1 /* x11window.c
2  *
3  * Kevin P. Smith  6/11/89 Much modified by Jerry Frain and Joe Young
4  *
5  */
6 
7 #define DEBUG 0
8 
9 #include "config.h"
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 #include INC_SYS_SELECT
16 #include INC_STRINGS
17 #include <X11/Xlib.h>
18 #include <X11/Xutil.h>
19 #include <X11/cursorfont.h>
20 #include <X11/Xatom.h>
21 #include <X11/keysym.h>
22 #include <assert.h>
23 #include <time.h>
24 #include <sys/time.h>
25 #include INC_SYS_TIMEB
26 #include "Wlib.h"
27 #include "defs.h"
28 #include "struct.h"
29 #include "data.h"
30 #include "teams.bitmap"
31 #include "mapcursor.bitmap"
32 #include "localcursor.bitmap"
33 #include "smessage.h"
34 #include "defaults.h"
35 #include "x11window.h"
36 #include "x11sprite.h"
37 #include "camera.h"
38 
39 extern void terminate(int error);
40 
41 /* XFIX speedup */
42 #define MAXCACHE        128
43 #define MAX_TEXT_WIDTH	100
44 
45 /* changes too good to risk leaving out, by Richard Caley (rjc@cstr.ed.ac.uk) */
46 /* Was #ifdef RJC, but now they're just part of the code                    */
47 
48 #define FONT_SMALL "5x7"
49 #define FONT_NORMAL "6x10"
50 #define FONT_BOLD "-*-clean-bold-r-normal--10-100-75-75-c-60-*"
51 #define FONT_ITALIC "-*-clean-bold-r-normal--10-100-75-75-c-60-*"
52 #define FONT_INDEPENDENT "-*-clean-bold-r-normal--10-100-75-75-c-60-*"
53 #define FONT_BIG         "-*-lucidatypewriter-*-*-*-*-40-*-*-*-*-*-*-*"
54 int     forceMono = 0;
55 
56 
57 #ifdef BEEPLITE
58 #define TTS_FONT        "10x20"
59 extern void init_tts(void);
60 
61 #endif
62 
63 #define G_SET_WIDTH     0x1
64 #define G_SET_HEIGHT    0x2
65 #define G_SET_X         0x4
66 #define G_SET_Y         0x8
67 
68 
69 static char *_nfonts[] =
70 {
71   FONT_NORMAL,
72   "-*-clean-medium-r-normal--10-100-75-75-c-60-*",
73   "fixed",
74   NULL,
75 };
76 static char *_bfonts[] =
77 {
78   FONT_BOLD,
79   "-*-clean-bold-r-normal--10-100-75-75-c-60-*",
80   "fixed",
81   NULL,
82 };
83 static char *_ifonts[] =
84 {
85   FONT_ITALIC,
86   "-*-clean-bold-r-normal--10-100-75-75-c-60-*",
87   "fixed",
88   NULL,
89 };
90 static char *_bgfonts[] =
91 {
92   FONT_BIG,
93   "fixed",
94   "fixed",
95   NULL,
96 };
97 XFontStruct *find_font(char *oldf, char **fonts);
98 
99 #define FONTS 4
100 #define BITGC 4
101 
102 #define WHITE   0
103 #define BLACK   1
104 #define RED     2
105 #define GREEN   3
106 #define YELLOW  4
107 #define CYAN    5
108 #define GREY    6
109 
110 #ifdef RACE_COLORS
111 #define C_ROM   7
112 #define C_KLI   8
113 #define C_FED   9
114 #define C_ORI   10
115 #define C_IND   11
116 #endif
117 
118 #ifdef RACE_COLORS
119 #define COLORS  16
120 #define PLANES  4
121 #else
122 #define COLORS  8
123 #define PLANES  3
124 #endif
125 
126 #define RaceDefaultOffset (C_ROM - RED)
127 
128 extern int takeNearest;
129 
130 static int zero = 0;
131 static int one = 1;
132 static int two = 2;
133 static int three = 3;
134 
135 
136 int     W_FastClear = 0;
137 Window  W_Root;
138 Colormap W_Colormap;
139 int     W_Screen;
140 
141 Visual *W_Visual;
142 
143 W_Font  W_BigFont = (W_Font) & zero, W_RegularFont = (W_Font) & one;
144 W_Font  W_HighlightFont = (W_Font) & two, W_UnderlineFont = (W_Font) & three;
145 Display *W_Display;
146 W_Color W_White = WHITE, W_Black = BLACK, W_Red = RED, W_Green = GREEN;
147 W_Color W_Yellow = YELLOW, W_Cyan = CYAN, W_Grey = GREY;
148 
149 #ifdef RACE_COLORS
150 W_Color W_Ind = C_IND, W_Fed = C_FED, W_Rom = C_ROM, W_Kli = C_KLI, W_Ori = C_ORI;
151 
152 #endif
153 int     W_BigTextwidth, W_BigTextheight, W_Textwidth, W_Textheight;
154 char   *getdefault(char *str);
155 
156 int     W_in_message = 0;			 /* jfy -- for Jerry's warp *
157 
158 						  *
159 						  *
160 						  * * message hack */
161 
162 /* TTS: moved this out so we can use the 8th color */
163 
164 static unsigned long planes[PLANES];
165 
166 /* Scrollable message windows */
167 #define SCROLL_THUMB_WIDTH	5
168 static int scrollbar = 1;
169 static int scroll_thumb_width = SCROLL_THUMB_WIDTH;
170 static GC scroll_thumb_gc;
171 static Pixmap scroll_thumb_pixmap;
172 static int scroll_lines = 100;			 /* save 100 lines */
173 
174 Atom wm_protocols, wm_delete_window;
175 
176 extern W_Window baseWin;
177 static XClassHint class_hint =
178 {
179   "netrek", "Netrek",
180 };
181 
182 static XWMHints wm_hint =
183 {
184   InputHint | StateHint,
185   True,
186   NormalState,
187   None,
188   None,
189   0, 0,
190   None,
191   None,
192 };
193 
194 #ifdef WINDOWMAKER
195   char **wm_argv;
196   int wm_argc;
197 #endif
198 
199 static W_Event W_myevent;
200 static int W_isEvent = 0; /* an event is being held here for the caller */
201 
202 struct fontInfo
203   {
204     int     baseline;
205   };
206 
207 struct colors
208   {
209     char   *name;
210     GC      contexts[FONTS + 1];
211     GC      insens_contexts[FONTS + 1];
212     Pixmap  pixmap;
213     int     pixelValue;
214   };
215 
216 Pixmap  insens_tile;
217 
218 struct icon
219   {
220     Window  window;
221     Pixmap  bitmap;
222     int     width, height;
223     Pixmap  pixmap;
224   };
225 
226 #define WIN_GRAPH       1
227 #define WIN_TEXT        2
228 #define WIN_MENU        3
229 #define WIN_SCROLL      4
230 
231 static void changeMenuItem(struct window *win, int col, int n, char *str, W_Color color);
232 static void scrollUp(struct window *win, int y);
233 static void scrollDown(struct window *win, int y);
234 static void scrollPosition(struct window *win, int y);
235 static void scrollTo(struct window *win, struct scrollingWindow *sw, int topline);
236 static void scrollScrolling(W_Event * wevent);
237 static void configureScrolling(struct window *win, int x, int y, int width, int height);
238 static void AddToScrolling(struct window *win, W_Color color, W_Font font, char *str, int len);
239 static void drawThumb(struct window *win, struct scrollingWindow *sw);
240 static void redrawScrolling(struct window *win);
241 static int checkGeometry(char *name, int *x, int *y, int *width, int *height);
242 
243 struct stringList
244   {
245     char    string[MAX_TEXT_WIDTH];
246     W_Color color;
247     W_Font  font;
248     struct stringList *next, *prev;
249   };
250 
251 struct menuItem
252   {
253     int     column;
254     char   *string;
255     W_Color color;
256   };
257 
258 struct colors colortable[] =
259 {
260   {"white"},
261   {"black"},
262   {"red"},
263   {"green"},
264   {"yellow"},
265   {"cyan"},
266   {"dark grey"}
267 
268 #ifdef RACE_COLORS
269   ,
270   {"Rom"},
271   {"Kli"},
272   {"Fed"},
273   {"Ori"},
274   {"Ind"}
275 #endif
276 
277 };
278 
279 struct windowlist
280   {
281     struct window *window;
282     struct windowlist *next;
283   };
284 
285 #define HASHSIZE 101
286 #define hash(x) (((int) (x)) % HASHSIZE)
287 
288 struct windowlist *hashtable[HASHSIZE];
289 struct fontInfo fonts[FONTS];
290 
291 struct window *newWindow(Window window, int type);
292 struct window *findWindow(Window window);
293 
294 /* char *malloc (size_t); */
295 short  *x11tox10bits();
296 
297 struct window myroot;
298 
299 #define NCOLORS (sizeof(colortable)/sizeof(colortable[0]))
300 #define W_Void2Window(win) ((win) ? ((struct window *) (win)) : (&myroot))
301 #define W_Window2Void(window) ((W_Window) (window))
302 #define W_Void2Icon(bit) ((struct icon *) (bit))
303 #define W_Icon2Void(bit) ((W_Icon) (bit))
304 #define fontNum(font) (*((int *) font))
305 #define TILESIDE 16
306 
307 #define WIN_EDGE 5				 /* border on l/r edges of *
308 						  * * text windows */
309 #define MENU_PAD 6				 /* border on t/b edges of *
310 						  * * text windows */
311 #define MENU_BAR 1				 /* width of menu bar */
312 
313 static char gray[] =
314 {
315   0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
316   0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
317   0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
318   0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55
319 };
320 
321 static char striped[] =
322 {
323   0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
324   0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
325   0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
326   0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0
327 };
328 
329 static char solid[] =
330 {
331   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
332   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
333   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
334   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
335 };
336 
337 int full_screen_default, full_screen_enabled;
338 
339 #ifdef FULLSCREEN
340 static void video_mode_off(void);
341 static int video_mode_initialise(void);
342 static void video_mode_on(void);
343 static void view_port_warp(W_Window window);
344 static void pointer_grab_on(W_Window window);
345 static void pointer_grab_off(W_Window window);
346 static void kde_fullscreen_on(W_Window window);
347 static void kde_fullscreen_off(W_Window window);
348 #endif
349 
350 /* X debugging */
351 int
_myerror(Display * d,XErrorEvent * e)352         _myerror(Display * d, XErrorEvent * e)
353 {
354   fprintf(stderr, "netrek: x11window: _myerror\n");
355   abort();
356 }
357 
pastebuffer(void)358 void pastebuffer(void)
359 {
360   int     nbytes, x;
361   char   *buff, c;
362 
363   buff = XFetchBuffer(W_Display, &nbytes, 0);
364   for (x = 0; x < nbytes; x++)
365     {
366       c = buff[x];
367       smessage(c);
368     }
369 }
370 
371 static long
WMXYHintMode_default(void)372         WMXYHintMode_default(void)
373 {
374   static int fetched = 0;
375   static long WMXYHM_default;
376   char   *hm_default_string;
377 
378   if (!fetched)
379     {
380       hm_default_string = getdefault("WMXYHintMode");
381       if (!hm_default_string || strcmp(hm_default_string, "USPosition") == 0)
382 	WMXYHM_default = USPosition;
383       else
384 	WMXYHM_default = PPosition;
385       fetched = 1;
386     }
387   return WMXYHM_default;
388 }
389 
390 
391 void
W_Initialize(char * str)392         W_Initialize(char *str)
393 {
394   int     i;
395 
396 #if DEBUG > 0
397   printf("Initializing...\n");
398 #endif
399 
400   for (i = 0; i < HASHSIZE; i++)
401     {
402       hashtable[i] = NULL;
403     }
404   if ((W_Display = XOpenDisplay(str)) == NULL)
405     {
406       fprintf(stderr, "I can't open your display, twink!\n");
407       terminate(1);
408     }
409 
410   /* prevent X socket from being copied to forked exec'd process */
411   if (fcntl(ConnectionNumber(W_Display), F_SETFD, FD_CLOEXEC) < 0)
412     {
413       fprintf(stderr, "failed to set the X socket to close on exec(),\n"
414               "fcntl F_SETFD FD_CLOEXEC failure,\n'%s'",
415               strerror(errno));
416     }
417 
418   // uncomment this to synchronise display for testing
419   // XSynchronize(W_Display, True);
420 
421   // uncomment this to enable a fatal error handler
422   // XSetErrorHandler(_myerror);
423 
424   wm_protocols = XInternAtom(W_Display, "WM_PROTOCOLS", False);
425   wm_delete_window = XInternAtom(W_Display, "WM_DELETE_WINDOW", False);
426 
427   W_Root = DefaultRootWindow(W_Display);
428   W_Visual = DefaultVisual(W_Display, DefaultScreen(W_Display));
429   W_Screen = DefaultScreen(W_Display);
430   W_Colormap = DefaultColormap(W_Display, W_Screen);
431   myroot.window = W_Root;
432   myroot.type = WIN_GRAPH;
433   GetFonts();
434   GetColors();
435 
436   /* display scroll thumb */
437   scrollbar = booleanDefault("ScrollBar", scrollbar);
438   scroll_lines = intDefault("ScrollSaveLines", scroll_lines);
439   scroll_thumb_width = intDefault("ScrollBarWidth", scroll_thumb_width);
440 
441 #ifdef BEEPLITE
442   init_tts();
443 #endif
444 }
445 
W_GetPixmaps(W_Window t,W_Window g)446 void W_GetPixmaps(W_Window t, W_Window g)
447 {
448   GetPixmaps(W_Display, &myroot, t, g);
449 }
450 
451 /* Make sure the font will work, ie: that it fits in the 6x10 character cell
452  * that we expect. */
checkFont(XFontStruct * fontinfo,char * fontname)453 void checkFont(XFontStruct * fontinfo, char *fontname)
454 {
455   if (small_screen) return;
456   if (fontinfo->max_bounds.width != 6 ||
457       fontinfo->min_bounds.width != 6 ||
458       fontinfo->descent + fontinfo->ascent != 10 ||
459       fontinfo->min_bounds.lbearing < 0 ||
460       fontinfo->max_bounds.rbearing > 6 ||
461       fontinfo->max_bounds.ascent > 8 ||
462       fontinfo->max_bounds.descent > 2) {
463     fprintf(stderr, "Warning: font '%s'\ndoes not conform to 6x10 character cell rules.\n", fontname);
464   }
465 }
466 
GetFonts(void)467 void GetFonts(void)
468 {
469   Font    regular, italic, bold, big;
470   int     i;
471   XGCValues values;
472   XFontStruct *fontinfo;
473   char   *fontname;
474   int     black, white;
475 
476   fontname = getdefault("font");
477   if (fontname == NULL)
478     fontname = small_screen ? FONT_SMALL : FONT_NORMAL;
479   fontinfo = XLoadQueryFont(W_Display, fontname);
480   if (fontinfo == NULL)
481     {
482       fontinfo = find_font(fontname, _nfonts);
483     }
484   if (fontinfo == NULL)
485     {
486       printf("netrek: Can't find any fonts!\n");
487       terminate(1);
488     }
489   checkFont(fontinfo, fontname);
490   regular = fontinfo->fid;
491   W_Textwidth = fontinfo->max_bounds.width;
492   W_Textheight = fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent;
493   fonts[1].baseline = fontinfo->max_bounds.ascent;
494 
495   fontname = getdefault("boldfont");
496   if (fontname == NULL)
497     fontname = small_screen ? FONT_SMALL : FONT_BOLD;
498   fontinfo = XLoadQueryFont(W_Display, fontname);
499   if (fontinfo == NULL)
500     {
501       fontinfo = find_font(fontname, _bfonts);
502     }
503   if (fontinfo == NULL)
504     {
505       bold = regular;
506       fonts[2].baseline = fonts[1].baseline;
507     }
508   else
509     {
510       checkFont(fontinfo, fontname);
511       bold = fontinfo->fid;
512       fonts[2].baseline = fontinfo->max_bounds.ascent;
513       if (fontinfo->max_bounds.width > W_Textwidth)
514 	W_Textwidth = fontinfo->max_bounds.width;
515       if (fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent > W_Textheight)
516 	W_Textheight = fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent;
517     }
518 
519   fontname = getdefault("italicfont");
520   if (fontname == NULL)
521     fontname = small_screen ? FONT_SMALL : FONT_ITALIC;
522   fontinfo = XLoadQueryFont(W_Display, fontname);
523   if (fontinfo == NULL)
524     {
525       fontinfo = find_font(fontname, _ifonts);
526     }
527   if (fontinfo == NULL)
528     {
529       italic = regular;
530       fonts[3].baseline = fonts[1].baseline;
531     }
532   else
533     {
534       checkFont(fontinfo, fontname);
535       italic = fontinfo->fid;
536       fonts[3].baseline = fontinfo->max_bounds.ascent;
537       if (fontinfo->max_bounds.width > W_Textwidth)
538 	W_Textwidth = fontinfo->max_bounds.width;
539       if (fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent > W_Textheight)
540 	W_Textheight = fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent;
541     }
542 
543   fontname = getdefault("bigfont");
544   if (fontname == NULL)
545     fontname = small_screen ? FONT_SMALL : FONT_BIG;
546   fontinfo = XLoadQueryFont(W_Display, fontname);
547   if (fontinfo == NULL)
548     {
549       fontinfo = find_font(fontname, _bgfonts);
550     }
551   if (fontinfo == NULL)
552     {
553       big = regular;
554       fonts[0].baseline = fonts[1].baseline;
555       W_BigTextwidth = W_Textwidth;
556       W_BigTextheight = W_Textheight;
557     }
558   else
559     {
560       big = fontinfo->fid;
561       fonts[0].baseline = fontinfo->max_bounds.ascent;
562       W_BigTextwidth = fontinfo->max_bounds.width;
563       W_BigTextheight = fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent;
564     }
565   white = WhitePixel(W_Display, W_Screen);
566   black = BlackPixel(W_Display, W_Screen);
567   insens_tile = XCreatePixmapFromBitmapData(W_Display, W_Root, gray,
568        TILESIDE, TILESIDE, black, white, DefaultDepth(W_Display, W_Screen));
569   for (i = 0; i < NCOLORS; i++)
570     {
571       values.font = big;
572       colortable[i].contexts[0] = XCreateGC(W_Display, W_Root, GCFont, &values);
573       XSetGraphicsExposures(W_Display, colortable[i].contexts[0], False);
574       values.font = regular;
575       colortable[i].contexts[1] = XCreateGC(W_Display, W_Root, GCFont, &values);
576       XSetGraphicsExposures(W_Display, colortable[i].contexts[1], False);
577 
578       values.fill_style = FillTiled;
579       values.tile = insens_tile;
580       colortable[i].insens_contexts[1] = XCreateGC(W_Display, W_Root,
581 				    GCFont | GCFillStyle | GCTile, &values);
582       XSetGraphicsExposures(W_Display, colortable[i].insens_contexts[1],
583 			    False);
584       values.font = bold;
585       colortable[i].contexts[2] = XCreateGC(W_Display, W_Root, GCFont, &values);
586       XSetGraphicsExposures(W_Display, colortable[i].contexts[2], False);
587       values.font = italic;
588       colortable[i].contexts[3] = XCreateGC(W_Display, W_Root, GCFont, &values);
589       XSetGraphicsExposures(W_Display, colortable[i].contexts[3], False);
590       {
591 	char dl[] = {1, 8};
592 
593 	XSetLineAttributes(W_Display, colortable[i].contexts[3],
594 			   0, LineOnOffDash, CapButt, JoinMiter);
595 	XSetDashes(W_Display, colortable[i].contexts[3], 0, dl, 2);
596       }
597       values.function = GXor;
598       colortable[i].contexts[BITGC] = XCreateGC(W_Display, W_Root, GCFunction,
599 						&values);
600       XSetGraphicsExposures(W_Display, colortable[i].contexts[BITGC], False);
601     }
602 }
603 XFontStruct *
find_font(char * oldf,char ** fonts)604         find_font(char *oldf, char **fonts)
605 {
606   XFontStruct *fi;
607   char  **f;
608 
609   fprintf(stderr, "netrek: Can't find font %s.  Trying others...\n",
610 	  oldf);
611   for (f = fonts; *f; f++)
612     {
613       if (strcmp(*f, oldf) != 0)
614 	{
615 	  if ((fi = XLoadQueryFont(W_Display, *f)))
616 	    return fi;
617 	}
618     }
619   return NULL;
620 }
621 
622 static unsigned short extrared[COLORS] =
623 {0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xb0, 0xc0};
624 static unsigned short extragreen[COLORS] =
625 {0x40, 0x60, 0x80, 0xa0, 0xb0, 0xc0, 0x00, 0x20};
626 static unsigned short extrablue[COLORS] =
627 {0x80, 0xa0, 0xb0, 0xc0, 0x00, 0x20, 0x40, 0x60};
628 
629 
GetColors(void)630 void GetColors(void)
631 {
632   int     i, j;
633   XGCValues values;
634   XColor  foo;
635   int     white, black;
636   unsigned long pixel;
637   char    defaultstring[100];
638   char   *defaults;
639   unsigned long extracolors[COLORS];
640   XColor  colordef;
641 
642 
643   forceMono = booleanDefault("forcemono", forceMono);	/* 11/14/91 TC */
644 
645   if ((DisplayCells(W_Display, W_Screen) <= 2) || forceMono)
646     {
647       white = WhitePixel(W_Display, W_Screen);
648       black = BlackPixel(W_Display, W_Screen);
649       for (i = 0; i < NCOLORS; i++)
650 	{
651 	  if (i != W_Black)
652 	    {
653 	      colortable[i].pixelValue = white;
654 	    }
655 	  else
656 	    {
657 	      colortable[i].pixelValue = black;
658 	    }
659 	  if (i == W_Red)
660 	    {
661 	      colortable[i].pixmap = XCreatePixmapFromBitmapData(W_Display,
662 			  W_Root, striped, TILESIDE, TILESIDE, white, black,
663 					 DefaultDepth(W_Display, W_Screen));
664 	    }
665 	  else if (i == W_Yellow)
666 	    {
667 	      colortable[i].pixmap = XCreatePixmapFromBitmapData(W_Display,
668 			     W_Root, gray, TILESIDE, TILESIDE, white, black,
669 					 DefaultDepth(W_Display, W_Screen));
670 	    }
671 	  else
672 	    {
673 	      colortable[i].pixmap = XCreatePixmapFromBitmapData(W_Display,
674 					  W_Root, solid, TILESIDE, TILESIDE,
675 						   colortable[i].pixelValue,
676 						   colortable[i].pixelValue,
677 					 DefaultDepth(W_Display, W_Screen));
678 	    }
679 	  /* We assume white is 0 or 1, and black is 0 or 1. We adjust * *
680 	   * graphics function based upon who is who. */
681 	  if (white == 0)
682 	    {					 /* Black is 1 */
683 	      XSetFunction(W_Display, colortable[i].contexts[BITGC],
684 			   GXand);
685 	    }
686 	}
687     }
688   else if (W_Visual->class == PseudoColor)
689     {
690       if (!XAllocColorCells(W_Display, W_Colormap, False, planes, PLANES,
691 			    &pixel, 1) && !takeNearest)
692 	{
693 	  /* couldn't allocate 3 planes, make a new colormap */
694 	  W_Colormap = XCreateColormap(W_Display, W_Root, W_Visual, AllocNone);
695 
696 	  if (!XAllocColorCells(W_Display, W_Colormap, False, planes, PLANES,
697 				&pixel, 1))
698 	    {
699 	      fprintf(stderr, "Cannot create new colormap\n");
700 	      terminate(1);
701 	    }
702 	  /* and fill it with at least 8 more colors so when mouse is inside
703 	   * * * netrek windows, use might be able to see his other windows */
704 	  if (XAllocColorCells(W_Display, W_Colormap, False, NULL, 0,
705 			       extracolors, COLORS))
706 	    {
707 	      colordef.flags = DoRed | DoGreen | DoBlue;
708 
709 	      for (i = 0; i < COLORS; i++)
710 		{
711 		  colordef.pixel = extracolors[i];
712 		  colordef.red = extrared[i] << 8;
713 		  colordef.green = extragreen[i] << 8;
714 		  colordef.blue = extrablue[i] << 8;
715 		  XStoreColor(W_Display, W_Colormap, &colordef);
716 		}
717 	    }
718 	}
719 
720       for (i = 0; i < NCOLORS; i++)
721 	{
722 	  sprintf(defaultstring, "color.%s", colortable[i].name);
723 	  defaults = getdefault(defaultstring);
724 
725 	  if (defaults == NULL)
726 	    {
727 
728 #ifdef RACE_COLORS
729 	      if (i > GREY)
730 		{
731 		  /* The default colour from the ROMS is the colour defined *
732 		   *
733 		   * * to be RED and not the colour which is actually RED. */
734 
735 		  sprintf(defaultstring, "color.%s",
736 			  colortable[i - RaceDefaultOffset].name);
737 		  defaults = getdefault(defaultstring);
738 
739 		  if (defaults == NULL)
740 		    defaults = colortable[i - RaceDefaultOffset].name;
741 		}
742 	      else
743 #endif
744 
745 		defaults = colortable[i].name;
746 	    }
747 
748 	  XParseColor(W_Display, W_Colormap, defaults, &foo);
749 
750 	  switch (i)
751 	    {
752 
753 #ifndef RACE_COLORS
754 	    case WHITE:
755 	      foo.pixel = pixel | planes[0] | planes[1] | planes[2];
756 	      break;
757 	    case BLACK:
758 	      foo.pixel = pixel;
759 	      break;
760 	    case RED:
761 	      foo.pixel = pixel | planes[0];
762 	      break;
763 	    case CYAN:
764 	      foo.pixel = pixel | planes[1];
765 	      break;
766 	    case YELLOW:
767 	      foo.pixel = pixel | planes[2];
768 	      break;
769 	    case GREY:
770 	      foo.pixel = pixel | planes[0] | planes[1];
771 	      break;
772 	    case GREEN:
773 	      foo.pixel = pixel | planes[1] | planes[2];
774 	      break;
775 #else
776 	      /*
777 	       * Choose colors so that when two ships overlap, things look
778 	       * ok.  When players overlab, the bits are ORed together. */
779 
780 	      /* Background color */
781 	    case BLACK:
782 	      foo.pixel = pixel;
783 	      break;
784 
785 	      /* Alert colors (sum to grey usually) */
786 	    case RED:
787 	      foo.pixel = pixel | planes[1] | planes[2];
788 	      break;
789 	    case CYAN:
790 	      foo.pixel = pixel | planes[1] | planes[3];
791 	      break;
792 	    case YELLOW:
793 	      foo.pixel = pixel | planes[2] | planes[3];
794 	      break;
795 	    case GREEN:
796 	      foo.pixel = pixel | planes[1];
797 	      break;
798 	    case GREY:
799 	      foo.pixel = pixel | planes[1] | planes[2] | planes[3];
800 	      break;
801 
802 	      /* Your color */
803 	    case WHITE:
804 	      foo.pixel = pixel | planes[0];
805 	      break;
806 
807 	      /* The color of other ships should dominate over your color * *
808 	       * and should sum to C_IND where possible. */
809 	    case C_FED:
810 	      foo.pixel = pixel | planes[0] | planes[1] | planes[2];
811 	      break;
812 	    case C_ROM:
813 	      foo.pixel = pixel | planes[0] | planes[1] | planes[3];
814 	      break;
815 	    case C_KLI:
816 	      foo.pixel = pixel | planes[0] | planes[2] | planes[3];
817 	      break;
818 	    case C_ORI:
819 	      foo.pixel = pixel | planes[0] | planes[1];
820 	      break;
821 	    case C_IND:
822 	      foo.pixel = pixel | planes[0] | planes[1] | planes[2] | planes[3];
823 	      break;
824 #endif
825 	    }
826 	  if (takeNearest)
827 	    XAllocColor(W_Display, W_Colormap, &foo);
828 	  else
829 	    XStoreColor(W_Display, W_Colormap, &foo);
830 	  colortable[i].pixelValue = foo.pixel;
831 	  colortable[i].pixmap = XCreatePixmapFromBitmapData(W_Display,
832 		    W_Root, solid, TILESIDE, TILESIDE, foo.pixel, foo.pixel,
833 					 DefaultDepth(W_Display, W_Screen));
834 	}
835     }
836   else if (W_Visual->class >= TrueColor)
837     {
838       /* Stuff added by sheldon@iastate.edu 5/28/93 This is supposed to * *
839        * detect a TrueColor display, and then do a lookup of the colors in *
840        * * default colormap, instead of creating new colormap. */
841       for (i = 0; i < NCOLORS; i++)
842 	{
843 	  sprintf(defaultstring, "color.%s", colortable[i].name);
844 
845 	  defaults = getdefault(defaultstring);
846 	  if (defaults == NULL)
847 	    {
848 
849 #ifdef RACE_COLORS
850 	      if (i > GREY)
851 		{
852 		  /* The default color from the ROMS is the color defined to
853 		   * * * be RED and not the color which is actually RED. */
854 
855 		  sprintf(defaultstring, "color.%s",
856 			  colortable[i - RaceDefaultOffset].name);
857 		  defaults = getdefault(defaultstring);
858 
859 		  if (defaults == NULL)
860 		    defaults = colortable[i - RaceDefaultOffset].name;
861 		}
862 	      else
863 #endif
864 
865 		defaults = colortable[i].name;
866 	    }
867 
868 
869 	  XParseColor(W_Display, W_Colormap, defaults, &foo);
870 	  XAllocColor(W_Display, W_Colormap, &foo);
871 	  colortable[i].pixelValue = foo.pixel;
872 	  colortable[i].pixmap = XCreatePixmapFromBitmapData(W_Display,
873 		    W_Root, solid, TILESIDE, TILESIDE, foo.pixel, foo.pixel,
874 					 DefaultDepth(W_Display, W_Screen));
875 	}
876     }
877   else
878     {
879 
880       fprintf(stderr, "Don't know how to deal with a Class %d Visual\n",
881 	      W_Visual->class);
882       fprintf(stderr, "Your X server is not supported at %d bpp!\n",
883 	      DefaultDepth(W_Display, W_Screen));
884       terminate(1);
885     }
886   for (i = 0; i < NCOLORS; i++)
887     {
888       for (j = 0; j < FONTS + 1; j++)
889 	{
890 	  XSetForeground(W_Display, colortable[i].contexts[j],
891 			 colortable[i].pixelValue);
892 	  XSetBackground(W_Display, colortable[i].contexts[j],
893 			 colortable[W_Black].pixelValue);
894 	}
895     }
896 
897   if (scrollbar)
898     {
899       scroll_thumb_pixmap = XCreatePixmapFromBitmapData(W_Display,
900 					   W_Root, gray, TILESIDE, TILESIDE,
901 					     colortable[W_White].pixelValue,
902 					     colortable[W_Black].pixelValue,
903 					 DefaultDepth(W_Display, W_Screen));
904 
905       values.fill_style = FillTiled;
906       values.tile = scroll_thumb_pixmap;
907 
908       scroll_thumb_gc = XCreateGC(W_Display, W_Root,
909 				  GCFillStyle | GCTile, &values);
910     }
911 }
912 
W_RenameWindow(W_Window window,char * str)913 void W_RenameWindow(W_Window window, char *str)
914 {
915   struct window *win = W_Void2Window(window);
916   XStoreName(W_Display, win->window, str);
917 }
918 
919 W_Window
W_MakeWindow(char * name,int x,int y,int width,int height,W_Window parent,int border,W_Color color)920 W_MakeWindow(char *name, int x, int y, int width, int height, W_Window parent, int border, W_Color color)
921 {
922   struct window *newwin;
923   Window  wparent;
924   XSetWindowAttributes attrs;
925   char   *window_title = "Netrek", title_buff[257];
926   XSizeHints *sz_hints;
927   int     gcheck_result;
928 
929 #if DEBUG > 0
930   printf("New window...\n");
931 #endif
932 
933   gcheck_result = checkGeometry(name, &x, &y, &width, &height);
934   checkParent(name, &parent);
935   wparent = W_Void2Window(parent)->window;
936   attrs.border_pixel = colortable[color].pixelValue;
937   attrs.event_mask = KeyPressMask | ButtonPressMask | ExposureMask | LeaveWindowMask;
938 
939 #ifdef AUTOKEY
940   attrs.event_mask |= KeyReleaseMask;
941 #endif /* AUTOKEY */
942 
943 #ifdef MOTION_MOUSE
944   attrs.event_mask |= ButtonMotionMask;
945 #endif
946 
947   if (strcmp(name, "netrek_icon") == 0)		 /* icon should not select *
948 						  * for input */
949     attrs.event_mask = ExposureMask;
950   attrs.background_pixel = colortable[W_Black].pixelValue;
951   attrs.do_not_propagate_mask = KeyPressMask | ButtonPressMask | ExposureMask;
952   newwin = newWindow(
953 	      XCreateWindow(W_Display, wparent, x, y, width, height, border,
954 			    CopyFromParent, InputOutput, CopyFromParent,
955 			    CWBackPixel | CWEventMask | CWBorderPixel,
956 			    &attrs),
957 		      WIN_GRAPH);
958 
959   if (!strcmp(name, "netrek")) {
960     if (full_screen_enabled) {
961 #ifdef FULLSCREEN
962       kde_fullscreen_on(W_Window2Void(newwin));
963 #endif
964     }
965   }
966 
967   /* top window */
968   sz_hints = XAllocSizeHints();
969   if (strcmp(name, "netrek") == 0 || strcmp(name, "wait") == 0 ||
970       strcmp(name, "waitmotd") == 0)
971     {
972       if (!title && serverName)
973 	{
974 	  if (strcmp(name, "wait") == 0)
975 	    strcpy(title_buff, serverName);
976 	  else if (strcmp(name, "waitmotd") == 0)
977 	    strcpy(title_buff, "Motd-[f]forward, [b]back, [space]unmap");
978 	  else
979 	    sprintf(title_buff, "Netrek  @  %s", serverName);
980 	  window_title = title_buff;
981 	}
982       else
983 	/* but title on command line will override */ if (title)
984 	window_title = title;
985       sz_hints->min_width = width;
986       sz_hints->max_width = width;
987       sz_hints->min_height = height;
988       sz_hints->max_height = height;
989       sz_hints->flags = PMinSize | PMaxSize;
990 
991       if (!small_screen)
992 	/* avoid this check for small_screen; otherwise root window
993 	may not be aligned with upper-left corner of screen */
994 	if (gcheck_result & G_SET_X || gcheck_result & G_SET_Y)
995       sz_hints->flags |= WMXYHintMode_default();
996     }
997   else
998     {
999       window_title = name;
1000       if (gcheck_result & G_SET_X || gcheck_result & G_SET_Y)
1001 	sz_hints->flags |= WMXYHintMode_default();
1002     }
1003   XStoreName(W_Display, newwin->window, window_title);
1004   XSetWMNormalHints(W_Display, newwin->window, sz_hints);
1005   class_hint.res_name = name;
1006   XSetClassHint(W_Display, newwin->window, &class_hint);
1007   XSetWMHints(W_Display, newwin->window, &wm_hint);
1008   newwin->name = strdup(name);
1009   newwin->width = width;
1010   newwin->height = height;
1011   if (wparent != W_Root)
1012     if (checkMapped(name))
1013       W_MapWindow(W_Window2Void(newwin));
1014 
1015 #if DEBUG > 0
1016   printf("New graphics window %d, child of %d\n", newwin, parent);
1017 #endif
1018 
1019   XSetWindowColormap(W_Display, newwin->window, W_Colormap);
1020   return W_Window2Void(newwin);
1021 }
1022 
1023 void
W_ChangeBorder(W_Window window,int color)1024         W_ChangeBorder(W_Window window, int color)
1025 {
1026 
1027 #if DEBUG > 2
1028   printf("Changing border of %d\n", window);
1029 #endif
1030 
1031   /* fix inexplicable color bug */
1032   if ((DisplayCells(W_Display, W_Screen) <= 2) || forceMono)
1033 
1034     XSetWindowBorderPixmap(W_Display, W_Void2Window(window)->window,
1035 			   colortable[color].pixmap);
1036   else
1037     XSetWindowBorder(W_Display, W_Void2Window(window)->window,
1038 		     colortable[color].pixelValue);
1039 
1040 
1041 }
1042 
1043 void
W_MapWindow(W_Window window)1044         W_MapWindow(W_Window window)
1045 {
1046   struct window *win;
1047 
1048 #if DEBUG > 2
1049   printf("Mapping %d\n", window);
1050 #endif
1051 
1052   win = W_Void2Window(window);
1053   if (win->mapped)
1054     return;
1055   win->mapped = 1;
1056   XMapRaised(W_Display, win->window);
1057 }
1058 
1059 void
W_UnmapWindow(W_Window window)1060         W_UnmapWindow(W_Window window)
1061 {
1062   struct window *win;
1063 
1064 #if DEBUG > 2
1065   printf("UnMapping %d\n", window);
1066 #endif
1067 
1068   win = W_Void2Window(window);
1069   if (win->mapped == 0)
1070     return;
1071   win->mapped = 0;
1072   XUnmapWindow(W_Display, win->window);
1073 }
1074 
1075 int
W_IsMapped(W_Window window)1076         W_IsMapped(W_Window window)
1077 {
1078   struct window *win;
1079 
1080   win = W_Void2Window(window);
1081   if (win == NULL)
1082     return 0;
1083   return win->mapped;
1084 }
1085 
1086 void
W_FillArea(W_Window window,int x,int y,int width,int height,W_Color color)1087         W_FillArea(W_Window window, int x, int y, int width, int height, W_Color color)
1088 {
1089   struct window *win;
1090 
1091 #if DEBUG > 2
1092   printf("Clearing (%d %d) x (%d %d) with %d on %d\n", x, y, width, height,
1093 	 color, window);
1094 #endif
1095 
1096   win = W_Void2Window(window);
1097   switch (win->type)
1098     {
1099     case WIN_GRAPH:
1100       XFillRectangle(W_Display, win->window, colortable[color].contexts[0],
1101 		     x, y, width, height);
1102       break;
1103     case WIN_SCROLL:
1104       XFillRectangle(W_Display, win->window, colortable[color].contexts[0],
1105 		     WIN_EDGE + x * W_Textwidth,
1106 		     MENU_PAD + y * W_Textheight,
1107 		     width * W_Textwidth, height * W_Textheight);
1108       break;
1109     default:
1110       XFillRectangle(W_Display, win->window, colortable[color].contexts[0],
1111 		     WIN_EDGE + x * W_Textwidth, MENU_PAD + y * W_Textheight,
1112 		     width * W_Textwidth, height * W_Textheight);
1113     }
1114 }
1115 
1116 /* XFIX */
1117 
1118 static XRectangle _rcache[MAXCACHE];
1119 static int _rcache_index;
1120 
1121 static void
FlushClearAreaCache(Window win)1122         FlushClearAreaCache(Window win)
1123 {
1124   XFillRectangles(W_Display, win, colortable[backColor].contexts[0],
1125 		  _rcache, _rcache_index);
1126   _rcache_index = 0;
1127 }
1128 
1129 /* local window only */
1130 void
W_CacheClearArea(W_Window window,int x,int y,int width,int height)1131         W_CacheClearArea(W_Window window, int x, int y, int width, int height)
1132 {
1133   Window  win = W_Void2Window(window)->window;
1134   register XRectangle *r;
1135 
1136   if (_rcache_index == MAXCACHE)
1137     FlushClearAreaCache(win);
1138 
1139   r = &_rcache[_rcache_index++];
1140   r->x = (short) x;
1141   r->y = (short) y;
1142   r->width = (unsigned short) width;
1143   r->height = (unsigned short) height;
1144 }
1145 
1146 void
W_FlushClearAreaCache(W_Window window)1147         W_FlushClearAreaCache(W_Window window)
1148 {
1149   Window  win = W_Void2Window(window)->window;
1150 
1151   if (_rcache_index)
1152     FlushClearAreaCache(win);
1153 }
1154 
1155 /* XFIX: clears now instead of filling. */
1156 void
W_ClearArea(W_Window window,int x,int y,int width,int height)1157         W_ClearArea(W_Window window, int x, int y, int width, int height)
1158 {
1159   struct window *win;
1160 
1161   win = W_Void2Window(window);
1162   switch (win->type)
1163     {
1164     case WIN_GRAPH:
1165       /* XFIX: changed */
1166       XClearArea(W_Display, win->window, x, y, width, height, False);
1167       break;
1168     case WIN_SCROLL:
1169       XClearArea(W_Display, win->window, WIN_EDGE + x * W_Textwidth,
1170 		 MENU_PAD + y * W_Textheight,
1171 		 width * W_Textwidth, height * W_Textheight, False);
1172       break;
1173     default:
1174       /* XFIX: changed */
1175       XClearArea(W_Display, win->window, WIN_EDGE + x * W_Textwidth,
1176 		 MENU_PAD + y * W_Textheight, width * W_Textwidth, height * W_Textheight, False);
1177       break;
1178     }
1179 }
1180 
1181 void
W_ClearWindow(W_Window window)1182         W_ClearWindow(W_Window window)
1183 {
1184 
1185 #if DEBUG > 2
1186   printf("Clearing %d\n", window);
1187 #endif
1188 
1189   XClearWindow(W_Display, W_Void2Window(window)->window);
1190 }
1191 
1192 int
W_Pending(void)1193 	W_Pending(void)
1194 {
1195   return XPending(W_Display);
1196 }
1197 
1198 int
W_EventsPending(void)1199         W_EventsPending(void)
1200 {
1201   if (W_isEvent)
1202     return 1;
1203   while (XPending(W_Display))
1204     {
1205       if (W_SpNextEvent(&W_myevent))
1206 	{
1207 	  W_isEvent = 1;
1208 	  return 1;
1209 	}
1210     }
1211   return 0;
1212 }
1213 
1214 void
W_NextEvent(W_Event * wevent)1215         W_NextEvent(W_Event * wevent)
1216 {
1217   if (W_isEvent)
1218     {
1219       *wevent = W_myevent;
1220       W_isEvent = 0;
1221       return;
1222     }
1223   while (W_SpNextEvent(wevent) == 0);
1224 }
1225 
sym_to_key(int sym)1226 static unsigned char sym_to_key(int sym)
1227 {
1228   switch (sym) {
1229   case XK_Up: return W_Key_Up;
1230   case XK_Down: return W_Key_Down;
1231   }
1232   return 0;
1233 }
1234 
1235 int
W_SpNextEvent(W_Event * wevent)1236         W_SpNextEvent(W_Event * wevent)
1237 {
1238   XEvent  event;
1239   XKeyEvent *key;
1240   XButtonEvent *button;
1241   XExposeEvent *expose;
1242   XConfigureEvent *configure;
1243 
1244 #ifdef MOTION_MOUSE
1245   XMotionEvent *motion;
1246   static int prev_x, prev_y;
1247   int     thresh;
1248 #endif
1249 
1250 #ifdef CONTROL_KEY
1251   int     control_key = 0;
1252 #endif
1253   unsigned char ch;
1254   int nch;
1255   struct window *win;
1256   KeySym  sym;
1257 
1258 #if DEBUG > 1
1259   printf("event");
1260 #endif
1261 
1262   key = (XKeyEvent *) & event;
1263   button = (XButtonEvent *) & event;
1264   expose = (XExposeEvent *) & event;
1265   configure = (XConfigureEvent *) & event;
1266 
1267 #ifdef MOTION_MOUSE
1268   motion = (XMotionEvent *) & event;
1269 #endif
1270 
1271   for (;;)
1272     {
1273       XNextEvent(W_Display, &event);
1274 
1275 #if DEBUG > 1
1276       printf(", read type=%d\n", event.type);
1277 #endif
1278       win = findWindow(key->window);
1279       if (win == NULL)
1280 	return 0;
1281       if (key->send_event == True && event.type != ClientMessage)
1282 	return 0; /* event sent by another client */
1283       if ((event.type == KeyPress || event.type == ButtonPress) &&
1284 	  win->type == WIN_MENU)
1285 	{
1286 	  if (key->y % (W_Textheight + MENU_PAD * 2 + MENU_BAR) >=
1287 	      W_Textheight + MENU_PAD * 2)
1288 	    return 0;
1289 	  key->y = key->y / (W_Textheight + MENU_PAD * 2 + MENU_BAR);
1290 	}
1291       switch ((int) event.type)
1292 	{
1293 	case ClientMessage:
1294 	  if (event.xclient.message_type == wm_protocols &&
1295 	      event.xclient.data.l[0] == wm_delete_window)
1296 	    {
1297 	      W_UnmapWindow(W_Window2Void(win));
1298 	      wevent->type = W_EV_CLOSED;
1299 	      wevent->Window = W_Window2Void(win);
1300 	      wevent->key = wevent->x = wevent->y = 0;
1301 	      return 1;
1302 	    }
1303 	  break;
1304 
1305 	case LeaveNotify: /* for message window -- jfy */
1306 	  if (win == (struct window *) messagew)
1307 	    {
1308 	      W_in_message = 0;
1309 	    }
1310 	  return 0;
1311 	  break;
1312 	case KeyPress:
1313 	  if ((key->state & LockMask) && !(key->state & ShiftMask) &&
1314 	      (ignoreCaps))
1315 	    {
1316 	      printf("Got a capslock!\n");
1317 	      key->state = key->state & ~LockMask;
1318 	    }
1319 
1320 #ifdef CONTROL_KEY
1321 	  if (key->state & ControlMask && use_control_key)
1322 	    {
1323 	      control_key = 1;
1324 	      key->state = key->state & ~ControlMask;
1325 	    }
1326 	  else
1327 	    control_key = 0;
1328 #endif
1329 
1330 	  nch = XLookupString(key, (char *) &ch, 1, &sym, NULL);
1331 	  if (nch == 0) {
1332 	    ch = sym_to_key(sym);
1333 	    if (ch == 0) return 0;
1334 	  }
1335 #ifdef MOUSE_AS_SHIFT
1336 	  if (mouse_as_shift)
1337 	    {
1338 	      if (key->state & Button1Mask)
1339 		{
1340 		  wevent->modifier = W_LBUTTON;
1341 		  wevent->type = W_EV_MKEY;
1342 		}
1343 	      else if (key->state & Button2Mask)
1344 		{
1345 		  wevent->modifier = W_MBUTTON;
1346 		  wevent->type = W_EV_MKEY;
1347 		}
1348 	      else if (key->state & Button3Mask)
1349 		{
1350 		  wevent->modifier = W_RBUTTON;
1351 		  wevent->type = W_EV_MKEY;
1352 		}
1353 	      else
1354 		{
1355 		  wevent->type = W_EV_KEY;
1356 		}
1357 	    }
1358 	  else
1359 	    wevent->type = W_EV_KEY;
1360 #else
1361 	  wevent->type = W_EV_KEY;
1362 #endif
1363 
1364 	  wevent->Window = W_Window2Void(win);
1365 	  wevent->x = key->x;
1366 	  wevent->y = key->y;
1367 
1368 #ifdef CONTROL_KEY
1369 	  if (control_key)
1370 	    wevent->key = (unsigned char) (ch + 96);
1371 	  else
1372 	    wevent->key = ch;
1373 #else
1374 	  wevent->key = ch;
1375 #endif
1376 
1377 	  return 1;
1378 	  break;
1379 
1380 #ifdef AUTOKEY
1381 	case KeyRelease:
1382 	  if (XLookupString(key, &ch, 1, NULL, NULL) > 0)
1383 	    {
1384 	      wevent->type = W_EV_KEY_OFF;
1385 	      wevent->Window = W_Window2Void(win);
1386 	      wevent->x = key->x;
1387 	      wevent->y = key->y;
1388 	      wevent->key = ch;
1389 	      return 1;
1390 	    }
1391 	  return 0;
1392 	  break;
1393 #endif /* AUTOKEY */
1394 
1395 	case ButtonPress:
1396 	  wevent->type = W_EV_BUTTON;
1397 	  wevent->Window = W_Window2Void(win);
1398 
1399 #ifdef MOTION_MOUSE
1400 	  prev_x = wevent->x = button->x;
1401 	  prev_y = wevent->y = button->y;
1402 #else
1403 	  wevent->x = button->x;
1404 	  wevent->y = button->y;
1405 #endif
1406 
1407 
1408 #ifdef MOUSE_AS_SHIFT
1409 	  if (mouse_as_shift &&
1410 	      (wevent->Window == mapw || wevent->Window == w))
1411 	    switch (button->button & 0xf)
1412 	      {
1413 	      case Button3:
1414 		if (b3_as_shift)
1415 		  return 0;
1416 		break;
1417 	      case Button1:
1418 		if (b1_as_shift)
1419 		  return 0;
1420 		break;
1421 	      case Button2:
1422 		if (b2_as_shift)
1423 		  return 0;
1424 		break;
1425 	      }
1426 #endif
1427 
1428 	  switch (button->button & 0xf)
1429 	    {
1430 	    case Button3:
1431 	      wevent->key = W_RBUTTON;
1432 	      break;
1433 	    case Button1:
1434 	      wevent->key = W_LBUTTON;
1435 	      break;
1436 	    case Button2:
1437 	      wevent->key = W_MBUTTON;
1438 	      break;
1439 #ifdef Button4
1440 	    case Button4:
1441 	      wevent->key = W_WUBUTTON;
1442 	      break;
1443 #endif
1444 #ifdef Button5
1445 	    case Button5:
1446 	      wevent->key = W_WDBUTTON;
1447 	      break;
1448 #endif
1449 #ifdef Button6
1450 	    case Button6:
1451 	      wevent->key = W_X1BUTTON;
1452 	      break;
1453 #endif
1454 #ifdef Button7
1455 	    case Button7:
1456 	      wevent->key = W_X2BUTTON;
1457 	      break;
1458 #endif
1459 	    }
1460 
1461 #ifdef SHIFTED_MOUSE
1462 	  if (extended_mouse)
1463 	    {
1464 	      if (button->state & (ControlMask | ShiftMask))
1465 		{
1466 
1467 		  if (button->state & ShiftMask)
1468 		    {
1469 		      wevent->key |= W_SHIFT_BUTTON;
1470 		    }
1471 
1472 		  if (button->state & ControlMask)
1473 		    {
1474 		      wevent->key |= W_CTRL_BUTTON;
1475 		    }
1476 
1477 		  return 1;
1478 		}
1479 
1480 	    }
1481 #endif
1482 
1483 	  if (win->type == WIN_SCROLL)
1484 	    {
1485 	      scrollScrolling(wevent);
1486 	      return 0;
1487 	    }
1488 	  return 1;
1489 
1490 #ifdef MOTION_MOUSE
1491 	case MotionNotify:
1492 	  if (!motion_mouse ||
1493 	      (!motion_mouse_enablable && !motion_mouse_steering))
1494 	    return 0;
1495 	  wevent->type = W_EV_CM_BUTTON;
1496 	  wevent->Window = W_Window2Void(win);
1497 
1498 	  thresh = abs(prev_x - motion->x) + abs(prev_y - motion->y);
1499 
1500 	  if (thresh < user_motion_thresh)
1501 	    return 0;
1502 
1503 	  prev_x = wevent->x = motion->x;
1504 	  prev_y = wevent->y = motion->y;
1505 
1506 
1507 #ifdef MOUSE_AS_SHIFT
1508 	  if (mouse_as_shift &&
1509 	      (wevent->Window == mapw || wevent->Window == w))
1510 	    switch (button->button & 0xf)
1511 	      {
1512 	      case Button3:
1513 		if (b3_as_shift)
1514 		  return 0;
1515 		break;
1516 	      case Button1:
1517 		if (b1_as_shift)
1518 		  return 0;
1519 		break;
1520 	      case Button2:
1521 		if (b2_as_shift)
1522 		  return 0;
1523 		break;
1524 	      }
1525 #endif
1526 
1527 	  switch (button->button & 0xf)
1528 	    {
1529 	    case Button3:
1530 	      wevent->key = W_RBUTTON;
1531 	      break;
1532 	    case Button1:
1533 	      wevent->key = W_LBUTTON;
1534 	      break;
1535 	    case Button2:
1536 	      wevent->key = W_MBUTTON;
1537 	      break;
1538 #ifdef Button4
1539 	    case Button4:
1540 	      wevent->key = W_WUBUTTON;
1541 	      break;
1542 #endif
1543 #ifdef Button5
1544 	    case Button5:
1545 	      wevent->key = W_WDBUTTON;
1546 	      break;
1547 #endif
1548 #ifdef Button6
1549 	    case Button6:
1550 	      wevent->key = W_X1BUTTON;
1551 	      break;
1552 #endif
1553 #ifdef Button7
1554 	    case Button7:
1555 	      wevent->key = W_X2BUTTON;
1556 	      break;
1557 #endif
1558 	    }
1559 
1560 #ifdef SHIFTED_MOUSE
1561 	  if (extended_mouse)
1562 	    {
1563 	      if (button->state & (ControlMask | ShiftMask))
1564 		{
1565 
1566 		  if (button->state & ShiftMask)
1567 		    {
1568 		      wevent->key |= W_SHIFT_BUTTON;
1569 		    }
1570 
1571 		  if (button->state & ControlMask)
1572 		    {
1573 		      wevent->key |= W_CTRL_BUTTON;
1574 		    }
1575 
1576 		  return 1;
1577 		}
1578 	    }
1579 #endif
1580 
1581 	  return 1;
1582 #endif
1583 
1584 	case Expose:
1585 	  if (expose->count != 0)
1586 	    return 0;
1587 	  if (win->type == WIN_SCROLL)
1588 	    {
1589 	      configureScrolling(win, expose->x, expose->y,
1590 				 expose->width, expose->height);
1591 	      redrawScrolling(win);
1592 	      return 0;
1593 	    }
1594 	  if (win->type == WIN_MENU)
1595 	    {
1596 	      redrawMenu(win);
1597 	      return 0;
1598 	    }
1599 
1600 	  wevent->type = W_EV_EXPOSE;
1601 	  wevent->Window = W_Window2Void(win);
1602 	  return 1;
1603 	case ConfigureNotify:
1604 	  configureScrolling(win, configure->x, configure->y,
1605 			     configure->width, configure->height);
1606 	  break;
1607 	default:
1608 	  return 0;
1609 	  break;
1610 	}
1611     }
1612 }
1613 
1614 void
W_MakeLine(W_Window window,int x0,int y0,int x1,int y1,W_Color color)1615         W_MakeLine(W_Window window, int x0, int y0, int x1, int y1, W_Color color)
1616 {
1617   Window  win;
1618 
1619 #if DEBUG > 3
1620   printf("Line on %d\n", window);
1621 #endif
1622 
1623   win = W_Void2Window(window)->window;
1624   XDrawLine(W_Display, win, colortable[color].contexts[0], x0, y0, x1, y1);
1625 }
1626 
1627 /* XFIX */
1628 
1629 static XSegment _lcache[NCOLORS][MAXCACHE];
1630 static int _lcache_index[NCOLORS];
1631 
1632 static void
FlushLineCache(Window win,int color)1633         FlushLineCache(Window win, int color)
1634 {
1635   XDrawSegments(W_Display, win, colortable[color].contexts[0],
1636 		_lcache[color], _lcache_index[color]);
1637   _lcache_index[color] = 0;
1638 }
1639 
1640 /* for local window only */
1641 void
W_CacheLine(W_Window window,int x0,int y0,int x1,int y1,int color)1642         W_CacheLine(W_Window window, int x0, int y0, int x1, int y1, int color)
1643 {
1644   Window  win = W_Void2Window(window)->window;
1645   register XSegment *s;
1646 
1647   if (_lcache_index[color] == MAXCACHE)
1648     FlushLineCache(win, color);
1649 
1650   s = &_lcache[color][_lcache_index[color]++];
1651   s->x1 = (short) x0;
1652   s->y1 = (short) y0;
1653   s->x2 = (short) x1;
1654   s->y2 = (short) y1;
1655 }
1656 
1657 void
W_FlushLineCaches(W_Window window)1658         W_FlushLineCaches(W_Window window)
1659 {
1660   Window  win = W_Void2Window(window)->window;
1661   int i;
1662 
1663   for (i = 0; i < NCOLORS; i++)
1664     {
1665       if (_lcache_index[i])
1666 	FlushLineCache(win, i);
1667     }
1668 }
1669 
1670 void
W_MakeTractLine(W_Window window,int x0,int y0,int x1,int y1,W_Color color)1671         W_MakeTractLine(W_Window window, int x0, int y0, int x1, int y1, W_Color color)
1672 {
1673   Window  win;
1674 
1675 #if DEBUG > 3
1676   printf("Line on %d\n", window);
1677 #endif
1678 
1679   win = W_Void2Window(window)->window;
1680   XDrawLine(W_Display, win, colortable[color].contexts[3], x0, y0, x1, y1);
1681 }
1682 
1683 void
W_MakePhaserLine(W_Window window,int x0,int y0,int x1,int y1,W_Color color)1684         W_MakePhaserLine(W_Window window, int x0, int y0, int x1, int y1, W_Color color)
1685 {
1686   Window  win;
1687 
1688 #if DEBUG > 3
1689   printf("Line on %d\n", window);
1690 #endif
1691 
1692   win = W_Void2Window(window)->window;
1693   XDrawLine(W_Display, win, colortable[color].contexts[1], x0, y0, x1, y1);
1694 }
1695 
W_WriteCircle(W_Window window,int x,int y,int r,W_Color color)1696 void W_WriteCircle (W_Window window,
1697                     int x,
1698                     int y,
1699                     int r,
1700                     W_Color color)
1701 {
1702   struct window *win = W_Void2Window(window);
1703 
1704   XSetForeground(W_Display, colortable[color].contexts[0],
1705 		 colortable[color].pixelValue);
1706   XDrawArc(W_Display, win->window, colortable[color].contexts[0],
1707 	   x, y, r, r, 0, 23040);
1708 }
1709 
1710 void
W_WriteTriangle(W_Window window,int x,int y,int s,int t,W_Color color)1711         W_WriteTriangle(W_Window window, int x, int y, int s, int t, W_Color color)
1712 {
1713   struct window *win = W_Void2Window(window);
1714   XPoint  points[4];
1715 
1716   if (t == 0)
1717     {
1718       points[0].x = x;
1719       points[0].y = y;
1720       points[1].x = x + s;
1721       points[1].y = y - s;
1722       points[2].x = x - s;
1723       points[2].y = y - s;
1724       points[3].x = x;
1725       points[3].y = y;
1726     }
1727   else
1728     {
1729       points[0].x = x;
1730       points[0].y = y;
1731       points[1].x = x + s;
1732       points[1].y = y + s;
1733       points[2].x = x - s;
1734       points[2].y = y + s;
1735       points[3].x = x;
1736       points[3].y = y;
1737     }
1738 
1739 
1740   XDrawLines(W_Display, win->window, colortable[color].contexts[0],
1741 	     points, 4, CoordModeOrigin);
1742 }
1743 
1744 void
W_WriteText(W_Window window,int x,int y,W_Color color,char * str,int len,W_Font font)1745         W_WriteText(W_Window window, int x, int y, W_Color color, char *str, int len, W_Font font)
1746 {
1747   struct window *win;
1748   int     addr;
1749 
1750 #if DEBUG > 3
1751   printf("Text for %d @ (%d, %d) in %d: [%s]\n", window, x, y, color, str);
1752 #endif
1753 
1754   if (font == 0)
1755     font = W_RegularFont;
1756   win = W_Void2Window(window);
1757 
1758   switch (win->type)
1759     {
1760     case WIN_GRAPH:
1761       addr = fonts[fontNum(font)].baseline;
1762       if (len < 0) len = strlen(str);
1763       XDrawImageString(W_Display, win->window,
1764 
1765 #ifdef SHORT_PACKETS
1766 		       win->insensitive ?
1767 		       colortable[color].insens_contexts[1] :
1768 		       colortable[color].contexts[fontNum(font)],
1769 #else
1770 		       colortable[color].contexts[fontNum(font)],
1771 #endif
1772 
1773 		       x, y + addr, str, len);
1774       break;
1775     case WIN_SCROLL:
1776       XCopyArea(W_Display, win->window, win->window,
1777 	 colortable[W_White].contexts[0], WIN_EDGE, MENU_PAD + W_Textheight,
1778 		win->width * W_Textwidth, (win->height - 1) * W_Textheight,
1779 		WIN_EDGE, MENU_PAD);
1780       XClearArea(W_Display, win->window,
1781 		 WIN_EDGE, MENU_PAD + W_Textheight * (win->height - 1),
1782 		 W_Textwidth * win->width, W_Textheight, False);
1783       if (len < 0) len = strlen(str);
1784       XDrawImageString(W_Display, win->window,
1785 
1786 #ifdef SHORT_PACKETS
1787 		       win->insensitive ?
1788 		       colortable[color].insens_contexts[1] :
1789 		       colortable[color].contexts[fontNum(font)],
1790 #else
1791 		       colortable[color].contexts[fontNum(font)],
1792 #endif
1793 
1794 		       WIN_EDGE, MENU_PAD + W_Textheight * (win->height - 1) + fonts[fontNum(font)].baseline,
1795 		       str, len);
1796       AddToScrolling(win, color, font, str, len);
1797       break;
1798     case WIN_MENU:
1799       changeMenuItem(win, x, y, str, color);
1800       break;
1801     default:
1802       addr = fonts[fontNum(font)].baseline;
1803       if (len < 0) len = strlen(str);
1804       XDrawImageString(W_Display, win->window,
1805 
1806 #ifdef SHORT_PACKETS
1807 		       win->insensitive ?
1808 		       colortable[color].insens_contexts[1] :
1809 		       colortable[color].contexts[fontNum(font)],
1810 #else
1811 		       colortable[color].contexts[fontNum(font)],
1812 #endif
1813 
1814 	     x * W_Textwidth + WIN_EDGE, MENU_PAD + y * W_Textheight + addr,
1815 		       str, len);
1816       break;
1817     }
1818 }
1819 
1820 void
W_MaskText(W_Window window,int x,int y,W_Color color,char * str,int len,W_Font font)1821         W_MaskText(W_Window window, int x, int y, W_Color color, char *str, int len, W_Font font)
1822 {
1823   struct window *win;
1824   int     addr;
1825 
1826   addr = fonts[fontNum(font)].baseline;
1827 
1828 #if DEBUG > 3
1829   printf("TextMask for %d @ (%d, %d) in %d: [%s]\n", window, x, y, color, str);
1830 #endif
1831 
1832   win = W_Void2Window(window);
1833   XDrawString(W_Display, win->window,
1834 	  colortable[color].contexts[fontNum(font)], x, y + addr, str, len);
1835 }
1836 
1837 W_Icon
W_StoreBitmap(int width,int height,char * data,W_Window window)1838 W_StoreBitmap(int width, int height, char *data, W_Window window)
1839 {
1840   struct icon *newicon;
1841   struct window *win;
1842 
1843 #if DEBUG > 0
1844   printf("Storing bitmap for %d (%d x %d)\n", window, width, height);
1845   fflush(stdout);
1846 #endif
1847 
1848   win = W_Void2Window(window);
1849   newicon = (struct icon *) malloc(sizeof(struct icon));
1850 
1851   newicon->width = width;
1852   newicon->height = height;
1853   newicon->bitmap = XCreateBitmapFromData(W_Display, win->window,
1854 					  data, width, height);
1855 
1856 #ifdef nodef
1857   /* XFIX: changed to Pixmap */
1858   white = WhitePixel(W_Display, W_Screen);
1859   black = BlackPixel(W_Display, W_Screen);
1860   newicon->bitmap = XCreatePixmapFromBitmapData(W_Display, W_Root, data,
1861 						width, height, white, black,
1862 						DefaultDepth(W_Display,
1863 							     W_Screen));
1864 #endif /* nodef */
1865 
1866   newicon->window = win->window;
1867   newicon->pixmap = 0;
1868   return W_Icon2Void(newicon);
1869 }
1870 
1871 void
W_WriteBitmap(int x,int y,W_Icon bit,W_Color color)1872         W_WriteBitmap(int x, int y, W_Icon bit, W_Color color)
1873 {
1874   struct icon *icon;
1875 
1876   icon = W_Void2Icon(bit);
1877 
1878 #if DEBUG > 4
1879   printf("Writing bitmap to %d\n", icon->window);
1880 #endif
1881 
1882   XCopyPlane(W_Display, icon->bitmap, icon->window,
1883 	 colortable[color].contexts[BITGC], 0, 0, icon->width, icon->height,
1884 	     x, y, 1);
1885 
1886 #ifdef nodef
1887   /* XFIX : copyarea */
1888   XCopyArea(W_Display, icon->bitmap, icon->window,
1889 	 colortable[color].contexts[BITGC], 0, 0, icon->width, icon->height,
1890 	    x, y);
1891 #endif
1892 }
1893 
1894 
1895 void
W_TileWindow(W_Window window,W_Icon bit)1896         W_TileWindow(W_Window window, W_Icon bit)
1897 {
1898   Window  win;
1899   struct icon *icon;
1900 
1901 #if DEBUG > 4
1902   printf("Tiling window %d\n", window);
1903 #endif
1904 
1905   icon = W_Void2Icon(bit);
1906   win = W_Void2Window(window)->window;
1907 
1908   if (icon->pixmap == 0)
1909     {
1910       icon->pixmap = XCreatePixmap(W_Display, W_Root,
1911 	      icon->width, icon->height, DefaultDepth(W_Display, W_Screen));
1912       XCopyPlane(W_Display, icon->bitmap, icon->pixmap,
1913 	   colortable[W_White].contexts[0], 0, 0, icon->width, icon->height,
1914 		 0, 0, 1);
1915     }
1916   XSetWindowBackgroundPixmap(W_Display, win, icon->pixmap);
1917   XClearWindow(W_Display, win);
1918 
1919   /* if (icon->pixmap==0) { icon->pixmap=XMakePixmap(icon->bitmap, * *
1920    * colortable[W_White].pixelValue, colortable[W_Black].pixelValue); } * *
1921    * XChangeBackground(win, icon->pixmap); XClear(win); */
1922 }
1923 
1924 void
W_UnTileWindow(W_Window window)1925         W_UnTileWindow(W_Window window)
1926 {
1927   Window  win;
1928 
1929 #if DEBUG > 4
1930   printf("Untiling window %d\n", window);
1931 #endif
1932 
1933   win = W_Void2Window(window)->window;
1934 
1935   XSetWindowBackground(W_Display, win, colortable[W_Black].pixelValue);
1936   XClearWindow(W_Display, win);
1937 }
1938 
1939 W_Window
W_MakeTextWindow(char * name,int x,int y,int width,int height,W_Window parent,int border)1940 W_MakeTextWindow(char *name, int x, int y, int width, int height, W_Window parent, int border)
1941 {
1942   struct window *newwin;
1943   Window  wparent;
1944   XSetWindowAttributes attrs;
1945   XSizeHints *sz_hints;
1946   int     gcheck_result;
1947 
1948 #if DEBUG > 0
1949   printf("New window...\n");
1950 #endif
1951 
1952   gcheck_result = checkGeometry(name, &x, &y, &width, &height);
1953   checkParent(name, &parent);
1954   attrs.border_pixel = colortable[W_White].pixelValue;
1955   attrs.event_mask = ExposureMask;
1956 
1957 #ifdef AUTOKEY
1958   attrs.event_mask |= KeyReleaseMask;
1959 #endif /* AUTOKEY */
1960 
1961 #ifdef SHORT_PACKETS
1962   attrs.event_mask |= ButtonPressMask;
1963 #endif
1964 
1965   attrs.background_pixel = colortable[W_Black].pixelValue;
1966   attrs.do_not_propagate_mask = ExposureMask;
1967   wparent = W_Void2Window(parent)->window;
1968   newwin = newWindow(
1969 		      XCreateWindow(W_Display, wparent, x, y,
1970    width * W_Textwidth + WIN_EDGE * 2, MENU_PAD * 2 + height * W_Textheight,
1971 			border, CopyFromParent, InputOutput, CopyFromParent,
1972 				    CWBackPixel | CWEventMask |
1973 				    CWBorderPixel,
1974 				    &attrs),
1975 		      WIN_TEXT);
1976   class_hint.res_name = name;
1977   sz_hints = XAllocSizeHints();
1978   sz_hints->min_width = WIN_EDGE * 2 + width * W_Textwidth;
1979   sz_hints->max_width = WIN_EDGE * 2 + width * W_Textwidth;
1980   sz_hints->base_width = WIN_EDGE * 2;
1981   sz_hints->width_inc = W_Textwidth;
1982   sz_hints->min_height = MENU_PAD * 2 + 3 * W_Textheight;
1983   sz_hints->max_height = MENU_PAD * 2 + height * W_Textheight;
1984   sz_hints->base_height = MENU_PAD * 2 + 2 * W_Textheight;
1985   sz_hints->height_inc = W_Textheight;
1986   sz_hints->flags = PResizeInc | PMinSize | PMaxSize | PBaseSize;
1987   if (gcheck_result & G_SET_X || gcheck_result & G_SET_Y)
1988     sz_hints->flags |= WMXYHintMode_default();
1989   XStoreName(W_Display, newwin->window, name);
1990   XSetWMNormalHints(W_Display, newwin->window, sz_hints);
1991   XSetClassHint(W_Display, newwin->window, &class_hint);
1992   XSetWMHints(W_Display, newwin->window, &wm_hint);
1993   newwin->name = strdup(name);
1994   newwin->width = width;
1995   newwin->height = height;
1996   if (wparent != W_Root)
1997     if (checkMapped(name))
1998       W_MapWindow(W_Window2Void(newwin));
1999 
2000 #if DEBUG > 0
2001   printf("New text window %d, child of %d\n", newwin, parent);
2002 #endif
2003 
2004   XSetWindowColormap(W_Display, newwin->window, W_Colormap);
2005   return W_Window2Void(newwin);
2006 }
2007 
2008 struct window *
newWindow(Window window,int type)2009         newWindow(Window window, int type)
2010 {
2011   struct window *newwin;
2012 
2013   XSetWMProtocols (W_Display, window, &wm_delete_window, 1);
2014   newwin = (struct window *) malloc(sizeof(struct window));
2015 
2016   newwin->window = window;
2017   newwin->type = type;
2018   newwin->mapped = 0;
2019   newwin->handle_keydown = 0;
2020   newwin->handle_keyup = 0;
2021   newwin->handle_button = 0;
2022   newwin->handle_expose = 0;
2023   addToHash(newwin);
2024 
2025 #ifdef SHORT_PACKETS
2026   newwin->insensitive = 0;
2027 #endif
2028 
2029   newwin->cursor = (Cursor) 0;			 /* about the best I can do *
2030 						  *
2031 						  * * -jw */
2032   return newwin;
2033 }
2034 
2035 struct window *
findWindow(Window window)2036         findWindow(Window window)
2037 {
2038   struct windowlist *entry;
2039 
2040   entry = hashtable[hash(window)];
2041   while (entry != NULL)
2042     {
2043       if (entry->window->window == window)
2044 	return entry->window;
2045       entry = entry->next;
2046     }
2047   return NULL;
2048 }
2049 
addToHash(struct window * win)2050 void addToHash(struct window * win)
2051 {
2052   struct windowlist **new;
2053 
2054 #if DEBUG > 0
2055   printf("Adding to %d\n", hash(win->window));
2056 #endif
2057 
2058   new = &hashtable[hash(win->window)];
2059   while (*new != NULL)
2060     {
2061       new = &((*new)->next);
2062     }
2063   *new = (struct windowlist *) malloc(sizeof(struct windowlist));
2064 
2065   (*new)->next = NULL;
2066   (*new)->window = win;
2067 }
2068 
2069 W_Window
W_MakeScrollingWindow(name,x,y,width,height,parent,border)2070 W_MakeScrollingWindow(name, x, y, width, height, parent, border)
2071 char   *name;
2072 int     x, y, width, height;
2073 W_Window parent;
2074 int     border;
2075 {
2076   struct window *newwin;
2077   Window  wparent;
2078   XSetWindowAttributes attrs;
2079   XSizeHints *sz_hints;
2080   int     gcheck_result;
2081   struct scrollingWindow *sw;
2082   int     scw = (scrollbar ? scroll_thumb_width : 0);
2083 
2084 #if DEBUG > 0
2085   printf("New window...\n");
2086 #endif
2087 
2088   gcheck_result = checkGeometry(name, &x, &y, &width, &height);
2089   checkParent(name, &parent);
2090   wparent = W_Void2Window(parent)->window;
2091   attrs.border_pixel = colortable[W_White].pixelValue;
2092   attrs.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask;
2093 
2094 #ifdef AUTOKEY
2095   attrs.event_mask |= KeyReleaseMask;
2096 #endif /* AUTOKEY */
2097 
2098   attrs.background_pixel = colortable[W_Black].pixelValue;
2099 
2100   /* NOTE: CWDontPropagate seems to crash in OpenWindows */
2101   attrs.do_not_propagate_mask = ResizeRedirectMask | ExposureMask;
2102   newwin = newWindow(
2103 		      XCreateWindow(W_Display, wparent, x, y,
2104 				    width * W_Textwidth + WIN_EDGE * 2 + scw,
2105 				    MENU_PAD * 2 + height * W_Textheight,
2106 			border, CopyFromParent, InputOutput, CopyFromParent,
2107 				    CWBackPixel | CWEventMask |
2108 				    CWBorderPixel /* | CWDontPropagate */ ,
2109 				    &attrs), WIN_SCROLL);
2110   class_hint.res_name = name;
2111   sz_hints = XAllocSizeHints();
2112   sz_hints->width_inc = W_Textwidth;
2113   sz_hints->height_inc = W_Textheight;
2114   sz_hints->min_width = WIN_EDGE * 2 + W_Textwidth + scw;
2115   sz_hints->min_height = MENU_PAD * 2 + W_Textheight;
2116   sz_hints->base_width = WIN_EDGE * 2 + scw;
2117   sz_hints->base_height = MENU_PAD * 2;
2118   sz_hints->flags = PResizeInc | PMinSize | PBaseSize;
2119   if (gcheck_result & XValue || gcheck_result & YValue)
2120     sz_hints->flags |= WMXYHintMode_default();
2121   XStoreName(W_Display, newwin->window, name);
2122   XSetWMNormalHints(W_Display, newwin->window, sz_hints);
2123   XFree((void *) sz_hints);
2124   XSetClassHint(W_Display, newwin->window, &class_hint);
2125   XSetWMHints(W_Display, newwin->window, &wm_hint);
2126   newwin->name = strdup(name);
2127   sw = (struct scrollingWindow *) malloc(sizeof(struct scrollingWindow));
2128 
2129   sw->lines = 0;
2130   sw->updated = 0;
2131   sw->head = sw->tail = sw->index = NULL;
2132   sw->topline = 0;
2133   newwin->data = (char *) sw;
2134   newwin->width = width;
2135   newwin->height = height;
2136   if (wparent != W_Root)
2137     if (checkMapped(name))
2138       W_MapWindow(W_Window2Void(newwin));
2139 
2140 #if DEBUG > 0
2141   printf("New scroll window %d, child of %d\n", newwin, parent);
2142 #endif
2143 
2144   XSetWindowColormap(W_Display, newwin->window, W_Colormap);
2145   return W_Window2Void(newwin);
2146 }
2147 
2148 /*
2149  * Add a string to the string list of the scrolling window.
2150  */
2151 static void
AddToScrolling(win,color,font,str,len)2152         AddToScrolling(win, color, font, str, len)
2153 struct window *win;
2154 W_Color color;
2155 W_Font  font;
2156 char   *str;
2157 int     len;
2158 {
2159   struct scrollingWindow *sw;
2160   struct stringList *new;
2161 
2162   /* simple, fast */
2163 
2164   sw = (struct scrollingWindow *) win->data;
2165   if (sw->lines > 0 && sw->lines > scroll_lines /* some large number */ )
2166     {
2167       /* resuse tail */
2168       new = sw->tail;
2169       sw->tail = new->prev;
2170       new->prev->next = NULL;
2171       new->prev = NULL;
2172       new->next = sw->head;
2173       sw->head->prev = new;
2174       sw->head = new;
2175     }
2176   else
2177     {
2178       new = (struct stringList *) malloc(sizeof(struct stringList));
2179 
2180       new->next = sw->head;
2181       new->prev = NULL;
2182       if (sw->head)
2183 	sw->head->prev = new;
2184       sw->head = new;
2185       if (!sw->tail)
2186 	sw->tail = new;
2187       sw->lines++;
2188       /*
2189        * printf("adding one line \"%s\" C:%d F:%d.\n", str, color,
2190        * fontNum(font)); */
2191     }
2192   sw->index = sw->head;				 /* input forces to end of *
2193 						  * list */
2194   sw->topline = 0;
2195 
2196   sw->updated++;				 /* mark for *
2197 						  * W_FlushScrollingWindow */
2198 
2199   STRNCPY(new->string, str, MAX_TEXT_WIDTH - 1);
2200   new->color = color;
2201   new->font = font;
2202 
2203   if (len >= MAX_TEXT_WIDTH)
2204     {
2205       new->string[MAX_TEXT_WIDTH - 1] = 0;
2206     }
2207   else
2208     {
2209       /* we pad out the string with spaces so we don't have to clear the *
2210        * window */
2211       memset(&new->string[len], ' ', MAX_TEXT_WIDTH - len - 1);
2212       new->string[MAX_TEXT_WIDTH - 1] = 0;
2213     }
2214 }
2215 
2216 void
W_FlushScrollingWindow(window)2217         W_FlushScrollingWindow(window)
2218 
2219 W_Window window;
2220 {
2221   struct window *win = W_Void2Window(window);
2222   struct scrollingWindow *sw;
2223 
2224   if (!win->mapped)
2225     return;
2226   if (win->type != WIN_SCROLL)
2227     {
2228       fprintf(stderr, "bad window type in W_FlushScrollingWindow.\n");
2229       return;
2230     }
2231   sw = (struct scrollingWindow *) win->data;
2232   if (!sw->updated)
2233     return;
2234 
2235 #ifndef NO_COPYAREA
2236   else
2237     {
2238       struct stringList *item;
2239       int y;
2240 
2241       if (win->height > sw->updated)
2242 	{
2243 	  XCopyArea(W_Display, win->window, win->window,
2244 		    colortable[W_White].contexts[0],
2245 		    WIN_EDGE, MENU_PAD + sw->updated * W_Textheight,
2246 		    win->width * W_Textwidth,
2247 		    (win->height - sw->updated) * W_Textheight,
2248 		    WIN_EDGE, MENU_PAD);
2249 	}
2250 
2251 
2252       y = (win->height - 1) * W_Textheight + fonts[1].baseline;
2253 
2254       for (item = sw->index; item && y > 0 && sw->updated; item = item->next,
2255 	   y -= W_Textheight,
2256 	   sw->updated--)
2257 	{
2258 	  XDrawImageString(W_Display, win->window,
2259 		      colortable[item->color].contexts[fontNum(item->font)],
2260 			   WIN_EDGE, MENU_PAD + y, item->string,
2261 			   win->width);
2262 	}
2263       sw->updated = 0;
2264       if (scrollbar)
2265 	drawThumb(win, sw);
2266     }
2267 #else
2268   redrawScrolling(win);
2269 #endif
2270 }
2271 
2272 static void
drawThumb(win,sw)2273         drawThumb(win, sw)
2274 
2275 struct window *win;
2276 struct scrollingWindow *sw;
2277 {
2278   int x, y, h;
2279   int savedlines, maxrow, thumbTop, thumbHeight, totalHeight, winheight;
2280 
2281 /*
2282  * savedlines : Number of offscreen text lines,
2283  * sw->lines - win->height
2284  *
2285  * maxrow + 1 : Number of onscreen  text lines,
2286  *
2287  * min(sw->lines + 1, win->height+1)
2288  *
2289  * sw->topline    : -Number of lines above the last max_row+1 lines
2290  *
2291  * thumbTop    = screen->topline + screen->savedlines;
2292  * thumbHeight = screen->max_row + 1;
2293  * totalHeight = thumbHeight + screen->savedlines;
2294  *
2295  * XawScrollbarSetThumb(scrollWidget,
2296  * ((float)thumbTop) / totalHeight,
2297  * ((float)thumbHeight) / totalHeight);
2298  */
2299 
2300   savedlines = sw->lines - win->height;
2301   if (savedlines < 0)
2302     savedlines = 0;
2303   maxrow = sw->lines < win->height ? sw->lines : win->height;
2304   winheight = win->height * W_Textheight + MENU_PAD * 2;
2305 
2306   thumbTop = sw->topline + savedlines;
2307   thumbHeight = maxrow + 1;
2308   totalHeight = thumbHeight + savedlines;
2309 
2310   x = win->width * W_Textwidth + WIN_EDGE * 2;
2311   y = winheight * thumbTop / totalHeight;
2312   h = winheight * thumbHeight / totalHeight;
2313 
2314   XClearArea(W_Display, win->window, x, 0, scroll_thumb_width, winheight,
2315 	     False);
2316   XFillRectangle(W_Display, win->window, scroll_thumb_gc,
2317 		 x, y,
2318 		 scroll_thumb_width, h);
2319   XDrawLine(W_Display, win->window, colortable[W_Red].contexts[0],
2320 	    x, 0, x, winheight);
2321 }
2322 
2323 static void
redrawScrolling(win)2324         redrawScrolling(win)
2325 struct window *win;
2326 {
2327   int     y;
2328   struct scrollingWindow *sw;
2329   register struct stringList *item;
2330 
2331   if (!win->mapped)
2332     return;
2333 
2334   /* simple, fast */
2335 
2336   sw = (struct scrollingWindow *) win->data;
2337   if (!sw->lines)
2338     return;
2339   sw->updated = 0;
2340 
2341   y = (win->height - 1) * W_Textheight + fonts[1].baseline;
2342   for (item = sw->index; item && y > 0; item = item->next, y -= W_Textheight)
2343     {
2344       XDrawImageString(W_Display, win->window,
2345 		       colortable[item->color].contexts[fontNum(item->font)],
2346 		       WIN_EDGE, MENU_PAD + y, item->string,
2347 		       win->width);
2348     }
2349   if (scrollbar)
2350     drawThumb(win, sw);
2351 }
2352 
2353 #ifdef SHORT_PACKETS
W_SetSensitive(W_Window w,int v)2354 void W_SetSensitive(W_Window w, int v)
2355 {
2356   struct window *win = W_Void2Window(w);
2357 
2358   win->insensitive = !v;
2359 
2360   if (win->type == WIN_SCROLL)
2361     redrawScrolling(win);
2362 }
2363 #endif
2364 
2365 W_Window
W_MakeMenu(char * name,int x,int y,int width,int height,W_Window parent,int border)2366 W_MakeMenu(char *name, int x, int y, int width, int height, W_Window parent, int border)
2367 {
2368   struct window *newwin;
2369   struct menuItem *items;
2370   Window  wparent;
2371   int     i;
2372   XSetWindowAttributes attrs;
2373 
2374 #if DEBUG > 0
2375   printf("New window...\n");
2376 #endif
2377 
2378   checkGeometry(name, &x, &y, &width, &height);
2379   checkParent(name, &parent);
2380   wparent = W_Void2Window(parent)->window;
2381   attrs.border_pixel = colortable[W_White].pixelValue;
2382   attrs.event_mask = KeyPressMask | ButtonPressMask | ExposureMask;
2383 
2384 #ifdef AUTOKEY
2385   attrs.event_mask |= KeyReleaseMask;
2386 #endif /* AUTOKEY */
2387 
2388   attrs.background_pixel = colortable[W_Black].pixelValue;
2389   attrs.do_not_propagate_mask = KeyPressMask | ButtonPressMask | ExposureMask;
2390   newwin = newWindow(
2391 		      XCreateWindow(W_Display, wparent, x, y,
2392 				    width * W_Textwidth + WIN_EDGE * 2,
2393    height * (W_Textheight + MENU_PAD * 2) + (height - 1) * MENU_BAR, border,
2394 				CopyFromParent, InputOutput, CopyFromParent,
2395 				    CWBackPixel | CWEventMask |
2396 				    CWBorderPixel,
2397 				    &attrs),
2398 		      WIN_MENU);
2399   class_hint.res_name = name;
2400   XSetClassHint(W_Display, newwin->window, &class_hint);
2401   XSetWMHints(W_Display, newwin->window, &wm_hint);
2402   XStoreName(W_Display, newwin->window, name);
2403   newwin->name = strdup(name);
2404   items = (struct menuItem *) malloc(height * sizeof(struct menuItem));
2405 
2406   for (i = 0; i < height; i++)
2407     {
2408       /* new: allocate once and reuse -tsh */
2409       items[i].column = 0;
2410       items[i].string = (char *) malloc(MAX_TEXT_WIDTH);
2411       items[i].color = W_White;
2412     }
2413   newwin->data = (char *) items;
2414   newwin->width = width;
2415   newwin->height = height;
2416   if (wparent != W_Root)
2417     if (checkMapped(name))
2418       W_MapWindow(W_Window2Void(newwin));
2419 
2420 #if DEBUG > 0
2421   printf("New menu window %d, child of %d\n", newwin, parent);
2422 #endif
2423 
2424   XSetWindowColormap(W_Display, newwin->window, W_Colormap);
2425   return W_Window2Void(newwin);
2426 }
2427 
redrawMenu(struct window * win)2428 void redrawMenu(struct window * win)
2429 {
2430   int     count;
2431 
2432   for (count = 1; count < win->height; count++)
2433     {
2434       XFillRectangle(W_Display, win->window,
2435 		     colortable[W_Grey].contexts[0],
2436 	  0, count * (W_Textheight + MENU_PAD * 2) + (count - 1) * MENU_BAR,
2437 		     win->width * W_Textwidth + WIN_EDGE * 2, MENU_BAR);
2438     }
2439   for (count = 0; count < win->height; count++)
2440     {
2441       redrawMenuItem(win, count);
2442     }
2443 }
2444 
redrawMenuItem(struct window * win,int n)2445 void redrawMenuItem(struct window *win, int n)
2446 {
2447   struct menuItem *items;
2448 
2449   items = (struct menuItem *) win->data;
2450   XFillRectangle(W_Display, win->window,
2451 		 colortable[W_Black].contexts[0],
2452 	  WIN_EDGE, n * (W_Textheight + MENU_PAD * 2 + MENU_BAR) + MENU_PAD,
2453 		 win->width * W_Textwidth, W_Textheight);
2454   if (items[n].string)
2455     {
2456       XDrawImageString(W_Display, win->window,
2457 		       colortable[items[n].color].contexts[1],
2458 		       WIN_EDGE + W_Textwidth * items[n].column,
2459 		       n * (W_Textheight + MENU_PAD * 2 + MENU_BAR) + MENU_PAD + fonts[1].baseline,
2460 		       items[n].string, strlen(items[n].string));
2461     }
2462 }
2463 
changeMenuItem(struct window * win,int col,int n,char * str,W_Color color)2464 static void changeMenuItem(struct window *win, int col, int n, char *str, W_Color color)
2465 {
2466   struct menuItem *items;
2467 
2468   items = (struct menuItem *) win->data;
2469 
2470   STRNCPY(items[n].string, str, MAX_TEXT_WIDTH - 1);
2471   items[n].string[MAX_TEXT_WIDTH - 1] = 0;
2472   items[n].color = color;
2473   items[n].column = col;
2474   redrawMenuItem(win, n);
2475 }
2476 
2477 void
W_DefineMapcursor(W_Window window)2478         W_DefineMapcursor(W_Window window)
2479 {
2480   Cursor  new;
2481   Pixmap  mapcursmaskbit;
2482   Pixmap  mapcursbit;
2483   struct window *win = W_Void2Window(window);
2484   char   *path;
2485   static
2486   XColor  f, b;
2487   int     w, h, xh, yh;
2488 
2489   xh = yh = 5;
2490   f.pixel = colortable[W_White].pixelValue;
2491   b.pixel = colortable[W_Black].pixelValue;
2492 
2493   XQueryColor(W_Display, W_Colormap, &f);
2494   XQueryColor(W_Display, W_Colormap, &b);
2495 
2496   mapcursbit = XCreateBitmapFromData(W_Display, win->window, mapcursor_bits,
2497 				     mapcursor_width, mapcursor_height);
2498 
2499   if ((path = getdefault("mapCursorDef")))
2500     {
2501 
2502       if (W_LoadBitmap(window, path, &mapcursmaskbit, &w, &h, &xh, &yh) != 1)
2503 	{
2504 	  mapcursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2505 			       mapmask_bits, mapmask_width, mapmask_height);
2506 	  xh = yh = 5;
2507 	}
2508       else
2509 	{
2510 	  mapcursbit = XCreatePixmap(W_Display, win->window, w, h, 1);
2511 	  XFillRectangle(W_Display, mapcursbit,
2512 			 colortable[W_White].contexts[0], 0, 0, w, h);
2513 	}
2514     }
2515 
2516   else
2517     mapcursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2518 			       mapmask_bits, mapmask_width, mapmask_height);
2519 
2520   if (win->cursor)
2521     XFreeCursor(W_Display, win->cursor);
2522 
2523   new = XCreatePixmapCursor(W_Display, mapcursbit, mapcursmaskbit,
2524 			    &b, &f, xh, yh);
2525   XRecolorCursor(W_Display, new, &b, &f);
2526   XDefineCursor(W_Display, win->window, new);
2527   win->cursor = new;
2528 }
2529 
2530 void
W_DefineLocalcursor(W_Window window)2531         W_DefineLocalcursor(W_Window window)
2532 {
2533   Cursor  new;
2534   Pixmap  localcursmaskbit;
2535   Pixmap  localcursbit;
2536   struct window *win = W_Void2Window(window);
2537   char   *path;
2538   static
2539   XColor  f, b;
2540   int     w, h, xh, yh;
2541 
2542   xh = yh = 5;
2543   f.pixel = colortable[W_White].pixelValue;
2544   b.pixel = colortable[W_Black].pixelValue;
2545 
2546   XQueryColor(W_Display, W_Colormap, &f);
2547   XQueryColor(W_Display, W_Colormap, &b);
2548 
2549   localcursbit = XCreateBitmapFromData(W_Display, win->window,
2550 		   localcursor_bits, localcursor_width, localcursor_height);
2551 
2552   if ((path = getdefault("localCursorDef")))
2553     {
2554       if (W_LoadBitmap(window, path, &localcursmaskbit, &w, &h, &xh, &yh) != 1)
2555 	{
2556 	  localcursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2557 			 localmask_bits, localmask_width, localmask_height);
2558 	  xh = yh = 5;
2559 	}
2560       else
2561 	{
2562 	  localcursbit = XCreatePixmap(W_Display, win->window, w, h, 1);
2563 	  XFillRectangle(W_Display, localcursbit,
2564 			 colortable[W_White].contexts[0], 0, 0, w, h);
2565 	}
2566     }
2567   else
2568     localcursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2569 			 localmask_bits, localmask_width, localmask_height);
2570 
2571   if (win->cursor)
2572     XFreeCursor(W_Display, win->cursor);
2573 
2574   new = XCreatePixmapCursor(W_Display, localcursbit, localcursmaskbit,
2575 			    &b, &f, xh, yh);
2576   XRecolorCursor(W_Display, new, &b, &f);
2577   XDefineCursor(W_Display, win->window, new);
2578   win->cursor = new;
2579 }
2580 
2581 void
W_DefineFedCursor(W_Window window)2582         W_DefineFedCursor(W_Window window)
2583 {
2584   Cursor  new;
2585   Pixmap  fedcursmaskbit;
2586   Pixmap  fedcursbit;
2587   struct window *win = W_Void2Window(window);
2588 
2589   static
2590   XColor  f, b;
2591 
2592   f.pixel = colortable[W_White].pixelValue;
2593   b.pixel = colortable[W_Black].pixelValue;
2594 
2595   XQueryColor(W_Display, W_Colormap, &f);
2596   XQueryColor(W_Display, W_Colormap, &b);
2597 
2598   fedcursbit = XCreateBitmapFromData(W_Display, win->window, fed_cruiser_bits,
2599 				     fed_cruiser_width, fed_cruiser_height);
2600   fedcursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2601 			    fed_mask_bits, fed_mask_width, fed_mask_height);
2602   if (win->cursor)
2603     XFreeCursor(W_Display, win->cursor);
2604 
2605   new = XCreatePixmapCursor(W_Display, fedcursmaskbit, fedcursbit,
2606 			    &b, &f, 10, 10);
2607   XRecolorCursor(W_Display, new, &b, &f);
2608   XDefineCursor(W_Display, win->window, new);
2609   win->cursor = new;
2610 }
2611 
2612 void
W_DefineRomCursor(W_Window window)2613         W_DefineRomCursor(W_Window window)
2614 {
2615   Cursor  new;
2616   Pixmap  romcursmaskbit;
2617   Pixmap  romcursbit;
2618   struct window *win = W_Void2Window(window);
2619 
2620   static
2621   XColor  f, b;
2622 
2623   f.pixel = colortable[W_White].pixelValue;
2624   b.pixel = colortable[W_Black].pixelValue;
2625 
2626   XQueryColor(W_Display, W_Colormap, &f);
2627   XQueryColor(W_Display, W_Colormap, &b);
2628 
2629   romcursbit = XCreateBitmapFromData(W_Display, win->window, rom_cruiser_bits,
2630 				     rom_cruiser_width, rom_cruiser_height);
2631   romcursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2632 		      rom_mask_bits, rom_cruiser_width, rom_cruiser_height);
2633   if (win->cursor)
2634     XFreeCursor(W_Display, win->cursor);
2635 
2636   new = XCreatePixmapCursor(W_Display, romcursmaskbit, romcursbit,
2637 			    &b, &f, 10, 10);
2638   XRecolorCursor(W_Display, new, &b, &f);
2639   XDefineCursor(W_Display, win->window, new);
2640   win->cursor = new;
2641 }
2642 
2643 void
W_DefineKliCursor(W_Window window)2644         W_DefineKliCursor(W_Window window)
2645 {
2646   Cursor  new;
2647   Pixmap  klicursmaskbit;
2648   Pixmap  klicursbit;
2649   struct window *win = W_Void2Window(window);
2650 
2651   static
2652   XColor  f, b;
2653 
2654   f.pixel = colortable[W_White].pixelValue;
2655   b.pixel = colortable[W_Black].pixelValue;
2656 
2657   XQueryColor(W_Display, W_Colormap, &f);
2658   XQueryColor(W_Display, W_Colormap, &b);
2659 
2660   klicursbit = XCreateBitmapFromData(W_Display, win->window, kli_cruiser_bits,
2661 				     kli_cruiser_width, kli_cruiser_height);
2662   klicursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2663 		      fed_mask_bits, kli_cruiser_width, kli_cruiser_height);
2664   if (win->cursor)
2665     XFreeCursor(W_Display, win->cursor);
2666 
2667   new = XCreatePixmapCursor(W_Display, klicursmaskbit, klicursbit,
2668 			    &b, &f, 10, 10);
2669   XRecolorCursor(W_Display, new, &b, &f);
2670   XDefineCursor(W_Display, win->window, new);
2671   win->cursor = new;
2672 }
2673 
2674 void
W_DefineOriCursor(W_Window window)2675         W_DefineOriCursor(W_Window window)
2676 {
2677   Cursor  new;
2678   Pixmap  oricursmaskbit;
2679   Pixmap  oricursbit;
2680   struct window *win = W_Void2Window(window);
2681 
2682   static
2683   XColor  f, b;
2684 
2685   f.pixel = colortable[W_White].pixelValue;
2686   b.pixel = colortable[W_Black].pixelValue;
2687 
2688   XQueryColor(W_Display, W_Colormap, &f);
2689   XQueryColor(W_Display, W_Colormap, &b);
2690 
2691   oricursbit = XCreateBitmapFromData(W_Display, win->window, ori_cruiser_bits,
2692 				     ori_cruiser_width, ori_cruiser_height);
2693   oricursmaskbit = XCreateBitmapFromData(W_Display, win->window,
2694 		      fed_mask_bits, ori_cruiser_width, ori_cruiser_height);
2695   if (win->cursor)
2696     XFreeCursor(W_Display, win->cursor);
2697 
2698   new = XCreatePixmapCursor(W_Display, oricursmaskbit, oricursbit,
2699 			    &b, &f, 10, 10);
2700   XRecolorCursor(W_Display, new, &b, &f);
2701   XDefineCursor(W_Display, win->window, new);
2702   win->cursor = new;
2703 }
2704 
2705 void
W_DefineTrekCursor(W_Window window)2706         W_DefineTrekCursor(W_Window window)
2707 {
2708   Cursor  new;
2709   struct window *win = W_Void2Window(window);
2710   XColor  f, b;
2711   char   *path;
2712   int     w, h, xh, yh, mw, mh, mxh, myh;
2713 
2714   f.pixel = colortable[W_Yellow].pixelValue;
2715   b.pixel = colortable[W_Black].pixelValue;
2716 
2717   XQueryColor(W_Display, W_Colormap, &f);
2718   XQueryColor(W_Display, W_Colormap, &b);
2719 
2720   if (win->cursor)
2721     XFreeCursor(W_Display, win->cursor);
2722 
2723   if ((path = getdefault("infoCursorDef")))
2724     {
2725       Pixmap  pm, mpm;
2726 
2727       if (W_LoadBitmap(window, path, &pm, &w, &h, &xh, &yh) != 1)
2728 	new = XCreateFontCursor(W_Display, XC_trek);
2729       else
2730 	{
2731 	  char    mask_path[512];
2732 
2733 	  strcpy(mask_path, path);
2734 	  strcat(mask_path, ".mask");
2735 
2736 	  if (W_LoadBitmap(window, mask_path, &mpm, &mw, &mh, &mxh, &myh) != 1)
2737 	    {
2738 	      mw = w;
2739 	      mh = h;
2740 	      mpm = XCreatePixmap(W_Display, win->window, w, h, 1);
2741 	      XFillRectangle(W_Display, mpm,
2742 			     colortable[W_White].contexts[0], 0, 0, w, h);
2743 	    }
2744 
2745 	  if ((w != mw) || (h != mh))
2746 	    {
2747 	      printf("Cursor and mask are not the same size. %s\n", path);
2748 	      new = XCreateFontCursor(W_Display, XC_trek);
2749 	    }
2750 	  else
2751 	    new = XCreatePixmapCursor(W_Display, pm, mpm,
2752 				      &b, &f, xh, yh);
2753 	}
2754     }
2755   else
2756     new = XCreateFontCursor(W_Display, XC_trek);
2757 
2758   XRecolorCursor(W_Display, new, &f, &b);
2759   XDefineCursor(W_Display, win->window, new);
2760   win->cursor = new;
2761 }
2762 
2763 void
W_DefineWarningCursor(W_Window window)2764         W_DefineWarningCursor(W_Window window)
2765 {
2766   Cursor  new;
2767   struct window *win = W_Void2Window(window);
2768   XColor  f, b;
2769 
2770   f.pixel = colortable[W_Red].pixelValue;
2771   b.pixel = colortable[W_Black].pixelValue;
2772 
2773   XQueryColor(W_Display, W_Colormap, &f);
2774   XQueryColor(W_Display, W_Colormap, &b);
2775 
2776   if (win->cursor)
2777     XFreeCursor(W_Display, win->cursor);
2778 
2779   new = XCreateFontCursor(W_Display, XC_pirate);
2780   XRecolorCursor(W_Display, new, &f, &b);
2781   XDefineCursor(W_Display, win->window, new);
2782   win->cursor = new;
2783 }
2784 
2785 void
W_DefineArrowCursor(W_Window window)2786         W_DefineArrowCursor(W_Window window)
2787 {
2788   Cursor  new;
2789   struct window *win = W_Void2Window(window);
2790   XColor  f, b;
2791   char   *path;
2792   int     w, h, xh, yh, mw, mh, mxh, myh;
2793 
2794   f.pixel = colortable[W_Black].pixelValue;
2795   b.pixel = colortable[W_White].pixelValue;
2796 
2797   XQueryColor(W_Display, W_Colormap, &f);
2798   XQueryColor(W_Display, W_Colormap, &b);
2799 
2800   if (win->cursor)
2801     XFreeCursor(W_Display, win->cursor);
2802 
2803   if ((path = getdefault("arrowCursorDef")))
2804     {
2805       Pixmap  pm, mpm;
2806 
2807       if (W_LoadBitmap(window, path, &pm, &w, &h, &xh, &yh) != 1)
2808 	new = XCreateFontCursor(W_Display, XC_left_ptr);
2809       else
2810 	{
2811 	  char    mask_path[512];
2812 
2813 	  strcpy(mask_path, path);
2814 	  strcat(mask_path, ".mask");
2815 
2816 	  if (W_LoadBitmap(window, mask_path, &mpm, &mw, &mh, &mxh, &myh) != 1)
2817 	    {
2818 	      mw = w;
2819 	      mh = h;
2820 	      mpm = XCreatePixmap(W_Display, win->window, w, h, 1);
2821 	      XFillRectangle(W_Display, mpm,
2822 			     colortable[W_White].contexts[0], 0, 0, w, h);
2823 	    }
2824 
2825 	  if ((w != mw) || (h != mh))
2826 	    {
2827 	      printf("Cursor and mask are not the same size. %s\n", path);
2828 	      new = XCreateFontCursor(W_Display, XC_left_ptr);
2829 	    }
2830 	  else
2831 	    new = XCreatePixmapCursor(W_Display, pm, mpm,
2832 				      &b, &f, xh, yh);
2833 	}
2834     }
2835   else
2836     new = XCreateFontCursor(W_Display, XC_left_ptr);
2837 
2838   XRecolorCursor(W_Display, new, &f, &b);
2839   XDefineCursor(W_Display, win->window, new);
2840   win->cursor = new;
2841 }
2842 
2843 void
W_DefineTextCursor(W_Window window)2844         W_DefineTextCursor(W_Window window)
2845 {
2846   Cursor  new;
2847   struct window *win = W_Void2Window(window);
2848   XColor  f, b;
2849   char   *path;
2850   int     w, h, xh, yh, mw, mh, mxh, myh;
2851 
2852   f.pixel = colortable[W_Yellow].pixelValue;
2853   b.pixel = colortable[W_Black].pixelValue;
2854 
2855   XQueryColor(W_Display, W_Colormap, &f);
2856   XQueryColor(W_Display, W_Colormap, &b);
2857 
2858   if (win->cursor)
2859     XFreeCursor(W_Display, win->cursor);
2860 
2861   if ((path = getdefault("textCursorDef")))
2862     {
2863       Pixmap  pm, mpm;
2864 
2865       if (W_LoadBitmap(window, path, &pm, &w, &h, &xh, &yh) != 1)
2866 	new = XCreateFontCursor(W_Display, XC_xterm);
2867       else
2868 	{
2869 	  char    mask_path[512];
2870 
2871 	  strcpy(mask_path, path);
2872 	  strcat(mask_path, ".mask");
2873 
2874 	  if (W_LoadBitmap(window, mask_path, &mpm, &mw, &mh, &mxh, &myh) != 1)
2875 	    {
2876 	      mw = w;
2877 	      mh = h;
2878 	      mpm = XCreatePixmap(W_Display, win->window, w, h, 1);
2879 	      XFillRectangle(W_Display, mpm,
2880 			     colortable[W_White].contexts[0], 0, 0, w, h);
2881 	    }
2882 
2883 	  if ((w != mw) || (h != mh))
2884 	    {
2885 	      printf("Cursor and mask are not the same size. %s\n", path);
2886 	      new = XCreateFontCursor(W_Display, XC_xterm);
2887 	    }
2888 	  else
2889 	    new = XCreatePixmapCursor(W_Display, pm, mpm,
2890 				      &b, &f, xh, yh);
2891 	}
2892     }
2893   else
2894     new = XCreateFontCursor(W_Display, XC_xterm);
2895 
2896   XRecolorCursor(W_Display, new, &f, &b);
2897   XDefineCursor(W_Display, win->window, new);
2898   win->cursor = new;
2899 }
2900 
2901 void
W_DefineCursor(W_Window window,int width,int height,char * bits,char * mask,int xhot,int yhot)2902         W_DefineCursor(W_Window window, int width, int height, char *bits, char *mask, int xhot, int yhot)
2903 {
2904   static char *oldbits = NULL;
2905   static Cursor curs;
2906   Pixmap  cursbits;
2907   Pixmap  cursmask;
2908   struct window *win;
2909   XColor  whiteCol, blackCol;
2910 
2911 #if DEBUG > 0
2912   printf("Defining cursor for %d\n", window);
2913 #endif
2914 
2915   win = W_Void2Window(window);
2916   whiteCol.pixel = colortable[W_White].pixelValue;
2917   XQueryColor(W_Display, W_Colormap, &whiteCol);
2918   blackCol.pixel = colortable[W_Black].pixelValue;
2919   XQueryColor(W_Display, W_Colormap, &blackCol);
2920   if (!oldbits || oldbits != bits)
2921     {
2922       cursbits = XCreateBitmapFromData(W_Display, win->window,
2923 				       bits, width, height);
2924       cursmask = XCreateBitmapFromData(W_Display, win->window,
2925 				       mask, width, height);
2926       oldbits = bits;
2927       curs = XCreatePixmapCursor(W_Display, cursbits, cursmask,
2928 				 &whiteCol, &blackCol, xhot, yhot);
2929       XFreePixmap(W_Display, cursbits);
2930       XFreePixmap(W_Display, cursmask);
2931     }
2932   XDefineCursor(W_Display, win->window, curs);
2933 }
2934 
2935 int
W_LoadBitmap(W_Window window,char * path,Pixmap * pixmap,int * width,int * height,int * x_hot,int * y_hot)2936         W_LoadBitmap(W_Window window, char *path, Pixmap * pixmap, int *width, int *height, int *x_hot, int *y_hot)
2937 {
2938   int     status;
2939   struct window *win;
2940 
2941   win = W_Void2Window(window);
2942 
2943   status = XReadBitmapFile(W_Display, win->window, path, (unsigned int *) width,
2944 			   (unsigned int *) height, pixmap, x_hot, y_hot);
2945 
2946   if (status == BitmapSuccess)
2947     {
2948       if (*x_hot < 0)
2949 	{
2950 	  *x_hot = *width / 2;
2951 	  *y_hot = *height / 2;
2952 	}
2953 
2954       return 1;
2955     }
2956   else
2957     return 0;
2958 }
2959 
2960 void
W_Beep(void)2961         W_Beep(void)
2962 {
2963   XBell(W_Display, 0);
2964 }
2965 
2966 int
W_WindowWidth(W_Window window)2967         W_WindowWidth(W_Window window)
2968 {
2969   return W_Void2Window(window)->width;
2970 }
2971 
2972 int
W_WindowHeight(W_Window window)2973         W_WindowHeight(W_Window window)
2974 {
2975   return W_Void2Window(window)->height;
2976 }
2977 
2978 int
W_Socket(void)2979         W_Socket(void)
2980 {
2981   return ConnectionNumber(W_Display);
2982 }
2983 
2984 void
W_DestroyWindow(W_Window window)2985         W_DestroyWindow(W_Window window)
2986 {
2987   struct window *win;
2988 
2989 #if DEBUG > 0
2990   printf("Destroying %d\n", window);
2991 #endif
2992 
2993   win = W_Void2Window(window);
2994   deleteWindow(win);
2995   XDestroyWindow(W_Display, win->window);
2996   free((char *) win);
2997 }
2998 
deleteWindow(struct window * window)2999 void deleteWindow(struct window *window)
3000 {
3001   struct windowlist **rm;
3002   struct windowlist *temp;
3003 
3004   rm = &hashtable[hash(window->window)];
3005   while (*rm != NULL && (*rm)->window != window)
3006     {
3007       rm = &((*rm)->next);
3008     }
3009   if (*rm == NULL)
3010     {
3011       printf("Attempt to delete non-existent window!\n");
3012       return;
3013     }
3014   temp = *rm;
3015   *rm = temp->next;
3016   free((char *) temp);
3017 }
3018 
3019 void
W_SetIconWindow(W_Window main,W_Window icon)3020         W_SetIconWindow(W_Window main, W_Window icon)
3021 {
3022   XWMHints hints;
3023 
3024   XSetIconName(W_Display, W_Void2Window(icon)->window, W_Void2Window(main)->name);
3025 
3026   hints.flags = IconWindowHint;
3027   hints.icon_window = W_Void2Window(icon)->window;
3028 #ifdef WINDOWMAKER
3029   hints.window_group = W_Void2Window(main)->window;
3030   hints.flags |= WindowGroupHint;
3031 
3032   XSetCommand(W_Display, W_Void2Window(main)->window, wm_argv, wm_argc);
3033 #endif
3034 
3035   XSetWMHints(W_Display, W_Void2Window(main)->window, &hints);
3036 }
3037 
3038 static void
scrollUp(win,y)3039         scrollUp(win, y)
3040 
3041 struct window *win;
3042 int     y;
3043 {
3044   struct scrollingWindow *sw = (struct scrollingWindow *) win->data;
3045   int     savedlines = sw->lines - win->height;
3046 
3047   if (savedlines < 0)
3048     savedlines = 0;
3049 
3050   if (sw->topline + savedlines > 0)
3051     {
3052       if (!sw->index)
3053 	{
3054 	  fprintf(stderr, "scroll error, NULL index (scrollUp).\n");
3055 	  return;
3056 	}
3057       sw->index = sw->index->next;
3058       sw->topline--;
3059       redrawScrolling(win);
3060     }
3061 }
3062 
3063 static void
scrollDown(win,y)3064         scrollDown(win, y)
3065 
3066 struct window *win;
3067 int     y;
3068 {
3069   struct scrollingWindow *sw = (struct scrollingWindow *) win->data;
3070 
3071   if (sw->topline < 0)
3072     {
3073       if (!sw->index)
3074 	{
3075 	  fprintf(stderr, "scroll error, NULL index (scrollDown).\n");
3076 	  return;
3077 	}
3078       sw->index = sw->index->prev;
3079       sw->topline++;
3080       redrawScrolling(win);
3081     }
3082 }
3083 
3084 
3085 static void
scrollPosition(win,y)3086         scrollPosition(win, y)
3087 
3088 struct window *win;
3089 int     y;
3090 {
3091   struct scrollingWindow *sw = (struct scrollingWindow *) win->data;
3092   int     savedlines, maxrow, winheight, newtop;
3093 
3094   savedlines = sw->lines - win->height;
3095   if (savedlines < 0)
3096     savedlines = 0;
3097   maxrow = sw->lines < win->height ? sw->lines : win->height;
3098   winheight = win->height * W_Textheight + MENU_PAD * 2;
3099 
3100   newtop = (y * (savedlines + maxrow + 1)) / winheight - savedlines;
3101   if (newtop < -savedlines)
3102     newtop = -savedlines;
3103   else if (newtop > 0)
3104     newtop = 0;
3105   scrollTo(win, sw, newtop);
3106 }
3107 
3108 static void
scrollTo(win,sw,topline)3109         scrollTo(win, sw, topline)
3110 
3111 struct window *win;
3112 struct scrollingWindow *sw;
3113 int     topline;
3114 {
3115   while (topline < sw->topline)
3116     {
3117       if (!sw->index)
3118 	{
3119 	  fprintf(stderr, "scroll error, NULL index (1).\n");
3120 	  break;
3121 	}
3122       sw->index = sw->index->next;
3123       sw->topline--;
3124     }
3125   while (topline > sw->topline)
3126     {
3127       if (!sw->index)
3128 	{
3129 	  fprintf(stderr, "scroll error, NULL index (2).\n");
3130 	  break;
3131 	}
3132       sw->index = sw->index->prev;
3133       sw->topline++;
3134     }
3135   redrawScrolling(win);
3136 }
3137 
3138 static void
scrollScrolling(wevent)3139         scrollScrolling(wevent)
3140 
3141 W_Event *wevent;
3142 {
3143   switch (wevent->key)
3144     {
3145     case W_RBUTTON:
3146     case W_WUBUTTON:
3147       scrollUp(W_Void2Window(wevent->Window), wevent->y);
3148       break;
3149     case W_LBUTTON:
3150     case W_WDBUTTON:
3151       scrollDown(W_Void2Window(wevent->Window), wevent->y);
3152       break;
3153     case W_MBUTTON:
3154       scrollPosition(W_Void2Window(wevent->Window), wevent->y);
3155       break;
3156     default:
3157       break;
3158     }
3159 }
3160 
3161 static void
configureScrolling(win,x,y,width,height)3162         configureScrolling(win, x, y, width, height)
3163 
3164 struct window *win;
3165 int     x, y;					 /* TODO */
3166 int     width, height;
3167 
3168 {
3169   int     new_text_width, new_text_height;
3170   int     new_real_width, new_real_height;
3171   XWindowAttributes wa;
3172   int     sw = scrollbar ? scroll_thumb_width : 0;
3173 
3174 #if 0
3175   /* XXX: can't shrink window */
3176 
3177   if (width <= win->width * W_Textwidth + WIN_EDGE * 2 &&
3178       height <= win->height * W_Textheight + MENU_PAD * 2)
3179     return;
3180 #endif
3181 
3182   XGetWindowAttributes(W_Display, win->window, &wa);
3183 
3184   new_text_width = (wa.width - WIN_EDGE * 2 - sw) / W_Textwidth;
3185   new_text_height = (wa.height - MENU_PAD * 2) / W_Textheight;
3186 
3187   if (new_text_width <= 0)
3188     new_text_width = 1;
3189   if (new_text_height <= 0)
3190     new_text_height = 1;
3191   if (new_text_width >= MAX_TEXT_WIDTH)
3192     new_text_width = MAX_TEXT_WIDTH - 1;
3193 
3194   new_real_width = new_text_width * W_Textwidth + WIN_EDGE * 2 + sw;
3195   new_real_height = new_text_height * W_Textheight + MENU_PAD * 2;
3196 
3197   if (new_real_height != wa.height || new_real_width != wa.width)
3198     {
3199       XResizeWindow(W_Display, win->window, new_real_width, new_real_height);
3200     }
3201 
3202   win->width = new_text_width;
3203   win->height = new_text_height;
3204 
3205   /* an expose event will follow a resize request, triggering  *
3206    * redrawScrolling */
3207 }
3208 
3209 /*****************************************************************************/
3210 /* Looks up any default geometry specified in the defaults file and        */
3211 /* returns the values found there.  Geometry should be of the form         */
3212 /* [=][<width>x<height>][{+-}<xoffset>{+-}<yoffset>]                  */
3213 /* */
3214 /* The result returned indicates which values were set.                    */
3215 /* XValue, YValue, WidthValue, HeightValue                                */
3216 /* */
3217 /*****************************************************************************/
3218 
3219 static int
checkGeometry(char * name,int * x,int * y,int * width,int * height)3220         checkGeometry(char *name, int *x, int *y, int *width, int *height)
3221 {
3222   char    buf[80], *geom_default;
3223 
3224   sprintf(buf, "%s.geometry", name);
3225   geom_default = getdefault(buf);
3226   if (!geom_default)
3227     return 0;					 /* nothing set */
3228 
3229   return XParseGeometry(geom_default, x, y, (unsigned int *) width, (unsigned int *) height);
3230 }
3231 
checkParent(char * name,W_Window * parent)3232 void checkParent(char *name, W_Window * parent)
3233 {
3234   char   *adefault;
3235   char    buf[100];
3236   int     i;
3237   struct windowlist *windows;
3238 
3239   sprintf(buf, "%s.parent", name);
3240   adefault = getdefault(buf);
3241   if (adefault == NULL)
3242     return;
3243   /* parent must be name of other window or "root" */
3244   if (strcmpi(adefault, "root") == 0)
3245     {
3246       *parent = W_Window2Void(&myroot);
3247       return;
3248     }
3249   for (i = 0; i < HASHSIZE; i++)
3250     {
3251       windows = hashtable[i];
3252       while (windows != NULL)
3253 	{
3254 	  if (strcmpi(adefault, windows->window->name) == 0)
3255 	    {
3256 	      *parent = W_Window2Void(windows->window);
3257 	      return;
3258 	    }
3259 	  windows = windows->next;
3260 	}
3261     }
3262 }
3263 
checkMapped(char * name)3264 int checkMapped(char *name)
3265 {
3266   char    buf[100];
3267 
3268   sprintf(buf, "%s.mapped", name);
3269   return booleanDefault(buf, 0);
3270 }
3271 
checkMappedPref(char * name,int preferred)3272 int checkMappedPref(char *name, int preferred)
3273 {
3274   char    buf[100];
3275 
3276   sprintf(buf, "%s.mapped", name);
3277   return booleanDefault(buf, preferred);
3278 }
3279 
3280 void
W_WarpPointer(W_Window window,int x,int y)3281         W_WarpPointer(W_Window window, int x, int y)
3282 {
3283   static int warped_from_x = 0, warped_from_y = 0;
3284 
3285   if (window == NULL)
3286     {
3287       if (W_in_message)
3288 	{
3289 	  XWarpPointer(W_Display, None, W_Root, 0, 0, 0, 0, warped_from_x, warped_from_y);
3290 	  W_in_message = 0;
3291 	}
3292     }
3293   else
3294     {
3295       findMouse(&warped_from_x, &warped_from_y);
3296       XWarpPointer(W_Display, None, W_Void2Window(window)->window, 0, 0, 0, 0, 0, 0);
3297       W_in_message = 1;
3298     }
3299 }
3300 
findMouse(int * x,int * y)3301 void findMouse(int *x, int *y)
3302 {
3303   Window  theRoot, theChild;
3304   int     wX, wY, rootX, rootY, status;
3305   unsigned int wButtons;
3306 
3307   status = XQueryPointer(W_Display, W_Root, &theRoot, &theChild, &rootX, &rootY, &wX, &wY, &wButtons);
3308   if (status == True)
3309     {
3310       *x = wX;
3311       *y = wY;
3312     }
3313   else
3314     {
3315       *x = 0;
3316       *y = 0;
3317     }
3318 }
3319 
3320 int
findMouseInWin(int * x,int * y,W_Window w)3321         findMouseInWin(int *x, int *y, W_Window w)
3322 {
3323   Window  theRoot, theChild;
3324   int     wX, wY, rootX, rootY, status;
3325   unsigned int wButtons;
3326   struct window *win = W_Void2Window(w);
3327   Window  thisWin = win->window;
3328 
3329   status = XQueryPointer(W_Display, thisWin, &theRoot, &theChild,
3330 			 &rootX, &rootY, &wX, &wY, &wButtons);
3331   if (status == True)
3332     {
3333       /* if it's in the window we specified then the values returned should *
3334        *
3335        * * be within the with and height of the window */
3336       if (wX <= win->width && wY <= win->height)
3337 	{
3338 	  *x = wX;
3339 	  *y = wY;
3340 	  return 1;
3341 	}
3342     }
3343   *x = 0;
3344   *y = 0;
3345   return 0;
3346 }
3347 
W_Flush(void)3348 void W_Flush(void)
3349 {
3350   XFlush(W_Display);
3351 }
3352 
3353 #define MAKE_WINDOW_GETTER(name, part) \
3354   W_Callback name(W_Window w) \
3355   { \
3356     return W_Void2Window(w)->part; \
3357   }
3358 
3359 #define MAKE_WINDOW_SETTER(name, part) \
3360   void name(W_Window w, W_Callback c) \
3361   { \
3362     W_Void2Window(w)->part = c; \
3363   }
3364 
MAKE_WINDOW_GETTER(W_GetWindowKeyDownHandler,handle_keydown)3365 MAKE_WINDOW_GETTER(W_GetWindowKeyDownHandler, handle_keydown)
3366 MAKE_WINDOW_SETTER(W_SetWindowKeyDownHandler, handle_keydown)
3367 
3368 MAKE_WINDOW_GETTER(W_GetWindowKeyUpHandler, handle_keyup)
3369 MAKE_WINDOW_SETTER(W_SetWindowKeyUpHandler, handle_keyup)
3370 
3371 MAKE_WINDOW_GETTER(W_GetWindowButtonHandler, handle_button)
3372 MAKE_WINDOW_SETTER(W_SetWindowButtonHandler, handle_button)
3373 
3374 MAKE_WINDOW_GETTER(W_GetWindowExposeHandler, handle_expose)
3375 MAKE_WINDOW_SETTER(W_SetWindowExposeHandler, handle_expose)
3376 
3377 void
3378         W_ResizeWindow(W_Window window, int neww, int newh)	/* TSH 2/93 */
3379 
3380 
3381 
3382 {
3383   struct window *w = W_Void2Window(window);
3384   XSizeHints *sz_hints;
3385 
3386   sz_hints = XAllocSizeHints();
3387   sz_hints->min_width = neww;
3388   sz_hints->max_width = neww;
3389   sz_hints->min_height = newh;
3390   sz_hints->max_height = newh;
3391   sz_hints->flags = PMinSize | PMaxSize;
3392   XSetWMNormalHints(W_Display, w->window, sz_hints);
3393   XResizeWindow(W_Display, w->window, neww, newh);
3394 }
3395 
3396 void
W_ReinitMenu(W_Window window,int neww,int newh)3397 W_ReinitMenu(W_Window window, int neww, int newh)
3398 {
3399    struct window	*win = W_Void2Window(window);
3400    struct menuItem	*items;
3401    int			i;
3402 
3403    items = (struct menuItem *) win->data;
3404    for(i=0; i< win->height; i++){
3405       free((char *) items[i].string);
3406    }
3407    free ((char *)items);
3408    items = (struct menuItem *) malloc(newh * sizeof(struct menuItem));
3409    for(i=0; i< newh; i++){
3410       items[i].column = 0;
3411       items[i].string = (char *) malloc(MAX_TEXT_WIDTH);
3412       items[i].color = W_White;
3413    }
3414    win->data = (char *) items;
3415 }
3416 
3417 /* this procedure should only be used if the menu is initially defined
3418    by W_MakeMenu as large as it will get.  If menu may grow, call
3419    W_ReinitMenu first */
3420 
3421 void
W_ResizeMenu(W_Window window,int neww,int newh)3422 W_ResizeMenu(W_Window window, int neww, int newh) /* TSH 2/93 */
3423 {
3424    struct window	*w = W_Void2Window(window);
3425 
3426    w->width = neww;
3427    w->height = newh;
3428 
3429    W_ResizeWindow(window, neww*W_Textwidth+WIN_EDGE*2,
3430             newh*(W_Textheight+MENU_PAD*2)+(newh-1)*MENU_BAR);
3431 }
3432 
3433 void
W_ResizeTextWindow(W_Window window,int neww,int newh)3434         W_ResizeTextWindow(W_Window window, int neww, int newh) /* TSH 2/93 */
3435 {
3436   W_ResizeWindow(window, neww * W_Textwidth + WIN_EDGE * 2,
3437 		 newh * W_Textheight + WIN_EDGE * 2);
3438 }
3439 
3440 int
W_Mono(void)3441         W_Mono(void)
3442 {
3443   return (DisplayCells(W_Display, W_Screen) <= 2) || forceMono;
3444 }
3445 
3446 int
W_EventsQueued(void)3447         W_EventsQueued(void)
3448 {
3449   return XEventsQueued(W_Display, QueuedAlready);
3450 }
3451 
3452 int
W_EventsQueuedCk(void)3453         W_EventsQueuedCk(void)
3454 {
3455   return XEventsQueued(W_Display, QueuedAfterReading);
3456 }
3457 
W_ReadEvents(void)3458 int W_ReadEvents(void)
3459 {
3460   XEvent  event;
3461   struct timeval timeout = {0, 0};
3462   fd_set  readfds;
3463 
3464   FD_ZERO(&readfds);
3465   FD_SET(ConnectionNumber(W_Display), &readfds);
3466   if (SELECT(max_fd, &readfds, 0, 0, &timeout) == 1)
3467     {
3468       XPeekEvent(W_Display, &event);
3469       return 1;
3470     }
3471   return 0;
3472 }
3473 
W_OverlayBitmap(int x,int y,W_Icon bit,W_Color color)3474 void W_OverlayBitmap(int x, int y, W_Icon bit, W_Color color)
3475 {
3476   struct icon *icon = W_Void2Icon(bit);
3477 
3478 #if DEBUG > 4
3479   printf("Overlaying bitmap to %d\n", icon->window);
3480 #endif
3481 
3482   XCopyPlane(W_Display, icon->bitmap, icon->window,
3483 	     colortable[color].contexts[0], 0, 0, icon->width, icon->height,
3484 	     x, y, 1);
3485 }
3486 
W_SetWindowName(W_Window w,char * name)3487 void    W_SetWindowName(W_Window w, char *name)
3488 {
3489   struct window *win = W_Void2Window(w);
3490 
3491   XStoreName(W_Display, win->window, name);
3492 
3493   return;
3494 }
3495 
3496 #ifdef BEEPLITE
3497 static GC _tts_gc;
3498 static XFontStruct *_tts_fontinfo;
3499 static int _tts_th, _tts_tw;
3500 
3501 int
W_TTSTextHeight(void)3502         W_TTSTextHeight(void)
3503 {
3504   return _tts_th;
3505 }
3506 
3507 int
W_TTSTextWidth(char * s,int l)3508         W_TTSTextWidth(char *s, int l)
3509 {
3510   return XTextWidth(_tts_fontinfo, s, l);
3511 }
3512 
3513 
3514 void
init_tts(void)3515         init_tts(void)
3516 {
3517   char   *fontname;
3518   XGCValues values;
3519   char   *color;
3520   XColor  xc;
3521 
3522   fontname = getdefault("tts_font");
3523   if (!fontname)
3524     fontname = TTS_FONT;
3525 
3526 #ifdef SHOW_DEFAULTS
3527   show_defaults("TTS", "tts_font", fontname, "TTS font.");
3528 #endif
3529 
3530 #ifdef nodef
3531   if (forceMono || DisplayCells(W_Display, W_Screen) <= 2)
3532     {
3533       /* this is not going to work at all for b/w */
3534       tts_time = 0;
3535       F_beeplite_flags &= ~LITE_TTS;
3536       return;
3537     }
3538 #endif
3539 
3540   _tts_fontinfo = XLoadQueryFont(W_Display, fontname);
3541   if (!_tts_fontinfo)
3542     {
3543       fprintf(stderr, "netrek: Can't find font \"%s\".\n", fontname);
3544       _tts_fontinfo = XLoadQueryFont(W_Display, "fixed");
3545     }
3546   if (!_tts_fontinfo)
3547     {
3548       fprintf(stderr, "netrek: Can't find any fonts.\n");
3549       terminate(1);
3550     }
3551   _tts_th = _tts_fontinfo->max_bounds.descent +
3552       _tts_fontinfo->max_bounds.ascent;
3553   _tts_tw = _tts_fontinfo->max_bounds.width;
3554 
3555   values.font = _tts_fontinfo->fid;
3556 
3557   if (forceMono || DisplayCells(W_Display, W_Screen) <= 2)
3558     {
3559       values.foreground = colortable[W_White].pixelValue;
3560       values.function = GXor;
3561     }
3562 
3563   else
3564     {
3565 
3566       color = getdefault("tts_color");
3567       if (!color)
3568 	color = "grey";
3569 
3570 #ifdef SHOW_DEFAULTS
3571       show_defaults("TTS", "tts_color", color, "TTS msg color.");
3572 #endif
3573 
3574       if (!XParseColor(W_Display, W_Colormap, color, &xc))
3575 	{
3576 	  fprintf(stderr, "netrek: Unknown tts_color \"%s\", using #777\n", color);
3577 	  (void) XParseColor(W_Display, W_Colormap, "#777", &xc);
3578 	}
3579       /* using the 8th color allocated in GetColors() */
3580       xc.pixel = colortable[W_Black].pixelValue | planes[0] | planes[2];
3581       if ((takeNearest) || (W_Visual->class != PseudoColor))
3582 	XAllocColor(W_Display, W_Colormap, &xc);
3583       else
3584 	XStoreColor(W_Display, W_Colormap, &xc);
3585       values.foreground = xc.pixel;
3586       values.function = GXor;
3587     }
3588 
3589   _tts_gc = XCreateGC(W_Display, W_Root, GCFont | GCForeground | GCFunction,
3590 		      &values);
3591 
3592   XSetGraphicsExposures(W_Display, _tts_gc, False);
3593 }
3594 
3595 void
W_EraseTTSText(W_Window window,int max_width,int y,int width)3596         W_EraseTTSText(W_Window window, int max_width, int y, int width)
3597 {
3598   //  struct window *win = W_Void2Window(window);
3599   int x = (max_width - width) / 2;
3600 
3601   if (x < 0)
3602     x = 4;
3603   y -= W_TTSTextHeight();
3604 
3605   W_ClearArea(window, x, y, width, W_TTSTextHeight());
3606 }
3607 
3608 void
W_WriteTTSText(W_Window window,int max_width,int y,int width,char * str,int len)3609         W_WriteTTSText(W_Window window, int max_width, int y, int width, char *str, int len)
3610 
3611 
3612 /* max_width of window */
3613 /* y coordinate */
3614 /* actual width */
3615 /* string */
3616 /* length of string */
3617 {
3618   struct window *win = W_Void2Window(window);
3619   int x = (max_width - width) / 2;
3620 
3621   if (x < 0)
3622     x = 4;
3623 
3624   y -= _tts_fontinfo->max_bounds.descent;
3625 
3626   /* y -= W_TTSTextHeight(); y += _tts_fontinfo->max_bounds.ascent; */
3627 
3628   XDrawString(W_Display, win->window, _tts_gc, x, y, str, len);
3629 }
3630 #endif
3631 
W_Halo(int x,int y,W_Color color)3632 void    W_Halo(int x, int y, W_Color color)
3633 {
3634   struct window *win = W_Void2Window(mapw);
3635 
3636   if ((color != W_Ind) && (color != W_Grey))
3637     {
3638       XSetForeground(W_Display, colortable[color].contexts[0],
3639 		     colortable[color].pixelValue);
3640       XDrawArc(W_Display, win->window, colortable[color].contexts[0],
3641 	       x - (mplanet_width / 2), y - (mplanet_width / 2),
3642 	       mplanet_width, mplanet_height, 0, 23040);
3643     }
3644 }
3645 
W_CameraSnap(W_Window window)3646 void W_CameraSnap(W_Window window)
3647 {
3648 #ifdef CAMERA
3649   struct window *win = W_Void2Window(window);
3650   camera_snap(W_Display, win->window);
3651 #else
3652   fprintf(stderr, "W_CameraSnap: function not implemented in this build.");
3653 #endif
3654 }
3655 
3656 #ifdef FULLSCREEN
3657 
3658 /* XFree86 VidMode X extension handling */
3659 
3660 #include <X11/extensions/xf86vmode.h>
3661 
3662 XF86VidModeModeInfo **video_mode_list;
3663 XF86VidModeModeInfo *video_mode_current, *video_mode_original;
3664 int video_mode_dotclock, video_mode_list_size;
3665 
3666 /* restore video mode to known previous mode */
video_mode_off()3667 static void video_mode_off()
3668 {
3669   if (video_mode_current != video_mode_original) {
3670     XF86VidModeSwitchToMode(W_Display, W_Screen, video_mode_original);
3671     video_mode_current = video_mode_original;
3672   }
3673 }
3674 
3675 /* check if X server has support for changing modes */
video_mode_initialise()3676 static int video_mode_initialise() {
3677   int major, minor;
3678   if (!XF86VidModeQueryVersion(W_Display, &major, &minor)) {
3679     fprintf(stderr, "video_mode_initialise: XFree86-VidMode X extension absent\n");
3680     return 0;
3681   }
3682 
3683   static int done = 0;
3684   if (done) return 1;
3685   done++;
3686 
3687   int line;
3688   XF86VidModeModeLine current;
3689 
3690   /* obtain the current mode line and list of known mode lines */
3691   XF86VidModeGetModeLine(W_Display, W_Screen, &video_mode_dotclock, &current);
3692   XF86VidModeGetAllModeLines(W_Display, W_Screen,
3693                              &video_mode_list_size, &video_mode_list);
3694 
3695   /* find the current mode within the list of known mode lines */
3696   video_mode_current = NULL;
3697   for (line=0; line < video_mode_list_size; line++) {
3698     XF86VidModeModeInfo *mode = video_mode_list[line];
3699     if (mode->hdisplay == current.hdisplay &&
3700         mode->vdisplay == current.vdisplay &&
3701         mode->dotclock == video_mode_dotclock &&
3702         mode->htotal == current.htotal &&
3703         mode->vtotal == current.vtotal &&
3704         mode->flags == current.flags) {
3705       video_mode_original = video_mode_current = mode;
3706     }
3707   }
3708 
3709   /* do not change if the current mode was not found */
3710   if (video_mode_current == NULL) {
3711     fprintf(stderr, "video_mode_begin: this mode not found, "
3712             "cannot switch back, so not switching\n");
3713     return 0;
3714   }
3715 
3716   return 1;
3717 }
3718 
video_mode_on()3719 static void video_mode_on()
3720 {
3721   int line;
3722 
3723   /* if there is a mode line for 1024x768 then use it */
3724   for (line=0; line < video_mode_list_size; line++) {
3725     XF86VidModeModeInfo *mode = video_mode_list[line];
3726     if (mode->hdisplay == (small_screen ? 800 : 1024) &&
3727 	mode->vdisplay == (small_screen ? 600 : 768)) {
3728       XF86VidModeSwitchToMode(W_Display, W_Screen, mode);
3729       /*! @bug: if this is done on a non-local display, the X error
3730       XF86VidModeClientNotLocal occurs. */
3731       video_mode_current = mode;
3732       return;
3733     }
3734   }
3735 }
3736 
view_port_warp(W_Window window)3737 static void view_port_warp(W_Window window)
3738 {
3739   struct window *win = W_Void2Window(window);
3740 
3741   /* force the video view port to cover the window */
3742   int tx = 0, ty = 0;
3743   Window child;
3744   XTranslateCoordinates(W_Display, win->window, W_Root, 0, 0, &tx, &ty, &child);
3745   XF86VidModeSetViewPort(W_Display, W_Screen, tx, ty);
3746   XMapRaised(W_Display, win->window);
3747   XRaiseWindow(W_Display, win->window);
3748 }
3749 
3750 /* force the cursor to stay within the window */
pointer_grab_on(W_Window window)3751 static void pointer_grab_on(W_Window window)
3752 {
3753   struct window *win = W_Void2Window(window);
3754 
3755   XGrabPointer(W_Display, win->window, True, ButtonPressMask |
3756                  ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
3757                  PointerMotionMask | PointerMotionHintMask |
3758                  Button1MotionMask | Button2MotionMask |
3759                  Button3MotionMask | Button4MotionMask |
3760                  Button5MotionMask | ButtonMotionMask |
3761                  KeymapStateMask, GrabModeAsync, GrabModeAsync,
3762                  win->window, None, CurrentTime);
3763   XGrabKeyboard(W_Display, win->window, True, GrabModeAsync,
3764                 GrabModeAsync, CurrentTime);
3765   XFlush(W_Display);
3766 }
3767 
pointer_grab_off(W_Window window)3768 static void pointer_grab_off(W_Window window)
3769 {
3770   XUngrabPointer(W_Display, CurrentTime);
3771   XUngrabKeyboard(W_Display, CurrentTime);
3772 }
3773 
kde_fullscreen_on(W_Window window)3774 static void kde_fullscreen_on(W_Window window) {
3775   struct window *win = W_Void2Window(window);
3776   Atom WM_HINTS;
3777   WM_HINTS = XInternAtom(W_Display, "_NET_WM_STATE", True);
3778   if (WM_HINTS != None) {
3779     Atom p[1];
3780     p[0] = XInternAtom(W_Display, "_NET_WM_STATE_FULLSCREEN", True);
3781     XChangeProperty(W_Display, win->window, WM_HINTS, XA_ATOM, 32,
3782                     PropModeReplace, (unsigned char *)p, 1);
3783   }
3784 }
3785 
kde_fullscreen_off(W_Window window)3786 static void kde_fullscreen_off(W_Window window) {
3787   struct window *win = W_Void2Window(window);
3788   Atom WM_HINTS;
3789   WM_HINTS = XInternAtom(W_Display, "_NET_WM_STATE", True);
3790   if (WM_HINTS != None) {
3791     XDeleteProperty(W_Display, win->window, WM_HINTS);
3792   }
3793 }
3794 
3795 #endif /* FULLSCREEN */
3796 
W_FullScreenOn(W_Window window)3797 void W_FullScreenOn(W_Window window)
3798 {
3799   struct window *win = W_Void2Window(window);
3800 #ifdef FULLSCREEN
3801 #if DEBUG > 0
3802   fprintf(stderr, "W_FullScreenOn\n");
3803 #endif
3804   XResizeWindow(W_Display, win->window,
3805                 small_screen ? 800 : 1024,
3806                 small_screen ? 600 : 768);
3807   pointer_grab_on(window);
3808   video_mode_on();
3809   view_port_warp(window);
3810   kde_fullscreen_on(window);
3811 #endif
3812 }
3813 
W_FullScreenOff(W_Window window)3814 void W_FullScreenOff(W_Window window)
3815 {
3816 #ifdef FULLSCREEN
3817 #if DEBUG > 0
3818   fprintf(stderr, "W_FullScreenOff\n");
3819 #endif
3820   pointer_grab_off(window);
3821   kde_fullscreen_off(window);
3822   video_mode_off();
3823 #endif
3824 }
3825 
W_FullScreenInitialise()3826 void W_FullScreenInitialise() {
3827 #ifdef FULLSCREEN
3828 #if DEBUG > 0
3829   fprintf(stderr, "W_FullScreenInitialise\n");
3830 #endif
3831   full_screen_enabled = 0;
3832   full_screen_default = 0;
3833   if (booleanDefault("FullScreen", 0)) {
3834     full_screen_default++;
3835     if (video_mode_initialise())
3836       full_screen_enabled++;
3837   }
3838 #endif
3839 }
3840 
W_FullScreenToggle(W_Window window)3841 int W_FullScreenToggle(W_Window window) {
3842 #ifdef FULLSCREEN
3843 #if DEBUG > 0
3844   fprintf(stderr, "W_FullScreenToggle\n");
3845 #endif
3846   if (full_screen_enabled) {
3847     full_screen_enabled = 0;
3848     W_FullScreenOff(window);
3849   } else {
3850     if (!full_screen_default) {
3851       if (!video_mode_initialise()) {
3852         return FULLSCREEN_FAILED;
3853       }
3854     }
3855     full_screen_enabled++;
3856     W_FullScreenOn(window);
3857   }
3858   return FULLSCREEN_OK;
3859 #else
3860   return FULLSCREEN_NOT_COMPILED;
3861 #endif
3862 }
3863 
W_FullScreenBegin(W_Window window)3864 void W_FullScreenBegin(W_Window window) {
3865 #ifdef FULLSCREEN
3866 #if DEBUG > 0
3867   fprintf(stderr, "W_FullScreenBegin\n");
3868 #endif
3869   if (full_screen_enabled) {
3870     W_FullScreenOn(window);
3871   }
3872 #endif
3873 }
3874 
3875 /* regularly enforce */
W_FullScreen(W_Window window)3876 void W_FullScreen(W_Window window) {
3877 #ifdef FULLSCREEN
3878   if (full_screen_enabled) {
3879     view_port_warp(window);
3880     pointer_grab_on(window);
3881   }
3882 #endif
3883 }
3884