edit.c: fix bad selection ranges.
C. Scott Ananian
cscott at cscott.net
Thu Mar 17 15:10:14 CST 2005
ChangeLog:
- EDIT_EM_SetSel: Old/new selection range ordering code would break when
old_end < start < end < old_start
Rearrange the comparisons slightly to fix this; also document
the ordering relation this code is supposed to produce, and
verify optimality.
--scott
DC counter-intelligence Shoal Bay shortwave CABOUNCE NSA AES SUMAC
BOND Sigint domestic disruption overthrow BGGYPSY OVER THE HORIZON RADAR
( http://cscott.net/ )
Index: dlls/user/edit.c
===================================================================
RCS file: /home/wine/wine/dlls/user/edit.c,v
retrieving revision 1.20
diff -u -p -r1.20 edit.c
--- dlls/user/edit.c 25 Feb 2005 16:51:13 -0000 1.20
+++ dlls/user/edit.c 17 Mar 2005 21:07:43 -0000
@@ -3603,11 +3603,23 @@ static void EDIT_EM_SetSel(EDITSTATE *es
es->flags |= EF_AFTER_WRAP;
else
es->flags &= ~EF_AFTER_WRAP;
-/* This is a little bit more efficient than before, not sure if it can be improved. FIXME? */
- ORDER_UINT(start, end);
+ /* Compute the necessary invalidation region. */
+ /* Note that we don't need to invalidate regions which have
+ * "never" been selected, or those which are "still" selected.
+ * In fact, every time we hit a selection boundary, we can
+ * *toggle* whether we need to invalidate. Thus we can optimize by
+ * *sorting* the interval endpoints. Let's assume that we sort them
+ * in this order:
+ * start <= end <= old_start <= old_end
+ * Knuth 5.3.1 (p 183) asssures us that this can be done optimally
+ * in 5 comparisons; ie it's impossible to do better than the
+ * following: */
ORDER_UINT(end, old_end);
ORDER_UINT(start, old_start);
ORDER_UINT(old_start, old_end);
+ ORDER_UINT(start, end);
+ /* Note that at this point 'end' and 'old_start' are not in order, but
+ * start is definitely the min. and old_end is definitely the max. */
if (end != old_start)
{
/*
@@ -3616,6 +3628,7 @@ static void EDIT_EM_SetSel(EDITSTATE *es
* EDIT_InvalidateText(es, start, end);
* EDIT_InvalidateText(es, old_start, old_end);
* in place of the following if statement.
+ * (That would complete the optimal five-comparison four-element sort.)
*/
if (old_start > end )
{
More information about the wine-patches
mailing list