diff options
Diffstat (limited to 'appl/lib/convcs/big5_btos.b')
| -rw-r--r-- | appl/lib/convcs/big5_btos.b | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/appl/lib/convcs/big5_btos.b b/appl/lib/convcs/big5_btos.b new file mode 100644 index 00000000..f92fe471 --- /dev/null +++ b/appl/lib/convcs/big5_btos.b @@ -0,0 +1,87 @@ +implement Btos; + +include "sys.m"; +include "convcs.m"; + +# Big5 consists of 89 fonts of 157 chars each +BIG5MAX : con 13973; +BIG5FONT : con 157; + +BIG5DATA : con "/lib/convcs/big5"; + +MAXINT : con 16r7fffffff; +BADCHAR : con 16rFFFD; + +big5map := ""; + +init(nil : string) : string +{ + sys := load Sys Sys->PATH; + fd := sys->open(BIG5DATA, Sys->OREAD); + if (fd == nil) + return sys->sprint("%s: %r", BIG5DATA); + + buf := array[BIG5MAX * Sys->UTFmax] of byte; + nread := 0; + for (;nread < len buf;) { + n := sys->read(fd, buf[nread:], Sys->ATOMICIO); + if (n <= 0) + break; + nread += n; + } + big5map = string buf[:nread]; + if (len big5map != BIG5MAX) { + big5map = nil; + return sys->sprint("%s: corrupt data", BIG5DATA); + } + return nil; +} + +btos(nil : Convcs->State, b : array of byte, n : int) : (Convcs->State, string, int) +{ + nbytes := 0; + str := ""; + + if (n == -1) + n = MAXINT; + + font := -1; + for (i := 0; i < len b && len str < n; i++) { + c := int b[i]; + if (font == -1) { + # idle state + if(c >= 16rA1){ + font = c; + continue; + } + if(c == 26) + c = '\n'; + str[len str] = c; + nbytes = i + 1; + continue; + } else { + # seen a font spec + f := font; + font = -1; + ch := Sys->UTFerror; + if(c >= 64 && c <= 126) + c -= 64; + else if(c >= 161 && c <= 254) + c = c-161 + 63; + else + # bad big5 char + f = 255; + if(f <= 254) { + f -= 161; + ix := f*BIG5FONT + c; + if(ix < len big5map) + ch = big5map[ix]; + if (ch == -1) + ch = BADCHAR; + } + str[len str] = ch; + nbytes = i + 1; + } + } + return (nil, str, nbytes); +} |
