lynx-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

lynx-dev Re: [PATCH 2.8.4dev.18] GridText.c cleanup


From: Ilya Zakharevich
Subject: lynx-dev Re: [PATCH 2.8.4dev.18] GridText.c cleanup
Date: Thu, 8 Mar 2001 02:33:14 -0500
User-agent: Mutt/1.2.5i

On Sat, Mar 03, 2001 at 01:10:00AM -0500, Ilya Zakharevich wrote:
> On Sun, Feb 25, 2001 at 01:46:54AM -0500, Ilya Zakharevich wrote:
> > This patch does not add any new functionality.  All I did was I went
> > through more than 1000 lines of extremely badly written obfuscated C code
> > worthy of a first year CS student...
> 
> The patch in the current message is an addition to that patch of
> several days ago.  It adds the following:

This part III of the patch removes the last significant obfuscation
from split_line().  It also starts to collect the fruits of the
cleanup.  It removes a bug which lead to style change markup pointing
past end-of-string (might be benign).

It also removes a bug which lead to a significant memory overhead,
garish display, and possibly other side effect.  The bug is caused by
off-by-one error in the removal-of-zero-length-markup logic.  Due to
this bug, zero-length markup was never removed, which lead to
accumulation of style change entries, eventually to a buffer overflow.
At this moment lynx stylification engine would give up, resulting in
uncomprehensible ocean of colors on the display.  To demonstrate, make
a select entry with more than 46 entries.  [My auto-display-charset
logic added 2 new encodings to the table of Lynx, bringing the number
to 46 on the 'o'ption form. ;-]

Enjoy,
Ilya

--- ./src/GridText.c-as-sent2   Sun Feb 25 05:57:18 2001
+++ ./src/GridText.c    Thu Mar  8 02:16:20 2001
@@ -155,17 +155,6 @@ typedef struct _stylechange {
 } HTStyleChange;
 #endif
 
-#define STYLES_ARE_OPPOSITE(p1,p2)                     \
-       ((p1)->style == (p2)->style                     \
-        && (((p1)->direction == STACK_OFF              \
-             && (p2)->direction == STACK_ON)           \
-            || ((p1)->direction == ABS_OFF             \
-                && (p2)->direction == ABS_ON)          \
-            || ((p1)->direction == STACK_ON            \
-                && (p2)->direction == STACK_OFF)       \
-            || ((p1)->direction == ABS_ON              \
-                && (p2)->direction == ABS_OFF)))
-
 typedef struct _line {
        struct _line    *next;
        struct _line    *prev;
@@ -2469,7 +2458,8 @@ PRIVATE HTLine * insert_blanks_in_line A
 #if defined(USE_COLOR_STYLE)
     int istyle = 0;
 #endif
-    int added_chars = 0, shift = 0, head_processed = 1;
+    int added_chars = 0, shift = 0;
+    int head_processed;
     HTLine * mod_line;
     char *newdata, *s = line->data, *copied = line->data, *t;
 
@@ -2489,6 +2479,7 @@ PRIVATE HTLine * insert_blanks_in_line A
        return NULL;
     if (!prev_anchor)
        prev_anchor = text->first_anchor;
+    head_processed = (prev_anchor && prev_anchor->line_num < line_number);
     memcpy(mod_line, line, LINE_SIZE(1));
     t = newdata = mod_line->data;
     ip = 0;
@@ -2548,6 +2539,35 @@ PRIVATE HTLine * insert_blanks_in_line A
     return mod_line;
 }
 
+PRIVATE HTStyleChange * skip_matched_and_correct_offsets ARGS3(
+       HTStyleChange *,        end,
+       HTStyleChange *,        start,
+       unsigned,               split_pos)
+{ /* Found an OFF change not part of an adjacent matched pair.
+   * Walk backward looking for the corresponding ON change.
+   * Move everything after split_pos to be at split_pos.
+   * This can only work correctly if all changes are correctly
+   * nested!  If this fails, assume it is safer to leave whatever
+   * comes before the OFF on the previous line alone. */
+    int level = 0;
+    HTStyleChange *tmp = end;
+
+    for (; tmp >= start; tmp--) {
+       if (tmp->style == end->style) {
+           if (tmp->direction == STACK_OFF)
+               level--;
+           else if (tmp->direction == STACK_ON) {
+               if (++level == 0)
+                   return tmp;
+           } else
+               return 0;
+       }
+       if (tmp->horizpos > split_pos)
+           tmp->horizpos = split_pos;
+    }
+    return 0;
+}
+
 PRIVATE void split_line ARGS2(
        HText *,        text,
        unsigned,       split)
@@ -2790,87 +2810,61 @@ PRIVATE void split_line ARGS2(
            to--;
            from--;
        }
-       /* FROM may be invalid, otherwise it either an ON change at or
+       /* FROM may be invalid, otherwise it is either an ON change at or
           before s_pre, or is an OFF change at or before s_post.  */
