gschem

x_dialog.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00021 #include <config.h>
00022 #include <version.h>
00023 #include <missing.h>
00024 
00025 #include <stdio.h>
00026 #ifdef HAVE_STDLIB_H
00027 #include <stdlib.h>
00028 #endif
00029 #ifdef HAVE_STRING_H
00030 #include <string.h>
00031 #endif
00032 
00033 #include "gschem.h"
00034 
00035 #ifdef HAVE_LIBDMALLOC
00036 #include <dmalloc.h>
00037 #endif
00038 
00039 #define GLADE_HOOKUP_OBJECT(component,widget,name) \
00040   g_object_set_data_full (G_OBJECT (component), name, \
00041     gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
00042 
00043 static GtkWidget* create_menu_linetype (GSCHEM_TOPLEVEL *w_current);
00044 static gint line_type_dialog_linetype_change (GtkWidget *w, gpointer data);
00045 static void line_type_dialog_ok (GtkWidget *w, gpointer data);
00046 
00047 static GtkWidget* create_menu_filltype (GSCHEM_TOPLEVEL *w_current);
00048 static gint fill_type_dialog_filltype_change(GtkWidget *w, gpointer data);
00049 static void fill_type_dialog_ok(GtkWidget *w, gpointer data);
00050 
00051 
00052 struct line_type_data {
00053   GtkWidget *dialog;
00054   GtkWidget *width_entry;
00055   GtkWidget *line_type;
00056   GtkWidget *length_entry;
00057   GtkWidget *space_entry;
00058 
00059   GSCHEM_TOPLEVEL *w_current;
00060 };
00061 
00062 struct fill_type_data {
00063   GtkWidget *dialog;
00064   GtkWidget *fill_type;
00065   GtkWidget *width_entry;
00066   GtkWidget *angle1_entry;
00067   GtkWidget *pitch1_entry;
00068   GtkWidget *angle2_entry;
00069   GtkWidget *pitch2_entry;
00070 
00071   GSCHEM_TOPLEVEL *w_current;
00072 };
00073 
00079 void destroy_window(GtkWidget *widget, GtkWidget **window)
00080 {
00081   *window = NULL;
00082 }
00083 
00084 /* TODO: This string is used by the dialogs: show_text, find_text and hide_text
00085  * I think it should be removed. (Werner Hoch)
00086  */
00087 char generic_textstring[256] = "refdes=R";
00088 
00089 /***************** Start of Text Input dialog box *********************/
00090 
00095 void text_input_dialog_apply(GtkWidget *w, GSCHEM_TOPLEVEL *w_current)
00096 {
00097   gchar *string = NULL;
00098   gchar *tmp = NULL;
00099   GtkWidget *tientry;
00100   GtkTextBuffer *textbuffer;
00101   GtkTextIter start, end;
00102 
00103   tientry = gtk_object_get_data(GTK_OBJECT(w_current->tiwindow),"tientry");
00104 
00105   textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tientry));
00106   gtk_text_buffer_get_bounds (textbuffer, &start, &end);
00107   string =  gtk_text_iter_get_text (&start, &end);
00108 
00109   if (string[0] == '\0' )
00110     return;
00111 
00112   switch(w_current->text_caps) {
00113     case(LOWER):
00114       tmp = g_utf8_strdown (string, -1);
00115       break;
00116 
00117     case(UPPER):
00118       tmp = g_utf8_strup (string, -1);
00119       break;
00120 
00121     case(BOTH):
00122     default:
00123       /* do nothing */
00124       break;
00125   }
00126 
00127   /* select the text, so you can continue immediatly writing the next text */
00128   select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
00129   gtk_widget_grab_focus(tientry);
00130 
00131   w_current->toplevel->page_current->CHANGED=1;
00132 
00133   o_text_prepare_place (w_current, tmp == NULL ? string : tmp);
00134   g_free (string);
00135   g_free (tmp);
00136 }
00137 
00142 void text_input_dialog_response(GtkWidget * widget, gint response, GSCHEM_TOPLEVEL *w_current)
00143 {
00144   switch(response) {
00145   case GTK_RESPONSE_ACCEPT:
00146     text_input_dialog_apply(widget, w_current);
00147     break;
00148   case GTK_RESPONSE_REJECT:
00149   case GTK_RESPONSE_DELETE_EVENT:
00150     i_set_state(w_current, SELECT);
00151     i_update_toolbar(w_current);
00152     gtk_widget_destroy(w_current->tiwindow);
00153     w_current->tiwindow=NULL;
00154     break;
00155   default:
00156     printf("text_edit_dialog_response(): strange signal %d\n", response);
00157   }
00158 }
00159 
00160 
00165 void text_input_dialog (GSCHEM_TOPLEVEL *w_current)
00166 {
00167   GtkWidget *label = NULL;
00168   GtkWidget *tientry = NULL;
00169   GtkWidget *vbox;
00170   GtkWidget *viewport1 = NULL;
00171   GtkWidget *scrolled_window = NULL;
00172   PangoTabArray *tab_array;
00173   int real_tab_width;
00174 
00175   if (!w_current->tiwindow) { /* dialog not created yet */
00176     w_current->tiwindow = gschem_dialog_new_with_buttons(_("Text Entry..."),
00177                                                          GTK_WINDOW(w_current->main_window),
00178                                                          0, /* NON_MODAL */
00179                                                          "text-entry", w_current,
00180                                                          GTK_STOCK_CLOSE,
00181                                                          GTK_RESPONSE_REJECT,
00182                                                          GTK_STOCK_APPLY,
00183                                                          GTK_RESPONSE_ACCEPT,
00184                                                          NULL);
00185 
00186   /* Set the alternative button order (ok, cancel, help) for other systems */
00187     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tiwindow),
00188                                             GTK_RESPONSE_ACCEPT,
00189                                             GTK_RESPONSE_REJECT,
00190                                             -1);
00191 
00192     gtk_window_position(GTK_WINDOW (w_current->tiwindow),
00193                         GTK_WIN_POS_NONE);
00194 
00195     g_signal_connect (G_OBJECT (w_current->tiwindow), "response",
00196                       G_CALLBACK (text_input_dialog_response),
00197                       w_current);
00198 
00199     gtk_dialog_set_default_response(GTK_DIALOG(w_current->tiwindow),
00200                                     GTK_RESPONSE_ACCEPT);
00201 
00202     gtk_container_border_width(GTK_CONTAINER (w_current->tiwindow),
00203                                DIALOG_BORDER_SPACING);
00204     vbox = GTK_DIALOG(w_current->tiwindow)->vbox;
00205     gtk_box_set_spacing(GTK_BOX(vbox),DIALOG_V_SPACING);
00206 
00207     label = gtk_label_new (_("Enter text, click apply,\n"
00208                              "move cursor into window, click to place text.\n"
00209                              "Middle button to rotate while placing."));
00210     gtk_misc_set_alignment(GTK_MISC(label),0,0);
00211     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
00212 
00213     viewport1 = gtk_viewport_new (NULL, NULL);
00214     gtk_widget_show (viewport1);
00215 
00216     scrolled_window = gtk_scrolled_window_new(NULL, NULL);
00217     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
00218                                    GTK_POLICY_AUTOMATIC,
00219                                    GTK_POLICY_AUTOMATIC);
00220     gtk_container_add (GTK_CONTAINER (viewport1), scrolled_window);
00221     gtk_box_pack_start( GTK_BOX(vbox), viewport1, TRUE, TRUE, 0);
00222 
00223     tientry = gtk_text_view_new();
00224     gtk_text_view_set_editable(GTK_TEXT_VIEW(tientry), TRUE);
00225     select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
00226 
00227     /* Set the tab width, using pango tab array */
00229     tab_array = pango_tab_array_new (1, TRUE);
00230     real_tab_width = text_view_calculate_real_tab_width(GTK_TEXT_VIEW(tientry),
00231                                                         tab_in_chars);
00232     if (real_tab_width >= 0) {
00233       pango_tab_array_set_tab (tab_array, 0, PANGO_TAB_LEFT, real_tab_width);
00234       /* printf("Real tab width: %i\n", real_tab_width);*/
00235       gtk_text_view_set_tabs (GTK_TEXT_VIEW (tientry),
00236                               tab_array);
00237     }
00238     else {
00239       g_warning ("text_input_dialog: Impossible to set tab width.\n");
00240     }
00241     pango_tab_array_free (tab_array);
00242     gtk_container_add(GTK_CONTAINER(scrolled_window), tientry);
00243 
00244     gtk_object_set_data(GTK_OBJECT(w_current->tiwindow),
00245                         "tientry",tientry);
00246 
00247     gtk_widget_show_all (w_current->tiwindow);
00248   }
00249   else { /* dialog already created */
00250     gtk_window_present (GTK_WINDOW(w_current->tiwindow));
00251   }
00252 
00253   /* always select the text in the entry */
00254   tientry = gtk_object_get_data(GTK_OBJECT(w_current->tiwindow),"tientry");
00255   select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
00256   gtk_widget_grab_focus(tientry);
00257 }
00258 
00259 /***************** End of Text Input dialog box ***********************/
00260 
00261 /***************** Start of Text Edit dialog box **********************/
00269 gint change_alignment(GtkComboBox *w, GSCHEM_TOPLEVEL *w_current)
00270 {
00271   GtkTreeIter iter;
00272   GtkTreeModel *model;
00273   gint value;
00274   if( gtk_combo_box_get_active_iter(w, &iter))
00275   {
00276     model = gtk_combo_box_get_model(w);
00277     gtk_tree_model_get(model, &iter, 1, &value, -1);
00278     w_current->text_alignment = value;
00279   }
00280 
00281   /*w_current->page_current->CHANGED=1; I don't think this belongs */
00282   /* o_undo_savestate(w_current, UNDO_ALL); I don't think this belongs */
00283 
00284   return 0;
00285 }
00286 
00293 static GtkListStore *create_menu_alignment (GSCHEM_TOPLEVEL *w_current)
00294 {
00295   GtkListStore *store;
00296   GtkTreeIter   iter;
00297 
00298   store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
00299 
00300   gtk_list_store_append(store, &iter);
00301   gtk_list_store_set(store, &iter, 0, _("Upper Left"), -1);
00302   gtk_list_store_set(store, &iter, 1, 2, -1);
00303   gtk_list_store_append(store, &iter);
00304   gtk_list_store_set(store, &iter, 0, _("Upper Middle"), -1);
00305   gtk_list_store_set(store, &iter, 1, 5, -1);
00306   gtk_list_store_append( store, &iter);
00307   gtk_list_store_set(store, &iter, 0, _("Upper Right"), -1);
00308   gtk_list_store_set(store, &iter, 1, 8, -1);
00309 
00310   gtk_list_store_append(store, &iter);
00311   gtk_list_store_set(store, &iter, 0, _("Middle Left"), -1);
00312   gtk_list_store_set(store, &iter, 1, 1, -1);
00313   gtk_list_store_append(store, &iter);
00314   gtk_list_store_set(store, &iter, 0, _("Middle Middle"), -1);
00315   gtk_list_store_set(store, &iter, 1, 4, -1);
00316   gtk_list_store_append(store, &iter);
00317   gtk_list_store_set(store, &iter, 0, _("Middle Right"), -1);
00318   gtk_list_store_set(store, &iter, 1, 7, -1);
00319 
00320   gtk_list_store_append(store, &iter);
00321   gtk_list_store_set(store, &iter, 0, _("Lower Left"), -1);
00322   gtk_list_store_set(store, &iter, 1, 0, -1);
00323   gtk_list_store_append(store, &iter);
00324   gtk_list_store_set(store, &iter, 0, _("Lower Middle"), -1);
00325   gtk_list_store_set(store, &iter, 1, 3, -1);
00326   gtk_list_store_append(store, &iter);
00327   gtk_list_store_set(store, &iter, 0, _("Lower Right"), -1);
00328   gtk_list_store_set(store, &iter, 1, 6, -1);
00329 
00330   return store;
00331 }
00332 
00333 /* we reuse the color menu so we need to declare it */
00334 static GtkWidget *create_color_menu(GSCHEM_TOPLEVEL * w_current);
00335 
00341 void text_edit_dialog_ok(GtkWidget *w, GSCHEM_TOPLEVEL *w_current)
00342 {
00343   int len=0;
00344   int text_size=8;
00345   char *text_string = NULL;
00346   char *text_size_string = NULL;
00347   int new_text_alignment;
00348   int num_selected;
00349   GtkTextBuffer *textbuffer;
00350   GtkTextIter start, end;
00351   GtkWidget *widget;
00352 
00353   num_selected = g_list_length( geda_list_get_glist( w_current->toplevel->page_current->selection_list ));
00354 
00355   /* text string entry will only show up if one object is selected */
00356   if (num_selected == 1) {
00357     widget = g_object_get_data (G_OBJECT (w_current->tewindow), "textentry");
00358     textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
00359     gtk_text_buffer_get_bounds (textbuffer, &start, &end);
00360     text_string =  gtk_text_iter_get_text (&start, &end);
00361   } /* else the string will be null which is okay */
00362 
00363   widget = g_object_get_data (G_OBJECT (w_current->tewindow), "sizeentry");
00364   text_size_string = (char *) gtk_entry_get_text(GTK_ENTRY(widget));
00365 
00366   if (text_string) {
00367     len = strlen(text_string);
00368   }
00369 
00370   if (text_size_string) {
00371     text_size = atoi(text_size_string);
00372   }
00373 
00374   if (text_size == 0) {
00375     text_size = default_text_size;
00376   }
00377 
00378   new_text_alignment = w_current->text_alignment;
00379 
00380   o_text_edit_end(w_current, text_string, len, text_size, new_text_alignment);
00381 }
00382 
00389 void text_edit_dialog_response(GtkWidget * widget, gint response, GSCHEM_TOPLEVEL *w_current)
00390 {
00391   switch(response) {
00392   case GTK_RESPONSE_ACCEPT:
00393     text_edit_dialog_ok(widget, w_current);
00394     break;
00395   case GTK_RESPONSE_REJECT:
00396   case GTK_RESPONSE_DELETE_EVENT:
00397     /* void */
00398     break;
00399   default:
00400     printf("text_edit_dialog_response(): strange signal %d\n", response);
00401   }
00402   /* clean up */
00403   i_set_state(w_current, SELECT);
00404   i_update_toolbar(w_current);
00405   gtk_widget_destroy(w_current->tewindow);
00406   w_current->tewindow = NULL;
00407 }
00408 
00415 void text_edit_dialog (GSCHEM_TOPLEVEL *w_current, const char *string, int text_size,
00416                        int text_alignment)
00417 {
00418   GtkWidget *label;
00419   GtkWidget *table;
00420   GtkWidget *vbox;
00421   GtkWidget *optionmenu;
00422   GtkWidget *combobox;
00423   GtkListStore *align_menu_model;
00424   GtkCellRenderer *cell;
00425   GtkWidget *viewport1;
00426   GtkWidget *textentry;
00427   GtkWidget *sizeentry;
00428   GtkWidget *alignment;
00429   GtkWidget *scrolled_window;
00430   GtkTextBuffer *textbuffer;
00431   char *text_size_string;
00432   int num_selected;
00433   /* Lookup table for quickly translating between alignment values and the
00434      combo box list indices, index is alignment value, value is list index */
00435   static int alignment_lookup[] = {6, 3, 0, 7, 4, 1, 8, 5, 2};
00436 
00437   if (!w_current->tewindow) {
00438     w_current->tewindow = gschem_dialog_new_with_buttons(_("Edit Text Properties"),
00439                                                          GTK_WINDOW(w_current->main_window),
00440                                                          GTK_DIALOG_MODAL,
00441                                                          "text-edit", w_current,
00442                                                          GTK_STOCK_CANCEL,
00443                                                          GTK_RESPONSE_REJECT,
00444                                                          GTK_STOCK_OK,
00445                                                          GTK_RESPONSE_ACCEPT,
00446                                                          NULL);
00447 
00448   /* Set the alternative button order (ok, cancel, help) for other systems */
00449     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tewindow),
00450                                             GTK_RESPONSE_ACCEPT,
00451                                             GTK_RESPONSE_REJECT,
00452                                             -1);
00453 
00454     gtk_dialog_set_default_response(GTK_DIALOG(w_current->tewindow),
00455                                     GTK_RESPONSE_ACCEPT);
00456 
00457     g_signal_connect (G_OBJECT (w_current->tewindow), "response",
00458                       G_CALLBACK (text_edit_dialog_response),
00459                       w_current);
00460 
00461     gtk_window_position(GTK_WINDOW (w_current->tewindow),
00462                         GTK_WIN_POS_MOUSE);
00463 
00464 
00465     vbox = GTK_DIALOG(w_current->tewindow)->vbox;
00466     gtk_container_set_border_width(GTK_CONTAINER(w_current->tewindow),DIALOG_BORDER_SPACING);
00467     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
00468 
00469     /* add a text box if only one object is selected */
00470     num_selected = g_list_length( geda_list_get_glist( w_current->toplevel->page_current->selection_list ));
00471 
00472     if (num_selected == 1) {
00473       label = gtk_label_new (_("<b>Text Content</b>"));
00474       gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
00475       gtk_misc_set_alignment(GTK_MISC(label),0,0);
00476       gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
00477 
00478       alignment = gtk_alignment_new(0,0,1,1);
00479       gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
00480                                 DIALOG_INDENTATION, 0);
00481       gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
00482 
00483       viewport1 = gtk_viewport_new (NULL, NULL);
00484       gtk_widget_set_size_request(GTK_WIDGET(viewport1),-1,75);
00485 
00486       scrolled_window = gtk_scrolled_window_new(NULL, NULL);
00487       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
00488                                      GTK_POLICY_AUTOMATIC,
00489                                      GTK_POLICY_AUTOMATIC);
00490       gtk_container_add (GTK_CONTAINER (viewport1), scrolled_window);
00491       gtk_container_add( GTK_CONTAINER(alignment), viewport1);
00492 
00493       textentry = gtk_text_view_new();
00494       gtk_text_view_set_editable (GTK_TEXT_VIEW (textentry), TRUE);
00495       if (string != NULL) {
00496         textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textentry));
00497         gtk_text_buffer_set_text (GTK_TEXT_BUFFER (textbuffer), string, -1);
00498         select_all_text_in_textview (GTK_TEXT_VIEW (textentry));
00499       }
00500 
00502       /* See first the code in text_input_dialog and get it working before adding it here. */
00503 
00504       gtk_container_add(GTK_CONTAINER(scrolled_window), textentry);
00505       gtk_widget_grab_focus(textentry);
00506       GLADE_HOOKUP_OBJECT(w_current->tewindow, textentry,"textentry");
00507     }
00508 
00509     label = gtk_label_new(_("<b>Text Properties</b>"));
00510     gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
00511     gtk_misc_set_alignment(GTK_MISC(label),0,0);
00512     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
00513 
00514     alignment = gtk_alignment_new(0,0,1,1);
00515     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
00516                               DIALOG_INDENTATION, 0);
00517     gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
00518 
00519     table = gtk_table_new (3, 2, FALSE);
00520     gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
00521     gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
00522     gtk_container_add(GTK_CONTAINER(alignment), table);
00523 
00524     label = gtk_label_new(_("Color:"));
00525     gtk_misc_set_alignment(GTK_MISC(label),0,0);
00526     gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
00527 
00528     optionmenu = create_color_menu (w_current);
00529     gtk_table_attach_defaults(GTK_TABLE(table), optionmenu, 1,2,0,1);
00530 
00531     label = gtk_label_new(_("Size:"));
00532     gtk_misc_set_alignment(GTK_MISC(label),0,0);
00533     gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
00534 
00535     sizeentry = gtk_entry_new_with_max_length (10);
00536     gtk_editable_select_region(GTK_EDITABLE (sizeentry), 0, -1);
00537     gtk_table_attach_defaults(GTK_TABLE(table), sizeentry, 1,2,1,2);
00538     gtk_entry_set_activates_default(GTK_ENTRY(sizeentry), TRUE);
00539 
00540     label = gtk_label_new(_("Alignment:"));
00541     gtk_misc_set_alignment(GTK_MISC(label),0,0);
00542     gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
00543 
00544     align_menu_model = create_menu_alignment(w_current);
00545     combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(align_menu_model));
00546     gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combobox), 3);
00547     cell = gtk_cell_renderer_text_new();
00548     gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), cell, TRUE);
00549     gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), cell,
00550                                    "text", 0, NULL);
00551     gtk_combo_box_set_active(GTK_COMBO_BOX(combobox),
00552                              alignment_lookup[text_alignment]);
00553     w_current->text_alignment = text_alignment;
00554     g_object_unref (align_menu_model);
00555     gtk_table_attach_defaults(GTK_TABLE(table), combobox, 1,2,2,3);
00556     g_signal_connect(G_OBJECT(combobox), "changed",
00557                       G_CALLBACK(change_alignment), w_current);
00558 
00559     GLADE_HOOKUP_OBJECT(w_current->tewindow, sizeentry,"sizeentry");
00560     gtk_widget_show_all(w_current->tewindow);
00561   }
00562 
00563   else { /* dialog already there */
00564     gtk_window_present(GTK_WINDOW(w_current->tewindow));
00565   }
00566 
00567   text_size_string = g_strdup_printf("%d", text_size);
00568   sizeentry = g_object_get_data (G_OBJECT (w_current->tewindow), "sizeentry");
00569   gtk_entry_set_text(GTK_ENTRY(sizeentry),
00570                      text_size_string);
00571   g_free(text_size_string);
00572 }
00573 
00574 /***************** End of Text Edit dialog box ************************/
00575 
00576 /***************** Start of Line Type/width dialog box ****************/
00577 
00582 static GtkWidget *create_menu_linetype (GSCHEM_TOPLEVEL *w_current)
00583 {
00584   GtkWidget *menu;
00585   GSList *group;
00586   struct line_type {
00587     gchar *str;
00588     OBJECT_TYPE type;
00589   } types[] = { { N_("Solid"),   TYPE_SOLID },
00590                 { N_("Dotted"),  TYPE_DOTTED },
00591                 { N_("Dashed"),  TYPE_DASHED },
00592                 { N_("Center"),  TYPE_CENTER },
00593                 { N_("Phantom"), TYPE_PHANTOM },
00594                 { N_("*unchanged*"), TYPE_ERASE } };
00595   gint i;
00596 
00597   menu  = gtk_menu_new ();
00598   group = NULL;
00599 
00600   for (i = 0; i < sizeof (types) / sizeof (struct line_type); i++) {
00601     GtkWidget *menuitem;
00602 
00603     menuitem = gtk_radio_menu_item_new_with_label (group, _(types[i].str));
00604     group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
00605     gtk_menu_append (GTK_MENU (menu), menuitem);
00606     gtk_object_set_data (GTK_OBJECT(menuitem), "linetype",
00607                          GINT_TO_POINTER (types[i].type));
00608     gtk_widget_show (menuitem);
00609   }
00610 
00611   return(menu);
00612 }
00613 
00627 static gboolean selection_get_line_type(GList *selection,
00628                                         OBJECT_END *end, OBJECT_TYPE *type,
00629                                         gint *width, gint *length, gint *space)
00630 {
00631   GList *iter;
00632   OBJECT *object;
00633   gboolean found = FALSE;
00634   OBJECT_END oend;
00635   OBJECT_TYPE otype;
00636   gint owidth, olength, ospace;
00637 
00638   for (iter = selection; iter != NULL; iter = g_list_next(iter)) {
00639     object = (OBJECT *) iter->data;
00640     if (! o_get_line_options(object, &oend, &otype, 
00641                              &owidth, &olength, &ospace))
00642       continue;
00643 
00644     if (found == FALSE) {  /* first object with filltype */
00645       found = TRUE;
00646       *end = oend;
00647       *type = otype;
00648       *width = owidth;
00649       *length = olength;
00650       *space = ospace;
00651     } else {
00652       /* indicate different values with the value -2 */
00653       if (*end != oend) *end = -2;
00654       if (*type != otype) *type = -2;
00655       if (*width != owidth) *width = -2;
00656       if (*length != olength) *length = -2;
00657       if (*space != ospace) *space = -2;
00658     }
00659   }
00660 
00661   return found;
00662 }
00663  
00664 
00676 static void line_type_dialog_set_values(struct line_type_data *line_type_data,
00677                                         OBJECT_END end, OBJECT_TYPE type,
00678                                         gint width, gint length, gint space)
00679 {
00680   gchar *text;
00681   GtkWidget *menu, *menuitem;
00682 
00683   if (type == -2)
00684     type = TYPE_ERASE;
00685   gtk_option_menu_set_history(GTK_OPTION_MENU(line_type_data->line_type), type);
00686   menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(line_type_data->line_type));
00687   menuitem = gtk_menu_get_active(GTK_MENU(menu));
00688   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
00689 
00690   if (width == -2)
00691     text = g_strdup(_("*unchanged*"));
00692   else
00693     text = g_strdup_printf ("%d", width);
00694   gtk_entry_set_text (GTK_ENTRY (line_type_data->width_entry), text);
00695   gtk_entry_select_region (GTK_ENTRY (line_type_data->width_entry), 
00696                            0, strlen (text));
00697   g_free(text);
00698 
00699   if (length == -2)
00700     text = g_strdup(_("*unchanged*"));
00701   else
00702     text = g_strdup_printf ("%d", length);
00703   gtk_entry_set_text (GTK_ENTRY (line_type_data->length_entry), text);
00704   gtk_entry_select_region (GTK_ENTRY (line_type_data->length_entry), 
00705                            0, strlen (text));
00706   g_free(text);
00707 
00708   if (space == -2)
00709     text = g_strdup(_("*unchanged*"));
00710   else
00711     text = g_strdup_printf ("%d", space);
00712   gtk_entry_set_text (GTK_ENTRY (line_type_data->space_entry), text);
00713   gtk_entry_select_region (GTK_ENTRY (line_type_data->space_entry),
00714                            0, strlen (text));
00715   g_free(text);
00716 }
00717                                          
00718 
00724 static gint line_type_dialog_linetype_change(GtkWidget *w, gpointer data)
00725 {
00726   struct line_type_data *line_type_data = (struct line_type_data*) data;
00727   GtkWidget *menuitem;
00728   gboolean activate_length_entry, activate_space_entry;
00729   gint type;
00730 
00731   menuitem = gtk_menu_get_active (
00732     GTK_MENU (gtk_option_menu_get_menu (
00733                 GTK_OPTION_MENU (line_type_data->line_type))));
00734 
00735   type = GPOINTER_TO_INT(
00736     gtk_object_get_data (GTK_OBJECT (menuitem), "linetype"));
00737   switch(type) {
00738       case(TYPE_SOLID):
00739         activate_length_entry = FALSE;
00740         activate_space_entry  = FALSE;
00741         break;
00742       case(TYPE_DOTTED):
00743         activate_length_entry = FALSE;
00744         activate_space_entry  = TRUE;
00745         break;
00746       case(TYPE_DASHED):
00747       case(TYPE_CENTER):
00748       case(TYPE_PHANTOM):
00749         activate_length_entry = TRUE;
00750         activate_space_entry  = TRUE;
00751         break;
00752       default:
00753         activate_length_entry = TRUE;
00754         activate_space_entry  = TRUE;
00755   }
00756 
00757   gtk_widget_set_sensitive (line_type_data->space_entry,
00758                             activate_space_entry);
00759   gtk_widget_set_sensitive (line_type_data->length_entry,
00760                             activate_length_entry);
00761 
00762   return(0);
00763 }
00764 
00765 
00771 static void line_type_dialog_ok(GtkWidget *w, gpointer data)
00772 {
00773   struct line_type_data *line_type_data = (struct line_type_data*)data;
00774   GSCHEM_TOPLEVEL *w_current = line_type_data->w_current;
00775   TOPLEVEL *toplevel = w_current->toplevel;
00776   GList *selection, *iter;
00777   OBJECT *object;
00778   const gchar *width_str, *length_str, *space_str;
00779   OBJECT_TYPE type;
00780   gint width, length, space;
00781   OBJECT_TYPE otype;
00782   OBJECT_END oend;
00783   gint owidth, olength, ospace;
00784 
00785   /* get the selection */
00786   if (! o_select_selected(w_current))
00787     return;
00788   selection = 
00789     geda_list_get_glist(w_current->toplevel->page_current->selection_list);
00790 
00791   /* get the new values from the text entries of the dialog */
00792   width_str   = gtk_entry_get_text (GTK_ENTRY (
00793                                       line_type_data->width_entry));
00794   length_str  = gtk_entry_get_text (GTK_ENTRY (
00795                                       line_type_data->length_entry));
00796   space_str   = gtk_entry_get_text (GTK_ENTRY (
00797                                       line_type_data->space_entry));
00798   type = GPOINTER_TO_INT(
00799     gtk_object_get_data (
00800       GTK_OBJECT (
00801         gtk_menu_get_active (
00802           GTK_MENU (gtk_option_menu_get_menu (
00803                       GTK_OPTION_MENU (
00804                         line_type_data->line_type))))), "linetype"));
00805   if (type == TYPE_ERASE)
00806     type = -1;
00807   
00808   /* convert the options to integers (-1 means unchanged) */
00809   width =  g_utf8_collate (g_utf8_casefold (width_str, -1),
00810                            g_utf8_casefold (_("*unchanged*"), -1))
00811     ? atoi (width_str)  : -1;
00812   length = g_utf8_collate (g_utf8_casefold (length_str, -1),
00813                            g_utf8_casefold (_("*unchanged*"), -1))
00814     ? atoi (length_str) : -1;
00815   space  = g_utf8_collate (g_utf8_casefold (space_str, -1),
00816                            g_utf8_casefold (_("*unchanged*"), -1))
00817     ? atoi (space_str)  : -1;
00818 
00819   for (iter = selection; iter != NULL; iter = g_list_next(iter)) {
00820     object = (OBJECT *) iter->data;
00821     if (! o_get_line_options(object, &oend, &otype,
00822                              &owidth, &olength, &ospace))
00823       continue;
00824 
00825     /* oend is not in the dialog, yet */
00826     otype = type == -1 ? otype : type;
00827     owidth = width  == -1 ? owidth : width;
00828     olength = length == -1 ? olength : length;
00829     ospace = space  == -1 ? ospace : space;
00830 
00831     /* set all not required options to -1 and 
00832        set nice parameters if not provided by the user */
00833     switch (otype) {
00834     case (TYPE_SOLID):
00835       olength = ospace = -1;
00836       break;
00837     case (TYPE_DOTTED):
00838       olength = -1;
00839       if (ospace < 1) ospace = 100;
00840       break;
00841     case (TYPE_DASHED):
00842     case (TYPE_CENTER):
00843     case (TYPE_PHANTOM):
00844       if (ospace < 1) ospace = 100;
00845       if (olength < 1) olength = 100;
00846       break;
00847     default:
00848       g_assert_not_reached();
00849     }
00850 
00851     o_set_line_options (toplevel, object,
00852                         oend, otype, owidth, olength, ospace);
00853   }
00854 
00855   toplevel->page_current->CHANGED = 1;
00856   o_undo_savestate(w_current, UNDO_ALL);
00857 }
00858 
00865 void line_type_dialog_response(GtkWidget *widget, gint response,
00866                                struct line_type_data *line_type_data)
00867 {
00868   switch (response) {
00869   case GTK_RESPONSE_REJECT:
00870   case GTK_RESPONSE_DELETE_EVENT:
00871     /* void */
00872     break;
00873   case GTK_RESPONSE_ACCEPT:
00874     line_type_dialog_ok(widget, line_type_data);
00875     break;
00876   default:
00877     printf("line_type_dialog_response(): strange signal %d\n",response);
00878   }
00879 
00880   i_set_state (line_type_data->w_current, SELECT);
00881   i_update_toolbar (line_type_data->w_current);
00882   gtk_widget_destroy (line_type_data->dialog);
00883 
00884   g_free (line_type_data);
00885 }
00886 
00892 void line_type_dialog (GSCHEM_TOPLEVEL *w_current)
00893 {
00894   GtkWidget *dialog;
00895   GtkWidget *vbox;
00896   GtkWidget *optionmenu   = NULL;
00897   GtkWidget *length_entry = NULL;
00898   GtkWidget *space_entry  = NULL;
00899   GtkWidget *width_entry  = NULL;
00900   GtkWidget *table;
00901   GtkWidget *label;
00902   struct line_type_data *line_type_data;
00903   GList *selection;
00904   OBJECT_END end=END_NONE;
00905   OBJECT_TYPE type=TYPE_SOLID;
00906   gint width=1, length=-1, space=-1;
00907 
00908   if (! o_select_selected(w_current))
00909     return;
00910 
00911   selection = 
00912     geda_list_get_glist(w_current->toplevel->page_current->selection_list);
00913 
00914   if (! selection_get_line_type(selection, &end, &type,
00915                                 &width, &length, &space))
00916     return;
00917 
00918   line_type_data = (struct line_type_data*) g_malloc (
00919     sizeof (struct line_type_data));
00920 
00921   dialog = gschem_dialog_new_with_buttons(_("Edit Line Width & Type"),
00922                                           GTK_WINDOW(w_current->main_window),
00923                                           GTK_DIALOG_MODAL,
00924                                           "line-type", w_current,
00925                                           GTK_STOCK_CANCEL,
00926                                           GTK_RESPONSE_REJECT,
00927                                           GTK_STOCK_OK,
00928                                           GTK_RESPONSE_ACCEPT,
00929                                           NULL);
00930 
00931   /* Set the alternative button order (ok, cancel, help) for other systems */
00932   gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
00933                                           GTK_RESPONSE_ACCEPT,
00934                                           GTK_RESPONSE_REJECT,
00935                                           -1);
00936 
00937   gtk_window_position(GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
00938 
00939   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
00940 
00941   g_signal_connect (G_OBJECT (dialog), "response",
00942                     G_CALLBACK (line_type_dialog_response),
00943                     line_type_data);
00944 
00945   gtk_container_border_width(GTK_CONTAINER(dialog),
00946                              DIALOG_BORDER_SPACING);
00947   vbox = GTK_DIALOG(dialog)->vbox;
00948   gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
00949 
00950   /*  Don't know whether to set the headline or not (Werner) */
00951   /*  label = gtk_label_new(_("Line Properties:"));
00952       gtk_misc_set_alignment(GTK_MISC(label),0,0);
00953       gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); */
00954 
00955   table = gtk_table_new (4, 2, FALSE);
00956   gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
00957   gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
00958   gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
00959 
00960   label = gtk_label_new (_("Type:"));
00961   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
00962   gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
00963 
00964   label = gtk_label_new (_("Width:"));
00965   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
00966   gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
00967 
00968   label = gtk_label_new (_("Dash Length:"));
00969   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
00970   gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
00971 
00972   label = gtk_label_new (_("Dash Space:"));
00973   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
00974   gtk_table_attach(GTK_TABLE(table), label, 0,1,3,4, GTK_FILL,0,0,0);
00975 
00976   optionmenu = gtk_option_menu_new ();
00977   gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu),
00978                            create_menu_linetype (w_current));
00979   gtk_table_attach_defaults(GTK_TABLE(table), optionmenu,
00980                             1,2,0,1);
00981 
00982   width_entry = gtk_entry_new();
00983   gtk_entry_set_activates_default (GTK_ENTRY(width_entry), TRUE);
00984   gtk_editable_select_region(GTK_EDITABLE(width_entry), 0, -1);
00985   gtk_table_attach_defaults(GTK_TABLE(table), width_entry,
00986                             1,2,1,2);
00987 
00988   g_signal_connect(G_OBJECT (optionmenu), "changed",
00989                    G_CALLBACK (line_type_dialog_linetype_change),
00990                    line_type_data);
00991 
00992   length_entry = gtk_entry_new();
00993   gtk_entry_set_activates_default (GTK_ENTRY(length_entry), TRUE);
00994   gtk_editable_select_region(GTK_EDITABLE(length_entry), 0, -1);
00995   gtk_table_attach_defaults(GTK_TABLE(table), length_entry,
00996                             1,2,2,3);
00997 
00998   space_entry = gtk_entry_new();
00999   gtk_entry_set_activates_default (GTK_ENTRY(space_entry), TRUE);
01000   gtk_editable_select_region(GTK_EDITABLE(space_entry), 0, -1);
01001   gtk_table_attach_defaults(GTK_TABLE(table), space_entry,
01002                             1,2,3,4);
01003 
01004   /* populate the data structure */
01005   line_type_data->dialog = dialog;
01006   line_type_data->width_entry  = width_entry;
01007   line_type_data->line_type    = optionmenu;
01008   line_type_data->length_entry = length_entry;
01009   line_type_data->space_entry  = space_entry;
01010 
01011   line_type_data->w_current = w_current;
01012 
01013   /* fill in the fields of the dialog */
01014   line_type_dialog_set_values(line_type_data, end, type,
01015                               width, length, space);
01016 
01017   /* calling it once will set the dash space/length activity */
01018   line_type_dialog_linetype_change(optionmenu, line_type_data);
01019 
01020   gtk_widget_grab_focus(width_entry);
01021   gtk_widget_show_all (dialog);
01022 }
01023 
01024 /***************** End of Line Type / Width dialog box ****************/
01025 
01026 /***************** Start of Fill Type dialog box **********************/
01027 
01032 static GtkWidget *create_menu_filltype (GSCHEM_TOPLEVEL *w_current)
01033 {
01034   GtkWidget *menu;
01035   GSList *group;
01036   struct fill_type {
01037     gchar *str;
01038     OBJECT_FILLING type;
01039   } types[] = { { N_("Hollow"), FILLING_HOLLOW },
01040                 { N_("Filled"), FILLING_FILL },
01041                 { N_("Mesh"),   FILLING_MESH },
01042                 { N_("Hatch"),  FILLING_HATCH },
01043                 { N_("*unchanged*"), FILLING_VOID } };
01044   gint i;
01045 
01046   menu  = gtk_menu_new ();
01047   group = NULL;
01048 
01049   for (i = 0; i < sizeof (types) / sizeof (struct fill_type); i++) {
01050     GtkWidget *menuitem;
01051 
01052     menuitem = gtk_radio_menu_item_new_with_label (group, _(types[i].str));
01053     group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
01054     gtk_menu_append (GTK_MENU (menu), menuitem);
01055     gtk_object_set_data (GTK_OBJECT(menuitem), "filltype",
01056                          GINT_TO_POINTER (types[i].type));
01057     gtk_widget_show (menuitem);
01058   }
01059 
01060   return menu;
01061 }
01062 
01077 static gboolean selection_get_fill_type(GList *selection,
01078                                         OBJECT_FILLING *type, gint *width,
01079                                         gint *pitch1, gint *angle1,
01080                                         gint *pitch2, gint *angle2)
01081 {
01082   GList *iter;
01083   OBJECT *object;
01084   gboolean found = FALSE;
01085   OBJECT_FILLING otype;
01086   gint owidth, opitch1, oangle1, opitch2, oangle2;
01087 
01088 
01089   for (iter = selection; iter != NULL; iter = g_list_next(iter)) {
01090     object = (OBJECT *) iter->data;
01091     if (! o_get_fill_options(object, &otype, &owidth, 
01092                              &opitch1, &oangle1, &opitch2, &oangle2))
01093       continue;
01094 
01095     if (found == FALSE) {  /* first object with filltype */
01096       found = TRUE;
01097       *type = otype;
01098       *width = owidth;
01099       *pitch1 = opitch1;
01100       *angle1 = oangle1;
01101       *pitch2 = opitch2;
01102       *angle2 = oangle2;
01103     } else {
01104       /* indicate different values with the value -2 */
01105       if (*type != otype) *type = -2;
01106       if (*width != owidth) *width = -2;
01107       if (*pitch1 != opitch1) *pitch1 = -2;
01108       if (*angle1 != oangle1) *angle1 = -2;
01109       if (*pitch2 != opitch2) *pitch2 = -2;
01110       if (*angle2 != oangle2) *angle2 = -2;
01111     }
01112   }
01113 
01114   return found;
01115 }
01116 
01117 
01130 static void fill_type_dialog_set_values(struct fill_type_data *fill_type_data,
01131                                         OBJECT_FILLING type, gint width,
01132                                         gint pitch1, gint angle1,
01133                                         gint pitch2, gint angle2)
01134 {
01135   gchar *text;
01136   GtkWidget *menu, *menuitem;
01137 
01138   if (type == -2)
01139     type = FILLING_VOID;
01140   gtk_option_menu_set_history(GTK_OPTION_MENU(fill_type_data->fill_type), type);
01141   menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(fill_type_data->fill_type));
01142   menuitem = gtk_menu_get_active(GTK_MENU(menu));
01143   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
01144 
01145   if (width == -2)
01146     text = g_strdup(_("*unchanged*"));
01147   else
01148     text = g_strdup_printf ("%d", width);
01149   gtk_entry_set_text (GTK_ENTRY (fill_type_data->width_entry), text);
01150   gtk_entry_select_region (GTK_ENTRY (fill_type_data->width_entry), 
01151                            0, strlen (text));
01152   g_free(text);
01153 
01154   if (pitch1 == -2)
01155     text = g_strdup(_("*unchanged*"));
01156   else
01157     text = g_strdup_printf ("%d", pitch1);
01158   gtk_entry_set_text (GTK_ENTRY (fill_type_data->pitch1_entry), text);
01159   gtk_entry_select_region (GTK_ENTRY (fill_type_data->pitch1_entry), 
01160                            0, strlen (text));
01161   g_free(text);
01162 
01163   if (angle1 == -2)
01164     text = g_strdup(_("*unchanged*"));
01165   else
01166     text = g_strdup_printf ("%d", angle1);
01167   gtk_entry_set_text (GTK_ENTRY (fill_type_data->angle1_entry), text);
01168   gtk_entry_select_region (GTK_ENTRY (fill_type_data->angle1_entry), 
01169                            0, strlen (text));
01170   g_free(text);
01171 
01172   if (pitch2 == -2)
01173     text = g_strdup(_("*unchanged*"));
01174   else
01175     text = g_strdup_printf ("%d", pitch2);
01176   gtk_entry_set_text (GTK_ENTRY (fill_type_data->pitch2_entry), text);
01177   gtk_entry_select_region (GTK_ENTRY (fill_type_data->pitch2_entry), 
01178                            0, strlen (text));
01179   g_free(text);
01180 
01181   if (angle2 == -2)
01182     text = g_strdup(_("*unchanged*"));
01183   else
01184     text = g_strdup_printf ("%d", angle2);
01185   gtk_entry_set_text (GTK_ENTRY (fill_type_data->angle2_entry), text);
01186   gtk_entry_select_region (GTK_ENTRY (fill_type_data->angle2_entry), 
01187                            0, strlen (text));
01188   g_free(text);
01189 }
01190 
01191 
01197 static gint fill_type_dialog_filltype_change(GtkWidget *w, gpointer data)
01198 {
01199   struct fill_type_data *fill_type_data = (struct fill_type_data*) data;
01200   GtkWidget *menuitem;
01201   gboolean activate_width_entry;
01202   gboolean activate_anglepitch1_entries;
01203   gboolean activate_anglepitch2_entries;
01204   gint type;
01205 
01206   menuitem = gtk_menu_get_active (
01207     GTK_MENU (gtk_option_menu_get_menu (
01208                 GTK_OPTION_MENU (fill_type_data->fill_type))));
01209 
01210   type = GPOINTER_TO_INT(
01211     gtk_object_get_data (GTK_OBJECT (menuitem), "filltype"));
01212   switch(type) {
01213   case(FILLING_HOLLOW):
01214   case(FILLING_FILL):
01215     activate_width_entry = FALSE;
01216     activate_anglepitch1_entries = FALSE;
01217     activate_anglepitch2_entries = FALSE;
01218     break;
01219   case(FILLING_HATCH):
01220     activate_width_entry = TRUE;
01221     activate_anglepitch1_entries = TRUE;
01222     activate_anglepitch2_entries = FALSE;
01223     break;
01224   case(FILLING_MESH):
01225   case(FILLING_VOID):
01226     activate_width_entry = TRUE;
01227     activate_anglepitch1_entries = TRUE;
01228     activate_anglepitch2_entries = TRUE;
01229     break;
01230   default:
01231     g_assert_not_reached ();
01232   }
01233 
01234   gtk_widget_set_sensitive (fill_type_data->width_entry,
01235                             activate_width_entry);
01236   gtk_widget_set_sensitive (fill_type_data->angle1_entry,
01237                             activate_anglepitch1_entries);
01238   gtk_widget_set_sensitive (fill_type_data->pitch1_entry,
01239                             activate_anglepitch1_entries);
01240   gtk_widget_set_sensitive (fill_type_data->angle2_entry,
01241                             activate_anglepitch2_entries);
01242   gtk_widget_set_sensitive (fill_type_data->pitch2_entry,
01243                             activate_anglepitch2_entries);
01244 
01245   return(0);
01246 }
01247 
01253 static void fill_type_dialog_ok(GtkWidget *w, gpointer data)
01254 {
01255   struct fill_type_data *fill_type_data = (struct fill_type_data*) data;
01256   GSCHEM_TOPLEVEL *w_current = fill_type_data->w_current;
01257   TOPLEVEL *toplevel = w_current->toplevel;
01258   GList *selection, *iter;
01259   OBJECT *object;
01260   const gchar *width_str, *angle1_str, *pitch1_str, *angle2_str, *pitch2_str;
01261   OBJECT_FILLING type;
01262   gint width, angle1, pitch1, angle2, pitch2;
01263   OBJECT_FILLING otype;
01264   gint owidth, oangle1, opitch1, oangle2, opitch2;
01265 
01266   /* get the selection */
01267   if (! o_select_selected(w_current))
01268     return;
01269   selection = 
01270     geda_list_get_glist(w_current->toplevel->page_current->selection_list);
01271 
01272   /* get the new values from the text entries of the dialog */
01273   width_str  = gtk_entry_get_text (GTK_ENTRY (
01274                                      fill_type_data->width_entry));
01275   angle1_str = gtk_entry_get_text (GTK_ENTRY (
01276                                      fill_type_data->angle1_entry));
01277   pitch1_str = gtk_entry_get_text (GTK_ENTRY (
01278                                      fill_type_data->pitch1_entry));
01279   angle2_str = gtk_entry_get_text (GTK_ENTRY (
01280                                      fill_type_data->angle2_entry));
01281   pitch2_str = gtk_entry_get_text (GTK_ENTRY (
01282                                      fill_type_data->pitch2_entry));
01283   type = GPOINTER_TO_INT(
01284     gtk_object_get_data (
01285       GTK_OBJECT (
01286         gtk_menu_get_active (
01287           GTK_MENU (gtk_option_menu_get_menu (
01288                       GTK_OPTION_MENU (
01289                         fill_type_data->fill_type))))), "filltype"));
01290   if (type == FILLING_VOID)
01291     type = -1;
01292 
01293   /* convert the options to integers (-1 means unchanged) */
01294   width  = g_utf8_collate (g_utf8_casefold (width_str, -1),
01295                            g_utf8_casefold(_("*unchanged*"), -1))
01296     ? atoi (width_str)  : -1;
01297   angle1 = g_utf8_collate (g_utf8_casefold (angle1_str, -1),
01298                            g_utf8_casefold (_("*unchanged*"), -1))
01299     ? atoi (angle1_str) : -1;
01300   pitch1 = g_utf8_collate (g_utf8_casefold (pitch1_str, -1),
01301                            g_utf8_casefold (_("*unchanged*"), -1))
01302     ? atoi (pitch1_str) : -1;
01303   angle2 = g_utf8_collate (g_utf8_casefold (angle2_str, -1),
01304                            g_utf8_casefold (_("*unchanged*"), -1))
01305     ? atoi (angle2_str) : -1;
01306   pitch2 = g_utf8_collate (g_utf8_casefold (pitch2_str, -1),
01307                            g_utf8_casefold(_("*unchanged*"), -1))
01308     ? atoi (pitch2_str) : -1;
01309 
01310   for (iter = selection; iter != NULL; iter = g_list_next(iter)) {
01311     object = (OBJECT *) iter->data;
01312     if (! o_get_fill_options(object, &otype, &owidth,
01313                              &opitch1, &oangle1, &opitch2, &oangle2))
01314       continue;
01315 
01316     otype = type == -1 ? otype : type;
01317     owidth = width == -1 ? owidth : width;
01318     opitch1 = pitch1 == -1 ? opitch1 : pitch1;
01319     oangle1 = angle1 == -1 ? oangle1 : angle1;
01320     opitch2 = pitch2 == -1 ? opitch2 : pitch2;
01321     oangle2 = angle2 == -1 ? oangle2 : angle2;
01322     
01323     /* set all not required options to -1 and 
01324        set nice parameters if not provided by the user */
01325     switch (otype) {
01326     case (FILLING_HOLLOW):
01327     case (FILLING_FILL):
01328       owidth = opitch1 = oangle1 = opitch2 = oangle2 = -1;
01329       break;
01330     case (FILLING_HATCH):
01331       if (owidth < 1) owidth = 1;
01332       if (opitch1 < 1) opitch1 = 100;
01333       opitch2 = oangle2 = -1;
01334       break;
01335     case (FILLING_MESH):
01336       if (owidth < 1) owidth = 1;
01337       if (opitch1 < 1) opitch1 = 100;
01338       if (opitch2 < 1) opitch2 = 100;
01339       break;
01340     default:
01341       g_assert_not_reached();
01342     }
01343     
01344     o_set_fill_options (toplevel, object, otype, owidth,
01345                         opitch1, oangle1, opitch2, oangle2);
01346   }
01347 
01348   toplevel->page_current->CHANGED = 1;
01349   o_undo_savestate(w_current, UNDO_ALL);
01350 }
01351 
01357 void fill_type_dialog_response(GtkWidget *widget, gint response,
01358                                struct fill_type_data *fill_type_data)
01359 {
01360   switch (response) {
01361   case GTK_RESPONSE_REJECT:
01362   case GTK_RESPONSE_DELETE_EVENT:
01363     /* void */
01364     break;
01365   case GTK_RESPONSE_ACCEPT:
01366     fill_type_dialog_ok(widget, fill_type_data);
01367     break;
01368   default:
01369     printf("line_type_dialog_response(): strange signal %d\n",response);
01370   }
01371 
01372   i_set_state (fill_type_data->w_current, SELECT);
01373   i_update_toolbar (fill_type_data->w_current);
01374 
01375   gtk_grab_remove (fill_type_data->dialog);
01376   gtk_widget_destroy (fill_type_data->dialog);
01377 
01378   g_free (fill_type_data);
01379 }
01380 
01386 void fill_type_dialog(GSCHEM_TOPLEVEL *w_current)
01387 {
01388   GtkWidget *dialog;
01389   GtkWidget *vbox;
01390   GtkWidget *optionmenu = NULL;
01391   GtkWidget *width_entry = NULL;
01392   GtkWidget *angle1_entry = NULL;
01393   GtkWidget *pitch1_entry = NULL;
01394   GtkWidget *angle2_entry = NULL;
01395   GtkWidget *pitch2_entry = NULL;
01396   GtkWidget *label;
01397   GtkWidget *table;
01398   struct fill_type_data *fill_type_data;
01399   GList *selection;
01400   OBJECT_FILLING type=FILLING_VOID;
01401   gint width=0, pitch1=0, angle1=0, pitch2=0, angle2=0;
01402 
01403   if (! o_select_selected(w_current))
01404     return;
01405 
01406   selection = 
01407     geda_list_get_glist(w_current->toplevel->page_current->selection_list);
01408 
01409   if (! selection_get_fill_type(selection, &type, &width,
01410                                 &pitch1, &angle1, &pitch2, &angle2))
01411     return;
01412 
01413   fill_type_data = (struct fill_type_data*) g_malloc (
01414     sizeof (struct fill_type_data));
01415 
01416   dialog = gschem_dialog_new_with_buttons(_("Edit Fill Type"),
01417                                           GTK_WINDOW(w_current->main_window),
01418                                           GTK_DIALOG_MODAL,
01419                                           "fill-type", w_current,
01420                                           GTK_STOCK_CANCEL,
01421                                           GTK_RESPONSE_REJECT,
01422                                           GTK_STOCK_OK,
01423                                           GTK_RESPONSE_ACCEPT,
01424                                           NULL);
01425 
01426   /* Set the alternative button order (ok, cancel, help) for other systems */
01427   gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
01428                                           GTK_RESPONSE_ACCEPT,
01429                                           GTK_RESPONSE_REJECT,
01430                                           -1);
01431 
01432   gtk_window_position(GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
01433 
01434   gtk_dialog_set_default_response(GTK_DIALOG(dialog),
01435                                   GTK_RESPONSE_ACCEPT);
01436 
01437   g_signal_connect (G_OBJECT (dialog), "response",
01438                     G_CALLBACK (fill_type_dialog_response),
01439                     fill_type_data);
01440 
01441   gtk_container_border_width(GTK_CONTAINER(dialog), DIALOG_BORDER_SPACING);
01442   vbox = GTK_DIALOG(dialog)->vbox;
01443   gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
01444 
01445   /*  Don't know whether to use the headline or not (Werner) */
01446   /*  label = gtk_label_new(_("Fill Properties:"));
01447       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01448       gtk_box_pack_start(GTK_BOX(vbox),label, FALSE, FALSE, 0);  */
01449 
01450   table = gtk_table_new (6, 2, FALSE);
01451   gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
01452   gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
01453   gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
01454 
01455   label = gtk_label_new (_("Fill Type:"));
01456   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01457   gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
01458 
01459   label = gtk_label_new (_("Line Width:"));
01460   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01461   gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
01462 
01463   label = gtk_label_new (_("Angle 1:"));
01464   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01465   gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
01466 
01467   label = gtk_label_new (_("Pitch 1:"));
01468   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01469   gtk_table_attach(GTK_TABLE(table), label, 0,1,3,4, GTK_FILL,0,0,0);
01470 
01471   label = gtk_label_new (_("Angle 2:"));
01472   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01473   gtk_table_attach(GTK_TABLE(table), label, 0,1,4,5, GTK_FILL,0,0,0);
01474 
01475   label = gtk_label_new (_("Pitch 2:"));
01476   gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01477   gtk_table_attach(GTK_TABLE(table), label, 0,1,5,6, GTK_FILL,0,0,0);
01478 
01479 
01480   optionmenu = gtk_option_menu_new ();
01481   gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu),
01482                            create_menu_filltype (w_current));
01483   gtk_table_attach_defaults(GTK_TABLE(table), optionmenu,
01484                             1,2,0,1);
01485 
01486   g_signal_connect (G_OBJECT (optionmenu), "changed",
01487                     G_CALLBACK (fill_type_dialog_filltype_change),
01488                     fill_type_data);
01489 
01490   width_entry = gtk_entry_new();
01491   gtk_entry_set_activates_default (GTK_ENTRY(width_entry), TRUE);
01492   gtk_table_attach_defaults(GTK_TABLE(table), width_entry,
01493                             1,2,1,2);
01494 
01495   angle1_entry = gtk_entry_new ();
01496   gtk_entry_set_activates_default (GTK_ENTRY(angle1_entry), TRUE);
01497   gtk_table_attach_defaults(GTK_TABLE(table), angle1_entry,
01498                             1,2,2,3);
01499 
01500   pitch1_entry = gtk_entry_new ();
01501   gtk_entry_set_activates_default (GTK_ENTRY(pitch1_entry), TRUE);
01502   gtk_table_attach_defaults(GTK_TABLE(table), pitch1_entry,
01503                             1,2,3,4);
01504 
01505   angle2_entry = gtk_entry_new ();
01506   gtk_entry_set_activates_default (GTK_ENTRY(angle2_entry), TRUE);
01507   gtk_table_attach_defaults(GTK_TABLE(table), angle2_entry,
01508                             1,2,4,5);
01509 
01510   pitch2_entry = gtk_entry_new ();
01511   gtk_entry_set_activates_default (GTK_ENTRY(pitch2_entry), TRUE);
01512   gtk_table_attach_defaults(GTK_TABLE(table), pitch2_entry,
01513                             1,2,5,6);
01514 
01515   /* populate the data structure */
01516   fill_type_data->dialog = dialog;
01517   fill_type_data->fill_type    = optionmenu;
01518   fill_type_data->width_entry  = width_entry;
01519   fill_type_data->angle1_entry = angle1_entry;
01520   fill_type_data->pitch1_entry = pitch1_entry;
01521   fill_type_data->angle2_entry = angle2_entry;
01522   fill_type_data->pitch2_entry = pitch2_entry;
01523 
01524   fill_type_data->w_current = w_current;
01525 
01526   /* fill in the fields of the dialog */
01527   fill_type_dialog_set_values(fill_type_data, type, width,
01528                               pitch1, angle1, pitch2, angle2);
01529 
01530   /* Set the widget activity according to the current filltype */
01531   fill_type_dialog_filltype_change(optionmenu, fill_type_data);
01532 
01533   gtk_widget_grab_focus(width_entry);
01534   gtk_widget_show_all (dialog);
01535 }
01536 
01537 /***************** End of Fill Type dialog box ***********************/
01538 
01539 /***************** Start of Arc dialog box ***************************/
01540 
01547 void arc_angle_dialog_response(GtkWidget *w, gint response,
01548                                GSCHEM_TOPLEVEL *w_current)
01549 {
01550   GtkWidget *spinentry;
01551   gint radius, start_angle, sweep_angle;
01552   OBJECT *arc_object = NULL;
01553 
01554   switch (response) {
01555   case GTK_RESPONSE_REJECT:
01556   case GTK_RESPONSE_DELETE_EVENT:
01557     /* void */
01558     break;
01559   case GTK_RESPONSE_ACCEPT:
01560     spinentry = g_object_get_data(G_OBJECT(w_current->aawindow),"radius");
01561     radius = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinentry));
01562     spinentry = g_object_get_data(G_OBJECT(w_current->aawindow),"spin_start");
01563     start_angle = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinentry));
01564     spinentry = g_object_get_data(G_OBJECT(w_current->aawindow),"spin_sweep");
01565     sweep_angle = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinentry));
01566     arc_object = (OBJECT*) g_object_get_data(G_OBJECT(w_current->aawindow),"arc_object");
01567 
01568     if (arc_object != NULL) {
01569       o_arc_modify(w_current->toplevel, arc_object, radius, 0, ARC_RADIUS);
01570       o_arc_modify(w_current->toplevel, arc_object, start_angle, 0, ARC_START_ANGLE);
01571       o_arc_modify(w_current->toplevel, arc_object, sweep_angle, 0, ARC_END_ANGLE);
01572     } else {
01573       o_arc_end4(w_current, radius, start_angle, sweep_angle);
01574     }
01575     break;
01576   default:
01577     printf("arc_angle_dialog_response(): strange signal %d\n",response);
01578   }
01579 
01580   gtk_widget_destroy(w_current->aawindow);
01581   w_current->aawindow = NULL;
01582 }
01583 
01594 void arc_angle_dialog (GSCHEM_TOPLEVEL *w_current, OBJECT *arc_object)
01595 {
01596   GtkWidget *label = NULL;
01597   GtkWidget *vbox;
01598   GtkWidget *alignment, *table;
01599   GtkWidget *radius, *spin_start, *spin_sweep;
01600 
01601   if (!w_current->aawindow) {
01602     w_current->aawindow = gschem_dialog_new_with_buttons(_("Arc Params"),
01603                                                          GTK_WINDOW(w_current->main_window),
01604                                                          GTK_DIALOG_MODAL,
01605                                                          "arc-angle", w_current,
01606                                                          GTK_STOCK_CANCEL,
01607                                                          GTK_RESPONSE_REJECT,
01608                                                          GTK_STOCK_OK,
01609                                                          GTK_RESPONSE_ACCEPT,
01610                                                          NULL);
01611 
01612   /* Set the alternative button order (ok, cancel, help) for other systems */
01613     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->aawindow),
01614                                             GTK_RESPONSE_ACCEPT,
01615                                             GTK_RESPONSE_REJECT,
01616                                             -1);
01617 
01618     gtk_window_position(GTK_WINDOW(w_current->aawindow),
01619                         GTK_WIN_POS_MOUSE);
01620 
01621     g_signal_connect (G_OBJECT (w_current->aawindow), "response",
01622                       G_CALLBACK (arc_angle_dialog_response),
01623                       w_current);
01624 
01625     gtk_dialog_set_default_response(GTK_DIALOG(w_current->aawindow),
01626                                     GTK_RESPONSE_ACCEPT);
01627 
01628     gtk_container_border_width(GTK_CONTAINER(w_current->aawindow), DIALOG_BORDER_SPACING);
01629     vbox = GTK_DIALOG(w_current->aawindow)->vbox;
01630     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
01631 
01632 
01633     alignment = gtk_alignment_new(0,0,1,1);
01634     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
01635                               0 /*DIALOG_INDENTATION */, 0);
01636     gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
01637 
01638     table = gtk_table_new (2, 3, FALSE);
01639     gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
01640     gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
01641     gtk_container_add(GTK_CONTAINER(alignment), table);
01642 
01643     label = gtk_label_new (_("Arc Radius:"));
01644     gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01645     gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
01646 
01647     radius = gtk_spin_button_new_with_range(1, 100000, 100);
01648     gtk_entry_set_activates_default(GTK_ENTRY(radius), TRUE);
01649     gtk_table_attach_defaults(GTK_TABLE(table), radius, 1,2,0,1);
01650 
01651     label = gtk_label_new (_("Start Angle:"));
01652     gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01653     gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
01654 
01655     spin_start = gtk_spin_button_new_with_range(-360,360,1);
01656     gtk_entry_set_activates_default(GTK_ENTRY(spin_start), TRUE);
01657     gtk_table_attach_defaults(GTK_TABLE(table), spin_start, 1,2,1,2);
01658 
01659     label = gtk_label_new(_("Degrees of Sweep:"));
01660     gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
01661     gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
01662 
01663     spin_sweep = gtk_spin_button_new_with_range(-360,360,1);
01664     gtk_entry_set_activates_default(GTK_ENTRY(spin_sweep), TRUE);
01665     gtk_table_attach_defaults(GTK_TABLE(table), spin_sweep, 1,2,2,3);
01666 
01667     GLADE_HOOKUP_OBJECT(w_current->aawindow, radius, "radius");
01668     GLADE_HOOKUP_OBJECT(w_current->aawindow, spin_start,"spin_start");
01669     GLADE_HOOKUP_OBJECT(w_current->aawindow, spin_sweep,"spin_sweep");
01670     g_object_set_data(G_OBJECT(w_current->aawindow), "arc_object", arc_object);
01671     gtk_widget_show_all (w_current->aawindow);
01672   }
01673 
01674   else {  /* dialog already created */
01675     gtk_window_present (GTK_WINDOW(w_current->aawindow));
01676     radius = g_object_get_data(G_OBJECT(w_current->aawindow),"radius");
01677     spin_start = g_object_get_data(G_OBJECT(w_current->aawindow),"spin_start");
01678     spin_sweep = g_object_get_data(G_OBJECT(w_current->aawindow),"spin_sweep");
01679   }
01680 
01681   if (arc_object == NULL) {
01682     gtk_spin_button_set_value(GTK_SPIN_BUTTON(radius), w_current->distance);
01683     gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_start),0);
01684     gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sweep), 90);
01685   } else {
01686     gtk_spin_button_set_value(GTK_SPIN_BUTTON(radius), 
01687                   arc_object->arc->width / 2);
01688     gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_start),
01689                   arc_object->arc->start_angle);
01690     gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sweep),
01691                   arc_object->arc->end_angle);
01692   }
01693 
01694   gtk_widget_grab_focus(radius);
01695 }
01696 
01697 /***************** End of Arc dialog box *****************************/
01698 
01699 /***************** Start of Translate dialog box *********************/
01700 
01706 void translate_dialog_response(GtkWidget *widget, gint response,
01707                                GSCHEM_TOPLEVEL *w_current)
01708 {
01709   GtkWidget *textentry;
01710   gchar *string;
01711 
01712   switch (response) {
01713   case GTK_RESPONSE_REJECT:
01714   case GTK_RESPONSE_DELETE_EVENT:
01715     /* void */
01716     break;
01717   case GTK_RESPONSE_ACCEPT:
01718     textentry = g_object_get_data(G_OBJECT(w_current->trwindow),"textentry");
01719     string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
01720     if (strlen(string) != 0) {
01721       o_complex_translate_all(w_current, atoi(string));
01722     }
01723     break;
01724   default:
01725     printf("translate_edit_dialog_response(): strange signal %d\n",response);
01726   }
01727 
01728   i_set_state(w_current, SELECT);
01729   i_update_toolbar(w_current);
01730   gtk_widget_destroy(w_current->trwindow);
01731   w_current->trwindow=NULL;
01732 }
01733 
01734 
01739 void translate_dialog (GSCHEM_TOPLEVEL *w_current)
01740 {
01741   GtkWidget *label;
01742   GtkWidget *textentry;
01743   GtkWidget *vbox;
01744 
01745   if (!w_current->trwindow) {
01746     w_current->trwindow = gschem_dialog_new_with_buttons(_("Translate"),
01747                                                          GTK_WINDOW(w_current->main_window),
01748                                                          GTK_DIALOG_MODAL,
01749                                                          "translate", w_current,
01750                                                          GTK_STOCK_CANCEL,
01751                                                          GTK_RESPONSE_REJECT,
01752                                                          GTK_STOCK_OK,
01753                                                          GTK_RESPONSE_ACCEPT,
01754                                                          NULL);
01755 
01756   /* Set the alternative button order (ok, cancel, help) for other systems */
01757     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->trwindow),
01758                                             GTK_RESPONSE_ACCEPT,
01759                                             GTK_RESPONSE_REJECT,
01760                                             -1);
01761 
01762     gtk_window_position(GTK_WINDOW (w_current->trwindow),
01763                         GTK_WIN_POS_MOUSE);
01764 
01765     g_signal_connect (G_OBJECT (w_current->trwindow), "response",
01766                       G_CALLBACK (translate_dialog_response),
01767                       w_current);
01768 
01769     gtk_dialog_set_default_response(GTK_DIALOG(w_current->trwindow),
01770                                     GTK_RESPONSE_ACCEPT);
01771 
01772     gtk_container_border_width(GTK_CONTAINER(w_current->trwindow),
01773                                DIALOG_BORDER_SPACING);
01774     vbox = GTK_DIALOG(w_current->trwindow)->vbox;
01775     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
01776 
01777     label = gtk_label_new(_("Offset to translate?\n(0 for origin)"));
01778     gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
01779     gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
01780 
01781     textentry = gtk_entry_new_with_max_length (10);
01782     gtk_entry_set_text(GTK_ENTRY(textentry), "0");
01783     gtk_editable_select_region(GTK_EDITABLE(textentry), 0, -1);
01784     gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
01785     gtk_box_pack_start(GTK_BOX(vbox),textentry, FALSE, FALSE, 0);
01786 
01787     GLADE_HOOKUP_OBJECT(w_current->trwindow, textentry, "textentry");
01788     gtk_widget_show_all (w_current->trwindow);
01789   }
01790 
01791   else  { /* dialog already created */
01792     gtk_window_present(GTK_WINDOW(w_current->trwindow));
01793   }
01794 }
01795 
01796 /***************** End of Translate dialog box ***********************/
01797 
01798 /***************** Start of Text size dialog box *********************/
01799 
01804 void text_size_dialog_response(GtkWidget *w, gint response,
01805                                GSCHEM_TOPLEVEL *w_current)
01806 {
01807   GtkWidget *spin_size;
01808   gint size;
01809 
01810   switch (response) {
01811   case GTK_RESPONSE_ACCEPT:
01812     spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
01813     size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_size));
01814 
01815     w_current->text_size = size;
01816     w_current->toplevel->page_current->CHANGED=1;
01817     o_undo_savestate(w_current, UNDO_ALL);
01818     break;
01819   case GTK_RESPONSE_REJECT:
01820   case GTK_RESPONSE_DELETE_EVENT:
01821     /* void */
01822     break;
01823   default:
01824     printf("text_size_dialog_response(): strange signal %d\n",response);
01825   }
01826 
01827   /* clean up */
01828   i_set_state(w_current, SELECT);
01829   i_update_toolbar(w_current);
01830   gtk_widget_destroy(w_current->tswindow);
01831   w_current->tswindow = NULL;
01832 }
01833 
01838 void text_size_dialog (GSCHEM_TOPLEVEL *w_current)
01839 {
01840   GtkWidget *label = NULL;
01841   GtkWidget *vbox;
01842   GtkWidget *spin_size;
01843 
01844   if (!w_current->tswindow) {
01845     w_current->tswindow = gschem_dialog_new_with_buttons(_("Text Size"),
01846                                                          GTK_WINDOW(w_current->main_window),
01847                                                          GTK_DIALOG_MODAL,
01848                                                          "text-size", w_current,
01849                                                          GTK_STOCK_CANCEL,
01850                                                          GTK_RESPONSE_REJECT,
01851                                                          GTK_STOCK_OK,
01852                                                          GTK_RESPONSE_ACCEPT,
01853                                                          NULL);
01854 
01855   /* Set the alternative button order (ok, cancel, help) for other systems */
01856     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tswindow),
01857                                             GTK_RESPONSE_ACCEPT,
01858                                             GTK_RESPONSE_REJECT,
01859                                             -1);
01860 
01861     gtk_window_position(GTK_WINDOW(w_current->tswindow),
01862                         GTK_WIN_POS_MOUSE);
01863 
01864     g_signal_connect (G_OBJECT (w_current->tswindow), "response",
01865                       G_CALLBACK (text_size_dialog_response),
01866                       w_current);
01867     gtk_dialog_set_default_response(GTK_DIALOG(w_current->tswindow),
01868                                     GTK_RESPONSE_ACCEPT);
01869 
01870     gtk_container_border_width(GTK_CONTAINER(w_current->tswindow),
01871                                DIALOG_BORDER_SPACING);
01872     vbox = GTK_DIALOG(w_current->tswindow)->vbox;
01873     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
01874 
01875     label = gtk_label_new (_("Enter new text size:"));
01876     gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
01877     gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
01878 
01879     spin_size = gtk_spin_button_new_with_range(2,10000,2);
01880     gtk_editable_select_region( GTK_EDITABLE(spin_size), 0, -1);
01881     gtk_box_pack_start(GTK_BOX(vbox), spin_size, FALSE, FALSE, 0);
01882     gtk_entry_set_activates_default(GTK_ENTRY(spin_size), TRUE);
01883     gtk_widget_grab_focus(spin_size);
01884 
01885     GLADE_HOOKUP_OBJECT(w_current->tswindow, spin_size, "spin_size");
01886     gtk_widget_show_all(w_current->tswindow);
01887   }
01888 
01889   else { /* dialog already created */
01890     gtk_window_present(GTK_WINDOW(w_current->tswindow));
01891   }
01892 
01893   /* always set the current text size to the dialog */
01894   spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
01895   gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_size), w_current->text_size);
01896   gtk_editable_select_region(GTK_EDITABLE(spin_size), 0, -1);
01897 }
01898 
01899 /***************** End of Text size dialog box ***********************/
01900 
01901 /***************** Start of Snap size dialog box *********************/
01902 
01908 void snap_size_dialog_response(GtkWidget *w, gint response,
01909                                GSCHEM_TOPLEVEL *w_current)
01910 {
01911   GtkWidget *spin_size;
01912   gint size;
01913 
01914   switch (response) {
01915   case GTK_RESPONSE_ACCEPT:
01916     spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
01917     size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_size));
01918 
01919     w_current->snap_size = size;
01920     i_update_grid_info (w_current);
01921     o_invalidate_all (w_current);
01922     w_current->toplevel->page_current->CHANGED=1;  /* maybe remove those two lines */
01923     o_undo_savestate(w_current, UNDO_ALL);
01924     break;
01925   case GTK_RESPONSE_REJECT:
01926   case GTK_RESPONSE_DELETE_EVENT:
01927     /* void */
01928     break;
01929   default:
01930     printf("snap_size_dialog_response(): strange signal %d\n",response);
01931   }
01932 
01933   /* clean up */
01934   i_set_state(w_current, SELECT);
01935   i_update_toolbar(w_current);
01936   gtk_widget_destroy(w_current->tswindow);
01937   w_current->tswindow = NULL;
01938 }
01939 
01944 void snap_size_dialog (GSCHEM_TOPLEVEL *w_current)
01945 {
01946   GtkWidget *label = NULL;
01947   GtkWidget *vbox;
01948   GtkWidget *spin_size;
01949 
01950   if (!w_current->tswindow) {
01951     w_current->tswindow = gschem_dialog_new_with_buttons(_("Snap Size"),
01952                                                          GTK_WINDOW(w_current->main_window),
01953                                                          GTK_DIALOG_MODAL,
01954                                                          "snap-size", w_current,
01955                                                          GTK_STOCK_CANCEL,
01956                                                          GTK_RESPONSE_REJECT,
01957                                                          GTK_STOCK_OK,
01958                                                          GTK_RESPONSE_ACCEPT,
01959                                                          NULL);
01960 
01961   /* Set the alternative button order (ok, cancel, help) for other systems */
01962     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tswindow),
01963                                             GTK_RESPONSE_ACCEPT,
01964                                             GTK_RESPONSE_REJECT,
01965                                             -1);
01966 
01967     gtk_window_position(GTK_WINDOW(w_current->tswindow),
01968                         GTK_WIN_POS_MOUSE);
01969 
01970     g_signal_connect (G_OBJECT (w_current->tswindow), "response",
01971                       G_CALLBACK (snap_size_dialog_response),
01972                       w_current);
01973     gtk_dialog_set_default_response(GTK_DIALOG(w_current->tswindow),
01974                                     GTK_RESPONSE_ACCEPT);
01975 
01976     gtk_container_border_width(GTK_CONTAINER(w_current->tswindow),
01977                                DIALOG_BORDER_SPACING);
01978     vbox = GTK_DIALOG(w_current->tswindow)->vbox;
01979     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
01980 
01981     label = gtk_label_new (_("Enter new snap grid spacing:"));
01982     gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
01983     gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
01984 
01985     spin_size = gtk_spin_button_new_with_range(0,100000,5);
01986     gtk_editable_select_region( GTK_EDITABLE(spin_size), 0, -1);
01987     gtk_box_pack_start(GTK_BOX(vbox), spin_size, FALSE, FALSE, 0);
01988     gtk_entry_set_activates_default(GTK_ENTRY(spin_size), TRUE);
01989     gtk_widget_grab_focus(spin_size);
01990 
01991     GLADE_HOOKUP_OBJECT(w_current->tswindow, spin_size, "spin_size");
01992     gtk_widget_show_all(w_current->tswindow);
01993   }
01994 
01995   else {  /* dialog already there */
01996     gtk_window_present(GTK_WINDOW(w_current->tswindow));
01997   }
01998 
01999   /* always set the current gschem value to the dialog entry */
02000   spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
02001   gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_size), w_current->snap_size);
02002   gtk_editable_select_region(GTK_EDITABLE(spin_size), 0, -1);
02003 }
02004 
02005 /***************** End of Snap size dialog box ***********************/
02006 
02007 /***************** Start of slot edit dialog box *********************/
02008 
02014 void slot_edit_dialog_response(GtkWidget *widget, gint response, GSCHEM_TOPLEVEL *w_current)
02015 {
02016   GtkWidget *textentry;
02017   char *slot_string;
02018   int len;
02019   gchar *string = NULL;
02020 
02021   switch (response) {
02022   case GTK_RESPONSE_REJECT:
02023   case GTK_RESPONSE_DELETE_EVENT:
02024     /* void */
02025     break;
02026   case GTK_RESPONSE_ACCEPT:
02027     textentry = g_object_get_data(G_OBJECT(w_current->sewindow),"textentry");
02028     string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
02029     len = strlen(string);
02030     if (len != 0) {
02031       slot_string = g_strdup_printf ("slot=%s", string);
02032       o_slot_end (w_current, o_select_return_first_object (w_current),
02033                   slot_string);
02034       g_free (slot_string);
02035     }
02036     break;
02037   default:
02038     printf("slot_edit_dialog_response(): strange signal %d\n",response);
02039   }
02040   i_set_state(w_current, SELECT);
02041   i_update_toolbar(w_current);
02042   gtk_widget_destroy(w_current->sewindow);
02043   w_current->sewindow = NULL;
02044 }
02045 
02046 
02051 void slot_edit_dialog (GSCHEM_TOPLEVEL *w_current, const char *string)
02052 {
02053   GtkWidget *label = NULL;
02054   GtkWidget *textentry;
02055   GtkWidget *vbox;
02056 
02057   if (!w_current->sewindow) {
02058     w_current->sewindow = gschem_dialog_new_with_buttons(_("Edit slot number"),
02059                                                          GTK_WINDOW(w_current->main_window),
02060                                                          GTK_DIALOG_MODAL,
02061                                                          "slot-edit", w_current,
02062                                                          GTK_STOCK_CANCEL,
02063                                                          GTK_RESPONSE_REJECT,
02064                                                          GTK_STOCK_OK,
02065                                                          GTK_RESPONSE_ACCEPT,
02066                                                          NULL);
02067 
02068   /* Set the alternative button order (ok, cancel, help) for other systems */
02069     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->sewindow),
02070                                             GTK_RESPONSE_ACCEPT,
02071                                             GTK_RESPONSE_REJECT,
02072                                             -1);
02073 
02074     gtk_window_position(GTK_WINDOW(w_current->sewindow),
02075                         GTK_WIN_POS_MOUSE);
02076 
02077     gtk_dialog_set_default_response (GTK_DIALOG (w_current->sewindow),
02078                                      GTK_RESPONSE_ACCEPT);
02079 
02080     g_signal_connect (G_OBJECT (w_current->sewindow), "response",
02081                       G_CALLBACK (slot_edit_dialog_response),
02082                       w_current);
02083 
02084     gtk_container_border_width(GTK_CONTAINER(w_current->sewindow),
02085                                DIALOG_BORDER_SPACING);
02086     vbox = GTK_DIALOG(w_current->sewindow)->vbox;
02087     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
02088 
02089     label = gtk_label_new (_("Edit slot number:"));
02090     gtk_misc_set_alignment(GTK_MISC(label),0,0);
02091     gtk_box_pack_start(GTK_BOX (vbox), label, FALSE, FALSE, 0);
02092 
02093     textentry = gtk_entry_new();
02094     gtk_box_pack_start( GTK_BOX(vbox),
02095                        textentry, FALSE, FALSE, 0);
02096     gtk_entry_set_max_length(GTK_ENTRY(textentry), 80);
02097     gtk_entry_set_activates_default (GTK_ENTRY(textentry),TRUE);
02098 
02099     GLADE_HOOKUP_OBJECT(w_current->sewindow, textentry, "textentry");
02100     gtk_widget_show_all (w_current->sewindow);
02101   }
02102 
02103   else { /* dialog already created */
02104     gtk_window_present (GTK_WINDOW(w_current->sewindow));
02105   }
02106 
02107   /* always set the current text and select the number of the slot */
02108   if (string != NULL) {
02109     textentry = g_object_get_data(G_OBJECT(w_current->sewindow),"textentry");
02110     gtk_entry_set_text(GTK_ENTRY(textentry), string);
02111     gtk_editable_select_region (GTK_EDITABLE(textentry), 0, -1);
02112   }
02113 }
02114 
02115 /***************** End of Slot Edit dialog box ***********************/
02116 
02117 /***************** Start of help/about dialog box ********************/
02118 
02123 void about_dialog (GSCHEM_TOPLEVEL *w_current)
02124 {
02125   char *version_string;
02126   char *logo_file;
02127   GdkPixbuf *logo;
02128   GError *error = NULL;
02129 
02130   version_string = g_strdup_printf (_("%s (g%.7s)"),
02131                                     PACKAGE_DOTTED_VERSION,
02132                                     PACKAGE_GIT_COMMIT);
02133 
02134   logo_file = g_strconcat (w_current->toplevel->bitmap_directory,
02135                            G_DIR_SEPARATOR_S, "gschem-about-logo.png", NULL);
02136 
02137   logo = gdk_pixbuf_new_from_file (logo_file, &error);
02138   g_free (logo_file);
02139 
02140   if (error != NULL) {
02141     g_assert (logo == NULL);
02142     s_log_message ("Could not load image at file: %s\n%s\n",
02143                    logo_file, error->message);
02144     g_error_free (error);
02145   }
02146 
02147   gtk_show_about_dialog (
02148       GTK_WINDOW (w_current->main_window),
02149       "version",        version_string,
02150       "logo",           logo,
02151       "title",          _("About gschem"),
02152       "comments",       _("gEDA: GPL Electronic Design Automation"),
02153       "copyright",
02154       /* TRANSLATORS: "ChangeLog" is a literal filename; please don't translate it. */
02155       _("Copyright © 1998-2012 Ales Hvezda"
02156         " <ahvezda@geda.seul.org>\n"
02157         "Copyright © 1998-2012 gEDA Contributors"
02158         " (see ChangeLog for details)"),
02159       "website",        "http://www.gpleda.org/",
02160       NULL);
02161 
02162   g_free (version_string);
02163   g_object_unref (logo);
02164 }
02165 
02166 /***************** End of help/about dialog box *********************/
02167 
02168 /***************** Start of coord dialog box ************************/
02173 void coord_dialog_response(GtkWidget *w, gint response, GSCHEM_TOPLEVEL *w_current)
02174 {
02175   gtk_widget_destroy(w_current->cowindow);
02176   w_current->cowindow = NULL;
02177   w_current->coord_world = NULL;
02178   w_current->coord_screen = NULL;
02179 }
02180 
02186 void coord_display_update(GSCHEM_TOPLEVEL *w_current, int x, int y)
02187 {
02188   char *string;
02189   int world_x, world_y;
02190 
02191   string = g_strdup_printf("(%d, %d)", x, y);
02192   gtk_label_set_text(GTK_LABEL(w_current->coord_screen), string );
02193   g_free(string);
02194 
02195   SCREENtoWORLD (w_current, x, y, &world_x, &world_y);
02196   world_x = snap_grid (w_current, world_x);
02197   world_y = snap_grid (w_current, world_y);
02198 
02199   string = g_strdup_printf("(%d, %d)", world_x, world_y);
02200   gtk_label_set_text(GTK_LABEL(w_current->coord_world), string );
02201   g_free(string);
02202 }
02203 
02208 void coord_dialog (GSCHEM_TOPLEVEL *w_current, int x, int y)
02209 {
02210   GtkWidget *frame;
02211   GtkWidget *vbox;
02212 
02213   if (!w_current->cowindow) {
02214     w_current->cowindow = gschem_dialog_new_with_buttons(_("Coords"),
02215                                                          GTK_WINDOW(w_current->main_window),
02216                                                          0, /* Not modal GTK_DIALOG_MODAL */
02217                                                          "coord", w_current,
02218                                                          GTK_STOCK_CLOSE,
02219                                                          GTK_RESPONSE_REJECT,
02220                                                          NULL);
02221 
02222     gtk_window_position (GTK_WINDOW (w_current->cowindow),
02223                          GTK_WIN_POS_NONE);
02224 
02225     g_signal_connect (G_OBJECT (w_current->cowindow), "response",
02226                       G_CALLBACK (coord_dialog_response),
02227                       w_current);
02228 
02229     gtk_container_border_width (GTK_CONTAINER(w_current->cowindow),
02230                                 DIALOG_BORDER_SPACING);
02231     vbox = GTK_DIALOG(w_current->cowindow)->vbox;
02232     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
02233 
02234 
02235     frame = gtk_frame_new (_("Screen"));
02236     w_current->coord_screen = gtk_label_new("(########, ########)");
02237     gtk_label_set_justify( GTK_LABEL(w_current->coord_screen), GTK_JUSTIFY_LEFT);
02238     gtk_misc_set_padding(GTK_MISC(w_current->coord_screen),
02239                          DIALOG_H_SPACING, DIALOG_V_SPACING);
02240     gtk_container_add(GTK_CONTAINER (frame),
02241                       w_current->coord_screen);
02242     gtk_box_pack_start(GTK_BOX (vbox), frame, FALSE, FALSE, 0);
02243 
02244     frame = gtk_frame_new (_("World"));
02245     w_current->coord_world = gtk_label_new ("(########, ########)");
02246     gtk_misc_set_padding(GTK_MISC(w_current->coord_world),
02247                          DIALOG_H_SPACING, DIALOG_V_SPACING);
02248     gtk_label_set_justify(GTK_LABEL(w_current->coord_world),
02249                           GTK_JUSTIFY_LEFT);
02250     gtk_container_add(GTK_CONTAINER (frame),
02251                       w_current->coord_world);
02252     gtk_box_pack_start(GTK_BOX (vbox), frame, FALSE, FALSE, 0);
02253 
02254     gtk_widget_show_all(w_current->cowindow);
02255   }
02256 
02257   else { /* window already creatad  */
02258     gtk_window_present(GTK_WINDOW(w_current->cowindow));
02259   }
02260 
02261   /* always update the coords when the dialog is requested */
02262   coord_display_update(w_current, x, y);
02263 }
02264 
02265 /***************** End of coord dialog box **************************/
02266 
02267 /***************** Start of color edit dialog box *******************/
02268 
02277 char *index2functionstring(int index)
02278 {
02279   char *string;
02280 
02281   switch(index) {
02282     case(BACKGROUND_COLOR):
02283       string = g_strdup (_("Background"));
02284       break;
02285     case(PIN_COLOR):
02286       string = g_strdup (_("Pin"));
02287       break;
02288     case(NET_ENDPOINT_COLOR):
02289       string = g_strdup (_("Net endpoint"));
02290       break;
02291     case(GRAPHIC_COLOR):
02292       string = g_strdup (_("Graphic"));
02293       break;
02294     case(NET_COLOR):
02295       string = g_strdup (_("Net"));
02296       break;
02297     case(ATTRIBUTE_COLOR):
02298       string = g_strdup (_("Attribute"));
02299       break;
02300     case(LOGIC_BUBBLE_COLOR):
02301       string = g_strdup (_("Logic bubble"));
02302       break;
02303     case(DOTS_GRID_COLOR):
02304       string = g_strdup (_("Grid point"));
02305       break;
02306     case(DETACHED_ATTRIBUTE_COLOR):
02307       string = g_strdup (_("Detached attribute"));
02308       break;
02309     case(TEXT_COLOR):
02310       string = g_strdup (_("Text"));
02311       break;
02312     case(BUS_COLOR):
02313       string = g_strdup (_("Bus"));
02314       break;
02315     case(SELECT_COLOR):
02316       string = g_strdup (_("Selection"));
02317       break;
02318     case(BOUNDINGBOX_COLOR):
02319       string = g_strdup (_("Bounding box"));
02320       break;
02321     case(ZOOM_BOX_COLOR):
02322       string = g_strdup (_("Zoom box"));
02323       break;
02324     case(STROKE_COLOR):
02325       string = g_strdup (_("Stroke"));
02326       break;
02327     case(LOCK_COLOR):
02328       string = g_strdup (_("Lock"));
02329       break;
02330     case(OUTPUT_BACKGROUND_COLOR):
02331       string = g_strdup (_("Output background"));
02332       break;
02333     case(JUNCTION_COLOR):
02334       string = g_strdup (_("Net junction"));
02335       break;
02336     case(MESH_GRID_MAJOR_COLOR):
02337       string = g_strdup (_("Mesh grid major"));
02338       break;
02339     case(MESH_GRID_MINOR_COLOR):
02340       string = g_strdup (_("Mesh grid minor"));
02341       break;
02342     default:
02343       string = g_strdup (_("Unknown"));
02344       break;
02345   }
02346   return(string);
02347 }
02348 
02360 static void
02361 color_menu_swatch_layout_data (GtkCellLayout *layout,
02362                                GtkCellRenderer *cell,
02363                                GtkTreeModel *model,
02364                                GtkTreeIter *iter,
02365                                gpointer data)
02366 {
02367   /* GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) data; */
02368   GValue v = {0, };
02369   gint idx;
02370 
02371   /* Get the index of the color on this row */
02372   gtk_tree_model_get_value (model, iter, 1, &v);
02373   idx = g_value_get_int (&v);
02374 
02375   /* Set the cell's background color */
02376   g_object_set (cell, "background-gdk", x_get_color (idx), NULL);
02377 }
02378 
02387 static void
02388 color_menu_change_selection (GtkWidget *widget,
02389                              gpointer data)
02390 {
02391   GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) data;
02392   GtkComboBox *cbox = GTK_COMBO_BOX (widget);
02393   gint idx;
02394   GtkTreeIter iter;
02395   GValue v = {0, };
02396 
02397   if (!gtk_combo_box_get_active_iter (cbox, &iter)) {
02398     return; /* No color selected */
02399   }
02400   gtk_tree_model_get_value (gtk_combo_box_get_model (cbox),
02401                             &iter, 1, &v);
02402   idx = g_value_get_int (&v);
02403 
02404   /* Stash the selected color in the GSCHEM_TOPLEVEL.
02405    * FIXME this is ugly. */
02406   w_current->edit_color = idx;
02407 }
02408 
02420 static GtkWidget *
02421 create_color_menu (GSCHEM_TOPLEVEL *w_current)
02422 {
02423   GtkListStore *store;
02424   GtkComboBox *cbox;
02425   GtkCellLayout *layout;
02426   GtkCellRenderer *text_cell;
02427   GtkCellRenderer *color_cell;
02428 
02429   gint i;
02430   gchar *str;
02431   OBJECT *obj;
02432   GtkTreeIter iter;
02433 
02434   obj = o_select_return_first_object (w_current);
02435   if (obj != NULL)
02436     w_current->edit_color = obj->color;
02437 
02438   /* The columns are: name of color, index of color. */
02439   store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
02440   cbox = GTK_COMBO_BOX (gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)));
02441   layout = GTK_CELL_LAYOUT (cbox); /* For convenience */
02442 
02443   /* Renders the color swatch. Since this won't contain text, set a
02444    * minimum width. */
02445   color_cell = GTK_CELL_RENDERER (gtk_cell_renderer_text_new());
02446   g_object_set (color_cell, "width", 25, NULL);
02447   gtk_cell_layout_pack_start (layout, color_cell, FALSE);
02448   gtk_cell_layout_set_cell_data_func (layout, color_cell,
02449                                       color_menu_swatch_layout_data,
02450                                       (gpointer) w_current,
02451                                       NULL);
02452 
02453   /* Renders the name of the color */
02454   text_cell = GTK_CELL_RENDERER (gtk_cell_renderer_text_new());
02455   g_object_set (text_cell, "xpad", 5, NULL);
02456   gtk_cell_layout_pack_start (layout, text_cell, TRUE);
02457   gtk_cell_layout_add_attribute (layout, text_cell, "text", 0);
02458 
02459   /* Populate the list */
02460   for (i = 0; i < MAX_COLORS; i++) {
02461     /* Skip 'invalid' colors. */
02462     if (!x_color_display_enabled(i)) continue;
02463 
02464     str = index2functionstring (i);
02465     gtk_list_store_append (store, &iter);
02466     gtk_list_store_set (store, &iter, 0, str, 1, i, -1);
02467     if (i == w_current->edit_color)
02468       gtk_combo_box_set_active_iter (cbox, &iter);
02469   }
02470 
02471   g_signal_connect (cbox,
02472                     "changed",
02473                     GTK_SIGNAL_FUNC (color_menu_change_selection),
02474                     w_current);
02475 
02476   return GTK_WIDGET (cbox);
02477 }
02478 
02483 void color_edit_dialog_apply(GtkWidget *w, GSCHEM_TOPLEVEL *w_current)
02484 {
02485   GList *s_current = NULL;
02486   OBJECT *object = NULL;
02487 
02488   s_current = geda_list_get_glist( w_current->toplevel->page_current->selection_list );
02489 
02490   while(s_current != NULL) {
02491 
02492     object = (OBJECT *) s_current->data;
02493     if (object == NULL) {
02494       fprintf(stderr, _("ERROR: NULL object in color_edit_dialog_apply!\n"));
02495       exit(-1);
02496     }
02497 
02498     o_set_color (w_current->toplevel, object, w_current->edit_color);
02499     w_current->toplevel->page_current->CHANGED = 1;
02500 
02501     s_current = g_list_next(s_current);
02502   }
02503   o_undo_savestate(w_current, UNDO_ALL);
02504 }
02505 
02510 void color_edit_dialog_response(GtkWidget *widget, gint response, GSCHEM_TOPLEVEL *w_current)
02511 {
02512   switch (response) {
02513   case GTK_RESPONSE_REJECT:
02514   case GTK_RESPONSE_DELETE_EVENT:
02515     gtk_widget_destroy(w_current->clwindow);
02516     w_current->clwindow = NULL;
02517     break;
02518   case GTK_RESPONSE_ACCEPT:
02519     color_edit_dialog_apply(widget, w_current);
02520     break;
02521   default:
02522     printf("ERROR: color_edit_dialog_response(): strange signal %d\n",response);
02523   }
02524 }
02525 
02526 
02531 void color_edit_dialog (GSCHEM_TOPLEVEL *w_current)
02532 {
02533   GtkWidget *optionmenu;
02534   GtkWidget *label;
02535   GtkWidget *vbox;
02536 
02537   if (!w_current->clwindow) {
02538     w_current->clwindow = gschem_dialog_new_with_buttons(_("Color Edit"),
02539                                                          GTK_WINDOW(w_current->main_window),
02540                                                          0, /* nonmodal dialog */
02541                                                          "color-edit", w_current,
02542                                                          GTK_STOCK_CLOSE,
02543                                                          GTK_RESPONSE_REJECT,
02544                                                          GTK_STOCK_APPLY,
02545                                                          GTK_RESPONSE_ACCEPT,
02546                                                          NULL);
02547 
02548   /* Set the alternative button order (ok, cancel, help) for other systems */
02549     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->clwindow),
02550                                             GTK_RESPONSE_ACCEPT,
02551                                             GTK_RESPONSE_REJECT,
02552                                             -1);
02553 
02554     gtk_window_position (GTK_WINDOW (w_current->clwindow),
02555                          GTK_WIN_POS_MOUSE);
02556 
02557     gtk_dialog_set_default_response (GTK_DIALOG (w_current->clwindow),
02558                                      GTK_RESPONSE_ACCEPT);
02559 
02560     g_signal_connect (G_OBJECT (w_current->clwindow), "response",
02561                       G_CALLBACK (color_edit_dialog_response),
02562                       w_current);
02563 
02564     gtk_container_border_width(GTK_CONTAINER(w_current->clwindow),
02565                                DIALOG_BORDER_SPACING);
02566     vbox = GTK_DIALOG(w_current->clwindow)->vbox;
02567     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
02568 
02569     label = gtk_label_new(_("Object color:"));
02570     gtk_misc_set_alignment(GTK_MISC(label),0,0);
02571     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
02572 
02573     optionmenu = create_color_menu (w_current);
02574     gtk_box_pack_start(GTK_BOX(vbox),
02575                        optionmenu, FALSE, FALSE, 0);
02576     gtk_widget_show_all(w_current->clwindow);
02577   }
02578 
02579   else { /* dialog already created */
02580     gtk_window_present(GTK_WINDOW(w_current->clwindow));
02581   }
02582 }
02583 
02584 /***************** End of color edit dialog box *********************/
02585 
02586 /***************** Start of help/keymapping dialog box **************/
02587 
02592 void x_dialog_hotkeys_response(GtkWidget *w, gint response,
02593                                GSCHEM_TOPLEVEL *w_current)
02594 {
02595   switch(response) {
02596   case GTK_RESPONSE_REJECT:
02597   case GTK_RESPONSE_DELETE_EVENT:
02598     /* void */
02599     break;
02600   default:
02601     printf("x_dialog_hotkeys_response(): strange signal %d\n", response);
02602   }
02603   /* clean up */
02604   gtk_widget_destroy(w_current->hkwindow);
02605   w_current->hkwindow = NULL;
02606 }
02607 
02613 void x_dialog_hotkeys (GSCHEM_TOPLEVEL *w_current)
02614 {
02615   GtkWidget *vbox, *scrolled_win;
02616   GtkListStore *store;
02617   GtkWidget *treeview;
02618   GtkCellRenderer *renderer;
02619   GtkTreeViewColumn *column;
02620 
02621   if (!w_current->hkwindow) {
02622     w_current->hkwindow = gschem_dialog_new_with_buttons(_("Hotkeys"),
02623                                                          GTK_WINDOW(w_current->main_window),
02624                                                          0, /* not modal */
02625                                                          "hotkeys", w_current,
02626                                                          GTK_STOCK_CLOSE,
02627                                                          GTK_RESPONSE_REJECT,
02628                                                          NULL);
02629 
02630     gtk_window_position (GTK_WINDOW (w_current->hkwindow),
02631                          GTK_WIN_POS_NONE);
02632 
02633     g_signal_connect (G_OBJECT (w_current->hkwindow), "response",
02634                       G_CALLBACK (x_dialog_hotkeys_response),
02635                       w_current);
02636 
02637     gtk_dialog_set_default_response(GTK_DIALOG(w_current->hkwindow),
02638                                     GTK_RESPONSE_ACCEPT);
02639 
02640     gtk_container_border_width (GTK_CONTAINER (w_current->hkwindow),
02641                                 DIALOG_BORDER_SPACING);
02642     gtk_widget_set_usize(w_current->hkwindow, 300,300);
02643 
02644     vbox = GTK_DIALOG(w_current->hkwindow)->vbox;
02645     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
02646 
02647     scrolled_win = gtk_scrolled_window_new (NULL, NULL);
02648     gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
02649     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
02650                                     GTK_POLICY_AUTOMATIC,
02651                                     GTK_POLICY_AUTOMATIC);
02652 
02653     /* the model */
02654     store = g_keys_to_list_store ();
02655 
02656     /* the tree view */
02657     treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
02658     gtk_container_add(GTK_CONTAINER(scrolled_win), treeview);
02659 
02660     /* the columns */
02661     renderer = gtk_cell_renderer_text_new ();
02662     column = gtk_tree_view_column_new_with_attributes (_("Function"),
02663                                                        renderer,
02664                                                        "text",
02665                                                        0,
02666                                                        NULL);
02667     gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
02668     renderer = gtk_cell_renderer_text_new ();
02669     column = gtk_tree_view_column_new_with_attributes (_("Keystroke(s)"),
02670                                                        renderer,
02671                                                        "text",
02672                                                        1,
02673                                                        NULL);
02674     gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
02675 
02676     /* show all recursively */
02677     gtk_widget_show_all(w_current->hkwindow);
02678   }
02679 
02680   else { /* dialog already created */
02681     gtk_window_present(GTK_WINDOW(w_current->hkwindow));
02682   }
02683 }
02684 
02685 /***************** End of help/keymapping dialog box ****************/
02686 
02687 /*********** Start of misc support functions for dialog boxes *******/
02688 extern GtkWidget *stwindow;
02689 
02695 void x_dialog_raise_all(GSCHEM_TOPLEVEL *w_current)
02696 {
02697   if(w_current->sowindow) {
02698     gdk_window_raise(w_current->sowindow->window);
02699   }
02700   if(w_current->cswindow) {
02701     gdk_window_raise(w_current->cswindow->window);
02702   }
02703   if(w_current->iwindow) {
02704     gdk_window_raise(w_current->iwindow->window);
02705   }
02706   if(w_current->tiwindow) {
02707     gdk_window_raise(w_current->tiwindow->window);
02708   }
02709   if(w_current->tewindow) {
02710     gdk_window_raise(w_current->tewindow->window);
02711   }
02712   if(w_current->sewindow) {
02713     gdk_window_raise(w_current->sewindow->window);
02714   }
02715   if(w_current->aawindow) {
02716     gdk_window_raise(w_current->aawindow->window);
02717   }
02718   if(w_current->mawindow) {
02719     gdk_window_raise(w_current->mawindow->window);
02720   }
02721   if(w_current->aewindow) {
02722     gdk_window_raise(w_current->aewindow->window);
02723   }
02724   if(w_current->trwindow) {
02725     gdk_window_raise(w_current->trwindow->window);
02726   }
02727   if(w_current->tswindow) {
02728     gdk_window_raise(w_current->tswindow->window);
02729   }
02730   if(w_current->hkwindow) {
02731     gdk_window_raise(w_current->hkwindow->window);
02732   }
02733   if(w_current->cowindow) {
02734     gdk_window_raise(w_current->cowindow->window);
02735   }
02736   if(w_current->clwindow) {
02737     gdk_window_raise(w_current->clwindow->window);
02738   }
02739 
02740 }
02741 
02742 /*********** End of misc support functions for dialog boxes *******/
02743 
02744 /***************** Start of generic message dialog box *******************/
02745 
02751 void generic_msg_dialog (const char *msg)
02752 {
02753   GtkWidget *dialog;
02754 
02755   dialog = gtk_message_dialog_new (NULL,
02756                                    GTK_DIALOG_MODAL |
02757                                      GTK_DIALOG_DESTROY_WITH_PARENT,
02758                                    GTK_MESSAGE_INFO,
02759                                    GTK_BUTTONS_OK,
02760                                    "%s", msg);
02761 
02762   gtk_dialog_run (GTK_DIALOG (dialog));
02763   gtk_widget_destroy (dialog);
02764 
02765 }
02766 
02767 /***************** End of generic message dialog box *********************/
02768 
02769 /***************** Start of generic confirm dialog box *******************/
02770 
02776 int generic_confirm_dialog (const char *msg)
02777 {
02778   GtkWidget *dialog;
02779   gint r;
02780 
02781   dialog = gtk_message_dialog_new (NULL,
02782                                    GTK_DIALOG_MODAL |
02783                                      GTK_DIALOG_DESTROY_WITH_PARENT,
02784                                    GTK_MESSAGE_INFO,
02785                                    GTK_BUTTONS_OK_CANCEL,
02786                                    "%s", msg);
02787 
02788   r = gtk_dialog_run (GTK_DIALOG (dialog));
02789   gtk_widget_destroy (dialog);
02790 
02791   if (r ==  GTK_RESPONSE_OK)
02792     return 1;
02793   else
02794     return 0;
02795 }
02796 
02797 /***************** End of generic confirm dialog box *********************/
02798 
02799 /***************** Start of generic file select dialog box ***************/
02807 char *generic_filesel_dialog (const char *msg, const char *templ, gint flags)
02808 {
02809   GtkWidget *dialog;
02810   gchar *result = NULL, *folder, *seed;
02811   char *title;
02812   static gchar *path = NULL;
02813   static gchar *shortcuts = NULL;
02814 
02815   /* Default to load if not specified.  Maybe this should cause an error. */
02816   if (! (flags & (FSB_LOAD | FSB_SAVE))) {
02817     flags = flags | FSB_LOAD;
02818   }
02819 
02820   if (flags & FSB_LOAD) {
02821     title = g_strdup_printf("%s: Open", msg);
02822     dialog = gtk_file_chooser_dialog_new (title,
02823                                           NULL,
02824                                           GTK_FILE_CHOOSER_ACTION_OPEN,
02825                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
02826                                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
02827                                           NULL);
02828     /* Since this is a load dialog box, the file must exist! */
02829     flags = flags | FSB_MUST_EXIST;
02830 
02831   } else {
02832     title = g_strdup_printf("%s: Save", msg);
02833     dialog = gtk_file_chooser_dialog_new (title,
02834                                           NULL,
02835                                           GTK_FILE_CHOOSER_ACTION_SAVE,
02836                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
02837                                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
02838                                           NULL);
02839   }
02840 
02841   /* Set the alternative button order (ok, cancel, help) for other systems */
02842   gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
02843                                           GTK_RESPONSE_OK,
02844                                           GTK_RESPONSE_CANCEL,
02845                                           -1);
02846 
02847   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
02848 
02849   /* Pick the current default folder to look for files in */
02850   if (path && *path) {
02851     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path);
02852   }
02853 
02854 
02855   /* Pick the current template (*.rc) or default file name */
02856   if (templ && *templ) {
02857     if (flags & FSB_SAVE)  {
02858       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), templ);
02859     } else {
02860       gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog), templ);
02861     }
02862   }
02863 
02864 
02865   if (shortcuts && *shortcuts) {
02866     printf ("shortcuts = \"%s\"\n", shortcuts);
02867     folder = g_strdup (shortcuts);
02868     seed = folder;
02869     while ((folder = strtok (seed, ":")) != NULL) {
02870       gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog),
02871                                             folder, NULL);
02872       seed = NULL;
02873     }
02874 
02875     g_free (folder);
02876   }
02877 
02878   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
02879     result = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
02880     folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
02887   }
02888   gtk_widget_destroy (dialog);
02889 
02890   g_free (title);
02891 
02892   return result;
02893 
02894 }
02895 
02896 /***************** End of generic file select dialog box *****************/
02897 
02898 /*********** Start of find text dialog box *******/
02899 
02900 int start_find;
02901 PAGE *remember_page;
02902 
02908 void find_text_dialog_response(GtkWidget *w, gint response,
02909                                GSCHEM_TOPLEVEL *w_current)
02910 {
02911   TOPLEVEL *toplevel = w_current->toplevel;
02912   GtkWidget *textentry;
02913   GtkWidget *checkdescend;
02914   gchar *string;
02915   gint done=0, close=0;
02916 
02917   switch (response) {
02918   case GTK_RESPONSE_ACCEPT:
02919     textentry = g_object_get_data(G_OBJECT(w_current->tfindwindow),"textentry");
02920     string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
02921     checkdescend = g_object_get_data(G_OBJECT(w_current->tfindwindow),"checkdescend");
02922 
02923     strncpy(generic_textstring, string, sizeof(generic_textstring)-1);
02924     generic_textstring[sizeof(generic_textstring)-1] = '\0';
02925 
02926     if (remember_page != toplevel->page_current) {
02927       s_page_goto(toplevel, remember_page);
02928     }
02929     done =
02930       o_edit_find_text (w_current, s_page_objects (remember_page), string,
02931                         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
02932                                                      (checkdescend)),
02933                         !start_find);
02934     if (done) {
02935       o_invalidate_all (w_current);
02936       close = 1;
02937     }
02938     start_find = 0;
02939     break;
02940   case GTK_RESPONSE_REJECT:
02941   case GTK_RESPONSE_DELETE_EVENT:
02942     close = 1;
02943     break;
02944   default:
02945     printf("find_text_dialog_response(): strange signal %d\n", response);
02946   }
02947   if (close) {
02948     gtk_widget_destroy(w_current->tfindwindow);
02949     w_current->tfindwindow = NULL;
02950   }
02951 }
02952 
02957 void find_text_dialog(GSCHEM_TOPLEVEL *w_current)
02958 {
02959   GtkWidget *label = NULL;
02960   GtkWidget *vbox;
02961   GtkWidget *checkdescend;
02962   GtkWidget *textentry;
02963   OBJECT *object = NULL;
02964 
02965   start_find = 1;
02966   remember_page = w_current->toplevel->page_current;
02967   if ((object = o_select_return_first_object(w_current)) != NULL) {
02968     if (object->type == OBJ_TEXT) {
02969       strncpy (generic_textstring,
02970                o_text_get_string (w_current->toplevel, object),
02971                sizeof(generic_textstring)-1);
02972       generic_textstring[sizeof(generic_textstring)-1] = '\0';
02973     }
02974   }
02975 
02976   if (!w_current->tfindwindow) {
02977     w_current->tfindwindow = gschem_dialog_new_with_buttons(_("Find Text"),
02978                                                             GTK_WINDOW(w_current->main_window),
02979                                                             0, /* not modal GTK_DIALOG_MODAL */
02980                                                             "find-text", w_current,
02981                                                             GTK_STOCK_CLOSE,
02982                                                             GTK_RESPONSE_REJECT,
02983                                                             GTK_STOCK_FIND,
02984                                                             GTK_RESPONSE_ACCEPT,
02985                                                             NULL);
02986 
02987   /* Set the alternative button order (ok, cancel, help) for other systems */
02988     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tfindwindow),
02989                                             GTK_RESPONSE_ACCEPT,
02990                                             GTK_RESPONSE_REJECT,
02991                                             -1);
02992 
02993     gtk_window_position(GTK_WINDOW(w_current->tfindwindow),
02994                         GTK_WIN_POS_MOUSE);
02995 
02996     g_signal_connect (G_OBJECT (w_current->tfindwindow), "response",
02997                       G_CALLBACK (find_text_dialog_response),
02998                       w_current);
02999 
03000     gtk_dialog_set_default_response(GTK_DIALOG(w_current->tfindwindow),
03001                                      GTK_RESPONSE_ACCEPT);
03002 
03003     gtk_container_border_width(GTK_CONTAINER(w_current->tfindwindow),
03004                                DIALOG_BORDER_SPACING);
03005     vbox = GTK_DIALOG(w_current->tfindwindow)->vbox;
03006     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
03007 
03008     label = gtk_label_new(_("Text to find:"));
03009     gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
03010     gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
03011 
03012     textentry = gtk_entry_new_with_max_length(20);
03013     gtk_editable_select_region(GTK_EDITABLE(textentry), 0, -1);
03014     gtk_box_pack_start(GTK_BOX(vbox), textentry, FALSE, FALSE, 0);
03015     gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
03016     gtk_widget_grab_focus(textentry);
03017 
03018     checkdescend = gtk_check_button_new_with_label(_("descend into hierarchy"));
03019     gtk_box_pack_start(GTK_BOX(vbox), checkdescend, TRUE, TRUE, 0);
03020 
03021     GLADE_HOOKUP_OBJECT(w_current->tfindwindow, textentry, "textentry");
03022     GLADE_HOOKUP_OBJECT(w_current->tfindwindow, checkdescend, "checkdescend");
03023 
03024     gtk_widget_show_all(w_current->tfindwindow);
03025   }
03026 
03027   else { /* dialog already created */
03028     gtk_window_present(GTK_WINDOW(w_current->tfindwindow));
03029   }
03030 
03031   /* always select the text string in the entry */
03032   textentry = g_object_get_data (G_OBJECT (w_current->tfindwindow), "textentry");
03033   gtk_entry_set_text(GTK_ENTRY(textentry), generic_textstring);
03034   gtk_entry_select_region(GTK_ENTRY(textentry), 0, -1);
03035 }
03036 
03037 /*********** End of find text dialog box *******/
03038 
03039 /*********** Start of hide text dialog box *******/
03040 
03046 void hide_text_dialog_response(GtkWidget *w, gint response,
03047                                GSCHEM_TOPLEVEL *w_current)
03048 {
03049   GtkWidget *textentry;
03050   gchar *string;
03051 
03052   switch (response) {
03053   case GTK_RESPONSE_ACCEPT:
03054     textentry = g_object_get_data(G_OBJECT(w_current->thidewindow),"textentry");
03055     string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
03056 
03057     strncpy(generic_textstring, string, sizeof(generic_textstring)-1);
03058     generic_textstring[sizeof(generic_textstring)-1] = '\0';
03059     o_edit_hide_specific_text (w_current,
03060                                s_page_objects (w_current->toplevel->page_current),
03061                                string);
03062     break;
03063   case GTK_RESPONSE_REJECT:
03064   case GTK_RESPONSE_DELETE_EVENT:
03065     gtk_widget_destroy(w_current->thidewindow);
03066     w_current->thidewindow = NULL;
03067     break;
03068   default:
03069     printf("show_text_dialog_response(): strange signal %d\n",response);
03070   }
03071 }
03072 
03077 void hide_text_dialog(GSCHEM_TOPLEVEL * w_current)
03078 {
03079   GtkWidget *label = NULL;
03080   GtkWidget *textentry;
03081   GtkWidget *vbox;
03082 
03083   if (!w_current->thidewindow) {
03084     w_current->thidewindow = gschem_dialog_new_with_buttons(_("Hide Text"),
03085                                                            GTK_WINDOW(w_current->main_window),
03086                                                            0, /* not modal GTK_DIALOG_MODAL, */
03087                                                            "hide-text", w_current,
03088                                                            GTK_STOCK_CLOSE,
03089                                                            GTK_RESPONSE_REJECT,
03090                                                            GTK_STOCK_APPLY,
03091                                                            GTK_RESPONSE_ACCEPT,
03092                                                            NULL);
03093 
03094   /* Set the alternative button order (ok, cancel, help) for other systems */
03095     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->thidewindow),
03096                                             GTK_RESPONSE_ACCEPT,
03097                                             GTK_RESPONSE_REJECT,
03098                                             -1);
03099 
03100     gtk_window_position(GTK_WINDOW(w_current->thidewindow),
03101                         GTK_WIN_POS_MOUSE);
03102 
03103     g_signal_connect (G_OBJECT (w_current->thidewindow), "response",
03104                       G_CALLBACK (hide_text_dialog_response),
03105                       w_current);
03106 
03107     gtk_dialog_set_default_response(GTK_DIALOG(w_current->thidewindow),
03108                                     GTK_RESPONSE_ACCEPT);
03109 
03110     gtk_container_border_width(GTK_CONTAINER(w_current->thidewindow),
03111                                DIALOG_BORDER_SPACING);
03112     vbox = GTK_DIALOG(w_current->thidewindow)->vbox;
03113     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
03114 
03115     label = gtk_label_new(_("Hide text starting with:"));
03116     gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
03117     gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
03118 
03119     textentry = gtk_entry_new_with_max_length(20);
03120     gtk_box_pack_start(GTK_BOX(vbox), textentry, FALSE, FALSE, 0);
03121     gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
03122     gtk_widget_grab_focus(textentry);
03123 
03124     GLADE_HOOKUP_OBJECT(w_current->thidewindow, textentry, "textentry");
03125     gtk_widget_show_all(w_current->thidewindow);
03126   }
03127 
03128   else { /* dialog already created, just select it */
03129     gtk_window_present(GTK_WINDOW(w_current->thidewindow));
03130   }
03131 
03132   /* always select the text in the search entry */
03133   textentry = g_object_get_data (G_OBJECT (w_current->thidewindow), "textentry");
03134   gtk_entry_set_text(GTK_ENTRY(textentry), generic_textstring);
03135   gtk_entry_select_region(GTK_ENTRY(textentry), 0, -1);
03136 }
03137 
03138 /*********** End of hide text dialog box *******/
03139 
03140 /*********** Start of show text dialog box *******/
03141 
03147 void show_text_dialog_response(GtkWidget *widget, gint response,
03148                                GSCHEM_TOPLEVEL *w_current)
03149 {
03150   GtkWidget *textentry;
03151   gchar *string;
03152 
03153   switch (response) {
03154   case GTK_RESPONSE_ACCEPT:
03155     textentry = g_object_get_data(G_OBJECT(w_current->tshowwindow),"textentry");
03156     string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
03157 
03158     strncpy(generic_textstring, string, sizeof(generic_textstring)-1);
03159     generic_textstring[sizeof(generic_textstring)-1] = '\0';
03160     o_edit_show_specific_text (w_current,
03161                                s_page_objects (w_current->toplevel->page_current),
03162                                string);
03163     break;
03164   case GTK_RESPONSE_REJECT:
03165   case GTK_RESPONSE_DELETE_EVENT:
03166     gtk_widget_destroy(w_current->tshowwindow);
03167     w_current->tshowwindow = NULL;
03168     break;
03169   default:
03170     printf("show_text_dialog_response(): strange signal %d\n",response);
03171   }
03172 }
03173 
03178 void show_text_dialog(GSCHEM_TOPLEVEL * w_current)
03179 {
03180   GtkWidget *label = NULL;
03181   GtkWidget *textentry;
03182   GtkWidget *vbox;
03183 
03184   if (!w_current->tshowwindow) {
03185     w_current->tshowwindow = gschem_dialog_new_with_buttons(_("Show Text"),
03186                                                             GTK_WINDOW(w_current->main_window),
03187                                                             0, /* not modal GTK_DIALOG_MODAL, */
03188                                                             "show-text", w_current,
03189                                                             GTK_STOCK_CLOSE,
03190                                                             GTK_RESPONSE_REJECT,
03191                                                             GTK_STOCK_APPLY,
03192                                                             GTK_RESPONSE_ACCEPT,
03193                                                             NULL);
03194 
03195   /* Set the alternative button order (ok, cancel, help) for other systems */
03196     gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tshowwindow),
03197                                             GTK_RESPONSE_ACCEPT,
03198                                             GTK_RESPONSE_REJECT,
03199                                             -1);
03200 
03201     gtk_window_position(GTK_WINDOW(w_current->tshowwindow),
03202                         GTK_WIN_POS_MOUSE);
03203 
03204     g_signal_connect (G_OBJECT (w_current->tshowwindow), "response",
03205                       G_CALLBACK (show_text_dialog_response),
03206                       w_current);
03207 
03208     gtk_dialog_set_default_response(GTK_DIALOG(w_current->tshowwindow),
03209                                     GTK_RESPONSE_ACCEPT);
03210 
03211     gtk_container_border_width(GTK_CONTAINER(w_current->tshowwindow),
03212                                DIALOG_BORDER_SPACING);
03213     vbox = GTK_DIALOG(w_current->tshowwindow)->vbox;
03214     gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
03215 
03216     label = gtk_label_new(_("Show text starting with:"));
03217     gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
03218     gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
03219 
03220     textentry = gtk_entry_new_with_max_length(20);
03221     gtk_box_pack_start(GTK_BOX(vbox), textentry, FALSE, FALSE, 0);
03222     gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
03223     gtk_widget_grab_focus(textentry);
03224 
03225     GLADE_HOOKUP_OBJECT(w_current->tshowwindow, textentry, "textentry");
03226     gtk_widget_show_all(w_current->tshowwindow);
03227   }
03228 
03229   else { /* dialog already created. Show it */
03230     gtk_window_present(GTK_WINDOW(w_current->tshowwindow));
03231   }
03232 
03233   /* always select the text in the entry */
03234   textentry = g_object_get_data (G_OBJECT (w_current->tshowwindow), "textentry");
03235   gtk_entry_set_text(GTK_ENTRY(textentry), generic_textstring);
03236   gtk_entry_select_region(GTK_ENTRY(textentry), 0, -1);
03237 }
03238 
03239 /*********** End of show text dialog box *******/
03240 
03241 /*********** Start of some Gtk utils  *******/
03242 
03247 void select_all_text_in_textview(GtkTextView *textview)
03248 {
03249   GtkTextBuffer *textbuffer;
03250   GtkTextIter start, end;
03251 
03252   textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
03253   gtk_text_buffer_get_bounds (textbuffer, &start, &end);
03254   gtk_text_buffer_select_range(textbuffer, &start, &end);
03255 }
03256 
03262 int text_view_calculate_real_tab_width(GtkTextView *textview, int tab_size)
03263 {
03264   PangoLayout *layout;
03265   gchar *tab_string;
03266   gint tab_width = 0;
03267 
03268   if (tab_size == 0)
03269   return -1;
03270 
03271   tab_string = g_strnfill (tab_size, ' ');
03272 
03273   layout = gtk_widget_create_pango_layout (
03274                                            GTK_WIDGET (textview),
03275                                            tab_string);
03276   g_free (tab_string);
03277 
03278   if (layout != NULL) {
03279     pango_layout_get_pixel_size (layout, &tab_width, NULL);
03280     g_object_unref (G_OBJECT (layout));
03281   } else
03282   tab_width = -1;
03283 
03284   return tab_width;
03285 
03286 }
03287 
03288 /*********** End of some Gtk utils *******/
03289 
03290 /*********** Start of major symbol changed dialog box *******/
03291 
03297 void major_changed_dialog(GSCHEM_TOPLEVEL* w_current)
03298 {
03299   GtkWidget* dialog;
03300   char* refdes_string = NULL;
03301   char* tmp;
03302 
03303   if (w_current->toplevel->major_changed_refdes) {
03304 
03305     GList* current = w_current->toplevel->major_changed_refdes;
03306     while (current)
03307     {
03308       char *value = (char*) current->data;
03309 
03310       if (!refdes_string)
03311       {
03312         refdes_string = g_strdup (value);
03313       } else {
03314         tmp = g_strconcat (refdes_string, "\n", value, NULL);
03315         g_free(refdes_string);
03316         refdes_string = tmp;
03317       }
03318 
03319       current = g_list_next(current);
03320     }
03321 
03322     tmp = g_strconcat (refdes_string,
03323                        "\n\nBe sure to verify each of these symbols!",
03324                        NULL);
03325     g_free(refdes_string);
03326     refdes_string = tmp;
03327 
03328     dialog = gtk_message_dialog_new ((GtkWindow*) w_current->main_window,
03329                                      GTK_DIALOG_DESTROY_WITH_PARENT,
03330                                      GTK_MESSAGE_ERROR,
03331                                      GTK_BUTTONS_CLOSE,
03332                         "Major symbol changes detected in refdes:\n\n%s\n",
03333                                      refdes_string);
03334 
03335     gtk_widget_show(dialog);
03336 
03337     g_signal_connect_swapped (dialog, "response",
03338                               G_CALLBACK (gtk_widget_destroy),
03339                               dialog);
03340 
03341     g_free(refdes_string);
03342   }
03343 }
03344 
03345 /*********** End of major symbol changed dialog box *******/
03346 
03347 /***************** Start of Close Confirmation dialog box ************/
03348 
03349 #define TYPE_CLOSE_CONFIRMATION_DIALOG            (close_confirmation_dialog_get_type ())
03350 #define CLOSE_CONFIRMATION_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialog))
03351 #define CLOSE_CONFIRMATION_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
03352 #define IS_CLOSE_CONFIRMATION_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG))
03353 #define IS_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG))
03354 #define CLOSE_CONFIRMATION_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
03355 
03356 
03357 typedef struct _CloseConfirmationDialog      CloseConfirmationDialog;
03358 typedef struct _CloseConfirmationDialogClass CloseConfirmationDialogClass;
03359 
03360 struct _CloseConfirmationDialog
03361 {
03362   GtkDialog parent;
03363 
03364   GtkListStore *store_unsaved_pages;
03365 };
03366 
03367 struct _CloseConfirmationDialogClass
03368 {
03369   GtkDialogClass parent_class;
03370 };
03371 
03372 
03373 enum {
03374   PROP_UNSAVED_PAGE=1,
03375   PROP_UNSAVED_PAGES,
03376   PROP_SELECTED_PAGES
03377 };
03378 
03379 enum {
03380   COLUMN_SAVE,
03381   COLUMN_PAGE,
03382   NUM_COLUMNS
03383 };
03384 
03385 
03386 static gpointer close_confirmation_dialog_parent_class = NULL;
03387 
03388 
03389 static void close_confirmation_dialog_class_init (CloseConfirmationDialogClass *klass);
03390 static void close_confirmation_dialog_init (CloseConfirmationDialog *self);
03391 static void close_confirmation_dialog_set_property (GObject      *object,
03392                                                     guint         property_id,
03393                                                     const GValue *value,
03394                                                     GParamSpec   *pspec);
03395 static void close_confirmation_dialog_get_property (GObject      *object,
03396                                                     guint         property_id,
03397                                                     GValue       *value,
03398                                                     GParamSpec   *pspec);
03399 static GObject* close_confirmation_dialog_constructor (GType type,
03400                                                        guint n_construct_properties,
03401                                                        GObjectConstructParam *construct_params);
03402 
03403 GList *close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog *dialog);
03404 
03405 
03406 
03407 GType
03408 close_confirmation_dialog_get_type ()
03409 {
03410   static GType close_confirmation_dialog_type = 0;
03411 
03412   if (!close_confirmation_dialog_type) {
03413     static const GTypeInfo close_confirmation_dialog_info = {
03414       sizeof(CloseConfirmationDialogClass),
03415       NULL, /* base_init */
03416       NULL, /* base_finalize */
03417       (GClassInitFunc) close_confirmation_dialog_class_init,
03418       NULL, /* class_finalize */
03419       NULL, /* class_data */
03420       sizeof(CloseConfirmationDialog),
03421       0,    /* n_preallocs */
03422       (GInstanceInitFunc) close_confirmation_dialog_init,
03423     };
03424 
03425     close_confirmation_dialog_type =
03426       g_type_register_static (GTK_TYPE_DIALOG,
03427                               "CloseConfirmationDialog",
03428                               &close_confirmation_dialog_info, 0);
03429   }
03430 
03431   return close_confirmation_dialog_type;
03432 }
03433 
03434 static void
03435 close_confirmation_dialog_class_init (CloseConfirmationDialogClass *klass)
03436 {
03437   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
03438 
03439   close_confirmation_dialog_parent_class = g_type_class_peek_parent (klass);
03440 
03441   gobject_class->constructor  = close_confirmation_dialog_constructor;
03442   gobject_class->set_property = close_confirmation_dialog_set_property;
03443   gobject_class->get_property = close_confirmation_dialog_get_property;
03444 
03445   g_object_class_install_property (
03446     gobject_class, PROP_UNSAVED_PAGE,
03447     g_param_spec_pointer ("unsaved-page",
03448                           "",
03449                           "",
03450                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
03451   g_object_class_install_property (
03452     gobject_class, PROP_UNSAVED_PAGES,
03453     g_param_spec_pointer ("unsaved-pages",
03454                           "",
03455                           "",
03456                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
03457   g_object_class_install_property (
03458     gobject_class, PROP_SELECTED_PAGES,
03459     g_param_spec_pointer ("selected-pages",
03460                           "",
03461                           "",
03462                           G_PARAM_READABLE));
03463 
03464 }
03465 
03466 static void
03467 close_confirmation_dialog_init (CloseConfirmationDialog *self)
03468 {
03469   /* create model for treeview and populate */
03470   self->store_unsaved_pages = gtk_list_store_new (NUM_COLUMNS,
03471                                                   G_TYPE_BOOLEAN,  /* save? */
03472                                                   G_TYPE_POINTER); /* page */
03473 
03474 }
03475 
03484 static gint
03485 count_pages (GtkTreeModel *model)
03486 {
03487   GtkTreeIter iter;
03488   gint n_pages;
03489 
03490   gtk_tree_model_get_iter_first (model, &iter);
03491   for (n_pages = 1;
03492        gtk_tree_model_iter_next (model, &iter);
03493        n_pages++);
03494 
03495   return n_pages;
03496 }
03497 
03513 static gchar*
03514 get_page_name (GtkTreeModel *model, GtkTreeIter *piter)
03515 {
03516   GtkTreeIter iter;
03517   PAGE *page;
03518 
03519   g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
03520 
03521   if (piter == NULL) {
03522     gtk_tree_model_get_iter_first (model, &iter);
03523   } else {
03524     iter = *piter;
03525   }
03526 
03527   gtk_tree_model_get (model, &iter,
03528                       COLUMN_PAGE, &page,
03529                       -1);
03530   g_assert (page != NULL && page->page_filename != NULL);
03531   return g_path_get_basename (page->page_filename);
03532 }
03533 
03546 static void
03547 close_confirmation_dialog_set_page_name (GtkTreeViewColumn *tree_column,
03548                                          GtkCellRenderer   *cell,
03549                                          GtkTreeModel      *tree_model,
03550                                          GtkTreeIter       *iter,
03551                                          gpointer           data)
03552 {
03553   gchar *page_name;
03554 
03555   page_name = get_page_name (tree_model, iter);
03556   g_object_set (cell,
03557                 "text", page_name,
03558                 NULL);
03559   g_free (page_name);
03560 
03561 }
03562 
03573 static void
03574 close_confirmation_dialog_callback_renderer_toggled (GtkCellRendererToggle *cell_renderer,
03575                                                      gchar                 *path,
03576                                                      gpointer               user_data)
03577 {
03578   CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (user_data);
03579   GtkTreeModel *model;
03580   GtkTreeIter iter;
03581   gboolean save;
03582 
03583   model = GTK_TREE_MODEL (dialog->store_unsaved_pages);
03584 
03585   if (!gtk_tree_model_get_iter_from_string (model, &iter, path)) {
03586     return;
03587   }
03588   gtk_tree_model_get (model, &iter,
03589                       COLUMN_SAVE, &save,
03590                       -1);
03591   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
03592                       COLUMN_SAVE, (save != TRUE),
03593                       -1);
03594 
03595 }
03596 
03607 static GtkWidget*
03608 close_confirmation_dialog_build_page_list (CloseConfirmationDialog *dialog)
03609 {
03610   GtkWidget *vbox, *scrolled_window, *treeview, *label;
03611   GtkCellRenderer *renderer;
03612   GtkTreeViewColumn *column;
03613   const gchar *text;
03614 
03615   /* place the treeview and its caption into their own box */
03616   vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
03617                                    /* GtkBox */
03618                                    "homogeneous", FALSE,
03619                                    "spacing",     8,
03620                                    NULL));
03621 
03622   /* the list of pages with changes */
03623   /*  - scrolled window as container for the treeview first */
03624   scrolled_window = GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
03625                                               /* GtkScrolledWindow */
03626                                               "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
03627                                               "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
03628                                               "shadow-type",       GTK_SHADOW_IN,
03629                                               NULL));
03630   /*  - then the treeview */
03631   /* create model for treeview and populate */
03632   treeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW,
03633                                        /* GtkTreeView */
03634                                        "enable-search",   FALSE,
03635                                        "headers-visible", FALSE,
03636                                        "model",           dialog->store_unsaved_pages,
03637                                        NULL));
03638   renderer = gtk_cell_renderer_toggle_new ();
03639   g_signal_connect (renderer, "toggled",
03640                     G_CALLBACK (
03641                       close_confirmation_dialog_callback_renderer_toggled),
03642                     dialog);
03643   column   = gtk_tree_view_column_new_with_attributes ("Save?",
03644                                                        renderer,
03645                                                        "active", COLUMN_SAVE,
03646                                                        NULL);
03647   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
03648 
03649   renderer = gtk_cell_renderer_text_new ();
03650   column = GTK_TREE_VIEW_COLUMN (
03651     g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
03652                   /* GtkTreeViewColumn */
03653                   "title", _("Name"),
03654                   NULL));
03655   gtk_tree_view_column_pack_start (column, renderer, TRUE);
03656   gtk_tree_view_column_set_cell_data_func (column, renderer,
03657                                            close_confirmation_dialog_set_page_name,
03658                                            NULL, NULL);
03659   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
03660 
03661   gtk_container_add (GTK_CONTAINER (scrolled_window), treeview);
03662 
03663   gtk_box_pack_end (GTK_BOX (vbox), scrolled_window,
03664                     TRUE, TRUE, 0);
03665 
03666   /* the caption label above the list of pages */
03667   label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
03668                                     /* GtkMisc */
03669                                     "xalign",          0.0,
03670                                     "yalign",          0.0,
03671                                     /* GtkLabel */
03672                                     "wrap",            TRUE,
03673                                     "mnemonic-widget", treeview,
03674                                     NULL));
03675   text = _("S_elect the schematics you want to save:");
03676   gtk_label_set_text_with_mnemonic (GTK_LABEL (label), text);
03677   gtk_label_set_mnemonic_widget (GTK_LABEL (label), treeview);
03678   gtk_box_pack_start (GTK_BOX (vbox), label,
03679                       FALSE, FALSE, 0);
03680 
03681   return vbox;
03682 }
03683 
03684 static GObject*
03685 close_confirmation_dialog_constructor (GType type,
03686                                        guint n_construct_properties,
03687                                        GObjectConstructParam *construct_params)
03688 {
03689   GObject *object;
03690   CloseConfirmationDialog *dialog;
03691   GtkWidget *hbox, *image, *vbox, *label;
03692   GtkTreeIter iter;
03693   gboolean ret, single_page;
03694   gchar *tmp, *str;
03695   const gchar *cstr;
03696 
03697   /* chain up to constructor of parent class */
03698   object =
03699     G_OBJECT_CLASS (close_confirmation_dialog_parent_class)->constructor (
03700       type,
03701       n_construct_properties,
03702       construct_params);
03703   dialog = CLOSE_CONFIRMATION_DIALOG (object);
03704 
03705   g_object_set (dialog,
03706                 /* GtkDialog */
03707                 "has-separator",     FALSE,
03708                 /* GtkWindow */
03709                 "resizable",         FALSE,
03710                 "skip-taskbar-hint", TRUE,
03711                 /* GtkContainer */
03712                 "border-width",      5,
03713                 NULL);
03714   g_object_set (GTK_DIALOG (dialog)->vbox,
03715                 /* GtkBox */
03716                 "spacing", 14,
03717                 NULL);
03718   g_object_set (GTK_DIALOG (dialog)->action_area,
03719                 /* GtkBox */
03720                 "spacing",      6,
03721                 /* GtkContainer */
03722                 "border-width", 5,
03723                 NULL);
03724 
03725   /* check if there is one or more than one page with changes */
03726   ret = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
03727                                          dialog->store_unsaved_pages),
03728                                        &iter);
03729   g_assert (ret);
03730   single_page = !gtk_tree_model_iter_next (GTK_TREE_MODEL (
03731                                              dialog->store_unsaved_pages),
03732                                            &iter);
03733 
03734   /* here starts the layout of the dialog */
03735   hbox = GTK_WIDGET (g_object_new (GTK_TYPE_HBOX,
03736                                    /* GtkContainer */
03737                                    "border-width", 5,
03738                                    /* GtkBox */
03739                                    "homogeneous",  FALSE,
03740                                    "spacing",      12,
03741                                    NULL));
03742 
03743   /* warning image */
03744   image = g_object_new (GTK_TYPE_IMAGE,
03745                         /* GtkMisc */
03746                         "xalign",    0.5,
03747                         "yalign",    0.0,
03748                         /* GtkImage */
03749                         "stock",     GTK_STOCK_DIALOG_WARNING,
03750                         "icon-size", GTK_ICON_SIZE_DIALOG,
03751                         NULL);
03752   gtk_box_pack_start (GTK_BOX (hbox), image,
03753                       FALSE, FALSE, 0);
03754 
03755   /* vertical box on the right hand side of the dialog */
03756   vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
03757                                    /* GtkBox */
03758                                    "homogeneous", FALSE,
03759                                    "spacing",     12,
03760                                    NULL));
03761 
03762   /* primary label */
03763   if (single_page) {
03764     /* single page */
03765     gchar *page_name;
03766 
03767     page_name = get_page_name (GTK_TREE_MODEL (dialog->store_unsaved_pages),
03768                                NULL);
03769     tmp = g_strdup_printf (
03770       _("Save the changes to schematic \"%s\" before closing?"),
03771       page_name);
03772     g_free (page_name);
03773   } else {
03774     /* multi page */
03775     tmp = g_strdup_printf (
03776       _("There are %d schematics with unsaved changes. "
03777         "Save changes before closing?"),
03778       count_pages (GTK_TREE_MODEL (dialog->store_unsaved_pages)));
03779   }
03780   str = g_strconcat ("<big><b>", tmp, "</b></big>", NULL);
03781   g_free (tmp);
03782   label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
03783                                     /* GtkMisc */
03784                                     "xalign",     0.0,
03785                                     "yalign",     0.0,
03786                                     "selectable", TRUE,
03787                                     /* GtkLabel */
03788                                     "wrap",       TRUE,
03789                                     "use-markup", TRUE,
03790                                     "label",      str,
03791                                     NULL));
03792   g_free (str);
03793   gtk_box_pack_start (GTK_BOX (vbox), label,
03794                       FALSE, FALSE, 0);
03795 
03796   if (!single_page) {
03797     /* more than one page with changes, display each page and offer */
03798     /* the opportunity to save them before exiting */
03799     gtk_box_pack_start (GTK_BOX (vbox),
03800                         close_confirmation_dialog_build_page_list (dialog),
03801                         FALSE, FALSE, 0);
03802   }
03803 
03804   /* secondary label */
03805   cstr = _("If you don't save, all your changes will be permanently lost.");
03806   label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
03807                                     /* GtkMisc */
03808                                     "xalign",     0.0,
03809                                     "yalign",     0.0,
03810                                     "selectable", TRUE,
03811                                     /* GtkLabel */
03812                                     "wrap",       TRUE,
03813                                     "label",      cstr,
03814                                     NULL));
03815   gtk_box_pack_start (GTK_BOX (vbox), label,
03816                       FALSE, FALSE, 0);
03817 
03818 
03819   gtk_box_pack_start (GTK_BOX (hbox), vbox,
03820                       FALSE, FALSE, 0);
03821 
03822 
03823   /* add buttons to dialog action area */
03824   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
03825                           _("_Close without saving"), GTK_RESPONSE_NO,
03826                           GTK_STOCK_CANCEL,           GTK_RESPONSE_CANCEL,
03827                           GTK_STOCK_SAVE,             GTK_RESPONSE_YES,
03828                           NULL);
03829 
03830   /* Set the alternative button order (ok, cancel, help) for other systems */
03831   gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
03832                                           GTK_RESPONSE_YES,
03833                                           GTK_RESPONSE_NO,
03834                                           GTK_RESPONSE_CANCEL,
03835                                           -1);
03836 
03837   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
03838 
03839   /* all done, let's show the contents of the dialog */
03840   gtk_widget_show_all (hbox);
03841 
03842   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
03843                       FALSE, FALSE, 0);
03844 
03845   return object;
03846 }
03847 
03848 static void
03849 close_confirmation_dialog_set_property (GObject      *object,
03850                                         guint         property_id,
03851                                         const GValue *value,
03852                                         GParamSpec   *pspec)
03853 {
03854   CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (object);
03855   GtkTreeIter iter;
03856   gpointer data;
03857   GList *p_current;
03858 
03859   switch(property_id) {
03860     case PROP_UNSAVED_PAGE:
03861       data = g_value_get_pointer (value);
03862       if (data != NULL) {
03863         /* add single page to model */
03864         gtk_list_store_append (dialog->store_unsaved_pages,
03865                                &iter);
03866         gtk_list_store_set (dialog->store_unsaved_pages,
03867                             &iter,
03868                             COLUMN_SAVE, TRUE,
03869                             COLUMN_PAGE, data,
03870                             -1);
03871       }
03872       break;
03873 
03874     case PROP_UNSAVED_PAGES:
03875       data = g_value_get_pointer (value);
03876       /* add set of pages to model */
03877       for (p_current = (GList*)data;
03878            p_current != NULL;
03879            p_current = g_list_next (p_current)) {
03880         gtk_list_store_append (dialog->store_unsaved_pages,
03881                                &iter);
03882         gtk_list_store_set (dialog->store_unsaved_pages,
03883                             &iter,
03884                             COLUMN_SAVE, TRUE,
03885                             COLUMN_PAGE, p_current->data,
03886                             -1);
03887       }
03888       break;
03889 
03890     default:
03891       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
03892   }
03893 
03894 }
03895 
03896 static void
03897 close_confirmation_dialog_get_property (GObject    *object,
03898                                         guint       property_id,
03899                                         GValue     *value,
03900                                         GParamSpec *pspec)
03901 {
03902   CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (object);
03903 
03904   switch(property_id) {
03905     case PROP_SELECTED_PAGES:
03906       g_value_set_pointer (
03907         value,
03908         close_confirmation_dialog_get_selected_pages (dialog));
03909       break;
03910 
03911     default:
03912       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
03913   }
03914 
03915 }
03916 
03932 static gboolean
03933 get_selected_pages (GtkTreeModel *model,
03934                     GtkTreePath  *path,
03935                     GtkTreeIter  *iter,
03936                     gpointer     data)
03937 {
03938   PAGE *page;
03939   gboolean save;
03940 
03941   gtk_tree_model_get (model, iter,
03942                       COLUMN_SAVE, &save,
03943                       COLUMN_PAGE, &page,
03944                       -1);
03945   if (save) {
03946     g_assert (page != NULL);
03947     *(GList**)data = g_list_append (*(GList**)data, page);
03948   }
03949 
03950   return FALSE;
03951 }
03952 
03963 GList*
03964 close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog *dialog)
03965 {
03966   GList *selected = NULL;
03967 
03968   gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->store_unsaved_pages),
03969                           (GtkTreeModelForeachFunc)get_selected_pages,
03970                           &selected);
03971 
03972   return selected;
03973 }
03974 
03975 
03988 void
03989 x_dialog_close_changed_page (GSCHEM_TOPLEVEL *w_current, PAGE *page)
03990 {
03991   GtkWidget *dialog;
03992   PAGE *keep_page;
03993 
03994   g_return_if_fail (page != NULL && page->CHANGED);
03995 
03996   keep_page = w_current->toplevel->page_current;
03997 
03998   dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
03999                                      "unsaved-page", page,
04000                                      NULL));
04001   /* set default response signal. This is usually triggered by the
04002      "Return" key */
04003   gtk_dialog_set_default_response(GTK_DIALOG(dialog),
04004                                   GTK_RESPONSE_YES);
04005 
04006   switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
04007       case GTK_RESPONSE_NO:
04008         /* action selected: close without saving */
04009         /* close the page, discard changes */
04010         x_window_close_page (w_current, page);
04011         break;
04012 
04013 
04014       case GTK_RESPONSE_YES:
04015         /* action selected: save */
04016         s_page_goto (w_current->toplevel, page);
04017         i_callback_file_save(w_current, 0, NULL);
04018         /* has the page been really saved? */
04019         if (!page->CHANGED) {
04020           x_window_close_page (w_current, page);
04021         }
04022         /* no, user has cancelled the save and page has changes */
04023         /* do not close page */
04024         break;
04025 
04026       case GTK_RESPONSE_CANCEL:
04027         /* action selected: cancel */
04028         /* fall through */
04029       default:
04030         /* Hit when the user breaks out of the dialog with the escape key
04031          * or otherwise destroys the dialog window without a proper response */
04032         /* nothing to do */
04033         break;
04034   }
04035   gtk_widget_destroy (dialog);
04036 
04037   /* Switch back to the page we were on if it wasn't the one being closed */
04038   g_return_if_fail (keep_page != NULL);
04039   if (keep_page != page)
04040     s_page_goto (w_current->toplevel, keep_page);
04041 }
04042 
04058 gboolean
04059 x_dialog_close_window (GSCHEM_TOPLEVEL *w_current)
04060 {
04061   TOPLEVEL *toplevel = w_current->toplevel;
04062   GList *iter;
04063   GtkWidget *dialog;
04064   PAGE *p_current;
04065   PAGE *keep_page;
04066   GList *unsaved_pages, *p_unsaved;
04067   gboolean ret = FALSE;
04068 
04069   keep_page = toplevel->page_current;
04070 
04071   for ( iter = geda_list_get_glist( toplevel->pages ), unsaved_pages = NULL;
04072         iter != NULL;
04073         iter = g_list_next( iter ) ) {
04074 
04075     p_current = (PAGE*)iter->data;
04076 
04077     if (p_current->CHANGED) {
04078       unsaved_pages = g_list_append (unsaved_pages, (gpointer)p_current);
04079     }
04080   }
04081 
04082   if (unsaved_pages == NULL) {
04083     /* no page with unsaved changes, close window */
04084     return TRUE;
04085   }
04086 
04087   dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
04088                                      "unsaved-pages", unsaved_pages,
04089                                      NULL));
04090 
04091   gtk_window_set_transient_for (GTK_WINDOW (dialog),
04092                                 GTK_WINDOW (w_current->main_window));
04093 
04094   g_list_free (unsaved_pages);
04095   switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
04096       case GTK_RESPONSE_NO:
04097         /* action selected: close without saving */
04098         /* discard changes, ok to close window */
04099         ret = TRUE;
04100         break;
04101 
04102       case GTK_RESPONSE_YES:
04103         /* action selected: save */
04104         g_object_get (dialog,
04105                       "selected-pages", &unsaved_pages,
04106                       NULL);
04107         for (p_unsaved = unsaved_pages, ret = TRUE;
04108              p_unsaved != NULL;
04109              p_unsaved = g_list_next (p_unsaved)) {
04110           p_current = (PAGE*)p_unsaved->data;
04111 
04112           s_page_goto (toplevel, p_current);
04113           i_callback_file_save(w_current, 0, NULL);
04114           /* if user cancelled previous, do not close window */
04115           ret &= !p_current->CHANGED;
04116         }
04117         g_list_free (unsaved_pages);
04118         break;
04119 
04120       case GTK_RESPONSE_CANCEL:
04121         /* action selected: cancel */
04122         /* fall through */
04123       default:
04124         /* Hit when the user breaks out of the dialog with the escape key
04125          * or otherwise destroys the dialog window without a proper response */
04126         ret = FALSE;
04127         break;
04128   }
04129   gtk_widget_destroy (dialog);
04130 
04131   /* Switch back to the page we were on */
04132   g_return_val_if_fail (keep_page != NULL, ret);
04133   s_page_goto (toplevel, keep_page);
04134 
04135   return ret;
04136 }
04137 
04138 /***************** End of Close Confirmation dialog box **************/
04139 
04140 
04141 /***************** Start of misc helper dialog boxes **************/
04151 int x_dialog_validate_attribute(GtkWindow* parent, char *attribute)
04152 {
04153   GtkWidget* message_box;
04154 
04155   /* validate the new attribute */
04156   if (!o_attrib_string_get_name_value (attribute, NULL, NULL)) {
04157       message_box = gtk_message_dialog_new_with_markup (parent,
04158                                   GTK_DIALOG_DESTROY_WITH_PARENT,
04159                                   GTK_MESSAGE_ERROR,
04160                                   GTK_BUTTONS_CLOSE,
04161                                   _("<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."),
04162                                   attribute);
04163      gtk_window_set_title(GTK_WINDOW(message_box), _("Invalid Attribute"));
04164      gtk_dialog_run (GTK_DIALOG (message_box));
04165      gtk_widget_destroy (message_box);
04166      return FALSE;
04167   }
04168   return TRUE;
04169 }
04170 /***************** End of misc helper dialog boxes **************/
04171 
04177 void x_dialog_edit_pin_type (GSCHEM_TOPLEVEL *w_current, const GList *obj_list)
04178 {
04179   GtkWidget *dialog;
04180   GtkWidget *vbox;
04181   GtkWidget *radio1;
04182   GtkWidget *radio2;
04183   const GList *iter;
04184   int new_type;
04185   int found_pins = FALSE;
04186   int changed_anything = FALSE;
04187 
04188   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
04189     OBJECT *object = iter->data;
04190     if (object->type == OBJ_PIN) {
04191       found_pins = TRUE;
04192       break;
04193     }
04194   }
04195 
04196   if (!found_pins)
04197     return;
04198 
04199   dialog = gschem_dialog_new_with_buttons(_("Pin type"),
04200                                           GTK_WINDOW(w_current->main_window),
04201                                           GTK_DIALOG_MODAL,
04202                                           "pin-type-edit", w_current,
04203                                           GTK_STOCK_CANCEL,
04204                                           GTK_RESPONSE_CANCEL,
04205                                           GTK_STOCK_OK,
04206                                           GTK_RESPONSE_OK,
04207                                           NULL);
04208 
04209   /* Set the alternative button order (ok, cancel, help) for other systems */
04210   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
04211                                            GTK_RESPONSE_OK,
04212                                            GTK_RESPONSE_CANCEL,
04213                                            -1);
04214 
04215   gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
04216 
04217   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
04218 
04219   gtk_container_border_width (GTK_CONTAINER (dialog), DIALOG_BORDER_SPACING);
04220   vbox = GTK_DIALOG (dialog)->vbox;
04221   gtk_box_set_spacing (GTK_BOX(vbox), DIALOG_V_SPACING);
04222 
04223   radio1 = gtk_radio_button_new_with_label (NULL, _("Net pin"));
04224   radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1),
04225                                                         _("Bus pin (graphical)"));
04226   /* Pack them into a box, then show all the widgets */
04227   gtk_box_pack_start (GTK_BOX (vbox), radio1, TRUE, TRUE, 2);
04228   gtk_box_pack_start (GTK_BOX (vbox), radio2, TRUE, TRUE, 2);
04229   gtk_widget_show_all (vbox);
04230 
04231   switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
04232     case GTK_RESPONSE_OK:
04233       new_type = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio1)) ?
04234                    PIN_TYPE_NET : PIN_TYPE_BUS;
04235       for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
04236         OBJECT *object = iter->data;
04237 
04238         if (object->type == OBJ_PIN &&
04239             object->pin_type != new_type) {
04240           changed_anything = TRUE;
04241           s_conn_remove_object (w_current->toplevel, object);
04242           o_pin_set_type (w_current->toplevel, object, new_type);
04243           s_conn_update_object (w_current->toplevel, object);
04244         }
04245       }
04246       if (changed_anything)
04247         o_undo_savestate (w_current, UNDO_ALL);
04248       break;
04249 
04250     case GTK_RESPONSE_CANCEL:
04251     default:
04252       /* Do nothing */
04253       break;
04254   }
04255 
04256   gtk_widget_destroy (dialog);
04257 }
04258 
04259 /***************** End of pin type edit dialog box *********************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines