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"
26 BOOL
build_item(struct git_data
*me
, const struct menu_item
*item
,
29 struct osx_menu_data
*osx_data
= platform
;
30 AERecord menu_entry
= { typeNull
, NULL
};
31 MenuItemAttributes attr
= item
->flags
& MI_DISABLED
?
32 kMenuItemAttrSectionHeader
: 0;
34 char *item_name
= strdup(item
->string
);
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
))
54 AEDisposeDesc(&menu_entry
);
59 BOOL
build_separator(struct git_data
*me
, const struct menu_item
*item
,
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
,
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
);
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
,
103 AEPutDesc(parent_menu
->menu
, 0, &menu_entry
);
105 AEDisposeDesc(submenu
->menu
);
106 AEDisposeDesc(&menu_entry
);
107 free(submenu
->menu_name
);
112 OSStatus
query_context_menu(void *_me
, const AEDescList
*selection
,
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
121 * TODO: add support to handle selection of multiple items
122 * e.g. selection_to_path could be called more often until no
125 if (!selection_to_path(me
->git_data
.name
, MAX_PATH
, selection
))
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
{
140 static void free_platform_argv(void *data
)
142 struct menu_argv_data
*my_data
= data
;
145 free(my_data
->apple_script
);
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
;
156 const char **argv
= NULL
;
157 const char *bash_argv
[] = { "osascript", "-e",
158 "tell application \"Terminal\"", "-e",
159 NULL
, "-e", "end tell", NULL
};
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))
184 *argv_data
= my_data
;
185 *free_argv
= free_platform_argv
;
196 /* this is called by the finder after clicking on some item from us */
197 OSStatus
invoke_command(void *_me
, AEDesc
*selection
,
200 struct plugin_data
*me
= _me
;
202 if (!selection_to_path(path
, MAX_PATH
, selection
))
205 debug_git("invoke_command: %s, id: %i", path
, id
);
206 handle_menu_item(&me
->git_data
, id
);
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 */