Camilla Löwy 8 éve
szülő
commit
ed59b80cc7
10 módosított fájl, 257 hozzáadás és 287 törlés
  1. 1 1
      CMakeLists.txt
  2. 50 34
      docs/input.dox
  3. 1 2
      include/GLFW/glfw3.h
  4. 9 34
      src/cocoa_window.m
  5. 2 3
      src/input.c
  6. 3 6
      src/internal.h
  7. 40 76
      src/win32_window.c
  8. 1 1
      src/window.c
  9. 148 127
      src/x11_window.c
  10. 2 3
      tests/events.c

+ 1 - 1
CMakeLists.txt

@@ -226,7 +226,7 @@ endif()
 if (_GLFW_WIN32)
 if (_GLFW_WIN32)
 
 
     list(APPEND glfw_PKG_LIBS "-lgdi32")
     list(APPEND glfw_PKG_LIBS "-lgdi32")
-    list(APPEND glfw_LIBRARIES "imm32")
+    list(APPEND glfw_LIBRARIES "-limm32")
 
 
     if (GLFW_USE_HYBRID_HPG)
     if (GLFW_USE_HYBRID_HPG)
         set(_GLFW_USE_HYBRID_HPG 1)
         set(_GLFW_USE_HYBRID_HPG 1)

+ 50 - 34
docs/input.dox

@@ -206,35 +206,42 @@ void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
 }
 }
 @endcode
 @endcode
 
 
