1/* Copyright 1992 NEC Corporation, Tokyo, Japan.
2 *
3 * Permission to use, copy, modify, distribute and sell this software
4 * and its documentation for any purpose is hereby granted without
5 * fee, provided that the above copyright notice appear in all copies
6 * and that both that copyright notice and this permission notice
7 * appear in supporting documentation, and that the name of NEC
8 * Corporation not be used in advertising or publicity pertaining to
9 * distribution of the software without specific, written prior
10 * permission.  NEC Corporation makes no representations about the
11 * suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
16 * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19 * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23/************************************************************************/
24/* THIS SOURCE CODE IS MODIFIED FOR TKO BY T.MURAI 1997
25/************************************************************************/
26
27#if !defined(lint) && !defined(__CODECENTER__)
28static char m_s_map_id[] = "@(#) 102.1 $Id: multi.c 14875 2005-11-12 21:25:31Z bonefish $";
29#endif /* lint */
30
31#include "canna.h"
32#include <canna/mfdef.h>
33
34#define NONE CANNA_FN_Undefined
35
36static unsigned char *showChar(int c);
37static int _DoFuncSequence(uiContext d, BYTE *keytbl, BYTE key);
38
39extern int askQuitKey();
40extern int checkGLineLen();
41extern int NothingChangedWithBeep();
42
43static unsigned char *keyHistory;
44
45struct map {
46  KanjiMode tbl;
47  unsigned char key;
48  KanjiMode mode;
49  struct map *next;
50};
51
52extern struct map *mapFromHash();
53
54static unsigned char *
55showChar(int c)
56{
57  static unsigned char Gkey[9];
58  static char *keyCharMap[] = {
59    "space",    "DEL",      "Nfer",     "Xfer",     "Up",
60    "Left",     "Right",    "Down",     "Insert",   "Rollup",
61    "Rolldown", "Home",     "HELP",     "KeyPad",   "S-nfer",
62    "S-xfer",   "S-up",     "S-left",   "S-right",  "S-down",
63    "C-nfer",   "C-xfer",   "C-up",     "C-left",   "C-right",
64    "C-down",   "F1",       "F2",       "F3",       "F4",
65    "F5",       "F6",       "F7",       "F8",       "F9",
66    "F10",      "PF1",      "PF2",      "PF3",      "PF4",
67    "PF5",      "PF6",      "PF7",      "PF8",      "PF9",
68    "PF10",
69  };
70
71  if (c < 0x20) {
72    strcpy((char *)Gkey, "C-");
73    if (c == 0x00 || (c > 0x1a && c < 0x20 ))
74      Gkey[2] = c + 0x40;
75    else
76      Gkey[2] = c + 0x60;
77    Gkey[3] = '\0';
78  }
79  else if (c > ' ' && c <= '~' ) {
80    Gkey[0] = c;
81    Gkey[1] = '\0';
82  }
83  else if (c > 0xa0 && c < 0xdf) {
84    Gkey[0] = 0x8e;
85    Gkey[1] = c;
86    Gkey[2] = '\0';
87  }
88  else if (c == 0x20)
89    strcpy((char *)Gkey, keyCharMap[0]);
90  else if (c > 0x7e && c < 0x8c)
91    strcpy((char *)Gkey, keyCharMap[c -0x7f +1]);
92  else if (c > 0x8f && c < 0x9c)
93    strcpy((char *)Gkey, keyCharMap[c -0x90 +14]);
94  else if (c > 0xdf && c < 0xea)
95    strcpy((char *)Gkey, keyCharMap[c -0xe0 +26]);
96  else if (c > 0xef && c < 0xfa)
97    strcpy((char *)Gkey, keyCharMap[c -0xf0 +36]);
98  else
99    return 0;
100  return Gkey;
101}
102
103int UseOtherKeymap(uiContext d)
104{
105  struct map *p;
106  unsigned char showKey[10];
107
108  strcpy((char *)showKey, (char *)showChar(d->ch));
109  p = mapFromHash((KanjiMode)d->current_mode->keytbl,
110		  d->ch, (struct map ***)0);
111  if (p == (struct map *)NULL)
112    return NothingChangedWithBeep(d);
113  p->mode->ftbl = (struct funccfunc *)d->current_mode;
114  keyHistory = (unsigned char *)malloc(strlen((char *)showKey) + 1);
115  if (keyHistory) {
116    strcpy((char *)keyHistory,(char *)showKey);
117    makeGLineMessageFromString(d, (char *)keyHistory);
118    if (p->mode->keytbl == (BYTE *)NULL) {
119      free(keyHistory);
120      return NothingChangedWithBeep(d);
121    }
122    d->current_mode = p->mode;
123  }
124  return NothingForGLine(d);
125}
126
127static
128int _DoFuncSequence(uiContext d, BYTE *keytbl, BYTE key)
129{
130  int res, total_res, ginfo = 0;
131  int prevEchoLen = -1, prevRevPos, prevRevLen;
132  int prevGEchoLen, prevGRevPos, prevGRevLen;
133  WCHAR_T *prevEcho, *prevGEcho;
134  BYTE *p;
135  WCHAR_T *malloc_echo = (WCHAR_T *)0, *malloc_gline = (WCHAR_T *)0;
136
137  if (key == 0) {
138    key = (BYTE)d->ch;
139  }
140  if (keytbl == (BYTE *)NULL)
141    keytbl = d->current_mode->keytbl;
142
143  p = actFromHash(keytbl, key);
144
145  if (p == (BYTE *)NULL) {
146    return 0;
147  }
148
149  total_res = 0;
150  for(; *p ; p++) {
151    /* £²²óÌܰʹߤ˰ʲ¼¤Î¥Ç¡¼¥¿¤¬¼º¤ï¤ì¤Æ¤¤¤ë¾ì¹ç¤¬¤¢¤ë¤Î¤ÇÆþ¤ìľ¤¹¡£ */
152    d->ch = (unsigned)(*(d->buffer_return) = (WCHAR_T)key);
153    d->nbytes = 1;
154    res = _doFunc(d, (int)*p); /* À¸¤Î doFunc ¤ò¸Æ¤Ö¡£ */
155
156    if (d->kanji_status_return->length >= 0) {
157      prevEcho    = d->kanji_status_return->echoStr;
158      prevEchoLen = d->kanji_status_return->length;
159      prevRevPos  = d->kanji_status_return->revPos;
160      prevRevLen  = d->kanji_status_return->revLen;
161      if (d->genbuf <= prevEcho && prevEcho < d->genbuf + ROMEBUFSIZE) {
162	/* ¥Ç¡¼¥¿¤Ï d->genbuf ¤Ë¤¢¤ë¤Í */
163	if (!malloc_echo &&
164	    !(malloc_echo =
165	      (WCHAR_T *)malloc(ROMEBUFSIZE * sizeof(WCHAR_T)))) {
166	  res = -1; /* ¥¨¥é¡¼¤¬¤â¤È¤â¤ÈÊ֤äÆÍ褿¤È¤¤¤¦¤³¤È¤Ë¤¹¤ë */
167	}
168	else {
169	  prevEcho = malloc_echo;
170	  WStrncpy(prevEcho, d->kanji_status_return->echoStr, prevEchoLen);
171	  prevEcho[prevEchoLen] = (WCHAR_T)0;
172	  d->kanji_status_return->echoStr = prevEcho;
173	}
174      }
175    }
176    if (d->kanji_status_return->info & KanjiGLineInfo) {
177      ginfo = 1;
178      prevGEcho    = d->kanji_status_return->gline.line;
179      prevGEchoLen = d->kanji_status_return->gline.length;
180      prevGRevPos  = d->kanji_status_return->gline.revPos;
181      prevGRevLen  = d->kanji_status_return->gline.revLen;
182      if (d->genbuf <= prevGEcho && prevGEcho < d->genbuf + ROMEBUFSIZE) {
183	/* ¥Ç¡¼¥¿¤Ï d->genbuf ¤Ë¤¢¤ë¤Í */
184	if (!malloc_gline &&
185	    !(malloc_gline =
186	      (WCHAR_T *)malloc(ROMEBUFSIZE * sizeof(WCHAR_T)))) {
187	  res = -1; /* ¥¨¥é¡¼¤¬¤â¤È¤â¤ÈÊ֤äÆÍ褿¤È¤¤¤¦¤³¤È¤Ë¤¹¤ë */
188	}
189	else {
190	  prevGEcho = malloc_gline;
191	  WStrncpy(prevGEcho, d->kanji_status_return->gline.line,
192		   prevGEchoLen);
193	  prevGEcho[prevGEchoLen] = (WCHAR_T)0;
194	  d->kanji_status_return->gline.line = prevGEcho;
195	  d->kanji_status_return->info &= ~KanjiGLineInfo;
196	}
197      }
198    }
199    if (res < 0) {
200      break;
201    }
202    if (res > 0) {
203      total_res += res;
204      d->buffer_return += res;
205      d->n_buffer -= res;
206    }
207  }
208  total_res = _afterDoFunc(d, total_res);
209  d->flags |= MULTI_SEQUENCE_EXECUTED;
210  if (malloc_echo) {
211    WStrncpy(d->genbuf, prevEcho, prevEchoLen);
212    d->genbuf[prevEchoLen] = (WCHAR_T)0;
213    free(malloc_echo); /* ¿ʬ malloc_echo ¤¬ prevEcho ¤«¤â */
214    prevEcho = d->genbuf;
215  }
216  d->kanji_status_return->echoStr = prevEcho;
217  d->kanji_status_return->length  = prevEchoLen;
218  d->kanji_status_return->revPos  = prevRevPos;
219  d->kanji_status_return->revLen  = prevRevLen;
220  if (ginfo) {
221    if (malloc_gline) {
222      WStrncpy(d->genbuf, prevGEcho, prevGEchoLen);
223      d->genbuf[prevGEchoLen] = (WCHAR_T)0;
224      free(malloc_gline); /* ¿ʬ malloc_gline ¤¬ prevGEcho ¤«¤â */
225      prevGEcho = d->genbuf;
226    }
227    d->kanji_status_return->gline.line    = prevGEcho;
228    d->kanji_status_return->gline.length  = prevGEchoLen;
229    d->kanji_status_return->gline.revPos  = prevGRevPos;
230    d->kanji_status_return->gline.revLen  = prevGRevLen;
231    d->kanji_status_return->info |= KanjiGLineInfo;
232  }
233  return total_res;
234}
235
236int DoFuncSequence(uiContext d)
237{
238  return _DoFuncSequence(d, (BYTE *)NULL, (BYTE)NULL);
239}
240
241int
242multiSequenceFunc(uiContext d, KanjiMode mode, int whattodo, int key, int fnum)
243{
244  int i;
245  unsigned char *p;
246  struct map *m;
247
248  if (whattodo != KEY_CALL)
249    return 0;
250
251  if (fnum == CANNA_FN_Kakutei || fnum == CANNA_FN_Quit || askQuitKey(key)) {
252    /* Kakutei ¤Ï KC_KAKUTEI ¤Ø¤ÎÂбþ */
253    free(keyHistory);
254    GlineClear(d);
255    d->current_mode = (KanjiMode)(mode->ftbl);
256    if (d->current_mode->flags & CANNA_KANJIMODE_EMPTY_MODE) {
257      d->kanji_status_return->info |= KanjiEmptyInfo;
258    }
259    /* Nop ¤ò¹Ô¤¦ */
260    (void)doFunc(d, CANNA_FN_Nop);
261    d->flags |= MULTI_SEQUENCE_EXECUTED;
262    return 0;
263  }
264  for (i= 0, p = mode->keytbl; *p != 255; p += 2,i+=2) {
265    debug_message("multiSequenceFunc:\263\254\301\330[%d]\n",i,0,0);
266                                   /* ³¬ÁØ */
267    if (*p == key) { /* ¤³¤Î¥­¡¼¤ÏÅÐÏ¿¤µ¤ì¤Æ¤¤¤¿¡£ */
268      keyHistory =
269	(unsigned char *)realloc(keyHistory, strlen((char *)keyHistory) + strlen((char *)showChar(key)) +2);
270      if (keyHistory) {
271	strcat((char *)keyHistory," ");
272	strcat((char *)keyHistory,(char *)showChar(key));
273
274        makeGLineMessageFromString(d, (char *)keyHistory);
275        if (*++p == CANNA_FN_UseOtherKeymap) { /* ¤Þ¤À¥­¡¼¥·¥±¥ó¥¹¤Î³¤­¤¬Â¸ºß */
276          m = mapFromHash(mode, key, (struct map ***)0);
277          m->mode->ftbl = mode->ftbl;
278          d->current_mode = m->mode;
279          return NothingForGLine(d);
280        }
281        free(keyHistory);
282      }
283      GlineClear(d);
284      d->current_mode = (KanjiMode)(mode->ftbl); /* µ¡Ç½¤ò¼Â¹Ô */
285      if (*p == CANNA_FN_FuncSequence) {
286	return _DoFuncSequence(d, (unsigned char *)mode, key);
287      }
288      return (*d->current_mode->func)(d, d->current_mode, KEY_CALL, 0, *p);
289    }
290  }
291  return NothingForGLineWithBeep(d);  /* ÅÐÏ¿¤·¤Æ¤¤¤Ê¤¤¥­¡¼¤ò²¡¤·¤¿ */
292}
293