Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libstand / pager.c
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  * $FreeBSD: src/lib/libstand/pager.c,v 1.4.2.1 2001/03/05 06:27:44 kris Exp $
27  */
28 /*
29  * Simple paged-output and paged-viewing functions
30  */
31
32 #include "stand.h"
33 #include <string.h>
34
35 static int      p_maxlines = -1;
36 static int      p_freelines;
37
38 static char *pager_prompt1 = " --more--  <space> page down <enter> line down <q> quit ";
39 static char *pager_blank   = "                                                        ";
40
41 /*
42  * 'open' the pager
43  */
44 void
45 pager_open(void)
46 {
47     int         nlines;
48     char        *cp, *lp;
49     
50     nlines = 24;                /* sensible default */
51     if ((cp = getenv("LINES")) != NULL) {
52         nlines = strtol(cp, &lp, 0);
53     }
54
55     p_maxlines = nlines - 1;
56     if (p_maxlines < 1)
57         p_maxlines = 1;
58     p_freelines = p_maxlines;
59 }
60
61 /*
62  * 'close' the pager
63  */
64 void
65 pager_close(void)
66 {
67     p_maxlines = -1;
68 }
69
70 /*
71  * Emit lines to the pager; may not return until the user
72  * has responded to the prompt.
73  *
74  * Will return nonzero if the user enters 'q' or 'Q' at the prompt.
75  *
76  * XXX note that this watches outgoing newlines (and eats them), but
77  *     does not handle wrap detection (req. count of columns).
78  */
79
80 int
81 pager_output(const char *cp)
82 {
83     int         action;
84
85     if (cp == NULL)
86         return(0);
87     
88     for (;;) {
89         if (*cp == 0)
90             return(0);
91         
92         putchar(*cp);                   /* always emit character */
93
94         if (*(cp++) == '\n') {          /* got a newline? */
95             p_freelines--;
96             if (p_freelines <= 0) {
97                 printf("%s", pager_prompt1);
98                 action = 0;
99                 while (action == 0) {
100                     switch(getchar()) {
101                     case '\r':
102                     case '\n':
103                         p_freelines = 1;
104                         action = 1;
105                         break;
106                     case ' ':
107                         p_freelines = p_maxlines;
108                         action = 1;
109                         break;
110                     case 'q':
111                     case 'Q':
112                         action = 2;
113                         break;
114                     default:
115                         break;
116                     }
117                 }
118                 printf("\r%s\r", pager_blank);
119                 if (action == 2)
120                     return(1);
121             }
122         }
123     }
124 }
125
126 /*
127  * Display from (fd).
128  */
129 int
130 pager_file(const char *fname)
131 {
132     char        buf[80];
133     size_t      hmuch;
134     int         fd;
135     int         result;
136     
137     if ((fd = open(fname, O_RDONLY)) == -1) {
138         printf("can't open '%s': %s\n", fname, strerror(errno));
139         return(-1);
140     }
141
142     for (;;) {
143         hmuch = read(fd, buf, sizeof(buf) - 1);
144         if (hmuch == -1) {
145             result = -1;
146             break;
147         }
148         if (hmuch == 0) {
149             result = 0;
150             break;
151         }
152         buf[hmuch] = 0;
153         if (pager_output(buf)) {
154             result = 1;
155             break;
156         }
157     }
158     close(fd);
159     return(result);
160 }