diff options
author | rodri <rgl@antares-labs.eu> | 2022-07-06 20:19:14 +0000 |
---|---|---|
committer | rodri <rgl@antares-labs.eu> | 2022-07-06 20:19:14 +0000 |
commit | 566c5121064c4872fd9b21bfa37b1f997d779f18 (patch) | |
tree | 561b5c86ac534e3684475af6fa5f112d52a12950 /sys/src/cmd/ktrans/main.c | |
parent | 6972974f8df3ead3043185c046b7871110b85b79 (diff) |
add ktrans. こんにちは!
Diffstat (limited to 'sys/src/cmd/ktrans/main.c')
-rw-r--r-- | sys/src/cmd/ktrans/main.c | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/sys/src/cmd/ktrans/main.c b/sys/src/cmd/ktrans/main.c new file mode 100644 index 000000000..e6c6be754 --- /dev/null +++ b/sys/src/cmd/ktrans/main.c @@ -0,0 +1,471 @@ +/* + * Mostly based on the original source codes of Plan 9 release 2 + * distribution. + * by Kenji Okamoto, August 4 2000 + * Osaka Prefecture Univ. + * okamoto@granite.cias.osakafu-u.ac.jp + */ + +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "ktrans.h" +#include "jisho.h" + +#define LSIZE 256 + +Rune lbuf[LSIZE]; /* hiragana buffer for key input written by send() */ +Map *table = hira; /* default language conversion table */ +uchar okurigana[LSIZE]; /* buffer for okurigana */ +char okuri = 0; /* buffer/flag for capital input char */ +int in, out; +int llen, olen, joshi = 0; +int natural = 1; /* not Japanese but English mode */ + +int changelang(int); +int dotrans(Dictionary*); +int nrune(char *); +void send(uchar *, int); +Map *match(uchar *p, int *nc, Map *table); + +extern Dictionary *openQDIC(char *); +extern KouhoList *getKouhoHash(Dictionary*, char *); +extern KouhoList *getKouhoFile(DicList*, char *); +extern void freeQDIC(Dictionary*); +extern void selectKouho(KouhoList **, KouhoList*); + +void +kbdopen(void) +{ + int n, kinfd, koutfd, fd[2]; + char buf[128]; + int kbd; + + kbd = 1; + if((kinfd = open("/dev/kbd", OREAD)) < 0){ + kbd = 0; + if((kinfd = open("/dev/cons", OREAD)) < 0) + sysfatal("open kbd: %r"); + } + if(bind("#|", "/n/temp", MREPL) < 0) + sysfatal("bind /n/temp: %r"); + if((koutfd = open("/n/temp/data1", OWRITE)) < 0) + sysfatal("open kbd pipe: %r"); + if(bind("/n/temp/data", kbd? "/dev/kbd": "/dev/cons", MREPL) < 0) + sysfatal("bind kbd pipe: %r"); + unmount(nil, "/n/temp"); + if(!kbd){ + in = kinfd; + out = koutfd; + return; + } + if(pipe(fd) < 0) + sysfatal("pipe: %r"); + if(fork()){ + in = out = fd[0]; + close(fd[1]); + close(kinfd); + close(koutfd); + return; + } + close(fd[0]); + if(fork()){ + Biobuf b; + long r; + + Binit(&b, fd[1], OREAD); + while((r = Bgetrune(&b)) >= 0){ + n = snprint(buf, sizeof(buf), "c%C", (Rune)r)+1; + write(koutfd, buf, n); /* pass on result */ + } + } else + while((n = read(kinfd, buf, sizeof(buf))) > 0){ + buf[n-1] = 0; + if(n < 2 || buf[0] != 'c') + write(koutfd, buf, n); /* pass on */ + else + write(fd[1], buf+1, n-2); /* to translator */ + } + exits(nil); +} + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + + uchar *bp, *ep, buf[128]; + Map *mp; + int nchar, wantmore; + int n, c; + char *dictname; + Dictionary *jisho; + + ARGBEGIN{ + default: usage(); + }ARGEND; + if(argc != 0) + usage(); + + if((dictname = getenv("jisho")) == nil) + dictname = "/lib/kanji.jisho"; + jisho = openQDIC(dictname); + + kbdopen(); + if(fork()) + exits(nil); /* parent process will exit */ + + bp = ep = buf; + wantmore = 0; + for (;;) { /* key board input loop */ + getmore: + if (bp>=ep || wantmore) { + if (wantmore==0) + bp = ep = buf; /* clear all */ + n = read(in, ep, &buf[sizeof(buf)]-ep); + if (n<=0) + exits(""); + ep += n; + *ep = '\0'; + } + while (bp<ep) { /* there are input data */ + if (table == hira && natural != 1 && (*bp>'A' && *bp<='Z') && ep-bp<2 + && !strchr("EIOU", *bp)) { + wantmore = 1; + goto getmore; + } + if (!fullrune((char *)bp, ep-bp)) { /* not enough length of input */ + wantmore = 1; + goto getmore; + } + wantmore = 0; + + if (*bp=='') { /* ^x read ktrans-jisho once more */ + freeQDIC(jisho); + jisho = openQDIC(dictname); + llen = 0; + olen = okuri = joshi = 0; + wantmore=0; + bp=ep=buf; + continue; + } + if (*bp=='') { /* ^\ (start translation command) */ + c = dotrans(jisho); + if (c) + *bp = c; /* pointer to translated rune */ + else + bp++; + continue; + } + if (*bp=='') { /* ^l (no translate command) */ + bp++; + llen = 0; + olen = okuri = joshi = 0; + continue; + } + if (changelang(*bp)) { /* change language mode OK */ + bp++; + olen = okuri = joshi = 0; + continue; + } + if (natural || *bp<=' ' || *bp>='{') { /* English mode but not ascii */ + Rune r; + int rlen = chartorune(&r, (char *)bp); + send(bp, rlen); /* write bp to /dev/cons */ + bp += rlen; + continue; + } + if (table == hira && (*bp >= 'A' && *bp <= 'Z') && (*(bp+1) < 'A' + || *(bp+1) > 'Z')) { + *bp = okuri = tolower(*bp); + joshi = olen = 0; + } else if (table == hira && (*bp >= 'A' && *bp <= 'Z') && + (*(bp+1) >= 'A' && *(bp+1) <= 'Z')) { + *bp = okuri = tolower(*bp); + *(bp+1) = tolower(*(bp+1)); + joshi = 1; + olen = 0; + } + mp = match(bp, &nchar, table); + if (mp == 0) { + if (nchar>0) { /* match, longer possible */ + wantmore++; + break; + } + send(bp++, 1); /* alphabet in kana mode */ + } else { + send((uchar*)mp->kana, strlen(mp->kana)); + bp += nchar; + } + } + } +} + +int +min(int a, int b) +{ + return a<b? a: b; +} + +/* + * send UTF string (p) with length (n) to stdout + * and write rune (r) in global lbuf[] buffer + * or okurigana[] buffer if okuri (verb or joshi) mode + */ +void +send(uchar *p, int n) +{ + Rune r; + uchar *ep; + + if (write(out, (char*)p, n) != n) + sysfatal("write: %r"); + + if (llen>LSIZE-64) { + memmove((char*)lbuf, (char*)lbuf+64, 64*sizeof(Rune)); + llen -= 64; + } + + if (table!=hira || natural) + return; + + ep = p+n; + if(okuri) + while (olen<LSIZE && p<ep) + okurigana[olen++] = *p++; + else + while (llen<LSIZE && p<ep) { + p += chartorune(&r, (char*)p); + if (r=='\b') { + if (llen>0) + llen--; + continue; + } + if (r==0x80) /* ignore view key */ + continue; + lbuf[llen++] = r; + } +} + +/* + * Romaji to Hiragana/Katakana conversion + * romaji shoud be input as small letter + * returns the matched address in table, hira, kata, etc. + * nc: number of character (return value) + */ +Map * +match(uchar *p, int *nc, Map *table) +{ + register Map *longp = 0, *kp; + static char last; + int longest = 0; + + *nc = -1; + for (kp=table; kp->roma; kp++) { + if (*p == *kp->roma) { + int lr = strlen(kp->roma); + int len = min(lr, strlen((char *)p)); + if (strncmp(kp->roma, (char *)p, len)==0) { + if (len<lr) { + *nc = 1; + return 0; + } + if (len>longest) { + longest = len; + longp = kp; + } + } + } + } + if (longp) { + last = longp->roma[longest-1]; + *nc = longp->advance; + } + return longp; +} + +int +changelang(int c) +{ + switch(c){ + case '': /* ^t (English mode) */ + natural = 1; + llen = 0; + return 1; + break; + + case '': /* ^n (Japanese hiragana mode ) */ + natural = 0; + table = hira; + llen = 0; + return 1; + break; + + case '': /* ^k (Japanese katakana mode) */ + natural = 0; + table = kata; + llen = 0; + return 1; + break; + + case '': /* ^r (Russian mode) */ + natural = 0; + table = cyril; + llen = 0; + return 1; + break; + + case '': /* ^o (Greek mode) */ + natural = 0; + table = greek; + llen = 0; + return 1; + break; + + case '': /* ^s (Korean mode) */ + natural = 0; + table = hangul; + llen = 0; + return 1; + break; + } + return 0; +} + +/* + * write translated kanji runes to stdout and return last character + * if it's not ctl-\. if the last is ctl-\, proceed with + * translation of the next kouho + */ +int +dotrans(Dictionary *dic) +{ + Rune *res, r[1]; + char v[1024], *p, tbuf[64], hirabuf[64]; + int j, lastlen, nokouho = 0; + char ch; + KouhoList *fstkouho, *currentkouho; + + if (llen==0) + return 0; /* don't use kanji transform function */ + if (okuri && joshi != 1) { + lbuf[llen++] = (Rune)okuri; + lbuf[llen] = 0; + }else + lbuf[llen] = 0; + okurigana[olen] = 0; + + /* + * search the matched index for the key word in the dict hash table, and + * return a pointer to the matched kouho, 0 otherwise. + */ + res = lbuf; + for (j=0; *res != L'\0'; j += runetochar(v+j, res++)) + ; + v[j] = '\0'; + strcpy(tbuf, v); + strcpy(hirabuf, v); /* to remember the initial hiragana input */ + + if (okuri && joshi != 1) /* verb mode */ + hirabuf[strlen(hirabuf) - 1] = '\0'; + + if(!(fstkouho = getKouhoHash(dic, v))) { /* not found */ + llen = olen = okuri = joshi = 0; + okurigana[0] = 0; + return 0; + } + + currentkouho = fstkouho; + for(;;) { + p = currentkouho->kouhotop; /* p to the head of kanji kouho array */ + lastlen = nrune(tbuf); /* number of rune chars */ + + if (okuri && joshi != 1) /* verb mode */ + for (j=0; j<lastlen-1; j++) + write(out, "\b", 1); /* clear hiragana input */ + else + for (j=0; j<lastlen; j++) + write(out, "\b", 1); /* clear hiragana input */ + + if (okuri) { + lastlen = nrune((char *)okurigana); + for (j=0; j<lastlen; j++) + write(out, "\b", 1); + } + + write(out, p, strlen(p)); /* write kanji to stdout */ + if (okuri) + write(out, (char *)okurigana, olen); + + if (read(in, &ch, 1)<=0) /* read from stdin */ + exits(nil); + + if (ch == '') { /* if next input is ^\, once again */ + if(currentkouho->nextkouho != 0) { /* have next kouho */ + nokouho = 0; + strcpy(tbuf, p); + currentkouho = currentkouho->nextkouho; + + if (okuri && joshi != 1) /* verb mode */ + for (j=0; j<nrune(tbuf); j++) + write(out, "\b", 1); + continue; + } else { /* the last kouho */ + if (okuri) { + lastlen = nrune((char *)okurigana); + for (j=0; j<lastlen; j++) + write(out, "\b", 1); + } + + for (lastlen=0; *p != 0; p += j) { + j = chartorune(r, p); + lastlen++; + } + + for (j=0; j<lastlen; j++) + write(out, "\b", 1); + + if(hirabuf[0]) + write(out, hirabuf, strlen(hirabuf)); + + if(okurigana[0]) + write(out, (char *)okurigana, olen); + + olen = okuri = joshi = 0; + okurigana[0] = 0; + break; + } + } else { + if(!nokouho) /* learn the previous use of the kouho */ + selectKouho(&(fstkouho->dicitem->kouho), currentkouho); + + olen = okuri = joshi = 0; + okurigana[0] = 0; + break; + } + } + llen = 0; + return ch; +} + +/* + * returns the number of characters in the pointed Rune + */ +int +nrune(char *p) +{ + int n = 0; + Rune r; + + while (*p) { + p += chartorune(&r, p); + n++; + } + return n; +} |