Prechádzať zdrojové kódy

X11TK: Introduce Thai support and rewrite/cleanup messagebox positioning code (#14474)

eafton 3 týždňov pred
rodič
commit
36976ecb43

+ 3 - 0
CMakeLists.txt

@@ -349,6 +349,8 @@ dep_option(SDL_X11_XSYNC           "Enable Xsync support" ON SDL_X11 OFF)
 dep_option(SDL_X11_XTEST           "Enable XTest support" ON SDL_X11 OFF)
 dep_option(SDL_X11_XTEST           "Enable XTest support" ON SDL_X11 OFF)
 dep_option(SDL_FRIBIDI             "Enable Fribidi support" ON SDL_X11 OFF)
 dep_option(SDL_FRIBIDI             "Enable Fribidi support" ON SDL_X11 OFF)
 dep_option(SDL_FRIBIDI_SHARED      "Dynamically load Fribidi support" ON "SDL_FRIBIDI;SDL_DEPS_SHARED" OFF)
 dep_option(SDL_FRIBIDI_SHARED      "Dynamically load Fribidi support" ON "SDL_FRIBIDI;SDL_DEPS_SHARED" OFF)
+dep_option(SDL_LIBTHAI             "Enable Thai support" ON SDL_X11 OFF)
+dep_option(SDL_LIBTHAI_SHARED      "Dynamically load Thai support" ON "SDL_LIBTHAI;SDL_DEPS_SHARED" OFF)
 dep_option(SDL_WAYLAND             "Use Wayland video driver" ${UNIX_SYS} "SDL_VIDEO" OFF)
 dep_option(SDL_WAYLAND             "Use Wayland video driver" ${UNIX_SYS} "SDL_VIDEO" OFF)
 dep_option(SDL_WAYLAND_SHARED      "Dynamically load Wayland support" ON "SDL_WAYLAND;SDL_DEPS_SHARED" OFF)
 dep_option(SDL_WAYLAND_SHARED      "Dynamically load Wayland support" ON "SDL_WAYLAND;SDL_DEPS_SHARED" OFF)
 dep_option(SDL_WAYLAND_LIBDECOR    "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF)
 dep_option(SDL_WAYLAND_LIBDECOR    "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF)
@@ -1813,6 +1815,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
     CheckROCKCHIP()
     CheckROCKCHIP()
     CheckX11()
     CheckX11()
     CheckFribidi()
     CheckFribidi()
+    CheckLibThai()
     # Need to check for EGL first because KMSDRM and Wayland depend on it.
     # Need to check for EGL first because KMSDRM and Wayland depend on it.
     CheckEGL()
     CheckEGL()
     CheckKMSDRM()
     CheckKMSDRM()

+ 25 - 0
cmake/sdlchecks.cmake

@@ -588,6 +588,31 @@ macro(CheckFribidi)
   endif()
   endif()
 endmacro()
 endmacro()
 
 
+macro(CheckLibThai)
+  if(SDL_LIBTHAI)
+    set(LIBTHAI_PKG_CONFIG_SPEC libthai)
+    set(PC_LIBTHAI_FOUND FALSE)
+    if(PKG_CONFIG_FOUND)
+      pkg_check_modules(PC_LIBTHAI IMPORTED_TARGET ${LIBTHAI_PKG_CONFIG_SPEC})
+    endif()
+    if(PC_LIBTHAI_FOUND)
+      set(HAVE_LIBTHAI TRUE)
+      set(HAVE_LIBTHAI_H 1)
+      if(SDL_LIBTHAI_SHARED AND NOT HAVE_SDL_LOADSO)
+        message(WARNING "You must have SDL_LoadObject() support for dynamic libthai loading")
+      endif()
+      FindLibraryAndSONAME("thai" LIBDIRS ${PC_LIBTHAI_LIBRARY_DIRS})
+      if(SDL_LIBTHAI_SHARED AND THAI_LIB AND HAVE_SDL_LOADSO)
+        set(SDL_LIBTHAI_DYNAMIC "\"${THAI_LIB_SONAME}\"")
+        set(HAVE_LIBTHAI_SHARED TRUE)
+        sdl_include_directories(PRIVATE SYSTEM $<TARGET_PROPERTY:PkgConfig::PC_LIBTHAI,INTERFACE_INCLUDE_DIRECTORIES>)
+      else()
+        sdl_link_dependency(libthai LIBS PkgConfig::PC_LIBTHAI PKG_CONFIG_PREFIX PC_LIBTHAI PKG_CONFIG_SPECS ${LIBTHAI_PKG_CONFIG_SPEC})
+      endif()
+    endif()
+  endif()
+endmacro()
+
 macro(WaylandProtocolGen _SCANNER _CODE_MODE _XML _PROTL)
 macro(WaylandProtocolGen _SCANNER _CODE_MODE _XML _PROTL)
     set(_WAYLAND_PROT_C_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
     set(_WAYLAND_PROT_C_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
     set(_WAYLAND_PROT_H_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-client-protocol.h")
     set(_WAYLAND_PROT_H_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-client-protocol.h")

+ 2 - 0
include/build_config/SDL_build_config.h.cmake

@@ -218,6 +218,8 @@
 #cmakedefine HAVE_LIBURING_H 1
 #cmakedefine HAVE_LIBURING_H 1
 #cmakedefine HAVE_FRIBIDI_H 1
 #cmakedefine HAVE_FRIBIDI_H 1
 #cmakedefine SDL_FRIBIDI_DYNAMIC @SDL_FRIBIDI_DYNAMIC@
 #cmakedefine SDL_FRIBIDI_DYNAMIC @SDL_FRIBIDI_DYNAMIC@
+#cmakedefine HAVE_LIBTHAI_H 1
+#cmakedefine SDL_LIBTHAI_DYNAMIC @SDL_LIBTHAI_DYNAMIC@
 
 
 #cmakedefine HAVE_DDRAW_H 1
 #cmakedefine HAVE_DDRAW_H 1
 #cmakedefine HAVE_DSOUND_H 1
 #cmakedefine HAVE_DSOUND_H 1

+ 76 - 0
src/core/unix/SDL_libthai.c

@@ -0,0 +1,76 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+#ifdef HAVE_LIBTHAI_H
+
+#include "SDL_libthai.h"
+
+#ifdef SDL_LIBTHAI_DYNAMIC
+SDL_ELF_NOTE_DLOPEN(
+    "Thai",
+    "Thai language support",
+    SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
+    SDL_LIBTHAI_DYNAMIC
+);
+#endif
+
+
+SDL_LibThai *SDL_LibThai_Create(void)
+{
+    SDL_LibThai *th;
+
+    th = (SDL_LibThai *)SDL_malloc(sizeof(SDL_LibThai));
+    if (!th) {
+        return NULL;
+    }
+
+#ifdef SDL_LIBTHAI_DYNAMIC
+    #define SDL_LIBTHAI_LOAD_SYM(a, x, n, t) x = ((t)SDL_LoadFunction(a->lib, n)); if (!x) { SDL_UnloadObject(a->lib); SDL_free(a); return NULL; }
+
+    th->lib = SDL_LoadObject(SDL_LIBTHAI_DYNAMIC);
+    if (!th->lib) {
+        SDL_free(th);
+        return NULL;
+    }
+
+    SDL_LIBTHAI_LOAD_SYM(th, th->make_cells, "th_make_cells", SDL_LibThaiMakeCells);
+#else
+    th->make_cells = th_make_cells;
+#endif
+
+    return th;
+}
+
+void SDL_LibThai_Destroy(SDL_LibThai *th)
+{
+    if (!th) {
+        return;
+    }
+
+#ifdef SDL_LIBTHAI_DYNAMIC
+    SDL_UnloadObject(th->lib);
+#endif
+
+    SDL_free(th);
+}
+
+#endif

+ 43 - 0
src/core/unix/SDL_libthai.h

@@ -0,0 +1,43 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_internal.h"
+
+#ifndef SDL_libthai_h_
+#define SDL_libthai_h_
+
+#ifdef HAVE_LIBTHAI_H
+#include <thai/thcell.h>
+
+typedef size_t (*SDL_LibThaiMakeCells)(const thchar_t *s, size_t, struct thcell_t cells[], size_t *, int);
+
+typedef struct SDL_LibThai {
+    SDL_SharedObject *lib;
+ 
+    SDL_LibThaiMakeCells make_cells;
+} SDL_LibThai;
+
+extern SDL_LibThai *SDL_LibThai_Create(void);
+extern void SDL_LibThai_Destroy(SDL_LibThai *th);
+
+#endif // HAVE_LIBTHAI_H
+
+#endif // SDL_libthai_h_

+ 131 - 202
src/video/x11/SDL_x11messagebox.c

@@ -28,7 +28,7 @@
 #include "SDL_x11toolkit.h"
 #include "SDL_x11toolkit.h"
 
 
 #ifndef SDL_FORK_MESSAGEBOX
 #ifndef SDL_FORK_MESSAGEBOX
-#define SDL_FORK_MESSAGEBOX 1
+#define SDL_FORK_MESSAGEBOX 0
 #endif
 #endif
 
 
 #if SDL_FORK_MESSAGEBOX
 #if SDL_FORK_MESSAGEBOX
@@ -38,246 +38,181 @@
 #include <errno.h>
 #include <errno.h>
 #endif
 #endif
 
 
-typedef struct SDL_MessageBoxCallbackDataX11
-{
-    int *buttonID;
-    SDL_ToolkitWindowX11 *window;
-} SDL_MessageBoxCallbackDataX11;
-
-typedef struct SDL_MessageBoxControlsX11
+typedef struct SDL_MessageBoxX11
 {
 {
     SDL_ToolkitWindowX11 *window;
     SDL_ToolkitWindowX11 *window;
     SDL_ToolkitControlX11 *icon;
     SDL_ToolkitControlX11 *icon;
-    SDL_ToolkitControlX11 fake_icon;
     SDL_ToolkitControlX11 *message;
     SDL_ToolkitControlX11 *message;
     SDL_ToolkitControlX11 **buttons;
     SDL_ToolkitControlX11 **buttons;
     const SDL_MessageBoxData *messageboxdata;
     const SDL_MessageBoxData *messageboxdata;
-} SDL_MessageBoxControlsX11;
+    int *buttonID;
+} SDL_MessageBoxX11;
 
 
 static void X11_MessageBoxButtonCallback(SDL_ToolkitControlX11 *control, void *data)
 static void X11_MessageBoxButtonCallback(SDL_ToolkitControlX11 *control, void *data)
 {
 {
-    SDL_MessageBoxCallbackDataX11 *cbdata;
+    SDL_MessageBoxX11 *cbdata;
 
 
-    cbdata = (SDL_MessageBoxCallbackDataX11 *)data;
+    cbdata = data;
     *cbdata->buttonID = X11Toolkit_GetButtonControlData(control)->buttonID;
     *cbdata->buttonID = X11Toolkit_GetButtonControlData(control)->buttonID;
     X11Toolkit_SignalWindowClose(cbdata->window);
     X11Toolkit_SignalWindowClose(cbdata->window);
 }
 }
 
 
-static void X11_PositionMessageBox(SDL_MessageBoxControlsX11 *controls, int *wp, int *hp) {
-    int max_button_w;
-    int max_button_h;
-    int total_button_w;
-    int total_text_and_icon_w;
-    int w;
-    int h;
+static void X11_PositionMessageBox(SDL_MessageBoxX11 *controls, int *wp, int *hp) {
+    int first_line_width;
+    int first_line_height;
+    int second_line_width;
+    int second_line_height;
+    int max_button_width;
+    int max_button_height;
+    int window_width;
+    int window_height;
     int i;
     int i;
-    int t;
-
-    /* Init vars */
-    max_button_w = 50;
-    max_button_h = 0;
-    w = h = 2;
-    i = t = total_button_w = total_text_and_icon_w = 0;
-    max_button_w *= controls->window->iscale;
-
-    /* Positioning and sizing */
-    for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
-        max_button_w = SDL_max(max_button_w, controls->buttons[i]->rect.w);
-        max_button_h = SDL_max(max_button_h, controls->buttons[i]->rect.h);
-        controls->buttons[i]->rect.x = 0;
-    }
-
-    if (controls->icon) {
-        controls->icon->rect.x = controls->icon->rect.y = 0;
-    }
-
-    if (controls->icon) {
-        controls->message->rect.x = (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) + controls->icon->rect.x + controls->icon->rect.w;
-        controls->message->rect.y = X11Toolkit_GetIconControlCharY(controls->icon);
+    bool rtl;
+    
+    /* window size */
+    window_width = 1;
+    window_height = 1;
+    
+    /* rtl */
+    if (controls->messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
+        rtl = true;
+    } else if (controls->messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT) {
+        rtl = false;
     } else {
     } else {
+        rtl = controls->window->flip_interface;
+    }
+    
+    /* first line */
+    first_line_width = first_line_height = 0;
+    if (controls->icon && controls->message) {
+        controls->icon->rect.y = 0;
+        
+        first_line_width = controls->icon->rect.w + SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale + controls->message->rect.w;  
+        
+        if (!controls->window->flip_interface) {
+            controls->message->rect.x = controls->icon->rect.w + SDL_TOOLKIT_X11_ELEMENT_PADDING_2  * controls->window->iscale;
+            controls->icon->rect.x = 0;
+        } else {
+            controls->message->rect.x = 0;    
+            controls->icon->rect.x = controls->message->rect.w + SDL_TOOLKIT_X11_ELEMENT_PADDING_2  * controls->window->iscale;;
+        }
+        
+        if (controls->message->rect.h > controls->icon->rect.h) {
+            controls->message->rect.y = (controls->icon->rect.h - X11Toolkit_GetLabelControlFirstLineHeight(controls->message))/2;
+            first_line_height = controls->message->rect.y + controls->message->rect.h;
+        } else {
+            controls->message->rect.y = (controls->icon->rect.h - controls->message->rect.h)/2;
+            first_line_height = controls->icon->rect.h;
+        }        
+    } else if (!controls->icon && controls->message) {
+        first_line_width = controls->message->rect.w;  
+        first_line_height = controls->message->rect.h;
         controls->message->rect.x = 0;
         controls->message->rect.x = 0;
-        controls->message->rect.y = -2  * controls->window->iscale;
-        controls->icon = &controls->fake_icon;
-        controls->icon->rect.w = 0;
-        controls->icon->rect.h = 0;
+        controls->message->rect.y = 0;
+    } else if (controls->icon && !controls->message) {
+        first_line_width = controls->icon->rect.w;  
+        first_line_height = controls->icon->rect.h;
         controls->icon->rect.x = 0;
         controls->icon->rect.x = 0;
-        controls->icon->rect.y = 0;
+        controls->icon->rect.y = 0;        
     }
     }
-    if (controls->messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
-        for (i = controls->messageboxdata->numbuttons; i != -1; i--) {
-            controls->buttons[i]->rect.w = max_button_w;
-            controls->buttons[i]->rect.h = max_button_h;
+    
+    /* second line */
+    max_button_width = 50;
+    max_button_height = 0;
+    second_line_width = second_line_height = 0;
+    
+    for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
+        max_button_width = SDL_max(max_button_width, controls->buttons[i]->rect.w);
+        max_button_height = SDL_max(max_button_height, controls->buttons[i]->rect.h);
+        controls->buttons[i]->rect.x = 0;
+        controls->buttons[i]->rect.y = 0;
+    }
+
+    if (rtl) {
+        for (i = (controls->messageboxdata->numbuttons - 1); i != -1; i--) {
+            controls->buttons[i]->rect.w = max_button_width;
+            controls->buttons[i]->rect.h = max_button_height;
             X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]);
             X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]);
 
 
-            if (controls->icon->rect.h > controls->message->rect.h) {
-                controls->buttons[i]->rect.y = controls->icon->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 *controls-> window->iscale);
+            if (first_line_height) {
+                controls->buttons[i]->rect.y = first_line_height + SDL_TOOLKIT_X11_ELEMENT_PADDING_4 * controls->window->iscale;
+                second_line_height = max_button_height + SDL_TOOLKIT_X11_ELEMENT_PADDING_4 * controls->window->iscale;
             } else {
             } else {
-                controls->buttons[i]->rect.y = controls->message->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
+                second_line_height = max_button_height;
             }
             }
-
-            if (i) {
-                controls->buttons[i]->rect.x = controls->buttons[i-1]->rect.x + controls->buttons[i-1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale);
+            
+            if ((i + 1) < controls->messageboxdata->numbuttons) {
+                controls->buttons[i]->rect.x = controls->buttons[i + 1]->rect.x + controls->buttons[i + 1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale);
             }
             }
-        }
+        }    
     } else {
     } else {
         for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
         for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
-            controls->buttons[i]->rect.w = max_button_w;
-            controls->buttons[i]->rect.h = max_button_h;
+            controls->buttons[i]->rect.w = max_button_width;
+            controls->buttons[i]->rect.h = max_button_height;
             X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]);
             X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]);
 
 
