X-Git-Url: https://git.stderr.nl/gitweb?p=projects%2Fchimara%2Fchimara.git;a=blobdiff_plain;f=interpreters%2Fbocfel%2Fosdep.c;fp=interpreters%2Fbocfel%2Fosdep.c;h=454c1b26df5085b3f1cd59931b9842c8ff8d9d88;hp=0000000000000000000000000000000000000000;hb=aa30979369091c96bca34499c28cb01bc16efb1d;hpb=61180dab8f5c29f5a29b83fcb7d62942f7a741d1 diff --git a/interpreters/bocfel/osdep.c b/interpreters/bocfel/osdep.c new file mode 100644 index 0000000..454c1b2 --- /dev/null +++ b/interpreters/bocfel/osdep.c @@ -0,0 +1,312 @@ +/*- + * Copyright 2010-2012 Chris Spiegel. + * + * This file is part of Bocfel. + * + * Bocfel is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version + * 2 or 3, as published by the Free Software Foundation. + * + * Bocfel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Bocfel. If not, see . + */ + +#ifdef ZTERP_UNIX +#define _XOPEN_SOURCE 600 +#endif + +#include +#include +#include + +#include "osdep.h" +#include "screen.h" + +/* OS-specific functions should all be collected in this file for + * convenience. A sort of poor-man’s “reverse” inheritance is used: for + * each function that a particular operating system provides, it should + * #define a macro of the same name. At the end of the file, a generic + * function is provided for each function that has no associated macro + * definition. + * + * The functions required are as follows: + * + * long zterp_os_filesize(FILE *fp) + * + * Return the size of the file referred to by fp. It is safe to assume + * that the file is opened in binary mode. The file position indicator + * need not be maintained. If the size of the file is larger than + * LONG_MAX, -1 should be returned. + * + * int zterp_os_have_unicode(void) + * + * The main purpose behind this function is to indicate whether + * transcripts will be written in UTF-8 or Latin-1. This is, of course, + * not necessarily an OS matter, but I’ve run into some issues with + * UTF-8 and Windows (at least through Wine), so I want to be as + * sensible as I can with the defaults. The user is able to override + * this value if he so desires. + * If a Glk build is not being used, this function also serves to + * indicate whether all I/O, not just transcripts, should be UTF-8 or + * not. Glk libraries are able to be queried as to their support for + * Unicode so there is no need to make assumptions in that case. + * + * void zterp_os_rcfile(char *s, size_t n) + * + * Different operating systems have different ideas about where + * configuration data should be stored; this function will copy a + * suitable value for the bocfel configuration file into the buffer s + * which is n bytes long. + * + * void zterp_os_reopen_binary(FILE *fp) + * + * Writing UTF-8 requires that no mangling be done, such as might happen + * when a stream is opened in text mode. This function should, if + * necessary, set the mode on the file pointer in fp to be binary. + * + * The following functions are useful for non-Glk builds only. They + * provide for some handling of screen functions that is normally taken + * care of by Glk. + * + * void zterp_os_get_screen_size(unsigned *w, unsigned *h) + * + * The size of the terminal, if known, is written into *w (width) and *h + * (height). If terminal size is unavalable, nothing should be written. + * + * void zterp_os_init_term(void) + * + * If something special needs to be done to prepare the terminal for + * output, it should be done here. This function is called once at + * program startup. + * + * int zterp_os_have_style(int style) + * + * This should return true if the provided style (see style.h for valid + * STYLE_ values) is available. It is safe to assume that styles will + * not be combined; e.g. this will not be called as: + * zterp_os_have_style(STYLE_BOLD | STYLE_ITALIC); + * + * int zterp_os_have_colors(void) + * + * Returns true if the terminal supports colors. + * + * void zterp_os_set_style(int style, int fg, int bg) + * + * Set both a style and foreground/background color. Any previous + * settings should be ignored; for example, if the last call to + * zterp_os_set_style() turned on italics and the current call sets + * bold, the result should be bold, not bold italic. + * Unlike in zterp_os_have_style(), here styles may be combined. See + * the Unix implementation for a reference. + * The colors are Z-machine colors (see §8.3.1), with the following + * note: the only color values that will ever be passed in are 1–9. + */ + +/****************** + * Unix functions * + ******************/ +#ifdef ZTERP_UNIX +#include + +long zterp_os_filesize(FILE *fp) +{ + struct stat buf; + int fd = fileno(fp); + + if(fd == -1 || fstat(fd, &buf) == -1 || !S_ISREG(buf.st_mode) || buf.st_size > LONG_MAX) return -1; + + return buf.st_size; +} +#define zterp_os_filesize + +int zterp_os_have_unicode(void) +{ + return 1; +} +#define zterp_os_have_unicode + +void zterp_os_rcfile(char *s, size_t n) +{ + snprintf(s, n, "%s/.bocfelrc", getenv("HOME") != NULL ? getenv("HOME") : "."); +} +#define zterp_os_rcfile + +#ifndef ZTERP_GLK +#include +#include +#include +#include +#ifdef TIOCGWINSZ +void zterp_os_get_screen_size(unsigned *w, unsigned *h) +{ + struct winsize winsize; + + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) == 0) + { + *w = winsize.ws_col; + *h = winsize.ws_row; + } +} +#define zterp_os_get_screen_size +#endif + +static const char *ital = NULL, *rev = NULL, *bold = NULL, *none = NULL; +static char *fg_string = NULL, *bg_string = NULL; +static int have_colors = 0; +void zterp_os_init_term(void) +{ + if(setupterm(NULL, STDIN_FILENO, NULL) != OK) return; + + /* prefer italics over underline for emphasized text */ + ital = tgetstr("ZH", NULL); + if(ital == NULL) ital = tgetstr("us", NULL); + rev = tgetstr("mr", NULL); + bold = tgetstr("md", NULL); + none = tgetstr("me", NULL); + + fg_string = tgetstr("AF", NULL); + bg_string = tgetstr("AB", NULL); + + have_colors = none != NULL && fg_string != NULL && bg_string != NULL; +} +#define zterp_os_init_term + +int zterp_os_have_style(int style) +{ + if(none == NULL) return 0; + + if (style == STYLE_ITALIC) return ital != NULL; + else if(style == STYLE_REVERSE) return rev != NULL; + else if(style == STYLE_BOLD) return bold != NULL; + else if(style == STYLE_NONE) return none != NULL; + + return 0; +} +#define zterp_os_have_style + +int zterp_os_have_colors(void) +{ + return have_colors; +} +#define zterp_os_have_colors + +void zterp_os_set_style(int style, int fg, int bg) +{ + /* If the terminal cannot be reset, nothing can be used. */ + if(none == NULL) return; + + putp(none); + + if((style & STYLE_ITALIC) && ital != NULL) putp(ital); + if((style & STYLE_REVERSE) && rev != NULL) putp(rev); + if((style & STYLE_BOLD) && bold != NULL) putp(bold); + + if(have_colors) + { + if(fg > 1) putp(tparm(fg_string, fg - 2, 0, 0, 0, 0, 0, 0, 0, 0)); + if(bg > 1) putp(tparm(bg_string, bg - 2, 0, 0, 0, 0, 0, 0, 0, 0)); + } +} +#define zterp_os_set_style +#endif + +/********************* + * Windows functions * + *********************/ +#elif defined(ZTERP_WIN32) +void zterp_os_rcfile(char *s, size_t n) +{ + char *p; + + p = getenv("APPDATA"); + if(p == NULL) p = getenv("LOCALAPPDATA"); + if(p == NULL) p = "."; + + snprintf(s, n, "%s\\bocfel.ini", p); +} +#define zterp_os_rcfile + +#endif + +/********************* + * Generic functions * + *********************/ +#ifndef zterp_os_filesize +long zterp_os_filesize(FILE *fp) +{ + /* Assume fseek() can seek to the end of binary streams. */ + if(fseek(fp, 0, SEEK_END) == -1) return -1; + + return ftell(fp); +} +#endif + +#ifndef zterp_os_have_unicode +int zterp_os_have_unicode(void) +{ + return 0; +} +#endif + +#ifndef zterp_os_rcfile +void zterp_os_rcfile(char *s, size_t n) +{ + snprintf(s, n, "bocfelrc"); +} +#endif + +/* When UTF-8 output is enabled, special translation of characters (e.g. + * newline) should not be done. Theoretically this function exists to + * set stdin/stdout to binary mode, if necessary. Unix makes no + * text/binary distinction, but Windows does. I’m under the impression + * that there is a setmode() function that should be able to do this, + * but my knowledge of Windows is so small that I do not want to do much + * more than I have, lest I completely break Windows support—assuming it + * even works. + * freopen() should be able to do this, but with my testing under Wine, + * no text gets output in such a case. + */ +#ifndef zterp_os_reopen_binary +void zterp_os_reopen_binary(FILE *fp) +{ +} +#endif + +#ifndef ZTERP_GLK +#ifndef zterp_os_get_screen_size +void zterp_os_get_screen_size(unsigned *w, unsigned *h) +{ +} +#endif + +#ifndef zterp_os_init_term +void zterp_os_init_term(void) +{ +} +#endif + +#ifndef zterp_os_have_style +int zterp_os_have_style(int style) +{ + return 0; +} +#endif + +#ifndef zterp_os_have_colors +int zterp_os_have_colors(void) +{ + return 0; +} +#endif + +#ifndef zterp_os_set_style +void zterp_os_set_style(int style, int fg, int bg) +{ +} +#endif +#endif