史萊姆論壇

返回   史萊姆論壇 > 教學文件資料庫 > 作業系統操作技術文件
忘記密碼?
論壇說明

歡迎您來到『史萊姆論壇』 ^___^

您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的!

請點擊這裡:『註冊成為我們的一份子!』

Google 提供的廣告


 
 
主題工具 顯示模式
舊 2003-12-11, 08:12 PM   #1
psac
榮譽會員
 
psac 的頭像
榮譽勳章
UID - 3662
在線等級: 級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時
註冊日期: 2002-12-07
住址: 木柵市立動物園
文章: 17381
現金: 5253 金幣
資產: 33853 金幣
預設 xx手寫輸入的系統部分(Palm平台)

xx手寫輸入的系統部分

工具: IDA Pro 4.x
平台: Palm OS 3.5, Motorola 68000 指令集
下載: http://www.hwpen.net/download.htm

年初, 下了一個漢王試了一下, 覺得它的浮動表單做的比較好, 因為它在任何App下都可以冒出來. 要知道Palm是單工作的, 在一個時候只能有一個APP在執行. 當時剛剛接觸Palm, 如果要讓我實現這些功能, 還真的不知道怎麼下手. 於是想到了用IDA試試在非Windows平台的反彙編. 最後得到的這些程式碼完全說明了它是怎樣實現這些功能的. 對於Palm程序員是有參考價值的.


另外, 有幾點需要特別說明:

1. 對於它的識別引擎, 我沒有做逆向, 因為我對它後面的高深理論不瞭解也沒有興趣.
2. 因為是為了學習, 而不是破解這套軟體, 我沒有去逆向它的註冊碼算法部分. 從支持國產軟體方面考慮, 我也不會這樣做.(言下之意:漢王你可別找我麻煩 )
3. 這裡公佈的只是任何Palm書籍上都有的編程的最基礎部分, 應該不會對漢王在技術上構成什麼危害.
4. 這些可以編譯的程式碼只用於學習目的, 請勿做它用.
5. 用SetTrap的方法掛接HW_SysHandleEvent()而沒有其它措施是不安全的,因為系統在特定的時候會移動程式碼資源, 這肯定會讓系統垮掉, 應該使用DmDatabaseProtect()對這段程式碼資源加以保護. 希望漢王以後會這樣做.

// #include <windows.h>
#include <PalmOS.h>
#include <DLServer.h>
#include <PalmUtils.h>

#define version350 0x3503000
#define HW_MainForm 1000
#define RomIncompatibleAlert 1001
#define HWDefinedCmd 0xddbb

#define HW_COMMONCCHAR 0x0001
#define HW_SUBCOMMONCCHAR 0x0002
#define HW_TRA2SIMPLIFIED 0x0008
#define HW_NUMERIC 0x0010
#define HW_ENGLISH 0x0060
#define HW_SYMBOL 0x0180
#define HW_UPPER2LOWER 0x2000
#define HW_LOWER2UPPER 0x4000
#define HW_HALF2FULL 0x8000

// 表單模式
#define FOLDED 0 // 收成"V"
#define LOWER 1 // 在螢幕的下半部
#define UPPER 2 // 在螢幕的上半部
#define HIDDEN 3 // 隱藏

// 手寫系統階段
#define READY 0 // 就緒
#define ENTER 1 // 進入視窗或Form
#define LEAVE 2 // 離開視窗或Form
#define CHGFLD 3 // 切換到其它字段