-            if (controls->icon->rect.h > controls->message->rect.h) {
-                controls->buttons[i]->rect.y = controls->icon->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
+            if (first_line_height) {
+                controls->buttons[i]->rect.y = first_line_height + SDL_TOOLKIT_X11_ELEMENT_PADDING_4 * controls->window->iscale;
+                second_line_height = max_button_height + SDL_TOOLKIT_X11_ELEMENT_PADDING_4 * controls->window->iscale;
             } else {
             } else {
-                controls->buttons[i]->rect.y = controls->message->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
+                second_line_height = max_button_height;
             }
             }
-
+            
             if (i) {
             if (i) {
                 controls->buttons[i]->rect.x = controls->buttons[i-1]->rect.x + controls->buttons[i-1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale);
                 controls->buttons[i]->rect.x = controls->buttons[i-1]->rect.x + controls->buttons[i-1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale);
             }
             }
         }
         }
     }
     }
-    total_button_w = controls->buttons[controls->messageboxdata->numbuttons-1]->rect.x + controls->buttons[controls->messageboxdata->numbuttons-1]->rect.w;
-    total_text_and_icon_w =  controls->message->rect.x + controls->message->rect.w;
-    if (total_button_w > total_text_and_icon_w) {
-        w = total_button_w;
-    } else {
-        w = total_text_and_icon_w;
-    }
-    w += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) * 2;
-    if (controls->message->rect.h > controls->icon->rect.h) {
-        h = controls->message->rect.h;
-    } else {
-        h = controls->icon->rect.h;
-    }
-    h += max_button_h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) * 3;
-    t = (w - total_text_and_icon_w) / 2;
-    controls->icon->rect.x += t;
-    controls->message->rect.x += t;
-    controls->icon->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-    controls->message->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-    t = (w - total_button_w) / 2;
-    for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
-        controls->buttons[i]->rect.x += t;
-        controls->buttons[i]->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-    }
-    if (!controls->messageboxdata->message) {
-        controls->icon->rect.x = (w - controls->icon->rect.w)/2;
-    }
-
-    *wp = w;
-    *hp = h;
-}
-
-static void X11_PositionMessageBoxFlipped(SDL_MessageBoxControlsX11 *controls, int *wp, int *hp)
-{
-    int max_button_w;
-    int max_button_h;
-    int total_button_w;
-    int total_text_and_icon_w;
-    int w;
-    int h;
-    int i;
-    int t;
-
-    /* Init vars */
-    max_button_w = 50;
-    max_button_h = 0;
-    w = h = 2;
-    i = t = total_button_w = total_text_and_icon_w = 0;
-    max_button_w *= controls->window->iscale;
-
-    /* Positioning and sizing */
-    for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
-        max_button_w = SDL_max(max_button_w, controls->buttons[i]->rect.w);
-        max_button_h = SDL_max(max_button_h, controls->buttons[i]->rect.h);
-        controls->buttons[i]->rect.x = 0;
-    }
-
-    if (controls->icon) {
-        controls->icon->rect.y = 0;
-    }
-
-    if (controls->icon) {
-        controls->message->rect.x = 0;
-        controls->message->rect.y = X11Toolkit_GetIconControlCharY(controls->icon);
-        controls->icon->rect.x = (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) + controls->message->rect.w + controls->message->rect.x;
-   } else {
-        controls->message->rect.x = 0;
-        controls->message->rect.y = -2  * controls->window->iscale;
-        controls->icon = &controls->fake_icon;
-        controls->icon->rect.w = 0;
-        controls->icon->rect.h = 0;
-        controls->icon->rect.x = 0;
-        controls->icon->rect.y = 0;
+    
+    if (controls->messageboxdata->numbuttons) {
+        if (rtl) {
+            second_line_width = controls->buttons[0]->rect.x + controls->buttons[0]->rect.w;
+        } else {
+            second_line_width = controls->buttons[controls->messageboxdata->numbuttons - 1]->rect.x + controls->buttons[controls->messageboxdata->numbuttons - 1]->rect.w;            
+        }
     }
     }
