Eliminate addprintf.
[vms-empire.git] / term.c
1 /*
2  *    Copyright (C) 1987, 1988 Chuck Simmons
3  * 
4  * See the file COPYING, distributed with empire, for restriction
5  * and warranty information.
6  */
7
8 /*
9 term.c -- this file contains various routines used to control the
10 user communications area of the terminal.  This area consists of
11 the top 3 lines of the terminal where messages are displayed to the
12 user and input is acquired from the user.
13
14 There are two types of output in this area.  One type is interactive
15 output.  This consists of a prompt line and an error message line.
16 The other type of output is informational output.  The user must
17 be given time to read informational output.
18
19 Whenever input is received, the top three lines are cleared and the
20 screen refreshed as the user has had time to read these lines.  We
21 also clear the 'need_delay' flag, saying that the user has read the
22 information on the screen.
23
24 When information is to be displayed, if the 'need_delay' flag is set,
25 we refresh the screen and pause momentarily to give the user a chance
26 to read the lines.  The new information is then displayed, and the
27 'need_delay' flag is set.
28 */
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <curses.h>
34 #include <ctype.h>
35 #include <stdarg.h>
36
37 #include "empire.h"
38 #include "extern.h"
39
40 static bool need_delay;
41 static FILE *my_stream;
42
43 void
44 /* VARARGS1 */
45 pdebug(char *s, 
46        int a, int b, int c, int d, int e, int f, int g, int h)
47 {
48         if (!print_debug) return;
49         comment (s, a, b, c, d, e, f, g, h);
50 }
51
52 /*
53 Here are routines that handle printing to the top few lines of the
54 screen.  'topini' should be called at initialization, and whenever
55 we finish printing information to the screen.
56 */
57
58 void
59 topini(void)
60 {
61         info (0, 0, 0);
62 }
63 /*
64 Write a message to one of the top lines.
65 */
66
67 static void vtopmsg(int line, const char *fmt, va_list varglist)
68 /* assemble command in printf(3) style, print to a top line */
69 {
70         char junkbuf[STRSIZE];
71         
72         if (line < 1 || line > NUMTOPS)
73             line = 1;
74         (void) move (line - 1, 0);
75         vsprintf(junkbuf, fmt, varglist);
76         (void) addstr (junkbuf);
77         (void) clrtoeol();
78 }
79
80 void
81 topmsg(int line, char *fmt, ...)
82 {
83         va_list ap;
84
85         va_start(ap, fmt);
86         vtopmsg(line, fmt, ap);
87         va_end(ap);
88 }
89
90 void
91 topmsg1(int line, char *fmt, ...)
92 {
93         va_list ap;
94
95         va_start(ap, fmt);
96         vtopmsg(line, fmt, ap);
97         va_end(ap);
98 }
99
100 void
101 topmsg2(int line, char *fmt, ...) 
102 {
103         va_list ap;
104
105         va_start(ap, fmt);
106         vtopmsg(line, fmt, ap);
107         va_end(ap);
108 }
109
110 /*
111 Print a prompt on the first message line.
112 */
113
114 void
115 prompt(char *fmt, ...)
116 {
117         va_list ap;
118
119         va_start(ap, fmt);
120         vtopmsg(1, fmt, ap);
121         va_end(ap);
122 }
123
124 void
125 prompt1(char *fmt, ...)
126 {
127         va_list ap;
128
129         va_start(ap, fmt);
130         vtopmsg(1, fmt, ap);
131         va_end(ap);
132 }
133
134 void
135 prompt2 (char *fmt, ...)
136 {
137         va_list ap;
138
139         va_start(ap, fmt);
140         vtopmsg(1, fmt, ap);
141         va_end(ap);
142 }
143
144 /*
145 Print an error message on the second message line.
146 */
147
148 void
149 error(char *fmt, ...)
150 {
151         va_list ap;
152
153         va_start(ap, fmt);
154         vtopmsg(2, fmt, ap);
155         va_end(ap);
156 }
157
158 /*
159 Print out extra information.
160 */
161
162 void
163 extra(char *fmt, ...)
164 {
165         va_list ap;
166
167         va_start(ap, fmt);
168         vtopmsg(3, fmt, ap);
169         va_end(ap);
170 }
171
172
173 /*
174 Print out a generic error message.
175 */
176
177 void
178 huh(void)
179 {
180         error ("Type H for Help.");
181 }
182
183 /*
184 Display information on the screen.  If the 'need_delay' flag is set,
185 we force a delay, then print the information.  After we print the
186 information, we set the need_delay flag.
187 */
188
189 void
190 info(char *a, char *b, char *c)
191 {
192         if (need_delay) delay ();
193         topmsg (1, a);
194         topmsg (2, b);
195         topmsg (3, c);
196         need_delay = (a || b || c);
197 }
198
199 void
200 set_need_delay(void) {
201         need_delay = 1;
202 }
203
204 void
205 comment (char *fmt, ...)
206 {
207         va_list ap;
208
209         va_start(ap, fmt);
210         if (need_delay) delay ();
211         topmsg (1, "");
212         topmsg (2, "");
213         vtopmsg (3, fmt, ap);
214         need_delay = (fmt != 0);
215         va_end(ap);
216 }
217         
218 void
219 comment1 (char *fmt, ...)
220 {
221         va_list ap;
222
223         va_start(ap, fmt);
224         if (need_delay) delay ();
225         topmsg (1, "");
226         topmsg (2, "");
227         vtopmsg (3, fmt, ap);
228         need_delay = (fmt != 0);
229         va_end(ap);
230 }
231         
232         
233 /* kermyt begin */
234
235 void
236 vksend(const char *fmt, va_list varglist)
237 {
238         if(!(my_stream=fopen("info_list.txt","a")))
239         {
240                 error("Cannot open info_list.txt");
241                 return;
242         }
243         vfprintf(my_stream, fmt, varglist);
244         fclose(my_stream);
245         return;
246 }
247
248 void
249 ksend(char *fmt, ...)
250 {
251         va_list ap;
252
253         va_start(ap, fmt);
254         vksend(fmt, ap);
255         va_end(ap);
256 }
257
258 void
259 ksend1(char *fmt, ...)
260 {
261         va_list ap;
262
263         va_start(ap, fmt);
264         vksend(fmt, ap);
265         va_end(ap);
266 }
267 /* kermyt end */
268
269 /*
270 Get a string from the user, echoing characters all the while.
271 */
272
273 void
274 get_str(char *buf, int sizep)
275 {
276         (void) echo();
277         get_strq(buf, sizep);
278         (void) noecho();
279 }
280
281 /*
282 Get a string from the user, ignoring the current echo mode.
283 */
284
285 void
286 get_strq(char *buf, int sizep)
287 {
288         sizep = sizep; /* size of buf, currently unused */
289
290         (void) nocrmode ();
291         (void) refresh ();
292         (void) getstr (buf);
293         need_delay = false;
294         info (0, 0, 0);
295         (void) crmode ();
296 }
297
298 /*
299 Get a character from the user and convert it to uppercase.
300 */
301
302 char
303 get_chx(void)
304 {
305         char c;
306
307         c = get_cq ();
308
309         if (islower(c))
310                 return (toupper(c));
311         else
312                 return (c);
313 }
314
315 /*
316 Input an integer from the user.
317 */
318
319 int
320 getint(char *message)
321 {
322         char buf[STRSIZE];
323         char *p;
324
325         for (;;) { /* until we get a legal number */
326                 prompt (message,0,0,0,0,0,0,0,0);
327                 get_str (buf, sizeof (buf));
328                 
329                 for (p = buf; *p; p++) {
330                         if (*p < '0' || *p > '9') {
331                                 error ("Please enter an integer.",0,0,0,0,0,0,0,0);
332                                 break;
333                         }
334                 }
335                 if (*p == 0) { /* no error yet? */
336                         if (p - buf > 7) /* too many digits? */
337                                 error ("Please enter a small integer.",0,0,0,0,0,0,0,0);
338                         else return (atoi (buf));
339                 }
340         }
341 }
342
343 /*
344 Input a character from the user with echoing.
345 */
346
347 char
348 get_c(void)
349 {
350         char c; /* one char and a null */
351
352         (void) echo ();
353         c = get_cq ();
354         (void) noecho ();
355         return (c);
356 }
357
358 /*
359 Input a character quietly.
360 */
361
362 char
363 get_cq(void)
364 {
365         char c;
366
367         (void) crmode ();
368         (void) refresh ();
369         c = getch ();
370         topini (); /* clear information lines */
371         (void) nocrmode ();
372         return (c);
373 }
374
375 /*
376 Input a yes or no response from the user.  We loop until we get
377 a valid response.  We return true iff the user replies 'y'.
378 */
379
380 bool
381 getyn(char *message)
382 {
383         char c;
384
385         for (;;) {
386                 prompt (message,0,0,0,0,0,0,0,0);
387                 c = get_chx ();
388
389                 if (c == 'Y') return (true);
390                 if (c == 'N') return (false);
391
392                 error ("Please answer Y or N.",0,0,0,0,0,0,0,0);
393         }
394 }
395
396 /*
397 Input an integer in a range.
398 */
399
400 int
401 get_range(char *message, int low, int high)
402 {
403         int result;
404
405         for (;;) {
406                 result = getint (message);
407
408                 if (result >= low && result <= high) return (result);
409
410                 error ("Please enter an integer in the range %d..%d.",low, high,0,0,0,0,0,0);
411         }
412 }
413
414 /*
415 Print a screen of help information.
416 */
417
418 void
419 help(char **text, int nlines)
420 {
421         int i, r, c;
422         int text_lines;
423
424         text_lines = (nlines + 1) / 2; /* lines of text */
425
426         clear_screen ();
427
428         pos_str (NUMTOPS, 1, text[0],0,0,0,0,0,0,0,0); /* mode */
429         pos_str (NUMTOPS, 41, "See empire(6) for more information.",0,0,0,0,0,0,0,0);
430
431         for (i = 1; i < nlines; i++) {
432                 if (i > text_lines)
433                         pos_str (i - text_lines + NUMTOPS + 1, 41, text[i],0,0,0,0,0,0,0,0);
434                 else pos_str (i + NUMTOPS + 1, 1, text[i],0,0,0,0,0,0,0,0);
435         }
436
437         pos_str (text_lines + NUMTOPS + 2,  1, "--Piece---Yours-Enemy-Moves-Hits-Cost",0,0,0,0,0,0,0,0);
438         pos_str (text_lines + NUMTOPS + 2, 41, "--Piece---Yours-Enemy-Moves-Hits-Cost",0,0,0,0,0,0,0,0);
439
440         for (i = 0; i < NUM_OBJECTS; i++) {
441                 if (i >= (NUM_OBJECTS+1)/2) {
442                         r = i - (NUM_OBJECTS+1)/2;
443                         c = 41;
444                 }
445                 else {
446                         r = i;
447                         c = 1;
448                 }
449                 pos_str1 (r + text_lines + NUMTOPS + 3, c,"%-12s%c     %c%6d%5d%6d",
450                         piece_attr[i].nickname,
451                         piece_attr[i].sname,
452                         tolower (piece_attr[i].sname),
453                         piece_attr[i].speed,
454                         piece_attr[i].max_hits,
455                         piece_attr[i].build_time,0,0);          //FLAG
456
457         }
458         (void) refresh ();
459 }
460
461 #define COL_DIGITS ((MAP_WIDTH <= 100) ? 2 : ((MAP_WIDTH <= 1000 ? 3 : (1 / 0))))
462
463 int
464 loc_disp(int loc)
465 {
466   int row = loc / MAP_WIDTH;
467   int nrow = row;
468   int col = loc % MAP_WIDTH;
469   ASSERT (loc == (row * MAP_WIDTH) + col);
470   int i;
471   for (i = COL_DIGITS; i > 0; i--) {
472     nrow *= 10; }
473   move (LINES - 1, 0);
474   return nrow + col;
475 }