diff options
-rw-r--r-- | pw.1 | 53 | ||||
-rw-r--r-- | pw.c | 109 |
2 files changed, 148 insertions, 14 deletions
@@ -153,11 +153,19 @@ count greater than 1 is in effect. (See the .B -q option). -.IP "\fBl\fP, \fILeft Arrow\fP" -Scroll the display to the left. +.IP "[\fIcount\fP]\fBl\fP, [\fIcount\fP]\fILeft Arrow\fP" +Scroll the display to the left by +.I count +characters, defaulting to 8 if +.I count +is absent. -.IP "\fBh\fP, \fIRight Arrow\fP" -Scroll the display to the right. +.IP "[\fIcount\fP]\fBh\fP, [\fIcount\fP]\fIRight Arrow\fP" +Scroll the display to the right by +.I count +characters, defaulting to 8 if +.I count +is absent. .IP "\fB0\fP, \fIHome\fP" Reset scroll to first column. @@ -165,6 +173,43 @@ Reset scroll to first column. .IP \fBCtrl-L\fP Refresh the display. +.IP "\fB[, ]\fP" +Adjust the left vertical split, separating the left pane of the display. The +left pane is an area of the display which always shows the prefix of each line, +protected from horizontal scrolling. If the line is longer than the prefix, +then either the +.B > +character appears to separate the left pane from the right pane, +where the horizontally scrolling portion of remainder of the line appears, +or else the +.B | +character appears to separate the left pane from the middle pane. +The left pane has a zero width by default, so that it does not appear. +These commands decrease and increase its width by one character. + +.IP "\fB<, >\fP" +Adjust the right vertical split, separating the middle pane of the display +from the right pane. The middle pane is an area of the +display which always shows some middle portion of each line, protected +from horizontal scrolling. It may appear together with the left split (see the +.B [ +and +.B ] +commands) or by itself. The +.B > +character separates the middle pane from the right pane. + +The middle pane has a zero width by default, so that +it does not appear. These commands decrease and increase the width by one +character. Which portion of each line is shown in the middle pane is determined +each time the middle pane is increased from zero width to nonzero: +in other words, when the middle pane is changed from its hidden state to +visible. At that moment, the current horizontal scroll position, together +with the size of the left pane, determines the part of the line which is +assigned to the middle pane. After that, the width of the pane can be +adjusted without affecting what portion of the line it shows, independently +of any horizontal scrolling adjustments occurring in the right pane. + .IP \fISpace\fP Suspend the acquisition of new snapshots. In suspended mode, input continues to pass through the FIFO, but new snapshots of data aren't @@ -83,6 +83,7 @@ typedef struct pwstate { char **circbuf; int nlines; unsigned hpos; + unsigned vsplit1, vsplit2, vs2pos; unsigned hist; int columns; unsigned stat; @@ -338,16 +339,65 @@ static void clreol(int nl) static void drawline(pwstate *pw, const char *line, int lineno) { + const char *oline = line; size_t len = dslen(line); int columns = pw->columns; + unsigned vsplit1 = pw->vsplit1; + unsigned vsplit2 = pw->vsplit2; + unsigned vs2pos = pw->vs2pos; + int endmark = 0; if (lineno >= 0) columns -= printf("%3d ", lineno); - if ((size_t) pw->hpos <= len) { - if (pw->hpos) { - line += pw->hpos; - len -= pw->hpos; + if (vsplit1 > 0) { + if (len <= vsplit1) { + fputs(line, stdout); + columns -= len; + len = 0; + } else { + for (unsigned i = 0; i < vsplit1; i++) + putchar(line[i]); + len -= vsplit1; + line += vsplit1; + columns -= vsplit1; + endmark = 1; + } + } + + if (vsplit2 > 0) { + unsigned pos = line - oline; + unsigned delta = vs2pos - pos; + if (pos + len <= vs2pos) { + len = 0; + } else if (len - delta <= vsplit2) { + if (vsplit1) { + putchar('|'); + delta++; + } + fputs(line + delta, stdout); + columns -= len; + len = 0; + endmark = 0; + } else { + unsigned start = 0; + if (vsplit1) { + putchar('|'); + start++; + } + for (unsigned i = start; i < vsplit2; i++) + putchar(line[delta + i]); + line += vsplit2; + len -= vsplit2; + columns -= vsplit2; + endmark = 1; + } + } + + if ((size_t) pw->hpos + 1 <= len) { + if (pw->hpos || vsplit1 || vsplit2) { + line += pw->hpos + 1; + len -= pw->hpos + 1; putchar('>'); columns--; } @@ -360,7 +410,8 @@ static void drawline(pwstate *pw, const char *line, int lineno) puts("<"); } } else { - putchar('>'); + if (endmark) + putchar('>'); clreol(1); } } @@ -1097,14 +1148,52 @@ int main(int argc, char **argv) } break; case 'h': - if (pw.hpos >= 8) { - pw.hpos -= 8; + if (cmdcount == UINT_MAX) + cmdcount = 8; + if (pw.hpos >= cmdcount) + pw.hpos -= cmdcount; + else + pw.hpos = 0; + pw.stat |= stat_force; + break; + case 'l': + if (cmdcount == UINT_MAX) + cmdcount = 8; + if (pw.hpos < 10000) + pw.hpos += cmdcount; + pw.stat |= stat_force; + break; + case ']': + if ((int) pw.vsplit1 < pw.columns - 2) { + pw.vsplit1++; + if (pw.vsplit2 > 0) { + pw.vsplit2--; + pw.vs2pos++; + } pw.stat |= stat_force; } break; - case 'l': - if (pw.hpos < 10000) { - pw.hpos += 8; + case '[': + if (pw.vsplit1 > 0) { + pw.vsplit1--; + if (pw.vsplit2 > 0) { + pw.vsplit2++; + pw.vs2pos--; + } + pw.stat |= stat_force; + } + break; + case '>': + if ((int) (pw.vsplit1 + pw.vsplit2) < pw.columns - 2) { + if (pw.vsplit2 == 0) + pw.vs2pos = pw.hpos + pw.vsplit1; + pw.vsplit2++; + pw.stat |= stat_force; + } + break; + case '<': + if (pw.vsplit2 > 0) { + pw.vsplit2--; pw.stat |= stat_force; } break; |