|
論壇說明 |
歡迎您來到『史萊姆論壇』 ^___^ 您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的! 請點擊這裡:『註冊成為我們的一份子!』 |
|
主題工具 | 顯示模式 |
2003-12-11, 08:12 PM | #1 |
榮譽會員
|
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 |
送花文章: 3,
|