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