1 #ifndef __global_h
2 # include "global.H"
3 #endif
4 #ifndef __port_h
5 # include "port.H"
6 #endif
7 #ifndef __color_h
8 # include "color.H"
9 #endif
10 #ifndef __tile_h
11 # include "tile.H"
12 #endif
13 #ifndef __board_h
14 # include "board.H"
15 #endif
16 #ifndef __font_h
17 # include "font.H"
18 #endif
19 #ifndef __game_h
20 # include "game.H"
21 #endif
22 #ifndef __mem_image_h
23 # include "mem_image.H"
24 #endif
25 #ifndef __color_mapper_h
26 # include "color_mapper.H"
27 #endif
28
29 #include <X11/Xutil.h>
30 #include <X11/cursorfont.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 // #include <string.h>
35 // #include <sys/time.h>
36 #ifdef WIN32
37 // l�schen der schlechtesten Macros der Xlib
38 # undef Status
39 # include "winsock.h"
40 #endif
41 #include <X11/Xos.h>
42 #ifndef X_GETTIMEOFDAY
43 /* define X_GETTIMEOFDAY macro, a portable gettimeofday() */
44 /* copied from Xos.h for pre-X11R6 releases */
45 # if defined(SVR4) || defined(VMS) || defined(WIN32)
46 # define X_GETTIMEOFDAY(t) gettimeofday(t)
47 # else
48 # define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0)
49 # endif
50 #endif
51 #ifndef FDS_TYPE
52 //
53 // The problem occured, that on HP-UX, the type used in the masks of the
54 // select() system call are not the usual 'fd_set'. Instead they are just
55 // integer pointers, which leads to an compile-error, when not casted.
56 // Therefore it actually will get casted by the following Macro FDS_TYPE,
57 // which should usually be defined to an empty string.
58 //
59 # ifdef __hpux
60 # define FDS_TYPE (int*)
61 # else
62 # define FDS_TYPE
63 # endif
64 #endif
65
66 #include "stipple.h"
67 #include "rstipple.h"
68
69 /* Field position */
70 #define MFieldX(x) ((x)*sizex+offx+border)
71 #define MFieldY(y) ((y)*sizey+offy+border)
72
73 /* Score position */
74 #define SCol(x) ((x)*bsizex+(dwidth)*sizex+2*border+offx)
75 #define STop() (border+offy)
76 #define SRow(y) (dheight*sizey+border-(y+1)*bsizey+offy)
77
78 #define FACTOR (2)
79 #define FlashSpeed 20
80
81 #define _TRACE_COLORS
82
83 unsigned long current_time;
84
get_current_time()85 static unsigned long get_current_time() {
86 unsigned long ret;
87 struct timeval timeval;
88 static unsigned long start=0;
89
90 X_GETTIMEOFDAY( &timeval );
91 if (!start) start=timeval.tv_sec;
92 ret = ((timeval.tv_sec-start) * 100) + timeval.tv_usec/10000;
93 return( ret );
94 }
95
96
97 Port *Port::first = 0;
98 int Port::color_id = 1;
99 int Port::dwidth = 8;
100 int Port::dheight = 3;
101 int Port::dsize = 44;
102 int Port::wsizex = 100;
103 int Port::wsizey = 100;
104 int Port::nplayers = 1;
105 Mode Port::def_mode = Smiley;
106 int Port::def_size = 1;
107 MemImage *Port::gif = 0;
108 int Port::remove_flag = 1;
109 int Port::sync_flag = 0;
110 int Port::resize_lock = 0;
111 static unsigned long next_sec;
112
113 struct fd_set Port::readfds;
114 int Port::nfds = 0;
115
116 #ifndef MaxBorder
117 # define MaxBorder (80)
118 #endif
119
Port(char * disp_name,char * color)120 Port::Port( char *disp_name, char *color )
121 {
122 char dsp_nam[30];
123 static int w=0;
124 int i;
125
126 wbsizex = (wsizex<wsizey)?wsizex:wsizey;
127 wbsizey = (wsizey*dheight)/(dwidth*dheight);
128 wborder = (wsizex+wsizey)/2;
129 if (wborder>MaxBorder) wborder=MaxBorder;
130
131 strcpy( dsp_nam, disp_name );
132 if ((*disp_name)&&(!strchr(dsp_nam,':'))) {
133 strcat( dsp_nam, ":0" );
134 }
135
136 // open connection to display and create a window
137 display = XOpenDisplay( dsp_nam );
138 if (!display) {
139 fprintf(stderr,"\n" );
140 fprintf( stderr, "*** can't open display '%s'.\n", dsp_nam );
141 fprintf(stderr,"\n" );
142 exit(-1);
143 }
144 screen = DefaultScreenOfDisplay( display );
145 mapper = new ColorMapper(display);
146 double_depth=(DefaultDepthOfScreen(screen)>8)?0:1;
147 // XSynchronize(display,1);
148
149 // Check for non-pseudocolor visual, since there are
150 // no planes available -> need for a stipple instead
151 if (DefaultVisualOfScreen(screen)->c_class!=PseudoColor || def_mode==Photo) {
152 light=mapper->alloc_named_color("white");
153 fg =mapper->alloc_named_color("grey30");
154 bg =mapper->alloc_named_color("grey60");
155 dark =mapper->alloc_named_color("black");
156
157 stipple_pmap=XCreateBitmapFromData( display,RootWindowOfScreen( screen ),
158 stipple_bits, stipple_width, stipple_height );
159 rstipple_pmap=XCreateBitmapFromData( display,RootWindowOfScreen( screen ),
160 rstipple_bits, rstipple_width, rstipple_height );
161 }
162 else {
163 stipple_pmap = 0;
164 rstipple_pmap = 0;
165 light = 0;
166 fg = 2;
167 bg = 1;
168 dark = 3;
169 }
170 MInit(dsize);
171 window = XCreateSimpleWindow( display, RootWindowOfScreen( screen ),
172 0, 0, MWidth(), MHeight(),
173 0, BlackPixelOfScreen(screen), WhitePixelOfScreen(screen) );
174 XStoreName( display, window, color );
175 XSelectInput( display, window, StructureNotifyMask|ExposureMask|ButtonPressMask );
176
177 normal_cursor = XCreateFontCursor( display, XC_top_left_arrow );
178 // idle_cursor = XCreateFontCursor( display, XC_dotbox );
179 idle_cursor = XCreateFontCursor( display, XC_circle );
180
181 XSetWindowAttributes attrib;
182 attrib.bit_gravity = ForgetGravity;
183 XChangeWindowAttributes(display,window,CWBitGravity,&attrib);
184
185 XSizeHints hints;
186 hints.flags = USPosition | USSize | PAspect;
187 hints.x = 100+(w%2)*(50+MWidth());
188 hints.y = 100+(w/2)*(50+MHeight());
189 hints.width = MWidth();
190 hints.height = MHeight();
191 hints.min_aspect.x = hints.max_aspect.x = MWidth();
192 hints.min_aspect.y = hints.max_aspect.y = MHeight();
193 #if (1)
194 XSetNormalHints( display,window,&hints );
195 #endif
196 w++;
197
198 this->width = hints.width;
199 this->height = hints.height;
200
201 Atom atom = XInternAtom(display,"PmWindowType",True);
202 if (atom) {
203 char* win_type = "FGnormal";
204 XTextProperty prop;
205 XStringListToTextProperty (&win_type, 1, &prop);
206 XSetTextProperty (display, window, &prop, atom);
207 XFree((void*)prop.value);
208 }
209
210 //
211 // Reaktion auf Destroy Message anmelden
212 //
213 WmProtocolsPropId = XInternAtom(display,"WM_PROTOCOLS",False);
214 WmDeleteWindowPropId = XInternAtom(display,"WM_DELETE_WINDOW",False);
215 XSetWMProtocols( display, window, &WmDeleteWindowPropId, 1 );
216
217 //
218 // Fileselector merken
219 //
220 if (!nfds) FD_ZERO( &readfds );
221 FD_SET( ConnectionNumber(display), &readfds );
222 if (nfds<=ConnectionNumber(display)) nfds = ConnectionNumber(display)+1;
223
224 mode=def_mode;
225 if (mode==Photo) {
226 ncols=gif->GetNCols();
227 gif_cols=new unsigned long[ncols];
228 for (i=0;i<ncols;i++) {
229 XColor def;
230 gif->GetColor(i,&def.red,&def.green,&def.blue);
231 gif_cols[i]=mapper->alloc_color(&def);
232 }
233 }
234
235 tile = new Tile*[board_p->ntiles];
236 for (i=0;i<board_p->ntiles;i++) tile[i]=0;
237 blank = 0;
238 empty = 0;
239 // initialize graphic context for drawing tiles
240 // on a pseudocolor display, only the lower 2 planes are to
241 // be drawn, the tile gets its color through overlay-planes.
242 gc_tile = XCreateGC( display, RootWindowOfScreen(screen), 0L, NULL );
243 if (stipple_pmap) {
244 XSetStipple( display, gc_tile, rstipple_pmap );
245 XSetFillStyle( display, gc_tile, FillStippled );
246 }
247 else {
248 XSetPlaneMask( display, gc_tile, 0x3 );
249 }
250 gc_all = XCreateGC( display, RootWindowOfScreen(screen), 0L, NULL );
251
252 // initialize tiles
253 sizex=0;
254 sizey=0;
255 resize( hints.width, hints.height );
256
257 // exchange colors of ports
258 colors=0;
259 color_name = new char[strlen(color)+1];
260 strcpy( color_name, color );
261 my_id = color_id;
262
263 #ifdef TRACE_COLORS
264 printf( "new Port: %08lx\n", this );
265 #endif
266 add_color( 0, "yellow" );
267 if (first) add_foreign_color( first, color_name );
268 add_color( color_id, color_name );
269
270 if (stipple_pmap) XSetWindowBackground( display, window, colors->pixel );
271 else XSetWindowBackground( display, window, colors->pixel+bg );
272 XMapRaised( display, window );
273
274 // connect to list of created displays
275 next = first;
276 first = this;
277
278 color_id++;
279 lock_count = 0;
280 lock_time = 0;
281 flash_time = 0;
282 lock[0] = lock[1] = -1;
283
284 points = 0;
285 selections = 0;
286 active = (sync_flag)?0:1;
287
288 #ifdef TRACE_COLORS
289 printf( " Port %08lx initialized\n", this );
290 #endif
291 }
292
add_foreign_color(Port * current,char * color_name)293 void Port::add_foreign_color( Port *current, char *color_name ) {
294 current->add_color( color_id, color_name );
295 if (current->next) add_foreign_color(current->next,color_name);
296 add_color( current->my_id, current->color_name );
297 }
298
299
sub_color(int id)300 void Port::sub_color( int id ) {
301 Color *current= colors;
302 Color *mark=0;
303
304 //
305 // Id dekrementieren
306 //
307 while(current) {
308 if (current->color_id==id) mark = current;
309 if (current->color_id>id) current->color_id--;
310 current=current->next;
311 }
312 //
313 // Farbe ausketten
314 //
315 if (mark==colors) {
316 colors = mark->next;
317 }
318 else {
319 current = colors;
320 while( current->next != mark ) current = current->next;
321 current->next = mark->next;
322 }
323 //
324 // Farbe loeschen
325 //
326 mark->next = 0;
327 delete mark;
328
329 //
330 // neue Fensterdimension:
331 //
332 offx = (width-MWidth())/2;
333 XClearArea(display,window,0,0,0,0,True);
334 }
335
~Port()336 Port::~Port() {
337
338 activate_next_player(); // checks, if I was the active player ...
339
340 nplayers--; // Zahl der Spieler
341 board_p->color_removed(my_id); // Farbe im Brett freigeben
342 color_id--; // Gesamtfarbenzaehler
343 //
344 // Farbe aus allen Ports austragen
345 //
346 Port *current;
347
348 current=first;
349 do {
350 if (current->my_id>my_id) current->my_id--;
351 current = current->next;
352 } while(current);
353
354 //
355 // Port ausketten
356 //
357 if (this==first) {
358 first = this->next;
359 }
360 else {
361 current = first;
362 while( current->next != this ) current = current->next;
363 current->next = this->next;
364 }
365
366 //
367 // Farbumsetzungstabelle freigeben
368 //
369 if (gif_cols) delete gif_cols;
370 if (gif&&!first) { delete gif; gif=0; }
371 //
372 // Farbe aus den Ports austragen
373 //
374 for (current=first;current;current=current->next)
375 current->sub_color( my_id );
376
377 for (int i=0;i<board_p->ntiles;i++) {
378 if (tile[i]) delete tile[i];
379 }
380 delete tile;
381 if (blank) delete blank;
382 if (empty) delete empty;
383 delete colors;
384 delete color_name;
385 if (stipple_pmap) {
386 XFreePixmap( display, stipple_pmap );
387 XFreePixmap( display, rstipple_pmap );
388 }
389 XFreeGC( display, gc_all );
390 XFreeGC( display, gc_tile );
391 XFreeCursor( display, normal_cursor );
392 XFreeCursor( display, idle_cursor );
393
394 delete mapper;
395 XSync( display, 0 );
396 XCloseDisplay( display );
397 }
398
UpdateTime(const char * time_str)399 void Port::UpdateTime( const char *time_str ) {
400 XStoreName( display, window, time_str );
401 }
402
add_color(int color_id,char * color_name)403 void Port::add_color( int color_id, char *color_name )
404 {
405 Color *new_color;
406
407 #ifdef TRACE_COLORS
408 printf( "%08lx: add %d = %s\n", this, color_id, color_name );
409 #endif
410
411 new_color = new Color( this, color_id, color_name );
412 #if(1)
413 new_color->next = colors;
414 colors = new_color;
415 #else
416 new_color->next = 0;
417 if (!colors) colors = new_color;
418 else {
419 Color *col = colors;
420 while( col->next ) col=col->next;
421 col->next=new_color;
422 }
423 #endif
424 }
425
426
empty_queue()427 int Port::empty_queue() {
428 XEvent event;
429
430 // XSync( display, 0 );
431 while ( XEventsQueued( display, QueuedAfterFlush ) ) {
432 XNextEvent( display, &event );
433 switch( event.type ) {
434 case ButtonPress:
435 {
436 switch(event.xbutton.button) {
437 case 2:
438 if (my_id==1) return 1;
439
440 default:
441 { if (board_p->finished&¤t_time>board_p->finished+5000) return 1;
442 int x = (event.xbutton.x-offx-border)/sizex;
443 int y = (event.xbutton.y-offy-border)/sizey;
444 #if (0)
445 printf(" press: (%d,%d)\n", x, y );
446 #endif
447 selected(x,y);
448 }
449 }
450 break;
451 }
452 case Expose:
453 {
454 #if (0)
455 printf("%d - Expose: (%d,%d) - (%d,%d)\n", my_id,
456 event.xexpose.x, event.xexpose.y,
457 event.xexpose.x + event.xexpose.width,
458 event.xexpose.y + event.xexpose.height );
459 #endif
460 redraw( event.xexpose.x, event.xexpose.y,
461 event.xexpose.x + event.xexpose.width,
462 event.xexpose.y + event.xexpose.height );
463 break;
464 }
465 case ConfigureNotify:
466 #if (0)
467 printf("%d - Configure: (%d,%d)\n", my_id,
468 event.xconfigure.width, event.xconfigure.height );
469 #endif
470 resize( event.xconfigure.width, event.xconfigure.height );
471 break;
472
473 case ClientMessage:
474 if (event.xclient.message_type == WmProtocolsPropId) {
475 Atom data_atom = (Atom)event.xclient.data.l[0];
476 if (data_atom == WmDeleteWindowPropId) {
477 if (my_id==1) return 1; // main-window -> than exit
478 return -1; // delete me !
479 }
480 }
481 }
482 }
483 return 0;
484 }
485
wait_event()486 int Port::wait_event() {
487 static unsigned long next=0;
488 int erg = 0;
489
490 current_time = get_current_time();
491 if (!next||next>next_sec) next=next_sec;
492
493 if (current_time<next) {
494 struct timeval timeout;
495 unsigned long dist = next-current_time;
496 struct fd_set readfds_cp;
497
498 memcpy( &readfds_cp, &readfds, sizeof(readfds) );
499 timeout.tv_sec = dist / 100;
500 timeout.tv_usec = dist % 100;
501 select( nfds, FDS_TYPE &readfds_cp, 0, 0, &timeout );
502 current_time = get_current_time();
503 }
504 if (current_time>next_sec) {
505 next_sec = ((current_time/100)+1)*100;
506 if (!board_p->finished) {
507 char buffer[20];
508 sprintf( buffer, "%02ld:%02ld",
509 (next_sec/100) / 60, (next_sec/100) % 60 );
510
511 for( Port *current = first; current; current=current->next ) {
512 current->UpdateTime(buffer);
513 }
514 }
515 }
516
517 next = 0;
518 for( Port *current = first; current; current=current->next ) {
519 int delete_flag = current->empty_queue();
520
521 if (delete_flag<0) {
522 delete current;
523 if (first) return erg+wait_event();
524 else return 1;
525 }
526 else erg+=delete_flag;
527 unsigned long current_next = current->deselect();
528 if (current_next) {
529 if (!next||current_next<next) next = current_next;
530 }
531 }
532 return erg;
533 }
534
gc_color_n(int id)535 GC Port::gc_color_n( int id ) {
536 Color *current=colors;
537 int i;
538
539 for (i=color_id-1;i>id;i--) current=current->next;
540
541 return( current->gc_n );
542 }
543
Points(int id)544 int Port::Points( int id ) {
545 Port *current=first;
546 int i;
547
548 for (i=color_id-1;i>id;i--) current=current->next;
549 return( current->points );
550 }
551
statistic()552 void Port::statistic() {
553 Port *current=first;
554
555 printf( "SUMMARY Points Selections\n" );
556 for (current=first;current;current=current->next) {
557 printf("%-10s %3d %-5d\n",
558 current->color_name,
559 current->points, current->selections );
560 }
561 if (board_p->finished) {
562 printf( "TIME: %02ld:%02ld.%02ld\n",
563 (board_p->finished/100) / 60,
564 (board_p->finished/100) % 60,
565 (board_p->finished%100) );
566 }
567 }
568
redraw(int x,int y)569 void Port::redraw( int x, int y )
570 {
571 Field *f= board_p->field(x,y);
572
573 if (!f) return;
574
575 if (f->locked && !f->gone) {
576 XCopyArea( display, tile[f->tile_id]->pixmap, window, gc_tile,
577 0, 0, sizex, sizey, MFieldX(x), MFieldY(y) );
578 if (!stipple_pmap||f->flash||f->lock_col!=my_id) {
579 XFillRectangle( display, window,
580 (f->flash)? gc_color_n(0) : gc_color_n(f->lock_col),
581 MFieldX(x), MFieldY(y), sizex, sizey );
582 }
583 #if (0)
584 XSetFillStyle( display, gc_tile, FillStippled );
585 XCopyArea( display, tile[f->tile_id]->pixmap, window, gc_tile,
586 0, 0, sizex, sizey, MFieldX(x), MFieldY(y) );
587 #endif
588 }
589 else {
590 if (remove_flag || !f->gone || f->lock_col!=my_id) {
591 XCopyArea( display, ((f->found)?empty->pixmap:blank->pixmap),
592 window, gc_tile, 0, 0, sizex, sizey, MFieldX(x), MFieldY(y) );
593 XFillRectangle( display, window,
594 (f->found)?gc_color_n(f->lock_col):gc_color_n(my_id),
595 MFieldX(x), MFieldY(y), sizex, sizey );
596 }
597 else {
598 XCopyArea( display, tile[f->tile_id]->pixmap, window, gc_tile,
599 0, 0, sizex, sizey, MFieldX(x), MFieldY(y) );
600 }
601 }
602 }
603
draw_block(int p,int x,int y)604 void Port::draw_block( int p, int x, int y ) {
605 XFillRectangle( display, window, gc_color_n(p+1), x, y, bsizex, bsizey );
606
607 XSetForeground( display, gc_tile, bg );
608 XFillRectangle( display, window, gc_tile, x, y, bsizex, bsizey );
609
610 XSetForeground( display, gc_tile, light );
611 XDrawLine( display, window, gc_tile, x, y, x+bsizex-1, y );
612 XDrawLine( display, window, gc_tile, x, y, x, y+bsizey-1 );
613
614 XSetForeground( display, gc_tile, dark );
615 XDrawLine( display, window, gc_tile, x, y+bsizey-1, x+bsizex-1, y+bsizey-1 );
616 XDrawLine( display, window, gc_tile, x+bsizex-1, y, x+bsizex-1, y+bsizey-1 );
617 }
618
redraw_score(int x)619 void Port::redraw_score( int x )
620 {
621 if (x>=nplayers || x<0) return;
622
623 XFillRectangle( display, window, gc_color_n(my_id),
624 SCol(x), STop(), bsizex, dheight*sizey );
625
626 XSetForeground( display, gc_tile, fg);
627 XFillRectangle( display, window, gc_tile,
628 SCol(x), STop(), bsizex, dheight*sizey );
629
630 XSetForeground( display, gc_tile, dark);
631 XDrawLine( display, window, gc_tile,
632 SCol(x), STop(), SCol(x+1)-1, STop() );
633 XDrawLine( display, window, gc_tile,
634 SCol(x), STop(), SCol(x), STop()+dheight*sizey-1 );
635
636 XSetForeground( display, gc_tile, light);
637 XDrawLine( display, window, gc_tile,
638 SCol(x), STop()+dheight*sizey-1, SCol(x+1)-1, STop()+dheight*sizey-1 );
639 XDrawLine( display, window, gc_tile,
640 SCol(x+1)-1, STop(), SCol(x+1)-1, STop()+dheight*sizey-1 );
641
642 int height = Points(x+1);
643 for (int y=1;y<=height;y++) {
644 draw_block( x, SCol(x), SRow(y-1) );
645 }
646 XFlush( display );
647 }
648
redraw(int x1,int y1,int x2,int y2)649 void Port::redraw( int x1, int y1, int x2, int y2 )
650 {
651 int x1s,y1s,x2s,y2s;
652 int x, y;
653
654 #if (1)
655 XClearArea( display, window, x1, y1, x2-x1, y2-y1, False );
656 #endif
657
658 // check for score redraw
659 x1s = (x1-SCol(1))/bsizex; // make it one field smaller
660 x2s = (x2-SCol(0))/bsizex;
661 if (x2s>=0) {
662 for (x=x1s;x<=x2s;x++) {
663 redraw_score(x);
664 }
665 }
666
667 x1s=(x1-offx-border)/sizex;
668 y1s=(y1-offy-border)/sizey;
669 x2s=(x2-offx-border)/sizex;
670 y2s=(y2-offy-border)/sizey;
671
672 for (x=x1s-1;x<=x2s;x++) {
673 for (y=y1s-1;y<=y2s;y++) {
674 redraw( x, y );
675 }
676 }
677 }
678
tile_redraw(int fid)679 void Port::tile_redraw( int fid )
680 {
681 int x = fid%board_p->dx;
682 int y = fid/board_p->dx;
683
684
685 for ( Port *current = first; current; current = current->next )
686 { current->redraw( x, y );
687 // XFlush( current->display );
688 XSync( current->display, 0 );
689 }
690 }
691
flush_all()692 void Port::flush_all()
693 {
694 for ( Port *current = first; current; current = current->next )
695 XFlush( current->display );
696 }
697
activate_next_player()698 void Port::activate_next_player()
699 {
700 Port *current;
701
702 if (sync_flag && active) {
703 for ( current = first; current; current = current->next ) {
704 if (current==this) break;
705 }
706 Port *next=(current->next)?current->next:first;
707 current->set_active( 0 );
708 next->set_active( 1 );
709 }
710 }
711
set_active(int a)712 void Port::set_active( int a ) {
713 if ( a ) {
714 XDefineCursor( display, window, normal_cursor );
715 }
716 else {
717 XDefineCursor( display, window, idle_cursor );
718 }
719 active=a;
720 }
721
activate_any_player()722 void Port::activate_any_player()
723 {
724 Port *current;
725 int id=rand()%nplayers;
726
727 if (sync_flag) {
728 for ( current = first; current; current = current->next ) {
729 current->set_active( (id)?0:1 );
730 id--;
731 }
732 }
733 }
734
remove()735 int Port::remove() {
736 if ((lock_count>1)&&(board_p->field(lock[1])->found)) {
737 board_p->field(lock[1])->gone = 1;
738 tile_redraw( lock[1] );
739 board_p->field(lock[0])->gone = 1;
740 tile_redraw( lock[0] );
741 lock_count=0;
742 points+=2;
743
744 for (Port *p=first;p;p=p->next) {
745 p->redraw_score(my_id-1);
746 }
747 board_p->tile_removed(my_id);
748 flash_time=0;
749 return 1;
750 }
751 else {
752 activate_next_player();
753 return 0;
754 }
755 }
756
deselect()757 unsigned long Port::deselect()
758 {
759 unsigned long next = 0;
760
761 if (flash_time) {
762 if (flash_time<current_time) {
763 board_p->field(lock[0])->flash ^= 1;
764 board_p->field(lock[1])->flash ^= 1;
765 tile_redraw(lock[0]);
766 tile_redraw(lock[1]);
767 next=flash_time=current_time+FlashSpeed;
768 // printf("FLASH %lu\n",flash_time);
769 }
770 else {
771 next = flash_time;
772 // printf("FLASH SUPPRESSED\n");
773 }
774 }
775 if (lock_time&¤t_time<lock_time)
776 return (!next||next>lock_time)?lock_time:next;
777
778 if (lock_count>1) {
779 if (!remove()) {
780 board_p->field(lock[1])->locked = 0;
781 tile_redraw( lock[1] );
782 }
783 }
784 if (lock_count>0) {
785 board_p->field(lock[0])->locked = 0;
786 tile_redraw( lock[0] );
787 }
788 lock_count=0;
789 lock_time =0;
790
791 return 0;
792 }
793
selected(int x,int y)794 void Port::selected( int x, int y )
795 {
796 int fid;
797 Field *f= board_p->field(x,y);
798
799 if (!f) return;
800
801 //printf( "Pos: (%d,%d), Tile: %d, Locks %d\n", x,y,f->tile_id,lock_count );
802 if (lock_count==2) {
803 if (!remove()) {
804 // XBell( display, 100 );
805 return;
806 }
807 }
808
809 fid = x+board_p->dx*y;
810
811 //printf(" fid: %d, removed: %d, lock_id: %d\n", fid, f->removed, f->lock_id );
812
813 if (f->found) return;
814 if (f->locked || !active) {
815 #if (1)
816 if (!active) XBell( display,100 );
817 return;
818 #else
819 if (f->lock_col!=my_id){
820 }
821 else {
822 if (lock[0]==fid) {
823 lock[0]=lock[1];
824 }
825 lock_count--;
826 f->locked=0;
827 tile_redraw( fid );
828 lock_time=current_time;
829 return;
830 }
831 #endif
832 }
833
834 selections++;
835
836 f->lock_col = my_id;
837 f->locked = 1;
838 lock[lock_count++] = fid;
839
840 if (lock_count==2) {
841 if (board_p->field(lock[0])->tile_id==board_p->field(lock[1])->tile_id) {
842 board_p->field(lock[0])->found = 1;
843 board_p->field(lock[0])->flash = 1;
844 board_p->field(lock[1])->found = 1;
845 board_p->field(lock[1])->flash = 1;
846 tile_redraw( lock[0] );
847 // tile_redraw( lock[1] );
848 flash_time = current_time+FlashSpeed;
849 // printf( "FLASH: %lu (current: %lu\n)\n", current_time, flash_time );
850 }
851 }
852 tile_redraw( fid );
853 lock_time = current_time + ((lock_count==2)?100:((sync_flag)?6000:300));
854 }
855
find_font(const char * pattern,int size)856 const char *Port::find_font( const char *pattern, int size ) {
857 char **font;
858 int count;
859 int i;
860 char *true_name = 0;
861 char *true_scale = 0;
862 char *bitmap_name = 0;
863 char *bitmap_scale = 0;
864 char *closest_name = 0;
865 int closest_scale = -1;
866 static char ret_buffer[200];
867
868 font=XListFonts(display,pattern,100,&count);
869
870 for (i=0;i<count;i++) {
871 int sep;
872 char *scale;
873
874 scale = font[i];
875 sep=7;
876 while( *scale && sep ) {
877 if (*scale++=='-') sep--;
878 }
879 if (scale) {
880 if (!strncmp("0-0-0-0-",scale,8)) {
881 true_name = font[i];
882 true_scale = scale;
883 }
884 else if (!strncmp("0-0-",scale,4)) {
885 bitmap_name = font[i];
886 bitmap_scale = scale;
887 }
888 else {
889 int csize = atoi(scale);
890 if ( csize<size && csize>closest_scale ) {
891 closest_name = font[i];
892 closest_scale = csize;
893 }
894 }
895 }
896 }
897
898 ret_buffer[0]='\0';
899 if (bitmap_name) {
900 strcpy( ret_buffer, bitmap_name );
901 sprintf(ret_buffer+(bitmap_scale-bitmap_name),"%d%s", size, bitmap_scale+1 );
902 }
903 if (true_name) {
904 strcpy( ret_buffer, true_name );
905 sprintf(ret_buffer+(true_scale-true_name),"%d%s", size, true_scale+1 );
906 }
907 if ( closest_name && closest_scale > size-4 ) {
908 strcpy(ret_buffer,closest_name);
909 }
910
911 XFreeFontNames(font);
912
913 if (ret_buffer[0]=='\0') {
914 fprintf(stderr,"\n" );
915 fprintf(stderr,"*** Unable to find any matching fonts with pattern\n" );
916 fprintf(stderr,"*** '%s' on display '%s'.\n", pattern, DisplayString(display) );
917 fprintf(stderr,"*** Please make the font available via xset(1) or use the\n" );
918 fprintf(stderr,"*** option -font <name> to select a different pattern.\n" );
919 fprintf(stderr,"\n" );
920 exit(-1);
921 }
922 // printf( "%2d %2d: %s\n", size, closest_scale, ret_buffer );
923 return ret_buffer;
924 }
925
resize(int width,int height)926 void Port::resize( int width, int height )
927 {
928 int nsizex;
929 int nsizey;
930 int i;
931 //
932 // check window size
933 //
934 nsizex = wsizex*width/WWidth(); // calculate new pixel values
935 nsizey = wsizey*height/WHeight();
936
937 if (nsizex*wsizey<nsizey*wsizex) { // check aspect ratio
938 nsizey = nsizex*wsizey/wsizex;
939 }
940 else { nsizex = nsizey*wsizex/wsizey;
941 }
942
943 if (resize_lock!=0) {
944 if (resize_lock>0) {
945 nsizex=wsizex*resize_lock/100;
946 }
947 else {
948 int ratio = (nsizex*100)/wsizex;
949 ratio = 10*(ratio/10);
950 nsizex=wsizex*ratio/100;
951 }
952 }
953
954 if ((nsizex==sizex)&&(nsizey==sizey)) {
955 offx = (width-MWidth())/2;
956 offy = (height-MHeight())/2;
957 return;
958 }
959
960 MInit(nsizex);
961 offx = (width-MWidth())/2;
962 offy = (height-MHeight())/2;
963
964 this->width = width;
965 this->height = height;
966 // XResizeWindow( display, window, MWidth(sizex), MHeight(sizey) );
967
968 // calculate screen resolution in dots per inch 25.4mm=1 inch
969 // int res_x = (int)(WidthOfScreen(screen)/(WidthMMOfScreen(screen)/25.4));
970 // int res_y = (int)(HeightOfScreen(screen)/(HeightMMOfScreen(screen)/25.4));
971
972
973 ScalableFont *font;
974
975 if (param[Port::def_mode].font_mode) {
976 font = new FlipFont(display,
977 find_font(param[Port::def_mode].font,sizex-4 ) ,270);
978 }
979 else {
980 font = new ScalableFont(display,
981 find_font(param[Port::def_mode].font,sizey-10 ),0);
982 }
983
984 //
985 // initialize tiles
986 //
987 for (i=0;i<board_p->ntiles;i++) {
988 if ( tile[i] ) delete tile[i];
989 tile[i] = new Tile( this, font, i );
990 }
991 if (blank) delete blank;
992 if (empty) delete empty;
993 empty = new Tile(this, font, -1);
994 blank = new Tile(this, font, -2);
995
996 delete font;
997 }
998