1 /* $OpenBSD: hack.topl.c,v 1.9 2009/10/27 23:59:25 deraadt 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 <stdarg.h> 66 #include <stdlib.h> 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() 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() 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() 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((char *) 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() 177 { 178 xmore(""); 179 } 180 181 void 182 cmore(char *s) 183 { 184 xmore(s); 185 } 186 187 void 188 clrlin() 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 /*VARARGS1*/ 200 void 201 pline(char *line, ...) 202 { 203 char pbuf[BUFSZ]; 204 char *bp = pbuf, *tl; 205 int n,n0; 206 va_list ap; 207 208 if(!line || !*line) return; 209 va_start(ap, line); 210 (void) vsnprintf(pbuf, sizeof pbuf, line, ap); 211 va_end(ap); 212 if(flags.toplin == 1 && !strcmp(pbuf, toplines)) return; 213 nscr(); /* %% */ 214 215 /* If there is room on the line, print message on same line */ 216 /* But messages like "You die..." deserve their own line */ 217 n0 = strlen(bp); 218 if(flags.toplin == 1 && tly == 1 && 219 n0 + strlen(toplines) + 3 < CO-8 && /* leave room for --More-- */ 220 strncmp(bp, "You ", 4)) { 221 (void) strlcat(toplines, " ", sizeof toplines); 222 (void) strlcat(toplines, bp, sizeof toplines); 223 tlx += 2; 224 addtopl(bp); 225 return; 226 } 227 if(flags.toplin == 1) more(); 228 remember_topl(); 229 toplines[0] = 0; 230 while(n0){ 231 if(n0 >= CO){ 232 /* look for appropriate cut point */ 233 n0 = 0; 234 for(n = 0; n < CO; n++) if(bp[n] == ' ') 235 n0 = n; 236 if(!n0) for(n = 0; n < CO-1; n++) 237 if(!letter(bp[n])) n0 = n; 238 if(!n0) n0 = CO-2; 239 } 240 (void) strncpy((tl = eos(toplines)), bp, n0); 241 tl[n0] = '\0'; 242 bp += n0; 243 244 /* remove trailing spaces, but leave one */ 245 while(n0 > 1 && tl[n0-1] == ' ' && tl[n0-2] == ' ') 246 tl[--n0] = 0; 247 248 n0 = strlen(bp); 249 if(n0 && tl[0]) 250 (void) strlcat(tl, "\n", 251 toplines + sizeof toplines - tl); 252 } 253 redotoplin(); 254 } 255 256 void 257 putsym(char c) 258 { 259 switch(c) { 260 case '\b': 261 backsp(); 262 return; 263 case '\n': 264 curx = 1; 265 cury++; 266 if(cury > tly) tly = cury; 267 break; 268 default: 269 if(curx == CO) 270 putsym('\n'); /* 1 <= curx <= CO; avoid CO */ 271 else 272 curx++; 273 } 274 (void) putchar(c); 275 } 276 277 void 278 putstr(char *s) 279 { 280 while(*s) putsym(*s++); 281 } 282