1 /* ************************************************************************* *
2 bugsx - (C) Copyright 1990-1997 Joshua R. Smith (jrs@media.mit.edu)
3 http://physics.www.media.mit.edu/~jrs
4
5 (C) Copyright 1995-1997 Robert Gasch (Robert_Gasch@peoplesoft.com)
6 http://www.peoplesoft.com/peoplepages/g/robert_gasch/index.htm
7
8 Permission to use, copy, modify and distribute this software for any
9 purpose and without fee is hereby granted, provided that this copyright
10 notice appear in all copies as well as supporting documentation. All
11 work developed as a consequence of the use of this program should duly
12 acknowledge such use.
13
14 No representations are made about the suitability of this software for
15 any purpose. This software is provided "as is" without express or implied
16 warranty.
17
18 See the GNU General Public Licence for more information.
19 * ************************************************************************* */
20
21
22
23
24 /* *************************************************************************
25 This program displays a list of bar graphs for the file systems of the
26 machine you are on. The following switches are supported:
27
28 +rv reverse video (use to override xrdb entry)
29 +synchronous syncronous mode (use to override xrdb entry)
30 -? help
31 -background <arg> backgound color
32 -batch run program in batch mode
33 -bg <arg> same as -background
34 -bordercolor <arg> border color
35 -borderwidth <arg> border width
36 -cycle # of iterations after which we re-initialize
37 -display display
38 -extend_print show extended reproduction info while running
39 -fg <arg> same as -forground
40 -font <arg> font
41 -foreground <arg> forground color (also file system bar color)
42 -geometry <arg> geometry (will override extreme window sizes to
43 apply reasonable settings)
44 -help help
45 -iconic iconic
46 -interval <arg> interval used per turn
47 -mb show menu border
48 -name <arg> run bugsx under this name
49 -nobreed do not breed when running in batch mode
50 -number <arg> number of biomorphs to draw (must be a square #)
51 -printpop print the population when breeding
52 -rv reverse video
53 -seed <arg> use this seed
54 -segments <arg> use this many segments to draw an organism
55 -showbreed show brreding subpopulation when in batch mode
56 -showgenes show a graphical representation of the genes
57 -synchronous synchronous mode
58 -v verbose
59 -xrm make no entry in resrouce database
60 help help
61
62
63
64 Version History:
65 10-05-90: 1.00
66 First version by Joshua R. Smith, running only
67 under Xview and Suntools.
68 21-04-95: 1.01
69 First version running under XWindows.
70 24-04-95: 1.02
71 Lots of improvements. Added resource handling,
72 -printpop, -extend_print, -number, -batch,
73 -interval, -segments, -nobreed flags.
74 Cleaned up some other code.
75 26-04-95: 1.03
76 Added -seed, -showbreed flags, lots of parameter
77 sanity checking added.
78 26-04-95: 1.04
79 Made sure breeding subpop is selected when user
80 clicks on "Initialize" when running in batch mode.
81 Fixed bug with handling of -nobreed.
82 02-05-95: 1.05
83 Added resize support, changed #ifdef __STDC__ to
84 #if __STDC__.
85 02-06-95: 1.06
86 Changed the #if __STDC__ back to #ifdef __STDC__
87 since some compilers rely on the ambigous construct,
88 changed HP check to #ifdef __hpux, updated resource
89 handling, updated README file.
90 29-03-96: 1.07
91 Changed method for checking if -number is a square
92 number, added some (double) casts for sqrt(),
93 got genes to print, added -showgenes, changed
94 address to Robert_Gasch@peoplesoft.com.
95 20-08-97: 1.08
96 Added code so that you can select organisms to
97 keep prior to re-initializing the gene pool,
98 added -cycle flag.
99
100 ************************************************************************* */
101
102
103 #include "bugsx.h"
104
105
106 Display *mydisplay;
107 char* myname; /* Name we hunt resources with */
108 XrmDatabase resourceDB; /* X resources. */
109 WinType main_win, /* main window */
110 menu[MENU_ITEMS], /* menu items */
111 draw_win[MAX_DRAW_WINS];/* windows we draw in */
112 XGCValues gray_gc_val; /* GC values for gray fill */
113 XEvent myevent; /* event */
114 unsigned long fg, bg; /* forgrund, background */
115 unsigned long warn1col, /* warn color level 1 */
116 warn2col, /* warn color level 2 */
117 warn3col; /* warn color level 3 */
118 XSizeHints mainwin_hint, /* main Window size hints */
119 szhint; /* detail Window size hints */
120 Pixmap warn_pix; /* Warning Pixmap */
121 Population G_Population[MAX_POP]; /* Array of Organisms */
122 Population G_Kids_Pop[MAX_POP]; /* Next generation */
123 double G_fit_thresh, /* fitness threshold */
124 G_pCross, /* probability of crossover */
125 G_pMutation, /* probability of mutation */
126 G_mutation_std, /* gauss fn STD used to mutate*/
127 G_weight[MAX_CHROM_SIZE],/*weight for each term */
128 G_sum_weights; /* Sum of weights -- yscaling */
129 int G_size_pop, /* # organisms in population */
130 G_size_breeding_pop, /* # organisms reproducing */
131 G_generation=NOGOOD, /* # generations so far */
132 G_switch_default, /* switches start on or off */
133 G_show_genes, /* display gene window */
134 G_current_width, /* Current size of pixwin */
135 G_current_height,
136 G_org_height, /* Size in pixels of organism */
137 G_org_width,
138 G_x_scale, /* These are used for scaling */
139 G_y_scale, /* curves. */
140 G_x_trans,
141 G_y_trans,
142 cycle=0,
143 verbose=FALSE,
144 batch=FALSE,
145 batch_breed=TRUE,
146 show_breed=FALSE,
147 upd_interval=UPDINTERVAL,
148 segments=ORG_SEGMENTS,
149 selected[MAX_DRAW_WINS],
150 do_big=FALSE,
151 do_print_pop=FALSE,
152 extend_print=FALSE,
153 Draw_Wins=DRAW_WINS,
154 Draw_Rows=DRAW_ROWS,
155 Draw_Columns=DRAW_COLUMNS,
156 menu_border=FALSE; /* menu border */
157 long seed,
158 mstime=MSTIME;
159
160
161
162 static XrmOptionDescRec opTable[] = {
163 /* KEEP THIS SORTED BY THE FIRST ARGUMENT! */
164 /* the char * should be XPointer but many systems don't support it */
165 {"+rv", "*reverseVideo", XrmoptionNoArg, (char *) "off"},
166 {"+synchronous","*synchronous", XrmoptionNoArg, (char *) "off"},
167 {"-?", ".help", XrmoptionNoArg, (char *) "on"},
168 {"-background", "*background", XrmoptionSepArg, (char *) NULL},
169 {"-batch", ".batch", XrmoptionNoArg, (char *) "on"},
170 {"-bg", "*background", XrmoptionSepArg, (char *) NULL},
171 {"-bordercolor","*borderColor", XrmoptionSepArg, (char *) NULL},
172 {"-borderwidth",".borderWidth", XrmoptionSepArg, (char *) NULL},
173 {"-cycle", ".cycle", XrmoptionSepArg, (char *) NULL},
174 {"-display", ".display", XrmoptionSepArg, (char *) NULL},
175 {"-extend_print",".extend_print",XrmoptionNoArg, (char *) "on"},
176 {"-fg", "*foreground", XrmoptionSepArg, (char *) NULL},
177 {"-font", "*font", XrmoptionSepArg, (char *) NULL},
178 {"-foreground", "*foreground", XrmoptionSepArg, (char *) NULL},
179 {"-geometry", "*mainWin.geometry",XrmoptionSepArg, (char *) NULL},
180 {"-help", ".help", XrmoptionNoArg, (char *) "on"},
181 {"-interval", ".interval", XrmoptionSepArg, (char *) NULL},
182 {"-iconic", ".iconic", XrmoptionNoArg, (char *) "on"},
183 {"-mb", ".menuborder", XrmoptionNoArg, (char *) "on"},
184 {"-name", ".name", XrmoptionSepArg, (char *) NULL},
185 {"-nobreed", ".batchbreed", XrmoptionNoArg, (char *) "off"},
186 {"-number", ".number", XrmoptionSepArg, (char *) NULL},
187 {"-printpop", ".printpop", XrmoptionNoArg, (char *) "on"},
188 {"-rv", "*reverseVideo",XrmoptionNoArg, (char *) "on"},
189 {"-seed", ".seed", XrmoptionSepArg, (char *) NULL},
190 {"-segments", ".segments", XrmoptionSepArg, (char *) NULL},
191 {"-showbreed", ".showbreed", XrmoptionNoArg, (char *) "on"},
192 {"-showgenes", ".showgenes", XrmoptionNoArg, (char *) "on"},
193 {"-synchronous","*synchronous", XrmoptionNoArg, (char *) "on"},
194 {"-v", ".verbose", XrmoptionNoArg, (char *) "on"},
195 {"-xrm", NULL, XrmoptionResArg, (char *) NULL},
196 {"help", ".help", XrmoptionNoArg, (char *) "on"},
197 };
198
199
main(argc,argv)200 void main (argc, argv)
201 int argc;
202 char **argv;
203 {
204 int i=0;
205 XrmDatabase commandlineDB=NULL;
206 char* myDisplayName = NULL;
207 XrmString str_type;
208 XrmValue value;
209
210 /* *** Try and work out the name the application will run under *** */
211 /* *** This needed for finding the correct resources. *** */
212 {
213 char** ptr = &argv[1];
214
215 for (; *ptr != NULL; ptr++)
216 if (strcmp(*ptr, "-name") == 0 && *(ptr + 1) != NULL)
217 {
218 myname = *(ptr + 1);
219 break;
220 }
221
222 if (*ptr == NULL)
223 {
224 char* ptr1 = rindex(argv[0], '/');
225 if (ptr1)
226 myname = ++ptr1;
227 else
228 myname = argv[0];
229 }
230 }
231
232 XrmInitialize();
233 XrmParseCommand(&commandlineDB, opTable,
234 sizeof(opTable) / sizeof(opTable[0]), myname, &argc, argv);
235 if (XrmGetResource(commandlineDB,
236 catlist(myname, ".name", (char*) NULL), "Xfsm.Name",
237 &str_type, &value))
238 myname = value.addr;
239 if (XrmGetResource(commandlineDB,
240 catlist(myname, ".display", (char*) NULL), "Xfsm.Display",
241 &str_type, &value))
242 myDisplayName = value.addr;
243
244 /* *** connect to X Server and assign screen *** */
245 if ((mydisplay = XOpenDisplay(myDisplayName)) == NULL)
246 {
247 fprintf (stderr, "Error Opening Display ... Exiting\n");
248 exit (1);
249 }
250
251 /* *** init the simulation constants *** */
252 init();
253
254 /* *** process arguments and the resource database *** */
255 process_databases (argc, argv, commandlineDB);
256
257 /* *** Turn on X server synchronization if the user wants it. *** */
258 XSynchronize(mydisplay, getBoolResource(resourceDB,
259 catlist(myname, ".synchronous", (char*) NULL),
260 "Xfsm.Synchronous", False));
261
262 init_all_windows();
263 srand48 (seed);
264
265 /* *** Check to see of the user wants the colors reversed. *** */
266 if (getBoolResource(resourceDB,
267 catlist(myname, ".reverseVideo", (char*) NULL),
268 "Xfsm.ReverseVideo", False))
269 {
270 long temp;
271 temp = fg;
272 fg = bg ;
273 bg = temp;
274 }
275
276 /* *** create Main Program Window and set up the properties. *** */
277 {
278 XClassHint clshint;
279 XWMHints wmhints;
280
281 mainwin_hint.min_width = MIN_WIN_X;
282 mainwin_hint.min_height = MIN_WIN_Y;
283 mainwin_hint.width = main_win.width;
284 mainwin_hint.height = main_win.height;
285 mainwin_hint.x = main_win.x;
286 mainwin_hint.y = main_win.y;
287 mainwin_hint.flags = main_win.flags | PMinSize | PSize;
288
289 clshint.res_name = myname;
290 clshint.res_class = CLASS_NAME;
291
292 wmhints.input = True;
293 wmhints.initial_state = (getBoolResource(resourceDB,
294 catlist(myname, ".iconic", (char*) NULL),
295 "Xfsm.Iconic", False))
296 ? IconicState : NormalState;
297 wmhints.window_group = main_win.win;
298 wmhints.flags = InputHint | StateHint | WindowGroupHint;
299
300 create_window (DefaultRootWindow(mydisplay), &main_win, fg, bg);
301 XSetStandardProperties (mydisplay, main_win.win, main_win.text,
302 main_win.text, None, argv, argc, &mainwin_hint);
303 XSetClassHint(mydisplay, main_win.win, &clshint);
304 XSetWMHints(mydisplay, main_win.win, &wmhints);
305 }
306
307 if (do_big)
308 Draw_Wins=1;
309 /* *** create all the buttons using child windows *** */
310 for (i = 0; i < MENU_ITEMS; ++i)
311 create_window (main_win.win, &menu[i], fg, bg);
312 for (i = 0; i < Draw_Wins; i++)
313 create_window (main_win.win, &draw_win[i], fg, bg);
314
315 /* *** Map window definitions onto screen *** */
316 XMapRaised (mydisplay, main_win.win);
317 XMapSubwindows (mydisplay, main_win.win);
318
319 randomize_pop();
320
321 #ifdef DEBUG
322 fprintf (stdout, "Setup is Done!\n");
323 #endif
324
325 /* ************************************************************ */
326 /* ************** setup is done - main event loop ************* */
327 /* ************************************************************ */
328
329 do_event_loop (argc, argv);
330
331 /* *** we are done - destroy all the windows *** */
332
333 destroy_menu (menu, MENU_ITEMS);
334 destroy_menu (draw_win, Draw_Wins);
335 XFreeGC (mydisplay, main_win.gc);
336 XDestroyWindow (mydisplay, main_win.win);
337 XCloseDisplay (mydisplay);
338 exit (0);
339 }
340
341
342
343 /* *** This is the main event loop. Here we handle events and deal *** */
344 /* *** with all the user inputs we get *** */
do_event_loop(argc,argv)345 void do_event_loop (argc, argv)
346 int argc;
347 char **argv;
348 {
349 XEvent tevent;
350 int iter=0, count, cont, this_item, i, done=FALSE;
351 char text[10];
352 long target = time(NULL);
353
354 while (!done)
355 {
356 if (batch)
357 {
358 /* *** here we wait while there are no events *** */
359 /* *** and count out down our interval. *** */
360 while (XPending (mydisplay) == 0)
361 {
362 struct timeval sleept;
363 fd_set reads;
364
365 FD_ZERO(&reads);
366 FD_SET(ConnectionNumber(mydisplay), &reads);
367 sleept.tv_sec = target - time(NULL);
368 sleept.tv_usec = 0;
369 #ifdef __hpux
370 select(ConnectionNumber(mydisplay) + 1, (int *)
371 &reads, NULL, NULL, &sleept);
372 #else
373 select(ConnectionNumber(mydisplay) + 1, &reads,
374 NULL, NULL, &sleept);
375 #endif
376 /* *** interval has passed *** */
377 if ((time(NULL)) >= target)
378 {
379 grow_pop();
380 target = target + upd_interval;
381 if (!batch_breed)
382 randomize_pop();
383 else
384 {
385 breed();
386 select_breeding_sub_pop();
387 }
388
389 if (++iter == cycle)
390 {
391 printf ("HERE\n");
392 randomize_pop();
393 iter=0;
394 }
395 }
396 }
397 }
398
399 /* *** read the next event *** */
400 XNextEvent (mydisplay, &myevent);
401
402 switch (myevent.type)
403 {
404 /* *** expose event -> redraw the window *** */
405 case Expose:
406 /* ********************************************* *
407 * since a window can generate multiple expose *
408 * events we can collapse these into one redraw *
409 * ********************************************* */
410 count=0;
411 do
412 {
413 if (XPending (mydisplay) == 0)
414 break;
415 XPeekEvent (mydisplay, &tevent);
416 if (tevent.xexpose.window == myevent.xexpose.window)
417 {
418 XNextEvent (mydisplay, &myevent);
419 count++;
420 }
421 }
422 while(tevent.xexpose.window==myevent.xexpose.window);
423
424 #ifdef DEBUG
425 if (!count)
426 fprintf(stdout, "got expose event in window: %d\n",
427 myevent.xexpose.window);
428 else
429 fprintf(stdout,
430 "Compressed %d expose events into 1 in window: %d\n",
431 count, myevent.xexpose.window);
432 #endif
433
434 /* ******************************************* *
435 * ** now deal with the actual expose event ** *
436 * ******************************************* */
437 if (myevent.xexpose.window == main_win.win &&
438 myevent.xexpose.count == 0)
439 {
440 redraw_main_win ();
441 break;
442 }
443 cont = expose_menu (menu, MENU_ITEMS);
444 if (!cont)
445 break;
446 if (G_generation != NOGOOD)
447 cont = expose_win (draw_win, Draw_Wins);
448
449 break;
450
451 /* *** change work window if main window changes *** */
452 case ConfigureNotify:
453 #ifdef DEBUG
454 fprintf(stdout, "got configure notify event in window: %d\n",
455 myevent.xconfigure.window);
456 #endif
457 /* *** we don't allow changes in the detail window *** */
458 if (myevent.xconfigure.window != main_win.win)
459 break;
460
461 /* *** size stays the same -> nothing to do *** */
462 if (myevent.xconfigure.width == main_win.width &&
463 myevent.xconfigure.height == main_win.height)
464 break;
465
466 XClearWindow (mydisplay, main_win.win);
467 handle_resize (myevent.xconfigure.width,
468 myevent.xconfigure.height);
469 break;
470
471 /* *** process keyboard mapping changes *** */
472 case MappingNotify:
473 #ifdef DEBUG
474 fprintf(stdout, "got mapping notify event in window: %d\n",
475 myevent.xexpose.window);
476 #endif
477
478 XRefreshKeyboardMapping ((XMappingEvent *) &myevent );
479 break;
480
481 /* *** drag in work window *** */
482 case MotionNotify:
483 #ifdef DEBUG
484 fprintf(stdout, "got motion notify event in window: %d\n",
485 myevent.xbutton.window);
486 #endif
487 break;
488
489 /* *** mouse enters a window *** */
490 case EnterNotify:
491 this_item = highlight_menu (menu, MENU_ITEMS, TRUE);
492 break;
493
494 /* *** Mouse Leaves a window *** */
495 case LeaveNotify:
496 this_item = highlight_menu (menu, MENU_ITEMS, FALSE);
497 break;
498
499 /* *** process mouse-button presses *** */
500 case ButtonPress:
501 #ifdef DEBUG
502 fprintf(stdout, "button press (%d) in window: %d\n",
503 myevent.xbutton.button, myevent.xbutton.window);
504 #endif
505
506 if (myevent.xbutton.button == 1 || myevent.xbutton.button == 2)
507 {
508 this_item = which_button_pressed (menu, MENU_ITEMS);
509 if (this_item == INITIALIZE)
510 {
511 randomize_pop();
512 grow_pop();
513 if (batch)
514 select_breeding_sub_pop();
515 break;
516 }
517 else if (this_item == BREED)
518 {
519 if (batch || Draw_Wins == 1)
520 break;
521 breed ();
522 break;
523 }
524 else if (this_item == QUIT)
525 {
526 done = TRUE;
527 break;
528 }
529 /*
530 else if (this_item == PLUS)
531 {
532 while (!XPending (mydisplay))
533 {
534 msleep (mstime);
535 if (mstime > 5000)
536 mstime-=5000;
537 if (segments < MAX_SEGMENTS)
538 segments++;
539 sprintf (menu[SHOW].text, "%8d", segments);
540 XDrawImageString (mydisplay,
541 menu[SHOW].win,
542 menu[SHOW].gc, 1,
543 LETTER_ASCENT (menu[SHOW]),
544 menu[SHOW].text,
545 strlen (menu[SHOW].text));
546 }
547 mstime=MSTIME;
548 break;
549 }
550 else if (this_item == MIN)
551 {
552 while (!XPending (mydisplay))
553 {
554 msleep (mstime);
555 if (mstime > 5000)
556 mstime-=5000;
557 if (segments > MIN_SEGMENTS)
558 segments--;
559 sprintf (menu[SHOW].text, "%8d", segments);
560 XDrawImageString (mydisplay,
561 menu[SHOW].win,
562 menu[SHOW].gc, 1,
563 LETTER_ASCENT (menu[SHOW]),
564 menu[SHOW].text,
565 strlen (menu[SHOW].text));
566 }
567 mstime=MSTIME;
568 break;
569 }
570 else if (this_item == OK)
571 {
572 grow_pop();
573 }
574 */
575
576 this_item = which_button_pressed (draw_win, Draw_Wins);
577 if (this_item == NOGOOD || G_generation == NOGOOD)
578 break;
579 else
580 highlight_org_window (this_item);
581 }
582 break;
583
584 /* *** process mouse-button release *** */
585 case ButtonRelease:
586 #ifdef DEBUG
587 fprintf(stdout, "button release in window: %d\n",
588 myevent.xbutton.window);
589 #endif
590 break;
591
592 /* *** process Resize *** */
593 case ResizeRequest:
594 #ifdef DEBUG
595 fprintf (stdout, "got resize event \n");
596 #endif
597 break;
598
599 /* *** process keyboard input *** */
600 case KeyPress:
601 #ifdef DEBUG
602 fprintf (stdout, "got keypress event in window: %d\n",
603 myevent.xkey.window);
604 #endif
605 i = XLookupString ((XKeyEvent *)&myevent, text, 10, NULL, 0 );
606
607 if (text[0] == INIT_KEY)
608 {
609 randomize_pop();
610 grow_pop();
611 if (batch)
612 select_breeding_sub_pop();
613 break;
614 }
615 else
616 if (text[0] == BREED_KEY)
617 {
618 if (batch || Draw_Wins == 1)
619 break;
620 breed ();
621 break;
622 }
623 else
624 if (text[0] == QUIT_KEY)
625 {
626 done = TRUE;
627 break;
628 }
629 break;
630 } /* switch (myevent.type) */
631 } /* while (done == 0) */
632 }
633