diff options
Diffstat (limited to 'src/main-ros.c')
-rw-r--r-- | src/main-ros.c | 8670 |
1 files changed, 0 insertions, 8670 deletions
diff --git a/src/main-ros.c b/src/main-ros.c deleted file mode 100644 index 124505d2..00000000 --- a/src/main-ros.c +++ /dev/null @@ -1,8670 +0,0 @@ -/* - * File: main-ros.c - * - * Abstract: Support for RISC OS versions of Angband, including support - * for multitasking and dynamic areas. - * - * Authors: Musus Umbra, Andrew Sidwell, Ben Harrison, and others. - * - * Licences: Angband licence. - */ - -#ifdef __riscos - -#include "angband.h" - -/* - * Purpose: Support for RISC OS Angband 2.9.x onwards (and variants) - * - * NB: This code is still under continuous development - if you want to use - * it for your own compilation/variant, please contact me so that I can - * keep you up to date and give you support :) - * - * Prerequisites to compiling: - * - * DeskLib 2.30 or later (earlier versions may be OK though) - * - * An ANSI C compiler (tested with Acorn's C/C++ and GCC, but should be OK - * with any decent compiler) - * - * My binary distribution (for the templates and other bits) - * - * Note: - * The following symbols are *required* and *must* be defined properly. - */ - -/* - * VARIANT & VERSION - * These two get variant and version data from Angband itself; older - * variants may not have these defined and will have to be altered. - */ -#define VARIANT "ToME" -#define VERSION "2.2.2" - -/* - * PORTVERSION - * This is the port version; it appears in the infobox. - */ -#define PORTVERSION "1.29-dev (2003-08-06)" - -/* - * RISCOS_VARIANT - * This must match the entry in the !Variant Obey file, and it must only - * contain characters that are valid as part of a RISC OS path variable. - * [eg. "Yin-Yangband" is not okay, "EyAngband" is.] - */ -#define RISCOS_VARIANT "ToME" - -/* - * AUTHORS - * For the info box. [eg. "Ben Harrison"] - */ -#define AUTHORS "DarkGod & co." - -/* - * PORTERS - * For the info box. [eg. "Musus Umbra"] - */ -#define PORTERS "A. Sidwell" - -/* - * ICONNAME - * Iconbar icon sprite name eg. "!angband". Note that this must be a valid - * sprite name; it may need modifying for long variant names. - */ -#define ICONNAME "!"RISCOS_VARIANT - -/* - * PDEADCHK - * This should expand to an expression that is true if the player is dead. - * [eg. (p_ptr->is_dead) for Angband or (!alive || dead) for some Zangbands] - */ - -#define PDEADCHK (!alive) - -/* - * The following symbols control the (optional) file-cache: - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * NB: Variants that don't repeatedly read any files whilst running - * (eg. vanilla, sang, etc) should NOT define USE_FILECACHE, etc. as - * it causes a non-negligable amount of code to be compiled in. - * - * NB: The file-cache functions require that some code in files.c is modified - * to use the cached_* functions. This should be utterly trivial. - * - * NB: The returned handle from cached_fopen() is almost certainly *NOT* - * a |FILE*| (although it may be if the cache cannot accomodate the file). - * - * Therefore, you *MUST* ensure that any file opened with cached_fopen() - * is only ever accessed via cached_fgets() and cached_fclose(). - * - * Failure to do so will result in, ahem, unpleasantness. Extreme - * unpleasantness. "Him fall down, go boom." - * - * This /may/ change in the near future (ie. to apply caching in a - * transparent manner), so do keep a backup of files.c (and any other files - * you modify). You always keep backups anyway, don't you? Don't you?! - */ - -/* - * USE_FILECACHE - * if defined then some caching functions will be compiled for use by the - * various get_rnd_line(), etc. in files.c. This could be used in a - * variety of places that read data repeatedly, but it's up to you to - * implement it then. - */ - -/* #define USE_FILECACHE */ - -/* - * SMART_FILECACHE - * This causes lines beginning with '#' (and blank lines) to be discarded - * when caching files. This should help Zangband 2.2.5+ but could cause - * trouble for other variants. If defined, then smart file caching will be - * on by default. - */ - -/* #define SMART_FILECACHE */ - -/* - * ABBR_FILECACHE - * ABBR_FILECACHE causes data read into file-cache to be compressed (using a - * simple set of abbreviations) by default. This can be overridden using a - * command line option. If this symbol is not defined then no compression - * code will be compiled and the user option will be ignored/unavailable. - */ - -/* #define ABBR_FILECACHE */ - -/* - * Note: - * The following symbols control debugging information. - */ - -/* - * FE_DEBUG_INFO - * If defined, some functions will be compiled to display some info. on the - * state of the front-end (accessible) from the '!' user menu. - * - * NB: For actual releases you should NOT define this symbol since it causes - * a non-negligable amount of code/data to be sucked in. - */ -/* #define FE_DEBUG_INFO */ - -/* - * USE_DA - * If defined, it enables the use of dynamic areas (these are still only - * used when the !Variant file allows it). It is likely that this option - * will eventually be removed altogether as there is no major advantege - * to using DAs over just using the Wimpslot. - */ -#define USE_DA - - -/* Constants, etc. ---------------------------------------------------------*/ - -/* Deal with any weird file-caching symbols */ -#ifndef USE_FILECACHE -# undef ABBR_FILECACHE -# undef SMART_FILECACHE -#endif - -/* Maximum terminals */ -#define MAX_TERM_DATA 8 - -/* Menu entry numbers */ -#define IBAR_MENU_INFO 0 -#define IBAR_MENU_SAVE 1 -#define IBAR_MENU_FULLSCREEN 2 -#define IBAR_MENU_GAMMA 3 -#define IBAR_MENU_SOUND 4 -#define IBAR_MENU_WINDOWS 5 -#define IBAR_MENU_SAVECHOICES 6 -#define IBAR_MENU_QUIT 7 - -#define TERM_MENU_INFO 0 -#define TERM_MENU_SAVE 1 -#define TERM_MENU_FONT 2 -#define TERM_MENU_WINDOWS 3 - -/* Icon numbers */ -#define SND_VOL_SLIDER 0 -#define SND_VOL_DOWN 1 -#define SND_VOL_UP 2 -#define SND_ENABLE 3 - -#define GAMMA_ICN 0 -#define GAMMA_DOWN 1 -#define GAMMA_UP 2 - -#define SAVE_ICON 2 -#define SAVE_PATH 1 -#define SAVE_OK 0 -#define SAVE_CANCEL 3 - -/* Position and size of the colours strip in the gamma window */ -#define GC_XOFF 20 -#define GC_YOFF -14 -#define GC_WIDTH 512 -#define GC_HEIGHT 72 - -/* Maximum and minimum allowed volume levels */ -#define SOUND_VOL_MIN 16 -#define SOUND_VOL_MAX 176 - -/*--------------------------------------------------------------------------*/ - - -#undef rename -#undef remove - -#include "Desklib:Event.h" -#include "Desklib:EventMsg.h" -#include "Desklib:Template.h" -#include "Desklib:Window.h" -#include "Desklib:Handler.h" -#include "Desklib:Screen.h" -#include "Desklib:Menu.h" -#include "Desklib:Msgs.h" -#include "Desklib:Icon.h" -#include "Desklib:Resource.h" -#include "Desklib:SWI.h" -#include "Desklib:Time.h" -#include "Desklib:Sound.h" -#include "Desklib:KeyCodes.h" -#include "Desklib:Kbd.h" -#include "Desklib:GFX.h" -#include "Desklib:ColourTran.h" -#include "Desklib:Error.h" -#include "Desklib:Coord.h" -#include "Desklib:Slider.h" -#include "Desklib:Hourglass.h" -#include "Desklib:Save.h" -#include "Desklib:Sprite.h" -#include "Desklib:KernelSWIs.h" -#include "DeskLib:Filing.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <signal.h> -#include <stdarg.h> -#include <time.h> -#include <math.h> - -/*--------------------------------------------------------------------------*/ - -/* - | We use the hourglass around calls to Wimp_Poll in an attempt to stop - | users thinking that the game has 'hung'. - | Kamband/Zangband and the Borg in particular can have quite long delays at - | times. - */ -#define Start_Hourglass \ - { if ( use_glass && !glass_on ) { glass_on=1; Hourglass_Start(50); } } -#define Stop_Hourglass \ - { if ( glass_on ) { glass_on=0; Hourglass_Off(); } } - - -/*--------------------------------------------------------------------------*/ -/* Types */ -/*--------------------------------------------------------------------------*/ - -/* - | A ZapRedraw block - */ -typedef struct -{ - union - { - unsigned int value; - struct - { - unsigned int vdu:1; - unsigned int double_height:1; - unsigned int extension:1; - unsigned int padding:29; - } - bits; - } - r_flags; - - int r_minx; /* min x of redraw in pixels from LHS, incl */ - int r_miny; /* min y of redraw in pixels from top, incl */ - int r_maxx; /* max x of redraw in pixels from LHS, excl */ - int r_maxy; /* max y of redraw in pixels from top, excl */ - - void *r_screen; /* DSA: address of screen to write to (0=>read) */ - int r_bpl; /* DSA: bytes per raster line */ - - int r_bpp; /* log base 2 of bits per pixel */ - int r_charw; /* width of a character in pixels */ - int r_charh; /* height of a character in pixels */ - void *r_caddr; /* DSA: ->character cache | VDU: ->font name */ - int r_cbpl; /* DSA: #bytes/character line | VDU: x OS offset */ - int r_cbpc; /* DSA: #bytes/character | VDU: y OS offset */ - - int r_linesp; /* line spacing (pixels) */ - - void *r_data; /* -> text to display */ - int r_scrollx; /* see Redraw dox */ - int r_scrolly; /* see Redraw dox */ - - void *r_palette; /* -> palette lookup table */ - int r_for; /* foreground colour at start of line */ - int r_bac; /* background colour at start of line */ - - void *r_workarea; /* -> word aligned workspace */ - - int r_magx; /* log2 x OS coords per pixel */ - int r_magy; /* log2 y OS coords per pixel */ - - int r_xsize; /* width of screen in pixels */ - int r_ysize; /* height of screen in pixels */ - - int r_mode; /* current screen mode */ -} -ZapRedrawBlock; - - -/* - | We cache font data using an array of 'font handles' (since there is a - | known maximum no. of fonts required). - | This is what a font 'handle' looks like: - */ -typedef struct -{ - char *name; /* font name */ - int usage; /* usage count */ - int w, h; /* width, height */ - int f, l; /* first and last character defined */ - void *bpp_1; /* source bitmap */ - void *bpp_n; /* bitmap for the current screen mode */ -} -ZapFont; - -/* - | A struct to hold all the data relevant to a term window - */ -typedef struct -{ - term t; /* The Term itself */ - window_handle w; /* Window handle */ - ZapFont *font; /* Font */ - wimp_box changed_box; /* Area out of date */ - struct - { - wimp_point pos; /* Cursor position */ - BOOL visible; /* visibility flag */ - } - cursor; - char name[12]; /* Name to give menus opened from the term */ - int def_open; /* Open by default? */ - wimp_box def_pos; /* default position */ - wimp_point def_scroll; /* default scroll offset */ - int unopened; /* Has this window not been opened yet? */ -} -term_data; - - - -/*--------------------------------------------------------------------------*/ -/* ZapRedraw SWI numbers */ -/*--------------------------------------------------------------------------*/ - -#define SWI_ZapRedraw_ 0x48480 -#define SWI_ZapRedraw_RedrawArea (SWI_ZapRedraw_ + 0x00) -#define SWI_ZapRedraw_GetPaletteEntry (SWI_ZapRedraw_ + 0x01) -#define SWI_ZapRedraw_RedrawRaster (SWI_ZapRedraw_ + 0x02) -#define SWI_ZapRedraw_ConvertBitmap (SWI_ZapRedraw_ + 0x03) -#define SWI_ZapRedraw_PrepareDataLine (SWI_ZapRedraw_ + 0x04) -#define SWI_ZapRedraw_AddCursor (SWI_ZapRedraw_ + 0x05) -#define SWI_ZapRedraw_FindCharacter (SWI_ZapRedraw_ + 0x06) -#define SWI_ZapRedraw_MoveBytes (SWI_ZapRedraw_ + 0x07) -#define SWI_ZapRedraw_CachedCharSize (SWI_ZapRedraw_ + 0x08) -#define SWI_ZapRedraw_ConvBitmapChar (SWI_ZapRedraw_ + 0x09) -#define SWI_ZapRedraw_CreatePalette (SWI_ZapRedraw_ + 0x0a) -#define SWI_ZapRedraw_InsertChar (SWI_ZapRedraw_ + 0x0b) -#define SWI_ZapRedraw_ReadSystemChars (SWI_ZapRedraw_ + 0x0c) -#define SWI_ZapRedraw_ReverseBitmaps (SWI_ZapRedraw_ + 0x0d) -#define SWI_ZapRedraw_ReadVduVars (SWI_ZapRedraw_ + 0x0e) -#define SWI_ZapRedraw_GetRectangle (SWI_ZapRedraw_ + 0x0f) -#define SWI_ZapRedraw_AddVduBitmaps (SWI_ZapRedraw_ + 0x10) -#define SWI_ZapRedraw_CacheFontChars (SWI_ZapRedraw_ + 0x11) -#define SWI_ZapRedraw_SpriteSize (SWI_ZapRedraw_ + 0x12) -#define SWI_ZapRedraw_RedrawWindow (SWI_ZapRedraw_ + 0x13) - - -/* - | Other SWI numbers that aren't defined in DeskLib's SWI.h: - */ -#define SWI_OS_ScreenMode 0x65 -#define SWI_OS_DynamicArea 0x66 -#define SWI_ColourTrans_ReturnColourNumber 0x40744 -#define SWI_Wimp_ReportError 0x400df -#define SWI_PlayIt_Volume 0x4d146 - - - -/*--------------------------------------------------------------------------* - | File scope variables | - *--------------------------------------------------------------------------*/ -static int ftype = 0xffd; /* hack so saved games get the right type */ -static int filehandle[16]; /* we keep track of open files with this */ -static int openfiles = 0; /* how many files are currently open */ - -/* - | Paths we use... - */ -static char resource_path[260] = ""; /* Path pointng to "!Angband.Lib." */ -static char scrap_path[260] = ""; /* Path to create scrap files on */ -static char choices_file[3][260] = -{ "", "", "" }; /* Choices paths (read/write, mirror, read) */ -static char alarm_file[2][260] = -{ "", "" }; /* Alarm choices paths (read/write, mirror, read) */ -/* - | So we can use something more meaningful later... - | NB: Mirror is only meaningful for Choices and we don't - | even reserve space for alarm_file[CHFILE_MIRROR]. - */ -#define CHFILE_WRITE 0 -#define CHFILE_READ 1 -#define CHFILE_MIRROR 2 - -/* - | Other 'globals': - */ -static int initialised = 0; /* Used to determine whether to try to save */ -static int game_in_progress = 0; /* if Quit (or core() is called), etc. */ - -static byte a_palette[256][4]; /* a copy of the raw Angband palette */ -static unsigned int palette[256]; /* palette as gamma'd bbggrrxx words */ -static unsigned int zpalette[256]; /* And our version for ZapRedraw */ -static double gamma = 1.0; /* assume gamma of 1.0 if unspecified */ - -static int enable_sound = 0; /* enable sound FX */ -static int sound_volume = 127; /* Full volume */ -static int force_mono = 0; /* force monochrome */ -static int start_fullscreen = 0; /* start up full screen (added in 1.18) */ -static int hack_flush = 0; /* Should TERM_XTRA_FLUSH wait for all keys to be released? */ -static int flush_scrap = 1; /* Should any scrapfiles (incl. filecache) be deleted at exit? */ -static int max_file_cache_size = 64 << 10; -static unsigned int vfiletype; -static int allow_iclear_hack = 0; /* Allow the hideously evil Iclear workaround thing */ -static int alarm_type = 0; /* is there an alarm set? */ -static int alarm_h = 0, alarm_m = 0; /* alarm time (midnight) */ -static char alarm_message[80] = "Time for bed!"; /* the message to give */ -static int alarm_disp = 0; /* is the alarm being displayed? */ -static int alarm_beep = 0; /* should be beep? */ -static const char *alarm_types[] = -{ "Off", "On (one-shot)", "On (repeating)", "On (one-shot)" }; -static unsigned int alarm_lastcheck = 0; - - -/* A little macro to save some typing later: */ -#define COLOUR_CHANGED(x) \ - ( (angband_color_table[x][1]!=a_palette[x][1]) || \ - (angband_color_table[x][2]!=a_palette[x][2]) || \ - (angband_color_table[x][3]!=a_palette[x][3]) ) - -static int got_caret = 0; /* Do we own the caret? */ -static int key_pressed = 0; /* 'Key has been pressed' Flag */ -static int use_glass = 1; /* use the hourglass between WimpPolls? */ -static int glass_on = 1; /* is the hourglass on? */ -static int user_menu_active = FALSE; /* set to TRUE when the user menu is active */ - -/* Font system variables */ -static ZapFont fonts[MAX_TERM_DATA + 1]; /* The +1 is for the system font */ - -/* The system font is always font 0 */ -#define SYSTEM_FONT (&(fonts[0])) - -/* Term system variables */ -static term_data data[MAX_TERM_DATA]; /* One per term */ - -#ifndef FULLSCREEN_ONLY -static char r_data[24 * (80 * 5 + 4) + 25 * 4]; /* buffer for ZapRedraw data */ - -/* Wimp variables */ -static icon_handle ibar_icon; /* Iconbar icon handle */ -static window_handle info_box; /* handle of the info window */ -static window_handle gamma_win; /* gamma correction window */ -static window_handle sound_win; /* sound options window */ -static window_handle save_box; /* The savebox */ -static menu_ptr ibar_menu; /* Iconbar menu */ -static menu_ptr term_menu; /* Term window menu */ -static menu_ptr wind_menu; /* windows (sub) menu */ -static menu_ptr font_menu; /* Font (sub)menu */ - -static save_saveblock *saveblk = NULL; /* For the save box */ - -/* List of Wimp messages we want to be given */ -static int message_list[] = -{ - message_MODECHANGE, - message_PALETTECHANGE, - - /* For the savebox */ - message_MENUWARN, - message_DATASAVEACK, - - message_PREQUIT, - 0 -}; - - -static term_data *menu_term; /* term the last menu was opened for */ - -#endif /* FULLSCREEN_ONLY */ - -static ZapRedrawBlock zrb; /* a redraw block */ - -/* Cursor colour */ -#define CURSOR_COLOUR 255 /* Cursor's Angband colour */ -#define CURSOR_RGB 0x00ffff00 /* if undefined, use bbggrrxx */ - -static int cursor_rgb = -1; /* colour to use for cursor */ - -static int fullscreen_mode = 0; /* screen mode in use */ -static int old_screenmode = 0; /* Mode we started out in */ -static int *fullscreen_font = 0; /* font data for fullscreen use */ -static int *fullscreen_base = 0; /* base address of screen */ -static int fullscreen_height; /* height of the fullscreen font */ -static int fullscreen_topline; /* raster offset of fullscreen */ - -#define KEYPRESS_QUIT 0x1cc /* F12 gets back to the desktop */ -#define TERM_TOPLINE_HR 32 /* vertical pixel offset in mode 27 */ -#define TERM_TOPLINE_LR 16 /* vertical pixel offset in mode 12 */ -#define TIME_LINE 26 /* Line to display the clock on */ - -/* text to display at the bottom left of the fullscreen display */ -static const char *fs_quit_key_text = "Press f12 to return to the desktop"; -static const char *alarm_cancel_text = "(Press ^Escape to cancel the alarm)"; - -/* Debugging flags, etc. */ -static int log_g_malloc = 0; /* Log calls to ralloc, etc */ -static int show_sound_alloc = 0; /* Log sound mappings, etc */ - -/* Activate file caching? */ -#ifdef USE_FILECACHE -static int use_filecache = TRUE; -#else -static int use_filecache = FALSE; -#endif - -/* Cripple some things to save memory */ -static int minimise_memory = 0; - -/* Forward declarations of some of the Full Screen Mode stuff */ -static void enter_fullscreen_mode(void); -static void leave_fullscreen_mode(void); -static void set_keys(int claim); - -/* Forwards declarations of the sound stuff */ -static void initialise_sound(void); -static void play_sound(int event); - -/* Forward declarations of Term hooks, etc. */ -static void Term_init_acn(term *t); -static errr Term_user_acn(int n); - -#ifndef FULLSCREEN_ONLY -static errr Term_curs_acn(int x, int y); -static errr Term_text_acn(int x, int y, int n, byte a, cptr s); -static errr Term_xtra_acn(int n, int v); -static errr Term_wipe_acn(int x, int y, int n); -static errr Term_xtra_acn_check(void); -static errr Term_xtra_acn_event(void); -static errr Term_xtra_acn_react(void); -#endif /* FULLSCREEN_ONLY */ - -static errr Term_curs_acnFS(int x, int y); -static errr Term_text_acnFS(int x, int y, int n, byte a, cptr s); -static errr Term_xtra_acnFS(int n, int v); -static errr Term_wipe_acnFS(int x, int y, int n); -static errr Term_xtra_acn_checkFS(void); -static errr Term_xtra_acn_clearFS(void); -static errr Term_xtra_acn_eventFS(void); -static errr Term_xtra_acn_reactFS(int force); - -#ifdef USE_DA -/* Forward declarations of the memory stuff */ -static void init_memory(int, int); -#endif - -/* Forward declarations of the alarm stuff */ -static void check_alarm(void); -#ifndef FULLSCREEN_ONLY -static void trigger_alarm_desktop(void); -#endif /* FULLSCREEN_ONLY */ -static void ack_alarm(void); -static void write_alarm_choices(void); -static void read_alarm_choices(void); - - -/* This just shows some debugging info (if enabled with FE_DEBUG_INFO) */ -static void show_debug_info(void); - - - -/* File-caching functions (if enabled at compile time) */ -#ifdef USE_FILECACHE -FILE *cached_fopen(char *name, char *mode); -errr cached_fclose(FILE *fch); -errr cached_fgets(FILE *fch, char *buffer, int max_len); -#endif - -/* - | These functions act as malloc/free, but (if possible) using memory - | in the 'Game' Dynamic Area created by init_memory() - | We attach these functions to the ralloc_aux and rnfree_aux hooks - | that z-virt.c provides. - */ -#ifdef USE_DA -static vptr g_malloc(huge size); -static vptr g_free(vptr blk, huge); -#else - #define g_malloc(size) malloc(size); - #define g_free(block, size) free(block); -#endif - -/* - | These functions act as malloc/free, but (if possible) using memory - | in the 'Fonts' Dynamic Area created by init_memory() - */ -#ifdef USE_DA -static void* f_malloc(size_t size); -static void f_free(void *blk); -#else - #define f_malloc(size) malloc(size); - #define f_free(block) free(block); -#endif - -/* - | These two functions perpetrate great evil to stop IClear from mucking - | with the cursor keys in fullscreen mode. - */ -static void iclear_hack(void); -static void remove_iclear_hack(void); - -/* - | We use this to locate the choices file(s)... - */ -static char *find_choices(int write); -static char *find_choices_mirror(void); -static char *find_alarmfile(int write); - - - -/* - | This function is supplied as a wrapper to the save_player function. - | - | Its purpose is to change the filename that the game will be saved with - | the leafname "!!PANIC!!" so that panic saves that break the savefile - | won't overwrite the original savefile. - | - | To get this to work, you'll need to ammend files.c and change the call - | to save_player in the panic save function(s) (search for "panic save") - | to a call to save_player_panic_acn. You can declare a prototype for - | the function if you like. - */ - -extern int save_player_panic_acn(void) -{ - char *e, *l; - - /* Find the final / in the savefile name */ - for (l = e = savefile; *e; e++) - if (*e == '/') - { - l = e + 1; - } - - /* Write over the current leaf with the special panic one */ - strcpy(l, "!!PANIC!!"); - - /* save the game */ - return save_player(); -} - - -/*--------------------------------------------------------------------------*/ -/* Error reporting, etc. */ -/*--------------------------------------------------------------------------*/ - - -/* Tell the user something important */ -static void plog_hook(cptr str) -{ - Msgs_Report(1, "err.plog", str); -} - -/* Tell the user something, then quit */ -static void quit_hook(cptr str) -{ - /* str may be null */ - if (str) Msgs_Report(1, "err.quit", str); - exit(0); -} - -/* Tell the user something then crash ;) */ -static void core_hook(cptr str) -{ - Msgs_Report(1, "err.core", str); - - if (game_in_progress && character_generated) - save_player_panic_acn(); - - quit(NULL); -} - -static void debug(const char *fmt, ...) -{ - va_list ap; - char buffer[260]; - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - plog(buffer); -} - - - -/* -static void oserror_handler( int sig ) -{ - core(_kernel_last_oserror()->errmess); -} -*/ - - -/*--------------------------------------------------------------------------*/ -/* File handling */ -/*--------------------------------------------------------------------------*/ - -static int myFile_Open(const char *name, int mode) -{ - int handle; - if (SWI(2, 1, SWI_OS_Find, mode, name, /**/ &handle)) - return 0; - return handle; -} - -static int myFile_Size(const char *name) -{ - int size, type; - if (SWI(2, 5, SWI_OS_File, 17, name, /**/ &type, 0, 0, 0, &size)) - return -2; - return type ? size : -1; -} - -static os_error *myFile_Close(const int handle) -{ - return SWI(2, 0, SWI_OS_Find, 0, handle); -} - -static os_error *myFile_Seek(const int handle, const int offset) -{ - return SWI(3, 0, SWI_OS_Args, 1, handle, offset); -} - -static int myFile_WriteBytes(const int handle, const void *buf, const int n) -{ - int ntf; - if (SWI(4, 4, SWI_OS_GBPB, 2, handle, buf, n, /**/ NULL, NULL, NULL, &ntf)) - return n; - return ntf; -} - -static int myFile_ReadBytes(const int handle, void *buf, const int n) -{ - int ntf; - if (SWI(4, 4, SWI_OS_GBPB, 4, handle, buf, n, /**/ NULL, NULL, NULL, &ntf)) - return n; - return ntf; -} - -static os_error *myFile_SetType(const char *n, const int type) -{ - return SWI(3, 0, SWI_OS_File, 18, n, type); -} - - -static int myFile_Extent(const int handle) -{ - int ext; - if (SWI(2, 3, SWI_OS_Args, 2, handle, /**/ NULL, NULL, &ext)) - return -1; - return ext; -} - - -/* - | Determine if one file is newer than another. - | - | The filenames should be specified in RISC OS style. - | - | Returns -1 if 'a' is newer than 'b'. - */ -static int file_is_newer(const char *a, const char *b) -{ - os_error *e; - struct - { - unsigned int msw; - unsigned int lsw; - } - a_time; - struct - { - unsigned int msw; - unsigned int lsw; - } - b_time; - int a_type, b_type; - - /* Get the datestamp of the 'a' file */ - e = SWI(2, 4, SWI_OS_File, - /* In */ - 17, (int)a, - /* Out */ - &a_type, /* object type */ - NULL, &(a_time.msw), /* Load Addr */ - &(a_time.lsw) /* Exec Addr */ - ); - if (e) - { - core(e->errmess); - } - - - /* Get the datestamp of the 'b' file */ - e = SWI(2, 4, SWI_OS_File, - /* In */ - 17, (int)b, - /* Out */ - &b_type, /* object type */ - NULL, &(b_time.msw), /* Load Addr */ - &(b_time.lsw) /* Exec Addr */ - ); - if (e) - { - core(e->errmess); - } - - /* If 'b' doesn't exist then 'b' is OOD. */ - if (!b_type) - { - return -1; - } - /* If 'a' doesn't exist then 'b' isn't OOD. (?) */ - if (!a_type) - { - return 0; - } - - /* Compare the timestamps (assume that the files are typed) */ - if ((a_time.msw & 0xff) >= (b_time.msw & 0xff)) - if ((a_time.lsw) > (b_time.lsw)) - return -1; /* OOD */ - return 0; /* Not OOD */ -} - - -/* - | As fprintf, but outout to all files (if their handles are non zero). - | NB: void type. - */ -static void f2printf(FILE *a, FILE *b, const char *fmt, ...) -{ - va_list ap; - char buffer[2048]; - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - if (a) - { - fprintf(a, buffer); - } - if (b) - { - fprintf(b, buffer); - } - va_end(ap); -} - - - - -/*--------------------------------------------------------------------------*/ -/* Clean up (ie. close files, etc). */ -/*--------------------------------------------------------------------------*/ - -static void final_acn(void) -{ - int i; - - for (i = 0; i < openfiles; i++) - myFile_Close(filehandle[i]); - - if (fullscreen_mode) - { - /* Restore the screen mode */ - Wimp_SetMode(old_screenmode); - - /* Restore the various soft keys */ - set_keys(FALSE); - - /* - | Hack: Early WIMP versions do the "Press SPACE" thing, or something - | odd. It's bloody annoying, whatever it is... - */ - if (event_wimpversion < 300) - Wimp_CommandWindow(-1); - } - - if (flush_scrap && *scrap_path) - { - char tmp[512]; - strcpy(tmp, scrap_path); - tmp[strlen(tmp) - 1] = 0; /* Remove trailing dot */ - SWI(4, 0, SWI_OS_FSControl, 27, tmp, 0, 1); /* ie. "*Wipe <scrapdir> r~c~v~f" */ - } - -#ifdef FULLSCREEN_ONLY - Wimp_CommandWindow(-1); -#endif /* FULLSCREEN_ONLY */ - - Stop_Hourglass; -} - - -/*--------------------------------------------------------------------------* - | Various UNIX-like support funtions | - *--------------------------------------------------------------------------*/ - -/* - | Hack: determine whether filenames should be truncated to 10 chars or not. - | - | Needed since RO2 (and RO3 with Truncate configured off) will return - | errors instead of automatically truncating long filenames. - */ -static int truncate_names(void) -{ - int r1, r2; - - /* First, check the OS version */ - OS_Byte(osbyte_READOSIDENTIFIER, 0x00, 0xff, &r1, &r2); - - /* Assume that we need to truncate if running under RO2 */ - if (r1 == 0xa1 || r1 == 0xa2) - return TRUE; - - /* Okay, so we've got RO3 (or later), so check the CMOS RAM */ - OS_Byte(osbyte_READCMOSRAM, 28, 0, &r1, &r2); - - /* Bit 0 of byte 28 is the Truncate flag */ - return !(r2 & 1); -} - - -/* - | The PathName translation is now done by two separate functions: - | unixify_name() and riscosify_name(). - | - | This is done because only the UNIX=>RISCOS translation should - | ever affect the length of the leafname (ie. by truncating it to - | 10 chars if necessary). - | - | Note that the two functions are identical but for the truncation - | check so all that's really been done is that translate_name() now - | takes an extra argument: 'trunc' that controls whether truncation - | is applied, and riscosify and unixify just call translate_name(). - */ -static char *translate_name(const char *path, int trunc) -{ - static char buf[260]; - char c, *p; - - /* Copy 'path' into 'buf', swapping dots and slashes */ - p = buf; /* Output position */ - do - { - c = *path++; - if (c == '/') - c = '.'; - else if (c == '.') - c = '/'; - *p++ = c; - } - while (c); /* Terminator /is/ copied */ - - /* - | When saving a game, the old game is renamed as - | "SavedGame.old", the new one is saved as "SavedGame.new", - | "SavedGame.old" is deleted, "SavedGame.new" is renamed - | as "SavedGame". This will go wrong on a Filecore based filing - | system if the saved game has a leafname > 8 chars. - */ - - if ((p = strstr(buf, "/old")) == NULL) - { - p = strstr(buf, "/new"); - } - if (!p) - { - ftype = 0xffd; - } - else - { - char *q = strrchr(buf, '.'); - if (q) - if (p - q > 6) - { - memmove(q + 6, p, 5); - } - ftype = vfiletype; - } - - /* - | Hack: Do we need to truncate the leafname? - */ - if (trunc) - { - if (truncate_names()) - { - char *a, *b; - /* - | Assume that only the leafname needs attention - | (this should be true for any variant) - */ - for (a = b = buf; *a; a++) - if (*a == '.') - b = a + 1; - /* - | Now b points to the start of the leafname. - | If the leafname is >10 chars, write over the 10th with a - | terminator. - */ - if (strlen(b) > 10) - { - b[10] = 0; - }; - } - } - - return buf; -} - - -extern char *riscosify_name(const char *path) -{ - return translate_name(path, TRUE); -} - -static char *unixify_name(const char *path) -{ - return translate_name(path, FALSE); -} - - -/*--------------------------------------------------------------------------*/ - - -/* Open a file [as fopen()] but translate the requested filename first */ - -FILE *my_fopen(const char *f, const char *m) -{ - FILE *fp; - char *n = riscosify_name(f); /* translate for RO */ - - /* Try to open the file */ - fp = fopen(n, m); - - /* If it succeded and the file was opened for binary output - | then set the type according to the 'ftype' hack. - | NB: This will fail on some filing systems. - */ - - if (fp && strstr(m, "wb")) - { - myFile_SetType(n, ftype); - } - - return fp; -} - - - - -/* Close a file, a la fclose() */ - -errr my_fclose(FILE *fp) -{ - /* Close the file, return 1 for an error, 0 otherwise */ - return fclose(fp) ? 1 : 0; -} - - -/* Open/Create a file */ - -int fd_make(cptr file, int mode) -{ - char *real_path; - int handle; - - /* Translate the filename into a RISCOS one */ - real_path = riscosify_name(file); - - /* Try to OPENOUT the file (no path, error if dir or not found) */ - handle = myFile_Open(real_path, 0x8f); - - /* Check for failure */ - if (!handle) - { - return -1; - } - - /* Try to set the filetype according to the ftype hack */ - myFile_SetType(real_path, ftype); - - /* We keep track of up to 16 open files at any given time */ - if (openfiles < 16) - filehandle[openfiles++] = handle; - - return (handle); -} - - -/* Delete a file [as remove()] */ -errr fd_kill(cptr file) -{ - return remove(riscosify_name(file)) ? 1 : 0; -} - - -/* Rename a file [as rename()] */ -errr fd_move(cptr old, cptr new) -{ - char new_[260]; - strcpy(new_, riscosify_name(new)); - return rename(riscosify_name(old), new_) ? 1 : 0; -} - -/* Open a file */ -int fd_open(cptr path, int flags) -{ - int handle = 0; - char *real_path = riscosify_name(path); - - switch (flags & 0x0f) - { - case O_RDONLY: /* Read only */ - handle = myFile_Open(real_path, 0x4f); - break; - case O_WRONLY: /* Write only */ - case O_RDWR: /* Read/Write */ - handle = myFile_Open(real_path, 0xcf); - } - - /* Check for failure */ - if (!handle) - { - return (-1); - } - - /* Keep track of upto 16 open files... */ - if (openfiles < 16) - filehandle[openfiles++] = handle; - - return (handle); -} - - -/* Close a file opened with fd_make or fd_open */ -errr fd_close(int handle) -{ - int i; - - if (handle <= 0) - { - return -1; - } /* Illegal handle */ - - /* Try to close the file */ - if (myFile_Close(handle)) - { - return 1; - } - - /* Mark the file as closed in our array of file handles */ - openfiles--; - /* Find the entry in the array (if it exists) */ - for (i = 0; i < 16; i++) - if (filehandle[i] == handle) - { - break; - } - /* Shuffle the remaining entries down */ - for (; i < openfiles; i++) - filehandle[i] = filehandle[i + 1]; - - return 0; /* Sucess */ -} - - - -/* Read some bytes from a file */ -errr fd_read(int handle, char *buf, huge nbytes) -{ - int unread; - - if (handle <= 0) - { - return -1; - } /* Illegal handle */ - unread = myFile_ReadBytes(handle, buf, (int)nbytes); - - return unread ? 1 : 0; -} - - -/* Write some bytes to a file */ -errr fd_write(int handle, const char *buf, huge nbytes) -{ - int unwritten; - - if (handle <= 0) - { - return -1; - } /* Illegal handle */ - unwritten = myFile_WriteBytes(handle, (const void *)buf, (int)nbytes); - - return unwritten ? 1 : 0; -} - - -/* Seek in a file */ -errr fd_seek(int handle, huge offset) -{ - os_error *e; - - if (handle <= 0) - { - return -1; - } /* Illegal handle */ - e = myFile_Seek(handle, (int)offset); - - return e ? 1 : 0; -} - - -/* RISC OS provides no file locking facilities, so: */ -errr fd_lock(int handle, int what) -{ - return 0; -} - - -/* Get a temporary filename */ -errr path_temp(char *buf, int max) -{ - - /* - | New in 1.25 - use the scrap path we decided on earlier, or - | fall back on tmpnam() if that fails for some reason. - */ - if (*scrap_path) - { - time_t t; - int m; - char tmp[512]; - - time(&t); - for (m = 0; m < 80; m++) - { - sprintf(tmp, "%s0x%08x", scrap_path, (int)t + m); - if (myFile_Size(tmp) == -1) - { - break; - } - } - - if (m < 80) - { - strncpy(buf, unixify_name(tmp), max); - return 0; - } - } - - strncpy(buf, unixify_name(tmpnam(NULL)), max); - return 0; -} - - - -/* - * Create a new path by appending a file (or directory) to a path - * - * This requires no special processing on simple machines, except - * for verifying the size of the filename, but note the ability to - * bypass the given "path" with certain special file-names. - * - * Note that the "file" may actually be a "sub-path", including - * a path and a file. - * - * Note that this function yields a path which must be "parsed" - * using the "parse" function above. - */ -errr path_build(char *buf, int max, cptr path, cptr file) -{ - /* Special file */ - if (file[0] == '~') - { - /* Use the file itself */ - strnfmt(buf, max, "%s", file); - } - - /* Absolute file, on "normal" systems */ - else if (prefix(file, PATH_SEP) && !streq(PATH_SEP, "")) - { - /* Use the file itself */ - strnfmt(buf, max, "%s", file); - } - - /* No path given */ - else if (!path[0]) - { - /* Use the file itself */ - strnfmt(buf, max, "%s", file); - } - - /* Path and File */ - else - { - /* Build the new path */ - strnfmt(buf, max, "%s%s%s", path, PATH_SEP, file); - } - - /* Success */ - return (0); -} - - - -/*--------------------------------------------------------------------------*/ - - - - - -/*--------------------------------------------------------------------------*/ -/* Font Functions */ -/*--------------------------------------------------------------------------*/ - -/* - | Cache the system font as fonts[0] - | Returns 1 for sucess or 0 for failure. - | NB: The n_bpp data is *not* cached, just the 1bpp data and font info. - | Also, the usage is never affected. - */ -static int cache_system_font(void) -{ - ZapFont *sys = SYSTEM_FONT; - ZapRedrawBlock zrb; - char work_area[16]; - int i; - - /* Cache the system font (as fonts[0]) */ - if (sys->bpp_1) - { - f_free(sys->bpp_1); - sys->bpp_1 = 0; - } - sys->bpp_1 = f_malloc(8 * 256); /* 2K */ - if (!sys->bpp_1) - { - return 0; - } - - /* Mung so that undefined characters show up as inverted ?s */ - work_area[3] = '?'; - SWI(2, 0, SWI_OS_Word, 10, work_area + 3); - for (i = 4; i < 12; i++) - work_area[i] ^= 255; /* invert colours */ - SWI(4, 0, SWI_ZapRedraw_ReverseBitmaps, 0, work_area + 4, work_area + 4, 8); - for (i = 0; i < 0x20; i++) - memcpy(((char *)sys->bpp_1) + i * 8, work_area + 4, 8); - - /* Read the system font */ - zrb.r_workarea = work_area; - SWI(2, 0, SWI_ZapRedraw_ReadSystemChars, sys->bpp_1, &zrb); - - /* Set up some little bits of info */ - sys->name = (char *) "<System>"; - sys->w = sys->h = 8; - sys->f = 0; - sys->l = 255; - - return 1; -} - - - -/* - | Prepare the font system - */ -static void initialise_fonts(void) -{ - /* Initialise the array */ - memset(fonts, 0, sizeof(fonts)); /* Clear to zeroes */ - - /* Cache the system font */ - cache_system_font(); - fonts[0].usage = 0; /* No users */ -} - - -#ifndef FULLSCREEN_ONLY -/* - | Find a font (by name) in the array. - | Returns 0 if the font isn't loaded, or a ZapFont* for it if it is. - */ -static ZapFont *find_font_by_name(char *name) -{ - int i; - for (i = 0; i <= MAX_TERM_DATA; i++) - if (fonts[i].name) - if (!strcmp(fonts[i].name, name)) - return &(fonts[i]); - return NULL; -} - -/* - | Find a free slot in the fonts array - */ -static ZapFont *find_free_font(void) -{ - int i; - for (i = 1; i <= MAX_TERM_DATA; i++) - if (!fonts[i].name) - { - return &(fonts[i]); - } - return NULL; -} - - - -/* - | Load a font from disc and set up the header info, etc. - | NB: doesn't cache the nbpp data, just the 1bpp data. - | (Sets usage to 1) - | Returns NULL if failed. - */ -static ZapFont *load_font(char *name, ZapFont *f) -{ - int handle, extent; - char path[260]; - struct - { - char id[8]; - int w, h, f, l, r1, r2; - } - header; - char *font_path; - char *t; - char *real_name = name; /* need to preserve this */ - - /* - | 1.10 - the first element of the name determines the path to load - | the font from. - */ - - /* The font paths start <RISCOS_VARIANT>$ */ - t = path + sprintf(path, "%s$", RISCOS_VARIANT); - - /* Copy the path specifier and move 'name' past it */ - for (; *name != '.'; *t++ = *name++) ; - - /* After this, the name now points to the font name proper */ - name++; - - /* Append the end of the path name */ - strcpy(t, "$FontPath"); - - /* Get the path setting */ - font_path = getenv(path); - if (!font_path || !*font_path) - strcpy(path, "null:$."); - else - { - strcpy(path, font_path); - for (t = path; *t > ' '; t++) - ; - if (t[-1] != '.' && t[-1] != ':') - { - *t++ = '.'; - } - *t = 0; - } - strcat(path, name); - - - /* Open the file */ - handle = myFile_Open(path, 0x4f); - if (!handle) - { - return NULL; - } - - /* Read the header */ - if (myFile_ReadBytes(handle, &header, sizeof(header))) - { - myFile_Close(handle); - return NULL; - } - - /* Check that it's a zapfont */ - if (strncmp(header.id, "ZapFont\r", 8)) - { - myFile_Close(handle); - return NULL; - } - - /* Calculate the size of the 1bpp data */ - extent = myFile_Extent(handle) - sizeof(header); - - /* Allocate the storage for the 1bpp data */ - f->bpp_1 = f_malloc(extent); - if (!f->bpp_1) - { - myFile_Close(handle); - return NULL; - } - - /* Load the 1bpp data */ - if (myFile_ReadBytes(handle, f->bpp_1, extent)) - { - f_free(f->bpp_1); - f->bpp_1 = 0; - myFile_Close(handle); - return NULL; - } - - /* Close the file and set the header, etc. */ - myFile_Close(handle); - f->name = f_malloc(strlen(real_name) + 1); - if (!f->name) - { - f_free(f->bpp_1); - f->bpp_1 = 0; - return NULL; - } - - strcpy(f->name, real_name); - f->w = header.w; - f->h = header.h; - f->f = header.f; - f->l = header.l; - f->usage = 1; - - return f; -} - - - - -/* - | Cache a font at a suitable number of bpp for the current mode - | Returns 0 for failure, 1 for sucess. - | If the call fails then the font's bpp_n entry will be NULL. - */ -static int cache_font_for_mode(ZapFont *f) -{ - ZapRedrawBlock b; - char work_area[128]; - int size; - - if (!f) - { - return 0; - } - if (!f->bpp_1) - { - return 0; - } - - b.r_workarea = work_area; - SWI(2, 0, SWI_ZapRedraw_ReadVduVars, 0, &b); - - b.r_workarea = work_area; /* Paranoia */ - b.r_charh = f->h; - b.r_charw = f->w; - SWI(4, 4, SWI_ZapRedraw_CachedCharSize, b.r_bpp, 0, f->w, f->h, - NULL, NULL, &(b.r_cbpl), &(b.r_cbpc)); - - size = 256 * b.r_cbpc; - if (f->bpp_n) - { - f_free(f->bpp_n); - f->bpp_n = NULL; - } - f->bpp_n = f_malloc(size); - if (!f->bpp_n) - { - return 0; - } - - b.r_workarea = work_area; /* Paranoia */ - b.r_caddr = f->bpp_n; - SWI(5, 0, SWI_ZapRedraw_ConvertBitmap, 0, &b, 0, 255, f->bpp_1); - - return 1; -} - - - -/* - | Stop using a font. - | If the font's usage drops to zero then the font data is purged. - */ -static void lose_font(ZapFont *f) -{ - if (--f->usage) - { - /*debug("Losing font %s (still cached)",f->name); */ - return; - } - /*debug("Losing font %s (no longer in use)",f->name); */ - f_free(f->name); - f_free(f->bpp_1); - if (f->bpp_n) - { - f_free(f->bpp_n); - } - memset(f, 0, sizeof(ZapFont)); -} - - -/* - | Get a font. - */ -static ZapFont *find_font(char *name) -{ - ZapFont *f; - - /* Check to see if it's already loaded */ - f = find_font_by_name(name); - if (f) - { - /*debug("Find font %s (already cached)",name); */ - f->usage++; - if (f == SYSTEM_FONT) - { - if (!cache_system_font()) - core("Failed to cache system font!"); - if (!cache_font_for_mode(SYSTEM_FONT)) - core("Failed to cache system font!"); - } - return f; - } - - /* Ok, now check to see if there's a free slot for it */ - f = find_free_font(); - if (!f) - { - return NULL; - } /* Oh dear :( */ - - /* Load the font */ - /*debug("Find font %s (loading)",name); */ - f = load_font(name, f); - if (f) - { - if (!cache_font_for_mode(f)) - return NULL; - return f; - } - return NULL; -} - - - - -/* - | Cache the n_bpp data for all the active fonts (including system) - */ -static void cache_fonts(void) -{ - int i; - for (i = 0; i <= MAX_TERM_DATA; i++) - if (fonts[i].name) - if (!cache_font_for_mode(&(fonts[i]))) - core("Failed to (re)cache font tables"); -} - - - - - - -typedef struct -{ - int load, exec, size, attr, type; - char name[4]; /* Actual size is unknown */ -} -osgbpb10_block; - - -static char *leafname(char *path) -{ - char *s = path + strlen(path); - while (--s > path) - if (*s == '.' || *s == ':') - { - return s + 1; - } - return path; -} - -/* - | NB: This function is recursive. - */ -static menu_ptr make_zfont_menu(char *dir) -{ - int entries, entry; - int read, offset; - unsigned int max_width; - menu_ptr m; - menu_item *mi; - char *temp; - osgbpb10_block *item_info; - char buffer[1024]; /* 1Kb buffer */ - - /* Count the entries in the directory */ - entries = read = offset = 0; - while (offset != -1) - { - if (SWI(7, 5, SWI_OS_GBPB, 10, dir, buffer, 77, offset, 1024, 0, - NULL, NULL, NULL, &read, &offset)) - { - offset = -1; - read = 0; - } - entries += read; - } - - if (!entries) - { - return NULL; - } - - /* Allocate a big enough area of storage for the number of entries */ - m = f_malloc(sizeof(menu_block) + entries * sizeof(menu_item)); - if (!m) - { - return NULL; - } - memset(m, 0, sizeof(menu_block) + entries * sizeof(menu_item)); - - /* Set up the menu header */ - strncpy(m->title, leafname(dir), 12); - m->titlefore = 7; - m->titleback = 2; - m->workfore = 7; - m->workback = 0; - m->height = 44; - m->gap = 0; - mi = (menu_item *) (((int)m) + sizeof(menu_block)); - max_width = strlen(m->title); - - entry = 0; - - /* Read the entries */ - read = offset = 0; - while (offset != -1) - { - if (SWI(7, 5, SWI_OS_GBPB, 10, dir, buffer, 77, offset, 1024, 0, - NULL, NULL, NULL, &read, &offset)) - { - offset = -1; - read = 0; - /*free(m);return NULL; */ - } - - item_info = (osgbpb10_block *) buffer; - - /* Create a menu item for each entry read (if it fits) */ - while (read-- > 0) - { - switch (item_info->type) - { - case 1: /* File */ - if ((item_info->load & 0xffffff00) == 0xfffffd00) - { - /* Data file */ - mi[entry].submenu.value = -1; - mi[entry].iconflags.data.text = 1; - mi[entry].iconflags.data.filled = 1; - mi[entry].iconflags.data.foreground = 7; - mi[entry].iconflags.data.background = 0; - strncpy(mi[entry].icondata.text, item_info->name, 12); - if (strlen(mi[entry].icondata.text) > max_width) - max_width = strlen(mi[entry].icondata.text); - entry++; - } - break; - case 2: /* Directory */ - case 3: /* Image */ - { - menu_ptr sub; - char new_path[260]; - if (strchr(":.", dir[strlen(dir) - 1])) - sprintf(new_path, "%s%s", dir, item_info->name); - else - sprintf(new_path, "%s.%s", dir, item_info->name); - sub = make_zfont_menu(new_path); - if (sub) - { - /* Add the submenu */ - mi[entry].submenu.menu = sub; - mi[entry].iconflags.data.text = 1; - mi[entry].iconflags.data.filled = 1; - mi[entry].iconflags.data.foreground = 7; - mi[entry].iconflags.data.background = 0; - strncpy(mi[entry].icondata.text, item_info->name, 12); - if (strlen(mi[entry].icondata.text) > max_width) - max_width = strlen(mi[entry].icondata.text); - entry++; - } - } - break; - } - temp = ((char *)item_info) + 20; - while (*temp++) ; - item_info = (osgbpb10_block *) ((((int)temp) + 3) & ~3); - } - } - - if (entry) - { - m->width = (max_width + 2) * 16; - mi[entry - 1].menuflags.data.last = 1; - /* - | We could possibly realloc() the storage to fit the - | actual no. of entries read, but this is probably more - | trouble than it's worth. - */ - } - else - { - /* - | No point in returning an empty menu. - */ - f_free(m); - m = NULL; - } - - return m; -} - -#endif /* FULLSCREEN_ONLY */ - - - - -/*--------------------------------------------------------------------------*/ - -/* - | Initialise the palette stuff - */ -static void initialise_palette(void) -{ - memset(a_palette, 0, sizeof(a_palette)); - memset(palette, 0, sizeof(palette)); - memset(zpalette, 0, sizeof(zpalette)); -} - - - -#ifndef FULLSCREEN_ONLY - -/* - | Cache the ZapRedraw palette - */ -static void cache_palette(void) -{ - static ZapRedrawBlock b; - char workspace[128]; - int i; - - static double old_gamma = -1.0; - - /* Idiocy check: */ - if (gamma < 0.01) - { - plog("Internal error: Attempt to apply zero gamma - recovering..."); - gamma = 1.00; - } - - if (gamma != old_gamma) - { - memset(a_palette, 0, sizeof(a_palette)); - old_gamma = gamma; - } - - /* Go through the palette updating any changed values */ - for (i = 0; i < 256; i++) - { - if (COLOUR_CHANGED(i)) - { - int r, g, b; - r = (int)(255.0 * - pow(angband_color_table[i][1] / 255.0, 1.0 / gamma)); - g = (int)(255.0 * - pow(angband_color_table[i][2] / 255.0, 1.0 / gamma)); - b = (int)(255.0 * - pow(angband_color_table[i][3] / 255.0, 1.0 / gamma)); - palette[i] = (b << 24) | (g << 16) | (r << 8); - a_palette[i][1] = angband_color_table[i][1]; - a_palette[i][2] = angband_color_table[i][2]; - a_palette[i][3] = angband_color_table[i][3]; - } - } - - cursor_rgb = palette[CURSOR_COLOUR]; - - /* Cache the ZapRedraw palette for it */ - b.r_workarea = workspace; - if (b.r_mode != screen_mode) - SWI(2, 0, SWI_ZapRedraw_ReadVduVars, 0, &b); - SWI(5, 0, SWI_ZapRedraw_CreatePalette, 2, &b, palette, zpalette, 256); -} - - - - -/*--------------------------------------------------------------------------*/ - -/* - | Functions for dealing with the SaveBox - */ - -/* - | Create the window and claim various handlers for it - */ -static void init_save_window(void) -{ - /* Create the window */ - save_box = Window_Create("save", template_TITLEMIN); - - /* Set the file icon */ - Icon_printf(save_box, SAVE_ICON, "file_%03x", vfiletype); - -} -#endif /* FULLSCREEN_ONLY */ - -/* - | Hack: can't use Str.h without defining HAS_STRICMP. Rather than - | require that the header files are altered we simply provide our - | own strnicmp() function. - */ -static int my_strnicmp(const char *a, const char *b, int n) -{ - int i; - - n--; - - for (i = 0; i <= n; i++) - { - if (tolower((unsigned char)a[i]) != tolower((unsigned char)b[i])) - return tolower((unsigned char)a[i]) - tolower((unsigned char)b[i]); - - if (a[i] == '\0') - break; - } - - return 0; -} - -#ifndef FULLSCREEN_ONLY -/* - | This is the handler called when a 'save' occurrs. - | All it does is to update the game's own savefile setting and - | then (if possible) save the character. - */ -static BOOL SaveHnd_FileSave(char *filename, void *ref) -{ - char old_savefile[1024]; - - /* Hack: refuse to save if the character is dead */ - if (PDEADCHK) - { - Msgs_Report(0, "err.cheat"); - return FALSE; - } - - /* Hack: disallow saves to <Wimp$Scrap>* */ - if (!my_strnicmp("<wimp$scrap>", filename, 12)) - { - Msgs_Report(0, "err.scrap"); - return FALSE; - } - - /* Preserve the old path, in case something goes wrong... */ - strcpy(old_savefile, savefile); - - /* Set the new path */ - strcpy(savefile, unixify_name(filename)); - - /* Try a save (if sensible) */ - if (game_in_progress && character_generated) - { - if (!save_player()) - { - Msgs_Report(0, "err.save", filename); - strcpy(savefile, old_savefile); - return FALSE; /* => failure */ - } - } - - /* Set the pathname icon */ - Icon_printf(save_box, SAVE_PATH, "%s", riscosify_name(savefile)); - - /* Kill the menu */ - Wimp_CreateMenu((menu_block *) - 1, -1, -1); - - return TRUE; /* => Success */ -} - - - -/* - | Init the handlers for the savebox (eg. as a result of a menuwarning - | being received for the savebox) - */ - -static void init_savehandlers(void) -{ - if (saveblk) - { - Save_ReleaseSaveHandlers(saveblk); - saveblk = 0; - } - - saveblk = Save_InitSaveWindowHandler(save_box, /* Window handle */ - TRUE, /* it's part of a menu */ - FALSE, /* not a window */ - FALSE, /* Don't auto release the handlers */ - SAVE_ICON, /* The file icon */ - SAVE_OK, /* The OK icon */ - SAVE_CANCEL, /* The cancel icon */ - SAVE_PATH, /* The pathname icon */ - SaveHnd_FileSave, /* Handler to "save the file" */ - NULL, /* No RAM transfer support */ - NULL, /* No 'result handler' */ - 100 << 10, /* Est. size (irelevant anyway) */ - vfiletype, /* filetype (irelevant) */ - NULL /* ref */ - ); -} - - -/* - | Handle a MenuWarning message for the savebox - */ -static BOOL Hnd_SaveWarning(event_pollblock * pb, void *ref) -{ - os_error *e; - - init_savehandlers(); - - /* Set the pathname */ - Icon_printf(save_box, SAVE_PATH, "%s", riscosify_name(savefile)); - - /* Open the submenu */ - e = Wimp_CreateSubMenu((menu_block *) save_box, - pb->data.message.data.menuwarn.openpos.x, - pb->data.message.data.menuwarn.openpos.y); - - if (e) - { - Msgs_ReportFatal(0, "err.swi", __LINE__, e->errmess); - } - - return TRUE; -} - - -/*--------------------------------------------------------------------------*/ - - -/* - | Initialise the r_data array - | Mainly we just set up the line offset pointers and make sure that the - | lines themselves are 'safe' by writing end-of-line codes to them. - */ -static void initialise_r_data(void) -{ - int *lo = (int *)r_data; - char *ld; - int j; - for (j = 0; j < 24; j++) - { - lo[j] = 25 * 4 + (80 * 5 + 4) * j; /* Offset of line */ - ld = r_data + lo[j]; - *ld++ = 0; /* 0,2 == */ - *ld = 2; /* end of line */ - } - lo[j] = 0; /* Terminate line index */ -} - - - -/* - | Create the r_data array for a term - | This is typically quite fast (1ms or so on a RPC700) - | so we don't bother caching r_data for each term or using the - | 'frosh' concept. - */ -static void make_r_data(term_data *t) -{ - char **c = t->t.old->c; /* char array [24][80] */ - byte **a = t->t.old->a; /* attr array [24][80] */ - char *o; - int i, j, cf; - -/* New code: */ - - o = r_data + 25 * 4; /* First byte of r_data after line index */ - - if (force_mono) - { - for (j = 0; j < 24; j++) - { - /* Set up the line offset entry */ - ((int *)r_data)[j] = o - r_data; - - for (i = 0; i < 80; i++) - *o++ = a[j][i] != TERM_DARK ? c[j][i] : ' '; - /* 0,2 => end of line */ - *o++ = 0; - *o++ = 2; - } - } - else - { - for (j = 0; j < 24; j++) - { - /* Set up the line offset entry */ - ((int *)r_data)[j] = o - r_data; - - /* Each line starts in white */ - cf = TERM_WHITE; - - for (i = 0; i < 80; i++) - { - if (a[j][i] != cf) - { - /* 0,6 => change FG */ - *o++ = 0; - *o++ = 6; - cf = *o++ = a[j][i]; - } - *o++ = c[j][i]; - } - /* 0,2 => end of line */ - *o++ = 0; - *o++ = 2; - } - } -} - - -/* - | Set up 'zrb' for the current screen mode. - */ -static void set_up_zrb_for_mode(void) -{ - static char work_area[4096]; - zrb.r_workarea = work_area; - zrb.r_palette = zpalette; - zrb.r_linesp = 0; - zrb.r_for = TERM_WHITE; - zrb.r_bac = 0; - zrb.r_data = r_data; - SWI(2, 0, SWI_ZapRedraw_ReadVduVars, 0, &zrb); -} - - - -/* - | Set up the ZapRedrawBlock ready to redraw term 't' - | (caches the r_data as part of the process) - */ -static void set_up_zrb(term_data *t) -{ - int fw, fh; - - zrb.r_flags.value = 0; - - /* Set font info up */ - fw = t->font->w; - fh = t->font->h; - SWI(4, 4, SWI_ZapRedraw_CachedCharSize, zrb.r_bpp, 0, fw, fh, - NULL, NULL, &(zrb.r_cbpl), &(zrb.r_cbpc)); - zrb.r_caddr = (void *)(((int)t->font->bpp_n) - (t->font->f * zrb.r_cbpc)); - - zrb.r_charw = fw; /* Character size in pixels */ - zrb.r_charh = fh; - - if (t->font == SYSTEM_FONT) - zrb.r_flags.bits.double_height = screen_eig.y == 1; - else - zrb.r_flags.bits.double_height = 0; - - make_r_data(t); /* Cache the r_data */ -} - - - - - -static void redraw_window(window_redrawblock * rb, BOOL *more, term_data *t) -{ - int cx, cy, cw, ch; - - /* set GCOL for cursor colour */ - if (t->cursor.visible) - { - cw = zrb.r_charw << screen_eig.x; - ch = -(zrb.r_charh << screen_eig.y); - if (zrb.r_flags.bits.double_height) - { - ch *= 2; - } - cx = t->cursor.pos.x * cw; - cy = t->cursor.pos.y * ch; - cx += (rb->rect.min.x - rb->scroll.x); - cy += (rb->rect.max.y - rb->scroll.y); - cw -= (1 << screen_eig.x); - ch += (1 << screen_eig.y); - cy -= (1 << screen_eig.y); - } - - while (*more) - { - SWI(2, 0, SWI_ZapRedraw_GetRectangle, rb, &zrb); - SWI(2, 0, SWI_ZapRedraw_RedrawArea, NULL, &zrb); - if (t->cursor.visible) - { - ColourTrans_SetGCOL(cursor_rgb, 0, 0); - GFX_Move(cx, cy); - GFX_DrawBy(cw, 0); - GFX_DrawBy(0, ch); - GFX_DrawBy(-cw, 0); - GFX_DrawBy(0, -ch); - } - Wimp_GetRectangle(rb, more); - } -} - - - - - -static BOOL Hnd_Redraw(event_pollblock * pb, void *ref) -{ - term_data *t = (term_data *)ref; - window_redrawblock rb; - BOOL more; - - rb.window = t->w; - Wimp_RedrawWindow(&rb, &more); - - set_up_zrb(t); - - redraw_window(&rb, &more, t); - - return TRUE; -} - - - - - -static void refresh_window(term_data *t) -{ - window_redrawblock rb; - BOOL more; - int fw, fh; - - if ((t->changed_box.min.x >= t->changed_box.max.x) || - (t->changed_box.min.y >= t->changed_box.max.y)) - return; - - set_up_zrb(t); - - fw = zrb.r_charw << screen_eig.x; - fh = -(zrb.r_charh << screen_eig.y); - if (zrb.r_flags.bits.double_height) - { - fh *= 2; - } - - rb.window = t->w; - rb.rect.min.x = fw * t->changed_box.min.x; - rb.rect.max.x = fw * t->changed_box.max.x; - - rb.rect.max.y = fh * t->changed_box.min.y; - rb.rect.min.y = fh * t->changed_box.max.y; - - Wimp_UpdateWindow(&rb, &more); - redraw_window(&rb, &more, t); - - t->changed_box.min.x = t->changed_box.min.y = 255; - t->changed_box.max.x = t->changed_box.max.y = 0; -} - - - -static void refresh_windows(void) -{ - int i; - window_info info; - for (i = 0; i < MAX_TERM_DATA; i++) - { - info.window = data[i].w; - Wimp_GetWindowInfo(&info); - if (info.block.flags.data.open) - refresh_window(&(data[i])); - } -} - - -/* - | Set the size of a window. - | If the window grows but has no scroll bars then it is re-sized to - | the new extent. If it shrinks then it is resized regardless. - | - | If the window isn't open then it is opened behind the backwindow, - | resized and then closed again... I /did/ have a reason for doing this - | rather than simply recreating the window at the new size, but for the - | life of me I can't remember what it was... - */ -static void set_window_size(window_handle w, int width, int height) -{ - window_state ws; - int reclose; -/* - * int cw,ch; - */ - - Wimp_GetWindowState(w, &ws); - Window_SetExtent(w, 0, -height, width, 0); - - reclose = !ws.flags.data.open; - if (!(ws.flags.value & (0xf << 27))) - { - if (reclose) - { - ws.openblock.behind = -3; - Wimp_OpenWindow(&(ws.openblock)); - } - /* Removed - caused "pixel creep" :) - * cw = ws.openblock.screenrect.max.x; - * ch = ws.openblock.screenrect.max.y; - * cw -= ws.openblock.screenrect.min.x; - * ch -= ws.openblock.screenrect.min.y; - * ws.openblock.screenrect.min.x -= ((width-cw)/2)-(1<<screen_eig.x); - * ws.openblock.screenrect.min.y -= ((height-ch)/2)-(1<<screen_eig.y); - */ - ws.openblock.screenrect.max.x = ws.openblock.screenrect.min.x + width; - ws.openblock.screenrect.max.y = ws.openblock.screenrect.min.y + height; - Wimp_OpenWindow(&(ws.openblock)); - if (reclose) - { - Wimp_CloseWindow(w); - } - } -} - - - - - - - - - - - - - - - -/* - | Change the size of a window to suit the font displayed in it - */ -static void resize_term_for_font(term_data *t) -{ - int fw, fh; - set_up_zrb(t); - - fw = zrb.r_charw << screen_eig.x; - fh = zrb.r_charh << screen_eig.y; - if (zrb.r_flags.bits.double_height) - { - fh *= 2; - } - - /* Caulculate new size */ - fw *= 80; - fh *= 24; - - set_window_size(t->w, fw, fh); -} - - - - - - - - - - - - - - - - - - - -static BOOL Hnd_Caret(event_pollblock * pb, void *ref) -{ - if (ref) - got_caret = 1; - else - got_caret = 0; - return TRUE; -} - - - - -/* - | Attach a (named) font to the specified term. - | If 'font' is NULL then the system font is attached. - | The bpp_n data is calculated if necessary - | returns: - | 1 => the font was attached OK - | 0 => the system font was substituted - */ -static int attach_font_to_term(term_data *t, char *font) -{ - if (t->font != SYSTEM_FONT) - { - lose_font(t->font); - } - if (font) - { - t->font = find_font(font); - } - if (!t->font) - { - t->font = SYSTEM_FONT; - if (font) - { - Msgs_Report(1, "err.font_l", font); - } - } - else - { - if (!t->font->bpp_n) - { - lose_font(t->font); - t->font = SYSTEM_FONT; - if (font) - { - Msgs_Report(1, "err.font_c", font); - } - } - } - resize_term_for_font(t); - return !(t->font == SYSTEM_FONT); -} - - - - -/*--------------------------------------------------------------------------*/ - - - -/* - | Create a menu of all the (probable!) fonts in the specified location - | NB: Any file of type 'data' is considered a font. - | - | Subdirectories are recursively searched. - | - | 1.10 - Uses <variant>$FontPaths to get a (space separated) list of paths - | to search. For each path name, the menu text will be the name and the - | path searched will be <variant>$<name>$FontPath - | - | Eg. (for angband): - | Angband$FontPaths Zap Angband - | Angband$Zap$FontPath ZapFonts: - | Angband$Angband$FontPath Angband:xtra.fonts. - */ -static void make_font_menu(void) -{ - char *t; - char buffer[260]; - char menu_buffer[260]; - int paths; - int i; - unsigned int max_width; - const char *path[64]; /* pointers to path names */ - menu_item *mi; - - font_menu = NULL; - - /* Get the path (ie. dir) to look under */ - t = getenv(RISCOS_VARIANT "$FontPaths"); - - /* Hack: cope if the path isn't set */ - if (!t) - { - t = ""; - } - - strcpy(buffer, t); - - /* - | Count how many paths there are, build an array of pointers to them - | and terminate them in the buffer - */ - paths = 1; /* including the system font fake path '<System>' */ - for (t = buffer; *t; t++) - { - if (*t == ' ') - { - *t = 0; - } - else - { - if (t == buffer || !t[-1]) - { - path[paths] = t; - paths++; - } - } - } - - /* - | Create the menu - */ - path[0] = SYSTEM_FONT->name; - - font_menu = f_malloc(sizeof(menu_block) + paths * sizeof(menu_item)); - if (!font_menu) - { - core("Out of memory (building font menu)"); - } - memset(font_menu, 0, sizeof(menu_block) + paths * sizeof(menu_item)); - - strncpy(font_menu->title, "Fonts", 12); - font_menu->titlefore = 7; - font_menu->titleback = 2; - font_menu->workfore = 7; - font_menu->workback = 0; - font_menu->height = 44; - font_menu->gap = 0; - max_width = strlen(font_menu->title); - - mi = (menu_item *) (font_menu + 1); - - for (i = 0; i < paths; i++) - { - mi[i].submenu.value = -1; - mi[i].iconflags.data.text = 1; - mi[i].iconflags.data.filled = 1; - mi[i].iconflags.data.foreground = 7; - mi[i].iconflags.data.background = 0; - strncpy(mi[i].icondata.text, path[i], 12); - if (strlen(mi[i].icondata.text) > max_width) - max_width = strlen(mi[i].icondata.text); - } - font_menu->width = (max_width + 2) * 16; - mi[i - 1].menuflags.data.last = 1; - - /* - | Hack: add a dotted line after the system font entry if appropriate - */ - if (paths > 1) mi[0].menuflags.data.dotted = 1; - - /* - | Iterate over the paths, building the appropriate submenus - */ - for (i = 1; i < paths; i++) - { - menu_ptr sub_menu = NULL; - - sprintf(menu_buffer, "%s$%s$FontPath", RISCOS_VARIANT, path[i]); - t = getenv(menu_buffer); - /* Hack: cope if the path isn't defined */ - if (!t) - { - t = ""; - } - - /* Fudge so that the fontpath can be a path, not just a dir. */ - strcpy(menu_buffer, t); - for (t = menu_buffer; *t > ' '; t++) - ; - if (t[-1] == '.') - { - t--; - } - *t = 0; - - /* Build the menu. Don't bother if the path variable was empty */ - if (*menu_buffer) - sub_menu = make_zfont_menu(menu_buffer); - - if (!sub_menu) - { - mi[i].iconflags.data.shaded = 1; - } - else - { - mi[i].submenu.menu = sub_menu; - /* Override the title of the 'root' sub-menu */ - strncpy(sub_menu->title, path[i], 12); - /* Add the submenu to the main menu */ - } - } - - return; -} - -/* ----------------------------------------------- musus, xxxx-xx-xx --- - * Create and set up the infobox. - * --------------------------------------------------------------------- */ -static void create_info_box(void) -{ - info_box = Window_Create("info", template_TITLEMIN); - Icon_printf(info_box, 0, "%s %s", VARIANT, VERSION); - Icon_SetText(info_box, 2, AUTHORS); - Icon_SetText(info_box, 3, PORTERS); - Icon_SetText(info_box, 7, PORTVERSION); - - return; -} - -/* - | Create the various menus - */ -static void init_menus(void) -{ - char buffer1[256]; - char buffer2[32]; - char *o; - - create_info_box(); /* For the Info> entries */ - make_font_menu(); /* Make the fonts menu */ - - Msgs_Lookup("menu.ibar:Info|>Save As|Full screen,Gamma correction,Sound," - "Windows|Save choices|Quit (& save)", buffer1, 256); - ibar_menu = Menu_New(VARIANT, buffer1); - if (!ibar_menu) core("Can't create Iconbar menu!"); - - Msgs_Lookup("menu.term:Info|>Save As|Font,Windows", buffer1, 256); - term_menu = Menu_New(VARIANT, buffer1); - if (!term_menu) core("Can't create Term menu!"); - -#ifndef OLD_TERM_MENU - o = buffer1; - o += sprintf(buffer1, "%s|", VARIANT); - o += sprintf(o, "%s,%s,%s|", angband_term_name[1], angband_term_name[2], - angband_term_name[3]); - sprintf(o, "%s,%s,%s,%s", angband_term_name[4], angband_term_name[5], - angband_term_name[6], angband_term_name[7]); -#else - Msgs_printf(buffer1, "menu.windows:%s|Term-1 (Mirror),Term-2 (Recall)," - "Term-3 (Choice)|Term-4,Term-5,Term-6,Term-7", VARIANT); -#endif - Msgs_Lookup("menu.winT:Windows", buffer2, 32); - wind_menu = Menu_New(buffer2, buffer1); - if (!wind_menu) - { - core("Can't create Windows menu!"); - } - - /* Now attach the various submenus to where they belong */ - Menu_AddSubMenu(ibar_menu, IBAR_MENU_INFO, (menu_ptr) info_box); - Menu_AddSubMenu(ibar_menu, IBAR_MENU_GAMMA, (menu_ptr) gamma_win); - Menu_AddSubMenu(ibar_menu, IBAR_MENU_SOUND, (menu_ptr) sound_win); - Menu_AddSubMenu(ibar_menu, IBAR_MENU_WINDOWS, (menu_ptr) wind_menu); - Menu_AddSubMenu(term_menu, TERM_MENU_INFO, (menu_ptr) info_box); - Menu_AddSubMenu(term_menu, TERM_MENU_WINDOWS, wind_menu); - - /* Add the savebox */ - Menu_Warn(ibar_menu, IBAR_MENU_SAVE, TRUE, Hnd_SaveWarning, NULL); - Menu_Warn(term_menu, TERM_MENU_SAVE, TRUE, Hnd_SaveWarning, NULL); - - if (font_menu) - /* add the submenu */ - Menu_AddSubMenu(term_menu, TERM_MENU_FONT, font_menu); - else - /* If the font menu is buggered, shade its entry */ - /* unticked, shaded */ - Menu_SetFlags(term_menu, TERM_MENU_FONT, FALSE, TRUE); -} - - - - -static void grab_caret(void) -{ - caret_block cb; - cb.window = data[0].w; - cb.icon = -1; - cb.height = 1 << 25; /* Invisible */ - Wimp_SetCaretPosition(&cb); -} - - - - -/* - | (Recursively) clear all ticks from the specified menu - */ -static void clear_all_menu_ticks(menu_ptr mp) -{ - menu_item *mi = (menu_item *) (mp + 1); - - do - { - if (mi->menuflags.data.ticked) - mi->menuflags.data.ticked = 0; - if (mi->submenu.value != -1) - clear_all_menu_ticks(mi->submenu.menu); - mi++; - } - while (mi[-1].menuflags.data.last != 1); -} - - - - - - -/* - | Set the font menu's ticks to match the specifed font name. - | - | fm is the (sub) menu to scan down (recursing into it's submenus (if any)) - | fn is the font name to match - | prefix is the menu text to be prepended to the menu entries due to - | previous menus (eg. "08x16" will cause fn="08x16.fred" to match menu - | entry "fred". - | - | NB: recursive. - | - */ - -static void set_font_menu_ticks(menu_ptr fm, char *fn, const char *prefix) -{ - char buffer[260]; - char *b_leaf; /* -> menu 'leaf' text in buffer */ - int pl; /* prefix string length */ - menu_item *mi = (menu_item *) (fm + 1); - - strcpy(buffer, prefix); - pl = strlen(buffer); - b_leaf = buffer + pl; - - do - { - /* Check for (substring) match */ - strncpy(b_leaf, mi->icondata.text, 12); - - /* Is it a sub-menu? */ - if (mi->submenu.value == -1) - { - /* No - must be an exact match */ - mi->menuflags.data.ticked = !strcmp(buffer, fn); - } - else - { - /* Yes - must be a partial match (with a dot on :) */ - strcat(b_leaf, "."); - mi->menuflags.data.ticked = - !strncmp(buffer, fn, pl + strlen(b_leaf)); - if (mi->menuflags.data.ticked) - set_font_menu_ticks(mi->submenu.menu, fn, buffer); - else - clear_all_menu_ticks(mi->submenu.menu); - } - - /* Next item */ - mi++; - } - while (mi[-1].menuflags.data.last != 1); /* Until finished */ -} - - - - - - - - - - - -/* - | Set ticks, etc. in the term_menu to reflect the current state of the - | term 't' - */ -static void set_up_term_menu(term_data *t) -{ - int i; - menu_ptr mp; - menu_item *mi; - window_state ws; - - /* First of all, set up menu title to be the term's title */ - strncpy(term_menu->title, t->name, 12); - - /* Now set the ticks in the Windows> submenu (cuz it's easy) */ - mp = wind_menu; /* Windows submenu */ - mi = (menu_item *) (mp + 1); /* First entry */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - Wimp_GetWindowState(data[i].w, &ws); - mi[i].menuflags.data.ticked = ws.flags.data.open; - } - - /* - | Now, the tricky bit: find out which font is selected in this - | term and tick it in the menu. Untick all the rest. - */ - set_font_menu_ticks(font_menu, t->font->name, ""); - - /* Shade the 'Save>' entry if saving isn't possible (yet) */ - if (game_in_progress && character_generated) - Menu_SetFlags(term_menu, TERM_MENU_SAVE, 0, PDEADCHK); - else - Menu_SetFlags(term_menu, TERM_MENU_SAVE, 0, TRUE); - -} - - - -/* - | Generic 'click' handler for windows - turns a drag on the window - | into a move-window style drag. - */ -static BOOL Hnd_Click(event_pollblock * pb, void *ref) -{ - if (pb->data.mouse.button.data.dragselect || - pb->data.mouse.button.data.dragadjust) - { - drag_block b; - b.window = pb->data.mouse.window; - b.screenrect.min.x = b.screenrect.min.y = 0; - b.screenrect.max.x = screen_size.x; - b.screenrect.max.y = screen_size.y; - b.type = drag_MOVEWINDOW; - Wimp_DragBox(&b); - } - - return TRUE; -} - - - -/* - | Handle a click on a Term window. - */ -static BOOL Hnd_TermClick(event_pollblock * pb, void *ref) -{ - term_data *t = (term_data *)ref; - - if (pb->data.mouse.button.data.menu) - { - menu_term = t; - set_up_term_menu(t); - Menu_Show(term_menu, pb->data.mouse.pos.x - 32, - pb->data.mouse.pos.y + 32); - } - else - { - grab_caret(); - Hnd_Click(pb, ref); - } - - return TRUE; -} - -#endif /* FULLSCREEN_ONLY */ - - - -static void mark_ood(term_data *t, int minx, int miny, int maxx, int maxy) -{ - if (t->changed_box.min.x > minx) - t->changed_box.min.x = minx; - if (t->changed_box.max.x < maxx) - t->changed_box.max.x = maxx; - if (t->changed_box.min.y > miny) - t->changed_box.min.y = miny; - if (t->changed_box.max.y < maxy) - t->changed_box.max.y = maxy; -} - - -#ifndef FULLSCREEN_ONLY - -/* Check for an event (ie. key press) */ -static errr Term_xtra_acn_check(void) -{ - static int last_poll = 0; - unsigned int curr_time; - int bh, bl; - - /* - | Only poll the wimp if there's something in the keyboard buffer - | or every 10cs. This is presumably so that we process as many - | keypresses as possible before any other application gets a go. - */ - - /* Check the kbd buffer */ - SWI(3, 3, SWI_OS_Byte, 128, 255, 0, /**/ NULL, &bl, &bh); - bl = (bl & 0xff) + (bh << 8); - - /* Check how long it is since we last polled */ - curr_time = Time_Monotonic(); - - if ((bl > 0 && got_caret) || ((curr_time - last_poll) > 9)) - { - last_poll = curr_time; - Stop_Hourglass; - Event_Poll(); - Start_Hourglass; - } - - /* - | This allows the user to interrupt the borg. - */ - if (key_pressed) return key_pressed = 0; - - return 1; -} - - -/* - | Wait for an event (ie. keypress) - | Note that we idle poll once a second to allow us to implement the - | alarm system. - */ -static errr Term_xtra_acn_event(void) -{ - Stop_Hourglass; - - while (!key_pressed && !fullscreen_font) - { - Event_PollIdle(100); - } - Start_Hourglass; - - return key_pressed = 0; -} - - - -/* React to changes (eg. palette change) */ -static errr Term_xtra_acn_react(void) -{ - int c; - - cache_palette(); - - /* Mark the entirety of each window as out of date */ - for (c = 0; c < MAX_TERM_DATA; c++) - mark_ood(&data[c], 0, 0, 80, 24); - - /* Force a redraw of the windows */ - refresh_windows(); - - /* Success */ - return 0; -} - - - -/* Do various things to a term */ -static errr Term_xtra_acn(int n, int v) -{ - term_data *t = (term_data *)Term; - - switch (n) - { - case TERM_XTRA_CLEAR: /* Clear the Term */ - /*for ( i=0; i<Term->hgt; i++ ) - t->froshed[i] = 1; */ - mark_ood(t, 0, 0, Term->wid, Term->hgt); - /*refresh_window( t ); - NB: Term isn't actually cleared yet! */ - /* Success */ - return 0; - - case TERM_XTRA_EVENT: /* Wait/check for an event */ - if (v) - return Term_xtra_acn_event(); - else - return Term_xtra_acn_check(); - - case TERM_XTRA_BORED: /* Bored */ - return Term_xtra_acn_check(); - - case TERM_XTRA_FLUSH: /* Flush input */ - if (got_caret) - { - /* 1.21 - Hack: wait until no keys are pressed */ - if (hack_flush) - for (v = 0; v != 0xff;) - SWI(1, 2, SWI_OS_Byte, 122, 0, &v); - SWI(3, 0, SWI_OS_Byte, 21, 0, 0); /* Flush Kbd buffer */ - } - return 0; - - case TERM_XTRA_FRESH: /* Flush output */ - refresh_window(t); - return 0; - - case TERM_XTRA_FROSH: /* Ensure line 'v' is plotted */ - /* Doesn't do anything */ - return 0; - - case TERM_XTRA_SHAPE: /* Set cursor visibility */ - t->cursor.visible = v ? TRUE : FALSE; - mark_ood(t, t->cursor.pos.x, t->cursor.pos.y, - t->cursor.pos.x + 1, t->cursor.pos.y + 1); - refresh_window(t); /* needed? */ - return 0; - - case TERM_XTRA_NOISE: /* Make a beep */ - Sound_SysBeep(); - return 0; - - case TERM_XTRA_REACT: /* React to, eg. palette changes */ - return Term_xtra_acn_react(); - - case TERM_XTRA_DELAY: /* Delay for 'v' ms */ - if (v > 0) - { - unsigned int start = Time_Monotonic(); - v = (v + 5) / 10; /* Round to nearest cs */ - GFX_Wait(); - while ((Time_Monotonic() - start) < v) - ; - } - return 0; - - case TERM_XTRA_SOUND: /* Play a sound :) */ - if (enable_sound) - { - play_sound(v); - } - return 0; - - /* Subdirectory scan */ - case TERM_XTRA_SCANSUBDIR: - { - filing_dirdata directory; - filing_direntry *entry; - - scansubdir_max = 0; - - if (Filing_OpenDir(riscosify_name(scansubdir_dir), &directory, sizeof(filing_direntry), readdirtype_DIRENTRY) != NULL) - { - Error_Report(0, "Couldn't open directory \"%s\"", riscosify_name(scansubdir_dir)); - return 0; - } - - while ((entry = Filing_ReadDir(&directory)) != NULL) - { - if (entry->objtype == filing_DIRECTORY) - { - string_free(scansubdir_result[scansubdir_max]); - scansubdir_result[scansubdir_max] = string_make(entry->name); - ++scansubdir_max; - } - } - - Filing_CloseDir(&directory); - - return 0; - } - - /* Return current "time" in milliseconds */ - case TERM_XTRA_GET_DELAY: - { - Term_xtra_long = Time_Monotonic() * 100; - - return 0; - } - - /* Rename main window */ - case TERM_XTRA_RENAME_MAIN_WIN: - { - Window_SetTitle(data[0].w, angband_term_name[0]); - return 0; - } - - default: - return 1; /* Unsupported */ - } -} - - - -/* Move (but don't necessarily display) the cursor */ -static errr Term_curs_acn(int x, int y) -{ - term_data *t = (term_data *)Term; - - if (t->cursor.visible) - mark_ood(t, t->cursor.pos.x, t->cursor.pos.y, - t->cursor.pos.x + 1, t->cursor.pos.y + 1); - - t->cursor.pos.x = x; - t->cursor.pos.y = y; - - if (t->cursor.visible) - mark_ood(t, t->cursor.pos.x, t->cursor.pos.y, - t->cursor.pos.x + 1, t->cursor.pos.y + 1); - - return 0; -} - - - -/* - | NB: these two are very simple since we use the Term's contents - | directly to generate the r_data for ZapRedraw. - */ - -/* Erase 'n' characters at (x,y) */ -static errr Term_wipe_acn(int x, int y, int n) -{ - mark_ood((term_data *)Term, x, y, x + n, y + 1); - return 0; -} - -/* Write 'n' characters from 's' with attr 'a' at (x,y) */ -static errr Term_text_acn(int x, int y, int n, byte a, cptr s) -{ - mark_ood((term_data *)Term, x, y, x + n, y + 1); - return 0; -} - -#endif /* FULLSCREEN_ONLY */ - - -/* Initialise one of our terms */ -static void Term_init_acn(term *t) -{ - term_data *term = (term_data *)t; - - /* Ludicrous changed box settings :) */ - term->changed_box.min.x = 256; - term->changed_box.min.y = 256; - term->changed_box.max.x = 0; - term->changed_box.max.y = 0; -} - - - -static void term_data_link(term_data *td, int k) -{ - term *t = &(td->t); - - /* Initialise the term */ - term_init(t, 80, 24, k); - - /* Set flags and hooks */ - t->attr_blank = TERM_WHITE; - t->char_blank = ' '; - - /* Experiment (FS mode requires them) */ - t->always_text = TRUE; - t->never_frosh = TRUE; - /* Experiment (FS mode requires them) */ - -#ifdef FULLSCREEN_ONLY - t->wipe_hook = Term_wipe_acnFS; - t->xtra_hook = Term_xtra_acnFS; - t->curs_hook = Term_curs_acnFS; - t->text_hook = Term_text_acnFS; -#else - t->init_hook = Term_init_acn; - t->xtra_hook = Term_xtra_acn; - t->wipe_hook = Term_wipe_acn; - t->curs_hook = Term_curs_acn; - t->text_hook = Term_text_acn; - t->user_hook = Term_user_acn; -#endif /* FULLSCREEN_ONLY */ - - t->data = td; - - Term_activate(t); -} - - -#ifndef FULLSCREEN_ONLY - -/* Open default windows (ie. as set in choices) at the appropriate sizes */ -static void show_windows(void) -{ - int i; - for (i = MAX_TERM_DATA; i-- > 0;) - { - if (!data[i].unopened) - { - if (data[i].def_open) - Window_Show(data[i].w, open_WHEREVER); - } - else - { - if (data[i].def_open) - { - window_openblock ob; - ob.window = data[i].w; - ob.screenrect = data[i].def_pos; - ob.scroll = data[i].def_scroll; - ob.behind = -1; - Wimp_OpenWindow(&ob); - data[i].unopened = 0; - } - } - } -} - - -/* - | 'ref' is used to indicate whether this close is being forced by some other - | part of the code (eg. the Windows> submenu code). This is used to modify - | the 'adjust doesn't close other terms' behavior. - */ - -static BOOL Hnd_MainClose(event_pollblock * pb, void *ref) -{ - int i; - window_state ws; - mouse_block mb; - - /* New in 1.08: don't close other Terms if closed with adjust */ - Wimp_GetPointerInfo(&mb); - if (ref || mb.button.data.adjust) - { - Wimp_CloseWindow(data[0].w); - } - else - { - /* Close all the terms, but mark the open ones as 'def_open' */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - Wimp_GetWindowState(data[i].w, &ws); - if (!ws.flags.data.open) - { - data[i].def_open = 0; - } - else - { - Wimp_CloseWindow(data[i].w); - data[i].def_open = 1; - } - } - } - - return TRUE; -} - - -static BOOL Hnd_PaletteChange(event_pollblock * pb, void *ref) -{ - cache_palette(); - return TRUE; -} - - - -static BOOL Hnd_ModeChange(event_pollblock * pb, void *ref) -{ - int i; - Screen_CacheModeInfo(); - set_up_zrb_for_mode(); /* (re)set up the redraw block */ - cache_palette(); /* (re)cache the palette */ - cache_fonts(); /* (re)cache the fonts */ - /* Enforce sizes (eg. if screen_eig.y has changed) */ - for (i = 0; i < MAX_TERM_DATA; i++) - resize_term_for_font(&(data[i])); - return TRUE; -} - - - - -static BOOL Hnd_Keypress(event_pollblock * pb, void *ref) -{ - static const char hex[] = "0123456789ABCDEF"; - int c = pb->data.key.code; - /* Check whether this key was pressed in Term 0 */ - if (pb->data.key.caret.window == data[0].w) - { - switch (c) - { - case keycode_F12: - case keycode_SHIFT_F12: - case keycode_CTRL_F12: - case keycode_CTRL_SHIFT_F12: - /* Never intercept these */ - break; - - case 27: /* handle escape specially */ - if (Kbd_KeyDown(inkey_CTRL)) - { - ack_alarm(); - return TRUE; - } - - /* Send everything else onto the Term package */ - default: - /* Take care of "special" keypresses */ - switch (c) - { - case keycode_TAB: - { - c = '\t'; - break; - } - - case keycode_PAGEUP: - { - c = '9'; - break; - } - - case keycode_PAGEDOWN: - { - c = '3'; - break; - } - - case keycode_COPY: - { - c = '1'; - break; - } - - case keycode_HOME: - { - c = '7'; - break; - } - } - /* Pass to the angband engine */ - /* Allow shift & ctrl to modify the keypad keys */ - if (c >= '0' && c <= '9') - { - kbd_modifiers m = Kbd_GetModifiers(FALSE); - if (m.shift) - { - c |= 0x800; - } - if (m.ctrl) - { - c |= 0x400; - } - /* Could maybe add ALT as 0x1000 ??? */ - } - - /* Keys >255 have to be send as escape sequences (31=escape) */ - if (c > 255 || c == 31) - { - Term_keypress(31); - Term_keypress(hex[(c & 0xf00) >> 8]); - Term_keypress(hex[(c & 0x0f0) >> 4]); - Term_keypress(hex[(c & 0x00f)]); - c = 13; - } - Term_keypress(c); - key_pressed = 1; - /*if ( c==27 ) { escape_pressed = 1; } */ - return TRUE; - } - } - - Wimp_ProcessKey(c); - return TRUE; -} - - -/*--------------------------------------------------------------------------*/ -/* Gamma correction window stuff */ -/*--------------------------------------------------------------------------*/ - -static void redraw_gamma(window_redrawblock * rb, BOOL *more) -{ - int i, y, x, h, w; - int bx, by; - int dither; - - bx = Coord_XToScreen(GC_XOFF, (convert_block *) & (rb->rect)); - by = Coord_YToScreen(GC_YOFF, (convert_block *) & (rb->rect)); - - h = GC_HEIGHT / 4; - w = GC_WIDTH / 16; - - x = bx; - - while (*more) - { - for (i = 0; i < 16; i++) - { - y = by; - for (dither = 0; dither < 2; dither++) - { - /* Solid block: */ - ColourTrans_SetGCOL(palette[i], dither << 8, 0); - GFX_RectangleFill(x, y, w, -h); - y -= h; - /* Dot on black: */ - ColourTrans_SetGCOL(palette[0], dither << 8, 0); - GFX_RectangleFill(x, y, w, -h); - ColourTrans_SetGCOL(palette[i], dither << 8, 0); - GFX_RectangleFill(x + (w / 2) - 2, y - (h / 2), 2, 2); - y -= h; - } - x += w; - } - Wimp_GetRectangle(rb, more); - } -} - - -static void update_gamma(void) -{ - window_redrawblock rb; - BOOL more; - - rb.window = gamma_win; - rb.rect.min.x = GC_XOFF; - rb.rect.min.y = GC_YOFF - GC_HEIGHT; - rb.rect.max.y = GC_XOFF + GC_WIDTH + screen_delta.x; - rb.rect.max.y = GC_YOFF + screen_delta.y; - - Wimp_UpdateWindow(&rb, &more); - if (more) - { - redraw_gamma(&rb, &more); - } -} - - - -static BOOL Hnd_RedrawGamma(event_pollblock * pb, void *ref) -{ - window_redrawblock rb; - BOOL more; - - rb.window = pb->data.openblock.window; - Wimp_RedrawWindow(&rb, &more); - if (more) - { - redraw_gamma(&rb, &more); - } - - return TRUE; -} - - -static BOOL Hnd_GammaClick(event_pollblock * pb, void *ref) -{ - int up = (ref == 0); - - if (up) - { - if (gamma < 9.0) - { - gamma += 0.05; - Icon_SetDouble(gamma_win, 0, gamma, 2); - Term_xtra_acn_react(); - update_gamma(); - } - } - else - { - if (gamma > 0.05) - { - gamma -= 0.05; - Icon_SetDouble(gamma_win, GAMMA_ICN, gamma, 2); - Term_xtra_acn_react(); - update_gamma(); - } - } - - /* Hack: if the user menu is active then force it to redraw */ - if (user_menu_active) - { - Term_keypress(18); - key_pressed = 1; - } - - return TRUE; -} - -/* - | Reflect the current options in the gamma window - */ -static void set_gamma_window_state(void) -{ - if (minimise_memory) return; - - Icon_SetDouble(gamma_win, 0, gamma, 2); -} - - -static void init_gamma_window(void) -{ - if (minimise_memory) return; - - Template_UseSpriteArea(resource_sprites); - gamma_win = Window_Create("gamma", template_TITLEMIN); - Template_UseSpriteArea(NULL); - Event_Claim(event_REDRAW, gamma_win, event_ANY, Hnd_RedrawGamma, 0); - Event_Claim(event_CLICK, gamma_win, GAMMA_DOWN, Hnd_GammaClick, (void *)1); - Event_Claim(event_CLICK, gamma_win, GAMMA_UP, Hnd_GammaClick, (void *)0); - set_gamma_window_state(); -} - - -/*--------------------------------------------------------------------------*/ -/* Sound options window stuff */ -/*--------------------------------------------------------------------------*/ - -static slider_info volume_slider; - - -/* - | Reflect the current sound config in the sound options window - */ -static void set_sound_window_state(void) -{ - if (minimise_memory) return; - - Icon_SetSelect(sound_win, SND_ENABLE, enable_sound); - Slider_SetValue(&volume_slider, sound_volume, NULL, NULL); - - if (sound_volume > 127) - volume_slider.colour.foreground = colour_RED; - else - volume_slider.colour.foreground = colour_GREEN; -} - - - -/* - | The sound slider has been dragged, so update the sound volume setting - */ -static int update_volume_from_slider(slider_info *si, void *ref) -{ - sound_volume = Slider_ReadValue(si); - - if (sound_volume > 127) - volume_slider.colour.foreground = colour_RED; - else - volume_slider.colour.foreground = colour_GREEN; - - return 0; -} - - -/* - | Handle redraw events for the sound options window - */ -static BOOL Hnd_RedrawSnd(event_pollblock * pb, void *ref) -{ - window_redrawblock redraw; - BOOL more; - - redraw.window = pb->data.openblock.window; - Wimp_RedrawWindow(&redraw, &more); - - while (more) - { - Slider_Redraw(((slider_info *) ref), &redraw.cliprect); - Wimp_GetRectangle(&redraw, &more); - } - return (TRUE); -} - - -/* - | Handle clicks on the sound options window - */ -static BOOL Hnd_SndClick(event_pollblock * pb, void *ref) -{ - int icn = pb->data.mouse.icon; - int adj = pb->data.mouse.button.data.adjust; - slider_info *si = (slider_info *) ref; - - switch (icn) - { - /* Bump arrows for the slider: */ - case SND_VOL_DOWN: - adj = !adj; - - case SND_VOL_UP: - adj = adj ? -1 : 1; - sound_volume += adj; - if (sound_volume < SOUND_VOL_MIN) - { - sound_volume = SOUND_VOL_MIN; - } - if (sound_volume > SOUND_VOL_MAX) - { - sound_volume = SOUND_VOL_MAX; - } - set_sound_window_state(); - break; - - /* The slider itself */ - case SND_VOL_SLIDER: - Icon_ForceRedraw(sound_win, SND_VOL_SLIDER); - Slider_Drag(si, NULL, NULL, NULL); - break; - - /* The enable/disable icon */ - case SND_ENABLE: - enable_sound = !enable_sound; - Icon_SetSelect(sound_win, SND_ENABLE, enable_sound); - if (enable_sound) - { - initialise_sound(); - } - break; - } - - /* Hack: if the user menu is active then force it to redraw */ - if (user_menu_active) - { - Term_keypress(18); - key_pressed = 1; - } - - return TRUE; -} - - - -/* - | Set the sound options window up, ready to rock :) - */ -static void init_sound_window(void) -{ - Template_UseSpriteArea(resource_sprites); - sound_win = Window_Create("sound", template_TITLEMIN); - Template_UseSpriteArea(NULL); - - Event_Claim(event_REDRAW, sound_win, event_ANY, Hnd_RedrawSnd, - (void *)&volume_slider); - Event_Claim(event_CLICK, sound_win, event_ANY, Hnd_SndClick, - (void *)&volume_slider); - - /* Set up the slider info */ - volume_slider.window = sound_win; - volume_slider.icon = SND_VOL_SLIDER; - volume_slider.limits.min = SOUND_VOL_MIN; - volume_slider.limits.max = SOUND_VOL_MAX; - volume_slider.colour.foreground = colour_GREEN; - volume_slider.colour.background = colour_WHITE; - volume_slider.border.x = 8; - volume_slider.border.y = 8; - volume_slider.update = update_volume_from_slider; - - set_sound_window_state(); -} - - - - - -/*--------------------------------------------------------------------------*/ - - - - - - - - - - - -/* - | A font has been selected. - | At this point, menu_term is a pointer to the term for which the - | menu was opened. - */ -static void handle_font_selection(int *s) -{ - char name[260]; - os_error *e; - char *r; - menu_ptr mp = font_menu; - int *mis; - - /* Follow the >s to the entry specified */ - for (mis = s; *mis != -1; mis++) - mp = ((menu_item *) (mp + 1))[*mis].submenu.menu; - - /* - | Now, check to see if we've hit a leaf entry. - | NB: If the entry isn't a leaf entry then the first entry in its submenu - | is used instead - */ - if (((int)mp) != -1) - { - mis[0] = 0; - mis[1] = -1; - mp = ((menu_item *) (mp + 1))[0].submenu.menu; - } - - if (((int)mp) != -1) - return; - - e = Wimp_DecodeMenu(font_menu, s, name); - if (e) - { - plog(e->errmess); - return; - } - - /* Make sure that the string is NULL terminated */ - for (r = name; *r >= ' '; r++) - ; - *r = 0; - - attach_font_to_term(menu_term, name); - mark_ood(menu_term, 0, 0, 80, 24); - refresh_window(menu_term); -} - - -#endif /* FULLSCREEN_ONLY */ - - - - -static void load_choices(void) -{ - FILE *fp = NULL; - char *cf; - int i; - char buffer[260]; - - cf = find_choices(FALSE); - if (*cf) - fp = fopen(cf, "r"); - - /* Implement default choices */ - data[0].def_open = 1; - data[0].unopened = 1; /* ie. force def_pos */ - data[0].def_pos.min.x = (screen_size.x - 1280) / 2; - data[0].def_pos.max.x = (screen_size.x + 1280) / 2; - data[0].def_pos.min.y = (screen_size.y - 768) / 2 - 32; - data[0].def_pos.max.y = (screen_size.y + 768) / 2 - 32; - data[0].def_scroll.x = data[0].def_scroll.y = 0; - for (i = 1; i < MAX_TERM_DATA; i++) - { - data[i].def_open = 0; - data[i].unopened = 1; /* ie. force def_pos */ - data[i].def_pos.min.x = (screen_size.x - 1280) / 2; - data[i].def_pos.max.x = (screen_size.x + 1280) / 2; - data[i].def_pos.min.y = (screen_size.y - 768) / 2; - data[i].def_pos.max.y = (screen_size.y + 768) / 2; - data[i].def_scroll.x = data[i].def_scroll.y = 0; - } - - if (fp) - { - const char *t_; - char *o_; - - if (!fgets(buffer, sizeof(buffer), fp)) - { - fclose(fp); - return; - } - if (strcmp(buffer, "[Angband config, Musus' port]\n")) - { - fclose(fp); - return; - } - - /* Load choices */ - while (fgets(buffer, sizeof(buffer), fp)) - { - t_ = strtok(buffer, " "); /* Term number (or keyword, "Gamma", etc.) */ - o_ = strtok(NULL, "\n"); /* argument string */ - if (!o_) - { - o_ = ""; - } /* missing (or null) argument? */ - if (t_) - { - if (!strcmp(t_, "Gamma")) - gamma = atof(o_); - else if (!strcmp(t_, "Monochrome")) - force_mono = !strcmp(o_, "on"); - else if (!strcmp(t_, "Sound")) - enable_sound = !strcmp(o_, "on"); - else if (!strcmp(t_, "Volume")) - sound_volume = atoi(o_); - else if (!strcmp(t_, "FullScreen")) - start_fullscreen = !strcmp(o_, "on"); - else if (!strcmp(t_, "Hourglass")) - use_glass = !strcmp(o_, "on"); - else if (!strcmp(t_, "HackFlush")) - hack_flush = !strcmp(o_, "on"); - else if (!strcmp(t_, "AlarmTimeH")) - alarm_h = atoi(o_); - else if (!strcmp(t_, "AlarmTimeM")) - alarm_m = atoi(o_); - else if (!strcmp(t_, "AlarmText")) - strcpy(alarm_message, o_); - else if (!strcmp(t_, "AlarmBeep")) - alarm_beep = !strcmp(o_, "on"); - else if (!strcmp(t_, "AlarmType")) - { - int i; - for (i = 0; i < 4; i++) - if (!strcmp(alarm_types[i], o_)) - alarm_type = i; - } - else if (isdigit((unsigned char)*t_)) - { - int t = atoi(t_); - if (t >= 0 && t < MAX_TERM_DATA) - { - char *f_, *x0_, *y0_, *x1_, *y1_, *sx_, *sy_; - o_ = strtok(o_, " "); /* first word */ - f_ = strtok(NULL, " "); /* font name */ - x0_ = strtok(NULL, " "); /* x posn (min) */ - y0_ = strtok(NULL, " "); /* y posn (min) */ - x1_ = strtok(NULL, " "); /* x posn (max) */ - y1_ = strtok(NULL, " "); /* y posn (max) */ - sx_ = strtok(NULL, " "); /* x scroll offset */ - sy_ = strtok(NULL, "\n"); /* y scroll offset */ - data[t].def_open = (t == 0) || atoi(o_); - data[t].def_pos.min.x = atoi(x0_); - data[t].def_pos.min.y = atoi(y0_); - data[t].def_pos.max.x = atoi(x1_); - data[t].def_pos.max.y = atoi(y1_); - data[t].def_scroll.x = atoi(sx_); - data[t].def_scroll.y = atoi(sy_); - data[t].unopened = 1; /* ie. force def_pos */ -#ifndef FULLSCREEN_ONLY - attach_font_to_term(&(data[t]), f_); -#endif /* FULLSCREEN_ONLY */ - } - } - } - } - fclose(fp); - } - -#ifndef FULLSCREEN_ONLY - /* - | Fudge so that the main term is *always* fullsize - */ - { - int fw, fh; - - set_up_zrb(&(data[0])); - fw = zrb.r_charw << screen_eig.x; - fh = zrb.r_charh << screen_eig.y; - if (zrb.r_flags.bits.double_height) - { - fh *= 2; - } - fw *= 80; - fh *= 24; - data[0].def_pos.max.x = data[0].def_pos.min.x + fw; - data[0].def_pos.max.y = data[0].def_pos.min.y + fh; - data[0].def_scroll.x = 0; - data[0].def_scroll.y = 0; - } -#endif /* FULLSCREEN_ONLY */ - - -} - - - - -static void save_choices(void) -{ - FILE *fp = NULL; - FILE *fpm = NULL; - char *cf; - int i; - - write_alarm_choices(); - - cf = find_choices(TRUE); - if (!*cf) - { - plog("Failed to locate writable choices file!"); - return; - } - - fp = fopen(cf, "w"); - if (!fp) - { - plog("Can't write choices file"); - return; - } - - fpm = fopen(find_choices_mirror(), "w"); - - f2printf(fp, fpm, "[Angband config, Musus' port]\n"); - f2printf(fp, fpm, "Gamma %.2lf\n", gamma); - f2printf(fp, fpm, "Monochrome %s\n", force_mono ? "on" : "off"); - f2printf(fp, fpm, "Sound %s\n", enable_sound ? "on" : "off"); - f2printf(fp, fpm, "Volume %d\n", sound_volume); - f2printf(fp, fpm, "FullScreen %s\n", start_fullscreen ? "on" : "off"); - f2printf(fp, fpm, "Hourglass %s\n", use_glass ? "on" : "off"); - f2printf(fp, fpm, "HackFlush %s\n", hack_flush ? "on" : "off"); - - for (i = 0; i < MAX_TERM_DATA; i++) - { - window_state ws; - Wimp_GetWindowState(data[i].w, &ws); - f2printf(fp, fpm, "%d %d %s ", i, ws.flags.data.open, - data[i].font->name); - f2printf(fp, fpm, "%d ", ws.openblock.screenrect.min.x); - f2printf(fp, fpm, "%d ", ws.openblock.screenrect.min.y); - f2printf(fp, fpm, "%d ", ws.openblock.screenrect.max.x); - f2printf(fp, fpm, "%d ", ws.openblock.screenrect.max.y); - f2printf(fp, fpm, "%d %d\n", ws.openblock.scroll.x, - ws.openblock.scroll.y); - } - - fclose(fp); - - if (fpm) - { - fclose(fpm); - } -} - -/* - | Update the Alarm choices file to reflect changed alarm settings. - */ -static void write_alarm_choices(void) -{ - FILE *fp; - char *cf; - - /* Open the choices file for reading */ - cf = find_alarmfile(TRUE); - if (!*cf) - { - plog("Can't determine Alarm file location!"); - return; - } - - fp = fopen(cf, "w"); - if (!fp) - { - plog("Can't write Alarm file"); - return; - } - - /* Write the new alarm options */ - fprintf(fp, "AlarmType %s\n", alarm_types[alarm_type]); - fprintf(fp, "AlarmTimeH %d\n", alarm_h); - fprintf(fp, "AlarmTimeM %d\n", alarm_m); - fprintf(fp, "AlarmText %s\n", alarm_message); - fprintf(fp, "AlarmBeep %s\n", alarm_beep ? "on" : "off"); - - fclose(fp); -} - -/* - | Read the Alarm choices file. - */ -static void read_alarm_choices(void) -{ - char buffer[260]; - FILE *fp; - char *cf; - - cf = find_alarmfile(FALSE); - if (!*cf) - { - return; - } - - fp = fopen(cf, "r"); - if (fp) - { - const char *t_, *o_; - /* Load choices */ - while (fgets(buffer, sizeof(buffer), fp)) - { - t_ = strtok(buffer, " "); /* Keyword */ - o_ = strtok(NULL, "\n"); /* argument string */ - if (!o_) - { - o_ = ""; - } /* missing (or null) argument? */ - if (t_) - { - if (!strcmp(t_, "AlarmTimeH")) - alarm_h = atoi(o_); - else if (!strcmp(t_, "AlarmTimeM")) - alarm_m = atoi(o_); - else if (!strcmp(t_, "AlarmText")) - strcpy(alarm_message, o_); - else if (!strcmp(t_, "AlarmBeep")) - alarm_beep = !strcmp(o_, "on"); - else if (!strcmp(t_, "AlarmType")) - { - int i; - for (i = 0; i < 4; i++) - if (!strcmp(alarm_types[i], o_)) - alarm_type = i; - } - } - } - fclose(fp); - } -} - - - -#ifndef FULLSCREEN_ONLY -/* - | Handle selections from the term menu(s) - */ -static BOOL Hnd_TermMenu(event_pollblock * pb, void *ref) -{ - mouse_block mb; - int i; - - Wimp_GetPointerInfo(&mb); - - switch (pb->data.selection[0]) - { - case TERM_MENU_INFO: /* Info> */ - break; - case TERM_MENU_FONT: /* Font> */ - /* Sub item selected? */ - if (pb->data.selection[1] == -1) - { - break; - } - handle_font_selection(pb->data.selection + 1); - break; - case TERM_MENU_WINDOWS: /* Windows> */ - if (pb->data.selection[1] == -1) - { - break; - } - i = pb->data.selection[1]; - { - window_state ws; - Wimp_GetWindowState(data[i].w, &ws); - if (ws.flags.data.open) - { - if (!i) - Hnd_MainClose(NULL, (void *)TRUE); - else - Window_Hide(data[i].w); - } - else - { - if (!i) - { - show_windows(); - grab_caret(); - } - else - { - if (!data[i].unopened) - { - Window_Show(data[i].w, open_WHEREVER); - } - else - { - window_openblock ob; - ob.window = data[i].w; - ob.screenrect = data[i].def_pos; - ob.scroll = data[i].def_scroll; - ob.behind = -1; /* could use data[0].w; ? */ - Wimp_OpenWindow(&ob); - data[i].unopened = 0; - } - } - } - } - break; - } - - if (mb.button.data.adjust) - { - set_up_term_menu(menu_term); - Menu_ShowLast(); - } - - return TRUE; -} - - - - - - -/* - | Handle selections from the iconbar menu - */ -static BOOL Hnd_IbarMenu(event_pollblock * pb, void *ref) -{ - mouse_block mb; - Wimp_GetPointerInfo(&mb); - - switch (pb->data.selection[0]) - { - case IBAR_MENU_INFO: /* Info> */ - break; - case IBAR_MENU_FULLSCREEN: /* Full screen */ - /* Do Full Screen mode */ - enter_fullscreen_mode(); - break; - case IBAR_MENU_GAMMA: /* Gamma correction */ - break; - case IBAR_MENU_SOUND: /* Sound */ - /* - | enable_sound = !enable_sound; - | if ( enable_sound ) { initialise_sound(); } - | Menu_SetFlags( ibar_menu, IBAR_MENU_SOUND, enable_sound, 0 ); - | set_sound_window_state(); - */ - break; - case IBAR_MENU_WINDOWS: /* Windows> */ - /* - | Hack: pass it off as the equivalent selection from - | the term menu. - */ - pb->data.selection[0] = TERM_MENU_WINDOWS; - return Hnd_TermMenu(pb, ref); - break; - case IBAR_MENU_SAVECHOICES: /* Save choices */ - save_choices(); - break; - case IBAR_MENU_QUIT: /* Quit */ - if (game_in_progress && character_generated) - save_player(); - quit(NULL); - break; - } - - if (mb.button.data.adjust) - Menu_ShowLast(); - - return TRUE; -} - - - - -/* - * Handler for NULL events (should this check the alarm in the desktop? - */ -static BOOL Hnd_null(event_pollblock *event, void *ref) -{ - /* Really no need to check the alarm more than once per second. */ - if (alarm_type && Time_Monotonic() > alarm_lastcheck + 100) - { - check_alarm(); - } - - return TRUE; -} - - - - - - - - -static BOOL Hnd_MenuSel(event_pollblock * pb, void *ref) -{ - if (menu_currentopen == ibar_menu) - return Hnd_IbarMenu(pb, ref); - else if (menu_currentopen == term_menu) - return Hnd_TermMenu(pb, ref); - return FALSE; -} - - -static BOOL Hnd_IbarClick(event_pollblock * pb, void *ref) -{ - if (pb->data.mouse.button.data.menu) - { - set_gamma_window_state(); - set_sound_window_state(); - - /* Hack: shade the Save> option if appropriate */ - if (game_in_progress && character_generated) - Menu_SetFlags(ibar_menu, IBAR_MENU_SAVE, 0, PDEADCHK); - else - Menu_SetFlags(ibar_menu, IBAR_MENU_SAVE, 0, TRUE); - - /* - | Hack: set up the Term menu as if it was opened over the main - | window (so that the Windows> submenu is set correctly) - */ - menu_term = (term_data *)&data[0]; - set_up_term_menu(menu_term); - - Menu_Show(ibar_menu, pb->data.mouse.pos.x, -1); - return TRUE; - } - - if (pb->data.mouse.button.data.select) - { - show_windows(); - grab_caret(); - return TRUE; - } - - if (pb->data.mouse.button.data.adjust) - { - enter_fullscreen_mode(); - return TRUE; - } - - return FALSE; -} - - - - - - -/* - | Handler for PreQuit messages (eg. at shutdown). - */ -static BOOL Hnd_PreQuit(event_pollblock * b, void *ref) -{ - BOOL shutdown = (b->data.message.data.words[0] & 1) == 0; - task_handle originator = b->data.message.header.sender; - unsigned int quitref; - message_block mb; - char buffer1[64]; - os_error e; - int ok; - - if (!(game_in_progress && character_generated)) - return TRUE; /* ignore, we're OK to die */ - - /* Stop the shutdown/quit */ - memcpy(&mb, &(b->data.message), 24); - quitref = mb.header.yourref; - mb.header.yourref = mb.header.myref; - Wimp_SendMessage(event_ACK, &mb, originator, 0); - - /* - | We handle this differently depending on the version of the Wimp; - | newer versions give us much more flexibility. - */ - if (event_wimpversion < 350) - { - /* - | Older versions - use 'OK' and 'Cancel'. - | There is no "Save & Quit" button. - */ - Msgs_Lookup("err.shuttitl:Query from %s", e.errmess, 64); - sprintf(buffer1, e.errmess, VARIANT); - Msgs_Lookup("err.shutdown:Unsaved game; are you sure you want to quit?", - e.errmess, 260); - e.errnum = 0; - SWI(3, 2, SWI_Wimp_ReportError, &e, 3 | 16, buffer1, NULL, &ok); - - if (ok != 1) - return TRUE; /* no! Pleeeeeease don't kill leeeeddle ol' me! */ - } - else - { - /* - | Newer version: can add buttons to the dialog. - | we add a 'Save and Quit' button to allow the shutdown to - | continue /after/ saving. - */ - int flags; - char buttons[64]; - - Msgs_Lookup("err.shutbuts:Save & quit,Don't quit,Quit anyway", - buttons, 64); - Msgs_Lookup("err.shuttitl:Query from %s", e.errmess, 64); - sprintf(buffer1, e.errmess, VARIANT); - Msgs_Lookup("err.shutdown:Unsaved game; are you sure you want to quit?", - e.errmess, 260); - e.errnum = 0; - - flags = 0 | 16 | 256 | (4 << 9); - - SWI(6, 2, SWI_Wimp_ReportError, &e, flags, buffer1, ICONNAME, 0, - buttons, NULL, &ok); - - if (ok == 4) - return TRUE; /* no! Pleeeeeease don't kill leeeeddle ol' me! */ - - if (ok == 3) - save_player(); /* Save & Quit */ - } - - - /* RO2 doesn't use the shudown flag */ - if (shutdown && event_wimpversion >= 300 && mb.header.size >= 24) - { - key_block kb; - kb.code = 0x1fc; /* restart shutdown sequence */ - Wimp_SendMessage(event_KEY, (message_block *) & kb, originator, 0); - } - - /* "Time... to die." */ - Event_CloseDown(); - exit(0); - return TRUE; /* The one great certainty (sic) */ -} - -#endif /* FULLSCREEN_ONLY */ - - - - -static void initialise_terms(void) -{ - char t[80]; - int i; - -#ifndef FULLSCREEN_ONLY - if (!minimise_memory) - { - /* Create a window for each term. Term 0 is special (no scroll bars) */ - data[0].w = Window_Create("angband", sizeof(angband_term_name[0])); - data[0].font = SYSTEM_FONT; - data[0].def_open = 1; - data[0].unopened = 1; - sprintf(t, "%s %s", VARIANT, VERSION); - Window_SetTitle(data[0].w, t); - strncpy(data[0].name, VARIANT, 12); - Event_Claim(event_KEY, data[0].w, event_ANY, Hnd_Keypress, - (void *)&(data[0])); - Event_Claim(event_REDRAW, data[0].w, event_ANY, Hnd_Redraw, - (void *)&(data[0])); - Event_Claim(event_CLICK, data[0].w, event_ANY, Hnd_TermClick, - (void *)&(data[0])); - Event_Claim(event_CLOSE, data[0].w, event_ANY, Hnd_MainClose, NULL); - - for (i = 1; i < MAX_TERM_DATA; i++) - { - data[i].w = Window_Create("term", template_TITLEMIN); - data[i].font = SYSTEM_FONT; - data[i].def_open = 0; - data[i].unopened = 1; -#ifndef OLD_TERM_MENU - sprintf(t, "%s (%s %s)", angband_term_name[i], VARIANT, VERSION); -#else - sprintf(t, "Term-%d (%s %s)", i, VARIANT, VERSION); -#endif - Window_SetTitle(data[i].w, t); - strncpy(data[i].name, t, 12); - Event_Claim(event_CLICK, data[i].w, event_ANY, Hnd_TermClick, - (void *)&(data[i])); - Event_Claim(event_REDRAW, data[i].w, event_ANY, Hnd_Redraw, - (void *)&(data[i])); - } - } -#endif /* FULLSCREEN_ONLY */ - - term_data_link(&(data[0]), 256); - - for (i = 1; i < MAX_TERM_DATA; i++) - { - term_data_link(&(data[i]), 16); - angband_term[i] = &(data[i].t); - } - - angband_term[0] = &(data[0].t); - Term_activate(&(data[0].t)); -} - - - - -/* - | Hack(ish) - determine the version of RISC OS - */ -static int os_version(void) -{ - int osv; - SWI(3, 2, SWI_OS_Byte, 129, 0, 255, NULL, &osv); - switch (osv) - { - case 0xa0: return 120; - case 0xa1: return 200; - case 0xa2: return 201; - case 0xa3: return 300; - case 0xa4: return 310; - case 0xa5: return 350; - case 0xa6: return 360; - case 0xa7: return 370; - case 0xa8: return 400; - default: return 370; - } - return -1; /* -sigh- */ -} - -#ifndef FULLSCREEN_ONLY -/* - | Determine whether the current screen mode is "high-res" - | (ie. should we use the "Sprites22" or the "Sprites" file. - */ -static int sprites22(void) -{ - int yeig; - - OS_ReadModeVariable(-1, modevar_YEIGFACTOR, &yeig); - - return yeig < 2; -} - -/* - | Determine whether we should use 2D or 3D templates. - | 2D templates *must* be used under Wimp <3.00, but under RO3 we - | use the CMOS settings to decide. - */ -static int templates2d(void) -{ - int r1, r2; - - if (event_wimpversion < 300) - return TRUE; - - /* The 3D bit is bit 0 of byte 140 */ - OS_Byte(osbyte_READCMOSRAM, 140, 0, &r1, &r2); - - return !(r2 && 1); -} -#endif /* FULLSCREEN_ONLY */ - - - -static unsigned int htoi(char *s) -{ - static const char hex[] = "0123456789ABCDEF"; - unsigned int v = 0; - while (*s) - { - char *m; - int d = toupper((unsigned char)*s++); - m = strchr(hex, d); - if (!m) - { - return v; - } - v = (v << 4) + (m - hex); - } - return v; -} - -static int read_unsigned(char *t) -{ - int r; - if (SWI(2, 3, SWI_OS_ReadUnsigned, 2, t, NULL, NULL, &r)) - r = 0; - return r; -} - -/* - | Scan the string at 'n', replacing dodgy characters with underbars - */ -static void sanitise_name(char *n) -{ - for (; *n; n++) - { - if (strchr("\"$%^&*\\\'@#.,", *n)) - *n = '_'; - } -} - - -/* - | Ensure that the path to a given object exists. - | Ie. if |p| = "a.b.c.d" then we attempt to - | create directories a, a.b and a.b.c if they don't - | already exist. - | Note that 'd' may be absent. - */ -static int ensure_path(char *p) -{ - char tmp[260]; - char *l = tmp; - - while (*p) - { - if (*p == '.') - { - *l = 0; - if (SWI(5, 0, SWI_OS_File, 8, tmp, 0, 0, 77)) - return 0; /* Eeek! */ - } - *l++ = *p++; - } - - return 1; -} - - -/* - * Set up the Scrap, Choices and Alarm paths, trying for - * Choices:blah...,etc. by preference, but falling back on lib/xtra - * if need be. - */ -static void init_paths(void) -{ - char tmp[512]; - char subpath[128]; - char *v; - char *t; - - /* Form the sub-path we use for both Choices and Scrap dirs: */ - v = subpath + sprintf(subpath, "%s", VARIANT); - sanitise_name(subpath); - sprintf(v, ".%s", VERSION); - sanitise_name(v + 1); - - /* Do the Scrap path first: */ - *scrap_path = 0; - - /* Try for Wimp$ScrapDir... */ - t = getenv("Wimp$ScrapDir"); - if (t && *t) - { - sprintf(tmp, "%s.AngbandEtc.%s.", t, subpath); - if (ensure_path(tmp)) - { - strcpy(scrap_path, tmp); - } - } - - /* Couldn't use Wimp$ScrapDir, so fall back on lib.xtra.scrap */ - if (!*scrap_path) - { - sprintf(tmp, "%sxtra.scrap.", resource_path); - if (ensure_path(tmp)) - { - strcpy(scrap_path, tmp); - } - } - - /* Now set up the Choices and Alarm files: */ - - /* Read only Choices file is always lib.xtra.Choices */ - sprintf(choices_file[CHFILE_READ], "%sXtra.Choices", resource_path); - /* Default writable Choices file is the same */ - strcpy(choices_file[CHFILE_WRITE], choices_file[CHFILE_READ]); - /* No default mirror Choices file */ - strcpy(choices_file[CHFILE_MIRROR], ""); - - /* Read only Alarm file is always lib.xtra.Alarm */ - sprintf(alarm_file[CHFILE_READ], "%sXtra.Alarm", resource_path); - /* Default writable Alarm file is the same */ - strcpy(alarm_file[CHFILE_WRITE], alarm_file[CHFILE_READ]); - - /* Try to use Choices$Path, etc. for the others... */ - - t = getenv("Choices$Write"); /* Ie. where choices should be written */ - if (t && *t) - { - /* Choices file: */ - sprintf(tmp, "%s.AngbandEtc.%s", t, subpath); - if (ensure_path(tmp)) - { - /* Use for writable file: */ - strcpy(choices_file[CHFILE_WRITE], tmp); - /* Form 'mirror' filename: same path but with a fixed leafname */ - strcpy(v + 1, "Default"); - sprintf(tmp, "%s.AngbandEtc.%s", t, subpath); - strcpy(choices_file[CHFILE_MIRROR], tmp); - } - - /* Alarm file (doesn't involve subpath) */ - sprintf(tmp, "%s.AngbandEtc.Global.Alarm", t); - if (ensure_path(tmp)) - { - /* Use for read/writable file */ - strcpy(alarm_file[CHFILE_WRITE], tmp); - } - } -} - - - - - - - -/* - * Return the appropriate (full) pathname. - * - * For write ops, the read/write file is returned. - * - * For read ops, either the read/write file, the mirror file, - * or the read only file will be returned as appropriate. - */ -static char *find_choices(int write) -{ - if (write) - return choices_file[CHFILE_WRITE]; - - if (myFile_Size(choices_file[CHFILE_WRITE]) > 0) - return choices_file[CHFILE_WRITE]; - - if (myFile_Size(choices_file[CHFILE_MIRROR]) > 0) - return choices_file[CHFILE_MIRROR]; - - return choices_file[CHFILE_READ]; -} - -static char *find_choices_mirror(void) -{ - return choices_file[CHFILE_MIRROR]; -} - -static char *find_alarmfile(int write) -{ - if (write) - return alarm_file[CHFILE_WRITE]; - - if (myFile_Size(alarm_file[CHFILE_WRITE]) > 0) - return alarm_file[CHFILE_WRITE]; - - return alarm_file[CHFILE_READ]; -} - - - - -int main(int argc, char *argv[]) -{ - int i, j; - int start_full = 0; - char *arg_savefile = 0; - char *t; -#ifdef USE_DA - int da_font = 1, da_game = 1; -#endif - - atexit(final_acn); /* "I never did care about the little things." */ - - Start_Hourglass; - - /* Parse arguments */ - for (i = 1; i < argc; i++) - { - if (argv[i][0] == '-') - { - switch (tolower((unsigned char)argv[i][1])) - { - case 'm': - { - /* Minimise Memory */ - minimise_memory = 1; - - /* Break */ - break; - } - case 'c': /* -c[a][s][f][<n>] */ - for (j = 2; argv[i][j]; j++) - { - int on = isupper((unsigned char)argv[i][j]); - - switch (tolower((unsigned char)argv[i][j])) - { -#ifdef ABBR_FILECACHE - case 'a': abbr_filecache = - on; - break; - case 'f': abbr_tmpfile = - on; - break; -#endif -#ifdef SMART_FILECACHE - case 's': smart_filecache = - on; - break; -#endif - - case 'p': flush_scrap = - !on; - break; - - default: - if (isdigit((unsigned char)argv[i][j])) - { - max_file_cache_size = - atoi(argv[i] + j) << 10; - while (isdigit((unsigned char)argv[i][++j])) - ; - if (max_file_cache_size <= 0) - { - use_filecache = 0; - } - j--; - } - else - { - fprintf(stderr, "Unrecognised option: -c%s", - argv[i] + j); - exit(EXIT_FAILURE); - } - } - } - break; - case 'w': /* -waitrelease */ - hack_flush = 1; - break; - case 'e': /* -Evil */ - allow_iclear_hack = 1; - break; - case 's': /* -s<savefile> */ - if (argv[i][2]) - arg_savefile = argv[i] + 2; - break; - case 'f': /* -fullscreen */ - start_full = 1; - break; - case 'h': /* -hourglass */ - use_glass = 1; - break; - case 't': /* -T<filetype> */ - if (argv[i][2]) - vfiletype = htoi(argv[i] + 2); - break; -#ifdef USE_DA - case 'd': /* -df, -dg, -dc or -d : disable DAs */ - switch (tolower((unsigned char)argv[i][2])) - { - case 0: /* -d => disable both */ - da_font = da_game = 0; - break; - case 'f': /* -df => disable font only */ - da_font = 0; - break; - case 'g': /* -dg => disable game only */ - da_game = 0; - break; - } - break; -#endif - case '%': /* -%<debug_opts> */ - { - int v = read_unsigned(argv[i] + 2); - log_g_malloc = v & 1; - show_sound_alloc = v & 2; - } - break; - default: - fprintf(stderr, "Unrecognised option: %s", argv[i]); - exit(EXIT_FAILURE); - } - } - } - - /* 1.27 - new handling of -minimise-memory: */ -#ifndef FULLSCREEN_ONLY - if (minimise_memory) -#endif /* FULLSCREEN_ONLY */ - { - start_full = 1; - fs_quit_key_text = "(fullscreen only mode)"; - } -#ifdef USE_DA - init_memory(da_font, da_game); /* Set up dynamic areas, etc. if possible */ - - /* Install memory allocation hooks */ - ralloc_aux = g_malloc; - rnfree_aux = g_free; -#endif - - /* Install replacement error reporting routines */ - quit_aux = quit_hook; - plog_aux = plog_hook; - core_aux = core_hook; - - /* Expand the (Angband) resource path */ - t = getenv(RISCOS_VARIANT "$Path"); - if (!t || !*t) Msgs_ReportFatal(0, "A resources path could not be formed."); - strcpy(resource_path, t); - - /* Decide where scrap, choices and alarm files live: */ - init_paths(); - - /* Hack: if no savefile specified, use a default */ - if (!arg_savefile) - { - arg_savefile = malloc(strlen(resource_path) + 32); - if (!arg_savefile) - { - Msgs_ReportFatal(0, "err.mem"); - } - sprintf(arg_savefile, "%s%s", resource_path, ">Save.Savefile"); - } - - /* This crap appears here so that plog() will work properly before - init_acn() is called... */ - Resource_Initialise(RISCOS_VARIANT); - Msgs_LoadFile("Messages"); - -#ifndef FULLSCREEN_ONLY - if (!minimise_memory) - { - /* This is a hack to only call Event_Initialise3 under RO3 */ - if (os_version() < 300) - Event_Initialise(RISCOS_VARIANT); - else - Event_Initialise3(RISCOS_VARIANT, 300, message_list); - - EventMsg_Initialise(); - - /* - | This is a possible workaround for the FP regs getting - | bolloxed in the ! menu because the compiler sets them - | up before a call to Wimp_Poll if CSE optimisation is on. - | At the moment I've just turned off CSE for the function - | affected. - | - | event_mask.data.keepfpregisters = 1; - */ - - /* Load Templates */ - Template_Initialise(); - if (templates2d()) - Template_LoadFile("Templates2"); - else - Template_LoadFile("Templates"); - - /* Load Sprites */ - if (sprites22()) - resource_sprites = - Sprite_LoadFile("<" RISCOS_VARIANT "$Dir>.Sprites22"); - else - resource_sprites = Sprite_LoadFile("<" RISCOS_VARIANT "$Dir>.Sprites"); - } -#endif /* FULLSCREEN_ONLY */ - - Screen_CacheModeInfo(); - - /* Initialise some ZapRedraw stuff */ - initialise_palette(); - initialise_fonts(); /* Set up the fonts */ -#ifndef FULLSCREEN_ONLY - initialise_r_data(); /* Set up the r_data buffer */ - - if (!minimise_memory) - { - /* Initialise some Wimp specific stuff */ - init_gamma_window(); - init_sound_window(); - init_save_window(); - init_menus(); - ibar_icon = Icon_BarIcon(ICONNAME, iconbar_RIGHT); - - /* Global handlers */ - Event_Claim(event_OPEN, event_ANY, event_ANY, Handler_OpenWindow, NULL); - Event_Claim(event_CLOSE, event_ANY, event_ANY, Handler_CloseWindow, NULL); - Event_Claim(event_GAINCARET, event_ANY, event_ANY, Hnd_Caret, (void *)1); - Event_Claim(event_LOSECARET, event_ANY, event_ANY, Hnd_Caret, (void *)0); - Event_Claim(event_MENU, event_ANY, event_ANY, Hnd_MenuSel, NULL); - Event_Claim(event_CLICK, window_ICONBAR, ibar_icon, Hnd_IbarClick, NULL); - Event_Claim(event_CLICK, event_ANY, event_ANY, Hnd_Click, NULL); - EventMsg_Claim(message_PALETTECHANGE, event_ANY, Hnd_PaletteChange, NULL); - EventMsg_Claim(message_MODECHANGE, event_ANY, Hnd_ModeChange, NULL); - EventMsg_Claim(message_PREQUIT, event_ANY, Hnd_PreQuit, NULL); - - /* Initialise the sound stuff */ - initialise_sound(); - } -#endif /* FULLSCREEN_ONLY */ - - /* Initialise some Angband stuff */ - initialise_terms(); - load_choices(); - read_alarm_choices(); - init_file_paths(unixify_name(resource_path)); - - Start_Hourglass; /* Paranoia */ - - /* Hack - override the saved options if -F was on the command line */ - start_fullscreen |= start_full; - - /* hack so that the cursor is yellow if undefined */ - if (palette[CURSOR_COLOUR] == palette[0]) - { - angband_color_table[CURSOR_COLOUR][1] = (CURSOR_RGB & 0xff00) >> 8; - angband_color_table[CURSOR_COLOUR][2] = (CURSOR_RGB & 0xff0000) >> 16; - angband_color_table[CURSOR_COLOUR][3] = (CURSOR_RGB & 0xff000000) >> 24; - } - - /* Catch nasty signals */ - signals_init(); - /* use pref-acn.prf */ - ANGBAND_SYS = "acn"; - -#ifndef FULLSCREEN_ONLY - if (start_fullscreen) - { -#endif /* FULLSCREEN_ONLY */ - enter_fullscreen_mode(); -#ifndef FULLSCREEN_ONLY - } - else - { - Start_Hourglass; /* Paranoia */ - Hnd_ModeChange(NULL, NULL); /* Caches the various fonts/palettes */ - show_windows(); - grab_caret(); - - Event_Claim(event_NULL, event_ANY, event_ANY, Hnd_null, NULL); - - /* Wait for a null poll so that the windows can appear */ - do - { - Event_Poll(); - } - while (event_lastevent.type != 0); - } -#endif /* FULLSCREEN_ONLY */ - - /* Initialise Angband */ - Start_Hourglass; /* Paranoia */ - - strncpy(savefile, unixify_name(arg_savefile), sizeof(savefile)); - savefile[sizeof(savefile) - 1] = '\0'; - - use_sound = 1; - init_angband(); - initialised = 1; - game_in_progress = 1; -/* pause_line(23);*/ - flush(); - /* Stop_Hourglass; */ - play_game(FALSE); - - if (fullscreen_mode) leave_fullscreen_mode(); - - Stop_Hourglass; - - quit(NULL); - - return 0; - - debug("to stop the 'unused' warning :)"); -} - - - - - - - - - - - - - -/*--------------------------------------------------------------------------*/ -/* Stuff below here is for the full screen display */ -/*--------------------------------------------------------------------------*/ - -static errr Term_xtra_acn_checkFS(void); -static errr Term_xtra_acn_eventFS(void); -static errr Term_xtra_acn_reactFS(int force); -static errr Term_curs_acnFS(int x, int y); -static errr Term_xtra_acn_clearFS(void); -static errr Term_xtra_acnFS(int n, int v); -static errr Term_wipe_acnFS(int x, int y, int n); -static errr Term_text_acnFS(int x, int y, int n, byte a, cptr s); -static void bored(void); -static void redraw_areaFS(int x, int y, int w, int h); -static void draw_cursor(int x, int y); - -/* - | We use this to keep the mouse in the same place on return from full-screen - | mode. - */ -static wimp_point old_mouse_posn; - -/* - | Take a copy of the current mode descriptor/number and return either - | a pointer to it (as an int) if it's a new mode, or the mode number. - | NB: A static pointer is used and the descriptor returned is only - | valid until the next call to this function. - | - | Basically, a replacement for OS_Byte 135 / OS_ScreenMode1, IYSWIM. - */ -static int current_mode(void) -{ - static void *descriptor = NULL; - int mode; - int size; - int i; - int *vals; - - if (descriptor) - { - free(descriptor); - descriptor = NULL; - } - - SWI(1, 3, SWI_OS_Byte, 135, NULL, NULL, &mode); - if (mode < 256) - { - return mode; - } - - vals = (int *)(mode + 20); - for (i = 0; vals[i] != -1; i += 2) - ; - - size = 24 + 8 * i; /* Size of data */ - descriptor = malloc(size); - if (!descriptor) - { - core("Out of memory!"); - } - memcpy(descriptor, (void *)mode, size); - - return (int)descriptor; -} - - - -/* - | Select the best mode we can for full screen. - | Returns 12 for (low-res, ie. mode 12) or 27 for high-res, - | or a pointer to a mode descriptor (as an int). - */ -static int select_fullscreen_mode(void) -{ - static struct - { - int flags, x, y, l2bpp, hz, term; - } - desc; - int mode = 0; - - desc.flags = 1; /* format 0 */ - desc.x = 640; - desc.y = 480; /* 640x480 */ - desc.l2bpp = 2; /* 16 colours */ - desc.hz = -1; /* best we can get */ - desc.term = -1; /* don't fuss about modevars */ - - SWI(1, 1, SWI_OS_CheckModeValid, &desc, &mode); - if (mode != (int)&desc) - { - SWI(1, 1, SWI_OS_CheckModeValid, 27, /**/ &mode); - if (mode != 27) - { - SWI(1, 1, SWI_OS_CheckModeValid, 12, /**/ &mode); - if (mode != 12) - { - mode = 0; - } - } - } - - return mode; -} - - -/* - | Change screen mode - */ -static void change_screenmode(int to) -{ - if (SWI(2, 0, SWI_OS_ScreenMode, 0, to)) - { - if (to < 256) - { - GFX_VDU(22); - GFX_VDU(to); - } - else - { - /* Finished with my woman / cos she couldn't help me with ... */ - core("Eeek! mode isn't valid, but it /should/ be..."); - } - } -} - - -/* - | Constrain the mouse pointer to a point - this means that the damn - | hourglass won't move around with the mouse :) - */ -static void constrain_pointer(void) -{ - mouse_block ptr; - wimp_rect r; - int ys = screen_eig.y == 1 ? 32 : 64; /* Cope with dbl height glass */ - - Screen_CacheModeInfo(); /* Make sure we know the screen size */ - r.min.x = r.max.x = screen_size.x - 32; - r.min.y = r.max.y = screen_size.y - ys; - - /* Retrieve and store old (wimp) pointer position */ - Wimp_GetPointerInfo(&ptr); - old_mouse_posn = ptr.pos; - - Pointer_RestrictToRect(r); - - /* Turn the pointer off also */ - SWI(2, 0, SWI_OS_Byte, 106, 0); -} - -static void release_pointer() -{ - wimp_rect r; - - r.min.x = r.max.x = old_mouse_posn.x; - r.min.y = r.max.y = old_mouse_posn.y; - - Pointer_RestrictToRect(r); - - Pointer_Unrestrict(); - - /* Turn the pointer back on also */ - SWI(2, 0, SWI_OS_Byte, 106, 1); -} - - - - - -/* - | Convert a 1bpp bitmap into a 4bpp bitmap (bit flipped) - */ -static int byte_to_word_flipped(int b) -{ - int w; - if (b & 128) - { - w = 0xf0000000; - } - else - { - w = 0; - } - if (b & 64) - { - w |= 0x0f000000; - } - if (b & 32) - { - w |= 0x00f00000; - } - if (b & 16) - { - w |= 0x000f0000; - } - if (b & 8) - { - w |= 0x0000f000; - } - if (b & 4) - { - w |= 0x00000f00; - } - if (b & 2) - { - w |= 0x000000f0; - } - if (b & 1) - { - w |= 0x0000000f; - } - return w; -} - - - - -/* - | try to load the fallback fullscreen font and convert it to 4bpp - */ -static int cache_zapfontHR(void) -{ - int handle; - unsigned int extent; - char buffer[260]; - struct - { - char id[8]; - int w, h, f, l, r1, r2; - } - zfh; - int *op; - char *ip; - int l, i; - - /* Try to open the file */ - sprintf(buffer, "%s%s", resource_path, "xtra.FullScreen"); - handle = myFile_Open(buffer, 0x4f); - if (!handle) - { - return 0; - } - - /* Check file's extent */ - extent = myFile_Extent(handle); - if (extent > sizeof(zfh) + 256 * 16) - { - myFile_Close(handle); - return 0; - } - - /* Load the header */ - if (myFile_ReadBytes(handle, &zfh, sizeof(zfh))) - { - myFile_Close(handle); - return 0; - } - - /* Check font size */ - if ((zfh.w != 8) || (zfh.h > 16)) - { - myFile_Close(handle); - return 0; - } - - /* Load the 1bpp data */ - if (myFile_ReadBytes(handle, fullscreen_font, extent - sizeof(zfh))) - { - myFile_Close(handle); - return 0; - } - - myFile_Close(handle); - - l = zfh.l > 255 ? 255 : zfh.l; - - if (zfh.h > 8) - { - op = (int *)(((int)fullscreen_font) + (l + 1) * zfh.h * 4); - ip = (char *)(((int)fullscreen_font) + (l + 1) * zfh.h - - (zfh.f * zfh.h)); - while (l-- >= zfh.f) - { - for (i = 0; i < zfh.h; i++) - { - *--op = byte_to_word_flipped(*--ip); - } - } - fullscreen_height = zfh.h; - } - else - { - op = (int *)(((int)fullscreen_font) + (l + 1) * zfh.h * 8); - ip = (char *)(((int)fullscreen_font) + (l + 1) * zfh.h - - (zfh.f * zfh.h)); - while (l-- >= zfh.f) - { - for (i = -zfh.h; i < zfh.h; i++) - { - int t = byte_to_word_flipped(*--ip); - *--op = t; - *--op = t; - } - } - fullscreen_height = zfh.h * 2; - } - - fullscreen_topline = TERM_TOPLINE_HR; - fullscreen_topline += ((16 - fullscreen_height) * 13); - - return 1; -} - - - - - -static int cache_fs_fontHR(void) -{ - ZapFont *src = SYSTEM_FONT; - int c; - int *op; - char *ip; - - /* Allocate the storage for the font */ - fullscreen_font = f_malloc(256 * 4 * 16); - if (!fullscreen_font) - { - return 0; - } - op = (int *)fullscreen_font; - - /* Check to see if the main term's font is suitable (ie. 8x16 or 8x8) */ - if ((data[0].font->w == 8) && (data[0].font->h <= 16)) - src = data[0].font; - - /* - | Hack: if we're forced to use the system font, try to load the - | 'fullscreen' font from lib.xtra. If that fails, then I guess we're - | stuck with the system font. - */ - - if (src == SYSTEM_FONT) - if (cache_zapfontHR()) - { - return 1; - } - - ip = (char *)(src->bpp_1); - - /* Now, create the font */ - if (src->h > 8) - { - int e = src->h * (src->l > 256 ? 256 : src->l); - op += (src->f * src->h); - for (c = src->f * src->h; c < e; c++) - *op++ = byte_to_word_flipped(*ip++); - fullscreen_height = src->h; - } - else - { - int e = src->h * (src->l > 256 ? 256 : src->l); - op += (src->f * src->h) * 2; - for (c = src->f * src->h; c < e; c++) - { - int t = byte_to_word_flipped(*ip++); - *op++ = t; - *op++ = t; - } - fullscreen_height = src->h * 2; - } - - fullscreen_topline = TERM_TOPLINE_HR; - fullscreen_topline += ((16 - fullscreen_height) * 13); - - return 1; -} - - - - - -static int cache_fs_fontLR(void) -{ - ZapFont *src = SYSTEM_FONT; - int c, e; - int *op; - char *ip; - - /* Allocate the storage for the font */ - fullscreen_font = f_malloc(256 * 4 * 8); - if (!fullscreen_font) - { - return 0; - } - op = (int *)fullscreen_font; - - /* Check to see if the main term's font is suitable (ie. 8x8) */ - if ((data[0].font->w == 8) && (data[0].font->h <= 8)) - src = data[0].font; - - ip = (char *)(src->bpp_1); - - /* Now, create the font */ - e = src->h * (src->l > 256 ? 256 : src->l); - op += (src->f * src->h); - for (c = src->f * src->h; c < e; c++) - *op++ = byte_to_word_flipped(*ip++); - - fullscreen_height = src->h; - fullscreen_topline = TERM_TOPLINE_LR; - fullscreen_topline += ((8 - fullscreen_height) * 13); - - return 1; -} - - - -static void set_keys(int claim) -{ - static int old_c_state; - static int old_f_state[8]; - int i; - - if (claim) - { - /* Cursors/copy act as function keys */ - /* f0-f9, cursors, generate 0x80-0x8f */ - /* sh-f0-f9,cursors, generate 0x90-0x9f */ - /* ctrl f0-f9,cursors, generate 0xa0-0xaf */ - /* sh-c-f0-f9,cursors, generate 0xb0-0xbf */ - /* f10-f12 generate 0xca-0xcc */ - /* shift f10-f12 generate 0xda-0xdc */ - /* ctrl f10-f12 generate 0xea-0xec */ - /* ctrlshift f10-f12 generate 0xfa-0xfc */ - - SWI(3, 2, SWI_OS_Byte, 4, 2, 0, /**/ NULL, &old_c_state); - - for (i = 0; i < 4; i++) - { - SWI(3, 2, SWI_OS_Byte, 225 + i, 0x80 + (i * 0x10), 0, NULL, - old_f_state + i); - SWI(3, 2, SWI_OS_Byte, 221 + i, 0xc0 + (i * 0x10), 0, NULL, - old_f_state + i + 4); - } - } - else - { - SWI(3, 0, SWI_OS_Byte, 4, old_c_state, 0); - for (i = 0; i < 4; i++) - { - SWI(3, 0, SWI_OS_Byte, 225 + i, old_f_state[i], 0); - SWI(3, 0, SWI_OS_Byte, 221 + i, old_f_state[i + 4], 0); - } - } -} - - - - - - -/* - | Enter the full screen mode. - | - | Full screen display uses either mode 27 (if supported) and 8x16 fonts - | (or system font 'twiddled' to double height), or mode 12 (if mode 27 - | is unavailable) and the system font (or an 8x8 font). - | - */ - -static void enter_fullscreen_mode(void) -{ - int vduvars[2] = - { 149, -1 }; - int i; - - /* New in 1.18 - protect against 're-entracy' */ - if (fullscreen_font) - return; - - /* New in 1.20 - hack IClear out of the way */ - if (allow_iclear_hack) - iclear_hack(); - - /* Choose the mode we want */ - fullscreen_mode = select_fullscreen_mode(); - - if (!fullscreen_mode) - { - plog("Unable to select a suitable screen mode (27 or 12)"); - return; - } - - if (!((fullscreen_mode == 12) ? cache_fs_fontLR() : cache_fs_fontHR())) - { - plog("Unable to cache a font for full screen mode"); - return; - } - - /* Read the current screen mode */ - /* SWI( 1,3, SWI_OS_Byte, 135, NULL, NULL, &old_screenmode ); */ - old_screenmode = current_mode(); - - Stop_Hourglass; - - /* Change to the chosen screen mode */ - change_screenmode(fullscreen_mode); - - /* Restrict the pointer */ - constrain_pointer(); - - /* Remove the cursors */ - SWI(0, 0, SWI_OS_RemoveCursors); - - Start_Hourglass; - - /* Get the base address of screen memory */ - SWI(2, 0, SWI_OS_ReadVduVariables, vduvars, vduvars); - fullscreen_base = (int *)(vduvars[0]); - - /* Fudge the Term interface */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - term *t = &(data[i].t); - t->xtra_hook = Term_xtra_acnFS; - t->wipe_hook = Term_wipe_acnFS; - t->curs_hook = Term_curs_acnFS; - t->text_hook = Term_text_acnFS; - } - - /* Grab the palette */ - Term_xtra_acn_reactFS(TRUE); - - /* Make sure that the keys work properly */ - set_keys(TRUE); - - /* refresh the term */ - /*Term_activate( &(data[0].t) ); */ - redraw_areaFS(0, 0, 80, 24); - if (data[0].cursor.visible) - draw_cursor(data[0].cursor.pos.x, data[0].cursor.pos.y); - - /* Display a reminder of how to get back... */ - /* Hack: disable force_mono */ - i = force_mono; - force_mono = 0; - Term_text_acnFS(0, TIME_LINE, strlen(fs_quit_key_text), 8, - fs_quit_key_text); - force_mono = i; -} - - - - -static void leave_fullscreen_mode(void) -{ - int i; - - /* New in 1.18 - protect against 're-entracy' */ - if (!fullscreen_font) - return; - - /* Restore the Term interface */ - for (i = 0; i < MAX_TERM_DATA; i++) - { -#ifndef FULLSCREEN_ONLY - term *t = &(data[i].t); - t->xtra_hook = Term_xtra_acn; - t->wipe_hook = Term_wipe_acn; - t->curs_hook = Term_curs_acn; - t->text_hook = Term_text_acn; -#endif - mark_ood(&(data[i]), 0, 0, 80, 24); - } - - /* Deallocate the font */ - f_free(fullscreen_font); - fullscreen_font = 0; - fullscreen_mode = 0; - - Stop_Hourglass; - - /* Restore the screen mode */ - Wimp_SetMode(old_screenmode); - - /* Restore the pointer */ - release_pointer(); - - Start_Hourglass; - - /* Restore the various soft keys */ - set_keys(FALSE); - - /* New in 1.20 Remove the IClear hack */ - if (allow_iclear_hack) - remove_iclear_hack(); - -#ifndef FULLSCREEN_ONLY - /* Refresh the windows - this probably isn't necessary anyway */ - if (!minimise_memory) - refresh_windows(); -#endif /* FULLSCREEN_ONLY */ -} - - - - - -static void fs_writechars(int x, int y, int n, const char *chars, char attr) -{ - int *scr, *scrb; - int *cdat; - int j; - unsigned int fgm; - - if (force_mono) - { - if (attr != TERM_DARK) - { - attr = TERM_WHITE; - } - } - fgm = (unsigned int)zpalette[(unsigned int) attr]; - - scrb = (int *)(((int)fullscreen_base) + y * fullscreen_height * 320 - + x * 4 + 320 * fullscreen_topline); - - while (n--) - { - scr = scrb++; - cdat = (int *)(((int)fullscreen_font) - + (*chars++) * (fullscreen_height << 2)); - for (j = 0; j < fullscreen_height; j++) - { - *scr = *cdat++ & fgm; - scr += 80; - } - } -} - - -static void fs_writechar(int x, int y, char c, char attr) -{ - int *scrb; - int *cdat; - int j; - unsigned int fgm; - - if (force_mono) - { - if (attr != TERM_DARK) - { - attr = TERM_WHITE; - } - } - fgm = (unsigned int)zpalette[(unsigned int) attr]; - - scrb = (int *)(((int)fullscreen_base) + y * fullscreen_height * 320 - + x * 4 + 320 * fullscreen_topline); - cdat = (int *)(((int)fullscreen_font) + (c * (fullscreen_height << 2))); - for (j = 0; j < fullscreen_height; j++) - { - *scrb = *cdat++ & fgm; - scrb += 80; - } -} - - - -static void draw_cursorHR(int x, int y) -{ - ColourTrans_SetGCOL(cursor_rgb, 0, 0); - GFX_Move(x * 16, - 959 - y * (fullscreen_height * 2) - fullscreen_topline * 2); - GFX_DrawBy(14, 0); - GFX_DrawBy(0, -(fullscreen_height * 2 - 2)); - GFX_DrawBy(-14, 0); - GFX_DrawBy(0, fullscreen_height * 2 - 2); -} - -static void draw_cursorLR(int x, int y) -{ - ColourTrans_SetGCOL(cursor_rgb, 0, 0); - GFX_Move(x * 16, - 1023 - y * (fullscreen_height * 4) - fullscreen_topline * 4); - GFX_DrawBy(14, 0); - GFX_DrawBy(0, -(fullscreen_height * 4 - 4)); - GFX_DrawBy(-14, 0); - GFX_DrawBy(0, fullscreen_height * 4 - 4); -} - - - - - -static void draw_cursor(int x, int y) -{ - if (fullscreen_mode == 12) - draw_cursorLR(x, y); - else - draw_cursorHR(x, y); -} - - - -static void redraw_areaFS(int x, int y, int w, int h) -{ - int i, j; - for (j = y; j < y + h; j++) - for (i = x; i < x + w; i++) - fs_writechar(i, j, data[0].t.old->c[j][i], data[0].t.old->a[j][i]); -} - - - -static int wimp_code(int c) -{ - /* shift/ctrl keypad? */ - if (c >= '0' && c <= '9') - { - kbd_modifiers m = Kbd_GetModifiers(FALSE); - if (m.shift) - { - c |= 0x800; - } - if (m.ctrl) - { - c |= 0x400; - } - return c; - } - if (c == 9) - { - return 0x18a; - } /* Tab */ - if (c <= 127) - { - return c; - } /* normal ASCII/ctrl */ - if (c >= 0x80 && c <= 0xff) - { - return c + 0x100; - } /* f0-f9, etc. */ - - return -1; /* unknown */ -} - - - - -static void do_keypress(int code) -{ - static const char hex[] = "0123456789ABCDEF"; - - if (code == KEYPRESS_QUIT && !minimise_memory) - { -#ifdef FULLSCREEN_ONLY - Sound_SysBeep(); -#else - leave_fullscreen_mode(); -#endif - return; - } - - if (code == 27) - { - if (Kbd_KeyDown(inkey_CTRL)) - { - ack_alarm(); - return; - } - } - - if (code <= 255) - { - Term_keypress(code); - } - else - { - Term_keypress(31); - Term_keypress(hex[(code & 0xf00) >> 8]); - Term_keypress(hex[(code & 0x0f0) >> 4]); - Term_keypress(hex[(code & 0x00f)]); - Term_keypress(13); - } -} - - - - -static errr Term_xtra_acn_checkFS(void) -{ - int bh, bl; - int c; - - Stop_Hourglass; - - bored(); - - SWI(3, 3, SWI_OS_Byte, 128, 255, 0, /**/ NULL, &bl, &bh); - bl = (bl & 0xff) + (bh << 8); - - if (bl > 0) - { - SWI(0, 1, SWI_OS_ReadC, &c); - bl = wimp_code(c); - if (bl >= 0) - { - do_keypress(bl); - } - } - - Start_Hourglass; - - return 0; -} - - - - -static errr Term_xtra_acn_eventFS(void) -{ - int c; - int w = -1; - - Stop_Hourglass; - - for (w = -1; w == -1;) - { - int bh, bl; - do - { - bored(); - SWI(3, 3, SWI_OS_Byte, 128, 255, 0, /**/ NULL, &bl, &bh); - bl = (bl & 0xff) + (bh << 8); - } - while (!bl); - - SWI(0, 1, SWI_OS_ReadC, &c); - w = wimp_code(c); - if (w >= 0) - { - do_keypress(w); - } - } - - Start_Hourglass; - - return 0; -} - - - -/* - * React to changes - */ -static errr Term_xtra_acn_reactFS(int force) -{ - unsigned int i; - int p, r, g, b; - - static double old_gamma = -1.0; - - if (gamma != old_gamma) - { - force = 1; - old_gamma = gamma; - } - - /* Set the screen colours */ - for (i = 0; i < 16; i++) - { - if (COLOUR_CHANGED(i) || force) - { - r = (int)(255.0 * - pow(angband_color_table[i][1] / 255.0, 1.0 / gamma)); - g = (int)(255.0 * - pow(angband_color_table[i][2] / 255.0, 1.0 / gamma)); - b = (int)(255.0 * - pow(angband_color_table[i][3] / 255.0, 1.0 / gamma)); - GFX_VDU(19); - GFX_VDU(i); - GFX_VDU(16); - GFX_VDU(r); - GFX_VDU(g); - GFX_VDU(b); - - palette[i] = (b << 24) | (g << 16) | (r << 8); - p = i; - p |= (p << 4); - p |= (p << 8); - p |= (p << 16); - zpalette[i] = p; - - a_palette[i][1] = angband_color_table[i][1]; - a_palette[i][2] = angband_color_table[i][2]; - a_palette[i][3] = angband_color_table[i][3]; - - /* Find any higher colour numbers and make them "wrong" */ - for (p = 16; p < 256; p++) - if ((zpalette[p] & 0xf) == i) - a_palette[p][1] = angband_color_table[p][1] + 2; - } - } - - - /* Go through the palette updating any changed values */ - for (i = 16; i < 256; i++) - { - if (COLOUR_CHANGED(i) || force) - { - r = (int)(255.0 * - pow(angband_color_table[i][1] / 255.0, 1.0 / gamma)); - g = (int)(255.0 * - pow(angband_color_table[i][2] / 255.0, 1.0 / gamma)); - b = (int)(255.0 * - pow(angband_color_table[i][3] / 255.0, 1.0 / gamma)); - p = (b << 24) | (g << 16) | (r << 8); - palette[i] = p; - SWI(1, 1, SWI_ColourTrans_ReturnColourNumber, palette[i], &p); - p |= (p << 4); - p |= (p << 8); - p |= (p << 16); - zpalette[i] = p; - a_palette[i][1] = angband_color_table[i][1]; - a_palette[i][2] = angband_color_table[i][2]; - a_palette[i][3] = angband_color_table[i][3]; - } - } - - cursor_rgb = palette[CURSOR_COLOUR]; - - return 0; -} - - -static errr Term_curs_acnFS(int x, int y) -{ - if (Term == &(data[0].t)) - { - if (data[0].cursor.visible) - redraw_areaFS(data[0].cursor.pos.x, data[0].cursor.pos.y, 1, 1); - data[0].cursor.pos.x = x; - data[0].cursor.pos.y = y; - if (data[0].cursor.visible) - draw_cursor(x, y); - } - return 0; -} - -static errr Term_xtra_acn_clearFS(void) -{ - char e[80]; - int j; - - if (Term == &(data[0].t)) - { - for (j = 0; j < 80; j++) - e[j] = ' '; - - GFX_Wait(); - - for (j = 0; j < 24; j++) - fs_writechars(0, j, 80, e, 0); - } - - return 0; -} - - - - - - - -static errr Term_xtra_acnFS(int n, int v) -{ - term_data *t = (term_data *)Term; - - switch (n) - { - case TERM_XTRA_CLEAR: - if (t == (&data[0])) - Term_xtra_acn_clearFS(); - return 0; - - case TERM_XTRA_EVENT: - if (v) - return Term_xtra_acn_eventFS(); - else - return Term_xtra_acn_checkFS(); - - case TERM_XTRA_BORED: - bored(); - return Term_xtra_acn_checkFS(); - - case TERM_XTRA_FLUSH: - /* 1.21 - Hack: wait until no keys are pressed */ - if (hack_flush) - for (v = 0; v != 0xff;) - SWI(1, 2, SWI_OS_Byte, 122, 0, &v); - SWI(3, 0, SWI_OS_Byte, 21, 0, 0); /* Flush Kbd buffer */ - return 0; - - case TERM_XTRA_FRESH: - return 0; - - case TERM_XTRA_FROSH: - return 0; - - case TERM_XTRA_SHAPE: - if (t == (&data[0])) - { - t->cursor.visible = v; - if (v) - draw_cursor(t->cursor.pos.x, t->cursor.pos.y); - else - redraw_areaFS(t->cursor.pos.x, t->cursor.pos.y, 1, 1); - } - return 0; - - case TERM_XTRA_NOISE: - Sound_SysBeep(); - return 0; - - case TERM_XTRA_REACT: - return Term_xtra_acn_reactFS(FALSE); - - case TERM_XTRA_DELAY: - if (v > 0) - { - int start = Time_Monotonic(); - v = (v + 5) / 10; /* Round to nearest cs */ - GFX_Wait(); - while ((Time_Monotonic() - start) < v) - ; - } - return (0); - - case TERM_XTRA_SOUND: /* Play a sound :) */ - if (enable_sound) - { - play_sound(v); - } - return 0; - - /* Subdirectory scan */ - case TERM_XTRA_SCANSUBDIR: - { - filing_dirdata directory; - filing_direntry *entry; - - scansubdir_max = 0; - - if (Filing_OpenDir(riscosify_name(scansubdir_dir), &directory, sizeof(filing_direntry), readdirtype_DIRENTRY) != NULL) - { - Error_Report(0, "Couldn't open directory \"%s\"", riscosify_name(scansubdir_dir)); - return 0; - } - - while ((entry = Filing_ReadDir(&directory)) != NULL) - { - if (entry->objtype == filing_DIRECTORY) - { - string_free(scansubdir_result[scansubdir_max]); - scansubdir_result[scansubdir_max] = string_make(entry->name); - ++scansubdir_max; - } - } - - Filing_CloseDir(&directory); - - return 0; - } - - /* Return current "time" in milliseconds */ - case TERM_XTRA_GET_DELAY: - { - Term_xtra_long = Time_Monotonic() * 100; - - return 0; - } - - /* Rename main window */ - case TERM_XTRA_RENAME_MAIN_WIN: - { - Window_SetTitle(data[0].w, angband_term_name[0]); - return 0; - } - - default: - return 1; - } -} - -static errr Term_wipe_acnFS(int x, int y, int n) -{ - if (Term == &(data[0].t)) - while (n--) - fs_writechar(x++, y, ' ', 0); - return 0; -} - -static errr Term_text_acnFS(int x, int y, int n, byte a, cptr s) -{ - if (Term == &(data[0].t)) - fs_writechars(x, y, n, s, (char)a); - return 0; -} - - - -static void bored() -{ - static int last = -1; - char ts[80]; - time_t ct; - struct tm *lt; - unsigned int l; - int ofm; - static int alarm_flash = 1; - - /* Really no need to check the alarm more than once per second. */ - if (alarm_type && Time_Monotonic() > alarm_lastcheck + 100) - { - check_alarm(); - } - - l = Time_Monotonic(); - if ((l - last) < (alarm_flash ? 25 : 50)) - { - return; - } - last = l; - - time(&ct); - lt = localtime(&ct); - l = strftime(ts, 80, "%c %Z", lt); - - /* Hack: disable force_mono around printing the time */ - ofm = force_mono; - force_mono = 0; - - /* Hack: Is the alarm supposed to be going off? */ - if (alarm_disp || alarm_flash) - { - char blk[60]; - int c = 8; - if (!alarm_disp) - { - alarm_flash = 11; - } - switch (alarm_flash / 2) - { - case 4: sprintf(blk, "%-57s", alarm_cancel_text); - break; - case 5: sprintf(blk, "%-57s", fs_quit_key_text); - break; - default: - c = alarm_flash & 1 ? TERM_RED : TERM_WHITE; - sprintf(blk, "%02d:%02d %-51s", alarm_h, alarm_m, - alarm_message); - } - fs_writechars(0, TIME_LINE, 57, blk, c); - if (++alarm_flash > 11) - { - alarm_flash = 0; - } - } - - /* Display time */ - fs_writechar(79 - l, TIME_LINE, ' ', 0); - fs_writechars(80 - l, TIME_LINE, l, ts, 8); - - force_mono = ofm; -} - - - - - - -#ifdef USE_DA -/*--------------------------------------------------------------------------*/ -/* (Simple) Heap management (using OS_Heap) */ -/*--------------------------------------------------------------------------*/ - -typedef void *heap; - -static os_error *Heap_Initialise(heap h, size_t size) -{ - return SWI(4, 0, SWI_OS_Heap, 0, h, 0, size); -} - -static void *Heap_Claim(heap h, size_t size) -{ - void *fred; - os_error *e; - e = SWI(4, 3, SWI_OS_Heap, 2, h, 0, size, NULL, NULL, &fred); - return e ? NULL : fred; -} - -static os_error *Heap_Release(heap h, void *block) -{ - return SWI(3, 0, SWI_OS_Heap, 3, h, block); -} - -static int Heap_ChangeHeapSize(heap h, int resize_by) -{ - int by; - SWI(4, 4, SWI_OS_Heap, 5, h, 0, resize_by, 0, 0, 0, &by); - return by; -} - - - -/*--------------------------------------------------------------------------*/ -/* Stuff below here is for using Dynamic areas (under RO3.5+) */ -/*--------------------------------------------------------------------------*/ - -static int game_area = -1; /* The DA the game is using */ -static int font_area = -1; /* The DA the fonts are using */ - -static void *game_area_base; /* base address of game area */ -static void *font_area_base; /* base address of font area */ - -static int font_area_size; /* size of the fonts' DA */ -static int font_heap_size; /* size of the fonts' heap */ -static int game_area_size; /* size of the game's DA */ -static int game_heap_size; /* size of the game's heap */ - -#define MAX_F_DA_SIZE (2<<20) /* Max size of font area (2Mb) */ -#define MAX_G_DA_SIZE (4<<20) /* Max size of game area (4Mb) */ -#define SHRINK_GRAN (4<<10) /* Try to recalaim wastage > this (4Kb) */ - - -/* - | Free dynamic areas when we exit - */ -static void cleanup_memory(void) -{ - if (game_area != -1) - { - SWI(2, 0, SWI_OS_DynamicArea, 1, game_area); - game_area = -1; - } - - if (font_area != -1) - { - SWI(2, 0, SWI_OS_DynamicArea, 1, font_area); - font_area = -1; - } - -} - - - -/* - | Set up the memory allocation stuff. - | We check to see if DAs are possible and if so initialise two: - | one for the game's use (via the rnalloc() hooks) and one for - | our own use (for fonts, etc). - | - | Each area is created 16Kb in size, with a max size of 2/4Mb. - | - | If 'daf' is TRUE, an area is created for the fonts. - | If 'dag' is TRUE, an area is created for the game. - */ -static void init_memory(int daf, int dag) -{ - os_error *e = NULL; - - if (!daf) - { - /* Paranoia */ - font_area = -1; - font_area_base = 0; - } - else - { - e = SWI(9, 4, SWI_OS_DynamicArea, 0, /* Create */ - -1, /* Let OS allocate no. */ - 16 << 10, /* Initial size */ - -1, /* Let OS allocate address */ - 1 << 7, /* Cacheable, bufferable, RW */ - MAX_F_DA_SIZE, /* Max size */ - 0, /* handler */ - 0, /* handler workspace */ - VARIANT " font data", /* Name */ - /* */ - NULL, /* r0 */ - &font_area, /* area number allocated */ - NULL, /* r2 */ - &font_area_base /* base address of area */ - ); - - if (e) - { - game_area = font_area = -1; - game_area_base = font_area_base = 0; /* paranoia */ - return; - } - else - { - e = SWI(2, 3, SWI_OS_DynamicArea, 2, font_area, - NULL, NULL, &font_area_size); - if (e) - { - Error_ReportFatal(e->errnum, "%d:%s", e->errmess); - } - - e = Heap_Initialise((heap) font_area_base, font_area_size); - if (e) - { - Error_ReportFatal(e->errnum, "%d:%s", e->errmess); - } - font_heap_size = font_area_size; - } - } - - /* Make sure DA(s) are removed when we quit */ - atexit(cleanup_memory); - - if (!dag) - { - /* Paranoia */ - game_area = -1; - game_area_base = 0; - } - else - { - e = SWI(9, 4, SWI_OS_DynamicArea, 0, /* Create */ - -1, /* Let OS allocate no. */ - 16 << 10, /* Initial size */ - -1, /* Let OS allocate address */ - 1 << 7, /* Cacheable, bufferable, RW */ - MAX_G_DA_SIZE, /* Max size */ - 0, /* handler */ - 0, /* handler workspace */ - VARIANT " game data", /* Name */ - /* */ - NULL, /* r0 */ - &game_area, /* area number allocated */ - NULL, /* r2 */ - &game_area_base /* base address of area */ - ); - - if (e) - { - game_area = -1; - game_area_base = 0; /* paranoia */ - } - else - { - e = SWI(2, 3, SWI_OS_DynamicArea, 2, game_area, - NULL, NULL, &game_area_size); - if (e) - { - Error_ReportFatal(e->errnum, "%d:%s", e->errmess); - } - - e = Heap_Initialise((heap) game_area_base, game_area_size); - if (e) - { - Error_ReportFatal(e->errnum, "%d:%s", e->errmess); - } - game_heap_size = game_area_size; - } - } -} - -static int grow_dynamicarea(int area, int by) -{ - os_error *e; - e = SWI(2, 2, SWI_OS_ChangeDynamicArea, area, by, /**/ NULL, &by); - /* Can't check errors since a 'failed' shrink returns one... */ - return by; -} - - -/* - | Try to shrink the font-cache heap and area as much as possible. - */ -static void f_shrink_heap(void) -{ - int s; - /* Shrink the heap as far as possible */ - font_heap_size -= - Heap_ChangeHeapSize((heap) font_area_base, -MAX_F_DA_SIZE); - /* Shrink the dynamic area if necessary */ - s = font_area_size - font_heap_size; - if (s >= SHRINK_GRAN) - font_area_size -= grow_dynamicarea(font_area, -s); -} - -/* - | Allocate a block of memory in the font heap - */ -static void *f_malloc(size_t size) -{ - void *c; - int s; - if (font_area == -1) - { - return malloc(size); - } - c = Heap_Claim((heap) font_area_base, size); - - if (!c) - { - /* The Claim failed. Try to grow the area by the size of the block */ - s = grow_dynamicarea(font_area, size + 64); /* 64 is overkill */ - if (!s) - { - return NULL; - } - font_area_size += s; - s = font_area_size - font_heap_size; - font_heap_size += Heap_ChangeHeapSize((heap) font_area_base, s); - c = Heap_Claim((heap) font_area_base, size); - if (c) - { - f_shrink_heap(); - } - } - return c; -} - - -/* - | Free a block of memory in the font heap - */ -static void f_free(void *blk) -{ - os_error *e; - if (font_area == -1) - { - free(blk); - return; - } - e = Heap_Release((heap) font_area_base, blk); - if (e) - Msgs_ReportFatal(e->errnum, "err.swi", __LINE__, e->errmess); - f_shrink_heap(); -} - - - - - -/* - | Allocate a block of memory in the game heap - */ -static vptr g_malloc(huge size) -{ - void *c; - int s; - - if (game_area == -1) - { - return malloc((size_t) size); - } - c = Heap_Claim((heap) game_area_base, (size_t) size + 4); - if (!c) - { - /* The Claim failed. Try to grow the area by the size of the block */ - s = grow_dynamicarea(game_area, (size_t) size + 64); /* 64 is overkill */ - if (!s) - { - return NULL; - } - game_area_size += s; - s = game_area_size - game_heap_size; - game_heap_size += Heap_ChangeHeapSize((heap) game_area_base, s); - c = Heap_Claim((heap) game_area_base, (size_t) size + 4); - } - - if (c) - { - strcpy((char *)c, "MUSH"); - c = (void *)(((int)c) + 4); - } - - if (log_g_malloc) - fprintf(stderr, "ralloc(%ld) == %p\n", (long)size, c); - - return c; -} - - -/* - | Free a block of memory in the game heap - | - | The 'len' is to be compatible with z-virt.c (we don't need/use it) - | Returns NULL. - */ -static vptr g_free(vptr blk, huge size) -{ - os_error *e; - int s; - - if (game_area == -1) - { - free(blk); - return NULL; - } - - if (log_g_malloc) - fprintf(stderr, "rnfree(%p)\n", blk); - - if (strncmp(((char *)blk) - 4, "MUSH", 4)) - core("game heap corrupt / bad attempt to free memory"); - - blk = (void *)(((int)blk) - 4); - - e = Heap_Release((heap) game_area_base, blk); - if (e) - Msgs_ReportFatal(e->errnum, "err.swi", __LINE__, e->errmess); - - /* Shrink the heap as far as possible */ - game_heap_size -= - Heap_ChangeHeapSize((heap) game_area_base, -MAX_G_DA_SIZE); - - /* Shrink the dynamic area if necessary */ - s = game_area_size - game_heap_size; - if (s >= SHRINK_GRAN) - game_area_size -= grow_dynamicarea(game_area, -s); - - return NULL; -} - - -#endif /* USE_DA */ - - - -/*--------------------------------------------------------------------------*/ - -/* - | New to 1.04: Sound support :) - | - | We use the PlayIt module (for convenience). - | - | The Lib/xtra/sound/sound.cfg file is used to map sample names onto - | event names. - | - | Since textual names are used in the .cfg file, we need to have a lookup - | table to translate them into numbers. At present we use the - | angband_sound_name array defined in variable.c - | - | Since there can be multiple sounds for each event we need to use a - | list to store them. - */ - -/* NB: This will be clipped to 10 under RISC OS 2 */ -#define MAX_SAMPNAME_LEN 64 - - - - -/* - | The list format: - */ -typedef struct samp_node -{ - char sample_name[MAX_SAMPNAME_LEN + 1]; /* Sample name */ - struct samp_node *next; /* -> next node */ -} -SampNode; - -typedef struct samp_info -{ - int samples; /* # samples for this event */ - SampNode *samplist; /* list of sample names */ -} -SampInfo; - - -/* - | Just need an array of SampInfos - */ -static SampInfo sample[SOUND_MAX]; - -/* - | This flag will only be set non-zero if the SampInfo array is - | valid. - */ -static int sound_initd = 0; - - -static void read_sound_config(void) -{ - int i; - char buffer[2048]; - FILE *f; - int max_sampname_len = truncate_names()? 10 : MAX_SAMPNAME_LEN; - FILE *dbo = NULL; - - if (show_sound_alloc) - { - sprintf(buffer, "%s%s", resource_path, "sndmap/out"); - dbo = fopen(buffer, "w"); - if (!dbo) - { - core("can't create sndmap/out debugging file"); - } - } - - if (!sound_initd) - { - /* Initialise the sample array */ - for (i = 0; i < SOUND_MAX; i++) - { - sample[i].samples = 0; - sample[i].samplist = NULL; - } - sound_initd = 1; - } - else - { - /* Deallocate the sample lists */ - for (i = 0; i < SOUND_MAX; i++) - { - SampNode *si = sample[i].samplist; - sample[i].samples = 0; - sample[i].samplist = NULL; - while (si) - { - SampNode *ns = si->next; - free(si); - si = ns; - } - } - } - - - /* Open the config file */ - sprintf(buffer, "%sSound:%s", RISCOS_VARIANT, "sound/cfg"); - f = fopen(buffer, "r"); - - /* No cfg file => no sounds */ - if (!f) - { - if (show_sound_alloc) - { - fprintf(dbo, "** Can't open cfg file '%s'\n", buffer); - fclose(dbo); - } - return; - } - - /* Parse the file */ - while (fgets(buffer, sizeof(buffer), f)) - { - char *sample_name; - int event_number; - - /* Skip comments and lines that begin with whitespace */ - if (*buffer == '#' || isspace((unsigned char)*buffer)) - { - continue; - } - - /* Hack: ignore any line beginning '[' (section marker) */ - if (*buffer == '[') - { - continue; - } - - /* Place a NULL after the event name and find the first sample name */ - sample_name = buffer; - while (*sample_name && !isspace((unsigned char)*sample_name)) - sample_name++; - - /* Bad line? */ - if (*sample_name == 0) - { - continue; - } /* just ignore it */ - - /* Terminate the sample name */ - *sample_name++ = 0; - - /* Look up the event name to get the event number */ - for (event_number = SOUND_MAX - 1; event_number >= 0; event_number--) - if (!strcmp(buffer, angband_sound_name[event_number])) - break; - - /* No match -> just ignore the line */ - if (event_number < 0) - { - if (show_sound_alloc) - fprintf(dbo, "* Ignoring unknown event '%s'\n", buffer); - continue; - } - - /* Find the = */ - while (*sample_name && *sample_name != '=') - sample_name++; - - /* Bad line? */ - if (*sample_name == 0) - { - continue; - } /* just ignore it */ - - /* Skip the '=' */ - sample_name++; - - - /* - | Now we find all the sample names and add them to the - | appropriate list in the sample mapping array - */ - - while (*sample_name) - { - char *s; - SampNode *sn; - - /* Find the start of the next word */ - while (isspace((unsigned char)*sample_name) && *sample_name) - sample_name++; - - /* End of line? */ - if (!*sample_name) - { - break; - } - - /* Find the end of the sample name */ - s = sample_name; /* start of the name */ - while (!isspace((unsigned char)*sample_name) && *sample_name) - sample_name++; - - /* Hack: shorten sample names that are too long */ - if ((sample_name - s) > max_sampname_len) - s[max_sampname_len] = ' '; - - /* Allocate a node in the sample list for the event */ - if ((sn = malloc(sizeof(SampNode))) == NULL) - core("Out of memory (scanning sound.cfg)"); - - /* Link the node to the list */ - sn->next = sample[event_number].samplist; - sample[event_number].samplist = sn; - - /* Imcrement the sample count for that event */ - sample[event_number].samples++; - - /* - | Copy the sample name into the node, converting it into - | RISC OS style as we go. - */ - for (i = 0; !isspace((unsigned char)s[i]) && s[i]; i++) - { - if (s[i] == '.') - sn->sample_name[i] = '/'; - else if (s[i] == '/') - sn->sample_name[i] = '.'; - else - sn->sample_name[i] = s[i]; - } - /* - | The sample name '*' is special and means "no new sound" - | so don't store a filename for these mappings. - */ - if (i == 1 && sn->sample_name[0] == '*') - { - i = 0; - } - sn->sample_name[i] = 0; - } - } - - /* Close the file */ - fclose(f); - - if (show_sound_alloc) - { - int i; - SampNode *l; - - for (i = 0; i < SOUND_MAX; i++) - { - fprintf(dbo, "\n\nEvent '%s'", angband_sound_name[i]); - fprintf(dbo, " (%d sounds)\n", sample[i].samples); - for (l = sample[i].samplist; l; l = l->next) - fprintf(dbo, "\t%s\n", l->sample_name); - } - fclose(dbo); - } - -} - - - -/* - | Try to make sure that PlayIt is loaded. - | This requires AngSound rel. 4 - */ -static void check_playit(void) -{ - if (SWI(2, 0, SWI_OS_Module, 18, "PlayIt")) - { - int t; - SWI(2, 1, SWI_OS_File, 17, "Angsound:LoadPlayIt", &t); - if (t == 1) - SWI(1, 0, SWI_OS_CLI, - "RMEnsure PlayIt 0.00 Run AngSound:LoadPlayIt"); - } -} - - - - -static void initialise_sound(void) -{ - /* Load the configuration file */ - Hourglass_On(); - read_sound_config(); - check_playit(); - Hourglass_Off(); -} - - - -static void play_sample(char *leafname) -{ - char buffer[260]; - - strcpy(buffer, "%playit_stop"); - - if (!SWI(1, 0, SWI_OS_CLI, buffer)) - { - SWI(1, 0, SWI_PlayIt_Volume, sound_volume); - sprintf(buffer, "%%playit_play %sSound:%s", RISCOS_VARIANT, leafname); - SWI(1, 0, SWI_OS_CLI, buffer); - } - - return; -} - - - -static void play_sound(int event) -{ - /* Paranoia */ - if (!sound_initd) - { - return; - } - - /* Paranoia */ - if (event < 0 || event >= SOUND_MAX) - return; - - /* msg_format("Sound '%s'",angband_sound_name[event]); */ - - /* Choose a sample */ - if (sample[event].samples) - { - int s = rand() % sample[event].samples; - SampNode *sn = sample[event].samplist; - while (s--) - { - sn = sn->next; - if (!sn) - { - plog("Adny botched the sound config - please send him a copy of your sound/cfg file."); - } - } - if (*(sn->sample_name)) - play_sample(sn->sample_name); - } -} - - - - -/*--------------------------------------------------------------------------*/ - -/* - | This stuff is for the Term_user hook - */ - - - -static void display_line(int x, int y, int c, const char *fmt, ...) -{ - va_list ap; - char buffer[260]; - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - Term_putstr(x, y, -1, c, buffer); - va_end(ap); -} - - - -/* - | Let the user change the alarm message - */ -static void do_alarm_message_input(int y) -{ - int k; - int inspos = strlen(alarm_message); - char old_message[52]; - - strcpy(old_message, alarm_message); - - do - { - display_line(26, y, TERM_YELLOW, "%-51s", alarm_message); - Term_gotoxy(26 + inspos, y); - k = inkey(); - switch (k) - { - case 21: /* ^U */ - *alarm_message = 0; - inspos = 0; - break; - case 128: case 8: /* delete */ - if (inspos > 0) - { - alarm_message[--inspos] = 0; - } - break; - case 27: /* escape */ - strcpy(alarm_message, old_message); - k = 13; - break; - default: - if (k > 31 && k < 127 && inspos < 50) - { - alarm_message[inspos++] = k; - alarm_message[inspos] = 0; - } - } - } - while (k != 13); - - display_line(26, y, TERM_WHITE, "%-51s", alarm_message); -} - - -#define tum_col(X) ((X) ? TERM_L_BLUE : TERM_WHITE ) -#define tum_onoff(X) ((X) ? "On " : "Off") - -static errr Term_user_acn(int n) -{ - int cursor_state; - int optn = 0; - int k, adj; - int redraw_mung = 0; - int max_opt = 11; - int alarm_modified = 0; /* Will be true if the alarm choices need to be (re)saved */ - - /* - | Hack: let the desktop front end know that - | the user menu is active... - */ - user_menu_active = TRUE; - - - /* - | This is thanks to Norcroft CC... it seems to want - | to set up FP regs nice and early and then relies - | on them remaining constant over the function call. - | The trouble is that we implicitly call Wimp_Poll - | whilst waiting for a key press... - */ - event_mask.data.keepfpregisters = 1; - - /* - | Hack: alarm type 1 /looks/ the same as type 3 but doesn't get - | cancelled as a type 3 would. This allows alarms to go off and - | be cancelled without affecting the alarm type whilst it's being - | set up here. - */ - if (alarm_type == 3) - { - alarm_type = 1; - } - - /* - | Store the screen - */ - Term_activate(&(data[0].t)); - Term_save(); - Term_get_cursor(&cursor_state); - Term_set_cursor(TRUE); - - do - { - redraw_mung = 0; - Term_clear(); - display_line(2, 1, TERM_YELLOW, "%s %s", VARIANT, VERSION); - display_line(2, 2, TERM_SLATE, "Front-end %s", PORTVERSION); - display_line(2, 4, TERM_WHITE, - "Use cursor up/down to select an option then cursor left/right to alter it."); - display_line(2, 5, TERM_WHITE, - "Hit 'S' to save these settings (alarm settings are saved automatically)."); - display_line(2, 6, TERM_WHITE, "Hit ESC to return to the game."); - - for (k = 0; k < 16; k++) - display_line(31 + k * 3, 8, k, "##", k); - - do - { - display_line(2, 8, tum_col(optn == 0), - " Gamma correction : %.2lf", gamma); - display_line(2, 9, tum_col(optn == 1), " Force monochrome : %s", - tum_onoff(force_mono)); - display_line(2, 10, tum_col(optn == 2), " Sound effects : %s", - tum_onoff(enable_sound)); - display_line(2, 11, tum_col(optn == 3), " Sound effect volume : "); - display_line(26, 11, - sound_volume > 127 ? TERM_RED : tum_col(optn == 3), - "%-3d", sound_volume); - display_line(30, 11, tum_col(optn == 3), "(127 = full volume)"); - display_line(2, 12, tum_col(optn == 4), " Start fullscreen : %s", - tum_onoff(start_fullscreen)); - display_line(30, 12, tum_col(optn == 4), - "(also selects fullscreen/desktop now)"); - display_line(2, 13, tum_col(optn == 5), " Use hourglass : %s", - tum_onoff(use_glass)); - display_line(2, 14, tum_col(optn == 6), - "'Hard' input flushing : %s", tum_onoff(hack_flush)); - - display_line(7, 16, tum_col(optn == 7), " Alarm type : %-20s", - alarm_types[alarm_type]); - display_line(7, 17, TERM_WHITE, " Time : "); - display_line(26, 17, tum_col(optn == 8), "%02d", alarm_h); - display_line(28, 17, TERM_WHITE, ":"); - display_line(29, 17, tum_col(optn == 9), "%02d", alarm_m); - display_line(7, 18, tum_col(optn == 10), " Message : %-51s", - alarm_message); - display_line(7, 19, tum_col(optn == 11), " Beep : %s", - tum_onoff(alarm_beep)); - -#ifdef FE_DEBUG_INFO - display_line(2, 23, tum_col(optn == 23), "Show debug info"); - max_opt = 12; -#endif - - switch (optn) - { - case 12: Term_gotoxy(2, 23); - break; - case 11: Term_gotoxy(26, 19); - break; - case 10: Term_gotoxy(26, 18); - break; - case 9: Term_gotoxy(29, 17); - break; - case 8: Term_gotoxy(26, 17); - break; - case 7: Term_gotoxy(26, 16); - break; - default: Term_gotoxy(26, optn + 8); - } - - k = inkey(); - adj = (k == '4' || k == 'h') ? -1 : (k == '6' || k == 'l') ? 1 : 0; - - switch (k) - { - case 18: /* Hack: force the screen to update */ - redraw_mung = 1; - k = 27; - break; - case 's': case 'S': - save_choices(); - display_line(2, 23, TERM_YELLOW, "Options saved. "); - Term_fresh(); - Term_xtra(TERM_XTRA_DELAY, 750); - Term_erase(2, 23, 60); - break; - case '8': case 'k': - if (--optn < 0) - { - optn = max_opt; - } - break; - case '2': case 'j': - if (++optn > max_opt) - { - optn = 0; - } - break; - case 13: case 32: case 't': /* Allow return, space and t to toggle some options */ - case '4': case 'h': - case '6': case 'l': - { - switch (optn) - { - case 0: /* Gamma correction */ - gamma += adj * 0.05; - if (gamma > 9.00) - { - gamma = 9.00; - } - if (gamma < 0.05) - { - gamma = 0.05; - } - Term_xtra(TERM_XTRA_REACT, 0); -#ifndef FULLSCREEN_ONLY - set_gamma_window_state(); -#endif /* FULLSCREEN_ONLY */ - /* flush(); */ - Term_fresh(); - break; - case 1: /* Force monochrome */ - force_mono = !force_mono; - if (fullscreen_font) - redraw_areaFS(0, 0, 80, 24); - else - Term_xtra(TERM_XTRA_REACT, 0); - /* flush(); */ - Term_fresh(); - break; - case 2: /* Sound enable / disable */ - enable_sound = !enable_sound; -#ifndef FULLSCREEN_ONLY - set_sound_window_state(); -#endif /* FULLSCREEN_ONLY */ - if (enable_sound) - { - initialise_sound(); - } - break; - case 3: /* Sound volume */ - sound_volume += adj; - if (sound_volume < SOUND_VOL_MIN) - sound_volume = SOUND_VOL_MIN; - if (sound_volume > SOUND_VOL_MAX) - sound_volume = SOUND_VOL_MAX; -#ifndef FULLSCREEN_ONLY - set_sound_window_state(); -#endif /* FULLSCREEN_ONLY */ - break; - case 4: /* Start fullscreen */ - start_fullscreen = !start_fullscreen; - if (start_fullscreen) - enter_fullscreen_mode(); - else if (!minimise_memory) - leave_fullscreen_mode(); - break; - case 5: /* Start fullscreen */ - use_glass = !use_glass; - if (!use_glass) - { - if (glass_on) - { - Hourglass_Off(); - } - glass_on = 0; - } - break; - case 6: /* hack flush */ - hack_flush = !hack_flush; - break; - case 7: /* Alarm on/off */ - alarm_type += adj; - if (adj) - { - alarm_modified = 1; - } - if (alarm_type > 2) - { - alarm_type = 0; - } - if (alarm_type < 0) - { - alarm_type = 2; - } - if (!alarm_type && alarm_disp) - { - ack_alarm(); - } /* XXXXX Cancel an already active alarm? */ - break; - case 8: /* Alarm hours */ - alarm_h += adj; - if (adj) - { - alarm_modified = 1; - } - if (alarm_h < 0) - { - alarm_h += 24; - } - if (alarm_h > 23) - { - alarm_h -= 24; - } - if (alarm_disp) - { - ack_alarm(); - } - break; - case 9: /* Alarm minutes */ - alarm_m += adj; - if (adj) - { - alarm_modified = 1; - } - if (alarm_m < 0) - { - alarm_m += 60; - } - if (alarm_m > 59) - { - alarm_m -= 60; - } - if (alarm_disp) - { - ack_alarm(); - } - break; - case 10: - alarm_modified = 1; - do_alarm_message_input(18); - break; - case 11: - alarm_modified = 1; - alarm_beep = !alarm_beep; - break; - case 12: - show_debug_info(); - redraw_mung = 1; - k = 27; - break; - } - } - } - } - while (k != 27); - } - while (redraw_mung); - - /* Rehack the alarm type: */ - if (alarm_type == 1) - { - alarm_type = 3; - } - - if (alarm_modified) - { - write_alarm_choices(); - } - - Term_set_cursor(cursor_state); - - /* Restore the screen */ - Term_load(); - - /* Don't need to preserve FP regs any more */ - event_mask.data.keepfpregisters = 0; - - /* - | Hack: tell the desktop front end that we're done. - */ - user_menu_active = FALSE; - - return 0; -} - - - - -/*--------------------------------------------------------------------------*/ - -#ifdef USE_FILECACHE - -/* - | 'Random' File-cacheing for *band. - | - | Rewritten since as of Zang 225 the mechanism for handling - | these files has changed dramatically and the old system - | is no longer viable. - | - | These new functions basically provide an alternative to the - | normal my_fopen() (or fopen()) and my_fgets() functions. - | - | To use the file caching it is therefore necessary to alter - | files.c to call cached_fopen(), cached_fclose() and cached_fgets() - | rather than the normal functions. - | - | Note that these funtions will only work for files that are intended - | to be read as a series of \n terminated lines of ASCII text using my_fgets(). - | - */ - -/* - | Hack: use the game's dynamic area if possible: - */ -#define fc_malloc(X) (g_malloc(X)) -#define fc_free(X) (g_free(X,0)) - -#ifndef ABBR_FILECACHE -/* - | Make these to do nothing. They'll never - | be called anyway. Having them present makes - | for neater code later on (ie. we use a variable - | rather than the pre-processor to decide whether - | to do compression). - */ -static int compress_string(char *os, char *s) -{ - core("main-acn internal logic error 001"); - return 0; -} -static int decompress_string(char *d, char *s, int max_len) -{ - core("main-acn internal logic error 002"); - return 0; -} -static int compressed_length(char *s) -{ - core("main-acn internal logic error 003"); - return 0; -} - -#else - -/* - | When caching files we try to use some abbreviations. - | We use both whole words and pairs of letters. - | NB: For this to work, the file must contain only - | 7 bit characters. - */ -static char *abbrv_w[] = -{ - /* These words all begin with a space */ - " of ", " the ", " you ", " to ", " a ", " says", " is ", " that ", " and ", - " your ", " are ", " it ", " be ", " for ", " me", " will ", " in ", - " not ", " this ", " have ", " can ", " on ", " my ", " with ", " say ", - " all", " by ", " get ", " but ", " just ", " die", " as ", " time ", - " if ", - " like ", - /* These words do not */ - "I ", "The ", "You ", "They ", "It ", "don", 0 -}; - -/* Number of words */ -#define FC_ABBRV_NUMWORDS 41 - -/* Number of them that don't start with a space */ -#define FC_ABBRV_NONSPC 6 - -/* - | NB: No letter pair may start with \0. - */ -static char abbrv_lp[] = - "e ttht s heiner aoure'\0, anonf sd y r ongofator.\0" - "n arllstha wes m ieaisen bl yndtoo yometele d f hve" - "ayuralitneelN: chig ilroassaseliti lraa otedbede 'ri" "..u nntno!'ee\0\0"; - - -/* - | Compress the given string using the abbreviation tables above. - | Returns compressed length *including* terminator (it may - | be part of an abbreviation, you see...) - | Note that we can compress the string in-place, ie. 'os' may be - | the same as 's'. - */ -static int compress_string(char *os, char *s) -{ - char *o, *f, *d; - int i; - - o = os; - - while (*s) - { - int fw, lw; - if (*s == ' ') - { - fw = 0; - lw = FC_ABBRV_NUMWORDS - FC_ABBRV_NONSPC; - } - else - { - fw = FC_ABBRV_NUMWORDS - FC_ABBRV_NONSPC; - lw = FC_ABBRV_NUMWORDS; - } - for (i = fw; i < lw; i++) - { - d = abbrv_w[i]; /* Word to check against */ - for (f = s; *f && *f == *d; f++, d++) - ; - if (*d == 0) /* Match? */ - { - s = *f ? f : f - 1; /* Update string pointer */ - *o++ = 128 + i; /* store code */ - break; /* Quit looking for words */ - } - } - - /* Do we need to check the letter pairs? */ - if (i == lw) - { - for (i = 0; abbrv_lp[i]; i += 2) - { - if (s[0] == abbrv_lp[i] && s[1] == abbrv_lp[i + 1]) - { - *o++ = 128 + FC_ABBRV_NUMWORDS + i / 2; - /* NB: If the next character is the terminator then we're done. */ - if (!s[1]) - { - return (o - os); - } - s += 2; /* Quit looking for letters */ - break; - } - } - /* NB: This next check is only safe because no letter pair starts with a NULL */ - if (!abbrv_lp[i]) - *o++ = *s++; - } - } - - /* Don't forget that terminator! */ - *o++ = 0; - - return o - os; -} - -/* - | As compress_string (above), but stores nothing and - | only returns the length of the compressed string. - */ -static int compressed_length(char *s) -{ - char *f, *d; - int i, l; - - l = 0; - while (*s) - { - int fw, lw; - if (*s == ' ') - { - fw = 0; - lw = FC_ABBRV_NUMWORDS - FC_ABBRV_NONSPC; - } - else - { - fw = FC_ABBRV_NUMWORDS - FC_ABBRV_NONSPC; - lw = FC_ABBRV_NUMWORDS; - } - for (i = fw; i < lw; i++) - { - d = abbrv_w[i]; - for (f = s; *f && *f == *d; f++, d++) - ; - if (*d == 0) /* Match? */ - { - s = *f ? f : f - 1; /* Update string pointer */ - l++; /* increment output length */ - break; /* Quit looking for words */ - } - } - - /* Do we need to check the letter pairs? */ - if (i == lw) - { - for (i = 0; abbrv_lp[i]; i += 2) - { - if (s[0] == abbrv_lp[i] && s[1] == abbrv_lp[i + 1]) - { - l++; /* increment output length */ - /* NB: If the next character is the terminator then we're done. */ - if (!s[1]) - { - return l; - } - s += 2; /* Quit looking for letters */ - break; - } - } - /* NB: This next check is only safe because no letter pair starts with a NULL */ - if (!abbrv_lp[i]) - { - l++; - s++; - } - } - } - /* Don't forget that terminator! */ - return l + 1; -} - - - -/* - | Decompress the given string 's' into the buffer at 'd'. - | At most, max_len characters (incl. \0 terminator) will be - | written into d. - | Returns the length of 's'. - */ -static int decompress_string(char *d, char *s, int max_len) -{ - char *os = s; - - while (max_len > 1) - { - int nc = *s++; /* Get next character */ - - if (nc < 128) /* Is it a plain character? */ - { - if (0 == (*d++ = nc)) - { - break; - } - max_len--; - } - else /* Abbreviation to expand. */ - { - if (nc >= FC_ABBRV_NUMWORDS + 128) /* Letter pair? */ - { - *d++ = abbrv_lp[(nc - (FC_ABBRV_NUMWORDS + 128)) * 2]; - if (0 == - (*d++ = abbrv_lp[(nc - (FC_ABBRV_NUMWORDS + 128)) * 2 + 1])) - break; - max_len -= 2; - } - else /* It's a word */ - { - char *ws = abbrv_w[nc - 128]; - while (*ws && max_len > 1) - { - *d++ = *ws++; - max_len--; - } - } - } - } - - /* Skip over the rest of the abbreviated string if we ran out of space */ - if (max_len <= 1) /* Out of space? */ - { - int nc; - *d = 0; /* Terminate */ - do - { - nc = *s++; /* Next char */ - if (nc >= 128 + FC_ABBRV_NUMWORDS) /* Ignore words */ - nc = abbrv_lp[(nc - (FC_ABBRV_NUMWORDS + 128) * 2) + 1]; /* Only check 2nd letter of pair */ - } - while (nc); - } - return s - os; /* Length of abbreviated string */ -} - -#endif /* ABBR_FILECACHE */ - - -/* Each entry in the cache looks like this: */ -typedef struct fce_ -{ - char *name; /* canonical pathname of file */ - char *text; /* text (be it compressed or not) */ - char *eof; /* byte beyond the last byte of text */ - int used; /* access counter when the file was last used */ - int compressed; /* compression method, (ie. 0 for none or 1 for abbreviations) */ -} -FileCacheEntry; - -/* - | The handles we chuck around are pointers to one of these structs. - | Note that since we actually return (and take) |FILE*|s we just - | compare the value of a |FILE*| with the limits of the array of - | |CachedFileHandle|s to decide whether its 'ours' or a genuine - | (ie. stdio) file handle. This /is/ pretty lame, I know... - */ -typedef struct cfh_ -{ - char *ptr; /* sequential file pointer, as it were */ - FileCacheEntry *fce; /* ->the file-cache entry data */ -} -CachedFileHandle; - -#define MAX_OPEN_CACHED_FILES 16 /* We allow up to 16 of these files open at once */ -#define MAX_CACHE_ENTRIES 64 /* We allow up to 64 cache entries */ - -static FileCacheEntry *file_cache; /* to be used as file_cache[MAX_CACHE_ENTRIES] */ -static CachedFileHandle *cached_file_handle; /* to be used as cached_file_handle[MAX_OPEN_CACHED_FILES] */ -static int file_cache_initd = 0; /* Is the cache initialised? */ -static int file_cache_size = 0; /* Total size of the cached files */ -static int fc_access_counter = 1; /* incremented on each cache access */ -/* - | Pre-calculate max. possible value of a FILE* (ie. address in memory) - | that could be a valid |CachedFileHandle*|. - */ -static FILE *max_cfh_addr; /* == (FILE*) (&(cached_file_handle[MAX_OPEN_CACHED_FILES-1])) */ - -/* - | Initialise the file cache - */ -static void init_file_cache(void) -{ - int i; - - /* Allocate storage */ - file_cache = fc_malloc(MAX_CACHE_ENTRIES * sizeof(FileCacheEntry)); - cached_file_handle = - fc_malloc(MAX_OPEN_CACHED_FILES * sizeof(CachedFileHandle)); - - if (!file_cache || !cached_file_handle) - { - /* Disable file-caching */ - if (file_cache) - { - fc_free(file_cache); - } - if (cached_file_handle) - { - fc_free(cached_file_handle); - } - use_filecache = 0; - } - else - { - /* Initialise the cache */ - for (i = 0; i < MAX_CACHE_ENTRIES; i++) - file_cache[i].name = NULL; - for (i = 0; i < MAX_OPEN_CACHED_FILES; i++) - cached_file_handle[i].fce = NULL; - fc_access_counter = 1; - file_cache_size = 0; - max_cfh_addr = - (FILE *)(&(cached_file_handle[MAX_OPEN_CACHED_FILES - 1])); - } - file_cache_initd = 1; -} - - -/* - | Helper: take a copy of the string and return a pointer to it - */ -static char *string_cpy(char *s) -{ - char *d = fc_malloc(strlen(s) + 1L); - if (d) - { - strcpy(d, s); - } - return d; -} - - -/* - | Cache the specified file, returning either the cache entry - | that it has been cached at, or NULL for failure. - | - | Note that for the abbreviated file cache a temporary file - | is used to allow the compression to be applied just once. - | (otherwise it has to be done twice - once to determine the - | eventual compressed size and once to actually store and compress - | it). - */ -static FileCacheEntry *cache_file(char *name) -{ - int i, size = 0; - FILE *fp; - char buffer[1024]; - char *d; - - FILE *tf = NULL; /* Used if abbr_filecache and abbr_tmpfile are set */ - char cfn[1024]; /* Used if abbr_filecache and abbr_tmpfile are set */ - - /* Find the first free slot in the cache */ - for (i = 0; i < MAX_CACHE_ENTRIES; i++) - if (!file_cache[i].name) - break; - - /* No more entries? */ - if (i >= MAX_CACHE_ENTRIES) - { - return NULL; - } - - /* Set up the info on the file */ - if ((file_cache[i].name = string_cpy(name)) == NULL) - { - return NULL; - } - - /* Open the file */ - fp = my_fopen(name, "r"); - if (!fp) - { - fc_free(file_cache[i].name); - file_cache[i].name = 0; - return NULL; - } - - /* Open/create tempfile if need be: */ - if (abbr_filecache && abbr_tmpfile) - { - /* Hack: Form the pathname of the cached compressed file (in canonical form) */ - sprintf(cfn, "%s%s", scrap_path, - riscosify_name(name + strlen(resource_path))); - /* Ensure that that particular directory exists... */ - ensure_path(cfn); - /* Check whether cache file is out of date */ - if (file_is_newer(riscosify_name(name), cfn)) - { - tf = fopen(cfn, "wb"); - size = 0; - } - else - { - tf = fopen(cfn, "rb"); - if (tf) - { - size = myFile_Size(cfn); - } - } - } - - /* If we don't have the cached file (but want it), compress the source text to it */ - if (tf) - { - if (!size) - { - int k; - while (!my_fgets(fp, buffer, sizeof(buffer))) - { - if (smart_filecache && (!*buffer || *buffer == '#')) - continue; - k = compress_string(buffer, buffer); - if (fwrite(buffer, 1, k, tf) != k) - { - fclose(tf); - remove(cfn); - core("error writing tempfile"); - } - size += k; - } - fclose(tf); - tf = fopen(cfn, "rb"); - } - } - else - { - /* Count the number of bytes */ - while (!my_fgets(fp, buffer, sizeof(buffer))) - { - if (smart_filecache && (!*buffer || *buffer == '#')) - continue; - if (abbr_filecache) - size += compressed_length(buffer); - else - size += strlen(buffer) + 1; - } - } - - /* Close the (source) file */ - my_fclose(fp); - - /* Allocate enough storage for the text */ - file_cache[i].text = fc_malloc(size + 1L); - if (!file_cache[i].text) - { - fc_free(file_cache[i].name); - file_cache[i].name = 0; - if (tf) - { - fclose(tf); - } - return NULL; - } - - /* Do we have a tempfile to load? */ - if (tf) - { - if (fread(file_cache[i].text, 1, size, tf) != size) - core("error reading tempfile"); - fclose(tf); - } - else - { - /* Re-open the file... */ - fp = my_fopen(name, "r"); - if (!fp) - { - fc_free(file_cache[i].name); - fc_free(file_cache[i].text); - file_cache[i].name = 0; - return NULL; - } - - /* And read it into the buffer... */ - d = file_cache[i].text; - while (!my_fgets(fp, buffer, sizeof(buffer))) - { - if (smart_filecache && (!*buffer || *buffer == '#')) - continue; - if (abbr_filecache) - d += compress_string(d, buffer); - else - { - strcpy(d, buffer); - d += strlen(buffer) + 1; - } - } - - if ((d - file_cache[i].text) != size) - { - debug("Calculated size is %d, pointer offset is %d", size, - (d - file_cache[i].text)); - core("Cached file is larger than calculated!"); - } - - /* Close the file */ - my_fclose(fp); - } - - /* Set up the 'last accessed' value, etc. */ - file_cache[i].used = fc_access_counter++; - file_cache[i].eof = file_cache[i].text + size; - file_cache[i].compressed = abbr_filecache; - file_cache_size += size; - - /* Return success */ - return &(file_cache[i]); -} - - -/* - | Discard a file from the cache - */ -static void discard_cached_file(int i) -{ - if (!file_cache[i].name) - { - return; - } /* invalid request */ - fc_free(file_cache[i].text); - fc_free(file_cache[i].name); - file_cache_size -= (file_cache[i].eof) - (file_cache[i].text); - file_cache[i].name = 0; -} - - -/* - | Attempt to flush as much of the cache as required - | to bring it within the size limit. - | If protect != 0 then that entry in the cache won't be flushed. - */ -static void flush_file_cache(FileCacheEntry * protect) -{ - int i, j, done; - int oldest_u, oldest_e; - FileCacheEntry *fce; - int needed = (4 << 10); /* Hack: try to free at least 4K */ - - done = (file_cache_size + needed) <= max_file_cache_size; - - while (!done) - { - oldest_u = fc_access_counter; - oldest_e = -1; - - fce = file_cache; - /* Find oldest entry that isn't in use */ - for (i = 0; i < MAX_CACHE_ENTRIES; fce++, i++) - { - if (fce == protect) - { - continue; - } /* Hack ;) */ - if (fce->name) /* Is this cache slot full? */ - { - for (j = 0; j < MAX_OPEN_CACHED_FILES; j++) - if (cached_file_handle[j].fce == fce) - break; - if (j < MAX_OPEN_CACHED_FILES) - continue; /* Cached file is still open */ - if (fce->used < oldest_u) - { - oldest_e = i; - oldest_u = file_cache[i].used; - } - } - } - - if (oldest_e < 0) - done = 1; /* We can flush nothing more */ - else - { - discard_cached_file(oldest_e); - done = (file_cache_size + needed) <= max_file_cache_size; - } - } -} - - -/* - | Locate the specified file within the cache. - | Returns NULL if the file is not cached - */ -static FileCacheEntry *find_cached_file(char *name) -{ - int i; - FileCacheEntry *fce = file_cache; - - for (i = 0; i < MAX_CACHE_ENTRIES; i++, fce++) - { - if (fce->name) - if (streq(fce->name, name)) - return fce; - } - return NULL; -} - - - -/*--------------------------------------------------------------------------*/ -/* Externally visible file cache stuff */ -/*--------------------------------------------------------------------------*/ - -/* - | Open a file... - | Returns the file cache handle of the file, or NULL for failure. - | Note that if mode is anything other than "r" the call defers to - | my_fopen(). - | - | NB: The returned handle is almost certainly *NOT* a |FILE*| - | (although it may be if the cache cannot accomodate the file). - | - | Therefore, you *MUST* ensure that any file opened with cached_fopen() - | is only ever accessed via cached_fgets() and cached_fclose(). - | - | Failure to do so will result in, ahem, unpleasantness. Extreme - | unpleasantness. - */ -FILE *cached_fopen(char *name, char *mode) -{ - FileCacheEntry *fcs = NULL; - int fch; - - if (strcmp(mode, "r") || !use_filecache) - return my_fopen(name, mode); - - if (!file_cache_initd) - { - init_file_cache(); - } - - if (max_file_cache_size >= 0) - { - /* Find a free cache entry */ - for (fch = 0; fch < MAX_OPEN_CACHED_FILES; fch++) - if (!cached_file_handle[fch].fce) - break; - - /* Out of handles? */ - if (fch >= MAX_OPEN_CACHED_FILES) - return my_fopen(name, mode); - - /* Is the file already cached? */ - fcs = find_cached_file(name); - if (!fcs) - { - /* File wasn't cached, so cache it */ - flush_file_cache(NULL); /* Clean stuff out of the cache if need be */ - fcs = cache_file(name); /* Cache the new file */ - flush_file_cache(fcs); /* Flush, but keep the latest file */ - } - } - - /* Did we fail to cache the file? */ - if (!fcs) - { - return my_fopen(name, mode); - } - - /* File was cached OK */ - cached_file_handle[fch].ptr = fcs->text; /* Init sequential pointer */ - cached_file_handle[fch].fce = fcs; /* Cache block pointer */ - fcs->used = fc_access_counter++; /* Opening the file counts as an access */ - - return (FILE *)(&cached_file_handle[fch]); -} - - -/* - | Close a file - */ -errr cached_fclose(FILE *fch_) -{ - CachedFileHandle *fch; - - /* Is the FILE* genuine? */ - if ((fch_ < (FILE *)cached_file_handle) || (fch_ > max_cfh_addr)) - return my_fclose(fch_); - - fch = (CachedFileHandle *) fch_; - - /* Check for "Ooopses": */ - if (fch->fce == NULL) - core("cached_fclose called on a non-open file handle"); - - flush_file_cache(NULL); /* Clean out the cache if need be */ - fch->fce = NULL; /* Mark file handle as inactive */ - - return 0; -} - - -/* - | Do the my_fgets thing on a file - */ -errr cached_fgets(FILE *fch_, char *buffer, int max_len) -{ - CachedFileHandle *fch; - char *eof; - char *ptr; - - /* Is the FILE* genuine? */ - if ((fch_ < (FILE *)cached_file_handle) || (fch_ > max_cfh_addr)) - return my_fgets(fch_, buffer, max_len); - - fch = (CachedFileHandle *) fch_; - - /* Check for "Oopses": */ - if (!file_cache_initd) - core("cached_fgets() on uninitialised file-cache"); - if (!fch->fce) - core("cached_fgets called for a un-open file"); - - eof = fch->fce->eof; - ptr = fch->ptr; - - /* Out of bounds? */ - if (ptr >= eof) - { - return 1; - } /* Read failed */ - - /* - | Read the next line, up to \0 (which would have v=been \n in the original file), - | or max_len-1 characters - */ - if (fch->fce->compressed) - ptr += decompress_string(buffer, ptr, max_len); - else - { - if (eof - ptr < max_len) - { - max_len = eof - ptr; - } - for (; max_len >= 1; max_len--) - if ((*buffer++ = *ptr++) == 0) - break; - *buffer = 0; /* terminate (paranoia) */ - } - - /* Update sequential pointer */ - fch->ptr = ptr; - - return 0; -} - -#endif /* USE_FILECACHE */ - - -/* - | This section deals with checking that the .raw files are up to date - | wrt to the .txt files. Note that this function won't work for RISC OS 2 - | (due to the lack of OS_Args 7) so it simply returns 0 to indicate that - | the file isn't OOD. - | - | For this to work, the equivalent function (in init2.c) needs to be - | #if-d out (and this function should be declared). You'll probably - | also need to zap the UNIX #includes at the top of the file - */ - -extern errr check_modification_date(int fd, cptr template_file) -{ - char raw_buf[1024]; - char txt_buf[1024]; - int i; - os_error *e; - - if (os_version() < 300) - { - return 0; - } - - /* Use OS_Args 7 to find out the pathname 'fd' refers to */ - e = SWI(6, 0, SWI_OS_Args, - /* In: */ - 7, /* Get path from filehandle */ - fd, /* file handle */ - raw_buf, /* buffer */ - 0, 0, /* unused */ - 1024 /* size of buffer */ - /* No output regs used */ - ); - if (e) - { - core(e->errmess); - } - - /* Build the path to the template_file */ - path_build(txt_buf, sizeof(txt_buf), ANGBAND_DIR_EDIT, template_file); - - i = file_is_newer(riscosify_name(txt_buf), raw_buf); - - return i; -} - - -/*--------------------------------------------------------------------------*/ - -/* - | This is the hideous IClear hack. Basically what we do is to take a copy - | of the module and kill it in the RMA. Then, on return to the desktop - | we reinstate the module. - | - | NB: This is truly, truly evil. - */ - -static int *iclear_module = NULL; - -/* - | Start the IClear hack - */ -static void iclear_hack(void) -{ - os_error *e; - int code = 0; - int *i; - - /* Get base address of module */ - e = SWI(2, 4, SWI_OS_Module, 18, "IClear", 0, 0, 0, &code); - if (e || !code) - return; - - /* Module size is at code!-4 */ - i = (int *)code; - iclear_module = malloc(i[-1] + 4); - if (!iclear_module) - return; - - /* Copy the module */ - *iclear_module = i[-1]; - memcpy(iclear_module + 1, (void *)code, i[-1]); - - /* Kill the current version */ - e = SWI(2, 0, SWI_OS_Module, 4, "IClear"); - if (e) - { - free(iclear_module); - iclear_module = NULL; - } -} - - -/* - | Remove the IClear hack - */ -static void remove_iclear_hack(void) -{ - os_error *e; - - if (!iclear_module) - return; - - e = SWI(3, 0, SWI_OS_Module, 11, iclear_module + 1, *iclear_module); - if (e) - debug("Failed to reinstall IClear: %s", e->errmess); - - free(iclear_module); - iclear_module = NULL; -} - - - -/*--------------------------------------------------------------------------*/ - -/* Alarm functions */ -static int alarm_ackd = 0; /* has the alarm been acknowledged? */ -static window_handle aw = 0; /* alarm window */ - -/* - | Is the alarm due to go off, ie. is it enabled, and if so - | does the current time match the alarm time? - */ -static void check_alarm() -{ - time_t t; - struct tm *lt; - - alarm_lastcheck = Time_Monotonic(); - - time(&t); - lt = localtime(&t); - if (lt->tm_hour == alarm_h && lt->tm_min == alarm_m) - { - if (!alarm_ackd) alarm_disp = 1; - } - else - { - alarm_ackd = 0; - } - - /* Hack: if the alarm has already been acknowledged then don't re-trigger it */ - if (alarm_ackd) - { - alarm_disp = 0; - } - - /* Hack: if the alarm should make a noise, then make one: */ - if (alarm_disp && alarm_beep == 1) - { - static unsigned int last_beep = 0; - unsigned int t = Time_Monotonic(); - if (t >= last_beep + 100) - { - Sound_SysBeep(); - last_beep = t; - } - } - - /* - | If we're in the desktop then fire the alarm off if need be. - | If we aren't then do nothing - the fullscreen bored() function - | will take care of the alarm. - */ -#ifndef FULLSCREEN_ONLY - if (!fullscreen_font && alarm_disp) - trigger_alarm_desktop(); -#endif /* FULLSCREEN_ONLY */ -} - - -static void ack_alarm(void) -{ - if (aw) - { - Window_Delete(aw); - aw = 0; - } - alarm_ackd = 1; - alarm_disp = 0; - - if (alarm_type == 3) - { - /* One shot alarm */ - alarm_type = 0; - write_alarm_choices(); - } - -} - -#ifndef FULLSCREEN_ONLY -/* - | Click in the (desktop) alarm window - */ -static BOOL Hnd_AlarmClick(event_pollblock * pb, void *ref) -{ - ack_alarm(); - return TRUE; -} - - -/* - | The alarm has gone off in the desktop - */ -static void trigger_alarm_desktop(void) -{ - char buffer[120]; - if (aw) - return; - - aw = Window_Create("alarm", template_TITLEMIN); - if (!aw) - { - core("failed to create Alarm window!"); - } - sprintf(buffer, "Alarm from %s", VARIANT); - Window_SetTitle(aw, buffer); - Event_Claim(event_CLICK, aw, 0, Hnd_AlarmClick, NULL); - Event_Claim(event_CLOSE, aw, event_ANY, Hnd_AlarmClick, NULL); - - Icon_printf(aw, 1, "An alarm was set for %02d:%02d", alarm_h, alarm_m); - Icon_SetText(aw, 2, alarm_message); - Window_Show(aw, open_CENTERED); -} - -#endif /* FULLSCREEN_ONLY */ - - -/*--------------------------------------------------------------------------*/ - -#ifndef FE_DEBUG_INFO -static void show_debug_info(void) -{ - core("main-acn internal logic error 004"); -} -#else - -static int debug_cx = 0; -static int debug_cy = 0; -static int debug_cl = TERM_WHITE; -static int debug_sl = 0; - - -static void debug_cls(void) -{ - Term_clear(); - debug_cx = debug_cy = debug_sl = 0; -} - -static void debug_tcol(int c) -{ - debug_cl = c; -} - - -static void debug_scroll(void) -{ - char **c = ((term_data *)Term)->t.scr->c; /* char array [24][80] */ - byte **a = ((term_data *)Term)->t.scr->a; /* attr array [24][80] */ - int cc; - char tmp[82]; - int y, x, p; - - cc = a[1][0]; - - for (y = 1; y < 23; y++) - { - for (x = p = 0; x < 80; x++) - { - if (a[y][x] != cc) - { - tmp[p] = 0; - Term_putstr(x - p, y - 1, p, cc, tmp); - p = 0; - cc = a[y][x]; - } - tmp[p++] = c[y][x]; - } - Term_putstr(x - p, y - 1, p, cc, tmp); - } - - Term_erase(0, 22, 80); -} - - -static void debug_print_line(char *l) -{ - char *le; - int cr = 0; - - /* Handle scrolling */ - if (debug_cy > 22) - { - debug_cy = 22; - if (--debug_sl < 0) - { - int k; - display_line(0, 23, TERM_YELLOW, "[RET one line, SPC one page]"); - do - { - k = inkey(); - } - while (k != 32 && k != 13); - Term_erase(0, 23, 79); - debug_sl = k == 32 ? 21 : 0; - } - debug_scroll(); - } - - /* Hack: check for NL */ - for (le = l; *le; le++) - if (*le == '\n') - { - cr = 1; - break; - } - - /* display text */ - Term_putstr(debug_cx, debug_cy, le - l, debug_cl, l); - - /* move cursor */ - if (!cr) - { - debug_cx += (le - l); - if (debug_cx >= 80) - { - cr = 1; - } - } - if (cr) - { - debug_cx = 0; - debug_cy += 1; - } - - Term_gotoxy(debug_cx, debug_cy); - -} - - -static int debug_next_line(char *lb, char **t, int cx) -{ - int i = 0; - char *lt = *t; - - if (!*lt) - { - return -1; - } /* Out of text */ - - while (*lt && cx < 80) - { - lb[i] = *lt++; - - if (lb[i] == '\n') /* New line */ - { - cx = 0; /* Cursor x will be 0 after displaying */ - i++; /* Keep the \n in the output */ - break; /* All done */ - } - else if (lb[i] == '\t') /* Tab */ - { - while (cx < 80) - { - lb[i++] = ' '; - cx++; - if ((cx & 7) == 0) - { - break; - } - } - } - else /* Anything else */ - { - cx++; - i++; - } - } - - lb[i] = 0; /* terminate line buffer */ - *t = lt; /* update text pointer */ - return cx; /* return cursor x after printing */ -} - -static void debug_printf(char *fmt, ...) -{ - char buffer[1024]; - char line[82]; - va_list ap; - char *p = buffer; - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - - /* Now split the string into display lines */ - while (debug_next_line(line, &p, debug_cx) >= 0) - debug_print_line(line); -} - - -static void debug_version_info(void) -{ - debug_tcol(TERM_YELLOW); - - debug_printf("\n\nMisc. Info:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\tVariant name = \"%s\"\n", VARIANT); - debug_printf("\tFront-end version: %s\n", PORTVERSION); - debug_printf("\tFront-end compiled: %s %s\n", __TIME__, __DATE__); - debug_printf("\tCompile time flags:\n"); - -#ifdef USE_FILECACHE - debug_printf("\t\tUSE_FILECACHE\n"); -#endif - -#ifdef ABBR_FILECACHE - debug_printf("\t\tABBR_FILECACHE\n"); -#endif - -#ifdef SMART_FILECACHE - debug_printf("\t\tSMART_FILECACHE\n"); -#endif - - debug_tcol(TERM_YELLOW); - debug_printf("\nResource path:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\t\"%s\"\n", resource_path); - - debug_tcol(TERM_YELLOW); - debug_printf("\nTempfile path:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\t\"%s\"\n", scrap_path); - debug_printf("\tScrapfiles are %s deleted at exit.\n", - (flush_scrap ? "" : "NOT")); - - debug_tcol(TERM_YELLOW); - debug_printf("\nChoices files:\n"); - debug_tcol(TERM_L_BLUE); - debug_printf("\tDesired files:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\tPrimary (r/w): \"%s\"\n", choices_file[CHFILE_WRITE]); - debug_printf("\t Fallback (r): \"%s\"\n", choices_file[CHFILE_READ]); - debug_printf("\t Mirror (r/w): \"%s\"\n", choices_file[CHFILE_MIRROR]); - debug_tcol(TERM_L_BLUE); - debug_printf("\tActual files:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\t Write: \"%s\"\n", find_choices(TRUE)); - debug_printf("\t Read: \"%s\"\n", find_choices(FALSE)); - - debug_tcol(TERM_YELLOW); - debug_printf("\nAlarm files:\n"); - debug_tcol(TERM_L_BLUE); - debug_printf("\tDesired files:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\tPrimary (r/w): \"%s\"\n", alarm_file[CHFILE_WRITE]); - debug_printf("\t Fallback (r): \"%s\"\n", alarm_file[CHFILE_READ]); - debug_tcol(TERM_L_BLUE); - debug_printf("\tActual files:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\t Write: \"%s\"\n", find_alarmfile(TRUE)); - debug_printf("\t Read: \"%s\"\n", find_alarmfile(FALSE)); -#ifdef USE_DA - debug_tcol(TERM_YELLOW); - debug_printf("\nDynamic areas:\n"); - debug_tcol(TERM_WHITE); - debug_printf("\tFontcache DA = %d\t", font_area); - debug_printf("size = %d\theap size = %d\n", font_area_size, font_heap_size); - debug_printf("\t ralloc DA = %d\t", game_area); - debug_printf("size = %d\theap size = %d\n", game_area_size, game_heap_size); -#endif -} - - -static void debug_filecache_info(void) -{ -#ifndef USE_FILECACHE - debug_tcol(TERM_L_DARK); - debug_printf("File cache disabled at compile time.\n"); -#else - int j, k; - int t, cs, ucs, cf; - - cf = cs = ucs = j = k = 0; /* To stop an usused warning if USE_FILECACHE is undefined */ - t = strlen(resource_path); - - if (!file_cache_initd) - { - init_file_cache(); - } /* Paranoia */ - debug_tcol(TERM_YELLOW); - debug_printf("\nFilecache contents:\n"); - debug_tcol(TERM_L_BLUE); - debug_printf("Flags: Smart=%d; Abbrv=%d; Slave=%d; Enable=%d\n", - smart_filecache, abbr_filecache, abbr_tmpfile, use_filecache); - debug_tcol(TERM_SLATE); - if (smart_filecache || abbr_filecache) - debug_printf("\t\t%3s %6s/%-6s %6s %6s Path (relative to lib/)\n", - "Hnd", "Cache", "Disc", "Time", "Status"); - else - debug_printf("\t\t%3s %6s %6s %6s Path (relative to lib/)\n", "Hnd", - "Size", "Time", "Status"); - - for (j = 0; j < MAX_CACHE_ENTRIES; j++) - { - FileCacheEntry *fce = &(file_cache[j]); - if (fce->name) - { - cf++; - debug_tcol(TERM_L_GREEN); - debug_printf("\t\t%3d ", j); - debug_tcol(TERM_L_UMBER); - if (!smart_filecache && !abbr_filecache) - debug_printf("%6d ", fce->eof - fce->text); - else - { - debug_printf("%6d/", fce->eof - fce->text); - k = myFile_Size(riscosify_name(fce->name)); - debug_printf("%-6d ", k); - if (k > 0) - { - ucs += k; - } - } - cs += fce->eof - fce->text; - debug_printf("%6d ", fce->used); - for (k = 0; k < MAX_OPEN_CACHED_FILES; k++) - if (cached_file_handle[k].fce == fce) - break; - debug_tcol(TERM_RED); - debug_printf("%-6s ", k < MAX_OPEN_CACHED_FILES ? "Open" : ""); - debug_tcol(TERM_L_UMBER); - debug_printf("%s\n", fce->name + t); - } - } - - debug_tcol(TERM_L_BLUE); - debug_printf("\tTotal:\t%3d ", cf); - if (ucs) - debug_printf("%6d/%-6d\n", cs, ucs); - else - debug_printf("%6d\n", cs); - debug_tcol(TERM_BLUE); -#endif /* USE_FILECACHE */ -} - - -static void show_debug_info(void) -{ - int k; - /* blank the term */ - debug_cls(); - - /* Repeatedly prompt for a command */ - do - { - debug_tcol(TERM_VIOLET); - debug_printf("\nInfo: (V)ersion, (F)ilecache, ESC=exit "); - do - { - k = inkey(); - switch (k) - { - case 'v': case 'V': debug_version_info(); - break; - case 'f': case 'F': debug_filecache_info - (); - break; - case 27: break; - default: k = 0; - } - } - while (!k); - } - while (k != 27); - - Term_clear(); -} - -#endif /* FE_DEBUG_INFO */ - -#endif /* __riscos */ - - |