Alexandre Julliard : user32: Add a thunking mechanism for 16-bit edit word break procedures.

Alexandre Julliard julliard at winehq.org
Mon Dec 14 09:51:09 CST 2009


Module: wine
Branch: master
Commit: dcec342b50524562844f64d43d423ed2c83c1f97
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dcec342b50524562844f64d43d423ed2c83c1f97

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Dec 11 14:52:28 2009 +0100

user32: Add a thunking mechanism for 16-bit edit word break procedures.

---

 dlls/user32/edit.c |  122 +++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 88 insertions(+), 34 deletions(-)

diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c
index b512aa4..c5a78c7 100644
--- a/dlls/user32/edit.c
+++ b/dlls/user32/edit.c
@@ -131,7 +131,6 @@ typedef struct
 					   and just line width for single line controls	*/
 	INT region_posx;		/* Position of cursor relative to region: */
 	INT region_posy;		/* -1: to left, 0: within, 1: to right */
-	EDITWORDBREAKPROC16 word_break_proc16;
 	void *word_break_proc;		/* 32-bit word break proc: ANSI or Unicode */
 	INT line_count;			/* number of lines */
 	INT y_offset;			/* scroll offset in number of lines */
@@ -252,6 +251,90 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
 }
 
 
+/**********************************************************************
+ * Support for word break proc thunks
+ */
+
+#define MAX_THUNKS 32
+
+#include <pshpack1.h>
+static struct word_break_thunk
+{
+    BYTE                popl_eax;       /* popl  %eax (return address) */
+    BYTE                pushl_proc16;   /* pushl proc16 */
+    EDITWORDBREAKPROC16 proc16;
+    BYTE                pushl_eax;      /* pushl %eax */
+    BYTE                jmp;            /* ljmp call_word_break_proc16 */
+    DWORD               callback;
+} *word_break_thunks;
+#include <poppack.h>
+
+/**********************************************************************
+ *           call_word_break_proc16
+ */
+static INT16 CALLBACK call_word_break_proc16( SEGPTR proc16, LPSTR text, INT index, INT count, INT action )
+{
+    SEGPTR segptr;
+    WORD args[5];
+    DWORD result;
+
+    segptr = MapLS( text );
+    args[4] = SELECTOROF(segptr);
+    args[3] = OFFSETOF(segptr);
+    args[2] = index;
+    args[1] = count;
+    args[0] = action;
+    WOWCallback16Ex( proc16, WCB16_PASCAL, sizeof(args), args, &result );
+    UnMapLS( segptr );
+    return LOWORD(result);
+}
+
+/******************************************************************
+ *		add_word_break_thunk
+ */
+static struct word_break_thunk *add_word_break_thunk( EDITWORDBREAKPROC16 proc16 )
+{
+    struct word_break_thunk *thunk;
+
+    if (!word_break_thunks)
+    {
+        word_break_thunks = VirtualAlloc( NULL, MAX_THUNKS * sizeof(*thunk),
+                                          MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+        if (!word_break_thunks) return NULL;
+
+        for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
+        {
+            thunk->popl_eax     = 0x58;   /* popl  %eax */
+            thunk->pushl_proc16 = 0x68;   /* pushl proc16 */
+            thunk->pushl_eax    = 0x50;   /* pushl %eax */
+            thunk->jmp          = 0xe9;   /* jmp call_word_break_proc16 */
+            thunk->callback     = (char *)call_word_break_proc16 - (char *)(&thunk->callback + 1);
+        }
+    }
+    for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
+        if (thunk->proc16 == proc16) return thunk;
+
+    for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
+    {
+        if (thunk->proc16) continue;
+        thunk->proc16 = proc16;
+        return thunk;
+    }
+    FIXME("Out of word break thunks\n");
+    return NULL;
+}
+
+/******************************************************************
+ *		get_word_break_thunk
+ */
+static EDITWORDBREAKPROC16 get_word_break_thunk( EDITWORDBREAKPROCA proc )
+{
+    struct word_break_thunk *thunk = (struct word_break_thunk *)proc;
+    if (word_break_thunks && thunk >= word_break_thunks && thunk < &word_break_thunks[MAX_THUNKS])
+        return thunk->proc16;
+    return NULL;
+}
+
 /*********************************************************************
  *
  *	EDIT_WordBreakProc
@@ -336,28 +419,7 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count
 {
 	INT ret;
 
-	if (es->word_break_proc16) {
-	    HGLOBAL16 hglob16;
-	    SEGPTR segptr;
-	    INT countA;
-            WORD args[5];
-            DWORD result;
-
-	    countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
-	    hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA);
-	    segptr = WOWGlobalLock16(hglob16);
-	    WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL);
-            args[4] = SELECTOROF(segptr);
-            args[3] = OFFSETOF(segptr);
-            args[2] = index;
-            args[1] = countA;
-            args[0] = action;
-            WOWCallback16Ex((DWORD)es->word_break_proc16, WCB16_PASCAL, sizeof(args), args, &result);
-            ret = LOWORD(result);
-	    GlobalUnlock16(hglob16);
-	    GlobalFree16(hglob16);
-	}
-	else if (es->word_break_proc)
+        if (es->word_break_proc)
         {
 	    if(es->is_unicode)
 	    {
@@ -3091,7 +3153,6 @@ static void EDIT_EM_SetWordBreakProc(EDITSTATE *es, void *wbp)
 		return;
 
 	es->word_break_proc = wbp;
-	es->word_break_proc16 = NULL;
 
 	if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
 		EDIT_BuildLineDefs_ML(es, 0, get_text_length(es), 0, NULL);
@@ -3107,15 +3168,8 @@ static void EDIT_EM_SetWordBreakProc(EDITSTATE *es, void *wbp)
  */
 static void EDIT_EM_SetWordBreakProc16(EDITSTATE *es, EDITWORDBREAKPROC16 wbp)
 {
-	if (es->word_break_proc16 == wbp)
-		return;
-
-	es->word_break_proc = NULL;
-	es->word_break_proc16 = wbp;
-	if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
-		EDIT_BuildLineDefs_ML(es, 0, get_text_length(es), 0, NULL);
-		EDIT_UpdateText(es, NULL, TRUE);
-	}
+    struct word_break_thunk *thunk = add_word_break_thunk( wbp );
+    if (thunk) EDIT_EM_SetWordBreakProc( es, thunk );
 }
 
 
@@ -5048,7 +5102,7 @@ static LRESULT EditWndProc_common( HWND hwnd, UINT msg,
 		break;
 
 	case EM_GETWORDBREAKPROC16:
-		result = (LRESULT)es->word_break_proc16;
+                result = (LRESULT)get_word_break_thunk( es->word_break_proc );
 		break;
 	case EM_GETWORDBREAKPROC:
 		result = (LRESULT)es->word_break_proc;




More information about the wine-cvs mailing list