Codebase list frotz / upstream/2.32r2 ux_text.c
upstream/2.32r2

Tree @upstream/2.32r2 (Download .tar.gz)

ux_text.c @upstream/2.32r2raw · history · blame

/*
 * ux_text.c
 *
 * Unix interface, text functions
 *
 */

#define __UNIX_PORT_FILE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef USE_NCURSES_H
#include <ncurses.h>
#else
#include <curses.h>
#endif

#include "frotz.h"
#include "ux_frotz.h"

#ifdef COLOR_SUPPORT
int current_color = 0;
#endif

static char latin1_to_ascii[] =
    "   !  c  L  >o<Y  |  S  '' C  a  << not-  R  _  "
    "^0 +/-^2 ^3 '  my P  .  ,  ^1 o  >> 1/41/23/4?  "
    "A  A  A  A  Ae A  AE C  E  E  E  E  I  I  I  I  "
    "Th N  O  O  O  O  Oe *  O  U  U  U  Ue Y  Th ss "
    "a  a  a  a  ae a  ae c  e  e  e  e  i  i  i  i  "
    "th n  o  o  o  o  oe :  o  u  u  u  ue y  th y  ";
/*
 * os_font_data
 *
 * Return true if the given font is available. The font can be
 *
 *    TEXT_FONT
 *    PICTURE_FONT
 *    GRAPHICS_FONT
 *    FIXED_WIDTH_FONT
 *
 * The font size should be stored in "height" and "width". If
 * the given font is unavailable then these values must _not_
 * be changed.
 *
 */

int os_font_data (int font, int *height, int *width)
{

    if (font == TEXT_FONT) {
      *height = 1; *width = 1; return 1; /* Truth in advertising */
    }
    return 0;

}/* os_font_data */

#ifdef COLOR_SUPPORT
/*
 * unix_convert
 *
 * Converts frotz's (and Infocom's) color values to ncurses color values.
 *
 */

static int unix_convert(int color)
{
  switch(color) {
        case BLACK_COLOUR: return COLOR_BLACK;
        case RED_COLOUR: return COLOR_RED;
        case GREEN_COLOUR: return COLOR_GREEN;
        case YELLOW_COLOUR: return COLOR_YELLOW;
        case BLUE_COLOUR: return COLOR_BLUE;
        case MAGENTA_COLOUR: return COLOR_MAGENTA;
        case CYAN_COLOUR: return COLOR_CYAN;
        case WHITE_COLOUR: return COLOR_WHITE;
  }
  return 0;
}
#endif

/*
 * os_set_colour
 *
 * Set the foreground and background colours which can be:
 *
 *     DEFAULT_COLOUR
 *     BLACK_COLOUR
 *     RED_COLOUR
 *     GREEN_COLOUR
 *     YELLOW_COLOUR
 *     BLUE_COLOUR
 *     MAGENTA_COLOUR
 *     CYAN_COLOUR
 *     WHITE_COLOUR
 *
 *     MS-DOS 320 columns MCGA mode only:
 *
 *     GREY_COLOUR
 *
 *     Amiga only:
 *
 *     LIGHTGREY_COLOUR
 *     MEDIUMGREY_COLOUR
 *     DARKGREY_COLOUR
 *
 * There may be more colours in the range from 16 to 255; see the
 * remarks on os_peek_colour.
 *
 */

#ifdef COLOR_SUPPORT
static int colorspace[10][10];
static int count = 0;
#endif

void os_set_colour (int new_foreground, int new_background)
{
#ifdef COLOR_SUPPORT
    int saved_style;

    saved_style = current_text_style;
    if (new_foreground == 1) new_foreground = h_default_foreground;
    if (new_background == 1) new_background = h_default_background;
    if (!colorspace[new_foreground][new_background]) {
      init_pair(++count, unix_convert(new_foreground), unix_convert(new_background));
      colorspace[new_foreground][new_background] = count;
    }
    current_color = COLOR_PAIR(colorspace[new_foreground][new_background]);
    os_set_text_style(saved_style);

#endif
}/* os_set_colour */

/*
 * os_set_text_style
 *
 * Set the current text style. Following flags can be set:
 *
 *     REVERSE_STYLE
 *     BOLDFACE_STYLE
 *     EMPHASIS_STYLE (aka underline aka italics)
 *     FIXED_WIDTH_STYLE
 *
 */

