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