/* vi:ts=4:sw=4 * * VIM - Vi IMitation Extension for Japanese Frontend Processor * * Code Contributions By: Atsushi Nakamura ann@mrit.mei.co.jp */ #include "vim.h" #ifdef JP #include "globals.h" #include "proto.h" #include "param.h" #include "jp.h" #define ISKFUNC(c) ((c & 0x60) == 0) static char *saved_line = NULL; #endif #ifdef JPFEP static char fep_buf[MAX_COLUMNS * 2 + 1] = "", *fbp = fep_buf; static void fep_delchars(); static int fep_insstr(); #ifdef ONEW static char kanakan_buf[MAX_COLUMNS + 1] = ""; static char hira_buf[MAX_COLUMNS + 1] = ""; static int kanakan_len = 0; static int freq_save = FALSE; void Onew_putmsg(), Onew_kakutei(); void Onew_RK_init(), Onew_RK_cmode_set(), Onew_KK_freqsave(); int Onew_RK_imode(), Onew_kanakan(), Onew_romkan(); char *Onew_version(); #define FUNCMASK 0xffffff00 int ONEW_GETCHAR() { u_char c; c = (u_char)vgetc(); if (c == K_ZERO || c == Ctrl('\\')) /* convert key */ return p_oh ? NUL : (K_ZERO | FUNCMASK); if (IsKanji(c) && ISKFUNC(c)) /* function key */ return c | FUNCMASK; if (p_okc && isupper(c)) { ONEW_KAKUTEI(c); return p_oh ? c : tolower(c); } return c; } int ONEW_PEEKCHAR(timeout) int *timeout; { int c; if(!( c = vpeekc() )) *timeout = -1; return c; } static char *modep = ""; void ONEW_DISP_ROMKANMODE(mode, help, imode) int imode; char *mode, *help; { int rk; char *mchrs, *cp; static char modebuf[20]; static int oldimode = -1; if (!mode) { oldimode = -1; Onew_putmsg(FALSE, ""); return; } rk = Onew_RK_imode(); if (State == CMDLINE) { cmd_message(rk ? mode : ""); modep = mode; if (oldimode != imode) { oldimode = imode; if (rk) Onew_putmsg(rk, "%s %s", help, Onew_version()); else Onew_putmsg(rk, ""); } cursorcmd(); return; } switch(State) { case INSERT: mchrs = "[]"; break; case REPLACE: mchrs = "<>"; break; case NOMAPPING: mchrs = "()"; break; default: mchrs = "//"; break; } sprintf(modebuf, p_ri ? "%c<-%s": "%c%s", *mchrs++, mode + 1); cp = modebuf + strlen(modebuf) - 1; *cp++ = *mchrs; if (p_ja) *cp++ = *p_ji; *cp = NUL; if (oldimode != imode) { oldimode = imode; if (p_fm) { screen_msg(FALSE, NULL); Onew_putmsg(FALSE, Recording ? "[%s].%c... %s/%s" : "[%s]:%c %s/%s", help, *p_jc, JpVersion, Onew_version()); } else Onew_putmsg(rk, Recording ? "%s%s ...%c %s/%s" : "%s%s %c %s/%s", modebuf, help, *p_jc, JpVersion, Onew_version()); } if (p_fm && rk) screen_msg(rk, modebuf); cursupdate(); setcursor(); } void ONEW_DISP_KANAHALVES(s) char *s; { if (State == CMDLINE) { cmd_insertstr(s); cmd_delchars(strlen(s)); cursorcmd(); } else { int mode, n; char *cp; mode = State; State = INSERT; for(cp = s, n = 0; *cp; cp++, n++) insertchar(*cp, NUL); if (p_ri) KconvEnd += n; else Curpos.col -= n; cursupdate(); setcursor(); updateline(); for(cp = s; *cp; cp++) delchar(FALSE); if (p_ri) KconvEnd -= n; State = mode; } } int ONEW_DISP_KANAKANB(so, left, cur, right) int so; char *left, *cur, *right; { int mode = State; sprintf(kanakan_buf, "%s%s%s", left, cur, right); if (State == CMDLINE) { Kconvlnum = -1; KconvStart = KconvEnd = 0; KconvAltStart = strlen(left); /* Reverse start */ KconvAltEnd = KconvAltStart + strlen(cur); /* Reverse end */ } else { if (State !=REPLACE) State = INSERT; Kconvlnum = Curpos.lnum; KconvStart = Curpos.col; /* UL start */ KconvAltStart = KconvStart + strlen(p_ri?right:left); /* RV start */ KconvAltEnd = KconvAltStart+ strlen(cur); /* RV end */ KconvEnd = KconvAltEnd + strlen(p_ri?left:right); /* UL end */ } kanakan_len = fep_insstr(kanakan_buf); if (State == CMDLINE) cmd_message(modep); fep_delchars(kanakan_len); windgoto(Rows - 1, Columns - 1); State = mode; return 0; } int onew_noredraw = FALSE; /* to avoid textwidth folding */ int ONEW_KANAKAN(ch) int ch; { if (fbp != fep_buf) { fep_delchars(strlen(fep_buf)); strncpy(hira_buf, fep_buf, fbp - fep_buf); hira_buf[fbp - fep_buf] = NUL; ch = Onew_kanakan(ch, fep_buf, 0, fbp - fep_buf); freq_save = TRUE; strcpy(fep_buf, kanakan_buf); fbp = fep_buf + fep_insstr(fep_buf); Onew_kakutei(ch); if (ch != ESC && ch != TAB) ch = NUL; } return ch; } int ONEW_KAKUTEI(ch) int ch; { int fix = FALSE; if (fbp != fep_buf) { if (ch == BS || ch == DEL) { fep_delchars(fbp - fep_buf); strcpy(fep_buf, hira_buf); fbp = fep_buf + strlen(fep_buf); if (State == CMDLINE) { Kconvlnum = 0; KconvAltStart = KconvAltEnd = -1; } else { Kconvlnum = Curpos.lnum; KconvStart = Curpos.col; KconvEnd = KconvStart + (fbp - fep_buf); } fep_insstr(fep_buf); } else { *fbp = NUL; AppendToRedobuff(fep_buf); *(fbp = fep_buf) = hira_buf[0] = NUL; fix = TRUE; Kconvlnum = 0; if (p_tw) { onew_noredraw = FALSE; insertchar(NUL, NUL); onew_noredraw = TRUE; } } } if (State == CMDLINE) redrawcmdline(); else { cursupdate(); setcursor(); updateline(); } kanakan_len = 0; return fix; } void ONEW_GOT_2BCHAR(buf, a, b) char *buf, a, b; { sprintf(buf, "%c%c", a, b); } int ONEW_MESSAGE_COLS() { return sc_col; } void ONEW_MESSAGE(so, form, a, b, c, d, e) int so; char *form, *a, *b, *c, *d, *e; { sprintf(IObuff, form, a, b, c, d, e); if (!onew_rvmsg) so = FALSE; if (State == CMDLINE) screen_msg(so, IObuff); else { gotocmdline(TRUE, NUL); if (so && T_TI) outstr(T_TI); outtrans(IObuff, -1); if (so && T_TP) outstr(T_TP); flushbuf(); } } void ONEW_BEEP() { beep(); } static int fep_insstr(s) char *s; { int len; int sm; sm = p_sm; /* turn off showmatch option */ p_sm = FALSE; if (State == CMDLINE) len = cmd_insertstr(s); else { int w; int mode; mode = State; if (State != REPLACE) State = INSERT; for(len = 0; *s; len += w, s += w) { insertchar(*s, *(s + 1)); w = IsKanji(*s) ? 2 : 1; } cursupdate(); setcursor(); updateline(); State = mode; } p_sm = sm; /* restore showmatch option */ return len; } static void fep_delchars(len) int len; { switch(State) { case CMDLINE: cmd_delchars(len); break; case REPLACE: if (saved_line) { char *p, *c, *s; int nins; int col; if (!p_ri) { Curpos.col -= len; col = Curpos.col; } else { col = Curpos.col + len; incCurpos(); } p = nr2ptr(Curpos.lnum); c = p + Curpos.col; s = saved_line; while(p < c) { p += IsKanji(*p) ? 2 : 1; if (*s) s += IsKanji(*s) ? 2 : 1; } State = INSERT; for(nins = 0; len > 0; nins++) { if (IsKanji(*p)) /* delete one char. */ { delchar(FALSE); len--; } delchar(FALSE); len--; } for(; nins > 0 && *s; nins--) { /* insert one char. */ insertchar(*s, *(s + 1)); if (IsKanji(*s)) s++; s++; } Curpos.col = col; State = REPLACE; return; } default: if (!p_ri) Curpos.col -= len; for(; len; len--) delchar(FALSE); } } #endif /* ONEW */ /* * vim JPFEP interface */ /* * fep_mode_switch(TRUE ); FEP turned into KANJI mode * FALSE ; ASCII mode */ void fep_mode_switch(mode) int mode; { #ifdef ONEW Onew_RK_init(); Onew_RK_cmode_set(mode ? 'h' : '@'); #else return; #endif } /* * fep_mode() return TRUE ; FEP is in KANJI mode * FALSE; ASCII mode */ int fep_mode() { #ifdef ONEW return Onew_RK_imode(); #else return FALSE; #endif } /* * fep_freqsave(); save dictionary contents */ void fep_freqsave() { #ifdef ONEW if (freq_save) { smsg("saving kanji frequency..."); Onew_KK_freqsave(); smsg(""); freq_save = FALSE; } #endif } #endif /* JPFEP */ /* * jp_getchar(char *k1, char *k2); * return EUC character into k1 & k2 * or ascii character into k1 */ void jp_getchar(k1, k2, savedl) char *k1, *k2, *savedl; { #ifdef JP saved_line = savedl; #endif #ifdef ONEW if (!p_oh) #endif #ifdef JPFEP if (!KanjiInput) #endif { char c; *k1 = c = vgetc(); #ifdef JP *k2 = (IsKanji(c) && !ISKFUNC(c)) ? vgetc() : NUL; #endif #ifdef DOSGEN if (c == Ctrl(']')) { c = vgetc(); #ifdef JP if (IsKanji(c) && !ISKFUNC(c)) { beep(); c = vgetc(); jp_getchar(k1, k2, savedl); return; } #endif switch (c) { case 'h': case Ctrl('B'): c = K_LARROW; break; case 'j': case Ctrl('N'): c = K_DARROW; break; case 'k': case Ctrl('P'): c = K_UARROW; break; case 'l': case Ctrl('F'): c = K_RARROW; break; case 'H': case 'b': c = K_SLARROW; break; case 'J': c = K_SDARROW; break; case 'K': c = K_SUARROW; break; case 'L': case 'w': c = K_SRARROW; break; default: beep(); jp_getchar(k1, k2, savedl); return; } *k1 = c; } #endif /* DOSGEN */ return; } /* fep interface */ #ifdef ONEW { int oin; u_char in, ink; static int first = TRUE; if (first) { *(fbp = fep_buf) = hira_buf[0] = NUL; first = FALSE; } if (onew_noredraw) { if (State != CMDLINE) updateline(); } else onew_noredraw = TRUE; ink = NUL; if ((oin = Onew_romkan()) == -1) mch_windexit(5); in = oin & ~FUNCMASK; /* for function key */ if (in == NUL) in = K_ZERO; if (State == NOMAPPING) goto normal; switch(in) { case Ctrl('V'): got_int = FALSE; break; case Ctrl('C'): if (p_oh) in = ESC; case '\n': case '\r': case Ctrl('Q'): case K_ZERO: case ESC: Onew_kakutei(in); Kconvlnum = 0; first = TRUE; ONEW_DISP_ROMKANMODE(NULL, "", -1); smsg(""); onew_noredraw = FALSE; screen_msg(FALSE, NULL); if (State == CMDLINE) { redrawcmdline(); if (in == ESC) if (!p_oh) in = K_ZERO; else if (fep_mode()) { fep_mode_switch(FALSE); in = K_ZERO; } } break; case Ctrl('U'): fep_delchars(fbp - fep_buf); *(fbp = fep_buf) = hira_buf[0] = NUL; if (State == CMDLINE) redrawcmdline(); else updateline(); break; case DEL: case BS: if (fbp != fep_buf) { if (State == CMDLINE) { Kconvlnum = 0; KconvStart = -1; } else { KconvStart = KconvEnd - (fbp - fep_buf); KconvEnd --; } if (IsKanji(* --fbp)) { fbp --; KconvEnd --; } } else Kconvlnum = 0; break; case ' ': case TAB: *fbp++ = in; goto thru; case Ctrl('P'): ONEW_DISP_ROMKANMODE(NULL, "", -1); case Ctrl('D'): /* pass through characters */ case Ctrl('T'): case Ctrl('W'): case Ctrl('N'): case Ctrl('Y'): case Ctrl('E'): case Ctrl('B'): case Ctrl('F'): case Ctrl('X'): case K_DARROW: case K_UARROW: case K_RARROW: case K_LARROW: thru: Onew_kakutei(in); Kconvlnum = 0; ink = NUL; break; normal: default: if (fbp - fep_buf > MAX_COLUMNS) { emsg("Input buffer filled."); in = ink = NUL; break; } if (IsKanji(in) && !ISKFUNC(in)) { ink = Onew_romkan(); *fbp++ = in; *fbp++ = ink; KconvEnd = Curpos.col + (p_ri ? fbp - fep_buf : 2); } else if (State == NOMAPPING || (' ' <= in && in < DEL)) { *fbp++ = in; KconvEnd = Curpos.col + (p_ri ? fbp - fep_buf : 1); } else { first = TRUE; if (in < ' ') Onew_putmsg(TRUE,"JVim:'^%c' unsupported", in + '@'); if (in >= DEL) Onew_putmsg(TRUE,"JVim:x'%c' unsupported", in & 0x7f); ONEW_BEEP(1); in = 0; break; } if (State == CMDLINE) { Kconvlnum = KconvAltStart = -1; } else { Kconvlnum = Curpos.lnum; KconvStart = KconvEnd - (fbp - fep_buf); KconvAltStart = KconvAltEnd = Curpos.col; } break; } *fbp = NUL; *k1 = in; *k2 = ink; return; } #endif /* ONEW */ #if defined(JPFEP) && !defined(ONEW) { char *cp; int kanji; if (! *fbp) { smsg("Kanji> "); settmode(0); fgets(fep_buf, MAX_COLUMNS+1, stdin); settmode(1); cp = strchr(fep_buf, '\n'); if (cp) *cp = '\0'; if (State == CMDLINE) redrawcmdline(); else updateScreen(VALID); fbp = fep_buf; fep_mode_switch(KanjiInput = FALSE); } *k1 = *fbp++; if (IsKanji(*k1)) *k2 = *fbp++; return; } #endif /* ONEW */ } /* * get one kanji character from terminal */ void jp_getc1(cp1, cp2) char *cp1, *cp2; { #ifdef JPFEP int orgKanjiInput; orgKanjiInput = KanjiInput; fep_mode_switch(KanjiInput = TRUE); #endif jp_getchar(cp1, cp2, NULL); #ifdef JPFEP Kconvlnum = 0; updateline(); #endif screen_msg(FALSE, NULL); smsg(""); #ifdef ONEW onew_noredraw = FALSE; ONEW_DISP_ROMKANMODE(NULL, "", -1); hira_buf[0] = #endif /* ONEW */ #ifdef JPFEP *(fbp = fep_buf) = NUL; fep_mode_switch(KanjiInput = orgKanjiInput); #endif showmode(); }