Up$Date: 2002/01/14 06:43:51 $ $Revision: 1.17 $ |
PalmKanaKBは、 PalmのGraffitiエリアを五十音キーボードとみなし、そのタップにより ローマ字を直接入力できるようにするHackプログラムです。 「あ」「か」のような通常のかなに加え、 「にゅう」「じょう」「げん」「って」などのような 拗音/撥音/促音などを含む読みを1操作で入力することができます。
News |
To: kanakb@quickml.com Cc: masui@csl.sony.co.jp From: (自分のメールアドレス)
特徴 |
かう きゃ か かい かん
きゅう きゅう き きい きん
くう きゅ く くい くん
きょう きょう け けい けん
こう きょ こ こい こん
ダウンロード |
最新版は0.6.1です。
キー配置 |
以下のシールをGraffitiエリアに貼って使います。
「記」をタップしてからGraffiti操作を行なうと記号を入力できます。
「P」をタップするとPOBoxをOn/Offできます§。
キー位置調整 |
HackMasterまたはX-Masterから 下図のような設定画面を呼び出すことにより 五十音キーボードの位置を設定することができます。
参考資料 |
問題点/他の操作案 |
以下は開発者向け情報 (というか覚えがき) です。 |
実装の工夫 |
ソース |
// // $Date: 2002/01/14 06:43:51 $ // $Revision: 1.17 $ // Version = 0.5.1 // #include#include "pbinline.h" #include "kanakb.h" #include "kbprefs.h" typedef Err EvtProcessSoftKeyStrokeFunc(PointType *start, PointType *end); void QueueAIUEO(int ycol); void Interpret(UInt16 xcol, UInt16 ycol, UInt16 r, UInt16 slowtap); //#define Queue(c) EvtEnqueueKey(c,0,0) void QueueAIUEO(int ycol) { Char aiueo[] = "aiueo"; EvtEnqueueKey(aiueo[ycol],0,0); } void Queue(Char *s) { for(;*s;s++) EvtEnqueueKey(*s,0,0); } Err KanaKB(PointType *start, PointType *end) { EvtProcessSoftKeyStrokeFunc *trapfunc; UInt32 ftrvalue; Int16 x,y; UInt32 dist; UInt32 ticks; UInt32 msec; UInt32 kanakbmode; UInt16 slowtap = 0; Int16 r = -1; Int16 xcol,ycol; Boolean valid; KBPref pref; Int16 xd,yd,xu,yu; // システムの漢字変換は常にoffにする TsmSetFepMode(NULL,tsmFepModeOff); FtrGet(CREATOR,FEATURE_TICKS,&ticks); FtrGet(CREATOR,FEATURE_KANAKBMODE,&kanakbmode); GetKBPreferences(&pref,true); if(kanakbmode){ FtrSet(CREATOR,FEATURE_KANAKBMODE,0); xd = start->x; yd = start->y; xu = end->x; yu = end->y; x = xu-xd; y = yu-yd; y = -y; dist = x*x+y*y; if(dist < 3){ // ペン移動なし msec = (TimGetTicks()-ticks) * 1000 / SysTicksPerSecond(); slowtap = (msec > 600 ? 2 : msec > 200 ? 1 : 0); r = 0; } else if(dist < 300){ // ペン移動あり msec = (TimGetTicks()-ticks) * 1000 / SysTicksPerSecond(); slowtap = (msec > 800 ? 2 : msec > 300 ? 1 : 0); // ペン移動方向の認識。右方向がr=1,あとは半時計回りにr=2〜4 if(x > 0){ if(y > x){ r = 2; } else if(y * -1 > x){ r = 4; } else { r = 1; } } else { x = -x; if(y > x){ r = 2; } else if(y * -1 > x){ r = 4; } else { r = 3; } } } if(r >= 0){ xcol = (xd-pref.left) * 10 / (pref.right-pref.left); ycol = (yd-pref.top) * 5 / (pref.bottom-pref.top); // POBoxのon/off指令 if(xcol == 0 && ycol == 4){ EvtEnqueueKey(TOGGLECHR,0,0); FtrSet(CREATOR,FEATURE_KANAKBMODE,0); return 0; } // 特定の場所をタップした場合だけ記号シフトモードと解釈する。 valid = true; if(xcol == 2 && ycol == 3){ valid = false; } if(r == 3 && dist > 150){ // 左方向だけ厳しくする valid = false; } if(r == 3 && (ycol == 1 || ycol == 3)){ valid = false; } if(xcol < 0 || xcol >= 10 || ycol < 0 || ycol >= 5){ valid = false; } if(valid){ Interpret(xcol,ycol,r,slowtap); return 0; } } } // オリジナルのEvtProcessSoftKeyStroke呼出し FtrGet(CREATOR,1000,&ftrvalue); trapfunc = (EvtProcessSoftKeyStrokeFunc*)ftrvalue; return (*trapfunc)(start,end); } void Interpret(UInt16 xcol, UInt16 ycol, UInt16 r, UInt16 slowtap) { switch(xcol){ case 0: if(r == 0){ switch(ycol){ case 0: Queue("wa"); break; case 1: Queue("wo"); break; case 2: Queue("n"); break; case 3: Queue("."); break; default: break; } } else { Queue("w"); } break; case 1: Queue("r"); break; case 2: if(r == 0){ switch(ycol){ case 0: Queue("ya"); break; case 1: Queue("-"); break; case 2: Queue("yu"); break; case 4: Queue("yo"); break; default: break; } } else { Queue("y"); } break; case 3: Queue(slowtap > 1 ? "mm" : "m"); break; case 4: Queue(slowtap > 2 ? "pp" : slowtap > 1 ? "p" : slowtap > 0 ? "b" : "h"); break; case 5: Queue("n"); break; case 6: Queue(slowtap > 1 ? "tt" : slowtap > 0 ? "d" : "t"); break; case 7: Queue(slowtap > 1 ? "ss" : slowtap > 0 ? "z" : "s"); break; case 8: Queue(slowtap > 1 ? "kk" : slowtap > 0 ? "g" : "k"); break; default: break; } switch(r){ // 撥音、促音など case 0: if(xcol != 0 && xcol != 2) QueueAIUEO(ycol); break; case 1: QueueAIUEO(ycol); Queue("i"); break; case 2: switch(ycol){ case 0: case 2: case 4: QueueAIUEO(ycol); Queue("u"); break; case 1: Queue("yuu"); break; case 3: Queue("you"); break; } break; case 3: if(xcol != 0 && xcol != 2){ switch(ycol){ case 0: Queue("ya"); break; case 2: Queue("yu"); break; case 4: Queue("yo"); break; default: break; } } break; case 4: QueueAIUEO(ycol); Queue("n"); break; default: break; } }
// // $Date: 2002/01/14 06:43:51 $ // $Revision: 1.17 $ // Version = 0.4.1 // #include#include "kanakb.h" typedef void EvtGetEventTrapFunc(EventType*, Int32); void GetEventFunc(EventType *event, Int32 timeout) { EvtGetEventTrapFunc *trapfunc; UInt32 ftrvalue; UInt32 ticks; UInt32 msec; RectangleType winrect; UInt32 xd,yd,xm,ym; UInt32 kanakbmode; Int32 dist; // オリジナルのEvtGetEvent()呼出し FtrGet(CREATOR,1001,&ftrvalue); trapfunc = (EvtGetEventTrapFunc*)ftrvalue; (*trapfunc)(event,timeout); switch(event->eType){ case penDownEvent: WinGetWindowBounds(&winrect); xd = event->screenX + winrect.topLeft.x; yd = event->screenY + winrect.topLeft.y; if(xd >= LEFT && xd < RIGHT && yd >= TOP && yd < BOTTOM){ // 大域変数が使えないので、ペンを押したときの座標はfeatureに格納しておく。 FtrSet(CREATOR,SCREENX,xd); FtrSet(CREATOR,SCREENY,yd); FtrSet(CREATOR,KANAKBMODE,1); // タッピングによるかな入力モード FtrSet(CREATOR,TAPLATENCY,0); // タップ後の静止時間 ticks = TimGetTicks(); // 静止時間を計算するため、タップ時のtickを記憶 FtrSet(CREATOR,TICKS,ticks); event->eType = nilEvent; // } break; case penMoveEvent: FtrGet(CREATOR,KANAKBMODE,&kanakbmode); if(kanakbmode){ WinGetWindowBounds(&winrect); FtrGet(CREATOR,SCREENX,&xd); FtrGet(CREATOR,SCREENY,&yd); xm = event->screenX + winrect.topLeft.x; ym = event->screenY + winrect.topLeft.y; dist = (((int)xm-(int)xd)*((int)xm-(int)xd)+ ((int)ym-(int)yd)*((int)ym-(int)yd)); if(dist > 300){ // Graffitiストロークの場合はタップモードを無効にする FtrSet(CREATOR,KANAKBMODE,0); } else if(dist > 4){ // タップ後ペンが移動した倍数は、タップ時から移動時までの // 時間を計測してTAPLATENCYに格納しておく。 // タップ後ペンを移動させなくてもタブレットのせいで // penMoveEventが発生してしまうことがあるので // dist <= 4 のペン移動は移動とみなさない。 // これはPalmの機種により異なるのだと思う。 FtrGet(CREATOR,TAPLATENCY,&msec); if(msec == 0){ FtrGet(CREATOR,TICKS,&ticks); msec = (TimGetTicks()-ticks) * 1000 / SysTicksPerSecond(); FtrSet(CREATOR,TAPLATENCY,msec); } } } break; case penUpEvent: FtrGet(CREATOR,KANAKBMODE,&kanakbmode); if(kanakbmode){ FtrGet(CREATOR,TAPLATENCY,&msec); if(msec == 0){ FtrGet(CREATOR,TICKS,&ticks); msec = (TimGetTicks()-ticks) * 1000 / SysTicksPerSecond(); FtrSet(CREATOR,TAPLATENCY,msec); } } break; default: break; } }
// // $Date: 2002/01/14 06:43:51 $ // $Revision: 1.17 $ // #includevoid KanaKB(EventType *event, Int32 timeout); void EvtGetEventHack(EventType *event, Int32 timeout) { KanaKB(event,timeout); }