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