void os_set_text_style (int new_style)
{
    int temp = 0;

    current_text_style = new_style;
    if (new_style & REVERSE_STYLE) temp |= A_REVERSE;
    if (new_style & BOLDFACE_STYLE) temp |= A_BOLD;
    if (new_style & EMPHASIS_STYLE) temp |= A_UNDERLINE;
#ifdef COLOR_SUPPORT
    attrset(temp | current_color);
#else
    attrset(temp);
#endif

}/* os_set_text_style */

/*
 * os_set_font
 *
 * Set the font for text output. The interpreter takes care not to
 * choose fonts which aren't supported by the interface.
 *
 */

void os_set_font (int new_font)
{

    /* Not implemented */

}/* os_set_font */

/*
 * os_display_char
 *
 * Display a character of the current font using the current colours and
 * text style. The cursor moves to the next position. Printable codes are
 * all ASCII values from 32 to 126, ISO Latin-1 characters from 160 to
 * 255, ZC_GAP (gap between two sentences) and ZC_INDENT (paragraph
 * indentation). The screen should not be scrolled after printing to the
 * bottom right corner.
 *
 */

void os_display_char (zchar c)
{

    if (c >= ZC_LATIN1_MIN && c <= ZC_LATIN1_MAX) {
        if (unix_plain_ascii) {

	  char *ptr = latin1_to_ascii + 3 * (c - ZC_LATIN1_MIN);
	  char c1 = *ptr++;
	  char c2 = *ptr++;
	  char c3 = *ptr++;

	  addch(c1);

	  if (c2 != ' ')
	    addch(c2);
	  if (c3 != ' ')
	    addch(c3);

	} else
	  addch(c);
	return;
    }
    if (c >= 32 && c <= 126) {
        addch(c);
	return;
    }
    if (c == ZC_INDENT) {
      addch(' '); addch(' '); addch(' ');
      return;
    }
    if (c == ZC_GAP) {
      addch(' '); addch(' ');
      return;
    }

}/* os_display_char */

/*
 * os_display_string
 *
 * Pass a string of characters to os_display_char.
 *
 */

void os_display_string (const zchar *s)
{

    zchar c;

    while ((c = (unsigned char) *s++) != 0)

        if (c == ZC_NEW_FONT || c == ZC_NEW_STYLE) {

            int arg = (unsigned char) *s++;

            if (c == ZC_NEW_FONT)
                os_set_font (arg);
            if (c == ZC_NEW_STYLE)
                os_set_text_style (arg);

        } else os_display_char (c);

}/* os_display_string */

/*
 * os_char_width
 *
 * Return the width of the character in screen units.
 *
 */

int os_char_width (zchar c)
{

    if (c >= ZC_LATIN1_MIN && c <= ZC_LATIN1_MAX && unix_plain_ascii) {

        int width = 0;
        const char *ptr = latin1_to_ascii + 3 * (c - ZC_LATIN1_MIN);
	char c1 = *ptr++;
	char c2 = *ptr++;
	char c3 = *ptr++;

	width++;
	if (c2 != ' ')
	  width++;
	if (c3 != ' ')
	  width++;
	return width;
    }
    return 1;

}/* os_char_width*/

/*
 * os_string_width
 *
 * Calculate the length of a word in screen units. Apart from letters,
 * the word may contain special codes:
 *
 *    NEW_STYLE - next character is a new text style
 *    NEW_FONT  - next character is a new font
 *
 */

int os_string_width (const zchar *s)
{
    int width = 0;
    zchar c;

    while ((c = *s++) != 0)

      if (c == ZC_NEW_STYLE || c == ZC_NEW_FONT) {

	s++;
	/* No effect */

      } else width += os_char_width(c);

    return width;

}/* os_string_width */

/*
 * os_set_cursor
 *
 * Place the text cursor at the given coordinates. Top left is (1,1).
 *
 */

void os_set_cursor (int y, int x)
{

    /* Curses thinks the top left is (0,0) */
    move(--y, --x);

}/* os_set_cursor */

/*
 * os_more_prompt
 *
 * Display a MORE prompt, wait for a keypress and remove the MORE
 * prompt from the screen.
 *
 */

void os_more_prompt (void)
{
    int saved_style, saved_x, saved_y;

    /* Save some useful information */
    saved_style = current_text_style;
    getyx(stdscr, saved_y, saved_x);

    os_set_text_style(0);
    addstr("[MORE]");
    os_read_key(0, TRUE);

    move(saved_y, saved_x);
    addstr("      ");
    move(saved_y, saved_x);
    os_set_text_style(saved_style);

}/* os_more_prompt */