/* * * UNICON - The Console Chinese & I18N * Copyright (c) 1999-2002 * * This file is part of UNICON, a console Chinese & I18N * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * See the file COPYING directory of this archive * Author: see CREDITS */ #include #include #include #include #include #include #include /* Associate Phrase Support */ #define IMM_MAX_ASSOCIATE_PHRASE 1024 #define MAX_USHORT 65535 #define error printf void LoadPhrase (HzInputTable_T *pClient, int phrno, char *tt) { TL_GetPhrase (pClient->pSysPhrase, phrno, tt); } long GetAssociatePhraseIndex (HzInputTable_T *pClient, int index, u_long *nPhrase) { int n, i; ITEM *q; AssociatePhrase *p = pClient->cur_table->pAssociatePhrase; if (index < 0) return 0; n = index / IMM_MAX_ASSOCIATE_PHRASE; i = index % IMM_MAX_ASSOCIATE_PHRASE; if (p[n].total == 0 || i > p[n].total || i < 0) return 0; q = p[n].pPhrase[i]; *nPhrase = q->nPhrase; return 1; } static int CaculateAssociateIndex (u_char *p) { int index = (int) p[0] * 256 + p[1]; return index; } static void CaculatePhraseKeys (HzInputTable_T *pClient, u_char *szCode, u_long *pKey1, u_long *pKey2) { int len, i; u_long key1, key2; int k; len = strlen(szCode); if (len > pClient->cur_table->MaxPress) pClient->cur_table->MaxPress = len; key1 = key2 = 0; for (i = 0; i < len; i++) { if(i<5) { k = pClient->cur_table->KeyMap[szCode[i]]; key1 |= k << (24-i*6); } else { k = pClient->cur_table->KeyMap[szCode[i]]; key2 |= k << (24-(i-5)*6); } } *pKey1 = key1; *pKey2 = key2; } static void InitPhrase (HzInputTable_T *pClient, ITEM *p, long nPhrase, u_char *szCode) { u_long key1, key2; CaculatePhraseKeys (pClient, szCode, &key1, &key2); memcpy(&p->key1,&key1,4); memcpy(&p->key2,&key2,4); p->nPhrase = nPhrase; } static int AddToAssociatePhrase (HzInputTable_T *pClient, u_char *szPhrase, ITEM *pItem) { AssociatePhrase *p = pClient->cur_table->pAssociatePhrase; int index = CaculateAssociateIndex (szPhrase); p[index].total++; if (p[index].total == 1) { p[index].pPhrase = malloc (sizeof (ITEM)); } else { p[index].pPhrase = realloc (p[index].pPhrase, sizeof (ITEM) * p[index].total); } p[index].pPhrase[p[index].total-1] = pItem; return 1; } int IsThisPhraseExist (HzInputTable_T *p, char *szCode, char *szPhrase) { u_long key1, key2; u_long start, end; char buf[256]; u_long i; CaculatePhraseKeys (p, szCode, &key1, &key2); start = p->cur_table->KeyIndex[(int) szCode[0]]; end = p->cur_table->KeyIndex[(int) szCode[0]+1]; for (i = 0; i < p->cur_table->TotalChar; i++) { if (p->cur_table->item[i].key1 == key1 && p->cur_table->item[i].key2 == key2) { TL_GetPhrase (p->pSysPhrase, p->cur_table->item[i].nPhrase, buf); if (strcmp (buf, szPhrase) == 0) return 1; } } return 0; } int AppendPhrase (HzInputTable_T *p, char *szCode, char *szPhrase) { long n = TL_AppendPhrase (p->pSysPhrase, szPhrase); if (IsThisPhraseExist (p, szCode, szPhrase) == 1) return 1; p->cur_table->TotalChar ++; p->cur_table->item = realloc (p->cur_table->item, sizeof(ITEM) * p->cur_table->TotalChar); InitPhrase (p, &p->cur_table->item[p->cur_table->TotalChar-1], n, szCode); AddToAssociatePhrase (p, szPhrase, &p->cur_table->item[p->cur_table->TotalChar-1]); ResortPhraseFreq (p); return 1; } int DeletePhrase (HzInputTable_T *p, char *szPhrase) { return 1; } int AdjustPhraseOrder (HzInputTable_T *pClient, long nPhrase) { int n = TL_AdjustPhraseOrder (pClient->pSysPhrase, nPhrase); /* int ResortPhraseFreq (HzInputTable_T *pClient); ResortPhraseFreq (pClient); */ return n; } int ResortPhraseFreq (HzInputTable_T *pClient) { hz_input_table *p = pClient->cur_table; u_short CharDef[64]; int i, index = p->TotalChar; int TotalKeyNum = p->TotalKey; SortPhraseItem (pClient->pSysPhrase, pClient->cur_table); bzero (CharDef, sizeof(CharDef)); bzero (p->KeyIndex, sizeof (unsigned short) * TotalKeyNum); for (i = 0; i < index; i++) { int kk = p->item[i].key1 >> 24 & 0x3f; if (!CharDef[kk]) { p->KeyIndex[kk]= (u_short) i; CharDef[kk]=1; } } p->KeyIndex[TotalKeyNum] = index; for(i=TotalKeyNum-1; i>0; i--) { if (!CharDef[i]) p->KeyIndex[i] = p->KeyIndex[i+1]; } return 1; } /* public Associate Phrase Interface */ int FindAssociateKey (HzInputTable_T *pClient, u_char *pStr) { AssociatePhrase *p = pClient->cur_table->pAssociatePhrase; int index; index = CaculateAssociateIndex (pStr); if (p[index].total == 0) { pClient->StartKey = pClient->EndKey = 0; return 0; /* no match */ } pClient->StartKey = IMM_MAX_ASSOCIATE_PHRASE * index; pClient->EndKey = IMM_MAX_ASSOCIATE_PHRASE * index + p[index].total; return 1; } /*************************************************************************** * The File format of Turbo Linux Input Method * * symbol len meaning * cur_table sizeof (hz_input_table) the same as CCE * n sizeof (long) total phrase * pItem n * sizeof (ITEM) read Item * **************************************************************************/ #include hz_input_table* LoadInputMethod(char *filename) { int nread, i, j; FILE *fd; hz_input_table *cur_table; long offset, end, handle; cur_table = malloc (sizeof(hz_input_table)); if (cur_table == NULL) error("Out of memory in LoadInputMethod"); fd = fopen(filename, "rb"); if (fd == NULL) { error("Cannot open input method %s", filename); free(cur_table); return NULL; } nread = fread(cur_table, sizeof(hz_input_table), 1, fd); if (nread != 1) { error("Cannot read file header %s", filename); return NULL; } if( strcmp(MAGIC_NUMBER, cur_table->magic_number) ) { printf("is not a valid tab file\n\n"); return NULL; } cur_table->item = (ITEM *)malloc(sizeof(ITEM ) * cur_table->TotalChar); //warn("Totalchar=%d\n",cur_table->TotalChar); if ( cur_table->item == NULL ) { error("Gosh, cannot malloc enough memory"); return NULL; } assert (fread(cur_table->item, sizeof(ITEM) , cur_table->TotalChar, fd) == cur_table->TotalChar); cur_table->pAssociatePhrase = (AssociatePhrase *)malloc(sizeof(AssociatePhrase) * MAX_USHORT); if (cur_table->pAssociatePhrase == NULL) { error("Gosh, cannot malloc enough memory"); return NULL; } memset (cur_table->pAssociatePhrase, 0, sizeof(AssociatePhrase) * MAX_USHORT); offset = ftell (fd); fseek (fd, 0L, SEEK_END); end = ftell (fd); // assert (0); handle = openMemFile (fd, offset, end - offset); for (i = 0; i < cur_table->TotalAssociatePhrase; i++) { u_short n; long nPhrase[1024]; // fread (&n, sizeof (u_short), 1, fd); readMemFile (handle, sizeof (u_short), (void *) &n); //fread (&cur_table->pAssociatePhrase[n], // sizeof (AssociatePhrase), 1, fd); readMemFile (handle, sizeof (AssociatePhrase), (void *) &cur_table->pAssociatePhrase[n]); //fread (nPhrase, sizeof (long), // cur_table->pAssociatePhrase[n].total, fd); readMemFile (handle, sizeof (long) * cur_table->pAssociatePhrase[n].total, (void *) nPhrase); cur_table->pAssociatePhrase[n].pPhrase = (ITEM **) malloc (sizeof (ITEM *) * cur_table->pAssociatePhrase[n].total); for (j = 0; j < cur_table->pAssociatePhrase[n].total; j++) cur_table->pAssociatePhrase[n].pPhrase[j] = &cur_table->item[nPhrase[j]]; } closeMemFile (handle); fclose (fd); // SortPhraseItem (cur_table); return cur_table; } void UnloadInputMethod (hz_input_table *p) { int i; // printf ("Calling UnloadInputMethod \n"); if (p == NULL) return; free (p->item); for (i = 0; i < MAX_USHORT; i++) if (p->pAssociatePhrase[i].pPhrase != NULL) free (p->pAssociatePhrase[i].pPhrase); free (p->pAssociatePhrase); free (p); } /*************************************************************************** * The File format of Turbo Linux Input Method * * symbol len meaning * cur_table sizeof (hz_input_table) the same as CCE * n sizeof (long) total phrase * pItem n * sizeof (ITEM) read Item * **************************************************************************/ int SaveLoadInputMethod (hz_input_table *cur_table, char *filename) { int nread, i, j; FILE *fd; fd = fopen(filename, "wb"); if (fd == NULL) { error("Cannot open input method %s", filename); fclose(fd); return 0; } nread = fwrite (cur_table, sizeof(hz_input_table), 1, fd); if (nread != 1) { error("Cannot read file header %s", filename); return 0; } if (strcmp(MAGIC_NUMBER, cur_table->magic_number)) { printf("is not a valid tab file\n\n"); return 0; } fwrite (cur_table->item, sizeof(ITEM) , cur_table->TotalChar, fd); for (i = 0; i < MAX_USHORT; i++) { u_short m = i; if (cur_table->pAssociatePhrase[i].total == 0) continue; fwrite (&m, sizeof (u_short), 1, fd); fwrite (&cur_table->pAssociatePhrase[i], sizeof (AssociatePhrase), 1, fd); for (j = 0; j < cur_table->pAssociatePhrase[i].total; j++) fwrite (&cur_table->pAssociatePhrase[i].pPhrase[j]->nPhrase, sizeof (long), 1, fd); } fclose (fd); return 1; } int DumpLoadInputMethod (HzInputTable_T *p, char *filename) { int i; FILE *fp; TL_SysPhrase_T *q = p->pSysPhrase; hz_input_table *cur_table = p->cur_table; fp = fopen(filename, "wt"); if (fp == NULL) { error("Cannot open input method %s", filename); fclose(fp); return 0; } fprintf (fp, "Total = %ld\n", (u_long) cur_table->TotalChar); for (i = 0; i < (int) cur_table->TotalChar; i++) { char buf[256]; TL_GetPhrase (q, cur_table->item[i].nPhrase, buf); fprintf (fp, "%s::0x%lx, 0x%lx \n", buf, cur_table->item[i].key1, cur_table->item[i].key2); } fclose (fp); return 1; } static TL_SysPhrase_T *pDefaultSysPhrase = NULL; static int qcmp (void *t1, void *t2) { u_long c1, c2; ITEM *a = (ITEM *) t1, *b = (ITEM*) t2; if (a->key1 > b->key1) return 1; if (a->key1 < b->key1) return -1; if (a->key2 > b->key2) return 1; if (a->key2 < b->key2) return -1; /* { static char p1[256], p2[256]; int len1, len2; TL_GetPhrase (a->nPhrase, p1); TL_GetPhrase (b->nPhrase, p2); len1 = strlen (p1); len2 = strlen (p2); if (len1 > len2) return 1; else if (len1 < len2) return -1; } */ TL_GetPhraseFreq (pDefaultSysPhrase, a->nPhrase, &c1); TL_GetPhraseFreq (pDefaultSysPhrase, b->nPhrase, &c2); if (c1 > c2) return 1; else if (c1 < c2) return -1; return 0; } void SortPhraseItem (TL_SysPhrase_T *q, hz_input_table *cur_table) { ITEM *p = cur_table->item; int total = cur_table->TotalChar; pDefaultSysPhrase = q; qsort (p, total, sizeof(ITEM), qcmp); }