diff options
Diffstat (limited to 'src/main-xaw.c')
-rw-r--r-- | src/main-xaw.c | 1888 |
1 files changed, 0 insertions, 1888 deletions
diff --git a/src/main-xaw.c b/src/main-xaw.c deleted file mode 100644 index 8795e00d..00000000 --- a/src/main-xaw.c +++ /dev/null @@ -1,1888 +0,0 @@ -/* File: main-xaw.c */ - -/* - * Copyright (c) 1997 Ben Harrison, Torbjorn Lindgren, and others - * - * 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. - */ - - -/* - * This file helps Angband work with UNIX/X11 computers. - * - * To use this file, compile with "USE_XAW" defined, and link against all - * the various "X11" libraries which may be needed. - * - * See also "main-x11.c". - * - * The Angband widget is not as self-contained as it really should be. - * Originally everything was output to a Pixmap which was later copied - * to the screen when necessary. The idea was abandoned since Pixmaps - * create big performance problems for some really old X terminals (such - * as 3/50's running Xkernel). - * - * Initial framework (and some code) by Ben Harrison (benh@phial.com). - * - * Most of this file is by Torbjorn Lindgren (tl@cd.chalmers.se). - * - * Major modifications by Ben Harrison (benh@phial.com). - */ - - -#include "angband.h" - - -#ifdef USE_XAW - - -#ifndef __MAKEDEPEND__ -#include <X11/Xlib.h> -#include <X11/StringDefs.h> -#include <X11/Xutil.h> -#include <X11/Intrinsic.h> -#include <X11/Shell.h> -#include <X11/keysym.h> -#include <X11/keysymdef.h> -#include <X11/IntrinsicP.h> -#include <X11/CoreP.h> -#include <X11/ShellP.h> -#include <X11/StringDefs.h> -#include <X11/Xaw/SimpleP.h> -#include <X11/Xaw/Simple.h> -#include <X11/Xaw/XawInit.h> -#endif /* __MAKEDEPEND__ */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <dirent.h> - -/* /me pffts Solaris */ -#ifndef NAME_MAX -#define NAME_MAX _POSIX_NAME_MAX -#endif - - -/* - * Include some helpful X11 code. - */ -#include "maid-x11.c" - - - -/**** Resources ****/ - - -/* - -Name Class RepType Default Value ----- ----- ------- ------------- -background Background Pixel XtDefaultBackground -border BorderColor Pixel XtDefaultForeground -borderWidth BorderWidth Dimension 1 -cursor Cursor Cursor None -cursorName Cursor String NULL -destroyCallback Callback Pointer NULL -height Height Dimension 0 -insensitiveBorder Insensitive Pixmap Gray -mappedWhenManaged MappedWhenManaged Boolean True -pointerColor Foreground Pixel XtDefaultForeground -pointerColorBackground Background Pixel XtDefaultBackground -sensitive Sensitive Boolean True -width Width Dimension 0 -x Position Position 0 -y Position Position 0 - - -The colors can be changed using the standard Angband user pref files, -which can also be used to provide black text on a white background, -by setting color zero to "#FFFFFF" and color one to "#000000", since -the other colors are unused. - -*/ - - -/* - * New resource names - */ -#define XtNstartRows "startRows" -#define XtNstartColumns "startColumns" -#define XtNminRows "minRows" -#define XtNminColumns "minColumns" -#define XtNmaxRows "maxRows" -#define XtNmaxColumns "maxColumns" -#define XtNinternalBorder "internalBorder" -#define XtNredrawCallback "redrawCallback" - -/* - * Total normal colors - */ -#define NUM_COLORS 256 - -/* - * Special "XOR" color - */ -#define COLOR_XOR 256 - - - -/**** The Widget Code ****/ - - -/* - * Forward declarations - */ -typedef struct AngbandPart AngbandPart; -typedef struct AngbandRec *AngbandWidget; -typedef struct AngbandRec AngbandRec; -typedef struct AngbandClassRec *AngbandWidgetClass; -typedef struct AngbandClassPart AngbandClassPart; -typedef struct AngbandClassRec AngbandClassRec; - -typedef struct term_data term_data; - - -/* - * A structure for each "term" - */ -struct term_data -{ - term t; - - AngbandWidget widget; -}; - - -/* - * Maximum number of windows - */ -#define MAX_TERM_DATA 8 - - -/* - * An array of term_data's - */ -static term_data data[MAX_TERM_DATA]; - - -/* - * Current number of windows open - */ -static int num_term = MAX_TERM_DATA; - - -/* - * New fields for the Angband widget record - */ -struct AngbandPart -{ - /* Settable resources */ - int start_rows; - int start_columns; - int min_rows; - int min_columns; - int max_rows; - int max_columns; - int internal_border; - String font; - - XtCallbackList redraw_callbacks; - -#ifdef USE_GRAPHICS - - /* Tiles */ - XImage *tiles; - - /* Tempory storage for overlaying tiles. */ - XImage *TmpImage; - -#endif /* USE_GRAPHICS */ - - /* Private state */ - XFontStruct *fnt; - Dimension fontheight; - Dimension fontwidth; - Dimension fontascent; - - /* Color info for GC's */ - byte color[NUM_COLORS][4]; - - /* GC's (including "xor") */ - GC gc[NUM_COLORS + 1]; -}; - - -/* - * Full instance record declaration - */ -struct AngbandRec -{ - CorePart core; - SimplePart simple; - AngbandPart angband; -}; - - -/* - * New fields for the Angband widget class record - */ -struct AngbandClassPart -{ - int dummy; -}; - - -/* - * Full class record declaration - */ -struct AngbandClassRec -{ - CoreClassPart core_class; - SimpleClassPart simple_class; - AngbandClassPart angband_class; -}; - - - -/* - * Hack -- see below - */ -#define offset(field) XtOffsetOf(AngbandRec, angband.field) - - -/* - * Fallback resources for Angband widget - */ -static XtResource resources[] = -{ - { XtNstartRows, XtCValue, XtRInt, sizeof(int), - offset(start_rows), XtRImmediate, (XtPointer) 24 }, - { XtNstartColumns, XtCValue, XtRInt, sizeof(int), - offset(start_columns), XtRImmediate, (XtPointer) 80 }, - { XtNminRows, XtCValue, XtRInt, sizeof(int), - offset(min_rows), XtRImmediate, (XtPointer) 1 }, - { XtNminColumns, XtCValue, XtRInt, sizeof(int), - offset(min_columns), XtRImmediate, (XtPointer) 1 }, - { XtNmaxRows, XtCValue, XtRInt, sizeof(int), - offset(max_rows), XtRImmediate, (XtPointer) 255 }, - { XtNmaxColumns, XtCValue, XtRInt, sizeof(int), - offset(max_columns), XtRImmediate, (XtPointer) 255 }, - { XtNinternalBorder, XtCValue, XtRInt, sizeof(int), - offset(internal_border), XtRImmediate, (XtPointer) 2 }, - { XtNfont, XtCFont, XtRString, sizeof(char *), - offset(font), XtRString, DEFAULT_X11_FONT }, - { XtNredrawCallback, XtCCallback, XtRCallback, sizeof(XtPointer), - offset(redraw_callbacks), XtRCallback, (XtPointer)NULL } -}; - - -/* - * Hack -- see above - */ -#undef offset - - -/* - * Forward declarations for Widget functions - */ -static void Initialize(AngbandWidget request, AngbandWidget wnew); -static void Redisplay(AngbandWidget w, XEvent *event, Region region); -static Boolean SetValues(AngbandWidget current, AngbandWidget request, - AngbandWidget wnew, ArgList args, Cardinal *num_args); -static void Destroy(AngbandWidget widget); -static void Resize_term(AngbandWidget wnew); - -/* - * Forward declaration for internal functions - */ -static void calculateSizeHints(AngbandWidget wnew); -static XFontStruct *getFont(AngbandWidget widget, - String font, Boolean fallback); - - -/* - * Hack -- see below - */ -#define superclass (&simpleClassRec) - - -/* - * Class record constanst - */ -AngbandClassRec angbandClassRec = -{ - { - /* Core class fields initialization */ - /* superclass */ (WidgetClass) superclass, - /* class_name */ "Angband", - /* widget_size */ sizeof(AngbandRec), - /* class_initialize */ NULL, - /* class_part_initialize*/ NULL, - /* class_inited */ FALSE, - /* initialize */ (XtInitProc) Initialize, - /* initialize_hook */ NULL, - /* realize */ XtInheritRealize, - /* actions */ NULL, - /* num_actions */ 0, - /* resources */ resources, - /* num_resources */ XtNumber(resources), - /* xrm_class */ NULLQUARK, - /* compress_motion */ TRUE, - /* compress_exposure */ XtExposeCompressMultiple, - /* compress_enterleave */ TRUE, - /* visible_interest */ FALSE, - /* destroy */ (XtWidgetProc) Destroy, - /* resize */ (XtWidgetProc) Resize_term, - /* expose */ (XtExposeProc) Redisplay, - /* set_values */ (XtSetValuesFunc) SetValues, - /* set_values_hook */ NULL, - /* set_values_almost */ XtInheritSetValuesAlmost, - /* get_values_hook */ NULL, - /* accept_focus */ NULL, - /* version */ XtVersion, - /* callback_private */ NULL, - /* tm_table */ NULL, - /* query_geometry */ NULL, - /* display_accelerator */ XtInheritDisplayAccelerator, - /* extension */ NULL - }, - /* Simple class fields initialization */ - { - /* change_sensitive */ XtInheritChangeSensitive -#ifndef OLDXAW - , NULL -#endif - }, - /* Angband class fields initialization */ - { - /* nothing */ 0 - } -}; - -/* - * Hack -- see above - */ -#undef superclass - - -/* - * Class record pointer - */ -WidgetClass angbandWidgetClass = (WidgetClass) &angbandClassRec; - - -/* - * Public procedures - */ - -/* - * Simple routine to save the state of the game when the display connection - * is broken. Remember, you cannot do anything in this function that will - * generate X protocol requests. - */ -static int x_io_error_handler(Display *d) -{ - /* We have nothing to save */ - if (!character_generated) return 0; - - save_dungeon(); - save_player(); - - return 0; -} - - -/* - * Clear an area - */ -static void AngbandClearArea(AngbandWidget widget, - int x, int y, int w, int h, int a) -{ - /* Figure out which area to clear */ - y = y * widget->angband.fontheight + widget->angband.internal_border; - x = x * widget->angband.fontwidth + widget->angband.internal_border; - - /* Clear the area */ - XFillRectangle(XtDisplay(widget), XtWindow(widget), - widget->angband.gc[a], - x, y, - widget->angband.fontwidth * w, - widget->angband.fontheight * h); -} - - - -/* - * Output some text - */ -static void AngbandOutputText(AngbandWidget widget, int x, int y, - String txt, int len, int a) -{ - /* Do nothing if the string is null */ - if (!txt || !*txt) return; - - /* Check the length, and fix it if it's below zero */ - if (len < 0) len = strlen(txt); - - /* Figure out where to place the text */ - y = (y * widget->angband.fontheight + widget->angband.fontascent + - widget->angband.internal_border); - x = (x * widget->angband.fontwidth + widget->angband.internal_border); - - /* Place the string */ - XDrawImageString(XtDisplay(widget), XtWindow(widget), - widget->angband.gc[a], x, y, txt, len); -} - - -#ifdef USE_GRAPHICS - -/* - * Draw some graphical characters. - */ -static void AngbandOutputPict(AngbandWidget widget, int x, int y, int n, - const byte *ap, const char *cp, const byte *tap, const char *tcp, - const byte *eap, const char *ecp) -{ - int i, x1, y1; - - byte a; - char c; - - byte ta; - char tc; - - int x2, y2; - - byte ea; - char ec; - - int x3, y3; - bool_ has_overlay; - - int k, l; - unsigned long pixel, blank; - - /* Figure out where to place the text */ - y = (y * widget->angband.fontheight + widget->angband.internal_border); - x = (x * widget->angband.fontwidth + widget->angband.internal_border); - - for (i = 0; i < n; ++i) - { - a = *ap++; - c = *cp++; - - /* For extra speed - cache these values */ - x1 = (c & 0x7F) * widget->angband.fontwidth; - y1 = (a & 0x7F) * widget->angband.fontheight; - - ta = *tap++; - tc = *tcp++; - - /* For extra speed - cache these values */ - x2 = (tc & 0x7F) * widget->angband.fontwidth; - y2 = (ta & 0x7F) * widget->angband.fontheight; - - ea = *eap++; - ec = *ecp++; - has_overlay = (ea && ec); - - /* For extra speed -- cache these values */ - x3 = (ec & 0x7F) * widget->angband.fontwidth; - y3 = (ea & 0x7F) * widget->angband.fontheight; - - /* Optimise the common case */ - if ((x1 == x2) && (y1 == y2)) - { - - /* No overlay */ - if (!has_overlay) - { - /* Draw object / terrain */ - XPutImage(XtDisplay(widget), XtWindow(widget), - widget->angband.gc[0], - widget->angband.tiles, - x1, y1, - x, y, - widget->angband.fontwidth, - widget->angband.fontheight); - } - - /* Terrain overlay */ - else - { - /* Mega Hack^2 - assume the top left corner is "black" */ - blank = XGetPixel(widget->angband.tiles, - 0, widget->angband.fontheight * 6); - - for (k = 0; k < widget->angband.fontwidth; k++) - { - for (l = 0; l < widget->angband.fontheight; l++) - { - /* If mask set... */ - if ((pixel = XGetPixel(widget->angband.tiles, - x3 + k, y3 + l)) == blank) - { - /* Output from the terrain */ - pixel = XGetPixel(widget->angband.tiles, - x1 + k, y1 + l); - } - - /* Store into the temp storage */ - XPutPixel(widget->angband.TmpImage, - k, l, pixel); - } - } - - /* Draw terrain + overlay */ - XPutImage(XtDisplay(widget), XtWindow(widget), - widget->angband.gc[0], - widget->angband.TmpImage, - 0, 0, - x, y, - widget->angband.fontwidth, - widget->angband.fontheight); - } - - } - else - { - /* Mega Hack^2 - assume the top left corner is "black" */ - blank = XGetPixel(widget->angband.tiles, - 0, widget->angband.fontheight * 6); - - for (k = 0; k < widget->angband.fontwidth; k++) - { - for (l = 0; l < widget->angband.fontheight; l++) - { - /* Get overlay pixel */ - if (has_overlay) - { - pixel = XGetPixel(widget->angband.tiles, - x3 + k, y3 + l); - } - - /* Hack -- no overlay */ - else - { - pixel = blank; - } - - /* If it's blank */ - if (pixel == blank) - { - /* Use obj/mon */ - pixel = XGetPixel(widget->angband.tiles, - x1 + k, y1 + l); - } - - /* Use terrain if it's blank too */ - if (pixel == blank) - { - pixel = XGetPixel(widget->angband.tiles, - x2 + k, y2 + l); - } - - /* Store into the temp storage. */ - XPutPixel(widget->angband.TmpImage, - k, l, pixel); - } - } - - /* Draw to screen */ - - /* Draw object / terrain */ - XPutImage(XtDisplay(widget), XtWindow(widget), - widget->angband.gc[0], - widget->angband.TmpImage, - 0, 0, - x, y, - widget->angband.fontwidth, - widget->angband.fontheight); - } - - x += widget->angband.fontwidth; - } -} - -#endif /* USE_GRAPHICS */ - -/* - * Private procedures - */ - - -/* - * Procedure Initialize() is called during the widget creation - * process. Initialize() load fonts and calculates window geometry. - * The request parameter is filled in by parents to this widget. The - * wnew parameter is the request parameter plus data filled in by this - * widget. All changes should be done to the wnew parameter. - */ -static void Initialize(AngbandWidget request, AngbandWidget wnew) -{ - Display *dpy = XtDisplay(wnew); - - int depth = DefaultDepthOfScreen(XtScreen((Widget) wnew)); - - XGCValues gcv; - TopLevelShellWidget parent = - (TopLevelShellWidget)XtParent((Widget) wnew); - int i; - - /* Default background pixel */ - unsigned long bg = create_pixel(dpy, - angband_color_table[0][1], - angband_color_table[0][2], - angband_color_table[0][3]); - - /* Default foreground pixel */ - unsigned long fg = create_pixel(dpy, - angband_color_table[1][1], - angband_color_table[1][2], - angband_color_table[1][3]); - - /* Fix the background color */ - wnew->core.background_pixel = bg; - - /* Get some information about the font */ - wnew->angband.fnt = getFont(wnew, wnew->angband.font, TRUE); - wnew->angband.fontheight = wnew->angband.fnt->ascent + - wnew->angband.fnt->descent; - wnew->angband.fontwidth = wnew->angband.fnt->max_bounds.width; - wnew->angband.fontascent = wnew->angband.fnt->ascent; - - /* Create and initialize the graphics contexts */ /* GXset? */ - gcv.font = wnew->angband.fnt->fid; - gcv.graphics_exposures = FALSE; - gcv.background = bg; - - for (i = 0; i < NUM_COLORS; i++) - { - unsigned long pixel; - - /* Acquire Angband colors */ - wnew->angband.color[i][0] = angband_color_table[i][0]; - wnew->angband.color[i][1] = angband_color_table[i][1]; - wnew->angband.color[i][2] = angband_color_table[i][2]; - wnew->angband.color[i][3] = angband_color_table[i][3]; - - if (depth > 1) - { - /* Create pixel */ - pixel = create_pixel(dpy, - wnew->angband.color[i][1], - wnew->angband.color[i][2], - wnew->angband.color[i][3]); - } - else - { - /* Use background or foreground */ - pixel = ((i == 0) ? bg : fg); - } - - gcv.foreground = pixel; - - /* Copy */ - gcv.function = 3; - - wnew->angband.gc[i] = XtGetGC((Widget)wnew, - (GCFont | GCForeground | GCFunction | - GCBackground | GCGraphicsExposures), - &gcv); - } - - /* Create a special GC for highlighting */ - gcv.foreground = (BlackPixelOfScreen(XtScreen((Widget)wnew)) ^ - WhitePixelOfScreen(XtScreen((Widget)wnew))); - gcv.background = 0; - - gcv.function = GXxor; - wnew->angband.gc[COLOR_XOR] = XtGetGC((Widget)wnew, - (GCFunction | GCForeground | GCBackground | - GCGraphicsExposures), - &gcv); - - /* Calculate window geometry */ - wnew->core.height = (wnew->angband.start_rows * wnew->angband.fontheight + - 2 * wnew->angband.internal_border); - wnew->core.width = (wnew->angband.start_columns * wnew->angband.fontwidth + - 2 * wnew->angband.internal_border); - - /* We need to be able to resize the Widget if the user wants to */ - /* change font on the fly! */ - parent->shell.allow_shell_resize = TRUE; - - /* Calculates all the size hints */ - calculateSizeHints(wnew); -} - - -/* - * Procedure Destroy() is called during the destruction of the widget. - * Destroy() releases and frees GCs, frees the pixmaps and frees the - * fonts. - */ -static void Destroy(AngbandWidget widget) -{ - int n; - - /* Free all GC's */ - for (n = 0; n < NUM_COLORS + 1; n++) - { - XtReleaseGC((Widget)widget, widget->angband.gc[n]); - } - - /* Free the font */ - XFreeFont(XtDisplay((Widget)widget), widget->angband.fnt); -} - - -static void Resize_term(AngbandWidget wnew) -{ - int cols, rows, wid, hgt; - - int ox = wnew->angband.internal_border; - int oy = wnew->angband.internal_border; - - int i; - term_data *old_td; - term_data *td = &data[0]; - - - /* - * Mega-Hack -- avoid calling this before the terms package is - * initialised - */ - if (!Term) return; - - old_td = (term_data*)(Term->data); - - /* Hack - Find the term to activate */ - for (i = 0; i < num_term; i++) - { - td = &data[i]; - - /* Paranoia: none of the widgets matched */ - if (!td) return; - - /* Have we found it? */ - if (td->widget == wnew) break; - } - - /* Paranoia -- No matches */ - if (i == num_term) return; - - /* Activate the proper Term */ - Term_activate(&td->t); - - /* Determine "proper" number of rows/cols */ - cols = ((wnew->core.width - (ox + ox)) / wnew->angband.fontwidth); - rows = ((wnew->core.height - (oy + oy)) / wnew->angband.fontheight); - - /* Hack -- minimal size */ - if (cols < 1) cols = 1; - if (rows < 1) rows = 1; - - if (i == 0) - { - /* Hack the main window must be at least 80x24 */ - if (cols < 80) cols = 80; - if (rows < 24) rows = 24; - } - - /* Desired size of window */ - wid = cols * wnew->angband.fontwidth + (ox + ox); - hgt = rows * wnew->angband.fontheight + (oy + oy); - - /* Resize the Term (if needed) */ - (void) Term_resize(cols, rows); - - /* Activate the old term */ - Term_activate(&old_td->t); -} - -/* - * Procedure Redisplay() is called as the result of an Expose event. - * Use the redraw callback to do a full redraw - */ -static void Redisplay(AngbandWidget wnew, XEvent *xev, Region region) -{ - int x1, x2, y1, y2; - - int i; - - term_data *old_td = (term_data*)(Term->data); - term_data *td = &data[0]; - - /* Hack - Find the term to activate */ - for (i = 0; i < num_term; i++) - { - td = &data[i]; - - /* Have we found it? */ - if (td->widget == wnew) break; - - /* Paranoia: none of the widgets matched */ - if (!td) return; - } - - /* Activate the proper Term */ - Term_activate(&td->t); - - /* Find the bounds of the exposed region */ - - /* - * This probably could be obtained from the Region parameter - - * but I don't know anything about XAW. - */ - x1 = (xev->xexpose.x - wnew->angband.internal_border) - / wnew->angband.fontwidth; - x2 = (xev->xexpose.x + xev->xexpose.width - - wnew->angband.internal_border) / wnew->angband.fontwidth; - - y1 = (xev->xexpose.y - wnew->angband.internal_border) - / wnew->angband.fontheight; - y2 = (xev->xexpose.y + xev->xexpose.height - - wnew->angband.internal_border) / wnew->angband.fontheight; - - Term_redraw_section(x1, y1, x2, y2); - - /* Activate the old term */ - Term_activate(&old_td->t); - - -#if 0 - if (XtHasCallbacks((Widget)widget, XtNredrawCallback) == XtCallbackHasSome) - { - XtCallCallbacks((Widget)widget, XtNredrawCallback, NULL); - } -#endif /* 0 */ -} - - -/* - * Font and internal_border can be changed on the fly. - * - * The entire widget is redrawn if any of those parameters change (all - * can potentially have effects that spans the whole widget). - * - * Color changes are handled elsewhere. - * - * This function is very underspecified, in terms of how these changes can - * occur, and what is true about the various AngbandWidget's passed in. It - * is very likely that this code no longer works. - */ -static Boolean SetValues(AngbandWidget current, AngbandWidget request, - AngbandWidget wnew, ArgList args, - Cardinal *num_args) -{ - Display *dpy = XtDisplay(wnew); - - Boolean font_changed = FALSE; - Boolean border_changed = FALSE; - int height, width; - int i; - - - /* Handle font change */ - if (wnew->angband.font != current->angband.font) - { - /* Check if the font exists */ - wnew->angband.fnt = getFont(wnew, wnew->angband.font, FALSE); - - /* The font didn't exist */ - if (wnew->angband.fnt == NULL) - { - wnew->angband.fnt = current->angband.fnt; - wnew->angband.font = current->angband.font; - XtWarning("Couldn't find the requested font!"); - } - else - { - font_changed = TRUE; - - /* Free the old font */ - XFreeFont(XtDisplay((Widget)wnew), current->angband.fnt); - /* Update font information */ - wnew->angband.fontheight = wnew->angband.fnt->ascent + - wnew->angband.fnt->descent; - wnew->angband.fontwidth = wnew->angband.fnt->max_bounds.width; - wnew->angband.fontascent = wnew->angband.fnt->ascent; - } - } - - /* Handle font change */ - if (font_changed) - { - /* Update all GC's */ - for (i = 0; i < NUM_COLORS; i++) - { - /* Steal the old GC */ - wnew->angband.gc[i] = current->angband.gc[i]; - current->angband.gc[i] = NULL; - - /* Be sure the correct font is ready */ - XSetFont(dpy, wnew->angband.gc[i], wnew->angband.fnt->fid); - } - - /* Steal the old GC */ - wnew->angband.gc[NUM_COLORS] = current->angband.gc[NUM_COLORS]; - current->angband.gc[NUM_COLORS] = NULL; - } - - - /* Check if internal border width has changed, used later */ - if (current->angband.internal_border != wnew->angband.internal_border) - { - border_changed = TRUE; - } - - - /* If the font or the internal border has changed, all geometry */ - /* has to be recalculated */ - if (font_changed || border_changed) - { - /* Change window size */ - height = ((current->core.height - 2 * current->angband.internal_border) / - current->angband.fontheight * wnew->angband.fontheight + - 2 * current->angband.internal_border); - width = ((current->core.width - 2 * current->angband.internal_border) / - current->angband.fontwidth * wnew->angband.fontwidth + - 2 * wnew->angband.internal_border); - - /* Get the new width */ - if (XtMakeResizeRequest((Widget)wnew, width, height, NULL, NULL) == - XtGeometryNo) - { - /* Not allowed */ - XtWarning("Size change denied!"); - } - else - { - /* Recalculate size hints */ - calculateSizeHints(wnew); - } - } - - /* Tell it to redraw the widget if anything has changed */ - return (font_changed || border_changed); -} - - -/* - * Calculate size hints - */ -static void calculateSizeHints(AngbandWidget wnew) -{ - TopLevelShellWidget parent = - (TopLevelShellWidget)XtParent((Widget) wnew); - - /* Calculate minimum size */ - parent->wm.size_hints.min_height = - (wnew->angband.min_rows * wnew->angband.fontheight + - 2 * wnew->angband.internal_border); - - /* Calculate minimum size */ - parent->wm.size_hints.min_width = - (wnew->angband.min_columns * wnew->angband.fontwidth + - 2 * wnew->angband.internal_border); - - /* Calculate minimum size */ - parent->wm.size_hints.flags |= PMinSize; - - /* Calculate maximum size */ - parent->wm.size_hints.max_height = - (wnew->angband.max_rows * wnew->angband.fontheight + - 2 * wnew->angband.internal_border); - - /* Calculate maximum size */ - parent->wm.size_hints.max_width = - (wnew->angband.max_columns * wnew->angband.fontwidth + - 2 * wnew->angband.internal_border); - - /* Calculate maximum size */ - parent->wm.size_hints.flags |= PMaxSize; - - /* Calculate increment size */ - parent->wm.size_hints.height_inc = wnew->angband.fontheight; - parent->wm.size_hints.width_inc = wnew->angband.fontwidth; - parent->wm.size_hints.flags |= PResizeInc; - - /* Calculate base size */ - parent->wm.base_height = 2 * wnew->angband.internal_border; - parent->wm.base_width = 2 * wnew->angband.internal_border; - parent->wm.size_hints.flags |= PBaseSize; -} - - -/* - * Load a font - */ -static XFontStruct *getFont(AngbandWidget widget, - String font, Boolean fallback) -{ - Display *dpy = XtDisplay((Widget) widget); - char buf[256]; - XFontStruct *fnt = NULL; - - if (!(fnt = XLoadQueryFont(dpy, font)) && fallback) - { - sprintf(buf, "Can't find the font \"%s\", trying fixed\n", font); - XtWarning(buf); - if (!(fnt = XLoadQueryFont(dpy, "fixed"))) - { - XtError("Can't fint the font \"fixed\"!, bailing out\n"); - } - } - - return fnt; -} - - - -/*** The Angband code ****/ - - - - - -/* - * Number of fallback resources per window - */ -#define TERM_FALLBACKS 6 - - - -/* - * The names of the term_data's - */ -char *termNames[MAX_TERM_DATA] = -{ - "angband", - "mirror", - "recall", - "choice", - "term-4", - "term-5", - "term-6", - "term-7" -}; - - -/* - * The special Arg's - */ -Arg specialArgs[TERM_FALLBACKS] = -{ - { XtNstartRows, 24}, - { XtNstartColumns, 80}, - { XtNminRows, 24}, - { XtNminColumns, 80}, - { XtNmaxRows, 255}, - { XtNmaxColumns, 255} -}; - - -/* - * The default Arg's - */ -Arg defaultArgs[TERM_FALLBACKS] = -{ - { XtNstartRows, 24}, - { XtNstartColumns, 80}, - { XtNminRows, 1}, - { XtNminColumns, 1}, - { XtNmaxRows, 255}, - { XtNmaxColumns, 255} -}; - - -/* - * The application context - */ -XtAppContext appcon; - - -/* - * User changable information about widgets - */ -static String fallback[] = -{ - "Angband.angband.iconName: ToME", - "Angband.angband.title: ToME", - "Angband.term-1.iconName: Mirror", - "Angband.term-1.title: Mirror", - "Angband.term-2.iconName: Recall", - "Angband.term-2.title: Recall", - "Angband.term-3.iconName: Choice", - "Angband.term-3.title: Choice", - "Angband.term-4.iconName: Term 4", - "Angband.term-4.title: Term 4", - "Angband.term-5.iconName: Term 5", - "Angband.term-5.title: Term 5", - "Angband.term-6.iconName: Term 6", - "Angband.term-6.title: Term 6", - "Angband.term-7.iconName: Term 7", - "Angband.term-7.title: Term 7", - NULL -}; - - - -/* - * Do a redraw - */ -static void react_redraw(Widget widget, - XtPointer client_data, XtPointer call_data) -{ - term_data *old_td = (term_data*)(Term->data); - term_data *td = (term_data*)client_data; - - /* Activate the proper Term */ - Term_activate(&td->t); - - /* Request a redraw */ - Term_redraw(); - - /* Activate the old Term */ - Term_activate(&old_td->t); -} - - - -/* - * Process a keypress event - * - * Also appears in "main-x11.c". - */ -static void react_keypress(XKeyEvent *xev) -{ - int i, n, mc, ms, mo, mx; - - uint ks1; - - XKeyEvent *ev = (XKeyEvent*)(xev); - - KeySym ks; - - char buf[128]; - char msg[128]; - - - /* Check for "normal" keypresses */ - n = XLookupString(ev, buf, 125, &ks, NULL); - - /* Terminate */ - buf[n] = '\0'; - - - /* Hack -- Ignore "modifier keys" */ - if (IsModifierKey(ks)) return; - - - /* Hack -- convert into an unsigned int */ - ks1 = (uint)(ks); - - /* Extract four "modifier flags" */ - mc = (ev->state & ControlMask) ? TRUE : FALSE; - ms = (ev->state & ShiftMask) ? TRUE : FALSE; - mo = (ev->state & Mod1Mask) ? TRUE : FALSE; - mx = (ev->state & Mod2Mask) ? TRUE : FALSE; - - - /* Normal keys with no modifiers */ - if (n && !mo && !mx && !IsSpecialKey(ks)) - { - /* Enqueue the normal key(s) */ - for (i = 0; buf[i]; i++) Term_keypress(buf[i]); - - /* All done */ - return; - } - - - /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */ - switch (ks1) - { - case XK_Escape: - { - Term_keypress(ESCAPE); - return; - } - - case XK_Return: - { - Term_keypress('\r'); - return; - } - - case XK_Tab: - { - Term_keypress('\t'); - return; - } - - case XK_Delete: - case XK_BackSpace: - { - Term_keypress('\010'); - return; - } - } - - - /* Hack -- Use the KeySym */ - if (ks) - { - sprintf(msg, "%c%s%s%s%s_%lX%c", 31, - mc ? "N" : "", ms ? "S" : "", - mo ? "O" : "", mx ? "M" : "", - (unsigned long)(ks), 13); - } - - /* Hack -- Use the Keycode */ - else - { - sprintf(msg, "%c%s%s%s%sK_%X%c", 31, - mc ? "N" : "", ms ? "S" : "", - mo ? "O" : "", mx ? "M" : "", - ev->keycode, 13); - } - - /* Enqueue the "macro trigger" string */ - for (i = 0; msg[i]; i++) Term_keypress(msg[i]); - - - /* Hack -- auto-define macros as needed */ - if (n && (macro_find_exact(msg) < 0)) - { - /* Create a macro */ - macro_add(msg, buf); - } -} - - -/* - * Handle an event - */ -static void handle_event(Widget widget, XtPointer client_data, XEvent *event, - Boolean *continue_to_dispatch) -{ - term_data *old_td = (term_data*)(Term->data); - term_data *td = (term_data *)client_data; - - /* Continue to process the event by default */ - *continue_to_dispatch = TRUE; - - /* Activate the Term */ - Term_activate(&td->t); - - switch (event->type) - { - case KeyPress: - { - /* Hack -- use old term */ - Term_activate(&old_td->t); - - /* Handle the keypress */ - react_keypress(&(event->xkey)); - - /* We took care of the event */ - *continue_to_dispatch = FALSE; - - break; - } - - /* Oops */ - default: - { - break; - } - } - - /* Activate the old term */ - Term_activate(&old_td->t); - - return; -} - - -/* - * Process an event (or just check for one) - */ -errr CheckEvent(bool_ wait) -{ - XEvent event; - - /* No events ready, and told to just check */ - if (!wait && !XtAppPending(appcon)) return 1; - - /* Process */ - while (1) - { - XtAppNextEvent(appcon, &event); - XtDispatchEvent(&event); - if (!XtAppPending(appcon)) break; - } - - return (0); -} - - -/* - * Monstrous hack. - */ -static void Term_xtra_xaw_react_aux(term_data *td) -{ - AngbandWidget wnew = td->widget; - - Display *dpy = XtDisplay((Widget) wnew); - - int depth = DefaultDepthOfScreen(XtScreen((Widget) wnew)); - - int i; - - /* See if any colors need to be changed */ - for (i = 0; i < NUM_COLORS; i++) - { - if (depth > 1) - { - if ((wnew->angband.color[i][0] != angband_color_table[i][0]) || - (wnew->angband.color[i][1] != angband_color_table[i][1]) || - (wnew->angband.color[i][2] != angband_color_table[i][2]) || - (wnew->angband.color[i][3] != angband_color_table[i][3])) - { - unsigned long pixel; - - /* Save new values */ - wnew->angband.color[i][0] = angband_color_table[i][0]; - wnew->angband.color[i][1] = angband_color_table[i][1]; - wnew->angband.color[i][2] = angband_color_table[i][2]; - wnew->angband.color[i][3] = angband_color_table[i][3]; - - /* Create pixel */ - pixel = create_pixel(dpy, - wnew->angband.color[i][1], - wnew->angband.color[i][2], - wnew->angband.color[i][3]); - - - /* Change */ - XSetForeground(dpy, wnew->angband.gc[i], pixel); - } - } - } -} - - -/* - * Monstrous hack. - */ -static errr Term_xtra_xaw_react(void) -{ - int i; - - /* Initialize the windows */ - for (i = 0; i < num_term; i++) - { - term_data *td = &data[i]; - - if (!td) break; - - Term_xtra_xaw_react_aux(td); - } - - return (0); -} - - -/* - * Handle a "special request" - */ -static errr Term_xtra_xaw(int n, int v) -{ - term_data *td = (term_data*)(Term->data); - - Widget widget = (Widget)(td->widget); - - Display *dpy = XtDisplay(widget); - - /* Handle a subset of the legal requests */ - switch (n) - { - /* Make a noise */ - case TERM_XTRA_NOISE: - XBell(dpy, 100); - return (0); - - /* Flush the output */ - case TERM_XTRA_FRESH: - XFlush(dpy); - /* Allow flushed events to be showed */ - CheckEvent(FALSE); - return (0); - - /* Process random events */ - case TERM_XTRA_BORED: - return (CheckEvent(0)); - - /* Process events */ - case TERM_XTRA_EVENT: - return (CheckEvent(v)); - - /* Flush events */ - case TERM_XTRA_FLUSH: - while (!CheckEvent(FALSE)); - return (0); - - /* Clear the window */ - case TERM_XTRA_CLEAR: - XClearWindow(dpy, XtWindow(widget)); - return (0); - - /* Delay */ - case TERM_XTRA_DELAY: - usleep(1000 * v); - 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)) - { - 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) && S_ISDIR((filedata.st_mode))) - { - string_free(scansubdir_result[scansubdir_max]); - scansubdir_result[scansubdir_max] = string_make(entry->d_name); - ++scansubdir_max; - } - } - } - - case TERM_XTRA_REACT: - return (Term_xtra_xaw_react()); - } - - /* Unknown */ - return (1); -} - - - -/* - * Erase a number of characters - */ -static errr Term_wipe_xaw(int x, int y, int n) -{ - term_data *td = (term_data*)(Term->data); - - /* Erase using color 0 */ - AngbandClearArea(td->widget, x, y, n, 1, 0); - - /* Success */ - return (0); -} - - - -/* - * Draw the cursor, by hiliting with XOR - * - * Should perhaps use rectangle outline, ala "main-mac.c". XXX XXX XXX - */ -static errr Term_curs_xaw(int x, int y) -{ - term_data *td = (term_data*)(Term->data); - - /* Hilite the cursor character */ - AngbandClearArea(td->widget, x, y, 1, 1, COLOR_XOR); - - /* Success */ - return (0); -} - - -/* - * Draw a number of characters - */ -static errr Term_text_xaw(int x, int y, int n, byte a, cptr s) -{ - term_data *td = (term_data*)(Term->data); - - /* Draw the text */ - AngbandOutputText(td->widget, x, y, (String)s, n, a); - - /* Success */ - return (0); -} - - -#ifdef USE_GRAPHICS - -/* - * Draw some graphical characters. - */ -static errr Term_pict_xaw(int x, int y, int n, const byte *ap, const char *cp, - const byte *tap, const char *tcp, const byte *eap, const char *ecp) -{ - term_data *td = (term_data*)(Term->data); - - /* Draw the pictures */ - AngbandOutputPict(td->widget, x, y, n, ap, cp, tap, tcp, eap, ecp); - - /* Success */ - return (0); -} - -#endif /* USE_GRAPHICS */ - - -/* - * Raise a term - */ -static void term_raise(term_data *td) -{ - Widget widget = (Widget)(td->widget); - - XRaiseWindow(XtDisplay(XtParent(widget)), XtWindow(XtParent(widget))); -} - - -/* - * Initialize a term_data - */ -static errr term_data_init(term_data *td, Widget topLevel, - int key_buf, String name, - ArgList widget_arg, Cardinal widget_arg_no, int i) -{ - Widget parent; - term *t = &td->t; - - int cols = 80; - int rows = 24; - - char buf[80]; - cptr str; - - int val; - - /* Create the shell widget */ - parent = XtCreatePopupShell(name, topLevelShellWidgetClass, topLevel, - NULL, 0); - - /* Window specific cols */ - sprintf(buf, "ANGBAND_X11_COLS_%d", i); - str = getenv(buf); - val = (str != NULL) ? atoi(str) : -1; - if (val > 0) cols = val; - - /* Window specific rows */ - sprintf(buf, "ANGBAND_X11_ROWS_%d", i); - str = getenv(buf); - val = (str != NULL) ? atoi(str) : -1; - if (val > 0) rows = val; - - /* Hack the main window must be at least 80x24 */ - if (i == 0) - { - if (cols < 80) cols = 80; - if (rows < 24) rows = 24; - } - - /* Reset the initial size */ - widget_arg[0].value = rows; - widget_arg[1].value = cols; - - /* Create the interior widget */ - td->widget = (AngbandWidget) - XtCreateManagedWidget(name, angbandWidgetClass, - parent, widget_arg, widget_arg_no); - - /* Initialize the term (full size) */ - term_init(t, cols, rows, key_buf); - - /* Use a "soft" cursor */ - t->soft_cursor = TRUE; - - /* Erase with "white space" */ - t->attr_blank = TERM_WHITE; - t->char_blank = ' '; - - /* Hooks */ - t->xtra_hook = Term_xtra_xaw; - t->curs_hook = Term_curs_xaw; - t->wipe_hook = Term_wipe_xaw; - t->text_hook = Term_text_xaw; - - /* Save the data */ - t->data = td; - - /* Register the keypress event handler */ - XtAddEventHandler((Widget)td->widget, KeyPressMask, - False, (XtEventHandler) handle_event, td); - - /* Redraw callback */ - XtAddCallback((Widget)td->widget, XtNredrawCallback, - react_redraw, td); - - /* Realize the widget */ - XtRealizeWidget(parent); - - /* Make it visible */ - XtPopup(parent, XtGrabNone); - - /* Activate (important) */ - Term_activate(t); - - Resize_term(td->widget); - - return 0; -} - - -/* - * Initialization function for an X Athena Widget module to Angband - * - * We should accept "-d<dpy>" requests in the "argv" array. XXX XXX XXX - */ -errr init_xaw(int argc, char *argv[]) -{ - int i; - Widget topLevel; - Display *dpy; - - cptr dpy_name = ""; - - -#ifdef USE_GRAPHICS - - char filename[1024]; - - int pict_wid = 0; - int pict_hgt = 0; - bool_ force_old_graphics = FALSE; - - char *TmpData; - -#endif /* USE_GRAPHICS */ - - /* Parse args */ - for (i = 1; i < argc; i++) - { - if (prefix(argv[i], "-d")) - { - dpy_name = &argv[i][2]; - continue; - } - -#ifdef USE_GRAPHICS - - if (prefix(argv[i], "-s")) - { - smoothRescaling = FALSE; - continue; - } - - if (prefix(argv[i], "-o")) - { - force_old_graphics = TRUE; - continue; - } - -#endif /* USE_GRAPHICS */ - - 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; - } - - plog_fmt("Ignoring option: %s", argv[i]); - } - - - /* Attempt to open the local display */ - dpy = XOpenDisplay(dpy_name); - - /* Failure -- assume no X11 available */ - if (!dpy) return ( -1); - - /* Close the local display */ - XCloseDisplay(dpy); - - -#ifdef USE_XAW_LANG - - /* Support locale processing */ - XtSetLanguageProc(NULL, NULL, NULL); - -#endif /* USE_XAW_LANG */ - - - /* Initialize the toolkit */ - topLevel = XtAppInitialize(&appcon, "Angband", NULL, 0, &argc, argv, - fallback, NULL, 0); - - XSetIOErrorHandler(x_io_error_handler); - - /* Initialize the windows */ - for (i = 0; i < num_term; i++) - { - term_data *td = &data[i]; - - term_data_init(td, topLevel, 1024, termNames[i], - (i == 0) ? specialArgs : defaultArgs, - TERM_FALLBACKS, i); - - angband_term[i] = Term; - } - - /* Activate the "Angband" window screen */ - Term_activate(&data[0].t); - - /* Raise the "Angband" window */ - term_raise(&data[0]); - - -#ifdef USE_GRAPHICS - - /* Try graphics */ - if (arg_graphics) - { - /* Try the "16x16.bmp" file */ - path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/16x16.bmp"); - - /* Use the "16x16.bmp" file if it exists */ - if (!force_old_graphics && - (0 == fd_close(fd_open(filename, O_RDONLY)))) - { - /* Use graphics */ - use_graphics = TRUE; - - pict_wid = pict_hgt = 16; - - ANGBAND_GRAF = "new"; - } - else - { - /* Try the "8x8.bmp" file */ - path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/8x8.bmp"); - - /* Use the "8x8.bmp" file if it exists */ - if (0 == fd_close(fd_open(filename, O_RDONLY))) - { - /* Use graphics */ - use_graphics = TRUE; - - pict_wid = pict_hgt = 8; - - ANGBAND_GRAF = "old"; - } - } - } - - /* Load graphics */ - if (use_graphics) - { - /* Hack -- Get the Display */ - term_data *td = &data[0]; - Widget widget = (Widget)(td->widget); - Display *dpy = XtDisplay(widget); - - XImage *tiles_raw; - - /* Load the graphical tiles */ - tiles_raw = ReadBMP(dpy, filename); - - /* Initialize the windows */ - for (i = 0; i < num_term; i++) - { - term_data *td = &data[i]; - - term *t = &td->t; - - t->pict_hook = Term_pict_xaw; - - t->higher_pict = TRUE; - - /* Resize tiles */ - td->widget->angband.tiles = - ResizeImage(dpy, tiles_raw, - pict_wid, pict_hgt, - td->widget->angband.fontwidth, - td->widget->angband.fontheight); - } - - /* Initialize the transparency temp storage*/ - for (i = 0; i < num_term; i++) - { - term_data *td = &data[i]; - int ii, jj; - int depth = DefaultDepth(dpy, DefaultScreen(dpy)); - Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy)); - int total; - - - /* Determine total bytes needed for image */ - ii = 1; - jj = (depth - 1) >> 2; - while (jj >>= 1) ii <<= 1; - total = td->widget->angband.fontwidth * - td->widget->angband.fontheight * ii; - - - TmpData = (char *)malloc(total); - - td->widget->angband.TmpImage = XCreateImage(dpy, - visual, depth, - ZPixmap, 0, TmpData, - td->widget->angband.fontwidth, - td->widget->angband.fontheight, 8, 0); - - } - - - /* Free tiles_raw? XXX XXX */ - } - -#endif /* USE_GRAPHICS */ - - /* Success */ - return (0); -} - -#endif /* USE_XAW */ - |