+
        scan = from;
        at_end = from;
        /* Now on the previous line we have a correctly nested but
           possibly non-terminated sequence of style changes.
           Terminate it, and duplicate unterminated changes at the
-          beginning of the new line.
-
-          SCAN always goes backwards, skipping ajacent matching
-          ON/OFF pairs, and finding a matching ON change to any other
-          OFF change.  Anything else is an ON change which need to
-          be terminated.  AT_END may go backwards to cancel two opposite
-          changes at end. */
-       while (at_end >= previous->styles && to >= line->styles) {
-           if (at_end > previous->styles
-               && at_end->horizpos == at_end[-1].horizpos
-               && STYLES_ARE_OPPOSITE(at_end, at_end - 1)) {
-               /*
-                *  Discard pairs of ON/OFF for the same color style, but only
-                *  if they appear at the same position. - kw
-                */
-               at_end -= 2;
-               if (scan > at_end)
-                   scan = at_end;
-           } else if (scan >= previous->styles && scan->direction /* ON */
-                      && at_end - previous->styles + 1 < MAX_STYLES_ON_LINE) {
-               /*  Found an ON change which isn't followed by a
-                *  corresponding OFF.  Append the missing OFF change at
-                *  the end, and add an ON change at the beginning of
-                *  the current line. - kw */
-               to->horizpos = 0;
-               to->direction = STACK_ON;
-               to->style = scan->style;
-               at_end++;
-               at_end->style = to->style;
-               at_end->direction = ABS_OFF;
-               at_end->horizpos = previous->size;
-               to--;
-               scan--;
-           } else if (scan > previous->styles &&
-                      STYLES_ARE_OPPOSITE(scan, scan-1)) {
-               /* Skip pairs of adjacent ON/OFF or OFF/ON changes. */
-               scan -= 2;
-           } else if (scan >= previous->styles && !scan->direction) { /* OFF */
-               /*
-                *  Found an OFF change not part of an adjacent matched pair.
-                *  Walk backward looking for the corresponding ON change.
-                *  If we find it, skip the ON/OFF and everything in between.
-                *  This can only work correctly if all changes are correctly
-                *  nested!  If this fails, assume it is safer to leave whatever
-                *  comes before the OFF on the previous line alone.  Setting
-                *  spare to 0 ensures that it won't be used in a following
-                *  iteration. - kw
-                */
-               int level=-1;
-               int itmp;
-               HTStyleChange *tmp = scan - 1;
-
-               for (; tmp >= previous->styles; tmp--) {
-                   if (tmp->style == scan->style) {
-                       if (tmp->direction == STACK_OFF) {
-                           level--;
-                       } else if (tmp->direction == STACK_ON) {
-                           if (++level == 0)
-                               break;
-                       } else
-                           break;
-                   }
+          beginning of the new line. */
+       while (scan >= previous->styles && at_end >= previous->styles) {
+           /* The algorithm: scan back though the styles on the previous line.
+              a) If OFF, skip the matched group.
+                 Report a bug on failure.
+              b) If ON, (try to) cancel the corresponding ON at at_end,
+                 and the corresponding OFF at to;
+                 If not, put the corresponding OFF at at_end, and copy to to;
+            */
+           if (scan->direction == STACK_OFF) {
+               scan = skip_matched_and_correct_offsets(scan, previous->styles,
+                                                       s_pre);
+               if (!scan) {
+                   CTRACE((tfp, "BUG: styles improperly nested.\n"));
+                   break;
                }
-               if (level == 0)
-                   scan = tmp - 1;
-               else
-                   scan = previous->styles - 1; /* Stop */
-           } else /* Nothing applied, so we are done with the loop. - kw */
-               break;
-       }
-       if (at_end >= previous->styles && at_end->direction) {
-           CTRACE((tfp, "%s\n%s%s\n",
-                   "........... Too many character styles on line:",
-                   "........... ", previous->data));
+           } else if (scan->direction == STACK_ON) {
+               if ( at_end->direction == STACK_ON
+                    && at_end->style == scan->style
+                    && at_end->horizpos >= s_pre )
+                   at_end--;
+               else if (at_end >= previous->styles + MAX_STYLES_ON_LINE - 1) {
+                   CTRACE((tfp, "BUG: style overflow before split_line.\n"));
+                   break;
+               } else {
+                   at_end++;
+                   at_end->direction = STACK_OFF;
+                   at_end->style = scan->style;
+                   at_end->horizpos = s_pre;
+               }
+               if ( to < line->styles + MAX_STYLES_ON_LINE - 1
+                    && to[1].direction == STACK_OFF
+                    && to[1].horizpos <= SpecialAttrChars
+                    && to[1].style == scan->style )
+                   to++;
+               else if (to >= line->styles) {
+                   *to = *scan;
+                   to->horizpos = SpecialAttrChars;
+                   to--;
+               } else {
+                   CTRACE((tfp, "BUG: style overflow after split_line.\n"));
+                   break;
+               }
+           }
+           if (scan->horizpos > s_pre)
+               scan->horizpos = s_pre;
+           scan--;
        }
        line->numstyles = line->styles + MAX_STYLES_ON_LINE - 1 - to;
        if (line->numstyles > 0 && line->numstyles < MAX_STYLES_ON_LINE) {
@@ -2881,7 +2875,7 @@ PRIVATE void split_line ARGS2(
        } else if (line->numstyles == 0)
            line->styles[0].horizpos = ~0; /* ?!!! */
        previous->numstyles = at_end - previous->styles + 1;
-       if (at_end < previous->styles)
+       if (previous->numstyles == 0)
            previous->styles[0].horizpos = ~0;  /* ?!!! */
     }
 #endif /*USE_COLOR_STYLE*/
@@ -4331,9 +4330,9 @@ PUBLIC void _internal_HTC ARGS3(HText *,
        line = text->last_line;
 
        if (line->numstyles > 0 && dir == 0 &&
-           line->styles[line->numstyles].direction &&
-           line->styles[line->numstyles].style == style &&
-           (int) line->styles[line->numstyles].horizpos
+           line->styles[line->numstyles-1].direction &&
+           line->styles[line->numstyles-1].style == style &&
+           (int) line->styles[line->numstyles-1].horizpos
            == (int)line->size - ctrl_chars_on_this_line) {
            /*
             *  If this is an OFF change directly preceded by an

; To UNSUBSCRIBE: Send "unsubscribe lynx-dev" to address@hidden

reply via email to

[Prev in Thread] Current Thread [Next in Thread]