1 /* mxp.c - Mandelbrot Explorer (main program and X11 setup)
2  *
3  * Released under version 2 of the Gnu Public License.
4  * By Chris Brady, cbrady@sgi.com
5  */
6 
7 #include <X11/Xlib.h>
8 #include <X11/Intrinsic.h>
9 #include <X11/StringDefs.h>
10 #include <X11/Xaw/Cardinals.h>
11 #include <X11/Xaw/Label.h>
12 #include <X11/Xaw/Command.h>
13 #include <X11/Xaw/Repeater.h>
14 #include <X11/Xaw/Simple.h>
15 #include <X11/Xaw/Paned.h>
16 #include <X11/Xaw/Box.h>
17 #include <X11/Xaw/AsciiText.h>
18 #include <X11/Shell.h>
19 #include <X11/cursorfont.h>
20 #include <X11/bitmaps/xlogo11>
21 #include "mxp.h"
22 #ifdef XPM
23 #include <X11/xpm.h>
24 #include "icon.xpm"
25 #else
26 #include "icon.xbm"
27 #endif
28 #ifdef MPI
29 #include <mpi.h>
30 #endif
31 
32 /* externals from menu.c */
33 extern void make_menus();
34 extern struct menud *get_menu();
35 
36 /* externals from colors.c */
37 extern Colormap cmap;
38 extern int colors;
39 extern int reserved;
40 extern void init_cmap();
41 extern void setup_cmap();
42 extern void color_inc();
43 extern void color_dec();
44 extern void bias_inc();
45 extern void bias_dec();
46 
47 /* externals from file.c */
48 extern struct setup set;
49 extern void read_rc_file();
50 extern void filename_cb();
51 extern void pop_down();
52 extern char fname[];
53 
54 /* externals from mandel.c */
55 extern void mooz();
56 extern void redo();
57 extern void decrement();
58 extern void increment();
59 
60 /* externals from draw.c */
61 void create_draw();
62 void create_images();
63 
64 /* externals from anim.c */
65 void make_anim_popup();
66 
67 void command_done();
68 void close_stats();
69 void show_stats();
70 void set_wm_hints();
71 void quit();
72 
73 XtAppContext ctx;
74 Widget toplevel;
75 Widget command;
76 Widget status_pu, stats_btn;
77 Widget st_time, st_pct, st_pixsec, st_pixels, st_mag;
78 Widget st_ux, st_uy, st_lx, st_ly, st_cx, st_cy, st_size, st_mflops;
79 Widget iter_label, error_pu, errorm;
80 Widget mag_label, color_label, file_popup, file_text;
81 Cursor crosshair_xcr;
82 Cursor watch_xcr;
83 Cursor hand_xcr;
84 Dimension wwidth;
85 Dimension wheight;
86 Pixmap marker;
87 Pixmap icon_pixmap;
88 Pixmap icon_shape;
89 Pixel black_pix;
90 Pixel def_bg;
91 short depth;
92 int stats_flag;
93 #ifdef MPI
94 int mpi_rank;
95 int mpi_size;
96 #endif
97 
98 static String fallback[] = {
99 	"*background:                gray",
100 	"*Label.background:          lightskyblue",
101 	"*Command.background:        slateblue3",
102 	"*Command.foreground:        white",
103 	"*Repeater.background:       slateblue3",
104 	"*Repeater.foreground:       white",
105 	"*Toggle.background:         slateblue3",
106 	"*Toggle.foreground:         white",
107 	"*MenuButton.background:     slateblue3",
108 	"*MenuButton.foreground:     white",
109 	"*SimpleMenu.background:     turquoise",
110 	NULL
111 };
112 
113 String text_trans = "<Key>Return: filecb()";
114 static XtActionsRec acts[] = {
115         { "filecb", filename_cb }
116 };
117 
main(int argc,char ** argv)118 int main(int argc, char **argv) {
119 	Display *dp;
120 	int i;
121 	Arg argies[10];
122 	Widget temp;
123 	Widget button, command;
124 
125 #ifdef MPI
126 	MPI_Init( &argc, &argv);
127 	MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
128 	if (mpi_rank != 0) {
129 		sched();
130 	}
131 	MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
132 	if (mpi_size == 1) {
133 		printf("FATAL: MXP must be run with 2 or more threads when compiled with MPI suport.\n");
134 		exit(1);
135 	}
136 #endif
137 
138 	/*
139 	 * Create top level widget
140 	 */
141 	toplevel = XtAppInitialize(&ctx, "Mxp", NULL,
142 	    0, &argc, argv, fallback, NULL, 0);
143 
144 	dp = XtDisplay(toplevel);
145 	black_pix = BlackPixel(dp, DefaultScreen(dp));
146 	depth = DisplayPlanes(dp,DefaultScreen(dp));
147 
148 	marker = XCreateBitmapFromData(dp,
149 		RootWindowOfScreen(XtScreen(toplevel)),
150 		xlogo11_bits, xlogo11_width, xlogo11_height);
151 	i = 0;
152 	XtSetArg(argies[i], XtNbackground, &def_bg); i++;
153         XtGetValues(toplevel, argies, i);
154 	crosshair_xcr = XCreateFontCursor(dp, XC_crosshair);
155 	watch_xcr = XCreateFontCursor(dp, XC_watch);
156 	hand_xcr = XCreateFontCursor(dp, XC_hand2);
157 
158 #ifdef XPM
159 	XpmCreatePixmapFromData(dp, RootWindowOfScreen(XtScreen(toplevel)),
160 		icon_xpm, &icon_pixmap, &icon_shape, NULL);
161 #else
162 	icon_pixmap = XCreateBitmapFromData(dp,
163 		RootWindowOfScreen(XtScreen(toplevel)),
164 		icon_bits, icon_width, icon_height);
165 #endif
166 
167 	/*
168 	 * Read parameters from rc file (if one exists)
169 	 */
170 	read_rc_file();
171 	wwidth = set.win_wid;
172 	wheight = set.win_hgt;
173 
174 	/*
175 	 * Create a private colormap
176 	 */
177 	init_cmap(dp);
178 	reserved = 0;
179 
180 	/*
181 	 * Create a paned widget to hold all of the command and status
182 	 * buttons / labels
183 	 */
184 	i = 0;
185 	XtSetArg( argies[i], XtNwidth, (XtArgVal) 170); i++;
186 	command = XtCreateManagedWidget("command", panedWidgetClass, toplevel,
187 		argies, i);
188 
189 	/*
190 	 * Create menus (File, Size and Color Scheme)
191 	 */
192 	make_menus(command);
193 
194 	/*
195 	 * Create animation setup popup
196 	 */
197 	make_anim_popup();
198 
199 	/*
200 	 * Creat a popup to get a filename
201 	 */
202 	file_popup = XtCreatePopupShell("filename", transientShellWidgetClass,
203 		toplevel, NULL, 0);
204         temp = XtCreateManagedWidget("filebox", boxWidgetClass,
205                 file_popup, NULL, 0);
206         i = 0;
207         XtSetArg(argies[i], XtNborderWidth, 0); i++;
208         XtSetArg(argies[i], XtNbackground, def_bg); i++;
209         XtSetArg(argies[i], XtNlabel, "File Name:"); i++;
210         XtCreateManagedWidget("file_label", labelWidgetClass,
211                 temp, argies, i);
212         i = 0;
213         XtSetArg(argies[i], XtNuseStringInPlace, TRUE); i++;
214         XtSetArg(argies[i], XtNtype, XawAsciiString); i++;
215         XtSetArg(argies[i], XtNlength, MAX_NAME); i++;
216         XtSetArg(argies[i], XtNstring, fname); i++;
217         XtSetArg(argies[i], XtNeditType, XawtextEdit); i++;
218         file_text = XtCreateManagedWidget("filetext", asciiTextWidgetClass,
219                 temp, argies, i);
220         button = XtCreateManagedWidget("OK", commandWidgetClass,
221                 temp, NULL, 0);
222 	XtAddCallback(button, XtNcallback, filename_cb, (XtPointer)0);
223         button = XtCreateManagedWidget("Cancel", commandWidgetClass,
224                 temp, NULL, 0);
225 	XtAddCallback(button, XtNcallback, pop_down, (XtPointer)file_popup);
226 
227 	/*
228 	 * Creat a popup to report errors
229 	 */
230 	error_pu = XtCreatePopupShell("error_pu", transientShellWidgetClass,
231 		toplevel, NULL, 0);
232 	i = 0;
233 	temp = XtCreateManagedWidget("error", boxWidgetClass,
234 		error_pu, argies, i);
235 	errorm = XtCreateManagedWidget("Error", labelWidgetClass, temp,
236 		argies, i);
237 	button = XtCreateManagedWidget("OK", commandWidgetClass,
238 	    temp, argies, i);
239 	XtAddCallback(button, XtNcallback, pop_down, (XtPointer)error_pu);
240 
241 	/*
242 	 * Creat a popup to display status information
243 	 */
244 	i = 0;
245         XtSetArg( argies[i], XtNtransient, (XtArgVal) FALSE); i++;
246 	status_pu = XtCreatePopupShell("Statistics", transientShellWidgetClass,
247 		toplevel, argies, i);
248 	i = 0;
249 	XtSetArg( argies[i], XtNwidth, (XtArgVal) 170); i++;
250 	temp = XtCreateManagedWidget("status", panedWidgetClass, status_pu,
251 		argies, i);
252 	i = 0;
253 	XtSetArg( argies[i], XtNshowGrip, (XtArgVal)FALSE); i++;
254 	XtSetArg( argies[i], XtNborderWidth, (XtArgVal) 0); i++;
255 	XtSetArg( argies[i], XtNbackground, (XtArgVal) def_bg); i++;
256 	button = XtCreateManagedWidget("Close", commandWidgetClass, temp,
257 		argies, i);
258 	XtSetArg( argies[i], XtNjustify, (XtArgVal) XtJustifyLeft); i++;
259 	st_time = XtCreateManagedWidget("Time", labelWidgetClass, temp,
260 		argies, i);
261 	st_pct = XtCreateManagedWidget("Percent", labelWidgetClass, temp,
262 		argies, i);
263 	st_pixsec = XtCreateManagedWidget("Pixsec", labelWidgetClass, temp,
264 		argies, i);
265 	st_mflops = XtCreateManagedWidget("Mflops", labelWidgetClass, temp,
266 		argies, i);
267 	st_mag = XtCreateManagedWidget("Zoom", labelWidgetClass, temp,
268 		argies, i);
269 	st_size = XtCreateManagedWidget("Size", labelWidgetClass, temp,
270 		argies, i);
271 	st_pixels = XtCreateManagedWidget("Pixels", labelWidgetClass, temp,
272 		argies, i);
273 	st_cx = XtCreateManagedWidget("X", labelWidgetClass, temp,
274 		argies, i);
275 	st_cy = XtCreateManagedWidget("Y", labelWidgetClass, temp,
276 		argies, i);
277 	st_ux = XtCreateManagedWidget("UX", labelWidgetClass, temp,
278 		argies, i);
279 	st_uy = XtCreateManagedWidget("UY", labelWidgetClass, temp,
280 		argies, i);
281 	st_lx = XtCreateManagedWidget("LX", labelWidgetClass, temp,
282 		argies, i);
283 	st_ly = XtCreateManagedWidget("LY", labelWidgetClass, temp,
284 		argies, i);
285 	XtAddCallback(button, XtNcallback, close_stats, 0);
286 
287 	/*
288 	 * Create buttons and labels that are in the command box
289 	 */
290 	i = 0;
291 	XtSetArg( argies[i], XtNshowGrip, (XtArgVal)FALSE); i++;
292 	stats_btn = XtCreateManagedWidget("Statistics", commandWidgetClass,
293 	    command, argies, i);
294 	XtAddCallback(stats_btn, XtNcallback, show_stats, 0);
295 	i = 0;
296 	XtSetArg( argies[i], XtNshowGrip, (XtArgVal)FALSE); i++;
297 	button = XtCreateManagedWidget("Unzoom", commandWidgetClass,
298 	    command, argies, i);
299 	XtAddCallback(button, XtNcallback, mooz, 0);
300 	i = 0;
301 	XtSetArg( argies[i], XtNshowGrip, (XtArgVal)FALSE); i++;
302 	button = XtCreateManagedWidget("Redo", commandWidgetClass,
303 	    command, argies, i);
304 	XtAddCallback(button, XtNcallback, redo, 0);
305 
306 	i = 0;
307 	XtSetArg( argies[i], XtNshowGrip, (XtArgVal)FALSE); i++;
308 	temp = XtCreateManagedWidget("iter", boxWidgetClass, command,
309 		argies, i);
310 	i = 0;
311 	XtSetArg( argies[i], XtNborderWidth, (XtArgVal) 0); i++;
312 	XtSetArg( argies[i], XtNbackground, (XtArgVal) def_bg); i++;
313 	XtCreateManagedWidget("Iter", labelWidgetClass, temp, argies, i);
314 	i = 0;
315 	XtSetArg( argies[i], XtNinitialDelay, (XtArgVal) 350); i++;
316 	XtSetArg( argies[i], XtNrepeatDelay, (XtArgVal) 100); i++;
317 	button = XtCreateManagedWidget("+", repeaterWidgetClass, temp,
318 		argies, i);
319 	XtAddCallback(button, XtNcallback, increment, 0);
320 	i = 0;
321 	XtSetArg( argies[i], XtNborderWidth, (XtArgVal) 0); i++;
322 	iter_label = XtCreateManagedWidget("     0", labelWidgetClass,
323 	    temp, argies, i);
324 	i = 0;
325 	XtSetArg( argies[i], XtNinitialDelay, (XtArgVal) 350); i++;
326 	XtSetArg( argies[i], XtNrepeatDelay, (XtArgVal) 100); i++;
327 	button = XtCreateManagedWidget("-", repeaterWidgetClass, temp,
328 		argies, i);
329 	XtAddCallback(button, XtNcallback, decrement, 0);
330 
331 	i = 0;
332 	XtSetArg( argies[i], XtNshowGrip, (XtArgVal)FALSE); i++;
333 	temp = XtCreateManagedWidget("colors", boxWidgetClass, command,
334 		argies, i);
335 	i = 0;
336 	XtSetArg( argies[i], XtNborderWidth, (XtArgVal) 0); i++;
337 	XtSetArg( argies[i], XtNbackground, (XtArgVal) def_bg); i++;
338 	XtCreateManagedWidget("Colors", labelWidgetClass, temp, argies, i);
339 	i = 0;
340 	XtSetArg( argies[i], XtNinitialDelay, (XtArgVal) 350); i++;
341 	XtSetArg( argies[i], XtNrepeatDelay, (XtArgVal) 100); i++;
342 	button = XtCreateManagedWidget("+", repeaterWidgetClass, temp,
343 		argies, i);
344 	XtAddCallback(button, XtNcallback, color_inc, 0);
345 	i = 0;
346 	XtSetArg( argies[i], XtNborderWidth, (XtArgVal) 0); i++;
347 	color_label = XtCreateManagedWidget("  0", labelWidgetClass,
348 	    temp, argies, i);
349 	i = 0;
350 	XtSetArg( argies[i], XtNinitialDelay, (XtArgVal) 350); i++;
351 	XtSetArg( argies[i], XtNrepeatDelay, (XtArgVal) 100); i++;
352 	button = XtCreateManagedWidget("-", repeaterWidgetClass, temp,
353 		argies, i);
354 	XtAddCallback(button, XtNcallback, color_dec, 0);
355 
356 	i = 0;
357 	XtSetArg( argies[i], XtNshowGrip, (XtArgVal)FALSE); i++;
358 	temp = XtCreateManagedWidget("Rotate", boxWidgetClass, command,
359 		argies, i);
360 	i = 0;
361 	XtSetArg( argies[i], XtNborderWidth, (XtArgVal) 0); i++;
362 	XtSetArg( argies[i], XtNbackground, (XtArgVal) def_bg); i++;
363 	XtCreateManagedWidget("Col_Rotate", labelWidgetClass, temp, argies, i);
364 	i = 0;
365 	XtSetArg( argies[i], XtNinitialDelay, (XtArgVal) 350); i++;
366 	XtSetArg( argies[i], XtNrepeatDelay, (XtArgVal) 150); i++;
367 	button = XtCreateManagedWidget("+", repeaterWidgetClass, temp,
368 		argies, i);
369 	XtAddCallback(button, XtNcallback, bias_inc, 0);
370 	i = 0;
371 	XtSetArg( argies[i], XtNinitialDelay, (XtArgVal) 350); i++;
372 	XtSetArg( argies[i], XtNrepeatDelay, (XtArgVal) 150); i++;
373 	button = XtCreateManagedWidget("-", repeaterWidgetClass, temp,
374 		argies, i);
375 	XtAddCallback(button, XtNcallback, bias_dec, 0);
376 
377 	XtRealizeWidget(toplevel);
378 	set_wm_hints(toplevel, "Controls", "Controls", NULL, hand_xcr);
379 	XtAddEventHandler(toplevel, StructureNotifyMask,
380 		FALSE, command_done, 0);
381 
382 	XtOverrideTranslations(file_text, XtParseTranslationTable(text_trans));
383 	XtAppAddActions(ctx, acts, XtNumber(acts));
384 	XtAppMainLoop(ctx);
385 }
386 
387 /*
388  * Called when the toplevel widget has been mapped. This provides
389  * syncronization so that the drawform window can be placed relative
390  * the toplevel window after it has been mapped.
391  */
command_done(w,call_data,evnt)392 void command_done(w, call_data, evnt)
393 Widget w;
394 caddr_t call_data;
395 XEvent *evnt;
396 {
397         if (evnt->type == MapNotify) {
398                 XtRemoveEventHandler(toplevel, StructureNotifyMask,
399                         FALSE, (XtEventHandler)command_done, 0);
400                 create_draw();
401                 create_images();
402         }
403 }
404 
quit()405 void quit()
406 {
407         exit(0);
408 }
409 
410 /*
411  * Popup the status window
412  */
show_stats()413 void show_stats()
414 {
415 	int i;
416 	Arg arg[2];
417 	Position top_y, thgt, shgt;
418 	Dimension border_w, scr_h;
419 	Position pos_x, pos_y, tmp, title;
420 	XSizeHints sizehints;
421 
422 	XtRealizeWidget(status_pu);
423 
424 	stats_flag = 1;
425 	XtSetArg( arg[0], XtNsensitive, (XtArgVal) FALSE);
426 	XtSetValues(stats_btn, arg, 1);
427 
428 
429 	scr_h = HeightOfScreen(XtScreen(toplevel));
430 
431 	i = 0;
432         XtSetArg (arg[i], XtNheight, &thgt); i++;
433         XtGetValues(toplevel, arg, i);
434 
435 	i = 0;
436         XtSetArg (arg[i], XtNheight, &shgt); i++;
437         XtGetValues(status_pu, arg, i);
438 
439 	/*
440 	 * I don't know how to get these dimensions the title and border
441 	 * dimensions so I am hard coding my defaults. KLUDGE!!!
442 	 */
443 	border_w = 5;
444 	title = 18;
445 
446 	XtTranslateCoords(toplevel, 0, 0, &pos_x, &top_y);
447 
448 	/*
449 	 * Place the new window on the screen just below the command
450 	 * window if possible, otherwise put it on top.
451 	 */
452 	tmp = top_y + shgt + thgt + (border_w * 2) + title;
453 	if (tmp <= scr_h) {
454 		pos_y = top_y + thgt + (border_w * 1);
455 	} else {
456 		pos_y = top_y - shgt - (border_w * 3) - (title * 2);
457 	}
458 	pos_x -= border_w;
459 
460 	i = 0;
461        	XtSetArg (arg[i], XtNx, pos_x); i++;
462         XtSetArg (arg[i], XtNy, pos_y); i++;
463         XtSetValues(status_pu, arg, i);
464 	sizehints.flags = USPosition;
465 	set_wm_hints(status_pu, "Statistics", "Stats", &sizehints, hand_xcr);
466 
467 	XtPopup(status_pu, XtGrabNone);
468 }
469 
470 /*
471  * Popdown the status window
472  */
close_stats()473 void close_stats()
474 {
475 	Arg arg[1];
476 
477 	stats_flag = 0;
478 	XtSetArg( arg[0], XtNsensitive, (XtArgVal) TRUE);
479 	XtSetValues(stats_btn, arg, 1);
480 	XtPopdown(status_pu);
481 }
482 
483 /*
484  * Called to set window manager hints, sizehints, window name, icon name,
485  * icon, cursor and colormap for all windows.
486  */
set_wm_hints(w,name,iname,szhints,cursor)487 void set_wm_hints(w, name, iname, szhints, cursor)
488 Widget w;
489 char *name;
490 char *iname;
491 XSizeHints *szhints;
492 Cursor cursor;
493 {
494 	Arg arg[1];
495 	XWMHints wmhints;
496 	XTextProperty nm;
497 	XTextProperty inm;
498 
499 	wmhints.flags = IconPixmapHint|WindowGroupHint;
500 	wmhints.icon_pixmap = icon_pixmap;
501 	wmhints.window_group = 991;
502 #ifdef XPM
503 	wmhints.flags |= IconMaskHint;
504 	wmhints.icon_mask = icon_shape;
505 #endif
506 	XStringListToTextProperty(&name, 1, &nm);
507 	XStringListToTextProperty(&iname, 1, &inm);
508 	XSetWMProperties(XtDisplay(w), XtWindow(w), &nm, &inm, NULL, 0,
509                    szhints, &wmhints, NULL);
510 
511 	if (depth == 8) {
512 		XtSetArg(arg[0], XtNcolormap, cmap);
513 		XtSetValues(w, arg, 1);
514 	}
515 
516 	XDefineCursor(XtDisplay(w), XtWindow(w), cursor);
517 }
518