1    | /***************************************
2    |   $Header: /cvsroot/petscgraphics/chui.c,v 1.13 2004/05/25 13:27:27 hazelsct Exp $
3    | 
4    |   This is a Glade front end to the little phase field/fluid structure
5    |   interactions program based on PETSc, but can serve as a front end to a
6    |   variety of PETSc programs with minor adjustments.
7    | 
8    |   Callback functions are grouped here according to where they appear in the
9    |   main window (except on_run_clicked is below main window items), then the run
10   |   control dialog, and save dialog.
11   | 
12   |   I haven't put function comments in to keep the line count down, the functions
13   |   are generally pretty simple GTK+ callbacks.
14   | ***************************************/
15   | 
16   | 
17   | /* Includes, using GTK_ENABLE_BROKEN to enable the GtkText widget for now. */
18   | #include <glade/glade.h>
19   | #include <gnome.h>
20   | #include <libgnomeui/libgnomeui.h>
21   | #include <stdio.h>
22   | #include <math.h>
23   | 
24   | GladeXML *xml;
25   | FILE *simulation_input_file, *simulation_output_file;
26   | 
27   | /* Simple debugging macro */
28   | #ifdef DEBUG
29   | #define DPRINTF printf
30   | #else
31   | #define DPRINTF(fmt...)
32   | #endif
33   | 
34   | /* Discretization stuff */
35   | double Lx;
36   | int nx;
37   | 
38   | void on_width_changed (GtkWidget *width, gpointer user_data) {
39   |   G_CONST_RETURN gchar *entrytext;
40   |   entrytext = gtk_entry_get_text (GTK_ENTRY (width));
41   |   sscanf (entrytext, "%lf", &Lx);
42   |   DPRINTF ("Width set to %g\n", Lx); }
43   | 
44   | void on_resolution_changed (GtkWidget *resolution, gpointer user_data) {
45   |   /* Note: gtk_spin_button_get_value_as_int doesn't respond to typed entry */
46   |   nx = gtk_spin_button_get_value (GTK_SPIN_BUTTON (resolution));
47   |   DPRINTF ("Resolution set to %d\n", nx); }
48   | 
49   | /* Timestep stuff */
50   | double dt, dt_factor, dt_max;
51   | int last_tstep;
52   | 
53   | void on_timestep_changed (GtkWidget *timestep, gpointer user_data) {
54   |   G_CONST_RETURN gchar *entrytext;
55   |   entrytext = gtk_entry_get_text (GTK_ENTRY (timestep));
56   |   sscanf (entrytext, "%lf", &dt);
57   |   DPRINTF ("Timestep set to %g\n", dt); }
58   | 
59   | void on_time_factor_changed (GtkWidget *time_factor, gpointer user_data) {
60   |   G_CONST_RETURN gchar *entrytext;
61   |   entrytext = gtk_entry_get_text (GTK_ENTRY (time_factor));
62   |   sscanf (entrytext, "%lf", &dt_factor);
63   |   DPRINTF ("Time factor set to %g\n", dt_factor); }
64   | 
65   | void on_max_timestep_changed (GtkWidget *max_timestep, gpointer user_data) {
66   |   G_CONST_RETURN gchar *entrytext;
67   |   entrytext = gtk_entry_get_text (GTK_ENTRY (max_timestep));
68   |   sscanf (entrytext, "%lf", &dt_max);
69   |   DPRINTF ("Max timestep set to %g\n", dt_max); }
70   | 
71   | void on_last_timestep_changed (GtkWidget *last_timestep, gpointer user_data) {
72   |   /* Note: gtk_spin_button_get_value_as_int doesn't respond to typed entry */
73   |   last_tstep = gtk_spin_button_get_value (GTK_SPIN_BUTTON (last_timestep));
74   |   DPRINTF ("Last timestep set to %d\n", last_tstep); }
75   | 
76   | /* Display stuff */
77   | gboolean display_x, display_text;
78   | 
79   | void on_xdisplay_toggled (GtkWidget *xdisplay, gpointer user_data) {
80   |   display_x = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (xdisplay));
81   |   DPRINTF (display_x ? "Using X display\n" : "Not using X display\n"); }
82   | 
83   | void on_textdisplay_toggled (GtkWidget *textdisplay, gpointer user_data) {
84   |   display_text = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(textdisplay));
85   |   DPRINTF(display_text ? "Using text display\n" : "Not using text display\n");}
86   | 
87   | /* Remote host stuff */
88   | gboolean remote_host;
89   | G_CONST_RETURN gchar *remote_hostname;
90   | gchar thetransport[50];
91   | 
92   | void on_remote_check_toggled (GtkWidget *remote_check, gpointer user_data) {
93   |   if (remote_host = gtk_toggle_button_get_active
94   |       (GTK_TOGGLE_BUTTON (remote_check))) {
95   |     gtk_widget_set_sensitive
96   |       (glade_xml_get_widget (xml, "transport_label"), TRUE);
97   |     gtk_widget_set_sensitive
98   |       (glade_xml_get_widget (xml, "transport_options"), TRUE);
99   |     gtk_widget_set_sensitive
100  |       (glade_xml_get_widget (xml, "remote_host_label"), TRUE);
101  |     gtk_widget_set_sensitive
102  |       (glade_xml_get_widget (xml, "remote_host"), TRUE); }
103  |   else {
104  |     gtk_widget_set_sensitive
105  |       (glade_xml_get_widget (xml, "transport_label"), FALSE);
106  |     gtk_widget_set_sensitive
107  |       (glade_xml_get_widget (xml, "transport_options"), FALSE);
108  |     gtk_widget_set_sensitive
109  |       (glade_xml_get_widget (xml, "remote_host_label"), FALSE);
110  |     gtk_widget_set_sensitive
111  |       (glade_xml_get_widget (xml, "remote_host"), FALSE); }
112  |   DPRINTF (remote_host ? "Using remote host\n" : "Using local host\n"); }
113  | 
114  | void on_ssh_item_activate (GtkWidget *widget, gpointer user_data) {
115  |   sprintf (thetransport, "ssh");
116  |   DPRINTF ("Transport type = %s\n", thetransport); }
117  | 
118  | void on_rsh_item_activate (GtkWidget *widget, gpointer user_data) {
119  |   sprintf (thetransport, "rsh");
120  |   DPRINTF ("Transport type = %s\n", thetransport); }
121  | 
122  | void on_remote_host_changed (GtkWidget *remote_host, gpointer user_data) {
123  |   remote_hostname = gtk_entry_get_text (GTK_ENTRY (remote_host));
124  |   DPRINTF ("Remote host set to %s\n", remote_hostname); }
125  | 
126  | /* MPI stuff */
127  | G_CONST_RETURN gchar *mpirun_command;
128  | int number_cpus;
129  | 
130  | void on_mpirun_changed (GtkWidget *mpirun, gpointer user_data) {
131  |   mpirun_command = gtk_entry_get_text (GTK_ENTRY (mpirun));
132  |   DPRINTF ("MPIrun command set to %s\n", mpirun_command); }
133  | 
134  | void on_num_cpus_changed (GtkWidget *num_cpus, gpointer user_data) {
135  |   /* Note: gtk_spin_button_get_value_as_int doesn't respond to typed entry */
136  |   number_cpus = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (num_cpus));
137  |   if (number_cpus > 1) {
138  |     gtk_widget_set_sensitive
139  |       (glade_xml_get_widget (xml, "mpirun_label"), TRUE);
140  |     gtk_widget_set_sensitive
141  |       (glade_xml_get_widget (xml, "mpirun"), TRUE); }
142  |   else {
143  |     gtk_widget_set_sensitive
144  |       (glade_xml_get_widget (xml, "mpirun_label"), FALSE);
145  |     gtk_widget_set_sensitive
146  |       (glade_xml_get_widget (xml, "mpirun"), FALSE); }
147  |   DPRINTF ("Num_CPUs set to %d\n", number_cpus); }
148  | 
149  | /* Dimensionality */
150  | gboolean twodee;
151  | 
152  | void on_2d_activate (GtkWidget *unused, gpointer user_data) {
153  |   twodee = TRUE; DPRINTF ("Simulating in two dimensions\n"); }
154  | 
155  | void on_3d_activate (GtkWidget *unused, gpointer user_data) {
156  |   twodee = FALSE; DPRINTF ("Simulating in three dimensions\n"); }
157  | 
158  | /* Load and save (unfinished!) */
159  | gchar *options_filename = NULL;
160  | void on_load_ok_clicked (GtkWidget *load_file, gpointer user_data) {
161  |   gtk_widget_hide (load_file); }
162  | 
163  | void on_save_ok_clicked (GtkWidget *save_file, gpointer user_data) {
164  |   gtk_widget_hide (save_file); }
165  | 
166  | /* Toggle buttons */
167  | void on_show_options_toggled (GtkWidget *show_options, gpointer user_data) {
168  |   GtkWidget *simulation_options =
169  |     glade_xml_get_widget (xml,"simulation_options");
170  |   GtkWidget *options_notebook = glade_xml_get_widget (xml,"options_notebook");
171  |   gboolean show_options_active =
172  |     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_options));
173  |   gboolean simulation_options_active =
174  |     gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (simulation_options));
175  |   DPRINTF ("on_show_options_toggled: show %d, simulation %d\n",
176  | 	   show_options_active, simulation_options_active);
177  | 
178  |   if (show_options_active != simulation_options_active)
179  |   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (simulation_options),
180  | 				  show_options_active);
181  |   if (show_options_active)
182  |     gtk_widget_show (options_notebook);
183  |   else {
184  |     GtkWidget *main_window = glade_xml_get_widget (xml, "main_window");
185  |     gtk_widget_hide (options_notebook);
186  |     gtk_window_resize (GTK_WINDOW (main_window), 1, 1); }
187  | }
188  | 
189  | void on_show_output_toggled (GtkWidget *show_output, gpointer user_data) {
190  |   GtkWidget *simulation_output =
191  |     glade_xml_get_widget (xml,"simulation_output");
192  |   GtkWidget *output_window = glade_xml_get_widget (xml,"output_window");
193  |   gboolean show_output_active =
194  |     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_output));
195  |   gboolean simulation_output_active =
196  |     gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (simulation_output));
197  |   DPRINTF ("on_show_output_toggled: show %d, simulation %d\n",
198  | 	   show_output_active, simulation_output_active);
199  | 
200  |   if (show_output_active != simulation_output_active)
201  |   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (simulation_output),
202  | 				  show_output_active);
203  |   if (show_output_active)
204  |     gtk_widget_show (output_window);
205  |   else
206  |     gtk_widget_hide (output_window); }
207  | 
208  | /* Menu items, mainly calling things above (SO annoying that menu signals don't
209  |    have associated objects!) */
210  | void open_params (GtkWidget *null_widget, gpointer user_data) {
211  |   GtkWidget *load_file = glade_xml_get_widget (xml,"load_file");
212  |   gtk_widget_show (load_file); }
213  | 
214  | void save_params_as (GtkWidget *null_widget, gpointer user_data) {
215  |   GtkWidget *save_file = glade_xml_get_widget (xml,"save_file");
216  |   gtk_widget_show (save_file); }
217  | 
218  | void save_params (GtkWidget *null_widget, gpointer user_data) {
219  |   if (options_filename == NULL)
220  |     save_params_as (null_widget, user_data); }
221  | 
222  | void on_show_options_activate (GtkWidget *null_widget, gpointer user_data) {
223  |   GtkWidget *simulation_options =
224  |     glade_xml_get_widget (xml,"simulation_options");
225  |   GtkWidget *show_options = glade_xml_get_widget (xml,"show_options");
226  |   gboolean simulation_options_active =
227  |     gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (simulation_options));
228  |   gboolean show_options_active =
229  |     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_options));
230  |   DPRINTF ("on_show_options_activate: show %d, simulation %d\n",
231  | 	   show_options_active, simulation_options_active);
232  | 
233  |   /* They will be unequal if this one was activated */
234  |   if (simulation_options_active != show_options_active)
235  |     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (show_options),
236  | 				  simulation_options_active); }
237  | 
238  | void on_show_output_activate (GtkWidget *null_widget, gpointer user_data) {
239  |   GtkWidget *simulation_output =
240  |     glade_xml_get_widget (xml,"simulation_output");
241  |   GtkWidget *show_output = glade_xml_get_widget (xml,"show_output");
242  |   gboolean simulation_output_active =
243  |     gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (simulation_output));
244  |   gboolean show_output_active =
245  |     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_output));
246  |   DPRINTF ("on_show_output_activate: show %d, simulation %d\n",
247  | 	   show_output_active, simulation_output_active);
248  | 
249  |   /* They will be unequal if this one was activated */
250  |   if (simulation_output_active != show_output_active)
251  |     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (show_output),
252  | 				  simulation_output_active); }
253  | 
254  | void on_about_activate (GtkWidget *null_widget, gpointer user_data) {
255  |   GtkWidget *about_window = glade_xml_get_widget (xml,"about_window");
256  |   gtk_widget_show (about_window); }
257  | 
258  | /* The run button! */
259  | gint pipe_input_tag; /* Tag number for gdk_input_add/remove */
260  | 
261  | /* First an ancillary function to read from the pipe and write to the window */
262  | void read_simulation_data (gpointer user_data, gint source,
263  | 			   GdkInputCondition condition)
264  | {
265  |   int i, len;
266  |   gfloat residual;
267  |   char simulation_input [200];
268  |   gchar start[50], current[50], final[50];
269  |   static GtkWidget *output_text=NULL,
270  |     *timestep_progressbar, *start_timestep, *current_timestep, *final_timestep,
271  |     *newton_progressbar, *start_newton, *current_newton, *final_newton,
272  |     *gcr_progressbar, *start_gcr, *current_gcr, *final_gcr;
273  |   static gfloat orig_gcr=0., orig_newton=0., tol_gcr=5.0E-4, tol_newton=5.0E-4;
274  |   static int orig_timestep = 0;
275  |   void on_stop_clicked (GtkWidget *, gpointer);
276  | 
277  |   if (output_text == NULL) {
278  |     output_text = glade_xml_get_widget (xml, "output_text");
279  |     timestep_progressbar = glade_xml_get_widget (xml, "timestep_progressbar");
280  |     start_timestep = glade_xml_get_widget (xml, "start_timestep");
281  |     current_timestep = glade_xml_get_widget (xml, "current_timestep");
282  |     final_timestep = glade_xml_get_widget (xml, "final_timestep");
283  |     newton_progressbar = glade_xml_get_widget (xml, "newton_progressbar");
284  |     start_newton = glade_xml_get_widget (xml, "start_newton");
285  |     current_newton = glade_xml_get_widget (xml, "current_newton");
286  |     final_newton = glade_xml_get_widget (xml, "final_newton");
287  |     gcr_progressbar = glade_xml_get_widget (xml, "gcr_progressbar");
288  |     start_gcr = glade_xml_get_widget (xml, "start_gcr");
289  |     current_gcr = glade_xml_get_widget (xml, "current_gcr");
290  |     final_gcr = glade_xml_get_widget (xml, "final_gcr"); }
291  | 
292  |   /* Read text until end-of-line */
293  |   if (fgets (simulation_input, sizeof (simulation_input),
294  | 	     simulation_input_file) != NULL) {
295  | 
296  |     /* KSP residual */
297  |     if (!(strncmp (simulation_input+4, "KSP", 3)) ||
298  | 	!(strncmp (simulation_input+5, "KSP", 3)) ||
299  | 	!(strncmp (simulation_input+6, "KSP", 3)) ||
300  | 	!(strncmp (simulation_input+7, "KSP", 3)) ||
301  | 	!(strncmp (simulation_input+8, "KSP", 3))) {
302  |       /* Get current GCR residual, set orig and final if necessary */
303  |       sscanf (simulation_input, "%d KSP Residual norm %f", &i, &residual);
304  |       sprintf (current, "%.4e", residual);
305  |       gtk_label_set_text (GTK_LABEL (current_gcr), current);
306  |       if (i == 0) {
307  | 	orig_gcr = residual;
308  | 	tol_gcr = residual * 1.e-5;
309  | 	sprintf (start, "%.4e", orig_gcr);
310  | 	gtk_label_set_text (GTK_LABEL (start_gcr), start);
311  | 	sprintf (final, "%.4e", tol_gcr);
312  | 	gtk_label_set_text (GTK_LABEL (final_gcr), final); }
313  | 
314  |       /* Reset when falls below tolerance (it's done), plot progress */
315  |       if (residual < tol_gcr)
316  | 	residual = orig_gcr;
317  |       if (residual <= orig_gcr)
318  | 	gtk_progress_bar_update (GTK_PROGRESS_BAR (gcr_progressbar),
319  | 				 (gfloat) log(orig_gcr/residual) /
320  | 				 log(orig_gcr/tol_gcr)); }
321  | 
322  |     /* Newton residual */
323  |     else if (!(strncmp (simulation_input+4, "SNES", 4)) ||
324  | 	!(strncmp (simulation_input+5, "SNES", 4)) ||
325  | 	!(strncmp (simulation_input+6, "SNES", 4))) {
326  |       /* Reset GCR orig and progress bar */
327  |       orig_gcr = 0.0;
328  |       gtk_progress_bar_update (GTK_PROGRESS_BAR (gcr_progressbar),
329  | 			       (gfloat) 0.0);
330  |       /* Get current Newton residual, set orig and final if necessary */
331  |       sscanf (simulation_input, "%d SNES Function norm %f", &i, &residual);
332  |       sprintf (current, "%.4e", residual);
333  |       gtk_label_set_text (GTK_LABEL (current_newton), current);
334  |       if (i == 0) {
335  | 	orig_newton = residual;
336  | 	tol_newton = residual * 1.e-8;
337  | 	sprintf (start, "%.4e", orig_newton);
338  | 	gtk_label_set_text (GTK_LABEL (start_newton), start);
339  | 	sprintf (final, "%.4e", tol_newton);
340  | 	gtk_label_set_text (GTK_LABEL (final_newton), final); }
341  | 
342  |       /* Reset when falls below tolerance (it's done), plot progress */
343  |       if (residual < tol_newton)
344  | 	residual = orig_newton;
345  |       if (residual <= orig_newton)
346  | 	gtk_progress_bar_update (GTK_PROGRESS_BAR (newton_progressbar),
347  | 				 (gfloat) log(orig_newton/residual) /
348  | 				 log(orig_newton/tol_newton)); }
349  | 
350  |     /* Timestep */
351  |     else if (!(strncmp (simulation_input, "timestep", 8))) {
352  |       sscanf (simulation_input, "timestep %d", &i);
353  |       sprintf (current, "%d", i);
354  |       gtk_label_set_text (GTK_LABEL (current_timestep), current);
355  |       if (i == 0) {
356  | 	sprintf (current, "%d", last_tstep);
357  | 	gtk_label_set_text (GTK_LABEL (final_timestep), current); }
358  |       gtk_progress_bar_update (GTK_PROGRESS_BAR (timestep_progressbar),
359  | 			       (gfloat) i/last_tstep); }
360  | 
361  |     /* End of simulation */
362  |     else if (!(strncmp (simulation_input, "Game over", 9)))
363  |       on_stop_clicked
364  | 	(glade_xml_get_widget (xml, "output_window"), NULL);
365  | 
366  |     /* Write the text to the output widget in the run dialog */
367  |     else
368  |       {
369  | 	GtkTextBuffer *buffer = gtk_text_view_get_buffer
370  | 	  (GTK_TEXT_VIEW (output_text));
371  | 	GtkTextIter iter;
372  | 	gtk_text_buffer_get_end_iter (buffer, &iter);
373  | 	gtk_text_buffer_insert
374  | 	  (buffer, &iter, simulation_input, strlen (simulation_input));
375  |       }
376  |   }
377  | }
378  |   
379  | 
380  | #define MAX_COMMAND_LINE_OPTIONS 22
381  | 
382  | int from_simulation_pipe[2], to_simulation_pipe[2];
383  | 
384  | void on_run_activate (GtkWidget *null_widget, gpointer user_data) {
385  |   gchar command_line [MAX_COMMAND_LINE_OPTIONS][50],
386  |     clinestr [MAX_COMMAND_LINE_OPTIONS*50];
387  |   int simulation_pid;
388  |   int command = 0, i;
389  | 
390  |   /* Font: -misc-fixed-medium-r-semicondensed-*-*-110-c-*-iso10646-1, or
391  |      -misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso10646-1 (or 70) */
392  | 
393  |   /* Construct the command line string, of special and standard options */
394  |   if (remote_host) {
395  |     strcpy (command_line[command++], thetransport);
396  |     if (!strcmp (thetransport, "ssh"))
397  |       sprintf (command_line[command++], "-AX");
398  |     strcpy (command_line[command++], remote_hostname); }
399  |   if (number_cpus > 1) {
400  |     sprintf (command_line[command++], "%s", mpirun_command);
401  |     sprintf (command_line[command++], "-np");
402  |     sprintf (command_line[command++], "%d", number_cpus); }
403  |   /* Note that if we add to this list, we must also modify the COMMAND_LINE
404  |      macros above, and also the execlp command below. */
405  |   sprintf (command_line[command], CHTS_PATH);
406  |   strcat (command_line[command++], "/chts");
407  |   sprintf (command_line[command++], "-ts_max_steps");
408  |   sprintf (command_line[command++], "%d", last_tstep);
409  |   sprintf (command_line[command++], "-mx");
410  |   sprintf (command_line[command++], "%d", nx);
411  |   sprintf (command_line[command++], "-my");
412  |   sprintf (command_line[command++], "%d", nx);
413  |   sprintf (command_line[command++], "-mz");
414  |   sprintf (command_line[command++], "%d", nx);
415  |   sprintf (command_line[command++], "-dt");
416  |   sprintf (command_line[command++], "%e", dt);
417  |   if (!display_x)
418  |     sprintf (command_line[command++], "-no_contours");
419  |   if (twodee)
420  |     sprintf (command_line[command++], "-twodee");
421  |   sprintf (command_line[command++], "-ts_monitor");
422  |   sprintf (command_line[command++], "-snes_monitor");
423  |   sprintf (command_line[command++], "-ksp_monitor");
424  | 
425  |   while (command < MAX_COMMAND_LINE_OPTIONS)
426  |     command_line [command++][0] = '\0';
427  |   sprintf (clinestr, "Command line:");
428  |   for (command = 0;
429  |        command < MAX_COMMAND_LINE_OPTIONS && command_line [command][0];
430  |        command++)
431  |     sprintf (clinestr+strlen(clinestr), " %s", command_line [command]);
432  |   sprintf (clinestr+strlen(clinestr), "\n");
433  |   DPRINTF ("%s", clinestr);
434  |   {
435  |     GtkTextBuffer *buffer = gtk_text_view_get_buffer
436  |       (GTK_TEXT_VIEW (glade_xml_get_widget (xml, "output_text")));
437  |     GtkTextIter iter;
438  |     gtk_text_buffer_get_end_iter (buffer, &iter);
439  |     gtk_text_buffer_insert
440  |       (buffer, &iter, clinestr, strlen (clinestr));
441  |   }
442  | 
443  |   /* Try to spawn a new simulation process.  Most of this was shamelessly
444  |      ripped from Ken Brakke's Surface Evolver. */
445  |   pipe (from_simulation_pipe); /* from simulation stdout */
446  |   pipe (to_simulation_pipe); /* to simulation stdin */
447  |   simulation_pid = fork ();
448  | 
449  |   if(simulation_pid==0) { /* child */
450  |     close (0);
451  |     dup (to_simulation_pipe[0]);
452  |     close (to_simulation_pipe[0]);
453  |     close (to_simulation_pipe[1]);
454  |     close (1);
455  |     dup (from_simulation_pipe[1]);
456  |     close (from_simulation_pipe[0]);
457  |     close (from_simulation_pipe[1]);
458  | 
459  |     /* Change to the correct directory */
460  |     /* if (chdir ("/home/hazelsct/davidch/oscsolid")) {
461  |        perror (command_line[0]); exit (1); } */
462  | 
463  |     /* signal(SIGINT,SIG_IGN); */
464  |     /* Okay, so this is a retarded way to do it... :-) */
465  |     execlp(command_line[0], command_line[0], command_line[1], command_line[2],
466  | 	   command_line[3], command_line[4], command_line[5], command_line[6],
467  | 	   command_line[7], command_line[8], command_line[9], command_line[10],
468  | 	   command_line[11],command_line[12],command_line[13],command_line[14],
469  | 	   command_line[15],command_line[16],command_line[17],command_line[18],
470  | 	   command_line[19],command_line[20],command_line[21],NULL);
471  |     perror (command_line[0]); /* only error gets here */
472  |     exit (1);
473  |   }
474  | 
475  |   /* Chui program execution resumes here */
476  |   close (from_simulation_pipe[1]);
477  |   close (to_simulation_pipe[0]);
478  | 
479  |   /* simulation_input_file is hooked to stdout of simulation */
480  |   simulation_input_file = fdopen (from_simulation_pipe[0], "r");
481  |   /* simulation_output_file is hooked to stdin of simulation */
482  |   simulation_output_file = fdopen (to_simulation_pipe[1], "w");
483  | 
484  |   /* Sensitize and desensitize various widgets */
485  |   gtk_widget_set_sensitive
486  |     (glade_xml_get_widget (xml, "model_options_vbox"), FALSE);
487  |   gtk_widget_set_sensitive
488  |     (glade_xml_get_widget (xml, "petsc_options_scrolledwindow"), FALSE);
489  |   gtk_widget_set_sensitive
490  |     (glade_xml_get_widget (xml, "misc_options_vbox"), FALSE);
491  |   gtk_widget_set_sensitive
492  |     (glade_xml_get_widget (xml, "open"), FALSE);
493  |   gtk_widget_set_sensitive
494  |     (glade_xml_get_widget (xml, "save"), FALSE);
495  |   gtk_widget_set_sensitive
496  |     (glade_xml_get_widget (xml, "save_as"), FALSE);
497  |   gtk_widget_set_sensitive
498  |     (glade_xml_get_widget (xml, "run"), FALSE);
499  |   gtk_widget_set_sensitive
500  |     (glade_xml_get_widget (xml, "open_button"), FALSE);
501  |   gtk_widget_set_sensitive
502  |     (glade_xml_get_widget (xml, "save_button"), FALSE);
503  |   gtk_widget_set_sensitive
504  |     (glade_xml_get_widget (xml, "save_as_button"), FALSE);
505  |   gtk_widget_set_sensitive
506  |     (glade_xml_get_widget (xml, "run_button"), FALSE);
507  |   /* gtk_widget_set_sensitive
508  |     (glade_xml_get_widget (xml, "pause"), TRUE);
509  |   gtk_widget_set_sensitive
510  |   (glade_xml_get_widget (xml, "stop"), TRUE); */
511  | 
512  |   /* Show the run control table and text output window */
513  |   /* gtk_widget_show (output_window); */
514  |   if (!(gtk_toggle_button_get_active
515  | 	(GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "show_output"))))) {
516  |     gtk_toggle_button_set_active
517  |       (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "show_output")), TRUE);
518  |     gtk_widget_show (glade_xml_get_widget (xml, "output_window")); }
519  | 
520  |   /* Add the input function, this will have gtk_main() call
521  |      read_simulation_data() when input is received on the pipe. */
522  |   pipe_input_tag = gdk_input_add (from_simulation_pipe [0], GDK_INPUT_READ,
523  | 				  read_simulation_data, NULL);
524  | }
525  | 
526  | void on_stop_clicked (GtkWidget *output_window, gpointer user_data) {
527  |   /* This should really send some kind of "stop" signal to chts and wait for a
528  |      reply... interactive options setting, etc. */
529  | 
530  |   /* Remove the pipe sensitivity and close the files and pipes */
531  |   gdk_input_remove (pipe_input_tag);
532  |   fclose (simulation_input_file);
533  |   fclose (simulation_output_file);
534  |   close (from_simulation_pipe [0]);
535  |   close (to_simulation_pipe [1]);
536  | 
537  |   /* Make appropriate widget readjustments */
538  |   /* gtk_widget_hide (output_window); */
539  |   gtk_widget_set_sensitive
540  |     (glade_xml_get_widget (xml, "model_options_vbox"), TRUE);
541  |   gtk_widget_set_sensitive
542  |     (glade_xml_get_widget (xml, "petsc_options_scrolledwindow"), TRUE);
543  |   gtk_widget_set_sensitive
544  |     (glade_xml_get_widget (xml, "misc_options_vbox"), TRUE);
545  |   gtk_widget_set_sensitive
546  |     (glade_xml_get_widget (xml, "open"), TRUE);
547  |   gtk_widget_set_sensitive
548  |     (glade_xml_get_widget (xml, "save"), TRUE);
549  |   gtk_widget_set_sensitive
550  |     (glade_xml_get_widget (xml, "save_as"), TRUE);
551  |   gtk_widget_set_sensitive
552  |     (glade_xml_get_widget (xml, "run"), TRUE);
553  |   gtk_widget_set_sensitive
554  |     (glade_xml_get_widget (xml, "open_button"), TRUE);
555  |   gtk_widget_set_sensitive
556  |     (glade_xml_get_widget (xml, "save_button"), TRUE);
557  |   gtk_widget_set_sensitive
558  |     (glade_xml_get_widget (xml, "save_as_button"), TRUE);
559  |   gtk_widget_set_sensitive
560  |     (glade_xml_get_widget (xml, "run_button"), TRUE);
561  |   /* gtk_widget_set_sensitive
562  |     (glade_xml_get_widget (xml, "pause"), FALSE);
563  |   gtk_widget_set_sensitive
564  |   (glade_xml_get_widget (xml, "stop"), FALSE); */}
565  | 
566  | /* Does nothing for now */
567  | void on_pause_clicked (GtkWidget *forgot, gpointer user_data) {
568  |   DPRINTF ("Pause was clicked\n");
569  |   return; }
570  | 
571  | /* And finally, main() */
572  | int main (int argc, char *argv[])
573  | {
574  |   gchar buff[200];
575  |   GtkWidget *transport_options, *transport_menu, *ssh_item, *rsh_item,
576  |     *dimension_options, *dimension_menu;
577  | 
578  |   /* Basic init stufff */
579  |   gnome_program_init ("CHUI", VERSION, LIBGNOMEUI_MODULE, argc, argv, NULL);
580  | 
581  |   /* Load the interface, display the initial window, and connect the signals */
582  |   strncpy (buff, GLADE_DIRECTORY, 187);
583  |   strcat (buff, "/chui.glade");
584  |   xml = glade_xml_new (buff, NULL, NULL);
585  |   glade_xml_signal_autoconnect (xml);
586  | 
587  |   /* For some reason, option menus don't quite work in Glade, so I had to make
588  |      a popup menu and attach it to the option menu */
589  |   /* transport_options = glade_xml_get_widget (xml, "transport_options");
590  |   gtk_option_menu_remove_menu (GTK_OPTION_MENU (transport_options));
591  |   transport_menu = glade_xml_get_widget (xml, "transport_menu");
592  |   gtk_option_menu_set_menu (GTK_OPTION_MENU(transport_options),transport_menu);
593  |   gtk_widget_show (transport_menu);
594  |   dimension_options = glade_xml_get_widget (xml, "dimension_options");
595  |   gtk_option_menu_remove_menu (GTK_OPTION_MENU (dimension_options));
596  |   dimension_menu = glade_xml_get_widget (xml, "dimension_menu");
597  |   gtk_option_menu_set_menu (GTK_OPTION_MENU(dimension_options),dimension_menu);
598  |   gtk_widget_show (dimension_menu); */
599  | 
600  |   /* Call handlers to set initial values from Glade defaults */
601  |   on_width_changed (glade_xml_get_widget (xml, "width"), NULL);
602  |   on_resolution_changed (glade_xml_get_widget (xml, "resolution"), NULL);
603  |   on_timestep_changed (glade_xml_get_widget (xml, "timestep"), NULL);
604  |   on_time_factor_changed (glade_xml_get_widget (xml, "time_factor"), NULL);
605  |   on_max_timestep_changed (glade_xml_get_widget (xml, "max_timestep"), NULL);
606  |   on_last_timestep_changed (glade_xml_get_widget (xml, "last_timestep"), NULL);
607  |   on_xdisplay_toggled (glade_xml_get_widget (xml, "xdisplay"), NULL);
608  |   on_textdisplay_toggled (glade_xml_get_widget (xml, "textdisplay"), NULL);
609  |   on_remote_check_toggled (glade_xml_get_widget (xml, "remote_check"), NULL);
610  |   on_ssh_item_activate (NULL, NULL);
611  |   on_remote_host_changed (glade_xml_get_widget (xml, "remote_host"), NULL);
612  |   on_mpirun_changed (glade_xml_get_widget (xml, "mpirun"), NULL);
613  |   on_num_cpus_changed (glade_xml_get_widget (xml, "num_cpus"), NULL);
614  |   on_3d_activate (NULL, NULL);
615  | 
616  |   /* Off we go! */
617  |   gtk_main();
618  | 
619  |   return 0;
620  | }