Reindent the code.
[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 {
153     need_delay = 1;
154 }
155
156 void
157 comment (char *fmt, ...)
158 {
159     va_list ap;
160
161     va_start(ap, fmt);
162     if (need_delay) delay ();
163     topmsg (1, "");
164     topmsg (2, "");
165     vtopmsg (3, fmt, ap);
166     need_delay = (fmt != 0);
167     va_end(ap);
168 }
169         
170 void
171 pdebug(char *fmt, ...)
172 {
173     va_list ap;
174
175     if (!print_debug) return;
176
177     va_start(ap, fmt);
178     if (need_delay) delay ();
179     topmsg (1, "");
180     topmsg (2, "");
181     vtopmsg (3, fmt, ap);
182     need_delay = (fmt != 0);
183     va_end(ap);
184 }
185
186 /* kermyt begin */
187
188 void
189 vksend(const char *fmt, va_list varglist)
190 {
191     if(!(my_stream=fopen("info_list.txt","a")))
192     {
193         error("Cannot open info_list.txt");
194         return;
195     }
196     vfprintf(my_stream, fmt, varglist);
197     fclose(my_stream);
198     return;
199 }
200
201 void
202 ksend(char *fmt, ...)
203 {
204     va_list ap;
205
206     va_start(ap, fmt);
207     vksend(fmt, ap);
208     va_end(ap);
209 }
210 /* kermyt end */
211
212 /*
213 Get a string from the user, echoing characters all the while.
214 */
215
216 void
217 get_str(char *buf, int sizep)
218 {
219     (void) echo();
220     get_strq(buf, sizep);
221     (void) noecho();
222 }
223
224 /*
225 Get a string from the user, ignoring the current echo mode.
226 */
227
228 void
229 get_strq(char *buf, int sizep)
230 {
231     sizep = sizep; /* size of buf, currently unused */
232
233     (void) nocrmode ();
234     (void) refresh ();
235     (void) getstr (buf);
236     need_delay = false;
237     info (0, 0, 0);
238     (void) crmode ();
239 }
240
241 /*
242 Get a character from the user and convert it to uppercase.
243 */
244
245 char
246 get_chx(void)
247 {
248     char c;
249
250     c = get_cq ();
251
252     if (islower(c))
253         return (toupper(c));
254     else
255         return (c);
256 }
257
258 /*
259 Input an integer from the user.
260 */
261
262 int
263 getint(char *message)
264 {
265     char buf[STRSIZE];
266     char *p;
267
268     for (;;) { /* until we get a legal number */
269         prompt (message,0,0,0,0,0,0,0,0);
270         get_str (buf, sizeof (buf));
271                 
272         for (p = buf; *p; p++) {
273             if (*p < '0' || *p > '9') {
274                 error ("Please enter an integer.",0,0,0,0,0,0,0,0);
275                 break;
276             }
277         }
278         if (*p == 0) { /* no error yet? */
279             if (p - buf > 7) /* too many digits? */
280                 error ("Please enter a small integer.",0,0,0,0,0,0,0,0);
281             else return (atoi (buf));
282         }
283     }
284 }
285
286 /*
287 Input a character from the user with echoing.
288 */
289
290 char
291 get_c(void)
292 {
293     char c; /* one char and a null */
294
295     (void) echo ();
296     c = get_cq ();
297     (void) noecho ();
298     return (c);
299 }
300
301 /*
302 Input a character quietly.
303 */
304
305 char
306 get_cq(void)
307 {
308     char c;
309
310     (void) crmode ();
311     (void) refresh ();
312     c = getch ();
313     topini (); /* clear information lines */
314     (void) nocrmode ();
315     return (c);
316 }
317
318 /*
319 Input a yes or no response from the user.  We loop until we get
320 a valid response.  We return true iff the user replies 'y'.
321 */
322
323 bool
324 getyn(char *message)
325 {
326     char c;
327
328     for (;;) {
329         prompt (message,0,0,0,0,0,0,0,0);
330         c = get_chx ();
331
332         if (c == 'Y') return (true);
333         if (c == 'N') return (false);
334
335         error ("Please answer Y or N.",0,0,0,0,0,0,0,0);
336     }
337 }
338
339 /*
340 Input an integer in a range.
341 */
342
343 int
344 get_range(char *message, int low, int high)
345 {
346     int result;
347
348     for (;;) {
349         result = getint (message);
350
351         if (result >= low && result <= high) return (result);
352
353         error ("Please enter an integer in the range %d..%d.",low, high);
354     }
355 }
356
357 /*
358 Print a screen of help information.
359 */
360
361 void
362 help(char **text, int nlines)
363 {
364     int i, r, c;
365     int text_lines;
366
367     text_lines = (nlines + 1) / 2; /* lines of text */
368
369     clear_screen ();
370
371     pos_str (NUMTOPS, 1, text[0]); /* mode */
372     pos_str (NUMTOPS, 41, "See empire(6) for more information.");
373
374     for (i = 1; i < nlines; i++) {
375         if (i > text_lines)
376             pos_str (i - text_lines + NUMTOPS + 1, 41, text[i]);
377         else pos_str (i + NUMTOPS + 1, 1, text[i]);
378     }
379
380     pos_str (text_lines + NUMTOPS + 2,  1, "--Piece---Yours-Enemy-Moves-Hits-Cost");
381     pos_str (text_lines + NUMTOPS + 2, 41, "--Piece---Yours-Enemy-Moves-Hits-Cost");
382
383     for (i = 0; i < NUM_OBJECTS; i++) {
384         if (i >= (NUM_OBJECTS+1)/2) {
385             r = i - (NUM_OBJECTS+1)/2;
386             c = 41;
387         }
388         else {
389             r = i;
390             c = 1;
391         }
392         pos_str1 (r + text_lines + NUMTOPS + 3, c,"%-12s%c     %c%6d%5d%6d",
393                   piece_attr[i].nickname,
394                   piece_attr[i].sname,
395                   tolower (piece_attr[i].sname),
396                   piece_attr[i].speed,
397                   piece_attr[i].max_hits,
398                   piece_attr[i].build_time,0,0);                //FLAG
399
400     }
401     (void) refresh ();
402 }
403
404 #define COL_DIGITS ((MAP_WIDTH <= 100) ? 2 : ((MAP_WIDTH <= 1000 ? 3 : (1 / 0))))
405
406 int
407 loc_disp(int loc)
408 {
409     int row = loc / MAP_WIDTH;
410     int nrow = row;
411     int col = loc % MAP_WIDTH;
412     ASSERT (loc == (row * MAP_WIDTH) + col);
413     int i;
414     for (i = COL_DIGITS; i > 0; i--) {
415         nrow *= 10; }
416     move (LINES - 1, 0);
417     return nrow + col;
418 }
419
420 /* end */