1 /* $NetBSD: hack.topl.c,v 1.7 2003/04/02 18:36:41 jsm 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.7 2003/04/02 18:36:41 jsm Exp $"); 67 #endif /* not lint */ 68 69 #include <stdlib.h> 70 #include "hack.h" 71 #include "extern.h" 72 73 char toplines[BUFSZ]; 74 xchar tlx, tly; /* set by pline; used by addtopl */ 75 76 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 82 int 83 doredotopl() 84 { 85 if (last_redone_topl) 86 last_redone_topl = last_redone_topl->next_topl; 87 if (!last_redone_topl) 88 last_redone_topl = old_toplines; 89 if (last_redone_topl) { 90 (void) strcpy(toplines, last_redone_topl->topl_text); 91 } 92 redotoplin(); 93 return (0); 94 } 95 96 void 97 redotoplin() 98 { 99 home(); 100 if (strchr(toplines, '\n')) 101 cl_end(); 102 putstr(toplines); 103 cl_end(); 104 tlx = curx; 105 tly = cury; 106 flags.toplin = 1; 107 if (tly > 1) 108 more(); 109 } 110 111 void 112 remember_topl() 113 { 114 struct topl *tl; 115 int cnt = OTLMAX; 116 if (last_redone_topl && 117 !strcmp(toplines, last_redone_topl->topl_text)) 118 return; 119 if (old_toplines && 120 !strcmp(toplines, old_toplines->topl_text)) 121 return; 122 last_redone_topl = 0; 123 tl = (struct topl *) 124 alloc((unsigned) (strlen(toplines) + sizeof(struct topl) + 1)); 125 tl->next_topl = old_toplines; 126 tl->topl_text = (char *) (tl + 1); 127 (void) strcpy(tl->topl_text, toplines); 128 old_toplines = tl; 129 while (cnt && tl) { 130 cnt--; 131 tl = tl->next_topl; 132 } 133 if (tl && tl->next_topl) { 134 free((char *) tl->next_topl); 135 tl->next_topl = 0; 136 } 137 } 138 139 void 140 addtopl(s) 141 const char *s; 142 { 143 curs(tlx, tly); 144 if (tlx + strlen(s) > CO) 145 putsym('\n'); 146 putstr(s); 147 tlx = curx; 148 tly = cury; 149 flags.toplin = 1; 150 } 151 152 void 153 xmore(s) 154 const char *s; /* allowed chars besides space/return */ 155 { 156 if (flags.toplin) { 157 curs(tlx, tly); 158 if (tlx + 8 > CO) 159 putsym('\n'), tly++; 160 } 161 if (flags.standout) 162 standoutbeg(); 163 putstr("--More--"); 164 if (flags.standout) 165 standoutend(); 166 167 xwaitforspace(s); 168 if (flags.toplin && tly > 1) { 169 home(); 170 cl_end(); 171 docorner(1, tly - 1); 172 } 173 flags.toplin = 0; 174 } 175 176 void 177 more() 178 { 179 xmore(""); 180 } 181 182 void 183 cmore(s) 184 const char *s; 185 { 186 xmore(s); 187 } 188 189 void 190 clrlin() 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 202 void 203 pline(const char *fmt, ...) 204 { 205 va_list ap; 206 207 va_start(ap, fmt); 208 vpline(fmt, ap); 209 va_end(ap); 210 } 211 212 void 213 vpline(line, ap) 214 const char *line; 215 va_list ap; 216 { 217 char pbuf[BUFSZ]; 218 char *bp = pbuf, *tl; 219 int n, n0; 220 221 if (!line || !*line) 222 return; 223 if (!strchr(line, '%')) 224 (void) strcpy(pbuf, line); 225 else 226 (void) vsprintf(pbuf, line, ap); 227 if (flags.toplin == 1 && !strcmp(pbuf, toplines)) 228 return; 229 nscr(); /* %% */ 230 231 /* If there is room on the line, print message on same line */ 232 /* But messages like "You die..." deserve their own line */ 233 n0 = strlen(bp); 234 if (flags.toplin == 1 && tly == 1 && 235 n0 + strlen(toplines) + 3 < CO - 8 && /* leave room for 236 * --More-- */ 237 strncmp(bp, "You ", 4)) { 238 (void) strcat(toplines, " "); 239 (void) strcat(toplines, bp); 240 tlx += 2; 241 addtopl(bp); 242 return; 243 } 244 if (flags.toplin == 1) 245 more(); 246 remember_topl(); 247 toplines[0] = 0; 248 while (n0) { 249 if (n0 >= CO) { 250 /* look for appropriate cut point */ 251 n0 = 0; 252 for (n = 0; n < CO; n++) 253 if (bp[n] == ' ') 254 n0 = n; 255 if (!n0) 256 for (n = 0; n < CO - 1; n++) 257 if (!letter(bp[n])) 258 n0 = n; 259 if (!n0) 260 n0 = CO - 2; 261 } 262 (void) strncpy((tl = eos(toplines)), bp, n0); 263 tl[n0] = 0; 264 bp += n0; 265 266 /* remove trailing spaces, but leave one */ 267 while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ') 268 tl[--n0] = 0; 269 270 n0 = strlen(bp); 271 if (n0 && tl[0]) 272 (void) strcat(tl, "\n"); 273 } 274 redotoplin(); 275 } 276 277 void 278 putsym(c) 279 char c; 280 { 281 switch (c) { 282 case '\b': 283 backsp(); 284 return; 285 case '\n': 286 curx = 1; 287 cury++; 288 if (cury > tly) 289 tly = cury; 290 break; 291 default: 292 if (curx == CO) 293 putsym('\n'); /* 1 <= curx <= CO; avoid CO */ 294 else 295 curx++; 296 } 297 (void) putchar(c); 298 } 299 300 void 301 putstr(s) 302 const char *s; 303 { 304 while (*s) 305 putsym(*s++); 306 } 307