OSDN Git Service

[cleanup] GCCの警告に対応
[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 #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  * Convert to EUC-JP
1045  */
1046 #ifdef USE_XIM
1047 static void convert_to_euc(char *buf)
1048 {
1049         size_t inlen = strlen(buf);
1050         size_t outlen = inlen + 1;
1051         char tmp[outlen];
1052
1053         iconv_t iconvd = iconv_open("EUC-JP", "UTF-8");
1054         char *inbuf = buf;
1055         char *outbuf = tmp;
1056         iconv(iconvd, &inbuf, &inlen, &outbuf, &outlen);
1057         iconv_close(iconvd);
1058
1059         int i, l = strlen(tmp);
1060         for (i = 0; i < l; i++)
1061                 buf[i] = tmp[i];
1062         buf[l] = '\0';
1063 }
1064 #endif
1065
1066 /*
1067  * Push multiple keys reversal
1068  */
1069 static void term_string_push(char *buf)
1070 {
1071         int i, l = strlen(buf);
1072         for (i = l; i >= 0; i--)
1073                 term_key_push(buf[i]);
1074 }
1075
1076 /*
1077  * Process a keypress event
1078  *
1079  * Also appears in "main-xaw.c".
1080  */
1081 static void react_keypress(XKeyEvent *xev)
1082 {
1083         int n, mc, ms, mo, mx;
1084         uint ks1;
1085         XKeyEvent *ev = (XKeyEvent*)(xev);
1086         KeySym ks;
1087         char buf[128];
1088         char msg[128];
1089
1090 #ifdef USE_XIM
1091         int valid_keysym = TRUE;
1092 #endif
1093
1094 #ifdef USE_XIM
1095         if(Focuswin && Focuswin->xic){
1096                 Status status;
1097                 n = XmbLookupString(Focuswin->xic, ev, buf, 125, &ks, &status);
1098                 if(status == XBufferOverflow){
1099                         printf("Input is too long, and dropped\n");
1100                         return;
1101                 }
1102                 if(status != XLookupKeySym && status != XLookupBoth){
1103                         valid_keysym = FALSE;
1104                 }
1105         }else{
1106                 n = XLookupString(ev, buf, 125, &ks, NULL);
1107         }
1108 #else
1109         n = XLookupString(ev, buf, 125, &ks, NULL);
1110 #endif
1111
1112         buf[n] = '\0';
1113
1114 #ifdef USE_XIM
1115         if(!valid_keysym) { /* XIMからの入力時のみ FALSE になる */
1116                 convert_to_euc(buf);
1117                 term_string_push(buf);
1118                 return;
1119         }
1120 #endif
1121
1122         if (IsModifierKey(ks)) return;
1123
1124         ks1 = (uint)(ks);
1125         mc = (ev->state & ControlMask) ? TRUE : FALSE;
1126         ms = (ev->state & ShiftMask) ? TRUE : FALSE;
1127         mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
1128         mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
1129         if (n && !mo && !mx && !IsSpecialKey(ks))
1130         {
1131                 term_string_push(buf);
1132                 return;
1133         }
1134
1135         switch (ks1)
1136         {
1137                 case XK_Escape:
1138                 {
1139                         term_key_push(ESCAPE);
1140                         return;
1141                 }
1142
1143                 case XK_Return:
1144                 {
1145                         term_key_push('\r');
1146                         return;
1147                 }
1148
1149                 case XK_Tab:
1150                 {
1151                         term_key_push('\t');
1152                         return;
1153                 }
1154
1155                 case XK_Delete:
1156                 {
1157                         term_key_push(0x7f);
1158                         return;
1159                 }
1160                 case XK_BackSpace:
1161                 {
1162                         term_key_push('\010');
1163                         return;
1164                 }
1165         }
1166
1167         if (ks)
1168         {
1169                 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
1170                         mc ? "N" : "", ms ? "S" : "",
1171                         mo ? "O" : "", mx ? "M" : "",
1172                         (unsigned long)(ks), 13);
1173         }
1174         else
1175         {
1176                 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
1177                         mc ? "N" : "", ms ? "S" : "",
1178                         mo ? "O" : "", mx ? "M" : "",
1179                         ev->keycode, 13);
1180         }
1181
1182         term_string_push(msg);
1183
1184         if (n && (macro_find_exact(msg) < 0))
1185         {
1186                 macro_add(msg, buf);
1187         }
1188 }
1189
1190 /*
1191  * Find the square a particular pixel is part of.
1192  */
1193 static void pixel_to_square(int * const x, int * const y,
1194         const int ox, const int oy)
1195 {
1196         (*x) = (ox - Infowin->ox) / Infofnt->wid;
1197         (*y) = (oy - Infowin->oy) / Infofnt->hgt;
1198 }
1199
1200 /*
1201  * Find the pixel at the top-left corner of a square.
1202  */
1203 static void square_to_pixel(int * const x, int * const y,
1204         const int ox, const int oy)
1205 {
1206         (*x) = ox * Infofnt->wid + Infowin->ox;
1207         (*y) = oy * Infofnt->hgt + Infowin->oy;
1208 }
1209
1210 /*
1211  * Convert co-ordinates from starting corner/opposite corner to minimum/maximum.
1212  */
1213 static void sort_co_ord(co_ord *min, co_ord *max,
1214         const co_ord *b, const co_ord *a)
1215 {
1216         min->x = MIN(a->x, b->x);
1217         min->y = MIN(a->y, b->y);
1218         max->x = MAX(a->x, b->x);
1219         max->y = MAX(a->y, b->y);
1220 }
1221
1222 /*
1223  * Remove the selection by redrawing it.
1224  */
1225 static void mark_selection_clear(int x1, int y1, int x2, int y2)
1226 {
1227         term_redraw_section(x1,y1,x2,y2);
1228 }
1229
1230 /*
1231  * Select an area by drawing a grey box around it.
1232  * NB. These two functions can cause flicker as the selection is modified,
1233  * as the game redraws the entire marked section.
1234  */
1235 static void mark_selection_mark(int x1, int y1, int x2, int y2)
1236 {
1237         square_to_pixel(&x1, &y1, x1, y1);
1238         square_to_pixel(&x2, &y2, x2, y2);
1239 #ifdef USE_XFT
1240         XftDrawRect(Infowin->draw, &clr[2]->fg, x1, y1, x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
1241 #else
1242         XDrawRectangle(Metadpy->dpy, Infowin->win, clr[2]->gc, x1, y1,
1243                 x2-x1+Infofnt->wid - 1, y2-y1+Infofnt->hgt - 1);
1244 #endif
1245 }
1246
1247 /*
1248  * Mark a selection by drawing boxes around it (for now).
1249  */
1250 static void mark_selection(void)
1251 {
1252         co_ord min, max;
1253         term_type *old = Term;
1254         bool draw = s_ptr->select;
1255         bool clear = s_ptr->drawn;
1256         if (s_ptr->t != old) term_activate(s_ptr->t);
1257
1258         if (clear)
1259         {
1260                 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->old);
1261                 mark_selection_clear(min.x, min.y, max.x, max.y);
1262         }
1263         if (draw)
1264         {
1265                 sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
1266                 mark_selection_mark(min.x, min.y, max.x, max.y);
1267         }
1268
1269         if (s_ptr->t != old) term_activate(old);
1270
1271         s_ptr->old.x = s_ptr->cur.x;
1272         s_ptr->old.y = s_ptr->cur.y;
1273         s_ptr->drawn = s_ptr->select;
1274 }
1275
1276 /*
1277  * Forget a selection for one reason or another.
1278  */
1279 static void copy_x11_release(void)
1280 {
1281         s_ptr->select = FALSE;
1282         mark_selection();
1283 }
1284
1285 /*
1286  * Start to select some text on the screen.
1287  */
1288 static void copy_x11_start(int x, int y)
1289 {
1290         if (s_ptr->select) copy_x11_release();
1291
1292         s_ptr->t = Term;
1293         s_ptr->init.x = s_ptr->cur.x = s_ptr->old.x = x;
1294         s_ptr->init.y = s_ptr->cur.y = s_ptr->old.y = y;
1295 }
1296
1297 /*
1298  * Respond to movement of the mouse when selecting text.
1299  */
1300 static void copy_x11_cont(int x, int y, unsigned int buttons)
1301 {
1302         x = MIN(MAX(x, 0), Term->wid-1);
1303         y = MIN(MAX(y, 0), Term->hgt-1);
1304         if (~buttons & Button1Mask) return;
1305         if (s_ptr->t != Term) return;
1306         if (x == s_ptr->old.x && y == s_ptr->old.y && s_ptr->select) return;
1307
1308         s_ptr->select = TRUE;
1309         s_ptr->cur.x = x;
1310         s_ptr->cur.y = y;
1311         mark_selection();
1312 }
1313
1314 /*
1315  * Respond to release of the left mouse button by putting the selected text in
1316  * the primary buffer.
1317  */
1318 static void copy_x11_end(const Time time)
1319 {
1320         if (!s_ptr->select) return;
1321         if (s_ptr->t != Term) return;
1322
1323         s_ptr->time = time;
1324         XSetSelectionOwner(Metadpy->dpy, XA_PRIMARY, Infowin->win, time);
1325         if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) != Infowin->win)
1326         {
1327                 s_ptr->select = FALSE;
1328                 mark_selection();
1329         }
1330 }
1331
1332 static Atom xa_targets, xa_timestamp, xa_text, xa_compound_text;
1333
1334 /*
1335  * Set the required variable atoms at start-up to avoid errors later.
1336  */
1337 static void set_atoms(void)
1338 {
1339         xa_targets = XInternAtom(DPY, "TARGETS", False);
1340         xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
1341         xa_text = XInternAtom(DPY, "TEXT", False);
1342         xa_compound_text = XInternAtom(DPY, "COMPOUND_TEXT", False);
1343 }
1344
1345 static Atom request_target = 0;
1346
1347 /*
1348  * Send a message to request that the PRIMARY buffer be sent here.
1349  */
1350 static void paste_x11_request(Atom target, const Time time)
1351 {
1352         Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1353         if (XGetSelectionOwner(DPY, XA_PRIMARY) == None)
1354         {
1355                 /* No selection. */
1356                 /* bell("No selection found."); */
1357                 return;
1358         }
1359
1360         request_target = target;
1361     XConvertSelection(DPY, XA_PRIMARY, target, property, WIN, time);
1362 }
1363
1364 /*
1365  * Add the contents of the PRIMARY buffer to the input queue.
1366  *
1367  * Hack - This doesn't use the "time" of the event, and so accepts anything a
1368  * client tries to send it.
1369  */
1370 static void paste_x11_accept(const XSelectionEvent *ptr)
1371 {
1372         unsigned long left;
1373         const long offset = 0;
1374         const long length = 32000;
1375         XTextProperty xtextproperty;
1376         errr err = 0;
1377         Atom property = XInternAtom(DPY, "__COPY_TEXT", False);
1378         if (ptr->property == None)
1379         {
1380                 if (request_target == xa_compound_text)
1381                 {
1382                         paste_x11_request(XA_STRING, ptr->time);
1383                 }
1384                 else
1385                 {
1386                         request_target = 0;
1387                         plog("Paste failure (remote client could not send).");
1388                 }
1389
1390                 return;
1391         }
1392
1393         if (ptr->selection != XA_PRIMARY)
1394         {
1395                 plog("Paste failure (remote client did not send primary selection).");
1396                 return;
1397         }
1398
1399         if (ptr->target != request_target)
1400         {
1401                 plog("Paste failure (selection in unknown format).");
1402                 return;
1403         }
1404
1405         if (XGetWindowProperty(Metadpy->dpy, Infowin->win, property, offset,
1406                                length, TRUE, request_target,
1407                                &xtextproperty.encoding,
1408                                &xtextproperty.format,
1409                                &xtextproperty.nitems,
1410                                &left,
1411                                &xtextproperty.value)
1412             != Success)
1413         {
1414                 return;
1415         }
1416
1417         if (request_target == xa_compound_text)
1418         {
1419                 char **list;
1420                 int count;
1421                 
1422                 XmbTextPropertyToTextList(DPY, &xtextproperty, &list, &count);
1423
1424                 if (list)
1425                 {
1426                         int i;
1427
1428                         for (i = 0; i < count; i++)
1429                         {
1430                                 err = type_string(list[i], 0);
1431                                 if (err) break;
1432                         }
1433
1434                         XFreeStringList(list);
1435                 }
1436         }
1437         else
1438         {
1439                 err = type_string((char *)xtextproperty.value, xtextproperty.nitems);
1440         }
1441
1442         XFree(xtextproperty.value); 
1443         if (err)
1444         {
1445                 plog("Paste failure (too much text selected).");
1446         }
1447 }
1448
1449 /*
1450  * Add a character to a string in preparation for sending it to another
1451  * client as a STRING.
1452  * This doesn't change anything, as clients tend not to have difficulty in
1453  * receiving this format (although the standard specifies a restricted set).
1454  * Strings do not have a colour.
1455  */
1456 static bool paste_x11_send_text(XSelectionRequestEvent *rq)
1457 {
1458         char buf[1024];
1459         char *list[1000];
1460         co_ord max, min;
1461         TERM_LEN x,y;
1462         int l,n;
1463         TERM_COLOR a;
1464         char c;
1465
1466         if (rq->time < s_ptr->time) return FALSE;
1467
1468         sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
1469         if (XGetSelectionOwner(DPY, XA_PRIMARY) != WIN)
1470         {
1471                 return FALSE;
1472         }
1473
1474         XDeleteProperty(DPY, rq->requestor, rq->property);
1475
1476         for (n = 0, y = 0; y < Term->hgt; y++)
1477         {
1478 #ifdef JP
1479                 int kanji = 0;
1480 #endif
1481                 if (y < min.y) continue;
1482                 if (y > max.y) break;
1483
1484                 for (l = 0, x = 0; x < Term->wid; x++)
1485                 {
1486 #ifdef JP
1487                         if (x > max.x) break;
1488
1489                         term_what(x, y, &a, &c);
1490                         if (1 == kanji) kanji = 2;
1491                         else if (iskanji(c)) kanji = 1;
1492                         else kanji = 0;
1493
1494                         if (x < min.x) continue;
1495
1496                         /*
1497                          * A single kanji character was divided in two...
1498                          * Delete the garbage.
1499                          */
1500                         if ((2 == kanji && x == min.x) ||
1501                             (1 == kanji && x == max.x))
1502                                 c = ' ';
1503 #else
1504                         if (x > max.x) break;
1505                         if (x < min.x) continue;
1506
1507                         term_what(x, y, &a, &c);
1508 #endif
1509
1510                         buf[l] = c;
1511                         l++;
1512                 }
1513
1514                 while (buf[l-1] == ' ') l--;
1515
1516                 if (min.y != max.y)
1517                 {
1518                         buf[l] = '\n';
1519                         l++;
1520                 }
1521
1522                 buf[l] = '\0';
1523                 list[n++] = (char *)string_make(buf);
1524         }
1525
1526         list[n] = NULL;
1527         if (rq->target == XA_STRING)
1528         {
1529                 for (n = 0; list[n]; n++)
1530                 {
1531                         XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
1532                                         PropModeAppend, (unsigned char *)list[n], strlen(list[n]));
1533                 }
1534         }
1535         else if (rq->target == xa_text || 
1536                  rq->target == xa_compound_text)
1537         {
1538                 XTextProperty text_prop;
1539                 XICCEncodingStyle style;
1540
1541                 if (rq->target == xa_text)
1542                         style = XStdICCTextStyle;
1543                 else
1544                         style = XCompoundTextStyle;
1545
1546                 if (Success ==
1547                     XmbTextListToTextProperty(DPY, list, n, style, &text_prop))
1548                 {
1549                         XChangeProperty(DPY,
1550                                         rq->requestor,
1551                                         rq->property,
1552                                         text_prop.encoding,
1553                                         text_prop.format,
1554                                         PropModeAppend,
1555                                         text_prop.value,
1556                                         text_prop.nitems);
1557                         XFree(text_prop.value);
1558                 }
1559         }
1560
1561         for (n = 0; list[n]; n++)
1562         {
1563                 string_free(list[n]);
1564         }
1565
1566         return TRUE;
1567 }
1568
1569 /*
1570  * Send some text requested by another X client.
1571  */
1572 static void paste_x11_send(XSelectionRequestEvent *rq)
1573 {
1574         XEvent event;
1575         XSelectionEvent *ptr = &(event.xselection);
1576
1577         ptr->type = SelectionNotify;
1578         ptr->property = rq->property;
1579         ptr->display = rq->display;
1580         ptr->requestor = rq->requestor;
1581         ptr->selection = rq->selection;
1582         ptr->target = rq->target;
1583         ptr->time = rq->time;
1584
1585         /*
1586          * Paste the appropriate information for each target type.
1587          * Note that this currently rejects MULTIPLE targets.
1588          */
1589
1590         if (rq->target == XA_STRING ||
1591             rq->target == xa_text ||
1592             rq->target == xa_compound_text)
1593         {
1594                 if (!paste_x11_send_text(rq))
1595                         ptr->property = None;
1596         }
1597         else if (rq->target == xa_targets)
1598         {
1599                 Atom target_list[4];
1600                 target_list[0] = XA_STRING;
1601                 target_list[1] = xa_text;
1602                 target_list[2] = xa_compound_text;
1603                 target_list[3] = xa_targets;
1604                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
1605                         (8 * sizeof(target_list[0])), PropModeReplace,
1606                         (unsigned char *)target_list,
1607                         (sizeof(target_list) / sizeof(target_list[0])));
1608         }
1609         else if (rq->target == xa_timestamp)
1610         {
1611                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
1612                         (8 * sizeof(Time)), PropModeReplace,
1613                         (unsigned char *)s_ptr->time, 1);
1614         }
1615         else
1616         {
1617                 ptr->property = None;
1618         }
1619
1620         XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
1621 }
1622
1623 /*
1624  * Handle various events conditional on presses of a mouse button.
1625  */
1626 static void handle_button(Time time, int x, int y, int button, bool press)
1627 {
1628         pixel_to_square(&x, &y, x, y);
1629
1630         if (press && button == 1) copy_x11_start(x, y);
1631         if (!press && button == 1) copy_x11_end(time);
1632         if (!press && button == 2) paste_x11_request(xa_compound_text, time);
1633 }
1634
1635 /*
1636  * Process events
1637  */
1638 static errr CheckEvent(bool wait)
1639 {
1640         term_data *old_td = (term_data*)(Term->data);
1641
1642         XEvent xev_body, *xev = &xev_body;
1643
1644         term_data *td = NULL;
1645         infowin *iwin = NULL;
1646
1647         int i;
1648
1649 #ifdef USE_XIM
1650         do
1651         {
1652 #endif
1653
1654                 if (!wait && !XPending(Metadpy->dpy)) return (1);
1655
1656                 if (s_ptr->select && !s_ptr->drawn) mark_selection();
1657
1658                 XNextEvent(Metadpy->dpy, xev);
1659
1660 #ifdef USE_XIM
1661         } while (XFilterEvent(xev, xev->xany.window));
1662 #endif
1663
1664         if (xev->type == MappingNotify)
1665         {
1666                 XRefreshKeyboardMapping(&xev->xmapping);
1667                 return 0;
1668         }
1669
1670         for (i = 0; i < MAX_TERM_DATA; i++)
1671         {
1672                 if (!data[i].win) continue;
1673                 if (xev->xany.window == data[i].win->win)
1674                 {
1675                         td = &data[i];
1676                         iwin = td->win;
1677                         break;
1678                 }
1679         }
1680
1681         if (!td || !iwin) return (0);
1682
1683         term_activate(&td->t);
1684         Infowin_set(iwin);
1685         switch (xev->type)
1686         {
1687                 case ButtonPress:
1688                 case ButtonRelease:
1689                 {
1690                         bool press = (xev->type == ButtonPress);
1691                         int x = xev->xbutton.x;
1692                         int y = xev->xbutton.y;
1693                         int z;
1694                         if (xev->xbutton.button == Button1) z = 1;
1695                         else if (xev->xbutton.button == Button2) z = 2;
1696                         else if (xev->xbutton.button == Button3) z = 3;
1697                         else if (xev->xbutton.button == Button4) z = 4;
1698                         else if (xev->xbutton.button == Button5) z = 5;
1699                         else z = 0;
1700
1701                         handle_button(xev->xbutton.time, x, y, z, press);
1702                         break;
1703                 }
1704                 case EnterNotify:
1705                 case LeaveNotify:
1706                 {
1707                         break;
1708                 }
1709                 case MotionNotify:
1710                 {
1711                         int x = xev->xmotion.x;
1712                         int y = xev->xmotion.y;
1713                         unsigned int z = xev->xmotion.state;
1714                         pixel_to_square(&x, &y, x, y);
1715                         copy_x11_cont(x, y, z);
1716                         break;
1717                 }
1718                 case SelectionNotify:
1719                 {
1720                         paste_x11_accept(&(xev->xselection));
1721                         break;
1722                 }
1723                 case SelectionRequest:
1724                 {
1725                         paste_x11_send(&(xev->xselectionrequest));
1726                         break;
1727                 }
1728                 case SelectionClear:
1729                 {
1730                         s_ptr->select = FALSE;
1731                         mark_selection();
1732                         break;
1733                 }
1734                 case KeyRelease:
1735                 {
1736                         break;
1737                 }
1738                 case KeyPress:
1739                 {
1740                         term_activate(&old_td->t);
1741                         react_keypress(&(xev->xkey));
1742                         break;
1743                 }
1744                 case Expose:
1745                 {
1746                         int x1, x2, y1, y2;
1747                         x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
1748                         x2 = (xev->xexpose.x + xev->xexpose.width -
1749                                  Infowin->ox)/Infofnt->wid;
1750                         
1751                         y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
1752                         y2 = (xev->xexpose.y + xev->xexpose.height -
1753                                  Infowin->oy)/Infofnt->hgt;
1754                         
1755                         term_redraw_section(x1, y1, x2, y2);
1756                         break;
1757                 }
1758                 case MapNotify:
1759                 {
1760                         Infowin->mapped = 1;
1761                         Term->mapped_flag = TRUE;
1762                         break;
1763                 }
1764                 case UnmapNotify:
1765                 {
1766                         Infowin->mapped = 0;
1767                         Term->mapped_flag = FALSE;
1768                         break;
1769                 }
1770                 case ConfigureNotify:
1771                 {
1772                         int cols, rows, wid, hgt;
1773                         int ox = Infowin->ox;
1774                         int oy = Infowin->oy;
1775                         Infowin->x = xev->xconfigure.x;
1776                         Infowin->y = xev->xconfigure.y;
1777                         Infowin->w = xev->xconfigure.width;
1778                         Infowin->h = xev->xconfigure.height;
1779                         cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
1780                         rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
1781                         if (cols < 1) cols = 1;
1782                         if (rows < 1) rows = 1;
1783
1784                         if (td == &data[0])
1785                         {
1786                                 if (cols < 80) cols = 80;
1787                                 if (rows < 24) rows = 24;
1788                         }
1789
1790                         wid = cols * td->fnt->wid + (ox + ox);
1791                         hgt = rows * td->fnt->hgt + (oy + oy);
1792                         term_resize(cols, rows);
1793                         if ((Infowin->w != wid) || (Infowin->h != hgt))
1794                         {
1795                                 Infowin_set(td->win);
1796                                 Infowin_resize(wid, hgt);
1797                         }
1798
1799                         break;
1800                 }
1801 #ifdef USE_XIM
1802                 case FocusIn:
1803                 {
1804                         if(iwin->xic){
1805                                 XSetICFocus(iwin->xic);
1806                         }
1807                         Focuswin = iwin;
1808                         break;
1809                 }
1810                 case FocusOut:
1811                 {
1812                         if(iwin->xic)
1813                         {
1814                                 XUnsetICFocus(iwin->xic);
1815                         }
1816
1817                         break;
1818                 }
1819 #endif
1820         }
1821
1822         term_activate(&old_td->t);
1823         Infowin_set(old_td->win);
1824         return (0);
1825 }
1826
1827 /*
1828  * An array of sound file names
1829  */
1830 static concptr sound_file[SOUND_MAX];
1831
1832 /*
1833  * Check for existance of a file
1834  */
1835 static bool check_file(concptr s)
1836 {
1837         FILE *fff;
1838
1839         fff = fopen(s, "r");
1840         if (!fff) return (FALSE);
1841         
1842         fclose(fff);
1843         return (TRUE);
1844 }
1845
1846 /*
1847  * Initialize sound
1848  */
1849 static void init_sound(void)
1850 {
1851         int i;
1852         char wav[128];
1853         char buf[1024];
1854         char dir_xtra_sound[1024];
1855         path_build(dir_xtra_sound, sizeof(dir_xtra_sound), ANGBAND_DIR_XTRA, "sound");
1856         for (i = 1; i < SOUND_MAX; i++)
1857         {
1858                 sprintf(wav, "%s.wav", angband_sound_name[i]);
1859                 path_build(buf, sizeof(buf), dir_xtra_sound, wav);
1860                 if (check_file(buf)) sound_file[i] = string_make(buf);
1861         }
1862
1863         use_sound = TRUE;
1864         return;
1865 }
1866
1867 /*
1868  * Hack -- make a sound
1869  */
1870 static errr Term_xtra_x11_sound(int v)
1871 {
1872         char buf[1024];
1873         if (!use_sound) return (1);
1874         if ((v < 0) || (v >= SOUND_MAX)) return (1);
1875         if (!sound_file[v]) return (1);
1876         
1877         sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
1878         return (system(buf) < 0);
1879         
1880 }
1881
1882 /*
1883  * Handle "activation" of a term
1884  */
1885 static errr Term_xtra_x11_level(int v)
1886 {
1887         term_data *td = (term_data*)(Term->data);
1888         if (v)
1889         {
1890                 Infowin_set(td->win);
1891                 Infofnt_set(td->fnt);
1892         }
1893
1894         return (0);
1895 }
1896
1897 /*
1898  * React to changes
1899  */
1900 static errr Term_xtra_x11_react(void)
1901 {
1902         int i;
1903         
1904         if (Metadpy->color)
1905         {
1906                 for (i = 0; i < 256; i++)
1907                 {
1908                         if ((color_table[i][0] != angband_color_table[i][0]) ||
1909                             (color_table[i][1] != angband_color_table[i][1]) ||
1910                             (color_table[i][2] != angband_color_table[i][2]) ||
1911                             (color_table[i][3] != angband_color_table[i][3]))
1912                         {
1913                                 Pixell pixel;
1914                                 color_table[i][0] = angband_color_table[i][0];
1915                                 color_table[i][1] = angband_color_table[i][1];
1916                                 color_table[i][2] = angband_color_table[i][2];
1917                                 color_table[i][3] = angband_color_table[i][3];
1918                                 pixel = create_pixel(Metadpy->dpy,
1919                                                      color_table[i][1],
1920                                                      color_table[i][2],
1921                                                      color_table[i][3]);
1922                                 Infoclr_set(clr[i]);
1923                                 Infoclr_change_fg(pixel);
1924                         }
1925                 }
1926         }
1927
1928         return (0);
1929 }
1930
1931 /*
1932  * Handle a "special request"
1933  */
1934 static errr Term_xtra_x11(int n, int v)
1935 {
1936         switch (n)
1937         {
1938                 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
1939                 case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
1940 #ifdef USE_XFT
1941                 case TERM_XTRA_FRESH: Metadpy_update(1, 1, 0); return (0);
1942 #else
1943                 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
1944 #endif
1945                 case TERM_XTRA_BORED: return (CheckEvent(0));
1946                 case TERM_XTRA_EVENT: return (CheckEvent(v));
1947                 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
1948                 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
1949                 case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
1950                 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
1951                 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
1952         }
1953
1954         return (1);
1955 }
1956
1957 /*
1958  * Draw the cursor as an inverted rectangle.
1959  *
1960  * Consider a rectangular outline like "main-mac.c".  XXX XXX
1961  */
1962 static errr Term_curs_x11(int x, int y)
1963 {
1964         if (use_graphics)
1965         {
1966 #ifdef USE_XFT
1967                 XftDrawRect(Infowin->draw, &xor->fg,
1968                             x * Infofnt->wid + Infowin->ox,
1969                             y * Infofnt->hgt + Infowin->oy,
1970                             Infofnt->wid - 1, Infofnt->hgt - 1);
1971                 XftDrawRect(Infowin->draw, &xor->fg,
1972                             x * Infofnt->wid + Infowin->ox + 1,
1973                             y * Infofnt->hgt + Infowin->oy + 1,
1974                             Infofnt->wid - 3, Infofnt->hgt - 3);
1975 #else
1976                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
1977                                x * Infofnt->wid + Infowin->ox,
1978                                y * Infofnt->hgt + Infowin->oy,
1979                                Infofnt->wid - 1, Infofnt->hgt - 1);
1980                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
1981                                x * Infofnt->wid + Infowin->ox + 1,
1982                                y * Infofnt->hgt + Infowin->oy + 1,
1983                                Infofnt->wid - 3, Infofnt->hgt - 3);
1984 #endif
1985         }
1986         else
1987         {
1988                 Infoclr_set(xor);
1989                 Infofnt_text_non(x, y, " ", 1);
1990         }
1991
1992         return (0);
1993 }
1994
1995
1996 /*
1997  * Draw the double width cursor
1998  */
1999 static errr Term_bigcurs_x11(int x, int y)
2000 {
2001         if (use_graphics)
2002         {
2003 #ifdef USE_XFT
2004                 XftDrawRect(Infowin->draw, &xor->fg,
2005                             x * Infofnt->wid + Infowin->ox,
2006                             y * Infofnt->hgt + Infowin->oy,
2007                             Infofnt->twid - 1, Infofnt->hgt - 1);
2008                 XftDrawRect(Infowin->draw, &xor->fg,
2009                             x * Infofnt->wid + Infowin->ox + 1,
2010                             y * Infofnt->hgt + Infowin->oy + 1,
2011                             Infofnt->twid - 3, Infofnt->hgt - 3);
2012 #else
2013                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2014                                x * Infofnt->wid + Infowin->ox,
2015                                y * Infofnt->hgt + Infowin->oy,
2016                                Infofnt->twid - 1, Infofnt->hgt - 1);
2017                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2018                                x * Infofnt->wid + Infowin->ox + 1,
2019                                y * Infofnt->hgt + Infowin->oy + 1,
2020                                Infofnt->twid - 3, Infofnt->hgt - 3);
2021 #endif
2022         }
2023         else
2024         {
2025                 Infoclr_set(xor);
2026                 Infofnt_text_non(x, y, "  ", 2);
2027         }
2028
2029         return (0);
2030 }
2031
2032 /*
2033  * Erase some characters.
2034  */
2035 static errr Term_wipe_x11(int x, int y, int n)
2036 {
2037         Infoclr_set(clr[TERM_DARK]);
2038         Infofnt_text_non(x, y, "", n);
2039         s_ptr->drawn = FALSE;
2040         return (0);
2041 }
2042
2043 /*
2044  * Draw some textual characters.
2045  */
2046 static errr Term_text_x11(TERM_LEN x, TERM_LEN y, int n, TERM_COLOR a, concptr s)
2047 {
2048         Infoclr_set(clr[a]);
2049         Infofnt_text_std(x, y, s, n);
2050         s_ptr->drawn = FALSE;
2051         return (0);
2052 }
2053
2054 #ifndef USE_XFT
2055 /*
2056  * Draw some graphical characters.
2057  */
2058 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)
2059 {
2060         int i, x1, y1;
2061
2062         TERM_COLOR a;
2063         char c;
2064
2065         TERM_COLOR ta;
2066         char tc;
2067
2068         int x2, y2;
2069         int k,l;
2070
2071         unsigned long pixel, blank;
2072
2073         term_data *td = (term_data*)(Term->data);
2074
2075         y *= Infofnt->hgt;
2076         x *= Infofnt->wid;
2077
2078         y += Infowin->oy;
2079         x += Infowin->ox;
2080         for (i = 0; i < n; ++i, x += td->fnt->wid)
2081         {
2082                 a = *ap++;
2083                 c = *cp++;
2084                 x1 = (c&0x7F) * td->fnt->twid;
2085                 y1 = (a&0x7F) * td->fnt->hgt;
2086                 if (td->tiles->width < x1 + td->fnt->wid ||
2087                     td->tiles->height < y1 + td->fnt->hgt)
2088                 {
2089                         XFillRectangle(Metadpy->dpy, td->win->win, clr[0]->gc, x, y,  td->fnt->twid, td->fnt->hgt);
2090                         continue;
2091                 }
2092
2093                 ta = *tap++;
2094                 tc = *tcp++;
2095
2096                 x2 = (tc&0x7F) * td->fnt->twid;
2097                 y2 = (ta&0x7F) * td->fnt->hgt;
2098                 
2099                 if (((x1 == x2) && (y1 == y2)) ||
2100                     !(((byte)ta & 0x80) && ((byte)tc & 0x80)) ||
2101                     td->tiles->width < x2 + td->fnt->wid ||
2102                     td->tiles->height < y2 + td->fnt->hgt)
2103                 {
2104                         XPutImage(Metadpy->dpy, td->win->win,
2105                                 clr[0]->gc,
2106                                 td->tiles,
2107                                 x1, y1,
2108                                 x, y,
2109                                 td->fnt->twid, td->fnt->hgt);   
2110                 }
2111                 else
2112                 {
2113                         blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
2114                         for (k = 0; k < td->fnt->twid; k++)
2115                         {
2116                                 for (l = 0; l < td->fnt->hgt; l++)
2117                                 {
2118                                         if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
2119                                         {
2120                                                 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
2121                                         }
2122                                         
2123                                         XPutPixel(td->TmpImage, k, l, pixel);
2124                                 }
2125                         }
2126
2127                         XPutImage(Metadpy->dpy, td->win->win,
2128                               clr[0]->gc,
2129                              td->TmpImage,
2130                              0, 0, x, y,
2131                              td->fnt->twid, td->fnt->hgt);
2132                 }
2133         }
2134
2135         s_ptr->drawn = FALSE;
2136         return (0);
2137 }
2138 #endif
2139
2140 #ifdef USE_XIM
2141 static void IMDestroyCallback(XIM, XPointer, XPointer);
2142
2143 static void
2144 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
2145 {
2146         XIM xim;
2147         XIMCallback ximcallback;
2148         XIMStyles *xim_styles = NULL;
2149         int i;
2150
2151         (void)unused1;
2152         (void)unused2;
2153
2154         xim = XOpenIM(display, NULL, NULL, NULL);
2155         if(!xim){
2156                 printf("can't open IM\n");
2157                 return;
2158         }
2159
2160         ximcallback.callback = IMDestroyCallback;
2161         ximcallback.client_data = NULL;
2162         XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
2163         XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
2164         for (i = 0; i < xim_styles->count_styles; i++){
2165                 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
2166         }
2167         if(i >= xim_styles->count_styles){
2168                 printf("Sorry, your IM does not support 'Root' preedit style...\n");
2169                 XCloseIM(xim);
2170                 return;
2171         }
2172         XFree(xim_styles);
2173
2174         Metadpy->xim = xim;
2175
2176         for (i = 0; i < MAX_TERM_DATA; i++)
2177         {
2178                 infowin *iwin = data[i].win;
2179                 if (!iwin) continue;
2180                 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
2181                 if(!iwin->xic)
2182                 {
2183                         printf("Can't create input context for Term%d\n", i);
2184                         continue;
2185                 }
2186
2187                 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL)
2188                 {
2189                         iwin->xic_mask = 0L;
2190                 }
2191
2192                 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
2193         }
2194
2195         return;
2196 }
2197
2198 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
2199 {
2200         int i;
2201         (void)xim;
2202         (void)client_data;
2203
2204         if (call_data == NULL){
2205                 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
2206         }
2207
2208         for(i = 0; i < MAX_TERM_DATA; i++)
2209         {
2210                 infowin *iwin = data[i].win;
2211                 if(!iwin) continue;
2212                 if(iwin->xic_mask){
2213                         XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
2214                         iwin->xic_mask = 0L;
2215                 }
2216                 iwin->xic = NULL;
2217         }
2218
2219         Metadpy->xim = NULL;
2220 }
2221 #endif
2222
2223 static char force_lower(char a)
2224 {
2225         return ((isupper((a))) ? tolower((a)) : (a));
2226 }
2227
2228 /*
2229  * Initialize a term_data
2230  */
2231 static errr term_data_init(term_data *td, int i)
2232 {
2233         term_type *t = &td->t;
2234
2235         concptr name = angband_term_name[i];
2236
2237         concptr font;
2238         int x = 0;
2239         int y = 0;
2240
2241         int cols = 80;
2242         int rows = 24;
2243
2244         int ox = 1;
2245         int oy = 1;
2246
2247         int wid, hgt, num;
2248
2249         char buf[80];
2250
2251         concptr str;
2252
2253         int val;
2254
2255         XClassHint *ch;
2256
2257         char res_name[20];
2258         char res_class[20];
2259
2260         XSizeHints *sh;
2261 #ifdef USE_XIM
2262         XWMHints *wh;
2263 #endif
2264
2265         sprintf(buf, "ANGBAND_X11_FONT_%d", i);
2266         font = getenv(buf);
2267         if (!font) font = getenv("ANGBAND_X11_FONT");
2268
2269         if (!font)
2270         {
2271                 switch (i)
2272                 {
2273                         case 0:
2274                         {
2275                                 font = DEFAULT_X11_FONT_0;
2276                         }
2277                         break;
2278                         case 1:
2279                         {
2280                                 font = DEFAULT_X11_FONT_1;
2281                         }
2282                         break;
2283                         case 2:
2284                         {
2285                                 font = DEFAULT_X11_FONT_2;
2286                         }
2287                         break;
2288                         case 3:
2289                         {
2290                                 font = DEFAULT_X11_FONT_3;
2291                         }
2292                         break;
2293                         case 4:
2294                         {
2295                                 font = DEFAULT_X11_FONT_4;
2296                         }
2297                         break;
2298                         case 5:
2299                         {
2300                                 font = DEFAULT_X11_FONT_5;
2301                         }
2302                         break;
2303                         case 6:
2304                         {
2305                                 font = DEFAULT_X11_FONT_6;
2306                         }
2307                         break;
2308                         case 7:
2309                         {
2310                                 font = DEFAULT_X11_FONT_7;
2311                         }
2312                         break;
2313                         default:
2314                         {
2315                                 font = DEFAULT_X11_FONT;
2316                         }
2317                 }
2318         }
2319
2320         sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
2321         str = getenv(buf);
2322         x = (str != NULL) ? atoi(str) : -1;
2323
2324         sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
2325         str = getenv(buf);
2326         y = (str != NULL) ? atoi(str) : -1;
2327
2328         sprintf(buf, "ANGBAND_X11_COLS_%d", i);
2329         str = getenv(buf);
2330         val = (str != NULL) ? atoi(str) : -1;
2331         if (val > 0) cols = val;
2332
2333         sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
2334         str = getenv(buf);
2335         val = (str != NULL) ? atoi(str) : -1;
2336         if (val > 0) rows = val;
2337
2338         if (!i)
2339         {
2340                 if (cols < 80) cols = 80;
2341                 if (rows < 24) rows = 24;
2342         }
2343
2344         sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
2345         str = getenv(buf);
2346         val = (str != NULL) ? atoi(str) : -1;
2347         if (val > 0) ox = val;
2348
2349         sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
2350         str = getenv(buf);
2351         val = (str != NULL) ? atoi(str) : -1;
2352         if (val > 0) oy = val;
2353
2354         MAKE(td->fnt, infofnt);
2355         Infofnt_set(td->fnt);
2356         Infofnt_init_data(font);
2357
2358         num = ((i == 0) ? 1024 : 16);
2359         wid = cols * td->fnt->wid + (ox + ox);
2360         hgt = rows * td->fnt->hgt + (oy + oy);
2361         MAKE(td->win, infowin);
2362         Infowin_set(td->win);
2363         Infowin_init_top(x, y, wid, hgt, 0,
2364                          Metadpy->fg, Metadpy->bg);
2365
2366 #if defined(USE_XIM)
2367         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask);
2368 #else
2369         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
2370 #endif
2371
2372         Infowin_set_name(name);
2373         Infowin->ox = ox;
2374         Infowin->oy = oy;
2375         ch = XAllocClassHint();
2376
2377         if (ch == NULL) quit("XAllocClassHint failed");
2378
2379         strcpy(res_name, name);
2380         res_name[0] = force_lower(res_name[0]);
2381         ch->res_name = res_name;
2382
2383         strcpy(res_class, "Angband");
2384         ch->res_class = res_class;
2385
2386         XSetClassHint(Metadpy->dpy, Infowin->win, ch);
2387         sh = XAllocSizeHints();
2388         if (sh == NULL) quit("XAllocSizeHints failed");
2389
2390         if (i == 0)
2391         {
2392                 sh->flags = PMinSize | PMaxSize;
2393                 sh->min_width = 80 * td->fnt->wid + (ox + ox);
2394                 sh->min_height = 24 * td->fnt->hgt + (oy + oy);
2395                 sh->max_width = 255 * td->fnt->wid + (ox + ox);
2396                 sh->max_height = 255 * td->fnt->hgt + (oy + oy);
2397         }
2398         else
2399         {
2400                 sh->flags = PMinSize | PMaxSize;
2401                 sh->min_width = td->fnt->wid + (ox + ox);
2402                 sh->min_height = td->fnt->hgt + (oy + oy);
2403                 sh->max_width = 256 * td->fnt->wid + (ox + ox);
2404                 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
2405         }
2406
2407         sh->flags |= PResizeInc;
2408         sh->width_inc = td->fnt->wid;
2409         sh->height_inc = td->fnt->hgt;
2410         sh->flags |= PBaseSize;
2411         sh->base_width = (ox + ox);
2412         sh->base_height = (oy + oy);
2413         XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
2414         Infowin_map();
2415
2416 #ifdef USE_XIM
2417         wh = XAllocWMHints();
2418         if(wh == NULL) quit("XAllocWMHints failed");
2419         wh->flags = InputHint;
2420         wh->input = True;
2421         XSetWMHints(Metadpy->dpy, Infowin->win, wh);
2422 #endif
2423
2424         if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
2425
2426         term_init(t, cols, rows, num);
2427         t->soft_cursor = TRUE;
2428         t->attr_blank = TERM_WHITE;
2429         t->char_blank = ' ';
2430         t->xtra_hook = Term_xtra_x11;
2431         t->curs_hook = Term_curs_x11;
2432         t->bigcurs_hook = Term_bigcurs_x11;
2433         t->wipe_hook = Term_wipe_x11;
2434         t->text_hook = Term_text_x11;
2435         t->data = td;
2436         term_activate(t);
2437         return (0);
2438 }
2439
2440 /*
2441  * Initialization function for an "X11" module to Angband
2442  */
2443 errr init_x11(int argc, char *argv[])
2444 {
2445         int i;
2446         concptr dpy_name = "";
2447         int num_term = 3;
2448
2449 #ifndef USE_XFT
2450         char filename[1024];
2451
2452         int pict_wid = 0;
2453         int pict_hgt = 0;
2454
2455         char *TmpData;
2456 #endif
2457
2458         for (i = 1; i < argc; i++)
2459         {
2460                 if (prefix(argv[i], "-d"))
2461                 {
2462                         dpy_name = &argv[i][2];
2463                         continue;
2464                 }
2465                 
2466 #ifndef USE_XFT
2467                 if (prefix(argv[i], "-s"))
2468                 {
2469                         smoothRescaling = FALSE;
2470                         continue;
2471                 }
2472
2473                 if (prefix(argv[i], "-a"))
2474                 {
2475                         arg_graphics = GRAPHICS_ADAM_BOLT;
2476                         continue;
2477                 }
2478
2479                 if (prefix(argv[i], "-o"))
2480                 {
2481                         arg_graphics = GRAPHICS_ORIGINAL;
2482                         continue;
2483                 }
2484 #endif
2485
2486                 if (prefix(argv[i], "-b"))
2487                 {
2488                         arg_bigtile = use_bigtile = TRUE;
2489                         continue;
2490                 }
2491
2492                 if (prefix(argv[i], "-n"))
2493                 {
2494                         num_term = atoi(&argv[i][2]);
2495                         if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
2496                         else if (num_term < 1) num_term = 1;
2497                         continue;
2498                 }
2499
2500                 if (prefix(argv[i], "--"))
2501                 {
2502                         continue;
2503                 }
2504
2505                 plog_fmt("Ignoring option: %s", argv[i]);
2506         }
2507
2508 #ifdef USE_LOCALE
2509
2510 #ifdef JP
2511         setlocale(LC_ALL, "");
2512
2513 #ifdef DEFAULT_LOCALE
2514         if(!strcmp(setlocale(LC_ALL, NULL), "C")){
2515                 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
2516                 setlocale(LC_ALL, DEFAULT_LOCALE);
2517         }
2518 #endif
2519
2520         if(!strcmp(setlocale(LC_ALL, NULL), "C"))
2521         {
2522                 printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
2523         }
2524
2525         if(!XSupportsLocale()){
2526                 printf("can't support locale in X\n");
2527                 setlocale(LC_ALL, "C");
2528         }
2529 #else
2530         setlocale(LC_ALL, "C");
2531 #endif /* JP */
2532
2533 #endif /* USE_LOCALE */
2534
2535         if (Metadpy_init_name(dpy_name)) return (-1);
2536
2537         MAKE(xor, infoclr);
2538         Infoclr_set(xor);
2539         Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
2540         for (i = 0; i < 256; ++i)
2541         {
2542                 Pixell pixel;
2543                 MAKE(clr[i], infoclr);
2544                 Infoclr_set(clr[i]);
2545                 color_table[i][0] = angband_color_table[i][0];
2546                 color_table[i][1] = angband_color_table[i][1];
2547                 color_table[i][2] = angband_color_table[i][2];
2548                 color_table[i][3] = angband_color_table[i][3];
2549                 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
2550                 if (Metadpy->color)
2551                 {
2552                         pixel = create_pixel(Metadpy->dpy,
2553                                              color_table[i][1],
2554                                              color_table[i][2],
2555                                              color_table[i][3]);
2556                 }
2557
2558                 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
2559         }
2560
2561         set_atoms();
2562         for (i = 0; i < num_term; i++)
2563         {
2564                 term_data *td = &data[i];
2565                 term_data_init(td, i);
2566                 angband_term[i] = Term;
2567         }
2568
2569         Infowin_set(data[0].win);
2570         Infowin_raise();
2571         term_activate(&data[0].t);
2572
2573 #ifdef USE_XIM
2574         {
2575                 char *p;
2576                 p = XSetLocaleModifiers("");
2577                 if(!p || !*p){
2578                         p = XSetLocaleModifiers("@im=");
2579                 }
2580         }
2581         XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
2582 #endif
2583
2584         if (arg_sound) init_sound();
2585
2586 #ifndef USE_XFT
2587         switch (arg_graphics)
2588         {
2589         case GRAPHICS_ORIGINAL:
2590                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/8x8.bmp");
2591                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
2592                 {
2593                         use_graphics = TRUE;
2594                         pict_wid = pict_hgt = 8;
2595                         ANGBAND_GRAF = "old";
2596                         break;
2597                 }
2598         case GRAPHICS_ADAM_BOLT:
2599                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/16x16.bmp");
2600                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
2601                 {
2602                         use_graphics = TRUE;
2603                         pict_wid = pict_hgt = 16;
2604                         ANGBAND_GRAF = "new";
2605                         break;
2606                 }
2607         }
2608
2609         if (use_graphics)
2610         {
2611                 Display *dpy = Metadpy->dpy;
2612                 XImage *tiles_raw;
2613                 tiles_raw = ReadBMP(dpy, filename);
2614                 for (i = 0; i < num_term; i++)
2615                 {
2616                         term_data *td = &data[i];
2617                         term_type *t = &td->t;
2618                         t->pict_hook = Term_pict_x11;
2619                         t->higher_pict = TRUE;
2620                         td->tiles =
2621                         ResizeImage(dpy, tiles_raw,
2622                                     pict_wid, pict_hgt,
2623                                     td->fnt->twid, td->fnt->hgt);
2624                 }
2625
2626                 for (i = 0; i < num_term; i++)
2627                 {
2628                         term_data *td = &data[i];
2629                         int ii, jj;
2630                         int depth = DefaultDepth(dpy, DefaultScreen(dpy));
2631                         Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
2632                         int total;
2633                         ii = 1;
2634                         jj = (depth - 1) >> 2;
2635                         while (jj >>= 1) ii <<= 1;
2636                         total = td->fnt->twid * td->fnt->hgt * ii;
2637                         TmpData = (char *)malloc(total);
2638                         td->TmpImage = XCreateImage(dpy,visual,depth,
2639                                 ZPixmap, 0, TmpData,
2640                                 td->fnt->twid, td->fnt->hgt, 8, 0);
2641                 }
2642         }
2643 #endif /* ! USE_XFT */
2644         return (0);
2645 }
2646
2647 #endif /* USE_X11 */