OSDN Git Service

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