33 GHOST_ImeWin32::GHOST_ImeWin32()
34 : is_composing_(false),
36 input_language_id_(LANG_USER_DEFAULT),
38 caret_rect_(-1, -1, 0, 0),
44 GHOST_ImeWin32::~GHOST_ImeWin32()
48 bool GHOST_ImeWin32::SetInputLanguage()
56 HKL keyboard_layout = ::GetKeyboardLayout(0);
57 input_language_id_ = LOWORD(keyboard_layout);
58 ime_status_ = ::ImmIsIME(keyboard_layout);
62 void GHOST_ImeWin32::CreateImeWindow(HWND window_handle)
76 if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE ||
77 PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) {
79 if (::CreateCaret(window_handle,
NULL, 1, 1)) {
85 UpdateImeWindow(window_handle);
88 void GHOST_ImeWin32::SetImeWindowStyle(
89 HWND window_handle,
UINT message, WPARAM wparam, LPARAM lparam, BOOL *handled)
102 lparam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
103 ::DefWindowProc(window_handle, message, wparam, lparam);
106 void GHOST_ImeWin32::DestroyImeWindow(HWND window_handle)
111 system_caret_ =
false;
115 void GHOST_ImeWin32::MoveImeWindow(HWND window_handle, HIMC imm_context)
117 int x = caret_rect_.m_l;
118 int y = caret_rect_.m_t;
119 const int kCaretMargin = 1;
132 CANDIDATEFORM candidate_position = {0, CFS_CANDIDATEPOS, {
x,
y}, {0, 0, 0, 0}};
133 ::ImmSetCandidateWindow(imm_context, &candidate_position);
135 switch (PRIMARYLANGID(input_language_id_)) {
137 ::SetCaretPos(
x,
y + caret_rect_.getHeight());
144 if (PRIMARYLANGID(input_language_id_) == LANG_KOREAN) {
159 CANDIDATEFORM exclude_rectangle = {
160 0, CFS_EXCLUDE, {
x,
y}, {
x,
y,
x + caret_rect_.getWidth(),
y + caret_rect_.getHeight()}};
161 ::ImmSetCandidateWindow(imm_context, &exclude_rectangle);
164 void GHOST_ImeWin32::UpdateImeWindow(HWND window_handle)
167 if (caret_rect_.m_l >= 0 && caret_rect_.m_t >= 0) {
168 HIMC imm_context = ::ImmGetContext(window_handle);
170 MoveImeWindow(window_handle, imm_context);
171 ::ImmReleaseContext(window_handle, imm_context);
176 void GHOST_ImeWin32::CleanupComposition(HWND window_handle)
184 HIMC imm_context = ::ImmGetContext(window_handle);
186 ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
187 ::ImmReleaseContext(window_handle, imm_context);
189 ResetComposition(window_handle);
193 void GHOST_ImeWin32::CheckFirst(HWND window_handle)
196 this->EndIME(window_handle);
201 void GHOST_ImeWin32::ResetComposition(HWND window_handle)
204 is_composing_ =
false;
207 void GHOST_ImeWin32::CompleteComposition(HWND window_handle, HIMC imm_context)
215 ::ImmNotifyIME(imm_context, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
216 ResetComposition(window_handle);
220 void GHOST_ImeWin32::GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *composition)
232 int target_start = -1;
234 switch (PRIMARYLANGID(input_language_id_)) {
236 if (lparam & CS_NOMOVECARET) {
242 int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE,
NULL, 0);
244 static std::vector<unsigned long> clauses;
245 clause_size = clause_size /
sizeof(clauses[0]);
246 clauses.resize(clause_size);
247 ImmGetCompositionStringW(
248 imm_context, GCS_COMPCLAUSE, &clauses[0],
sizeof(clauses[0]) * clause_size);
249 if (composition->cursor_position == composition->ime_string.size()) {
250 target_start = clauses[clause_size - 2];
251 target_end = clauses[clause_size - 1];
254 for (
int i = 0; i < clause_size - 1; i++) {
255 if (clauses[i] == composition->cursor_position) {
256 target_start = clauses[i];
257 target_end = clauses[i + 1];
264 if (composition->cursor_position != -1) {
265 target_start = composition->cursor_position;
266 target_end = composition->ime_string.size();
279 if (lparam & GCS_COMPATTR) {
280 int attribute_size = ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR,
NULL, 0);
281 if (attribute_size > 0) {
282 char *attribute_data =
new char[attribute_size];
283 if (attribute_data) {
284 ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR, attribute_data, attribute_size);
285 for (target_start = 0; target_start < attribute_size; ++target_start) {
286 if (IsTargetAttribute(attribute_data[target_start]))
289 for (target_end = target_start; target_end < attribute_size; ++target_end) {
290 if (!IsTargetAttribute(attribute_data[target_end]))
293 if (target_start == attribute_size) {
299 target_end = target_start;
302 if (target_start != -1 && target_start < attribute_size &&
303 attribute_data[target_start] == ATTR_TARGET_NOTCONVERTED) {
304 composition->cursor_position = target_start;
307 delete[] attribute_data;
312 composition->target_start = target_start;
313 composition->target_end = target_end;
316 bool GHOST_ImeWin32::GetString(HIMC imm_context,
319 ImeComposition *composition)
323 int string_size = ::ImmGetCompositionStringW(imm_context,
type,
NULL, 0);
324 if (string_size > 0) {
325 int string_length = string_size /
sizeof(wchar_t);
326 wchar_t *string_data =
new wchar_t[string_length + 1];
327 string_data[string_length] =
'\0';
330 ::ImmGetCompositionStringW(imm_context,
type, string_data, string_size);
331 composition->string_type =
type;
332 composition->ime_string = string_data;
335 delete[] string_data;
341 bool GHOST_ImeWin32::GetResult(HWND window_handle, LPARAM lparam, ImeComposition *composition)
344 HIMC imm_context = ::ImmGetContext(window_handle);
347 result = GetString(imm_context, lparam, GCS_RESULTSTR, composition);
352 composition->cursor_position = -1;
353 composition->target_start = -1;
354 composition->target_end = -1;
355 ::ImmReleaseContext(window_handle, imm_context);
360 bool GHOST_ImeWin32::GetComposition(HWND window_handle, LPARAM lparam, ImeComposition *composition)
363 HIMC imm_context = ::ImmGetContext(window_handle);
366 result = GetString(imm_context, lparam, GCS_COMPSTR, composition);
369 int cursor_position = ::ImmGetCompositionStringW(imm_context, GCS_CURSORPOS,
NULL, 0);
370 composition->cursor_position = cursor_position;
371 composition->target_start = -1;
372 composition->target_end = -1;
375 GetCaret(imm_context, lparam, composition);
378 is_composing_ =
true;
380 ::ImmReleaseContext(window_handle, imm_context);
385 void GHOST_ImeWin32::EndIME(HWND window_handle)
397 CleanupComposition(window_handle);
398 ::ImmAssociateContextEx(window_handle,
NULL, 0);
399 eventImeData.composite_len = 0;
402 void GHOST_ImeWin32::BeginIME(HWND window_handle,
const GHOST_Rect &caret_rect,
bool complete)
404 if (is_enable && complete)
413 ::ImmAssociateContextEx(window_handle,
NULL, IACE_DEFAULT);
415 HIMC imm_context = ::ImmGetContext(window_handle);
426 CompleteComposition(window_handle, imm_context);
433 if (caret_rect.
m_l >= 0 && caret_rect.
m_t >= 0) {
434 caret_rect_ = caret_rect;
435 MoveImeWindow(window_handle, imm_context);
437 ::ImmReleaseContext(window_handle, imm_context);
441 static void convert_utf16_to_utf8_len(std::wstring s,
int &
len)
443 if (
len >= 0 &&
len <= s.size())
449 static size_t updateUtf8Buf(ImeComposition &info)
452 info.utf8_buf.resize(
len);
454 convert_utf16_to_utf8_len(info.ime_string, info.cursor_position);
455 convert_utf16_to_utf8_len(info.ime_string, info.target_start);
456 convert_utf16_to_utf8_len(info.ime_string, info.target_end);
460 void GHOST_ImeWin32::UpdateInfo(HWND window_handle)
462 int res = this->GetResult(window_handle, GCS_RESULTSTR, &resultInfo);
463 int comp = this->GetComposition(window_handle, GCS_COMPSTR | GCS_COMPATTR, &compInfo);
467 eventImeData.result = &resultInfo.utf8_buf[0];
470 eventImeData.result = 0;
471 eventImeData.result_len = 0;
475 eventImeData.composite = &compInfo.utf8_buf[0];
476 eventImeData.cursor_position = compInfo.cursor_position;
477 eventImeData.target_start = compInfo.target_start;
478 eventImeData.target_end = compInfo.target_end;
481 eventImeData.composite = 0;
482 eventImeData.composite_len = 0;
483 eventImeData.cursor_position = -1;
484 eventImeData.target_start = -1;
485 eventImeData.target_end = -1;
GHOST C-API function and type declarations.
void * GHOST_TUserDataPtr
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
size_t count_utf_8_from_16(const wchar_t *string16)
int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)