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