pager.c revision 72621
138451Smsmith/*-
238451Smsmith * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
338451Smsmith * All rights reserved.
438451Smsmith *
538451Smsmith * Redistribution and use in source and binary forms, with or without
638451Smsmith * modification, are permitted provided that the following conditions
738451Smsmith * are met:
838451Smsmith * 1. Redistributions of source code must retain the above copyright
938451Smsmith *    notice, this list of conditions and the following disclaimer.
1038451Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1138451Smsmith *    notice, this list of conditions and the following disclaimer in the
1238451Smsmith *    documentation and/or other materials provided with the distribution.
1338451Smsmith *
1438451Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738451Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2038451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438451Smsmith * SUCH DAMAGE.
2538451Smsmith *
2650476Speter * $FreeBSD: head/lib/libstand/pager.c 72621 2001-02-18 04:51:47Z kris $
2738451Smsmith */
2838451Smsmith/*
2938451Smsmith * Simple paged-output and paged-viewing functions
3038451Smsmith */
3138451Smsmith
3238451Smsmith#include "stand.h"
3338451Smsmith#include <string.h>
3438451Smsmith
3538451Smsmithstatic int	p_maxlines = -1;
3638451Smsmithstatic int	p_freelines;
3738451Smsmith
3838451Smsmithstatic char *pager_prompt1 = " --more--  <space> page down <enter> line down <q> quit ";
3938451Smsmithstatic char *pager_blank   = "                                                        ";
4038451Smsmith
4138451Smsmith/*
4238451Smsmith * 'open' the pager
4338451Smsmith */
4438451Smsmithvoid
4538451Smsmithpager_open(void)
4638451Smsmith{
4738451Smsmith    int		nlines;
4838451Smsmith    char	*cp, *lp;
4938451Smsmith
5038451Smsmith    nlines = 24;		/* sensible default */
5138451Smsmith    if ((cp = getenv("LINES")) != NULL) {
5238451Smsmith	nlines = strtol(cp, &lp, 0);
5338451Smsmith    }
5438451Smsmith
5538451Smsmith    p_maxlines = nlines - 1;
5638451Smsmith    if (p_maxlines < 1)
5738451Smsmith	p_maxlines = 1;
5838451Smsmith    p_freelines = p_maxlines;
5938451Smsmith}
6038451Smsmith
6138451Smsmith/*
6238451Smsmith * 'close' the pager
6338451Smsmith */
6438451Smsmithvoid
6538451Smsmithpager_close(void)
6638451Smsmith{
6738451Smsmith    p_maxlines = -1;
6838451Smsmith}
6938451Smsmith
7038451Smsmith/*
7138451Smsmith * Emit lines to the pager; may not return until the user
7238451Smsmith * has responded to the prompt.
7338451Smsmith *
7438451Smsmith * Will return nonzero if the user enters 'q' or 'Q' at the prompt.
7538451Smsmith *
7638451Smsmith * XXX note that this watches outgoing newlines (and eats them), but
7738451Smsmith *     does not handle wrap detection (req. count of columns).
7838451Smsmith */
7938451Smsmith
8038451Smsmithint
8138451Smsmithpager_output(const char *cp)
8238451Smsmith{
8338451Smsmith    int		action;
8438451Smsmith
8538451Smsmith    if (cp == NULL)
8638451Smsmith	return(0);
8738451Smsmith
8838451Smsmith    for (;;) {
8938451Smsmith	if (*cp == 0)
9038451Smsmith	    return(0);
9138451Smsmith
9238451Smsmith	putchar(*cp);			/* always emit character */
9338451Smsmith
9438451Smsmith	if (*(cp++) == '\n') {		/* got a newline? */
9538451Smsmith	    p_freelines--;
9638451Smsmith	    if (p_freelines <= 0) {
9772621Skris		printf("%s", pager_prompt1);
9838451Smsmith		action = 0;
9938451Smsmith		while (action == 0) {
10038451Smsmith		    switch(getchar()) {
10138451Smsmith		    case '\r':
10238451Smsmith		    case '\n':
10338451Smsmith			p_freelines = 1;
10438451Smsmith			action = 1;
10538451Smsmith			break;
10638451Smsmith		    case ' ':
10738451Smsmith			p_freelines = p_maxlines;
10838451Smsmith			action = 1;
10938451Smsmith			break;
11038451Smsmith		    case 'q':
11138451Smsmith		    case 'Q':
11238451Smsmith			action = 2;
11338451Smsmith			break;
11438451Smsmith		    default:
11538451Smsmith			break;
11638451Smsmith		    }
11738451Smsmith		}
11838451Smsmith		printf("\r%s\r", pager_blank);
11938451Smsmith		if (action == 2)
12038451Smsmith		    return(1);
12138451Smsmith	    }
12238451Smsmith	}
12338451Smsmith    }
12438451Smsmith}
12538451Smsmith
12638451Smsmith/*
12738451Smsmith * Display from (fd).
12838451Smsmith */
12938451Smsmithint
13039468Smsmithpager_file(const char *fname)
13138451Smsmith{
13238451Smsmith    char	buf[80];
13338451Smsmith    size_t	hmuch;
13438451Smsmith    int		fd;
13538451Smsmith    int		result;
13638451Smsmith
13738451Smsmith    if ((fd = open(fname, O_RDONLY)) == -1) {
13838451Smsmith	printf("can't open '%s': %s\n", fname, strerror(errno));
13938451Smsmith	return(-1);
14038451Smsmith    }
14138451Smsmith
14238451Smsmith    for (;;) {
14338451Smsmith	hmuch = read(fd, buf, sizeof(buf) - 1);
14438451Smsmith	if (hmuch == -1) {
14538451Smsmith	    result = -1;
14638451Smsmith	    break;
14738451Smsmith	}
14838451Smsmith	if (hmuch == 0) {
14938451Smsmith	    result = 0;
15038451Smsmith	    break;
15138451Smsmith	}
15238451Smsmith	buf[hmuch] = 0;
15338451Smsmith	if (pager_output(buf)) {
15438451Smsmith	    result = 1;
15538451Smsmith	    break;
15638451Smsmith	}
15738451Smsmith    }
15838451Smsmith    close(fd);
15938451Smsmith    return(result);
16038451Smsmith}
161