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