|
現在のところ、 公開している部分(マニュアル/掲示板)と 内部使用の部分(ソース)が 分離している。
■ TODO |
■ 更新履歴 |
■ 辞書について |
辞書の構造 |
{コンテクスト\001}検索パタン{\002単語}\n
というエントリの集合を辞書とする。
例文辞書の場合はコンテクストを指定する。
POBox
検索パタンと単語が一致する場合(英語の場合など)は検索パタンは省略できる。
PDBのレコード番号で辞書を区別している。
辞書のバックアップ |
PDBのバックアップビットをプレファレンスで設定可能としている。 バックアップビットを立てるとHotSyncでバックアップされる。
1.4.4以降で PBinlearnDBという学習専用辞書を用意した。 ( 記事)
データベース形式について |
メモリ内のデータベースとPDB, PRCはほとんど同じ形をしている。
PRCを作るにははbuild-prcが使えるが
PDBを作るにはword2pdbのように自力で作る。
PDB, PRC内のバックアップビットが立っているとHotSyncで自動的に
バックアップされる。
■ 関連文書 |
DB関連マニュアル (PDF)
プログラム |
#pragma pack(2) #define SEARCHAGAIN // 候補選択後、次候補を表示するかどうか #define SHOWPATINWIN // 入力パタンをもとFieldでなく候補枠に表示する #if SDK_VERSION >= 35 #include |
static int HexChar(int n) { return (n < 10 ? '0'+n : 'A'+(n-10)); } void DumpHex(int val, int x, int y) { unsigned char buf[10]; buf[0] = HexChar((val >> 12) & 0xf); buf[1] = HexChar((val >> 8) & 0xf); buf[2] = HexChar((val >> 4) & 0xf); buf[3] = HexChar(val & 0xf); WinDrawChars(buf,4,x,y); } VoidPtr GetObjPtr(Int id) { VoidPtr p = NULL; FormPtr frm; UInt16 idx; if((frm = FrmGetActiveForm())){ idx = FrmGetObjectIndex(frm, id); ErrFatalDisplayIf(idx==NULL,"GetObjPtr fail"); p = FrmGetObjectPtr(frm, idx); ErrFatalDisplayIf(p==NULL,"Null Ptr"); } return p; } Boolean BackupBit(DmOpenRef dic) { LocalID id; UInt16 cardno; UInt16 attr; DmOpenDatabaseInfo(dic,&id,NULL,NULL,&cardno,NULL); DmDatabaseInfo(cardno,id,NULL,&attr,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL); return (attr & dmHdrAttrBackup ? true : false); } void SetBackupBit(DmOpenRef dic,int backup) { LocalID id; UInt16 cardno; UInt16 attr; DmOpenDatabaseInfo(dic,&id,NULL,NULL,&cardno,NULL); DmDatabaseInfo(cardno,id,NULL,&attr,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); attr = (backup ? (attr | dmHdrAttrBackup) : (attr & ~dmHdrAttrBackup)); DmSetDatabaseInfo(cardno,id,NULL,&attr,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } Boolean Lock(void) // HackのLockをこころみ、成功すればtrueを返す { Err err; UInt32 locked; err = FtrGet(CREATORID,FEATURE_LOCK,&locked); if(err) locked = 0; if(locked == 0){ FtrSet(CREATORID,FEATURE_LOCK,1); // Lock return true; } return false; } void Unlock(void) { FtrSet(CREATORID,FEATURE_LOCK,0); // UnLock } static void GetFeaturePref(int option, UInt32 *featurep, int defaultval) // // Featureとしてセーブされたオプションを取得する。 // 設定されていない場合はデフォルト値を設定する。 // { Err err; err = FtrGet(CREATORID,option,featurep); if(err){ *featurep = (UInt32)defaultval; FtrSet(CREATORID,option,*featurep); } } #ifdef USEVFS FileRef CheckVFSDict() // // CLIEのメモリースティックのような外部ファイルシステムが // 存在するか調べ、存在する場合はFileRefを返す // { Err err; UInt32 vfsMgrVersion; UInt32 volIterator; UInt16 volRefNum; FileRef fileRef; // VFS Managerが存在するかチェック err = FtrGet(sysFileCVFSMgr, vfsFtrIDVersion, &vfsMgrVersion); if(err) return NULL; // 外部メモリが存在しない // マウントされているボリュームを取得する。複数マウントされて // いる場合は最後のものを返す。 volIterator = expIteratorStart; for(;;){ err = VFSVolumeEnumerate(&volRefNum,&volIterator); if(err) return NULL; if(volIterator == expIteratorStop) break; } // POBox辞書をオープン err = VFSFileOpen(volRefNum,"/PALM/Programs/POBox/PBInlineDB.pdb", vfsModeRead,&fileRef); if(err) return NULL; // POBox辞書が存在しない return fileRef; } #endif |
Err PBInline(FieldPtr fld, EventPtr e) // // sysTrapFldHandleEvent() の置き換え(Hack)関数 // { EventType event; Global *g; UInt32 ftrvalue; UInt32 enable; UInt32 shift; UInt32 selection; // 選択領域 - 前に選択した領域が現在の選択領域と同じならばPOBox継続と思う FormPtr frm; FldHandleEventTrapFunc *trapfunc; UInt16 c; Err err; Boolean poboxinprogress; int i; // POBoxPref pref; UInt16 prefsize; UInt16 wb,we; UInt dbmode; MemHandle h; UChar *s; // 2000/11/11 04:47:17 UInt alarmamp,sysamp,defamp; // デフォルトの音量 UInt pbalarmamp,pbsysamp,pbdefamp; // 音を消すためのもの if(e->eType == nilEvent) return 1; // 2001/7/23 Stowaway Keyboard対応? SndGetDefaultVolume(&alarmamp,&sysamp,&defamp); pbalarmamp = pbsysamp = pbdefamp = 0; // オリジナルのトラップを取得 FtrGet(CREATORID,1000,&ftrvalue); trapfunc = (FldHandleEventTrapFunc*)ftrvalue; // POBoxを使用するモードかどうか調べる GetFeaturePref(FEATURE_ENABLE,&enable,false); // Command+Space, キーボード呼出文字などの場合トグルする if(e->eType == keyDownEvent && (e->data.keyDown.chr == 0xf2 || // Alt-X for Palm Portable Keyboard e->data.keyDown.chr == 0x13ac || // Alt-X for Happy Hacking Keyboard e->data.keyDown.chr == 0x00d7 || // Alt-X for GoType! e->data.keyDown.chr == TOGGLECHR )){ // Palm Portable KBはCommand-なんとかとかControl-なんとかを出力しないので // 上記のような変なコードを割り当てている。 if(!enable){ // POBoxが動いていないときのシフトインジケータの状態を得て保存 shift = (UInt32)GsiEnabled(); FtrSet(CREATORID,FEATURE_SHIFT,shift); } enable = !enable; DisplayPOBoxMode((int)enable); FtrSet(CREATORID,FEATURE_ENABLE,enable); if(!enable){ GsiEnable(shift ? true : false); } return 0; } // 上ドラッグ-下ドラッグ, 下ドラッグ-上ドラッグでon/offするように (2000/11/07 12:29:39) if(e->eType == keyDownEvent){ if(e->data.keyDown.chr == nextFieldChr){ enable = true; DisplayPOBoxMode(enable); FtrSet(CREATORID,FEATURE_ENABLE,enable); return 0; } else if(e->data.keyDown.chr == prevFieldChr){ enable = false; DisplayPOBoxMode(enable); FtrSet(CREATORID,FEATURE_ENABLE,enable); FtrGet(CREATORID,FEATURE_SHIFT,&shift); GsiEnable(shift ? true : false); return 0; } } if(! enable){ GsiEnable(true); return (*trapfunc)(fld,e); } GsiEnable(false); DisplayPOBoxMode(true); // 2001/7/23 StowawayキーボードのドライバがnilEventを吐くのに // キーダウンイベントのときだけPOBox起動 if(e->eType != keyDownEvent){ UInt32 selection = 0xffffffff; // POBox入力継続中止 FtrSet(CREATORID,FEATURE_SELECTION,selection); // もともとのシステムコール呼出し return (*trapfunc)(fld,e); } // // Keyboard, Keyboard hackなどでもうまく動くようにする工夫。 // POBox終了時の選択領域がPOBox開始時の選択領域と一致した場合は // POBoxがまだ実行中だということで、空白文字や後退文字でも // POBox的処理を行なう。そうでない場合はアルファベットが入力 // されたときだけPOBox枠を表示して変換を開始する。 // poboxinprogress = false; FldGetSelection(fld,&wb,&we); err = FtrGet(CREATORID,FEATURE_SELECTION,&selection); if(!err){ if(wb != we && (wb == (UInt16)((selection & 0xffff0000) >> 16)) && (we == (UInt16)(selection & 0xffff))){ // 前の選択と同じ poboxinprogress = true; } } if(! poboxinprogress){ c = e->data.keyDown.chr; if(c < 0x20 || c >= 0x100 || (c == 0x20 && wb == we)){ return (*trapfunc)(fld,e); } } if(! Lock()){ // 二重よびだし禁止 return (*trapfunc)(fld,e); } DisplayPOBoxMode(true); if((frm = FrmGetActiveForm()) == NULL) return 0; if(FrmGetFocus(frm) == -1) return 0; #ifdef WNN_PALM_OS if(wnn_palm_init()) return 0; if(wnn_dic_enable()){ wnn_palm_term(); return 0; } #endif // グローバルデータ領域確保 g = (Global*)MemPtrNew(sizeof(Global)); ErrFatalDisplayIf(g==NULL,"Can't alloc global data"); // // 「大域変数」をFeatureに格納しておく // FtrSet(CREATORID,FEATURE_GLOBAL,(UInt32)g); g->origform = frm; g->field = fld; // // 空白文字を入力すると遅延変換 // if(e->data.keyDown.chr != 0x20){ g->useselection = poboxinprogress; EvtAddEventToQueue(e); // Fieldに入力されたイベント(キー入力とか)がPOBox枠で処理されるようにする。 } else { g->useselection = true; } ///////////////////////////////////////////////////////////////// // 辞書関連初期化 // ///////////////////////////////////////////////////////////////// // // (もしあれば)学習辞書データベースオープン 2000/11/11 21:49:39 // g->ldic = DmOpenDatabaseByTypeCreator(LDICTYPE,CREATORID,dmModeReadWrite); // 辞書データベースオープン // // 学習辞書があるときは拡張辞書は読み出し専用にする。 // (TRG Proのフラッシュに焼けるようになることを期待) 2001/1/15 // // g->dicはNULLかもしれないので注意。(1.4.x以前ではg->dicは常にnon-NULL) // dbmode = (g->ldic ? dmModeReadOnly : dmModeReadWrite); g->dic = DmOpenDatabaseByTypeCreator(DICTYPE,CREATORID,dbmode); #ifdef USEVFS // (もしあれば)外部メモリ辞書オープン 2001/5/20 // g->vdic = CheckVFSDict(); #endif // 学習辞書と固定辞書(もしあれば)の存在チェック if(g->ldic){ #ifdef USEVFS ErrFatalDisplayIf(g->dic == NULL && g->vdic == NULL, "Learning dict with no static dictionary"); #else ErrFatalDisplayIf(g->dic == NULL, "Learning dict with no static dictionary"); #endif } else { ErrFatalDisplayIf(g->dic == NULL, "No learning dictionary"); } // // 拡張辞書の数と先頭文字を調査 // #ifdef USEVFS if(g->vdic){ // // VFS(メモリースティックなど)内部に固定辞書DBがある場合 // Int32 pos; UInt8 c; UInt32 *offset,dummy; Boolean extraindexexists; UInt16 nrecords; // レコード数を取得 VFSFileDBInfo(g->vdic,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, &nrecords); // 拡張辞書のインデクスが存在するか調べる err = VFSFileDBGetRecord(g->vdic,nrecords-1,&h,(UInt8*)NULL,(UInt32*)NULL); ErrFatalDisplayIf(err,"Can't get VFS handle"); ErrFatalDisplayIf(h==NULL,"Can't open extra dictionary index"); s = MemHandleLock(h); extraindexexists = (*s == '\0'); if(extraindexexists){ StrCopy(g->extra,s+1); g->nextra = StrLen(g->extra); } MemHandleUnlock(h); MemHandleFree(h); if(!extraindexexists){ // VFSFileDBGetRecord()が遅いのでPDBファイルの内容を自力で読む。 // PDBファイルヘッダは78バイトで、その後にポインタ等が // レコードの数だけ並んでいる。 pos = 78 + (8 * 0xa00); VFSFileSeek(g->vdic,fsOriginBeginning,pos); g->nextra = nrecords - 0xa00; if(g->nextra > MAXEXTRA) g->nextra = MAXEXTRA; offset = MemPtrNew(sizeof(UInt32) * (nrecords - 0xa00)); for(i=0;i< g->nextra; i++){ VFSFileRead(g->vdic,4,&offset[i],NULL); VFSFileRead(g->vdic,4,&dummy,NULL); } for(i=0;i< g->nextra; i++){ VFSFileSeek(g->vdic,fsOriginBeginning,offset[i]); VFSFileRead(g->vdic,1,&c,NULL); g->extra[i] = c; } MemPtrFree(offset); } /* // メモリ内データベースと同様のやり方を適用した場合。 // 拡張辞書エントリをひとつずつ調べると非常に遅い! // VFSFileDBGetRecord()がいちいちメモリに展開するからと思われる for(i=0;i< g->nextra;i++){ err = VFSFileDBGetRecord(g->vdic,0xa00+i,&h,(UInt8*)NULL,(UInt32*)NULL); ErrFatalDisplayIf(err,"Can't get VFS handle"); ErrFatalDisplayIf(h==NULL,"Can't open extra dictionary area"); s0 = MemHandleLock(h); g->extra[i] = *s0; MemHandleUnlock(h); MemHandleFree(h); } */ } else #endif if(g->dic){ g->nextra = DmNumRecords(g->dic) - 0xa00; if(g->nextra > MAXEXTRA) g->nextra = MAXEXTRA; for(i=0;i< g->nextra;i++){ h = DmQueryRecord(g->dic,0xa00+i); ErrFatalDisplayIf(h==NULL,"Can't open extra dictionary area"); s = MemHandleLock(h); g->extra[i] = *s; MemHandleUnlock(h); } } else { // NOTREACHED ErrFatalDisplayIf(true,"No dict"); } // Formを呼びだせるようにするために共通データベースをオープン g->db = DmOpenDatabaseByTypeCreator(APPTYPE,CREATORID, dmModeReadWrite); ErrFatalDisplayIf(g->db==NULL,"Can't open PBInline DB"); // // プレファレンス // prefsize = sizeof(POBoxPref); if(PrefGetAppPreferences(CREATORID,0,&(g->pref),&prefsize,true) == noPreferenceFound){ g->pref.savedict = false; g->pref.dispbottom = false; g->pref.spacefortankanji = false; g->pref.righthanded = true; PrefSetAppPreferences(CREATORID,0,1,&(g->pref),sizeof(POBoxPref),true); } g->prevwascommandkey = false; g->prevwordlen = 0; g->exact = 0; g->searchlevel[0] = 0; // OpenRomaTable(g); g->rktable = InitRomaTable(); OpenPBInline(g); // PBInline画面初期化 SearchCand(g,NEWCAND); // 何故かこれが無いと動かない?? #ifdef XXXX g->patlen = 0; g->pat[g->patlen++] = (char)e->data.keyDown.chr; InsertPatAndSearch(g); #endif //GrfSetState(true,false,false); g->finish = false; ///////////////////////////////////////////////////////////////// // PBInlineのイベント処理ループ // ///////////////////////////////////////////////////////////////// do { UInt16 error; // 2000/11/11 04:50:02 // フォーム外をタップするとエラー音がするので // 一時的に音量をゼロにする SndSetDefaultVolume(&pbalarmamp,&pbsysamp,&pbdefamp); EvtGetEvent(&event, evtWaitForever); SndSetDefaultVolume(&alarmamp,&sysamp,&defamp); //if(event.eType == nilEvent) continue; if(event.eType == penDownEvent && (event.screenY < 0 || (event.screenY > 20 && g->pbform->window.windowBounds.topLeft.y + event.screenY < 160))){ MenuBarType *menu; menu = MenuGetActiveMenu(); if(! (menu && menu->attr.visible)){ // メニューが出ているとき以外は枠外をタップされると終了する EventType evt; evt.eType = keyDownEvent; // \n, \r などによりPOBox枠の終了を指示する。 // \r のときは選択領域を変化させない。(次回に継続) evt.data.keyDown.chr = '\n'; // 窓終了文字 evt.data.keyDown.chr = '\r'; // 窓終了文字 evt.data.keyDown.modifiers = 0; EvtAddEventToQueue(&evt); EvtAddEventToQueue(&event); // 本来のイベントを使う。(荒井氏による指摘) } continue; } if (AppHandleEvent(g,&event)) continue; if (SysHandleEvent(&event)) continue; if (MenuHandleEvent(NULL, &event, &error)) continue; FrmDispatchEvent(&event); } // // Applicationボタンを押した場合はすぐに別アプリに移るように // してみていたが、TODOなどではappStopEventの処理が足りないせいか // FatalErrorになってしまうので、POBox枠が出ているときは // 終了できないことにする。 // #ifndef FINISH_IF_APPBUTTON_IS_PRESSED while (! g->finish); #else while (! g->finish && event.eType != appStopEvent); if(event.eType == appStopEvent){ EvtAddEventToQueue(&event); } #endif // CloseRomaTable(g); if(g->dic) DmCloseDatabase(g->dic); if(g->ldic) DmCloseDatabase(g->ldic); #ifdef USEVFS if(g->vdic) VFSFileClose(g->vdic); #endif DmCloseDatabase(g->db); ///// Unlock(); MemPtrFree(g->rktable); MemPtrFree(g); // DisplayPOBoxMode(true); FtrGet(CREATORID,FEATURE_ENABLE,&enable); if(enable){ DisplayPOBoxMode(true); } else { DisplayPOBoxMode(false); FtrGet(CREATORID,FEATURE_SHIFT,&shift); GsiEnable(shift ? true : false); } // // 次回のPBInline()呼出しがこの呼出しに引き続くものかどうか // 判断できるようにするため、現在の領域選択状況をFeatureに記憶しておく。 // この値が変化すればPOBox処理は継続でないと判断する。 // FldGetSelection(fld,&wb,&we); selection = ((((UInt32)wb) << 16) & 0xffff0000) + ((UInt32)(we) & 0xffff); FtrSet(CREATORID,FEATURE_SELECTION,selection); #ifdef WNN_PALM_OS wnn_dic_disable(); wnn_palm_term(); #endif return 1; } |
/*
PBInline画面開始/終了 |