Separate struct git_data from Windows-specific definitions
[git-cheetah/kirill.git] / menu.c
blob15c20a736ca6cdd5a397b9a024c3a935b5afbc43
1 #include "cache.h"
3 #include <shlobj.h>
4 #include <tchar.h>
5 #include "menuengine.h"
6 #include "menu.h"
7 #include "ext.h"
8 #include "debug.h"
9 #include "systeminfo.h"
10 #include "exec.h"
12 #define LONGEST_MENU_ITEM 40
15 * These are the functions for handling the context menu.
18 static STDMETHODIMP query_context_menu(void *p, HMENU menu,
19 UINT index, UINT first_command,
20 UINT last_command, UINT flags)
22 struct git_menu *this_menu = p;
23 struct git_data *this_ = this_menu->git_data;
24 char *wd;
25 BOOL bDirSelected = TRUE;
27 UINT original_first = first_command;
28 char menu_item[LONGEST_MENU_ITEM];
30 int status;
32 if (flags & CMF_DEFAULTONLY)
33 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
35 /* figure out the directory */
36 wd = strdup(this_->name);
37 if (!(FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(wd))) {
38 char *c = strrchr(wd, '\\');
39 if (c) {
40 *c = 0;
41 bDirSelected = FALSE;
45 status = exec_program(wd, NULL, NULL, WAITMODE,
46 "git", "rev-parse", "--show-cdup", NULL);
47 free (wd);
49 /* something really bad happened, could run git */
50 if (status < 0)
51 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
54 * TODO: the following big, ugly code needs to be something like
55 * build_menu_items()
56 * It's left as is to signify the preview nature of the patch
58 if (status) { /* this is not a repository */
59 if (bDirSelected)
60 strcpy(menu_item, "&Git Clone Here");
61 else
62 strcpy(menu_item, "&Git Init Here");
63 } else
64 strcpy(menu_item, "&Git");
66 InsertMenu(menu, index, MF_SEPARATOR | MF_BYPOSITION,
67 first_command++, "");
68 InsertMenu(menu, index+1, MF_STRING | MF_BYPOSITION,
69 first_command++, menu_item);
72 * TODO: when the above block is fixed, we'll just have
73 * return MAKE_RESULT(..., build_menu_items());
75 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL,
76 first_command - original_first);
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 static 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 int command = LOWORD(info->lpVerb);
139 if (HIWORD(info->lpVerb) != 0)
140 return E_INVALIDARG;
142 if (command == 1)
144 const char *wd;
145 DWORD dwAttr, fa;
147 wd = this_->name;
148 if (wd == NULL || strlen(wd) == 0)
149 wd = info->lpDirectory;
151 dwAttr = FILE_ATTRIBUTE_DIRECTORY;
152 fa = GetFileAttributes(wd);
153 if (!(fa & dwAttr))
154 wd = info->lpDirectory;
156 exec_program(wd, NULL, NULL, NORMALMODE,
157 "git", "gui", NULL);
159 return S_OK;
162 return E_INVALIDARG;
165 static STDMETHODIMP get_command_string(void *p, UINT id,
166 UINT flags, UINT *reserved,
167 LPSTR name, UINT size)
170 struct git_menu *this_menu = p;
171 struct git_data *this_ = this_menu->git_data;
173 if (id != 1)
174 return E_INVALIDARG;
177 if (flags & GCS_HELPTEXT) {
178 LPCTSTR text = _T("Launch the GIT Gui in the local or chosen directory.");
179 size_t len = strlen(text) + 1;
180 LPWSTR tw = malloc(len * sizeof(wchar_t));
181 /* need to convert terminating NULL as well */
182 mbstowcs(tw, text, len);
183 /* use Win32 lstrcpyn to [automatically] avoid buffer overflow */
184 if (flags & GCS_UNICODE)
185 lstrcpynW((LPWSTR)name, tw, size);
186 else
187 lstrcpynA(name, text, size);
188 free(tw);
189 return S_OK;
193 return E_INVALIDARG;
196 DEFINE_STANDARD_METHODS(git_menu)
198 struct git_menu_virtual_table git_menu_virtual_table = {
199 query_interface_git_menu,
200 add_ref_git_menu,
201 release_git_menu,
202 query_context_menu,
203 invoke_command,
204 get_command_string