Fix unterminated string when providing a help string.
[git-cheetah/kirill.git] / menu.c
blobbcad14c6bd39aac35ced8cb9ff32debe4512e797
1 #include <shlobj.h>
2 #include <stdarg.h>
3 #include <tchar.h>
4 #include <stdio.h>
5 #include "menu.h"
6 #include "ext.h"
7 #include "debug.h"
8 #include "systeminfo.h"
11 * These are the functions for handling the context menu.
14 static STDMETHODIMP query_context_menu(void *p, HMENU menu,
15 UINT index, UINT first_command,
16 UINT last_command, UINT flags)
18 struct git_menu *this_menu = p;
19 struct git_data *this_ = this_menu->git_data;
21 if (flags & CMF_DEFAULTONLY)
22 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
24 InsertMenu(menu, index, MF_SEPARATOR | MF_BYPOSITION,
25 first_command, "");
26 InsertMenu(menu, index+1, MF_STRING | MF_BYPOSITION,
27 first_command+1, _T("&Git Gui"));
29 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 2);
33 * Perform a couple of transformations, such that a directory
34 * C:\Program Files\Bunch of stuff\in\A dir
35 * becomes
36 * /C/Program\ Files/Bunch\ of\ stuff/in/A\ dir
38 * Assumes path is initially a correctly formed Windows-style path.
39 * Returns a new string.
41 static char *convert_directory_format(const char *path)
43 int i;
44 int size_incr = 0;
45 char *converted;
46 char *dst;
48 /* Figure out how much extra space we need to escape spaces */
49 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
50 if (path[i] == ' ')
51 size_incr++;
53 converted = (char *)calloc(size_incr + i + 1, sizeof(char));
54 dst = converted;
56 /* Transform:
57 * " " -> "\ "
58 * "\" -> "/"
60 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
62 switch (path[i])
64 case ' ':
65 *(dst++) = '\\';
66 *(dst++) = ' ';
67 break;
68 case '\\':
69 *(dst++) = '/';
70 break;
71 default:
72 *(dst++) = path[i];
73 break;
76 *dst = '\0';
78 /* X: -> /X */
79 converted[1] = converted[0];
80 converted[0] = '/';
82 return converted;
85 static void adjust_path_for_git(const char *msys_path)
87 static int initialized = 0;
89 if (!initialized) {
90 const char *old_path = getenv("PATH");
91 size_t old_len = strlen(old_path);
92 size_t msys_path_len = strlen(msys_path);
93 char *new_path = malloc(old_len + 2 * msys_path_len + 23);
94 if (!new_path)
95 return;
96 sprintf(new_path, "PATH=%s\\bin;%s\\mingw\\bin;%s",
97 old_path, msys_path, msys_path);
98 putenv(new_path);
99 initialized = 1;
103 static STDMETHODIMP invoke_command(void *p,
104 LPCMINVOKECOMMANDINFO info)
106 struct git_menu *this_menu = p;
107 struct git_data *this_ = this_menu->git_data;
108 int command = LOWORD(info->lpVerb);
110 if (HIWORD(info->lpVerb) != 0)
111 return E_INVALIDARG;
113 if (command == 1)
115 STARTUPINFO si = { sizeof(si) };
116 PROCESS_INFORMATION pi;
118 TCHAR * msysPath = msys_path();
120 if (msysPath)
122 TCHAR command[1024];
123 const char *wd;
124 DWORD dwAttr, fa;
126 adjust_path_for_git(msysPath);
127 wsprintf(command, TEXT("wish.exe \"%s/bin/git-gui\""),
128 msysPath);
131 wd = this_->name;
132 if (wd == NULL || strlen(wd) == 0)
133 wd = info->lpDirectory;
135 dwAttr = FILE_ATTRIBUTE_DIRECTORY;
136 fa = GetFileAttributes(wd);
137 if (! (fa & dwAttr))
138 wd = info->lpDirectory;
140 debug_git("Trying to spawn '%s' in working directory '%s'\n", command, wd);
141 if (CreateProcess(
142 NULL,
143 command,
144 NULL,
145 NULL,
146 FALSE,
147 0, NULL, wd, &si, &pi))
149 CloseHandle(pi.hProcess);
150 CloseHandle(pi.hThread);
152 else
154 debug_git("[ERROR] %s/%s:%d Could not create git gui process (%d) Command: %s",
155 __FILE__, __FUNCTION__, __LINE__,
156 GetLastError(), command);
159 else
161 debug_git("[ERROR] %s/%s:%d Could not find msysPath",
162 __FILE__, __FUNCTION__, __LINE__);
165 return S_OK;
168 return E_INVALIDARG;
171 static STDMETHODIMP get_command_string(void *p, UINT id,
172 UINT flags, UINT *reserved,
173 LPSTR name, UINT size)
176 struct git_menu *this_menu = p;
177 struct git_data *this_ = this_menu->git_data;
179 if (id != 1)
180 return E_INVALIDARG;
183 if (flags & GCS_HELPTEXT) {
184 LPCTSTR text = _T("Launch the GIT Gui in the local or chosen directory.");
185 size_t len = strlen(text) + 1;
186 LPWSTR tw = malloc(len * sizeof(wchar_t));
187 /* need to convert terminating NULL as well */
188 mbstowcs(tw, text, len);
189 /* use Win32 lstrcpyn to [automatically] avoid buffer overflow */
190 if (flags & GCS_UNICODE)
191 lstrcpynW((LPWSTR)name, tw, size);
192 else
193 lstrcpynA(name, text, size);
194 free(tw);
195 return S_OK;
199 return E_INVALIDARG;
202 DEFINE_STANDARD_METHODS(git_menu)
204 struct git_menu_virtual_table git_menu_virtual_table = {
205 query_interface_git_menu,
206 add_ref_git_menu,
207 release_git_menu,
208 query_context_menu,
209 invoke_command,
210 get_command_string