lynx-dev
[Top][All Lists]
Advanced

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

lynx-dev [PATCH 2.8.5-dev15] Tables in lynx


From: Ilya Zakharevich
Subject: lynx-dev [PATCH 2.8.5-dev15] Tables in lynx
Date: Sat, 10 May 2003 16:26:46 -0700
User-agent: Mutt/1.4i

This patch improves 1.5x the handling of tables in lynx.  Before, out of
4 steps needed to setup a table, lynx did only one: it moved the
content of cells in horizontal direction to align things vertically.

What remains is to move the contents of cells in vertical direction
(to align things horizontally), and to insert table-lines.  This patch
implements 50% of the logic needed for the vertical movement; this
logic is enough to move a cell one notch up, so that the first line of
the next cell is on the last line of the previous cell.

[I hope that implementing the other 50% should be pretty
straighforward.]  Can somebody look into adding table-lines?  At least
on how to get the info which table cells should be surrounded by
lines?

Enjoy,
Ilya

--- ./src/TRSTable.h--pre       Sun Apr 27 16:38:00 2003
+++ ./src/TRSTable.h    Sat May 10 02:23:14 2003
@@ -30,7 +30,9 @@ extern int Stbl_getFixupPositions PARAMS
     STable_info *      me,
     int                        lineno,
     int *              oldpos,
-    int *              newpos));
+    int *              newpos,
+    int                        prevline_len,
+    int *              do_unsplit));
 extern short Stbl_getAlignment PARAMS((STable_info *));
 
 #ifdef EXP_NESTED_TABLES
