xref: /minix3/lib/libcurses/EXAMPLES/view.c (revision 51ffecc181005cb45a40108612ee28d1daaeeb86)
1*51ffecc1SBen Gras /*
2*51ffecc1SBen Gras  * view.c -- a silly little viewer program
3*51ffecc1SBen Gras  *
4*51ffecc1SBen Gras  * written by Eric S. Raymond <esr@snark.thyrsus.com> December 1994
5*51ffecc1SBen Gras  * to test the scrolling code in ncurses.
6*51ffecc1SBen Gras  *
7*51ffecc1SBen Gras  * modified by Thomas Dickey <dickey@clark.net> July 1995 to demonstrate
8*51ffecc1SBen Gras  * the use of 'resizeterm()', and May 2000 to illustrate wide-character
9*51ffecc1SBen Gras  * handling.
10*51ffecc1SBen Gras  *
11*51ffecc1SBen Gras  * Takes a filename argument.  It's a simple file-viewer with various
12*51ffecc1SBen Gras  * scroll-up and scroll-down commands.
13*51ffecc1SBen Gras  *
14*51ffecc1SBen Gras  * n	-- scroll one line forward
15*51ffecc1SBen Gras  * p	-- scroll one line back
16*51ffecc1SBen Gras  *
17*51ffecc1SBen Gras  * Either command accepts a numeric prefix interpreted as a repeat count.
18*51ffecc1SBen Gras  * Thus, typing `5n' should scroll forward 5 lines in the file.
19*51ffecc1SBen Gras  *
20*51ffecc1SBen Gras  * The way you can tell this is working OK is that, in the trace file,
21*51ffecc1SBen Gras  * there should be one scroll operation plus a small number of line
22*51ffecc1SBen Gras  * updates, as opposed to a whole-page update.  This means the physical
23*51ffecc1SBen Gras  * scroll operation worked, and the refresh() code only had to do a
24*51ffecc1SBen Gras  * partial repaint.
25*51ffecc1SBen Gras  *
26*51ffecc1SBen Gras  * $Id: view.c,v 1.2 2007/05/28 15:01:58 blymn Exp $
27*51ffecc1SBen Gras  */
28*51ffecc1SBen Gras 
29*51ffecc1SBen Gras #include <stdlib.h>
30*51ffecc1SBen Gras #include <string.h>
31*51ffecc1SBen Gras #include <sys/types.h>
32*51ffecc1SBen Gras #include <signal.h>
33*51ffecc1SBen Gras #ifdef NCURSES
34*51ffecc1SBen Gras #define _XOPEN_SOURCE_EXTENDED
35*51ffecc1SBen Gras #include <ncurses.h>
36*51ffecc1SBen Gras #include <term.h>
37*51ffecc1SBen Gras #else
38*51ffecc1SBen Gras #include <curses.h>
39*51ffecc1SBen Gras #endif /* NCURSES */
40*51ffecc1SBen Gras #include <locale.h>
41*51ffecc1SBen Gras #include <assert.h>
42*51ffecc1SBen Gras #include <ctype.h>
43*51ffecc1SBen Gras #include <termios.h>
44*51ffecc1SBen Gras #include <util.h>
45*51ffecc1SBen Gras #include <unistd.h>
46*51ffecc1SBen Gras #ifdef HAVE_WCHAR
47*51ffecc1SBen Gras #include <wchar.h>
48*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
49*51ffecc1SBen Gras #ifdef DEBUG
50*51ffecc1SBen Gras #include <syslog.h>
51*51ffecc1SBen Gras #endif /* DEBUG */
52*51ffecc1SBen Gras 
53*51ffecc1SBen Gras #define UChar(c)    ((unsigned char)(c))
54*51ffecc1SBen Gras #define SIZEOF(table)	(sizeof(table)/sizeof(table[0]))
55*51ffecc1SBen Gras #define typeMalloc(type,n) (type *) malloc((n) * sizeof(type))
56*51ffecc1SBen Gras 
57*51ffecc1SBen Gras #define my_pair 1
58*51ffecc1SBen Gras 
59*51ffecc1SBen Gras #undef CURSES_CH_T
60*51ffecc1SBen Gras #ifdef HAVE_WCHAR
61*51ffecc1SBen Gras #define CURSES_CH_T cchar_t
62*51ffecc1SBen Gras #else
63*51ffecc1SBen Gras #define CURSES_CH_T chtype
64*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
65*51ffecc1SBen Gras 
66*51ffecc1SBen Gras static void finish(int sig);
67*51ffecc1SBen Gras static void show_all(const char *tag);
68*51ffecc1SBen Gras 
69*51ffecc1SBen Gras static int shift = 0;
70*51ffecc1SBen Gras static bool try_color = FALSE;
71*51ffecc1SBen Gras 
72*51ffecc1SBen Gras static char *fname;
73*51ffecc1SBen Gras static CURSES_CH_T **my_lines;
74*51ffecc1SBen Gras static CURSES_CH_T **lptr;
75*51ffecc1SBen Gras static unsigned num_lines;
76*51ffecc1SBen Gras 
usage(void)77*51ffecc1SBen Gras static void usage(void)
78*51ffecc1SBen Gras {
79*51ffecc1SBen Gras     static const char *msg[] = {
80*51ffecc1SBen Gras 	    "Usage: view [options] file"
81*51ffecc1SBen Gras 	    ,""
82*51ffecc1SBen Gras 	    ,"Options:"
83*51ffecc1SBen Gras 	    ," -c       use color if terminal supports it"
84*51ffecc1SBen Gras 	    ," -i       ignore INT, QUIT, TERM signals"
85*51ffecc1SBen Gras 	    ," -n NUM   specify maximum number of lines (default 1000)"
86*51ffecc1SBen Gras #if defined(KEY_RESIZE)
87*51ffecc1SBen Gras 	    ," -r       use old-style sigwinch handler rather than KEY_RESIZE"
88*51ffecc1SBen Gras #endif
89*51ffecc1SBen Gras #ifdef TRACE
90*51ffecc1SBen Gras 	    ," -t       trace screen updates"
91*51ffecc1SBen Gras 	    ," -T NUM   specify trace mask"
92*51ffecc1SBen Gras #endif
93*51ffecc1SBen Gras     };
94*51ffecc1SBen Gras     size_t n;
95*51ffecc1SBen Gras     for (n = 0; n < SIZEOF(msg); n++)
96*51ffecc1SBen Gras 	    fprintf(stderr, "%s\n", msg[n]);
97*51ffecc1SBen Gras     exit( 1 );
98*51ffecc1SBen Gras }
99*51ffecc1SBen Gras 
ch_len(CURSES_CH_T * src)100*51ffecc1SBen Gras static int ch_len(CURSES_CH_T * src)
101*51ffecc1SBen Gras {
102*51ffecc1SBen Gras     int result = 0;
103*51ffecc1SBen Gras 
104*51ffecc1SBen Gras #ifdef HAVE_WCHAR
105*51ffecc1SBen Gras     while (getcchar(src++, NULL, NULL, NULL, NULL) > 0)
106*51ffecc1SBen Gras 	    result++;
107*51ffecc1SBen Gras #else
108*51ffecc1SBen Gras     while (*src++)
109*51ffecc1SBen Gras 	result++;
110*51ffecc1SBen Gras #endif
111*51ffecc1SBen Gras     return result;
112*51ffecc1SBen Gras }
113*51ffecc1SBen Gras 
114*51ffecc1SBen Gras /*
115*51ffecc1SBen Gras  * Allocate a string into an array of chtype's.  If UTF-8 mode is
116*51ffecc1SBen Gras  * active, translate the string accordingly.
117*51ffecc1SBen Gras  */
ch_dup(char * src)118*51ffecc1SBen Gras static CURSES_CH_T * ch_dup(char *src)
119*51ffecc1SBen Gras {
120*51ffecc1SBen Gras     unsigned len = strlen(src);
121*51ffecc1SBen Gras     CURSES_CH_T *dst = typeMalloc(CURSES_CH_T, len + 1);
122*51ffecc1SBen Gras     unsigned j, k;
123*51ffecc1SBen Gras #ifdef HAVE_WCHAR
124*51ffecc1SBen Gras     wchar_t wstr[CCHARW_MAX + 1];
125*51ffecc1SBen Gras     wchar_t wch;
126*51ffecc1SBen Gras     int l = 0;
127*51ffecc1SBen Gras     mbstate_t state;
128*51ffecc1SBen Gras     size_t rc;
129*51ffecc1SBen Gras     int width;
130*51ffecc1SBen Gras #endif
131*51ffecc1SBen Gras 
132*51ffecc1SBen Gras #ifdef HAVE_WCHAR
133*51ffecc1SBen Gras     mbrtowc( NULL, NULL, 1, &state );
134*51ffecc1SBen Gras #endif
135*51ffecc1SBen Gras     for (j = k = 0; j < len; j++) {
136*51ffecc1SBen Gras #ifdef HAVE_WCHAR
137*51ffecc1SBen Gras 	    rc = mbrtowc(&wch, src + j, len - j, &state);
138*51ffecc1SBen Gras #ifdef DEBUG
139*51ffecc1SBen Gras         syslog( LOG_INFO, "[ch_dup]mbrtowc() returns %d", rc );
140*51ffecc1SBen Gras #endif /* DEBUG */
141*51ffecc1SBen Gras 	    if (rc == (size_t) -1 || rc == (size_t) -2)
142*51ffecc1SBen Gras 	        break;
143*51ffecc1SBen Gras 	    j += rc - 1;
144*51ffecc1SBen Gras 	    if ((width = wcwidth(wch)) < 0)
145*51ffecc1SBen Gras 	        break;
146*51ffecc1SBen Gras 	    if ((width > 0 && l > 0) || l == CCHARW_MAX) {
147*51ffecc1SBen Gras 	        wstr[l] = L'\0';
148*51ffecc1SBen Gras 	        l = 0;
149*51ffecc1SBen Gras 	        if (setcchar(dst + k, wstr, 0, 0, NULL) != OK)
150*51ffecc1SBen Gras 		        break;
151*51ffecc1SBen Gras 	        ++k;
152*51ffecc1SBen Gras 	    }
153*51ffecc1SBen Gras 	    if (width == 0 && l == 0)
154*51ffecc1SBen Gras 	        wstr[l++] = L' ';
155*51ffecc1SBen Gras 	    wstr[l++] = wch;
156*51ffecc1SBen Gras #ifdef DEBUG
157*51ffecc1SBen Gras         syslog( LOG_INFO, "[ch_dup]wch=%x", wch );
158*51ffecc1SBen Gras #endif /* DEBUG */
159*51ffecc1SBen Gras #else
160*51ffecc1SBen Gras 	    dst[k++] = src[j];
161*51ffecc1SBen Gras #endif
162*51ffecc1SBen Gras     }
163*51ffecc1SBen Gras #ifdef HAVE_WCHAR
164*51ffecc1SBen Gras     if (l > 0) {
165*51ffecc1SBen Gras 	    wstr[l] = L'\0';
166*51ffecc1SBen Gras 	    if (setcchar(dst + k, wstr, 0, 0, NULL) == OK)
167*51ffecc1SBen Gras 	        ++k;
168*51ffecc1SBen Gras     }
169*51ffecc1SBen Gras     setcchar(dst + k, L"", 0, 0, NULL);
170*51ffecc1SBen Gras #else
171*51ffecc1SBen Gras     dst[k] = 0;
172*51ffecc1SBen Gras #endif
173*51ffecc1SBen Gras     return dst;
174*51ffecc1SBen Gras }
175*51ffecc1SBen Gras 
main(int argc,char * argv[])176*51ffecc1SBen Gras int main(int argc, char *argv[])
177*51ffecc1SBen Gras {
178*51ffecc1SBen Gras     int MAXLINES = 1000;
179*51ffecc1SBen Gras     FILE *fp;
180*51ffecc1SBen Gras     char buf[BUFSIZ];
181*51ffecc1SBen Gras     int i;
182*51ffecc1SBen Gras     int my_delay = 0;
183*51ffecc1SBen Gras     CURSES_CH_T **olptr;
184*51ffecc1SBen Gras     int length = 0;
185*51ffecc1SBen Gras     int value = 0;
186*51ffecc1SBen Gras     bool done = FALSE;
187*51ffecc1SBen Gras     bool got_number = FALSE;
188*51ffecc1SBen Gras     const char *my_label = "Input";
189*51ffecc1SBen Gras #ifdef HAVE_WCHAR
190*51ffecc1SBen Gras     cchar_t icc;
191*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
192*51ffecc1SBen Gras 
193*51ffecc1SBen Gras     setlocale(LC_ALL, "");
194*51ffecc1SBen Gras 
195*51ffecc1SBen Gras     (void) signal(SIGINT, finish);	/* arrange interrupts to terminate */
196*51ffecc1SBen Gras 
197*51ffecc1SBen Gras     while ((i = getopt(argc, argv, "cin:rtT:")) != EOF) {
198*51ffecc1SBen Gras 	    switch (i) {
199*51ffecc1SBen Gras 	        case 'c':
200*51ffecc1SBen Gras 	            try_color = TRUE;
201*51ffecc1SBen Gras 	            break;
202*51ffecc1SBen Gras 	        case 'i':
203*51ffecc1SBen Gras 	            signal(SIGINT, SIG_IGN);
204*51ffecc1SBen Gras 	            signal(SIGQUIT, SIG_IGN);
205*51ffecc1SBen Gras 	            signal(SIGTERM, SIG_IGN);
206*51ffecc1SBen Gras 	            break;
207*51ffecc1SBen Gras 	        case 'n':
208*51ffecc1SBen Gras 	            if ((MAXLINES = atoi(optarg)) < 1)
209*51ffecc1SBen Gras 		        usage();
210*51ffecc1SBen Gras 	            break;
211*51ffecc1SBen Gras #ifdef TRACE
212*51ffecc1SBen Gras 	        case 'T':
213*51ffecc1SBen Gras 	            trace(atoi(optarg));
214*51ffecc1SBen Gras 	            break;
215*51ffecc1SBen Gras 	        case 't':
216*51ffecc1SBen Gras 	            trace(TRACE_CALLS);
217*51ffecc1SBen Gras 	            break;
218*51ffecc1SBen Gras #endif
219*51ffecc1SBen Gras 	        default:
220*51ffecc1SBen Gras 	            usage();
221*51ffecc1SBen Gras 	    }
222*51ffecc1SBen Gras     }
223*51ffecc1SBen Gras     if (optind + 1 != argc)
224*51ffecc1SBen Gras 	    usage();
225*51ffecc1SBen Gras 
226*51ffecc1SBen Gras     if ((my_lines = typeMalloc(CURSES_CH_T *, MAXLINES + 2)) == 0)
227*51ffecc1SBen Gras 	    usage();
228*51ffecc1SBen Gras 
229*51ffecc1SBen Gras     fname = argv[optind];
230*51ffecc1SBen Gras     if ((fp = fopen(fname, "r")) == 0) {
231*51ffecc1SBen Gras 	    perror(fname);
232*51ffecc1SBen Gras 	    exit( 1 );
233*51ffecc1SBen Gras     }
234*51ffecc1SBen Gras 
235*51ffecc1SBen Gras     /* slurp the file */
236*51ffecc1SBen Gras     num_lines = 0;
237*51ffecc1SBen Gras     for (lptr = &my_lines[0]; (lptr - my_lines) < MAXLINES; lptr++) {
238*51ffecc1SBen Gras 	    char temp[BUFSIZ], *s, *d;
239*51ffecc1SBen Gras 	    int col;
240*51ffecc1SBen Gras 
241*51ffecc1SBen Gras 	    if (fgets(buf, sizeof(buf), fp) == 0)
242*51ffecc1SBen Gras 	        break;
243*51ffecc1SBen Gras 
244*51ffecc1SBen Gras 	    /* convert tabs so that shift will work properly */
245*51ffecc1SBen Gras 	    for (s = buf, d = temp, col = 0; (*d = *s) != '\0'; s++) {
246*51ffecc1SBen Gras 	        if (*d == '\n') {
247*51ffecc1SBen Gras 		        *d = '\0';
248*51ffecc1SBen Gras 		        break;
249*51ffecc1SBen Gras 	        } else if (*d == '\t') {
250*51ffecc1SBen Gras 		        col = (col | 7) + 1;
251*51ffecc1SBen Gras 		        while ((d - temp) != col)
252*51ffecc1SBen Gras 		            *d++ = ' ';
253*51ffecc1SBen Gras 	        } else
254*51ffecc1SBen Gras #ifdef HAVE_WCHAR
255*51ffecc1SBen Gras 		        col++, d++;
256*51ffecc1SBen Gras #else
257*51ffecc1SBen Gras 	            if (isprint(UChar(*d))) {
258*51ffecc1SBen Gras 		            col++;
259*51ffecc1SBen Gras 		            d++;
260*51ffecc1SBen Gras 	            } else {
261*51ffecc1SBen Gras 		            sprintf(d, "\\%03o", UChar(*s));
262*51ffecc1SBen Gras 		            d += strlen(d);
263*51ffecc1SBen Gras 		            col = (d - temp);
264*51ffecc1SBen Gras 	            }
265*51ffecc1SBen Gras #endif
266*51ffecc1SBen Gras 	    }
267*51ffecc1SBen Gras 	    *lptr = ch_dup(temp);
268*51ffecc1SBen Gras 	    num_lines++;
269*51ffecc1SBen Gras     }
270*51ffecc1SBen Gras     (void) fclose(fp);
271*51ffecc1SBen Gras     length = lptr - my_lines;
272*51ffecc1SBen Gras 
273*51ffecc1SBen Gras     (void) initscr();		/* initialize the curses library */
274*51ffecc1SBen Gras     keypad(stdscr, TRUE);	/* enable keyboard mapping */
275*51ffecc1SBen Gras     (void) nonl();	 /* tell curses not to do NL->CR/NL on output */
276*51ffecc1SBen Gras     (void) cbreak(); /* take input chars one at a time, no wait for \n */
277*51ffecc1SBen Gras     (void) noecho();		/* don't echo input */
278*51ffecc1SBen Gras     nodelay(stdscr, TRUE);
279*51ffecc1SBen Gras     idlok(stdscr, TRUE);	/* allow use of insert/delete line */
280*51ffecc1SBen Gras 
281*51ffecc1SBen Gras     if (try_color) {
282*51ffecc1SBen Gras 	    if (has_colors()) {
283*51ffecc1SBen Gras 	        start_color();
284*51ffecc1SBen Gras 	        init_pair(my_pair, COLOR_WHITE, COLOR_BLUE);
285*51ffecc1SBen Gras 	        bkgd(COLOR_PAIR(my_pair));
286*51ffecc1SBen Gras 	    } else {
287*51ffecc1SBen Gras 	        try_color = FALSE;
288*51ffecc1SBen Gras 	    }
289*51ffecc1SBen Gras     }
290*51ffecc1SBen Gras 
291*51ffecc1SBen Gras     lptr = my_lines;
292*51ffecc1SBen Gras     while (!done) {
293*51ffecc1SBen Gras 	    int n;
294*51ffecc1SBen Gras #ifdef HAVE_WCHAR
295*51ffecc1SBen Gras         wint_t c = 0;
296*51ffecc1SBen Gras         int ret;
297*51ffecc1SBen Gras #else
298*51ffecc1SBen Gras         int c = 0;
299*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
300*51ffecc1SBen Gras 
301*51ffecc1SBen Gras 	    if (!got_number)
302*51ffecc1SBen Gras 	        show_all(my_label);
303*51ffecc1SBen Gras 
304*51ffecc1SBen Gras 	    n = 0;
305*51ffecc1SBen Gras 	    for (;;) {
306*51ffecc1SBen Gras             c = 0;
307*51ffecc1SBen Gras #ifdef HAVE_WCHAR
308*51ffecc1SBen Gras             ret = get_wch( &c );
309*51ffecc1SBen Gras             if ( ret == ERR ) {
310*51ffecc1SBen Gras 	            if (!my_delay)
311*51ffecc1SBen Gras 		            napms(50);
312*51ffecc1SBen Gras                 continue;
313*51ffecc1SBen Gras             }
314*51ffecc1SBen Gras #ifdef DEBUG
315*51ffecc1SBen Gras             else if ( ret == KEY_CODE_YES )
316*51ffecc1SBen Gras                 syslog( LOG_INFO, "[main]Func key(%x)", c );
317*51ffecc1SBen Gras             else
318*51ffecc1SBen Gras                 syslog( LOG_INFO, "[main]c=%x", c );
319*51ffecc1SBen Gras #endif /* DEBUG */
320*51ffecc1SBen Gras #else
321*51ffecc1SBen Gras 	        c = getch();
322*51ffecc1SBen Gras #ifdef DEBUG
323*51ffecc1SBen Gras             syslog( LOG_INFO, "[main]c='%c'", c );
324*51ffecc1SBen Gras #endif /* DEBUG */
325*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
326*51ffecc1SBen Gras 	        if ((c < 127) && isdigit(c)) {
327*51ffecc1SBen Gras 		        if (!got_number) {
328*51ffecc1SBen Gras 		            mvprintw(0, 0, "Count: ");
329*51ffecc1SBen Gras 		            clrtoeol();
330*51ffecc1SBen Gras 		        }
331*51ffecc1SBen Gras 		        addch(c);
332*51ffecc1SBen Gras 		        value = 10 * value + (c - '0');
333*51ffecc1SBen Gras 		        got_number = TRUE;
334*51ffecc1SBen Gras 	        } else
335*51ffecc1SBen Gras 		        break;
336*51ffecc1SBen Gras 	    }
337*51ffecc1SBen Gras 	    if (got_number && value) {
338*51ffecc1SBen Gras 	        n = value;
339*51ffecc1SBen Gras 	    } else {
340*51ffecc1SBen Gras 	        n = 1;
341*51ffecc1SBen Gras 	    }
342*51ffecc1SBen Gras 
343*51ffecc1SBen Gras #ifdef HAVE_WCHAR
344*51ffecc1SBen Gras 	    if (ret != ERR)
345*51ffecc1SBen Gras             my_label = key_name( c );
346*51ffecc1SBen Gras         else
347*51ffecc1SBen Gras 	        if (!my_delay)
348*51ffecc1SBen Gras 		        napms(50);
349*51ffecc1SBen Gras #else
350*51ffecc1SBen Gras 	    if (c != ERR)
351*51ffecc1SBen Gras 	        my_label = keyname(c);
352*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
353*51ffecc1SBen Gras 	    switch (c) {
354*51ffecc1SBen Gras 	        case KEY_DOWN:
355*51ffecc1SBen Gras #ifdef HAVE_WCHAR
356*51ffecc1SBen Gras             case L'n':
357*51ffecc1SBen Gras #else
358*51ffecc1SBen Gras 	        case 'n':
359*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
360*51ffecc1SBen Gras 	            olptr = lptr;
361*51ffecc1SBen Gras 	            for (i = 0; i < n; i++)
362*51ffecc1SBen Gras 		            if ((lptr - my_lines) < (length - LINES + 1))
363*51ffecc1SBen Gras 		                lptr++;
364*51ffecc1SBen Gras 		            else
365*51ffecc1SBen Gras 		                break;
366*51ffecc1SBen Gras 	            wscrl(stdscr, lptr - olptr);
367*51ffecc1SBen Gras 	            break;
368*51ffecc1SBen Gras 
369*51ffecc1SBen Gras 	        case KEY_UP:
370*51ffecc1SBen Gras #ifdef HAVE_WCHAR
371*51ffecc1SBen Gras             case L'p':
372*51ffecc1SBen Gras #else
373*51ffecc1SBen Gras 	        case 'p':
374*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
375*51ffecc1SBen Gras 	            olptr = lptr;
376*51ffecc1SBen Gras 	            for (i = 0; i < n; i++)
377*51ffecc1SBen Gras 		            if (lptr > my_lines)
378*51ffecc1SBen Gras 		                lptr--;
379*51ffecc1SBen Gras 		            else
380*51ffecc1SBen Gras 		                break;
381*51ffecc1SBen Gras 	            wscrl(stdscr, lptr - olptr);
382*51ffecc1SBen Gras 	            break;
383*51ffecc1SBen Gras 
384*51ffecc1SBen Gras #ifdef HAVE_WCHAR
385*51ffecc1SBen Gras             case L'h':
386*51ffecc1SBen Gras #else
387*51ffecc1SBen Gras 	        case 'h':
388*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
389*51ffecc1SBen Gras 	        case KEY_HOME:
390*51ffecc1SBen Gras 	            lptr = my_lines;
391*51ffecc1SBen Gras 	            break;
392*51ffecc1SBen Gras 
393*51ffecc1SBen Gras #ifdef HAVE_WCHAR
394*51ffecc1SBen Gras             case L'e':
395*51ffecc1SBen Gras #else
396*51ffecc1SBen Gras 	        case 'e':
397*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
398*51ffecc1SBen Gras 	        case KEY_END:
399*51ffecc1SBen Gras 	            if (length > LINES)
400*51ffecc1SBen Gras 		            lptr = my_lines + length - LINES + 1;
401*51ffecc1SBen Gras 	            else
402*51ffecc1SBen Gras 		            lptr = my_lines;
403*51ffecc1SBen Gras 	            break;
404*51ffecc1SBen Gras 
405*51ffecc1SBen Gras #ifdef HAVE_WCHAR
406*51ffecc1SBen Gras             case L'r':
407*51ffecc1SBen Gras #else
408*51ffecc1SBen Gras 	        case 'r':
409*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
410*51ffecc1SBen Gras 	        case KEY_RIGHT:
411*51ffecc1SBen Gras 	            shift += n;
412*51ffecc1SBen Gras 	            break;
413*51ffecc1SBen Gras 
414*51ffecc1SBen Gras #ifdef HAVE_WCHAR
415*51ffecc1SBen Gras             case L'l':
416*51ffecc1SBen Gras #else
417*51ffecc1SBen Gras 	        case 'l':
418*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
419*51ffecc1SBen Gras 	        case KEY_LEFT:
420*51ffecc1SBen Gras 	            shift -= n;
421*51ffecc1SBen Gras 	            if (shift < 0) {
422*51ffecc1SBen Gras 		            shift = 0;
423*51ffecc1SBen Gras 		            beep();
424*51ffecc1SBen Gras 	            }
425*51ffecc1SBen Gras 	            break;
426*51ffecc1SBen Gras 
427*51ffecc1SBen Gras #ifdef HAVE_WCHAR
428*51ffecc1SBen Gras             case L'q':
429*51ffecc1SBen Gras #else
430*51ffecc1SBen Gras 	        case 'q':
431*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
432*51ffecc1SBen Gras 	            done = TRUE;
433*51ffecc1SBen Gras 	            break;
434*51ffecc1SBen Gras 
435*51ffecc1SBen Gras #ifdef KEY_RESIZE
436*51ffecc1SBen Gras 	        case KEY_RESIZE:
437*51ffecc1SBen Gras                 //refresh();
438*51ffecc1SBen Gras 	            break;
439*51ffecc1SBen Gras #endif
440*51ffecc1SBen Gras #ifdef HAVE_WCHAR
441*51ffecc1SBen Gras 	        case L's':
442*51ffecc1SBen Gras #else
443*51ffecc1SBen Gras             case 's':
444*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
445*51ffecc1SBen Gras 	            if (got_number) {
446*51ffecc1SBen Gras 		            halfdelay(my_delay = n);
447*51ffecc1SBen Gras 	            } else {
448*51ffecc1SBen Gras 		            nodelay(stdscr, FALSE);
449*51ffecc1SBen Gras 		            my_delay = -1;
450*51ffecc1SBen Gras 	            }
451*51ffecc1SBen Gras 	            break;
452*51ffecc1SBen Gras #ifdef HAVE_WCHAR
453*51ffecc1SBen Gras             case L' ':
454*51ffecc1SBen Gras #else
455*51ffecc1SBen Gras 	        case ' ':
456*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
457*51ffecc1SBen Gras 	            nodelay(stdscr, TRUE);
458*51ffecc1SBen Gras 	            my_delay = 0;
459*51ffecc1SBen Gras 	            break;
460*51ffecc1SBen Gras #ifndef HAVE_WCHAR
461*51ffecc1SBen Gras 	        case ERR:
462*51ffecc1SBen Gras 	            if (!my_delay)
463*51ffecc1SBen Gras 		            napms(50);
464*51ffecc1SBen Gras 	            break;
465*51ffecc1SBen Gras #endif /* HAVE_WCHAR */
466*51ffecc1SBen Gras 	        default:
467*51ffecc1SBen Gras 	            beep();
468*51ffecc1SBen Gras 	            break;
469*51ffecc1SBen Gras 	    }
470*51ffecc1SBen Gras 	    if (c >= KEY_MIN || (c > 0 && !isdigit(c))) {
471*51ffecc1SBen Gras 	        got_number = FALSE;
472*51ffecc1SBen Gras 	        value = 0;
473*51ffecc1SBen Gras 	    }
474*51ffecc1SBen Gras     }
475*51ffecc1SBen Gras 
476*51ffecc1SBen Gras     finish(0);			/* we're done */
477*51ffecc1SBen Gras }
478*51ffecc1SBen Gras 
finish(int sig)479*51ffecc1SBen Gras static void finish(int sig)
480*51ffecc1SBen Gras {
481*51ffecc1SBen Gras     endwin();
482*51ffecc1SBen Gras     exit(sig != 0 ?  1 : 0 );
483*51ffecc1SBen Gras }
484*51ffecc1SBen Gras 
show_all(const char * tag)485*51ffecc1SBen Gras static void show_all(const char *tag)
486*51ffecc1SBen Gras {
487*51ffecc1SBen Gras     int i;
488*51ffecc1SBen Gras     char temp[BUFSIZ];
489*51ffecc1SBen Gras     CURSES_CH_T *s;
490*51ffecc1SBen Gras     time_t this_time;
491*51ffecc1SBen Gras 
492*51ffecc1SBen Gras     sprintf(temp, "%s (%3dx%3d) col %d ", tag, LINES, COLS, shift);
493*51ffecc1SBen Gras     i = strlen(temp);
494*51ffecc1SBen Gras     sprintf(temp + i, "view %.*s", (int) (sizeof(temp) - 7 - i), fname);
495*51ffecc1SBen Gras     move(0, 0);
496*51ffecc1SBen Gras     printw("%.*s", COLS, temp);
497*51ffecc1SBen Gras     clrtoeol();
498*51ffecc1SBen Gras     this_time = time((time_t *) 0);
499*51ffecc1SBen Gras     strcpy(temp, ctime(&this_time));
500*51ffecc1SBen Gras     if ((i = strlen(temp)) != 0) {
501*51ffecc1SBen Gras 	    temp[--i] = 0;
502*51ffecc1SBen Gras 	    if (move(0, COLS - i - 2) != ERR)
503*51ffecc1SBen Gras 	        printw("  %s", temp);
504*51ffecc1SBen Gras     }
505*51ffecc1SBen Gras 
506*51ffecc1SBen Gras     scrollok(stdscr, FALSE);	/* prevent screen from moving */
507*51ffecc1SBen Gras     for (i = 1; i < LINES; i++) {
508*51ffecc1SBen Gras 	    move(i, 0);
509*51ffecc1SBen Gras 	    printw("%3ld:", (long) (lptr + i - my_lines));
510*51ffecc1SBen Gras 	    clrtoeol();
511*51ffecc1SBen Gras 	    if ((s = lptr[i - 1]) != 0) {
512*51ffecc1SBen Gras 		    if (i < num_lines) {
513*51ffecc1SBen Gras 			    int len = ch_len(s);
514*51ffecc1SBen Gras 			    if (len > shift) {
515*51ffecc1SBen Gras #ifdef HAVE_WCHAR
516*51ffecc1SBen Gras 				    add_wchstr(s + shift);
517*51ffecc1SBen Gras #else
518*51ffecc1SBen Gras 				    addchstr(s + shift);
519*51ffecc1SBen Gras #endif
520*51ffecc1SBen Gras 			    }
521*51ffecc1SBen Gras 		    }
522*51ffecc1SBen Gras 	    }
523*51ffecc1SBen Gras     }
524*51ffecc1SBen Gras     setscrreg(1, LINES - 1);
525*51ffecc1SBen Gras     scrollok(stdscr, TRUE);
526*51ffecc1SBen Gras     refresh();
527*51ffecc1SBen Gras }
528