|
現在のところ、 公開している部分(マニュアル/掲示板)と 内部使用の部分(ソース)が 分離している。
■ 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画面開始/終了 |