Implement and use varargs interface to mingw_spawnvpe
[git-cheetah/kirill.git] / menu.c
blob566b7e832a6880825555424b39ec9138b117ccf6
1 #include "cache.h"
3 #include <shlobj.h>
4 #include <tchar.h>
5 #include "menu.h"
6 #include "ext.h"
7 #include "debug.h"
8 #include "systeminfo.h"
9 #include "exec.h"
11 #define LONGEST_MENU_ITEM 40
14 * These are the functions for handling the context menu.
17 static STDMETHODIMP query_context_menu(void *p, HMENU menu,
18 UINT index, UINT first_command,
19 UINT last_command, UINT flags)
21 struct git_menu *this_menu = p;
22 struct git_data *this_ = this_menu->git_data;
23 char *wd;
24 BOOL bDirSelected = TRUE;
26 UINT original_first = first_command;
27 char menu_item[LONGEST_MENU_ITEM];
29 int status;
31 if (flags & CMF_DEFAULTONLY)
32 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
34 /* figure out the directory */
35 wd = strdup(this_->name);
36 if (!(FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(wd))) {
37 char *c = strrchr(wd, '\\');
38 if (c) {
39 *c = 0;
40 bDirSelected = FALSE;
44 status = exec_program(wd, NULL, NULL, WAITMODE,
45 "git", "rev-parse", "--show-cdup", NULL);
46 free (wd);
48 /* something really bad happened, could run git */
49 if (status < 0)
50 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
53 * TODO: the following big, ugly code needs to be something like
54 * build_menu_items()
55 * It's left as is to signify the preview nature of the patch
57 if (status) { /* this is not a repository */
58 if (bDirSelected)
59 strcpy(menu_item, "&Git Clone Here");
60 else
61 strcpy(menu_item, "&Git Init Here");
62 } else
63 strcpy(menu_item, "&Git");
65 InsertMenu(menu, index, MF_SEPARATOR | MF_BYPOSITION,
66 first_command++, "");
67 InsertMenu(menu, index+1, MF_STRING | MF_BYPOSITION,
68 first_command++, menu_item);
71 * TODO: when the above block is fixed, we'll just have
72 * return MAKE_RESULT(..., build_menu_items());
74 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL,
75 first_command - original_first);
79 * Perform a couple of transformations, such that a directory
80 * C:\Program Files\Bunch of stuff\in\A dir
81 * becomes
82 * /C/Program\ Files/Bunch\ of\ stuff/in/A\ dir
84 * Assumes path is initially a correctly formed Windows-style path.
85 * Returns a new string.
87 static char *convert_directory_format(const char *path)
89 int i;
90 int size_incr = 0;
91 char *converted;
92 char *dst;
94 /* Figure out how much extra space we need to escape spaces */
95 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
96 if (path[i] == ' ')
97 size_incr++;
99 converted = (char *)calloc(size_incr + i + 1, sizeof(char));
100 dst = converted;
102 /* Transform:
103 * " " -> "\ "
104 * "\" -> "/"
106 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
108 switch (path[i])
110 case ' ':
111 *(dst++) = '\\';
112 *(dst++) = ' ';
113 break;
114 case '\\':
115 *(dst++) = '/';
116 break;
117 default:
118 *(dst++) = path[i];
119 break;
122 *dst = '\0';
124 /* X: -> /X */
125 converted[1] = converted[0];
126 converted[0] = '/';
128 return converted;
131 static STDMETHODIMP invoke_command(void *p,
132 LPCMINVOKECOMMANDINFO info)
134 struct git_menu *this_menu = p;
135 struct git_data *this_ = this_menu->git_data;
136 int command = LOWORD(info->lpVerb);
138 if (HIWORD(info->lpVerb) != 0)
139 return E_INVALIDARG;
141 if (command == 1)
143 const char *wd;
144 DWORD dwAttr, fa;
146 wd = this_->name;
147 if (wd == NULL || strlen(wd) == 0)
148 wd = info->lpDirectory;
150 dwAttr = FILE_ATTRIBUTE_DIRECTORY;
151 fa = GetFileAttributes(wd);
152 if (!(fa & dwAttr))
153 wd = info->lpDirectory;
155 exec_program(wd, NULL, NULL, NORMALMODE,
156 "git", "gui", NULL);
158 return S_OK;
161 return E_INVALIDARG;
164 static STDMETHODIMP get_command_string(void *p, UINT id,
165 UINT flags, UINT *reserved,
166 LPSTR name, UINT size)
169 struct git_menu *this_menu = p;
170 struct git_data *this_ = this_menu->git_data;
172 if (id != 1)
173 return E_INVALIDARG;
176 if (flags & GCS_HELPTEXT) {
177 LPCTSTR text = _T("Launch the GIT Gui in the local or chosen directory.");
178 size_t len = strlen(text) + 1;
179 LPWSTR tw = malloc(len * sizeof(wchar_t));
180 /* need to convert terminating NULL as well */
181 mbstowcs(tw, text, len);
182 /* use Win32 lstrcpyn to [automatically] avoid buffer overflow */
183 if (flags & GCS_UNICODE)
184 lstrcpynW((LPWSTR)name, tw, size);
185 else
186 lstrcpynA(name, text, size);
187 free(tw);
188 return S_OK;
192 return E_INVALIDARG;
195 DEFINE_STANDARD_METHODS(git_menu)
197 struct git_menu_virtual_table git_menu_virtual_table = {
198 query_interface_git_menu,
199 add_ref_git_menu,
200 release_git_menu,
201 query_context_menu,
202 invoke_command,
203 get_command_string