/* * Copyright (C) 1994,1995 Edward Der-Hua Liu, Hsin-Chu, Taiwan */ #include "big5con.h" #ifndef SEEK_SET #define SEEK_SET 0 #endif #define U_short(tt) (*(u_short *)(tt)) #define KeyBits (6) #define b2cpy(a,b) memcpy(a,b,2) #define MAX_CIN_PHR (40) typedef struct { ITEM *tbl; u_char quick1[46][10][2]; int use_quick; char cname[16]; u_char keycol[50]; int KeyS; /* number of keys needed */ int MaxPress; /* Max len of keystrike ar30:4 changjei:5 */ int DefChars; /* defined chars */ u_char keyname[128]; u_short idx1[51]; u_char keymap[128]; char selkey[12]; u_char *sel1st; int M_DUP_SEL; FILE *fp, *fphr; u_short revidx[256]; int phrnum; } INMD; static INMD inmd[10], *cur_inmd; static int spc_pressed = 0; static char seltab[12][MAX_CIN_PHR]; static int defsel = 0; static u_long inch[5]; static int ci; static int last_full, last_idx; static int more_pg, pg_idx, m_pg_mode; static int sel1st_i; int wild_mode; int wild_page; extern int cursor_x; /* for array30-like quick code */ static char keyrow[] = "qwertyuiop" "asdfghjkl;" "zxcvbnm,./"; #define key_col(cha) ( ((u_long)strchr(keyrow, cha) -(u_long)keyrow)%10) void ClrSelArea() { int i; gotox(SelAreaX); for (i = 0; i < MCOL; i++) xprintf(" "); gotox(SelAreaX); } static void ClrInArea() { int i; gotox(InAreaX); set_att(InAreaColor); for (i = 0; i < cur_inmd->MaxPress; i++) xprintf(" "); set_att(NormalColor); for (; i < 5; i++) xprintf(" "); last_idx = 0; } static void ClrIn() { bzero(inch, sizeof(inch)); bzero(seltab, sizeof(seltab)); m_pg_mode = pg_idx = more_pg = wild_mode = wild_page = last_idx = defsel = spc_pressed = ci = 0; sel1st_i = 15; } static void DispInArea() { int i; gotox(InAreaX); set_att(InAreaColor); for (i = 0; i < ci; i++) xprintf("%c%c", cur_inmd->keyname[inch[i] << 1], cur_inmd->keyname[(inch[i] << 1) + 1]); if (i < cur_inmd->MaxPress) xprintf(" "); set_att(NormalColor); } static void reset_inp() { ClrIn(); ClrInArea(); ClrSelArea(); last_full = 0; } extern char *tabfname[], TabDir[]; extern int show_keys[]; extern show_keys_n; void init_tab(int inmdno, int usenow) { FILE *fp; char ttt[128], uuu[128]; int i; INMD *inp = &inmd[inmdno]; struct TableHead th; if (inp->tbl) { gotox(0); xprintf("%s", inp->cname); cur_inmd = inp; reset_inp(); ClrInArea(); DispInArea(); return; /* table is already loaded */ } strcpy(ttt, TabDir); if ((fp = fopen(strcat(ttt, tabfname[inmdno]), "r")) == NULL) { error("init_tab:1 err open %s", ttt); return; } strcpy(uuu, ttt); fread(&th, 1, sizeof(th), fp); fread(ttt, 1, th.KeyS, fp); fread(inp->keyname, 2, th.KeyS, fp); inp->keyname[61 * 2] = ' '; /* for wild card */ inp->keyname[61 * 2 + 1] = '?'; inp->keyname[62 * 2] = ' '; inp->keyname[62 * 2 + 1] = '*'; inp->KeyS = th.KeyS; inp->MaxPress = th.MaxPress; inp->DefChars = th.DefC; strcpy(inp->selkey, th.selkey); inp->M_DUP_SEL = th.M_DUP_SEL; for (i = 0; i < th.KeyS; i++) { inp->keymap[ttt[i]] = i; inp->keymap[toupper(ttt[i])] = i; inp->keycol[i] = key_col(ttt[i]); } if ((inp->fp = fopen(strcat(uuu, ".rev"), "r")) == NULL) { error("init_tab:2 err open %s.rev", uuu); error("Wildcard & code lookup will not function"); } else { show_keys[show_keys_n++] = inmdno; fread(inp->revidx, 2, 256, inp->fp); } if (strlen(th.cname) > 8) strcpy(ttt, th.cname); else { ttt[0] = ' '; strcpy(&ttt[1], th.cname); } strcpy(inp->cname, ttt); inp->keymap[(int)'?'] = 61; inp->keymap[(int)'*'] = 62; fread(inp->idx1, 2, th.KeyS + 1, fp); /* printf("chars: %d\n",th.DefC); */ if ((inp->tbl = (ITEM *) malloc(sizeof(ITEM) * th.DefC)) == NULL) { error("malloc err"); return; } #if 0 printf("init %s\n", tabfname[inmdno]); #endif /* 0 */ fread(inp->tbl, sizeof(ITEM), th.DefC, fp); #if 0 printf("KeyNum:%d MaxPress:%d\n", th.KeyS, th.MaxPress); #endif /* 0 */ fclose(fp); strcpy(ttt, TabDir); strcat(ttt, tabfname[inmdno]); strcat(ttt, ".quick"); if (fp = fopen(ttt, "r")) { fread(inp->quick1, 2, (th.KeyS - 1) * 10, fp); inp->use_quick = 1; fclose(fp); } strcpy(ttt, TabDir); strcat(ttt, tabfname[inmdno]); strcat(ttt, ".sel1st"); if (fp = fopen(ttt, "r")) { struct stat fst; int fsize; fstat(fileno(fp), &fst); fsize = fst.st_size; if (inp->sel1st) free(inp->sel1st); inp->sel1st = (u_char *) malloc(fsize + 2); fread(inp->sel1st, 1, fsize, fp); inp->sel1st[fsize] = inp->sel1st[fsize + 1] = 0; fclose(fp); } strcpy(ttt, TabDir); strcat(ttt, tabfname[inmdno]); strcat(ttt, ".phr"); if (inp->fphr = fopen(ttt, "r")) { fread(&inp->phrnum, 4, 1, inp->fphr); } if (usenow) { cur_inmd = inp; reset_inp(); gotox(0); xprintf("%s", inp->cname); gotox(InAreaX); set_att(InAreaColor); ClrInArea(); DispInArea(); } } static void putstr_inp(u_char * p) { if (p[2]) putstr(p); else sendkey_b5(p); ClrIn(); ClrSelArea(); ClrInArea(); } void b52key(int inmdno, u_char * ch, u_char * out) { u_long kkk; u_short ofs, ofs1; int k1, k2, k3, k4, k5, slen, len; INMD *inp = &inmd[inmdno]; char *kname = inp->keyname; FILE *fp = inp->fp; ITEM it; extern cur_input_ch[]; *out = 0; if (!fp) init_tab(inmdno, 0); ofs = inp->revidx[ch[0]]; ofs1 = inp->revidx[ch[0] + 1]; fseek(fp, ofs * sizeof(ITEM) + 256 * 2, 0); slen = 0; while (ofs < ofs1) { if (fread(&it, 1, sizeof(ITEM), fp) != sizeof(ITEM)) break; ofs++; if (it.ch[1] > ch[1]) break; if (it.ch[1] != ch[1] || it.ch[0] != ch[0]) continue; kkk = CONVT(it.key); k1 = (kkk >> 24) & 0x3f; k2 = (kkk >> 18) & 0x3f; k3 = (kkk >> 12) & 0x3f; k4 = (kkk >> 6) & 0x3f; k5 = (kkk) & 0x3f; #define t0(k) kname[k<<1] #define t1(k) kname[(k<<1)+1] if (k1) { out[slen++] = t0(k1); out[slen++] = t1(k1); } if (k2) { out[slen++] = t0(k2); out[slen++] = t1(k2); } if (k3) { out[slen++] = t0(k3); out[slen++] = t1(k3); } if (k4) { out[slen++] = t0(k4); out[slen++] = t1(k4); } if (k5) { out[slen++] = t0(k5); out[slen++] = t1(k5); } slen++; } #undef t0 #undef t1 } #define swap(a,b) { tt=a; a=b; b=tt; } static u_long vmask[] = {0, 0x3f << 24, (0x3f << 24) | (0x3f << 18), (0x3f << 24) | (0x3f << 18) | (0x3f << 12), (0x3f << 24) | (0x3f << 18) | (0x3f << 12) | (0x3f << 6), (0x3f << 24) | (0x3f << 18) | (0x3f << 12) | (0x3f << 6) | 0x3f }; qcmp_b5(u_char * a, u_char * b) { return strcmp(a, b); } /* for strict match, use stack */ void wildcard() { int i, j, t, vv, match, wild_ofs = 0; u_long kk; ITEM it; int found = 0; FILE *fp; if (!(fp = cur_inmd->fp)) return; ClrSelArea(); bzero(seltab, sizeof(seltab)); /* printf("wild %d %d %d %d\n", inch[0], inch[1], inch[2], inch[3]); */ defsel = 0; gotox(SelAreaX + 1); fseek(fp, 256 * 2, SEEK_SET); for (t = 0; t < cur_inmd->DefChars && defsel < 10; t++) { bzero(&it, sizeof(it)); fread(&it, 1, sizeof(it), fp); kk = CONVT(it.key); match = 1; for (i = 0; i < ci && match && kk;) switch (inch[i]) { case 61: /* ? */ kk = (kk << 6) & vmask[4]; i++; break; case 62: /* * */ if (i == ci - 1) { kk = 0; i++; break; } if (inch[i + 1] == '*' || inch[i + 1] == '?') { i += 2; continue; } do { vv = (kk >> 24) & 0x3f; kk = (kk << 6) & vmask[4]; } while (vv && vv != inch[i + 1]); if (vv != inch[i + 1]) match = 0; if (i == ci - 2 && kk) continue; i += 2; continue; default: if (inch[i] != ((kk >> 24) & 0x3f)) { match = 0; break; } kk = (kk << 6) & vmask[4]; i++; } /* switch */ if (i == ci && match && !(kk & vmask[4])) { if (wild_ofs >= wild_page) { xprintf("%d%c%c", (defsel + 1) % 10, it.ch[0], it.ch[1]); cursor_x++; b2cpy(seltab[defsel++], it.ch); } else wild_ofs++; found = 1; } } /* for t */ if (!found) bell(); } static char * is_selkey(int key) { return strchr(cur_inmd->selkey, key); } static void load_phr(int j, char *tt) { FILE *fp = cur_inmd->fphr; int ofs[2], len; int phrno = ((int)(cur_inmd->tbl[j].ch[0]) << 8) | cur_inmd->tbl[j].ch[1]; fseek(fp, (phrno + 1) * 4, SEEK_SET); fread(ofs, 4, 2, fp); len = ofs[1] - ofs[0]; if (len > 128 || len <= 0) { error("phrae error %d\n", len); strcpy(tt, "err"); return; } ofs[0] += (cur_inmd->phrnum + 1) * 4; fseek(fp, ofs[0], SEEK_SET); fread(tt, 1, len, fp); tt[len] = 0; } feedkey(int key) { int i, j; static u_long val; static int s1, e1; int inkey; int exa_match; char *iselkey = (char *)0; switch (key) { case VK_BackSpace: #if DELETE_K case VK_Delete: #endif last_idx = 0; if (ci == 0) return 0; if (ci > 0) inch[--ci] = 0; wild_mode = spc_pressed = 0; if (ci == 1 && cur_inmd->use_quick) { int i; bzero(seltab, sizeof(seltab)); for (i = 0; i < 10; i++) memcpy(seltab[i], &cur_inmd->quick1[inch[0] - 1][i][0], 2); defsel = 10; DispInArea(); goto Disp_opt; } break; case VK_Escape: if (ci) { ClrSelArea(); ClrInArea(); ClrIn(); return 1; } else return 0; case '<': if (wild_mode) { if (wild_page >= 10) wild_page -= 10; wildcard(); return 1; } return 0; case ' ': if (wild_mode) { if (defsel == 10) wild_page += 10; else wild_page = 0; wildcard(); return 1; } else if (more_pg) { j = pg_idx; goto next_pg; } else if (seltab[sel1st_i][0]) { putstr_inp((u_char *) & seltab[sel1st_i]); /* select 1st */ return 1; } if (ci == 0) { if (last_full) { last_full = 0; return 1; } return 0; } last_full = 0; spc_pressed = 1; for (i = 0; i < 5; i++) if (inch[i] > 60) { wild_page = 0; wild_mode = 1; wildcard(); return 1; } break; case '?': case '*': if (ci < cur_inmd->MaxPress) { inkey = cur_inmd->keymap[key]; inch[ci++] = inkey; DispInArea(); if (ci == cur_inmd->MaxPress) { wild_page = 0; wild_mode = 1; wildcard(); } return 1; } return 0; default: if (is_kp_num(key)) key &= 0xff; if (key < 32 || key > 0x7e) { if (seltab[sel1st_i][0]) putstr_inp(seltab[sel1st_i]); /* select 1st */ return 0; } iselkey = is_selkey(key); if (iselkey && !ci) return 0; if (!iselkey && seltab[sel1st_i][0] && key != 8 && !wild_mode) { putstr_inp(seltab[sel1st_i]); /* select 1st */ } if (wild_mode) goto XXXX; inkey = cur_inmd->keymap[key]; spc_pressed = 0; if (inkey >= 1 && ci < cur_inmd->MaxPress) { inch[ci++] = inkey; last_full = 0; if (ci == 1 && cur_inmd->use_quick) { int i; for (i = 0; i < 10; i++) memcpy(seltab[i], &cur_inmd->quick1[inkey - 1][i][0], 2); defsel = 10; DispInArea(); goto Disp_opt; } } if (inkey) for (i = 0; i < 5; i++) if (inch[i] > 60) { DispInArea(); if (ci == cur_inmd->MaxPress) { wild_mode = 1; wild_page = 0; wildcard(); } return 1; } if (iselkey && CurInMethod == 8 && inch[0] == 23 && ci == 3) goto YYYY; /* * if (iselkey && defsel && (CurInMethod!=8 || inch[0]!=23 ||ci!=2)) * goto XXXX; */ if (!inkey && iselkey && defsel) goto YYYY; if (!inkey && !iselkey) return 0; } /* switch */ if (ci == 0) { ClrSelArea(); ClrInArea(); ClrIn(); return 1; } DispInArea(); val = inch[4] | (inch[3] << 6) | (inch[2] << 12) | (inch[1] << 18) | (inch[0] << 24); if (!last_idx) { s1 = cur_inmd->idx1[inch[0]]; } else s1 = last_idx; e1 = cur_inmd->idx1[inch[0] + 1]; while ((CONVT(cur_inmd->tbl[s1].key) & vmask[ci]) != val && CONVT(cur_inmd->tbl[s1].key) < val && s1 < e1) s1++; last_idx = s1; XXXX: if ((CONVT(cur_inmd->tbl[s1].key) & vmask[ci]) != val || (wild_mode && defsel) || (ci == cur_inmd->MaxPress || spc_pressed) && defsel && iselkey) { YYYY: if ((iselkey || wild_mode) && defsel) { int vv = iselkey - cur_inmd->selkey; if (vv < 0) vv = 9; if (seltab[vv][0]) { putstr_inp(seltab[vv]); return 1; } } if (iselkey && !defsel) return 0; bell(); if (ci > 0) inch[--ci] = 0; last_idx = 0; DispInArea(); return 1; } if (CurInMethod == 8 && CONVT(cur_inmd->tbl[s1].key) == val && iselkey) { spc_pressed = 1; } refill: j = s1; if (ci < cur_inmd->MaxPress && !spc_pressed) { int shiftb = (4 - ci) * KeyBits; defsel = 0; bzero(seltab, sizeof(seltab)); while (CONVT(cur_inmd->tbl[j].key) == val && defsel < 10) { if (cur_inmd->tbl[j].ch[0] >= 0x80) b2cpy(seltab[defsel++], cur_inmd->tbl[j].ch); j++; } if (defsel) qsort(seltab, defsel, MAX_CIN_PHR, qcmp_b5); exa_match = defsel - 1; while ((CONVT(cur_inmd->tbl[j].key) & vmask[ci]) == val && j < e1) { int fff = cur_inmd->keycol[(CONVT(cur_inmd->tbl[j].key) >> shiftb) & (u_long) 0x3f]; if (!(seltab[fff][0]) || (memcmp(seltab[fff], cur_inmd->tbl[j].ch, 2) > 0 && fff > exa_match)) { if (cur_inmd->tbl[j].ch[0] >= 0x80) { b2cpy(seltab[fff], cur_inmd->tbl[j].ch); defsel++; } } j++; } } else { next_pg: defsel = more_pg = 0; bzero(seltab, sizeof(seltab)); /* * printf("** pg_idx:%d j:%d e1:%d val:%x\n", pg_idx, j, e1, val); */ while (CONVT(cur_inmd->tbl[j].key) == val && defsel < cur_inmd->M_DUP_SEL && j < e1) { if (cur_inmd->tbl[j].ch[0] < 0x80) load_phr(j++, seltab[defsel++]); else b2cpy(&seltab[defsel++], cur_inmd->tbl[j++].ch); } if (j < e1 && CONVT(cur_inmd->tbl[j].key) == val && defsel == cur_inmd->M_DUP_SEL) { pg_idx = j; more_pg = 1; m_pg_mode = 1; } else if (m_pg_mode) { pg_idx = s1; more_pg = 1; } if (defsel == 1 && !more_pg) { if (ci == cur_inmd->MaxPress) last_full = 1; putstr_inp(seltab[0]); return 1; } else if (!defsel) { bell(); spc_pressed = 0; goto refill; } else if (!more_pg) bell(); } Disp_opt: ClrSelArea(); sel1st_i = 15; for (i = 0; i < 10; i++) if (seltab[i][2]) break; if (i >= 10) { gotox(SelAreaX + 37); for (i = 9; i >= 0; i--) { int k; if (seltab[i][0]) { int new_x; if (cur_inmd->sel1st && (spc_pressed || ci == cur_inmd->MaxPress)) { for (k = 0; cur_inmd->sel1st[k]; k += 2) if (!memcmp(&cur_inmd->sel1st[k], seltab[i], 2)) { set_att(InAreaColor); sel1st_i = i; break; } if (sel1st_i == 15 && !i && !more_pg) { set_att(InAreaColor); sel1st_i = i; } } else { if ((spc_pressed || ci == cur_inmd->MaxPress) && !i && !more_pg) { set_att(InAreaColor); sel1st_i = i; } } xprintf("%d", (i + 1) % 10); set_att(NormalColor); xprintf("%s", seltab[i]); cursor_x -= 7; } else cursor_x -= 4; } } else { gotox(SelAreaX); for (i = 0; i < 10; i++) { if (seltab[i][0]) { xprintf("%d", (i + 1) % 10); set_att(NormalColor); xprintf("%s ", seltab[i]); } } } return 1; }