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 #include <X11/Xatom.h>
127 #endif /* __MAKEDEPEND__ */
131 * Include some helpful X11 code.
133 #include "maid-x11.c"
137 * Hack -- avoid some compiler warnings
139 #define IGNORE_UNUSED_FUNCTIONS
145 * 1) On a monochrome (or "fake-monochrome") display, all colors
146 * will be "cast" to "fg," except for the bg color, which is,
147 * obviously, cast to "bg". Thus, one can ignore this setting.
149 * 2) Because of the inner functioning of the color allocation
150 * routines, colors may be specified as (a) a typical color name,
151 * (b) a hexidecimal color specification (preceded by a pound sign),
152 * or (c) by strings such as "fg", "bg", "zg".
154 * 3) Due to the workings of the init routines, many colors
155 * may also be dealt with by their actual pixel values. Note that
156 * the pixel with all bits set is "zg = (1<<metadpy->depth)-1", which
157 * is not necessarily either black or white.
162 /**** Generic Types ****/
166 * An X11 pixell specifier
168 typedef unsigned long Pixell;
171 * The structures defined below
173 typedef struct metadpy metadpy;
174 typedef struct infowin infowin;
175 typedef struct infoclr infoclr;
176 typedef struct infofnt infofnt;
180 * A structure summarizing a given Display.
182 * - The Display itself
183 * - The default Screen for the display
184 * - The virtual root (usually just the root)
185 * - The default colormap (from a macro)
187 * - The "name" of the display
189 * - The socket to listen to for events
191 * - The width of the display screen (from a macro)
192 * - The height of the display screen (from a macro)
193 * - The bit depth of the display screen (from a macro)
195 * - The black Pixell (from a macro)
196 * - The white Pixell (from a macro)
198 * - The background Pixell (default: black)
199 * - The foreground Pixell (default: white)
200 * - The maximal Pixell (Equals: ((2 ^ depth)-1), is usually ugly)
202 * - Bit Flag: Force all colors to black and white (default: !color)
203 * - Bit Flag: Allow the use of color (default: depth > 1)
204 * - Bit Flag: We created 'dpy', and so should nuke it when done.
239 * A Structure summarizing Window Information.
241 * I assume that a window is at most 30000 pixels on a side.
242 * I assume that the root windw is also at most 30000 square.
245 * - The current Input Event Mask
247 * - The location of the window
248 * - The width, height of the window
249 * - The border width of this window
251 * - Byte: 1st Extra byte
253 * - Bit Flag: This window is currently Mapped
254 * - Bit Flag: This window needs to be redrawn
255 * - Bit Flag: This window has been resized
257 * - Bit Flag: We should nuke 'win' when done with it
259 * - Bit Flag: 1st extra flag
260 * - Bit Flag: 2nd extra flag
261 * - Bit Flag: 3rd extra flag
262 * - Bit Flag: 4th extra flag
300 * A Structure summarizing Operation+Color Information
302 * - The actual GC corresponding to this info
304 * - The Foreground Pixell Value
305 * - The Background Pixell Value
307 * - Num (0-15): The operation code (As in Clear, Xor, etc)
308 * - Bit Flag: The GC is in stipple mode
309 * - Bit Flag: Destroy 'gc' at Nuke time.
326 * A Structure to Hold Font Information
328 * - The 'XFontStruct*' (yields the 'Font')
332 * - The default character width
333 * - The default character height
334 * - The default character ascent
336 * - Byte: Pixel offset used during fake mono
338 * - Flag: Force monospacing via 'wid'
339 * - Flag: Nuke info when done
365 /**** Generic Macros ****/
369 /* Set current metadpy (Metadpy) to 'M' */
370 #define Metadpy_set(M) \
374 /* Initialize 'M' using Display 'D' */
375 #define Metadpy_init_dpy(D) \
376 Metadpy_init_2(D,cNULL)
378 /* Initialize 'M' using a Display named 'N' */
379 #define Metadpy_init_name(N) \
380 Metadpy_init_2((Display*)(NULL),N)
382 /* Initialize 'M' using the standard Display */
383 #define Metadpy_init() \
384 Metadpy_init_name("")
387 /* Init an infowin by giving father as an (info_win*) (or NULL), and data */
388 #define Infowin_init_dad(D,X,Y,W,H,B,FG,BG) \
389 Infowin_init_data(((D) ? ((D)->win) : (Window)(None)), \
393 /* Init a top level infowin by pos,size,bord,Colors */
394 #define Infowin_init_top(X,Y,W,H,B,FG,BG) \
395 Infowin_init_data(None,X,Y,W,H,B,FG,BG)
398 /* Request a new standard window by giving Dad infowin and X,Y,W,H */
399 #define Infowin_init_std(D,X,Y,W,H,B) \
400 Infowin_init_dad(D,X,Y,W,H,B,Metadpy->fg,Metadpy->bg)
403 /* Set the current Infowin */
404 #define Infowin_set(I) \
408 /* Set the current Infoclr */
409 #define Infoclr_set(C) \
413 #define Infoclr_init_ppo(F,B,O,M) \
414 Infoclr_init_data(F,B,O,M)
416 #define Infoclr_init_cco(F,B,O,M) \
417 Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M)
419 #define Infoclr_init_ppn(F,B,O,M) \
420 Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M)
422 #define Infoclr_init_ccn(F,B,O,M) \
423 Infoclr_init_cco(F,B,Infoclr_Opcode(O),M)
426 /* Set the current infofnt */
427 #define Infofnt_set(I) \
431 /* Errr: Expose Infowin */
432 #define Infowin_expose() \
433 (!(Infowin->redraw = 1))
435 /* Errr: Unxpose Infowin */
436 #define Infowin_unexpose() \
437 (Infowin->redraw = 0)
441 /**** Generic Globals ****/
445 * The "default" values
447 static metadpy metadpy_default;
451 * The "current" variables
453 static metadpy *Metadpy = &metadpy_default;
454 static infowin *Infowin = (infowin*)(NULL);
456 static infowin *Focuswin = (infowin*)(NULL);
458 static infoclr *Infoclr = (infoclr*)(NULL);
460 static infofnt *Infofnt = (infofnt*)(NULL);
461 static infofnt *Infokfnt = (infofnt*)(NULL);
463 static infofnt *Infofnt = (infofnt*)(NULL);
469 /**** Generic code ****/
473 #define Infokfnt_set(I) \
477 * Init the current metadpy, with various initialization stuff.
480 * dpy: The Display* to use (if NULL, create it)
481 * name: The name of the Display (if NULL, the current)
484 * If 'name' is NULL, but 'dpy' is set, extract name from dpy
485 * If 'dpy' is NULL, then Create the named Display
486 * If 'name' is NULL, and so is 'dpy', use current Display
488 * Return -1 if no Display given, and none can be opened.
490 static errr Metadpy_init_2(Display *dpy, cptr name)
492 metadpy *m = Metadpy;
494 /*** Open the display if needed ***/
496 /* If no Display given, attempt to Create one */
499 /* Attempt to open the display */
500 dpy = XOpenDisplay(name);
503 if (!dpy) return (-1);
505 /* We will have to nuke it when done */
509 /* Since the Display was given, use it */
512 /* We will not have to nuke it when done */
517 /*** Save some information ***/
519 /* Save the Display itself */
522 /* Get the Screen and Virtual Root Window */
523 m->screen = DefaultScreenOfDisplay(dpy);
524 m->root = RootWindowOfScreen(m->screen);
526 /* Get the default colormap */
527 m->cmap = DefaultColormapOfScreen(m->screen);
529 /* Extract the true name of the display */
530 m->name = DisplayString(dpy);
533 m->fd = ConnectionNumber(Metadpy->dpy);
535 /* Save the Size and Depth of the screen */
536 m->width = WidthOfScreen(m->screen);
537 m->height = HeightOfScreen(m->screen);
538 m->depth = DefaultDepthOfScreen(m->screen);
540 /* Save the Standard Colors */
541 m->black = BlackPixelOfScreen(m->screen);
542 m->white = WhitePixelOfScreen(m->screen);
544 /*** Make some clever Guesses ***/
546 /* Guess at the desired 'fg' and 'bg' Pixell's */
550 /* Calculate the Maximum allowed Pixel value. */
551 m->zg = (1 << m->depth) - 1;
553 /* Save various default Flag Settings */
554 m->color = ((m->depth > 1) ? 1 : 0);
555 m->mono = ((m->color) ? 0 : 1);
557 /* Return "success" */
562 #ifndef IGNORE_UNUSED_FUNCTIONS
565 * Nuke the current metadpy
567 static errr Metadpy_nuke(void)
569 metadpy *m = Metadpy;
572 /* If required, Free the Display */
575 /* Close the Display */
576 XCloseDisplay(m->dpy);
578 /* Forget the Display */
579 m->dpy = (Display*)(NULL);
581 /* Do not nuke it again */
589 #endif /* IGNORE_UNUSED_FUNCTIONS */
593 * General Flush/ Sync/ Discard routine
595 static errr Metadpy_update(int flush, int sync, int discard)
597 /* Flush if desired */
598 if (flush) XFlush(Metadpy->dpy);
600 /* Sync if desired, using 'discard' */
601 if (sync) XSync(Metadpy->dpy, discard);
611 static errr Metadpy_do_beep(void)
613 /* Make a simple beep */
614 XBell(Metadpy->dpy, 100);
622 * Set the name (in the title bar) of Infowin
624 static errr Infowin_set_name(cptr name)
631 st = XStringListToTextProperty(&bp, 1, &tp);
632 if (st) XSetWMName(Metadpy->dpy, Infowin->win, &tp);
637 #ifndef IGNORE_UNUSED_FUNCTIONS
640 * Set the icon name of Infowin
642 static errr Infowin_set_icon_name(cptr name)
649 st = XStringListToTextProperty(&bp, 1, &tp);
650 if (st) XSetWMIconName(Metadpy->dpy, Infowin->win, &tp);
658 static errr Infowin_nuke(void)
660 infowin *iwin = Infowin;
662 /* Nuke if requested */
665 /* Destory the old window */
666 XDestroyWindow(Metadpy->dpy, iwin->win);
673 #endif /* IGNORE_UNUSED_FUNCTIONS */
677 * Prepare a new 'infowin'.
679 static errr Infowin_prepare(Window xid)
681 infowin *iwin = Infowin;
684 XWindowAttributes xwa;
686 unsigned int w, h, b, d;
691 /* Check For Error XXX Extract some ACTUAL data from 'xid' */
692 XGetGeometry(Metadpy->dpy, xid, &tmp_win, &x, &y, &w, &h, &b, &d);
694 /* Apply the above info */
701 /* Check Error XXX Extract some more ACTUAL data */
702 XGetWindowAttributes(Metadpy->dpy, xid, &xwa);
704 /* Apply the above info */
705 iwin->mask = xwa.your_event_mask;
706 iwin->mapped = ((xwa.map_state == IsUnmapped) ? 0 : 1);
708 /* And assume that we are exposed */
716 #ifndef IGNORE_UNUSED_FUNCTIONS
719 * Initialize a new 'infowin'.
721 static errr Infowin_init_real(Window xid)
724 (void)WIPE(Infowin, infowin);
726 /* Start out non-nukable */
729 /* Attempt to Prepare ourself */
730 return (Infowin_prepare(xid));
733 #endif /* IGNORE_UNUSED_FUNCTIONS */
737 * Init an infowin by giving some data.
740 * dad: The Window that should own this Window (if any)
741 * x,y: The position of this Window
742 * w,h: The size of this Window
743 * b,d: The border width and pixel depth
746 * If 'dad == None' assume 'dad == root'
748 static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
749 int b, Pixell fg, Pixell bg)
754 (void)WIPE(Infowin, infowin);
757 /*** Error Check XXX ***/
760 /*** Create the Window 'xid' from data ***/
762 /* What happened here? XXX XXX XXX */
764 /* If no parent given, depend on root */
767 /* #ifdef USE_GRAPHICS
769 xid = XCreateWindow(Metadpy->dpy, Metadpy->root, x, y, w, h, b, 8, InputOutput, CopyFromParent, 0, 0);
780 /* Create the Window XXX Error Check */
781 xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg, bg);
783 /* Start out selecting No events */
784 XSelectInput(Metadpy->dpy, xid, 0L);
787 /*** Prepare the new infowin ***/
789 /* Mark it as nukable */
792 /* Attempt to Initialize the infowin */
793 return (Infowin_prepare(xid));
799 * Modify the event mask of an Infowin
801 static errr Infowin_set_mask(long mask)
803 /* Save the new setting */
804 Infowin->mask = mask;
806 /* Execute the Mapping */
807 XSelectInput(Metadpy->dpy, Infowin->win, Infowin->mask);
815 * Request that Infowin be mapped
817 static errr Infowin_map(void)
819 /* Execute the Mapping */
820 XMapWindow(Metadpy->dpy, Infowin->win);
827 #ifndef IGNORE_UNUSED_FUNCTIONS
830 * Request that Infowin be unmapped
832 static errr Infowin_unmap(void)
834 /* Execute the Un-Mapping */
835 XUnmapWindow(Metadpy->dpy, Infowin->win);
841 #endif /* IGNORE_UNUSED_FUNCTIONS */
845 * Request that Infowin be raised
847 static errr Infowin_raise(void)
849 /* Raise towards visibility */
850 XRaiseWindow(Metadpy->dpy, Infowin->win);
857 #ifndef IGNORE_UNUSED_FUNCTIONS
860 * Request that Infowin be lowered
862 static errr Infowin_lower(void)
864 /* Lower towards invisibility */
865 XLowerWindow(Metadpy->dpy, Infowin->win);
871 #endif /* IGNORE_UNUSED_FUNCTIONS */
875 * Request that Infowin be moved to a new location
877 static errr Infowin_impell(int x, int y)
879 /* Execute the request */
880 XMoveWindow(Metadpy->dpy, Infowin->win, x, y);
890 static errr Infowin_resize(int w, int h)
892 /* Execute the request */
893 XResizeWindow(Metadpy->dpy, Infowin->win, w, h);
900 #ifndef IGNORE_UNUSED_FUNCTIONS
903 * Move and Resize an infowin
905 static errr Infowin_locate(int x, int y, int w, int h)
907 /* Execute the request */
908 XMoveResizeWindow(Metadpy->dpy, Infowin->win, x, y, w, h);
914 #endif /* IGNORE_UNUSED_FUNCTIONS */
918 * Visually clear Infowin
920 static errr Infowin_wipe(void)
922 /* Execute the request */
923 XClearWindow(Metadpy->dpy, Infowin->win);
930 #ifndef IGNORE_UNUSED_FUNCTIONS
933 * Visually Paint Infowin with the current color
935 static errr Infowin_fill(void)
937 /* Execute the request */
938 XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc,
939 0, 0, Infowin->w, Infowin->h);
945 #endif /* IGNORE_UNUSED_FUNCTIONS */
949 * A NULL terminated pair list of legal "operation names"
951 * Pairs of values, first is texttual name, second is the string
952 * holding the decimal value that the operation corresponds to.
954 static cptr opcode_pairs[] =
973 "+copyInverted", "12",
981 * Parse a word into an operation "code"
984 * str: A string, hopefully representing an Operation
987 * 0-15: if 'str' is a valid Operation
988 * -1: if 'str' could not be parsed
990 static int Infoclr_Opcode(cptr str)
994 /* Scan through all legal operation names */
995 for (i = 0; opcode_pairs[i*2]; ++i)
997 /* Is this the right oprname? */
998 if (streq(opcode_pairs[i*2], str))
1000 /* Convert the second element in the pair into a Code */
1001 return (atoi(opcode_pairs[i*2+1]));
1005 /* The code was not found, return -1 */
1010 #ifndef IGNORE_UNUSED_FUNCTIONS
1013 * Request a Pixell by name. Note: uses 'Metadpy'.
1016 * name: The name of the color to try to load (see below)
1019 * The Pixell value that metched the given name
1020 * 'Metadpy->fg' if the name was unparseable
1022 * Valid forms for 'name':
1023 * 'fg', 'bg', 'zg', '<name>' and '#<code>'
1025 static Pixell Infoclr_Pixell(cptr name)
1029 /* Attempt to Parse the name */
1030 if (name && name[0])
1032 /* The 'bg' color is available */
1033 if (streq(name, "bg")) return (Metadpy->bg);
1035 /* The 'fg' color is available */
1036 if (streq(name, "fg")) return (Metadpy->fg);
1038 /* The 'zg' color is available */
1039 if (streq(name, "zg")) return (Metadpy->zg);
1041 /* The 'white' color is available */
1042 if (streq(name, "white")) return (Metadpy->white);
1044 /* The 'black' color is available */
1045 if (streq(name, "black")) return (Metadpy->black);
1047 /* Attempt to parse 'name' into 'scrn' */
1048 if (!(XParseColor(Metadpy->dpy, Metadpy->cmap, name, &scrn)))
1050 plog_fmt("Warning: Couldn't parse color '%s'\n", name);
1053 /* Attempt to Allocate the Parsed color */
1054 if (!(XAllocColor(Metadpy->dpy, Metadpy->cmap, &scrn)))
1056 plog_fmt("Warning: Couldn't allocate color '%s'\n", name);
1059 /* The Pixel was Allocated correctly */
1060 else return (scrn.pixel);
1063 /* Warn about the Default being Used */
1064 plog_fmt("Warning: Using 'fg' for unknown color '%s'\n", name);
1066 /* Default to the 'Foreground' color */
1067 return (Metadpy->fg);
1072 * Initialize a new 'infoclr' with a real GC.
1074 static errr Infoclr_init_1(GC gc)
1076 infoclr *iclr = Infoclr;
1078 /* Wipe the iclr clean */
1079 (void)WIPE(iclr, infoclr);
1090 * Nuke an old 'infoclr'.
1092 static errr Infoclr_nuke(void)
1094 infoclr *iclr = Infoclr;
1096 /* Deal with 'GC' */
1100 XFreeGC(Metadpy->dpy, iclr->gc);
1103 /* Forget the current */
1104 Infoclr = (infoclr*)(NULL);
1110 #endif /* IGNORE_UNUSED_FUNCTIONS */
1114 * Initialize an infoclr with some data
1117 * fg: The Pixell for the requested Foreground (see above)
1118 * bg: The Pixell for the requested Background (see above)
1119 * op: The Opcode for the requested Operation (see above)
1120 * stip: The stipple mode
1122 static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
1124 infoclr *iclr = Infoclr;
1128 unsigned long gc_mask;
1132 /*** Simple error checking of opr and clr ***/
1134 /* Check the 'Pixells' for realism */
1135 if (bg > Metadpy->zg) return (-1);
1136 if (fg > Metadpy->zg) return (-1);
1138 /* Check the data for trueness */
1139 if ((op < 0) || (op > 15)) return (-1);
1142 /*** Create the requested 'GC' ***/
1144 /* Assign the proper GC function */
1147 /* Assign the proper GC background */
1148 gcv.background = bg;
1150 /* Assign the proper GC foreground */
1151 gcv.foreground = fg;
1153 /* Hack -- Handle XOR (xor is code 6) by hacking bg and fg */
1154 if (op == 6) gcv.background = 0;
1155 if (op == 6) gcv.foreground = (bg ^ fg);
1157 /* Assign the proper GC Fill Style */
1158 gcv.fill_style = (stip ? FillStippled : FillSolid);
1160 /* Turn off 'Give exposure events for pixmap copying' */
1161 gcv.graphics_exposures = False;
1163 /* Set up the GC mask */
1164 gc_mask = (GCFunction | GCBackground | GCForeground |
1165 GCFillStyle | GCGraphicsExposures);
1167 /* Create the GC detailed above */
1168 gc = XCreateGC(Metadpy->dpy, Metadpy->root, gc_mask, &gcv);
1171 /*** Initialize ***/
1173 /* Wipe the iclr clean */
1174 (void)WIPE(iclr, infoclr);
1179 /* Nuke it when done */
1182 /* Assign the parms */
1186 iclr->stip = stip ? 1 : 0;
1195 * Change the 'fg' for an infoclr
1198 * fg: The Pixell for the requested Foreground (see above)
1200 static errr Infoclr_change_fg(Pixell fg)
1202 infoclr *iclr = Infoclr;
1205 /*** Simple error checking of opr and clr ***/
1207 /* Check the 'Pixells' for realism */
1208 if (fg > Metadpy->zg) return (-1);
1214 XSetForeground(Metadpy->dpy, iclr->gc, fg);
1222 #ifndef IGNORE_UNUSED_FUNCTIONS
1225 * Nuke an old 'infofnt'.
1227 static errr Infofnt_nuke(void)
1229 infofnt *ifnt = Infofnt;
1232 infofnt *ikfnt = Infokfnt;
1234 /* Deal with 'name' */
1238 string_free(ifnt->name);
1245 string_free(ikfnt->name);
1248 /* Nuke info if needed */
1252 XFreeFont(Metadpy->dpy, ifnt->info);
1259 XFreeFont(Metadpy->dpy, ikfnt->info);
1266 #endif /* IGNORE_UNUSED_FUNCTIONS */
1270 * Prepare a new 'infofnt'
1273 static errr Infofnt_prepare(XFontStruct *info, XFontStruct *kinfo)
1276 static errr Infofnt_prepare(XFontSet info)
1278 static errr Infofnt_prepare(XFontStruct *info)
1283 infofnt *ifnt = Infofnt;
1286 infofnt *ikfnt = Infokfnt;
1290 XFontStruct **fontinfo;
1293 int ascent, descent, width;
1296 /* Assign the struct */
1300 n_fonts = XFontsOfFontSet(info, &fontinfo, &fontname);
1302 ascent = descent = width = 0;
1303 while(n_fonts-- > 0){
1304 cs = &((*fontinfo)->max_bounds);
1305 if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
1306 if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
1307 if(((*fontinfo)->max_byte1) > 0){
1308 /* ¿¥Ð¥¤¥Èʸ»ú¤Î¾ì¹ç¤ÏÉýȾʬ(ü¿ôÀÚ¤ê¾å¤²)¤Çɾ²Á¤¹¤ë */
1309 if(width < (cs->width+1)/2) width = (cs->width+1)/2;
1311 if(width < cs->width) width = cs->width;
1317 ifnt->hgt = ascent + descent;
1320 /* Jump into the max bouonds thing */
1321 cs = &(info->max_bounds);
1323 /* Extract default sizing info */
1324 ifnt->asc = info->ascent;
1325 ifnt->hgt = info->ascent + info->descent;
1326 ifnt->wid = cs->width;
1330 ifnt->twid = 2 * ifnt->wid;
1332 ifnt->twid = ifnt->wid;
1335 /* Assign the struct */
1336 ikfnt->info = kinfo;
1338 /* Jump into the max bouonds thing */
1339 cs = &(kinfo->max_bounds);
1341 /* Extract default sizing info */
1342 ikfnt->asc = kinfo->ascent;
1343 ikfnt->hgt = kinfo->ascent + kinfo->descent;
1344 ikfnt->wid = cs->width;
1347 #ifdef OBSOLETE_SIZING_METHOD
1348 /* Extract default sizing info */
1349 ifnt->asc = cs->ascent;
1350 ifnt->hgt = (cs->ascent + cs->descent);
1351 ifnt->wid = cs->width;
1360 #ifndef IGNORE_UNUSED_FUNCTIONS
1363 * Initialize a new 'infofnt'.
1366 static errr Infofnt_init_real(XFontStruct *info, XFontStruct *kinfo)
1369 static errr Infofnt_init_real(XFontSet info)
1371 static errr Infofnt_init_real(XFontStruct *info)
1376 /* Wipe the thing */
1377 (void)WIPE(Infofnt, infofnt);
1380 WIPE(Infokfnt, infofnt);
1388 /* Attempt to prepare it */
1390 return (Infofnt_prepare (info, kinfo));
1392 return (Infofnt_prepare(info));
1397 #endif /* IGNORE_UNUSED_FUNCTIONS */
1401 * Init an infofnt by its Name
1404 * name: The name of the requested Font
1407 static void Infofnt_init_data(cptr name, cptr kname)
1409 static void Infofnt_init_data(cptr name)
1415 char **missing_list;
1426 /*** Load the info Fresh, using the name ***/
1428 /* If the name is not given, report an error */
1429 if (!name || !*name) quit("Missing font!");
1432 if (!kname || !*kname) quit("Missing kanji font!");
1434 /* Attempt to load the font */
1436 info = XCreateFontSet(Metadpy->dpy, name, &missing_list, &missing_count, &default_font);
1437 if(missing_count > 0){
1438 printf("missing font(s): \n");
1439 while(missing_count-- > 0){
1440 printf("\t%s\n", missing_list[missing_count]);
1442 XFreeStringList(missing_list);
1445 info = XLoadQueryFont(Metadpy->dpy, name);
1447 kinfo = XLoadQueryFont(Metadpy->dpy, kname);
1452 /* The load failed, try to recover */
1453 if (!info) quit_fmt("Failed to find font:\"%s\"", name);
1455 if (!kinfo) quit_fmt("Failed to find font:\"%s\"", kname);
1460 /*** Init the font ***/
1462 /* Wipe the thing */
1463 (void)WIPE(Infofnt, infofnt);
1466 WIPE(Infokfnt, infofnt);
1468 /* Attempt to prepare it */
1470 if (Infofnt_prepare(info, kinfo))
1472 if (Infofnt_prepare(info))
1478 XFreeFontSet(Metadpy->dpy, info);
1480 XFreeFont(Metadpy->dpy, info);
1482 XFreeFont(Metadpy->dpy, kinfo);
1486 quit_fmt("Failed to prepare font:\"%s\"", name);
1489 /* Save a copy of the font name */
1490 Infofnt->name = string_make(name);
1492 Infokfnt->name = string_make(kname);
1495 /* Mark it as nukable */
1505 * EUCÆüËܸ쥳¡¼¥É¤ò´Þ¤àʸ»úÎó¤òɽ¼¨¤¹¤ë (Xlib)
1508 XDrawMultiString(display,d,gc, x, y, string, len, afont,
1509 afont_width, afont_height, afont_ascent, kfont, kfont_width)
1517 int afont_width, afont_height, afont_ascent;
1524 unsigned char *endp;
1527 endp = string + len;
1529 while ( str < endp && *str ) {
1532 if ( (*str) == 0x7f ) {
1534 /* 0x7F¤Ï¢£¤Ç·è¤áÂǤÁ */
1536 /* Ϣ³¤¹¤ë0x7F¤ÎŤµ¤ò¸¡½Ð */
1538 while ( str < endp && (*str) == 0x7f ) {
1544 XFillRectangle( display, d, gc, x, y-afont_ascent,
1545 slen * afont_width, afont_height);
1547 /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1548 x += afont_width * slen;
1552 if ( iskanji(*str) ) {
1556 /* Ϣ³¤¹¤ëUJISʸ»ú¤ÎŤµ¤ò¸¡½Ð */
1558 while ( str < endp && *str && iskanji(*str) ) {
1559 kanji[slen].byte1 = *str++ & 0x7f;
1560 kanji[slen++].byte2 = *str++ & 0x7f;
1564 XSetFont( display, gc, kfont->fid );
1565 XDrawImageString16( display, d, gc, x, y, kanji, slen );
1568 /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1569 x += kfont_width * slen;
1573 /* Èó´Á»ú(=ASCII¤È²¾Äê)¤Î»Ï¤Þ¤ê */
1575 /* Ϣ³¤¹¤ëASCIIʸ»ú¤ò¸¡½Ð */
1578 while ( str < endp && *str && !iskanji(*str) ) {
1580 if (*str == 0x7f)break;
1587 XSetFont( display, gc, afont->fid );
1588 XDrawImageString( display, d, gc, x, y, p, slen );
1590 /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1591 x += afont_width * slen;
1600 static errr Infofnt_text_std(int x, int y, cptr str, int len)
1605 /*** Do a brief info analysis ***/
1607 /* Do nothing if the string is null */
1608 if (!str || !*str) return (-1);
1610 /* Get the length of the string */
1611 if (len < 0) len = strlen(str);
1613 /*** Decide where to place the string, vertically ***/
1615 /* Ignore Vertical Justifications */
1616 y = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
1619 /*** Decide where to place the string, horizontally ***/
1621 /* Line up with x at left edge of column 'x' */
1622 x = (x * Infofnt->wid) + Infowin->ox;
1625 /*** Actually draw 'str' onto the infowin ***/
1629 /* Be sure the correct font is ready */
1630 XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
1634 /*** Handle the fake mono we can enforce on fonts ***/
1636 /* Monotize the font */
1640 /* Be sure the correct font is ready */
1641 XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
1643 /* Do each character */
1644 for (i = 0; i < len; ++i)
1646 /* Note that the Infoclr is set up to contain the Infofnt */
1647 XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1648 x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
1652 /* Assume monoospaced font */
1655 /* Note that the Infoclr is set up to contain the Infofnt */
1657 /* ´Á»ú¥Õ¥©¥ó¥È¤Îɽ¼¨Éý¤Ï ASCII¥Õ¥©¥ó¥È¤Î2Çܤ˸ÇÄê */
1658 XDrawMultiString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1660 Infofnt->info, Infofnt->wid, Infofnt->hgt,
1662 Infokfnt->info, Infofnt->wid * 2);
1665 XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info,
1666 Infoclr->gc, x, y, str, len);
1668 XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1682 * Painting where text would be
1684 static errr Infofnt_text_non(int x, int y, cptr str, int len)
1689 /*** Find the width ***/
1691 /* Negative length is a flag to count the characters in str */
1692 if (len < 0) len = strlen(str);
1694 /* The total width will be 'len' chars * standard width */
1695 w = len * Infofnt->wid;
1698 /*** Find the X dimensions ***/
1700 /* Line up with x at left edge of column 'x' */
1701 x = x * Infofnt->wid + Infowin->ox;
1704 /*** Find other dimensions ***/
1706 /* Simply do 'Infofnt->hgt' (a single row) high */
1709 /* Simply do "at top" in row 'y' */
1710 y = y * h + Infowin->oy;
1713 /*** Actually 'paint' the area ***/
1715 /* Just do a Fill Rectangle */
1716 XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, x, y, w, h);
1724 /*************************************************************************/
1728 * Angband specific code follows... (ANGBAND)
1733 * Hack -- cursor color
1735 static infoclr *xor;
1738 * Actual color table
1740 static infoclr *clr[256];
1743 * Color info (unused, red, green, blue).
1745 static byte color_table[256][4];
1750 typedef struct term_data term_data;
1753 * A structure for each "term"
1771 #ifdef USE_TRANSPARENCY
1773 /* Tempory storage for overlaying tiles. */
1784 * The number of term data structures
1786 #define MAX_TERM_DATA 8
1789 * The array of term data structures
1791 static term_data data[MAX_TERM_DATA];
1794 /* Use short names for the most commonly used elements of various structures. */
1795 #define DPY (Metadpy->dpy)
1796 #define WIN (Infowin->win)
1799 /* Describe a set of co-ordinates. */
1800 typedef struct co_ord co_ord;
1809 * A special structure to store information about the text currently
1812 typedef struct x11_selection_type x11_selection_type;
1813 struct x11_selection_type
1815 bool select; /* The selection is currently in use. */
1816 bool drawn; /* The selection is currently displayed. */
1817 term *t; /* The window where the selection is found. */
1818 co_ord init; /* The starting co-ordinates. */
1819 co_ord cur; /* The end co-ordinates (the current ones if still copying). */
1820 co_ord old; /* The previous end co-ordinates. */
1821 Time time; /* The time at which the selection was finalised. */
1824 static x11_selection_type s_ptr[1];
1828 * Process a keypress event
1830 * Also appears in "main-xaw.c".
1832 static void react_keypress(XKeyEvent *xev)
1834 int i, n, mc, ms, mo, mx;
1838 XKeyEvent *ev = (XKeyEvent*)(xev);
1846 int valid_keysym = TRUE;
1849 /* Check for "normal" keypresses */
1851 if(Focuswin && Focuswin->xic){
1853 n = XmbLookupString(Focuswin->xic, ev, buf, 125, &ks, &status);
1854 if(status == XBufferOverflow){
1855 printf("Input is too long, and dropped\n");
1858 if(status != XLookupKeySym && status != XLookupBoth){
1859 valid_keysym = FALSE;
1862 n = XLookupString(ev, buf, 125, &ks, NULL);
1865 n = XLookupString(ev, buf, 125, &ks, NULL);
1873 /* Enqueue the normal key(s) */
1874 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1881 /* Hack -- Ignore "modifier keys" */
1882 if (IsModifierKey(ks)) return;
1885 /* Hack -- convert into an unsigned int */
1888 /* Extract four "modifier flags" */
1889 mc = (ev->state & ControlMask) ? TRUE : FALSE;
1890 ms = (ev->state & ShiftMask) ? TRUE : FALSE;
1891 mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
1892 mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
1895 /* Normal keys with no modifiers */
1896 if (n && !mo && !mx && !IsSpecialKey(ks))
1898 /* Enqueue the normal key(s) */
1899 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1906 /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */
1911 Term_keypress(ESCAPE);
1917 Term_keypress('\r');
1923 Term_keypress('\t');
1929 Term_keypress(0x7f);
1934 Term_keypress('\010');
1940 /* Hack -- Use the KeySym */
1943 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
1944 mc ? "N" : "", ms ? "S" : "",
1945 mo ? "O" : "", mx ? "M" : "",
1946 (unsigned long)(ks), 13);
1949 /* Hack -- Use the Keycode */
1952 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
1953 mc ? "N" : "", ms ? "S" : "",
1954 mo ? "O" : "", mx ? "M" : "",
1958 /* Enqueue the "macro trigger" string */
1959 for (i = 0; msg[i]; i++) Term_keypress(msg[i]);
1962 /* Hack -- auto-define macros as needed */
1963 if (n && (macro_find_exact(msg) < 0))
1965 /* Create a macro */
1966 macro_add(msg, buf);
1972 * Find the square a particular pixel is part of.
1974 static void pixel_to_square(int * const x, int * const y,
1975 const int ox, const int oy)
1977 (*x) = (ox - Infowin->ox) / Infofnt->wid;
1978 (*y) = (oy - Infowin->oy) / Infofnt->hgt;
1982 * Find the pixel at the top-left corner of a square.
1984 static void square_to_pixel(int * const x, int * const y,
1985 const int ox, const int oy)
1987 (*x) = ox * Infofnt->wid + Infowin->ox;
1988 (*y) = oy * Infofnt->hgt + Infowin->oy;
1992 * Convert co-ordinates from starting corner/opposite corner to minimum/maximum.
1994 static void sort_co_ord(co_ord *min, co_ord *max,
1995 const co_ord *b, const co_ord *a)
1997 min->x = MIN(a->x, b->x);
1998 min->y = MIN(a->y, b->y);
1999 max->x = MAX(a->x, b->x);
2000 max->y = MAX(a->y, b->y);
2004 * Remove the selection by redrawing it.
2006 static void mark_selection_clear(int x1, int y1, int x2, int y2)
2008 Term_redraw_section(x1,y1,x2,y2);
2012 * Select an area by drawing a grey box around it.
2013 * NB. These two functions can cause flicker as the selection is modified,
2014 * as the game redraws the entire marked section.
2016 static void mark_selection_mark(int x1, int y1, int x2, int y2)
2018 square_to_pixel(&x1, &y1, x1, y1);
2019 square_to_pixel(&x2, &y2, x2, y2);
2020 XDrawRectangle(Metadpy->dpy, Infowin->win, clr[2]->gc, x1, y1,
2021 x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
2025 * Mark a selection by drawing boxes around it (for now).
2027 static void mark_selection(void)
2031 bool draw = s_ptr->select;
2032 bool clear = s_ptr->drawn;
2034 /* Open the correct term if necessary. */
2035 if (s_ptr->t != old) Term_activate(s_ptr->t);
2039 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->old);
2040 mark_selection_clear(min.x, min.y, max.x, max.y);
2044 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
2045 mark_selection_mark(min.x, min.y, max.x, max.y);
2048 /* Finish on the current term. */
2049 if (s_ptr->t != old) Term_activate(old);
2051 s_ptr->old.x = s_ptr->cur.x;
2052 s_ptr->old.y = s_ptr->cur.y;
2053 s_ptr->drawn = s_ptr->select;
2057 * Forget a selection for one reason or another.
2059 static void copy_x11_release(void)
2061 /* Deselect the current selection. */
2062 s_ptr->select = FALSE;
2064 /* Remove its graphical represesntation. */
2069 * Start to select some text on the screen.
2071 static void copy_x11_start(int x, int y)
2073 if (s_ptr->select) copy_x11_release();
2075 /* Remember where the selection started. */
2077 s_ptr->init.x = s_ptr->cur.x = s_ptr->old.x = x;
2078 s_ptr->init.y = s_ptr->cur.y = s_ptr->old.y = y;
2082 * Respond to movement of the mouse when selecting text.
2084 static void copy_x11_cont(int x, int y, unsigned int buttons)
2086 /* Use the nearest square within bounds if the mouse is outside. */
2087 x = MIN(MAX(x, 0), Term->wid-1);
2088 y = MIN(MAX(y, 0), Term->hgt-1);
2090 /* The left mouse button isn't pressed. */
2091 if (~buttons & Button1Mask) return;
2093 /* Not a selection in this window. */
2094 if (s_ptr->t != Term) return;
2096 /* Not enough movement. */
2097 if (x == s_ptr->old.x && y == s_ptr->old.y && s_ptr->select) return;
2099 /* Something is being selected. */
2100 s_ptr->select = TRUE;
2102 /* Track the selection. */
2106 /* Hack - display it inefficiently. */
2111 * Respond to release of the left mouse button by putting the selected text in
2112 * the primary buffer.
2114 static void copy_x11_end(const Time time)
2117 if (!s_ptr->select) return;
2119 /* Not a selection in this window. */
2120 if (s_ptr->t != Term) return;
2122 /* Remember when the selection was finalised. */
2125 /* Acquire the primary selection. */
2126 XSetSelectionOwner(Metadpy->dpy, XA_PRIMARY, Infowin->win, time);
2127 if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) != Infowin->win)
2129 /* Failed to acquire the selection, so forget it. */
2130 /* bell("Failed to acquire primary buffer."); */
2131 s_ptr->select = FALSE;
2137 * Send a message to request that the PRIMARY buffer be sent here.
2139 static void paste_x11_request(const Time time)
2141 /* Check the owner. */
2142 if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) == None)
2145 /* bell("No selection found."); */
2149 /* Request the event as a STRING. */
2150 XConvertSelection(DPY, XA_PRIMARY, XA_STRING, XA_STRING, WIN, time);
2154 * Add a character to a string in preparation for sending it to another
2155 * client as a STRING.
2156 * This doesn't change anything, as clients tend not to have difficulty in
2157 * receiving this format (although the standard specifies a restricted set).
2158 * Strings do not have a colour.
2160 static int add_char_string(char *buf, byte a, char c)
2168 static bool paste_x11_send_text(XSelectionRequestEvent *rq, int (*add)(char *, byte, char))
2176 /* Too old, or incorrect call. */
2177 if (rq->time < s_ptr->time || !add) return FALSE;
2179 /* Work out which way around to paste. */
2180 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
2183 if (XGetSelectionOwner(DPY, XA_PRIMARY) != WIN)
2185 /* bell("Someone stole my selection!"); */
2189 /* Delete the old value of the property. */
2190 XDeleteProperty(DPY, rq->requestor, rq->property);
2192 for (y = 0; y < Term->hgt; y++)
2194 if (y < min.y) continue;
2195 if (y > max.y) break;
2197 for (x = l = 0; x < Term->wid; x++)
2199 if (x < min.x) continue;
2200 if (x > max.x) break;
2202 /* Find the character. */
2203 Term_what(x, y, &a, &c);
2206 l += (*add)(buf+l, a, c);
2210 /* Terminate all but the last line in an appropriate way. */
2211 if (y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n');
2213 /* Terminate all line unless single line message. */
2214 if (min.y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n');
2217 /* Send the (non-empty) string. */
2218 XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
2219 PropModeAppend, (byte*)buf, l);
2224 static Atom xa_targets, xa_timestamp;
2227 * Set the required variable atoms at start-up to avoid errors later.
2229 static void set_atoms(void)
2231 xa_targets = XInternAtom(DPY, "TARGETS", False);
2232 xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
2236 * Send some text requested by another X client.
2238 static void paste_x11_send(XSelectionRequestEvent *rq)
2241 XSelectionEvent *ptr = &(event.xselection);
2243 /* Set the event parameters. */
2244 ptr->type = SelectionNotify;
2245 ptr->property = rq->property;
2246 ptr->display = rq->display;
2247 ptr->requestor = rq->requestor;
2248 ptr->selection = rq->selection;
2249 ptr->target = rq->target;
2250 ptr->time = rq->time;
2252 /* Paste the appropriate information for each target type.
2253 * Note that this currently rejects MULTIPLE targets.
2256 if (rq->target == XA_STRING)
2258 if (!paste_x11_send_text(rq, add_char_string))
2259 ptr->property = None;
2261 else if (rq->target == xa_targets)
2263 Atom target_list[2];
2264 target_list[0] = XA_STRING;
2265 target_list[1] = xa_targets;
2266 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
2267 (8 * sizeof(target_list[0])), PropModeReplace,
2268 (unsigned char *)target_list,
2269 (sizeof(target_list) / sizeof(target_list[0])));
2271 else if (rq->target == xa_timestamp)
2273 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
2274 (8 * sizeof(Time)), PropModeReplace,
2275 (unsigned char *)s_ptr->time, 1);
2279 ptr->property = None;
2282 /* Send whatever event we're left with. */
2283 XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
2287 * Add the contents of the PRIMARY buffer to the input queue.
2289 * Hack - This doesn't use the "time" of the event, and so accepts anything a
2290 * client tries to send it.
2292 static void paste_x11_accept(const XSelectionEvent *ptr)
2294 unsigned long offset, left;
2297 if (ptr->property == None)
2299 /* bell("Paste failure (remote client could not send)."); */
2303 if (ptr->selection != XA_PRIMARY)
2305 /* bell("Paste failure (remote client did not send primary selection)."); */
2309 if (ptr->target != XA_STRING)
2311 /* bell("Paste failure (selection in unknown format)."); */
2315 for (offset = 0; ; offset += left)
2319 /* A pointer for the pasted information. */
2320 unsigned char *data;
2324 unsigned long nitems;
2326 /* Set data to the string, and catch errors. */
2327 if (XGetWindowProperty(Metadpy->dpy, Infowin->win, XA_STRING, offset,
2328 32767, TRUE, XA_STRING, &type, &fmt, &nitems, &left, &data)
2331 /* Paste the text. */
2332 err = type_string((char*)data, nitems);
2334 /* Free the data pasted. */
2338 if (err == PARSE_ERROR_OUT_OF_MEMORY)
2340 /* bell("Paste failure (too much text selected)."); */
2343 /* Paranoia? - strange errors. */
2349 /* Pasted everything. */
2353 /* An error has occurred, so free the last bit of data before returning. */
2358 * Handle various events conditional on presses of a mouse button.
2360 static void handle_button(Time time, int x, int y, int button,
2363 /* The co-ordinates are only used in Angband format. */
2364 pixel_to_square(&x, &y, x, y);
2366 if (press && button == 1) copy_x11_start(x, y);
2367 if (!press && button == 1) copy_x11_end(time);
2368 if (!press && button == 2) paste_x11_request(time);
2375 static errr CheckEvent(bool wait)
2377 term_data *old_td = (term_data*)(Term->data);
2379 XEvent xev_body, *xev = &xev_body;
2381 term_data *td = NULL;
2382 infowin *iwin = NULL;
2390 /* Do not wait unless requested */
2391 if (!wait && !XPending(Metadpy->dpy)) return (1);
2394 * Hack - redraw the selection, if needed.
2395 * This doesn't actually check that one of its squares was drawn to,
2396 * only that this may have happened.
2398 if (s_ptr->select && !s_ptr->drawn) mark_selection();
2400 /* Load the Event */
2401 XNextEvent(Metadpy->dpy, xev);
2404 /* #define DEBUG_EVENT */
2407 printf("event: type=%d", xev->type);
2410 printf("(KeyPress), keycode=%X", xev->xkey.keycode);
2413 printf("(FocusIn)");
2416 printf("(FocusOut)");
2418 case ReparentNotify:
2419 printf("(ReparentNotify)");
2421 case ConfigureNotify:
2422 printf("(ConfigureNotify)");
2425 printf("(MapNotify)");
2431 printf("(ClientMessage)");
2437 if (XFilterEvent(xev, xev->xany.window)
2438 /*XFilterEvent(xev, (data[0].win)->win)*/){
2440 printf(", [filtered by IM]\n");
2442 goto redo_checkevent;
2449 /* Notice new keymaps */
2450 if (xev->type == MappingNotify)
2452 XRefreshKeyboardMapping(&xev->xmapping);
2457 /* Scan the windows */
2458 for (i = 0; i < MAX_TERM_DATA; i++)
2460 if (!data[i].win) continue;
2461 if (xev->xany.window == data[i].win->win)
2469 /* Unknown window */
2470 if (!td || !iwin) return (0);
2473 /* Hack -- activate the Term */
2474 Term_activate(&td->t);
2476 /* Hack -- activate the window */
2480 /* Switch on the Type */
2486 bool press = (xev->type == ButtonPress);
2488 /* Where is the mouse */
2489 int x = xev->xbutton.x;
2490 int y = xev->xbutton.y;
2494 /* Which button is involved */
2495 if (xev->xbutton.button == Button1) z = 1;
2496 else if (xev->xbutton.button == Button2) z = 2;
2497 else if (xev->xbutton.button == Button3) z = 3;
2498 else if (xev->xbutton.button == Button4) z = 4;
2499 else if (xev->xbutton.button == Button5) z = 5;
2503 handle_button(xev->xbutton.time, x, y, z, press);
2518 /* Where is the mouse */
2519 int x = xev->xmotion.x;
2520 int y = xev->xmotion.y;
2521 unsigned int z = xev->xmotion.state;
2523 /* Convert to co-ordinates Angband understands. */
2524 pixel_to_square(&x, &y, x, y);
2526 /* Highlight the current square, if appropriate. */
2527 /* highlight_square(window, y, x); */
2529 /* Alter the selection if appropriate. */
2530 copy_x11_cont(x, y, z);
2537 case SelectionNotify:
2539 paste_x11_accept(&(xev->xselection));
2543 case SelectionRequest:
2545 paste_x11_send(&(xev->xselectionrequest));
2549 case SelectionClear:
2551 s_ptr->select = FALSE;
2564 /* Hack -- use "old" term */
2565 Term_activate(&old_td->t);
2567 /* Process the key */
2568 react_keypress(&(xev->xkey));
2577 /* Ignore "extra" exposes */
2578 /*if (xev->xexpose.count) break;*/
2580 /* Clear the window */
2583 x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
2584 x2 = (xev->xexpose.x + xev->xexpose.width -
2585 Infowin->ox)/Infofnt->wid;
2587 y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
2588 y2 = (xev->xexpose.y + xev->xexpose.height -
2589 Infowin->oy)/Infofnt->hgt;
2591 Term_redraw_section(x1, y1, x2, y2);
2601 Infowin->mapped = 1;
2602 Term->mapped_flag = TRUE;
2608 Infowin->mapped = 0;
2609 Term->mapped_flag = FALSE;
2613 /* Move and/or Resize */
2614 case ConfigureNotify:
2616 int cols, rows, wid, hgt;
2618 int ox = Infowin->ox;
2619 int oy = Infowin->oy;
2621 /* Save the new Window Parms */
2622 Infowin->x = xev->xconfigure.x;
2623 Infowin->y = xev->xconfigure.y;
2624 Infowin->w = xev->xconfigure.width;
2625 Infowin->h = xev->xconfigure.height;
2627 /* Determine "proper" number of rows/cols */
2628 cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
2629 rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
2631 /* Hack -- minimal size */
2632 if (cols < 1) cols = 1;
2633 if (rows < 1) rows = 1;
2637 /* Hack the main window must be at least 80x24 */
2638 if (cols < 80) cols = 80;
2639 if (rows < 24) rows = 24;
2642 /* Desired size of window */
2643 wid = cols * td->fnt->wid + (ox + ox);
2644 hgt = rows * td->fnt->hgt + (oy + oy);
2646 /* Resize the Term (if needed) */
2647 Term_resize(cols, rows);
2649 /* Resize the windows if any "change" is needed */
2650 if ((Infowin->w != wid) || (Infowin->h != hgt))
2653 Infowin_set(td->win);
2654 Infowin_resize(wid, hgt);
2663 XSetICFocus(iwin->xic);
2671 XUnsetICFocus(iwin->xic);
2673 /* Focuswin = NULL;*/
2680 /* Hack -- Activate the old term */
2681 Term_activate(&old_td->t);
2683 /* Hack -- Activate the proper window */
2684 Infowin_set(old_td->win);
2695 * An array of sound file names
2697 static cptr sound_file[SOUND_MAX];
2700 * Check for existance of a file
2702 static bool check_file(cptr s)
2706 fff = fopen(s, "r");
2707 if (!fff) return (FALSE);
2716 static void init_sound(void)
2721 char dir_xtra_sound[1024];
2723 /* Build the "sound" path */
2724 path_build(dir_xtra_sound, sizeof(dir_xtra_sound), ANGBAND_DIR_XTRA, "sound");
2726 /* Prepare the sounds */
2727 for (i = 1; i < SOUND_MAX; i++)
2729 /* Extract name of sound file */
2730 sprintf(wav, "%s.wav", angband_sound_name[i]);
2732 /* Access the sound */
2733 path_build(buf, sizeof(buf), dir_xtra_sound, wav);
2735 /* Save the sound filename, if it exists */
2736 if (check_file(buf)) sound_file[i] = string_make(buf);
2743 * Hack -- make a sound
2745 static errr Term_xtra_x11_sound(int v)
2749 /* Sound disabled */
2750 if (!use_sound) return (1);
2753 if ((v < 0) || (v >= SOUND_MAX)) return (1);
2756 if (!sound_file[v]) return (1);
2758 sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
2764 #endif /* USE_SOUND */
2768 * Handle "activation" of a term
2770 static errr Term_xtra_x11_level(int v)
2772 term_data *td = (term_data*)(Term->data);
2774 /* Handle "activate" */
2777 /* Activate the window */
2778 Infowin_set(td->win);
2780 /* Activate the font */
2781 Infofnt_set(td->fnt);
2783 Infokfnt_set(td->kfnt);
2795 static errr Term_xtra_x11_react(void)
2801 /* Check the colors */
2802 for (i = 0; i < 256; i++)
2804 if ((color_table[i][0] != angband_color_table[i][0]) ||
2805 (color_table[i][1] != angband_color_table[i][1]) ||
2806 (color_table[i][2] != angband_color_table[i][2]) ||
2807 (color_table[i][3] != angband_color_table[i][3]))
2811 /* Save new values */
2812 color_table[i][0] = angband_color_table[i][0];
2813 color_table[i][1] = angband_color_table[i][1];
2814 color_table[i][2] = angband_color_table[i][2];
2815 color_table[i][3] = angband_color_table[i][3];
2818 pixel = create_pixel(Metadpy->dpy,
2823 /* Change the foreground */
2824 Infoclr_set(clr[i]);
2825 Infoclr_change_fg(pixel);
2836 * Handle a "special request"
2838 static errr Term_xtra_x11(int n, int v)
2840 /* Handle a subset of the legal requests */
2844 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
2847 /* Make a special sound */
2848 case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
2851 /* Flush the output XXX XXX */
2852 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
2854 /* Process random events XXX */
2855 case TERM_XTRA_BORED: return (CheckEvent(0));
2857 /* Process Events XXX */
2858 case TERM_XTRA_EVENT: return (CheckEvent(v));
2860 /* Flush the events XXX */
2861 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
2863 /* Handle change in the "level" */
2864 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
2866 /* Clear the screen */
2867 case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
2869 /* Delay for some milliseconds */
2870 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
2872 /* React to changes */
2873 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
2882 * Draw the cursor as an inverted rectangle.
2884 * Consider a rectangular outline like "main-mac.c". XXX XXX
2886 static errr Term_curs_x11(int x, int y)
2890 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2891 x * Infofnt->wid + Infowin->ox,
2892 y * Infofnt->hgt + Infowin->oy,
2893 Infofnt->wid - 1, Infofnt->hgt - 1);
2894 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2895 x * Infofnt->wid + Infowin->ox + 1,
2896 y * Infofnt->hgt + Infowin->oy + 1,
2897 Infofnt->wid - 3, Infofnt->hgt - 3);
2901 /* Draw the cursor */
2904 /* Hilite the cursor character */
2905 Infofnt_text_non(x, y, " ", 1);
2914 * Draw the double width cursor
2916 static errr Term_bigcurs_x11(int x, int y)
2920 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2921 x * Infofnt->wid + Infowin->ox,
2922 y * Infofnt->hgt + Infowin->oy,
2923 Infofnt->twid - 1, Infofnt->hgt - 1);
2924 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2925 x * Infofnt->wid + Infowin->ox + 1,
2926 y * Infofnt->hgt + Infowin->oy + 1,
2927 Infofnt->twid - 3, Infofnt->hgt - 3);
2931 /* Draw the cursor */
2934 /* Hilite the cursor character */
2935 Infofnt_text_non(x, y, " ", 2);
2943 * Erase some characters.
2945 static errr Term_wipe_x11(int x, int y, int n)
2947 /* Erase (use black) */
2948 Infoclr_set(clr[TERM_DARK]);
2950 /* Mega-Hack -- Erase some space */
2951 Infofnt_text_non(x, y, "", n);
2953 /* Redraw the selection if any, as it may have been obscured. (later) */
2954 s_ptr->drawn = FALSE;
2962 * Draw some textual characters.
2964 static errr Term_text_x11(int x, int y, int n, byte a, cptr s)
2967 Infoclr_set(clr[a]);
2970 Infofnt_text_std(x, y, s, n);
2972 /* Redraw the selection if any, as it may have been obscured. (later) */
2973 s_ptr->drawn = FALSE;
2983 * Draw some graphical characters.
2985 # ifdef USE_TRANSPARENCY
2986 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
2987 # else /* USE_TRANSPARENCY */
2988 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
2989 # endif /* USE_TRANSPARENCY */
2996 #ifdef USE_TRANSPARENCY
3003 unsigned long pixel, blank;
3004 #endif /* USE_TRANSPARENCY */
3006 term_data *td = (term_data*)(Term->data);
3011 /* Add in affect of window boundaries */
3015 for (i = 0; i < n; ++i, x += td->fnt->wid)
3020 /* For extra speed - cache these values */
3021 x1 = (c&0x7F) * td->fnt->twid;
3022 y1 = (a&0x7F) * td->fnt->hgt;
3024 /* Illegal tile index */
3025 if (td->tiles->width < x1 + td->fnt->wid ||
3026 td->tiles->height < y1 + td->fnt->hgt)
3028 /* Draw black square */
3029 XFillRectangle(Metadpy->dpy, td->win->win, clr[0]->gc,
3031 td->fnt->twid, td->fnt->hgt);
3033 /* Skip drawing tile */
3037 #ifdef USE_TRANSPARENCY
3042 /* For extra speed - cache these values */
3043 x2 = (tc&0x7F) * td->fnt->twid;
3044 y2 = (ta&0x7F) * td->fnt->hgt;
3046 /* Optimise the common case */
3047 if (((x1 == x2) && (y1 == y2)) ||
3048 !(((byte)ta & 0x80) && ((byte)tc & 0x80)) ||
3049 td->tiles->width < x2 + td->fnt->wid ||
3050 td->tiles->height < y2 + td->fnt->hgt)
3052 /* Draw object / terrain */
3053 XPutImage(Metadpy->dpy, td->win->win,
3058 td->fnt->twid, td->fnt->hgt);
3063 /* Mega Hack^2 - assume the top left corner is "black" */
3064 blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
3066 for (k = 0; k < td->fnt->twid; k++)
3068 for (l = 0; l < td->fnt->hgt; l++)
3070 /* If mask set... */
3071 if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
3073 /* Output from the terrain */
3074 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
3077 /* Store into the temp storage. */
3078 XPutPixel(td->TmpImage, k, l, pixel);
3083 /* Draw to screen */
3085 XPutImage(Metadpy->dpy, td->win->win,
3089 td->fnt->twid, td->fnt->hgt);
3092 #else /* USE_TRANSPARENCY */
3094 /* Draw object / terrain */
3095 XPutImage(Metadpy->dpy, td->win->win,
3100 td->fnt->twid, td->fnt->hgt);
3102 #endif /* USE_TRANSPARENCY */
3105 /* Redraw the selection if any, as it may have been obscured. (later) */
3106 s_ptr->drawn = FALSE;
3112 #endif /* USE_GRAPHICS */
3115 static void IMDestroyCallback(XIM, XPointer, XPointer);
3118 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
3121 XIMCallback ximcallback;
3122 XIMStyles *xim_styles = NULL;
3129 xim = XOpenIM(display, NULL, NULL, NULL);
3131 printf("can't open IM\n");
3135 /* initialize destroy callback */
3136 ximcallback.callback = IMDestroyCallback;
3137 ximcallback.client_data = NULL;
3138 XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
3140 /* set style (only "Root" is supported yet...) */
3141 XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
3142 for (i = 0; i < xim_styles->count_styles; i++){
3143 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
3145 if(i >= xim_styles->count_styles){
3146 printf("Sorry, your IM does not support 'Root' preedit style...\n");
3154 for (i = 0; i < MAX_TERM_DATA; i++)
3156 infowin *iwin = data[i].win;
3157 if (!iwin) continue;
3158 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
3160 printf("Can't create input context for Term%d\n", i);
3163 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL){
3164 /* printf("Can't get XNFilterEvents\n"); */
3165 iwin->xic_mask = 0L;
3167 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
3173 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
3181 if (call_data == NULL){
3182 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3185 for(i = 0; i < MAX_TERM_DATA; i++)
3187 infowin *iwin = data[i].win;
3190 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
3191 iwin->xic_mask = 0L;
3196 Metadpy->xim = NULL;
3201 * Initialize a term_data
3203 static errr term_data_init(term_data *td, int i)
3207 cptr name = angband_term_name[i];
3242 /* Window specific font name */
3243 sprintf(buf, "ANGBAND_X11_FONT_%d", i);
3245 /* Check environment for that font */
3248 /* Check environment for "base" font */
3249 if (!font) font = getenv("ANGBAND_X11_FONT");
3251 /* No environment variables, use default font */
3258 font = DEFAULT_X11_FONT_0;
3263 font = DEFAULT_X11_FONT_1;
3268 font = DEFAULT_X11_FONT_2;
3273 font = DEFAULT_X11_FONT_3;
3278 font = DEFAULT_X11_FONT_4;
3283 font = DEFAULT_X11_FONT_5;
3288 font = DEFAULT_X11_FONT_6;
3293 font = DEFAULT_X11_FONT_7;
3298 font = DEFAULT_X11_FONT;
3304 /* Window specific font name */
3305 sprintf(buf, "ANGBAND_X11_KFONT_%d", i);
3307 /* Check environment for that font */
3308 kfont = getenv(buf);
3310 /* Check environment for "base" font */
3311 if (!kfont) kfont = getenv("ANGBAND_X11_KFONT");
3313 /* No environment variables, use default font */
3320 kfont = DEFAULT_X11_KFONT_0;
3325 kfont = DEFAULT_X11_KFONT_1;
3330 kfont = DEFAULT_X11_KFONT_2;
3335 kfont = DEFAULT_X11_KFONT_3;
3340 kfont = DEFAULT_X11_KFONT_4;
3345 kfont = DEFAULT_X11_KFONT_5;
3350 kfont = DEFAULT_X11_KFONT_6;
3355 kfont = DEFAULT_X11_KFONT_7;
3360 kfont = DEFAULT_X11_KFONT;
3365 /* Window specific location (x) */
3366 sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
3368 x = (str != NULL) ? atoi(str) : -1;
3370 /* Window specific location (y) */
3371 sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
3373 y = (str != NULL) ? atoi(str) : -1;
3376 /* Window specific cols */
3377 sprintf(buf, "ANGBAND_X11_COLS_%d", i);
3379 val = (str != NULL) ? atoi(str) : -1;
3380 if (val > 0) cols = val;
3382 /* Window specific rows */
3383 sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
3385 val = (str != NULL) ? atoi(str) : -1;
3386 if (val > 0) rows = val;
3388 /* Hack the main window must be at least 80x24 */
3391 if (cols < 80) cols = 80;
3392 if (rows < 24) rows = 24;
3395 /* Window specific inner border offset (ox) */
3396 sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
3398 val = (str != NULL) ? atoi(str) : -1;
3399 if (val > 0) ox = val;
3401 /* Window specific inner border offset (oy) */
3402 sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
3404 val = (str != NULL) ? atoi(str) : -1;
3405 if (val > 0) oy = val;
3408 /* Prepare the standard font */
3410 MAKE(td->fnt, infofnt);
3411 Infofnt_set(td->fnt);
3412 MAKE(td->kfnt, infofnt);
3413 Infokfnt_set(td->kfnt);
3414 Infofnt_init_data(font, kfont);
3416 MAKE(td->fnt, infofnt);
3417 Infofnt_set(td->fnt);
3418 Infofnt_init_data(font);
3422 /* Hack -- key buffer size */
3423 num = ((i == 0) ? 1024 : 16);
3425 /* Assume full size windows */
3426 wid = cols * td->fnt->wid + (ox + ox);
3427 hgt = rows * td->fnt->hgt + (oy + oy);
3429 /* Create a top-window */
3430 MAKE(td->win, infowin);
3431 Infowin_set(td->win);
3432 Infowin_init_top(x, y, wid, hgt, 0,
3433 Metadpy->fg, Metadpy->bg);
3435 /* Ask for certain events */
3436 #if defined(USE_XIM)
3437 Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask);
3439 Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
3442 /* Set the window name */
3443 Infowin_set_name(name);
3445 /* Save the inner border */
3449 /* Make Class Hints */
3450 ch = XAllocClassHint();
3452 if (ch == NULL) quit("XAllocClassHint failed");
3454 strcpy(res_name, name);
3455 res_name[0] = FORCELOWER(res_name[0]);
3456 ch->res_name = res_name;
3458 strcpy(res_class, "Angband");
3459 ch->res_class = res_class;
3461 XSetClassHint(Metadpy->dpy, Infowin->win, ch);
3463 /* Make Size Hints */
3464 sh = XAllocSizeHints();
3467 if (sh == NULL) quit("XAllocSizeHints failed");
3469 /* Main window has a differing minimum size */
3472 /* Main window min size is 80x24 */
3473 sh->flags = PMinSize | PMaxSize;
3474 sh->min_width = 80 * td->fnt->wid + (ox + ox);
3475 sh->min_height = 24 * td->fnt->hgt + (oy + oy);
3476 sh->max_width = 255 * td->fnt->wid + (ox + ox);
3477 sh->max_height = 255 * td->fnt->hgt + (oy + oy);
3480 /* Other windows can be shrunk to 1x1 */
3484 sh->flags = PMinSize | PMaxSize;
3485 sh->min_width = td->fnt->wid + (ox + ox);
3486 sh->min_height = td->fnt->hgt + (oy + oy);
3487 sh->max_width = 256 * td->fnt->wid + (ox + ox);
3488 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
3491 /* Resize increment */
3492 sh->flags |= PResizeInc;
3493 sh->width_inc = td->fnt->wid;
3494 sh->height_inc = td->fnt->hgt;
3496 /* Base window size */
3497 sh->flags |= PBaseSize;
3498 sh->base_width = (ox + ox);
3499 sh->base_height = (oy + oy);
3501 /* Use the size hints */
3502 XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
3504 /* Map the window */
3509 wh = XAllocWMHints();
3510 if(wh == NULL) quit("XAllocWMHints failed");
3511 wh->flags = InputHint;
3513 XSetWMHints(Metadpy->dpy, Infowin->win, wh);
3516 /* Move the window to requested location */
3517 if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
3520 /* Initialize the term */
3521 term_init(t, cols, rows, num);
3523 /* Use a "soft" cursor */
3524 t->soft_cursor = TRUE;
3526 /* Erase with "white space" */
3527 t->attr_blank = TERM_WHITE;
3528 t->char_blank = ' ';
3531 t->xtra_hook = Term_xtra_x11;
3532 t->curs_hook = Term_curs_x11;
3533 t->bigcurs_hook = Term_bigcurs_x11;
3534 t->wipe_hook = Term_wipe_x11;
3535 t->text_hook = Term_text_x11;
3540 /* Activate (important) */
3549 * Initialization function for an "X11" module to Angband
3551 errr init_x11(int argc, char *argv[])
3561 char filename[1024];
3566 #ifdef USE_TRANSPARENCY
3569 #endif /* USE_TRANSPARENCY */
3571 #endif /* USE_GRAPHICS */
3575 for (i = 1; i < argc; i++)
3577 if (prefix(argv[i], "-d"))
3579 dpy_name = &argv[i][2];
3584 if (prefix(argv[i], "-s"))
3586 smoothRescaling = FALSE;
3590 if (prefix(argv[i], "-a"))
3592 arg_graphics = GRAPHICS_ADAM_BOLT;
3596 if (prefix(argv[i], "-o"))
3598 arg_graphics = GRAPHICS_ORIGINAL;
3602 if (prefix(argv[i], "-b"))
3604 arg_bigtile = use_bigtile = TRUE;
3607 #endif /* USE_GRAPHICS */
3609 if (prefix(argv[i], "-n"))
3611 num_term = atoi(&argv[i][2]);
3612 if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
3613 else if (num_term < 1) num_term = 1;
3617 if (prefix(argv[i], "--"))
3623 plog_fmt("Ignoring option: %s", argv[i]);
3627 setlocale(LC_ALL, "");
3628 #ifdef DEFAULT_LOCALE
3629 if(!strcmp(setlocale(LC_ALL, NULL), "C")){
3630 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
3631 setlocale(LC_ALL, DEFAULT_LOCALE);
3635 char *current_locale = setlocale(LC_ALL, NULL);
3636 /* printf("set locale to \"%s\"\n", current_locale); */
3637 if(!strcmp(current_locale, "C")){
3638 printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
3642 if(!XSupportsLocale()){
3643 printf("can't support locale in X\n");
3644 setlocale(LC_ALL, "C");
3646 #endif /* USE_LOCALE */
3649 /* Init the Metadpy if possible */
3650 if (Metadpy_init_name(dpy_name)) return (-1);
3653 /* Prepare cursor color */
3656 Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
3659 /* Prepare normal colors */
3660 for (i = 0; i < 256; ++i)
3664 MAKE(clr[i], infoclr);
3666 Infoclr_set(clr[i]);
3668 /* Acquire Angband colors */
3669 color_table[i][0] = angband_color_table[i][0];
3670 color_table[i][1] = angband_color_table[i][1];
3671 color_table[i][2] = angband_color_table[i][2];
3672 color_table[i][3] = angband_color_table[i][3];
3674 /* Default to monochrome */
3675 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
3681 pixel = create_pixel(Metadpy->dpy,
3687 /* Initialize the color */
3688 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
3692 /* Prepare required atoms. */
3696 /* Initialize the windows */
3697 for (i = 0; i < num_term; i++)
3699 term_data *td = &data[i];
3701 /* Initialize the term_data */
3702 term_data_init(td, i);
3704 /* Save global entry */
3705 angband_term[i] = Term;
3708 /* Raise the "Angband" window */
3709 Infowin_set(data[0].win);
3712 /* Activate the "Angband" window screen */
3713 Term_activate(&data[0].t);
3718 p = XSetLocaleModifiers("");
3720 p = XSetLocaleModifiers("@im=");
3722 /* printf("XMODIFIERS=\"%s\"\n", p); */
3724 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3728 /* initialize sound */
3729 if (arg_sound) init_sound();
3735 switch (arg_graphics)
3737 case GRAPHICS_ORIGINAL:
3738 /* Try the "8x8.bmp" file */
3739 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/8x8.bmp");
3741 /* Use the "8x8.bmp" file if it exists */
3742 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3745 use_graphics = TRUE;
3747 pict_wid = pict_hgt = 8;
3749 ANGBAND_GRAF = "old";
3754 case GRAPHICS_ADAM_BOLT:
3755 /* Try the "16x16.bmp" file */
3756 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/16x16.bmp");
3758 /* Use the "16x16.bmp" file if it exists */
3759 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3762 use_graphics = TRUE;
3764 pict_wid = pict_hgt = 16;
3766 ANGBAND_GRAF = "new";
3775 Display *dpy = Metadpy->dpy;
3779 /* Load the graphical tiles */
3780 tiles_raw = ReadBMP(dpy, filename);
3782 /* Initialize the windows */
3783 for (i = 0; i < num_term; i++)
3785 term_data *td = &data[i];
3790 t->pict_hook = Term_pict_x11;
3792 /* Use graphics sometimes */
3793 t->higher_pict = TRUE;
3797 ResizeImage(dpy, tiles_raw,
3799 td->fnt->twid, td->fnt->hgt);
3802 #ifdef USE_TRANSPARENCY
3803 /* Initialize the transparency masks */
3804 for (i = 0; i < num_term; i++)
3806 term_data *td = &data[i];
3808 int depth = DefaultDepth(dpy, DefaultScreen(dpy));
3809 Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
3813 /* Determine total bytes needed for image */
3815 jj = (depth - 1) >> 2;
3816 while (jj >>= 1) ii <<= 1;
3817 total = td->fnt->twid * td->fnt->hgt * ii;
3820 TmpData = (char *)malloc(total);
3822 td->TmpImage = XCreateImage(dpy,visual,depth,
3823 ZPixmap, 0, TmpData,
3824 td->fnt->twid, td->fnt->hgt, 8, 0);
3827 #endif /* USE_TRANSPARENCY */
3830 /* Free tiles_raw? XXX XXX */
3833 #endif /* USE_GRAPHICS */
3840 #endif /* USE_X11 */