OSDN Git Service

hengband 1.0.8 fix2
[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 #endif /* __MAKEDEPEND__ */
127
128
129 /*
130  * Include some helpful X11 code.
131  */
132 #include "maid-x11.c"
133
134
135 /*
136  * Hack -- avoid some compiler warnings
137  */
138 #define IGNORE_UNUSED_FUNCTIONS
139
140
141 /*
142  * Notes on Colors:
143  *
144  *   1) On a monochrome (or "fake-monochrome") display, all colors
145  *   will be "cast" to "fg," except for the bg color, which is,
146  *   obviously, cast to "bg".  Thus, one can ignore this setting.
147  *
148  *   2) Because of the inner functioning of the color allocation
149  *   routines, colors may be specified as (a) a typical color name,
150  *   (b) a hexidecimal color specification (preceded by a pound sign),
151  *   or (c) by strings such as "fg", "bg", "zg".
152  *
153  *   3) Due to the workings of the init routines, many colors
154  *   may also be dealt with by their actual pixel values.  Note that
155  *   the pixel with all bits set is "zg = (1<<metadpy->depth)-1", which
156  *   is not necessarily either black or white.
157  */
158
159
160
161 /**** Generic Types ****/
162
163
164 /*
165  * An X11 pixell specifier
166  */
167 typedef unsigned long Pixell;
168
169 /*
170  * The structures defined below
171  */
172 typedef struct metadpy metadpy;
173 typedef struct infowin infowin;
174 typedef struct infoclr infoclr;
175 typedef struct infofnt infofnt;
176
177
178 /*
179  * A structure summarizing a given Display.
180  *
181  *      - The Display itself
182  *      - The default Screen for the display
183  *      - The virtual root (usually just the root)
184  *      - The default colormap (from a macro)
185  *
186  *      - The "name" of the display
187  *
188  *      - The socket to listen to for events
189  *
190  *      - The width of the display screen (from a macro)
191  *      - The height of the display screen (from a macro)
192  *      - The bit depth of the display screen (from a macro)
193  *
194  *      - The black Pixell (from a macro)
195  *      - The white Pixell (from a macro)
196  *
197  *      - The background Pixell (default: black)
198  *      - The foreground Pixell (default: white)
199  *      - The maximal Pixell (Equals: ((2 ^ depth)-1), is usually ugly)
200  *
201  *      - Bit Flag: Force all colors to black and white (default: !color)
202  *      - Bit Flag: Allow the use of color (default: depth > 1)
203  *      - Bit Flag: We created 'dpy', and so should nuke it when done.
204  */
205 struct metadpy
206 {
207         Display *dpy;
208         Screen *screen;
209         Window root;
210         Colormap cmap;
211 #ifdef USE_XIM
212         XIM xim;
213 #endif
214
215         char *name;
216
217         int fd;
218
219         uint width;
220         uint height;
221         uint depth;
222
223         Pixell black;
224         Pixell white;
225
226         Pixell bg;
227         Pixell fg;
228         Pixell zg;
229
230         uint mono:1;
231         uint color:1;
232         uint nuke:1;
233 };
234
235
236
237 /*
238  * A Structure summarizing Window Information.
239  *
240  * I assume that a window is at most 30000 pixels on a side.
241  * I assume that the root windw is also at most 30000 square.
242  *
243  *      - The Window
244  *      - The current Input Event Mask
245  *
246  *      - The location of the window
247  *      - The width, height of the window
248  *      - The border width of this window
249  *
250  *      - Byte: 1st Extra byte
251  *
252  *      - Bit Flag: This window is currently Mapped
253  *      - Bit Flag: This window needs to be redrawn
254  *      - Bit Flag: This window has been resized
255  *
256  *      - Bit Flag: We should nuke 'win' when done with it
257  *
258  *      - Bit Flag: 1st extra flag
259  *      - Bit Flag: 2nd extra flag
260  *      - Bit Flag: 3rd extra flag
261  *      - Bit Flag: 4th extra flag
262  */
263 struct infowin
264 {
265         Window win;
266 #ifdef USE_XIM
267         XIC xic;
268         long xic_mask;
269 #endif
270
271         long mask;
272
273         s16b ox, oy;
274
275         s16b x, y;
276         s16b w, h;
277         u16b b;
278
279         byte byte1;
280
281         uint mapped:1;
282         uint redraw:1;
283         uint resize:1;
284
285         uint nuke:1;
286
287         uint flag1:1;
288         uint flag2:1;
289         uint flag3:1;
290         uint flag4:1;
291 };
292
293
294
295
296
297
298 /*
299  * A Structure summarizing Operation+Color Information
300  *
301  *      - The actual GC corresponding to this info
302  *
303  *      - The Foreground Pixell Value
304  *      - The Background Pixell Value
305  *
306  *      - Num (0-15): The operation code (As in Clear, Xor, etc)
307  *      - Bit Flag: The GC is in stipple mode
308  *      - Bit Flag: Destroy 'gc' at Nuke time.
309  */
310 struct infoclr
311 {
312         GC gc;
313
314         Pixell fg;
315         Pixell bg;
316
317         uint code:4;
318         uint stip:1;
319         uint nuke:1;
320 };
321
322
323
324 /*
325  * A Structure to Hold Font Information
326  *
327  *      - The 'XFontStruct*' (yields the 'Font')
328  *
329  *      - The font name
330  *
331  *      - The default character width
332  *      - The default character height
333  *      - The default character ascent
334  *
335  *      - Byte: Pixel offset used during fake mono
336  *
337  *      - Flag: Force monospacing via 'wid'
338  *      - Flag: Nuke info when done
339  */
340 struct infofnt
341 {
342 #ifdef USE_FONTSET
343         XFontSet info;
344 #else
345         XFontStruct *info;
346 #endif
347
348         cptr name;
349
350         s16b wid;
351         s16b hgt;
352         s16b asc;
353
354         byte off;
355
356         uint mono:1;
357         uint nuke:1;
358 };
359
360
361
362
363 /**** Generic Macros ****/
364
365
366
367 /* Set current metadpy (Metadpy) to 'M' */
368 #define Metadpy_set(M) \
369         Metadpy = M
370
371
372 /* Initialize 'M' using Display 'D' */
373 #define Metadpy_init_dpy(D) \
374         Metadpy_init_2(D,cNULL)
375
376 /* Initialize 'M' using a Display named 'N' */
377 #define Metadpy_init_name(N) \
378         Metadpy_init_2((Display*)(NULL),N)
379
380 /* Initialize 'M' using the standard Display */
381 #define Metadpy_init() \
382         Metadpy_init_name("")
383
384
385 /* Init an infowin by giving father as an (info_win*) (or NULL), and data */
386 #define Infowin_init_dad(D,X,Y,W,H,B,FG,BG) \
387         Infowin_init_data(((D) ? ((D)->win) : (Window)(None)), \
388                           X,Y,W,H,B,FG,BG)
389
390
391 /* Init a top level infowin by pos,size,bord,Colors */
392 #define Infowin_init_top(X,Y,W,H,B,FG,BG) \
393         Infowin_init_data(None,X,Y,W,H,B,FG,BG)
394
395
396 /* Request a new standard window by giving Dad infowin and X,Y,W,H */
397 #define Infowin_init_std(D,X,Y,W,H,B) \
398         Infowin_init_dad(D,X,Y,W,H,B,Metadpy->fg,Metadpy->bg)
399
400
401 /* Set the current Infowin */
402 #define Infowin_set(I) \
403         (Infowin = (I))
404
405
406 /* Set the current Infoclr */
407 #define Infoclr_set(C) \
408         (Infoclr = (C))
409
410
411 #define Infoclr_init_ppo(F,B,O,M) \
412         Infoclr_init_data(F,B,O,M)
413
414 #define Infoclr_init_cco(F,B,O,M) \
415         Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M)
416
417 #define Infoclr_init_ppn(F,B,O,M) \
418         Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M)
419
420 #define Infoclr_init_ccn(F,B,O,M) \
421         Infoclr_init_cco(F,B,Infoclr_Opcode(O),M)
422
423
424 /* Set the current infofnt */
425 #define Infofnt_set(I) \
426         (Infofnt = (I))
427
428
429 /* Errr: Expose Infowin */
430 #define Infowin_expose() \
431         (!(Infowin->redraw = 1))
432
433 /* Errr: Unxpose Infowin */
434 #define Infowin_unexpose() \
435         (Infowin->redraw = 0)
436
437
438
439 /**** Generic Globals ****/
440
441
442 /*
443  * The "default" values
444  */
445 static metadpy metadpy_default;
446
447
448 /*
449  * The "current" variables
450  */
451 static metadpy *Metadpy = &metadpy_default;
452 static infowin *Infowin = (infowin*)(NULL);
453 #ifdef USE_XIM
454 static infowin *Focuswin = (infowin*)(NULL);
455 #endif
456 static infoclr *Infoclr = (infoclr*)(NULL);
457 #ifdef _JP
458 static infofnt *Infofnt = (infofnt*)(NULL);
459 static infofnt *Infokfnt = (infofnt*)(NULL);
460 #else
461 static infofnt *Infofnt = (infofnt*)(NULL);
462 #endif
463
464
465
466
467 /**** Generic code ****/
468
469
470 #ifdef _JP
471 #define Infokfnt_set(I) \
472         (Infokfnt = (I))
473 #endif
474 /*
475  * Init the current metadpy, with various initialization stuff.
476  *
477  * Inputs:
478  *      dpy:  The Display* to use (if NULL, create it)
479  *      name: The name of the Display (if NULL, the current)
480  *
481  * Notes:
482  *      If 'name' is NULL, but 'dpy' is set, extract name from dpy
483  *      If 'dpy' is NULL, then Create the named Display
484  *      If 'name' is NULL, and so is 'dpy', use current Display
485  *
486  * Return -1 if no Display given, and none can be opened.
487  */
488 static errr Metadpy_init_2(Display *dpy, cptr name)
489 {
490         metadpy *m = Metadpy;
491
492         /*** Open the display if needed ***/
493
494         /* If no Display given, attempt to Create one */
495         if (!dpy)
496         {
497                 /* Attempt to open the display */
498                 dpy = XOpenDisplay(name);
499
500                 /* Failure */
501                 if (!dpy) return (-1);
502
503                 /* We will have to nuke it when done */
504                 m->nuke = 1;
505         }
506
507         /* Since the Display was given, use it */
508         else
509         {
510                 /* We will not have to nuke it when done */
511                 m->nuke = 0;
512         }
513
514
515         /*** Save some information ***/
516
517         /* Save the Display itself */
518         m->dpy = dpy;
519
520         /* Get the Screen and Virtual Root Window */
521         m->screen = DefaultScreenOfDisplay(dpy);
522         m->root = RootWindowOfScreen(m->screen);
523
524         /* Get the default colormap */
525         m->cmap = DefaultColormapOfScreen(m->screen);
526
527         /* Extract the true name of the display */
528         m->name = DisplayString(dpy);
529
530         /* Extract the fd */
531         m->fd = ConnectionNumber(Metadpy->dpy);
532
533         /* Save the Size and Depth of the screen */
534         m->width = WidthOfScreen(m->screen);
535         m->height = HeightOfScreen(m->screen);
536         m->depth = DefaultDepthOfScreen(m->screen);
537
538         /* Save the Standard Colors */
539         m->black = BlackPixelOfScreen(m->screen);
540         m->white = WhitePixelOfScreen(m->screen);
541
542         /*** Make some clever Guesses ***/
543
544         /* Guess at the desired 'fg' and 'bg' Pixell's */
545         m->bg = m->black;
546         m->fg = m->white;
547
548         /* Calculate the Maximum allowed Pixel value.  */
549         m->zg = (1 << m->depth) - 1;
550
551         /* Save various default Flag Settings */
552         m->color = ((m->depth > 1) ? 1 : 0);
553         m->mono = ((m->color) ? 0 : 1);
554
555         /* Return "success" */
556         return (0);
557 }
558
559
560 #ifndef IGNORE_UNUSED_FUNCTIONS
561
562 /*
563  * Nuke the current metadpy
564  */
565 static errr Metadpy_nuke(void)
566 {
567         metadpy *m = Metadpy;
568
569
570         /* If required, Free the Display */
571         if (m->nuke)
572         {
573                 /* Close the Display */
574                 XCloseDisplay(m->dpy);
575
576                 /* Forget the Display */
577                 m->dpy = (Display*)(NULL);
578
579                 /* Do not nuke it again */
580                 m->nuke = 0;
581         }
582
583         /* Return Success */
584         return (0);
585 }
586
587 #endif /* IGNORE_UNUSED_FUNCTIONS */
588
589
590 /*
591  * General Flush/ Sync/ Discard routine
592  */
593 static errr Metadpy_update(int flush, int sync, int discard)
594 {
595         /* Flush if desired */
596         if (flush) XFlush(Metadpy->dpy);
597
598         /* Sync if desired, using 'discard' */
599         if (sync) XSync(Metadpy->dpy, discard);
600
601         /* Success */
602         return (0);
603 }
604
605
606 /*
607  * Make a simple beep
608  */
609 static errr Metadpy_do_beep(void)
610 {
611         /* Make a simple beep */
612         XBell(Metadpy->dpy, 100);
613
614         return (0);
615 }
616
617
618
619 /*
620  * Set the name (in the title bar) of Infowin
621  */
622 static errr Infowin_set_name(cptr name)
623 {
624         Status st;
625         XTextProperty tp;
626         char buf[128];
627         char *bp = buf;
628         strcpy(buf, name);
629         st = XStringListToTextProperty(&bp, 1, &tp);
630         if (st) XSetWMName(Metadpy->dpy, Infowin->win, &tp);
631         return (0);
632 }
633
634
635 #ifndef IGNORE_UNUSED_FUNCTIONS
636
637 /*
638  * Set the icon name of Infowin
639  */
640 static errr Infowin_set_icon_name(cptr name)
641 {
642         Status st;
643         XTextProperty tp;
644         char buf[128];
645         char *bp = buf;
646         strcpy(buf, name);
647         st = XStringListToTextProperty(&bp, 1, &tp);
648         if (st) XSetWMIconName(Metadpy->dpy, Infowin->win, &tp);
649         return (0);
650 }
651
652
653 /*
654  * Nuke Infowin
655  */
656 static errr Infowin_nuke(void)
657 {
658         infowin *iwin = Infowin;
659
660         /* Nuke if requested */
661         if (iwin->nuke)
662         {
663                 /* Destory the old window */
664                 XDestroyWindow(Metadpy->dpy, iwin->win);
665         }
666
667         /* Success */
668         return (0);
669 }
670
671 #endif /* IGNORE_UNUSED_FUNCTIONS */
672
673
674 /*
675  * Prepare a new 'infowin'.
676  */
677 static errr Infowin_prepare(Window xid)
678 {
679         infowin *iwin = Infowin;
680
681         Window tmp_win;
682         XWindowAttributes xwa;
683         int x, y;
684         unsigned int w, h, b, d;
685
686         /* Assign stuff */
687         iwin->win = xid;
688
689         /* Check For Error XXX Extract some ACTUAL data from 'xid' */
690         XGetGeometry(Metadpy->dpy, xid, &tmp_win, &x, &y, &w, &h, &b, &d);
691
692         /* Apply the above info */
693         iwin->x = x;
694         iwin->y = y;
695         iwin->w = w;
696         iwin->h = h;
697         iwin->b = b;
698
699         /* Check Error XXX Extract some more ACTUAL data */
700         XGetWindowAttributes(Metadpy->dpy, xid, &xwa);
701
702         /* Apply the above info */
703         iwin->mask = xwa.your_event_mask;
704         iwin->mapped = ((xwa.map_state == IsUnmapped) ? 0 : 1);
705
706         /* And assume that we are exposed */
707         iwin->redraw = 1;
708
709         /* Success */
710         return (0);
711 }
712
713
714 #ifndef IGNORE_UNUSED_FUNCTIONS
715
716 /*
717  * Initialize a new 'infowin'.
718  */
719 static errr Infowin_init_real(Window xid)
720 {
721         /* Wipe it clean */
722         (void)WIPE(Infowin, infowin);
723
724         /* Start out non-nukable */
725         Infowin->nuke = 0;
726
727         /* Attempt to Prepare ourself */
728         return (Infowin_prepare(xid));
729 }
730
731 #endif /* IGNORE_UNUSED_FUNCTIONS */
732
733
734 /*
735  * Init an infowin by giving some data.
736  *
737  * Inputs:
738  *      dad: The Window that should own this Window (if any)
739  *      x,y: The position of this Window
740  *      w,h: The size of this Window
741  *      b,d: The border width and pixel depth
742  *
743  * Notes:
744  *      If 'dad == None' assume 'dad == root'
745  */
746 static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
747                               int b, Pixell fg, Pixell bg)
748 {
749         Window xid;
750
751         /* Wipe it clean */
752         (void)WIPE(Infowin, infowin);
753
754
755         /*** Error Check XXX ***/
756
757
758         /*** Create the Window 'xid' from data ***/
759
760         /* What happened here?  XXX XXX XXX */
761
762         /* If no parent given, depend on root */
763         if (dad == None)
764
765 /* #ifdef USE_GRAPHICS
766
767                 xid = XCreateWindow(Metadpy->dpy, Metadpy->root, x, y, w, h, b, 8, InputOutput, CopyFromParent, 0, 0);
768
769         else
770 */
771
772 /* #else */
773
774                 dad = Metadpy->root;
775
776 /* #endif */
777
778         /* Create the Window XXX Error Check */
779         xid = XCreateSimpleWindow(Metadpy->dpy, dad, x, y, w, h, b, fg, bg);
780
781         /* Start out selecting No events */
782         XSelectInput(Metadpy->dpy, xid, 0L);
783
784
785         /*** Prepare the new infowin ***/
786
787         /* Mark it as nukable */
788         Infowin->nuke = 1;
789
790         /* Attempt to Initialize the infowin */
791         return (Infowin_prepare(xid));
792 }
793
794
795
796 /*
797  * Modify the event mask of an Infowin
798  */
799 static errr Infowin_set_mask(long mask)
800 {
801         /* Save the new setting */
802         Infowin->mask = mask;
803
804         /* Execute the Mapping */
805         XSelectInput(Metadpy->dpy, Infowin->win, Infowin->mask);
806
807         /* Success */
808         return (0);
809 }
810
811
812 /*
813  * Request that Infowin be mapped
814  */
815 static errr Infowin_map(void)
816 {
817         /* Execute the Mapping */
818         XMapWindow(Metadpy->dpy, Infowin->win);
819
820         /* Success */
821         return (0);
822 }
823
824
825 #ifndef IGNORE_UNUSED_FUNCTIONS
826
827 /*
828  * Request that Infowin be unmapped
829  */
830 static errr Infowin_unmap(void)
831 {
832         /* Execute the Un-Mapping */
833         XUnmapWindow(Metadpy->dpy, Infowin->win);
834
835         /* Success */
836         return (0);
837 }
838
839 #endif /* IGNORE_UNUSED_FUNCTIONS */
840
841
842 /*
843  * Request that Infowin be raised
844  */
845 static errr Infowin_raise(void)
846 {
847         /* Raise towards visibility */
848         XRaiseWindow(Metadpy->dpy, Infowin->win);
849
850         /* Success */
851         return (0);
852 }
853
854
855 #ifndef IGNORE_UNUSED_FUNCTIONS
856
857 /*
858  * Request that Infowin be lowered
859  */
860 static errr Infowin_lower(void)
861 {
862         /* Lower towards invisibility */
863         XLowerWindow(Metadpy->dpy, Infowin->win);
864
865         /* Success */
866         return (0);
867 }
868
869 #endif /* IGNORE_UNUSED_FUNCTIONS */
870
871
872 /*
873  * Request that Infowin be moved to a new location
874  */
875 static errr Infowin_impell(int x, int y)
876 {
877         /* Execute the request */
878         XMoveWindow(Metadpy->dpy, Infowin->win, x, y);
879
880         /* Success */
881         return (0);
882 }
883
884
885 /*
886  * Resize an infowin
887  */
888 static errr Infowin_resize(int w, int h)
889 {
890         /* Execute the request */
891         XResizeWindow(Metadpy->dpy, Infowin->win, w, h);
892
893         /* Success */
894         return (0);
895 }
896
897
898 #ifndef IGNORE_UNUSED_FUNCTIONS
899
900 /*
901  * Move and Resize an infowin
902  */
903 static errr Infowin_locate(int x, int y, int w, int h)
904 {
905         /* Execute the request */
906         XMoveResizeWindow(Metadpy->dpy, Infowin->win, x, y, w, h);
907
908         /* Success */
909         return (0);
910 }
911
912 #endif /* IGNORE_UNUSED_FUNCTIONS */
913
914
915 /*
916  * Visually clear Infowin
917  */
918 static errr Infowin_wipe(void)
919 {
920         /* Execute the request */
921         XClearWindow(Metadpy->dpy, Infowin->win);
922
923         /* Success */
924         return (0);
925 }
926
927
928 #ifndef IGNORE_UNUSED_FUNCTIONS
929
930 /*
931  * Visually Paint Infowin with the current color
932  */
933 static errr Infowin_fill(void)
934 {
935         /* Execute the request */
936         XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc,
937                        0, 0, Infowin->w, Infowin->h);
938
939         /* Success */
940         return (0);
941 }
942
943 #endif /* IGNORE_UNUSED_FUNCTIONS */
944
945
946 /*
947  * A NULL terminated pair list of legal "operation names"
948  *
949  * Pairs of values, first is texttual name, second is the string
950  * holding the decimal value that the operation corresponds to.
951  */
952 static cptr opcode_pairs[] =
953 {
954         "cpy", "3",
955         "xor", "6",
956         "and", "1",
957         "ior", "7",
958         "nor", "8",
959         "inv", "10",
960         "clr", "0",
961         "set", "15",
962
963         "src", "3",
964         "dst", "5",
965
966         "+andReverse", "2",
967         "+andInverted", "4",
968         "+noop", "5",
969         "+equiv", "9",
970         "+orReverse", "11",
971         "+copyInverted", "12",
972         "+orInverted", "13",
973         "+nand", "14",
974         NULL
975 };
976
977
978 /*
979  * Parse a word into an operation "code"
980  *
981  * Inputs:
982  *      str: A string, hopefully representing an Operation
983  *
984  * Output:
985  *      0-15: if 'str' is a valid Operation
986  *      -1:   if 'str' could not be parsed
987  */
988 static int Infoclr_Opcode(cptr str)
989 {
990         register int i;
991
992         /* Scan through all legal operation names */
993         for (i = 0; opcode_pairs[i*2]; ++i)
994         {
995                 /* Is this the right oprname? */
996                 if (streq(opcode_pairs[i*2], str))
997                 {
998                         /* Convert the second element in the pair into a Code */
999                         return (atoi(opcode_pairs[i*2+1]));
1000                 }
1001         }
1002
1003         /* The code was not found, return -1 */
1004         return (-1);
1005 }
1006
1007
1008 #ifndef IGNORE_UNUSED_FUNCTIONS
1009
1010 /*
1011  * Request a Pixell by name.  Note: uses 'Metadpy'.
1012  *
1013  * Inputs:
1014  *      name: The name of the color to try to load (see below)
1015  *
1016  * Output:
1017  *      The Pixell value that metched the given name
1018  *      'Metadpy->fg' if the name was unparseable
1019  *
1020  * Valid forms for 'name':
1021  *      'fg', 'bg', 'zg', '<name>' and '#<code>'
1022  */
1023 static Pixell Infoclr_Pixell(cptr name)
1024 {
1025         XColor scrn;
1026
1027         /* Attempt to Parse the name */
1028         if (name && name[0])
1029         {
1030                 /* The 'bg' color is available */
1031                 if (streq(name, "bg")) return (Metadpy->bg);
1032
1033                 /* The 'fg' color is available */
1034                 if (streq(name, "fg")) return (Metadpy->fg);
1035
1036                 /* The 'zg' color is available */
1037                 if (streq(name, "zg")) return (Metadpy->zg);
1038
1039                 /* The 'white' color is available */
1040                 if (streq(name, "white")) return (Metadpy->white);
1041
1042                 /* The 'black' color is available */
1043                 if (streq(name, "black")) return (Metadpy->black);
1044
1045                 /* Attempt to parse 'name' into 'scrn' */
1046                 if (!(XParseColor(Metadpy->dpy, Metadpy->cmap, name, &scrn)))
1047                 {
1048                         plog_fmt("Warning: Couldn't parse color '%s'\n", name);
1049                 }
1050
1051                 /* Attempt to Allocate the Parsed color */
1052                 if (!(XAllocColor(Metadpy->dpy, Metadpy->cmap, &scrn)))
1053                 {
1054                         plog_fmt("Warning: Couldn't allocate color '%s'\n", name);
1055                 }
1056
1057                 /* The Pixel was Allocated correctly */
1058                 else return (scrn.pixel);
1059         }
1060
1061         /* Warn about the Default being Used */
1062         plog_fmt("Warning: Using 'fg' for unknown color '%s'\n", name);
1063
1064         /* Default to the 'Foreground' color */
1065         return (Metadpy->fg);
1066 }
1067
1068
1069 /*
1070  * Initialize a new 'infoclr' with a real GC.
1071  */
1072 static errr Infoclr_init_1(GC gc)
1073 {
1074         infoclr *iclr = Infoclr;
1075
1076         /* Wipe the iclr clean */
1077         (void)WIPE(iclr, infoclr);
1078
1079         /* Assign the GC */
1080         iclr->gc = gc;
1081
1082         /* Success */
1083         return (0);
1084 }
1085
1086
1087 /*
1088  * Nuke an old 'infoclr'.
1089  */
1090 static errr Infoclr_nuke(void)
1091 {
1092         infoclr *iclr = Infoclr;
1093
1094         /* Deal with 'GC' */
1095         if (iclr->nuke)
1096         {
1097                 /* Free the GC */
1098                 XFreeGC(Metadpy->dpy, iclr->gc);
1099         }
1100
1101         /* Forget the current */
1102         Infoclr = (infoclr*)(NULL);
1103
1104         /* Success */
1105         return (0);
1106 }
1107
1108 #endif /* IGNORE_UNUSED_FUNCTIONS */
1109
1110
1111 /*
1112  * Initialize an infoclr with some data
1113  *
1114  * Inputs:
1115  *      fg:   The Pixell for the requested Foreground (see above)
1116  *      bg:   The Pixell for the requested Background (see above)
1117  *      op:   The Opcode for the requested Operation (see above)
1118  *      stip: The stipple mode
1119  */
1120 static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
1121 {
1122         infoclr *iclr = Infoclr;
1123
1124         GC gc;
1125         XGCValues gcv;
1126         unsigned long gc_mask;
1127
1128
1129
1130         /*** Simple error checking of opr and clr ***/
1131
1132         /* Check the 'Pixells' for realism */
1133         if (bg > Metadpy->zg) return (-1);
1134         if (fg > Metadpy->zg) return (-1);
1135
1136         /* Check the data for trueness */
1137         if ((op < 0) || (op > 15)) return (-1);
1138
1139
1140         /*** Create the requested 'GC' ***/
1141
1142         /* Assign the proper GC function */
1143         gcv.function = op;
1144
1145         /* Assign the proper GC background */
1146         gcv.background = bg;
1147
1148         /* Assign the proper GC foreground */
1149         gcv.foreground = fg;
1150
1151         /* Hack -- Handle XOR (xor is code 6) by hacking bg and fg */
1152         if (op == 6) gcv.background = 0;
1153         if (op == 6) gcv.foreground = (bg ^ fg);
1154
1155         /* Assign the proper GC Fill Style */
1156         gcv.fill_style = (stip ? FillStippled : FillSolid);
1157
1158         /* Turn off 'Give exposure events for pixmap copying' */
1159         gcv.graphics_exposures = False;
1160
1161         /* Set up the GC mask */
1162         gc_mask = (GCFunction | GCBackground | GCForeground |
1163                    GCFillStyle | GCGraphicsExposures);
1164
1165         /* Create the GC detailed above */
1166         gc = XCreateGC(Metadpy->dpy, Metadpy->root, gc_mask, &gcv);
1167
1168
1169         /*** Initialize ***/
1170
1171         /* Wipe the iclr clean */
1172         (void)WIPE(iclr, infoclr);
1173
1174         /* Assign the GC */
1175         iclr->gc = gc;
1176
1177         /* Nuke it when done */
1178         iclr->nuke = 1;
1179
1180         /* Assign the parms */
1181         iclr->fg = fg;
1182         iclr->bg = bg;
1183         iclr->code = op;
1184         iclr->stip = stip ? 1 : 0;
1185
1186         /* Success */
1187         return (0);
1188 }
1189
1190
1191
1192 /*
1193  * Change the 'fg' for an infoclr
1194  *
1195  * Inputs:
1196  *      fg:   The Pixell for the requested Foreground (see above)
1197  */
1198 static errr Infoclr_change_fg(Pixell fg)
1199 {
1200         infoclr *iclr = Infoclr;
1201
1202
1203         /*** Simple error checking of opr and clr ***/
1204
1205         /* Check the 'Pixells' for realism */
1206         if (fg > Metadpy->zg) return (-1);
1207
1208
1209         /*** Change ***/
1210
1211         /* Change */
1212         XSetForeground(Metadpy->dpy, iclr->gc, fg);
1213
1214         /* Success */
1215         return (0);
1216 }
1217
1218
1219
1220 #ifndef IGNORE_UNUSED_FUNCTIONS
1221
1222 /*
1223  * Nuke an old 'infofnt'.
1224  */
1225 static errr Infofnt_nuke(void)
1226 {
1227         infofnt *ifnt = Infofnt;
1228
1229 #ifdef _JP
1230         infofnt *ikfnt = Infokfnt;
1231 #endif
1232         /* Deal with 'name' */
1233         if (ifnt->name)
1234         {
1235                 /* Free the name */
1236                 string_free(ifnt->name);
1237         }
1238
1239 #ifdef _JP
1240         if (ikfnt->name)
1241         {
1242                 /* Free the name */
1243                 string_free(ikfnt->name);
1244         }
1245 #endif
1246         /* Nuke info if needed */
1247         if (ifnt->nuke)
1248         {
1249                 /* Free the font */
1250                 XFreeFont(Metadpy->dpy, ifnt->info);
1251         }
1252
1253 #ifdef _JP
1254         if (ikfnt->nuke)
1255         {
1256                 /* Free the font */
1257                 XFreeFont(Metadpy->dpy, ikfnt->info);
1258         }
1259 #endif
1260         /* Success */
1261         return (0);
1262 }
1263
1264 #endif /* IGNORE_UNUSED_FUNCTIONS */
1265
1266
1267 /*
1268  * Prepare a new 'infofnt'
1269  */
1270 #ifdef _JP
1271 static errr Infofnt_prepare(XFontStruct *info, XFontStruct *kinfo)
1272 #else
1273 #ifdef USE_FONTSET
1274 static errr Infofnt_prepare(XFontSet info)
1275 #else
1276 static errr Infofnt_prepare(XFontStruct *info)
1277 #endif
1278 #endif
1279
1280 {
1281         infofnt *ifnt = Infofnt;
1282
1283 #ifdef _JP
1284         infofnt *ikfnt = Infokfnt;
1285 #endif
1286         XCharStruct *cs;
1287 #ifdef USE_FONTSET
1288         XFontStruct **fontinfo;
1289         char **fontname;
1290         int n_fonts;
1291         int ascent, descent, width;
1292 #endif
1293
1294         /* Assign the struct */
1295         ifnt->info = info;
1296
1297 #ifdef USE_FONTSET
1298         n_fonts = XFontsOfFontSet(info, &fontinfo, &fontname);
1299
1300         ascent = descent = width = 0;
1301         while(n_fonts-- > 0){
1302                 cs = &((*fontinfo)->max_bounds);
1303                 if(ascent < (*fontinfo)->ascent) ascent = (*fontinfo)->ascent;
1304                 if(descent < (*fontinfo)->descent) descent = (*fontinfo)->descent;
1305                 if(((*fontinfo)->max_byte1) > 0){
1306                         /* Â¿¥Ð¥¤¥Èʸ»ú¤Î¾ì¹ç¤ÏÉýȾʬ(ü¿ôÀÚ¤ê¾å¤²)¤Çɾ²Á¤¹¤ë */
1307                         if(width < (cs->width+1)/2) width = (cs->width+1)/2;
1308                 }else{
1309                         if(width < cs->width) width = cs->width;
1310                 }
1311                 fontinfo++;
1312                 fontname++;
1313         }
1314         ifnt->asc = ascent;
1315         ifnt->hgt = ascent + descent;
1316         ifnt->wid = width;
1317 #else
1318         /* Jump into the max bouonds thing */
1319         cs = &(info->max_bounds);
1320
1321         /* Extract default sizing info */
1322         ifnt->asc = info->ascent;
1323         ifnt->hgt = info->ascent + info->descent;
1324         ifnt->wid = cs->width;
1325 #endif
1326
1327 #ifdef _JP
1328     /* Assign the struct */
1329     ikfnt->info = kinfo;
1330  
1331     /* Jump into the max bouonds thing */
1332     cs = &(kinfo->max_bounds);
1333  
1334     /* Extract default sizing info */
1335     ikfnt->asc = kinfo->ascent;
1336     ikfnt->hgt = kinfo->ascent + kinfo->descent;
1337     ikfnt->wid = cs->width;
1338 #endif
1339 #ifndef JP
1340 #ifdef OBSOLETE_SIZING_METHOD
1341         /* Extract default sizing info */
1342         ifnt->asc = cs->ascent;
1343         ifnt->hgt = (cs->ascent + cs->descent);
1344         ifnt->wid = cs->width;
1345 #endif
1346 #endif
1347
1348         /* Success */
1349         return (0);
1350 }
1351
1352
1353 #ifndef IGNORE_UNUSED_FUNCTIONS
1354
1355 /*
1356  * Initialize a new 'infofnt'.
1357  */
1358 #ifdef _JP
1359 static errr Infofnt_init_real(XFontStruct *info, XFontStruct *kinfo)
1360 #else
1361 #ifdef USE_FONTSET
1362 static errr Infofnt_init_real(XFontSet info)
1363 #else
1364 static errr Infofnt_init_real(XFontStruct *info)
1365 #endif
1366 #endif
1367
1368 {
1369         /* Wipe the thing */
1370         (void)WIPE(Infofnt, infofnt);
1371
1372 #ifdef _JP
1373         WIPE(Infokfnt, infofnt);
1374 #endif
1375         /* No nuking */
1376         Infofnt->nuke = 0;
1377
1378 #ifdef _JP
1379         Infokfnt->nuke = 0;
1380 #endif
1381         /* Attempt to prepare it */
1382 #ifdef _JP
1383         return (Infofnt_prepare (info, kinfo));
1384 #else
1385         return (Infofnt_prepare(info));
1386 #endif
1387
1388 }
1389
1390 #endif /* IGNORE_UNUSED_FUNCTIONS */
1391
1392
1393 /*
1394  * Init an infofnt by its Name
1395  *
1396  * Inputs:
1397  *      name: The name of the requested Font
1398  */
1399 #ifdef _JP
1400 static errr Infofnt_init_data(cptr name, cptr kname)
1401 #else
1402 static errr Infofnt_init_data(cptr name)
1403 #endif
1404
1405 {
1406 #ifdef USE_FONTSET
1407         XFontSet info;
1408         char **missing_list;
1409         int missing_count;
1410         char *default_font;
1411 #else
1412         XFontStruct *info;
1413 #endif
1414
1415
1416 #ifdef _JP
1417         XFontStruct *kinfo;
1418 #endif
1419         /*** Load the info Fresh, using the name ***/
1420
1421         /* If the name is not given, report an error */
1422         if (!name) return (-1);
1423
1424 #ifdef _JP
1425         if (!kname) return (-1);
1426 #endif
1427         /* Attempt to load the font */
1428 #ifdef USE_FONTSET
1429         info = XCreateFontSet(Metadpy->dpy, name, &missing_list, &missing_count, &default_font);
1430         if(missing_count > 0){
1431                 printf("missing font(s): \n");
1432                 while(missing_count-- > 0){
1433                         printf("\t%s\n", missing_list[missing_count]);
1434                 }
1435                 XFreeStringList(missing_list);
1436         }
1437 #else
1438         info = XLoadQueryFont(Metadpy->dpy, name);
1439 #ifdef _JP
1440         kinfo = XLoadQueryFont(Metadpy->dpy, kname);
1441 #endif
1442 #endif
1443
1444
1445         /* The load failed, try to recover */
1446         if (!info) return (-1);
1447 #ifdef _JP
1448         if (!kinfo) return (-1);
1449 #endif
1450
1451
1452
1453         /*** Init the font ***/
1454
1455         /* Wipe the thing */
1456         (void)WIPE(Infofnt, infofnt);
1457
1458 #ifdef _JP
1459         WIPE(Infokfnt, infofnt);
1460 #endif
1461         /* Attempt to prepare it */
1462 #ifdef _JP
1463         if (Infofnt_prepare(info, kinfo))
1464 #else
1465         if (Infofnt_prepare(info))
1466 #endif
1467
1468         {
1469                 /* Free the font */
1470 #ifdef USE_FONTSET
1471                 XFreeFontSet(Metadpy->dpy, info);
1472 #else
1473                 XFreeFont(Metadpy->dpy, info);
1474 #ifdef _JP
1475                 XFreeFont(Metadpy->dpy, kinfo);
1476 #endif
1477 #endif
1478                 /* Fail */
1479                 return (-1);
1480         }
1481
1482         /* Save a copy of the font name */
1483         Infofnt->name = string_make(name);
1484 #ifdef _JP
1485         Infokfnt->name = string_make(kname);
1486 #endif
1487
1488         /* Mark it as nukable */
1489         Infofnt->nuke = 1;
1490 #ifdef _JP
1491         Infokfnt->nuke = 1;
1492 #endif
1493
1494         /* Success */
1495         return (0);
1496 }
1497
1498
1499 #ifdef _JP
1500 /*
1501  * EUCÆüËܸ쥳¡¼¥É¤ò´Þ¤àʸ»úÎó¤òɽ¼¨¤¹¤ë (Xlib)
1502  */
1503 static void
1504 XDrawMultiString(display,d,gc, x, y, string, len, afont, 
1505       afont_width, afont_height, afont_ascent, kfont, kfont_width)
1506     Display *display;
1507     Drawable d;
1508     GC gc;
1509     int       x, y;
1510     char      *string;
1511     int len;
1512     XFontStruct *afont;
1513     int afont_width, afont_height, afont_ascent;
1514     XFontStruct *kfont;
1515     int kfont_width;
1516 {
1517     XChar2b       kanji[500];
1518     char *p;
1519     unsigned char *str;
1520     unsigned char *endp;
1521     int slen;
1522     str = string;
1523     endp = string + len;
1524
1525     while ( str < endp && *str ) {
1526
1527 #ifdef TOFU      
1528       if ( (*str) == 0x7f ) {
1529           
1530           /* 0x7F¤Ï¢£¤Ç·è¤áÂǤÁ */
1531           
1532           /* Ï¢Â³¤¹¤ë0x7F¤ÎŤµ¤ò¸¡½Ð */
1533           slen = 0;
1534           while ( str < endp && (*str) == 0x7f ) {
1535               slen++; 
1536               str++;
1537           }
1538           
1539           /* ÉÁ²è */
1540           XFillRectangle( display, d, gc, x, y-afont_ascent, 
1541                           slen * afont_width, afont_height);
1542  
1543           /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1544           x += afont_width * slen;
1545       } 
1546       else  
1547 #endif
1548       if ( iskanji(*str) ) {
1549           
1550           /* UJIS¤Î»Ï¤Þ¤ê */
1551           
1552           /* Ï¢Â³¤¹¤ëUJISʸ»ú¤ÎŤµ¤ò¸¡½Ð */
1553           slen = 0;
1554           while ( str < endp && *str && iskanji(*str) ) {
1555               kanji[slen].byte1 = *str++ & 0x7f;
1556               kanji[slen++].byte2 = *str++ & 0x7f;
1557           }
1558           
1559           /* ÉÁ²è */
1560           XSetFont( display, gc, kfont->fid );
1561           XDrawImageString16( display, d, gc, x, y, kanji, slen );
1562
1563  
1564           /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1565           x += kfont_width * slen;
1566           
1567       } else {
1568           
1569           /* Èó´Á»ú(=ASCII¤È²¾Äê)¤Î»Ï¤Þ¤ê */
1570           
1571           /* Ï¢Â³¤¹¤ëASCIIʸ»ú¤ò¸¡½Ð */
1572           p = str;
1573           slen = 0;
1574           while ( str < endp && *str && !iskanji(*str) ) {
1575 #ifdef TOFU
1576               if (*str == 0x7f)break;
1577 #endif
1578               str++;
1579               slen++;
1580           }
1581           
1582           /* ÉÁ²è */
1583           XSetFont( display, gc, afont->fid );
1584           XDrawImageString( display, d, gc, x, y, p, slen );
1585           
1586           /* ¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë */
1587           x += afont_width * slen;
1588       }
1589     }
1590 }
1591 #endif
1592
1593 /*
1594  * Standard Text
1595  */
1596 static errr Infofnt_text_std(int x, int y, cptr str, int len)
1597 {
1598         int i;
1599
1600
1601         /*** Do a brief info analysis ***/
1602
1603         /* Do nothing if the string is null */
1604         if (!str || !*str) return (-1);
1605
1606         /* Get the length of the string */
1607         if (len < 0) len = strlen(str);
1608
1609
1610         /*** Decide where to place the string, vertically ***/
1611
1612         /* Ignore Vertical Justifications */
1613         y = (y * Infofnt->hgt) + Infofnt->asc + Infowin->oy;
1614
1615
1616         /*** Decide where to place the string, horizontally ***/
1617
1618         /* Line up with x at left edge of column 'x' */
1619         x = (x * Infofnt->wid) + Infowin->ox;
1620
1621
1622         /*** Actually draw 'str' onto the infowin ***/
1623
1624 #if 1
1625 #ifndef JP
1626         /* Be sure the correct font is ready */
1627         XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
1628 #endif
1629 #endif
1630
1631         /*** Handle the fake mono we can enforce on fonts ***/
1632
1633         /* Monotize the font */
1634         if (Infofnt->mono)
1635         {
1636 #ifdef _JP
1637                 /* Be sure the correct font is ready */
1638                 XSetFont(Metadpy->dpy, Infoclr->gc, Infofnt->info->fid);
1639 #endif
1640                 /* Do each character */
1641                 for (i = 0; i < len; ++i)
1642                 {
1643                         /* Note that the Infoclr is set up to contain the Infofnt */
1644                         XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1645                                          x + i * Infofnt->wid + Infofnt->off, y, str + i, 1);
1646                 }
1647         }
1648
1649         /* Assume monoospaced font */
1650         else
1651         {
1652                 /* Note that the Infoclr is set up to contain the Infofnt */
1653 #ifdef _JP
1654                 /* ´Á»ú¥Õ¥©¥ó¥È¤Îɽ¼¨Éý¤Ï ASCII¥Õ¥©¥ó¥È¤Î2Çܤ˸ÇÄê */
1655                 XDrawMultiString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1656                                  x, y, str, len,
1657                                  Infofnt->info, Infofnt->wid, Infofnt->hgt,
1658                                  Infofnt->asc, 
1659                                  Infokfnt->info, Infofnt->wid * 2);
1660 #else
1661 #ifdef USE_FONTSET
1662                 XmbDrawImageString(Metadpy->dpy, Infowin->win, Infofnt->info,
1663                                    Infoclr->gc, x, y, str, len);
1664 #else
1665                 XDrawImageString(Metadpy->dpy, Infowin->win, Infoclr->gc,
1666                                  x, y, str, len);
1667 #endif
1668 #endif
1669
1670         }
1671
1672
1673         /* Success */
1674         return (0);
1675 }
1676
1677
1678 /*
1679  * Painting where text would be
1680  */
1681 static errr Infofnt_text_non(int x, int y, cptr str, int len)
1682 {
1683         int w, h;
1684
1685
1686         /*** Find the width ***/
1687
1688         /* Negative length is a flag to count the characters in str */
1689         if (len < 0) len = strlen(str);
1690
1691         /* The total width will be 'len' chars * standard width */
1692         w = len * Infofnt->wid;
1693
1694
1695         /*** Find the X dimensions ***/
1696
1697         /* Line up with x at left edge of column 'x' */
1698         x = x * Infofnt->wid + Infowin->ox;
1699
1700
1701         /*** Find other dimensions ***/
1702
1703         /* Simply do 'Infofnt->hgt' (a single row) high */
1704         h = Infofnt->hgt;
1705
1706         /* Simply do "at top" in row 'y' */
1707         y = y * h + Infowin->oy;
1708
1709
1710         /*** Actually 'paint' the area ***/
1711
1712         /* Just do a Fill Rectangle */
1713         XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, x, y, w, h);
1714
1715         /* Success */
1716         return (0);
1717 }
1718
1719
1720
1721 /*************************************************************************/
1722
1723
1724 /*
1725  * Angband specific code follows... (ANGBAND)
1726  */
1727
1728
1729 /*
1730  * Hack -- cursor color
1731  */
1732 static infoclr *xor;
1733
1734 /*
1735  * Actual color table
1736  */
1737 static infoclr *clr[256];
1738
1739 /*
1740  * Color info (unused, red, green, blue).
1741  */
1742 static byte color_table[256][4];
1743
1744 /*
1745  * Forward declare
1746  */
1747 typedef struct term_data term_data;
1748
1749 /*
1750  * A structure for each "term"
1751  */
1752 struct term_data
1753 {
1754         term t;
1755
1756         infofnt *fnt;
1757 #ifdef _JP
1758         infofnt *kfnt;
1759 #endif
1760
1761
1762         infowin *win;
1763
1764 #ifdef USE_GRAPHICS
1765
1766         XImage *tiles;
1767
1768 #ifdef USE_TRANSPARENCY
1769
1770         /* Tempory storage for overlaying tiles. */
1771         XImage *TmpImage;
1772
1773 #endif
1774
1775 #endif
1776
1777 };
1778
1779
1780 /*
1781  * The number of term data structures
1782  */
1783 #define MAX_TERM_DATA 8
1784
1785 /*
1786  * The array of term data structures
1787  */
1788 static term_data data[MAX_TERM_DATA];
1789
1790
1791
1792 /*
1793  * Process a keypress event
1794  *
1795  * Also appears in "main-xaw.c".
1796  */
1797 static void react_keypress(XKeyEvent *xev)
1798 {
1799         int i, n, mc, ms, mo, mx;
1800
1801         uint ks1;
1802
1803         XKeyEvent *ev = (XKeyEvent*)(xev);
1804
1805         KeySym ks;
1806
1807         char buf[128];
1808         char msg[128];
1809
1810 #ifdef USE_XIM
1811         int valid_keysym = TRUE;
1812 #endif
1813
1814         /* Check for "normal" keypresses */
1815 #ifdef USE_XIM
1816         if(Focuswin && Focuswin->xic){
1817                 Status status;
1818                 n = XmbLookupString(Focuswin->xic, ev, buf, 125, &ks, &status);
1819                 if(status == XBufferOverflow){
1820                         printf("Input is too long, and dropped\n");
1821                         return;
1822                 }
1823                 if(status != XLookupKeySym && status != XLookupBoth){
1824                         valid_keysym = FALSE;
1825                 }
1826         }else{
1827                 n = XLookupString(ev, buf, 125, &ks, NULL);
1828         }
1829 #else
1830         n = XLookupString(ev, buf, 125, &ks, NULL);
1831 #endif
1832
1833         /* Terminate */
1834         buf[n] = '\0';
1835
1836 #ifdef USE_XIM
1837         if(!valid_keysym){
1838                 /* Enqueue the normal key(s) */
1839                 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1840
1841                 /* All done */
1842                 return;
1843         }
1844 #endif
1845
1846         /* Hack -- Ignore "modifier keys" */
1847         if (IsModifierKey(ks)) return;
1848
1849
1850         /* Hack -- convert into an unsigned int */
1851         ks1 = (uint)(ks);
1852
1853         /* Extract four "modifier flags" */
1854         mc = (ev->state & ControlMask) ? TRUE : FALSE;
1855         ms = (ev->state & ShiftMask) ? TRUE : FALSE;
1856         mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
1857         mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
1858
1859
1860         /* Normal keys with no modifiers */
1861         if (n && !mo && !mx && !IsSpecialKey(ks))
1862         {
1863                 /* Enqueue the normal key(s) */
1864                 for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
1865
1866                 /* All done */
1867                 return;
1868         }
1869
1870
1871         /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */
1872         switch (ks1)
1873         {
1874                 case XK_Escape:
1875                 {
1876                         Term_keypress(ESCAPE);
1877                         return;
1878                 }
1879
1880                 case XK_Return:
1881                 {
1882                         Term_keypress('\r');
1883                         return;
1884                 }
1885
1886                 case XK_Tab:
1887                 {
1888                         Term_keypress('\t');
1889                         return;
1890                 }
1891
1892                 case XK_Delete:
1893                 case XK_BackSpace:
1894                 {
1895                         Term_keypress('\010');
1896                         return;
1897                 }
1898         }
1899
1900
1901         /* Hack -- Use the KeySym */
1902         if (ks)
1903         {
1904                 sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
1905                         mc ? "N" : "", ms ? "S" : "",
1906                         mo ? "O" : "", mx ? "M" : "",
1907                         (unsigned long)(ks), 13);
1908         }
1909
1910         /* Hack -- Use the Keycode */
1911         else
1912         {
1913                 sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
1914                         mc ? "N" : "", ms ? "S" : "",
1915                         mo ? "O" : "", mx ? "M" : "",
1916                         ev->keycode, 13);
1917         }
1918
1919         /* Enqueue the "macro trigger" string */
1920         for (i = 0; msg[i]; i++) Term_keypress(msg[i]);
1921
1922
1923         /* Hack -- auto-define macros as needed */
1924         if (n && (macro_find_exact(msg) < 0))
1925         {
1926                 /* Create a macro */
1927                 macro_add(msg, buf);
1928         }
1929 }
1930
1931
1932
1933
1934 /*
1935  * Process events
1936  */
1937 static errr CheckEvent(bool wait)
1938 {
1939         term_data *old_td = (term_data*)(Term->data);
1940
1941         XEvent xev_body, *xev = &xev_body;
1942
1943         term_data *td = NULL;
1944         infowin *iwin = NULL;
1945
1946         int i, x, y;
1947
1948 #ifdef USE_XIM
1949  redo_checkevent:
1950 #endif
1951
1952         /* Do not wait unless requested */
1953         if (!wait && !XPending(Metadpy->dpy)) return (1);
1954
1955         /* Load the Event */
1956         XNextEvent(Metadpy->dpy, xev);
1957
1958 #ifdef USE_XIM
1959 /* #define DEBUG_EVENT */
1960 #ifdef DEBUG_EVENT
1961         {
1962                 printf("event: type=%d", xev->type);
1963                 switch(xev->type){
1964                 case KeyPress:
1965                         printf("(KeyPress), keycode=%X", xev->xkey.keycode);
1966                         break;
1967                 case FocusIn:
1968                         printf("(FocusIn)");
1969                         break;
1970                 case FocusOut:
1971                         printf("(FocusOut)");
1972                         break;
1973                 case ReparentNotify:
1974                         printf("(ReparentNotify)");
1975                         break;
1976                 case ConfigureNotify:
1977                         printf("(ConfigureNotify)");
1978                         break;
1979                 case MapNotify:
1980                         printf("(MapNotify)");
1981                         break;
1982                 case Expose:
1983                         printf("(Expose)");
1984                         break;
1985                 case ClientMessage:
1986                         printf("(ClientMessage)");
1987                         break;
1988                 }
1989                         
1990         }
1991 #endif
1992         if (XFilterEvent(xev, xev->xany.window)
1993                 /*XFilterEvent(xev, (data[0].win)->win)*/){
1994 #ifdef DEBUG_EVENT
1995                 printf(", [filtered by IM]\n");
1996 #endif
1997                 goto redo_checkevent;
1998         }
1999 #ifdef DEBUG_EVENT
2000         printf("\n");
2001 #endif
2002 #endif
2003
2004         /* Notice new keymaps */
2005         if (xev->type == MappingNotify)
2006         {
2007                 XRefreshKeyboardMapping(&xev->xmapping);
2008                 return 0;
2009         }
2010
2011
2012         /* Scan the windows */
2013         for (i = 0; i < MAX_TERM_DATA; i++)
2014         {
2015                 if (!data[i].win) continue;
2016                 if (xev->xany.window == data[i].win->win)
2017                 {
2018                         td = &data[i];
2019                         iwin = td->win;
2020                         break;
2021                 }
2022         }
2023
2024         /* Unknown window */
2025         if (!td || !iwin) return (0);
2026
2027
2028         /* Hack -- activate the Term */
2029         Term_activate(&td->t);
2030
2031         /* Hack -- activate the window */
2032         Infowin_set(iwin);
2033
2034
2035         /* Switch on the Type */
2036         switch (xev->type)
2037         {
2038
2039 #if 0
2040
2041                 case ButtonPress:
2042                 case ButtonRelease:
2043                 {
2044                         int z = 0;
2045
2046                         /* Which button is involved */
2047                         if (xev->xbutton.button == Button1) z = 1;
2048                         else if (xev->xbutton.button == Button2) z = 2;
2049                         else if (xev->xbutton.button == Button3) z = 3;
2050                         else if (xev->xbutton.button == Button4) z = 4;
2051                         else if (xev->xbutton.button == Button5) z = 5;
2052
2053                         /* Where is the mouse */
2054                         x = xev->xbutton.x;
2055                         y = xev->xbutton.y;
2056
2057                         /* XXX Handle */
2058
2059                         break;
2060                 }
2061
2062                 case EnterNotify:
2063                 case LeaveNotify:
2064                 {
2065                         /* Where is the mouse */
2066                         x = xev->xcrossing.x;
2067                         y = xev->xcrossing.y;
2068
2069                         /* XXX Handle */
2070
2071                         break;
2072                 }
2073
2074                 case MotionNotify:
2075                 {
2076                         /* Where is the mouse */
2077                         x = xev->xmotion.x;
2078                         y = xev->xmotion.y;
2079
2080                         /* XXX Handle */
2081
2082                         break;
2083                 }
2084
2085                 case KeyRelease:
2086                 {
2087                         /* Nothing */
2088                         break;
2089                 }
2090
2091 #endif
2092
2093                 case KeyPress:
2094                 {
2095                         /* Save the mouse location */
2096                         x = xev->xkey.x;
2097                         y = xev->xkey.y;
2098
2099                         /* Hack -- use "old" term */
2100                         Term_activate(&old_td->t);
2101
2102                         /* Process the key */
2103                         react_keypress(&(xev->xkey));
2104
2105                         break;
2106                 }
2107
2108                 case Expose:
2109                 {
2110                         int x1, x2, y1, y2;
2111                         
2112                         /* Ignore "extra" exposes */
2113                         /*if (xev->xexpose.count) break;*/
2114
2115                         /* Clear the window */
2116                         /*Infowin_wipe();*/
2117                         
2118                         x1 = (xev->xexpose.x - Infowin->ox)/Infofnt->wid;
2119                         x2 = (xev->xexpose.x + xev->xexpose.width -
2120                                  Infowin->ox)/Infofnt->wid;
2121                         
2122                         y1 = (xev->xexpose.y - Infowin->oy)/Infofnt->hgt;
2123                         y2 = (xev->xexpose.y + xev->xexpose.height -
2124                                  Infowin->oy)/Infofnt->hgt;
2125                         
2126                         Term_redraw_section(x1, y1, x2, y2);
2127
2128                         /* Redraw */
2129                         /*Term_redraw();*/
2130
2131                         break;
2132                 }
2133
2134                 case MapNotify:
2135                 {
2136                         Infowin->mapped = 1;
2137                         Term->mapped_flag = TRUE;
2138                         break;
2139                 }
2140
2141                 case UnmapNotify:
2142                 {
2143                         Infowin->mapped = 0;
2144                         Term->mapped_flag = FALSE;
2145                         break;
2146                 }
2147
2148                 /* Move and/or Resize */
2149                 case ConfigureNotify:
2150                 {
2151                         int cols, rows, wid, hgt;
2152
2153                         int ox = Infowin->ox;
2154                         int oy = Infowin->oy;
2155
2156                         /* Save the new Window Parms */
2157                         Infowin->x = xev->xconfigure.x;
2158                         Infowin->y = xev->xconfigure.y;
2159                         Infowin->w = xev->xconfigure.width;
2160                         Infowin->h = xev->xconfigure.height;
2161
2162                         /* Determine "proper" number of rows/cols */
2163                         cols = ((Infowin->w - (ox + ox)) / td->fnt->wid);
2164                         rows = ((Infowin->h - (oy + oy)) / td->fnt->hgt);
2165
2166                         /* Paranoia */
2167                         if (td == &data[0]) cols = 80;
2168                         if (td == &data[0]) rows = 24;
2169
2170                         /* Hack -- minimal size */
2171                         if (cols < 1) cols = 1;
2172                         if (rows < 1) rows = 1;
2173
2174                         /* Desired size of window */
2175                         wid = cols * td->fnt->wid + (ox + ox);
2176                         hgt = rows * td->fnt->hgt + (oy + oy);
2177
2178                         /* Resize the Term (if needed) */
2179                         Term_resize(cols, rows);
2180
2181                         /* Resize the windows if any "change" is needed */
2182                         if ((Infowin->w != wid) || (Infowin->h != hgt))
2183                         {
2184                                 /* Resize window */
2185                                 Infowin_set(td->win);
2186                                 Infowin_resize(wid, hgt);
2187                         }
2188
2189                         break;
2190                 }
2191 #ifdef USE_XIM
2192                 case FocusIn:
2193                 {
2194                         if(iwin->xic){
2195                                 XSetICFocus(iwin->xic);
2196                         }
2197                         Focuswin = iwin;
2198                         break;
2199                 }
2200                 case FocusOut:
2201                 {
2202                         if(iwin->xic){
2203                                 XUnsetICFocus(iwin->xic);
2204                         }
2205                         /* Focuswin = NULL;*/
2206                         break;
2207                 }
2208 #endif
2209         }
2210
2211
2212         /* Hack -- Activate the old term */
2213         Term_activate(&old_td->t);
2214
2215         /* Hack -- Activate the proper window */
2216         Infowin_set(old_td->win);
2217
2218
2219         /* Success */
2220         return (0);
2221 }
2222
2223
2224 /*
2225  * Handle "activation" of a term
2226  */
2227 static errr Term_xtra_x11_level(int v)
2228 {
2229         term_data *td = (term_data*)(Term->data);
2230
2231         /* Handle "activate" */
2232         if (v)
2233         {
2234                 /* Activate the window */
2235                 Infowin_set(td->win);
2236
2237                 /* Activate the font */
2238                 Infofnt_set(td->fnt);
2239 #ifdef _JP
2240                 Infokfnt_set(td->kfnt);
2241 #endif
2242         }
2243
2244         /* Success */
2245         return (0);
2246 }
2247
2248
2249 /*
2250  * React to changes
2251  */
2252 static errr Term_xtra_x11_react(void)
2253 {
2254         int i;
2255         
2256         if (Metadpy->color)
2257         {
2258                 /* Check the colors */
2259                 for (i = 0; i < 256; i++)
2260                 {
2261                         if ((color_table[i][0] != angband_color_table[i][0]) ||
2262                             (color_table[i][1] != angband_color_table[i][1]) ||
2263                             (color_table[i][2] != angband_color_table[i][2]) ||
2264                             (color_table[i][3] != angband_color_table[i][3]))
2265                         {
2266                                 Pixell pixel;
2267
2268                                 /* Save new values */
2269                                 color_table[i][0] = angband_color_table[i][0];
2270                                 color_table[i][1] = angband_color_table[i][1];
2271                                 color_table[i][2] = angband_color_table[i][2];
2272                                 color_table[i][3] = angband_color_table[i][3];
2273
2274                                 /* Create pixel */
2275                                 pixel = create_pixel(Metadpy->dpy,
2276                                                      color_table[i][1],
2277                                                      color_table[i][2],
2278                                                      color_table[i][3]);
2279
2280                                 /* Change the foreground */
2281                                 Infoclr_set(clr[i]);
2282                                 Infoclr_change_fg(pixel);
2283                         }
2284                 }
2285         }
2286
2287         /* Success */
2288         return (0);
2289 }
2290
2291
2292 /*
2293  * Handle a "special request"
2294  */
2295 static errr Term_xtra_x11(int n, int v)
2296 {
2297         /* Handle a subset of the legal requests */
2298         switch (n)
2299         {
2300                 /* Make a noise */
2301                 case TERM_XTRA_NOISE: Metadpy_do_beep(); return (0);
2302
2303                 /* Flush the output XXX XXX */
2304                 case TERM_XTRA_FRESH: Metadpy_update(1, 0, 0); return (0);
2305
2306                 /* Process random events XXX */
2307                 case TERM_XTRA_BORED: return (CheckEvent(0));
2308
2309                 /* Process Events XXX */
2310                 case TERM_XTRA_EVENT: return (CheckEvent(v));
2311
2312                 /* Flush the events XXX */
2313                 case TERM_XTRA_FLUSH: while (!CheckEvent(FALSE)); return (0);
2314
2315                 /* Handle change in the "level" */
2316                 case TERM_XTRA_LEVEL: return (Term_xtra_x11_level(v));
2317
2318                 /* Clear the screen */
2319                 case TERM_XTRA_CLEAR: Infowin_wipe(); return (0);
2320
2321                 /* Delay for some milliseconds */
2322                 case TERM_XTRA_DELAY: usleep(1000 * v); return (0);
2323
2324                 /* React to changes */
2325                 case TERM_XTRA_REACT: return (Term_xtra_x11_react());
2326         }
2327
2328         /* Unknown */
2329         return (1);
2330 }
2331
2332
2333 /*
2334  * Draw the cursor as an inverted rectangle.
2335  *
2336  * Consider a rectangular outline like "main-mac.c".  XXX XXX
2337  */
2338 static errr Term_curs_x11(int x, int y)
2339 {
2340         /* Draw the cursor */
2341         Infoclr_set(xor);
2342
2343         /* Hilite the cursor character */
2344         Infofnt_text_non(x, y, " ", 1);
2345
2346         /* Success */
2347         return (0);
2348 }
2349
2350
2351 /*
2352  * Erase some characters.
2353  */
2354 static errr Term_wipe_x11(int x, int y, int n)
2355 {
2356         /* Erase (use black) */
2357         Infoclr_set(clr[TERM_DARK]);
2358
2359         /* Mega-Hack -- Erase some space */
2360         Infofnt_text_non(x, y, "", n);
2361
2362         /* Success */
2363         return (0);
2364 }
2365
2366
2367 /*
2368  * Draw some textual characters.
2369  */
2370 static errr Term_text_x11(int x, int y, int n, byte a, cptr s)
2371 {
2372         /* Draw the text */
2373         Infoclr_set(clr[a]);
2374
2375         /* Draw the text */
2376         Infofnt_text_std(x, y, s, n);
2377
2378         /* Success */
2379         return (0);
2380 }
2381
2382
2383 #ifdef USE_GRAPHICS
2384
2385 /*
2386  * Draw some graphical characters.
2387  */
2388 # ifdef USE_TRANSPARENCY
2389 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
2390 # else /* USE_TRANSPARENCY */
2391 static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp)
2392 # endif /* USE_TRANSPARENCY */
2393 {
2394         int i, x1, y1;
2395
2396         byte a;
2397         char c;
2398
2399
2400 #ifdef USE_TRANSPARENCY
2401         byte ta;
2402         char tc;
2403
2404         int x2, y2;
2405         int k,l;
2406
2407         unsigned long pixel, blank;
2408 #endif /* USE_TRANSPARENCY */
2409
2410         term_data *td = (term_data*)(Term->data);
2411
2412         y *= Infofnt->hgt;
2413         x *= Infofnt->wid;
2414
2415         /* Add in affect of window boundaries */
2416         y += Infowin->oy;
2417         x += Infowin->ox;
2418
2419         for (i = 0; i < n; ++i)
2420         {
2421                 a = *ap++;
2422                 c = *cp++;
2423
2424                 /* For extra speed - cache these values */
2425                 x1 = (c&0x7F) * td->fnt->wid;
2426                 y1 = (a&0x7F) * td->fnt->hgt;
2427
2428 #ifdef USE_TRANSPARENCY
2429
2430                 ta = *tap++;
2431                 tc = *tcp++;
2432
2433                 /* For extra speed - cache these values */
2434                 x2 = (tc&0x7F) * td->fnt->wid;
2435                 y2 = (ta&0x7F) * td->fnt->hgt;
2436                 
2437                 /* Optimise the common case */
2438                 if ((x1 == x2) && (y1 == y2))
2439                 {
2440                         /* Draw object / terrain */
2441                         XPutImage(Metadpy->dpy, td->win->win,
2442                                 clr[0]->gc,
2443                                 td->tiles,
2444                                 x1, y1,
2445                                 x, y,
2446                                 td->fnt->wid, td->fnt->hgt);    
2447                 }
2448                 else
2449                 {
2450
2451                         /* Mega Hack^2 - assume the top left corner is "black" */
2452                         blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
2453
2454                         for (k = 0; k < td->fnt->wid; k++)
2455                         {
2456                                 for (l = 0; l < td->fnt->hgt; l++)
2457                                 {
2458                                         /* If mask set... */
2459                                         if ((pixel = XGetPixel(td->tiles, x1 + k, y1 + l)) == blank)
2460                                         {
2461                                                 /* Output from the terrain */
2462                                                 pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
2463                                         }
2464                                         
2465                                         /* Store into the temp storage. */
2466                                         XPutPixel(td->TmpImage, k, l, pixel);
2467                                 }
2468                         }
2469
2470
2471                         /* Draw to screen */
2472
2473                         XPutImage(Metadpy->dpy, td->win->win,
2474                               clr[0]->gc,
2475                              td->TmpImage,
2476                              0, 0, x, y,
2477                              td->fnt->wid, td->fnt->hgt);
2478                 }
2479
2480 #else /* USE_TRANSPARENCY */
2481
2482                 /* Draw object / terrain */
2483                 XPutImage(Metadpy->dpy, td->win->win,
2484                           clr[0]->gc,
2485                           td->tiles,
2486                           x1, y1,
2487                           x, y,
2488                           td->fnt->wid, td->fnt->hgt);
2489
2490 #endif /* USE_TRANSPARENCY */
2491                 x += td->fnt->wid;
2492         }
2493
2494         /* Success */
2495         return (0);
2496 }
2497
2498 #endif /* USE_GRAPHICS */
2499
2500 #ifdef USE_XIM
2501 static void IMDestroyCallback(XIM, XPointer, XPointer);
2502
2503 static void
2504 IMInstantiateCallback(Display *display, XPointer unused1, XPointer unused2)
2505 {
2506         XIM xim;
2507         XIMCallback ximcallback;
2508         XIMStyles *xim_styles = NULL;
2509         int i;
2510
2511         xim = XOpenIM(display, NULL, NULL, NULL);
2512         if(!xim){
2513                 printf("can't open IM\n");
2514                 return;
2515         }
2516
2517         /* initialize destroy callback */
2518         ximcallback.callback = IMDestroyCallback;
2519         ximcallback.client_data = NULL;
2520         XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL);
2521
2522         /* set style (only "Root" is supported yet...) */
2523         XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
2524         for (i = 0; i < xim_styles->count_styles; i++){
2525                 if(xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) break;
2526         }
2527         if(i >= xim_styles->count_styles){
2528                 printf("Sorry, your IM does not support 'Root' preedit style...\n");
2529                 XCloseIM(xim);
2530                 return;
2531         }
2532         XFree(xim_styles);
2533
2534         Metadpy->xim = xim;
2535
2536         for (i = 0; i < MAX_TERM_DATA; i++)
2537         {
2538                 infowin *iwin = data[i].win;
2539                 if (!iwin) continue;
2540                 iwin->xic = XCreateIC(xim, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, iwin->win, XNFocusWindow, iwin->win, NULL);
2541                 if(!iwin->xic){
2542                         printf("Can't create input context for Term%d\n", i);
2543                         continue;
2544                 }
2545                 if(XGetICValues(iwin->xic, XNFilterEvents, &iwin->xic_mask, NULL) != NULL){
2546 /*                      printf("Can't get XNFilterEvents\n"); */
2547                         iwin->xic_mask = 0L;
2548                 }
2549                 XSelectInput(Metadpy->dpy, iwin->win, iwin->mask | iwin->xic_mask);
2550         }
2551
2552         return;
2553 }
2554
2555 static void IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data)
2556 {
2557         int i;
2558
2559     if (call_data == NULL){
2560                 XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
2561         }
2562
2563         for(i = 0; i < MAX_TERM_DATA; i++)
2564         {
2565                 infowin *iwin = data[i].win;
2566                 if(!iwin) continue;
2567                 if(iwin->xic_mask){
2568                         XSelectInput(Metadpy->dpy, iwin->win, iwin->mask);
2569                         iwin->xic_mask = 0L;
2570                 }
2571                 iwin->xic = NULL;
2572         }
2573
2574         Metadpy->xim = NULL;
2575 }
2576 #endif
2577
2578 /*
2579  * Initialize a term_data
2580  */
2581 static errr term_data_init(term_data *td, int i)
2582 {
2583         term *t = &td->t;
2584
2585         bool fixed = (i == 0);
2586
2587         cptr name = angband_term_name[i];
2588
2589         cptr font;
2590 #ifdef _JP
2591         cptr kfont;
2592 #endif
2593
2594
2595         int x = 0;
2596         int y = 0;
2597
2598         int cols = 80;
2599         int rows = 24;
2600
2601         int ox = 1;
2602         int oy = 1;
2603
2604         int wid, hgt, num;
2605
2606         char buf[80];
2607
2608         cptr str;
2609
2610         int val;
2611
2612         XClassHint *ch;
2613
2614         char res_name[20];
2615         char res_class[20];
2616
2617         XSizeHints *sh;
2618 #ifdef USE_XIM
2619         XWMHints *wh;
2620 #endif
2621
2622         /* Window specific font name */
2623         sprintf(buf, "ANGBAND_X11_FONT_%d", i);
2624
2625         /* Check environment for that font */
2626         font = getenv(buf);
2627
2628         /* Check environment for "base" font */
2629         if (!font) font = getenv("ANGBAND_X11_FONT");
2630
2631         /* No environment variables, use default font */
2632         if (!font)
2633         {
2634                 switch (i)
2635                 {
2636                         case 0:
2637                         {
2638                                 font = DEFAULT_X11_FONT_0;
2639                         }
2640                         break;
2641                         case 1:
2642                         {
2643                                 font = DEFAULT_X11_FONT_1;
2644                         }
2645                         break;
2646                         case 2:
2647                         {
2648                                 font = DEFAULT_X11_FONT_2;
2649                         }
2650                         break;
2651                         case 3:
2652                         {
2653                                 font = DEFAULT_X11_FONT_3;
2654                         }
2655                         break;
2656                         case 4:
2657                         {
2658                                 font = DEFAULT_X11_FONT_4;
2659                         }
2660                         break;
2661                         case 5:
2662                         {
2663                                 font = DEFAULT_X11_FONT_5;
2664                         }
2665                         break;
2666                         case 6:
2667                         {
2668                                 font = DEFAULT_X11_FONT_6;
2669                         }
2670                         break;
2671                         case 7:
2672                         {
2673                                 font = DEFAULT_X11_FONT_7;
2674                         }
2675                         break;
2676                         default:
2677                         {
2678                                 font = DEFAULT_X11_FONT;
2679                         }
2680                 }
2681         }
2682
2683 #ifdef _JP
2684         /* Window specific font name */
2685         sprintf(buf, "ANGBAND_X11_KFONT_%d", i);
2686
2687         /* Check environment for that font */
2688         kfont = getenv(buf);
2689
2690         /* Check environment for "base" font */
2691         if (!kfont) kfont = getenv("ANGBAND_X11_KFONT");
2692
2693         /* No environment variables, use default font */
2694         if (!kfont)
2695         {
2696                 switch (i)
2697                 {
2698                         case 0:
2699                         {
2700                                 kfont = DEFAULT_X11_KFONT_0;
2701                         }
2702                         break;
2703                         case 1:
2704                         {
2705                                 kfont = DEFAULT_X11_KFONT_1;
2706                         }
2707                         break;
2708                         case 2:
2709                         {
2710                                 kfont = DEFAULT_X11_KFONT_2;
2711                         }
2712                         break;
2713                         case 3:
2714                         {
2715                                 kfont = DEFAULT_X11_KFONT_3;
2716                         }
2717                         break;
2718                         case 4:
2719                         {
2720                                 kfont = DEFAULT_X11_KFONT_4;
2721                         }
2722                         break;
2723                         case 5:
2724                         {
2725                                 kfont = DEFAULT_X11_KFONT_5;
2726                         }
2727                         break;
2728                         case 6:
2729                         {
2730                                 kfont = DEFAULT_X11_KFONT_6;
2731                         }
2732                         break;
2733                         case 7:
2734                         {
2735                                 kfont = DEFAULT_X11_KFONT_7;
2736                         }
2737                         break;
2738                         default:
2739                         {
2740                                 kfont = DEFAULT_X11_KFONT;
2741                         }
2742                 }
2743         }
2744 #endif
2745         /* Window specific location (x) */
2746         sprintf(buf, "ANGBAND_X11_AT_X_%d", i);
2747         str = getenv(buf);
2748         x = (str != NULL) ? atoi(str) : -1;
2749
2750         /* Window specific location (y) */
2751         sprintf(buf, "ANGBAND_X11_AT_Y_%d", i);
2752         str = getenv(buf);
2753         y = (str != NULL) ? atoi(str) : -1;
2754
2755
2756         if (!fixed)
2757         {
2758                 /* Window specific cols */
2759                 sprintf(buf, "ANGBAND_X11_COLS_%d", i);
2760                 str = getenv(buf);
2761                 val = (str != NULL) ? atoi(str) : -1;
2762                 if (val > 0) cols = val;
2763
2764                 /* Window specific rows */
2765                 sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
2766                 str = getenv(buf);
2767                 val = (str != NULL) ? atoi(str) : -1;
2768                 if (val > 0) rows = val;
2769         }
2770
2771
2772         /* Window specific inner border offset (ox) */
2773         sprintf(buf, "ANGBAND_X11_IBOX_%d", i);
2774         str = getenv(buf);
2775         val = (str != NULL) ? atoi(str) : -1;
2776         if (val > 0) ox = val;
2777
2778         /* Window specific inner border offset (oy) */
2779         sprintf(buf, "ANGBAND_X11_IBOY_%d", i);
2780         str = getenv(buf);
2781         val = (str != NULL) ? atoi(str) : -1;
2782         if (val > 0) oy = val;
2783
2784
2785         /* Prepare the standard font */
2786 #ifdef _JP
2787         MAKE(td->fnt, infofnt);
2788         Infofnt_set(td->fnt);
2789         MAKE(td->kfnt, infofnt);
2790         Infokfnt_set(td->kfnt);
2791         Infofnt_init_data(font, kfont);
2792 #else
2793         MAKE(td->fnt, infofnt);
2794         Infofnt_set(td->fnt);
2795         Infofnt_init_data(font);
2796 #endif
2797
2798
2799         /* Hack -- key buffer size */
2800         num = (fixed ? 1024 : 16);
2801
2802         /* Assume full size windows */
2803         wid = cols * td->fnt->wid + (ox + ox);
2804         hgt = rows * td->fnt->hgt + (oy + oy);
2805
2806         /* Create a top-window */
2807         MAKE(td->win, infowin);
2808         Infowin_set(td->win);
2809         Infowin_init_top(x, y, wid, hgt, 0,
2810                          Metadpy->fg, Metadpy->bg);
2811
2812         /* Ask for certain events */
2813 #if defined(USE_XIM)
2814 #if 0
2815         /* XIM ¤¬Í­¸ú¤Ê¤Î¤Ï¥á¥¤¥ó¥¦¥£¥ó¥É¥¦¤Î¤ß¤Ê¤Î¤Ç¡¢¼óÈø¤ò°ì´Ó¤µ¤»¤ë¤¿¤á
2816            Ä̾ï¤Î¥­¡¼ÆþÎϤâ̵¸ú¤Ë¤¹¤ë */
2817         if(i == 0){
2818                 Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask);
2819         }else{
2820                 Infowin_set_mask(ExposureMask | StructureNotifyMask);
2821         }
2822 #else
2823         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask | FocusChangeMask);
2824 #endif
2825 #else
2826         Infowin_set_mask(ExposureMask | StructureNotifyMask | KeyPressMask);
2827 #endif
2828
2829         /* Set the window name */
2830         Infowin_set_name(name);
2831
2832         /* Save the inner border */
2833         Infowin->ox = ox;
2834         Infowin->oy = oy;
2835
2836         /* Make Class Hints */
2837         ch = XAllocClassHint();
2838
2839         if (ch == NULL) quit("XAllocClassHint failed");
2840
2841         strcpy(res_name, name);
2842         res_name[0] = FORCELOWER(res_name[0]);
2843         ch->res_name = res_name;
2844
2845         strcpy(res_class, "Angband");
2846         ch->res_class = res_class;
2847
2848         XSetClassHint(Metadpy->dpy, Infowin->win, ch);
2849
2850         /* Make Size Hints */
2851         sh = XAllocSizeHints();
2852
2853         /* Oops */
2854         if (sh == NULL) quit("XAllocSizeHints failed");
2855
2856         /* Fixed window size */
2857         if (fixed)
2858         {
2859                 /* Fixed size */
2860                 sh->flags = PMinSize | PMaxSize;
2861                 sh->min_width = sh->max_width = wid;
2862                 sh->min_height = sh->max_height = hgt;
2863         }
2864
2865         /* Variable window size */
2866         else
2867         {
2868                 /* Variable size */
2869                 sh->flags = PMinSize | PMaxSize;
2870                 sh->min_width = td->fnt->wid + (ox + ox);
2871                 sh->min_height = td->fnt->hgt + (oy + oy);
2872                 sh->max_width = 256 * td->fnt->wid + (ox + ox);
2873                 sh->max_height = 256 * td->fnt->hgt + (oy + oy);
2874         }
2875
2876         /* Resize increment */
2877         sh->flags |= PResizeInc;
2878         sh->width_inc = td->fnt->wid;
2879         sh->height_inc = td->fnt->hgt;
2880
2881         /* Base window size */
2882         sh->flags |= PBaseSize;
2883         sh->base_width = (ox + ox);
2884         sh->base_height = (oy + oy);
2885
2886         /* Use the size hints */
2887         XSetWMNormalHints(Metadpy->dpy, Infowin->win, sh);
2888
2889         /* Map the window */
2890         Infowin_map();
2891
2892 #ifdef USE_XIM
2893         /* Make WM Hints */
2894         wh = XAllocWMHints();
2895         if(wh == NULL) quit("XAllocWMHints failed");
2896         wh->flags = InputHint;
2897         wh->input = True;
2898         XSetWMHints(Metadpy->dpy, Infowin->win, wh);
2899 #endif
2900
2901         /* Move the window to requested location */
2902         if ((x >= 0) && (y >= 0)) Infowin_impell(x, y);
2903
2904
2905         /* Initialize the term */
2906         term_init(t, cols, rows, num);
2907
2908         /* Use a "soft" cursor */
2909         t->soft_cursor = TRUE;
2910
2911         /* Erase with "white space" */
2912         t->attr_blank = TERM_WHITE;
2913         t->char_blank = ' ';
2914
2915         /* Hooks */
2916         t->xtra_hook = Term_xtra_x11;
2917         t->curs_hook = Term_curs_x11;
2918         t->wipe_hook = Term_wipe_x11;
2919         t->text_hook = Term_text_x11;
2920
2921         /* Save the data */
2922         t->data = td;
2923
2924         /* Activate (important) */
2925         Term_activate(t);
2926
2927         /* Success */
2928         return (0);
2929 }
2930
2931
2932 /*
2933  * Initialization function for an "X11" module to Angband
2934  */
2935 errr init_x11(int argc, char *argv[])
2936 {
2937         int i;
2938
2939         cptr dpy_name = "";
2940
2941         int num_term = MAX_TERM_DATA;
2942
2943 #ifdef USE_GRAPHICS
2944
2945         char filename[1024];
2946
2947         int pict_wid = 0;
2948         int pict_hgt = 0;
2949
2950 #ifdef USE_TRANSPARENCY
2951
2952         char *TmpData;
2953 #endif /* USE_TRANSPARENCY */
2954
2955 #endif /* USE_GRAPHICS */
2956
2957
2958         /* Parse args */
2959         for (i = 1; i < argc; i++)
2960         {
2961                 if (prefix(argv[i], "-d"))
2962                 {
2963                         dpy_name = &argv[i][2];
2964                         continue;
2965                 }
2966                 
2967 #ifdef USE_GRAPHICS
2968                 if (prefix(argv[i], "-s"))
2969                 {
2970                         smoothRescaling = FALSE;
2971                         continue;
2972                 }
2973 #endif /* USE_GRAPHICS */
2974
2975                 if (prefix(argv[i], "-n"))
2976                 {
2977                         num_term = atoi(&argv[i][2]);
2978                         if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
2979                         else if (num_term < 1) num_term = 1;
2980                         continue;
2981                 }
2982
2983                 plog_fmt("Ignoring option: %s", argv[i]);
2984         }
2985
2986 #ifdef USE_LOCALE
2987         setlocale(LC_ALL, "");
2988 #ifdef DEFAULT_LOCALE
2989         if(!strcmp(setlocale(LC_ALL, NULL), "C")){
2990                 printf("try default locale \"%s\"\n", DEFAULT_LOCALE);
2991                 setlocale(LC_ALL, DEFAULT_LOCALE);
2992         }
2993 #endif
2994         {
2995                 char *current_locale = setlocale(LC_ALL, NULL);
2996 /*              printf("set locale to \"%s\"\n", current_locale); */
2997                 if(!strcmp(current_locale, "C")){
2998                         printf("WARNING: Locale is not supported. Non-english font may be displayed incorrectly.\n");
2999                 }
3000         }
3001
3002         if(!XSupportsLocale()){
3003                 printf("can't support locale in X\n");
3004                 setlocale(LC_ALL, "C");
3005         }
3006 #endif /* USE_LOCALE */
3007
3008
3009         /* Init the Metadpy if possible */
3010         if (Metadpy_init_name(dpy_name)) return (-1);
3011
3012
3013         /* Prepare cursor color */
3014         MAKE(xor, infoclr);
3015         Infoclr_set(xor);
3016         Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
3017
3018
3019         /* Prepare normal colors */
3020         for (i = 0; i < 256; ++i)
3021         {
3022                 Pixell pixel;
3023
3024                 MAKE(clr[i], infoclr);
3025
3026                 Infoclr_set(clr[i]);
3027
3028                 /* Acquire Angband colors */
3029                 color_table[i][0] = angband_color_table[i][0];
3030                 color_table[i][1] = angband_color_table[i][1];
3031                 color_table[i][2] = angband_color_table[i][2];
3032                 color_table[i][3] = angband_color_table[i][3];
3033
3034                 /* Default to monochrome */
3035                 pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg);
3036
3037                 /* Handle color */
3038                 if (Metadpy->color)
3039                 {
3040                         /* Create pixel */
3041                         pixel = create_pixel(Metadpy->dpy,
3042                                              color_table[i][1],
3043                                              color_table[i][2],
3044                                              color_table[i][3]);
3045                 }
3046
3047                 /* Initialize the color */
3048                 Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0);
3049         }
3050
3051
3052         /* Initialize the windows */
3053         for (i = 0; i < num_term; i++)
3054         {
3055                 term_data *td = &data[i];
3056
3057                 /* Initialize the term_data */
3058                 term_data_init(td, i);
3059
3060                 /* Save global entry */
3061                 angband_term[i] = Term;
3062         }
3063
3064         /* Raise the "Angband" window */
3065         Infowin_set(data[0].win);
3066         Infowin_raise();
3067
3068         /* Activate the "Angband" window screen */
3069         Term_activate(&data[0].t);
3070
3071 #ifdef USE_XIM
3072         {
3073                 char *p;
3074                 p = XSetLocaleModifiers("");
3075                 if(!p || !*p){
3076                         p = XSetLocaleModifiers("@im=");
3077                 }
3078 /*              printf("XMODIFIERS=\"%s\"\n", p); */
3079         }
3080         XRegisterIMInstantiateCallback(Metadpy->dpy, NULL, NULL, NULL, IMInstantiateCallback, NULL);
3081 #endif
3082
3083 #ifdef USE_GRAPHICS
3084
3085         /* Try graphics */
3086         if (arg_graphics)
3087         {
3088                 /* Try the "16x16.bmp" file */
3089                 path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/16x16.bmp");
3090
3091                 /* Use the "16x16.bmp" file if it exists */
3092                 if (0 == fd_close(fd_open(filename, O_RDONLY)))
3093                 {
3094                         /* Use graphics */
3095                         use_graphics = TRUE;
3096
3097                         use_transparency = TRUE;
3098
3099                         pict_wid = pict_hgt = 16;
3100
3101                         ANGBAND_GRAF = "new";
3102                 }
3103                 else
3104                 {
3105                         /* Try the "8x8.bmp" file */
3106                         path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/8x8.bmp");
3107
3108                         /* Use the "8x8.bmp" file if it exists */
3109                         if (0 == fd_close(fd_open(filename, O_RDONLY)))
3110                         {
3111                                 /* Use graphics */
3112                                 use_graphics = TRUE;
3113
3114                                 pict_wid = pict_hgt = 8;
3115
3116                                 ANGBAND_GRAF = "old";
3117                         }
3118                 }
3119         }
3120
3121         /* Load graphics */
3122         if (use_graphics)
3123         {
3124                 Display *dpy = Metadpy->dpy;
3125
3126                 XImage *tiles_raw;
3127
3128                 /* Load the graphical tiles */
3129                 tiles_raw = ReadBMP(dpy, filename);
3130
3131                 /* Initialize the windows */
3132                 for (i = 0; i < num_term; i++)
3133                 {
3134                         term_data *td = &data[i];
3135
3136                         term *t = &td->t;
3137
3138                         /* Graphics hook */
3139                         t->pict_hook = Term_pict_x11;
3140
3141                         /* Use graphics sometimes */
3142                         t->higher_pict = TRUE;
3143
3144                         /* Resize tiles */
3145                         td->tiles =
3146                         ResizeImage(dpy, tiles_raw,
3147                                     pict_wid, pict_hgt,
3148                                     td->fnt->wid, td->fnt->hgt);
3149                 }
3150
3151 #ifdef USE_TRANSPARENCY
3152                 /* Initialize the transparency masks */
3153                 for (i = 0; i < num_term; i++)
3154                 {
3155                         term_data *td = &data[i];
3156                         int ii, jj;
3157                         int depth = DefaultDepth(dpy, DefaultScreen(dpy));
3158                         Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
3159                         int total;
3160
3161
3162                         /* Determine total bytes needed for image */
3163                         ii = 1;
3164                         jj = (depth - 1) >> 2;
3165                         while (jj >>= 1) ii <<= 1;
3166                         total = td->fnt->wid * td->fnt->hgt * ii;
3167                         
3168                         
3169                         TmpData = (char *)malloc(total);
3170
3171                         td->TmpImage = XCreateImage(dpy,visual,depth,
3172                                 ZPixmap, 0, TmpData,
3173                                 td->fnt->wid, td->fnt->hgt, 8, 0);
3174
3175                 }
3176 #endif /* USE_TRANSPARENCY */
3177
3178
3179                 /* Free tiles_raw? XXX XXX */
3180         }
3181
3182 #endif /* USE_GRAPHICS */
3183
3184
3185         /* Success */
3186         return (0);
3187 }
3188
3189 #endif /* USE_X11 */
3190