home *** CD-ROM | disk | FTP | other *** search
- /*
- * screen.c
- *
- * Generic screen manipulation
- *
- */
-
- #include "frotz.h"
- #include "s5api.h"
-
- extern void set_header_extension (struct sg *g, short, zword);
- extern short direct_call (struct sg *g, zword);
-
- /*
- * winarg0
- *
- * Return the window number in zargs[0]. In V6 only, -3 refers to the
- * current window.
- *
- */
-
- zword winarg0 (struct sg *g)
- {
-
- if (g->h_version == V6 && (short) g->zargs[0] == -3)
- return g->cwin;
-
- if (g->zargs[0] >= ((g->h_version == V6) ? 8 : 2))
- runtime_error (g,"Illegal window");
-
- return (g->zargs[0]);
-
- }/* winarg0 */
-
- /*
- * winarg2
- *
- * Return the (optional) window number in zargs[2]. -3 refers to the
- * current window. This optional window number was only used by some
- * V6 opcodes: set_cursor, set_margins, set_colour.
- *
- */
-
- zword winarg2 (struct sg *g)
- {
-
- if (g->zargc < 3 || (short) (g->zargs[2]) == -3)
- return g->cwin;
-
- if (g->zargs[2] >= 8)
- runtime_error (g,"Illegal window");
-
- return (g->zargs[2]);
-
- }/* winarg2 */
-
- /*
- * update_cursor
- *
- * Move the hardware cursor to make it match the window properties.
- *
- */
-
- void update_cursor (struct sg *g)
- {
-
- os_set_cursor (g,
- g->cwp->y_pos + g->cwp->y_cursor - 1,
- g->cwp->x_pos + g->cwp->x_cursor - 1);
-
- }/* update_cursor */
-
- /*
- * reset_cursor
- *
- * Reset the cursor of a given window to its initial position.
- *
- */
-
- void reset_cursor (struct sg *g, zword win)
- {
- short lines = 0;
-
- if (g->h_version <= V4 && win == 0)
- lines = g->wp[0].y_size / hi (g->wp[0].font_size) - 1;
-
- g->wp[win].y_cursor = hi (g->wp[0].font_size) * lines + 1;
- g->wp[win].x_cursor = g->wp[win].left + 1;
-
- if (win == g->cwin)
- update_cursor (g);
-
- }/* reset_cursor */
-
- /*
- * set_more_prompts
- *
- * Turn more prompts on/off.
- *
- */
-
- void set_more_prompts (struct sg *g, short flag)
- {
-
- if (flag && !g->more_prompts)
- g->cwp->line_count = 0;
-
- g->more_prompts = flag;
-
- }/* set_more_prompts */
-
- /*
- * units_left
- *
- * Return the #screen units from the cursor to the end of the line.
- *
- */
-
- short units_left (struct sg *g)
- {
-
- // Was this, don't know why +1 was added as this means words
- // can go over the edge of the screen
- // return g->cwp->x_size - g->cwp->right - g->cwp->x_cursor + 1;
-
- return g->cwp->x_size - g->cwp->right - g->cwp->x_cursor;
-
- }/* units_left */
-
- /*
- * get_max_width
- *
- * Return maximum width of a line in the given window. This is used in
- * connection with the extended output stream #3 call in V6.
- *
- */
-
- zword get_max_width (struct sg *g, zword win)
- {
-
- if (g->h_version == V6) {
-
- if (win >= 8)
- runtime_error (g,"Illegal window");
-
- return g->wp[win].x_size - g->wp[win].left - g->wp[win].right;
-
- } else return 0xffff;
-
- }/* get_max_width */
-
- /*
- * countdown
- *
- * Decrement the newline counter. Call the newline interrupt when the
- * counter hits zero. This is a helper function for screen_new_line.
- *
- */
-
- void countdown (struct sg *g)
- {
-
- if (g->cwp->nl_countdown != 0)
- if (--g->cwp->nl_countdown == 0)
- direct_call (g,g->cwp->nl_routine);
-
- }/* countdown */
-
- /*
- * screen_new_line
- *
- * Print a newline to the screen.
- *
- */
-
- void screen_new_line (struct sg *g)
- {
-
- if (g->discarding) return;
-
- /* Handle newline interrupts at the start (for most cases) */
-
- if (g->h_interpreter_number != INTERP_MSDOS || g->story_id != ZORK_ZERO || g->h_release != 393)
- countdown (g);
-
- /* Check whether the last input line gets destroyed */
-
- if (g->input_window == g->cwin)
- g->input_redraw = TRUE;
-
- /* If the cursor has not reached the bottom line, then move it to
- the next line; otherwise scroll the window or reset the cursor
- to the top left. */
-
- g->cwp->x_cursor = g->cwp->left + 1;
-
- if (g->cwp->y_cursor + 2 * g->font_height - 1 > g->cwp->y_size)
-
- if (g->enable_scrolling) {
-
- zword y = g->cwp->y_pos;
- zword x = g->cwp->x_pos;
-
- os_scroll_area (g, y,
- x,
- y + g->cwp->y_size - 1,
- x + g->cwp->x_size - 1,
- g->font_height);
-
- } else g->cwp->y_cursor = 1;
-
- else g->cwp->y_cursor += g->font_height;
-
- update_cursor (g);
-
- /* See if we need to print a more prompt (unless the game has set
- the line counter to -999 in order to suppress more prompts). */
-
- if (g->enable_scrolling && (short) g->cwp->line_count != -999) {
-
- zword above = (g->cwp->y_cursor - 1) / g->font_height;
- zword below = (g->cwp->y_size - g->cwp->y_cursor + 1) / g->font_height;
-
- g->cwp->line_count++;
-
- if ((short) g->cwp->line_count >= (short) above + below - 1) {
-
- if (g->more_prompts)
- os_more_prompt (g);
-
- g->cwp->line_count = g->option_context_lines;
-
- }
-
- }
-
- /* Handle newline interrupts at the end for Zork Zero under DOS */
-
- if (g->h_interpreter_number == INTERP_MSDOS && g->story_id == ZORK_ZERO && g->h_release == 393)
- countdown (g);
-
- }/* screen_new_line */
-
- /*
- * screen_char
- *
- * Display a single character on the screen.
- *
- */
-
- void screen_char (struct sg *g, zchar c)
- {
-
- if (g->discarding) return;
-
- if (c == ZC_INDENT && g->cwp->x_cursor != g->cwp->left + 1)
- c = ' ';
-
- if (units_left (g) < 1) {
-
- if (!g->enable_wrapping)
- { g->cwp->x_cursor = g->cwp->x_size - g->cwp->right; return; }
-
- screen_new_line (g);
-
- }
-
- os_display_char (g,c); g->cwp->x_cursor++;
-
- }/* screen_char */
-
- /*
- * screen_word
- *
- * Display a string of characters on the screen. If the word doesn't fit
- * then use wrapping or clipping depending on the current setting of the
- * enable_wrapping flag.
- *
- */
-
- void screen_word (struct sg *g, const zchar *s)
- {
- short width;
-
- if (g->discarding) return;
-
- if (*s == ZC_INDENT && g->cwp->x_cursor != g->cwp->left + 1)
- screen_char (g,*s++);
-
- if (units_left (g) < (width = os_string_width (g,s))) {
-
- if (!g->enable_wrapping) {
-
- zchar c;
-
- while ((c = *s++) != 0)
-
- if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE) {
-
- short arg = (short) *s++;
-
- if (c == ZC_NEW_FONT)
- os_set_font (g,arg);
- if (c == ZC_NEW_STYLE)
- os_set_text_style (g,arg);
-
- } else screen_char (g,c);
-
- return;
-
- }
-
- if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
- width = os_string_width (g,++s);
-
- screen_new_line (g);
-
- }
-
- os_display_string (g,s); g->cwp->x_cursor += width;
-
- }/* screen_word */
-
- /*
- * screen_write_input
- *
- * Display an input line on the screen. This is required during playback.
- *
- */
-
- void screen_write_input (struct sg *g, const zchar *buf, zchar key)
- {
- short width;
-
- if (units_left (g) < (width = os_string_width (g,buf)))
- screen_new_line (g);
-
- os_display_string (g,buf); g->cwp->x_cursor += width;
-
- if (key == ZC_RETURN)
- screen_new_line (g);
-
- }/* screen_write_input */
-
- /*
- * screen_erase_input
- *
- * Remove an input line that has already been printed from the screen
- * as if it was deleted by the player. This could be necessary during
- * playback.
- *
- */
-
- void screen_erase_input (struct sg *g, const zchar *buf)
- {
-
- if (buf[0] != 0) {
-
- short width = os_string_width (g,buf);
-
- zword y;
- zword x;
-
- g->cwp->x_cursor -= width;
-
- y = g->cwp->y_pos + g->cwp->y_cursor - 1;
- x = g->cwp->x_pos + g->cwp->x_cursor - 1;
-
- os_erase_area (g,y, x, y + g->font_height - 1, x + width - 1);
- os_set_cursor (g,y, x);
-
- }
-
- }/* screen_erase_input */
-
- /*
- * console_read_input
- *
- * Read an input line from the keyboard and return the terminating key.
- *
- */
-
- zchar console_read_input (struct sg *g, short max, zchar *buf, zword timeout, short continued)
- {
- zchar key;
- short i;
-
- /* Make sure there is some space for input */
-
- if (g->cwin == 0 && units_left (g) + os_string_width (g,buf) < 10 * g->font_width)
- screen_new_line (g);
-
- /* Make sure the input line is visible */
-
- if (continued && g->input_redraw)
- screen_write_input (g, buf, 0xFF);
-
- g->input_window = g->cwin;
- g->input_redraw = FALSE;
-
- /* Get input line from IO interface */
-
- g->cwp->x_cursor -= os_string_width (g,buf);
- key = os_read_line (g,max, buf, timeout, units_left (g), continued);
- g->cwp->x_cursor += os_string_width (g,buf);
-
- if (key != ZC_TIME_OUT)
- for (i = 0; i < 8; i++)
- g->wp[i].line_count = 0;
-
- /* Add a newline if the input was terminated normally */
-
- if (key == ZC_RETURN)
- screen_new_line (g);
-
- return key;
-
- }/* console_read_input */
-
- /*
- * console_read_key
- *
- * Read a single keystroke and return it.
- *
- */
-
- zchar console_read_key (struct sg *g, zword timeout)
- {
- zchar key;
- short i;
-
- key = os_read_key (g,timeout, g->cursor);
-
- if (key != ZC_TIME_OUT)
- for (i = 0; i < 8; i++)
- g->wp[i].line_count = 0;
-
- return key;
-
- }/* console_read_key */
-
- /*
- * update_attributes
- *
- * Set the three enable_*** variables to make them match the attributes
- * of the current window.
- *
- */
-
- void update_attributes (struct sg *g)
- {
- zword attr = g->cwp->attribute;
-
- g->enable_wrapping = attr & 1;
- g->enable_scrolling = attr & 2;
- g->enable_scripting = attr & 4;
- g->enable_buffering = attr & 8;
-
- /* Some story files forget to select wrapping for printing hints */
-
- if (g->story_id == ZORK_ZERO && g->h_release == 366)
- if (g->cwin == 0)
- g->enable_wrapping = TRUE;
- if (g->story_id == SHOGUN && g->h_release <= 295)
- if (g->cwin == 0)
- g->enable_wrapping = TRUE;
-
- }/* update_attributes */
-
- /*
- * refresh_text_style
- *
- * Set the right text style. This can be necessary when the fixed font
- * flag is changed, or when a new window is selected, or when the game
- * uses the set_text_style opcode.
- *
- */
-
- void refresh_text_style (struct sg *g)
- {
- zword style;
-
- if (g->h_version != V6) {
-
- style = g->wp[0].style;
-
- if (g->cwin != 0 || g->h_flags & FIXED_FONT_FLAG)
- style |= FIXED_WIDTH_STYLE;
-
- } else style = g->cwp->style;
-
- if (!g->ostream_memory && g->ostream_screen && g->enable_buffering) {
-
- print_char (g,ZC_NEW_STYLE);
- print_char (g,(unsigned char)style);
-
- } else os_set_text_style (g,style);
-
- }/* refresh_text_style */
-
- /*
- * set_window
- *
- * Set the current window. In V6 every window has its own set of window
- * properties such as colours, text style, cursor position and size.
- *
- */
-
- void set_window (struct sg *g, zword win)
- {
-
- flush_buffer (g);
-
- g->cwin = win; g->cwp = g->wp + win;
-
- update_attributes (g);
-
- if (g->h_version == V6) {
-
- //os_set_colour (lo (cwp->colour), hi (cwp->colour));
-
- if (os_font_data (g,g->cwp->font, &(g->font_height), &(g->font_width)))
- os_set_font (g,g->cwp->font);
-
- os_set_text_style (g,g->cwp->style);
-
- } else refresh_text_style (g);
-
- if (g->h_version != V6 && win != 0) {
- g->wp[win].y_cursor = 1;
- g->wp[win].x_cursor = 1;
- }
-
- update_cursor (g);
-
- }/* set_window */
-
- /*
- * erase_window
- *
- * Erase a window to background colour.
- *
- */
-
- void erase_window (struct sg *g, zword win)
- {
- zword y = g->wp[win].y_pos;
- zword x = g->wp[win].x_pos;
-
-
- os_erase_area (g,y,
- x,
- y + g->wp[win].y_size - 1,
- x + g->wp[win].x_size - 1);
-
- if (g->h_version == V6 && win != g->cwin && g->h_interpreter_number != INTERP_AMIGA)
-
- reset_cursor (g,win);
-
- g->wp[win].line_count = 0;
-
- }/* erase_window */
-
- /*
- * split_window
- *
- * Divide the screen into upper (1) and lower (0) windows. In V3 the upper
- * window appears below the status line.
- *
- */
-
- void split_window (struct sg *g, zword height)
- {
- zword stat_height = 0;
-
- flush_buffer (g);
-
- /* Calculate height of status line and upper window */
-
- if (g->h_version != V6)
- height *= hi (g->wp[1].font_size);
-
- if (g->h_version <= V3)
- stat_height = hi (g->wp[7].font_size);
-
- /* Cursor of upper window mustn't be swallowed by the lower window */
-
- g->wp[1].y_cursor += g->wp[1].y_pos - 1 - stat_height;
-
- g->wp[1].y_pos = 1 + stat_height;
- g->wp[1].y_size = height;
-
- if ((short) g->wp[1].y_cursor > (short) g->wp[1].y_size)
- reset_cursor (g, 1);
-
- /* Cursor of lower window mustn't be swallowed by the upper window */
-
- g->wp[0].y_cursor += g->wp[0].y_pos - 1 - stat_height - height;
-
- g->wp[0].y_pos = 1 + stat_height + height;
- g->wp[0].y_size = g->h_screen_height - stat_height - height;
-
- if ((short) (g->wp[0].y_cursor) < 1)
- reset_cursor (g,0);
-
- /* Erase the upper window in V3 only */
-
- if (g->h_version == V3 && height != 0)
- erase_window (g,1);
-
- }/* split_window */
-
- /*
- * erase_screen
- *
- * Erase the entire screen to background colour.
- *
- */
-
- void erase_screen (struct sg *g, zword win)
- {
- short i;
-
- os_erase_area (g,1, 1, g->h_screen_height, g->h_screen_width);
-
- if ((short) win == -1) {
- split_window (g,0);
- set_window (g,0);
- reset_cursor (g,0);
- }
-
- for (i = 0; i < 8; i++)
- g->wp[i].line_count = 0;
-
- }/* erase_screen */
-
- /*
- * restart_screen
- *
- * Prepare the screen for a new game.
- *
- */
-
- void restart_screen (struct sg *g)
- {
-
- /* Use default settings */
-
- //os_set_colour (h_default_foreground, h_default_background);
-
- if (os_font_data (g,TEXT_FONT, &(g->font_height), &(g->font_width)))
- os_set_font (g,TEXT_FONT);
-
- os_set_text_style (g,0);
-
- g->cursor = TRUE;
-
- /* Initialise window properties */
-
- g->mwin = 1;
-
- for (g->cwp = g->wp; g->cwp < g->wp + 8; (g->cwp)++) {
- g->cwp->y_pos = 1;
- g->cwp->x_pos = 1;
- g->cwp->y_size = 0;
- g->cwp->x_size = 0;
- g->cwp->y_cursor = 1;
- g->cwp->x_cursor = 1;
- g->cwp->left = 0;
- g->cwp->right = 0;
- g->cwp->nl_routine = 0;
- g->cwp->nl_countdown = 0;
- g->cwp->style = 0;
- g->cwp->colour = (g->h_default_background << 8) | g->h_default_foreground;
- g->cwp->font = TEXT_FONT;
- g->cwp->font_size = (g->font_height << 8) | g->font_width;
- g->cwp->attribute = 8;
- }
-
- /* Prepare lower/upper windows and status line */
-
- g->wp[0].attribute = 15;
-
- g->wp[0].left = g->option_left_margin;
- g->wp[0].right = g->option_right_margin;
-
- g->wp[0].x_size = g->h_screen_width;
- g->wp[1].x_size = g->h_screen_width;
-
- if (g->h_version <= V3)
- g->wp[7].x_size = g->h_screen_width;
-
- os_restart_game (g,RESTART_WPROP_SET);
-
- /* Clear the screen, unsplit it and select window 0 */
-
- erase_screen (g,(word) (-1));
-
- }/* restart_screen */
-
- /*
- * validate_click
- *
- * Return false if the last mouse click occured outside the current
- * mouse window; otherwise write the mouse arrow coordinates to the
- * memory of the header extension table and return true.
- *
- */
-
- short validate_click (struct sg *g)
- {
-
- if (g->mwin >= 0) {
-
- if (g->mouse_y < g->wp[g->mwin].y_pos || g->mouse_y >= g->wp[g->mwin].y_pos + g->wp[g->mwin].y_size)
- return FALSE;
- if (g->mouse_x < g->wp[g->mwin].x_pos || g->mouse_x >= g->wp[g->mwin].x_pos + g->wp[g->mwin].x_size)
- return FALSE;
-
- g->hx_mouse_y = g->mouse_y - g->wp[g->mwin].y_pos + 1;
- g->hx_mouse_x = g->mouse_x - g->wp[g->mwin].x_pos + 1;
-
- } else {
-
- if (g->mouse_y < 1 || g->mouse_y > g->h_screen_height)
- return FALSE;
- if (g->mouse_x < 1 || g->mouse_x > g->h_screen_width)
- return FALSE;
-
- g->hx_mouse_y = g->mouse_y;
- g->hx_mouse_x = g->mouse_x;
-
- }
-
- if (g->h_version != V6) {
- g->hx_mouse_y = (g->hx_mouse_y - 1) / g->h_font_height + 1;
- g->hx_mouse_x = (g->hx_mouse_x - 1) / g->h_font_width + 1;
- }
-
- set_header_extension (g,HX_MOUSE_Y, g->hx_mouse_y);
- set_header_extension (g,HX_MOUSE_X, g->hx_mouse_x);
-
- return TRUE;
-
- }/* validate_click */
-
- /*
- * screen_mssg_on
- *
- * Start printing a so-called debugging message. The contents of the
- * message are passed to the message stream, a Frotz specific output
- * stream with maximum priority.
- *
- */
-
- void screen_mssg_on (struct sg *g)
- {
-
- if (g->cwin == 0) { /* messages in window 0 only */
-
- os_set_text_style (g,0);
-
- if (g->cwp->x_cursor != g->cwp->left + 1)
- screen_new_line (g);
-
- screen_char (g,ZC_INDENT);
-
- } else g->discarding = TRUE; /* discard messages in other windows */
-
- }/* screen_mssg_on */
-
- /*
- * screen_mssg_off
- *
- * Stop printing a "debugging" message.
- *
- */
-
- void screen_mssg_off (struct sg *g)
- {
-
- if (g->cwin == 0) { /* messages in window 0 only */
-
- screen_new_line (g);
-
- refresh_text_style (g);
-
- } else g->discarding = FALSE; /* message has been discarded */
-
- }/* screen_mssg_off */
-
- /*
- * z_buffer_mode, turn text buffering on/off.
- *
- * zargs[0] = new text buffering flag (0 or 1)
- *
- */
-
- void z_buffer_mode (struct sg *g)
- {
-
- /* Infocom's V6 games rarely use the buffer_mode opcode. If they do
- then only to print text immediately, without any delay. This was
- used to give the player some sign of life while the game was
- spending much time on parsing a complicated input line. (To turn
- off word wrapping, V6 games use the window_style opcode instead.)
- Today we can afford to ignore buffer_mode in V6. */
-
- if (g->h_version != V6) {
-
- flush_buffer (g);
-
- g->wp[0].attribute &= ~8;
-
- if (g->zargs[0] != 0)
- g->wp[0].attribute |= 8;
-
- update_attributes (g);
-
- }
-
- }/* z_buffer_mode */
-
- /*
- * z_draw_picture, draw a picture.
- *
- * zargs[0] = number of picture to draw
- * zargs[1] = y-coordinate of top left corner
- * zargs[2] = x-coordinate of top left corner
- *
- */
-
- void z_draw_picture (struct sg *g)
- {
- zword pic = g->zargs[0];
-
- zword y = g->zargs[1];
- zword x = g->zargs[2];
-
- short i;
-
- flush_buffer (g);
-
- if (y == 0) /* use cursor line if y-coordinate is 0 */
- y = g->cwp->y_cursor;
- if (x == 0) /* use cursor column if x-coordinate is 0 */
- x = g->cwp->x_cursor;
-
- y += g->cwp->y_pos - 1;
- x += g->cwp->x_pos - 1;
-
- /* The following is necessary to make Amiga and Macintosh story
- files work with MCGA graphics files. Some screen-filling
- pictures of the original Amiga release like the borders of
- Zork Zero were split into several MCGA pictures (left, right
- and top borders). We pretend this has not happened. */
-
- for (i = 0; g->mapper[i].story_id != UNKNOWN; i++)
-
- if (g->story_id == g->mapper[i].story_id && pic == g->mapper[i].pic) {
-
- short delta = 0;
-
- /*os_picture_data (pic, &height1, &width1);
- os_picture_data (mapper[i].pic2, &height2, &width2); */
-
- if (g->story_id == ARTHUR && pic == 54)
- delta = g->h_screen_width / 160;
-
- /* os_draw_picture (mapper[i].pic1, y + height1, x + delta);
- os_draw_picture (mapper[i].pic2, y + height1, x + width1 - width2 - delta);*/
-
- }
-
- /*os_draw_picture (pic, y, x);*/
-
- if (g->story_id == SHOGUN)
-
- if (pic == 3) {
-
- /* short height, width;
-
- os_picture_data (59, &height, &width);
- os_draw_picture (59, y, h_screen_width - width + 1);*/
-
- }
-
- }/* z_draw_picture */
-
- /*
- * z_erase_line, erase the line starting at the cursor position.
- *
- * zargs[0] = 1 + #units to erase (1 clears to the end of the line)
- *
- */
-
- void z_erase_line (struct sg *g)
- {
- zword pixels = g->zargs[0];
- zword y, x;
-
- flush_buffer (g);
-
- /* Clipping at the right margin of the current window */
-
- if (--pixels == 0 || pixels > units_left (g))
- pixels = units_left (g);
-
- /* Erase from cursor position */
-
- y = g->cwp->y_pos + g->cwp->y_cursor - 1;
- x = g->cwp->x_pos + g->cwp->x_cursor - 1;
-
- // Corrected following code as line was not being erased correctly, perhaps
- // bug a in original Frotz engine?
- // os_erase_area (g, y, x, y + g->font_height - 1, x + pixels - 1);
- os_erase_area (g, y, x, y + g->font_height - 1, x + pixels);
-
- }/* z_erase_line */
-
- /*
- * z_erase_picture, erase a picture with background colour.
- *
- * zargs[0] = number of picture to erase
- * zargs[1] = y-coordinate of top left corner (optional)
- * zargs[2] = x-coordinate of top left corner (optional)
- *
- */
-
- void z_erase_picture (struct sg *g)
- {
- // short height, width;
- //
- // zword y = g->zargs[1];
- // zword x = g->zargs[2];
- //
- flush_buffer (g);
- //
- // if (y == 0) /* use cursor line if y-coordinate is 0 */
- // y = g->cwp->y_cursor;
- // if (x == 0) /* use cursor column if x-coordinate is 0 */
- // x = g->cwp->x_cursor;
- //
- // os_picture_data (zargs[0], &height, &width);
- // y += g->cwp->y_pos - 1;
- // x += g->cwp->x_pos - 1;
- //
- // os_erase_area (g,y, x, y + height - 1, x + width - 1);
-
- }/* z_erase_picture */
-
- /*
- * z_erase_window, erase a window or the screen to background colour.
- *
- * zargs[0] = window (-3 current, -2 screen, -1 screen & unsplit)
- *
- */
-
- void z_erase_window (struct sg *g)
- {
-
- flush_buffer (g);
-
- if ((short) (g->zargs[0]) == -1 || (short) (g->zargs[0]) == -2)
- erase_screen (g,g->zargs[0]);
- else
- erase_window (g,winarg0 (g));
-
- }/* z_erase_window */
-
- /*
- * z_get_cursor, write the cursor coordinates into a table.
- *
- * zargs[0] = address to write information to
- *
- */
-
- void z_get_cursor (struct sg *g)
- {
- zword y, x;
-
- flush_buffer (g);
-
- y = g->cwp->y_cursor;
- x = g->cwp->x_cursor;
-
- if (g->h_version != V6) { /* convert to grid positions */
- y = (y - 1) / g->h_font_height + 1;
- x = (x - 1) / g->h_font_width + 1;
- }
-
- storew (g,(zword) (g->zargs[0] + 0), y);
- storew (g,(zword) (g->zargs[0] + 2), x);
-
- }/* z_get_cursor */
-
- /*
- * z_get_wind_prop, store the value of a window property.
- *
- * zargs[0] = window (-3 is the current one)
- * zargs[1] = number of window property to be stored
- *
- */
-
- void z_get_wind_prop (struct sg *g)
- {
-
- flush_buffer (g);
-
- if (g->zargs[1] >= 16)
- runtime_error (g,"Illegal window property");
-
- store (g,((zword *) (g->wp + winarg0 (g))) [g->zargs[1]]);
-
- }/* z_get_wind_prop */
-
- /*
- * z_mouse_window, select a window as mouse window.
- *
- * zargs[0] = window number (-3 is the current) or -1 for the screen
- *
- */
-
- void z_mouse_window (struct sg *g)
- {
-
- g->mwin = ((short) (g->zargs[0]) == -1) ? -1 : winarg0 (g);
-
- }/* z_mouse_window */
-
- /*
- * z_move_window, place a window on the screen.
- *
- * zargs[0] = window (-3 is the current one)
- * zargs[1] = y-coordinate
- * zargs[2] = x-coordinate
- *
- */
-
- void z_move_window (struct sg *g)
- {
- zword win = winarg0 (g);
-
- flush_buffer (g);
-
- g->wp[win].y_pos = g->zargs[1];
- g->wp[win].x_pos = g->zargs[2];
-
- if (win == g->cwin)
- update_cursor (g);
-
- }/* z_move_window */
-
- /*
- * z_picture_data, get information on a picture or the graphics file.
- *
- * zargs[0] = number of picture or 0 for the graphics file
- * zargs[1] = address to write information to
- *
- */
-
- void z_picture_data (struct sg *g)
- {
- zword pic = g->zargs[0];
- zword table = g->zargs[1];
-
- /* short height, width;
- short i;
-
- short avail = os_picture_data (pic, &height, &width);
-
- for (i = 0; mapper[i].story_id != UNKNOWN; i++)
-
- if (story_id == mapper[i].story_id)
-
- if (pic == mapper[i].pic) {
-
- short height2, width2;
-
- avail &= os_picture_data (mapper[i].pic1, &height2, &width2);
- avail &= os_picture_data (mapper[i].pic2, &height2, &width2);
-
- height += height2;
-
- } else if (pic == mapper[i].pic1 || pic == mapper[i].pic2)
-
- avail = FALSE;
-
- storew ((zword) (table + 0), (zword) (height));
- storew ((zword) (table + 2), (zword) (width));
-
- branch (avail);*/
- branch(g,FALSE);
-
- }/* z_picture_data */
-
- /*
- * z_picture_table, prepare a group of pictures for faster display.
- *
- * zargs[0] = address of table holding the picture numbers
- *
- */
-
- void z_picture_table (struct sg *g)
- {
-
- /* This opcode is used by Shogun and Zork Zero when the player
- encounters built-in games such as Peggleboz. Nowadays it is
- not very helpful to hold the picture data in memory because
- even a small disk cache avoids re-loading of data. */
-
- }/* z_picture_table */
-
- /*
- * z_print_table, print ASCII text in a rectangular area.
- *
- * zargs[0] = address of text to be printed
- * zargs[1] = width of rectangular area
- * zargs[2] = height of rectangular area (optional)
- * zargs[3] = number of char's to skip between lines (optional)
- *
- */
-
- void z_print_table (struct sg *g)
- {
- zword addr = g->zargs[0];
- zword x;
- short i, j;
-
- flush_buffer (g);
-
- /* Supply default arguments */
-
- if (g->zargc < 3)
- g->zargs[2] = 1;
- if (g->zargc < 4)
- g->zargs[3] = 0;
-
- /* Write text in width x height rectangle */
-
- x = g->cwp->x_cursor;
-
- for (i = 0; i < g->zargs[2]; i++) {
-
- if (i != 0) {
-
- flush_buffer (g);
-
- g->cwp->y_cursor += g->font_height;
- g->cwp->x_cursor = x;
-
- update_cursor (g);
-
- }
-
- for (j = 0; j < g->zargs[1]; j++) {
-
- zbyte c;
-
- LOW_BYTE (addr, c)
- addr++;
-
- print_char (g,c);
-
- }
-
- addr += g->zargs[3];
-
- }
-
- }/* z_print_table */
-
- /*
- * z_put_wind_prop, set the value of a window property.
- *
- * zargs[0] = window (-3 is the current one)
- * zargs[1] = number of window property to set
- * zargs[2] = value to set window property to
- *
- */
-
- void z_put_wind_prop (struct sg *g)
- {
-
- flush_buffer (g);
-
- if (g->zargs[1] >= 16)
- runtime_error (g,"Illegal window property");
-
- ((zword *) (g->wp + winarg0 (g))) [g->zargs[1]] = g->zargs[2];
-
- }/* z_put_wind_prop */
-
- /*
- * z_scroll_window, scroll a window up or down.
- *
- * zargs[0] = window (-3 is the current one)
- * zargs[1] = #screen units to scroll up (positive) or down (negative)
- *
- */
-
- void z_scroll_window (struct sg *g)
- {
- zword win = winarg0 (g);
- zword y, x;
-
- flush_buffer (g);
-
- /* Use the correct set of colours when scrolling the window */
-
-
- y = g->wp[win].y_pos;
- x = g->wp[win].x_pos;
-
- os_scroll_area (g,y,
- x,
- y + g->wp[win].y_size - 1,
- x + g->wp[win].x_size - 1,
- (short) g->zargs[1]);
-
-
- }/* z_scroll_window */
-
- /*
- * z_set_colour, set the foreground and background colours.
- *
- * zargs[0] = foreground colour
- * zargs[1] = background colour
- * zargs[2] = window (-3 is the current one, optional)
- *
- */
-
- void z_set_colour (struct sg *g)
- {
- flush_buffer (g);
-
- g->fg = 1;
- g->bg = 0;
-
- }/* z_set_colour */
-
- /*
- * z_set_font, set the font for text output and store the previous font.
- *
- * zargs[0] = number of font or 0 to keep current font
- *
- */
-
- void z_set_font (struct sg *g)
- {
- zword win = (g->h_version == V6) ? g->cwin : 0;
- zword font = g->zargs[0];
-
- if (font != 0) {
-
- if (g->story_id == JOURNEY && font == 4) /* Journey uses fixed fonts */
- font = 1; /* for most interpreter #'s */
-
- if (os_font_data (g,font, &(g->font_height), &(g->font_width))) {
-
- store (g,g->wp[win].font);
-
- g->wp[win].font = font;
- g->wp[win].font_size = (g->font_height << 8) | g->font_width;
-
- if (!g->ostream_memory && g->ostream_screen && g->enable_buffering) {
-
- print_char (g,ZC_NEW_FONT);
- print_char (g,(unsigned char)font);
-
- } else os_set_font (g,font);
-
- } else store (g,0);
-
- } else store (g,g->wp[win].font);
-
- }/* z_set_font */
-
- /*
- * z_set_cursor, set the cursor position or turn the cursor on/off.
- *
- * zargs[0] = y-coordinate or -2/-1 for cursor on/off
- * zargs[1] = x-coordinate
- * zargs[2] = window (-3 is the current one, optional)
- *
- */
-
- void z_set_cursor (struct sg *g)
- {
- zword win = (g->h_version == V6) ? winarg2 (g) : 1;
-
- zword y = g->zargs[0];
- zword x = g->zargs[1];
-
- flush_buffer (g);
-
- /* Supply default arguments */
-
- if (g->zargc < 3)
- g->zargs[2] = 0xFFFD; // -3
-
- /* Handle cursor on/off */
-
- if ((short) y < 0) {
-
- if ((short) y == -2)
- g->cursor = TRUE;
- if ((short) y == -1)
- g->cursor = FALSE;
-
- return;
-
- }
-
- /* Convert grid positions to screen units if this is not V6 */
-
- if (g->h_version != V6) {
-
- if (g->cwin == 0)
- return;
-
- y = (y - 1) * g->h_font_height + 1;
- x = (x - 1) * g->h_font_width + 1;
-
- }
-
- /* Protect the margins */
-
- if (x <= g->wp[win].left || x > g->wp[win].x_size - g->wp[win].right)
- x = g->wp[win].left + 1;
-
- /* Move the cursor */
-
- g->wp[win].y_cursor = y;
- g->wp[win].x_cursor = x;
-
- if (win == g->cwin)
- update_cursor (g);
-
- }/* z_set_cursor */
-
- /*
- * z_set_margins, set the left and right margins of a window.
- *
- * zargs[0] = left margin in pixels
- * zargs[1] = right margin in pixels
- * zargs[2] = window (-3 is the current one, optional)
- *
- */
-
- void z_set_margins (struct sg *g)
- {
- zword win = winarg2 (g);
-
- flush_buffer (g);
-
- g->wp[win].left = g->zargs[0];
- g->wp[win].right = g->zargs[1];
-
- /* Protect the margins */
-
- if (g->wp[win].x_cursor <= g->zargs[0] || g->wp[win].x_cursor > g->wp[win].x_size - g->zargs[1]) {
-
- g->wp[win].x_cursor = g->zargs[0] + 1;
-
- if (win == g->cwin)
- update_cursor (g);
-
- }
-
- }/* z_set_margins */
-
- /*
- * z_set_text_style, set the style for text output.
- *
- * zargs[0] = style flags to set or 0 to reset text style
- *
- */
-
- void z_set_text_style (struct sg *g)
- {
- zword win = (g->h_version == V6) ? g->cwin : 0;
- zword style = g->zargs[0];
-
- g->wp[win].style |= style;
-
- if (style == 0)
- g->wp[win].style = 0;
-
- refresh_text_style (g);
-
- }/* z_set_text_style */
-
- /*
- * z_set_window, select the current window.
- *
- * zargs[0] = window to be selected (-3 is the current one)
- *
- */
-
- void z_set_window (struct sg *g)
- {
-
- set_window (g,winarg0 (g));
-
- }/* z_set_window */
-
- /*
- * pad_status_line
- *
- * Pad the status line with spaces up to the given position.
- *
- */
-
- void pad_status_line (struct sg *g, short column)
- {
- short spaces;
-
- flush_buffer (g);
-
- spaces = units_left (g) / 1 - column;
-
- while (spaces--)
- screen_char (g,' ');
-
- }/* pad_status_line */
-
- /*
- * z_show_status, display the status line for V1 to V3 games.
- *
- * no zargs used
- *
- */
-
- void z_show_status (struct sg *g)
- {
- zword global0;
- zword global1;
- zword global2;
- zword addr;
-
- short brief = FALSE;
-
- /* One V5 game (Wishbringer Solid Gold) contains this opcode by
- accident, so just return if the version number does not fit */
-
- if (g->h_version >= V4)
- return;
-
- /* Read all relevant global variables from the memory of the
- Z-machine into local variables */
-
- addr = g->h_globals;
- LOW_WORD (addr, global0)
- addr += 2;
- LOW_WORD (addr, global1)
- addr += 2;
- LOW_WORD (addr, global2)
-
- /* Frotz uses window 7 for the status line. Don't forget to select
- reverse and fixed width text style */
-
- set_window (g,7);
-
- print_char (g,ZC_NEW_STYLE);
- print_char (g,REVERSE_STYLE | FIXED_WIDTH_STYLE);
-
- /* If the screen width is below 55 characters then we have to use
- the brief status line format */
-
- if (g->h_screen_cols < 55)
- brief = TRUE;
-
- /* Print the object description for the global variable 0 */
-
- print_char (g,' ');
- print_object (g,global0);
-
- /* A header flag tells us whether we have to display the current
- time or the score/moves information */
-
- if (g->h_config & CONFIG_TIME) { /* print hours and minutes */
-
- zword hours = (global1 + 11) % 12 + 1;
-
- pad_status_line (g,brief ? 15 : 20);
-
- print_string (g,"Time: ");
-
- if (hours < 10)
- print_char (g,' ');
- print_num (g,hours);
-
- print_char (g,':');
-
- if (global2 < 10)
- print_char (g,'0');
- print_num (g,global2);
-
- print_char (g,' ');
-
- print_char (g,(global1 >= 12) ? 'p' : 'a');
- print_char (g,'m');
-
- } else { /* print score and moves */
-
- pad_status_line (g,brief ? 15 : 30);
-
- print_string (g,brief ? "S: " : "Score: ");
- print_num (g,global1);
-
- pad_status_line (g,brief ? 8 : 14);
-
- print_string (g,brief ? "M: " : "Moves: ");
- print_num (g,global2);
-
- }
-
- /* Pad the end of the status line with spaces */
-
- pad_status_line (g,0);
-
- /* Return to the lower window */
-
- set_window (g,0);
-
- }/* z_show_status */
-
- /*
- * z_split_window, split the screen into an upper (1) and lower (0) window.
- *
- * zargs[0] = height of upper window in screen units (V6) or #lines
- *
- */
-
- void z_split_window (struct sg *g)
- {
-
- split_window (g,g->zargs[0]);
-
- }/* z_split_window */
-
- /*
- * z_window_size, change the width and height of a window.
- *
- * zargs[0] = window (-3 is the current one)
- * zargs[1] = new height in screen units
- * zargs[2] = new width in screen units
- *
- */
-
- void z_window_size (struct sg *g)
- {
- zword win = winarg0 (g);
-
- flush_buffer (g);
-
- g->wp[win].y_size = g->zargs[1];
- g->wp[win].x_size = g->zargs[2];
-
- /* Keep the cursor within the window */
-
- if (g->wp[win].y_cursor > g->zargs[1] || g->wp[win].x_cursor > g->zargs[2])
- reset_cursor (g,win);
-
- }/* z_window_size */
-
- /*
- * z_window_style, set / clear / toggle window attributes.
- *
- * zargs[0] = window (-3 is the current one)
- * zargs[1] = window attribute flags
- * zargs[2] = operation to perform (optional, defaults to 0)
- *
- */
-
- void z_window_style (struct sg *g)
- {
- zword win = winarg0 (g);
- zword flags = g->zargs[1];
-
- flush_buffer (g);
-
- /* Supply default arguments */
-
- if (g->zargc < 3)
- g->zargs[2] = 0;
-
- /* Set window style */
-
- switch (g->zargs[2]) {
- case 0: g->wp[win].attribute = flags; break;
- case 1: g->wp[win].attribute |= flags; break;
- case 2: g->wp[win].attribute &= ~flags; break;
- case 3: g->wp[win].attribute ^= flags; break;
- }
-
- if (g->cwin == win)
- update_attributes (g);
-
- }/* z_window_style */
-