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 rcs_id[] = "@(#) 102.1 $Id: keydef.c 14875 2005-11-12 21:25:31Z bonefish $";
29#endif /* lint */
30
31#include "canna.h"
32#include <canna/mfdef.h>
33#include <canna/keydef.h>
34
35extern KanjiModeRec alpha_mode, empty_mode, yomi_mode;
36extern KanjiModeRec jishu_mode, ce_mode, cy_mode, cb_mode;
37extern KanjiModeRec tankouho_mode, ichiran_mode, onoff_mode;
38extern KanjiModeRec khal_mode, khkt_mode, kzal_mode, kzhr_mode, kzkt_mode;
39extern KanjiModeRec kigo_mode;
40extern KanjiModeRec tourokureibun_mode;
41extern KanjiModeRec bunsetsu_mode;
42extern KanjiModeRec cy_mode, cb_mode;
43
44//extern multiSequenceFunc
45//  (struct _uiContext *, struct _kanjiMode *, int, int, int);
46
47#define NONE 0
48#define ACTHASHTABLESIZE 64
49#define KEYHASHTABLESIZE 16
50
51#define SINGLE 0
52#define MULTI  1
53#define OTHER  2
54
55static unsigned char *duplicatekmap(unsigned char *kmap);
56static int changeKeyOnSomeCondition(KanjiMode mode, int key, int fnum, unsigned char *actbuff, unsigned char *keybuff);
57static void undefineKeyfunc(unsigned char *keytbl, unsigned fnum);
58//static unsigned int createHashKey(unsigned char *data1, unsigned char data2, int which_seq);
59static void regist_act_hash(unsigned char *tbl_ptr, unsigned char key, unsigned char *buff);
60static void remove_hash(unsigned char *tbl_ptr, unsigned char key, int which_seq);
61static void freeChain(struct seq_struct *p);
62static void clearAllFuncSequence(void);
63static void freeKeySeqMode(KanjiMode m);
64static void freeMap(struct map *m);
65static void clearAllKeySequence(void);
66static int specialen(unsigned char *block);
67static int to_write_act(int depth, int keysize, int actsize, unsigned singleAct);
68static struct map *regist_map(KanjiMode tbl, unsigned char *keybuff, unsigned char *actbuff, int depth);
69static int regist_key_hash(unsigned char *tbl_ptr, unsigned char *keybuff, unsigned char *actbuff);
70static int copyMultiSequence(unsigned char key, KanjiMode old_tbl, KanjiMode new_tbl);
71static void freeMultiSequence(unsigned char key, KanjiMode tbl);
72
73struct  seq_struct{
74  unsigned char    *to_tbl;
75  unsigned char    as_key;
76  unsigned char    *kinou_seq;
77  struct  seq_struct *next;
78};
79
80static struct seq_struct *seq_hash[ACTHASHTABLESIZE];
81
82struct map{
83  KanjiMode tbl;
84  unsigned char key;
85  KanjiMode  mode;
86  struct map *next;
87};
88
89static struct map *otherMap[KEYHASHTABLESIZE];
90
91static KanjiMode ModeTbl[CANNA_MODE_MAX_REAL_MODE] = {
92  &alpha_mode,        /* AlphaMode          ����������������������������������������         */
93  &empty_mode,	      /* EmptyMode          ������������������������������������           */
94  &kigo_mode,	      /* KigoMode           ����������������������������������������������������   */
95  &yomi_mode,         /* YomiMode           ����������������������������������������         */
96  &jishu_mode,	      /* JishuMode          ��������������������������������������������       */
97  &tankouho_mode,     /* TankouhoMode       �������������������������������������������������������� */
98  &ichiran_mode,      /* IchiranMode        ����������������������������������������������������   */
99  &tourokureibun_mode, /* TourokuReibunMode ��������������������������������������������       */
100  &onoff_mode,        /* OnOffMode          On/Off��������������������������������       */
101  &bunsetsu_mode,     /* AdjustBunsetsuMode ����������������������������               */
102  &cy_mode,	      /* ChikujiYomiMode    ������������������������������������           */
103  &cb_mode,           /* ChikujiHenkanMode  ����������������������������������������         */
104};
105
106
107static unsigned char *
108duplicatekmap(unsigned char *kmap)
109{
110  unsigned char *res;
111  int i;
112
113  res = (unsigned char *)calloc(256, sizeof(unsigned char));
114  if (res) {
115    for (i = 0 ; i < 256 ; i++) {
116      res[i] = kmap[i];
117    }
118  }
119  return res;
120}
121
122static unsigned char *defaultkeytables[CANNA_MODE_MAX_REAL_MODE];
123static unsigned char defaultsharing[CANNA_MODE_MAX_REAL_MODE];
124static unsigned char *defaultmap;
125unsigned char *alphamap, *emptymap;
126
127/* cfuncdef
128
129  initKeyTables() -- ������������������������������������������������������������
130
131  �������������������������������������������������������������������������������������������������������������������� ����������������
132  ������������������������������������������������������������������������
133
134*/
135
136int initKeyTables(void)
137{
138  int i;
139  unsigned char *tbl;
140  extern unsigned char default_kmap[], alpha_kmap[], empty_kmap[];
141
142  defaultmap = duplicatekmap(default_kmap);
143  if (defaultmap) {
144    alphamap   = duplicatekmap(alpha_kmap);
145    if (alphamap) {
146      emptymap   = duplicatekmap(empty_kmap);
147      if (emptymap) {
148        for (i = 0 ; i < CANNA_MODE_MAX_REAL_MODE ; i++) {
149          if (ModeTbl[i]) {
150            defaultsharing[i] = ModeTbl[i]->flags;
151            tbl = defaultkeytables[i] = ModeTbl[i]->keytbl;
152            if (tbl == default_kmap) {
153              ModeTbl[i]->keytbl = defaultmap;
154            }
155            else if (tbl == alpha_kmap) {
156              ModeTbl[i]->keytbl = alphamap;
157            }
158            else if (tbl == empty_kmap) {
159              ModeTbl[i]->keytbl = emptymap;
160            }
161          }
162        }
163        return 0;
164      }
165      free(alphamap);
166    }
167    free(defaultmap);
168  }
169  return NG;
170}
171
172void
173restoreDefaultKeymaps(void)
174{
175  int i;
176
177  for (i = 0 ; i < CANNA_MODE_MAX_REAL_MODE ; i++) {
178    if (ModeTbl[i]) {
179      if ( !(ModeTbl[i]->flags & CANNA_KANJIMODE_TABLE_SHARED) ) {
180	free(ModeTbl[i]->keytbl);
181      }
182      ModeTbl[i]->keytbl = defaultkeytables[i];
183      ModeTbl[i]->flags = defaultsharing[i];
184    }
185  }
186  free(defaultmap);
187  free(alphamap);
188  free(emptymap);
189  clearAllFuncSequence();
190  clearAllKeySequence();
191}
192
193
194/*
195 * ����������������������������������������������������������������������������������������
196 *
197 */
198
199/*
200
201  ��������������������������������������������������������������������������������������������������������
202
203 */
204
205extern int nothermodes;
206
207int changeKeyfunc(int modenum, int key, int fnum, unsigned char *actbuff, unsigned char *keybuff)
208{
209  int i, retval = 0;
210  unsigned char *p, *q;
211  KanjiMode mode;
212  newmode *nmode;
213
214  /* ���������������������������� */
215  if (modenum == CANNA_MODE_HenkanNyuryokuMode) {
216    retval = changeKeyfunc(CANNA_MODE_EmptyMode, key, fnum, actbuff, keybuff);
217    if (retval < 0) {
218      return retval;
219    }
220    modenum = CANNA_MODE_YomiMode;
221  }
222
223  if (modenum < 0) {
224    return 0;
225  }
226  else if (modenum < CANNA_MODE_MAX_REAL_MODE) {
227    mode = ModeTbl[modenum];
228  }
229  else if (modenum < CANNA_MODE_MAX_IMAGINARY_MODE) {
230    return 0;
231  }
232  else if (modenum < CANNA_MODE_MAX_IMAGINARY_MODE + nothermodes) {
233    nmode = findExtraKanjiMode(modenum);
234    if (!nmode) {
235      return 0;
236    }
237    else {
238      mode = nmode->emode;
239    }
240  }
241  else {
242    return 0;
243  }
244
245  if (mode && mode->func((uiContext)0/*dummy*/, mode,
246                           KEY_CHECK, 0/*dummy*/, fnum)) {
247    /* �������������������������������������������������������������������������������������������� */
248    if (mode->keytbl) { /* ������������������������������������������������ */
249      /* �������������������������������������������������������� */
250      if (mode->flags & CANNA_KANJIMODE_TABLE_SHARED) {
251	/* ������������������������������������������������������������������������������������ */
252	p = (unsigned char *)calloc(256, sizeof(unsigned char));
253        if (!p) {
254          return -1;
255        }
256        bcopy(mode->keytbl, p, 256 * sizeof(unsigned char));
257        for (i = 0; i < 256; i++) {
258          if (mode->keytbl[i] == CANNA_FN_FuncSequence) {
259            q = actFromHash(mode->keytbl,i);
260            if (q) { /* ���������������������������������������������������������������� */
261              regist_act_hash(p, i, q);
262            }
263          }
264          if (mode->keytbl[i] == CANNA_FN_UseOtherKeymap) {
265	    debug_message("changeKeyfunc:\245\306\241\274\245\326\245\353"
266		"\260\334\306\260\72\244\263\244\316\244\310\244\255\244\316"
267		"\245\255\241\274\244\317%d\n",i,0,0);
268                          /* ������������������������:�������������������������������� */
269            (void)copyMultiSequence(i, (KanjiMode)mode->keytbl,
270                                       (KanjiMode)p);
271          }
272        }
273        mode->keytbl = p;
274        mode->flags &= ~CANNA_KANJIMODE_TABLE_SHARED;
275        if (modenum == CANNA_MODE_YomiMode &&
276             (ModeTbl[CANNA_MODE_ChikujiYomiMode]->flags
277              & CANNA_KANJIMODE_TABLE_SHARED)) {
278          ModeTbl[CANNA_MODE_ChikujiYomiMode]->keytbl = p;
279        }
280        else if (modenum == CANNA_MODE_TankouhoMode &&
281	          (ModeTbl[CANNA_MODE_ChikujiTanMode]->flags
282                   & CANNA_KANJIMODE_TABLE_SHARED)) {
283	  ModeTbl[CANNA_MODE_ChikujiTanMode]->keytbl = p;
284        }
285      }
286      if (key >= 0 && key < 255) {
287        if (mode->keytbl[key] == CANNA_FN_UseOtherKeymap &&
288             fnum != CANNA_FN_UseOtherKeymap)
289          freeMultiSequence(key,(KanjiMode)mode->keytbl);
290        mode->keytbl[key] = fnum;
291        if (fnum == CANNA_FN_FuncSequence) {
292          regist_act_hash(mode->keytbl,key,actbuff);
293        }
294        if (fnum == CANNA_FN_UseOtherKeymap) {
295          retval = regist_key_hash(mode->keytbl,keybuff,actbuff);
296          if (retval) {
297            return retval;
298          }
299        }
300      }
301      else if (key == CANNA_KEY_Undefine) {
302        undefineKeyfunc(mode->keytbl, fnum);
303      }
304    }
305  }
306  return 0;
307}
308
309static int
310changeKeyOnSomeCondition(KanjiMode mode, int key, int fnum, unsigned char *actbuff, unsigned char *keybuff)
311{
312  int retval = 0;
313
314  if (mode && /* ������������������������������������������������ */
315      mode->func((uiContext)0/*dummy*/, mode,
316                   KEY_CHECK, 0/*dummy*/, fnum)) {
317    /* ���������������������������������������������������� */
318    if ( !(mode->flags & CANNA_KANJIMODE_TABLE_SHARED) ) {
319      /* ������������������������������������������������������������ */
320      if (mode->keytbl) { /* ������������������������������������������������ */
321	if (mode->keytbl[key] == CANNA_FN_UseOtherKeymap &&
322	    fnum != CANNA_FN_UseOtherKeymap)
323	  freeMultiSequence(key,(KanjiMode)mode->keytbl);
324	mode->keytbl[key] = fnum;
325	if (fnum == CANNA_FN_FuncSequence) {
326	  regist_act_hash(mode->keytbl,key,actbuff);
327	}
328	if (fnum == CANNA_FN_UseOtherKeymap) {
329	  retval = regist_key_hash(mode->keytbl,keybuff,actbuff);
330	}
331      }
332    }
333  }
334  return retval;
335}
336
337/*
338 * ��������������������������������������������������������������������������������������������������������
339 *
340 */
341
342int changeKeyfuncOfAll(int key, int fnum, unsigned char *actbuff, unsigned char *keybuff)
343{
344  extern extraFunc *extrafuncp;
345  extraFunc *ep;
346  KanjiMode mode;
347  int i, retval = 0;
348
349  if (key >= 0 && key < 255) {
350    if (defaultmap[key] == CANNA_FN_UseOtherKeymap &&
351	      fnum != CANNA_FN_UseOtherKeymap)
352      freeMultiSequence(key,(KanjiMode)defaultmap);
353    if (alphamap[key] == CANNA_FN_UseOtherKeymap &&
354	      fnum != CANNA_FN_UseOtherKeymap)
355      freeMultiSequence(key,(KanjiMode)alphamap);
356    if (emptymap[key] == CANNA_FN_UseOtherKeymap &&
357	      fnum != CANNA_FN_UseOtherKeymap)
358      freeMultiSequence(key,(KanjiMode)emptymap);
359    defaultmap[key] = fnum;
360    alphamap[key]   = fnum;
361    emptymap[key]   = fnum;
362    if (fnum == CANNA_FN_FuncSequence) {
363      regist_act_hash(defaultmap,key,actbuff);
364      regist_act_hash(alphamap,key,actbuff);
365      regist_act_hash(emptymap,key,actbuff);
366    }
367    if (fnum == CANNA_FN_UseOtherKeymap) {
368      if (regist_key_hash(defaultmap,keybuff,actbuff) == NG ||
369            regist_key_hash(alphamap,keybuff,actbuff) == NG ||
370            regist_key_hash(emptymap,keybuff,actbuff) == NG) {
371        return -1;
372      }
373    }
374    for (i = 0 ; i < CANNA_MODE_MAX_REAL_MODE ; i++) {
375      mode = ModeTbl[i];
376      retval = changeKeyOnSomeCondition(mode, key, fnum, actbuff, keybuff);
377      if (retval < 0) {
378        return retval;
379      }
380    }
381    for (ep = extrafuncp ; ep ; ep = ep->next) {
382      /* defmode �������������������������������������������������������� */
383      if (ep->keyword == EXTRA_FUNC_DEFMODE) {
384	retval = changeKeyOnSomeCondition(ep->u.modeptr->emode, key, fnum,
385                                            actbuff, keybuff);
386        if (retval < 0) {
387          return retval;
388        }
389      }
390    }
391  }
392  else if (key == CANNA_KEY_Undefine) {
393    undefineKeyfunc(defaultmap, (unsigned)fnum);
394    undefineKeyfunc(alphamap, (unsigned)fnum);
395    undefineKeyfunc(emptymap, (unsigned)fnum);
396    for (i = 0 ; i < CANNA_MODE_MAX_REAL_MODE ; i++) {
397      mode = ModeTbl[i];
398      if (mode && /* ������������������������������������������������ */
399	  mode->func((uiContext)0/*dummy*/, mode,
400                       KEY_CHECK, 0/*dummy*/, fnum)) {
401	/* ���������������������������������������������������� */
402	if ( !(mode->flags & CANNA_KANJIMODE_TABLE_SHARED) ) {
403	  /* ������������������������������������������������������������ */
404	  if (mode->keytbl) { /* ������������������������������������������������ */
405	    undefineKeyfunc(mode->keytbl, (unsigned)fnum);
406	  }
407	}
408      }
409    }
410  }
411  return retval;
412}
413
414static void
415undefineKeyfunc(unsigned char *keytbl, unsigned fnum)
416{
417  int i;
418
419  for (i = 0 ; i < ' ' ; i++) {
420    if (keytbl[i] == fnum) {
421      keytbl[i] = CANNA_FN_Undefined;
422    }
423  }
424  for (i = ' ' ; i < 0x7f ; i++) {
425    if (keytbl[i] == fnum) {
426      keytbl[i] = CANNA_FN_FunctionalInsert;
427    }
428  }
429  for (i = 0x7f ; i < 0xa0 ; i++) {
430    if (keytbl[i] == fnum) {
431      keytbl[i] = CANNA_FN_Undefined;
432    }
433  }
434  for (i = 0xa0 ; i < 0xe0 ; i++) {
435    if (keytbl[i] == fnum) {
436      keytbl[i] = CANNA_FN_FunctionalInsert;
437    }
438  }
439  for (i = 0xe0 ; i < 0x100 ; i++) {
440    if (keytbl[i] == fnum) {
441      keytbl[i] = CANNA_FN_Undefined;
442    }
443  }
444}
445
446inline
447unsigned int
448createHashKey(unsigned char *data1, unsigned char data2, unsigned long which_seq)
449{
450  unsigned long hashKey;
451
452  hashKey = (*data1 + data2) % which_seq;
453  return hashKey;
454}
455
456/* ������������������������������������������������ */
457unsigned char *
458actFromHash(unsigned char *tbl_ptr, unsigned char key)
459{
460  unsigned int hashKey;
461  struct seq_struct *p;
462
463  hashKey = createHashKey(tbl_ptr, key, ACTHASHTABLESIZE);
464  for (p = seq_hash[hashKey] ; p ; p = p->next) {
465    if (p->to_tbl == tbl_ptr && p->as_key == key) {
466      return p->kinou_seq;
467    }
468  }
469#ifndef WIN
470  debug_message("actFromHash:����������������������������������������������������������������������������\n",0,0,0);
471#else
472  debug_message("actFromHash:\245\255\241\274\245\267\245\261\245\363\245\271"
473	"\244\362\244\337\244\304\244\261\244\351\244\354\244\336\244\273"
474	"\244\363\244\307\244\267\244\277\241\243\n",0,0,0);
475#endif
476  return (unsigned char *)NULL; /* �������������������������������������������������������������������� */
477}
478
479/* �������������������������������������������� */
480static void
481regist_act_hash(unsigned char *tbl_ptr, unsigned char key, unsigned char *buff)
482{
483  unsigned int hashKey;
484  struct seq_struct *p, **pp;
485
486  hashKey = createHashKey(tbl_ptr, key, ACTHASHTABLESIZE);
487  for (pp = &seq_hash[hashKey] ; (p = *pp) != (struct seq_struct *)0 ;
488       pp = &(p->next)) {
489    if (p->to_tbl == tbl_ptr && p->as_key == key) {
490      if (p->kinou_seq)
491	free(p->kinou_seq);
492      p->kinou_seq = (unsigned char *)malloc(strlen((char *)buff)+1);
493      if (p->kinou_seq)
494	strcpy((char *)p->kinou_seq,(char *)buff);
495      return;
496    }
497  }
498  p = *pp = (struct seq_struct *)malloc(sizeof(struct seq_struct));
499  if(p) {
500    p->to_tbl = tbl_ptr;
501    p->as_key = key;
502    p->kinou_seq = (unsigned char *)malloc(strlen((char *)buff)+1);
503    if(p->kinou_seq)
504      strcpy((char *)p->kinou_seq,(char *)buff);
505    p->next = (struct seq_struct *)NULL;
506  }
507}
508
509/* ������������������������������������������������ */
510static void
511remove_hash(unsigned char *tbl_ptr, unsigned char key, int which_seq)
512{
513  unsigned int hashKey;
514  struct seq_struct *p, **pp;
515
516  hashKey = createHashKey(tbl_ptr, key, which_seq);
517  for (pp = &seq_hash[hashKey] ; (p = *pp) != (struct seq_struct *)0 ;
518       pp = &(p->next)) {
519    if (p->to_tbl == tbl_ptr && p->as_key == key) {
520      *pp = p->next;
521      free(p);
522    }
523  }
524}
525
526static void
527freeChain(struct seq_struct *p)
528{
529  struct seq_struct *nextp;
530
531  while (p) {
532    free(p->kinou_seq);
533    nextp = p->next;
534    free(p);
535    p = nextp;
536  }
537}
538
539static void
540clearAllFuncSequence(void)
541{
542  int i;
543
544  for (i = 0 ; i < ACTHASHTABLESIZE ; i++) {
545    freeChain(seq_hash[i]);
546    seq_hash[i] = 0;
547  }
548}
549
550static void
551freeKeySeqMode(KanjiMode m)
552{
553  if (m) {
554    if (m->keytbl) {
555      free(m->keytbl);
556    }
557    free(m);
558  }
559}
560
561static void
562freeMap(struct map *m)
563{
564  struct map *n;
565
566  while (m) {
567    freeKeySeqMode(m->mode);
568    n = m->next;
569    free(m);
570    m = n;
571  }
572}
573
574static void
575clearAllKeySequence(void)
576{
577  int i;
578
579  for (i = 0 ; i < KEYHASHTABLESIZE ; i++) {
580    freeMap(otherMap[i]);
581    otherMap[i] = 0;
582  }
583}
584
585static
586int specialen(unsigned char *block)
587{
588  int i;
589  for (i = 0 ; block[i] != 255 ;) {
590    i++;
591  }
592  debug_message("specialen:\304\271\244\265\244\317%d\244\311\244\271\241\243\n",i,0,0);
593                /* specialen:������������%d������������ */
594  return i;
595}
596
597static
598int to_write_act(int depth, int keysize, int actsize, unsigned singleAct)
599{
600  if (depth == (keysize -2)) {
601    if (actsize > 1){
602      debug_message("to_write_act:CANNA_FN_FuncSequence\244\307\244\271\241\243\n",0,0,0);
603                                                     /* ������������ */
604      return CANNA_FN_FuncSequence;
605    }
606    if (actsize == 1) {
607      debug_message("to_write_act:singleAct%d\244\307\244\271\241\243\n",singleAct,0,0);
608                                              /* ������������ */
609      return (int)singleAct;
610    }
611    else { /* ������������������������ */
612      return 0;
613    }
614  } else if (depth < (keysize -2)){
615    debug_message("to_write_act:CANNA_FN_UseOtherKeymap\244\307\244\271\241\243\n",0,0,0);
616                                              /* ������������ */
617    return CANNA_FN_UseOtherKeymap;
618  }
619  else { /* ������������������������ */
620    return 0;
621  }
622}
623
624static struct map *
625regist_map(KanjiMode tbl, unsigned char *keybuff, unsigned char *actbuff, int depth)
626{
627  unsigned int hashKey;
628  int sequencelen, keybuffsize, actbuffsize, offs;
629  struct map *p,**pp;
630  unsigned char *q, prevfunc;
631
632  actbuffsize = strlen((char *)actbuff);
633  keybuffsize = specialen(keybuff);
634  hashKey =
635    createHashKey((unsigned char *)tbl, keybuff[depth], KEYHASHTABLESIZE);
636  debug_message("regist_map:hashKey = %d \244\307\244\271\241\243\n",hashKey,0,0);
637                                         /* ������������ */
638  for (pp = &otherMap[hashKey]; (p = *pp) != (struct map *)0 ;
639       pp = &(p->next)) {
640    if (p->key == keybuff[depth] && p->tbl == tbl) {
641      for (q = p->mode->keytbl; *q != 255; q += 2) {
642	if (*q == keybuff[depth+1]) {  /* ������������������������������������������������ */
643	  ++q;
644	  prevfunc = *q; /* �������������������������������������������������������������������� */
645	  *q = to_write_act(depth,keybuffsize,actbuffsize,actbuff[0]);
646	  if(prevfunc == CANNA_FN_UseOtherKeymap &&
647	     *q != CANNA_FN_UseOtherKeymap) {
648            freeMultiSequence(keybuff[depth + 1], p->mode);
649          }
650	  if (*q == CANNA_FN_FuncSequence) {
651	    regist_act_hash((unsigned char *)p->mode, keybuff[depth+1],
652			    actbuff);
653	  }
654	  debug_message("regist_map:\264\373\244\313\306\261\244\270\245\255\241\274\244\254\302\270\272\337:q=%d\n",*q,0,0);
655                        /* ������������������������������������ */
656	  return p;
657	}
658      }
659      /* ��������������������������������������������������������������������������������:keybuff[depth +1]���������������� */
660      sequencelen = specialen(p->mode->keytbl);
661      offs = q - p->mode->keytbl;
662      if (p->mode->keytbl) {
663	p->mode->keytbl =
664	  (unsigned char *)realloc(p->mode->keytbl,sequencelen +3);
665        if (!p->mode->keytbl) {
666          return (struct map *)0;
667        }
668        p->mode->keytbl[sequencelen] = keybuff[depth +1];
669        p->mode->keytbl[++sequencelen] =
670        to_write_act(depth,keybuffsize,actbuffsize,actbuff[0]);
671        p->mode->keytbl[++sequencelen] = (BYTE)-1;
672      }
673      if (p->mode->keytbl[offs] == CANNA_FN_FuncSequence) {
674	regist_act_hash((unsigned char *)p->mode, keybuff[depth+1], actbuff);
675      }
676      debug_message("regist_map:\244\275\244\263\244\336\244\307\244\316"
677	"\241\242\245\255\241\274\244\316\315\372\316\362\244\317\244\242"
678	"\244\303\244\277\244\254\244\263\244\316\245\255\241\274%u\244\317"
679	"\275\351\244\341\244\306\n",
680		    p->mode->keytbl[sequencelen-3],0,0);
681                /* ��������������������������������������������������������������������������������%u���������������� */
682      debug_message("regist_map:sequencelen����%d������������\n",sequencelen,0,0);
683      return p;
684    }
685  }
686  /* ���������������������������������������������������������������������������� */
687  p = *pp = (struct map *)malloc(sizeof(struct map));
688  if (p) {
689    p->tbl = tbl;
690    p->key = keybuff[depth];
691    p->mode = (KanjiMode)malloc(sizeof(KanjiModeRec));
692    if (p->mode) {
693      p->mode->func = multiSequenceFunc;
694      p->mode->flags = 0;
695      p->mode->keytbl = (unsigned char *)malloc(3);
696      if (p->mode->keytbl) {
697	p->mode->keytbl[0] = keybuff[depth +1];
698	p->mode->keytbl[1] = to_write_act(depth,keybuffsize,actbuffsize,actbuff[0]);
699	debug_message("regist_map:p->mode->keytbl[1]\244\317%d\244\307\244\271\241\243\n",p->mode->keytbl[1],0,0);
700                                                  /* ����%d������������ */
701	p->mode->keytbl[2] = (BYTE)-1;
702
703        p->next = (struct map *)NULL;
704        if (p->mode->keytbl[1] == CANNA_FN_FuncSequence) {
705          regist_act_hash((unsigned char *)p->mode, keybuff[depth+1], actbuff);
706        }
707        return p;
708      }
709      free(p->mode);
710    }
711    free(p);
712  }
713  return (struct map *)0;
714}
715
716struct map *
717mapFromHash(KanjiMode tbl, unsigned char key, struct map ***ppp)
718{
719  unsigned int hashKey;
720  struct map *p, **pp;
721
722  hashKey = createHashKey((unsigned char *)tbl, key, KEYHASHTABLESIZE);
723  debug_message("mapFromHash:hashKey����%d\n",hashKey,0,0);
724  for(pp = otherMap + hashKey ; (p = *pp) != (struct map *)0 ;
725      pp = &(p->next)) {
726    if (p->tbl == tbl && p->key == key) {
727      debug_message("mapFromHash:map\244\254\244\337\244\304\244\253\244\352"
728	"\244\336\244\267\244\277\241\243\n",0,0,0);
729                            /* ������������������������������������ */
730      if (ppp) {
731	*ppp = pp;
732      }
733      return p;
734    }
735  }
736#ifndef WIN
737  debug_message("mapFromHash:map������������������������������������\n",0,0,0);
738#else
739  debug_message("mapFromHash:map\244\254\244\337\244\304\244\253\244\352"
740	"\244\336\244\273\244\363\241\243\n",0,0,0);
741#endif
742  return (struct map *)NULL;
743}
744
745static int
746regist_key_hash(unsigned char *tbl_ptr, unsigned char *keybuff, unsigned char *actbuff)
747{
748  struct map *map_ptr;
749  int keybuffsize, i;
750
751  keybuffsize = specialen(keybuff);
752  map_ptr = regist_map((KanjiMode)tbl_ptr, keybuff, actbuff, 0);
753  if (!map_ptr) {
754    return NG;
755  }
756  for (i = 1; i <= (keybuffsize -2); i++) {
757    map_ptr = regist_map(map_ptr->mode, keybuff, actbuff, i);
758    if (!map_ptr) {
759      return NG;
760    }
761  }
762  debug_message("regist_key_hash:keybuffsize\244\317%d����actbuffsize"
763	"\244\317����%d����i\244\317%d\244\307\244\271\241\243\n",
764		keybuffsize,strlen(actbuff),i);
765                                     /* ���� */ /* ���� */ /* ���� */ /* ������������ */
766  return 0;
767}
768
769static
770int
771copyMultiSequence(unsigned char key, KanjiMode old_tbl, KanjiMode new_tbl)
772{
773  unsigned char hashKey;
774  unsigned char *old_sequence, *new_sequence;
775  int i, sequencelen;
776  struct map *p, **pp;
777  struct map *old_map;
778
779  old_map = mapFromHash(old_tbl, key, (struct map ***)0);
780  old_sequence = old_map->mode->keytbl;
781  sequencelen = specialen(old_sequence);
782  hashKey = createHashKey((unsigned char *)new_tbl, key, KEYHASHTABLESIZE);
783  for (pp = &otherMap[hashKey]; (p = *pp) != (struct map *)0 ;
784       pp = &(p->next)) {
785    if (p->key == key && p->tbl == new_tbl) {
786      return 0;
787    }
788  }
789  p = *pp = (struct map *)malloc(sizeof(struct map));
790  if (p) {
791    p->tbl = new_tbl;
792    p->key = key;
793    p->mode = (KanjiMode)malloc(sizeof(KanjiModeRec));
794    if (p->mode) {
795      p->mode->func = multiSequenceFunc;
796      p->mode->flags = 0;
797      p->next = (struct map *)NULL;
798      p->mode->keytbl = (unsigned char *)malloc(sequencelen+1);
799      if (p->mode->keytbl) {
800	for (i = 0, new_sequence = p->mode->keytbl; i <= sequencelen; i++) {
801	  new_sequence[i] = old_sequence[i];
802	  if (i%2 == 1) {
803	    if (old_sequence[i] == CANNA_FN_UseOtherKeymap) {
804	      if (copyMultiSequence(old_sequence[i-1],
805				    old_map->mode, p->mode) < 0) {
806		free(p->mode->keytbl);
807		free(p->mode);
808		free(p);
809		*pp = (struct map *)0;
810		return(-1);
811	      }
812	    } else if (old_sequence[i] == CANNA_FN_FuncSequence)
813	      regist_act_hash((unsigned char *)p->mode, old_sequence[i-1],
814			      actFromHash((unsigned char *)old_map->mode,
815					  old_sequence[i-1]));
816	  }
817	}
818	return 0;
819      } else {
820	free(p->mode);
821	free(p);
822	*pp = (struct map *)0;
823	return(-1);
824      }
825    } else {
826      free(p);
827      *pp = (struct map *)0;
828      return(-1);
829    }
830  } else
831    return(-1);
832}
833
834static void
835freeMultiSequence(unsigned char key, KanjiMode tbl)
836{
837  unsigned char *sequence;
838  int i, sequencelen;
839  struct map *map, **ptr;
840
841  map = mapFromHash(tbl, key, &ptr);
842  if (!map)
843    return;
844  *ptr = map->next;
845  sequence = map->mode->keytbl;
846  sequencelen = specialen(sequence);
847
848  for (i = 0; i <= sequencelen; i++) {
849    if (i%2 == 1) {
850      if (sequence[i] == CANNA_FN_UseOtherKeymap)
851	freeMultiSequence(sequence[i-1], map->mode);
852      if (sequence[i] == CANNA_FN_FuncSequence)
853	remove_hash((unsigned char *)map->mode, sequence[i-1],
854		    ACTHASHTABLESIZE);
855    }
856  }
857  debug_message("\241\374\153\145\171\133\45\144\135\244\316\155\141\160\260"
858	"\312\262\274\244\362\245\325\245\352\241\274\244\267\244\306\244\244"
859	"\244\353\244\276\n",key,0,0);
860    /* ����key[%d]����map�������������������������������������������� */
861  if (map->mode && sequence)
862    free(sequence);
863  if (map->mode)
864    free(map->mode);
865  free(map);
866}
867
868int askQuitKey(unsigned key)
869{
870  if (defaultmap[key] == CANNA_FN_Quit) {
871    return 1; /* ��������������������key����quit���������������� */
872  }
873  return 0; /* ��������������������key����quit������������������������ */
874}
875