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