1 1.14 dholland /* $NetBSD: hack.topl.c,v 1.14 2011/08/06 20:29:37 dholland 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.14 dholland __RCSID("$NetBSD: hack.topl.c,v 1.14 2011/08/06 20:29:37 dholland 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.12 dholland static char toplines[BUFSZ]; 74 1.12 dholland static xchar tlx, tly; /* set by pline; used by addtopl */ 75 1.1 cgd 76 1.12 dholland static 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.12 dholland static void redotoplin(void); 83 1.12 dholland static void xmore(const char *); 84 1.12 dholland 85 1.4 christos int 86 1.9 dholland doredotopl(void) 87 1.4 christos { 88 1.4 christos if (last_redone_topl) 89 1.1 cgd last_redone_topl = last_redone_topl->next_topl; 90 1.4 christos if (!last_redone_topl) 91 1.1 cgd last_redone_topl = old_toplines; 92 1.4 christos if (last_redone_topl) { 93 1.1 cgd (void) strcpy(toplines, last_redone_topl->topl_text); 94 1.1 cgd } 95 1.1 cgd redotoplin(); 96 1.4 christos return (0); 97 1.1 cgd } 98 1.1 cgd 99 1.12 dholland static void 100 1.9 dholland redotoplin(void) 101 1.4 christos { 102 1.1 cgd home(); 103 1.4 christos if (strchr(toplines, '\n')) 104 1.4 christos cl_end(); 105 1.1 cgd putstr(toplines); 106 1.1 cgd cl_end(); 107 1.1 cgd tlx = curx; 108 1.1 cgd tly = cury; 109 1.1 cgd flags.toplin = 1; 110 1.4 christos if (tly > 1) 111 1.1 cgd more(); 112 1.1 cgd } 113 1.1 cgd 114 1.4 christos void 115 1.9 dholland remember_topl(void) 116 1.4 christos { 117 1.4 christos struct topl *tl; 118 1.4 christos int cnt = OTLMAX; 119 1.4 christos if (last_redone_topl && 120 1.4 christos !strcmp(toplines, last_redone_topl->topl_text)) 121 1.4 christos return; 122 1.4 christos if (old_toplines && 123 1.4 christos !strcmp(toplines, old_toplines->topl_text)) 124 1.4 christos return; 125 1.1 cgd last_redone_topl = 0; 126 1.13 dholland tl = alloc(strlen(toplines) + sizeof(*tl) + 1); 127 1.1 cgd tl->next_topl = old_toplines; 128 1.4 christos tl->topl_text = (char *) (tl + 1); 129 1.1 cgd (void) strcpy(tl->topl_text, toplines); 130 1.1 cgd old_toplines = tl; 131 1.4 christos while (cnt && tl) { 132 1.1 cgd cnt--; 133 1.1 cgd tl = tl->next_topl; 134 1.1 cgd } 135 1.4 christos if (tl && tl->next_topl) { 136 1.14 dholland free(tl->next_topl); 137 1.1 cgd tl->next_topl = 0; 138 1.1 cgd } 139 1.1 cgd } 140 1.1 cgd 141 1.4 christos void 142 1.9 dholland addtopl(const char *s) 143 1.4 christos { 144 1.4 christos curs(tlx, tly); 145 1.8 dholland if (tlx + (int)strlen(s) > CO) 146 1.4 christos putsym('\n'); 147 1.1 cgd putstr(s); 148 1.1 cgd tlx = curx; 149 1.1 cgd tly = cury; 150 1.1 cgd flags.toplin = 1; 151 1.1 cgd } 152 1.1 cgd 153 1.9 dholland /* s = allowed chars besides space/return */ 154 1.12 dholland static void 155 1.9 dholland xmore(const char *s) 156 1.1 cgd { 157 1.4 christos if (flags.toplin) { 158 1.1 cgd curs(tlx, tly); 159 1.4 christos if (tlx + 8 > CO) 160 1.4 christos putsym('\n'), tly++; 161 1.1 cgd } 162 1.4 christos if (flags.standout) 163 1.1 cgd standoutbeg(); 164 1.1 cgd putstr("--More--"); 165 1.4 christos if (flags.standout) 166 1.1 cgd standoutend(); 167 1.1 cgd 168 1.1 cgd xwaitforspace(s); 169 1.4 christos if (flags.toplin && tly > 1) { 170 1.1 cgd home(); 171 1.1 cgd cl_end(); 172 1.4 christos docorner(1, tly - 1); 173 1.1 cgd } 174 1.1 cgd flags.toplin = 0; 175 1.1 cgd } 176 1.1 cgd 177 1.4 christos void 178 1.9 dholland more(void) 179 1.4 christos { 180 1.1 cgd xmore(""); 181 1.1 cgd } 182 1.1 cgd 183 1.4 christos void 184 1.9 dholland cmore(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.9 dholland clrlin(void) 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.9 dholland vpline(const char *line, va_list ap) 214 1.4 christos { 215 1.4 christos char pbuf[BUFSZ]; 216 1.4 christos char *bp = pbuf, *tl; 217 1.11 dholland int n, n0, tlpos, dead; 218 1.4 christos 219 1.4 christos if (!line || !*line) 220 1.4 christos return; 221 1.4 christos if (!strchr(line, '%')) 222 1.10 dholland (void) strlcpy(pbuf, line, sizeof(pbuf)); 223 1.4 christos else 224 1.10 dholland (void) vsnprintf(pbuf, sizeof(pbuf), line, ap); 225 1.4 christos if (flags.toplin == 1 && !strcmp(pbuf, toplines)) 226 1.4 christos return; 227 1.4 christos nscr(); /* %% */ 228 1.1 cgd 229 1.1 cgd /* If there is room on the line, print message on same line */ 230 1.1 cgd /* But messages like "You die..." deserve their own line */ 231 1.1 cgd n0 = strlen(bp); 232 1.4 christos if (flags.toplin == 1 && tly == 1 && 233 1.8 dholland n0 + (int)strlen(toplines) + 3 < CO - 8 && /* leave room for 234 1.4 christos * --More-- */ 235 1.1 cgd strncmp(bp, "You ", 4)) { 236 1.1 cgd (void) strcat(toplines, " "); 237 1.1 cgd (void) strcat(toplines, bp); 238 1.1 cgd tlx += 2; 239 1.1 cgd addtopl(bp); 240 1.1 cgd return; 241 1.1 cgd } 242 1.4 christos if (flags.toplin == 1) 243 1.4 christos more(); 244 1.1 cgd remember_topl(); 245 1.11 dholland dead = 0; 246 1.1 cgd toplines[0] = 0; 247 1.11 dholland while (n0 && !dead) { 248 1.4 christos if (n0 >= CO) { 249 1.1 cgd /* look for appropriate cut point */ 250 1.1 cgd n0 = 0; 251 1.4 christos for (n = 0; n < CO; n++) 252 1.4 christos if (bp[n] == ' ') 253 1.4 christos n0 = n; 254 1.4 christos if (!n0) 255 1.4 christos for (n = 0; n < CO - 1; n++) 256 1.4 christos if (!letter(bp[n])) 257 1.4 christos n0 = n; 258 1.4 christos if (!n0) 259 1.4 christos n0 = CO - 2; 260 1.1 cgd } 261 1.11 dholland tlpos = strlen(toplines); 262 1.11 dholland tl = toplines + tlpos; 263 1.11 dholland /* avoid overflow */ 264 1.11 dholland if (tlpos + n0 > (int)sizeof(toplines) - 1) { 265 1.11 dholland n0 = sizeof(toplines) - 1 - tlpos; 266 1.11 dholland dead = 1; 267 1.11 dholland } 268 1.11 dholland (void) memcpy(tl, bp, n0); 269 1.1 cgd tl[n0] = 0; 270 1.1 cgd bp += n0; 271 1.1 cgd 272 1.1 cgd /* remove trailing spaces, but leave one */ 273 1.4 christos while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ') 274 1.1 cgd tl[--n0] = 0; 275 1.1 cgd 276 1.1 cgd n0 = strlen(bp); 277 1.4 christos if (n0 && tl[0]) 278 1.11 dholland (void) strlcat(toplines, "\n", sizeof(toplines)); 279 1.1 cgd } 280 1.1 cgd redotoplin(); 281 1.1 cgd } 282 1.1 cgd 283 1.4 christos void 284 1.9 dholland putsym(int c1) 285 1.4 christos { 286 1.9 dholland char c = c1; /* XXX this hack prevents .o diffs -- remove later */ 287 1.9 dholland 288 1.4 christos switch (c) { 289 1.1 cgd case '\b': 290 1.1 cgd backsp(); 291 1.1 cgd return; 292 1.1 cgd case '\n': 293 1.1 cgd curx = 1; 294 1.1 cgd cury++; 295 1.4 christos if (cury > tly) 296 1.4 christos tly = cury; 297 1.1 cgd break; 298 1.1 cgd default: 299 1.4 christos if (curx == CO) 300 1.1 cgd putsym('\n'); /* 1 <= curx <= CO; avoid CO */ 301 1.1 cgd else 302 1.1 cgd curx++; 303 1.1 cgd } 304 1.1 cgd (void) putchar(c); 305 1.1 cgd } 306 1.1 cgd 307 1.4 christos void 308 1.9 dholland putstr(const char *s) 309 1.4 christos { 310 1.4 christos while (*s) 311 1.4 christos putsym(*s++); 312 1.1 cgd } 313