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