1
2 #include "pointer.h"
3 #include "stipple.h"
4 #ifndef _xsound_h
5 # include "xsound.h"
6 #endif
7
8 #ifndef _game_h
9 # include "game.h"
10 #endif
11 #ifndef _rgb_h
12 # include "rgb.h"
13 #endif
14
15 #include <stdarg.h>
16
17 Display *dpy; // the display connection
18 int scr; // default screen of the display
19 Window win; // the output window
20 Window new_root=0; // a surrounding black window, when started with option -root (default)
21 Colormap cmap; // the colormap used for the window
22 Colormap local_cmap; // flag, if the colormap had to be created local
23
24 static int nbg_cols_all;
25 static int bg_unused;
26 static int nball_cols_to_alloc;
27
28 Pixmap pointer_pmap; // Pixmap (wird vom PBall benutzt)
29 int pointer_off_x, pointer_off_y;
30
31 static Pixmap stipple_pmap=0;
32
33 // The stipple cache is used to store the 'textured' pixmap to
34 // reuse some on several output-operation.
35 #define STIPPLE_CACHE 10
36 static const int stipple_sz=128;
37 static Pixmap rand_stipple[STIPPLE_CACHE];
38 static long rand_col[STIPPLE_CACHE];
39
40 static unsigned long start_seconds;
41
42 static int info_ch = 0;
43
44 #ifdef STATISTICS
45 static GC gc_text;
46 static int info_cw = 0;
47
48 static XFontStruct *fs = 0;
49 static Font info_font;
50 static unsigned long info_fg, info_bg;
51 static const int info_width = 16;
52 static int info_offset = 0;
53
showinfo(StatType stat,const char * info)54 void showinfo( StatType stat, const char *info ) {
55 static info_toggle=0;
56
57 if (new_root) {
58 int len = strlen(info);
59 if (stat==OffsetInfo) {
60 if (len) {
61 info_toggle^=1;
62 if (info_toggle) {
63 XSetForeground( dpy, gc_text, info_bg );
64 XSetBackground( dpy, gc_text, info_fg );
65 }
66 }
67 else {
68 info = " ";
69 len = 20;
70 }
71 }
72 XDrawImageString( dpy, new_root,
73 gc_text,
74 info_offset - (stat+1)*info_width*info_cw,
75 DisplayHeight(dpy,scr)- 1,
76 info, len);
77
78 if ((stat==OffsetInfo) && (info_toggle)) {
79 XSetForeground( dpy, gc_text, info_fg );
80 XSetBackground( dpy, gc_text, info_bg );
81 }
82 }
83 }
84
85 #define GRAPH_SIZE_X 50
86 #define GRAPH_SIZE_Y 800
graphinfo(int value)87 void graphinfo( int value ) {
88 static int row=-1;
89 if (row<0) {
90 for (row=0;row<=GRAPH_SIZE_Y;row+=20) {
91 for (int i=0;i<=100;i+=20) {
92 XDrawPoint(dpy,new_root,gc_text,row,DisplayHeight(dpy,scr)-1-i );
93 }
94 }
95 row=0;
96 }
97 if (value>120) value=120;
98
99 XSetForeground( dpy, gc_text, info_bg );
100 XDrawLine(dpy, new_root, gc_text,
101 row, DisplayHeight(dpy,scr)-1,
102 row, DisplayHeight(dpy,scr)-1-GRAPH_SIZE_X);
103 XSetForeground( dpy, gc_text, info_fg );
104 if (row%20==0) {
105 for (int i=0;i<=100;i+=20) {
106 XDrawPoint(dpy, new_root, gc_text, row, DisplayHeight(dpy,scr)-1-i );
107 }
108 }
109 XDrawLine(dpy, new_root, gc_text,
110 row, DisplayHeight(dpy,scr)-1-value+1,
111 row, DisplayHeight(dpy,scr)-1-value-1);
112 row++;
113 if (row>GRAPH_SIZE_Y) row=0;
114 XDrawLine(dpy, new_root, gc_text,
115 row, DisplayHeight(dpy,scr)-1,
116 row, DisplayHeight(dpy,scr)-11);
117 }
118 #endif
119
120
InitTime()121 static void InitTime() {
122 struct timeval start;
123
124 X_GETTIMEOFDAY( &start ); // comes with X11R6 (see stdinc.h)
125 start_seconds = start.tv_sec;
126 }
127
GetCurrentTime()128 double GetCurrentTime() {
129 struct timeval current;
130
131 X_GETTIMEOFDAY( ¤t ); // comes with X11R6 (see stdinc.h)
132 return( ((double)(current.tv_sec-start_seconds))+(current.tv_usec/1000000.0) );
133 }
134
135
136 GC gc_default;
137
138 GC gc_lay1;
139 GC gc_lay2;
140 GC gc_cursor;
141
142 GC gc_current;
143
144 GC gc_bxor;
145 GC gc_bclear;
146
147 GC gc_ballwhite;
148 GC gc_ball[MAX_BALL];
149
150
SetBgColor(ColorId col)151 void SetBgColor( ColorId col ) {
152 gc_current = gc_default;
153
154 //
155 // set the foreground pixel
156 //
157 if (col&BG_MASK) {
158 XSetForeground( dpy, gc_current, ball_pix[0]|bg_pix[col&COLOR_MASK] );
159 }
160 else if (col&STAT_MASK) {
161 XSetForeground( dpy, gc_current, stat_pix[col&COLOR_MASK] );
162 }
163 else {
164 XSetForeground( dpy, gc_current, ball_pix[col&COLOR_MASK] );
165 }
166
167 //
168 // set background (when in mixed mode)
169 //
170 if (col&MIX_MASK) {
171 //
172 // set background color
173 //
174 if ((col>>COLOR_BITS)&BG_MASK) {
175 XSetBackground( dpy, gc_current,
176 ball_pix[0]|bg_pix[(col>>COLOR_BITS)&COLOR_MASK] );
177 }
178 else if ((col>>COLOR_BITS)&STAT_MASK) {
179 XSetBackground(dpy,gc_current,stat_pix[(col>>COLOR_BITS)&COLOR_MASK]);
180 }
181 else {
182 XSetBackground(dpy,gc_current,ball_pix[(col>>COLOR_BITS)&COLOR_MASK]);
183 }
184
185 //
186 // set (or create) background stipple
187 //
188 if (col&RAND_MASK) {
189 int i;
190 for (i=0;i<STIPPLE_CACHE;i++) {
191 if (col==rand_col[i]) break;
192 if (rand_col[i]==0) break;
193 }
194 if (i==STIPPLE_CACHE) {
195 XFreePixmap(dpy,rand_col[0]); // drop first map
196 for (i=0;i<STIPPLE_CACHE-1;i++) { // shift other maps
197 rand_col[i] = rand_col[i+1];
198 rand_stipple[i] = rand_stipple[i+1];
199 }
200 rand_col[i] = 0; // mark last cache as unused
201 }
202
203 if (!rand_col[i]) {
204 // create a new map for the given color
205 rand_col[i] =col;
206 rand_stipple[i]=XCreatePixmap(dpy,win,stipple_sz,stipple_sz,1);
207
208 GC gc = XCreateGC( dpy, rand_stipple[i], 0, 0L );
209 XSetFunction(dpy,gc,GXset);
210 XFillRectangle(dpy,rand_stipple[i],gc,0,0,stipple_sz,stipple_sz);
211 XSetFunction(dpy,gc,GXclear);
212 for (int j=stipple_sz*stipple_sz/
213 ((int)((col&RAND_MASK)>>RAND_SHIFT)+1); j>0;j--) {
214 XDrawPoint(dpy,rand_stipple[i],gc,rand()%stipple_sz,rand()%stipple_sz);
215 }
216 XFreeGC(dpy,gc);
217 }
218 XSetStipple( dpy, gc_current, rand_stipple[i] );
219 }
220 else {
221 XSetStipple( dpy, gc_current, stipple_pmap );
222 }
223 XSetFillStyle( dpy, gc_current, FillOpaqueStippled );
224 }
225 else {
226 XSetFillStyle( dpy, gc_current, FillSolid );
227 }
228 }
229
ParseColor(const char * name,XColor * col)230 int ParseColor( const char *name, XColor *col ) {
231 RGBColor rgbcol;
232
233 if ( rgbcol.SetColor(name)==0 ) {
234 col->red = rgbcol.red | (rgbcol.red <<8);
235 col->green = rgbcol.green | (rgbcol.green<<8);
236 col->blue = rgbcol.blue | (rgbcol.blue <<8);
237 // printf("'%s': %04x/%04x/%04x\n",name,col->red,col->green,col->blue);
238 return 0;
239 }
240 if (XParseColor(dpy,cmap,name,col)) return 0;
241 else {
242 fprintf(stderr,"failed to query RGB-values for '%s'\n",name );
243 return -1;
244 }
245 }
246
StoreColor(unsigned pixel)247 int StoreColor( unsigned pixel ) {
248 long stat=-1;
249 unsigned long bgc;
250 int nbgc;
251 unsigned long shc;
252 int nshc;
253 unsigned long cuc;
254 unsigned long bc;
255 int nbc;
256
257 bgc = pixel&bg_mask; // Hintergrund
258 for (nbgc=(nbg_cols_all-1)-1;nbgc>=0;nbgc--) {// passenden Index suchen
259 if (bg_pix[nbgc]==bgc) break;
260 }
261 if ((bgc)&&nbgc>=nbg_cols) {
262 stat = nbgc-nbg_cols; // unbenutztes Pixel -> static
263 }
264
265 shc = pixel&shade_mask; // Schattierung
266 for (nshc=0;nshc<nshade_cols;nshc++) { // passenden Index suchen
267 if (shade_pix[nshc]==shc) break;
268 }
269 if ((shc)&&nshc>=nshade_cols) {
270 printf( "not implemented: shaded %d free for static\n", pixel );
271 return -1; // unbenutztes Pixel
272 }
273
274 cuc = pixel&cursor_mask; // Cursor
275
276 bc = pixel-bgc-shc-cuc; // Ballfarbe
277 for (nbc=0;nbc<nball_cols_to_alloc;nbc++) { // passenden Index suchen
278 if (ball_pix[nbc]==bc) break;
279 }
280 if (nbc>=nball_cols_to_alloc) return -1;
281
282 if (nbc>=nball_cols) {
283 stat = nball_cols*bg_unused + (nbc-nball_cols)*(nbg_cols_all)
284 + ((nbgc>=0)?nbgc+1:0);
285 }
286 else {
287 if (stat>=0) stat+=(nbc*bg_unused);
288 }
289
290 XColor col;
291
292 if (cuc&&(stat<nstat_cols)) {
293 ParseColor(cursor_col, &col );
294 }
295 else {
296 if (stat>=0) {
297 if (stat<nstat_cols) {
298 ParseColor(stat_col[stat], &col );
299 if (!shc) {
300 DBG2( ShowColors, "Static %2ld at pixel %3d\n", stat, pixel );
301 stat_pix[stat] = pixel;
302 }
303 }
304 else return -1;
305 }
306 else if (nbc) {
307 ParseColor(ball_col[nbc], &col ); // RGB-Werte lesen
308 }
309 else if (bgc) {
310 ParseColor(bg_col[nbgc], &col ); // RGB-Werte lesen
311 }
312 else ParseColor(ball_col[0], &col );
313
314 if (shc) {
315 XColor scol;
316 ParseColor(shade_col[nshc], &scol ); // RGB-Werte lesen
317
318 col.red = (col.red *m[nshc] + scol.red *d[nshc])/(m[nshc]+d[nshc]);
319 col.green = (col.green*m[nshc] + scol.green*d[nshc])/(m[nshc]+d[nshc]);
320 col.blue = (col.blue *m[nshc] + scol.blue *d[nshc])/(m[nshc]+d[nshc]);
321 }
322 }
323
324 col.pixel = pixel;
325 col.flags = DoRed|DoGreen|DoBlue;
326 XStoreColor( dpy,cmap,&col);
327 return 0;
328 }
329
StoreColors()330 void StoreColors() {
331 for (int i=0;i<256;i++) StoreColor(i);
332 }
333
GetBlackPixel()334 unsigned long GetBlackPixel() {
335 unsigned long erg=GetAllocatedPixel( "black" );
336
337 if (erg) return erg;
338 else return BlackPixel(dpy,scr);
339 }
340
AllocColors()341 void AllocColors() {
342 unsigned long plane_mask[8];
343 int nplanes = 0;
344 int n;
345
346 nball_cols_to_alloc = nball_cols;
347 //
348 // Ausrechnen, wieviele Planes ben�tigt werden
349 //
350 n = nbg_cols; // Planes f�r Hintergrund sammeln
351 while( n ) { nplanes++; n>>=1; }
352 nbg_cols_all = (1<<nplanes);
353 bg_unused = nbg_cols_all-1-nbg_cols;
354 n = nshade_cols;
355 while( n ) { nplanes++; n>>=1; }
356 if (cursor_col) nplanes++;
357
358 //
359 // Anfordern der Farben
360 //
361 DBG1( ShowColors, "Graphic: %d planes\n", nplanes );
362 DBG1( ShowColors, "Graphic: %d ball colors\n", nball_cols );
363 DBG1( ShowColors, "Graphic: %d static colors\n", nstat_cols );
364 while (nstat_cols>nball_cols*bg_unused
365 +(nball_cols_to_alloc-nball_cols)*(nbg_cols_all)) {
366 nball_cols_to_alloc++;
367 }
368 DBG1( ShowColors, "Graphic: %d statics 'between planes'\n", nball_cols*bg_unused );
369 DBG1( ShowColors, "Graphic: allocating %d ball colors\n", nball_cols_to_alloc );
370
371 cmap = DefaultColormap( dpy, scr );
372 if (XAllocColorCells( dpy, cmap, False,
373 plane_mask, nplanes, ball_pix, nball_cols_to_alloc )==0) {
374 DBG0( UnixTrace,
375 "Allocation of colors failed - creating local colormap.\n" );
376 cmap= XCreateColormap(dpy,win,DefaultVisual(dpy,scr),AllocNone);
377 if (XAllocColorCells( dpy, cmap, False,
378 plane_mask, nplanes, ball_pix, nball_cols_to_alloc )==0) {
379 fprintf(stderr, "not enough colors: " );
380 fprintf(stderr, "I need %d colors + %d planes.\n",
381 nball_cols_to_alloc, nplanes );
382 exit(0);
383 }
384 if (new_root) {
385 XSetWindowAttributes attrib;
386 attrib.colormap = cmap;
387 XChangeWindowAttributes( dpy, new_root, CWColormap, &attrib );
388 XSetWindowColormap( dpy, new_root, cmap );
389 }
390 else {
391 XSetWindowAttributes attrib;
392 attrib.colormap = cmap;
393 XChangeWindowAttributes( dpy, win, CWColormap, &attrib );
394 XSetWindowColormap( dpy, win, cmap );
395 }
396 XSync(dpy,0);
397 }
398
399 //
400 // Verteilen der Planes auf die Farben
401 //
402 int c=0;
403 for (n=0;n<nbg_cols+bg_unused;n++) {
404 bg_pix[n] = 0;
405 if ((n+1)&1) bg_pix[n]+=plane_mask[c+0];
406 if ((n+1)&2) bg_pix[n]+=plane_mask[c+1];
407 if ((n+1)&4) bg_pix[n]+=plane_mask[c+2];
408 }
409 n=nbg_cols;
410 bg_mask=0;
411 while(n) { bg_mask+=plane_mask[c++]; n>>=1; }
412
413 for (n=0;n<nshade_cols;n++) {
414 shade_pix[n] = 0;
415 if ((n+1)&1) shade_pix[n]+=plane_mask[c+0];
416 if ((n+1)&2) shade_pix[n]+=plane_mask[c+1];
417 if ((n+1)&4) shade_pix[n]+=plane_mask[c+2];
418 }
419 n=nshade_cols;
420 shade_mask=0;
421 while(n) { shade_mask+=plane_mask[c++]; n>>=1; }
422
423 if (cursor_col) {
424 cursor_mask = plane_mask[c];
425 }
426
427 ball_mask=0;
428 for (n=0;n<nball_cols_to_alloc;n++) {
429 ball_mask|=ball_pix[n];
430 }
431 //
432 // Farben eintragen
433 //
434 StoreColors(); // Farben in Tabelle eintragen
435 //
436 // GC's besetzen
437 //
438 unsigned long value_mask;
439 XGCValues values;
440
441 value_mask = GCPlaneMask | GCForeground | GCBackground | GCFunction
442 | GCArcMode | GCStipple | GCFillStyle | GCGraphicsExposures;
443 values.graphics_exposures = False;
444 values.foreground = 0xffff;
445 values.background = 0;
446 values.function = GXxor;
447 values.arc_mode = ArcChord; // statt ArcPieSlice
448 stipple_pmap =
449 values.stipple = XCreateBitmapFromData( dpy, RootWindow( dpy, scr ),
450 stipple_bits, stipple_width, stipple_height );
451 values.fill_style = FillSolid;
452 #ifdef STATISTICS
453 values.font= info_font;
454 if (values.font) value_mask|=GCFont;
455 #endif
456
457 values.plane_mask = bg_pix[0];
458 gc_lay1 = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
459 values.plane_mask = shade_pix[0];
460 gc_lay2 = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
461
462 values.plane_mask = cursor_mask;
463 gc_cursor = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
464
465 //
466 // Default Graphic-Context erzeugen
467 //
468 values.foreground = ball_pix[0];
469 values.plane_mask = ball_mask | shade_pix[0]; // Arbeiten in lay2
470 values.function = GXxor;
471 gc_bxor = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
472 values.function = GXclear;
473 gc_bclear = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
474
475 values.plane_mask = ball_mask|shade_mask|bg_mask|cursor_mask;
476 values.function = GXcopy;
477 gc_default = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
478
479 values.plane_mask = ball_mask;
480 gc_ball[0] = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
481 //
482 // Kontext f�r den Text
483 //
484 #ifdef STATISTICS
485 values.foreground = info_fg = ball_pix[0];
486 values.background = info_bg = GetBlackPixel();
487 values.plane_mask = AllPlanes;
488 gc_text = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
489
490 info_offset = (DisplayWidth(dpy,scr)+max_x)/2;
491 #endif
492 //
493 // GC's f�r die Ballfarben
494 //
495 unsigned long white_pix=0;
496
497 values.fill_style = FillSolid;
498 values.plane_mask = ball_mask;
499 values.function = GXxor;
500 values.background = 0;
501 if (deluxe) {
502 white_pix = GetAllocatedPixel( "ivory" );
503 if (!white_pix) {
504 fprintf( stderr, "white color 'ivory' missing for ball-underground\n");
505 exit(-1);
506 }
507 values.foreground = (white_pix^ball_pix[0]);
508 gc_ballwhite=XCreateGC(dpy,RootWindow(dpy,scr),value_mask,&values);
509 }
510
511
512 for (int i=0;i<nball_ids;i++) {
513 ColorId col = ball_ids[i];
514
515 if (deluxe) values.foreground = white_pix^ball_pix[col&COLOR_MASK];
516 else values.foreground = ball_pix[0]^ball_pix[col&COLOR_MASK];
517 if (col&MIX_MASK) {
518 values.foreground = ball_pix[0]^ball_pix[(col>>COLOR_BITS)&COLOR_MASK];
519 values.fill_style = FillOpaqueStippled;
520 }
521 else {
522 values.fill_style = FillSolid;
523 }
524
525 gc_ball[i]=XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
526 }
527 //
528 // Pixmaps erzeugen
529 //
530 pointer_pmap = XCreatePixmapFromBitmapData(dpy,win,
531 pointer_bits, pointer_width, pointer_height, cursor_mask, 0,
532 DefaultDepth(dpy,scr) );
533 pointer_off_x = pointer_x_hot;
534 pointer_off_y = pointer_y_hot;
535
536 #ifdef DEBUG
537 if (debug&Sync) {
538 XSynchronize(dpy,1);
539 }
540 if ((debug&ShowSubWindow)&&(!new_root)) {
541 XSizeHints hints;
542
543 hints.flags = PPosition | PSize | PAspect | PMinSize | PMaxSize;
544 hints.x = (DisplayWidth(dpy,scr) -max_x)/2;
545 hints.y = 0;
546 hints.width = hints.min_width = hints.max_width = max_x;
547 hints.height = hints.min_height = hints.max_height = max_y;
548 XSetWMNormalHints( dpy,win,&hints );
549 }
550 #endif
551
552 #ifdef DEBUG
553 if (debug&ShowColors) {
554 Window help;
555 const int lpixs_x = 16;
556 const int lpixs_y = 16;
557 const int d=16;
558 const int o=2;
559
560 // To overcome a bug? in the fvwm window-manager, the server is now
561 // synchronized and a pause for a second is taken. I wonder what fvwm
562 // is doing in that second ...
563
564 XSync(dpy,0);
565 printf( "wait a second, so that even the FVWM gets a change for not crashing\n" );
566 sleep(1);
567
568 help = CreateWindow("Noname",lpixs_x*(d+o)+1 ,lpixs_y*(d+o)+1);
569
570 for (int px=0;px<lpixs_x;px++) {
571 for (int py=0;py<lpixs_y;py++) {
572 if (!StoreColor(px+py*lpixs_x)) {
573 XSetForeground(dpy,gc_default,px+py*lpixs_x);
574 XFillRectangle(dpy,help,gc_default,1+px*(d+o),1+py*(d+o),d,d );
575 }
576 }
577 }
578 }
579 #endif
580 }
581
582
MapMainWindow()583 void MapMainWindow() {
584 XEvent event;
585
586 XSetWindowBackground( dpy, win, ball_pix[0] );
587 XMapRaised( dpy, win );
588 if (new_root) {
589 XSetWindowBackground( dpy, new_root, GetBlackPixel() );
590 XMapRaised( dpy, new_root );
591 if (!no_override) XInstallColormap( dpy, cmap );
592 }
593 XWindowEvent( dpy, win, ExposureMask, &event );
594 XSetInputFocus( dpy, win, RevertToNone, CurrentTime );
595 XSync(dpy,0);
596 }
597
598
CreateWindow(const char * name,int width,int height)599 Window CreateWindow( const char *name, int width, int height )
600 {
601 Window win;
602 XSetWindowAttributes attrib;
603 XSizeHints hints;
604 XEvent event;
605 static int offx=10;
606 const int frame = 7;
607
608 hints.flags = PPosition | PSize | PAspect | PMinSize | PMaxSize;
609 hints.x = DisplayWidth(dpy,scr) -offx-width-frame;
610 hints.y = DisplayHeight(dpy,scr)-height-2*frame,
611 hints.width = hints.min_width = hints.max_width = width;
612 hints.height = hints.min_height = hints.max_height = height;
613 offx+=width+2*frame;
614
615 win = XCreateSimpleWindow( dpy, RootWindow(dpy,scr),
616 hints.x, hints.y, hints.width, hints.height,
617 0, ball_pix[0], ball_pix[0] );
618 attrib.colormap = cmap;
619 XChangeWindowAttributes( dpy, win, CWColormap, &attrib );
620
621 XSetWMNormalHints( dpy,win,&hints );
622
623 XStoreName( dpy, win, name );
624 XSelectInput( dpy,win,ExposureMask );
625 XMapRaised( dpy, win );
626 XWindowEvent( dpy, win, ExposureMask, &event );
627 printf( "window '%s' mapped and raised at (%d,%d) size: (%dx%d)\n", name, hints.x, hints.y, hints.width, hints.height );
628 return win;
629 }
630
InitGraphic(double x,double y)631 void InitGraphic( double x, double y )
632 {
633 XSetWindowAttributes setwinattr;
634
635 #if (SOUND_SUBSYSTEM)
636 if (sound_request) init_sound( "" );
637 #endif
638
639 dpy = XOpenDisplay( "" );
640 if (!dpy) {
641 fprintf( stderr, "can't open display\n" );
642 exit(0);
643 }
644 scr = DefaultScreen(dpy);
645
646 #ifdef STATISTICS
647 fs=XLoadQueryFont(dpy,"5x8");
648 if (!fs) { fs=XLoadQueryFont(dpy,"6x10");
649 if (!fs) fs=XLoadQueryFont(dpy,"fixed");
650 }
651 if (fs) {
652 info_font = fs->fid;
653 info_cw = XTextWidth(fs,"A",1);
654 info_ch = fs->ascent + fs->descent;
655 }
656 #endif
657
658 //
659 // Gr��e des Fensters bestimmen: Fenster zentrieren
660 //
661 int dp_height = DisplayHeight(dpy,scr)-info_ch;
662
663 world_x = x;
664 world_y = y;
665 if ( size>0 ) {
666 if (size>DisplayWidth(dpy,scr)) size = DisplayWidth(dpy,scr);
667 max_x = size;
668 max_y = (int)(size/world_x*world_y);
669 if (max_y>dp_height) {
670 max_y = dp_height;
671 size = max_x = (int)(max_y/world_y*world_x);
672 }
673 }
674 else if ( ((double)DisplayWidth(dpy,scr))/dp_height < world_x/world_y ) {
675 max_x = DisplayWidth(dpy,scr);
676 max_y = (int)(max_x/world_x*world_y);
677 }
678 else {
679 max_y = dp_height;
680 max_x = (int)(max_y/world_y*world_x);
681 }
682
683 //
684 if ( size<=0 ) {
685 setwinattr.override_redirect = (no_override)?False:True;
686 new_root = XCreateSimpleWindow( dpy, RootWindow( dpy, scr ),
687 0, 0, DisplayWidth( dpy,scr ), DisplayHeight( dpy,scr ),
688 0, WhitePixel( dpy,scr ), BlackPixel( dpy,scr ) );
689 XChangeWindowAttributes( dpy, new_root, CWOverrideRedirect, &setwinattr );
690
691 win = XCreateSimpleWindow( dpy, new_root,
692 (DisplayWidth( dpy,scr )-max_x)/2,
693 (dp_height-max_y)/2,
694 max_x, max_y, 0, BlackPixel( dpy,scr ),WhitePixel( dpy,scr ) );
695 XSelectInput( dpy, new_root, ColormapChangeMask|FocusChangeMask|KeyPressMask );
696 XSelectInput( dpy, win, ExposureMask|KeyPressMask );
697 setwinattr.backing_store = (0)?Always:NotUseful;
698 setwinattr.bit_gravity = ForgetGravity;;
699 XChangeWindowAttributes(dpy,win,CWBitGravity|CWBackingStore,&setwinattr );
700 w2n = (max_x-2)/world_x;
701 }
702 else {
703 new_root = 0;
704 win = XCreateSimpleWindow( dpy, RootWindow( dpy, scr ),
705 0,0 , max_x, max_y, 2, 0,0 );
706 XSelectInput( dpy, win, KeyPressMask|ExposureMask);
707 setwinattr.backing_store = (0)?Always:NotUseful;
708 setwinattr.bit_gravity = ForgetGravity;;
709 XChangeWindowAttributes(dpy,win,CWBitGravity|CWBackingStore,&setwinattr );
710 w2n = (max_x-2)/world_x;
711 }
712
713 //
714 // BellPitch einstellen
715 //
716 XStoreName( dpy, win, "flying" );
717 InitTime(); // Initialisierung der Zeitmessung
718 }
719
UnlockGraphic()720 void UnlockGraphic() {
721 XUngrabServer(dpy);
722 XSync(dpy,0);
723 no_server_grabs+=100;
724 }
725
CloseGraphic()726 void CloseGraphic()
727 {
728 int i;
729 #ifdef STATISTICS
730 if (fs) XFreeFont(dpy,fs);
731 #endif
732 for (i=0;i<STIPPLE_CACHE;i++) {
733 if (rand_stipple[i]) XFreePixmap(dpy,rand_stipple[i]);
734 rand_stipple[i]=0;
735 rand_col[i]=0;
736 }
737
738 XFreePixmap( dpy, pointer_pmap );
739 XFreePixmap( dpy, stipple_pmap );
740
741 XFreeGC( dpy, gc_default );
742
743 XFreeGC( dpy, gc_lay1 );
744 XFreeGC( dpy, gc_lay2 );
745 XFreeGC( dpy, gc_cursor );
746
747 XFreeGC( dpy, gc_bxor );
748 XFreeGC( dpy, gc_bclear );
749
750 if (deluxe) XFreeGC( dpy, gc_ballwhite );
751 for (i=0;i<nball_ids;i++) {
752 XFreeGC( dpy, gc_ball[i] );
753 }
754
755 #ifdef STATISTICS
756 XFreeGC( dpy, gc_text );
757 #endif
758
759 if (new_root) {
760 XUninstallColormap( dpy, cmap );
761 }
762 if (cmap!=DefaultColormap( dpy, scr )) {
763 XFreeColormap(dpy,cmap);
764 }
765
766 end_sound();
767 XSync( dpy, 0 );
768 XCloseDisplay( dpy );
769 }
770
771
772
773
774
GetKey()775 char GetKey()
776 {
777 XEvent event;
778
779 XSync( dpy, 0 );
780 PBall::WaitForEvents();
781
782 while (XEventsQueued( dpy, QueuedAfterFlush )) {
783 XNextEvent( dpy, &event );
784 switch( event.xany.type ) {
785 case KeyPress:
786 { char buffer=0;
787 XComposeStatus compose;
788 KeySym keysym;
789
790 XLookupString( (XKeyEvent*)&event, &buffer, 1, &keysym, &compose );
791 if (buffer!='\014') {
792 if (isupper(buffer)) return tolower(buffer);
793 return buffer;
794 }
795 // run straight down to the exposure event when ^L was pressed
796 }
797 case Expose:
798 {
799 while( XCheckMaskEvent( dpy, ExposureMask, &event ))
800 ;
801 XClearWindow( dpy, win );
802 g->ExposeRedraw();
803 PBallTop::ForAll( &PBallTop::Redraw );
804 break;
805 }
806 case ColormapNotify:
807 while( XCheckMaskEvent( dpy, ColormapChangeMask, &event ));
808 if (event.xcolormap.state!=ColormapInstalled && event.xcolormap.colormap==cmap) {
809 printf( "### colormap was uninstalled by window manager\n" );
810 if (no_server_grabs) {
811 printf( " please let me grab the server or try the option -no_override\n" );
812 exit(0);
813 }
814 else {
815 printf( " I AM GRABBING THE SERVER NOW ...\n" );
816 }
817 XGrabServer(dpy);
818 XInstallColormap(dpy,cmap);
819 no_server_grabs-=100;
820 }
821 break;
822 case FocusIn:
823 // printf( "focus: In\n" );
824 break;
825 case FocusOut:
826 // printf( "focus: Out\n" );
827 break;
828 default:
829 break;
830 }
831 }
832 return 0;
833 }
834
835
836 #define XPix(x) ((int)((x)*w2n))
837 #define YPix(y) ((int)((y)*w2n))
838 #define Pix(r) ((int)((r)*w2n))
839
DrawLine(const Real & x1,const Real & y1,const Real & x2,const Real & y2)840 void DrawLine( const Real& x1, const Real& y1, const Real& x2, const Real& y2 ) {
841 int px1 = XPix(x1);
842 int py1 = YPix(y1);
843 int px2 = XPix(x2);
844 int py2 = YPix(y2);
845 XDrawLine( dpy, win, gc_current, px1, py1, px2, py2 );
846 }
847
848
DrawArc(const Real & x,const Real & y,const Real & r,const Real & from,const Real & angle)849 void DrawArc( const Real& x, const Real& y, const Real& r, const Real& from, const Real& angle ) {
850 int px = XPix(x-r);
851 int py = YPix(y-r);
852 int size= Pix(2.*r);
853
854 XDrawArc( dpy, win, gc_current,
855 px, py, size, size,
856 (int)(from*64.), (int)(angle*64.) );
857 }
858
859
DrawCircle(const Real & x,const Real & y,const Real & r)860 void DrawCircle( const Real& x, const Real& y, const Real& r ) {
861 int px = XPix(x-r);
862 int py = YPix(y-r);
863 int size= Pix(2.*r);
864
865 XDrawArc( dpy, win, gc_current,
866 px, py, size, size,
867 0, (int)360*64 );
868 }
869
870
FillArc(const Real & x,const Real & y,const Real & r,const Real & from,const Real & angle)871 void FillArc( const Real& x, const Real& y, const Real& r, const Real& from, const Real& angle ) {
872 int px = XPix(x-r);
873 int py = YPix(y-r);
874 int size= Pix(2.*r);
875
876 XFillArc( dpy, win, gc_current,
877 px, py, size, size,
878 (int)(from*64.), (int)(angle*64.) );
879 }
880
FillCircle(const Real & x,const Real & y,const Real & r)881 void FillCircle( const Real& x, const Real& y, const Real& r ) {
882 int px = XPix(x-r);
883 int py = YPix(y-r);
884 int size= Pix(2.*r);
885
886 XFillArc( dpy, win, gc_current,
887 px, py, size, size,
888 0, (int)360*64 );
889 }
890
891
FillRectangle(const Real & x,const Real & y,const Real & width,const Real & height)892 void FillRectangle( const Real& x, const Real& y, const Real& width, const Real& height ) {
893 int px1 = XPix(x);
894 int py1 = YPix(y);
895 int px2 = XPix(x+width);
896 int py2 = YPix(y+height);
897 XFillRectangle( dpy, win, gc_current, px1, py1, px2-px1, py2-py1 );
898 }
899
FillPoly(int n,...)900 void FillPoly( int n, ... ) {
901 va_list argptr;
902 Vec2 *v;
903 int i;
904 XPoint buffer[10];
905 XPoint *p; // Zeiger auf Puffer, um gegebenenfalls mehr anzufordern
906
907 va_start(argptr,n);
908
909 if (sizeof(buffer)/sizeof(XPoint)<(unsigned)n) p=new XPoint[n];
910 else p=buffer;
911
912 for (i=0;i<n;i++) {
913 v = va_arg(argptr,Vec2*);
914 p[i].x = XPix(v->X());
915 p[i].y = YPix(v->Y());
916
917 }
918 XFillPolygon( dpy,win,gc_current,p,n,0,0);
919
920 if (p!=buffer) delete p;
921 va_end(argptr);
922 }
923
FillPoly(int n,Vec2 v[])924 void FillPoly( int n, Vec2 v[] ) {
925 int i;
926 XPoint buffer[10];
927 XPoint *p;
928
929 if (sizeof(buffer)/sizeof(XPoint)<(unsigned)n) p=new XPoint[n];
930 else p=buffer;
931
932 for (i=0;i<n;i++) {
933 p[i].x = XPix(v[i].X());
934 p[i].y = YPix(v[i].Y());
935 }
936 XFillPolygon( dpy,win,gc_current,p,n,0,0);
937
938 if (p!=buffer) delete p;
939 }
940
941
942