/*
 * bc_text.c
 *
 * Borland C interface, text functions
 *
 */

#include <conio.h>
#include <dos.h>
#include "bc_frotz.h"

extern byte far *get_scrnptr (int);

int current_bg = 0;
int current_fg = 0;
int current_style = 0;
int current_font = 0;

byte text_bg = 0;
byte text_fg = 0;

byte scrn_attr = 0;

int cursor_x = 0;
int cursor_y = 0;

extern char euro_substitute[];

unsigned char euro_map[] = {
    0x84, 0x94, 0x81, 0x8e, 0x99, 0x9a, 0xe1, 0xaf, 0xae, 0x89,
    0x8b, 0x98, 0xd3, 0xd8, 0xa0, 0x82, 0xa1, 0xa2, 0xa3, 0xec,
    0xb5, 0x90, 0xd6, 0xe0, 0xe9, 0xed, 0x85, 0x8a, 0x8d, 0x95,
    0x97, 0xb7, 0xd4, 0xde, 0xe3, 0xeb, 0x83, 0x88, 0x8c, 0x93,
    0x96, 0xb6, 0xd2, 0xd7, 0xe2, 0xea, 0x86, 0x8f, 0x9b, 0x9d,
    0xc6, 0xa4, 0xe4, 0xc7, 0xa5, 0xe5, 0x91, 0x92, 0x87, 0x80,
    0xe7, 0xd0, 0xe8, 0xd1, 0x9c, 0x00, 0x00, 0xad, 0xa8
};

