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 } 31 redotoplin(); 32 return(0); 33 } 34 35 static void 36 redotoplin(void) 37 { 38 home(); 39 if(index(toplines, '\n')) 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 if(last_redone_topl && 55 !strcmp(toplines, last_redone_topl->topl_text)) return; 56 if(old_toplines && 57 !strcmp(toplines, old_toplines->topl_text)) return; 58 last_redone_topl = 0; 59 tl = (struct topl *) 60 alloc((unsigned)(strlen(toplines) + sizeof(struct topl) + 1)); 61 tl->next_topl = old_toplines; 62 tl->topl_text = (char *)(tl + 1); 63 strcpy(tl->topl_text, toplines); 64 old_toplines = tl; 65 while(cnt && tl){ 66 cnt--; 67 tl = tl->next_topl; 68 } 69 if(tl && tl->next_topl){ 70 free((char *) tl->next_topl); 71 tl->next_topl = 0; 72 } 73 } 74 75 void 76 addtopl(const char *s) 77 { 78 curs(tlx,tly); 79 if(tlx + (int)strlen(s) > CO) putsym('\n'); 80 putstr(s); 81 tlx = curx; 82 tly = cury; 83 flags.toplin = 1; 84 } 85 86 static void 87 xmore(const char *s) /* allowed chars besides space/return */ 88 { 89 if(flags.toplin) { 90 curs(tlx, tly); 91 if(tlx + 8 > CO) putsym('\n'), tly++; 92 } 93 94 if(flags.standout) 95 standoutbeg(); 96 putstr("--More--"); 97 if(flags.standout) 98 standoutend(); 99 100 xwaitforspace(s); 101 if(flags.toplin && tly > 1) { 102 home(); 103 cl_end(); 104 docorner(1, tly-1); 105 } 106 flags.toplin = 0; 107 } 108 109 void 110 more(void) 111 { 112 xmore(""); 113 } 114 115 void 116 cmore(const char *s) 117 { 118 xmore(s); 119 } 120 121 void 122 clrlin(void) 123 { 124 if(flags.toplin) { 125 home(); 126 cl_end(); 127 if(tly > 1) docorner(1, tly-1); 128 remember_topl(); 129 } 130 flags.toplin = 0; 131 } 132 133 void 134 pline(const char *line, ...) 135 { 136 va_list ap; 137 va_start(ap, line); 138 vpline(line, ap); 139 va_end(ap); 140 } 141 142 /*VARARGS1*/ 143 void 144 vpline(const char *line, va_list ap) 145 { 146 char pbuf[BUFSZ]; 147 char *bp = pbuf, *tl; 148 int n,n0; 149 150 if(!line || !*line) return; 151 if(!index(line, '%')) strcpy(pbuf,line); else 152 vsprintf(pbuf, line, ap); 153 if(flags.toplin == 1 && !strcmp(pbuf, toplines)) return; 154 nscr(); /* %% */ 155 156 /* If there is room on the line, print message on same line */ 157 /* But messages like "You die..." deserve their own line */ 158 n0 = strlen(bp); 159 if(flags.toplin == 1 && tly == 1 && 160 n0 + (int)strlen(toplines) + 3 < CO-8 && /* room for --More-- */ 161 strncmp(bp, "You ", 4)) { 162 strcat(toplines, " "); 163 strcat(toplines, bp); 164 tlx += 2; 165 addtopl(bp); 166 return; 167 } 168 if(flags.toplin == 1) more(); 169 remember_topl(); 170 toplines[0] = 0; 171 while(n0){ 172 if(n0 >= CO){ 173 /* look for appropriate cut point */ 174 n0 = 0; 175 for(n = 0; n < CO; n++) if(bp[n] == ' ') 176 n0 = n; 177 if(!n0) for(n = 0; n < CO-1; n++) 178 if(!letter(bp[n])) n0 = n; 179 if(!n0) n0 = CO-2; 180 } 181 strncpy((tl = eos(toplines)), bp, n0); 182 tl[n0] = 0; 183 bp += n0; 184 185 /* remove trailing spaces, but leave one */ 186 while(n0 > 1 && tl[n0-1] == ' ' && tl[n0-2] == ' ') 187 tl[--n0] = 0; 188 189 n0 = strlen(bp); 190 if(n0 && tl[0]) strcat(tl, "\n"); 191 } 192 redotoplin(); 193 } 194 195 void 196 putsym(char c) 197 { 198 switch(c) { 199 case '\b': 200 backsp(); 201 return; 202 case '\n': 203 curx = 1; 204 cury++; 205 if(cury > tly) tly = cury; 206 break; 207 default: 208 if(curx == CO) 209 putsym('\n'); /* 1 <= curx <= CO; avoid CO */ 210 else 211 curx++; 212 } 213 putchar(c); 214 } 215 216 void 217 putstr(const char *s) 218 { 219 while(*s) putsym(*s++); 220 } 221