1 /*======================================================================
2     xrot
3                                 Copyright (C) 1997,1998 Masao Shiraishi
4                                 e-mail:msiro@cs.meiji.ac.jp
5 ========================================================================*/
6 
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
9 #include <X11/keysym.h>
10 #include <X11/xpm.h>
11 #include <sys/types.h>
12 #include <memory.h>
13 #include <stdlib.h>
14 #include <math.h>
15 #include <stdio.h>
16 
17 #include "xrot.h"
18 #include "pixmap.h"
19 #include "xwin.h"
20 #include "record.h"
21 
22 #include "c1.h"
23 #include "c2.h"
24 #include "c3.h"
25 #include "c4.h"
26 #include "c5.h"
27 #include "c6.h"
28 #include "c7.h"
29 
30 #ifdef MITSHM
31 #include <sys/ipc.h>
32 #include <sys/shm.h>
33 #include <X11/extensions/XShm.h>
34 XShmSegmentInfo shminfo[2];
35 int shm = 1;
36 #endif
37 
38 #define PROG_NAME "xrot"
39 
40 int vwidth, vheight;
41 int RWIDTH, RHEIGHT;
42 
43 Display *dp = NULL;
44 Colormap cmap;
45 XColor colors;
46 unsigned long gpixel, b3pixel, otpixel, cs_pixel;
47 unsigned long tipix[4];
48 char g_pixel;
49 unsigned short grad[64];
50 int redc;
51 int owncmap;
52 
53 #define FONT   "-*-new century schoolbook-medium-i-*--18-*-*-*-p-*-*-*"
54 #define FONT_CS   "-*-new century schoolbook-medium-r-*--18-*-*-*-p-*-*-*"
55 #define FONT2  "-*-times-bold-r-*--14-*-*-*-p-*-*-*"
56 
57 Pixel *bg_col;
58 unsigned int bg_num;
59 
60 Window win, root;
61 GC copyGC, clearGC, blackGC, goalGC;
62 GC textGC, text_csGC[2], titleGC, keysGC, fadeGC;
63 int sc;
64 XImage *ximage[2];
65 int dbl_buf;
66 XEvent ev;
67 XFontStruct *fn, *fn2, *fn_cs;
68 int ascent, ascent2, ascent_cs;
69 
70 static int cs_width, cs_x, cs_text_x;
71 static int cs_num;
72 static int cs_state[COURSE];
73 
74 /* pixmap */
75 Pixmap p_frame, p_titlem;
76 Pixmap num[5];
77 int num_state;
78 Pixmap back_pix;
79 char **bg_data[4];
80 XImage *back_image;
81 Pixmap p_wall[21];
82 int wall_width[21], wall_height[21];
83 char **p_wall_data[21];
84 Pixmap point_ball;
85 
86 Pixmap p_ball[2], mask[2];
87 GC ballGC[2][2];
88 XpmAttributes xpatt;
89 int ball_x, ball_y, ball_w, ball_h;
90 int ball_x_bg, ball_y_bg;
91 int view_x, view_y;
92 Pixmap p_course;
93 
94 Pixmap fade[25];
95 
96 char *image[2];
97 unsigned char *temp;
98 
99 int key_right, key_left;
100 int key_space, jump_key, soft_key;
101 int escape;
102 int restart; /* RET key */
103 
104 unsigned long black_pixel, white_pixel;
105 
106 struct course_d *cs_d[COURSE];
107 int lx[COURSE];
108 int ly[COURSE];
109 int sdeg[COURSE];
110 int gx[COURSE];
111 int gy[COURSE];
112 int gw[COURSE];
113 int gh[COURSE];
114 
115 /* course data */
116 unsigned int bw, bh;
117 XImage *bimage;
118 char *bdata;
119 
120 int width, height;
121 
122 #define TCOL1 "white"
123 #define TCOL2 "orange"
124 #define TCOL3 "yellow"
125 
init_X()126 void init_X()
127 {
128     XSizeHints size;
129     XWMHints hints;
130     Visual *visual;
131     XColor set_pixel, rgb;
132     int i;
133     unsigned long bpixel, wpixel;
134     unsigned long plane_mask, pixel[64];
135 
136     if( (dp = XOpenDisplay( NULL )) == NULL ){
137 	fprintf( stderr, "Can't connect X server\n" );
138 	exit(1);
139     }
140     sc = DefaultScreen( dp );
141     root = RootWindow( dp, sc );
142     visual = DefaultVisual( dp, sc );
143     win = XCreateSimpleWindow( dp, root, 0, 0, WWIDTH, WHEIGHT,
144 			                0, 0, 0);
145     bpixel = BlackPixel( dp, sc );
146     wpixel = WhitePixel( dp, sc );
147     cmap = DefaultColormap( dp, sc );
148     if( XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 80 ) == 0 )
149 	owncmap = 1;
150     else
151 	XFreeColors( dp, cmap, pixel, 80, 0 );
152     if( visual->class != PseudoColor || DefaultDepth(dp, sc) != 8 )
153 	owncmap = 1;
154     if( owncmap )
155 	create_cmap( &bpixel, &wpixel );
156     XSetWindowBackground( dp, win, bpixel );
157 
158     copyGC = XCreateGC( dp, root, 0, NULL );
159     XSetGraphicsExposures( dp, copyGC, False );
160     clearGC = XCreateGC( dp, root, 0, NULL );
161     XSetForeground( dp, clearGC, 0 );
162     blackGC = XCreateGC( dp, root, 0, NULL );
163     XSetForeground( dp, blackGC, bpixel );
164     black_pixel = bpixel;
165     white_pixel = wpixel;
166 
167     XAllocNamedColor( dp, cmap, "yellow", &set_pixel, &rgb );
168     b3pixel = set_pixel.pixel;
169     XAllocNamedColor( dp, cmap, "red", &set_pixel, &rgb );
170     otpixel = set_pixel.pixel;
171     XAllocNamedColor( dp, cmap, "orange", &set_pixel, &rgb );
172     cs_pixel = set_pixel.pixel;
173 
174     set_fade();
175 
176     /* font */
177     textGC = XCreateGC( dp, root, 0, NULL );
178     if( (fn = XLoadQueryFont( dp, FONT )) == NULL )
179 	p_err("Unable to load font");
180     XSetFont( dp, textGC, fn->fid );
181     ascent = fn->max_bounds.ascent;
182     XSetForeground( dp, textGC, wpixel );
183 
184     text_csGC[0] = XCreateGC( dp, root, 0, NULL );
185     if( (fn_cs = XLoadQueryFont( dp, FONT_CS )) == NULL )
186 	p_err("Unable to load font");
187     XSetFont( dp, text_csGC[0], fn_cs->fid );
188     ascent_cs = fn_cs->max_bounds.ascent;
189     XSetForeground( dp, text_csGC[0], wpixel );
190 
191     text_csGC[1] = XCreateGC( dp, root, 0, NULL );
192     XSetFont( dp, text_csGC[1], fn_cs->fid );
193     ascent_cs = fn_cs->max_bounds.ascent;
194     XSetForeground( dp, text_csGC[1], cs_pixel );
195 
196     titleGC = XCreateGC( dp, root, 0, NULL );
197     if( (fn2 = XLoadQueryFont( dp, FONT2 )) == NULL )
198 	p_err("Unable to load font");
199     XSetFont( dp, titleGC, fn2->fid );
200     keysGC = XCreateGC( dp, root, 0, NULL );
201     XSetFont( dp, keysGC, fn2->fid );
202     ascent2 = fn2->max_bounds.ascent;
203     XAllocNamedColor( dp, cmap, TCOL2, &set_pixel, &rgb );
204     tipix[1] = set_pixel.pixel;
205     XAllocNamedColor( dp, cmap, TCOL3, &set_pixel, &rgb );
206     tipix[2] = set_pixel.pixel;
207 
208     for( i = 0; i < 64; i++ )
209 	grad[i] = (unsigned short) (sin(M_PI/64.0*i) * 65535.0);
210     redc = 0;
211 
212     XSelectInput( dp, win, ExposureMask | KeyPressMask | KeyReleaseMask );
213 
214     size.flags = PMinSize | PMaxSize;
215     size.min_width  = WWIDTH;
216     size.min_height = WHEIGHT;
217     size.max_width  = WWIDTH;
218     size.max_height = WHEIGHT;
219     XSetNormalHints( dp, win, &size );
220 
221     hints.flags = InputHint;
222 #ifdef HINT_TRUE
223     hints.input = True;
224 #else
225     hints.input = False;
226 #endif
227     XSetWMHints( dp, win, &hints );
228 
229     XStoreName( dp, win, PROG_NAME );
230 
231     key_left = key_right = 0;
232     key_space = 0;
233     jump_key = 0;
234     XMapWindow( dp, win );
235     XFlush( dp );
236   ev_loop1:
237     XNextEvent( dp, &ev );
238     if( ev.type != Expose )
239 	goto ev_loop1;
240 
241 #ifdef MITSHM
242     if( XShmQueryExtension( dp ) != True )
243 	shm = 0;
244     if( shm ){
245     ximage[0] = XShmCreateImage( dp, DefaultVisual( dp, sc ),
246       8, ZPixmap, NULL, &shminfo[0], vwidth, vheight );
247     ximage[1] = XShmCreateImage( dp, DefaultVisual( dp, sc ),
248       8, ZPixmap, NULL, &shminfo[1], vwidth, vheight );
249     RWIDTH = ximage[0]->bytes_per_line;
250     RHEIGHT = ximage[0]->height;
251     shminfo[0].shmid = shmget( IPC_PRIVATE,
252       ximage[0]->bytes_per_line * ximage[0]->height, IPC_CREAT | 0777 );
253     shminfo[0].shmaddr = ximage[0]->data = image[0]
254 	               = (char *)shmat( shminfo[0].shmid, 0, 0 );
255     shminfo[0].readOnly = True;
256     if( !XShmAttach( dp, &shminfo[0] ) )
257 	p_err("MIT-SHM error\n");
258     shminfo[1].shmid = shmget( IPC_PRIVATE,
259       ximage[1]->bytes_per_line * ximage[1]->height, IPC_CREAT | 0777 );
260     shminfo[1].shmaddr = ximage[1]->data = image[1]
261 	               = (char *)shmat( shminfo[1].shmid, 0, 0 );
262     shminfo[1].readOnly = True;
263     if( !XShmAttach( dp, &shminfo[1] ) )
264 	p_err("MIT-SHM error\n");
265     }else
266 #endif
267     {
268     image[0] = (char *)malloc(vwidth * vheight);
269     image[1] = (char *)malloc(vwidth * vheight);
270     ximage[0] = XCreateImage( dp, DefaultVisual( dp, sc ),
271       8, ZPixmap, 0, image[0], vwidth, vheight, 8, 0 );
272     ximage[1] = XCreateImage( dp, DefaultVisual( dp, sc ),
273       8, ZPixmap, 0, image[1], vwidth, vheight, 8, 0 );
274     RWIDTH = ximage[0]->bytes_per_line;
275     RHEIGHT = ximage[0]->height;
276     }
277     dbl_buf = 0;
278     XSync(dp, True);
279 
280     view_x = (225-vwidth)/2;
281     view_y = (225-vheight)/2;
282     ballGC[0][0] = XCreateGC( dp, root, 0, NULL );
283     ballGC[1][0] = XCreateGC( dp, root, 0, NULL );
284     ballGC[0][1] = XCreateGC( dp, root, 0, NULL );
285     ballGC[1][1] = XCreateGC( dp, root, 0, NULL );
286     xpatt.valuemask = XpmColormap;
287     xpatt.colormap = cmap;
288     XpmCreatePixmapFromData(
289 	dp, root, ball_xpm, &p_ball[0], &mask[0], &xpatt );
290     xpatt.valuemask = XpmColormap;
291     xpatt.colormap = cmap;
292     XpmCreatePixmapFromData(
293 	dp, root, ball2_xpm, &p_ball[1], &mask[1], &xpatt );
294     XSetFillStyle( dp, ballGC[0][0], FillTiled );
295     XSetClipMask( dp, ballGC[0][0], mask[0] );
296     XSetFillStyle( dp, ballGC[1][0], FillTiled );
297     XSetClipMask( dp, ballGC[1][0], mask[1] );
298     XSetFillStyle( dp, ballGC[0][1], FillTiled );
299     XSetClipMask( dp, ballGC[0][1], mask[0] );
300     XSetFillStyle( dp, ballGC[1][1], FillTiled );
301     XSetClipMask( dp, ballGC[1][1], mask[1] );
302     ball_w = xpatt.width;
303     ball_h = xpatt.height;
304     ball_x_bg = (200-xpatt.width)/2;
305     ball_y_bg = (200-xpatt.height)/2;
306     XSetClipOrigin( dp, ballGC[0][0], ball_x_bg, ball_y_bg );
307     XSetTSOrigin( dp, ballGC[0][0], ball_x_bg, ball_y_bg );
308     XSetTile( dp, ballGC[0][0], p_ball[0] );
309     XSetClipOrigin( dp, ballGC[0][1], ball_x_bg, ball_y_bg );
310     XSetTSOrigin( dp, ballGC[0][1], ball_x_bg, ball_y_bg );
311     XSetTile( dp, ballGC[0][1], p_ball[1] );
312     ball_x = (vwidth-xpatt.width)/2 + view_x;
313     ball_y = (vheight-xpatt.height)/2 + view_y;
314     XSetClipOrigin( dp, ballGC[1][0], ball_x, ball_y );
315     XSetTSOrigin( dp, ballGC[1][0], ball_x, ball_y );
316     XSetTile( dp, ballGC[1][0], p_ball[0] );
317     XSetClipOrigin( dp, ballGC[1][1], ball_x, ball_y );
318     XSetTSOrigin( dp, ballGC[1][1], ball_x, ball_y );
319     XSetTile( dp, ballGC[1][1], p_ball[1] );
320 
321     p_wall_data[0] = wall1_xpm;
322     p_wall_data[1] = wall2_xpm;
323     p_wall_data[2] = wall3_xpm;
324     p_wall_data[3] = wall4_xpm;
325     p_wall_data[4] = wall5_xpm;
326     p_wall_data[5] = wall6_xpm;
327     p_wall_data[6] = wall7_xpm;
328     p_wall_data[7] = wall8_xpm;
329     p_wall_data[8] = wall9_xpm;
330     p_wall_data[9] = wall10_xpm;
331     p_wall_data[10] = down_xpm;
332     p_wall_data[11] = left_xpm;
333     p_wall_data[12] = right_xpm;
334     p_wall_data[13] = up_xpm;
335     p_wall_data[14] = down1_xpm;
336     p_wall_data[15] = left1_xpm;
337     p_wall_data[16] = right1_xpm;
338     p_wall_data[17] = up1_xpm;
339     p_wall_data[18] = left2_xpm;
340     p_wall_data[19] = right2_xpm;
341     p_wall_data[20] = pin_xpm;
342     read_pixmap();
343     bg_data[0] = bg1_xpm;
344     bg_data[1] = bg2_xpm;
345     bg_data[2] = bg3_xpm;
346     bg_data[3] = bg4_xpm;
347 
348     XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 );
349     tipix[0] = pixel[0];
350     XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 );
351     tipix[3] = pixel[0];
352     XSetForeground( dp, keysGC, tipix[3] );
353     if( XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 ) ){
354 	gpixel = pixel[0];
355 	g_pixel = (char) gpixel;
356 	goalGC = XCreateGC( dp, root, 0, NULL );
357 	XSetForeground( dp, goalGC, gpixel );
358 	colors.pixel = gpixel;
359 	colors.flags = DoRed | DoGreen | DoBlue;
360 	colors.green = 0;
361 	colors.blue = 0;
362 	colors.red = 0;
363 	XStoreColor( dp, cmap, &colors );
364     }else
365 	if( owncmap == 0 )
366 	    goalGC = XCreateGC( dp, root, 0, NULL );
367 	else
368 	    p_err("Color Allocation Error");
369 
370 /* course parameter set */
371     cs_d[0] = c1;
372     cs_d[1] = c2;
373     cs_d[2] = c3;
374     cs_d[3] = c4;
375     cs_d[4] = c5;
376     cs_d[5] = c6;
377 /*    cs_d[6] = c7; */
378 
379     lx[0] = c1_x;
380     ly[0] = c1_y;
381     sdeg[0] = c1_deg;
382     gx[0] = g1x;
383     gy[0] = g1y;
384     gw[0] = g1w;
385     gh[0] = g1h;
386     lx[1] = c2_x;
387     ly[1] = c2_y;
388     sdeg[1] = c2_deg;
389     gx[1] = g2x;
390     gy[1] = g2y;
391     gw[1] = g2w;
392     gh[1] = g2h;
393     lx[2] = c3_x;
394     ly[2] = c3_y;
395     sdeg[2] = c3_deg;
396     gx[2] = g3x;
397     gy[2] = g3y;
398     gw[2] = g3w;
399     gh[2] = g3h;
400     lx[3] = c4_x;
401     ly[3] = c4_y;
402     sdeg[3] = c4_deg;
403     gx[3] = g4x;
404     gy[3] = g4y;
405     gw[3] = g4w;
406     gh[3] = g4h;
407     lx[4] = c5_x;
408     ly[4] = c5_y;
409     sdeg[4] = c5_deg;
410     gx[4] = g5x;
411     gy[4] = g5y;
412     gw[4] = g5w;
413     gh[4] = g5h;
414     gx[5] = g6x;
415     gy[5] = g6y;
416     gw[5] = g6w;
417     gh[5] = g6h;
418     lx[6] = c7_x;
419     ly[6] = c7_y;
420     sdeg[6] = c7_deg;
421     XAutoRepeatOff( dp );
422     cs_num = 0;
423 }
424 
read_pixmap()425 read_pixmap()
426 {
427     int i;
428 
429     xpatt.valuemask = XpmColormap;
430     xpatt.colormap = cmap;
431     for( i = 0; i < 21; i++ ){
432 	XpmCreatePixmapFromData( dp, root,
433 				 p_wall_data[i], &p_wall[i], NULL, &xpatt );
434 	wall_width[i] = xpatt.width;
435 	wall_height[i] = xpatt.height;
436     }
437     XpmCreatePixmapFromData( dp, root, frame_xpm, &p_frame, NULL, &xpatt );
438     XpmCreatePixmapFromData( dp, root, titlem_xpm, &p_titlem, NULL, &xpatt );
439     XpmCreatePixmapFromData( dp, root, ball3_xpm, &point_ball, NULL, &xpatt );
440 
441     XpmCreatePixmapFromData( dp, root, one_xpm, &num[0], NULL, &xpatt );
442     XpmCreatePixmapFromData( dp, root, two_xpm, &num[1], NULL, &xpatt );
443     XpmCreatePixmapFromData( dp, root, three_xpm, &num[2], NULL, &xpatt );
444     XpmCreatePixmapFromData( dp, root, go_xpm, &num[3], NULL, &xpatt );
445     XpmCreatePixmapFromData( dp, root, goal_xpm, &num[4], NULL, &xpatt );
446 }
447 
change_cmap()448 void change_cmap()
449 {
450     int i;
451     unsigned long bpixel, wpixel;
452     unsigned long plane_mask, pixel[1];
453     XColor set_pixel, rgb;
454 
455     /* free pixmap */
456     free_pix( p_ball[0] );
457     free_pix( p_ball[1] );
458     free_pix( mask[0] );
459     free_pix( mask[1] );
460     for( i = 0; i < 20; i++ )
461 	free_pix( p_wall[i] );
462     free_pix( p_frame );
463     free_pix( p_titlem );
464     free_pix( point_ball );
465     for( i = 0; i < 5; i++ )
466 	free_pix( num[i] );
467 
468     owncmap = 1;
469     create_cmap( &bpixel, &wpixel );
470 
471     XSetForeground( dp, textGC, wpixel );
472     XSetForeground( dp, text_csGC[0], wpixel );
473     XSetForeground( dp, text_csGC[1], cs_pixel );
474     XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 );
475     tipix[0] = pixel[0];
476     XAllocNamedColor( dp, cmap, TCOL2, &set_pixel, &rgb );
477     tipix[1] = set_pixel.pixel;
478     XAllocNamedColor( dp, cmap, TCOL3, &set_pixel, &rgb );
479     tipix[2] = set_pixel.pixel;
480     XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 );
481     tipix[3] = pixel[0];
482     XSetForeground( dp, keysGC, tipix[3] );
483 
484     XSetForeground( dp, blackGC, bpixel );
485     black_pixel = bpixel;
486     XSetWindowBackground( dp, win, bpixel );
487 
488     /* ball */
489     xpatt.valuemask = XpmColormap;
490     xpatt.colormap = cmap;
491     XpmCreatePixmapFromData(
492 	dp, root, ball_xpm, &p_ball[0], &mask[0], &xpatt );
493     XpmCreatePixmapFromData(
494 	dp, root, ball2_xpm, &p_ball[1], &mask[1], &xpatt );
495     XSetClipMask( dp, ballGC[0][0], mask[0] );
496     XSetClipMask( dp, ballGC[0][1], mask[1] );
497     XSetTile( dp, ballGC[0][0], p_ball[0] );
498     XSetTile( dp, ballGC[0][1], p_ball[1] );
499     XSetClipMask( dp, ballGC[1][0], mask[0] );
500     XSetClipMask( dp, ballGC[1][1], mask[1] );
501     XSetTile( dp, ballGC[1][0], p_ball[0] );
502     XSetTile( dp, ballGC[1][1], p_ball[1] );
503 
504     /* misc */
505     read_pixmap();
506 
507     XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 );
508     tipix[0] = pixel[0];
509     XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 );
510     tipix[3] = pixel[0];
511     XSetForeground( dp, keysGC, tipix[3] );
512     XAllocColorCells( dp, cmap, False, &plane_mask, 0, pixel, 1 );
513     gpixel = pixel[0];
514     g_pixel = (char) gpixel;
515     XSetForeground( dp, goalGC, gpixel );
516     colors.pixel = gpixel;
517     colors.flags = DoRed | DoGreen | DoBlue;
518     colors.green = 0;
519     colors.blue = 0;
520     colors.red = 0;
521     XStoreColor( dp, cmap, &colors );
522 }
523 
set_fade()524 set_fade()
525 {
526     GC fgc,bgc;
527     int i,j;
528     struct {
529 	int x;
530 	int y;
531     } maskd[25] = {
532 	{0,0},{2,2},{0,2},{2,0},{1,1},{3,3},{1,3},{3,1},
533 	{0,4},{2,4},{4,2},{4,0},{4,4},{0,1},{2,3},{3,0},
534 	{1,2},{4,3},{2,1},{1,4},{3,2},{1,0},{3,4},{4,1},{0,3}
535     };
536 
537     for( i = 0; i < 25; i++ )
538 	fade[i] = XCreatePixmap( dp, root, 5, 5, 1 );
539     fgc = XCreateGC( dp, fade[0], 0, NULL );
540     bgc = XCreateGC( dp, fade[0], 0, NULL );
541     XSetForeground( dp, fgc, 1 );
542     XSetForeground( dp, bgc, 0 );
543     for( i = 0; i < 25; i++ ){
544 	XFillRectangle( dp, fade[i], bgc, 0, 0, 5, 5 );
545 	for( j = 0; j <= i; j++ )
546 	    XDrawPoint( dp, fade[i], fgc, maskd[j].x, maskd[j].y );
547     }
548     fadeGC = XCreateGC( dp, root, 0, NULL );
549     XSetFillStyle( dp, fadeGC, FillStippled );
550     XFreeGC( dp, fgc );
551     XFreeGC( dp, bgc );
552 }
553 
free_pix(fpix)554 free_pix( fpix )
555 Pixmap fpix;
556 {
557     if( fpix )
558 	XFreePixmap( dp, fpix );
559 }
560 
create_cmap(bpixel,wpixel)561 create_cmap( bpixel, wpixel )
562 unsigned long *bpixel, *wpixel;
563 {
564     Colormap new_cmap;
565     XColor set_pixel, rgb;
566     XVisualInfo v_info;
567 
568     if( XMatchVisualInfo( dp, sc, 8, PseudoColor, &v_info ) == 0 )
569 	p_err("This X server doesn't support PseudoColor (256 colors)");
570     new_cmap = XCreateColormap( dp, root, v_info.visual, AllocNone );
571     XInstallColormap( dp, new_cmap );
572     XSetWindowColormap( dp, win, new_cmap );
573     XAllocNamedColor( dp, new_cmap, "black", &set_pixel, &rgb );
574     *bpixel = set_pixel.pixel;
575     XAllocNamedColor( dp, new_cmap, "white", &set_pixel, &rgb );
576     *wpixel = set_pixel.pixel;
577     XAllocNamedColor( dp, new_cmap, "yellow", &set_pixel, &rgb );
578     b3pixel = set_pixel.pixel;
579     XAllocNamedColor( dp, new_cmap, "red", &set_pixel, &rgb );
580     otpixel = set_pixel.pixel;
581     XAllocNamedColor( dp, new_cmap, "orange", &set_pixel, &rgb );
582     cs_pixel = set_pixel.pixel;
583     white_pixel = *wpixel;
584     black_pixel = *bpixel;
585 
586     cmap = new_cmap;
587 }
588 
589 /*
590     goal
591 */
592 
clear_screen()593 void clear_screen()
594 {
595     int i;
596 
597     XSetForeground( dp, fadeGC, black_pixel );
598     for( i = 0; i < 25; i++ ){
599 	XSetStipple( dp, fadeGC, fade[i] );
600 	XFillRectangle( dp, win, fadeGC, 0, 0, WWIDTH, WHEIGHT );
601 	XFlush( dp );
602 	u_sleep(20000);
603     }
604     XSync( dp, True );
605     u_sleep(300000);
606 }
607 
draw_result(high,res_time)608 void draw_result( high, res_time )
609 int high;
610 int res_time;
611 {
612     XCharStruct overall;
613     int dir;
614     int ascent_i;
615     int descent;
616     int s_width;
617     int i;
618     int x, rec_x[3], min_x;
619     char form[20];
620 
621     char buf[20], n_buf[3][20+NAME_MAX], buf_t[10];
622 
623     XClearWindow( dp, win );
624     sprintf(buf, "COURSE  %d", select_course);
625     XTextExtents( fn, buf, strlen(buf), &dir, &ascent_i, &descent, &overall );
626     s_width = overall.rbearing - overall.lbearing;
627     x = (WWIDTH - s_width) / 2 - overall.lbearing;
628     XDrawString( dp, win, textGC, x, 30+ascent, buf, strlen(buf) );
629 
630     for( i = 0; i < 3; i++ ){
631 	conv_time( record[select_course-1][i], buf_t );
632 	sprintf(form, "%%d    %%s  %%-%ds", NAME_MAX );
633 	sprintf(n_buf[i], form, i+1, buf_t, name[select_course-1][i] );
634 	XTextExtents( fn, n_buf[i], strlen(n_buf[i]),
635 		                 &dir, &ascent_i, &descent, &overall );
636 	s_width = overall.rbearing - overall.lbearing;
637 	rec_x[i] = (WWIDTH - s_width) / 2 - overall.lbearing;
638     }
639     min_x = rec_x[0];
640     if( rec_x[1] < min_x )
641 	min_x = rec_x[1];
642     if( rec_x[2] < min_x )
643 	min_x = rec_x[2];
644     for( i = 0; i < 3; i++ )
645 	XDrawString( dp, win, textGC, min_x,
646 		         65+ascent+i*30, n_buf[i], strlen(n_buf[i]) );
647 
648     if( high > 0 )
649 	XCopyArea( dp, point_ball, win, copyGC, 0, 0, 14, 14,
650 		               min_x-20+(overall.lbearing), 68+(high-1)*30 );
651     conv_time( res_time, buf_t );
652     sprintf(buf, "Results :  %s",buf_t);
653     XTextExtents( fn, buf, strlen(buf), &dir, &ascent_i, &descent, &overall );
654     s_width = overall.rbearing - overall.lbearing;
655     x = (WWIDTH - s_width) / 2 - overall.lbearing;
656     if( high > 0 ){
657 	XSetForeground( dp, textGC, b3pixel );
658 	XDrawString( dp, win, textGC, x, 180, buf, strlen(buf) );
659 	XSetForeground( dp, textGC, white_pixel );
660     }else if( over_time > (res_time/6) ){
661 	XSetForeground( dp, textGC, otpixel );
662 	XDrawString( dp, win, textGC, x, 180, buf, strlen(buf) );
663 	XSetForeground( dp, textGC, white_pixel );
664     }else
665 	XDrawString( dp, win, textGC, x, 180, buf, strlen(buf) );
666 
667     XFlush( dp );
668 }
669 
conv_time(tm,buf)670 void conv_time( tm, buf )
671 int tm;
672 char *buf;
673 {
674     int min, sec, msec;
675 
676     msec = tm % 100;
677     sec = tm / 100;
678     min = sec / 60;
679     sec = sec % 60;
680 
681     sprintf(buf, "%01d\'%02d\"%02d", min, sec, msec);
682 }
683 
684 /*
685     course select
686 */
687 
course_select()688 int course_select()
689 {
690     int sc;
691 
692     set_cs_state();
693     draw_cst();
694     sc = cs_ev();
695     cs_num = sc - 1;
696     set_cs_state();
697     draw_cst_sub();
698 
699     if( sc != 1 )
700 	XFillRectangle( dp, win, blackGC, cs_x, 45, cs_width, 23 );
701     if( sc != 2 )
702 	XFillRectangle( dp, win, blackGC, cs_x, 70, cs_width, 23 );
703     if( sc != 3 )
704 	XFillRectangle( dp, win, blackGC, cs_x, 95, cs_width, 23 );
705     if( sc != 4 )
706 	XFillRectangle( dp, win, blackGC, cs_x, 120, cs_width, 23 );
707     if( sc != 5 )
708 	XFillRectangle( dp, win, blackGC, cs_x, 145, cs_width, 23 );
709     if( sc != 6 )
710 	XFillRectangle( dp, win, blackGC, cs_x, 170, cs_width, 23 );
711     if( sc != 7 )
712 	XFillRectangle( dp, win, blackGC, cs_x, 195, cs_width, 23 );
713     XFlush(dp);
714 
715     return sc;
716 }
717 
cs_ev()718 int cs_ev()
719 {
720     int a;
721     while(1){
722 	XNextEvent( dp, &ev );
723 	if( ev.type == Expose )
724             draw_cst();
725         if( ev.type == KeyPress )
726             if( (a = keycheck3(ev)) )
727                 return a;
728     }
729 }
730 
keycheck3(ev)731 keycheck3(ev)
732 XKeyEvent ev;
733 {
734     char ch;
735     KeySym ksym;
736 
737     XLookupString( &ev, &ch, 1, &ksym, NULL );
738     switch(ksym){
739     case XK_Up:
740 	cs_num--;
741 	cs_num = (cs_num + COURSE) % COURSE;
742 	set_cs_state();
743 	draw_cst_sub();
744 	return 0;
745     case XK_Down:
746 	cs_num++;
747 	cs_num %= COURSE;
748 	set_cs_state();
749 	draw_cst_sub();
750 	return 0;
751     case XK_space:
752 	return (cs_num+1);
753     case XK_1:
754 	return 1;
755     case XK_2:
756 	return 2;
757     case XK_3:
758 	return 3;
759     case XK_4:
760 	return 4;
761     case XK_5:
762 	return 5;
763     case XK_6:
764 	return 6;
765     case XK_7:
766 	return 7;
767     case XK_q:
768 	end_prog();
769     }
770     return 0;
771 }
772 
set_cs_state()773 set_cs_state()
774 {
775     int i;
776 
777     for( i = 0; i < COURSE; i++ )
778 	cs_state[i] = 0;
779     cs_state[cs_num] = 1;
780 }
781 
draw_cst()782 draw_cst()
783 {
784     XCharStruct overall;
785     int dir;
786     int ascent_i;
787     int descent;
788     int s_width;
789     int x;
790 
791     char buf[20];
792 
793     XClearWindow( dp, win );
794     sprintf(buf, "COURSE SELECT");
795     XTextExtents( fn_cs, buf, strlen(buf),
796 		         &dir, &ascent_i, &descent, &overall );
797     s_width = overall.rbearing - overall.lbearing;
798     x = (WWIDTH - s_width) / 2 - overall.lbearing;
799     XDrawString( dp, win, text_csGC[0], x, 15+ascent_cs, buf, strlen(buf) );
800 
801     sprintf(buf, "5.    Professional");
802     XTextExtents( fn_cs, buf, strlen(buf),
803 		         &dir, &ascent_i, &descent, &overall );
804     s_width = overall.rbearing - overall.lbearing;
805     cs_text_x = (WWIDTH - s_width) / 2 - overall.lbearing;
806     cs_width = s_width;
807     cs_x = cs_text_x + overall.lbearing;
808 
809     draw_cst_sub();
810 }
811 
draw_cst_sub()812 draw_cst_sub()
813 {
814     char buf[20];
815 
816     XFillRectangle( dp, win, blackGC, cs_x, 45, cs_width, 175 );
817     sprintf(buf, "1.    Novice");
818     XDrawString( dp, win, text_csGC[cs_state[0]],
819 		                 cs_text_x, 45+ascent_cs, buf, strlen(buf) );
820     sprintf(buf, "2.    Average");
821     XDrawString( dp, win, text_csGC[cs_state[1]],
822 		                 cs_text_x, 70+ascent_cs, buf, strlen(buf) );
823     sprintf(buf, "3.    Master");
824     XDrawString( dp, win, text_csGC[cs_state[2]],
825 		                 cs_text_x, 95+ascent_cs, buf, strlen(buf) );
826     sprintf(buf, "4.    Expert");
827     XDrawString( dp, win, text_csGC[cs_state[3]],
828 		                 cs_text_x, 120+ascent_cs, buf, strlen(buf) );
829     sprintf(buf, "5.    Professional");
830     XDrawString( dp, win, text_csGC[cs_state[4]],
831 		                 cs_text_x, 145+ascent_cs, buf, strlen(buf) );
832     sprintf(buf, "6.    Special  1");
833     XDrawString( dp, win, text_csGC[cs_state[5]],
834 		                 cs_text_x, 170+ascent_cs, buf, strlen(buf) );
835     sprintf(buf, "7.    Special  2");
836     XDrawString( dp, win, text_csGC[cs_state[6]],
837 		                 cs_text_x, 195+ascent_cs, buf, strlen(buf) );
838     XFlush( dp );
839 }
840 
841 
create_course()842 void create_course()
843 {
844     int x, y, pix;
845     struct course_d *cd;
846 
847 
848     p_course = XCreatePixmap( dp, root, MWIDTH, MHEIGHT,
849 			                        DefaultDepth( dp, sc ) );
850     XFillRectangle( dp, p_course, clearGC, 0, 0, MWIDTH, MHEIGHT );
851     init_course();
852 
853     if( select_course != 7 ){
854 	cd = cs_d[select_course-1];
855 	while(1){
856 	    x = cd->x;
857 	    y = cd->y;
858 	    pix = (cd++)->pix;
859 	    if( pix == '@' )
860 		break;
861 	    if( pix == 20 )
862 		XCopyArea( dp, p_wall[20], p_course, copyGC, 0, 0,
863 			   wall_width[20], wall_height[20], x * 5, y * 5 );
864 	    else
865 		XCopyArea( dp, p_wall[pix], p_course, copyGC, 0, 0,
866 			   wall_width[pix], wall_height[pix], x * 25, y * 25 );
867 	}
868     }else
869 	c7_make();
870 
871     bimage = XGetImage( dp, p_course, 0, 0,
872 			              MWIDTH, MHEIGHT, AllPlanes, ZPixmap );
873     bw = MWIDTH; bh = MHEIGHT;
874     bdata = bimage->data;
875 }
876 
init_course()877 init_course()
878 {
879     int a;
880 
881     a = select_course-1;
882     if( select_course != 7 )
883 	XFillRectangle( dp, p_course, goalGC, gx[a], gy[a], gw[a], gh[a] );
884     else{
885 	XFillRectangle( dp, p_course, goalGC, g7x[0], g7y[0], g7w[0], g7h[0] );
886 	XFillRectangle( dp, p_course, goalGC, g7x[1], g7y[1], g7w[1], g7h[1] );
887     }
888 }
889 
890 /* course 7 */
c7_make()891 c7_make()
892 {
893     int w[29][29], w2[29][29], *p;
894     int dx[] = {0,1,0,-1}, dy[] = {-1,0,1,0};
895     int x, y;
896     int a, i;
897 
898     for( x = 0; x < 29; x++ )
899 	for( y = 0; y < 29; y++ )
900 	    w[x][y] = 0;
901     for( x = 2; x < 28; x += 2 )
902 	for( y = 2; y < 28; y += 2 ){
903 	  l1:
904 	    if( x == 2 )
905 		a = (rand() & 0x30) >> 4;
906 	    else
907 		a = rand() % 3;
908 	    p = &w[x+dx[a]][y+dy[a]];
909 	    if( *p ){
910                 if( (rand() & 0xff) > 0x80 )
911 		    goto l1;
912 	    } else
913 		*p = 1;
914 	}
915     a = rand() & 0x3;
916     switch( a ){
917     case 0:
918 	for( x = 0; x < 29; x++ )
919 	    for( y = 0; y < 29; y++ )
920 		w2[x][y] = w[x][y];
921 	break;
922     case 1:
923 	for( x = 0; x < 29; x++ )
924 	    for( y = 0; y < 29; y++ )
925 		w2[28-y][x] = w[x][y];
926 	break;
927     case 2:
928 	for( x = 0; x < 29; x++ )
929 	    for( y = 0; y < 29; y++ )
930 		w2[28-x][28-y] = w[x][y];
931 	break;
932     case 3:
933 	for( x = 0; x < 29; x++ )
934 	    for( y = 0; y < 29; y++ )
935 		w2[y][28-x] = w[x][y];
936     }
937     for( x = 0; x < 29; x++ )
938 	for( y = 0; y < 29; y++ )
939 	    if( w2[x][y] )
940 		if( y & 1 )
941 		    draw_c7(x,y,1);
942 		else
943 		    draw_c7(x,y,0);
944 
945     for( i = 0; i < 950; i += 50 ){
946 	XCopyArea( dp, p_wall[2], p_course, copyGC, 0, 0,
947 		                  wall_width[2], wall_height[2], i, 995 );
948 	XCopyArea( dp, p_wall[3], p_course, copyGC, 0, 0,
949 		                  wall_width[3], wall_height[3], 0, i );
950     }
951     XCopyArea( dp, p_wall[2], p_course, copyGC, 0, 0,
952 		              wall_width[2]-5, wall_height[2], 950, 995 );
953     XCopyArea( dp, p_wall[3], p_course, copyGC, 0, 0,
954 		              wall_width[3], wall_height[3]-5, 0, 950 );
955     for( i = 970; i > 25; i -= 50 ){
956 	XCopyArea( dp, p_wall[2], p_course, copyGC, 0, 0,
957 		                  wall_width[2], wall_height[2], i, 0 );
958 	XCopyArea( dp, p_wall[3], p_course, copyGC, 0, 0,
959 		                  wall_width[3], wall_height[3], 995, i );
960     }
961     XCopyArea( dp, p_wall[2], p_course, copyGC, 5, 0,
962 	                      wall_width[2]-5, wall_height[2], 25, 0 );
963     XCopyArea( dp, p_wall[3], p_course, copyGC, 0, 5,
964 		              wall_width[3], wall_height[3]-5, 995, 25 );
965 
966 }
967 
draw_c7(x,y,ty)968 draw_c7( x, y, ty )
969 int x, y, ty;
970 {
971     int i;
972 
973     if( ty )
974 	for( i = 0; i < 8; i++ )
975 	    XCopyArea( dp, p_wall[20], p_course, copyGC,
976 		                 0, 0, 10, 10, x*35+15, (y-1)*35+i*10+15);
977     else
978 	for( i = 0; i < 8; i++ )
979 	    XCopyArea( dp, p_wall[20], p_course, copyGC,
980 		                 0, 0, 10, 10, (x-1)*35+i*10+15, y*35+15);
981 }
982 
set_background(scn)983 void set_background(scn)
984 int scn;
985 {
986     int bx, by;
987     int y;
988     int p_status;
989     int wid;
990 
991   retry:
992     xpatt.valuemask = XpmReturnPixels | XpmColormap;
993     xpatt.colormap = cmap;
994     if( (p_status = XpmCreatePixmapFromData(
995 	dp, win, bg_data[scn], &back_pix, NULL, &xpatt )) != XpmSuccess ){
996 	if( owncmap == 0 ){
997 	    change_cmap();
998 	    goto retry;
999 	}
1000 	p_err(XpmGetErrorString(p_status));
1001     }
1002     bg_col = xpatt.pixels;
1003     bg_num = xpatt.npixels;
1004     XFillRectangle(dp, back_pix,
1005 		   ballGC[0][ball_type], ball_x_bg, ball_y_bg, ball_w, ball_h);
1006     back_image = XGetImage( dp, back_pix, 0, 0, 200, 200, AllPlanes, ZPixmap );
1007     wid = RWIDTH;
1008     if( wid > 200 )
1009 	wid = 200;
1010     back_data = (char *)malloc(wid * vheight);
1011     bx = (200-wid)/2;
1012     by = (200-vheight)/2;
1013     for( y = 0; y < vheight; y++ )
1014 	memcpy( back_data+y*wid, (back_image->data)+bx+(by+y)*200, wid );
1015 }
1016 
free_xres()1017 void free_xres()
1018 {
1019     XFreePixmap( dp, p_course );
1020     XDestroyImage( bimage );
1021 
1022     XFreeColors( dp, cmap, bg_col, bg_num, 0 );
1023     XDestroyImage( back_image );
1024     XFreePixmap( dp, back_pix );
1025     free( back_data );
1026     XFlush(dp);
1027 }
1028 
draw_win()1029 void draw_win()
1030 {
1031     XClearWindow( dp, win );
1032     XCopyArea( dp, p_frame, win, copyGC, 0, 0, 225, 225, 0, 0 );
1033     XCopyArea( dp, p_titlem, win, copyGC, 0, 0, 70, 35,
1034 	       (WWIDTH-225-75)/2+225, 10 );
1035 }
1036 
draw_mesg()1037 void draw_mesg()
1038 {
1039     XFillRectangle( dp, win, blackGC, (WWIDTH-225-70)/2+225, 150, 70, 60 );
1040     if( num_state < 3 )
1041 	XCopyArea( dp, num[num_state], win, copyGC, 0, 0, 60, 60,
1042 		   (WWIDTH-225-60)/2+225, 150 );
1043     else if( num_state < 5 )
1044 	XCopyArea( dp, num[num_state], win, copyGC, 0, 0, 70, 60,
1045 		   (WWIDTH-225-70)/2+225, 150 );
1046 
1047     XFlush(dp);
1048 }
1049 
pre_ev()1050 int pre_ev()
1051 {
1052     while( XEventsQueued( dp, QueuedAfterReading ) ){
1053 	XNextEvent( dp, &ev );
1054 	switch( ev.type ){
1055 	case Expose:
1056 	    draw_win();
1057 	    screen();
1058 	    break;
1059 	case KeyPress:
1060 	case KeyRelease:
1061 	    key_check( ev );
1062 	    if( escape == 1 )
1063 		return 1;
1064 	    restart = 0;
1065 	}
1066     }
1067     return 0;
1068 }
1069 
pre_event()1070 void pre_event()
1071 {
1072     while( XCheckWindowEvent( dp, win, KeyPressMask, &ev ) )
1073 	;
1074 }
1075 
goal_event(h,t)1076 void goal_event( h, t )
1077 int h, t;
1078 {
1079     while(1){
1080 	XNextEvent( dp, &ev );
1081 	if( ev.type == Expose )
1082 	    draw_result( h, t );
1083 	if( ev.type == KeyPress )
1084 	    if( keycheck2(ev) )
1085 		return;
1086     }
1087 }
1088 
keycheck2(ev)1089 keycheck2(ev)
1090 XKeyEvent ev;
1091 {
1092     char ch;
1093     KeySym ksym;
1094 
1095     XLookupString( &ev, &ch, 1, &ksym, NULL );
1096     if( ksym == XK_space )
1097         return 1;
1098     if( ksym == XK_q ){
1099         end_prog();
1100     }
1101     return 0;
1102 }
1103 
check_ev()1104 void check_ev()
1105 {
1106     redc++;
1107     redc &= 0x3f;
1108     colors.red = grad[redc];
1109     XStoreColor( dp, cmap, &colors );
1110 
1111     while( XEventsQueued( dp, QueuedAfterReading ) ){
1112 	XNextEvent( dp, &ev );
1113 	switch( ev.type ){
1114 	case KeyPress:
1115 	case KeyRelease:
1116 	    key_check( ev );
1117 	    break;
1118 	case Expose:
1119 	    draw_win();
1120 	    draw_mesg();
1121 	}
1122     }
1123 }
1124 
key_check(ev)1125 key_check( ev )
1126 XKeyEvent ev;
1127 {
1128     register int set=0;
1129     KeySym ksym;
1130     char ch;
1131 
1132     if( ev.type == KeyPress )
1133 	set = 1;
1134 
1135     XLookupString( &ev, &ch, 1, &ksym, NULL );
1136     switch( ksym ){
1137     case XK_Left:
1138 	key_left = set;
1139 	break;
1140     case XK_Right:
1141 	key_right = set;
1142 	break;
1143     case XK_space:
1144 	key_space = set;
1145 	break;
1146     case XK_Up:
1147 	jump_key = set;
1148 	break;
1149     case XK_Down:
1150 	soft_key = set * 9;
1151 	break;
1152     case XK_Return:
1153 	if( ev.type == KeyPress )
1154 	    restart = 1;
1155 	break;
1156     case XK_Escape:
1157 	if( ev.type == KeyPress )
1158 	    escape = 1;
1159 	break;
1160     case XK_q:
1161 	end_prog();
1162     }
1163 }
1164 
end_prog()1165 void end_prog()
1166 {
1167     if( dp ){
1168 #ifdef MITSHM
1169 	if( shm ){
1170 	    if( shminfo[0].shmid > 0 )
1171 		XShmDetach( dp, &(shminfo[0]) );
1172 	    if( shminfo[1].shmid > 0 )
1173 		XShmDetach( dp, &(shminfo[1]) );
1174 	}
1175 #endif
1176 	XAutoRepeatOn( dp );
1177 	XCloseDisplay( dp );
1178     }
1179 #ifdef MITSHM
1180     if( shm ){
1181 	if( image[0] )
1182 	    shmdt( image[0] );
1183 	if( image[1] )
1184 	    shmdt( image[1] );
1185 	if( shminfo[0].shmid >= 0 )
1186 	    shmctl( shminfo[0].shmid, IPC_RMID, 0 );
1187 	if( shminfo[1].shmid >= 0 )
1188 	    shmctl( shminfo[1].shmid, IPC_RMID, 0 );
1189     }
1190 #endif
1191     exit(0);
1192 }
1193