static byte graphics_font[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x30, 0x70, 0xff, 0x70, 0x30, 0x00, 0x00,
    0x00, 0x0c, 0x0e, 0xff, 0x0e, 0x0c, 0x00, 0x00,
    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
    0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
    0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
    0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08,
    0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08,
    0x10, 0x10, 0x10, 0x10, 0xf0, 0x10, 0x10, 0x10,
    0x10, 0x10, 0x10, 0x10, 0x1f, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0x10, 0x10, 0x10, 0x10,
    0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08, 0x08,
    0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00,
    0x10, 0x10, 0x10, 0x10, 0x1f, 0x20, 0x40, 0x80,
    0x80, 0x40, 0x20, 0x1f, 0x10, 0x10, 0x10, 0x10,
    0x01, 0x02, 0x04, 0xf8, 0x08, 0x08, 0x08, 0x08,
    0x08, 0x08, 0x08, 0x08, 0xf8, 0x04, 0x02, 0x01,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
    0x08, 0x08, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x08, 0x08,
    0xf8, 0xf8, 0xf8, 0xf8, 0xff, 0xf8, 0xf8, 0xf8,
    0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0x1f, 0x1f,
    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
    0x00, 0x00, 0x00, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
    0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x00, 0x00,
    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x40, 0x80,
    0x80, 0x40, 0x20, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
    0x01, 0x02, 0x04, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
    0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x04, 0x02, 0x01,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x00,
    0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0x00,
    0x00, 0xff, 0xe0, 0xe0, 0xe0, 0xe0, 0xff, 0x00,
    0x00, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0x00,
    0x00, 0xff, 0xf8, 0xf8, 0xf8, 0xf8, 0xff, 0x00,
    0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0x00,
    0x00, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0x00,
    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
    0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
    0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81,
    0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08,
    0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
    0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18,
    0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
    0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff,
    0x00, 0x3c, 0x66, 0x06, 0x18, 0x00, 0x18, 0x00,
    0x63, 0x76, 0x5c, 0x60, 0x78, 0x66, 0x60, 0x00,
    0x78, 0x6e, 0x63, 0x7c, 0x63, 0x6e, 0x78, 0x00,
    0x00, 0x1e, 0x1b, 0x18, 0x18, 0xd8, 0x78, 0x00,
    0x63, 0x63, 0x77, 0x49, 0x77, 0x63, 0x63, 0x00,
    0x63, 0x77, 0x6b, 0x6b, 0x63, 0x63, 0x63, 0x00,
    0x49, 0x52, 0x64, 0x68, 0x70, 0x60, 0x60, 0x00,
    0x00, 0x63, 0x36, 0x1c, 0x1c, 0x36, 0x63, 0x00,
    0x63, 0x53, 0x4f, 0x63, 0x79, 0x65, 0x63, 0x00,
    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00,
    0x18, 0x18, 0x7e, 0x99, 0x7e, 0x18, 0x18, 0x00,
    0x60, 0x60, 0x78, 0x6c, 0x67, 0x63, 0x63, 0x00,
    0x38, 0x3c, 0x36, 0x30, 0x30, 0x30, 0x30, 0x00,
    0x77, 0x6b, 0x77, 0x63, 0x63, 0x63, 0x63, 0x00,
    0x18, 0xd8, 0x78, 0x3c, 0x1e, 0x1b, 0x18, 0x00,
    0x71, 0x6a, 0x64, 0x71, 0x6a, 0x64, 0x60, 0x00,
    0x60, 0x60, 0x63, 0x67, 0x6f, 0x7b, 0x73, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x3c, 0x5a, 0xdb, 0x00,
    0x7c, 0x63, 0x63, 0x7c, 0x66, 0x63, 0x63, 0x00,
    0x60, 0x63, 0x67, 0x6f, 0x7b, 0x73, 0x03, 0x00,
    0x18, 0x3c, 0x5a, 0x99, 0x18, 0x18, 0x18, 0x00,
    0x70, 0x78, 0x6c, 0x66, 0x63, 0x63, 0x63, 0x00,
    0x7e, 0x03, 0x7e, 0x03, 0x03, 0x03, 0x7c, 0x00,
    0x70, 0x6c, 0x63, 0x6c, 0x78, 0x60, 0x60, 0x00,
    0xdb, 0x5a, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00,
    0x78, 0x64, 0x52, 0x49, 0x4f, 0x49, 0x49, 0x00,
    0x60, 0x63, 0x66, 0x6c, 0x78, 0x60, 0x60, 0x00,
    0xe7, 0xc3, 0x81, 0xe7, 0xe7, 0xe7, 0xe7, 0xff,
    0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0x81, 0xc3, 0xe7,
    0xe7, 0xc3, 0x81, 0xe7, 0xe7, 0x81, 0xc3, 0xe7,
    0xff, 0xc3, 0x99, 0xf9, 0xe7, 0xff, 0xe7, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

static byte text_font[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00,
    0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x50, 0xf8, 0x50, 0xf8, 0x50, 0x00, 0x00, 0x00,
    0x20, 0xf8, 0xa0, 0xf8, 0x28, 0xf8, 0x20, 0x00,
    0x90, 0x10, 0x20, 0x40, 0x80, 0x90, 0x00, 0x00,
    0x40, 0xa0, 0x40, 0xa8, 0x90, 0x68, 0x00, 0x00,
    0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x20, 0x40, 0x80, 0x80, 0x80, 0x40, 0x20, 0x00,
    0x80, 0x40, 0x20, 0x20, 0x20, 0x40, 0x80, 0x00,
    0x00, 0x90, 0x60, 0xf0, 0x60, 0x90, 0x00, 0x00,
    0x00, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, 0x00,
    0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
    0x10, 0x10, 0x20, 0x40, 0x80, 0x80, 0x00, 0x00,
    0x60, 0x90, 0x90, 0x90, 0x90, 0x60, 0x00, 0x00,
    0x40, 0xc0, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00,
    0x60, 0x90, 0x20, 0x40, 0x80, 0xf0, 0x00, 0x00,
    0x60, 0x90, 0x20, 0x10, 0x90, 0x60, 0x00, 0x00,
    0xa0, 0xa0, 0xf0, 0x20, 0x20, 0x20, 0x00, 0x00,
    0xf0, 0x80, 0xe0, 0x10, 0x10, 0xe0, 0x00, 0x00,
    0x70, 0x80, 0xe0, 0x90, 0x90, 0x60, 0x00, 0x00,
    0xf0, 0x10, 0x20, 0x40, 0x40, 0x40, 0x00, 0x00,
    0x60, 0x90, 0x60, 0x90, 0x90, 0x60, 0x00, 0x00,
    0x60, 0x90, 0x90, 0x70, 0x10, 0xe0, 0x00, 0x00,
    0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x80, 0x00,
    0x00, 0x20, 0x40, 0x80, 0x40, 0x20, 0x00, 0x00,
    0x00, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0x00,
    0x00, 0x80, 0x40, 0x20, 0x40, 0x80, 0x00, 0x00,
    0x70, 0x88, 0x10, 0x20, 0x00, 0x20, 0x00, 0x00,
    0x60, 0x90, 0xb0, 0xb0, 0x80, 0x70, 0x00, 0x00,
    0x60, 0x90, 0x90, 0xf0, 0x90, 0x90, 0x00, 0x00,
    0xe0, 0x90, 0xe0, 0x90, 0x90, 0xe0, 0x00, 0x00,
    0x70, 0x80, 0x80, 0x80, 0x80, 0x70, 0x00, 0x00,
    0xe0, 0x90, 0x90, 0x90, 0x90, 0xe0, 0x00, 0x00,
    0xf0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x00, 0x00,
    0xf0, 0x80, 0xe0, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x70, 0x80, 0x80, 0xb0, 0x90, 0x70, 0x00, 0x00,
    0x90, 0x90, 0x90, 0xf0, 0x90, 0x90, 0x00, 0x00,
    0xe0, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00,
    0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, 0x00,
    0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x90, 0x00, 0x00,
    0x80, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x00, 0x00,
    0x88, 0xd8, 0xa8, 0x88, 0x88, 0x88, 0x00, 0x00,
    0x90, 0xd0, 0xb0, 0x90, 0x90, 0x90, 0x00, 0x00,
    0x60, 0x90, 0x90, 0x90, 0x90, 0x60, 0x00, 0x00,
    0xe0, 0x90, 0x90, 0xe0, 0x80, 0x80, 0x00, 0x00,
    0x60, 0x90, 0x90, 0x90, 0xb0, 0x70, 0x18, 0x00,
    0xe0, 0x90, 0x90, 0xe0, 0xc0, 0xb0, 0x00, 0x00,
    0x70, 0x80, 0x60, 0x10, 0x90, 0x60, 0x00, 0x00,
    0xf8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x60, 0x00, 0x00,
    0x88, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, 0x00,
    0x88, 0x88, 0x88, 0xa8, 0xd8, 0x88, 0x00, 0x00,
    0x88, 0x50, 0x20, 0x20, 0x50, 0x88, 0x00, 0x00,
    0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00, 0x00,
    0xf0, 0x10, 0x20, 0x40, 0x80, 0xf0, 0x00, 0x00,
    0xc0, 0x80, 0x80, 0x80, 0x80, 0xc0, 0x00, 0x00,
    0x80, 0x80, 0x40, 0x20, 0x10, 0x10, 0x00, 0x00,
    0xc0, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x00, 0x00,
    0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
    0x80, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xe0, 0x20, 0xe0, 0xa0, 0xe0, 0x00, 0x00,
    0x80, 0xe0, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00,
    0x00, 0xe0, 0x80, 0x80, 0x80, 0xe0, 0x00, 0x00,
    0x20, 0xe0, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00,
    0x00, 0xe0, 0xa0, 0xe0, 0x80, 0xe0, 0x00, 0x00,
    0x60, 0x40, 0xe0, 0x40, 0x40, 0x40, 0x00, 0x00,
    0x00, 0xe0, 0xa0, 0xa0, 0xa0, 0xe0, 0x20, 0xe0,
    0x80, 0xe0, 0xa0, 0xa0, 0xa0, 0xa0, 0x00, 0x00,
    0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0,
    0x80, 0xa0, 0xa0, 0xc0, 0xa0, 0xa0, 0x00, 0x00,
    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x00, 0xf8, 0xa8, 0xa8, 0xa8, 0xa8, 0x00, 0x00,
    0x00, 0xe0, 0xa0, 0xa0, 0xa0, 0xa0, 0x00, 0x00,
    0x00, 0xe0, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00,
    0x00, 0xe0, 0xa0, 0xa0, 0xa0, 0xe0, 0x80, 0x80,
    0x00, 0xe0, 0xa0, 0xa0, 0xa0, 0xe0, 0x20, 0x20,
    0x00, 0xe0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x00, 0xe0, 0x80, 0xe0, 0x20, 0xe0, 0x00, 0x00,
    0x40, 0xe0, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
    0x00, 0xa0, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00,
    0x00, 0xa0, 0xa0, 0xa0, 0xa0, 0x40, 0x00, 0x00,
    0x00, 0xa8, 0xa8, 0xa8, 0xa8, 0xf8, 0x00, 0x00,
    0x00, 0xa0, 0xa0, 0x40, 0xa0, 0xa0, 0x00, 0x00,
    0x00, 0xa0, 0xa0, 0xa0, 0xa0, 0xe0, 0x20, 0xe0,
    0x00, 0xe0, 0x20, 0x40, 0x80, 0xe0, 0x00, 0x00,
    0x20, 0x40, 0x40, 0x80, 0x40, 0x40, 0x20, 0x00,
    0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
    0x80, 0x40, 0x40, 0x20, 0x40, 0x40, 0x80, 0x00,
    0x00, 0x00, 0x40, 0xa8, 0x10, 0x00, 0x00, 0x00,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

static byte char_width[] = {
    4, 2, 4, 6, 6, 5, 6, 3,
    4, 4, 5, 6, 3, 5, 2, 5,
    5, 4, 5, 5, 5, 5, 5, 5,
    5, 5, 2, 3, 4, 5, 4, 6,
    5, 5, 5, 5, 5, 5, 5, 5,
    5, 4, 5, 5, 5, 6, 5, 5,
    5, 6, 5, 5, 6, 5, 6, 6,
    6, 6, 5, 3, 5, 3, 6, 5,
    3, 4, 4, 4, 4, 4, 4, 4,
    4, 2, 3, 4, 2, 6, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 6,
    4, 4, 4, 4, 2, 4, 6, 4
};

/*
 * 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)
{

    /* All fonts of this interface have the same size */

    *height = h_font_height;
    *width = h_font_width;

    /* Not every font is available in every mode */

    if (font == TEXT_FONT)
	return 1;
    if (font == GRAPHICS_FONT && (display == _CGA_ || display >= _EGA_))
	return 1;
    if (font == FIXED_WIDTH_FONT)
	return 1;

    /* Unavailable font */

    return 0;

}/* os_font_data */

/*
 * adjust_style
 *
 * Set the current colours. This combines the current colour selection
 * and the current text style.
 *
 */

static void adjust_style (void)
{
    static byte amiga_palette[][3] = {
	{ 0x00, 0x00, 0x00 },
	{ 0x2a, 0x00, 0x00 },
	{ 0x00, 0x2a, 0x00 },
	{ 0x3f, 0x3f, 0x15 },
	{ 0x00, 0x00, 0x2a },
	{ 0x2a, 0x00, 0x2a },
	{ 0x00, 0x2a, 0x2a },
	{ 0x3f, 0x3f, 0x3f },
	{ 0x31, 0x31, 0x31 },
	{ 0x24, 0x24, 0x24 },
	{ 0x15, 0x15, 0x15 },
    };

    static byte pc_colour[] = {
	BLACK,
	RED,
	GREEN,
	YELLOW,
	BLUE,
	MAGENTA,
	CYAN,
	WHITE,
	DARKGRAY
    };

    static byte palette_bg = 0xff;
    static byte palette_fg = 0xff;

    byte fg = current_fg;
    byte bg = current_bg;

    /* V6 game, Amiga mode: Alter the palette registers if the colours
       of window 0 have changed. Palette register 15 is the foreground,
       register 0 is the background colour. */

    if (display == _AMIGA_ && h_version == V6 && cwin == 0) {

	if (fg < 16 && fg != palette_fg) {

	    byte R = amiga_palette[fg - 2][0];
	    byte G = amiga_palette[fg - 2][1];
	    byte B = amiga_palette[fg - 2][2];

	    asm mov ax,0x1010
	    asm mov bx,15
	    asm mov dh,R
	    asm mov ch,G
	    asm mov cl,B
	    asm int 0x10

	    palette_fg = fg;

	}

	if (bg < 16 && bg != palette_bg) {

	    byte R = amiga_palette[bg - 2][0];
	    byte G = amiga_palette[bg - 2][1];
	    byte B = amiga_palette[bg - 2][2];

	    asm mov ax,0x1010
	    asm mov bx,0
	    asm mov dh,R
	    asm mov ch,G
	    asm mov cl,B
	    asm int 0x10

	    palette_bg = bg;

	}

    }

    /* Handle colours. */

    if (fg < 16)

	if (display == _MONO_)
	    fg = (fg == WHITE_COLOUR) ? LIGHTGRAY : BLACK;
	else if (h_version == V6 && display == _AMIGA_)
	    fg = (palette_fg == fg) ? 15 : 0;
	else
	    fg = pc_colour[fg - 2];

    else fg -= 16;

    if (bg < 16)

	if (display == _MONO_)
	    bg = (bg == WHITE_COLOUR) ? LIGHTGRAY : BLACK;
	else if (h_version == V6 && display == _AMIGA_)
	    bg = (palette_bg == bg) ? 0 : 15;
	else
	    bg = pc_colour[bg - 2];

    else bg -= 16;

    /* Handle reverse text style */

    if (current_style & REVERSE_STYLE) {
	text_fg = (user_reverse_fg != -1) ? user_reverse_fg : bg;
	text_bg = (user_reverse_bg != -1) ? user_reverse_bg : fg;
    } else {
	text_fg = fg;
	text_bg = bg;
    }

    /* Handle emphasis style */

    if (current_style & EMPHASIS_STYLE) {

	if (display == _MONO_ && text_bg == BLACK)
	    text_fg = BLUE;	/* blue in monochrome mode is underlined */
	if (display == _TEXT_)
	    text_fg = (user_emphasis != -1) ? user_emphasis : YELLOW;

    }

    /* Handle boldface style */

    if (current_style & BOLDFACE_STYLE) {

	if (display == _MONO_)
	    text_fg = WHITE;
	if (display == _TEXT_)
	    text_fg ^= 8;

    }

    /* Set the screen attribute for scrolling and erasing */

    if (display <= _TEXT_)
	scrn_attr = (bg << 4) | fg;
    else if (display == _CGA_)
	scrn_attr = (bg != BLACK) ? 0xff : 0x00;
    else
	scrn_attr = bg;

}/* adjust_style */

/*
 * 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.
 *
 */

void os_set_colour (int new_foreground, int new_background)
{

    current_fg = new_foreground;
    current_bg = new_background;

    /* Apply changes */

    adjust_style ();

}/* 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)
{

    current_style = new_style;

    /* Apply changes */

    adjust_style ();

}/* 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)
{

    current_font = new_font;

}/* 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, European characters from
 * EURO_MIN to EURO_MAX (as defined in the Specification of the
 * Z-machine), character 9 (gap between two sentences) and character
 * 11 (paragraph indentation). The screen should not be scrolled after
 * printing to the bottom right corner.
 *
 */

