Home | History | Annotate | Line # | Download | only in hack
hack.topl.c revision 1.8.14.2.2.1
      1  1.8.14.2.2.1      matt /*	$NetBSD: hack.topl.c,v 1.8.14.2.2.1 2010/04/21 05:25:15 matt Exp $	*/
      2           1.4  christos 
      3           1.2   mycroft /*
      4           1.7       jsm  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
      5           1.7       jsm  * Amsterdam
      6           1.7       jsm  * All rights reserved.
      7           1.7       jsm  *
      8           1.7       jsm  * Redistribution and use in source and binary forms, with or without
      9           1.7       jsm  * modification, are permitted provided that the following conditions are
     10           1.7       jsm  * met:
     11           1.7       jsm  *
     12           1.7       jsm  * - Redistributions of source code must retain the above copyright notice,
     13           1.7       jsm  * this list of conditions and the following disclaimer.
     14           1.7       jsm  *
     15           1.7       jsm  * - Redistributions in binary form must reproduce the above copyright
     16           1.7       jsm  * notice, this list of conditions and the following disclaimer in the
     17           1.7       jsm  * documentation and/or other materials provided with the distribution.
     18           1.7       jsm  *
     19           1.7       jsm  * - Neither the name of the Stichting Centrum voor Wiskunde en
     20           1.7       jsm  * Informatica, nor the names of its contributors may be used to endorse or
     21           1.7       jsm  * promote products derived from this software without specific prior
     22           1.7       jsm  * written permission.
     23           1.7       jsm  *
     24           1.7       jsm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     25           1.7       jsm  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26           1.7       jsm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     27           1.7       jsm  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     28           1.7       jsm  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     29           1.7       jsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     30           1.7       jsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     31           1.7       jsm  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     32           1.7       jsm  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     33           1.7       jsm  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34           1.7       jsm  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35           1.7       jsm  */
     36           1.7       jsm 
     37           1.7       jsm /*
     38           1.7       jsm  * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org>
     39           1.7       jsm  * All rights reserved.
     40           1.7       jsm  *
     41           1.7       jsm  * Redistribution and use in source and binary forms, with or without
     42           1.7       jsm  * modification, are permitted provided that the following conditions
     43           1.7       jsm  * are met:
     44           1.7       jsm  * 1. Redistributions of source code must retain the above copyright
     45           1.7       jsm  *    notice, this list of conditions and the following disclaimer.
     46           1.7       jsm  * 2. Redistributions in binary form must reproduce the above copyright
     47           1.7       jsm  *    notice, this list of conditions and the following disclaimer in the
     48           1.7       jsm  *    documentation and/or other materials provided with the distribution.
     49           1.7       jsm  * 3. The name of the author may not be used to endorse or promote products
     50           1.7       jsm  *    derived from this software without specific prior written permission.
     51           1.7       jsm  *
     52           1.7       jsm  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     53           1.7       jsm  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     54           1.7       jsm  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     55           1.7       jsm  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     56           1.7       jsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     57           1.7       jsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     58           1.7       jsm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     59           1.7       jsm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     60           1.7       jsm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     61           1.7       jsm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     62           1.2   mycroft  */
     63           1.2   mycroft 
     64           1.4  christos #include <sys/cdefs.h>
     65           1.2   mycroft #ifndef lint
     66  1.8.14.2.2.1      matt __RCSID("$NetBSD: hack.topl.c,v 1.8.14.2.2.1 2010/04/21 05:25:15 matt Exp $");
     67           1.4  christos #endif				/* not lint */
     68           1.1       cgd 
     69           1.4  christos #include <stdlib.h>
     70           1.1       cgd #include "hack.h"
     71           1.4  christos #include "extern.h"
     72           1.1       cgd 
     73           1.4  christos char            toplines[BUFSZ];
     74           1.4  christos xchar           tlx, tly;	/* set by pline; used by addtopl */
     75           1.1       cgd 
     76           1.1       cgd struct topl {
     77           1.4  christos 	struct topl    *next_topl;
     78           1.4  christos 	char           *topl_text;
     79           1.4  christos }              *old_toplines, *last_redone_topl;
     80           1.1       cgd #define	OTLMAX	20		/* max nr of old toplines remembered */
     81           1.1       cgd 
     82           1.4  christos int
     83           1.4  christos doredotopl()
     84           1.4  christos {
     85           1.4  christos 	if (last_redone_topl)
     86           1.1       cgd 		last_redone_topl = last_redone_topl->next_topl;
     87           1.4  christos 	if (!last_redone_topl)
     88           1.1       cgd 		last_redone_topl = old_toplines;
     89           1.4  christos 	if (last_redone_topl) {
     90           1.1       cgd 		(void) strcpy(toplines, last_redone_topl->topl_text);
     91           1.1       cgd 	}
     92           1.1       cgd 	redotoplin();
     93           1.4  christos 	return (0);
     94           1.1       cgd }
     95           1.1       cgd 
     96           1.4  christos void
     97           1.4  christos redotoplin()
     98           1.4  christos {
     99           1.1       cgd 	home();
    100           1.4  christos 	if (strchr(toplines, '\n'))
    101           1.4  christos 		cl_end();
    102           1.1       cgd 	putstr(toplines);
    103           1.1       cgd 	cl_end();
    104           1.1       cgd 	tlx = curx;
    105           1.1       cgd 	tly = cury;
    106           1.1       cgd 	flags.toplin = 1;
    107           1.4  christos 	if (tly > 1)
    108           1.1       cgd 		more();
    109           1.1       cgd }
    110           1.1       cgd 
    111           1.4  christos void
    112           1.4  christos remember_topl()
    113           1.4  christos {
    114           1.4  christos 	struct topl    *tl;
    115           1.4  christos 	int             cnt = OTLMAX;
    116           1.4  christos 	if (last_redone_topl &&
    117           1.4  christos 	    !strcmp(toplines, last_redone_topl->topl_text))
    118           1.4  christos 		return;
    119           1.4  christos 	if (old_toplines &&
    120           1.4  christos 	    !strcmp(toplines, old_toplines->topl_text))
    121           1.4  christos 		return;
    122           1.1       cgd 	last_redone_topl = 0;
    123           1.1       cgd 	tl = (struct topl *)
    124           1.4  christos 		alloc((unsigned) (strlen(toplines) + sizeof(struct topl) + 1));
    125           1.1       cgd 	tl->next_topl = old_toplines;
    126           1.4  christos 	tl->topl_text = (char *) (tl + 1);
    127           1.1       cgd 	(void) strcpy(tl->topl_text, toplines);
    128           1.1       cgd 	old_toplines = tl;
    129           1.4  christos 	while (cnt && tl) {
    130           1.1       cgd 		cnt--;
    131           1.1       cgd 		tl = tl->next_topl;
    132           1.1       cgd 	}
    133           1.4  christos 	if (tl && tl->next_topl) {
    134           1.1       cgd 		free((char *) tl->next_topl);
    135           1.1       cgd 		tl->next_topl = 0;
    136           1.1       cgd 	}
    137           1.1       cgd }
    138           1.1       cgd 
    139           1.4  christos void
    140           1.4  christos addtopl(s)
    141           1.5       jsm 	const char           *s;
    142           1.4  christos {
    143           1.4  christos 	curs(tlx, tly);
    144           1.8  dholland 	if (tlx + (int)strlen(s) > CO)
    145           1.4  christos 		putsym('\n');
    146           1.1       cgd 	putstr(s);
    147           1.1       cgd 	tlx = curx;
    148           1.1       cgd 	tly = cury;
    149           1.1       cgd 	flags.toplin = 1;
    150           1.1       cgd }
    151           1.1       cgd 
    152           1.4  christos void
    153           1.1       cgd xmore(s)
    154           1.5       jsm 	const char *s;	/* allowed chars besides space/return */
    155           1.1       cgd {
    156           1.4  christos 	if (flags.toplin) {
    157           1.1       cgd 		curs(tlx, tly);
    158           1.4  christos 		if (tlx + 8 > CO)
    159           1.4  christos 			putsym('\n'), tly++;
    160           1.1       cgd 	}
    161           1.4  christos 	if (flags.standout)
    162           1.1       cgd 		standoutbeg();
    163           1.1       cgd 	putstr("--More--");
    164           1.4  christos 	if (flags.standout)
    165           1.1       cgd 		standoutend();
    166           1.1       cgd 
    167           1.1       cgd 	xwaitforspace(s);
    168           1.4  christos 	if (flags.toplin && tly > 1) {
    169           1.1       cgd 		home();
    170           1.1       cgd 		cl_end();
    171           1.4  christos 		docorner(1, tly - 1);
    172           1.1       cgd 	}
    173           1.1       cgd 	flags.toplin = 0;
    174           1.1       cgd }
    175           1.1       cgd 
    176           1.4  christos void
    177           1.4  christos more()
    178           1.4  christos {
    179           1.1       cgd 	xmore("");
    180           1.1       cgd }
    181           1.1       cgd 
    182           1.4  christos void
    183           1.1       cgd cmore(s)
    184           1.5       jsm 	const char           *s;
    185           1.1       cgd {
    186           1.1       cgd 	xmore(s);
    187           1.1       cgd }
    188           1.1       cgd 
    189           1.4  christos void
    190           1.4  christos clrlin()
    191           1.4  christos {
    192           1.4  christos 	if (flags.toplin) {
    193           1.1       cgd 		home();
    194           1.1       cgd 		cl_end();
    195           1.4  christos 		if (tly > 1)
    196           1.4  christos 			docorner(1, tly - 1);
    197           1.1       cgd 		remember_topl();
    198           1.1       cgd 	}
    199           1.1       cgd 	flags.toplin = 0;
    200           1.1       cgd }
    201           1.1       cgd 
    202           1.4  christos void
    203           1.4  christos pline(const char *fmt, ...)
    204           1.4  christos {
    205           1.4  christos 	va_list ap;
    206           1.6       wiz 
    207           1.4  christos 	va_start(ap, fmt);
    208           1.4  christos 	vpline(fmt, ap);
    209           1.4  christos 	va_end(ap);
    210           1.4  christos }
    211           1.4  christos 
    212           1.4  christos void
    213           1.4  christos vpline(line, ap)
    214           1.4  christos 	const char *line;
    215           1.4  christos 	va_list ap;
    216           1.4  christos {
    217           1.4  christos 	char            pbuf[BUFSZ];
    218           1.4  christos 	char           *bp = pbuf, *tl;
    219      1.8.14.2       snj 	int             n, n0, tlpos, dead;
    220           1.4  christos 
    221           1.4  christos 	if (!line || !*line)
    222           1.4  christos 		return;
    223           1.4  christos 	if (!strchr(line, '%'))
    224      1.8.14.1       snj 		(void) strlcpy(pbuf, line, sizeof(pbuf));
    225           1.4  christos 	else
    226      1.8.14.1       snj 		(void) vsnprintf(pbuf, sizeof(pbuf), line, ap);
    227           1.4  christos 	if (flags.toplin == 1 && !strcmp(pbuf, toplines))
    228           1.4  christos 		return;
    229           1.4  christos 	nscr();			/* %% */
    230           1.1       cgd 
    231           1.1       cgd 	/* If there is room on the line, print message on same line */
    232           1.1       cgd 	/* But messages like "You die..." deserve their own line */
    233           1.1       cgd 	n0 = strlen(bp);
    234           1.4  christos 	if (flags.toplin == 1 && tly == 1 &&
    235           1.8  dholland 	    n0 + (int)strlen(toplines) + 3 < CO - 8 &&	/* leave room for
    236           1.4  christos 							 * --More-- */
    237           1.1       cgd 	    strncmp(bp, "You ", 4)) {
    238           1.1       cgd 		(void) strcat(toplines, "  ");
    239           1.1       cgd 		(void) strcat(toplines, bp);
    240           1.1       cgd 		tlx += 2;
    241           1.1       cgd 		addtopl(bp);
    242           1.1       cgd 		return;
    243           1.1       cgd 	}
    244           1.4  christos 	if (flags.toplin == 1)
    245           1.4  christos 		more();
    246           1.1       cgd 	remember_topl();
    247      1.8.14.2       snj 	dead = 0;
    248           1.1       cgd 	toplines[0] = 0;
    249      1.8.14.2       snj 	while (n0 && !dead) {
    250           1.4  christos 		if (n0 >= CO) {
    251           1.1       cgd 			/* look for appropriate cut point */
    252           1.1       cgd 			n0 = 0;
    253           1.4  christos 			for (n = 0; n < CO; n++)
    254           1.4  christos 				if (bp[n] == ' ')
    255           1.4  christos 					n0 = n;
    256           1.4  christos 			if (!n0)
    257           1.4  christos 				for (n = 0; n < CO - 1; n++)
    258           1.4  christos 					if (!letter(bp[n]))
    259           1.4  christos 						n0 = n;
    260           1.4  christos 			if (!n0)
    261           1.4  christos 				n0 = CO - 2;
    262           1.1       cgd 		}
    263      1.8.14.2       snj 		tlpos = strlen(toplines);
    264      1.8.14.2       snj 		tl = toplines + tlpos;
    265      1.8.14.2       snj 		/* avoid overflow */
    266      1.8.14.2       snj 		if (tlpos + n0 > (int)sizeof(toplines) - 1) {
    267      1.8.14.2       snj 			n0 = sizeof(toplines) - 1 - tlpos;
    268      1.8.14.2       snj 			dead = 1;
    269      1.8.14.2       snj 		}
    270      1.8.14.2       snj 		(void) memcpy(tl, bp, n0);
    271           1.1       cgd 		tl[n0] = 0;
    272           1.1       cgd 		bp += n0;
    273           1.1       cgd 
    274           1.1       cgd 		/* remove trailing spaces, but leave one */
    275           1.4  christos 		while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ')
    276           1.1       cgd 			tl[--n0] = 0;
    277           1.1       cgd 
    278           1.1       cgd 		n0 = strlen(bp);
    279           1.4  christos 		if (n0 && tl[0])
    280      1.8.14.2       snj 			(void) strlcat(toplines, "\n", sizeof(toplines));
    281           1.1       cgd 	}
    282           1.1       cgd 	redotoplin();
    283           1.1       cgd }
    284           1.1       cgd 
    285           1.4  christos void
    286           1.4  christos putsym(c)
    287           1.4  christos 	char            c;
    288           1.4  christos {
    289           1.4  christos 	switch (c) {
    290           1.1       cgd 	case '\b':
    291           1.1       cgd 		backsp();
    292           1.1       cgd 		return;
    293           1.1       cgd 	case '\n':
    294           1.1       cgd 		curx = 1;
    295           1.1       cgd 		cury++;
    296           1.4  christos 		if (cury > tly)
    297           1.4  christos 			tly = cury;
    298           1.1       cgd 		break;
    299           1.1       cgd 	default:
    300           1.4  christos 		if (curx == CO)
    301           1.1       cgd 			putsym('\n');	/* 1 <= curx <= CO; avoid CO */
    302           1.1       cgd 		else
    303           1.1       cgd 			curx++;
    304           1.1       cgd 	}
    305           1.1       cgd 	(void) putchar(c);
    306           1.1       cgd }
    307           1.1       cgd 
    308           1.4  christos void
    309           1.4  christos putstr(s)
    310           1.5       jsm 	const char           *s;
    311           1.4  christos {
    312           1.4  christos 	while (*s)
    313           1.4  christos 		putsym(*s++);
    314           1.1       cgd }
    315