sj3/henkan.c

805 lines
17 KiB
C

/*
* Copyright (c) 1994 Sony Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Sony Corporation
* shall not be used in advertising or otherwise to promote the sale, use
* or other dealings in this Software without prior written authorization
* from Sony Corporation.
*
*/
#include "common.h"
#include "key.h"
#include "wchar16.h"
#include "kctype.h"
void Rdisp(void);
int i_point;
int exec_henkan(void)
{
Conversion* cv;
int i, j;
wchar16_t * s, *p;
short sp;
int len, rlen, ilen;
int opos, ipos, bnum;
unsigned char index[BUFFLENGTH * 2], mode;
cv = GetConversion();
sp = 0;
mode = cv->in_mode[sp];
cv->kettei[sp] = mode;
for(i = 1; i < cv->out_point; i++) {
if(mode != cv->in_mode[i]) {
p = &cv->out_buf[i];
cv->span_l[sp] = p - cv->span_p[sp];
sp++;
cv->span_p[sp] = p;
mode = cv->in_mode[i];
cv->kettei[sp] = mode;
}
}
cv->span_l[sp] = &cv->out_buf[i] - cv->span_p[sp];
sp++;
cv->span_point = sp;
p = cv->yomiout;
i_point = 0;
ipos = -1;
for(i = 0; i < cv->span_point; i++) {
len = cv->span_l[i];
s = cv->span_p[i];
if(cv->kettei[i] == MODE_ZHIRA) {
if(ipos >= 0) {
ilen = getipos(s - cv->out_buf) - ipos;
Strncpy(p, &cv->Halpha[ipos], ilen);
p += ilen;
ipos = -1;
for(j = 0; j < ilen; j++)
index[i_point++] = ObjMuhenkan;
}
Strncpy(p, s, len);
p += len;
for(j = 0; j < len; j++)
index[i_point++] = ObjHenkan;
} else if(ipos == -1)
ipos = getipos(s - cv->out_buf);
}
if(ipos >= 0) {
ilen = cv->ha_point - ipos;
Strncpy(p, &cv->Halpha[ipos], ilen);
p += ilen;
for(j = 0; j < ilen; j++)
index[i_point++] = ObjMuhenkan;
}
index[i_point] = ObjEnd;
*p = '\0';
bnum = SJ2_henkan(cv->yomiout, cv->Bun, cv->kanjiout, BUFFLENGTH * 4);
if(bnum < 0 && !dconnect(1))
bnum = SJ2_henkan(cv->yomiout, cv->Bun, cv->kanjiout, BUFFLENGTH * 4);
if(bnum <= 0) {
cv->Bun[0].srclen = i_point;
cv->Bun[0].srcstr = cv->yomiout;
cv->Bun[0].destlen = 0;
cv->Bun[0].deststr = NULL;
bnum = 1;
}
i_point = 0;
cv->Bnum = 0;
i = 0;
while(i < bnum && i < cv->span_point) {
s = cv->span_p[i];
len = cv->span_l[i];
if(index[i_point] == ObjMuhenkan) {
cv->Bkettei[cv->Bnum] = Bmuhenkan;
opos = s - cv->out_buf;
len = getipos(opos + len) - getipos(opos);
if(len < cv->Bun[i].srclen) {
i_point += len;
rlen = cv->Bun[i].srclen - len;
opos = cv->span_p[i + 1] - cv->out_buf;
if(index[i_point + rlen] == ObjMuhenkan ||
rlen != 1 || cv->out_mode[opos + rlen] == 0) {
addBun(i, bnum);
cv->Bun[i].srclen = len;
cv->Bun[i + 1].srclen -= len;
cv->Bun[i + 1].srcstr += len;
if(cv->Bun[i].deststr != NULL) {
cv->Bun[i].destlen = len;
cv->Bun[i + 1].destlen -= len;
cv->Bun[i + 1].deststr += len;
}
bnum++;
} else {
cv->span_l[i] += rlen;
if((unsigned int)cv->span_l[i + 1] >= rlen) {
cv->span_l[i + 1] -= rlen;
cv->span_p[i + 1] += rlen;
} else {
delspan(i + 1);
cv->span_point--;
}
i_point += rlen;
}
} else if(len > cv->Bun[i].srclen) {
delBun(i, bnum);
bnum--;
continue;
} else {
i_point += len;
}
} else if(index[i_point] == ObjHenkan) {
cv->Bkettei[cv->Bnum] = Bhenkan;
if(len < cv->Bun[i].srclen) {
i_point += len;
addBun(i, bnum);
cv->Bun[i].srclen = len;
cv->Bun[i + 1].srclen -= len;
cv->Bun[i + 1].srcstr += len;
if(cv->Bun[i].deststr != NULL) {
rlen = cv->Bun[i + 1].srclen;
cv->Bun[i].destlen -= rlen;
cv->Bun[i + 1].destlen = rlen;
cv->Bun[i + 1].deststr +=
cv->Bun[i].destlen;
}
bnum++;
} else if(len > cv->Bun[i].srclen) {
for(j = cv->span_point; j > i; j--) {
cv->span_p[j] = cv->span_p[j - 1];
cv->span_l[j] = cv->span_l[j - 1];
cv->kettei[j] = cv->kettei[j - 1];
}
cv->span_point++;
rlen = cv->Bun[i].srclen;
i_point += rlen;
cv->span_l[i] = rlen;
cv->span_l[i + 1] -= rlen;
cv->span_p[i + 1] += rlen;
} else {
i_point += len;
}
} else {
cv->Bnum++;
break;
}
cv->Bnum++;
i++;
}
cv->Bkettei[cv->Bnum] = Bend;
for(i = 0; i < cv->Bnum; i++) {
cv->Pkettei[i] = cv->kettei[i];
cv->Ppoint[i] = cv->span_p[i];
cv->OrgPlen[i] = cv->Plen[i] = cv->span_l[i];
cv->Pedited[i] = 0;
cv->Bpoint[i] = i + 1;
}
if(flush_conversion)
cv->PreBun = cv->CurBun = -1;
else
cv->PreBun = cv->CurBun = 0;
Bdisp(1);
cv->Dflag = -1;
cv->Enum = 0;
cv->e_point = 0;
cv->Kanji = 1;
}
int addBun(int cur, int end)
{
int i;
Conversion* cv;
cv = GetConversion();
for(i = end; i > cur; i--) {
cv->Bun[i].srclen = cv->Bun[i - 1].srclen;
cv->Bun[i].srcstr = cv->Bun[i - 1].srcstr;
cv->Bun[i].destlen = cv->Bun[i - 1].destlen;
cv->Bun[i].deststr = cv->Bun[i - 1].deststr;
}
}
int delspan(int cur)
{
int i;
Conversion* cv;
cv = GetConversion();
for(i = cur; i < cv->span_point - 1; i++) {
cv->span_l[i] = cv->span_l[i + 1];
cv->span_p[i] = cv->span_p[i + 1];
cv->kettei[i] = cv->kettei[i + 1];
}
}
int delBun(int cur, int end)
{
int i;
Conversion* cv;
cv = GetConversion();
cv->Bun[cur].srclen += cv->Bun[cur + 1].srclen;
cv->Bun[cur].destlen += cv->Bun[cur + 1].destlen;
for(i = cur + 1; i < end; i++) {
cv->Bun[i].srclen = cv->Bun[i + 1].srclen;
cv->Bun[i].srcstr = cv->Bun[i + 1].srcstr;
cv->Bun[i].destlen = cv->Bun[i + 1].destlen;
cv->Bun[i].deststr = cv->Bun[i + 1].deststr;
}
}
int IsHex(wchar16_t c)
{
return (iswxdigit(c));
}
int Getcode(wchar16_t * in, wchar16_t * out)
{
int c, i, j;
unsigned char s[5];
int base, c_code;
unsigned short code;
wchar16_t sw[5];
wchar16_t tmp[3];
*out = (wchar16_t)'\0';
i = 0;
if(((c_code = GetCcode()) == CODE_KUTEN) || (c_code == CODE_KUTEN2))
base = 10;
else
base = 16;
while((c = *in) != '\0') {
if(WcIsKANJI(c)) {
in++;
*(out++) = c;
i = 0;
continue;
} else if(IsHex(c))
s[i++] = WcLowByte(c);
else
break;
in++;
if(i == 4) {
s[i] = '\0';
code = (unsigned short)strtol((char*)s, (char**)NULL, base);
switch(c_code) {
case CODE_KUTEN:
case CODE_KUTEN2:
c = ((code / 100) << 8) + code % 100;
code = c + 0x2020;
case CODE_JIS:
case CODE_JIS2:
code = jis2euc(code);
break;
case CODE_SJIS:
code = sjis2euc(code);
break;
}
if((c_code == CODE_KUTEN2) ||
(c_code == CODE_JIS2) || (c_code == CODE_EUC2))
code &= WcX0212MASK;
if(!WcIsZENKAKU(code))
break;
*out++ = code;
i = 0;
}
}
*out = (wchar16_t)'\0';
if(i) {
for(j = 0; j < i; j++)
sw[j] = (wchar16_t)s[j];
sw[i] = (wchar16_t)'\0';
i = sj_hantozen(out, sw, i);
out += i;
}
if(*in != '\0')
/*
* Remove warning.
* Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/10
*/
(void)sj_hantozen(out, in, strlen((char*)in));
}
static unsigned char load_mode;
int load_bun(int num, wchar16_t * s, unsigned char type)
{
Conversion* cv;
int len, ilen;
unsigned char itype;
wchar16_t Htmp[BUFFLENGTH], Ztmp[BUFFLENGTH * 2];
cv = GetConversion();
if(num < 0 || (len = cv->Plen[num]) == 0) {
*s = '\0';
return (0);
}
if(type == 0)
type = MODE_ZHIRA;
if(cv->Bpoint[num] < cv->Bpoint[0])
itype = MODE_ALPHA;
else
itype = cv->kettei[cv->Bpoint[num] - 1];
if(type & MODE_ZEN)
load_mode = 1;
else
load_mode = 0;
if(type == itype) {
Strncpy(s, cv->Ppoint[num], len);
s += len;
*s = '\0';
} else {
if(type == MODE_CODE && itype != MODE_CODE) {
ilen = getistr(Htmp, cv->Ppoint[num], len);
Getcode(Htmp, s);
len = wslen(s);
} else if((type & MODE_CONV) && (itype == MODE_ALPHA ||
itype == MODE_ZALPHA)) {
ilen = sj_zentohan(Htmp, cv->Ppoint[num], len);
ilen = sj_rkconv(Ztmp, Htmp, ilen);
if(type & MODE_ZEN) {
len = sj_hantozen(s, Ztmp, ilen);
if(type == MODE_ZKATA) {
wscpy(Ztmp, s);
sj_htok(s, Ztmp);
}
} else
len = sj_zentohan(s, Ztmp, ilen);
} else if(!(type & MODE_CONV) && (itype == MODE_CODE ||
itype & MODE_CONV)) {
if(type & MODE_ZEN) {
ilen = getistr(Htmp, cv->Ppoint[num], len);
len = sj_hantozen(s, Htmp, ilen);
} else {
len = getistr(s, cv->Ppoint[num], len);
}
} else {
if(type & MODE_ZEN) {
len = sj_hantozen(Ztmp, cv->Ppoint[num], len);
if(type == MODE_ZKATA)
sj_htok(s, Ztmp);
else
sj_ktoh(s, Ztmp);
} else
len = sj_zentohan(s, cv->Ppoint[num], len);
}
}
return (len);
}
int load_bun2(int num, wchar16_t * htmp, wchar16_t * ztmp, unsigned short * omode)
{
Conversion* cv;
int i;
int len, ilen;
unsigned short* op;
unsigned char type;
wchar16_t Ztmp[DLEN + 1];
cv = GetConversion();
if(num < 0 || (len = cv->Plen[num]) == 0) {
*ztmp = '\0';
return (0);
}
if(cv->Bpoint[num] < cv->Bpoint[0])
i = cv->span_point;
else
i = cv->Bpoint[num];
type = cv->kettei[i - 1];
if(type == MODE_ZHIRA || type == MODE_ZKATA) {
if(len > DLEN)
return (len);
if(type == MODE_ZHIRA) {
Strncpy(ztmp, cv->Ppoint[num], len);
ztmp += len;
*ztmp = '\0';
} else {
Strncpy(Ztmp, cv->Ppoint[num], len);
Ztmp[len] = '\0';
sj_ktoh(ztmp, Ztmp);
}
(void)load_bun(num, htmp, MODE_ALPHA);
op = &cv->out_mode[cv->Ppoint[num] - cv->Ppoint[0]];
for(i = 0; i < len; i++)
*omode++ = *op++;
} else {
ilen = load_bun(num, htmp, MODE_ALPHA);
len = sj_rkconv2(ztmp, htmp, omode, ilen);
}
return (len);
}
int getistr(wchar16_t * s, wchar16_t * ostr, int len)
{
int ipos, opos;
Conversion* cv;
int rlen;
cv = GetConversion();
opos = ostr - cv->out_buf;
if(!(cv->out_mode[opos] & OMODE_MASK))
chhstr(cv->Halpha, cv->out_buf, cv->out_mode, opos);
ipos = getipos(opos);
if(*(ostr + len) != '\0' && !(cv->out_mode[opos + len] & OMODE_MASK))
chhstr(cv->Halpha, cv->out_buf, cv->out_mode, opos + len);
rlen = getipos(opos + len) - ipos;
Strncpy(s, &cv->Halpha[ipos], rlen);
s += rlen;
*s = (wchar16_t)'\0';
return (rlen);
}
int exec_muhenkan(int first)
{
Conversion* cv;
cv = GetConversion();
cv->Bnum = 1;
cv->Ppoint[0] = &(cv->out_buf[0]);
cv->Plen[0] = cv->out_point;
cv->OrgPlen[0] = cv->Plen[0];
cv->Pedited[0] = 0;
if(first) {
cv->Bkettei[0] = Bmuhenkan;
cv->Pkettei[0] = cv->Imode;
} else if(cv->Bkettei[0] != Bmuhenkan) {
cv->Bkettei[0] = Bmuhenkan;
cv->Pkettei[0] = MODE_ZHIRA;
} else if(cv->Pkettei[0] != MODE_ZHIRA) {
cv->Pkettei[0] = MODE_ZHIRA;
} else {
cv->Pkettei[0] = MODE_ZKATA;
}
if(flush_conversion)
cv->PreBun = cv->CurBun = -1;
else
cv->PreBun = cv->CurBun = 0;
cv->Dflag = -1;
cv->Enum = 0;
cv->e_point = 0;
cv->Kanji = 1;
Bdisp(1);
}
static unsigned char Bstr_mode;
int Bstr(int bnum, wchar16_t * s)
{
Conversion* cv;
int i, len;
cv = GetConversion();
if(cv->Bkettei[bnum] & Bmuhenkan) {
len = load_bun(bnum, s, cv->Pkettei[bnum]);
Bstr_mode = load_mode;
} else if(cv->Bkettei[bnum] & Bedit) {
i = cv->Edit[bnum];
len = cv->Elen[i];
if(len <= DLEN) {
if(cv->Epoint[i] != NULL) {
Strncpy(s, cv->Epoint[i], len);
s += len;
*s = '\0';
} else
len = -1;
} else
len = load_bun(bnum, s, 0);
Bstr_mode = 1;
} else if(cv->Bkettei[bnum] & Bhenkan) {
if(!(i = cv->Bpoint[bnum])) {
len = -1;
return len;
}
if(cv->Bun[i - 1].deststr != NULL) {
len = cv->Bun[i - 1].destlen;
Strncpy(s, cv->Bun[i - 1].deststr, len);
s += len;
*s = '\0';
} else if(cv->Bun[i - 1].srcstr != NULL) {
len = cv->Bun[i - 1].srclen;
Strncpy(s, cv->Bun[i - 1].srcstr, len);
s += len;
*s = '\0';
} else
len = -1;
Bstr_mode = 1;
} else
len = -1;
return (len);
}
int mode_muhenkan(int mod, int bkettei)
{
int def;
if(!(bkettei & Bmuhenkan))
return (KEY_ZHIRA);
def = value_muhenkan();
if(mod == MODE_ZHIRA)
return (KEY_ZKATA);
else if(mod == MODE_ZKATA) {
if(def != KEY_ZHIRA && def != KEY_ZKATA)
return (def);
}
return (KEY_ZHIRA);
}
int Bchange(int mod)
{
Conversion* cv;
int i;
int PushKettei;
cv = GetConversion();
if(cv->CurBun == -1)
cv->CurBun = 0;
i = cv->PreBun = cv->CurBun;
if(mod == KEY_MUHENKAN)
mod = mode_muhenkan(cv->Pkettei[i], cv->Bkettei[i]);
else if(mod == KEY_TOGGLE)
mod = toggle_mode(cv->Pkettei[i]);
PushKettei = cv->Bkettei[i];
if(!(cv->Bkettei[i] & Bmuhenkan)) {
cv->Bkettei[i] |= Bmuhenkan;
cv->Bkettei[i] &= ~Bhenkan;
}
switch(mod) {
case KEY_CODE:
cv->Pkettei[i] = MODE_CODE;
Rdisp();
break;
case KEY_ZHIRA:
cv->Pkettei[i] = MODE_ZHIRA;
Rdisp();
break;
case KEY_HALPHA:
cv->Pkettei[i] = MODE_HALPHA;
Rdisp();
break;
case KEY_ZALPHA:
cv->Pkettei[i] = MODE_ZALPHA;
Rdisp();
break;
case KEY_HKATA:
cv->Pkettei[i] = MODE_HKATA;
Rdisp();
break;
case KEY_ZKATA:
cv->Pkettei[i] = MODE_ZKATA;
Rdisp();
break;
default:
cv->Bkettei[i] = PushKettei;
beep();
break;
}
}
Bdisp(redraw) {
Conversion* cv;
int i;
int len;
wchar16_t BDtmp[BUFFLENGTH * 2];
int displen;
int amount = 0;
int tmpcol = 0;
unsigned short row, col;
CursorRead(&row, &col);
cv = GetConversion();
Cclear(redraw);
SetVcol(0);
for(i = 0; i < cv->Bnum; i++) {
if((len = Bstr(i, BDtmp)) < 0)
continue;
amount += len;
if(amount > BUFFLENGTH * 2) {
cv->Bnum = i + 1;
break;
}
displen = wcbyte(BDtmp);
tmpcol += displen;
if((tmpcol > (unsigned int)cv->column) && (row == cv->line) && (row == cv->SavedRow) && (row > 0)) {
cv->SavedRow--;
tmpcol -= cv->column;
}
cv->Displen[i] = displen;
cv->Dispmod[i] = Bstr_mode;
if(len <= 0)
continue;
if(i == cv->CurBun)
vprintR(BDtmp, Bstr_mode);
else
vprintU(BDtmp, Bstr_mode);
}
Flush();
}
void Rdisp(void)
{
Conversion* cv;
int i;
int Total;
int len;
wchar16_t BDtmp[BUFFLENGTH * 2];
int displen;
int amount = 0;
int tmpcol = 0;
unsigned short row, col;
CursorRead(&row, &col);
cv = GetConversion();
Total = 0;
for(i = 0; i < cv->Bnum; i++) {
if((len = Bstr(i, BDtmp)) < 0)
continue;
amount += len;
if(amount > BUFFLENGTH * 2) {
cv->Bnum = i + 1;
break;
}
displen = wcbyte(BDtmp);
tmpcol += displen;
if((tmpcol > (unsigned int)cv->column) && (row == cv->line) && (row == cv->SavedRow) && (row > 0)) {
cv->SavedRow--;
tmpcol -= cv->column;
}
if(cv->Displen[i] != displen || cv->Dispmod[i] != Bstr_mode) {
AfterAllPrint(i, Total);
return;
}
if(len <= 0)
continue;
if(i == cv->CurBun || i == cv->PreBun) {
if(i == cv->CurBun)
IprintR(BDtmp, Total);
else
IprintU(BDtmp, Total);
}
Total += displen;
}
Cgoto(Total);
Flush();
}
int AfterAllPrint(int from, int Total)
{
Conversion* cv;
int i;
int len;
wchar16_t BDtmp[BUFFLENGTH * 2];
int displen;
int amount = 0;
int tmpcol = 0;
unsigned short row, col;
CursorRead(&row, &col);
cv = GetConversion();
Cgoto(Total);
for(i = from; i < cv->Bnum; i++) {
if((len = Bstr(i, BDtmp)) < 0)
continue;
amount += len;
if(amount > BUFFLENGTH * 2) {
cv->Bnum = i + 1;
break;
}
displen = wcbyte(BDtmp);
tmpcol += displen;
if((tmpcol > (unsigned int)cv->column) && (row == cv->line) && (row == cv->SavedRow) && (row > 0)) {
cv->SavedRow--;
tmpcol -= cv->column;
}
cv->Displen[i] = displen;
cv->Dispmod[i] = Bstr_mode;
if(len <= 0)
continue;
if(i == cv->CurBun)
vprintR(BDtmp, Bstr_mode);
else
vprintU(BDtmp, Bstr_mode);
Total += displen;
}
ClearToMax();
Cgoto(Total);
Flush();
}
void Bright(void)
{
Conversion* cv;
int flag;
cv = GetConversion();
flag = 0;
cv->PreBun = cv->CurBun;
do {
cv->CurBun++;
if(cv->CurBun >= cv->Bnum) {
if(flag)
return;
else
flag = 1;
cv->CurBun = 0;
}
} while(cv->Plen[cv->CurBun] <= 0);
Rdisp();
}
void Bleft(void)
{
Conversion* cv;
int flag;
cv = GetConversion();
flag = 0;
cv->PreBun = cv->CurBun;
do {
cv->CurBun--;
if(cv->CurBun < 0) {
if(flag)
return;
else
flag = 1;
cv->CurBun = cv->Bnum - 1;
}
} while(cv->Plen[cv->CurBun] <= 0);
Rdisp();
}
void Blast(void)
{
Conversion* cv;
cv = GetConversion();
cv->PreBun = cv->CurBun;
cv->CurBun = cv->Bnum - 1;
while(cv->Plen[cv->CurBun] <= 0) {
cv->CurBun--;
if(cv->CurBun < 0)
return;
}
Rdisp();
}
void Btop(void)
{
Conversion* cv;
cv = GetConversion();
cv->PreBun = cv->CurBun;
cv->CurBun = 0;
while(cv->Plen[cv->CurBun] <= 0) {
cv->CurBun++;
if(cv->CurBun >= cv->Bnum)
return;
}
Rdisp();
}