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