OSDN Git Service

[Refactor] #40413 Separated x11-type-string.c/h from util.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 #include "system/angband.h"
96 #include "cmd-io/macro-util.h"
97 #include "game-option/runtime-arguments.h"
98 #include "game-option/special-options.h"
99 #include "io/files-util.h"
100 #include "main/sound-definitions-table.h"
101 #include "main/sound-of-music.h"
102 #include "main/x11-type-string.h"
103 #include "system/system-variables.h"
104 #include "term/gameterm.h"
105 #include "term/term-color-types.h"
106 #include "util/int-char-converter.h"
107
108 /*
109  * Available graphic modes
110  */
111 #define GRAPHICS_NONE       0
112 #define GRAPHICS_ORIGINAL   1
113 #define GRAPHICS_ADAM_BOLT  2
114 #define GRAPHICS_HENGBAND   3
115 #ifdef USE_X11
116 #ifndef __MAKEDEPEND__
117 #include <X11/Xlib.h>
118 #include <X11/Xutil.h>
119 #include <X11/keysym.h>
120 #include <X11/keysymdef.h>
121 #ifdef USE_LOCALE
122 #include <X11/Xlocale.h>
123 #endif
124 #include <X11/Xatom.h>
125 #endif /* __MAKEDEPEND__ */
126
127 #include <iconv.h>
128 #ifdef USE_XFT
129 #include <X11/Xft/Xft.h>
130 #endif
131
132 /*
133  * Include some helpful X11 code.
134  */
135 #include "maid-x11.c"
136
137
138 /*
139  * Notes on Colors:
140  *
141  *   1) On a monochrome (or "fake-monochrome") display, all colors
142  *   will be "cast" to "fg," except for the bg color, which is,
143  *   obviously, cast to "bg".  Thus, one can ignore this setting.
144  *
145  *   2) Because of the inner functioning of the color allocation
146  *   routines, colors may be specified as (a) a typical color name,
147  *   (b) a hexidecimal color specification (preceded by a pound sign),
148  *   or (c) by strings such as "fg", "bg", "zg".
149  *
150  *   3) Due to the workings of the init routines, many colors
151  *   may also be dealt with by their actual pixel values.  Note that
152  *   the pixel with all bits set is "zg = (1<<metadpy->depth)-1", which
153  *   is not necessarily either black or white.
154  */
155
156 /**** Generic Types ****/
157
158 /*
159  * An X11 pixell specifier
160  */
161 #ifdef USE_XFT
162 typedef XftColor Pixell;
163 #else
164 typedef unsigned long Pixell;
165 #endif
166
167 /*
168  * The structures defined below
169  */
170 typedef struct metadpy metadpy;
171 typedef struct infowin infowin;
172 typedef struct infoclr infoclr;
173 typedef struct infofnt infofnt;
174
175 /*
176  * A structure summarizing a given Display.
177  *
178  *      - The Display itself
179  *      - The default Screen for the display
180  *      - The virtual root (usually just the root)
181  *      - The default colormap (from a macro)
182  *
183  *      - The "name" of the display
184  *
185  *      - The socket to listen to for events
186  *
187  *      - The width of the display screen (from a macro)
188  *      - The height of the display screen (from a macro)
189  *      - The bit depth of the display screen (from a macro)
190  *
191  *      - The black Pixell (from a macro)
192  *      - The white Pixell (from a macro)
193  *
194  *      - The background Pixell (default: black)
195  *      - The foreground Pixell (default: white)
196  *      - The maximal Pixell (Equals: ((2 ^ depth)-1), is usually ugly)
197  *
198  *      - Bit Flag: Force all colors to black and white (default: !color)
199  *      - Bit Flag: Allow the use of color (default: depth > 1)
200  *      - Bit Flag: We created 'dpy', and so should nuke it when done.
201  */
202 struct metadpy
203 {
204         Display *dpy;
205         Screen *screen;
206         Window root;
207         Colormap cmap;
208 #ifdef USE_XIM
209         XIM xim;
210 #endif
211
212         char *name;
213
214         int fd;
215
216         uint width;
217         uint height;
218         uint depth;
219
220         Pixell black;
221         Pixell white;
222
223         Pixell bg;
224         Pixell fg;
225 #ifndef USE_XFT
226         Pixell zg;
227 #endif
228
229         uint mono:1;
230         uint color:1;
231         uint nuke:1;
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  * A Structure summarizing Operation+Color Information
295  *
296  *      - The actual GC corresponding to this info
297  *
298  *      - The Foreground Pixell Value
299  *      - The Background Pixell Value
300  *
301  *      - Num (0-15): The operation code (As in Clear, Xor, etc)
302  *      - Bit Flag: The GC is in stipple mode
303  *      - Bit Flag: Destroy 'gc' at Nuke time.
304  */
305 struct infoclr
306 {
307 #ifndef USE_XFT
308         GC gc;
309 #endif
310
311         Pixell fg;
312         Pixell bg;
313
314         uint code:4;
315         uint stip:1;
316         uint nuke:1;
317 };
318
319 /*
320  * A Structure to Hold Font Information
321  *
322  *      - The 'XFontStruct*' (yields the 'Font')
323  *
324  *      - The font name
325  *
326  *      - The default character width
327  *      - The default character height
328  *      - The default character ascent
329  *
330  *      - Byte: Pixel offset used during fake mono
331  *
332  *      - Flag: Force monospacing via 'wid'
333  *      - Flag: Nuke info when done
334  */
335 struct infofnt
336 {
337 #ifdef USE_XFT
338         XftFont *info;
339 #else
340         XFontSet info;
341 #endif
342         concptr name;
343
344         s16b wid;
345         s16b twid;
346         s16b hgt;
347         s16b asc;
348
349         byte off;
350
351         uint mono:1;
352         uint nuke:1;
353 };
354
355 /* Set current metadpy (Metadpy) to 'M' */
356 #define Metadpy_set(M) \
357         Metadpy = M
358
359 /* Initialize 'M' using Display 'D' */
360 #define Metadpy_init_dpy(D) \
361         Metadpy_init_2(D,cNULL)
362
363 /* Initialize 'M' using a Display named 'N' */
364 #define Metadpy_init_name(N) \
365         Metadpy_init_2((Display*)(NULL),N)
366
367 /* Initialize 'M' using the standard Display */
368 #define Metadpy_init() \
369         Metadpy_init_name("")
370
371 /* Init an infowin by giving father as an (info_win*) (or NULL), and data */
372 #define Infowin_init_dad(D,X,Y,W,H,B,FG,BG) \
373         Infowin_init_data(((D) ? ((D)->win) : (Window)(None)), \
374                           X,Y,W,H,B,FG,BG)
375
376 /* Init a top level infowin by pos,size,bord,Colors */
377 #define Infowin_init_top(X,Y,W,H,B,FG,BG) \
378         Infowin_init_data(None,X,Y,W,H,B,FG,BG)
379
380 /* Request a new standard window by giving Dad infowin and X,Y,W,H */
381 #define Infowin_init_std(D,X,Y,W,H,B) \
382         Infowin_init_dad(D,X,Y,W,H,B,Metadpy->fg,Metadpy->bg)
383
384 /* Set the current Infowin */
385 #define Infowin_set(I) \
386         (Infowin = (I))
387
388 /* Set the current Infoclr */
389 #define Infoclr_set(C) \
390         (Infoclr = (C))
391
392 #define Infoclr_init_ppo(F,B,O,M) \
393         Infoclr_init_data(F,B,O,M)
394
395 #define Infoclr_init_cco(F,B,O,M) \
396         Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M)
397
398 #define Infoclr_init_ppn(F,B,O,M) \
399         Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M)
400
401 #define Infoclr_init_ccn(F,B,O,M) \
402         Infoclr_init_cco(F,B,Infoclr_Opcode(O),M)
403
404 /* Set the current infofnt */
405 #define Infofnt_set(I) \
406         (Infofnt = (I))
407
408 /* Errr: Expose Infowin */
409 #define Infowin_expose() \
410         (!(Infowin->redraw = 1))
411
412 /* Errr: Unxpose Infowin */
413 #define Infowin_unexpose() \
414         (Infowin->redraw = 0)
415
416 /*
417  * The "default" values
418  */
419 static metadpy metadpy_default;
420
421 /*
422  * The "current" variables
423  */
424 static metadpy *Metadpy = &metadpy_default;
425 static infowin *Infowin = (infowin*)(NULL);
426 #ifdef USE_XIM
427 static infowin *Focuswin = (infowin*)(NULL);
428 #endif
429 static infoclr *Infoclr = (infoclr*)(NULL);
430 static infofnt *Infofnt = (infofnt*)(NULL);
431
432 /*
433  * Init the current metadpy, with various initialization stuff.
434  *
435  * Inputs:
436  *      dpy:  The Display* to use (if NULL, create it)
437  *      name: The name of the Display (if NULL, the current)
438  *
439  * Notes:
440  *      If 'name' is NULL, but 'dpy' is set, extract name from dpy
441  *      If 'dpy' is NULL, then Create the named Display
442  *      If 'name' is NULL, and so is 'dpy', use current Display
443  *
444  * Return -1 if no Display given, and none can be opened.
445  */
446 static errr Metadpy_init_2(Display *dpy, concptr name)
447 {
448         metadpy *m = Metadpy;
449         if (!dpy)
450         {
451                 dpy = XOpenDisplay(name);
452                 if (!dpy) return (-1);
453
454                 m->nuke = 1;
455         }
456         else
457         {
458                 m->nuke = 0;
459         }
460
461         m->dpy = dpy;
462         m->screen = DefaultScreenOfDisplay(dpy);
463         m->root = RootWindowOfScreen(m->screen);
464         m->cmap = DefaultColormapOfScreen(m->screen);
465         m->name = DisplayString(dpy);
466         m->fd = ConnectionNumber(Metadpy->dpy);
467         m->width = WidthOfScreen(m->screen);
468         m->height = HeightOfScreen(m->screen);
469         m->depth = DefaultDepthOfScreen(m->screen);
470
471 #ifdef USE_XFT
472         Visual *vis = DefaultVisual(dpy, 0);
473         XftColorAllocName(dpy, vis, m->cmap, "black", &m->black);
474         XftColorAllocName(dpy, vis, m->cmap, "white", &m->white);
475 #else
476         m->black = BlackPixelOfScreen(m->screen);
477         m->white = WhitePixelOfScreen(m->screen);
478 #endif
479
480         m->bg = m->black;
481         m->fg = m->white;
482
483 #ifndef USE_XFT
484         m->zg = (1 << m->depth) - 1;
485 #endif
486
487         m->color = ((m->depth > 1) ? 1 : 0);
488         m->mono = ((m->color) ? 0 : 1);
489         return (0);
490 }
491
492 /*
493  * General Flush/ Sync/ Discard routine
494  */
495 static errr Metadpy_update(int flush, int sync, int discard)
496 {
497         if (flush) XFlush(Metadpy->dpy);
498         if (sync) XSync(Metadpy->dpy, discard);
499
500         return (0);
501 }
502
503
504 /*
505  * Make a simple beep
506  */
507 static errr Metadpy_do_beep(void)
508 {
509         XBell(Metadpy->dpy, 100);
510         return (0);
511 }
512
513 /*
514  * Set the name (in the title bar) of Infowin
515  */
516 static errr Infowin_set_name(concptr name)
517 {
518         Status st;
519         XTextProperty tp;
520         char buf[128];
521         char *bp = buf;
522         strcpy(buf, name);
523         st = XStringListToTextProperty(&bp, 1, &tp);
524         if (st) XSetWMName(Metadpy->dpy, Infowin->win, &tp);
525         return (0);
526 }
527
528 /*
529  * Prepare a new 'infowin'.
530  */
531 static errr Infowin_prepare(Window xid)
532 {
533         infowin *iwin = Infowin;
534         Window tmp_win;
535         XWindowAttributes xwa;
536         int x, y;
537         unsigned int w, h, b, d;
538         iwin->win = xid;
539         XGetGeometry(Metadpy->dpy, xid, &tmp_win, &x, &y, &w, &h, &b, &d);
540
541 #ifdef USE_XFT
542         Visual *vis = DefaultVisual(Metadpy->dpy, 0);
543         if (vis->class != TrueColor) {
544                 quit_fmt("Display does not support truecolor.\n");
545         }
546         iwin->draw = XftDrawCreate(Metadpy->dpy, iwin->win, vis, Metadpy->cmap);
547 #endif
548
549         iwin->x = x;
550         iwin->y = y;
551         iwin->w = w;
552         iwin->h = h;
553         iwin->b = b;
554
555         XGetWindowAttributes(Metadpy->dpy, xid, &xwa);
556         iwin->mask = xwa.your_event_mask;
557         iwin->mapped = ((xwa.map_state == IsUnmapped) ? 0 : 1);
558         iwin->redraw = 1;
559         return (0);
560 }
561
562 /*
563  * Init an infowin by giving some data.
564  *
565  * Inputs:
566  *      dad: The Window that should own this Window (if any)
567  *      x,y: The position of this Window
568  *      w,h: The size of this Window
569  *      b,d: The border width and pixel depth
570  *
571  * Notes:
572  *      If 'dad == None' assume 'dad == root'
573  */
574 static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
575                               int b, Pixell fg, Pixell bg)
576 {
577         Window xid;
578         (void)WIPE(Infowin, infowin);
579         if (dad == None) dad = Metadpy->root;
580
581 #ifdef USE_XFT
582         xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg.pixel, bg.pixel);
583 #else
584         xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg, bg);
585 #endif
586
587         XSelectInput(Metadpy->dpy, xid, 0L);
588         Infowin->nuke = 1;
589         return (Infowin_prepare(xid));
590 }
591
592 /*
593  * Modify the event mask of an Infowin
594  */
595 static errr Infowin_set_mask(long mask)
596 {
597         Infowin->mask = mask;
598         XSelectInput(Metadpy->dpy, Infowin->win, Infowin->mask);
599         return (0);
600 }
601
602 /*
603  * Request that Infowin be mapped
604  */
605 static errr Infowin_map(void)
606 {
607         XMapWindow(Metadpy->dpy, Infowin->win);
608         return (0);
609 }
610
611 /*
612  * Request that Infowin be raised
613  */
614 static errr Infowin_raise(void)
615 {
616         XRaiseWindow(Metadpy->dpy, Infowin->win);
617         return (0);
618 }
619
620 /*
621  * Request that Infowin be moved to a new location
622  */
623 static errr Infowin_impell(int x, int y)
624 {
625         XMoveWindow(Metadpy->dpy, Infowin->win, x, y);
626         return (0);
627 }
628
629 /*
630  * Resize an infowin
631  */
632 static errr Infowin_resize(int w, int h)
633 {
634         XResizeWindow(Metadpy->dpy, Infowin->win, w, h);
635         return (0);
636 }
637
638 /*
639  * Visually clear Infowin
640  */
641 static errr Infowin_wipe(void)
642 {
643         XClearWindow(Metadpy->dpy, Infowin->win);
644         return (0);
645 }
646
647 /*
648  * A NULL terminated pair list of legal "operation names"
649  *
650  * Pairs of values, first is texttual name, second is the string
651  * holding the decimal value that the operation corresponds to.
652  */
653 static concptr opcode_pairs[] =
654 {
655         "cpy", "3",
656         "xor", "6",
657         "and", "1",
658         "ior", "7",
659         "nor", "8",
660         "inv", "10",
661         "clr", "0",
662         "set", "15",
663
664         "src", "3",
665         "dst", "5",
666
667         "+andReverse", "2",
668         "+andInverted", "4",
669         "+noop", "5",
670         "+equiv", "9",
671         "+orReverse", "11",
672         "+copyInverted", "12",
673         "+orInverted", "13",
674         "+nand", "14",
675         NULL
676 };
677
678 /*
679  * Parse a word into an operation "code"
680  *
681  * Inputs:
682  *      str: A string, hopefully representing an Operation
683  *
684  * Output:
685  *      0-15: if 'str' is a valid Operation
686  *      -1:   if 'str' could not be parsed
687  */
688 static int Infoclr_Opcode(concptr str)
689 {
690         register int i;
691         for (i = 0; opcode_pairs[i*2]; ++i)
692         {
693                 if (streq(opcode_pairs[i*2], str))
694                 {
695                         return (atoi(opcode_pairs[i*2+1]));
696                 }
697         }
698
699         return (-1);
700 }
701
702 /*
703  * Initialize an infoclr with some data
704  *
705  * Inputs:
706  *      fg:   The Pixell for the requested Foreground (see above)
707  *      bg:   The Pixell for the requested Background (see above)
708  *      op:   The Opcode for the requested Operation (see above)
709  *      stip: The stipple mode
710  */
711 static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
712 {
713         infoclr *iclr = Infoclr;
714
715 #ifndef USE_XFT
716         GC gc;
717         XGCValues gcv;
718         unsigned long gc_mask;
719 #endif
720
721 #ifndef USE_XFT
722         if (bg > Metadpy->zg) return (-1);
723         if (fg > Metadpy->zg) return (-1);
724         if ((op < 0) || (op > 15)) return (-1);
725
726         gcv.function = op;
727         gcv.background = bg;
728         gcv.foreground = fg;
729         if (op == 6) gcv.background = 0;
730         if (op == 6) gcv.foreground = (bg ^ fg);
731
732         gcv.fill_style = (stip ? FillStippled : FillSolid);
733         gcv.graphics_exposures = False;
734         gc_mask = (GCFunction | GCBackground | GCForeground | GCFillStyle | GCGraphicsExposures);
735         gc = XCreateGC(Metadpy->dpy, Metadpy->root, gc_mask, &gcv);
736 #endif
737
738         (void)WIPE(iclr, infoclr);
739
740 #ifndef USE_XFT
741         iclr->gc = gc;
742 #endif
743
744         iclr->nuke = 1;
745         iclr->fg = fg;
746         iclr->bg = bg;
747         iclr->code = op;
748         iclr->stip = stip ? 1 : 0;
749         return (0);
750 }
751
752 /*
753  * Change the 'fg' for an infoclr
754  *
755  * Inputs:
756  *      fg:   The Pixell for the requested Foreground (see above)
757  */
758 static errr Infoclr_change_fg(Pixell fg)
759 {
760         infoclr *iclr = Infoclr;
761
762 #ifdef USE_XFT
763         iclr->fg = fg;
764 #else
765         if (fg > Metadpy->zg) return (-1);
766
767         XSetForeground(Metadpy->dpy, iclr->gc, fg);
768 #endif
769
770         return (0);
771 }
772
773 /*
774  * Prepare a new 'infofnt'
775  */
776 #ifdef USE_XFT
777 static errr Infofnt_prepare(XftFont *info)
778 #else
779 static errr Infofnt_prepare(XFontSet info)
780 #endif
781 {
782         infofnt *ifnt = Infofnt;
783
784 #ifndef USE_XFT
785         XCharStruct *cs;
786         XFontStruct **fontinfo;
787         char **fontname;
788         int n_fonts;
789         int ascent, descent, width;
790 #endif
791
792         ifnt->info = info;
793
794
795 #ifdef USE_XFT
796         ifnt->asc = info->ascent;
797         ifnt->hgt = info->ascent + info->descent;
798         const char *text = "A";
799         XGlyphInfo extent;
800         XftTextExtentsUtf8(Metadpy->dpy, info, (FcChar8*)text, strlen(text), &extent);
801         ifnt->wid = extent.xOff;
802 #else
803         n_fonts = XFontsOfFontSet(info, &fontinfo, &fontname);
804
805         ascent = descent = width = 0;
806         while(n_fonts-- > 0){
807                 cs = &((*fontinfo)->max_bounds);
808                 if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
809                 if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
810                 if(((*fontinfo)->max_byte1) > 0){
811                         /* 多バイト文字の場合は幅半分(端数切り上げ)で評価する */
812                         if(width < (cs->width+1)/2) width = (cs->width+1)/2;
813                 }else{
814                         if(width < cs->width) width = cs->width;
815                 }
816                 fontinfo++;
817                 fontname++;
818         }
819         ifnt->asc = ascent;
820         ifnt->hgt = ascent + descent;
821         ifnt->wid = width;
822 #endif
823
824         if (use_bigtile)
825                 ifnt->twid = 2 * ifnt->wid;
826         else
827                 ifnt->twid = ifnt->wid;
828
829         return (0);
830 }
831
832 /*
833  * Init an infofnt by its Name
834  *
835  * Inputs:
836  *      name: The name of the requested Font
837  */
838 static void Infofnt_init_data(concptr name)
839
840 {
841 #ifdef USE_XFT
842         XftFont *info;
843 #else
844         XFontSet info;
845         char **missing_list;
846         int missing_count;
847         char *default_font;
848 #endif
849
850         if (!name || !*name) quit("Missing font!");
851
852 #ifdef USE_XFT
853         info = XftFontOpenName(Metadpy->dpy, 0, name);
854         /* TODO: error handling */
855 #else
856         info = XCreateFontSet(Metadpy->dpy, name, &missing_list, &missing_count, &default_font);
857         if(missing_count > 0){
858                 printf("missing font(s): \n");
859                 while(missing_count-- > 0){
860                         printf("\t%s\n", missing_list[missing_count]);
861                 }
862                 XFreeStringList(missing_list);
863         }
864 #endif
865
866         if (!info) quit_fmt("Failed to find font:\"%s\"", name);
867
868         (void)WIPE(Infofnt, infofnt);
869         if (Infofnt_prepare(info))
870         {
871 #ifdef USE_XFT
872                 XftFontClose(Metadpy->dpy, info);
873 #else
874                 XFreeFontSet(Metadpy->dpy, info);
875 #endif
876                 quit_fmt("Failed to prepare font:\"%s\"", name);
877         }
878
879         Infofnt->name = string_make(name);
880         Infofnt->nuke = 1;
881 }
882
883 /*
884  * Standard Text
885  */
886 static errr Infofnt_text_std(int x, int y, concptr str, int len)
887 {
888         if (!str || !*str) return (-1);
889
890         if (len < 0) len = strlen(str);
891
892         y = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
893         x = (x * Infofnt->wid) + Infowin->ox;
894         if (Infofnt->mono)
895         {
896 #ifndef USE_XFT
897                 int i;
898                 for (i = 0; i < len; ++i)
899                 {
900                         XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc, x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
901                 }
902 #endif
903         }
904         else
905         {
906                 iconv_t cd = iconv_open("UTF-8", "EUC-JP");
907                 size_t inlen = len;
908                 size_t outlen = len * 2;
909                 char *kanji = malloc(outlen);
910                 char *sp; char *kp = kanji;
911                 char sbuf[1024];
912                 angband_strcpy(sbuf, str, sizeof(sbuf));
913                 sp = sbuf;
914                 iconv(cd, &sp, &inlen, &kp, &outlen);
915                 iconv_close(cd);
916
917 #ifdef USE_XFT
918                 XftDraw* draw = Infowin->draw;
919
920                 XRectangle r;
921                 r.x = 0;
922                 r.y = 0;
923                 r.width = Infofnt->wid*len;
924                 r.height = Infofnt->hgt;
925                 XftDrawSetClipRectangles(draw, x, y-Infofnt->asc, &r, 1);
926                 XftDrawRect(draw, &Infoclr->bg, x, y-Infofnt->asc, Infofnt->wid*len, Infofnt->hgt);
927                 XftDrawStringUtf8(draw, &Infoclr->fg, Infofnt->info, x, y,
928                          (FcChar8*)kanji, kp - kanji);
929                 XftDrawSetClip(draw, 0);
930 #else
931                 XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info,
932                                 Infoclr->gc, x, y, kanji, kp-kanji);
933 #endif
934                 free(kanji);
935         }
936
937         return (0);
938 }
939
940 /*
941  * Painting where text would be
942  */
943 static errr Infofnt_text_non(int x, int y, concptr str, int len)
944 {
945         int w, h;
946         if (len < 0) len = strlen(str);
947
948         w = len * Infofnt->wid;
949         x = x * Infofnt->wid + Infowin->ox;
950         h = Infofnt->hgt;
951         y = y * h + Infowin->oy;
952
953 #ifdef USE_XFT
954         XftDrawRect(Infowin->draw, &Infoclr->fg, x, y, w, h);
955 #else
956         XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, x, y, w, h);
957 #endif
958
959         return (0);
960 }
961
962 /*
963  * Angband specific code follows... (ANGBAND)
964  */
965
966 /*
967  * Hack -- cursor color
968  */
969 static infoclr *xor;
970
971 /*
972  * Actual color table
973  */
974 static infoclr *clr[256];
975
976 /*
977  * Color info (unused, red, green, blue).
978  */
979 static byte color_table[256][4];
980
981 /*
982  * Forward declare
983  */
984 typedef struct term_data term_data;
985
986 /*
987  * A structure for each "term"
988  */
989 struct term_data
990 {
991         term t;
992         infofnt *fnt;
993         infowin *win;
994 #ifndef USE_XFT
995         XImage *tiles;
996         XImage *TmpImage;
997 #endif
998 };
999
1000 /*
1001  * The number of term data structures
1002  */
1003 #define MAX_TERM_DATA 8
1004
1005 /*
1006  * The array of term data structures
1007  */
1008 static term_data data[MAX_TERM_DATA];
1009
1010
1011 /* Use short names for the most commonly used elements of various structures. */
1012 #define DPY (Metadpy->dpy)
1013 #define WIN (Infowin->win)
1014
1015 /* Describe a set of co-ordinates. */
1016 typedef struct co_ord co_ord;
1017 struct co_ord
1018 {
1019         int x;
1020         int y;
1021 };
1022
1023 /*
1024  * A special structure to store information about the text currently
1025  * selected.
1026  */
1027 typedef struct x11_selection_type x11_selection_type;
1028 struct x11_selection_type
1029 {
1030         bool select; /* The selection is currently in use. */
1031         bool drawn; /* The selection is currently displayed. */
1032         term *t; /* The window where the selection is found. */
1033         co_ord init; /* The starting co-ordinates. */
1034         co_ord cur; /* The end co-ordinates (the current ones if still copying). */
1035         co_ord old; /* The previous end co-ordinates. */
1036         Time time; /* The time at which the selection was finalised. */
1037 };
1038
1039 static x11_selection_type s_ptr[1];
1040
1041 /*
1042  * Process a keypress event
1043  *
1044  * Also appears in "main-xaw.c".
1045  */
1046 static void react_keypress(XKeyEvent *xev)
1047 {
1048         int i, n, mc, ms, mo, mx;
1049         uint ks1;
1050         XKeyEvent *ev = (XKeyEvent*)(xev);
1051         KeySym ks;
1052         char buf[128];
1053         char msg[128];
1054
1055 #ifdef USE_XIM
1056         int valid_keysym = TRUE;
1057 #endif
1058
1059 #ifdef USE_XIM
1060         if(Focuswin && Focuswin->xic){
1061                 Status status;
1062                 n = XmbLookupString(Focuswin->xic, ev, buf, 125, &ks, &status);
1063                 if(status == XBufferOverflow){
1064                         printf("Input is too long, and dropped\n");
1065                         return;
1066                 }
1067                 if(status != XLookupKeySym && status != XLookupBoth){
1068                         valid_keysym = FALSE;
1069                 }
1070         }else{
1071                 n = XLookupString(ev, buf, 125, &ks, NULL);
1072         }
1073 #else
1074         n = XLookupString(ev, buf, 125, &ks, NULL);
1075 #endif
1076
1077         buf[n] = '\0';
1078
1079 #ifdef USE_XIM
1080         if(!valid_keysym){
1081                 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1082
1083                 return;
1084         }
1085 #endif
1086
1087         if (IsModifierKey(ks)) return;
1088
1089         ks1 = (uint)(ks);
1090         mc = (ev->state & ControlMask) ? TRUE : FALSE;
1091         ms = (ev->state & ShiftMask) ? TRUE : FALSE;
1092         mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
1093         mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
1094         if (n && !mo && !mx && !IsSpecialKey(ks))
1095         {
1096                 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1097
1098                 return;
1099         }
1100
1101         switch (ks1)
1102         {
1103                 case XK_Escape:
1104                 {
1105                         Term_keypress(ESCAPE);
1106                         return;
1107                 }
1108
1109                 case XK_Return:
1110                 {
1111                         Term_keypress('\r');
1112                         return;
1113                 }
1114
1115                 case XK_Tab:
1116                 {
1117                         Term_keypress('\t');
1118                         return;
1119                 }
1120
1121                 case XK_Delete:
1122                 {
1123                         Term_keypress(0x7f);
1124                         return;
1125                 }
1126                 case XK_BackSpace:
1127                 {
1128                         Term_keypress('\010');
1129                         return;
1130                 }
1131         }
1132
1133         if (ks)
1134         {
1135                 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
1136                         mc ? "N" : "", ms ? "S" : "",
1137                         mo ? "O" : "", mx ? "M" : "",
1138                         (unsigned long)(ks), 13);
1139         }
1140         else
1141         {
1142                 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
1143                         mc ? "N" : "", ms ? "S" : "",
1144                         mo ? "O" : "", mx ? "M" : "",
1145                         ev->keycode, 13);
1146         }
1147
1148         for (i = 0; msg[i]; i++) Term_keypress(msg[i]);
1149
1150         if (n && (macro_find_exact(msg) < 0))
1151         {
1152                 macro_add(msg, buf);
1153         }
1154 }
1155
1156 /*
1157  * Find the square a particular pixel is part of.
1158  */
1159 static void pixel_to_square(int * const x, int * const y,
1160         const int ox, const int oy)
1161 {
1162         (*x) = (ox - Infowin->ox) / Infofnt->wid;
1163         (*y) = (oy - Infowin->oy) / Infofnt->hgt;
1164 }
1165
1166 /*
1167  * Find the pixel at the top-left corner of a square.
1168  */
1169 static void square_to_pixel(int * const x, int * const y,
1170         const int ox, const int oy)
1171 {
1172         (*x) = ox * Infofnt->wid + Infowin->ox;
1173         (*y) = oy * Infofnt->hgt + Infowin->oy;
1174 }
1175
1176 /*
1177  * Convert co-ordinates from starting corner/opposite corner to minimum/maximum.
1178  */
1179 static void sort_co_ord(co_ord *min, co_ord *max,
1180         const co_ord *b, const co_ord *a)
1181 {
1182         min->x = MIN(a->x, b->x);
1183         min->y = MIN(a->y, b->y);
1184         max->x = MAX(a->x, b->x);
1185         max->y = MAX(a->y, b->y);
1186 }
1187
1188 /*
1189  * Remove the selection by redrawing it.
1190  */
1191 static void mark_selection_clear(int x1, int y1, int x2, int y2)
1192 {
1193         Term_redraw_section(x1,y1,x2,y2);
1194 }
1195
1196 /*
1197  * Select an area by drawing a grey box around it.
1198  * NB. These two functions can cause flicker as the selection is modified,
1199  * as the game redraws the entire marked section.
1200  */
1201 static void mark_selection_mark(int x1, int y1, int x2, int y2)
1202 {
1203         square_to_pixel(&x1, &y1, x1, y1);
1204         square_to_pixel(&x2, &y2, x2, y2);
1205 #ifdef USE_XFT
1206         XftDrawRect(Infowin->draw, &clr[2]->fg, x1, y1, x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
1207 #else
1208         XDrawRectangle(Metadpy->dpy, Infowin->win, clr[2]->gc, x1, y1,
1209                 x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
1210 #endif
1211 }
1212
1213 /*
1214  * Mark a selection by drawing boxes around it (for now).
1215  */
1216 static void mark_selection(void)
1217 {
1218         co_ord min, max;
1219         term *old = Term;
1220         bool draw = s_ptr->select;
1221         bool clear = s_ptr->drawn;
1222         if (s_ptr->t != old) Term_activate(s_ptr->t);
1223
1224         if (clear)
1225         {
1226                 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->old);
1227                 mark_selection_clear(min.x, min.y, max.x, max.y);
1228         }
1229         if (draw)
1230         {
1231                 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
1232                 mark_selection_mark(min.x, min.y, max.x, max.y);
1233         }
1234
1235         if (s_ptr->t != old) Term_activate(old);
1236
1237         s_ptr->old.x = s_ptr->cur.x;
1238         s_ptr->old.y = s_ptr->cur.y;
1239         s_ptr->drawn = s_ptr->select;
1240 }
1241
1242 /*
1243  * Forget a selection for one reason or another.
1244  */
1245 static void copy_x11_release(void)
1246 {
1247         s_ptr->select = FALSE;
1248         mark_selection();
1249 }
1250
1251 /*
1252  * Start to select some text on the screen.
1253  */
1254 static void copy_x11_start(int x, int y)
1255 {
1256         if (s_ptr->select) copy_x11_release();
1257
1258         s_ptr->t = Term;
1259         s_ptr->init.x = s_ptr->cur.x = s_ptr->old.x = x;
1260         s_ptr->init.y = s_ptr->cur.y = s_ptr->old.y = y;
1261 }
1262
1263 /*
1264  * Respond to movement of the mouse when selecting text.
1265  */
1266 static void copy_x11_cont(int x, int y, unsigned int buttons)
1267 {
1268         x = MIN(MAX(x, 0), Term->wid-1);
1269         y = MIN(MAX(y, 0), Term->hgt-1);
1270         if (~buttons & Button1Mask) return;
1271         if (s_ptr->t != Term) return;
1272         if (x == s_ptr->old.x && y == s_ptr->old.y && s_ptr->select) return;
1273
1274         s_ptr->select = TRUE;
1275         s_ptr->cur.x = x;
1276         s_ptr->cur.y = y;
1277         mark_selection();
1278 }
1279
1280 /*
1281  * Respond to release of the left mouse button by putting the selected text in
1282  * the primary buffer.
1283  */
1284 static void copy_x11_end(const Time time)
1285 {
1286         if (!s_ptr->select) return;
1287         if (s_ptr->t != Term) return;
1288
1289         s_ptr->time = time;
1290         XSetSelectionOwner(Metadpy->dpy, XA_PRIMARY, Infowin->win, time);
1291         if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) != Infowin->win)
1292         {
1293                 s_ptr->select = FALSE;
1294                 mark_selection();
1295         }
1296 }
1297
1298 static Atom xa_targets, xa_timestamp, xa_text, xa_compound_text;
1299
1300 /*
1301  * Set the required variable atoms at start-up to avoid errors later.
1302  */
1303 static void set_atoms(void)
1304 {
1305         xa_targets = XInternAtom(DPY, "TARGETS", False);
1306         xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
1307         xa_text = XInternAtom(DPY, "TEXT", False);
1308         xa_compound_text = XInternAtom(DPY, "COMPOUND_TEXT", False);
1309 }
1310
1311 static Atom request_target = 0;
1312
1313 /*
1314  * Send a message to request that the PRIMARY buffer be sent here.
1315  */
1316 static void paste_x11_request(Atom target, const Time time)
1317 {
1318         Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1319         if (XGetSelectionOwner(DPY, XA_PRIMARY) == None)
1320         {
1321                 /* No selection. */
1322                 /* bell("No selection found."); */
1323                 return;
1324         }
1325
1326         request_target = target;
1327     XConvertSelection(DPY, XA_PRIMARY, target, property, WIN, time);
1328 }
1329
1330 /*
1331  * Add the contents of the PRIMARY buffer to the input queue.
1332  *
1333  * Hack - This doesn't use the "time" of the event, and so accepts anything a
1334  * client tries to send it.
1335  */
1336 static void paste_x11_accept(const XSelectionEvent *ptr)
1337 {
1338         unsigned long left;
1339         const long offset = 0;
1340         const long length = 32000;
1341         XTextProperty xtextproperty;
1342         errr err = 0;
1343         Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1344         if (ptr->property == None)
1345         {
1346                 if (request_target == xa_compound_text)
1347                 {
1348                         paste_x11_request(XA_STRING, ptr->time);
1349                 }
1350                 else
1351                 {
1352                         request_target = 0;
1353                         plog("Paste failure (remote client could not send).");
1354                 }
1355
1356                 return;
1357         }
1358
1359         if (ptr->selection != XA_PRIMARY)
1360         {
1361                 plog("Paste failure (remote client did not send primary selection).");
1362                 return;
1363         }
1364
1365         if (ptr->target != request_target)
1366         {
1367                 plog("Paste failure (selection in unknown format).");
1368                 return;
1369         }
1370
1371         if (XGetWindowProperty(Metadpy->dpy, Infowin->win, property, offset,
1372                                length, TRUE, request_target,
1373                                &xtextproperty.encoding,
1374                                &xtextproperty.format,
1375                                &xtextproperty.nitems,
1376                                &left,
1377                                &xtextproperty.value)
1378             != Success)
1379         {
1380                 return;
1381         }
1382
1383         if (request_target == xa_compound_text)
1384         {
1385                 char **list;
1386                 int count;
1387                 
1388                 XmbTextPropertyToTextList(DPY, &xtextproperty, &list, &count);
1389
1390                 if (list)
1391                 {
1392                         int i;
1393
1394                         for (i = 0; i < count; i++)
1395                         {
1396                                 err = type_string(list[i], 0);
1397                                 if (err) break;
1398                         }
1399
1400                         XFreeStringList(list);
1401                 }
1402         }
1403         else
1404         {
1405                 err = type_string((char *)xtextproperty.value, xtextproperty.nitems);
1406         }
1407
1408         XFree(xtextproperty.value); 
1409         if (err)
1410         {
1411                 plog("Paste failure (too much text selected).");
1412         }
1413 }
1414
1415 /*
1416  * Add a character to a string in preparation for sending it to another
1417  * client as a STRING.
1418  * This doesn't change anything, as clients tend not to have difficulty in
1419  * receiving this format (although the standard specifies a restricted set).
1420  * Strings do not have a colour.
1421  */
1422 static bool paste_x11_send_text(XSelectionRequestEvent *rq)
1423 {
1424         char buf[1024];
1425         char *list[1000];
1426         co_ord max, min;
1427         TERM_LEN x,y;
1428         int l,n;
1429         TERM_COLOR a;
1430         char c;
1431
1432         if (rq->time < s_ptr->time) return FALSE;
1433
1434         sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
1435         if (XGetSelectionOwner(DPY, XA_PRIMARY) != WIN)
1436         {
1437                 return FALSE;
1438         }
1439
1440         XDeleteProperty(DPY, rq->requestor, rq->property);
1441
1442         for (n = 0, y = 0; y < Term->hgt; y++)
1443         {
1444 #ifdef JP
1445                 int kanji = 0;
1446 #endif
1447                 if (y < min.y) continue;
1448                 if (y > max.y) break;
1449
1450                 for (l = 0, x = 0; x < Term->wid; x++)
1451                 {
1452 #ifdef JP
1453                         if (x > max.x) break;
1454
1455                         Term_what(x, y, &a, &c);
1456                         if (1 == kanji) kanji = 2;
1457                         else if (iskanji(c)) kanji = 1;
1458                         else kanji = 0;
1459
1460                         if (x < min.x) continue;
1461
1462                         /*
1463                          * A single kanji character was divided in two...
1464                          * Delete the garbage.
1465                          */
1466                         if ((2 == kanji && x == min.x) ||
1467                             (1 == kanji && x == max.x))
1468                                 c = ' ';
1469 #else
1470                         if (x > max.x) break;
1471                         if (x < min.x) continue;
1472
1473                         Term_what(x, y, &a, &c);
1474 #endif
1475
1476                         buf[l] = c;
1477                         l++;
1478                 }
1479
1480                 while (buf[l-1] == ' ') l--;
1481
1482                 if (min.y != max.y)
1483                 {
1484                         buf[l] = '\n';
1485                         l++;
1486                 }
1487
1488                 buf[l] = '\0';
1489                 list[n++] = (char *)string_make(buf);
1490         }
1491
1492         list[n] = NULL;
1493         if (rq->target == XA_STRING)
1494         {
1495                 for (n = 0; list[n]; n++)
1496                 {
1497                         XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
1498                                         PropModeAppend, (unsigned char *)list[n], strlen(list[n]));
1499                 }
1500         }
1501         else if (rq->target == xa_text || 
1502                  rq->target == xa_compound_text)
1503         {
1504                 XTextProperty text_prop;
1505                 XICCEncodingStyle style;
1506
1507                 if (rq->target == xa_text)
1508                         style = XStdICCTextStyle;
1509                 else
1510                         style = XCompoundTextStyle;
1511
1512                 if (Success ==
1513                     XmbTextListToTextProperty(DPY, list, n, style, &text_prop))
1514                 {
1515                         XChangeProperty(DPY,
1516                                         rq->requestor,
1517                                         rq->property,
1518                                         text_prop.encoding,
1519                                         text_prop.format,
1520                                         PropModeAppend,
1521                                         text_prop.value,
1522                                         text_prop.nitems);
1523                         XFree(text_prop.value);
1524                 }
1525         }
1526
1527         for (n = 0; list[n]; n++)
1528         {
1529                 string_free(list[n]);
1530         }
1531
1532         return TRUE;
1533 }
1534
1535 /*
1536  * Send some text requested by another X client.
1537  */
1538 static void paste_x11_send(XSelectionRequestEvent *rq)
1539 {
1540         XEvent event;
1541         XSelectionEvent *ptr = &(event.xselection);
1542
1543         ptr->type = SelectionNotify;
1544         ptr->property = rq->property;
1545         ptr->display = rq->display;
1546         ptr->requestor = rq->requestor;
1547         ptr->selection = rq->selection;
1548         ptr->target = rq->target;
1549         ptr->time = rq->time;
1550
1551         /*
1552          * Paste the appropriate information for each target type.
1553          * Note that this currently rejects MULTIPLE targets.
1554          */
1555
1556         if (rq->target == XA_STRING ||
1557             rq->target == xa_text ||
1558             rq->target == xa_compound_text)
1559         {
1560                 if (!paste_x11_send_text(rq))
1561                         ptr->property = None;
1562         }
1563         else if (rq->target == xa_targets)
1564         {
1565                 Atom target_list[4];
1566                 target_list[0] = XA_STRING;
1567                 target_list[1] = xa_text;
1568                 target_list[2] = xa_compound_text;
1569                 target_list[3] = xa_targets;
1570                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
1571                         (8 * sizeof(target_list[0])), PropModeReplace,
1572                         (unsigned char *)target_list,
1573                         (sizeof(target_list) / sizeof(target_list[0])));
1574         }
1575         else if (rq->target == xa_timestamp)
1576         {
1577                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
1578                         (8 * sizeof(Time)), PropModeReplace,
1579                         (unsigned char *)s_ptr->time, 1);
1580         }
1581         else
1582         {
1583                 ptr->property = None;
1584         }
1585
1586         XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
1587 }
1588
1589 /*
1590  * Handle various events conditional on presses of a mouse button.
1591  */
1592 static void handle_button(Time time, int x, int y, int button, bool press)
1593 {
1594         pixel_to_square(&x, &y, x, y);
1595
1596         if (press && button == 1) copy_x11_start(x, y);
1597         if (!press && button == 1) copy_x11_end(time);
1598         if (!press && button == 2) paste_x11_request(xa_compound_text, time);
1599 }
1600
1601 /*
1602  * Process events
1603  */
1604 static errr CheckEvent(bool wait)
1605 {
1606         term_data *old_td = (term_data*)(Term->data);
1607
1608         XEvent xev_body, *xev = &xev_body;
1609
1610         term_data *td = NULL;
1611         infowin *iwin = NULL;
1612
1613         int i;
1614
1615 #ifdef USE_XIM
1616         do
1617         {
1618 #endif
1619
1620                 if (!wait && !XPending(Metadpy->dpy)) return (1);
1621
1622                 if (s_ptr->select && !s_ptr->drawn) mark_selection();
1623
1624                 XNextEvent(Metadpy->dpy, xev);
1625
1626 #ifdef USE_XIM
1627         } while (XFilterEvent(xev, xev->xany.window));
1628 #endif
1629
1630         if (xev->type == MappingNotify)
1631         {
1632                 XRefreshKeyboardMapping(&xev->xmapping);
1633                 return 0;
1634         }
1635
1636         for (i = 0; i < MAX_TERM_DATA; i++)
1637         {
1638                 if (!data[i].win) continue;
1639                 if (xev->xany.window == data[i].win->win)
1640                 {
1641                         td = &data[i];
1642                         iwin = td->win;
1643                         break;
1644                 }
1645         }
1646
1647         if (!td || !iwin) return (0);
1648
1649         Term_activate(&td->t);
1650         Infowin_set(iwin);
1651         switch (xev->type)
1652         {
1653                 case ButtonPress:
1654                 case ButtonRelease:
1655                 {
1656                         bool press = (xev->type == ButtonPress);
1657                         int x = xev->xbutton.x;
1658                         int y = xev->xbutton.y;
1659                         int z;
1660                         if (xev->xbutton.button == Button1) z = 1;
1661                         else if (xev->xbutton.button == Button2) z = 2;
1662                         else if (xev->xbutton.button == Button3) z = 3;
1663                         else if (xev->xbutton.button == Button4) z = 4;
1664                         else if (xev->xbutton.button == Button5) z = 5;
1665                         else z = 0;
1666
1667                         handle_button(xev->xbutton.time, x, y, z, press);
1668                         break;
1669                 }
1670                 case EnterNotify:
1671                 case LeaveNotify:
1672                 {
1673                         break;
1674                 }
1675                 case MotionNotify:
1676                 {
1677                         int x = xev->xmotion.x;
1678                         int y = xev->xmotion.y;
1679                         unsigned int z = xev->xmotion.state;
1680                         pixel_to_square(&x, &y, x, y);
1681                         copy_x11_cont(x, y, z);
1682                         break;
1683                 }
1684                 case SelectionNotify:
1685                 {
1686                         paste_x11_accept(&(xev->xselection));
1687                         break;
1688                 }
1689                 case SelectionRequest:
1690                 {
1691                         paste_x11_send(&(xev->xselectionrequest));
1692                         break;
1693                 }
1694                 case SelectionClear:
1695                 {
1696                         s_ptr->select = FALSE;
1697                         mark_selection();
1698                         break;
1699                 }
1700                 case KeyRelease:
1701                 {
1702                         break;
1703                 }
1704                 case KeyPress:
1705                 {
1706                         Term_activate(&old_td->t);
1707                         react_keypress(&(xev->xkey));
1708                         break;
1709                 }
1710                 case Expose:
1711                 {
1712                         int x1, x2, y1, y2;
1713                         x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
1714                         x2 = (xev->xexpose.x + xev->xexpose.width -
1715                                  Infowin->ox)/Infofnt->wid;
1716                         
1717                         y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
1718                         y2 = (xev->xexpose.y + xev->xexpose.height -
1719                                  Infowin->oy)/Infofnt->hgt;
1720                         
1721                         Term_redraw_section(x1, y1, x2, y2);
1722                         break;
1723                 }
1724                 case MapNotify:
1725                 {
1726                         Infowin->mapped = 1;
1727                         Term->mapped_flag = TRUE;
1728                         break;
1729                 }
1730                 case UnmapNotify:
1731                 {
1732                         Infowin->mapped = 0;
1733                         Term->mapped_flag = FALSE;
1734                         break;
1735                 }
1736                 case ConfigureNotify:
1737                 {
1738                         int cols, rows, wid, hgt;
1739                         int ox = Infowin->ox;
1740                         int oy = Infowin->oy;
1741                         Infowin->x = xev->xconfigure.x;
1742                         Infowin->y = xev->xconfigure.y;
1743                         Infowin->w = xev->xconfigure.width;
1744                         Infowin->h = xev->xconfigure.height;
1745                         cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
1746                         rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
1747                         if (cols < 1) cols = 1;
1748                         if (rows < 1) rows = 1;
1749
1750                         if (td == &data[0])
1751                         {
1752                                 if (cols < 80) cols = 80;
1753                                 if (rows < 24) rows = 24;
1754                         }
1755
1756                         wid = cols * td->fnt->wid + (ox + ox);
1757                         hgt = rows * td->fnt->hgt + (oy + oy);
1758                         Term_resize(cols, rows);
1759                         if ((Infowin->w != wid) || (Infowin->h != hgt))
1760                         {
1761                                 Infowin_set(td->win);
1762                                 Infowin_resize(wid, hgt);
1763                         }
1764
1765                         break;
1766                 }
1767 #ifdef USE_XIM
1768                 case FocusIn:
1769                 {
1770                         if(iwin->xic){
1771                                 XSetICFocus(iwin->xic);
1772                         }
1773                         Focuswin = iwin;
1774                         break;
1775                 }
1776                 case FocusOut:
1777                 {
1778                         if(iwin->xic)
1779                         {
1780                                 XUnsetICFocus(iwin->xic);
1781                         }
1782
1783                         break;
1784                 }
1785 #endif
1786         }
1787
1788         Term_activate(&old_td->t);
1789         Infowin_set(old_td->win);
1790         return (0);
1791 }
1792
1793 /*
1794  * An array of sound file names
1795  */
1796 static concptr sound_file[SOUND_MAX];
1797
1798 /*
1799  * Check for existance of a file
1800  */
1801 static bool check_file(concptr s)
1802 {
1803         FILE *fff;
1804
1805         fff = fopen(s, "r");
1806         if (!fff) return (FALSE);
1807         
1808         fclose(fff);
1809         return (TRUE);
1810 }
1811
1812 /*
1813  * Initialize sound
1814  */
1815 static void init_sound(void)
1816 {
1817         int i;
1818         char wav[128];
1819         char buf[1024];
1820         char dir_xtra_sound[1024];
1821         path_build(dir_xtra_sound, sizeof(dir_xtra_sound), ANGBAND_DIR_XTRA, "sound");
1822         for (i = 1; i < SOUND_MAX; i++)
1823         {
1824                 sprintf(wav, "%s.wav", angband_sound_name[i]);
1825                 path_build(buf, sizeof(buf), dir_xtra_sound, wav);
1826                 if (check_file(buf)) sound_file[i] = string_make(buf);
1827         }
1828
1829         use_sound = TRUE;
1830         return;
1831 }
1832
1833 /*
1834  * Hack -- make a sound
1835  */
1836 static errr Term_xtra_x11_sound(int v)
1837 {
1838         char buf[1024];
1839         if (!use_sound) return (1);
1840         if ((v < 0) || (v >= SOUND_MAX)) return (1);
1841         if (!sound_file[v]) return (1);
1842         
1843         sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
1844         return (system(buf) < 0);
1845         
1846 }
1847
1848 /*
1849  * Handle "activation" of a term
1850  */
1851 static errr Term_xtra_x11_level(int v)
1852 {
1853         term_data *td = (term_data*)(Term->data);
1854         if (v)
1855         {
1856                 Infowin_set(td->win);
1857                 Infofnt_set(td->fnt);
1858         }
1859
1860         return (0);
1861 }
1862
1863 /*
1864  * React to changes
1865  */
1866 static errr Term_xtra_x11_react(void)
1867 {
1868         int i;
1869         
1870         if (Metadpy->color)
1871         {
1872                 for (i = 0; i < 256; i++)
1873                 {
1874                         if ((color_table[i][0] != angband_color_table[i][0]) ||
1875                             (color_table[i][1] != angband_color_table[i][1]) ||
1876                             (color_table[i][2] != angband_color_table[i][2]) ||
1877                             (color_table[i][3] != angband_color_table[i][3]))
1878                         {
1879                                 Pixell pixel;
1880                                 color_table[i][0] = angband_color_table[i][0];
1881                                 color_table[i][1] = angband_color_table[i][1];
1882                                 color_table[i][2] = angband_color_table[i][2];
1883                                 color_table[i][3] = angband_color_table[i][3];
1884                                 pixel = create_pixel(Metadpy->dpy,
1885                                                      color_table[i][1],
1886                                                      color_table[i][2],
1887                                                      color_table[i][3]);
1888                                 Infoclr_set(clr[i]);
1889                                 Infoclr_change_fg(pixel);
1890                         }
1891                 }
1892         }
1893
1894         return (0);
1895 }
1896
1897 /*
1898  * Handle a "special request"
1899  */
1900 static errr Term_xtra_x11(int n, int v)
1901 {
1902         switch (n)
1903         {
1904                 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
1905                 case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
1906 #ifdef USE_XFT
1907                 case TERM_XTRA_FRESH: Metadpy_update(1, 1, 0); return (0);
1908 #else
1909                 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
1910 #endif
1911                 case TERM_XTRA_BORED: return (CheckEvent(0));
1912                 case TERM_XTRA_EVENT: return (CheckEvent(v));
1913                 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
1914                 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
1915                 case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
1916                 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
1917                 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
1918         }
1919
1920         return (1);
1921 }
1922
1923 /*
1924  * Draw the cursor as an inverted rectangle.
1925  *
1926  * Consider a rectangular outline like "main-mac.c".  XXX XXX
1927  */
1928 static errr Term_curs_x11(int x, int y)
1929 {
1930         if (use_graphics)
1931         {
1932 #ifdef USE_XFT
1933                 XftDrawRect(Infowin->draw, &xor->fg,
1934                             x * Infofnt->wid + Infowin->ox,
1935                             y * Infofnt->hgt + Infowin->oy,
1936                             Infofnt->wid - 1, Infofnt->hgt - 1);
1937                 XftDrawRect(Infowin->draw, &xor->fg,
1938                             x * Infofnt->wid + Infowin->ox + 1,
1939                             y * Infofnt->hgt + Infowin->oy + 1,
1940                             Infofnt->wid - 3, Infofnt->hgt - 3);
1941 #else
1942                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
1943                                x * Infofnt->wid + Infowin->ox,
1944                                y * Infofnt->hgt + Infowin->oy,
1945                                Infofnt->wid - 1, Infofnt->hgt - 1);
1946                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
1947                                x * Infofnt->wid + Infowin->ox + 1,
1948                                y * Infofnt->hgt + Infowin->oy + 1,
1949                                Infofnt->wid - 3, Infofnt->hgt - 3);
1950 #endif
1951         }
1952         else
1953         {
1954                 Infoclr_set(xor);
1955                 Infofnt_text_non(x, y, " ", 1);
1956         }
1957
1958         return (0);
1959 }
1960
1961
1962 /*
1963  * Draw the double width cursor
1964  */
1965 static errr Term_bigcurs_x11(int x, int y)
1966 {
1967         if (use_graphics)
1968         {
1969 #ifdef USE_XFT
1970                 XftDrawRect(Infowin->draw, &xor->fg,
1971                             x * Infofnt->wid + Infowin->ox,
1972                             y * Infofnt->hgt + Infowin->oy,
1973                             Infofnt->twid - 1, Infofnt->hgt - 1);
1974                 XftDrawRect(Infowin->draw, &xor->fg,
1975                             x * Infofnt->wid + Infowin->ox + 1,
1976                             y * Infofnt->hgt + Infowin->oy + 1,
1977                             Infofnt->twid - 3, Infofnt->hgt - 3);
1978 #else
1979                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
1980                                x * Infofnt->wid + Infowin->ox,
1981                                y * Infofnt->hgt + Infowin->oy,
1982                                Infofnt->twid - 1, Infofnt->hgt - 1);
1983                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
1984                                x * Infofnt->wid + Infowin->ox + 1,
1985                                y * Infofnt->hgt + Infowin->oy + 1,
1986                                Infofnt->twid - 3, Infofnt->hgt - 3);
1987 #endif
1988         }
1989         else
1990         {
1991                 Infoclr_set(xor);
1992                 Infofnt_text_non(x, y, "  ", 2);
1993         }
1994
1995         return (0);
1996 }
1997
1998 /*
1999  * Erase some characters.
2000  */
2001 static errr Term_wipe_x11(int x, int y, int n)
2002 {
2003         Infoclr_set(clr[TERM_DARK]);
2004         Infofnt_text_non(x, y, "", n);
2005         s_ptr->drawn = FALSE;
2006         return (0);
2007 }
2008
2009 /*
2010  * Draw some textual characters.
2011  */
2012 static errr Term_text_x11(TERM_LEN x, TERM_LEN y, int n, TERM_COLOR a, concptr s)
2013 {
2014         Infoclr_set(clr[a]);
2015         Infofnt_text_std(x, y, s, n);
2016         s_ptr->drawn = FALSE;
2017         return (0);
2018 }
2019
2020 #ifndef USE_XFT
2021 /*
2022  * Draw some graphical characters.
2023  */
2024 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)
2025 {
2026         int i, x1, y1;
2027
2028         TERM_COLOR a;
2029         char c;
2030
2031         TERM_COLOR ta;
2032         char tc;
2033
2034         int x2, y2;
2035         int k,l;
2036
2037         unsigned long pixel, blank;
2038
2039         term_data *td = (term_data*)(Term->data);
2040
2041         y *= Infofnt->hgt;
2042         x *= Infofnt->wid;
2043
2044         y += Infowin->oy;
2045         x += Infowin->ox;
2046         for (i = 0; i < n; ++i, x += td->fnt->wid)
2047         {
2048                 a = *ap++;
2049                 c = *cp++;
2050                 x1 = (c&0x7F) * td->fnt->twid;
2051                 y1 = (a&0x7F) * td->fnt->hgt;
2052                 if (td->tiles->width < x1 + td->fnt->wid ||
2053                     td->tiles->height < y1 + td->fnt->hgt)
2054                 {
2055                         XFillRectangle(Metadpy->dpy, td->win->win, clr[0]->gc, x, y,  td->fnt->twid, td->fnt->hgt);
2056                         continue;
2057                 }
2058
2059                 ta = *tap++;
2060                 tc = *tcp++;
2061
2062                 x2 = (tc&0x7F) * td->fnt->twid;
2063                 y2 = (ta&0x7F) * td->fnt->hgt;
2064                 
2065                 if (((x1 == x2) && (y1 == y2)) ||
2066                     !(((byte)ta & 0x80) && ((byte)tc & 0x80)) ||
2067                     td->tiles->width < x2 + td->fnt->wid ||
2068                     td->tiles->height < y2 + td->fnt->hgt)
2069                 {
2070                         XPutImage(Metadpy->dpy, td->win->win,
2071                                 clr[0]->gc,
2072                                 td->tiles,
2073                                 x1, y1,
2074                                 x, y,
2075                                 td->fnt->twid, td->fnt->hgt);   
2076                 }
2077                 else
2078                 {
2079                         blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
2080                         for (k = 0; k < td->fnt->twid; k++)
2081                         {
2082                                 for (l = 0; l < td->fnt->hgt; l++)
2083                                 {
2084                                         if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
2085                                         {
2086                                                 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
2087                                         }
2088                                         
2089                                         XPutPixel(td->TmpImage, k, l, pixel);
2090                                 }
2091                         }
2092
2093                         XPutImage(Metadpy->dpy, td->win->win,
2094                               clr[0]->gc,
2095                              td->TmpImage,
2096                              0, 0, x, y,
2097                              td->fnt->twid, td->fnt->hgt);
2098                 }
2099         }
2100
2101         s_ptr->drawn = FALSE;
2102         return (0);
2103 }
2104 #endif
2105
2106 #ifdef USE_XIM
2107 static void IMDestroyCallback(XIM, XPointer, XPointer);
2108
2109 static void
2110 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
2111 {
2112         XIM xim;
2113         XIMCallback ximcallback;
2114         XIMStyles *xim_styles = NULL;
2115         int i;
2116
2117         (void)unused1;
2118         (void)unused2;
2119
2120         xim = XOpenIM(display, NULL, NULL, NULL);
2121         if(!xim){
2122                 printf("can't open IM\n");
2123                 return;
2124         }
2125
2126         ximcallback.callback = IMDestroyCallback;
2127         ximcallback.client_data = NULL;
2128         XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
2129         XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
2130         for (i = 0; i < xim_styles->count_styles; i++){
2131                 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
2132         }
2133         if(i >= xim_styles->count_styles){
2134                 printf("Sorry, your IM does not support 'Root' preedit style...\n");
2135                 XCloseIM(xim);
2136                 return;
2137         }
2138         XFree(xim_styles);
2139
2140         Metadpy->xim = xim;
2141
2142         for (i = 0; i < MAX_TERM_DATA; i++)
2143         {
2144                 infowin *iwin = data[i].win;
2145                 if (!iwin) continue;
2146                 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
2147                 if(!iwin->xic)
2148                 {
2149                         printf("Can't create input context for Term%d\n", i);
2150                         continue;
2151                 }
2152
2153                 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL)
2154                 {
2155                         iwin->xic_mask = 0L;
2156                 }
2157
2158                 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
2159         }
2160
2161         return;
2162 }
2163
2164 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
2165 {
2166         int i;
2167         (void)xim;
2168         (void)client_data;
2169
2170         if (call_data == NULL){
2171                 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
2172         }
2173
2174         for(i = 0; i < MAX_TERM_DATA; i++)
2175         {
2176                 infowin *iwin = data[i].win;
2177                 if(!iwin) continue;
2178                 if(iwin->xic_mask){
2179                         XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
2180                         iwin->xic_mask = 0L;
2181                 }
2182                 iwin->xic = NULL;
2183         }
2184
2185         Metadpy->xim = NULL;
2186 }
2187 #endif
2188
2189 static char force_lower(char a)
2190 {
2191         return ((isupper((a))) ? tolower((a)) : (a))
2192 }
2193
2194 /*
2195  * Initialize a term_data
2196  */
2197 static errr term_data_init(term_data *td, int i)
2198 {
2199         term *t = &td->t;
2200
2201         concptr name = angband_term_name[i];
2202
2203         concptr font;
2204         int x = 0;
2205         int y = 0;
2206
2207         int cols = 80;
2208         int rows = 24;
2209
2210         int ox = 1;
2211         int oy = 1;
2212
2213         int wid, hgt, num;
2214
2215         char buf[80];
2216
2217         concptr str;
2218
2219         int val;
2220
2221         XClassHint *ch;
2222
2223         char res_name[20];
2224         char res_class[20];
2225
2226         XSizeHints *sh;
2227 #ifdef USE_XIM
2228         XWMHints *wh;
2229 #endif
2230
2231         sprintf(buf, "ANGBAND_X11_FONT_%d", i);
2232         font = getenv(buf);
2233         if (!font) font = getenv("ANGBAND_X11_FONT");
2234
2235         if (!font)
2236         {
2237                 switch (i)
2238                 {
2239                         case 0:
2240                         {
2241                                 font = DEFAULT_X11_FONT_0;
2242                         }
2243                         break;
2244                         case 1:
2245                         {
2246                                 font = DEFAULT_X11_FONT_1;
2247                         }
2248                         break;
2249                         case 2:
2250                         {
2251                                 font = DEFAULT_X11_FONT_2;
2252                         }
2253                         break;
2254                         case 3:
2255                         {
2256                                 font = DEFAULT_X11_FONT_3;
2257                         }
2258                         break;
2259                         case 4:
2260                         {
2261                                 font = DEFAULT_X11_FONT_4;
2262                         }
2263                         break;
2264                         case 5:
2265                         {
2266                                 font = DEFAULT_X11_FONT_5;
2267                         }
2268                         break;
2269                         case 6:
2270                         {
2271                                 font = DEFAULT_X11_FONT_6;
2272                         }
2273                         break;
2274                         case 7:
2275                         {
2276                                 font = DEFAULT_X11_FONT_7;
2277                         }
2278                         break;
2279                         default:
2280                         {
2281                                 font = DEFAULT_X11_FONT;
2282                         }
2283                 }
2284         }
2285
2286         sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
2287         str = getenv(buf);
2288         x = (str != NULL) ? atoi(str) : -1;
2289
2290         sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
2291         str = getenv(buf);
2292         y = (str != NULL) ? atoi(str) : -1;
2293
2294         sprintf(buf, "ANGBAND_X11_COLS_%d", i);
2295         str = getenv(buf);
2296         val = (str != NULL) ? atoi(str) : -1;
2297         if (val > 0) cols = val;
2298
2299         sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
2300         str = getenv(buf);
2301         val = (str != NULL) ? atoi(str) : -1;
2302         if (val > 0) rows = val;
2303
2304         if (!i)
2305         {
2306                 if (cols < 80) cols = 80;
2307                 if (rows < 24) rows = 24;
2308         }
2309
2310         sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
2311         str = getenv(buf);
2312         val = (str != NULL) ? atoi(str) : -1;
2313         if (val > 0) ox = val;
2314
2315         sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
2316         str = getenv(buf);
2317         val = (str != NULL) ? atoi(str) : -1;
2318         if (val > 0) oy = val;
2319
2320         MAKE(td->fnt, infofnt);
2321         Infofnt_set(td->fnt);
2322         Infofnt_init_data(font);
2323
2324         num = ((i == 0) ? 1024 : 16);
2325         wid = cols * td->fnt->wid + (ox + ox);
2326         hgt = rows * td->fnt->hgt + (oy + oy);
2327         MAKE(td->win, infowin);
2328         Infowin_set(td->win);
2329         Infowin_init_top(x, y, wid, hgt, 0,
2330                          Metadpy->fg, Metadpy->bg);
2331
2332 #if defined(USE_XIM)
2333         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask);
2334 #else
2335         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
2336 #endif
2337
2338         Infowin_set_name(name);
2339         Infowin->ox = ox;
2340         Infowin->oy = oy;
2341         ch = XAllocClassHint();
2342
2343         if (ch == NULL) quit("XAllocClassHint failed");
2344
2345         strcpy(res_name, name);
2346         res_name[0] = force_lower(res_name[0]);
2347         ch->res_name = res_name;
2348
2349         strcpy(res_class, "Angband");
2350         ch->res_class = res_class;
2351
2352         XSetClassHint(Metadpy->dpy, Infowin->win, ch);
2353         sh = XAllocSizeHints();
2354         if (sh == NULL) quit("XAllocSizeHints failed");
2355
2356         if (i == 0)
2357         {
2358                 sh->flags = PMinSize | PMaxSize;
2359                 sh->min_width = 80 * td->fnt->wid + (ox + ox);
2360                 sh->min_height = 24 * td->fnt->hgt + (oy + oy);
2361                 sh->max_width = 255 * td->fnt->wid + (ox + ox);
2362                 sh->max_height = 255 * td->fnt->hgt + (oy + oy);
2363         }
2364         else
2365         {
2366                 sh->flags = PMinSize | PMaxSize;
2367                 sh->min_width = td->fnt->wid + (ox + ox);
2368                 sh->min_height = td->fnt->hgt + (oy + oy);
2369                 sh->max_width = 256 * td->fnt->wid + (ox + ox);
2370                 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
2371         }
2372
2373         sh->flags |= PResizeInc;
2374         sh->width_inc = td->fnt->wid;
2375         sh->height_inc = td->fnt->hgt;
2376         sh->flags |= PBaseSize;
2377         sh->base_width = (ox + ox);
2378         sh->base_height = (oy + oy);
2379         XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
2380         Infowin_map();
2381
2382 #ifdef USE_XIM
2383         wh = XAllocWMHints();
2384         if(wh == NULL) quit("XAllocWMHints failed");
2385         wh->flags = InputHint;
2386         wh->input = True;
2387         XSetWMHints(Metadpy->dpy, Infowin->win, wh);
2388 #endif
2389
2390         if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
2391
2392         term_init(t, cols, rows, num);
2393         t->soft_cursor = TRUE;
2394         t->attr_blank = TERM_WHITE;
2395         t->char_blank = ' ';
2396         t->xtra_hook = Term_xtra_x11;
2397         t->curs_hook = Term_curs_x11;
2398         t->bigcurs_hook = Term_bigcurs_x11;
2399         t->wipe_hook = Term_wipe_x11;
2400         t->text_hook = Term_text_x11;
2401         t->data = td;
2402         Term_activate(t);
2403         return (0);
2404 }
2405
2406 /*
2407  * Initialization function for an "X11" module to Angband
2408  */
2409 errr init_x11(int argc, char *argv[])
2410 {
2411         int i;
2412         concptr dpy_name = "";
2413         int num_term = 3;
2414
2415 #ifndef USE_XFT
2416         char filename[1024];
2417
2418         int pict_wid = 0;
2419         int pict_hgt = 0;
2420
2421         char *TmpData;
2422 #endif
2423
2424         for (i = 1; i < argc; i++)
2425         {
2426                 if (prefix(argv[i], "-d"))
2427                 {
2428                         dpy_name = &argv[i][2];
2429                         continue;
2430                 }
2431                 
2432 #ifndef USE_XFT
2433                 if (prefix(argv[i], "-s"))
2434                 {
2435                         smoothRescaling = FALSE;
2436                         continue;
2437                 }
2438
2439                 if (prefix(argv[i], "-a"))
2440                 {
2441                         arg_graphics = GRAPHICS_ADAM_BOLT;
2442                         continue;
2443                 }
2444
2445                 if (prefix(argv[i], "-o"))
2446                 {
2447                         arg_graphics = GRAPHICS_ORIGINAL;
2448                         continue;
2449                 }
2450 #endif
2451
2452                 if (prefix(argv[i], "-b"))
2453                 {
2454                         arg_bigtile = use_bigtile = TRUE;
2455                         continue;
2456                 }
2457
2458                 if (prefix(argv[i], "-n"))
2459                 {
2460                         num_term = atoi(&argv[i][2]);
2461                         if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
2462                         else if (num_term < 1) num_term = 1;
2463                         continue;
2464                 }
2465
2466                 if (prefix(argv[i], "--"))
2467                 {
2468                         continue;
2469                 }
2470
2471                 plog_fmt("Ignoring option: %s", argv[i]);
2472         }
2473
2474 #ifdef USE_LOCALE
2475
2476 #ifdef JP
2477         setlocale(LC_ALL, "");
2478
2479 #ifdef DEFAULT_LOCALE
2480         if(!strcmp(setlocale(LC_ALL, NULL), "C")){
2481                 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
2482                 setlocale(LC_ALL, DEFAULT_LOCALE);
2483         }
2484 #endif
2485
2486         if(!strcmp(setlocale(LC_ALL, NULL), "C"))
2487         {
2488                 printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
2489         }
2490
2491         if(!XSupportsLocale()){
2492                 printf("can't support locale in X\n");
2493                 setlocale(LC_ALL, "C");
2494         }
2495 #else
2496         setlocale(LC_ALL, "C");
2497 #endif /* JP */
2498
2499 #endif /* USE_LOCALE */
2500
2501         if (Metadpy_init_name(dpy_name)) return (-1);
2502
2503         MAKE(xor, infoclr);
2504         Infoclr_set(xor);
2505         Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
2506         for (i = 0; i < 256; ++i)
2507         {
2508                 Pixell pixel;
2509                 MAKE(clr[i], infoclr);
2510                 Infoclr_set(clr[i]);
2511                 color_table[i][0] = angband_color_table[i][0];
2512                 color_table[i][1] = angband_color_table[i][1];
2513                 color_table[i][2] = angband_color_table[i][2];
2514                 color_table[i][3] = angband_color_table[i][3];
2515                 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
2516                 if (Metadpy->color)
2517                 {
2518                         pixel = create_pixel(Metadpy->dpy,
2519                                              color_table[i][1],
2520                                              color_table[i][2],
2521                                              color_table[i][3]);
2522                 }
2523
2524                 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
2525         }
2526
2527         set_atoms();
2528         for (i = 0; i < num_term; i++)
2529         {
2530                 term_data *td = &data[i];
2531                 term_data_init(td, i);
2532                 angband_term[i] = Term;
2533         }
2534
2535         Infowin_set(data[0].win);
2536         Infowin_raise();
2537         Term_activate(&data[0].t);
2538
2539 #ifdef USE_XIM
2540         {
2541                 char *p;
2542                 p = XSetLocaleModifiers("");
2543                 if(!p || !*p){
2544                         p = XSetLocaleModifiers("@im=");
2545                 }
2546         }
2547         XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
2548 #endif
2549
2550         if (arg_sound) init_sound();
2551
2552 #ifndef USE_XFT
2553         switch (arg_graphics)
2554         {
2555         case GRAPHICS_ORIGINAL:
2556                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/8x8.bmp");
2557                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
2558                 {
2559                         use_graphics = TRUE;
2560                         pict_wid = pict_hgt = 8;
2561                         ANGBAND_GRAF = "old";
2562                         break;
2563                 }
2564         case GRAPHICS_ADAM_BOLT:
2565                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/16x16.bmp");
2566                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
2567                 {
2568                         use_graphics = TRUE;
2569                         pict_wid = pict_hgt = 16;
2570                         ANGBAND_GRAF = "new";
2571                         break;
2572                 }
2573         }
2574
2575         if (use_graphics)
2576         {
2577                 Display *dpy = Metadpy->dpy;
2578                 XImage *tiles_raw;
2579                 tiles_raw = ReadBMP(dpy, filename);
2580                 for (i = 0; i < num_term; i++)
2581                 {
2582                         term_data *td = &data[i];
2583                         term *t = &td->t;
2584                         t->pict_hook = Term_pict_x11;
2585                         t->higher_pict = TRUE;
2586                         td->tiles =
2587                         ResizeImage(dpy, tiles_raw,
2588                                     pict_wid, pict_hgt,
2589                                     td->fnt->twid, td->fnt->hgt);
2590                 }
2591
2592                 for (i = 0; i < num_term; i++)
2593                 {
2594                         term_data *td = &data[i];
2595                         int ii, jj;
2596                         int depth = DefaultDepth(dpy, DefaultScreen(dpy));
2597                         Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
2598                         int total;
2599                         ii = 1;
2600                         jj = (depth - 1) >> 2;
2601                         while (jj >>= 1) ii <<= 1;
2602                         total = td->fnt->twid * td->fnt->hgt * ii;
2603                         TmpData = (char *)malloc(total);
2604                         td->TmpImage = XCreateImage(dpy,visual,depth,
2605                                 ZPixmap, 0, TmpData,
2606                                 td->fnt->twid, td->fnt->hgt, 8, 0);
2607                 }
2608         }
2609 #endif /* ! USE_XFT */
2610         return (0);
2611 }
2612
2613 #endif /* USE_X11 */