Dear Lesstifferss:
Here is a diff -u patch for lesstif 0.91.4 Xm/lib that
fixes a bug that results in faulty highlighting
in Text widgets when the pointer is dragged to the left.
The selection operated properly, but the highlighting
jumped to the end of the text and stuck there.

The patch modifies XmTextSetHighlight only.

Highlighting and the selection are now back in sync
on a few of the test cases in test/text

However, under ddd 3.2.1, highlighting and selection 
are still not always in sync.  ddd tries to highlight 
and select a full word when you left-press on it.
Then, dragging the selection and highlighting don't
always stay in sync under dragging.  With my 
patch, the selection feature of ddd Text windows
is still a lot more useable than it was before.

Thanks,
Seth Chaiken
Dept. of Computer Science
University at Albany
Albany NY 12222
[EMAIL PROTECTED]


--- Text.c.orig Wed Jul 12 16:51:27 2000
+++ Text.c      Thu Jul 13 14:56:36 2000
@@ -24,7 +24,7 @@
 
 static const char rcsid[] = "$Id: Text.c,v 1.123 2000/05/20 15:46:14 hennessy Exp $";
 
-#undef VERBOSE
+/* #undef VERBOSE */
 
 #include <LTconfig.h>
 #include <Xm/XmP.h>
@@ -1064,7 +1064,7 @@
                                   Text_LineTable(w)[i].start_pos != 0);
         i++)
     {
-       DEBUGOUT(XdbDebug(__FILE__, w,
+       DEBUGOUT(XdbDebug(__FILE__, (Widget) w,
                          "RefigureLines: [%d] start_pos %d virt %d\n",
                          i, Text_LineTable(w)[i].start_pos,
                          Text_LineTable(w)[i].virt_line));
@@ -2565,11 +2565,14 @@
 void
 XmTextSetHighlight(Widget w, XmTextPosition left, XmTextPosition right, 
XmHighlightMode mode)
 {
-    if (left >= right)
+#define ldebug 0
+
+  /* sdc 7/13/00 check left<0 too. */
+  if( (left >= right) || ( left < 0 ) )
     {
        /* FIX ME */
        DEBUGOUT(XdbDebug(__FILE__, w,
-                         "XmTextSetHighlight %d >= %d, not sure what to do.\n",
+                         "XmTextSetHighlight not 0 <= %d < %d, not sure what to 
+do.\n",
                          left, right));
 
        return;
@@ -2577,17 +2580,35 @@
 
     if (XtIsSubclass(w, xmTextWidgetClass))
     {
-       int             i, j, k, l;
-       XmHighlightMode lm, rm;
 
-#if 0
+      /* [EMAIL PROTECTED] 7/13/00 Seth Chaiken, SUNY at Albany.
+         Scan algorithm rewritten to fix a bug that highlighting
+        sometimes is extended to right (MAX_INT) end of the text
+         when the cursor is dragged two or more spaces to the left. */
+
+      /* Each index variable == -1 if the specified index doesn't exist. */
+      int      i, s1, s2, s3, s4;  /* list indices, see below. */
+      int       sneeded = 0;        /* # list entries needed for
+                                      [left, right) highlight */
+
+      int       sleft, sright;      /* list indices 
+                                      for [left, right) highlight */
+      XmHighlightMode rmode;        /* mode at right boundary */
+
+      int      d;             /* Change in number of list entries. */
+
+      int      number;             /* number of highlist list entries used */
+
+#if ldebug
        fprintf(stderr,
-                         "XmTextSetHighlight(%d,%d,%s)\n",
-                         left, right, XdbHighlightMode2String(mode));
+               "XmTextSetHighlight(%d,%d,%s)\n",
+               (int) left, (int) right, 
+               XdbHighlightMode2String(mode));
 #endif
        DEBUGOUT(XdbDebug(__FILE__, w,
                          "XmTextSetHighlight(%d,%d,%s)\n",
-                         left, right, XdbHighlightMode2String(mode)));
+                         (int) left, (int) right, 
+                         XdbHighlightMode2String(mode)));
 
        /* Provide for initial entries if there's none */
        if (Text_Highlight(w).number == 0) 
@@ -2599,106 +2620,136 @@
            Text_Highlight(w).number = 2;
        }
 
-       /* Find the place from where to change the highlight */
-       for (i=0; i < Text_Highlight(w).number &&
-                       Text_Highlight(w).list[i].position < left; i++)
-               ;
-       if (i == 0)
-       {
-           /* assert(left==0); */
-           lm = XmHIGHLIGHT_NORMAL;
-       }
+       number = Text_Highlight(w).number;
+
+#if ldebug
+       fprintf(stderr,"\tXmTextSetHighlight input:\n");
+       for (i=0; i<number; i++)
+               fprintf(stderr,
+                         "\tXmTextSetHighlight -> [%d] %d %s\n",
+                         i, (int)Text_Highlight(w).list[i].position,
+                         XdbHighlightMode2String(Text_Highlight(w).list[i].mode));
+#endif
+
+       /* First, find the places from where to change the highlight */
+       /* Sequential search is used.  If this is too inefficient,
+          you can code binary search. 
+           sdc 7/13/00 */
+       s1 = -1;
+       i  = 0;
+       while( i < number &&
+              Text_Highlight(w).list[i].position < left )
+         {
+           s1 = i++;
+         }
+       /* s1 == max. index in list with list[index].position < left. */
+
+       s2 = s1;
+       while( i < number &&
+              Text_Highlight(w).list[i].position <= left )
+         {
+           s2 = i++;
+         }
+       /* s2 == max. index in list with list[index].position <= left. */
+
+       s3 = s2;
+       while( i < number &&
+              Text_Highlight(w).list[i].position < right )
+         {
+           s3 = i++;
+         }
+       /* s3 == max. index in list 
+                 with list[index].position <= left or < right. */
+
+       s4 = s3;
+       while( i < number &&
+              Text_Highlight(w).list[i].position <= right )
+         {
+           s4 = i++;
+         }
+       /* s4 == max. index in list 
+                 with list[index].position <= left or <= right. */
+
+       /*Second, figure out what new highlight list records are needed.*/
+       /*For the left... */
+       if( s1 >= 0 && Text_Highlight(w).list[s1].mode == mode )
+         {
+           sleft = s1;  /* Mode at left boundary == mode. */
+         }
        else
-       {
-           lm = Text_Highlight(w).list[i-1].mode;
-       }
-       for (j=i; j < Text_Highlight(w).number &&
-                       Text_Highlight(w).list[j].position < right; j++)
-               ;
-       if (j == 0)
-       {
-           /* assert(right==0); */
-           rm = XmHIGHLIGHT_NORMAL;
-       }
+         {
+           sleft = s1 + 1;
+           sneeded++;  /* We need a record at the left change boundary */
+         }
+
+        /*Determine if a record is needed for the right.*/
+       if( s4 == number-1 )
+         {
+           /* right change boundary is the sentinal.  We need to 
+              preserve the sentinal.  I don't know whether to 
+              set the sentinal's mode from mode, or keep its old mode. 
+              sdc 7/13/00 */
+           sright = sleft + 1; 
+           sneeded++;
+           rmode = Text_Highlight(w).list[number - 1].mode;  /*Keep old mode*/
+         }
+       else if( (rmode = Text_Highlight(w).list[s4].mode) != mode )
+         {
+           /* mode changes at right boundary. */
+           sright = sleft + 1;
+           sneeded++;
+         }
        else
-       {
-           rm = Text_Highlight(w).list[j-1].mode;
-       }
-       if (Text_Highlight(w).list[i].position == left) 
-       {
-           Text_Highlight(w).list[i].mode = mode;
-       } 
-       else if (Text_Highlight(w).list[i].position < right) 
-       {
-           Text_Highlight(w).list[i].mode = mode;
-           Text_Highlight(w).list[i].position = left;
-       } 
-       else 
-       {
-           /* Insert an entry for the left */
-           if (lm != mode) 
-           {
-               /* Need one more entry */
-               /* Make sure there's an empty space */
-               if (Text_Highlight(w).number == Text_Highlight(w).maximum) 
-               {
-                   Text_Highlight(w).maximum += 32;
-                   Text_Highlight(w).list = (_XmHighlightRec *)XtRealloc(
-                               (XtPointer)Text_Highlight(w).list,
-                               Text_Highlight(w).maximum * sizeof(_XmHighlightRec));
-               }
+         {
+           /* Original mode at right boundary == new highlight mode */
+           sright = -1; /* Don't need a right record. */
+         }
 
-               /* Go ahead. Do we need to insert ? */
-               for (j=Text_Highlight(w).number; j>i; j--) 
-               {
-                   Text_Highlight(w).list[j] = Text_Highlight(w).list[j-1];
-               }
-               Text_Highlight(w).number++;
-               Text_Highlight(w).list[i].mode = mode;
-               Text_Highlight(w).list[i].position = left;
-           }
-       }
 
-       /* Remove entries */
-       /* FIX ME this can be more efficient */
-       for (i=0; i<Text_Highlight(w).number && Text_Highlight(w).list[i].position < 
left; i++) ;
-               /* i points to the entry just beyond "left" */
-       for (j=i; j<Text_Highlight(w).number && Text_Highlight(w).list[j].position <= 
right; j++) ;
-       if (i < j-1) 
-       {
-           for (k=i+1, l=j; l<Text_Highlight(w).number; k++,l++) 
-           {
-               Text_Highlight(w).list[k] = Text_Highlight(w).list[l];
-           }
-           Text_Highlight(w).number -= j-i-1;
-       }
-       /* Now this is hilarious - insert one again */
-       i++;
-       if (rm != mode) 
-       {
-           if (Text_Highlight(w).number == Text_Highlight(w).maximum) 
-           {
+       /*Third, move or remove old records if necessary.*/
+       d = sneeded - (s4 - s1);
+       if( d > 0 )
+         {
+           /* Make sure there's enough empty space; initialize i too. */
+           if (((i=number) + d) 
+               > Text_Highlight(w).maximum) 
+             {
                Text_Highlight(w).maximum += 32;
-               Text_Highlight(w).list = (_XmHighlightRec *)XtRealloc(
-                           (XtPointer)Text_Highlight(w).list,
-                           Text_Highlight(w).maximum * sizeof(_XmHighlightRec));
-           }
-           for (k=Text_Highlight(w).number; k>i; k--) 
-           {
-               Text_Highlight(w).list[k] = Text_Highlight(w).list[k-1];
-           }
-           Text_Highlight(w).number++;
-           Text_Highlight(w).list[i].mode = rm;
-           Text_Highlight(w).list[i].position = right;
-       }
+               Text_Highlight(w).list 
+                 = (_XmHighlightRec *)XtRealloc(
+                       (XtPointer)Text_Highlight(w).list,
+                       Text_Highlight(w).maximum * sizeof(_XmHighlightRec));
+             }
+           for( i = i - 1; i > s1; i-- )
+             Text_Highlight(w).list[i + d] = Text_Highlight(w).list[i];
+         }
+       else if ( d < 0 )
+         {
+           for( i = (s1 + 1) - d; i < number; i++ )
+             Text_Highlight(w).list[i + d] = Text_Highlight(w).list[i];
+         }
+       number = (Text_Highlight(w).number += d);
+
+       /*Finally, install our 1-2 new highlight records.*/
+       /*left record install might be redundant, but it simplifies the code*/
+       Text_Highlight(w).list[sleft].mode = mode;
+       Text_Highlight(w).list[sleft].position = left;
+       /*install right record only if needed.*/
+       if( sright >= 0 )
+         {
+           Text_Highlight(w).list[sright].mode = rmode;
+           Text_Highlight(w).list[sright].position = right;
+         }
        /* End Highlighting */
-#if 0
-       for (i=0; i<Text_Highlight(w).number; i++)
+#if ldebug
+       fprintf(stderr,"\tXmTextSetHighlight results:\n");
+       for (i=0; i<number; i++)
                fprintf(stderr,
                          "\tXmTextSetHighlight -> [%d] %d %s\n",
-                         i, Text_Highlight(w).list[i].position,
+                         i, (int)Text_Highlight(w).list[i].position,
                          XdbHighlightMode2String(Text_Highlight(w).list[i].mode));
 #endif
+       /*end patch by [EMAIL PROTECTED] 7/13/00*/
 
        if (XtIsRealized(w))
        {
@@ -2713,6 +2764,8 @@
     {
        _XmWarning(w, "XmTextSetHighlight: widget has invalid class");
     }
+#undef ldebug
+
 }
 
 void

Reply via email to