|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 17810 (0x4592)
Types: TextFile
Names: »disp.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦e83f91978⟧ »EurOpenD22/isode/osimis-2.0.tar.Z«
└─⟦d846658bd⟧
└─⟦this⟧ »osimis/smap/disp.c«
/*
* Copyright (c) 1988 University College London
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the Department of Computer Science, University College London.
* The name of the University may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* `curses' display for the osimon program */
/*
* Initially by Graham Knight, modified by George Pavlou
* October 1988
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <curses.h>
#include <errno.h>
#include <ctype.h>
#include "disp.h"
#include "recs.h"
#include "defs.h"
#define beep() putc('▶07◀', stderr)
#define nullstr(s) ((s == NULL) || (*(char *)(s) == '\0'))
char *index ();
extern REC recs[];
extern RECID endrec;
#define relmove(yi, xi) {int y,x; getyx(stdscr, y,x); \
move(y+yi, x+xi);}
int redisplay (); /* called to update display */
int stdoutch ();
static char *forcen ();
extern int LINES; /* number of lines on screen */
extern int COLS; /* number of columns on screen */
DISFL *dfp; /* pointer to current display structure */
int gap;
startdisplay (dp, gp)
DISFL *dp;
int gp;
{
dfp = dp;
gap = gp;
initscr (); /* start up curses package */
raw ();
#ifdef VAX
crmode();
#else
cbreak ();
#endif
noecho ();
scrollok (stdscr, 1);
screeninit (gap); /* start up screen stuff */
/* initialise and read the records */
initrecs (dfp->df_getrec, dfp->df_open, dfp->df_close, dfp->df_order);
getdata ();
settop (first ()); /* start with first page */
dspl (); /* display first page */
}
/* Get new record and re-display screen to show it */
redisplay ()
{
RECID nid; /* identifier for new record in table */
getdata ();
/* do deletions */
nid = first ();
while (!pastend (nid)) {
switch (recflag (nid)) {
case R_NEW:
case R_CHANGE:
case R_NOCHANGE:
break;
case R_DEL:
disprem (nid);
continue; /* don't increase nid */
case R_ERROR:
fprintf (stderr, "Too many records\n");
break;
default:
fprintf (stderr, "Bad enterec return code\n");
break;
}
incr (nid);
}
/* do insertions and changes */
nid = first ();
while (!pastend (nid)) {
switch (recflag (nid)) {
case R_NEW:
dispnew (nid);
break;
case R_CHANGE:
dispchange (nid);
break;
case R_NOCHANGE:
case R_DEL:
break;
case R_ERROR:
fprintf (stderr, "Too many records\n");
break;
default:
fprintf (stderr, "Bad enterec return code\n");
break;
}
incr (nid);
}
}
static dispchange (id)
RECID id;
{
RECID fid, lid;
int x, y, newscreen;
register int i;
beep ();
newscreen = lookat (id); /* lookat selects a new top of page */
delim (&fid, &lid); /* get screen delimiters */
move (TTLNS - 1, 0);
redraw (fid, id);
/* alternate between old and new versions */
getyx (stdscr, y, x);
if (newscreen) {
move (y + 1, 0);
redraw (next (id), lid);
}
for (i = 1; i < 3; i++) { /* flash change */
move (y, x);
if (i & 1)
woaddrec (stdscr, id);
else {
wmove (curscr, y, x);
wstandout (curscr);
woaddrec (curscr, id);
wstandend (curscr);
/* now curses thinks the text is already bold */
move (y, x);
standout (); /* switch on bolding */
addrec (id);
standend ();
}
refresh ();
sleep (2);
}
move (y, x);
redraw (id, lid);
refresh ();
}
static dispnew (id)
RECID id;
{
RECID fid, lid;
int x, y, newscreen, len;
register int i;
beep ();
newscreen = lookat (next (id)); /* lookat selects a new top of
* page */
delim (&fid, &lid); /* get screen delimiters */
move (TTLNS - 1, 0);
redraw (fid, id);
getyx (stdscr, y, x); /* save coords. This is where new one goes */
if (newscreen)
redraw (next (id), lid);
refresh ();
move (y + 1, 0);
refresh ();
/* create a gap */
for (i = 0; i < gap + linecnt (id); i++) {
sinsertln ();
refresh ();
}
if ((len = pagelen () + TTLNS) < LINES) {
move (len, 0);
clrtobot ();
refresh ();
}
/* sleep (2); */
move (y, x);
standout ();
addrec (id);
standend ();
refresh ();
sleep (2);
move (y, x);
redraw (id, lid);
refresh ();
}
/*
* display the removal of a record. Record is still present when called
*/
/* disprem does actually remove the record */
static disprem (id)
RECID id;
{
RECID fid, lid;
int x, y, newscreen;
register int i;
beep ();
newscreen = lookat (id); /* lookat selects a new top of page */
delim (&fid, &lid); /* get screen delimiters */
move (TTLNS - 1, 0);
redraw (fid, id);
getyx (stdscr, y, x); /* co-ords of record to be removed */
standout (); /* highlight text to remove */
addrec (id);
standend ();
redraw (next (id), lid);
refresh ();
/*
* sleep ((newscreen) ? 4 : 2);
*/
/* delete the record from the screen */
if (equal (fid, id))
move (y + 1, 0); /* no gap at top */
else
move (y + 1 + gap, 0);
/*
* for (i = 0; i < linecnt (id); i++) {
* addch ('\n');
* refresh ();
* sleep (1);
* }
*/
sleep (2);
if ((equal (id, fid)) && (d_downone ())) {
fid = next (id);
remrec (id);
settop (fid);
return;
}
if ((equal (next (id), lid)) && (d_upone ())) {
remrec (id);
settop (fid);
return;
}
move (y + 1, 0);
refresh ();
if (!nullstr (DL)) {
for (i = 0; i < linecnt (id) + gap; i++) {
tputs (DL, 1, stdoutch); /* delete a line */
wdeleteln (curscr); /* fiddle curscr */
deleteln (); /* bring stdscr into line */
}
refresh ();
}
remrec (id);
settop (fid);
delim (&fid, &lid); /* get screen delimiters */
move (TTLNS - 1, 0);
redraw (fid, lid);
refresh ();
sleep (2);
}
/* check single character command from the terminal */
checkcmd (c)
int c;
{
static int escape = NO;
if (c == EOF)
return (EOF);
c &= 0x7f; /* strip parity */
if (!escape)
switch (c) {
case 0:
case 'q':
case '▶03◀':
case '▶04◀':
return (EOF);
case ESCAPE:
escape = YES;
return (ESCAPE);
default:
return (c);
}
else {
escape = NO;
/* character after ESC to suit h19 vt100 etc. */
switch (c) {
case 'F': /* End */
case 'f':
return ('E');
case 'B': /* Down Arrow */
case 'b':
return (DOWNONE);
case 'H': /* Page Down */
case 'h':
return (DOWNPAGE);
case 'E': /* Home */
case 'e':
return (HOME);
case 'A': /* Up Arrow */
case 'a':
return (UPONE);
case 'G': /* Page Up */
case 'g':
return (UPPAGE);
default:
return ('?');
}
}
}
/* execute the command */
docmd (c)
int c;
{
int ret = 1;
switch (c) {
case 'K':
case 'k':
case '-':
case UPONE:
ret = d_upone ();
break;
case 'J':
case 'j':
case '+':
case '\r':
case DOWNONE: /* defined as '\n' */
ret = d_downone ();
break;
case '^':
case UPPAGE:
ret = d_uppage ();
break;
case ' ':
case DOWNPAGE:
ret = d_downpage ();
break;
case 'C':
case 'c':
case CLEAR:
dspl ();
ret = 1;
break;
case 's':
case 'S':
case '1':
case HOME:
ret = d_home ();
break;
case 'e':
case 'E':
case '$':
ret = d_fin ();
break;
default:
ret = 0;
break;
}
header ();
refresh ();
/*
* if (ret == 0) beep ();
*/
}
/* display a whole page */
dspl ()
{
RECID fid, lid;
delim (&fid, &lid);
clear ();
header ();
move (TTLNS - 1, 0);
redraw (fid, lid);
refresh ();
}
/* set up (part of) a screen */
/* assume cursor is at end of previous text line at start */
static redraw (sid, eid)
RECID sid, eid;
{
while (before (sid, eid)) {
addrec (sid);
incr (sid);
}
}
/* set up (part of) a screen using old records if available */
/* assume cursor is at end of previous text line at start */
static woredraw (scrp, sid, eid)
WINDOW *scrp;
RECID sid, eid;
{
while (before (sid, eid)) {
woaddrec (scrp, sid);
incr (sid);
}
}
/* add a record to the current "curses" screen */
/* assume cursor is at end of previous text line at start */
static addrec (id)
RECID id;
{
register int i;
RECID sid, eid;
int y, x;
delim (&sid, &eid);
getyx (stdscr, y, x);
move (y + 1, 0); /* move to next line */
if (!equal (id, sid)) {
for (i = gap; i; i--)
addch ('\n');
}
myaddstr (text (id));
}
/* add an OLD record to a "curses" screen */
/* assume cursor is at end of previous text line at start */
static woaddrec (scrp, id)
WINDOW *scrp;
RECID id;
{
register int i;
RECID sid, eid;
int y, x;
delim (&sid, &eid);
getyx (scrp, y, x);
wmove (scrp, y + 1, 0); /* move to next line */
if (!equal (id, sid)) {
for (i = gap; i; i--)
waddch (scrp, '\n');
}
mywaddstr (scrp, otext (id) ? forcen (id) : text (id));
}
/* insert a new record at top of screen and push the rest down */
static d_upone ()
{
register char *cp;
register int i, len = 0;
RECID id, eid;
if (upone () == 0)
return (0);
delim (&id, &eid);
move (TTLNS, 0);
refresh ();
/* do gap */
for (i = 0; i < gap; i++) {
sinsertln ();
refresh ();
}
/* find ends of lines, replace them with length of the line */
/* N.B. there will be no trailing lf */
cp = text (id);
while (*cp) {
if (*cp == '\n') {
*cp = len;
len = 0;
} else
len++;
cp++;
}
/* cp-> null at end of text, len is length of last line */
/* display last line */
sinsertln ();
myaddstr (cp -= len);
refresh ();
/* now do the rest in reverse order */
for (i = 1; i < linecnt (id); i++) {
len = (int) (*--cp) & 0xff;
*cp = '\0';
sinsertln ();
myaddstr (cp - len);
refresh ();
*cp = '\n';
cp -= len;
}
if ((len = pagelen () + TTLNS) < LINES) {
move (len, 0);
clrtobot ();
refresh ();
}
return (1);
}
/*
* insert a new record(s) at bottom of screen push and the rest up
* (if necessary)
*/
static d_downone ()
{
RECID nsid, nlid, osid, olid;
register int i;
register char *cp;
register RECID id;
int len, bspace, new = 0;
len = pagelen () + TTLNS;
bspace = LINES - len; /* space at bottom */
delim (&osid, &olid); /* old position */
if (downone () == 0)
return (0);
delim (&nsid, &nlid); /* new position */
move (len - 1, 0); /* start adding new records here */
refresh ();
/* add new records */
id = olid;
while (before (id, nlid)) {
cp = text (id);
/* add one new record */
for (i = 0; i < gap; i++) {
curscrlf (); /* down to next line */
clrtoeol ();
refresh ();
}
for (i = 0; i < linecnt (id); i++) {
curscrlf (); /* down to next line */
while ((*cp != '\n') && (*cp != '\0'))
addch (*cp++);
cp++;
refresh ();
}
new += (linecnt (id) + gap);
incr (id);
}
if (new <= bspace)
return (0); /* no scrolling took place */
/* pad at bottom so as to get first record at top of screen */
for (i = 0; i < LINES - pagelen () - TTLNS; i++) {
curscrlf (); /* down to next line */
clrtoeol ();
refresh ();
}
return (1);
}
/* display the previous page, scroll if possible */
static d_uppage ()
{
if (scrollfirst ())
return (1); /* done it by scrolling */
/* complete new screen required */
if (uppage ()) {
dspl ();
return (1);
}
return (0);
}
/* display the next page, scroll if possible */
static d_downpage ()
{
if (scrolllast ())
return (1); /* done it by scrolling */
/* complete new screen required */
if (downpage ()) {
dspl ();
return (1);
}
return (0);
}
/* go back to the start, scroll if possible */
static d_home ()
{
if (scrollfirst ())
return (1); /* done it by scrolling */
/* complete new screen required */
if (home ()) {
dspl ();
return (1);
}
return (0);
}
/* go to the end, scroll if possible */
static d_fin ()
{
if (scrolllast ())
return (1); /* done it by scrolling */
/* complete new screen required */
if (fin ()) {
dspl ();
return (1);
}
return (0);
}
/* tidy up at end */
clrup ()
{
move (LINES - 1, 0);
refresh ();
endwin ();
putchar ('\n');
}
/*
* Insert a blank line at the current cursor position and scroll
* screen below down one line. If current position is at bottom of
* screen, scroll up instead
*/
static sinsertln ()
{
int x, y;
register int i;
getyx (curscr, y, x);
move (y, 0);
refresh ();
if (y == LINES - 1) {
/* fprintf (stdout, "\n"); */
winsertln (curscr); /* fiddle curscr */
insertln (); /* bring stdscr into line */
return;
}
if (!nullstr (AL)) {
tputs (AL, 1, stdoutch); /* add a new blank line */
winsertln (curscr); /* fiddle curscr */
insertln (); /* bring stdscr into line */
return;
}
if (!nullstr (SR)) {
tputs (SR, 1, stdoutch); /* reverse scroll */
for (i = 1; i < 10; i++)
putchar ('\0');
winsertln (curscr); /* fiddle curscr */
insertln (); /* bring stdscr into line */
for (i = 0; i < y; i++) { /* make top part blank */
move (i, 0);
wclrtoeol (curscr);
}
move (y, 0);
return;
}
/* do it without scrolling */
insertln ();
}
/*
* move cursor to start of next line scroll screen up if necessary NB
* dont scroll header
*/
static curscrlf ()
{
int x, y;
register int i;
getyx (curscr, y, x);
if (y < LINES - 1) {
/* just move down */
move (y + 1, 0);
refresh ();
return;
}
if (!nullstr (DL)) {
move (TTLNS, 0);
refresh ();
tputs (DL, 1, stdoutch); /* delete a line */
wdeleteln (curscr); /* fiddle curscr */
deleteln (); /* bring stdscr into line */
move (LINES - 1, 0);
return;
}
move (LINES - 1, 0);
refresh ();
fprintf (stdout, "\n");
winsertln (curscr); /* fiddle curscr */
insertln (); /* bring stdscr into line */
for (i = 0; i < TTLNS; i++) { /* make top part blank */
move (i, 0);
wclrtoeol (curscr);
}
move (LINES - 1, 0);
return;
}
/*
* scroll up until first record is reached, return 0 if this would
* scroll more than one screen, or no screens
*/
static scrollfirst ()
{
RECID osid, olid;
delim (&osid, &olid); /* get current position */
if ((!onpage (first (), osid)) || /* more than one page required */
(equal (first (), osid))) /* already there */
return (0);
/* old record(s) will still be on screen so scroll */
while (d_upone ()); /* keep going until the top */
return (1);
}
/*
* scroll down until last record is reached, return 0 if this would
* scroll more than one screen, or no screens
*/
static scrolllast ()
{
RECID osid, olid;
delim (&osid, &olid); /* get current position */
if ((!onpage (olid, last ())) || /* more than one page */
(equal (olid, nextslot ())))/* already there */
return (0);
/* old record(s) will still be on screen so scroll */
while (d_downone ()); /* keep going until the bottom */
return (1);
}
/* output on character to stdout - termcaps requirement */
static stdoutch (c)
char c;
{
putchar (c);
}
/* display header */
static header ()
{
move (0, 0);
standout ();
myaddstr (dfp->df_title);
standend ();
move (0, 0);
}
/* return an "old" string the same length as the "new" string */
static char *forcen (id)
RECID id;
{
register char *cp;
static char buf[1024];
register int diff, i;
strcpy (buf, otext (id));
if ((diff = linecnt (id) - olinecnt (id)) == 0)
return (buf);
if (diff > 0) {
/* new > old */
cp = &buf[strlen (buf)];
for (; diff; diff--)
*cp++ = '\n';
*cp = '\0';
return (buf);
}
/* old > new */
cp = buf;
for (i = 0; i < linecnt (id); i++)
cp = index (cp, '\n');
*cp = '\0';
return ((char *) NULL);
}
static myaddstr (cp)
register char *cp;
{
register int i;
for (i = 0; i < COLS && *cp != '\0'; i++)
addch (*cp++);
}
static mywaddstr (win, cp)
WINDOW *win;
register char *cp;
{
register int i;
for (i = 0; i < COLS && *cp != '\0'; i++)
waddch (win, *cp++);
}
winredraw ()
{
RECID fid, lid;
delim (&fid, &lid);
settop (fid);
dspl ();
}