2 * view.c -- a silly little viewer program
4 * written by Eric S. Raymond <esr@snark.thyrsus.com> December 1994
5 * to test the scrolling code in ncurses.
7 * modified by Thomas Dickey <dickey@clark.net> July 1995 to demonstrate
8 * the use of 'resizeterm()'.
10 * Takes a filename argument. It's a simple file-viewer with various
11 * scroll-up and scroll-down commands.
13 * n -- scroll one line forward
14 * p -- scroll one line back
16 * Either command accepts a numeric prefix interpreted as a repeat count.
17 * Thus, typing `5n' should scroll forward 5 lines in the file.
19 * The way you can tell this is working OK is that, in the trace file,
20 * there should be one scroll operation plus a small number of line
21 * updates, as opposed to a whole-page update. This means the physical
22 * scroll operation worked, and the refresh() code only had to do a
25 * $Id: view.c,v 1.27 1998/08/22 18:33:41 tom Exp $
28 #include <test.priv.h>
40 #if !defined(sun) || !HAVE_TERMIOS_H
42 # include <sys/ioctl.h>
46 /* This is needed to compile 'struct winsize' */
48 #include <sys/stream.h>
52 static RETSIGTYPE finish(int sig) GCC_NORETURN;
53 static void show_all(void);
55 #if defined(SIGWINCH) && defined(TIOCGWINSZ) && defined(NCURSES_VERSION)
62 static RETSIGTYPE adjust(int sig);
63 static int interrupted;
74 #define strdup my_strdup
75 static char *strdup (char *s)
79 p = malloc(strlen(s)+1);
84 #endif /* not HAVE_STRDUP */
86 static void usage(void)
88 static const char *msg[] = {
89 "Usage: view [options] file"
92 ," -n NUM specify maximum number of lines (default 1000)"
93 #if defined(KEY_RESIZE)
94 ," -r use experimental KEY_RESIZE rather than our own handler"
97 ," -t trace screen updates"
98 ," -T NUM specify trace mask"
102 for (n = 0; n < SIZEOF(msg); n++)
103 fprintf(stderr, "%s\n", msg[n]);
107 int main(int argc, char *argv[])
117 bool use_resize = TRUE;
120 while ((i = getopt(argc, argv, "n:rtT:")) != EOF) {
123 if ((MAXLINES = atoi(optarg)) < 1)
143 if (optind + 1 != argc)
146 if ((lines = (char **)calloc(MAXLINES+2, sizeof(*lines))) == 0)
149 fname = argv[optind];
150 if ((fp = fopen(fname, "r")) == 0) {
155 (void) signal(SIGINT, finish); /* arrange interrupts to terminate */
158 (void) signal(SIGWINCH, adjust); /* arrange interrupts to resize */
162 for (lptr = &lines[0]; (lptr - lines) < MAXLINES; lptr++) {
163 char temp[BUFSIZ], *s, *d;
166 if (fgets(buf, sizeof(buf), fp) == 0)
169 /* convert tabs so that shift will work properly */
170 for (s = buf, d = temp, col = 0; (*d = *s) != '\0'; s++) {
174 } else if (*d == '\t') {
176 while ((d-temp) != col)
178 } else if (isprint(*d)) {
182 sprintf(d, "\\%03o", *s & 0xff);
187 *lptr = strdup(temp);
190 length = lptr - lines;
192 (void) initscr(); /* initialize the curses library */
193 keypad(stdscr, TRUE); /* enable keyboard mapping */
194 (void) nonl(); /* tell curses not to do NL->CR/NL on output */
195 (void) cbreak(); /* take input chars one at a time, no wait for \n */
196 (void) noecho(); /* don't echo input */
197 idlok(stdscr, TRUE); /* allow use of insert/delete line */
216 if ((c < 127) && isdigit(c)) {
218 mvprintw(0,0, "Count: ");
222 n = 10 * n + (c - '0');
228 if (!got_number && n == 0)
235 for (i = 0; i < n; i++)
236 if ((lptr - lines) < (length - LINES + 1))
240 wscrl(stdscr, lptr - olptr);
246 for (i = 0; i < n; i++)
251 wscrl(stdscr, lptr - olptr);
262 lptr = lines + length - LINES + 1;
285 case KEY_RESIZE: /* ignore this; ncurses will repaint */
297 finish(0); /* we're done */
300 static RETSIGTYPE finish(int sig)
303 exit(sig != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
308 * This uses functions that are "unsafe", but it seems to work on SunOS and
309 * Linux. The 'wrefresh(curscr)' is needed to force the refresh to start from
310 * the top of the screen -- some xterms mangle the bitmap while resizing.
312 static RETSIGTYPE adjust(int sig)
314 if (waiting || sig == 0) {
317 if (ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0) {
318 resizeterm(size.ws_row, size.ws_col);
319 wrefresh(curscr); /* Linux needs this */
326 (void) signal(SIGWINCH, adjust); /* some systems need this */
328 #endif /* CAN_RESIZE */
330 static void show_all(void)
337 sprintf(temp, "(%3dx%3d) col %d ", LINES, COLS, shift);
339 sprintf(temp+i, "view %.*s", (int)(sizeof(temp)-7-i), fname);
341 sprintf(temp, "view %.*s", (int)sizeof(temp)-7, fname);
344 printw("%.*s", COLS, temp);
347 scrollok(stdscr, FALSE); /* prevent screen from moving */
348 for (i = 1; i < LINES; i++) {
350 if ((s = lptr[i-1]) != 0 && (int)strlen(s) > shift)
351 printw("%3ld:%.*s", (long) (lptr+i-lines), COLS-4, s + shift);
353 printw("%3ld:", (long) (lptr+i-lines));
356 setscrreg(1, LINES-1);
357 scrollok(stdscr, TRUE);
361 /* view.c ends here */