1 /*
2  *  xnec2c - GTK2-based version of nec2c, the C translation of NEC2
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 /* callback_func.c
20  *
21  * Functions to handle GTK callbacks for xnec2c
22  */
23 
24 #include "callback_func.h"
25 #include "shared.h"
26 
27 /*-----------------------------------------------------------------------*/
28 
29 /* Save_Pixmap()
30  *
31  * Saves pixmaps as png files
32  */
33   void
Save_Pixmap(GdkPixmap * pixmap,int pixmap_width,int pixmap_height,char * filename)34 Save_Pixmap(
35 	GdkPixmap *pixmap, int pixmap_width,
36 	int pixmap_height, char *filename )
37 {
38   GdkPixbuf *pixbuf;
39   GError *error = NULL;
40 
41   /* Get image from pixmap */
42   gtk_widget_grab_focus( structure_drawingarea );
43   pixbuf = gdk_pixbuf_get_from_drawable(
44 	  NULL, pixmap, gdk_drawable_get_colormap(pixmap),
45 	  0, 0, 0, 0, pixmap_width, pixmap_height );
46 
47   /* Save image as PNG file */
48   gdk_pixbuf_save( pixbuf, filename, "png", &error, NULL );
49   g_object_unref( pixbuf );
50 
51 } /* Save_Pixmap() */
52 
53 /*-----------------------------------------------------------------------*/
54 
55 /* New_Viewer_Angle()
56  *
57  * Sets parameters for a new viewer angle
58  */
59 void
New_Viewer_Angle(double wr,double wi,GtkSpinButton * wr_spb,GtkSpinButton * wi_spb,projection_parameters_t * params)60 New_Viewer_Angle(
61 	double wr, double wi,
62 	GtkSpinButton *wr_spb,
63 	GtkSpinButton *wi_spb,
64 	projection_parameters_t *params )
65 {
66   /* Recalculate projection paramenters */
67   params->Wr = wr;
68   params->Wi = wi;
69 
70   /* Set new value */
71   Set_Spin_Button( wr_spb, (gdouble)params->Wr );
72   Set_Spin_Button( wi_spb, (gdouble)params->Wi );
73 
74 } /* New_Viewer_Angle() */
75 
76 /*-----------------------------------------------------------------------*/
77 
78 /* Set_Spin_Button()
79  *
80  * Sets the value of a spin button
81  */
82   void
Set_Spin_Button(GtkSpinButton * spin,gdouble value)83 Set_Spin_Button( GtkSpinButton *spin, gdouble value )
84 {
85   /* Save original value and set new */
86   gdouble sav = gtk_spin_button_get_value( spin );
87   gtk_spin_button_set_value( spin, value );
88 
89   /* Issue a value_changed signal if needed (given same values) */
90   if( sav == value )
91 	g_signal_emit_by_name( G_OBJECT(spin), "value_changed", NULL );
92 
93 } /* Set_Spin_Button() */
94 
95 /*-----------------------------------------------------------------------*/
96 
97 /* Create_Pixmap()
98  *
99  * Creates or resizes a pixmap after a configure event
100  */
101 void
Create_Pixmap(GdkPixmap ** pixmap,int * pixmap_width,int * pixmap_height,GtkWidget * widget,GdkEventConfigure * event,projection_parameters_t * params)102 Create_Pixmap(
103 	GdkPixmap **pixmap,
104 	int *pixmap_width,
105 	int *pixmap_height,
106 	GtkWidget *widget,
107 	GdkEventConfigure *event,
108 	projection_parameters_t *params )
109 {
110   /* Create or resize pixmap */
111   if( *pixmap != NULL )
112   {
113 	g_object_unref( *pixmap );
114 	*pixmap = NULL;
115   }
116 
117   *pixmap = gdk_pixmap_new(
118 	  widget->window,
119 	  event->width,
120 	  event->height, -1 );
121   *pixmap_width  = event->width;
122   *pixmap_height = event->height;
123 
124   /* Calculate new projection parameters */
125   if( params != NULL )
126 	New_Projection_Parameters( *pixmap_width, *pixmap_height, params );
127 
128 } /* Create_Pixmap() */
129 
130 /*-----------------------------------------------------------------------*/
131 
132 /* Motion_Event()
133  *
134  * Handles pointer motion event on drawingareas
135  */
136 void
Motion_Event(GdkEventMotion * event,projection_parameters_t * params)137 Motion_Event(
138 	GdkEventMotion *event,
139 	projection_parameters_t *params )
140 {
141   /* Save previous pointer position */
142   static gdouble x_old = 0.0, y_old = 0.0;
143 
144   gdouble x = event->x;
145   gdouble y = event->y;
146   gdouble dx, dy;
147   gchar value[6];
148   size_t s = sizeof( value );
149 
150   /* Initialize saved x,y */
151   if( params->reset )
152   {
153 	x_old = x;
154 	y_old = y;
155 	params->reset = FALSE;
156   }
157 
158   /* Recalculate projection parameters
159    * according to pointer motion */
160   dx = x - x_old;
161   dy = y - y_old;
162   x_old = x;
163   y_old = y;
164 
165   /* Other buttons are used for moving axes on screen */
166   if( event->state & GDK_BUTTON1_MASK )
167   {
168 	/* Set the structure rotate/incline spinbuttons */
169 	if( isFlagSet(COMMON_PROJECTION) ||
170 		(params->type == STRUCTURE_DRAWINGAREA) )
171 	{
172 	  structure_proj_params.Wr -= dx / (gdouble)MOTION_EVENTS_COUNT;
173 	  structure_proj_params.Wi += dy / (gdouble)MOTION_EVENTS_COUNT;
174 	  snprintf( value, s, "%d", (int)structure_proj_params.Wr );
175 	  gtk_entry_set_text( GTK_ENTRY(rotate_structure), value );
176 	  snprintf( value, s, "%d", (int)structure_proj_params.Wi );
177 	  gtk_entry_set_text( GTK_ENTRY(incline_structure), value );
178 	}
179 
180 	/* Set the rdpattern rotate/incline spinbuttons */
181 	if( (isFlagSet(DRAW_ENABLED) &&
182 		  isFlagSet(COMMON_PROJECTION)) ||
183 		(params->type == RDPATTERN_DRAWINGAREA) )
184 	{
185 	  rdpattern_proj_params.Wr -= dx / (gdouble)MOTION_EVENTS_COUNT;
186 	  rdpattern_proj_params.Wi += dy / (gdouble)MOTION_EVENTS_COUNT;
187 	  snprintf( value, s, "%d", (int)rdpattern_proj_params.Wr );
188 	  gtk_entry_set_text( GTK_ENTRY(rotate_rdpattern), value );
189 	  snprintf( value, s, "%d", (int)rdpattern_proj_params.Wi );
190 	  gtk_entry_set_text( GTK_ENTRY(incline_rdpattern), value );
191 	}
192 
193 	/* Rotate/incline structure */
194 	if( params->type == STRUCTURE_DRAWINGAREA )
195 	{
196 	  New_Structure_Projection_Angle();
197 	  if( isFlagSet(DRAW_ENABLED) &&
198 		  isFlagSet(COMMON_PROJECTION) )
199 		New_Radiation_Projection_Angle();
200 	}
201 	else if( params->type == RDPATTERN_DRAWINGAREA )
202 	{
203 	  /* Rotate/incline rdpattern */
204 	  New_Radiation_Projection_Angle();
205 	  if( isFlagSet(COMMON_PROJECTION) )
206 		New_Structure_Projection_Angle();
207 	}
208   }    /* if( event->state & GDK_BUTTON1_MASK ) */
209   else
210   {
211 	/* Move structure or rdpattern axes on screen */
212 	params->x_center += dx;
213 	params->y_center -= dy;
214 	if( params->type == STRUCTURE_DRAWINGAREA )
215 	  Draw_Structure( structure_drawingarea );
216 	if( params->type == RDPATTERN_DRAWINGAREA )
217 	  Draw_Radiation( rdpattern_drawingarea );
218   }
219 
220 } /* Motion_Event() */
221 
222 /*-----------------------------------------------------------------------*/
223 
224 /* Plot_Select()
225  *
226  * Sets up plotting of requested freq data
227  */
228   void
Plot_Select(GtkToggleButton * togglebutton,unsigned long long int flag)229 Plot_Select( GtkToggleButton *togglebutton, unsigned long long int flag )
230 {
231   if( gtk_toggle_button_get_active(togglebutton) )
232   {
233 	SetFlag( flag | PLOT_SELECT );
234 	calc_data.ngraph++;
235   }
236   else
237   {
238 	ClearFlag( flag );
239 	calc_data.ngraph--;
240   }
241 
242   /* Trigger a redraw of frequency plots drawingarea */
243   if( isFlagSet(PLOT_ENABLED) && isFlagSet(FREQ_LOOP_DONE) )
244 	Plot_Frequency_Data();
245 
246 } /* Plot_Select() */
247 
248 /*-----------------------------------------------------------------------*/
249 
250 /* Delete_Event()
251  *
252  * Handles user request to delete a window
253  */
254  void
Delete_Event(gchar * mesg)255 Delete_Event( gchar *mesg )
256 {
257   quit_dialog = create_quit_dialog();
258   gtk_widget_show( quit_dialog );
259 
260   if( isFlagSet(FREQ_LOOP_RUNNING) )
261   {
262 	if( isFlagSet(MAIN_QUIT) )
263 	  gtk_label_set_text( GTK_LABEL(lookup_widget(
264 			  quit_dialog, "quit_label")),
265 		  _("The frequency loop is running\n"\
266 			"Really end operation?") );
267 	else gtk_label_set_text( GTK_LABEL(lookup_widget(
268 			quit_dialog, "quit_label")),
269 		_("The frequency loop is running\n"\
270 		  "Really close this window?") );
271   }
272   else gtk_label_set_text( GTK_LABEL(lookup_widget(
273 		  quit_dialog, "quit_label")), mesg );
274 
275 } /* Delete_Event() */
276 
277 /*-----------------------------------------------------------------------*/
278 
279 /* Set_Pol_Menuitem()
280  *
281  * Sets the polarization type menuitem to current setting
282  */
283   void
Set_Pol_Menuitem(GtkMenuItem * menuitem)284 Set_Pol_Menuitem( GtkMenuItem *menuitem )
285 {
286   gchar *pol_menu[NUM_POL] =
287   {
288 	"rdpattern_total",
289 	"rdpattern_horizontal",
290 	"rdpattern_vertical",
291 	"rdpattern_right_hand",
292 	"rdpattern_left_hand",
293   };
294 
295   gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(lookup_widget(
296 		  GTK_WIDGET(menuitem), pol_menu[calc_data.pol_type])), TRUE );
297 
298 } /* Set_Pol_Menuitem() */
299 
300 /*-----------------------------------------------------------------------*/
301 
302 /* Close_Windows()
303  *
304  * Closes some open windows
305  */
306   void
Close_Windows(void)307 Close_Windows( void )
308 {
309   if( isFlagSet(PLOT_ENABLED) )
310   {
311 	gtk_widget_destroy( freqplots_window );
312 	gtk_check_menu_item_set_active(
313 		GTK_CHECK_MENU_ITEM(lookup_widget(
314 			main_window, "main_freqplots")), FALSE );
315   }
316 
317   if( isFlagSet(DRAW_ENABLED) )
318   {
319 	gtk_widget_destroy( rdpattern_window );
320 	gtk_check_menu_item_set_active(
321 		GTK_CHECK_MENU_ITEM(lookup_widget(
322 			main_window, "main_rdpattern")), FALSE );
323   }
324 
325 } /* Close_Windows() */
326 
327 /*-----------------------------------------------------------------------*/
328 
329 /* Open_Editor()
330  *
331  * Pops up a Editor window on user
332  * right-click on a NEC2 Editor treeview
333  */
334   gboolean
Open_Editor(GtkTreeView * view)335 Open_Editor( GtkTreeView *view )
336 {
337   GtkTreeSelection *selection;
338   GtkTreeIter iter;
339   GtkTreeModel *model;
340   gchar *card;
341   GtkWidget *button;
342 
343   /* Find the selected treeview row */
344   selection = gtk_tree_view_get_selection( view );
345   if( !gtk_tree_selection_get_selected(selection, &model, &iter) )
346 	return( FALSE );
347 
348   /* Get the "card" name from first column */
349   gtk_tree_model_get( model, &iter, 0, &card, -1);
350   size_t s = strlen( card );
351 
352   /* Some "cards" have common editors */
353   if( strcmp(card, "GC") == 0 )
354 	Strlcpy( card, "GW", s );
355   else if( strcmp(card, "SC") == 0 )
356 	Strlcpy( card, "SP", s );
357   else if( strcmp(card, "SM") == 0 )
358 	Strlcpy( card, "SP", s );
359   else if( strcmp(card, "NH") == 0 )
360 	Strlcpy( card, "NE", s );
361   else if( strcmp(card, "GE") == 0 )
362   {
363 	Gend_Editor( EDITOR_EDIT );
364 	return( TRUE );
365   } /* EN Not editable */
366   else if( strcmp(card, "EN") == 0 )
367 	return( TRUE );
368 
369   /* Send a "clicked" signal to the appropriate editor button */
370   card[0] = (gchar)tolower((int)card[0]);
371   card[1] = (gchar)tolower((int)card[1]);
372   button = lookup_widget( GTK_WIDGET(view), card );
373   g_free(card);
374   if( button != NULL )
375 	g_signal_emit_by_name( button, "clicked" );
376   else return( FALSE );
377 
378   return( TRUE );
379 } /* Open_Editor() */
380 
381 /*-----------------------------------------------------------------------*/
382 
383 /* Main_Rdpattern_Activate()
384  *
385  * Callback function for the Radiation Pattern draw button
386  */
387   void
Main_Rdpattern_Activate(gboolean from_menu)388 Main_Rdpattern_Activate( gboolean from_menu )
389 {
390   /* Set E field check menu item */
391   if( fpat.nfeh & NEAR_EFIELD )
392   {
393 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
394 		  lookup_widget(rdpattern_window,
395 			"rdpattern_e_field")), TRUE );
396 	SetFlag( DRAW_EFIELD );
397   }
398   else
399   {
400 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
401 		  lookup_widget(rdpattern_window,
402 			"rdpattern_e_field")), FALSE );
403 	ClearFlag( DRAW_EFIELD );
404   }
405 
406   /* Set H field check menu item */
407   if( fpat.nfeh & NEAR_HFIELD )
408   {
409 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
410 		  lookup_widget(rdpattern_window,
411 			"rdpattern_h_field")), TRUE );
412 	SetFlag( DRAW_HFIELD );
413   }
414   else
415   {
416 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
417 		  lookup_widget(rdpattern_window,
418 			"rdpattern_h_field")), FALSE );
419 	ClearFlag( DRAW_HFIELD );
420   }
421 
422   /* Set Poynting vector check menu item */
423   if( (fpat.nfeh & NEAR_EHFIELD) == NEAR_EHFIELD )
424   {
425 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
426 		  lookup_widget(rdpattern_window,
427 			"rdpattern_poynting_vector")), TRUE );
428 	SetFlag( DRAW_POYNTING );
429   }
430   else
431   {
432 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
433 		  lookup_widget(rdpattern_window,
434 			"rdpattern_poynting_vector")), FALSE );
435 	ClearFlag( DRAW_POYNTING );
436   }
437 
438   /* Set structure overlay in Rad Pattern window */
439   if( isFlagClear(OVERLAY_STRUCT) )
440 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
441 		  lookup_widget(rdpattern_window,
442 			"rdpattern_overlay_structure")), FALSE );
443   else
444 	gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(
445 		  lookup_widget(rdpattern_window,
446 			"rdpattern_overlay_structure")), TRUE );
447 
448 
449   /* Sync common projection spinbuttons */
450   if( isFlagSet(COMMON_PROJECTION) )
451   {
452 	gchar value[6];
453 	size_t s = sizeof( value ) - 1;
454 
455 	rdpattern_proj_params.Wr = structure_proj_params.Wr;
456 	rdpattern_proj_params.Wi = structure_proj_params.Wi;
457 	snprintf( value, s, "%d", (int)rdpattern_proj_params.Wr );
458 	value[s] = '\0';
459 	gtk_entry_set_text( GTK_ENTRY(rotate_rdpattern), value );
460 	snprintf( value, s, "%d", (int)rdpattern_proj_params.Wi );
461 	value[s] = '\0';
462 	gtk_entry_set_text( GTK_ENTRY(incline_rdpattern), value );
463   }
464   else	/* Initialize radiation pattern projection angles */
465   {
466 	rdpattern_proj_params.Wr =
467 	  gtk_spin_button_get_value(rotate_rdpattern);
468 	rdpattern_proj_params.Wi =
469 	  gtk_spin_button_get_value(incline_rdpattern);
470   }
471   New_Radiation_Projection_Angle();
472 
473   /* Redo currents if not reaching this function
474    * from the menu callback (e.g. not user action) */
475   if( !crnt.valid && !from_menu ) Redo_Currents( NULL );
476 
477   /* Display frequency in freq spinbutton */
478   if( from_menu )
479   {
480 	char value[9];
481 	size_t s = sizeof( value );
482 	snprintf( value, s, "%.3f", calc_data.fmhz );
483 	value[s - 1] = '\0';
484 	gtk_entry_set_text(
485 		GTK_ENTRY(rdpattern_frequency), value );
486   }
487 
488   /* Enable Gain or E/H field drawing */
489   SetFlag( DRAW_ENABLED );
490 
491 } /* Main_Rdpattern_Activate() */
492 
493 /*-----------------------------------------------------------------------*/
494 
495 /* Main_Freqplots_Activate()
496  *
497  * Callback function for for the main Frequency Plots button
498  */
499   gboolean
Main_Freqplots_Activate(void)500 Main_Freqplots_Activate( void )
501 {
502   /* No plots for Incident Field and
503    * Elementary Current Source Excitation */
504   if( (fpat.ixtyp != 0) && (fpat.ixtyp != 5) )
505   {
506 	stop( _("Not available for Incident Field or\n"\
507 		  "Elementary Current Source Excitation.\n"\
508 		  "(Excitation Types 1 to 4)"), ERR_OK );
509 	return( FALSE );
510   }
511 
512   /* Enable freq data graph plotting */
513   SetFlag( PLOT_ENABLED );
514 
515   return( TRUE );
516 } /* Main_Freqplots_Activate() */
517 
518 /*-----------------------------------------------------------------------*/
519 
520 /* Rdpattern_Gain_Togglebutton_Toggled()
521  *
522  * Callback function for Rad Pattern window Gain button
523  */
524   void
Rdpattern_Gain_Togglebutton_Toggled(gboolean flag)525 Rdpattern_Gain_Togglebutton_Toggled( gboolean flag )
526 {
527   /* If radiation pattern data do not
528    * allow drawing of radiation pattern */
529   if( isFlagClear(ENABLE_RDPAT) ) return;
530 
531   /* Enable or not gain (radiation) pattern plotting */
532   if( flag )
533   {
534 	SetFlag( DRAW_GAIN );
535 	ClearFlag( DRAW_EHFIELD );
536 	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(lookup_widget(
537 			rdpattern_window, "rdpattern_eh_togglebutton")), FALSE );
538 
539 	/* Redraw radiation pattern drawingarea */
540 	if( isFlagSet(DRAW_ENABLED) &&
541 		isFlagClear(FREQ_LOOP_RUNNING) )
542 	{
543 	  if( !crnt.valid ) Redo_Currents( NULL );
544 	  SetFlag( DRAW_NEW_RDPAT );
545 	  Draw_Radiation( rdpattern_drawingarea );
546 	}
547 
548 	Set_Window_Labels();
549   }
550   else
551   {
552 	ClearFlag( DRAW_GAIN );
553 	/* Clear radiation pattern drawingarea */
554 	if( isFlagClear(DRAW_EHFIELD) &&
555 		isFlagSet(DRAW_ENABLED) )
556 	  Draw_Radiation( rdpattern_drawingarea );
557 	Free_Draw_Buffers();
558   }
559 
560   return;
561 } /* Rdpattern_Gain_Togglebutton_Toggled() */
562 
563 /*-----------------------------------------------------------------------*/
564 
565 /* Rdpattern_EH_Togglebutton_Toggled()
566  *
567  * Callback function for Rad Pattern window E/H field button
568  */
569   void
Rdpattern_EH_Togglebutton_Toggled(gboolean flag)570 Rdpattern_EH_Togglebutton_Toggled( gboolean flag )
571 {
572   /* If no near EH data */
573   if( !fpat.nfeh ) return;
574 
575   /* Enable or not E/H fields plotting */
576   if( flag )
577   {
578 	SetFlag( DRAW_EHFIELD );
579 	ClearFlag( DRAW_GAIN );
580 	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(lookup_widget(
581 			rdpattern_window, "rdpattern_gain_togglebutton")), FALSE );
582 
583 	/* Delegate near field calcuations to child
584 	 * processes if forked and near field data valid */
585 	if( FORKED )
586 	{
587 	  Alloc_Nearfield_Buffers(fpat.nrx, fpat.nry, fpat.nrz);
588 	  Pass_EH_Flags();
589 	}
590 
591 	/* Redraw radiation pattern drawingarea */
592 	if( isFlagSet(DRAW_ENABLED) &&
593 		isFlagClear(FREQ_LOOP_RUNNING) )
594 	{
595 	  if( !near_field.valid ) Redo_Currents(NULL);
596 	  Near_Field_Pattern();
597 	  SetFlag( DRAW_NEW_EHFIELD );
598 	  Draw_Radiation( rdpattern_drawingarea );
599 	}
600 
601 	Set_Window_Labels();
602   }
603   else
604   {
605 	ClearFlag( NEAREH_ANIMATE );
606 	ClearFlag( DRAW_EHFIELD );
607 
608 	/* Clear radiation pattern drawingarea */
609 	if( isFlagClear(DRAW_GAIN)  &&
610 		isFlagSet(DRAW_ENABLED) )
611 	  Draw_Radiation( rdpattern_drawingarea );
612 
613 	/* Disable near field calcuations
614 	 * by child processes if forked */
615 	Pass_EH_Flags();
616   }
617 
618 } /* Rdpattern_EH_Togglebutton_Toggled() */
619 
620 /*-----------------------------------------------------------------------*/
621 
622 /* Main_Currents_Togglebutton_Toggled()
623  *
624  * Callback function for Main Currents toggle button
625  */
626   void
Main_Currents_Togglebutton_Toggled(gboolean flag)627 Main_Currents_Togglebutton_Toggled( gboolean flag )
628 {
629   /* Enable calculation and rendering of structure curents */
630   if( flag )
631   {
632 	SetFlag( DRAW_CURRENTS );
633 	ClearFlag( DRAW_CHARGES );
634 	crnt.newer = 1;
635 	Alloc_Crnt_Buffs();
636 
637 	gtk_toggle_button_set_active(
638 		GTK_TOGGLE_BUTTON(lookup_widget(main_window,
639 			"main_charges_togglebutton")), FALSE );
640 	gtk_label_set_text(
641 		GTK_LABEL(lookup_widget(main_window, "struct_label")),
642 		_("View Currents") );
643 
644 	if( !crnt.valid && isFlagClear(FREQ_LOOP_RUNNING) )
645 	  Redo_Currents( NULL );
646 	else if( crnt.valid )
647 	  Draw_Structure( structure_drawingarea );
648 
649 	if( isFlagSet(OVERLAY_STRUCT) )
650 	  Draw_Radiation( rdpattern_drawingarea );
651   }
652   else
653   {
654 	ClearFlag( DRAW_CURRENTS );
655 	if( isFlagClear(DRAW_CHARGES) )
656 	{
657 	  /* Redraw structure on screen if frequency loop is not running */
658 	  gtk_label_set_text(
659 		  GTK_LABEL(lookup_widget(main_window, "struct_label")),
660 		  _("View Geometry") );
661 	  if( isFlagClear(FREQ_LOOP_RUNNING) )
662 		Draw_Structure( structure_drawingarea );
663 	  Free_Crnt_Buffs();
664 	}
665 	if( isFlagSet(OVERLAY_STRUCT) )
666 	  Draw_Radiation( rdpattern_drawingarea );
667   }
668 } /* Main_Currents_Togglebutton_Toggled() */
669 
670 /*-----------------------------------------------------------------------*/
671 
672 /* Main_Charges_Togglebutton_Toggled()
673  *
674  * Callback function for Main Charges toggle button
675  */
676   void
Main_Charges_Togglebutton_Toggled(gboolean flag)677 Main_Charges_Togglebutton_Toggled( gboolean flag )
678 {
679   if( flag )
680   {
681 	SetFlag( DRAW_CHARGES );
682 	ClearFlag( DRAW_CURRENTS );
683 	crnt.newer = 1;
684 	Alloc_Crnt_Buffs();
685 
686 	gtk_toggle_button_set_active(
687 		GTK_TOGGLE_BUTTON(lookup_widget(main_window,
688 			"main_currents_togglebutton")), FALSE );
689 	gtk_label_set_text(
690 		GTK_LABEL(lookup_widget(main_window, "struct_label")),
691 		_("View Charges") );
692 
693 	if( !crnt.valid && isFlagClear(FREQ_LOOP_RUNNING) )
694 	  Redo_Currents( NULL );
695 	else if( crnt.valid )
696 	  Draw_Structure( structure_drawingarea );
697 
698 	if( isFlagSet(OVERLAY_STRUCT) )
699 	  Draw_Radiation( rdpattern_drawingarea );
700   }
701   else
702   {
703 	ClearFlag( DRAW_CHARGES );
704 	if( isFlagClear(DRAW_CURRENTS) )
705 	{
706 	  /* Redraw structure on screen if frequency loop is not running */
707 	  gtk_label_set_text(
708 		  GTK_LABEL(lookup_widget(main_window, "struct_label")),
709 		  _("View Geometry") );
710 	  if( isFlagClear(FREQ_LOOP_RUNNING) )
711 		Draw_Structure( structure_drawingarea );
712 	  Free_Crnt_Buffs();
713 	}
714 	if( isFlagSet(OVERLAY_STRUCT) )
715 	  Draw_Radiation( rdpattern_drawingarea );
716   }
717 } /* Main_Charges_Togglebutton_Toggled() */
718 
719 /*-----------------------------------------------------------------------*/
720 
721 /* Open_Nec2_Editor()
722  *
723  * Opens NEC2 editor window and fills
724  * tree view according to action flag
725  */
726   void
Open_Nec2_Editor(int action)727 Open_Nec2_Editor( int action )
728 {
729   nec2_edit_window = create_nec2_editor();
730   gtk_widget_show( nec2_edit_window );
731 
732   geom_treeview = GTK_TREE_VIEW(
733 	  lookup_widget(nec2_edit_window, "nec2_geom_treeview") );
734   cmnd_treeview = GTK_TREE_VIEW(
735 	  lookup_widget(nec2_edit_window, "nec2_cmnd_treeview") );
736 
737   Nec2_Input_File_Treeview( action );
738 
739   geom_adjustment = gtk_scrolled_window_get_vadjustment(
740 	  GTK_SCROLLED_WINDOW(lookup_widget(nec2_edit_window,
741 		  "scrolledwindow4")) );
742   cmnd_adjustment = gtk_scrolled_window_get_vadjustment(
743 	  GTK_SCROLLED_WINDOW(lookup_widget(nec2_edit_window,
744 		  "scrolledwindow3")) );
745 } /* Open_Nec2_Editor() */
746 
747 /*-----------------------------------------------------------------------*/
748 
749 /* Nec2_Apply_Checkbuton()
750  *
751  * Checks whether the NEC2 editor's "Apply" check button is active
752  */
753 
754   gboolean
Nec2_Apply_Checkbutton(void)755 Nec2_Apply_Checkbutton( void )
756 {
757   return( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
758 		  lookup_widget(nec2_edit_window,
759 			"nec2_apply_checkbutton" ))) );
760 }
761 
762 /*-----------------------------------------------------------------------*/
763 
764 /* Gtk_Quit()
765  *
766  * Quits gtk main
767  */
768   void
Gtk_Quit(void)769 Gtk_Quit( void )
770 {
771   int i, k;
772 
773   Close_File( &input_fp );
774   SetFlag( MAIN_QUIT );
775 
776   /* Kill child processes */
777   if( FORKED && !CHILD )
778 	while( num_child_procs )
779 	{
780 	  num_child_procs--;
781 	  kill( forked_proc_data[num_child_procs]->child_pid, SIGKILL );
782 	}
783 
784   /* Kill possibly nested loops */
785   k = (int)gtk_main_level();
786   for( i = 0; i < k; i++ )
787 	gtk_main_quit();
788 
789 } /* Gtk_Quit() */
790 
791 /*-----------------------------------------------------------------------*/
792 
793 /* Pass_EH_Flags
794  *
795  * Passes near field related flags to child processes
796  */
797   void
Pass_EH_Flags(void)798 Pass_EH_Flags( void )
799 {
800   char flag;
801   size_t cnt;
802   int idx;
803 
804   /* Abort if not forked */
805   if( !FORKED ) return;
806 
807   /* Tell child process to calculate near field data */
808   cnt = strlen( fork_commands[EHFIELD] );
809   for( idx = 0; idx < calc_data.num_jobs; idx++ )
810 	Write_Pipe( idx, fork_commands[EHFIELD], (ssize_t)cnt, TRUE );
811 
812   /* Tell child to set near field flags */
813   flag = 0;
814   if( isFlagSet(DRAW_EHFIELD) )		flag |= 0x01;
815   if( isFlagSet(NEAREH_SNAPSHOT) )	flag |= 0x02;
816   if( isFlagSet(DRAW_EFIELD) )		flag |= 0x04;
817   if( isFlagSet(DRAW_HFIELD) )		flag |= 0x08;
818 
819   cnt = sizeof( flag );
820   for( idx = 0; idx < calc_data.num_jobs; idx++ )
821 	Write_Pipe( idx, &flag, (ssize_t)cnt, TRUE );
822 
823 } /* Pass_EH_Flags */
824 
825 /*-----------------------------------------------------------------------*/
826 
827 /* Alloc_Crnt_Buffs()
828  *
829  * Allocates memory for current/charge draw buffers
830  */
831   void
Alloc_Crnt_Buffs(void)832 Alloc_Crnt_Buffs( void )
833 {
834   /* Patch currents buffer */
835   if( data.m > 0 )
836   {
837 	size_t mreq = (size_t)data.m * sizeof( double );
838 	mem_realloc( (void **)&ct1m, mreq, "in callback_func.c" );
839 	mem_realloc( (void **)&ct2m, mreq, "in callback_func.c" );
840   }
841 
842   /* Segment currents buffer */
843   if( data.n > 0 )
844   {
845 	size_t mreq = (size_t)data.n * sizeof( double );
846 	mem_realloc( (void **)&cmag, mreq, "in callback_func.c" );
847   }
848 
849 } /* Alloc_Crnt_Buffs() */
850 
851 /*-----------------------------------------------------------------------*/
852 
853 /* Free_Crnt_Buffs()
854  *
855  * Frees current/charge draw buffers
856  */
857   void
Free_Crnt_Buffs(void)858 Free_Crnt_Buffs( void )
859 {
860   free_ptr( (void **)&ct1m );
861   free_ptr( (void **)&ct2m );
862   free_ptr( (void **)&cmag );
863 } /* Free_Crnt_Buffs() */
864 
865 /*-----------------------------------------------------------------------*/
866 
867