diff options
-rw-r--r-- | miscutils/less.c | 137 |
1 files changed, 136 insertions, 1 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index 049814319..c66788007 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -28,6 +28,9 @@ #include "xregex.h" #endif +/* In progress */ +#define ENABLE_FEATURE_LESS_REWRAP 0 + /* FIXME: currently doesn't work right */ #undef ENABLE_FEATURE_LESS_FLAGCS #define ENABLE_FEATURE_LESS_FLAGCS 0 @@ -81,6 +84,7 @@ enum { FLAG_TILDE = 1 << 4, FLAG_I = 1 << 5, /* hijack command line options variable for internal state vars */ + LESS_STATE_NO_WRAP = 1 << 14, LESS_STATE_MATCH_BACKWARDS = 1 << 15, }; @@ -214,6 +218,88 @@ static void less_exit(int code) exit(code); } +#if ENABLE_FEATURE_LESS_REWRAP +static void re_wrap(void) +{ + int w = width; + int rem; + int src_idx; + int dst_idx; + int new_cur_fline = 0; + uint32_t lineno; + char linebuf[w + 1]; + const char **old_flines = flines; + const char *s; + char **new_flines = NULL; + char *d; + + if (option_mask32 & FLAG_N) + w -= 8; + + src_idx = 0; + dst_idx = 0; + s = old_flines[0]; + lineno = LINENO(s); + d = linebuf; + rem = w; + while (1) { + *d = *s; + if (*d != '\0') { + s++; + d++; + rem--; + if (rem == 0) { + int sz; + /* new line is full, create next one */ + *d = '\0'; + next_new: + sz = (d - linebuf) + 1; /* + 1: NUL */ + d = ((char*)xmalloc(sz + 4)) + 4; + LINENO(d) = lineno; + memcpy(d, linebuf, sz); + new_flines = xrealloc_vector(new_flines, 8, dst_idx); + new_flines[dst_idx] = d; + dst_idx++; + if (rem) { + /* did we come here thru "goto next_new"? */ + if (src_idx > max_fline) + break; + lineno = LINENO(s); + } + d = linebuf; + rem = w; + } + continue; + } + /* *d == NUL: old line ended, go to next old one */ + free(MEMPTR(old_flines[src_idx])); + /* btw, convert cur_fline... */ + if (cur_fline == src_idx) { + new_cur_fline = dst_idx; + } + src_idx++; + /* no more lines? finish last new line (and exit the loop) */ + if (src_idx > max_fline) { + goto next_new; + } + s = old_flines[src_idx]; + if (lineno != LINENO(s)) { + /* this is not a continuation line! + * create next _new_ line too */ + goto next_new; + } + } + + free(old_flines); + flines = (const char **)new_flines; + + max_fline = dst_idx - 1; + linepos = 0; // XXX + cur_fline = new_cur_fline; + /* max_lineno is screen-size independent */ +} +#endif + #if ENABLE_FEATURE_LESS_REGEXP static void fill_match_lines(unsigned pos); #else @@ -502,7 +588,7 @@ static void lineno_str(char *nbuf9, const char *line) } /* Width of 7 preserves tab spacing in the text */ fmt = "%7u "; - n = LINENO(line); + n = LINENO(line) + 1; if (n > 9999999) { n %= 10000000; fmt = "%07u "; @@ -633,6 +719,35 @@ static void buffer_print(void) status_print(); } +#if ENABLE_FEATURE_LESS_REWRAP +static void buffer_fill_and_print(void) +{ + unsigned i = 0; + int fpos = cur_fline + i; + + if (option_mask32 & LESS_STATE_NO_WRAP) { + /* Go back to the beginning of this line */ + while (fpos && LINENO(flines[fpos]) == LINENO(flines[fpos-1])) + fpos--; + } + + while (i <= max_displayed_line && fpos <= max_fline) { + int lineno = LINENO(flines[fpos]); + buffer[i] = flines[fpos]; + i++; + do { + fpos++; + } while ((fpos <= max_fline) + && (option_mask32 & LESS_STATE_NO_WRAP) + && lineno == LINENO(flines[fpos]) + ); + } + for (; i <= max_displayed_line; i++) { + buffer[i] = empty_line_marker; + } + buffer_print(); +} +#else static void buffer_fill_and_print(void) { unsigned i; @@ -644,6 +759,7 @@ static void buffer_fill_and_print(void) } buffer_print(); } +#endif /* Move the buffer up and down in the file in order to scroll */ static void buffer_down(int nlines) @@ -1371,6 +1487,25 @@ static void keypress_process(int keypress) case ':': colon_process(); break; +#if ENABLE_FEATURE_LESS_REWRAP + case '*': + option_mask32 ^= FLAG_N; + get_terminal_width_height(kbd_fd, &width, &max_displayed_line); + if (width < 20) /* 20: two tabstops + 4 */ + width = 20; + if (max_displayed_line < 3) + max_displayed_line = 3; + max_displayed_line -= 2; + free(buffer); + buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); + re_wrap(); + buffer_fill_and_print(); + break; + case '&': + option_mask32 ^= LESS_STATE_NO_WRAP; + buffer_fill_and_print(); + break; +#endif } if (isdigit(keypress)) |