/* vi: set sw=4 ts=4: */ /* * CCE - Console Chinese Environment - * Copyright (C) 1998-2003 Rui He (rhe@3eti.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define SUPPORT_ASSOCIATE #define MAX_ASSOCIATE_CANDIATES 8 /* 10 */ #ifdef SUPPORT_ASSOCIATE static unsigned char LastOutputChar[2]; int LoadAssociateFile(hz_input_table *table, const char *filename) { AssociateHeader AscHeader; char fname[CCE_PATHNAME_MAX+1]; if (!table) return -1; if (!(table->AssocFile = fopen( filename, R_CNTRL))) { strcpy(fname, CCELIB "/"); if (strlen(fname) + strlen(filename) >= CCE_PATHNAME_MAX) return -1; /* buffer overrun */ strcat(fname, filename); table->AssocFile = fopen( fname, R_CNTRL); } if (table->AssocFile == NULL || fread(&AscHeader, sizeof(AscHeader), 1, table->AssocFile) != 1 || strcmp(ASSOCIATE_MAGIC_NUMBER, AscHeader.MagicNum) ) { warn("Load Assoc File %s error!\n", filename); if (table->AssocFile) fclose(table->AssocFile); table->AssocFile = NULL; return -1; } { table->AscEncoding = AscHeader.Encoding; /* for calculating index */ table->AscMinIndex = AscHeader.MinIndex; table->AscMaxIndex = AscHeader.MaxIndex; table->AscPhraseOffset = AscHeader.PhraseOffset; return 0; } warn("Assoc File %s is using an incompatible encoding with the input method!\n", filename); fclose(table->AssocFile); table->AssocFile = NULL; return -1; } int FindAssociateKeyAndFill(unsigned char LastChar[]) { int ofs[2], index; unsigned char myLastChar[2]; /* in AscEncoding */ LastOutputChar[0] = LastChar[0]; LastOutputChar[1] = LastChar[1]; /* save it */ if (!cur_table->AssocFile) return 0; if ( ConvertEncoding_Char(lInfo.sysCoding, cur_table->AscEncoding, LastChar[0], LastChar[1], myLastChar, myLastChar+1) == -1) /* failed to convert */ return 0; index = CalculateCharIndex(cur_table->AscEncoding, myLastChar[0], myLastChar[1]); if (index < cur_table->AscMinIndex || index >= cur_table->AscMaxIndex) /* not within valid range */ return 0; index -= cur_table->AscMinIndex; if (fseek(cur_table->AssocFile, index * sizeof(int) + sizeof(AssociateHeader), SEEK_SET) || fread(ofs, sizeof(int), 2, cur_table->AssocFile) != 2) return 0; /* some error */ StartIndex = ofs[0] + cur_table->AscPhraseOffset; EndIndex = ofs[1] + cur_table->AscPhraseOffset; CurrentPageIndex = StartIndex; /* update the current page pointer */ FillAssociateChars(StartIndex); if (CurSelNum > 0) { IsDirectSelect = 0; /* !cur_table->FirstInputSelectKeyConflict; */ IsAssociateMode = 1; DisplayAssociateInput(); DisplaySelection(); /* using the SelTab */ } return CurSelNum; } int FillAssociateChars(int index) { unsigned char str[MAX_PHRASE_LENGTH+1]; int i, CurLen = 0, len = 0, converted; if (index < StartIndex) index = StartIndex; if (StartIndex == index) CurrentPage = 0; if (CurrentPage < MAX_PAGE_INDEX) SavedPageIndex[CurrentPage] = index; for(CurSelNum = 0; CurSelNum < /*cur_table->MaxDupSel*/ MAX_ASSOCIATE_CANDIATES && index < EndIndex && CurLen < cur_table->SelAreaWidth-3; index += len+1) { /* -2 for < > */ if (fseek( cur_table->AssocFile, index, SEEK_SET ) || fread( str, 1, sizeof(str), cur_table->AssocFile ) < 2) break; /* error occurs */ str[MAX_PHRASE_LENGTH] = '\0'; /* for safety reason */ len = strlen(str); if (len & 1) len--; converted = 1; for(i = 0; i < len; i += 2) { if (ConvertEncoding_Char(cur_table->AscEncoding, lInfo.sysCoding, str[i], str[i+1], str+i, str+i+1) == -1) { converted = 0; break; } } if (converted) /* success */ { strncpy(SelTab[CurSelNum],str, len); SelTab[CurSelNum++][len] = '\0'; /* terminate */ CurLen += len + 2; /* we plus 2 for SELECT KEY and SPACE after it */ } } if (CurSelNum == 0) return 0; /* no match found */ if ( index < EndIndex /* && CurSelNum == cur_table->MaxDupSel */ ) { NextPageIndex = index; MultiPageMode = 1; } else if (MultiPageMode) { NextPageIndex = StartIndex; /* rotate selection */ } return CurSelNum; } void DisplayAssociateInput(void) { int n; char buf[MAX_INPUT_LENGTH]; int StartPos = cur_table->InputAreaX; int EndPos = cur_table->InputAreaWidth + cur_table->InputAreaX; if (cur_table->InputType == INPUT_TYPE_INTCODE) n = snprintf(buf, sizeof(buf), "%c%c:", LastOutputChar[0], LastOutputChar[1]); else n = snprintf(buf, sizeof(buf), " %s %c%c:", LianXiangStr[(int)lInfo.sysCoding ], LastOutputChar[0], LastOutputChar[1]); InputAreaOutput(lInfo.sysCoding /* cur_table->AscEncoding */, StartPos, buf, INPUT_FGCOLOR,INPUT_BGCOLOR); StartPos += n; while(StartPos < EndPos) pVideoInfo->input_sput(StartPos++, ' ', INPUT_FGCOLOR,INPUT_BGCOLOR); /* output a space */ } int Associate_HZFilter(int tty_fd, unsigned char key) { int SelKeyIndex; char *SelKeyStr; char *is_sel_key = (char*)0; if (CurSelNum <= 0) return 0; /* we have no candidates? we don't handle it it's for safety reason only */ SelKeyStr = ( IsDirectSelect ? cur_table->selkey : cur_table->Shift_SelKey); if ((is_sel_key = strchr( SelKeyStr, key))) /* not NULL, we fount it */ { SelKeyIndex = is_sel_key - SelKeyStr; if (SelKeyIndex < CurSelNum && SelTab[SelKeyIndex][0]) { OutputSelection(lInfo.sysCoding, tty_fd, SelTab[SelKeyIndex]); return 1; /* if In DirectSelect and it's a valid select key, output and return */ } } if (MultiPageMode) { if (index(/*cur_table->pageprevkey*/ ASSOCIATE_PAGEPREV_KEYS , key)) { if (CurrentPage != 0) { if (--CurrentPage < MAX_PAGE_INDEX) CurrentPageIndex = SavedPageIndex[CurrentPage]; else /* These index are file offsets, pointing to strings ending with 0, so at least 3*10 */ CurrentPageIndex -= 3 * MAX_ASSOCIATE_CANDIATES; /* 2 bytes(1 Chinese char) + 1 '\0' */ FillAssociateChars(CurrentPageIndex); DisplaySelection(); return 1; /* we handled it and stay in AssociateMode */ } } else if (index(/*cur_table->pagenextkey*/ ASSOCIATE_PAGENEXT_KEYS , key) && CurSelNum > 0 ) { if (NextPageIndex <= CurrentPageIndex) /* last page, need to rorate */ CurrentPage = 0; else CurrentPage++; CurrentPageIndex = NextPageIndex; FillAssociateChars(CurrentPageIndex); DisplaySelection(); return 1; /* we handled it and stay in AssociateMode */ } } #if 0 switch ( key ) { case '\010': /* BackSpace Ctrl+H */ case '\177': /* BackSpace */ case '\033': /* ESCAPE */ break; case ' ': if ( SelTab[0][0] ) /* output first item */ { OutputSelection(lInfo.sysCoding, tty_fd, SelTab[0]); return 1; /* we handled it and no need to reset */ } break; default: /* we don't handle any other keys */ break; } #endif ResetInput(1,1); /* clear everything IsAssociateMode will be set to 0 */ return 0; /* we didn't handle it */ } #endif