aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/less.c137
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))