Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve styles support #10

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open

Conversation

townba
Copy link

@townba townba commented Apr 19, 2020

Some notes:

  • In handling styles and style hints, I’ve tried to follow the standard, replicating the behavior of Gargoyle and Inform 7 as best I can when there’s any ambiguity.

  • I’ve tested it with Glulxe and Bocfel and a number of games and custom and existing test files, including some by erkyrath and curiousdannii.

  • This provides support for terminals with 8, 16, 256, or 16Mi colors. It attempts to reset the first 8, 16, or 256 colors (depending on the number of colors available) to known values.

  • Makefile uses pkg-config if available to find ncurses. This helps when building with Homebrew and its ncurses on macOS when PKG_CONFIG_PATH is set properly; otherwise, builds tend to use the macOS’s ncurses, which is version 5.4 and now 16 years out of date.

  • This adds several command-line options:

    • -color BOOL: enable color (default “yes”)
    • -fgcolor COLOR: use given color for foreground
    • -bgcolor COLOR: use given color for background
      • -fgcolor and -bgcolor can take CSS color names like red or navy, three-digit hexadecimal numbers like #639 (rebeccapurple), or six-digit hexadecimal numbers like #ADFF2F (greenyellow).
    • -stylehint BOOL: enable style hints (default “yes”)
    • -emphul BOOL: use underline for emphasis instead of italics (default “no”)
      • Only enabled on ncurses builds that support A_ITALIC.
  • This works with ncurses and PDCurses. It should work with other curses libraries as well.

  • This prefers handling resizing with the ncurses SIGWINCH handler and responding to KEY_RESIZE events to avoid flashing when resizing. It uses the previous behavior as a fallback when KEY_RESIZE isn’t available (non-ncurses) or if the ncurses handler was not used.

  • This includes (optional) support for four functions introduced by Gargoyle: garglk_set_zcolors. garglk_set_zcolors_stream, garglk_set_reversevideo, and garglk_set_reversevideo_stream. These are enabled using GLK_MODULE_GARGLKTEXT. Bocfel in particular uses these functions to provide full support for combinations of bold, italic, and reverse video, and to allow color. (As of this writing, this requires very light editing of Bocfel source to look for GLK_MODULE_GARGLKTEXT rather than GARGLK in a few places.)

* Set colors to known defaults for 8-, 16-, 256-, and (first 8 colors
  of) 16Mi-color terminals.
* Use ncurses alloc_pair when a working version is available.
* Fix compile-time warnings.
* Add helper macros.
* Make minor changes to names and comments.
Ncurses had a somewhat broken alloc_pair and free_pair until patch
20200411. This change tests alloc_pair when it's available; if it works,
we use it. Otherwise, we fall back on the list-of-pairs approach. This
way, when using a shared ncurses library, we get the better alloc_pair
approach when the library is updated.
PDCurses no longer provides the low-level terminfo function putp, which
is okay because a build of PDCurses only knows about its particular
platform, not multiple terminfo entries. In addition, I renamed the
Makefile variables that can be set when calling make. For example:

make CURSES_CFLAGS=-I/usr/local/include/xcurses \
    CURSES_LIBDIRS= \
    CURSES_LIBS=/usr/local/libXCurses.dylib

I tested this with PDCurses 3.9 for X11 and SDL2 on macOS 10.14.4. The
SDL2 implementation was unable to set foreground colors, but it had the
same problem with its own demos.
@townba
Copy link
Author

townba commented Apr 19, 2020

Bocfel changes to use this (note that this includes changes for both pull requests /pull/10 and /pull/11, but it shouldn't break anything if you're only trying one, or perhaps even neither):

diff --git a/screen.c b/screen.c
index df5fb0f..b6678fe 100644
--- a/screen.c
+++ b/screen.c
@@ -141,7 +141,7 @@ struct input
 
 #ifndef ZTERP_GLK
 static int16_t fg_color = 1, bg_color = 1;