-@subsection preedit IME Support
 
 
-All desktop operating systems support IME (Input Method Editor) to input characters
-that are not mapped with physical keys. IME have been popular among Eeastern Asian people.
-And some operating systems start supporting voice input via IME mechanism.
+@subsection preedit IME support
 
 
-GLFW provides IME support functions to help
-you implement better text input features. You should add suitable visualization code for
-preedit text.
+All modern operating systems provide a
+[IME](https://en.wikipedia.org/wiki/Input_method) (Input Method Editor)
+mechanism to input character sets that cannot be mapped to physical keys, such
+as [CJK characters](https://en.wikipedia.org/wiki/CJK_characters) (Chinese,
+Japanese, Korean).  Some operating systems also support speech-to-text input via
+the IME mechanism.
+
+GLFW provides IME support functions to help you implement better text input
+features.  You should add suitable visualization code for pre-edit text.
 
 
 IME works in front of actual character input events (@ref input_char).
 IME works in front of actual character input events (@ref input_char).
-If your application uses text input and you want to support IME,
-you should register preedit callback to receive preedit text before committed.
+If your application uses text input and you want to support IME, you should
+register pre-edit callback to receive pre-edit text before committed.
 
 
 @code
 @code
 glfwSetPreeditCallback(window, preedit_callback);
 glfwSetPreeditCallback(window, preedit_callback);
 @endcode
 @endcode
 
 
-The callback function receives chunk of text and focused block information.
+The callback function receives the pre-edit text and block information.
 
 
 @code
 @code
-static void preedit_callback(GLFWwindow* window, int strLength, unsigned int* string, int blockLength, int* blocks, int focusedBlock) {
+static void preedit_callback(GLFWwindow* window, unsigned int* codepoints, int blockCount, int* blocks, int focusedBlock)
+{
 }
 }
 @endcode
 @endcode
 
 
-strLength and string parameter reprsent whole preedit text. Each character of the preedit string is a codepoint like @ref input_char.
+The codepoints parameter contains the whole pre-edit text.  Each character of the
+pre-edit string is a Unicode codepoint like with @ref input_char.
 
 
-If you want to type the text "寿司(sushi)", Usually the callback is called several times like the following sequence:
+If you want to type the text "寿司" (sushi), usually the callback is called
+several times like the following sequence:
 
 
+@code
 -# key event: s
 -# key event: s
 -# preedit: [string: "s", block: [1], focusedBlock: 0]
 -# preedit: [string: "s", block: [1], focusedBlock: 0]
 -# key event: u
 -# key event: u
@@ -250,52 +257,61 @@ If you want to type the text "寿司(sushi)", Usually the callback is called sev
 -# char: '寿'
 -# char: '寿'
 -# char: '司'
 -# char: '司'
 -# preedit: [string: "", block: [], focusedBlock: 0]
 -# preedit: [string: "", block: [], focusedBlock: 0]
+@endcode
 
 
-If preedit text includes several semantic blocks, preedit callbacks returns several blocks after a space key pressed:
+If pre-edit text includes several semantic blocks, pre-edit callbacks returns
+several blocks after a space key pressed:
 
 
+@code
 -# preedit: [string: "わたしはすしをたべます", block: [11], focusedBlock: 0]
 -# preedit: [string: "わたしはすしをたべます", block: [11], focusedBlock: 0]
 -# preedit: [string: "私は寿司を食べます", block: [2, 7], focusedBlock: 1]
 -# preedit: [string: "私は寿司を食べます", block: [2, 7], focusedBlock: 1]
+@endcode
 
 
-"blocks" is a list of block length. The above case, it contains the following blocks and second block is focused.
+"blocks" is a list of block length. The above case, it contains the following
+blocks and second block is focused.
 
 
+@code
 - 私は
 - 私は
 - [寿司を食べます]
 - [寿司を食べます]
+@endcode
 
 
-commited text(passed via regular @ref input_char event), unfocused block, focused block should have different text style.
-
+committed text (passed via regular @ref input_char event), unfocused block,
+focused block should have different text style.
 
 
-GLFW provides helper function to teach suitable position of the candidate window to window system.
-Window system decides the best position from text cursor geometry (x, y coords and height). You should call this function
-in the above preedit text callback function.
+GLFW provides helper function to teach suitable position of the candidate window
+to window system.  Window system decides the best position from text cursor
+geometry (window coordinates and height).  You should call this function in the
+above pre-edit text callback function.
 
 
 @code
 @code
-glfwSetPreeditCursorPos(window, x, y, h);
-glfwGetPreeditCursorPos(window, &x, &y, &h);
+int xpos, ypos, height;
+glfwSetPreeditCursorPos(window, xpos, ypos, height);
+glfwGetPreeditCursorPos(window, &xpos, &ypos, &height);
 @endcode
 @endcode
 
 
-Sometimes IME task is interrupted by user or application. There are several functions to support these situation.
-You can receive notification about IME status change(on/off) by using the following function:
+Sometimes IME task is interrupted by user or application. There are several
+functions to support these situation.  You can receive notification about IME
+status change(on/off) by using the following function:
 
 
 @code
 @code
-glfwSetIMEStatusCallback(window, imestatus_callback);
+glfwSetIMEStatusCallback(window, ime_status_callback);
 @endcode
 @endcode
 
 
-imestatus_callback has simple sigunature like this:
+The ime_status_callback has simple signature like this:
 
 
 @code
 @code
-static void imestatus_callback(GLFWwindow* window) {
+static void ime_status_callback(GLFWwindow* window)
+{
 }
 }
 @endcode
 @endcode
 
 
-You can implement the code that resets or commits preedit text when IME status is changed and preedit text is not empty.
+You can implement the code that resets or commits pre-edit text when IME status
+is changed and pre-edit text is not empty.
 
 
-When the focus is gone from text box, you can use the following functions to reset IME status:
+When the focus is gone from text box, you can use @ref glfwSetInputMode, @ref
+glfwGetInputMode with the `GLFW_IME` mode and the @ref glfwResetPreeditText
+function.
 
 
-@code
-void glfwResetPreeditText(GLFWwindow* window);
-void glfwSetIMEStatus(GLFWwindow* window, int active)
-int glfwGetIMEStatus(GLFWwindow* window)
-@endcode
 
 
 @subsection input_key_name Key names
 @subsection input_key_name Key names
 
 

+ 1 - 2
include/GLFW/glfw3.h

@@ -1106,7 +1106,6 @@ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
  *  This is the function signature for preedit callback functions.
  *  This is the function signature for preedit callback functions.
  *
  *
  *  @param[in] window The window that received the event.
  *  @param[in] window The window that received the event.
- *  @param[in] length Preedit string length.
  *  @param[in] string Preedit string.
  *  @param[in] string Preedit string.
  *  @param[in] count Attributed block count.
  *  @param[in] count Attributed block count.
  *  @param[in] blocksizes List of attributed block size.
  *  @param[in] blocksizes List of attributed block size.
@@ -1117,7 +1116,7 @@ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
  *
  *
  *  @ingroup input
  *  @ingroup input
  */
  */
-typedef void (* GLFWpreeditfun)(GLFWwindow*,int,unsigned int*,int,int*,int);
+typedef void (* GLFWpreeditfun)(GLFWwindow*,unsigned int*,int,int*,int);
 
 
 /*! @brief The function signature for IME status change callbacks.
 /*! @brief The function signature for IME status change callbacks.
  *
  *

+ 9 - 34
src/cocoa_window.m

@@ -721,33 +721,17 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
     NSString* markedTextString = markedText.string;
     NSString* markedTextString = markedText.string;
 
 
     NSUInteger i, length = [markedTextString length];
     NSUInteger i, length = [markedTextString length];
-    int ctext = window->ctext;
-    while (ctext < length + 1)
-        ctext = ctext ? ctext * 2 : 1;
 
 
-    if (ctext != window->ctext)
-    {
-        unsigned int* preeditText = realloc(window->preeditText, sizeof(unsigned int) * ctext);
-        if (!preeditText)
-            return;
-
-        window->preeditText = preeditText;
-        window->ctext = ctext;
-    }
-
-    window->ntext = length;
-    window->preeditText[length] = 0;
+    free(window->preeditText);
+    window->preeditText = calloc(length + 1, sizeof(unsigned int));
 
 
     for (i = 0;  i < length;  i++)
     for (i = 0;  i < length;  i++)
-    {
-        const unichar codepoint = [markedTextString characterAtIndex:i];
-        window->preeditText[i] = codepoint;
-    }
+        window->preeditText[i] = [markedTextString characterAtIndex:i];
 
 
     int focusedBlock = 0;
     int focusedBlock = 0;
     NSInteger offset = 0;
     NSInteger offset = 0;
 
 
-    window->nblocks = 0;
+    window->preeditBlockCount = 0;
 
 
     while (offset < length)
     while (offset < length)
     {
     {
@@ -755,27 +739,18 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
         NSDictionary *attributes = [markedText attributesAtIndex:offset
         NSDictionary *attributes = [markedText attributesAtIndex:offset
                                                   effectiveRange:&effectiveRange];
                                                   effectiveRange:&effectiveRange];
 
 
-        if (window->nblocks == window->cblocks)
-        {
-            int cblocks = window->cblocks * 2;
-            int* blocks = realloc(window->preeditAttributeBlocks, sizeof(int) * cblocks);
-            if (!blocks)
-                return;
+        window->preeditBlockCount++;
+        window->preeditBlocks = realloc(window->preeditBlocks,
+                                        window->preeditBlockCount * sizeof(int));
 
 
-            window->preeditAttributeBlocks = blocks;
-            window->cblocks = cblocks;
-        }
-
-        window->preeditAttributeBlocks[window->nblocks] = effectiveRange.length;
+        window->preeditBlocks[window->preeditBlockCount - 1] = effectiveRange.length;
         offset += effectiveRange.length;
         offset += effectiveRange.length;
         if (!effectiveRange.length)
         if (!effectiveRange.length)
             break;
             break;
 
 
         NSNumber* underline = (NSNumber*) [attributes objectForKey:@"NSUnderline"];
         NSNumber* underline = (NSNumber*) [attributes objectForKey:@"NSUnderline"];
         if ([underline intValue] != 1)
         if ([underline intValue] != 1)
-            focusedBlock = window->nblocks;
-
-        window->nblocks++;
+            focusedBlock = window->preeditBlockCount - 1;
     }
     }
 
 
     _glfwInputPreedit(window, focusedBlock);
     _glfwInputPreedit(window, focusedBlock);

+ 2 - 3
src/input.c

@@ -84,10 +84,9 @@ void _glfwInputPreedit(_GLFWwindow* window, int focusedBlock)
     if (window->callbacks.preedit)
     if (window->callbacks.preedit)
     {
     {
         window->callbacks.preedit((GLFWwindow*) window,
         window->callbacks.preedit((GLFWwindow*) window,
-                                  window->ntext,
                                   window->preeditText,
                                   window->preeditText,
-                                  window->nblocks,
-                                  window->preeditAttributeBlocks,
+                                  window->preeditBlockCount,
+                                  window->preeditBlocks,
                                   focusedBlock);
                                   focusedBlock);
     }
     }
 }
 }

+ 3 - 6
src/internal.h

@@ -374,13 +374,10 @@ struct _GLFWwindow
     // Virtual cursor position when cursor is disabled
     // Virtual cursor position when cursor is disabled
     double              virtualCursorPosX, virtualCursorPosY;
     double              virtualCursorPosX, virtualCursorPosY;
 
 
-    // Preedit texts
+    // IME preedit data
     unsigned int*       preeditText;
     unsigned int*       preeditText;
-    int                 ntext;
-    int                 ctext;
-    int*                preeditAttributeBlocks;
-    int                 nblocks;
-    int                 cblocks;
+    int*                preeditBlocks;
+    int                 preeditBlockCount;
     int                 preeditCaretPosX, preeditCaretPosY;
     int                 preeditCaretPosX, preeditCaretPosY;
     int                 preeditCaretHeight;
     int                 preeditCaretHeight;
 
 

+ 40 - 76
src/win32_window.c

@@ -425,12 +425,12 @@ static void releaseMonitor(_GLFWwindow* window)
 
 
 // Set cursor position to decide candidate window
 // Set cursor position to decide candidate window
 //
 //
-static void changeCaretPosition(HIMC imc, _GLFWwindow* window)
+static void updateCaretPosition(_GLFWwindow* window, HIMC imc)
 {
 {
     const int x = window->preeditCaretPosX;
     const int x = window->preeditCaretPosX;
     const int y = window->preeditCaretPosY;
     const int y = window->preeditCaretPosY;
     const int h = window->preeditCaretHeight;
     const int h = window->preeditCaretHeight;
-    CANDIDATEFORM excludeRect = {0, CFS_EXCLUDE, {x, y}, {x, y, x, y + h}};
+    CANDIDATEFORM excludeRect = { 0, CFS_EXCLUDE, { x, y }, { x, y, x, y + h } };
     ImmSetCandidateWindow(imc, &excludeRect);
     ImmSetCandidateWindow(imc, &excludeRect);
 }
 }
 
 
@@ -586,12 +586,15 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
         case WM_IME_COMPOSITION:
         case WM_IME_COMPOSITION:
         {
         {
             HIMC imc;
             HIMC imc;
-            LONG preeditTextLength, attrLength, clauseLength;
+            LONG textSize, attrSize, clauseSize;
+            int i, focusedBlock, length;
+            LPWSTR buffer;
+            LPSTR attributes;
+            DWORD* clauses;
 
 
             if (lParam & GCS_RESULTSTR)
             if (lParam & GCS_RESULTSTR)
             {
             {
-                window->nblocks = 0;
-                window->ntext = 0;
+                window->preeditBlockCount = 0;
                 _glfwInputPreedit(window, 0);
                 _glfwInputPreedit(window, 0);
                 return TRUE;
                 return TRUE;
             }
             }
@@ -600,87 +603,48 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
                 break;
                 break;
 
 
             imc = ImmGetContext(hWnd);
             imc = ImmGetContext(hWnd);
-            preeditTextLength = ImmGetCompositionStringW(imc, GCS_COMPSTR, NULL, 0);
-            attrLength = ImmGetCompositionString(imc, GCS_COMPATTR, NULL, 0);
-            clauseLength = ImmGetCompositionString(imc, GCS_COMPCLAUSE, NULL, 0);
+            textSize = ImmGetCompositionStringW(imc, GCS_COMPSTR, NULL, 0);
+            attrSize = ImmGetCompositionStringW(imc, GCS_COMPATTR, NULL, 0);
+            clauseSize = ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, NULL, 0);
 
 
-            if (preeditTextLength > 0)
+            if (textSize <= 0)
             {
             {
-                // get preedit data
-                int i, ctext, cblocks, focusedBlock, length = preeditTextLength / sizeof(WCHAR);
-                LPWSTR buffer = malloc(sizeof(WCHAR) + preeditTextLength);
-                LPSTR attributes = malloc(attrLength);
-                DWORD* clauses = malloc(clauseLength);
-
-                ImmGetCompositionStringW(imc, GCS_COMPSTR, buffer, preeditTextLength);
-                ImmGetCompositionString(imc, GCS_COMPATTR, attributes, attrLength);
-                ImmGetCompositionString(imc, GCS_COMPCLAUSE, clauses, clauseLength);
-
-                // store preedit text
-                ctext = window->ctext;
-                while (ctext < length + 1)
-                    ctext = ctext ? ctext * 2 : 1;
-
-                if (ctext != window->ctext)
-                {
-                    unsigned int* preeditText = realloc(window->preeditText, sizeof(unsigned int) * ctext);
-                    if (!preeditText)
-                    {
-                        free(buffer);
-                        free(attributes);
-                        free(clauses);
-                        return FALSE;
-                    }
+                ImmReleaseContext(hWnd, imc);
+                return TRUE;
+            }
 
 
-                    window->preeditText = preeditText;
-                    window->ctext = ctext;
-                }
+            length = textSize / sizeof(WCHAR);
+            buffer = calloc(length + 1, sizeof(WCHAR));
+            attributes = calloc(attrSize, 1);
+            clauses = calloc(clauseSize, 1);
 
 
-                window->ntext = length;
-                window->preeditText[length] = 0;
-                for (i = 0;  i < length;  i++)
-                    window->preeditText[i] = buffer[i];
+            ImmGetCompositionStringW(imc, GCS_COMPSTR, buffer, textSize);
+            ImmGetCompositionStringW(imc, GCS_COMPATTR, attributes, attrSize);
+            ImmGetCompositionStringW(imc, GCS_COMPCLAUSE, clauses, clauseSize);
 
 
-                // store blocks
-                window->nblocks = clauseLength / sizeof(DWORD) - 1;
+            free(window->preeditText);
+            window->preeditText = calloc(length + 1, sizeof(unsigned int));
+            memcpy(window->preeditText, buffer, sizeof(unsigned int) * length);
 
 
-                // last element of clauses is a block count, but
-                // text length is convenient.
-                clauses[window->nblocks] = length;
-                cblocks = window->cblocks;
-                while (cblocks < window->nblocks)
-                    cblocks = (cblocks == 0) ? 1 : cblocks * 2;
+            focusedBlock = 0;
 
 
-                if (cblocks != window->cblocks)
-                {
-                    int* blocks = realloc(window->preeditAttributeBlocks, sizeof(int) * cblocks);
-                    if (!blocks)
-                    {
-                        free(buffer);
-                        free(attributes);
-                        free(clauses);
-                        return FALSE;
-                    }
+            window->preeditBlockCount = clauseSize / sizeof(DWORD) - 1;
+            free(window->preeditBlocks);
+            window->preeditBlocks = calloc(window->preeditBlockCount, sizeof(int));
 
 
-                    window->preeditAttributeBlocks = blocks;
-                    window->cblocks = cblocks;
-                }
-
-                focusedBlock = 0;
-                for (i = 0;  i < window->nblocks;  i++)
-                {
-                    window->preeditAttributeBlocks[i] = clauses[i + 1] - clauses[i];
-                    if (attributes[clauses[i]] != ATTR_CONVERTED)
-                        focusedBlock = i;
-                }
+            for (i = 0;  i < window->preeditBlockCount;  i++)
+            {
+                window->preeditBlocks[i] = clauses[i + 1] - clauses[i];
+                if (attributes[clauses[i]] != ATTR_CONVERTED)
+                    focusedBlock = i;
+            }
 
 
-                free(buffer);
-                free(attributes);
-                free(clauses);
+            free(buffer);
+            free(attributes);
+            free(clauses);
 
 
-                _glfwInputPreedit(window, focusedBlock);
-                changeCaretPosition(imc, window);
-            }
+            _glfwInputPreedit(window, focusedBlock);
+            updateCaretPosition(window, imc);
 
 
             ImmReleaseContext(hWnd, imc);
             ImmReleaseContext(hWnd, imc);
             return TRUE;
             return TRUE;

+ 1 - 1
src/window.c

@@ -404,7 +404,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
     _glfwPlatformDestroyWindow(window);
     _glfwPlatformDestroyWindow(window);
 
 
     free(window->preeditText);
     free(window->preeditText);
-    free(window->preeditAttributeBlocks);
+    free(window->preeditBlocks);
 
 
     // Unlink window from global linked list
     // Unlink window from global linked list
     {
     {

+ 148 - 127
src/x11_window.c

@@ -440,194 +440,216 @@ static char** parseUriList(char* text, int* count)
     return paths;
     return paths;
 }
 }
 
 
-// Update cursor position to decide candidate window
-static void _ximChangeCursorPosition(XIC xic, _GLFWwindow* window)
+// Update caret position to decide candidate window
+//
+static void updateCaretPosition(_GLFWwindow* window, XIC xic)
 {
 {
-    XVaNestedList preedit_attr;
-    XPoint        spot;
+    XVaNestedList attributes;
+    XPoint spot;
 
 
     spot.x = window->preeditCursorPosX;
     spot.x = window->preeditCursorPosX;
     spot.y = window->preeditCursorPosY + window->preeditCursorHeight;
     spot.y = window->preeditCursorPosY + window->preeditCursorHeight;
-    preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
-    XSetICValues(xic, XNPreeditAttributes, preedit_attr, NULL);
-    XFree(preedit_attr);
+    attributes = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
+    XSetICValues(xic, XNPreeditAttributes, attributes, NULL);
+    XFree(attributes);
 }
 }
 
 
-// IME Start callback (do nothing)
-static void _ximPreeditStartCallback(XIC xic, XPointer clientData, XPointer callData)
+// IME start callback (do nothing)
+//
+static void preeditStartCallback(XIC xic, XPointer clientData, XPointer callData)
 {
 {
 }
 }
 
 
-// IME Done callback (do nothing)
-static void _ximPreeditDoneCallback(XIC xic, XPointer clientData, XPointer callData)
+// IME done callback (do nothing)
+//
+static void preeditDoneCallback(XIC xic, XPointer clientData, XPointer callData)
 {
 {
 }
 }
 
 
-// IME Draw callback
-static void _ximPreeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDrawCallbackStruct *callData)
+// IME draw callback
+//
+static void preeditDrawCallback(XIC xic, XPointer clientData, XIMPreeditDrawCallbackStruct* callData)
 {
 {
-    int i, j, length, ctext, rstart, rend;
+    int i, j, length, rstart, rend;
     XIMText* text;
     XIMText* text;
     const char* src;
     const char* src;
     unsigned int codePoint;
     unsigned int codePoint;
     unsigned int* preeditText;
     unsigned int* preeditText;
     XIMFeedback f;
     XIMFeedback f;
-    _GLFWwindow* window = (_GLFWwindow*)clientData;
+    _GLFWwindow* window = (_GLFWwindow*) clientData;
 
 
     // keep cursor position to reduce API call
     // keep cursor position to reduce API call
     int cursorX = window->preeditCursorPosX;
     int cursorX = window->preeditCursorPosX;
     int cursorY = window->preeditCursorPosY;
     int cursorY = window->preeditCursorPosY;
     int cursorHeight = window->preeditCursorHeight;
     int cursorHeight = window->preeditCursorHeight;
 
 
-    if (!callData->text) {
-        // preedit text is empty
-        window->ntext = 0;
-        window->nblocks = 0;
+    if (!callData->text)
+    {
+        // Composition string is empty
+        window->preeditBlockCount = 0;
         _glfwInputPreedit(window, 0);
         _glfwInputPreedit(window, 0);
         return;
         return;
-    } else {
+    }
+    else
+    {
         text = callData->text;
         text = callData->text;
         length = callData->chg_length;
         length = callData->chg_length;
-        if (text->encoding_is_wchar) {
+        if (text->encoding_is_wchar)
+        {
             // wchar is not supported
             // wchar is not supported
             return;
             return;
         }
         }
-        ctext = window->ctext;
-        while (ctext < length+1) {
-            ctext = (ctext == 0) ? 1 : ctext * 2;
-        }
-        if (ctext != window->ctext) {
-            preeditText = realloc(window->preeditText, sizeof(unsigned int)*ctext);
-            if (preeditText == NULL) {
-                return;
-            }
-            window->preeditText = preeditText;
-            window->ctext = ctext;
-        }
-        window->ntext = length;
-        window->preeditText[length] = 0;
-        if (window->cblocks == 0) {
-            window->preeditAttributeBlocks = malloc(sizeof(int)*4);
-            window->cblocks = 4;
-        }
+
+        free(window->preeditText);
+        window->preeditText = calloc(length + 1, sizeof(unsigned int));
+
+        if (!window->preeditBlocks)
+            window->preeditBlocks = calloc(4, sizeof(int));
+
         src = text->string.multi_byte;
         src = text->string.multi_byte;
         rend = 0;
         rend = 0;
         rstart = length;
         rstart = length;
-        for (i = 0, j = 0; i < text->length; i++) {
-            #if defined(X_HAVE_UTF8_STRING)
+
+        for (i = 0, j = 0;  i < text->length;  i++)
+        {
+#if defined(X_HAVE_UTF8_STRING)
             codePoint = decodeUTF8(&src);
             codePoint = decodeUTF8(&src);
-            #else
+#else
             codePoint = *src;
             codePoint = *src;
             src++;
             src++;
-            #endif
-            if (i < callData->chg_first || callData->chg_first+length < i) {
+#endif
+            if (i < callData->chg_first || callData->chg_first + length < i)
                 continue;
                 continue;
-            }
+
             window->preeditText[j++] = codePoint;
             window->preeditText[j++] = codePoint;
             f = text->feedback[i];
             f = text->feedback[i];
-            if ((f & XIMReverse) || (f & XIMHighlight)) {
+
+            if ((f & XIMReverse) || (f & XIMHighlight))
+            {
                 rend = i;
                 rend = i;
-                if (i < rstart) {
+                if (i < rstart)
                     rstart = i;
                     rstart = i;
-                }
             }
             }
         }
         }
-        if (rstart == length) {
-            window->nblocks = 1;
-            window->preeditAttributeBlocks[0] = length;
-            window->preeditAttributeBlocks[1] = 0;
+
+        if (rstart == length)
+        {
+            window->preeditBlockCount = 1;
+            window->preeditBlocks[0] = length;
+            window->preeditBlocks[1] = 0;
             _glfwInputPreedit(window, 0);
             _glfwInputPreedit(window, 0);
-        } else if (rstart == 0) {
-            if (rend == length -1) {
-                window->nblocks = 1;
-                window->preeditAttributeBlocks[0] = length;
-                window->preeditAttributeBlocks[1] = 0;
+        }
+        else if (rstart == 0)
+        {
+            if (rend == length -1)
+            {
+                window->preeditBlockCount = 1;
+                window->preeditBlocks[0] = length;
+                window->preeditBlocks[1] = 0;
                 _glfwInputPreedit(window, 0);
                 _glfwInputPreedit(window, 0);
-            } else {
-                window->nblocks = 2;
-                window->preeditAttributeBlocks[0] = rend + 1;
-                window->preeditAttributeBlocks[1] = length - rend - 1;
-                window->preeditAttributeBlocks[2] = 0;
+            }
+            else
+            {
+                window->preeditBlockCount = 2;
+                window->preeditBlocks[0] = rend + 1;
+                window->preeditBlocks[1] = length - rend - 1;
+                window->preeditBlocks[2] = 0;
                 _glfwInputPreedit(window, 0);
                 _glfwInputPreedit(window, 0);
             }
             }
-        } else if (rend == length -1) {
-            window->nblocks = 2;
-            window->preeditAttributeBlocks[0] = rstart;
-            window->preeditAttributeBlocks[1] = length - rstart;
-            window->preeditAttributeBlocks[2] = 0;
+        }
+        else if (rend == length -1)
+        {
+            window->preeditBlockCount = 2;
+            window->preeditBlocks[0] = rstart;
+            window->preeditBlocks[1] = length - rstart;
+            window->preeditBlocks[2] = 0;
             _glfwInputPreedit(window, 1);
             _glfwInputPreedit(window, 1);
-        } else {
-            window->nblocks = 3;
-            window->preeditAttributeBlocks[0] = rstart;
-            window->preeditAttributeBlocks[1] = rend - rstart + 1;
-            window->preeditAttributeBlocks[2] = length - rend - 1;
-            window->preeditAttributeBlocks[3] = 0;
+        }
+        else
+        {
+            window->preeditBlockCount = 3;
+            window->preeditBlocks[0] = rstart;
+            window->preeditBlocks[1] = rend - rstart + 1;
+            window->preeditBlocks[2] = length - rend - 1;
+            window->preeditBlocks[3] = 0;
             _glfwInputPreedit(window, 1);
             _glfwInputPreedit(window, 1);
         }
         }
-        if ((cursorX != window->preeditCursorPosX)
-                || (cursorY != window->preeditCursorPosY)
-                || (cursorHeight != window->preeditCursorHeight)) {
-            _ximChangeCursorPosition(xic, window);
+
+        if ((caretX != window->preeditCaretPosX) ||
+            (caretY != window->preeditCaretPosY) ||
+            (caretHeight != window->preeditCaretHeight))
+        {
+            updateCaretPosition(window, xic);
         }
         }
     }
     }
 }
 }
 
 
 // IME Caret callback (do nothing)
 // IME Caret callback (do nothing)
-static void _ximPreeditCaretCallback(XIC xic, XPointer clientData, XPointer callData)
+//
+static void preeditCaretCallback(XIC xic, XPointer clientData, XPointer callData)
 {
 {
 }
 }
 
 
-static void _ximStatusStartCallback(XIC xic, XPointer clientData, XPointer callData)
+static void statusStartCallback(XIC xic, XPointer clientData, XPointer callData)
 {
 {
-    _GLFWwindow* window = (_GLFWwindow*)clientData;
+    _GLFWwindow* window = (_GLFWwindow*) clientData;
     window->x11.imeFocus = GLFW_TRUE;
     window->x11.imeFocus = GLFW_TRUE;
 }
 }
 
 
-static void _ximStatusDoneCallback(XIC xic, XPointer clientData, XPointer callData)
+static void statusDoneCallback(XIC xic, XPointer clientData, XPointer callData)
 {
 {
-    _GLFWwindow* window = (_GLFWwindow*)clientData;
+    _GLFWwindow* window = (_GLFWwindow*) clientData;
     window->x11.imeFocus = GLFW_FALSE;
     window->x11.imeFocus = GLFW_FALSE;
 }
 }
 
 
-static void _ximStatusDrawCallback(XIC xic, XPointer clientData, XIMStatusDrawCallbackStruct* callData)
+static void statusDrawCallback(XIC xic, XPointer clientData, XIMStatusDrawCallbackStruct* callData)
 {
 {
-    _GLFWwindow* window = (_GLFWwindow*)clientData;
+    _GLFWwindow* window = (_GLFWwindow*) clientData;
     _glfwInputIMEStatus(window);
     _glfwInputIMEStatus(window);
 }
 }
 
 
 // Create XIM Preedit callback
 // Create XIM Preedit callback
+//
 static XVaNestedList _createXIMPreeditCallbacks(_GLFWwindow* window)
 static XVaNestedList _createXIMPreeditCallbacks(_GLFWwindow* window)
 {
 {
     window->x11.preeditStartCallback.client_data = (XPointer)window;
     window->x11.preeditStartCallback.client_data = (XPointer)window;
-    window->x11.preeditStartCallback.callback = (XIMProc)_ximPreeditStartCallback;
+    window->x11.preeditStartCallback.callback = (XIMProc) preeditStartCallback;
     window->x11.preeditDoneCallback.client_data = (XPointer)window;
     window->x11.preeditDoneCallback.client_data = (XPointer)window;
-    window->x11.preeditDoneCallback.callback = (XIMProc)_ximPreeditDoneCallback;
+    window->x11.preeditDoneCallback.callback = (XIMProc) preeditDoneCallback;
     window->x11.preeditDrawCallback.client_data = (XPointer)window;
     window->x11.preeditDrawCallback.client_data = (XPointer)window;
-    window->x11.preeditDrawCallback.callback = (XIMProc)_ximPreeditDrawCallback;
+    window->x11.preeditDrawCallback.callback = (XIMProc) preeditDrawCallback;
     window->x11.preeditCaretCallback.client_data = (XPointer)window;
     window->x11.preeditCaretCallback.client_data = (XPointer)window;
-    window->x11.preeditCaretCallback.callback = (XIMProc)_ximPreeditCaretCallback;
-    return XVaCreateNestedList (0,
-        XNPreeditStartCallback, &window->x11.preeditStartCallback.client_data,
-        XNPreeditDoneCallback, &window->x11.preeditDoneCallback.client_data,
-        XNPreeditDrawCallback, &window->x11.preeditDrawCallback.client_data,
-        XNPreeditCaretCallback, &window->x11.preeditCaretCallback.client_data,
-        NULL);
+    window->x11.preeditCaretCallback.callback = (XIMProc) preeditCaretCallback;
+    return XVaCreateNestedList(0,
+                               XNPreeditStartCallback,
+                               &window->x11.preeditStartCallback.client_data,
+                               XNPreeditDoneCallback,
+                               &window->x11.preeditDoneCallback.client_data,
+                               XNPreeditDrawCallback,
+                               &window->x11.preeditDrawCallback.client_data,
+                               XNPreeditCaretCallback,
+                               &window->x11.preeditCaretCallback.client_data,
+                               NULL);
 }
 }
 
 
 // Create XIM status callback
 // Create XIM status callback
+//
 static XVaNestedList _createXIMStatusCallbacks(_GLFWwindow* window)
 static XVaNestedList _createXIMStatusCallbacks(_GLFWwindow* window)
 {
 {
     window->x11.statusStartCallback.client_data = (XPointer)window;
     window->x11.statusStartCallback.client_data = (XPointer)window;
-    window->x11.statusStartCallback.callback = (XIMProc)_ximStatusStartCallback;
+    window->x11.statusStartCallback.callback = (XIMProc) statusStartCallback;
     window->x11.statusDoneCallback.client_data = (XPointer)window;
     window->x11.statusDoneCallback.client_data = (XPointer)window;
-    window->x11.statusDoneCallback.callback = (XIMProc)_ximStatusDoneCallback;
+    window->x11.statusDoneCallback.callback = (XIMProc) statusDoneCallback;
     window->x11.statusDrawCallback.client_data = (XPointer)window;
     window->x11.statusDrawCallback.client_data = (XPointer)window;
-    window->x11.statusDrawCallback.callback = (XIMProc)_ximStatusDrawCallback;
-    return XVaCreateNestedList (0,
-        XNStatusStartCallback, &window->x11.statusStartCallback.client_data,
-        XNStatusDoneCallback, &window->x11.statusDoneCallback.client_data,
-        XNStatusDrawCallback, &window->x11.statusDrawCallback.client_data,
-        NULL);
+    window->x11.statusDrawCallback.callback = (XIMProc) statusDrawCallback;
+    return XVaCreateNestedList(0,
+                               XNStatusStartCallback,
+                               &window->x11.statusStartCallback.client_data,
+                               XNStatusDoneCallback,
+                               &window->x11.statusDoneCallback.client_data,
+                               XNStatusDrawCallback,
+                               &window->x11.statusDrawCallback.client_data,
+                               NULL);
 }
 }
 
 
 // Centers the cursor over the window client area
 // Centers the cursor over the window client area
@@ -2682,47 +2704,46 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
     }
     }
 }
 }
 
 
-void _glfwPlatformResetPreeditText(_GLFWwindow* window) {
-    XIC ic = window->x11.ic;
-
-    /* restore conversion state after resetting ic later */
-    XIMPreeditState preedit_state = XIMPreeditUnKnown;
-    XVaNestedList preedit_attr;
+void _glfwPlatformResetPreeditText(_GLFWwindow* window)
+{
+    // Restore conversion state after resetting ic later
+    XIMPreeditState state = XIMPreeditUnKnown;
+    XVaNestedList attributes;
     char* result;
     char* result;
 
 
-    if (window->ntext == 0)
+    if (*window->preeditText == 0)
         return;
         return;
 
 
-    preedit_attr = XVaCreateNestedList(0, XNPreeditState, &preedit_state, NULL);
-    XGetICValues(ic, XNPreeditAttributes, preedit_attr, NULL);
-    XFree(preedit_attr);
+    attributes = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
+    XGetICValues(window->x11.ic, XNPreeditAttributes, attributes, NULL);
+    XFree(attributes);
 
 
-    result = XmbResetIC(ic);
+    result = XmbResetIC(window->x11.ic);
 
 
-    preedit_attr = XVaCreateNestedList(0, XNPreeditState, preedit_state, NULL);
-    XSetICValues(ic, XNPreeditAttributes, preedit_attr, NULL);
-    XFree(preedit_attr);
+    attributes = XVaCreateNestedList(0, XNPreeditState, state, NULL);
+    XSetICValues(window->x11.ic, XNPreeditAttributes, attributes, NULL);
+    XFree(attributes);
 
 
-    window->ntext = 0;
-    window->nblocks = 0;
+    window->preeditBlockCount = 0;
     _glfwInputPreedit(window, 0);
     _glfwInputPreedit(window, 0);
 
 
-    XFree (result);
+    XFree(result);
 }
 }
 
 