-    if (controls->messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
-        for (i = controls->messageboxdata->numbuttons; i != -1; i--) {
-            controls->buttons[i]->rect.w = max_button_w;
-            controls->buttons[i]->rect.h = max_button_h;
-            X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]);
 
 
-            if (controls->icon->rect.h > controls->message->rect.h) {
-                controls->buttons[i]->rect.y = controls->icon->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 *controls-> window->iscale);
-            } else {
-                controls->buttons[i]->rect.y = controls->message->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-            }
-
-            if (i) {
-                controls->buttons[i]->rect.x = controls->buttons[i-1]->rect.x + controls->buttons[i-1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale);
-            }
+    /* center lines */
+    if (second_line_width > first_line_width) {
+        int pad;
+        
+        pad = (second_line_width - first_line_width)/2;
+        if (controls->message) {
+            controls->message->rect.x += pad;
+        }
+        if (controls->icon) {
+            controls->icon->rect.x += pad;
         }
         }
     } else {
     } else {
+        int pad;
+        
+        pad = (first_line_width - second_line_width)/2;
         for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
         for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
-            controls->buttons[i]->rect.w = max_button_w;
-            controls->buttons[i]->rect.h = max_button_h;
-            X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]);
-
-            if (controls->icon->rect.h > controls->message->rect.h) {
-                controls->buttons[i]->rect.y = controls->icon->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-            } else {
-                controls->buttons[i]->rect.y = controls->message->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-            }
-
-            if (i) {
-                controls->buttons[i]->rect.x = controls->buttons[i-1]->rect.x + controls->buttons[i-1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale);
-            }
+            controls->buttons[i]->rect.x += pad;
         }
         }
     }
     }
-    total_button_w = controls->buttons[controls->messageboxdata->numbuttons-1]->rect.x + controls->buttons[controls->messageboxdata->numbuttons-1]->rect.w;
-    total_text_and_icon_w =  controls->message->rect.w + controls->icon->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-    if (total_button_w > total_text_and_icon_w) {
-        w = total_button_w;
-    } else {
-        w = total_text_and_icon_w;
+     
+    /* window size and final padding */
+    window_width = SDL_max(first_line_width, second_line_width) + SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * 2 * controls->window->iscale;
+    window_height = first_line_height + second_line_height + SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * 2 * controls->window->iscale;
+    *wp = window_width;
+    *hp = window_height;
+    if (controls->message) {
+        controls->message->rect.x += SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale;
+        controls->message->rect.y += SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale;
     }
     }
-    w += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) * 2;
-    if (controls->message->rect.h > controls->icon->rect.h) {
-        h = controls->message->rect.h;
-    } else {
-        h = controls->icon->rect.h;
+    if (controls->icon) {
+        controls->icon->rect.x += SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale;
+        controls->icon->rect.y += SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale;
     }
     }
-    h += max_button_h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) * 3;
-    t = (w - total_text_and_icon_w) / 2;
-    controls->icon->rect.x += t;
-    controls->message->rect.x += t;
-    controls->icon->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-    controls->message->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
-    t = (w - total_button_w) / 2;
     for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
     for (i = 0; i < controls->messageboxdata->numbuttons; i++) {
-        controls->buttons[i]->rect.x += t;
-        controls->buttons[i]->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale);
+        controls->buttons[i]->rect.x += SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale;
+        controls->buttons[i]->rect.y += SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale;
     }
     }
-    if (!controls->messageboxdata->message) {
-        controls->icon->rect.x = (w - controls->icon->rect.w)/2;
-    }
-
-    *wp = w;
-    *hp = h;
 }
 }
 
 
-
 static void X11_OnMessageBoxScaleChange(SDL_ToolkitWindowX11 *window, void *data) {
 static void X11_OnMessageBoxScaleChange(SDL_ToolkitWindowX11 *window, void *data) {
-    SDL_MessageBoxControlsX11 *controls;
+    SDL_MessageBoxX11 *controls;
     int w;
     int w;
     int h;
     int h;
 
 
@@ -290,8 +225,7 @@ static bool X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int
 {
 {
     SDL_VideoDevice *video = SDL_GetVideoDevice();
     SDL_VideoDevice *video = SDL_GetVideoDevice();
     SDL_Window *parent_window = NULL;
     SDL_Window *parent_window = NULL;
-    SDL_MessageBoxControlsX11 controls;
-    SDL_MessageBoxCallbackDataX11 data;
+    SDL_MessageBoxX11 controls;
     const SDL_MessageBoxColor *colorhints;
     const SDL_MessageBoxColor *colorhints;
     int i;
     int i;
     int w;
     int w;
@@ -323,22 +257,17 @@ static bool X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int
     }
     }
 
 
     /* Create controls */
     /* Create controls */
+    controls.buttonID = buttonID;
     controls.buttons = SDL_calloc(messageboxdata->numbuttons, sizeof(SDL_ToolkitControlX11 *));
     controls.buttons = SDL_calloc(messageboxdata->numbuttons, sizeof(SDL_ToolkitControlX11 *));
     controls.icon = X11Toolkit_CreateIconControl(controls.window, messageboxdata->flags);
     controls.icon = X11Toolkit_CreateIconControl(controls.window, messageboxdata->flags);
     controls.message = X11Toolkit_CreateLabelControl(controls.window, (char *)messageboxdata->message);
     controls.message = X11Toolkit_CreateLabelControl(controls.window, (char *)messageboxdata->message);
-    data.buttonID = buttonID;
-    data.window = controls.window;
     for (i = 0; i < messageboxdata->numbuttons; i++) {
     for (i = 0; i < messageboxdata->numbuttons; i++) {
         controls.buttons[i] = X11Toolkit_CreateButtonControl(controls.window, &messageboxdata->buttons[i]);
         controls.buttons[i] = X11Toolkit_CreateButtonControl(controls.window, &messageboxdata->buttons[i]);
-        X11Toolkit_RegisterCallbackForButtonControl(controls.buttons[i], &data, X11_MessageBoxButtonCallback);
+        X11Toolkit_RegisterCallbackForButtonControl(controls.buttons[i], &controls, X11_MessageBoxButtonCallback);
     }
     }
 
 
     /* Positioning */
     /* Positioning */
-    if (data.window->flip_interface) {
-        X11_PositionMessageBoxFlipped(&controls, &w, &h);
-    } else {
-        X11_PositionMessageBox(&controls, &w, &h);
-    }
+    X11_PositionMessageBox(&controls, &w, &h);
 
 
     /* Actually create window, do event loop, cleanup */
     /* Actually create window, do event loop, cleanup */
     X11Toolkit_CreateWindowRes(controls.window, w, h, 0, 0, (char *)messageboxdata->title);
     X11Toolkit_CreateWindowRes(controls.window, w, h, 0, 0, (char *)messageboxdata->title);

+ 1 - 0
src/video/x11/SDL_x11sym.h

@@ -56,6 +56,7 @@ SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c))
 SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b))
 SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b))
 SDL_X11_SYM(int,XDisplayKeycodes,(Display* a,int* b,int* c))
 SDL_X11_SYM(int,XDisplayKeycodes,(Display* a,int* b,int* c))
 SDL_X11_SYM(int,XDrawRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g))
 SDL_X11_SYM(int,XDrawRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g))
+SDL_X11_SYM(int,XFontsOfFontSet,(XFontSet a,XFontStruct ***b,char ***c))
 SDL_X11_SYM(int,XFillArc,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g, int h, int i))
 SDL_X11_SYM(int,XFillArc,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g, int h, int i))
 SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a))
 SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a))
 SDL_X11_SYM(int,XDrawString,(Display* a,Drawable b,GC c,int d,int e,_Xconst char* f,int g))
 SDL_X11_SYM(int,XDrawString,(Display* a,Drawable b,GC c,int d,int e,_Xconst char* f,int g))

+ 516 - 226
src/video/x11/SDL_x11toolkit.c

@@ -42,6 +42,35 @@
 #define SDL_SET_LOCALE 1
 #define SDL_SET_LOCALE 1
 #define SDL_GRAB 1
 #define SDL_GRAB 1
 
 
+typedef enum SDL_ToolkitTextTypeX11
+{
+    SDL_TOOLKIT_TEXT_TYPE_X11_GENERIC,
+    SDL_TOOLKIT_TEXT_TYPE_X11_THAI
+} SDL_ToolkitTextTypeX11;
+
+#ifdef HAVE_LIBTHAI_H
+typedef struct SDL_ToolkitThaiOverlayX11
+{
+    bool top;
+    char *str;
+    size_t sz;
+    SDL_Rect rect;
+} SDL_ToolkitThaiOverlayX11;
+#endif
+
+typedef struct SDL_ToolkitTextElementX11
+{
+    SDL_ToolkitTextTypeX11 type;
+    char *str;
+    size_t sz;
+    SDL_Rect rect;
+    int font_h;
+    void (*str_free)(void *);
+#ifdef HAVE_LIBTHAI_H
+    SDL_ListNode *thai_overlays;
+#endif
+} SDL_ToolkitTextElementX11;
+
 typedef struct SDL_ToolkitIconControlX11
 typedef struct SDL_ToolkitIconControlX11
 {
 {
     SDL_ToolkitControlX11 parent;
     SDL_ToolkitControlX11 parent;
@@ -75,25 +104,28 @@ typedef struct SDL_ToolkitButtonControlX11
     const SDL_MessageBoxButtonData *data;
     const SDL_MessageBoxButtonData *data;
 
 
     /* Text */
     /* Text */
+    SDL_ListNode *text;
     SDL_Rect text_rect;
     SDL_Rect text_rect;
-    int text_a;
-    int text_d;
-    int str_sz;
-#ifdef HAVE_FRIBIDI_H
-    char *text;
-    bool free_text;
-#endif
-
+    
     /* Callback */
     /* Callback */
     void *cb_data;
     void *cb_data;
     void (*cb)(struct SDL_ToolkitControlX11 *, void *);
     void (*cb)(struct SDL_ToolkitControlX11 *, void *);
 } SDL_ToolkitButtonControlX11;
 } SDL_ToolkitButtonControlX11;
 
 
