mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
3224 lines
146 KiB
C++
3224 lines
146 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/* TADS OS interface file type definitions
|
|
*
|
|
* Defines certain datatypes used in the TADS operating system interface
|
|
*/
|
|
|
|
#ifndef GLK_TADS_OS_GLK
|
|
#define GLK_TADS_OS_GLK
|
|
|
|
#include "common/scummsys.h"
|
|
#include "glk/tads/os_frob_tads.h"
|
|
|
|
namespace Glk {
|
|
namespace TADS {
|
|
|
|
#define TADS_RUNTIME_VERSION "2.5.17"
|
|
#define OS_SYSTEM_NAME "ScummVM Glk"
|
|
|
|
#define OSPATHCHAR '/'
|
|
#define OSPATHALT ""
|
|
#define OSPATHURL "/"
|
|
#define OSPATHSEP ':'
|
|
#define OS_NEWLINE_SEQ "\n"
|
|
#define DBG_OFF
|
|
|
|
/* maximum width (in characters) of a line of text */
|
|
#define OS_MAXWIDTH 255
|
|
|
|
/* round a size to worst-case alignment boundary */
|
|
#define osrndsz(s) (((s)+3) & ~3)
|
|
|
|
/* round a pointer to worst-case alignment boundary */
|
|
#define osrndpt(p) ((uchar *)((((unsigned long)(p)) + 3) & ~3))
|
|
|
|
/* read unaligned portable unsigned 2-byte value, returning int */
|
|
#define osrp2(p) READ_LE_UINT16(p)
|
|
|
|
/* read unaligned portable signed 2-byte value, returning int */
|
|
#define osrp2s(p) READ_LE_INT16(p)
|
|
|
|
/* write int to unaligned portable 2-byte value */
|
|
#define oswp2(p, i) WRITE_LE_UINT16(p, i)
|
|
#define oswp2s(p, i) WRITE_LE_INT16(p, i)
|
|
|
|
/* read unaligned portable 4-byte value, returning unsigned long */
|
|
#define osrp4(p) READ_LE_UINT32(p)
|
|
#define osrp4s(p) READ_LE_INT32(p)
|
|
|
|
#define oswp4(p, l) WRITE_LE_UINT32(p, l)
|
|
#define oswp4s(p, l) WRITE_LE_INT32(p, l)
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
typedef int32 int32_t;
|
|
typedef uint32 uint32_t;
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* <time.h> definitions.
|
|
*
|
|
* os_time() should act like Unix time(), returning the number of seconds
|
|
* elapsed since January 1, 1970 at midnight UTC.
|
|
*
|
|
* The original Unix <time.h> package defined time_t as a 32-bit signed
|
|
* int, and many subsequent C compilers on other platforms followed suit.
|
|
* A signed 32-bit time_t has the well-known year-2038 problem; some later
|
|
* C compilers tried to improve matters by using an unsigned 32-bit time_t
|
|
* instead, but for many purposes this is even worse since it can't
|
|
* represent any date before 1/1/1970. *Most* modern compilers solve the
|
|
* problem once and for all (for 300 billion years in either direction of
|
|
* 1/1/1970, anyway - enough to represent literally all of eternity in most
|
|
* current cosmological models) by defining time_t as a signed 64-bit int.
|
|
* But some compilers stubbornly stick to the old 32-bit time_t even in
|
|
* newer versions, for the sake of compatibility with older code that might
|
|
* be lax about mixing time_t's with ordinary int's. E.g., MSVC2003 does
|
|
* this. Fortunately, some of these compilers (such as MSVC2003 again)
|
|
* also define a parallel, transitional set of 64-bit time functions that
|
|
* you can use by replacing all references to the standard time_t and
|
|
* related names with the corresponding 64-bit names.
|
|
*
|
|
* We'd really like to use a 64-bit time_t wherever we can - the TADS
|
|
* release cycle can be a bit slow, and we don't want 2038 to sneak up on
|
|
* us and catch us unawares. So for those compilers that offer a choice of
|
|
* 32 or 64 bits, we'd like to select the 64 bit version. To facilitate
|
|
* this, we define covers here for the time.h types and functions that we
|
|
* use. On platforms where the regular time_t is already 64 bits, or where
|
|
* there's no 64-bit option at all, you can simply do nothing - the
|
|
* defaults defined here use the standard time_t typedef and functions, so
|
|
* that's what you'll get if you don't define these in the OS-specific
|
|
* headers for your platform. For compilers that provide both a 32-bit
|
|
* time_t and a 64-bit other_time_t, the OS headers should #define these
|
|
* macros in terms of those compiler-specific 64-bit names.
|
|
*/
|
|
#ifndef os_time_t
|
|
# define os_time_t int64
|
|
# define os_gmtime(t) gmtime(t)
|
|
# define os_localtime(t) localtime(t)
|
|
# define os_time(t) time(t)
|
|
#endif
|
|
|
|
/*
|
|
* Initialize the time zone. This routine is meant to take care of any
|
|
* work that needs to be done prior to calling localtime() and other
|
|
* time-zone-dependent routines in the run-time library. For DOS and
|
|
* Windows, we need to call the run-time library routine tzset() to set up
|
|
* the time zone from the environment; most systems shouldn't need to do
|
|
* anything in this routine. It's sufficient to call this once during the
|
|
* process lifetime, since it's meant to perform static initialization that
|
|
* lasts as long as the process is running.
|
|
*/
|
|
#ifndef os_tzset
|
|
void os_tzset(void);
|
|
#endif
|
|
|
|
/*
|
|
* Higher-precision time. This retrieves the same time information as
|
|
* os_time() (i.e., the elapsed time since the standard Unix Epoch, January
|
|
* 1, 1970 at midnight UTC), but retrieves it with the highest precision
|
|
* available on the local system, up to nanosecond precision. If less
|
|
* precision is available, that's fine; just return the time to the best
|
|
* precision available, but expressed in terms of the number of
|
|
* nanoseconds. For example, if you can retrieve milliseconds, you can
|
|
* convert that to nanoseconds by multiplying by 1,000,000.
|
|
*
|
|
* On return, fills in '*seconds' with the number of whole seconds since
|
|
* the Epoch, and fills in '*nanoseconds' with the fractional portion,
|
|
* expressed in nanosceconds. Note that '*nanoseconds' is merely the
|
|
* fractional portion of the time, so 0 <= *nanoseconds < 1000000000.
|
|
*/
|
|
void os_time_ns(os_time_t *seconds, long *nanoseconds);
|
|
|
|
/*
|
|
* Get the local time zone name, as a location name in the IANA zoneinfo
|
|
* database. For example, locations using US Pacific Time should return
|
|
* "America/Los_Angeles".
|
|
*
|
|
* Returns true if successful, false if not. If the local operating system
|
|
* doesn't have a way to obtain this information, or if it's not available
|
|
* in the local machine's configuration, this returns false.
|
|
*
|
|
* The zoneinfo database is also known as the Olson or TZ (timezone)
|
|
* database; it's widely used on Unix systems as the definitive source of
|
|
* local time zone settings. See http://www.iana.org/time-zones for more
|
|
* information.
|
|
*
|
|
* On many Unix systems, the TZ environment variable contains the zoneinfo
|
|
* zone name when its first character is ':'. Windows uses a proprietary
|
|
* list of time zone names that can be mapped to zoneinfo names via a
|
|
* hand-coded list (such a list is maintained in the Unicode CLDR; our
|
|
* Windows implementation uses the CLDR list to generate the mapping).
|
|
* macOS uses zoneinfo keys directly; /etc/localtime is a link to the
|
|
* zoneinfo file for the local zone as set via the system preferences.
|
|
*
|
|
* os_tzset() must be invoked at some point before this routine is called.
|
|
*/
|
|
int os_get_zoneinfo_key(char *buf, size_t buflen);
|
|
|
|
/*
|
|
* Get a description of the local time zone. Fills in '*info' with the
|
|
* available information. Returns true on success, false on failure.
|
|
*
|
|
* See osstzprs.h/.c for a portable implementation of a parser for
|
|
* POSIX-style TZ strings. That can serve as a full implementation of this
|
|
* function for systems that use the POSIX TZ environment variable syntax
|
|
* to specify the timezone. (That routine simply parses a string from any
|
|
* source, so it can be used to parse the TZ syntax even on systems where
|
|
* the string comes from somewhere other than the TZ environment variable.)
|
|
*
|
|
* os_tzset() must be invoked at some point before this routine is called.
|
|
*
|
|
* The following two structures are used for the return information:
|
|
*
|
|
* os_tzrule_t - Timezone Rule structure. This describes a rule for an
|
|
* annual transition between daylight savings time and standard time in a
|
|
* time zone. Most timezones that have recurring standard/daylight changes
|
|
* require two of these rules, one for switching to daylight time in the
|
|
* spring and one for switching to standard time in the fall.
|
|
*
|
|
* os_tzinfo_t - Timezone Information structure. This describes a
|
|
* timezone's clock settings, name(s), and rules for recurring annual
|
|
* changes between standard time and daylight time, if applicable.
|
|
*/
|
|
struct os_tzrule_t {
|
|
/*
|
|
* Day of year, 1-365, NEVER counting Feb 29; set to 0 if not used.
|
|
* Corresponds to the "J" format in Unix TZ strings. (Called "Julian
|
|
* day" in the POSIX docs, thus the "J", even though it's a bit of a
|
|
* misnomer.)(Because of the invariance of the mapping from J-number to
|
|
* date, this is just an obtuse way of specifying a month/day date.
|
|
* But even so, we'll let the OS layer relay this back to us in
|
|
* J-number format and count on the portable caller to work out the
|
|
* date, rather than foisting that work on each platform
|
|
* implementation.)
|
|
*/
|
|
int jday;
|
|
|
|
/*
|
|
* Day of year, 1-366, counting Feb 29 on leap years; set to 0 if not
|
|
* used; ignored if 'jday' is nonzero. This corresponds to the Julian
|
|
* day sans "J" in TZ strings (almost - that TZ format uses 0-365 as
|
|
* its range, so bump it up by one when parsing a TZ string). This
|
|
* format is even more obtuse than the J-day format, in that it doesn't
|
|
* even have an invariant month/day mapping (not after day 59, anyway -
|
|
* day 60 is either February 29 or March 1, depending on the leapness
|
|
* of the year, and every day after that is similarly conditional). As
|
|
* far as I can tell, no one uses this option, so I'm not sure why it
|
|
* exists. The zoneinfo source format doesn't have a way to represent
|
|
* it, which says to me that no one has ever used it in a statutory DST
|
|
* start/end date definition in the whole history of time zones around
|
|
* the world, since the whole history of time zones around the world is
|
|
* exactly what the zoneinfo database captures in exhaustive and
|
|
* painstaking detail. If anyone had ever used it in defining a time
|
|
* zone, zoneinfo would have an option for it. My guess is that it's a
|
|
* fossilized bug from some early C RTL that's been retained out of an
|
|
* abundance of caution vis-a-vis compatibility, and was entirely
|
|
* replaced in practice by the J-number format as soon as someone
|
|
* noticed the fiddly leap year behavior. But for the sake of
|
|
* completeness...
|
|
*/
|
|
int yday;
|
|
|
|
/*
|
|
* The month (1-12), week of the month, and day of the week (1-7 for
|
|
* Sunday to Saturday). Week 1 is the first week in which 'day'
|
|
* occurs, week 2 is the second, etc.; week 5 is the last occurrence of
|
|
* 'day' in the month. These fields are used for "second Sunday in
|
|
* March" types of rules. Set these to zero if they're not used;
|
|
* they're ignored in any case if 'jday' or 'yday' are non-zero.
|
|
*/
|
|
int month;
|
|
int week;
|
|
int day;
|
|
|
|
/* time of day, in seconds after midnight (e.g., 2AM is 120 == 2*60*60) */
|
|
int time;
|
|
};
|
|
struct os_tzinfo_t {
|
|
/*
|
|
* The local offset from GMT, in seconds, for standard time and
|
|
* daylight time in this zone. These values are positive for zones
|
|
* east of GMT and negative for zones west: New York standard time
|
|
* (EST) is 5 hours west of GMT, so its offset is -5*60*60.
|
|
*
|
|
* Set both of these fields (if possible) regardless of whether
|
|
* standard or daylight time is currently in effect in the zone. The
|
|
* caller will select which offset to use based on the start/end rules,
|
|
* or based on the 'is_dst' flag if no rules are available.
|
|
*
|
|
* If it's only possible to determine the current wall clock offset, be
|
|
* it standard or daylight time, and it's not possible to determine the
|
|
* time difference between the two, simply set both of these to the
|
|
* current offset. This information isn't available from the standard
|
|
* C library, and many OS APIs also lack it.
|
|
*/
|
|
int32_t std_ofs;
|
|
int32_t dst_ofs;
|
|
|
|
/*
|
|
* The abbreviations for the local zone's standard time and daylight
|
|
* time, respectively, when displaying date/time values. E.g., "EST"
|
|
* and "EDT" for US Eastern Time. If the zone doesn't observe daylight
|
|
* time (it's on standard time year round), set dst_abbr to an empty
|
|
* string.
|
|
*
|
|
* As with std_ofs and dst_ofs, you can set both of these to the same
|
|
* string if it's only possible to determine the one that's currently
|
|
* in effect.
|
|
*/
|
|
char std_abbr[16];
|
|
char dst_abbr[16];
|
|
|
|
/*
|
|
* The ongoing rules for switching between daylight and standard time
|
|
* in this zone, if available. 'dst_start' is the date when daylight
|
|
* savings starts, 'dst_end' is the date when standard time resumes.
|
|
* Set all fields to 0 if the start/stop dates aren't available, or the
|
|
* zone is on standard time year round.
|
|
*/
|
|
struct os_tzrule_t dst_start;
|
|
struct os_tzrule_t dst_end;
|
|
|
|
/*
|
|
* True -> the zone is CURRENTLY on daylight savings time; false means
|
|
* it's currently on standard time.
|
|
*
|
|
* This is only used if the start/end rules aren't specified. In the
|
|
* absence of start/end rules, there's no way to know when the current
|
|
* standard/daylight phase ends, so we'll have to assume that the
|
|
* current mode is in effect permanently. In this case, the caller
|
|
* will use only be able to use the offset and abbreviation for the
|
|
* current mode and will have to ignore the other one.
|
|
*/
|
|
int is_dst;
|
|
};
|
|
int os_get_timezone_info(struct os_tzinfo_t *info);
|
|
|
|
|
|
/*
|
|
* Get the current system high-precision timer. This function returns a
|
|
* value giving the wall-clock ("real") time in milliseconds, relative to
|
|
* any arbitrary zero point. It doesn't matter what this value is relative
|
|
* to -- the only important thing is that the values returned by two
|
|
* different calls should differ by the number of actual milliseconds that
|
|
* have elapsed between the two calls. This might be the number of
|
|
* milliseconds since the computer was booted, since the current user
|
|
* logged in, since midnight of the previous night, since the program
|
|
* started running, since 1-1-1970, etc - it doesn't matter what the epoch
|
|
* is, so the implementation can use whatever's convenient on the local
|
|
* system.
|
|
*
|
|
* True millisecond precision isn't required. Each implementation should
|
|
* simply use the best precision available on the system. If your system
|
|
* doesn't have any kind of high-precision clock, you can simply use the
|
|
* time() function and multiply the result by 1000 (but see the note below
|
|
* about exceeding 32-bit precision).
|
|
*
|
|
* However, it *is* required that the return value be in *units* of
|
|
* milliseconds, even if your system clock doesn't have that much
|
|
* precision; so on a system that uses its own internal clock units, this
|
|
* routine must multiply the clock units by the appropriate factor to yield
|
|
* milliseconds for the return value.
|
|
*
|
|
* It is also required that the values returned by this function be
|
|
* monotonically increasing. In other words, each subsequent call must
|
|
* return a value that is equal to or greater than the value returned from
|
|
* the last call. On some systems, you must be careful of two special
|
|
* situations.
|
|
*
|
|
* First, the system clock may "roll over" to zero at some point; for
|
|
* example, on some systems, the internal clock is reset to zero at
|
|
* midnight every night. If this happens, you should make sure that you
|
|
* apply a bias after a roll-over to make sure that the value returned from
|
|
* this return continues to increase despite the reset of the system clock.
|
|
*
|
|
* Second, a 32-bit signed number can only hold about twenty-three days
|
|
* worth of milliseconds. While it seems unlikely that a TADS game would
|
|
* run for 23 days without a break, it's certainly reasonable to expect
|
|
* that the computer itself may run this long without being rebooted. So,
|
|
* if your system uses some large type (a 64-bit number, for example) for
|
|
* its high-precision timer, you may want to store a zero point the very
|
|
* first time this function is called, and then always subtract this zero
|
|
* point from the large value returned by the system clock. If you're
|
|
* using time(0)*1000, you should use this technique, since the result of
|
|
* time(0)*1000 will almost certainly not fit in 32 bits in most cases.
|
|
*/
|
|
long os_get_sys_clock_ms();
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Hardware Configuration. Define the following functions appropriately
|
|
* for your hardware. For efficiency, these functions should be defined
|
|
* as macros if possible.
|
|
*
|
|
* Note that these hardware definitions are independent of the OS, at
|
|
* least to the extent that your OS can run on multiple types of
|
|
* hardware. So, rather than combining these definitions into your
|
|
* osxxx.h header file, we recommend that you put these definitions in a
|
|
* separate h_yyy.h header file, which can be configured into os.h with
|
|
* an appropriate "_M_yyy" preprocessor symbol. Refer to os.h for
|
|
* details of configuring the hardware include file.
|
|
*/
|
|
|
|
/*
|
|
* Round a size up to worst-case alignment boundary. For example, on a
|
|
* platform where the largest type must be aligned on a 4-byte boundary,
|
|
* this should round the value up to the next higher mutliple of 4 and
|
|
* return the result.
|
|
*/
|
|
/* size_t osrndsz(size_t siz); */
|
|
|
|
/*
|
|
* Round a pointer up to worst-case alignment boundary.
|
|
*/
|
|
/* void *osrndpt(void *ptr); */
|
|
|
|
/*
|
|
* Read an unaligned portable unsigned 2-byte value, returning an int
|
|
* value. The portable representation has the least significant byte
|
|
* first, so the value 0x1234 is represented as the byte 0x34, followed
|
|
* by the byte 0x12.
|
|
*
|
|
* The source value must be treated as unsigned, but the result is
|
|
* signed. This is significant on 32- and 64-bit platforms, because it
|
|
* means that the source value should never be sign-extended to 32-bits.
|
|
* For example, if the source value is 0xffff, the result is 65535, not
|
|
* -1.
|
|
*/
|
|
/* int osrp2(unsigned char *p); */
|
|
|
|
/*
|
|
* Read an unaligned portable signed 2-byte value, returning int. This
|
|
* differs from osrp2() in that this function treats the source value as
|
|
* signed, and returns a signed result; hence, on 32- and 64-bit
|
|
* platforms, the result must be sign-extended to the int size. For
|
|
* example, if the source value is 0xffff, the result is -1.
|
|
*/
|
|
/* int osrp2s(unsigned char *p); */
|
|
|
|
/*
|
|
* Write unsigned int to unaligned portable 2-byte value. The portable
|
|
* representation stores the low-order byte first in memory, so
|
|
* oswp2(0x1234) should result in storing a byte value 0x34 in the first
|
|
* byte, and 0x12 in the second byte.
|
|
*/
|
|
/* void oswp2(unsigned char *p, unsigned int i); */
|
|
|
|
/*
|
|
* Write signed int to unaligned portable 2-byte value. Negative values
|
|
* must be stored in two's complement notation. E.g., -1 is stored as
|
|
* FF.FF, -32768 is stored as 00.80 (little-endian).
|
|
*
|
|
* Virtually all modern hardware uses two's complement notation as the
|
|
* native representation, which makes this routine a trivial synonym of
|
|
* osrp2() (i.e., #define oswp2s(p,i) oswp2(p,i)). We distinguish the
|
|
* signed version on the extremely off chance that TADS is ever ported to
|
|
* wacky hardware with a different representation for negative integers
|
|
* (one's complement, sign bit, etc).
|
|
*/
|
|
/* void oswp2s(unsigned char *p, int i); */
|
|
|
|
/*
|
|
* Read an unaligned unsigned portable 4-byte value, returning long. The
|
|
* underlying value should be considered signed, and the result is signed.
|
|
* The portable representation stores the bytes starting with the least
|
|
* significant: the value 0x12345678 is stored with 0x78 in the first byte,
|
|
* 0x56 in the second byte, 0x34 in the third byte, and 0x12 in the fourth
|
|
* byte.
|
|
*/
|
|
/* unsigned long osrp4(unsigned char *p); */
|
|
|
|
/*
|
|
* Read an unaligned signed portable 4-byte value, returning long.
|
|
*/
|
|
/* long osrp4s(unsigned char *p); */
|
|
|
|
/*
|
|
* Write an unsigned long to an unaligned portable 4-byte value. The
|
|
* portable representation stores the low-order byte first in memory, so
|
|
* 0x12345678 is written to memory as 0x78, 0x56, 0x34, 0x12.
|
|
*/
|
|
/* void oswp4(unsigned char *p, unsigned long l); */
|
|
|
|
/*
|
|
* Write a signed long, using little-endian byte order and two's complement
|
|
* notation for negative numbers. This is a trivial synonym for oswp4()
|
|
* for all platforms with native two's complement arithmetic (which is
|
|
* virtually all modern platforms). See oswp2s() for more discussion.
|
|
*/
|
|
/* void oswp4s(unsigned char *p, long l); */
|
|
|
|
/*
|
|
* For convenience and readability, the 1-byte integer (signed and
|
|
* unsigned) equivalents of the above.
|
|
*/
|
|
#define osrp1(p) (*(unsigned char *)(p))
|
|
#define osrp1s(p) (*(signed char *)(p))
|
|
#define oswp1(p, b) (*(unsigned char *)(p) = (b))
|
|
#define oswp1s(p, b) (*(signed char *)(p) = (b))
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* varargs va_copy() extension.
|
|
*
|
|
* On some compilers, va_list is a reference type. This means that if a
|
|
* va_list value is passed to a function that uses va_arg() to step through
|
|
* the referenced arguments, the caller's copy of the va_list might be
|
|
* updated on return. This is problematic in cases where the caller needs
|
|
* to use the va_list again in another function call, since the va_list is
|
|
* no longer pointing to the first argument for the second call. C99 has a
|
|
* solution in the form of the va_copy() macro. Unfortunately, this isn't
|
|
* typically available in pre-C99 compilers, and isn't standard in *any*
|
|
* C++ version. We thus virtualize it here in a macro.
|
|
*
|
|
* os_va_copy() has identical semantics to C99 va_copy(). A matching call
|
|
* to os_va_copy_end() must be made for each call to os_va_copy() before
|
|
* the calling function returns; this has identical semantics to C99
|
|
* va_end().
|
|
*
|
|
* Because our semantics are identical to the C99 version, we provide a
|
|
* default definition here for compilers that define va_copy(). Platform
|
|
* headers must provide suitable definitions only if their compilers don't
|
|
* have va_copy(). We also provide a definition for GCC compilers that
|
|
* define the private __va_copy macro, which also has the same semantics.
|
|
*/
|
|
#ifdef va_copy
|
|
# define os_va_copy(dst, src) va_copy(dst, src)
|
|
# define os_va_copy_end(dst) va_end(dst)
|
|
#else
|
|
# if defined(__GNUC__) && defined(__va_copy)
|
|
# define os_va_copy(dst, src) __va_copy(dst, src)
|
|
# define os_va_copy_end(dst) va_end(dst)
|
|
# endif
|
|
#endif
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Platform Identifiers. You must define the following macros in your
|
|
* osxxx.h header file:
|
|
*
|
|
* OS_SYSTEM_NAME - a string giving the system identifier. This string
|
|
* must contain only characters that are valid in a TADS identifier:
|
|
* letters, numbers, and underscores; and must start with a letter or
|
|
* underscore. For example, on MS-DOS, this string is "MSDOS".
|
|
*
|
|
* OS_SYSTEM_LDESC - a string giving the system descriptive name. This
|
|
* is used in messages displayed to the user. For example, on MS-DOS,
|
|
* this string is "MS-DOS".
|
|
*/
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Message Linking Configuration. You should #define ERR_LINK_MESSAGES
|
|
* in your osxxx.h header file if you want error messages linked into
|
|
* the application. Leave this symbol undefined if you want an external
|
|
* message file.
|
|
*/
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Program Exit Codes. These values are used for the argument to exit()
|
|
* to conform to local conventions. Define the following values in your
|
|
* OS-specific header:
|
|
*
|
|
* OSEXSUCC - successful completion. Usually defined to 0.
|
|
*. OSEXFAIL - failure. Usually defined to 1.
|
|
*/
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Basic memory management interface. These functions are merely
|
|
* documented here, but no prototypes are defined, because most
|
|
* platforms #define macros for these functions and types, mapping them
|
|
* to malloc or other system interfaces.
|
|
*/
|
|
|
|
/*
|
|
* Theoretical maximum osmalloc() size. This may be less than the
|
|
* capacity of the argument to osmalloc() on some systems. For example,
|
|
* on segmented architectures (such as 16-bit x86), memory is divided into
|
|
* segments, so a single memory allocation can allocate only a subset of
|
|
* the total addressable memory in the system. This value thus specifies
|
|
* the maximum amount of memory that can be allocated in one chunk.
|
|
*
|
|
* Note that this is an architectural maximum for the hardware and
|
|
* operating system. It doesn't have anything to do with the total amount
|
|
* of memory actually available at run-time.
|
|
*
|
|
* #define OSMALMAX to a constant long value with theoretical maximum
|
|
* osmalloc() argument value. For a platform with a flat (unsegmented)
|
|
* 32-bit memory space, this is usually 0xffffffff; for 16-bit platforms,
|
|
* this is usually 0xffff.
|
|
*/
|
|
/* #define OSMALMAX 0xffffffff */
|
|
|
|
/*
|
|
* Allocate a block of memory of the given size in bytes. The actual
|
|
* allocation may be larger, but may be no smaller. The block returned
|
|
* should be worst-case aligned (i.e., suitably aligned for any type).
|
|
* Return null if the given amount of memory is not available.
|
|
*/
|
|
/* void *osmalloc(size_t siz); */
|
|
|
|
/*
|
|
* Free memory previously allocated with osmalloc().
|
|
*/
|
|
/* void osfree(void *block); */
|
|
|
|
/*
|
|
* Reallocate memory previously allocated with osmalloc() or
|
|
* osrealloc(), changing the block's size to the given number of bytes.
|
|
* If necessary, a new block at a different address can be allocated, in
|
|
* which case the data from the original block is copied (the lesser of
|
|
* the old block size and the new size is copied) to the new block, and
|
|
* the original block is freed. If the new size is less than the old
|
|
* size, this need not do anything at all, since the returned block can
|
|
* be larger than the new requested size. If the block cannot be
|
|
* enlarged to the requested size, return null.
|
|
*/
|
|
/* void *osrealloc(void *block, size_t siz); */
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Basic file I/O interface. These functions are merely documented here,
|
|
* but no prototypes are defined, because most platforms #define macros for
|
|
* these functions and types, mapping them to stdio or other system I/O
|
|
* interfaces.
|
|
*
|
|
* When writing a file, writes might or might not be buffered in
|
|
* application memory; this is up to the OS implementation, which can
|
|
* perform buffering according to local conventions and what's most
|
|
* efficient. However, it shouldn't make any difference to the caller
|
|
* whether writes are buffered or not - the OS implementation must take
|
|
* care that any buffering is invisible to the app. (Porters: note that
|
|
* the basic C stdio package has the proper behavior here, so you'll get
|
|
* the correct semantics if you use a simple stdio implementation.)
|
|
*
|
|
* Write buffering might be visible to *other* apps, though. In
|
|
* particular, another process might not see data written to a file (with
|
|
* osfwb(), os_fprint(), etc) immediately, since the write functions might
|
|
* hold the written bytes in an internal memory buffer rather than sending
|
|
* them to the OS. Any internal buffers are guaranteed to be flushed to
|
|
* the OS upon calling osfcls() or osfflush(). Note that it's never
|
|
* *necessary* to call osfflush(), because buffered data will always be
|
|
* flushed on closing the file with osfcls(). However, if you want other
|
|
* apps to be able to see updates immediately, you can use osfflush() to
|
|
* ensure that buffers are flushed to a file before you close it.
|
|
*
|
|
* You can also use osfflush() to check for buffered write errors. When
|
|
* you use osfwb() or other write functions to write data, they will return
|
|
* a success indication even if the data was only copied into a buffer.
|
|
* This means that a write that appeared to succeed might actually fail
|
|
* later, when the buffer is flushed. The only way to know for sure is to
|
|
* explicitly flush buffers using osfflush(), and check the result code.
|
|
* If the original write function and a subsequent osfflush() *both* return
|
|
* success indications, then the write has definitely succeeded.
|
|
*/
|
|
|
|
|
|
/*
|
|
* Define the following values in your OS header to indicate local
|
|
* file/path syntax conventions:
|
|
*
|
|
* OSFNMAX - integer indicating maximum length of a filename
|
|
*
|
|
* OSPATHCHAR - character giving the normal path separator character
|
|
*. OSPATHALT - string giving other path separator characters
|
|
*. OSPATHURL - string giving path separator characters for URL conversions
|
|
*. OSPATHSEP - directory separator for PATH-style environment variables
|
|
*. OSPATHPWD - string giving the special path representing the current
|
|
*. working directory; for Unix or Windows, this is "."
|
|
*
|
|
* OSPATHURL is a little different: this specifies the characters that
|
|
* should be converted to URL-style separators when converting a path from
|
|
* local notation to URL notation. This is usually the same as the union
|
|
* of OSPATHCHAR and OSPATHALT, but need not be; for example, on DOS, the
|
|
* colon (':') is a path separator for most purposes, but is NOT a path
|
|
* character for URL conversions.
|
|
*/
|
|
|
|
/*
|
|
* Define the type osfildef as the appropriate file handle structure for
|
|
* your osfxxx functions. This type is always used as a pointer, but
|
|
* the value is always obtained from an osfopxxx call, and is never
|
|
* synthesized by portable code, so you can use essentially any type
|
|
* here that you want.
|
|
*
|
|
* For platforms that use C stdio functions to implement the osfxxx
|
|
* functions, osfildef can simply be defined as FILE.
|
|
*/
|
|
/* typedef FILE osfildef; */
|
|
|
|
|
|
/*
|
|
* File types.
|
|
*
|
|
* These are symbols of the form OSFTxxxx defining various content types,
|
|
* somewhat aking to MIME types. These were mainly designed for the old
|
|
* Mac OS (versions up to OS 9), where the file system stored a type tag
|
|
* with each file's metadata. The type tags were used for things like
|
|
* filtering file selector dialogs and setting file-to-app associations in
|
|
* the desktop shell.
|
|
*
|
|
* Our OSFTxxx symbols are abstract file types that we define, for types
|
|
* used within the TADS family of applications. They give us a common,
|
|
* cross-platform reference point for each type we use. Each port where
|
|
* file types are meaningful then maps our abstract type IDs to the
|
|
* corresponding port-specific type IDs. In practice, this has never been
|
|
* used anywhere other than the old Mac OS ports; in fact, it's not even
|
|
* used in the modern macOS since Apple decided to stop
|
|
* fighting the tide and start using filename suffixes for this sort of
|
|
* tagging, like everyone else always has.
|
|
*
|
|
* For the list of file types, see osifctyp.h
|
|
*/
|
|
|
|
|
|
/*
|
|
* Local newline convention.
|
|
*
|
|
* Because of the pernicious NIH ("Not Invented Here") cultures of the
|
|
* major technology vendors, basically every platform out there has its own
|
|
* unique way of expressing newlines in text files. Unix uses LF (ASCII
|
|
* 10); Mac uses CR (ASCII 13); DOS and Windows use CR-LF pairs. In the
|
|
* past there were heaven-only-knows how many other conventions in use, but
|
|
* fortunately these three have the market pretty well locked up at this
|
|
* point. But we do still have to worry about these three.
|
|
*
|
|
* Our strategy on input is to be open to just about anything whenever
|
|
* possible. So, when we're reading something that we believe to be a text
|
|
* file, we'll treat all of these as line endings: CR, LF, CR-LF, and
|
|
* LF-CR. It's pretty safe to do this; if we have a CR and LF occurring
|
|
* adjacently, it's almost certain that they're intended to be taken
|
|
* together as a single newline sequence. Likewise, if there's a lone CR
|
|
* or LF, it's rare for it to mean anything other than a newline.
|
|
*
|
|
* On output, though, we can't be as loose. The problem is that other
|
|
* applications on our big three platforms *don't* tend to aim for the same
|
|
* flexibility we do on input: other apps usually expect exactly the local
|
|
* conventions on input, and don't always work well if they don't get it.
|
|
* So it's important that when we're writing a text file, we write newlines
|
|
* in the local convention. This means that we sometimes need to know what
|
|
* the local convention actually is. That's where this definition comes
|
|
* in.
|
|
*
|
|
* Each port must define OS_NEWLINE_SEQ as an ASCII string giving the local
|
|
* newline sequence to write on output. For example, DOS defines it as
|
|
* "\r\n" (CR-LF). Always define it as a STRING (not a character
|
|
* constant), even if it's only one character long.
|
|
*
|
|
* (Note that some compilers use wacky mappings for \r and \n. Some older
|
|
* Mac compilers, for example, defined \n as CR and \r as LF, because of
|
|
* the Mac convention where newline is represented as CR in a text file.
|
|
* If there's any such variability on your platform, you can always use the
|
|
* octal codes to be unambiguous: \012 for LF and \015 for CR.)
|
|
*/
|
|
/* #define OS_NEWLINE_SEQ "\r\n" */
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* File "stat()" information - mode, size, time stamps
|
|
*/
|
|
|
|
/*
|
|
* Get a file's mode and attribute flags. This retrieves information on
|
|
* the given file equivalent to the st_mode member of the 'struct stat'
|
|
* data returned by the Unix stat() family of functions, as well as some
|
|
* extra system-specific attributes. On success, fills in *mode (if mode
|
|
* is non-null) with the mode information as a bitwise combination of
|
|
* OSFMODE_xxx values, fills in *attr (if attr is non-null) with a
|
|
* combination of OSFATTR_xxx attribute flags, and returns true; on
|
|
* failure, simply returns false. Failure can occur if the file doesn't
|
|
* exist, can't be accessed due to permissions, etc.
|
|
*
|
|
* Note that 'mode' and/or 'attr' can be null if the caller doesn't need
|
|
* that information. Implementations must check these parameters for null
|
|
* pointers and skip returning the corresponding information if null.
|
|
*
|
|
* If the file in 'fname' is a symbolic link, the behavior depends upon
|
|
* 'follow_links'. If 'follow_links' is true, the function should resolve
|
|
* the link reference (and if that points to another link, the function
|
|
* resolves that link as well, and so on) and return information on the
|
|
* object the link points to. Otherwise, the function returns information
|
|
* on the link itself. This only applies for symbolic links (not for hard
|
|
* links), and only if the underlying OS and file system support this
|
|
* distinction; if the OS transparently resolves links and doesn't allow
|
|
* retrieving information about the link itself, 'follow_links' can be
|
|
* ignored. Likewise, hard links (on systems that support them) are
|
|
* generally indistinguishable from regular files, so this function isn't
|
|
* expected to do anything special with them.
|
|
*
|
|
* The '*mode' value returned is a bitwise combination of OSFMODE_xxx flag.
|
|
* Many of the flags are mutually exclusive; for example, "file" and
|
|
* "directory" should never be combined. It's also possible for '*mode' to
|
|
* be zero for a valid file; this means that the file is of some special
|
|
* type on the local system that doesn't fit any of the OSFMODE_xxx types.
|
|
* (If any ports do encounter such cases, we can add OSFMODE_xxx types to
|
|
* accommodate new types. The list below isn't meant to be final; it's
|
|
* just what we've encountered so far on the platforms where TADS has
|
|
* already been ported.)
|
|
*
|
|
* The OSFMODE_xxx values are left for the OS to define so that they can be
|
|
* mapped directly to the OS API's equivalent constants, if desired. This
|
|
* makes the routine easy to write, since you can simply set *mode directly
|
|
* to the mode information the OS returns from its stat() or equivalent.
|
|
* However, note that these MUST be defined as bit flags - that is, each
|
|
* value must be exactly a power of 2. Windows and Unix-like systems
|
|
* follow this practice, as do most "stat()" functions in C run-time
|
|
* libraries, so this usually works automatically if you map these
|
|
* constants to OS or C library values. However, if a port defines its own
|
|
* values for these, take care that they're all powers of 2.
|
|
*
|
|
* Obviously, a given OS might not have all of the file types listed here.
|
|
* If any OSFMODE_xxx values aren't applicable on the local OS, you can
|
|
* simply define them as zero since they'll never be returned.
|
|
*
|
|
* Notes on attribute flags:
|
|
*
|
|
* OSFATTR_HIDDEN means that the file is conventionally hidden by default
|
|
* in user interface views or listings, but is still fully accessible to
|
|
* the user. Hidden files are also usually excluded by default from
|
|
* wildcard patterns in commands ("rm *.*"). On Unix, a hidden file is one
|
|
* whose name starts with "."; on Windows, it's a file with the HIDDEN bit
|
|
* in its file attributes. On systems where this concept exists, the user
|
|
* can still manipulate these files as normal by naming them explicitly,
|
|
* and can typically make them appear in UI views or directory listings via
|
|
* a preference setting or command flag (e.g., "ls -a" on Unix). The
|
|
* "hidden" flag is explicitly NOT a security or permissions mechanism, and
|
|
* it doesn't protect the file against intentional access by a user; it's
|
|
* merely a convenience designed to reduce clutter by excluding files
|
|
* maintained by the OS or by an application (such as preference files,
|
|
* indices, caches, etc) from casual folder browsing, where a user is
|
|
* typically only concerned with her own document files. On systems where
|
|
* there's no such naming convention or attribute metadata, this flag will
|
|
* never appear.
|
|
*
|
|
* OSFATTR_SYSTEM is similar to 'hidden', but means that the file is
|
|
* specially marked as an operating system file. This is mostly a
|
|
* DOS/Windows concept, where it corresponds to the SYSTEM bit in the file
|
|
* attributes; this flag will probably never appear on other systems. The
|
|
* distinction between 'system' and 'hidden' is somewhat murky even on
|
|
* Windows; most 'system' file are also marked as 'hidden', and in
|
|
* practical terms in the user interface, 'system' files are treated the
|
|
* same as 'hidden'.
|
|
*
|
|
* OSFATTR_READ means that the file is readable by this process.
|
|
*
|
|
* OSFATTR_WRITE means that the file is writable by this process.
|
|
*/
|
|
/* int osfmode(const char *fname, int follow_links, */
|
|
/* unsigned long *mode, unsigned long *attr); */
|
|
|
|
/* file mode/type constants */
|
|
/* #define OSFMODE_FILE - regular file */
|
|
/* #define OSFMODE_DIR - directory */
|
|
/* #define OSFMODE_BLK - block-mode device */
|
|
/* #define OSFMODE_CHAR - character-mode device */
|
|
/* #define OSFMODE_PIPE - pipe/FIFO/other character-oriented IPC */
|
|
/* #define OSFMODE_SOCKET - network socket */
|
|
/* #define OSFMODE_LINK - symbolic link */
|
|
|
|
/* file attribute constants */
|
|
/* #define OSFATTR_HIDDEN - hidden file */
|
|
/* #define OSFATTR_SYSTEM - system file */
|
|
/* #define OSFATTR_READ - the file is readable by this process */
|
|
/* #define OSFATTR_WRITE - the file is writable by this process */
|
|
|
|
struct os_file_stat_t {
|
|
/*
|
|
* Size of the file, in bytes. For platforms lacking 64-bit types, we
|
|
* split this into high and low 32-bit portions. Platforms where the
|
|
* native stat() or equivalent only returns a 32-bit file size can
|
|
* simply set sizehi to zero, since sizelo can hold the entire size
|
|
* value.
|
|
*/
|
|
uint32_t sizelo;
|
|
uint32_t sizehi;
|
|
|
|
/*
|
|
* Creation time, modification time, and last access time. If the file
|
|
* system doesn't keep information on one or more of these, use
|
|
* (os_time_t)0 to indicate that the timestamp isn't available. It's
|
|
* fine to return any subset of these. Per the standard C stat(),
|
|
* these should be expressed as seconds after the Unix Epoch.
|
|
*/
|
|
os_time_t cre_time;
|
|
os_time_t mod_time;
|
|
os_time_t acc_time;
|
|
|
|
/* file mode, using the same flags as returned from osfmode() */
|
|
unsigned long mode;
|
|
|
|
/* file attributes, using the same flags as returned from osfmode() */
|
|
unsigned long attrs;
|
|
};
|
|
|
|
|
|
/*
|
|
* Get stat() information. This fills in the portable os_file_stat
|
|
* structure with the requested file information. Returns true on success,
|
|
* false on failure (file not found, permissions error, etc).
|
|
*
|
|
* 'follow_links' has the same meaning as for osfmode().
|
|
*/
|
|
int os_file_stat(const char *fname, int follow_links, os_file_stat_t *s);
|
|
|
|
/*
|
|
* Manually resolve a symbolic link. If the local OS and file system
|
|
* support symbolic links, and the given filename is a symbolic link (in
|
|
* which case osfmode(fname, FALSE, &m, &a) will set OSFMODE_LINK in the
|
|
* mode bits), this fills in 'target' with the name of the link target
|
|
* (i.e., the object that the link in 'fname' points to). This should
|
|
* return a fully qualified file system path. Returns true on success,
|
|
* false on failure.
|
|
*
|
|
* This should only resolve a single level of indirection. If the link
|
|
* target of 'fname' is itself a link to a second target, this should only
|
|
* resolve the single reference from 'fname' to its direct direct. Callers
|
|
* that wish to resolve the final target of a chain of link references must
|
|
* iterate until the returned path doesn't refer to a link.
|
|
*/
|
|
int os_resolve_symlink(const char *fname, char *target, size_t target_size);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Get a list of root directories. If 'buf' is non-null, fills in 'buf'
|
|
* with a list of strings giving the root directories for the local,
|
|
* file-oriented devices on the system. The strings are each null
|
|
* terminated and are arranged consecutively in the buffer, with an extra
|
|
* null terminator after the last string to mark the end of the list.
|
|
*
|
|
* The return value is the length of the buffer required to hold the
|
|
* results. If the caller's buffer is null or is too short, the routine
|
|
* should return the full length required, and leaves the contents of the
|
|
* buffer undefined; the caller shouldn't expect any contents to be filled
|
|
* in if the return value is greater than buflen. Both 'buflen' and the
|
|
* return value include the null terminators, including the extra null
|
|
* terminator at the end of the list. If an error occurs, or the system
|
|
* has no concept of a root directory, returns zero.
|
|
*
|
|
* Each result string should be expressed using the syntax for the root
|
|
* directory on a device. For example, on Windows, "C:\" represents the
|
|
* root directory on the C: drive.
|
|
*
|
|
* "Local" means a device is mounted locally, as opposed to being merely
|
|
* visible on the network via some remote node syntax; e.g., on Windows
|
|
* this wouldn't include any UNC-style \\SERVER\SHARE names, and on VMS it
|
|
* excludes any SERVER:: nodes. It's up to each system how to treat
|
|
* virtual local devices, i.e., those that look synctactically like local
|
|
* devices but are actually mounted network devices, such as Windows mapped
|
|
* network drives; we recommend including them if it would take extra work
|
|
* to filter them out, and excluding them if it would take extra work to
|
|
* include them. "File-oriented" means that the returned devices are
|
|
* accessed via file systems, not as character devices or raw block
|
|
* devices; so this would exclude /dev/xxx devices on Unix and things like
|
|
* CON: and LPT1: on Windows.
|
|
*
|
|
* Examples ("." represents a null byte):
|
|
*
|
|
* Windows: C:\.D:\.E:\..
|
|
*
|
|
* Unix example: /..
|
|
*/
|
|
size_t os_get_root_dirs(char *buf, size_t buflen);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Open a directory. This begins an enumeration of a directory's contents.
|
|
* 'dirname' is a relative or absolute path to a directory. On success,
|
|
* returns true, and 'handle' is set to a port-defined handle value that's
|
|
* used in subsequent calls to os_read_dir() and os_close_dir(). Returns
|
|
* false on failure.
|
|
*
|
|
* If the routine succeeds, the caller must eventually call os_close_dir()
|
|
* to release the resources associated with the handle.
|
|
*/
|
|
/* typedef <local system type> osdirhdl_t; */
|
|
int os_open_dir(const char *dirname, /*OUT*/osdirhdl_t *handle);
|
|
|
|
/*
|
|
* Read the next file in a directory. 'handle' is a handle value obtained
|
|
* from a call to os_open_dir(). On success, returns true and fills in
|
|
* 'fname' with the next filename; the handle is also internally updated so
|
|
* that the next call to this function will retrieve the next file, and so
|
|
* on until all files have been retrieved. If an error occurs, or there
|
|
* are no more files in the directory, returns false.
|
|
*
|
|
* The filename returned is the root filename only, without the path. The
|
|
* caller can build the full path by calling os_build_full_path() or
|
|
* os_combine_paths() with the original directory name and the returned
|
|
* filename as parameters.
|
|
*
|
|
* This routine lists all objects in the directory that are visible to the
|
|
* corresponding native API, and is non-recursive. The listing should thus
|
|
* include subdirectory objects, but not the contents of subdirectories.
|
|
* Implementations are encouraged to simply return all objects returned
|
|
* from the corresponding native directory scan API; there's no need to do
|
|
* any filtering, except perhaps in cases where it's difficult or
|
|
* impossible to represent an object in terms of the osifc APIs (e.g., it
|
|
* might be reasonable to exclude files without names). System relative
|
|
* links, such as the Unix/DOS "." and "..", specifically should be
|
|
* included in the listing. For unusual objects that don't fit into the
|
|
* os_file_stat() taxonomy or that otherwise might create confusion for a
|
|
* caller, err on the side of full disclosure (i.e., just return everything
|
|
* unfiltered); if necessary, we can extend the os_file_stat() taxonomy or
|
|
* add new osifc APIs to create a portable abstraction to handle whatever
|
|
* is unusual or potentially confusing about the native object. For
|
|
* example, Unix implementations should feel free to return symbolic link
|
|
* objects, including dangling links, since we have the portable
|
|
* os_resolve_symlink() that lets the caller examine the meaning of the
|
|
* link object.
|
|
*/
|
|
int os_read_dir(osdirhdl_t handle, char *fname, size_t fname_size);
|
|
|
|
/*
|
|
* Close a directory handle. This releases the resources associated with a
|
|
* directory search started with os_open_dir(). Every successful call to
|
|
* os_open_dir() must have a matching call to os_close_dir(). As usual for
|
|
* open/close protocols, the handle is invalid after calling this function,
|
|
* so no more calls to os_read_dir() may be made with the handle.
|
|
*/
|
|
void os_close_dir(osdirhdl_t handle);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* NB - this routine is DEPRECATED as of TADS 2.5.16/3.1.1. Callers should
|
|
* use os_open_dir(), os_read_dir(), os_close_dir() instead.
|
|
*
|
|
* Find the first file matching a given pattern. The returned context
|
|
* pointer is a pointer to whatever system-dependent context structure is
|
|
* needed to continue the search with the next file, and is opaque to the
|
|
* caller. The caller must pass the context pointer to the next-file
|
|
* routine. The caller can optionally cancel a search by calling the
|
|
* close-search routine with the context pointer. If the return value is
|
|
* null, it indicates that no matching files were found. If a file was
|
|
* found, outbuf will be filled in with its name, and isdir will be set to
|
|
* true if the match is a directory, false if it's a file. If pattern is
|
|
* null, all files in the given directory should be returned; otherwise,
|
|
* pattern is a string containing '*' and '?' as wildcard characters, but
|
|
* not containing any directory separators, and all files in the given
|
|
* directory matching the pattern should be returned.
|
|
*
|
|
* Important: because this routine may allocate memory for the returned
|
|
* context structure, the caller must either call os_find_next_file until
|
|
* that routine returns null, or call os_find_close() to cancel the search,
|
|
* to ensure that the os code has a chance to release the allocated memory.
|
|
*
|
|
* 'outbuf' should be set on output to the name of the matching file,
|
|
* without any path information.
|
|
*
|
|
* 'outpathbuf' should be set on output to full path of the matching file.
|
|
* If possible, 'outpathbuf' should use the same relative or absolute
|
|
* notation that the search criteria used on input. For example, if dir =
|
|
* "resfiles", and the file found is "MyPic.jpg", outpathbuf should be set
|
|
* to "resfiles/MyPic.jpg" (or appropriate syntax for the local platform).
|
|
* Similarly, if dir = "/home/tads/resfiles", outpath buf should be
|
|
* "/home/tads/resfiles/MyPic.jpg". The result should always conform to
|
|
* correct local conventions, which may require some amount of manipulation
|
|
* of the filename; for example, on the Mac, if dir = "resfiles", the
|
|
* result should be ":resfiles:MyPic.jpg" (note the added leading colon) to
|
|
* conform to Macintosh relative path notation.
|
|
*
|
|
* Note that 'outpathbuf' may be null, in which case the caller is not
|
|
* interested in the full path information.
|
|
*/
|
|
/*
|
|
* Note the following possible ways this function may be called:
|
|
*
|
|
* dir = "", pattern = filename - in this case, pattern is the name of a
|
|
* file or directory in the current directory. filename *might* be a
|
|
* relative path specified by the user (on a command line, for example);
|
|
* for instance, on Unix, it could be something like "resfiles/jpegs".
|
|
*
|
|
* dir = path, pattern = filname - same as above, but this time the
|
|
* filename or directory pattern is relative to the given path, rather
|
|
* than to the current directory. For example, we could have dir =
|
|
* "/games/mygame" and pattern = "resfiles/jpegs".
|
|
*
|
|
* dir = path, pattern = 0 (NULL) - this should search for all files in
|
|
* the given path. The path might be absolute or it might be relative.
|
|
*
|
|
* dir = path, pattern = "*" - this should have the same result as when
|
|
* pattern = 0.
|
|
*
|
|
* dir = path, pattern = "*.ext" - this should search for all files in
|
|
* the given path whose names end with ".ext".
|
|
*
|
|
* dir = path, pattern = "abc*" - this should search for all files in
|
|
* the given path whose names start with "abc".
|
|
*
|
|
* All of these combinations are possible because callers, for
|
|
* portability, must generally not manipulate filenames directly;
|
|
* instead, callers obtain paths and search strings from external
|
|
* sources, such as from the user, and present them to this routine with
|
|
* minimal manipulation.
|
|
*/
|
|
void *os_find_first_file(const char *dir,
|
|
char *outbuf, size_t outbufsiz, int *isdir,
|
|
char *outpathbuf, size_t outpathbufsiz);
|
|
|
|
/*
|
|
* Implementation notes for porting os_find_first_file:
|
|
*
|
|
* The algorithm for this routine should go something like this:
|
|
*
|
|
* - If 'path' is null, create a variable real_path and initialize it
|
|
* with the current directory. Otherwise, copy path to real_path.
|
|
*
|
|
* - If 'pattern' contains any directory separators ("/" on Unix, for
|
|
* example), change real_path so that it reflects the additional leading
|
|
* subdirectories in the path in 'pattern', and remove the leading path
|
|
* information from 'pattern'. For example, on Unix, if real_path
|
|
* starts out as "./subdir", and pattern is "resfiles/jpegs", change
|
|
* real_path to "./subdir/resfiles", and change pattern to "jpegs".
|
|
* Take care to add and remove path separators as needed to keep the
|
|
* path strings well-formed.
|
|
*
|
|
* - Begin a search using appropriate OS API's for all files in
|
|
* real_path.
|
|
*
|
|
* - Check each file found. Skip any files that don't match 'pattern',
|
|
* treating "*" as a wildcard that matches any string of zero or more
|
|
* characters, and "?" as a wildcard that matches any single character
|
|
* (or matches nothing at the end of a string). For example:
|
|
*
|
|
*. "*" matches anything
|
|
*. "abc?" matches "abc", "abcd", "abce", "abcf", but not "abcde"
|
|
*. "abc???" matches "abc", "abcd", "abcde", "abcdef", but not "abcdefg"
|
|
*. "?xyz" matches "wxyz", "axyz", but not "xyz" or "abcxyz"
|
|
*
|
|
* - Return the first file that matches, if any, by filling in 'outbuf'
|
|
* and 'isdir' with appropriate information. Before returning, allocate
|
|
* a context structure (which is entirely for your own use, and opaque
|
|
* to the caller) and fill it in with the information necessary for
|
|
* os_find_next_file to get the next matching file. If no file matches,
|
|
* return null.
|
|
*/
|
|
|
|
|
|
/*
|
|
* Find the next matching file, continuing a search started with
|
|
* os_find_first_file(). Returns null if no more files were found, in
|
|
* which case the search will have been automatically closed (i.e.,
|
|
* there's no need to call os_find_close() after this routine returns
|
|
* null). Returns a non-null context pointer, which is to be passed to
|
|
* this function again to get the next file, if a file was found.
|
|
*
|
|
* 'outbuf' and 'outpathbuf' are filled in with the filename (without
|
|
* path) and full path (relative or absolute, as appropriate),
|
|
* respectively, in the same manner as they do for os_find_first_file().
|
|
*
|
|
* Implementation note: if os_find_first_file() allocated memory for the
|
|
* search context, this routine must free the memory if it returs null,
|
|
* because this indicates that the search is finished and the caller
|
|
* need not call os_find_close().
|
|
*/
|
|
void *os_find_next_file(void *ctx, char *outbuf, size_t outbufsiz,
|
|
int *isdir, char *outpathbuf, size_t outpathbufsiz);
|
|
|
|
/*
|
|
* Cancel a search. The context pointer returned by the last call to
|
|
* os_find_first_file() or os_find_next_file() is the parameter. There
|
|
* is no need to call this function if find-first or find-next returned
|
|
* null, since they will have automatically closed the search.
|
|
*
|
|
* Implementation note: if os_find_first_file() allocated memory for the
|
|
* search context, this routine should release the memory.
|
|
*/
|
|
void os_find_close(void *ctx);
|
|
|
|
/*
|
|
* Special filename classification
|
|
*/
|
|
enum os_specfile_t
|
|
{
|
|
/* not a special file */
|
|
OS_SPECFILE_NONE,
|
|
|
|
/*
|
|
* current directory link - this is a file like the "." file on Unix
|
|
* or DOS, which is a special link that simply refers to itself
|
|
*/
|
|
OS_SPECFILE_SELF,
|
|
|
|
/*
|
|
* parent directory link - this is a file like the ".." file on Unix
|
|
* or DOS, which is a special link that refers to the parent
|
|
* directory
|
|
*/
|
|
OS_SPECFILE_PARENT
|
|
};
|
|
|
|
/*
|
|
* Determine if the given filename refers to a special file. Returns the
|
|
* appropriate enum value if so, or OS_SPECFILE_NONE if not. The given
|
|
* filename must be a root name - it must not contain a path prefix. The
|
|
* purpose here is to classify the results from os_find_first_file() and
|
|
* os_find_next_file() to identify the special relative links, so callers
|
|
* can avoid infinite recursion when traversing a directory tree.
|
|
*/
|
|
enum os_specfile_t os_is_special_file(const char *fname);
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Convert string to all-lowercase.
|
|
*/
|
|
char *os_strlwr(char *s);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Character classifications for quote characters. os_squote() returns
|
|
* true if its argument is any type of single-quote character;
|
|
* os_dquote() returns true if its argument is any type of double-quote
|
|
* character; and os_qmatch(a, b) returns true if a and b are matching
|
|
* open- and close-quote characters.
|
|
*
|
|
* These functions allow systems with extended character codes with
|
|
* weird quote characters (such as the Mac) to match the weird
|
|
* characters, so that users can use the extended quotes in input.
|
|
*
|
|
* These are usually implemented as macros. The most common
|
|
* implementation simply returns true for the standard ASCII quote
|
|
* characters:
|
|
*
|
|
* #define os_squote(c) ((c) == '\'')
|
|
*. #define os_dquote(c) ((c) == '"')
|
|
*. #define os_qmatch(a, b) ((a) == (b))
|
|
*
|
|
* These functions take int arguments to allow for the possibility of
|
|
* Unicode input.
|
|
*/
|
|
/* int os_squote(int c); */
|
|
/* int os_dquote(int c); */
|
|
/* int os_qmatch(int a, int b); */
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Special file and directory locations
|
|
*/
|
|
|
|
/*
|
|
* Get the full filename (including directory path) to the executable
|
|
* file, given the argv[0] parameter passed into the main program. This
|
|
* fills in the buffer with a null-terminated string that can be used in
|
|
* osfoprb(), for example, to open the executable file.
|
|
*
|
|
* Returns non-zero on success. If it's not possible to determine the
|
|
* name of the executable file, returns zero.
|
|
*
|
|
* Some operating systems might not provide access to the executable file
|
|
* information, so non-trivial implementation of this routine is optional;
|
|
* if the necessary information is not available, simply implement this to
|
|
* return zero. If the information is not available, callers should offer
|
|
* gracefully degraded functionality if possible.
|
|
*/
|
|
int os_get_exe_filename(char *buf, size_t buflen, const char *argv0);
|
|
|
|
/*
|
|
* Get a special directory path. Returns the selected path, in a format
|
|
* suitable for use with os_build_full_path(). The main program's argv[0]
|
|
* parameter is provided so that the system code can choose to make the
|
|
* special paths relative to the program install directory, but this is
|
|
* entirely up to the system implementation, so the argv[0] parameter can
|
|
* be ignored if it is not needed.
|
|
*
|
|
* The 'id' parameter selects which special path is requested; this is one
|
|
* of the constants defined below. If the id is not understood, there is
|
|
* no way of signalling an error to the caller; this routine can fail with
|
|
* an assert() in such cases, because it indicates that the OS layer code
|
|
* is out of date with respect to the calling code.
|
|
*
|
|
* This routine can be implemented using one of the strategies below, or a
|
|
* combination of these. These are merely suggestions, though, and systems
|
|
* are free to ignore these and implement this routine using whatever
|
|
* scheme is the best fit to local conventions.
|
|
*
|
|
* - Relative to argv[0]. Some systems use this approach because it keeps
|
|
* all of the TADS files together in a single install directory tree, and
|
|
* doesn't require any extra configuration information to find the install
|
|
* directory. Since we base the path name on the executable that's
|
|
* actually running, we don't need any environment variables or parameter
|
|
* files or registry entries to know where to look for related files.
|
|
*
|
|
* - Environment variables or local equivalent. On some systems, it is
|
|
* conventional to set some form of global system parameter (environment
|
|
* variables on Unix, for example) for this sort of install configuration
|
|
* data. In these cases, this routine can look up the appropriate
|
|
* configuration variables in the system environment.
|
|
*
|
|
* - Hard-coded paths. Some systems have universal conventions for the
|
|
* installation configuration of compiler-like tools, so the paths to our
|
|
* component files can be hard-coded based on these conventions.
|
|
*
|
|
* - Hard-coded default paths with environment variable overrides. Let the
|
|
* user set environment variables if they want, but use the standard system
|
|
* paths as hard-coded defaults if the variables aren't set. This is often
|
|
* the best choice; users who expect the standard system conventions won't
|
|
* have to fuss with any manual settings or even be aware of them, while
|
|
* users who need custom settings aren't stuck with the defaults.
|
|
*/
|
|
void os_get_special_path(char *buf, size_t buflen,
|
|
const char *argv0, int id);
|
|
|
|
/*
|
|
* TADS 3 system resource path. This path is used to load system
|
|
* resources, such as character mapping files and error message files.
|
|
*/
|
|
#define OS_GSP_T3_RES 1
|
|
|
|
/*
|
|
* TADS 3 compiler - system headers. This is the #include path for the
|
|
* header files included with the compiler.
|
|
*/
|
|
#define OS_GSP_T3_INC 2
|
|
|
|
/*
|
|
* TADS 3 compiler - system library source code. This is the path to the
|
|
* library source files that the compiler includes in every compilation by
|
|
* default (such as _main.t).
|
|
*/
|
|
#define OS_GSP_T3_LIB 3
|
|
|
|
/*
|
|
* TADS 3 compiler - user library path list. This is a list of directory
|
|
* paths, separated by the OSPATHSEP character, that should be searched for
|
|
* user library files. The TADS 3 compiler uses this as an additional set
|
|
* of locations to search after the list of "-Fs" options and before the
|
|
* OS_GSP_T3_LIB directory.
|
|
*
|
|
* This path list is intended for the user's use, so no default value is
|
|
* needed. The value should be user-configurable using local conventions;
|
|
* on Unix, for example, this might be handled with an environment
|
|
* variable.
|
|
*/
|
|
#define OS_GSP_T3_USER_LIBS 4
|
|
|
|
/*
|
|
* TADS 3 interpreter - application data path. This is the directory where
|
|
* we should store things like option settings: data that we want to store
|
|
* in a file, global to all games. Depending on local system conventions,
|
|
* this can be a global shared directory for all users, or can be a
|
|
* user-specific directory.
|
|
*/
|
|
#define OS_GSP_T3_APP_DATA 5
|
|
|
|
/*
|
|
* TADS 3 interpreter - system configuration files. This is used for files
|
|
* that affect all games, and generally all users on the system, so it
|
|
* should be in a central location. On Windows, for example, we simply
|
|
* store these files in the install directory containing the intepreter
|
|
* binary.
|
|
*/
|
|
#define OS_GSP_T3_SYSCONFIG 6
|
|
|
|
/*
|
|
* System log files. This is the directory for system-level status, debug,
|
|
* and error logging files. (Note that we're NOT talking about in-game
|
|
* transcript logging per the SCRIPT command. SCRIPT logs are usually sent
|
|
* to files selected by the user via a save-file dialog, so these don't
|
|
* need a special location.)
|
|
*/
|
|
#define OS_GSP_LOGFILE 7
|
|
|
|
|
|
/*
|
|
* Seek to the resource file embedded in the current executable file,
|
|
* given the main program's argv[0].
|
|
*
|
|
* On platforms where the executable file format allows additional
|
|
* information to be attached to an executable, this function can be used
|
|
* to find the extra information within the executable.
|
|
*
|
|
* The 'typ' argument gives a resource type to find. This is an arbitrary
|
|
* string that the caller uses to identify what type of object to find.
|
|
* The "TGAM" type, for example, is used by convention to indicate a TADS
|
|
* compiled GAM file.
|
|
*/
|
|
osfildef *os_exeseek(const char *argv0, const char *typ);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Load a string resource. Given a string ID number, load the string
|
|
* into the given buffer.
|
|
*
|
|
* Returns zero on success, non-zero if an error occurs (for example,
|
|
* the buffer is too small, or the requested resource isn't present).
|
|
*
|
|
* Whenever possible, implementations should use an operating system
|
|
* mechanism for loading the string from a user-modifiable resource
|
|
* store; this will make localization of these strings easier, since the
|
|
* resource store can be modified without the need to recompile the
|
|
* application. For example, on the Macintosh, the normal system string
|
|
* resource mechanism should be used to load the string from the
|
|
* application's resource fork.
|
|
*
|
|
* When no operating system mechanism exists, the resources can be
|
|
* stored as an array of strings in a static variable; this isn't ideal,
|
|
* because it makes it much more difficult to localize the application.
|
|
*
|
|
* Resource ID's are application-defined. For example, for TADS 2,
|
|
* "res.h" defines the resource ID's.
|
|
*/
|
|
int os_get_str_rsc(int id, char *buf, size_t buflen);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Get a suitable seed for a random number generator; should use the system
|
|
* clock or some other source of an unpredictable and changing seed value.
|
|
*/
|
|
void os_rand(long *val);
|
|
|
|
/*
|
|
* Generate random bytes for use in seeding a PRNG (pseudo-random number
|
|
* generator). This is an extended version of os_rand() for PRNGs that use
|
|
* large seed vectors containing many bytes, rather than the simple 32-bit
|
|
* seed that os_rand() assumes.
|
|
*
|
|
* As with os_rand(), this function isn't meant to be used directly as a
|
|
* random number source for ongoing use - instead, this is intended mostly
|
|
* for seeding a PRNG, which will then be used as the primary source of
|
|
* random numbers. The big problem with using this routine directly as a
|
|
* randomness source is that some implementations might rely heavily on
|
|
* environmental randomness, such as the real-time clock or OS usage
|
|
* statistics. Such sources tend to provide reasonable entropy from one
|
|
* run to the next, but not within a single session, as the underlying data
|
|
* sources don't change rapidly enough.
|
|
*
|
|
* Ideally, this routine should generate *truly* random bytes obtained from
|
|
* hardware sources. Not all systems can provide that, though, so true
|
|
* randomness isn't guaranteed. Here are the suggested implementation
|
|
* options, in descending order of desirability:
|
|
*
|
|
* 1. Use a hardware source of true randomness, such as a /dev/rand type
|
|
* of device. However, note that this call should return reasonably
|
|
* quickly, so always use a non-blocking source. Some Unix /dev/rand
|
|
* devices, for example, can block indefinitely to allow sufficient entropy
|
|
* to accumulate.
|
|
*
|
|
* 2. Use a cryptographic random number source provided by the OS. Some
|
|
* systems provide this as an API service. If going this route, be sure
|
|
* that the OS generator is itself "seeded" with some kind of true
|
|
* randomness source, as it defeats the whole purpose if you always return
|
|
* a fixed pseudo-random sequence each time the program runs.
|
|
*
|
|
* 3. Use whatever true random sources are available locally to seed a
|
|
* software pseudo-random number generator, then generate bytes from your
|
|
* PRNG. Some commonly available sources of true randomness are a
|
|
* high-resolution timer, the system clock, the current process ID,
|
|
* logged-in user ID, environment variables, uninitialized pages of memory,
|
|
* the IP address; each of these sources might give you a few bits of
|
|
* entropy at best, so the best bet is to use an ensemble. You could, for
|
|
* example, concatenate a bunch of this type of information together and
|
|
* calculate an MD5 or SHA1 hash to mix the bits more thoroughly. For the
|
|
* PRNG, use a cryptographic generator. (You could use the ISAAC generator
|
|
* from TADS 3, as that's a crypto PRNG, but it's probably better to use a
|
|
* different generator here since TADS 3 is going to turn around and use
|
|
* this function's output to seed ISAAC - seeding one ISAAC instance with
|
|
* another ISAAC's output seems likely to magnify any weaknesses in the
|
|
* ISAAC algorithm.) Note that this option is basically the DIY version of
|
|
* option 2. Option 2 is better because the OS probably has access to
|
|
* better sources of true randomness than an application does.
|
|
*/
|
|
void os_gen_rand_bytes(unsigned char *buf, size_t len);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Display routines.
|
|
*
|
|
* Our display model is a simple stdio-style character stream.
|
|
*
|
|
* In addition, we provide an optional "status line," which is a
|
|
* non-scrolling area where a line of text can be displayed. If the status
|
|
* line is supported, text should only be displayed in this area when
|
|
* os_status() is used to enter status-line mode (mode 1); while in status
|
|
* line mode, text is written to the status line area, otherwise (mode 0)
|
|
* it's written to the normal main text area. The status line is normally
|
|
* shown in a different color to set it off from the rest of the text.
|
|
*
|
|
* The OS layer can provide its own formatting (word wrapping in
|
|
* particular) if it wants, in which case it should also provide pagination
|
|
* using os_more_prompt().
|
|
*/
|
|
|
|
/*
|
|
* OS_MAXWIDTH - the maximum width of a line of text. Most platforms use
|
|
* 135 for this, but you can use more or less as appropriate. If you use
|
|
* OS-level line wrapping, then the true width of a text line is
|
|
* irrelevant, and the portable code will use this merely for setting its
|
|
* internal buffer sizes.
|
|
*
|
|
* This must be defined in the os_xxx.h header file for each platform.
|
|
*/
|
|
/*#define OS_MAXWIDTH 135 - example only: define for real in os_xxx.h header*/
|
|
|
|
/*
|
|
* Print a string on the console. These routines come in two varieties:
|
|
*
|
|
* os_printz - write a NULL-TERMINATED string
|
|
*. os_print - write a COUNTED-LENGTH string, which may not end with a null
|
|
*
|
|
* These two routines are identical except that os_printz() takes a string
|
|
* which is terminated by a null byte, and os_print() instead takes an
|
|
* explicit length, and a string that may not end with a null byte.
|
|
*
|
|
* os_printz(str) may be implemented as simply os_print(str, strlen(str)).
|
|
*
|
|
* The string is written in one of three ways, depending on the status mode
|
|
* set by os_status():
|
|
*
|
|
* status mode == 0 -> write to main text window
|
|
*. status mode == 1 -> write to status line
|
|
*. anything else -> do not display the text at all
|
|
*
|
|
* Implementations are free to omit any status line support, in which case
|
|
* they should simply suppress all output when the status mode is anything
|
|
* other than zero.
|
|
*
|
|
* The following special characters must be recognized in the displayed
|
|
* text:
|
|
*
|
|
* '\n' - newline: end the current line and move the cursor to the start of
|
|
* the next line. If the status line is supported, and the current status
|
|
* mode is 1 (i.e., displaying in the status line), then two special rules
|
|
* apply to newline handling: newlines preceding any other text should be
|
|
* ignored, and a newline following any other text should set the status
|
|
* mode to 2, so that all subsequent output is suppressed until the status
|
|
* mode is changed with an explicit call by the client program to
|
|
* os_status().
|
|
*
|
|
* '\r' - carriage return: end the current line and move the cursor back to
|
|
* the beginning of the current line. Subsequent output is expected to
|
|
* overwrite the text previously on this same line. The implementation
|
|
* may, if desired, IMMEDIATELY clear the previous text when the '\r' is
|
|
* written, rather than waiting for subsequent text to be displayed.
|
|
*
|
|
* All other characters may be assumed to be ordinary printing characters.
|
|
* The routine need not check for any other special characters.
|
|
*
|
|
*/
|
|
void os_printz(const char *str);
|
|
void os_print(const char *str, size_t len);
|
|
|
|
/*
|
|
* Print to the debugger console. These routines are for interactive
|
|
* debugger builds only: they display the given text to a separate window
|
|
* within the debugger UI (separate from the main game command window)
|
|
* where the debugger displays status information specific to the debugging
|
|
* session (such as compiler/build output, breakpoint status messages,
|
|
* etc). For example, TADS Workbench on Windows displays these messages in
|
|
* its "Debug Log" window.
|
|
*
|
|
* These routines only need to be implemented for interactive debugger
|
|
* builds, such as TADS Workbench on Windows. These can be omitted for
|
|
* regular interpreter builds.
|
|
*/
|
|
void os_dbg_printf(const char *fmt, ...);
|
|
void os_dbg_vprintf(const char *fmt, va_list args);
|
|
|
|
/*
|
|
* Allocating sprintf and vsprintf. These work like the regular C library
|
|
* sprintf and vsprintf funtions, but they allocate a return buffer that's
|
|
* big enough to hold the result, rather than formatting into a caller's
|
|
* buffer. This protects against buffer overruns and ensures that the
|
|
* result isn't truncated.
|
|
*
|
|
* On return, '*bufptr' is filled in with a pointer to a buffer allocated
|
|
* with osmalloc(). This buffer contains the formatted string result. The
|
|
* caller is responsible for freeing the buffer by calling osfree().
|
|
* *bufptr can be null on return if an error occurs.
|
|
*
|
|
* The return value is the number of bytes written to the allocated buffer,
|
|
* not including the null terminator. If an error occurs, the return value
|
|
* is -1 and *bufptr is undefined.
|
|
*
|
|
* Many modern C libraries provide equivalents of these, usually called
|
|
* asprintf() and vasprintf(), respectively.
|
|
*/
|
|
/* int os_asprintf(char **bufptr, const char *fmt, ...); */
|
|
int os_vasprintf(char **bufptr, const char *fmt, va_list ap);
|
|
|
|
|
|
/*
|
|
* Set the status line mode. There are three possible settings:
|
|
*
|
|
* 0 -> main text mode. In this mode, all subsequent text written with
|
|
* os_print() and os_printz() is to be displayed to the main text area.
|
|
* This is the normal mode that should be in effect initially. This mode
|
|
* stays in effect until an explicit call to os_status().
|
|
*
|
|
* 1 -> statusline mode. In this mode, text written with os_print() and
|
|
* os_printz() is written to the status line, which is usually rendered as
|
|
* a one-line area across the top of the terminal screen or application
|
|
* window. In statusline mode, leading newlines ('\n' characters) are to
|
|
* be ignored, and any newline following any other character must change
|
|
* the mode to 2, as though os_status(2) had been called.
|
|
*
|
|
* 2 -> suppress mode. In this mode, all text written with os_print() and
|
|
* os_printz() must simply be ignored, and not displayed at all. This mode
|
|
* stays in effect until an explicit call to os_status().
|
|
*/
|
|
void os_status(int stat);
|
|
|
|
/* get the status line mode */
|
|
int os_get_status();
|
|
|
|
/*
|
|
* Set the score value. This displays the given score and turn counts on
|
|
* the status line. In most cases, these values are displayed at the right
|
|
* edge of the status line, in the format "score/turns", but the format is
|
|
* up to the implementation to determine. In most cases, this can simply
|
|
* be implemented as follows:
|
|
*
|
|
*. void os_score(int score, int turncount)
|
|
*. {
|
|
*. char buf[40];
|
|
*. Common::sprintf_s(buf, "%d/%d", score, turncount);
|
|
*. os_strsc(buf);
|
|
*. }
|
|
*/
|
|
void os_score(int score, int turncount);
|
|
|
|
/* display a string in the score area in the status line */
|
|
void os_strsc(const char *p);
|
|
|
|
/* clear the screen */
|
|
void oscls(void);
|
|
|
|
/* redraw the screen */
|
|
void os_redraw(void);
|
|
|
|
/* flush any buffered display output */
|
|
void os_flush(void);
|
|
|
|
/*
|
|
* Update the display - process any pending drawing immediately. This
|
|
* only needs to be implemented for operating systems that use
|
|
* event-driven drawing based on window invalidations; the Windows and
|
|
* Macintosh GUI's both use this method for drawing window contents.
|
|
*
|
|
* The purpose of this routine is to refresh the display prior to a
|
|
* potentially long-running computation, to avoid the appearance that the
|
|
* application is frozen during the computation delay.
|
|
*
|
|
* Platforms that don't need to process events in the main thread in order
|
|
* to draw their window contents do not need to do anything here. In
|
|
* particular, text-mode implementations generally don't need to implement
|
|
* this routine.
|
|
*
|
|
* This routine doesn't absolutely need a non-empty implementation on any
|
|
* platform, but it will provide better visual feedback if implemented for
|
|
* those platforms that do use event-driven drawing.
|
|
*/
|
|
void os_update_display();
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Set text attributes. Text subsequently displayed through os_print() and
|
|
* os_printz() are to be displayed with the given attributes.
|
|
*
|
|
* 'attr' is a (bitwise-OR'd) combination of OS_ATTR_xxx values. A value
|
|
* of zero indicates normal text, with no extra attributes.
|
|
*/
|
|
void os_set_text_attr(int attr);
|
|
|
|
/* attribute code: bold-face */
|
|
#define OS_ATTR_BOLD 0x0001
|
|
|
|
/* attribute code: italic */
|
|
#define OS_ATTR_ITALIC 0x0002
|
|
|
|
/*
|
|
* Abstract attribute codes. Each platform can choose a custom rendering
|
|
* for these by #defining them before this point, in the OS-specific header
|
|
* (osdos.h, osmac.h, etc). We provide *default* definitions in case the
|
|
* platform doesn't define these.
|
|
*
|
|
* For compatibility with past versions, we treat HILITE, EM, and BOLD as
|
|
* equivalent. Platforms that can display multiple kinds of text
|
|
* attributes (boldface and italic, say) should feel free to use more
|
|
* conventional HTML mappings, such as EM->italic and STRONG->bold.
|
|
*/
|
|
|
|
/*
|
|
* "Highlighted" text, as appropriate to the local platform. On most
|
|
* text-mode platforms, the only kind of rendering variation possible is a
|
|
* brighter or intensified color. If actual bold-face is available, that
|
|
* can be used instead. This is the attribute used for text enclosed in a
|
|
* TADS2 "\( \)" sequence.
|
|
*/
|
|
#ifndef OS_ATTR_HILITE
|
|
# define OS_ATTR_HILITE OS_ATTR_BOLD
|
|
#endif
|
|
|
|
/* HTML <em> attribute - by default, map this to bold-face */
|
|
#ifndef OS_ATTR_EM
|
|
# define OS_ATTR_EM OS_ATTR_BOLD
|
|
#endif
|
|
|
|
/* HTML <strong> attribute - by default, this has no effect */
|
|
#ifndef OS_ATTR_STRONG
|
|
# define OS_ATTR_STRONG 0
|
|
#endif
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Colors.
|
|
*
|
|
* There are two ways of encoding a color. First, a specific color can be
|
|
* specified as an RGB (red-green-blue) value, with discreet levels for
|
|
* each component's intensity, ranging from 0 to 255. Second, a color can
|
|
* be "parameterized," which doesn't specify a color in absolute terms but
|
|
* rather specified one of a number of pre-defined *types* of colors;
|
|
* these pre-defined types can be chosen by the OS implementation, or, on
|
|
* some systems, selected by the user via a preferences mechanism.
|
|
*
|
|
* The os_color_t type encodes a color in 32 bits. The high-order 8 bits
|
|
* of a color value give the parameterized color identifier, or are set to
|
|
* zero to indicate an RGB color. An RGB color is encoded in the
|
|
* low-order 24 bits, via the following formula:
|
|
*
|
|
* (R << 16) + (G << 8) + B
|
|
*
|
|
* R specifies the intensity of the red component of the color, G green,
|
|
* and B blue. Each of R, G, and B must be in the range 0-255.
|
|
*/
|
|
typedef unsigned long os_color_t;
|
|
|
|
/* encode an R, G, B triplet into an os_color_t value */
|
|
#define os_rgb_color(r, g, b) (((r) << 16) + ((g) << 8) + (b))
|
|
|
|
/*
|
|
* Determine if a color is given as an RGB value or as a parameterized
|
|
* color value. Returns true if the color is given as a parameterized
|
|
* color (one of the OS_COLOR_xxx values), false if it's given as an
|
|
* absolute RGB value.
|
|
*/
|
|
#define os_color_is_param(color) (((color) & 0xFF000000) != 0)
|
|
|
|
/* get the red/green/blue components of an os_color_t value */
|
|
#define os_color_get_r(color) ((int)(((color) >> 16) & 0xFF))
|
|
#define os_color_get_g(color) ((int)(((color) >> 8) & 0xFF))
|
|
#define os_color_get_b(color) ((int)((color) & 0xFF))
|
|
|
|
/*
|
|
* Parameterized color codes. These are os_color_t values that indicate
|
|
* colors by type, rather than by absolute RGB values.
|
|
*/
|
|
|
|
/*
|
|
* "transparent" - applicable to backgrounds only, this specifies that the
|
|
* current screen background color should be used
|
|
*/
|
|
#define OS_COLOR_P_TRANSPARENT ((os_color_t)0x01000000)
|
|
|
|
/* "normal text" color (as set via user preferences, if applicable) */
|
|
#define OS_COLOR_P_TEXT ((os_color_t)0x02000000)
|
|
|
|
/* normal text background color (from user preferences) */
|
|
#define OS_COLOR_P_TEXTBG ((os_color_t)0x03000000)
|
|
|
|
/* "status line" text color (as set via user preferences, if applicable) */
|
|
#define OS_COLOR_P_STATUSLINE ((os_color_t)0x04000000)
|
|
|
|
/* status line background color (from user preferences) */
|
|
#define OS_COLOR_P_STATUSBG ((os_color_t)0x05000000)
|
|
|
|
/* input text color (as set via user preferences, if applicable) */
|
|
#define OS_COLOR_P_INPUT ((os_color_t)0x06000000)
|
|
|
|
/*
|
|
* Set the text foreground and background colors. This sets the text
|
|
* color for subsequent os_printf() and os_vprintf() calls.
|
|
*
|
|
* The background color can be OS_COLOR_TRANSPARENT, in which case the
|
|
* background color is "inherited" from the current screen background.
|
|
* Note that if the platform is capable of keeping old text for
|
|
* "scrollback," then the transparency should be a permanent attribute of
|
|
* the character - in other words, it should not be mapped to the current
|
|
* screen color in the scrollback buffer, because doing so would keep the
|
|
* current screen color even if the screen color changes in the future.
|
|
*
|
|
* Text color support is optional. If the platform doesn't support text
|
|
* colors, this can simply do nothing. If the platform supports text
|
|
* colors, but the requested color or attributes cannot be displayed, the
|
|
* implementation should use the best available approximation.
|
|
*/
|
|
void os_set_text_color(os_color_t fg, os_color_t bg);
|
|
|
|
/*
|
|
* Set the screen background color. This sets the text color for the
|
|
* background of the screen. If possible, this should immediately redraw
|
|
* the main text area with this background color. The color is given as an
|
|
* OS_COLOR_xxx value.
|
|
*
|
|
* If the platform is capable of redisplaying the existing text, then any
|
|
* existing text that was originally displayed with 'transparent'
|
|
* background color should be redisplayed with the new screen background
|
|
* color. In other words, the 'transparent' background color of previously
|
|
* drawn text should be a permanent attribute of the character - the color
|
|
* should not be mapped on display to the then-current background color,
|
|
* because doing so would lose the transparency and thus retain the old
|
|
* screen color on a screen color change.
|
|
*/
|
|
void os_set_screen_color(os_color_t color);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* os_plain() - Use plain ascii mode for the display. If possible and
|
|
* necessary, turn off any text formatting effects, such as cursor
|
|
* positioning, highlighting, or coloring. If this routine is called,
|
|
* the terminal should be treated as a simple text stream; users might
|
|
* wish to use this mode for things like text-to-speech converters.
|
|
*
|
|
* Purely graphical implementations that cannot offer a textual mode
|
|
* (such as Mac OS or Windows) can ignore this setting.
|
|
*
|
|
* If this routine is to be called, it must be called BEFORE os_init().
|
|
* The implementation should set a flag so that os_init() will know to
|
|
* set up the terminal for plain text output.
|
|
*/
|
|
#ifndef os_plain
|
|
/*
|
|
* some platforms (e.g. Mac OS) define this to be a null macro, so don't
|
|
* define a prototype in those cases
|
|
*/
|
|
void os_plain(void);
|
|
#endif
|
|
|
|
/*
|
|
* Set the game title. The output layer calls this routine when a game
|
|
* sets its title (via an HTML <title> tag, for example). If it's
|
|
* convenient to do so, the OS layer can use this string to set a window
|
|
* caption, or whatever else makes sense on each system. Most
|
|
* character-mode implementations will provide an empty implementation,
|
|
* since there's not usually any standard way to show the current
|
|
* application title on a character-mode display.
|
|
*/
|
|
void os_set_title(const char *title);
|
|
|
|
/*
|
|
* Show the system-specific MORE prompt, and wait for the user to respond.
|
|
* Before returning, remove the MORE prompt from the screen.
|
|
*
|
|
* This routine is only used and only needs to be implemented when the OS
|
|
* layer takes responsibility for pagination; this will be the case on
|
|
* most systems that use proportionally-spaced (variable-pitch) fonts or
|
|
* variable-sized windows, since on such platforms the OS layer must do
|
|
* most of the formatting work, leaving the standard output layer unable
|
|
* to guess where pagination should occur.
|
|
*
|
|
* If the portable output formatter handles the MORE prompt, which is the
|
|
* usual case for character-mode or terminal-style implementations, this
|
|
* routine is not used and you don't need to provide an implementation.
|
|
* Note that HTML TADS provides an implementation of this routine, because
|
|
* the HTML renderer handles line breaking and thus must handle
|
|
* pagination.
|
|
*/
|
|
void os_more_prompt();
|
|
|
|
/*
|
|
* Interpreter Class Configuration.
|
|
*
|
|
* If this is a TEXT-ONLY interpreter: DO NOT define USE_HTML.
|
|
*
|
|
* If this is a MULTIMEDIA (HTML TADS) intepreter: #define USE_HTML
|
|
*
|
|
* (This really should be called something like OS_USE_HTML - the USE_ name
|
|
* is for historical reasons. This purpose of this macro is to configure
|
|
* the tads 2 VM-level output formatter's line breaking and MORE mode
|
|
* behavior. In HTML mode, the VM-level formatter knows that it's feeding
|
|
* its output to a page layout engine, so the VM-level output is just a
|
|
* text stream. In plain-text mode, the VM formatter *is* the page layout
|
|
* engine, so it needs to do all of the word wrapping and MORE prompting
|
|
* itself. The tads 3 output layer does NOT use this macro for its
|
|
* equivalent configuration, but instead has different .cpp files for the
|
|
* different modes, and you simply link in the one for the configuration
|
|
* you want.)
|
|
*/
|
|
/* #define USE_HTML */
|
|
|
|
|
|
/*
|
|
* Enter HTML mode. This is only used when the run-time is compiled
|
|
* with the USE_HTML flag defined. This call instructs the renderer
|
|
* that HTML sequences should be parsed; until this call is made, the
|
|
* renderer should not interpret output as HTML. Non-HTML
|
|
* implementations do not need to define this routine, since the
|
|
* run-time will not call it if USE_HTML is not defined.
|
|
*/
|
|
void os_start_html(void);
|
|
|
|
/* exit HTML mode */
|
|
void os_end_html(void);
|
|
|
|
/*
|
|
* Global variables with the height and width (in character cells - rows
|
|
* and columns) of the main text display area into which os_printf
|
|
* displays. The height and width are given in text lines and character
|
|
* columns, respectively. The portable code can use these values to
|
|
* format text for display via os_printf(); for example, the caller can
|
|
* use the width to determine where to put line breaks.
|
|
*
|
|
* These values are only needed for systems where os_printf() doesn't
|
|
* perform its own word-wrap formatting. On systems such as the Mac,
|
|
* where os_printf() performs word wrapping, these sizes aren't really
|
|
* important because the portable code doesn't need to perform any real
|
|
* formatting.
|
|
*
|
|
* These variables reflect the size of the "main text area," which is the
|
|
* area of the screen excluding the status line and any "banner" windows
|
|
* (as created with the os_banner_xxx() interfaces).
|
|
*
|
|
* The OS code must initialize these variables during start-up, and must
|
|
* adjust them whenever the display size is changed by user action or
|
|
* other external events (for example, if we're running inside a terminal
|
|
* window, and the user resizes the window, the OS code must recalculate
|
|
* the layout and adjust these accordingly).
|
|
*/
|
|
extern int G_os_pagelength;
|
|
extern int G_os_linewidth;
|
|
|
|
/*
|
|
* Global flag that tells the output formatter whether to count lines
|
|
* that it's displaying against the total on the screen so far. If this
|
|
* variable is true, lines are counted, and the screen is paused with a
|
|
* [More] message when it's full. When not in MORE mode, lines aren't
|
|
* counted. This variable should be set to false when displaying text
|
|
* that doesn't count against the current page, such as status line
|
|
* information.
|
|
*
|
|
* This flag should not be modified by OS code. Instead, the output
|
|
* formatter will set this flag according to its current state; the OS
|
|
* code can use this flag to determine whether or not to display a MORE
|
|
* prompt during os_printf()-type operations. Note that this flag is
|
|
* normally interesting to the OS code only when the OS code itself is
|
|
* handling the MORE prompt.
|
|
*/
|
|
extern int G_os_moremode;
|
|
|
|
/*
|
|
* Global buffer containing the name of the byte-code file (the "game
|
|
* file") loaded into the VM. This is used only where applicable, which
|
|
* generally means in TADS Interpreter builds. In other application
|
|
* builds, this is simply left empty. The application is responsible for
|
|
* setting this during start-up (or wherever else the byte-code filename
|
|
* becomes known or changes).
|
|
*/
|
|
extern char G_os_gamename[OSFNMAX];
|
|
|
|
/*
|
|
* Set non-stop mode. This tells the OS layer that it should disable any
|
|
* MORE prompting it would normally do.
|
|
*
|
|
* This routine is needed only when the OS layer handles MORE prompting; on
|
|
* character-mode platforms, where the prompting is handled in the portable
|
|
* console layer, this can be a dummy implementation.
|
|
*/
|
|
void os_nonstop_mode(int flag);
|
|
|
|
/*
|
|
* Update progress display with current info, if appropriate. This can
|
|
* be used to provide a status display during compilation. Most
|
|
* command-line implementations will just ignore this notification; this
|
|
* can be used for GUI compiler implementations to provide regular
|
|
* display updates during compilation to show the progress so far.
|
|
*/
|
|
/* void os_progress(const char *fname, unsigned long linenum); */
|
|
|
|
/*
|
|
* Set busy cursor. If 'flag' is true, provide a visual representation
|
|
* that the system or application is busy doing work. If 'flag' is
|
|
* false, remove any visual "busy" indication and show normal status.
|
|
*
|
|
* We provide a prototype here if your osxxx.h header file does not
|
|
* #define a macro for os_csr_busy. On many systems, this function has
|
|
* no effect at all, so the osxxx.h header file simply #define's it to
|
|
* do an empty macro.
|
|
*/
|
|
#ifndef os_csr_busy
|
|
void os_csr_busy(int flag);
|
|
#endif
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* User Input Routines
|
|
*/
|
|
|
|
/*
|
|
* Ask the user for a filename, using a system-dependent dialog or other
|
|
* mechanism. Returns one of the OS_AFE_xxx status codes (see below).
|
|
*
|
|
* prompt_type is the type of prompt to provide -- this is one of the
|
|
* OS_AFP_xxx codes (see below). The OS implementation doesn't need to
|
|
* pay any attention to this parameter, but it can be used if desired to
|
|
* determine the type of dialog to present if the system provides
|
|
* different types of dialogs for different types of operations.
|
|
*
|
|
* file_type is one of the OSFTxxx codes for system file type. The OS
|
|
* implementation is free to ignore this information, but can use it to
|
|
* filter the list of files displayed if desired; this can also be used
|
|
* to apply a default suffix on systems that use suffixes to indicate
|
|
* file type. If OSFTUNK is specified, it means that no filtering
|
|
* should be performed, and no default suffix should be applied.
|
|
*/
|
|
int os_askfile(const char *prompt, char *fname_buf, int fname_buf_len,
|
|
int prompt_type, os_filetype_t file_type);
|
|
|
|
/*
|
|
* os_askfile status codes
|
|
*/
|
|
|
|
/* success */
|
|
#define OS_AFE_SUCCESS 0
|
|
|
|
/*
|
|
* Generic failure - this is largely provided for compatibility with
|
|
* past versions, in which only zero and non-zero error codes were
|
|
* meaningful; since TRUE is defined as 1 on most platforms, we assume
|
|
* that 1 is probably the generic non-zero error code that most OS
|
|
* implementations have traditionally used. In addition, this can be
|
|
* used to indicate any other error for which there is no more specific
|
|
* error code.
|
|
*/
|
|
#define OS_AFE_FAILURE 1
|
|
|
|
/* user cancelled */
|
|
#define OS_AFE_CANCEL 2
|
|
|
|
/*
|
|
* os_askfile prompt types
|
|
*
|
|
* Important note: do not change these values when porting TADS. These
|
|
* values can be used by games, so they must be the same on all
|
|
* platforms.
|
|
*/
|
|
#define OS_AFP_OPEN 1 /* choose an existing file to open for reading */
|
|
#define OS_AFP_SAVE 2 /* choose a filename for saving to a file */
|
|
|
|
|
|
/*
|
|
* Read a string of input. Fills in the buffer with a null-terminated
|
|
* string containing a line of text read from the standard input. The
|
|
* returned string should NOT contain a trailing newline sequence. On
|
|
* success, returns 'buf'; on failure, including end of file, returns a
|
|
* null pointer.
|
|
*/
|
|
unsigned char *os_gets(unsigned char *buf, size_t bufl);
|
|
|
|
/*
|
|
* Read a string of input with an optional timeout. This behaves like
|
|
* os_gets(), in that it allows the user to edit a line of text (ideally
|
|
* using the same editing keys that os_gets() does), showing the line of
|
|
* text under construction during editing. This routine differs from
|
|
* os_gets() in that it returns if the given timeout interval expires
|
|
* before the user presses Return (or the local equivalent).
|
|
*
|
|
* If the user presses Return before the timeout expires, we store the
|
|
* command line in the given buffer, just as os_gets() would, and we return
|
|
* OS_EVT_LINE. We also update the display in the same manner that
|
|
* os_gets() would, by moving the cursor to a new line and scrolling the
|
|
* displayed text as needed.
|
|
*
|
|
* If a timeout occurs before the user presses Return, we store the command
|
|
* line so far in the given buffer, statically store the cursor position,
|
|
* insert mode, buffer text, and anything else relevant to the editing
|
|
* state, and we return OS_EVT_TIMEOUT.
|
|
*
|
|
* If the implementation does not support the timeout operation, this
|
|
* routine should simply return OS_EVT_NOTIMEOUT immediately when called;
|
|
* the routine should not allow the user to perform any editing if the
|
|
* timeout is not supported. Callers must use the ordinary os_gets()
|
|
* routine, which has no timeout capabilities, if the timeout is not
|
|
* supported.
|
|
*
|
|
* When we return OS_EVT_TIMEOUT, the caller is responsible for doing one
|
|
* of two things.
|
|
*
|
|
* The first possibility is that the caller performs some work that doesn't
|
|
* require any display operations (in other words, the caller doesn't
|
|
* invoke os_printf, os_getc, or anything else that would update the
|
|
* display), and then calls os_gets_timeout() again. In this case, we will
|
|
* use the editing state that we statically stored before we returned
|
|
* OS_EVT_TIMEOUT to continue editing where we left off. This allows the
|
|
* caller to perform some computation in the middle of user command editing
|
|
* without interrupting the user - the extra computation is transparent to
|
|
* the user, because we act as though we were still in the midst of the
|
|
* original editing.
|
|
*
|
|
* The second possibility is that the caller wants to update the display.
|
|
* In this case, the caller must call os_gets_cancel() BEFORE making any
|
|
* display changes. Then, the caller must do any post-input work of its
|
|
* own, such as updating the display mode (for example, closing HTML font
|
|
* tags that were opened at the start of the input). The caller is now
|
|
* free to do any display work it wants.
|
|
*
|
|
* If we have information stored from a previous call that was interrupted
|
|
* by a timeout, and os_gets_cancel(TRUE) was never called, we will resume
|
|
* editing where we left off when the cancelled call returned; this means
|
|
* that we'll restore the cursor position, insertion state, and anything
|
|
* else relevant. Note that if os_gets_cancel(FALSE) was called, we must
|
|
* re-display the command line under construction, but if os_gets_cancel()
|
|
* was never called, we will not have to make any changes to the display at
|
|
* all.
|
|
*
|
|
* Note that when resuming an interrupted editing session (interrupted via
|
|
* os_gets_cancel()), the caller must re-display the prompt prior to
|
|
* invoking this routine.
|
|
*
|
|
* Note that we can return OS_EVT_EOF in addition to the other codes
|
|
* mentioned above. OS_EVT_EOF indicates that an error occurred reading,
|
|
* which usually indicates that the application is being terminated or that
|
|
* some hardware error occurred reading the keyboard.
|
|
*
|
|
* If 'use_timeout' is false, the timeout should be ignored. Without a
|
|
* timeout, the function behaves the same as os_gets(), except that it will
|
|
* resume editing of a previously-interrupted command line if appropriate.
|
|
* (This difference is why the timeout is optional: a caller might not need
|
|
* a timeout, but might still want to resume a previous input that did time
|
|
* out, in which case the caller would invoke this routine with
|
|
* use_timeout==FALSE. The regular os_gets() would not satisfy this need,
|
|
* because it cannot resume an interrupted input.)
|
|
*
|
|
* Note that a zero timeout has the same meaning as for os_get_event(): if
|
|
* input is available IMMEDIATELY, return the input, otherwise return
|
|
* immediately with the OS_EVT_TIMEOUT result code.
|
|
*/
|
|
int os_gets_timeout(unsigned char *buf, size_t bufl,
|
|
unsigned long timeout_in_milliseconds, int use_timeout);
|
|
|
|
/*
|
|
* Cancel an interrupted editing session. This MUST be called if any
|
|
* output is to be displayed after a call to os_gets_timeout() returns
|
|
* OS_EVT_TIMEOUT.
|
|
*
|
|
* 'reset' indicates whether or not we will forget the input state saved
|
|
* by os_gets_timeout() when it last returned. If 'reset' is true, we'll
|
|
* clear the input state, so that the next call to os_gets_timeout() will
|
|
* start with an empty input buffer. If 'reset' is false, we will retain
|
|
* the previous input state, if any; this means that the next call to
|
|
* os_gets_timeout() will re-display the same input buffer that was under
|
|
* construction when it last returned.
|
|
*
|
|
* This routine need not be called if os_gets_timeout() is to be called
|
|
* again with no other output operations between the previous
|
|
* os_gets_timeout() call and the next one.
|
|
*
|
|
* Note that this routine needs only a trivial implementation when
|
|
* os_gets_timeout() is not supported (i.e., the function always returns
|
|
* OS_EVT_NOTIMEOUT).
|
|
*/
|
|
void os_gets_cancel(int reset);
|
|
|
|
/*
|
|
* Read a character from the keyboard. For extended keystrokes, this
|
|
* function returns zero, and then returns the CMD_xxx code for the
|
|
* extended keystroke on the next call. For example, if the user presses
|
|
* the up-arrow key, the first call to os_getc() should return 0, and the
|
|
* next call should return CMD_UP. Refer to the CMD_xxx codes below.
|
|
*
|
|
* os_getc() should return a high-level, translated command code for
|
|
* command editing. This means that, where a functional interpretation of
|
|
* a key and the raw key-cap interpretation both exist as CMD_xxx codes,
|
|
* the functional interpretation should be returned. For example, on Unix,
|
|
* Ctrl-E is conventionally used in command editing to move to the end of
|
|
* the line, following Emacs key bindings. Hence, os_getc() should return
|
|
* CMD_END for this keystroke, rather than a single 0x05 character (ASCII
|
|
* Ctrl-E), because CMD_END is the high-level command code for the
|
|
* operation.
|
|
*
|
|
* The translation ability of this function allows for system-dependent key
|
|
* mappings to functional meanings.
|
|
*/
|
|
int os_getc(void);
|
|
|
|
/*
|
|
* Read a character from the keyboard, following the same protocol as
|
|
* os_getc() for CMD_xxx codes (i.e., when an extended keystroke is
|
|
* encountered, os_getc_raw() returns zero, then returns the CMD_xxx code
|
|
* on the subsequent call).
|
|
*
|
|
* This function differs from os_getc() in that this function returns the
|
|
* low-level, untranslated key code whenever possible. This means that,
|
|
* when a functional interpretation of a key and the raw key-cap
|
|
* interpretation both exist as CMD_xxx codes, this function returns the
|
|
* key-cap interpretation. For the Unix Ctrl-E example in the comments
|
|
* describing os_getc() above, this function should return 5 (the ASCII
|
|
* code for Ctrl-E), because the ASCII control character interpretation is
|
|
* the low-level key code.
|
|
*
|
|
* This function should return all control keys using their ASCII control
|
|
* codes, whenever possible. Similarly, this function should return ASCII
|
|
* 27 for the Escape key, if possible.
|
|
*
|
|
* For keys for which there is no portable ASCII representation, this
|
|
* should return the CMD_xxx sequence. So, this function acts exactly the
|
|
* same as os_getc() for arrow keys, function keys, and other special keys
|
|
* that have no ASCII representation. This function returns a
|
|
* non-translated version ONLY when an ASCII representation exists - in
|
|
* practice, this means that this function and os_getc() vary only for CTRL
|
|
* keys and Escape.
|
|
*/
|
|
int os_getc_raw(void);
|
|
|
|
|
|
/* wait for a character to become available from the keyboard */
|
|
void os_waitc(void);
|
|
|
|
/*
|
|
* Constants for os_getc() when returning commands. When used for
|
|
* command line editing, special keys (arrows, END, etc.) should cause
|
|
* os_getc() to return 0, and return the appropriate CMD_ value on the
|
|
* NEXT call. Hence, os_getc() must keep the appropriate information
|
|
* around statically for the next call when a command key is issued.
|
|
*
|
|
* The comments indicate which CMD_xxx codes are "translated" codes and
|
|
* which are "raw"; the difference is that, when a particular keystroke
|
|
* could be interpreted as two different CMD_xxx codes, one translated
|
|
* and the other raw, os_getc() should always return the translated
|
|
* version of the key, and os_getc_raw() should return the raw version.
|
|
*/
|
|
#define CMD_UP 1 /* move up/up arrow (translated) */
|
|
#define CMD_DOWN 2 /* move down/down arrow (translated) */
|
|
#define CMD_RIGHT 3 /* move right/right arrow (translated) */
|
|
#define CMD_LEFT 4 /* move left/left arrow (translated) */
|
|
#define CMD_END 5 /* move cursor to end of line (translated) */
|
|
#define CMD_HOME 6 /* move cursor to start of line (translated) */
|
|
#define CMD_DEOL 7 /* delete to end of line (translated) */
|
|
#define CMD_KILL 8 /* delete entire line (translated) */
|
|
#define CMD_DEL 9 /* delete current character (translated) */
|
|
#define CMD_SCR 10 /* toggle scrollback mode (translated) */
|
|
#define CMD_PGUP 11 /* page up (translated) */
|
|
#define CMD_PGDN 12 /* page down (translated) */
|
|
#define CMD_TOP 13 /* top of file (translated) */
|
|
#define CMD_BOT 14 /* bottom of file (translated) */
|
|
#define CMD_F1 15 /* function key F1 (raw) */
|
|
#define CMD_F2 16 /* function key F2 (raw) */
|
|
#define CMD_F3 17 /* function key F3 (raw) */
|
|
#define CMD_F4 18 /* function key F4 (raw) */
|
|
#define CMD_F5 19 /* function key F5 (raw) */
|
|
#define CMD_F6 20 /* function key F6 (raw) */
|
|
#define CMD_F7 21 /* function key F7 (raw) */
|
|
#define CMD_F8 22 /* function key F8 (raw) */
|
|
#define CMD_F9 23 /* function key F9 (raw) */
|
|
#define CMD_F10 24 /* function key F10 (raw) */
|
|
#define CMD_CHOME 25 /* control-home (raw) */
|
|
#define CMD_TAB 26 /* tab (translated) */
|
|
#define CMD_SF2 27 /* shift-F2 (raw) */
|
|
/* not used (obsolete) - 28 */
|
|
#define CMD_WORD_LEFT 29 /* word left (ctrl-left on dos) (translated) */
|
|
#define CMD_WORD_RIGHT 30 /* word right (ctrl-right on dos) (translated) */
|
|
#define CMD_WORDKILL 31 /* delete word right (translated) */
|
|
#define CMD_EOF 32 /* end-of-file (raw) */
|
|
#define CMD_BREAK 33 /* break (Ctrl-C or local equivalent) (translated) */
|
|
#define CMD_INS 34 /* insert key (raw) */
|
|
|
|
|
|
/*
|
|
* ALT-keys - add alphabetical code to CMD_ALT: ALT-A == CMD_ALT + 0,
|
|
* ALT-B == CMD_ALT + 1, ALT-C == CMD_ALT + 2, etc
|
|
*
|
|
* These keys are all raw (untranslated).
|
|
*/
|
|
#define CMD_ALT 128 /* start of ALT keys */
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Event information structure for os_get_event. The appropriate union
|
|
* member should be filled in, depending on the type of event that
|
|
* occurs.
|
|
*/
|
|
union os_event_info_t
|
|
{
|
|
/*
|
|
* OS_EVT_KEY - this returns the one or two characters of the
|
|
* keystroke. If the key is an extended key, so that os_getc() would
|
|
* return a two-character sequence for the keystroke, the first
|
|
* character should be zero and the second the extended key code.
|
|
* Otherwise, the first character should simply be the ASCII key code.
|
|
*
|
|
* The key code here is the "raw" keycode, equivalent to the codes
|
|
* returned by os_getc_raw(). Note in particular that this means that
|
|
* CTRL and Escape keys are presented as one-byte ASCII control
|
|
* characters, not as two-byte CMD_xxx sequences.
|
|
*
|
|
* For multi-byte character sets (Shift-JIS, for example), note that
|
|
* os_get_event() must NOT return a complete two-byte character here.
|
|
* The two bytes here are exclusively used to represent special
|
|
* CMD_xxx keys (such as arrow keys and function keys). For a
|
|
* keystroke that is represented in a multi-byte character set using
|
|
* more than one byte, os_get_event() must return a series of events.
|
|
* Return an ordinary OS_EVT_KEY for the first byte of the sequence,
|
|
* putting the byte in key[0]; then, return the second byte as a
|
|
* separate OS_EVT_KEY as the next event; and so on for any additional
|
|
* bytes. This will allow callers that are not multibyte-aware to
|
|
* treat multi-byte characters as though they were sequences of
|
|
* one-byte characters.
|
|
*/
|
|
int key[2];
|
|
|
|
/*
|
|
* OS_EVT_HREF - this returns the text of the HREF as a
|
|
* null-terminated string.
|
|
*/
|
|
char href[256];
|
|
|
|
/* command ID (for OS_EVT_COMMAND) */
|
|
int cmd_id;
|
|
};
|
|
typedef union os_event_info_t os_event_info_t;
|
|
|
|
/*
|
|
* Event types for os_get_event
|
|
*/
|
|
|
|
/* invalid/no event */
|
|
#define OS_EVT_NONE 0x0000
|
|
|
|
/* OS_EVT_KEY - user typed a key on the keyboard */
|
|
#define OS_EVT_KEY 0x0001
|
|
|
|
/* OS_EVT_TIMEOUT - no event occurred before the timeout elapsed */
|
|
#define OS_EVT_TIMEOUT 0x0002
|
|
|
|
/*
|
|
* OS_EVT_HREF - user clicked on a <A HREF> link. This only applies to
|
|
* the HTML-enabled run-time.
|
|
*/
|
|
#define OS_EVT_HREF 0x0003
|
|
|
|
/*
|
|
* OS_EVT_NOTIMEOUT - caller requested a timeout, but timeout is not
|
|
* supported by this version of the run-time
|
|
*/
|
|
#define OS_EVT_NOTIMEOUT 0x0004
|
|
|
|
/*
|
|
* OS_EVT_EOF - an error occurred reading the event. This generally
|
|
* means that the application is quitting or we can no longer read from
|
|
* the keyboard or terminal.
|
|
*/
|
|
#define OS_EVT_EOF 0x0005
|
|
|
|
/*
|
|
* OS_EVT_LINE - user entered a line of text on the keyboard. This event
|
|
* is not returned from os_get_event(), but rather from os_gets_timeout().
|
|
*/
|
|
#define OS_EVT_LINE 0x0006
|
|
|
|
|
|
/*
|
|
* Get an input event. The event types are shown above. If use_timeout is
|
|
* false, this routine should simply wait until one of the events it
|
|
* recognizes occurs, then return the appropriate information on the event.
|
|
* If use_timeout is true, this routine should return OS_EVT_TIMEOUT after
|
|
* the given number of milliseconds elapses if no event occurs first.
|
|
*
|
|
* This function is not obligated to obey the timeout. If a timeout is
|
|
* specified and it is not possible to obey the timeout, the function
|
|
* should simply return OS_EVT_NOTIMEOUT. The trivial implementation thus
|
|
* checks for a timeout, returns an error if specified, and otherwise
|
|
* simply waits for the user to press a key.
|
|
*
|
|
* A timeout value of 0 does *not* mean that there's no timeout (i.e., it
|
|
* doesn't mean we should wait indefinitely) - that's specified by passing
|
|
* FALSE for use_timeout. A zero timeout also doesn't meant that the
|
|
* function should unconditionally return OS_EVT_TIMEOUT. Instead, a zero
|
|
* timeout specifically means that IF an event is available IMMEDIATELY,
|
|
* without blocking the thread, we should return that event; otherwise we
|
|
* should immediately return a timeout event.
|
|
*/
|
|
int os_get_event(unsigned long timeout_in_milliseconds, int use_timeout,
|
|
os_event_info_t *info);
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Extended os_get_event() codes.
|
|
*
|
|
* THESE ARE NOT USED in the basic osifc implementation - these are only
|
|
* used if the interpreter supports the "extended" interface defined in
|
|
* osifcext.h.
|
|
*/
|
|
|
|
/*
|
|
* System menu command event. Some interpreters (such as HTML TADS for
|
|
* Windows) provide menu commands for common system-level game verbs -
|
|
* SAVE, RESTORE, UNDO, QUIT. By default, these commands are returned as
|
|
* literal command strings ("save", "restore", etc) via os_gets(), as
|
|
* though the user had typed the commands at the keyboard. The extended OS
|
|
* interface allows the program to receive these commands via
|
|
* os_get_event(). When a command is enabled for os_get_event() via the
|
|
* extended OS interface, and the player selects the command via a menu (or
|
|
* toolbar button, etc) during a call to os_get_event(), os_get_event()
|
|
* returns this event code, with the menu ID stored in the cmd_id field of
|
|
* the event structure.
|
|
*/
|
|
#define OS_EVT_COMMAND 0x0100
|
|
|
|
/* command IDs for OS_EVT_COMMAND */
|
|
#define OS_CMD_NONE 0x0000 /* invalid command ID, for internal use */
|
|
#define OS_CMD_SAVE 0x0001 /* save game */
|
|
#define OS_CMD_RESTORE 0x0002 /* restore game */
|
|
#define OS_CMD_UNDO 0x0003 /* undo last turn */
|
|
#define OS_CMD_QUIT 0x0004 /* quit game */
|
|
#define OS_CMD_CLOSE 0x0005 /* close the game window */
|
|
#define OS_CMD_HELP 0x0006 /* show game help */
|
|
|
|
/* highest command ID used in this version of the interface */
|
|
#define OS_CMD_LAST 0x0006
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Ask for input through a dialog.
|
|
*
|
|
* 'prompt' is a text string to display as a prompting message. For
|
|
* graphical systems, this message should be displayed in the dialog;
|
|
* for text systems, this should be displayed on the terminal after a
|
|
* newline.
|
|
*
|
|
* 'standard_button_set' is one of the OS_INDLG_xxx values defined
|
|
* below, or zero. If this value is zero, no standard button set is to
|
|
* be used; the custom set of buttons defined in 'buttons' is to be used
|
|
* instead. If this value is non-zero, the appropriate set of standard
|
|
* buttons, with labels translated to the local language if possible, is
|
|
* to be used.
|
|
*
|
|
* 'buttons' is an array of strings to use as button labels.
|
|
* 'button_count' gives the number of entries in the 'buttons' array.
|
|
* 'buttons' and 'button_count' are ignored if 'standard_button_set' is
|
|
* non-zero, since a standard set of buttons is used instead. If
|
|
* 'buttons' and 'button_count' are to be used, each entry contains the
|
|
* label of a button to show.
|
|
*/
|
|
/*
|
|
* An ampersand ('&') character in a label string indicates that the
|
|
* next character after the '&' is to be used as the short-cut key for
|
|
* the button, if supported. The '&' should NOT be displayed in the
|
|
* string; instead, the character should be highlighted according to
|
|
* local system conventions. On Windows, for example, the short-cut
|
|
* character should be shown underlined; on a text display, the response
|
|
* might be shown with the short-cut character enclosed in parentheses.
|
|
* If there is no local convention for displaying a short-cut character,
|
|
* then the '&' should simply be removed from the displayed text.
|
|
*
|
|
* The short-cut key specified by each '&' character should be used in
|
|
* processing responses. If the user presses the key corresponding to a
|
|
* button's short-cut, the effect should be the same as if the user
|
|
* clicked the button with the mouse. If local system conventions don't
|
|
* allow for short-cut keys, any short-cut keys can be ignored.
|
|
*
|
|
* 'default_index' is the 1-based index of the button to use as the
|
|
* default. If this value is zero, there is no default response. If
|
|
* the user performs the appropriate system-specific action to select
|
|
* the default response for the dialog, this is the response that is to
|
|
* be selected. On Windows, for example, pressing the "Return" key
|
|
* should select this item.
|
|
*
|
|
* 'cancel_index' is the 1-based index of the button to use as the
|
|
* cancel response. If this value is zero, there is no cancel response.
|
|
* This is the response to be used if the user cancels the dialog using
|
|
* the appropriate system-specific action. On Windows, for example,
|
|
* pressing the "Escape" key should select this item.
|
|
*/
|
|
/*
|
|
* icon_id is one of the OS_INDLG_ICON_xxx values defined below. If
|
|
* possible, an appropriate icon should be displayed in the dialog.
|
|
* This can be ignored in text mode, and also in GUI mode if there is no
|
|
* appropriate system icon.
|
|
*
|
|
* The return value is the 1-based index of the response selected. If
|
|
* an error occurs, return 0.
|
|
*/
|
|
int os_input_dialog(int icon_id, const char *prompt, int standard_button_set,
|
|
const char **buttons, int button_count,
|
|
int default_index, int cancel_index);
|
|
|
|
/*
|
|
* Standard button set ID's
|
|
*/
|
|
|
|
/* OK */
|
|
#define OS_INDLG_OK 1
|
|
|
|
/* OK, Cancel */
|
|
#define OS_INDLG_OKCANCEL 2
|
|
|
|
/* Yes, No */
|
|
#define OS_INDLG_YESNO 3
|
|
|
|
/* Yes, No, Cancel */
|
|
#define OS_INDLG_YESNOCANCEL 4
|
|
|
|
/*
|
|
* Dialog icons
|
|
*/
|
|
|
|
/* no icon */
|
|
#define OS_INDLG_ICON_NONE 0
|
|
|
|
/* warning */
|
|
#define OS_INDLG_ICON_WARNING 1
|
|
|
|
/* information */
|
|
#define OS_INDLG_ICON_INFO 2
|
|
|
|
/* question */
|
|
#define OS_INDLG_ICON_QUESTION 3
|
|
|
|
/* error */
|
|
#define OS_INDLG_ICON_ERROR 4
|
|
|
|
/*
|
|
* OBSOLETE - Get filename from startup parameter, if possible; returns
|
|
* true and fills in the buffer with the parameter filename on success,
|
|
* false if no parameter file could be found.
|
|
*
|
|
* (This was used until TADS 2.2.5 for the benefit of the Mac interpreter,
|
|
* and interpreters on systems with similar desktop shells, to allow the
|
|
* user to launch the terp by double-clicking on a saved game file. The
|
|
* terp would read the launch parameters, discover that a saved game had
|
|
* been used to invoke it, and would then stash away the saved game info
|
|
* for later retrieval from this function. This functionality was replaced
|
|
* in 2.2.5 with a command-line parameter: the terp now uses the desktop
|
|
* launch data to synthesize a suitable argv[] vectro to pass to os0main()
|
|
* or os0main2(). This function should now simply be stubbed out - it
|
|
* should simply return FALSE.)
|
|
*/
|
|
int os_paramfile(char *buf);
|
|
|
|
/*
|
|
* Initialize. This should be called during program startup to
|
|
* initialize the OS layer and check OS-specific command-line arguments.
|
|
*
|
|
* If 'prompt' and 'buf' are non-null, and there are no arguments on the
|
|
* given command line, the OS code can use the prompt to ask the user to
|
|
* supply a filename, then store the filename in 'buf' and set up
|
|
* argc/argv to give a one-argument command string. (This mechanism for
|
|
* prompting for a filename is obsolescent, and is retained for
|
|
* compatibility with a small number of existing implementations only;
|
|
* new implementations should ignore this mechanism and leave the
|
|
* argc/argv values unchanged.)
|
|
*/
|
|
int os_init(int *argc, char *argv[], const char *prompt,
|
|
char *buf, int bufsiz);
|
|
|
|
/*
|
|
* Termination functions. There are three main termination functions,
|
|
* described individually below; here's a brief overview of the
|
|
* relationship among the functions. The important thing to realize is
|
|
* that these functions have completely independent purposes; they should
|
|
* never call one another, and they should never do any of the work that's
|
|
* intended for the others.
|
|
*
|
|
* os_uninit() is meant to undo the effects of os_init(). On many
|
|
* systems, os_init() has some global effect, such as setting the terminal
|
|
* to some special input or output mode. os_uninit's purpose is to undo
|
|
* these global effects, returning the terminal mode (and whatever else)
|
|
* to the conditions they were in at program startup. Portable callers
|
|
* are meant to call this routine at some point before terminating if they
|
|
* ever called os_init(). Note that this routine DOES NOT terminate the
|
|
* program - it should simply undo anything that os_init() did and return,
|
|
* to let the caller do any additional termination work of its own.
|
|
*
|
|
* os_expause() optionally pauses before termination, to allow the user to
|
|
* acknowledge any text the program displays just before exiting. This
|
|
* doesn't have to do anything at all, but it's useful on systems where
|
|
* program termination will do something drastic like close the window:
|
|
* without a pause, the user wouldn't have a chance to read any text the
|
|
* program displayed after the last interactive input, because the window
|
|
* would abruptly disappear moments after the text was displayed. For
|
|
* systems where termination doesn't have such drastic effects, there's no
|
|
* need to do anything in this routine. Because it's up to this routine
|
|
* whether or not to pause, this routine must display a prompt if it's
|
|
* going to pause for user input - the portable caller obviously can't do
|
|
* so, because the caller doesn't know if the routine is going to pause or
|
|
* not (so if the caller displayed a prompt assuming the routine would
|
|
* pause, the prompt would show up even on systems where there actually is
|
|
* no pause, which would be confusing). This routine DOES NOT terminate
|
|
* the program; it simply pauses if necessary to allow the user to
|
|
* acknowledge the last bit of text the program displayed, then returns to
|
|
* allow the caller to carry on with its own termination work.
|
|
*
|
|
* os_term() is meant to perform the same function as the C standard
|
|
* library routine exit(): this actually terminates the program, exiting
|
|
* to the operating system. This routine is not meant to return to its
|
|
* caller, because it's supposed to exit the program directly. For many
|
|
* systems, this routine can simply call exit(); the portable code calls
|
|
* this routine instead of calling exit() directly, because some systems
|
|
* have their own OS-specific way of terminating rather than using exit().
|
|
* This routine MUST NOT undo the effects of os_init(), because callers
|
|
* might not have ever called os_init(); callers are required to call
|
|
* os_uninit() if they ever called os_init(), before calling os_term(), so
|
|
* this routine can simply assume that any global modes set by os_init()
|
|
* have already been undone by the time this is called.
|
|
*/
|
|
|
|
/*
|
|
* Uninitialize. This is called prior to progam termination to reverse
|
|
* the effect of any changes made in os_init(). For example, if
|
|
* os_init() put the terminal in raw mode, this should restore the
|
|
* previous terminal mode. This routine should not terminate the
|
|
* program (so don't call exit() here) - the caller might have more
|
|
* processing to perform after this routine returns.
|
|
*/
|
|
void os_uninit(void);
|
|
|
|
/*
|
|
* Pause prior to exit, if desired. This is meant to be called by
|
|
* portable code just before the program is to be terminated; it can be
|
|
* implemented to show a prompt and wait for user acknowledgment before
|
|
* proceeding. This is useful for implementations that are using
|
|
* something like a character-mode terminal window running on a graphical
|
|
* operating system: this gives the implementation a chance to pause
|
|
* before exiting, so that the window doesn't just disappear
|
|
* unceremoniously.
|
|
*
|
|
* This is allowed to do nothing at all. For regular character-mode
|
|
* systems, this routine usually doesn't do anything, because when the
|
|
* program exits, the terminal will simply return to the OS command
|
|
* prompt; none of the text displayed just before the program exited will
|
|
* be lost, so there's no need for any interactive pause. Likewise, for
|
|
* graphical systems where the window will remain open, even after the
|
|
* program exits, until the user explicitly closes the window, there's no
|
|
* need to do anything here.
|
|
*
|
|
* If this is implemented to pause, then this routine MUST show some kind
|
|
* of prompt to let the user know we're waiting. In the simple case of a
|
|
* text-mode terminal window on a graphical OS, this should simply print
|
|
* out some prompt text ("Press a key to exit...") and then wait for the
|
|
* user to acknowledge the prompt (by pressing a key, for example). For
|
|
* graphical systems, the prompt could be placed in the window's title
|
|
* bar, or status-bar, or wherever is appropriate for the OS.
|
|
*/
|
|
void os_expause(void);
|
|
|
|
/*
|
|
* Terminate. This should exit the program with the given exit status.
|
|
* In general, this should be equivalent to the standard C library
|
|
* exit() function, but we define this interface to allow the OS code to
|
|
* do any necessary pre-termination cleanup.
|
|
*/
|
|
void os_term(int status);
|
|
|
|
/*
|
|
* Install/uninstall the break handler. If possible, the OS code should
|
|
* set (if 'install' is true) or clear (if 'install' is false) a signal
|
|
* handler for keyboard break signals (control-C, etc, depending on
|
|
* local convention). The OS code should set its own handler routine,
|
|
* which should note that a break occurred with an internal flag; the
|
|
* portable code uses os_break() from time to time to poll this flag.
|
|
*/
|
|
void os_instbrk(int install);
|
|
|
|
/*
|
|
* Check for user break ("control-C", etc) - returns true if a break is
|
|
* pending, false if not. If this returns true, it should "consume" the
|
|
* pending break (probably by simply clearing the OS code's internal
|
|
* break-pending flag).
|
|
*/
|
|
bool os_break(void);
|
|
|
|
/*
|
|
* Sleep for a given interval. This should simply pause for the given
|
|
* number of milliseconds, then return. On multi-tasking systems, this
|
|
* should use a system API to suspend the current process for the desired
|
|
* delay; on single-tasking systems, this can simply sit in a wait loop
|
|
* until the desired interval has elapsed.
|
|
*/
|
|
void os_sleep_ms(long delay_in_milliseconds);
|
|
|
|
/*
|
|
* Yield CPU; returns TRUE if user requested an interrupt (a "control-C"
|
|
* type of operation to abort the entire program), FALSE to continue.
|
|
* Portable code should call this routine from time to time during lengthy
|
|
* computations that don't involve any UI operations; if practical, this
|
|
* routine should be invoked roughly every 10 to 100 milliseconds.
|
|
*
|
|
* The purpose of this routine is to support "cooperative multitasking"
|
|
* systems, such as pre-X MacOS, where it's necessary for each running
|
|
* program to call the operating system explicitly in order to yield the
|
|
* CPU from time to time to other concurrently running programs. On
|
|
* cooperative multitasking systems, a program can only lose control of
|
|
* the CPU by making specific system calls, usually related to GUI events;
|
|
* a program can never lose control of the CPU asynchronously. So, a
|
|
* program that performs lengthy computations without any UI interaction
|
|
* can cause the rest of the system to freeze up until the computations
|
|
* are finished; but if a compute-intensive program explicitly yields the
|
|
* CPU from time to time, it allows other programs to remain responsive.
|
|
* Yielding the CPU at least every 100 milliseconds or so will generally
|
|
* allow the UI to remain responsive; yielding more frequently than every
|
|
* 10 ms or so will probably start adding noticeable overhead.
|
|
*
|
|
* On single-tasking systems (such as MS-DOS), there's only one program
|
|
* running at a time, so there's no need to yield the CPU; on virtually
|
|
* every modern system, the OS automatically schedules CPU time without
|
|
* the running programs having any say in the matter, so again there's no
|
|
* need for a program to yield the CPU. For systems where this routine
|
|
* isn't needed, the system header should simply #define os_yield to
|
|
* something like "((void)0)" - this will allow the compiler to completely
|
|
* ignore calls to this routine for systems where they aren't needed.
|
|
*
|
|
* Note that this routine is NOT meant to provide scheduling hinting to
|
|
* modern systems with true multitasking, so a trivial implementation is
|
|
* fine for any modern system.
|
|
*/
|
|
#ifndef os_yield
|
|
int os_yield(void);
|
|
#endif
|
|
|
|
/*
|
|
* Set the default saved-game extension. This routine will NOT be called
|
|
* when we're using the standard saved game extension; this routine will be
|
|
* invoked only if we're running as a stand-alone game, and the game author
|
|
* specified a non-standard saved-game extension when creating the
|
|
* stand-alone game.
|
|
*
|
|
* This routine is not required if the system does not use the standard,
|
|
* semi-portable os0.c implementation. Even if the system uses the
|
|
* standard os0.c implementation, it can provide an empty routine here if
|
|
* the system code doesn't need to do anything special with this
|
|
* information.
|
|
*
|
|
* The extension is specified as a null-terminated string. The extension
|
|
* does NOT include the leading period.
|
|
*/
|
|
void os_set_save_ext(const char *ext);
|
|
|
|
/*
|
|
* Get the saved game extension previously set with os_set_save_ext().
|
|
* Returns null if no custom extension has been set.
|
|
*/
|
|
const char *os_get_save_ext();
|
|
|
|
|
|
/* ------------------------------------------------------------------------*/
|
|
/*
|
|
* Translate a character from the HTML 4 Unicode character set to the
|
|
* current character set used for display. Takes an HTML 4 character
|
|
* code and returns the appropriate local character code.
|
|
*
|
|
* The result buffer should be filled in with a null-terminated string
|
|
* that should be used to represent the character. Multi-character
|
|
* results are possible, which may be useful for certain approximations
|
|
* (such as using "(c)" for the copyright symbol).
|
|
*
|
|
* Note that we only define this prototype if this symbol isn't already
|
|
* defined as a macro, which may be the case on some platforms.
|
|
* Alternatively, if the function is already defined (for example, as an
|
|
* inline function), the defining code can define OS_XLAT_HTML4_DEFINED,
|
|
* in which case we'll also omit this prototype.
|
|
*
|
|
* Important: this routine provides the *default* mapping that is used
|
|
* when no external character mapping file is present, and for any named
|
|
* entities not defined in the mapping file. Any entities in the
|
|
* mapping file, if used, will override this routine.
|
|
*
|
|
* A trivial implementation of this routine (that simply returns a
|
|
* one-character result consisting of the original input character,
|
|
* truncated to eight bits if necessary) can be used if you want to
|
|
* require an external mapping file to be used for any game that
|
|
* includes HTML character entities. The DOS version implements this
|
|
* routine so that games will still look reasonable when played with no
|
|
* mapping file present, but other systems are not required to do this.
|
|
*/
|
|
#ifndef os_xlat_html4
|
|
# ifndef OS_XLAT_HTML4_DEFINED
|
|
void os_xlat_html4(unsigned int html4_char,
|
|
char *result, size_t result_buf_len);
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
* Generate a filename for a character-set mapping file. This function
|
|
* should determine the current native character set in use, if
|
|
* possible, then generate a filename, according to system-specific
|
|
* conventions, that we should attempt to load to get a mapping between
|
|
* the current native character set and the internal character set
|
|
* identified by 'internal_id'.
|
|
*
|
|
* The internal character set ID is a string of up to 4 characters.
|
|
*
|
|
* On DOS, the native character set is a DOS code page. DOS code pages
|
|
* are identified by 3- or 4-digit identifiers; for example, code page
|
|
* 437 is the default US ASCII DOS code page. We generate the
|
|
* character-set mapping filename by appending the internal character
|
|
* set identifier to the DOS code page number, then appending ".TCP" to
|
|
* the result. So, to map between ISO Latin-1 (internal ID = "La1") and
|
|
* DOS code page 437, we would generate the filename "437La1.TCP".
|
|
*
|
|
* Note that this function should do only two things. First, determine
|
|
* the current native character set that's in use. Second, generate a
|
|
* filename based on the current native code page and the internal ID.
|
|
* This function is NOT responsible for figuring out the mapping or
|
|
* anything like that -- it's simply where we generate the correct
|
|
* filename based on local convention.
|
|
*
|
|
* 'filename' is a buffer of at least OSFNMAX characters.
|
|
*
|
|
* 'argv0' is the executable filename from the original command line.
|
|
* This parameter is provided so that the system code can look for
|
|
* mapping files in the original TADS executables directory, if desired.
|
|
*/
|
|
void os_gen_charmap_filename(char *filename, char *internal_id, char *argv0);
|
|
|
|
/*
|
|
* Receive notification that a character mapping file has been loaded.
|
|
* The caller doesn't require this routine to do anything at all; this
|
|
* is purely for the system-dependent code's use so that it can take
|
|
* care of any initialization that it must do after the caller has
|
|
* loaded a charater mapping file. 'id' is the character set ID, and
|
|
* 'ldesc' is the display name of the character set. 'sysinfo' is the
|
|
* extra system information string that is stored in the mapping file;
|
|
* the interpretation of this information is up to this routine.
|
|
*
|
|
* For reference, the Windows version uses the extra information as a
|
|
* code page identifier, and chooses its default font character set to
|
|
* match the code page. On DOS, the run-time requires the player to
|
|
* activate an appropriate code page using a DOS command (MODE CON CP
|
|
* SELECT) prior to starting the run-time, so this routine doesn't do
|
|
* anything at all on DOS.
|
|
*/
|
|
void os_advise_load_charmap(const char *id, const char *ldesc, const char *sysinfo);
|
|
|
|
/*
|
|
* Generate the name of the character set mapping table for Unicode
|
|
* characters to and from the given local character set. Fills in the
|
|
* buffer with the implementation-dependent name of the desired
|
|
* character set map. See below for the character set ID codes.
|
|
*
|
|
* For example, on Windows, the implementation would obtain the
|
|
* appropriate active code page (which is simply a Windows character set
|
|
* identifier number) from the operating system, and build the name of
|
|
* the Unicode mapping file for that code page, such as "CP1252". On
|
|
* Macintosh, the implementation would look up the current script system
|
|
* and return the name of the Unicode mapping for that script system,
|
|
* such as "ROMAN" or "CENTEURO".
|
|
*
|
|
* If it is not possible to determine the specific character set that is
|
|
* in use, this function should return "asc7dflt" (ASCII 7-bit default)
|
|
* as the character set identifier on an ASCII system, or an appropriate
|
|
* base character set name on a non-ASCII system. "asc7dflt" is the
|
|
* generic character set mapping for plain ASCII characters.
|
|
*
|
|
* The given buffer must be at least 32 bytes long; the implementation
|
|
* must limit the result it stores to 32 bytes. (We use a fixed-size
|
|
* buffer in this interface for simplicity, and because there seems no
|
|
* need for greater flexibility in the interface; a character set name
|
|
* doesn't carry very much information so shouldn't need to be very
|
|
* long. Note that this function doesn't generate a filename, but
|
|
* simply a mapping name; in practice, a map name will be used to
|
|
* construct a mapping file name.)
|
|
*
|
|
* Because this function obtains the Unicode mapping name, there is no
|
|
* need to specify the internal character set to be used: the internal
|
|
* character set is Unicode.
|
|
*/
|
|
/*
|
|
* Implementation note: when porting this routine, the convention that
|
|
* you use to name your mapping files is up to you. You should simply
|
|
* choose a convention for this implementation, and then use the same
|
|
* convention for packaging the mapping files for your OS release. In
|
|
* most cases, the best convention is to use the names that the Unicode
|
|
* consortium uses in their published cross-mapping listings, since
|
|
* these listings can be used as the basis of the mapping files that you
|
|
* include with your release. For example, on Windows, the convention
|
|
* is to use the code page number to construct the map name, as in
|
|
* CP1252 or CP1250.
|
|
*/
|
|
void os_get_charmap(char *mapname, int charmap_id);
|
|
|
|
/*
|
|
* Character map for the display (i.e., for the user interface). This
|
|
* is the character set which is used for input read from the keyboard,
|
|
* and for output displayed on the monitor or terminal.
|
|
*/
|
|
#define OS_CHARMAP_DISPLAY 1
|
|
|
|
/*
|
|
* Character map for mapping filename strings. This should identify the
|
|
* character set currently in use on the local system for filenames
|
|
* (i.e., for strings identifying objects in the local file system),
|
|
* providing a suitable name for use in opening a mapping file.
|
|
*
|
|
* On many platforms, the entire system uses only one character set at
|
|
* the OS level, so the file system character set is the same as the
|
|
* display character set. Some systems define a particular character
|
|
* set for file system use, though, because different users might be
|
|
* running applications on terminals that display different character
|
|
* sets.
|
|
*/
|
|
#define OS_CHARMAP_FILENAME 2
|
|
|
|
/*
|
|
* Default character map for file contents. On most systems, this will
|
|
* be the same as display. On some systems, it won't be possible to
|
|
* know in general what character set files use; in fact, this isn't
|
|
* possible anywhere, since a file might have been copied without
|
|
* translation from a different type of computer using a different
|
|
* character set. So, this isn't meant to provide a reliable choice of
|
|
* character set for any arbitrary file; it's simply meant to be a good
|
|
* guess that most files on this system are likely to use.
|
|
*/
|
|
#define OS_CHARMAP_FILECONTENTS 3
|
|
|
|
/*
|
|
* Default character map for the command line. This is the maping we use
|
|
* to interpret command line arguments passed to our main() or equivalent.
|
|
* On most systems, this will be the same as the display character set.
|
|
*/
|
|
#define OS_CHARMAP_CMDLINE 4
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Get system information. 'code' is a SYSINFO_xxx code, which
|
|
* specifies what type of information to get. The 'param' argument's
|
|
* meaning depends on which code is selected. 'result' is a pointer to
|
|
* an integer that is to be filled in with the result value. If the
|
|
* code is not known, this function should return FALSE. If the code is
|
|
* known, the function should fill in *result and return TRUE.
|
|
*/
|
|
int os_get_sysinfo(int code, void *param, long *result);
|
|
|
|
/* determine if systemInfo is supported - os_get_sysinfo never gets this */
|
|
#define SYSINFO_SYSINFO 1
|
|
|
|
/* get interpreter version number - os_get_sysinfo never gets this */
|
|
#define SYSINFO_VERSION 2
|
|
|
|
/* get operating system name - os_get_sysinfo never gets this */
|
|
#define SYSINFO_OS_NAME 3
|
|
|
|
/*
|
|
* Can the system process HTML directives? returns 1 if so, 0 if not.
|
|
* Note that if this returns false, then all of the codes below from
|
|
* JPEG to LINKS are implicitly false as well, since TADS can only use
|
|
* images, sounds, and links through HTML.
|
|
*/
|
|
#define SYSINFO_HTML 4
|
|
|
|
/* can the system display JPEG's? 1 if yes, 0 if no */
|
|
#define SYSINFO_JPEG 5
|
|
|
|
/* can the system display PNG's? 1 if yes, 0 if no */
|
|
#define SYSINFO_PNG 6
|
|
|
|
/* can the system play WAV's? 1 if yes, 0 if no */
|
|
#define SYSINFO_WAV 7
|
|
|
|
/* can the system play MIDI's? 1 if yes, 0 if no */
|
|
#define SYSINFO_MIDI 8
|
|
|
|
/* can the system play MIDI and WAV's simultaneously? yes=1, no=0 */
|
|
#define SYSINFO_WAV_MIDI_OVL 9
|
|
|
|
/* can the system play multiple WAV's simultaneously? yes=1, no=0 */
|
|
#define SYSINFO_WAV_OVL 10
|
|
|
|
/*
|
|
* GENERAL NOTES ON PREFERENCE SETTINGS:
|
|
*
|
|
* Several of the selectors below refer to the preference settings. We're
|
|
* talking about user-settable options to control various aspects of the
|
|
* interpreter. The conventional GUI for this kind of thing is a dialog
|
|
* box reachable through a menu command named something like "Options" or
|
|
* "Preferences". A couple of general notes about these:
|
|
*
|
|
* 1. The entire existence of a preferences mechanism is optional -
|
|
* interpreter writers aren't required to implement anything along these
|
|
* lines. In some cases the local platforms might not have any suitable
|
|
* conventions for a preferences UI (e.g., character-mode console
|
|
* applications), and in other cases the terp developer might just want to
|
|
* omit a prefs mechanism because of the work involved to implement it, or
|
|
* to keep the UI simpler.
|
|
*
|
|
* 2. If a given SYSINFO_PREF_xxx selector refers to a preference item
|
|
* that's not implemented in the local interpreter, the terp should simply
|
|
* return a suitable default result. For example, if the interpreter
|
|
* doesn't have a preference item to allow the user to turn sounds off, the
|
|
* selector SYSINFO_PREF_SOUNDS should return 1 to indicate that the user
|
|
* has not in fact turned off sounds (because there's no way to do so).
|
|
*
|
|
* 3. The various SYSINFO_PREF_xxx selectors are purely queries - they're
|
|
* NOT a mechanism for enforcing the preferences. For example, if the
|
|
* interpreter provides a "Sounds On/Off" option, it's up to the terp to
|
|
* enforce it the Off setting by ignoring any sound playback requests. The
|
|
* game isn't under any obligation to query any of the preferences or to
|
|
* alter its behavior based on their settings - you should expect that the
|
|
* game will go on trying to play sounds even when "Sounds Off" is selected
|
|
* in the preferences. The purpose of these SYSINFO selectors is to let
|
|
* the game determine the current presentation status, but *only if it
|
|
* cares*. For example, the game might determine whether or not sounds are
|
|
* actually being heard just before playing a sound effect that's important
|
|
* to the progress of the game, so that it can provide a visual alternative
|
|
* if the effect won't be heard.
|
|
*/
|
|
|
|
/*
|
|
* Get image preference setting - 1 = images can be displayed, 0 = images
|
|
* are not being displayed because the user turned off images in the
|
|
* preferences. This is, of course, irrelevant if images can't be
|
|
* displayed at all.
|
|
*
|
|
* See the general notes on preferences queries above.
|
|
*/
|
|
#define SYSINFO_PREF_IMAGES 11
|
|
|
|
/*
|
|
* Get digitized sound effect (WAV) preference setting - 1 = sounds can be
|
|
* played, 0 = sounds are not being played because the user turned off
|
|
* sounds in the preferences.
|
|
*
|
|
* See the general notes on preferences queries above.
|
|
*/
|
|
#define SYSINFO_PREF_SOUNDS 12
|
|
|
|
/*
|
|
* Get music (MIDI) preference setting - 1 = music can be played, 0 = music
|
|
* is not being played because the user turned off music in the
|
|
* preferences.
|
|
*
|
|
* See the general notes on preferences queries above.
|
|
*/
|
|
#define SYSINFO_PREF_MUSIC 13
|
|
|
|
/*
|
|
* Get link display preference setting - 0 = links are not being displayed
|
|
* because the user set a preference item that suppresses all links (which
|
|
* doesn't actually hide them, but merely displays them and otherwise
|
|
* treats them as ordinary text). 1 = links are to be displayed normally.
|
|
* 2 = links can be displayed temporarily by the user by pressing a key or
|
|
* some similar action, but aren't being displayed at all times.
|
|
*
|
|
* See the general note on preferences queries above.
|
|
*/
|
|
#define SYSINFO_PREF_LINKS 14
|
|
|
|
/* can the system play MPEG sounds of any kind? */
|
|
#define SYSINFO_MPEG 15
|
|
|
|
/* can the system play MPEG audio 2.0 layer I/II/III sounds? */
|
|
#define SYSINFO_MPEG1 16
|
|
#define SYSINFO_MPEG2 17
|
|
#define SYSINFO_MPEG3 18
|
|
|
|
/*
|
|
* is the system *currently* in HTML mode? os_get_sysinfo never gets
|
|
* this code, since the portable output layer keeps track of this
|
|
*/
|
|
#define SYSINFO_HTML_MODE 19
|
|
|
|
/*
|
|
* Does the system allow following external URL links of the various
|
|
* types? These return true if the system is capable of following these
|
|
* types of hypertext links, false if not. Note that, if the system is
|
|
* capable of following these links, these should return true regardless
|
|
* of any current mode settings; in particular, these should not be
|
|
* sensitive to the current HTML mode or the current link display mode,
|
|
* since the question is not whether a link now displayed can be
|
|
* followed by the user, but rather whether the system has the
|
|
* capability to follow these types of links at all.
|
|
*/
|
|
#define SYSINFO_LINKS_HTTP 20
|
|
#define SYSINFO_LINKS_FTP 21
|
|
#define SYSINFO_LINKS_NEWS 22
|
|
#define SYSINFO_LINKS_MAILTO 23
|
|
#define SYSINFO_LINKS_TELNET 24
|
|
|
|
/* is PNG transparency supported? */
|
|
#define SYSINFO_PNG_TRANS 25
|
|
|
|
/* is PNG alpha blending supported? */
|
|
#define SYSINFO_PNG_ALPHA 26
|
|
|
|
/* is the Ogg Vorbis audio format supported? */
|
|
#define SYSINFO_OGG 27
|
|
|
|
/* can the system display MNG's? */
|
|
#define SYSINFO_MNG 28
|
|
|
|
/* can the system display MNG's with transparency? */
|
|
#define SYSINFO_MNG_TRANS 29
|
|
|
|
/* can the system display MNG's with alpha blending? */
|
|
#define SYSINFO_MNG_ALPHA 30
|
|
|
|
/* can we display highlighted text in its own appearance? */
|
|
#define SYSINFO_TEXT_HILITE 31
|
|
|
|
/*
|
|
* Can we display text colors? This returns a SYSINFO_TXC_xxx code
|
|
* indicating the level of color support.
|
|
*
|
|
* The os_xxx interfaces don't presently support anything beyond the ANSI
|
|
* colors; however, HTML-enabled interpreters generally support full RGB
|
|
* colors, so we call this out as a separate level.
|
|
*/
|
|
#define SYSINFO_TEXT_COLORS 32
|
|
|
|
/* no text color support */
|
|
#define SYSINFO_TXC_NONE 0
|
|
|
|
/* parameterized color names only (OS_COLOR_P_TEXT, etc) */
|
|
#define SYSINFO_TXC_PARAM 1
|
|
|
|
/*
|
|
* we support only the basic ANSI colors, foreground control only (white,
|
|
* black, blue, red, green, yellow, cyan, magenta)
|
|
*/
|
|
#define SYSINFO_TXC_ANSI_FG 2
|
|
|
|
/* ANSI colors, foreground and background */
|
|
#define SYSINFO_TXC_ANSI_FGBG 3
|
|
|
|
/* full RGB support */
|
|
#define SYSINFO_TXC_RGB 4
|
|
|
|
/* are the os_banner_xxx() interfaces supported? */
|
|
#define SYSINFO_BANNERS 33
|
|
|
|
/* Interpreter Class - this returns one of the SYSINFO_ICLASS_xxx codes */
|
|
#define SYSINFO_INTERP_CLASS 34
|
|
|
|
/*
|
|
* Interpreter class: Character-mode Text-Only. Interpreters of this class
|
|
* use a single, fixed-pitch font to display all text, and use the
|
|
* text-only HTML subset, and cannot display graphics.
|
|
*/
|
|
#define SYSINFO_ICLASS_TEXT 1
|
|
|
|
/*
|
|
* Interpreter class: Text-Only GUI. Interpreters of this class are
|
|
* traditional text-only interpreters running on graphical operating
|
|
* systems. These interpreters might use multiple fonts (for example, they
|
|
* might display highlighted text in boldface), and might use
|
|
* proportionally-spaced text for some windows. These interpreters support
|
|
* the text-only HTML subset, and cannot display graphics.
|
|
*
|
|
* Text-only GUI interpreters act essentially the same as character-mode
|
|
* text-only interpreters, from the perspective of the client program.
|
|
*/
|
|
#define SYSINFO_ICLASS_TEXTGUI 2
|
|
|
|
/*
|
|
* Interpreter class: HTML. Interpreters of this class can display
|
|
* graphics and sounds, can display multiple fonts and font sizes, can use
|
|
* proportional fonts, and support the full HTML TADS markup language for
|
|
* formatting.
|
|
*/
|
|
#define SYSINFO_ICLASS_HTML 3
|
|
|
|
/*
|
|
* Audio fade information.
|
|
*
|
|
* SYSINFO_AUDIO_FADE: basic fade-in and fade-out support. Interpreters
|
|
* that don't support audio fade at all should return 0. Interpreters that
|
|
* support fades should return a bitwise OR'd combination of
|
|
* SYSINFO_AUDIOFADE_xxx flags below indicating which formats can be used
|
|
* with fades.
|
|
*
|
|
* SYSINFO_AUDIO_CROSSFADE: cross-fades are supported (i.e., simultaneous
|
|
* play of overlapping tracks, one fading out while the other fades in).
|
|
* If cross-fades aren't supported, return 0. If they're supported, return
|
|
* a combination of SYSINFO_AUDIOFADE_xxx flags indicating which formats
|
|
* can be used with cross-fades.
|
|
*/
|
|
#define SYSINFO_AUDIO_FADE 35
|
|
#define SYSINFO_AUDIO_CROSSFADE 36
|
|
|
|
/*
|
|
* Specific audio fading features. These are bit flags that can be
|
|
* combined to indicate the fading capabilities of the interpreter.
|
|
*/
|
|
#define SYSINFO_AUDIOFADE_MPEG 0x0001 /* supported for MPEG audio */
|
|
#define SYSINFO_AUDIOFADE_OGG 0x0002 /* supported for Ogg Vorbis */
|
|
#define SYSINFO_AUDIOFADE_WAV 0x0004 /* supported for WAV */
|
|
#define SYSINFO_AUDIOFADE_MIDI 0x0008 /* supported for MIDI */
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/*
|
|
* Integer division operators. For any compiler that follows ANSI C
|
|
* rules, no definitions are required for these routine, since the
|
|
* standard definitions below will work properly. However, if your
|
|
* compiler does not follow ANSI standards with respect to integer
|
|
* division of negative numbers, you must provide implementations of
|
|
* these routines that produce the correct results.
|
|
*
|
|
* Division must "truncate towards zero," which means that any
|
|
* fractional part is dropped from the result. If the result is
|
|
* positive, the result must be the largest integer less than the
|
|
* algebraic result: 11/3 yields 3. If the result is negative, the
|
|
* result must be the smallest integer less than the result: (-11)/3
|
|
* yields -3.
|
|
*
|
|
* The remainder must obey the relationship (a/b)*b + a%b == a, for any
|
|
* integers a and b (b != 0).
|
|
*
|
|
* If your compiler does not obey the ANSI rules for the division
|
|
* operators, make the following changes in your osxxx.h file
|
|
*
|
|
* - define the symbol OS_NON_ANSI_DIVIDE in the osxxx.h file
|
|
*
|
|
* - either define your own macros for os_divide_long() and
|
|
* os_remainder_long(), or put actual prototypes for these functions
|
|
* into your osxxx.h file and write appropriate implementations of these
|
|
* functions in one of your osxxx.c or .cpp files.
|
|
*/
|
|
/* long os_divide_long(long a, long b); // returns (a/b) with ANSI rules */
|
|
/* long os_remainder_long(long a, long b); // returns (a%b) with ANSI rules */
|
|
|
|
/* standard definitions for any ANSI compiler */
|
|
#ifndef OS_NON_ANSI_DIVIDE
|
|
#define os_divide_long(a, b) ((a) / (b))
|
|
#define os_remainder_long(a, b) ((a) % (b))
|
|
#endif
|
|
|
|
int memicmp(const char *s1, const char *s2, int len);
|
|
|
|
} // End of namespace TADS
|
|
} // End of namespace Glk
|
|
|
|
#endif
|