-void _glfwPlatformSetIMEStatus(_GLFWwindow* window, int active) {
-    XIC ic = window->x11.ic;
-    if (active) {
-        XSetICFocus(ic);
-    } else {
-        XUnsetICFocus(ic);
-    }
+void _glfwPlatformSetIMEStatus(_GLFWwindow* window, int active)
+{
+    if (active)
+        XSetICFocus(window->x11.ic);
+    else
+        XUnsetICFocus(window->x11.ic);
 }
 }
 
 
-int  _glfwPlatformGetIMEStatus(_GLFWwindow* window) {
+int _glfwPlatformGetIMEStatus(_GLFWwindow* window)
+{
     return window->x11.imeFocus;
     return window->x11.imeFocus;
 }
 }
 
 
+
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////                        GLFW native API                       //////
 //////                        GLFW native API                       //////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////

+ 2 - 3
tests/events.c

@@ -421,7 +421,6 @@ static void char_mods_callback(GLFWwindow* window, unsigned int codepoint, int m
 }
 }
 
 
 static void preedit_callback(GLFWwindow* window,
 static void preedit_callback(GLFWwindow* window,
-                             int strLength,
                              unsigned int* string,
                              unsigned int* string,
                              int blockLength,
                              int blockLength,
                              int* blocks,
                              int* blocks,
@@ -434,9 +433,9 @@ static void preedit_callback(GLFWwindow* window,
     printf("%08x to %i at %0.3f: Preedit text ",
     printf("%08x to %i at %0.3f: Preedit text ",
            counter++, slot->number, glfwGetTime());
            counter++, slot->number, glfwGetTime());
 
 
-    if (strLength && blockLength)
+    if (*string && blockLength)
     {
     {
-        for (i = 0;  i < strLength;  i++)
+        for (i = 0;  string[i];  i++)
         {
         {
             if (blockCount == 0)
             if (blockCount == 0)
             {
             {