Add a simple script to kill and restart explorer and task manager
[git-cheetah.git] / menu.c
blob0df3b3243afe0913479487535063a952c560132f
1 #include <shlobj.h>
2 #include <stdarg.h>
3 #include <tchar.h>
4 #include "menu.h"
5 #include "ext.h"
6 #include "debug.h"
7 #include "systeminfo.h"
9 /*
10 * These are the functions for handling the context menu.
13 static STDMETHODIMP query_context_menu(void *p, HMENU menu,
14 UINT index, UINT first_command,
15 UINT last_command, UINT flags)
17 struct git_menu *this_menu = p;
18 struct git_data *this_ = this_menu->git_data;
20 if (flags & CMF_DEFAULTONLY)
21 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
23 InsertMenu(menu, index, MF_SEPARATOR | MF_BYPOSITION,
24 first_command, "");
25 InsertMenu(menu, index+1, MF_STRING | MF_BYPOSITION,
26 first_command+1, _T("&Git Gui"));
28 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 2);
32 * Perform a couple of transformations, such that a directory
33 * C:\Program Files\Bunch of stuff\in\A dir
34 * becomes
35 * /C/Program\ Files/Bunch\ of\ stuff/in/A\ dir
37 * Assumes path is initially a correctly formed Windows-style path.
38 * Returns a new string.
40 static char * convert_directory_format(const char * path)
42 int i;
43 int size_incr = 0;
45 /* Figure out how much extra space we need to escape spaces */
46 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
47 if (path[i] == ' ')
48 size_incr++;
50 char * converted = (char *)calloc(size_incr + i + 1, sizeof(char));
51 char * dst = converted;
53 /* Transform:
54 * " " -> "\ "
55 * "\" -> "/"
57 for (i = 0; i < MAX_PATH && path[i] != '\0'; ++i)
59 switch (path[i])
61 case ' ':
62 *(dst++) = '\\';
63 *(dst++) = ' ';
64 break;
65 case '\\':
66 *(dst++) = '/';
67 break;
68 default:
69 *(dst++) = path[i];
70 break;
73 *dst = '\0';
75 /* X: -> /X */
76 converted[1] = converted[0];
77 converted[0] = '/';
79 return converted;
82 static void adjust_path_for_git(const char *msys_path)
84 static int initialized = 0;
86 if (!initialized) {
87 const char *old_path = getenv("PATH");
88 int old_len = strlen(old_path);
89 int msys_path_len = strlen(msys_path);
90 char *new_path = malloc(old_len + 2 * msys_path_len + 23);
91 if (!new_path)
92 return;
93 sprintf(new_path, "PATH=%s\\bin;%s\\mingw\\bin;%s",
94 old_path, msys_path, msys_path);
95 putenv(new_path);
96 initialized = 1;
100 static STDMETHODIMP invoke_command(void *p,
101 LPCMINVOKECOMMANDINFO info)
103 struct git_menu *this_menu = p;
104 struct git_data *this_ = this_menu->git_data;
105 int command = LOWORD(info->lpVerb);
107 if (HIWORD(info->lpVerb) != 0)
108 return E_INVALIDARG;
110 if (command == 1)
112 STARTUPINFO si = { sizeof(si) };
113 PROCESS_INFORMATION pi;
115 TCHAR * msysPath = msys_path();
117 if (msysPath)
119 TCHAR command[1024];
121 adjust_path_for_git(msysPath);
122 wsprintf(command, TEXT("wish.exe \"%s/bin/git-gui\""),
123 msysPath);
126 const char *wd = this_->name;
127 if (wd == NULL || strlen(wd) == 0)
128 wd = info->lpDirectory;
130 DWORD dwAttr = FILE_ATTRIBUTE_DIRECTORY;
131 DWORD fa = GetFileAttributes(wd);
132 if (! (fa & dwAttr))
133 wd = info->lpDirectory;
135 debug_git("Trying to spawn '%s' in working directory '%s'\n", command, wd);
136 if (CreateProcess(
137 NULL,
138 command,
139 NULL,
140 NULL,
141 FALSE,
142 0, NULL, wd, &si, &pi))
144 CloseHandle(pi.hProcess);
145 CloseHandle(pi.hThread);
147 else
149 debug_git("[ERROR] %s/%s:%d Could not create git gui process (%d) Command: %s",
150 __FILE__, __FUNCTION__, __LINE__,
151 GetLastError(), command);
154 else
156 debug_git("[ERROR] %s/%s:%d Could not find msysPath",
157 __FILE__, __FUNCTION__, __LINE__);
160 return S_OK;
163 return E_INVALIDARG;
166 static STDMETHODIMP get_command_string(void *p, UINT id,
167 UINT flags, UINT *reserved,
168 LPSTR name, UINT size)
171 struct git_menu *this_menu = p;
172 struct git_data *this_ = this_menu->git_data;
174 if (id != 1)
175 return E_INVALIDARG;
178 if (flags & GCS_HELPTEXT) {
179 LPCTSTR text = _T("Launch the GIT Gui in the local or chosen directory.");
180 LPWSTR tw = malloc((strlen(text)+1)*sizeof(wchar_t));
181 mbstowcs(tw, text, strlen(text));
182 if (flags & GCS_UNICODE)
183 lstrcpynW((LPWSTR)name, tw, size);
184 else
185 lstrcpynA(name, text, size);
186 free(tw);
187 return S_OK;
191 return E_INVALIDARG;
194 DEFINE_STANDARD_METHODS(git_menu)
196 struct git_menu_virtual_table git_menu_virtual_table = {
197 query_interface_git_menu,
198 add_ref_git_menu,
199 release_git_menu,
200 query_context_menu,
201 invoke_command,
202 get_command_string