original 1.0.1 release
[xwelltris.git] / src / x11 / xwellengine.cxx
blob9e2c987360003f0ce3b0f5500880bb0a2b2277bf
1 // docm_prefix(///)
2 /****************************************************************************
3 * Copyright (C) 2002 by Leo Khramov
4 * email: leo@xnc.dubna.su
5 *
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.
24 #include "version.h"
25 #include "globals.h"
26 #include "xwellengine.h"
27 #include "xwellinput.h"
28 #include "image/image.h"
29 #include "bilist.h"
30 #include "commonfuncs.h"
31 #include "wellclass.h"
33 Display *disp;
34 Colormap defcmp;
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] =
41 /* 0*/ "Red",
42 /* 1*/ "Green",
43 /* 2*/ "Blue",
44 /* 3*/ "Yellow",
45 /* 4*/ "Magenta",
46 /* 5*/ "Cyan",
47 /* 6*/ "FireBrick",
48 /* 7*/ "SpringGreen",
49 /* 8*/ "CornflowerBlue",
50 /* 9*/ "Khaki",
51 /*10*/ "Plum",
52 /*11*/ "Violet",
53 /*12*/ "DarkTurquoise",
54 /*13*/ "Gold",
55 /*14*/ "Orchid",
56 /*15*/ "Turquoise",
57 /*16*/ "Orange",
58 /*17*/ "OrangeRed",
59 /*18*/ "VioletRed",
60 /*19*/ "BlueViolet",
61 /*20*/ "SeaGreen",
62 /*21*/ "Pink",
63 /*22*/ "ForestGreen",
64 /*23*/ "SkyBlue",
65 /*24*/ "Coral",
66 /*25*/ "Wheat",
67 /*26*/ "GoldenRod",
68 /*27*/ "IndianRed",
69 /*28*/ "SpringGreen",
70 /*29*/ "CornflowerBlue",
71 /*30*/ "Thistle",
72 /*31*/ "Aquamarine",
73 /*32*/ "CadetBlue",
74 /*33*/ "LightSteelBlue",
75 /*34*/ "NavyBlue",
76 /*35*/ "SteelBlue",
77 /*36*/ "YellowGreen",
78 /*37*/ "DarkViolet",
79 /*38*/ "MediumSeaGreen",
80 /*39*/ "DarkSlateGray",
81 /*40*/ "LightGray",
82 /*41*/ "MediumVioletRed",
83 /*42*/ "Sienna",
84 /*43*/ "MediumAquamarine",
85 /*44*/ "MediumBlue",
86 /*45*/ "Navy",
87 /*46*/ "DarkOliveGreen",
88 /*47*/ "DarkGreen",
89 /*48*/ "DimGray",
90 /*49*/ "Tan",
91 /*50*/ "MediumTurquoise",
92 /*51*/ "DarkSlateBlue",
93 /*52*/ "Maroon",
94 /*53*/ "Gray",
95 /*54*/ "#303030",
97 /*55*/ "Black",
98 /*56*/ "#00aa00",
99 /*56*/ "#00ee00",
100 /*57*/ "#aa0000",
101 /*58*/ "#aaaaaa",
102 /*59*/ "#cccc00",
103 /*60*/ "#eeee00"
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'
120 /// args
121 /// +argc: number of commanline args
122 /// +argv: command line args
123 /// tags XWellEngine
124 XWellEngine::XWellEngine(int argc, char** argv):WellEngine(argc,argv)
126 int i;
127 char *dispchr=0;
128 for(i=1;i<argc;i++)
129 if((strcmp("-display",argv[i])==0 ||
130 strcmp("-d", argv[i])==0) && i+1<argc)
131 dispchr=argv[i+1];
132 if((disp=XOpenDisplay(dispchr))==NULL)
134 fprintf(stderr,
135 "%s: connection to X server failed on display %s.....\n",
136 argv[0],dispchr);
137 exit(1);
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);
148 init_imagengine();
149 init_mainwindow(argc,argv);
150 load_images();
151 init_colors();
154 //===========================================================================
155 /// global XWellEngine(argc,argv)
156 /// Destructor of class that incupsulates work with X window
157 /// tags XWellEngine
158 XWellEngine::~XWellEngine()
160 XCloseDisplay(disp);
161 disp=0;
164 //===========================================================================
165 /// global init_mainwindow(argc,argv)
166 /// create main game window and all other stuff around it
167 /// tags XWellEngine
168 void XWellEngine::init_mainwindow(int argc,char **argv)
170 char *winname="X Welltris "VERSION;
171 XSetWindowAttributes xswa;
172 XWindowAttributes xwinattr;
173 XGCValues gcv;
175 if((pxsh=XAllocSizeHints())==NULL)
177 fprintf(stderr,"xwelltris: Error allocating size hints\n");
178 exit(1);
181 pxsh->flags=(USSize | PSize | PMinSize | PMaxSize);
182 pxsh->height=mainh;
183 pxsh->width=mainl;
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");
195 exit(1);
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");
202 exit(1);
204 if(XStringListToTextProperty(&pch->res_name,1,&iname)==0)
206 fprintf(stderr,"xwelltris: Error creating TextProperty\n");
207 exit(1);
209 if((pxwmh=XAllocWMHints())==NULL)
211 fprintf(stderr,"welltris: Error allocating WMHints\n");
212 exit(0);
214 pxwmh->flags=(InputHint|StateHint);
215 pxwmh->input=True;
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,
226 ExposureMask |
227 FocusChangeMask |
228 StructureNotifyMask |
229 KeyPressMask |
230 ButtonPressMask |
231 PointerMotionMask |
232 ButtonReleaseMask |
233 FocusChangeMask);
234 wmDeleteWindow = XInternAtom(disp, "WM_DELETE_WINDOW", False);
235 XSetWMProtocols(disp, mainw, &wmDeleteWindow, 1);
236 XSetGraphicsExposures(disp,maingc,False);
239 //===========================================================================
240 /// global show_main()
241 /// show main window
242 /// tags XWellEngine
243 void XWellEngine::show_main()
245 XMapRaised(disp,mainw);
246 XFlush(disp);
249 //===========================================================================
250 /// global load_image(Images id, char* name)
251 /// Load image into memory and register it with given id for use
252 /// tags XWellEngine
253 bool XWellEngine::load_image(Images id, char* name)
255 char buf[L_MAXPATH];
257 if(id>=MAX_IMAGES)
258 return false;
260 find_full_path_for_file(name,buf);
261 image_pixmaps[id]=LoadPixmap(buf,F_AUTO,images[id].l,images[id].h,CMP_OWN);
262 images[id].id=id;
263 return true;
267 //===========================================================================
268 /// global screen_copy(Geo*)
269 /// copy part of image to the screen
270 /// tags XWellEngine
271 void XWellEngine::screen_copy(Geo *pgeo)
273 if(pgeo->im==imNone)
275 screen_clear(pgeo);
276 return;
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
286 /// tags XWellEngine
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
296 /// tags XWellEngine
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
310 /// tags XWellEngine
311 void XWellEngine::event_loop()
313 MouseEvent mev;
314 struct timezone tzone;
315 int count=0;
316 done_loop_var=false;
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();
329 if(XPending(disp))
331 dbgprintf(("Got xevent: %d for window 0x%x\n",xev.type,xev.xany.window));
332 XNextEvent(disp,&xev);
333 switch(xev.type)
335 case Expose:
336 dbgprintf(("Expose event\n"));
337 process_event_for_all(wEvent(eExpose,&xev));
338 break;
340 case KeyPress:
341 dbgprintf(("KeyPressed event\n"));
342 process_event_for_all(wEvent(eKeyPress,&xev));
343 break;
345 case ButtonPress:
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));
351 break;
353 case MotionNotify:
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));
359 break;
361 case ClientMessage:
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));
368 done_loop_var=true;
370 break;
372 case FocusOut:
373 dbgprintf(("FocusOut event\n"));
374 process_event_for_all(wEvent(eFocusOut));
375 break;
380 dbgprintf(("Exiting from event_loop\n"));
383 //===========================================================================
384 /// global wait_for_timers()
385 /// calculate delay and wait for events and timers
386 /// tags XWellEngine
387 int XWellEngine::wait_for_timers()
389 struct timeval delayt;
390 struct timezone tzone;
391 int ret=0;
392 fd_set writefd, exceptfd, readfd;
394 FD_ZERO(&writefd);
395 FD_ZERO(&exceptfd);
396 FD_ZERO(&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);
415 return ret;
418 //===========================================================================
419 /// global correct_to_real_time(struct timeval&)
420 /// corrects timval to real values
421 /// tags XWellEngine
422 void XWellEngine::correct_to_real_time(struct timeval& tv)
424 while (tv.tv_usec < 0)
426 tv.tv_sec --;
427 tv.tv_usec += MILLION;
429 while (tv.tv_usec >= MILLION)
431 tv.tv_sec ++;
432 tv.tv_usec -= MILLION;
437 //===========================================================================
438 /// global udelay(int msec)
439 /// Unix portable delay :)
440 /// tags XWellEngine
441 void XWellEngine::udelay(int msec)
443 struct timeval tout;
444 tout.tv_sec=0;
445 tout.tv_usec=msec;
446 select(0,0,0,0,&tout);
451 //===========================================================================
452 /// local init_colors()
453 /// allocate all nessesary colors
454 /// tags XWellEngine
455 void XWellEngine::init_colors()
457 XColor tmp;
458 int i;
460 colormap=im_get_colormap();
462 if(!colormap)
463 colormap=defcmp;
464 else
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;
483 if(colormap!=defcmp)
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];
505 } else
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
528 /// tags XWellEngine
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
537 /// tags XWellEngine
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
546 /// tags XWellEngine
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
555 /// tags XWellEngine
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
564 /// tags XWellEngine
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
573 /// tags XWellEngine
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
582 /// tags XWellEngine
583 WellBase* XWellEngine::new_well_base()
585 return new WellBase;
588 //===========================================================================
589 /// global new_well_image_font()
590 /// creates image font object - version for X Window
591 /// tags XWellEngine
592 WellImageFont* XWellEngine::new_well_image_font(Images id,
593 unsigned int ifl,
594 unsigned int ifh,
595 int idx, int idy)
597 return new XWellImageFont(id,ifl,ifh,idx,idy);