Allow changing the working directory when getting platform arguments
[git-cheetah/kirill.git] / finder / menu.c
blob2096ba4b62a36843f5643a625cfcacc23aad590c
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 MenuItemAttributes attr = item->flags & MI_DISABLED ?
32 kMenuItemAttrSectionHeader : 0;
33 BOOL status = TRUE;
34 char *item_name = strdup(item->string);
35 char shortcut_key;
37 if (!platform)
38 return TRUE;
40 shortcut_key = parse_and_remove_shortcuts(item_name);
42 debug_git("Adding entry: %s", item_name);
44 if ((AECreateList(NULL, 0, true, &menu_entry) != noErr) ||
45 (AEPutKeyPtr(&menu_entry, keyAEName, typeCString, item_name,
46 strlen(item_name) + 1) != noErr) ||
47 (AEPutKeyPtr(&menu_entry, keyContextualMenuCommandID, typeSInt32,
48 &next_active_item, sizeof(next_active_item)) != noErr) ||
49 (AEPutKeyPtr(&menu_entry, keyContextualMenuAttributes, typeSInt32,
50 &attr, sizeof(attr)) != noErr) ||
51 (AEPutDesc(osx_data->menu, 0, &menu_entry) != noErr))
52 status = FALSE;
54 AEDisposeDesc(&menu_entry);
55 free(item_name);
56 return status;
59 BOOL build_separator(struct git_data *me, const struct menu_item *item,
60 void *platform)
62 return TRUE;
65 /* osx does not need to reset anything */
66 void reset_platform(void *platform)
70 void *start_submenu(struct git_data *me, const struct menu_item *item,
71 void *platform)
73 struct osx_menu_data *parent_menu = platform;
74 struct osx_menu_data *submenu =
75 xmalloc(sizeof(struct osx_menu_data));
77 submenu->selection = parent_menu->selection;
78 submenu->status = parent_menu->status;
80 submenu->menu = xmalloc(sizeof(*submenu->menu));
81 submenu->menu->descriptorType = typeNull;
82 submenu->menu->dataHandle = NULL;
83 AECreateList(NULL, 0, false, submenu->menu);
85 submenu->menu_name = strdup(item->string);
86 parse_and_remove_shortcuts(submenu->menu_name);
87 return submenu;
90 void end_submenu(void *parent, void *platform)
92 struct osx_menu_data *parent_menu = parent;
93 struct osx_menu_data *submenu = platform;
94 AERecord menu_entry = { typeNull, NULL };
96 debug_git("Adding submenu: %s", submenu->menu_name);
98 AECreateList(NULL, 0, true, &menu_entry);
99 AEPutKeyPtr(&menu_entry, keyAEName, typeCString, submenu->menu_name,
100 strlen(submenu->menu_name) + 1);
101 AEPutKeyDesc(&menu_entry, keyContextualMenuSubmenu,
102 submenu->menu);
103 AEPutDesc(parent_menu->menu, 0, &menu_entry);
105 AEDisposeDesc(submenu->menu);
106 AEDisposeDesc(&menu_entry);
107 free(submenu->menu_name);
108 free(submenu->menu);
109 free(submenu);
112 OSStatus query_context_menu(void *_me, const AEDescList *selection,
113 AEDescList *menu)
115 struct plugin_data *me = _me;
116 struct osx_menu_data osx_data = { menu, NULL, selection, noErr };
118 /* currently this fails when multiple files/directories are
119 * selected
121 * TODO: add support to handle selection of multiple items
122 * e.g. selection_to_path could be called more often until no
123 * item is left
125 if (!selection_to_path(me->git_data.name, MAX_PATH, selection))
126 return noErr;
128 debug_git("Selected: %s", me->git_data.name);
130 build_cheetah_menu(&me->git_data, &osx_data);
132 return osx_data.status;
135 struct menu_argv_data {
136 char *apple_script;
137 const char **argv;
140 static void free_platform_argv(void *data)
142 struct menu_argv_data *my_data = data;
144 free(my_data->argv);
145 free(my_data->apple_script);
146 free(my_data);
149 const char **menu_get_platform_argv(menu_commands cmd, void *data,
150 free_func_t *free_argv, void **argv_data)
152 struct menu_argv_data *my_data;
153 int script_len;
154 const char *wd;
155 char *apple_script;
156 const char **argv = NULL;
157 const char *bash_argv[] = { "osascript", "-e",
158 "tell application \"Terminal\"", "-e",
159 NULL, "-e", "end tell", NULL };
161 *argv_data = NULL;
162 *free_argv = NULL;
164 switch(cmd)
166 case MENU_BASH:
167 wd = (const char *) data;
169 my_data = xmalloc(sizeof(struct menu_argv_data));
170 apple_script = xmalloc((MAX_PATH+32) * sizeof(char));
171 argv = xmalloc(sizeof(bash_argv));
173 bash_argv[4] = apple_script;
174 my_data->apple_script = apple_script;
175 my_data->argv = argv;
177 memcpy(argv, bash_argv, sizeof(bash_argv));
179 script_len = snprintf(apple_script, MAX_PATH+32,
180 "do script \"cd %s\"", wd);
181 if (script_len >= (MAX_PATH+32))
182 argv = NULL;
184 *argv_data = my_data;
185 *free_argv = free_platform_argv;
187 break;
189 default:
190 return NULL;
193 return argv;
196 /* this is called by the finder after clicking on some item from us */
197 OSStatus invoke_command(void *_me, AEDesc *selection,
198 SInt32 id)
200 struct plugin_data *me = _me;
201 char path[MAX_PATH];
202 if (!selection_to_path(path, MAX_PATH, selection))
203 return noErr;
205 debug_git("invoke_command: %s, id: %i", path, id);
206 handle_menu_item(&me->git_data, id);
208 return noErr;
211 /* this is called after display of the menu to give the plugin a chance
212 * to cleanup anything needed during display phase
214 void cleanup_context_menu(void *_me) {
215 /* we do not need to cleanup anything */