1 /*
2 * screen.c
3 *
4 * Generic screen manipulation routines. Most of these routines call the machine
5 * specific routines to do the actual work.
6 *
7 */
8
9 #include "ztypes.h"
10
11 /*
12 * select_window
13 *
14 * Put the cursor in the text or status window. The cursor is free to move in
15 * the status window, but is fixed to the input line in the text window.
16 *
17 */
18
19 #ifdef __STDC__
select_window(zword_t w)20 void select_window (zword_t w)
21 #else
22 void select_window (w)
23 zword_t w;
24 #endif
25 {
26 int row, col;
27
28 flush_buffer (FALSE);
29
30 screen_window = w;
31
32 if (screen_window == STATUS_WINDOW) {
33
34 /* Status window: disable formatting and select status window */
35
36 formatting = OFF;
37 scripting_disable = ON;
38 select_status_window ();
39
40 /* Put cursor at top of status area */
41
42 if (h_type < V4)
43 move_cursor (2, 1);
44 else
45 move_cursor (1, 1);
46
47 } else {
48
49 /* Text window: enable formatting and select text window */
50
51 select_text_window ();
52 scripting_disable = OFF;
53 formatting = ON;
54
55 /* Move cursor if it has been left in the status area */
56
57 /*get_cursor_position (&row, &col);
58 if (row <= status_size)
59 move_cursor (status_size + 1, 1);*/
60
61 }
62
63 /* Force text attribute to normal rendition */
64
65 set_attribute (NORMAL);
66
67 }/* select_window */
68
69 /*
70 * set_status_size
71 *
72 * Set the size of the status window. The default size for the status window is
73 * zero lines for both type 3 and 4 games. The status line is handled specially
74 * for type 3 games and always occurs the line immediately above the status
75 * window.
76 *
77 */
78
79 #ifdef __STDC__
set_status_size(zword_t lines)80 void set_status_size (zword_t lines)
81 #else
82 void set_status_size (lines)
83 zword_t lines;
84 #endif
85 {
86 /* Maximum status window size is 255 */
87
88 lines &= 0xff;
89
90 /* The top line is always set for V1 to V3 games, so account for it here. */
91
92 if (h_type < V4)
93 lines++;
94
95 if (lines) {
96
97 /* If size is non zero the turn on the status window */
98
99 status_active = ON;
100
101 /* Bound the status size to one line less than the total screen height */
102
103 if (lines > (zword_t) (screen_rows - 1))
104 status_size = (zword_t) (screen_rows - 1);
105 else
106 status_size = lines;
107
108 /* Create the status window, or resize it */
109
110 create_status_window (lines);
111
112 /* Need to clear the status window for type 3 games */
113
114 if (h_type < V4)
115 erase_window (STATUS_WINDOW);
116
117 } else {
118
119 /* Lines are zero so turn off the status window */
120
121 status_active = OFF;
122
123 /* Reset the lines written counter and status size */
124
125 lines_written = 0;
126 status_size = 0;
127
128 /* Delete the status window */
129
130 delete_status_window ();
131
132 /* Return cursor to text window */
133
134 select_text_window ();
135 }
136
137 }/* set_status_size */
138
139 /*
140 * erase_window
141 *
142 * Clear one or all windows on the screen.
143 *
144 */
145
146 #ifdef __STDC__
erase_window(zword_t w)147 void erase_window (zword_t w)
148 #else
149 void erase_window (w)
150 zword_t w;
151 #endif
152 {
153 flush_buffer (TRUE);
154
155 if ((zbyte_t) w == (zbyte_t) SCREEN) {
156 clear_screen ();
157 } else if ((zbyte_t) w == TEXT_WINDOW) {
158 clear_text_window ();
159 } else if ((zbyte_t) w == STATUS_WINDOW) {
160 clear_status_window ();
161 return;
162 }
163
164 if (h_type > V4)
165 move_cursor (1, 1);
166 else
167 move_cursor (screen_rows, 1);
168
169 }/* erase_window */
170
171 /*
172 * erase_line
173 *
174 * Clear one line on the screen.
175 *
176 */
177
178 #ifdef __STDC__
erase_line(zword_t flag)179 void erase_line (zword_t flag)
180 #else
181 void erase_line (flag)
182 zword_t flag;
183 #endif
184 {
185 if (flag == TRUE)
186 clear_line ();
187
188 }/* erase_line */
189
190 /*
191 * set_cursor_position
192 *
193 * Set the cursor position in the status window only.
194 *
195 */
196
197 #ifdef __STDC__
set_cursor_position(zword_t row,zword_t column)198 void set_cursor_position (zword_t row, zword_t column)
199 #else
200 void set_cursor_position (row, column)
201 zword_t row;
202 zword_t column;
203 #endif
204 {
205
206 /* Can only move cursor if format mode is off and in status window */
207
208 if (formatting == OFF && screen_window == STATUS_WINDOW)
209 move_cursor (row, column);
210
211 }/* set_cursor_position */
212
213 /*
214 * pad_line
215 *
216 * Pad the status line with spaces up to a column position.
217 *
218 */
219
220 #ifdef __STDC__
pad_line(int column)221 static void pad_line (int column)
222 #else
223 static void pad_line (column)
224 int column;
225 #endif
226 {
227 int i;
228
229 for (i = status_pos; i < column; i++)
230 write_char (' ');
231 status_pos = column;
232
233 }/* pad_line */
234
235 /*
236 * display_status_line
237 *
238 * Format and output the status line for type 3 games only.
239 *
240 */
241
242 #ifdef __STDC__
display_status_line(void)243 void display_status_line (void)
244 #else
245 void display_status_line ()
246 #endif
247 {
248 int i, count = 0, end_of_string[3];
249 char *status_part[3];
250
251 /* Move the cursor to the top line of the status window, set the reverse
252 rendition and print the status line */
253
254 select_window (STATUS_WINDOW);
255 move_cursor (1, 1);
256 set_attribute (REVERSE);
257
258 /* Redirect output to the status line buffer */
259
260 set_print_modes (3, 0);
261
262 /* Print the object description for global variable 16 */
263
264 pad_line (1);
265 status_part[count] = &status_line[status_pos];
266 if (load_variable (16) != 0)
267 print_object (load_variable (16));
268 end_of_string[count++] = status_pos;
269 status_line[status_pos++] = '\0';
270
271 if (get_byte (H_CONFIG) & CONFIG_TIME) {
272
273 /* If a time display print the hours and minutes from global
274 variables 17 and 18 */
275
276 pad_line (screen_cols - 21);
277 status_part[count] = &status_line[status_pos];
278 write_string (" Time: ");
279 print_time (load_variable (17), load_variable (18));
280 end_of_string[count++] = status_pos;
281 status_line[status_pos++] = '\0';
282 } else {
283
284 /* If a moves/score display print the score and moves from global
285 variables 17 and 18 */
286
287 pad_line (screen_cols - 31);
288 status_part[count] = &status_line[status_pos];
289 write_string (" Score: ");
290 print_number (load_variable (17));
291 end_of_string[count++] = status_pos;
292 status_line[status_pos++] = '\0';
293
294 pad_line (screen_cols - 15);
295 status_part[count] = &status_line[status_pos];
296 write_string (" Moves: ");
297 print_number (load_variable (18));
298 end_of_string[count++] = status_pos;
299 status_line[status_pos++] = '\0';
300 }
301
302 /* Pad the end of status line with spaces then disable output redirection */
303
304 pad_line (screen_cols);
305 set_print_modes ((zword_t) -3, 0);
306
307 /* Try and print the status line for a proportional font screen. If this
308 fails then remove embedded nulls in status line buffer and just output
309 it to the screen */
310
311 if (print_status (count, status_part) == FALSE) {
312 for (i = 0; i < count; i++)
313 status_line[end_of_string[i]] = ' ';
314 status_line[status_pos] = '\0';
315 write_string (status_line);
316 }
317
318 set_attribute (NORMAL);
319 select_window (TEXT_WINDOW);
320
321 }/* display_status_line */
322
323 /*
324 * blank_status_line
325 *
326 * Output a blank status line for type 3 games only.
327 *
328 */
329
330 #ifdef __STDC__
blank_status_line(void)331 void blank_status_line (void)
332 #else
333 void blank_status_line ()
334 #endif
335 {
336
337 /* Move the cursor to the top line of the status window, set the reverse
338 rendition and print the status line */
339
340 select_window (STATUS_WINDOW);
341 move_cursor (1, 1);
342 set_attribute (REVERSE);
343
344 /* Redirect output to the status line buffer and pad the status line with
345 spaces then disable output redirection */
346
347 set_print_modes (3, 0);
348 pad_line (screen_cols);
349 status_line[status_pos] = '\0';
350 set_print_modes ((zword_t) -3, 0);
351
352 /* Write the status line */
353
354 write_string (status_line);
355
356 /* Turn off attributes and return to text window */
357
358 set_attribute (NORMAL);
359 select_window (TEXT_WINDOW);
360
361 }/* blank_status_line */
362
363 /*
364 * output_string
365 *
366 * Output a string of characters.
367 *
368 */
369
370 #ifdef __STDC__
output_string(const char * s)371 void output_string (const char *s)
372 #else
373 void output_string (s)
374 const char *s;
375 #endif
376 {
377
378 while (*s)
379 output_char (*s++);
380
381 }/* output_string */
382
383 /*
384 * output_line
385 *
386 * Output a string of characters followed by a new line.
387 *
388 */
389
390 #ifdef __STDC__
output_line(const char * s)391 void output_line (const char *s)
392 #else
393 void output_line (s)
394 const char *s;
395 #endif
396 {
397
398 output_string (s);
399 output_new_line ();
400
401 }/* output_line */
402
403 /*
404 * output_char
405 *
406 * Output a character and rendition selection. This routine also handles
407 * selecting rendition attributes such as bolding and reverse. There are
408 * five attributes distinguished by a bit mask. 0 means turn all attributes
409 * off. The attributes are: 1 = reverse, 2 = bold, 4 = emphasis, and
410 * 8 = fixed font.
411 *
412 */
413
414 #ifdef __STDC__
output_char(int c)415 void output_char (int c)
416 #else
417 void output_char (c)
418 int c;
419 #endif
420 {
421
422 /* If output is enabled then either select the rendition attribute
423 or just display the character */
424
425 if (outputting == ON) {
426
427 /* Make sure we are dealing with a positive integer */
428
429 c = (unsigned int) (c & 0xff);
430
431 /* Attribute selection. We have to check the force-fixed flag, because the game can set it at whim. */
432 {
433 static int forcefix = (-1);
434 int currentfix = (get_word (H_FLAGS) & FIXED_FONT_FLAG);
435 if (forcefix != currentfix) {
436 forcefix = currentfix;
437 /* tickle the display attribute so it notices the changed flag */
438 set_attribute(NO_CHANGE_ATTRIBUTE);
439 }
440 }
441
442 if (c >= (MIN_ATTRIBUTE + 1) && c <= (MAX_ATTRIBUTE + 1)) {
443
444 set_attribute (--c);
445
446 } else {
447
448 display_char (c);
449
450 }
451 }
452
453 }/* output_char */
454
455 /*
456 * output_new_line
457 *
458 * Scroll the text window up one line and pause the window if it is full.
459 *
460 */
461
462 #ifdef __STDC__
output_new_line(void)463 void output_new_line (void)
464 #else
465 void output_new_line ()
466 #endif
467 {
468 int row, col;
469
470 /* Don't print if output is disabled or replaying commands */
471
472 if (outputting == ON) {
473
474 if (formatting == ON && screen_window == TEXT_WINDOW) {
475
476 /* If this is the text window then scroll it up one line */
477
478 scroll_line ();
479
480 /* paging ain't done here any more. --zarf */
481
482 } else
483
484 /* If this is the status window then just output a new line */
485
486 output_char ('\n');
487 }
488
489 }/* output_new_line */
490
491 /*
492 * print_window
493 *
494 * Writes text into a rectangular window on the screen.
495 *
496 * argv[0] = start of text address
497 * argv[1] = rectangle width
498 * argv[2] = rectangle height (default = 1)
499 *
500 */
501
502 #ifdef __STDC__
print_window(int argc,zword_t * argv)503 void print_window (int argc, zword_t *argv)
504 #else
505 void print_window (argc, argv)
506 int argc;
507 zword_t *argv;
508 #endif
509 {
510 unsigned long address;
511 unsigned int width, height;
512 unsigned int row, column;
513
514 /* Supply default arguments */
515
516 if (argc < 3)
517 argv[2] = 1;
518
519 /* Don't do anything if the window is zero high or wide */
520
521 if (argv[1] == 0 || argv[2] == 0)
522 return;
523
524 /* Get coordinates of top left corner of rectangle */
525
526 get_cursor_position ((int *) &row, (int *) &column);
527
528 address = argv[0];
529
530 /* Write text in width * height rectangle */
531
532 for (height = 0; height < argv[2]; height++) {
533
534 for (width = 0; width < argv[1]; width++)
535 write_char (read_data_byte (&address));
536
537 /* Put cursor back to lefthand side of rectangle on next line */
538
539 if (height != (argv[2] - 1))
540 move_cursor (++row, column);
541
542 }
543
544 }/* print_window */
545
546 /*
547 * set_font_attribute
548 *
549 * Set text or graphic font. 1 = text font, 3 = graphics font.
550 *
551 */
552
553 #ifdef __STDC__
set_font_attribute(zword_t new_font)554 void set_font_attribute (zword_t new_font)
555 #else
556 void set_font_attribute (new_font)
557 zword_t new_font;
558 #endif
559 {
560 zword_t old_font = font;
561 int res;
562
563 if (new_font != old_font) {
564 font = new_font;
565 res = set_font (font);
566 if (!res)
567 old_font = 0;
568 }
569
570 store_operand (old_font);
571
572 }/* set_font_attribute */
573
574 /*
575 * set_colour_attribute
576 *
577 * Set the colour of the screen. Colour can be set on four things:
578 * Screen background
579 * Text typed by player
580 * Text written by game
581 * Graphics characters
582 *
583 * Colors can be set to 1 of 9 values:
584 * 1 = machine default (IBM/PC = blue background, everything else white)
585 * 2 = black
586 * 3 = red
587 * 4 = green
588 * 5 = brown
589 * 6 = blue
590 * 7 = magenta
591 * 8 = cyan
592 * 9 = white
593 *
594 */
595
596 #ifdef __STDC__
set_colour_attribute(zword_t foreground,zword_t background)597 void set_colour_attribute (zword_t foreground, zword_t background)
598 #else
599 void set_colour_attribute (foreground, background)
600 zword_t foreground;
601 zword_t background;
602 #endif
603 {
604 if (!(foreground >= 0 && foreground <= 9 && background >= 0 && background <= 9)) {
605 fatal ("Bad colour!");
606 }
607
608 flush_buffer (FALSE);
609
610 set_colours (foreground, background);
611
612 return;
613
614 }/* set_colour_attribute */
615