+typedef struct SDL_ToolkitLabelControlLineX11
+{
+    SDL_ListNode *text;
+    SDL_Rect rect;
+#ifdef HAVE_FRIBIDI_H
+    FriBidiParType par;
+#endif
+} SDL_ToolkitLabelControlLineX11;
+
 typedef struct SDL_ToolkitLabelControlX11
 typedef struct SDL_ToolkitLabelControlX11
 {
 {
     SDL_ToolkitControlX11 parent;
     SDL_ToolkitControlX11 parent;
 
 
-    char **lines;
+ /*   char **lines;
     int *y;
     int *y;
     size_t *szs;
     size_t *szs;
     size_t sz;
     size_t sz;
@@ -102,7 +134,9 @@ typedef struct SDL_ToolkitLabelControlX11
     int *w;
     int *w;
     bool *free_lines;
     bool *free_lines;
     FriBidiParType *par_types;
     FriBidiParType *par_types;
-#endif
+#endif*/
+    SDL_ToolkitLabelControlLineX11 *lines;
+    size_t sz;
 } SDL_ToolkitLabelControlX11;
 } SDL_ToolkitLabelControlX11;
 
 
 typedef struct SDL_ToolkitMenuBarControlX11
 typedef struct SDL_ToolkitMenuBarControlX11
@@ -258,7 +292,9 @@ static void X11Toolkit_InitWindowPixmap(SDL_ToolkitWindowX11 *data) {
 }
 }
 
 
 static void X11Toolkit_InitWindowFonts(SDL_ToolkitWindowX11 *window)
 static void X11Toolkit_InitWindowFonts(SDL_ToolkitWindowX11 *window)
-{
+{    
+    window->thai_encoding = SDL_TOOLKIT_THAI_ENCODING_X11_NONE;
+    window->thai_font = SDL_TOOLKIT_THAI_FONT_X11_CELL;
 #ifdef X_HAVE_UTF8_STRING
 #ifdef X_HAVE_UTF8_STRING
     window->utf8 = true;
     window->utf8 = true;
     window->font_set = NULL;
     window->font_set = NULL;
@@ -301,9 +337,56 @@ static void X11Toolkit_InitWindowFonts(SDL_ToolkitWindowX11 *window)
         if (!window->font_set) {
         if (!window->font_set) {
             goto load_font_traditional;
             goto load_font_traditional;
         } else {
         } else {
+            XFontStruct **font_structs;
+            char **font_names;
+            int font_sz;
+            int i;
+            
 #ifdef HAVE_FRIBIDI_H
 #ifdef HAVE_FRIBIDI_H
             window->do_shaping = !X11_XContextDependentDrawing(window->font_set);
             window->do_shaping = !X11_XContextDependentDrawing(window->font_set);
 #endif
 #endif
+            /* TODO: What to do the XFontSet happens to have more than one Thai font? */
+            font_sz = X11_XFontsOfFontSet(window->font_set, &font_structs, &font_names);
+            for (i = 0; i < font_sz; i++) {
+                SDL_ToolkitThaiEncodingX11 thai_encoding;
+                
+                thai_encoding = SDL_TOOLKIT_THAI_ENCODING_X11_NONE;
+                if (SDL_strstr(font_names[i], "tis620-0")) {
+                    thai_encoding = SDL_TOOLKIT_THAI_ENCODING_X11_TIS;
+                } else if (SDL_strstr(font_names[i], "tis620-1")) {
+                    thai_encoding = SDL_TOOLKIT_THAI_ENCODING_X11_TIS_MAC;
+                } else if (SDL_strstr(font_names[i], "tis620-2")) {
+                    thai_encoding = SDL_TOOLKIT_THAI_ENCODING_X11_TIS_WIN;
+                } else if (SDL_strstr(font_names[i], "iso8859-11")) {
+                    thai_encoding = SDL_TOOLKIT_THAI_ENCODING_X11_8859;
+                } else if (SDL_strstr(font_names[i], "iso10646-1")) {
+                    thai_encoding = SDL_TOOLKIT_THAI_ENCODING_X11_UNICODE;
+                }
+                                                
+                /* TODO: Set encoding to none if the font does not actually have any Thai codepoints */
+                if (thai_encoding != SDL_TOOLKIT_THAI_ENCODING_X11_NONE) {
+                    XFontStruct *font_struct;
+
+                    /* We have to load the font again because the font_struct supplied by FontsOfFontSet does not have the per_char member set */
+                    font_struct = X11_XLoadQueryFont(window->display, font_names[i]);
+                    if (font_struct) {
+                        if (font_struct->per_char) {
+                            int glyphs_sz;
+                            int j;
+
+                            glyphs_sz = (font_struct->max_char_or_byte2 - font_struct->min_char_or_byte2 + 1) * (font_struct->max_byte1 - font_struct->min_byte1 + 1);
+                            for (j = 0; j < glyphs_sz; j++) {
+                                if (font_struct->per_char[j].lbearing < 0) {
+                                    window->thai_font = SDL_TOOLKIT_THAI_FONT_X11_OFFSET;
+                                }
+                            }
+                        }
+                        X11_XFreeFont(window->display, font_struct);
+                    }
+                }
+                
+                window->thai_encoding = thai_encoding;
+            } 
         }
         }
     } else
     } else
 #endif
 #endif
@@ -445,16 +528,18 @@ static void X11Toolkit_SettingsNotify(const char *name, XSettingsAction action,
     }
     }
 }
 }
 
 
-static void X11Toolkit_GetTextWidthHeightForFont(XFontStruct *font, const char *str, int nbytes, int *pwidth, int *pheight, int *ascent)
+static void X11Toolkit_GetTextWidthHeightForFont(XFontStruct *font, const char *str, int nbytes, int *pwidth, int *pheight, int *ascent, int *font_height)
 {
 {
     XCharStruct text_structure;
     XCharStruct text_structure;
     int font_direction, font_ascent, font_descent;
     int font_direction, font_ascent, font_descent;
-    X11_XTextExtents(font, str, nbytes,
-                     &font_direction, &font_ascent, &font_descent,
-                     &text_structure);
+    
+    X11_XTextExtents(font, str, nbytes, &font_direction, &font_ascent, &font_descent, &text_structure);
     *pwidth = text_structure.width;
     *pwidth = text_structure.width;
     *pheight = text_structure.ascent + text_structure.descent;
     *pheight = text_structure.ascent + text_structure.descent;
     *ascent = text_structure.ascent;
     *ascent = text_structure.ascent;
+    if (font_height) {
+       *font_height = font_ascent + font_descent;
+    }
 }
 }
 
 
 static void X11Toolkit_GetTextWidthHeight(SDL_ToolkitWindowX11 *data, const char *str, int nbytes, int *pwidth, int *pheight, int *ascent, int *descent, int *font_height)
 static void X11Toolkit_GetTextWidthHeight(SDL_ToolkitWindowX11 *data, const char *str, int nbytes, int *pwidth, int *pheight, int *ascent, int *descent, int *font_height)
@@ -494,6 +579,335 @@ static void X11Toolkit_GetTextWidthHeight(SDL_ToolkitWindowX11 *data, const char
     }
     }
 }
 }
 
 
