Updated interpreters
[projects/chimara/chimara.git] / interpreters / frotz / glkscreen.c
index 37ef562e5865135c7076268c916687b27f894eca..f7c8e08b30e5b7386a542001a532187c4132c775 100644 (file)
@@ -1,6 +1,7 @@
 /******************************************************************************
  *                                                                            *
  * Copyright (C) 2006-2009 by Tor Andersson.                                  *
+ * Copyright (C) 2010 by Ben Cressey, Chris Spiegel.                          *
  *                                                                            *
  * This file is part of Gargoyle.                                             *
  *                                                                            *
 
 #include "glkfrotz.h"
 
-static unsigned char statusline[256];
+static zchar statusline[256];
 static int oldstyle = 0;
 static int curstyle = 0;
-static int upperstyle = 0;
-static int lowerstyle = 0;
 static int cury = 1;
 static int curx = 1;
+static int fixforced = 0;
 
-int curr_fg = 0;
-int curr_bg = 0;
+static int curr_fg = -2;
+static int curr_bg = -2;
+static int curr_font = 1;
+static int prev_font = 1;
+static int temp_font = 0;
 
 /* To make the common code happy */
 
@@ -57,6 +60,13 @@ int os_string_width (const zchar *s)
        return width;
 }
 
+int os_string_length (zchar *s)
+{
+       int length = 0;
+       while (*s++) length++;
+       return length;
+}
+
 void os_prepare_sample (int a)
 {
        glk_sound_load_hint(a, 1);
@@ -155,19 +165,26 @@ void reset_status_ht(void)
        {
                glk_window_get_size(gos_upper, NULL, &height);
                if (mach_status_ht != height)
+               {
                        glk_window_set_arrangement(
                                glk_window_get_parent(gos_upper),
                                winmethod_Above | winmethod_Fixed,
                                mach_status_ht, NULL);
+               }
        }
 }
 
-void erase_window (int w)
+void erase_window (zword w)
 {
        if (w == 0)
                glk_window_clear(gos_lower);
        else if (gos_upper)
        {
+#ifdef GARGLK
+                       garglk_set_reversevideo_stream(
+                               glk_window_get_stream(gos_upper),
+                               TRUE);
+#endif /* GARGLK */
                memset(statusline, ' ', sizeof statusline);
                glk_window_clear(gos_upper);
                reset_status_ht();
@@ -175,7 +192,7 @@ void erase_window (int w)
        }
 }
 
