xref: /freebsd/stand/libsa/pager.c (revision 783d3ff6)
1 /*-
2  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 /*
27  * Simple paged-output and paged-viewing functions
28  */
29 
30 #include "stand.h"
31 #include <string.h>
32 
33 static int	p_maxlines = -1;
34 static int	p_freelines;
35 
36 static char *pager_prompt1 = " --more--  <space> page down <enter> line down <q> quit ";
37 static char *pager_blank   = "                                                        ";
38 
39 /*
40  * 'open' the pager
41  */
42 void
43 pager_open(void)
44 {
45     int		nlines;
46     char	*cp, *lp;
47 
48     nlines = 24;		/* sensible default */
49     if ((cp = getenv("LINES")) != NULL) {
50 	nlines = strtol(cp, &lp, 0);
51     }
52 
53     p_maxlines = nlines - 1;
54     if (p_maxlines < 1)
55 	p_maxlines = 1;
56     p_freelines = p_maxlines;
57 }
58 
59 /*
60  * 'close' the pager
61  */
62 void
63 pager_close(void)
64 {
65     p_maxlines = -1;
66 }
67 
68 /*
69  * Emit lines to the pager; may not return until the user
70  * has responded to the prompt.
71  *
72  * Will return nonzero if the user enters 'q' or 'Q' at the prompt.
73  *
74  * XXX note that this watches outgoing newlines (and eats them), but
75  *     does not handle wrap detection (req. count of columns).
76  */
77 
78 int
79 pager_output(const char *cp)
80 {
81     int		action;
82 
83     if (cp == NULL)
84 	return(0);
85 
86     for (;;) {
87 	if (*cp == 0)
88 	    return(0);
89 
90 	putchar(*cp);			/* always emit character */
91 
92 	if (*(cp++) == '\n') {		/* got a newline? */
93 	    p_freelines--;
94 	    if (p_freelines <= 0) {
95 		printf("%s", pager_prompt1);
96 		action = 0;
97 		while (action == 0) {
98 		    switch(getchar()) {
99 		    case '\r':
100 		    case '\n':
101 			p_freelines = 1;
102 			action = 1;
103 			break;
104 		    case ' ':
105 			p_freelines = p_maxlines;
106 			action = 1;
107 			break;
108 		    case 'q':
109 		    case 'Q':
110 			action = 2;
111 			break;
112 		    default:
113 			break;
114 		    }
115 		}
116 		printf("\r%s\r", pager_blank);
117 		if (action == 2)
118 		    return(1);
119 	    }
120 	}
121     }
122 }
123 
124 /*
125  * Display from (fd).
126  */
127 int
128 pager_file(const char *fname)
129 {
130     char	buf[80];
131     size_t	hmuch;
132     int		fd;
133     int		result;
134 
135     if ((fd = open(fname, O_RDONLY)) == -1) {
136 	printf("can't open '%s': %s\n", fname, strerror(errno));
137 	return(-1);
138     }
139 
140     for (;;) {
141 	hmuch = read(fd, buf, sizeof(buf) - 1);
142 	if (hmuch == -1) {
143 	    result = -1;
144 	    break;
145 	}
146 	if (hmuch == 0) {
147 	    result = 0;
148 	    break;
149 	}
150 	buf[hmuch] = 0;
151 	if (pager_output(buf)) {
152 	    result = 1;
153 	    break;
154 	}
155     }
156     close(fd);
157     return(result);
158 }
159