+#ifdef HAVE_FRIBIDI_H
+SDL_ListNode *X11Toolkit_MakeTextElements(SDL_ToolkitWindowX11 *data, char *txt, size_t sz, FriBidiParType *par)
+#else
+SDL_ListNode *X11Toolkit_MakeTextElements(SDL_ToolkitWindowX11 *data, char *txt, size_t sz)
+#endif
+{
+    SDL_ListNode *list;
+    char *str;
+    char *buffer;
+    Uint32 cp;
+    bool thai;
+    bool free_txt;
+    
+    free_txt = false;
+    list = NULL;
+    thai = 0;
+    str = txt;
+    buffer = SDL_malloc(1);
+    buffer[0] = 0;
+    
+#ifdef HAVE_FRIBIDI_H
+    if (par) {
+        *par = FRIBIDI_PAR_LTR;
+    }
+    if (data->fribidi) {
+        char *fstr;
+                
+        fstr = SDL_FriBidi_Process(data->fribidi, str, sz, data->do_shaping, par);
+        if (fstr) {
+            txt = fstr;
+            str = fstr;
+            sz = SDL_strlen(str);
+            free_txt = true;
+        } 
+    }
+#endif        
+
+    while (1) {
+        char *new;
+        char utf8[5];
+        size_t csz;
+        bool cond;
+
+        SDL_memset(utf8, 0, 5);
+        cp = SDL_StepUTF8((const char **)&str, &sz);
+        cond = (0xe00 <= cp && cp <= 0xe7f) ? true : false;
+        if (cp == 0 || cond == (thai ? false : true)) {
+            SDL_ToolkitTextElementX11 *element;
+            
+            element = SDL_malloc(sizeof(SDL_ToolkitTextElementX11));
+            if (thai) {
+                element->type = SDL_TOOLKIT_TEXT_TYPE_X11_THAI;
+            } else {
+                element->type = SDL_TOOLKIT_TEXT_TYPE_X11_GENERIC;
+            }
+            element->str = SDL_strdup(buffer);
+            element->sz = SDL_strlen(buffer);
+            element->str_free = SDL_free;
+            
+            SDL_ListAdd(&list, element);
+            
+            SDL_free(buffer);
+            buffer = SDL_malloc(1);
+            buffer[0] = 0;
+            thai = thai ? false : true;
+        }
+
+        if (!cp) {
+            break;
+        }
+        
+        SDL_UCS4ToUTF8(cp, utf8);
+        csz = SDL_strlen(buffer) + SDL_strlen(utf8) + 1;
+        new = SDL_malloc(csz);
+        SDL_strlcpy(new, buffer, csz);
+        SDL_strlcat(new, utf8, csz);
+        SDL_free(buffer);
+        buffer = new;
+    }
+
+    SDL_free(buffer);
+    if (free_txt) {
+        SDL_free(txt);
+    }
+    return list;
+}
+
+void X11Toolkit_ShapeTextElements(SDL_ToolkitWindowX11 *data, SDL_ListNode *list)
+{
+    SDL_ListNode *cursor;
+    SDL_ToolkitTextElementX11 *prev;
+    int temp;
+    
+    /* Shape and calculate bounding box */
+    cursor = list;
+    while (cursor) {
+        SDL_ToolkitTextElementX11 *element;
+        
+        element = cursor->entry;
+#ifdef HAVE_LIBTHAI_H
+        element->thai_overlays = NULL;
+#endif
+        if (element->type == SDL_TOOLKIT_TEXT_TYPE_X11_THAI) {
+            if (data->thai_font == SDL_TOOLKIT_THAI_FONT_X11_OFFSET) {
+                X11Toolkit_GetTextWidthHeight(data, element->str, element->sz, &element->rect.w, &element->rect.h, &element->rect.y, &temp, NULL);
+            } else {
+#ifdef HAVE_LIBTHAI_H
+                if (data->th) {
+                    struct thcell_t *cells;
+                    char *tis_str;
+                    char *base_tis_str;
+                    size_t cells_sz;
+                    size_t base_tis_str_sz;
+                    size_t tis_str_sz;
+                                                    
+                    tis_str = SDL_iconv_string("TIS-620", "UTF-8", element->str, element->sz);
+                    cells_sz = tis_str_sz = SDL_strlen(tis_str);
+                    
+                    cells = SDL_calloc(cells_sz, sizeof(struct thcell_t));
+                    data->th->make_cells((const thchar_t *)tis_str, tis_str_sz, cells, &cells_sz, 0);
+
+                    base_tis_str_sz = cells_sz;
+                    base_tis_str = SDL_malloc(base_tis_str_sz + 1);
+                    for (temp = 0; temp < cells_sz; temp++) {
+                        base_tis_str[temp] = cells[temp].base;
+                        
+                        if (cells[temp].hilo) {
+                            SDL_ToolkitThaiOverlayX11 *overlay;
+                            char *pre;
+                            int temp2;
+                            
+                            overlay = SDL_malloc(sizeof(SDL_ToolkitThaiOverlayX11));
+                            pre = SDL_iconv_string("UTF-8", "TIS-620", base_tis_str, temp);
+                            overlay->str = SDL_iconv_string("UTF-8", "TIS-620", (const char *)&cells[temp].hilo, 1);
+                            overlay->sz = SDL_strlen(overlay->str);
+                            overlay->top = false;
+                            X11Toolkit_GetTextWidthHeight(data, pre, SDL_strlen(pre), &overlay->rect.x, &temp2, &temp2, &temp2, NULL);
+                            X11Toolkit_GetTextWidthHeight(data, overlay->str, overlay->sz, &overlay->rect.w, &overlay->rect.h, &overlay->rect.y, &temp2, NULL);
+                            SDL_ListAdd(&element->thai_overlays, overlay);
+                            SDL_free(pre);
+                        }
+                        
+                        if (cells[temp].top) {
+                            SDL_ToolkitThaiOverlayX11 *overlay;
+                            char *pre;
+                            int temp2;
+                            
+                            overlay = SDL_malloc(sizeof(SDL_ToolkitThaiOverlayX11));
+                            pre = SDL_iconv_string("UTF-8", "TIS-620", base_tis_str, temp);
+                            overlay->str = SDL_iconv_string("UTF-8", "TIS-620", (const char *)&cells[temp].top, 1);
+                            overlay->sz = SDL_strlen(overlay->str);
+                            overlay->top = true;
+                            X11Toolkit_GetTextWidthHeight(data, pre, SDL_strlen(pre), &overlay->rect.x, &temp2, &temp2, &temp2, NULL);
+                            X11Toolkit_GetTextWidthHeight(data, overlay->str, overlay->sz, &overlay->rect.w, &overlay->rect.h, &overlay->rect.y, &temp2, NULL);
+                            SDL_ListAdd(&element->thai_overlays, overlay);
+                            SDL_free(pre);
+                        }
+                    }
+                    base_tis_str[base_tis_str_sz] = '\0';
+                    
+                    element->str_free(element->str);
+                    element->str = SDL_iconv_string("UTF-8", "TIS-620", base_tis_str, base_tis_str_sz);
+                    element->sz = SDL_strlen(element->str);
+                    X11Toolkit_GetTextWidthHeight(data, element->str, element->sz, &element->rect.w, &element->rect.h, &element->rect.y, &temp, &element->font_h);
+
+                    SDL_free(tis_str);
+                    SDL_free(cells);                
+                    SDL_free(base_tis_str);
+                }
+#else
+                X11Toolkit_GetTextWidthHeight(data, element->str, element->sz, &element->rect.w, &element->rect.h, &element->rect.y, &temp, &element->font_h);
+#endif            
+            }
+        } else {
+            X11Toolkit_GetTextWidthHeight(data, element->str, element->sz, &element->rect.w, &element->rect.h, &element->rect.y, &temp, &element->font_h);
+        }
+        
+        cursor = cursor->next;
+    }
+    
+    /* Add offsets */
+    prev = NULL;
+    cursor = list;
+    while (cursor) {
+        SDL_ToolkitTextElementX11 *element;
+        
+        element = cursor->entry;        
+        if (prev) {
+            element->rect.x = prev->rect.x + prev->rect.w;
+        } else {
+            element->rect.x = 0;
+        }
+        
+        prev = element;
+        cursor = cursor->next;
+    }
+}
+
+
+void X11Toolkit_DrawTextElements(SDL_ToolkitWindowX11 *data, SDL_ListNode *list, int x, int y)
+{
+    SDL_ListNode *cursor;
+    
+    cursor = list;
+    
+    while (cursor) {
+        SDL_ToolkitTextElementX11 *element;
+        
+        element = cursor->entry;
+        if (element->type == SDL_TOOLKIT_TEXT_TYPE_X11_THAI) {
+            if (data->thai_font == SDL_TOOLKIT_THAI_FONT_X11_OFFSET) {
+#ifdef X_HAVE_UTF8_STRING
+                if (data->utf8) {
+                    X11_Xutf8DrawString(data->display, data->drawable, data->font_set, data->ctx, x + element->rect.x, y + element->rect.y, element->str, element->sz);
+                } else
+#endif
+                {
+                    X11_XDrawString(data->display, data->drawable, data->ctx, x + element->rect.x, y + element->rect.y, element->str, element->sz);
+                }
+            } else {    
+#ifdef HAVE_LIBTHAI_H
+                SDL_ListNode *overlay_cursor;
+                    
+                /* Draw the base string */
+#ifdef X_HAVE_UTF8_STRING
+                if (data->utf8) {
+                    X11_Xutf8DrawString(data->display, data->drawable, data->font_set, data->ctx, x + element->rect.x, y + element->rect.y, element->str, element->sz);
+                } else
+#endif
+                {
+                    X11_XDrawString(data->display, data->drawable, data->ctx, x + element->rect.x, y + element->rect.y, element->str, element->sz);
+                }                        
+                
+                /* Draw overlays */
+                overlay_cursor = element->thai_overlays;
+                while (overlay_cursor) {
+                    SDL_ToolkitThaiOverlayX11 *overlay;
+                    
+                    overlay = overlay_cursor->entry;
+#ifdef X_HAVE_UTF8_STRING
+                    if (data->utf8) {
+                        X11_Xutf8DrawString(data->display, data->drawable, data->font_set, data->ctx, x + element->rect.x + overlay->rect.x, y + overlay->rect.y, overlay->str, overlay->sz);
+                    } else
+#endif
+                    {
+                        X11_XDrawString(data->display, data->drawable, data->ctx, x + element->rect.x + overlay->rect.x, y + element->rect.y + overlay->rect.y, overlay->str, overlay->sz);
+                    }                        
+                            
+                    overlay_cursor = overlay_cursor->next;
+                }
+#endif                
+            }
+        } else {
+#ifdef X_HAVE_UTF8_STRING
+            if (data->utf8) {
+                X11_Xutf8DrawString(data->display, data->drawable, data->font_set, data->ctx, x + element->rect.x, y + element->rect.y, element->str, element->sz);
+            } else
+#endif
+            {
+                X11_XDrawString(data->display, data->drawable, data->ctx, x + element->rect.x, y + element->rect.y, element->str, element->sz);
+            }
+        }
+        
+        cursor = cursor->next;
+    }
+}
+
+int X11Toolkit_GetTextElementsRect(SDL_ListNode *list, SDL_Rect *out)
+{
+    SDL_ListNode *cursor;
+    int ret;
+    
+    ret = 0;
+    out->x = out->y = 0;
+    out->w = out->h = 0;
+    cursor = list;
+    while (cursor) {
+        SDL_ToolkitTextElementX11 *element;
+        
+        element = cursor->entry;
+        
+        out->w += element->rect.w;
+        out->h = SDL_max(out->h, element->rect.h);
+        ret = SDL_max(ret, element->font_h);
+        
+        cursor = cursor->next;
+    }
+    
+    return ret;
+}
+
+void X11Toolkit_FreeTextElementsListContents(SDL_ListNode *list)
+{
+    SDL_ListNode *cursor;
+    
+    cursor = list;
+    while (cursor) {
+        SDL_ToolkitTextElementX11 *element;
+#ifdef HAVE_LIBTHAI_H
+        SDL_ListNode *overlay_cursor;
+#endif
+
+        element = cursor->entry;
+        
+        if (element->str_free) {
+            element->str_free(element->str);
+        }
+        
+#ifdef HAVE_LIBTHAI_H        
+        overlay_cursor = element->thai_overlays;
+        while (overlay_cursor) {
+            SDL_ToolkitThaiOverlayX11 *overlay;
+                    
+            overlay = overlay_cursor->entry;
+            SDL_free(overlay->str);
+            SDL_free(overlay);
+            overlay_cursor = overlay_cursor->next;
+        }
+        SDL_ListClear(&element->thai_overlays);
+#endif
+        
+        SDL_free(element);
+        
+        cursor = cursor->next;
+    }
+}
+
+#define X11Toolkit_FreeTextElements(x) X11Toolkit_FreeTextElementsListContents(x); SDL_ListClear(&x)
+ 
 static bool X11Toolkit_ShouldFlipUI(void) 
 static bool X11Toolkit_ShouldFlipUI(void) 
 {
 {
     SDL_Locale **current_locales;
     SDL_Locale **current_locales;
@@ -744,6 +1158,10 @@ SDL_ToolkitWindowX11 *X11Toolkit_CreateWindowStruct(SDL_Window *parent, SDL_Tool
     window->fribidi = SDL_FriBidi_Create();
     window->fribidi = SDL_FriBidi_Create();
 #endif
 #endif
 
 
+#ifdef HAVE_LIBTHAI_H
+    window->th = SDL_LibThai_Create();
+#endif
+    
     /* Interface direction */
     /* Interface direction */
     window->flip_interface = X11Toolkit_ShouldFlipUI();
     window->flip_interface = X11Toolkit_ShouldFlipUI();
     
     
@@ -1466,7 +1884,7 @@ static void X11Toolkit_CalculateIconControl(SDL_ToolkitControlX11 *base_control)
     int icon_wh;
     int icon_wh;
 
 
     control = (SDL_ToolkitIconControlX11 *)base_control;
     control = (SDL_ToolkitIconControlX11 *)base_control;
-    X11Toolkit_GetTextWidthHeightForFont(control->icon_char_font, &control->icon_char, 1, &icon_char_w, &control->icon_char_h, &control->icon_char_a);
+    X11Toolkit_GetTextWidthHeightForFont(control->icon_char_font, &control->icon_char, 1, &icon_char_w, &control->icon_char_h, &control->icon_char_a, NULL);
     base_control->rect.w = icon_char_w;
     base_control->rect.w = icon_char_w;
     base_control->rect.h = control->icon_char_h;
     base_control->rect.h = control->icon_char_h;
     icon_wh = SDL_max(icon_char_w, control->icon_char_h) + SDL_TOOLKIT_X11_ELEMENT_PADDING * 2 * base_control->window->iscale;
     icon_wh = SDL_max(icon_char_w, control->icon_char_h) + SDL_TOOLKIT_X11_ELEMENT_PADDING * 2 * base_control->window->iscale;
@@ -1632,31 +2050,23 @@ bool X11Toolkit_NotifyControlOfSizeChange(SDL_ToolkitControlX11 *control) {
 
 
 static void X11Toolkit_CalculateButtonControl(SDL_ToolkitControlX11 *control) {
 static void X11Toolkit_CalculateButtonControl(SDL_ToolkitControlX11 *control) {
     SDL_ToolkitButtonControlX11 *button_control;
     SDL_ToolkitButtonControlX11 *button_control;
-    int text_d;
 
 
     button_control = (SDL_ToolkitButtonControlX11 *)control;
     button_control = (SDL_ToolkitButtonControlX11 *)control;
-    X11Toolkit_GetTextWidthHeight(control->window, button_control->data->text, button_control->str_sz, &button_control->text_rect.w, &button_control->text_rect.h, &button_control->text_a, &text_d, NULL);
+    X11Toolkit_GetTextElementsRect(button_control->text, &button_control->text_rect);
     if (control->do_size) {
     if (control->do_size) {
         control->rect.w = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.w;
         control->rect.w = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.w;
         control->rect.h = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.h;
         control->rect.h = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.h;
     }
     }
     button_control->text_rect.x = (control->rect.w - button_control->text_rect.w)/2;
     button_control->text_rect.x = (control->rect.w - button_control->text_rect.w)/2;
-    button_control->text_rect.y = button_control->text_a + (control->rect.h - button_control->text_rect.h)/2;
+    button_control->text_rect.y = (control->rect.h - button_control->text_rect.h)/2;
 }
 }
 
 
 
 
 static void X11Toolkit_DrawButtonControl(SDL_ToolkitControlX11 *control) {
 static void X11Toolkit_DrawButtonControl(SDL_ToolkitControlX11 *control) {
     SDL_ToolkitButtonControlX11 *button_control;
     SDL_ToolkitButtonControlX11 *button_control;
-    char *text;
 
 
     button_control = (SDL_ToolkitButtonControlX11 *)control;
     button_control = (SDL_ToolkitButtonControlX11 *)control;
 
 
-#ifdef HAVE_FRIBIDI_H
-    text = button_control->text;
-#else
-    text = (char *)button_control->data->text;
-#endif
-
     X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
     X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
     /* Draw bevel */
     /* Draw bevel */
     if (control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED || control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED_HELD) {
     if (control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED || control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED_HELD) {
@@ -1738,20 +2148,8 @@ static void X11Toolkit_DrawButtonControl(SDL_ToolkitControlX11 *control) {
             }
             }
         }
         }
 
 
-        X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
-#ifdef X_HAVE_UTF8_STRING
-        if (control->window->utf8) {
-            X11_Xutf8DrawString(control->window->display, control->window->drawable, control->window->font_set, control->window->ctx,
-                                control->rect.x + button_control->text_rect.x,
-                                control->rect.y + button_control->text_rect.y,
-                                text, button_control->str_sz);
-        } else
-#endif
-        {
-            X11_XDrawString(control->window->display, control->window->drawable, control->window->ctx,
-                            control->rect.x + button_control->text_rect.x, control->rect.y + button_control->text_rect.y,
-                            text, button_control->str_sz);
-        }
+    X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
+    X11Toolkit_DrawTextElements(control->window, button_control->text, control->rect.x + button_control->text_rect.x, control->rect.y + button_control->text_rect.y);
 }
 }
 
 
 static void X11Toolkit_OnButtonControlStateChange(SDL_ToolkitControlX11 *control) {
 static void X11Toolkit_OnButtonControlStateChange(SDL_ToolkitControlX11 *control) {
@@ -1764,21 +2162,18 @@ static void X11Toolkit_OnButtonControlStateChange(SDL_ToolkitControlX11 *control
 }
 }
 
 
 static void X11Toolkit_DestroyButtonControl(SDL_ToolkitControlX11 *control) {
 static void X11Toolkit_DestroyButtonControl(SDL_ToolkitControlX11 *control) {
-#ifdef HAVE_FRIBIDI_H
     SDL_ToolkitButtonControlX11 *button_control;
     SDL_ToolkitButtonControlX11 *button_control;
 
 
     button_control = (SDL_ToolkitButtonControlX11 *)control;
     button_control = (SDL_ToolkitButtonControlX11 *)control;
-    if (button_control->free_text) {
-        SDL_free(button_control->text);
-    }
-#endif
+
+    X11Toolkit_FreeTextElements(button_control->text);
+    
     SDL_free(control);
     SDL_free(control);
 }
 }
 
 
 SDL_ToolkitControlX11 *X11Toolkit_CreateButtonControl(SDL_ToolkitWindowX11 *window, const SDL_MessageBoxButtonData *data) {
 SDL_ToolkitControlX11 *X11Toolkit_CreateButtonControl(SDL_ToolkitWindowX11 *window, const SDL_MessageBoxButtonData *data) {
     SDL_ToolkitButtonControlX11 *control;
     SDL_ToolkitButtonControlX11 *control;
     SDL_ToolkitControlX11 *base_control;
     SDL_ToolkitControlX11 *base_control;
-    int text_d;
 
 
     control = (SDL_ToolkitButtonControlX11 *)SDL_malloc(sizeof(SDL_ToolkitButtonControlX11));
     control = (SDL_ToolkitButtonControlX11 *)SDL_malloc(sizeof(SDL_ToolkitButtonControlX11));
     base_control = (SDL_ToolkitControlX11 *)control;
     base_control = (SDL_ToolkitControlX11 *)control;
@@ -1805,30 +2200,19 @@ SDL_ToolkitControlX11 *X11Toolkit_CreateButtonControl(SDL_ToolkitWindowX11 *wind
         base_control->is_default_enter = true;
         base_control->is_default_enter = true;
         base_control->selected = true;
         base_control->selected = true;
     }
     }
-    base_control->do_size = false;
+    control->cb = NULL;
     control->data = data;
     control->data = data;
-    control->str_sz = SDL_strlen(control->data->text);
 #ifdef HAVE_FRIBIDI_H
 #ifdef HAVE_FRIBIDI_H
-    if (base_control->window->fribidi) {
-        control->text = SDL_FriBidi_Process(base_control->window->fribidi, (char *)control->data->text, control->str_sz, base_control->window->do_shaping, NULL);
-        if (control->text) {
-            control->free_text = true;
-            control->str_sz = SDL_strlen(control->text);
-        } else {
-            control->text = (char *)control->data->text;
-            control->free_text = false;
-        }
-    } else {
-        control->text = (char *)control->data->text;
-        control->free_text = false;
-    }
+    control->text = X11Toolkit_MakeTextElements(base_control->window, (char *)control->data->text, SDL_strlen(control->data->text), NULL);
+#else 
+    control->text = X11Toolkit_MakeTextElements(base_control->window, (char *)control->data->text, SDL_strlen(control->data->text));
 #endif
 #endif
-    control->cb = NULL;
-    X11Toolkit_GetTextWidthHeight(base_control->window, control->data->text, control->str_sz, &control->text_rect.w, &control->text_rect.h, &control->text_a, &text_d, NULL);
-    base_control->rect.w = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * window->iscale + control->text_rect.w;
-    base_control->rect.h = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * window->iscale + control->text_rect.h;
-    control->text_rect.x = control->text_rect.y = 0;
+    X11Toolkit_ShapeTextElements(base_control->window, control->text);
+    
+    base_control->do_size = true;
     X11Toolkit_CalculateButtonControl(base_control);
     X11Toolkit_CalculateButtonControl(base_control);
+    base_control->do_size = false;
+
     X11Toolkit_AddControlToWindow(window, base_control);
     X11Toolkit_AddControlToWindow(window, base_control);
     return base_control;
     return base_control;
 }
 }
@@ -1936,6 +2320,10 @@ void X11Toolkit_DestroyWindow(SDL_ToolkitWindowX11 *data) {
     SDL_FriBidi_Destroy(data->fribidi);
     SDL_FriBidi_Destroy(data->fribidi);
 #endif
 #endif
 
 
+#ifdef HAVE_LIBTHAI_H
+    SDL_LibThai_Destroy(data->th);
+#endif
+
     SDL_free(data);
     SDL_free(data);
 }
 }
 
 
@@ -1953,143 +2341,112 @@ static int X11Toolkit_CountLinesOfText(const char *text)
 static void X11Toolkit_DrawLabelControl(SDL_ToolkitControlX11 *control) {
 static void X11Toolkit_DrawLabelControl(SDL_ToolkitControlX11 *control) {
     SDL_ToolkitLabelControlX11 *label_control;
     SDL_ToolkitLabelControlX11 *label_control;
     int i;
     int i;
-    int x;
 
 
     label_control = (SDL_ToolkitLabelControlX11 *)control;
     label_control = (SDL_ToolkitLabelControlX11 *)control;
     X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
     X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
     for (i = 0; i < label_control->sz; i++) {
     for (i = 0; i < label_control->sz; i++) {
-        x = control->rect.x;
-#ifdef HAVE_FRIBIDI_H
-        if (control->window->fribidi) {
-            x += label_control->x[i];
-        }
-#endif
-#ifdef X_HAVE_UTF8_STRING
-        if (control->window->utf8) {
-            X11_Xutf8DrawString(control->window->display, control->window->drawable, control->window->font_set, control->window->ctx,
-                                x, control->rect.y + label_control->y[i],
-                                label_control->lines[i], label_control->szs[i]);
-        } else
-#endif
-        {
-            X11_XDrawString(control->window->display, control->window->drawable, control->window->ctx,
-                                x, control->rect.y + label_control->y[i],
-                                label_control->lines[i], label_control->szs[i]);
-        }
+        X11Toolkit_DrawTextElements(control->window, label_control->lines[i].text, control->rect.x + label_control->lines[i].rect.x, control->rect.y + label_control->lines[i].rect.y);
     }
     }
 }
 }
 
 
 static void X11Toolkit_DestroyLabelControl(SDL_ToolkitControlX11 *control) {
 static void X11Toolkit_DestroyLabelControl(SDL_ToolkitControlX11 *control) {
     SDL_ToolkitLabelControlX11 *label_control;
     SDL_ToolkitLabelControlX11 *label_control;
+    int i;
 
 
     label_control = (SDL_ToolkitLabelControlX11 *)control;
     label_control = (SDL_ToolkitLabelControlX11 *)control;
-#ifdef HAVE_FRIBIDI_H
-    if (control->window->fribidi) {
-        int i;
-
-        for (i = 0; i < label_control->sz; i++) {
-            if (label_control->free_lines[i]) {
-                SDL_free(label_control->lines[i]);
-            }
-        }
-        SDL_free(label_control->x);
-        SDL_free(label_control->free_lines);
-        SDL_free(label_control->w);
-        SDL_free(label_control->par_types);
+    for (i = 0; i < label_control->sz; i++) {
+        X11Toolkit_FreeTextElements(label_control->lines[i].text);
     }
     }
-#endif
     SDL_free(label_control->lines);
     SDL_free(label_control->lines);
-    SDL_free(label_control->szs);
-    SDL_free(label_control->y);
     SDL_free(label_control);
     SDL_free(label_control);
 }
 }
 
 
 static void X11Toolkit_CalculateLabelControl(SDL_ToolkitControlX11 *base_control) {
 static void X11Toolkit_CalculateLabelControl(SDL_ToolkitControlX11 *base_control) {
     SDL_ToolkitLabelControlX11 *control;
     SDL_ToolkitLabelControlX11 *control;
-    int last_h;
-    int ascent;
-    int descent;
-    int font_h;
-    int w;
-    int h;
     int i;
     int i;
-#ifdef HAVE_FRIBIDI_H
-    FriBidiParType first_ndn_dir;
-    int last_ndn;
-#endif
 
 
-    last_h = 0;
     control = (SDL_ToolkitLabelControlX11 *)base_control;
     control = (SDL_ToolkitLabelControlX11 *)base_control;
+    
+    if (base_control->do_size) {
+        base_control->rect.w = 0;
+        base_control->rect.h = 0;
+    }
+    
     for (i = 0; i < control->sz; i++) {
     for (i = 0; i < control->sz; i++) {
-        X11Toolkit_GetTextWidthHeight(base_control->window, control->lines[i], control->szs[i], &w, &h, &ascent, &descent, &font_h);
-        base_control->rect.w = SDL_max(base_control->rect.w, w);
-
+        int font_h;
+        
+        font_h = X11Toolkit_GetTextElementsRect(control->lines[i].text, &control->lines[i].rect);
+        
+        if (base_control->do_size) {
+            base_control->rect.w = SDL_max(base_control->rect.w, control->lines[i].rect.w);
+        }
+        
         if (i > 0) {
         if (i > 0) {
-            control->y[i] = font_h + control->y[i-1];
+            control->lines[i].rect.y = font_h + control->lines[i - 1].rect.y;
         } else {
         } else {
-            control->y[i] = ascent;
+            control->lines[i].rect.y = 0;
         }
         }
-
-        last_h = h;
     }
     }
-    base_control->rect.h = control->y[control->sz -1] + last_h;
 
 
 #ifdef HAVE_FRIBIDI_H
 #ifdef HAVE_FRIBIDI_H
     if (base_control->window->fribidi) {
     if (base_control->window->fribidi) {
+        FriBidiParType first_ndn_dir;
+        int last_ndn;
+    
         first_ndn_dir = FRIBIDI_PAR_LTR;
         first_ndn_dir = FRIBIDI_PAR_LTR;
         for (i = 0; i < control->sz; i++) {
         for (i = 0; i < control->sz; i++) {
-            if (control->par_types[i] != FRIBIDI_PAR_ON) {
-                first_ndn_dir = control->par_types[i];
+            if (control->lines[i].par != FRIBIDI_PAR_ON) {
+                first_ndn_dir = control->lines[i].par;
             }
             }
         }
         }
 
 
         last_ndn = -1;
         last_ndn = -1;
         for (i = 0; i < control->sz; i++) {
         for (i = 0; i < control->sz; i++) {
-            switch (control->par_types[i]) {
+            switch (control->lines[i].par) {
                 case FRIBIDI_PAR_LTR:
                 case FRIBIDI_PAR_LTR:
-                    control->x[i] = 0;
+                    control->lines[i].rect.x = 0;
                     last_ndn = i;
                     last_ndn = i;
                     break;
                     break;
                 case FRIBIDI_PAR_RTL:
                 case FRIBIDI_PAR_RTL:
-                    control->x[i] = base_control->rect.w - control->w[i];
+                    control->lines[i].rect.x = base_control->rect.w - control->lines[i].rect.w;
                     last_ndn = i;
                     last_ndn = i;
                     break;
                     break;
                 default:
                 default:
                     if (last_ndn != -1) {
                     if (last_ndn != -1) {
-                        if (control->par_types[last_ndn] == FRIBIDI_PAR_RTL) {
-                            control->x[i] = base_control->rect.w - control->w[i];
+                        if (control->lines[last_ndn].par == FRIBIDI_PAR_RTL) {
+                            control->lines[i].rect.x = base_control->rect.w - control->lines[i].rect.w;
                         } else {
                         } else {
-                            control->x[i] = 0;
+                            control->lines[i].rect.x = 0;
                         }
                         }
                     } else {
                     } else {
                         if (first_ndn_dir == FRIBIDI_PAR_RTL) {
                         if (first_ndn_dir == FRIBIDI_PAR_RTL) {
-                            control->x[i] = base_control->rect.w - control->w[i];
+                            control->lines[i].rect.x = base_control->rect.w - control->lines[i].rect.w;
                         } else {
                         } else {
-                            control->x[i] = 0;
+                            control->lines[i].rect.x = 0;
                         }
                         }
                     }
                     }
             }
             }
         }
         }
     }
     }
 #endif
 #endif
+    
+    if (base_control->do_size && control->sz) {
+        base_control->rect.h = control->lines[control->sz - 1].rect.y + control->lines[control->sz - 1].rect.h;
+    }
 }
 }
 
 
 SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *window, char *utf8) {
 SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *window, char *utf8) {
     SDL_ToolkitLabelControlX11 *control;
     SDL_ToolkitLabelControlX11 *control;
     SDL_ToolkitControlX11 *base_control;
     SDL_ToolkitControlX11 *base_control;
-#ifdef HAVE_FRIBIDI_H
-    FriBidiParType first_ndn_dir;
-    int last_ndn;
-#endif
-    int font_h;
-    int last_h;
-    int ascent;
-    int descent;
     int i;
     int i;
-
+    
     if (!utf8) {
     if (!utf8) {
         return NULL;
         return NULL;
     }
     }
+ 
+    if (!SDL_strcmp(utf8, "")) {
+        return NULL;
+    }   
     control = (SDL_ToolkitLabelControlX11 *)SDL_malloc(sizeof(SDL_ToolkitLabelControlX11));
     control = (SDL_ToolkitLabelControlX11 *)SDL_malloc(sizeof(SDL_ToolkitLabelControlX11));
     base_control = (SDL_ToolkitControlX11 *)control;
     base_control = (SDL_ToolkitControlX11 *)control;
     if (!control) {
     if (!control) {
@@ -2109,113 +2466,46 @@ SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *windo
     base_control->rect.h = 0;
     base_control->rect.h = 0;
     base_control->is_default_enter = false;
     base_control->is_default_enter = false;
     base_control->is_default_esc = false;
     base_control->is_default_esc = false;
+    
     control->sz = X11Toolkit_CountLinesOfText(utf8);
     control->sz = X11Toolkit_CountLinesOfText(utf8);
-    control->lines = (char **)SDL_malloc(sizeof(char *) * control->sz);
-    control->y = (int *)SDL_calloc(control->sz, sizeof(int));
-    control->szs = (size_t *)SDL_calloc(control->sz, sizeof(size_t));
-#ifdef HAVE_FRIBIDI_H
-    if (base_control->window->fribidi) {
-        control->x = (int *)SDL_calloc(control->sz, sizeof(int));
-        control->free_lines = (bool *)SDL_calloc(control->sz, sizeof(bool));
-        control->par_types = (FriBidiParType *)SDL_calloc(control->sz, sizeof(FriBidiParType));
-        control->w = (int *)SDL_calloc(control->sz, sizeof(int));
-    }
-#endif
-    last_h = 0;
+    control->lines = SDL_calloc(control->sz, sizeof(SDL_ToolkitLabelControlLineX11));
     for (i = 0; i < control->sz; i++) {
     for (i = 0; i < control->sz; i++) {
         const char *lf = SDL_strchr(utf8, '\n');
         const char *lf = SDL_strchr(utf8, '\n');
         const int length = lf ? (lf - utf8) : SDL_strlen(utf8);
         const int length = lf ? (lf - utf8) : SDL_strlen(utf8);
-        int w;
-        int h;
-
-#ifdef HAVE_FRIBIDI_H
-        if (base_control->window->fribidi) {
-            control->lines[i] = SDL_FriBidi_Process(base_control->window->fribidi, utf8, length, base_control->window->do_shaping, &control->par_types[i]);
-            control->szs[i] = SDL_strlen(control->lines[i]);
-            control->free_lines[i] = true;
-        } else
-#endif
-        {
-            control->lines[i] = utf8;
-            control->szs[i] = length;
-#ifdef HAVE_FRIBIDI_H
-            control->free_lines[i] = false;
-#endif
+        int sz;
+        
+        sz = length;
+        if (lf && (lf > utf8) && (lf[-1] == '\r')) {
+            sz--;
         }
         }
-        X11Toolkit_GetTextWidthHeight(window, control->lines[i], control->szs[i], &w, &h, &ascent, &descent, &font_h);
+
 #ifdef HAVE_FRIBIDI_H
 #ifdef HAVE_FRIBIDI_H
-        if (base_control->window->fribidi) {
-            control->w[i] = w;
-        }
+        control->lines[i].text = X11Toolkit_MakeTextElements(base_control->window, (char *)utf8, sz, &control->lines[i].par);
+#else 
+        control->lines[i].text = X11Toolkit_MakeTextElements(base_control->window, (char *)utf8, sz);
 #endif
 #endif
-        base_control->rect.w = SDL_max(base_control->rect.w, w);
-
-        if (lf && (lf > control->lines[i]) && (lf[-1] == '\r')) {
-            control->szs[i]--;
-        }
+        X11Toolkit_ShapeTextElements(base_control->window, control->lines[i].text);
 
 
-        if (i > 0) {
-            control->y[i] = font_h + control->y[i-1];
-        } else {
-            control->y[i] = ascent;
-        }
-        last_h = h;
         utf8 += length + 1;
         utf8 += length + 1;
-
         if (!lf) {
         if (!lf) {
             break;
             break;
         }
         }
     }
     }
-    base_control->rect.h = control->y[control->sz -1] + last_h;
-#ifdef HAVE_FRIBIDI_H
-    if (base_control->window->fribidi) {
-        first_ndn_dir = FRIBIDI_PAR_LTR;
-        for (i = 0; i < control->sz; i++) {
-            if (control->par_types[i] != FRIBIDI_PAR_ON) {
-                first_ndn_dir = control->par_types[i];
-            }
-        }
-
-        last_ndn = -1;
-        for (i = 0; i < control->sz; i++) {
-            switch (control->par_types[i]) {
-                case FRIBIDI_PAR_LTR:
-                    control->x[i] = 0;
-                    last_ndn = i;
-                    break;
-                case FRIBIDI_PAR_RTL:
-                    control->x[i] = base_control->rect.w - control->w[i];
-                    last_ndn = i;
-                    break;
-                default:
-                    if (last_ndn != -1) {
-                        if (control->par_types[last_ndn] == FRIBIDI_PAR_RTL) {
-                            control->x[i] = base_control->rect.w - control->w[i];
-                        } else {
-                            control->x[i] = 0;
-                        }
-                    } else {
-                        if (first_ndn_dir == FRIBIDI_PAR_RTL) {
-                            control->x[i] = base_control->rect.w - control->w[i];
-                        } else {
-                            control->x[i] = 0;
-                        }
-                    }
-            }
-        }
-    }
-#endif
 
 
+    base_control->do_size = true;
+    X11Toolkit_CalculateLabelControl(base_control);
+    base_control->do_size = false;
     X11Toolkit_AddControlToWindow(window, base_control);
     X11Toolkit_AddControlToWindow(window, base_control);
 
 
     return base_control;
     return base_control;
 }
 }
 
 
-int X11Toolkit_GetIconControlCharY(SDL_ToolkitControlX11 *control) {
-    SDL_ToolkitIconControlX11 *icon_control;
+int X11Toolkit_GetLabelControlFirstLineHeight(SDL_ToolkitControlX11 *control) {
+    SDL_ToolkitLabelControlX11 *label_control;
 
 
-    icon_control = (SDL_ToolkitIconControlX11 *)control;
-    return icon_control->icon_char_y - icon_control->icon_char_a + icon_control->icon_char_h/4;
+    label_control = (SDL_ToolkitLabelControlX11 *)control;
+
+    return label_control->lines[0].rect.h;
 }
 }
 
 
 void X11Toolkit_SignalWindowClose(SDL_ToolkitWindowX11 *data) {
 void X11Toolkit_SignalWindowClose(SDL_ToolkitWindowX11 *data) {

+ 27 - 2
src/video/x11/SDL_x11toolkit.h

@@ -32,6 +32,9 @@
 #ifdef HAVE_FRIBIDI_H
 #ifdef HAVE_FRIBIDI_H
 #include "../../core/unix/SDL_fribidi.h"
 #include "../../core/unix/SDL_fribidi.h"
 #endif
 #endif
+#ifdef HAVE_LIBTHAI_H
+#include "../../core/unix/SDL_libthai.h"
+#endif
 
 
 #ifdef SDL_VIDEO_DRIVER_X11
 #ifdef SDL_VIDEO_DRIVER_X11
 
 
@@ -50,6 +53,22 @@ typedef enum SDL_ToolkitChildModeX11
     SDL_TOOLKIT_WINDOW_MODE_X11_TOOLTIP
     SDL_TOOLKIT_WINDOW_MODE_X11_TOOLTIP
 } SDL_ToolkitWindowModeX11;
 } SDL_ToolkitWindowModeX11;
 
 
+typedef enum SDL_ToolkitThaiEncodingX11
+{
+    SDL_TOOLKIT_THAI_ENCODING_X11_NONE,
+    SDL_TOOLKIT_THAI_ENCODING_X11_TIS, /* -0 */
+    SDL_TOOLKIT_THAI_ENCODING_X11_TIS_WIN, /* -2 */
+    SDL_TOOLKIT_THAI_ENCODING_X11_TIS_MAC, /* -1 */
+    SDL_TOOLKIT_THAI_ENCODING_X11_8859,
+    SDL_TOOLKIT_THAI_ENCODING_X11_UNICODE
+} SDL_ToolkitThaiEncodingX11;
+
+typedef enum SDL_ToolkitThaiFontX11
+{
+    SDL_TOOLKIT_THAI_FONT_X11_OFFSET,
+    SDL_TOOLKIT_THAI_FONT_X11_CELL
+} SDL_ToolkitThaiFontX11;
+
 typedef struct SDL_ToolkitWindowX11
 typedef struct SDL_ToolkitWindowX11
 {
 {
     /* Locale */
     /* Locale */
@@ -119,7 +138,9 @@ typedef struct SDL_ToolkitWindowX11
     /* Font */
     /* Font */
     XFontSet font_set;        // for UTF-8 systems
     XFontSet font_set;        // for UTF-8 systems
     XFontStruct *font_struct; // Latin1 (ASCII) fallback.
     XFontStruct *font_struct; // Latin1 (ASCII) fallback.
-
+    SDL_ToolkitThaiEncodingX11 thai_encoding;
+    SDL_ToolkitThaiFontX11 thai_font;
+    
     /* Control colors */
     /* Control colors */
     const SDL_MessageBoxColor *color_hints;
     const SDL_MessageBoxColor *color_hints;
     XColor xcolor[SDL_MESSAGEBOX_COLOR_COUNT];
     XColor xcolor[SDL_MESSAGEBOX_COLOR_COUNT];
@@ -164,6 +185,10 @@ typedef struct SDL_ToolkitWindowX11
     bool do_shaping;
     bool do_shaping;
 #endif
 #endif
 
 
+#ifdef HAVE_LIBTHAI_H
+    SDL_LibThai *th;
+#endif
+
     bool flip_interface;
     bool flip_interface;
 } SDL_ToolkitWindowX11;
 } SDL_ToolkitWindowX11;
 
 
@@ -231,10 +256,10 @@ extern bool X11Toolkit_NotifyControlOfSizeChange(SDL_ToolkitControlX11 *control)
 
 
 /* ICON CONTROL FUNCTIONS */
 /* ICON CONTROL FUNCTIONS */
 extern SDL_ToolkitControlX11 *X11Toolkit_CreateIconControl(SDL_ToolkitWindowX11 *window, SDL_MessageBoxFlags flags);
 extern SDL_ToolkitControlX11 *X11Toolkit_CreateIconControl(SDL_ToolkitWindowX11 *window, SDL_MessageBoxFlags flags);
-extern int X11Toolkit_GetIconControlCharY(SDL_ToolkitControlX11 *control);
 
 
 /* LABEL CONTROL FUNCTIONS */
 /* LABEL CONTROL FUNCTIONS */
 extern SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *window, char *utf8);
 extern SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *window, char *utf8);
+extern int X11Toolkit_GetLabelControlFirstLineHeight(SDL_ToolkitControlX11 *control);
 
 
 /* BUTTON CONTROL FUNCTIONS */
 /* BUTTON CONTROL FUNCTIONS */
 extern SDL_ToolkitControlX11 *X11Toolkit_CreateButtonControl(SDL_ToolkitWindowX11 *window, const SDL_MessageBoxButtonData *data);
 extern SDL_ToolkitControlX11 *X11Toolkit_CreateButtonControl(SDL_ToolkitWindowX11 *window, const SDL_MessageBoxButtonData *data);

+ 5 - 0
test/testmessage.c

@@ -164,6 +164,11 @@ int main(int argc, char *argv[])
         quit(1);
         quit(1);
     }
     }
 
 
+    success = SDL_ShowSimpleMessageBox(0,
+                                       "No icon",
+                                       "This is a MessageBox with no icon!",
+                                       NULL);
+
     /* Google says this is Traditional Chinese for "beef with broccoli" */
     /* Google says this is Traditional Chinese for "beef with broccoli" */
     success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
     success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
                                        "UTF-8 Simple MessageBox",
                                        "UTF-8 Simple MessageBox",