1 /*
2  * XPilot NG, a multiplayer space war game.
3  *
4  * Copyright (C) 1991-2001 by
5  *
6  *      Bj�rn Stabell        <bjoern@xpilot.org>
7  *      Ken Ronny Schouten   <ken@xpilot.org>
8  *      Bert Gijsbers        <bert@xpilot.org>
9  *      Dick Balaska         <dick@xpilot.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25 
26 #include "xpclient_x11.h"
27 #include "icon.h"
28 
29 /*
30  * Item structures.
31  *
32  * If you add an item here then please make sure you also add
33  * the item in the proper place in ../replay/xp-replay.c.
34  */
35 #include "items/itemRocketPack.xbm"
36 #include "items/itemCloakingDevice.xbm"
37 #include "items/itemEnergyPack.xbm"
38 #include "items/itemWideangleShot.xbm"
39 #include "items/itemRearShot.xbm"
40 #include "items/itemMinePack.xbm"
41 #include "items/itemSensorPack.xbm"
42 #include "items/itemTank.xbm"
43 #include "items/itemEcm.xbm"
44 #include "items/itemArmor.xbm"
45 #include "items/itemAfterburner.xbm"
46 #include "items/itemTransporter.xbm"
47 #include "items/itemDeflector.xbm"
48 #include "items/itemHyperJump.xbm"
49 #include "items/itemPhasingDevice.xbm"
50 #include "items/itemMirror.xbm"
51 #include "items/itemLaser.xbm"
52 #include "items/itemEmergencyThrust.xbm"
53 #include "items/itemTractorBeam.xbm"
54 #include "items/itemAutopilot.xbm"
55 #include "items/itemEmergencyShield.xbm"
56 
57 
58 /* How far away objects should be placed from each other etc... */
59 #define BORDER			10
60 #define BTN_BORDER		4
61 
62 /* Information window dimensions */
63 #define ABOUT_WINDOW_WIDTH	600
64 #define ABOUT_WINDOW_HEIGHT	700
65 
66 /*
67  * Globals.
68  */
69 int			ButtonHeight;
70 Atom			ProtocolAtom, KillAtom;
71 bool			quitting = false;
72 unsigned		top_width, top_height;
73 unsigned		players_width, players_height;
74 bool			radar_score_mapped;
75 Cursor			pointerControlCursor;
76 bool			ignoreWindowManager;
77 
78 XFontStruct* gameFont;		/* The fonts used in the game */
79 XFontStruct* messageFont;
80 XFontStruct* scoreListFont;
81 XFontStruct* buttonFont;
82 XFontStruct* textFont;
83 XFontStruct* talkFont;
84 XFontStruct* motdFont;
85 
86 /*static char myName[] = "xpilot";*/
87 static char myClass[] = "XPilot";
88 
89 /*
90  * NB!  Is dependent on the order of the items in item.h!
91  */
92 static struct {
93     unsigned char*	data;
94     const char*		keysText;
95 } itemBitmapData[NUM_ITEMS] = {
96     {
97 	itemEnergyPack_bits,
98 	"Extra energy/fuel"
99     },
100     {
101 	itemWideangleShot_bits,
102 	"Extra front cannons"
103     },
104     {
105 	itemRearShot_bits,
106 	"Extra rear cannon"
107     },
108     {
109 	itemAfterburner_bits,
110 	"Afterburner; makes your engines more powerful"
111     },
112     {
113 	itemCloakingDevice_bits,
114 	"Cloaking device; "
115 	"makes you almost invisible, both on radar and on screen"
116     },
117     {
118 	itemSensorPack_bits,
119 	"Sensor; "
120 	"enables you to see cloaked opponents more easily"
121     },
122     {
123 	itemTransporter_bits,
124 	"Transporter; enables you to steal equipment from "
125 	"other players"
126     },
127     {
128 	itemTank_bits,
129 	"Tank; "
130 	"makes refueling quicker, increases maximum fuel "
131 	"capacity and can be jettisoned to confuse enemies"
132     },
133     {
134 	itemMinePack_bits,
135 	"Mine; "
136 	"can be dropped as a bomb or as a stationary mine"
137     },
138     {
139 	itemRocketPack_bits,
140 	"Rocket; can be utilized as smart missile, "
141 	"heatseeking missile, nuclear missile or just a "
142 	"plain unguided missile (torpedo)"
143     },
144     {
145 	itemEcm_bits,
146 	"ECM (Electronic Counter Measures); "
147 	"can be used to disturb electronic equipment, for instance "
148 	"can it be used to confuse smart missiles and reprogram "
149 	"robots to seek certain players"
150     },
151     {
152 	itemLaser_bits,
153 	"Laser; "
154 	"limited range laser beam, costs a lot of fuel, "
155 	"having more laser items increases the range of the laser, "
156 	"they can be irrepairably damaged by ECMs"
157     },
158     {
159 	itemEmergencyThrust_bits,
160 	"Emergency Thrust; "
161 	"gives emergency thrust capabilities for a limited period"
162     },
163     {   itemTractorBeam_bits,
164 	"Tractor Beam; "
165 	"gives mutual attractive force to currently locked on ship, "
166 	"this means the heavier your ship, the less likely you will move "
167 	"when being tractored or using a tractor"
168     },
169     {
170 	itemAutopilot_bits,
171 	"Autopilot; "
172 	"when on, the ship will turn and thrust against the "
173 	"direction of travel"
174     },
175     {
176 	itemEmergencyShield_bits,
177 	"EmergencyShield; "
178 	"gives emergency shield capabilities for a limited period"
179     },
180     {
181 	itemDeflector_bits,
182 	"Deflector; "
183 	"pushes hostile objects away from your ship"
184     },
185     {
186 	itemHyperJump_bits,
187 	"Hyperjump; "
188 	"enables you to teleport to a random map location"
189     },
190     {
191 	itemPhasingDevice_bits,
192 	"Phasing Device; "
193 	"lets you fly through anything for a limited period"
194     },
195     {
196 	itemMirror_bits,
197 	"Mirror; "
198 	"reflects laser beams"
199     },
200     {
201 	itemArmor_bits,
202 	"Armor; "
203 	"absorbs shots in the absence of shields"
204     },
205 };
206 
207 Pixmap	itemBitmaps[NUM_ITEMS];		/* Bitmaps for the items */
208 
209 char dashes[NUM_DASHES];
210 char cdashes[NUM_CDASHES];
211 
212 static int Quit_callback(int, void *, const char **);
213 static int Config_callback(int, void *, const char **);
214 static int Colors_callback(int, void *, const char **);
215 static int Score_callback(int, void *, const char **);
216 static int Player_callback(int, void *, const char **);
217 
218 int button_form;
219 static int menu_button;
220 
Item_get_text(int i)221 const char *Item_get_text(int i)
222 {
223     return itemBitmapData[i].keysText;
224 }
225 
226 /*
227  * Set specified font for that GC.
228  * Return font that is used for this GC, even if setting a new
229  * font failed (return default font in that case).
230  */
Set_font(Display * display,GC gc,const char * fontName,const char * resName)231 static XFontStruct* Set_font(Display* display, GC gc,
232 			     const char* fontName,
233 			     const char *resName)
234 {
235     XFontStruct*	font;
236 
237     if ((font = XLoadQueryFont(display, fontName)) == NULL) {
238 	error("Couldn't find font '%s' for %s, using default font",
239 	      fontName, resName);
240 	font = XQueryFont(display, XGContextFromGC(gc));
241     } else
242 	XSetFont(display, gc, font->fid);
243 
244     return font;
245 }
246 
247 /*
248  * Initialize miscellaneous window hints and properties.
249  */
250 extern char		**Argv;
251 extern int		Argc;
252 
Init_disp_prop(Display * d,Window win,unsigned w,unsigned h,int x,int y,int flags)253 static void Init_disp_prop(Display *d, Window win,
254 			   unsigned w, unsigned h, int x, int y,
255 			   int flags)
256 {
257     XClassHint		xclh;
258     XWMHints		xwmh;
259     XSizeHints		xsh;
260 
261     xwmh.flags	   = InputHint|StateHint|IconPixmapHint;
262     xwmh.input	   = True;
263     xwmh.initial_state = NormalState;
264     xwmh.icon_pixmap   = XCreateBitmapFromData(d, win,
265 					       (char *)icon_bits,
266 					       icon_width, icon_height);
267 
268     xsh.flags = (flags|PMinSize|PMaxSize|PBaseSize|PResizeInc);
269     xsh.width = w;
270     xsh.base_width =
271     xsh.min_width = MIN_TOP_WIDTH;
272     xsh.max_width = MAX_TOP_WIDTH;
273     xsh.width_inc = 1;
274     xsh.height = h;
275     xsh.base_height =
276     xsh.min_height = MIN_TOP_HEIGHT;
277     xsh.max_height = MAX_TOP_HEIGHT;
278     xsh.height_inc = 1;
279     xsh.x = x;
280     xsh.y = y;
281 
282     xclh.res_name = NULL;	/* NULL: Automatically uses Argv[0], */
283     xclh.res_class = myClass; /* stripped of directory prefixes. */
284 
285     /*
286      * Set the above properties.
287      */
288     XSetWMProperties(d, win, NULL, NULL, Argv, Argc,
289 		     &xsh, &xwmh, &xclh);
290 
291     /*
292      * Now initialize icon and window title name.
293      */
294     XStoreName(d, win, TITLE);
295     XSetIconName(d, win, TITLE);
296 
297     if (d != dpy)
298 	return;
299 
300     /*
301      * Specify IO error handler and the WM_DELETE_WINDOW atom in
302      * an attempt to catch 'nasty' quits.
303      */
304     ProtocolAtom = XInternAtom(d, "WM_PROTOCOLS", False);
305     KillAtom = XInternAtom(d, "WM_DELETE_WINDOW", False);
306     XSetWMProtocols(d, win, &KillAtom, 1);
307     XSetIOErrorHandler(FatalError);
308 }
309 
310 
311 /*
312  * The following function initializes a toplevel window.
313  * It returns 0 if the initialization was successful,
314  * or -1 if it couldn't initialize the double buffering routine.
315  */
Init_top(void)316 int Init_top(void)
317 {
318     int					top_x, top_y;
319     int					i;
320     int					x, y;
321     unsigned				w, h;
322     unsigned long			values;
323     int					top_flags;
324     XGCValues				xgc;
325     XSetWindowAttributes		sattr;
326     unsigned long			mask;
327 
328     if (topWindow)
329 	fatal("Init_top called twice");
330 
331     if (Colors_init() == -1)
332 	return -1;
333 
334     radarDrawRectanglePtr = XFillRectangle;
335 
336     /*
337      * Get toplevel geometry.
338      */
339     top_flags = 0;
340     if (geometry != NULL && geometry[0] != '\0')
341 	mask = XParseGeometry(geometry, &x, &y, &w, &h);
342     else
343 	mask = 0;
344 
345     if ((mask & WidthValue) != 0) {
346 	top_width = w;
347 	top_flags |= USSize;
348     } else {
349 	top_width = DEF_TOP_WIDTH;
350 	top_flags |= PSize;
351     }
352     LIMIT(top_width, MIN_TOP_WIDTH, MAX_TOP_WIDTH);
353     if ((mask & HeightValue) != 0) {
354 	top_height = h;
355 	top_flags |= USSize;
356     } else {
357 	top_height = DEF_TOP_HEIGHT;
358 	top_flags |= PSize;
359     }
360     LIMIT(top_height, MIN_TOP_HEIGHT, MAX_TOP_HEIGHT);
361     if ((mask & XValue) != 0) {
362 	if ((mask & XNegative) != 0)
363 	    top_x = DisplayWidth(dpy, DefaultScreen(dpy)) - top_width + x;
364 	else
365 	    top_x = x;
366 	top_flags |= USPosition;
367     } else {
368 	top_x = (DisplayWidth(dpy, DefaultScreen(dpy)) - top_width) /2;
369 	top_flags |= PPosition;
370     }
371     if ((mask & YValue) != 0) {
372 	if ((mask & YNegative) != 0)
373 	    top_y = DisplayHeight(dpy, DefaultScreen(dpy)) - top_height + y;
374 	else
375 	    top_y = y;
376 	top_flags |= USPosition;
377     } else {
378 	top_y = (DisplayHeight(dpy, DefaultScreen(dpy)) - top_height) /2;
379 	top_flags |= PPosition;
380     }
381     if (geometry != NULL) {
382 	free(geometry);
383 	geometry = NULL;
384     }
385 
386     /*
387      * Create toplevel window (we need this first so that we can create GCs)
388      */
389     mask = 0;
390     /*old debug: sattr.background_pixel = colors[WHITE].pixel;*/
391     sattr.background_pixel = colors[BLACK].pixel;
392     mask |= CWBackPixel;
393     sattr.border_pixel = colors[WHITE].pixel;
394     mask |= CWBorderPixel;
395     if (colormap != 0) {
396 	sattr.colormap = colormap;
397 	mask |= CWColormap;
398     }
399     if (ignoreWindowManager) {
400 	sattr.override_redirect = True;
401 	mask |= CWOverrideRedirect;
402     }
403     topWindow = XCreateWindow(dpy,
404 			      DefaultRootWindow(dpy),
405 			      top_x, top_y,
406 			      top_width, top_height,
407 			      0, (int)dispDepth,
408 			      InputOutput, visual,
409 			      mask, &sattr);
410     XSelectInput(dpy, topWindow,
411 		 KeyPressMask | KeyReleaseMask
412 		 | FocusChangeMask | StructureNotifyMask);
413     Init_disp_prop(dpy, topWindow, top_width, top_height,
414 		   top_x, top_y, top_flags);
415     if (kdpy) {
416 	int scr = DefaultScreen(kdpy);
417 	keyboardWindow = XCreateSimpleWindow(kdpy,
418 					     DefaultRootWindow(kdpy),
419 					     top_x, top_y,
420 					     top_width, top_height,
421 					     0, 0, BlackPixel(dpy, scr));
422 	XSelectInput(kdpy, keyboardWindow,
423 		     KeyPressMask | KeyReleaseMask | FocusChangeMask);
424 	Init_disp_prop(kdpy, keyboardWindow, top_width, top_height,
425 		       top_x, top_y, top_flags);
426     }
427 
428     /*
429      * Create item bitmaps
430      */
431     for (i = 0; i < NUM_ITEMS; i++)
432 	itemBitmaps[i]
433 	    = XCreateBitmapFromData(dpy, topWindow,
434 				    (char *)itemBitmapData[i].data,
435 				    ITEM_SIZE, ITEM_SIZE);
436 
437     /*
438      * Creates and initializes the graphic contexts.
439      */
440     xgc.line_width = 0;
441     xgc.line_style = LineSolid;
442     xgc.cap_style = CapButt;
443     xgc.join_style = JoinMiter;		/* I think this is fastest, is it? */
444     xgc.graphics_exposures = False;
445     values
446 	= GCLineWidth|GCLineStyle|GCCapStyle|GCJoinStyle|GCGraphicsExposures;
447 
448     messageGC	= XCreateGC(dpy, topWindow, values, &xgc);
449     radarGC	= XCreateGC(dpy, topWindow, values, &xgc);
450     buttonGC	= XCreateGC(dpy, topWindow, values, &xgc);
451     scoreListGC	= XCreateGC(dpy, topWindow, values, &xgc);
452     textGC	= XCreateGC(dpy, topWindow, values, &xgc);
453     talkGC	= XCreateGC(dpy, topWindow, values, &xgc);
454     motdGC	= XCreateGC(dpy, topWindow, values, &xgc);
455     gameGC	= XCreateGC(dpy, topWindow, values, &xgc);
456     XSetBackground(dpy, gameGC, colors[BLACK].pixel);
457 
458     /*
459      * Set fonts
460      */
461     gameFont
462 	= Set_font(dpy, gameGC, gameFontName, "gameFont");
463     messageFont
464 	= Set_font(dpy, messageGC, messageFontName, "messageFont");
465     scoreListFont
466 	= Set_font(dpy, scoreListGC, scoreListFontName, "scoreListFont");
467     buttonFont
468 	= Set_font(dpy, buttonGC, buttonFontName, "buttonFont");
469     textFont
470 	= Set_font(dpy, textGC, textFontName, "textFont");
471     talkFont
472 	= Set_font(dpy, talkGC, talkFontName, "talkFont");
473     motdFont
474 	= Set_font(dpy, motdGC, motdFontName, "motdFont");
475 
476     XSetState(dpy, gameGC,
477 	      WhitePixel(dpy, DefaultScreen(dpy)),
478 	      BlackPixel(dpy, DefaultScreen(dpy)),
479 	      GXcopy, AllPlanes);
480     XSetState(dpy, radarGC,
481 	      WhitePixel(dpy, DefaultScreen(dpy)),
482 	      BlackPixel(dpy, DefaultScreen(dpy)),
483 	      GXcopy, AllPlanes);
484     XSetState(dpy, messageGC,
485 	      WhitePixel(dpy, DefaultScreen(dpy)),
486 	      BlackPixel(dpy, DefaultScreen(dpy)),
487 	      GXcopy, AllPlanes);
488     XSetState(dpy, buttonGC,
489 	      WhitePixel(dpy, DefaultScreen(dpy)),
490 	      BlackPixel(dpy, DefaultScreen(dpy)),
491 	      GXcopy, AllPlanes);
492     XSetState(dpy, scoreListGC,
493 	      WhitePixel(dpy, DefaultScreen(dpy)),
494 	      BlackPixel(dpy, DefaultScreen(dpy)),
495 	      GXcopy, AllPlanes);
496 
497     if (dbuf_state->type == COLOR_SWITCH)
498 	XSetPlaneMask(dpy, gameGC, dbuf_state->drawing_planes);
499 
500     return 0;
501 }
502 
503 
504 /*
505  * Creates the playing windows.
506  * Returns 0 on success, -1 on error.
507  */
Init_playing_windows(void)508 int Init_playing_windows(void)
509 {
510     unsigned			w, h;
511     Pixmap			pix;
512     GC				cursorGC;
513 
514     if (!topWindow) {
515 	if (Init_top())
516 	    return -1;
517     }
518 
519     Scale_dashes();
520 
521     draw_width = top_width - (256 + 2);
522     draw_height = top_height;
523     drawWindow = XCreateSimpleWindow(dpy, topWindow, 258, 0,
524 				     draw_width, draw_height,
525 				     0, 0, colors[BLACK].pixel);
526     radarWindow = XCreateSimpleWindow(dpy, topWindow, 0, 0,
527 				      256, RadarHeight, 0, 0,
528 				      colors[BLACK].pixel);
529     radar_score_mapped = true;
530 
531     /* Create buttons */
532 #define BUTTON_WIDTH	84
533     ButtonHeight = buttonFont->ascent + buttonFont->descent + 2*BTN_BORDER;
534 
535     button_form
536 	= Widget_create_form(0, topWindow,
537 			     0, (int)RadarHeight,
538 			     256, ButtonHeight + 2,
539 			     0);
540     Widget_create_activate(button_form,
541 			   0 + 0*BUTTON_WIDTH, 0,
542 			   BUTTON_WIDTH, ButtonHeight,
543 			   1, "QUIT",
544 			   Quit_callback, NULL);
545     Widget_create_activate(button_form,
546 			   1 + 1*BUTTON_WIDTH, 0,
547 			   BUTTON_WIDTH, ButtonHeight,
548 			   1, "ABOUT",
549 			   About_callback, NULL);
550     menu_button
551 	= Widget_create_menu(button_form,
552 			     2 + 2*BUTTON_WIDTH, 0,
553 			     BUTTON_WIDTH, ButtonHeight,
554 			     1, "MENU");
555     Widget_add_pulldown_entry(menu_button,
556 			      "KEYS", Keys_callback, NULL);
557     Widget_add_pulldown_entry(menu_button,
558 			      "CONFIG", Config_callback, NULL);
559     Widget_add_pulldown_entry(menu_button,
560 			      "COLORS", Colors_callback, NULL);
561     Widget_add_pulldown_entry(menu_button,
562 			      "SCORE", Score_callback, NULL);
563     Widget_add_pulldown_entry(menu_button,
564 			      "PLAYER", Player_callback, NULL);
565     Widget_add_pulldown_entry(menu_button,
566 			      "MOTD", Motd_callback, NULL);
567     Widget_map_sub(button_form);
568 
569     /* Create score list window */
570     players_width = RadarWidth;
571     players_height = top_height - (RadarHeight + ButtonHeight + 2);
572     playersWindow
573 	= XCreateSimpleWindow(dpy, topWindow,
574 			      0, (int)RadarHeight + ButtonHeight + 2,
575 			      players_width, players_height,
576 			      0, 0,
577 			      colors[windowColor].pixel);
578 
579     /*
580      * Selecting the events we can handle.
581      */
582     XSelectInput(dpy, radarWindow, ExposureMask);
583     XSelectInput(dpy, playersWindow, ExposureMask);
584     XSelectInput(dpy, drawWindow, ButtonPressMask | ButtonReleaseMask);
585 
586     /*
587      * Initialize misc. pixmaps if we're not color switching.
588      * (This could be in dbuff_init_buffer completely IMHO, -- Metalite)
589      */
590     switch (dbuf_state->type) {
591 
592     case PIXMAP_COPY:
593 	radarPixmap
594 	    = XCreatePixmap(dpy, radarWindow, 256, RadarHeight, dispDepth);
595 	radarPixmap2
596 	    = XCreatePixmap(dpy, radarWindow, 256, RadarHeight, dispDepth);
597 	drawPixmap
598 	    = XCreatePixmap(dpy, drawWindow, draw_width, draw_height,
599 			    dispDepth);
600 	break;
601 
602     case MULTIBUFFER:
603 	radarPixmap
604 	    = XCreatePixmap(dpy, radarWindow, 256, RadarHeight, dispDepth);
605 	radarPixmap2
606 	    = XCreatePixmap(dpy, radarWindow, 256, RadarHeight, dispDepth);
607 	dbuff_init_buffer(dbuf_state);
608 	break;
609 
610     case COLOR_SWITCH:
611 	radarPixmap2 = radarWindow;
612 	radarPixmap = radarWindow;
613 	drawPixmap = drawWindow;
614 	Paint_sliding_radar();
615 	break;
616 
617     default:
618 	assert(0 && "Init_playing_windows: unknown dbuf state type.");
619 	break;
620     }
621 
622     XAutoRepeatOff(dpy);	/* We don't want any autofire, yet! */
623     if (kdpy)
624 	XAutoRepeatOff(kdpy);
625 
626     /*
627      * Define a blank cursor for use with pointer control
628      */
629     XQueryBestCursor(dpy, drawWindow, 1, 1, &w, &h);
630     pix = XCreatePixmap(dpy, drawWindow, w, h, 1);
631     cursorGC = XCreateGC(dpy, pix, 0, NULL);
632     XSetForeground(dpy, cursorGC, 0);
633     XFillRectangle(dpy, pix, cursorGC, 0, 0, w, h);
634     XFreeGC(dpy, cursorGC);
635     pointerControlCursor = XCreatePixmapCursor(dpy, pix, pix, &colors[BLACK],
636 					       &colors[BLACK], 0, 0);
637     XFreePixmap(dpy, pix);
638 
639     /*
640      * Maps the windows, makes the visible. Voila!
641      */
642     XMapSubwindows(dpy, topWindow);
643     XMapWindow(dpy, topWindow);
644     XSync(dpy, False);
645 
646     if (kdpy) {
647 	XMapWindow(kdpy, keyboardWindow);
648 	XSync(kdpy, False);
649     }
650 
651     Init_spark_colors();
652 
653     return 0;
654 }
655 
Config_callback(int widget_desc,void * data,const char ** str)656 static int Config_callback(int widget_desc, void *data, const char **str)
657 {
658     UNUSED_PARAM(widget_desc); UNUSED_PARAM(data); UNUSED_PARAM(str);
659     Config(true, CONFIG_DEFAULT);
660     return 0;
661 }
662 
Colors_callback(int widget_desc,void * data,const char ** str)663 static int Colors_callback(int widget_desc, void *data, const char **str)
664 {
665     UNUSED_PARAM(widget_desc); UNUSED_PARAM(data); UNUSED_PARAM(str);
666     Config(true, CONFIG_COLORS);
667     return 0;
668 }
669 
Score_callback(int widget_desc,void * data,const char ** str)670 static int Score_callback(int widget_desc, void *data, const char **str)
671 {
672     UNUSED_PARAM(widget_desc); UNUSED_PARAM(data); UNUSED_PARAM(str);
673     Config(false, CONFIG_NONE);
674     if (showUserName) {
675 	showUserName = false;
676 	scoresChanged = true;
677     }
678     return 0;
679 }
680 
Player_callback(int widget_desc,void * data,const char ** str)681 static int Player_callback(int widget_desc, void *data, const char **str)
682 {
683     UNUSED_PARAM(widget_desc); UNUSED_PARAM(data); UNUSED_PARAM(str);
684     Config(false, CONFIG_NONE);
685     if (!showUserName) {
686 	showUserName = true;
687 	scoresChanged = true;
688     }
689     return 0;
690 }
691 
Quit_callback(int widget_desc,void * data,const char ** str)692 static int Quit_callback(int widget_desc, void *data, const char **str)
693 {
694     UNUSED_PARAM(widget_desc); UNUSED_PARAM(data); UNUSED_PARAM(str);
695     quitting = true;
696     return 0;
697 }
698 
Raise_window(void)699 void Raise_window(void)
700 {
701     XMapRaised(dpy, topWindow);
702 }
703 
Resize(Window w,unsigned width,unsigned height)704 void Resize(Window w, unsigned width, unsigned height)
705 {
706     if (w != topWindow)
707 	return;
708 
709     /* ignore illegal resizes */
710     LIMIT(width, MIN_TOP_WIDTH, MAX_TOP_WIDTH);
711     LIMIT(height, MIN_TOP_HEIGHT, MAX_TOP_HEIGHT);
712     top_width = width;
713     top_height = height;
714     if (!drawWindow)
715 	return;
716 
717     if (radar_score_mapped)
718 	draw_width = top_width - 258;
719     else
720 	draw_width = top_width;
721     draw_height = top_height;
722 
723     Check_view_dimensions();
724     Net_flush();
725     XResizeWindow(dpy, drawWindow, draw_width, draw_height);
726     if (dbuf_state->type == PIXMAP_COPY) {
727 	XFreePixmap(dpy, drawPixmap);
728 	drawPixmap = XCreatePixmap(dpy, drawWindow, draw_width, draw_height,
729 				   dispDepth);
730     }
731     players_height = top_height - (RadarHeight + ButtonHeight + 2);
732     XResizeWindow(dpy, playersWindow,
733 		  players_width, players_height);
734     Talk_resize();
735     Config_resize();
736 }
737 
738 
739 /*
740  * Close the display etc.
741  */
Platform_specific_cleanup(void)742 void Platform_specific_cleanup(void)
743 {
744     /* Here we restore the mouse to its former self */
745     /* the option may have been toggled in game to  */
746     /* off so we cant trust that                    */
747 
748     if (dpy != NULL) {
749 	if (pre_exists)
750 	    XChangePointerControl(dpy, True, True, pre_acc_num,
751 				  pre_acc_denom, pre_threshold);
752 	XAutoRepeatOn(dpy);
753 	Colors_cleanup();
754 	XCloseDisplay(dpy);
755 	dpy = NULL;
756 	if (kdpy) {
757 	    XAutoRepeatOn(kdpy);
758 	    XCloseDisplay(kdpy);
759 	    kdpy = NULL;
760 	}
761     }
762     Widget_cleanup();
763 }
764 
765 
FatalError(Display * display)766 int FatalError(Display *display)
767 {
768     UNUSED_PARAM(display);
769     Client_exit(0);
770     /* make complier not warn */
771     return 0;
772 }
773 
Scale_dashes(void)774 void Scale_dashes(void)
775 {
776     if (dpy == NULL)
777 	return;
778 
779     dashes[0] = WINSCALE(8);
780     if (dashes[0] < 1)
781 	dashes[0] = 1;
782     dashes[1] = WINSCALE(4);
783     if (dashes[1] < 1)
784 	dashes[1] = 1;
785 
786     cdashes[0] = WINSCALE(3);
787     if (cdashes[0] < 1)
788 	cdashes[0] = 1;
789     cdashes[1] = WINSCALE(9);
790     if (cdashes[1] < 1)
791 	cdashes[1] = 1;
792 
793     XSetDashes(dpy, gameGC, 0, dashes, NUM_DASHES);
794 }
795