4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 /* This file written by Bill Wilson for the PCB Gtk port.
37 #include "../hidint.h"
46 #include "misc.h" /* MKDIR() */
47 #include "pcb-printf.h"
53 #ifdef HAVE_LIBDMALLOC
57 extern int MoveLayerAction(int argc
, char **argv
, int x
, int y
);
58 /* This is defined in main.c */
59 void save_increments (const Increments
*mm
, const Increments
*mil
);
90 HID_Attribute
*attributes
;
93 gboolean color_is_mapped
;
97 static GList
*config_color_list
, *lib_newlib_list
;
99 static gchar
*lib_newlib_config
, *board_size_override
;
102 static gchar
*color_file
;
104 extern void ghid_set_special_colors (HID_Attribute
* ha
);
107 #define PCB_CONFIG_DIR ".pcb"
108 #define PCB_CONFIG_FILE "preferences"
109 #define PCB_COLORS_DIR "colors"
111 static gchar
*config_dir
, *color_dir
;
113 /* CONFIG_Unused types are expected to be found in main_attribute_list and
114 | will be assigned the type found there. NULL value pointers here are
115 | also expected to be assigned values from the main_attribute_list.
117 /* PinoutFont also not used anymore */
119 static ConfigAttribute config_attributes
[] = {
120 {"gui-compact-horizontal", CONFIG_Boolean
, &_ghidgui
.compact_horizontal
},
121 {"gui-compact-vertical", CONFIG_Boolean
, &_ghidgui
.compact_vertical
},
122 {"use-command-window", CONFIG_Boolean
, &_ghidgui
.use_command_window
},
123 {"save-in-tmp", CONFIG_Unused
, NULL
},
124 {"grid-units", CONFIG_Unused
, NULL
},
125 {"grid", CONFIG_Unused
, NULL
},
127 {"grid-increment-mm", CONFIG_Unused
, NULL
},
128 {"line-increment-mm", CONFIG_Unused
, NULL
},
129 {"size-increment-mm", CONFIG_Unused
, NULL
},
130 {"clear-increment-mm", CONFIG_Unused
, NULL
},
131 {"grid-increment-mil", CONFIG_Unused
, NULL
},
132 {"line-increment-mil", CONFIG_Unused
, NULL
},
133 {"size-increment-mil", CONFIG_Unused
, NULL
},
134 {"clear-increment-mil", CONFIG_Unused
, NULL
},
136 {"history-size", CONFIG_Integer
, &_ghidgui
.history_size
},
137 {"top-window-width", CONFIG_Integer
, &_ghidgui
.top_window_width
},
138 {"top-window-height", CONFIG_Integer
, &_ghidgui
.top_window_height
},
139 {"log-window-width", CONFIG_Integer
, &_ghidgui
.log_window_width
},
140 {"log-window-height", CONFIG_Integer
, &_ghidgui
.log_window_height
},
141 {"drc-window-width", CONFIG_Integer
, &_ghidgui
.drc_window_width
},
142 {"drc-window-height", CONFIG_Integer
, &_ghidgui
.drc_window_height
},
143 {"library-window-width", CONFIG_Integer
, &_ghidgui
.library_window_width
},
144 {"library-window-height", CONFIG_Integer
, &_ghidgui
.library_window_height
},
145 {"netlist-window-height", CONFIG_Integer
, &_ghidgui
.netlist_window_height
},
146 {"keyref-window-width", CONFIG_Integer
, &_ghidgui
.keyref_window_width
},
147 {"keyref-window-height", CONFIG_Integer
, &_ghidgui
.keyref_window_height
},
148 {"text-scale", CONFIG_Unused
, NULL
},
149 {"via-thickness", CONFIG_Unused
, NULL
},
150 {"via-drilling-hole", CONFIG_Unused
, NULL
},
151 {"backup-interval", CONFIG_Unused
, NULL
},
152 {"line-thickness", CONFIG_Unused
, NULL
},
153 {"rat-thickness", CONFIG_Unused
, NULL
},
154 {"bloat", CONFIG_Unused
, NULL
},
155 {"shrink", CONFIG_Unused
, NULL
},
156 {"min-width", CONFIG_Unused
, NULL
},
157 {"min-silk", CONFIG_Unused
, NULL
},
158 {"min-drill", CONFIG_Unused
, NULL
},
159 {"min-ring", CONFIG_Unused
, NULL
},
160 {"default-PCB-width", CONFIG_Unused
, NULL
},
161 {"default-PCB-height", CONFIG_Unused
, NULL
},
163 {"groups", CONFIG_Unused
, NULL
},
164 {"route-styles", CONFIG_Unused
, NULL
},
165 {"library-newlib", CONFIG_String
, &lib_newlib_config
},
166 {"color-file", CONFIG_String
, &color_file
},
167 /* FIXME: construct layer-names- in a list */
168 {"layer-name-1", CONFIG_Unused
, NULL
},
169 {"layer-name-2", CONFIG_Unused
, NULL
},
170 {"layer-name-3", CONFIG_Unused
, NULL
},
171 {"layer-name-4", CONFIG_Unused
, NULL
},
172 {"layer-name-5", CONFIG_Unused
, NULL
},
173 {"layer-name-6", CONFIG_Unused
, NULL
},
174 {"layer-name-7", CONFIG_Unused
, NULL
},
175 {"layer-name-8", CONFIG_Unused
, NULL
},
179 dup_core_string (gchar
** dst
, const gchar
* src
)
181 if (dst
== NULL
|| (*dst
== NULL
&& src
== NULL
))
184 if (*dst
!= NULL
&& src
!= NULL
&& strcmp (*dst
, src
) == 0)
188 *dst
= (src
== NULL
) ? NULL
: strdup (src
);
194 config_file_open (gchar
* mode
)
197 gchar
*homedir
, *fname
;
200 homedir
= (gchar
*) g_get_home_dir ();
203 g_message ("config_file_open: Can't get home directory!");
210 g_build_path (G_DIR_SEPARATOR_S
, homedir
, PCB_CONFIG_DIR
, NULL
);
211 if (!g_file_test (config_dir
, G_FILE_TEST_IS_DIR
)
212 && MKDIR (config_dir
, 0755) < 0)
214 g_message ("config_file_open: Can't make \"%s\" directory!",
222 if (!color_dir
) /* Convenient to make the color dir here */
225 g_build_path (G_DIR_SEPARATOR_S
, config_dir
, PCB_COLORS_DIR
, NULL
);
226 if (!g_file_test (color_dir
, G_FILE_TEST_IS_DIR
))
228 if (MKDIR (color_dir
, 0755) < 0)
230 g_message ("config_file_open: Can't make \"%s\" directory!",
235 fname
= g_build_path (G_DIR_SEPARATOR_S
,
236 color_dir
, "Default", NULL
);
237 dup_string (&color_file
, fname
);
242 fname
= g_build_path (G_DIR_SEPARATOR_S
, config_dir
, PCB_CONFIG_FILE
, NULL
);
243 f
= fopen (fname
, mode
);
249 static ConfigAttribute
*
250 lookup_config_attribute (gchar
* name
, gboolean if_null_value
)
254 for (ca
= &config_attributes
[0];
255 ca
< &config_attributes
[0] + G_N_ELEMENTS (config_attributes
); ++ca
)
257 if (name
&& (!strcmp (name
, ca
->name
)))
259 if (ca
->value
&& if_null_value
)
268 ghid_config_init (void)
272 ConfigAttribute
*ca
, dummy_attribute
;
276 ghidgui
->n_mode_button_columns
= 3;
277 ghidgui
->small_label_markup
= TRUE
;
278 ghidgui
->history_size
= 5;
279 dup_string (&color_file
, "");
281 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
283 for (a
= ha
->attributes
; a
< ha
->attributes
+ ha
->n
; ++a
)
287 if ((ca
= lookup_config_attribute (a
->name
, TRUE
)) == NULL
)
288 ca
= &dummy_attribute
;
289 ca
->value
= a
->value
; /* Typically &Setting.xxx */
290 ca
->type
= CONFIG_Unused
;
294 *(char *) a
->value
= a
->default_val
.int_value
;
295 ca
->type
= CONFIG_Boolean
;
298 *(int *) a
->value
= a
->default_val
.int_value
;
299 ca
->type
= CONFIG_Integer
;
302 *(Coord
*) a
->value
= a
->default_val
.coord_value
;
303 ca
->type
= CONFIG_Coord
;
306 *(double *) a
->value
= a
->default_val
.real_value
;
307 ca
->type
= CONFIG_Real
;
313 *(char **) a
->value
= g_strdup (a
->default_val
.str_value
);
314 ca
->type
= CONFIG_String
;
316 len
= strlen (a
->name
);
317 if (len
< 7 || strstr (a
->name
, "color") == NULL
)
320 cc
= g_new0 (ConfigColor
, 1);
323 if (!strncmp (a
->name
, "layer-color", 11))
324 cc
->type
= LAYER_COLOR
;
325 else if (!strncmp (a
->name
, "layer-selected-color", 20))
326 cc
->type
= LAYER_SELECTED_COLOR
;
327 else if (!strncmp (a
->name
+ len
- 14, "selected-color", 14))
328 cc
->type
= MISC_SELECTED_COLOR
;
330 cc
->type
= MISC_COLOR
;
332 config_color_list
= g_list_append (config_color_list
, cc
);
337 *(int *) a
->value
= a
->default_val
.int_value
;
352 parse_option_line (gchar
* line
, gchar
** option_result
, gchar
** arg_result
)
354 gchar
*s
, *ss
, option
[64], arg
[512];
358 *option_result
= NULL
;
363 while (*s
== ' ' || *s
== '\t')
365 if (!*s
|| *s
== '\n' || *s
== '#' || *s
== '[')
367 if ((ss
= strchr (s
, '\n')) != NULL
)
370 sscanf (s
, "%63s %511[^\n]", option
, arg
);
372 s
= option
; /* Strip trailing ':' or '=' */
373 while (*s
&& *s
!= ':' && *s
!= '=')
377 s
= arg
; /* Strip leading ':', '=', and whitespace */
378 while (*s
== ' ' || *s
== '\t' || *s
== ':' || *s
== '=' || *s
== '"')
380 if ((ss
= strchr (s
, '"')) != NULL
)
384 *option_result
= g_strdup (option
);
385 if (arg_result
&& *s
)
387 *arg_result
= g_strdup (s
);
394 set_config_attribute (gchar
* option
, gchar
* arg
)
399 gchar locale_point
, *comma_point
, *period_point
;
401 /* Until LC_NUMERIC is totally resolved, check if we need to decimal
402 | point convert. Ultimately, data files will be POSIX and gui
403 | presentation (hence the config file reals) will be in the users locale.
406 locale_point
= *lc
->decimal_point
;
409 if ((ca
= lookup_config_attribute (option
, FALSE
)) == NULL
)
414 *(gchar
*) ca
->value
= (gchar
) atoi (arg
);
418 *(gint
*) ca
->value
= atoi (arg
);
422 /* Hopefully temporary locale decimal point check:
425 comma_point
= strrchr (arg
, ',');
426 period_point
= strrchr (arg
, '.');
427 if (comma_point
&& *comma_point
!= locale_point
)
428 *comma_point
= locale_point
;
429 else if (period_point
&& *period_point
!= locale_point
)
430 *period_point
= locale_point
;
432 *(double *) ca
->value
= atof (arg
);
436 dup_string ((gchar
**) ca
->value
, arg
? arg
: (gchar
*)"");
439 *(Coord
*) ca
->value
= GetValue (arg
, NULL
, NULL
);
448 config_file_read (void)
451 gchar buf
[512], *option
, *arg
;
453 if ((f
= config_file_open ("r")) == NULL
)
457 while (fgets (buf
, sizeof (buf
), f
))
459 if (parse_option_line (buf
, &option
, &arg
) > 0)
460 set_config_attribute (option
, arg
);
469 config_colors_write (gchar
* path
)
476 if ((f
= fopen (path
, "w")) == NULL
)
478 for (list
= config_color_list
; list
; list
= list
->next
)
480 cc
= (ConfigColor
*) list
->data
;
482 fprintf (f
, "%s =\t%s\n", ha
->name
, *(char **) ha
->value
);
488 config_colors_read (gchar
* path
)
494 gchar
*s
, buf
[512], option
[64], arg
[512];
496 if (!path
|| !*path
|| (f
= fopen (path
, "r")) == NULL
)
499 while (fgets (buf
, sizeof (buf
), f
))
501 sscanf (buf
, "%63s %511[^\n]", option
, arg
);
502 s
= option
; /* Strip trailing ':' or '=' */
503 while (*s
&& *s
!= ':' && *s
!= '=')
506 s
= arg
; /* Strip leading ':', '=', and whitespace */
507 while (*s
== ' ' || *s
== '\t' || *s
== ':' || *s
== '=')
510 for (list
= config_color_list
; list
; list
= list
->next
)
512 cc
= (ConfigColor
*) list
->data
;
514 if (!strcmp (option
, ha
->name
))
516 *(char **) ha
->value
= g_strdup (s
);
517 cc
->color_is_mapped
= FALSE
;
518 ghid_set_special_colors (ha
);
529 expand_dir (gchar
* dir
)
534 s
= g_build_filename ((gchar
*) g_get_home_dir (), dir
+ 1, NULL
);
541 add_to_paths_list (GList
** list
, gchar
* path_string
)
545 paths
= g_strdup (path_string
);
546 for (p
= strtok (paths
, PCB_PATH_DELIMETER
); p
&& *p
; p
= strtok (NULL
, PCB_PATH_DELIMETER
))
547 *list
= g_list_prepend (*list
, expand_dir (p
));
551 /* Parse command line code borrowed from hid/common/hidinit.c
554 parse_optionv (gint
* argc
, gchar
*** argv
, gboolean from_cmd_line
)
561 gboolean matched
= FALSE
;
563 offset
= from_cmd_line
? 2 : 0;
566 && (((*argv
)[0][0] == '-' && (*argv
)[0][1] == '-')
569 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
571 for (a
= ha
->attributes
; a
< ha
->attributes
+ ha
->n
; ++a
)
573 if (!a
->name
|| strcmp ((*argv
)[0] + offset
, a
->name
))
581 *(int *) a
->value
= strtol ((*argv
)[1], 0, 0);
583 a
->default_val
.int_value
= strtol ((*argv
)[1], 0, 0);
589 *(Coord
*) a
->value
= GetValue ((*argv
)[1], 0, 0);
591 a
->default_val
.coord_value
= GetValue ((*argv
)[1], 0, 0);
597 *(double *) a
->value
= strtod ((*argv
)[1], 0);
599 a
->default_val
.real_value
= strtod ((*argv
)[1], 0);
605 *(char **) a
->value
= g_strdup((*argv
)[1]);
607 a
->default_val
.str_value
= g_strdup((*argv
)[1]);
613 *(char *) a
->value
= 1;
615 a
->default_val
.int_value
= 1;
618 a
->default_val
.real_value
= strtod ((*argv
)[1], &ep
);
624 for (e
= 0; a
->enumerations
[e
]; e
++)
625 if (strcmp (a
->enumerations
[e
], ep
) == 0)
628 a
->default_val
.int_value
= e
;
629 a
->default_val
.str_value
= ep
;
635 "ERROR: \"%s\" is an unknown value for the --%s option\n",
636 (*argv
)[1], a
->name
);
644 a
->default_val
.str_value
= (*argv
)[1];
649 unit
= get_unit_struct ((*argv
)[1]);
653 "ERROR: unit \"%s\" is unknown to pcb (option --%s)\n",
654 (*argv
)[1], a
->name
);
657 a
->default_val
.int_value
= unit
->index
;
658 a
->default_val
.str_value
= unit
->suffix
;
668 if (a
< ha
->attributes
+ ha
->n
)
675 fprintf (stderr
, "unrecognized option: %s\n", (*argv
)[0]);
679 // ghid_log("unrecognized option: %s\n", (*argv)[0]);
680 fprintf (stderr
, "unrecognized option: %s\n", (*argv
)[0]);
689 load_rc_file (gchar
* path
)
692 gchar buf
[1024], *av
[2], **argv
;
695 f
= fopen (path
, "r");
699 if (Settings
.verbose
)
700 printf ("Loading pcbrc file: %s\n", path
);
701 while (fgets (buf
, sizeof (buf
), f
))
704 if ((argc
= parse_option_line (buf
, &av
[0], &av
[1])) > 0)
705 parse_optionv (&argc
, &argv
, FALSE
);
717 load_rc_file ("/etc/pcbrc");
718 load_rc_file ("/usr/local/etc/pcbrc");
720 path
= g_build_filename (pcblibdir
, "pcbrc", NULL
);
724 path
= g_build_filename ((gchar
*) g_get_home_dir (), ".pcb/pcbrc", NULL
);
728 load_rc_file ("pcbrc");
733 ghid_config_files_read (gint
* argc
, gchar
*** argv
)
744 config_colors_read (color_file
);
747 parse_optionv (argc
, argv
, TRUE
);
749 if (board_size_override
750 && sscanf (board_size_override
, "%dx%d", &width
, &height
) == 2)
752 Settings
.MaxWidth
= TO_PCB_UNITS (width
);
753 Settings
.MaxHeight
= TO_PCB_UNITS (height
);
756 if (lib_newlib_config
&& *lib_newlib_config
)
757 add_to_paths_list (&lib_newlib_list
, lib_newlib_config
);
759 for (list
= lib_newlib_list
; list
; list
= list
->next
)
761 str
= Settings
.LibraryTree
;
762 dir
= expand_dir ((gchar
*) list
->data
);
763 Settings
.LibraryTree
= g_strconcat (str
, PCB_PATH_DELIMETER
, dir
, NULL
);
770 ghid_config_files_write (void)
775 if (!ghidgui
->config_modified
|| (f
= config_file_open ("w")) == NULL
)
778 fprintf (f
, "### PCB configuration file. ###\n");
780 for (ca
= &config_attributes
[0];
781 ca
< &config_attributes
[0] + G_N_ELEMENTS (config_attributes
); ++ca
)
786 fprintf (f
, "%s = %d\n", ca
->name
, (gint
) * (gchar
*) ca
->value
);
790 fprintf (f
, "%s = %d\n", ca
->name
, *(gint
*) ca
->value
);
794 fprintf (f
, "%s = %f\n", ca
->name
, *(double *) ca
->value
);
798 pcb_fprintf (f
, "%s = %$mS\n", ca
->name
, *(Coord
*) ca
->value
);
802 if (*(char **) ca
->value
== NULL
)
803 fprintf (f
, "# %s = NULL\n", ca
->name
);
805 fprintf (f
, "%s = %s\n", ca
->name
, *(char **) ca
->value
);
813 ghidgui
->config_modified
= FALSE
;
816 /* =================== OK, now the gui stuff ======================
818 static GtkWidget
*config_window
;
820 /* -------------- The General config page ----------------
824 config_command_window_toggle_cb (GtkToggleButton
* button
, gpointer data
)
826 gboolean active
= gtk_toggle_button_get_active (button
);
827 static gboolean holdoff
;
832 /* Can't toggle into command window mode if the status line command
835 if (ghidgui
->command_entry_status_line_active
)
838 gtk_toggle_button_set_active (button
, FALSE
);
842 ghidgui
->use_command_window
= active
;
843 ghid_command_use_command_window_sync ();
848 config_compact_horizontal_toggle_cb (GtkToggleButton
* button
, gpointer data
)
850 gboolean active
= gtk_toggle_button_get_active (button
);
852 ghidgui
->compact_horizontal
= active
;
853 ghid_set_status_line_label ();
854 ghidgui
->config_modified
= TRUE
;
858 config_compact_vertical_toggle_cb (GtkToggleButton
* button
, gpointer data
)
860 gboolean active
= gtk_toggle_button_get_active (button
);
862 ghidgui
->compact_vertical
= active
;
863 ghid_pack_mode_buttons();
864 ghidgui
->config_modified
= TRUE
;
868 config_general_toggle_cb (GtkToggleButton
* button
, void * setting
)
870 *(gint
*)setting
= gtk_toggle_button_get_active (button
);
871 ghidgui
->config_modified
= TRUE
;
875 config_backup_spin_button_cb (GtkSpinButton
* spin_button
, gpointer data
)
877 Settings
.BackupInterval
= gtk_spin_button_get_value_as_int (spin_button
);
879 ghidgui
->config_modified
= TRUE
;
883 config_history_spin_button_cb (GtkSpinButton
* spin_button
, gpointer data
)
885 ghidgui
->history_size
= gtk_spin_button_get_value_as_int (spin_button
);
886 ghidgui
->config_modified
= TRUE
;
890 config_general_tab_create (GtkWidget
* tab_vbox
)
894 gtk_container_set_border_width (GTK_CONTAINER (tab_vbox
), 6);
896 vbox
= ghid_category_vbox (tab_vbox
, _("Enables"), 4, 2, TRUE
, TRUE
);
898 ghid_check_button_connected (vbox
, NULL
, ghidgui
->use_command_window
,
899 TRUE
, FALSE
, FALSE
, 2,
900 config_command_window_toggle_cb
, NULL
,
901 _("Use separate window for command entry"));
903 ghid_check_button_connected (vbox
, NULL
, ghidgui
->compact_horizontal
,
904 TRUE
, FALSE
, FALSE
, 2,
905 config_compact_horizontal_toggle_cb
, NULL
,
906 _("Alternate window layout to allow smaller horizontal size"));
908 ghid_check_button_connected (vbox
, NULL
, ghidgui
->compact_vertical
,
909 TRUE
, FALSE
, FALSE
, 2,
910 config_compact_vertical_toggle_cb
, NULL
,
911 _("Alternate window layout to allow smaller vertical size"));
913 vbox
= ghid_category_vbox (tab_vbox
, _("Backups"), 4, 2, TRUE
, TRUE
);
914 ghid_check_button_connected (vbox
, NULL
, Settings
.SaveInTMP
,
915 TRUE
, FALSE
, FALSE
, 2,
916 config_general_toggle_cb
, &Settings
.SaveInTMP
,
917 _("If layout is modified at exit, save into PCB.%i.save"));
918 ghid_spin_button (vbox
, NULL
, Settings
.BackupInterval
, 0.0, 60 * 60, 60.0,
919 600.0, 0, 0, config_backup_spin_button_cb
, NULL
, FALSE
,
920 _("Seconds between auto backups\n"
921 "(set to zero to disable auto backups)"));
923 vbox
= ghid_category_vbox (tab_vbox
, _("Misc"), 4, 2, TRUE
, TRUE
);
924 ghid_spin_button (vbox
, NULL
, ghidgui
->history_size
,
925 5.0, 25.0, 1.0, 1.0, 0, 0,
926 config_history_spin_button_cb
, NULL
, FALSE
,
927 _("Number of commands to remember in the history list"));
932 config_general_apply (void)
934 /* save the settings */
935 ghid_config_files_write ();
939 /* -------------- The Sizes config page ----------------
942 static GtkWidget
*config_sizes_vbox
,
943 *config_sizes_tab_vbox
, *config_text_spin_button
;
945 static GtkWidget
*use_board_size_default_button
,
946 *use_drc_sizes_default_button
,
947 *use_increments_default_button
;
949 static Coord new_board_width
, new_board_height
;
952 config_sizes_apply (void)
957 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
958 (use_board_size_default_button
));
961 Settings
.MaxWidth
= new_board_width
;
962 Settings
.MaxHeight
= new_board_height
;
963 ghidgui
->config_modified
= TRUE
;
967 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
968 (use_drc_sizes_default_button
));
971 Settings
.Bloat
= PCB
->Bloat
;
972 Settings
.Shrink
= PCB
->Shrink
;
973 Settings
.minWid
= PCB
->minWid
;
974 Settings
.minSlk
= PCB
->minSlk
;
975 Settings
.IsleArea
= PCB
->IsleArea
;
976 Settings
.minDrill
= PCB
->minDrill
;
977 Settings
.minRing
= PCB
->minRing
;
978 ghidgui
->config_modified
= TRUE
;
982 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
983 (use_increments_default_button
));
986 save_increments (get_increments_struct (METRIC
),
987 get_increments_struct (IMPERIAL
));
988 ghidgui
->config_modified
= TRUE
;
991 if (PCB
->MaxWidth
!= new_board_width
|| PCB
->MaxHeight
!= new_board_height
)
992 ChangePCBSize (new_board_width
, new_board_height
);
996 text_spin_button_cb (GtkSpinButton
* spin
, void * dst
)
998 *(gint
*)dst
= gtk_spin_button_get_value_as_int (spin
);
999 ghidgui
->config_modified
= TRUE
;
1000 ghid_set_status_line_label ();
1004 coord_entry_cb (GHidCoordEntry
* ce
, void * dst
)
1006 *(Coord
*) dst
= ghid_coord_entry_get_value (ce
);
1007 ghidgui
->config_modified
= TRUE
;
1011 config_sizes_tab_create (GtkWidget
* tab_vbox
)
1013 GtkWidget
*table
, *vbox
, *hbox
;
1015 /* Need a vbox we can destroy if user changes grid units.
1017 if (!config_sizes_vbox
)
1019 vbox
= gtk_vbox_new (FALSE
, 0);
1020 gtk_box_pack_start (GTK_BOX (tab_vbox
), vbox
, FALSE
, FALSE
, 0);
1021 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 6);
1022 config_sizes_vbox
= vbox
;
1023 config_sizes_tab_vbox
= tab_vbox
;
1026 /* ---- Board Size ---- */
1027 vbox
= ghid_category_vbox (config_sizes_vbox
, _("Board Size"),
1029 hbox
= gtk_hbox_new (FALSE
, 0);
1030 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1031 table
= gtk_table_new (2, 2, FALSE
);
1032 gtk_box_pack_start (GTK_BOX (hbox
), table
, FALSE
, FALSE
, 0);
1033 gtk_table_set_col_spacings (GTK_TABLE (table
), 6);
1034 gtk_table_set_row_spacings (GTK_TABLE (table
), 3);
1036 new_board_width
= PCB
->MaxWidth
;
1037 new_board_height
= PCB
->MaxHeight
;
1038 ghid_table_coord_entry (table
, 0, 0, NULL
,
1039 PCB
->MaxWidth
, MIN_SIZE
, MAX_COORD
,
1040 CE_LARGE
, 0, coord_entry_cb
,
1041 &new_board_width
, FALSE
, _("Width"));
1043 ghid_table_coord_entry (table
, 1, 0, NULL
,
1044 PCB
->MaxHeight
, MIN_SIZE
, MAX_COORD
,
1045 CE_LARGE
, 0, coord_entry_cb
,
1046 &new_board_height
, FALSE
, _("Height"));
1047 ghid_check_button_connected (vbox
, &use_board_size_default_button
, FALSE
,
1048 TRUE
, FALSE
, FALSE
, 0, NULL
, NULL
,
1049 _("Use this board size as the default for new layouts"));
1051 /* ---- Text Scale ---- */
1052 vbox
= ghid_category_vbox (config_sizes_vbox
, _("Text Scale"),
1054 hbox
= gtk_hbox_new (FALSE
, 0);
1055 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1056 table
= gtk_table_new (4, 2, FALSE
);
1057 gtk_box_pack_start (GTK_BOX (hbox
), table
, FALSE
, FALSE
, 0);
1058 gtk_table_set_col_spacings (GTK_TABLE (table
), 6);
1059 gtk_table_set_row_spacings (GTK_TABLE (table
), 3);
1061 ghid_table_spin_button (table
, 0, 0, &config_text_spin_button
,
1063 MIN_TEXTSCALE
, MAX_TEXTSCALE
,
1065 0, 0, text_spin_button_cb
,
1066 &Settings
.TextScale
, FALSE
, "%");
1069 /* ---- DRC Sizes ---- */
1070 vbox
= ghid_category_vbox (config_sizes_vbox
, _("Design Rule Checking"),
1072 hbox
= gtk_hbox_new (FALSE
, 0);
1073 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1074 table
= gtk_table_new (4, 2, FALSE
);
1075 gtk_box_pack_start (GTK_BOX (hbox
), table
, FALSE
, FALSE
, 0);
1076 gtk_table_set_col_spacings (GTK_TABLE (table
), 6);
1077 gtk_table_set_row_spacings (GTK_TABLE (table
), 3);
1079 ghid_table_coord_entry (table
, 0, 0, NULL
,
1080 PCB
->Bloat
, MIN_DRC_VALUE
, MAX_DRC_VALUE
,
1081 CE_SMALL
, 0, coord_entry_cb
,
1083 _("Minimum copper spacing"));
1085 ghid_table_coord_entry (table
, 1, 0, NULL
,
1086 PCB
->minWid
, MIN_DRC_VALUE
, MAX_DRC_VALUE
,
1087 CE_SMALL
, 0, coord_entry_cb
,
1088 &PCB
->minWid
, FALSE
,
1089 _("Minimum copper width"));
1091 ghid_table_coord_entry (table
, 2, 0, NULL
,
1092 PCB
->Shrink
, MIN_DRC_VALUE
, MAX_DRC_VALUE
,
1093 CE_SMALL
, 0, coord_entry_cb
,
1094 &PCB
->Shrink
, FALSE
,
1095 _("Minimum touching copper overlap"));
1097 ghid_table_coord_entry (table
, 3, 0, NULL
,
1098 PCB
->minSlk
, MIN_DRC_VALUE
, MAX_DRC_VALUE
,
1099 CE_SMALL
, 0, coord_entry_cb
,
1100 &PCB
->minSlk
, FALSE
,
1101 _("Minimum silk width"));
1103 ghid_table_coord_entry (table
, 4, 0, NULL
,
1104 PCB
->minDrill
, MIN_DRC_VALUE
, MAX_DRC_VALUE
,
1105 CE_SMALL
, 0, coord_entry_cb
,
1106 &PCB
->minDrill
, FALSE
,
1107 _("Minimum drill diameter"));
1109 ghid_table_coord_entry (table
, 5, 0, NULL
,
1110 PCB
->minRing
, MIN_DRC_VALUE
, MAX_DRC_VALUE
,
1111 CE_SMALL
, 0, coord_entry_cb
,
1112 &PCB
->minRing
, FALSE
,
1113 _("Minimum annular ring"));
1115 ghid_check_button_connected (vbox
, &use_drc_sizes_default_button
, FALSE
,
1116 TRUE
, FALSE
, FALSE
, 0, NULL
, NULL
,
1118 ("Use DRC values as the default for new layouts"));
1120 gtk_widget_show_all (config_sizes_vbox
);
1124 /* -------------- The Increments config page ----------------
1126 /* Increment/decrement values are kept in mil and mm units and not in
1129 static GtkWidget
*config_increments_vbox
, *config_increments_tab_vbox
;
1132 increment_spin_button_cb (GHidCoordEntry
* ce
, void * dst
)
1134 *(Coord
*)dst
= ghid_coord_entry_get_value (ce
);
1135 ghidgui
->config_modified
= TRUE
;
1139 config_increments_tab_create (GtkWidget
* tab_vbox
)
1141 Increments
*incr_mm
= get_increments_struct (METRIC
);
1142 Increments
*incr_mil
= get_increments_struct (IMPERIAL
);
1143 GtkWidget
*vbox
, *hbox
, *table
;
1145 /* Need a vbox we can destroy if user changes grid units.
1147 if (!config_increments_vbox
)
1149 vbox
= gtk_vbox_new (FALSE
, 0);
1150 gtk_box_pack_start (GTK_BOX (tab_vbox
), vbox
, FALSE
, FALSE
, 0);
1151 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 6);
1152 config_increments_vbox
= vbox
;
1153 config_increments_tab_vbox
= tab_vbox
;
1156 #define INCR_ENTRY(row, name, family, type, msg) \
1157 gtk_table_attach_defaults (GTK_TABLE (table), \
1158 gtk_label_new (name), \
1159 0, 1, row, row + 1); \
1160 ghid_table_coord_entry (table, row, 1, NULL, \
1161 incr_##family->type, \
1162 incr_##family->type##_min, \
1163 incr_##family->type##_max, \
1164 CE_SMALL, 0, increment_spin_button_cb, \
1165 &incr_##family->type, FALSE, \
1168 /* ---- Metric Settings ---- */
1169 vbox
= ghid_category_vbox (config_increments_vbox
,
1170 _("Metric Increment Settings"), 4, 2, TRUE
, TRUE
);
1171 hbox
= gtk_hbox_new (FALSE
, 0);
1172 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1173 table
= gtk_table_new (4, 3, FALSE
);
1174 gtk_box_pack_start (GTK_BOX (hbox
), table
, FALSE
, FALSE
, 0);
1175 gtk_table_set_col_spacings (GTK_TABLE (table
), 6);
1176 gtk_table_set_row_spacings (GTK_TABLE (table
), 18);
1178 INCR_ENTRY (0, _("Grid:"), mm
, grid
,
1179 _("For 'g' and '<shift>g' grid change actions"));
1180 INCR_ENTRY (1, _("Size:"), mm
, size
,
1181 _("For 's' and '<shift>s' size change actions on lines,\n"
1182 "pads, pins and text.\n"
1183 "Use '<ctrl>s' and '<shift><ctrl>s' for drill holes."));
1184 INCR_ENTRY (2, _("Line:"), mm
, line
,
1185 _("For 'l' and '<shift>l' routing line width change actions"));
1186 INCR_ENTRY (3, _("Clear:"), mm
, clear
,
1187 _("For 'k' and '<shift>k' line clearance inside polygon size\n"
1190 vbox
= ghid_category_vbox (config_increments_vbox
,
1191 _("Imperial Increment Settings"), 4, 2, TRUE
, TRUE
);
1192 hbox
= gtk_hbox_new (FALSE
, 0);
1193 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1194 table
= gtk_table_new (4, 3, FALSE
);
1195 gtk_box_pack_start (GTK_BOX (hbox
), table
, FALSE
, FALSE
, 0);
1196 gtk_table_set_col_spacings (GTK_TABLE (table
), 6);
1197 gtk_table_set_row_spacings (GTK_TABLE (table
), 18);
1199 INCR_ENTRY (0, _("Grid:"), mil
, grid
,
1200 _("For 'g' and '<shift>g' grid change actions"));
1201 INCR_ENTRY (1, _("Size:"), mil
, size
,
1202 _("For 's' and '<shift>s' size change actions on lines,\n"
1203 "pads, pins and text.\n"
1204 "Use '<ctrl>s' and '<shift><ctrl>s' for drill holes."));
1205 INCR_ENTRY (2, _("Line:"), mil
, line
,
1206 _("For 'l' and '<shift>l' routing line width change actions"));
1207 INCR_ENTRY (3, _("Clear:"), mil
, clear
,
1208 _("For 'k' and '<shift>k' line clearance inside polygon size\n"
1212 vbox
= ghid_category_vbox (config_increments_vbox
,
1213 _("Save as Default"), 4, 2, TRUE
, TRUE
);
1214 ghid_check_button_connected (vbox
, &use_increments_default_button
, FALSE
,
1215 TRUE
, FALSE
, FALSE
, 0, NULL
, NULL
,
1216 _("Use values as the default for new layouts"));
1218 gtk_widget_show_all (config_increments_vbox
);
1221 /* -------------- The Library config page ----------------
1223 static GtkWidget
*library_newlib_entry
;
1226 config_library_apply (void)
1229 (&lib_newlib_config
, ghid_entry_get_text (library_newlib_entry
)))
1230 ghidgui
->config_modified
= TRUE
;
1234 config_library_tab_create (GtkWidget
* tab_vbox
)
1236 GtkWidget
*vbox
, *label
, *entry
;
1238 gtk_container_set_border_width (GTK_CONTAINER (tab_vbox
), 6);
1239 vbox
= ghid_category_vbox (tab_vbox
, _("Element Directories"),
1241 label
= gtk_label_new ("");
1242 gtk_label_set_use_markup (GTK_LABEL (label
), TRUE
);
1243 gtk_label_set_markup (GTK_LABEL (label
),
1245 ("<small>Enter a \""
1247 "\" separated list of custom top level\n"
1248 "element directories. For example:\n"
1249 "\t<b>~/gaf/pcb-elements"
1253 "/usr/local/pcb-elements</b>\n"
1254 "Elements should be organized into subdirectories below each\n"
1255 "top level directory. Restart program for changes to take effect."
1258 gtk_box_pack_start (GTK_BOX (vbox
), label
, FALSE
, FALSE
, 0);
1259 entry
= gtk_entry_new ();
1260 library_newlib_entry
= entry
;
1261 gtk_entry_set_text (GTK_ENTRY (entry
), lib_newlib_config
);
1262 gtk_box_pack_start (GTK_BOX (vbox
), entry
, FALSE
, FALSE
, 4);
1266 /* -------------- The Layers Group config page ----------------
1268 static GtkWidget
*config_groups_table
, *config_groups_vbox
, *config_groups_window
;
1270 static GtkWidget
*layer_entry
[MAX_LAYER
];
1271 static GtkWidget
*group_button
[MAX_LAYER
+ 2][MAX_LAYER
];
1274 static GtkWidget
*use_layer_default_button
;
1277 static gint config_layer_group
[MAX_LAYER
+ 2];
1279 static LayerGroupType layer_groups
, /* Working copy */
1280 *lg_monitor
; /* Keep track if our working copy */
1281 /* needs to be changed (new layout) */
1283 static gboolean groups_modified
, groups_holdoff
, layers_applying
;
1285 static gchar
*layer_info_text
[] = {
1286 N_("<h>Layer Names\n"),
1287 N_("You may enter layer names for the layers drawn on the screen.\n"
1288 "The special 'top side' and 'bottom side' are layers which\n"
1289 "will be printed out, so they must have in their group at least one\n"
1290 "of the other layers that are drawn on the screen.\n"),
1292 N_("<h>Layer Groups\n"),
1293 N_("Each layer on the screen may be in its own group which allows the\n"
1294 "maximum number of board layers. However, for boards with fewer\n"
1295 "layers, you may group layers together which will then print as a\n"
1296 "single layer on a printout. This allows a visual color distinction\n"
1297 "to be displayed on the screen for signal groups which will print as\n"
1298 "a single layer\n"),
1300 N_("For example, for a 4 layer board a useful layer group arrangement\n"
1301 "can be to have 3 screen displayed layers grouped into the same group\n"
1302 "as the 'top side' and 'bottom side' printout layers. Then\n"
1303 "groups such as signals, ground, and supply traces can be color\n"
1304 "coded on the screen while printing as a single layer. For this\n"
1305 "you would select buttons and enter names on the Setup page to\n"
1306 "structure four layer groups similar to this:\n"),
1339 config_layer_groups_radio_button_cb (GtkToggleButton
* button
, gpointer data
)
1341 gint layer
= GPOINTER_TO_INT (data
) >> 8;
1342 gint group
= GPOINTER_TO_INT (data
) & 0xff;
1344 if (!gtk_toggle_button_get_active (button
) || groups_holdoff
)
1346 config_layer_group
[layer
] = group
;
1347 groups_modified
= TRUE
;
1348 ghidgui
->config_modified
= TRUE
;
1351 /* Construct a layer group string. Follow logic in WritePCBDataHeader(),
1352 | but use g_string functions.
1355 make_layer_group_string (LayerGroupType
* lg
)
1358 gint group
, entry
, layer
;
1360 string
= g_string_new ("");
1362 for (group
= 0; group
< max_group
; group
++)
1364 if (lg
->Number
[group
] == 0)
1366 for (entry
= 0; entry
< lg
->Number
[group
]; entry
++)
1368 layer
= lg
->Entries
[group
][entry
];
1369 if (layer
== component_silk_layer
)
1370 string
= g_string_append (string
, "c");
1371 else if (layer
== solder_silk_layer
)
1372 string
= g_string_append (string
, "s");
1374 g_string_append_printf (string
, "%d", layer
+ 1);
1376 if (entry
!= lg
->Number
[group
] - 1)
1377 string
= g_string_append (string
, ",");
1379 if (group
!= max_group
- 1)
1380 string
= g_string_append (string
, ":");
1382 return g_string_free (string
, FALSE
); /* Don't free string->str */
1386 config_layers_apply (void)
1391 gint componentgroup
= 0, soldergroup
= 0;
1392 gboolean use_as_default
= FALSE
, layers_modified
= FALSE
;
1396 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
1397 (use_layer_default_button
));
1400 /* Get each layer name entry and dup if modified into the PCB layer names
1401 | and, if to use as default, the Settings layer names.
1403 for (i
= 0; i
< max_copper_layer
; ++i
)
1405 layer
= &PCB
->Data
->Layer
[i
];
1406 s
= ghid_entry_get_text (layer_entry
[i
]);
1407 if (dup_core_string (&layer
->Name
, s
))
1408 layers_modified
= TRUE
;
1410 if (use_as_default
&& dup_core_string (&Settings
.DefaultLayerName
[i
], s
))
1411 ghidgui
->config_modified
= TRUE
;
1414 /* Layer names can be changed from the menus and that can update the
1415 | config. So holdoff the loop.
1417 layers_applying
= TRUE
;
1418 if (layers_modified
)
1419 ghid_layer_buttons_update ();
1420 layers_applying
= FALSE
;
1422 if (groups_modified
) /* If any group radio buttons were toggled. */
1424 /* clear all entries and read layer by layer
1426 for (group
= 0; group
< max_group
; group
++)
1427 layer_groups
.Number
[group
] = 0;
1429 for (i
= 0; i
< max_copper_layer
+ 2; i
++)
1431 group
= config_layer_group
[i
] - 1;
1432 layer_groups
.Entries
[group
][layer_groups
.Number
[group
]++] = i
;
1434 if (i
== component_silk_layer
)
1435 componentgroup
= group
;
1436 else if (i
== solder_silk_layer
)
1437 soldergroup
= group
;
1440 /* do some cross-checking
1441 | top-side and bottom-side must be in different groups
1442 | top-side and bottom-side must not be the only one in the group
1444 if (layer_groups
.Number
[soldergroup
] <= 1
1445 || layer_groups
.Number
[componentgroup
] <= 1)
1448 ("Both, 'top side' and 'bottom side' layer must have at least\n"
1449 "\tone other layer in their group.\n"));
1452 else if (soldergroup
== componentgroup
)
1455 ("The 'top side' and 'bottom side' layers are not allowed\n"
1456 "\tto be in the same layer group #\n"));
1459 PCB
->LayerGroups
= layer_groups
;
1460 ghid_invalidate_all();
1461 groups_modified
= FALSE
;
1465 s
= make_layer_group_string (&PCB
->LayerGroups
);
1466 if (dup_core_string (&Settings
.Groups
, s
))
1468 ParseGroupString (Settings
.Groups
, &Settings
.LayerGroups
, max_copper_layer
);
1469 ghidgui
->config_modified
= TRUE
;
1476 config_layer_group_button_state_update (void)
1480 /* Set button active corresponding to layer group state.
1482 groups_holdoff
= TRUE
;
1483 for (g
= 0; g
< max_group
; g
++)
1484 for (i
= 0; i
< layer_groups
.Number
[g
]; i
++)
1486 /* printf("layer %d in group %d\n", layer_groups.Entries[g][i], g +1); */
1487 config_layer_group
[layer_groups
.Entries
[g
][i
]] = g
+ 1;
1488 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
1490 [layer_groups
.Entries
[g
][i
]][g
]),
1493 groups_holdoff
= FALSE
;
1497 layer_name_entry_cb(GtkWidget
*entry
, gpointer data
)
1499 gint i
= GPOINTER_TO_INT(data
);
1503 layer
= &PCB
->Data
->Layer
[i
];
1504 name
= ghid_entry_get_text(entry
);
1505 if (dup_core_string (&layer
->Name
, name
))
1506 ghid_layer_buttons_update();
1510 ghid_config_groups_changed(void)
1512 GtkWidget
*vbox
, *table
, *button
, *label
, *scrolled_window
;
1514 gchar buf
[32], *name
;
1517 if (!config_groups_vbox
)
1519 vbox
= config_groups_vbox
;
1521 if (config_groups_table
)
1522 gtk_widget_destroy(config_groups_table
);
1523 if (config_groups_window
)
1524 gtk_widget_destroy(config_groups_window
);
1526 config_groups_window
= scrolled_window
=
1527 gtk_scrolled_window_new (NULL
, NULL
);
1528 gtk_widget_set_size_request (scrolled_window
, 34, 408);
1529 gtk_container_set_border_width (GTK_CONTAINER (scrolled_window
), 3);
1530 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window
),
1531 GTK_POLICY_AUTOMATIC
, GTK_POLICY_ALWAYS
);
1532 gtk_box_pack_start (GTK_BOX (vbox
), scrolled_window
, TRUE
, TRUE
, 0);
1533 gtk_widget_show (scrolled_window
);
1536 table
= gtk_table_new (max_copper_layer
+ 3, max_group
+ 1, FALSE
);
1537 config_groups_table
= table
;
1538 gtk_table_set_row_spacings (GTK_TABLE (table
), 3);
1539 gtk_scrolled_window_add_with_viewport (
1540 GTK_SCROLLED_WINDOW (scrolled_window
), table
);
1541 gtk_widget_show (table
);
1543 layer_groups
= PCB
->LayerGroups
; /* working copy */
1544 lg_monitor
= &PCB
->LayerGroups
; /* So can know if PCB changes on us */
1546 label
= gtk_label_new (_("Group #"));
1547 gtk_table_attach_defaults (GTK_TABLE (table
), label
, 0, 1, 0, 1);
1548 gtk_misc_set_alignment (GTK_MISC (label
), 1.0, 0.5);
1550 for (i
= 1; i
< max_group
+ 1; ++i
)
1553 snprintf (buf
, sizeof (buf
), " %d", i
);
1555 snprintf (buf
, sizeof (buf
), "%d", i
);
1556 label
= gtk_label_new (buf
);
1557 gtk_table_attach_defaults (GTK_TABLE (table
), label
, i
, i
+ 1, 0, 1);
1560 /* Create a row of radio toggle buttons for layer. So each layer
1561 | can have an active radio button set for the group it needs to be in.
1563 for (layer
= 0; layer
< max_copper_layer
+ 2; ++layer
)
1565 if (layer
== component_silk_layer
)
1566 name
= _("top side");
1567 else if (layer
== solder_silk_layer
)
1568 name
= _("bottom side");
1570 name
= (gchar
*) UNKNOWN (PCB
->Data
->Layer
[layer
].Name
);
1572 if (layer
>= max_copper_layer
)
1574 label
= gtk_label_new (name
);
1575 gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5);
1576 gtk_table_attach_defaults (GTK_TABLE (table
), label
,
1577 0, 1, layer
+ 1, layer
+ 2);
1581 layer_entry
[layer
] = gtk_entry_new ();
1582 gtk_entry_set_text (GTK_ENTRY (layer_entry
[layer
]), name
);
1583 gtk_table_attach_defaults (GTK_TABLE (table
), layer_entry
[layer
],
1584 0, 1, layer
+ 1, layer
+ 2);
1585 g_signal_connect(G_OBJECT(layer_entry
[layer
]), "activate",
1586 G_CALLBACK(layer_name_entry_cb
), GINT_TO_POINTER(layer
));
1590 for (i
= 0; i
< max_group
; ++i
)
1592 snprintf (buf
, sizeof (buf
), "%2.2d", i
+1);
1593 button
= gtk_radio_button_new_with_label (group
, buf
);
1595 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button
), FALSE
);
1596 group
= gtk_radio_button_get_group (GTK_RADIO_BUTTON (button
));
1597 gtk_table_attach_defaults (GTK_TABLE (table
), button
,
1598 i
+ 1, i
+ 2, layer
+ 1, layer
+ 2);
1599 g_signal_connect (G_OBJECT (button
), "toggled",
1600 G_CALLBACK (config_layer_groups_radio_button_cb
),
1601 GINT_TO_POINTER ((layer
<< 8) | (i
+ 1)));
1602 group_button
[layer
][i
] = button
;
1605 gtk_widget_show_all(config_groups_vbox
);
1606 config_layer_group_button_state_update ();
1611 edit_layer_button_cb(GtkWidget
*widget
, gchar
*data
)
1615 if (PCB
->RatDraw
|| PCB
->SilkActive
)
1618 argv
= g_strsplit(data
, ",", -1);
1619 MoveLayerAction(2, argv
, 0, 0);
1624 config_layers_tab_create (GtkWidget
* tab_vbox
)
1626 GtkWidget
*tabs
, *vbox
, *vbox1
, *button
, *text
, *sep
;
1627 GtkWidget
*hbox
, *arrow
;
1630 tabs
= gtk_notebook_new ();
1631 gtk_box_pack_start (GTK_BOX (tab_vbox
), tabs
, TRUE
, TRUE
, 0);
1634 vbox
= ghid_notebook_page(tabs
, _("Change"), 0, 6);
1635 vbox1
= ghid_category_vbox(vbox
,
1636 _("Operations on currently selected layer:"),
1639 button
= gtk_button_new();
1640 arrow
= gtk_arrow_new(GTK_ARROW_UP
, GTK_SHADOW_ETCHED_IN
);
1641 gtk_container_add(GTK_CONTAINER(button
), arrow
);
1642 g_signal_connect(G_OBJECT(button
), (gchar
*)"clicked",
1643 G_CALLBACK(edit_layer_button_cb
), (gchar
*)"c,up");
1644 hbox
= gtk_hbox_new(FALSE
, 0);
1645 gtk_box_pack_start(GTK_BOX(vbox1
), hbox
, TRUE
, TRUE
, 0);
1646 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
1648 button
= gtk_button_new();
1649 arrow
= gtk_arrow_new(GTK_ARROW_DOWN
, GTK_SHADOW_ETCHED_IN
);
1650 gtk_container_add(GTK_CONTAINER(button
), arrow
);
1651 g_signal_connect(G_OBJECT(button
), (gchar
*)"clicked",
1652 G_CALLBACK(edit_layer_button_cb
), (gchar
*)"c,down");
1653 hbox
= gtk_hbox_new(FALSE
, 0);
1654 gtk_box_pack_start(GTK_BOX(vbox1
), hbox
, TRUE
, TRUE
, 0);
1655 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
1657 button
= gtk_button_new_from_stock(GTK_STOCK_DELETE
);
1658 g_signal_connect(G_OBJECT(button
), (gchar
*)"clicked",
1659 G_CALLBACK(edit_layer_button_cb
), (gchar
*)"c,-1");
1660 hbox
= gtk_hbox_new(FALSE
, 0);
1661 gtk_box_pack_start(GTK_BOX(vbox1
), hbox
, TRUE
, TRUE
, 0);
1662 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
1664 vbox1
= ghid_category_vbox(vbox
,
1665 _("Add new layer above currently selected layer:"),
1667 button
= gtk_button_new_from_stock(GTK_STOCK_ADD
);
1668 g_signal_connect(G_OBJECT(button
), (gchar
*)"clicked",
1669 G_CALLBACK(edit_layer_button_cb
), (gchar
*)"-1,c");
1670 hbox
= gtk_hbox_new(FALSE
, 0);
1671 gtk_box_pack_start(GTK_BOX(vbox1
), hbox
, TRUE
, TRUE
, 0);
1672 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
1675 vbox
= ghid_notebook_page (tabs
, _("Groups"), 0, 6);
1676 config_groups_vbox
= gtk_vbox_new(FALSE
, 0);
1677 gtk_box_pack_start(GTK_BOX(vbox
), config_groups_vbox
, FALSE
, FALSE
, 0);
1678 ghid_config_groups_changed();
1680 sep
= gtk_hseparator_new ();
1681 gtk_box_pack_start (GTK_BOX (vbox
), sep
, FALSE
, FALSE
, 4);
1684 ghid_check_button_connected (vbox
, &use_layer_default_button
, FALSE
,
1685 TRUE
, FALSE
, FALSE
, 8, NULL
, NULL
,
1686 ("Use these layer settings as the default for new layouts"));
1691 vbox
= ghid_notebook_page (tabs
, _("Info"), 0, 6);
1693 text
= ghid_scrolled_text_view (vbox
, NULL
,
1694 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1695 for (i
= 0; i
< sizeof (layer_info_text
) / sizeof (gchar
*); ++i
)
1696 ghid_text_view_append (text
, _(layer_info_text
[i
]));
1701 ghid_config_layer_name_update (gchar
* name
, gint layer
)
1703 if (!config_window
|| layers_applying
|| !name
)
1705 gtk_entry_set_text (GTK_ENTRY (layer_entry
[layer
]), name
);
1707 /* If we get a config layer name change because a new PCB is loaded
1708 | or new layout started, need to change our working layer group copy.
1710 if (lg_monitor
!= &PCB
->LayerGroups
)
1712 layer_groups
= PCB
->LayerGroups
;
1713 lg_monitor
= &PCB
->LayerGroups
;
1714 config_layer_group_button_state_update ();
1715 groups_modified
= FALSE
;
1719 /* -------------- The Colors config page ----------------
1721 static GtkWidget
*config_colors_vbox
,
1722 *config_colors_tab_vbox
,
1723 *config_colors_save_button
,
1724 *config_color_file_label
, *config_color_warn_label
;
1726 static void config_colors_tab_create (GtkWidget
* tab_vbox
);
1728 static gboolean config_colors_modified
;
1731 config_color_file_set_label (void)
1736 name
= g_strdup ("defaults");
1738 name
= g_path_get_basename (color_file
);
1740 str
= g_strdup_printf (_("Current colors loaded: <b>%s</b>"), name
);
1741 gtk_label_set_markup (GTK_LABEL (config_color_file_label
), str
);
1747 config_color_defaults_cb (gpointer data
)
1753 for (list
= config_color_list
; list
; list
= list
->next
)
1755 cc
= (ConfigColor
*) list
->data
;
1756 ha
= cc
->attributes
;
1757 dup_core_string ((char **) ha
->value
, ha
->default_val
.str_value
);
1758 cc
->color_is_mapped
= FALSE
;
1759 ghid_set_special_colors (ha
);
1762 dup_string (&color_file
, "");
1763 ghidgui
->config_modified
= TRUE
;
1765 gtk_widget_set_sensitive (config_colors_save_button
, FALSE
);
1766 gtk_widget_set_sensitive (config_color_warn_label
, FALSE
);
1767 config_color_file_set_label ();
1768 config_colors_modified
= FALSE
;
1770 ghid_layer_buttons_color_update ();
1772 /* Receate the colors config page to pick up new colors.
1774 gtk_widget_destroy (config_colors_vbox
);
1775 config_colors_tab_create (config_colors_tab_vbox
);
1777 ghid_invalidate_all();
1781 config_color_load_cb (gpointer data
)
1783 gchar
*path
, *dir
= g_strdup (color_dir
);
1785 path
= ghid_dialog_file_select_open (_("Load Color File"), &dir
, NULL
);
1788 config_colors_read (path
);
1789 dup_string (&color_file
, path
);
1790 ghidgui
->config_modified
= TRUE
;
1792 gtk_widget_set_sensitive (config_colors_save_button
, FALSE
);
1793 gtk_widget_set_sensitive (config_color_warn_label
, FALSE
);
1794 config_color_file_set_label ();
1795 config_colors_modified
= FALSE
;
1800 /* Receate the colors config page to pick up new colors.
1802 gtk_widget_destroy (config_colors_vbox
);
1803 config_colors_tab_create (config_colors_tab_vbox
);
1805 ghid_layer_buttons_color_update ();
1806 ghid_invalidate_all();
1810 config_color_save_cb (gpointer data
)
1812 gchar
*name
, *path
, *dir
= g_strdup (color_dir
);
1815 ghid_dialog_file_select_save (_("Save Color File"), &dir
, NULL
, NULL
);
1818 name
= g_path_get_basename (path
);
1819 if (!strcmp (name
, "default"))
1820 ghid_dialog_message (_
1821 ("Sorry, not overwriting the default color file!"));
1824 config_colors_write (path
);
1825 dup_string (&color_file
, path
);
1826 ghidgui
->config_modified
= TRUE
;
1828 gtk_widget_set_sensitive (config_colors_save_button
, FALSE
);
1829 gtk_widget_set_sensitive (config_color_warn_label
, FALSE
);
1830 config_color_file_set_label ();
1831 config_colors_modified
= FALSE
;
1840 config_color_set_cb (GtkWidget
* button
, ConfigColor
* cc
)
1843 HID_Attribute
*ha
= cc
->attributes
;
1846 gtk_color_button_get_color (GTK_COLOR_BUTTON (button
), &new_color
);
1847 str
= ghid_get_color_name (&new_color
);
1848 ghid_map_color_string (str
, &cc
->color
);
1849 *(char **) ha
->value
= str
;
1850 /* g_free(str); Memory leak */
1852 config_colors_modified
= TRUE
;
1853 gtk_widget_set_sensitive (config_colors_save_button
, TRUE
);
1854 gtk_widget_set_sensitive (config_color_warn_label
, TRUE
);
1856 ghid_set_special_colors (ha
);
1857 ghid_layer_buttons_color_update ();
1858 ghid_invalidate_all();
1862 config_color_button_create (GtkWidget
* box
, ConfigColor
* cc
)
1864 GtkWidget
*button
, *hbox
, *label
;
1865 HID_Attribute
*ha
= cc
->attributes
;
1868 hbox
= gtk_hbox_new (FALSE
, 6);
1869 gtk_box_pack_start (GTK_BOX (box
), hbox
, FALSE
, FALSE
, 0);
1871 if (!cc
->color_is_mapped
)
1872 ghid_map_color_string (*(char **) ha
->value
, &cc
->color
);
1873 cc
->color_is_mapped
= TRUE
;
1875 title
= g_strdup_printf (_("PCB %s Color"), ha
->name
);
1876 button
= gtk_color_button_new_with_color (&cc
->color
);
1877 gtk_color_button_set_title (GTK_COLOR_BUTTON (button
), title
);
1880 gtk_box_pack_start (GTK_BOX (hbox
), button
, FALSE
, FALSE
, 0);
1881 label
= gtk_label_new (ha
->name
);
1882 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1883 g_signal_connect (G_OBJECT (button
), "color-set",
1884 G_CALLBACK (config_color_set_cb
), cc
);
1888 config_colors_tab_create (GtkWidget
* tab_vbox
)
1890 GtkWidget
*scrolled_vbox
, *vbox
, *hbox
, *expander
, *sep
;
1894 vbox
= gtk_vbox_new (FALSE
, 0);
1895 gtk_box_pack_start (GTK_BOX (tab_vbox
), vbox
, TRUE
, TRUE
, 0);
1896 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 6);
1898 config_colors_vbox
= vbox
; /* can be destroyed if color file loaded */
1899 config_colors_tab_vbox
= tab_vbox
;
1901 scrolled_vbox
= ghid_scrolled_vbox (config_colors_vbox
, NULL
,
1902 GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
1904 /* ---- Main colors ---- */
1905 expander
= gtk_expander_new (_("Main colors"));
1906 gtk_box_pack_start (GTK_BOX (scrolled_vbox
), expander
, FALSE
, FALSE
, 2);
1907 vbox
= gtk_vbox_new (FALSE
, 0);
1908 gtk_container_add (GTK_CONTAINER (expander
), vbox
);
1909 vbox
= ghid_category_vbox (vbox
, NULL
, 0, 2, TRUE
, FALSE
);
1911 for (list
= config_color_list
; list
; list
= list
->next
)
1913 cc
= (ConfigColor
*) list
->data
;
1914 if (cc
->type
!= MISC_COLOR
)
1916 config_color_button_create (vbox
, cc
);
1919 /* ---- Layer colors ---- */
1920 expander
= gtk_expander_new (_("Layer colors"));
1921 gtk_box_pack_start (GTK_BOX (scrolled_vbox
), expander
, FALSE
, FALSE
, 2);
1922 vbox
= gtk_vbox_new (FALSE
, 0);
1923 gtk_container_add (GTK_CONTAINER (expander
), vbox
);
1924 vbox
= ghid_category_vbox (vbox
, NULL
, 0, 2, TRUE
, FALSE
);
1926 for (list
= config_color_list
; list
; list
= list
->next
)
1928 cc
= (ConfigColor
*) list
->data
;
1929 if (cc
->type
!= LAYER_COLOR
)
1931 config_color_button_create (vbox
, cc
);
1934 /* ---- Selected colors ---- */
1935 expander
= gtk_expander_new (_("Selected colors"));
1936 gtk_box_pack_start (GTK_BOX (scrolled_vbox
), expander
, FALSE
, FALSE
, 2);
1937 vbox
= gtk_vbox_new (FALSE
, 0);
1938 gtk_container_add (GTK_CONTAINER (expander
), vbox
);
1939 vbox
= ghid_category_vbox (vbox
, NULL
, 0, 2, TRUE
, FALSE
);
1941 for (list
= config_color_list
; list
; list
= list
->next
)
1943 cc
= (ConfigColor
*) list
->data
;
1944 if (cc
->type
!= MISC_SELECTED_COLOR
)
1946 config_color_button_create (vbox
, cc
);
1948 sep
= gtk_hseparator_new ();
1949 gtk_box_pack_start (GTK_BOX (vbox
), sep
, FALSE
, FALSE
, 2);
1950 for (list
= config_color_list
; list
; list
= list
->next
)
1952 cc
= (ConfigColor
*) list
->data
;
1953 if (cc
->type
!= LAYER_SELECTED_COLOR
)
1955 config_color_button_create (vbox
, cc
);
1958 config_color_warn_label
= gtk_label_new ("");
1959 gtk_label_set_use_markup (GTK_LABEL (config_color_warn_label
), TRUE
);
1960 gtk_label_set_markup (GTK_LABEL (config_color_warn_label
),
1961 _("<b>Warning:</b> unsaved color changes will be lost"
1962 " at program exit."));
1963 gtk_box_pack_start (GTK_BOX (config_colors_vbox
), config_color_warn_label
,
1966 hbox
= gtk_hbox_new (FALSE
, 0);
1967 gtk_box_pack_start (GTK_BOX (config_colors_vbox
), hbox
, FALSE
, FALSE
, 6);
1969 config_color_file_label
= gtk_label_new ("");
1970 gtk_label_set_use_markup (GTK_LABEL (config_color_file_label
), TRUE
);
1971 config_color_file_set_label ();
1972 gtk_box_pack_start (GTK_BOX (hbox
), config_color_file_label
,
1975 ghid_button_connected (hbox
, NULL
, FALSE
, FALSE
, FALSE
, 4,
1976 config_color_load_cb
, NULL
, _("Load"));
1977 ghid_button_connected (hbox
, &config_colors_save_button
,
1978 FALSE
, FALSE
, FALSE
, 4,
1979 config_color_save_cb
, NULL
, _("Save"));
1980 ghid_button_connected (hbox
, NULL
, FALSE
, FALSE
, FALSE
, 4,
1981 config_color_defaults_cb
, NULL
, _("Defaults"));
1983 gtk_widget_set_sensitive (config_colors_save_button
,
1984 config_colors_modified
);
1985 gtk_widget_set_sensitive (config_color_warn_label
, config_colors_modified
);
1986 gtk_widget_show_all (config_colors_vbox
);
1990 /* --------------- The main config page -----------------
1999 static GtkNotebook
*config_notebook
;
2002 config_page_create (GtkTreeStore
* tree
, GtkTreeIter
* iter
,
2003 GtkNotebook
* notebook
)
2008 vbox
= gtk_vbox_new (FALSE
, 0);
2009 gtk_notebook_append_page (notebook
, vbox
, NULL
);
2010 page
= gtk_notebook_get_n_pages (notebook
) - 1;
2011 gtk_tree_store_set (tree
, iter
, CONFIG_PAGE_COLUMN
, page
, -1);
2016 ghid_config_handle_units_changed (void)
2018 gchar
*text
= pcb_g_strdup_printf ("<b>%s</b>",
2019 Settings
.grid_unit
->in_suffix
);
2020 ghid_set_cursor_position_labels ();
2021 gtk_label_set_markup (GTK_LABEL (ghidgui
->grid_units_label
), text
);
2024 if (config_sizes_vbox
)
2026 gtk_widget_destroy (config_sizes_vbox
);
2027 config_sizes_vbox
= NULL
;
2028 config_sizes_tab_create (config_sizes_tab_vbox
);
2030 if (config_increments_vbox
)
2032 gtk_widget_destroy (config_increments_vbox
);
2033 config_increments_vbox
= NULL
;
2034 config_increments_tab_create (config_increments_tab_vbox
);
2036 ghidgui
->config_modified
= TRUE
;
2040 ghid_config_text_scale_update (void)
2043 gtk_spin_button_set_value (GTK_SPIN_BUTTON (config_text_spin_button
),
2044 (gdouble
) Settings
.TextScale
);
2048 config_close_cb (gpointer data
)
2050 /* Config pages may need to check for modified entries, use as default
2051 | options, etc when the config window is closed.
2053 config_sizes_apply ();
2054 config_layers_apply ();
2055 config_library_apply ();
2056 config_general_apply ();
2058 config_sizes_vbox
= NULL
;
2059 config_increments_vbox
= NULL
;
2061 config_groups_vbox
= config_groups_table
= NULL
;
2062 config_groups_window
= NULL
;
2064 gtk_widget_destroy (config_window
);
2065 config_window
= NULL
;
2069 config_destroy_cb (gpointer data
)
2071 config_sizes_vbox
= NULL
;
2072 config_increments_vbox
= NULL
;
2073 config_groups_vbox
= config_groups_table
= NULL
;
2074 config_groups_window
= NULL
;
2075 gtk_widget_destroy (config_window
);
2076 config_window
= NULL
;
2080 config_selection_changed_cb (GtkTreeSelection
* selection
, gpointer data
)
2083 GtkTreeModel
*model
;
2086 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
2088 gtk_tree_model_get (model
, &iter
, CONFIG_PAGE_COLUMN
, &page
, -1);
2089 gtk_notebook_set_current_page (config_notebook
, page
);
2093 ghid_config_window_show (void)
2095 GtkWidget
*widget
, *main_vbox
, *vbox
, *config_hbox
, *hbox
;
2096 GtkWidget
*scrolled
;
2098 GtkTreeStore
*model
;
2099 GtkTreeView
*treeview
;
2101 GtkCellRenderer
*renderer
;
2102 GtkTreeViewColumn
*column
;
2103 GtkTreeSelection
*select
;
2107 gtk_window_present (GTK_WINDOW (config_window
));
2111 config_window
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
2112 g_signal_connect (G_OBJECT (config_window
), "delete_event",
2113 G_CALLBACK (config_destroy_cb
), NULL
);
2115 gtk_window_set_title (GTK_WINDOW (config_window
), _("PCB Preferences"));
2116 gtk_window_set_wmclass (GTK_WINDOW (config_window
), "Pcb_Conf", "PCB");
2117 gtk_container_set_border_width (GTK_CONTAINER (config_window
), 2);
2119 config_hbox
= gtk_hbox_new (FALSE
, 4);
2120 gtk_container_add (GTK_CONTAINER (config_window
), config_hbox
);
2122 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
2123 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
2124 GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
2125 gtk_box_pack_start (GTK_BOX (config_hbox
), scrolled
, FALSE
, FALSE
, 0);
2127 main_vbox
= gtk_vbox_new (FALSE
, 4);
2128 gtk_box_pack_start (GTK_BOX (config_hbox
), main_vbox
, TRUE
, TRUE
, 0);
2130 widget
= gtk_notebook_new ();
2131 gtk_box_pack_start (GTK_BOX (main_vbox
), widget
, TRUE
, TRUE
, 0);
2132 config_notebook
= GTK_NOTEBOOK (widget
);
2133 gtk_notebook_set_show_tabs (config_notebook
, FALSE
);
2135 model
= gtk_tree_store_new (N_CONFIG_COLUMNS
, G_TYPE_STRING
, G_TYPE_INT
);
2139 gtk_tree_store_append (model
, &iter
, NULL
);
2140 gtk_tree_store_set (model
, &iter
, CONFIG_NAME_COLUMN
, _("General"), -1);
2141 vbox
= config_page_create (model
, &iter
, config_notebook
);
2142 config_general_tab_create (vbox
);
2146 gtk_tree_store_append (model
, &iter
, NULL
);
2147 gtk_tree_store_set (model
, &iter
, CONFIG_NAME_COLUMN
, _("Sizes"), -1);
2148 vbox
= config_page_create (model
, &iter
, config_notebook
);
2149 config_sizes_tab_create (vbox
);
2151 /* -- Increments -- */
2152 gtk_tree_store_append (model
, &iter
, NULL
);
2153 gtk_tree_store_set (model
, &iter
, CONFIG_NAME_COLUMN
, _("Increments"), -1);
2154 vbox
= config_page_create (model
, &iter
, config_notebook
);
2155 config_increments_tab_create (vbox
);
2158 gtk_tree_store_append (model
, &iter
, NULL
);
2159 gtk_tree_store_set (model
, &iter
, CONFIG_NAME_COLUMN
, _("Library"), -1);
2160 vbox
= config_page_create (model
, &iter
, config_notebook
);
2161 config_library_tab_create (vbox
);
2163 /* -- Layer names and groups -- */
2164 gtk_tree_store_append (model
, &iter
, NULL
);
2165 gtk_tree_store_set (model
, &iter
, CONFIG_NAME_COLUMN
, _("Layers"), -1);
2166 vbox
= config_page_create (model
, &iter
, config_notebook
);
2167 config_layers_tab_create (vbox
);
2171 gtk_tree_store_append (model
, &iter
, NULL
);
2172 gtk_tree_store_set (model
, &iter
, CONFIG_NAME_COLUMN
, _("Colors"), -1);
2173 vbox
= config_page_create (model
, &iter
, config_notebook
);
2174 config_colors_tab_create (vbox
);
2177 /* Create the tree view
2180 GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (model
)));
2181 g_object_unref (G_OBJECT (model
)); /* Don't need the model anymore */
2183 renderer
= gtk_cell_renderer_text_new ();
2184 column
= gtk_tree_view_column_new_with_attributes (NULL
, renderer
,
2188 gtk_tree_view_append_column (treeview
, column
);
2189 gtk_container_add (GTK_CONTAINER (scrolled
), GTK_WIDGET (treeview
));
2192 select
= gtk_tree_view_get_selection (treeview
);
2193 gtk_tree_selection_set_mode (select
, GTK_SELECTION_SINGLE
);
2194 g_signal_connect (G_OBJECT (select
), "changed",
2195 G_CALLBACK (config_selection_changed_cb
), NULL
);
2198 hbox
= gtk_hbutton_box_new ();
2199 gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox
), GTK_BUTTONBOX_END
);
2200 gtk_box_set_spacing (GTK_BOX (hbox
), 5);
2201 gtk_box_pack_start (GTK_BOX (main_vbox
), hbox
, FALSE
, FALSE
, 0);
2203 button
= gtk_button_new_from_stock (GTK_STOCK_OK
);
2204 gtk_widget_set_can_default (button
, TRUE
);
2205 g_signal_connect (G_OBJECT (button
), "clicked",
2206 G_CALLBACK (config_close_cb
), NULL
);
2207 gtk_box_pack_start (GTK_BOX (hbox
), button
, TRUE
, TRUE
, 0);
2208 gtk_widget_grab_default (button
);
2210 gtk_widget_show_all (config_window
);