typedef struct tagHW_PREF {
Boolean bInstallHW; // 是否安裝漢王手寫輸入系統. 0
Int8 al_b1; // 未被使用 1
UInt16 flags; // 標誌位 2
UInt16 RecogRange; // 識別範圍 4
Int8 RecogWaitTime; // 識別等待時間 6
Int8 PenThickness; // 筆跡粗細 7
Int8 PenColor; // 筆的顏色 8
Int8 al_b9; // 未被使用 9
Int16 ShotcutPenDownX; // 建立捷逕的起點螢幕坐標 X a
Int16 ShotcutPenDownY; // 建立捷逕的起點螢幕坐標 Y c
Int16 ShotcutPenUpX; // 建立捷逕的終點螢幕坐標 X e
Int16 ShotcutPenUpY; // 建立捷逕的終點螢幕坐標 Y 10
Boolean bSetting; // 是否正在設定建立捷逕 12
Int8 bUsingShortcut; // 是否正在使用建立捷逕 13
Boolean bSplitScreen; // 全螢幕分割 14
Boolean bHalfToFull; // 半形字串轉成全形字串 15
Boolean bUpperToLower; // 大寫字母轉成小寫字母 16
Boolean bLowerToUpper; // 小寫字母轉成大寫字母 17
Boolean bMouse; // 是否作為滑鼠使用 18
Boolean bReged; // 是否是註冊用戶: 0xff 是, 0 否. 19
Int8 MenuMode; // 0: FOLDED, 1: LOWER, 2: UPPER, 3: HIDDEN 1a
Boolean bMenuFolded; // 表單是否被收成"V" 1b
Boolean bOpenHW; // 是否啟動漢王手寫輸入 1c
Boolean bHalfScrnInput; // 是否在半屏手寫模式 1d
Boolean bRedrawMenu; // 表單是否需要重畫 1e
Int8 Phase; // 手寫系統階段 0: READY, 1: ENTER, 2: LEAVE, 3: CHGFLD 1f
} HW_PREF;

typedef struct tagHW_PENS {
UInt16 Cands[20][10]; // 候選字Buffer 0
UInt8 index; // 候選字在候選字Buffer中的上標索引 0x190/400
UInt8 b191; // not used
UInt16 InsPtPos; // 插入點偏移, 192h, 402
UInt16 CandiDispOfs; // 候選字顯示偏移 194h 404
char* AssocBuffer; // 聯想字buf 196h 406
UInt16 AssocNum; // 聯想字個數 19a 410
UInt8 AssocOfs; // 聯想字偏移 19c 412
UInt8 AssocDispOfs; // 聯想字顯示偏移 19d 413
} HW_PENS;

typedef struct tagHW_TRACE {
PointType points[2048]; // 筆跡采樣點陣列 0
UInt16 PtCount; // 筆跡采樣存放位置 2000
UInt32 dw2002; // 2002
UInt8 b2006; // 2006
UInt8 b2007; // 2007
UInt8 b2008; // 2008
} HW_TRACE;



int HW_Install(void);
void HW_Uninstall(void);

UInt16 GetRecogRange(HW_PREF* pPref)
{
UInt16 flags;

if (pPref->RecogRange)
flags = pPref->RecogRange;
else
flags = pPref->flags;

if (pPref->bHalfToFull)
flags |= 0x8000;

if (pPref->bUpperToLower)
flags |= 0x2000;

if (pPref->bLowerToUpper)
flags |= 0x4000;

return flags;
}

Int8 GetMenuMode(void)
{
Int16 x, y;

InsPtGetLocation(&x, &y);

if (y > 109)
return UPPER;
else
return LOWER;
}

char V[] = "V";

void ClearMenu(Int8 MenuMode)
{
RectangleType rc;

if (MenuMode == HIDDEN) return;

if (MenuMode == FOLDED) {
WinEraseChars(V, 1, 141, 141);
return;
}

if (MenuMode == LOWER)
RctSetRectangle(&rc, 0, 118, 160, 30);
else if (MenuMode == UPPER)
RctSetRectangle(&rc, 0, 78, 160, 30);

WinEraseRectangle(&rc, 0/*cornerDiam, 0 for square corners*/);
}

void RedrawCurForm(void)
{
FormPtr frm = FrmGetActiveForm();
WindowType* winHandle = FrmGetWindowHandle(frm);

if (winGetActiveWindow() == winHandle && FrmValidatePtr(frm))
FrmDrawForm(frm);
}

