/* * multilingual support for nvi * Copyright(c) 1996, 1997 by Jun-ichiro Itoh. All rights reserved. * Author contact: * $Id: multi_canna.c,v 1.1 2001/10/23 04:33:23 itojun Exp $ * * Freely redistributable, reusable, unless otherwise noted in accompanying * document. (for example, redistribution is prohibited during alpha-test * period) * Absolutely no warranty. * * The code is based on: * jelvis japanization patch by Jun-ichiro Itoh * nvi 1.03 japanization patch by Yoshitaka Tokugawa */ /* * Derived code: * * Canna support code was originally implemented by Nobuyuki Koganemaru * for jelvis. */ /* * Known bugs: * - sometimes dumps core if you do screen resize while canna fence is on * - while in ex, it won't work since ex is implemented by COOKED mode console. */ #include "config.h" #ifdef MULTIBYTE #ifdef CANNA #include #include #include #include #include #include #include #include #include #include #include #include #include "../common/common.h" #include "../vi/vi.h" #include "multibyte.h" static void canna_beep __P((void)); static void canna_setmode __P((SCR *, int, int)); static void canna_updatemodeline __P((SCR *)); static void canna_echoback __P((SCR *)); static void canna_inject __P((SCR *, ARG_CHAR_T)); static void canna_puteucjpstr3 __P((SCR *, char *, size_t, size_t, size_t, int)); static void canna_puteucjpstr __P((SCR *, char *, size_t, int)); static struct { int init; /* initialized flag */ /* canna fence on/off */ int mode; int keepmode; /* fence string. */ size_t fencelen; size_t fencelenmax; int fenceloc; #define FENCE_CURSOR 0 #define FENCE_MODELINE 1 #define FENCE_BOTTOM 2 size_t oldfencefrow; size_t oldfencetrow; size_t oldfencex; size_t oldfencey; /* modeline string. */ size_t modelinemax; /* width got from cannaserver */ size_t modelinelen; char *modeline; /* not CHAR_T. */ int modelinesw; /* 1: modeline is ours * 0: msg on modeline, don't overwrite */ /* guideline string. */ #define GUIDELINEMAX 100 size_t guidelinemax; size_t guidelinelen; char *guideline; /* not CHAR_T. */ size_t guidelinerevstart; size_t guidelinerevlen; size_t guidelinewidth; /* width registered with cannaserver */ /* canna server communication buffer. */ #define INBUFMAX 1024 u_char inbuf[INBUFMAX]; #define OUTBUFMAX 1024 CHAR_T outbuf[OUTBUFMAX]; size_t outhead; size_t outtail; #define C_OUTSIZE() (cannastate.outtail - cannastate.outhead) #define C_OUTGET() (cannastate.outbuf[cannastate.outhead++]) #define C_OUTPUT(c) { cannastate.outbuf[cannastate.outtail++] = (c); } #define C_OUTCLEAN() { \ if (cannastate.outtail == cannastate.outhead) \ cannastate.outtail = cannastate.outhead = 0; \ } int errorbell; jrKanjiStatus ks; jrKanjiStatusWithValue ksv; } cannastate; void canna_keyinput(sp, e, kbuf, kbuflen, intbuf, pintbuflen, pstate, pconsumed) SCR *sp; ENCODING const *e; CHAR_T *kbuf; size_t kbuflen; CHAR_T *intbuf; size_t *pintbuflen; int *pstate; size_t *pconsumed; { size_t i; size_t j; size_t consumed; int ch; int ilen; i = j = consumed = 0; while (i < kbuflen) { canna_inject(sp, kbuf[i]); i++; consumed++; } while (C_OUTSIZE()) { intbuf[j++] = C_OUTGET(); } C_OUTCLEAN(); *pintbuflen = j; *pconsumed = consumed; } /*------------------------------------------------------------*/ /* * PUBLIC: #ifdef CANNA * PUBLIC: int canna_enabled __P((SCR *)); * PUBLIC: #endif */ int canna_enabled(sp) SCR *sp; { return cannastate.mode; } /* * PUBLIC: #ifdef CANNA * PUBLIC: int canna_fenceactive __P((SCR *)); * PUBLIC: #endif */ int canna_fenceactive(sp) SCR *sp; { return cannastate.fencelen; } /* * PUBLIC: #ifdef CANNA * PUBLIC: void canna_on __P((SCR *)); * PUBLIC: #endif */ void canna_on(sp) SCR *sp; { if (cannastate.keepmode) canna_setmode(sp, 1, 0); } /* * PUBLIC: #ifdef CANNA * PUBLIC: void canna_off __P((SCR *)); * PUBLIC: #endif */ void canna_off(sp) SCR *sp; { cannastate.keepmode = cannastate.mode; canna_setmode(sp, 0, 0); } /* * PUBLIC: #ifdef CANNA * PUBLIC: void canna_force_on __P((SCR *)); * PUBLIC: #endif */ void canna_force_on(sp) SCR *sp; { canna_setmode(sp, 1, 0); } /* * PUBLIC: #ifdef CANNA * PUBLIC: void canna_force_off __P((SCR *)); * PUBLIC: #endif */ void canna_force_off(sp) SCR *sp; { canna_setmode(sp, 0, 1); } /*------------------------------------------------------------*/ /* * PUBLIC: #ifdef CANNA * PUBLIC: int canna_init __P((SCR *)); * PUBLIC: #endif */ int canna_init(sp) SCR *sp; { int r; /* * Attempt to connect to canna server. */ r = jrKanjiControl(0, KC_INITIALIZE, (char *)0); if (r != 0) return 1; /* * disallow JIS x0201-right. */ jrKanjiControl(0, KC_INHIBITHANKAKUKANA, (char *)1); /* * Register my name to canna server. */ { char myname[30]; (void)snprintf(myname, sizeof(myname), "nvi (pid=%lu)\n", (u_long)getpid()); jrKanjiControl(0, KC_SETAPPNAME, myname); } /* * modeline set-up. */ cannastate.modelinemax = (size_t)jrKanjiControl(0, KC_QUERYMAXMODESTR, (char *)0); if (cannastate.modeline) { REALLOC(sp, cannastate.modeline, u_char *, cannastate.modelinemax); } else { MALLOC_RET(sp, cannastate.modeline, u_char *, cannastate.modelinemax); } cannastate.modeline[cannastate.modelinelen = 0] = '\0'; /* * guideline setup */ cannastate.guidelinemax = GUIDELINEMAX; if (!cannastate.guideline) { MALLOC_RET(sp, cannastate.guideline, u_char *, cannastate.guidelinemax); } cannastate.guideline[cannastate.guidelinelen = 0] = '\0'; cannastate.guidelinerevstart = 0; cannastate.guidelinerevlen = 0; cannastate.guidelinewidth = 0; jrKanjiControl(0, KC_SETWIDTH, (char *)cannastate.guidelinewidth); /* * bind beep function */ { extern void (*jrBeepFunc)(); jrBeepFunc = canna_beep; jrKanjiControl(0, KC_SETUNDEFKEYFUNCTION, kc_normal); } /* * initial mode setup */ cannastate.mode = cannastate.keepmode = 0; /* * initial server setup */ canna_setserver(sp, O_STR(sp, O_CANNASERVER)); cannastate.init = 1; return 0; } /* * PUBLIC: #ifdef CANNA * PUBLIC: int canna_end __P((SCR *)); * PUBLIC: #endif */ int canna_end(sp) SCR *sp; { int r; /* * unbind beep function */ { extern void (*jrBeepFunc)(); jrBeepFunc = NULL; } /* * Attempt to disconnect from canna server. */ r = jrKanjiControl(0, KC_FINALIZE, (char *)0); if (r != 0) return 1; /* * finalize modeline. */ if (cannastate.modeline) free(cannastate.modeline); cannastate.modeline = NULL; cannastate.modelinelen = 0; /* * finalize guideline. */ if (cannastate.guideline) free(cannastate.guideline); cannastate.guideline = NULL; cannastate.guidelinelen = 0; cannastate.guidelinewidth = 0; /* * mode finalize, for safety. */ cannastate.mode = cannastate.keepmode = 0; cannastate.init = 0; return 0; } /* * PUBLIC: #ifdef CANNA * PUBLIC: void canna_setserver __P((SCR *, char *)); * PUBLIC: #endif */ void canna_setserver(sp, name) SCR *sp; char *name; { jrKanjiControl(0, KC_DISCONNECTSERVER, (char *)0); jrKanjiControl(0, KC_SETSERVERNAME, name); } /* * PUBLIC: #ifdef CANNA * PUBLIC: int canna_modelinesw __P((SCR *, int)); * PUBLIC: #endif */ int canna_modelinesw(sp, x) SCR *sp; int x; { cannastate.modelinesw = x; } /* * Will be called from vs_modeline(). * * PUBLIC: #ifdef CANNA * PUBLIC: int canna_modeline __P((SCR *)); * PUBLIC: #endif */ int canna_modeline(sp) SCR *sp; { GS *gp; int x, y; int maxch; if (!cannastate.mode) return 0; if (! (cannastate.modelinelen || cannastate.guidelinelen)) return 0; gp = sp->gp; if (cannastate.fenceloc == FENCE_MODELINE) { size_t fenceend; (void)gp->scr_move(sp, LASTLINE(sp), 0); if (cannastate.modelinelen && cannastate.modelinelen < sp->cols) { canna_puteucjpstr(sp, cannastate.modeline, cannastate.modelinelen, 0); } fenceend = cannastate.modelinemax + cannastate.fencelen; if (fenceend < sp->cols) { (void)gp->scr_move(sp, LASTLINE(sp), fenceend); (void)gp->scr_clrtoeol(sp); } return sp->cols; } (void)gp->scr_move(sp, LASTLINE(sp), 0); #if 0 (void)gp->scr_clrtoeol(sp); #endif maxch = 0; if (cannastate.modelinelen && cannastate.modelinelen < sp->cols) { canna_puteucjpstr(sp, cannastate.modeline, cannastate.modelinelen, 0); maxch = cannastate.modelinemax; } if (cannastate.guidelinelen && cannastate.modelinemax + cannastate.guidelinelen < sp->cols) { (void)gp->scr_move(sp, LASTLINE(sp), cannastate.modelinemax); canna_puteucjpstr3(sp, cannastate.guideline, cannastate.guidelinelen, cannastate.guidelinerevstart, cannastate.guidelinerevlen, 0); maxch = cannastate.modelinemax + cannastate.guidelinelen; } return maxch; } /*------------------------------------------------------------*/ static void canna_beep() { cannastate.errorbell = 1; } static void canna_setmode(sp, mode, drop) SCR *sp; int mode; int drop; { VI_PRIVATE *vip; vip = VIP(sp); if (mode) { if (cannastate.mode) return; /* switch canna mode */ cannastate.ksv.ks = &cannastate.ks; cannastate.ksv.buffer = cannastate.inbuf; cannastate.ksv.bytes_buffer = sizeof(cannastate.inbuf); cannastate.ksv.val = CANNA_MODE_HenkanMode; jrKanjiControl(0, KC_CHANGEMODE, (char *)&cannastate.ksv); cannastate.outhead = cannastate.outtail = 0; /* obtain modeline */ jrKanjiControl(0, KC_QUERYMODE, (char *)cannastate.modeline); cannastate.modelinelen = strlen(cannastate.modeline); /* initialize fence */ cannastate.fencelen = cannastate.fencelenmax = 0; cannastate.oldfencefrow = cannastate.oldfencetrow = 0; cannastate.oldfencex = cannastate.oldfencey = 999999; /*XXX*/ cannastate.fenceloc = FENCE_CURSOR; } else { if (!cannastate.mode) return; /* obtain kakutei string */ cannastate.ksv.ks = &cannastate.ks; cannastate.ksv.buffer = cannastate.inbuf; cannastate.ksv.bytes_buffer = sizeof(cannastate.inbuf); jrKanjiControl(0, KC_KAKUTEI, (char *)&cannastate.ksv); if (!drop && 0 < cannastate.ksv.val) { size_t i; size_t ilen; ilen = cannastate.ksv.val; for (i = 0; i < ilen; i++) { if (i + 1 < ilen && iseuckanji(cannastate.inbuf[i])) { C_OUTPUT(CS_JISX0208_1983); C_OUTPUT(cannastate.inbuf[i+0] & 0x7f); C_OUTPUT(cannastate.inbuf[i+1] & 0x7f); i++; } else if (i + 1 < ilen && cannastate.inbuf[i] == SS2) { C_OUTPUT(CS_JISX0201_RIGHT); C_OUTPUT(cannastate.inbuf[i+1] & 0x7f); i++; } else if (i + 2 < ilen && cannastate.inbuf[i] == SS3) { C_OUTPUT(CS_JISX0212_1990); C_OUTPUT(cannastate.inbuf[i+1] & 0x7f); C_OUTPUT(cannastate.inbuf[i+2] & 0x7f); i += 2; } else if (cannastate.inbuf[i] & 0x80) { C_OUTPUT(CS_RAW0 + v_key_len(sp, cannastate.inbuf[i])); C_OUTPUT(cannastate.inbuf[i] & 0x7f); } else { C_OUTPUT(cannastate.inbuf[i]); } } } } cannastate.mode = mode; if (F_ISSET(sp, SC_SCR_VI) && !IS_ONELINE(sp) && !F_ISSET(vip, VIP_S_MODELINE) && !F_ISSET(sp, SC_TINPUT_INFO)) { if (cannastate.modelinesw) { /* update modeline */ canna_updatemodeline(sp); (void)sp->gp->scr_refresh(sp, 0); } } } static void canna_updatemodeline(sp) SCR *sp; { GS *gp; size_t x, y; gp = sp->gp; (void)gp->scr_cursor(sp, &y, &x); vs_modeline(sp); (void)gp->scr_move(sp, y, x); } /* * XXX The code assumes that canna returns fence in euc-jp. */ static void canna_echoback(sp) SCR *sp; { GS *gp; VI_PRIVATE *vip; gp = sp->gp; vip = VIP(sp); /* repaint the fence. */ { size_t ofencelen; size_t nfencelen; ofencelen = cannastate.fencelen; if (cannastate.ks.length < 0) goto nofencechange; else if (0 < cannastate.ks.length) { /* plus two for surrounding chars (pipe mark) */ nfencelen = cannastate.ks.length + 2; } else nfencelen = 0; if (F_ISSET(sp, SC_SCR_VI)) { /* vi mode, on screen/status line. */ size_t x, y; size_t nx, ny; int fenceloc; int fencemove; int fencerepaint; (void)gp->scr_cursor(sp, &y, &x); fencemove = fencerepaint = 0; /* reset */ if (nfencelen == 0) cannastate.fenceloc = FENCE_CURSOR; /* guess the location first. */ switch (cannastate.fenceloc) { case FENCE_CURSOR: fenceloc = FENCE_CURSOR; if (!F_ISSET(sp, SC_TINPUT_INFO) && sp->cols < x + nfencelen) { fenceloc = FENCE_MODELINE; fencemove++; fencerepaint++; } else if (F_ISSET(sp, SC_TINPUT_INFO) && sp->cols < x + nfencelen + (y == LASTLINE(sp) ? 1 : 0)) { fenceloc = FENCE_BOTTOM; fencemove++; fencerepaint++; } break; case FENCE_MODELINE: fenceloc = FENCE_MODELINE; break; case FENCE_BOTTOM: fenceloc = FENCE_BOTTOM; break; } /* * fence repaint checks. * 1. if fence shrinked, repaint is necessery. * 2. if the cursor has moved from the previous position, * repaint is necessery. */ if (nfencelen < ofencelen) fencerepaint++; if (ofencelen && (cannastate.oldfencex != x || cannastate.oldfencey != y)) fencerepaint++; /* * If we are making input on the modeline, and we hit the * last char (fencemove), need to scroll the line to make room. */ if (fencemove && fenceloc == FENCE_BOTTOM && y == LASTLINE(sp)) { TEXT *tp; size_t i; size_t scno; size_t slen; size_t colinc; size_t ocno; tp = sp->tiq.cqh_first; if (tp == (TEXT *)&sp->tiq) abort(); /*XXX*/ /* append fake space chars to make room. */ scno = vs_columns(sp, tp->lb, tp->lno, &tp->cno, NULL); slen = vs_columns(sp, tp->lb, tp->lno, &tp->len, NULL); if (scno / sp->cols != slen / sp->cols) colinc = 1; else { colinc = ((slen / sp->cols) + 1) * sp->cols; colinc -= scno; colinc += 2; /*for safety */ } BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + colinc); if (0) { alloc_err: abort(); } for (i = 0; i < colinc; i++) { tp->lb[tp->len] = ' '; ++tp->len; ++tp->owrite; } /* * move cursor to the end, and refresh the screen once. */ ocno = tp->cno; sp->cno = tp->cno = tp->len - 1; tp->owrite -= (tp->cno - ocno); (void)vs_change(sp, tp->lno, LINE_RESET); (void)vs_refresh(sp, 0); /* backup cursor. */ tp->owrite += (tp->cno - ocno); sp->cno = tp->cno = ocno; (void)vs_refresh(sp, 0); /* forget about fake spacing. */ tp->len -= colinc; tp->owrite -= colinc; /* remember new cursor position. */ (void)gp->scr_cursor(sp, &y, &x); /* repaint was already done. */ fencerepaint = 0; } /* * repaint underlying chars, or clear old fence, if needed. */ if (fencerepaint) { switch (cannastate.fenceloc) { case FENCE_CURSOR: { if (cannastate.fencelenmax) { EVENT ev; ev.e_event = E_REPAINT; ev.e_flno = cannastate.oldfencefrow; ev.e_tlno = cannastate.oldfencetrow; (void)vs_repaint(sp, &ev); cannastate.fencelenmax = 0; } /* remember new cursor position. */ (void)gp->scr_cursor(sp, &y, &x); break; } case FENCE_MODELINE: case FENCE_BOTTOM: (void)gp->scr_move(sp, cannastate.oldfencey, cannastate.oldfencex); (void)gp->scr_clrtoeol(sp); (void)gp->scr_move(sp, y, x); break; } /* repaint was already done. */ fencerepaint = 0; } /* * move cursor to new fence location. */ switch (fenceloc) { case FENCE_CURSOR: nx = x; ny = y; break; case FENCE_MODELINE: ny = LASTLINE(sp); nx = cannastate.modelinemax; (void)gp->scr_move(sp, ny, nx); break; case FENCE_BOTTOM: ny = LASTLINE(sp); nx = 0; (void)gp->scr_move(sp, ny, nx); break; } /* * paint the new fence. */ if (nfencelen) { if (nfencelen) (void)gp->scr_addstr(sp, "|", 1); canna_puteucjpstr3(sp, cannastate.ks.echoStr, cannastate.ks.length, cannastate.ks.revPos, cannastate.ks.revLen, 0); if (nfencelen) { if (cannastate.ks.length == cannastate.ks.revPos) { (void)gp->scr_attr(sp, SA_INVERSE, 1); (void)gp->scr_addstr(sp, "|", 1); (void)gp->scr_attr(sp, SA_INVERSE, 0); } else (void)gp->scr_addstr(sp, "|", 1); } (void)gp->scr_move(sp, y, x); } (void)gp->scr_refresh(sp, 0); /* * try to remember old fence location for redraw. * XXX how should we deal with scrolling? */ cannastate.oldfencefrow = ny + 1; if (sp->rows < cannastate.oldfencefrow) cannastate.oldfencefrow = sp->rows; cannastate.oldfencetrow = ny + 1; cannastate.oldfencetrow += (nx + cannastate.fencelenmax) / sp->cols; if (sp->rows < cannastate.oldfencetrow) cannastate.oldfencetrow = sp->rows; cannastate.oldfencex = nx; cannastate.oldfencey = ny; cannastate.fenceloc = fenceloc; } else { /* ex mode. we can't use curses routines. */ /* XXX some optimization would be nice */ size_t i; /* erase the old fence. */ for (i = 0; i < ofencelen; i++) (void)printf("\b \b"); /* repaint the fence. */ if (nfencelen) { (void)printf("|"); canna_puteucjpstr3(sp, cannastate.ks.echoStr, cannastate.ks.length, cannastate.ks.revPos, cannastate.ks.revLen, 1); (void)printf("|"); } } cannastate.fencelen = nfencelen; if (cannastate.fencelenmax < nfencelen) cannastate.fencelenmax = nfencelen; } nofencechange:; /* modeline */ if (cannastate.ks.info & KanjiModeInfo) { strcpy(cannastate.modeline, cannastate.ks.mode); cannastate.modelinelen = strlen(cannastate.modeline); } /* guideline */ if (cannastate.ks.info & KanjiGLineInfo) { memcpy(cannastate.guideline, cannastate.ks.gline.line, cannastate.ks.gline.length); cannastate.guidelinelen = cannastate.ks.gline.length; cannastate.guidelinerevstart = cannastate.ks.gline.revPos; cannastate.guidelinerevlen = cannastate.ks.gline.revLen; } if (F_ISSET(sp, SC_SCR_VI) && !IS_ONELINE(sp) && !F_ISSET(vip, VIP_S_MODELINE) && !F_ISSET(sp, SC_TINPUT_INFO)) { if (cannastate.modelinesw) { /* update modeline */ canna_updatemodeline(sp); (void)gp->scr_refresh(sp, 0); } } } static void canna_inject(sp, arg) SCR *sp; ARG_CHAR_T arg; { CHAR_T c; int ilen; c = arg; /* set guidelinewidth */ { int nwidth; if (F_ISSET(sp, SC_SCR_VI) && !F_ISSET(sp, SC_TINPUT_INFO)) { nwidth = sp->cols; nwidth -= cannastate.modelinemax; } else nwidth = 0; if (nwidth != cannastate.guidelinewidth) { jrKanjiControl(0, KC_SETWIDTH, (char *)nwidth); cannastate.guidelinewidth = nwidth; } } cannastate.errorbell = 0; ilen = jrKanjiString(0, c, (char *)cannastate.inbuf, sizeof(cannastate.inbuf), &cannastate.ks); if (ilen < 0) { /* XXX bark something */ return; } canna_echoback(sp); if (cannastate.errorbell && F_ISSET(sp, SC_SCR_VI)) (void)sp->gp->scr_bell(sp); if (0 < ilen) { size_t i; for (i = 0; i < ilen; i++) { if (i + 1 < ilen && iseuckanji(cannastate.inbuf[i])) { C_OUTPUT(CS_JISX0208_1983); C_OUTPUT(cannastate.inbuf[i + 0] & 0x7f); C_OUTPUT(cannastate.inbuf[i + 1] & 0x7f); i++; } else if (i + 1 < ilen && cannastate.inbuf[i] == SS2) { C_OUTPUT(CS_JISX0201_RIGHT); C_OUTPUT(cannastate.inbuf[i+1] & 0x7f); i++; } else if (i + 2 < ilen && cannastate.inbuf[i] == SS3) { C_OUTPUT(CS_JISX0212_1990); C_OUTPUT(cannastate.inbuf[i+1] & 0x7f); C_OUTPUT(cannastate.inbuf[i+2] & 0x7f); i += 2; } else if (cannastate.inbuf[i] & 0x80) { C_OUTPUT(CS_RAW0 + v_key_len(sp, cannastate.inbuf[i])); C_OUTPUT(cannastate.inbuf[i] & 0x7f); } else { C_OUTPUT(cannastate.inbuf[i]); } } } } static void canna_puteucjpstr3(sp, p, len, revpos, revlen, mode) SCR *sp; char *p; size_t len; size_t revpos; size_t revlen; int mode; /* 0: vi 1: ex */ { GS *gp; gp = sp->gp; canna_puteucjpstr(sp, p, revpos, mode); (void)gp->scr_attr(sp, SA_INVERSE, 1); canna_puteucjpstr(sp, p + revpos, revlen, mode); (void)gp->scr_attr(sp, SA_INVERSE, 0); canna_puteucjpstr(sp, p + revpos + revlen, len - revpos - revlen, mode); } static void canna_puteucjpstr(sp, p0, len, mode) SCR *sp; char *p0; size_t len; int mode; /* 0: vi 1: ex */ { GS *gp; size_t col; u_char *p; u_char name[4]; gp = sp->gp; p = (u_char *)p0; col = 0; while (col < len) { if (col + 1 < len && iseuckanji(*p)) { name[0] = CS_JISX0208_1983; name[1] = *p++ & 0x7f; name[2] = *p++ & 0x7f; name[3] = '\0'; if (mode) (void)printf("%s", name); else (void)gp->scr_addstr(sp, name, 3); col += 2; } else if (col + 1 < len && *p == SS2) { p++; name[0] = CS_JISX0201_RIGHT; name[1] = *p++ & 0x7f; name[2] = '\0'; if (mode) (void)printf("%s", name); else (void)gp->scr_addstr(sp, name, 2); col += 2; /*XXX*/ } else if (col + 2 < len && *p == SS3) { p++; name[0] = CS_JISX0212_1990; name[1] = *p++ & 0x7f; name[2] = *p++ & 0x7f; name[3] = '\0'; if (mode) (void)printf("%s", name); else (void)gp->scr_addstr(sp, name, 3); col += 3; /*XXX*/ } else if (*p & 0x80) { name[0] = CS_RAW0 + v_key_len(sp, *p); name[1] = *p++ & 0x7f; name[2] = '\0'; if (mode) (void)printf("%s", name); else (void)gp->scr_addstr(sp, name, 2); col++; } else { name[0] = *p++; name[1] = '\0'; if (mode) (void)printf("%s", name); else (void)gp->scr_addstr(sp, name, 1); col++; } } } #endif /*CANNA*/ #endif /*MULTIBYTE*/