1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 /*
25  * HISTORY
26  */
27 #ifdef REV_INFO
28 #ifndef lint
29 static char rcsid[] = "$XConsortium: earth.c /main/5 1995/07/14 09:41:16 drk $"
30 #endif
31 #endif
32 /***************************************************************************
33  *  earth.
34  *   This demo illustrates the use of the R4 shape extension and Motif.
35  *   Author: Daniel Dardailler.
36  *
37  *   Effects by: Andrew deBlois
38  ***************************************************************************/
39 #define APP_CLASS "XmdEarth"
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <math.h>
44 #include <Xm/XmAll.h>
45 #include <X11/extensions/shape.h> /* R4 header required */
46 #include "terre.xbm"               /* can cause compilation problem with
47 				      some gcc version, due of the size of
48 				      the bitmap array */
49 /*** Application default stuff */
50 typedef struct {
51   int          speed;
52   XtIntervalId timeoutID;
53   Pixel        foreground ;
54   Pixel        background ;
55   Boolean      persue;
56 } ApplicationData, *ApplicationDataPtr;
57 ApplicationData AppData;
58 
59 #define PERSUE_ON_VALUE   94
60 #define PERSUE_OFF_VALUE -94
61 #define XmNspeed  "speed"
62 #define XmCSpeed  "Speed"
63 #define XmNpersue "persue"
64 #define XmCPersue "Persue"
65 static XtResource resources[] = {
66     {
67 	XmNspeed, XmCSpeed, XmRInt, sizeof(int),
68 	XtOffsetOf (ApplicationData, speed),
69 	XmRImmediate, (caddr_t) 50 },
70 
71     /* overwrite the default colors (doing that will lead to weird
72        behavior if you specify -fg or -bg on the command line, but
73        I really don't care, it's easier to use the standard names) */
74     {
75 	XmNforeground, XmCForeground, XmRPixel, sizeof (Pixel),
76 	XtOffsetOf (ApplicationData, foreground),
77 	XmRString, "brown"},
78     {
79 	XmNbackground, XmCBackground, XmRPixel, sizeof (Pixel),
80 	XtOffsetOf (ApplicationData, background),
81 	XmRString, "turquoise"},
82     {
83         XmNpersue, XmCPersue, XmRBoolean, sizeof (Boolean),
84 	XtOffsetOf (ApplicationData, persue),
85 	XmRImmediate, (caddr_t) 0}
86 };
87 
88 static XrmOptionDescRec options[] = {
89     {"-speed", "*speed", XrmoptionSepArg, NULL},
90 } ;
91 /*** end of Application default stuff */
92 
93 static XtAppContext app_con;
94 static Widget       toplevel, draw ;
95 static Pixmap       pterre ;
96 static GC           gc ;
97 static int          n ;
98 
99 static void    Syntax() ;
100 static void    input_callback();
101 static void    expose_callback();
102 static void    speed_callback() ;
103 static void    NextBitmap ();
104 
delayInterval(speed)105 int delayInterval (speed)
106 /**************************/
107 int speed;
108 {
109   double maxDelay = 1000.0;
110   double val      = (double)(abs(speed));
111 
112 
113   return (int)( maxDelay / val );
114 }
115 
116 char *fallback[] = {
117     /* too bad there is no real converter for that stuff! */
118   "*mwmDecorations:  0",
119   "*XmDialogShell*mwmDecorations: 1",
120   NULL
121 };
122 
123 
main(argc,argv)124 int main(argc, argv) int argc; char **argv ;
125 /**************************************/
126 {
127     Arg args[10] ;
128     Cardinal n;
129 
130     XGCValues values;
131     XtGCMask  valueMask;
132     Pixmap shape_mask ;
133     XGCValues	xgcv;
134     GC shapeGC ;
135     int shape_event_base,
136         shape_error_base; /* just used as dummy parameters */
137 
138     /* Initialize, using my options */
139     toplevel = XtAppInitialize(&app_con, APP_CLASS,
140 			       options, XtNumber(options),
141 			       &argc, argv, fallback, NULL, 0);
142 
143     /* if a bad option was reached, XtAppInitialize should let it */
144     if (argc > 1) Syntax(argv[0]) ;
145 
146     /* read the programmer app default */
147     XtGetApplicationResources(toplevel,
148 			      (XtPointer)&AppData,
149 			      resources,
150 			      XtNumber(resources),
151 			      NULL,
152 			      0);
153 
154     /* create a fixed size drawing area + callback for dialog popup */
155     n = 0 ;
156     XtSetArg(args[n], XmNwidth, 64);  n++ ;
157     XtSetArg(args[n], XmNheight, 64); n++ ;
158     draw = XmCreateDrawingArea (toplevel, "draw", args, n);
159     XtManageChild(draw);
160     XtAddCallback(draw,XmNinputCallback,(XtCallbackProc)input_callback,NULL);
161     XtAddCallback(draw,XmNexposeCallback,(XtCallbackProc)expose_callback,NULL);
162 
163     XtRealizeWidget(toplevel);
164 
165     /* create the big bitmap on the server */
166     pterre = XCreateBitmapFromData (XtDisplay(toplevel),XtWindow(toplevel),
167 				    (char *)terre_bits,terre_width,terre_height) ;
168 
169     /* create a GC for the earth colors */
170     valueMask = GCForeground | GCBackground ;
171     values.foreground = AppData.foreground ;
172     values.background = AppData.background ;
173     gc = XtGetGC ((Widget) toplevel, valueMask , &values);
174 
175     /* if there is a shape extension, use it */
176     if (XShapeQueryExtension (XtDisplay (draw),
177 			      &shape_event_base,
178 			      &shape_error_base)) {
179 	shape_mask = XCreatePixmap (XtDisplay (draw), XtWindow (draw),
180 				    64, 64, 1);
181 	shapeGC = XCreateGC (XtDisplay (draw), shape_mask, 0, &xgcv);
182 
183 	/* erase the pixmap as a mask */
184 	XSetForeground (XtDisplay (draw), shapeGC, 0);
185 	XFillRectangle (XtDisplay (draw), shape_mask, shapeGC, 0,0, 64,64);
186 	XSetForeground (XtDisplay (draw), shapeGC, 1);
187 	/* draw the bounding/clipping shape : a circle */
188 	XFillArc(XtDisplay (draw), shape_mask, shapeGC, 0,0, 64,64, 0,23040);
189 	/* shape the parent for event managing and the widget for drawing */
190 	XShapeCombineMask (XtDisplay (toplevel), XtWindow (toplevel),
191 			   ShapeBounding, 0,0, shape_mask, ShapeSet);
192 	XShapeCombineMask (XtDisplay (draw), XtWindow (draw),
193 			   ShapeClip, 0,0, shape_mask, ShapeSet);
194 	XFreePixmap (XtDisplay (draw), shape_mask);
195 	/* don't ask me why I use alternatively draw and toplevel as
196 	   a parameter of XtDisplay, it doesn't matter at all */
197     } else {
198 	fprintf(stderr,
199 		"Bad news: there is no shape extension on your server...\n");
200     }
201 
202     /* animation done in background */
203     AppData.timeoutID = XtAppAddTimeOut(app_con,
204 					delayInterval(AppData.speed),
205 					NextBitmap, NULL);
206 
207     XtAppMainLoop(app_con);
208 
209     return 0;    /* make compiler happy */
210 }
211 
NextBitmap(client_data,id)212 static void NextBitmap (client_data, id)
213 /****************************************************/
214 XtPointer client_data;
215 XtIntervalId *id;
216 {
217 
218 
219   AppData.timeoutID = 0;
220 
221   if (AppData.speed != 0)
222     {
223       if (XtIsRealized(draw))
224 	{
225 	  Position x, y;
226 
227 	  if (AppData.speed > 0) n = (n>28)?0:n+1;
228 	  else                   n = (n>0)?n-1:29;
229 
230 	  XCopyPlane (XtDisplay(draw), pterre, XtWindow(draw), gc,
231 		      0, 64*n, 64, 64, 0, 0, 1);
232 
233 	  if (AppData.persue)
234 	    {
235 	      Position     x, y;
236 	      int          mx, my, ji;
237 	      Window       jw;
238 	      unsigned int jk;
239 
240 	      XtVaGetValues(toplevel, XmNx, &x, XmNy, &y, NULL);
241 	      XQueryPointer(XtDisplay(toplevel), XtWindow(toplevel),
242 			    &jw, &jw, &mx, &my, &ji, &ji, &jk);
243 	      XtVaSetValues(toplevel,XmNx, x+((mx-x)/10),XmNy,
244 			    y+((my-y)/10),NULL);
245 	    }
246 	}
247 
248       AppData.timeoutID = XtAppAddTimeOut(app_con,
249 					  delayInterval(AppData.speed),
250 					  NextBitmap, NULL);
251     }
252 }
253 
254 
expose_callback(widget,tag,callback_data)255 static void expose_callback(widget, tag, callback_data)
256 /****************************************************/
257 Widget widget ;
258 XtPointer tag ;
259 XtPointer callback_data ;
260 {
261     XCopyPlane (XtDisplay(draw), pterre, XtWindow(draw), gc,
262 		0, 64*n, 64, 64, 0, 0, 1);
263 }
264 
input_callback(widget,tag,callback_data)265 static void input_callback(widget, tag, callback_data)
266 /****************************************************/
267 Widget widget ;
268 XtPointer tag ;
269 XtPointer callback_data ;
270 {
271   XmDrawingAreaCallbackStruct * dacb = (XmDrawingAreaCallbackStruct *) callback_data ;
272   static Widget speed_dialog = NULL ;
273   Widget speed_scale ;
274   Arg args[15] ;
275   Cardinal n;
276   XmString title_string;
277 
278 
279   if ((dacb->event->type == ButtonPress) &&
280        (dacb->event->xbutton.button == Button3))
281     {
282       if (speed_dialog == NULL) {
283 	speed_dialog = XmCreateFormDialog(toplevel,
284 					  "Speed control",
285 					  NULL, 0) ;
286 	n = 0 ;
287 	title_string = XmStringGenerate("rotation speed", NULL,
288 						     XmCHARSET_TEXT, NULL);
289 	XtSetArg(args[n], XmNtitleString,     title_string);  n++ ;
290 	XtSetArg(args[n], XmNshowValue,       True); n++ ;
291 	XtSetArg(args[n], XmNvalue,           AppData.speed); n++ ;
292 	XtSetArg(args[n], XmNorientation,     XmHORIZONTAL); n++ ;
293 	XtSetArg(args[n], XmNleftAttachment,  XmATTACH_POSITION); n++;
294 	XtSetArg(args[n], XmNleftPosition,    10); n++;
295 	XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
296 	XtSetArg(args[n], XmNrightPosition,   90); n++;
297 	XtSetArg(args[n], XmNminimum,         -100); n++;
298 	XtSetArg(args[n], XmNmaximum,         100); n++;
299 	speed_scale = XmCreateScale(speed_dialog,
300 				    "speed_scale",
301 				    args, n) ;
302 	XtAddCallback(speed_scale,XmNdragCallback,
303 		      (XtCallbackProc)speed_callback,NULL);
304 	XtAddCallback(speed_scale,XmNvalueChangedCallback,
305 		      (XtCallbackProc)speed_callback,NULL);
306 	XtManageChild(speed_scale);
307       }
308 
309       XtManageChild(speed_dialog);
310       if (AppData.speed == PERSUE_ON_VALUE)  AppData.persue = TRUE;
311         else
312       if (AppData.speed == PERSUE_OFF_VALUE) AppData.persue = FALSE;
313     }
314 }
315 
316 
speed_callback(widget,tag,callback_data)317 static void speed_callback(widget, tag, callback_data)
318 /******************************************************/
319 Widget widget ;
320 XtPointer tag ;
321 XtPointer callback_data ;
322 {
323   XmScaleCallbackStruct * scb =
324     (XmScaleCallbackStruct *) callback_data ;
325 
326 
327   if ((AppData.speed == 0) && (scb->value != 0))
328     {
329       AppData.speed = scb->value;
330       if (AppData.timeoutID != 0) XtRemoveTimeOut(AppData.timeoutID);
331       XtAppAddTimeOut(app_con, delayInterval(AppData.speed), NextBitmap, NULL);
332     }
333   else
334     AppData.speed = scb->value ;
335 }
336 
337 
Syntax(com)338 static void Syntax(com) char * com ;
339 /**********************************/
340 {
341     fprintf(stderr, "%s understands all standard Xt options, plus:\n",com);
342     fprintf(stderr, "       -speed:    -100,100  (earth rotation speed)\n");
343 }
344 
345 
346