From 05417a24443e701bf8831801df5bf40380777c82 Mon Sep 17 00:00:00 2001 From: Chris Allegretta Date: Mon, 17 Aug 2009 07:52:10 +0000 Subject: [PATCH] 2009-08-17 Chris Allegretta * Initial soft line wrapping implementation. Command line flags -$ or --softwrap. * nano.c, text.c: Clean up some fprintf warnings in debug mode due to printing a size_t without using the zd specifier. git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4402 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 5 +++ TODO | 2 +- doc/man/nano.1 | 7 ++++ doc/man/nanorc.5 | 6 ++++ src/global.c | 3 ++ src/nano.c | 28 ++++++++++------ src/nano.h | 1 + src/proto.h | 2 +- src/rcfile.c | 1 + src/text.c | 10 +++--- src/winio.c | 84 +++++++++++++++++++++++++++++++++++++++--------- 11 files changed, 117 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 397b7f13..85925009 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-08-17 Chris Allegretta + * Initial soft line wrapping implementation. Command line flags + -$ or --softwrap. + * nano.c, text.c: Clean up some fprintf warnings in debug mode due to printing + a size_t without using the zd specifier. 2009-08-13 Chris Allegretta * New global flag implementation courtesy of Adam Wysocki , allows previous undo flag to be implemented consistent with other flags. diff --git a/TODO b/TODO index 9fce6e5c..6780d61a 100644 --- a/TODO +++ b/TODO @@ -24,7 +24,6 @@ For the future (no targeted version, catch-all) allow movement between them with a single keystroke? (we're running out of keystrokes) - Allow searching for and replacing newlines. -- Allow soft wrapping as well as hard wrapping? - Fix handling of bad/incomplete UTF-8 sequences to display one Unicode FFFD (Replacement Character) per sequence instead of one per byte. @@ -48,6 +47,7 @@ For version 2.2: - Allow nano to work like a pager (read from stdin) [DONE] - Allow color syntaxes to be selected based on more than just filename extension, [DONE] +- Allow soft wrapping as well as hard wrapping? [DONE] For version 2.0: - UTF-8 support. [DONE] diff --git a/doc/man/nano.1 b/doc/man/nano.1 index 9af89978..e9954e95 100644 --- a/doc/man/nano.1 +++ b/doc/man/nano.1 @@ -205,6 +205,13 @@ Disable help screen at bottom of editor. .B \-z (\-\-suspend) Enable suspend ability. .TP +.B \-$ (\-\-softwrap) +Enable 'soft wrapping'. Nano will attempt to display lines the entire +contents of a line, even if it is longer than the screen width. +Since '$' normally refers to a variable in the Unix shell, you should +specify this option last when using other options (e.g. 'nano -wS$') +or pass it separately (e.g. 'nano -wS -$'). +.TP .B \-a, \-b, \-e, \-f, \-g, \-j Ignored, for compatibility with Pico. diff --git a/doc/man/nanorc.5 b/doc/man/nanorc.5 index 73e7d972..4d56d7ff 100644 --- a/doc/man/nanorc.5 +++ b/doc/man/nanorc.5 @@ -185,6 +185,9 @@ line. .B set/unset smooth Use smooth scrolling by default. .TP +.B set/unset softwrap +Enable soft line wrapping for easier viewing of very long lones. +.TP .B set speller "\fIspellprog\fP" Use spelling checker \fIspellprog\fP instead of the built-in one, which calls \fIspell\fP. @@ -208,6 +211,9 @@ Enable experimental generic-purpose undo code. .B set/unset view Disallow file modification. .TP +.B set/unset softwrap +Enable soft line wrapping for easier viewing of very long lones. +.TP .B set whitespace "\fIstring\fP" Set the two characters used to display the first characters of tabs and spaces. They must be single-column characters. diff --git a/src/global.c b/src/global.c index f6826d7f..dbd42091 100644 --- a/src/global.c +++ b/src/global.c @@ -1164,6 +1164,7 @@ void shortcut_init(bool unjustify) add_to_sclist(MMAIN, "M-M", DO_TOGGLE, USE_MOUSE, TRUE); add_to_sclist(MMAIN, "M-N", DO_TOGGLE, NO_CONVERT, TRUE); add_to_sclist(MMAIN, "M-Z", DO_TOGGLE, SUSPEND, TRUE); + add_to_sclist(MMAIN, "M-$", DO_TOGGLE, SOFTWRAP, TRUE); #endif add_to_sclist(MGOTOLINE, "^T", GOTOTEXT_MSG, 0, FALSE); add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", NEW_BUFFER_MSG, 0, FALSE); @@ -1376,6 +1377,8 @@ char *flagtostr(int flag) return N_("No conversion from DOS/Mac format"); case SUSPEND: return N_("Suspension"); + case SOFTWRAP: + return N_("Soft line wrapping"); default: return "?????"; } diff --git a/src/nano.c b/src/nano.c index 7ef21b17..9d1e011f 100644 --- a/src/nano.c +++ b/src/nano.c @@ -901,6 +901,7 @@ void usage(void) #endif print_opt("-x", "--nohelp", N_("Don't show the two help lines")); print_opt("-z", "--suspend", N_("Enable suspension")); + print_opt("-$", "--softwrap", N_("Enable soft line wrapping")); /* This is a special case. */ print_opt("-a, -b, -e,", "", NULL); @@ -1333,6 +1334,9 @@ void do_toggle(int flag) edit_refresh(); break; #endif + case SOFTWRAP: + total_refresh(); + break; } enabled = ISSET(flag); @@ -1733,7 +1737,7 @@ void precalc_multicolorinfo(void) #ifdef DEBUG - fprintf(stderr, "working on lineno %d\n", fileptr->lineno); + fprintf(stderr, "working on lineno %zd\n", fileptr->lineno); #endif alloc_multidata_if_needed(fileptr); @@ -1766,7 +1770,7 @@ void precalc_multicolorinfo(void) for (endptr = fileptr->next; endptr != NULL; endptr = endptr->next) { #ifdef DEBUG - fprintf(stderr, "advancing to line %d to find end...\n", endptr->lineno); + fprintf(stderr, "advancing to line %zd to find end...\n", endptr->lineno); #endif /* Check for keyboard input again */ if ((cur_check = time(NULL)) - last_check > 1) { @@ -1794,18 +1798,18 @@ void precalc_multicolorinfo(void) lines in between and the ends properly */ fileptr->multidata[tmpcolor->id] |= CENDAFTER; #ifdef DEBUG - fprintf(stderr, "marking line %d as CENDAFTER\n", fileptr->lineno); + fprintf(stderr, "marking line %zd as CENDAFTER\n", fileptr->lineno); #endif for (fileptr = fileptr->next; fileptr != endptr; fileptr = fileptr->next) { alloc_multidata_if_needed(fileptr); fileptr->multidata[tmpcolor->id] = CWHOLELINE; #ifdef DEBUG - fprintf(stderr, "marking intermediary line %d as CWHOLELINE\n", fileptr->lineno); + fprintf(stderr, "marking intermediary line %zd as CWHOLELINE\n", fileptr->lineno); #endif } alloc_multidata_if_needed(endptr); #ifdef DEBUG - fprintf(stderr, "marking line %d as BEGINBEFORE\n", fileptr->lineno); + fprintf(stderr, "marking line %zd as BEGINBEFORE\n", fileptr->lineno); #endif endptr->multidata[tmpcolor->id] |= CBEGINBEFORE; /* We should be able to skip all the way to the line of the match. @@ -1813,12 +1817,12 @@ void precalc_multicolorinfo(void) fileptr = endptr; startx = endmatch.rm_eo; #ifdef DEBUG - fprintf(stderr, "jumping to line %d pos %d to continue\n", endptr->lineno, startx); + fprintf(stderr, "jumping to line %zd pos %d to continue\n", endptr->lineno, startx); #endif } if (nostart && startx == 0) { #ifdef DEBUG - fprintf(stderr, "no start found on line %d, continuing\n", fileptr->lineno); + fprintf(stderr, "no start found on line %zd, continuing\n", fileptr->lineno); #endif fileptr->multidata[tmpcolor->id] = CNONE; continue; @@ -2020,6 +2024,7 @@ int main(int argc, char **argv) {"wordbounds", 0, NULL, 'W'}, {"autoindent", 0, NULL, 'i'}, {"cut", 0, NULL, 'k'}, + {"softwrap", 0, NULL, '$'}, #endif {NULL, 0, NULL, 0} }; @@ -2058,11 +2063,11 @@ int main(int argc, char **argv) while ((optchr = #ifdef HAVE_GETOPT_LONG getopt_long(argc, argv, - "h?ABC:DEFHIKLNOQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz", + "h?ABC:DEFHIKLNOQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz$", long_options, NULL) #else getopt(argc, argv, - "h?ABC:DEFHIKLNOQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz") + "h?ABC:DEFHIKLNOQ:RST:UVWY:abcdefgijklmo:pqr:s:tuvwxz$") #endif ) != -1) { switch (optchr) { @@ -2230,6 +2235,11 @@ int main(int argc, char **argv) case 'z': SET(SUSPEND); break; +#ifndef NANO_TINY + case '$': + SET(SOFTWRAP); + break; +#endif default: usage(); } diff --git a/src/nano.h b/src/nano.h index 9400fe05..e9996a4d 100644 --- a/src/nano.h +++ b/src/nano.h @@ -490,6 +490,7 @@ enum BOLD_TEXT, QUIET, UNDOABLE, + SOFTWRAP, }; /* Flags for which menus in which a given function should be present */ diff --git a/src/proto.h b/src/proto.h index 3e83f1ba..19b3881d 100644 --- a/src/proto.h +++ b/src/proto.h @@ -765,7 +765,7 @@ void onekey(const char *keystroke, const char *desc, size_t len); void reset_cursor(void); void edit_draw(filestruct *fileptr, const char *converted, int line, size_t start); -void update_line(filestruct *fileptr, size_t index); +int update_line(filestruct *fileptr, size_t index); bool need_horizontal_update(size_t pww_save); bool need_vertical_update(size_t pww_save); void edit_scroll(scroll_dir direction, ssize_t nlines); diff --git a/src/rcfile.c b/src/rcfile.c index 60a9f3dd..decae786 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -92,6 +92,7 @@ static const rcoption rcopts[] = { {"undo", 0}, {"whitespace", 0}, {"wordbounds", WORD_BOUNDS}, + {"softwrap", SOFTWRAP}, #endif {NULL, 0} }; diff --git a/src/text.c b/src/text.c index a3683f40..51ad00b2 100644 --- a/src/text.c +++ b/src/text.c @@ -409,7 +409,7 @@ void redo_cut(undo *u) { for (c = u->cutbuffer, t = openfile->current; c->next != NULL && t->next != NULL; ) { #ifdef DEBUG - fprintf(stderr, "Advancing, lineno = %d, data = \"%s\"\n", t->lineno, t->data); + fprintf(stderr, "Advancing, lineno = %zd, data = \"%s\"\n", t->lineno, t->data); #endif c = c->next; t = t->next; @@ -943,7 +943,7 @@ void add_undo(undo_type current_action) } #ifdef DEBUG - fprintf(stderr, "fs->current->data = \"%s\", current_x = %d, u->begin = %d, type = %d\n", + fprintf(stderr, "fs->current->data = \"%s\", current_x = %zd, u->begin = %d, type = %d\n", fs->current->data, fs->current_x, u->begin, current_action); fprintf(stderr, "left add_undo...\n"); #endif @@ -966,10 +966,10 @@ void update_undo(undo_type action) return; #ifdef DEBUG - fprintf(stderr, "action = %d, fs->last_action = %d, openfile->current->lineno = %d", + fprintf(stderr, "action = %d, fs->last_action = %d, openfile->current->lineno = %zd", action, fs->last_action, openfile->current->lineno); if (fs->current_undo) - fprintf(stderr, "fs->current_undo->lineno = %d\n", fs->current_undo->lineno); + fprintf(stderr, "fs->current_undo->lineno = %zd\n", fs->current_undo->lineno); else fprintf(stderr, "\n"); #endif @@ -989,7 +989,7 @@ void update_undo(undo_type action) switch (u->type) { case ADD: #ifdef DEBUG - fprintf(stderr, "fs->current->data = \"%s\", current_x = %d, u->begin = %d\n", + fprintf(stderr, "fs->current->data = \"%s\", current_x = %zd, u->begin = %d\n", fs->current->data, fs->current_x, u->begin); #endif len = strlen(u->strdata) + 2; diff --git a/src/winio.c b/src/winio.c index 759b69e6..6a9be893 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2426,6 +2426,7 @@ void onekey(const char *keystroke, const char *desc, size_t len) * in the edit window at (current_y, current_x). */ void reset_cursor(void) { + size_t xpt; /* If we haven't opened any files yet, put the cursor in the top * left corner of the edit window and get out. */ if (openfile == NULL) { @@ -2433,13 +2434,24 @@ void reset_cursor(void) return; } - openfile->current_y = openfile->current->lineno - - openfile->edittop->lineno; - if (openfile->current_y < editwinrows) { - size_t xpt = xplustabs(); + xpt = xplustabs(); - wmove(edit, openfile->current_y, xpt - get_page_start(xpt)); - } + if (ISSET(SOFTWRAP)) { + openfile->current_y = 0; + filestruct *tmp; + for (tmp = openfile->edittop; tmp != openfile->current; tmp = tmp->next) + openfile->current_y += 1 + strlenpt(tmp->data) / COLS; + + openfile->current_y += xplustabs() / COLS; + if (openfile->current_y < editwinrows) + wmove(edit, openfile->current_y, xpt % COLS); + } else { + openfile->current_y = openfile->current->lineno - + openfile->edittop->lineno; + + if (openfile->current_y < editwinrows) + wmove(edit, openfile->current_y, xpt - get_page_start(xpt)); + } } /* edit_draw() takes care of the job of actually painting a line into @@ -2813,19 +2825,35 @@ void edit_draw(filestruct *fileptr, const char *converted, int /* Just update one line in the edit buffer. This is basically a wrapper * for edit_draw(). The line will be displayed starting with - * fileptr->data[index]. Likely arguments are current_x or zero. */ -void update_line(filestruct *fileptr, size_t index) + * fileptr->data[index]. Likely arguments are current_x or zero. + * Returns: Number of additiona lines consumed (needed for SOFTWRAP) + */ +int update_line(filestruct *fileptr, size_t index) { - int line; + int line = 0; + int extralinesused = 0; /* The line in the edit window that we want to update. */ char *converted; /* fileptr->data converted to have tabs and control characters * expanded. */ size_t page_start; + filestruct *tmp; assert(fileptr != NULL); - line = fileptr->lineno - openfile->edittop->lineno; + if (ISSET(SOFTWRAP)) { + for (tmp = openfile->edittop; tmp != fileptr; tmp = tmp->next) { + line += 1 + (strlenpt(tmp->data) / COLS); +#ifdef DEBUG + fprintf(stderr, "update_line(): inside loop, line = %d\n", line); +#endif + } + } else + line = fileptr->lineno - openfile->edittop->lineno; + +#ifdef DEBUG + fprintf(stderr, "update_line(): line = %d\n", line); +#endif if (line < 0 || line >= editwinrows) return; @@ -2835,7 +2863,10 @@ void update_line(filestruct *fileptr, size_t index) /* Next, convert variables that index the line to their equivalent * positions in the expanded line. */ - index = strnlenpt(fileptr->data, index); + if (ISSET(SOFTWRAP)) + index = 0; + else + index = strnlenpt(fileptr->data, index); page_start = get_page_start(index); /* Expand the line, replacing tabs with spaces, and control @@ -2846,10 +2877,31 @@ void update_line(filestruct *fileptr, size_t index) edit_draw(fileptr, converted, line, page_start); free(converted); - if (page_start > 0) - mvwaddch(edit, line, 0, '$'); - if (strlenpt(fileptr->data) > page_start + COLS) - mvwaddch(edit, line, COLS - 1, '$'); + if (!ISSET(SOFTWRAP)) { + if (page_start > 0) + mvwaddch(edit, line, 0, '$'); + if (strlenpt(fileptr->data) > page_start + COLS) + mvwaddch(edit, line, COLS - 1, '$'); + } else { + int full_length = strlenpt(fileptr->data); + for (index += COLS; index < full_length && line < editwinrows; index += COLS) { + line++; +#ifdef DEBUG + fprintf(stderr, "update_line(): Softwrap code, moving to %d\n", line); +#endif + blank_line(edit, line, 0, COLS); + + /* Expand the line, replacing tabs with spaces, and control + * characters with their displayed forms. */ + converted = display_string(fileptr->data, index, COLS, TRUE); + + /* Paint the line. */ + edit_draw(fileptr, converted, line, index); + free(converted); + extralinesused++; + } + } + return extralinesused; } /* Return TRUE if we need an update after moving horizontally, and FALSE @@ -3115,7 +3167,7 @@ void edit_refresh(void) #endif for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) { - update_line(foo, (foo == openfile->current) ? + nlines += update_line(foo, (foo == openfile->current) ? openfile->current_x : 0); foo = foo->next; } -- 2.39.5