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