void os_display_char (int c)
{
    int width;
    int i;

    /* CGA and MCGA modes cannot display any European characters, and some
       European characters (Oe and oe ligatures) can't be displayed at all.
       Another problem is that "Beyond Zork" uses graphic characters from
       the IBM font when the interpreter number is MS-DOS and the graphics
       flag is clear. */

    if (c >= EURO_MIN && c <= EURO_MAX && story_id != BEYOND_ZORK)

	if (display == _CGA_ || display == _MCGA_ || !euro_map[c - EURO_MIN]) {

	    int c1 = euro_substitute[2 * (c - EURO_MIN)];
	    int c2 = euro_substitute[2 * (c - EURO_MIN) + 1];

	    os_display_char (c1);

	    if (c2 != ' ')
		c = c2;
	    else
		return;

	} else c = euro_map[c - EURO_MIN];

    /* Handle special indentations */

    if (c == 9) {
	os_display_char (' ');
	os_display_char (' ');
	c = ' ';
    }
    if (c == 11) {
	os_display_char (' ');
	c = ' ';
    }

    /* Get width of character */

    width = os_char_width (c);

    /* Display character */

    if (display <= _TEXT_) {

	asm mov ah,2
	asm mov bh,0
	asm mov dh,byte ptr cursor_y
	asm mov dl,byte ptr cursor_x
	asm int 0x10
	asm mov ah,9
	asm mov bh,0
	asm mov bl,byte ptr text_bg
	asm mov cl,4
	asm shl bl,cl
	asm or bl,byte ptr text_fg
	asm mov cx,1
	asm mov al,byte ptr c
	asm int 0x10

    } else if (display == _CGA_) {

	unsigned val;

	int shift = cursor_x % 8;

	byte far *table = (byte far *) MK_FP (0xf000, 0xfa6e) + 8 * c;

	if (current_font == GRAPHICS_FONT)
	    table = graphics_font + 8 * (c - 32);

	for (i = 0; i < 8; i++) {

	    byte far *screen = get_scrnptr (cursor_y + i) + cursor_x / 8;

	    val = *table++;

	    if (user_bold_typing != -1 && (current_style & BOLDFACE_STYLE))
		val |= val >> 1;

	    if (i == 7 && (current_style & EMPHASIS_STYLE))
		val = 0xff;

	    if (text_bg == WHITE)
		val ^= 0xff;

	    asm les bx,screen
	    asm mov ax,es:[bx]
	    asm mov cl,byte ptr shift
	    asm mov dx,0xff00
	    asm ror dx,cl
	    asm and ax,dx
	    asm mov dx,val
	    asm ror dx,cl
	    asm or ax,dx
	    asm mov es:[bx],ax
	}

    } else if (display == _MCGA_) {

	unsigned val;

	int shift = (width + 1 - char_width[c - 32]) / 2;

	byte far *table = text_font + 8 * (c - 32);

	for (i = 0; i < 8; i++) {

	    byte far *screen = get_scrnptr (cursor_y + i) + cursor_x;

	    val = *table++ >> shift;

	    if (i == 7 && (current_style & EMPHASIS_STYLE))
		val = 0xff00 >> width;

	    asm les di,screen
	    asm mov dl,byte ptr val
	    asm mov dh,0x80
	    asm mov cx,width
	    asm cld
	loop:
	    asm mov al,text_bg
	    asm test dl,dh
	    asm jz draw_pixel
	    asm mov al,text_fg
	draw_pixel:
	    asm stosb
	    asm shr dh,1
	    asm loop loop
	}

    } else {

	unsigned val;

	int shift = cursor_x % 8;

	byte far *table = (byte far *) getvect (0x43) + h_font_height * c;

	outport (0x03ce, 0x0205);
	outport (0x03ce, 0xff08);

	if (current_font == GRAPHICS_FONT)

	    table = graphics_font + 8 * (c - 32);

	for (i = 0; i < h_font_height; i++) {

	    byte far *screen = get_scrnptr (cursor_y + i) + cursor_x / 8;

	    if (display != _AMIGA_ || current_font != GRAPHICS_FONT || (i & 1) == 0)
		val = *table++;

	    if (user_bold_typing != -1 && (current_style & BOLDFACE_STYLE))
		val |= val >> 1;

	    if (i == h_font_height - 1 && (current_style & EMPHASIS_STYLE))
		val = 0xff;

	    asm mov dx,0x03cf
	    asm les bx,screen
	    asm mov cl,byte ptr shift
	    asm mov ch,text_bg
	    asm mov ax,0x00ff
	    asm ror ax,cl
	    asm out dx,al
	    asm mov al,es:[bx]
	    asm mov es:[bx],ch
	    asm inc bx
	    asm mov al,ah
	    asm out dx,al
	    asm mov al,es:[bx]
	    asm mov es:[bx],ch
	    asm dec bx
	    asm mov ch,text_fg
	    asm mov ax,val
	    asm ror ax,cl
	    asm out dx,al
	    asm mov al,es:[bx]
	    asm mov es:[bx],ch
	    asm inc bx
	    asm mov al,ah
	    asm out dx,al
	    asm mov al,es:[bx]
	    asm mov es:[bx],ch
	}
    }

    /* Move cursor to next position */

    cursor_x += width;

}/* os_display_char */

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

