Aric Stewart : user32: Use uniscribe ScriptBreak to handle edit control linebreaking.

Alexandre Julliard julliard at winehq.org
Tue Oct 11 14:03:37 CDT 2011


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

Author: Aric Stewart <aric at codeweavers.com>
Date:   Mon Oct 10 14:54:41 2011 -0500

user32: Use uniscribe ScriptBreak to handle edit control linebreaking.

---

 dlls/user32/Makefile.in |    2 +-
 dlls/user32/edit.c      |  115 +++++++++++++++++++++++------------------------
 2 files changed, 58 insertions(+), 59 deletions(-)

diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in
index d2cdc92..3607956 100644
--- a/dlls/user32/Makefile.in
+++ b/dlls/user32/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -D_USER32_ -D_WINABLE_
 MODULE    = user32.dll
 IMPORTLIB = user32
 IMPORTS   = gdi32 version advapi32
-DELAYIMPORTS = imm32
+DELAYIMPORTS = imm32 usp10
 
 C_SRCS = \
 	button.c \
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c
index 87f8682..e02a268 100644
--- a/dlls/user32/edit.c
+++ b/dlls/user32/edit.c
@@ -53,6 +53,7 @@
 #include "winnt.h"
 #include "win.h"
 #include "imm.h"
+#include "usp10.h"
 #include "wine/unicode.h"
 #include "controls.h"
 #include "user_private.h"
@@ -153,6 +154,10 @@ typedef struct
 	 */
 	UINT composition_len;   /* length of composition, 0 == no composition */
 	int composition_start;  /* the character position for the composition */
+	/*
+	 * Uniscribe Data
+	 */
+	SCRIPT_LOGATTR *logAttr;
 } EDITSTATE;
 
 
@@ -247,6 +252,14 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
 }
 
 
+static inline UINT get_text_length(EDITSTATE *es)
+{
+    if(es->text_length == (UINT)-1)
+        es->text_length = strlenW(es->text);
+    return es->text_length;
+}
+
+
 /*********************************************************************
  *
  *	EDIT_WordBreakProc
@@ -256,61 +269,51 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
  *		allows to be called without linebreaks between s[0] up to
  *		s[count - 1].  Remember it is only called
  *		internally, so we can decide this for ourselves.
+ *		Additional we will always be breaking the full string.
  *
  */
-static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
+static INT EDIT_WordBreakProc(EDITSTATE *es, LPWSTR s, INT index, INT count, INT action)
 {
-	INT ret = 0;
+    INT ret = 0;
 
-	TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
+    TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
 
-	if(!s) return 0;
+    if(!s) return 0;
 
-	switch (action) {
-	case WB_LEFT:
-		if (!count)
-			break;
-		if (index)
-			index--;
-		if (s[index] == ' ') {
-			while (index && (s[index] == ' '))
-				index--;
-			if (index) {
-				while (index && (s[index] != ' '))
-					index--;
-				if (s[index] == ' ')
-					index++;
-			}
-		} else {
-			while (index && (s[index] != ' '))
-				index--;
-			if (s[index] == ' ')
-				index++;
-		}
-		ret = index;
-		break;
-	case WB_RIGHT:
-		if (!count)
-			break;
-		if (index)
-			index--;
-		if (s[index] == ' ')
-			while ((index < count) && (s[index] == ' ')) index++;
-		else {
-			while (s[index] && (s[index] != ' ') && (index < count))
-				index++;
-			while ((s[index] == ' ') && (index < count)) index++;
-		}
-		ret = index;
-		break;
-	case WB_ISDELIMITER:
-		ret = (s[index] == ' ');
-		break;
-	default:
-		ERR("unknown action code, please report !\n");
-		break;
-	}
-	return ret;
+    if (!es->logAttr)
+    {
+        SCRIPT_ANALYSIS psa;
+
+        memset(&psa,0,sizeof(SCRIPT_ANALYSIS));
+        psa.eScript = SCRIPT_UNDEFINED;
+
+        es->logAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_LOGATTR) * get_text_length(es));
+        ScriptBreak(es->text, get_text_length(es), &psa, es->logAttr);
+    }
+
+    switch (action) {
+    case WB_LEFT:
+        if (index)
+            index--;
+        while (index && !es->logAttr[index].fSoftBreak)
+            index--;
+        ret = index;
+        break;
+    case WB_RIGHT:
+        if (!count)
+            break;
+        while (s[index] && index < count && !es->logAttr[index].fSoftBreak)
+            index++;
+        ret = index;
+        break;
+    case WB_ISDELIMITER:
+        ret = es->logAttr[index].fWhiteSpace;
+        break;
+    default:
+        ERR("unknown action code, please report !\n");
+        break;
+    }
+    return ret;
 }
 
 
@@ -357,7 +360,7 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count
 	    }
         }
 	else
-            ret = EDIT_WordBreakProc(es->text + start, index, count, action);
+            ret = EDIT_WordBreakProc(es, es->text, index+start, count+start, action) - start;
 
 	return ret;
 }
@@ -642,14 +645,6 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
 	ReleaseDC(es->hwndSelf, dc);
 }
 
-
-static inline UINT get_text_length(EDITSTATE *es)
-{
-    if(es->text_length == (UINT)-1)
-        es->text_length = strlenW(es->text);
-    return es->text_length;
-}
-
 /*********************************************************************
  *
  *	EDIT_GetPasswordPointer_SL
@@ -1086,6 +1081,9 @@ static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT
 static inline void text_buffer_changed(EDITSTATE *es)
 {
     es->text_length = (UINT)-1;
+
+    HeapFree( GetProcessHeap(), 0, es->logAttr );
+    es->logAttr = NULL;
 }
 
 /*********************************************************************
@@ -4318,6 +4316,7 @@ cleanup:
 	HeapFree(GetProcessHeap(), 0, es->first_line_def);
 	HeapFree(GetProcessHeap(), 0, es->undo_text);
 	if (es->hloc32W) LocalFree(es->hloc32W);
+	HeapFree(GetProcessHeap(), 0, es->logAttr);
 	HeapFree(GetProcessHeap(), 0, es);
 	return FALSE;
 }




More information about the wine-cvs mailing list