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