/* * screen.c * * Generic screen manipulation routines. Most of these routines call the machine * specific routines to do the actual work. * */ #include "ztypes.h" /* * select_window * * Put the cursor in the text or status window. The cursor is free to move in * the status window, but is fixed to the input line in the text window. * */ #ifdef __STDC__ void select_window (zword_t w) #else void select_window (w) zword_t w; #endif { int row, col; flush_buffer (FALSE); screen_window = w; if (screen_window == STATUS_WINDOW) { /* Status window: disable formatting and select status window */ formatting = OFF; scripting_disable = ON; select_status_window (); /* Put cursor at top of status area */ if (h_type < V4) move_cursor (2, 1); else move_cursor (1, 1); } else { /* Text window: enable formatting and select text window */ select_text_window (); scripting_disable = OFF; formatting = ON; /* Move cursor if it has been left in the status area */ /*get_cursor_position (&row, &col); if (row <= status_size) move_cursor (status_size + 1, 1);*/ } /* Force text attribute to normal rendition */ set_attribute (NORMAL); }/* select_window */ /* * set_status_size * * Set the size of the status window. The default size for the status window is * zero lines for both type 3 and 4 games. The status line is handled specially * for type 3 games and always occurs the line immediately above the status * window. * */ #ifdef __STDC__ void set_status_size (zword_t lines) #else void set_status_size (lines) zword_t lines; #endif { /* Maximum status window size is 255 */ lines &= 0xff; /* The top line is always set for V1 to V3 games, so account for it here. */ if (h_type < V4) lines++; if (lines) { /* If size is non zero the turn on the status window */ status_active = ON; /* Bound the status size to one line less than the total screen height */ if (lines > (zword_t) (screen_rows - 1)) status_size = (zword_t) (screen_rows - 1); else status_size = lines; /* Create the status window, or resize it */ create_status_window (lines); /* Need to clear the status window for type 3 games */ if (h_type < V4) erase_window (STATUS_WINDOW); } else { /* Lines are zero so turn off the status window */ status_active = OFF; /* Reset the lines written counter and status size */ lines_written = 0; status_size = 0; /* Delete the status window */ delete_status_window (); /* Return cursor to text window */ select_text_window (); } }/* set_status_size */ /* * erase_window * * Clear one or all windows on the screen. * */ #ifdef __STDC__ void erase_window (zword_t w) #else void erase_window (w) zword_t w; #endif { flush_buffer (TRUE); if ((zbyte_t) w == (zbyte_t) SCREEN) { clear_screen (); } else if ((zbyte_t) w == TEXT_WINDOW) { clear_text_window (); } else if ((zbyte_t) w == STATUS_WINDOW) { clear_status_window (); return; } if (h_type > V4) move_cursor (1, 1); else move_cursor (screen_rows, 1); }/* erase_window */ /* * erase_line * * Clear one line on the screen. * */ #ifdef __STDC__ void erase_line (zword_t flag) #else void erase_line (flag) zword_t flag; #endif { if (flag == TRUE) clear_line (); }/* erase_line */ /* * set_cursor_position * * Set the cursor position in the status window only. * */ #ifdef __STDC__ void set_cursor_position (zword_t row, zword_t column) #else void set_cursor_position (row, column) zword_t row; zword_t column; #endif { /* Can only move cursor if format mode is off and in status window */ if (formatting == OFF && screen_window == STATUS_WINDOW) move_cursor (row, column); }/* set_cursor_position */ /* * pad_line * * Pad the status line with spaces up to a column position. * */ #ifdef __STDC__ static void pad_line (int column) #else static void pad_line (column) int column; #endif { int i; for (i = status_pos; i < column; i++) write_char (' '); status_pos = column; }/* pad_line */ /* * display_status_line * * Format and output the status line for type 3 games only. * */ #ifdef __STDC__ void display_status_line (void) #else void display_status_line () #endif { int i, count = 0, end_of_string[3]; char *status_part[3]; /* Move the cursor to the top line of the status window, set the reverse rendition and print the status line */ select_window (STATUS_WINDOW); move_cursor (1, 1); set_attribute (REVERSE); /* Redirect output to the status line buffer */ set_print_modes (3, 0); /* Print the object description for global variable 16 */ pad_line (1); status_part[count] = &status_line[status_pos]; if (load_variable (16) != 0) print_object (load_variable (16)); end_of_string[count++] = status_pos; status_line[status_pos++] = '\0'; if (get_byte (H_CONFIG) & CONFIG_TIME) { /* If a time display print the hours and minutes from global variables 17 and 18 */ pad_line (screen_cols - 21); status_part[count] = &status_line[status_pos]; write_string (" Time: "); print_time (load_variable (17), load_variable (18)); end_of_string[count++] = status_pos; status_line[status_pos++] = '\0'; } else { /* If a moves/score display print the score and moves from global variables 17 and 18 */ pad_line (screen_cols - 31); status_part[count] = &status_line[status_pos]; write_string (" Score: "); print_number (load_variable (17)); end_of_string[count++] = status_pos; status_line[status_pos++] = '\0'; pad_line (screen_cols - 15); status_part[count] = &status_line[status_pos]; write_string (" Moves: "); print_number (load_variable (18)); end_of_string[count++] = status_pos; status_line[status_pos++] = '\0'; } /* Pad the end of status line with spaces then disable output redirection */ pad_line (screen_cols); set_print_modes ((zword_t) -3, 0); /* Try and print the status line for a proportional font screen. If this fails then remove embedded nulls in status line buffer and just output it to the screen */ if (print_status (count, status_part) == FALSE) { for (i = 0; i < count; i++) status_line[end_of_string[i]] = ' '; status_line[status_pos] = '\0'; write_string (status_line); } set_attribute (NORMAL); select_window (TEXT_WINDOW); }/* display_status_line */ /* * blank_status_line * * Output a blank status line for type 3 games only. * */ #ifdef __STDC__ void blank_status_line (void) #else void blank_status_line () #endif { /* Move the cursor to the top line of the status window, set the reverse rendition and print the status line */ select_window (STATUS_WINDOW); move_cursor (1, 1); set_attribute (REVERSE); /* Redirect output to the status line buffer and pad the status line with spaces then disable output redirection */ set_print_modes (3, 0); pad_line (screen_cols); status_line[status_pos] = '\0'; set_print_modes ((zword_t) -3, 0); /* Write the status line */ write_string (status_line); /* Turn off attributes and return to text window */ set_attribute (NORMAL); select_window (TEXT_WINDOW); }/* blank_status_line */ /* * output_string * * Output a string of characters. * */ #ifdef __STDC__ void output_string (const char *s) #else void output_string (s) const char *s; #endif { while (*s) output_char (*s++); }/* output_string */ /* * output_line * * Output a string of characters followed by a new line. * */ #ifdef __STDC__ void output_line (const char *s) #else void output_line (s) const char *s; #endif { output_string (s); output_new_line (); }/* output_line */ /* * output_char * * Output a character and rendition selection. This routine also handles * selecting rendition attributes such as bolding and reverse. There are * five attributes distinguished by a bit mask. 0 means turn all attributes * off. The attributes are: 1 = reverse, 2 = bold, 4 = emphasis, and * 8 = fixed font. * */ #ifdef __STDC__ void output_char (int c) #else void output_char (c) int c; #endif { /* If output is enabled then either select the rendition attribute or just display the character */ if (outputting == ON) { /* Make sure we are dealing with a positive integer */ c = (unsigned int) (c & 0xff); /* Attribute selection. We have to check the force-fixed flag, because the game can set it at whim. */ { static int forcefix = (-1); int currentfix = (get_word (H_FLAGS) & FIXED_FONT_FLAG); if (forcefix != currentfix) { forcefix = currentfix; /* tickle the display attribute so it notices the changed flag */ set_attribute(NO_CHANGE_ATTRIBUTE); } } if (c >= (MIN_ATTRIBUTE + 1) && c <= (MAX_ATTRIBUTE + 1)) { set_attribute (--c); } else { display_char (c); } } }/* output_char */ /* * output_new_line * * Scroll the text window up one line and pause the window if it is full. * */ #ifdef __STDC__ void output_new_line (void) #else void output_new_line () #endif { int row, col; /* Don't print if output is disabled or replaying commands */ if (outputting == ON) { if (formatting == ON && screen_window == TEXT_WINDOW) { /* If this is the text window then scroll it up one line */ scroll_line (); /* paging ain't done here any more. --zarf */ } else /* If this is the status window then just output a new line */ output_char ('\n'); } }/* output_new_line */ /* * print_window * * Writes text into a rectangular window on the screen. * * argv[0] = start of text address * argv[1] = rectangle width * argv[2] = rectangle height (default = 1) * */ #ifdef __STDC__ void print_window (int argc, zword_t *argv) #else void print_window (argc, argv) int argc; zword_t *argv; #endif { unsigned long address; unsigned int width, height; unsigned int row, column; /* Supply default arguments */ if (argc < 3) argv[2] = 1; /* Don't do anything if the window is zero high or wide */ if (argv[1] == 0 || argv[2] == 0) return; /* Get coordinates of top left corner of rectangle */ get_cursor_position ((int *) &row, (int *) &column); address = argv[0]; /* Write text in width * height rectangle */ for (height = 0; height < argv[2]; height++) { for (width = 0; width < argv[1]; width++) write_char (read_data_byte (&address)); /* Put cursor back to lefthand side of rectangle on next line */ if (height != (argv[2] - 1)) move_cursor (++row, column); } }/* print_window */ /* * set_font_attribute * * Set text or graphic font. 1 = text font, 3 = graphics font. * */ #ifdef __STDC__ void set_font_attribute (zword_t new_font) #else void set_font_attribute (new_font) zword_t new_font; #endif { zword_t old_font = font; int res; if (new_font != old_font) { font = new_font; res = set_font (font); if (!res) old_font = 0; } store_operand (old_font); }/* set_font_attribute */ /* * set_colour_attribute * * Set the colour of the screen. Colour can be set on four things: * Screen background * Text typed by player * Text written by game * Graphics characters * * Colors can be set to 1 of 9 values: * 1 = machine default (IBM/PC = blue background, everything else white) * 2 = black * 3 = red * 4 = green * 5 = brown * 6 = blue * 7 = magenta * 8 = cyan * 9 = white * */ #ifdef __STDC__ void set_colour_attribute (zword_t foreground, zword_t background) #else void set_colour_attribute (foreground, background) zword_t foreground; zword_t background; #endif { if (!(foreground >= 0 && foreground <= 9 && background >= 0 && background <= 9)) { fatal ("Bad colour!"); } flush_buffer (FALSE); set_colours (foreground, background); return; }/* set_colour_attribute */