DrawTextEx reprefixing

Medland, Bill Bill.Medland at accpac.com
Thu Jan 31 10:54:54 CST 2002


-------------- next part --------------
Bill Medland (medbi01 at accpac.com)
1. Introduce a significant design decision.
2. Recalculate the prefix location if ellipsification alters it.  This carefully
   does NOT emulate a Microsoft bug in which reprefixing is wrong when the 
   first character removed by ellipsification is the one that would have been
   underlined (under Win98 at least).
   

Index: wine/dlls/user/text.c
===================================================================
RCS file: /home/wine/wine/dlls/user/text.c,v
retrieving revision 1.20
diff -u -r1.20 text.c
--- wine/dlls/user/text.c	2002/01/29 02:46:09	1.20
+++ wine/dlls/user/text.c	2002/01/31 14:43:36
@@ -28,6 +28,40 @@
 /*********************************************************************
  *
  *            DrawText functions
+ *
+ * Design issues
+ *   How many buffers to use
+ *     While processing in DrawText there are potentially three different forms
+ *     of the text that need to be held.  How are they best held?
+ *     1. The original text is needed, of course, to see what to display.
+ *     2. The text that will be returned to the user if the DT_MODIFYSTRING is
+ *        in effect.
+ *     3. The buffered text that is about to be displayed e.g. the current line.
+ *        Typically this will exclude the ampersands used for prefixing etc.
+ *
+ *     Complications.
+ *     a. If the buffered text to be displayed includes the ampersands then
+ *        we will need special measurement and draw functions that will ignore
+ *        the ampersands (e.g. by copying to a buffer without the prefix and
+ *        then using the normal forms).  This may involve less space but may 
+ *        require more processing.  e.g. since a line containing tabs may
+ *        contain several underlined characters either we need to carry around
+ *        a list of prefix locations or we may need to locate them several
+ *        times.
+ *     b. If we actually directly modify the "original text" as we go then we
+ *        will need some special "caching" to handle the fact that when we 
+ *        ellipsify the text the ellipsis may modify the next line of text,
+ *        which we have not yet processed.  (e.g. ellipsification of a W at the
+ *        end of a line will overwrite the W, the \n and the first character of
+ *        the next line, and a \0 will overwrite the second.  Try it!!)
+ *
+ *     Option 1.  Three separate storages. (To be implemented)
+ *       If DT_MODIFYSTRING is in effect then allocate an extra buffer to hold
+ *       the edited string in some form, either as the string itself or as some
+ *       sort of "edit list" to be applied just before returning.
+ *       Use a buffer that holds the ellipsified current line sans ampersands
+ *       and accept the need occasionally to recalculate the prefixes (if
+ *       DT_EXPANDTABS and not DT_NOPREFIX and not DT_HIDEPREFIX)
  */
 
 #define TAB     9
@@ -51,6 +85,56 @@
 static int spacewidth;
 static int prefix_offset;
 
+/*********************************************************************
+ *                      TEXT_Reprefix
+ *
+ *  Reanalyse the text to find the prefixed character.  This is called when
+ *  wordbreaking or ellipsification has shortened the string such that the
+ *  previously noted prefixed character is no longer visible.
+ *
+ * Parameters
+ *   str        [in] The original string segment (including all characters)
+ *   n1         [in] The number of characters visible before the path ellipsis
+ *   n2         [in] The number of characters replaced by the path ellipsis
+ *   ne         [in] The number of characters in the path ellipsis, ignored if
+ *              n2 is zero
+ *   n3         [in] The number of characters visible after the path ellipsis
+ *
+ * Return Values
+ *   The prefix offset within the new string segment (the one that contains the
+ *   ellipses and does not contain the prefix characters) (-1 if none)
+ *
+ * Remarks
+ *   We know that n1+n2+n3 must be strictly less than the length of the segment
+ *   (because otherwise there would be no need to call this function)
+ */
+
+static int TEXT_Reprefix (const WCHAR *str, unsigned int n1, unsigned int n2,
+                          unsigned int ne, unsigned int n3)
+{
+    int result = -1;
+    unsigned int i = 0;
+    unsigned int n = n1 + n2 + n3;
+    if (!n2) ne = 0;
+    while (i < n)
+    {
+        if (i == n1)
+        {
+            /* Reached the path ellipsis; jump over it */
+            str += n2;
+            i += n2;
+            if (!n3) break; /* Nothing after the path ellipsis */
+        }
+        if (*str++ == PREFIX)
+        {
+            result = (i < n1) ? i : i - n2 + ne;
+            str++;
+        }
+        else;
+        i++;
+    }
+    return result;
+}
 
 /*********************************************************************
  *  Return next line of text from a string.
@@ -329,6 +413,8 @@
 	        int totalLen = i_count >= 0 ? i_count : strlenW(str);
 	            int fnameLen = totalLen;
                 int old_prefix_offset = prefix_offset;
+                int len_before_ellipsis;
+                int len_after_ellipsis;
 
 	            /* allow room for '...' */
 	            count = min(totalLen+3, countof(line)-3);
@@ -386,17 +472,21 @@
 
 	            if (fnameLen < len-3) /* some of the path will fit */
 	            {
+                        len_before_ellipsis = len-3-fnameLen;
+                        len_after_ellipsis = fnameLen;
 	                /* put the ELLIPSIS between the path and filename */
-	                strncpyW(swapStr, &line[fnameLen+3], len-3-fnameLen);
-	                swapStr[len-3-fnameLen] = '\0';
+	                strncpyW(swapStr, &line[fnameLen+3], len_before_ellipsis);
+	                swapStr[len_before_ellipsis] = '\0';
 	                strcatW(swapStr, ELLIPSISW);
 	                strncpyW(swapStr+strlenW(swapStr), &line[3], fnameLen);
 	            }
 	            else
 	            {
 	                /* move the ELLIPSIS to the end */
-	                strncpyW(swapStr, &line[3], len-3);
-	                swapStr[len-3] = '\0';
+                        len_before_ellipsis = len-3;
+                        len_after_ellipsis = 0;
+	                strncpyW(swapStr, &line[3], len_before_ellipsis);
+	                swapStr[len_before_ellipsis] = '\0';
 	                strcpyW(swapStr+strlenW(swapStr), ELLIPSISW);
 	            }
 
@@ -404,12 +494,9 @@
 	            line[len] = '\0';
 	            strPtr = NULL;
 
-               /* Note that really we ought to refigure the location of
-                * the underline for the prefix; it might be currently set for
-                * something we have just ellipsified out.
-                * NB We had better do it before modifying the string and
-                * loosing the ampersands
-                */
+               if (prefix_offset >= 0 &&
+                   prefix_offset >= len_before_ellipsis)
+                   prefix_offset = TEXT_Reprefix (str, len_before_ellipsis, strlenW(str)-3-len_before_ellipsis-len_after_ellipsis, 3, len_after_ellipsis);
 
                if (flags & DT_MODIFYSTRING)
                     strcpyW(str, swapStr);


More information about the wine-patches mailing list