PalmKanaKB
Up$Date: 2002/01/14 06:43:51 $ $Revision: 1.17 $

PalmKanaKBは、 PalmのGraffitiエリアを五十音キーボードとみなし、そのタップにより ローマ字を直接入力できるようにするHackプログラムです。 「あ」「か」のような通常のかなに加え、 「にゅう」「じょう」「げん」「って」などのような 拗音/撥音/促音などを含む読みを1操作で入力することができます。

News

特徴

ダウンロード

最新版は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 $
//
#include 

void KanaKB(EventType *event, Int32 timeout);

void EvtGetEventHack(EventType *event, Int32 timeout)
{
	KanaKB(event,timeout);
}