diff --git a/winio.c b/winio.c index 3cb92f8427a0e23dcd70191065563a7679b9811c..bbf6d5a12f7d09f1e8fdb84e5858a48d58993373 100644 --- a/winio.c +++ b/winio.c @@ -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) } } -#ifndef NANO_SMALL -void add_marked_sameline(int begin, int end, filestruct * fileptr, int y) -{ - int col, actual_col = 0, begin_mapped = 0, end_mapped = 0; +inline int get_page_from_virtual(int virtual) { + int page = 2; - 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; + if(virtual <= COLS - 2) return 1; + virtual -= (COLS - 2); + + while (virtual > COLS - 2 - 7) { + virtual -= (COLS - 2 - 7); + page++; } - 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)); + 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 +/* 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) +{ + /* where we are on the line */ + int virtual_col = xplustabs(); + + /* 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; } + + /* 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)