Compose.pas
资源名称:Wingb_Mz.rar [点击查看]
上传用户:wen198501
上传日期:2013-04-01
资源大小:335k
文件大小:15k
源码类别:
输入法编程
开发平台:
Delphi
- {******************************************************}
- { }
- { Copyright (c) 1990-1999 Microsoft Corporation }
- { }
- { Module Name: Compose.c ->> Compose.pas }
- { }
- { Translator: Liu_mazi@126.com, 2005-11-19 }
- { }
- {******************************************************}
- unit Compose;
- {$I Define.Inc}
- interface
- uses Windows, ImmDev, ImeDefs;
- function GBEngine(lpImcP: PPrivContext): Word; // Conv GBcode
- procedure AddCodeIntoCand(lpCandList: PCandiDateList; wCode: Word); // 添加Candidate
- procedure CompEscapeKey(lpIMC: PInputContext; lpCompStr: PCompositionString;
- lpGuideLine: PGuideLine; lpImcP: PPrivContext); // Composition取消处理
- procedure CompWord(wCharCode: Word; lpIMC: PInputContext;
- lpCompStr: PCompositionString; lpImcP: PPrivContext; lpGuideLine: PGuideLine);
- implementation
- uses Data, DDIS;
- // 单个字符转数值
- function CharToHex(cChar: Char): Word;
- begin
- if (cChar >= '0') and (cChar <= '9') then
- Result := Ord(cChar) - Ord('0')
- else
- if (cChar >= 'a') and (cChar <= 'f') then
- Result := Ord(cChar) - Ord('a') + $0A
- else
- Result := 0;
- end;
- // GB内码串转内码
- function AsciiToGB(lpImcP: PPrivContext): Word;
- begin
- Result := (CharToHex(lpImcP.bSeq[2]) shl 4) or CharToHex(lpImcP.bSeq[3]);
- Result := (Result shl 8);
- Result := (CharToHex(lpImcP.bSeq[0]) shl 4) or CharToHex(lpImcP.bSeq[1]) or Result;
- end;
- // 区位码串转内码
- function AsciiToArea(lpImcP: PPrivContext): Word;
- begin
- Result := (CharToHex(lpImcP.bSeq[2]) * 10) + CharToHex(lpImcP.bSeq[3]) + $A0;
- Result := (Result shl 8);
- Result := (CharToHex(lpImcP.bSeq[0]) * 10) + CharToHex(lpImcP.bSeq[1]) + $A0 or Result;
- end;
- // Conv GBcode
- function GBEngine(lpImcP: PPrivContext): Word;
- begin
- if (lpImcP.bSeq[3] <> #0) or (lpImcP.bSeq[2] = '?') then
- begin
- if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then //Area mode
- begin
- if (lpImcP.bSeq[2] = '?') then
- begin
- lpImcP.bSeq[2] := '0';
- lpImcP.bSeq[3] := '1';
- end;
- Result := AsciiToArea(lpImcP);
- end else
- if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then //GB mode
- begin
- if (lpImcP.bSeq[2] = '?') then
- begin
- lpImcP.bSeq[2] := 'a';
- lpImcP.bSeq[3] := '1';
- end;
- Result := AsciiToGB(lpImcP);
- end else
- Result := 0;
- end else
- Result := 0;
- end;
- // Conv GBcode for Space
- function GBSpcEng(lpImcP: PPrivContext): Word;
- begin
- if (lpImcP.bSeq[0] >= '0') and (lpImcP.bSeq[0] <= '9') then //Area mode
- begin
- lpImcP.bSeq[2] := '0';
- lpImcP.bSeq[3] := '1';
- Result := AsciiToArea(lpImcP);
- end else
- if (lpImcP.bSeq[0] >= 'a') and (lpImcP.bSeq[0] <= 'f') then //GB mode
- begin
- lpImcP.bSeq[2] := 'a';
- lpImcP.bSeq[3] := '1';
- Result := AsciiToGB(lpImcP);
- end else
- Result := 0;
- end;
- // search MB, and fill lpCompStr & lpCandList
- function Engine(lpCompStr: PCompositionString; lpCandList: PCandiDateList;
- lpImcP: PPrivContext; lpIMC: PInputContext; wCharCode: Word): Integer;
- var
- J: DWord;
- wCode: Word;
- ResaultStr: array[0..2] of Char;
- begin
- if (lpCompStr.dwCursorPos < 4) and (lpImcP.bSeq[2] <> '?') and (wCharCode <> Ord(' ')) then
- begin
- Result := ENGINE_COMP;
- Exit;
- end else
- if (lpCompStr.dwCursorPos = 4) or (lpImcP.bSeq[2] = '?') or
- ((wCharCode = Ord(' ')) and (lpCompStr.dwCursorPos = 2)) then
- begin
- if (lpCompStr = nil) then
- begin
- MessageBeep($FFFFFFFF);
- Result := -1;
- Exit;
- end;
- if (lpImcP = nil) then
- begin
- MessageBeep($FFFFFFFF);
- Result := -1;
- Exit;
- end;
- if (lpImcP.bSeq[2] = '?') then // 查询
- begin
- wCode := GBEngine(lpImcP);
- wCode := HiByte(wCode) or (LoByte(wCode) shl 8);
- for J := 0 to IME_MAXCAND - 1 do
- begin
- AddCodeIntoCand(lpCandList, wCode);
- Inc(wCode);
- end;
- Result := ENGINE_COMP;
- Exit;
- end else
- if (wCharCode = Ord(' ')) then // 查询
- begin
- wCode := GBSpcEng(lpImcP);
- lpImcP.bSeq[2] := #0;
- lpImcP.bSeq[3] := #0;
- wCode := HiByte(wCode) or (LoByte(wCode) shl 8);
- for J := 0 to IME_MAXCAND - 1 do
- begin
- AddCodeIntoCand(lpCandList, wCode);
- Inc(wCode);
- end;
- Result := ENGINE_COMP;
- Exit
- end else // 转换
- begin
- InitCompStr(lpCompStr);
- wCode := GBEngine(lpImcP); // the result string = the selected candidate;
- ResaultStr[0] := Chr(LoByte(wCode));
- ResaultStr[1] := Chr(HiByte(wCode));
- ResaultStr[2] := #0;
- lStrCpy(PChar(DWord(lpCompStr) + lpCompStr.dwResultStrOffset), ResaultStr);
- lpCompStr.dwResultStrLen := lStrLen(ResaultStr); // calculate result string length
- Result := ENGINE_RESAULT;
- Exit;
- end;
- end;
- MessageBeep($FFFFFFFF);
- Result := ENGINE_COMP;
- end;
- // Call Engine finalize Chinese word(s) by searching table
- function Finalize(lpIMC: PInputContext; lpCompStr: PCompositionString; lpImcP: PPrivContext; wCharCode: Word): uInt;
- var
- lpCandInfo: PCandiDateInfo;
- lpCandList: PCandiDateList;
- begin
- Result := 0;
- if (lpIMC.hCandInfo = 0) then Exit;
- // get lpCandInfo
- lpCandInfo := ImmLockIMCC(lpIMC.hCandInfo);
- if (lpCandInfo = nil) then Exit;
- // get lpCandList and init dwCount & dwSelection
- lpCandList := PCandiDateList(DWord(lpCandInfo) + lpCandInfo.dwOffset[0]);
- lpCandList.dwCount := 0;
- lpCandList.dwSelection := 0;
- // search the IME tables
- Result := Engine(lpCompStr, lpCandList, lpImcP, lpIMC, wCharCode);
- if (Result = ENGINE_COMP) then
- begin
- lpCandInfo.dwCount := 1;
- if ( (lpCompStr.dwCursorPos < 3) and (wCharCode <> Ord(' ')) ) or
- ( (lpCompStr.dwCursorPos = 3) and (wCharCode <> Ord(' ')) and (wCharCode <> Ord('?')) ) then
- begin
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CLOSE_CANDIDATE) and (not MSG_OPEN_CANDIDATE);
- ImmUnlockIMCC(lpIMC.hCandInfo);
- Exit;
- end;
- if (lpCandList.dwCount <> 0) then
- begin // open composition candidate UI window for the string(s)
- if (lpImcP.fdwImeMsg and MSG_ALREADY_OPEN <> 0) and (MSG_ALREADY_OPEN and MSG_CLOSE_CANDIDATE <> 0) then
- begin
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CHANGE_CANDIDATE) and (not MSG_CLOSE_CANDIDATE);
- end else
- if ((lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0) then
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CHANGE_CANDIDATE)
- else
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_OPEN_CANDIDATE) and (not MSG_CLOSE_CANDIDATE);
- end;
- if ((lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0) then lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_COMPOSITION;
- end else
- if (Result = ENGINE_ASCII) then
- begin
- // **
- end else
- if (Result = ENGINE_RESAULT) then
- begin
- // Set lpImep! and tell application, there is a reslut string
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_COMPOSITION;
- lpImcP.dwCompChar := 0;
- lpImcP.fdwGcsFlag := lpImcP.fdwGcsFlag or GCS_COMPREAD or
- GCS_COMP or GCS_CURSORPOS or GCS_DELTASTART or GCS_RESULTREAD or GCS_RESULT;
- if ((lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0) then
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CLOSE_CANDIDATE) and (not MSG_OPEN_CANDIDATE);
- // clear candidate now
- lpCandList.dwCount := 0;
- // set iImeState with CST_INIT
- lpImcP.iImeState := CST_INIT;
- PDWord(@lpImcP.bSeq)^ := 0;
- end;
- ImmUnlockIMCC(lpIMC.hCandInfo);
- end;
- // 添加Candidate
- procedure AddCodeIntoCand(lpCandList: PCandiDateList; wCode: Word);
- var
- wInCode: Word;
- begin
- if (lpCandList.dwCount >= IME_MAXCAND) then Exit;
- wInCode := HiByte(wCode) or (LoByte(wCode) shl 8);
- // add GB string into candidate list
- PUnaWord(DWord(lpCandList) + lpCandList.dwOffset[lpCandList.dwCount])^ := wInCode;
- // null terminator
- PChar(DWord(lpCandList) + lpCandList.dwOffset[lpCandList.dwCount] + SizeOf(Word))^ := #0;
- lpCandList.dwOffset[lpCandList.dwCount + 1] := lpCandList.dwOffset[lpCandList.dwCount] + SizeOf(Word) + SizeOf(Char);
- Inc(lpCandList.dwCount);
- end;
- // Composition取消处理
- procedure CompEscapeKey(lpIMC: PInputContext; lpCompStr: PCompositionString; lpGuideLine: PGuideLine; lpImcP: PPrivContext);
- begin
- if (lpGuideLine = nil) then
- begin
- MessageBeep($FFFFFFFF);
- end else
- if (lpGuideLine.dwLevel <> GL_LEVEL_NOGUIDELINE) then
- begin
- lpGuideLine.dwLevel := GL_LEVEL_NOGUIDELINE;
- lpGuideLine.dwIndex := GL_ID_UNKNOWN;
- lpGuideLine.dwStrLen := 0;
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_GUIDELINE;
- end;
- if (lpImcP.iImeState <> CST_CHOOSE) then
- if ((lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0) then
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_END_COMPOSITION) and (not MSG_START_COMPOSITION);
- lpImcP.iImeState := CST_INIT;
- PDWord(@lpImcP.bSeq)^ := 0;
- if (lpCompStr <> nil) then
- begin
- InitCompStr(lpCompStr);
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_COMPOSITION;
- lpImcP.dwCompChar := VK_ESCAPE;
- lpImcP.fdwGcsFlag := lpImcP.fdwGcsFlag or GCS_COMPREAD or GCS_COMP or GCS_CURSORPOS or GCS_DELTASTART;
- end;
- end;
- // Composition回退处理
- procedure CompBackSpaceKey(lpIMC: PInputContext; lpCompStr: PCompositionString; lpImcP: PPrivContext);
- begin
- if (lpCompStr.dwCursorPos < SizeOf(Byte)) then lpCompStr.dwCursorPos := SizeOf(Byte);
- lpImcP.bSeq[3] := #0;
- // go back a compsoition char
- Dec(lpCompStr.dwCursorPos, SizeOf(Byte));
- // clean the sequence code
- lpImcP.bSeq[lpCompStr.dwCursorPos] := #0;
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_COMPOSITION;
- lpImcP.dwCompChar := $08;
- lpImcP.fdwGcsFlag := lpImcP.fdwGcsFlag or GCS_COMPREAD or GCS_COMP or GCS_CURSORPOS or GCS_DELTASTART;
- if (lpCompStr.dwCursorPos = 0) then
- begin
- if ((lpImcP.fdwImeMsg and MSG_ALREADY_OPEN) <> 0) then
- begin
- ClearCand(lpIMC);
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_CLOSE_CANDIDATE) and (not MSG_OPEN_CANDIDATE);
- end;
- if (lpImcP.iImeState <> CST_INIT) then
- begin
- lpImcP.iImeState := CST_INIT;
- lpCompStr.dwCompReadStrLen := lpCompStr.dwCursorPos;
- lpCompStr.dwCompStrLen := lpCompStr.dwCursorPos;
- lpCompStr.dwDeltaStart := lpCompStr.dwCursorPos;
- Finalize(lpIMC, lpCompStr, lpImcP, $08);
- Exit;
- end;
- if ((lpImcP.fdwImeMsg and MSG_ALREADY_START) <> 0) then
- begin
- InitCompStr(lpCompStr);
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_END_COMPOSITION) and (not MSG_START_COMPOSITION);
- Exit;
- end;
- end;
- // reading string is composition string for some simple IMEs
- // delta start is the same as cursor position for backspace
- lpCompStr.dwCompReadStrLen := lpCompStr.dwCursorPos;
- lpCompStr.dwCompStrLen := lpCompStr.dwCursorPos;
- lpCompStr.dwDeltaStart := lpCompStr.dwCursorPos;
- Finalize(lpIMC, lpCompStr, lpImcP, $08);
- end;
- // 添加Composition, **
- procedure CompStrInfo(lpCompStr: PCompositionString; lpImcP: PPrivContext; lpGuideLine: PGuideLine; wCharCode: Word);
- var
- dwCursorPos: DWord;
- begin
- dwCursorPos := lpCompStr.dwCursorPos;
- // dwCrusorPos limit
- if (dwCursorPos >= sImeL.nMaxKey) then
- begin
- // exceed the max input key limitation
- lpGuideLine.dwLevel := GL_LEVEL_ERROR;
- lpGuideLine.dwIndex := GL_ID_TOOMANYSTROKE;
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_GUIDELINE;
- Exit;
- end;
- // set MSG_START_COMPOSITION
- if ((lpImcP.fdwImeMsg and MSG_ALREADY_START) = 0) then
- lpImcP.fdwImeMsg := (lpImcP.fdwImeMsg or MSG_START_COMPOSITION) and (not MSG_END_COMPOSITION);
- // clean the 4 bytes in one time
- if (lpImcP.iImeState = CST_INIT) then PDWord(@lpImcP.bSeq)^ := 0;
- // **
- lpImcP.bSeq[dwCursorPos] := Chr(Byte(wCharCode));
- // composition/reading string - UsedCode(Full Shape)
- lpImcP.dwCompChar := wCharCode;
- // set reading string for lpCompStr
- PUnaWord(DWord(lpCompStr) + lpCompStr.dwCompReadStrOffset + dwCursorPos)^ := Byte(lpImcP.dwCompChar);
- PUnaWord(DWord(lpCompStr) + lpCompStr.dwCompReadAttrOffset + dwCursorPos)^ := (ATTR_TARGET_CONVERTED shl 8) or ATTR_TARGET_CONVERTED;
- // set reading string lenght for lpCompStr
- if (lpCompStr.dwCompReadStrLen <= dwCursorPos) then Inc(lpCompStr.dwCompReadStrLen, SizeOf(Byte));
- // composition string is reading string for some simple IMEs
- lpCompStr.dwCompStrLen := lpCompStr.dwCompReadStrLen;
- // composition/reading attribute length is equal to reading string length
- lpCompStr.dwCompReadAttrLen := lpCompStr.dwCompReadStrLen;
- lpCompStr.dwCompAttrLen := lpCompStr.dwCompStrLen;
- // delta start from previous cursor position
- lpCompStr.dwDeltaStart := lpCompStr.dwCursorPos;
- // set new cursor with next to the composition string
- lpCompStr.dwCursorPos := lpCompStr.dwCompStrLen;
- // set lpImcp->iImeState
- lpImcP.iImeState := CST_INPUT;
- // tell app, there is a composition char generated
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_COMPOSITION;
- // set lpImeP->fdwGcsFlag
- lpImcP.fdwGcsFlag := lpImcP.fdwGcsFlag or GCS_COMPREAD or GCS_COMP or GCS_CURSORPOS or GCS_DELTASTART;
- end;
- // compose the Chinese word(s) according to input key
- procedure CompWord(wCharCode: Word; lpIMC: PInputContext;
- lpCompStr: PCompositionString; lpImcP: PPrivContext; lpGuideLine: PGuideLine);
- begin
- if (lpCompStr = nil) then begin MessageBeep($FFFFFFFF); Exit; end;
- // not good to use VK as char, but..., ??
- if (wCharCode = VK_ESCAPE) then // 取消
- begin
- CompEscapeKey(lpIMC, lpCompStr, lpGuideLine, lpImcP);
- Exit;
- end;
- if (lpGuideLine = nil) then
- begin
- end else
- if (lpGuideLine.dwLevel = GL_LEVEL_NOGUIDELINE) then
- begin
- lpGuideLine.dwStrLen := 0;
- end else
- begin
- // previous input error cause us trancate some chars
- if (lpGuideLine.dwLevel = GL_LEVEL_ERROR) then
- begin
- lpImcP.bSeq[lpCompStr.dwCursorPos div 2] := #0;
- lpCompStr.dwCompReadStrLen := lpCompStr.dwCursorPos; // **
- lpCompStr.dwCompStrLen := lpCompStr.dwCursorPos;
- lpCompStr.dwCompReadAttrLen := lpCompStr.dwCompReadStrLen;
- lpCompStr.dwCompAttrLen := lpCompStr.dwCompStrLen;
- end;
- lpGuideLine.dwLevel := GL_LEVEL_NOGUIDELINE;
- lpGuideLine.dwIndex := GL_ID_UNKNOWN;
- lpGuideLine.dwStrLen := 0;
- lpImcP.fdwImeMsg := lpImcP.fdwImeMsg or MSG_GUIDELINE;
- end;
- if (wCharCode = $08) then // 回格
- begin
- CompBackSpaceKey(lpIMC, lpCompStr, lpImcP);
- Exit;
- end;
- if (wCharCode <> Ord(' ')) then
- CompStrInfo(lpCompStr, lpImcP, lpGuideLine, wCharCode); // build up composition string info
- Finalize(lpIMC, lpCompStr, lpImcP, wCharCode); // compsition
- end;
- end.