1 #include "core/keymapio.h"
2 #include "core/kbd-custom.h"
3 #include "core/view.h"
4 #include "ui/mousing.h"
5
6 static gchar*
find_command_dir(gint idx,gchar * filename)7 find_command_dir(gint idx, gchar* filename)
8 {
9 command_row* row = NULL;
10 keymap_get_command_row(Denemo.map, &row, idx);
11
12 if(!row->menupath)
13 g_debug("Command %s has no menupath", filename);
14
15 GList* dirs = NULL;
16 dirs = g_list_append(dirs, g_build_filename (PACKAGE_SOURCE_DIR, COMMANDS_DIR, "menus", row->menupath, NULL));
17 dirs = g_list_append(dirs, g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", row->menupath, NULL));
18 dirs = g_list_append(dirs, g_build_filename (get_user_data_dir (TRUE), "download", COMMANDS_DIR, "menus", row->menupath, NULL));
19 dirs = g_list_append(dirs, g_build_filename (get_system_data_dir (), COMMANDS_DIR, "menus", row->menupath, NULL));
20
21 return find_dir_for_file (filename, dirs);
22 }
23
24 static int
get_command_type(xmlChar * type)25 get_command_type(xmlChar* type)
26 {
27 return 0 == xmlStrcmp (type, COMMAND_TYPE_SCHEME) ? COMMAND_SCHEME : COMMAND_BUILTIN;
28 }
29
30 static void
parseScripts(xmlDocPtr doc,xmlNodePtr cur,gchar * fallback)31 parseScripts (xmlDocPtr doc, xmlNodePtr cur, gchar * fallback)
32 {
33 command_row* command = NULL;
34 xmlChar *type = NULL;
35 xmlNodePtr head = cur;
36 type = xmlGetProp(cur, COMMANDXML_TAG_TYPE);
37 for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
38 {
39 if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_ACTION))
40 {
41 if (cur->xmlChildrenNode == NULL)
42 {
43 g_warning ("Empty action node found in keymap file");
44 }
45 else
46 {
47 // We allow multiple locations for a given action, all are added to the gtk_ui when this command is processed after the tooltip node.
48 // This is very bad xml, as the action should have all the others as children, and not depend on the order.FIXME
49 gchar* name = (gchar*) xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
50 command = get_or_create_command(name);
51 command->fallback = fallback;
52 command->locations = NULL;
53
54 if(type && 0 == xmlStrcmp (type, COMMAND_TYPE_SCHEME))
55 command->script_type = get_command_type(type);
56 }
57 }
58 }
59 cur = head;
60 for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
61 {
62 if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_HIDDEN))
63 {
64 command->hidden = TRUE;
65 }
66 else if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_MENUPATH))
67 {
68 command->locations = g_list_append (command->locations, xmlNodeListGetString (doc, cur->xmlChildrenNode, 1));
69 }
70 else if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_LABEL))
71 {
72 command->label = _((gchar*) xmlNodeListGetString (doc, cur->xmlChildrenNode, 1));
73 }
74 else if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_AFTER))
75 {
76 command->after = (gchar*) xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
77 }
78 else if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_TOOLTIP))
79 {
80 command->tooltip = _((gchar*) xmlNodeListGetString (doc, cur->xmlChildrenNode, 1));
81 }
82 }
83 create_command(command);
84 xmlFree(type);
85 }
86
87 static void
parseBindings(xmlDocPtr doc,xmlNodePtr cur,keymap * the_keymap)88 parseBindings (xmlDocPtr doc, xmlNodePtr cur, keymap * the_keymap)
89 {
90
91 xmlChar *name = NULL; //keyval variables
92 gint command_number = -1;
93 guint keyval = 0;
94 GdkModifierType state = 0;
95 name = 0; //defend against corrupt files.
96 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
97 {
98 if (0 == xmlStrcmp (cur->name, BINDINGXML_TAG_ACTION))
99 {
100 if (cur->xmlChildrenNode == NULL)
101 {
102 g_warning ("Empty children node found in keymap file");
103 }
104 else
105 {
106 name = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
107 show_action_of_name ((gchar*) name);
108 }
109 }
110 else if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_HIDDEN))
111 {
112 if (name)
113 hide_action_of_name ((gchar*) name);
114
115 }
116 else if (0 == xmlStrcmp (cur->name, BINDINGXML_TAG_BIND))
117 {
118 if (name)
119 command_number = lookup_command_from_name (the_keymap, (gchar *) name);
120 //g_debug("Found bind node for action %s %d\n", name, command_number);
121 if (cur->xmlChildrenNode == NULL)
122 {
123 g_warning ("Empty <bind><\\bind> found in commandset file");
124 }
125 else
126 {
127 xmlChar *tmp = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
128 if (name && tmp)
129 {
130 gchar *gtk_binding = translate_binding_dnm_to_gtk ((gchar *) tmp);
131 //g_debug("gtk_binding is %s\n", gtk_binding);
132 if (gtk_binding)
133 {
134 keyval = 0;
135 if (Denemo.prefs.strictshortcuts)
136 dnm_accelerator_parse (gtk_binding, &keyval, &state);
137 //g_debug ("binding %s, keyval %d, state %d, Command Number %d", gtk_binding, keyval, state, command_number);
138 {
139 gchar *comma;
140 comma = strtok (gtk_binding, ",");
141 if (comma) //two key binding, remove any single keybinding
142 {
143 if (-1 != lookup_command_for_keybinding_name (the_keymap, comma))
144 remove_keybinding_from_name (the_keymap, comma);
145 *(comma + strlen (comma)) = ',';
146 }
147 }
148 if (command_number != -1)
149 {
150 if (keyval)
151 add_keybinding_to_idx (the_keymap, keyval, state, command_number, POS_LAST);
152 else
153 add_named_binding_to_idx (the_keymap, (gchar*) tmp, command_number, POS_LAST);
154 }
155 g_free (gtk_binding);
156 }
157 else
158 {
159 g_warning ("No gtk equivalent for shortcut %s", tmp);
160 }
161 xmlFree (tmp);
162 }
163 }
164 }
165 }
166 }
167
168 static void
parseCursorBinding(xmlDocPtr doc,xmlNodePtr cur)169 parseCursorBinding (xmlDocPtr doc, xmlNodePtr cur)
170 {
171 gint state, cursor_num;
172 xmlChar *tmp;
173 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
174 {
175 if (0 == xmlStrcmp (cur->name, BINDINGXML_TAG_STATE))
176 {
177 tmp = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
178 if (tmp)
179 {
180 sscanf ((char*) tmp, "%x", &state); // = atoi(tmp);
181 xmlFree (tmp);
182 }
183
184 }
185 else if (0 == xmlStrcmp (cur->name, BINDINGXML_TAG_CURSOR))
186 {
187 tmp = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
188 if (tmp)
189 {
190 cursor_num = atoi ((char*) tmp);
191 xmlFree (tmp);
192 }
193 assign_cursor (state, cursor_num);
194 //g_debug("type is %s\n",g_type_name(G_TYPE_FROM_INSTANCE(Denemo.window->window)));
195 // set_cursor_for(state);
196 }
197 }
198 }
199
200 static void
parseCursors(xmlDocPtr doc,xmlNodePtr cur)201 parseCursors (xmlDocPtr doc, xmlNodePtr cur)
202 {
203 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
204 {
205 if (0 == xmlStrcmp (cur->name, BINDINGXML_TAG_CURSORBINDING))
206 {
207 parseCursorBinding (doc, cur);
208 }
209 }
210 }
211
212 static void
parseCommands(xmlDocPtr doc,xmlNodePtr cur,keymap * the_keymap,gchar * menupath)213 parseCommands (xmlDocPtr doc, xmlNodePtr cur, keymap * the_keymap, gchar * menupath)
214 {
215 xmlNodePtr ncur;
216
217 //Parse commands first
218 for (ncur = cur->xmlChildrenNode; ncur; ncur = ncur->next)
219 {
220 if ((0 == xmlStrcmp (ncur->name, COMMANDXML_TAG_ROW)))
221 {
222 parseScripts (doc, ncur, menupath);
223 }
224 }
225
226 //Then parse bindings
227 if(!Denemo.non_interactive){
228 for (ncur = cur->xmlChildrenNode; ncur; ncur = ncur->next)
229 {
230 if ((0 == xmlStrcmp (ncur->name, COMMANDXML_TAG_ROW)))
231 {
232 parseBindings (doc, ncur, the_keymap);
233 }
234 else if (0 == xmlStrcmp (ncur->name, COMMANDXML_TAG_CURSORS))
235 {
236 parseCursors (doc, ncur);
237 }
238 }
239 }
240 }
241
242 static void
parseKeymap(xmlDocPtr doc,xmlNodePtr cur,keymap * the_keymap,gchar * menupath)243 parseKeymap (xmlDocPtr doc, xmlNodePtr cur, keymap * the_keymap, gchar * menupath)
244 {
245 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
246 {
247 if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_MAP))
248 {
249 parseCommands (doc, cur, the_keymap, menupath);
250 }
251 }
252 }
253
254 /*
255 * load a command from filename.
256 * if not scripted and merging with other commands, tell the user where the new command is.
257 * If an action exists but has an empty script load the scheme script,
258 if action is a new action leave script as empty string for loading on demand.
259 * Create a widget for the action in a menupath found in filename or failing that deduced from
260 * the path to filename itself (starting from actions/menus).
261 * returns 0 on success
262 * negative on failure
263 */
264 gint
load_xml_keymap(gchar * filename)265 load_xml_keymap (gchar * filename)
266 {
267 gint ret = -1;
268 xmlDocPtr doc;
269 xmlNodePtr rootElem;
270 xmlKeepBlanksDefault (0);
271
272 if (filename == NULL)
273 return ret;
274
275 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
276 return ret;
277
278 if (g_file_test (filename, G_FILE_TEST_IS_DIR))
279 {
280 warningdialog (_("There is no support for loading whole folders of commands yet, sorry"));
281 return ret;
282 }
283 doc = xmlParseFile (filename);
284 gchar *menupath = extract_menupath (filename);
285 if (doc == NULL)
286 {
287 g_debug ("Could not read XML file %s", filename);
288 return ret;
289 }
290
291 rootElem = xmlDocGetRootElement (doc);
292 if (rootElem == NULL)
293 {
294 g_warning ("Empty Document");
295 xmlFreeDoc (doc);
296 return ret;
297 }
298
299 if (xmlStrcmp (rootElem->name, COMMANDXML_TAG_ROOT))
300 {
301 g_warning ("Document has wrong type");
302 xmlFreeDoc (doc);
303 return ret;
304 }
305 rootElem = rootElem->xmlChildrenNode;
306
307
308 while (rootElem != NULL)
309 {
310 parseKeymap (doc, rootElem, Denemo.map, menupath);
311
312 if (Denemo.last_merged_command)
313 g_free (Denemo.last_merged_command);
314 Denemo.last_merged_command = g_strdup (filename);
315 if (menupath)
316 execute_init_scripts (menupath);
317
318 if(!Denemo.non_interactive)
319 update_all_labels (Denemo.map);
320 ret = 0;
321
322 rootElem = rootElem->next;
323 }
324
325 xmlFreeDoc (doc);
326 {static gboolean init=FALSE;
327 if (!init)
328 {
329 alphabeticalize_commands (Denemo.map);
330 init = TRUE;
331 }
332 }
333 {
334 //if this is a new-style .commands file, we need to load the keybindings separately
335 gchar *name = g_strdup (filename);
336 gchar *ext = remove_extension (name);
337 if (ext && !strcmp (ext, "commands") && !Denemo.non_interactive)
338 {
339 gchar *newname = g_strdup_printf ("%s%s", name, ".shortcuts");
340 load_xml_keybindings (newname);
341 g_free (newname);
342 }
343 g_free (name);
344 }
345 return ret;
346 }
347
348 gint
load_xml_keybindings(gchar * filename)349 load_xml_keybindings (gchar * filename)
350 {
351 gint ret = -1;
352 xmlDocPtr doc;
353 //xmlNsPtr ns;
354 xmlNodePtr rootElem;
355 if (filename == NULL)
356 return ret;
357 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
358 return ret;
359 doc = xmlParseFile (filename);
360 if (doc == NULL)
361 {
362 g_debug ("Could not read XML file %s", filename);
363 return ret;
364 }
365 rootElem = xmlDocGetRootElement (doc);
366 if (rootElem == NULL)
367 {
368 g_warning ("Empty Document");
369 xmlFreeDoc (doc);
370 return ret;
371 }
372 //g_debug ("RootElem %s\n", rootElem->name);
373 if (xmlStrcmp (rootElem->name, COMMANDXML_TAG_ROOT))
374 {
375 g_warning ("Document has wrong type");
376 xmlFreeDoc (doc);
377 return ret;
378 }
379 rootElem = rootElem->xmlChildrenNode;
380
381 while (rootElem != NULL)
382 {
383 if ((0 == xmlStrcmp (rootElem->name, COMMANDXML_TAG_MERGE)))
384 {
385 xmlNodePtr cur;
386 for (cur = rootElem->xmlChildrenNode; cur != NULL; cur = cur->next)
387 {
388 if (0 == xmlStrcmp (cur->name, COMMANDXML_TAG_MAP))
389 {
390 xmlNodePtr ncur;
391 for (ncur = cur->xmlChildrenNode; ncur != NULL; ncur = ncur->next)
392 {
393 parseBindings (doc, ncur, Denemo.map);
394 }
395 ret = 0;
396 }
397 }
398 update_all_labels (Denemo.map);
399 }
400 rootElem = rootElem->next;
401 }
402 xmlFreeDoc (doc);
403 return ret;
404 }
405
406 static void
write_xml_keybinding_info(gchar * kb_name,xmlNodePtr node)407 write_xml_keybinding_info (gchar * kb_name, xmlNodePtr node)
408 {
409 gchar *dnm_binding = translate_binding_gtk_to_dnm (kb_name);
410 g_debug ("binding is : (dnm) %s, (gtk) %s \n", dnm_binding, kb_name);
411 if (!(Denemo.prefs.return_key_is_special && !strcmp (dnm_binding, N_("Return"))))
412 xmlNewTextChild (node, NULL, (xmlChar *) "bind", (xmlChar *) dnm_binding);
413 g_free (dnm_binding);
414 }
415
416 static void
output_pointer_shortcut(gint * state,GdkCursor * cursor,xmlNodePtr parent)417 output_pointer_shortcut (gint * state, GdkCursor * cursor, xmlNodePtr parent)
418 {
419 gchar *statestr = g_strdup_printf ("%x", *state);
420 #if GTK_MAJOR_VERSION==3
421 gint cursor_num = gdk_cursor_get_cursor_type (cursor);
422 #else
423 gint cursor_num = cursor->type;
424 #endif
425 gchar *numstr = g_strdup_printf ("%d", cursor_num);
426 xmlNodePtr child = xmlNewTextChild (parent, NULL, (xmlChar *) "cursor-binding", NULL);
427 xmlNewChild (child, NULL, (xmlChar*) "state", (xmlChar*) statestr);
428 xmlNewChild (child, NULL, (xmlChar*) "cursor", (xmlChar*) numstr);
429 g_free (statestr);
430 g_free (numstr);
431 }
432
433 gint
save_xml_keymap(gchar * filename)434 save_xml_keymap (gchar * filename) //_!!! create a DEV version here, saving C-code to create the actions at runtime with translatable tooltips.
435 {
436 keymap *the_keymap = Denemo.map;
437 gint i, ret = -1;
438 xmlDocPtr doc;
439 xmlNodePtr parent, child;
440 gchar* cfilename = NULL;
441 const gchar *basename = NULL;
442 gchar* dir = NULL;
443 doc = xmlNewDoc ((xmlChar *) "1.0");
444 command_row* row;
445 doc->xmlRootNode = parent = xmlNewDocNode (doc, NULL, COMMANDXML_TAG_ROOT, NULL);
446
447 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_MERGE, NULL);
448
449 xmlNewTextChild (child, NULL, COMMANDXML_TAG_TITLE, (xmlChar *) "A Denemo Command Set");
450 xmlNewTextChild (child, NULL, COMMANDXML_TAG_AUTHOR, (xmlChar *) "AT, JRR, RTS");
451
452 parent = xmlNewChild (child, NULL, COMMANDXML_TAG_MAP, NULL);
453
454 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_CURSORS, NULL);
455
456 g_hash_table_foreach (Denemo.map->cursors, (GHFunc) output_pointer_shortcut, child);
457
458
459 for (i = 0; i < keymap_size (the_keymap); i++)
460 {
461 keymap_get_command_row (the_keymap, &row, i);
462
463 gpointer action = (gpointer) lookup_action_from_idx (the_keymap, i);
464 gchar *name = (gchar *) lookup_name_from_idx (the_keymap, i);
465
466 basename = gtk_action_get_name (action);
467
468 if(!is_action_name_builtin(name))
469 {
470 // Check if the command metada file exists
471 cfilename = g_strconcat (basename, XML_EXT, NULL);
472 dir = find_command_dir(i, cfilename);
473 g_free(cfilename);
474 if(!dir)
475 {
476 g_warning("Unable to find metadata file for script %s", name);
477 continue;
478 }
479
480 // Check if the command data file exists
481 cfilename = g_strconcat (basename, SCM_EXT, NULL);
482 dir = find_command_dir(i, cfilename);
483 g_free(cfilename);
484 if(!dir)
485 {
486 g_warning("Unable to find data file for script %s", name);
487 continue;
488 }
489 }
490
491 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_ROW, NULL);
492
493 xmlNewTextChild (child, NULL, COMMANDXML_TAG_ACTION, (xmlChar *) name);
494
495 if(!is_action_name_builtin(name))
496 xmlNewProp(child, COMMANDXML_TAG_TYPE, COMMAND_TYPE_SCHEME);
497 else
498 xmlNewProp(child, COMMANDXML_TAG_TYPE, COMMAND_TYPE_BUILTIN);
499
500 if (row->after)
501 xmlNewTextChild (child, NULL, COMMANDXML_TAG_AFTER, (xmlChar *) row->after);
502 if (row->deleted) //store as hidden in commands file
503 xmlNewTextChild (child, NULL, COMMANDXML_TAG_HIDDEN, (xmlChar *) "true");
504
505 if (row->menupath)
506 xmlNewTextChild (child, NULL, COMMANDXML_TAG_MENUPATH, (xmlChar *) row->menupath);
507
508 gchar *label = (gchar *) lookup_label_from_idx (the_keymap, i);
509 if (label)
510 xmlNewTextChild (child, NULL, COMMANDXML_TAG_LABEL, (xmlChar *) label);
511
512
513 gchar *tooltip = (gchar *) lookup_tooltip_from_idx (the_keymap, i);
514 if (tooltip)
515 xmlNewTextChild (child, NULL, COMMANDXML_TAG_TOOLTIP, (xmlChar *) tooltip);
516 }
517
518 xmlSaveFormatFileEnc (filename, doc, XML_ENCODING, 1);
519
520 xmlFreeDoc (doc);
521 return ret;
522 }
523
524 gint
save_xml_keybindings(gchar * filename)525 save_xml_keybindings (gchar * filename)
526 {
527 keymap *the_keymap = Denemo.map;
528 gint i, ret = -1;
529 xmlDocPtr doc;
530 //xmlNsPtr ns;
531 xmlNodePtr parent, child;
532 command_row *row;
533
534 doc = xmlNewDoc ((xmlChar *) "1.0");
535 doc->xmlRootNode = parent = xmlNewDocNode (doc, NULL, COMMANDXML_TAG_ROOT, NULL);
536 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_MERGE, NULL);
537
538 xmlNewTextChild (child, NULL, COMMANDXML_TAG_TITLE, (xmlChar *) "A Denemo Command Set");
539 xmlNewTextChild (child, NULL, COMMANDXML_TAG_AUTHOR, (xmlChar *) "AT, JRR, RTS");
540
541 parent = xmlNewChild (child, NULL, COMMANDXML_TAG_MAP, NULL);
542
543 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_CURSORS, NULL);
544
545 g_hash_table_foreach (Denemo.map->cursors, (GHFunc) output_pointer_shortcut, child);
546
547
548 for (i = 0; i < keymap_size (the_keymap); i++)
549 {
550 keymap_get_command_row (the_keymap, &row, i);
551
552 gpointer action = (gpointer) lookup_action_from_idx (the_keymap, i);
553 if (row->deleted && !is_action_id_builtin(i))
554 continue;
555 if (row->hidden || command_has_binding (i))
556 {
557 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_ROW, NULL);
558
559 gchar *name = (gchar *) lookup_name_from_idx (the_keymap, i);
560 //g_debug ("%s %s binding(s) \n", name, command_has_binding (i) ? "has" : "does not have");
561 xmlNewTextChild (child, NULL, COMMANDXML_TAG_ACTION, (xmlChar *) name);
562 if (row->hidden)
563 xmlNewTextChild (child, NULL, COMMANDXML_TAG_HIDDEN, (xmlChar *) "true");
564
565 g_list_foreach(row->bindings, (GFunc) write_xml_keybinding_info, child);
566 }
567 }
568
569 xmlSaveFormatFileEnc (filename, doc, XML_ENCODING, 1);
570
571 xmlFreeDoc (doc);
572 return ret;
573 }
574
575 /*
576 static void
577 show_type (GtkWidget * widget, gchar * message)
578 {
579 g_message ("%s%s", message, widget ? g_type_name (G_TYPE_FROM_INSTANCE (widget)) : "NULL widget");
580 }
581 */
582 /* not used */
583 /*
584 static gint
585 create_dir_for_menu (gchar * str)
586 {
587 gchar *thismenu = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "menus", str, NULL);
588 if (!g_file_test (thismenu, G_FILE_TEST_IS_DIR))
589 {
590 return g_mkdir_with_parents (thismenu, 0770);
591 }
592 return 0;
593 }
594 */
595
596 /* parse an entry in denemoui.xml recursively
597 set menupath as attribute of widgets
598 */
599 static gint
parseMenu(xmlNodePtr rootElem,gchar * path,DenemoProject * gui)600 parseMenu (xmlNodePtr rootElem, gchar * path, DenemoProject * gui)
601 {
602 for (rootElem = rootElem->xmlChildrenNode; rootElem; rootElem = rootElem->next)
603 {
604 if (0 == xmlStrcmp (rootElem->name, MENUXML_TAG_MENUBAR) ||
605 0 == xmlStrcmp (rootElem->name, MENUXML_TAG_MENU) ||
606 0 == xmlStrcmp (rootElem->name, MENUXML_TAG_TOOLBAR))
607 /* ignoring popup menus */
608 {
609 gchar *name = (gchar *) xmlGetProp (rootElem, MENUXML_PROP_NAME);
610 if (name == NULL)
611 name = (gchar *) xmlGetProp (rootElem, MENUXML_PROP_ACTION);
612
613 if (name)
614 {
615 gchar *str = g_strdup_printf ("%s%s%s", path, "/", name);
616 GtkWidget *widget = gtk_ui_manager_get_widget (Denemo.ui_manager, str);
617 if (widget)
618 {
619 g_object_set_data (G_OBJECT (widget), "menupath", str);
620 // we do this in menu_click when needed create_dir_for_menu(str);//FIXME we only need do this once for a given denemoui.xml
621 //show_type(widget, "The type is ");
622 //g_debug("set %p %s\n",widget, str);
623 parseMenu (rootElem, str, gui);
624 }
625 else
626 g_warning ("no object for %s", str);
627 }
628
629 }
630 if (0 == xmlStrcmp (rootElem->name, MENUXML_TAG_MENUITEM))
631 {
632 gchar *name = (gchar *) xmlGetProp (rootElem, MENUXML_PROP_ACTION);
633 if (name)
634 {
635 gchar *str = g_strdup_printf ("%s%s%s", path, "/", name);
636 GtkWidget *widget = gtk_ui_manager_get_widget (Denemo.ui_manager, str);
637 g_free (str);
638 //show_type(widget, "The type is ");
639 //g_debug("set %p %s\n",widget, path);
640 if (widget)
641 {
642 g_object_set_data (G_OBJECT (widget), "menupath", g_strdup (path));
643 }
644 }
645 g_free (name);
646 }
647 }
648 return 0;
649 }
650
651 /*
652 * attaches the menu hierarchy path to each menuitem widget in the passed file (denemoui.xml)
653 * returns 0 on success
654 * negative on failure
655 */
656 gint
parse_paths(gchar * filename,DenemoProject * gui)657 parse_paths (gchar * filename, DenemoProject * gui)
658 {
659 gint ret = -1;
660 xmlDocPtr doc;
661 xmlNodePtr rootElem;
662 if (filename == NULL)
663 return ret;
664 doc = xmlParseFile (filename);
665
666 if (doc == NULL)
667 {
668 g_warning ("Could not read XML file %s", filename);
669 return ret;
670 }
671
672 rootElem = xmlDocGetRootElement (doc);
673 if (rootElem == NULL)
674 {
675 g_warning ("Empty Document");
676 xmlFreeDoc (doc);
677 return ret;
678 }
679
680 if (xmlStrcmp (rootElem->name, (const xmlChar *) "ui"))
681 {
682 g_warning ("Document has wrong type");
683 xmlFreeDoc (doc);
684 return ret;
685 }
686
687 parseMenu (rootElem, "", gui);
688 ret = 0;
689 xmlFreeDoc (doc);
690 return ret;
691 }
692
693 gint
save_command_metadata(gchar * filename,gchar * myname,gchar * mylabel,gchar * mytooltip,gchar * after)694 save_command_metadata (gchar * filename, gchar * myname, gchar * mylabel, gchar * mytooltip, gchar * after)
695 {
696 xmlDocPtr doc;
697 xmlNodePtr parent, child;
698
699 doc = xmlNewDoc ((xmlChar *) "1.0");
700 doc->xmlRootNode = parent = xmlNewDocNode (doc, NULL, COMMANDXML_TAG_ROOT, NULL);
701 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_MERGE, NULL);
702
703 xmlNewTextChild (child, NULL, COMMANDXML_TAG_TITLE, (xmlChar *) "A Denemo Keymap");
704 xmlNewTextChild (child, NULL, COMMANDXML_TAG_AUTHOR, (xmlChar *) "AT, JRR, RTS");
705
706 parent = xmlNewChild (child, NULL, COMMANDXML_TAG_MAP, NULL);
707
708 child = xmlNewChild (parent, NULL, COMMANDXML_TAG_ROW, NULL);
709 xmlNewProp(child, COMMANDXML_TAG_TYPE, COMMAND_TYPE_SCHEME);
710
711 xmlNewTextChild (child, NULL, COMMANDXML_TAG_ACTION, (xmlChar *) myname);
712
713 if (after)
714 xmlNewTextChild (child, NULL, COMMANDXML_TAG_AFTER, (xmlChar *) after);
715
716
717 xmlNewTextChild (child, NULL, COMMANDXML_TAG_LABEL, (xmlChar *) mylabel);
718
719 xmlNewTextChild (child, NULL, COMMANDXML_TAG_TOOLTIP, (xmlChar *) mytooltip);
720
721 xmlSaveFormatFileEnc (filename, doc, XML_ENCODING, 1);
722 xmlFreeDoc (doc);
723 return 0;
724 }
725
726 gint
save_command_data(gchar * filename,gchar * myscheme)727 save_command_data (gchar * filename, gchar * myscheme)
728 {
729 g_file_set_contents (filename, myscheme, -1, NULL);
730 return 0;
731 }
732
733 gchar *
load_command_data(gint idx)734 load_command_data (gint idx)
735 {
736 gchar *basename = (gchar*) lookup_name_from_idx (Denemo.map, idx);
737 gchar *filename = g_strconcat (basename, SCM_EXT, NULL);
738 gchar* path = NULL;
739 gchar* scheme = NULL;
740 GError* error = NULL;
741
742 // Locate the script
743 gchar* dir = find_command_dir(idx, filename);
744 if(!dir)
745 {
746 gchar* msg = g_strdup_printf(_("Unable to locate the script %s"), filename);
747 warningdialog (msg);
748 g_free(msg);
749 g_free(filename);
750 return NULL;
751 }
752
753 // Load the script
754 path = g_build_filename(dir, filename, NULL);
755 g_free(filename);
756 if(!g_file_get_contents (path, &scheme, NULL, &error))
757 {
758 gchar* msg = g_strdup_printf(_("Unable to load the script %s"), path);
759 warningdialog (msg);
760 g_free(msg);
761 g_free(path);
762 return NULL;
763 }
764 g_free(path);
765
766 // Load the init script if there is one
767 path = g_build_filename (dir, INIT_SCM, NULL);
768 if (g_file_test (path, G_FILE_TEST_EXISTS))
769 //scm_c_primitive_load(path);Use scm_c_primitive_load together with scm_internal_catch and scm_handle_by_message_no_exit instead.
770 eval_file_with_catch (path);
771 g_free (path);
772
773 g_free (dir);
774
775 return scheme;
776 }
777
778 #ifdef DEVELOPER
779 //code to take denemoui.xml and Default.commands from the cwd and output a new version of Default.commands with builtin commands' menupaths inserted
780 GString *contents = NULL;
781
782
insert_path(gchar * name,gchar * path)783 static void insert_path (gchar *name, gchar *path)
784 {
785 if(!contents)
786 {
787 GError* error = NULL;
788 gchar *temp;
789 g_file_get_contents ("Default.commands", &temp, NULL, &error);
790 if(error) exit (-1);
791 contents = g_string_new (temp);
792 //g_print ("contents %s\n", contents->str);
793 }
794 name = g_strconcat ("<action>", name, "</action>", NULL);
795 gchar *found = g_strrstr (contents->str, name);
796 if(found)
797 {
798 path = g_strconcat ("<menupath>", path, "</menupath>\n", NULL);
799 contents = g_string_insert (contents, found - contents->str, path);
800 }
801 }
802
803 static void
parseMenuItems(xmlDocPtr doc,xmlNodePtr cur,gchar * folder)804 parseMenuItems (xmlDocPtr doc, xmlNodePtr cur, gchar *folder)
805 {
806 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next)
807 {
808 if (0 == xmlStrcmp (cur->name, "menuitem"))
809 {
810 gchar *name = xmlGetProp (cur, "action");
811 insert_path (name, folder);
812 }
813 else if (0 == xmlStrcmp (cur->name, "menu"))
814 {
815 gchar *menufolder = g_strconcat (folder, "/", xmlGetProp (cur, "action"), NULL);
816 parseMenuItems (doc, cur, menufolder);
817 }
818 }
819 }
820
821 gint
attach_menupaths(void)822 attach_menupaths (void)
823 {
824 gchar * filename = "denemoui.xml";
825 gchar * commands = "Default.commands";
826 gint ret = -1;
827 xmlDocPtr doc;
828 //xmlNsPtr ns;
829 xmlNodePtr rootElem;
830 if (filename == NULL)
831 return ret;
832 if (!g_file_test (filename, G_FILE_TEST_EXISTS))
833 return ret;
834 doc = xmlParseFile (filename);
835 if (doc == NULL)
836 {
837 g_debug ("Could not read XML file %s", filename);
838 return ret;
839 }
840 rootElem = xmlDocGetRootElement (doc);
841 if (rootElem == NULL)
842 {
843 g_warning ("Empty Document");
844 xmlFreeDoc (doc);
845 return ret;
846 }
847 //g_debug ("RootElem %s\n", rootElem->name);
848 if (xmlStrcmp (rootElem->name, "ui"))
849 {
850 g_warning ("Document has wrong type");
851 xmlFreeDoc (doc);
852 return ret;
853 }
854
855 xmlNodePtr cur;
856 for (cur = rootElem->xmlChildrenNode; cur != NULL; cur = cur->next)
857 {
858 if ((0 == xmlStrcmp (cur->name, "menubar")))
859 {
860 gchar *folder = xmlGetProp (cur, "name");
861 parseMenuItems (doc, cur, folder);
862 }
863 }
864 g_print ("\n%s", contents->str);
865 xmlFreeDoc (doc);
866 return ret;
867 }
868 #endif
869