1 /*
2   XBlockOut a 3D Tetris
3 
4   Copyright (C) 1992,1993,1994,2001  Thierry EXCOFFIER
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 1, or (at your option)
9   any later version.
10 
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   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 
20   Contact: Thierry.EXCOFFIER@liris.univ-lyon1.fr
21 */
22 #include "bl.h"
23 #include "icone.h"
24 #include <stdio.h>
25 #include <X11/Xatom.h>
26 #include <X11/Xutil.h>
27 
28 #if HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
31 #ifdef HAVE_MALLOC_H
32 #include "malloc.h"
33 #endif
34 #if HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 
38 #if HAVE_STRING_H
39 #include <string.h>
40 #else
41 #include <strings.h>
42 #endif
43 
restorecolor(Display * d,int n,Colormap c1,Colormap c2)44 void restorecolor(Display *d, int n, Colormap c1, Colormap c2)
45 {
46   XColor *c ;
47   unsigned int i ;
48   unsigned long plane_mask ;
49   unsigned long *pixel ;
50 
51   c = (XColor *) malloc( n*sizeof(XColor) ) ;
52   pixel = (unsigned long*) malloc( n*sizeof(unsigned long) ) ;
53 
54   XAllocColorCells(d,c1,False,&plane_mask,0,pixel,n) ;
55 
56   for(i=0;i<n;i++)
57     if ( pixel[i] != (unsigned long)i )
58       {
59 	fprintf(stderr,"Future Problems... pixel[%ld]=%d\n", pixel[i],i);
60 	break ;
61       }
62 
63   for(i=0;i<n;i++) c[i].pixel = i ;
64 
65   XQueryColors(d,c2,c,n) ;
66 
67   for(i=0;i<n;i++) c[i].flags = DoRed|DoGreen|DoBlue ;
68 
69   XStoreColors(d,c1,c,n) ;
70 
71   free( (void*) c) ;
72   free( (void*) pixel) ;
73 }
74 
75 
76 
initwin(struct opt * opt,struct x * x)77 void initwin(struct opt *opt, struct x *x)
78 {
79   XSetWindowAttributes wa ;
80   XSizeHints sh ;
81   XTextProperty tp ;
82   char buf[LINE_LENGTH] ;
83 
84   x->icone = XCreateBitmapFromData(x->display,x->root,
85 				   icone_bits,icone_width,icone_height) ;
86 
87   if ( opt->buffering==1 || opt->buffering==3 || opt->buffering==4 )
88     {
89       if ( x->map_entries >= (opt->buffering!=3?16:32) &&
90 	   ( x->visual->class==PseudoColor || x->visual->class==GrayScale )
91            )
92 	{
93 	  opt->newmap = 1 ;
94 	}
95       else
96 	{
97 	  fprintf(stderr,"Can't make single buffering because :\n");
98 	  fprintf(stderr,"   Your display hasn't %d colors (only %ld)\n",
99 		  (opt->buffering!=3 ? 16: 32), x->map_entries);
100 	  fprintf(stderr,"   OR Colors cannot be changed (truecolor)\n");
101 	  fprintf(stderr,"\nTry to use the option '-visual 1'\n") ;
102 	  exit(1) ;
103 	}
104     }
105 
106   if ( opt->newmap )
107     {
108       if ( opt->verbose ) fprintf(stderr,"START newcolormap\n") ;
109       x->color1 = XCopyColormapAndFree(x->display,x->colormap) ;
110       if ( opt->verbose ) fprintf(stderr,"      Create OK\n") ;
111       restorecolor(x->display,(int)x->map_entries,
112 		   x->color1,x->colormap) ;
113       if ( opt->verbose ) fprintf(stderr,"      Colors OK\n") ;
114       if (opt->buffering==3)
115 	{
116 	  x->color2 = XCopyColormapAndFree(x->display,x->colormap) ;
117 	  restorecolor(x->display,(int)x->map_entries,
118 		       x->color2,x->colormap) ;
119 	  x->colormap = x->color1 ;
120 	  x->black_pixel = x->map_entries - 4*(opt->use_bw?2:8) ;
121 	  x->white_pixel = x->black_pixel + (opt->use_bw?2:8)-1 ;
122 	}
123       else { x->colormap = x->color1 ;
124       x->black_pixel = x->map_entries - 2*(opt->use_bw?2:8) ;
125       x->white_pixel = x->black_pixel + (opt->use_bw?2:8)-1 ;
126       }
127       if ( opt->verbose ) fprintf(stderr,"END   newcolormap\n") ;
128     }
129 
130   if ( opt->verbose )
131     {
132       fprintf(stderr,"display=%p\n",x->display);
133       fprintf(stderr,"screen=%d\n",x->screen);
134       fprintf(stderr,"root=%lu\n",x->root);
135       fprintf(stderr,"depth=%d\n",x->depth);
136       fprintf(stderr,"colormap=%lu\n",x->colormap);
137       fprintf(stderr,"DISPLAY open OK\n");
138     }
139 
140   x->posx = 0 ;
141   x->posy = 0 ;
142 
143   if ( opt->geometry[0]!='\0' )
144     {
145       MyXParseGeometry(x->display,x->screen,opt->geometry,&x->posx,&x->posy,
146 		       (unsigned int*)&x->dimx,(unsigned int*)&x->dimy) ;
147     }
148 
149   wa.event_mask = KeyPressMask|KeyReleaseMask|ExposureMask|StructureNotifyMask
150     |FocusChangeMask ;
151   wa.background_pixel = x->black_pixel ;
152 
153   x->window = XCreateWindow(
154 			    x->display,
155 			    x->root,
156 			    x->posx,x->posy,
157 			    (unsigned int)x->dimx,(unsigned int)x->dimy,
158 			    0,
159 			    x->depth,
160 			    InputOutput,
161 			    x->visual,
162 			    CWEventMask|CWBackPixel,
163 			    &wa);
164 
165   XSetWindowColormap(x->display,x->window,x->colormap) ;
166 
167   gethostname(buf,LINE_LENGTH) ;
168   tp.value = (unsigned char*)buf ;
169   tp.encoding = XA_STRING ;
170   tp.format = 8 ;
171   tp.nitems = strlen((char*)tp.value) ;
172   XSetWMClientMachine(x->display,x->window,&tp) ;
173 
174   sh.flags = PResizeInc|PBaseSize ;
175   if ( opt->geometry[0]!='\0' ) sh.flags |= PPosition ;
176 
177   sh.width_inc = 2 ;      /* Size must always be ODD in X and Y */
178   sh.height_inc = 2 ;
179   sh.base_width = 3 ;
180   sh.base_height = 3 ;
181   sh.x = x->posx ;
182   sh.y = x->posy ;
183   XSetWMNormalHints( x->display,x->window,&sh ) ;
184 
185 
186   x->back = 0 ;
187   x->work = 0 ;
188   XMapWindow( x->display,x->window) ;
189 }
190 
191 /* Create the argument string, to set window properties */
192 /* This function is call when a change arise */
193 
194 #define ADDARG(X) { sprintf(pc,"%s",X) ; argv[i++] = pc ; pc += strlen(pc)+1 ; }
195 
setargs(struct bl * bl)196 void setargs(struct bl *bl)
197 {
198   char *argv[LINE_LENGTH] ;
199   char tt[10*LINE_LENGTH] ;   /* Text of the parameters */
200   char tmp[LINE_LENGTH] ;
201   char *pc ;
202   int i ;
203   Window gar ;
204   int x,y ;
205   unsigned int nbc ;
206   unsigned int dx,dy,gar2,gar3 ;
207   XTextProperty tp,tp2 ;
208   XWMHints wh ;
209   Window w,root,father,*childrens[1] ;
210 
211   i = 0 ;
212   pc = tt ;
213 
214   ADDARG(bl->progname) ;
215 
216   if ( bl->x.window )
217     {
218       XQueryTree(bl->x.display,bl->x.window,&root,&father,childrens,&nbc) ;
219       XGetGeometry(bl->x.display,bl->x.window,&gar,&x,&y,&dx,&dy,&gar2,&gar3) ;
220       XTranslateCoordinates(bl->x.display,father,bl->x.root,0,0,&x,&y,&w) ;
221       ADDARG("-geometry") ;
222       sprintf(tmp,"%dx%d+%d+%d",dx,dy,x,y) ;
223       ADDARG(tmp) ;
224     }
225 
226   if ( bl->menu.window )
227     {
228       XQueryTree(bl->x.display,bl->menu.window,&root,&father,childrens,&nbc) ;
229       XGetGeometry(bl->x.display,bl->menu.window,&gar,&x,&y,&dx,&dy,&gar2,&gar3) ;
230       XTranslateCoordinates(bl->x.display,father,bl->x.root,0,0,&x,&y,&w) ;
231       ADDARG("-menugeometry") ;
232       sprintf(tmp,"%dx%d+%d+%d",dx,dy,x,y) ;
233       ADDARG(tmp) ;
234     }
235 
236   if ( bl->x.wscore )
237     {
238       XQueryTree(bl->x.display,bl->x.wscore,&root,&father,childrens,&nbc) ;
239       XGetGeometry(bl->x.display,bl->x.wscore,&gar,&x,&y,&dx,&dy,&gar2,&gar3) ;
240       XTranslateCoordinates(bl->x.display,father,bl->x.root,0,0,&x,&y,&w) ;
241       ADDARG("-scoregeometry") ;
242       sprintf(tmp,"%dx%d+%d+%d",dx,dy,x,y) ;
243       ADDARG(tmp) ;
244     }
245 
246   if ( bl->menu.zoo )
247     {
248       XQueryTree(bl->x.display,bl->menu.zoo,&root,&father,childrens,&nbc) ;
249       XGetGeometry(bl->x.display,bl->menu.zoo,&gar,&x,&y,&dx,&dy,&gar2,&gar3) ;
250       XTranslateCoordinates(bl->x.display,father,bl->x.root,0,0,&x,&y,&w) ;
251       ADDARG("-zoogeometry") ;
252       sprintf(tmp,"%dx%d+%d+%d",dx,dy,x,y) ;
253       ADDARG(tmp) ;
254     }
255 
256   if ( bl->opt.smooth )		ADDARG("-smooth") ;
257   if ( bl->menu.showzoo )		ADDARG("-zoo") ;
258   if ( bl->menu.showscore )	ADDARG("-score") ;
259   if ( bl->opt.newmap )		ADDARG("-colormap") ;
260   if ( bl->opt.presskey )		ADDARG("-presskey") ;
261   if ( bl->opt.use_bw )		ADDARG("-bw") ;
262   if ( bl->opt.clearline )	ADDARG("-clearline") ;
263   if ( bl->opt.mode==TRAINING )	ADDARG("-training") ;
264   if ( bl->bloc.nextpiece )	ADDARG("-shownext") ;
265 
266   ADDARG("-draw") ;	sprintf(tmp,"%d",bl->opt.drawmode) ;	ADDARG(tmp) ;
267   ADDARG("-linewidth") ;	sprintf(tmp,"%d",bl->opt.linewidth) ;	ADDARG(tmp) ;
268   ADDARG("-buffer") ;	sprintf(tmp,"%d",bl->opt.buffering) ;	ADDARG(tmp) ;
269   ADDARG("-volume") ;	sprintf(tmp,"%d",bl->opt.volume) ;	ADDARG(tmp) ;
270   ADDARG("-land") ;	sprintf(tmp,"%d",bl->opt.land) ;	ADDARG(tmp) ;
271   ADDARG("-x") ;		sprintf(tmp,"%d",bl->opt.wx) ;		ADDARG(tmp) ;
272   ADDARG("-y") ;		sprintf(tmp,"%d",bl->opt.wy) ;		ADDARG(tmp) ;
273   ADDARG("-z") ;		sprintf(tmp,"%d",bl->opt.wz) ;		ADDARG(tmp) ;
274   ADDARG("-level") ;	sprintf(tmp,"%d",bl->opt.level) ;	ADDARG(tmp) ;
275   ADDARG("-buttonheight");sprintf(tmp,"%d",bl->opt.button_height);ADDARG(tmp) ;
276   ADDARG("-keyboard") ;	sprintf(tmp,"%d",bl->opt.keyboard) ;	ADDARG(tmp) ;
277   ADDARG("-color") ;	sprintf(tmp,"%d",bl->opt.backcolor) ;	ADDARG(tmp) ;
278   ADDARG("-bloctype") ;	sprintf(tmp,"%d",bl->bloc.typepiece) ;	ADDARG(tmp) ;
279   ADDARG("-time_to_demo");sprintf(tmp,"%d",bl->opt.time_to_demo);	ADDARG(tmp) ;
280   ADDARG("-eyedistance"); sprintf(tmp,"%g",bl->opt.eye_distance);	ADDARG(tmp) ;
281   if ( bl->opt.keyboard==0 )
282     {
283       ADDARG("-keytable") ;
284       sprintf(tmp,"%s",bl->opt.userkey) ;
285       ADDARG(tmp) ;
286     }
287   ADDARG("-font") ;	ADDARG(bl->opt.thefont) ;
288   ADDARG("-bigfont") ;	ADDARG(bl->opt.thefont2) ;
289 
290   sprintf(tmp,"XBlockOut %s",XBLVERSION) ;
291   tp.value = (unsigned char*)tmp ;
292   tp.encoding = XA_STRING ;
293   tp.format = 8 ;
294   tp.nitems = strlen((char*)tp.value) ;
295 
296   tp2.value = (unsigned char*)"XBlockOut" ;
297   tp2.encoding = XA_STRING ;
298   tp2.format = 8 ;
299   tp2.nitems = strlen((char*)tp2.value) ;
300 
301   wh.flags = IconPixmapHint ;
302   wh.icon_pixmap = bl->x.icone ;
303 
304   XSetWMProperties(bl->x.display,bl->x.window,&tp,&tp2,
305 		   argv,i,
306 		   NULL,&wh,NULL ) ;
307   /*
308     { int j ; for(j=0;j<i;j++) printf("%s ",argv[j]) ; printf("\n") ; }
309   */
310 }
311 
312 /* Compute window position, WHY THIS FUNCTION IS NOT IN XLIB? */
313 /*			 I have found it (too late) thanks to Brian V. SMITH */
314 
MyXParseGeometry(Display * d,int s,char * c,int * x,int * y,unsigned int * dx,unsigned int * dy)315 void MyXParseGeometry(Display *d, int s, char *c, int *x, int *y, unsigned int *dx, unsigned int *dy)
316 {
317   *x = 0 ;
318   *y = 0 ;
319   *dy = 0 ;
320 
321   *dx = atoi(c) ;
322   while( *c && *c!='x' ) c++ ;
323   if ( *c==0 ) return ;
324   c++ ;
325   *dy = atoi(c) ;
326   while( *c && *c!='+' && *c!='-' ) c++ ;
327   if ( *c==0 ) return ;
328   if ( *c=='+' ) *x = atoi(c+1) ;
329   else *x = DisplayWidth(d,s) - atoi(c+1) - *dx ;
330   c++ ;
331   if ( *c==0 ) return ;
332   if ( *c=='-' || *c=='+' ) c++ ;
333   while( *c && *c!='+' && *c!='-' ) c++ ;
334   if ( *c==0 ) return ;
335   if ( *c=='+' ) *y = atoi(c+1) ;
336   else *y = DisplayHeight(d,s) - atoi(c+1) - *dy ;
337 }
338