ime sanity

This commit is contained in:
David Rose 2007-07-12 20:54:38 +00:00
parent 5669af441b
commit d3a1cafb54
4 changed files with 29 additions and 177 deletions

View File

@ -745,17 +745,16 @@ update_cursor() {
update_text();
_cursor_position = min(_cursor_position, _text.get_num_characters());
_candidate_cursor_pos = min(_candidate_cursor_pos, _candidate_wtext.length());
// Determine the row and column of the cursor.
int row, column;
float xpos, ypos;
if (_obscure_mode) {
_obscure_text.calc_r_c(row, column, _cursor_position + _candidate_cursor_pos);
_obscure_text.calc_r_c(row, column, _cursor_position);
xpos = _obscure_text.get_xpos(row, column);
ypos = _obscure_text.get_ypos(row, column);
} else {
_text.calc_r_c(row, column, _cursor_position + _candidate_cursor_pos);
_text.calc_r_c(row, column, _cursor_position);
xpos = _text.get_xpos(row, column);
ypos = _text.get_ypos(row, column);
}
@ -765,7 +764,7 @@ update_cursor() {
}
// Should the cursor be visible?
if (!get_focus()) {
if (!get_focus() || !_candidate_wtext.empty()) {
show_hide_cursor(false);
} else {
double elapsed_time =

View File

@ -44,13 +44,6 @@ ConfigVariableBool do_vidmemsize_check
PRC_DESC("if true, use ddraw's GetAvailVidMem to fail if driver says "
"it has too little video mem"));
ConfigVariableBool ime_composition_w
("ime-composition-w", true,
PRC_DESC("For now, set this true to use the IME correctly on Win2000, or "
"false on Win98. This is temporary; once we have been able to "
"verify that this distinction is actually necessary, we can replace "
"this config variable with an actual OS detection."));
ConfigVariableBool ime_aware
("ime-aware", false,
PRC_DESC("Set this true to show ime texts on the chat panel and hide the "

View File

@ -99,7 +99,6 @@ WinGraphicsWindow(GraphicsPipe *pipe,
_hWnd = (HWND)0;
_ime_open = false;
_ime_active = false;
_ime_composition_w = false;
_tracking_mouse_leaving = false;
_maximized = false;
_cursor = 0;
@ -427,41 +426,6 @@ open_window() {
ImmReleaseContext(_hWnd, hIMC);
}
// Check the version of the OS we are running. If we are running
// win2000, we must use ImmGetCompositionStringW() to report the
// characters returned by the IME, since WM_CHAR and
// ImmGetCompositionStringA() both just return question marks.
// However, this function doesn't work for Win98; on this OS, we
// have to use ImmGetCompositionStringA() instead, which returns an
// encoded string in shift-jis (which we then have to decode).
// For now, this is user-configurable, to allow testing of this code
// on both OS's. After we verify that truth of the above claim, we
// should base this decision on GetVersionEx() or maybe
// VerifyVersionInfo().
_ime_composition_w = ime_composition_w;
// need to re-evaluate above in light of this, it seems that
// ImmGetCompositionStringW should work on both:
// The Input Method Editor and Unicode Windows 98/Me, Windows
// NT/2000/XP: Windows supports a Unicode interface for the
// IME, in addition to the ANSI interface originally supported.
// Windows 98/Me supports all the Unicode functions except
// ImmIsUIMessage. Also, all the messages in Windows 98/Me are
// ANSI based. Since Windows 98/Me does not support Unicode
// messages, applications can use ImmGetCompositionString to
// receive Unicode characters from a Unicode based IME on
// Windows 98/Me. There are two issues involved with Unicode
// handling and the IME. One is that the Unicode versions of
// IME routines return the size of a buffer in bytes rather
// than 16-bit Unicode characters,and the other is the IME
// normally returns Unicode characters (rather than DBCS) in
// the WM_CHAR and WM_IME_CHAR messages. Use RegisterClassW
// to cause the WM_CHAR and WM_IME_CHAR messages to return
// Unicode characters in the wParam parameter rather than DBCS
// characters. This is only available under Windows NT; it is
// stubbed out in Windows 95/98/Me.
// Registers to receive the WM_INPUT messages
if ((pRegisterRawInputDevices)&&(_input_devices.size() > 1)) {
RAWINPUTDEVICE Rid;
@ -1382,31 +1346,6 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
ImmReleaseContext(hwnd, hIMC);
}
/*
else if (_ime_open && (wparam == IMN_OPENCANDIDATE)) {
HIMC hIMC = ImmGetContext(hwnd);
nassertr(hIMC != 0, 0);
DWORD need_byte;
LPCANDIDATELIST pCanList;
char pBuff[1024];
need_byte = ImmGetCandidateListW(hIMC, 0, NULL, 0);
windisplay_cat.debug() << "need byte " << need_byte << endl;
need_byte = ImmGetCandidateListW(hIMC, 0, (LPCANDIDATELIST)pBuff, need_byte);
pCanList = (LPCANDIDATELIST)pBuff;
windisplay_cat.debug() << "need byte " << need_byte << " ,size " << pCanList->dwSize
<< " ,count " << pCanList->dwCount
<< " ,selected " << pCanList->dwSelection << endl;
wstring candidate_str;
for (DWORD i=0; i<pCanList->dwCount; ++i) {
// lets append all the candidate strings together
windisplay_cat.debug() << "string offset " << pCanList->dwOffset[i] << endl;
candidate_str.append((wchar_t*)((char*)pCanList + pCanList->dwOffset[i]));
}
windisplay_cat.debug() << "concatenated string " << (wchar_t*)candidate_str.c_str() << endl;
//_input_devices[0].candidate(candidate_str, 0, 0);
ImmReleaseContext(hwnd, hIMC);
}
*/
break;
case WM_IME_STARTCOMPOSITION:
@ -1433,106 +1372,42 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
// we don't want to send the current composition string in that
// case. But we do need to return 0 to tell windows not to try
// to send the composition string through WM_CHAR messages.
if (!_ime_active)
if (!_ime_active) {
return 0;
}
HIMC hIMC = ImmGetContext(hwnd);
nassertr(hIMC != 0, 0);
static const int max_ime_result = 128;
static char ime_result[max_ime_result];
DWORD result_size = 0;
const int max_t = 256;
wchar_t can_t[max_t];
static const int ime_buffer_size = 256;
static const int ime_buffer_size_bytes = ime_buffer_size / sizeof(wchar_t);
wchar_t ime_buffer[ime_buffer_size];
size_t cursor_pos, delta_start;
if (_ime_composition_w) {
// Since ImmGetCompositionStringA() doesn't seem to work
// for Win2000 (it always returns question mark
// characters), we have to use ImmGetCompositionStringW()
// on this OS. This is actually the easier of the two
// functions to use.
if (lparam & GCS_RESULTSTR) {
windisplay_cat.debug() << "GCS_RESULTSTR\n";
result_size = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
ime_result, max_ime_result);
// Add this string into the text buffer of the application.
// ImmGetCompositionStringW() returns a string, but it's
// filled in with wstring data: every two characters defines a
// 16-bit unicode char. The docs aren't clear on the
// endianness of this. I guess it's safe to assume all Win32
// machines are little-endian.
for (DWORD i = 0; i < result_size; i += 2) {
int result =
((int)(unsigned char)ime_result[i + 1] << 8) |
(unsigned char)ime_result[i];
_input_devices[0].keystroke(result);
}
}
if (lparam & GCS_COMPSTR) {
windisplay_cat.debug() << "GCS_COMPSTR\n";
/*
result_size = ImmGetCompositionStringW(hIMC, GCS_COMPREADSTR, can_t, max_t);
windisplay_cat.debug() << "got readstr of size " << result_size << endl;
*/
result_size = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, can_t, max_t);
cursor_pos = result_size&0xffff;
windisplay_cat.debug() << "got cursorpos at " << cursor_pos << endl;
result_size = ImmGetCompositionStringW(hIMC, GCS_DELTASTART, can_t, max_t);
delta_start = result_size&0xffff;
windisplay_cat.debug() << "got deltastart at " << delta_start << endl;
/*
result_size = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, can_t, max_t);
windisplay_cat.debug() << "got compatr of size " << result_size << endl;
result_size = ImmGetCompositionStringW(hIMC, GCS_COMPREADSTR, can_t, max_t);
windisplay_cat.debug() << "got compreadstr of size " << result_size << endl;
result_size = ImmGetCompositionStringW(hIMC, GCS_COMPCLAUSE, can_t, max_t);
windisplay_cat.debug() << "got compclause of size " << result_size << endl;
*/
result_size = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, can_t, max_t);
windisplay_cat.debug() << "got compstr of size " << result_size << endl;
can_t[result_size/sizeof(wchar_t)] = '\0';
_input_devices[0].candidate(can_t, min(cursor_pos, delta_start), max(cursor_pos, delta_start), cursor_pos);
}
} else {
if (lparam & GCS_RESULTSTR) {
// On the other hand, ImmGetCompositionStringW() doesn't
// work on Win95 or Win98; for these OS's we must use
// ImmGetCompositionStringA().
result_size = ImmGetCompositionStringA(hIMC, GCS_RESULTSTR,
ime_result, max_ime_result);
// ImmGetCompositionStringA() returns an encoded ANSI
// string, which we now have to map to wide-character
// Unicode.
static const int max_wide_result = 128;
static wchar_t wide_result[max_wide_result];
int wide_size =
MultiByteToWideChar(CP_ACP, 0,
ime_result, result_size,
wide_result, max_wide_result);
if (wide_size == 0) {
show_error_message();
}
for (int i = 0; i < wide_size; i++) {
_input_devices[0].keystroke(wide_result[i]);
}
if (lparam & GCS_RESULTSTR) {
result_size = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
ime_buffer, ime_buffer_size_bytes);
size_t num_chars = result_size / sizeof(wchar_t);
for (size_t i = 0; i < num_chars; ++i) {
_input_devices[0].keystroke(ime_buffer[i]);
}
}
if (lparam & GCS_COMPSTR) {
result_size = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0);
cursor_pos = result_size & 0xffff;
result_size = ImmGetCompositionStringW(hIMC, GCS_DELTASTART, NULL, 0);
delta_start = result_size & 0xffff;
result_size = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, ime_buffer, ime_buffer_size);
size_t num_chars = result_size / sizeof(wchar_t);
_input_devices[0].candidate(wstring(ime_buffer, num_chars),
min(cursor_pos, delta_start),
max(cursor_pos, delta_start),
cursor_pos);
}
ImmReleaseContext(hwnd, hIMC);
}
break;
@ -1547,20 +1422,6 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
_input_devices[0].keystroke(wparam);
}
break;
/*
case WM_PAINT:
// draw ime window on top
PAINTSTRUCT ps;
HDC hdc;
//RECT rc;
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
if (_ime_active) {
hdc = BeginPaint(_ime_hWnd, &ps);
EndPaint(_ime_hWnd, &ps);
}
break;
*/
case WM_SYSKEYDOWN:
if (_lost_keypresses) {

View File

@ -125,7 +125,6 @@ private:
HWND _ime_hWnd;
bool _ime_open;
bool _ime_active;
bool _ime_composition_w;
bool _tracking_mouse_leaving;
bool _maximized;
bool _bCursor_in_WindowClientArea;