-void split_window (int lines)
+void split_window (zword lines)
 {
        if (!gos_upper)
                return;
@@ -219,11 +236,13 @@ void restart_screen (void)
  * so ... split status text into regions, reformat and print anew.
  */
 
-void packspaces(unsigned char *src, unsigned char *dst)
+void packspaces(zchar *src, zchar *dst)
 {
        int killing = 0;
        while (*src)
        {
+               if (*src == 0x20202020)
+                       *src = ' ';
                if (*src == ' ')
                        killing++;
                else
@@ -238,17 +257,17 @@ void packspaces(unsigned char *src, unsigned char *dst)
 
 void smartstatusline (void)
 {
-       unsigned char packed[256];
-       unsigned char buf[256];
-       unsigned char *a, *b, *c, *d;
+       zchar packed[256];
+       zchar buf[256];
+       zchar *a, *b, *c, *d;
        int roomlen, scorelen, scoreofs;
-       int len;
+       int len, tmp;
 
        statusline[curx - 1] = 0; /* terminate! */
 
        packspaces(statusline, packed);
        //strcpy(packed, statusline);
-       len = strlen(packed);
+       len = os_string_length(packed);
 
        a = packed;
        while (a[0] == ' ')
@@ -279,15 +298,16 @@ void smartstatusline (void)
        if (scoreofs <= roomlen)
                scoreofs = roomlen + 2;
 
-       memset(buf, ' ', h_screen_cols);
-       memcpy(buf + 1 + scoreofs, c, scorelen);
-       memcpy(buf + 1, a, roomlen);
+       for (tmp = 0; tmp < h_screen_cols; tmp++)
+               buf[tmp] = ' ';
+
+       memcpy(buf + 1 + scoreofs, c, scorelen * sizeof(zchar));
+       memcpy(buf + 1, a, roomlen * sizeof(zchar));
        //if (roomlen >= scoreofs)
        //      buf[roomlen + 1] = '|';
 
        glk_window_move_cursor(gos_upper, 0, 0);
-       glk_set_style(style_User1);
-       glk_put_buffer(buf, h_screen_cols);
+       glk_put_buffer_uni(buf, h_screen_cols);
        glk_window_move_cursor(gos_upper, cury - 1, curx - 1);
 }
 
@@ -306,16 +326,19 @@ void screen_char (zchar c)
        }
 
        /* check fixed flag in header, game can change it at whim */
-       if (gos_curwin == gos_lower)
+       int forcefix = ((h_flags & FIXED_FONT_FLAG) != 0);
+       int curfix = ((curstyle & FIXED_WIDTH_STYLE) != 0);
+       if (forcefix && !curfix)
        {
-               static int forcefix = -1;
-               int curfix = h_flags & FIXED_FONT_FLAG;
-               if (forcefix != curfix)
-               {
-                       forcefix = curfix;
-                       zargs[0] = 0xf000;      /* tickle tickle! */
-                       z_set_text_style();
-               }
+               zargs[0] = 0xf000;      /* tickle tickle! */
+               z_set_text_style();
+               fixforced = TRUE;
+       }
+       else if (!forcefix && fixforced)
+       {
+               zargs[0] = 0xf000;      /* tickle tickle! */
+               z_set_text_style();
+               fixforced = FALSE;
        }
 
        if (gos_upper && gos_curwin == gos_upper)
@@ -332,13 +355,13 @@ void screen_char (zchar c)
                                        statusline[curx - 1] = c;
                                curx++;
                                if (curx <= h_screen_cols)
-                                       glk_put_char(c);
+                                       glk_put_char_uni(c);
                                else
                                        smartstatusline();
                        }
                        else
                        {
-                               glk_put_char(c);
+                               glk_put_char_uni(c);
                                curx++;
                                if (curx > h_screen_cols) {
                                        curx = 1;
@@ -351,7 +374,7 @@ void screen_char (zchar c)
        {
                if (c == ZC_RETURN)
                        glk_put_char('\n');
-               else glk_put_char(c);
+               else glk_put_char_uni(c);
        }
 }
 
@@ -405,6 +428,18 @@ void z_buffer_mode (void)
 {
 }
 
+/*
+ * z_buffer_screen, set the screen buffering mode.
+ *
+ *     zargs[0] = mode
+ *
+ */
+
+void z_buffer_screen (void)
+{
+       store (0);
+}
+
 /*
  * z_erase_line, erase the line starting at the cursor position.
  *
@@ -527,6 +562,59 @@ void z_print_table (void)
        }
 }
 
+#define zB(i) ((((i >> 10) & 0x1F) << 3) | (((i >> 10) & 0x1F) >> 2))
+#define zG(i) ((((i >>  5) & 0x1F) << 3) | (((i >>  5) & 0x1F) >> 2))
+#define zR(i) ((((i      ) & 0x1F) << 3) | (((i      ) & 0x1F) >> 2))
+
+#define zRGB(i) (zR(i) << 16 | zG(i) << 8 | zB(i))
+
+/*
+ * z_set_true_colour, set the foreground and background colours
+ * to specific RGB colour values.
+ *
+ *     zargs[0] = foreground colour
+ *     zargs[1] = background colour
+ *     zargs[2] = window (-3 is the current one, optional)
+ *
+ */
+
+void z_set_true_colour (void)
+{
+       int zfore = zargs[0];
+       int zback = zargs[1];
+
+       if (!(zfore < 0))
+               zfore = zRGB(zargs[0]);
+
+       if (!(zback < 0))
+               zback = zRGB(zargs[1]);
+
+#ifdef GARGLK
+       garglk_set_zcolors(zfore, zback);
+#endif /* GARGLK */
+
+       curr_fg = zfore;
+       curr_bg = zback;
+}
+
+static int zcolor_map[] = {
+       -2,                                             /*  0 = current */
+       -1,                                             /*  1 = default */
+       0x0000,                                 /*  2 = black */
+       0x001D,                                 /*  3 = red */
+       0x0340,                                 /*  4 = green */
+       0x03BD,                                 /*  5 = yellow */
+       0x59A0,                                 /*  6 = blue */
+       0x7C1F,                                 /*  7 = magenta */
+       0x77A0,                                 /*  8 = cyan */
+       0x7FFF,                                 /*  9 = white */
+       0x5AD6,                                 /* 10 = light grey */
+       0x4631,                                 /* 11 = medium grey */
+       0x2D6B,                                 /* 12 = dark grey */
+};
+
+#define zcolor_NUMCOLORS    (13)
+
 /*
  * z_set_colour, set the foreground and background colours.
  *
@@ -541,12 +629,41 @@ void z_set_colour (void)
        int zfore = zargs[0];
        int zback = zargs[1];
 
+       switch (zfore)
+       {
+       case -1:
+               zfore = -3;
+
+       case 0:
+       case 1:
+               zfore = zcolor_map[zfore];
+               break;
+
+       default:
+               if (zfore < zcolor_NUMCOLORS)
+                       zfore = zRGB(zcolor_map[zfore]);
+               break;
+       }
+
+       switch (zback)
+       {
+       case -1:
+               zback = -3;
+
+       case 0:
+       case 1:
+               zback = zcolor_map[zback];
+               break;
+
+       default:
+               if (zback < zcolor_NUMCOLORS)
+                       zback = zRGB(zcolor_map[zback]);
+               break;
+       }
 
-       if (!(zfore == 0 && zback == 0)) {
 #ifdef GARGLK
-               garglk_set_zcolors(zfore, zback);
+       garglk_set_zcolors(zfore, zback);
 #endif /* GARGLK */
-       }
 
        curr_fg = zfore;
        curr_bg = zback;
@@ -561,6 +678,41 @@ void z_set_colour (void)
 
 void z_set_font (void)
 {
+       zword font = zargs[0];
+
+       switch (font)
+       {
+               case 0: /* previous font */
+                       temp_font = curr_font;
+                       curr_font = prev_font;
+                       prev_font = temp_font;
+                       zargs[0] = 0xf000;      /* tickle tickle! */
+                       z_set_text_style();
+                       store (curr_font);
+                       break;
+
+               case 1: /* normal font */
+                       prev_font = curr_font;
+                       curr_font = 1;
+                       zargs[0] = 0xf000;      /* tickle tickle! */
+                       z_set_text_style();
+                       store (prev_font);
+                       break; 
+
+               case 4: /* fixed-pitch font*/
+                       prev_font = curr_font;
+                       curr_font = 4;
+                       zargs[0] = 0xf000;      /* tickle tickle! */
+                       z_set_text_style();
+                       store (prev_font);
+                       break;
+
+               case 2: /* picture font, undefined per 1.1 */
+               case 3: /* character graphics font */
+               default: /* unavailable */
+                       store (0);
+                       break;
+       }
 }
 
 /*
@@ -603,7 +755,7 @@ void z_set_text_style (void)
        else if (zargs[0] != 0xf000) /* not tickle time */
                curstyle |= zargs[0];
 
-       if (h_flags & FIXED_FONT_FLAG)
+       if (h_flags & FIXED_FONT_FLAG || curr_font == 4)
                style = curstyle | FIXED_WIDTH_STYLE;
        else
                style = curstyle;
@@ -613,29 +765,41 @@ void z_set_text_style (void)
 
        if (style & REVERSE_STYLE)
        {
-               if (gos_curwin == gos_upper && gos_upper) {
-                       glk_set_style(style_User1);
-               }
 #ifdef GARGLK
                garglk_set_reversevideo(TRUE);
 #endif /* GARGLK */
        }
-       else if (style & FIXED_WIDTH_STYLE)
-               glk_set_style(style_Preformatted);
-       else if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
-               glk_set_style(style_Alert);
-       else if (style & BOLDFACE_STYLE)
-               glk_set_style(style_Subheader);
-       else if (style & EMPHASIS_STYLE)
-               glk_set_style(style_Emphasized);
+
+       if (style & FIXED_WIDTH_STYLE)
+       {
+               if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
+                       glk_set_style(style_BlockQuote);        /* monoz */
+               else if (style & EMPHASIS_STYLE)
+                       glk_set_style(style_Alert);                     /* monoi */
+               else if (style & BOLDFACE_STYLE)
+                       glk_set_style(style_Subheader);         /* monob */
+               else
+                       glk_set_style(style_Preformatted);      /* monor */
+       }
        else
-               glk_set_style(style_Normal);
+       {
+               if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
+                       glk_set_style(style_Note);                      /* propz */
+               else if (style & EMPHASIS_STYLE)
+                       glk_set_style(style_Emphasized);        /* propi */
+               else if (style & BOLDFACE_STYLE)
+                       glk_set_style(style_Header);            /* propb */
+               else
+                       glk_set_style(style_Normal);            /* propr */
+       }
 
-       if (curstyle == 0) {
+       if (curstyle == 0)
+       {
 #ifdef GARGLK
                garglk_set_reversevideo(FALSE);
 #endif /* GARGLK */
        }
+
 }
 
 /*
@@ -649,29 +813,25 @@ void z_set_window (void)
 {
        int win = zargs[0];
 
-       if (gos_curwin == gos_lower)
-               lowerstyle = curstyle;
-       else
-               upperstyle = curstyle;
-
        if (win == 0)
        {
                glk_set_window(gos_lower);
                gos_curwin = gos_lower;
-               curstyle = lowerstyle;
        }
        else
        {
                if (gos_upper)
                        glk_set_window(gos_upper);
                gos_curwin = gos_upper;
-               curstyle = upperstyle;
        }
 
-        if (win == 0)
-            enable_scripting = TRUE;
-        else
-            enable_scripting = FALSE;
+       if (win == 0)
+               enable_scripting = TRUE;
+       else
+               enable_scripting = FALSE;
+
+       zargs[0] = 0xf000;      /* tickle tickle! */
+       z_set_text_style();
 }
 
 /*
@@ -724,7 +884,6 @@ void z_show_status (void)
 
        curx = cury = 1;
        glk_window_move_cursor(gos_upper, 0, 0);
-       glk_set_style(style_User1);
 
        /* If the screen width is below 55 characters then we have to use
           the brief status line format */