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