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