1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 /*! \todo STILL NEED to clean up line lengths in aa and tr */
31 #include <libgeda/libgeda.h>
33 #include "../include/i_vars.h"
34 #include "../include/globals.h"
35 #include "../include/prototype.h"
36 #include "../include/x_dialog.h"
37 #include "../include/gschem_dialog.h"
39 #ifdef HAVE_LIBDMALLOC
43 #define GLADE_HOOKUP_OBJECT(component,widget,name) \
44 g_object_set_data_full (G_OBJECT (component), name, \
45 gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
47 static GtkWidget
* create_menu_linetype (TOPLEVEL
*w_current
);
48 static gint
line_type_dialog_linetype_change (GtkWidget
*w
, gpointer data
);
49 static void line_type_dialog_ok (GtkWidget
*w
, gpointer data
);
51 static GtkWidget
* create_menu_filltype (TOPLEVEL
*w_current
);
52 static gint
fill_type_dialog_filltype_change(GtkWidget
*w
, gpointer data
);
53 static void fill_type_dialog_ok(GtkWidget
*w
, gpointer data
);
56 struct line_type_data
{
58 GtkWidget
*width_entry
;
60 GtkWidget
*length_entry
;
61 GtkWidget
*space_entry
;
67 struct fill_type_data
{
70 GtkWidget
*width_entry
;
71 GtkWidget
*angle1_entry
;
72 GtkWidget
*pitch1_entry
;
73 GtkWidget
*angle2_entry
;
74 GtkWidget
*pitch2_entry
;
80 /*! \todo Finish function documentation!!!
82 * \par Function Description
85 void destroy_window(GtkWidget
*widget
, GtkWidget
**window
)
90 /* TODO: This string is used by the dialogs: show_text, find_text and hide_text
91 * I think it should be removed. (Werner Hoch)
93 char generic_textstring
[256] = "refdes=R";
95 /***************** Start of Text Input dialog box *********************/
97 /*! \brief worker function for the text entry dialog
98 * \par Function Description
99 * This function applies the text from the text entry dialog.
101 void text_input_dialog_apply(GtkWidget
*w
, TOPLEVEL
*w_current
)
106 GtkTextBuffer
*textbuffer
;
107 GtkTextIter start
, end
;
109 tientry
= gtk_object_get_data(GTK_OBJECT(w_current
->tiwindow
),"tientry");
111 textbuffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(tientry
));
112 gtk_text_buffer_get_bounds (textbuffer
, &start
, &end
);
113 string
= gtk_text_iter_get_text (&start
, &end
);
115 if (string
[0] != '\0' ) {
116 len
= strlen(string
);
118 printf("text was: _%s_ %d\n", string
, len
);
120 switch(w_current
->text_caps
) {
122 string_tolower(string
, string
);
126 string_toupper(string
, string
);
135 /* select the text, so you can continue immediatly writing the next text */
136 select_all_text_in_textview(GTK_TEXT_VIEW(tientry
));
137 gtk_widget_grab_focus(tientry
);
139 o_attrib_set_string(w_current
, string
);
140 w_current
->page_current
->CHANGED
=1;
141 w_current
->event_state
= DRAWTEXT
;
142 w_current
->inside_action
= 1;
146 /*! \brief response function for the text entry dialog
147 * \par Function Description
148 * Callback function for the text entry dialog.
150 void text_input_dialog_response(GtkWidget
* widget
, gint response
, TOPLEVEL
*w_current
)
153 case GTK_RESPONSE_ACCEPT
:
154 text_input_dialog_apply(widget
, w_current
);
156 case GTK_RESPONSE_REJECT
:
157 case GTK_RESPONSE_DELETE_EVENT
:
158 i_set_state(w_current
, SELECT
);
159 i_update_toolbar(w_current
);
160 gtk_widget_destroy(w_current
->tiwindow
);
161 w_current
->tiwindow
=NULL
;
164 printf("text_edit_dialog_response(): strange signal %d\n", response
);
169 /*! \brief create or present the text entry dialog
170 * \par Function Description
171 * This function creates or raises the modal text entry dialog
173 void text_input_dialog (TOPLEVEL
*w_current
)
175 GtkWidget
*label
= NULL
;
176 GtkWidget
*tientry
= NULL
;
178 GtkWidget
*viewport1
= NULL
;
179 GtkWidget
*scrolled_window
= NULL
;
180 PangoTabArray
*tab_array
;
183 if (!w_current
->tiwindow
) { /* dialog not created yet */
184 w_current
->tiwindow
= gschem_dialog_new_with_buttons(_("Text Entry..."),
185 GTK_WINDOW(w_current
->main_window
),
187 "text-entry", w_current
,
194 #if GTK_CHECK_VERSION (2,6,0)
195 /* Set the alternative button order (ok, cancel, help) for other systems */
196 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->tiwindow
),
202 gtk_window_position(GTK_WINDOW (w_current
->tiwindow
),
205 gtk_signal_connect(GTK_OBJECT (w_current
->tiwindow
), "response",
206 GTK_SIGNAL_FUNC(text_input_dialog_response
),
209 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->tiwindow
),
210 GTK_RESPONSE_ACCEPT
);
212 gtk_container_border_width(GTK_CONTAINER (w_current
->tiwindow
),
213 DIALOG_BORDER_SPACING
);
214 vbox
= GTK_DIALOG(w_current
->tiwindow
)->vbox
;
215 gtk_box_set_spacing(GTK_BOX(vbox
),DIALOG_V_SPACING
);
217 label
= gtk_label_new (_("Enter text, click apply,\n"
218 "move cursor into window, click to place text.\n"
219 "Middle button to rotate while placing."));
220 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
221 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
223 viewport1
= gtk_viewport_new (NULL
, NULL
);
224 gtk_widget_show (viewport1
);
226 scrolled_window
= gtk_scrolled_window_new(NULL
, NULL
);
227 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window
),
228 GTK_POLICY_AUTOMATIC
,
229 GTK_POLICY_AUTOMATIC
);
230 gtk_container_add (GTK_CONTAINER (viewport1
), scrolled_window
);
231 gtk_box_pack_start( GTK_BOX(vbox
), viewport1
, TRUE
, TRUE
, 0);
233 tientry
= gtk_text_view_new();
234 gtk_text_view_set_editable(GTK_TEXT_VIEW(tientry
), TRUE
);
235 select_all_text_in_textview(GTK_TEXT_VIEW(tientry
));
237 /* Set the tab width, using pango tab array */
238 /*! \bug FIXME: This doesn't work. Why? */
239 tab_array
= pango_tab_array_new (1, TRUE
);
240 real_tab_width
= text_view_calculate_real_tab_width(GTK_TEXT_VIEW(tientry
),
242 if (real_tab_width
>= 0) {
243 pango_tab_array_set_tab (tab_array
, 0, PANGO_TAB_LEFT
, real_tab_width
);
244 /* printf("Real tab width: %i\n", real_tab_width);*/
245 gtk_text_view_set_tabs (GTK_TEXT_VIEW (tientry
),
249 g_warning ("text_input_dialog: Impossible to set tab width.\n");
251 pango_tab_array_free (tab_array
);
252 gtk_container_add(GTK_CONTAINER(scrolled_window
), tientry
);
254 gtk_object_set_data(GTK_OBJECT(w_current
->tiwindow
),
257 gtk_widget_show_all (w_current
->tiwindow
);
259 else { /* dialog already created */
260 gtk_window_present (GTK_WINDOW(w_current
->tiwindow
));
263 /* always select the text in the entry */
264 tientry
= gtk_object_get_data(GTK_OBJECT(w_current
->tiwindow
),"tientry");
265 select_all_text_in_textview(GTK_TEXT_VIEW(tientry
));
266 gtk_widget_grab_focus(tientry
);
269 /***************** End of Text Input dialog box ***********************/
271 /***************** Start of Text Edit dialog box **********************/
272 /*! \brief CAllback for a text aligment change
273 * \par Function Description
274 * This function stores a change of the text alignment in the
275 * <b>TOPLEVEL</b> struct.
276 * \todo Remove that function. Only the OK-Button should set any
277 * properties in the TOPLEVEL struct.
279 gint
change_alignment(GtkWidget
*w
, TOPLEVEL
*w_current
)
282 alignment
= gtk_object_get_data(GTK_OBJECT(w
),"alignment");
283 w_current
->text_alignment
= atoi(alignment
);
285 /*w_current->page_current->CHANGED=1; I don't think this belongs */
286 /* o_undo_savestate(w_current, UNDO_ALL); I don't think this belongs */
291 /*! \brief Create the alignment menu for the text property dialog
292 * \par Function Description
293 * This function creates a GtkMenu with nine different alignment
296 static GtkWidget
*create_menu_alignment (TOPLEVEL
*w_current
)
303 menu
= gtk_menu_new ();
306 buf
= g_strdup_printf( _("Lower Left"));
307 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
309 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
310 gtk_menu_append (GTK_MENU (menu
), menuitem
);
311 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "0");
312 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
313 (GtkSignalFunc
) change_alignment
,
315 gtk_widget_show (menuitem
);
317 buf
= g_strdup_printf( _("Middle Left"));
318 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
320 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
321 gtk_menu_append (GTK_MENU (menu
), menuitem
);
322 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "1");
323 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
324 (GtkSignalFunc
) change_alignment
,
326 gtk_widget_show (menuitem
);
328 buf
= g_strdup_printf( _("Upper Left"));
329 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
331 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
332 gtk_menu_append (GTK_MENU (menu
), menuitem
);
333 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "2");
334 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
335 (GtkSignalFunc
) change_alignment
,
337 gtk_widget_show (menuitem
);
339 buf
= g_strdup_printf( _("Lower Middle"));
340 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
342 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
343 gtk_menu_append (GTK_MENU (menu
), menuitem
);
344 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "3");
345 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
346 (GtkSignalFunc
) change_alignment
,
348 gtk_widget_show (menuitem
);
350 buf
= g_strdup_printf( _("Middle Middle"));
351 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
353 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
354 gtk_menu_append (GTK_MENU (menu
), menuitem
);
355 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "4");
356 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
357 (GtkSignalFunc
) change_alignment
,
359 gtk_widget_show (menuitem
);
361 buf
= g_strdup_printf( _("Upper Middle"));
362 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
364 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
365 gtk_menu_append (GTK_MENU (menu
), menuitem
);
366 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "5");
367 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
368 (GtkSignalFunc
) change_alignment
,
370 gtk_widget_show (menuitem
);
372 buf
= g_strdup_printf( _("Lower Right"));
373 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
375 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
376 gtk_menu_append (GTK_MENU (menu
), menuitem
);
377 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "6");
378 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
379 (GtkSignalFunc
) change_alignment
,
381 gtk_widget_show (menuitem
);
383 buf
= g_strdup_printf( _("Middle Right"));
384 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
386 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
387 gtk_menu_append (GTK_MENU (menu
), menuitem
);
388 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "7");
389 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
390 (GtkSignalFunc
) change_alignment
,
392 gtk_widget_show (menuitem
);
394 buf
= g_strdup_printf( _("Upper Right"));
395 menuitem
= gtk_radio_menu_item_new_with_label (group
, buf
);
397 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
398 gtk_menu_append (GTK_MENU (menu
), menuitem
);
399 gtk_object_set_data (GTK_OBJECT(menuitem
), "alignment", "8");
400 gtk_signal_connect(GTK_OBJECT (menuitem
), "activate",
401 (GtkSignalFunc
) change_alignment
,
403 gtk_widget_show (menuitem
);
408 /* we reuse the color menu so we need to declare it */
409 static GtkWidget
*create_color_menu(TOPLEVEL
* w_current
, int * select_index
);
411 /*! \brief Apply the settings from the text property dialog
412 * \par Function Description
413 * This function applies the user settings to the selected text objects
414 * and closes the dialog
416 void text_edit_dialog_ok(GtkWidget
*w
, TOPLEVEL
*w_current
)
420 char *text_string
= NULL
;
421 char *text_size_string
= NULL
;
422 int new_text_alignment
;
424 GtkTextBuffer
*textbuffer
;
425 GtkTextIter start
, end
;
428 num_selected
= g_list_length( geda_list_get_glist( w_current
->page_current
->selection_list
));
430 /* text string entry will only show up if one object is selected */
431 if (num_selected
== 1) {
432 widget
= g_object_get_data (G_OBJECT (w_current
->tewindow
), "textentry");
433 textbuffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget
));
434 gtk_text_buffer_get_bounds (textbuffer
, &start
, &end
);
435 text_string
= gtk_text_iter_get_text (&start
, &end
);
436 } /* else the string will be null which is okay */
438 widget
= g_object_get_data (G_OBJECT (w_current
->tewindow
), "sizeentry");
439 text_size_string
= (char *) gtk_entry_get_text(GTK_ENTRY(widget
));
442 len
= strlen(text_string
);
445 if (text_size_string
) {
446 text_size
= atoi(text_size_string
);
449 if (text_size
== 0) {
450 text_size
= default_text_size
;
453 new_text_alignment
= w_current
->text_alignment
;
455 o_text_edit_end(w_current
, text_string
, len
, text_size
, new_text_alignment
);
458 /*! \brief Response function for the text property dialog
459 * \par Function Description
460 * This function receives the user response of the text property dialog.
461 * The response is either <b>OK</b>, <b>Cancel</b> or delete.
464 void text_edit_dialog_response(GtkWidget
* widget
, gint response
, TOPLEVEL
*w_current
)
467 case GTK_RESPONSE_ACCEPT
:
468 text_edit_dialog_ok(widget
, w_current
);
470 case GTK_RESPONSE_REJECT
:
471 case GTK_RESPONSE_DELETE_EVENT
:
475 printf("text_edit_dialog_response(): strange signal %d\n", response
);
478 i_set_state(w_current
, SELECT
);
479 i_update_toolbar(w_current
);
480 gtk_widget_destroy(w_current
->tewindow
);
481 w_current
->tewindow
= NULL
;
484 /*! \brief Create the edit text properties dialog
485 * \par Function Description
486 * This Function creates the dialog to edit text properties.
487 * \todo Check why there's no color in the calling parameters
488 * \todo If more than one text element is selected, add an unchanged option
490 void text_edit_dialog (TOPLEVEL
*w_current
, char *string
, int text_size
,
493 GtkWidget
*label
= NULL
;
496 GtkWidget
*optionmenu
= NULL
;
497 GtkWidget
*align_menu
= NULL
;
498 GtkWidget
*viewport1
= NULL
;
499 GtkWidget
*textentry
= NULL
;
500 GtkWidget
*sizeentry
= NULL
;
501 GtkWidget
*alignment
;
502 GtkWidget
*scrolled_window
= NULL
;
503 GtkTextBuffer
*textbuffer
;
504 char *text_size_string
;
508 if (!w_current
->tewindow
) {
509 w_current
->tewindow
= gschem_dialog_new_with_buttons(_("Edit Text Properties"),
510 GTK_WINDOW(w_current
->main_window
),
512 "text-edit", w_current
,
519 #if GTK_CHECK_VERSION (2,6,0)
520 /* Set the alternative button order (ok, cancel, help) for other systems */
521 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->tewindow
),
527 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->tewindow
),
528 GTK_RESPONSE_ACCEPT
);
530 gtk_signal_connect(GTK_OBJECT(w_current
->tewindow
), "response",
531 GTK_SIGNAL_FUNC(text_edit_dialog_response
), w_current
);
533 gtk_window_position(GTK_WINDOW (w_current
->tewindow
),
537 vbox
= GTK_DIALOG(w_current
->tewindow
)->vbox
;
538 gtk_container_set_border_width(GTK_CONTAINER(w_current
->tewindow
),DIALOG_BORDER_SPACING
);
539 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
541 /* add a text box if only one object is selected */
542 num_selected
= g_list_length( geda_list_get_glist( w_current
->page_current
->selection_list
));
544 if (num_selected
== 1) {
545 label
= gtk_label_new (_("<b>Text Content</b>"));
546 gtk_label_set_use_markup (GTK_LABEL (label
), TRUE
);
547 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
548 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
550 alignment
= gtk_alignment_new(0,0,1,1);
551 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment
), 0, 0,
552 DIALOG_INDENTATION
, 0);
553 gtk_box_pack_start(GTK_BOX(vbox
), alignment
, TRUE
, TRUE
, 0);
555 viewport1
= gtk_viewport_new (NULL
, NULL
);
556 gtk_widget_set_size_request(GTK_WIDGET(viewport1
),-1,75);
558 scrolled_window
= gtk_scrolled_window_new(NULL
, NULL
);
559 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window
),
560 GTK_POLICY_AUTOMATIC
,
561 GTK_POLICY_AUTOMATIC
);
562 gtk_container_add (GTK_CONTAINER (viewport1
), scrolled_window
);
563 gtk_container_add( GTK_CONTAINER(alignment
), viewport1
);
565 textentry
= gtk_text_view_new();
566 gtk_text_view_set_editable(GTK_TEXT_VIEW(textentry
), TRUE
);
567 select_all_text_in_textview(GTK_TEXT_VIEW(textentry
));
569 /*! \bug FIXME: Set tab's width in the textview widget. */
570 /* See first the code in text_input_dialog and get it working before adding it here. */
572 gtk_container_add(GTK_CONTAINER(scrolled_window
), textentry
);
573 gtk_widget_grab_focus(textentry
);
574 GLADE_HOOKUP_OBJECT(w_current
->tewindow
, textentry
,"textentry");
577 label
= gtk_label_new(_("<b>Text Properties</b>"));
578 gtk_label_set_use_markup(GTK_LABEL(label
), TRUE
);
579 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
580 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
582 alignment
= gtk_alignment_new(0,0,1,1);
583 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment
), 0, 0,
584 DIALOG_INDENTATION
, 0);
585 gtk_box_pack_start(GTK_BOX(vbox
), alignment
, FALSE
, FALSE
, 0);
587 table
= gtk_table_new (3, 2, FALSE
);
588 gtk_table_set_row_spacings(GTK_TABLE(table
), DIALOG_V_SPACING
);
589 gtk_table_set_col_spacings(GTK_TABLE(table
), DIALOG_H_SPACING
);
590 gtk_container_add(GTK_CONTAINER(alignment
), table
);
592 label
= gtk_label_new(_("Color:"));
593 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
594 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,0,1, GTK_FILL
,0,0,0);
596 optionmenu
= gtk_option_menu_new();
597 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu
),
598 create_color_menu(w_current
, &select_index
));
599 gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu
), select_index
);
600 gtk_table_attach_defaults(GTK_TABLE(table
), optionmenu
, 1,2,0,1);
602 label
= gtk_label_new(_("Size:"));
603 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
604 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,1,2, GTK_FILL
,0,0,0);
606 sizeentry
= gtk_entry_new_with_max_length (10);
607 gtk_editable_select_region(GTK_EDITABLE (sizeentry
), 0, -1);
608 gtk_table_attach_defaults(GTK_TABLE(table
), sizeentry
, 1,2,1,2);
609 gtk_entry_set_activates_default(GTK_ENTRY(sizeentry
), TRUE
);
611 label
= gtk_label_new(_("Alignment:"));
612 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
613 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,2,3, GTK_FILL
,0,0,0);
615 optionmenu
= gtk_option_menu_new ();
616 align_menu
= create_menu_alignment (w_current
);
617 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu
),
619 gtk_option_menu_set_history(GTK_OPTION_MENU (optionmenu
),
621 w_current
->text_alignment
= text_alignment
;
622 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_menu_get_active(GTK_MENU(align_menu
))),
624 gtk_table_attach_defaults(GTK_TABLE(table
), optionmenu
, 1,2,2,3);
626 GLADE_HOOKUP_OBJECT(w_current
->tewindow
, sizeentry
,"sizeentry");
627 gtk_widget_show_all(w_current
->tewindow
);
630 else { /* dialog already there */
631 gtk_window_present(GTK_WINDOW(w_current
->tewindow
));
634 if (string
!= NULL
) {
635 if (num_selected
== 1) { /* only if one thing is selected */
636 textentry
= g_object_get_data (G_OBJECT (w_current
->tewindow
), "textentry");
637 textbuffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(textentry
));
638 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(textbuffer
), string
, -1);
639 select_all_text_in_textview(GTK_TEXT_VIEW(textentry
));
643 text_size_string
= g_strdup_printf("%d", text_size
);
644 sizeentry
= g_object_get_data (G_OBJECT (w_current
->tewindow
), "sizeentry");
645 gtk_entry_set_text(GTK_ENTRY(sizeentry
),
647 g_free(text_size_string
);
650 /***************** End of Text Edit dialog box ************************/
652 /***************** Start of Line Type/width dialog box ****************/
654 /*! \brief Create a line type menu for the line type dialog
655 * \par Function Description
656 * This function creates a GtkMenu with the different linetypes.
658 static GtkWidget
*create_menu_linetype (TOPLEVEL
*w_current
)
665 } types
[] = { { N_("Solid"), TYPE_SOLID
},
666 { N_("Dotted"), TYPE_DOTTED
},
667 { N_("Dashed"), TYPE_DASHED
},
668 { N_("Center"), TYPE_CENTER
},
669 { N_("Phantom"), TYPE_PHANTOM
} };
672 menu
= gtk_menu_new ();
675 for (i
= 0; i
< sizeof (types
) / sizeof (struct line_type
); i
++) {
678 menuitem
= gtk_radio_menu_item_new_with_label (group
, _(types
[i
].str
));
679 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
680 gtk_menu_append (GTK_MENU (menu
), menuitem
);
681 gtk_object_set_data (GTK_OBJECT(menuitem
), "linetype",
682 GINT_TO_POINTER (types
[i
].type
));
683 gtk_widget_show (menuitem
);
689 /*! \brief Callback function for the linetype menu item in the line type dialog
690 * \par Function Description
691 * This Function is called when the user changes the line type selection.
692 * It sets the dash space/length entries either active or inactive.
694 static gint
line_type_dialog_linetype_change(GtkWidget
*w
, gpointer data
)
696 struct line_type_data
*line_type_data
= (struct line_type_data
*) data
;
698 gboolean activate_length_entry
, activate_space_entry
;
701 menuitem
= gtk_menu_get_active (
702 GTK_MENU (gtk_option_menu_get_menu (
703 GTK_OPTION_MENU (line_type_data
->line_type
))));
705 type
= GPOINTER_TO_INT(
706 gtk_object_get_data (GTK_OBJECT (menuitem
), "linetype"));
709 activate_length_entry
= FALSE
;
710 activate_space_entry
= FALSE
;
713 activate_length_entry
= FALSE
;
714 activate_space_entry
= TRUE
;
719 activate_length_entry
= TRUE
;
720 activate_space_entry
= TRUE
;
723 activate_length_entry
= TRUE
;
724 activate_space_entry
= TRUE
;
727 gtk_widget_set_sensitive (line_type_data
->space_entry
,
728 activate_space_entry
);
729 gtk_widget_set_sensitive (line_type_data
->length_entry
,
730 activate_length_entry
);
736 /*! \brief Worker function for the line type and width dialog
737 * \par Function Description
738 * The function takes the properties of the dialog and applies
739 * them to the selected objects.
741 static void line_type_dialog_ok(GtkWidget
*w
, gpointer data
)
743 struct line_type_data
*line_type_data
= (struct line_type_data
*)data
;
746 const gchar
*width_str
, *length_str
, *space_str
;
749 /* retrieve the list of objects and the toplevel */
750 objects
= line_type_data
->objects
;
751 toplevel
= line_type_data
->toplevel
;
753 /* get the new values from the text entries of the dialog */
754 width_str
= gtk_entry_get_text (GTK_ENTRY (
755 line_type_data
->width_entry
));
756 length_str
= gtk_entry_get_text (GTK_ENTRY (
757 line_type_data
->length_entry
));
758 space_str
= gtk_entry_get_text (GTK_ENTRY (
759 line_type_data
->space_entry
));
760 type
= GPOINTER_TO_INT(
761 gtk_object_get_data (
763 gtk_menu_get_active (
764 GTK_MENU (gtk_option_menu_get_menu (
766 line_type_data
->line_type
))))), "linetype"));
768 /* are there several objects concerned? */
769 if (g_list_next (objects
) == NULL
) {
770 /* no, there is only one object */
771 OBJECT
*o_current
= (OBJECT
*) objects
->data
;
772 gint width
, length
, space
;
774 width
= atoi (width_str
);
775 length
= atoi (length_str
);
776 space
= atoi (space_str
);
778 /* apply the new line options to object */
779 o_erase_single (toplevel
, o_current
);
780 o_set_line_options (toplevel
, o_current
,
786 o_redraw_single (toplevel
, o_current
);
789 /* more than one object in the list */
791 gint width
, length
, space
;
793 /* get the new line options */
794 width
= g_strcasecmp (width_str
,
795 _("*unchanged*")) ? atoi (width_str
) : -1;
796 length
= g_strcasecmp (length_str
,
797 _("*unchanged*")) ? atoi (length_str
) : -1;
798 space
= g_strcasecmp (space_str
,
799 _("*unchanged*")) ? atoi (space_str
) : -1;
801 /* apply changes to each object */
803 while (object
!= NULL
) {
804 OBJECT
*o_current
= (OBJECT
*)object
->data
;
806 o_erase_single (toplevel
, o_current
);
807 o_set_line_options (toplevel
, o_current
,
809 type
== -1 ? o_current
->line_type
: type
,
810 width
== -1 ? o_current
->line_width
: width
,
811 length
== -1 ? o_current
->line_length
: length
,
812 space
== -1 ? o_current
->line_space
: space
);
813 o_redraw_single (toplevel
, o_current
);
815 object
= object
->next
;
819 toplevel
->page_current
->CHANGED
= 1;
822 /*! \brief response function for the line type and width dialog
823 * \par Function Description
824 * This function takes the user input and applies it to selected
826 * After that it kills the dialog.
828 void line_type_dialog_response(GtkWidget
*widget
, gint response
,
829 struct line_type_data
*line_type_data
)
832 case GTK_RESPONSE_REJECT
:
833 case GTK_RESPONSE_DELETE_EVENT
:
836 case GTK_RESPONSE_ACCEPT
:
837 line_type_dialog_ok(widget
, line_type_data
);
840 printf("line_type_dialog_response(): strange signal %d\n",response
);
843 i_set_state (line_type_data
->toplevel
, SELECT
);
844 i_update_toolbar (line_type_data
->toplevel
);
845 gtk_widget_destroy (line_type_data
->dialog
);
847 /* get ride of the list of objects but not the objects */
848 g_list_free (line_type_data
->objects
);
849 g_free (line_type_data
);
852 /*! \brief Creates the line type and width dialog
853 * \par Function Description
854 * This function creates and sets up a dialog for manipulating the
855 * line width and the line type setting of objects.
857 void line_type_dialog (TOPLEVEL
*w_current
, GList
*objects
)
861 GtkWidget
*optionmenu
= NULL
;
862 GtkWidget
*length_entry
= NULL
;
863 GtkWidget
*space_entry
= NULL
;
864 GtkWidget
*width_entry
= NULL
;
867 struct line_type_data
*line_type_data
;
868 gchar
*width_str
, *space_str
, *length_str
;
871 line_type_data
= (struct line_type_data
*) g_malloc (
872 sizeof (struct line_type_data
));
874 dialog
= gschem_dialog_new_with_buttons(_("Edit Line Width & Type"),
875 GTK_WINDOW(w_current
->main_window
),
877 "line-type", w_current
,
884 #if GTK_CHECK_VERSION (2,6,0)
885 /* Set the alternative button order (ok, cancel, help) for other systems */
886 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog
),
892 gtk_window_position(GTK_WINDOW (dialog
), GTK_WIN_POS_MOUSE
);
894 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_ACCEPT
);
896 gtk_signal_connect(GTK_OBJECT(dialog
), "response",
897 GTK_SIGNAL_FUNC(line_type_dialog_response
),
900 gtk_container_border_width(GTK_CONTAINER(dialog
),
901 DIALOG_BORDER_SPACING
);
902 vbox
= GTK_DIALOG(dialog
)->vbox
;
903 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
905 /* Don't know whether to set the headline or not (Werner) */
906 /* label = gtk_label_new(_("Line Properties:"));
907 gtk_misc_set_alignment(GTK_MISC(label),0,0);
908 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); */
910 table
= gtk_table_new (4, 2, FALSE
);
911 gtk_table_set_row_spacings(GTK_TABLE(table
), DIALOG_V_SPACING
);
912 gtk_table_set_col_spacings(GTK_TABLE(table
), DIALOG_H_SPACING
);
913 gtk_box_pack_start(GTK_BOX(vbox
), table
, FALSE
, FALSE
, 0);
915 label
= gtk_label_new (_("Width:"));
916 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
917 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,0,1, GTK_FILL
,0,0,0);
919 label
= gtk_label_new (_("Type:"));
920 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
921 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,1,2, GTK_FILL
,0,0,0);
923 label
= gtk_label_new (_("Dash Length:"));
924 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
925 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,2,3, GTK_FILL
,0,0,0);
927 label
= gtk_label_new (_("Dash Space:"));
928 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
929 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,3,4, GTK_FILL
,0,0,0);
931 width_entry
= gtk_entry_new();
932 gtk_entry_set_activates_default (GTK_ENTRY(width_entry
), TRUE
);
933 gtk_editable_select_region(GTK_EDITABLE(width_entry
), 0, -1);
934 gtk_table_attach_defaults(GTK_TABLE(table
), width_entry
,
937 optionmenu
= gtk_option_menu_new ();
938 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu
),
939 create_menu_linetype (w_current
));
940 gtk_table_attach_defaults(GTK_TABLE(table
), optionmenu
,
943 gtk_signal_connect(GTK_OBJECT (optionmenu
), "changed",
944 (GtkSignalFunc
) line_type_dialog_linetype_change
,
947 length_entry
= gtk_entry_new();
948 gtk_entry_set_activates_default (GTK_ENTRY(length_entry
), TRUE
);
949 gtk_editable_select_region(GTK_EDITABLE(length_entry
), 0, -1);
950 gtk_table_attach_defaults(GTK_TABLE(table
), length_entry
,
953 space_entry
= gtk_entry_new();
954 gtk_entry_set_activates_default (GTK_ENTRY(space_entry
), TRUE
);
955 gtk_editable_select_region(GTK_EDITABLE(space_entry
), 0, -1);
956 gtk_table_attach_defaults(GTK_TABLE(table
), space_entry
,
959 /* populate the data structure */
960 line_type_data
->dialog
= dialog
;
961 line_type_data
->width_entry
= width_entry
;
962 line_type_data
->line_type
= optionmenu
;
963 line_type_data
->length_entry
= length_entry
;
964 line_type_data
->space_entry
= space_entry
;
966 line_type_data
->toplevel
= w_current
;
967 line_type_data
->objects
= objects
;
969 /* fill in the fields of the dialog */
970 if (g_list_next (objects
) == NULL
) {
971 /* only one object in object list */
972 OBJECT
*o_current
= (OBJECT
*) objects
->data
;
974 width_str
= g_strdup_printf ("%d", o_current
->line_width
);
975 space_str
= g_strdup_printf ("%d", o_current
->line_space
);
976 length_str
= g_strdup_printf ("%d", o_current
->line_length
);
977 type
= o_current
->line_type
;
982 width_str
= g_strdup_printf (_("*unchanged*"));
983 space_str
= g_strdup_printf (_("*unchanged*"));
984 length_str
= g_strdup_printf (_("*unchanged*"));
985 type
= TYPE_PHANTOM
+ 1;
987 /* add a new menuitem to option menu for line type */
988 menu
= gtk_option_menu_get_menu (GTK_OPTION_MENU (optionmenu
));
989 menuitem
= gtk_radio_menu_item_new_with_label (
990 gtk_radio_menu_item_get_group (
991 GTK_RADIO_MENU_ITEM (gtk_menu_get_active (GTK_MENU (menu
)))),
993 gtk_menu_append (menu
, menuitem
);
994 gtk_object_set_data (GTK_OBJECT (menuitem
),
996 GINT_TO_POINTER (-1));
997 gtk_widget_show (menuitem
);
1000 gtk_entry_set_text (GTK_ENTRY (width_entry
), width_str
);
1001 gtk_entry_select_region (GTK_ENTRY (width_entry
), 0, strlen (width_str
));
1002 gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu
), type
);
1003 gtk_entry_set_text (GTK_ENTRY (space_entry
), space_str
);
1004 gtk_entry_set_text (GTK_ENTRY (length_entry
), length_str
);
1006 /* calling it once will set the dash space/length activity */
1007 line_type_dialog_linetype_change(optionmenu
, line_type_data
);
1009 gtk_widget_grab_focus(width_entry
);
1010 gtk_widget_show_all (dialog
);
1014 g_free (length_str
);
1017 /***************** End of Line Type / Width dialog box ****************/
1019 /***************** Start of Fill Type dialog box **********************/
1021 /*! \brief Create a menu with fill types for the line type dialog
1022 * \par Function Description
1023 * This function creates a GtkMenu with the different fill types.
1025 static GtkWidget
*create_menu_filltype (TOPLEVEL
*w_current
)
1031 OBJECT_FILLING type
;
1032 } types
[] = { { N_("Hollow"), FILLING_HOLLOW
},
1033 { N_("Filled"), FILLING_FILL
},
1034 { N_("Mesh"), FILLING_MESH
},
1035 { N_("Hatch"), FILLING_HATCH
} };
1038 menu
= gtk_menu_new ();
1041 for (i
= 0; i
< sizeof (types
) / sizeof (struct fill_type
); i
++) {
1042 GtkWidget
*menuitem
;
1044 menuitem
= gtk_radio_menu_item_new_with_label (group
, _(types
[i
].str
));
1045 group
= gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem
));
1046 gtk_menu_append (GTK_MENU (menu
), menuitem
);
1047 gtk_object_set_data (GTK_OBJECT(menuitem
), "filltype",
1048 GINT_TO_POINTER (types
[i
].type
));
1049 gtk_widget_show (menuitem
);
1055 /*! \brief Callback function for the filltype menu in the filltype dialog
1056 * \par Function Description
1057 * This function sets the entry activity according to the selected
1058 * filltype of the filltype dialog.
1060 static gint
fill_type_dialog_filltype_change(GtkWidget
*w
, gpointer data
)
1062 struct fill_type_data
*fill_type_data
= (struct fill_type_data
*) data
;
1063 GtkWidget
*menuitem
;
1064 gboolean activate_width_entry
;
1065 gboolean activate_anglepitch1_entries
;
1066 gboolean activate_anglepitch2_entries
;
1069 menuitem
= gtk_menu_get_active (
1070 GTK_MENU (gtk_option_menu_get_menu (
1071 GTK_OPTION_MENU (fill_type_data
->fill_type
))));
1073 type
= GPOINTER_TO_INT(
1074 gtk_object_get_data (GTK_OBJECT (menuitem
), "filltype"));
1076 case(FILLING_HOLLOW
):
1078 activate_width_entry
= FALSE
;
1079 activate_anglepitch1_entries
= FALSE
;
1080 activate_anglepitch2_entries
= FALSE
;
1082 case(FILLING_HATCH
):
1083 activate_width_entry
= TRUE
;
1084 activate_anglepitch1_entries
= TRUE
;
1085 activate_anglepitch2_entries
= FALSE
;
1088 activate_width_entry
= TRUE
;
1089 activate_anglepitch1_entries
= TRUE
;
1090 activate_anglepitch2_entries
= TRUE
;
1093 activate_width_entry
= TRUE
;
1094 activate_anglepitch1_entries
= TRUE
;
1095 activate_anglepitch2_entries
= TRUE
;
1098 gtk_widget_set_sensitive (fill_type_data
->width_entry
,
1099 activate_width_entry
);
1100 gtk_widget_set_sensitive (fill_type_data
->angle1_entry
,
1101 activate_anglepitch1_entries
);
1102 gtk_widget_set_sensitive (fill_type_data
->pitch1_entry
,
1103 activate_anglepitch1_entries
);
1104 gtk_widget_set_sensitive (fill_type_data
->angle2_entry
,
1105 activate_anglepitch2_entries
);
1106 gtk_widget_set_sensitive (fill_type_data
->pitch2_entry
,
1107 activate_anglepitch2_entries
);
1112 /*! \brief Apply the settings of the filltype dialog to the selection
1113 * \par Function Description
1114 * This function applies the settings of the filltype dialog to the
1117 static void fill_type_dialog_ok(GtkWidget
*w
, gpointer data
)
1119 struct fill_type_data
*fill_type_data
= (struct fill_type_data
*)data
;
1122 const gchar
*width_str
, *angle1_str
, *pitch1_str
, *angle2_str
, *pitch2_str
;
1123 OBJECT_FILLING type
;
1125 /* retrieve the list of objects and the toplevel */
1126 objects
= fill_type_data
->objects
;
1127 toplevel
= fill_type_data
->toplevel
;
1129 /* get the new values from the text entries of the dialog */
1130 width_str
= gtk_entry_get_text (GTK_ENTRY (
1131 fill_type_data
->width_entry
));
1132 angle1_str
= gtk_entry_get_text (GTK_ENTRY (
1133 fill_type_data
->angle1_entry
));
1134 pitch1_str
= gtk_entry_get_text (GTK_ENTRY (
1135 fill_type_data
->pitch1_entry
));
1136 angle2_str
= gtk_entry_get_text (GTK_ENTRY (
1137 fill_type_data
->angle2_entry
));
1138 pitch2_str
= gtk_entry_get_text (GTK_ENTRY (
1139 fill_type_data
->pitch2_entry
));
1140 type
= GPOINTER_TO_INT(
1141 gtk_object_get_data (
1143 gtk_menu_get_active (
1144 GTK_MENU (gtk_option_menu_get_menu (
1146 fill_type_data
->fill_type
))))), "filltype"));
1148 /* are there several objects concerned? */
1149 if (g_list_next (objects
) == NULL
) {
1150 /* no, there is only one object */
1151 OBJECT
*o_current
= (OBJECT
*) objects
->data
;
1152 gint width
, angle1
, pitch1
, angle2
, pitch2
;
1154 width
= atoi (width_str
);
1155 angle1
= atoi (angle1_str
);
1156 pitch1
= atoi (pitch1_str
);
1157 angle2
= atoi (angle2_str
);
1158 pitch2
= atoi (pitch2_str
);
1160 /* apply the new line options to object */
1161 o_erase_single (toplevel
, o_current
);
1162 o_set_fill_options(toplevel
, o_current
,
1166 o_redraw_single (toplevel
, o_current
);
1169 /* more than one object in the list */
1171 gint width
, angle1
, pitch1
, angle2
, pitch2
;
1173 /* get the new line options */
1174 width
= g_strcasecmp (width_str
,
1175 _("*unchanged*")) ? atoi (width_str
) : -1;
1176 angle1
= g_strcasecmp (angle1_str
,
1177 _("*unchanged*")) ? atoi (angle1_str
) : -1;
1178 pitch1
= g_strcasecmp (pitch1_str
,
1179 _("*unchanged*")) ? atoi (pitch1_str
) : -1;
1180 angle2
= g_strcasecmp (angle2_str
,
1181 _("*unchanged*")) ? atoi (angle2_str
) : -1;
1182 pitch2
= g_strcasecmp (pitch2_str
,
1183 _("*unchanged*")) ? atoi (pitch2_str
) : -1;
1185 /* apply changes to each object */
1187 while (object
!= NULL
) {
1188 OBJECT
*o_current
= (OBJECT
*)object
->data
;
1190 o_erase_single (toplevel
, o_current
);
1191 o_set_fill_options (toplevel
, o_current
,
1192 type
== -1 ? o_current
->fill_type
: type
,
1193 width
== -1 ? o_current
->fill_width
: width
,
1194 pitch1
== -1 ? o_current
->fill_pitch1
: pitch1
,
1195 angle1
== -1 ? o_current
->fill_angle1
: angle1
,
1196 pitch2
== -1 ? o_current
->fill_pitch2
: pitch2
,
1197 angle2
== -1 ? o_current
->fill_angle2
: angle2
);
1198 o_redraw_single (toplevel
, o_current
);
1200 object
= object
->next
;
1203 toplevel
->page_current
->CHANGED
= 1;
1206 /*! \brief response function for the filltype dialog
1207 * \par Function Description
1208 * This function handles the user response to the filltype dialog.
1209 * It destroys the dialog after that.
1211 void fill_type_dialog_response(GtkWidget
*widget
, gint response
,
1212 struct fill_type_data
*fill_type_data
)
1215 case GTK_RESPONSE_REJECT
:
1216 case GTK_RESPONSE_DELETE_EVENT
:
1219 case GTK_RESPONSE_ACCEPT
:
1220 fill_type_dialog_ok(widget
, fill_type_data
);
1223 printf("line_type_dialog_response(): strange signal %d\n",response
);
1226 i_set_state (fill_type_data
->toplevel
, SELECT
);
1227 i_update_toolbar (fill_type_data
->toplevel
);
1229 gtk_grab_remove (fill_type_data
->dialog
);
1230 gtk_widget_destroy (fill_type_data
->dialog
);
1232 /* get ride of the list of objects but not the objects */
1233 g_list_free (fill_type_data
->objects
);
1234 g_free (fill_type_data
);
1237 /*! \brief Creates the fill type dialog
1238 * \par Function Description
1239 * This function creates the fill type dialog. It operates on a list
1242 void fill_type_dialog(TOPLEVEL
*w_current
, GList
*objects
)
1246 GtkWidget
*optionmenu
= NULL
;
1247 GtkWidget
*width_entry
= NULL
;
1248 GtkWidget
*angle1_entry
= NULL
;
1249 GtkWidget
*pitch1_entry
= NULL
;
1250 GtkWidget
*angle2_entry
= NULL
;
1251 GtkWidget
*pitch2_entry
= NULL
;
1254 struct fill_type_data
*fill_type_data
;
1255 gchar
*width_str
, *angle1_str
, *pitch1_str
, *angle2_str
, *pitch2_str
;
1258 fill_type_data
= (struct fill_type_data
*) g_malloc (
1259 sizeof (struct fill_type_data
));
1261 dialog
= gschem_dialog_new_with_buttons(_("Edit Fill Type"),
1262 GTK_WINDOW(w_current
->main_window
),
1264 "fill-type", w_current
,
1266 GTK_RESPONSE_REJECT
,
1268 GTK_RESPONSE_ACCEPT
,
1271 #if GTK_CHECK_VERSION (2,6,0)
1272 /* Set the alternative button order (ok, cancel, help) for other systems */
1273 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog
),
1274 GTK_RESPONSE_ACCEPT
,
1275 GTK_RESPONSE_REJECT
,
1279 gtk_window_position(GTK_WINDOW (dialog
), GTK_WIN_POS_MOUSE
);
1281 gtk_dialog_set_default_response(GTK_DIALOG(dialog
),
1282 GTK_RESPONSE_ACCEPT
);
1284 gtk_signal_connect(GTK_OBJECT(dialog
), "response",
1285 GTK_SIGNAL_FUNC(fill_type_dialog_response
), fill_type_data
);
1287 gtk_container_border_width(GTK_CONTAINER(dialog
), DIALOG_BORDER_SPACING
);
1288 vbox
= GTK_DIALOG(dialog
)->vbox
;
1289 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
1291 /* Don't know whether to use the headline or not (Werner) */
1292 /* label = gtk_label_new(_("Fill Properties:"));
1293 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1294 gtk_box_pack_start(GTK_BOX(vbox),label, FALSE, FALSE, 0); */
1296 table
= gtk_table_new (6, 2, FALSE
);
1297 gtk_table_set_row_spacings(GTK_TABLE(table
), DIALOG_V_SPACING
);
1298 gtk_table_set_col_spacings(GTK_TABLE(table
), DIALOG_H_SPACING
);
1299 gtk_box_pack_start(GTK_BOX(vbox
), table
, FALSE
, FALSE
, 0);
1301 label
= gtk_label_new (_("Fill Type:"));
1302 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1303 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,0,1, GTK_FILL
,0,0,0);
1305 label
= gtk_label_new (_("Line Width:"));
1306 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1307 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,1,2, GTK_FILL
,0,0,0);
1309 label
= gtk_label_new (_("Angle 1:"));
1310 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1311 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,2,3, GTK_FILL
,0,0,0);
1313 label
= gtk_label_new (_("Pitch 1:"));
1314 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1315 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,3,4, GTK_FILL
,0,0,0);
1317 label
= gtk_label_new (_("Angle 2:"));
1318 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1319 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,4,5, GTK_FILL
,0,0,0);
1321 label
= gtk_label_new (_("Pitch 2:"));
1322 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1323 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,5,6, GTK_FILL
,0,0,0);
1326 optionmenu
= gtk_option_menu_new ();
1327 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu
),
1328 create_menu_filltype (w_current
));
1329 gtk_table_attach_defaults(GTK_TABLE(table
), optionmenu
,
1332 gtk_signal_connect(GTK_OBJECT (optionmenu
), "changed",
1333 (GtkSignalFunc
) fill_type_dialog_filltype_change
,
1336 width_entry
= gtk_entry_new();
1337 gtk_entry_set_activates_default (GTK_ENTRY(width_entry
), TRUE
);
1338 gtk_table_attach_defaults(GTK_TABLE(table
), width_entry
,
1341 angle1_entry
= gtk_entry_new ();
1342 gtk_entry_set_activates_default (GTK_ENTRY(angle1_entry
), TRUE
);
1343 gtk_table_attach_defaults(GTK_TABLE(table
), angle1_entry
,
1346 pitch1_entry
= gtk_entry_new ();
1347 gtk_entry_set_activates_default (GTK_ENTRY(pitch1_entry
), TRUE
);
1348 gtk_table_attach_defaults(GTK_TABLE(table
), pitch1_entry
,
1351 angle2_entry
= gtk_entry_new ();
1352 gtk_entry_set_activates_default (GTK_ENTRY(angle2_entry
), TRUE
);
1353 gtk_table_attach_defaults(GTK_TABLE(table
), angle2_entry
,
1356 pitch2_entry
= gtk_entry_new ();
1357 gtk_entry_set_activates_default (GTK_ENTRY(pitch2_entry
), TRUE
);
1358 gtk_table_attach_defaults(GTK_TABLE(table
), pitch2_entry
,
1361 /* populate the data structure */
1362 fill_type_data
->dialog
= dialog
;
1363 fill_type_data
->fill_type
= optionmenu
;
1364 fill_type_data
->width_entry
= width_entry
;
1365 fill_type_data
->angle1_entry
= angle1_entry
;
1366 fill_type_data
->pitch1_entry
= pitch1_entry
;
1367 fill_type_data
->angle2_entry
= angle2_entry
;
1368 fill_type_data
->pitch2_entry
= pitch2_entry
;
1370 fill_type_data
->toplevel
= w_current
;
1371 fill_type_data
->objects
= objects
;
1373 /* fill in the fields of the dialog */
1374 if (g_list_next (objects
) == NULL
) {
1375 /* only one object in object list */
1376 OBJECT
*o_current
= (OBJECT
*) objects
->data
;
1378 type
= o_current
->fill_type
;
1379 width_str
= g_strdup_printf ("%d", o_current
->fill_width
);
1380 angle1_str
= g_strdup_printf ("%d", o_current
->fill_angle1
);
1381 pitch1_str
= g_strdup_printf ("%d", o_current
->fill_pitch1
);
1382 angle2_str
= g_strdup_printf ("%d", o_current
->fill_angle2
);
1383 pitch2_str
= g_strdup_printf ("%d", o_current
->fill_pitch2
);
1385 GtkWidget
*menuitem
;
1388 width_str
= g_strdup_printf (_("*unchanged*"));
1389 angle1_str
= g_strdup_printf (_("*unchanged*"));
1390 pitch1_str
= g_strdup_printf (_("*unchanged*"));
1391 angle2_str
= g_strdup_printf (_("*unchanged*"));
1392 pitch2_str
= g_strdup_printf (_("*unchanged*"));
1393 type
= FILLING_HATCH
+ 1;
1395 /* add a new menuitem to option menu for line type */
1396 menu
= gtk_option_menu_get_menu (GTK_OPTION_MENU (optionmenu
));
1397 menuitem
= gtk_radio_menu_item_new_with_label (
1398 gtk_radio_menu_item_get_group (
1399 GTK_RADIO_MENU_ITEM (gtk_menu_get_active (GTK_MENU (menu
)))),
1401 gtk_menu_append (menu
, menuitem
);
1402 gtk_object_set_data (GTK_OBJECT (menuitem
),
1404 GINT_TO_POINTER (-1));
1405 gtk_widget_show (menuitem
);
1408 gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu
), type
);
1409 gtk_entry_set_text (GTK_ENTRY (width_entry
), width_str
);
1410 gtk_entry_select_region (GTK_ENTRY (width_entry
), 0, strlen (width_str
));
1411 gtk_entry_set_text (GTK_ENTRY (angle1_entry
), angle1_str
);
1412 gtk_entry_select_region (GTK_ENTRY (angle1_entry
), 0, strlen (angle1_str
));
1413 gtk_entry_set_text (GTK_ENTRY (pitch1_entry
), pitch1_str
);
1414 gtk_entry_select_region (GTK_ENTRY (pitch1_entry
), 0, strlen (pitch1_str
));
1415 gtk_entry_set_text (GTK_ENTRY (angle2_entry
), angle2_str
);
1416 gtk_entry_select_region (GTK_ENTRY (angle2_entry
), 0, strlen (angle2_str
));
1417 gtk_entry_set_text (GTK_ENTRY (pitch2_entry
), pitch2_str
);
1418 gtk_entry_select_region (GTK_ENTRY (pitch2_entry
), 0, strlen (pitch2_str
));
1420 /* Set the widget activity according to the current filltype */
1421 fill_type_dialog_filltype_change(optionmenu
, fill_type_data
);
1423 gtk_widget_grab_focus(width_entry
);
1424 gtk_widget_show_all (dialog
);
1427 g_free (angle1_str
);
1428 g_free (pitch1_str
);
1429 g_free (angle2_str
);
1430 g_free (pitch2_str
);
1433 /***************** End of Fill Type dialog box ***********************/
1435 /***************** Start of Arc dialog box ***************************/
1437 /*! \brief response function for the arc angle dialog
1438 * \par Function Description
1439 * The response function of th arc angle dialog takes the content of
1440 * the dialog and applies it on the current arc.
1441 * If the dialog is closed or canceled the function destroys the dialog.
1443 void arc_angle_dialog_response(GtkWidget
*w
, gint response
,
1444 TOPLEVEL
*w_current
)
1446 GtkWidget
*spinentry
;
1447 gint start_angle
, sweep_angle
;
1450 case GTK_RESPONSE_REJECT
:
1451 case GTK_RESPONSE_DELETE_EVENT
:
1454 case GTK_RESPONSE_ACCEPT
:
1455 spinentry
= g_object_get_data(G_OBJECT(w_current
->aawindow
),"spin_start");
1456 start_angle
= gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinentry
));
1457 spinentry
= g_object_get_data(G_OBJECT(w_current
->aawindow
),"spin_sweep");
1458 sweep_angle
= gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinentry
));
1460 o_arc_end4(w_current
, start_angle
, sweep_angle
);
1463 printf("arc_angle_dialog_response(): strange signal %d\n",response
);
1466 gtk_widget_destroy(w_current
->aawindow
);
1467 w_current
->aawindow
= NULL
;
1468 w_current
->event_state
= DRAWARC
;
1471 /*! \brief Creates the arc angle dialog
1472 * \par Function Description
1473 * This function create the arc angle dialog.
1475 void arc_angle_dialog (TOPLEVEL
*w_current
)
1477 GtkWidget
*label
= NULL
;
1479 GtkWidget
*alignment
, *table
;
1480 GtkWidget
*spin_start
, *spin_sweep
;
1482 if (!w_current
->aawindow
) {
1483 w_current
->aawindow
= gschem_dialog_new_with_buttons(_("Arc Params"),
1484 GTK_WINDOW(w_current
->main_window
),
1486 "arc-angle", w_current
,
1488 GTK_RESPONSE_REJECT
,
1490 GTK_RESPONSE_ACCEPT
,
1493 #if GTK_CHECK_VERSION (2,6,0)
1494 /* Set the alternative button order (ok, cancel, help) for other systems */
1495 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->aawindow
),
1496 GTK_RESPONSE_ACCEPT
,
1497 GTK_RESPONSE_REJECT
,
1501 gtk_window_position(GTK_WINDOW(w_current
->aawindow
),
1504 gtk_signal_connect(GTK_OBJECT(w_current
->aawindow
), "response",
1505 GTK_SIGNAL_FUNC(arc_angle_dialog_response
), w_current
);
1507 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->aawindow
),
1508 GTK_RESPONSE_ACCEPT
);
1510 gtk_container_border_width(GTK_CONTAINER(w_current
->aawindow
), DIALOG_BORDER_SPACING
);
1511 vbox
= GTK_DIALOG(w_current
->aawindow
)->vbox
;
1512 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
1515 alignment
= gtk_alignment_new(0,0,1,1);
1516 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment
), 0, 0,
1517 0 /*DIALOG_INDENTATION */, 0);
1518 gtk_box_pack_start(GTK_BOX(vbox
), alignment
, FALSE
, FALSE
, 0);
1520 table
= gtk_table_new (2, 2, FALSE
);
1521 gtk_table_set_row_spacings(GTK_TABLE(table
), DIALOG_V_SPACING
);
1522 gtk_table_set_col_spacings(GTK_TABLE(table
), DIALOG_H_SPACING
);
1523 gtk_container_add(GTK_CONTAINER(alignment
), table
);
1525 label
= gtk_label_new (_("Start Angle:"));
1526 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1527 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,0,1, GTK_FILL
,0,0,0);
1529 spin_start
= gtk_spin_button_new_with_range(-360,360,1);
1530 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_start
),0);
1531 gtk_widget_grab_focus(spin_start
);
1532 gtk_entry_set_activates_default(GTK_ENTRY(spin_start
), TRUE
);
1533 gtk_table_attach_defaults(GTK_TABLE(table
), spin_start
, 1,2,0,1);
1535 label
= gtk_label_new(_("Degrees of Sweep:"));
1536 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1537 gtk_table_attach(GTK_TABLE(table
), label
, 0,1,1,2, GTK_FILL
,0,0,0);
1539 spin_sweep
= gtk_spin_button_new_with_range(-360,360,1);
1540 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sweep
), 90);
1541 gtk_widget_grab_focus(spin_sweep
);
1542 gtk_entry_set_activates_default(GTK_ENTRY(spin_sweep
), TRUE
);
1543 gtk_table_attach_defaults(GTK_TABLE(table
), spin_sweep
, 1,2,1,2);
1545 GLADE_HOOKUP_OBJECT(w_current
->aawindow
, spin_start
,"spin_start");
1546 GLADE_HOOKUP_OBJECT(w_current
->aawindow
, spin_sweep
,"spin_sweep");
1547 gtk_widget_show_all (w_current
->aawindow
);
1550 else { /* dialog already created */
1551 gtk_window_present (GTK_WINDOW(w_current
->aawindow
));
1555 /***************** End of Arc dialog box *****************************/
1557 /***************** Start of Translate dialog box *********************/
1559 /*! \brief response function for the translate dialog
1560 * \par Function Description
1561 * This function takes the user action and applies it.
1562 * \todo improve error detection / use a spin button?
1564 void translate_dialog_response(GtkWidget
*widget
, gint response
,
1565 TOPLEVEL
*w_current
)
1567 GtkWidget
*textentry
;
1571 case GTK_RESPONSE_REJECT
:
1572 case GTK_RESPONSE_DELETE_EVENT
:
1575 case GTK_RESPONSE_ACCEPT
:
1576 textentry
= g_object_get_data(G_OBJECT(w_current
->trwindow
),"textentry");
1577 string
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(textentry
));
1578 if (strlen(string
) != 0) {
1579 o_complex_translate_all(w_current
, atoi(string
));
1583 printf("translate_edit_dialog_response(): strange signal %d\n",response
);
1586 i_set_state(w_current
, SELECT
);
1587 i_update_toolbar(w_current
);
1588 gtk_widget_destroy(w_current
->trwindow
);
1589 w_current
->trwindow
=NULL
;
1593 /*! \brief Create the translate dialog
1594 * \par Function Description
1595 * Create the dialog to translate symbols.
1597 void translate_dialog (TOPLEVEL
*w_current
)
1600 GtkWidget
*textentry
;
1603 if (!w_current
->trwindow
) {
1604 w_current
->trwindow
= gschem_dialog_new_with_buttons(_("Translate"),
1605 GTK_WINDOW(w_current
->main_window
),
1607 "translate", w_current
,
1609 GTK_RESPONSE_REJECT
,
1611 GTK_RESPONSE_ACCEPT
,
1614 #if GTK_CHECK_VERSION (2,6,0)
1615 /* Set the alternative button order (ok, cancel, help) for other systems */
1616 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->trwindow
),
1617 GTK_RESPONSE_ACCEPT
,
1618 GTK_RESPONSE_REJECT
,
1622 gtk_window_position(GTK_WINDOW (w_current
->trwindow
),
1625 gtk_signal_connect(GTK_OBJECT (w_current
->trwindow
), "response",
1626 GTK_SIGNAL_FUNC(translate_dialog_response
), w_current
);
1628 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->trwindow
),
1629 GTK_RESPONSE_ACCEPT
);
1631 gtk_container_border_width(GTK_CONTAINER(w_current
->trwindow
),
1632 DIALOG_BORDER_SPACING
);
1633 vbox
= GTK_DIALOG(w_current
->trwindow
)->vbox
;
1634 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
1636 label
= gtk_label_new(_("Offset to translate?\n(0 for origin)"));
1637 gtk_misc_set_alignment(GTK_MISC (label
), 0, 0);
1638 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
1640 textentry
= gtk_entry_new_with_max_length (10);
1641 gtk_entry_set_text(GTK_ENTRY(textentry
), "0");
1642 gtk_editable_select_region(GTK_EDITABLE(textentry
), 0, -1);
1643 gtk_entry_set_activates_default(GTK_ENTRY(textentry
), TRUE
);
1644 gtk_box_pack_start(GTK_BOX(vbox
),textentry
, FALSE
, FALSE
, 0);
1646 GLADE_HOOKUP_OBJECT(w_current
->trwindow
, textentry
, "textentry");
1647 gtk_widget_show_all (w_current
->trwindow
);
1650 else { /* dialog already created */
1651 gtk_window_present(GTK_WINDOW(w_current
->trwindow
));
1655 /***************** End of Translate dialog box ***********************/
1657 /***************** Start of Text size dialog box *********************/
1659 /*! \brief response function for the text size dialog
1660 * \par Function Description
1661 * This function takes the user input and applies it to gschem
1663 void text_size_dialog_response(GtkWidget
*w
, gint response
,
1664 TOPLEVEL
*w_current
)
1666 GtkWidget
*spin_size
;
1670 case GTK_RESPONSE_ACCEPT
:
1671 spin_size
= g_object_get_data(G_OBJECT(w_current
->tswindow
),"spin_size");
1672 size
= gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_size
));
1674 w_current
->text_size
= size
;
1675 w_current
->page_current
->CHANGED
=1;
1676 o_undo_savestate(w_current
, UNDO_ALL
);
1678 case GTK_RESPONSE_REJECT
:
1679 case GTK_RESPONSE_DELETE_EVENT
:
1683 printf("text_size_dialog_response(): strange signal %d\n",response
);
1687 i_set_state(w_current
, SELECT
);
1688 i_update_toolbar(w_current
);
1689 gtk_widget_destroy(w_current
->tswindow
);
1690 w_current
->tswindow
= NULL
;
1693 /*! \brief Create the text size dialog
1694 * \par Function Description
1695 * This function creates the text size dialog.
1697 void text_size_dialog (TOPLEVEL
*w_current
)
1699 GtkWidget
*label
= NULL
;
1701 GtkWidget
*spin_size
;
1703 if (!w_current
->tswindow
) {
1704 w_current
->tswindow
= gschem_dialog_new_with_buttons(_("Text Size"),
1705 GTK_WINDOW(w_current
->main_window
),
1707 "text-size", w_current
,
1709 GTK_RESPONSE_REJECT
,
1711 GTK_RESPONSE_ACCEPT
,
1714 #if GTK_CHECK_VERSION (2,6,0)
1715 /* Set the alternative button order (ok, cancel, help) for other systems */
1716 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->tswindow
),
1717 GTK_RESPONSE_ACCEPT
,
1718 GTK_RESPONSE_REJECT
,
1722 gtk_window_position(GTK_WINDOW(w_current
->tswindow
),
1725 gtk_signal_connect(GTK_OBJECT(w_current
->tswindow
), "response",
1726 GTK_SIGNAL_FUNC(text_size_dialog_response
),
1728 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->tswindow
),
1729 GTK_RESPONSE_ACCEPT
);
1731 gtk_container_border_width(GTK_CONTAINER(w_current
->tswindow
),
1732 DIALOG_BORDER_SPACING
);
1733 vbox
= GTK_DIALOG(w_current
->tswindow
)->vbox
;
1734 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
1736 label
= gtk_label_new (_("Enter new text size:"));
1737 gtk_misc_set_alignment (GTK_MISC (label
), 0, 0);
1738 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
1740 spin_size
= gtk_spin_button_new_with_range(2,10000,2);
1741 gtk_editable_select_region( GTK_EDITABLE(spin_size
), 0, -1);
1742 gtk_box_pack_start(GTK_BOX(vbox
), spin_size
, FALSE
, FALSE
, 0);
1743 gtk_entry_set_activates_default(GTK_ENTRY(spin_size
), TRUE
);
1744 gtk_widget_grab_focus(spin_size
);
1746 GLADE_HOOKUP_OBJECT(w_current
->tswindow
, spin_size
, "spin_size");
1747 gtk_widget_show_all(w_current
->tswindow
);
1750 else { /* dialog already created */
1751 gtk_window_present(GTK_WINDOW(w_current
->tswindow
));
1754 /* always set the current text size to the dialog */
1755 spin_size
= g_object_get_data(G_OBJECT(w_current
->tswindow
),"spin_size");
1756 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_size
), w_current
->text_size
);
1757 gtk_editable_select_region(GTK_EDITABLE(spin_size
), 0, -1);
1760 /***************** End of Text size dialog box ***********************/
1762 /***************** Start of Snap size dialog box *********************/
1764 /*! \brief response function for the snap size dialog
1765 * \par Function Description
1766 * This is the response function for the snap size dialog.
1767 * It sets the given snap size to gschem.
1769 void snap_size_dialog_response(GtkWidget
*w
, gint response
,
1770 TOPLEVEL
*w_current
)
1772 GtkWidget
*spin_size
;
1776 case GTK_RESPONSE_ACCEPT
:
1777 spin_size
= g_object_get_data(G_OBJECT(w_current
->tswindow
),"spin_size");
1778 size
= gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_size
));
1780 w_current
->snap_size
= size
;
1781 o_redraw_all(w_current
);
1782 w_current
->page_current
->CHANGED
=1; /* maybe remove those two lines */
1783 o_undo_savestate(w_current
, UNDO_ALL
);
1785 case GTK_RESPONSE_REJECT
:
1786 case GTK_RESPONSE_DELETE_EVENT
:
1790 printf("snap_size_dialog_response(): strange signal %d\n",response
);
1794 i_set_state(w_current
, SELECT
);
1795 i_update_toolbar(w_current
);
1796 gtk_widget_destroy(w_current
->tswindow
);
1797 w_current
->tswindow
= NULL
;
1800 /*! \brief Create the snap size dialog
1801 * \par Function Description
1802 * This function creates the snap size dialog.
1804 void snap_size_dialog (TOPLEVEL
*w_current
)
1806 GtkWidget
*label
= NULL
;
1808 GtkWidget
*spin_size
;
1810 if (!w_current
->tswindow
) {
1811 w_current
->tswindow
= gschem_dialog_new_with_buttons(_("Snap Size"),
1812 GTK_WINDOW(w_current
->main_window
),
1814 "snap-size", w_current
,
1816 GTK_RESPONSE_REJECT
,
1818 GTK_RESPONSE_ACCEPT
,
1821 #if GTK_CHECK_VERSION (2,6,0)
1822 /* Set the alternative button order (ok, cancel, help) for other systems */
1823 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->tswindow
),
1824 GTK_RESPONSE_ACCEPT
,
1825 GTK_RESPONSE_REJECT
,
1829 gtk_window_position(GTK_WINDOW(w_current
->tswindow
),
1832 gtk_signal_connect(GTK_OBJECT(w_current
->tswindow
), "response",
1833 GTK_SIGNAL_FUNC(snap_size_dialog_response
),
1835 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->tswindow
),
1836 GTK_RESPONSE_ACCEPT
);
1838 gtk_container_border_width(GTK_CONTAINER(w_current
->tswindow
),
1839 DIALOG_BORDER_SPACING
);
1840 vbox
= GTK_DIALOG(w_current
->tswindow
)->vbox
;
1841 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
1843 label
= gtk_label_new (_("Enter new snap grid spacing:"));
1844 gtk_misc_set_alignment (GTK_MISC (label
), 0, 0);
1845 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
1847 spin_size
= gtk_spin_button_new_with_range(0,100000,5);
1848 gtk_editable_select_region( GTK_EDITABLE(spin_size
), 0, -1);
1849 gtk_box_pack_start(GTK_BOX(vbox
), spin_size
, FALSE
, FALSE
, 0);
1850 gtk_entry_set_activates_default(GTK_ENTRY(spin_size
), TRUE
);
1851 gtk_widget_grab_focus(spin_size
);
1853 GLADE_HOOKUP_OBJECT(w_current
->tswindow
, spin_size
, "spin_size");
1854 gtk_widget_show_all(w_current
->tswindow
);
1857 else { /* dialog already there */
1858 gtk_window_present(GTK_WINDOW(w_current
->tswindow
));
1861 /* always set the current gschem value to the dialog entry */
1862 spin_size
= g_object_get_data(G_OBJECT(w_current
->tswindow
),"spin_size");
1863 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_size
), w_current
->snap_size
);
1864 gtk_editable_select_region(GTK_EDITABLE(spin_size
), 0, -1);
1867 /***************** End of Snap size dialog box ***********************/
1869 /***************** Start of slot edit dialog box *********************/
1871 /*! \brief response function for the slot edit dialog
1872 * \par Function Description
1873 * The function takes the dialog entry and applies the new slot to the
1876 void slot_edit_dialog_response(GtkWidget
*widget
, gint response
, TOPLEVEL
*w_current
)
1878 GtkWidget
*textentry
;
1880 gchar
*string
= NULL
;
1883 case GTK_RESPONSE_REJECT
:
1884 case GTK_RESPONSE_DELETE_EVENT
:
1887 case GTK_RESPONSE_ACCEPT
:
1888 textentry
= g_object_get_data(G_OBJECT(w_current
->sewindow
),"textentry");
1889 string
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(textentry
));
1890 len
= strlen(string
);
1892 o_slot_end(w_current
, string
, len
);
1896 printf("slot_edit_dialog_response(): strange signal %d\n",response
);
1898 i_set_state(w_current
, SELECT
);
1899 i_update_toolbar(w_current
);
1900 gtk_widget_destroy(w_current
->sewindow
);
1901 w_current
->sewindow
= NULL
;
1905 /*! \brief Create the slot entry dialog
1906 * \par Function Description
1907 * This function creates the slot edit dialog.
1909 void slot_edit_dialog (TOPLEVEL
*w_current
, char *string
)
1911 GtkWidget
*label
= NULL
;
1912 GtkWidget
*textentry
;
1915 if (!w_current
->sewindow
) {
1916 w_current
->sewindow
= gschem_dialog_new_with_buttons(_("Edit slot number"),
1917 GTK_WINDOW(w_current
->main_window
),
1919 "slot-edit", w_current
,
1921 GTK_RESPONSE_REJECT
,
1923 GTK_RESPONSE_ACCEPT
,
1926 #if GTK_CHECK_VERSION (2,6,0)
1927 /* Set the alternative button order (ok, cancel, help) for other systems */
1928 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->sewindow
),
1929 GTK_RESPONSE_ACCEPT
,
1930 GTK_RESPONSE_REJECT
,
1934 gtk_window_position(GTK_WINDOW(w_current
->sewindow
),
1937 gtk_dialog_set_default_response (GTK_DIALOG (w_current
->sewindow
),
1938 GTK_RESPONSE_ACCEPT
);
1940 gtk_signal_connect(GTK_OBJECT(w_current
->sewindow
), "response",
1941 GTK_SIGNAL_FUNC(slot_edit_dialog_response
),
1944 gtk_container_border_width(GTK_CONTAINER(w_current
->sewindow
),
1945 DIALOG_BORDER_SPACING
);
1946 vbox
= GTK_DIALOG(w_current
->sewindow
)->vbox
;
1947 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
1949 label
= gtk_label_new (_("Edit slot number:"));
1950 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
1951 gtk_box_pack_start(GTK_BOX (vbox
), label
, FALSE
, FALSE
, 0);
1953 textentry
= gtk_entry_new();
1954 gtk_box_pack_start( GTK_BOX(vbox
),
1955 textentry
, FALSE
, FALSE
, 0);
1956 gtk_entry_set_max_length(GTK_ENTRY(textentry
), 80);
1957 gtk_entry_set_activates_default (GTK_ENTRY(textentry
),TRUE
);
1959 GLADE_HOOKUP_OBJECT(w_current
->sewindow
, textentry
, "textentry");
1960 gtk_widget_show_all (w_current
->sewindow
);
1963 else { /* dialog already created */
1964 gtk_window_present (GTK_WINDOW(w_current
->sewindow
));
1967 /* always set the current text and select the number of the slot */
1968 if (string
!= NULL
) {
1969 textentry
= g_object_get_data(G_OBJECT(w_current
->sewindow
),"textentry");
1970 gtk_entry_set_text(GTK_ENTRY(textentry
), string
);
1971 gtk_entry_select_region(GTK_ENTRY(textentry
),
1972 strlen("slot="), strlen(string
));
1976 /***************** End of Slot Edit dialog box ***********************/
1978 /***************** Start of help/about dialog box ********************/
1980 /*! \brief Response function for the about dialog
1981 * \par Function Description
1982 * This function destoys the about dialg.
1984 void about_dialog_response(GtkWidget
*w
, gint response
,
1985 TOPLEVEL
*w_current
)
1988 case GTK_RESPONSE_REJECT
:
1989 case GTK_RESPONSE_DELETE_EVENT
:
1993 printf("about_dialog_response(): strange signal %d\n",response
);
1996 gtk_widget_destroy(w_current
->abwindow
);
1997 w_current
->abwindow
= NULL
;
2000 /*! \brief Create the about dialog and show it
2001 * \par Function Description
2002 * This function creates the about dialog.
2004 void about_dialog (TOPLEVEL
*w_current
)
2006 GtkWidget
*label
= NULL
;
2010 if (!w_current
->abwindow
) {
2011 w_current
->abwindow
= gschem_dialog_new_with_buttons(_("About..."),
2012 GTK_WINDOW(w_current
->main_window
),
2016 GTK_RESPONSE_REJECT
,
2019 gtk_window_position (GTK_WINDOW (w_current
->abwindow
),
2022 gtk_signal_connect (GTK_OBJECT (w_current
->abwindow
), "response",
2023 GTK_SIGNAL_FUNC(about_dialog_response
),
2026 gtk_container_border_width (GTK_CONTAINER(w_current
->abwindow
),
2027 DIALOG_BORDER_SPACING
);
2028 vbox
= GTK_DIALOG(w_current
->abwindow
)->vbox
;
2029 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
2031 label
= gtk_label_new ( _("<b>gEDA: GPL Electronic Design Automation</b>"));
2032 gtk_label_set_use_markup (GTK_LABEL(label
), TRUE
);
2033 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
2035 string
= g_strdup_printf(_("<b>gschem version %s%s.%s</b>"),
2036 PREPEND_VERSION_STRING
, DOTTED_VERSION
,
2038 label
= gtk_label_new (string
);
2039 gtk_label_set_use_markup (GTK_LABEL(label
), TRUE
);
2041 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
2043 label
= gtk_label_new ( _("Written by:\n"
2045 "ahvezda@geda.seul.org\n"
2046 "And many others (See AUTHORS file)"));
2047 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
2048 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
2050 gtk_widget_show_all(w_current
->abwindow
);
2053 else { /* dialog already created */
2054 gtk_window_present(GTK_WINDOW(w_current
->abwindow
));
2058 /***************** End of help/about dialog box *********************/
2060 /***************** Start of coord dialog box ************************/
2061 /*! \brief Response function for the coord dialog
2062 * \par Function Description
2063 * This function destroys the coord dialog box and does some cleanup.
2065 void coord_dialog_response(GtkWidget
*w
, gint response
, TOPLEVEL
*w_current
)
2067 gtk_widget_destroy(w_current
->cowindow
);
2068 w_current
->cowindow
= NULL
;
2069 w_current
->coord_world
= NULL
;
2070 w_current
->coord_screen
= NULL
;
2073 /*! \brief Update the coordinates in the coord dialog box.
2074 * \par Function Description
2075 * This function takes the screen coordinates and prints the
2076 * screen and the world coordinates in the coord dialog.
2078 void coord_display_update(TOPLEVEL
*w_current
, int x
, int y
)
2081 int world_x
, world_y
;
2083 string
= g_strdup_printf("(%d, %d)", x
, y
);
2084 gtk_label_set_text(GTK_LABEL(w_current
->coord_screen
), string
);
2087 SCREENtoWORLD(w_current
, x
, y
, &world_x
, &world_y
);
2088 /* TODO: Do we want to snap the coordinate display? */
2089 world_x
= snap_grid(w_current
, world_x
);
2090 world_y
= snap_grid(w_current
, world_y
);
2092 string
= g_strdup_printf("(%d, %d)", world_x
, world_y
);
2093 gtk_label_set_text(GTK_LABEL(w_current
->coord_world
), string
);
2097 /*! \brief Create the coord dialog
2098 * \par Function Description
2099 * This function creates the coord dialog box.
2101 void coord_dialog (TOPLEVEL
*w_current
, int x
, int y
)
2106 if (!w_current
->cowindow
) {
2107 w_current
->cowindow
= gschem_dialog_new_with_buttons(_("Coords"),
2108 GTK_WINDOW(w_current
->main_window
),
2109 0, /* Not modal GTK_DIALOG_MODAL */
2112 GTK_RESPONSE_REJECT
,
2115 gtk_window_position (GTK_WINDOW (w_current
->cowindow
),
2118 gtk_signal_connect (GTK_OBJECT (w_current
->cowindow
), "response",
2119 GTK_SIGNAL_FUNC(coord_dialog_response
),
2122 gtk_container_border_width (GTK_CONTAINER(w_current
->cowindow
),
2123 DIALOG_BORDER_SPACING
);
2124 vbox
= GTK_DIALOG(w_current
->cowindow
)->vbox
;
2125 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
2128 frame
= gtk_frame_new (_("Screen"));
2129 w_current
->coord_screen
= gtk_label_new("(########, ########)");
2130 gtk_label_set_justify( GTK_LABEL(w_current
->coord_screen
), GTK_JUSTIFY_LEFT
);
2131 gtk_misc_set_padding(GTK_MISC(w_current
->coord_screen
),
2132 DIALOG_H_SPACING
, DIALOG_V_SPACING
);
2133 gtk_container_add(GTK_CONTAINER (frame
),
2134 w_current
->coord_screen
);
2135 gtk_box_pack_start(GTK_BOX (vbox
), frame
, FALSE
, FALSE
, 0);
2137 frame
= gtk_frame_new (_("World"));
2138 w_current
->coord_world
= gtk_label_new ("(########, ########)");
2139 gtk_misc_set_padding(GTK_MISC(w_current
->coord_world
),
2140 DIALOG_H_SPACING
, DIALOG_V_SPACING
);
2141 gtk_label_set_justify(GTK_LABEL(w_current
->coord_world
),
2143 gtk_container_add(GTK_CONTAINER (frame
),
2144 w_current
->coord_world
);
2145 gtk_box_pack_start(GTK_BOX (vbox
), frame
, FALSE
, FALSE
, 0);
2147 gtk_widget_show_all(w_current
->cowindow
);
2150 else { /* window already creatad */
2151 gtk_window_present(GTK_WINDOW(w_current
->cowindow
));
2154 /* always update the coords when the dialog is requested */
2155 coord_display_update(w_current
, x
, y
);
2158 /***************** End of coord dialog box **************************/
2160 /***************** Start of color edit dialog box *******************/
2162 /*! \todo Finish function documentation!!!
2164 * \par Function Description
2167 gint
color_set(GtkWidget
*w
, gpointer data
)
2172 * here we really are passing an int sized piece of data, the index rather
2173 * than a pointer and we shouldn't have issues as long as
2174 * sizeof(void *) >= sizeof(int)
2176 index
= GPOINTER_TO_INT( data
);
2178 /* hate to use this here... but I have to... */
2179 global_window_current
->edit_color
= index
;
2183 /*! \todo Finish function documentation!!!
2185 * \par Function Description
2188 * Caller must g_free returned character string.
2191 char *index2functionstring(int index
)
2196 case(BACKGROUND_COLOR
):
2197 string
= g_strdup ("background");
2200 string
= g_strdup ("pin");
2202 case(NET_ENDPOINT_COLOR
):
2203 string
= g_strdup ("net endpoint");
2205 case(GRAPHIC_COLOR
):
2206 string
= g_strdup ("graphic");
2209 string
= g_strdup ("net");
2211 case(ATTRIBUTE_COLOR
):
2212 string
= g_strdup ("attribute");
2214 case(LOGIC_BUBBLE_COLOR
):
2215 string
= g_strdup ("logic bubble");
2218 string
= g_strdup ("grid point");
2220 case(DETACHED_ATTRIBUTE_COLOR
):
2221 string
= g_strdup ("detached attribute");
2224 string
= g_strdup ("text");
2227 string
= g_strdup ("bus");
2230 string
= g_strdup ("select");
2232 case(BOUNDINGBOX_COLOR
):
2233 string
= g_strdup ("bounding box");
2235 case(ZOOM_BOX_COLOR
):
2236 string
= g_strdup ("zoom box");
2239 string
= g_strdup ("stroke");
2242 string
= g_strdup ("lock");
2244 case(OUTPUT_BACKGROUND_COLOR
):
2245 string
= g_strdup ("output background");
2248 string
= g_strdup ("unknown");
2254 /*! \brief Create a OptionMenu with the gschem colors.
2255 * \par Function Description
2256 * This Function creates a GtkOptionMenu with the color list.
2257 * It selects the color of the first selected object.
2259 static GtkWidget
*create_color_menu (TOPLEVEL
* w_current
, int * select_index
)
2262 GtkWidget
*menuitem
;
2269 /* first lets see if we have a selected object, if so select its color */
2270 int select_col
= -1;
2272 GList
*s_current
= NULL
;
2273 OBJECT
*object
= NULL
;
2275 menu
= gtk_menu_new ();
2278 s_current
= geda_list_get_glist( w_current
->page_current
->selection_list
);
2280 if (s_current
!= NULL
) {
2282 object
= (OBJECT
*) s_current
->data
;
2283 if (object
== NULL
) {
2284 fprintf(stderr
, "no object selected - WHEE!\n");
2286 select_col
= object
->saved_color
;
2287 /* fprintf(stderr, "setting object color %d\n", select_col); */
2289 }else /*fprintf(stderr, "no object selected\n")*/;
2291 for (index
=0; index
< MAX_COLORS
;index
++) {
2293 if ((buf
=x_color_get_name(index
)) != NULL
) {
2294 temp
= index2functionstring(index
);
2295 menu_string
= g_strdup_printf("%d | %s | %s", index
,
2302 menuitem
= gtk_radio_menu_item_new_with_label (group
,
2304 g_free(menu_string
);
2307 group
= gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(
2310 gtk_menu_append (GTK_MENU (menu
), menuitem
);
2312 gtk_signal_connect (GTK_OBJECT (menuitem
),
2314 (GtkSignalFunc
) color_set
,
2315 GINT_TO_POINTER( index
));
2317 /* I have no idea if doing the above cast is valid,
2318 * since index isn't a pointer, it's just being
2319 * treated as one, it's then cast to an int in
2320 * color_set. This should be ok as long as
2321 * sizeof(void *) >= sizeof(int)
2324 if (select_col
== -1){
2325 /* set the default to the current color */
2326 if (index
== global_window_current
->edit_color
) {
2327 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem
), TRUE
);
2328 /*fprintf(stderr, "checking item %d\n", index); */
2329 *select_index
= item_index
;
2332 if (index
== select_col
){
2333 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem
), TRUE
);
2334 /* fprintf(stderr, "checking selected item %d\n", index); */
2335 *select_index
= item_index
;
2338 gtk_widget_show(menuitem
);
2345 /*! \brief Apply a color change to selected objects
2346 * \par Function Description
2347 * This function applies a color change to the currently selected objects.
2349 void color_edit_dialog_apply(GtkWidget
*w
, TOPLEVEL
*w_current
)
2351 GList
*s_current
= NULL
;
2352 OBJECT
*object
= NULL
;
2354 s_current
= geda_list_get_glist( w_current
->page_current
->selection_list
);
2356 while(s_current
!= NULL
) {
2358 object
= (OBJECT
*) s_current
->data
;
2359 if (object
== NULL
) {
2360 fprintf(stderr
, _("ERROR: NULL object in color_edit_dialog_apply!\n"));
2364 switch(object
->type
) {
2372 object
->saved_color
= w_current
->edit_color
;
2373 w_current
->page_current
->CHANGED
= 1;
2377 object
->saved_color
= w_current
->edit_color
;
2378 o_complex_set_saved_color_only(
2379 object
->text
->prim_objs
,
2380 w_current
->edit_color
);
2381 w_current
->page_current
->CHANGED
= 1;
2385 s_current
= s_current
->next
;
2387 o_undo_savestate(w_current
, UNDO_ALL
);
2390 /*! \brief response function for the color edit dialog
2391 * \par Function Description
2392 * This function takes the user response from the color edit dialog
2394 void color_edit_dialog_response(GtkWidget
*widget
, gint response
, TOPLEVEL
*w_current
)
2397 case GTK_RESPONSE_REJECT
:
2398 case GTK_RESPONSE_DELETE_EVENT
:
2399 gtk_widget_destroy(w_current
->clwindow
);
2400 w_current
->clwindow
= NULL
;
2402 case GTK_RESPONSE_ACCEPT
:
2403 color_edit_dialog_apply(widget
, w_current
);
2406 printf("ERROR: color_edit_dialog_response(): strange signal %d\n",response
);
2411 /*! \brief Create the color edit dialog
2412 * \par Function Description
2413 * This function creates the color edit dialog
2415 void color_edit_dialog (TOPLEVEL
*w_current
)
2417 GtkWidget
*optionmenu
;
2420 int select_index
= 0;
2422 if (!w_current
->clwindow
) {
2423 w_current
->clwindow
= gschem_dialog_new_with_buttons(_("Color Edit"),
2424 GTK_WINDOW(w_current
->main_window
),
2425 0, /* nonmodal dialog */
2426 "color-edit", w_current
,
2428 GTK_RESPONSE_REJECT
,
2430 GTK_RESPONSE_ACCEPT
,
2433 #if GTK_CHECK_VERSION (2,6,0)
2434 /* Set the alternative button order (ok, cancel, help) for other systems */
2435 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->clwindow
),
2436 GTK_RESPONSE_ACCEPT
,
2437 GTK_RESPONSE_REJECT
,
2441 gtk_window_position (GTK_WINDOW (w_current
->clwindow
),
2444 gtk_dialog_set_default_response (GTK_DIALOG (w_current
->clwindow
),
2445 GTK_RESPONSE_ACCEPT
);
2447 gtk_signal_connect(GTK_OBJECT(w_current
->clwindow
), "response",
2448 GTK_SIGNAL_FUNC(color_edit_dialog_response
),
2451 gtk_container_border_width(GTK_CONTAINER(w_current
->clwindow
),
2452 DIALOG_BORDER_SPACING
);
2453 vbox
= GTK_DIALOG(w_current
->clwindow
)->vbox
;
2454 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
2456 label
= gtk_label_new(_("Object color:"));
2457 gtk_misc_set_alignment(GTK_MISC(label
),0,0);
2458 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
2460 optionmenu
= gtk_option_menu_new ();
2461 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu
),
2462 create_color_menu (w_current
, &select_index
));
2463 gtk_option_menu_set_history(GTK_OPTION_MENU (optionmenu
), select_index
);
2464 gtk_box_pack_start(GTK_BOX(vbox
),
2465 optionmenu
, FALSE
, FALSE
, 0);
2466 gtk_widget_show_all(w_current
->clwindow
);
2469 else { /* dialog already created */
2470 gtk_window_present(GTK_WINDOW(w_current
->clwindow
));
2474 /***************** End of color edit dialog box *********************/
2476 /***************** Start of help/keymapping dialog box **************/
2478 /*! \brief Response function for the hotkey dialog
2479 * \par Function Description
2480 * This function destroys the hotkey dialog and does some cleanup.
2482 void x_dialog_hotkeys_response(GtkWidget
*w
, gint response
,
2483 TOPLEVEL
*w_current
)
2486 case GTK_RESPONSE_REJECT
:
2487 case GTK_RESPONSE_DELETE_EVENT
:
2491 printf("x_dialog_hotkeys_response(): strange signal %d\n", response
);
2494 gtk_widget_destroy(w_current
->hkwindow
);
2495 w_current
->hkwindow
= NULL
;
2498 /*! \brief Creates the hotkeys dialog
2499 * \par Function Description
2500 * This function creates the hotkey dialog and puts the list of hotkeys
2503 void x_dialog_hotkeys (TOPLEVEL
*w_current
)
2505 GtkWidget
*vbox
, *scrolled_win
;
2506 GtkListStore
*store
;
2507 GtkWidget
*treeview
;
2508 GtkCellRenderer
*renderer
;
2509 GtkTreeViewColumn
*column
;
2512 struct keyseq_action_t
{
2513 gchar
*keyseq
, *action
;
2516 if (!w_current
->hkwindow
) {
2517 w_current
->hkwindow
= gschem_dialog_new_with_buttons(_("Hotkeys"),
2518 GTK_WINDOW(w_current
->main_window
),
2520 "hotkeys", w_current
,
2522 GTK_RESPONSE_REJECT
,
2525 gtk_window_position (GTK_WINDOW (w_current
->hkwindow
),
2528 gtk_signal_connect (GTK_OBJECT (w_current
->hkwindow
), "response",
2529 GTK_SIGNAL_FUNC(x_dialog_hotkeys_response
),
2532 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->hkwindow
),
2533 GTK_RESPONSE_ACCEPT
);
2535 gtk_container_border_width (GTK_CONTAINER (w_current
->hkwindow
),
2536 DIALOG_BORDER_SPACING
);
2537 gtk_widget_set_usize(w_current
->hkwindow
, 300,300);
2539 vbox
= GTK_DIALOG(w_current
->hkwindow
)->vbox
;
2540 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
2542 scrolled_win
= gtk_scrolled_window_new (NULL
, NULL
);
2543 gtk_box_pack_start (GTK_BOX (vbox
), scrolled_win
, TRUE
, TRUE
, 0);
2544 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win
),
2545 GTK_POLICY_AUTOMATIC
,
2546 GTK_POLICY_AUTOMATIC
);
2549 store
= gtk_list_store_new (2,G_TYPE_STRING
, G_TYPE_STRING
);
2551 /* retrieve current keymap */
2552 keymap
= g_keys_dump_keymap ();
2553 /* add each keymap entry to the list store of the dialog */
2554 for (i
= 0; i
< keymap
->len
; i
++) {
2556 struct keyseq_action_t
*keymap_entry
;
2558 keymap_entry
= &g_array_index (keymap
, struct keyseq_action_t
, i
);
2559 gtk_list_store_append (store
, &iter
);
2560 gtk_list_store_set (store
, &iter
,
2561 0, keymap_entry
->action
,
2562 1, keymap_entry
->keyseq
,
2566 /* finally free the array for keymap */
2567 for (i
= 0; i
< keymap
->len
; i
++) {
2568 struct keyseq_action_t
*keymap_entry
;
2569 keymap_entry
= &g_array_index (keymap
, struct keyseq_action_t
, i
);
2570 g_free (keymap_entry
->keyseq
);
2571 g_free (keymap_entry
->action
);
2573 g_array_free (keymap
, TRUE
);
2576 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(store
));
2577 gtk_container_add(GTK_CONTAINER(scrolled_win
), treeview
);
2580 renderer
= gtk_cell_renderer_text_new ();
2581 column
= gtk_tree_view_column_new_with_attributes (_("Function"),
2586 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
2587 renderer
= gtk_cell_renderer_text_new ();
2588 column
= gtk_tree_view_column_new_with_attributes (_("Keystroke(s)"),
2593 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
2595 /* show all recursively */
2596 gtk_widget_show_all(w_current
->hkwindow
);
2599 else { /* dialog already created */
2600 gtk_window_present(GTK_WINDOW(w_current
->hkwindow
));
2604 /***************** End of help/keymapping dialog box ****************/
2606 /*********** Start of misc support functions for dialog boxes *******/
2607 extern GtkWidget
*stwindow
;
2609 /*! \todo Finish function documentation!!!
2611 * \par Function Description
2614 void x_dialog_raise_all(TOPLEVEL
*w_current
)
2616 if(w_current
->fowindow
) {
2617 gdk_window_raise(w_current
->fowindow
->window
);
2619 if(w_current
->fswindow
) {
2620 gdk_window_raise(w_current
->fswindow
->window
);
2622 if(w_current
->sowindow
) {
2623 gdk_window_raise(w_current
->sowindow
->window
);
2625 if(w_current
->aswindow
) {
2626 gdk_window_raise(w_current
->aswindow
->window
);
2628 if(w_current
->cswindow
) {
2629 gdk_window_raise(w_current
->cswindow
->window
);
2632 if(w_current
->iwindow
) {
2633 gdk_window_raise(w_current
->iwindow
->window
);
2636 if(w_current
->tiwindow
) {
2637 gdk_window_raise(w_current
->tiwindow
->window
);
2639 if(w_current
->tewindow
) {
2640 gdk_window_raise(w_current
->tewindow
->window
);
2642 if(w_current
->sewindow
) {
2643 gdk_window_raise(w_current
->sewindow
->window
);
2645 if(w_current
->exwindow
) {
2646 gdk_window_raise(w_current
->exwindow
->window
);
2648 if(w_current
->aawindow
) {
2649 gdk_window_raise(w_current
->aawindow
->window
);
2651 if(w_current
->mawindow
) {
2652 gdk_window_raise(w_current
->mawindow
->window
);
2654 if(w_current
->aewindow
) {
2655 gdk_window_raise(w_current
->aewindow
->window
);
2657 if(w_current
->trwindow
) {
2658 gdk_window_raise(w_current
->trwindow
->window
);
2660 if(w_current
->tswindow
) {
2661 gdk_window_raise(w_current
->tswindow
->window
);
2663 if(w_current
->abwindow
) {
2664 gdk_window_raise(w_current
->abwindow
->window
);
2666 if(w_current
->hkwindow
) {
2667 gdk_window_raise(w_current
->hkwindow
->window
);
2669 if(w_current
->cowindow
) {
2670 gdk_window_raise(w_current
->cowindow
->window
);
2672 if(w_current
->clwindow
) {
2673 gdk_window_raise(w_current
->clwindow
->window
);
2675 if(w_current
->ltwindow
) {
2676 gdk_window_raise(w_current
->ltwindow
->window
);
2678 if(w_current
->ftwindow
) {
2679 gdk_window_raise(w_current
->ftwindow
->window
);
2684 /*********** End of misc support functions for dialog boxes *******/
2686 /***************** Start of generic message dialog box *******************/
2688 /*! \todo Finish function documentation!!!
2690 * \par Function Description
2693 void generic_msg_dialog (const char *msg
)
2697 dialog
= gtk_message_dialog_new (NULL
,
2701 | GTK_DIALOG_DESTROY_WITH_PARENT
,
2706 gtk_dialog_run (GTK_DIALOG (dialog
));
2707 gtk_widget_destroy (dialog
);
2711 /***************** End of generic message dialog box *********************/
2713 /***************** Start of generic confirm dialog box *******************/
2715 /*! \todo Finish function documentation!!!
2717 * \par Function Description
2720 int generic_confirm_dialog (const char *msg
)
2725 dialog
= gtk_message_dialog_new (NULL
,
2729 | GTK_DIALOG_DESTROY_WITH_PARENT
,
2731 GTK_BUTTONS_OK_CANCEL
,
2734 r
= gtk_dialog_run (GTK_DIALOG (dialog
));
2735 gtk_widget_destroy (dialog
);
2737 if (r
== GTK_RESPONSE_OK
)
2743 /***************** End of generic confirm dialog box *********************/
2745 /***************** Start of generic file select dialog box ***************/
2746 /*! \todo Finish function documentation!!!
2748 * \par Function Description
2751 * Caller must g_free returned character string.
2753 char *generic_filesel_dialog (const char *msg
, const char *templ
, gint flags
)
2756 gchar
*result
= NULL
, *folder
, *seed
;
2758 static gchar
*path
= NULL
;
2759 static gchar
*shortcuts
= NULL
;
2761 /* Default to load if not specified. Maybe this should cause an error. */
2762 if (! (flags
& (FSB_LOAD
| FSB_SAVE
))) {
2763 flags
= flags
| FSB_LOAD
;
2766 if (flags
& FSB_LOAD
) {
2767 title
= g_strdup_printf("%s: Open", msg
);
2768 dialog
= gtk_file_chooser_dialog_new (title
,
2770 GTK_FILE_CHOOSER_ACTION_OPEN
,
2771 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
2772 GTK_STOCK_OPEN
, GTK_RESPONSE_OK
,
2774 /* Since this is a load dialog box, the file must exist! */
2775 flags
= flags
| FSB_MUST_EXIST
;
2778 title
= g_strdup_printf("%s: Save", msg
);
2779 dialog
= gtk_file_chooser_dialog_new (title
,
2781 GTK_FILE_CHOOSER_ACTION_SAVE
,
2782 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
2783 GTK_STOCK_OPEN
, GTK_RESPONSE_OK
,
2787 #if GTK_CHECK_VERSION (2,6,0)
2788 /* Set the alternative button order (ok, cancel, help) for other systems */
2789 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog
),
2791 GTK_RESPONSE_CANCEL
,
2795 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
2797 /* Pick the current default folder to look for files in */
2798 if (path
&& *path
) {
2799 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog
), path
);
2803 /* Pick the current template (*.rc) or default file name */
2804 if (templ
&& *templ
) {
2805 if (flags
& FSB_SAVE
) {
2806 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog
), templ
);
2808 gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog
), templ
);
2813 if (shortcuts
&& *shortcuts
) {
2814 printf ("shortcuts = \"%s\"\n", shortcuts
);
2815 folder
= g_strdup (shortcuts
);
2817 while ((folder
= strtok (seed
, ":")) != NULL
) {
2818 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog
),
2826 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_OK
) {
2827 result
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
2828 folder
= gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog
));
2830 if (folder && path) {
2831 dup_string (path, folder);
2836 gtk_widget_destroy (dialog
);
2844 /***************** End of generic file select dialog box *****************/
2846 /*********** Start of find text dialog box *******/
2849 OBJECT
*remember_page
;
2851 /*! \brief response function for the find text dialog
2852 * \par Function Description
2853 * This function takes the string the user likes to find and searches it
2856 void find_text_dialog_response(GtkWidget
*w
, gint response
,
2857 TOPLEVEL
*w_current
)
2859 GtkWidget
*textentry
;
2860 GtkWidget
*checkdescend
;
2862 gint done
=0, close
=0;
2865 case GTK_RESPONSE_ACCEPT
:
2866 textentry
= g_object_get_data(G_OBJECT(w_current
->tfindwindow
),"textentry");
2867 string
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(textentry
));
2868 checkdescend
= g_object_get_data(G_OBJECT(w_current
->tfindwindow
),"checkdescend");
2870 strncpy(generic_textstring
, string
, 256);
2872 while (remember_page
!= w_current
->page_current
->object_head
) {
2873 s_hierarchy_up(w_current
, w_current
->page_current
->up
);
2876 o_edit_find_text(w_current
, remember_page
, string
,
2877 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
2881 o_redraw_all_fast(w_current
);
2886 case GTK_RESPONSE_REJECT
:
2887 case GTK_RESPONSE_DELETE_EVENT
:
2891 printf("find_text_dialog_response(): strange signal %d\n", response
);
2894 gtk_widget_destroy(w_current
->tfindwindow
);
2895 w_current
->tfindwindow
= NULL
;
2899 /*! \brief Create the text find dialog
2900 * \par Function Description
2901 * This function creates the text find dialog.
2903 void find_text_dialog(TOPLEVEL
* w_current
)
2905 GtkWidget
*label
= NULL
;
2907 GtkWidget
*checkdescend
;
2908 GtkWidget
*textentry
;
2909 OBJECT
*object
= NULL
;
2912 remember_page
= w_current
->page_current
->object_head
;
2913 if ((object
= o_select_return_first_object(w_current
)) != NULL
) {
2914 if (object
->type
== OBJ_TEXT
) {
2915 strncpy(generic_textstring
, object
->text
->string
, 256);
2919 if (!w_current
->tfindwindow
) {
2920 w_current
->tfindwindow
= gschem_dialog_new_with_buttons(_("Find Text"),
2921 GTK_WINDOW(w_current
->main_window
),
2922 0, /* not modal GTK_DIALOG_MODAL */
2923 "find-text", w_current
,
2925 GTK_RESPONSE_REJECT
,
2927 GTK_RESPONSE_ACCEPT
,
2930 #if GTK_CHECK_VERSION (2,6,0)
2931 /* Set the alternative button order (ok, cancel, help) for other systems */
2932 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->tfindwindow
),
2933 GTK_RESPONSE_ACCEPT
,
2934 GTK_RESPONSE_REJECT
,
2938 gtk_window_position(GTK_WINDOW(w_current
->tfindwindow
),
2941 gtk_signal_connect(GTK_OBJECT(w_current
->tfindwindow
), "response",
2942 GTK_SIGNAL_FUNC(find_text_dialog_response
),
2945 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->tfindwindow
),
2946 GTK_RESPONSE_ACCEPT
);
2948 gtk_container_border_width(GTK_CONTAINER(w_current
->tfindwindow
),
2949 DIALOG_BORDER_SPACING
);
2950 vbox
= GTK_DIALOG(w_current
->tfindwindow
)->vbox
;
2951 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
2953 label
= gtk_label_new(_("Text to find:"));
2954 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
2955 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
2957 textentry
= gtk_entry_new_with_max_length(20);
2958 gtk_editable_select_region(GTK_EDITABLE(textentry
), 0, -1);
2959 gtk_box_pack_start(GTK_BOX(vbox
), textentry
, FALSE
, FALSE
, 0);
2960 gtk_entry_set_activates_default(GTK_ENTRY(textentry
), TRUE
);
2961 gtk_widget_grab_focus(textentry
);
2963 checkdescend
= gtk_check_button_new_with_label(_("descend into hierarchy"));
2964 gtk_box_pack_start(GTK_BOX(vbox
), checkdescend
, TRUE
, TRUE
, 0);
2966 GLADE_HOOKUP_OBJECT(w_current
->tfindwindow
, textentry
, "textentry");
2967 GLADE_HOOKUP_OBJECT(w_current
->tfindwindow
, checkdescend
, "checkdescend");
2969 gtk_widget_show_all(w_current
->tfindwindow
);
2972 else { /* dialog already created */
2973 gtk_window_present(GTK_WINDOW(w_current
->tfindwindow
));
2976 /* always select the text string in the entry */
2977 textentry
= g_object_get_data (G_OBJECT (w_current
->tfindwindow
), "textentry");
2978 gtk_entry_set_text(GTK_ENTRY(textentry
), generic_textstring
);
2979 gtk_entry_select_region(GTK_ENTRY(textentry
), 0, -1);
2982 /*********** End of find text dialog box *******/
2984 /*********** Start of hide text dialog box *******/
2986 /*! \brief Response function for the hide text dialog
2987 * \par Function Description
2988 * This is the response function of the hide text dialog. It takes the user input
2989 * and hides all text elements that starts with the searchtext.
2991 void hide_text_dialog_response(GtkWidget
*w
, gint response
,
2992 TOPLEVEL
*w_current
)
2994 GtkWidget
*textentry
;
2998 case GTK_RESPONSE_ACCEPT
:
2999 textentry
= g_object_get_data(G_OBJECT(w_current
->thidewindow
),"textentry");
3000 string
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(textentry
));
3002 strncpy(generic_textstring
, string
, 256);
3003 o_edit_hide_specific_text(w_current
,
3004 w_current
->page_current
->object_head
, string
);
3006 case GTK_RESPONSE_REJECT
:
3007 case GTK_RESPONSE_DELETE_EVENT
:
3008 gtk_widget_destroy(w_current
->thidewindow
);
3009 w_current
->thidewindow
= NULL
;
3012 printf("show_text_dialog_response(): strange signal %d\n",response
);
3016 /*! \brief Creates the hide text dialog
3017 * \par Function Description
3018 * This function creates the hide text dialog.
3020 void hide_text_dialog(TOPLEVEL
* w_current
)
3022 GtkWidget
*label
= NULL
;
3023 GtkWidget
*textentry
;
3026 if (!w_current
->thidewindow
) {
3027 w_current
->thidewindow
= gschem_dialog_new_with_buttons(_("Hide Text"),
3028 GTK_WINDOW(w_current
->main_window
),
3029 0, /* not modal GTK_DIALOG_MODAL, */
3030 "hide-text", w_current
,
3032 GTK_RESPONSE_REJECT
,
3034 GTK_RESPONSE_ACCEPT
,
3037 #if GTK_CHECK_VERSION (2,6,0)
3038 /* Set the alternative button order (ok, cancel, help) for other systems */
3039 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->thidewindow
),
3040 GTK_RESPONSE_ACCEPT
,
3041 GTK_RESPONSE_REJECT
,
3045 gtk_window_position(GTK_WINDOW(w_current
->thidewindow
),
3048 gtk_signal_connect(GTK_OBJECT(w_current
->thidewindow
), "response",
3049 GTK_SIGNAL_FUNC(hide_text_dialog_response
),
3052 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->thidewindow
),
3053 GTK_RESPONSE_ACCEPT
);
3055 gtk_container_border_width(GTK_CONTAINER(w_current
->thidewindow
),
3056 DIALOG_BORDER_SPACING
);
3057 vbox
= GTK_DIALOG(w_current
->thidewindow
)->vbox
;
3058 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
3060 label
= gtk_label_new(_("Hide text starting with:"));
3061 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
3062 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
3064 textentry
= gtk_entry_new_with_max_length(20);
3065 gtk_box_pack_start(GTK_BOX(vbox
), textentry
, FALSE
, FALSE
, 0);
3066 gtk_entry_set_activates_default(GTK_ENTRY(textentry
), TRUE
);
3067 gtk_widget_grab_focus(textentry
);
3069 GLADE_HOOKUP_OBJECT(w_current
->thidewindow
, textentry
, "textentry");
3070 gtk_widget_show_all(w_current
->thidewindow
);
3073 else { /* dialog already created, just select it */
3074 gtk_window_present(GTK_WINDOW(w_current
->thidewindow
));
3077 /* always select the text in the search entry */
3078 textentry
= g_object_get_data (G_OBJECT (w_current
->thidewindow
), "textentry");
3079 gtk_entry_set_text(GTK_ENTRY(textentry
), generic_textstring
);
3080 gtk_entry_select_region(GTK_ENTRY(textentry
), 0, -1);
3083 /*********** End of hide text dialog box *******/
3085 /*********** Start of show text dialog box *******/
3087 /*! \brief Response function for the show text dialog
3088 * \par Function Description
3089 * This function takes the users input and searches all strings starting with
3090 * the given search text and hides those text objects.
3092 void show_text_dialog_response(GtkWidget
*widget
, gint response
,
3093 TOPLEVEL
*w_current
)
3095 GtkWidget
*textentry
;
3099 case GTK_RESPONSE_ACCEPT
:
3100 textentry
= g_object_get_data(G_OBJECT(w_current
->tshowwindow
),"textentry");
3101 string
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(textentry
));
3103 strncpy(generic_textstring
, string
, 256);
3104 o_edit_show_specific_text(w_current
,
3105 w_current
->page_current
->object_head
, string
);
3107 case GTK_RESPONSE_REJECT
:
3108 case GTK_RESPONSE_DELETE_EVENT
:
3109 gtk_widget_destroy(w_current
->tshowwindow
);
3110 w_current
->tshowwindow
= NULL
;
3113 printf("show_text_dialog_response(): strange signal %d\n",response
);
3117 /*! \brief Create the show text dialog.
3118 * \par Function Description
3119 * This function creates the show text dialog.
3121 void show_text_dialog(TOPLEVEL
* w_current
)
3123 GtkWidget
*label
= NULL
;
3124 GtkWidget
*textentry
;
3127 if (!w_current
->tshowwindow
) {
3128 w_current
->tshowwindow
= gschem_dialog_new_with_buttons(_("Show Text"),
3129 GTK_WINDOW(w_current
->main_window
),
3130 0, /* not modal GTK_DIALOG_MODAL, */
3131 "show-text", w_current
,
3133 GTK_RESPONSE_REJECT
,
3135 GTK_RESPONSE_ACCEPT
,
3138 #if GTK_CHECK_VERSION (2,6,0)
3139 /* Set the alternative button order (ok, cancel, help) for other systems */
3140 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current
->tshowwindow
),
3141 GTK_RESPONSE_ACCEPT
,
3142 GTK_RESPONSE_REJECT
,
3146 gtk_window_position(GTK_WINDOW(w_current
->tshowwindow
),
3149 gtk_signal_connect(GTK_OBJECT(w_current
->tshowwindow
), "response",
3150 GTK_SIGNAL_FUNC(show_text_dialog_response
),
3153 gtk_dialog_set_default_response(GTK_DIALOG(w_current
->tshowwindow
),
3154 GTK_RESPONSE_ACCEPT
);
3156 gtk_container_border_width(GTK_CONTAINER(w_current
->tshowwindow
),
3157 DIALOG_BORDER_SPACING
);
3158 vbox
= GTK_DIALOG(w_current
->tshowwindow
)->vbox
;
3159 gtk_box_set_spacing(GTK_BOX(vbox
), DIALOG_V_SPACING
);
3161 label
= gtk_label_new(_("Show text starting with:"));
3162 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
3163 gtk_box_pack_start(GTK_BOX(vbox
), label
, TRUE
, TRUE
, 0);
3165 textentry
= gtk_entry_new_with_max_length(20);
3166 gtk_box_pack_start(GTK_BOX(vbox
), textentry
, FALSE
, FALSE
, 0);
3167 gtk_entry_set_activates_default(GTK_ENTRY(textentry
), TRUE
);
3168 gtk_widget_grab_focus(textentry
);
3170 GLADE_HOOKUP_OBJECT(w_current
->tshowwindow
, textentry
, "textentry");
3171 gtk_widget_show_all(w_current
->tshowwindow
);
3174 else { /* dialog already created. Show it */
3175 gtk_window_present(GTK_WINDOW(w_current
->tshowwindow
));
3178 /* always select the text in the entry */
3179 textentry
= g_object_get_data (G_OBJECT (w_current
->tshowwindow
), "textentry");
3180 gtk_entry_set_text(GTK_ENTRY(textentry
), generic_textstring
);
3181 gtk_entry_select_region(GTK_ENTRY(textentry
), 0, -1);
3184 /*********** End of show text dialog box *******/
3186 /*********** Start of some Gtk utils *******/
3188 /*! \brief Selects all text in a TextView widget
3189 * \par Function Description
3190 * The function selects all the text in a TextView widget.
3192 void select_all_text_in_textview(GtkTextView
*textview
)
3194 GtkTextBuffer
*textbuffer
;
3195 GtkTextIter start
, end
;
3197 textbuffer
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview
));
3198 gtk_text_buffer_get_bounds (textbuffer
, &start
, &end
);
3199 gtk_text_buffer_select_range(textbuffer
, &start
, &end
);
3202 /*! \todo Finish function documentation!!!
3204 * \par Function Description
3207 int text_view_calculate_real_tab_width(GtkTextView
*textview
, int tab_size
)
3209 PangoLayout
*layout
;
3217 tab_string
= g_malloc (tab_size
+ 1);
3219 while (counter
< tab_size
) {
3220 tab_string
[counter
] = ' ';
3224 tab_string
[tab_size
] = 0;
3226 layout
= gtk_widget_create_pango_layout (
3227 GTK_WIDGET (textview
),
3229 g_free (tab_string
);
3231 if (layout
!= NULL
) {
3232 pango_layout_get_pixel_size (layout
, &tab_width
, NULL
);
3233 g_object_unref (G_OBJECT (layout
));
3241 /*********** End of some Gtk utils *******/
3243 /*********** Start of major symbol changed dialog box *******/
3245 /*! \todo Finish function documentation!!!
3247 * \par Function Description
3250 void major_changed_dialog(TOPLEVEL
* w_current
)
3253 char* refdes_string
= NULL
;
3256 if (w_current
->major_changed_refdes
) {
3258 GList
* current
= w_current
->major_changed_refdes
;
3261 char *value
= (char*) current
->data
;
3265 refdes_string
= g_strdup (value
);
3267 tmp
= g_strconcat (refdes_string
, "\n", value
, NULL
);
3268 g_free(refdes_string
);
3269 refdes_string
= tmp
;
3272 current
= current
->next
;
3275 tmp
= g_strconcat (refdes_string
,
3276 "\n\nBe sure to verify each of these symbols!",
3278 g_free(refdes_string
);
3279 refdes_string
= tmp
;
3281 dialog
= gtk_message_dialog_new ((GtkWindow
*) w_current
->main_window
,
3282 GTK_DIALOG_DESTROY_WITH_PARENT
,
3285 "Major symbol changes detected in refdes:\n\n%s\n",
3288 gtk_widget_show(dialog
);
3290 g_signal_connect_swapped (dialog
, "response",
3291 G_CALLBACK (gtk_widget_destroy
),
3294 if (refdes_string
) g_free(refdes_string
);
3298 /*********** End of major symbol changed dialog box *******/
3300 /***************** Start of Close Confirmation dialog box ************/
3302 #define TYPE_CLOSE_CONFIRMATION_DIALOG (close_confirmation_dialog_get_type ())
3303 #define CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialog))
3304 #define CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
3305 #define IS_CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG))
3306 #define IS_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG))
3307 #define CLOSE_CONFIRMATION_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
3310 typedef struct _CloseConfirmationDialog CloseConfirmationDialog
;
3311 typedef struct _CloseConfirmationDialogClass CloseConfirmationDialogClass
;
3313 struct _CloseConfirmationDialog
3317 GtkListStore
*store_unsaved_pages
;
3321 struct _CloseConfirmationDialogClass
3323 GtkDialogClass parent_class
;
3329 PROP_UNSAVED_PAGE
=1,
3341 static gpointer close_confirmation_dialog_parent_class
= NULL
;
3344 static void close_confirmation_dialog_class_init (CloseConfirmationDialogClass
*klass
);
3345 static void close_confirmation_dialog_init (CloseConfirmationDialog
*self
);
3346 static void close_confirmation_dialog_set_property (GObject
*object
,
3348 const GValue
*value
,
3350 static void close_confirmation_dialog_get_property (GObject
*object
,
3354 static GObject
* close_confirmation_dialog_constructor (GType type
,
3355 guint n_construct_properties
,
3356 GObjectConstructParam
*construct_params
);
3358 GList
*close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog
*dialog
);
3363 close_confirmation_dialog_get_type ()
3365 static GType close_confirmation_dialog_type
= 0;
3367 if (!close_confirmation_dialog_type
) {
3368 static const GTypeInfo close_confirmation_dialog_info
= {
3369 sizeof(CloseConfirmationDialogClass
),
3370 NULL
, /* base_init */
3371 NULL
, /* base_finalize */
3372 (GClassInitFunc
) close_confirmation_dialog_class_init
,
3373 NULL
, /* class_finalize */
3374 NULL
, /* class_data */
3375 sizeof(CloseConfirmationDialog
),
3376 0, /* n_preallocs */
3377 (GInstanceInitFunc
) close_confirmation_dialog_init
,
3380 close_confirmation_dialog_type
=
3381 g_type_register_static (GTK_TYPE_DIALOG
,
3382 "CloseConfirmationDialog",
3383 &close_confirmation_dialog_info
, 0);
3386 return close_confirmation_dialog_type
;
3390 close_confirmation_dialog_class_init (CloseConfirmationDialogClass
*klass
)
3392 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
3394 close_confirmation_dialog_parent_class
= g_type_class_peek_parent (klass
);
3396 gobject_class
->constructor
= close_confirmation_dialog_constructor
;
3397 gobject_class
->set_property
= close_confirmation_dialog_set_property
;
3398 gobject_class
->get_property
= close_confirmation_dialog_get_property
;
3400 g_object_class_install_property (
3401 gobject_class
, PROP_UNSAVED_PAGE
,
3402 g_param_spec_pointer ("unsaved-page",
3405 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_WRITABLE
));
3406 g_object_class_install_property (
3407 gobject_class
, PROP_UNSAVED_PAGES
,
3408 g_param_spec_pointer ("unsaved-pages",
3411 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_WRITABLE
));
3412 g_object_class_install_property (
3413 gobject_class
, PROP_SELECTED_PAGES
,
3414 g_param_spec_pointer ("selected-pages",
3422 close_confirmation_dialog_init (CloseConfirmationDialog
*self
)
3424 /* create model for treeview and populate */
3425 self
->store_unsaved_pages
= gtk_list_store_new (NUM_COLUMNS
,
3426 G_TYPE_BOOLEAN
, /* save? */
3427 G_TYPE_POINTER
); /* page */
3431 /*! \brief Returns the number of pages in the model.
3432 * \par Function Description
3433 * This function determines the number of pages with unsaved changes
3436 * \param in model The tree model.
3437 * \returns The number of pages with unsaved changes.
3440 count_pages (GtkTreeModel
*model
)
3445 gtk_tree_model_get_iter_first (model
, &iter
);
3447 gtk_tree_model_iter_next (model
, &iter
);
3453 /*! \brief Returns the name to use for the given page in the model.
3454 * \par Function Description
3455 * This function determines the text to be used to identify a
3456 * specific page from the model of pages with unsaved changes.
3458 * If <B>piter</B> is NULL, the name for the first page of the model
3459 * is returned. Otherwise, it returns the name for the page defined
3460 * by the pointed iterator.
3462 * The returned value must be freed by caller.
3464 * \param in model The tree model.
3465 * \param in piter A pointer on a GtkTreeIter of model or NULL.
3466 * \returns The name for the page.
3469 get_page_name (GtkTreeModel
*model
, GtkTreeIter
*piter
)
3474 g_return_val_if_fail (GTK_IS_TREE_MODEL (model
), NULL
);
3476 if (piter
== NULL
) {
3477 gtk_tree_model_get_iter_first (model
, &iter
);
3482 gtk_tree_model_get (model
, &iter
,
3485 g_assert (page
!= NULL
&& page
->page_filename
!= NULL
);
3486 return g_path_get_basename (page
->page_filename
);
3489 /*! \brief Sets the contents of the name cell in the treeview of dialog.
3490 * \par Function Description
3491 * This functions sets the cell of the treeview with the short name
3492 * of the page obtained with <B>get_page_name()</B>.
3494 * \param in tree_column A GtkTreeColumn.
3495 * \param in cell The GtkCellRenderer that is being rendered by
3497 * \param in tree_model The GtkTreeModel being rendered.
3498 * \param in iter A GtkTreeIter of the current row rendered.
3502 close_confirmation_dialog_set_page_name (GtkTreeViewColumn
*tree_column
,
3503 GtkCellRenderer
*cell
,
3504 GtkTreeModel
*tree_model
,
3510 page_name
= get_page_name (tree_model
, iter
);
3518 /*! \brief Callback function for the toggled signal of check box in treeview.
3519 * \par Function Description
3520 * This functions changes the value of the save column in the model
3521 * for the affected row when user toggles the check box in the
3524 * \param in cell_renderer The GtkCellRendererToggle.
3525 * \param in path The GtkTreePath to the concerned row in model.
3526 * \param in user The dialog as user data.
3529 close_confirmation_dialog_callback_renderer_toggled (GtkCellRendererToggle
*cell_renderer
,
3533 CloseConfirmationDialog
*dialog
= CLOSE_CONFIRMATION_DIALOG (user_data
);
3534 GtkTreeModel
*model
;
3538 model
= GTK_TREE_MODEL (dialog
->store_unsaved_pages
);
3540 gtk_tree_model_get_iter_from_string (model
, &iter
, path
);
3541 gtk_tree_model_get (model
, &iter
,
3544 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
3545 COLUMN_SAVE
, (save
!= TRUE
),
3550 /*! \brief Adds a treeview to confirmation dialog for selecting of pages.
3551 * \par Function Description
3552 * This function adds a treeview and caption to display the content
3553 * of the dialog model of pages with unsaved changes.
3555 * The treeview displays the page names with check boxes.
3557 * \param in dialog The dialog.
3558 * \returns A pointer on the GtkVBox to add to dialog.
3561 close_confirmation_dialog_build_page_list (CloseConfirmationDialog
*dialog
)
3563 GtkWidget
*vbox
, *scrolled_window
, *treeview
, *label
;
3564 GtkCellRenderer
*renderer
;
3565 GtkTreeViewColumn
*column
;
3568 /* place the treeview and its caption into their own box */
3569 vbox
= GTK_WIDGET (g_object_new (GTK_TYPE_VBOX
,
3571 "homogeneous", FALSE
,
3575 /* the list of pages with changes */
3576 /* - scrolled window as container for the treeview first */
3577 scrolled_window
= GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW
,
3578 /* GtkScrolledWindow */
3579 "hscrollbar-policy", GTK_POLICY_AUTOMATIC
,
3580 "vscrollbar-policy", GTK_POLICY_AUTOMATIC
,
3581 "shadow-type", GTK_SHADOW_IN
,
3583 /* - then the treeview */
3584 /* create model for treeview and populate */
3585 treeview
= GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW
,
3587 "enable-search", FALSE
,
3588 "headers-visible", FALSE
,
3589 "model", dialog
->store_unsaved_pages
,
3591 renderer
= gtk_cell_renderer_toggle_new ();
3592 g_signal_connect (renderer
, "toggled",
3594 close_confirmation_dialog_callback_renderer_toggled
),
3596 column
= gtk_tree_view_column_new_with_attributes ("Save?",
3598 "active", COLUMN_SAVE
,
3600 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview
), column
);
3602 renderer
= gtk_cell_renderer_text_new ();
3603 column
= GTK_TREE_VIEW_COLUMN (
3604 g_object_new (GTK_TYPE_TREE_VIEW_COLUMN
,
3605 /* GtkTreeViewColumn */
3608 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
3609 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
3610 close_confirmation_dialog_set_page_name
,
3612 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview
), column
);
3614 gtk_container_add (GTK_CONTAINER (scrolled_window
), treeview
);
3616 gtk_box_pack_end (GTK_BOX (vbox
), scrolled_window
,
3619 /* the caption label above the list of pages */
3620 label
= GTK_WIDGET (g_object_new (GTK_TYPE_LABEL
,
3626 "mnemonic-widget", treeview
,
3628 text
= _("S_elect the schematics you want to save:");
3629 gtk_label_set_text_with_mnemonic (GTK_LABEL (label
), text
);
3630 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), treeview
);
3631 gtk_box_pack_start (GTK_BOX (vbox
), label
,
3638 close_confirmation_dialog_constructor (GType type
,
3639 guint n_construct_properties
,
3640 GObjectConstructParam
*construct_params
)
3643 CloseConfirmationDialog
*dialog
;
3644 GtkWidget
*hbox
, *image
, *vbox
, *label
;
3646 gboolean ret
, single_page
;
3649 /* chain up to constructor of parent class */
3651 G_OBJECT_CLASS (close_confirmation_dialog_parent_class
)->constructor (
3653 n_construct_properties
,
3655 dialog
= CLOSE_CONFIRMATION_DIALOG (object
);
3657 g_object_set (dialog
,
3659 "has-separator", FALSE
,
3662 "skip-taskbar-hint", TRUE
,
3666 g_object_set (GTK_DIALOG (dialog
)->vbox
,
3670 g_object_set (GTK_DIALOG (dialog
)->action_area
,
3677 /* check if there is one or more than one page with changes */
3678 ret
= gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
3679 dialog
->store_unsaved_pages
),
3682 single_page
= !gtk_tree_model_iter_next (GTK_TREE_MODEL (
3683 dialog
->store_unsaved_pages
),
3686 /* here starts the layout of the dialog */
3687 hbox
= GTK_WIDGET (g_object_new (GTK_TYPE_HBOX
,
3691 "homogeneous", FALSE
,
3696 image
= g_object_new (GTK_TYPE_IMAGE
,
3701 "stock", GTK_STOCK_DIALOG_WARNING
,
3702 "icon-size", GTK_ICON_SIZE_DIALOG
,
3704 gtk_box_pack_start (GTK_BOX (hbox
), image
,
3707 /* vertical box on the right hand side of the dialog */
3708 vbox
= GTK_WIDGET (g_object_new (GTK_TYPE_VBOX
,
3710 "homogeneous", FALSE
,
3719 page_name
= get_page_name (GTK_TREE_MODEL (dialog
->store_unsaved_pages
),
3721 tmp
= g_strdup_printf (
3722 _("Save the changes to schematic \"%s\" before closing?"),
3727 tmp
= g_strdup_printf (
3728 _("There are %d schematics with unsaved changes. "
3729 "Save changes before closing?"),
3730 count_pages (GTK_TREE_MODEL (dialog
->store_unsaved_pages
)));
3732 str
= g_strconcat ("<big><b>", tmp
, "</b></big>", NULL
);
3734 label
= GTK_WIDGET (g_object_new (GTK_TYPE_LABEL
,
3745 gtk_box_pack_start (GTK_BOX (vbox
), label
,
3749 /* more than one page with changes, display each page and offer */
3750 /* the opportunity to save them before exiting */
3751 gtk_box_pack_start (GTK_BOX (vbox
),
3752 close_confirmation_dialog_build_page_list (dialog
),
3756 /* secondary label */
3757 str
= _("If you don't save, all your changes will be permanently lost.");
3758 label
= GTK_WIDGET (g_object_new (GTK_TYPE_LABEL
,
3767 gtk_box_pack_start (GTK_BOX (vbox
), label
,
3771 gtk_box_pack_start (GTK_BOX (hbox
), vbox
,
3775 /* add buttons to dialog action area */
3776 gtk_dialog_add_buttons (GTK_DIALOG (dialog
),
3777 _("_Close without saving"), GTK_RESPONSE_NO
,
3778 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
3779 GTK_STOCK_SAVE
, GTK_RESPONSE_YES
,
3782 #if GTK_CHECK_VERSION (2,6,0)
3783 /* Set the alternative button order (ok, cancel, help) for other systems */
3784 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog
),
3787 GTK_RESPONSE_CANCEL
,
3791 /* all done, let's show the contents of the dialog */
3792 gtk_widget_show_all (hbox
);
3794 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog
)->vbox
), hbox
,
3801 close_confirmation_dialog_set_property (GObject
*object
,
3803 const GValue
*value
,
3806 CloseConfirmationDialog
*dialog
= CLOSE_CONFIRMATION_DIALOG (object
);
3811 switch(property_id
) {
3812 case PROP_UNSAVED_PAGE
:
3813 data
= g_value_get_pointer (value
);
3815 /* add single page to model */
3816 gtk_list_store_append (dialog
->store_unsaved_pages
,
3818 gtk_list_store_set (dialog
->store_unsaved_pages
,
3826 case PROP_UNSAVED_PAGES
:
3827 data
= g_value_get_pointer (value
);
3828 /* add set of pages to model */
3829 for (p_current
= (GList
*)data
;
3831 p_current
= g_list_next (p_current
)) {
3832 gtk_list_store_append (dialog
->store_unsaved_pages
,
3834 gtk_list_store_set (dialog
->store_unsaved_pages
,
3837 COLUMN_PAGE
, p_current
->data
,
3843 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
3849 close_confirmation_dialog_get_property (GObject
*object
,
3854 CloseConfirmationDialog
*dialog
= CLOSE_CONFIRMATION_DIALOG (object
);
3856 switch(property_id
) {
3857 case PROP_SELECTED_PAGES
:
3858 g_value_set_pointer (
3860 close_confirmation_dialog_get_selected_pages (dialog
));
3864 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
3869 /*! \brief Helps building a list of selected page to save.
3870 * \par Function Description
3871 * This is the <B>GtkTreeModelForeachFunc</B> for function
3872 * <B>close_confirmation_dialog_get_selected_pages()</B>.
3874 * It builds from the tree model a list of PAGEs for which a save
3875 * action has been requested. Each selected page is appended to the
3876 * GList pointed by <B>data</B>
3878 * \param in model The tree model.
3881 * \param in data A pointer on a GList* to fill.
3882 * \returns FALSE to continue walking the tree.
3885 get_selected_pages (GtkTreeModel
*model
,
3893 gtk_tree_model_get (model
, iter
,
3898 g_assert (page
!= NULL
);
3899 *(GList
**)data
= g_list_append (*(GList
**)data
, page
);
3905 /*! \brief Returns a list of the selected pages with changes to save.
3906 * \par Function Description
3907 * This function returns the pages that the user has selected in the
3908 * confirmation dialog.
3910 * The returned list must be freed.
3912 * \param in dialog The dialog.
3913 * \returns A GList of selected PAGE* in dialog.
3916 close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog
*dialog
)
3918 GList
*selected
= NULL
;
3920 gtk_tree_model_foreach (GTK_TREE_MODEL (dialog
->store_unsaved_pages
),
3921 (GtkTreeModelForeachFunc
)get_selected_pages
,
3928 /*! \brief Asks for confirmation before closing a changed page.
3929 * \par Function Description
3930 * This function asks the user to confirm its closing order for
3931 * page <B>page</B> while it still has unsaved changes.
3933 * It displays a message dialog inviting the user to cancel the
3934 * closing, or to discard the changes or to save the changes to a
3937 * \param in toplevel The toplevel environment.
3938 * \param in page The page to close.
3941 x_dialog_close_changed_page (TOPLEVEL
*toplevel
, PAGE
*page
)
3945 g_return_if_fail (page
!= NULL
&& page
->CHANGED
);
3947 dialog
= GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG
,
3948 "unsaved-page", page
,
3950 /* set default response signal. This is usually triggered by the
3952 gtk_dialog_set_default_response(GTK_DIALOG(dialog
),
3955 switch (gtk_dialog_run (GTK_DIALOG (dialog
))) {
3956 case GTK_RESPONSE_NO
:
3957 /* action selected: close without saving */
3958 /* close the page, discard changes */
3959 x_window_close_page (toplevel
, page
);
3963 case GTK_RESPONSE_YES
:
3964 /* action selected: save */
3965 /* prompts user for the filename and ultimate confirmation */
3966 s_page_goto (toplevel
, page
);
3967 x_fileselect_save (toplevel
);
3968 /* has the page been really saved? */
3969 if (!page
->CHANGED
) {
3970 x_window_close_page (toplevel
, page
);
3972 /* no, user has cancelled the save and page has changes */
3973 /* do not close page */
3976 case GTK_RESPONSE_CANCEL
:
3977 /* action selected: cancel */
3980 /* Hit when the user breaks out of the dialog with the escape key
3981 * or otherwise destroys the dialog window without a proper response */
3985 gtk_widget_destroy (dialog
);
3989 /*! \brief Asks for confirmation before closing a window.
3990 * \par Function Description
3991 * This function asks the user to confirm its closing order for
3994 * The user is given the possibility to save the pages that currently
3995 * have unsaved changes, if any.
3997 * It returns TRUE if the user really accepts the close of the
3998 * window. Otherwise the user has somehow cancelled and the window
3999 * must not be closed.
4001 * \param in toplevel The toplevel environment.
4002 * \returns TRUE if the window can be closed, FALSE otherwise.
4005 x_dialog_close_window (TOPLEVEL
*toplevel
)
4009 GList
*unsaved_pages
, *p_unsaved
;
4010 gboolean ret
= FALSE
;
4012 /* build a list of unsaved pages */
4013 g_assert (toplevel
->page_head
!= NULL
&&
4014 toplevel
->page_head
->next
!= NULL
);
4015 for (p_current
= toplevel
->page_head
->next
, unsaved_pages
= NULL
;
4017 p_current
= p_current
->next
) {
4018 if (p_current
->CHANGED
) {
4019 unsaved_pages
= g_list_append (unsaved_pages
, (gpointer
)p_current
);
4023 if (unsaved_pages
== NULL
) {
4024 /* no page with unsaved changes, close window */
4028 dialog
= GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG
,
4029 "unsaved-pages", unsaved_pages
,
4032 g_list_free (unsaved_pages
);
4033 switch (gtk_dialog_run (GTK_DIALOG (dialog
))) {
4034 case GTK_RESPONSE_NO
:
4035 /* action selected: close without saving */
4036 /* discard changes, ok to close window */
4040 case GTK_RESPONSE_YES
:
4041 /* action selected: save */
4042 /* prompts user for the filename and ultimate confirmation for */
4043 /* each selected page */
4044 g_object_get (dialog
,
4045 "selected-pages", &unsaved_pages
,
4047 for (p_unsaved
= unsaved_pages
, ret
= TRUE
;
4049 p_unsaved
= g_list_next (p_unsaved
)) {
4050 p_current
= (PAGE
*)p_unsaved
->data
;
4052 s_page_goto (toplevel
, p_current
);
4053 x_fileselect_save (toplevel
);
4054 /* if user cancelled previous, do not close window */
4055 ret
&= !p_current
->CHANGED
;
4057 g_list_free (unsaved_pages
);
4060 case GTK_RESPONSE_CANCEL
:
4061 /* action selected: cancel */
4064 /* Hit when the user breaks out of the dialog with the escape key
4065 * or otherwise destroys the dialog window without a proper response */
4069 gtk_widget_destroy (dialog
);
4074 /***************** End of Close Confirmation dialog box **************/
4077 /***************** Start of misc helper dialog boxes **************/
4078 /*! \brief Validate the input attribute
4079 * \par Function Description
4080 * This function validates the attribute and if it isn't valid
4081 * pops up an error message box.
4083 * \param parent The parent window which spawned this dialog box.
4084 * \param attribute The attribute to be validated.
4085 * \returns TRUE if the attribute is valid, FALSE otherwise.
4087 int x_dialog_validate_attribute(GtkWindow
* parent
, char *attribute
)
4089 GtkWidget
* message_box
;
4090 char *name_ptr
, *value_ptr
;
4092 /* validate the new attribute */
4093 if (!o_attrib_get_name_value(attribute
, &name_ptr
, &value_ptr
)) {
4094 message_box
= gtk_message_dialog_new_with_markup (parent
,
4095 GTK_DIALOG_DESTROY_WITH_PARENT
,
4098 _("<span weight=\"bold\" size=\"larger\">The input attribute \"%s\" is invalid\nPlease correct in order to continue</span>\n\nThe name and value must be non-empty.\nThe name cannot end with a space.\nThe value cannot start with a space."),
4100 gtk_window_set_title(GTK_WINDOW(message_box
), _("Invalid Attribute"));
4101 gtk_dialog_run (GTK_DIALOG (message_box
));
4102 gtk_widget_destroy (message_box
);
4109 /***************** End of misc helper dialog boxes **************/