/* * mscio.c * * Microsoft C specific screen I/O routines for DOS. * */ #include "ztypes.h" #include #include #include #include #include #define BLACK 0 #define BLUE 1 #define GREEN 2 #define CYAN 3 #define RED 4 #define MAGENTA 5 #define BROWN 6 #define WHITE 7 #define BRIGHT 0x08 #define FLASH 0x10 static int screen_started = FALSE; static int cursor_saved = OFF; static int saved_row = 0; static int saved_col = 0; static int current_fg = WHITE; static int current_bg = BLUE; #ifdef __STDC__ static int timed_read_key (int, int); static int read_key (void); #else static int timed_read_key (); static int read_key (); #endif #ifdef __STDC__ void initialize_screen (void) #else void initialize_screen () #endif { _setvideomode (_TEXTC80); if (screen_rows) screen_rows = _settextrows (screen_rows); if (screen_rows == 0) screen_rows = 25; screen_cols = DEFAULT_COLS; _settextwindow (1, 1, screen_rows, screen_cols); _wrapon (_GWRAPOFF); move_cursor (1, 1); set_attribute (NORMAL); clear_screen (); move_cursor (screen_rows / 2 - 1, (screen_cols - sizeof (JZIPVER)) / 2); _outtext (JZIPVER); move_cursor (screen_rows / 2, (screen_cols - sizeof ("The story is loading...")) / 2); _outtext ("The story is loading..."); screen_started = TRUE; h_interpreter = INTERP_MSDOS; JTERP = INTERP_MSDOS; }/* initialize_screen */ #ifdef __STDC__ void restart_screen (void) #else void restart_screen () #endif { cursor_saved = OFF; set_byte (H_CONFIG, (get_byte (H_CONFIG) | CONFIG_WINDOWS)); if (h_type > V3) set_byte (H_CONFIG, (get_byte (H_CONFIG) | CONFIG_EMPHASIS | CONFIG_COLOUR)); set_word (H_FLAGS, get_word (H_FLAGS) & (~GRAPHICS_FLAG)); }/* restart_screen */ #ifdef __STDC__ void reset_screen (void) #else void reset_screen () #endif { if (screen_started == TRUE) { output_new_line (); output_string ("[Hit any key to exit.]"); (void) input_character (0); output_new_line (); _setvideomode (_DEFAULTMODE); } screen_started = FALSE; }/* reset_screen */ #ifdef __STDC__ void clear_screen (void) #else void clear_screen () #endif { _clearscreen (_GWINDOW); }/* clear_screen */ #ifdef __STDC__ void create_status_window (void) #else void create_status_window () #endif { }/* create_status_window */ #ifdef __STDC__ void delete_status_window (void) #else void delete_status_window () #endif { }/* delete_status_window */ #ifdef __STDC__ void select_status_window (void) #else void select_status_window () #endif { save_cursor_position (); _displaycursor (_GCURSOROFF); }/* select_status_window */ #ifdef __STDC__ void select_text_window (void) #else void select_text_window () #endif { _displaycursor (_GCURSORON); restore_cursor_position (); }/* select_text_window */ #ifdef __STDC__ void clear_line (void) #else void clear_line () #endif { int i, row, col; get_cursor_position (&row, &col); for (i = col; i <= screen_rows; i++) { move_cursor (row, i); display_char (' '); } move_cursor (row, col); }/* clear_line */ #ifdef __STDC__ void clear_text_window (void) #else void clear_text_window () #endif { short left, top, right, bottom; int row, col; get_cursor_position (&row, &col); _gettextwindow (&top, &left, &bottom, &right); _settextwindow (status_size + 1, left, bottom, right); _clearscreen (_GWINDOW); _settextwindow (top, left, bottom, right); move_cursor (row, col); }/* clear_text_window */ #ifdef __STDC__ void clear_status_window (void) #else void clear_status_window () #endif { short left, top, right, bottom; int row, col; get_cursor_position (&row, &col); _gettextwindow (&top, &left, &bottom, &right); _settextwindow (1, left, status_size, right); _clearscreen (_GWINDOW); _settextwindow (top, left, bottom, right); move_cursor (row, col); }/* clear_status_window */ #ifdef __STDC__ void move_cursor (int row, int col) #else void move_cursor (row, col) int row; int col; #endif { _settextposition (row, col); }/* move_cursor */ #ifdef __STDC__ void get_cursor_position (int *row, int *col) #else void get_cursor_position (row, col) int *row; int *col; #endif { struct rccoord rc; rc = _gettextposition (); *row = rc.row; *col = rc.col; }/* get_cursor_position */ #ifdef __STDC__ void save_cursor_position (void) #else void save_cursor_position () #endif { if (cursor_saved == OFF) { get_cursor_position (&saved_row, &saved_col); cursor_saved = ON; } }/* save_cursor_position */ #ifdef __STDC__ void restore_cursor_position (void) #else void restore_cursor_position () #endif { if (cursor_saved == ON) { move_cursor (saved_row, saved_col); cursor_saved = OFF; } }/* restore_cursor_position */ #ifdef __STDC__ void set_attribute (int attribute) #else void set_attribute (attribute) int attribute; #endif { int fg, bg, new_fg, new_bg; fg = (int) _gettextcolor (); bg = (int) _getbkcolor (); if (attribute == NORMAL) { new_fg = current_fg; new_bg = current_bg; } if (attribute & REVERSE) { new_fg = bg; new_bg = fg; } if (attribute & BOLD) { new_fg = fg | BRIGHT; new_bg = bg; } if (attribute & EMPHASIS) { new_fg = RED | BRIGHT; new_bg = bg; } if (attribute & FIXED_FONT) { new_fg = fg; new_bg = bg; } _settextcolor ((short) new_fg); _setbkcolor ((long) new_bg); }/* set_attribute */ #ifdef __STDC__ void display_char (int c) #else void display_char (c) int c; #endif { char string[2]; string[0] = (char) c; string[1] = '\0'; _outtext (string); }/* display_char */ #ifdef __STDC__ int input_line (int buflen, char *buffer, int timeout, int *read_size) #else int input_line (buflen, buffer, timeout, read_size) int buflen; char *buffer; int timeout; int *read_size; #endif { struct timeb timenow; struct tm *tmptr; int c, row, col, target_second, target_millisecond; if (timeout != 0) { ftime (&timenow); tmptr = gmtime (&timenow.time); target_second = (tmptr->tm_sec + timeout) % 60; target_millisecond = timenow.millitm; } for ( ; ; ) { /* Read a single keystroke */ do { if (timeout == 0) c = read_key (); else { c = timed_read_key (target_second, target_millisecond); if (c == -1) return (c); } } while (c == 0); if (c == '\b') { /* Delete key action */ if (*read_size == 0) { /* Ring bell if line is empty */ putchar ('\a'); } else { /* Decrement read count */ (*read_size)--; /* Erase last character typed */ get_cursor_position (&row, &col); move_cursor (row, --col); _outtext (" "); move_cursor (row, col); } } else { /* Normal key action */ if (*read_size == (buflen - 1)) { /* Ring bell if buffer is full */ putchar ('\a'); } else { /* Scroll line if return key pressed */ if (c == '\r' || c == '\n') { c = '\n'; scroll_line (); } if (c == '\n' || c >= (unsigned char) '\x080') { /* Return key if it is a line terminator */ return ((unsigned char) c); } else { /* Put key in buffer and display it */ buffer[(*read_size)++] = (char) c; display_char (c); } } } } }/* input_line */ #ifdef __STDC__ int input_character (int timeout) #else int input_character (timeout) int timeout; #endif { struct timeb timenow; struct tm *tmptr; int c, target_second, target_millisecond; if (timeout != 0) { ftime (&timenow); tmptr = gmtime (&timenow.time); target_second = (tmptr->tm_sec + timeout) % 60; target_millisecond = timenow.millitm; } if (timeout == 0) c = read_key (); else c = timed_read_key (target_second, target_millisecond); return (c); }/* input_character */ #ifdef __STDC__ static int timed_read_key (int target_second, int target_millisecond) #else static int timed_read_key (target_second, target_millisecond) int target_second; int target_millisecond; #endif { struct timeb timenow; struct tm *tmptr; int c; for ( ; ; ) { do { ftime (&timenow); tmptr = gmtime (&timenow.time); } while ((bdos (11, 0, 0) & 0xff) == 0 && (tmptr->tm_sec != target_second || (int) timenow.millitm < target_millisecond)); if ((bdos (11, 0, 0) & 0xff) == 0) return (-1); else { c = read_key (); if (c != 0) return (c); } } }/* timed_read_key */ #ifdef __STDC__ static int read_key (void) #else static int read_key () #endif { int c; c = bdos (8, 0, 0) & 0xff; if (c != '\0' && c != (unsigned char) '\x0e0') { if (c == '\x07f') c = '\b'; return (c); } c = bdos (8, 0, 0) & 0xff; if (c == 'H') /* Up arrow */ return ((unsigned char) '\x081'); else if (c == 'P') /* Down arrow */ return ((unsigned char) '\x082'); else if (c == 'K') /* Left arrow */ return ((unsigned char) '\x083'); else if (c == 'M') /* Right arrow */ return ((unsigned char) '\x084'); else if (c >= ';' && c <= 'D') /* Function keys F1 to F10 */ return ((c - ';') + (unsigned char) '\x085'); else if (c == 'O') /* End (SW) */ return ((unsigned char) '\x092'); else if (c == 'Q') /* PgDn (SE) */ return ((unsigned char) '\x094'); else if (c == 'G') /* Home (NW) */ return ((unsigned char) '\x098'); else if (c == 'I') /* PgUp (NE) */ return ((unsigned char) '\x09a'); putchar ('\a'); return (0); }/* read_key */ #ifdef __STDC__ void scroll_line (void) #else void scroll_line () #endif { short left, top, right, bottom; int row, col; get_cursor_position (&row, &col); _gettextwindow (&top, &left, &bottom, &right); if (row == bottom) { _settextwindow (status_size + 1, left, bottom, right); _scrolltextwindow (_GSCROLLUP); _settextwindow (top, left, bottom, right); } else { row++; } move_cursor (row, left); }/* scroll_line */ /* * set_colours * * Sets the screen foreground and background colours. * */ #ifdef __STDC__ void set_colours (int foreground, int background) #else void set_colours (foreground, background) int foreground; int background; #endif { int fg, bg; int colour_map[] = { BLACK, RED, GREEN, BROWN, BLUE, MAGENTA, CYAN, WHITE }; /* Translate from Z-code colour values to natural colour values */ fg = (foreground == 1) ? WHITE : colour_map[foreground - 2]; bg = (background == 1) ? BLUE : colour_map[background - 2]; /* Set foreground and background colour */ _settextcolor ((short) fg); _setbkcolor ((long) bg); /* Save new foreground and background colours for restoring colour */ current_fg = (int) _gettextcolor (); current_bg = (int) _getbkcolor (); }/* set_colours */ /* * codes_to_text * * Translate Z-code characters to machine specific characters. These characters * include line drawing characters and international characters. * * The routine takes one of the Z-code characters from the following table and * writes the machine specific text replacement. The target replacement buffer * is defined by MAX_TEXT_SIZE in ztypes.h. The replacement text should be in a * normal C, zero terminated, string. * * Return 0 if a translation was available, otherwise 1. * * Arrow characters (0x18 - 0x1b): * * 0x18 Up arrow * 0x19 Down arrow * 0x1a Right arrow * 0x1b Left arrow * * International characters (0x9b - 0xa3): * * 0x9b a umlaut (ae) * 0x9c o umlaut (oe) * 0x9d u umlaut (ue) * 0x9e A umlaut (Ae) * 0x9f O umlaut (Oe) * 0xa0 U umlaut (Ue) * 0xa1 sz (ss) * 0xa2 open quote (>>) * 0xa3 close quota (<<) * * Line drawing characters (0xb3 - 0xda): * * 0xb3 vertical line (|) * 0xba double vertical line (#) * 0xc4 horizontal line (-) * 0xcd double horizontal line (=) * all other are corner pieces (+) * */ #ifdef __STDC__ int codes_to_text (int c, char *s) #else int codes_to_text (c, s) int c; char *s; #endif { /* Characters 24 to 27 and 179 to 218 need no translation */ if ((c > 23 && c < 28) || (c > 178 && c < 219)) { s[0] = (char) c; s[1] = '\0'; return (0); } /* German characters need translation */ if (c > 154 && c < 164) { char xlat[9] = { 0x84, 0x94, 0x81, 0x8e, 0x99, 0x9a, 0xe1, 0xaf, 0xae }; s[0] = xlat[c - 155]; s[1] = '\0'; return (0); } return (1); }/* codes_to_text */