/* UNICON PROJECT Copyright (C) 1999 TLDN Authors: Li Qi Chen Arthur Ma Justin Yu Homepage: http://turbolinux.com.cn/TLDN/chinese/project/unicon/index.html Mailinglist: unicon@turbolinux.com.cn Download: http://turbolinux.com.cn/TLDN/chinese/project/unicon/download.html 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Imm Standard Interfaces */ #include #include #include #include #include #include #include #include #include #include "xl_hzinput.h" //#include "HL_Debug.h" #define CODING_SINGLE_BYTE 0x01 #define CODING_DOUBLE_BYTES 0x02 #define CODING_FOUR_BYTES 0x04 hz_input_table *IntCode_Init(void) { hz_input_table *table; int i,index; table = malloc(sizeof(hz_input_table)); if (table == NULL) return NULL; strcpy(table->magic_number,MAGIC_NUMBER); strcpy(table->ename, "IntCode"); strcpy(table->cname, "¡¾ÄÚÂë¡¿"); strcpy(table->selkey, "0123456789"); //printf("%s", table->selkey); table->last_full = 1; for(i = 0; i < 128; i++) { table->KeyMap[i] = 0; if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'f')) { if (i >= '0' && i <= '9') index = i - '0'; else index = i -'a' + 10; table->KeyMap[i] = index; table->KeyName[index] = toupper(i); } //printf("%d---%d,",i,table->KeyMap[i]); } return table; } int ConfigureInputArea (HzInputTable_T * pHzInputTable, int nSelectionLen) { pHzInputTable->MaxSelectLen = nSelectionLen; return 1; } void ResetInput(HzInputTable_T * pHzInputTable) { bzero (pHzInputTable->InpKey, sizeof(pHzInputTable->InpKey)); bzero (pHzInputTable->seltab, sizeof(pHzInputTable->seltab)); pHzInputTable->MultiPageMode = 0; pHzInputTable->NextPageIndex = 0; pHzInputTable->CurrentPageIndex = 0; pHzInputTable->CurSelNum = 0; pHzInputTable->InputCount = 0; pHzInputTable->InputMatch = 0; pHzInputTable->val1 = 0; } void ClearSelection(HzInputTable_T * pHzInputTable) { pHzInputTable->MultiPageMode = 0; pHzInputTable->NextPageIndex = 0; pHzInputTable->CurrentPageIndex = 0; pHzInputTable->CurSelNum = 0; } void IntCode_FindMatchKey(HzInputTable_T *pHzInputTable) { unsigned long Key; if (pHzInputTable->val1 == CODING_FOUR_BYTES) Key = (pHzInputTable->InpKey[0] << 28) | (pHzInputTable->InpKey[1] << 24) | (pHzInputTable->InpKey[2] << 20) | (pHzInputTable->InpKey[3] << 16) | (pHzInputTable->InpKey[4] << 12) | (pHzInputTable->InpKey[5] << 8); else Key = (pHzInputTable->InpKey[0] << 12) | (pHzInputTable->InpKey[1] << 8); switch(pHzInputTable->InputCount) { case 3: if (pHzInputTable->val1 == CODING_DOUBLE_BYTES) { pHzInputTable->StartKey = Key + (pHzInputTable->InpKey[2] << 4); pHzInputTable->EndKey = pHzInputTable->StartKey + 0x0F; } else pHzInputTable->StartKey = pHzInputTable->EndKey = 0; /* not display selection */ break; case 6: pHzInputTable->StartKey = Key + 0x30; pHzInputTable->EndKey = Key + 0x39; break; default: pHzInputTable->StartKey = pHzInputTable->EndKey = 0; } } void IntCode_FillMatchChars(HzInputTable_T *pHzInputTable, int index) { int MaxSel = 10, i; int CurSelNum = 0; if (pHzInputTable->InputCount < 2) return; if (pHzInputTable->InputCount == 6) { while( CurSelNum < MaxSel && index <= pHzInputTable->EndKey) { pHzInputTable->seltab[CurSelNum][0] = (char)((index & 0xFF000000) >> 24); pHzInputTable->seltab[CurSelNum][1] = (char)((index & 0x00FF0000) >> 16); pHzInputTable->seltab[CurSelNum][2] = (char)((index & 0x0000FF00) >> 8); pHzInputTable->seltab[CurSelNum][3] = (char)((index & 0x000000FF)); pHzInputTable->seltab[CurSelNum][4] = '\0'; CurSelNum++; index++; } } else { while( CurSelNum < MaxSel && index <= pHzInputTable->EndKey) { pHzInputTable->seltab[CurSelNum][0] = index / 256; pHzInputTable->seltab[CurSelNum][1] = index % 256; pHzInputTable->seltab[CurSelNum][2] = '\0'; CurSelNum++; index++; } } pHzInputTable->CurSelNum = CurSelNum; for(i = CurSelNum; i < 16; i++) pHzInputTable->seltab[i][0] = '\0'; /* zero out the unused area */ pHzInputTable->InputMatch = pHzInputTable->InputCount; if ( index <= pHzInputTable->EndKey && CurSelNum == MaxSel && MaxSel == 10) { /* has another matched key, so enter MultiPageMode, has more pages */ pHzInputTable->NextPageIndex = index; pHzInputTable->MultiPageMode = 1; } else if (pHzInputTable->MultiPageMode) { pHzInputTable->NextPageIndex = pHzInputTable->StartKey; /* rotate selection */ } else pHzInputTable->MultiPageMode = 0; } int Intcode_HZFilter(HzInputTable_T *pHzInputTable, unsigned char key, char *buff, int *len) { int inkey = 0; char *pSelChar = NULL; int nSelIndex; // printf ("In Intcode_HZFilter................\n"); switch ( key ) { case '\010': /* BackSpace Ctrl+H */ case '\177': /* BackSpace */ if (pHzInputTable->InputCount > 0) { pHzInputTable->InpKey[--pHzInputTable->InputCount]=0; if (pHzInputTable->InputCount == 2) { pHzInputTable->val1 = 0; ClearSelection(pHzInputTable); } if (pHzInputTable->InputCount == 0) ResetInput(pHzInputTable); else if (pHzInputTable->InputCount > 2) { IntCode_FindMatchKey(pHzInputTable); pHzInputTable->MultiPageMode = 0; pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey; IntCode_FillMatchChars(pHzInputTable, pHzInputTable->StartKey); } } else return 0; break; case '\033': /* ESCAPE */ if (pHzInputTable->InputCount > 0) ResetInput(pHzInputTable); else return 0; break; case '-': case ',': if ( pHzInputTable->MultiPageMode ) { if ( pHzInputTable->CurrentPageIndex > pHzInputTable->StartKey) pHzInputTable->CurrentPageIndex = pHzInputTable->CurrentPageIndex - 10; else pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey; IntCode_FillMatchChars(pHzInputTable, pHzInputTable->CurrentPageIndex); } else return 0; break; case '.': case '=': if ( pHzInputTable->MultiPageMode ) { pHzInputTable->CurrentPageIndex = pHzInputTable->NextPageIndex; IntCode_FillMatchChars(pHzInputTable, pHzInputTable->CurrentPageIndex); } else return 0; break; case ' ': if (pHzInputTable->CurSelNum == 0 ) return 0; if ( pHzInputTable->seltab[0][0] ) { strcpy(buff, pHzInputTable->seltab[0]); *len = strlen(buff); ResetInput(pHzInputTable); return 2; } break; default: inkey = pHzInputTable->cur_table->KeyMap[key]; pSelChar = strchr(pHzInputTable->cur_table->selkey, key); nSelIndex = pSelChar - pHzInputTable->cur_table->selkey; if (pSelChar && pHzInputTable->CurSelNum > 0 && pHzInputTable->seltab[nSelIndex][0]) { strcpy(buff, pHzInputTable->seltab[nSelIndex]); *len = strlen(buff); ResetInput(pHzInputTable); return 2; } //printf("nSelIndex = %d inkey = %d, InputCount = %d, key = %c, Coding = %ld\n", nSelIndex, inkey,pHzInputTable->InputCount, key, pHzInputTable->val1); switch(pHzInputTable->InputCount % 4) { case 0: /* 8-F */ if (inkey < 8) { //pHzInputTable->val1 = CODING_SINGLE_BYTE; return 0; } else { if ((pHzInputTable->val1 & CODING_FOUR_BYTES) && (pHzInputTable->InputCount == 4) && (pHzInputTable->InpKey[pHzInputTable->InputCount - 4] == 8) && (pHzInputTable->InpKey[pHzInputTable->InputCount - 3] == 4) && (pHzInputTable->InpKey[pHzInputTable->InputCount - 2] == 3) && (pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 1) && (inkey > 9)) { return 0; } else { pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey; } } break; case 1: /* 0-F */ if (((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 8) && (inkey == 0)) || ((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 15) && (inkey == 15))) //0x08 or 0xFF is invalid { return 0; } else { pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey; if (pHzInputTable->InputCount == 6) { IntCode_FindMatchKey(pHzInputTable); pHzInputTable->MultiPageMode = 0; pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey; IntCode_FillMatchChars(pHzInputTable, pHzInputTable->StartKey); pHzInputTable->InpKey[pHzInputTable->InputCount++] = 3; } } break; case 2: /* A-F */ if (inkey < 3) { return 0; } if (inkey == 3) { if (pHzInputTable->InputCount < 4) { if ((pHzInputTable->InpKey[pHzInputTable->InputCount - 2] == 8) && (pHzInputTable->InpKey[pHzInputTable->InputCount - 1] <= 4) && (pHzInputTable->InpKey[pHzInputTable->InputCount - 1] >= 1)) { pHzInputTable->val1 = CODING_FOUR_BYTES; ClearSelection(pHzInputTable); pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey; } else { return 0; } } else { pHzInputTable->val1 = CODING_FOUR_BYTES; ClearSelection(pHzInputTable); pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey; } } else { //if (pHzInputTable->val1) //{ // return 0; //} //else { pHzInputTable->val1 = CODING_DOUBLE_BYTES; pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey; IntCode_FindMatchKey(pHzInputTable); pHzInputTable->MultiPageMode = 0; pHzInputTable->CurrentPageIndex = pHzInputTable->StartKey; IntCode_FillMatchChars(pHzInputTable, pHzInputTable->StartKey); } } break; case 3: /* output char */ /* A1A1-FEFE */ if (((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 7) && (inkey == 15)) || ((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 15) && (inkey == 15)) || ((pHzInputTable->InpKey[pHzInputTable->InputCount - 1] == 3) && (inkey > 9))) //0x7F or 0xFF or 3A-3F is invalid { return 0; } else { if (pHzInputTable->val1 & CODING_DOUBLE_BYTES) { pHzInputTable->seltab[0][0] = (pHzInputTable->InpKey[0] << 4) | pHzInputTable->InpKey[1]; pHzInputTable->seltab[0][1] = (pHzInputTable->InpKey[2] << 4) | inkey ; pHzInputTable->seltab[0][2] = '\0'; //DebugLog("double bytes %s\n", seltab[0]); strcpy(buff, pHzInputTable->seltab[0]); *len = strlen(buff); ResetInput(pHzInputTable); return 2; } if ((pHzInputTable->val1 & CODING_FOUR_BYTES) && (pHzInputTable->InputCount == 3) && (pHzInputTable->InpKey[pHzInputTable->InputCount - 2] == 4) && (inkey > 1)) { return 0; } if ((pHzInputTable->val1 & CODING_FOUR_BYTES) && (pHzInputTable->InputCount == 7)) { pHzInputTable->seltab[0][0] = (pHzInputTable->InpKey[0] << 4) | pHzInputTable->InpKey[1]; pHzInputTable->seltab[0][1] = (pHzInputTable->InpKey[2] << 4) | pHzInputTable->InpKey[3]; pHzInputTable->seltab[0][2] = (pHzInputTable->InpKey[4] << 4) | pHzInputTable->InpKey[5]; pHzInputTable->seltab[0][3] = (pHzInputTable->InpKey[6] << 4) | inkey; pHzInputTable->seltab[0][4] = '\0'; //write(tty_fd, seltab[0], 4); strcpy(buff, pHzInputTable->seltab[0]); *len = strlen(buff); ResetInput(pHzInputTable); return 2; } pHzInputTable->InpKey[pHzInputTable->InputCount++] = inkey; } break; } } /* switch */ return 1; } int GetSelectDisplay (HzInputTable_T * pHzInputTable, char *strBuf, int nBufLen) { int i, pos = 0,len; iconv_t cd; wchar_t result[1]; char *in,*out; int buflen; if (pHzInputTable->MultiPageMode && pHzInputTable->CurrentPageIndex != pHzInputTable->StartKey) /* not first page */ { strcpy(strBuf + pos, "< "); pos += 2; } cd = iconv_open("ucs-2", nl_langinfo(CODESET)); for( i = 0; i < pHzInputTable->CurSelNum; i++ ) { if (!pHzInputTable->seltab[i][0]) break; len = strlen(pHzInputTable->seltab[i]); in = (char *)pHzInputTable->seltab[i]; out = (char *) result; buflen = len; if (iconv(cd,&in,&buflen,&out,&buflen) == -1) { pHzInputTable->seltab[i][0] = 0xa1; pHzInputTable->seltab[i][1] = 0xa1; pHzInputTable->seltab[i][2] = 0x0; pHzInputTable->seltab[i][3] = 0x0; len = 2; } if (pos + len + 3 > nBufLen) break; sprintf(strBuf + pos, "%d%s ", i, pHzInputTable->seltab[i]); pos += len + 2; //printf("<%d> %#lx\n",i, *(long*)pHzInputTable->seltab[i]); } if ( pHzInputTable->MultiPageMode && pHzInputTable->NextPageIndex != pHzInputTable->StartKey) /* not last page */ { strcpy(strBuf + pos, "> "); pos += 2; } strBuf[pos] = '\0'; return pHzInputTable->CurSelNum ? 1 : 0; } int GetInputDisplay (HzInputTable_T * pHzInputTable, char *buf) { int i; for( i = 0; i < pHzInputTable->InputCount ; i++) sprintf(buf + i, "%c", pHzInputTable->cur_table->KeyName[pHzInputTable->InpKey[i]]); buf[pHzInputTable->InputCount] = '\0'; return pHzInputTable->InputCount ? 1: 0; } /* ********************** Now the interface functions *********************** */ static IMM_CLIENT *IMM_open (char *szFileName, long type) { HzInputTable_T *pHzInputTable_T; IMM_CLIENT *pIMM_CLIENT; hz_input_table *phz_input_table; phz_input_table = IntCode_Init(); if (phz_input_table == NULL) return NULL; pHzInputTable_T = (HzInputTable_T *) malloc (sizeof (HzInputTable_T)); if (pHzInputTable_T == NULL) return NULL; pIMM_CLIENT = (IMM_CLIENT *) malloc (sizeof (IMM_CLIENT)); if (pIMM_CLIENT == NULL) { free (pHzInputTable_T); free (phz_input_table); return NULL; }; ResetInput(pHzInputTable_T); ConfigureInputArea(pHzInputTable_T, 48); // SetPhraseBuffer (&pIMM_CLIENT->m, pIMM_CLIENT->buf, sizeof (pIMM_CLIENT->buf)); pIMM_CLIENT->pImmClientData = (void *) pHzInputTable_T; pHzInputTable_T->cur_table = phz_input_table; return pIMM_CLIENT; } static int IMM_save (IMM_CLIENT *p, char *szFileName) { return 1; } static int IMM_close (IMM_CLIENT *p) { HzInputTable_T *pClient = (HzInputTable_T *) p->pImmClientData; free (pClient->cur_table); free (p->pImmClientData); free (p); return 1; } /* Indepent Modules support */ static int IMM_KeyFilter (IMM_CLIENT *p, u_char key, char *buf, int *len) { buf[0] = '\0'; *len = 0; return Intcode_HZFilter ((HzInputTable_T *) p->pImmClientData, key, buf, len); } /* Input Area Configuration & Operation */ static int IMM_ConfigInputArea (IMM_CLIENT *p, int SelectionLen) { return ConfigureInputArea ( (HzInputTable_T *) p->pImmClientData, SelectionLen); } static int IMM_GetInputDisplay (IMM_CLIENT *p, char *buf, long buflen) { return GetInputDisplay((HzInputTable_T *) p->pImmClientData, buf); } static int IMM_GetSelectDisplay (IMM_CLIENT *p, char *buf, long buflen) { return GetSelectDisplay((HzInputTable_T *) p->pImmClientData, buf, buflen); } int IMM_ResetInput (IMM_CLIENT *p) { //char buf[32]; //int len; /* Send Esc */ ResetInput ((HzInputTable_T *) p->pImmClientData); return 1; } PhraseItem * IMM_pGetItem (IMM_CLIENT *p, u_long n) { return NULL; } /* Phrase Operation */ static int IMM_AddPhrase (IMM_CLIENT *pClient, PhraseItem *p) { return 1; } static int IMM_ModifyPhraseItem (IMM_CLIENT *p, long n, PhraseItem *pItem) { return 1; } static int IMM_Flush () { return 1; } #ifdef __cplusplus extern "C" #endif struct ImmOperation ImmOp_Ptr = { "ÄÚÂë", "HCON Chinese Input Version 3.0", "Author:Dianzhi Wang", IMM_CCE | IMM_LC_GB2312 << 24, IMM_open, IMM_save, IMM_close, /* Indepent Modules support */ IMM_KeyFilter, IMM_ResetInput, /* Input Area Configuration & Operation */ IMM_ConfigInputArea, IMM_GetInputDisplay, IMM_GetSelectDisplay, IMM_pGetItem, IMM_AddPhrase, IMM_ModifyPhraseItem, IMM_Flush, }; #ifdef __CCE_HZINPUT_DEBUG__ int test (long a, PhraseItem *p) { printf ("%s\n", p->szPhrase); return 1; } /* gcc -g -I../include -I. -D__CCE_HZINPUT_DEBUG__ xl_hzinput.c CCE_hzinput.c */ int main () { IMM_CLIENT *pImm; char *szTest = "wa"; //ng"; int i, j; long n; PhraseItem *p; PhraseItem a; pImm = ImmOp_Ptr.open ("../../datas"); ///pinyin.tab"); //"../../datas/ziranma.tab"); pImm->m.szPhrase = pImm->buf; printf ("\n"); for (i = 0; i < strlen (szTest); i++) { char buf[256]; n = ImmOp_Ptr.KeyFilter (pImm, szTest[i]); ImmOp_Ptr.GetInputDisplay (pImm, buf, sizeof (buf)), printf ("Input::%s\n", buf); ImmOp_Ptr.GetSelectDisplay (pImm, buf, sizeof (buf)); printf ("Selection::%s\n", buf); printf ("each select test...\n"); for (j = 0; j < n; j++) { p = IMM_pGetItem (pImm, j); if (p != NULL) printf ("%s,", p->szPhrase); } printf ("\n"); } p = ImmOp_Ptr.DoSelectItem (pImm, 0); if (p != NULL) printf ("you select : 0 ==> %s\n", p->szPhrase); printf ("resuming....\n"); n = ImmOp_Ptr.RestoreToLastStep (pImm); for (j = 0; j < n; j++) { p = IMM_pGetItem (pImm, j); if (p != NULL) printf ("%s,", p->szPhrase); } printf ("\n"); ImmOp_Ptr.PageUp (pImm); ImmOp_Ptr.PageDown (pImm); ImmOp_Ptr.close (pImm); return 1; } #endif