/* * Copyright (C) 1995 Edward Der-Hua Liu, Hsin-Chu, Taiwan */ #include "big5con.h" #define b2cpy(a,b) memcpy(a,b,2) extern u_char *ch_pho; extern char *ph_pho[]; extern int ityp3_pho; extern u_char typ_pho[]; extern char inph[]; extern u_short idxnum_pho, idx_pho[]; extern u_short hash_pho[]; extern PHOKBM phkbm; char tsfname[64] = ""; char tsidxfname[64] = ""; static int phcount, a_phcount; static int hashidx[256]; static int *phidx; typedef struct { u_char ch[2]; u_short ph; } ITPH; static ITPH *sel1st; static u_short sel1st_hash[256]; static int sel1st_n; int going_key = 0; #define MAX_PH_BF (42) static u_char ch_buf[MAX_PH_BF + 1][2]; static u_char ch_obuf[MAX_PH_BF + 1][2]; static u_short ph_buf[MAX_PH_BF + 1]; static u_char pox[MAX_PH_BF + 1]; static u_char psta[MAX_PH_BF + 1]; static int psta_cnt[MAX_PH_BF + 1]; static int c_idx, c_len, c_x, c_xlen, ph_sta = -1; static FILE *fph; static int sel_pho; extern int cursor_x; static int eng_ph = 1, ph_hf = 0; static int save_frm, save_to, save_mode; static u_short tk[5]; static u_char tch[5][2]; static u_long sti, edi; static void prch(u_char * s) { char tt[3]; if (s[0] > 128) b2cpy(tt, s); else { tt[0] = *s; tt[1] = 0; } tt[2] = 0; xprintf("%s", tt); /* printf("### %s\n",tt); */ } static void drawcursor() { #if 0 printf("idx:%d %d\n", c_idx, pox[c_idx]); #endif gotox(c_x = pox[c_idx]); set_att(InAreaColor); prch(ch_buf[c_idx]); set_att(NormalColor); } static void clrcursor() { #if 0 printf("c_idx:%d %d\n", c_idx, pox[c_idx]); #endif gotox(pox[c_idx]); prch(ch_buf[c_idx]); } static void putbuf(u_char s[][2], int len) { u_char tt[128]; int i, idx; for (idx = i = 0; i < len; i++) { if (s[i][0] >= 128) { b2cpy(&tt[idx], &s[i][0]); idx += 2; } else tt[idx++] = s[i][0]; } tt[idx] = 0; putstr(tt); } static void prbuf() { int i; ClrSelArea(); for (i = 0; i <= c_len; i++) { pox[i] = cursor_x; prch(ch_buf[i]); } drawcursor(); } static void restore_ai() { if (sel_pho) return; ClrSelArea(); clrin_pho(); disp_in_area_pho(); prbuf(); } static void clr_ch_buf() { int i; for (i = 0; i <= MAX_PH_BF; i++) { ch_buf[i][0] = ' '; ch_buf[i][1] = 0; psta[i] = 0xff; } ph_sta = -1; } void show_stat() { static char *str_eng_ph[] = {"­^", "ª`"}; gotox(0); xprintf("[µü­µ/%s]", str_eng_ph[eng_ph]); } void init_tab_pp(int usenow) { FILE *fr; int i, cou; unsigned int ttt; extern char TabDir[]; extern char *tabfname[]; char phofname[128]; if (!ch_pho) init_tab_pho(0); if (phcount) { disp_prom: show_stat(); restore_ai(); return; } if (!tsfname[0]) { char tt[128]; char vv[128]; DIR *dir; #ifndef NO_PRIVATE_TSIN strcpy(tt, (char *)getenv("HOME")); strcat(tt, "/xcin_dir"); seteuid(getuid()); if ((dir = opendir(tt)) == NULL) { void (*sigf) (int); mkdir(tt, 0755); sprintf(vv, "/bin/cp %s/tsin* %s > /dev/null 2>&1", TabDir, tt); sigf = signal(SIGCHLD, SIG_DFL); system(vv); signal(SIGCHLD, sigf); } else closedir(dir); seteuid(0); strcat(tt, "/tsin"); strcpy(tsfname, tt); #else strcpy(tsfname, TabDir); strcat(tsfname, "tsin"); #endif } strcpy(tsidxfname, tsfname); strcat(tsidxfname, ".idx"); if ((fr = fopen(tsidxfname, "r")) == NULL) { error("Cannot open %s\n", tsidxfname); return; } fread(&phcount, 4, 1, fr); #if 0 printf("phcount:%d\n", phcount); #endif a_phcount = phcount + 256; fread(&hashidx, 1, sizeof(hashidx), fr); if ((phidx = (int *)malloc(a_phcount * 4)) == NULL) { p_err("malloc err pp 1"); } fread(phidx, 4, phcount, fr); fclose(fr); strcpy(phofname, TabDir); strcat(phofname, "pho.sel1st"); if ((fr = fopen(phofname, "r")) == NULL) { error("Cannot open %s", phofname); return; } fread(&sel1st_n, 4, 1, fr); fread(sel1st_hash, 2, 256, fr); if ((sel1st = (ITPH *) malloc(sel1st_n * sizeof(ITPH))) == NULL) p_err("malloc err pp 2"); fread(sel1st, sizeof(ITPH), sel1st_n, fr); fclose(fr); /* printf("1st_n:%d\n", sel1st_n); */ seteuid(getuid()); if ((fph = fopen(tsfname, "r+")) == NULL) { error("Cannot open %s", tsfname); return; } seteuid(0); tabfname[6] = (char *)1; clr_ch_buf(); goto disp_prom; } #if 0 void prph(u_short kk) { u_int k1, k2, k3, k4; #define pk ph_pho k4 = (kk & 7) << 1; kk >>= 3; k3 = (kk & 15) << 1; kk >>= 4; k2 = (kk & 3) << 1; kk >>= 2; k1 = (kk & 31) << 1; printf("%c%c%c%c%c%c%c%c", pk[0][k1], pk[0][k1 + 1], pk[1][k2], pk[1][k2 + 1], pk[2][k3], pk[2][k3 + 1], pk[3][k4], pk[3][k4 + 1]); #undef pk } #endif /* 0 */ static phseq(u_char * a, u_char * b) { int lena, lenb, i, mlen; u_short ka, kb; lena = *(a++); lenb = *(b++); mlen = lena > lenb ? lenb : lena; for (i = 0; i < mlen; i++) { memcpy(&ka, a, 2); memcpy(&kb, b, 2); if (ka > kb) return 1; if (ka < kb) return -1; a += 2; b += 2; } if (lena > lenb) return 1; if (lena < lenb) return -1; return 0; } static void save_phrase() { int tt, ofs, top, bottom, mid, ord, ph_ofs, hashno, hashno_end, i; FILE *fw; u_char len, tbuf[24], sbuf[24], ch[16]; if (save_frm == save_to) return; if (save_frm > save_to) { tt = save_frm; save_frm = save_to; save_to = tt; } if (save_to == c_len) save_to--; len = save_to - save_frm + 1; if (len < 2 || len > 5) return; for (i = save_frm; i <= save_to; i++) if (!ph_buf[i]) return; tbuf[0] = len; memcpy(&tbuf[1], &ph_buf[save_frm], 2 * len); memcpy(&tbuf[2 * len + 1], ch_buf[save_frm], 2 * len); hashno = ph_buf[save_frm] >> 6; for (mid = hashidx[hashno]; mid < hashidx[hashno + 1]; mid++) { ph_ofs = phidx[mid]; fseek(fph, ph_ofs, SEEK_SET); fread(sbuf, 1, 1, fph); fread(&sbuf[1], 4, sbuf[0], fph); if ((ord = phseq(sbuf, tbuf)) >= 0) break; } tt = sbuf[0] * 2; if (!ord && !memcmp(&sbuf[tt + 1], ch_buf[save_frm], tt)) { bell(); goto cursor_end; } for (i = phcount; i >= mid; i--) phidx[i + 1] = phidx[i]; fseek(fph, 0, SEEK_END); ph_ofs = ftell(fph); phidx[mid] = ph_ofs; phcount++; if (phcount >= a_phcount) { a_phcount += 256; if (!(phidx = (int *)realloc(phidx, a_phcount * 4))) { p_err("tsin.c:realloc err"); } } fwrite(tbuf, 1, 4 * len + 1, fph); fflush(fph); if (hashidx[hashno] > mid) hashidx[hashno] = mid; hashno++; for (; hashno < 256; hashno++) hashidx[hashno]++; seteuid(getuid()); if ((fw = fopen(tsidxfname, "w")) == NULL) { error("%s create err", tsidxfname); return; } seteuid(0); fwrite(&phcount, 4, 1, fw); fwrite(&hashidx, sizeof(hashidx), 1, fw); fwrite(phidx, 4, phcount, fw); fclose(fw); cursor_end: clrcursor(); ph_sta = -1; c_idx = c_len; drawcursor(); } static void shift_ins() { int i, j; if (!c_idx && c_xlen >= MAX_PH_BF) { c_len--; c_xlen -= 2; } else if (c_xlen >= MAX_PH_BF) { int ofs; if (!(ch_buf[0][0] & 0x80) && (ch_buf[1][0] & 0x80)) { putbuf(ch_buf, 2); ofs = 2; c_xlen -= 3; c_x -= 3; } else if (!(ch_buf[0][0] & 0x80) && !(ch_buf[1][0] & 0x80)) { putbuf(ch_buf, 2); ofs = 2; c_xlen -= 2; c_x -= 2; } else { putbuf(ch_buf, 1); ofs = 1; c_xlen -= 2; c_x -= 2; } ph_sta -= ofs; for (j = 0; j < MAX_PH_BF - ofs; j++) { memcpy(ch_buf[j], ch_buf[j + ofs], 2); memcpy(ch_obuf[j], ch_obuf[j + ofs], 2); ph_buf[j] = ph_buf[j + ofs]; psta[j] = psta[j + ofs] - ofs; } c_idx -= ofs; c_len -= ofs; prbuf(); } c_len++; if (c_idx < c_len - 1) { for (j = c_len; j >= c_idx; j--) { memcpy(ch_buf[j + 1], ch_buf[j], 2); memcpy(ch_obuf[j + 1], ch_obuf[j], 2); ph_buf[j + 1] = ph_buf[j]; psta[j + 1] = psta[j] + 1; } ch_buf[c_len][0] = ' '; /* prbuf(); */ } } static u_char selstr[6][5][2], sellen[6]; static int maxi, selidx[6]; static void sel_phr() { int sti, edi, i, j; u_short key, tk[10]; u_char len, mlen, tch[10][2], tt[3]; mlen = c_len - c_idx; if (mlen > 5) mlen = 5; key = ph_buf[c_idx]; j = key >> 6; sti = hashidx[j]; edi = hashidx[j + 1]; maxi = 0; ClrSelArea(); while (sti < edi && maxi < 5) { i = phidx[sti]; fseek(fph, i, SEEK_SET); fread(&len, 1, 1, fph); if (len > mlen) { sti++; continue; } fread(tk, 2, len, fph); if (!memcmp(&ph_buf[c_idx], tk, 2 * len)) { fread(tch, 2, (int)len, fph); sellen[maxi] = len; selidx[maxi] = sti; memcpy(selstr[maxi++], tch, 2 * len); xprintf("%d", maxi); for (i = 0; i < len; i++) { xprintf("%c%c", tch[i][0], tch[i][1]); } xprintf(" "); } sti++; } if (maxi) sel_pho = 1; else sel_pho = 2; } static u_short_seq(u_short * a, u_short * b, int len) { int i; for (i = 0; i < len; i++) if (a[i] > b[i]) return 1; else if (a[i] < b[i]) return -1; return 0; } static u_char scanphr(u_short * pp, int plen) { int i, top, bot, mid, cmp; u_short ss[21]; u_char len, mlen; i = *pp >> 6; top = hashidx[i]; bot = edi = hashidx[i + 1]; while (top <= bot) { mid = (top + bot) >> 1; fseek(fph, phidx[mid], SEEK_SET); sti++; fread(&len, 1, 1, fph); fread(ss, 2, len, fph); if (len > plen) mlen = plen; else mlen = len; cmp = u_short_seq(ss, pp, mlen); if (!cmp && len < plen) cmp = -1; if (cmp > 0) bot = mid - 1; else if (cmp < 0) top = mid + 1; else break; } if (cmp) return 0; for (; mid >= 0; mid--) { fseek(fph, phidx[mid], SEEK_SET); fread(&len, 1, 1, fph); fread(tk, 2, len, fph); if (len >= plen && !u_short_seq(tk, pp, plen)) continue; break; } mid++; sti = mid; fseek(fph, phidx[mid], SEEK_SET); fread(&len, 1, 1, fph); fread(tk, 2, len, fph); fread(tch, 2, len, fph); return len; } static raise_phr(int c) { int i, j, tmp; FILE *fp; if (!c) return; i = selidx[c]; j = selidx[0]; tmp = phidx[i]; phidx[i] = phidx[j]; phidx[j] = tmp; selidx[0] = tmp; seteuid(getuid()); if ((fp = fopen(tsidxfname, "r+")) == NULL) { error("%s modify err", tsidxfname); return; } seteuid(0); fseek(fp, sizeof(phcount) + sizeof(hashidx) + j * 4, SEEK_SET); fwrite(&phidx[j], 4, (c + 1), fp); fclose(fp); } char ochars[] = "<,>.?/:;\"'{[}]_-+=|\\~`"; #define SELKEY (9) feedkey_pp(int xkey, int kbstate) { static char ctyp; static u_int i, ii, ttt, end; static u_short key, tkey; u_char *pp; static int cpg; static int startf; static u_char len; static pho1st_lidx; extern u_char fullchar[]; int shift_m = kbstate & KEY_SHIFT_MASK; int j, jj, kk; char tt[3], kno; switch (xkey) { case VK_Escape: save_mode = 0; clrin_pho(); prbuf(); clr_in_area_pho(); cpg = sel_pho = 0; return 1; case VK_Enter: if (c_len) { if (shift_m) { save_frm = c_idx; save_to = c_len - 1; save_phrase(); return 1; } putbuf(ch_buf, c_len); ClrSelArea(); c_len = c_xlen = c_idx = 0; c_x = SelAreaX; clr_ch_buf(); return 1; } return 0; case VK_Home: if (!c_len) return 0; clrcursor(); c_idx = 0; c_x = SelAreaX; drawcursor(); return 1; case VK_End: if (!c_len) return 0; clrcursor(); c_idx = c_len; drawcursor(); return 1; case VK_Left: if (c_idx) { clrcursor(); c_idx--; drawcursor(); c_x = pox[c_idx]; return 1; } return 0; case VK_Right: if (c_idx < c_len) { clrcursor(); c_idx++; drawcursor(); c_x = pox[c_idx]; return 1; } return 0; case VK_Tab: eng_ph ^= 1; clrcursor(); if (c_idx == c_len) { if (eng_ph || HalfFull) { ch_buf[c_len][0] = 0xa1; ch_buf[c_len][1] = 0x40; } else ch_buf[c_len][0] = ' '; } show_stat(); drawcursor(); return 1; case VK_KP_Multiply: if (save_mode) { save_to = c_idx; save_phrase(); save_mode = 0; bell(); } else { save_frm = c_idx; save_mode = 1; bell(); } return 1; case VK_Delete: #if !DELETE_K return 1; #endif case VK_BackSpace: ityp3_pho = 0; for (j = 3; j >= 0; j--) if (typ_pho[j]) { typ_pho[j] = 0; disp_in_area_pho(); return 1; } if (!c_idx) return 0; { int k, pst; clrcursor(); c_idx--; pst = k = psta[c_idx]; if (ch_buf[c_idx][0] & 0x80) c_xlen -= 2; else c_xlen--; for (k = c_idx; k < c_len; k++) { memcpy(ch_buf[k], ch_buf[k + 1], 2); memcpy(ch_obuf[k], ch_obuf[k + 1], 2); ph_buf[k] = ph_buf[k + 1]; psta[k] = psta[k + 1] - 1; } c_len--; prbuf(); if (!c_idx) { ph_sta = -1; } else { k = c_idx - 1; pst = psta[k]; while (k > 0 && psta[k] == pst) k--; if (psta[k] != pst) k++; len = c_idx - k; if (!(len = scanphr(&ph_buf[k], len))) ph_sta = -1; else ph_sta = k; } return 1; } case ' ': case VK_Down: case VK_Up: if (going_key && xkey == ' ' && !typ_pho[0] && !typ_pho[1] && !typ_pho[2] && !typ_pho[3] ) goto asc_char; /* * if (!going_key && xkey==VK_Down) return 0; */ if (!eng_ph) goto asc_char; if (!ityp3_pho && (typ_pho[0] || typ_pho[1] || typ_pho[2])) { ctyp = 3; kno = 0; if (typ_pho[0] && !typ_pho[1] && !typ_pho[2] && !typ_pho[3]) { char tch = inph[0]; if (phkbm.phokbm[tch][1][1] == 2) { typ_pho[0] = 0; typ_pho[2] = phkbm.phokbm[tch][1][0]; } } goto llll1; } if (c_len) { if (sel_pho == 2) { if (xkey == VK_Up) { if (cpg >= SELKEY) cpg -= SELKEY; else { while ((startf + ((cpg + SELKEY) << 1)) < end) cpg += SELKEY; } } else { ii = startf + ((cpg + SELKEY) << 1); if (ii < end) cpg += SELKEY; else cpg = 0; } } else if (!sel_pho && c_len - c_idx >= 2) { sel_phr(); if (sel_pho == 1) return 1; } else sel_pho = 2; if (c_idx == c_len) key = ph_buf[c_idx - 1]; else key = ph_buf[c_idx]; if (!key) return 1; i = hash_pho[key >> 9]; while (i < idxnum_pho) { ttt = idx_pho[i]; if (ttt >= key) break; i += 2; } if (ttt != key) { /* error("err in table"); */ return 1; } ClrSelArea(); ii = idx_pho[i + 1]; end = idx_pho[i + 3]; startf = ii; ii += cpg << 1; i = 0; while (i < SELKEY && ii < end) { u_char t[3]; b2cpy(t, &ch_pho[ii]); t[2] = 0; xprintf("%c%s ", phkbm.selkey[i], t); ii += 2; i = i + 1; } if (ii < end) { if (cpg) xprintf("<\\"); else xprintf(" "); xprintf(">"); } else xprintf("<"); maxi = i; return 1; } return 0; default: if ((pp = strchr(phkbm.selkey, xkey)) && maxi && sel_pho) { int c = pp - phkbm.selkey; if (c < maxi) { if (sel_pho == 1) { memcpy(ch_buf[c_idx], selstr[c], sellen[c] * 2); raise_phr(c); } else { int ofs = startf + ((cpg + c) << 1); i = c_idx == c_len ? c_idx - 1 : c_idx; memcpy(ch_buf[i], &ch_pho[ofs], 2); key = ph_buf[i]; if (i && psta[i] < i) memcpy(ch_buf[i - 1], ch_obuf[i - 1], 2); #if Auto_First j = key >> 6; for (i = sel1st_hash[j]; i < sel1st_hash[j + 1]; i++) if (sel1st[i].ph == key) break; if (sel1st[i].ph == key) memcpy(sel1st[i].ch, &ch_pho[ofs], 2); else error("tsin.c:bug1"); #endif } prbuf(); cpg = maxi = sel_pho = ityp3_pho = 0; ph_sta = -1; } return 1; } if (xkey > 127 && !is_kp_num(xkey)) return 0; sel_pho = cpg = 0; } if (!eng_ph || shift_m || is_kp_num(xkey)) { u_char tt; asc_char: if (is_kp_num(xkey)) xkey &= 0xff; if (xkey >= 127 || xkey < ' ') return 0; if (shift_m && eng_ph) { char *ppp = strchr(ochars, xkey); if (!(kbstate & KEY_CAPS_MASK) && ppp && !((ppp - ochars) & 1)) xkey = *(ppp + 1); if (kbstate & KEY_CAPS_MASK && islower(xkey)) xkey -= 0x20; else if (!(kbstate & KEY_CAPS_MASK) && isupper(xkey)) xkey += 0x20; } tt = xkey; /* endian conv */ shift_ins(); gotox(c_x); pox[c_idx] = c_x; if (HalfFull) { b2cpy(ch_buf[c_idx], &fullchar[(xkey - ' ') << 1]); c_xlen += 2; c_x += 2; } else { ch_buf[c_idx][0] = tt; c_xlen++; c_x++; } prch(ch_buf[c_idx]); ph_buf[c_idx] = 0; c_idx++; pox[c_idx] = c_x; if (c_idx < c_len) prbuf(); if (c_idx == c_len) { if (HalfFull) { ch_buf[c_len][0] = 0xa1; ch_buf[c_len][1] = 0x40; } else ch_buf[c_len][0] = ' '; } drawcursor(); return 1; } else { /* pho */ if (xkey >= 'A' && xkey <= 'Z') xkey += 0x20; ctyp = -1; for (i = 2; i >= 0; i--) if (typ_pho[i]) break; kno = phkbm.phokbm[xkey][0][0]; ctyp = phkbm.phokbm[xkey][0][1]; for (j = 0; j < 3; j++) if (phkbm.phokbm[xkey][j][1] > i) { kno = phkbm.phokbm[xkey][j][0]; ctyp = phkbm.phokbm[xkey][j][1]; break; } if (!kno) return 0; typ_pho[ctyp] = kno; inph[ctyp] = xkey; llll1: jj = 0; kk = 1; llll2: if (ctyp == 3) ityp3_pho = 1; /* last key is entered */ disp_in_area_pho(); key = (u_short) typ_pho[0] << 9 | (u_short) typ_pho[1] << 7 | (u_short) typ_pho[2] << 3 | typ_pho[3]; j = key >> 6; for (i = sel1st_hash[j]; i < sel1st_hash[j + 1]; i++) { ttt = sel1st[i].ph; if (!typ_pho[0]) ttt &= ~(31 << 9); if (!typ_pho[1]) ttt &= ~(3 << 7); if (!typ_pho[2]) ttt &= ~(15 << 3); if (!typ_pho[3]) ttt &= ~(7); if (ttt == key) break; } if (ttt != key || ityp3_pho && sel1st[i].ph != key) { while (jj < 4) { while (kk < 3) if (phkbm.phokbm[inph[jj]][kk][0]) { ctyp = phkbm.phokbm[inph[jj]][kk - 1][1]; typ_pho[ctyp] = 0; kno = phkbm.phokbm[inph[jj]][kk][0]; ctyp = phkbm.phokbm[inph[jj]][kk][1]; typ_pho[ctyp] = kno; #if 0 printf("## jj:%d kk:%d kno:%d ctyp:%d\n", jj, kk, kno, ctyp); #endif /* 0 */ kk++; goto llll2; } else kk++; jj++; kk = 1; } if (ityp3_pho) { bell(); clrin_pho(); clr_in_area_pho(); return 1; } } if (key == 0 || !ityp3_pho) return 1; } /* pho */ shift_ins(); pho1st_lidx = i; memcpy(ch_buf[c_idx], (char *)sel1st[i].ch, 2); memcpy(ch_obuf[c_idx], (char *)sel1st[i].ch, 2); gotox(c_x); prch(ch_buf[c_idx]); ph_buf[c_idx] = key; pox[c_idx] = c_x; c_idx++; c_x += 2; c_xlen += 2; pox[c_idx] = c_x; if (c_idx < c_len - 1) prbuf(); drawcursor(); clrin_pho(); clr_in_area_pho(); if (ph_sta < 0) { restart: if (len = scanphr(&ph_buf[c_idx - 1], 1)) ph_sta = c_idx - 1; psta[c_idx - 1] = c_idx - 1; return 1; } else { j = c_idx - 1 - ph_sta; if (j < len && tk[j] == key) { if (memcmp(ch_buf[ph_sta], tch[0], 2)) { gotox(c_x - 4); prch(tch[0]); memcpy(ch_buf[ph_sta], tch[0], 2); } memcpy(ch_buf[c_idx - 1], tch[j], 2); psta[c_idx - 1] = ph_sta; gotox(c_x - 2); prch(tch[j]); return 1; } while (sti < edi) { i = phidx[sti]; fseek(fph, i, SEEK_SET); fread(&len, 1, 1, fph); if (j >= len) { sti++; continue; } fread(&tk, 2, len, fph); fread(tch, 2, len, fph); sti++; for (i = 0; i <= j; i++) if (tk[i] != ph_buf[ph_sta + i]) break; if (i <= j) { if (tk[i] < ph_buf[ph_sta + i]) continue; else break; } memcpy(&ch_buf[ph_sta], tch, (j + 1) * 2); psta[c_idx - 1] = ph_sta; gotox(pox[ph_sta]); for (i = 0; i <= j; i++) { prch(tch[i]); } return 1; } ph_sta = -1; goto restart; } return 1; }