dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libast / common / disc / sfdcmore.c
blob96dc09b13321ed07e42fb418fba50cf40cdc48ae
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #include "sfdchdr.h"
24 #if _PACKAGE_ast
25 #include <ast_tty.h>
26 #include <signal.h>
27 #endif
30 * a simple but fast more style pager discipline
31 * if on sfstdout then sfstdin ops reset the page state
33 * Glenn Fowler
34 * AT&T Research
36 * @(#)$Id: sfdcmore (AT&T Research) 1998-06-25 $
39 typedef struct
41 Sfdisc_t disc; /* sfio discipline */
42 Sfio_t* input; /* tied with this input stream */
43 Sfio_t* error; /* tied with this error stream */
44 int rows; /* max rows */
45 int cols; /* max cols */
46 int row; /* current row */
47 int col; /* current col */
48 int match; /* match length, 0 if none */
49 char pattern[128]; /* match pattern */
50 char prompt[1]; /* prompt string */
51 } More_t;
54 * more read
55 * we assume line-at-a-time input
58 #if __STD_C
59 static ssize_t moreread(Sfio_t* f, void* buf, size_t n, Sfdisc_t* dp)
60 #else
61 static ssize_t moreread(f, buf, n, dp)
62 Sfio_t* f;
63 void* buf;
64 size_t n;
65 Sfdisc_t* dp;
66 #endif
68 register More_t* more = (More_t*)dp;
70 more->match = 0;
71 more->row = 2;
72 more->col = 1;
73 return sfrd(f, buf, n, dp);
77 * output label on wfd and return next char on rfd with no echo
78 * return < -1 is -(signal + 1)
81 #if __STD_C
82 static int ttyquery(Sfio_t* rp, Sfio_t* wp, const char* label, Sfdisc_t* dp)
83 #else
84 static int ttyquery(rp, wp, label, dp)
85 Sfio_t* rp;
86 Sfio_t* wp;
87 char* label;
88 Sfdisc_t* dp;
89 #endif
91 register int r;
92 int n;
94 #ifdef TCSADRAIN
95 unsigned char c;
96 struct termios old;
97 struct termios tty;
98 int rfd = sffileno(rp);
99 int wfd = sffileno(rp);
101 if (!label)
102 n = 0;
103 else if (n = strlen(label))
104 write(wfd, label, n);
105 tcgetattr(rfd, &old);
106 tty = old;
107 tty.c_cc[VTIME] = 0;
108 tty.c_cc[VMIN] = 1;
109 tty.c_lflag &= ~(ICANON|ECHO|ECHOK|ISIG);
110 tcsetattr(rfd, TCSADRAIN, &tty);
111 if ((r = read(rfd, &c, 1)) == 1)
113 if (c == old.c_cc[VEOF])
114 r = -1;
115 else if (c == old.c_cc[VINTR])
116 r = -(SIGINT + 1);
117 else if (c == old.c_cc[VQUIT])
118 r = -(SIGQUIT + 1);
119 else if (c == '\r')
120 r = '\n';
121 else
122 r = c;
124 tcsetattr(rfd, TCSADRAIN, &old);
125 if (n)
127 write(wfd, "\r", 1);
128 while (n-- > 0)
129 write(wfd, " ", 1);
130 write(wfd, "\r", 1);
132 #else
133 register char* s;
135 if (label && (n = strlen(label)))
136 sfwr(wp, label, n, dp);
137 r = (s = sfgetr(rp, '\n', 0)) ? *s : -1;
138 #endif
139 return r;
143 * more write
146 #if __STD_C
147 static ssize_t morewrite(Sfio_t* f, const Void_t* buf, register size_t n, Sfdisc_t* dp)
148 #else
149 static ssize_t morewrite(f, buf, n, dp)
150 Sfio_t* f;
151 Void_t* buf;
152 register size_t n;
153 Sfdisc_t* dp;
154 #endif
156 register More_t* more = (More_t*)dp;
157 register char* b;
158 register char* s;
159 register char* e;
160 register ssize_t w;
161 register int r;
163 if (!more->row)
164 return n;
165 if (!more->col)
166 return sfwr(f, buf, n, dp);
167 w = 0;
168 b = (char*)buf;
169 s = b;
170 e = s + n;
171 if (more->match)
173 match:
174 for (r = more->pattern[0];; s++)
176 if (s >= e)
177 return n;
178 if (*s == '\n')
179 b = s + 1;
180 else if (*s == r && (e - s) >= more->match && !strncmp(s, more->pattern, more->match))
181 break;
183 s = b;
184 w += b - (char*)buf;
185 more->match = 0;
187 while (s < e)
189 switch (*s++)
191 case '\t':
192 more->col = ((more->col + 8) & ~7) - 1;
193 /*FALLTHROUGH*/
194 default:
195 if (++more->col <= more->cols || s < e && *s == '\n')
196 continue;
197 /*FALLTHROUGH*/
198 case '\n':
199 more->col = 1;
200 if (++more->row < more->rows)
201 continue;
202 break;
203 case '\b':
204 if (more->col > 1)
205 more->col--;
206 continue;
207 case '\r':
208 more->col = 1;
209 continue;
211 w += sfwr(f, b, s - b, dp);
212 b = s;
213 r = ttyquery(sfstdin, f, more->prompt, dp);
214 if (r == '/' || r == 'n')
216 if (r == '/')
218 sfwr(f, "/", 1, dp);
219 if ((s = sfgetr(sfstdin, '\n', 1)) && (n = sfvalue(sfstdin) - 1) > 0)
221 if (n >= sizeof(more->pattern))
222 n = sizeof(more->pattern) - 1;
223 memcpy(more->pattern, s, n);
224 more->pattern[n] = 0;
227 if (more->match = strlen(more->pattern))
229 more->row = 1;
230 more->col = 1;
231 goto match;
234 switch (r)
236 case '\n':
237 case '\r':
238 more->row--;
239 more->col = 1;
240 break;
241 case ' ':
242 more->row = 2;
243 more->col = 1;
244 break;
245 default:
246 more->row = 0;
247 return n;
250 if (s > b)
251 w += sfwr(f, b, s - b, dp);
252 return w;
256 * remove the discipline on close
259 #if __STD_C
260 static int moreexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* dp)
261 #else
262 static int moreexcept(f, type, data, dp)
263 Sfio_t* f;
264 int type;
265 Void_t* data;
266 Sfdisc_t* dp;
267 #endif
269 register More_t* more = (More_t*)dp;
271 if (type == SF_FINAL || type == SF_DPOP)
273 if (f = more->input)
275 more->input = 0;
276 sfdisc(f, SF_POPDISC);
278 else if (f = more->error)
280 more->error = 0;
281 sfdisc(f, SF_POPDISC);
283 else
284 free(dp);
286 else if (type == SF_SYNC)
288 more->match = 0;
289 more->row = 1;
290 more->col = 1;
292 return 0;
296 * push the more discipline on f
297 * if prompt==0 then a default ansi prompt is used
298 * if rows==0 or cols==0 then they are deterimined from the tty
299 * if f==sfstdout then input on sfstdin also resets the state
302 #if __STD_C
303 int sfdcmore(Sfio_t* f, const char* prompt, int rows, int cols)
304 #else
305 int sfdcmore(f, prompt, rows, cols)
306 Sfio_t* f;
307 char* prompt;
308 int rows;
309 int cols;
310 #endif
312 register More_t* more;
313 size_t n;
316 * this is a writeonly discipline for interactive io
319 if (!(sfset(f, 0, 0) & SF_WRITE) || !isatty(sffileno(sfstdin)) || !isatty(sffileno(sfstdout)))
320 return -1;
321 if (!prompt)
322 prompt = "\033[7m More\033[m";
323 n = strlen(prompt) + 1;
324 if (!(more = (More_t*)malloc(sizeof(More_t) + n)))
325 return -1;
326 memset(more, 0, sizeof(*more));
328 more->disc.readf = moreread;
329 more->disc.writef = morewrite;
330 more->disc.exceptf = moreexcept;
331 memcpy(more->prompt, prompt, n);
332 if (!rows || !cols)
334 #if _PACKAGE_ast
335 astwinsize(sffileno(sfstdin), &rows, &cols);
336 #endif
337 if (!rows)
338 rows = 24;
339 if (!cols)
340 cols = 80;
342 more->rows = rows;
343 more->cols = cols;
344 more->row = 1;
345 more->col = 1;
347 if (sfdisc(f, &more->disc) != &more->disc)
349 free(more);
350 return -1;
352 if (f == sfstdout)
354 if (sfdisc(sfstdin, &more->disc) != &more->disc)
356 sfdisc(f, SF_POPDISC);
357 return -1;
359 more->input = sfstdin;
360 if (sfdisc(sfstderr, &more->disc) != &more->disc)
362 sfdisc(f, SF_POPDISC);
363 return -1;
365 more->error = sfstdin;
368 return 0;