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