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 
00043 #ifdef HAVE_CONFIG_H
00044 #include <config.h>
00045 #endif
00046 
00047 #include <stdio.h>
00048 
00049 #ifdef HAVE_LOCALE_H
00050 #include <locale.h>
00051 #endif
00052 #ifdef HAVE_STRING_H
00053 #include <string.h>
00054 #endif
00055 #ifdef HAVE_STDLIB_H
00056 #include <stdlib.h>
00057 #endif
00058 
00059 #include "encode.h"
00060 #include "codetable.h"
00061 #include "logf.h"
00062 
00063 #define WILD_MATCH          0      /* exact match */
00064 #define WILD_PREFIX         1      /* no match, but maybe if go deeper */
00065 #define WILD_UNMATCH        2      /* complete mismatch */
00066 
00067 #define SC_FAIL                    0
00068 #define SC_OK               1
00069 
00070 #define WILDCHAR_MATCHSINGLE       '?'
00071 #define WILDCHAR_MATCHANY   '*'
00072 
00073 #define       MAX_CANDIDATES_NUM   16
00074 #define MAX_CANDIDATE_CHAR_NUM     64
00075 #define MAX_INPUT_KEY_NUM   32
00076 
00077 /* CodeTable Search Context */
00078 typedef struct _HZSearchContext {
00079 
00080   int depth;                              /* the current depth in the DFS traversal */
00081 
00082   char prefix[MAX_INPUT_KEY_NUM+1];              /* the prefix traced codes */
00083   char wildpattern[MAX_INPUT_KEY_NUM+1];         /* the wildchar pattern codes */
00084   char repcode[MAX_INPUT_KEY_NUM+1];             /* the tracing codes */
00085   tableNode *tNstack[MAX_INPUT_KEY_NUM+1];       /* the tableNode stack */
00086   short int tNnumSb[MAX_INPUT_KEY_NUM+1];        /* number of sibling tableNode */
00087 
00088 } HZSearchContext;
00089 
00090 /*********************** Load Codetable File ***********************/
00091 
00092 /*
00093  * LoadCodeTableHeader -- load the input table header from codetable binary file
00094  */
00095 int LoadCodeTableHeader (file_name, hztbl)
00096      char *file_name;
00097      CodeTableStruct *hztbl;
00098 {
00099   FILE *ifile;
00100   char ctFlag[256];
00101   int  ver;
00102 
00103   log_f("LoadCodeTableHeader ====\n");
00104 
00105   /* read table from file to memory buffer  */
00106   ifile = fopen (file_name, "r");
00107   if (! ifile) {
00108     fprintf(stderr, "Unable to open the input table file \"%s\"\n",file_name);
00109     return(-1);
00110   }
00111 
00112   /* Read CodeTable File Flag */
00113   if (fread (ctFlag, strlen(CODETABLE_FLAG), 1, ifile) != 1) {
00114     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00115     fclose(ifile);
00116     return(-1);
00117   }
00118 
00119   if (strncmp (ctFlag, CODETABLE_FLAG, strlen(CODETABLE_FLAG)) != 0) {
00120     fprintf (stderr, "File is not in CodeTable format\n");
00121     fclose(ifile);
00122     return(-1);
00123   }
00124 
00125   /* Read CodeTable Version Flag */
00126   if (fread ((char *)(&ver), sizeof (int), 1, ifile) != 1)  {
00127     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00128     fclose(ifile);
00129     return(-1);
00130   }
00131 
00132   if (ver != CODETABLE_VERSION) {
00133     fprintf (stderr, "File is not in correct Version Number\n");
00134     fclose(ifile);
00135     return(-1);
00136   }
00137 
00138   if (fread((char *)hztbl, sizeof(CodeTableStruct), 1, ifile) != 1) {
00139     fprintf(stderr, "Error in loading input table for %s\n", file_name);
00140     fclose(ifile);
00141     return(-1);
00142   }
00143 
00144   fclose (ifile);
00145   return(0);
00146 }
00147 
00148 /*
00149  * LoadCodeTable -- load the input table from codetable binary file
00150  */
00151 int LoadCodeTable (file_name, hztbl)
00152      char *file_name;
00153      CodeTableStruct *hztbl;
00154 {
00155   FILE *ifile;
00156   char ctFlag[256];
00157   int  ver, i;
00158 
00159   ifile = fopen (file_name, "r");
00160   if (! ifile) {
00161     log_f("Unable to open the input table file \"%s\"\n",file_name);
00162     return(-1);
00163   }
00164 
00165   /* Read CodeTable File Flag */
00166   if (fread (ctFlag, strlen(CODETABLE_FLAG), 1, ifile) != 1) {
00167     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00168     fclose (ifile);
00169     return(-1);
00170   }
00171 
00172   if (strncmp (ctFlag, CODETABLE_FLAG, strlen(CODETABLE_FLAG)) != 0) {
00173     fprintf (stderr, "File is not in CodeTable format\n");
00174     fclose (ifile);
00175     return(-1);
00176   }
00177 
00178   /* Read CodeTable Version Flag */
00179   if (fread ((char *)(&ver), sizeof (int), 1, ifile) != 1)  {
00180     fprintf (stderr, "Codetable File read Error:%s\n", file_name);
00181     fclose (ifile);
00182     return(-1);
00183   }
00184 
00185   if (ver != CODETABLE_VERSION) {
00186     fprintf (stderr, "File is not in correct Version Number\n");
00187     fclose (ifile);
00188     return(-1);
00189   }
00190 
00191   if (fread((char *)hztbl, sizeof(CodeTableStruct), 1, ifile) == 0) {
00192     log_f( "Error in loading input table for %s\n", file_name);
00193     fclose (ifile);
00194     return(-1);
00195   }
00196 
00197   /* malloc memory for codetable information */
00198   hztbl->nodeList = (tableNode *)calloc(hztbl->sizeNodeList,sizeof(tableNode));
00199   hztbl->hzList = (unsigned char *)calloc(hztbl->sizeHZList, sizeof(unsigned char));
00200   hztbl->keyprompt = (keyPrompt *)calloc(MAX_USEDCODES_NUM, sizeof(keyPrompt));
00201   hztbl->functionkey = (functionKey *)calloc(MAX_FUNCTIONKEY_NUM, sizeof(functionKey));
00202   if ((! hztbl->hzList) || (! hztbl->nodeList) ||
00203       (! hztbl->keyprompt) || (! hztbl->functionkey)) {
00204     log_f( "No memory to load input table for %s\n", file_name);
00205     fclose (ifile);
00206     return(-1);
00207   }
00208 
00209   if ((fread ((char *)(hztbl->nodeList), sizeof(tableNode),
00210              (int)hztbl->sizeNodeList, ifile) != hztbl->sizeNodeList) ||
00211       (fread ((char *)hztbl->hzList, sizeof(unsigned char),
00212              (int)(hztbl->sizeHZList), ifile) != hztbl->sizeHZList))
00213     {
00214       log_f( "Error in loading input table for %s\n", file_name);
00215       fclose (ifile);
00216       return(-1);
00217     }
00218        
00219   if (GETBIT(hztbl->bSectionsFlag, KEYPROMPT_SECTION)) {
00220     if (fread((char *)(&(hztbl->keyprompt[0])), MAX_USEDCODES_NUM, 
00221              sizeof(keyPrompt), ifile) != sizeof(keyPrompt))
00222       {
00223        log_f( "Error in loading input table for %s\n", file_name);
00224        fclose (ifile);
00225        return(-1);
00226       }
00227   }
00228 
00229   if (GETBIT(hztbl->bSectionsFlag, FUNCTIONKEY_SECTION)) {
00230     if (fread((char *)(&(hztbl->functionkey[0])), MAX_FUNCTIONKEY_NUM, 
00231              sizeof(functionKey), ifile) != sizeof(functionKey))
00232       {
00233        log_f( "Error in loading input table for %s\n", file_name);
00234        fclose (ifile);
00235        return(-1);
00236       }
00237   }
00238 
00239   for (i=0; i<MAX_USEDCODES_NUM; i++) {
00240     if (hztbl->keyprompt[i].prompt[0] == 0) {
00241       hztbl->keyprompt[i].prompt[0] = i;
00242       hztbl->keyprompt[i].prompt[1] = 0;
00243     }
00244   }
00245 
00246   fclose (ifile);
00247   return(0);
00248 }
00249 
00250 /*
00251  * UnloadCodeTable -- unload the input table, free the memory
00252  */
00253 void UnloadCodeTable(hztbl)
00254      CodeTableStruct *hztbl;
00255 {
00256   if (! hztbl) return;
00257 
00258   if (hztbl->nodeList)  free ((char *)(hztbl->nodeList));
00259   if (hztbl->hzList)  free ((char *)(hztbl->hzList));
00260   if (hztbl->keyprompt)  free ((char *)(hztbl->keyprompt));
00261   if (hztbl->functionkey)  free ((char *)(hztbl->functionkey));
00262 }
00263 
00264 int Is_WildcharMatchAny_Key(hztbl, key)
00265      CodeTableStruct *hztbl;
00266      int key;
00267 {
00268   if ( index(hztbl->UsedCodes, WILDCHAR_MATCHANY) )
00269     return(0);
00270   else
00271     return(0);
00272   /*
00273     return(key == WILDCHAR_MATCHANY);
00274   */
00275 
00276 }
00277 
00278 int Is_WildcharMatchSingle_Key(hztbl, key)
00279      CodeTableStruct *hztbl;
00280      int key;
00281 {
00282   if ( index(hztbl->UsedCodes, WILDCHAR_MATCHSINGLE) )
00283     return(0);
00284   else
00285     return(0);
00286 
00287   /*
00288     return(key == WILDCHAR_MATCHSINGLE);
00289   */
00290 }
00291 
00292 int Is_Wildchar_Key(hztbl, key)
00293      CodeTableStruct *hztbl;
00294      int key;
00295 {
00296   int ret;
00297 
00298   ret = ( Is_WildcharMatchSingle_Key(hztbl, key) || Is_WildcharMatchAny_Key(hztbl, key) );
00299   return(ret);
00300 }
00301 
00302 /*********************** Wild Char Matching ***********************/
00303 
00304 /*
00305  * WildcardMatch() returns 3 values.  WILD_MATCH is for an exact match.
00306  * WILD_PREFIX means the current traversal path (from "top" to the current
00307  * node) matches a prefix of the wildcard pattern, which might suggest a
00308  * possible match if the traversal goes deeper.  WILD_UNMATCH is a total
00309  * mismatch, in which case the traversal should stop go any deeper.
00310  */
00311 
00312 #define car(s)              (*(s))
00313 #define cdr(s)              ((s)+1)
00314 #define empty(s)     (!(*(s)))
00315 
00316 /*
00317  * recursively WildcharMatch string (with no wildcard) against pattern (possibly with wildcard)
00318  */
00319 static int WildcharMatch(hztbl, string, pattern)
00320      CodeTableStruct *hztbl;
00321      char *string;
00322      char *pattern;
00323 {
00324   if (empty(pattern))
00325     return (empty(string) ? WILD_MATCH : WILD_UNMATCH);
00326   else if (Is_WildcharMatchAny_Key(hztbl, car(pattern))) {
00327     int x = WildcharMatch(hztbl, string, cdr(pattern));
00328     if (x == WILD_UNMATCH)
00329       return (WildcharMatch(hztbl, cdr(string), pattern));
00330     else
00331       return x;
00332   } 
00333   else if (empty(string))
00334     return WILD_PREFIX;
00335   else if (Is_WildcharMatchSingle_Key(hztbl, car(pattern)) || car(pattern) == car(string))
00336     return WildcharMatch(hztbl, cdr(string), cdr(pattern));
00337   else
00338     return WILD_UNMATCH;
00339 }
00340 
00341 /*********************** Traversal in Codetable Node ***********************/
00342 
00343 /*
00344  * Search in the trie for the given suffix in the input sequent
00345  * that contains wildcard(s).  The "top" node matches the longest
00346  * prefix in the input sequent that contains no wildcard.
00347  * The traversal is a Deep-First-Search starting from "top".
00348  * But it visits the node before visiting any child under the node.
00349  *
00350  */
00351 
00352 /*
00353  * Move to next sibling, if no more sibling, move up to parent's sibling
00354  */
00355 static int Get_NextNode(pSC)
00356      HZSearchContext *pSC;
00357 {
00358   while (pSC->tNnumSb[pSC->depth] == 0) 
00359     {
00360       /* no more sibling, go up */
00361       if (pSC->depth == 0) {
00362        /* now at the topmost; we've tried everything! */
00363        pSC->tNstack[0] = NULL;
00364        return(SC_FAIL);
00365       } else {
00366        pSC->depth--;
00367        pSC->repcode[pSC->depth] = '\0';
00368       }
00369     }
00370 
00371   /* go to sibling node */
00372   pSC->tNnumSb[pSC->depth]-- ;
00373   pSC->tNstack[pSC->depth]++ ; 
00374   pSC->repcode[pSC->depth-1] = pSC->tNstack[pSC->depth]->key;
00375   return(SC_OK);
00376 }
00377 
00378 int is_valid_candidate(unsigned char *hzptr, int hzlen, int dict_encode, int output_encode)
00379 {
00380   int ret;
00381 
00382   if (dict_encode == output_encode)
00383     return(1);
00384 
00385   if (dict_encode == ENCODE_UTF8) {
00386     char *ip, *op, buffer[512];
00387     int ileft, oleft;
00388               
00389     ip = (char *)hzptr;
00390     ileft = hzlen;
00391     op = buffer;
00392     oleft = 512;
00393     memset(buffer, 0, 512);
00394     ret = Convert_UTF8_To_Native(output_encode, ip, ileft, &op, &oleft);
00395     log_f("ctim: Convert UTF-8 to native, ret: %d\n", ret);
00396     if (ret == -1) {
00397       return(0);
00398     } else {
00399       if(buffer[0] && is_valid_encode_string(output_encode, buffer, strlen(buffer)) == 0)
00400        return(1);
00401       else
00402        return(0);
00403     }
00404   }
00405 
00406   return (1);
00407 }
00408 
00409 int normal_search(hztbl, pSC, outbuf, attrbuf, pos, num)
00410      CodeTableStruct *hztbl;
00411      HZSearchContext *pSC;
00412      unsigned char **outbuf;
00413      unsigned char **attrbuf;
00414      int pos;
00415      int num;
00416 {
00417   tableNode *tnptr;
00418   unsigned char *hzptr, tmpbuf[MAX_CANDIDATE_CHAR_NUM];
00419   int outptr, i, j, hzlen, len;
00420   int num_matched = 0;      /* pointer that how many items match the conditions */
00421   int num_selected = 0;     /* pointer that how many items be selected */
00422   char dict_encode, output_encode;
00423 
00424   dict_encode = hztbl->Encode;
00425   output_encode = hztbl->Output_Encode;
00426 
00427   log_f("dict_encode:%d, output_encode:%d\n", dict_encode, output_encode);
00428   /* traversal all the subnodes of pSC->tNstack[0] */
00429   while (1) 
00430     {
00431       tnptr = pSC->tNstack[pSC->depth];
00432 
00433       /* check if any HZ choices on this node */
00434       if (tnptr->num_HZchoice > 0) 
00435        {
00436          /* if any HZ choices on this node,then check if match search conditions */
00437          log_f("repcode:%s  \t%d\n", pSC->repcode, tnptr->num_HZchoice);
00438 
00439          /* get HZ choices */
00440          hzptr = hztbl->hzList + tnptr->pos_HZidx;
00441          for (i=0; i<tnptr->num_HZchoice; i++) 
00442            {
00443              if (*hzptr == HZ_PHRASE_TAG) {
00444               hzlen = *(hzptr + 1);
00445               hzptr += 2;
00446              } else {
00447               hzlen = get_char_len_by_encodeid(hztbl->Encode, hzptr);
00448              }
00449 
00450              if (is_valid_candidate(hzptr, hzlen, dict_encode, output_encode)) {
00451               num_matched ++;
00452 
00453               outptr = 0; 
00454               if (num_matched > pos) {
00455                 log_f("pos:%d, matched:%d\n", pos, num_matched);
00456                 len = hzlen;
00457                 if (len>MAX_CANDIDATE_CHAR_NUM) 
00458                   len = MAX_CANDIDATE_CHAR_NUM;
00459                 for (j=0; j< len; j++)
00460                   tmpbuf[outptr++] = *(hzptr+j);
00461                 tmpbuf[outptr++] = '\0';
00462               }
00463        
00464               if (outptr > 0) {
00465                 strcpy((char *)outbuf[num_selected], tmpbuf);
00466                 sprintf((char *)attrbuf[num_selected], "%s%s", 
00467                        pSC->prefix, pSC->repcode); 
00468                 num_selected ++;
00469               }
00470               if (num_selected >= num) return (num);
00471              }
00472 
00473              hzptr += hzlen;
00474            }
00475        }
00476 
00477       /* if have any addition input key, move down */
00478       if (tnptr->num_NextKeys > 0) {
00479        tableNode *new_tnptr = &(hztbl->nodeList[tnptr->pos_NextKey]);
00480 
00481        pSC->depth++ ;
00482        pSC->tNnumSb[pSC->depth] = tnptr->num_NextKeys - 1;
00483        pSC->tNstack[pSC->depth] = new_tnptr;
00484        pSC->repcode[pSC->depth-1] = new_tnptr->key;
00485        continue;
00486       }
00487 
00488       /* No more additional key, hence no match for this node. */
00489       /* Don't go down, move forward */
00490       if ( Get_NextNode(pSC) == SC_FAIL )
00491        return (num_selected);
00492     }
00493 
00494 }
00495 
00496 int wildchar_search(hztbl, pSC, outbuf, attrbuf, pos, num)
00497      CodeTableStruct *hztbl;
00498      HZSearchContext *pSC;
00499      unsigned char **outbuf;
00500      unsigned char **attrbuf;
00501      int pos;
00502      int num;
00503 {
00504   tableNode *tnptr;
00505   unsigned char *hzptr, tmpbuf[MAX_CANDIDATE_CHAR_NUM];
00506   int outptr, i, j, hzlen, len;
00507   int num_matched = 0;    /* pointer that how many items match the conditions */
00508   int num_selected = 0;   /* pointer that how many items be selected */
00509   int bMatched;
00510 
00511   char dict_encode, output_encode;
00512 
00513   dict_encode = hztbl->Encode;
00514   output_encode = hztbl->Output_Encode;
00515 
00516   log_f("wildpattern:%s\n", pSC->wildpattern);
00517 
00518   /* traversal all the subodes of pSC->tNstack[0] */
00519   while (1) 
00520     {
00521       tnptr = pSC->tNstack[pSC->depth];
00522 
00523       /* check if any HZ choices on this node */
00524       bMatched = 0xff;
00525       if (tnptr->num_HZchoice > 0) {
00526        log_f("repcode:%s  ", pSC->repcode);
00527 
00528        /* if any HZ choices on this node, then check match search conditions */
00529        bMatched = WildcharMatch(hztbl, pSC->repcode, pSC->wildpattern);
00530       }
00531 
00532       if (bMatched == WILD_MATCH) 
00533        {
00534          /* if any HZ choices on this node,then check if match search conditions */
00535 
00536          log_f("repcode:%s  \t%d\n", pSC->repcode, tnptr->num_HZchoice);
00537 
00538          /* get HZ choices */
00539          hzptr = hztbl->hzList + tnptr->pos_HZidx;
00540          for (i=0; i<tnptr->num_HZchoice; i++) {
00541            if (*hzptr == HZ_PHRASE_TAG) {
00542              hzlen = *(hzptr + 1);
00543              hzptr += 2;
00544            } else {
00545              hzlen = get_char_len_by_encodeid(hztbl->Encode, hzptr);
00546            }
00547 
00548            if (is_valid_candidate(hzptr, hzlen, dict_encode, output_encode)) {
00549              num_matched ++;
00550 
00551              outptr = 0; 
00552              if (num_matched > pos) {
00553               len = hzlen;
00554               if (len>MAX_CANDIDATE_CHAR_NUM) 
00555                 len = MAX_CANDIDATE_CHAR_NUM;
00556               for (j=0; j< len; j++)
00557                 tmpbuf[outptr++] = *(hzptr+j);
00558               tmpbuf[outptr++] = '\0';
00559              }
00560        
00561              if (outptr > 0) {
00562               strcpy((char *)outbuf[num_selected], tmpbuf);
00563               sprintf((char *)attrbuf[num_selected], "%s%s", 
00564                      pSC->prefix, pSC->repcode); 
00565               num_selected ++;
00566              }
00567              if (num_selected >= num) return (num);
00568            }
00569 
00570            hzptr += hzlen;
00571          }
00572        } else if (bMatched == WILD_UNMATCH) {
00573          /* need not to go down */
00574          if ( Get_NextNode(pSC) == SC_FAIL )
00575            return (num_selected);
00576          continue;
00577        }
00578 
00579       /* if have any addition input key, move down */
00580       if (tnptr->num_NextKeys > 0) {
00581        tableNode *new_tnptr = &(hztbl->nodeList[tnptr->pos_NextKey]);
00582 
00583        pSC->depth++ ;
00584        pSC->tNnumSb[pSC->depth] = tnptr->num_NextKeys - 1;
00585        pSC->tNstack[pSC->depth] = new_tnptr;
00586        pSC->repcode[pSC->depth-1] = new_tnptr->key;
00587        continue;
00588       }
00589 
00590       /* No more additional key, hence no match for this node. */
00591       /* Don't go down, move forward */
00592       if ( Get_NextNode(pSC) == SC_FAIL )
00593        return (num_selected);
00594     }
00595 }
00596 
00597 int codetable_search(hztbl, inbuf, inlen, outbuf, attrbuf, pos, num)
00598      CodeTableStruct *hztbl;
00599      int *inbuf;
00600      int inlen;
00601      unsigned char **outbuf;
00602      unsigned char **attrbuf;
00603      int pos;
00604      int num;
00605 {
00606   HZSearchContext search_context, *pSC;
00607 
00608   int matched, i, j, k, len;
00609   tableNode *tnptr, *tCurTNptr;
00610   int search_num;
00611        
00612   /* search maxinum matched top node that not include wildchar */
00613   tCurTNptr = &(hztbl->nodeList[0]);
00614   i = 0;
00615   while (i < inlen)
00616     {
00617       if (    (Is_WildcharMatchSingle_Key(hztbl, inbuf[i])) || 
00618               (Is_WildcharMatchAny_Key(hztbl, inbuf[i])) )
00619        break;
00620 
00621       matched = 0;
00622       j = 0;
00623       tnptr = &(hztbl->nodeList[tCurTNptr->pos_NextKey]);
00624       while (j < tCurTNptr->num_NextKeys)
00625        {
00626          if (inbuf[i] == tnptr->key) {
00627            matched = 1;
00628            break;
00629          }
00630          tnptr ++;
00631          j ++;
00632        }
00633       if (matched == 0)
00634        return(0);
00635 
00636       tCurTNptr = tnptr;
00637       i++;
00638     }
00639 
00640   /* set search context */
00641   pSC = &search_context;
00642   pSC->depth = 0;
00643   pSC->tNnumSb[0] = 0;
00644   pSC->tNstack[0] = tCurTNptr;
00645   memset(pSC->repcode, 0, MAX_INPUT_KEY_NUM+1);
00646   memset(pSC->prefix, 0, MAX_INPUT_KEY_NUM+1);
00647   memset(pSC->wildpattern, 0, MAX_INPUT_KEY_NUM+1);
00648 
00649   if (i>0) {
00650     len = MAX_INPUT_KEY_NUM+1>i ? i : MAX_INPUT_KEY_NUM+1;  
00651     for(k=0;k<inlen;k++){
00652       pSC->prefix[k] = inbuf[k];
00653     }
00654     /*
00655       strncpy(pSC->prefix, inbuf, len);
00656     */
00657   }
00658 
00659   search_num = num > MAX_CANDIDATES_NUM ? MAX_CANDIDATES_NUM : num;
00660   if (i == inlen) {
00661     /* no wildchar,  begin normal mode search */
00662     num = normal_search(hztbl, pSC, outbuf, attrbuf, pos, search_num);
00663   } else {
00664     /* have any wildchar, begin wildchar mode search */
00665     for (k=0;k<inlen;k++){
00666       pSC->wildpattern[k] = inbuf[k+i];
00667     }
00668     num = wildchar_search(hztbl, pSC, outbuf, attrbuf, pos, search_num);
00669   }
00670   return(num);
00671 }
00672