From 8fb373998031f662bfcc6473e404e4fe2e72905d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 3 Mar 2012 20:59:35 +0100 Subject: gtk1: Removed GTK (1.x) front-end --- src/main-gtk.c | 5251 -------------------------------------------------------- src/main.c | 13 - 2 files changed, 5264 deletions(-) delete mode 100644 src/main-gtk.c diff --git a/src/main-gtk.c b/src/main-gtk.c deleted file mode 100644 index 367959cb..00000000 --- a/src/main-gtk.c +++ /dev/null @@ -1,5251 +0,0 @@ -/* File: main-gtk.c */ - -/* - * Copyright (c) 2000-2001 Robert Ruehlmann, - * Steven Fuerst, Uwe Siems, "pelpel", et al. - * - * This software may be copied and distributed for educational, research, - * and not for profit purposes provided that this copyright and statement - * are included in all such copies. - */ - -/* - * Robert Ruehlmann wrote the original Gtk port. Since an initial work is - * much harder than enhancements, his effort worth more credits than - * others. - * - * Steven Fuerst implemented colour-depth independent X server support, - * graphics, resizing and big screen support for ZAngband as well as - * fast image rescaling that is included here. - * - * Uwe Siems wrote smooth tiles rescaling code (on by default). - * Try this with 8x8 tiles. They *will* look different. - * - * "pelpel" wrote another colour-depth independent X support - * using GdkRGB, added several hooks and callbacks for various - * reasons, wrote no-backing store mode (off by default), - * added GtkItemFactory based menu system, introduced - * USE_GRAPHICS code bloat (^ ^;), added comments (I have - * a strange habit of writing comments while I code...) - * and reorganised the file a bit. - */ - -#include "angband.h" - - -/* - * Activate variant-specific features - * - * Angband 2.9.3 and close variants don't require any. - * - * Angband 2.9.4 alpha and later removed the short-lived - * can_save flag, so please #define can_save TRUE, or remove - * all the references to it. They also changed long-lived - * z-virt macro names. Find C_FREE/C_KILL and replace them - * with FREE/KILL, which takes one pointer parameter. - * - * [Z]-based variants (Gum and Cth, for example) usually need - * ANG293_COMPAT, ANG291_COMPAT and ANG281_RESET_VISUALS. - * - * [O] needs ANG293_COMPAT and ZANG_SAVE_GAME. - * - * ZAngband has its own enhanced main-gtk.c as mentioned above, and - * you *should* use it :-) - * - * ANG291_COMPAT does not include Angband 2.9.x's gamma correction code. - * If you like to use SUPPORT_GAMMA, copy the code bracketed - * inside of #ifdef SUPPORT_GAMMA in util.c of Angband 2.9.1 or greater. - */ -#define TOME - -#ifdef TOME -# define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ -# define ANG291_COMPAT /* Requires V2.9.1 compatibility code */ -# define ANG281_RESET_VISUALS /* The old style reset_visuals() */ -# define INTERACTIVE_GAMMA /* Supports interactive gamma correction */ -# define SAVEFILE_SCREEN /* New/Open integrated into the game */ -# define USE_DOUBLE_TILES /* Mogami's bigtile patch */ -#endif /* TOME */ - -/* - * Some examples - */ -#ifdef ANGBAND300 -# define can_save TRUE /* Mimick the short-lived flag */ -# define C_FREE(P, N, T) FREE(P) /* Emulate the long-lived macro */ -# define USE_TRANSPARENCY /* Because it's default now */ -#endif /* ANGBAND300 */ - -#ifdef GUMBAND -# define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ -# define ANG291_COMPAT /* Requires V2.9.1 compatibility code */ -# define ANG281_RESET_VISUALS /* The old style reset_visuals() */ -# define OLD_SAVEFILE_CODE /* See also SAVEFILE_MUTABLE in files.c */ -# define NO_REDRAW_SECTION /* Doesn't have Term_redraw_section() */ -#endif /* GUMBAND */ - -#ifdef OANGBAND -# define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ -# define ZANG_SAVE_GAME /* do_cmd_save_game with auto_save parameter */ -#endif /* OANGBAND */ - - -#ifdef USE_GTK - -/* Force ANSI standard */ -/* #define __STRICT_ANSI__ */ - -/* No GCC-specific includes */ -/* #undef __GNUC__ */ - -#include -#include -#include -#include -#include -#include - -/* /me pffts Solaris */ -#ifndef NAME_MAX -#define NAME_MAX _POSIX_NAME_MAX -#endif - - -/* - * Include some helpful X11 code. - */ -#ifndef ANG293_COMPAT -# include "maid-x11.h" -#endif /* !ANG293_COMPAT */ - - -/* - * Number of pixels inserted between the menu bar and the main screen - */ -#define NO_PADDING 0 - - -/* - * Largest possible number of terminal windows supported by the game - */ -#define MAX_TERM_DATA 8 - - -/* - * Extra data to associate with each "window" - * - * Each "window" is represented by a "term_data" structure, which - * contains a "term" structure, which contains a pointer (t->data) - * back to the term_data structure. - */ - -#ifdef USE_GRAPHICS - -/* - * Since GdkRGB doesn't provide us some useful functions... - */ -typedef struct GdkRGBImage GdkRGBImage; - -struct GdkRGBImage -{ - gint width; - gint height; - gint ref_count; - guchar *image; -}; - -#endif /* USE_GRAPHICS */ - - -/* - * This structure holds everything you need to manipulate terminals - */ -typedef struct term_data term_data; - -struct term_data -{ - term t; - - GtkWidget *window; - GtkWidget *drawing_area; - GdkPixmap *backing_store; - GdkFont *font; - GdkGC *gc; - - bool_ shown; - byte last_attr; - - int font_wid; - int font_hgt; - - int rows; - int cols; - -#ifdef USE_GRAPHICS - - int tile_wid; - int tile_hgt; - - GdkRGBImage *tiles; -# ifdef USE_TRANSPARENCY - guint32 bg_pixel; - GdkRGBImage *trans_buf; -# endif /* USE_TRANSPARENCY */ - -#endif /* USE_GRAPHICS */ - - cptr name; -}; - - -/* - * Where to draw when we call Gdk drawing primitives - */ -# define TERM_DATA_DRAWABLE(td) \ -((td)->backing_store ? (td)->backing_store : (td)->drawing_area->window) - -# define TERM_DATA_REFRESH(td, x, y, wid, hgt) \ -if ((td)->backing_store) gdk_draw_pixmap( \ -(td)->drawing_area->window, \ -(td)->gc, \ -(td)->backing_store, \ -(x) * (td)->font_wid, \ -(y) * (td)->font_hgt, \ -(x) * (td)->font_wid, \ -(y) * (td)->font_hgt, \ -(wid) * (td)->font_wid, \ -(hgt) * (td)->font_hgt) - - -#if 0 - -/* Compile time option version */ - -# ifdef USE_BACKING_STORE - -# define TERM_DATA_DRAWABLE(td) (td)->backing_store - -# define TERM_DATA_REFRESH(td, x, y, wid, hgt) \ -gdk_draw_pixmap( \ -(td)->drawing_area->window, \ -(td)->gc, \ -(td)->backing_store, \ -(x) * (td)->font_wid, \ -(y) * (td)->font_hgt, \ -(x) * (td)->font_wid, \ -(y) * (td)->font_hgt, \ -(wid) * (td)->font_wid, \ -(hgt) * (td)->font_hgt) - -# else /* USE_BACKING_STORE */ - -# define TERM_DATA_DRAWABLE(td) (td)->drawing_area->window -# define TERM_DATA_REFRESH(td, x, y, wid, hgt) - -# endif /* USE_BACKING_STORE */ - -#endif /* 0 */ - - -/* - * An array of "term_data" structures, one for each "sub-window" - */ -static term_data data[MAX_TERM_DATA]; - -/* - * Number of active terms - */ -static int num_term = 1; - - -/* - * RGB values of the sixteen Angband colours - */ -static guint32 angband_colours[16]; - - -/* - * Set to TRUE when a game is in progress - */ -static bool_ game_in_progress = FALSE; - - -/* - * This is in some cases used for double buffering as well as - * a backing store, speeding things up under client-server - * configurations, while turning this off *might* work better - * with the MIT Shm extention which is usually active if you run - * Angband locally, because it reduces amount of memory-to-memory copy. - */ -static bool_ use_backing_store = TRUE; - - - - -/**** Vanilla compatibility functions ****/ - -#ifdef ANG293_COMPAT - -/* - * Look up some environment variables to find font name for each window. - */ -static cptr get_default_font(int term) -{ - char buf[64]; - cptr font_name; - - /* Window specific font name */ - strnfmt(buf, 64, "ANGBAND_X11_FONT_%s", angband_term_name[term]); - - /* Check environment for that font */ - font_name = getenv(buf); - - /* Window specific font name */ - strnfmt(buf, 64, "ANGBAND_X11_FONT_%d", term); - - /* Check environment for that font */ - if (!font_name) font_name = getenv(buf); - - /* Check environment for "base" font */ - if (!font_name) font_name = getenv("ANGBAND_X11_FONT"); - - /* No environment variables, use default font */ - if (!font_name) font_name = DEFAULT_X11_FONT_SCREEN; - - return (font_name); -} - - -# ifndef SAVEFILE_SCREEN - -/* - * In [V]2.9.3, this frees all dynamically allocated memory - */ -static void cleanup_angband(void) -{ - /* XXX XXX XXX */ -} - -# endif /* !SAVEFILE_SCREEN */ - -/* - * New global flag to indicate if it's safe to save now - */ -#define can_save TRUE - -#endif /* ANG293_COMPAT */ - - -#ifdef ANG291_COMPAT - -/* - * The standard game uses this to implement lighting effects - * for 16x16 tiles in cave.c... - * - * Because of the way it is implemented in X11 ports, - * we can set this to TRUE even if we are using the 8x8 tileset. - */ -static bool_ use_transparency = TRUE; - -#endif /* ANG291_COMPAT */ - - - - -/**** Low level routines - memory allocation ****/ - -/* - * Hook to "release" memory - */ -#ifdef ANGBAND300 -static vptr hook_rnfree(vptr v) -#else -static vptr hook_rnfree(vptr v, huge size) -#endif /* ANGBAND300 */ -{ - /* Dispose */ - g_free(v); - - /* Success */ - return (NULL); -} - - -/* - * Hook to "allocate" memory - */ -static vptr hook_ralloc(huge size) -{ - /* Make a new pointer */ - return (g_malloc(size)); -} - - - -/**** Low level routines - colours and graphics ****/ - -#ifdef SUPPORT_GAMMA - -/* - * When set to TRUE, indicates that we can use gamma_table - */ -static bool_ gamma_table_ready = FALSE; - - -# ifdef INTERACTIVE_GAMMA - -/* - * Initialise the gamma-correction table for current gamma_val - * - interactive version - */ -static void setup_gamma_table(void) -{ - static u16b old_gamma_val = 0; - - /* Don't have to rebuild the table */ - if (gamma_val == old_gamma_val) return; - - /* Temporarily inactivate the table */ - gamma_table_ready = FALSE; - - /* Validate gamma_val */ - if ((gamma_val <= 0) || (gamma_val >= 256)) - { - /* Reset */ - old_gamma_val = gamma_val = 0; - - /* Leave it inactive */ - return; - } - - /* (Re)build the gamma table */ - build_gamma_table(gamma_val); - - /* Remember the gamma value used */ - old_gamma_val = gamma_val; - - /* Activate the table */ - gamma_table_ready = TRUE; -} - -# else /* INTERACTIVE_GAMMA */ - -/* - * Initialise the gamma-correction table if environment variable - * ANGBAND_X11_GAMMA is set and contains a meaningful value - * - * Restored for cross-variant compatibility - */ -static void setup_gamma_table(void) -{ - cptr tmp; - int gamma_val; - - - /* The table's already set up */ - if (gamma_table_ready) return; - - /* - * XXX XXX It's documented nowhere, but ANGBAND_X11_GAMMA is - * 256 * (1 / gamma), rounded to integer. A recommended value - * is 183, which is an approximation of the Macintosh hardware - * gamma of 1.4. - * - * gamma ANGBAND_X11_GAMMA - * ----- ----------------- - * 1.2 213 - * 1.25 205 - * 1.3 197 - * 1.35 190 - * 1.4 183 - * 1.45 177 - * 1.5 171 - * 1.6 160 - * 1.7 151 - * ... - * - * XXX XXX The environment variable, or better, - * the interact with colours command should allow users - * to specify gamma values (or gamma value * 100). - */ - tmp = getenv("ANGBAND_X11_GAMMA"); - - /* Nothing to do */ - if (tmp == NULL) return; - - /* Extract the value */ - gamma_val = atoi(tmp); - - /* - * Only need to build the table if gamma exists and set to - * a meaningful value. - * - * XXX It may be a good idea to prevent use of very high gamma values, - * say, greater than 2.5, which is gamma of normal CRT display IIRC. - */ - if ((gamma_val <= 0) || (gamma_val >= 256)) return; - - /* Build the gamma correction table */ - build_gamma_table(gamma_val); - - /* The table is properly set up */ - gamma_table_ready = TRUE; -} - -# endif /* INTERACTIVE_GAMMA */ - -#endif /* SUPPORT_GAMMA */ - - -/* - * Remeber RGB values for sixteen Angband colours, in a format - * that is convinient for GdkRGB GC functions. - * - * XXX XXX Duplication of maid-x11.c is far from the Angband - * ideal of code cleanliness, but the whole point of using GdkRGB - * is to let it handle colour allocation which it does in a very - * clever fashion. Ditto for the tile scaling code and the BMP loader - * below. - */ -static void init_colours(void) -{ - int i; - - -#ifdef SUPPORT_GAMMA - - /* (Re)build gamma table if necessary */ - setup_gamma_table(); - -#endif /* SUPPORT_GAMMA */ - - /* Process each colour */ - for (i = 0; i < 16; i++) - { - u32b red, green, blue; - - /* Retrieve RGB values from the game */ - red = angband_color_table[i][1]; - green = angband_color_table[i][2]; - blue = angband_color_table[i][3]; - -#ifdef SUPPORT_GAMMA - - /* Hack -- Gamma Correction */ - if (gamma_table_ready) - { - red = gamma_table[red]; - green = gamma_table[green]; - blue = gamma_table[blue]; - } - -#endif /* SUPPORT_GAMMA */ - - /* Remember a GdkRGB value, that is 0xRRGGBB */ - angband_colours[i] = (red << 16) | (green << 8) | blue; - } -} - - -/* - * Set foreground colour of window td to attr, only when it is necessary - */ -static void term_data_set_fg(term_data *td, byte attr) -{ - /* We can use the current gc */ - if (td->last_attr == attr) return; - - /* Activate the colour */ - gdk_rgb_gc_set_foreground(td->gc, angband_colours[attr]); - - /* Remember it */ - td->last_attr = attr; -} - - -#ifdef USE_GRAPHICS - -/* - * Graphics mode selector - current setting and requested value - */ -#define GRAF_MODE_NONE 0 -#define GRAF_MODE_OLD 1 -#define GRAF_MODE_NEW 2 - -static int graf_mode = GRAF_MODE_NONE; -static int graf_mode_request = GRAF_MODE_NONE; - -/* - * Use smooth rescaling? - */ -static bool_ smooth_rescaling = TRUE; -static bool_ smooth_rescaling_request = TRUE; - -/* - * Dithering - */ -static GdkRgbDither dith_mode = GDK_RGB_DITHER_NORMAL; - -/* - * Need to reload and resize tiles when fonts are changed. - */ -static bool_ resize_request = FALSE; - -/* - * Numbers of columns and rows in current tileset - * calculated and set by the tile loading code in graf_init() - * and used by Term_pict_gtk() - */ -static int tile_rows; -static int tile_cols; - - -/* - * Directory name(s) - */ -static cptr ANGBAND_DIR_XTRA_GRAF; - - -/* - * Be nice to old graphics hardwares -- using GdkRGB. - * - * We don't have colour allocation failure any longer this way, - * even with 8bpp X servers. Gimp *does* work with 8bpp, why not Angband? - * - * Initialisation (before any widgets are created) - * gdk_rgb_init(); - * gtk_widget_set_default_colormap (gdk_rgb_get_cmap()); - * gtk_widget_set_default_visual (gdk_rgb_get_visual()); - * - * Setting fg/bg colours - * void gdk_rgb_gc_set_foreground(GdkGC *gc, guint32 rgb); - * void gdk_rgb_gc_set_background(GdkGC *gc, guint32 rgb); - * where rgb is 0xRRGGBB. - * - * Drawing rgb images - * void gdk_draw_rgb_image( - * GdkDrawable *drawable, - * GdkGC *gc, - * gint x, gint y, - * gint width, gint height, - * GdkRgbDither dith, - * guchar *rgb_buf, - * gint rowstride); - * - * dith: - * GDK_RGB_DITHER_NORMAL : dither if 8bpp or below - * GDK_RGB_DITHER_MAX : dither if 16bpp or below. - * - * for 0 <= i < width and 0 <= j < height, - * the pixel (x + i, y + j) is colored with - * red value rgb_buf[j * rowstride + i * 3], - * green value rgb_buf[j * rowstride + i * 3 + 1], and - * blue value rgb_buf[j * rowstride + i * 3 + 2]. - */ - -/* - * gdk_image compatibility functions - should be part of gdk, IMHO. - */ - -/* - * Create GdkRGBImage of width * height and return pointer - * to it. Returns NULL on failure - */ -static GdkRGBImage *gdk_rgb_image_new( - gint width, - gint height) -{ - GdkRGBImage *result; - - /* Allocate a struct */ - result = g_new(GdkRGBImage, 1); - - /* Oops */ - if (result == NULL) return (NULL); - - /* Allocate buffer */ - result->image = g_new0(guchar, width * height * 3); - - /* Oops */ - if (result->image == NULL) - { - g_free(result); - return (NULL); - } - - /* Initialise size fields */ - result->width = width; - result->height = height; - - /* Initialise reference count */ - result->ref_count = 1; - - /* Success */ - return (result); -} - -/* - * Free a GdkRGBImage - */ -static void gdk_rgb_image_destroy( - GdkRGBImage *im) -{ - /* Paranoia */ - if (im == NULL) return; - - /* Free the RGB buffer */ - g_free(im->image); - - /* Free the structure */ - g_free(im); -} - - -#if 0 - -/* - * Unref a GdkRGBImage - */ -static void gdk_rgb_image_unref( - GdkRGBImage *im) -{ - /* Paranoia */ - g_return_if_fail(im != NULL); - - /* Decrease reference count by 1 */ - im->ref_count--; - - /* Free if nobody's using it */ - if (im->ref_count <= 0) gdk_rgb_image_destroy(im); -} - - -/* - * Reference a GdkRGBImage - */ -static void gdk_rgb_image_ref( - GdkRGBImage *im) -{ - /* Paranoia */ - g_return_if_fail(im != NULL); - - /* Increase reference count by 1 */ - im->ref_count++; -} - -#endif /* 0 */ - - -/* - * Write RGB pixel of the format 0xRRGGBB to (x, y) in GdkRGBImage - */ -static void gdk_rgb_image_put_pixel( - GdkRGBImage *im, - gint x, - gint y, - guint32 pixel) -{ - guchar *rgbp; - - /* Paranoia */ - g_return_if_fail(im != NULL); - - /* Paranoia */ - if ((x < 0) || (x >= im->width)) return; - - /* Paranoia */ - if ((y < 0) || (y >= im->height)) return; - - /* Access RGB data */ - rgbp = &im->image[(y * im->width * 3) + (x * 3)]; - - /* Red */ - *rgbp++ = (pixel >> 16) & 0xFF; - /* Green */ - *rgbp++ = (pixel >> 8) & 0xFF; - /* Blue */ - *rgbp = pixel & 0xFF; -} - - -/* - * Returns RGB pixel (0xRRGGBB) at (x, y) in GdkRGBImage - */ -static guint32 gdk_rgb_image_get_pixel( - GdkRGBImage *im, - gint x, - gint y) -{ - guchar *rgbp; - - /* Paranoia */ - if (im == NULL) return (0); - - /* Paranoia - returns black */ - if ((x < 0) || (x >= im->width)) return (0); - - /* Paranoia */ - if ((y < 0) || (y >= im->height)) return (0); - - /* Access RGB data */ - rgbp = &im->image[(y * im->width * 3) + (x * 3)]; - - /* Return result */ - return ((rgbp[0] << 16) | (rgbp[1] << 8) | (rgbp[2])); -} - - -/* - * Since gdk_draw_rgb_image is a bit harder to use than it's - * GdkImage counterpart, I wrote a grue function that takes - * exactly the same parameters as gdk_draw_image, with - * the GdkImage parameter replaced with GdkRGBImage. - */ -static void gdk_draw_rgb_image_2( - GdkDrawable *drawable, - GdkGC *gc, - GdkRGBImage *image, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height) -{ - /* Paranoia */ - g_return_if_fail(drawable != NULL); - g_return_if_fail(image != NULL); - - /* Paranoia */ - if (xsrc < 0 || (xsrc + width - 1) >= image->width) return; - if (ysrc < 0 || (ysrc + height - 1) >= image->height) return; - - /* Draw the image at (xdest, ydest), with dithering if bpp <= 8/16 */ - gdk_draw_rgb_image( - drawable, - gc, - xdest, - ydest, - width, - height, - dith_mode, - &image->image[(ysrc * image->width * 3) + (xsrc * 3)], - image->width * 3); -} - - -/* - * Code for smooth icon rescaling from Uwe Siems, Jan 2000 - * - * XXX XXX Duplication of maid-x11.c, again. It doesn't do any colour - * allocation, either. - */ - -/* - * to save ourselves some labour, define a maximum expected icon width here: - */ -#define MAX_ICON_WIDTH 32 - - -/* - * Each pixel is kept in this structure during smooth rescaling - * calculations, to make things a bit easier - */ -typedef struct rgb_type rgb_type; - -struct rgb_type -{ - guint32 red; - guint32 green; - guint32 blue; -}; - -/* - * Because there are many occurences of this, and because - * it's logical to do so... - */ -#define pixel_to_rgb(pix, rgb_buf) \ -(rgb_buf)->red = ((pix) >> 16) & 0xFF; \ -(rgb_buf)->green = ((pix) >> 8) & 0xFF; \ -(rgb_buf)->blue = (pix) & 0xFF - - -/* - * get_scaled_row reads a scan from the given GdkRGBImage, scales it smoothly - * and returns the red, green and blue values in arrays. - * The values in this arrays must be divided by a certain value that is - * calculated in scale_icon. - * x, y is the position, iw is the input width and ow the output width - * scan must be sufficiently sized - */ -static void get_scaled_row( - GdkRGBImage *im, - int x, - int y, - int iw, - int ow, - rgb_type *scan) -{ - int xi, si, sifrac, ci, cifrac, add_whole, add_frac; - guint32 pix; - rgb_type prev; - rgb_type next; - bool_ get_next_pix; - - /* Unscaled */ - if (iw == ow) - { - for (xi = 0; xi < ow; xi++) - { - pix = gdk_rgb_image_get_pixel(im, x + xi, y); - pixel_to_rgb(pix, &scan[xi]); - } - } - - /* Scaling by subsampling (grow) */ - else if (iw < ow) - { - iw--; - ow--; - - /* read first pixel: */ - pix = gdk_rgb_image_get_pixel(im, x, y); - pixel_to_rgb(pix, &next); - prev = next; - - /* si and sifrac give the subsampling position: */ - si = x; - sifrac = 0; - - /* get_next_pix tells us, that we need the next pixel */ - get_next_pix = TRUE; - - for (xi = 0; xi <= ow; xi++) - { - if (get_next_pix) - { - prev = next; - if (xi < ow) - { - /* only get next pixel if in same icon */ - pix = gdk_rgb_image_get_pixel(im, si + 1, y); - pixel_to_rgb(pix, &next); - } - } - - /* calculate subsampled color values: */ - /* division by ow occurs in scale_icon */ - scan[xi].red = prev.red * (ow - sifrac) + next.red * sifrac; - scan[xi].green = prev.green * (ow - sifrac) + next.green * sifrac; - scan[xi].blue = prev.blue * (ow - sifrac) + next.blue * sifrac; - - /* advance sampling position: */ - sifrac += iw; - if (sifrac >= ow) - { - si++; - sifrac -= ow; - get_next_pix = TRUE; - } - else - { - get_next_pix = FALSE; - } - - } - } - - /* Scaling by averaging (shrink) */ - else - { - /* width of an output pixel in input pixels: */ - add_whole = iw / ow; - add_frac = iw % ow; - - /* start position of the first output pixel: */ - si = x; - sifrac = 0; - - /* get first input pixel: */ - pix = gdk_rgb_image_get_pixel(im, x, y); - pixel_to_rgb(pix, &next); - - for (xi = 0; xi < ow; xi++) - { - /* find endpoint of the current output pixel: */ - ci = si + add_whole; - cifrac = sifrac + add_frac; - if (cifrac >= ow) - { - ci++; - cifrac -= ow; - } - - /* take fraction of current input pixel (starting segment): */ - scan[xi].red = next.red * (ow - sifrac); - scan[xi].green = next.green * (ow - sifrac); - scan[xi].blue = next.blue * (ow - sifrac); - si++; - - /* add values for whole pixels: */ - while (si < ci) - { - rgb_type tmp_rgb; - - pix = gdk_rgb_image_get_pixel(im, si, y); - pixel_to_rgb(pix, &tmp_rgb); - scan[xi].red += tmp_rgb.red * ow; - scan[xi].green += tmp_rgb.green * ow; - scan[xi].blue += tmp_rgb.blue * ow; - si++; - } - - /* add fraction of current input pixel (ending segment): */ - if (xi < ow - 1) - { - /* only get next pixel if still in icon: */ - pix = gdk_rgb_image_get_pixel(im, si, y); - pixel_to_rgb(pix, &next); - } - - sifrac = cifrac; - if (sifrac > 0) - { - scan[xi].red += next.red * sifrac; - scan[xi].green += next.green * sifrac; - scan[xi].blue += next.blue * sifrac; - } - } - } -} - - -/* - * put_rgb_scan takes arrays for red, green and blue and writes pixel values - * according to this values in the GdkRGBImage-structure. w is the number of - * pixels to write and div is the value by which all red/green/blue values - * are divided first. - */ -static void put_rgb_scan( - GdkRGBImage *im, - int x, - int y, - int w, - int div, - rgb_type *scan) -{ - int xi; - guint32 pix; - guint32 adj = div / 2; - - for (xi = 0; xi < w; xi++) - { - byte r, g, b; - - /* un-factor the RGB values */ - r = (scan[xi].red + adj) / div; - g = (scan[xi].green + adj) / div; - b = (scan[xi].blue + adj) / div; - -#ifdef SUPPORT_GAMMA - - /* Apply gamma correction if requested and available */ - if (gamma_table_ready) - { - r = gamma_table[r]; - g = gamma_table[g]; - b = gamma_table[b]; - } - -#endif /* SUPPORT_GAMMA */ - - /* Make a (virtual) 24-bit pixel */ - pix = (r << 16) | (g << 8) | (b); - - /* Draw it into image */ - gdk_rgb_image_put_pixel(im, x + xi, y, pix); - } -} - - -/* - * scale_icon transfers an area from GdkRGBImage im_in, locate (x1,y1) to - * im_out, locate (x2, y2). Source size is (ix, iy) and destination size - * is (ox, oy). - * - * It does this by getting icon scan line from get_scaled_scan and handling - * them the same way as pixels are handled in get_scaled_scan. - * This even allows icons to be scaled differently in horizontal and - * vertical directions (eg. shrink horizontal, grow vertical). - */ -static void scale_icon( - GdkRGBImage *im_in, - GdkRGBImage *im_out, - int x1, - int y1, - int x2, - int y2, - int ix, - int iy, - int ox, - int oy) -{ - int div; - int xi, yi, si, sifrac, ci, cifrac, add_whole, add_frac; - - /* buffers for pixel rows: */ - rgb_type prev[MAX_ICON_WIDTH]; - rgb_type next[MAX_ICON_WIDTH]; - rgb_type temp[MAX_ICON_WIDTH]; - - bool_ get_next_row; - - /* get divider value for the horizontal scaling: */ - if (ix == ox) - div = 1; - else if (ix < ox) - div = ox - 1; - else - div = ix; - - /* no scaling needed vertically: */ - if (iy == oy) - { - for (yi = 0; yi < oy; yi++) - { - get_scaled_row(im_in, x1, y1 + yi, ix, ox, temp); - put_rgb_scan(im_out, x2, y2 + yi, ox, div, temp); - } - } - - /* scaling by subsampling (grow): */ - else if (iy < oy) - { - iy--; - oy--; - div *= oy; - - /* get first row: */ - get_scaled_row(im_in, x1, y1, ix, ox, next); - - /* si and sifrac give the subsampling position: */ - si = y1; - sifrac = 0; - - /* get_next_row tells us, that we need the next row */ - get_next_row = TRUE; - for (yi = 0; yi <= oy; yi++) - { - if (get_next_row) - { - for (xi = 0; xi < ox; xi++) - { - prev[xi] = next[xi]; - } - if (yi < oy) - { - /* only get next row if in same icon */ - get_scaled_row(im_in, x1, si + 1, ix, ox, next); - } - } - - /* calculate subsampled color values: */ - /* division by oy occurs in put_rgb_scan */ - for (xi = 0; xi < ox; xi++) - { - temp[xi].red = (prev[xi].red * (oy - sifrac) + - next[xi].red * sifrac); - temp[xi].green = (prev[xi].green * (oy - sifrac) + - next[xi].green * sifrac); - temp[xi].blue = (prev[xi].blue * (oy - sifrac) + - next[xi].blue * sifrac); - } - - /* write row to output image: */ - put_rgb_scan(im_out, x2, y2 + yi, ox, div, temp); - - /* advance sampling position: */ - sifrac += iy; - if (sifrac >= oy) - { - si++; - sifrac -= oy; - get_next_row = TRUE; - } - else - { - get_next_row = FALSE; - } - - } - } - - /* scaling by averaging (shrink) */ - else - { - div *= iy; - - /* height of a output row in input rows: */ - add_whole = iy / oy; - add_frac = iy % oy; - - /* start position of the first output row: */ - si = y1; - sifrac = 0; - - /* get first input row: */ - get_scaled_row(im_in, x1, y1, ix, ox, next); - for (yi = 0; yi < oy; yi++) - { - /* find endpoint of the current output row: */ - ci = si + add_whole; - cifrac = sifrac + add_frac; - if (cifrac >= oy) - { - ci++; - cifrac -= oy; - } - - /* take fraction of current input row (starting segment): */ - for (xi = 0; xi < ox; xi++) - { - temp[xi].red = next[xi].red * (oy - sifrac); - temp[xi].green = next[xi].green * (oy - sifrac); - temp[xi].blue = next[xi].blue * (oy - sifrac); - } - si++; - - /* add values for whole pixels: */ - while (si < ci) - { - get_scaled_row(im_in, x1, si, ix, ox, next); - for (xi = 0; xi < ox; xi++) - { - temp[xi].red += next[xi].red * oy; - temp[xi].green += next[xi].green * oy; - temp[xi].blue += next[xi].blue * oy; - } - si++; - } - - /* add fraction of current input row (ending segment): */ - if (yi < oy - 1) - { - /* only get next row if still in icon: */ - get_scaled_row(im_in, x1, si, ix, ox, next); - } - sifrac = cifrac; - for (xi = 0; xi < ox; xi++) - { - temp[xi].red += next[xi].red * sifrac; - temp[xi].green += next[xi].green * sifrac; - temp[xi].blue += next[xi].blue * sifrac; - } - - /* write row to output image: */ - put_rgb_scan(im_out, x2, y2 + yi, ox, div, temp); - } - } -} - - -/* - * Rescale icons using sort of anti-aliasing technique. - */ -static GdkRGBImage *resize_tiles_smooth( - GdkRGBImage *im, - int ix, - int iy, - int ox, - int oy) -{ - int width1, height1, width2, height2; - int x1, x2, y1, y2; - - GdkRGBImage *tmp; - - /* Original size */ - width1 = im->width; - height1 = im->height; - - /* Rescaled size */ - width2 = ox * width1 / ix; - height2 = oy * height1 / iy; - - /* Allocate GdkRGBImage for resized tiles */ - tmp = gdk_rgb_image_new(width2, height2); - - /* Oops */ - if (tmp == NULL) return (NULL); - - /* Scale each icon */ - for (y1 = 0, y2 = 0; (y1 < height1) && (y2 < height2); y1 += iy, y2 += oy) - { - for (x1 = 0, x2 = 0; (x1 < width1) && (x2 < width2); x1 += ix, x2 += ox) - { - scale_icon(im, tmp, x1, y1, x2, y2, - ix, iy, ox, oy); - } - } - - return tmp; -} - - -/* - * Steven Fuerst's tile resizing code - * Taken from Z because I think the algorithm is cool. - */ - -/* 24-bit version - GdkRGB uses 24 bit RGB data internally */ -static void copy_pixels( - int wid, - int y, - int offset, - int *xoffsets, - GdkRGBImage *old_image, - GdkRGBImage *new_image) -{ - int i; - - /* Get source and destination */ - byte *src = &old_image->image[offset * old_image->width * 3]; - byte *dst = &new_image->image[y * new_image->width * 3]; - - /* Copy to the image */ - for (i = 0; i < wid; i++) - { -#ifdef SUPPORT_GAMMA - - if (gamma_table_ready) - { - *dst++ = gamma_table[src[3 * xoffsets[i]]]; - *dst++ = gamma_table[src[3 * xoffsets[i] + 1]]; - *dst++ = gamma_table[src[3 * xoffsets[i] + 2]]; - - continue; - } - -#endif /* SUPPORT_GAMMA */ - - *dst++ = src[3 * xoffsets[i]]; - *dst++ = src[3 * xoffsets[i] + 1]; - *dst++ = src[3 * xoffsets[i] + 2]; - } -} - - -#if 0 - -/* 32-bit version: it might be useful in the future */ -static void copy_pixels( - int wid, - int y, - int offset, - int *xoffsets, - GdkRGBImage *old_image, - GdkRGBImage *new_image) -{ - int i; - - /* Get source and destination */ - byte *src = &old_image->image[offset * old_image->width * 4]; - byte *dst = &new_image->image[y * new_image->width * 4]; - - /* Copy to the image */ - for (i = 0; i < wid; i++) - { - *dst++ = src[4 * xoffsets[i]]; - *dst++ = src[4 * xoffsets[i] + 1]; - *dst++ = src[4 * xoffsets[i] + 2]; - *dst++ = src[4 * xoffsets[i] + 3]; - } -} - -#endif - - -/* - * Resize ix * iy pixel tiles in old to ox * oy pixels - * and return a new GdkRGBImage containing the resized tiles - */ -static GdkRGBImage *resize_tiles_fast( - GdkRGBImage *old_image, - int ix, - int iy, - int ox, - int oy) -{ - GdkRGBImage *new_image; - - int old_wid, old_hgt; - - int new_wid, new_hgt; - - int add, remainder, rem_tot, offset; - - int *xoffsets; - - int i; - - - /* Get the size of the old image */ - old_wid = old_image->width; - old_hgt = old_image->height; - - /* Calculate the size of the new image */ - new_wid = (old_wid / ix) * ox; - new_hgt = (old_hgt / iy) * oy; - - /* Allocate a GdkRGBImage to store resized tiles */ - new_image = gdk_rgb_image_new(new_wid, new_hgt); - - /* Paranoia */ - if (new_image == NULL) return (NULL); - - /* now begins the cool part of SF's code */ - - /* - * Calculate an offsets table, so the transformation - * is faster. This is much like the Bresenham algorithm - */ - - /* Set up x offset table */ - C_MAKE(xoffsets, new_wid, int); - - /* Initialize line parameters */ - add = old_wid / new_wid; - remainder = old_wid % new_wid; - - /* Start at left */ - offset = 0; - - /* Half-tile offset so 'line' is centered correctly */ - rem_tot = new_wid / 2; - - for (i = 0; i < new_wid; i++) - { - /* Store into the table */ - xoffsets[i] = offset; - - /* Move to next entry */ - offset += add; - - /* Take care of fractional part */ - rem_tot += remainder; - if (rem_tot >= new_wid) - { - rem_tot -= new_wid; - offset++; - } - } - - /* Scan each row */ - - /* Initialize line parameters */ - add = old_hgt / new_hgt; - remainder = old_hgt % new_hgt; - - /* Start at left */ - offset = 0; - - /* Half-tile offset so 'line' is centered correctly */ - rem_tot = new_hgt / 2; - - for (i = 0; i < new_hgt; i++) - { - /* Copy pixels to new image */ - copy_pixels(new_wid, i, offset, xoffsets, old_image, new_image); - - /* Move to next entry */ - offset += add; - - /* Take care of fractional part */ - rem_tot += remainder; - if (rem_tot >= new_hgt) - { - rem_tot -= new_hgt; - offset++; - } - } - - /* Free offset table */ - C_FREE(xoffsets, new_wid, int); - - return (new_image); -} - - -/* - * Resize an image of ix * iy pixels and return a newly allocated - * image of ox * oy pixels. - */ -static GdkRGBImage *resize_tiles( - GdkRGBImage *im, - int ix, - int iy, - int ox, - int oy) -{ - GdkRGBImage *result; - - /* - * I hope we can always use this with GdkRGB, which uses a 5x5x5 - * colour cube (125 colours) by default, and resort to dithering - * when it can't find good match there or expand the cube, so it - * works with 8bpp X servers. - */ - if (smooth_rescaling_request && (ix != ox || iy != oy)) - { - result = resize_tiles_smooth(im, ix, iy, ox, oy); - } - - /* - * Unless smoothing is requested by user, we use the fast - * resizing code. - */ - else - { - result = resize_tiles_fast(im, ix, iy, ox, oy); - } - - /* Return rescaled tiles, or NULL */ - return (result); -} - - -/* - * Tile loaders - XPM and BMP - */ - -/* - * A helper function for the XPM loader - * - * Read next string delimited by double quotes from - * the input stream. Return TRUE on success, FALSE - * if it finds EOF or buffer overflow. - * - * I never mean this to be generic, so its EOF and buffer - * overflow behaviour is terribly stupid -- there are no - * provisions for recovery. - * - * CAVEAT: treatment of backslash is not compatible with the standard - * C usage XXX XXX XXX XXX - */ -static bool_ read_str(char *buf, u32b len, FILE *f) -{ - int c; - - /* Paranoia - Buffer too small */ - if (len <= 0) return (FALSE); - - /* Find " */ - while ((c = getc(f)) != '"') - { - /* Premature EOF */ - if (c == EOF) return (FALSE); - } - - while (1) - { - /* Read next char */ - c = getc(f); - - /* Premature EOF */ - if (c == EOF) return (FALSE); - - /* Terminating " */ - if (c == '"') break; - - /* Escape */ - if (c == '\\') - { - /* Use next char */ - c = getc(f); - - /* Premature EOF */ - if (c == EOF) return (FALSE); - } - - /* Store character in the buffer */ - *buf++ = c; - - /* Decrement count */ - len--; - - /* Buffer full - we have to place a NULL at the end */ - if (len <= 0) return (FALSE); - } - - /* Make a C string if there's room left */ - if (len > 0) *buf = '\0'; - - /* Success */ - return (TRUE); -} - - -/* - * Remember pixel symbol to RGB colour mappings - */ - -/* - * I've forgot the formula, but I remember prime number yields - * good results - */ -#define HASH_SIZE 19 - -typedef struct pal_type pal_type; - -struct pal_type -{ - u32b str; - u32b rgb; - pal_type *next; -}; - - -/* - * A simple, slow and stupid XPM loader - */ -static GdkRGBImage *load_xpm(cptr filename) -{ - FILE *f; - GdkRGBImage *img = NULL; - int width, height, colours, chars; - int i, j, k; - bool_ ret; - pal_type *pal = NULL; - pal_type *head[HASH_SIZE]; - u32b buflen = 0; - char *lin = NULL; - char buf[1024]; - - /* Build path to the XPM file */ - path_build(buf, 1024, ANGBAND_DIR_XTRA_GRAF, filename); - - /* Open it */ - f = my_fopen(buf, "r"); - - /* Oops */ - if (f == NULL) return (NULL); - - /* Read header */ - ret = read_str(buf, 1024, f); - - /* Oops */ - if (!ret) - { - /* Notify error */ - plog("Cannot find XPM header"); - - /* Failure */ - goto oops; - } - - /* Parse header */ - if (4 != sscanf(buf, "%d %d %d %d", &width, &height, &colours, &chars)) - { - /* Notify error */ - plog("Bad XPM header"); - - /* Failure */ - goto oops; - } - - /* - * Paranoia - the code can handle upto four letters per pixel, - * but such large number of colours certainly requires a smarter - * symbol-to-colour mapping algorithm... - */ - if ((width <= 0) || (height <= 0) || (colours <= 0) || (chars <= 0) || - (chars > 2)) - { - /* Notify error */ - plog("Invalid width/height/depth"); - - /* Failure */ - goto oops; - } - - /* Allocate palette */ - C_MAKE(pal, colours, pal_type); - - /* Initialise hash table */ - for (i = 0; i < HASH_SIZE; i++) head[i] = NULL; - - /* Parse palette */ - for (i = 0; i < colours; i++) - { - u32b tmp; - int h_idx; - - /* Read next string */ - ret = read_str(buf, 1024, f); - - /* Check I/O result */ - if (!ret) - { - /* Notify error */ - plog("EOF in palette"); - - /* Failure */ - goto oops; - } - - /* Clear symbol code */ - tmp = 0; - - /* Encode pixel symbol */ - for (j = 0; j < chars; j++) - { - tmp = (tmp << 8) | (buf[j] & 0xFF); - } - - /* Remember it */ - pal[i].str = tmp; - - /* Skip spaces */ - while ((buf[j] == ' ') || (buf[j] == '\t')) j++; - - /* Verify 'c' */ - if (buf[j] != 'c') - { - /* Notify error */ - plog("No 'c' in palette definition"); - - /* Failure */ - goto oops; - } - - /* Advance cursor */ - j++; - - /* Skip spaces */ - while ((buf[j] == ' ') || (buf[j] == '\t')) j++; - - /* Hack - Assume 'None' */ - if (buf[j] == 'N') - { - /* Angband always uses black background */ - pal[i].rgb = 0x000000; - } - - /* Read colour */ - else if ((1 != sscanf(&buf[j], "#%06lX", &tmp)) && - (1 != sscanf(&buf[j], "#%06lx", &tmp))) - { - /* Notify error */ - plog("Badly formatted colour"); - - /* Failure */ - goto oops; - } - - /* Remember it */ - pal[i].rgb = tmp; - - /* Store it in hash table as well */ - h_idx = pal[i].str % HASH_SIZE; - - /* Link the entry */ - pal[i].next = head[h_idx]; - head[h_idx] = &pal[i]; - } - - /* Allocate image */ - img = gdk_rgb_image_new(width, height); - - /* Oops */ - if (img == NULL) - { - /* Notify error */ - plog("Cannot allocate image"); - - /* Failure */ - goto oops; - } - - /* Calculate buffer length */ - buflen = width * chars + 1; - - /* Allocate line buffer */ - C_MAKE(lin, buflen, char); - - /* For each row */ - for (i = 0; i < height; i++) - { - /* Read a row of image data */ - ret = read_str(lin, buflen, f); - - /* Oops */ - if (!ret) - { - /* Notify error */ - plog("EOF in middle of image data"); - - /* Failure */ - goto oops; - } - - /* For each column */ - for (j = 0; j < width; j++) - { - u32b tmp; - pal_type *h_ptr; - - /* Clear encoded pixel */ - tmp = 0; - - /* Encode pixel symbol */ - for (k = 0; k < chars; k++) - { - tmp = (tmp << 8) | (lin[j * chars + k] & 0xFF); - } - - /* Find colour */ - for (h_ptr = head[tmp % HASH_SIZE]; - h_ptr != NULL; - h_ptr = h_ptr->next) - { - /* Found a match */ - if (h_ptr->str == tmp) break; - } - - /* No match found */ - if (h_ptr == NULL) - { - /* Notify error */ - plog("Invalid pixel symbol"); - - /* Failure */ - goto oops; - } - - /* Draw it */ - gdk_rgb_image_put_pixel( - img, - j, - i, - h_ptr->rgb); - } - } - - /* Close file */ - my_fclose(f); - - /* Free line buffer */ - C_FREE(lin, buflen, char); - - /* Free palette */ - C_FREE(pal, colours, pal_type); - - /* Return result */ - return (img); - -oops: - - /* Close file */ - my_fclose(f); - - /* Free image */ - if (img) gdk_rgb_image_destroy(img); - - /* Free line buffer */ - if (lin) C_FREE(lin, buflen, char); - - /* Free palette */ - if (pal) C_FREE(pal, colours, pal_type); - - /* Failure */ - return (NULL); -} - - -/* - * A BMP loader, yet another duplication of maid-x11.c functions. - * - * Another duplication, again because of different image format and - * avoidance of colour allocation. - * - * XXX XXX XXX XXX Should avoid using a propriatary and closed format. - * Since it's much bigger than gif that was used before, why don't - * we switch to XPM? NetHack does. Well, NH has always been much - * closer to the GNU/Un*x camp and it's GPL'ed quite early... - * - * The names and naming convention are worse than the worst I've ever - * seen, so I deliberately changed them to fit well with the rest of - * the code. Or are they what xx calls them? If it's the case, there's - * no reason to follow *their* words. - */ - -/* - * BMP file header - */ -typedef struct bmp_file_type bmp_file_type; - -struct bmp_file_type -{ - u16b type; - u32b size; - u16b reserved1; - u16b reserved2; - u32b offset; -}; - - -/* - * BMP file information fields - */ -typedef struct bmp_info_type bmp_info_type; - -struct bmp_info_type -{ - u32b size; - u32b width; - u32b height; - u16b planes; - u16b bit_count; - u32b compression; - u32b size_image; - u32b x_pels_per_meter; - u32b y_pels_per_meter; - u32b colors_used; - u32b color_importand; -}; - -/* - * "RGBQUAD" type. - */ -typedef struct rgb_quad_type rgb_quad_type; - -struct rgb_quad_type -{ - unsigned char b, g, r; - unsigned char filler; -}; - - -/*** Helper functions for system independent file loading. ***/ - -static byte get_byte(FILE *fff) -{ - /* Get a character, and return it */ - return (getc(fff) & 0xFF); -} - -static void rd_byte(FILE *fff, byte *ip) -{ - *ip = get_byte(fff); -} - -static void rd_u16b(FILE *fff, u16b *ip) -{ - (*ip) = get_byte(fff); - (*ip) |= ((u16b)(get_byte(fff)) << 8); -} - -static void rd_u32b(FILE *fff, u32b *ip) -{ - (*ip) = get_byte(fff); - (*ip) |= ((u32b)(get_byte(fff)) << 8); - (*ip) |= ((u32b)(get_byte(fff)) << 16); - (*ip) |= ((u32b)(get_byte(fff)) << 24); -} - - -/* - * Read a BMP file (a certain trademark nuked) - * - * This function replaces the old ReadRaw and RemapColors functions. - * - * Assumes that the bitmap has a size such that no padding is needed in - * various places. Currently only handles bitmaps with 3 to 256 colors. - */ -GdkRGBImage *load_bmp(cptr filename) -{ - FILE *f; - - char path[1024]; - - bmp_file_type file_hdr; - bmp_info_type info_hdr; - - GdkRGBImage *result = NULL; - - int ncol; - - int i; - - u32b x, y; - - guint32 colour_pixels[256]; - - - /* Build the path to the bmp file */ - path_build(path, 1024, ANGBAND_DIR_XTRA_GRAF, filename); - - /* Open the BMP file */ - f = fopen(path, "r"); - - /* No such file */ - if (f == NULL) - { - return (NULL); - } - - /* Read the "bmp_file_type" */ - rd_u16b(f, &file_hdr.type); - rd_u32b(f, &file_hdr.size); - rd_u16b(f, &file_hdr.reserved1); - rd_u16b(f, &file_hdr.reserved2); - rd_u32b(f, &file_hdr.offset); - - /* Read the "bmp_info_type" */ - rd_u32b(f, &info_hdr.size); - rd_u32b(f, &info_hdr.width); - rd_u32b(f, &info_hdr.height); - rd_u16b(f, &info_hdr.planes); - rd_u16b(f, &info_hdr.bit_count); - rd_u32b(f, &info_hdr.compression); - rd_u32b(f, &info_hdr.size_image); - rd_u32b(f, &info_hdr.x_pels_per_meter); - rd_u32b(f, &info_hdr.y_pels_per_meter); - rd_u32b(f, &info_hdr.colors_used); - rd_u32b(f, &info_hdr.color_importand); - - /* Verify the header */ - if (feof(f) || - (file_hdr.type != 19778) || - (info_hdr.size != 40)) - { - plog(format("Incorrect BMP file format %s", filename)); - fclose(f); - return (NULL); - } - - /* - * The two headers above occupy 54 bytes total - * The "offset" field says where the data starts - * The "colors_used" field does not seem to be reliable - */ - - /* Compute number of colors recorded */ - ncol = (file_hdr.offset - 54) / 4; - - for (i = 0; i < ncol; i++) - { - rgb_quad_type clr; - - /* Read an "rgb_quad_type" */ - rd_byte(f, &clr.b); - rd_byte(f, &clr.g); - rd_byte(f, &clr.r); - rd_byte(f, &clr.filler); - - /* Remember the pixel */ - colour_pixels[i] = (clr.r << 16) | (clr.g << 8) | (clr.b); - } - - /* Allocate GdkRGBImage large enough to store the image */ - result = gdk_rgb_image_new(info_hdr.width, info_hdr.height); - - /* Failure */ - if (result == NULL) - { - fclose(f); - return (NULL); - } - - for (y = 0; y < info_hdr.height; y++) - { - u32b y2 = info_hdr.height - y - 1; - - for (x = 0; x < info_hdr.width; x++) - { - int ch = getc(f); - - /* Verify not at end of file XXX XXX */ - if (feof(f)) - { - plog(format("Unexpected end of file in %s", filename)); - gdk_rgb_image_destroy(result); - fclose(f); - return (NULL); - } - - if (info_hdr.bit_count == 24) - { - int c3, c2 = getc(f); - - /* Verify not at end of file XXX XXX */ - if (feof(f)) - { - plog(format("Unexpected end of file in %s", filename)); - gdk_rgb_image_destroy(result); - fclose(f); - return (NULL); - } - - c3 = getc(f); - - /* Verify not at end of file XXX XXX */ - if (feof(f)) - { - plog(format("Unexpected end of file in %s", filename)); - gdk_rgb_image_destroy(result); - fclose(f); - return (NULL); - } - - /* Draw the pixel */ - gdk_rgb_image_put_pixel( - result, - x, - y2, - (ch << 16) | (c2 << 8) | (c3)); - } - else if (info_hdr.bit_count == 8) - { - gdk_rgb_image_put_pixel(result, x, y2, colour_pixels[ch]); - } - else if (info_hdr.bit_count == 4) - { - gdk_rgb_image_put_pixel(result, x, y2, colour_pixels[ch / 16]); - x++; - gdk_rgb_image_put_pixel(result, x, y2, colour_pixels[ch % 16]); - } - else - { - /* Technically 1 bit is legal too */ - plog(format("Illegal bit count %d in %s", - info_hdr.bit_count, filename)); - gdk_rgb_image_destroy(result); - fclose(f); - return (NULL); - } - } - } - - fclose(f); - - return result; -} - - -/* - * Try to load an XPM file, or a BMP file if it fails - * - * Choice of file format may better be made yet another option XXX - */ -static GdkRGBImage *load_tiles(cptr basename) -{ - char buf[32]; - GdkRGBImage *img; - - /* build xpm file name */ - strnfmt(buf, 32, "%s.xpm", basename); - - /* Try to load it */ - img = load_xpm(buf); - - /* OK */ - if (img) return (img); - - /* Try again for a bmp file */ - strnfmt(buf, 32, "%s.bmp", basename); - - /* Try loading it */ - img = load_bmp(buf); - - /* Return result, success or failure */ - return (img); -} - - -/* - * Free all tiles and graphics buffers associated with windows - * - * This is conspirator of graf_init() below, sharing its inefficiency - */ -static void graf_nuke() -{ - int i; - - term_data *td; - - - /* Nuke all terms */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - /* Access term_data structure */ - td = &data[i]; - - /* Disable graphics */ - td->t.higher_pict = FALSE; - - /* Free previously allocated tiles */ - if (td->tiles) gdk_rgb_image_destroy(td->tiles); - - /* Forget pointer */ - td->tiles = NULL; - -# ifdef USE_TRANSPARENCY - - /* Free previously allocated transparency buffer */ - if (td->trans_buf) gdk_rgb_image_destroy(td->trans_buf); - - /* Forget stale pointer */ - td->trans_buf = NULL; - -# endif /* USE_TRANSPARENCY */ - - } -} - - -/* - * Load tiles, scale them to current font size, and store a pointer - * to them in a term_data structure for each term. - * - * XXX XXX XXX This is a terribly stupid quick hack. - * - * XXX XXX XXX Windows using the same font should share resized tiles - */ -static bool_ graf_init( - cptr filename, - int tile_wid, - int tile_hgt) -{ - term_data *td; - - bool_ result; - - GdkRGBImage *raw_tiles, *scaled_tiles; - -# ifdef USE_TRANSPARENCY - GdkRGBImage *buffer; -# endif /* USE_TRANSPARENCY */ - - int i; - - - /* Paranoia */ - if (filename == NULL) return (FALSE); - - /* Load tiles */ - raw_tiles = load_tiles(filename); - - /* Oops */ - if (raw_tiles == NULL) - { - /* Clean up */ - graf_nuke(); - - /* Failure */ - return (FALSE); - } - - /* Calculate and remember numbers of rows and columns */ - tile_rows = raw_tiles->height / tile_hgt; - tile_cols = raw_tiles->width / tile_wid; - - /* Be optimistic */ - result = TRUE; - - - /* - * (Re-)init each term - * XXX It might help speeding this up to avoid doing so if a window - * doesn't need graphics (e.g. inventory/equipment and message recall). - */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - /* Access term_data */ - td = &data[i]; - - /* Shouldn't waste anything for unused terms */ - if (!td->shown) continue; - - /* Enable graphics */ - td->t.higher_pict = TRUE; - - /* See if we need rescaled tiles XXX */ - if ((td->tiles == NULL) || - (td->tiles->width != td->tile_wid * tile_cols) || - (td->tiles->height != td->tile_hgt * tile_rows)) - { - /* Free old tiles if present */ - if (td->tiles) gdk_rgb_image_destroy(td->tiles); - - /* Forget pointer */ - td->tiles = NULL; - - /* Scale the tiles to current font bounding rect */ - scaled_tiles = resize_tiles( - raw_tiles, - tile_wid, tile_hgt, - td->tile_wid, td->tile_hgt); - - /* Oops */ - if (scaled_tiles == NULL) - { - /* Failure */ - result = FALSE; - - break; - } - - /* Store it */ - td->tiles = scaled_tiles; - } - -# ifdef USE_TRANSPARENCY - - /* See if we have to (re)allocate a new buffer XXX */ - if ((td->trans_buf == NULL) || - (td->trans_buf->width != td->tile_wid) || - (td->trans_buf->height != td->tile_hgt)) - { - /* Free old buffer if present */ - if (td->trans_buf) gdk_rgb_image_destroy(td->trans_buf); - - /* Forget pointer */ - td->trans_buf = NULL; - - /* Allocate a new buffer */ - buffer = gdk_rgb_image_new(td->tile_wid, td->tile_hgt); - - /* Oops */ - if (buffer == NULL) - { - /* Failure */ - result = FALSE; - - break; - } - - /* Store it */ - td->trans_buf = buffer; - } - - /* - * Giga-Hack - assume top left corner of 0x86/0x80 should be - * in the background colour XXX XXX XXX XXX - */ - td->bg_pixel = gdk_rgb_image_get_pixel( - raw_tiles, - 0, - tile_hgt * 6); - -# endif /* USE_TRANSPARENCY */ - - } - - - /* Alas, we need to free wasted images */ - if (result == FALSE) graf_nuke(); - - /* We don't need the raw image any longer */ - gdk_rgb_image_destroy(raw_tiles); - - /* Report success or failure */ - return (result); -} - - -/* - * React to various changes in graphics mode settings - * - * It is *not* a requirement for tiles to have same pixel width and height. - * The program can work with any conbinations of graf_wid and graf_hgt - * (oops, they must be representable by u16b), as long as they are lesser - * or equal to 32 if you use smooth rescaling. - */ -static void init_graphics(void) -{ - cptr tile_name; - - u16b graf_wid = 0, graf_hgt = 0; - - - /* No graphics requests are made - Can't this be simpler? XXX XXX */ - if ((graf_mode_request == graf_mode) && - (smooth_rescaling_request == smooth_rescaling) && - !resize_request) return; - - /* Prevent further unsolicited reaction */ - resize_request = FALSE; - - - /* Dispose unusable old tiles - awkward... XXX XXX */ - if ((graf_mode_request == GRAF_MODE_NONE) || - (graf_mode_request != graf_mode) || - (smooth_rescaling_request != smooth_rescaling)) graf_nuke(); - - - /* Setup parameters according to request */ - switch (graf_mode_request) - { - /* ASCII - no graphics whatsoever */ - default: - case GRAF_MODE_NONE: - { - tile_name = NULL; - use_graphics = arg_graphics = FALSE; - - break; - } - - /* - * 8x8 tiles originally collected for the Amiga port - * from several contributers by Lars Haugseth, converted - * to 256 colours and expanded by the Z devteam - * - * Use the "old" tile assignments - * - * Dawnmist is working on it for ToME - */ - case GRAF_MODE_OLD: - { - tile_name = "8x8"; - graf_wid = graf_hgt = 8; - ANGBAND_GRAF = "old"; - use_graphics = arg_graphics = TRUE; - - break; - } - - /* - * Adam Bolt's 16x16 tiles - * "new" tile assignments - * It is updated for ToME by Andreas Koch - */ - case GRAF_MODE_NEW: - { - tile_name = "16x16"; - graf_wid = graf_hgt = 16; - ANGBAND_GRAF = "new"; - use_graphics = arg_graphics = TRUE; - - break; - } - } - - - /* load tiles and set them up if tiles are requested */ - if ((graf_mode_request != GRAF_MODE_NONE) && - !graf_init(tile_name, graf_wid, graf_hgt)) - { - /* Oops */ - plog("Cannot initialize graphics"); - - /* reject requests */ - graf_mode_request = GRAF_MODE_NONE; - smooth_rescaling_request = smooth_rescaling; - - /* reset graphics flags */ - use_graphics = arg_graphics = FALSE; - } - - /* Update current graphics mode */ - graf_mode = graf_mode_request; - smooth_rescaling = smooth_rescaling_request; - - /* Reset visuals */ -#ifndef ANG281_RESET_VISUALS - reset_visuals(TRUE); -#else - reset_visuals(); -#endif /* !ANG281_RESET_VISUALS */ -} - -#endif /* USE_GRAPHICS */ - - - - -/**** Term package support routines ****/ - - -/* - * Free data used by a term - */ -static void Term_nuke_gtk(term *t) -{ - term_data *td = t->data; - - - /* Free name */ - if (td->name) string_free(td->name); - - /* Forget it */ - td->name = NULL; - - /* Free font */ - if (td->font) gdk_font_unref(td->font); - - /* Forget it */ - td->font = NULL; - - /* Free backing store */ - if (td->backing_store) gdk_pixmap_unref(td->backing_store); - - /* Forget it too */ - td->backing_store = NULL; - -#ifdef USE_GRAPHICS - - /* Free tiles */ - if (td->tiles) gdk_rgb_image_destroy(td->tiles); - - /* Forget pointer */ - td->tiles = NULL; - -# ifdef USE_TRANSPARENCY - - /* Free transparency buffer */ - if (td->trans_buf) gdk_rgb_image_destroy(td->trans_buf); - - /* Amnesia */ - td->trans_buf = NULL; - -# endif /* USE_TRANSPARENCY */ - -#endif /* USE_GRAPHICS */ -} - - -/* - * Erase the whole term. - */ -static errr Term_clear_gtk(void) -{ - term_data *td = (term_data*)(Term->data); - - - /* Don't draw to hidden windows */ - if (!td->shown) return (0); - - /* Paranoia */ - g_assert(td->drawing_area->window != 0); - - /* Clear the area */ - gdk_draw_rectangle( - TERM_DATA_DRAWABLE(td), - td->drawing_area->style->black_gc, - 1, - 0, - 0, - td->cols * td->font_wid, - td->rows * td->font_hgt); - - /* Copy image from backing store if present */ - TERM_DATA_REFRESH(td, 0, 0, td->cols, td->rows); - - /* Success */ - return (0); -} - - -/* - * Erase some characters. - */ -static errr Term_wipe_gtk(int x, int y, int n) -{ - term_data *td = (term_data*)(Term->data); - - - /* Don't draw to hidden windows */ - if (!td->shown) return (0); - - /* Paranoia */ - g_assert(td->drawing_area->window != 0); - - /* Fill the area with the background colour */ - gdk_draw_rectangle( - TERM_DATA_DRAWABLE(td), - td->drawing_area->style->black_gc, - TRUE, - x * td->font_wid, - y * td->font_hgt, - n * td->font_wid, - td->font_hgt); - - /* Copy image from backing store if present */ - TERM_DATA_REFRESH(td, x, y, n, 1); - - /* Success */ - return (0); -} - - -/* - * Draw some textual characters. - */ -static errr Term_text_gtk(int x, int y, int n, byte a, cptr s) -{ - term_data *td = (term_data*)(Term->data); - - - /* Don't draw to hidden windows */ - if (!td->shown) return (0); - - /* Paranoia */ - g_assert(td->drawing_area->window != 0); - - /* Set foreground colour */ - term_data_set_fg(td, a); - - /* Clear the line */ - Term_wipe_gtk(x, y, n); - - /* Draw the text to the window */ - gdk_draw_text( - TERM_DATA_DRAWABLE(td), - td->font, - td->gc, - x * td->font_wid, - td->font->ascent + y * td->font_hgt, - s, - n); - - /* Copy image from backing store if present */ - TERM_DATA_REFRESH(td, x, y, n, 1); - - /* Success */ - return (0); -} - - -/* - * Draw software cursor at (x, y) - */ -static errr Term_curs_gtk(int x, int y) -{ - term_data *td = (term_data*)(Term->data); - int cells = 1; - - - /* Don't draw to hidden windows */ - if (!td->shown) return (0); - - /* Paranoia */ - g_assert(td->drawing_area->window != 0); - - /* Set foreground colour */ - term_data_set_fg(td, TERM_YELLOW); - -#ifdef USE_DOUBLE_TILES - - /* Mogami's bigtile patch */ - - /* Adjust it if wide tiles are requested */ - if (use_bigtile && - (x + 1 < Term->wid) && - (Term->old->a[y][x + 1] == 255)) - { - cells = 2; - } - -#endif /* USE_DOUBLE_TILES */ - - /* Draw the software cursor */ - gdk_draw_rectangle( - TERM_DATA_DRAWABLE(td), - td->gc, - FALSE, - x * td->font_wid, - y * td->font_hgt, - td->font_wid * cells - 1, - td->font_hgt - 1); - - /* Copy image from backing store if present */ - TERM_DATA_REFRESH(td, x, y, cells, 1); - - /* Success */ - return (0); -} - - -#ifdef USE_GRAPHICS - -# ifdef USE_TRANSPARENCY - -/* - * XXX XXX Low level graphics helper - * Draw a tile at (s_x, s_y) over one at (t_x, t_y) and store the - * result in td->trans_buf - * - * XXX XXX Even if CPU's are faster than necessary these days, - * this should be made inline. Or better, there should be an API - * to take advantage of graphics hardware. They almost always have - * assortment of builtin bitblt's... - */ -static void overlay_tiles_2( - term_data *td, - int s_x, int s_y, - int t_x, int t_y) -{ - guint32 pix; - int x, y; - - - /* Process each row */ - for (y = 0; y < td->tile_hgt; y++) - { - /* Process each column */ - for (x = 0; x < td->tile_wid; x++) - { - /* Get an overlay pixel */ - pix = gdk_rgb_image_get_pixel(td->tiles, s_x + x, s_y + y); - - /* If it's in background color, use terrain instead */ - if (pix == td->bg_pixel) - pix = gdk_rgb_image_get_pixel(td->tiles, t_x + x, t_y + y); - - /* Store the result in trans_buf */ - gdk_rgb_image_put_pixel(td->trans_buf, x, y, pix); - } - } -} - - -# ifdef USE_EGO_GRAPHICS - -/* - * XXX XXX Low level graphics helper - * Draw a tile at (e_x, e_y) over one at (s_x, s_y) over another one - * at (t_x, t_y) and store the result in td->trans_buf - * - * XXX XXX The same comment applies as that for the above... - */ -static void overlay_tiles_3( - term_data *td, - int e_x, int e_y, - int s_x, int s_y, - int t_x, int t_y) -{ - guint32 pix; - int x, y; - - - /* Process each row */ - for (y = 0; y < td->tile_hgt; y++) - { - /* Process each column */ - for (x = 0; x < td->tile_wid; x++) - { - /* Get an overlay pixel */ - pix = gdk_rgb_image_get_pixel(td->tiles, e_x + x, e_y + y); - - /* - * If it's background colour, try to use one from - * the second layer - */ - if (pix == td->bg_pixel) - pix = gdk_rgb_image_get_pixel(td->tiles, s_x + x, s_y + y); - - /* - * If it's background colour again, fall back to - * the terrain layer - */ - if (pix == td->bg_pixel) - pix = gdk_rgb_image_get_pixel(td->tiles, t_x + x, t_y + y); - - /* Store the pixel in trans_buf */ - gdk_rgb_image_put_pixel(td->trans_buf, x, y, pix); - } - } -} - -# endif /* USE_EGO_GRAPHICS */ - -# endif /* USE_TRANSPARENCY */ - - -/* - * Low level graphics (Assumes valid input) - * - * Draw "n" tiles/characters starting at (x,y) - */ -# ifdef USE_TRANSPARENCY -# ifdef USE_EGO_GRAPHICS -static errr Term_pict_gtk( - int x, int y, int n, - const byte *ap, const char *cp, - const byte *tap, const char *tcp, - const byte *eap, const char *ecp) -# else /* USE_EGO_GRAPHICS */ -static errr Term_pict_gtk( - int x, int y, int n, - const byte *ap, const char *cp, - const byte *tap, const char *tcp) -# endif /* USE_EGO_GRAPHICS */ -# else /* USE_TRANSPARENCY */ -static errr Term_pict_gtk( - int x, int y, int n, - const byte *ap, const char *cp) -# endif /* USE_TRANSPARENCY */ -{ - term_data *td = (term_data*)(Term->data); - - int i; - - int d_x, d_y; - -# ifdef USE_DOUBLE_TILES - - /* Hack - remember real number of columns affected XXX XXX XXX */ - int cols; - -# endif /* USE_DOUBLE_TILES */ - - - /* Don't draw to hidden windows */ - if (!td->shown) return (0); - - /* Paranoia */ - g_assert(td->drawing_area->window != 0); - - /* Top left corner of the destination rect */ - d_x = x * td->font_wid; - d_y = y * td->font_hgt; - - -# ifdef USE_DOUBLE_TILES - - /* Reset column counter */ - cols = 0; - -# endif /* USE_DOUBLE_TILES */ - - /* Scan the input */ - for (i = 0; i < n; i++) - { - byte a; - char c; - int s_x, s_y; - -# ifdef USE_TRANSPARENCY - - byte ta; - char tc; - int t_x, t_y; - -# ifdef USE_EGO_GRAPHICS - - byte ea; - char ec; - int e_x = 0, e_y = 0; - bool_ has_overlay; - -# endif /* USE_EGO_GRAPHICS */ - -# endif /* USE_TRANSPARENCY */ - - - /* Grid attr/char */ - a = *ap++; - c = *cp++; - -# ifdef USE_TRANSPARENCY - - /* Terrain attr/char */ - ta = *tap++; - tc = *tcp++; - -# ifdef USE_EGO_GRAPHICS - - /* Overlay attr/char */ - ea = *eap++; - ec = *ecp++; - has_overlay = (ea && ec); - -# endif /* USE_EGO_GRAPHICS */ - -# endif /* USE_TRANSPARENCY */ - - /* Row and Col */ - s_y = (((byte)a & 0x7F) % tile_rows) * td->tile_hgt; - s_x = (((byte)c & 0x7F) % tile_cols) * td->tile_wid; - -# ifdef USE_TRANSPARENCY - - /* Terrain Row and Col */ - t_y = (((byte)ta & 0x7F) % tile_rows) * td->tile_hgt; - t_x = (((byte)tc & 0x7F) % tile_cols) * td->tile_wid; - -# ifdef USE_EGO_GRAPHICS - - /* Overlay Row and Col */ - if (has_overlay) - { - e_y = (((byte)ea & 0x7F) % tile_rows) * td->tile_hgt; - e_x = (((byte)ec & 0x7F) % tile_cols) * td->tile_wid; - } - -# endif /* USE_EGO_GRAPHICS */ - - -# ifdef USE_DOUBLE_TILES - - /* Mogami's bigtile patch */ - - /* Hack -- a filler for wide tile */ - if (use_bigtile && (a == 255)) - { - /* Advance */ - d_x += td->font_wid; - - /* Ignore */ - continue; - } - -# endif /* USE_DOUBLE_TILES */ - - /* Optimise the common case: terrain == obj/mons */ - if (!use_transparency || - ((s_x == t_x) && (s_y == t_y))) - { - -# ifdef USE_EGO_GRAPHICS - - /* The simplest possible case - no overlay */ - if (!has_overlay) - { - /* Draw the tile */ - gdk_draw_rgb_image_2( - TERM_DATA_DRAWABLE(td), td->gc, td->tiles, - s_x, s_y, - d_x, d_y, - td->tile_wid, td->tile_hgt); - } - - /* We have to draw overlay... */ - else - { - /* Overlay */ - overlay_tiles_2(td, e_x, e_y, s_x, s_y); - - /* And draw the result */ - gdk_draw_rgb_image_2( - TERM_DATA_DRAWABLE(td), td->gc, td->trans_buf, - 0, 0, - d_x, d_y, - td->tile_wid, td->tile_hgt); - - /* Hack -- Prevent potential display problem */ - gdk_flush(); - } - -# else /* USE_EGO_GRAPHICS */ - - /* Draw the tile */ - gdk_draw_rgb_image_2( - TERM_DATA_DRAWABLE(td), td->gc, td->tiles, - s_x, s_y, - d_x, d_y, - td->tile_wid, td->tile_hgt); - -# endif /* USE_EGO_GRAPHICS */ - - } - - /* - * Since there's no masking bitblt in X, - * we have to do that manually... - */ - else - { - -# ifndef USE_EGO_GRAPHICS - - /* Draw mon/PC/obj over terrain */ - overlay_tiles_2(td, s_x, s_y, t_x, t_y); - -# else /* !USE_EGO_GRAPHICS */ - - /* No overlay */ - if (!has_overlay) - { - /* Build terrain + masked overlay image */ - overlay_tiles_2(td, s_x, s_y, t_x, t_y); - } - - /* With overlay */ - else - { - /* Ego over mon/PC over terrain */ - overlay_tiles_3(td, e_x, e_y, s_x, s_y, - t_x, t_y); - } - -# endif /* !USE_EGO_GRAPHICS */ - - /* Draw it */ - gdk_draw_rgb_image_2( - TERM_DATA_DRAWABLE(td), td->gc, td->trans_buf, - 0, 0, - d_x, d_y, - td->tile_wid, td->tile_hgt); - - /* Hack -- Prevent potential display problem */ - gdk_flush(); - } - -# else /* USE_TRANSPARENCY */ - - /* Draw the tile */ - gdk_draw_rgb_image_2( - TERM_DATA_DRAWABLE(td), td->gc, td->tiles, - s_x, s_y, - d_x, d_y, - td->tile_wid, td->tile_hgt); - -# endif /* USE_TRANSPARENCY */ - - /* - * Advance x-coordinate - wide font fillers are taken care of - * before entering the tile drawing code. - */ - d_x += td->font_wid; - -# ifdef USE_DOUBLE_TILES - - /* Add up *real* number of columns updated XXX XXX XXX */ - cols += use_bigtile ? 2 : 1; - -# endif /* USE_DOUBLE_TILES */ - } - -# ifndef USE_DOUBLE_TILES - - /* Copy image from backing store if present */ - TERM_DATA_REFRESH(td, x, y, n, 1); - -# else - - /* Copy image from backing store if present */ - TERM_DATA_REFRESH(td, x, y, cols, 1); - -# endif /* USE_DOUBLE_TILES */ - - /* Success */ - return (0); -} - -#endif /* USE_GRAPHICS */ - - -/* - * Process an event, if there's none block when wait is set true, - * return immediately otherwise. - */ -static void CheckEvent(bool_ wait) -{ - /* Process an event */ - (void)gtk_main_iteration_do(wait); -} - - -/* - * Process all pending events (without blocking) - */ -static void DrainEvents(void) -{ - while (gtk_events_pending()) - gtk_main_iteration(); -} - - -/* - * Handle a "special request" - */ -static errr Term_xtra_gtk(int n, int v) -{ - /* Handle a subset of the legal requests */ - switch (n) - { - /* Make a noise */ - case TERM_XTRA_NOISE: - { - /* Beep */ - gdk_beep(); - - /* Success */ - return (0); - } - - /* Flush the output */ - case TERM_XTRA_FRESH: - { - /* Flush pending X requests - almost always no-op */ - gdk_flush(); - - /* Success */ - return (0); - } - - /* Process random events */ - case TERM_XTRA_BORED: - { - /* Process a pending event if there's one */ - CheckEvent(FALSE); - - /* Success */ - return (0); - } - - /* Process Events */ - case TERM_XTRA_EVENT: - { - /* Process an event */ - CheckEvent(v); - - /* Success */ - return (0); - } - - /* Flush the events */ - case TERM_XTRA_FLUSH: - { - /* Process all pending events */ - DrainEvents(); - - /* Success */ - return (0); - } - - /* Handle change in the "level" */ - case TERM_XTRA_LEVEL: - return (0); - - /* Clear the screen */ - case TERM_XTRA_CLEAR: - return (Term_clear_gtk()); - - /* Delay for some milliseconds */ - case TERM_XTRA_DELAY: - { - /* sleep for v milliseconds */ - usleep(v * 1000); - - /* Done */ - return (0); - } - - /* Get Delay of some milliseconds */ - case TERM_XTRA_GET_DELAY: - { - int ret; - struct timeval tv; - - ret = gettimeofday(&tv, NULL); - Term_xtra_long = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - - return ret; - } - - /* Subdirectory scan */ - case TERM_XTRA_SCANSUBDIR: - { - DIR *directory; - struct dirent *entry; - - scansubdir_max = 0; - - directory = opendir(scansubdir_dir); - if (!directory) return (1); - - while ((entry = readdir(directory)) != NULL) - { - char file[PATH_MAX + NAME_MAX + 2]; - struct stat filedata; - - file[PATH_MAX + NAME_MAX] = 0; - strncpy(file, scansubdir_dir, PATH_MAX); - strncat(file, "/", 2); - strncat(file, entry->d_name, NAME_MAX); - if ((stat(file, &filedata) == 0) && S_ISDIR(filedata.st_mode)) - { - string_free(scansubdir_result[scansubdir_max]); - scansubdir_result[scansubdir_max] = - string_make(entry->d_name); - ++scansubdir_max; - } - } - } - - /* Rename main window */ - case TERM_XTRA_RENAME_MAIN_WIN: gtk_window_set_title(GTK_WINDOW(data[0].window), angband_term_name[0]); return (0); - - /* React to changes */ - case TERM_XTRA_REACT: - { - /* (re-)init colours */ - init_colours(); - -#ifdef USE_GRAPHICS - - /* Initialise graphics */ - init_graphics(); - -#endif /* USE_GRAPHICS */ - - /* Success */ - return (0); - } - } - - /* Unknown */ - return (1); -} - - - - -/**** Event handlers ****/ - - -/* - * Operation overkill - * Verify term size info - just because the other windowing ports have this - */ -static void term_data_check_size(term_data *td) -{ - /* Enforce minimum window size */ - if (td == &data[0]) - { - if (td->cols < 80) td->cols = 80; - if (td->rows < 24) td->rows = 24; - } - else - { - if (td->cols < 1) td->cols = 1; - if (td->rows < 1) td->rows = 1; - } - - /* Paranoia - Enforce maximum size allowed by the term package */ - if (td->cols > 255) td->cols = 255; - if (td->rows > 255) td->rows = 255; -} - - -/* - * Enforce these size constraints within Gtk/Gdk - * These increments are nice, because you can see numbers of rows/cols - * while you resize a term. - */ -static void term_data_set_geometry_hints(term_data *td) -{ - GdkGeometry geometry; - - /* Resizing is character size oriented */ - geometry.width_inc = td->font_wid; - geometry.height_inc = td->font_hgt; - - /* Enforce minimum size - the main window */ - if (td == &data[0]) - { - geometry.min_width = 80 * td->font_wid; - geometry.min_height = 24 * td->font_hgt; - } - - /* Subwindows can be much smaller */ - else - { - geometry.min_width = 1 * td->font_wid; - geometry.min_height = 1 * td->font_hgt; - } - - /* Enforce term package's hard limit */ - geometry.max_width = 255 * td->font_wid; - geometry.max_height = 255 * td->font_hgt; - - /* This affects geometry display while we resize a term */ - geometry.base_width = 0; - geometry.base_height = 0; - - /* Give the window a new set of resizing hints */ - gtk_window_set_geometry_hints(GTK_WINDOW(td->window), - td->drawing_area, &geometry, - GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE - | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC); -} - - -/* - * (Re)allocate a backing store for the window - */ -static void term_data_set_backing_store(term_data *td) -{ - /* Paranoia */ - if (!GTK_WIDGET_REALIZED(td->drawing_area)) return; - - /* Free old one if we cannot use it any longer */ - if (td->backing_store) - { - int wid, hgt; - - /* Retrive the size of the old backing store */ - gdk_window_get_size(td->backing_store, &wid, &hgt); - - /* Continue using it if it's the same with desired size */ - if (use_backing_store && - (td->cols * td->font_wid == wid) && - (td->rows * td->font_hgt == hgt)) return; - - /* Free it */ - gdk_pixmap_unref(td->backing_store); - - /* Forget the pointer */ - td->backing_store = NULL; - } - - /* See user preference */ - if (use_backing_store) - { - /* Allocate new backing store */ - td->backing_store = gdk_pixmap_new( - td->drawing_area->window, - td->cols * td->font_wid, - td->rows * td->font_hgt, - -1); - - /* Oops - but we can do without it */ - g_return_if_fail(td->backing_store != NULL); - - /* Clear the backing store */ - gdk_draw_rectangle( - td->backing_store, - td->drawing_area->style->black_gc, - TRUE, - 0, - 0, - td->cols * td->font_wid, - td->rows * td->font_hgt); - } -} - - -/* - * Save game only when it's safe to do so - */ -static void save_game_gtk(void) -{ - /* We have nothing to save, yet */ - if (!game_in_progress || !character_generated) return; - - /* It isn't safe to save game now */ - if (!inkey_flag || !can_save) - { - plog("You may not save right now."); - return; - } - - /* Hack -- Forget messages */ - msg_flag = FALSE; - - /* Save the game */ -#ifdef ZANG_SAVE_GAME - /* Also for OAngband - the parameter tells if it's autosave */ - do_cmd_save_game(FALSE); -#else -/* Everything else */ - do_cmd_save_game(); -#endif /* ZANG_SAVE_GAME */ -} - - -/* - * Display message in a modal dialog - */ -static void gtk_message(cptr msg) -{ - GtkWidget *dialog, *label, *ok_button; - - /* Create the widgets */ - dialog = gtk_dialog_new(); - g_assert(dialog != NULL); - - label = gtk_label_new(msg); - g_assert(label != NULL); - - ok_button = gtk_button_new_with_label("OK"); - g_assert(ok_button != NULL); - - /* Ensure that the dialogue box is destroyed when OK is clicked */ - gtk_signal_connect_object( - GTK_OBJECT(ok_button), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - (gpointer)dialog); - gtk_container_add( - GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), - ok_button); - - /* Add the label, and show the dialog */ - gtk_container_add( - GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), - label); - - /* And make it modal */ - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - - /* Show the dialog */ - gtk_widget_show_all(dialog); -} - - -/* - * Hook to tell the user something important - */ -static void hook_plog(cptr str) -{ - /* Warning message */ - gtk_message(str); -} - - -/* - * Process File-Quit menu command - */ -static void quit_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - /* Save current game */ - save_game_gtk(); - - /* It's done */ - quit(NULL); -} - - -/* - * Process File-Save menu command - */ -static void save_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - /* Save current game */ - save_game_gtk(); -} - - -/* - * Handle destruction of the Angband window - */ -static void destroy_main_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - /* This allows for cheating, but... */ - quit(NULL); -} - - -/* - * Handle destruction of Subwindows - */ -static void destroy_sub_event_handler( - GtkWidget *window, - gpointer user_data) -{ - /* Hide the window */ - gtk_widget_hide_all(window); -} - - -#ifndef SAVEFILE_SCREEN - -/* - * Process File-New menu command - */ -static void new_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - if (game_in_progress) - { - plog("You can't start a new game while you're still playing!"); - return; - } - - /* The game is in progress */ - game_in_progress = TRUE; - - /* Flush input */ - Term_flush(); - - /* Play game */ - play_game(TRUE); - - /* Houseclearing */ - cleanup_angband(); - - /* Done */ - quit(NULL); -} - -#endif /* !SAVEFILE_SCREEN */ - - -/* - * Load fond specified by an XLFD fontname and - * set up related term_data members - */ -static void load_font(term_data *td, cptr fontname) -{ - GdkFont *old = td->font; - - /* Load font */ - td->font = gdk_font_load(fontname); - - if (td->font) - { - /* Free the old font */ - if (old) gdk_font_unref(old); - } - else - { - /* Oops, but we can still use the old one */ - td->font = old; - } - - /* Calculate the size of the font XXX */ - td->font_wid = gdk_char_width(td->font, '@'); - td->font_hgt = td->font->ascent + td->font->descent; - -#ifndef USE_DOUBLE_TILES - - /* Use the current font size for tiles as well */ - td->tile_wid = td->font_wid; - td->tile_hgt = td->font_hgt; - -#else /* !USE_DOUBLE_TILES */ - - /* Calculate the size of tiles */ - if (use_bigtile && (td == &data[0])) td->tile_wid = td->font_wid * 2; - else td->tile_wid = td->font_wid; - td->tile_hgt = td->font_hgt; - -#endif /* !USE_DOUBLE_TILES */ -} - - -/* - * React to OK button press in font selection dialogue - */ -static void font_ok_callback( - GtkWidget *widget, - GtkWidget *font_selector) -{ - gchar *fontname; - term_data *td; - - td = gtk_object_get_data(GTK_OBJECT(font_selector), "term_data"); - - g_assert(td != NULL); - - /* Retrieve font name from player's selection */ - fontname = gtk_font_selection_dialog_get_font_name( - GTK_FONT_SELECTION_DIALOG(font_selector)); - - /* Leave unless selection was valid */ - if (fontname == NULL) return; - - /* Load font and update font size info */ - load_font(td, fontname); - - /* Hack - Hide the window - finally found the trick... */ - gtk_widget_hide_all(td->window); - - /* Resizes the drawing area */ - gtk_drawing_area_size( - GTK_DRAWING_AREA(td->drawing_area), - td->cols * td->font_wid, - td->rows * td->font_hgt); - - /* Update the geometry hints for the window */ - term_data_set_geometry_hints(td); - - /* Reallocate the backing store */ - term_data_set_backing_store(td); - - /* Hack - Show the window */ - gtk_widget_show_all(td->window); - -#ifdef USE_GRAPHICS - - /* We have to resize tiles when we are in graphics mode */ - resize_request = TRUE; - -#endif /* USE_GRAPHICS */ - - /* Hack - force redraw */ - Term_key_push(KTRL('R')); -} - - -/* - * Process Options-Font-* menu command - */ -static void change_font_event_handler( - GtkWidget *widget, - gpointer user_data) -{ - GtkWidget *font_selector; - - gchar *spacings[] = { "c", "m", NULL }; - - font_selector = gtk_font_selection_dialog_new("Select font"); - - gtk_object_set_data( - GTK_OBJECT(font_selector), - "term_data", - user_data); - - /* Filter to show only fixed-width fonts */ - gtk_font_selection_dialog_set_filter( - GTK_FONT_SELECTION_DIALOG(font_selector), - GTK_FONT_FILTER_BASE, - GTK_FONT_ALL, - NULL, - NULL, - NULL, - NULL, - spacings, - NULL); - - gtk_signal_connect( - GTK_OBJECT(GTK_FONT_SELECTION_DIALOG(font_selector)->ok_button), - "clicked", - font_ok_callback, - (gpointer)font_selector); - - /* - * Ensure that the dialog box is destroyed when the user clicks - * a button. - */ - gtk_signal_connect_object( - GTK_OBJECT(GTK_FONT_SELECTION_DIALOG(font_selector)->ok_button), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - (gpointer)font_selector); - - gtk_signal_connect_object( - GTK_OBJECT(GTK_FONT_SELECTION_DIALOG(font_selector)->cancel_button), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - (gpointer)font_selector); - - gtk_widget_show(GTK_WIDGET(font_selector)); -} - - -/* - * Process Terms-* menu command - hide/show terminal window - */ -static void term_event_handler( - GtkWidget *widget, - gpointer user_data) -{ - term_data *td = (term_data *)user_data; - - /* We don't mess with the Angband window */ - if (td == &data[0]) return; - - /* It's shown */ - if (td->shown) - { - /* Hide the window */ - gtk_widget_hide_all(td->window); - } - - /* It's hidden */ - else - { - /* Show the window */ - gtk_widget_show_all(td->window); - } -} - - -/* - * Toggles the boolean value of use_backing_store and - * setup / remove backing store for each term - */ -static void change_backing_store_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - int i; - - /* Toggle the backing store mode */ - use_backing_store = !use_backing_store; - - /* Reset terms */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - term_data_set_backing_store(&data[i]); - } -} - - -#ifdef USE_GRAPHICS - -/* - * Set graf_mode_request according to user selection, - * and let Term_xtra react to the change. - */ -static void change_graf_mode_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - /* Set request according to user selection */ - graf_mode_request = (int)user_data; - - /* - * Hack - force redraw - * This induces a call to Term_xtra(TERM_XTRA_REACT, 0) as well - */ - Term_key_push(KTRL('R')); -} - - -/* - * Set dither_mode according to user selection - */ -static void change_dith_mode_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - /* Set request according to user selection */ - dith_mode = (int)user_data; - - /* - * Hack - force redraw - */ - Term_key_push(KTRL('R')); -} - - -/* - * Toggles the graphics tile scaling mode (Fast/Smooth) - */ -static void change_smooth_mode_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - /* (Try to) toggle the smooth rescaling mode */ - smooth_rescaling_request = !smooth_rescaling; - - /* - * Hack - force redraw - * This induces a call to Term_xtra(TERM_XTRA_REACT, 0) as well - */ - Term_key_push(KTRL('R')); -} - - -# ifdef USE_DOUBLE_TILES - -static void change_wide_tile_mode_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - term *old = Term; - term_data *td = &data[0]; - - /* Toggle "use_bigtile" */ - use_bigtile = !use_bigtile; - -#ifdef TOME - /* T.o.M.E. requires this as well */ - arg_bigtile = use_bigtile; -#endif /* TOME */ - - /* Double the width of tiles (only for the main window) */ - if (use_bigtile) - { - td->tile_wid = td->font_wid * 2; - } - - /* Use the width of current font */ - else - { - td->tile_wid = td->font_wid; - } - - /* Need to resize the tiles */ - resize_request = TRUE; - - /* Activate the main window */ - Term_activate(&td->t); - - /* Resize the term */ - Term_resize(td->cols, td->rows); - - /* Activate the old term */ - Term_activate(old); - - /* Hack - force redraw XXX ??? XXX */ - Term_key_push(KTRL('R')); -} - -# endif /* USE_DOUBLE_TILES */ - - -# ifdef USE_TRANSPARENCY - -/* - * Toggles the boolean value of use_transparency - */ -static void change_trans_mode_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - /* Toggle the transparency mode */ - use_transparency = !use_transparency; - - /* Hack - force redraw */ - Term_key_push(KTRL('R')); -} - -# endif /* USE_TRANSPARENCY */ - -#endif /* USE_GRAPHICS */ - - -#ifndef SAVEFILE_SCREEN - -/* - * Caution: Modal or not, callbacks are called by gtk_main(), - * so this is the right place to start a game. - */ -static void file_ok_callback( - GtkWidget *widget, - GtkWidget *file_selector) -{ - strcpy(savefile, - gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector))); - - gtk_widget_destroy(file_selector); - - /* game is in progress */ - game_in_progress = TRUE; - - /* Flush input */ - Term_flush(); - - /* Play game */ - play_game(FALSE); - - /* Free memory allocated by game */ - cleanup_angband(); - - /* Done */ - quit(NULL); -} - - -/* - * Process File-Open menu command - */ -static void open_event_handler( - GtkButton *was_clicked, - gpointer user_data) -{ - GtkWidget *file_selector; - char buf[1024]; - - - if (game_in_progress) - { - plog("You can't open a new game while you're still playing!"); - return; - } - - /* Prepare the savefile path */ - path_build(buf, 1024, ANGBAND_DIR_SAVE, "*"); - - file_selector = gtk_file_selection_new("Select a savefile"); - gtk_file_selection_set_filename( - GTK_FILE_SELECTION(file_selector), - buf); - gtk_signal_connect( - GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), - "clicked", - file_ok_callback, - (gpointer)file_selector); - - /* - * Ensure that the dialog box is destroyed when the user - * clicks a button. - */ - gtk_signal_connect_object( - GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - (gpointer)file_selector); - - gtk_signal_connect_object( - GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->cancel_button), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - (gpointer)file_selector); - - gtk_window_set_modal(GTK_WINDOW(file_selector), TRUE); - gtk_widget_show(GTK_WIDGET(file_selector)); -} - -#endif /* !SAVEFILE_SCREEN */ - - -/* - * React to "delete" signal sent to Window widgets - */ -static gboolean delete_event_handler( - GtkWidget *widget, - GdkEvent *event, - gpointer user_data) -{ - /* Save game if possible */ - save_game_gtk(); - - /* Don't prevent closure */ - return (FALSE); -} - - -/* - * Convert keypress events to ASCII codes and enqueue them - * for game - */ -static gboolean keypress_event_handler( - GtkWidget *widget, - GdkEventKey *event, - gpointer user_data) -{ - int i, mc, ms, mo, mx; - - char msg[128]; - - - /* Extract four "modifier flags" */ - mc = (event->state & GDK_CONTROL_MASK) ? TRUE : FALSE; - ms = (event->state & GDK_SHIFT_MASK) ? TRUE : FALSE; - mo = (event->state & GDK_MOD1_MASK) ? TRUE : FALSE; - mx = (event->state & GDK_MOD3_MASK) ? TRUE : FALSE; - - /* - * Hack XXX - * Parse shifted numeric (keypad) keys specially. - */ - if ((event->state == GDK_SHIFT_MASK) - && (event->keyval >= GDK_KP_0) && (event->keyval <= GDK_KP_9)) - { - /* Build the macro trigger string */ - strnfmt(msg, 128, "%cS_%X%c", 31, event->keyval, 13); - - /* Enqueue the "macro trigger" string */ - for (i = 0; msg[i]; i++) Term_keypress(msg[i]); - - /* Hack -- auto-define macros as needed */ - if (event->length && (macro_find_exact(msg) < 0)) - { - /* Create a macro */ - macro_add(msg, event->string); - } - - return (TRUE); - } - - /* Normal keys with no modifiers */ - if (event->length && !mo && !mx) - { - /* Enqueue the normal key(s) */ - for (i = 0; i < event->length; i++) Term_keypress(event->string[i]); - - /* All done */ - return (TRUE); - } - - /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */ - switch ((uint) event->keyval) - { - case GDK_Escape: - { - Term_keypress(ESCAPE); - return (TRUE); - } - - case GDK_Return: - { - Term_keypress('\r'); - return (TRUE); - } - - case GDK_Tab: - { - Term_keypress('\t'); - return (TRUE); - } - - case GDK_Delete: - case GDK_BackSpace: - { - Term_keypress('\010'); - return (TRUE); - } - - case GDK_Shift_L: - case GDK_Shift_R: - case GDK_Control_L: - case GDK_Control_R: - case GDK_Caps_Lock: - case GDK_Shift_Lock: - case GDK_Meta_L: - case GDK_Meta_R: - case GDK_Alt_L: - case GDK_Alt_R: - case GDK_Super_L: - case GDK_Super_R: - case GDK_Hyper_L: - case GDK_Hyper_R: - { - /* Hack - do nothing to control characters */ - return (TRUE); - } - } - - /* Build the macro trigger string */ - strnfmt(msg, 128, "%c%s%s%s%s_%X%c", 31, - mc ? "N" : "", ms ? "S" : "", - mo ? "O" : "", mx ? "M" : "", - event->keyval, 13); - - /* Enqueue the "macro trigger" string */ - for (i = 0; msg[i]; i++) Term_keypress(msg[i]); - - /* Hack -- auto-define macros as needed */ - if (event->length && (macro_find_exact(msg) < 0)) - { - /* Create a macro */ - macro_add(msg, event->string); - } - - return (TRUE); -} - - -/* - * Widget customisation (for drawing area) - "realize" signal - * - * In this program, called when window containing the drawing - * area is shown first time. - */ -static void realize_event_handler( - GtkWidget *widget, - gpointer user_data) -{ - term_data *td = (term_data *)user_data; - - /* Create graphic context */ - td->gc = gdk_gc_new(td->drawing_area->window); - - /* Set foreground and background colours - isn't bg used at all? */ - gdk_rgb_gc_set_background(td->gc, 0x000000); - gdk_rgb_gc_set_foreground(td->gc, angband_colours[TERM_WHITE]); - - /* No last foreground colour, yet */ - td->last_attr = -1; - - /* Allocate the backing store */ - term_data_set_backing_store(td); - - /* Clear the window */ - gdk_draw_rectangle( - widget->window, - widget->style->black_gc, - TRUE, - 0, - 0, - td->cols * td->font_wid, - td->rows * td->font_hgt); -} - - -/* - * Widget customisation (for drawing area) - "show" signal - */ -static void show_event_handler( - GtkWidget *widget, - gpointer user_data) -{ - term_data *td = (term_data *)user_data; - - /* Set the shown flag */ - td->shown = TRUE; -} - - -/* - * Widget customisation (for drawing area) - "hide" signal - */ -static void hide_event_handler( - GtkWidget *widget, - gpointer user_data) -{ - term_data *td = (term_data *)user_data; - - /* Set the shown flag */ - td->shown = FALSE; -} - - -/* - * Widget customisation (for drawing area)- handle size allocation requests - */ -static void size_allocate_event_handler( - GtkWidget *widget, - GtkAllocation *allocation, - gpointer user_data) -{ - term_data *td = user_data; - int old_rows, old_cols; - term *old = Term; - - /* Paranoia */ - g_return_if_fail(widget != NULL); - g_return_if_fail(allocation != NULL); - g_return_if_fail(td != NULL); - - /* Remember old values */ - old_cols = td->cols; - old_rows = td->rows; - - /* Update numbers of rows and columns */ - td->cols = (allocation->width + td->font_wid - 1) / td->font_wid; - td->rows = (allocation->height + td->font_hgt - 1) / td->font_hgt; - - /* Overkill - Validate them */ - term_data_check_size(td); - - /* Adjust size request and set it */ - allocation->width = td->cols * td->font_wid; - allocation->height = td->rows * td->font_hgt; - widget->allocation = *allocation; - - /* Widget is realized, so we do some drawing works */ - if (GTK_WIDGET_REALIZED(widget)) - { - /* Reallocate the backing store */ - term_data_set_backing_store(td); - - /* Actually handles resizing in Gtk */ - gdk_window_move_resize( - widget->window, - allocation->x, - allocation->y, - allocation->width, - allocation->height); - - /* And in the term package */ - Term_activate(&td->t); - - /* Resize if necessary */ - if ((td->cols != old_cols) || (td->rows != old_rows)) - (void)Term_resize(td->cols, td->rows); - - /* Redraw its content */ - Term_redraw(); - - /* Refresh */ - Term_fresh(); - - /* Restore */ - Term_activate(old); - } -} - - -/* - * Update exposed area in a window (for drawing area) - */ -static gboolean expose_event_handler( - GtkWidget *widget, - GdkEventExpose *event, - gpointer user_data) -{ - term_data *td = user_data; - - term *old = Term; - -#ifndef NO_REDRAW_SECTION - - int x1, x2, y1, y2; - -#endif /* !NO_REDRAW_SECTION */ - - - /* Paranoia */ - if (td == NULL) return (TRUE); - - /* The window has a backing store */ - if (td->backing_store) - { - /* Simply restore the exposed area from the backing store */ - gdk_draw_pixmap( - td->drawing_area->window, - td->gc, - td->backing_store, - event->area.x, - event->area.y, - event->area.x, - event->area.y, - event->area.width, - event->area.height); - } - - /* No backing store - use the game's code to redraw the area */ - else - { - - /* Activate the relevant term */ - Term_activate(&td->t); - -# ifdef NO_REDRAW_SECTION - - /* K.I.S.S. version */ - - /* Redraw */ - Term_redraw(); - -# else /* NO_REDRAW_SECTION */ - - /* - * Complex version - The above is enough, but since we have - * Term_redraw_section... This might help if we had a graphics - * mode. - */ - - /* Convert coordinate in pixels to character cells */ - x1 = event->area.x / td->font_wid; - x2 = (event->area.x + event->area.width) / td->font_wid; - y1 = event->area.y / td->font_hgt; - y2 = (event->area.y + event->area.height) / td->font_hgt; - - /* - * No paranoia - boundary checking is done in - * Term_redraw_section - */ - - /* Redraw the area */ - Term_redraw_section(x1, y1, x2, y2); - -# endif /* NO_REDRAW_SECTION */ - - /* Refresh */ - Term_fresh(); - - /* Restore */ - Term_activate(old); - } - - /* We've processed the event ourselves */ - return (TRUE); -} - - - - -/**** Initialisation ****/ - -/* - * Initialise a term_data struct - */ -static errr term_data_init(term_data *td, int i) -{ - term *t = &td->t; - char *p; - - td->cols = 80; - td->rows = 24; - - /* Initialize the term */ - term_init(t, td->cols, td->rows, 1024); - - /* Store the name of the term */ - td->name = string_make(angband_term_name[i]); - - /* Instance names should start with a lowercase letter XXX */ - for (p = (char *)td->name; *p; p++) *p = tolower(*p); - - /* Use a "soft" cursor */ - t->soft_cursor = TRUE; - - /* Erase with "white space" */ - t->attr_blank = TERM_WHITE; - t->char_blank = ' '; - - t->xtra_hook = Term_xtra_gtk; - t->text_hook = Term_text_gtk; - t->wipe_hook = Term_wipe_gtk; - t->curs_hook = Term_curs_gtk; -#ifdef USE_GRAPHICS - t->pict_hook = Term_pict_gtk; -#endif /* USE_GRAPHICS */ - t->nuke_hook = Term_nuke_gtk; - - /* Save the data */ - t->data = td; - - /* Activate (important) */ - Term_activate(t); - - /* Success */ - return (0); -} - - -/* - * Neater menu code with GtkItemFactory. - * - * Menu bar of the Angband window - * - * Entry format: Path, Accelerator, Callback, Callback arg, type - * where type is one of: - * - simple item, alias NULL - * - has submenu - * - as you read it - * - has a check mark - * - is a toggle - */ -static GtkItemFactoryEntry main_menu_items[] = -{ - /* "File" menu */ - { "/File", NULL, - NULL, 0, "" - }, -#ifndef SAVEFILE_SCREEN - { "/File/New", "N", - new_event_handler, 0, NULL }, - { "/File/Open", "O", - open_event_handler, 0, NULL }, - { "/File/sep1", NULL, - NULL, 0, "" }, -#endif /* !SAVEFILE_SCREEN */ - { "/File/Save", "S", - save_event_handler, 0, NULL }, - { "/File/Quit", "Q", - quit_event_handler, 0, NULL }, - - /* "Terms" menu */ - { "/Terms", NULL, - NULL, 0, "" }, - /* XXX XXX XXX NULL's are replaced by the program */ - { NULL, "0", - term_event_handler, (guint)&data[0], "" }, - { NULL, "1", - term_event_handler, (guint)&data[1], "" }, - { NULL, "2", - term_event_handler, (guint)&data[2], "" }, - { NULL, "3", - term_event_handler, (guint)&data[3], "" }, - { NULL, "4", - term_event_handler, (guint)&data[4], "" }, - { NULL, "5", - term_event_handler, (guint)&data[5], "" }, - { NULL, "6", - term_event_handler, (guint)&data[6], "" }, - { NULL, "7", - term_event_handler, (guint)&data[7], "" }, - - /* "Options" menu */ - { "/Options", NULL, - NULL, 0, "" }, - - /* "Font" submenu */ - { "/Options/Font", NULL, - NULL, 0, "" }, - /* XXX XXX XXX Again, NULL's are filled by the program */ - { NULL, NULL, - change_font_event_handler, (guint)&data[0], NULL }, - { NULL, NULL, - change_font_event_handler, (guint)&data[1], NULL }, - { NULL, NULL, - change_font_event_handler, (guint)&data[2], NULL }, - { NULL, NULL, - change_font_event_handler, (guint)&data[3], NULL }, - { NULL, NULL, - change_font_event_handler, (guint)&data[4], NULL }, - { NULL, NULL, - change_font_event_handler, (guint)&data[5], NULL }, - { NULL, NULL, - change_font_event_handler, (guint)&data[6], NULL }, - { NULL, NULL, - change_font_event_handler, (guint)&data[7], NULL }, - -#ifdef USE_GRAPHICS - - /* "Graphics" submenu */ - { "/Options/Graphics", NULL, - NULL, 0, "" }, - { "/Options/Graphics/None", NULL, - change_graf_mode_event_handler, GRAF_MODE_NONE, "" }, - { "/Options/Graphics/Old", NULL, - change_graf_mode_event_handler, GRAF_MODE_OLD, "" }, - { "/Options/Graphics/New", NULL, - change_graf_mode_event_handler, GRAF_MODE_NEW, "" }, -# ifdef USE_DOUBLE_TILES - { "/Options/Graphics/sep3", NULL, - NULL, 0, "" }, - { "/Options/Graphics/Wide tiles", NULL, - change_wide_tile_mode_event_handler, 0, "" }, -# endif /* USE_DOUBLE_TILES */ - { "/Options/Graphics/sep1", NULL, - NULL, 0, "" }, - { "/Options/Graphics/Dither if <= 8bpp", NULL, - change_dith_mode_event_handler, GDK_RGB_DITHER_NORMAL, "" }, - { "/Options/Graphics/Dither if <= 16bpp", NULL, - change_dith_mode_event_handler, GDK_RGB_DITHER_MAX, "" }, - { "/Options/Graphics/sep2", NULL, - NULL, 0, "" }, - { "/Options/Graphics/Smoothing", NULL, - change_smooth_mode_event_handler, 0, "" }, -# ifdef USE_TRANSPARENCY - { "/Options/Graphics/Transparency", NULL, - change_trans_mode_event_handler, 0, "" }, -# endif /* USE_TRANSPARENCY */ - -#endif /* USE_GRAPHICS */ - - /* "Misc" submenu */ - { "/Options/Misc", NULL, - NULL, 0, "" }, - { "/Options/Misc/Backing store", NULL, - change_backing_store_event_handler, 0, "" }, -}; - - -/* - * XXX XXX Fill those NULL's in the menu definition with - * angband_term_name[] strings - */ -static void setup_menu_paths(void) -{ - int i; - int nmenu_items = sizeof(main_menu_items) / sizeof(main_menu_items[0]); - GtkItemFactoryEntry *term_entry, *font_entry; - char buf[64]; - - /* Find the "Terms" menu */ - for (i = 0; i < nmenu_items; i++) - { - /* Skip NULLs */ - if (main_menu_items[i].path == NULL) continue; - - /* Find a match */ - if (streq(main_menu_items[i].path, "/Terms")) break; - } - g_assert(i < (nmenu_items - MAX_TERM_DATA)); - - /* Remember the location */ - term_entry = &main_menu_items[i + 1]; - - /* Find "Font" menu */ - for (i = 0; i < nmenu_items; i++) - { - /* Skip NULLs */ - if (main_menu_items[i].path == NULL) continue; - - /* Find a match */ - if (streq(main_menu_items[i].path, "/Options/Font")) break; - } - g_assert(i < (nmenu_items - MAX_TERM_DATA)); - - /* Remember the location */ - font_entry = &main_menu_items[i + 1]; - - /* For each terminal */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - /* XXX XXX Build the real path name to the entry */ - strnfmt(buf, 64, "/Terms/%s", angband_term_name[i]); - - /* XXX XXX Store it in the menu definition */ - (cptr)term_entry[i].path = string_make(buf); - - /* XXX XXX Build the real path name to the entry */ - strnfmt(buf, 64, "/Options/Font/%s", angband_term_name[i]); - - /* XXX XXX Store it in the menu definition */ - (cptr)font_entry[i].path = string_make(buf); - } -} - - -/* - * XXX XXX Free strings allocated by setup_menu_paths() - */ -static void free_menu_paths(void) -{ - int i; - int nmenu_items = sizeof(main_menu_items) / sizeof(main_menu_items[0]); - GtkItemFactoryEntry *term_entry, *font_entry; - - /* Find the "Terms" menu */ - for (i = 0; i < nmenu_items; i++) - { - /* Skip NULLs */ - if (main_menu_items[i].path == NULL) continue; - - /* Find a match */ - if (streq(main_menu_items[i].path, "/Terms")) break; - } - g_assert(i < (nmenu_items - MAX_TERM_DATA)); - - /* Remember the location */ - term_entry = &main_menu_items[i + 1]; - - /* Find "Font" menu */ - for (i = 0; i < nmenu_items; i++) - { - /* Skip NULLs */ - if (main_menu_items[i].path == NULL) continue; - - /* Find a match */ - if (streq(main_menu_items[i].path, "/Options/Font")) break; - } - g_assert(i < (nmenu_items - MAX_TERM_DATA)); - - /* Remember the location */ - font_entry = &main_menu_items[i + 1]; - - /* For each terminal */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - /* XXX XXX Free Term menu path */ - if (term_entry[i].path) string_free((cptr)term_entry[i].path); - - /* XXX XXX Free Font menu path */ - if (font_entry[i].path) string_free((cptr)font_entry[i].path); - } -} - - -/* - * Find widget corresponding to path name - * return NULL on error - */ -static GtkWidget *get_widget_from_path(cptr path) -{ - GtkItemFactory *item_factory; - GtkWidget *widget; - - /* Paranoia */ - if (path == NULL) return (NULL); - - /* Look up item factory */ - item_factory = gtk_item_factory_from_path(path); - - /* Oops */ - if (item_factory == NULL) return (NULL); - - /* Look up widget */ - widget = gtk_item_factory_get_widget(item_factory, path); - - /* Return result */ - return (widget); -} - - -/* - * Enable/disable a menu item - */ -void enable_menu_item(cptr path, bool_ enabled) -{ - GtkWidget *widget; - - /* Access menu item widget */ - widget = get_widget_from_path(path); - - /* Paranoia */ - g_assert(widget != NULL); - g_assert(GTK_IS_MENU_ITEM(widget)); - - /* - * In Gtk's terminology, enabled is sensitive - * and disabled insensitive - */ - gtk_widget_set_sensitive(widget, enabled); -} - - -/* - * Check/uncheck a menu item. The item should be of the GtkCheckMenuItem type - */ -void check_menu_item(cptr path, bool_ checked) -{ - GtkWidget *widget; - - /* Access menu item widget */ - widget = get_widget_from_path(path); - - /* Paranoia */ - g_assert(widget != NULL); - g_assert(GTK_IS_CHECK_MENU_ITEM(widget)); - - /* - * Put/remove check mark - * - * Mega-Hack -- The function supposed to be used here, - * gtk_check_menu_item_set_active(), emits an "activate" signal - * to the GtkMenuItem class of the widget, as if the menu item - * were selected by user, thereby causing bizarre behaviour. - * XXX XXX XXX - */ - GTK_CHECK_MENU_ITEM(widget)->active = checked; -} - - -/* - * Update the "File" menu - */ -static void file_menu_update_handler( - GtkWidget *widget, - gpointer user_data) -{ -#ifndef SAVEFILE_SCREEN - bool_ game_start_ok; -#endif /* !SAVEFILE_SCREEN */ - bool_ save_ok, quit_ok; - -#ifndef SAVEFILE_SCREEN - - /* Can we start a game now? */ - game_start_ok = !game_in_progress; - -#endif /* !SAVEFILE_SCREEN */ - - /* Cave we save/quit now? */ - if (!character_generated || !game_in_progress) - { - save_ok = FALSE; - quit_ok = TRUE; - } - else - { - if (inkey_flag && can_save) save_ok = quit_ok = TRUE; - else save_ok = quit_ok = FALSE; - } - - /* Enable / disable menu items according to those conditions */ -#ifndef SAVEFILE_SCREEN - enable_menu_item("/File/New", game_start_ok); - enable_menu_item("/File/Open", game_start_ok); -#endif /* !SAVEFILE_SCREEN */ - enable_menu_item("/File/Save", save_ok); - enable_menu_item("/File/Quit", quit_ok); -} - - -/* - * Update the "Terms" menu - */ -static void term_menu_update_handler( - GtkWidget *widget, - gpointer user_data) -{ - int i; - char buf[64]; - - /* For each term */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - /* Build the path name */ - strnfmt(buf, 64, "/Terms/%s", angband_term_name[i]); - - /* Update the check mark on the item */ - check_menu_item(buf, data[i].shown); - } -} - - -/* - * Update the "Font" submenu - */ -static void font_menu_update_handler( - GtkWidget *widget, - gpointer user_data) -{ - int i; - char buf[64]; - - /* For each term */ - for (i = 0; i < MAX_TERM_DATA; i++) - { - /* Build the path name */ - strnfmt(buf, 64, "/Options/Font/%s", angband_term_name[i]); - - /* Enable selection if the term is shown */ - enable_menu_item(buf, data[i].shown); - } -} - - -/* - * Update the "Misc" submenu - */ -static void misc_menu_update_handler( - GtkWidget *widget, - gpointer user_data) -{ - /* Update an item */ - check_menu_item( - "/Options/Misc/Backing store", - use_backing_store); -} - - -#ifdef USE_GRAPHICS - -/* - * Update the "Graphics" submenu - */ -static void graf_menu_update_handler( - GtkWidget *widget, - gpointer user_data) -{ - /* Update menu items */ - check_menu_item( - "/Options/Graphics/None", - (graf_mode == GRAF_MODE_NONE)); - check_menu_item( - "/Options/Graphics/Old", - (graf_mode == GRAF_MODE_OLD)); - check_menu_item( - "/Options/Graphics/New", - (graf_mode == GRAF_MODE_NEW)); - -#ifdef USE_DOUBLE_TILES - - check_menu_item( - "/Options/Graphics/Wide tiles", - use_bigtile); - -#endif /* USE_DOUBLE_TILES */ - - check_menu_item( - "/Options/Graphics/Dither if <= 8bpp", - (dith_mode == GDK_RGB_DITHER_NORMAL)); - check_menu_item( - "/Options/Graphics/Dither if <= 16bpp", - (dith_mode == GDK_RGB_DITHER_MAX)); - - check_menu_item( - "/Options/Graphics/Smoothing", - smooth_rescaling); - -# ifdef USE_TRANSPARENCY - - check_menu_item( - "/Options/Graphics/Transparency", - use_transparency); - -# endif /* USE_TRANSPARENCY */ -} - -#endif /* USE_GRAPHICS */ - - -/* - * Construct a menu hierarchy using GtkItemFactory, setting up - * callbacks and accelerators along the way, and return - * a GtkMenuBar widget. - */ -GtkWidget *get_main_menu(term_data *td) -{ - GtkItemFactory *item_factory; - GtkAccelGroup *accel_group; - gint nmenu_items = sizeof(main_menu_items) / sizeof(main_menu_items[0]); - - - /* XXX XXX Setup path names in the "Terms" and "Font" menus */ - setup_menu_paths(); - - /* Allocate an accelerator group */ - accel_group = gtk_accel_group_new(); - g_assert(accel_group != NULL); - - /* Initialise the item factory */ - item_factory = gtk_item_factory_new( - GTK_TYPE_MENU_BAR, - "", - accel_group); - g_assert(item_factory != NULL); - - /* Generate the menu items */ - gtk_item_factory_create_items( - item_factory, - nmenu_items, - main_menu_items, - NULL); - - /* Attach the new accelerator group to the window */ - gtk_window_add_accel_group( - GTK_WINDOW(td->window), - accel_group); - - /* Return the actual menu bar created */ - return (gtk_item_factory_get_widget(item_factory, "")); -} - - -/* - * Install callbacks to update menus - */ -static void add_menu_update_callbacks() -{ - GtkWidget *widget; - - /* Access the "File" menu */ - widget = get_widget_from_path("/File"); - - /* Paranoia */ - g_assert(widget != NULL); - g_assert(GTK_IS_MENU(widget)); - - /* Assign callback */ - gtk_signal_connect( - GTK_OBJECT(widget), - "show", - GTK_SIGNAL_FUNC(file_menu_update_handler), - NULL); - - /* Access the "Terms" menu */ - widget = get_widget_from_path("/Terms"); - - /* Paranoia */ - g_assert(widget != NULL); - g_assert(GTK_IS_MENU(widget)); - - /* Assign callback */ - gtk_signal_connect( - GTK_OBJECT(widget), - "show", - GTK_SIGNAL_FUNC(term_menu_update_handler), - NULL); - - /* Access the "Font" menu */ - widget = get_widget_from_path("/Options/Font"); - - /* Paranoia */ - g_assert(widget != NULL); - g_assert(GTK_IS_MENU(widget)); - - /* Assign callback */ - gtk_signal_connect( - GTK_OBJECT(widget), - "show", - GTK_SIGNAL_FUNC(font_menu_update_handler), - NULL); - - /* Access the "Misc" menu */ - widget = get_widget_from_path("/Options/Misc"); - - /* Paranoia */ - g_assert(widget != NULL); - g_assert(GTK_IS_MENU(widget)); - - /* Assign callback */ - gtk_signal_connect( - GTK_OBJECT(widget), - "show", - GTK_SIGNAL_FUNC(misc_menu_update_handler), - NULL); - -#ifdef USE_GRAPHICS - - /* Access Graphics menu */ - widget = get_widget_from_path("/Options/Graphics"); - - /* Paranoia */ - g_assert(widget != NULL); - g_assert(GTK_IS_MENU(widget)); - - /* Assign callback */ - gtk_signal_connect( - GTK_OBJECT(widget), - "show", - GTK_SIGNAL_FUNC(graf_menu_update_handler), - NULL); - -#endif /* USE_GRAPHICS */ -} - - -/* - * Create Gtk widgets for a terminal window and set up callbacks - */ -static void init_gtk_window(term_data *td, int i) -{ - GtkWidget *menu_bar = NULL, *box; - cptr font; - - bool_ main_window = (i == 0) ? TRUE : FALSE; - - - /* Create window */ - td->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - /* Set title */ - gtk_window_set_title(GTK_WINDOW(td->window), td->name); - - - /* Get default font for this term */ - font = get_default_font(i); - - /* Load font and initialise related term_data fields */ - load_font(td, font); - - - /* Create drawing area */ - td->drawing_area = gtk_drawing_area_new(); - - /* Set the size of the drawing area */ - gtk_drawing_area_size( - GTK_DRAWING_AREA(td->drawing_area), - td->cols * td->font_wid, - td->rows * td->font_hgt); - - /* Set geometry hints */ - term_data_set_geometry_hints(td); - - - /* Install window event handlers */ - gtk_signal_connect( - GTK_OBJECT(td->window), - "delete_event", - GTK_SIGNAL_FUNC(delete_event_handler), - NULL); - gtk_signal_connect( - GTK_OBJECT(td->window), - "key_press_event", - GTK_SIGNAL_FUNC(keypress_event_handler), - NULL); - - /* Destroying the Angband window terminates the game */ - if (main_window) - { - gtk_signal_connect( - GTK_OBJECT(td->window), - "destroy_event", - GTK_SIGNAL_FUNC(destroy_main_event_handler), - NULL); - } - - /* The other windows are just hidden */ - else - { - gtk_signal_connect( - GTK_OBJECT(td->window), - "destroy_event", - GTK_SIGNAL_FUNC(destroy_sub_event_handler), - td); - } - - - /* Install drawing area event handlers */ - gtk_signal_connect( - GTK_OBJECT(td->drawing_area), - "realize", - GTK_SIGNAL_FUNC(realize_event_handler), - (gpointer)td); - gtk_signal_connect( - GTK_OBJECT(td->drawing_area), - "show", - GTK_SIGNAL_FUNC(show_event_handler), - (gpointer)td); - gtk_signal_connect( - GTK_OBJECT(td->drawing_area), - "hide", - GTK_SIGNAL_FUNC(hide_event_handler), - (gpointer)td); - gtk_signal_connect( - GTK_OBJECT(td->drawing_area), - "size_allocate", - GTK_SIGNAL_FUNC(size_allocate_event_handler), - (gpointer)td); - gtk_signal_connect( - GTK_OBJECT(td->drawing_area), - "expose_event", - GTK_SIGNAL_FUNC(expose_event_handler), - (gpointer)td); - - - /* Create menu */ - if (main_window) - { - /* Build the main menu bar */ - menu_bar = get_main_menu(td); - g_assert(menu_bar != NULL); - - /* Since it's tedious to scatter the menu update code around */ - add_menu_update_callbacks(); - } - - - /* Pack the menu bar together with the main window */ - /* For vertical placement of the menu bar and the drawing area */ - box = gtk_vbox_new(FALSE, 0); - - /* Let the window widget own it */ - gtk_container_add(GTK_CONTAINER(td->window), box); - - /* The main window has a menu bar */ - if (main_window) - gtk_box_pack_start( - GTK_BOX(box), - menu_bar, - FALSE, - FALSE, - NO_PADDING); - - /* And place the drawing area just beneath it */ - gtk_box_pack_start_defaults(GTK_BOX(box), td->drawing_area); - - - /* Show the widgets - use of td->shown is a dirty hack XXX XXX */ - if (td->shown) gtk_widget_show_all(td->window); -} - - -/* - * To be hooked into quit(). See z-util.c - */ -static void hook_quit(cptr str) -{ - /* Free menu paths dynamically allocated */ - free_menu_paths(); - -# ifdef USE_GRAPHICS - - /* Free pathname string */ - if (ANGBAND_DIR_XTRA_GRAF) string_free(ANGBAND_DIR_XTRA_GRAF); - -# endif /* USE_GRAPHICS */ - - /* Terminate the program */ - gtk_exit(0); -} - - -#ifdef ANGBAND300 - -/* - * Help message for this port - */ -const char help_gtk[] = - "GTK for X11, subopts -n\n" - " -b(acking store off)\n" -#ifdef USE_GRAPHICS - " -g(raphics) -o(ld graphics) -s(moothscaling off) \n" - " -t(ransparency on)\n" -# ifdef USE_DOUBLE_TILES - " -w(ide tiles)\n" -# endif /* USE_DOUBLE_TILES */ -#endif /* USE_GRAPHICS */ - " and standard GTK options"; - -#endif /* ANGBAND300 */ - - -/* - * Initialization function - */ -errr init_gtk(int argc, char **argv) -{ - int i; - - - /* Initialize the environment */ - gtk_init(&argc, &argv); - - /* Activate hooks - Use gtk/glib interface throughout */ - ralloc_aux = hook_ralloc; - rnfree_aux = hook_rnfree; - quit_aux = hook_quit; - core_aux = hook_quit; - - /* Parse args */ - for (i = 1; i < argc; i++) - { - /* Number of terminals displayed at start up */ - if (prefix(argv[i], "-n")) - { - num_term = atoi(&argv[i][2]); - if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA; - else if (num_term < 1) num_term = 1; - continue; - } - - /* Disable use of pixmaps as backing store */ - if (streq(argv[i], "-b")) - { - use_backing_store = FALSE; - continue; - } - -#ifdef USE_GRAPHICS - - /* Requests "old" graphics */ - if (streq(argv[i], "-o")) - { - graf_mode_request = GRAF_MODE_OLD; - continue; - } - - /* Requests "new" graphics */ - if (streq(argv[i], "-g")) - { - graf_mode_request = GRAF_MODE_NEW; - continue; - } - -# ifdef USE_DOUBLE_TILES - - /* Requests wide tile mode */ - if (streq(argv[i], "-w")) - { - use_bigtile = TRUE; -# ifdef TOME - /* T.o.M.E. uses older version of the patch */ - arg_bigtile = TRUE; -# endif /* TOME */ - continue; - } - -# endif /* USE_DOUBLE_TILES */ - - - /* Enable transparency effect */ - if (streq(argv[i], "-t")) - { - use_transparency = TRUE; - continue; - } - - /* Disable smooth rescaling of tiles */ - if (streq(argv[i], "-s")) - { - smooth_rescaling_request = FALSE; - continue; - } - -#endif /* USE_GRAPHICS */ - - /* None of the above */ - plog_fmt("Ignoring option: %s", argv[i]); - } - -#ifdef USE_GRAPHICS - - { - char path[1024]; - - /* Build the "graf" path */ - path_build(path, 1024, ANGBAND_DIR_XTRA, "graf"); - - /* Allocate the path */ - ANGBAND_DIR_XTRA_GRAF = string_make(path); - } - -#endif /* USE_GRAPHICS */ - - /* Initialise colours */ - gdk_rgb_init(); - gtk_widget_set_default_colormap(gdk_rgb_get_cmap()); - gtk_widget_set_default_visual(gdk_rgb_get_visual()); - init_colours(); - - /* - * Initialise the windows backwards, so that - * the Angband window comes in front - */ - for (i = MAX_TERM_DATA - 1; i >= 0; i--) - { - term_data *td = &data[i]; - - /* Initialize the term_data */ - term_data_init(td, i); - - /* Hack - Set the shown flag, meaning "to be shown" XXX XXX */ - if (i < num_term) td->shown = TRUE; - else td->shown = FALSE; - - /* Save global entry */ - angband_term[i] = Term; - - /* Init the window */ - init_gtk_window(td, i); - } - - /* Activate the "Angband" window screen */ - Term_activate(&data[0].t); - -#ifndef SAVEFILE_SCREEN - - /* Set the system suffix */ - ANGBAND_SYS = "gtk"; - - /* Catch nasty signals */ - signals_init(); - - /* Initialize */ - init_angband(); - -#ifndef OLD_SAVEFILE_CODE - - /* Hack - because this port has New/Open menus XXX */ - savefile[0] = '\0'; - -#endif /* !OLD_SAVEFILE_CODE */ - - /* Prompt the user */ - prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 17); - Term_fresh(); - - /* Activate more hook */ - plog_aux = hook_plog; - - - /* Processing loop */ - gtk_main(); - - - /* Free allocated memory */ - cleanup_angband(); - - /* Stop now */ - quit(NULL); - -#else /* !SAVEFILE_SCREEN */ - - /* Activate more hook */ - plog_aux = hook_plog; - - /* It's too early to set this, but cannot do so elsewhere XXX XXX */ - game_in_progress = TRUE; - -#endif /* !SAVEFILE_SCREEN */ - - /* Success */ - return (0); -} - -#endif /* USE_GTK */ diff --git a/src/main.c b/src/main.c index e2a26356..0a3dbb9b 100644 --- a/src/main.c +++ b/src/main.c @@ -498,19 +498,6 @@ usage: puts(" -m Force 'main-.c' usage"); puts(" -d Define a 'lib' dir sub-path"); -#ifdef USE_GTK - puts(" -mgtk To use GTK"); - puts(" -- Sub options"); - puts(" -- -n# Number of terms to use"); - puts(" -- -b Turn off software backing store"); -# ifdef USE_GRAPHICS - puts(" -- -s Turn off smoothscaling graphics"); - puts(" -- -o Requests \"old\" graphics"); - puts(" -- -g Requests \"new\" graphics"); - puts(" -- -t Enable transparency effect"); -# endif /* USE_GRAPHICS */ -#endif /* USE_GTK */ - #ifdef USE_GTK2 puts(" -mgtk2 To use GTK2"); puts(" -- Sub options"); -- cgit v1.2.3