missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / x_attribedit.c
blob1bba2dad08240fe50e14e4291ba15ad8099336ff
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /*! \todo STILL NEED to clean up line lengths in aa and tr
22 #include <config.h>
24 #include <stdio.h>
25 #ifdef HAVE_STDLIB_H
26 #include <stdlib.h>
27 #endif
28 #ifdef HAVE_STRING_H
29 #include <string.h>
30 #endif
32 #include "gschem.h"
34 /***************** Start of Attrib Edit dialog box ********************/
35 /*! \section attrib-edit-dialog-box Atrib Edit Dialog Box */
37 /*! \todo Finish function documentation!!!
38 * \brief
39 * \par Function Documentation
42 gint option_menu_get_history (GtkOptionMenu *option_menu)
44 GtkWidget *active_widget;
46 g_return_val_if_fail (GTK_IS_OPTION_MENU (option_menu), -1);
48 active_widget = gtk_menu_get_active (GTK_MENU (option_menu->menu));
50 if (active_widget)
51 return g_list_index (GTK_MENU_SHELL (option_menu->menu)->children,
52 active_widget);
53 else
54 return -1;
57 /*! \todo Finish function documentation!!!
58 * \brief
59 * \par Function Documentation
62 void attrib_edit_dialog_ok(GtkWidget * w, GschemToplevel *w_current)
64 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
65 const char *value, *label;
66 char *newtext;
67 GtkEntry *value_entry, *name_entry;
68 GtkWidget *visbutton, *show_options;
69 GtkWidget *addtocompsbutton, *addtonetsbutton, *addtoallbutton;
70 GtkWidget *overwritebutton;
71 OBJECT *attribptr;
72 OBJECT *object;
73 GList *s_current = NULL;
74 OBJECT *a_current;
75 GList *a_iter;
76 int vis, show;
77 int invocation_flag;
78 int nsel=0, addto=0, replace=0, addmask=0;
79 int option_index;
80 gint wx, wy;
82 value_entry =
83 g_object_get_data (G_OBJECT (w_current->aewindow), "value_entry");
84 name_entry =
85 g_object_get_data (G_OBJECT (w_current->aewindow), "attrib_combo_entry");
86 visbutton =
87 g_object_get_data (G_OBJECT (w_current->aewindow), "visbutton");
88 show_options =
89 g_object_get_data (G_OBJECT (w_current->aewindow), "show_options");
91 value = gtk_entry_get_text(value_entry);
92 label = gtk_entry_get_text(name_entry);
93 newtext = g_strconcat (label, "=", value, NULL);
95 if (!x_dialog_validate_attribute(GTK_WINDOW(w_current->aewindow), newtext))
97 g_free(newtext);
98 return;
101 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(visbutton)))
102 vis = VISIBLE;
103 else
104 vis = INVISIBLE;
106 option_index = option_menu_get_history(GTK_OPTION_MENU (show_options));
107 switch(option_index) {
108 case(0):
109 show = SHOW_VALUE;
110 break;
112 case(1):
113 show = SHOW_NAME;
114 break;
116 case(2):
117 show = SHOW_NAME_VALUE;
118 break;
120 default:
121 fprintf(stderr, _("Got invalid show option; defaulting to show both\n"));
122 show = SHOW_NAME_VALUE;
123 break;
126 attribptr =
127 g_object_get_data (G_OBJECT (w_current->aewindow), "attrib");
128 if (!attribptr) {
129 OBJECT *new = NULL;
131 s_current = geda_list_get_glist( toplevel->page_current->selection_list );
132 while (s_current != NULL) {
133 object = (OBJECT *)s_current->data;
134 if (object == NULL) {
135 fprintf(stderr, _("ERROR: NULL object!\n"));
136 exit(-1);
138 if (!object->attached_to) {
139 nsel++;
141 s_current = g_list_next(s_current);
143 s_current = geda_list_get_glist( toplevel->page_current->selection_list );
144 if (nsel > 1) {
145 gboolean changed = FALSE;
147 addtoallbutton =
148 g_object_get_data (G_OBJECT (w_current->aewindow), "addtoallbutton");
150 addtocompsbutton =
151 g_object_get_data (G_OBJECT (w_current->aewindow), "addtocompsbutton");
153 addtonetsbutton =
154 g_object_get_data (G_OBJECT (w_current->aewindow), "addtonetsbutton");
156 overwritebutton =
157 g_object_get_data (G_OBJECT (w_current->aewindow), "overwritebutton");
159 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overwritebutton))) {
160 replace = 1;
161 } else {
162 replace = 0;
165 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(addtoallbutton))) {
166 addto = 7;
168 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(addtocompsbutton))) {
169 addto = 2;
171 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(addtonetsbutton))) {
172 addto = 1;
175 while (s_current != NULL) {
176 gboolean replaced;
178 object = (OBJECT *) s_current->data;
179 if (object && !object->attached_to && object->type != OBJ_TEXT ) {
180 addmask = 4;
181 if (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER) {
182 addmask = 2;
184 if (object->type == OBJ_NET) {
185 addmask = 1;
187 replaced = FALSE;
188 if (addmask & addto) {
189 a_iter = object->attribs;
190 if (replace) {
191 while (a_iter != NULL) {
192 a_current = a_iter->data;
193 const gchar *str = o_text_get_string (toplevel, a_current);
194 if (str) {
195 if (!strncmp (str, newtext, strchr (newtext, '=') - newtext)) {
196 o_text_change(w_current, a_current, newtext, vis, show);
197 replaced = TRUE;
198 changed = TRUE;
201 a_iter = g_list_next (a_iter);
204 if (!replaced) {
205 o_attrib_add_attrib(w_current, newtext, vis, show, object);
206 changed = TRUE;
210 s_current = g_list_next (s_current);
212 if (changed) {
213 gschem_toplevel_page_content_changed (w_current,
214 toplevel->page_current);
215 o_undo_savestate_old (w_current, UNDO_ALL, NULL);
217 /* shouldn't be reached */
218 } else {
219 object = o_select_return_first_object(w_current);
220 new = o_attrib_add_attrib(w_current, newtext, vis, show, object);
222 invocation_flag =
223 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (w_current->aewindow),
224 "invocation_flag"));
225 wx =
226 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (w_current->aewindow),
227 "position_wx"));
228 wy =
229 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (w_current->aewindow),
230 "position_wy"));
232 #if DEBUG
233 printf("invocation flag: %d\n", invocation_flag);
234 #endif
235 if (invocation_flag == FROM_HOTKEY
236 && wx != -1 && wy != -1) {
237 o_invalidate (w_current, new);
238 new->text->x = wx;
239 new->text->y = wy;
240 o_text_recreate(toplevel, new);
242 gschem_toplevel_page_content_changed (w_current, toplevel->page_current);
243 o_undo_savestate_old (w_current, UNDO_ALL, _("Add Attribute"));
245 } else {
246 o_text_change(w_current, attribptr, newtext, vis, show);
247 gschem_toplevel_page_content_changed (w_current, toplevel->page_current);
248 o_undo_savestate_old (w_current, UNDO_ALL, _("Edit Attribute"));
250 gtk_grab_remove(w_current->aewindow);
251 gtk_widget_destroy(w_current->aewindow);
252 w_current->aewindow = NULL;
253 g_free(newtext);
256 /*! \brief Response function for the attribute add/edit dialog
257 * \par Function Description
258 * This function catches the user response for the add and edit
259 * attribute dialog.
261 void attribute_edit_dialog_response(GtkWidget *w, gint response,
262 GschemToplevel *w_current)
264 switch(response) {
265 case GTK_RESPONSE_APPLY:
266 attrib_edit_dialog_ok(NULL, w_current);
267 break;
268 case GTK_RESPONSE_REJECT:
269 case GTK_RESPONSE_DELETE_EVENT:
270 gtk_grab_remove(w_current->aewindow);
271 gtk_widget_destroy(w_current->aewindow);
272 w_current->aewindow = NULL;
273 break;
274 default:
275 printf("attrib_edit_dialog_response(): strange signal %d\n", response);
277 /* clean up */
282 /*! \brief Create the attribute add/edit dialog
283 * \par Function Description
284 * This function creates the single attribute edit dialog.
286 void attrib_edit_dialog (GschemToplevel *w_current, OBJECT *attr_obj, int flag)
288 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
289 GtkWidget *aewindow;
290 GtkWidget *vbox, *label, *table, *alignment;
291 GtkWidget *show_options;
292 GtkWidget *show_options_menu;
293 GtkWidget *glade_menuitem;
294 GtkWidget *attrib_combo_box_entry;
295 GtkWidget *attrib_combo_entry;
296 GtkWidget *value_entry;
297 GtkWidget *visbutton;
298 GSList *hbox2_group = NULL;
299 GtkWidget *addtoallbutton;
300 GtkWidget *addtocompsbutton;
301 GtkWidget *addtonetsbutton;
302 GtkWidget *overwritebutton;
303 GtkEntryCompletion *attrib_combo_entry_completion;
305 /* gschem specific */
306 GList *s_current = NULL;
307 char* string = NULL;
308 int nsel=0, i, len;
309 char *name = NULL;
310 char *val = NULL;
311 OBJECT *attrib = NULL;
312 gint wx, wy;
314 /* gschem specific */
315 if (w_current->aewindow)
316 return;
318 /* gschem specific: What do we count here? (Werner) */
319 for (s_current = geda_list_get_glist( toplevel->page_current->selection_list );
320 s_current != NULL;
321 s_current = g_list_next(s_current)) {
322 if (!((OBJECT *) s_current->data)->attached_to) {
323 nsel++;
327 aewindow = gschem_dialog_new_with_buttons(_("Single Attribute Editor"),
328 GTK_WINDOW(w_current->main_window),
329 GTK_DIALOG_MODAL,
330 "singleattrib", w_current,
331 GTK_STOCK_CANCEL,
332 GTK_RESPONSE_REJECT,
333 GTK_STOCK_OK,
334 GTK_RESPONSE_APPLY,
335 NULL);
336 /* Set the alternative button order (ok, cancel, help) for other systems */
337 gtk_dialog_set_alternative_button_order(GTK_DIALOG(aewindow),
338 GTK_RESPONSE_APPLY,
339 GTK_RESPONSE_REJECT,
340 -1);
342 g_signal_connect (G_OBJECT (aewindow), "response",
343 G_CALLBACK (attribute_edit_dialog_response),
344 w_current);
346 gtk_window_set_position (GTK_WINDOW (aewindow), GTK_WIN_POS_MOUSE);
348 gtk_dialog_set_default_response(GTK_DIALOG(aewindow),
349 GTK_RESPONSE_APPLY);
351 vbox = GTK_DIALOG(aewindow)->vbox;
352 gtk_container_set_border_width(GTK_CONTAINER(aewindow),
353 DIALOG_BORDER_SPACING);
354 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
356 if (attr_obj)
357 label = gtk_label_new(_("<b>Edit Attribute</b>"));
358 else
359 label = gtk_label_new(_("<b>Add Attribute</b>"));
360 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
361 gtk_misc_set_alignment(GTK_MISC(label),0,0);
362 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
364 alignment = gtk_alignment_new(0,0,1,1);
365 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
366 DIALOG_INDENTATION, 0);
367 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
369 table = gtk_table_new (3, 2, FALSE);
370 gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
371 gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
372 gtk_container_add (GTK_CONTAINER (alignment), table);
374 /* Name selection */
375 label = gtk_label_new (_("Name:"));
376 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
377 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
378 (GtkAttachOptions) (GTK_FILL),
379 (GtkAttachOptions) (GTK_FILL), 0, 0);
381 attrib_combo_box_entry = gtk_combo_box_entry_new_text ();
382 attrib_combo_entry = gtk_bin_get_child(GTK_BIN(attrib_combo_box_entry));
383 gtk_table_attach (GTK_TABLE (table), attrib_combo_box_entry, 1, 2, 0, 1,
384 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
385 (GtkAttachOptions) (0), 0, 0);
386 g_object_ref (attrib_combo_entry);
387 g_object_set_data_full (G_OBJECT (aewindow),
388 "attrib_combo_entry", attrib_combo_entry,
389 (GtkDestroyNotify) g_object_unref);
391 /* Value entry */
392 label = gtk_label_new (_("Value:"));
393 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
394 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
395 (GtkAttachOptions) (GTK_FILL),
396 (GtkAttachOptions) (0), 0, 0);
398 value_entry = gtk_entry_new ();
399 g_object_ref (value_entry);
400 g_object_set_data_full (G_OBJECT (aewindow), "value_entry", value_entry,
401 (GtkDestroyNotify) g_object_unref);
402 gtk_table_attach (GTK_TABLE (table), value_entry, 1, 2, 1, 2,
403 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
404 (GtkAttachOptions) (0), 0, 0);
405 gtk_entry_set_activates_default(GTK_ENTRY(value_entry), TRUE);
407 /* Visibility */
408 visbutton = gtk_check_button_new_with_label (_("Visible"));
409 g_object_ref (visbutton);
410 g_object_set_data_full (G_OBJECT (aewindow), "visbutton", visbutton,
411 (GtkDestroyNotify) g_object_unref);
413 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (visbutton), TRUE);
414 gtk_table_attach (GTK_TABLE (table), visbutton, 0, 1, 2, 3,
415 (GtkAttachOptions) (GTK_FILL),
416 (GtkAttachOptions) (0), 0, 0);
418 show_options = gtk_option_menu_new ();
419 g_object_ref (show_options);
420 g_object_set_data_full (G_OBJECT (aewindow), "show_options", show_options,
421 (GtkDestroyNotify) g_object_unref);
422 gtk_widget_show (show_options);
423 gtk_table_attach (GTK_TABLE (table), show_options, 1, 2, 2, 3,
424 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
425 (GtkAttachOptions) (0), 0, 0);
426 show_options_menu = gtk_menu_new ();
427 glade_menuitem = gtk_menu_item_new_with_label (_("Show Value Only"));
428 gtk_menu_shell_append (GTK_MENU_SHELL (show_options_menu), glade_menuitem);
429 glade_menuitem = gtk_menu_item_new_with_label (_("Show Name Only"));
430 gtk_menu_shell_append (GTK_MENU_SHELL (show_options_menu), glade_menuitem);
431 glade_menuitem = gtk_menu_item_new_with_label (_("Show Name & Value"));
432 gtk_menu_shell_append (GTK_MENU_SHELL (show_options_menu), glade_menuitem);
433 gtk_option_menu_set_menu (GTK_OPTION_MENU (show_options), show_options_menu);
434 gtk_option_menu_set_history (GTK_OPTION_MENU (show_options), 0);
436 if (nsel > 1) { /* gschem specific */
438 label = gtk_label_new(_("<b>Attach Options</b>"));
439 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
440 gtk_misc_set_alignment(GTK_MISC(label),0,0);
441 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
443 alignment = gtk_alignment_new(0,0,1,1);
444 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
445 DIALOG_INDENTATION, 0);
446 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
448 table = gtk_table_new (2, 3, FALSE);
449 gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
450 gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
451 gtk_container_add (GTK_CONTAINER (alignment), table);
453 addtoallbutton = gtk_radio_button_new_with_label (hbox2_group, _("All"));
454 hbox2_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (addtoallbutton));
455 g_object_ref (addtoallbutton);
456 g_object_set_data_full (G_OBJECT (aewindow), "addtoallbutton", addtoallbutton,
457 (GtkDestroyNotify) g_object_unref);
458 gtk_table_attach(GTK_TABLE(table), addtoallbutton, 0, 1, 0, 1,
459 (GtkAttachOptions) (GTK_FILL), 0, 0, 0);
461 addtocompsbutton = gtk_radio_button_new_with_label (hbox2_group, _("Components"));
462 hbox2_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (addtocompsbutton));
463 g_object_ref (addtocompsbutton);
464 g_object_set_data_full (G_OBJECT (aewindow), "addtocompsbutton", addtocompsbutton,
465 (GtkDestroyNotify) g_object_unref);
466 gtk_table_attach(GTK_TABLE(table), addtocompsbutton, 1, 2, 0, 1,
467 (GtkAttachOptions) (GTK_FILL), 0, 0, 0);
469 addtonetsbutton = gtk_radio_button_new_with_label (hbox2_group, _("Nets"));
470 hbox2_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (addtonetsbutton));
471 g_object_ref (addtonetsbutton);
472 g_object_set_data_full (G_OBJECT (aewindow), "addtonetsbutton", addtonetsbutton,
473 (GtkDestroyNotify) g_object_unref);
474 gtk_table_attach(GTK_TABLE(table), addtonetsbutton, 2, 3, 0, 1,
475 (GtkAttachOptions) (GTK_FILL), 0, 0, 0);
477 overwritebutton = gtk_check_button_new_with_label (_("Replace existing attributes"));
478 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(overwritebutton), TRUE);
479 g_object_ref (overwritebutton);
480 g_object_set_data_full (G_OBJECT (aewindow), "overwritebutton", overwritebutton,
481 (GtkDestroyNotify) g_object_unref);
482 gtk_table_attach(GTK_TABLE(table), overwritebutton, 0, 3, 1, 2,
483 (GtkAttachOptions) (GTK_FILL), 0, 0, 0);
486 /* gschem specific */
487 if (attr_obj) {
488 o_attrib_get_name_value (attr_obj, &name, &val);
489 attrib = attr_obj;
490 if (o_is_visible (attrib)) {
491 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(visbutton), TRUE);
492 } else {
493 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(visbutton), FALSE);
496 if (attrib->show_name_value == SHOW_VALUE) {
497 gtk_option_menu_set_history (GTK_OPTION_MENU (show_options), 0);
498 } else if (attrib->show_name_value == SHOW_NAME) {
499 gtk_option_menu_set_history (GTK_OPTION_MENU (show_options), 1);
500 } else {
501 gtk_option_menu_set_history (GTK_OPTION_MENU (show_options), 2);
503 } else {
504 OBJECT *object;
506 attrib = NULL;
508 if ((object = o_select_return_first_object(w_current))) {
509 if (object->type == OBJ_NET)
510 name = g_strdup("netname");
513 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(visbutton), TRUE);
514 /* show value only */
515 gtk_option_menu_set_history (GTK_OPTION_MENU (show_options), 0);
517 g_object_set_data (G_OBJECT (aewindow), "attrib", attrib);
518 if (name) {
519 gtk_entry_set_text(GTK_ENTRY(attrib_combo_entry), name);
521 if (val) {
522 gtk_entry_set_text(GTK_ENTRY(value_entry), val);
523 len = strlen(val);
524 gtk_editable_select_region (GTK_EDITABLE (value_entry), 0, len);
526 g_object_set_data (G_OBJECT (aewindow), "invocation_flag",
527 GINT_TO_POINTER(flag));
529 if (!x_event_get_pointer_position(w_current, TRUE, &wx, &wy)) {
530 wx = wy = -1;
532 g_object_set_data (G_OBJECT (aewindow), "position_wx", GINT_TO_POINTER(wx));
533 g_object_set_data (G_OBJECT (aewindow), "position_wy", GINT_TO_POINTER(wy));
535 /* gschem specific */
536 i = 0;
537 string = (char *) s_attrib_get(i);
538 while (string != NULL) {
539 gtk_combo_box_append_text(GTK_COMBO_BOX(attrib_combo_box_entry), string);
540 i++;
541 string = (char *) s_attrib_get(i);
544 /* Add completion to attribute combo box entry */
545 attrib_combo_entry_completion = gtk_entry_completion_new();
546 gtk_entry_completion_set_model(attrib_combo_entry_completion,
547 gtk_combo_box_get_model(GTK_COMBO_BOX(attrib_combo_box_entry)));
548 gtk_entry_completion_set_text_column(attrib_combo_entry_completion, 0);
549 gtk_entry_completion_set_inline_completion(attrib_combo_entry_completion, TRUE);
550 gtk_entry_completion_set_popup_single_match(attrib_combo_entry_completion, FALSE);
551 gtk_entry_set_completion(GTK_ENTRY(attrib_combo_entry), attrib_combo_entry_completion);
553 /* gschem specific */
554 gtk_widget_show_all(aewindow);
555 w_current->aewindow = aewindow;
557 gtk_grab_add(w_current->aewindow);
559 if (attrib || (name && strcmp(name, "netname") == 0)) {
560 gtk_widget_grab_focus(value_entry);
561 } else {
562 gtk_widget_grab_focus(attrib_combo_entry);
565 g_free(name);
566 g_free(val);
569 /***************** End of Attrib Edit dialog box **********************/