Home | History | Annotate | Line # | Download | only in hack
hack.topl.c revision 1.6
      1 /*	$NetBSD: hack.topl.c,v 1.6 2002/05/26 00:12:12 wiz 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.6 2002/05/26 00:12:12 wiz 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 pline(const char *fmt, ...)
    147 {
    148 	va_list ap;
    149 
    150 	va_start(ap, fmt);
    151 	vpline(fmt, ap);
    152 	va_end(ap);
    153 }
    154 
    155 void
    156 vpline(line, ap)
    157 	const char *line;
    158 	va_list ap;
    159 {
    160 	char            pbuf[BUFSZ];
    161 	char           *bp = pbuf, *tl;
    162 	int             n, n0;
    163 
    164 	if (!line || !*line)
    165 		return;
    166 	if (!strchr(line, '%'))
    167 		(void) strcpy(pbuf, line);
    168 	else
    169 		(void) vsprintf(pbuf, line, ap);
    170 	if (flags.toplin == 1 && !strcmp(pbuf, toplines))
    171 		return;
    172 	nscr();			/* %% */
    173 
    174 	/* If there is room on the line, print message on same line */
    175 	/* But messages like "You die..." deserve their own line */
    176 	n0 = strlen(bp);
    177 	if (flags.toplin == 1 && tly == 1 &&
    178 	    n0 + strlen(toplines) + 3 < CO - 8 &&	/* leave room for
    179 							 * --More-- */
    180 	    strncmp(bp, "You ", 4)) {
    181 		(void) strcat(toplines, "  ");
    182 		(void) strcat(toplines, bp);
    183 		tlx += 2;
    184 		addtopl(bp);
    185 		return;
    186 	}
    187 	if (flags.toplin == 1)
    188 		more();
    189 	remember_topl();
    190 	toplines[0] = 0;
    191 	while (n0) {
    192 		if (n0 >= CO) {
    193 			/* look for appropriate cut point */
    194 			n0 = 0;
    195 			for (n = 0; n < CO; n++)
    196 				if (bp[n] == ' ')
    197 					n0 = n;
    198 			if (!n0)
    199 				for (n = 0; n < CO - 1; n++)
    200 					if (!letter(bp[n]))
    201 						n0 = n;
    202 			if (!n0)
    203 				n0 = CO - 2;
    204 		}
    205 		(void) strncpy((tl = eos(toplines)), bp, n0);
    206 		tl[n0] = 0;
    207 		bp += n0;
    208 
    209 		/* remove trailing spaces, but leave one */
    210 		while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ')
    211 			tl[--n0] = 0;
    212 
    213 		n0 = strlen(bp);
    214 		if (n0 && tl[0])
    215 			(void) strcat(tl, "\n");
    216 	}
    217 	redotoplin();
    218 }
    219 
    220 void
    221 putsym(c)
    222 	char            c;
    223 {
    224 	switch (c) {
    225 	case '\b':
    226 		backsp();
    227 		return;
    228 	case '\n':
    229 		curx = 1;
    230 		cury++;
    231 		if (cury > tly)
    232 			tly = cury;
    233 		break;
    234 	default:
    235 		if (curx == CO)
    236 			putsym('\n');	/* 1 <= curx <= CO; avoid CO */
    237 		else
    238 			curx++;
    239 	}
    240 	(void) putchar(c);
    241 }
    242 
    243 void
    244 putstr(s)
    245 	const char           *s;
    246 {
    247 	while (*s)
    248 		putsym(*s++);
    249 }
    250