7c09de61e626ca4d8de225d4c178e32c2a59921a
[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 /*
44 Here are routines that handle printing to the top few lines of the
45 screen.  'topini' should be called at initialization, and whenever
46 we finish printing information to the screen.
47 */
48
49 void
50 topini(void)
51 {
52         info (0, 0, 0);
53 }
54 /*
55 Write a message to one of the top lines.
56 */
57
58 static void vtopmsg(int line, const char *fmt, va_list varglist)
59 /* assemble command in printf(3) style, print to a top line */
60 {
61         char junkbuf[STRSIZE];
62         
63         if (line < 1 || line > NUMTOPS)
64             line = 1;
65         (void) move (line - 1, 0);
66         vsprintf(junkbuf, fmt, varglist);
67         (void) addstr (junkbuf);
68         (void) clrtoeol();
69 }
70
71 void
72 topmsg(int line, char *fmt, ...)
73 {
74         va_list ap;
75
76         va_start(ap, fmt);
77         vtopmsg(line, fmt, ap);
78         va_end(ap);
79 }
80
81 /*
82 Print a prompt on the first message line.
83 */
84
85 void
86 prompt(char *fmt, ...)
87 {
88         va_list ap;
89
90         va_start(ap, fmt);
91         vtopmsg(1, fmt, ap);
92         va_end(ap);
93 }
94
95 /*
96 Print an error message on the second message line.
97 */
98
99 void
100 error(char *fmt, ...)
101 {
102         va_list ap;
103
104         va_start(ap, fmt);
105         vtopmsg(2, fmt, ap);
106         va_end(ap);
107 }
108
109 /*
110 Print out extra information.
111 */
112
113 void
114 extra(char *fmt, ...)
115 {
116         va_list ap;
117
118         va_start(ap, fmt);
119         vtopmsg(3, fmt, ap);
120         va_end(ap);
121 }
122
123
124 /*
125 Print out a generic error message.
126 */
127
128 void
129 huh(void)
130 {
131         error ("Type H for Help.");
132 }
133
134 /*
135 Display information on the screen.  If the 'need_delay' flag is set,
136 we force a delay, then print the information.  After we print the
137 information, we set the need_delay flag.
138 */
139
140 void
141 info(char *a, char *b, char *c)
142 {
143         if (need_delay) delay ();
144         topmsg (1, a);
145         topmsg (2, b);
146         topmsg (3, c);
147         need_delay = (a || b || c);
148 }
149
150 void
151 set_need_delay(void) {
152         need_delay = 1;
153 }
154
155 void
156 comment (char *fmt, ...)
157 {
158         va_list ap;
159
160         va_start(ap, fmt);
161         if (need_delay) delay ();
162         topmsg (1, "");
163         topmsg (2, "");
164         vtopmsg (3, fmt, ap);
165         need_delay = (fmt != 0);
166         va_end(ap);
167 }
168         
169 void
170 pdebug(char *fmt, ...)
171 {
172         va_list ap;
173
174         if (!print_debug) return;
175
176         va_start(ap, fmt);
177         if (need_delay) delay ();
178         topmsg (1, "");
179         topmsg (2, "");
180         vtopmsg (3, fmt, ap);
181         need_delay = (fmt != 0);
182         va_end(ap);
183 }
184
185 /* kermyt begin */
186
187 void
188 vksend(const char *fmt, va_list varglist)
189 {
190         if(!(my_stream=fopen("info_list.txt","a")))
191         {
192                 error("Cannot open info_list.txt");
193                 return;
194         }
195         vfprintf(my_stream, fmt, varglist);
196         fclose(my_stream);
197         return;
198 }
199
200 void
201 ksend(char *fmt, ...)
202 {
203         va_list ap;
204
205         va_start(ap, fmt);
206         vksend(fmt, ap);
207         va_end(ap);
208 }
209 /* kermyt end */
210
211 /*
212 Get a string from the user, echoing characters all the while.
213 */
214
215 void
216 get_str(char *buf, int sizep)
217 {
218         (void) echo();
219         get_strq(buf, sizep);
220         (void) noecho();
221 }
222
223 /*
224 Get a string from the user, ignoring the current echo mode.
225 */
226
227 void
228 get_strq(char *buf, int sizep)
229 {
230         sizep = sizep; /* size of buf, currently unused */
231
232         (void) nocrmode ();
233         (void) refresh ();
234         (void) getstr (buf);
235         need_delay = false;
236         info (0, 0, 0);
237         (void) crmode ();
238 }
239
240 /*
241 Get a character from the user and convert it to uppercase.
242 */
243
244 char
245 get_chx(void)
246 {
247         char c;
248
249         c = get_cq ();
250
251         if (islower(c))
252                 return (toupper(c));
253         else
254                 return (c);
255 }
256
257 /*
258 Input an integer from the user.
259 */
260
261 int
262 getint(char *message)
263 {
264         char buf[STRSIZE];
265         char *p;
266
267         for (;;) { /* until we get a legal number */
268                 prompt (message,0,0,0,0,0,0,0,0);
269                 get_str (buf, sizeof (buf));
270                 
271                 for (p = buf; *p; p++) {
272                         if (*p < '0' || *p > '9') {
273                                 error ("Please enter an integer.",0,0,0,0,0,0,0,0);
274                                 break;
275                         }
276                 }
277                 if (*p == 0) { /* no error yet? */
278                         if (p - buf > 7) /* too many digits? */
279                                 error ("Please enter a small integer.",0,0,0,0,0,0,0,0);
280                         else return (atoi (buf));
281                 }
282         }
283 }
284
285 /*
286 Input a character from the user with echoing.
287 */
288
289 char
290 get_c(void)
291 {
292         char c; /* one char and a null */
293
294         (void) echo ();
295         c = get_cq ();
296         (void) noecho ();
297         return (c);
298 }
299
300 /*
301 Input a character quietly.
302 */
303
304 char
305 get_cq(void)
306 {
307         char c;
308
309         (void) crmode ();
310         (void) refresh ();
311         c = getch ();
312         topini (); /* clear information lines */
313         (void) nocrmode ();
314         return (c);
315 }
316
317 /*
318 Input a yes or no response from the user.  We loop until we get
319 a valid response.  We return true iff the user replies 'y'.
320 */
321
322 bool
323 getyn(char *message)
324 {
325         char c;
326
327         for (;;) {
328                 prompt (message,0,0,0,0,0,0,0,0);
329                 c = get_chx ();
330
331                 if (c == 'Y') return (true);
332                 if (c == 'N') return (false);
333
334                 error ("Please answer Y or N.",0,0,0,0,0,0,0,0);
335         }
336 }
337
338 /*
339 Input an integer in a range.
340 */
341
342 int
343 get_range(char *message, int low, int high)
344 {
345         int result;
346
347         for (;;) {
348                 result = getint (message);
349
350                 if (result >= low && result <= high) return (result);
351
352                 error ("Please enter an integer in the range %d..%d.",low, high);
353         }
354 }
355
356 /*
357 Print a screen of help information.
358 */
359
360 void
361 help(char **text, int nlines)
362 {
363         int i, r, c;
364         int text_lines;
365
366         text_lines = (nlines + 1) / 2; /* lines of text */
367
368         clear_screen ();
369
370         pos_str (NUMTOPS, 1, text[0]); /* mode */
371         pos_str (NUMTOPS, 41, "See empire(6) for more information.");
372
373         for (i = 1; i < nlines; i++) {
374                 if (i > text_lines)
375                         pos_str (i - text_lines + NUMTOPS + 1, 41, text[i]);
376                 else pos_str (i + NUMTOPS + 1, 1, text[i]);
377         }
378
379         pos_str (text_lines + NUMTOPS + 2,  1, "--Piece---Yours-Enemy-Moves-Hits-Cost");
380         pos_str (text_lines + NUMTOPS + 2, 41, "--Piece---Yours-Enemy-Moves-Hits-Cost");
381
382         for (i = 0; i < NUM_OBJECTS; i++) {
383                 if (i >= (NUM_OBJECTS+1)/2) {
384                         r = i - (NUM_OBJECTS+1)/2;
385                         c = 41;
386                 }
387                 else {
388                         r = i;
389                         c = 1;
390                 }
391                 pos_str1 (r + text_lines + NUMTOPS + 3, c,"%-12s%c     %c%6d%5d%6d",
392                         piece_attr[i].nickname,
393                         piece_attr[i].sname,
394                         tolower (piece_attr[i].sname),
395                         piece_attr[i].speed,
396                         piece_attr[i].max_hits,
397                         piece_attr[i].build_time,0,0);          //FLAG
398
399         }
400         (void) refresh ();
401 }
402
403 #define COL_DIGITS ((MAP_WIDTH <= 100) ? 2 : ((MAP_WIDTH <= 1000 ? 3 : (1 / 0))))
404
405 int
406 loc_disp(int loc)
407 {
408   int row = loc / MAP_WIDTH;
409   int nrow = row;
410   int col = loc % MAP_WIDTH;
411   ASSERT (loc == (row * MAP_WIDTH) + col);
412   int i;
413   for (i = COL_DIGITS; i > 0; i--) {
414     nrow *= 10; }
415   move (LINES - 1, 0);
416   return nrow + col;
417 }