-#elif defined(GARGLK)
+#elif defined(GLK_MODULE_GARGLKTEXT)
 static glui32 zcolor_map[] = {
   zcolor_Default,
 
@@ -167,7 +167,7 @@ void update_color(int which, unsigned long color)
 }
 #endif
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
 /* Idea from Nitfol. */
 static const int style_map[] =
 {
@@ -205,7 +205,7 @@ void set_current_style(void)
 #ifdef ZTERP_GLK
   if(curwin->id == NULL) return;
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
   if(use_fixed_font()) style |= STYLE_FIXED;
 
   if(options.disable_fixed) style &= ~STYLE_FIXED;
@@ -1133,7 +1133,7 @@ void zget_cursor(void)
 void zset_colour(void)
 {
   /* Glk (apart from Gargoyle) has no color support. */
-#if !defined(ZTERP_GLK) || defined(GARGLK)
+#if !defined(ZTERP_GLK) || defined(GLK_MODULE_GARGLKTEXT)
   int16_t fg = as_signed(zargs[0]), bg = as_signed(zargs[1]);
 
   /* In V6, each window has its own color settings.  Since multiple
@@ -1145,7 +1145,7 @@ void zset_colour(void)
   if(options.disable_color) return;
 
   /* XXX -1 is a valid color in V6. */
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
   if(fg >= 1 && fg <= (zversion >= 5 ? 12 : 9)) fg_color = zcolor_map[fg - 1];
   if(bg >= 1 && bg <= (zversion >= 5 ? 12 : 9)) bg_color = zcolor_map[bg - 1];
 #else
@@ -1157,7 +1157,7 @@ void zset_colour(void)
 #endif
 }
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
 /* Convert a 15-bit color to a 24-bit color. */
 static glui32 convert_color(unsigned long color)
 {
@@ -1177,7 +1177,7 @@ static glui32 convert_color(unsigned long color)
 
 void zset_true_colour(void)
 {
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
   long fg = as_signed(zargs[0]), bg = as_signed(zargs[1]);
 
   if     (fg >=  0) fg_color = convert_color(fg);
@@ -1924,7 +1924,7 @@ void zshow_status(void)
 
   glk_window_get_size(statuswin.id, &width, &height);
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
   garglk_set_reversevideo(1);
 #else
   glk_set_style(style_Alert);
@@ -2302,7 +2302,7 @@ void zbuffer_screen(void)
   store(0);
 }
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
 /* Glk does not guarantee great control over how various styles are
  * going to look, but Gargoyle does.  Abusing the Glk “style hints”
  * functions allows for quite fine-grained control over style
@@ -2338,7 +2338,7 @@ bool create_mainwin(void)
   have_unicode = glk_gestalt(gestalt_Unicode, 0);
 #endif
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
   set_default_styles();
 
   /* Bold */
@@ -2459,7 +2459,7 @@ void init_screen(void)
 
   stop_timer();
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
   fg_color = zcolor_Default;
   bg_color = zcolor_Default;
 #endif
diff --git a/screen.h b/screen.h
index 40f12c1..581c3ce 100644
--- a/screen.h
+++ b/screen.h
@@ -41,7 +41,7 @@ void term_keys_reset(void);
 void term_keys_add(uint8_t);
 #endif
 
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
 void update_color(int, unsigned long);
 #endif
 
diff --git a/sound.c b/sound.c
index 08591a9..b225c6f 100644
--- a/sound.c
+++ b/sound.c
@@ -8,7 +8,7 @@
 
 #ifdef ZTERP_GLK
 #include <glk.h>
-#ifdef GARGLK
+#ifdef GLK_MODULE_SOUND
 #include <glkstart.h>
 #include <gi_blorb.h>
 static schanid_t sound_channel = NULL;
@@ -23,7 +23,7 @@ static schanid_t sound_channel = NULL;
  */
 void init_sound(bool story_is_blorb)
 {
-#ifdef GARGLK
+#ifdef GLK_MODULE_SOUND
   strid_t file = NULL;
 
   if(sound_loaded()) return;
@@ -58,14 +58,14 @@ void init_sound(bool story_is_blorb)
   if(file != NULL)
   {
     giblorb_set_resource_map(file);
-    sound_channel = glk_schannel_create(0);
   }
+  sound_channel = glk_schannel_create(0);
 #endif
 }
 
 bool sound_loaded(void)
 {
-#ifdef GARGLK
+#ifdef GLK_MODULE_SOUND
   return sound_channel != NULL;
 #else
   return false;
@@ -74,7 +74,7 @@ bool sound_loaded(void)
 
 void zsound_effect(void)
 {
-#ifdef GARGLK
+#ifdef GLK_MODULE_SOUND
   uint8_t repeats, volume;
   static uint32_t vols[8] = {
     0x02000, 0x04000, 0x06000, 0x08000,
diff --git a/util.c b/util.c
index 2fcee09..9eaa201 100644
--- a/util.c
+++ b/util.c
@@ -30,6 +30,7 @@
 
 #ifdef ZTERP_GLK
 #include <glk.h>
+#include <glkstart.h>
 #endif
 
 #ifndef ZTERP_NO_SAFETY_CHECKS
@@ -87,7 +88,11 @@ void help(void)
   const struct
   {
     const char *flag;
+#ifdef ZTERP_GLK
+    int arg;
+#else
     enum { glkunix_arg_NoValue, glkunix_arg_NumberValue, glkunix_arg_ValueFollows } arg;
+#endif
     const char *description;
   }
   flags[] = {
@@ -297,4 +302,7 @@ void process_arguments(int argc, char **argv)
 
   /* Just ignore excess stories for now. */
   if(zoptind < argc) game_file = argv[zoptind];
+#ifdef ZTERP_GLK
+  glkunix_set_base_file((char *)game_file);
+#endif
 }
diff --git a/zterp.c b/zterp.c
index d49ee50..12d8d36 100644
--- a/zterp.c
+++ b/zterp.c
@@ -293,7 +293,7 @@ static void read_config(void)
 #define NUMBER(name)	else if(strcmp(key, #name) == 0) options.name = n
 #define STRING(name)	else if(strcmp(key, #name) == 0) do { free(options.name); options.name = xstrdup(val); } while(0)
 #define CHAR(name)	else if(strcmp(key, #name) == 0) options.name = val[0]
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
 #define COLOR(name, num)else if(strcmp(key, "color_" #name) == 0) update_color(num, strtol(val, NULL, 16))
 #else
 #define COLOR(name, num)else if(0)
@@ -399,7 +399,7 @@ void write_header(void)
 
 #ifdef ZTERP_GLK
     if(glk_gestalt(gestalt_Timer, 0)) flags1 |= FLAGS1_TIMED;
-#ifdef GARGLK
+#ifdef GLK_MODULE_GARGLKTEXT
     if(zversion >= 5) flags1 |= FLAGS1_COLORS;
 #endif
 #else
@@ -899,6 +899,7 @@ int main(int argc, char **argv)
     if(ref != NULL)
     {
       game_file = xstrdup(garglk_fileref_get_name(ref));
+      glkunix_set_base_file(game_file);
       glk_fileref_destroy(ref);
     }
   }

@townba townba mentioned this pull request Apr 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant