Add explanations to Windows-specific menu_item_builder's
[git-cheetah/kirill.git] / menu.c
blobd1c7e33705279f2c361956a3ead8146293953dfe
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 */
31 * menu_item_builder to build a Windows-specific menu separator
33 * Always returns FALSE so the menu engine does not track this item
35 BOOL build_separator(struct git_data *data, const struct menu_item *item,
36 void *platform)
38 struct windows_menu_data *windows_menu = platform;
39 InsertMenu(windows_menu->menu, windows_menu->index,
40 MF_SEPARATOR | MF_BYPOSITION, 0, "");
41 windows_menu->index++;
43 return FALSE;
47 * menu_item_builder to build a simple menu item
49 * Explorer's context menu are limited in the number of comands
50 * that they can use, so build_item would:
51 * - do nothing if that limit is reached and return FALSE to
52 * instruct the menu engine to not track this item
53 * - create item and return TRUE, so the item can be handled later
55 BOOL build_item(struct git_data *data, const struct menu_item *item,
56 void *platform)
58 struct windows_menu_data *windows_menu = platform;
59 if (windows_menu->last < windows_menu->first + next_active_item)
60 return FALSE;
62 InsertMenu(windows_menu->menu, windows_menu->index,
63 MF_STRING | MF_BYPOSITION,
64 windows_menu->first + next_active_item,
65 item->string);
66 windows_menu->index++;
68 return TRUE;
72 * These are the functions for handling the context menu.
75 inline STDMETHODIMP query_context_menu(void *p, HMENU menu,
76 UINT index, UINT first_command,
77 UINT last_command, UINT flags)
79 struct git_menu *this_menu = p;
80 struct git_data *this_ = this_menu->git_data;
81 struct windows_menu_data windows_menu =
82 { menu, index, first_command, last_command };
84 if (flags & CMF_DEFAULTONLY)
85 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
87 build_cheetah_menu(this_, &windows_menu);
89 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL,
90 next_active_item);
94 * Perform a couple of transformations, such that a directory
95 * C:\Program Files\Bunch of stuff\in\A dir
96 * becomes
97 * /C/Program\ Files/Bunch\ of\ stuff/in/A\ dir
99 * Assumes path is initially a correctly formed Windows-style path.
100 * Returns a new string.
102 static char *convert_directory_format(const char *path)
104 int i;
105 int size_incr = 0;
106 char *converted;
107 char *dst;
109 /* Figure out how much extra space we need to escape spaces */
110 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
111 if (path[i] == ' ')
112 size_incr++;
114 converted = (char *)calloc(size_incr + i + 1, sizeof(char));
115 dst = converted;
117 /* Transform:
118 * " " -> "\ "
119 * "\" -> "/"
121 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
123 switch (path[i])
125 case ' ':
126 *(dst++) = '\\';
127 *(dst++) = ' ';
128 break;
129 case '\\':
130 *(dst++) = '/';
131 break;
132 default:
133 *(dst++) = path[i];
134 break;
137 *dst = '\0';
139 /* X: -> /X */
140 converted[1] = converted[0];
141 converted[0] = '/';
143 return converted;
146 inline STDMETHODIMP invoke_command(void *p,
147 LPCMINVOKECOMMANDINFO info)
149 struct git_menu *this_menu = p;
150 struct git_data *this_ = this_menu->git_data;
151 UINT id = LOWORD(info->lpVerb);
153 if (HIWORD(info->lpVerb))
154 return E_INVALIDARG;
156 handle_menu_item(this_, id);
157 return S_OK;
160 inline STDMETHODIMP get_command_string(void *p, UINT id,
161 UINT flags, UINT *reserved,
162 LPSTR name, UINT size)
164 const char *text;
166 if (!(flags & GCS_HELPTEXT))
167 return E_INVALIDARG;
169 text = get_menu_item_text(id);
170 if (!text)
171 return E_INVALIDARG;
173 if (flags & GCS_UNICODE) {
174 size_t len = strlen(text) + 1;
175 LPWSTR tw = malloc(len * sizeof(wchar_t));
176 /* need to convert terminating NULL as well */
177 mbstowcs(tw, text, len);
178 lstrcpynW((LPWSTR)name, tw, size);
179 free(tw);
180 } else
181 lstrcpynA(name, text, size);
183 return S_OK;
186 DEFINE_STANDARD_METHODS(git_menu)
188 struct git_menu_virtual_table git_menu_virtual_table = {
189 query_interface_git_menu,
190 add_ref_git_menu,
191 release_git_menu,
192 query_context_menu,
193 invoke_command,
194 get_command_string