missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / x_menus.c
blob404d969ba4b85fddc2310a6239194554824a6a50
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 #include "config.h"
22 #ifdef HAVE_STRING_H
23 #include <string.h>
24 #endif
27 #include "gschem.h"
29 #include <glib/gstdio.h>
32 static GtkWidget *
33 build_menu (SCM s_menu, gboolean is_main_menu, GschemToplevel *w_current)
35 GtkWidget *menu = gtk_menu_new ();
37 if (is_main_menu) {
38 GtkWidget *tearoff_menu_item = gtk_tearoff_menu_item_new ();
39 gtk_menu_shell_append (GTK_MENU_SHELL (menu), tearoff_menu_item);
40 gtk_widget_show (tearoff_menu_item);
43 for (SCM l0 = s_menu; scm_is_pair (l0); l0 = scm_cdr (l0)) {
44 SCM s_section = scm_car (l0);
45 SCM_ASSERT (scm_is_true (scm_list_p (s_section)),
46 s_section, SCM_ARGn, "build_menu section");
48 for (SCM l1 = s_section; scm_is_pair (l1); l1 = scm_cdr (l1)) {
49 SCM s_item = scm_car (l1);
50 SCM_ASSERT (scm_is_action (s_item),
51 s_item, SCM_ARGn, "build_menu item");
53 /* make sure the action won't ever be garbage collected
54 since we're going to point to it from C data structures */
55 scm_permanent_object (s_item);
57 GschemAction *action = scm_to_action (s_item);
58 GtkWidget *menu_item =
59 gschem_action_create_menu_item (action, is_main_menu, w_current);
60 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
61 gtk_widget_show (menu_item);
64 if (scm_is_pair (scm_cdr (l0))) {
65 /* add separator */
66 GtkWidget *menu_item = gtk_menu_item_new ();
67 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
68 gtk_widget_show (menu_item);
72 return menu;
75 /*! \todo Finish function documentation!!!
76 * \brief
77 * \par Function Description
80 void
81 x_menus_create_main_menu (GschemToplevel *w_current)
83 SCM s_var = scm_module_variable (scm_current_module (),
84 scm_from_utf8_symbol ("menubar"));
85 if (!scm_is_true (s_var)) {
86 g_critical (_("No menubar definition found\n"));
87 return;
90 SCM s_menubar = scm_variable_ref (s_var);
91 if (scm_is_null (s_menubar) || !scm_is_true (scm_list_p (s_menubar))) {
92 g_critical (_("Empty or malformed menubar definition\n"));
93 return;
96 w_current->menubar = gtk_menu_bar_new ();
98 for (SCM l = s_menubar; scm_is_pair (l); l = scm_cdr (l)) {
99 SCM s_menu = scm_car (l);
100 SCM_ASSERT (scm_is_pair (s_menu),
101 s_menu, SCM_ARGn, "get_main_menu menu");
103 SCM s_title = scm_car (s_menu);
104 SCM_ASSERT (scm_is_string (s_title),
105 s_title, SCM_ARGn, "get_main_menu menu title");
107 GtkWidget *menu = build_menu (scm_cdr (s_menu), TRUE, w_current);
109 scm_dynwind_begin (0);
111 char *title = scm_to_utf8_string (s_title);
112 scm_dynwind_free (title);
114 /* store lower-case title without underscores as settings name
115 for saving/restoring torn-off menus */
116 gchar *settings_name = g_ascii_strdown (title, -1);
117 gchar *i = settings_name, *j = settings_name;
118 do {
119 if (*i != '_')
120 *j++ = *i;
121 } while (*i++ != '\0');
122 g_object_set_data (G_OBJECT (menu), "settings-name", settings_name);
124 GtkWidget *root_menu = gtk_menu_item_new_with_mnemonic (title);
125 gtk_widget_show (root_menu);
126 gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
127 /* no longer right justify the help menu since that has gone out
128 of style */
129 gtk_menu_shell_append (GTK_MENU_SHELL (w_current->menubar), root_menu);
131 scm_dynwind_end ();
135 void
136 x_menus_create_main_popup (GschemToplevel *w_current)
138 SCM s_var = scm_module_variable (scm_current_module (),
139 scm_from_utf8_symbol ("context-menu"));
140 if (!scm_is_true (s_var)) {
141 g_warning (_("No context menu definition found\n"));
142 return;
145 SCM s_menu = scm_variable_ref (s_var);
146 if (scm_is_null (s_menu) || !scm_is_true (scm_list_p (s_menu))) {
147 g_warning (_("Empty or malformed context menu definition\n"));
148 return;
151 w_current->popup_menu = build_menu (s_menu, FALSE, w_current);
154 #define MAX_RECENT_FILES 10
155 /*! \brief Callback for recent-chooser.
157 * Will be called if element of recent-file-list is activated
159 void
160 recent_chooser_item_activated (GtkRecentChooser *chooser, GschemToplevel *w_current)
162 gchar *uri;
163 gchar *filename;
165 uri = gtk_recent_chooser_get_current_uri (chooser);
166 filename = g_filename_from_uri(uri, NULL, NULL);
167 x_highlevel_open_page (w_current, (char *) filename);
169 g_free(uri);
170 g_free(filename);
173 /*! \brief Create a submenu with filenames for the 'Open Recent'
174 * menu item.
176 static GtkWidget *
177 create_recent_chooser_menu (GschemToplevel *w_current)
179 GtkRecentFilter *recent_filter;
180 GtkWidget *menuitem_file_recent_items;
181 recent_manager = gtk_recent_manager_get_default();
183 menuitem_file_recent_items = gtk_recent_chooser_menu_new_for_manager(recent_manager);
185 /* Show only schematic- and symbol-files (*.sch and *.sym) in list */
186 recent_filter = gtk_recent_filter_new();
187 gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-schematic");
188 gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-symbol");
189 gtk_recent_filter_add_pattern(recent_filter, "*.sch");
190 gtk_recent_filter_add_pattern(recent_filter, "*.sym");
191 gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(menuitem_file_recent_items), recent_filter);
193 gtk_recent_chooser_set_show_tips(GTK_RECENT_CHOOSER(menuitem_file_recent_items), TRUE);
194 gtk_recent_chooser_set_sort_type(GTK_RECENT_CHOOSER(menuitem_file_recent_items),
195 GTK_RECENT_SORT_MRU);
196 gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(menuitem_file_recent_items), MAX_RECENT_FILES);
197 gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(menuitem_file_recent_items), FALSE);
198 gtk_recent_chooser_menu_set_show_numbers(GTK_RECENT_CHOOSER_MENU(menuitem_file_recent_items), TRUE);
199 g_signal_connect(GTK_OBJECT(menuitem_file_recent_items), "item-activated",
200 G_CALLBACK(recent_chooser_item_activated), w_current);
202 return menuitem_file_recent_items;
205 /*! \brief Create submenus for various menu items.
207 * Called from x_window_setup().
209 void
210 x_menus_create_submenus (GschemToplevel *w_current)
212 /* create recent files menu */
213 w_current->recent_chooser_menu = create_recent_chooser_menu (w_current);
214 g_object_set_data (G_OBJECT (w_current->recent_chooser_menu),
215 "settings-name", "recent-files");
217 /* create left docking area menu */
218 w_current->left_docking_area_menu = gtk_menu_new ();
219 g_object_set_data (G_OBJECT (w_current->left_docking_area_menu),
220 "settings-name", "left-docking-area");
221 gtk_menu_shell_append (GTK_MENU_SHELL (w_current->left_docking_area_menu),
222 gtk_tearoff_menu_item_new ());
223 gtk_widget_show_all (w_current->left_docking_area_menu);
225 /* create bottom docking area menu */
226 w_current->bottom_docking_area_menu = gtk_menu_new ();
227 g_object_set_data (G_OBJECT (w_current->bottom_docking_area_menu),
228 "settings-name", "bottom-docking-area");
229 gtk_menu_shell_append (GTK_MENU_SHELL (w_current->bottom_docking_area_menu),
230 gtk_tearoff_menu_item_new ());
231 gtk_widget_show_all (w_current->bottom_docking_area_menu);
233 /* create right docking area menu */
234 w_current->right_docking_area_menu = gtk_menu_new ();
235 g_object_set_data (G_OBJECT (w_current->right_docking_area_menu),
236 "settings-name", "right-docking-area");
237 gtk_menu_shell_append (GTK_MENU_SHELL (w_current->right_docking_area_menu),
238 gtk_tearoff_menu_item_new ());
239 gtk_widget_show_all (w_current->right_docking_area_menu);
242 void
243 x_menus_create_toolbar (GschemToplevel *w_current)
245 SCM s_var = scm_module_variable (scm_current_module (),
246 scm_from_utf8_symbol ("toolbar"));
247 if (!scm_is_true (s_var)) {
248 g_warning (_("No toolbar definition found\n"));
249 return;
252 SCM s_toolbar = scm_variable_ref (s_var);
253 if (scm_is_null (s_toolbar) || !scm_is_true (scm_list_p (s_toolbar))) {
254 g_warning (_("Empty or malformed toolbar definition\n"));
255 return;
258 w_current->toolbar = gtk_toolbar_new ();
259 gtk_orientable_set_orientation (GTK_ORIENTABLE (w_current->toolbar),
260 GTK_ORIENTATION_HORIZONTAL);
261 gtk_toolbar_set_style (GTK_TOOLBAR (w_current->toolbar), GTK_TOOLBAR_ICONS);
263 for (SCM l0 = s_toolbar; scm_is_pair (l0); l0 = scm_cdr (l0)) {
264 SCM s_section = scm_car (l0);
265 SCM_ASSERT (scm_is_true (scm_list_p (s_section)),
266 s_section, SCM_ARGn, "x_menus_create_toolbar section");
268 for (SCM l1 = s_section; scm_is_pair (l1); l1 = scm_cdr (l1)) {
269 SCM s_item = scm_car (l1);
270 SCM_ASSERT (scm_is_action (s_item),
271 s_item, SCM_ARGn, "x_menus_create_toolbar item");
273 /* make sure the action won't ever be garbage collected
274 since we're going to point to it from C data structures */
275 scm_permanent_object (s_item);
277 GschemAction *action = scm_to_action (s_item);
278 GtkToolItem *button =
279 gschem_action_create_tool_button (action, w_current);
280 gtk_toolbar_insert (GTK_TOOLBAR (w_current->toolbar), button, -1);
283 if (scm_is_pair (scm_cdr (l0)))
284 gtk_toolbar_insert (GTK_TOOLBAR (w_current->toolbar),
285 gtk_separator_tool_item_new (), -1);
288 gtk_widget_show_all (w_current->toolbar);
290 /* activate 'select' button at start-up */
291 i_update_toolbar (w_current);