Add a truly separated git-init in Cheetah menus
[git-cheetah/bosko.git] / menu.c
blobca2b4cbef25ea0db3046cff1a74aeb9e992d0244
1 #include "cache.h"
3 #include <shlobj.h>
4 #include <tchar.h>
5 #include "menuengine.h"
6 #include "cheetahmenu.h"
7 #include "menu.h"
8 #include "ext.h"
9 #include "debug.h"
10 #include "systeminfo.h"
11 #include "exec.h"
13 #define LONGEST_MENU_ITEM 40
16 * Windows-specific Cheetah menu functions
18 struct windows_menu_data {
19 HMENU menu;
20 UINT index;
21 UINT first;
22 UINT last;
25 void reset_platform(void *platform)
27 /* On Windows, we don't do anything to reset the menu */
30 BOOL build_separator(struct git_data *data, const struct menu_item *item,
31 void *platform)
33 struct windows_menu_data *windows_menu = platform;
34 InsertMenu(windows_menu->menu, windows_menu->index,
35 MF_SEPARATOR | MF_BYPOSITION, 0, "");
36 windows_menu->index++;
38 return FALSE;
41 BOOL build_item(struct git_data *data, const struct menu_item *item,
42 void *platform)
44 struct windows_menu_data *windows_menu = platform;
45 if (windows_menu->last < windows_menu->first + next_active_item)
46 return FALSE;
48 InsertMenu(windows_menu->menu, windows_menu->index,
49 MF_STRING | MF_BYPOSITION,
50 windows_menu->first + next_active_item,
51 item->string);
52 windows_menu->index++;
54 return TRUE;
58 * These are the functions for handling the context menu.
61 inline STDMETHODIMP query_context_menu(void *p, HMENU menu,
62 UINT index, UINT first_command,
63 UINT last_command, UINT flags)
65 struct git_menu *this_menu = p;
66 struct git_data *this_ = this_menu->git_data;
67 struct windows_menu_data windows_menu =
68 { menu, index, first_command, last_command };
70 if (flags & CMF_DEFAULTONLY)
71 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
73 build_cheetah_menu(this_, &windows_menu);
75 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL,
76 next_active_item);
80 * Perform a couple of transformations, such that a directory
81 * C:\Program Files\Bunch of stuff\in\A dir
82 * becomes
83 * /C/Program\ Files/Bunch\ of\ stuff/in/A\ dir
85 * Assumes path is initially a correctly formed Windows-style path.
86 * Returns a new string.
88 static char *convert_directory_format(const char *path)
90 int i;
91 int size_incr = 0;
92 char *converted;
93 char *dst;
95 /* Figure out how much extra space we need to escape spaces */
96 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
97 if (path[i] == ' ')
98 size_incr++;
100 converted = (char *)calloc(size_incr + i + 1, sizeof(char));
101 dst = converted;
103 /* Transform:
104 * " " -> "\ "
105 * "\" -> "/"
107 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
109 switch (path[i])
111 case ' ':
112 *(dst++) = '\\';
113 *(dst++) = ' ';
114 break;
115 case '\\':
116 *(dst++) = '/';
117 break;
118 default:
119 *(dst++) = path[i];
120 break;
123 *dst = '\0';
125 /* X: -> /X */
126 converted[1] = converted[0];
127 converted[0] = '/';
129 return converted;
132 inline STDMETHODIMP invoke_command(void *p,
133 LPCMINVOKECOMMANDINFO info)
135 struct git_menu *this_menu = p;
136 struct git_data *this_ = this_menu->git_data;
137 UINT id = LOWORD(info->lpVerb);
139 if (HIWORD(info->lpVerb))
140 return E_INVALIDARG;
142 handle_menu_item(this_, id);
143 return S_OK;
146 inline STDMETHODIMP get_command_string(void *p, UINT id,
147 UINT flags, UINT *reserved,
148 LPSTR name, UINT size)
150 const char *text;
152 if (!(flags & GCS_HELPTEXT))
153 return E_INVALIDARG;
155 text = get_menu_item_text(id);
156 if (!text)
157 return E_INVALIDARG;
159 if (flags & GCS_UNICODE) {
160 size_t len = strlen(text) + 1;
161 LPWSTR tw = malloc(len * sizeof(wchar_t));
162 /* need to convert terminating NULL as well */
163 mbstowcs(tw, text, len);
164 lstrcpynW((LPWSTR)name, tw, size);
165 free(tw);
166 } else
167 lstrcpynA(name, text, size);
169 return S_OK;
172 DEFINE_STANDARD_METHODS(git_menu)
174 struct git_menu_virtual_table git_menu_virtual_table = {
175 query_interface_git_menu,
176 add_ref_git_menu,
177 release_git_menu,
178 query_context_menu,
179 invoke_command,
180 get_command_string