nautilus: add submenu support
[git-cheetah/kirill.git] / finder / menu.c
blob83c8d683f72a5345b6976387ee5f3c6f2e213874
1 /* menu.c
3 * Implementation of a finder menu plugin for git-cheetah
5 * This implements the cheetah interface to create menu entries.
7 * Copyright (C) Heiko Voigt, 2009
9 * inspired by an example from Brent Simmons
10 * brent@ranchero.com, http://macte.ch/kmyXM
15 /* implements platform dependent functions declared by cheetah */
16 #include "../common/git-compat-util.h"
17 #include "../common/strbuf.h"
18 #include "../common/exec.h"
19 #include "../common/menuengine.h"
20 #include "../common/cheetahmenu.h"
21 #include "../common/debug.h"
22 #include "plugin.h"
23 #include "util.h"
24 #include "menu.h"
26 BOOL build_item(struct git_data *me, const struct menu_item *item,
27 void *platform)
29 struct osx_menu_data *osx_data = platform;
30 AERecord menu_entry = { typeNull, NULL };
31 BOOL status = TRUE;
32 char *item_name = strdup(item->string);
33 char shortcut_key;
34 static int not_shown_offset = 0;
36 if (!platform) {
37 not_shown_offset++;
38 return TRUE;
41 if (not_shown_offset) {
42 osx_data->item_id += not_shown_offset;
43 not_shown_offset = 0;
46 shortcut_key = parse_and_remove_shortcuts(item_name);
48 debug_git("Adding entry: %s", item_name);
50 if (AECreateList(NULL, 0, true, &menu_entry) != noErr)
51 return FALSE;
53 if (AEPutKeyPtr(&menu_entry, keyAEName, typeCString, item_name,
54 strlen(item_name) + 1) != noErr)
56 status = FALSE;
57 goto add_menu_entry_cleanup;
60 if (AEPutKeyPtr(&menu_entry, 'cmcd', typeSInt32, &osx_data->item_id,
61 sizeof(osx_data->item_id)) != noErr)
63 status = FALSE;
64 goto add_menu_entry_cleanup;
67 /* insert menu item at the end of the menu */
68 if (AEPutDesc(osx_data->menu, 0, &menu_entry) != noErr)
70 status = FALSE;
71 goto add_menu_entry_cleanup;
74 /* this needs to be uniqe for each item */
75 osx_data->item_id++;
77 add_menu_entry_cleanup:
78 AEDisposeDesc(&menu_entry);
79 free(item_name);
80 return status;
83 BOOL build_separator(struct git_data *me, const struct menu_item *item,
84 void *platform)
86 struct osx_menu_data *osx_data = platform;
87 osx_data->item_id++;
88 return TRUE;
91 /* osx does not need to reset anything */
92 void reset_platform(void *platform)
96 void *start_submenu(struct git_data *me, const struct menu_item *item,
97 void *platform)
99 /* not implemented, yet */
100 return NULL;
103 void end_submenu(void *parent, void *submenu)
107 OSStatus query_context_menu(void *_me, const AEDescList *selection,
108 AEDescList *menu)
110 struct plugin_data *me = _me;
111 struct osx_menu_data osx_data = { menu, selection, noErr , 0 };
113 /* currently this fails when multiple files/directories are
114 * selected
116 * TODO: add support to handle selection of multiple items
117 * e.g. selection_to_path could be called more often until no
118 * item is left
120 if (!selection_to_path(me->git_data.name, MAX_PATH, selection))
121 return noErr;
123 debug_git("Selected: %s", me->git_data.name);
125 build_cheetah_menu(&me->git_data, &osx_data);
127 return osx_data.status;
130 struct menu_argv_data {
131 char *apple_script;
132 const char **argv;
135 static void free_platform_argv(void *data)
137 struct menu_argv_data *my_data = data;
139 free(my_data->argv);
140 free(my_data->apple_script);
141 free(my_data);
144 const char **menu_get_platform_argv(menu_commands cmd, const void *data,
145 free_func_t *free_argv, void **argv_data)
147 struct menu_argv_data *my_data;
148 int script_len;
149 const char *wd;
150 char *apple_script;
151 const char **argv = NULL;
152 const char *bash_argv[] = { "osascript", "-e",
153 "tell application \"Terminal\"", "-e",
154 NULL, "-e", "end tell", NULL };
156 *argv_data = NULL;
157 *free_argv = NULL;
159 switch(cmd)
161 case MENU_BASH:
162 wd = (const char *) data;
164 my_data = xmalloc(sizeof(struct menu_argv_data));
165 apple_script = xmalloc((MAX_PATH+32) * sizeof(char));
166 argv = xmalloc(sizeof(bash_argv));
168 bash_argv[4] = apple_script;
169 my_data->apple_script = apple_script;
170 my_data->argv = argv;
172 memcpy(argv, bash_argv, sizeof(bash_argv));
174 script_len = snprintf(apple_script, MAX_PATH+32,
175 "do script \"cd %s\"", wd);
176 if (script_len >= (MAX_PATH+32))
177 argv = NULL;
179 *argv_data = my_data;
180 *free_argv = free_platform_argv;
182 break;
184 default:
185 return NULL;
188 return argv;
191 /* this is called by the finder after clicking on some item from us */
192 OSStatus invoke_command(void *_me, AEDesc *selection,
193 SInt32 id)
195 struct plugin_data *me = _me;
196 char path[MAX_PATH];
197 if (!selection_to_path(path, MAX_PATH, selection))
198 return noErr;
200 debug_git("invoke_command: %s, id: %i", path, id);
201 handle_menu_item(&me->git_data, id);
203 return noErr;
206 /* this is called after display of the menu to give the plugin a chance
207 * to cleanup anything needed during display phase
209 void cleanup_context_menu(void *_me) {
210 /* we do not need to cleanup anything */