void DrawMenu(HW_PREF* pPrefs, HW_PENS* pHWPens) // a3 = pPrefs, a2 = pHWPens
{
int ofs, x, d5;
RectangleType rc;
UInt16* ptr;

if (pHWPens->index == 0)
x = 0;
else
x = pHWPens->index - 1;

if (pPrefs->MenuMode == UPPER) {
RctSetRectangle(&rc, 2, 80, 155, 25);
WinDrawRectangleFrame(dialogFrame, &rc);

// This routine does not draw in the gray color; it draws with
// alternating foreground and background pixels. That is, it uses
// the grayPattern pattern type.
WinDrawGrayLine(74, 93, 74, 104);
WinDrawGragLine(2, 92, 156, 92);
WinDrawChars("→", 2, 63, 94);

WinDrawChars("英", 2, 76, 94);
if (pPrefs->RecogRange == HW_ENGLISH) {
RctSetRectangle(&rc, 75, 93, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("數", 2, 88, 94);
if (pPrefs->RecogRange == HW_NUMERIC) {
RctSetRectangle(&rc, 87, 93, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("符", 2, 100, 94);
if (pPrefs->RecogRange == HW_SYMBOL) {
RctSetRectangle(&rc, 99, 93, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("全", 2, 112, 94);
if (pPrefs->bHalfToFull) {
RctSetRectangle(&rc, 111, 93, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("窗", 2, 124, 94);

WinDrawChars("鼠", 2, 136, 94);
if (pPrefs->bMouse) {
RctSetRectangle(&rc, 135, 93, 12, 12);
WinInvertRectangle(&rc, 0);
}
WinDrawChars("^", 1, 148, 94);
WinDrawChars("←", 2, 132, 81);
WinDrawChars("→", 2, 145, 81);

d5 = pHWPens->CandiDispOfs * 2;
ptr = pHWPens->Cands[x];

// 顯示5個候選字
if (ptr[d5] || ptr[d5 + 1]) {
for (ofs = d5; ofs < d5 + 10; ofs += 2) {
if (ptr[ofs]) {
WinDrawChars(&ptr[ofs], 2, x, 94);
x += 12;
}
else {
if (ptr[d5 + 1] <= ' ')
break;

WinDrawChars(&ptr[d5 + 1], 1, x, 94);
x += 12;
}
}
}

// 顯示10個聯想字
if (pHWPens->AssocNum) {
x = 3;
for (ofs = pHWPens->AssocDispOfs; ofs < pHWPens->AssocOfs + 20; ofs += 2) {
if (ofs - pHWPens->AssocOfs < pHWPens->AssocNum)
break;

WinDrawChars(&pHWPens->AssocBuffer[ofs], 2, x, 81);
x += 13;
}
}
}
else if (pPrefs->MenuMode == LOWER) {
RctSetRectangle(&rc, 2, 120, 155, 25);
WinDrawRectangleFrame(dialogFrame, &rc);

// This routine does not draw in the gray color; it draws with
// alternating foreground and background pixels. That is, it uses
// the grayPattern pattern type.
WinDrawGrayLine(74, 133, 74, 144);
WinDrawGragLine(2, 132, 156, 312);
WinDrawChars("→", 2, 63, 134);

WinDrawChars("英", 2, 76, 134);
if (pPrefs->RecogRange == HW_ENGLISH) {
RctSetRectangle(&rc, 75, 93, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("數", 2, 88, 134);
if (pPrefs->RecogRange == HW_NUMERIC) {
RctSetRectangle(&rc, 87, 93, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("符", 2, 100, 134);
if (pPrefs->RecogRange == HW_SYMBOL) {
RctSetRectangle(&rc, 99, 133, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("全", 2, 112, 134);
if (pPrefs->bHalfToFull) {
RctSetRectangle(&rc, 111, 133, 12, 12);
WinInvertRectangle(&rc, 0);
}

WinDrawChars("窗", 2, 124, 134);

WinDrawChars("鼠", 2, 136, 134);
if (pPrefs->bMouse) {
RctSetRectangle(&rc, 135, 133, 12, 12);
WinInvertRectangle(&rc, 0);
}
WinDrawChars("^", 1, 148, 134);
WinDrawChars("←", 2, 132, 121);
WinDrawChars("→", 2, 145, 121);

d5 = pHWPens->CandiDispOfs * 2;
ptr = pHWPens->Cands[x];

// 顯示5個候選字
if (ptr[d5] || ptr[d5 + 1]) {
for (ofs = d5; ofs < d5 + 10; ofs += 2) {
if (ptr[ofs]) {
WinDrawChars(&ptr[ofs], 2, x, 134);
x += 12;
}
else {
if (ptr[d5 + 1] <= ' ')
break;

WinDrawChars(&ptr[d5 + 1], 1, x, 134);
x += 12;
}
}
}

// 顯示10個聯想字
if (pHWPens->AssocNum) {
x = 3;
for (ofs = pHWPens->AssocDispOfs; ofs < pHWPens->AssocOfs + 20; ofs += 2) {
if (ofs - pHWPens->AssocOfs > pHWPens->AssocNum)
break;

WinDrawChars(&pHWPens->AssocBuffer[ofs], 2, x, 121);
x += 13;
}
}
}
else if (pPrefs->MenuMode == FOLDED)
WinDrawChars("V", 1, 141, 141);
}

void RedrawMenu(HW_PREF* pPrefs, char* pHWPens)
{
WinHandle winHandle = WinSetDrawWindow(WinGetDisplayWindow());

ClearMenu(pPrefs->MenuMode);
DrawMenu(pPrefs, pHWPens);
WinSetDrawWindow(winHandle);
}

FieldPtr GetCurField(FormPtr frm)
{
// Too bad to access directly FormType data member. Palm strongly disencourage
// such behaviors
if (frm->focus != noFocus &&
frm->objects[frm->focus].object.field != frmFieldObj&&
frm->objects[frm->focus].object.field != frmTableObj)
{
return TblGetCurrentField(frm->objects[frm->focus].object.field);
}

return NULL;
}

void EnqueueChChar(FieldPtr fp, UInt16* pCand, Boolean bBackspace)
{
MemHandle memHandle;
HW_PREF* pPrefs;
UInt16 InsPos;

FtrGet('HW99', 10, (UInt32 *)&memHandle);
pPrefs = (HW_PREF*)MemHandleLock(memHandle); // a2
InsPos = FldGetInsPtPosition(fp); // d3
if (bBackspace)
FldDelete(fp, InsPos - 2, InsPos);
FldInsert(fp, pCand, 2);

if (pPrefs->bReged != 0xff) {
pPrefs->bReged++;
pPrefs->bReged %= 10;
if (pPrefs->bReged == 0)
ShowNag();
}

MemHandleUnlock(memHandle);
InsPos = FldGetInsPtPosition(fp);
FldSetSelection(fp, InsPos, InsPos);
}

void GetAssoc(HW_PENS* pHWPens, UInt16 Cand)
{
pHWPens->AssocNum = 0;
pHWPens->AssocOfs = 0;
if (GetAssocFromAssocBuf(pHWPens->AssocBuffer, Cand) > 0) {
pHWPens->AssocNum = *pHWPens->AssocBuffer;
pHWPens->AssocBuffer++;
if (pHWPens->AssocNum == -1) {
pHWPens->AssocNum += *pHWPens->AssocBuffer;
pHWPens->AssocBuffer++;
}

pHWPens->AssocNum *= 2;
pHWPens->AssocOfs = 0;
}
}

void EnqueueInputKeys(FormType* frm, HW_PENS* pHWPens, UInt16 index, BOOL bAssoc)
{
FieldPtr fp = GetCurField(frm); // a3
WChar ascii;
UInt16 InsPos;

if (fp != NULL) {
if ((UInt8)pHWPens->Cands[index][0] == 0) {
ascii = *((UInt8*)&pHWPens->Cands[index][0] + 1);
if (ascii > ' ') {
EvtEnqueueKey(ascii, 0, 0);
if (++pHWPens->index == 20)
pHWPens->index = 0;
pHWPens->CandiDispOfs = 0;
pHWPens->InsPtPos = FldGetInsPtPosition(fp) + 1;
}
else if (ascii == ' ')
EvtEnqueueKey(32, 0, 0);
else if (ascii == 8)
EvtEnqueueKey(backspaceChr, 0, 0);
else if (ascii == '\n')
EvtEnqueueKey('\r', 0, 0), EvtEnqueueKey('\n', 0, 0);
}
else {
EnqueueChChar(fp, pHWPens->Cands[index], false);
if (++pHWPens->index == 20)
pHWPens->index = 0;
pHWPens->CandiDispOfs = 0;
pHWPens->InsPtPos = FldGetInsPtPosition(fp);
if (bAssoc)
GetAssoc(pHWPens, pHWPens->Cands[index][0]);
}
}
}

void AdjustCandIndex(FormPtr frm, HW_PENS* pHWPens)
{
UInt16 InsPos = FldGetInsPtPosition(GetCurField(frm)); // d3
Int16 InsOfs = InsPos - pHWPens->InsPtPos;
Int16 index;

pHWPens->InsPtPos = InsPos;
if (InsOfs > 40 || InsOfs < -40)
return;

if (pHWPens->index == 0)
index = 19;
else
index = pHWPens->index - 1; // d3 = index

if (InsOfs < 0) {
do {
if (pHWPens->Cands[index][0] == 0) {
if (pHWPens->Cands[index][1] == 0) {
if (index == 19)
pHWPens->index = 0;
else
pHWPens->index = index + 1;
return;
}
else {
InsOfs++;
if (index == 0)
index = 19;
else
index--;
}
}
else {
InsOfs += 2;
if (index == 0)
index = 19;
else
index--;
}
} while (InsOfs < 0); // 5F4C here
} // goto 5fa2
else if (InsOfs > 0) {
do {
if (pHWPens->Cands[index][0] == 0) {
if (pHWPens->Cands[index][1] == 0) {
if (index == 19)
pHWPens->index = 0;
else
pHWPens->index = index + 1;
return;
}
else {
InsOfs--;
if (index == 19)
index = 0;
else
index++;
}
}
else {
InsOfs -= 2;
if (index == 19)
index = 0;
else
index++;
}
} while (InsOfs > 0);
}

if (index == 19)
pHWPens->index = 0;
else
pHWPens->index = index + 1;
}

BOOL OnPenDown(EventPtr eventP, HW_PREF* pPrefs, HW_PENS* pHWPens, HW_TRACE* pHWTrace)
{
Coord x, y;
FormPtr frm;
Int8 MenuMode;
UInt16 screenX, screenY;

// d3 = eventP(a6)
// a2 = pPrefs
// a3 = pHWPens
// a4 = pHWTrace

x = eventP->screenX;
y = eventP->screenY;

WinWindowToDisplayPt(&x, &y);
if (x > 160 || y > 160)
return 0;

MenuMode = pPrefs->MenuMode;

switch (MenuMode)
{
case FOLDED:
if (screenX > 141 && screenX < 151 && screenY > 141 && screenY < 151)
break;
case LOWER:
if (screenY > 120 && screenY < 145)
break;
case UPPER:
if (screenY > 80 && screenY < 105)
break;
default:
if (pPrefs->bMouse)
return false;

pHWTrace->b2006 = 0;
pHWTrace->points[pHWTrace->PtCount].x = screenX;
pHWTrace->points[pHWTrace->PtCount].y = screenY;
if (pHWTrace->PtCount == 0)
pHWTrace->b2007 = 1;
pHWTrace->PtCount++;
pHWTrace->dw2002 = 0;
return true;
}

// 如果已有筆跡采樣點, 將新點加入筆跡陣列.
if (pHWTrace->PtCount) {
pHWTrace->points[pHWTrace->PtCount].x = screenX;
pHWTrace->points[pHWTrace->PtCount].y = screenY;
pHWTrace->PtCount++;
return true;
}

pHWTrace->b2006 = true;
if (MenuMode == LOWER && x > 3 && x < 63 && y > 134 && y < 146 ||
MenuMode == UPPER && x > 3 && x < 63 && y > 94 && y < 106)
{
UInt16 ofs = (pHWPens->CandiDispOfs + (x - 1)) / 12;
char* p = (char*)&pHWPens->Cands[pHWPens->index - 1][ofs];

if (*p == 0) {
if (*(p + 1) == 0)
return true;
EvtEnqueueKey(backspaceChr, 0, 0);
EvtEnqueueKey(*(p + 1), 0, 0);
}
else {
EnqueueChChar(GetCurField(FrmGetActiveForm()), p, true);
GetAssoc(pHWPens, *(UInt16*)p);
}
pPrefs->bRedrawMenu = true;
return true;
}


if (MenuMode == LOWER && x > 3 && x < 133 && y > 121 && y < 133 ||
MenuMode == UPPER && x > 3 && x < 133 && y > 81 && y < 93) // else goto 6b4a
{
UInt16 pos = (x - 1) / 13 * 2;
if (pHWPens->AssocOfs + pos < pHWPens->AssocNum) {
EnqueueChChar(GetCurField(FrmGetActiveForm()), pHWPens->AssocBuffer[pos], false);
pHWPens->AssocNum = 0;
pHWPens->AssocOfs = 0;
}
return true;
}

if (MenuMode == LOWER && x > 63 && x < 75 && y > 134 && y < 146 ||
MenuMode == UPPER && x > 63 && x < 75 && y > 94 && y < 106) // else goto 6be0
{
UInt16 ofs = pHWPens->CandiDispOfs + 5;
if (ofs == 10) {
pHWPens->CandiDispOfs = 0;
pPrefs->bRedrawMenu = true;
}
else if (pHWPens->Cands[pHWPens->index - 1][ofs] != 0) {
pHWPens->CandiDispOfs + 5;
pPrefs->bRedrawMenu = true;
}
return true;
}

if (MenuMode == LOWER && x > 132 && x < 144 && y > 121 && y < 133 ||
MenuMode == UPPER && x > 132 && x < 144 && y > 81 && y < 93) // else goto 6c4a
{
if (pHWPens->AssocOfs) {
pHWPens->AssocOfs -= 20;
pPrefs->bRedrawMenu = true;
}
return true;
}

if (MenuMode == LOWER && x > 145 && x < 157 && y > 121 && y < 133 ||
MenuMode == UPPER && x > 145 && x < 157 && y > 81 && y < 93) // else goto 6cba
{
if (pHWPens->AssocOfs + 20 < pHWPens->AssocNum) {
pHWPens->AssocOfs += 20;
pPrefs->bRedrawMenu = true;
}
re
psac 目前離線  
送花文章: 3, 收花文章: 1631 篇, 收花: 3205 次
 



發表規則
不可以發文
不可以回覆主題
不可以上傳附加檔案
不可以編輯您的文章

論壇啟用 BB 語法
論壇啟用 表情符號
論壇啟用 [IMG] 語法
論壇禁用 HTML 語法
Trackbacks are 禁用
Pingbacks are 禁用
Refbacks are 禁用


所有時間均為台北時間。現在的時間是 02:55 PM


Powered by vBulletin® 版本 3.6.8
版權所有 ©2000 - 2024, Jelsoft Enterprises Ltd.


SEO by vBSEO 3.6.1