DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦776f834af⟧ TextFile

    Length: 17810 (0x4592)
    Types: TextFile
    Names: »disp.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦e83f91978⟧ »EurOpenD22/isode/osimis-2.0.tar.Z« 
        └─⟦d846658bd⟧ 
            └─⟦this⟧ »osimis/smap/disp.c« 

TextFile

/*
 * 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 ();
}