1 /* File: main-x11.c */
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.
13 * This file helps Angband work with UNIX/X11 computers.
15 * To use this file, compile with "USE_X11" defined, and link against all
16 * the various "X11" libraries which may be needed.
18 * See also "main-xaw.c".
20 * Part of this file provides a user interface package composed of several
21 * pseudo-objects, including "metadpy" (a display), "infowin" (a window),
22 * "infoclr" (a color), and "infofnt" (a font). Actually, the package was
23 * originally much more interesting, but it was bastardized to keep this
26 * The rest of this file is an implementation of "main-xxx.c" for X11.
28 * Most of this file is by Ben Harrison (benh@phial.com).
32 * The following shell script can be used to launch Angband, assuming that
33 * it was extracted into "~/Angband", and compiled using "USE_X11", on a
34 * Linux machine, with a 1280x1024 screen, using 6 windows (with the given
35 * characteristics), with gamma correction of 1.8 -> (1 / 1.8) * 256 = 142,
36 * and without graphics (add "-g" for graphics). Just copy this comment
37 * into a file, remove the leading " * " characters (and the head/tail of
38 * this comment), and make the file executable.
44 * echo "Launching angband..."
48 * setenv ANGBAND_X11_FONT_0 10x20
49 * setenv ANGBAND_X11_AT_X_0 5
50 * setenv ANGBAND_X11_AT_Y_0 510
53 * setenv ANGBAND_X11_FONT_1 8x13
54 * setenv ANGBAND_X11_AT_X_1 5
55 * setenv ANGBAND_X11_AT_Y_1 22
56 * setenv ANGBAND_X11_ROWS_1 35
59 * setenv ANGBAND_X11_FONT_2 8x13
60 * setenv ANGBAND_X11_AT_X_2 635
61 * setenv ANGBAND_X11_AT_Y_2 182
62 * setenv ANGBAND_X11_ROWS_3 23
65 * setenv ANGBAND_X11_FONT_3 8x13
66 * setenv ANGBAND_X11_AT_X_3 635
67 * setenv ANGBAND_X11_AT_Y_3 22
68 * setenv ANGBAND_X11_ROWS_3 12
70 * # Monster recall window
71 * setenv ANGBAND_X11_FONT_4 6x13
72 * setenv ANGBAND_X11_AT_X_4 817
73 * setenv ANGBAND_X11_AT_Y_4 847
74 * setenv ANGBAND_X11_COLS_4 76
75 * setenv ANGBAND_X11_ROWS_4 11
77 * # Object recall window
78 * setenv ANGBAND_X11_FONT_5 6x13
79 * setenv ANGBAND_X11_AT_X_5 817
80 * setenv ANGBAND_X11_AT_Y_5 520
81 * setenv ANGBAND_X11_COLS_5 76
82 * setenv ANGBAND_X11_ROWS_5 24
84 * # The build directory
88 * setenv ANGBAND_X11_GAMMA 142
91 * ./src/angband -mx11 -- -n6 &
103 * Available graphic modes
105 #define GRAPHICS_NONE 0
106 #define GRAPHICS_ORIGINAL 1
107 #define GRAPHICS_ADAM_BOLT 2
108 #define GRAPHICS_HENGBAND 3
112 #ifndef __MAKEDEPEND__
113 #include <X11/Xlib.h>
114 #include <X11/Xutil.h>
115 #include <X11/keysym.h>
116 #include <X11/keysymdef.h>
118 #include <X11/Xlocale.h>
120 #include <X11/Xatom.h>
121 #endif /* __MAKEDEPEND__ */
125 * Include some helpful X11 code.
127 #include "maid-x11.c"
131 * Hack -- avoid some compiler warnings
133 #define IGNORE_UNUSED_FUNCTIONS
139 * 1) On a monochrome (or "fake-monochrome") display, all colors
140 * will be "cast" to "fg," except for the bg color, which is,
141 * obviously, cast to "bg". Thus, one can ignore this setting.
143 * 2) Because of the inner functioning of the color allocation
144 * routines, colors may be specified as (a) a typical color name,
145 * (b) a hexidecimal color specification (preceded by a pound sign),
146 * or (c) by strings such as "fg", "bg", "zg".
148 * 3) Due to the workings of the init routines, many colors
149 * may also be dealt with by their actual pixel values. Note that
150 * the pixel with all bits set is "zg = (1<<metadpy->depth)-1", which
151 * is not necessarily either black or white.
156 /**** Generic Types ****/
160 * An X11 pixell specifier
162 typedef unsigned long Pixell;
165 * The structures defined below
167 typedef struct metadpy metadpy;
168 typedef struct infowin infowin;
169 typedef struct infoclr infoclr;
170 typedef struct infofnt infofnt;
174 * A structure summarizing a given Display.
176 * - The Display itself
177 * - The default Screen for the display
178 * - The virtual root (usually just the root)
179 * - The default colormap (from a macro)
181 * - The "name" of the display
183 * - The socket to listen to for events
185 * - The width of the display screen (from a macro)
186 * - The height of the display screen (from a macro)
187 * - The bit depth of the display screen (from a macro)
189 * - The black Pixell (from a macro)
190 * - The white Pixell (from a macro)
192 * - The background Pixell (default: black)
193 * - The foreground Pixell (default: white)
194 * - The maximal Pixell (Equals: ((2 ^ depth)-1), is usually ugly)
196 * - Bit Flag: Force all colors to black and white (default: !color)
197 * - Bit Flag: Allow the use of color (default: depth > 1)
198 * - Bit Flag: We created 'dpy', and so should nuke it when done.
233 * A Structure summarizing Window Information.
235 * I assume that a window is at most 30000 pixels on a side.
236 * I assume that the root windw is also at most 30000 square.
239 * - The current Input Event Mask
241 * - The location of the window
242 * - The width, height of the window
243 * - The border width of this window
245 * - Byte: 1st Extra byte
247 * - Bit Flag: This window is currently Mapped
248 * - Bit Flag: This window needs to be redrawn
249 * - Bit Flag: This window has been resized
251 * - Bit Flag: We should nuke 'win' when done with it
253 * - Bit Flag: 1st extra flag
254 * - Bit Flag: 2nd extra flag
255 * - Bit Flag: 3rd extra flag
256 * - Bit Flag: 4th extra flag
294 * A Structure summarizing Operation+Color Information
296 * - The actual GC corresponding to this info
298 * - The Foreground Pixell Value
299 * - The Background Pixell Value
301 * - Num (0-15): The operation code (As in Clear, Xor, etc)
302 * - Bit Flag: The GC is in stipple mode
303 * - Bit Flag: Destroy 'gc' at Nuke time.
320 * A Structure to Hold Font Information
322 * - The 'XFontStruct*' (yields the 'Font')
326 * - The default character width
327 * - The default character height
328 * - The default character ascent
330 * - Byte: Pixel offset used during fake mono
332 * - Flag: Force monospacing via 'wid'
333 * - Flag: Nuke info when done
354 /**** Generic Macros ****/
358 /* Set current metadpy (Metadpy) to 'M' */
359 #define Metadpy_set(M) \
363 /* Initialize 'M' using Display 'D' */
364 #define Metadpy_init_dpy(D) \
365 Metadpy_init_2(D,cNULL)
367 /* Initialize 'M' using a Display named 'N' */
368 #define Metadpy_init_name(N) \
369 Metadpy_init_2((Display*)(NULL),N)
371 /* Initialize 'M' using the standard Display */
372 #define Metadpy_init() \
373 Metadpy_init_name("")
376 /* Init an infowin by giving father as an (info_win*) (or NULL), and data */
377 #define Infowin_init_dad(D,X,Y,W,H,B,FG,BG) \
378 Infowin_init_data(((D) ? ((D)->win) : (Window)(None)), \
382 /* Init a top level infowin by pos,size,bord,Colors */
383 #define Infowin_init_top(X,Y,W,H,B,FG,BG) \
384 Infowin_init_data(None,X,Y,W,H,B,FG,BG)
387 /* Request a new standard window by giving Dad infowin and X,Y,W,H */
388 #define Infowin_init_std(D,X,Y,W,H,B) \
389 Infowin_init_dad(D,X,Y,W,H,B,Metadpy->fg,Metadpy->bg)
392 /* Set the current Infowin */
393 #define Infowin_set(I) \
397 /* Set the current Infoclr */
398 #define Infoclr_set(C) \
402 #define Infoclr_init_ppo(F,B,O,M) \
403 Infoclr_init_data(F,B,O,M)
405 #define Infoclr_init_cco(F,B,O,M) \
406 Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M)
408 #define Infoclr_init_ppn(F,B,O,M) \
409 Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M)
411 #define Infoclr_init_ccn(F,B,O,M) \
412 Infoclr_init_cco(F,B,Infoclr_Opcode(O),M)
415 /* Set the current infofnt */
416 #define Infofnt_set(I) \
420 /* Errr: Expose Infowin */
421 #define Infowin_expose() \
422 (!(Infowin->redraw = 1))
424 /* Errr: Unxpose Infowin */
425 #define Infowin_unexpose() \
426 (Infowin->redraw = 0)
430 /**** Generic Globals ****/
434 * The "default" values
436 static metadpy metadpy_default;
440 * The "current" variables
442 static metadpy *Metadpy = &metadpy_default;
443 static infowin *Infowin = (infowin*)(NULL);
445 static infowin *Focuswin = (infowin*)(NULL);
447 static infoclr *Infoclr = (infoclr*)(NULL);
448 static infofnt *Infofnt = (infofnt*)(NULL);
450 /**** Generic code ****/
453 * Init the current metadpy, with various initialization stuff.
456 * dpy: The Display* to use (if NULL, create it)
457 * name: The name of the Display (if NULL, the current)
460 * If 'name' is NULL, but 'dpy' is set, extract name from dpy
461 * If 'dpy' is NULL, then Create the named Display
462 * If 'name' is NULL, and so is 'dpy', use current Display
464 * Return -1 if no Display given, and none can be opened.
466 static errr Metadpy_init_2(Display *dpy, concptr name)
468 metadpy *m = Metadpy;
470 /*** Open the display if needed ***/
472 /* If no Display given, attempt to Create one */
475 /* Attempt to open the display */
476 dpy = XOpenDisplay(name);
479 if (!dpy) return (-1);
481 /* We will have to nuke it when done */
485 /* Since the Display was given, use it */
488 /* We will not have to nuke it when done */
493 /*** Save some information ***/
495 /* Save the Display itself */
498 /* Get the Screen and Virtual Root Window */
499 m->screen = DefaultScreenOfDisplay(dpy);
500 m->root = RootWindowOfScreen(m->screen);
502 /* Get the default colormap */
503 m->cmap = DefaultColormapOfScreen(m->screen);
505 /* Extract the true name of the display */
506 m->name = DisplayString(dpy);
509 m->fd = ConnectionNumber(Metadpy->dpy);
511 /* Save the Size and Depth of the screen */
512 m->width = WidthOfScreen(m->screen);
513 m->height = HeightOfScreen(m->screen);
514 m->depth = DefaultDepthOfScreen(m->screen);
516 /* Save the Standard Colors */
517 m->black = BlackPixelOfScreen(m->screen);
518 m->white = WhitePixelOfScreen(m->screen);
520 /*** Make some clever Guesses ***/
522 /* Guess at the desired 'fg' and 'bg' Pixell's */
526 /* Calculate the Maximum allowed Pixel value. */
527 m->zg = (1 << m->depth) - 1;
529 /* Save various default Flag Settings */
530 m->color = ((m->depth > 1) ? 1 : 0);
531 m->mono = ((m->color) ? 0 : 1);
533 /* Return "success" */
538 #ifndef IGNORE_UNUSED_FUNCTIONS
541 * Nuke the current metadpy
543 static errr Metadpy_nuke(void)
545 metadpy *m = Metadpy;
548 /* If required, Free the Display */
551 /* Close the Display */
552 XCloseDisplay(m->dpy);
554 /* Forget the Display */
555 m->dpy = (Display*)(NULL);
557 /* Do not nuke it again */
565 #endif /* IGNORE_UNUSED_FUNCTIONS */
569 * General Flush/ Sync/ Discard routine
571 static errr Metadpy_update(int flush, int sync, int discard)
573 /* Flush if desired */
574 if (flush) XFlush(Metadpy->dpy);
576 /* Sync if desired, using 'discard' */
577 if (sync) XSync(Metadpy->dpy, discard);
587 static errr Metadpy_do_beep(void)
589 /* Make a simple beep */
590 XBell(Metadpy->dpy, 100);
598 * Set the name (in the title bar) of Infowin
600 static errr Infowin_set_name(concptr name)
607 st = XStringListToTextProperty(&bp, 1, &tp);
608 if (st) XSetWMName(Metadpy->dpy, Infowin->win, &tp);
613 #ifndef IGNORE_UNUSED_FUNCTIONS
616 * Set the icon name of Infowin
618 static errr Infowin_set_icon_name(concptr name)
625 st = XStringListToTextProperty(&bp, 1, &tp);
626 if (st) XSetWMIconName(Metadpy->dpy, Infowin->win, &tp);
634 static errr Infowin_nuke(void)
636 infowin *iwin = Infowin;
638 /* Nuke if requested */
641 /* Destory the old window */
642 XDestroyWindow(Metadpy->dpy, iwin->win);
649 #endif /* IGNORE_UNUSED_FUNCTIONS */
653 * Prepare a new 'infowin'.
655 static errr Infowin_prepare(Window xid)
657 infowin *iwin = Infowin;
660 XWindowAttributes xwa;
662 unsigned int w, h, b, d;
667 /* Check For Error XXX Extract some ACTUAL data from 'xid' */
668 XGetGeometry(Metadpy->dpy, xid, &tmp_win, &x, &y, &w, &h, &b, &d);
670 /* Apply the above info */
677 /* Check Error XXX Extract some more ACTUAL data */
678 XGetWindowAttributes(Metadpy->dpy, xid, &xwa);
680 /* Apply the above info */
681 iwin->mask = xwa.your_event_mask;
682 iwin->mapped = ((xwa.map_state == IsUnmapped) ? 0 : 1);
684 /* And assume that we are exposed */
692 #ifndef IGNORE_UNUSED_FUNCTIONS
695 * Initialize a new 'infowin'.
697 static errr Infowin_init_real(Window xid)
700 (void)WIPE(Infowin, infowin);
702 /* Start out non-nukable */
705 /* Attempt to Prepare ourself */
706 return (Infowin_prepare(xid));
709 #endif /* IGNORE_UNUSED_FUNCTIONS */
713 * Init an infowin by giving some data.
716 * dad: The Window that should own this Window (if any)
717 * x,y: The position of this Window
718 * w,h: The size of this Window
719 * b,d: The border width and pixel depth
722 * If 'dad == None' assume 'dad == root'
724 static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
725 int b, Pixell fg, Pixell bg)
730 (void)WIPE(Infowin, infowin);
733 /*** Error Check XXX ***/
736 /*** Create the Window 'xid' from data ***/
738 /* What happened here? XXX XXX XXX */
740 /* If no parent given, depend on root */
743 /* Create the Window XXX Error Check */
744 xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg, bg);
746 /* Start out selecting No events */
747 XSelectInput(Metadpy->dpy, xid, 0L);
750 /*** Prepare the new infowin ***/
752 /* Mark it as nukable */
755 /* Attempt to Initialize the infowin */
756 return (Infowin_prepare(xid));
762 * Modify the event mask of an Infowin
764 static errr Infowin_set_mask(long mask)
766 /* Save the new setting */
767 Infowin->mask = mask;
769 /* Execute the Mapping */
770 XSelectInput(Metadpy->dpy, Infowin->win, Infowin->mask);
778 * Request that Infowin be mapped
780 static errr Infowin_map(void)
782 /* Execute the Mapping */
783 XMapWindow(Metadpy->dpy, Infowin->win);
790 #ifndef IGNORE_UNUSED_FUNCTIONS
793 * Request that Infowin be unmapped
795 static errr Infowin_unmap(void)
797 /* Execute the Un-Mapping */
798 XUnmapWindow(Metadpy->dpy, Infowin->win);
804 #endif /* IGNORE_UNUSED_FUNCTIONS */
808 * Request that Infowin be raised
810 static errr Infowin_raise(void)
812 /* Raise towards visibility */
813 XRaiseWindow(Metadpy->dpy, Infowin->win);
820 #ifndef IGNORE_UNUSED_FUNCTIONS
823 * Request that Infowin be lowered
825 static errr Infowin_lower(void)
827 /* Lower towards invisibility */
828 XLowerWindow(Metadpy->dpy, Infowin->win);
834 #endif /* IGNORE_UNUSED_FUNCTIONS */
838 * Request that Infowin be moved to a new location
840 static errr Infowin_impell(int x, int y)
842 /* Execute the request */
843 XMoveWindow(Metadpy->dpy, Infowin->win, x, y);
853 static errr Infowin_resize(int w, int h)
855 /* Execute the request */
856 XResizeWindow(Metadpy->dpy, Infowin->win, w, h);
863 #ifndef IGNORE_UNUSED_FUNCTIONS
866 * Move and Resize an infowin
868 static errr Infowin_locate(int x, int y, int w, int h)
870 /* Execute the request */
871 XMoveResizeWindow(Metadpy->dpy, Infowin->win, x, y, w, h);
877 #endif /* IGNORE_UNUSED_FUNCTIONS */
881 * Visually clear Infowin
883 static errr Infowin_wipe(void)
885 /* Execute the request */
886 XClearWindow(Metadpy->dpy, Infowin->win);
893 #ifndef IGNORE_UNUSED_FUNCTIONS
896 * Visually Paint Infowin with the current color
898 static errr Infowin_fill(void)
900 /* Execute the request */
901 XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc,
902 0, 0, Infowin->w, Infowin->h);
908 #endif /* IGNORE_UNUSED_FUNCTIONS */
912 * A NULL terminated pair list of legal "operation names"
914 * Pairs of values, first is texttual name, second is the string
915 * holding the decimal value that the operation corresponds to.
917 static concptr opcode_pairs[] =
936 "+copyInverted", "12",
944 * Parse a word into an operation "code"
947 * str: A string, hopefully representing an Operation
950 * 0-15: if 'str' is a valid Operation
951 * -1: if 'str' could not be parsed
953 static int Infoclr_Opcode(concptr str)
957 /* Scan through all legal operation names */
958 for (i = 0; opcode_pairs[i*2]; ++i)
960 /* Is this the right oprname? */
961 if (streq(opcode_pairs[i*2], str))
963 /* Convert the second element in the pair into a Code */
964 return (atoi(opcode_pairs[i*2+1]));
968 /* The code was not found, return -1 */
973 #ifndef IGNORE_UNUSED_FUNCTIONS
976 * Request a Pixell by name. Note: uses 'Metadpy'.
979 * name: The name of the color to try to load (see below)
982 * The Pixell value that metched the given name
983 * 'Metadpy->fg' if the name was unparseable
985 * Valid forms for 'name':
986 * 'fg', 'bg', 'zg', '<name>' and '#<code>'
988 static Pixell Infoclr_Pixell(concptr name)
992 /* Attempt to Parse the name */
995 /* The 'bg' color is available */
996 if (streq(name, "bg")) return (Metadpy->bg);
998 /* The 'fg' color is available */
999 if (streq(name, "fg")) return (Metadpy->fg);
1001 /* The 'zg' color is available */
1002 if (streq(name, "zg")) return (Metadpy->zg);
1004 /* The 'white' color is available */
1005 if (streq(name, "white")) return (Metadpy->white);
1007 /* The 'black' color is available */
1008 if (streq(name, "black")) return (Metadpy->black);
1010 /* Attempt to parse 'name' into 'scrn' */
1011 if (!(XParseColor(Metadpy->dpy, Metadpy->cmap, name, &scrn)))
1013 plog_fmt("Warning: Couldn't parse color '%s'\n", name);
1016 /* Attempt to Allocate the Parsed color */
1017 if (!(XAllocColor(Metadpy->dpy, Metadpy->cmap, &scrn)))
1019 plog_fmt("Warning: Couldn't allocate color '%s'\n", name);
1022 /* The Pixel was Allocated correctly */
1023 else return (scrn.pixel);
1026 /* Warn about the Default being Used */
1027 plog_fmt("Warning: Using 'fg' for unknown color '%s'\n", name);
1029 /* Default to the 'Foreground' color */
1030 return (Metadpy->fg);
1035 * Initialize a new 'infoclr' with a real GC.
1037 static errr Infoclr_init_1(GC gc)
1039 infoclr *iclr = Infoclr;
1041 /* Wipe the iclr clean */
1042 (void)WIPE(iclr, infoclr);
1053 * Nuke an old 'infoclr'.
1055 static errr Infoclr_nuke(void)
1057 infoclr *iclr = Infoclr;
1059 /* Deal with 'GC' */
1063 XFreeGC(Metadpy->dpy, iclr->gc);
1066 /* Forget the current */
1067 Infoclr = (infoclr*)(NULL);
1073 #endif /* IGNORE_UNUSED_FUNCTIONS */
1077 * Initialize an infoclr with some data
1080 * fg: The Pixell for the requested Foreground (see above)
1081 * bg: The Pixell for the requested Background (see above)
1082 * op: The Opcode for the requested Operation (see above)
1083 * stip: The stipple mode
1085 static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
1087 infoclr *iclr = Infoclr;
1091 unsigned long gc_mask;
1095 /*** Simple error checking of opr and clr ***/
1097 /* Check the 'Pixells' for realism */
1098 if (bg > Metadpy->zg) return (-1);
1099 if (fg > Metadpy->zg) return (-1);
1101 /* Check the data for trueness */
1102 if ((op < 0) || (op > 15)) return (-1);
1105 /*** Create the requested 'GC' ***/
1107 /* Assign the proper GC function */
1110 /* Assign the proper GC background */
1111 gcv.background = bg;
1113 /* Assign the proper GC foreground */
1114 gcv.foreground = fg;
1116 /* Hack -- Handle XOR (xor is code 6) by hacking bg and fg */
1117 if (op == 6) gcv.background = 0;
1118 if (op == 6) gcv.foreground = (bg ^ fg);
1120 /* Assign the proper GC Fill Style */
1121 gcv.fill_style = (stip ? FillStippled : FillSolid);
1123 /* Turn off 'Give exposure events for pixmap copying' */
1124 gcv.graphics_exposures = False;
1126 /* Set up the GC mask */
1127 gc_mask = (GCFunction | GCBackground | GCForeground |
1128 GCFillStyle | GCGraphicsExposures);
1130 /* Create the GC detailed above */
1131 gc = XCreateGC(Metadpy->dpy, Metadpy->root, gc_mask, &gcv);
1134 /*** Initialize ***/
1136 /* Wipe the iclr clean */
1137 (void)WIPE(iclr, infoclr);
1142 /* Nuke it when done */
1145 /* Assign the parms */
1149 iclr->stip = stip ? 1 : 0;
1158 * Change the 'fg' for an infoclr
1161 * fg: The Pixell for the requested Foreground (see above)
1163 static errr Infoclr_change_fg(Pixell fg)
1165 infoclr *iclr = Infoclr;
1168 /*** Simple error checking of opr and clr ***/
1170 /* Check the 'Pixells' for realism */
1171 if (fg > Metadpy->zg) return (-1);
1177 XSetForeground(Metadpy->dpy, iclr->gc, fg);
1185 #ifndef IGNORE_UNUSED_FUNCTIONS
1188 * Nuke an old 'infofnt'.
1190 static errr Infofnt_nuke(void)
1192 infofnt *ifnt = Infofnt;
1194 /* Deal with 'name' */
1198 string_free(ifnt->name);
1201 /* Nuke info if needed */
1205 XFreeFontSet(Metadpy->dpy, ifnt->info);
1212 #endif /* IGNORE_UNUSED_FUNCTIONS */
1216 * Prepare a new 'infofnt'
1218 static errr Infofnt_prepare(XFontSet info)
1220 infofnt *ifnt = Infofnt;
1223 XFontStruct **fontinfo;
1226 int ascent, descent, width;
1228 /* Assign the struct */
1231 n_fonts = XFontsOfFontSet(info, &fontinfo, &fontname);
1233 ascent = descent = width = 0;
1234 while(n_fonts-- > 0){
1235 cs = &((*fontinfo)->max_bounds);
1236 if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
1237 if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
1238 if(((*fontinfo)->max_byte1) > 0){
1239 /* 多バイト文字の場合は幅半分(端数切り上げ)で評価する */
1240 if(width < (cs->width+1)/2) width = (cs->width+1)/2;
1242 if(width < cs->width) width = cs->width;
1248 ifnt->hgt = ascent + descent;
1252 ifnt->twid = 2 * ifnt->wid;
1254 ifnt->twid = ifnt->wid;
1264 #ifndef IGNORE_UNUSED_FUNCTIONS
1267 * Initialize a new 'infofnt'.
1269 static errr Infofnt_init_real(XFontSet info)
1271 /* Wipe the thing */
1272 (void)WIPE(Infofnt, infofnt);
1277 /* Attempt to prepare it */
1278 return (Infofnt_prepare(info));
1281 #endif /* IGNORE_UNUSED_FUNCTIONS */
1285 * Init an infofnt by its Name
1288 * name: The name of the requested Font
1290 static void Infofnt_init_data(concptr name)
1294 char **missing_list;
1298 /*** Load the info Fresh, using the name ***/
1300 /* If the name is not given, report an error */
1301 if (!name || !*name) quit("Missing font!");
1303 /* Attempt to load the font */
1304 info = XCreateFontSet(Metadpy->dpy, name, &missing_list, &missing_count, &default_font);
1305 if(missing_count > 0){
1306 printf("missing font(s): \n");
1307 while(missing_count-- > 0){
1308 printf("\t%s\n", missing_list[missing_count]);
1310 XFreeStringList(missing_list);
1313 /* The load failed, try to recover */
1314 if (!info) quit_fmt("Failed to find font:\"%s\"", name);
1316 /*** Init the font ***/
1318 /* Wipe the thing */
1319 (void)WIPE(Infofnt, infofnt);
1321 /* Attempt to prepare it */
1322 if (Infofnt_prepare(info))
1325 XFreeFontSet(Metadpy->dpy, info);
1328 quit_fmt("Failed to prepare font:\"%s\"", name);
1331 /* Save a copy of the font name */
1332 Infofnt->name = string_make(name);
1334 /* Mark it as nukable */
1342 static errr Infofnt_text_std(int x, int y, concptr str, int len)
1347 /*** Do a brief info analysis ***/
1349 /* Do nothing if the string is null */
1350 if (!str || !*str) return (-1);
1352 /* Get the length of the string */
1353 if (len < 0) len = strlen(str);
1355 /*** Decide where to place the string, vertically ***/
1357 /* Ignore Vertical Justifications */
1358 y = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
1361 /*** Decide where to place the string, horizontally ***/
1363 /* Line up with x at left edge of column 'x' */
1364 x = (x * Infofnt->wid) + Infowin->ox;
1367 /*** Actually draw 'str' onto the infowin ***/
1369 /*** Handle the fake mono we can enforce on fonts ***/
1371 /* Monotize the font */
1374 /* Do each character */
1375 for (i = 0; i < len; ++i)
1377 /* Note that the Infoclr is set up to contain the Infofnt */
1378 XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1379 x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
1383 /* Assume monoospaced font */
1386 /* Note that the Infoclr is set up to contain the Infofnt */
1387 iconv_t cd = iconv_open("UTF-8", "EUC-JP");
1389 size_t outlen = len * 2;
1390 char *kanji = malloc(outlen);
1391 char *sp; char *kp = kanji;
1393 my_strcpy(sbuf, str, sizeof(sbuf));
1395 iconv(cd, &sp, &inlen, &kp, &outlen);
1398 XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info,
1399 Infoclr->gc, x, y, kanji, kp-kanji);
1409 * Painting where text would be
1411 static errr Infofnt_text_non(int x, int y, concptr str, int len)
1416 /*** Find the width ***/
1418 /* Negative length is a flag to count the characters in str */
1419 if (len < 0) len = strlen(str);
1421 /* The total width will be 'len' chars * standard width */
1422 w = len * Infofnt->wid;
1425 /*** Find the X dimensions ***/
1427 /* Line up with x at left edge of column 'x' */
1428 x = x * Infofnt->wid + Infowin->ox;
1431 /*** Find other dimensions ***/
1433 /* Simply do 'Infofnt->hgt' (a single row) high */
1436 /* Simply do "at top" in row 'y' */
1437 y = y * h + Infowin->oy;
1440 /*** Actually 'paint' the area ***/
1442 /* Just do a Fill Rectangle */
1443 XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, x, y, w, h);
1451 /*************************************************************************/
1455 * Angband specific code follows... (ANGBAND)
1460 * Hack -- cursor color
1462 static infoclr *xor;
1465 * Actual color table
1467 static infoclr *clr[256];
1470 * Color info (unused, red, green, blue).
1472 static byte color_table[256][4];
1477 typedef struct term_data term_data;
1480 * A structure for each "term"
1491 /* Tempory storage for overlaying tiles. */
1497 * The number of term data structures
1499 #define MAX_TERM_DATA 8
1502 * The array of term data structures
1504 static term_data data[MAX_TERM_DATA];
1507 /* Use short names for the most commonly used elements of various structures. */
1508 #define DPY (Metadpy->dpy)
1509 #define WIN (Infowin->win)
1512 /* Describe a set of co-ordinates. */
1513 typedef struct co_ord co_ord;
1522 * A special structure to store information about the text currently
1525 typedef struct x11_selection_type x11_selection_type;
1526 struct x11_selection_type
1528 bool select; /* The selection is currently in use. */
1529 bool drawn; /* The selection is currently displayed. */
1530 term *t; /* The window where the selection is found. */
1531 co_ord init; /* The starting co-ordinates. */
1532 co_ord cur; /* The end co-ordinates (the current ones if still copying). */
1533 co_ord old; /* The previous end co-ordinates. */
1534 Time time; /* The time at which the selection was finalised. */
1537 static x11_selection_type s_ptr[1];
1541 * Process a keypress event
1543 * Also appears in "main-xaw.c".
1545 static void react_keypress(XKeyEvent *xev)
1547 int i, n, mc, ms, mo, mx;
1551 XKeyEvent *ev = (XKeyEvent*)(xev);
1559 int valid_keysym = TRUE;
1562 /* Check for "normal" keypresses */
1564 if(Focuswin && Focuswin->xic){
1566 n = XmbLookupString(Focuswin->xic, ev, buf, 125, &ks, &status);
1567 if(status == XBufferOverflow){
1568 printf("Input is too long, and dropped\n");
1571 if(status != XLookupKeySym && status != XLookupBoth){
1572 valid_keysym = FALSE;
1575 n = XLookupString(ev, buf, 125, &ks, NULL);
1578 n = XLookupString(ev, buf, 125, &ks, NULL);
1586 /* Enqueue the normal key(s) */
1587 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1594 /* Hack -- Ignore "modifier keys" */
1595 if (IsModifierKey(ks)) return;
1598 /* Hack -- convert into an unsigned int */
1601 /* Extract four "modifier flags" */
1602 mc = (ev->state & ControlMask) ? TRUE : FALSE;
1603 ms = (ev->state & ShiftMask) ? TRUE : FALSE;
1604 mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
1605 mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
1608 /* Normal keys with no modifiers */
1609 if (n && !mo && !mx && !IsSpecialKey(ks))
1611 /* Enqueue the normal key(s) */
1612 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1619 /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */
1624 Term_keypress(ESCAPE);
1630 Term_keypress('\r');
1636 Term_keypress('\t');
1642 Term_keypress(0x7f);
1647 Term_keypress('\010');
1653 /* Hack -- Use the KeySym */
1656 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
1657 mc ? "N" : "", ms ? "S" : "",
1658 mo ? "O" : "", mx ? "M" : "",
1659 (unsigned long)(ks), 13);
1662 /* Hack -- Use the Keycode */
1665 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
1666 mc ? "N" : "", ms ? "S" : "",
1667 mo ? "O" : "", mx ? "M" : "",
1671 /* Enqueue the "macro trigger" string */
1672 for (i = 0; msg[i]; i++) Term_keypress(msg[i]);
1675 /* Hack -- auto-define macros as needed */
1676 if (n && (macro_find_exact(msg) < 0))
1678 /* Create a macro */
1679 macro_add(msg, buf);
1685 * Find the square a particular pixel is part of.
1687 static void pixel_to_square(int * const x, int * const y,
1688 const int ox, const int oy)
1690 (*x) = (ox - Infowin->ox) / Infofnt->wid;
1691 (*y) = (oy - Infowin->oy) / Infofnt->hgt;
1695 * Find the pixel at the top-left corner of a square.
1697 static void square_to_pixel(int * const x, int * const y,
1698 const int ox, const int oy)
1700 (*x) = ox * Infofnt->wid + Infowin->ox;
1701 (*y) = oy * Infofnt->hgt + Infowin->oy;
1705 * Convert co-ordinates from starting corner/opposite corner to minimum/maximum.
1707 static void sort_co_ord(co_ord *min, co_ord *max,
1708 const co_ord *b, const co_ord *a)
1710 min->x = MIN(a->x, b->x);
1711 min->y = MIN(a->y, b->y);
1712 max->x = MAX(a->x, b->x);
1713 max->y = MAX(a->y, b->y);
1717 * Remove the selection by redrawing it.
1719 static void mark_selection_clear(int x1, int y1, int x2, int y2)
1721 Term_redraw_section(x1,y1,x2,y2);
1725 * Select an area by drawing a grey box around it.
1726 * NB. These two functions can cause flicker as the selection is modified,
1727 * as the game redraws the entire marked section.
1729 static void mark_selection_mark(int x1, int y1, int x2, int y2)
1731 square_to_pixel(&x1, &y1, x1, y1);
1732 square_to_pixel(&x2, &y2, x2, y2);
1733 XDrawRectangle(Metadpy->dpy, Infowin->win, clr[2]->gc, x1, y1,
1734 x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
1738 * Mark a selection by drawing boxes around it (for now).
1740 static void mark_selection(void)
1744 bool draw = s_ptr->select;
1745 bool clear = s_ptr->drawn;
1747 /* Open the correct term if necessary. */
1748 if (s_ptr->t != old) Term_activate(s_ptr->t);
1752 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->old);
1753 mark_selection_clear(min.x, min.y, max.x, max.y);
1757 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
1758 mark_selection_mark(min.x, min.y, max.x, max.y);
1761 /* Finish on the current term. */
1762 if (s_ptr->t != old) Term_activate(old);
1764 s_ptr->old.x = s_ptr->cur.x;
1765 s_ptr->old.y = s_ptr->cur.y;
1766 s_ptr->drawn = s_ptr->select;
1770 * Forget a selection for one reason or another.
1772 static void copy_x11_release(void)
1774 /* Deselect the current selection. */
1775 s_ptr->select = FALSE;
1777 /* Remove its graphical represesntation. */
1782 * Start to select some text on the screen.
1784 static void copy_x11_start(int x, int y)
1786 if (s_ptr->select) copy_x11_release();
1788 /* Remember where the selection started. */
1790 s_ptr->init.x = s_ptr->cur.x = s_ptr->old.x = x;
1791 s_ptr->init.y = s_ptr->cur.y = s_ptr->old.y = y;
1795 * Respond to movement of the mouse when selecting text.
1797 static void copy_x11_cont(int x, int y, unsigned int buttons)
1799 /* Use the nearest square within bounds if the mouse is outside. */
1800 x = MIN(MAX(x, 0), Term->wid-1);
1801 y = MIN(MAX(y, 0), Term->hgt-1);
1803 /* The left mouse button isn't pressed. */
1804 if (~buttons & Button1Mask) return;
1806 /* Not a selection in this window. */
1807 if (s_ptr->t != Term) return;
1809 /* Not enough movement. */
1810 if (x == s_ptr->old.x && y == s_ptr->old.y && s_ptr->select) return;
1812 /* Something is being selected. */
1813 s_ptr->select = TRUE;
1815 /* Track the selection. */
1819 /* Hack - display it inefficiently. */
1824 * Respond to release of the left mouse button by putting the selected text in
1825 * the primary buffer.
1827 static void copy_x11_end(const Time time)
1830 if (!s_ptr->select) return;
1832 /* Not a selection in this window. */
1833 if (s_ptr->t != Term) return;
1835 /* Remember when the selection was finalised. */
1838 /* Acquire the primary selection. */
1839 XSetSelectionOwner(Metadpy->dpy, XA_PRIMARY, Infowin->win, time);
1840 if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) != Infowin->win)
1842 /* Failed to acquire the selection, so forget it. */
1843 /* bell("Failed to acquire primary buffer."); */
1844 s_ptr->select = FALSE;
1850 static Atom xa_targets, xa_timestamp, xa_text, xa_compound_text;
1853 * Set the required variable atoms at start-up to avoid errors later.
1855 static void set_atoms(void)
1857 xa_targets = XInternAtom(DPY, "TARGETS", False);
1858 xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
1859 xa_text = XInternAtom(DPY, "TEXT", False);
1860 xa_compound_text = XInternAtom(DPY, "COMPOUND_TEXT", False);
1864 static Atom request_target = 0;
1867 * Send a message to request that the PRIMARY buffer be sent here.
1869 static void paste_x11_request(Atom target, const Time time)
1872 * It's from some sample programs on the web.
1873 * What does it mean? -- XXX
1875 Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1877 /* Check the owner. */
1878 if (XGetSelectionOwner(DPY, XA_PRIMARY) == None)
1881 /* bell("No selection found."); */
1885 request_target = target;
1887 /* Request the event */
1888 XConvertSelection(DPY, XA_PRIMARY, target, property, WIN, time);
1893 * Add the contents of the PRIMARY buffer to the input queue.
1895 * Hack - This doesn't use the "time" of the event, and so accepts anything a
1896 * client tries to send it.
1898 static void paste_x11_accept(const XSelectionEvent *ptr)
1901 const long offset = 0;
1902 const long length = 32000;
1903 XTextProperty xtextproperty;
1907 * It's from some sample programs on the web.
1908 * What does it mean? -- XXX
1910 Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1914 if (ptr->property == None)
1916 if (request_target == xa_compound_text)
1918 /* Re-request as STRING */
1919 paste_x11_request(XA_STRING, ptr->time);
1924 plog("Paste failure (remote client could not send).");
1929 if (ptr->selection != XA_PRIMARY)
1931 plog("Paste failure (remote client did not send primary selection).");
1935 if (ptr->target != request_target)
1937 plog("Paste failure (selection in unknown format).");
1942 if (XGetWindowProperty(Metadpy->dpy, Infowin->win, property, offset,
1943 length, TRUE, request_target,
1944 &xtextproperty.encoding,
1945 &xtextproperty.format,
1946 &xtextproperty.nitems,
1948 &xtextproperty.value)
1955 if (request_target == xa_compound_text)
1960 XmbTextPropertyToTextList(DPY, &xtextproperty, &list, &count);
1966 for (i = 0; i < count; i++)
1968 /* Paste the text. */
1969 err = type_string(list[i], 0);
1974 /* Free the string */
1975 XFreeStringList(list);
1978 else /* if (request_target == XA_STRING) */
1980 /* Paste the text. */
1981 err = type_string((char *)xtextproperty.value, xtextproperty.nitems);
1984 /* Free the data pasted. */
1985 XFree(xtextproperty.value);
1990 plog("Paste failure (too much text selected).");
1996 * Add a character to a string in preparation for sending it to another
1997 * client as a STRING.
1998 * This doesn't change anything, as clients tend not to have difficulty in
1999 * receiving this format (although the standard specifies a restricted set).
2000 * Strings do not have a colour.
2002 static bool paste_x11_send_text(XSelectionRequestEvent *rq)
2012 /* Too old, or incorrect call. */
2013 if (rq->time < s_ptr->time) return FALSE;
2015 /* Work out which way around to paste. */
2016 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
2019 if (XGetSelectionOwner(DPY, XA_PRIMARY) != WIN)
2021 /* bell("Someone stole my selection!"); */
2025 /* Delete the old value of the property. */
2026 XDeleteProperty(DPY, rq->requestor, rq->property);
2028 for (n = 0, y = 0; y < Term->hgt; y++)
2033 if (y < min.y) continue;
2034 if (y > max.y) break;
2036 for (l = 0, x = 0; x < Term->wid; x++)
2039 if (x > max.x) break;
2041 /* Find the character. */
2042 Term_what(x, y, &a, &c);
2044 if (1 == kanji) kanji = 2;
2045 else if (iskanji(c)) kanji = 1;
2048 if (x < min.x) continue;
2051 * A single kanji character was divided in two...
2052 * Delete the garbage.
2054 if ((2 == kanji && x == min.x) ||
2055 (1 == kanji && x == max.x))
2058 if (x > max.x) break;
2059 if (x < min.x) continue;
2061 /* Find the character. */
2062 Term_what(x, y, &a, &c);
2070 /* Ignore trailing spaces */
2071 while (buf[l-1] == ' ') l--;
2073 /* Terminate all line unless it's single line. */
2083 list[n++] = (char *)string_make(buf);
2086 /* End of the list */
2090 if (rq->target == XA_STRING)
2092 for (n = 0; list[n]; n++)
2094 /* Send the (non-empty) string. */
2095 XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
2096 PropModeAppend, (unsigned char *)list[n], strlen(list[n]));
2100 else if (rq->target == xa_text ||
2101 rq->target == xa_compound_text)
2103 XTextProperty text_prop;
2104 XICCEncodingStyle style;
2106 if (rq->target == xa_text)
2107 style = XStdICCTextStyle;
2108 else /* if (rq->target == xa_compound_text) */
2109 style = XCompoundTextStyle;
2112 XmbTextListToTextProperty(DPY, list, n, style, &text_prop))
2114 /* Send the compound text */
2115 XChangeProperty(DPY,
2124 /* Free the data. */
2125 XFree(text_prop.value);
2129 /* Free the list of strings */
2130 for (n = 0; list[n]; n++)
2132 string_free(list[n]);
2139 * Send some text requested by another X client.
2141 static void paste_x11_send(XSelectionRequestEvent *rq)
2144 XSelectionEvent *ptr = &(event.xselection);
2146 /* Set the event parameters. */
2147 ptr->type = SelectionNotify;
2148 ptr->property = rq->property;
2149 ptr->display = rq->display;
2150 ptr->requestor = rq->requestor;
2151 ptr->selection = rq->selection;
2152 ptr->target = rq->target;
2153 ptr->time = rq->time;
2155 /* Paste the appropriate information for each target type.
2156 * Note that this currently rejects MULTIPLE targets.
2159 if (rq->target == XA_STRING ||
2160 rq->target == xa_text ||
2161 rq->target == xa_compound_text)
2163 if (!paste_x11_send_text(rq))
2164 ptr->property = None;
2166 else if (rq->target == xa_targets)
2168 Atom target_list[4];
2169 target_list[0] = XA_STRING;
2170 target_list[1] = xa_text;
2171 target_list[2] = xa_compound_text;
2172 target_list[3] = xa_targets;
2173 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
2174 (8 * sizeof(target_list[0])), PropModeReplace,
2175 (unsigned char *)target_list,
2176 (sizeof(target_list) / sizeof(target_list[0])));
2178 else if (rq->target == xa_timestamp)
2180 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
2181 (8 * sizeof(Time)), PropModeReplace,
2182 (unsigned char *)s_ptr->time, 1);
2186 ptr->property = None;
2189 /* Send whatever event we're left with. */
2190 XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
2195 * Handle various events conditional on presses of a mouse button.
2197 static void handle_button(Time time, int x, int y, int button,
2200 /* The co-ordinates are only used in Angband format. */
2201 pixel_to_square(&x, &y, x, y);
2203 if (press && button == 1) copy_x11_start(x, y);
2204 if (!press && button == 1) copy_x11_end(time);
2205 if (!press && button == 2) paste_x11_request(xa_compound_text, time);
2212 static errr CheckEvent(bool wait)
2214 term_data *old_td = (term_data*)(Term->data);
2216 XEvent xev_body, *xev = &xev_body;
2218 term_data *td = NULL;
2219 infowin *iwin = NULL;
2227 /* Do not wait unless requested */
2228 if (!wait && !XPending(Metadpy->dpy)) return (1);
2231 * Hack - redraw the selection, if needed.
2232 * This doesn't actually check that one of its squares was drawn to,
2233 * only that this may have happened.
2235 if (s_ptr->select && !s_ptr->drawn) mark_selection();
2237 /* Load the Event */
2238 XNextEvent(Metadpy->dpy, xev);
2241 /* #define DEBUG_EVENT */
2244 printf("event: type=%d", xev->type);
2247 printf("(KeyPress), keycode=%X", xev->xkey.keycode);
2250 printf("(FocusIn)");
2253 printf("(FocusOut)");
2255 case ReparentNotify:
2256 printf("(ReparentNotify)");
2258 case ConfigureNotify:
2259 printf("(ConfigureNotify)");
2262 printf("(MapNotify)");
2268 printf("(ClientMessage)");
2274 if (XFilterEvent(xev, xev->xany.window)
2275 /*XFilterEvent(xev, (data[0].win)->win)*/){
2277 printf(", [filtered by IM]\n");
2279 goto redo_checkevent;
2286 /* Notice new keymaps */
2287 if (xev->type == MappingNotify)
2289 XRefreshKeyboardMapping(&xev->xmapping);
2294 /* Scan the windows */
2295 for (i = 0; i < MAX_TERM_DATA; i++)
2297 if (!data[i].win) continue;
2298 if (xev->xany.window == data[i].win->win)
2306 /* Unknown window */
2307 if (!td || !iwin) return (0);
2310 /* Hack -- activate the Term */
2311 Term_activate(&td->t);
2313 /* Hack -- activate the window */
2317 /* Switch on the Type */
2323 bool press = (xev->type == ButtonPress);
2325 /* Where is the mouse */
2326 int x = xev->xbutton.x;
2327 int y = xev->xbutton.y;
2331 /* Which button is involved */
2332 if (xev->xbutton.button == Button1) z = 1;
2333 else if (xev->xbutton.button == Button2) z = 2;
2334 else if (xev->xbutton.button == Button3) z = 3;
2335 else if (xev->xbutton.button == Button4) z = 4;
2336 else if (xev->xbutton.button == Button5) z = 5;
2340 handle_button(xev->xbutton.time, x, y, z, press);
2355 /* Where is the mouse */
2356 int x = xev->xmotion.x;
2357 int y = xev->xmotion.y;
2358 unsigned int z = xev->xmotion.state;
2360 /* Convert to co-ordinates Angband understands. */
2361 pixel_to_square(&x, &y, x, y);
2363 /* Highlight the current square, if appropriate. */
2364 /* highlight_square(window, y, x); */
2366 /* Alter the selection if appropriate. */
2367 copy_x11_cont(x, y, z);
2374 case SelectionNotify:
2376 paste_x11_accept(&(xev->xselection));
2380 case SelectionRequest:
2382 paste_x11_send(&(xev->xselectionrequest));
2386 case SelectionClear:
2388 s_ptr->select = FALSE;
2401 /* Hack -- use "old" term */
2402 Term_activate(&old_td->t);
2404 /* Process the key */
2405 react_keypress(&(xev->xkey));
2414 /* Ignore "extra" exposes */
2415 /*if (xev->xexpose.count) break;*/
2417 /* Clear the window */
2420 x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
2421 x2 = (xev->xexpose.x + xev->xexpose.width -
2422 Infowin->ox)/Infofnt->wid;
2424 y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
2425 y2 = (xev->xexpose.y + xev->xexpose.height -
2426 Infowin->oy)/Infofnt->hgt;
2428 Term_redraw_section(x1, y1, x2, y2);
2438 Infowin->mapped = 1;
2439 Term->mapped_flag = TRUE;
2445 Infowin->mapped = 0;
2446 Term->mapped_flag = FALSE;
2450 /* Move and/or Resize */
2451 case ConfigureNotify:
2453 int cols, rows, wid, hgt;
2455 int ox = Infowin->ox;
2456 int oy = Infowin->oy;
2458 /* Save the new Window Parms */
2459 Infowin->x = xev->xconfigure.x;
2460 Infowin->y = xev->xconfigure.y;
2461 Infowin->w = xev->xconfigure.width;
2462 Infowin->h = xev->xconfigure.height;
2464 /* Determine "proper" number of rows/cols */
2465 cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
2466 rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
2468 /* Hack -- minimal size */
2469 if (cols < 1) cols = 1;
2470 if (rows < 1) rows = 1;
2474 /* Hack the main window must be at least 80x24 */
2475 if (cols < 80) cols = 80;
2476 if (rows < 24) rows = 24;
2479 /* Desired size of window */
2480 wid = cols * td->fnt->wid + (ox + ox);
2481 hgt = rows * td->fnt->hgt + (oy + oy);
2483 /* Resize the Term (if needed) */
2484 Term_resize(cols, rows);
2486 /* Resize the windows if any "change" is needed */
2487 if ((Infowin->w != wid) || (Infowin->h != hgt))
2490 Infowin_set(td->win);
2491 Infowin_resize(wid, hgt);
2500 XSetICFocus(iwin->xic);
2508 XUnsetICFocus(iwin->xic);
2510 /* Focuswin = NULL;*/
2517 /* Hack -- Activate the old term */
2518 Term_activate(&old_td->t);
2520 /* Hack -- Activate the proper window */
2521 Infowin_set(old_td->win);
2530 * Standard sound names
2532 static const concptr angband_sound_name[SOUND_MAX] =
2604 * An array of sound file names
2606 static concptr sound_file[SOUND_MAX];
2609 * Check for existance of a file
2611 static bool check_file(concptr s)
2615 fff = fopen(s, "r");
2616 if (!fff) return (FALSE);
2625 static void init_sound(void)
2630 char dir_xtra_sound[1024];
2632 /* Build the "sound" path */
2633 path_build(dir_xtra_sound, sizeof(dir_xtra_sound), ANGBAND_DIR_XTRA, "sound");
2635 /* Prepare the sounds */
2636 for (i = 1; i < SOUND_MAX; i++)
2638 /* Extract name of sound file */
2639 sprintf(wav, "%s.wav", angband_sound_name[i]);
2641 /* Access the sound */
2642 path_build(buf, sizeof(buf), dir_xtra_sound, wav);
2644 /* Save the sound filename, if it exists */
2645 if (check_file(buf)) sound_file[i] = string_make(buf);
2652 * Hack -- make a sound
2654 static errr Term_xtra_x11_sound(int v)
2658 /* Sound disabled */
2659 if (!use_sound) return (1);
2662 if ((v < 0) || (v >= SOUND_MAX)) return (1);
2665 if (!sound_file[v]) return (1);
2667 sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
2669 return (system(buf) < 0);
2675 * Handle "activation" of a term
2677 static errr Term_xtra_x11_level(int v)
2679 term_data *td = (term_data*)(Term->data);
2681 /* Handle "activate" */
2684 /* Activate the window */
2685 Infowin_set(td->win);
2687 /* Activate the font */
2688 Infofnt_set(td->fnt);
2699 static errr Term_xtra_x11_react(void)
2705 /* Check the colors */
2706 for (i = 0; i < 256; i++)
2708 if ((color_table[i][0] != angband_color_table[i][0]) ||
2709 (color_table[i][1] != angband_color_table[i][1]) ||
2710 (color_table[i][2] != angband_color_table[i][2]) ||
2711 (color_table[i][3] != angband_color_table[i][3]))
2715 /* Save new values */
2716 color_table[i][0] = angband_color_table[i][0];
2717 color_table[i][1] = angband_color_table[i][1];
2718 color_table[i][2] = angband_color_table[i][2];
2719 color_table[i][3] = angband_color_table[i][3];
2722 pixel = create_pixel(Metadpy->dpy,
2727 /* Change the foreground */
2728 Infoclr_set(clr[i]);
2729 Infoclr_change_fg(pixel);
2740 * Handle a "special request"
2742 static errr Term_xtra_x11(int n, int v)
2744 /* Handle a subset of the legal requests */
2748 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
2750 /* Make a special sound */
2751 case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
2753 /* Flush the output XXX XXX */
2754 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
2756 /* Process random events XXX */
2757 case TERM_XTRA_BORED: return (CheckEvent(0));
2759 /* Process Events XXX */
2760 case TERM_XTRA_EVENT: return (CheckEvent(v));
2762 /* Flush the events XXX */
2763 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
2765 /* Handle change in the "level" */
2766 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
2768 /* Clear the screen */
2769 case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
2771 /* Delay for some milliseconds */
2772 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
2774 /* React to changes */
2775 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
2784 * Draw the cursor as an inverted rectangle.
2786 * Consider a rectangular outline like "main-mac.c". XXX XXX
2788 static errr Term_curs_x11(int x, int y)
2792 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2793 x * Infofnt->wid + Infowin->ox,
2794 y * Infofnt->hgt + Infowin->oy,
2795 Infofnt->wid - 1, Infofnt->hgt - 1);
2796 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2797 x * Infofnt->wid + Infowin->ox + 1,
2798 y * Infofnt->hgt + Infowin->oy + 1,
2799 Infofnt->wid - 3, Infofnt->hgt - 3);
2803 /* Draw the cursor */
2806 /* Hilite the cursor character */
2807 Infofnt_text_non(x, y, " ", 1);
2816 * Draw the double width cursor
2818 static errr Term_bigcurs_x11(int x, int y)
2822 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2823 x * Infofnt->wid + Infowin->ox,
2824 y * Infofnt->hgt + Infowin->oy,
2825 Infofnt->twid - 1, Infofnt->hgt - 1);
2826 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2827 x * Infofnt->wid + Infowin->ox + 1,
2828 y * Infofnt->hgt + Infowin->oy + 1,
2829 Infofnt->twid - 3, Infofnt->hgt - 3);
2833 /* Draw the cursor */
2836 /* Hilite the cursor character */
2837 Infofnt_text_non(x, y, " ", 2);
2845 * Erase some characters.
2847 static errr Term_wipe_x11(int x, int y, int n)
2849 /* Erase (use black) */
2850 Infoclr_set(clr[TERM_DARK]);
2852 /* Mega-Hack -- Erase some space */
2853 Infofnt_text_non(x, y, "", n);
2855 /* Redraw the selection if any, as it may have been obscured. (later) */
2856 s_ptr->drawn = FALSE;
2864 * Draw some textual characters.
2866 static errr Term_text_x11(TERM_LEN x, TERM_LEN y, int n, TERM_COLOR a, concptr s)
2869 Infoclr_set(clr[a]);
2872 Infofnt_text_std(x, y, s, n);
2874 /* Redraw the selection if any, as it may have been obscured. (later) */
2875 s_ptr->drawn = FALSE;
2883 * Draw some graphical characters.
2885 static errr Term_pict_x11(TERM_LEN x, TERM_LEN y, int n, const TERM_COLOR *ap, const char *cp, const TERM_COLOR *tap, const char *tcp)
2898 unsigned long pixel, blank;
2900 term_data *td = (term_data*)(Term->data);
2905 /* Add in affect of window boundaries */
2909 for (i = 0; i < n; ++i, x += td->fnt->wid)
2914 /* For extra speed - cache these values */
2915 x1 = (c&0x7F) * td->fnt->twid;
2916 y1 = (a&0x7F) * td->fnt->hgt;
2918 /* Illegal tile index */
2919 if (td->tiles->width < x1 + td->fnt->wid ||
2920 td->tiles->height < y1 + td->fnt->hgt)
2922 /* Draw black square */
2923 XFillRectangle(Metadpy->dpy, td->win->win, clr[0]->gc,
2925 td->fnt->twid, td->fnt->hgt);
2927 /* Skip drawing tile */
2934 /* For extra speed - cache these values */
2935 x2 = (tc&0x7F) * td->fnt->twid;
2936 y2 = (ta&0x7F) * td->fnt->hgt;
2938 /* Optimise the common case */
2939 if (((x1 == x2) && (y1 == y2)) ||
2940 !(((byte)ta & 0x80) && ((byte)tc & 0x80)) ||
2941 td->tiles->width < x2 + td->fnt->wid ||
2942 td->tiles->height < y2 + td->fnt->hgt)
2944 /* Draw object / terrain */
2945 XPutImage(Metadpy->dpy, td->win->win,
2950 td->fnt->twid, td->fnt->hgt);
2955 /* Mega Hack^2 - assume the top left corner is "black" */
2956 blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
2958 for (k = 0; k < td->fnt->twid; k++)
2960 for (l = 0; l < td->fnt->hgt; l++)
2962 /* If mask set... */
2963 if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
2965 /* Output from the terrain */
2966 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
2969 /* Store into the temp storage. */
2970 XPutPixel(td->TmpImage, k, l, pixel);
2975 /* Draw to screen */
2977 XPutImage(Metadpy->dpy, td->win->win,
2981 td->fnt->twid, td->fnt->hgt);
2985 /* Redraw the selection if any, as it may have been obscured. (later) */
2986 s_ptr->drawn = FALSE;
2993 static void IMDestroyCallback(XIM, XPointer, XPointer);
2996 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
2999 XIMCallback ximcallback;
3000 XIMStyles *xim_styles = NULL;
3007 xim = XOpenIM(display, NULL, NULL, NULL);
3009 printf("can't open IM\n");
3013 /* initialize destroy callback */
3014 ximcallback.callback = IMDestroyCallback;
3015 ximcallback.client_data = NULL;
3016 XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
3018 /* set style (only "Root" is supported yet...) */
3019 XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
3020 for (i = 0; i < xim_styles->count_styles; i++){
3021 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
3023 if(i >= xim_styles->count_styles){
3024 printf("Sorry, your IM does not support 'Root' preedit style...\n");
3032 for (i = 0; i < MAX_TERM_DATA; i++)
3034 infowin *iwin = data[i].win;
3035 if (!iwin) continue;
3036 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
3038 printf("Can't create input context for Term%d\n", i);
3041 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL){
3042 /* printf("Can't get XNFilterEvents\n"); */
3043 iwin->xic_mask = 0L;
3045 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
3051 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
3059 if (call_data == NULL){
3060 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3063 for(i = 0; i < MAX_TERM_DATA; i++)
3065 infowin *iwin = data[i].win;
3068 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
3069 iwin->xic_mask = 0L;
3074 Metadpy->xim = NULL;
3079 * Initialize a term_data
3081 static errr term_data_init(term_data *td, int i)
3085 concptr name = angband_term_name[i];
3115 /* Window specific font name */
3116 sprintf(buf, "ANGBAND_X11_FONT_%d", i);
3118 /* Check environment for that font */
3121 /* Check environment for "base" font */
3122 if (!font) font = getenv("ANGBAND_X11_FONT");
3124 /* No environment variables, use default font */
3131 font = DEFAULT_X11_FONT_0;
3136 font = DEFAULT_X11_FONT_1;
3141 font = DEFAULT_X11_FONT_2;
3146 font = DEFAULT_X11_FONT_3;
3151 font = DEFAULT_X11_FONT_4;
3156 font = DEFAULT_X11_FONT_5;
3161 font = DEFAULT_X11_FONT_6;
3166 font = DEFAULT_X11_FONT_7;
3171 font = DEFAULT_X11_FONT;
3176 /* Window specific location (x) */
3177 sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
3179 x = (str != NULL) ? atoi(str) : -1;
3181 /* Window specific location (y) */
3182 sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
3184 y = (str != NULL) ? atoi(str) : -1;
3187 /* Window specific cols */
3188 sprintf(buf, "ANGBAND_X11_COLS_%d", i);
3190 val = (str != NULL) ? atoi(str) : -1;
3191 if (val > 0) cols = val;
3193 /* Window specific rows */
3194 sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
3196 val = (str != NULL) ? atoi(str) : -1;
3197 if (val > 0) rows = val;
3199 /* Hack the main window must be at least 80x24 */
3202 if (cols < 80) cols = 80;
3203 if (rows < 24) rows = 24;
3206 /* Window specific inner border offset (ox) */
3207 sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
3209 val = (str != NULL) ? atoi(str) : -1;
3210 if (val > 0) ox = val;
3212 /* Window specific inner border offset (oy) */
3213 sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
3215 val = (str != NULL) ? atoi(str) : -1;
3216 if (val > 0) oy = val;
3219 /* Prepare the standard font */
3220 MAKE(td->fnt, infofnt);
3221 Infofnt_set(td->fnt);
3222 Infofnt_init_data(font);
3224 /* Hack -- key buffer size */
3225 num = ((i == 0) ? 1024 : 16);
3227 /* Assume full size windows */
3228 wid = cols * td->fnt->wid + (ox + ox);
3229 hgt = rows * td->fnt->hgt + (oy + oy);
3231 /* Create a top-window */
3232 MAKE(td->win, infowin);
3233 Infowin_set(td->win);
3234 Infowin_init_top(x, y, wid, hgt, 0,
3235 Metadpy->fg, Metadpy->bg);
3237 /* Ask for certain events */
3238 #if defined(USE_XIM)
3239 Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask);
3241 Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
3244 /* Set the window name */
3245 Infowin_set_name(name);
3247 /* Save the inner border */
3251 /* Make Class Hints */
3252 ch = XAllocClassHint();
3254 if (ch == NULL) quit("XAllocClassHint failed");
3256 strcpy(res_name, name);
3257 res_name[0] = FORCELOWER(res_name[0]);
3258 ch->res_name = res_name;
3260 strcpy(res_class, "Angband");
3261 ch->res_class = res_class;
3263 XSetClassHint(Metadpy->dpy, Infowin->win, ch);
3265 /* Make Size Hints */
3266 sh = XAllocSizeHints();
3269 if (sh == NULL) quit("XAllocSizeHints failed");
3271 /* Main window has a differing minimum size */
3274 /* Main window min size is 80x24 */
3275 sh->flags = PMinSize | PMaxSize;
3276 sh->min_width = 80 * td->fnt->wid + (ox + ox);
3277 sh->min_height = 24 * td->fnt->hgt + (oy + oy);
3278 sh->max_width = 255 * td->fnt->wid + (ox + ox);
3279 sh->max_height = 255 * td->fnt->hgt + (oy + oy);
3282 /* Other windows can be shrunk to 1x1 */
3286 sh->flags = PMinSize | PMaxSize;
3287 sh->min_width = td->fnt->wid + (ox + ox);
3288 sh->min_height = td->fnt->hgt + (oy + oy);
3289 sh->max_width = 256 * td->fnt->wid + (ox + ox);
3290 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
3293 /* Resize increment */
3294 sh->flags |= PResizeInc;
3295 sh->width_inc = td->fnt->wid;
3296 sh->height_inc = td->fnt->hgt;
3298 /* Base window size */
3299 sh->flags |= PBaseSize;
3300 sh->base_width = (ox + ox);
3301 sh->base_height = (oy + oy);
3303 /* Use the size hints */
3304 XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
3306 /* Map the window */
3311 wh = XAllocWMHints();
3312 if(wh == NULL) quit("XAllocWMHints failed");
3313 wh->flags = InputHint;
3315 XSetWMHints(Metadpy->dpy, Infowin->win, wh);
3318 /* Move the window to requested location */
3319 if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
3322 /* Initialize the term */
3323 term_init(t, cols, rows, num);
3325 /* Use a "soft" cursor */
3326 t->soft_cursor = TRUE;
3328 /* Erase with "white space" */
3329 t->attr_blank = TERM_WHITE;
3330 t->char_blank = ' ';
3333 t->xtra_hook = Term_xtra_x11;
3334 t->curs_hook = Term_curs_x11;
3335 t->bigcurs_hook = Term_bigcurs_x11;
3336 t->wipe_hook = Term_wipe_x11;
3337 t->text_hook = Term_text_x11;
3342 /* Activate (important) */
3351 * Initialization function for an "X11" module to Angband
3353 errr init_x11(int argc, char *argv[])
3357 concptr dpy_name = "";
3361 char filename[1024];
3369 for (i = 1; i < argc; i++)
3371 if (prefix(argv[i], "-d"))
3373 dpy_name = &argv[i][2];
3377 if (prefix(argv[i], "-s"))
3379 smoothRescaling = FALSE;
3383 if (prefix(argv[i], "-a"))
3385 arg_graphics = GRAPHICS_ADAM_BOLT;
3389 if (prefix(argv[i], "-o"))
3391 arg_graphics = GRAPHICS_ORIGINAL;
3395 if (prefix(argv[i], "-b"))
3397 arg_bigtile = use_bigtile = TRUE;
3401 if (prefix(argv[i], "-n"))
3403 num_term = atoi(&argv[i][2]);
3404 if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
3405 else if (num_term < 1) num_term = 1;
3409 if (prefix(argv[i], "--"))
3415 plog_fmt("Ignoring option: %s", argv[i]);
3421 /* Get locale information from environment variables */
3422 setlocale(LC_ALL, "");
3424 #ifdef DEFAULT_LOCALE
3425 if(!strcmp(setlocale(LC_ALL, NULL), "C")){
3426 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
3427 setlocale(LC_ALL, DEFAULT_LOCALE);
3431 if(!strcmp(setlocale(LC_ALL, NULL), "C"))
3433 printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
3436 if(!XSupportsLocale()){
3437 printf("can't support locale in X\n");
3438 setlocale(LC_ALL, "C");
3441 /* Set locale to "C" without using environment variables */
3442 setlocale(LC_ALL, "C");
3445 #endif /* USE_LOCALE */
3448 /* Init the Metadpy if possible */
3449 if (Metadpy_init_name(dpy_name)) return (-1);
3452 /* Prepare cursor color */
3455 Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
3458 /* Prepare normal colors */
3459 for (i = 0; i < 256; ++i)
3463 MAKE(clr[i], infoclr);
3465 Infoclr_set(clr[i]);
3467 /* Acquire Angband colors */
3468 color_table[i][0] = angband_color_table[i][0];
3469 color_table[i][1] = angband_color_table[i][1];
3470 color_table[i][2] = angband_color_table[i][2];
3471 color_table[i][3] = angband_color_table[i][3];
3473 /* Default to monochrome */
3474 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
3480 pixel = create_pixel(Metadpy->dpy,
3486 /* Initialize the color */
3487 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
3491 /* Prepare required atoms. */
3495 /* Initialize the windows */
3496 for (i = 0; i < num_term; i++)
3498 term_data *td = &data[i];
3500 /* Initialize the term_data */
3501 term_data_init(td, i);
3503 /* Save global entry */
3504 angband_term[i] = Term;
3507 /* Raise the "Angband" window */
3508 Infowin_set(data[0].win);
3511 /* Activate the "Angband" window screen */
3512 Term_activate(&data[0].t);
3517 p = XSetLocaleModifiers("");
3519 p = XSetLocaleModifiers("@im=");
3521 /* printf("XMODIFIERS=\"%s\"\n", p); */
3523 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3526 /* initialize sound */
3527 if (arg_sound) init_sound();
3530 switch (arg_graphics)
3532 case GRAPHICS_ORIGINAL:
3533 /* Try the "8x8.bmp" file */
3534 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/8x8.bmp");
3536 /* Use the "8x8.bmp" file if it exists */
3537 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3540 use_graphics = TRUE;
3542 pict_wid = pict_hgt = 8;
3544 ANGBAND_GRAF = "old";
3549 case GRAPHICS_ADAM_BOLT:
3550 /* Try the "16x16.bmp" file */
3551 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/16x16.bmp");
3553 /* Use the "16x16.bmp" file if it exists */
3554 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3557 use_graphics = TRUE;
3559 pict_wid = pict_hgt = 16;
3561 ANGBAND_GRAF = "new";
3570 Display *dpy = Metadpy->dpy;
3574 /* Load the graphical tiles */
3575 tiles_raw = ReadBMP(dpy, filename);
3577 /* Initialize the windows */
3578 for (i = 0; i < num_term; i++)
3580 term_data *td = &data[i];
3585 t->pict_hook = Term_pict_x11;
3587 /* Use graphics sometimes */
3588 t->higher_pict = TRUE;
3592 ResizeImage(dpy, tiles_raw,
3594 td->fnt->twid, td->fnt->hgt);
3597 /* Initialize the transparency masks */
3598 for (i = 0; i < num_term; i++)
3600 term_data *td = &data[i];
3602 int depth = DefaultDepth(dpy, DefaultScreen(dpy));
3603 Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
3607 /* Determine total bytes needed for image */
3609 jj = (depth - 1) >> 2;
3610 while (jj >>= 1) ii <<= 1;
3611 total = td->fnt->twid * td->fnt->hgt * ii;
3614 TmpData = (char *)malloc(total);
3616 td->TmpImage = XCreateImage(dpy,visual,depth,
3617 ZPixmap, 0, TmpData,
3618 td->fnt->twid, td->fnt->hgt, 8, 0);
3622 /* Free tiles_raw? XXX XXX */
3629 #endif /* USE_X11 */