Back to index

im-sdk  12.3.91
codetable.c
Go to the documentation of this file.
00001 /*
00002   Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004   Permission is hereby granted, free of charge, to any person obtaining a
00005   copy of this software and associated documentation files (the
00006   "Software"), to deal in the Software without restriction, including
00007   without limitation the rights to use, copy, modify, merge, publish,
00008   distribute, sublicense, and/or sell copies of the Software, and to
00009   permit persons to whom the Software is furnished to do so, subject to
00010   the following conditions: The above copyright notice and this
00011   permission notice shall be included in all copies or substantial
00012   portions of the Software.
00013 
00014 
00015   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018   IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019   FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020   CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021   THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022   ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025   Except as contained in this notice, the names of The Open Group and/or
00026   Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027   promote the sale, use or other dealings in this Software without prior
00028   written authorization from The Open Group and/or Sun Microsystems,
00029   Inc., as applicable.
00030 
00031 
00032   X Window System is a trademark of The Open Group
00033 
00034   OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035   logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036   Group. All other trademarks and registered trademarks mentioned herein
00037   are the property of their respective owners. No right, title or
00038   interest in or to any trademark, service mark, logo or trade name of
00039   Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <locale.h>
00045 #include <string.h>
00046 #include <alloca.h>
00047 
00048 #include "encode.h"
00049 #include "codetable.h"
00050 #include "logf.h"
00051 
00052 #define WILD_MATCH          0      /* exact match */
00053 #define WILD_PREFIX         1      /* no match, but maybe if go deeper */
00054 #define WILD_UNMATCH        2      /* complete mismatch */
00055 
00056 #define SC_FAIL                    0
00057 #define SC_OK               1
00058 
00059 #define WILDCHAR_MATCHSINGLE       '?'
00060 #define WILDCHAR_MATCHANY   '*'
00061 
00062 #define       MAX_CANDIDATES_NUM   16
00063 #define MAX_CANDIDATE_CHAR_NUM     64
00064 #define MAX_INPUT_KEY_NUM   32
00065 
00066 /* CodeTable Search Context */
00067 typedef struct _HZSearchContext {
00068 
00069   int depth;                              /* the current depth in the DFS traversal */
00070 
00071   char prefix[MAX_INPUT_KEY_NUM+1];              /* the prefix traced codes */
00072   char wildpattern[MAX_INPUT_KEY_NUM+1];         /* the wildchar pattern codes */
00073   int kc_repcode;
00074   int mo_repcode;
00075   tableNode *tNstack[MAX_INPUT_KEY_NUM+1];       /* the tableNode stack */
00076   short int tNnumSb[MAX_INPUT_KEY_NUM+1];        /* number of sibling tableNode */
00077 
00078 } HZSearchContext;
00079 
00080 /*********************** Load Codetable File ***********************/
00081 
00082 /*
00083  * LoadCodeTableHeader -- load the input table header from codetable binary file
00084  */
00085 int LoadCodeTableHeader (file_name, hztbl)
00086      char *file_name;
00087      CodeTableStruct *hztbl;
00088 {
00089   FILE *ifile;
00090   char ctFlag[256];
00091   int  ver;
00092 
00093   log_f("LoadCodeTableHeader ====\n");
00094 
00095   /* read table from file to memory buffer  */
00096   ifile = fopen (file_name, "r");
00097   if (! ifile) {
00098     fprintf(stderr, "Unable to open the input table file \"%s\"\n",file_name);
00099     return(-1);
00100   }
00101 
00102   /* Read CodeTable File Flag */
00103   if (fread (ctFlag, strlen(CODETABLE_FLAG), 1, ifile) != 1) {
00104     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00105     fclose(ifile);
00106     return(-1);
00107   }
00108 
00109   if (strncmp (ctFlag, CODETABLE_FLAG, strlen(CODETABLE_FLAG)) != 0) {
00110     fprintf (stderr, "File is not in CodeTable format\n");
00111     fclose(ifile);
00112     return(-1);
00113   }
00114 
00115   /* Read CodeTable Version Flag */
00116   if (fread ((char *)(&ver), sizeof (int), 1, ifile) != 1)  {
00117     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00118     fclose(ifile);
00119     return(-1);
00120   }
00121 
00122   if (ver != CODETABLE_VERSION) {
00123     fprintf (stderr, "File is not in correct Version Number\n");
00124     fclose(ifile);
00125     return(-1);
00126   }
00127 
00128   if (fread((char *)hztbl, sizeof(CodeTableStruct), 1, ifile) != 1) {
00129     fprintf(stderr, "Error in loading input table for %s\n", file_name);
00130     fclose(ifile);
00131     return(-1);
00132   }
00133 
00134   fclose (ifile);
00135   return(0);
00136 }
00137 
00138 /*
00139  * LoadCodeTable -- load the input table from codetable binary file
00140  */
00141 int LoadCodeTable (file_name, hztbl)
00142      char *file_name;
00143      CodeTableStruct *hztbl;
00144 {
00145   FILE *ifile;
00146   char ctFlag[256];
00147   int  ver, i;
00148 
00149   ifile = fopen (file_name, "r");
00150   if (! ifile) {
00151     log_f("Unable to open the input table file \"%s\"\n",file_name);
00152     return(-1);
00153   }
00154 
00155   /* Read CodeTable File Flag */
00156   if (fread (ctFlag, strlen(CODETABLE_FLAG), 1, ifile) != 1) {
00157     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00158     fclose (ifile);
00159     return(-1);
00160   }
00161 
00162   if (strncmp (ctFlag, CODETABLE_FLAG, strlen(CODETABLE_FLAG)) != 0) {
00163     fprintf (stderr, "File is not in CodeTable format\n");
00164     fclose (ifile);
00165     return(-1);
00166   }
00167 
00168   /* Read CodeTable Version Flag */
00169   if (fread ((char *)(&ver), sizeof (int), 1, ifile) != 1)  {
00170     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00171     fclose (ifile);
00172     return(-1);
00173   }
00174 
00175   if (ver != CODETABLE_VERSION) {
00176     fprintf (stderr, "File is not in correct Version Number\n");
00177     fclose (ifile);
00178     return(-1);
00179   }
00180 
00181   if (fread((char *)hztbl, sizeof(CodeTableStruct), 1, ifile) == 0) {
00182     log_f( "Error in loading input table for %s\n", file_name);
00183     fclose (ifile);
00184     return(-1);
00185   }
00186 
00187   /* malloc memory for codetable information */
00188   hztbl->nodeList = (tableNode *)calloc(hztbl->sizeNodeList,sizeof(tableNode));
00189   hztbl->hzList = (unsigned char *)calloc(hztbl->sizeHZList, sizeof(unsigned char));
00190   hztbl->keyprompt = (keyPrompt *)calloc(MAX_USEDCODES_NUM, sizeof(keyPrompt));
00191   hztbl->functionkey = (functionKey *)calloc(MAX_FUNCTIONKEY_NUM, sizeof(functionKey));
00192   if ((! hztbl->hzList) || (! hztbl->nodeList) ||
00193       (! hztbl->keyprompt) || (! hztbl->functionkey)) {
00194     log_f( "No memory to load input table for %s\n", file_name);
00195     fclose (ifile);
00196     return(-1);
00197   }
00198 
00199   if ((fread ((char *)(hztbl->nodeList), sizeof(tableNode),
00200              (int)hztbl->sizeNodeList, ifile) != hztbl->sizeNodeList) ||
00201       (fread ((char *)hztbl->hzList, sizeof(unsigned char),
00202              (int)(hztbl->sizeHZList), ifile) != hztbl->sizeHZList))
00203     {
00204       log_f( "Error in loading input table for %s\n", file_name);
00205       fclose (ifile);
00206       return(-1);
00207     }
00208        
00209   if (GETBIT(hztbl->bSectionsFlag, KEYPROMPT_SECTION)) {
00210     if (fread((char *)(&(hztbl->keyprompt[0])), MAX_USEDCODES_NUM, 
00211              sizeof(keyPrompt), ifile) != sizeof(keyPrompt))
00212       {
00213        log_f( "Error in loading input table for %s\n", file_name);
00214        fclose (ifile);
00215        return(-1);
00216       }
00217   }
00218 
00219   if (GETBIT(hztbl->bSectionsFlag, FUNCTIONKEY_SECTION)) {
00220     if (fread((char *)(&(hztbl->functionkey[0])), MAX_FUNCTIONKEY_NUM, 
00221              sizeof(functionKey), ifile) != sizeof(functionKey))
00222       {
00223        log_f( "Error in loading input table for %s\n", file_name);
00224        fclose (ifile);
00225        return(-1);
00226       }
00227   }
00228 
00229   for (i=0; i<MAX_USEDCODES_NUM; i++) {
00230     if (hztbl->keyprompt[i].prompt[0] == 0) {
00231       hztbl->keyprompt[i].prompt[0] = i;
00232       hztbl->keyprompt[i].prompt[1] = 0;
00233     }
00234   }
00235 
00236   fclose (ifile);
00237   return(0);
00238 }
00239 
00240 /*
00241  * UnloadCodeTable -- unload the input table, free the memory
00242  */
00243 void UnloadCodeTable(hztbl)
00244      CodeTableStruct *hztbl;
00245 {
00246   if (! hztbl) return;
00247 
00248   if (hztbl->nodeList)  free ((char *)(hztbl->nodeList));
00249   if (hztbl->hzList)  free ((char *)(hztbl->hzList));
00250   if (hztbl->keyprompt)  free ((char *)(hztbl->keyprompt));
00251   if (hztbl->functionkey)  free ((char *)(hztbl->functionkey));
00252 }
00253 
00254 int Is_WildcharMatchAny_Key(hztbl, keycode, modifier)
00255      CodeTableStruct *hztbl;
00256      int keycode;
00257      int modifier;
00258 {
00259   if ( index(hztbl->UsedCodes, WILDCHAR_MATCHANY) )
00260     return(0);
00261   else
00262     return(0);
00263 
00264 }
00265 
00266 int Is_WildcharMatchSingle_Key(hztbl, key)
00267      CodeTableStruct *hztbl;
00268      int key;
00269 {
00270   if ( index(hztbl->UsedCodes, WILDCHAR_MATCHSINGLE) )
00271     return(0);
00272   else
00273     return(0);
00274 }
00275 
00276 int Is_Wildchar_Key(hztbl, key)
00277      CodeTableStruct *hztbl;
00278      int key;
00279 {
00280   int ret;
00281 
00282   ret = ( Is_WildcharMatchSingle_Key(hztbl, key) || Is_WildcharMatchAny_Key(hztbl, key) );
00283   return(ret);
00284 }
00285 
00286 /*********************** Wild Char Matching ***********************/
00287 
00288 /*
00289  * WildcardMatch() returns 3 values.  WILD_MATCH is for an exact match.
00290  * WILD_PREFIX means the current traversal path (from "top" to the current
00291  * node) matches a prefix of the wildcard pattern, which might suggest a
00292  * possible match if the traversal goes deeper.  WILD_UNMATCH is a total
00293  * mismatch, in which case the traversal should stop go any deeper.
00294  */
00295 
00296 #define car(s)              (*(s))
00297 #define cdr(s)              ((s)+1)
00298 #define empty(s)     (!(*(s)))
00299 
00300 /*
00301  * recursively WildcharMatch string (with no wildcard) against pattern (possibly with wildcard)
00302  */
00303 static int WildcharMatch(hztbl, string, pattern)
00304      CodeTableStruct *hztbl;
00305      char *string;
00306      char *pattern;
00307 {
00308   if (empty(pattern))
00309     return (empty(string) ? WILD_MATCH : WILD_UNMATCH);
00310   else if (Is_WildcharMatchAny_Key(hztbl, car(pattern))) {
00311     int x = WildcharMatch(hztbl, string, cdr(pattern));
00312     if (x == WILD_UNMATCH)
00313       return (WildcharMatch(hztbl, cdr(string), pattern));
00314     else
00315       return x;
00316   } 
00317   else if (empty(string))
00318     return WILD_PREFIX;
00319   else if (Is_WildcharMatchSingle_Key(hztbl, car(pattern)) || car(pattern) == car(string))
00320     return WildcharMatch(hztbl, cdr(string), cdr(pattern));
00321   else
00322     return WILD_UNMATCH;
00323 }
00324 
00325 /*********************** Traversal in Codetable Node ***********************/
00326 
00327 /*
00328  * Search in the trie for the given suffix in the input sequent
00329  * that contains wildcard(s).  The "top" node matches the longest
00330  * prefix in the input sequent that contains no wildcard.
00331  * The traversal is a Deep-First-Search starting from "top".
00332  * But it visits the node before visiting any child under the node.
00333  *
00334  */
00335 
00336 /*
00337  * Move to next sibling, if no more sibling, move up to parent's sibling
00338  */
00339 static int Get_NextNode(pSC)
00340      HZSearchContext *pSC;
00341 {
00342   while (pSC->tNnumSb[pSC->depth] == 0) 
00343     {
00344       /* no more sibling, go up */
00345       if (pSC->depth == 0) {
00346        /* now at the topmost; we've tried everything! */
00347        pSC->tNstack[0] = NULL;
00348        return(SC_FAIL);
00349       } else {
00350        pSC->depth--;
00351        pSC->kc_repcode = 0;
00352        pSC->mo_repcode = 0;
00353       }
00354     }
00355 
00356   /* go to sibling node */
00357   pSC->tNnumSb[pSC->depth]-- ;
00358   pSC->tNstack[pSC->depth]++ ; 
00359   pSC->kc_repcode = pSC->tNstack[pSC->depth]->keycode;
00360   pSC->mo_repcode = pSC->tNstack[pSC->depth]->modifier;
00361   return(SC_OK);
00362 }
00363 
00364 int is_valid_candidate(unsigned char *hzptr, int hzlen, int dict_encode, int output_encode)
00365 {
00366   int ret;
00367 
00368   if (dict_encode == output_encode)
00369     return(1);
00370 
00371   if (dict_encode == ENCODE_UTF8) {
00372     char *ip, *op, buffer[512];
00373     int ileft, oleft;
00374               
00375     ip = (char *)hzptr;
00376     ileft = hzlen;
00377     op = buffer;
00378     oleft = 512;
00379     memset(buffer, 0, 512);
00380     ret = Convert_UTF8_To_Native(output_encode, ip, ileft, &op, &oleft);
00381     log_f("ctim: Convert UTF-8 to native, ret: %d\n", ret);
00382     if (ret == -1) {
00383       return(0);
00384     } else {
00385       if(buffer[0] && is_valid_encode_string(output_encode, buffer, strlen(buffer)) == 0)
00386        return(1);
00387       else
00388        return(0);
00389     }
00390   }
00391 
00392   return (1);
00393 }
00394 
00395 int normal_search(hztbl, pSC, outbuf, attrbuf, pos, num)
00396      CodeTableStruct *hztbl;
00397      HZSearchContext *pSC;
00398      unsigned char **outbuf;
00399      unsigned char **attrbuf;
00400      int pos;
00401      int num;
00402 {
00403   tableNode *tnptr;
00404   int *outbuf_flag;
00405   unsigned char *hzptr, tmpbuf[MAX_CANDIDATE_CHAR_NUM];
00406   unsigned char buf[MAX_CANDIDATE_CHAR_NUM];
00407   int outptr, i, j, hzlen, len;
00408   int num_matched = 0;      /* pointer that how many items match the conditions */
00409   int num_selected = 0;     /* pointer that how many items be selected */
00410   char dict_encode, output_encode;
00411 
00412   dict_encode = hztbl->Encode;
00413   output_encode = hztbl->Output_Encode;
00414 
00415   log_f("dict_encode:%d, output_encode:%d\n", dict_encode, output_encode);
00416   outbuf_flag = (int *)alloca(num * sizeof(int));
00417   memset(outbuf_flag, 0, sizeof (num * sizeof(int)));
00418 
00419   /* traversal all the subnodes of pSC->tNstack[0] */
00420   while (1) 
00421     {
00422       tnptr = pSC->tNstack[pSC->depth];
00423 
00424       /* check if any HZ choices on this node */
00425       if (tnptr->num_HZchoice > 0) 
00426        {
00427          /* if any HZ choices on this node,check if match search conditions */
00428           /*
00429          log_f("kc_repcode:%d  \t%d\n", pSC->kc_repcode, tnptr->num_HZchoice);
00430           */
00431          /* get HZ choices */
00432          hzptr = hztbl->hzList + tnptr->pos_HZidx;
00433          for (i=0; i<tnptr->num_HZchoice; i++) 
00434            {
00435              if (*hzptr == HZ_PHRASE_TAG) {
00436               hzlen = *(hzptr + 1);
00437               hzptr += 2;
00438              } else {
00439               hzlen = get_char_len_by_encodeid(hztbl->Encode, hzptr);
00440              }
00441 
00442              if (is_valid_candidate(hzptr, hzlen, dict_encode, output_encode)) {
00443               num_matched ++;
00444 
00445               outptr = 0; 
00446               if (num_matched > pos) {
00447                 log_f("pos:%d, matched:%d\n", pos, num_matched);
00448                 len = hzlen;
00449                 if (len>MAX_CANDIDATE_CHAR_NUM) 
00450                   len = MAX_CANDIDATE_CHAR_NUM;
00451                 for (j=0; j< len; j++)
00452                   tmpbuf[outptr++] = *(hzptr+j);
00453                 tmpbuf[outptr++] = '\0';
00454               }
00455        
00456               if (outptr > 0) {
00457                   /*
00458                   log_f("kc_repcode [%d], tmpbuf [%s], num_selected [%d]\n",pSC->kc_repcode, tmpbuf, num_selected);
00459                   */
00460                   if (pSC->kc_repcode == 49) {
00461                     if (!num_selected) {
00462                     strcpy((char *)outbuf[0], tmpbuf);
00463                       outbuf_flag[0] = 1;
00464                     }else{
00465                     strcpy((char *)buf, (char *)outbuf[0]);
00466                     strcpy((char *)outbuf[0], tmpbuf);
00467                     strcpy((char *)outbuf[num_selected], (char *)buf);
00468                     }
00469                   } else if (pSC->kc_repcode == 50) {
00470                     if (num_selected <= 1) {
00471                     strcpy((char *)outbuf[1], tmpbuf);
00472                       outbuf_flag[1] = 1;
00473                     }else{
00474                     strcpy((char *)buf, (char *)outbuf[1]);
00475                     strcpy((char *)outbuf[1], tmpbuf);
00476                     strcpy((char *)outbuf[num_selected], (char *)buf);
00477                     }
00478                   } else if (pSC->kc_repcode == 51) {
00479                     if (num_selected <= 2) {
00480                     strcpy((char *)outbuf[2], tmpbuf);
00481                       outbuf_flag[2] = 1;
00482                     }else{
00483                     strcpy((char *)buf, (char *)outbuf[2]);
00484                     strcpy((char *)outbuf[2], tmpbuf);
00485                     strcpy((char *)outbuf[num_selected], (char *)buf);
00486                     }
00487                   } else if (pSC->kc_repcode == 52) {
00488                     if (num_selected <= 3) {
00489                     strcpy((char *)outbuf[3], tmpbuf);
00490                       outbuf_flag[3] = 1;
00491                     }else{
00492                     strcpy((char *)buf, (char *)outbuf[3]);
00493                     strcpy((char *)outbuf[3], tmpbuf);
00494                     strcpy((char *)outbuf[num_selected], (char *)buf);
00495                     }
00496                   } else {
00497                     for (i=0; i<num; i++){
00498                       if (outbuf_flag[i] != 1) {
00499                       strcpy((char *)outbuf[i], tmpbuf);
00500                         outbuf_flag[i] = 1;
00501                         break;
00502                       }
00503                     }
00504                   sprintf((char *)attrbuf[num_selected], "%s%d%d", pSC->prefix, pSC->kc_repcode, pSC->mo_repcode); 
00505                   }
00506                 num_selected ++;
00507               }
00508               if (num_selected >= num) {
00509                   /*
00510                   for (i=1; i<=num_selected; i++){
00511                     log_f("outbuf[%d]:[%s]\n",i,outbuf[i]);
00512                   }
00513                   */
00514                   return (num);
00515                 }
00516              }
00517              hzptr += hzlen;
00518            }
00519        }
00520 
00521       /* if have any addition input key, move down */
00522       if (tnptr->num_NextKeys > 0) {
00523        tableNode *new_tnptr = &(hztbl->nodeList[tnptr->pos_NextKey]);
00524 
00525        pSC->depth++ ;
00526        pSC->tNnumSb[pSC->depth] = tnptr->num_NextKeys - 1;
00527        pSC->tNstack[pSC->depth] = new_tnptr;
00528        pSC->kc_repcode = new_tnptr->keycode;
00529        pSC->mo_repcode = new_tnptr->modifier;
00530        continue;
00531       }
00532 
00533       /* No more additional key, hence no match for this node. */
00534       /* Don't go down, move forward */
00535       if ( Get_NextNode(pSC) == SC_FAIL )
00536        return (num_selected);
00537     }
00538 
00539 }
00540 
00541 int wildchar_search(hztbl, pSC, outbuf, attrbuf, pos, num)
00542      CodeTableStruct *hztbl;
00543      HZSearchContext *pSC;
00544      unsigned char **outbuf;
00545      unsigned char **attrbuf;
00546      int pos;
00547      int num;
00548 {
00549   tableNode *tnptr;
00550   unsigned char *hzptr, tmpbuf[MAX_CANDIDATE_CHAR_NUM];
00551   int outptr, i, j, hzlen, len;
00552   int num_matched = 0;    /* pointer that how many items match the conditions */
00553   int num_selected = 0;   /* pointer that how many items be selected */
00554   int bMatched;
00555 
00556   char dict_encode, output_encode;
00557 
00558   dict_encode = hztbl->Encode;
00559   output_encode = hztbl->Output_Encode;
00560 
00561   log_f("wildpattern:%s\n", pSC->wildpattern);
00562 
00563   /* traversal all the subodes of pSC->tNstack[0] */
00564   while (1) 
00565     {
00566       tnptr = pSC->tNstack[pSC->depth];
00567 
00568       /* check if any HZ choices on this node */
00569       bMatched = 0xff;
00570       if (tnptr->num_HZchoice > 0) {
00571        log_f("kc_repcode:%d  ", pSC->kc_repcode);
00572        log_f("mo_repcode:%d  ", pSC->mo_repcode);
00573 
00574        /* if any HZ choices on this node, then check match search conditions */
00575        bMatched = WildcharMatch(hztbl, pSC->kc_repcode,pSC->mo_repcode, pSC->wildpattern);
00576       }
00577 
00578       if (bMatched == WILD_MATCH) 
00579        {
00580          /* if any HZ choices on this node,then check if match search conditions */
00581 
00582          log_f("kc_repcode:%d\t mo_repcode:%d  \t%d\n", pSC->kc_repcode, pSC->mo_repcode, tnptr->num_HZchoice);
00583 
00584          /* get HZ choices */
00585          hzptr = hztbl->hzList + tnptr->pos_HZidx;
00586          for (i=0; i<tnptr->num_HZchoice; i++) {
00587            if (*hzptr == HZ_PHRASE_TAG) {
00588              hzlen = *(hzptr + 1);
00589              hzptr += 2;
00590            } else {
00591              hzlen = get_char_len_by_encodeid(hztbl->Encode, hzptr);
00592            }
00593 
00594            if (is_valid_candidate(hzptr, hzlen, dict_encode, output_encode)) {
00595              num_matched ++;
00596 
00597              outptr = 0; 
00598              if (num_matched > pos) {
00599               len = hzlen;
00600               if (len>MAX_CANDIDATE_CHAR_NUM) 
00601                 len = MAX_CANDIDATE_CHAR_NUM;
00602               for (j=0; j< len; j++)
00603                 tmpbuf[outptr++] = *(hzptr+j);
00604               tmpbuf[outptr++] = '\0';
00605              }
00606        
00607              if (outptr > 0) {
00608               strcpy((char *)outbuf[num_selected], tmpbuf);
00609               sprintf((char *)attrbuf[num_selected], "%s%d%d", pSC->prefix, pSC->kc_repcode, pSC->mo_repcode); 
00610               num_selected ++;
00611              }
00612              if (num_selected >= num) return (num);
00613            }
00614 
00615            hzptr += hzlen;
00616          }
00617        } else if (bMatched == WILD_UNMATCH) {
00618          /* need not to go down */
00619          if ( Get_NextNode(pSC) == SC_FAIL )
00620            return (num_selected);
00621          continue;
00622        }
00623 
00624       /* if have any addition input key, move down */
00625       if (tnptr->num_NextKeys > 0) {
00626        tableNode *new_tnptr = &(hztbl->nodeList[tnptr->pos_NextKey]);
00627 
00628        pSC->depth++ ;
00629        pSC->tNnumSb[pSC->depth] = tnptr->num_NextKeys - 1;
00630        pSC->tNstack[pSC->depth] = new_tnptr;
00631        pSC->kc_repcode = new_tnptr->keycode;
00632        pSC->mo_repcode = new_tnptr->modifier;
00633        continue;
00634       }
00635 
00636       /* No more additional key, hence no match for this node. */
00637       /* Don't go down, move forward */
00638       if ( Get_NextNode(pSC) == SC_FAIL )
00639        return (num_selected);
00640     }
00641 }
00642 
00643 int codetable_search(hztbl, inbuf, inlen, outbuf, attrbuf, pos, num)
00644      CodeTableStruct *hztbl;
00645      int *inbuf;
00646      int inlen;
00647      unsigned char **outbuf;
00648      unsigned char **attrbuf;
00649      int pos;
00650      int num;
00651 {
00652   HZSearchContext search_context, *pSC;
00653 
00654   int matched, i, j, k;
00655   tableNode *tnptr, *tCurTNptr;
00656   int search_num;
00657        
00658   /* search maxinum matched top node that not include wildchar */
00659   tCurTNptr = &(hztbl->nodeList[0]);
00660   i = 0;
00661   k = i+1;
00662   while (i < inlen)
00663     {
00664       if ( Is_WildcharMatchSingle_Key(hztbl, inbuf[i]) || 
00665           Is_WildcharMatchAny_Key(hztbl, inbuf[i]) )
00666        break;
00667 
00668       matched = 0;
00669       j = 0;
00670       tnptr = &(hztbl->nodeList[tCurTNptr->pos_NextKey]);
00671       while (j < tCurTNptr->num_NextKeys)
00672        {
00673          if ((inbuf[i] == tnptr->keycode) && (inbuf[k] == tnptr->modifier)) {
00674            matched = 1;
00675            break;
00676          }
00677          tnptr ++;
00678          j++;
00679        }
00680       if (matched == 0)
00681        return(0);
00682 
00683       tCurTNptr = tnptr;
00684       i+=2;
00685       k = i+1;
00686     }
00687 
00688   /* set search context */
00689   pSC = &search_context;
00690   pSC->depth = 0;
00691   pSC->tNnumSb[0] = 0;
00692   pSC->tNstack[0] = tCurTNptr;
00693   pSC->kc_repcode=0;
00694   pSC->mo_repcode=0;
00695   memset(pSC->prefix, 0, MAX_INPUT_KEY_NUM+1);
00696   memset(pSC->wildpattern, 0, MAX_INPUT_KEY_NUM+1);
00697 
00698   search_num = num > MAX_CANDIDATES_NUM ? MAX_CANDIDATES_NUM : num;
00699   log_f("search_num [%d], i [%d]\n",search_num,i);
00700   log_f("i[%d], inlen: [%d]\n",i,inlen);
00701   if (i == inlen) {
00702     log_f("normal_search: \n");
00703     /* no wildchar,  begin normal mode search */
00704     num = normal_search(hztbl, pSC, outbuf, attrbuf, pos, search_num);
00705   } else {
00706     /* have any wildchar, begin wildchar mode search */
00707     strcpy(pSC->wildpattern, (char *)inbuf+i);
00708     log_f("pSC->wildpattern [%s]\n",pSC->wildpattern);
00709     num = wildchar_search(hztbl, pSC, outbuf, attrbuf, pos, search_num);
00710   }
00711   return(num);
00712 }
00713