1 /* $NetBSD: hack.topl.c,v 1.12 2009/08/12 07:28:41 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.12 2009/08/12 07:28:41 dholland Exp $"); 67 #endif /* not lint */ 68 69 #include <stdlib.h> 70 #include "hack.h" 71 #include "extern.h" 72 73 static char toplines[BUFSZ]; 74 static xchar tlx, tly; /* set by pline; used by addtopl */ 75 76 static 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 static void redotoplin(void); 83 static void xmore(const char *); 84 85 int 86 doredotopl(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 99 static void 100 redotoplin(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 114 void 115 remember_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 = (struct topl *) 127 alloc((unsigned) (strlen(toplines) + sizeof(struct topl) + 1)); 128 tl->next_topl = old_toplines; 129 tl->topl_text = (char *) (tl + 1); 130 (void) strcpy(tl->topl_text, toplines); 131 old_toplines = tl; 132 while (cnt && tl) { 133 cnt--; 134 tl = tl->next_topl; 135 } 136 if (tl && tl->next_topl) { 137 free((char *) tl->next_topl); 138 tl->next_topl = 0; 139 } 140 } 141 142 void 143 addtopl(const char *s) 144 { 145 curs(tlx, tly); 146 if (tlx + (int)strlen(s) > CO) 147 putsym('\n'); 148 putstr(s); 149 tlx = curx; 150 tly = cury; 151 flags.toplin = 1; 152 } 153 154 /* s = allowed chars besides space/return */ 155 static void 156 xmore(const char *s) 157 { 158 if (flags.toplin) { 159 curs(tlx, tly); 160 if (tlx + 8 > CO) 161 putsym('\n'), tly++; 162 } 163 if (flags.standout) 164 standoutbeg(); 165 putstr("--More--"); 166 if (flags.standout) 167 standoutend(); 168 169 xwaitforspace(s); 170 if (flags.toplin && tly > 1) { 171 home(); 172 cl_end(); 173 docorner(1, tly - 1); 174 } 175 flags.toplin = 0; 176 } 177 178 void 179 more(void) 180 { 181 xmore(""); 182 } 183 184 void 185 cmore(const char *s) 186 { 187 xmore(s); 188 } 189 190 void 191 clrlin(void) 192 { 193 if (flags.toplin) { 194 home(); 195 cl_end(); 196 if (tly > 1) 197 docorner(1, tly - 1); 198 remember_topl(); 199 } 200 flags.toplin = 0; 201 } 202 203 void 204 pline(const char *fmt, ...) 205 { 206 va_list ap; 207 208 va_start(ap, fmt); 209 vpline(fmt, ap); 210 va_end(ap); 211 } 212 213 void 214 vpline(const char *line, va_list ap) 215 { 216 char pbuf[BUFSZ]; 217 char *bp = pbuf, *tl; 218 int n, n0, tlpos, dead; 219 220 if (!line || !*line) 221 return; 222 if (!strchr(line, '%')) 223 (void) strlcpy(pbuf, line, sizeof(pbuf)); 224 else 225 (void) vsnprintf(pbuf, sizeof(pbuf), line, ap); 226 if (flags.toplin == 1 && !strcmp(pbuf, toplines)) 227 return; 228 nscr(); /* %% */ 229 230 /* If there is room on the line, print message on same line */ 231 /* But messages like "You die..." deserve their own line */ 232 n0 = strlen(bp); 233 if (flags.toplin == 1 && tly == 1 && 234 n0 + (int)strlen(toplines) + 3 < CO - 8 && /* leave room for 235 * --More-- */ 236 strncmp(bp, "You ", 4)) { 237 (void) strcat(toplines, " "); 238 (void) strcat(toplines, bp); 239 tlx += 2; 240 addtopl(bp); 241 return; 242 } 243 if (flags.toplin == 1) 244 more(); 245 remember_topl(); 246 dead = 0; 247 toplines[0] = 0; 248 while (n0 && !dead) { 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 tlpos = strlen(toplines); 263 tl = toplines + tlpos; 264 /* avoid overflow */ 265 if (tlpos + n0 > (int)sizeof(toplines) - 1) { 266 n0 = sizeof(toplines) - 1 - tlpos; 267 dead = 1; 268 } 269 (void) memcpy(tl, bp, n0); 270 tl[n0] = 0; 271 bp += n0; 272 273 /* remove trailing spaces, but leave one */ 274 while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ') 275 tl[--n0] = 0; 276 277 n0 = strlen(bp); 278 if (n0 && tl[0]) 279 (void) strlcat(toplines, "\n", sizeof(toplines)); 280 } 281 redotoplin(); 282 } 283 284 void 285 putsym(int c1) 286 { 287 char c = c1; /* XXX this hack prevents .o diffs -- remove later */ 288 289 switch (c) { 290 case '\b': 291 backsp(); 292 return; 293 case '\n': 294 curx = 1; 295 cury++; 296 if (cury > tly) 297 tly = cury; 298 break; 299 default: 300 if (curx == CO) 301 putsym('\n'); /* 1 <= curx <= CO; avoid CO */ 302 else 303 curx++; 304 } 305 (void) putchar(c); 306 } 307 308 void 309 putstr(const char *s) 310 { 311 while (*s) 312 putsym(*s++); 313 } 314