--- ./src/TRSTable.c--pre       Fri May  9 23:49:10 2003
+++ ./src/TRSTable.c    Sat May 10 13:26:22 2003
@@ -99,6 +99,14 @@ enum ended_state {
 #define OFFSET_IS_VALID_LAST_CELL      0x10
 #define BELIEVE_OFFSET                 0x20
 #define IS_CONTINUATION_OF_MULTICELL   0x40
+#define IS_UNSPLIT_CANDIDATE           0x80
+#define LAST_CELL_STARTS_WITH_NL       0x100
+
+enum fakeRow_types {
+  fakeRow_starting,
+  fakeRow_finishing,
+  fakeRow_finishing_firstline,
+};
 
 typedef struct _STable_rowinfo {
     /* Each row may be displayed on many display lines, but we fix up
@@ -1323,7 +1331,7 @@ PRIVATE int Stbl_fakeFinishCellInTable A
     STable_info *,     me,
     STable_rowinfo *,  lastrow,
     int,               lineno,
-    int,               finishing)      /* Processing finish or start */
+    enum fakeRow_types,        finishing)      /* Processing finish or start */
 {
     STable_states * s = &me->s;
     int fake = 0;
@@ -1341,7 +1349,7 @@ PRIVATE int Stbl_fakeFinishCellInTable A
        /* <BR></TD> may produce these (XXXX instead of CS__cbf?).  But if
           finishing==0, the caller already checked that we are on a
           different line.  */
-       if (finishing==0)
+       if (finishing == fakeRow_starting)
            fake = 1;
        break;          /* Either can't happen, or may be ignored */
     case CS__eb:
@@ -1382,7 +1390,7 @@ PRIVATE int Stbl_fakeFinishCellInTable A
           the screen width, so the additional checks performed in
           Stbl_finishCellInTable (comparing to Stbl_finishCellInRow)
           are needed. */
-       if (finishing) {
+       if (finishing != fakeRow_starting) {
            /* Fake </TD> at BOL */
            if (Stbl_finishCellInTable(me, end_td, lineno, 0, 0) < 0) {
                return -1;
@@ -1399,9 +1407,9 @@ PRIVATE int Stbl_fakeFinishCellInTable A
        lastrow = me->rows + (me->nrows - 1);
        lastrow->content = IS_CONTINUATION_OF_CELL;
        if (is_multicell)
-           lastrow->content = IS_CONTINUATION_OF_MULTICELL;
-       else
-           lastrow->content = IS_CONTINUATION_OF_CELL;
+           lastrow->content |= IS_CONTINUATION_OF_MULTICELL;
+       if (finishing == fakeRow_finishing_firstline)
+           lastrow->content |= IS_UNSPLIT_CANDIDATE;
        for (i = 0; i < lastrow->allocated; i++) {
            if (lastrow->cells[i].alignment == RESERVEDCELL) {
                need_reserved = 1;
@@ -1473,7 +1481,7 @@ PRIVATE int Stbl_fakeFinishCellInTable A
        /* Fake <TD></TD>...<TD> (and maybe a </TD>) at BOL. */
        CTRACE2(TRACE_TRST,
                (tfp, "TRST:Stbl_fakeFinishCellInTable FAKE %d elts%s\n",
-                     ncells, (finishing ? ", last unfinished" : "")));
+                     ncells, ((finishing != fakeRow_starting) ? ", last 
unfinished" : "")));
        i = 0;
        while (++i <= ncells) {
            /* XXXX A lot of args may be wrong... */
@@ -1484,7 +1492,7 @@ PRIVATE int Stbl_fakeFinishCellInTable A
            lastrow->content &= ~HAS_BEG_OF_CELL; /* BEG_OF_CELL was fake */
            /* We cannot run out of width here, so it is safe to not
               call Stbl_finishCellInTable(), but Stbl_finishCellInRow. */
-           if (!finishing || (i != ncells)) {
+           if (finishing == fakeRow_starting || (i != ncells)) {
                if (Stbl_finishCellInRow(lastrow, s, end_td, lineno, 0) < 0) {
                    return -1;
                }
@@ -1494,7 +1502,8 @@ PRIVATE int Stbl_fakeFinishCellInTable A
                (tfp, "TRST:Stbl_fakeFinishCellInTable(lineno=%d) FINISH 
FAKING\n",
                      lineno));
        return 1;
-    }
+    } else if (finishing == fakeRow_finishing_firstline)
+       lastrow->content |= LAST_CELL_STARTS_WITH_NL;
     return 0;
 }
 #endif
@@ -1534,7 +1543,7 @@ PUBLIC int Stbl_addCellToTable ARGS8(
           appropriate amount of cells */
        if (!NO_AGGRESSIVE_NEWROW && pos == 0 && lastrow->ncells > 0
            && lastrow->cells[lastrow->ncells-1].cLine != lineno) {
-           int rc = Stbl_fakeFinishCellInTable(me, lastrow, lineno, 0);
+           int rc = Stbl_fakeFinishCellInTable(me, lastrow, lineno, 
fakeRow_starting);
 
            if (rc < 0)
                return -1;
@@ -1680,6 +1689,7 @@ PUBLIC int Stbl_trimFakeRows ARGS3(
        me->s.state = CS__0new;         /* This is enough to revive things. */
        me->s.x_td = lastrow->cells[lastrow->ncells - 1].pos;
        me->s.lineno = lastrow->cells[lastrow->ncells - 1].cLine;
+       lastrow->content &= ~LAST_CELL_STARTS_WITH_NL;
        CTRACE2(TRACE_TRST, (tfp, "  un-ended the last row.\n"));
        return 1;
     }
@@ -1752,7 +1762,13 @@ PUBLIC int Stbl_finishCellInTable ARGS5(
 #ifdef EXP_NESTED_TABLES
     if (nested_tables) {
        if (!NO_AGGRESSIVE_NEWROW && !(end_td & TRST_FAKING_CELLS)) {
-           int rc = Stbl_fakeFinishCellInTable(me, lastrow, lineno, 1);
+           /* Last cell, has it a newline in a beginning of cell? */
+           int nl = ((lastrow->content & LAST_CELL_STARTS_WITH_NL)
+                     && lineno > lastrow->cells[icell].cLine)
+                    || ((lastrow->content & HAS_BEG_OF_CELL)
+                        && lastrow->cells[icell].pos >= pos);
+           int rc = Stbl_fakeFinishCellInTable(me, lastrow, lineno,
+                       nl ? fakeRow_finishing_firstline : fakeRow_finishing);
 
            if (rc) {
                if (rc < 0)
@@ -1957,7 +1973,8 @@ PUBLIC int Stbl_finishTABLE ARGS1(
        int minoffset, have_offsets;
        int foundcell = -1, max_width;
 
-       if ((nextrow->content & (IS_CONTINUATION_OF_CELL | HAS_BEG_OF_CELL | 
BELIEVE_OFFSET))
+       if ((nextrow->content & (IS_CONTINUATION_OF_CELL | HAS_BEG_OF_CELL
+                                | IS_CONTINUATION_OF_MULTICELL | 
BELIEVE_OFFSET))
            != (IS_CONTINUATION_OF_CELL | BELIEVE_OFFSET))
            continue;                   /* Not a continuation line */
        minoffset = nextrow[-1].offset; /* Line before first continuation */
@@ -2060,20 +2077,25 @@ PUBLIC short Stbl_getAlignment ARGS1(
     return (short)(me ? me->alignment : HT_ALIGN_NONE);
 }
 
-PRIVATE int get_fixup_positions ARGS4(
+PRIVATE int get_fixup_positions ARGS6(
     STable_rowinfo *,  me,
     int *,             oldpos,
     int *,             newpos,
-    STable_cellinfo *, sumcols)
+    STable_cellinfo *, sumcols,
+    int,               prevline_len,
+    int *,             do_unsplit)
 {
     int i = 0, ip = 0;
     int next_i, newlen;
     int ninserts;
+    int unsplit = ((me->content & IS_UNSPLIT_CANDIDATE) && prevline_len >= 0);
+    int did_unsplit = 0, delta = 0;
 
     if (!me)
        return -1;
+    *do_unsplit = 0;
     while (i < me->ncells) {
-       int offset;
+       int offset, pos;
 
        next_i = i + HTMAX(1, me->cells[i].colspan);
        if (me->cells[i].cLine != me->Line) {
@@ -2082,14 +2104,13 @@ PRIVATE int get_fixup_positions ARGS4(
            i = next_i;
            continue;
        }
-       oldpos[ip] = me->cells[i].pos;
        if ((me->content & OFFSET_IS_VALID)
            && (i == me->ncells - 1
                || !((me->content & OFFSET_IS_VALID_LAST_CELL))))
            offset = me->offset;
        else
            offset = 0;
-       newpos[ip] = sumcols[i].pos + offset;
+       pos = sumcols[i].pos + offset;
        if ((me->cells[i].alignment == HT_CENTER ||
             me->cells[i].alignment == HT_RIGHT) &&
            me->cells[i].len > 0) {
@@ -2097,12 +2118,22 @@ PRIVATE int get_fixup_positions ARGS4(
            newlen = HTMAX(newlen, sumcols[i].len);
            if (me->cells[i].len < newlen) {
                if (me->cells[i].alignment == HT_RIGHT) {
-                   newpos[ip] += newlen - me->cells[i].len;
+                   pos += newlen - me->cells[i].len;
                } else {
-                   newpos[ip] += (newlen - me->cells[i].len) / 2;
+                   pos += (newlen - me->cells[i].len) / 2;
                }
            }
        }
+       if (unsplit && !me->cells[i].pos && me->cells[i].len && !did_unsplit) {
+           did_unsplit = 1;
+           if (sumcols[i].pos >= prevline_len) {
+               delta = prevline_len;
+               ip = 0;                         /* Undo changes */
+               *do_unsplit = 1;
+           }
+       }
+       oldpos[ip] = me->cells[i].pos;
+       newpos[ip] = pos - delta;
        ip++;
        i = next_i;
     }
@@ -2115,11 +2146,13 @@ PRIVATE int get_fixup_positions ARGS4(
  *           0 or greater (number of oldpos/newpos pairs) if we have
  *             a table row.
  */
-PUBLIC int Stbl_getFixupPositions ARGS4(
+PUBLIC int Stbl_getFixupPositions ARGS6(
     STable_info *,     me,
     int,               lineno,
     int *,             oldpos,
-    int *,             newpos)
+    int *,             newpos,
+    int,               prevline_len,
+    int *,             do_unsplit)
 {
     STable_rowinfo * row;
     int j;
@@ -2137,7 +2170,7 @@ PUBLIC int Stbl_getFixupPositions ARGS4(
        if (row->Line == lineno) {
            prev_row = j;
            ninserts = get_fixup_positions(row, oldpos, newpos,
-                                          me->sumcols);
+                                          me->sumcols, prevline_len, 
do_unsplit);
            break;
        }
     }
--- ./src/GridText.c--pre       Fri May  9 23:33:56 2003
+++ ./src/GridText.c    Sat May 10 16:11:02 2003
@@ -2689,6 +2689,141 @@ PRIVATE HTStyleChange * skip_matched_and
 }
 #endif /* USE_COLOR_STYLE */
 
+PRIVATE HTLine * line2pool ARGS2(
+       HText *,        text,
+       HTLine *,       previous)
+{
+    HTLine* temp;
+
+    POOLallocHTLine(temp, previous->size);
+    if (!temp)
+       outofmem(__FILE__, "split_line_2");
+    memcpy(temp, previous, LINE_SIZE(previous->size));
+#if defined(USE_COLOR_STYLE)
+    POOLallocstyles(temp->styles, previous->numstyles);
+    if (!temp->styles)
+       outofmem(__FILE__, "split_line_2");
+    memcpy(temp->styles, previous->styles, 
sizeof(HTStyleChange)*previous->numstyles);
+#endif
+    return temp;
+}
+
+
+/* Probably a flavor which does not add space is needed too... */
+PUBLIC BOOLEAN unsplit_line ARGS3(
+       HText *,        text,
+       HTLine *,       line,
+       int,            insert)
+{      /* Reverts the effects of split_line(): merges the line with
+          the preceding line, separating them by space (without
+          styles).  Follows the logic of split_line() backwards; 
+          some information on the styles of whitespace may be lost by
+          a split_line()/unsplit_line() pair, as well as
+          HT_NON_BREAK_SPACE vs ' '. */
+    HTLine * previous = line->prev;
+    int SpecialAttrChars = 0, i;
+    HTLine * last = text->last_line;
+    HTLine * tmpline;
+    TextAnchor * a;
+
+    if (text->Lines < 2)
+       return FALSE;
+
+    if (previous->size + insert + line->size >= MAX_LINE)
+       return FALSE;
+
+    /* Relocate previous to the scratch space */
+    if (last == TEMP_LINE(text, 0))
+       tmpline = TEMP_LINE(text, 1);
+    else
+       tmpline = TEMP_LINE(text, 0);
+    if (tmpline == NULL)
+       return FALSE;
+    memcpy(tmpline, previous, LINE_SIZE(previous->size));
+#if defined(USE_COLOR_STYLE)
+    if (previous->numstyles + line->numstyles > MAX_STYLES_ON_LINE)
+       return FALSE;
+    if (last->styles == stylechanges_buffers[0])
+       tmpline->styles = stylechanges_buffers[1];
+    else
+       tmpline->styles = stylechanges_buffers[0];
+
+    memcpy(tmpline->styles, previous->styles, 
sizeof(HTStyleChange)*previous->numstyles);
+#endif
+
+    /* Append the separating space */
+    while (insert--)
+       tmpline->data[tmpline->size++] = ' ';
+    /* And the characters */
+    strcpy(tmpline->data + tmpline->size, line->data);
+
+    /* We do not unjustify yet... */
+    /* Move anchors back to the previous line */
+    if (text->first_anchor) {
+       HTLine *before = FirstHTLine(text);
+       int n = 0;                      /* The first line is 0 */
+
+       while (before != previous) {
+           before = before->next;
+           n++;
+       }
+       a = text->last_anchor_before_split;
+       if (a->line_num > n)
+           a = text->first_anchor;
+       while (a && a->line_num <= n)   /* Over anchors before line */
+           a = a->next;
+       if (a)                          /* optimize for further unsplit()s */
+           text->last_anchor_before_split = a;
+       while (a && a->line_num <= n + 1) { /* Over anchors in `line' */
+           a->line_pos += tmpline->size;
+           a->line_num--;
+           a = a->next;
+       }
+       while (a) {                     /* Over anchors after `line' */
+           a->line_num--;
+           a = a->next;
+       }
+    }
+    text->in_line_1 = previous == previous->next->next;        /* unless 
caller sets it otherwise */
+#if 0
+    /* Un-align */
+    tmpline->offset = 0;       /* it was determined during split_line() */
+#endif
+    /* We do not need to count SpecialAttrChars since we copy them anyway */
+#if 0
+    while (line->data[SpecialAttrChars] == LY_UNDERLINE_START_CHAR
+          || line->data[SpecialAttrChars] == LY_BOLD_START_CHAR
+          || line->data[SpecialAttrChars] == LY_SOFT_NEWLINE)
+       SpecialAttrChars++;
+#endif
+    
+#if defined(USE_COLOR_STYLE)
+    /* Relocate the styles.  We do not need to care about
+       cancellation because of the intervening style-less space */
+    memcpy(tmpline->styles + tmpline->numstyles, line->styles,
+          line->numstyles * sizeof(*(line->styles)));
+    for (i = 0; i < line->numstyles; i++) {
+       tmpline->styles[i + tmpline->numstyles].horizpos += tmpline->size;
+    }
+    tmpline->numstyles += line->numstyles;
+#endif
+    tmpline->size += line->size;
+
+    if (line == last) {
+       text->last_line = tmpline;
+    } else {
+       tmpline = line2pool(text, tmpline);
+       tmpline->prev->next = tmpline;  /* Link in new line */
+       tmpline->next->prev = tmpline;  /* Could be same node of course */
+    }
+
+    /* Remove line (works even if tmpline->next->next == tmpline) */
+    tmpline->next = tmpline->next->next;
+    tmpline->next->prev = tmpline;
+    text->Lines--;
+    return TRUE;
+}
+
 PRIVATE void split_line ARGS2(
        HText *,        text,
        unsigned,       split)
@@ -2997,21 +3132,7 @@ PRIVATE void split_line ARGS2(
     }
 #endif /*USE_COLOR_STYLE*/
 
-    {
-    HTLine* temp;
-    POOLallocHTLine(temp, previous->size);
-    if (!temp)
-       outofmem(__FILE__, "split_line_2");
-    memcpy(temp, previous, LINE_SIZE(previous->size));
-#if defined(USE_COLOR_STYLE)
-    POOLallocstyles(temp->styles, previous->numstyles);
-    if (!temp->styles)
-       outofmem(__FILE__, "split_line_2");
-    memcpy(temp->styles, previous->styles, 
sizeof(HTStyleChange)*previous->numstyles);
-#endif
-    previous = temp;
-    }
-
+    previous = line2pool(text, previous);
     previous->prev->next = previous;   /* Link in new line */
     previous->next->prev = previous;   /* Could be same node of course */
 
@@ -4468,12 +4589,14 @@ PUBLIC void HText_setIgnoreExcess ARGS2(
  *  does additional updating of anchor positions, and makes sure the
  *  display of the lines on screen will be updated after partial display
  *  upon return to mainloop. - kw
+ *
+ *  May also merge lines after a split (required by offset-algorithm).
  */
 PRIVATE int HText_insertBlanksInStblLines ARGS2(
     HText *,           me,
     int,               ncols)
 {
-    HTLine *line;
+    HTLine *line, *nextline;
     HTLine *mod_line, *first_line = NULL;
     int *      oldpos;
     int *      newpos;
@@ -4487,7 +4610,7 @@ PRIVATE int HText_insertBlanksInStblLine
     int max_width = 0, indent, spare, table_offset;
     HTStyle *style;
     short alignment;
-    int i = 0;
+    int i = 0, prevline_len = -1, do_unsplit, deleted = 0;
 
     lineno = first_lineno = Stbl_getStartLine(me->stbl);
     if (lineno < 0 || lineno > me->Lines)
@@ -4507,8 +4630,12 @@ PRIVATE int HText_insertBlanksInStblLine
        }
     }
     first_lineno_pass2 = last_lineno = me->Lines;
-    for (; line && lineno <= last_lineno; line = line->next, lineno++) {
-       ninserts = Stbl_getFixupPositions(me->stbl, lineno, oldpos, newpos);
+    /* The lineno of this loop runs over line numbers *before* unsplitting,
+       those which are wired into TRST structures */
+    for (; line && lineno <= last_lineno; line = nextline, lineno++) {
+       nextline = line->next;
+       ninserts = Stbl_getFixupPositions(me->stbl, lineno, oldpos, newpos,
+                                         prevline_len, &do_unsplit);
        if (ninserts < 0)
            continue;
        if (!first_line) {
@@ -4549,6 +4676,7 @@ PRIVATE int HText_insertBlanksInStblLine
 #endif
            CTRACE((tfp, "line %d true/max width:%d/%d oldpos: NONE\n",
                   lineno, width, max_width));
+           prevline_len = width;
            continue;
        }
        mod_line = insert_blanks_in_line(line, lineno, me,
@@ -4581,6 +4709,15 @@ PRIVATE int HText_insertBlanksInStblLine
            }
 #endif
        }
+       if (do_unsplit && unsplit_line(me, line, 0)) {
+           deleted++;
+           /* Only one line is left is a special case */
+           if (me->last_line == me->last_line->next)
+               nextline = me->last_line;
+           if (line == first_line->next)
+               first_line = nextline->prev;
+           line = nextline->prev;
+       }
        {
            int width = HText_TrueLineSize(line, me, FALSE);
            if (width > max_width)
@@ -4599,6 +4736,7 @@ PRIVATE int HText_insertBlanksInStblLine
                    CTRACE((tfp, " %d", oldpos[ip]));
                CTRACE((tfp, "\n"));
            }
+           prevline_len = width;
        }
     }
     /*
@@ -4670,11 +4808,12 @@ PRIVATE int HText_insertBlanksInStblLine
     } /* switch */
 
     CTRACE((tfp, "changing offsets"));
+    prevline_len = -1;
+    last_lineno -= deleted;
     for (line = first_line, lineno = first_lineno_pass2;
         line && lineno <= last_lineno && line != me->last_line;
         line = line->next, lineno++) {
-       ninserts = Stbl_getFixupPositions(me->stbl, lineno, oldpos, newpos);
-       if (ninserts >= 0 && (int) line->offset != table_offset) {
+       if ((int) line->offset != table_offset) {
 #ifdef DISP_PARTIAL
            /*  As above make sure modified lines get fully re-displayed */
            if (me->first_lineno_last_disp_partial >= 0) {
@@ -4693,7 +4832,7 @@ PRIVATE int HText_insertBlanksInStblLine
 #ifdef EXP_NESTED_TABLES
     if (nested_tables) {
        if (max_width)
-           Stbl_update_enclosing(me->stbl, max_width, last_nonempty);
+           Stbl_update_enclosing(me->stbl, max_width, last_nonempty - deleted);
     }
 #endif
     CTRACE((tfp, " %d:done\n", lineno));

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

reply via email to

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