📄 pg.c
字号:
#ifndef lintstatic char *sccsid = "@(#)pg.c 4.2 (ULTRIX) 11/14/90";#endif lint/************************************************************************ * * * Copyright (c) Digital Equipment Corporation, 1988, 1990 * * * * All Rights Reserved. Unpublished rights reserved under the * * copyright laws of the United States. * * * * The software contained on this media is proprietary to and * * embodies the confidential technology of Digital Equipment * * Corporation. Possession, use, duplication or dissemination of * * the software and media is authorized only pursuant to a valid * * written license from Digital Equipment Corporation. * * * * RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by * * the U.S. Government is subject to restrictions as set forth in * * Subparagraph (c)(1)(ii) of DFARS 252.227-7013, or in FAR * * 52.227-19, as applicable. * * * * This software is derived from software received from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with AT&T. * * * ************************************************************************//**//************************************************************************* Systems V static char sccsid[] = "@(#)pg.c 1.5"; *************************************************************************//************************************************************************** Modification History** 13-Jun-88 Tim Burke* #include <sys/termio.h>** 09-Jun-88 Mark Parenti* Changed signal handlers to void.** 22-Apr-88 David Gray * Modified so the user responses are echoed.** 20-Nov-88 Jon Reeves for Dave Long* Fixed missing arg on call to set_state().** 15-Oct-90 GWS* changed #include <curses.h> to #include <cursesX.h> because* this uses X/Open (System V-based) "curses".*************************************************************************/#include <signal.h>#include <setjmp.h>#include <sys/types.h>#include <sys/dir.h>#include <sys/stat.h>#include <ctype.h>#include <stdio.h>#include <cursesX.h>#include <term.h>#include <sys/termio.h>/* * pg -- paginator for crt terminals * * Includes the ability to display pages that have * already passed by. Also gives the user the ability * to search forward and backwards for regular expressions. * This works for piped input by copying to a temporary file, * and resolving backreferences from there. * * Note: The reason that there are so many commands to do * the same types of things is to try to accommodate * users of other paginators. */#define LINSIZ 1024#define QUIT '\034'#define BOF (EOF - 1) /* Begining of File */#define STOP (EOF - 2)#define PROMPTSIZE 256struct line { /* how line addresses are stored */ long l_addr; /* file offset */ int l_no; /* line number in file */};typedef struct line LINE;LINE *zero = NULL, /* first line */ *dot, /* current line */ *dol, /* last line */ *contig; /* where contiguous (non-aged) lines start */short nlall; /* room for how many LINEs in memory */FILE *in_file, /* current input stream */ *tmp_fin, /* pipe temporary file in */ *tmp_fou; /* pipe temporary file out */char *tmp_name = "/tmp/pgXXXXXX";long ftell();char *malloc(), *realloc();short sign; /* sign of command input */int fnum, /* which file argument we're in */ pipe_in, /* set when stdin is a pipe */ out_is_tty; /* set if stdout is a tty */void on_brk(), end_it();short brk_hit; /* interrupt handling is pending flag */int window = 0; /* window size in lines */short eof_pause = 1; /* pause w/ prompt at end of files */short soflag = 0; /* output all messages in standout mode */short promptlen; /* length of the current prompt */short firstf = 1; /* set before first file has been processed */short inwait, /* set while waiting for user input */ errors; /* set if error message has been printed. * if so, need to erase it and prompt */char **fnames;short fflag = 0; /* set if the f option is used */short nflag = 0; /* set for "no newline" input option */short clropt = 0; /* set if the clear option is used */int initopt = 0; /* set if the line option is used */int srchopt = 0; /* set if the search option is used */int initline;char initbuf[BUFSIZ];char leave_search = 't'; /* where on the page to leave a found string */short nfiles;char *shell;char *promptstr = ":";char *setprompt();short lenprompt; /* length of prompt string */int nchars; /* return from getline in find() */jmp_buf restore;char Line[LINSIZ+2];struct screen_stat { int first_line; int last_line; short is_eof; };struct screen_stat old_ss = { 0, 0, 0 };struct screen_stat new_ss;short eoflag; /* set whenever at end of current file */short doliseof; /* set when last line of file is known */int eofl_no; /* what the last line of the file is */#define USAGE() { fprintf(stderr,"Usage: pg [-number] [-p string] [-cefs] [+line] [+/pattern/] files\n"); exit(1); }main(argc, argv)int argc;char *argv[];{ register char *s; register char *p; register char ch; int prnames = 0; char *getenv(); FILE *checkf(); nfiles = argc; fnames = argv; while (--nfiles > 0) { if ((ch = (*++fnames)[0]) == '-') { if (fnames[0][1] == '\0' ) break; for (s = fnames[0]+1; *s != '\0'; s++) if (isdigit(*s)) { window = 0; do { window = window*10+*s-'0'; } while (isdigit(*++s)); if (*s != '\0') USAGE(); break; } else if (*s == 'c') clropt = 1; else if (*s == 'e') eof_pause = 0; else if (*s == 'f') fflag = 1; else if (*s == 'n') nflag = 1; else if (*s == 's') soflag = 1; /* standout mode */ else if (*s == 'p') { if (*++s != '\0') promptstr = setprompt(s); else if (nfiles > 1) { promptstr = setprompt(*++fnames); nfiles--; } else USAGE(); break; } else USAGE(); } else if (ch == '+') { s = *fnames; if (*++s == '/') { srchopt++; initopt = 0; for (++s, p=initbuf; *s!='\0' && *s!='/';) if (p < initbuf + sizeof(initbuf)) *p++ = *s++; else { fprintf(stderr,"pg: pattern too long\n"); exit(1); } *p = '\0'; } else { initopt++; srchopt = 0; for (; isdigit(*s); s++) initline = initline*10 + *s -'0'; if (*s != '\0') USAGE(); } } else break; } signal(SIGQUIT,end_it); signal(SIGINT,end_it); out_is_tty = isatty(1); if (out_is_tty) { terminit(); signal(SIGQUIT,on_brk); signal(SIGINT,on_brk); } if (window == 0) window = lines - 1; lenprompt = strlen(promptstr); if (window <= 1) window = 2; if (initline <= 0) initline = 1; if (nfiles > 1) prnames++; if (nfiles == 0) { fnames[0] = "-"; nfiles++; } while (fnum < nfiles) { if (strcmp(fnames[fnum],"") == 0) fnames[fnum] = "-"; if ((in_file = checkf(fnames[fnum])) == NULL) fnum++; else { if (out_is_tty) fnum += screen(fnames[fnum]); else { if (prnames) { pr("::::::::::::::\n"); pr(fnames[fnum]); pr("\n::::::::::::::\n"); } copy_file(in_file,stdout); fnum++; } fflush(stdout); if (pipe_in) save_pipe(); else if (in_file != tmp_fin) fclose(in_file); } } end_it();}char *setprompt(s)register char *s;{ register int i = 0; register int pct_d = 0; static char pstr[PROMPTSIZE]; while (i < PROMPTSIZE - 2) switch(pstr[i++] = *s++) { case '\0': return(pstr); case '%': if (*s == 'd' && !pct_d) { pct_d++; } else if (*s != '%') pstr[i++] = '%'; if ((pstr[i++] = *s++) == '\0') return(pstr); break; default: break; } fprintf(stderr,"pg: prompt too long\n"); exit(1);}/* * Print out the contents of the file f, one screenful at a time. */screen(file_name)char *file_name;{ int cmd_ret = 0; int start; short hadchance = 0; old_ss.is_eof = 0; old_ss.first_line = 0; old_ss.last_line = 0; new_ss = old_ss; if (!firstf) cmd_ret = command(file_name); else { firstf = 0; if (initopt) { initopt = 0; new_ss.first_line = initline; new_ss.last_line = initline + window - 1; } else if (srchopt) { srchopt = 0; if (!search(initbuf,1)) cmd_ret = command(file_name); } else { new_ss.first_line = 1; new_ss.last_line = window; } } for (;;) { if (cmd_ret) return(cmd_ret); if (hadchance && new_ss.first_line >= eofl_no - 1) return(1); hadchance = 0; if (new_ss.last_line < window) new_ss.last_line = window; if (find(0,new_ss.last_line + 1) != EOF) new_ss.is_eof = 0; else { new_ss.is_eof = 1; new_ss.last_line = eofl_no - 1; new_ss.first_line = new_ss.last_line - window + 1; } if (new_ss.first_line < 1) new_ss.first_line = 1; if (clropt) { doclear(); start = new_ss.first_line; } else { if (new_ss.first_line == old_ss.last_line) start = new_ss.first_line + 1; else if (new_ss.first_line > old_ss.last_line) start = new_ss.first_line; else if (old_ss.first_line < new_ss.first_line) start = old_ss.last_line + 1; else start = new_ss.first_line; if (start < old_ss.first_line) sopr("...skipping backward\n",0); else if (start > old_ss.last_line + 1) sopr("...skipping forward\n",0); } for(; start <= new_ss.last_line; start++) { find(0,start); pr(Line); if (brk_hit) { new_ss.last_line = find(1,0); new_ss.is_eof = 0; break; } } brk_hit = 0; fflush(stdout); if (new_ss.is_eof) { if (!eof_pause || eofl_no == 1) return(1); hadchance++; error("(EOF)"); } old_ss = new_ss; cmd_ret = command((char *)NULL); }}char cmdbuf[LINSIZ], *cmdptr;#define BEEP() if (bell) { putp(bell); fflush(stdout); }#define BLANKS(p) while (*p == ' ' || *p == '\t') p++#define CHECKEND() BLANKS(cmdptr); if (*cmdptr) { BEEP(); break; }/* * Read a command and do it. A command consists of an optional integer * argument followed by the command character. Return the number of files * to skip, 0 if we're still talking about the same file. */command (filename)char *filename;{ register int nlines; register int retval; register char c; FILE *sf; char *cmdend; short checkit = 0; int id; int skip; for (;;) { /* Wait for output to drain before going on. */ /* This is done so that the user will not hit */ /* break and quit before he has seen the prompt. */ ioctl(1,TCSBRK,1); if (setjmp(restore) != 0) end_it(); inwait = 1; brk_hit = 0; if (errors) errors = 0; else { kill_line(); prompt(filename); } fflush(stdout); if (ttyin()) continue; cmdptr = cmdbuf; nlines = number(); BLANKS(cmdptr); switch (*cmdptr++) { case 'h': CHECKEND(); help(); break; case '\014': /* ^L */ case '.': /* redisplay current window */ CHECKEND(); new_ss.first_line = old_ss.first_line; new_ss.last_line = new_ss.first_line + window - 1; inwait = 0; return(0); case 'w': /* set window size */ case 'z': if (sign == -1) { BEEP(); break; } CHECKEND(); if (nlines == 0) nlines = window; else if (nlines > 1) window = nlines; else { BEEP(); break; } new_ss.first_line = old_ss.last_line; new_ss.last_line = new_ss.first_line + window - 1; inwait = 0; return(0); case '\004': /* ^D */ case 'd': CHECKEND(); if (sign == 0) sign = 1; new_ss.last_line = old_ss.last_line + sign*window/2; new_ss.first_line = new_ss.last_line - window + 1; inwait = 0; return(0); case 's': /* * save input in filename. * Check for filename, access, etc. */ BLANKS(cmdptr); if (!*cmdptr) { BEEP(); break; } if (setjmp(restore) != 0) { BEEP(); } else { if ((sf=fopen(cmdptr,"w")) == NULL) { error("cannot open save file");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -