OSDN Git Service

★聖騎士強化, その他新★のレアリティ調整.
[hengband/hengband.git] / src / main-x11.c
1 /* File: main-x11.c */
2
3 /*
4  * Copyright (c) 1997 Ben Harrison, and others
5  *
6  * This software may be copied and distributed for educational, research,
7  * and not for profit purposes provided that this copyright and statement
8  * are included in all such copies.
9  */
10
11
12 #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  * Send a message to request that the PRIMARY buffer be sent here.
2138  */
2139 static void paste_x11_request(const Time time)
2140 {
2141         /* Check the owner. */
2142         if (XGetSelectionOwner(Metadpy->dpy, XA_PRIMARY) == None)
2143         {
2144                 /* No selection. */
2145                 /* bell("No selection found."); */
2146                 return;
2147         }
2148
2149         /* Request the event as a STRING. */
2150         XConvertSelection(DPY, XA_PRIMARY, XA_STRING, XA_STRING, WIN, time);
2151 }
2152
2153 /*
2154  * Add a character to a string in preparation for sending it to another
2155  * client as a STRING.
2156  * This doesn't change anything, as clients tend not to have difficulty in
2157  * receiving this format (although the standard specifies a restricted set).
2158  * Strings do not have a colour.
2159  */
2160 static int add_char_string(char *buf, byte a, char c)
2161 {
2162         (void)a;
2163
2164         *buf = c;
2165         return 1;
2166 }
2167
2168 static bool paste_x11_send_text(XSelectionRequestEvent *rq, int (*add)(char *, byte, char))
2169 {
2170         char buf[1024];
2171         co_ord max, min;
2172         int x,y,l;
2173         byte a;
2174         char c;
2175
2176         /* Too old, or incorrect call. */
2177         if (rq->time < s_ptr->time || !add) return FALSE;
2178
2179         /* Work out which way around to paste. */
2180         sort_co_ord(&min, &max, &s_ptr->init, &s_ptr->cur);
2181
2182         /* Paranoia. */
2183         if (XGetSelectionOwner(DPY, XA_PRIMARY) != WIN)
2184         {
2185                 /* bell("Someone stole my selection!"); */
2186                 return FALSE;
2187         }
2188
2189         /* Delete the old value of the property. */
2190         XDeleteProperty(DPY, rq->requestor, rq->property);
2191
2192         for (y = 0; y < Term->hgt; y++)
2193         {
2194                 if (y < min.y) continue;
2195                 if (y > max.y) break;
2196
2197                 for (x = l = 0; x < Term->wid; x++)
2198                 {
2199                         if (x < min.x) continue;
2200                         if (x > max.x) break;
2201
2202                         /* Find the character. */
2203                         Term_what(x, y, &a, &c);
2204
2205                         /* Add it. */
2206                         l += (*add)(buf+l, a, c);
2207                 }
2208
2209 #if 0
2210                 /* Terminate all but the last line in an appropriate way. */
2211                 if (y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n');
2212 #else
2213                 /* Terminate all line unless single line message. */
2214                 if (min.y != max.y) l += (*add)(buf+l, TERM_WHITE, '\n');
2215 #endif
2216
2217                 /* Send the (non-empty) string. */
2218                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target, 8,
2219                         PropModeAppend, (byte*)buf, l);
2220         }
2221         return TRUE;
2222 }
2223
2224 static Atom xa_targets, xa_timestamp;
2225
2226 /*
2227  * Set the required variable atoms at start-up to avoid errors later.
2228  */
2229 static void set_atoms(void)
2230 {
2231         xa_targets = XInternAtom(DPY, "TARGETS", False);
2232         xa_timestamp = XInternAtom(DPY, "TIMESTAMP", False);
2233 }
2234
2235 /*
2236  * Send some text requested by another X client.
2237  */
2238 static void paste_x11_send(XSelectionRequestEvent *rq)
2239 {
2240         XEvent event;
2241         XSelectionEvent *ptr = &(event.xselection);
2242
2243         /* Set the event parameters. */
2244         ptr->type = SelectionNotify;
2245         ptr->property = rq->property;
2246         ptr->display = rq->display;
2247         ptr->requestor = rq->requestor;
2248         ptr->selection = rq->selection;
2249         ptr->target = rq->target;
2250         ptr->time = rq->time;
2251
2252         /* Paste the appropriate information for each target type.
2253          * Note that this currently rejects MULTIPLE targets.
2254          */
2255
2256         if (rq->target == XA_STRING)
2257         {
2258                 if (!paste_x11_send_text(rq, add_char_string))
2259                         ptr->property = None;
2260         }
2261         else if (rq->target == xa_targets)
2262         {
2263                 Atom target_list[2];
2264                 target_list[0] = XA_STRING;
2265                 target_list[1] = xa_targets;
2266                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
2267                         (8 * sizeof(target_list[0])), PropModeReplace,
2268                         (unsigned char *)target_list,
2269                         (sizeof(target_list) / sizeof(target_list[0])));
2270         }
2271         else if (rq->target == xa_timestamp)
2272         {
2273                 XChangeProperty(DPY, rq->requestor, rq->property, rq->target,
2274                         (8 * sizeof(Time)), PropModeReplace,
2275                         (unsigned char *)s_ptr->time, 1);
2276         }
2277         else
2278         {
2279                 ptr->property = None;
2280         }
2281
2282         /* Send whatever event we're left with. */
2283         XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
2284 }
2285
2286 /*
2287  * Add the contents of the PRIMARY buffer to the input queue.
2288  *
2289  * Hack - This doesn't use the "time" of the event, and so accepts anything a
2290  * client tries to send it.
2291  */
2292 static void paste_x11_accept(const XSelectionEvent *ptr)
2293 {
2294         unsigned long offset, left;
2295
2296         /* Failure. */
2297         if (ptr->property == None)
2298         {
2299                 /* bell("Paste failure (remote client could not send)."); */
2300                 return;
2301         }
2302
2303         if (ptr->selection != XA_PRIMARY)
2304         {
2305                 /* bell("Paste failure (remote client did not send primary selection)."); */
2306                 return;
2307         }
2308
2309         if (ptr->target != XA_STRING)
2310         {
2311                 /* bell("Paste failure (selection in unknown format)."); */
2312                 return;
2313         }
2314
2315         for (offset = 0; ; offset += left)
2316         {
2317                 errr err;
2318
2319                 /* A pointer for the pasted information. */
2320                 unsigned char *data;
2321
2322                 Atom type;
2323                 int fmt;
2324                 unsigned long nitems;
2325
2326                 /* Set data to the string, and catch errors. */
2327                 if (XGetWindowProperty(Metadpy->dpy, Infowin->win, XA_STRING, offset,
2328                         32767, TRUE, XA_STRING, &type, &fmt, &nitems, &left, &data)
2329                         != Success) break;
2330
2331                 /* Paste the text. */
2332                 err = type_string((char*)data, nitems);
2333
2334                 /* Free the data pasted. */
2335                 XFree(data);
2336
2337                 /* No room. */
2338                 if (err == PARSE_ERROR_OUT_OF_MEMORY)
2339                 {
2340                         /* bell("Paste failure (too much text selected)."); */
2341                         break;
2342                 }
2343                 /* Paranoia? - strange errors. */
2344                 else if (err)
2345                 {
2346                         break;
2347                 }
2348
2349                 /* Pasted everything. */
2350                 if (!left) return;
2351         }
2352
2353         /* An error has occurred, so free the last bit of data before returning. */
2354         XFree(data);
2355 }
2356
2357 /*
2358  * Handle various events conditional on presses of a mouse button.
2359  */
2360 static void handle_button(Time time, int x, int y, int button,
2361         bool press)
2362 {
2363         /* The co-ordinates are only used in Angband format. */
2364         pixel_to_square(&x, &y, x, y);
2365
2366         if (press && button == 1) copy_x11_start(x, y);
2367         if (!press && button == 1) copy_x11_end(time);
2368         if (!press && button == 2) paste_x11_request(time);
2369 }
2370
2371
2372 /*
2373  * Process events
2374  */
2375 static errr CheckEvent(bool wait)
2376 {
2377         term_data *old_td = (term_data*)(Term->data);
2378
2379         XEvent xev_body, *xev = &xev_body;
2380
2381         term_data *td = NULL;
2382         infowin *iwin = NULL;
2383
2384         int i;
2385
2386 #ifdef USE_XIM
2387  redo_checkevent:
2388 #endif
2389
2390         /* Do not wait unless requested */
2391         if (!wait && !XPending(Metadpy->dpy)) return (1);
2392
2393         /*
2394          * Hack - redraw the selection, if needed.
2395          * This doesn't actually check that one of its squares was drawn to,
2396          * only that this may have happened.
2397          */
2398         if (s_ptr->select && !s_ptr->drawn) mark_selection();
2399
2400         /* Load the Event */
2401         XNextEvent(Metadpy->dpy, xev);
2402
2403 #ifdef USE_XIM
2404 /* #define DEBUG_EVENT */
2405 #ifdef DEBUG_EVENT
2406         {
2407                 printf("event: type=%d", xev->type);
2408                 switch(xev->type){
2409                 case KeyPress:
2410                         printf("(KeyPress), keycode=%X", xev->xkey.keycode);
2411                         break;
2412                 case FocusIn:
2413                         printf("(FocusIn)");
2414                         break;
2415                 case FocusOut:
2416                         printf("(FocusOut)");
2417                         break;
2418                 case ReparentNotify:
2419                         printf("(ReparentNotify)");
2420                         break;
2421                 case ConfigureNotify:
2422                         printf("(ConfigureNotify)");
2423                         break;
2424                 case MapNotify:
2425                         printf("(MapNotify)");
2426                         break;
2427                 case Expose:
2428                         printf("(Expose)");
2429                         break;
2430                 case ClientMessage:
2431                         printf("(ClientMessage)");
2432                         break;
2433                 }
2434                         
2435         }
2436 #endif
2437         if (XFilterEvent(xev, xev->xany.window)
2438                 /*XFilterEvent(xev, (data[0].win)->win)*/){
2439 #ifdef DEBUG_EVENT
2440                 printf(", [filtered by IM]\n");
2441 #endif
2442                 goto redo_checkevent;
2443         }
2444 #ifdef DEBUG_EVENT
2445         printf("\n");
2446 #endif
2447 #endif
2448
2449         /* Notice new keymaps */
2450         if (xev->type == MappingNotify)
2451         {
2452                 XRefreshKeyboardMapping(&xev->xmapping);
2453                 return 0;
2454         }
2455
2456
2457         /* Scan the windows */
2458         for (i = 0; i < MAX_TERM_DATA; i++)
2459         {
2460                 if (!data[i].win) continue;
2461                 if (xev->xany.window == data[i].win->win)
2462                 {
2463                         td = &data[i];
2464                         iwin = td->win;
2465                         break;
2466                 }
2467         }
2468
2469         /* Unknown window */
2470         if (!td || !iwin) return (0);
2471
2472
2473         /* Hack -- activate the Term */
2474         Term_activate(&td->t);
2475
2476         /* Hack -- activate the window */
2477         Infowin_set(iwin);
2478
2479
2480         /* Switch on the Type */
2481         switch (xev->type)
2482         {
2483                 case ButtonPress:
2484                 case ButtonRelease:
2485                 {
2486                         bool press = (xev->type == ButtonPress);
2487
2488                         /* Where is the mouse */
2489                         int x = xev->xbutton.x;
2490                         int y = xev->xbutton.y;
2491
2492                         int z;
2493
2494                         /* Which button is involved */
2495                         if (xev->xbutton.button == Button1) z = 1;
2496                         else if (xev->xbutton.button == Button2) z = 2;
2497                         else if (xev->xbutton.button == Button3) z = 3;
2498                         else if (xev->xbutton.button == Button4) z = 4;
2499                         else if (xev->xbutton.button == Button5) z = 5;
2500                         else z = 0;
2501
2502                         /* XXX Handle */
2503                         handle_button(xev->xbutton.time, x, y, z, press);
2504
2505                         break;
2506                 }
2507
2508                 case EnterNotify:
2509                 case LeaveNotify:
2510                 {
2511                         /* XXX Handle */
2512
2513                         break;
2514                 }
2515
2516                 case MotionNotify:
2517                 {
2518                         /* Where is the mouse */
2519                         int x = xev->xmotion.x;
2520                         int y = xev->xmotion.y;
2521                         unsigned int z = xev->xmotion.state;
2522
2523                         /* Convert to co-ordinates Angband understands. */
2524                         pixel_to_square(&x, &y, x, y);
2525
2526                         /* Highlight the current square, if appropriate. */
2527                         /* highlight_square(window, y, x); */
2528
2529                         /* Alter the selection if appropriate. */
2530                         copy_x11_cont(x, y, z);
2531
2532                         /* XXX Handle */
2533
2534                         break;
2535                 }
2536
2537                 case SelectionNotify:
2538                 {
2539                         paste_x11_accept(&(xev->xselection));
2540                         break;
2541                 }
2542
2543                 case SelectionRequest:
2544                 {
2545                         paste_x11_send(&(xev->xselectionrequest));
2546                         break;
2547                 }
2548
2549                 case SelectionClear:
2550                 {
2551                         s_ptr->select = FALSE;
2552                         mark_selection();
2553                         break;
2554                 }
2555
2556                 case KeyRelease:
2557                 {
2558                         /* Nothing */
2559                         break;
2560                 }
2561
2562                 case KeyPress:
2563                 {
2564                         /* Hack -- use "old" term */
2565                         Term_activate(&old_td->t);
2566
2567                         /* Process the key */
2568                         react_keypress(&(xev->xkey));
2569
2570                         break;
2571                 }
2572
2573                 case Expose:
2574                 {
2575                         int x1, x2, y1, y2;
2576                         
2577                         /* Ignore "extra" exposes */
2578                         /*if (xev->xexpose.count) break;*/
2579
2580                         /* Clear the window */
2581                         /*Infowin_wipe();*/
2582                         
2583                         x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
2584                         x2 = (xev->xexpose.x + xev->xexpose.width -
2585                                  Infowin->ox)/Infofnt->wid;
2586                         
2587                         y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
2588                         y2 = (xev->xexpose.y + xev->xexpose.height -
2589                                  Infowin->oy)/Infofnt->hgt;
2590                         
2591                         Term_redraw_section(x1, y1, x2, y2);
2592
2593                         /* Redraw */
2594                         /*Term_redraw();*/
2595
2596                         break;
2597                 }
2598
2599                 case MapNotify:
2600                 {
2601                         Infowin->mapped = 1;
2602                         Term->mapped_flag = TRUE;
2603                         break;
2604                 }
2605
2606                 case UnmapNotify:
2607                 {
2608                         Infowin->mapped = 0;
2609                         Term->mapped_flag = FALSE;
2610                         break;
2611                 }
2612
2613                 /* Move and/or Resize */
2614                 case ConfigureNotify:
2615                 {
2616                         int cols, rows, wid, hgt;
2617
2618                         int ox = Infowin->ox;
2619                         int oy = Infowin->oy;
2620
2621                         /* Save the new Window Parms */
2622                         Infowin->x = xev->xconfigure.x;
2623                         Infowin->y = xev->xconfigure.y;
2624                         Infowin->w = xev->xconfigure.width;
2625                         Infowin->h = xev->xconfigure.height;
2626
2627                         /* Determine "proper" number of rows/cols */
2628                         cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
2629                         rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
2630
2631                         /* Hack -- minimal size */
2632                         if (cols < 1) cols = 1;
2633                         if (rows < 1) rows = 1;
2634
2635                         if (td == &data[0])
2636                         {
2637                                 /* Hack the main window must be at least 80x24 */
2638                                 if (cols < 80) cols = 80;
2639                                 if (rows < 24) rows = 24;
2640                         }
2641
2642                         /* Desired size of window */
2643                         wid = cols * td->fnt->wid + (ox + ox);
2644                         hgt = rows * td->fnt->hgt + (oy + oy);
2645
2646                         /* Resize the Term (if needed) */
2647                         Term_resize(cols, rows);
2648
2649                         /* Resize the windows if any "change" is needed */
2650                         if ((Infowin->w != wid) || (Infowin->h != hgt))
2651                         {
2652                                 /* Resize window */
2653                                 Infowin_set(td->win);
2654                                 Infowin_resize(wid, hgt);
2655                         }
2656
2657                         break;
2658                 }
2659 #ifdef USE_XIM
2660                 case FocusIn:
2661                 {
2662                         if(iwin->xic){
2663                                 XSetICFocus(iwin->xic);
2664                         }
2665                         Focuswin = iwin;
2666                         break;
2667                 }
2668                 case FocusOut:
2669                 {
2670                         if(iwin->xic){
2671                                 XUnsetICFocus(iwin->xic);
2672                         }
2673                         /* Focuswin = NULL;*/
2674                         break;
2675                 }
2676 #endif
2677         }
2678
2679
2680         /* Hack -- Activate the old term */
2681         Term_activate(&old_td->t);
2682
2683         /* Hack -- Activate the proper window */
2684         Infowin_set(old_td->win);
2685
2686
2687         /* Success */
2688         return (0);
2689 }
2690
2691
2692 #ifdef USE_SOUND
2693
2694 /*
2695  * An array of sound file names
2696  */
2697 static cptr sound_file[SOUND_MAX];
2698
2699 /*
2700  * Check for existance of a file
2701  */
2702 static bool check_file(cptr s)
2703 {
2704         FILE *fff;
2705
2706         fff = fopen(s, "r");
2707         if (!fff) return (FALSE);
2708         
2709         fclose(fff);
2710         return (TRUE);
2711 }
2712
2713 /*
2714  * Initialize sound
2715  */
2716 static void init_sound(void)
2717 {
2718         int i;
2719         char wav[128];
2720         char buf[1024];
2721         char dir_xtra_sound[1024];
2722                 
2723         /* Build the "sound" path */
2724         path_build(dir_xtra_sound, sizeof(dir_xtra_sound), ANGBAND_DIR_XTRA, "sound");
2725                 
2726         /* Prepare the sounds */
2727         for (i = 1; i < SOUND_MAX; i++)
2728         {
2729                 /* Extract name of sound file */
2730                 sprintf(wav, "%s.wav", angband_sound_name[i]);
2731                 
2732                 /* Access the sound */
2733                 path_build(buf, sizeof(buf), dir_xtra_sound, wav);
2734                 
2735                 /* Save the sound filename, if it exists */
2736                 if (check_file(buf)) sound_file[i] = string_make(buf);
2737         }
2738         use_sound = TRUE;
2739         return;
2740 }
2741
2742 /*
2743  * Hack -- make a sound
2744  */
2745 static errr Term_xtra_x11_sound(int v)
2746 {
2747         char buf[1024];
2748         
2749         /* Sound disabled */
2750         if (!use_sound) return (1);
2751         
2752         /* Illegal sound */
2753         if ((v < 0) || (v >= SOUND_MAX)) return (1);
2754         
2755         /* Unknown sound */
2756         if (!sound_file[v]) return (1);
2757         
2758         sprintf(buf,"./playwave.sh %s\n", sound_file[v]);
2759         system(buf);
2760         
2761         return (0);
2762         
2763 }
2764 #endif /* USE_SOUND */
2765
2766
2767 /*
2768  * Handle "activation" of a term
2769  */
2770 static errr Term_xtra_x11_level(int v)
2771 {
2772         term_data *td = (term_data*)(Term->data);
2773
2774         /* Handle "activate" */
2775         if (v)
2776         {
2777                 /* Activate the window */
2778                 Infowin_set(td->win);
2779
2780                 /* Activate the font */
2781                 Infofnt_set(td->fnt);
2782 #ifdef _JP
2783                 Infokfnt_set(td->kfnt);
2784 #endif
2785         }
2786
2787         /* Success */
2788         return (0);
2789 }
2790
2791
2792 /*
2793  * React to changes
2794  */
2795 static errr Term_xtra_x11_react(void)
2796 {
2797         int i;
2798         
2799         if (Metadpy->color)
2800         {
2801                 /* Check the colors */
2802                 for (i = 0; i < 256; i++)
2803                 {
2804                         if ((color_table[i][0] != angband_color_table[i][0]) ||
2805                             (color_table[i][1] != angband_color_table[i][1]) ||
2806                             (color_table[i][2] != angband_color_table[i][2]) ||
2807                             (color_table[i][3] != angband_color_table[i][3]))
2808                         {
2809                                 Pixell pixel;
2810
2811                                 /* Save new values */
2812                                 color_table[i][0] = angband_color_table[i][0];
2813                                 color_table[i][1] = angband_color_table[i][1];
2814                                 color_table[i][2] = angband_color_table[i][2];
2815                                 color_table[i][3] = angband_color_table[i][3];
2816
2817                                 /* Create pixel */
2818                                 pixel = create_pixel(Metadpy->dpy,
2819                                                      color_table[i][1],
2820                                                      color_table[i][2],
2821                                                      color_table[i][3]);
2822
2823                                 /* Change the foreground */
2824                                 Infoclr_set(clr[i]);
2825                                 Infoclr_change_fg(pixel);
2826                         }
2827                 }
2828         }
2829
2830         /* Success */
2831         return (0);
2832 }
2833
2834
2835 /*
2836  * Handle a "special request"
2837  */
2838 static errr Term_xtra_x11(int n, int v)
2839 {
2840         /* Handle a subset of the legal requests */
2841         switch (n)
2842         {
2843                 /* Make a noise */
2844                 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
2845
2846 #ifdef USE_SOUND
2847                 /* Make a special sound */
2848                 case TERM_XTRA_SOUND: return (Term_xtra_x11_sound(v));
2849 #endif
2850
2851                 /* Flush the output XXX XXX */
2852                 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
2853
2854                 /* Process random events XXX */
2855                 case TERM_XTRA_BORED: return (CheckEvent(0));
2856
2857                 /* Process Events XXX */
2858                 case TERM_XTRA_EVENT: return (CheckEvent(v));
2859
2860                 /* Flush the events XXX */
2861                 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
2862
2863                 /* Handle change in the "level" */
2864                 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
2865
2866                 /* Clear the screen */
2867                 case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
2868
2869                 /* Delay for some milliseconds */
2870                 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
2871
2872                 /* React to changes */
2873                 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
2874         }
2875
2876         /* Unknown */
2877         return (1);
2878 }
2879
2880
2881 /*
2882  * Draw the cursor as an inverted rectangle.
2883  *
2884  * Consider a rectangular outline like "main-mac.c".  XXX XXX
2885  */
2886 static errr Term_curs_x11(int x, int y)
2887 {
2888         if (use_graphics)
2889         {
2890                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2891                                x * Infofnt->wid + Infowin->ox,
2892                                y * Infofnt->hgt + Infowin->oy,
2893                                Infofnt->wid - 1, Infofnt->hgt - 1);
2894                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2895                                x * Infofnt->wid + Infowin->ox + 1,
2896                                y * Infofnt->hgt + Infowin->oy + 1,
2897                                Infofnt->wid - 3, Infofnt->hgt - 3);
2898         }
2899         else
2900         {
2901                 /* Draw the cursor */
2902                 Infoclr_set(xor);
2903
2904                 /* Hilite the cursor character */
2905                 Infofnt_text_non(x, y, " ", 1);
2906         }
2907
2908         /* Success */
2909         return (0);
2910 }
2911
2912
2913 /*
2914  * Draw the double width cursor
2915  */
2916 static errr Term_bigcurs_x11(int x, int y)
2917 {
2918         if (use_graphics)
2919         {
2920                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2921                                x * Infofnt->wid + Infowin->ox,
2922                                y * Infofnt->hgt + Infowin->oy,
2923                                Infofnt->twid - 1, Infofnt->hgt - 1);
2924                 XDrawRectangle(Metadpy->dpy, Infowin->win, xor->gc,
2925                                x * Infofnt->wid + Infowin->ox + 1,
2926                                y * Infofnt->hgt + Infowin->oy + 1,
2927                                Infofnt->twid - 3, Infofnt->hgt - 3);
2928         }
2929         else
2930         {
2931                 /* Draw the cursor */
2932                 Infoclr_set(xor);
2933
2934                 /* Hilite the cursor character */
2935                 Infofnt_text_non(x, y, "  ", 2);
2936         }
2937         /* Success */
2938         return (0);
2939 }
2940
2941
2942 /*
2943  * Erase some characters.
2944  */
2945 static errr Term_wipe_x11(int x, int y, int n)
2946 {
2947         /* Erase (use black) */
2948         Infoclr_set(clr[TERM_DARK]);
2949
2950         /* Mega-Hack -- Erase some space */
2951         Infofnt_text_non(x, y, "", n);
2952
2953         /* Redraw the selection if any, as it may have been obscured. (later) */
2954         s_ptr->drawn = FALSE;
2955
2956         /* Success */
2957         return (0);
2958 }
2959
2960
2961 /*
2962  * Draw some textual characters.
2963  */
2964 static errr Term_text_x11(int x, int y, int n, byte a, cptr s)
2965 {
2966         /* Draw the text */
2967         Infoclr_set(clr[a]);
2968
2969         /* Draw the text */
2970         Infofnt_text_std(x, y, s, n);
2971
2972         /* Redraw the selection if any, as it may have been obscured. (later) */
2973         s_ptr->drawn = FALSE;
2974
2975         /* Success */
2976         return (0);
2977 }
2978
2979
2980 #ifdef USE_GRAPHICS
2981
2982 /*
2983  * Draw some graphical characters.
2984  */
2985 # ifdef USE_TRANSPARENCY
2986 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
2987 # else /* USE_TRANSPARENCY */
2988 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
2989 # endif /* USE_TRANSPARENCY */
2990 {
2991         int i, x1, y1;
2992
2993         byte a;
2994         char c;
2995
2996 #ifdef USE_TRANSPARENCY
2997         byte ta;
2998         char tc;
2999
3000         int x2, y2;
3001         int k,l;
3002
3003         unsigned long pixel, blank;
3004 #endif /* USE_TRANSPARENCY */
3005
3006         term_data *td = (term_data*)(Term->data);
3007
3008         y *= Infofnt->hgt;
3009         x *= Infofnt->wid;
3010
3011         /* Add in affect of window boundaries */
3012         y += Infowin->oy;
3013         x += Infowin->ox;
3014
3015         for (i = 0; i < n; ++i, x += td->fnt->wid)
3016         {
3017                 a = *ap++;
3018                 c = *cp++;
3019
3020                 /* For extra speed - cache these values */
3021                 x1 = (c&0x7F) * td->fnt->twid;
3022                 y1 = (a&0x7F) * td->fnt->hgt;
3023
3024                 /* Illegal tile index */
3025                 if (td->tiles->width < x1 + td->fnt->wid ||
3026                     td->tiles->height < y1 + td->fnt->hgt)
3027                 {
3028                         /* Draw black square */
3029                         XFillRectangle(Metadpy->dpy, td->win->win, clr[0]->gc,
3030                                        x, y, 
3031                                        td->fnt->twid, td->fnt->hgt);
3032
3033                         /* Skip drawing tile */
3034                         continue;
3035                 }
3036
3037 #ifdef USE_TRANSPARENCY
3038
3039                 ta = *tap++;
3040                 tc = *tcp++;
3041
3042                 /* For extra speed - cache these values */
3043                 x2 = (tc&0x7F) * td->fnt->twid;
3044                 y2 = (ta&0x7F) * td->fnt->hgt;
3045                 
3046                 /* Optimise the common case */
3047                 if (((x1 == x2) && (y1 == y2)) ||
3048                     !(((byte)ta & 0x80) && ((byte)tc & 0x80)) ||
3049                     td->tiles->width < x2 + td->fnt->wid ||
3050                     td->tiles->height < y2 + td->fnt->hgt)
3051                 {
3052                         /* Draw object / terrain */
3053                         XPutImage(Metadpy->dpy, td->win->win,
3054                                 clr[0]->gc,
3055                                 td->tiles,
3056                                 x1, y1,
3057                                 x, y,
3058                                 td->fnt->twid, td->fnt->hgt);   
3059                 }
3060                 else
3061                 {
3062
3063                         /* Mega Hack^2 - assume the top left corner is "black" */
3064                         blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
3065
3066                         for (k = 0; k < td->fnt->twid; k++)
3067                         {
3068                                 for (l = 0; l < td->fnt->hgt; l++)
3069                                 {
3070                                         /* If mask set... */
3071                                         if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
3072                                         {
3073                                                 /* Output from the terrain */
3074                                                 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
3075                                         }
3076                                         
3077                                         /* Store into the temp storage. */
3078                                         XPutPixel(td->TmpImage, k, l, pixel);
3079                                 }
3080                         }
3081
3082
3083                         /* Draw to screen */
3084
3085                         XPutImage(Metadpy->dpy, td->win->win,
3086                               clr[0]->gc,
3087                              td->TmpImage,
3088                              0, 0, x, y,
3089                              td->fnt->twid, td->fnt->hgt);
3090                 }
3091
3092 #else /* USE_TRANSPARENCY */
3093
3094                 /* Draw object / terrain */
3095                 XPutImage(Metadpy->dpy, td->win->win,
3096                           clr[0]->gc,
3097                           td->tiles,
3098                           x1, y1,
3099                           x, y,
3100                           td->fnt->twid, td->fnt->hgt);
3101
3102 #endif /* USE_TRANSPARENCY */
3103         }
3104
3105         /* Redraw the selection if any, as it may have been obscured. (later) */
3106         s_ptr->drawn = FALSE;
3107
3108         /* Success */
3109         return (0);
3110 }
3111
3112 #endif /* USE_GRAPHICS */
3113
3114 #ifdef USE_XIM
3115 static void IMDestroyCallback(XIM, XPointer, XPointer);
3116
3117 static void
3118 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
3119 {
3120         XIM xim;
3121         XIMCallback ximcallback;
3122         XIMStyles *xim_styles = NULL;
3123         int i;
3124
3125         /* Unused */
3126         (void)unused1;
3127         (void)unused2;
3128
3129         xim = XOpenIM(display, NULL, NULL, NULL);
3130         if(!xim){
3131                 printf("can't open IM\n");
3132                 return;
3133         }
3134
3135         /* initialize destroy callback */
3136         ximcallback.callback = IMDestroyCallback;
3137         ximcallback.client_data = NULL;
3138         XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
3139
3140         /* set style (only "Root" is supported yet...) */
3141         XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
3142         for (i = 0; i < xim_styles->count_styles; i++){
3143                 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
3144         }
3145         if(i >= xim_styles->count_styles){
3146                 printf("Sorry, your IM does not support 'Root' preedit style...\n");
3147                 XCloseIM(xim);
3148                 return;
3149         }
3150         XFree(xim_styles);
3151
3152         Metadpy->xim = xim;
3153
3154         for (i = 0; i < MAX_TERM_DATA; i++)
3155         {
3156                 infowin *iwin = data[i].win;
3157                 if (!iwin) continue;
3158                 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
3159                 if(!iwin->xic){
3160                         printf("Can't create input context for Term%d\n", i);
3161                         continue;
3162                 }
3163                 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL){
3164 /*                      printf("Can't get XNFilterEvents\n"); */
3165                         iwin->xic_mask = 0L;
3166                 }
3167                 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
3168         }
3169
3170         return;
3171 }
3172
3173 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
3174 {
3175         int i;
3176
3177         /* Unused */
3178         (void)xim;
3179         (void)client_data;
3180
3181         if (call_data == NULL){
3182                 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3183         }
3184
3185         for(i = 0; i < MAX_TERM_DATA; i++)
3186         {
3187                 infowin *iwin = data[i].win;
3188                 if(!iwin) continue;
3189                 if(iwin->xic_mask){
3190                         XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
3191                         iwin->xic_mask = 0L;
3192                 }
3193                 iwin->xic = NULL;
3194         }
3195
3196         Metadpy->xim = NULL;
3197 }
3198 #endif
3199
3200 /*
3201  * Initialize a term_data
3202  */
3203 static errr term_data_init(term_data *td, int i)
3204 {
3205         term *t = &td->t;
3206
3207         cptr name = angband_term_name[i];
3208
3209         cptr font;
3210 #ifdef _JP
3211         cptr kfont;
3212 #endif
3213
3214
3215         int x = 0;
3216         int y = 0;
3217
3218         int cols = 80;
3219         int rows = 24;
3220
3221         int ox = 1;
3222         int oy = 1;
3223
3224         int wid, hgt, num;
3225
3226         char buf[80];
3227
3228         cptr str;
3229
3230         int val;
3231
3232         XClassHint *ch;
3233
3234         char res_name[20];
3235         char res_class[20];
3236
3237         XSizeHints *sh;
3238 #ifdef USE_XIM
3239         XWMHints *wh;
3240 #endif
3241
3242         /* Window specific font name */
3243         sprintf(buf, "ANGBAND_X11_FONT_%d", i);
3244
3245         /* Check environment for that font */
3246         font = getenv(buf);
3247
3248         /* Check environment for "base" font */
3249         if (!font) font = getenv("ANGBAND_X11_FONT");
3250
3251         /* No environment variables, use default font */
3252         if (!font)
3253         {
3254                 switch (i)
3255                 {
3256                         case 0:
3257                         {
3258                                 font = DEFAULT_X11_FONT_0;
3259                         }
3260                         break;
3261                         case 1:
3262                         {
3263                                 font = DEFAULT_X11_FONT_1;
3264                         }
3265                         break;
3266                         case 2:
3267                         {
3268                                 font = DEFAULT_X11_FONT_2;
3269                         }
3270                         break;
3271                         case 3:
3272                         {
3273                                 font = DEFAULT_X11_FONT_3;
3274                         }
3275                         break;
3276                         case 4:
3277                         {
3278                                 font = DEFAULT_X11_FONT_4;
3279                         }
3280                         break;
3281                         case 5:
3282                         {
3283                                 font = DEFAULT_X11_FONT_5;
3284                         }
3285                         break;
3286                         case 6:
3287                         {
3288                                 font = DEFAULT_X11_FONT_6;
3289                         }
3290                         break;
3291                         case 7:
3292                         {
3293                                 font = DEFAULT_X11_FONT_7;
3294                         }
3295                         break;
3296                         default:
3297                         {
3298                                 font = DEFAULT_X11_FONT;
3299                         }
3300                 }
3301         }
3302
3303 #ifdef _JP
3304         /* Window specific font name */
3305         sprintf(buf, "ANGBAND_X11_KFONT_%d", i);
3306
3307         /* Check environment for that font */
3308         kfont = getenv(buf);
3309
3310         /* Check environment for "base" font */
3311         if (!kfont) kfont = getenv("ANGBAND_X11_KFONT");
3312
3313         /* No environment variables, use default font */
3314         if (!kfont)
3315         {
3316                 switch (i)
3317                 {
3318                         case 0:
3319                         {
3320                                 kfont = DEFAULT_X11_KFONT_0;
3321                         }
3322                         break;
3323                         case 1:
3324                         {
3325                                 kfont = DEFAULT_X11_KFONT_1;
3326                         }
3327                         break;
3328                         case 2:
3329                         {
3330                                 kfont = DEFAULT_X11_KFONT_2;
3331                         }
3332                         break;
3333                         case 3:
3334                         {
3335                                 kfont = DEFAULT_X11_KFONT_3;
3336                         }
3337                         break;
3338                         case 4:
3339                         {
3340                                 kfont = DEFAULT_X11_KFONT_4;
3341                         }
3342                         break;
3343                         case 5:
3344                         {
3345                                 kfont = DEFAULT_X11_KFONT_5;
3346                         }
3347                         break;
3348                         case 6:
3349                         {
3350                                 kfont = DEFAULT_X11_KFONT_6;
3351                         }
3352                         break;
3353                         case 7:
3354                         {
3355                                 kfont = DEFAULT_X11_KFONT_7;
3356                         }
3357                         break;
3358                         default:
3359                         {
3360                                 kfont = DEFAULT_X11_KFONT;
3361                         }
3362                 }
3363         }
3364 #endif
3365         /* Window specific location (x) */
3366         sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
3367         str = getenv(buf);
3368         x = (str != NULL) ? atoi(str) : -1;
3369
3370         /* Window specific location (y) */
3371         sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
3372         str = getenv(buf);
3373         y = (str != NULL) ? atoi(str) : -1;
3374
3375
3376         /* Window specific cols */
3377         sprintf(buf, "ANGBAND_X11_COLS_%d", i);
3378         str = getenv(buf);
3379         val = (str != NULL) ? atoi(str) : -1;
3380         if (val > 0) cols = val;
3381
3382         /* Window specific rows */
3383         sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
3384         str = getenv(buf);
3385         val = (str != NULL) ? atoi(str) : -1;
3386         if (val > 0) rows = val;
3387
3388         /* Hack the main window must be at least 80x24 */
3389         if (!i)
3390         {
3391                 if (cols < 80) cols = 80;
3392                 if (rows < 24) rows = 24;
3393         }
3394
3395         /* Window specific inner border offset (ox) */
3396         sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
3397         str = getenv(buf);
3398         val = (str != NULL) ? atoi(str) : -1;
3399         if (val > 0) ox = val;
3400
3401         /* Window specific inner border offset (oy) */
3402         sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
3403         str = getenv(buf);
3404         val = (str != NULL) ? atoi(str) : -1;
3405         if (val > 0) oy = val;
3406
3407
3408         /* Prepare the standard font */
3409 #ifdef _JP
3410         MAKE(td->fnt, infofnt);
3411         Infofnt_set(td->fnt);
3412         MAKE(td->kfnt, infofnt);
3413         Infokfnt_set(td->kfnt);
3414         Infofnt_init_data(font, kfont);
3415 #else
3416         MAKE(td->fnt, infofnt);
3417         Infofnt_set(td->fnt);
3418         Infofnt_init_data(font);
3419 #endif
3420
3421
3422         /* Hack -- key buffer size */
3423         num = ((i == 0) ? 1024 : 16);
3424
3425         /* Assume full size windows */
3426         wid = cols * td->fnt->wid + (ox + ox);
3427         hgt = rows * td->fnt->hgt + (oy + oy);
3428
3429         /* Create a top-window */
3430         MAKE(td->win, infowin);
3431         Infowin_set(td->win);
3432         Infowin_init_top(x, y, wid, hgt, 0,
3433                          Metadpy->fg, Metadpy->bg);
3434
3435         /* Ask for certain events */
3436 #if defined(USE_XIM)
3437         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask);
3438 #else
3439         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
3440 #endif
3441
3442         /* Set the window name */
3443         Infowin_set_name(name);
3444
3445         /* Save the inner border */
3446         Infowin->ox = ox;
3447         Infowin->oy = oy;
3448
3449         /* Make Class Hints */
3450         ch = XAllocClassHint();
3451
3452         if (ch == NULL) quit("XAllocClassHint failed");
3453
3454         strcpy(res_name, name);
3455         res_name[0] = FORCELOWER(res_name[0]);
3456         ch->res_name = res_name;
3457
3458         strcpy(res_class, "Angband");
3459         ch->res_class = res_class;
3460
3461         XSetClassHint(Metadpy->dpy, Infowin->win, ch);
3462
3463         /* Make Size Hints */
3464         sh = XAllocSizeHints();
3465
3466         /* Oops */
3467         if (sh == NULL) quit("XAllocSizeHints failed");
3468
3469         /* Main window has a differing minimum size */
3470         if (i == 0)
3471         {
3472                 /* Main window min size is 80x24 */
3473                 sh->flags = PMinSize | PMaxSize;
3474                 sh->min_width = 80 * td->fnt->wid + (ox + ox);
3475                 sh->min_height = 24 * td->fnt->hgt + (oy + oy);
3476                 sh->max_width = 255 * td->fnt->wid + (ox + ox);
3477                 sh->max_height = 255 * td->fnt->hgt + (oy + oy);
3478         }
3479
3480         /* Other windows can be shrunk to 1x1 */
3481         else
3482         {
3483                 /* Other windows */
3484                 sh->flags = PMinSize | PMaxSize;
3485                 sh->min_width = td->fnt->wid + (ox + ox);
3486                 sh->min_height = td->fnt->hgt + (oy + oy);
3487                 sh->max_width = 256 * td->fnt->wid + (ox + ox);
3488                 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
3489         }
3490
3491         /* Resize increment */
3492         sh->flags |= PResizeInc;
3493         sh->width_inc = td->fnt->wid;
3494         sh->height_inc = td->fnt->hgt;
3495
3496         /* Base window size */
3497         sh->flags |= PBaseSize;
3498         sh->base_width = (ox + ox);
3499         sh->base_height = (oy + oy);
3500
3501         /* Use the size hints */
3502         XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
3503
3504         /* Map the window */
3505         Infowin_map();
3506
3507 #ifdef USE_XIM
3508         /* Make WM Hints */
3509         wh = XAllocWMHints();
3510         if(wh == NULL) quit("XAllocWMHints failed");
3511         wh->flags = InputHint;
3512         wh->input = True;
3513         XSetWMHints(Metadpy->dpy, Infowin->win, wh);
3514 #endif
3515
3516         /* Move the window to requested location */
3517         if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
3518
3519
3520         /* Initialize the term */
3521         term_init(t, cols, rows, num);
3522
3523         /* Use a "soft" cursor */
3524         t->soft_cursor = TRUE;
3525
3526         /* Erase with "white space" */
3527         t->attr_blank = TERM_WHITE;
3528         t->char_blank = ' ';
3529
3530         /* Hooks */
3531         t->xtra_hook = Term_xtra_x11;
3532         t->curs_hook = Term_curs_x11;
3533         t->bigcurs_hook = Term_bigcurs_x11;
3534         t->wipe_hook = Term_wipe_x11;
3535         t->text_hook = Term_text_x11;
3536
3537         /* Save the data */
3538         t->data = td;
3539
3540         /* Activate (important) */
3541         Term_activate(t);
3542
3543         /* Success */
3544         return (0);
3545 }
3546
3547
3548 /*
3549  * Initialization function for an "X11" module to Angband
3550  */
3551 errr init_x11(int argc, char *argv[])
3552 {
3553         int i;
3554
3555         cptr dpy_name = "";
3556
3557         int num_term = 3;
3558
3559 #ifdef USE_GRAPHICS
3560
3561         char filename[1024];
3562
3563         int pict_wid = 0;
3564         int pict_hgt = 0;
3565
3566 #ifdef USE_TRANSPARENCY
3567
3568         char *TmpData;
3569 #endif /* USE_TRANSPARENCY */
3570
3571 #endif /* USE_GRAPHICS */
3572
3573
3574         /* Parse args */
3575         for (i = 1; i < argc; i++)
3576         {
3577                 if (prefix(argv[i], "-d"))
3578                 {
3579                         dpy_name = &argv[i][2];
3580                         continue;
3581                 }
3582                 
3583 #ifdef USE_GRAPHICS
3584                 if (prefix(argv[i], "-s"))
3585                 {
3586                         smoothRescaling = FALSE;
3587                         continue;
3588                 }
3589
3590                 if (prefix(argv[i], "-a"))
3591                 {
3592                         arg_graphics = GRAPHICS_ADAM_BOLT;
3593                         continue;
3594                 }
3595
3596                 if (prefix(argv[i], "-o"))
3597                 {
3598                         arg_graphics = GRAPHICS_ORIGINAL;
3599                         continue;
3600                 }
3601
3602                 if (prefix(argv[i], "-b"))
3603                 {
3604                         arg_bigtile = use_bigtile = TRUE;
3605                         continue;
3606                 }
3607 #endif /* USE_GRAPHICS */
3608
3609                 if (prefix(argv[i], "-n"))
3610                 {
3611                         num_term = atoi(&argv[i][2]);
3612                         if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
3613                         else if (num_term < 1) num_term = 1;
3614                         continue;
3615                 }
3616
3617                 if (prefix(argv[i], "--"))
3618                 {
3619                         /* Ignore */
3620                         continue;
3621                 }
3622
3623                 plog_fmt("Ignoring option: %s", argv[i]);
3624         }
3625
3626 #ifdef USE_LOCALE
3627         setlocale(LC_ALL, "");
3628 #ifdef DEFAULT_LOCALE
3629         if(!strcmp(setlocale(LC_ALL, NULL), "C")){
3630                 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
3631                 setlocale(LC_ALL, DEFAULT_LOCALE);
3632         }
3633 #endif
3634         {
3635                 char *current_locale = setlocale(LC_ALL, NULL);
3636 /*              printf("set locale to \"%s\"\n", current_locale); */
3637                 if(!strcmp(current_locale, "C")){
3638                         printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
3639                 }
3640         }
3641
3642         if(!XSupportsLocale()){
3643                 printf("can't support locale in X\n");
3644                 setlocale(LC_ALL, "C");
3645         }
3646 #endif /* USE_LOCALE */
3647
3648
3649         /* Init the Metadpy if possible */
3650         if (Metadpy_init_name(dpy_name)) return (-1);
3651
3652
3653         /* Prepare cursor color */
3654         MAKE(xor, infoclr);
3655         Infoclr_set(xor);
3656         Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
3657
3658
3659         /* Prepare normal colors */
3660         for (i = 0; i < 256; ++i)
3661         {
3662                 Pixell pixel;
3663
3664                 MAKE(clr[i], infoclr);
3665
3666                 Infoclr_set(clr[i]);
3667
3668                 /* Acquire Angband colors */
3669                 color_table[i][0] = angband_color_table[i][0];
3670                 color_table[i][1] = angband_color_table[i][1];
3671                 color_table[i][2] = angband_color_table[i][2];
3672                 color_table[i][3] = angband_color_table[i][3];
3673
3674                 /* Default to monochrome */
3675                 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
3676
3677                 /* Handle color */
3678                 if (Metadpy->color)
3679                 {
3680                         /* Create pixel */
3681                         pixel = create_pixel(Metadpy->dpy,
3682                                              color_table[i][1],
3683                                              color_table[i][2],
3684                                              color_table[i][3]);
3685                 }
3686
3687                 /* Initialize the color */
3688                 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
3689         }
3690
3691
3692         /* Prepare required atoms. */
3693         set_atoms();
3694
3695
3696         /* Initialize the windows */
3697         for (i = 0; i < num_term; i++)
3698         {
3699                 term_data *td = &data[i];
3700
3701                 /* Initialize the term_data */
3702                 term_data_init(td, i);
3703
3704                 /* Save global entry */
3705                 angband_term[i] = Term;
3706         }
3707
3708         /* Raise the "Angband" window */
3709         Infowin_set(data[0].win);
3710         Infowin_raise();
3711
3712         /* Activate the "Angband" window screen */
3713         Term_activate(&data[0].t);
3714
3715 #ifdef USE_XIM
3716         {
3717                 char *p;
3718                 p = XSetLocaleModifiers("");
3719                 if(!p || !*p){
3720                         p = XSetLocaleModifiers("@im=");
3721                 }
3722 /*              printf("XMODIFIERS=\"%s\"\n", p); */
3723         }
3724         XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3725 #endif
3726
3727 #ifdef USE_SOUND
3728         /* initialize sound */
3729         if (arg_sound) init_sound();
3730 #endif
3731
3732 #ifdef USE_GRAPHICS
3733
3734         /* Try graphics */
3735         switch (arg_graphics)
3736         {
3737         case GRAPHICS_ORIGINAL:
3738                 /* Try the "8x8.bmp" file */
3739                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/8x8.bmp");
3740
3741                 /* Use the "8x8.bmp" file if it exists */
3742                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3743                 {
3744                         /* Use graphics */
3745                         use_graphics = TRUE;
3746
3747                         pict_wid = pict_hgt = 8;
3748
3749                         ANGBAND_GRAF = "old";
3750                         break;
3751                 }
3752                 /* Fall through */
3753
3754         case GRAPHICS_ADAM_BOLT:
3755                 /* Try the "16x16.bmp" file */
3756                 path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, "graf/16x16.bmp");
3757
3758                 /* Use the "16x16.bmp" file if it exists */
3759                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3760                 {
3761                         /* Use graphics */
3762                         use_graphics = TRUE;
3763
3764                         pict_wid = pict_hgt = 16;
3765
3766                         ANGBAND_GRAF = "new";
3767
3768                         break;
3769                 }
3770         }
3771
3772         /* Load graphics */
3773         if (use_graphics)
3774         {
3775                 Display *dpy = Metadpy->dpy;
3776
3777                 XImage *tiles_raw;
3778
3779                 /* Load the graphical tiles */
3780                 tiles_raw = ReadBMP(dpy, filename);
3781
3782                 /* Initialize the windows */
3783                 for (i = 0; i < num_term; i++)
3784                 {
3785                         term_data *td = &data[i];
3786
3787                         term *t = &td->t;
3788
3789                         /* Graphics hook */
3790                         t->pict_hook = Term_pict_x11;
3791
3792                         /* Use graphics sometimes */
3793                         t->higher_pict = TRUE;
3794
3795                         /* Resize tiles */
3796                         td->tiles =
3797                         ResizeImage(dpy, tiles_raw,
3798                                     pict_wid, pict_hgt,
3799                                     td->fnt->twid, td->fnt->hgt);
3800                 }
3801
3802 #ifdef USE_TRANSPARENCY
3803                 /* Initialize the transparency masks */
3804                 for (i = 0; i < num_term; i++)
3805                 {
3806                         term_data *td = &data[i];
3807                         int ii, jj;
3808                         int depth = DefaultDepth(dpy, DefaultScreen(dpy));
3809                         Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
3810                         int total;
3811
3812
3813                         /* Determine total bytes needed for image */
3814                         ii = 1;
3815                         jj = (depth - 1) >> 2;
3816                         while (jj >>= 1) ii <<= 1;
3817                         total = td->fnt->twid * td->fnt->hgt * ii;
3818                         
3819                         
3820                         TmpData = (char *)malloc(total);
3821
3822                         td->TmpImage = XCreateImage(dpy,visual,depth,
3823                                 ZPixmap, 0, TmpData,
3824                                 td->fnt->twid, td->fnt->hgt, 8, 0);
3825
3826                 }
3827 #endif /* USE_TRANSPARENCY */
3828
3829
3830                 /* Free tiles_raw? XXX XXX */
3831         }
3832
3833 #endif /* USE_GRAPHICS */
3834
3835
3836         /* Success */
3837         return (0);
3838 }
3839
3840 #endif /* USE_X11 */
3841