OSDN Git Service

[Refactor] #40274 Unified angband_sound_name[] into main/sound-definitions-table.c/h
[hengband/hengband.git] / src / main-x11.c
1 /* File: main-x11.c */
2
3 /*
4  * Copyright (c) 1997 Ben Harrison, and others
5  *
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.
9  */
10
11
12 /*
13  * This file helps Angband work with UNIX/X11 computers.
14  *
15  * To use this file, compile with "USE_X11" defined, and link against all
16  * the various "X11" libraries which may be needed.
17  *
18  * See also "main-xaw.c".
19  *
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
24  * file simple.
25  *
26  * The rest of this file is an implementation of "main-xxx.c" for X11.
27  *
28  * Most of this file is by Ben Harrison (benh@phial.com).
29  */
30
31 /*
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.
39  * 
40  *
41  * #!/bin/csh
42  * 
43  * # Describe attempt
44  * echo "Launching angband..."
45  * sleep 2
46  * 
47  * # Main window
48  * setenv ANGBAND_X11_FONT_0 10x20
49  * setenv ANGBAND_X11_AT_X_0 5
50  * setenv ANGBAND_X11_AT_Y_0 510
51  * 
52  * # Message window
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
57  * 
58  * # Inventory window
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
63  * 
64  * # Equipment window
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
69  * 
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
76  * 
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
83  * 
84  * # The build directory
85  * cd ~/Angband
86  *
87  * # Gamma correction
88  * setenv ANGBAND_X11_GAMMA 142
89  * 
90  * # Launch Angband
91  * ./src/angband -mx11 -- -n6 &
92  *
93  */
94
95
96 #include "angband.h"
97 #include "main/sound-definitions-table.h"
98 #include "core.h"
99 #include "files.h"
100 #include "gameterm.h"
101
102
103 /*
104  * Available graphic modes
105  */
106 #define GRAPHICS_NONE       0
107 #define GRAPHICS_ORIGINAL   1
108 #define GRAPHICS_ADAM_BOLT  2
109 #define GRAPHICS_HENGBAND   3
110 #ifdef USE_X11
111
112
113 #ifndef __MAKEDEPEND__
114 #include <X11/Xlib.h>
115 #include <X11/Xutil.h>
116 #include <X11/keysym.h>
117 #include <X11/keysymdef.h>
118 #ifdef USE_LOCALE
119 #include <X11/Xlocale.h>
120 #endif
121 #include <X11/Xatom.h>
122 #endif /* __MAKEDEPEND__ */
123
124 #include <iconv.h>
125 #ifdef USE_XFT
126 #include <X11/Xft/Xft.h>
127 #endif
128
129 /*
130  * Include some helpful X11 code.
131  */
132 #include "maid-x11.c"
133
134
135 /*
136  * Notes on Colors:
137  *
138  *   1) On a monochrome (or "fake-monochrome") display, all colors
139  *   will be "cast" to "fg," except for the bg color, which is,
140  *   obviously, cast to "bg".  Thus, one can ignore this setting.
141  *
142  *   2) Because of the inner functioning of the color allocation
143  *   routines, colors may be specified as (a) a typical color name,
144  *   (b) a hexidecimal color specification (preceded by a pound sign),
145  *   or (c) by strings such as "fg", "bg", "zg".
146  *
147  *   3) Due to the workings of the init routines, many colors
148  *   may also be dealt with by their actual pixel values.  Note that
149  *   the pixel with all bits set is "zg = (1<<metadpy->depth)-1", which
150  *   is not necessarily either black or white.
151  */
152
153 /**** Generic Types ****/
154
155 /*
156  * An X11 pixell specifier
157  */
158 #ifdef USE_XFT
159 typedef XftColor Pixell;
160 #else
161 typedef unsigned long Pixell;
162 #endif
163
164 /*
165  * The structures defined below
166  */
167 typedef struct metadpy metadpy;
168 typedef struct infowin infowin;
169 typedef struct infoclr infoclr;
170 typedef struct infofnt infofnt;
171
172
173 /*
174  * A structure summarizing a given Display.
175  *
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)
180  *
181  *      - The "name" of the display
182  *
183  *      - The socket to listen to for events
184  *
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)
188  *
189  *      - The black Pixell (from a macro)
190  *      - The white Pixell (from a macro)
191  *
192  *      - The background Pixell (default: black)
193  *      - The foreground Pixell (default: white)
194  *      - The maximal Pixell (Equals: ((2 ^ depth)-1), is usually ugly)
195  *
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.
199  */
200 struct metadpy
201 {
202         Display *dpy;
203         Screen *screen;
204         Window root;
205         Colormap cmap;
206 #ifdef USE_XIM
207         XIM xim;
208 #endif
209
210         char *name;
211
212         int fd;
213
214         uint width;
215         uint height;
216         uint depth;
217
218         Pixell black;
219         Pixell white;
220
221         Pixell bg;
222         Pixell fg;
223 #ifndef USE_XFT
224         Pixell zg;
225 #endif
226
227         uint mono:1;
228         uint color:1;
229         uint nuke:1;
230 };
231
232
233
234 /*
235  * A Structure summarizing Window Information.
236  *
237  * I assume that a window is at most 30000 pixels on a side.
238  * I assume that the root windw is also at most 30000 square.
239  *
240  *      - The Window
241  *      - The current Input Event Mask
242  *
243  *      - The location of the window
244  *      - The width, height of the window
245  *      - The border width of this window
246  *
247  *      - Byte: 1st Extra byte
248  *
249  *      - Bit Flag: This window is currently Mapped
250  *      - Bit Flag: This window needs to be redrawn
251  *      - Bit Flag: This window has been resized
252  *
253  *      - Bit Flag: We should nuke 'win' when done with it
254  *
255  *      - Bit Flag: 1st extra flag
256  *      - Bit Flag: 2nd extra flag
257  *      - Bit Flag: 3rd extra flag
258  *      - Bit Flag: 4th extra flag
259  */
260 struct infowin
261 {
262         Window win;
263 #ifdef USE_XIM
264         XIC xic;
265         long xic_mask;
266 #endif
267 #ifdef USE_XFT
268         XftDraw *draw;
269 #endif
270
271         long mask;
272
273         s16b ox, oy;
274
275         s16b x, y;
276         s16b w, h;
277         u16b b;
278
279         byte byte1;
280
281         uint mapped:1;
282         uint redraw:1;
283         uint resize:1;
284
285         uint nuke:1;
286
287         uint flag1:1;
288         uint flag2:1;
289         uint flag3:1;
290         uint flag4:1;
291 };
292
293
294
295
296
297
298 /*
299  * A Structure summarizing Operation+Color Information
300  *
301  *      - The actual GC corresponding to this info
302  *
303  *      - The Foreground Pixell Value
304  *      - The Background Pixell Value
305  *
306  *      - Num (0-15): The operation code (As in Clear, Xor, etc)
307  *      - Bit Flag: The GC is in stipple mode
308  *      - Bit Flag: Destroy 'gc' at Nuke time.
309  */
310 struct infoclr
311 {
312 #ifndef USE_XFT
313         GC gc;
314 #endif
315
316         Pixell fg;
317         Pixell bg;
318
319         uint code:4;
320         uint stip:1;
321         uint nuke:1;
322 };
323
324
325
326 /*
327  * A Structure to Hold Font Information
328  *
329  *      - The 'XFontStruct*' (yields the 'Font')
330  *
331  *      - The font name
332  *
333  *      - The default character width
334  *      - The default character height
335  *      - The default character ascent
336  *
337  *      - Byte: Pixel offset used during fake mono
338  *
339  *      - Flag: Force monospacing via 'wid'
340  *      - Flag: Nuke info when done
341  */
342 struct infofnt
343 {
344 #ifdef USE_XFT
345         XftFont *info;
346 #else
347         XFontSet info;
348 #endif
349         concptr name;
350
351         s16b wid;
352         s16b twid;
353         s16b hgt;
354         s16b asc;
355
356         byte off;
357
358         uint mono:1;
359         uint nuke:1;
360 };
361
362
363
364
365 /**** Generic Macros ****/
366
367
368
369 /* Set current metadpy (Metadpy) to 'M' */
370 #define Metadpy_set(M) \
371         Metadpy = M
372
373
374 /* Initialize 'M' using Display 'D' */
375 #define Metadpy_init_dpy(D) \
376         Metadpy_init_2(D,cNULL)
377
378 /* Initialize 'M' using a Display named 'N' */
379 #define Metadpy_init_name(N) \
380         Metadpy_init_2((Display*)(NULL),N)
381
382 /* Initialize 'M' using the standard Display */
383 #define Metadpy_init() \
384         Metadpy_init_name("")
385
386
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)), \
390                           X,Y,W,H,B,FG,BG)
391
392
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)
396
397
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)
401
402
403 /* Set the current Infowin */
404 #define Infowin_set(I) \
405         (Infowin = (I))
406
407
408 /* Set the current Infoclr */
409 #define Infoclr_set(C) \
410         (Infoclr = (C))
411
412
413 #define Infoclr_init_ppo(F,B,O,M) \
414         Infoclr_init_data(F,B,O,M)
415
416 #define Infoclr_init_cco(F,B,O,M) \
417         Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M)
418
419 #define Infoclr_init_ppn(F,B,O,M) \
420         Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M)
421
422 #define Infoclr_init_ccn(F,B,O,M) \
423         Infoclr_init_cco(F,B,Infoclr_Opcode(O),M)
424
425
426 /* Set the current infofnt */
427 #define Infofnt_set(I) \
428         (Infofnt = (I))
429
430
431 /* Errr: Expose Infowin */
432 #define Infowin_expose() \
433         (!(Infowin->redraw = 1))
434
435 /* Errr: Unxpose Infowin */
436 #define Infowin_unexpose() \
437         (Infowin->redraw = 0)
438
439
440
441 /**** Generic Globals ****/
442
443
444 /*
445  * The "default" values
446  */
447 static metadpy metadpy_default;
448
449
450 /*
451  * The "current" variables
452  */
453 static metadpy *Metadpy = &metadpy_default;
454 static infowin *Infowin = (infowin*)(NULL);
455 #ifdef USE_XIM
456 static infowin *Focuswin = (infowin*)(NULL);
457 #endif
458 static infoclr *Infoclr = (infoclr*)(NULL);
459 static infofnt *Infofnt = (infofnt*)(NULL);
460
461 /**** Generic code ****/
462
463 /*
464  * Init the current metadpy, with various initialization stuff.
465  *
466  * Inputs:
467  *      dpy:  The Display* to use (if NULL, create it)
468  *      name: The name of the Display (if NULL, the current)
469  *
470  * Notes:
471  *      If 'name' is NULL, but 'dpy' is set, extract name from dpy
472  *      If 'dpy' is NULL, then Create the named Display
473  *      If 'name' is NULL, and so is 'dpy', use current Display
474  *
475  * Return -1 if no Display given, and none can be opened.
476  */
477 static errr Metadpy_init_2(Display *dpy, concptr name)
478 {
479         metadpy *m = Metadpy;
480
481         /*** Open the display if needed ***/
482
483         /* If no Display given, attempt to Create one */
484         if (!dpy)
485         {
486                 /* Attempt to open the display */
487                 dpy = XOpenDisplay(name);
488
489                 /* Failure */
490                 if (!dpy) return (-1);
491
492                 /* We will have to nuke it when done */
493                 m->nuke = 1;
494         }
495
496         /* Since the Display was given, use it */
497         else
498         {
499                 /* We will not have to nuke it when done */
500                 m->nuke = 0;
501         }
502
503
504         /*** Save some information ***/
505
506         /* Save the Display itself */
507         m->dpy = dpy;
508
509         /* Get the Screen and Virtual Root Window */
510         m->screen = DefaultScreenOfDisplay(dpy);
511         m->root = RootWindowOfScreen(m->screen);
512
513         /* Get the default colormap */
514         m->cmap = DefaultColormapOfScreen(m->screen);
515
516         /* Extract the true name of the display */
517         m->name = DisplayString(dpy);
518
519         /* Extract the fd */
520         m->fd = ConnectionNumber(Metadpy->dpy);
521
522         /* Save the Size and Depth of the screen */
523         m->width = WidthOfScreen(m->screen);
524         m->height = HeightOfScreen(m->screen);
525         m->depth = DefaultDepthOfScreen(m->screen);
526
527         /* Save the Standard Colors */
528 #ifdef USE_XFT
529         Visual *vis = DefaultVisual(dpy, 0);
530         XftColorAllocName(dpy, vis, m->cmap, "black", &m->black);
531         XftColorAllocName(dpy, vis, m->cmap, "white", &m->white);
532 #else
533         m->black = BlackPixelOfScreen(m->screen);
534         m->white = WhitePixelOfScreen(m->screen);
535 #endif
536
537         /*** Make some clever Guesses ***/
538
539         /* Guess at the desired 'fg' and 'bg' Pixell's */
540         m->bg = m->black;
541         m->fg = m->white;
542
543 #ifndef USE_XFT
544         /* Calculate the Maximum allowed Pixel value.  */
545         m->zg = (1 << m->depth) - 1;
546 #endif
547
548         /* Save various default Flag Settings */
549         m->color = ((m->depth > 1) ? 1 : 0);
550         m->mono = ((m->color) ? 0 : 1);
551
552         /* Return "success" */
553         return (0);
554 }
555
556
557 /*
558  * General Flush/ Sync/ Discard routine
559  */
560 static errr Metadpy_update(int flush, int sync, int discard)
561 {
562         /* Flush if desired */
563         if (flush) XFlush(Metadpy->dpy);
564
565         /* Sync if desired, using 'discard' */
566         if (sync) XSync(Metadpy->dpy, discard);
567
568         /* Success */
569         return (0);
570 }
571
572
573 /*
574  * Make a simple beep
575  */
576 static errr Metadpy_do_beep(void)
577 {
578         /* Make a simple beep */
579         XBell(Metadpy->dpy, 100);
580
581         return (0);
582 }
583
584
585
586 /*
587  * Set the name (in the title bar) of Infowin
588  */
589 static errr Infowin_set_name(concptr name)
590 {
591         Status st;
592         XTextProperty tp;
593         char buf[128];
594         char *bp = buf;
595         strcpy(buf, name);
596         st = XStringListToTextProperty(&bp, 1, &tp);
597         if (st) XSetWMName(Metadpy->dpy, Infowin->win, &tp);
598         return (0);
599 }
600
601
602 /*
603  * Prepare a new 'infowin'.
604  */
605 static errr Infowin_prepare(Window xid)
606 {
607         infowin *iwin = Infowin;
608
609         Window tmp_win;
610         XWindowAttributes xwa;
611         int x, y;
612         unsigned int w, h, b, d;
613
614         /* Assign stuff */
615         iwin->win = xid;
616
617         /* Check For Error XXX Extract some ACTUAL data from 'xid' */
618         XGetGeometry(Metadpy->dpy, xid, &tmp_win, &x, &y, &w, &h, &b, &d);
619
620 #ifdef USE_XFT
621         Visual *vis = DefaultVisual(Metadpy->dpy, 0);
622         if (vis->class != TrueColor) {
623                 quit_fmt("Display does not support truecolor.\n");
624         }
625         iwin->draw = XftDrawCreate(Metadpy->dpy, iwin->win, vis, Metadpy->cmap);
626 #endif
627
628         /* Apply the above info */
629         iwin->x = x;
630         iwin->y = y;
631         iwin->w = w;
632         iwin->h = h;
633         iwin->b = b;
634
635         /* Check Error XXX Extract some more ACTUAL data */
636         XGetWindowAttributes(Metadpy->dpy, xid, &xwa);
637
638         /* Apply the above info */
639         iwin->mask = xwa.your_event_mask;
640         iwin->mapped = ((xwa.map_state == IsUnmapped) ? 0 : 1);
641
642         /* And assume that we are exposed */
643         iwin->redraw = 1;
644
645         /* Success */
646         return (0);
647 }
648
649
650 /*
651  * Init an infowin by giving some data.
652  *
653  * Inputs:
654  *      dad: The Window that should own this Window (if any)
655  *      x,y: The position of this Window
656  *      w,h: The size of this Window
657  *      b,d: The border width and pixel depth
658  *
659  * Notes:
660  *      If 'dad == None' assume 'dad == root'
661  */
662 static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
663                               int b, Pixell fg, Pixell bg)
664 {
665         Window xid;
666
667         /* Wipe it clean */
668         (void)WIPE(Infowin, infowin);
669
670
671         /*** Error Check XXX ***/
672
673
674         /*** Create the Window 'xid' from data ***/
675
676         /* What happened here?  XXX XXX XXX */
677
678         /* If no parent given, depend on root */
679         if (dad == None) dad = Metadpy->root;
680
681         /* Create the Window XXX Error Check */
682 #ifdef USE_XFT
683         xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg.pixel, bg.pixel);
684 #else
685         xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg, bg);
686 #endif
687
688         /* Start out selecting No events */
689         XSelectInput(Metadpy->dpy, xid, 0L);
690
691
692         /*** Prepare the new infowin ***/
693
694         /* Mark it as nukable */
695         Infowin->nuke = 1;
696
697         /* Attempt to Initialize the infowin */
698         return (Infowin_prepare(xid));
699 }
700
701
702
703 /*
704  * Modify the event mask of an Infowin
705  */
706 static errr Infowin_set_mask(long mask)
707 {
708         /* Save the new setting */
709         Infowin->mask = mask;
710
711         /* Execute the Mapping */
712         XSelectInput(Metadpy->dpy, Infowin->win, Infowin->mask);
713
714         /* Success */
715         return (0);
716 }
717
718
719 /*
720  * Request that Infowin be mapped
721  */
722 static errr Infowin_map(void)
723 {
724         /* Execute the Mapping */
725         XMapWindow(Metadpy->dpy, Infowin->win);
726
727         /* Success */
728         return (0);
729 }
730
731
732 /*
733  * Request that Infowin be raised
734  */
735 static errr Infowin_raise(void)
736 {
737         /* Raise towards visibility */
738         XRaiseWindow(Metadpy->dpy, Infowin->win);
739
740         /* Success */
741         return (0);
742 }
743
744
745 /*
746  * Request that Infowin be moved to a new location
747  */
748 static errr Infowin_impell(int x, int y)
749 {
750         /* Execute the request */
751         XMoveWindow(Metadpy->dpy, Infowin->win, x, y);
752
753         /* Success */
754         return (0);
755 }
756
757
758 /*
759  * Resize an infowin
760  */
761 static errr Infowin_resize(int w, int h)
762 {
763         /* Execute the request */
764         XResizeWindow(Metadpy->dpy, Infowin->win, w, h);
765
766         /* Success */
767         return (0);
768 }
769
770
771 /*
772  * Visually clear Infowin
773  */
774 static errr Infowin_wipe(void)
775 {
776         /* Execute the request */
777         XClearWindow(Metadpy->dpy, Infowin->win);
778
779         /* Success */
780         return (0);
781 }
782
783
784 /*
785  * A NULL terminated pair list of legal "operation names"
786  *
787  * Pairs of values, first is texttual name, second is the string
788  * holding the decimal value that the operation corresponds to.
789  */
790 static concptr opcode_pairs[] =
791 {
792         "cpy", "3",
793         "xor", "6",
794         "and", "1",
795         "ior", "7",
796         "nor", "8",
797         "inv", "10",
798         "clr", "0",
799         "set", "15",
800
801         "src", "3",
802         "dst", "5",
803
804         "+andReverse", "2",
805         "+andInverted", "4",
806         "+noop", "5",
807         "+equiv", "9",
808         "+orReverse", "11",
809         "+copyInverted", "12",
810         "+orInverted", "13",
811         "+nand", "14",
812         NULL
813 };
814
815
816 /*
817  * Parse a word into an operation "code"
818  *
819  * Inputs:
820  *      str: A string, hopefully representing an Operation
821  *
822  * Output:
823  *      0-15: if 'str' is a valid Operation
824  *      -1:   if 'str' could not be parsed
825  */
826 static int Infoclr_Opcode(concptr str)
827 {
828         register int i;
829
830         /* Scan through all legal operation names */
831         for (i = 0; opcode_pairs[i*2]; ++i)
832         {
833                 /* Is this the right oprname? */
834                 if (streq(opcode_pairs[i*2], str))
835                 {
836                         /* Convert the second element in the pair into a Code */
837                         return (atoi(opcode_pairs[i*2+1]));
838                 }
839         }
840
841         /* The code was not found, return -1 */
842         return (-1);
843 }
844
845
846 /*
847  * Initialize an infoclr with some data
848  *
849  * Inputs:
850  *      fg:   The Pixell for the requested Foreground (see above)
851  *      bg:   The Pixell for the requested Background (see above)
852  *      op:   The Opcode for the requested Operation (see above)
853  *      stip: The stipple mode
854  */
855 static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
856 {
857         infoclr *iclr = Infoclr;
858
859 #ifndef USE_XFT
860         GC gc;
861         XGCValues gcv;
862         unsigned long gc_mask;
863 #endif
864
865
866
867         /*** Simple error checking of opr and clr ***/
868
869         /* Check the 'Pixells' for realism */
870 #ifndef USE_XFT
871         if (bg > Metadpy->zg) return (-1);
872         if (fg > Metadpy->zg) return (-1);
873
874         /* Check the data for trueness */
875         if ((op < 0) || (op > 15)) return (-1);
876
877
878         /*** Create the requested 'GC' ***/
879
880         /* Assign the proper GC function */
881         gcv.function = op;
882
883         /* Assign the proper GC background */
884         gcv.background = bg;
885
886         /* Assign the proper GC foreground */
887         gcv.foreground = fg;
888
889         /* Hack -- Handle XOR (xor is code 6) by hacking bg and fg */
890         if (op == 6) gcv.background = 0;
891         if (op == 6) gcv.foreground = (bg ^ fg);
892
893         /* Assign the proper GC Fill Style */
894         gcv.fill_style = (stip ? FillStippled : FillSolid);
895
896         /* Turn off 'Give exposure events for pixmap copying' */
897         gcv.graphics_exposures = False;
898
899         /* Set up the GC mask */
900         gc_mask = (GCFunction | GCBackground | GCForeground |
901                    GCFillStyle | GCGraphicsExposures);
902
903         /* Create the GC detailed above */
904         gc = XCreateGC(Metadpy->dpy, Metadpy->root, gc_mask, &gcv);
905 #endif
906
907
908         /*** Initialize ***/
909
910         /* Wipe the iclr clean */
911         (void)WIPE(iclr, infoclr);
912
913 #ifndef USE_XFT
914         /* Assign the GC */
915         iclr->gc = gc;
916 #endif
917
918         /* Nuke it when done */
919         iclr->nuke = 1;
920
921         /* Assign the parms */
922         iclr->fg = fg;
923         iclr->bg = bg;
924         iclr->code = op;
925         iclr->stip = stip ? 1 : 0;
926
927         /* Success */
928         return (0);
929 }
930
931
932
933 /*
934  * Change the 'fg' for an infoclr
935  *
936  * Inputs:
937  *      fg:   The Pixell for the requested Foreground (see above)
938  */
939 static errr Infoclr_change_fg(Pixell fg)
940 {
941         infoclr *iclr = Infoclr;
942
943
944 #ifdef USE_XFT
945         iclr->fg = fg;
946 #else
947         /*** Simple error checking of opr and clr ***/
948
949         /* Check the 'Pixells' for realism */
950         if (fg > Metadpy->zg) return (-1);
951
952
953         /*** Change ***/
954
955         /* Change */
956         XSetForeground(Metadpy->dpy, iclr->gc, fg);
957 #endif
958
959         /* Success */
960         return (0);
961 }
962
963
964 /*
965  * Prepare a new 'infofnt'
966  */
967 #ifdef USE_XFT
968 static errr Infofnt_prepare(XftFont *info)
969 #else
970 static errr Infofnt_prepare(XFontSet info)
971 #endif
972 {
973         infofnt *ifnt = Infofnt;
974
975 #ifndef USE_XFT
976         XCharStruct *cs;
977         XFontStruct **fontinfo;
978         char **fontname;
979         int n_fonts;
980         int ascent, descent, width;
981 #endif
982
983         /* Assign the struct */
984         ifnt->info = info;
985
986
987 #ifdef USE_XFT
988         ifnt->asc = info->ascent;
989         ifnt->hgt = info->ascent + info->descent;
990         const char *text = "A";
991         XGlyphInfo extent;
992         XftTextExtentsUtf8(Metadpy->dpy, info, (FcChar8*)text, strlen(text), &extent);
993         ifnt->wid = extent.xOff;
994 #else
995         n_fonts = XFontsOfFontSet(info, &fontinfo, &fontname);
996
997         ascent = descent = width = 0;
998         while(n_fonts-- > 0){
999                 cs = &((*fontinfo)->max_bounds);
1000                 if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
1001                 if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
1002                 if(((*fontinfo)->max_byte1) > 0){
1003                         /* 多バイト文字の場合は幅半分(端数切り上げ)で評価する */
1004                         if(width < (cs->width+1)/2) width = (cs->width+1)/2;
1005                 }else{
1006                         if(width < cs->width) width = cs->width;
1007                 }
1008                 fontinfo++;
1009                 fontname++;
1010         }
1011         ifnt->asc = ascent;
1012         ifnt->hgt = ascent + descent;
1013         ifnt->wid = width;
1014 #endif
1015
1016         if (use_bigtile)
1017                 ifnt->twid = 2 * ifnt->wid;
1018         else
1019                 ifnt->twid = ifnt->wid;
1020
1021         return (0);
1022 }
1023
1024
1025 /*
1026  * Init an infofnt by its Name
1027  *
1028  * Inputs:
1029  *      name: The name of the requested Font
1030  */
1031 static void Infofnt_init_data(concptr name)
1032
1033 {
1034 #ifdef USE_XFT
1035         XftFont *info;
1036 #else
1037         XFontSet info;
1038         char **missing_list;
1039         int missing_count;
1040         char *default_font;
1041 #endif
1042
1043         /*** Load the info Fresh, using the name ***/
1044
1045         /* If the name is not given, report an error */
1046         if (!name || !*name) quit("Missing font!");
1047
1048         /* Attempt to load the font */
1049 #ifdef USE_XFT
1050         info = XftFontOpenName(Metadpy->dpy, 0, name);
1051         /* TODO: error handling */
1052 #else
1053         info = XCreateFontSet(Metadpy->dpy, name, &missing_list, &missing_count, &default_font);
1054         if(missing_count > 0){
1055                 printf("missing font(s): \n");
1056                 while(missing_count-- > 0){
1057                         printf("\t%s\n", missing_list[missing_count]);
1058                 }
1059                 XFreeStringList(missing_list);
1060         }
1061 #endif
1062
1063         /* The load failed, try to recover */
1064         if (!info) quit_fmt("Failed to find font:\"%s\"", name);
1065
1066         /*** Init the font ***/
1067
1068         /* Wipe the thing */
1069         (void)WIPE(Infofnt, infofnt);
1070
1071         /* Attempt to prepare it */
1072         if (Infofnt_prepare(info))
1073         {
1074                 /* Free the font */
1075 #ifdef USE_XFT
1076                 XftFontClose(Metadpy->dpy, info);
1077 #else
1078                 XFreeFontSet(Metadpy->dpy, info);
1079 #endif
1080
1081                 /* Fail */
1082                 quit_fmt("Failed to prepare font:\"%s\"", name);
1083         }
1084
1085         /* Save a copy of the font name */
1086         Infofnt->name = string_make(name);
1087
1088         /* Mark it as nukable */
1089         Infofnt->nuke = 1;
1090 }
1091
1092
1093 /*
1094  * Standard Text
1095  */
1096 static errr Infofnt_text_std(int x, int y, concptr str, int len)
1097 {
1098         /*** Do a brief info analysis ***/
1099
1100         /* Do nothing if the string is null */
1101         if (!str || !*str) return (-1);
1102
1103         /* Get the length of the string */
1104         if (len < 0) len = strlen(str);
1105
1106         /*** Decide where to place the string, vertically ***/
1107
1108         /* Ignore Vertical Justifications */
1109         y = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
1110
1111
1112         /*** Decide where to place the string, horizontally ***/
1113
1114         /* Line up with x at left edge of column 'x' */
1115         x = (x * Infofnt->wid) + Infowin->ox;
1116
1117
1118         /*** Actually draw 'str' onto the infowin ***/
1119
1120         /*** Handle the fake mono we can enforce on fonts ***/
1121
1122         /* Monotize the font */
1123         if (Infofnt->mono)
1124         {
1125 #ifndef USE_XFT
1126                 int i;
1127
1128                 /* Do each character */
1129                 for (i = 0; i < len; ++i)
1130                 {
1131                         /* Note that the Infoclr is set up to contain the Infofnt */
1132                         XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1133                                          x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
1134                 }
1135 #endif
1136         }
1137
1138         /* Assume monoospaced font */
1139         else
1140         {
1141                 /* Note that the Infoclr is set up to contain the Infofnt */
1142                 iconv_t cd = iconv_open("UTF-8", "EUC-JP");
1143                 size_t inlen = len;
1144                 size_t outlen = len * 2;
1145                 char *kanji = malloc(outlen);
1146                 char *sp; char *kp = kanji;
1147                 char sbuf[1024];
1148                 my_strcpy(sbuf, str, sizeof(sbuf));
1149                 sp = sbuf;
1150                 iconv(cd, &sp, &inlen, &kp, &outlen);
1151                 iconv_close(cd);
1152
1153 #ifdef USE_XFT
1154                 XftDraw* draw = Infowin->draw;
1155
1156                 XRectangle r;
1157                 r.x = 0;
1158                 r.y = 0;
1159                 r.width = Infofnt->wid*len;
1160                 r.height = Infofnt->hgt;
1161                 XftDrawSetClipRectangles(draw, x, y-Infofnt->asc, &r, 1);
1162                 XftDrawRect(draw, &Infoclr->bg, x, y-Infofnt->asc, Infofnt->wid*len, Infofnt->hgt);
1163                 XftDrawStringUtf8(draw, &Infoclr->fg, Infofnt->info, x, y,
1164                          (FcChar8*)kanji, kp - kanji);
1165                 XftDrawSetClip(draw, 0);
1166 #else
1167                 XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info,
1168                                 Infoclr->gc, x, y, kanji, kp-kanji);
1169 #endif
1170                 free(kanji);
1171         }
1172
1173         /* Success */
1174         return (0);
1175 }
1176
1177
1178 /*
1179  * Painting where text would be
1180  */
1181 static errr Infofnt_text_non(int x, int y, concptr str, int len)
1182 {
1183         int w, h;
1184
1185
1186         /*** Find the width ***/
1187
1188         /* Negative length is a flag to count the characters in str */
1189         if (len < 0) len = strlen(str);
1190
1191         /* The total width will be 'len' chars * standard width */
1192         w = len * Infofnt->wid;
1193
1194
1195         /*** Find the X dimensions ***/
1196
1197         /* Line up with x at left edge of column 'x' */
1198         x = x * Infofnt->wid + Infowin->ox;
1199
1200
1201         /*** Find other dimensions ***/
1202
1203         /* Simply do 'Infofnt->hgt' (a single row) high */
1204         h = Infofnt->hgt;
1205
1206         /* Simply do "at top" in row 'y' */
1207         y = y * h + Infowin->oy;
1208
1209
1210         /*** Actually 'paint' the area ***/
1211
1212         /* Just do a Fill Rectangle */
1213 #ifdef USE_XFT
1214         XftDrawRect(Infowin->draw, &Infoclr->fg, x, y, w, h);
1215 #else
1216         XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, x, y, w, h);
1217 #endif
1218
1219         /* Success */
1220         return (0);
1221 }
1222
1223
1224
1225 /*************************************************************************/
1226
1227
1228 /*
1229  * Angband specific code follows... (ANGBAND)
1230  */
1231
1232
1233 /*
1234  * Hack -- cursor color
1235  */
1236 static infoclr *xor;
1237
1238 /*
1239  * Actual color table
1240  */
1241 static infoclr *clr[256];
1242
1243 /*
1244  * Color info (unused, red, green, blue).
1245  */
1246 static byte color_table[256][4];
1247
1248 /*
1249  * Forward declare
1250  */
1251 typedef struct term_data term_data;
1252
1253 /*
1254  * A structure for each "term"
1255  */
1256 struct term_data
1257 {
1258         term t;
1259
1260         infofnt *fnt;
1261         infowin *win;
1262
1263 #ifndef USE_XFT
1264         XImage *tiles;
1265
1266         /* Tempory storage for overlaying tiles. */
1267         XImage *TmpImage;
1268 #endif
1269 };
1270
1271
1272 /*
1273  * The number of term data structures
1274  */
1275 #define MAX_TERM_DATA 8
1276
1277 /*
1278  * The array of term data structures
1279  */
1280 static term_data data[MAX_TERM_DATA];
1281
1282
1283 /* Use short names for the most commonly used elements of various structures. */
1284 #define DPY (Metadpy->dpy)
1285 #define WIN (Infowin->win)
1286
1287
1288 /* Describe a set of co-ordinates. */
1289 typedef struct co_ord co_ord;
1290 struct co_ord
1291 {
1292         int x;
1293         int y;
1294 };
1295
1296
1297 /*
1298  * A special structure to store information about the text currently
1299  * selected.
1300  */
1301 typedef struct x11_selection_type x11_selection_type;
1302 struct x11_selection_type
1303 {
1304         bool select; /* The selection is currently in use. */
1305         bool drawn; /* The selection is currently displayed. */
1306         term *t; /* The window where the selection is found. */
1307         co_ord init; /* The starting co-ordinates. */
1308         co_ord cur; /* The end co-ordinates (the current ones if still copying). */
1309         co_ord old; /* The previous end co-ordinates. */
1310         Time time; /* The time at which the selection was finalised. */
1311 };
1312
1313 static x11_selection_type s_ptr[1];
1314
1315
1316 /*
1317  * Process a keypress event
1318  *
1319  * Also appears in "main-xaw.c".
1320  */
1321 static void react_keypress(XKeyEvent *xev)
1322 {
1323         int i, n, mc, ms, mo, mx;
1324
1325         uint ks1;
1326
1327         XKeyEvent *ev = (XKeyEvent*)(xev);
1328
1329         KeySym ks;
1330
1331         char buf[128];
1332         char msg[128];
1333
1334 #ifdef USE_XIM
1335         int valid_keysym = TRUE;
1336 #endif
1337
1338         /* Check for "normal" keypresses */
1339 #ifdef USE_XIM
1340         if(Focuswin && Focuswin->xic){
1341                 Status status;
1342                 n = XmbLookupString(Focuswin->xic, ev, buf, 125, &ks, &status);
1343                 if(status == XBufferOverflow){
1344                         printf("Input is too long, and dropped\n");
1345                         return;
1346                 }
1347                 if(status != XLookupKeySym && status != XLookupBoth){
1348                         valid_keysym = FALSE;
1349                 }
1350         }else{
1351                 n = XLookupString(ev, buf, 125, &ks, NULL);
1352         }
1353 #else
1354         n = XLookupString(ev, buf, 125, &ks, NULL);
1355 #endif
1356
1357         /* Terminate */
1358         buf[n] = '\0';
1359
1360 #ifdef USE_XIM
1361         if(!valid_keysym){
1362                 /* Enqueue the normal key(s) */
1363                 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1364
1365                 /* All done */
1366                 return;
1367         }
1368 #endif
1369
1370         /* Hack -- Ignore "modifier keys" */
1371         if (IsModifierKey(ks)) return;
1372
1373
1374         /* Hack -- convert into an unsigned int */
1375         ks1 = (uint)(ks);
1376
1377         /* Extract four "modifier flags" */
1378         mc = (ev->state & ControlMask) ? TRUE : FALSE;
1379         ms = (ev->state & ShiftMask) ? TRUE : FALSE;
1380         mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
1381         mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
1382
1383
1384         /* Normal keys with no modifiers */
1385         if (n && !mo && !mx && !IsSpecialKey(ks))
1386         {
1387                 /* Enqueue the normal key(s) */
1388                 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1389
1390                 /* All done */
1391                 return;
1392         }
1393
1394
1395         /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */
1396         switch (ks1)
1397         {
1398                 case XK_Escape:
1399                 {
1400                         Term_keypress(ESCAPE);
1401                         return;
1402                 }
1403
1404                 case XK_Return:
1405                 {
1406                         Term_keypress('\r');
1407                         return;
1408                 }
1409
1410                 case XK_Tab:
1411                 {
1412                         Term_keypress('\t');
1413                         return;
1414                 }
1415
1416                 case XK_Delete:
1417                 {
1418                         Term_keypress(0x7f);
1419                         return;
1420                 }
1421                 case XK_BackSpace:
1422                 {
1423                         Term_keypress('\010');
1424                         return;
1425                 }
1426         }
1427
1428
1429         /* Hack -- Use the KeySym */
1430         if (ks)
1431         {
1432                 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
1433                         mc ? "N" : "", ms ? "S" : "",
1434                         mo ? "O" : "", mx ? "M" : "",
1435                         (unsigned long)(ks), 13);
1436         }
1437
1438         /* Hack -- Use the Keycode */
1439         else
1440         {
1441                 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
1442                         mc ? "N" : "", ms ? "S" : "",
1443                         mo ? "O" : "", mx ? "M" : "",
1444                         ev->keycode, 13);
1445         }
1446
1447         /* Enqueue the "macro trigger" string */
1448         for (i = 0; msg[i]; i++) Term_keypress(msg[i]);
1449
1450
1451         /* Hack -- auto-define macros as needed */
1452         if (n && (macro_find_exact(msg) < 0))
1453         {
1454                 /* Create a macro */
1455                 macro_add(msg, buf);
1456         }
1457 }
1458
1459
1460 /*
1461  * Find the square a particular pixel is part of.
1462  */
1463 static void pixel_to_square(int * const x, int * const y,
1464         const int ox, const int oy)
1465 {
1466         (*x) = (ox - Infowin->ox) / Infofnt->wid;
1467         (*y) = (oy - Infowin->oy) / Infofnt->hgt;
1468 }
1469
1470 /*
1471  * Find the pixel at the top-left corner of a square.
1472  */
1473 static void square_to_pixel(int * const x, int * const y,
1474         const int ox, const int oy)
1475 {
1476         (*x) = ox * Infofnt->wid + Infowin->ox;
1477         (*y) = oy * Infofnt->hgt + Infowin->oy;
1478 }
1479
1480 /*
1481  * Convert co-ordinates from starting corner/opposite corner to minimum/maximum.
1482  */
1483 static void sort_co_ord(co_ord *min, co_ord *max,
1484         const co_ord *b, const co_ord *a)
1485 {
1486         min->x = MIN(a->x, b->x);
1487         min->y = MIN(a->y, b->y);
1488         max->x = MAX(a->x, b->x);
1489         max->y = MAX(a->y, b->y);
1490 }
1491
1492 /*
1493  * Remove the selection by redrawing it.
1494  */
1495 static void mark_selection_clear(int x1, int y1, int x2, int y2)
1496 {
1497         Term_redraw_section(x1,y1,x2,y2);
1498 }
1499
1500 /*
1501  * Select an area by drawing a grey box around it.
1502  * NB. These two functions can cause flicker as the selection is modified,
1503  * as the game redraws the entire marked section.
1504  */
1505 static void mark_selection_mark(int x1, int y1, int x2, int y2)
1506 {
1507         square_to_pixel(&x1, &y1, x1, y1);
1508         square_to_pixel(&x2, &y2, x2, y2);
1509 #ifdef USE_XFT
1510         XftDrawRect(Infowin->draw, &clr[2]->fg, x1, y1, x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
1511 #else
1512         XDrawRectangle(Metadpy->dpy, Infowin->win, clr[2]->gc, x1, y1,
1513                 x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
1514 #endif
1515 }
1516
1517 /*
1518  * Mark a selection by drawing boxes around it (for now).
1519  */
1520 static void mark_selection(void)
1521 {
1522         co_ord min, max;
1523         term *old = Term;
1524         bool draw = s_ptr->select;
1525         bool clear = s_ptr->drawn;
1526
1527         /* Open the correct term if necessary. */
1528         if (s_ptr->t != old) Term_activate(s_ptr->t);
1529
1530         if (clear)
1531         {
1532                 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->old);
1533                 mark_selection_clear(min.x, min.y, max.x, max.y);
1534         }
1535         if (draw)
1536         {
1537                 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
1538                 mark_selection_mark(min.x, min.y, max.x, max.y);
1539         }
1540
1541         /* Finish on the current term. */
1542         if (s_ptr->t != old) Term_activate(old);
1543
1544         s_ptr->old.x = s_ptr->cur.x;
1545         s_ptr->old.y = s_ptr->cur.y;
1546         s_ptr->drawn = s_ptr->select;
1547 }
1548
1549 /*
1550  * Forget a selection for one reason or another.
1551  */
1552 static void copy_x11_release(void)
1553 {
1554         /* Deselect the current selection. */
1555         s_ptr->select = FALSE;
1556
1557         /* Remove its graphical represesntation. */
1558         mark_selection();
1559 }
1560
1561 /*
1562  * Start to select some text on the screen.
1563  */
1564 static void copy_x11_start(int x, int y)
1565 {
1566         if (s_ptr->select) copy_x11_release();
1567
1568         /* Remember where the selection started. */
1569         s_ptr->t = Term;
1570         s_ptr->init.x = s_ptr->cur.x = s_ptr->old.x = x;
1571         s_ptr->init.y = s_ptr->cur.y = s_ptr->old.y = y;
1572 }
1573
1574 /*
1575  * Respond to movement of the mouse when selecting text.
1576  */
1577 static void copy_x11_cont(int x, int y, unsigned int buttons)
1578 {
1579         /* Use the nearest square within bounds if the mouse is outside. */
1580         x = MIN(MAX(x, 0), Term->wid-1);
1581         y = MIN(MAX(y, 0), Term->hgt-1);
1582
1583         /* The left mouse button isn't pressed. */
1584         if (~buttons & Button1Mask) return;
1585
1586         /* Not a selection in this window. */
1587         if (s_ptr->t != Term) return;
1588
1589         /* Not enough movement. */
1590         if (x == s_ptr->old.x && y == s_ptr->old.y && s_ptr->select) return;
1591
1592         /* Something is being selected. */
1593         s_ptr->select = TRUE;
1594
1595         /* Track the selection. */
1596         s_ptr->cur.x = x;
1597         s_ptr->cur.y = y;
1598
1599         /* Hack - display it inefficiently. */
1600         mark_selection();
1601 }
1602
1603 /*
1604  * Respond to release of the left mouse button by putting the selected text in
1605  * the primary buffer.
1606  */
1607 static void copy_x11_end(const Time time)
1608 {
1609         /* No selection. */
1610         if (!s_ptr->select) return;
1611
1612         /* Not a selection in this window. */
1613         if (s_ptr->t != Term) return;
1614
1615         /* Remember when the selection was finalised. */
1616         s_ptr->time = time;
1617
1618         /* Acquire the primary selection. */
1619         XSetSelectionOwner(Metadpy->dpy, XA_PRIMARY, Infowin->win, time);
1620         if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) != Infowin->win)
1621         {
1622                 /* Failed to acquire the selection, so forget it. */
1623                 /* bell("Failed to acquire primary buffer."); */
1624                 s_ptr->select = FALSE;
1625                 mark_selection();
1626         }
1627 }
1628
1629
1630 static Atom xa_targets, xa_timestamp, xa_text, xa_compound_text;
1631
1632 /*
1633  * Set the required variable atoms at start-up to avoid errors later.
1634  */
1635 static void set_atoms(void)
1636 {
1637         xa_targets = XInternAtom(DPY, "TARGETS", False);
1638         xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
1639         xa_text = XInternAtom(DPY, "TEXT", False);
1640         xa_compound_text = XInternAtom(DPY, "COMPOUND_TEXT", False);
1641 }
1642
1643
1644 static Atom request_target = 0;
1645
1646 /*
1647  * Send a message to request that the PRIMARY buffer be sent here.
1648  */
1649 static void paste_x11_request(Atom target, const Time time)
1650 {
1651         /*
1652          * It's from some sample programs on the web.
1653          * What does it mean? -- XXX
1654          */
1655         Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1656
1657         /* Check the owner. */
1658         if (XGetSelectionOwner(DPY, XA_PRIMARY) == None)
1659         {
1660                 /* No selection. */
1661                 /* bell("No selection found."); */
1662                 return;
1663         }
1664
1665         request_target = target;
1666     
1667         /* Request the event */
1668         XConvertSelection(DPY, XA_PRIMARY, target, property, WIN, time);
1669 }
1670
1671
1672 /*
1673  * Add the contents of the PRIMARY buffer to the input queue.
1674  *
1675  * Hack - This doesn't use the "time" of the event, and so accepts anything a
1676  * client tries to send it.
1677  */
1678 static void paste_x11_accept(const XSelectionEvent *ptr)
1679 {
1680         unsigned long left;
1681         const long offset = 0;
1682         const long length = 32000;
1683         XTextProperty xtextproperty;
1684         errr err = 0;
1685
1686         /*
1687          * It's from some sample programs on the web.
1688          * What does it mean? -- XXX
1689          */
1690         Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1691
1692
1693         /* Failure. */
1694         if (ptr->property == None)
1695         {
1696                 if (request_target == xa_compound_text)
1697                 {
1698                         /* Re-request as STRING */
1699                         paste_x11_request(XA_STRING, ptr->time);
1700                 }
1701                 else
1702                 {
1703                         request_target = 0;
1704                         plog("Paste failure (remote client could not send).");
1705                 }
1706                 return;
1707         }
1708
1709         if (ptr->selection != XA_PRIMARY)
1710         {
1711                 plog("Paste failure (remote client did not send primary selection).");
1712                 return;
1713         }
1714
1715         if (ptr->target != request_target)
1716         {
1717                 plog("Paste failure (selection in unknown format).");
1718                 return;
1719         }
1720
1721         /* Get text */
1722         if (XGetWindowProperty(Metadpy->dpy, Infowin->win, property, offset,
1723                                length, TRUE, request_target,
1724                                &xtextproperty.encoding,
1725                                &xtextproperty.format,
1726                                &xtextproperty.nitems,
1727                                &left,
1728                                &xtextproperty.value)
1729             != Success)
1730         {
1731                 /* Failure */
1732                 return;
1733         }
1734
1735         if (request_target == xa_compound_text)
1736         {
1737                 char **list;
1738                 int count;
1739                 
1740                 XmbTextPropertyToTextList(DPY, &xtextproperty, &list, &count);
1741
1742                 if (list)
1743                 {
1744                         int i;
1745
1746                         for (i = 0; i < count; i++)
1747                         {
1748                                 /* Paste the text. */
1749                                 err = type_string(list[i], 0);
1750
1751                                 if (err) break;
1752                         }
1753
1754                         /* Free the string */
1755                         XFreeStringList(list);
1756                 }
1757         }
1758         else /* if (request_target == XA_STRING) */
1759         {
1760                 /* Paste the text. */
1761                 err = type_string((char *)xtextproperty.value, xtextproperty.nitems);
1762         }
1763
1764         /* Free the data pasted. */
1765         XFree(xtextproperty.value); 
1766
1767         /* No room. */
1768         if (err)
1769         {
1770                 plog("Paste failure (too much text selected).");
1771         }
1772 }
1773
1774
1775 /*
1776  * Add a character to a string in preparation for sending it to another
1777  * client as a STRING.
1778  * This doesn't change anything, as clients tend not to have difficulty in
1779  * receiving this format (although the standard specifies a restricted set).
1780  * Strings do not have a colour.
1781  */
1782 static bool paste_x11_send_text(XSelectionRequestEvent *rq)
1783 {
1784         char buf[1024];
1785         char *list[1000];
1786         co_ord max, min;
1787         TERM_LEN x,y;
1788         int l,n;
1789         TERM_COLOR a;
1790         char c;
1791
1792         /* Too old, or incorrect call. */
1793         if (rq->time < s_ptr->time) return FALSE;
1794
1795         /* Work out which way around to paste. */
1796         sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
1797
1798         /* Paranoia. */
1799         if (XGetSelectionOwner(DPY, XA_PRIMARY) != WIN)
1800         {
1801                 /* bell("Someone stole my selection!"); */
1802                 return FALSE;
1803         }
1804
1805         /* Delete the old value of the property. */
1806         XDeleteProperty(DPY, rq->requestor, rq->property);
1807
1808         for (n = 0, y = 0; y < Term->hgt; y++)
1809         {
1810 #ifdef JP
1811                 int kanji = 0;
1812 #endif
1813                 if (y < min.y) continue;
1814                 if (y > max.y) break;
1815
1816                 for (l = 0, x = 0; x < Term->wid; x++)
1817                 {
1818 #ifdef JP
1819                         if (x > max.x) break;
1820
1821                         /* Find the character. */
1822                         Term_what(x, y, &a, &c);
1823
1824                         if (1 == kanji) kanji = 2;
1825                         else if (iskanji(c)) kanji = 1;
1826                         else kanji = 0;
1827
1828                         if (x < min.x) continue;
1829
1830                         /*
1831                          * A single kanji character was divided in two...
1832                          * Delete the garbage.
1833                          */
1834                         if ((2 == kanji && x == min.x) ||
1835                             (1 == kanji && x == max.x))
1836                                 c = ' ';
1837 #else
1838                         if (x > max.x) break;
1839                         if (x < min.x) continue;
1840
1841                         /* Find the character. */
1842                         Term_what(x, y, &a, &c);
1843 #endif
1844
1845                         /* Add it. */
1846                         buf[l] = c;
1847                         l++;
1848                 }
1849
1850                 /* Ignore trailing spaces */
1851                 while (buf[l-1] == ' ') l--;
1852
1853                 /* Terminate all line unless it's single line. */
1854                 if (min.y != max.y)
1855                 {
1856                         buf[l] = '\n';
1857                         l++;
1858                 }
1859
1860                 /* End of string */
1861                 buf[l] = '\0';
1862
1863                 list[n++] = (char *)string_make(buf);
1864         }
1865
1866         /* End of the list */
1867         list[n] = NULL;
1868
1869
1870         if (rq->target == XA_STRING)
1871         {
1872                 for (n = 0; list[n]; n++)
1873                 {
1874                         /* Send the (non-empty) string. */
1875                         XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
1876                                         PropModeAppend, (unsigned char *)list[n], strlen(list[n]));
1877                 }
1878         }
1879
1880         else if (rq->target == xa_text || 
1881                  rq->target == xa_compound_text)
1882         {
1883                 XTextProperty text_prop;
1884                 XICCEncodingStyle style;
1885
1886                 if (rq->target == xa_text)
1887                         style = XStdICCTextStyle;
1888                 else /* if (rq->target == xa_compound_text) */
1889                         style = XCompoundTextStyle;
1890
1891                 if (Success ==
1892                     XmbTextListToTextProperty(DPY, list, n, style, &text_prop))
1893                 {
1894                         /* Send the compound text */
1895                         XChangeProperty(DPY,
1896                                         rq->requestor,
1897                                         rq->property,
1898                                         text_prop.encoding,
1899                                         text_prop.format,
1900                                         PropModeAppend,
1901                                         text_prop.value,
1902                                         text_prop.nitems);
1903                                 
1904                         /* Free the data. */
1905                         XFree(text_prop.value);
1906                 }
1907         }
1908
1909         /* Free the list of strings */
1910         for (n = 0; list[n]; n++)
1911         {
1912                 string_free(list[n]);
1913         }
1914
1915         return TRUE;
1916 }
1917
1918 /*
1919  * Send some text requested by another X client.
1920  */
1921 static void paste_x11_send(XSelectionRequestEvent *rq)
1922 {
1923         XEvent event;
1924         XSelectionEvent *ptr = &(event.xselection);
1925
1926         /* Set the event parameters. */
1927         ptr->type = SelectionNotify;
1928         ptr->property = rq->property;
1929         ptr->display = rq->display;
1930         ptr->requestor = rq->requestor;
1931         ptr->selection = rq->selection;
1932         ptr->target = rq->target;
1933         ptr->time = rq->time;
1934
1935         /* Paste the appropriate information for each target type.
1936          * Note that this currently rejects MULTIPLE targets.
1937          */
1938
1939         if (rq->target == XA_STRING ||
1940             rq->target == xa_text ||
1941             rq->target == xa_compound_text)
1942         {
1943                 if (!paste_x11_send_text(rq))
1944                         ptr->property = None;
1945         }
1946         else if (rq->target == xa_targets)
1947         {
1948                 Atom target_list[4];
1949                 target_list[0] = XA_STRING;
1950                 target_list[1] = xa_text;
1951                 target_list[2] = xa_compound_text;
1952                 target_list[3] = xa_targets;
1953                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
1954                         (8 * sizeof(target_list[0])), PropModeReplace,
1955                         (unsigned char *)target_list,
1956                         (sizeof(target_list) / sizeof(target_list[0])));
1957         }
1958         else if (rq->target == xa_timestamp)
1959         {
1960                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
1961                         (8 * sizeof(Time)), PropModeReplace,
1962                         (unsigned char *)s_ptr->time, 1);
1963         }
1964         else
1965         {
1966                 ptr->property = None;
1967         }
1968
1969         /* Send whatever event we're left with. */
1970         XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
1971 }
1972
1973
1974 /*
1975  * Handle various events conditional on presses of a mouse button.
1976  */
1977 static void handle_button(Time time, int x, int y, int button,
1978         bool press)
1979 {
1980         /* The co-ordinates are only used in Angband format. */
1981         pixel_to_square(&x, &y, x, y);
1982
1983         if (press && button == 1) copy_x11_start(x, y);
1984         if (!press && button == 1) copy_x11_end(time);
1985         if (!press && button == 2) paste_x11_request(xa_compound_text, time);
1986 }
1987
1988
1989 /*
1990  * Process events
1991  */
1992 static errr CheckEvent(bool wait)
1993 {
1994         term_data *old_td = (term_data*)(Term->data);
1995
1996         XEvent xev_body, *xev = &xev_body;
1997
1998         term_data *td = NULL;
1999         infowin *iwin = NULL;
2000
2001         int i;
2002
2003 #ifdef USE_XIM
2004         do
2005         {
2006 #endif
2007
2008                 /* Do not wait unless requested */
2009                 if (!wait && !XPending(Metadpy->dpy)) return (1);
2010
2011                 /*
2012                  * Hack - redraw the selection, if needed.
2013                  * This doesn't actually check that one of its squares was drawn to,
2014                  * only that this may have happened.
2015                  */
2016                 if (s_ptr->select && !s_ptr->drawn) mark_selection();
2017
2018                 /* Load the Event */
2019                 XNextEvent(Metadpy->dpy, xev);
2020
2021 #ifdef USE_XIM
2022         } while (XFilterEvent(xev, xev->xany.window));
2023 #endif
2024
2025         /* Notice new keymaps */
2026         if (xev->type == MappingNotify)
2027         {
2028                 XRefreshKeyboardMapping(&xev->xmapping);
2029                 return 0;
2030         }
2031
2032
2033         /* Scan the windows */
2034         for (i = 0; i < MAX_TERM_DATA; i++)
2035         {
2036                 if (!data[i].win) continue;
2037                 if (xev->xany.window == data[i].win->win)
2038                 {
2039                         td = &data[i];
2040                         iwin = td->win;
2041                         break;
2042                 }
2043         }
2044
2045         /* Unknown window */
2046         if (!td || !iwin) return (0);
2047
2048
2049         /* Hack -- activate the Term */
2050         Term_activate(&td->t);
2051
2052         /* Hack -- activate the window */
2053         Infowin_set(iwin);
2054
2055
2056         /* Switch on the Type */
2057         switch (xev->type)
2058         {
2059                 case ButtonPress:
2060                 case ButtonRelease:
2061                 {
2062                         bool press = (xev->type == ButtonPress);
2063
2064                         /* Where is the mouse */
2065                         int x = xev->xbutton.x;
2066                         int y = xev->xbutton.y;
2067
2068                         int z;
2069
2070                         /* Which button is involved */
2071                         if (xev->xbutton.button == Button1) z = 1;
2072                         else if (xev->xbutton.button == Button2) z = 2;
2073                         else if (xev->xbutton.button == Button3) z = 3;
2074                         else if (xev->xbutton.button == Button4) z = 4;
2075                         else if (xev->xbutton.button == Button5) z = 5;
2076                         else z = 0;
2077
2078                         /* XXX Handle */
2079                         handle_button(xev->xbutton.time, x, y, z, press);
2080
2081                         break;
2082                 }
2083
2084                 case EnterNotify:
2085                 case LeaveNotify:
2086                 {
2087                         /* XXX Handle */
2088
2089                         break;
2090                 }
2091
2092                 case MotionNotify:
2093                 {
2094                         /* Where is the mouse */
2095                         int x = xev->xmotion.x;
2096                         int y = xev->xmotion.y;
2097                         unsigned int z = xev->xmotion.state;
2098
2099                         /* Convert to co-ordinates Angband understands. */
2100                         pixel_to_square(&x, &y, x, y);
2101
2102                         /* Highlight the current square, if appropriate. */
2103                         /* highlight_square(window, y, x); */
2104
2105                         /* Alter the selection if appropriate. */
2106                         copy_x11_cont(x, y, z);
2107
2108                         /* XXX Handle */
2109
2110                         break;
2111                 }
2112
2113                 case SelectionNotify:
2114                 {
2115                         paste_x11_accept(&(xev->xselection));
2116                         break;
2117                 }
2118
2119                 case SelectionRequest:
2120                 {
2121                         paste_x11_send(&(xev->xselectionrequest));
2122                         break;
2123                 }
2124
2125                 case SelectionClear:
2126                 {
2127                         s_ptr->select = FALSE;
2128                         mark_selection();
2129                         break;
2130                 }
2131
2132                 case KeyRelease:
2133                 {
2134                         /* Nothing */
2135                         break;
2136                 }
2137
2138                 case KeyPress:
2139                 {
2140                         /* Hack -- use "old" term */
2141                         Term_activate(&old_td->t);
2142
2143                         /* Process the key */
2144                         react_keypress(&(xev->xkey));
2145
2146                         break;
2147                 }
2148
2149                 case Expose:
2150                 {
2151                         int x1, x2, y1, y2;
2152                         
2153                         /* Ignore "extra" exposes */
2154                         /*if (xev->xexpose.count) break;*/
2155
2156                         /* Clear the window */
2157                         /*Infowin_wipe();*/
2158                         
2159                         x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
2160                         x2 = (xev->xexpose.x + xev->xexpose.width -
2161                                  Infowin->ox)/Infofnt->wid;
2162                         
2163                         y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
2164                         y2 = (xev->xexpose.y + xev->xexpose.height -
2165                                  Infowin->oy)/Infofnt->hgt;
2166                         
2167                         Term_redraw_section(x1, y1, x2, y2);
2168
2169                         /* Redraw */
2170                         /*Term_redraw();*/
2171
2172                         break;
2173                 }
2174
2175                 case MapNotify:
2176                 {
2177                         Infowin->mapped = 1;
2178                         Term->mapped_flag = TRUE;
2179                         break;
2180                 }
2181
2182                 case UnmapNotify:
2183                 {
2184                         Infowin->mapped = 0;
2185                         Term->mapped_flag = FALSE;
2186                         break;
2187                 }
2188
2189                 /* Move and/or Resize */
2190                 case ConfigureNotify:
2191                 {
2192                         int cols, rows, wid, hgt;
2193
2194                         int ox = Infowin->ox;
2195                         int oy = Infowin->oy;
2196
2197                         /* Save the new Window Parms */
2198                         Infowin->x = xev->xconfigure.x;
2199                         Infowin->y = xev->xconfigure.y;
2200                         Infowin->w = xev->xconfigure.width;
2201                         Infowin->h = xev->xconfigure.height;
2202
2203                         /* Determine "proper" number of rows/cols */
2204                         cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
2205                         rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
2206
2207                         /* Hack -- minimal size */
2208                         if (cols < 1) cols = 1;
2209                         if (rows < 1) rows = 1;
2210
2211                         if (td == &data[0])
2212                         {
2213                                 /* Hack the main window must be at least 80x24 */
2214                                 if (cols < 80) cols = 80;
2215                                 if (rows < 24) rows = 24;
2216                         }
2217
2218                         /* Desired size of window */
2219                         wid = cols * td->fnt->wid + (ox + ox);
2220                         hgt = rows * td->fnt->hgt + (oy + oy);
2221
2222                         /* Resize the Term (if needed) */
2223                         Term_resize(cols, rows);
2224
2225                         /* Resize the windows if any "change" is needed */
2226                         if ((Infowin->w != wid) || (Infowin->h != hgt))
2227                         {
2228                                 /* Resize window */
2229                                 Infowin_set(td->win);
2230                                 Infowin_resize(wid, hgt);
2231                         }
2232
2233                         break;
2234                 }
2235 #ifdef USE_XIM
2236                 case FocusIn:
2237                 {
2238                         if(iwin->xic){
2239                                 XSetICFocus(iwin->xic);
2240                         }
2241                         Focuswin = iwin;
2242                         break;
2243                 }
2244                 case FocusOut:
2245                 {
2246                         if(iwin->xic){
2247                                 XUnsetICFocus(iwin->xic);
2248                         }
2249                         /* Focuswin = NULL;*/
2250                         break;
2251                 }
2252 #endif
2253         }
2254
2255
2256         /* Hack -- Activate the old term */
2257         Term_activate(&old_td->t);
2258
2259         /* Hack -- Activate the proper window */
2260         Infowin_set(old_td->win);
2261
2262
2263         /* Success */
2264         return (0);
2265 }
2266
2267
2268 /*
2269  * An array of sound file names
2270  */
2271 static concptr sound_file[SOUND_MAX];
2272
2273 /*
2274  * Check for existance of a file
2275  */
2276 static bool check_file(concptr s)
2277 {
2278         FILE *fff;
2279
2280         fff = fopen(s, "r");
2281         if (!fff) return (FALSE);
2282         
2283         fclose(fff);
2284         return (TRUE);
2285 }
2286
2287 /*
2288  * Initialize sound
2289  */
2290 static void init_sound(void)
2291 {
2292         int i;
2293         char wav[128];
2294         char buf[1024];
2295         char dir_xtra_sound[1024];
2296                 
2297         /* Build the "sound" path */
2298         path_build(dir_xtra_sound, sizeof(dir_xtra_sound), ANGBAND_DIR_XTRA, "sound");
2299                 
2300         /* Prepare the sounds */
2301         for (i = 1; i < SOUND_MAX; i++)
2302         {
2303                 /* Extract name of sound file */
2304                 sprintf(wav, "%s.wav", angband_sound_name[i]);
2305                 
2306                 /* Access the sound */
2307                 path_build(buf, sizeof(buf), dir_xtra_sound, wav);
2308                 
2309                 /* Save the sound filename, if it exists */
2310                 if (check_file(buf)) sound_file[i] = string_make(buf);
2311         }
2312         use_sound = TRUE;
2313         return;
2314 }
2315
2316 /*
2317  * Hack -- make a sound
2318  */
2319 static errr Term_xtra_x11_sound(int v)
2320 {
2321         char buf[1024];
2322         
2323         /* Sound disabled */
2324         if (!use_sound) return (1);
2325         
2326         /* Illegal sound */
2327         if ((v < 0) || (v >= SOUND_MAX)) return (1);
2328         
2329         /* Unknown sound */
2330         if (!sound_file[v]) return (1);
2331         
2332         sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
2333         
2334         return (system(buf) < 0);
2335         
2336 }
2337
2338
2339 /*
2340  * Handle "activation" of a term
2341  */
2342 static errr Term_xtra_x11_level(int v)
2343 {
2344         term_data *td = (term_data*)(Term->data);
2345
2346         /* Handle "activate" */
2347         if (v)
2348         {
2349                 /* Activate the window */
2350                 Infowin_set(td->win);
2351
2352                 /* Activate the font */
2353                 Infofnt_set(td->fnt);
2354         }
2355
2356         /* Success */
2357         return (0);
2358 }
2359
2360
2361 /*
2362  * React to changes
2363  */
2364 static errr Term_xtra_x11_react(void)
2365 {
2366         int i;
2367         
2368         if (Metadpy->color)
2369         {
2370                 /* Check the colors */
2371                 for (i = 0; i < 256; i++)
2372                 {
2373                         if ((color_table[i][0] != angband_color_table[i][0]) ||
2374                             (color_table[i][1] != angband_color_table[i][1]) ||
2375                             (color_table[i][2] != angband_color_table[i][2]) ||
2376                             (color_table[i][3] != angband_color_table[i][3]))
2377                         {
2378                                 Pixell pixel;
2379
2380                                 /* Save new values */
2381                                 color_table[i][0] = angband_color_table[i][0];
2382                                 color_table[i][1] = angband_color_table[i][1];
2383                                 color_table[i][2] = angband_color_table[i][2];
2384                                 color_table[i][3] = angband_color_table[i][3];
2385
2386                                 /* Create pixel */
2387                                 pixel = create_pixel(Metadpy->dpy,
2388                                                      color_table[i][1],
2389                                                      color_table[i][2],
2390                                                      color_table[i][3]);
2391
2392                                 /* Change the foreground */
2393                                 Infoclr_set(clr[i]);
2394                                 Infoclr_change_fg(pixel);
2395                         }
2396                 }
2397         }
2398
2399         /* Success */
2400         return (0);
2401 }
2402
2403
2404 /*
2405  * Handle a "special request"
2406  */
2407 static errr Term_xtra_x11(int n, int v)
2408 {
2409         /* Handle a subset of the legal requests */
2410         switch (n)
2411         {
2412                 /* Make a noise */
2413                 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
2414
2415                 /* Make a special sound */
2416                 case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
2417
2418                 /* Flush the output XXX XXX */
2419 #ifdef USE_XFT
2420                 case TERM_XTRA_FRESH: Metadpy_update(1, 1, 0); return (0);
2421 #else
2422                 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
2423 #endif
2424
2425                 /* Process random events XXX */
2426                 case TERM_XTRA_BORED: return (CheckEvent(0));
2427
2428                 /* Process Events XXX */
2429                 case TERM_XTRA_EVENT: return (CheckEvent(v));
2430
2431                 /* Flush the events XXX */
2432                 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
2433
2434                 /* Handle change in the "level" */
2435                 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
2436
2437                 /* Clear the screen */
2438                 case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
2439
2440                 /* Delay for some milliseconds */
2441                 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
2442
2443                 /* React to changes */
2444                 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
2445         }
2446
2447         /* Unknown */
2448         return (1);
2449 }
2450
2451
2452 /*
2453  * Draw the cursor as an inverted rectangle.
2454  *
2455  * Consider a rectangular outline like "main-mac.c".  XXX XXX
2456  */
2457 static errr Term_curs_x11(int x, int y)
2458 {
2459         if (use_graphics)
2460         {
2461 #ifdef USE_XFT
2462                 XftDrawRect(Infowin->draw, &xor->fg,
2463                             x * Infofnt->wid + Infowin->ox,
2464                             y * Infofnt->hgt + Infowin->oy,
2465                             Infofnt->wid - 1, Infofnt->hgt - 1);
2466                 XftDrawRect(Infowin->draw, &xor->fg,
2467                             x * Infofnt->wid + Infowin->ox + 1,
2468                             y * Infofnt->hgt + Infowin->oy + 1,
2469                             Infofnt->wid - 3, Infofnt->hgt - 3);
2470 #else
2471                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2472                                x * Infofnt->wid + Infowin->ox,
2473                                y * Infofnt->hgt + Infowin->oy,
2474                                Infofnt->wid - 1, Infofnt->hgt - 1);
2475                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2476                                x * Infofnt->wid + Infowin->ox + 1,
2477                                y * Infofnt->hgt + Infowin->oy + 1,
2478                                Infofnt->wid - 3, Infofnt->hgt - 3);
2479 #endif
2480         }
2481         else
2482         {
2483                 /* Draw the cursor */
2484                 Infoclr_set(xor);
2485
2486                 /* Hilite the cursor character */
2487                 Infofnt_text_non(x, y, " ", 1);
2488         }
2489
2490         /* Success */
2491         return (0);
2492 }
2493
2494
2495 /*
2496  * Draw the double width cursor
2497  */
2498 static errr Term_bigcurs_x11(int x, int y)
2499 {
2500         if (use_graphics)
2501         {
2502 #ifdef USE_XFT
2503                 XftDrawRect(Infowin->draw, &xor->fg,
2504                             x * Infofnt->wid + Infowin->ox,
2505                             y * Infofnt->hgt + Infowin->oy,
2506                             Infofnt->twid - 1, Infofnt->hgt - 1);
2507                 XftDrawRect(Infowin->draw, &xor->fg,
2508                             x * Infofnt->wid + Infowin->ox + 1,
2509                             y * Infofnt->hgt + Infowin->oy + 1,
2510                             Infofnt->twid - 3, Infofnt->hgt - 3);
2511 #else
2512                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2513                                x * Infofnt->wid + Infowin->ox,
2514                                y * Infofnt->hgt + Infowin->oy,
2515                                Infofnt->twid - 1, Infofnt->hgt - 1);
2516                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2517                                x * Infofnt->wid + Infowin->ox + 1,
2518                                y * Infofnt->hgt + Infowin->oy + 1,
2519                                Infofnt->twid - 3, Infofnt->hgt - 3);
2520 #endif
2521         }
2522         else
2523         {
2524                 /* Draw the cursor */
2525                 Infoclr_set(xor);
2526
2527                 /* Hilite the cursor character */
2528                 Infofnt_text_non(x, y, "  ", 2);
2529         }
2530         /* Success */
2531         return (0);
2532 }
2533
2534
2535 /*
2536  * Erase some characters.
2537  */
2538 static errr Term_wipe_x11(int x, int y, int n)
2539 {
2540         /* Erase (use black) */
2541         Infoclr_set(clr[TERM_DARK]);
2542
2543         /* Mega-Hack -- Erase some space */
2544         Infofnt_text_non(x, y, "", n);
2545
2546         /* Redraw the selection if any, as it may have been obscured. (later) */
2547         s_ptr->drawn = FALSE;
2548
2549         /* Success */
2550         return (0);
2551 }
2552
2553
2554 /*
2555  * Draw some textual characters.
2556  */
2557 static errr Term_text_x11(TERM_LEN x, TERM_LEN y, int n, TERM_COLOR a, concptr s)
2558 {
2559         /* Draw the text */
2560         Infoclr_set(clr[a]);
2561
2562         /* Draw the text */
2563         Infofnt_text_std(x, y, s, n);
2564
2565         /* Redraw the selection if any, as it may have been obscured. (later) */
2566         s_ptr->drawn = FALSE;
2567
2568         /* Success */
2569         return (0);
2570 }
2571
2572
2573 #ifndef USE_XFT
2574 /*
2575  * Draw some graphical characters.
2576  */
2577 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)
2578 {
2579         int i, x1, y1;
2580
2581         TERM_COLOR a;
2582         char c;
2583
2584         TERM_COLOR ta;
2585         char tc;
2586
2587         int x2, y2;
2588         int k,l;
2589
2590         unsigned long pixel, blank;
2591
2592         term_data *td = (term_data*)(Term->data);
2593
2594         y *= Infofnt->hgt;
2595         x *= Infofnt->wid;
2596
2597         /* Add in affect of window boundaries */
2598         y += Infowin->oy;
2599         x += Infowin->ox;
2600
2601         for (i = 0; i < n; ++i, x += td->fnt->wid)
2602         {
2603                 a = *ap++;
2604                 c = *cp++;
2605
2606                 /* For extra speed - cache these values */
2607                 x1 = (c&0x7F) * td->fnt->twid;
2608                 y1 = (a&0x7F) * td->fnt->hgt;
2609
2610                 /* Illegal tile index */
2611                 if (td->tiles->width < x1 + td->fnt->wid ||
2612                     td->tiles->height < y1 + td->fnt->hgt)
2613                 {
2614                         /* Draw black square */
2615                         XFillRectangle(Metadpy->dpy, td->win->win, clr[0]->gc,
2616                                        x, y, 
2617                                        td->fnt->twid, td->fnt->hgt);
2618
2619                         /* Skip drawing tile */
2620                         continue;
2621                 }
2622
2623                 ta = *tap++;
2624                 tc = *tcp++;
2625
2626                 /* For extra speed - cache these values */
2627                 x2 = (tc&0x7F) * td->fnt->twid;
2628                 y2 = (ta&0x7F) * td->fnt->hgt;
2629                 
2630                 /* Optimise the common case */
2631                 if (((x1 == x2) && (y1 == y2)) ||
2632                     !(((byte)ta & 0x80) && ((byte)tc & 0x80)) ||
2633                     td->tiles->width < x2 + td->fnt->wid ||
2634                     td->tiles->height < y2 + td->fnt->hgt)
2635                 {
2636                         /* Draw object / terrain */
2637                         XPutImage(Metadpy->dpy, td->win->win,
2638                                 clr[0]->gc,
2639                                 td->tiles,
2640                                 x1, y1,
2641                                 x, y,
2642                                 td->fnt->twid, td->fnt->hgt);   
2643                 }
2644                 else
2645                 {
2646
2647                         /* Mega Hack^2 - assume the top left corner is "black" */
2648                         blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
2649
2650                         for (k = 0; k < td->fnt->twid; k++)
2651                         {
2652                                 for (l = 0; l < td->fnt->hgt; l++)
2653                                 {
2654                                         /* If mask set... */
2655                                         if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
2656                                         {
2657                                                 /* Output from the terrain */
2658                                                 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
2659                                         }
2660                                         
2661                                         /* Store into the temp storage. */
2662                                         XPutPixel(td->TmpImage, k, l, pixel);
2663                                 }
2664                         }
2665
2666
2667                         /* Draw to screen */
2668
2669                         XPutImage(Metadpy->dpy, td->win->win,
2670                               clr[0]->gc,
2671                              td->TmpImage,
2672                              0, 0, x, y,
2673                              td->fnt->twid, td->fnt->hgt);
2674                 }
2675         }
2676
2677         /* Redraw the selection if any, as it may have been obscured. (later) */
2678         s_ptr->drawn = FALSE;
2679
2680         /* Success */
2681         return (0);
2682 }
2683 #endif
2684
2685 #ifdef USE_XIM
2686 static void IMDestroyCallback(XIM, XPointer, XPointer);
2687
2688 static void
2689 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
2690 {
2691         XIM xim;
2692         XIMCallback ximcallback;
2693         XIMStyles *xim_styles = NULL;
2694         int i;
2695
2696         /* Unused */
2697         (void)unused1;
2698         (void)unused2;
2699
2700         xim = XOpenIM(display, NULL, NULL, NULL);
2701         if(!xim){
2702                 printf("can't open IM\n");
2703                 return;
2704         }
2705
2706         /* initialize destroy callback */
2707         ximcallback.callback = IMDestroyCallback;
2708         ximcallback.client_data = NULL;
2709         XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
2710
2711         /* set style (only "Root" is supported yet...) */
2712         XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
2713         for (i = 0; i < xim_styles->count_styles; i++){
2714                 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
2715         }
2716         if(i >= xim_styles->count_styles){
2717                 printf("Sorry, your IM does not support 'Root' preedit style...\n");
2718                 XCloseIM(xim);
2719                 return;
2720         }
2721         XFree(xim_styles);
2722
2723         Metadpy->xim = xim;
2724
2725         for (i = 0; i < MAX_TERM_DATA; i++)
2726         {
2727                 infowin *iwin = data[i].win;
2728                 if (!iwin) continue;
2729                 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
2730                 if(!iwin->xic){
2731                         printf("Can't create input context for Term%d\n", i);
2732                         continue;
2733                 }
2734                 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL){
2735 /*                      printf("Can't get XNFilterEvents\n"); */
2736                         iwin->xic_mask = 0L;
2737                 }
2738                 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
2739         }
2740
2741         return;
2742 }
2743
2744 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
2745 {
2746         int i;
2747
2748         /* Unused */
2749         (void)xim;
2750         (void)client_data;
2751
2752         if (call_data == NULL){
2753                 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
2754         }
2755
2756         for(i = 0; i < MAX_TERM_DATA; i++)
2757         {
2758                 infowin *iwin = data[i].win;
2759                 if(!iwin) continue;
2760                 if(iwin->xic_mask){
2761                         XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
2762                         iwin->xic_mask = 0L;
2763                 }
2764                 iwin->xic = NULL;
2765         }
2766
2767         Metadpy->xim = NULL;
2768 }
2769 #endif
2770
2771 /*
2772  * Initialize a term_data
2773  */
2774 static errr term_data_init(term_data *td, int i)
2775 {
2776         term *t = &td->t;
2777
2778         concptr name = angband_term_name[i];
2779
2780         concptr font;
2781         int x = 0;
2782         int y = 0;
2783
2784         int cols = 80;
2785         int rows = 24;
2786
2787         int ox = 1;
2788         int oy = 1;
2789
2790         int wid, hgt, num;
2791
2792         char buf[80];
2793
2794         concptr str;
2795
2796         int val;
2797
2798         XClassHint *ch;
2799
2800         char res_name[20];
2801         char res_class[20];
2802
2803         XSizeHints *sh;
2804 #ifdef USE_XIM
2805         XWMHints *wh;
2806 #endif
2807
2808         /* Window specific font name */
2809         sprintf(buf, "ANGBAND_X11_FONT_%d", i);
2810
2811         /* Check environment for that font */
2812         font = getenv(buf);
2813
2814         /* Check environment for "base" font */
2815         if (!font) font = getenv("ANGBAND_X11_FONT");
2816
2817         /* No environment variables, use default font */
2818         if (!font)
2819         {
2820                 switch (i)
2821                 {
2822                         case 0:
2823                         {
2824                                 font = DEFAULT_X11_FONT_0;
2825                         }
2826                         break;
2827                         case 1:
2828                         {
2829                                 font = DEFAULT_X11_FONT_1;
2830                         }
2831                         break;
2832                         case 2:
2833                         {
2834                                 font = DEFAULT_X11_FONT_2;
2835                         }
2836                         break;
2837                         case 3:
2838                         {
2839                                 font = DEFAULT_X11_FONT_3;
2840                         }
2841                         break;
2842                         case 4:
2843                         {
2844                                 font = DEFAULT_X11_FONT_4;
2845                         }
2846                         break;
2847                         case 5:
2848                         {
2849                                 font = DEFAULT_X11_FONT_5;
2850                         }
2851                         break;
2852                         case 6:
2853                         {
2854                                 font = DEFAULT_X11_FONT_6;
2855                         }
2856                         break;
2857                         case 7:
2858                         {
2859                                 font = DEFAULT_X11_FONT_7;
2860                         }
2861                         break;
2862                         default:
2863                         {
2864                                 font = DEFAULT_X11_FONT;
2865                         }
2866                 }
2867         }
2868
2869         /* Window specific location (x) */
2870         sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
2871         str = getenv(buf);
2872         x = (str != NULL) ? atoi(str) : -1;
2873
2874         /* Window specific location (y) */
2875         sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
2876         str = getenv(buf);
2877         y = (str != NULL) ? atoi(str) : -1;
2878
2879
2880         /* Window specific cols */
2881         sprintf(buf, "ANGBAND_X11_COLS_%d", i);
2882         str = getenv(buf);
2883         val = (str != NULL) ? atoi(str) : -1;
2884         if (val > 0) cols = val;
2885
2886         /* Window specific rows */
2887         sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
2888         str = getenv(buf);
2889         val = (str != NULL) ? atoi(str) : -1;
2890         if (val > 0) rows = val;
2891
2892         /* Hack the main window must be at least 80x24 */
2893         if (!i)
2894         {
2895                 if (cols < 80) cols = 80;
2896                 if (rows < 24) rows = 24;
2897         }
2898
2899         /* Window specific inner border offset (ox) */
2900         sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
2901         str = getenv(buf);
2902         val = (str != NULL) ? atoi(str) : -1;
2903         if (val > 0) ox = val;
2904
2905         /* Window specific inner border offset (oy) */
2906         sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
2907         str = getenv(buf);
2908         val = (str != NULL) ? atoi(str) : -1;
2909         if (val > 0) oy = val;
2910
2911
2912         /* Prepare the standard font */
2913         MAKE(td->fnt, infofnt);
2914         Infofnt_set(td->fnt);
2915         Infofnt_init_data(font);
2916
2917         /* Hack -- key buffer size */
2918         num = ((i == 0) ? 1024 : 16);
2919
2920         /* Assume full size windows */
2921         wid = cols * td->fnt->wid + (ox + ox);
2922         hgt = rows * td->fnt->hgt + (oy + oy);
2923
2924         /* Create a top-window */
2925         MAKE(td->win, infowin);
2926         Infowin_set(td->win);
2927         Infowin_init_top(x, y, wid, hgt, 0,
2928                          Metadpy->fg, Metadpy->bg);
2929
2930         /* Ask for certain events */
2931 #if defined(USE_XIM)
2932         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask);
2933 #else
2934         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
2935 #endif
2936
2937         /* Set the window name */
2938         Infowin_set_name(name);
2939
2940         /* Save the inner border */
2941         Infowin->ox = ox;
2942         Infowin->oy = oy;
2943
2944         /* Make Class Hints */
2945         ch = XAllocClassHint();
2946
2947         if (ch == NULL) quit("XAllocClassHint failed");
2948
2949         strcpy(res_name, name);
2950         res_name[0] = FORCELOWER(res_name[0]);
2951         ch->res_name = res_name;
2952
2953         strcpy(res_class, "Angband");
2954         ch->res_class = res_class;
2955
2956         XSetClassHint(Metadpy->dpy, Infowin->win, ch);
2957
2958         /* Make Size Hints */
2959         sh = XAllocSizeHints();
2960
2961         /* Oops */
2962         if (sh == NULL) quit("XAllocSizeHints failed");
2963
2964         /* Main window has a differing minimum size */
2965         if (i == 0)
2966         {
2967                 /* Main window min size is 80x24 */
2968                 sh->flags = PMinSize | PMaxSize;
2969                 sh->min_width = 80 * td->fnt->wid + (ox + ox);
2970                 sh->min_height = 24 * td->fnt->hgt + (oy + oy);
2971                 sh->max_width = 255 * td->fnt->wid + (ox + ox);
2972                 sh->max_height = 255 * td->fnt->hgt + (oy + oy);
2973         }
2974
2975         /* Other windows can be shrunk to 1x1 */
2976         else
2977         {
2978                 /* Other windows */
2979                 sh->flags = PMinSize | PMaxSize;
2980                 sh->min_width = td->fnt->wid + (ox + ox);
2981                 sh->min_height = td->fnt->hgt + (oy + oy);
2982                 sh->max_width = 256 * td->fnt->wid + (ox + ox);
2983                 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
2984         }
2985
2986         /* Resize increment */
2987         sh->flags |= PResizeInc;
2988         sh->width_inc = td->fnt->wid;
2989         sh->height_inc = td->fnt->hgt;
2990
2991         /* Base window size */
2992         sh->flags |= PBaseSize;
2993         sh->base_width = (ox + ox);
2994         sh->base_height = (oy + oy);
2995
2996         /* Use the size hints */
2997         XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
2998
2999         /* Map the window */
3000         Infowin_map();
3001
3002 #ifdef USE_XIM
3003         /* Make WM Hints */
3004         wh = XAllocWMHints();
3005         if(wh == NULL) quit("XAllocWMHints failed");
3006         wh->flags = InputHint;
3007         wh->input = True;
3008         XSetWMHints(Metadpy->dpy, Infowin->win, wh);
3009 #endif
3010
3011         /* Move the window to requested location */
3012         if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
3013
3014
3015         /* Initialize the term */
3016         term_init(t, cols, rows, num);
3017
3018         /* Use a "soft" cursor */
3019         t->soft_cursor = TRUE;
3020
3021         /* Erase with "white space" */
3022         t->attr_blank = TERM_WHITE;
3023         t->char_blank = ' ';
3024
3025         /* Hooks */
3026         t->xtra_hook = Term_xtra_x11;
3027         t->curs_hook = Term_curs_x11;
3028         t->bigcurs_hook = Term_bigcurs_x11;
3029         t->wipe_hook = Term_wipe_x11;
3030         t->text_hook = Term_text_x11;
3031
3032         /* Save the data */
3033         t->data = td;
3034
3035         /* Activate (important) */
3036         Term_activate(t);
3037
3038         /* Success */
3039         return (0);
3040 }
3041
3042
3043 /*
3044  * Initialization function for an "X11" module to Angband
3045  */
3046 errr init_x11(int argc, char *argv[])
3047 {
3048         int i;
3049
3050         concptr dpy_name = "";
3051
3052         int num_term = 3;
3053
3054 #ifndef USE_XFT
3055         char filename[1024];
3056
3057         int pict_wid = 0;
3058         int pict_hgt = 0;
3059
3060         char *TmpData;
3061 #endif
3062
3063         /* Parse args */
3064         for (i = 1; i < argc; i++)
3065         {
3066                 if (prefix(argv[i], "-d"))
3067                 {
3068                         dpy_name = &argv[i][2];
3069                         continue;
3070                 }
3071                 
3072 #ifndef USE_XFT
3073                 if (prefix(argv[i], "-s"))
3074                 {
3075                         smoothRescaling = FALSE;
3076                         continue;
3077                 }
3078
3079                 if (prefix(argv[i], "-a"))
3080                 {
3081                         arg_graphics = GRAPHICS_ADAM_BOLT;
3082                         continue;
3083                 }
3084
3085                 if (prefix(argv[i], "-o"))
3086                 {
3087                         arg_graphics = GRAPHICS_ORIGINAL;
3088                         continue;
3089                 }
3090 #endif
3091
3092                 if (prefix(argv[i], "-b"))
3093                 {
3094                         arg_bigtile = use_bigtile = TRUE;
3095                         continue;
3096                 }
3097
3098                 if (prefix(argv[i], "-n"))
3099                 {
3100                         num_term = atoi(&argv[i][2]);
3101                         if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
3102                         else if (num_term < 1) num_term = 1;
3103                         continue;
3104                 }
3105
3106                 if (prefix(argv[i], "--"))
3107                 {
3108                         /* Ignore */
3109                         continue;
3110                 }
3111
3112                 plog_fmt("Ignoring option: %s", argv[i]);
3113         }
3114
3115 #ifdef USE_LOCALE
3116
3117 #ifdef JP
3118         /* Get locale information from environment variables */
3119         setlocale(LC_ALL, "");
3120
3121 #ifdef DEFAULT_LOCALE
3122         if(!strcmp(setlocale(LC_ALL, NULL), "C")){
3123                 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
3124                 setlocale(LC_ALL, DEFAULT_LOCALE);
3125         }
3126 #endif
3127
3128         if(!strcmp(setlocale(LC_ALL, NULL), "C"))
3129         {
3130                 printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
3131         }
3132
3133         if(!XSupportsLocale()){
3134                 printf("can't support locale in X\n");
3135                 setlocale(LC_ALL, "C");
3136         }
3137 #else
3138         /* Set locale to "C" without using environment variables */
3139         setlocale(LC_ALL, "C");
3140 #endif /* JP */
3141
3142 #endif /* USE_LOCALE */
3143
3144
3145         /* Init the Metadpy if possible */
3146         if (Metadpy_init_name(dpy_name)) return (-1);
3147
3148
3149         /* Prepare cursor color */
3150         MAKE(xor, infoclr);
3151         Infoclr_set(xor);
3152         Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
3153
3154
3155         /* Prepare normal colors */
3156         for (i = 0; i < 256; ++i)
3157         {
3158                 Pixell pixel;
3159
3160                 MAKE(clr[i], infoclr);
3161
3162                 Infoclr_set(clr[i]);
3163
3164                 /* Acquire Angband colors */
3165                 color_table[i][0] = angband_color_table[i][0];
3166                 color_table[i][1] = angband_color_table[i][1];
3167                 color_table[i][2] = angband_color_table[i][2];
3168                 color_table[i][3] = angband_color_table[i][3];
3169
3170                 /* Default to monochrome */
3171                 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
3172
3173                 /* Handle color */
3174                 if (Metadpy->color)
3175                 {
3176                         /* Create pixel */
3177                         pixel = create_pixel(Metadpy->dpy,
3178                                              color_table[i][1],
3179                                              color_table[i][2],
3180                                              color_table[i][3]);
3181                 }
3182
3183                 /* Initialize the color */
3184                 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
3185         }
3186
3187
3188         /* Prepare required atoms. */
3189         set_atoms();
3190
3191
3192         /* Initialize the windows */
3193         for (i = 0; i < num_term; i++)
3194         {
3195                 term_data *td = &data[i];
3196
3197                 /* Initialize the term_data */
3198                 term_data_init(td, i);
3199
3200                 /* Save global entry */
3201                 angband_term[i] = Term;
3202         }
3203
3204         /* Raise the "Angband" window */
3205         Infowin_set(data[0].win);
3206         Infowin_raise();
3207
3208         /* Activate the "Angband" window screen */
3209         Term_activate(&data[0].t);
3210
3211 #ifdef USE_XIM
3212         {
3213                 char *p;
3214                 p = XSetLocaleModifiers("");
3215                 if(!p || !*p){
3216                         p = XSetLocaleModifiers("@im=");
3217                 }
3218 /*              printf("XMODIFIERS=\"%s\"\n", p); */
3219         }
3220         XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3221 #endif
3222
3223         /* initialize sound */
3224         if (arg_sound) init_sound();
3225
3226 #ifndef USE_XFT
3227         /* Try graphics */
3228         switch (arg_graphics)
3229         {
3230         case GRAPHICS_ORIGINAL:
3231                 /* Try the "8x8.bmp" file */
3232                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/8x8.bmp");
3233
3234                 /* Use the "8x8.bmp" file if it exists */
3235                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3236                 {
3237                         /* Use graphics */
3238                         use_graphics = TRUE;
3239
3240                         pict_wid = pict_hgt = 8;
3241
3242                         ANGBAND_GRAF = "old";
3243                         break;
3244                 }
3245                 /* Fall through */
3246
3247         case GRAPHICS_ADAM_BOLT:
3248                 /* Try the "16x16.bmp" file */
3249                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/16x16.bmp");
3250
3251                 /* Use the "16x16.bmp" file if it exists */
3252                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3253                 {
3254                         /* Use graphics */
3255                         use_graphics = TRUE;
3256
3257                         pict_wid = pict_hgt = 16;
3258
3259                         ANGBAND_GRAF = "new";
3260
3261                         break;
3262                 }
3263         }
3264
3265         /* Load graphics */
3266         if (use_graphics)
3267         {
3268                 Display *dpy = Metadpy->dpy;
3269
3270                 XImage *tiles_raw;
3271
3272                 /* Load the graphical tiles */
3273                 tiles_raw = ReadBMP(dpy, filename);
3274
3275                 /* Initialize the windows */
3276                 for (i = 0; i < num_term; i++)
3277                 {
3278                         term_data *td = &data[i];
3279
3280                         term *t = &td->t;
3281
3282                         /* Graphics hook */
3283                         t->pict_hook = Term_pict_x11;
3284
3285                         /* Use graphics sometimes */
3286                         t->higher_pict = TRUE;
3287
3288                         /* Resize tiles */
3289                         td->tiles =
3290                         ResizeImage(dpy, tiles_raw,
3291                                     pict_wid, pict_hgt,
3292                                     td->fnt->twid, td->fnt->hgt);
3293                 }
3294
3295                 /* Initialize the transparency masks */
3296                 for (i = 0; i < num_term; i++)
3297                 {
3298                         term_data *td = &data[i];
3299                         int ii, jj;
3300                         int depth = DefaultDepth(dpy, DefaultScreen(dpy));
3301                         Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
3302                         int total;
3303
3304
3305                         /* Determine total bytes needed for image */
3306                         ii = 1;
3307                         jj = (depth - 1) >> 2;
3308                         while (jj >>= 1) ii <<= 1;
3309                         total = td->fnt->twid * td->fnt->hgt * ii;
3310                         
3311                         
3312                         TmpData = (char *)malloc(total);
3313
3314                         td->TmpImage = XCreateImage(dpy,visual,depth,
3315                                 ZPixmap, 0, TmpData,
3316                                 td->fnt->twid, td->fnt->hgt, 8, 0);
3317
3318                 }
3319
3320                 /* Free tiles_raw? XXX XXX */
3321         }
3322 #endif /* ! USE_XFT */
3323
3324         /* Success */
3325         return (0);
3326 }
3327
3328 #endif /* USE_X11 */