1 /* $NetBSD: hack.topl.c,v 1.6 2002/05/26 00:12:12 wiz Exp $ */ 2 3 /* 4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. 5 */ 6 7 #include <sys/cdefs.h> 8 #ifndef lint 9 __RCSID("$NetBSD: hack.topl.c,v 1.6 2002/05/26 00:12:12 wiz Exp $"); 10 #endif /* not lint */ 11 12 #include <stdlib.h> 13 #include "hack.h" 14 #include "extern.h" 15 16 char toplines[BUFSZ]; 17 xchar tlx, tly; /* set by pline; used by addtopl */ 18 19 struct topl { 20 struct topl *next_topl; 21 char *topl_text; 22 } *old_toplines, *last_redone_topl; 23 #define OTLMAX 20 /* max nr of old toplines remembered */ 24 25 int 26 doredotopl() 27 { 28 if (last_redone_topl) 29 last_redone_topl = last_redone_topl->next_topl; 30 if (!last_redone_topl) 31 last_redone_topl = old_toplines; 32 if (last_redone_topl) { 33 (void) strcpy(toplines, last_redone_topl->topl_text); 34 } 35 redotoplin(); 36 return (0); 37 } 38 39 void 40 redotoplin() 41 { 42 home(); 43 if (strchr(toplines, '\n')) 44 cl_end(); 45 putstr(toplines); 46 cl_end(); 47 tlx = curx; 48 tly = cury; 49 flags.toplin = 1; 50 if (tly > 1) 51 more(); 52 } 53 54 void 55 remember_topl() 56 { 57 struct topl *tl; 58 int cnt = OTLMAX; 59 if (last_redone_topl && 60 !strcmp(toplines, last_redone_topl->topl_text)) 61 return; 62 if (old_toplines && 63 !strcmp(toplines, old_toplines->topl_text)) 64 return; 65 last_redone_topl = 0; 66 tl = (struct topl *) 67 alloc((unsigned) (strlen(toplines) + sizeof(struct topl) + 1)); 68 tl->next_topl = old_toplines; 69 tl->topl_text = (char *) (tl + 1); 70 (void) strcpy(tl->topl_text, toplines); 71 old_toplines = tl; 72 while (cnt && tl) { 73 cnt--; 74 tl = tl->next_topl; 75 } 76 if (tl && tl->next_topl) { 77 free((char *) tl->next_topl); 78 tl->next_topl = 0; 79 } 80 } 81 82 void 83 addtopl(s) 84 const char *s; 85 { 86 curs(tlx, tly); 87 if (tlx + strlen(s) > CO) 88 putsym('\n'); 89 putstr(s); 90 tlx = curx; 91 tly = cury; 92 flags.toplin = 1; 93 } 94 95 void 96 xmore(s) 97 const char *s; /* allowed chars besides space/return */ 98 { 99 if (flags.toplin) { 100 curs(tlx, tly); 101 if (tlx + 8 > CO) 102 putsym('\n'), tly++; 103 } 104 if (flags.standout) 105 standoutbeg(); 106 putstr("--More--"); 107 if (flags.standout) 108 standoutend(); 109 110 xwaitforspace(s); 111 if (flags.toplin && tly > 1) { 112 home(); 113 cl_end(); 114 docorner(1, tly - 1); 115 } 116 flags.toplin = 0; 117 } 118 119 void 120 more() 121 { 122 xmore(""); 123 } 124 125 void 126 cmore(s) 127 const char *s; 128 { 129 xmore(s); 130 } 131 132 void 133 clrlin() 134 { 135 if (flags.toplin) { 136 home(); 137 cl_end(); 138 if (tly > 1) 139 docorner(1, tly - 1); 140 remember_topl(); 141 } 142 flags.toplin = 0; 143 } 144 145 void 146 pline(const char *fmt, ...) 147 { 148 va_list ap; 149 150 va_start(ap, fmt); 151 vpline(fmt, ap); 152 va_end(ap); 153 } 154 155 void 156 vpline(line, ap) 157 const char *line; 158 va_list ap; 159 { 160 char pbuf[BUFSZ]; 161 char *bp = pbuf, *tl; 162 int n, n0; 163 164 if (!line || !*line) 165 return; 166 if (!strchr(line, '%')) 167 (void) strcpy(pbuf, line); 168 else 169 (void) vsprintf(pbuf, line, ap); 170 if (flags.toplin == 1 && !strcmp(pbuf, toplines)) 171 return; 172 nscr(); /* %% */ 173 174 /* If there is room on the line, print message on same line */ 175 /* But messages like "You die..." deserve their own line */ 176 n0 = strlen(bp); 177 if (flags.toplin == 1 && tly == 1 && 178 n0 + strlen(toplines) + 3 < CO - 8 && /* leave room for 179 * --More-- */ 180 strncmp(bp, "You ", 4)) { 181 (void) strcat(toplines, " "); 182 (void) strcat(toplines, bp); 183 tlx += 2; 184 addtopl(bp); 185 return; 186 } 187 if (flags.toplin == 1) 188 more(); 189 remember_topl(); 190 toplines[0] = 0; 191 while (n0) { 192 if (n0 >= CO) { 193 /* look for appropriate cut point */ 194 n0 = 0; 195 for (n = 0; n < CO; n++) 196 if (bp[n] == ' ') 197 n0 = n; 198 if (!n0) 199 for (n = 0; n < CO - 1; n++) 200 if (!letter(bp[n])) 201 n0 = n; 202 if (!n0) 203 n0 = CO - 2; 204 } 205 (void) strncpy((tl = eos(toplines)), bp, n0); 206 tl[n0] = 0; 207 bp += n0; 208 209 /* remove trailing spaces, but leave one */ 210 while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ') 211 tl[--n0] = 0; 212 213 n0 = strlen(bp); 214 if (n0 && tl[0]) 215 (void) strcat(tl, "\n"); 216 } 217 redotoplin(); 218 } 219 220 void 221 putsym(c) 222 char c; 223 { 224 switch (c) { 225 case '\b': 226 backsp(); 227 return; 228 case '\n': 229 curx = 1; 230 cury++; 231 if (cury > tly) 232 tly = cury; 233 break; 234 default: 235 if (curx == CO) 236 putsym('\n'); /* 1 <= curx <= CO; avoid CO */ 237 else 238 curx++; 239 } 240 (void) putchar(c); 241 } 242 243 void 244 putstr(s) 245 const char *s; 246 { 247 while (*s) 248 putsym(*s++); 249 } 250