📄 pgpmoremod.c
字号:
/*
* pgpMoreMod.c -- A pipeline module to output text a page at a time.
*
* Copyright (C) 1996,1997 Pretty Good Privacy, Inc. All rights reserved.
*
* $Id: pgpMoreMod.c,v 1.3.2.1 1997/06/07 09:52:01 mhw Exp $
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <ctype.h>
#include "pgpDebug.h"
#include "pgpAnnotate.h"
#include "pgpMem.h"
#include "pgpPipeline.h"
#include "pgpKB.h"
#include "pgpScreen.h"
#include "pgpMoreMod.h"
#define MOREMAGIC 0xa5f91780
#define TABSTOP 8
struct MoreModContext {
int nrows; /* Number of rows on screen, minus 1 */
int row; /* Next row of output, 0 based */
int ncols; /* Number of columns on screen */
int col; /* Next column of output, 0 based */
long nbytes; /* Size of message, if given */
long byt; /* Number of bytes we have output */
char *rowbuf; /* Buffer holding row to be output */
byte flushing; /* True if discarding all input */
byte aftercr; /* Saw a cr, eat next lf if any */
byte quitting; /* Have printed quitting message */
int scope_depth; /* Nesting scope depth */
FILE *fp; /* Output file descriptor, must be console */
};
static void
moreflushrow(struct MoreModContext *context)
{
if (context->col) {
fputs (context->rowbuf, context->fp);
fputc('\n', context->fp);
context->col = 0;
}
}
static void
moreeraseline(struct MoreModContext *context)
{
int i;
int ncols = context->ncols;
FILE *fp = context->fp;
/* Blank out prompt */
for (i = 0; i < ncols; i++)
fputc (' ', fp);
fputc('\r', fp);
fflush(fp);
}
static void
morenewline(struct MoreModContext *context)
{
int c;
moreflushrow(context);
context->row += 1;
if (context->row == context->nrows) {
if (context->nbytes) {
fprintf (context->fp, "\
More -- %d%% -- Hit space for next screen, Enter for new line\
, 'Q' to quit --\r", (int)((100 * context->byt) / context->nbytes));
} else {
fputs ("\
More -- Hit space for next screen, Enter for new line, 'Q' to quit --\r",
context->fp);
}
fflush (context->fp);
for ( ; ; ) {
kbCbreak();
c = kbGet();
kbNorm();
moreeraseline(context);
c = toupper(c);
if (c == 'Q') {
context->flushing = 1;
break;
} else if (c == '\r' || c == '\n') {
context->row -= 1;
break;
} else if (c == ' ') {
context->row = 0;
break;
} else {
fprintf (context->fp, "\b");
}
}
}
}
static void
moreoutchar(struct MoreModContext *context, char c)
{
int aftercr = context->aftercr;
context->aftercr = 0;
if (c=='\n') {
if (aftercr)
return;
morenewline(context);
} else if (c=='\r') {
context->aftercr = 1;
morenewline(context);
} else if (c=='\t') {
int addspaces = TABSTOP - (context->col % TABSTOP);
while (addspaces--) {
if (context->col == context->ncols) {
context->rowbuf[context->col] = '\0';
return;
}
context->rowbuf[context->col++] = ' ';
}
context->rowbuf[context->col] = '\0';
} else if (c < ' ') {
return; /* Eat non-printing characters */
} else {
/* Eat characters beyond right column */
if (context->col == context->ncols)
return;
context->rowbuf[context->col++] = c;
context->rowbuf[context->col] = '\0';
}
}
static size_t
Write (struct PgpPipeline *myself, byte const *buf, size_t size, int *error)
{
struct MoreModContext *context;
int sz = size;
int c;
pgpAssert(myself);
pgpAssert(myself->magic == MOREMAGIC);
context = (struct MoreModContext *)myself->priv;
pgpAssert (context);
pgpAssert(error);
*error = 0;
while (!context->flushing && sz--) {
c = *(char *)buf++;
moreoutchar(context, (char)c);
++context->byt;
}
return size;
}
static int
Flush (struct PgpPipeline *myself)
{
pgpAssert(myself);
pgpAssert(myself->magic == MOREMAGIC);
/* To shut up compiler warnings */
(void)myself;
return 0;
}
static int
Annotate (struct PgpPipeline *myself, struct PgpPipeline *origin, int type,
byte const *string, size_t size)
{
struct MoreModContext *context;
/* To shut up compiler warnings */
(void)origin;
(void)string;
(void)size;
pgpAssert(myself);
pgpAssert(myself->magic == MOREMAGIC);
context = (struct MoreModContext *)myself->priv;
pgpAssert (context);
/* Currently the annotation reader does not pass us any annotations */
PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
pgpAssert (context->scope_depth != -1);
return 0;
}
static int
SizeAdvise (struct PgpPipeline *myself, unsigned long bytes)
{
struct MoreModContext *context;
pgpAssert (myself);
pgpAssert (myself->magic == MOREMAGIC);
context = (struct MoreModContext *)myself->priv;
pgpAssert (context);
if (bytes)
context->nbytes = bytes;
if (bytes || context->scope_depth)
return 0;
/* XXX
* End of "more" output. Note that scope_depth is not correct
* currently because annotation reader doesn't tell us scope.
* Not clear if this is a bug...
*/
if (!context->quitting) {
fputs ("\nDone...hit any key\n", context->fp);
kbCbreak();
kbGet();
kbNorm();
fputs ("\n", context->fp);
context->quitting = 1;
}
return 0;
}
static void
Teardown (struct PgpPipeline *myself)
{
struct MoreModContext *context;
pgpAssert(myself);
pgpAssert(myself->magic == MOREMAGIC);
context = (struct MoreModContext *)myself->priv;
pgpAssert (context);
memset (context->rowbuf, 0, context->ncols + 1);
pgpMemFree (context->rowbuf);
memset (context, 0, sizeof (*context));
pgpMemFree (context);
memset (myself, 0, sizeof (*myself));
pgpMemFree (myself);
}
struct PgpPipeline *
pgpMoreModCreate (struct PgpPipeline **head)
{
struct PgpPipeline *mod;
struct MoreModContext *context;
unsigned nrows, ncols;
if (!head)
return NULL;
context = (struct MoreModContext *)pgpMemAlloc (sizeof(*context));
if (!context)
return NULL;
memset(context, 0, sizeof(*context));
mod = (struct PgpPipeline *)pgpMemAlloc (sizeof(*mod));
if (!mod) {
pgpMemFree(context);
return NULL;
}
screenSizeGet (&nrows, &ncols);
context->rowbuf = (char *)pgpMemAlloc (ncols + 1);
if (!context->rowbuf) {
pgpMemFree(context);
pgpMemFree(mod);
return NULL;
}
context->nrows = nrows - 1;
context->ncols = ncols;
context->fp = stdout;
mod->magic = MOREMAGIC;
mod->write = Write;
mod->flush = Flush;
mod->sizeAdvise = SizeAdvise;
mod->annotate = Annotate;
mod->teardown = Teardown;
mod->name = "More";
mod->priv = context;
*head = mod;
return *head;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -