aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pw.153
-rw-r--r--pw.c109
2 files changed, 148 insertions, 14 deletions
diff --git a/pw.1 b/pw.1
index ac08c25..f4b3f21 100644
--- a/pw.1
+++ b/pw.1
@@ -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
diff --git a/pw.c b/pw.c
index cb3e2be..9daaf5e 100644
--- a/pw.c
+++ b/pw.c
@@ -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;