Substantial changes to winio.c that appear to fix the display problems

that we have been seeing on lines with tabs.

It introduces the concept of "pages" which might not be the best choice
for them.... Basically, it's the part of a line that would be visible on
screen at once.  the first part (visible when you open a file) is page
1... the second (you have to scroll to the right approx COLS, is 2.  The
third is at approx (2 * COLS) - 7 and so on...)

It's not terribly efficient as of yet, there are probabally quite a few
redundant calls to xpt(), for instance.


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@6 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
Robert Siemborski 2000-06-06 23:04:06 +00:00
parent a2ea193bd4
commit d8510b2732
1 changed files with 154 additions and 97 deletions

251
winio.c
View File

@ -34,6 +34,12 @@
static int statblank = 0; /* Number of keystrokes left after
we call statubar() before we
actually blank the statusbar */
/* Local Function Prototypes for only winio.c */
inline int get_page_from_virtual(int virtual);
inline int get_page_start_virtual(int page);
inline int get_page_end_virtual(int page);
/* Window I/O */
int do_first_line(void)
@ -88,34 +94,34 @@ int xplustabs(void)
}
/* Return what current_x should be, given xplustabs() for the line.
Opposite of xplustabs */
int actual_x(filestruct * fileptr, int xplus)
/* Return what current_x should be, given xplustabs() for the line,
* given a start position in the filestruct's data */
int actual_x_from_start(filestruct * fileptr, int xplus, int start)
{
int i, tot = 0;
int i, tot = 1;
if (fileptr == NULL || fileptr->data == NULL)
return 0;
for (i = 1; i + tot <= xplus && fileptr->data[i - 1] != 0; i++)
if (fileptr->data[i - 1] == NANO_CONTROL_I) {
if ((i + tot) % 8 == 0)
tot++;
else
tot += 8 - ((i + tot) % 8);
} else if (fileptr->data[i - 1] & 0x80)
tot ++; /* Make 8 bit chars only 1 column (again) */
else if (fileptr->data[i - 1] < 32)
for (i = start; tot <= xplus && fileptr->data[i] != 0; i++,tot++)
if (fileptr->data[i] == NANO_CONTROL_I) {
if (tot % 8 == 0) tot++;
else tot += 8 - (tot % 8);
} else if (fileptr->data[i] & 0x80)
tot++; /* Make 8 bit chars only 1 column (again) */
else if (fileptr->data[i] < 32)
tot += 2;
if (fileptr->data[i - 1] != 0)
i--; /* Im sure there's a good reason why this is needed for
it to work, I just cant figure out why =-) */
#ifdef DEBUG
fprintf(stderr, _("actual_x for xplus=%d returned %d\n"), xplus, i);
#endif
return i;
return i - start;
}
/* Opposite of xplustabs */
inline int actual_x(filestruct * fileptr, int xplus)
{
return actual_x_from_start(fileptr, xplus, 0);
}
/* a strlen with tabs factored in, similar to xplustabs() */
@ -160,9 +166,10 @@ void reset_cursor(void)
x = xplustabs();
if (x <= COLS - 2)
wmove(edit, current_y, x % (COLS - 1));
wmove(edit, current_y, x);
else
wmove(edit, current_y, x % (COLS - 7) + 1);
wmove(edit, current_y, x -
get_page_start_virtual(get_page_from_virtual(xplustabs())));
}
@ -517,43 +524,93 @@ void set_modified(void)
}
}
inline int get_page_from_virtual(int virtual) {
int page = 2;
if(virtual <= COLS - 2) return 1;
virtual -= (COLS - 2);
while (virtual > COLS - 2 - 7) {
virtual -= (COLS - 2 - 7);
page++;
}
return page;
}
inline int get_page_start_virtual(int page) {
int virtual;
virtual = --page * (COLS - 7);
if(page) virtual -= 2 * page - 1;
return virtual;
}
inline int get_page_end_virtual(int page) {
return get_page_start_virtual(page) + COLS - 1;
}
#ifndef NANO_SMALL
void add_marked_sameline(int begin, int end, filestruct * fileptr, int y)
/* begin, end: beginning and end of mark in data
* fileptr: the data
* y: the line on screen */
void add_marked_sameline(int begin, int end, filestruct *fileptr, int y)
{
int col, actual_col = 0, begin_mapped = 0, end_mapped = 0;
/* where we are on the line */
int virtual_col = xplustabs();
if (current_x > COLS - 2) {
col = (COLS - 7) * (xplustabs() / (COLS - 7)) - 1;
actual_col = actual_x(fileptr, col);
begin_mapped = begin % (COLS - 7) + 1;
end_mapped = end % (COLS - 7) + 1;
} else {
actual_col = 0;
begin_mapped = begin;
end_mapped = end;
/* actual_col is beginning of the line in the data */
int this_page = get_page_from_virtual(virtual_col),
this_page_start = get_page_start_virtual(this_page),
this_page_end = get_page_end_virtual(this_page),
actual_col = actual_x(fileptr, this_page_start);
/* 3 start points: 0 -> begin, begin->end, end->strlen(data) */
/* in data : pre sel post */
int virtual_sel_start = xpt(fileptr, begin),
sel_start = 0,
virtual_post_start = xpt(fileptr, end),
post_start = 0;
/* likewise, 3 data lengths */
int pre_data_len = begin,
sel_data_len = end - begin,
post_data_len = 0;
/* now fix the start locations & lengths according to the cursor's
* position (ie: our page) */
if(xpt(fileptr,pre_data_len) < this_page_start) pre_data_len = 0;
else pre_data_len -= actual_col;
if(virtual_sel_start < this_page_start) {
begin = actual_col;
virtual_sel_start = this_page_start;
}
if(virtual_post_start < this_page_start) {
end = actual_col;
virtual_post_start = this_page_start;
}
if (end > (COLS - 2) && ((begin / (COLS - 7)) != (end / (COLS - 7)))) {
if (current_x == begin) {
mvwaddnstr(edit, y, 0, &fileptr->data[actual_col],
begin_mapped);
wattron(edit, A_REVERSE);
waddnstr(edit, &fileptr->data[begin], COLS - begin_mapped);
wattroff(edit, A_REVERSE);
} else {
wattron(edit, A_REVERSE);
mvwaddnstr(edit, y, 0, &fileptr->data[actual_col], end_mapped);
wattroff(edit, A_REVERSE);
waddnstr(edit, &fileptr->data[end], COLS - end_mapped);
}
} else {
mvwaddnstr(edit, y, 0, &fileptr->data[actual_col], begin_mapped);
wattron(edit, A_REVERSE);
waddnstr(edit, &fileptr->data[begin], end_mapped - begin_mapped);
wattroff(edit, A_REVERSE);
waddnstr(edit, &fileptr->data[end],
COLS - (end_mapped - begin_mapped));
}
/* we don't care about end, because it will just get cropped
* due to length */
if(virtual_sel_start > this_page_end)
virtual_sel_start = this_page_end;
if(virtual_post_start > this_page_end)
virtual_post_start = this_page_end;
sel_data_len = actual_x(fileptr, virtual_post_start) -
actual_x(fileptr, virtual_sel_start);
post_data_len = actual_x(fileptr, this_page_end) -
actual_x(fileptr, virtual_post_start);
sel_start = virtual_sel_start - this_page_start;
post_start = virtual_post_start - this_page_start;
mvwaddnstr(edit, y, 0, &fileptr->data[actual_col], pre_data_len);
wattron(edit, A_REVERSE);
mvwaddnstr(edit, y, sel_start, &fileptr->data[begin], sel_data_len);
wattroff(edit, A_REVERSE);
mvwaddnstr(edit, y, post_start, &fileptr->data[end], post_data_len);
}
#endif
@ -563,69 +620,70 @@ void edit_add(filestruct * fileptr, int yval, int xval, int start)
int col;
if (ISSET(MARK_ISSET)) {
/* Our horribly ugly marker code, which needs to be rewritten too :P */
/* Our horribly ugly marker code */
if ((fileptr->lineno > mark_beginbuf->lineno
&& fileptr->lineno > current->lineno)
|| (fileptr->lineno < mark_beginbuf->lineno
&& fileptr->lineno < current->lineno)) {
/* We're on a normal, unselected line */
mvwaddnstr(edit, yval, 0, fileptr->data, COLS);
if (strlenpt(fileptr->data) > COLS)
mvwaddch(edit, yval, COLS - 1, '$');
mvwaddnstr(edit, yval, 0, fileptr->data,
actual_x(fileptr, COLS));
} else {
/* We're on selected text */
if (fileptr != mark_beginbuf && fileptr != current) {
wattron(edit, A_REVERSE);
mvwaddnstr(edit, yval, 0, fileptr->data, COLS);
if (strlenpt(fileptr->data) > COLS)
mvwaddch(edit, yval, COLS - 1, '$');
mvwaddnstr(edit, yval, 0, fileptr->data, actual_x(fileptr,COLS));
wattroff(edit, A_REVERSE);
}
/* Special case, we're still on the same line we started marking */
else if (fileptr == mark_beginbuf && fileptr == current) {
if (current_x < mark_beginx) {
add_marked_sameline(current_x, mark_beginx, fileptr,
yval);
} else {
add_marked_sameline(mark_beginx, current_x, fileptr,
yval);
}
if (current_x < mark_beginx)
add_marked_sameline(current_x, mark_beginx, fileptr, yval);
else
add_marked_sameline(mark_beginx, current_x, fileptr, yval);
} else if (fileptr == mark_beginbuf) {
int target;
/* we're at the line that was first marked */
if (mark_beginbuf->lineno > current->lineno)
wattron(edit, A_REVERSE);
mvwaddnstr(edit, yval, 0, fileptr->data, mark_beginx);
target = (xpt(fileptr,mark_beginx) < COLS - 1) ? mark_beginx : COLS - 1;
mvwaddnstr(edit, yval, 0, fileptr->data,
actual_x(fileptr, target));
if (mark_beginbuf->lineno < current->lineno)
wattron(edit, A_REVERSE);
else
wattroff(edit, A_REVERSE);
waddnstr(edit, &fileptr->data[mark_beginx],
COLS - xpt(fileptr, mark_beginx));
target = (COLS - 1) - xpt(fileptr,mark_beginx);
if(target < 0) target = 0;
if (strlenpt(fileptr->data) > COLS)
mvwaddch(edit, yval, COLS - 1, '$');
mvwaddnstr(edit, yval, xpt(fileptr,mark_beginx),
&fileptr->data[mark_beginx],
actual_x_from_start(fileptr, target, mark_beginx));
if (mark_beginbuf->lineno < current->lineno)
wattroff(edit, A_REVERSE);
} else if (fileptr == current) {
/* we're on the cursors line, but it's not the first
* one we marked... */
int this_page = get_page_from_virtual(xplustabs()),
this_page_start = get_page_start_virtual(this_page),
this_page_end = get_page_end_virtual(this_page);
if (mark_beginbuf->lineno < current->lineno)
wattron(edit, A_REVERSE);
/* Thank GOD for waddnstr, this can now be much cleaner */
if (xplustabs() > COLS - 2) {
col = (COLS - 7) * (xplustabs() / (COLS - 7));
mvwaddnstr(edit, yval, 1,
&fileptr->data[actual_x(current, col)],
current_x % (COLS - 7) + 1);
col = actual_x(current, this_page_start);
mvwaddnstr(edit, yval, 0, &fileptr->data[col],
current_x - col);
} else
mvwaddnstr(edit, yval, 0, fileptr->data, current_x);
@ -634,20 +692,15 @@ void edit_add(filestruct * fileptr, int yval, int xval, int start)
else
wattroff(edit, A_REVERSE);
if (xplustabs() > COLS - 2) {
mvwaddnstr(edit, yval,
xpt(current,
(current_x % (COLS - 7) + 1)),
mvwaddnstr(edit, yval, xplustabs() - this_page_start,
&fileptr->data[current_x],
COLS - current_x);
actual_x(current,this_page_end) - current_x);
} else
mvwaddnstr(edit, yval, xplustabs(),
&fileptr->data[current_x],
COLS - current_x);
if (strlenpt(fileptr->data) > COLS)
mvwaddch(edit, yval, COLS - 1, '$');
actual_x_from_start(fileptr,
COLS - xpt(fileptr,current_x), current_x));
if (mark_beginbuf->lineno > current->lineno)
wattroff(edit, A_REVERSE);
@ -657,7 +710,8 @@ void edit_add(filestruct * fileptr, int yval, int xval, int start)
} else
#endif
mvwaddnstr(edit, yval, xval, &fileptr->data[start], COLS - xval);
mvwaddnstr(edit, yval, xval, &fileptr->data[start],
actual_x_from_start(fileptr,COLS - xval,start));
}
@ -667,6 +721,7 @@ void edit_add(filestruct * fileptr, int yval, int xval, int start)
* index gives is a place in the string to update starting from.
* Likely args are current_x or 0.
*/
void update_line(filestruct * fileptr, int index)
{
filestruct *filetmp;
@ -679,19 +734,21 @@ void update_line(filestruct * fileptr, int index)
mvwaddstr(edit, line, 0, hblank);
if (current == fileptr && (x = xpt(current, index)) > COLS - 2) {
col = (COLS - 7) * (x / (COLS - 7));
int page = get_page_from_virtual(x);
col = get_page_start_virtual(page);
actual_col = actual_x(filetmp, col);
edit_add(filetmp, line, 1, actual_col);
edit_add(filetmp, line, 0, actual_col);
mvwaddch(edit, line, 0, '$');
} else
if (strlenpt(fileptr->data) > get_page_end_virtual(page))
mvwaddch(edit, line, COLS - 1, '$');
} else {
edit_add(filetmp, line, 0, 0);
if (strlenpt(&filetmp->data[actual_col]) > COLS)
mvwaddch(edit, line, COLS - 1, '$');
if (strlenpt(&filetmp->data[actual_col]) > COLS)
mvwaddch(edit, line, COLS - 1, '$');
}
}
void center_cursor(void)