1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
30 * a simple but fast more style pager discipline
31 * if on sfstdout then sfstdin ops reset the page state
36 * @(#)$Id: sfdcmore (AT&T Research) 1998-06-25 $
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 */
55 * we assume line-at-a-time input
59 static ssize_t
moreread(Sfio_t
* f
, void* buf
, size_t n
, Sfdisc_t
* dp
)
61 static ssize_t
moreread(f
, buf
, n
, dp
)
68 register More_t
* more
= (More_t
*)dp
;
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)
82 static int ttyquery(Sfio_t
* rp
, Sfio_t
* wp
, const char* label
, Sfdisc_t
* dp
)
84 static int ttyquery(rp
, wp
, label
, dp
)
98 int rfd
= sffileno(rp
);
99 int wfd
= sffileno(rp
);
103 else if (n
= strlen(label
))
104 write(wfd
, label
, n
);
105 tcgetattr(rfd
, &old
);
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
])
115 else if (c
== old
.c_cc
[VINTR
])
117 else if (c
== old
.c_cc
[VQUIT
])
124 tcsetattr(rfd
, TCSADRAIN
, &old
);
135 if (label
&& (n
= strlen(label
)))
136 sfwr(wp
, label
, n
, dp
);
137 r
= (s
= sfgetr(rp
, '\n', 0)) ? *s
: -1;
147 static ssize_t
morewrite(Sfio_t
* f
, const Void_t
* buf
, register size_t n
, Sfdisc_t
* dp
)
149 static ssize_t
morewrite(f
, buf
, n
, dp
)
156 register More_t
* more
= (More_t
*)dp
;
166 return sfwr(f
, buf
, n
, dp
);
174 for (r
= more
->pattern
[0];; s
++)
180 else if (*s
== r
&& (e
- s
) >= more
->match
&& !strncmp(s
, more
->pattern
, more
->match
))
192 more
->col
= ((more
->col
+ 8) & ~7) - 1;
195 if (++more
->col
<= more
->cols
|| s
< e
&& *s
== '\n')
200 if (++more
->row
< more
->rows
)
211 w
+= sfwr(f
, b
, s
- b
, dp
);
213 r
= ttyquery(sfstdin
, f
, more
->prompt
, dp
);
214 if (r
== '/' || r
== 'n')
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
))
251 w
+= sfwr(f
, b
, s
- b
, dp
);
256 * remove the discipline on close
260 static int moreexcept(Sfio_t
* f
, int type
, Void_t
* data
, Sfdisc_t
* dp
)
262 static int moreexcept(f
, type
, data
, dp
)
269 register More_t
* more
= (More_t
*)dp
;
271 if (type
== SF_FINAL
|| type
== SF_DPOP
)
276 sfdisc(f
, SF_POPDISC
);
278 else if (f
= more
->error
)
281 sfdisc(f
, SF_POPDISC
);
286 else if (type
== SF_SYNC
)
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
303 int sfdcmore(Sfio_t
* f
, const char* prompt
, int rows
, int cols
)
305 int sfdcmore(f
, prompt
, rows
, cols
)
312 register More_t
* more
;
316 * this is a writeonly discipline for interactive io
319 if (!(sfset(f
, 0, 0) & SF_WRITE
) || !isatty(sffileno(sfstdin
)) || !isatty(sffileno(sfstdout
)))
322 prompt
= "\033[7m More\033[m";
323 n
= strlen(prompt
) + 1;
324 if (!(more
= (More_t
*)malloc(sizeof(More_t
) + n
)))
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
);
335 astwinsize(sffileno(sfstdin
), &rows
, &cols
);
347 if (sfdisc(f
, &more
->disc
) != &more
->disc
)
354 if (sfdisc(sfstdin
, &more
->disc
) != &more
->disc
)
356 sfdisc(f
, SF_POPDISC
);
359 more
->input
= sfstdin
;
360 if (sfdisc(sfstderr
, &more
->disc
) != &more
->disc
)
362 sfdisc(f
, SF_POPDISC
);
365 more
->error
= sfstdin
;