4 * Copyright (c) 1997 Ben Harrison, and others
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies.
14 * ÆüËܸì(EUC-JAPAN)Âбþ (-DJP)
15 * ¡¦´Á»ú¥Õ¥©¥ó¥È¤Î°·¤¤¤òÄɲÃ
16 * ¡¦ÆüËܸì¤ò´Þ¤àʸ»úÎó¤Îɽ¼¨¥ë¡¼¥Á¥ó XDrawMultiString() ¤ÎÄɲÃ
17 * ¡¦ÆüËܸì¤Îɽ¼¨Éý¤Ï¡¤¥Õ¥©¥ó¥È¤Î¾ðÊó¤Ë¤è¤é¤¹ASCII¥Õ¥©¥ó¥È¤Î2Çܤ˸ÇÄê
22 * 1996/6/7 Íû ¹¸¿ (ri@kuis.kyoto-u.ac.jp)
26 * This file helps Angband work with UNIX/X11 computers.
28 * To use this file, compile with "USE_X11" defined, and link against all
29 * the various "X11" libraries which may be needed.
31 * See also "main-xaw.c".
33 * Part of this file provides a user interface package composed of several
34 * pseudo-objects, including "metadpy" (a display), "infowin" (a window),
35 * "infoclr" (a color), and "infofnt" (a font). Actually, the package was
36 * originally much more interesting, but it was bastardized to keep this
39 * The rest of this file is an implementation of "main-xxx.c" for X11.
41 * Most of this file is by Ben Harrison (benh@phial.com).
45 * The following shell script can be used to launch Angband, assuming that
46 * it was extracted into "~/Angband", and compiled using "USE_X11", on a
47 * Linux machine, with a 1280x1024 screen, using 6 windows (with the given
48 * characteristics), with gamma correction of 1.8 -> (1 / 1.8) * 256 = 142,
49 * and without graphics (add "-g" for graphics). Just copy this comment
50 * into a file, remove the leading " * " characters (and the head/tail of
51 * this comment), and make the file executable.
57 * echo "Launching angband..."
61 * setenv ANGBAND_X11_FONT_0 10x20
62 * setenv ANGBAND_X11_AT_X_0 5
63 * setenv ANGBAND_X11_AT_Y_0 510
66 * setenv ANGBAND_X11_FONT_1 8x13
67 * setenv ANGBAND_X11_AT_X_1 5
68 * setenv ANGBAND_X11_AT_Y_1 22
69 * setenv ANGBAND_X11_ROWS_1 35
72 * setenv ANGBAND_X11_FONT_2 8x13
73 * setenv ANGBAND_X11_AT_X_2 635
74 * setenv ANGBAND_X11_AT_Y_2 182
75 * setenv ANGBAND_X11_ROWS_3 23
78 * setenv ANGBAND_X11_FONT_3 8x13
79 * setenv ANGBAND_X11_AT_X_3 635
80 * setenv ANGBAND_X11_AT_Y_3 22
81 * setenv ANGBAND_X11_ROWS_3 12
83 * # Monster recall window
84 * setenv ANGBAND_X11_FONT_4 6x13
85 * setenv ANGBAND_X11_AT_X_4 817
86 * setenv ANGBAND_X11_AT_Y_4 847
87 * setenv ANGBAND_X11_COLS_4 76
88 * setenv ANGBAND_X11_ROWS_4 11
90 * # Object recall window
91 * setenv ANGBAND_X11_FONT_5 6x13
92 * setenv ANGBAND_X11_AT_X_5 817
93 * setenv ANGBAND_X11_AT_Y_5 520
94 * setenv ANGBAND_X11_COLS_5 76
95 * setenv ANGBAND_X11_ROWS_5 24
97 * # The build directory
101 * setenv ANGBAND_X11_GAMMA 142
104 * ./src/angband -mx11 -- -n6 &
115 #ifndef __MAKEDEPEND__
116 #include <X11/Xlib.h>
117 #include <X11/Xutil.h>
118 #include <X11/keysym.h>
119 #include <X11/keysymdef.h>
121 #include <X11/Xlocale.h>
124 char *XSetIMValues(XIM, ...); /* Hack for XFree86 4.0 */
126 #endif /* __MAKEDEPEND__ */
130 * Include some helpful X11 code.
132 #include "maid-x11.c"
136 * Hack -- avoid some compiler warnings
138 #define IGNORE_UNUSED_FUNCTIONS
144 * 1) On a monochrome (or "fake-monochrome") display, all colors
145 * will be "cast" to "fg," except for the bg color, which is,
146 * obviously, cast to "bg". Thus, one can ignore this setting.
148 * 2) Because of the inner functioning of the color allocation
149 * routines, colors may be specified as (a) a typical color name,
150 * (b) a hexidecimal color specification (preceded by a pound sign),
151 * or (c) by strings such as "fg", "bg", "zg".
153 * 3) Due to the workings of the init routines, many colors
154 * may also be dealt with by their actual pixel values. Note that
155 * the pixel with all bits set is "zg = (1<<metadpy->depth)-1", which
156 * is not necessarily either black or white.
161 /**** Generic Types ****/
165 * An X11 pixell specifier
167 typedef unsigned long Pixell;
170 * The structures defined below
172 typedef struct metadpy metadpy;
173 typedef struct infowin infowin;
174 typedef struct infoclr infoclr;
175 typedef struct infofnt infofnt;
179 * A structure summarizing a given Display.
181 * - The Display itself
182 * - The default Screen for the display
183 * - The virtual root (usually just the root)
184 * - The default colormap (from a macro)
186 * - The "name" of the display
188 * - The socket to listen to for events
190 * - The width of the display screen (from a macro)
191 * - The height of the display screen (from a macro)
192 * - The bit depth of the display screen (from a macro)
194 * - The black Pixell (from a macro)
195 * - The white Pixell (from a macro)
197 * - The background Pixell (default: black)
198 * - The foreground Pixell (default: white)
199 * - The maximal Pixell (Equals: ((2 ^ depth)-1), is usually ugly)
201 * - Bit Flag: Force all colors to black and white (default: !color)
202 * - Bit Flag: Allow the use of color (default: depth > 1)
203 * - Bit Flag: We created 'dpy', and so should nuke it when done.
238 * A Structure summarizing Window Information.
240 * I assume that a window is at most 30000 pixels on a side.
241 * I assume that the root windw is also at most 30000 square.
244 * - The current Input Event Mask
246 * - The location of the window
247 * - The width, height of the window
248 * - The border width of this window
250 * - Byte: 1st Extra byte
252 * - Bit Flag: This window is currently Mapped
253 * - Bit Flag: This window needs to be redrawn
254 * - Bit Flag: This window has been resized
256 * - Bit Flag: We should nuke 'win' when done with it
258 * - Bit Flag: 1st extra flag
259 * - Bit Flag: 2nd extra flag
260 * - Bit Flag: 3rd extra flag
261 * - Bit Flag: 4th extra flag
299 * A Structure summarizing Operation+Color Information
301 * - The actual GC corresponding to this info
303 * - The Foreground Pixell Value
304 * - The Background Pixell Value
306 * - Num (0-15): The operation code (As in Clear, Xor, etc)
307 * - Bit Flag: The GC is in stipple mode
308 * - Bit Flag: Destroy 'gc' at Nuke time.
325 * A Structure to Hold Font Information
327 * - The 'XFontStruct*' (yields the 'Font')
331 * - The default character width
332 * - The default character height
333 * - The default character ascent
335 * - Byte: Pixel offset used during fake mono
337 * - Flag: Force monospacing via 'wid'
338 * - Flag: Nuke info when done
364 /**** Generic Macros ****/
368 /* Set current metadpy (Metadpy) to 'M' */
369 #define Metadpy_set(M) \
373 /* Initialize 'M' using Display 'D' */
374 #define Metadpy_init_dpy(D) \
375 Metadpy_init_2(D,cNULL)
377 /* Initialize 'M' using a Display named 'N' */
378 #define Metadpy_init_name(N) \
379 Metadpy_init_2((Display*)(NULL),N)
381 /* Initialize 'M' using the standard Display */
382 #define Metadpy_init() \
383 Metadpy_init_name("")
386 /* Init an infowin by giving father as an (info_win*) (or NULL), and data */
387 #define Infowin_init_dad(D,X,Y,W,H,B,FG,BG) \
388 Infowin_init_data(((D) ? ((D)->win) : (Window)(None)), \
392 /* Init a top level infowin by pos,size,bord,Colors */
393 #define Infowin_init_top(X,Y,W,H,B,FG,BG) \
394 Infowin_init_data(None,X,Y,W,H,B,FG,BG)
397 /* Request a new standard window by giving Dad infowin and X,Y,W,H */
398 #define Infowin_init_std(D,X,Y,W,H,B) \
399 Infowin_init_dad(D,X,Y,W,H,B,Metadpy->fg,Metadpy->bg)
402 /* Set the current Infowin */
403 #define Infowin_set(I) \
407 /* Set the current Infoclr */
408 #define Infoclr_set(C) \
412 #define Infoclr_init_ppo(F,B,O,M) \
413 Infoclr_init_data(F,B,O,M)
415 #define Infoclr_init_cco(F,B,O,M) \
416 Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M)
418 #define Infoclr_init_ppn(F,B,O,M) \
419 Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M)
421 #define Infoclr_init_ccn(F,B,O,M) \
422 Infoclr_init_cco(F,B,Infoclr_Opcode(O),M)
425 /* Set the current infofnt */
426 #define Infofnt_set(I) \
430 /* Errr: Expose Infowin */
431 #define Infowin_expose() \
432 (!(Infowin->redraw = 1))
434 /* Errr: Unxpose Infowin */
435 #define Infowin_unexpose() \
436 (Infowin->redraw = 0)
440 /**** Generic Globals ****/
444 * The "default" values
446 static metadpy metadpy_default;
450 * The "current" variables
452 static metadpy *Metadpy = &metadpy_default;
453 static infowin *Infowin = (infowin*)(NULL);
455 static infowin *Focuswin = (infowin*)(NULL);
457 static infoclr *Infoclr = (infoclr*)(NULL);
459 static infofnt *Infofnt = (infofnt*)(NULL);
460 static infofnt *Infokfnt = (infofnt*)(NULL);
462 static infofnt *Infofnt = (infofnt*)(NULL);
468 /**** Generic code ****/
472 #define Infokfnt_set(I) \
476 * Init the current metadpy, with various initialization stuff.
479 * dpy: The Display* to use (if NULL, create it)
480 * name: The name of the Display (if NULL, the current)
483 * If 'name' is NULL, but 'dpy' is set, extract name from dpy
484 * If 'dpy' is NULL, then Create the named Display
485 * If 'name' is NULL, and so is 'dpy', use current Display
487 * Return -1 if no Display given, and none can be opened.
489 static errr Metadpy_init_2(Display *dpy, cptr name)
491 metadpy *m = Metadpy;
493 /*** Open the display if needed ***/
495 /* If no Display given, attempt to Create one */
498 /* Attempt to open the display */
499 dpy = XOpenDisplay(name);
502 if (!dpy) return (-1);
504 /* We will have to nuke it when done */
508 /* Since the Display was given, use it */
511 /* We will not have to nuke it when done */
516 /*** Save some information ***/
518 /* Save the Display itself */
521 /* Get the Screen and Virtual Root Window */
522 m->screen = DefaultScreenOfDisplay(dpy);
523 m->root = RootWindowOfScreen(m->screen);
525 /* Get the default colormap */
526 m->cmap = DefaultColormapOfScreen(m->screen);
528 /* Extract the true name of the display */
529 m->name = DisplayString(dpy);
532 m->fd = ConnectionNumber(Metadpy->dpy);
534 /* Save the Size and Depth of the screen */
535 m->width = WidthOfScreen(m->screen);
536 m->height = HeightOfScreen(m->screen);
537 m->depth = DefaultDepthOfScreen(m->screen);
539 /* Save the Standard Colors */
540 m->black = BlackPixelOfScreen(m->screen);
541 m->white = WhitePixelOfScreen(m->screen);
543 /*** Make some clever Guesses ***/
545 /* Guess at the desired 'fg' and 'bg' Pixell's */
549 /* Calculate the Maximum allowed Pixel value. */
550 m->zg = (1 << m->depth) - 1;
552 /* Save various default Flag Settings */
553 m->color = ((m->depth > 1) ? 1 : 0);
554 m->mono = ((m->color) ? 0 : 1);
556 /* Return "success" */
561 #ifndef IGNORE_UNUSED_FUNCTIONS
564 * Nuke the current metadpy
566 static errr Metadpy_nuke(void)
568 metadpy *m = Metadpy;
571 /* If required, Free the Display */
574 /* Close the Display */
575 XCloseDisplay(m->dpy);
577 /* Forget the Display */
578 m->dpy = (Display*)(NULL);
580 /* Do not nuke it again */
588 #endif /* IGNORE_UNUSED_FUNCTIONS */
592 * General Flush/ Sync/ Discard routine
594 static errr Metadpy_update(int flush, int sync, int discard)
596 /* Flush if desired */
597 if (flush) XFlush(Metadpy->dpy);
599 /* Sync if desired, using 'discard' */
600 if (sync) XSync(Metadpy->dpy, discard);
610 static errr Metadpy_do_beep(void)
612 /* Make a simple beep */
613 XBell(Metadpy->dpy, 100);
621 * Set the name (in the title bar) of Infowin
623 static errr Infowin_set_name(cptr name)
630 st = XStringListToTextProperty(&bp, 1, &tp);
631 if (st) XSetWMName(Metadpy->dpy, Infowin->win, &tp);
636 #ifndef IGNORE_UNUSED_FUNCTIONS
639 * Set the icon name of Infowin
641 static errr Infowin_set_icon_name(cptr name)
648 st = XStringListToTextProperty(&bp, 1, &tp);
649 if (st) XSetWMIconName(Metadpy->dpy, Infowin->win, &tp);
657 static errr Infowin_nuke(void)
659 infowin *iwin = Infowin;
661 /* Nuke if requested */
664 /* Destory the old window */
665 XDestroyWindow(Metadpy->dpy, iwin->win);
672 #endif /* IGNORE_UNUSED_FUNCTIONS */
676 * Prepare a new 'infowin'.
678 static errr Infowin_prepare(Window xid)
680 infowin *iwin = Infowin;
683 XWindowAttributes xwa;
685 unsigned int w, h, b, d;
690 /* Check For Error XXX Extract some ACTUAL data from 'xid' */
691 XGetGeometry(Metadpy->dpy, xid, &tmp_win, &x, &y, &w, &h, &b, &d);
693 /* Apply the above info */
700 /* Check Error XXX Extract some more ACTUAL data */
701 XGetWindowAttributes(Metadpy->dpy, xid, &xwa);
703 /* Apply the above info */
704 iwin->mask = xwa.your_event_mask;
705 iwin->mapped = ((xwa.map_state == IsUnmapped) ? 0 : 1);
707 /* And assume that we are exposed */
715 #ifndef IGNORE_UNUSED_FUNCTIONS
718 * Initialize a new 'infowin'.
720 static errr Infowin_init_real(Window xid)
723 (void)WIPE(Infowin, infowin);
725 /* Start out non-nukable */
728 /* Attempt to Prepare ourself */
729 return (Infowin_prepare(xid));
732 #endif /* IGNORE_UNUSED_FUNCTIONS */
736 * Init an infowin by giving some data.
739 * dad: The Window that should own this Window (if any)
740 * x,y: The position of this Window
741 * w,h: The size of this Window
742 * b,d: The border width and pixel depth
745 * If 'dad == None' assume 'dad == root'
747 static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
748 int b, Pixell fg, Pixell bg)
753 (void)WIPE(Infowin, infowin);
756 /*** Error Check XXX ***/
759 /*** Create the Window 'xid' from data ***/
761 /* What happened here? XXX XXX XXX */
763 /* If no parent given, depend on root */
766 /* #ifdef USE_GRAPHICS
768 xid = XCreateWindow(Metadpy->dpy, Metadpy->root, x, y, w, h, b, 8, InputOutput, CopyFromParent, 0, 0);
779 /* Create the Window XXX Error Check */
780 xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg, bg);
782 /* Start out selecting No events */
783 XSelectInput(Metadpy->dpy, xid, 0L);
786 /*** Prepare the new infowin ***/
788 /* Mark it as nukable */
791 /* Attempt to Initialize the infowin */
792 return (Infowin_prepare(xid));
798 * Modify the event mask of an Infowin
800 static errr Infowin_set_mask(long mask)
802 /* Save the new setting */
803 Infowin->mask = mask;
805 /* Execute the Mapping */
806 XSelectInput(Metadpy->dpy, Infowin->win, Infowin->mask);
814 * Request that Infowin be mapped
816 static errr Infowin_map(void)
818 /* Execute the Mapping */
819 XMapWindow(Metadpy->dpy, Infowin->win);
826 #ifndef IGNORE_UNUSED_FUNCTIONS
829 * Request that Infowin be unmapped
831 static errr Infowin_unmap(void)
833 /* Execute the Un-Mapping */
834 XUnmapWindow(Metadpy->dpy, Infowin->win);
840 #endif /* IGNORE_UNUSED_FUNCTIONS */
844 * Request that Infowin be raised
846 static errr Infowin_raise(void)
848 /* Raise towards visibility */
849 XRaiseWindow(Metadpy->dpy, Infowin->win);
856 #ifndef IGNORE_UNUSED_FUNCTIONS
859 * Request that Infowin be lowered
861 static errr Infowin_lower(void)
863 /* Lower towards invisibility */
864 XLowerWindow(Metadpy->dpy, Infowin->win);
870 #endif /* IGNORE_UNUSED_FUNCTIONS */
874 * Request that Infowin be moved to a new location
876 static errr Infowin_impell(int x, int y)
878 /* Execute the request */
879 XMoveWindow(Metadpy->dpy, Infowin->win, x, y);
889 static errr Infowin_resize(int w, int h)
891 /* Execute the request */
892 XResizeWindow(Metadpy->dpy, Infowin->win, w, h);
899 #ifndef IGNORE_UNUSED_FUNCTIONS
902 * Move and Resize an infowin
904 static errr Infowin_locate(int x, int y, int w, int h)
906 /* Execute the request */
907 XMoveResizeWindow(Metadpy->dpy, Infowin->win, x, y, w, h);
913 #endif /* IGNORE_UNUSED_FUNCTIONS */
917 * Visually clear Infowin
919 static errr Infowin_wipe(void)
921 /* Execute the request */
922 XClearWindow(Metadpy->dpy, Infowin->win);
929 #ifndef IGNORE_UNUSED_FUNCTIONS
932 * Visually Paint Infowin with the current color
934 static errr Infowin_fill(void)
936 /* Execute the request */
937 XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc,
938 0, 0, Infowin->w, Infowin->h);
944 #endif /* IGNORE_UNUSED_FUNCTIONS */
948 * A NULL terminated pair list of legal "operation names"
950 * Pairs of values, first is texttual name, second is the string
951 * holding the decimal value that the operation corresponds to.
953 static cptr opcode_pairs[] =
972 "+copyInverted", "12",
980 * Parse a word into an operation "code"
983 * str: A string, hopefully representing an Operation
986 * 0-15: if 'str' is a valid Operation
987 * -1: if 'str' could not be parsed
989 static int Infoclr_Opcode(cptr str)
993 /* Scan through all legal operation names */
994 for (i = 0; opcode_pairs[i*2]; ++i)
996 /* Is this the right oprname? */
997 if (streq(opcode_pairs[i*2], str))
999 /* Convert the second element in the pair into a Code */
1000 return (atoi(opcode_pairs[i*2+1]));
1004 /* The code was not found, return -1 */
1009 #ifndef IGNORE_UNUSED_FUNCTIONS
1012 * Request a Pixell by name. Note: uses 'Metadpy'.
1015 * name: The name of the color to try to load (see below)
1018 * The Pixell value that metched the given name
1019 * 'Metadpy->fg' if the name was unparseable
1021 * Valid forms for 'name':
1022 * 'fg', 'bg', 'zg', '<name>' and '#<code>'
1024 static Pixell Infoclr_Pixell(cptr name)
1028 /* Attempt to Parse the name */
1029 if (name && name[0])
1031 /* The 'bg' color is available */
1032 if (streq(name, "bg")) return (Metadpy->bg);
1034 /* The 'fg' color is available */
1035 if (streq(name, "fg")) return (Metadpy->fg);
1037 /* The 'zg' color is available */
1038 if (streq(name, "zg")) return (Metadpy->zg);
1040 /* The 'white' color is available */
1041 if (streq(name, "white")) return (Metadpy->white);
1043 /* The 'black' color is available */
1044 if (streq(name, "black")) return (Metadpy->black);
1046 /* Attempt to parse 'name' into 'scrn' */
1047 if (!(XParseColor(Metadpy->dpy, Metadpy->cmap, name, &scrn)))
1049 plog_fmt("Warning: Couldn't parse color '%s'\n", name);
1052 /* Attempt to Allocate the Parsed color */
1053 if (!(XAllocColor(Metadpy->dpy, Metadpy->cmap, &scrn)))
1055 plog_fmt("Warning: Couldn't allocate color '%s'\n", name);
1058 /* The Pixel was Allocated correctly */
1059 else return (scrn.pixel);
1062 /* Warn about the Default being Used */
1063 plog_fmt("Warning: Using 'fg' for unknown color '%s'\n", name);
1065 /* Default to the 'Foreground' color */
1066 return (Metadpy->fg);
1071 * Initialize a new 'infoclr' with a real GC.
1073 static errr Infoclr_init_1(GC gc)
1075 infoclr *iclr = Infoclr;
1077 /* Wipe the iclr clean */
1078 (void)WIPE(iclr, infoclr);
1089 * Nuke an old 'infoclr'.
1091 static errr Infoclr_nuke(void)
1093 infoclr *iclr = Infoclr;
1095 /* Deal with 'GC' */
1099 XFreeGC(Metadpy->dpy, iclr->gc);
1102 /* Forget the current */
1103 Infoclr = (infoclr*)(NULL);
1109 #endif /* IGNORE_UNUSED_FUNCTIONS */
1113 * Initialize an infoclr with some data
1116 * fg: The Pixell for the requested Foreground (see above)
1117 * bg: The Pixell for the requested Background (see above)
1118 * op: The Opcode for the requested Operation (see above)
1119 * stip: The stipple mode
1121 static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
1123 infoclr *iclr = Infoclr;
1127 unsigned long gc_mask;
1131 /*** Simple error checking of opr and clr ***/
1133 /* Check the 'Pixells' for realism */
1134 if (bg > Metadpy->zg) return (-1);
1135 if (fg > Metadpy->zg) return (-1);
1137 /* Check the data for trueness */
1138 if ((op < 0) || (op > 15)) return (-1);
1141 /*** Create the requested 'GC' ***/
1143 /* Assign the proper GC function */
1146 /* Assign the proper GC background */
1147 gcv.background = bg;
1149 /* Assign the proper GC foreground */
1150 gcv.foreground = fg;
1152 /* Hack -- Handle XOR (xor is code 6) by hacking bg and fg */
1153 if (op == 6) gcv.background = 0;
1154 if (op == 6) gcv.foreground = (bg ^ fg);
1156 /* Assign the proper GC Fill Style */
1157 gcv.fill_style = (stip ? FillStippled : FillSolid);
1159 /* Turn off 'Give exposure events for pixmap copying' */
1160 gcv.graphics_exposures = False;
1162 /* Set up the GC mask */
1163 gc_mask = (GCFunction | GCBackground | GCForeground |
1164 GCFillStyle | GCGraphicsExposures);
1166 /* Create the GC detailed above */
1167 gc = XCreateGC(Metadpy->dpy, Metadpy->root, gc_mask, &gcv);
1170 /*** Initialize ***/
1172 /* Wipe the iclr clean */
1173 (void)WIPE(iclr, infoclr);
1178 /* Nuke it when done */
1181 /* Assign the parms */
1185 iclr->stip = stip ? 1 : 0;
1194 * Change the 'fg' for an infoclr
1197 * fg: The Pixell for the requested Foreground (see above)
1199 static errr Infoclr_change_fg(Pixell fg)
1201 infoclr *iclr = Infoclr;
1204 /*** Simple error checking of opr and clr ***/
1206 /* Check the 'Pixells' for realism */
1207 if (fg > Metadpy->zg) return (-1);
1213 XSetForeground(Metadpy->dpy, iclr->gc, fg);
1221 #ifndef IGNORE_UNUSED_FUNCTIONS
1224 * Nuke an old 'infofnt'.
1226 static errr Infofnt_nuke(void)
1228 infofnt *ifnt = Infofnt;
1231 infofnt *ikfnt = Infokfnt;
1233 /* Deal with 'name' */
1237 string_free(ifnt->name);
1244 string_free(ikfnt->name);
1247 /* Nuke info if needed */
1251 XFreeFont(Metadpy->dpy, ifnt->info);
1258 XFreeFont(Metadpy->dpy, ikfnt->info);
1265 #endif /* IGNORE_UNUSED_FUNCTIONS */
1269 * Prepare a new 'infofnt'
1272 static errr Infofnt_prepare(XFontStruct *info, XFontStruct *kinfo)
1275 static errr Infofnt_prepare(XFontSet info)
1277 static errr Infofnt_prepare(XFontStruct *info)
1282 infofnt *ifnt = Infofnt;
1285 infofnt *ikfnt = Infokfnt;
1289 XFontStruct **fontinfo;
1292 int ascent, descent, width;
1295 /* Assign the struct */
1299 n_fonts = XFontsOfFontSet(info, &fontinfo, &fontname);
1301 ascent = descent = width = 0;
1302 while(n_fonts-- > 0){
1303 cs = &((*fontinfo)->max_bounds);
1304 if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
1305 if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
1306 if(((*fontinfo)->max_byte1) > 0){
1307 /* ¿¥Ð¥¤¥Èʸ»ú¤Î¾ì¹ç¤ÏÉýȾʬ(ü¿ôÀÚ¤ê¾å¤²)¤Çɾ²Á¤¹¤ë */
1308 if(width < (cs->width+1)/2) width = (cs->width+1)/2;
1310 if(width < cs->width) width = cs->width;
1316 ifnt->hgt = ascent + descent;
1319 /* Jump into the max bouonds thing */
1320 cs = &(info->max_bounds);
1322 /* Extract default sizing info */
1323 ifnt->asc = info->ascent;
1324 ifnt->hgt = info->ascent + info->descent;
1325 ifnt->wid = cs->width;
1329 ifnt->twid = 2 * ifnt->wid;
1331 ifnt->twid = ifnt->wid;
1334 /* Assign the struct */
1335 ikfnt->info = kinfo;
1337 /* Jump into the max bouonds thing */
1338 cs = &(kinfo->max_bounds);
1340 /* Extract default sizing info */
1341 ikfnt->asc = kinfo->ascent;
1342 ikfnt->hgt = kinfo->ascent + kinfo->descent;
1343 ikfnt->wid = cs->width;
1346 #ifdef OBSOLETE_SIZING_METHOD
1347 /* Extract default sizing info */
1348 ifnt->asc = cs->ascent;
1349 ifnt->hgt = (cs->ascent + cs->descent);
1350 ifnt->wid = cs->width;
1359 #ifndef IGNORE_UNUSED_FUNCTIONS
1362 * Initialize a new 'infofnt'.
1365 static errr Infofnt_init_real(XFontStruct *info, XFontStruct *kinfo)
1368 static errr Infofnt_init_real(XFontSet info)
1370 static errr Infofnt_init_real(XFontStruct *info)
1375 /* Wipe the thing */
1376 (void)WIPE(Infofnt, infofnt);
1379 WIPE(Infokfnt, infofnt);
1387 /* Attempt to prepare it */
1389 return (Infofnt_prepare (info, kinfo));
1391 return (Infofnt_prepare(info));
1396 #endif /* IGNORE_UNUSED_FUNCTIONS */
1400 * Init an infofnt by its Name
1403 * name: The name of the requested Font
1406 static errr Infofnt_init_data(cptr name, cptr kname)
1408 static errr Infofnt_init_data(cptr name)
1414 char **missing_list;
1425 /*** Load the info Fresh, using the name ***/
1427 /* If the name is not given, report an error */
1428 if (!name) return (-1);
1431 if (!kname) return (-1);
1433 /* Attempt to load the font */
1435 info = XCreateFontSet(Metadpy->dpy, name, &missing_list, &missing_count, &default_font);
1436 if(missing_count > 0){
1437 printf("missing font(s): \n");
1438 while(missing_count-- > 0){
1439 printf("\t%s\n", missing_list[missing_count]);
1441 XFreeStringList(missing_list);
1444 info = XLoadQueryFont(Metadpy->dpy, name);
1446 kinfo = XLoadQueryFont(Metadpy->dpy, kname);
1451 /* The load failed, try to recover */
1452 if (!info) return (-1);
1454 if (!kinfo) return (-1);
1459 /*** Init the font ***/
1461 /* Wipe the thing */
1462 (void)WIPE(Infofnt, infofnt);
1465 WIPE(Infokfnt, infofnt);
1467 /* Attempt to prepare it */
1469 if (Infofnt_prepare(info, kinfo))
1471 if (Infofnt_prepare(info))
1477 XFreeFontSet(Metadpy->dpy, info);
1479 XFreeFont(Metadpy->dpy, info);
1481 XFreeFont(Metadpy->dpy, kinfo);
1488 /* Save a copy of the font name */
1489 Infofnt->name = string_make(name);
1491 Infokfnt->name = string_make(kname);
1494 /* Mark it as nukable */
1507 * EUCÆüËܸ쥳¡¼¥É¤ò´Þ¤àʸ»úÎó¤òɽ¼¨¤¹¤ë (Xlib)
1510 XDrawMultiString(display,d,gc, x, y, string, len, afont,
1511 afont_width, afont_height, afont_ascent, kfont, kfont_width)
1519 int afont_width, afont_height, afont_ascent;
1526 unsigned char *endp;
1529 endp = string + len;
1531 while ( str < endp && *str ) {
1534 if ( (*str) == 0x7f ) {
1536 /* 0x7F¤Ï¢£¤Ç·è¤áÂǤÁ */
1538 /* Ϣ³¤¹¤ë0x7F¤ÎŤµ¤ò¸¡½Ð */
1540 while ( str < endp && (*str) == 0x7f ) {
1546 XFillRectangle( display, d, gc, x, y-afont_ascent,
1547 slen * afont_width, afont_height);
1549 /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1550 x += afont_width * slen;
1554 if ( iskanji(*str) ) {
1558 /* Ϣ³¤¹¤ëUJISʸ»ú¤ÎŤµ¤ò¸¡½Ð */
1560 while ( str < endp && *str && iskanji(*str) ) {
1561 kanji[slen].byte1 = *str++ & 0x7f;
1562 kanji[slen++].byte2 = *str++ & 0x7f;
1566 XSetFont( display, gc, kfont->fid );
1567 XDrawImageString16( display, d, gc, x, y, kanji, slen );
1570 /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1571 x += kfont_width * slen;
1575 /* Èó´Á»ú(=ASCII¤È²¾Äê)¤Î»Ï¤Þ¤ê */
1577 /* Ϣ³¤¹¤ëASCIIʸ»ú¤ò¸¡½Ð */
1580 while ( str < endp && *str && !iskanji(*str) ) {
1582 if (*str == 0x7f)break;
1589 XSetFont( display, gc, afont->fid );
1590 XDrawImageString( display, d, gc, x, y, p, slen );
1592 /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1593 x += afont_width * slen;
1602 static errr Infofnt_text_std(int x, int y, cptr str, int len)
1607 /*** Do a brief info analysis ***/
1609 /* Do nothing if the string is null */
1610 if (!str || !*str) return (-1);
1612 /* Get the length of the string */
1613 if (len < 0) len = strlen(str);
1615 /*** Decide where to place the string, vertically ***/
1617 /* Ignore Vertical Justifications */
1618 y = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
1621 /*** Decide where to place the string, horizontally ***/
1623 /* Line up with x at left edge of column 'x' */
1624 x = (x * Infofnt->wid) + Infowin->ox;
1627 /*** Actually draw 'str' onto the infowin ***/
1631 /* Be sure the correct font is ready */
1632 XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
1636 /*** Handle the fake mono we can enforce on fonts ***/
1638 /* Monotize the font */
1642 /* Be sure the correct font is ready */
1643 XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
1645 /* Do each character */
1646 for (i = 0; i < len; ++i)
1648 /* Note that the Infoclr is set up to contain the Infofnt */
1649 XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1650 x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
1654 /* Assume monoospaced font */
1657 /* Note that the Infoclr is set up to contain the Infofnt */
1659 /* ´Á»ú¥Õ¥©¥ó¥È¤Îɽ¼¨Éý¤Ï ASCII¥Õ¥©¥ó¥È¤Î2Çܤ˸ÇÄê */
1660 XDrawMultiString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1662 Infofnt->info, Infofnt->wid, Infofnt->hgt,
1664 Infokfnt->info, Infofnt->wid * 2);
1667 XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info,
1668 Infoclr->gc, x, y, str, len);
1670 XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1684 * Painting where text would be
1686 static errr Infofnt_text_non(int x, int y, cptr str, int len)
1691 /*** Find the width ***/
1693 /* Negative length is a flag to count the characters in str */
1694 if (len < 0) len = strlen(str);
1696 /* The total width will be 'len' chars * standard width */
1697 w = len * Infofnt->wid;
1700 /*** Find the X dimensions ***/
1702 /* Line up with x at left edge of column 'x' */
1703 x = x * Infofnt->wid + Infowin->ox;
1706 /*** Find other dimensions ***/
1708 /* Simply do 'Infofnt->hgt' (a single row) high */
1711 /* Simply do "at top" in row 'y' */
1712 y = y * h + Infowin->oy;
1715 /*** Actually 'paint' the area ***/
1717 /* Just do a Fill Rectangle */
1718 XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, x, y, w, h);
1726 /*************************************************************************/
1730 * Angband specific code follows... (ANGBAND)
1735 * Hack -- cursor color
1737 static infoclr *xor;
1740 * Actual color table
1742 static infoclr *clr[256];
1745 * Color info (unused, red, green, blue).
1747 static byte color_table[256][4];
1752 typedef struct term_data term_data;
1755 * A structure for each "term"
1773 #ifdef USE_TRANSPARENCY
1775 /* Tempory storage for overlaying tiles. */
1786 * The number of term data structures
1788 #define MAX_TERM_DATA 8
1791 * The array of term data structures
1793 static term_data data[MAX_TERM_DATA];
1798 * Process a keypress event
1800 * Also appears in "main-xaw.c".
1802 static void react_keypress(XKeyEvent *xev)
1804 int i, n, mc, ms, mo, mx;
1808 XKeyEvent *ev = (XKeyEvent*)(xev);
1816 int valid_keysym = TRUE;
1819 /* Check for "normal" keypresses */
1821 if(Focuswin && Focuswin->xic){
1823 n = XmbLookupString(Focuswin->xic, ev, buf, 125, &ks, &status);
1824 if(status == XBufferOverflow){
1825 printf("Input is too long, and dropped\n");
1828 if(status != XLookupKeySym && status != XLookupBoth){
1829 valid_keysym = FALSE;
1832 n = XLookupString(ev, buf, 125, &ks, NULL);
1835 n = XLookupString(ev, buf, 125, &ks, NULL);
1843 /* Enqueue the normal key(s) */
1844 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1851 /* Hack -- Ignore "modifier keys" */
1852 if (IsModifierKey(ks)) return;
1855 /* Hack -- convert into an unsigned int */
1858 /* Extract four "modifier flags" */
1859 mc = (ev->state & ControlMask) ? TRUE : FALSE;
1860 ms = (ev->state & ShiftMask) ? TRUE : FALSE;
1861 mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
1862 mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
1865 /* Normal keys with no modifiers */
1866 if (n && !mo && !mx && !IsSpecialKey(ks))
1868 /* Enqueue the normal key(s) */
1869 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1876 /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */
1881 Term_keypress(ESCAPE);
1887 Term_keypress('\r');
1893 Term_keypress('\t');
1899 Term_keypress(0x7f);
1904 Term_keypress('\010');
1910 /* Hack -- Use the KeySym */
1913 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
1914 mc ? "N" : "", ms ? "S" : "",
1915 mo ? "O" : "", mx ? "M" : "",
1916 (unsigned long)(ks), 13);
1919 /* Hack -- Use the Keycode */
1922 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
1923 mc ? "N" : "", ms ? "S" : "",
1924 mo ? "O" : "", mx ? "M" : "",
1928 /* Enqueue the "macro trigger" string */
1929 for (i = 0; msg[i]; i++) Term_keypress(msg[i]);
1932 /* Hack -- auto-define macros as needed */
1933 if (n && (macro_find_exact(msg) < 0))
1935 /* Create a macro */
1936 macro_add(msg, buf);
1946 static errr CheckEvent(bool wait)
1948 term_data *old_td = (term_data*)(Term->data);
1950 XEvent xev_body, *xev = &xev_body;
1952 term_data *td = NULL;
1953 infowin *iwin = NULL;
1961 /* Do not wait unless requested */
1962 if (!wait && !XPending(Metadpy->dpy)) return (1);
1964 /* Load the Event */
1965 XNextEvent(Metadpy->dpy, xev);
1968 /* #define DEBUG_EVENT */
1971 printf("event: type=%d", xev->type);
1974 printf("(KeyPress), keycode=%X", xev->xkey.keycode);
1977 printf("(FocusIn)");
1980 printf("(FocusOut)");
1982 case ReparentNotify:
1983 printf("(ReparentNotify)");
1985 case ConfigureNotify:
1986 printf("(ConfigureNotify)");
1989 printf("(MapNotify)");
1995 printf("(ClientMessage)");
2001 if (XFilterEvent(xev, xev->xany.window)
2002 /*XFilterEvent(xev, (data[0].win)->win)*/){
2004 printf(", [filtered by IM]\n");
2006 goto redo_checkevent;
2013 /* Notice new keymaps */
2014 if (xev->type == MappingNotify)
2016 XRefreshKeyboardMapping(&xev->xmapping);
2021 /* Scan the windows */
2022 for (i = 0; i < MAX_TERM_DATA; i++)
2024 if (!data[i].win) continue;
2025 if (xev->xany.window == data[i].win->win)
2033 /* Unknown window */
2034 if (!td || !iwin) return (0);
2037 /* Hack -- activate the Term */
2038 Term_activate(&td->t);
2040 /* Hack -- activate the window */
2044 /* Switch on the Type */
2055 /* Which button is involved */
2056 if (xev->xbutton.button == Button1) z = 1;
2057 else if (xev->xbutton.button == Button2) z = 2;
2058 else if (xev->xbutton.button == Button3) z = 3;
2059 else if (xev->xbutton.button == Button4) z = 4;
2060 else if (xev->xbutton.button == Button5) z = 5;
2062 /* Where is the mouse */
2074 /* Where is the mouse */
2075 x = xev->xcrossing.x;
2076 y = xev->xcrossing.y;
2085 /* Where is the mouse */
2104 /* Save the mouse location */
2108 /* Hack -- use "old" term */
2109 Term_activate(&old_td->t);
2111 /* Process the key */
2112 react_keypress(&(xev->xkey));
2121 /* Ignore "extra" exposes */
2122 /*if (xev->xexpose.count) break;*/
2124 /* Clear the window */
2127 x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
2128 x2 = (xev->xexpose.x + xev->xexpose.width -
2129 Infowin->ox)/Infofnt->wid;
2131 y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
2132 y2 = (xev->xexpose.y + xev->xexpose.height -
2133 Infowin->oy)/Infofnt->hgt;
2135 Term_redraw_section(x1, y1, x2, y2);
2145 Infowin->mapped = 1;
2146 Term->mapped_flag = TRUE;
2152 Infowin->mapped = 0;
2153 Term->mapped_flag = FALSE;
2157 /* Move and/or Resize */
2158 case ConfigureNotify:
2160 int cols, rows, wid, hgt;
2162 int ox = Infowin->ox;
2163 int oy = Infowin->oy;
2165 /* Save the new Window Parms */
2166 Infowin->x = xev->xconfigure.x;
2167 Infowin->y = xev->xconfigure.y;
2168 Infowin->w = xev->xconfigure.width;
2169 Infowin->h = xev->xconfigure.height;
2171 /* Determine "proper" number of rows/cols */
2172 cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
2173 rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
2175 /* Hack -- minimal size */
2176 if (cols < 1) cols = 1;
2177 if (rows < 1) rows = 1;
2181 /* Hack the main window must be at least 80x24 */
2182 if (cols < 80) cols = 80;
2183 if (rows < 24) rows = 24;
2186 /* Desired size of window */
2187 wid = cols * td->fnt->wid + (ox + ox);
2188 hgt = rows * td->fnt->hgt + (oy + oy);
2190 /* Resize the Term (if needed) */
2191 Term_resize(cols, rows);
2193 /* Resize the windows if any "change" is needed */
2194 if ((Infowin->w != wid) || (Infowin->h != hgt))
2197 Infowin_set(td->win);
2198 Infowin_resize(wid, hgt);
2207 XSetICFocus(iwin->xic);
2215 XUnsetICFocus(iwin->xic);
2217 /* Focuswin = NULL;*/
2224 /* Hack -- Activate the old term */
2225 Term_activate(&old_td->t);
2227 /* Hack -- Activate the proper window */
2228 Infowin_set(old_td->win);
2239 * An array of sound file names
2241 static cptr sound_file[SOUND_MAX];
2244 * Check for existance of a file
2246 static bool check_file(cptr s)
2250 fff = fopen(s, "r");
2251 if (!fff) return (FALSE);
2260 static void init_sound(void)
2265 char dir_xtra_sound[1024];
2267 /* Build the "sound" path */
2268 path_build(dir_xtra_sound, 1024, ANGBAND_DIR_XTRA, "sound");
2270 /* Prepare the sounds */
2271 for (i = 1; i < SOUND_MAX; i++)
2273 /* Extract name of sound file */
2274 sprintf(wav, "%s.wav", angband_sound_name[i]);
2276 /* Access the sound */
2277 path_build(buf, 1024, dir_xtra_sound, wav);
2279 /* Save the sound filename, if it exists */
2280 if (check_file(buf)) sound_file[i] = string_make(buf);
2287 * Hack -- make a sound
2289 static errr Term_xtra_x11_sound(int v)
2293 /* Sound disabled */
2294 if (!use_sound) return (1);
2297 if ((v < 0) || (v >= SOUND_MAX)) return (1);
2300 if (!sound_file[v]) return (1);
2302 sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
2308 #endif /* USE_SOUND */
2312 * Handle "activation" of a term
2314 static errr Term_xtra_x11_level(int v)
2316 term_data *td = (term_data*)(Term->data);
2318 /* Handle "activate" */
2321 /* Activate the window */
2322 Infowin_set(td->win);
2324 /* Activate the font */
2325 Infofnt_set(td->fnt);
2327 Infokfnt_set(td->kfnt);
2339 static errr Term_xtra_x11_react(void)
2345 /* Check the colors */
2346 for (i = 0; i < 256; i++)
2348 if ((color_table[i][0] != angband_color_table[i][0]) ||
2349 (color_table[i][1] != angband_color_table[i][1]) ||
2350 (color_table[i][2] != angband_color_table[i][2]) ||
2351 (color_table[i][3] != angband_color_table[i][3]))
2355 /* Save new values */
2356 color_table[i][0] = angband_color_table[i][0];
2357 color_table[i][1] = angband_color_table[i][1];
2358 color_table[i][2] = angband_color_table[i][2];
2359 color_table[i][3] = angband_color_table[i][3];
2362 pixel = create_pixel(Metadpy->dpy,
2367 /* Change the foreground */
2368 Infoclr_set(clr[i]);
2369 Infoclr_change_fg(pixel);
2380 * Handle a "special request"
2382 static errr Term_xtra_x11(int n, int v)
2384 /* Handle a subset of the legal requests */
2388 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
2391 /* Make a special sound */
2392 case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
2395 /* Flush the output XXX XXX */
2396 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
2398 /* Process random events XXX */
2399 case TERM_XTRA_BORED: return (CheckEvent(0));
2401 /* Process Events XXX */
2402 case TERM_XTRA_EVENT: return (CheckEvent(v));
2404 /* Flush the events XXX */
2405 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
2407 /* Handle change in the "level" */
2408 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
2410 /* Clear the screen */
2411 case TERM_XTRA_CLEAR: Infowin_wipe(); return (0);
2413 /* Delay for some milliseconds */
2414 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
2416 /* React to changes */
2417 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
2426 * Draw the cursor as an inverted rectangle.
2428 * Consider a rectangular outline like "main-mac.c". XXX XXX
2430 static errr Term_curs_x11(int x, int y)
2432 /* Draw the cursor */
2436 if (x + 1 < Term->wid &&
2437 ((use_bigtile && Term->old->a[y][x+1] == 255) ||
2438 (iskanji(Term->old->c[y][x]) && !(Term->old->a[y][x] & 0x80))))
2440 if (use_bigtile && x + 1 < Term->wid && Term->old->a[y][x+1] == 255)
2442 Infofnt_text_non(x, y, " ", 2);
2444 /* Hilite the cursor character */
2445 Infofnt_text_non(x, y, " ", 1);
2453 * Erase some characters.
2455 static errr Term_wipe_x11(int x, int y, int n)
2457 /* Erase (use black) */
2458 Infoclr_set(clr[TERM_DARK]);
2460 /* Mega-Hack -- Erase some space */
2461 Infofnt_text_non(x, y, "", n);
2469 * Draw some textual characters.
2471 static errr Term_text_x11(int x, int y, int n, byte a, cptr s)
2474 Infoclr_set(clr[a]);
2477 Infofnt_text_std(x, y, s, n);
2487 * Draw some graphical characters.
2489 # ifdef USE_TRANSPARENCY
2490 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
2491 # else /* USE_TRANSPARENCY */
2492 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
2493 # endif /* USE_TRANSPARENCY */
2500 #ifdef USE_TRANSPARENCY
2507 unsigned long pixel, blank;
2508 #endif /* USE_TRANSPARENCY */
2510 term_data *td = (term_data*)(Term->data);
2515 /* Add in affect of window boundaries */
2519 for (i = 0; i < n; ++i, x += td->fnt->wid)
2524 /* For extra speed - cache these values */
2525 x1 = (c&0x7F) * td->fnt->twid;
2526 y1 = (a&0x7F) * td->fnt->hgt;
2528 #ifdef USE_TRANSPARENCY
2533 /* For extra speed - cache these values */
2534 x2 = (tc&0x7F) * td->fnt->twid;
2535 y2 = (ta&0x7F) * td->fnt->hgt;
2537 /* Optimise the common case */
2538 if (((x1 == x2) && (y1 == y2)) ||
2539 !(((byte)ta & 0x80) && ((byte)tc & 0x80)))
2541 /* Draw object / terrain */
2542 XPutImage(Metadpy->dpy, td->win->win,
2547 td->fnt->twid, td->fnt->hgt);
2552 /* Mega Hack^2 - assume the top left corner is "black" */
2553 blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
2555 for (k = 0; k < td->fnt->twid; k++)
2557 for (l = 0; l < td->fnt->hgt; l++)
2559 /* If mask set... */
2560 if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
2562 /* Output from the terrain */
2563 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
2566 /* Store into the temp storage. */
2567 XPutPixel(td->TmpImage, k, l, pixel);
2572 /* Draw to screen */
2574 XPutImage(Metadpy->dpy, td->win->win,
2578 td->fnt->twid, td->fnt->hgt);
2581 #else /* USE_TRANSPARENCY */
2583 /* Draw object / terrain */
2584 XPutImage(Metadpy->dpy, td->win->win,
2589 td->fnt->twid, td->fnt->hgt);
2591 #endif /* USE_TRANSPARENCY */
2598 #endif /* USE_GRAPHICS */
2601 static void IMDestroyCallback(XIM, XPointer, XPointer);
2604 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
2607 XIMCallback ximcallback;
2608 XIMStyles *xim_styles = NULL;
2611 xim = XOpenIM(display, NULL, NULL, NULL);
2613 printf("can't open IM\n");
2617 /* initialize destroy callback */
2618 ximcallback.callback = IMDestroyCallback;
2619 ximcallback.client_data = NULL;
2620 XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
2622 /* set style (only "Root" is supported yet...) */
2623 XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
2624 for (i = 0; i < xim_styles->count_styles; i++){
2625 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
2627 if(i >= xim_styles->count_styles){
2628 printf("Sorry, your IM does not support 'Root' preedit style...\n");
2636 for (i = 0; i < MAX_TERM_DATA; i++)
2638 infowin *iwin = data[i].win;
2639 if (!iwin) continue;
2640 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
2642 printf("Can't create input context for Term%d\n", i);
2645 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL){
2646 /* printf("Can't get XNFilterEvents\n"); */
2647 iwin->xic_mask = 0L;
2649 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
2655 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
2659 if (call_data == NULL){
2660 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
2663 for(i = 0; i < MAX_TERM_DATA; i++)
2665 infowin *iwin = data[i].win;
2668 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
2669 iwin->xic_mask = 0L;
2674 Metadpy->xim = NULL;
2679 * Initialize a term_data
2681 static errr term_data_init(term_data *td, int i)
2685 cptr name = angband_term_name[i];
2720 /* Window specific font name */
2721 sprintf(buf, "ANGBAND_X11_FONT_%d", i);
2723 /* Check environment for that font */
2726 /* Check environment for "base" font */
2727 if (!font) font = getenv("ANGBAND_X11_FONT");
2729 /* No environment variables, use default font */
2736 font = DEFAULT_X11_FONT_0;
2741 font = DEFAULT_X11_FONT_1;
2746 font = DEFAULT_X11_FONT_2;
2751 font = DEFAULT_X11_FONT_3;
2756 font = DEFAULT_X11_FONT_4;
2761 font = DEFAULT_X11_FONT_5;
2766 font = DEFAULT_X11_FONT_6;
2771 font = DEFAULT_X11_FONT_7;
2776 font = DEFAULT_X11_FONT;
2782 /* Window specific font name */
2783 sprintf(buf, "ANGBAND_X11_KFONT_%d", i);
2785 /* Check environment for that font */
2786 kfont = getenv(buf);
2788 /* Check environment for "base" font */
2789 if (!kfont) kfont = getenv("ANGBAND_X11_KFONT");
2791 /* No environment variables, use default font */
2798 kfont = DEFAULT_X11_KFONT_0;
2803 kfont = DEFAULT_X11_KFONT_1;
2808 kfont = DEFAULT_X11_KFONT_2;
2813 kfont = DEFAULT_X11_KFONT_3;
2818 kfont = DEFAULT_X11_KFONT_4;
2823 kfont = DEFAULT_X11_KFONT_5;
2828 kfont = DEFAULT_X11_KFONT_6;
2833 kfont = DEFAULT_X11_KFONT_7;
2838 kfont = DEFAULT_X11_KFONT;
2843 /* Window specific location (x) */
2844 sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
2846 x = (str != NULL) ? atoi(str) : -1;
2848 /* Window specific location (y) */
2849 sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
2851 y = (str != NULL) ? atoi(str) : -1;
2854 /* Window specific cols */
2855 sprintf(buf, "ANGBAND_X11_COLS_%d", i);
2857 val = (str != NULL) ? atoi(str) : -1;
2858 if (val > 0) cols = val;
2860 /* Window specific rows */
2861 sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
2863 val = (str != NULL) ? atoi(str) : -1;
2864 if (val > 0) rows = val;
2866 /* Hack the main window must be at least 80x24 */
2869 if (cols < 80) cols = 80;
2870 if (rows < 24) rows = 24;
2873 /* Window specific inner border offset (ox) */
2874 sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
2876 val = (str != NULL) ? atoi(str) : -1;
2877 if (val > 0) ox = val;
2879 /* Window specific inner border offset (oy) */
2880 sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
2882 val = (str != NULL) ? atoi(str) : -1;
2883 if (val > 0) oy = val;
2886 /* Prepare the standard font */
2888 MAKE(td->fnt, infofnt);
2889 Infofnt_set(td->fnt);
2890 MAKE(td->kfnt, infofnt);
2891 Infokfnt_set(td->kfnt);
2892 Infofnt_init_data(font, kfont);
2894 MAKE(td->fnt, infofnt);
2895 Infofnt_set(td->fnt);
2896 Infofnt_init_data(font);
2900 /* Hack -- key buffer size */
2901 num = ((i == 0) ? 1024 : 16);
2903 /* Assume full size windows */
2904 wid = cols * td->fnt->wid + (ox + ox);
2905 hgt = rows * td->fnt->hgt + (oy + oy);
2907 /* Create a top-window */
2908 MAKE(td->win, infowin);
2909 Infowin_set(td->win);
2910 Infowin_init_top(x, y, wid, hgt, 0,
2911 Metadpy->fg, Metadpy->bg);
2913 /* Ask for certain events */
2914 #if defined(USE_XIM)
2915 Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | FocusChangeMask);
2917 Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask);
2920 /* Set the window name */
2921 Infowin_set_name(name);
2923 /* Save the inner border */
2927 /* Make Class Hints */
2928 ch = XAllocClassHint();
2930 if (ch == NULL) quit("XAllocClassHint failed");
2932 strcpy(res_name, name);
2933 res_name[0] = FORCELOWER(res_name[0]);
2934 ch->res_name = res_name;
2936 strcpy(res_class, "Angband");
2937 ch->res_class = res_class;
2939 XSetClassHint(Metadpy->dpy, Infowin->win, ch);
2941 /* Make Size Hints */
2942 sh = XAllocSizeHints();
2945 if (sh == NULL) quit("XAllocSizeHints failed");
2947 /* Main window has a differing minimum size */
2950 /* Main window min size is 80x24 */
2951 sh->flags = PMinSize | PMaxSize;
2952 sh->min_width = 80 * td->fnt->wid + (ox + ox);
2953 sh->min_height = 24 * td->fnt->hgt + (oy + oy);
2954 sh->max_width = 255 * td->fnt->wid + (ox + ox);
2955 sh->max_height = 255 * td->fnt->hgt + (oy + oy);
2958 /* Other windows can be shrunk to 1x1 */
2962 sh->flags = PMinSize | PMaxSize;
2963 sh->min_width = td->fnt->wid + (ox + ox);
2964 sh->min_height = td->fnt->hgt + (oy + oy);
2965 sh->max_width = 256 * td->fnt->wid + (ox + ox);
2966 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
2969 /* Resize increment */
2970 sh->flags |= PResizeInc;
2971 sh->width_inc = td->fnt->wid;
2972 sh->height_inc = td->fnt->hgt;
2974 /* Base window size */
2975 sh->flags |= PBaseSize;
2976 sh->base_width = (ox + ox);
2977 sh->base_height = (oy + oy);
2979 /* Use the size hints */
2980 XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
2982 /* Map the window */
2987 wh = XAllocWMHints();
2988 if(wh == NULL) quit("XAllocWMHints failed");
2989 wh->flags = InputHint;
2991 XSetWMHints(Metadpy->dpy, Infowin->win, wh);
2994 /* Move the window to requested location */
2995 if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
2998 /* Initialize the term */
2999 term_init(t, cols, rows, num);
3001 /* Use a "soft" cursor */
3002 t->soft_cursor = TRUE;
3004 /* Erase with "white space" */
3005 t->attr_blank = TERM_WHITE;
3006 t->char_blank = ' ';
3009 t->xtra_hook = Term_xtra_x11;
3010 t->curs_hook = Term_curs_x11;
3011 t->wipe_hook = Term_wipe_x11;
3012 t->text_hook = Term_text_x11;
3017 /* Activate (important) */
3026 * Initialization function for an "X11" module to Angband
3028 errr init_x11(int argc, char *argv[])
3038 char filename[1024];
3043 #ifdef USE_TRANSPARENCY
3046 #endif /* USE_TRANSPARENCY */
3048 #endif /* USE_GRAPHICS */
3052 for (i = 1; i < argc; i++)
3054 if (prefix(argv[i], "-d"))
3056 dpy_name = &argv[i][2];
3061 if (prefix(argv[i], "-s"))
3063 smoothRescaling = FALSE;
3067 if (prefix(argv[i], "-a"))
3069 arg_graphics = GRAPHICS_ADAM_BOLT;
3073 if (prefix(argv[i], "-o"))
3075 arg_graphics = GRAPHICS_ORIGINAL;
3079 if (prefix(argv[i], "-b"))
3081 arg_bigtile = use_bigtile = TRUE;
3084 #endif /* USE_GRAPHICS */
3086 if (prefix(argv[i], "-n"))
3088 num_term = atoi(&argv[i][2]);
3089 if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
3090 else if (num_term < 1) num_term = 1;
3094 if (prefix(argv[i], "--"))
3100 plog_fmt("Ignoring option: %s", argv[i]);
3104 setlocale(LC_ALL, "");
3105 #ifdef DEFAULT_LOCALE
3106 if(!strcmp(setlocale(LC_ALL, NULL), "C")){
3107 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
3108 setlocale(LC_ALL, DEFAULT_LOCALE);
3112 char *current_locale = setlocale(LC_ALL, NULL);
3113 /* printf("set locale to \"%s\"\n", current_locale); */
3114 if(!strcmp(current_locale, "C")){
3115 printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
3119 if(!XSupportsLocale()){
3120 printf("can't support locale in X\n");
3121 setlocale(LC_ALL, "C");
3123 #endif /* USE_LOCALE */
3126 /* Init the Metadpy if possible */
3127 if (Metadpy_init_name(dpy_name)) return (-1);
3130 /* Prepare cursor color */
3133 Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
3136 /* Prepare normal colors */
3137 for (i = 0; i < 256; ++i)
3141 MAKE(clr[i], infoclr);
3143 Infoclr_set(clr[i]);
3145 /* Acquire Angband colors */
3146 color_table[i][0] = angband_color_table[i][0];
3147 color_table[i][1] = angband_color_table[i][1];
3148 color_table[i][2] = angband_color_table[i][2];
3149 color_table[i][3] = angband_color_table[i][3];
3151 /* Default to monochrome */
3152 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
3158 pixel = create_pixel(Metadpy->dpy,
3164 /* Initialize the color */
3165 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
3169 /* Initialize the windows */
3170 for (i = 0; i < num_term; i++)
3172 term_data *td = &data[i];
3174 /* Initialize the term_data */
3175 term_data_init(td, i);
3177 /* Save global entry */
3178 angband_term[i] = Term;
3181 /* Raise the "Angband" window */
3182 Infowin_set(data[0].win);
3185 /* Activate the "Angband" window screen */
3186 Term_activate(&data[0].t);
3191 p = XSetLocaleModifiers("");
3193 p = XSetLocaleModifiers("@im=");
3195 /* printf("XMODIFIERS=\"%s\"\n", p); */
3197 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3201 /* initialize sound */
3202 if (arg_sound) init_sound();
3208 switch (arg_graphics)
3210 case GRAPHICS_ORIGINAL:
3211 /* Try the "8x8.bmp" file */
3212 path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/8x8.bmp");
3214 /* Use the "8x8.bmp" file if it exists */
3215 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3218 use_graphics = TRUE;
3220 pict_wid = pict_hgt = 8;
3222 ANGBAND_GRAF = "old";
3227 case GRAPHICS_ADAM_BOLT:
3228 /* Try the "16x16.bmp" file */
3229 path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/16x16.bmp");
3231 /* Use the "16x16.bmp" file if it exists */
3232 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3235 use_graphics = TRUE;
3237 pict_wid = pict_hgt = 16;
3239 ANGBAND_GRAF = "new";
3248 Display *dpy = Metadpy->dpy;
3252 /* Load the graphical tiles */
3253 tiles_raw = ReadBMP(dpy, filename);
3255 /* Initialize the windows */
3256 for (i = 0; i < num_term; i++)
3258 term_data *td = &data[i];
3263 t->pict_hook = Term_pict_x11;
3265 /* Use graphics sometimes */
3266 t->higher_pict = TRUE;
3270 ResizeImage(dpy, tiles_raw,
3272 td->fnt->twid, td->fnt->hgt);
3275 #ifdef USE_TRANSPARENCY
3276 /* Initialize the transparency masks */
3277 for (i = 0; i < num_term; i++)
3279 term_data *td = &data[i];
3281 int depth = DefaultDepth(dpy, DefaultScreen(dpy));
3282 Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
3286 /* Determine total bytes needed for image */
3288 jj = (depth - 1) >> 2;
3289 while (jj >>= 1) ii <<= 1;
3290 total = td->fnt->twid * td->fnt->hgt * ii;
3293 TmpData = (char *)malloc(total);
3295 td->TmpImage = XCreateImage(dpy,visual,depth,
3296 ZPixmap, 0, TmpData,
3297 td->fnt->twid, td->fnt->hgt, 8, 0);
3300 #endif /* USE_TRANSPARENCY */
3303 /* Free tiles_raw? XXX XXX */
3306 #endif /* USE_GRAPHICS */
3313 #endif /* USE_X11 */