1 /*
2 ** X11 routines for XOIDS
3 **
4 ** by Tim Ebling
5 ** tebling@oce.orst.edu
6 **
7 ** This is actually a hacked version of the X11 device driver
8 ** from the VOGLE graphics library.  Not much is left of the
9 ** original though :)
10 **
11 */
12 #include <stdio.h>
13 #include <math.h>
14 #include <string.h>
15 #include <X11/Xlib.h>
16 #include <X11/Xutil.h>
17 #include <X11/keysym.h>
18 #include <X11/keysymdef.h>
19 #include <xpm.h>
20 
21 #include "oids.h"
22 
23 #define LARGEX11R2	"courier12f.snf"
24 #define SMALLX11R2	"courier10f.snf"
25 
26 #define LARGEX11R3	"-adobe-courier-medium-r-normal--24-240-75-75-m-150-iso8859-1"
27 #define SMALLX11R3	"-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1"
28 
29 #define MIN(x,y)	((x) < (y) ? (x) : (y))
30 #define	CMAPSIZE	256
31 #define	EV_MASK		KeyReleaseMask|KeyPressMask|ExposureMask|VisibilityChangeMask|StructureNotifyMask
32 
33 static	Window		winder;
34 static	Display		*display;
35 static	int		screen;
36 static	unsigned long	carray[CMAPSIZE];
37 static	Colormap	colormap;
38 
39 static	Drawable	theDrawable;
40 static	GC		theGC;
41 static  GC		unclippedGC;
42 static  XGCValues	theGCvalues;
43 static	Pixmap		bbuf;		/* Back buffer pixmap */
44 static	int		back_used;	/* Have we backbuffered ? */
45 
46 static	XFontStruct	*font_id;
47 static	XFontStruct	*font_info;
48 
49 static	unsigned long	colour;
50 static	unsigned int	h, w;
51 
52 static  XRectangle	eng_outlinel,
53 			eng_outliner;
54 
55 static unsigned int	wo7, wo40;
56 
57 
58 
59 /*
60  * X_init
61  *
62  *	initialises X11 display.
63  */
X_init()64 void X_init()
65 {
66 	int		i;
67 	int		x, y, prefx, prefy, prefxs, prefys;
68 	unsigned int	bw, depth, mask;
69 	Window		rootw, childw;
70 	char		*av[2], name[50];
71 	XEvent		event;
72 
73 	XSetWindowAttributes    theWindowAttributes;
74         XSizeHints              theSizeHints;
75         unsigned long           theWindowMask;
76 	XWMHints                theWMHints;
77 
78 
79 	av[0] = "X11";
80 	av[1] = (char *)NULL;
81 
82 	if ((display = XOpenDisplay((char *)NULL)) == (Display *)NULL) {
83 		fprintf(stderr,"X_init: can't connect to X server\n");
84 		exit(1);
85 	}
86 
87 	winder = DefaultRootWindow(display);
88 	screen = DefaultScreen(display);
89 	vdevice.depth = DefaultDepth(display, screen);
90 	colormap = DefaultColormap(display, screen);
91 
92 	/*
93 	 * Set our standard colors...
94 	 */
95 	if (vdevice.depth == 1) {
96 		/*
97 		 * Black and white - anything that's not black is white.
98 		 */
99 		carray[0] = BlackPixel(display, screen);
100 		for (i = 1; i < CMAPSIZE; i++)
101 			carray[i] = WhitePixel(display, screen);
102 	} else {
103 		/*
104 		 * Color, try to get our colors close to what's in the
105 		 * default colormap.
106 		 */
107 		X_mapcolor(0, 0, 0, 0);
108 		X_mapcolor(1, 255, 0, 0);
109 		X_mapcolor(2, 0, 255, 0);
110 		X_mapcolor(3, 255, 255, 0);
111 		X_mapcolor(4, 0, 0, 255);
112 		X_mapcolor(5, 255, 0, 255);
113 		X_mapcolor(6, 0, 255, 255);
114 		X_mapcolor(7, 255, 255, 255);
115 	}
116 
117 
118 	/*
119 	 * NEED TO USE XGRABPOINTER here???
120 	 */
121 	XQueryPointer(display, winder, &rootw, &childw, &x, &y, &x, &y, &mask);
122 
123 	if (childw == None)
124 		childw = rootw;
125 
126 	XGetGeometry(display, childw, &rootw, &x, &y, &w, &h, &bw, &depth);
127 
128 	/*
129 	 * Tell the window manager not to mess with this window...
130 	 * (and hope the bastard of a thing listens)
131 	 * Unless it's using prefsize of prefposition of course.
132 	 */
133         theWindowAttributes.override_redirect = True;
134 
135 	prefx = 0;
136 	prefy = 0;
137 	prefxs = WINDOW_WIDTH;
138 	prefys = WINDOW_HEIGHT;
139 
140 	if (prefx > -1) {
141 		theWindowAttributes.override_redirect = False;
142 	        x = prefx;
143 	        y = prefy;
144 	}
145 
146 	if (prefxs > -1) {
147 		theWindowAttributes.override_redirect = False;
148 	        w = prefxs;
149 	        h = prefys;
150 	}
151 
152 	x += bw;
153 	y += bw;
154 
155 	w -= 2 * bw;
156 	h -= 2 * bw;
157 
158         /*theWindowMask = CWBackPixel|CWBorderPixel|CWOverrideRedirect;*/
159         theWindowMask = CWOverrideRedirect;
160 
161         winder = XCreateWindow(display,
162                                 winder,
163                                 x, y,
164                                 w, h,
165                                 bw,
166                                 (int)vdevice.depth,
167                                 InputOutput,
168                                 CopyFromParent,
169                                 theWindowMask,
170                                 &theWindowAttributes
171                         );
172 
173         theWMHints.initial_state = NormalState;
174         theWMHints.input = True;
175         theWMHints.flags = StateHint | InputHint;
176         XSetWMHints(display, winder, &theWMHints);
177 
178         theSizeHints.flags = PPosition|PSize;
179         theSizeHints.x = x;
180         theSizeHints.y = y;
181         theSizeHints.width = w;
182         theSizeHints.height = h;
183 
184         XSetNormalHints(display, winder, &theSizeHints);
185 
186 	sprintf(name, "XOIDS!");
187 
188 	XSetStandardProperties(display,
189 		winder,
190 		name,
191 		name,
192 		None,
193 		av,
194 		1,
195 		&theSizeHints
196 	);
197 
198 	XSelectInput(display, winder, EV_MASK);
199 
200 	theDrawable = (Drawable)winder;
201 
202 	/* Colors */
203 
204 	theGCvalues.foreground = WhitePixel(display, screen);
205 	theGCvalues.background = BlackPixel(display, screen);
206 	theGCvalues.function = GXcopy;
207 
208 	/*
209 	 *  Let us know about the window size.
210 	 */
211 	vdevice.sizeX = vdevice.sizeY = MIN(h, w) - 1;
212 	vdevice.sizeSx = w;
213 	vdevice.sizeSy = h;
214 
215 	/*
216 	 * Create Graphics Context and Drawable
217 	 */
218 	theGC = XCreateGC(display, RootWindow(display, screen), (GCForeground | GCBackground | GCFunction), &theGCvalues);
219 
220 	unclippedGC = XCreateGC(display, RootWindow(display, screen), (GCForeground | GCBackground | GCFunction), &theGCvalues);
221 
222 	X_color(0);
223 	colour = BLACK;
224 
225 	XMapRaised(display, winder);
226 	XFlush(display);
227 
228 	/*
229 	 * Wait for Exposure event.
230 	 */
231 	do {
232 		XNextEvent(display, &event);
233 	} while (event.type != Expose);
234 
235 	/*
236 	 * Set the input Focus to us.
237 	 */
238 
239 	XSetInputFocus(display, winder, RevertToParent, CurrentTime);
240 
241 	/* Turn off graphics exposures - if left on, a HUGE number of */
242 	/* NoExpose events are generated, slowing things considerably */
243 
244 	XSetGraphicsExposures(display, theGC, False);
245 	XSetGraphicsExposures(display, unclippedGC, False);
246 
247 	/* Set keyboard auto-repeat to off */
248 
249 	XAutoRepeatOff(display);
250 
251 	/* Set the clipping region = the score box */
252 
253 	clip_rect.x = 0;
254 	clip_rect.y = P->height + 4;
255 	clip_rect.width = vdevice.sizeSx;
256 	clip_rect.height = vdevice.sizeSy - (int) (P->height + 4);
257 
258 	/* Set outlines for engine heat bars */
259 
260 	wo7 = (int) (vdevice.sizeSx / 7);
261 	wo40 = (int) (vdevice.sizeSx / 40);
262 
263 	eng_outlinel.x = P->width + 150;
264 	eng_outlinel.y = 7;
265 	eng_outlinel.height = (int) P->height - 11;
266 	eng_outlinel.width = wo7;
267 
268 	eng_outliner.x = 6 * wo7 - 5;
269 	eng_outliner.y = 7;
270 	eng_outliner.height = P->height - 11;
271 	eng_outliner.width = wo7;
272 
273 	back_used = 0;
274 
275 }
276 
277 
278 
279 /*
280 ** XPM_MAKE_PIXMAPS
281 **
282 */
Xpm_make_pixmaps(obj)283 void Xpm_make_pixmaps(obj)
284 Sprite *obj;
285 {
286 
287 	int i, status;
288 	Sprite *root_obj;
289 	XpmAttributes attributes;
290 
291 	attributes.valuemask = XpmCloseness|XpmReturnExtensions|XpmColormap;
292 	attributes.extensions = NULL;
293 	attributes.colormap = colormap;
294 	attributes.closeness = 40000;
295 
296 	root_obj = obj;
297 
298 	X_frontbuf();
299 
300 	X_color(BLACK);
301 
302 	for (i=0;i<obj->num_pixmaps;i++) {
303 
304 		status = XpmCreatePixmapFromData(display, DefaultRootWindow(display), obj->pixmap_data[i], &obj->pixmaps[i], &obj->clipmasks[i], &attributes);
305 
306 		if (i == 0) {
307 
308 			X_draw_one_object(obj, (int) ((vdevice.sizeSx - obj->width) / 2), (int) ((vdevice.sizeSy  / 2) + 50));
309 
310 		}
311 
312 		X_update(0);
313 
314 	}
315 
316 	switch (status) {
317 	case XpmColorError:
318 		printf("Could not parse or allocate requested color\n");
319 		break;
320 	case XpmNoMemory:
321 		printf("Not enough memory\n");
322 		break;
323 	case XpmColorFailed:
324 		printf("Failed to parse or alloc some color\n");
325 		break;
326 	}
327 
328 	XFillRectangle(display, winder, theGC, (int) (vdevice.sizeSx - obj->width) / 2, (int) (vdevice.sizeSy / 2) + 50, obj->width, obj->height);
329 
330 	XFlush(display);
331 
332 	obj->orig_pixmaps = obj->pixmaps;
333 	obj->orig_clipmasks = obj->clipmasks;
334 
335 	while (obj = obj->next) {
336 		for (i=0;i<obj->num_pixmaps;i++) {
337 			obj->pixmaps[i] = root_obj->pixmaps[i];
338 			obj->clipmasks[i] = root_obj->clipmasks[i];
339 		}
340 
341 		obj->orig_pixmaps = obj->pixmaps;
342 		obj->orig_clipmasks = obj->clipmasks;
343 	};
344 
345 
346 	X_backbuf();
347 
348 	X_color(BLACK);
349 
350 } /* end XPM_MAKE_PIXMAPS */
351 
352 
353 
354 
355 /*
356 ** X_ROTATE_PIXMAP_DATA
357 **
358 **	Rotates the given pixmap of height h and width w by angle alpha.
359 **	Alpha ranges from 0 (no rotation) to MAPS_PER_360 (360 degrees).
360 **
361 **	Output is not interpolated - "holes" may result.
362 */
X_rotate_pixmap_data(orig_pmap,h,w,alpha)363 char **X_rotate_pixmap_data(orig_pmap, h, w, alpha)
364 char **orig_pmap;
365 unsigned int h, w;
366 unsigned int alpha;
367 {
368 
369 	char **rot_pmap;
370 	unsigned int i, x, y;
371 	unsigned int w2, colors, h2, perchar;
372 	int m, n;
373 	char pix_val, blank_val;
374 	float wo2, ho2, x2, y2;
375 
376 	wo2 = w / 2;
377 	ho2 = h / 2;
378 
379 	sscanf(orig_pmap[0], "%d %d %d %d", &w2, &h2, &colors, &perchar);
380 
381 	/* Copy header */
382 
383 	rot_pmap = (char **) calloc(colors + h + 1, sizeof(char *));
384 
385 	for (i=0;i<colors+1;i++) rot_pmap[i] = orig_pmap[i];
386 
387 	blank_val = orig_pmap[1][0];
388 
389 	/* Allocate space for this pixmap data */
390 
391 	for (i=colors+1;i<colors+1+h;i++)
392 		rot_pmap[i] = (char *) calloc(w, sizeof(char));
393 
394 	for (y=colors+1;y<colors+1+h;y++) {
395 		for (x=0;x<w;x++) {
396 
397 			/* Identify source pixel */
398 
399 			pix_val = orig_pmap[y][x];
400 
401 			/* Calculate destination location */
402 
403 			x2 = x - wo2;
404 			y2 = y - (colors+1) - ho2;
405 
406 			m = floor(x2 * cos_table[alpha] + y2 * sin_table[alpha] + wo2);
407 			n = floor(-x2 * sin_table[alpha] + y2 * cos_table[alpha] + ho2);
408 
409 			if (m < w && n < h && n > 0) {
410 				rot_pmap[n+colors+1][m] = pix_val;
411 			}
412 		}
413 	}
414 
415 	for (m=colors+1;m<h+colors+1;m++) {
416 		for (n=0;n<w;n++) {
417 			if (rot_pmap[m][n] == '\0') rot_pmap[m][n] = blank_val;
418 		}
419 	}
420 
421 	return(rot_pmap);
422 
423 } /* end X_ROTATE_PIXMAP_DATA */
424 
425 
426 
427 
428 /*
429 ** X_SPIN_PIXMAP360
430 **
431 **	Spins a bitmap by 360 degrees, calculating n number of intermediate
432 **	bitmaps.
433 **
434 **	A better way to do this would be to rotate by 90 degrees, then flip
435 **	horizontally and vertically to obtain the remaining quadrants.
436 **
437 **	Inputs: Object with bitmap[0] filled
438 **
439 */
X_spin_pixmap360(obj)440 void X_spin_pixmap360(obj)
441 Sprite *obj;
442 {
443 
444 	unsigned int i, n;
445 
446 	n = obj->num_pixmaps;
447 
448 	for (i=1;i<n;i++) {
449 		obj->pixmap_data[i] = X_rotate_pixmap_data(obj->pixmap_data[0], obj->height, obj->width, i);
450 	}
451 
452 
453 } /* end X_SPIN_PIXMAP360 */
454 
455 
456 
457 
458 
459 /*
460 ** X_INIT_PIXMAPS
461 **
462 */
X_init_pixmaps()463 void X_init_pixmaps()
464 {
465 
466 	int i, j, k, len1, len2, wid1, wid2;
467 	char *str1 = "ROTATING PIXMAPS";
468 	char *str2 = "Be patient, or else you won't get to play";
469 
470 	font_info = XLoadQueryFont(display, "9x15");
471 
472 	len1 = strlen(str1);
473 	len2 = strlen(str2);
474 
475 	wid1 = XTextWidth(font_info, str1, len1);
476 	wid2 = XTextWidth(font_info, str2, len2);
477 
478 	X_color(YELLOW);
479 
480 	XDrawString(display, winder, theGC, (vdevice.sizeSx / 2) - wid1 / 3, vdevice.sizeSy / 2 - 50, str1, len1);
481 
482 	X_color(RED);
483 
484 	XDrawString(display, winder, theGC, (vdevice.sizeSx / 2) - wid2 / 3, vdevice.sizeSy / 2, str2, len2);
485 
486 	X_color(BLACK);
487 
488 	Xpm_make_pixmaps(P);
489 	Xpm_make_pixmaps(P->next);
490 	Xpm_make_pixmaps(Slrb);
491 	Xpm_make_pixmaps(Homer);
492 	Xpm_make_pixmaps(Resur);
493 	Xpm_make_pixmaps(Power_Up);
494 	Xpm_make_pixmaps(Meta);
495 	Xpm_make_pixmaps(Flame);
496 	Xpm_make_pixmaps(Big_O);
497 	for (i=0;i<4;i++) Xpm_make_pixmaps(Shrd[i]);
498 	for (i=0;i<MAX_BIG_OIDS;i++) {
499 		for (j=0;j<OID_DIVIDE;j++) {
500 			if (i==0 && j==0) {
501 				Xpm_make_pixmaps(Med_O[0]);
502 			} else {
503 				for (k=0;k<Med_O[0]->num_pixmaps;k++) {
504 					Med_O[i][j].pixmaps[k] = Med_O[0]->pixmaps[k];
505 					Med_O[i][j].clipmasks[k] = Med_O[0]->clipmasks[k];
506 				}
507 			}
508 		}
509 	}
510 
511 	for (i=0;i<MAX_BIG_OIDS * OID_DIVIDE;i++) {
512 		for (j=0;j<OID_DIVIDE;j++) {
513 			if (i==0 && j==0) {
514 				Xpm_make_pixmaps(Sml_O[0]);
515 			} else {
516 				for (k=0;k<Sml_O[0]->num_pixmaps;k++) {
517 					Sml_O[i][j].pixmaps[k] = Sml_O[0]->pixmaps[k];
518 					Sml_O[i][j].clipmasks[k] = Sml_O[0]->clipmasks[k];
519 				}
520 			}
521 		}
522 	}
523 
524 	X_frontbuf();
525 	X_clear();
526 	X_backbuf();
527 	X_clear();
528 	XSetClipRectangles(display, theGC, 0, 0, &clip_rect, 1, Unsorted);
529 
530 } /* end X_INIT_PIXMAPS */
531 
532 
533 /*
534  * X_exit
535  *
536  *	cleans up before returning the window to normal.
537  */
X_exit()538 void X_exit()
539 {
540 
541 	XAutoRepeatOn(display);
542 
543 	XFlush(display);
544 
545 	XFreeGC(display, theGC);
546 
547 	if (back_used)
548 		XFreePixmap(display, bbuf);
549 
550 	XUnmapWindow(display, winder);
551 
552 	XDestroyWindow(display, winder);
553 
554 }
555 
556 
557 /*
558 ** X_clear_key_buffer
559 **
560 */
X_clear_key_buffer()561 void X_clear_key_buffer()
562 {
563 
564 	XEvent *event;
565 
566 	event = (XEvent *) calloc(1, sizeof(XEvent));
567 
568 	while (XCheckWindowEvent(display, winder, (KeyPressMask | KeyReleaseMask), event));
569 
570 } /* end X_clear_key_buffer */
571 
572 
573 
574 /*
575 ** X_get_menu_keys
576 **
577 */
X_get_menu_keys()578 int X_get_menu_keys()
579 {
580 
581 	static int r, dl;
582 
583 	XEvent	*event;
584 	char cc[1];
585 	KeySym key;
586 
587 	event = (XEvent *) calloc(1, sizeof(XEvent));
588 
589 	if (dl) dl--;
590 
591 	if (r == ENTER) r = 0;
592 
593 	XCheckWindowEvent(display, winder, (KeyPressMask | KeyReleaseMask), event);
594 	if (event->type == KeyPress) {
595 		XLookupString((XKeyEvent *) event, &cc[0], 1, &key, NULL);
596 		dl = 0;
597 		switch (key) {
598 
599 		case XK_Up:
600 		case XK_KP_8:
601 			r = UPARROW;
602 			break;
603 		case XK_Down:
604 		case XK_KP_2:
605 			r = DOWNARROW;
606 			break;
607 		case XK_Left:
608 		case XK_KP_4:
609 			r = LEFTARROW;
610 			break;
611 		case XK_Right:
612 		case XK_KP_6:
613 			r = RIGHTARROW;
614 			break;
615 		case XK_Return:
616 		case XK_KP_Enter:
617 			r = ENTER;
618 			break;
619 		default:
620 			break;
621 		}
622 
623 	} else if (event->type == KeyRelease) {
624 		r = 0;
625 		dl = 0;
626 	}
627 
628 	if (dl) {
629 		return(0);
630 	} else {
631 		dl = 20;
632 		return(r);
633 	}
634 
635 } /* end X_GET_MENU_KEYS */
636 
637 
638 
639 /*
640 ** X_check_keypress
641 **
642 */
X_check_keypress()643 void X_check_keypress()
644 {
645 
646 	XEvent event;
647 	KeySym 	key;
648 	char c[1];
649 	XComposeStatus compose;
650 
651 	c[0] = '\0';
652 
653 	while (XCheckWindowEvent(display, winder, (KeyReleaseMask | KeyPressMask), &event)) {
654 		XLookupString( (XKeyEvent *) &event, &c[0], 1, &key, &compose);
655 		switch (event.type) {
656 
657 		case KeyPress:
658 
659 			switch (key) {
660 
661 			case XK_Up:
662 			case XK_KP_8:
663 			case XK_R8:
664 				keyboard_state = keyboard_state | KEY_THRUST1;
665 				break;
666 			case XK_Left:
667 			case XK_KP_4:
668 			case XK_R10:
669 				keyboard_state = keyboard_state | KEY_LEFT1;
670 				break;
671 			case XK_Right:
672 			case XK_KP_6:
673 			case XK_R12:
674 				keyboard_state = keyboard_state | KEY_RIGHT1;
675 				break;
676 			case XK_Shift_R:
677 				keyboard_state = keyboard_state | KEY_FIRE1;
678 				break;
679 			case XK_Return:
680 				keyboard_state = keyboard_state | KEY_HYPER1;
681 				break;
682 			case XK_F:
683 			case XK_f:
684 				keyboard_state = keyboard_state | KEY_THRUST2;
685 				break;
686 			case XK_C:
687 			case XK_c:
688 				keyboard_state = keyboard_state | KEY_LEFT2;
689 				break;
690 			case XK_B:
691 			case XK_b:
692 				keyboard_state = keyboard_state | KEY_RIGHT2;
693 				break;
694 			case XK_Shift_L:
695 				keyboard_state = keyboard_state | KEY_FIRE2;
696 				break;
697 			case XK_space:
698 				keyboard_state = keyboard_state | KEY_HYPER2;
699 				break;
700 			case XK_Q:
701 			case XK_q:
702 				keyboard_state = keyboard_state | KEY_QUIT;
703 				break;
704 			case XK_P:
705 			case XK_p:
706 				keyboard_state = keyboard_state | KEY_PAUSE;
707 				break;
708 			case XK_Escape:
709 				keyboard_state = keyboard_state | KEY_ESC;
710 				break;
711 			case XK_underscore:
712 			case XK_minus:
713 				if (delay < 2000) delay += 10;
714 				break;
715 			case XK_plus:
716 			case XK_equal:
717 				if (delay > 0) delay -= 10;
718 				break;
719 			default:
720 				break;
721 			}
722 
723 			break;
724 
725 		case KeyRelease:
726 
727 			switch (key) {
728 
729 			case XK_Up:
730 			case XK_KP_8:
731 			case XK_R8:
732 				keyboard_state = keyboard_state & ~KEY_THRUST1;
733 				break;
734 			case XK_Left:
735 			case XK_KP_4:
736 			case XK_R10:
737 				keyboard_state = keyboard_state & ~KEY_LEFT1;
738 				break;
739 			case XK_Right:
740 			case XK_KP_6:
741 			case XK_R12:
742 				keyboard_state = keyboard_state & ~KEY_RIGHT1;
743 				break;
744 			case XK_Shift_R:
745 				keyboard_state = keyboard_state & ~KEY_FIRE1;
746 				break;
747 			case XK_F:
748 			case XK_f:
749 				keyboard_state = keyboard_state & ~KEY_THRUST2;
750 				break;
751 			case XK_C:
752 			case XK_c:
753 				keyboard_state = keyboard_state & ~KEY_LEFT2;
754 				break;
755 			case XK_B:
756 			case XK_b:
757 				keyboard_state = keyboard_state & ~KEY_RIGHT2;
758 				break;
759 			case XK_Shift_L:
760 				keyboard_state = keyboard_state & ~KEY_FIRE2;
761 				break;
762 			default:
763 				break;
764 			}
765 
766 			break;
767 
768 		default:
769 
770 			break;
771 
772 		}
773 	}
774 
775 } /* end X_CHECK_KEYPRESS */
776 
777 
778 /*
779 ** X_DRAW_OBJECT
780 **
781 */
X_draw_object(obj)782 void X_draw_object(obj)
783 Sprite *obj;
784 {
785 
786 	do {
787 
788 		if ((obj->state == EXPLODING || obj->state == REVIVING) && obj->death_sprite) X_draw_object(obj->death_sprite);
789 
790 		if (obj->state <= DYING) {
791 			XSetClipOrigin(display, theGC, (int) obj->x - obj->wo2, (int) obj->y - obj->ho2);
792 			XSetClipMask(display, theGC, obj->clipmasks[obj->curr_map]);
793 			XCopyArea(display, obj->pixmaps[obj->curr_map], theDrawable, theGC, 0, 0, obj->width, obj->height, (int) obj->x - obj->wo2, (int) obj->y - obj->ho2);
794 		}
795 
796 	} while (obj = obj->next_draw);
797 
798 	XSetClipRectangles(display, theGC, 0, 0, &clip_rect, 1, Unsorted);
799 
800 } /* END X_DRAW_OBJECT */
801 
802 
803 
804 /*
805 ** X_DRAW_ONE_OBJECT
806 **
807 */
X_draw_one_object(obj,x,y)808 void X_draw_one_object(obj, x, y)
809 Sprite *obj;
810 int x, y;
811 {
812 
813 	XSetClipOrigin(display, theGC, x, y);
814 	XSetClipMask(display, theGC, obj->clipmasks[0]);
815 
816 	XCopyArea(display, obj->pixmaps[0], theDrawable, theGC, 0, 0, obj->width, obj->height, x, y);
817 
818 	XSetClipRectangles(display, theGC, 0, 0, &clip_rect, 1, Unsorted);
819 
820 } /* END X_DRAW_ONE_OBJECT */
821 
822 
823 
824 
825 /*
826 ** X_DRAW_LINK
827 **
828 ** Draws a line from the object to obj->next
829 */
X_draw_link(obj,col)830 void X_draw_link(obj, col)
831 Sprite *obj;
832 int col;
833 {
834 
835 	static int old_x, old_y, old_xl, old_yl;
836 
837 	if (!(obj->state || obj->next->state)) {
838 
839 		X_frontbuf();
840 		X_color(BLACK);
841 
842 		XDrawLine(display, winder, theGC, (int) obj->ox, (int) obj->oy, (int) obj->next_draw->ox, (int) obj->next_draw->oy);
843 
844 		X_color(col);
845 
846 		XDrawLine(display, winder, theGC, (int) obj->x, (int) obj->y, (int) obj->next_draw->x, (int) obj->next_draw->y);
847 
848 		X_color(BLACK);
849 
850 		X_backbuf();
851 
852 		if (old_x) {
853 			old_x = old_y = 0;
854 		}
855 
856 	} else if (!obj->state) {
857 
858 		X_frontbuf();
859 		X_color(BLACK);
860 
861 		if (!old_x) {
862 			old_x = (int) obj->ox;
863 			old_y = (int) obj->oy;
864 			old_xl = (int) (obj->ox - 2*link.length * sin(link.ang - link.ang_vec));
865 			old_yl = (int) (obj->oy - 2*link.length * cos(link.ang - link.ang_vec));
866 		}
867 
868 		XDrawLine(display, winder, theGC, old_x, old_y, old_xl, old_yl);
869 
870 		old_x = (int) obj->x;
871 		old_y = (int) obj->y;
872 		old_xl = (int) (obj->x - 2*link.length * sin(link.ang - link.ang_vec));
873 		old_yl = (int) (obj->y - 2*link.length * cos(link.ang - link.ang_vec));
874 
875 		X_color(col);
876 
877 		XDrawLine(display, winder, theGC, old_x, old_y, old_xl, old_yl);
878 
879 		X_color(BLACK);
880 
881 		X_backbuf();
882 
883 	} else if (!obj->next->state) {
884 
885 		X_frontbuf();
886 		X_color(BLACK);
887 
888 		if (!old_x) {
889 			old_x = (int) obj->next->ox;
890 			old_y = (int) obj->next->oy;
891 			old_xl = (int) (obj->next->ox + 2*link.length * sin(link.ang - link.ang_vec));
892 			old_yl = (int) (obj->next->oy + 2*link.length * cos(link.ang - link.ang_vec));
893 		}
894 
895 		XDrawLine(display, winder, theGC, old_x, old_y, old_xl, old_yl);
896 
897 		old_x = (int) obj->next->x;
898 		old_y = (int) obj->next->y;
899 		old_xl = (int) (obj->next->x + 2*link.length * sin(link.ang - link.ang_vec));
900 		old_yl = (int) (obj->next->y + 2*link.length * cos(link.ang - link.ang_vec));
901 
902 		X_color(col);
903 
904 		XDrawLine(display, winder, theGC, old_x, old_y, old_xl, old_yl);
905 
906 		X_color(BLACK);
907 
908 		X_backbuf();
909 
910 
911 	}
912 
913 } /* end X_DRAW_LINK */
914 
915 
916 
917 /*
918 ** X_DRAW_STARS
919 **
920 */
X_draw_stars(col,b)921 void X_draw_stars(col, b)
922 int col, b;
923 {
924 
925 	int x0, y0, x_or, y_or, x_rot, y_rot, i;
926 
927 	x_or = 0;
928 	y_or = 0;
929 
930 	if (b) num_bursts = 0;
931 
932 	X_color(col);
933 
934 	for (x0 = x_or;x0 < vdevice.sizeSx;x0 += 600) {
935 		for (y0 = y_or;y0 < vdevice.sizeSy;y0 += 400) {
936 			for (i=0;i<NUM_STARS;i++) {
937 
938 				x_rot = x0 + starfield[i].x;
939 				y_rot = y0 + starfield[i].y;
940 
941 				if (b) {
942 					burst[num_bursts].x = x_rot;
943 					burst[num_bursts].y = y_rot;
944 					burst[num_bursts].color = (int) random_num(0.0, 8.0);
945 					burst[num_bursts].max_radius = (int) random_num(24.0, 48.0);
946 					burst[num_bursts].radius = 1;
947 					burst[num_bursts].x_vec = 0;
948 					burst[num_bursts].y_vec = 0;
949 					burst[num_bursts++].dir = 1;
950 				} else {
951 					XDrawPoint(display, winder, theGC, x_rot, y_rot);
952 				}
953 			}
954 
955 		}
956 	}
957 
958 	X_color(BLACK);
959 
960 } /* end X_XDRAW_STARS */
961 
962 
963 
964 
965 /*
966 ** X_DRAW_STATUS_BAR
967 **
968 */
X_draw_status_bar()969 void X_draw_status_bar()
970 {
971 
972 	char str1[30], str2[30];
973 	int i;
974 
975 	sprintf(str1, "%s Score: %d", P->name, P->score);
976 	if (num_players > 1) sprintf(str2, "%s Score: %d", P->next->name, P->next->score);
977 
978 	X_frontbuf();
979 
980 	X_color(BLACK);
981 
982 	XFillRectangle(display, theDrawable, unclippedGC, 0, 0, vdevice.sizeSx, P->height + 3);
983 
984 	XFlush(display);
985 
986 	if (num_players > 1) {
987 		X_draw_one_object(P->next, 5, 0);
988 		X_draw_one_object(P, eng_outliner.x - 175, 0);
989 	} else {
990 		for (i=0;i<P->lives;i++) {
991 			X_draw_one_object(P, i * (int) (P->width + 5) + 5, 0);
992 		}
993 	}
994 
995 	X_color(WHITE);
996 
997 	if (num_players > 1) {
998 		XDrawString(display, theDrawable, unclippedGC, 10 + P->width, P->height - 7, str2, strlen(str2));
999 		XDrawString(display, theDrawable, unclippedGC, eng_outliner.x - 170 + P->width, P->height - 7, str1, strlen(str1));
1000 		XDrawRectangle(display, theDrawable, unclippedGC, eng_outlinel.x, eng_outlinel.y, eng_outlinel.width, eng_outlinel.height);
1001 	} else {
1002 		XDrawString(display, theDrawable, unclippedGC, 10 + (P->lives > 0 ? P->lives : 1) * (P->width + 5), P->height - 7, str1, strlen(str1));
1003 	}
1004 
1005 	XDrawRectangle(display, theDrawable, unclippedGC, eng_outliner.x, eng_outliner.y, eng_outliner.width, eng_outliner.height);
1006 	XDrawLine(display, theDrawable, unclippedGC, 0, P->height + 3, vdevice.sizeSx, P->height + 3);
1007 
1008 	X_color(BLACK);
1009 
1010 	X_backbuf();
1011 
1012 } /* end X_DRAW_STATUS_BAR */
1013 
1014 
1015 
1016 /*
1017 ** X_update_status_bar
1018 **
1019 */
X_update_status_bar()1020 void X_update_status_bar()
1021 {
1022 
1023 	int new_val;
1024 
1025 	XFillRectangle(display, theDrawable, unclippedGC, eng_outliner.x, eng_outliner.y, eng_outliner.width, eng_outliner.height);
1026 
1027 	XFlush(display);
1028 
1029 	new_val = (int) (wo7 * P->engine / 1000);
1030 
1031 	if (P->engine > 750) {
1032 		X_color(RED);
1033 	} else if (P->engine > 500) {
1034 		X_color(YELLOW);
1035 	} else X_color(GREEN);
1036 
1037 	XFillRectangle(display, theDrawable, unclippedGC, eng_outliner.x+1, eng_outliner.y+1, new_val, eng_outliner.height-2);
1038 
1039 	if (num_players > 1) {
1040 
1041 		X_color(BLACK);
1042 
1043 		XFillRectangle(display, theDrawable, unclippedGC, eng_outlinel.x, eng_outlinel.y, eng_outlinel.width, eng_outlinel.height);
1044 
1045 		XFlush(display);
1046 
1047 		new_val = (int) (wo7 * P->next->engine / 1000);
1048 
1049 		if (P->next->engine > 750) {
1050 			X_color(RED);
1051 		} else if (P->next->engine > 500) {
1052 			X_color(YELLOW);
1053 		} else X_color(GREEN);
1054 
1055 		XFillRectangle(display, theDrawable, unclippedGC, eng_outlinel.x+1, eng_outlinel.y+1, new_val, eng_outlinel.height-2);
1056 	}
1057 
1058 	X_color(BLACK);
1059 
1060 } /* end UPDATE_STATUS_BAR */
1061 
1062 
1063 
1064 /*
1065  * X_FLASH_SCREEN
1066  *
1067  * Clear the screen (or current buffer )
1068  */
X_flash_screen(d)1069 void X_flash_screen(d)
1070 int d;
1071 {
1072 
1073 	int i;
1074 
1075 	X_frontbuf();
1076 
1077 	X_color(WHITE);
1078 
1079 	XSetClipRectangles(display, theGC, 0, 0, &clip_rect, 1, Unsorted);
1080 
1081 	for (i=0;i<d;i++) {
1082 
1083 		XFillRectangle(display,
1084 			theDrawable,
1085 			theGC,
1086 			0,
1087 			0,
1088 			(unsigned int)vdevice.sizeSx + 1,
1089 			(unsigned int)vdevice.sizeSy + 1
1090 		);
1091 
1092 		X_swapbuf();
1093 
1094 	}
1095 
1096 	X_color(BLACK);
1097 
1098 	XFillRectangle(display,
1099 		theDrawable,
1100 		theGC,
1101 		0,
1102 		0,
1103 		(unsigned int)vdevice.sizeSx + 1,
1104 		(unsigned int)vdevice.sizeSy + 1
1105 	);
1106 
1107 	X_backbuf();
1108 
1109 } /* end X_FLASH_SCREEN */
1110 
1111 
1112 
1113 /*
1114 ** X_DRAW_THRUST
1115 **
1116 */
X_draw_thrust(obj)1117 void X_draw_thrust(obj)
1118 Sprite *obj;
1119 {
1120 
1121 	int i, x1, y1, x2, y2, m1, n1, m2, n2;
1122 
1123 	x1 = thrust_pts_x[0];
1124 	y1 = thrust_pts_y[0];
1125 	m1 = x1*cos_table[obj->curr_map] - y1*sin_table[obj->curr_map];
1126 	n1 = -x1*sin_table[obj->curr_map] - y1*cos_table[obj->curr_map];
1127 
1128 	X_color(RED);
1129 
1130 	for (i=1;i<N_THRUST_PTS;i++) {
1131 		x2 = thrust_pts_x[i];
1132 		y2 = thrust_pts_y[i];
1133 		m2 = x2*cos_table[obj->curr_map] - y2*sin_table[obj->curr_map];
1134 		n2 = -x2*sin_table[obj->curr_map] - y2*cos_table[obj->curr_map];
1135 		XDrawLine(display, theDrawable, theGC, m1 + (int) obj->x, n1 + (int) obj->y, m2 + (int) obj->x, n2 + (int) obj->y);
1136 		m1 = m2;
1137 		n1 = n2;
1138 	}
1139 
1140 	X_color(BLACK);
1141 
1142 } /* end X_DRAW_THRUST */
1143 
1144 
1145 
1146 /*
1147 ** X_DRAW_BURSTS
1148 **
1149 */
X_draw_bursts(flag)1150 void X_draw_bursts(flag)
1151 int flag;
1152 {
1153 
1154 	int i,j,x,y;
1155 
1156 	for (i=0;i<num_bursts;i++) {
1157 
1158 		if (flag) {
1159 			X_color(burst[i].color);
1160 		} else {
1161 			X_color(BLACK);
1162 		}
1163 
1164 		for (j=0;j<16;j++) {
1165 
1166 			x = burst[i].x + (int) burst[i].radius * cos_table[j << 1];
1167 			y = burst[i].y + (int) burst[i].radius * sin_table[j << 1];
1168 
1169 			XDrawPoint(display, winder, theGC, x, y);
1170 
1171 		}
1172 
1173 	}
1174 
1175 	X_color(BLACK);
1176 
1177 } /* end X_DRAW_BURSTS */
1178 
1179 
1180 
1181 /*
1182 ** X_DRAW_SHOTS
1183 **
1184 */
X_draw_shots(obj)1185 void X_draw_shots(obj)
1186 Sprite *obj;
1187 {
1188 
1189 	int i, j;
1190 	float s, c;
1191 	struct Shot *curr;
1192 
1193 	do {
1194 
1195 		if (obj->shots) {
1196 
1197 			X_color(obj->shot_color);
1198 
1199 			for (i=0;i<obj->shots;i++) {
1200 
1201 				curr = obj->S[i];
1202 
1203 				for (j=0;j<4;j++)
1204 					XDrawLine(display, theDrawable, theGC,  (int) curr->x + curr->pts_x[j], (int) curr->y + curr->pts_y[j], (int) curr->x + curr->pts_x[j+1], (int) curr->y + curr->pts_y[j+1]);
1205 
1206 			}
1207 		}
1208 
1209 	} while (obj = obj->next);
1210 
1211 	X_color(BLACK);
1212 
1213 } /* end X_DRAW_SHOTS */
1214 
1215 
1216 /*
1217 ** X_CLEAR_SHOTS
1218 **
1219 */
X_clear_shots(obj)1220 void X_clear_shots(obj)
1221 Sprite *obj;
1222 {
1223 
1224 	int i, j;
1225 	float s, c;
1226 	struct Shot *curr;
1227 
1228 	X_color(BLACK);
1229 
1230 	do {
1231 		if (obj->shots) {
1232 
1233 			for (i=0;i<obj->shots;i++) {
1234 
1235 				curr = obj->S[i];
1236 
1237 				for (j=0;j<4;j++)
1238 					XDrawLine(display, theDrawable, theGC,  (int) curr->ox + curr->pts_x[j], (int) curr->oy + curr->pts_y[j], (int) curr->ox + curr->pts_x[j+1], (int) curr->oy + curr->pts_y[j+1]);
1239 
1240 			}
1241 
1242 		}
1243 
1244 	} while (obj = obj->next);
1245 
1246 } /* end X_CLEAR_SHOTS */
1247 
1248 
1249 /*
1250 ** X_CLEAR_OBJECT
1251 **
1252 */
X_clear_object(obj)1253 void X_clear_object(obj)
1254 Sprite *obj;
1255 {
1256 
1257 	do {
1258 
1259 		if ((obj->state == EXPLODING || obj->state == REVIVING) && obj->death_sprite) X_clear_object(obj->death_sprite);
1260 
1261 		if (obj->state <= DYING)
1262 			XFillRectangle(display, theDrawable, theGC, (int) obj->ox - obj->wo2, (int) obj->oy - obj->ho2, obj->width, obj->height);
1263 
1264 	} while (obj = obj->next_draw);
1265 
1266 } /* end X_CLEAR_OBJECT */
1267 
1268 
1269 /*
1270 ** X_CLEAR_ONE_OBJECT
1271 **
1272 */
X_clear_one_object(obj)1273 void X_clear_one_object(obj)
1274 Sprite *obj;
1275 {
1276 
1277 	XFillRectangle(display, theDrawable, theGC, (int) obj->x - obj->wo2, (int) obj->y - obj->ho2, obj->width, obj->height);
1278 
1279 } /* end X_CLEAR_ONE_OBJECT */
1280 
1281 
1282 
1283 /*
1284 **
1285 ** X_COPY_STATUS_BAR_TO_WINDOW
1286 **
1287 */
X_copy_status_bar_to_window()1288 void X_copy_status_bar_to_window()
1289 {
1290 
1291 	XFlush(display);
1292 
1293 	if (num_players > 1)
1294 		XCopyArea(display,
1295 			theDrawable,
1296 			winder,
1297 			unclippedGC,
1298 			eng_outlinel.x+1, eng_outlinel.y+1,
1299 			eng_outlinel.width-2,
1300 			eng_outlinel.height-2,
1301 			eng_outlinel.x+1, eng_outlinel.y+1
1302 		);
1303 
1304 	XCopyArea(display,
1305 		theDrawable,
1306 		winder,
1307 		unclippedGC,
1308 		eng_outliner.x+1, eng_outliner.y+1,
1309 		eng_outliner.width-2,
1310 		eng_outliner.height-2,
1311 		eng_outliner.x+1, eng_outliner.y+1
1312 	);
1313 
1314 	XFlush(display);
1315 
1316 } /* end X_COPY_STATUS_BAR_TO_WINDOW */
1317 
1318 
1319 
1320 
1321 /*
1322  * X_COPY_OBJECT_TO_WINDOW
1323  *
1324  *	Swap the back and from buffers. (Really, just copy the
1325  *	back buffer to the screen).
1326  */
X_copy_object_to_window(obj)1327 void X_copy_object_to_window(obj)
1328 Sprite *obj;
1329 {
1330 
1331 	int i, sz;
1332 	struct Shot *curr;
1333 
1334 	XFlush(display);
1335 
1336 	X_backbuf();
1337 
1338 	do {
1339 
1340 		sz = Weapon[obj->wpn].size + 2;
1341 
1342 		if ((obj->state == EXPLODING || obj->state == REVIVING) && obj->death_sprite) X_copy_object_to_window(obj->death_sprite);
1343 
1344 		if (obj->state <= DYING) {
1345 			XCopyArea(display,
1346 			theDrawable,
1347 			winder,
1348 			theGC,
1349 			(int) obj->x - obj->wo2, (int) obj->y - obj->ho2,
1350 			obj->width,
1351 			obj->height,
1352 			(int) obj->x - obj->wo2, (int) obj->y - obj->ho2
1353 			);
1354 
1355 			XCopyArea(display,
1356 			theDrawable,
1357 			winder,
1358 			theGC,
1359 			(int) obj->ox - obj->wo2, (int) obj->oy - obj->ho2,
1360 			obj->width,
1361 			obj->height,
1362 			(int) obj->ox - obj->wo2, (int) obj->oy - obj->ho2
1363 			);
1364 		}
1365 
1366 		if (obj->shots) {
1367 			for (i=0;i<obj->shots;i++) {
1368 
1369 				curr = obj->S[i];
1370 
1371 				XCopyArea(display,
1372 				theDrawable,
1373 				winder,
1374 				theGC,
1375 				(int) curr->x-sz, (int) curr->y-sz,
1376 				2*sz,
1377 				2*sz,
1378 				(int) curr->x-sz, (int) curr->y-sz
1379 				);
1380 
1381 				XCopyArea(display,
1382 				theDrawable,
1383 				winder,
1384 				theGC,
1385 				(int) curr->ox-sz, (int) curr->oy-sz,
1386 				2*sz,
1387 				2*sz,
1388 				(int) curr->ox-sz, (int) curr->oy-sz
1389 				);
1390 
1391 			}
1392 		}
1393 
1394 		XFlush(display);
1395 
1396 	} while (obj = obj->next_draw);
1397 
1398 	XSetFunction(display, theGC, GXcopy);
1399 
1400 } /* end X_COPY_OBJECT_TO_WINDOW */
1401 
1402 
1403 
1404 /*
1405  * X_draw
1406  *
1407  *	draws a line from the current graphics position to (x, y).
1408  *
1409  * Note: (0, 0) is defined as the top left of the window in X (easy
1410  * to forget).
1411  */
X_draw(x,y)1412 X_draw(x, y)
1413 	int	x, y;
1414 {
1415 	XDrawLine(display,
1416 		theDrawable,
1417 		theGC,
1418 		vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy,
1419 		x, vdevice.sizeSy - y
1420 	);
1421 
1422 	XFlush(display);
1423 }
1424 
1425 /*
1426 ** X_point
1427 **
1428 **	Draw a point!
1429 **
1430 */
X_point(x,y)1431 void X_point(x, y)
1432 int x, y;
1433 {
1434 
1435 	XDrawPoint(display, winder, theGC, x, y);
1436 
1437 } /* end X_point */
1438 
1439 
1440 
1441 /*
1442  * X_getkey
1443  *
1444  *	grab a character from the keyboard - blocks until one is there.
1445  */
1446 int
X_getkey()1447 X_getkey()
1448 {
1449 	char	c;
1450 	XEvent event;
1451 
1452 	do {
1453 		XNextEvent(display, &event);
1454 		if (event.type == KeyPress) {
1455 			if (XLookupString( (XKeyEvent *) &event, &c, 1, NULL, NULL) > 0)
1456 				return((int) c);
1457 			else
1458 				return(0);
1459 		}
1460 	} while (event.type != KeyPress);
1461 
1462 	return(0);
1463 }
1464 
1465 /*
1466 ** X_UPDATE
1467 **
1468 ** Flush the X server's queue and handle visilibity and
1469 ** window resizing events.
1470 **
1471 */
X_update(game_flag)1472 void X_update(game_flag)
1473 unsigned int game_flag;
1474 {
1475 
1476 	XEvent event;
1477 
1478 	/* Check for expose events */
1479 
1480 	if (XCheckWindowEvent(display, winder, VisibilityChangeMask, &event)) {
1481 		X_frontbuf();
1482 		X_clear();
1483 		if (game_flag) {
1484 			X_backbuf();
1485 			X_draw_status_bar();
1486 		}
1487 	}
1488 
1489 	/* Check for window resize */
1490 
1491 	if (XCheckWindowEvent(display, winder, StructureNotifyMask, &event)) {
1492 
1493 		if (event.type == ConfigureNotify) {
1494 
1495 			vdevice.sizeSx = event.xconfigure.width;
1496 			vdevice.sizeSy = event.xconfigure.height;
1497 
1498 			if (vdevice.sizeSx < 320) vdevice.sizeSx = 320;
1499 			if (vdevice.sizeSy < 200) vdevice.sizeSy = 200;
1500 
1501 			/* Set the clipping region = the score box */
1502 
1503 			clip_rect.x = 0;
1504 			clip_rect.y = P->height + 4;
1505 			clip_rect.width = vdevice.sizeSx;
1506 			clip_rect.height = vdevice.sizeSy - (int) (P->height + 4);
1507 
1508 			XSetClipRectangles(display, theGC, 0, 0, &clip_rect, 1, Unsorted);
1509 
1510 			/* Change the size of the back buffer */
1511 
1512 			XFreePixmap(display, bbuf);
1513 
1514 			bbuf = XCreatePixmap(display,
1515 				(Drawable)winder,
1516 				(unsigned int)vdevice.sizeSx,
1517 				(unsigned int)vdevice.sizeSy,
1518 				(unsigned int)vdevice.depth
1519 			);
1520 
1521 			/* Set outlines for engine heat bars */
1522 
1523 			wo7 = (int) (vdevice.sizeSx / 7);
1524 			wo40 = (int) (vdevice.sizeSx / 40);
1525 
1526 			eng_outlinel.x = 150 + P->width;
1527 			eng_outlinel.y = 7;
1528 			eng_outlinel.height = (int) P->height - 11;
1529 			eng_outlinel.width = wo7;
1530 
1531 			eng_outliner.x = 6 * wo7 - 5;
1532 			eng_outliner.y = 7;
1533 			eng_outliner.height = P->height - 11;
1534 			eng_outliner.width = wo7;
1535 
1536 			X_frontbuf();
1537 			X_clear();
1538 			if (game_flag) {
1539 				X_backbuf();
1540 				X_clear();
1541 				X_draw_status_bar();
1542 			}
1543 		}
1544 	}
1545 
1546 	/* Use XSYNC so that keyboard is ALWAYS updated! */
1547 
1548 	XSync(display, 0);
1549 
1550 } /* end X_UPDATE */
1551 
1552 
1553 /*
1554  * X_checkkey
1555  *
1556  *	Check if there has been a keyboard key pressed.
1557  *	and return it if there is.
1558  */
1559 int
X_checkkey()1560 X_checkkey()
1561 {
1562 	char	c;
1563 	XEvent event;
1564 
1565 	if (!XCheckWindowEvent(display, winder, KeyPressMask, &event))
1566 		return(0);
1567 
1568 	if (event.type == KeyPress)
1569 		if (XLookupString( (XKeyEvent *) &event, &c, 1, NULL, NULL) > 0)
1570 			return((int)c);
1571 
1572 	return(0);
1573 }
1574 
1575 /*
1576  * X_locator
1577  *
1578  *	return the window location of the cursor, plus which mouse button,
1579  * if any, is been pressed.
1580  */
1581 int
X_locator(wx,wy)1582 X_locator(wx, wy)
1583 	int	*wx, *wy;
1584 {
1585 	Window	rootw, childw;
1586 	int	x, y;
1587 	unsigned int mask;
1588 
1589 	XQueryPointer(display, winder, &rootw, &childw, &x, &y, wx, wy, &mask);
1590 
1591 	*wy = (int)vdevice.sizeSy - *wy;
1592 
1593 	return(mask >> 8);
1594 }
1595 
1596 /*
1597  * X_clear
1598  *
1599  * Clear the screen (or current buffer )to current colour
1600  */
X_clear()1601 void X_clear()
1602 {
1603 
1604 	X_color(BLACK);
1605 
1606 	XFillRectangle(display,
1607 		theDrawable,
1608 		theGC,
1609 		0,
1610 		0,
1611 		vdevice.sizeSx,
1612 		vdevice.sizeSy
1613 	);
1614 
1615 }
1616 
1617 /*
1618  * X_color
1619  *
1620  *	set the current drawing color index.
1621  */
X_color(ind)1622 void X_color(ind)
1623         int	ind;
1624 {
1625 	colour = carray[ind];
1626 	XSetForeground(display, theGC, colour);
1627 	XSetForeground(display, unclippedGC, colour);
1628 }
1629 
1630 /*
1631  * X_mapcolor
1632  *
1633  *	change index i in the color map to the appropriate r, g, b, value.
1634  */
X_mapcolor(i,r,g,b)1635 int X_mapcolor(i, r, g, b)
1636 	int	i;
1637 	int	r, g, b;
1638 {
1639 	int	stat;
1640 	XColor	tmp;
1641 
1642 	if (i >= CMAPSIZE)
1643 		return(-1);
1644 
1645 
1646 	/*
1647 	 * For Black and White.
1648 	 * If the index is 0 and r,g,b != 0 then we are remapping black.
1649 	 * If the index != 0 and r,g,b == 0 then we make it black.
1650 	 */
1651 	if (vdevice.depth == 1) {
1652 		if (i == 0 && (r != 0 || g != 0 || b != 0))
1653 			carray[i] = WhitePixel(display, screen);
1654 		else if (i != 0 && r == 0 && g == 0 && b == 0)
1655 			carray[i] = BlackPixel(display, screen);
1656 	} else {
1657 		tmp.red = (unsigned short)(r / 255.0 * 65535);
1658 		tmp.green = (unsigned short)(g / 255.0 * 65535);
1659 		tmp.blue = (unsigned short)(b / 255.0 * 65535);
1660 		tmp.flags = 0;
1661 		tmp.pixel = (unsigned long)i;
1662 
1663 		if ((stat = XAllocColor(display, colormap, &tmp)) == 0) {
1664 			fprintf(stderr, "XAllocColor failed (status = %d)\n", stat);
1665 			exit(1);
1666 		}
1667 		carray[i] = tmp.pixel;
1668 	}
1669 
1670 	XFlush(display);
1671 	return(0);
1672 }
1673 
1674 /*
1675  * X_font
1676  *
1677  *   Set up a hardware font. Return 1 on success 0 otherwise.
1678  *
1679  */
X_font(fontfile)1680 X_font(fontfile)
1681         char	*fontfile;
1682 {
1683 	XGCValues	xgcvals;
1684 
1685 	if (font_id != (XFontStruct *)NULL)
1686 		XFreeFont(display, font_id);
1687 
1688 	if (strcmp(fontfile, "small") == 0) {
1689 		if ((font_id = XLoadQueryFont(display, SMALLX11R2)) == (XFontStruct *)NULL) {		/* X11 R2 */
1690 			if ((font_id = XLoadQueryFont(display, SMALLX11R3)) == (XFontStruct *)NULL)	 	/* X11 R3 */
1691 				return(0);
1692 			else
1693 				fontfile = SMALLX11R3;
1694 		} else
1695 			fontfile = SMALLX11R2;
1696 	} else if (strcmp(fontfile, "large") == 0) {
1697 		if ((font_id = XLoadQueryFont(display, LARGEX11R2)) == (XFontStruct *)NULL) {		/* X11 R2 */
1698 			if ((font_id = XLoadQueryFont(display, LARGEX11R3)) == (XFontStruct *)NULL)	 	/* X11 R3 */
1699 				return(0);
1700 			else
1701 				fontfile = LARGEX11R3;
1702 		} else
1703 			fontfile = LARGEX11R2;
1704 	} else if ((font_id = XLoadQueryFont(display, fontfile)) == (XFontStruct *)NULL)
1705 		return(0);
1706 
1707 	vdevice.hheight = font_id->max_bounds.ascent + font_id->max_bounds.descent;
1708 	vdevice.hwidth = font_id->max_bounds.width;
1709 
1710 	xgcvals.font = XLoadFont(display, fontfile);
1711 	XChangeGC(display, theGC, GCFont, &xgcvals);
1712 
1713 	return(1);
1714 }
1715 
1716 /*
1717  * X_char
1718  *
1719  *	 outputs one char - is more complicated for other devices
1720  */
X_char(c)1721 X_char(c)
1722 	char	c;
1723 {
1724 	char	*s = " ";
1725 
1726 	s[0] = c;
1727 	XDrawString(display, theDrawable, theGC, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), s, 1);
1728 	XFlush(display);
1729 }
1730 
1731 /*
1732  * X_string
1733  *
1734  *	Display a string centered at the specified height
1735  */
X_string(s,y)1736 void X_string(s, y)
1737 char *s;
1738 int y;
1739 {
1740 	int len, wid;
1741 
1742 	len = strlen(s);
1743 
1744 	wid = XTextWidth(font_info, s, len);
1745 
1746 	XDrawString(display, theDrawable, theGC, (int) (vdevice.sizeSx / 2 - wid / 3), y, s, len);
1747 	XSync(display, 0);
1748 }
1749 
1750 /*
1751  * X_fill
1752  *
1753  *	fill a polygon
1754  */
X_fill(n,x,y)1755 X_fill(n, x, y)
1756 	int	n, x[], y[];
1757 {
1758 	XPoint	plist[128];
1759 	int	i;
1760 
1761 	if (n > 128)
1762 		perror("xoids: more than 128 points in a polygon");
1763 
1764 	for (i = 0; i < n; i++) {
1765 		plist[i].x = x[i];
1766 		plist[i].y = vdevice.sizeSy - y[i];
1767 	}
1768 
1769 	XFillPolygon(display, theDrawable, theGC, plist, n, Nonconvex, CoordModeOrigin);
1770 
1771 	vdevice.cpVx = x[n-1];
1772 	vdevice.cpVy = y[n-1];
1773 
1774 	XFlush(display);
1775 }
1776 
1777 #define	GC_COPY_MASK	~0
1778 
1779 /*
1780  * X_backbuf
1781  *
1782  *	Set up double buffering by allocating the back buffer and
1783  *	setting drawing into it.
1784  */
X_backbuf()1785 void X_backbuf()
1786 {
1787 	if (!back_used)
1788 		bbuf = XCreatePixmap(display,
1789 			(Drawable)winder,
1790 			(unsigned int)vdevice.sizeSx,
1791 			(unsigned int)vdevice.sizeSy,
1792 			(unsigned int)vdevice.depth
1793 		);
1794 
1795 	theDrawable = (Drawable)bbuf;
1796 
1797 	back_used = 1;
1798 
1799 }
1800 
1801 /*
1802  * X_swapbuf
1803  *
1804  *	Swap the back and from buffers. (Really, just copy the
1805  *	back buffer to the screen).
1806  */
X_swapbuf()1807 void X_swapbuf()
1808 {
1809 
1810 	XCopyArea(display,
1811 		theDrawable,
1812 		winder,
1813 		theGC,
1814 		0, P->height + 4,
1815 		vdevice.sizeSx+1,
1816 		vdevice.sizeSy-P->height-3,
1817 		0, P->height + 4
1818 	);
1819 
1820 	XSync(display, 0);	/* Not XFlush */
1821 }
1822 
1823 /*
1824  * X_frontbuf
1825  *
1826  *	Make sure we draw to the screen.
1827  */
X_frontbuf()1828 void X_frontbuf()
1829 {
1830 	theDrawable = (Drawable)winder;
1831 }
1832 
1833 /*
1834 ** X_PRINT_QUEUE
1835 **
1836 */
X_print_queue()1837 void X_print_queue()
1838 {
1839 
1840 	int q;
1841 
1842 	q = XEventsQueued(display, QueuedAlready);
1843 
1844 	fprintf(stderr, "Queued: %d events\n", q);
1845 
1846 } /* end X_PRINT_QUEUE */
1847