void os_display_string (const char *s)
{

    int c;

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

	if (c == NEW_FONT || c == NEW_STYLE) {

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

	    if (c == NEW_FONT)
		os_set_font (arg);
	    if (c == 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 (int c)
{

    /* CGA and MCGA modes cannot display any European characters, and some
       European characters (Oe and oe ligatures) can't be displayed at all */

    if (c >= EURO_MIN && c <= EURO_MAX && story_id != BEYOND_ZORK)

	if (display == _CGA_ || display == _MCGA_ || !euro_map[c - EURO_MIN]) {

	    const char *ptr = euro_substitute + 2 * (c - EURO_MIN);

	    int c1 = (unsigned char) *ptr++;
	    int c2 = (unsigned char) *ptr;

	    return os_char_width (c1) + (c2 == ' ' ? 0 : os_char_width (c2));
	}

    /* Handle special indentations */

    if (c == 9)
	return 3 * os_char_width (' ');
    if (c == 11)
	return 2 * os_char_width (' ');

    /* Plain characters */

    if (display <= _TEXT_)
	return 1;
    if (display != _MCGA_)
	return 8;
    if (current_font == FIXED_WIDTH_FONT || (current_style & FIXED_WIDTH_STYLE))
	return 5;

    return char_width[c - 32];

}/* 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 char *s)
{
    int saved_font = current_font;
    int saved_style = current_style;

    int width = 0;
    int c;

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

	if (c == NEW_STYLE || c == NEW_FONT) {

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

	    if (c == NEW_FONT)
		current_font = arg;
	    if (c == NEW_STYLE)
		current_style = arg;

	} else width += os_char_width (c);

    current_font = saved_font;
    current_style = saved_style;

    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)
{

    cursor_y = y - 1;
    cursor_x = x - 1;

}/* 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_font = current_font;
    int saved_style = current_style;

    int saved_x = cursor_x;

    /* Choose plain text style */

    current_font = TEXT_FONT;
    current_style = 0;

    adjust_style ();

    /* Wait until the user presses a key */

    os_display_string ("[MORE]");
    os_read_key (0);

    /* Remove MORE prompt from the screen */

    os_erase_area (cursor_y + 1,
		   saved_x + 1,
		   cursor_y + h_font_height,
		   cursor_x + 1);

    /* Restore text font and style */

    current_font = saved_font;
    current_style = saved_style;

    adjust_style ();

    /* Restore cursor position */

    cursor_x = saved_x;

}/* os_more_prompt */
