OSDN Git Service

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