[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- lynx-dev [PATCH 2.8.5-dev15] Tables in lynx,
Ilya Zakharevich <=