2 /****************************************************************************
3 * Copyright (C) 2002 by Leo Khramov
4 * email: leo@xnc.dubna.su
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 ****************************************************************************/
16 // $Id: xwellengine.cxx,v 1.3 2003/02/20 15:09:41 leo Exp $
18 /// module description
19 /// This module contains methods of class XWellEngine which implements X11 calls
20 /// for the game. So this is X11 dependent part. It receives XEvents,
21 /// make convertions, many initions and calls.
26 #include "xwellengine.h"
27 #include "xwellinput.h"
28 #include "image/image.h"
30 #include "commonfuncs.h"
31 #include "wellclass.h"
36 const unsigned long TIMESTEP
=10000l;
38 //Colors for welltris pieces and grid (x color names)
39 static char *game_color_names
[MAX_GAME_COLORS
] =
49 /* 8*/ "CornflowerBlue",
53 /*12*/ "DarkTurquoise",
70 /*29*/ "CornflowerBlue",
74 /*33*/ "LightSteelBlue",
79 /*38*/ "MediumSeaGreen",
80 /*39*/ "DarkSlateGray",
82 /*41*/ "MediumVioletRed",
84 /*43*/ "MediumAquamarine",
87 /*46*/ "DarkOliveGreen",
91 /*50*/ "MediumTurquoise",
92 /*51*/ "DarkSlateBlue",
107 //===========================================================================
108 /// global new_well_engine(argc,argv)
109 /// Creates new WellEngine object, X11 realization (create XWellEngine)
110 /// tags new_well_engine
111 WellEngine
* new_well_engine(int argc
, char** argv
)
113 return new XWellEngine(argc
,argv
);
116 //===========================================================================
117 /// global XWellEngine(argc,argv)
118 /// Constructor of class that incupsulates work with X window
119 /// This class must always be allocated through 'new'
121 /// +argc: number of commanline args
122 /// +argv: command line args
124 XWellEngine::XWellEngine(int argc
, char** argv
):WellEngine(argc
,argv
)
129 if((strcmp("-display",argv
[i
])==0 ||
130 strcmp("-d", argv
[i
])==0) && i
+1<argc
)
132 if((disp
=XOpenDisplay(dispchr
))==NULL
)
135 "%s: connection to X server failed on display %s.....\n",
139 dbgprintf(("Opened X display at [%s]\n",dispchr
));
141 scr
=DefaultScreen(disp
);
142 colormap
=defcmp
=DefaultColormap(disp
,scr
);
143 whitepixel
=WhitePixel(disp
,scr
);
144 blackpixel
=BlackPixel(disp
,scr
);
146 xcon
=ConnectionNumber(disp
);
149 init_mainwindow(argc
,argv
);
154 //===========================================================================
155 /// global XWellEngine(argc,argv)
156 /// Destructor of class that incupsulates work with X window
158 XWellEngine::~XWellEngine()
164 //===========================================================================
165 /// global init_mainwindow(argc,argv)
166 /// create main game window and all other stuff around it
168 void XWellEngine::init_mainwindow(int argc
,char **argv
)
170 char *winname
="X Welltris "VERSION
;
171 XSetWindowAttributes xswa
;
172 XWindowAttributes xwinattr
;
175 if((pxsh
=XAllocSizeHints())==NULL
)
177 fprintf(stderr
,"xwelltris: Error allocating size hints\n");
181 pxsh
->flags
=(USSize
| PSize
| PMinSize
| PMaxSize
);
184 pxsh
->min_width
=pxsh
->width
;
185 pxsh
->min_height
=pxsh
->height
;
186 pxsh
->max_width
=pxsh
->width
;
187 pxsh
->max_height
=pxsh
->height
;
189 mainw
=XCreateSimpleWindow(disp
,DefaultRootWindow(disp
),
190 0,0,pxsh
->width
,pxsh
->height
,
191 0,whitepixel
,blackpixel
);
192 if((pch
=XAllocClassHint())==NULL
)
194 fprintf(stderr
,"xwelltris: Error allocating ClassHint\n");
197 pch
->res_name
="xwelltris";
198 pch
->res_class
="XWELLTRIS";
199 if(XStringListToTextProperty(&winname
,1,&wname
)==0)
201 fprintf(stderr
,"xwelltris: Error creating TextProperty\n");
204 if(XStringListToTextProperty(&pch
->res_name
,1,&iname
)==0)
206 fprintf(stderr
,"xwelltris: Error creating TextProperty\n");
209 if((pxwmh
=XAllocWMHints())==NULL
)
211 fprintf(stderr
,"welltris: Error allocating WMHints\n");
214 pxwmh
->flags
=(InputHint
|StateHint
);
216 pxwmh
->initial_state
=NormalState
;
217 XSetWMProperties(disp
,mainw
,&wname
,&iname
,argv
,argc
,pxsh
,pxwmh
,pch
);
219 gcv
.foreground
=whitepixel
;
220 gcv
.background
=blackpixel
;
221 maingc
=XCreateGC(disp
,mainw
,(GCForeground
| GCBackground
),&gcv
);
222 xswa
.colormap
=defcmp
;
223 xswa
.bit_gravity
=CenterGravity
;
224 XChangeWindowAttributes(disp
,mainw
,(CWColormap
| CWBitGravity
),&xswa
);
225 XSelectInput(disp
,mainw
,
228 StructureNotifyMask
|
234 wmDeleteWindow
= XInternAtom(disp
, "WM_DELETE_WINDOW", False
);
235 XSetWMProtocols(disp
, mainw
, &wmDeleteWindow
, 1);
236 XSetGraphicsExposures(disp
,maingc
,False
);
239 //===========================================================================
240 /// global show_main()
243 void XWellEngine::show_main()
245 XMapRaised(disp
,mainw
);
249 //===========================================================================
250 /// global load_image(Images id, char* name)
251 /// Load image into memory and register it with given id for use
253 bool XWellEngine::load_image(Images id
, char* name
)
260 find_full_path_for_file(name
,buf
);
261 image_pixmaps
[id
]=LoadPixmap(buf
,F_AUTO
,images
[id
].l
,images
[id
].h
,CMP_OWN
);
267 //===========================================================================
268 /// global screen_copy(Geo*)
269 /// copy part of image to the screen
271 void XWellEngine::screen_copy(Geo
*pgeo
)
278 XCopyArea(disp
,image_pixmaps
[pgeo
->im
],mainw
,maingc
,
279 pgeo
->fromx
,pgeo
->fromy
,pgeo
->l
,pgeo
->h
,
280 pgeo
->tox
,pgeo
->toy
);
283 //===========================================================================
284 /// global screen_clear(Geo*)
285 /// clear part of screen
287 void XWellEngine::screen_clear(Geo
*pgeo
)
290 XClearArea(disp
,mainw
,pgeo
->tox
,pgeo
->toy
,pgeo
->l
,pgeo
->h
,False
);
293 //===========================================================================
294 /// global set_main_background_image(Images id)
295 /// set image with given id to background of main window
297 void XWellEngine::set_main_background_image(Images id
)
299 if(images
[id
].id
!=imNone
)
301 XSetWindowBackgroundPixmap(disp
,mainw
, image_pixmaps
[id
]);
302 XClearWindow(disp
,mainw
);
307 //===========================================================================
308 /// global event_loop()
309 /// main event loop - process all events and make game moves
311 void XWellEngine::event_loop()
314 struct timezone tzone
;
317 dbgprintf(("Entered in event_loop\n"));
319 gettimeofday(&now
, &tzone
);
320 gettimeofday(&nexttime
, &tzone
);
322 while(!done_loop_var
)
324 if(wait_for_timers()==0) //Time out
326 process_time_event();
331 dbgprintf(("Got xevent: %d for window 0x%x\n",xev
.type
,xev
.xany
.window
));
332 XNextEvent(disp
,&xev
);
336 dbgprintf(("Expose event\n"));
337 process_event_for_all(wEvent(eExpose
,&xev
));
341 dbgprintf(("KeyPressed event\n"));
342 process_event_for_all(wEvent(eKeyPress
,&xev
));
346 dbgprintf(("MouseButtonPress event\n"));
347 mev
.mx
=xev
.xbutton
.x
;
348 mev
.my
=xev
.xbutton
.y
;
349 mev
.bstate
=xev
.xbutton
.button
==Button1
? But1Press
: But2Press
;
350 process_event_for_all(wEvent(eMousePress
,&mev
));
354 dbgprintf(("MouseMotion event\n"));
355 mev
.mx
=xev
.xmotion
.x
;
356 mev
.my
=xev
.xmotion
.y
;
357 mev
.bstate
=xev
.xbutton
.button
==Button1
? But1Press
: But2Press
;
358 process_event_for_all(wEvent(eMouseMove
,&mev
));
362 dbgprintf(("ClientMessage event\n"));
363 if (xev
.xclient
.format
== 32 &&
364 xev
.xclient
.data
.l
[0] == wmDeleteWindow
)
366 dbgprintf(("Got WM_DELETE_WINDOW\n"));
367 process_event_for_all(wEvent(eDelete
));
373 dbgprintf(("FocusOut event\n"));
374 process_event_for_all(wEvent(eFocusOut
));
380 dbgprintf(("Exiting from event_loop\n"));
383 //===========================================================================
384 /// global wait_for_timers()
385 /// calculate delay and wait for events and timers
387 int XWellEngine::wait_for_timers()
389 struct timeval delayt
;
390 struct timezone tzone
;
392 fd_set writefd
, exceptfd
, readfd
;
397 FD_SET(xcon
, &readfd
);
399 gettimeofday(&now
, &tzone
);
400 delayt
.tv_sec
= nexttime
.tv_sec
- now
.tv_sec
;
401 delayt
.tv_usec
= nexttime
.tv_usec
- now
.tv_usec
;
402 correct_to_real_time(delayt
);
403 if (((long) delayt
.tv_sec
> 0) ||
404 (((long) delayt
.tv_sec
== 0) &&
405 ((long) delayt
.tv_usec
> 0)))
407 ret
=select(xcon
+ 1, &readfd
, &writefd
, &exceptfd
, &delayt
);
409 if(ret
==0) //Timed out
410 gettimeofday(&now
, &tzone
);
411 nexttime
.tv_sec
=now
.tv_sec
;
412 nexttime
.tv_usec
=now
.tv_usec
+ TIMESTEP
;
413 correct_to_real_time(nexttime
);
418 //===========================================================================
419 /// global correct_to_real_time(struct timeval&)
420 /// corrects timval to real values
422 void XWellEngine::correct_to_real_time(struct timeval
& tv
)
424 while (tv
.tv_usec
< 0)
427 tv
.tv_usec
+= MILLION
;
429 while (tv
.tv_usec
>= MILLION
)
432 tv
.tv_usec
-= MILLION
;
437 //===========================================================================
438 /// global udelay(int msec)
439 /// Unix portable delay :)
441 void XWellEngine::udelay(int msec
)
446 select(0,0,0,0,&tout
);
451 //===========================================================================
452 /// local init_colors()
453 /// allocate all nessesary colors
455 void XWellEngine::init_colors()
460 colormap
=im_get_colormap();
465 XSetWindowColormap(disp
,mainw
,colormap
);
467 for(i
=COLOR_DELTA
;i
<MAX_GAME_COLORS
;i
++)
469 if (XParseColor(disp
, colormap
, game_color_names
[i
], &tmp
) == 0)
471 fprintf(stderr
, "Welltris: invalid color '%s'.\n",
472 game_color_names
[i
]);
473 game_colors
[i
]=blackpixel
;
475 if (XAllocColor(disp
, colormap
, &tmp
) == 0) {
476 (void) fprintf(stderr
, "Welltris: can't allocate color '%s'.\n",
477 game_color_names
[i
]);
478 game_colors
[i
]=blackpixel
;
480 game_colors
[i
]=tmp
.pixel
;
485 dbgprintf(("Allocating colors for Pseudo Colormap\n"));
486 for(i
=0;i
<FREE_COLORS
;i
++)
488 if (XParseColor(disp
, colormap
, game_color_names
[i
], &tmp
) == 0)
490 fprintf(stderr
, "Welltris: invalid color '%s'.\n",
491 game_color_names
[i
]);
492 game_colors
[i
]=blackpixel
;
494 if (XAllocColor(disp
, colormap
, &tmp
) == 0) {
495 (void) fprintf(stderr
, "Welltris: can't allocate color '%s'."
496 "Using black instead\n",
497 game_color_names
[i
]);
498 game_colors
[i
]=blackpixel
;
500 game_colors
[i
]=tmp
.pixel
;
502 for(i
=FREE_COLORS
;i
<MAX_GAME_COLORS
- SYSCOLORS
;i
++)
503 game_colors
[i
]=game_colors
[i
-FREE_COLORS
];
507 for(i
=0;i
<MAX_GAME_COLORS
- SYSCOLORS
;i
++)
509 if (XParseColor(disp
, colormap
, game_color_names
[i
], &tmp
) == 0)
511 fprintf(stderr
, "Welltris: invalid color '%s'.\n",
512 game_color_names
[i
]);
513 game_colors
[i
]=blackpixel
;
515 if (XAllocColor(disp
, colormap
, &tmp
) == 0) {
516 (void) fprintf(stderr
, "Welltris: can't allocate color '%s'.\n",
517 game_color_names
[i
]);
518 game_colors
[i
]=blackpixel
;
520 game_colors
[i
]=tmp
.pixel
;
525 //===========================================================================
526 /// global new_well_drawing_engine()
527 /// creates drawing engine for well board - version for X Window
529 WellDrawingEngine
* XWellEngine::new_well_drawing_engine()
531 return new XWellDrawingEngine(this);
534 //===========================================================================
535 /// global new_well_top_nine()
536 /// creates new top nine object - version for X Window
538 WellTopNine
* XWellEngine::new_well_top_nine()
540 return new WellTopNine
;
543 //===========================================================================
544 /// global new_well_intro()
545 /// creates new introduction object - version for X Window
547 WellIntro
* XWellEngine::new_well_intro()
549 return new WellIntro
;
552 //===========================================================================
553 /// global new_well_key(char*)
554 /// creates new key object - version for X Window
556 WellKey
* XWellEngine::new_well_key(char* name
)
558 return new WellKey(name
);
561 //===========================================================================
562 /// global new_well_switch(char*)
563 /// creates new switch object - version for X Window
565 WellSwitch
* XWellEngine::new_well_switch(char* name
)
567 return new WellSwitch(name
);
570 //===========================================================================
571 /// global new_well_input(char*)
572 /// creates new input object - version for X Window
574 WellInput
* XWellEngine::new_well_input(char* name
)
576 return new XWellInput(name
);
579 //===========================================================================
580 /// global new_well_base()
581 /// creates new game object - version for X Window
583 WellBase
* XWellEngine::new_well_base()
588 //===========================================================================
589 /// global new_well_image_font()
590 /// creates image font object - version for X Window
592 WellImageFont
* XWellEngine::new_well_image_font(Images id
,
597 return new XWellImageFont(id
,ifl
,ifh
,idx
,idy
);