Home | History | Annotate | Line # | Download | only in hack
hack.topl.c revision 1.5
      1 /*	$NetBSD: hack.topl.c,v 1.5 2001/03/25 20:44:03 jsm Exp $	*/
      2 
      3 /*
      4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
      5  */
      6 
      7 #include <sys/cdefs.h>
      8 #ifndef lint
      9 __RCSID("$NetBSD: hack.topl.c,v 1.5 2001/03/25 20:44:03 jsm Exp $");
     10 #endif				/* not lint */
     11 
     12 #include <stdlib.h>
     13 #include "hack.h"
     14 #include "extern.h"
     15 
     16 char            toplines[BUFSZ];
     17 xchar           tlx, tly;	/* set by pline; used by addtopl */
     18 
     19 struct topl {
     20 	struct topl    *next_topl;
     21 	char           *topl_text;
     22 }              *old_toplines, *last_redone_topl;
     23 #define	OTLMAX	20		/* max nr of old toplines remembered */
     24 
     25 int
     26 doredotopl()
     27 {
     28 	if (last_redone_topl)
     29 		last_redone_topl = last_redone_topl->next_topl;
     30 	if (!last_redone_topl)
     31 		last_redone_topl = old_toplines;
     32 	if (last_redone_topl) {
     33 		(void) strcpy(toplines, last_redone_topl->topl_text);
     34 	}
     35 	redotoplin();
     36 	return (0);
     37 }
     38 
     39 void
     40 redotoplin()
     41 {
     42 	home();
     43 	if (strchr(toplines, '\n'))
     44 		cl_end();
     45 	putstr(toplines);
     46 	cl_end();
     47 	tlx = curx;
     48 	tly = cury;
     49 	flags.toplin = 1;
     50 	if (tly > 1)
     51 		more();
     52 }
     53 
     54 void
     55 remember_topl()
     56 {
     57 	struct topl    *tl;
     58 	int             cnt = OTLMAX;
     59 	if (last_redone_topl &&
     60 	    !strcmp(toplines, last_redone_topl->topl_text))
     61 		return;
     62 	if (old_toplines &&
     63 	    !strcmp(toplines, old_toplines->topl_text))
     64 		return;
     65 	last_redone_topl = 0;
     66 	tl = (struct topl *)
     67 		alloc((unsigned) (strlen(toplines) + sizeof(struct topl) + 1));
     68 	tl->next_topl = old_toplines;
     69 	tl->topl_text = (char *) (tl + 1);
     70 	(void) strcpy(tl->topl_text, toplines);
     71 	old_toplines = tl;
     72 	while (cnt && tl) {
     73 		cnt--;
     74 		tl = tl->next_topl;
     75 	}
     76 	if (tl && tl->next_topl) {
     77 		free((char *) tl->next_topl);
     78 		tl->next_topl = 0;
     79 	}
     80 }
     81 
     82 void
     83 addtopl(s)
     84 	const char           *s;
     85 {
     86 	curs(tlx, tly);
     87 	if (tlx + strlen(s) > CO)
     88 		putsym('\n');
     89 	putstr(s);
     90 	tlx = curx;
     91 	tly = cury;
     92 	flags.toplin = 1;
     93 }
     94 
     95 void
     96 xmore(s)
     97 	const char *s;	/* allowed chars besides space/return */
     98 {
     99 	if (flags.toplin) {
    100 		curs(tlx, tly);
    101 		if (tlx + 8 > CO)
    102 			putsym('\n'), tly++;
    103 	}
    104 	if (flags.standout)
    105 		standoutbeg();
    106 	putstr("--More--");
    107 	if (flags.standout)
    108 		standoutend();
    109 
    110 	xwaitforspace(s);
    111 	if (flags.toplin && tly > 1) {
    112 		home();
    113 		cl_end();
    114 		docorner(1, tly - 1);
    115 	}
    116 	flags.toplin = 0;
    117 }
    118 
    119 void
    120 more()
    121 {
    122 	xmore("");
    123 }
    124 
    125 void
    126 cmore(s)
    127 	const char           *s;
    128 {
    129 	xmore(s);
    130 }
    131 
    132 void
    133 clrlin()
    134 {
    135 	if (flags.toplin) {
    136 		home();
    137 		cl_end();
    138 		if (tly > 1)
    139 			docorner(1, tly - 1);
    140 		remember_topl();
    141 	}
    142 	flags.toplin = 0;
    143 }
    144 
    145 void
    146 #ifdef __STDC__
    147 pline(const char *fmt, ...)
    148 #else
    149 pline(va_alist)
    150 	va_dcl
    151 #endif
    152 {
    153 	va_list ap;
    154 #ifndef __STDC__
    155 	const char *fmt;
    156 	va_start(ap);
    157 	fmt = va_arg(ap, const char *);
    158 #else
    159 	va_start(ap, fmt);
    160 #endif
    161 	vpline(fmt, ap);
    162 	va_end(ap);
    163 }
    164 
    165 void
    166 vpline(line, ap)
    167 	const char *line;
    168 	va_list ap;
    169 {
    170 	char            pbuf[BUFSZ];
    171 	char           *bp = pbuf, *tl;
    172 	int             n, n0;
    173 
    174 	if (!line || !*line)
    175 		return;
    176 	if (!strchr(line, '%'))
    177 		(void) strcpy(pbuf, line);
    178 	else
    179 		(void) vsprintf(pbuf, line, ap);
    180 	if (flags.toplin == 1 && !strcmp(pbuf, toplines))
    181 		return;
    182 	nscr();			/* %% */
    183 
    184 	/* If there is room on the line, print message on same line */
    185 	/* But messages like "You die..." deserve their own line */
    186 	n0 = strlen(bp);
    187 	if (flags.toplin == 1 && tly == 1 &&
    188 	    n0 + strlen(toplines) + 3 < CO - 8 &&	/* leave room for
    189 							 * --More-- */
    190 	    strncmp(bp, "You ", 4)) {
    191 		(void) strcat(toplines, "  ");
    192 		(void) strcat(toplines, bp);
    193 		tlx += 2;
    194 		addtopl(bp);
    195 		return;
    196 	}
    197 	if (flags.toplin == 1)
    198 		more();
    199 	remember_topl();
    200 	toplines[0] = 0;
    201 	while (n0) {
    202 		if (n0 >= CO) {
    203 			/* look for appropriate cut point */
    204 			n0 = 0;
    205 			for (n = 0; n < CO; n++)
    206 				if (bp[n] == ' ')
    207 					n0 = n;
    208 			if (!n0)
    209 				for (n = 0; n < CO - 1; n++)
    210 					if (!letter(bp[n]))
    211 						n0 = n;
    212 			if (!n0)
    213 				n0 = CO - 2;
    214 		}
    215 		(void) strncpy((tl = eos(toplines)), bp, n0);
    216 		tl[n0] = 0;
    217 		bp += n0;
    218 
    219 		/* remove trailing spaces, but leave one */
    220 		while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ')
    221 			tl[--n0] = 0;
    222 
    223 		n0 = strlen(bp);
    224 		if (n0 && tl[0])
    225 			(void) strcat(tl, "\n");
    226 	}
    227 	redotoplin();
    228 }
    229 
    230 void
    231 putsym(c)
    232 	char            c;
    233 {
    234 	switch (c) {
    235 	case '\b':
    236 		backsp();
    237 		return;
    238 	case '\n':
    239 		curx = 1;
    240 		cury++;
    241 		if (cury > tly)
    242 			tly = cury;
    243 		break;
    244 	default:
    245 		if (curx == CO)
    246 			putsym('\n');	/* 1 <= curx <= CO; avoid CO */
    247 		else
    248 			curx++;
    249 	}
    250 	(void) putchar(c);
    251 }
    252 
    253 void
    254 putstr(s)
    255 	const char           *s;
    256 {
    257 	while (*s)
    258 		putsym(*s++);
    259 }
    260