To: vim-dev@vim.org Subject: Patch 5.6a.027 (extra) Fcc: outbox From: Bram Moolenaar ------------ Note: This is just the source code, please compile yourself. Note2: You need to create the "GvimExt" directory first. Patch 5.6a.027 (extra) Problem: Win32 GUI: The "Edit with Vim" popup menu entry causes problems for the Office toolbar. Solution: Use a shell extension dll. (Tianmiao Hu) Added it to the install and uninstal programs, replaces the old "Edit with Vim" menu registry entries. Files: src/dosinst.c, src/uninstal.c, gvimext/*, runtime/doc/gui_w32.txt *** ../vim-5.6a.26/src/dosinst.c Mon Dec 20 09:59:09 1999 --- src/dosinst.c Fri Jan 14 22:38:22 2000 *************** *** 48,53 **** --- 48,54 ---- /* * Return TRUE if the user types a 'y' or 'Y', FALSE otherwise. + * Eats white space first. */ int confirm(void) *************** *** 250,256 **** # define VER_PLATFORM_WIN32_WINDOWS 1 #endif - static void PlatformId(void); static DWORD g_PlatformId; /* --- 251,256 ---- *************** *** 507,512 **** --- 507,513 ---- int vimdirend; int need_vimvar = 1; /* need to set $VIM */ int has_gvim = 0; /* gvim.exe exists */ + struct stat st; #ifdef DJGPP /* *************** *** 748,756 **** /* * Add some entries to the registry to add "Edit with Vim" to the context * menu. ! * Only do this when gvim.exe was found and regedit.exe exists. */ if (has_gvim #ifndef WIN32 && searchpath("regedit.exe") != NULL #endif --- 749,759 ---- /* * Add some entries to the registry to add "Edit with Vim" to the context * menu. ! * Only do this when gvim.exe was found and both gvimext.dll and ! * regedit.exe exist. */ if (has_gvim + && stat("gvimext.dll", &st) >= 0 #ifndef WIN32 && searchpath("regedit.exe") != NULL #endif *************** *** 758,767 **** { printf("\nI can install an entry in the popup menu for the right\n"); printf("mouse button, so that you can edit any file with Vim.\n"); - printf("(NOTE: The MS-Office toolbar has a problem with this!)\n"); printf("Do you want me to do this? (Y/N) "); if (!confirm()) ! printf("didn't change popup menu\n"); else { fd = fopen("vim.reg", "w"); --- 761,769 ---- { printf("\nI can install an entry in the popup menu for the right\n"); printf("mouse button, so that you can edit any file with Vim.\n"); printf("Do you want me to do this? (Y/N) "); if (!confirm()) ! printf("didn't add Vim popup menu entry\n"); else { fd = fopen("vim.reg", "w"); *************** *** 771,786 **** { char buf[BUFSIZE]; ! /* The registry entries for the "Edit with Vim" menu */ ! fprintf(fd, "REGEDIT4\n\n"); ! fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\shell\\Vim]\n"); ! fprintf(fd, "@=\"Edit with &Vim\"\n\n"); ! fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\shell\\Vim\\command]\n"); double_bs(exedir, buf); /* double the backslashes */ ! fprintf(fd, "@=\"%sgvim.exe \\\"%%L\\\"\"\n\n", buf); /* The registry entries for uninstalling the menu */ ! fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\vim %s]\n", VIM_VERSION_SHORT); fprintf(fd, "\"DisplayName\"=\"Vim %s: Edit with Vim popup menu entry\"\n", VIM_VERSION_SHORT); double_bs(vimdir, buf); /* double the backslashes */ fprintf(fd, "\"UninstallString\"=\"%suninstal.exe\"\n", buf); --- 773,803 ---- { char buf[BUFSIZE]; ! /* ! * Write the registry entries for the "Edit with Vim" menu. ! */ ! fprintf(fd, "REGEDIT4\n"); ! fprintf(fd, "\n"); ! fprintf(fd, "HKEY_CLASSES_ROOT\\CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\n"); ! fprintf(fd, "@=\"Vim Shell Extension\"\n"); ! fprintf(fd, "[HKEY_CLASSES_ROOT\\CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\\InProcServer32]\n"); ! double_bs(vimdir, buf); /* double the backslashes */ ! fprintf(fd, "@=\"%sgvimext.dll\"\n", buf); ! fprintf(fd, "\"ThreadingModel\"=\"Apartment\"\n"); ! fprintf(fd, "\n"); ! fprintf(fd, "[HKEY_CLASSES_ROOT\\*\\shellex\\ContextMenuHandlers\\gvim]\n"); ! fprintf(fd, "@=\"{51EEE242-AD87-11d3-9C1E-0090278BBD99}\"\n"); ! fprintf(fd, "\n"); ! fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved]\n"); ! fprintf(fd, "\"{51EEE242-AD87-11d3-9C1E-0090278BBD99}\"=\"Vim Shell Extension\"\n"); ! fprintf(fd, "\n"); ! fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Vim\\Gvim]\n"); double_bs(exedir, buf); /* double the backslashes */ ! fprintf(fd, "\"path\"=\"%sgvim.exe\"\n", buf); ! fprintf(fd, "\n"); /* The registry entries for uninstalling the menu */ ! fprintf(fd, "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim %s]\n", VIM_VERSION_SHORT); fprintf(fd, "\"DisplayName\"=\"Vim %s: Edit with Vim popup menu entry\"\n", VIM_VERSION_SHORT); double_bs(vimdir, buf); /* double the backslashes */ fprintf(fd, "\"UninstallString\"=\"%suninstal.exe\"\n", buf); *** ../vim-5.6a.26/src/uninstal.c Mon Dec 20 09:59:15 1999 --- src/uninstal.c Fri Jan 14 22:40:47 2000 *************** *** 36,54 **** main(int argc, char *argv[]) { int fail = 0; printf("This program will remove the \"Edit with Vim\" entry from the popup menu\n"); printf("Continue (y/n)? "); if (confirm()) { ! if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\shell\\Vim\\command") ! != ERROR_SUCCESS) ++fail; ! if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\shell\\Vim") != ERROR_SUCCESS) ++fail; if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT) != ERROR_SUCCESS) ++fail; ! if (fail == 3) printf("No Vim registry entries could be removed\n"); else if (fail) printf("Some Vim registry entries could not be removed\n"); --- 36,70 ---- main(int argc, char *argv[]) { int fail = 0; + HKEY kh; printf("This program will remove the \"Edit with Vim\" entry from the popup menu.\n"); + printf("It will NOT delete the Vim executable or runtime files.\n"); printf("Continue (y/n)? "); if (confirm()) { ! if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\\InProcServer32") != ERROR_SUCCESS) ++fail; ! if (RegDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS) ! ++fail; ! if (RegDeleteKey(HKEY_CLASSES_ROOT, "*\\shellex\\ContextMenuHandlers\\gvim") != ERROR_SUCCESS) ! ++fail; ! if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0, KEY_ALL_ACCESS, &kh) != ERROR_SUCCESS) ! ++fail; ! else ! { ! if (RegDeleteValue(kh, "{51EEE242-AD87-11d3-9C1E-0090278BBD99}") != ERROR_SUCCESS) ! ++fail; ! RegCloseKey(kh); ! } ! if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim") != ERROR_SUCCESS) ! ++fail; ! if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Vim") != ERROR_SUCCESS) ++fail; if (RegDeleteKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Vim " VIM_VERSION_SHORT) != ERROR_SUCCESS) ++fail; ! ! if (fail == 7) printf("No Vim registry entries could be removed\n"); else if (fail) printf("Some Vim registry entries could not be removed\n"); diff -crN ../vim-5.6a.26/GvimExt/GvimExt.reg GvimExt/GvimExt.reg *** ../vim-5.6a.26/GvimExt/GvimExt.reg Thu Jan 1 01:00:00 1970 --- GvimExt/GvimExt.reg Fri Jan 14 16:01:29 2000 *************** *** 0 **** --- 1,20 ---- + REGEDIT4 + + [HKEY_CLASSES_ROOT\CLSID\{51EEE242-AD87-11d3-9C1E-0090278BBD99}] + @="Vim Shell Extension" + [HKEY_CLASSES_ROOT\CLSID\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\InProcServer32] + @="gvimext.dll" + "ThreadingModel"="Apartment" + + [HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\gvim] + @="{51EEE242-AD87-11d3-9C1E-0090278BBD99}" + + [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved] + "{51EEE242-AD87-11d3-9C1E-0090278BBD99}"="Vim Shell Extension" + + [HKEY_LOCAL_MACHINE\Software\Vim\Gvim] + "path"="gvim.exe" + + [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Vim 5.6] + "DisplayName"="Vim 5.6: Edit with Vim popup menu entry" + "UninstallString"="uninstal.exe" diff -crN ../vim-5.6a.26/GvimExt/Makefile GvimExt/Makefile *** ../vim-5.6a.26/GvimExt/Makefile Thu Jan 1 01:00:00 1970 --- GvimExt/Makefile Tue Jan 11 20:00:59 2000 *************** *** 0 **** --- 1,17 ---- + TARGETOS=BOTH + APPVER=4.0 + + !include + + all: gvimext.dll + + gvimext.dll: gvimext.obj \ + gvimext.res + $(implib) -machine:$(CPU) -def:gvimext.def $** -out:gvimext.lib + $(link) $(dlllflags) -base:0x1C000000 -out:$*.dll $** $(olelibsdll) shell32.lib gvimext.lib comctl32.lib gvimext.exp + + .cpp.obj: + $(cc) $(cflags) $(cvarsdll) $*.cpp + + gvimext.res: gvimext.rc + $(rc) $(rcflags) $(rcvars) gvimext.rc diff -crN ../vim-5.6a.26/GvimExt/README.txt GvimExt/README.txt *** ../vim-5.6a.26/GvimExt/README.txt Thu Jan 1 01:00:00 1970 --- GvimExt/README.txt Fri Jan 14 17:13:33 2000 *************** *** 0 **** --- 1,88 ---- + README.txt for the gvimext DLL. + + Written by Tianmiao Hu. Edited by Bram Moolenaar. + + + INSTALLATION + + To install the "Edit with Vim" popup menu entry, it is recommended to use the + "install.exe" program. It will ask you a few questions and install the needed + registry entries. + + In special situations you might want to make changes by hand. + - The gvimext.dll, gvim.exe and uninstal.exe either need to be in the search + path, or you have to set the full path in the registry entries. You could + move the gvimext.dll to the "windows\system" or "windows\system32" + directory, where the other DLL files are. + - You can find the names of the used registry entries in the file + "GvimExt.reg". You can edit this file to add the paths. To install the + registry entries, right-click the gvimext.reg file and choose the "merge" + menu option. + - The registry key [HKEY_LOCAL_MACHINE\Software\Vim\Gvim] is used by the + gvimext.dll. The value "path" specifies the location of "gvim.exe". If + gvim.exe is in the search path, the path can be omitted. + + + UNINSTALLATION + + To uninstall the "Edit with Vim" popup menu entry, it is recommended to use + the "uninstal.exe" program. + + In special situations you might want to uninstall by hand. + - Open the registry by running regedit.exe. + - Delete all the keys listed in GvimExt.reg, except this one: + [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved] + For this key, only delete one value: + "{51EEE242-AD87-11d3-9C1E-0090278BBD99}"="Vim Shell Extension" + - Delete the gvimext.dll, if you want. You might need to reboot the machine + in order to remove this file. A quick way is to log off and re-login. + + Another method is by using the uninst.bat script: + uninst gvimext.inf + This batch file will remove all the registry keys from the system. Then you + can remove the gvimext.dll file. + Note: In order for this batch file to work, you must have two system files: + rundll32.exe and setupapi.dll. I believe you will have rundll32.exe in your + system. I know windows nt 4.0 with the service pack 4 has setupapi.dll. My + windows 95 has setupapi.dll. I find that the internet explorer 4.0 comes with + the setupapi.dll in file Ie4_5.cab. + + If you do encounter problems running this script, then probably you need to + modify the uninst.bat to suit to your system. Basically, you must find out + where are the locations for your rundll32.exe and setupapi.dll files. In + windows nt, both files are under c:\winnt\system32 directory. In my windows 95 + system, I got setupapi.dll at c:\windows\system and rundll32.exe at + c:\windows. So you might want to try something like: + rundll32.exe c:\windows\system\setupapi.dll,InstallHinfSection DefaultUninstall 128 %1 + where %1 can be substitued by gvimext.inf + + + THE SOURCE CODE + + I have provided the source code here in hope that gvim users around world can + further enhance this little dll. I believe the only thing you need to change + is gvimext.cpp file. The important two functions you need to look at are + QueryContextMenu and InvokeCommand. You can modify righ-click menus in the + QueryContextMenu function and invoke gvim in the InvokeCommand function. Note + the selected files can be accessed from the DragQueryFile function. I am not + familiar with the invoking options for gvim. I believe there are some + improvements that can be made on that side. + + I use MS Visual C++ 6.0's nmake to make the gvimext.dll. I don't have a + chance to try earlier versions of MSVC. The files that are required for build + are: + gvimext.cpp + gvimext.h + gvimext.def + gvimext.rc + resource.h + Makefile + + To compile the DLL from the command line: + vcvars32 + nmake -f Makefile + + If you did something interesting to this dll, please let me know + @ tianmiao@acm.org. + + Happy vimming!!! diff -crN ../vim-5.6a.26/GvimExt/gvimext.cpp GvimExt/gvimext.cpp *** ../vim-5.6a.26/GvimExt/gvimext.cpp Thu Jan 1 01:00:00 1970 --- GvimExt/gvimext.cpp Wed Jan 12 12:38:21 2000 *************** *** 0 **** --- 1,509 ---- + /* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved gvimext by Tianmiao Hu + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + */ + + /* + * gvimext is a DLL which is used for the "Edit with Vim" context menu + * extension. It implements a MS defined interface with the Shell. + * + * If you have any questions or any suggestions concerning gvimext, please + * contact Tianmiao Hu: tianmiao@acm.org. + */ + + #include "gvimext.h" + + // Always get an error while putting the following stuff to the + // gvimext.h file as class protected variables, give up and + // declare them as global stuff + FORMATETC fmte = {CF_HDROP, + (DVTARGETDEVICE FAR *)NULL, + DVASPECT_CONTENT, + -1, + TYMED_HGLOBAL + }; + STGMEDIUM medium; + HRESULT hres = 0; + UINT cbFiles = 0; + + // + // Global variables + // + UINT g_cRefThisDll = 0; // Reference count of this DLL. + HINSTANCE g_hmodThisDll = NULL; // Handle to this DLL itself. + + extern "C" int APIENTRY + DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) + { + if (dwReason == DLL_PROCESS_ATTACH) + { + // Extension DLL one-time initialization + g_hmodThisDll = hInstance; + } + + return 1; // ok + } + + //--------------------------------------------------------------------------- + // DllCanUnloadNow + //--------------------------------------------------------------------------- + + STDAPI DllCanUnloadNow(void) + { + return (g_cRefThisDll == 0 ? S_OK : S_FALSE); + } + + STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut) + { + *ppvOut = NULL; + + if (IsEqualIID(rclsid, CLSID_ShellExtension)) + { + CShellExtClassFactory *pcf = new CShellExtClassFactory; + + return pcf->QueryInterface(riid, ppvOut); + } + + return CLASS_E_CLASSNOTAVAILABLE; + } + + CShellExtClassFactory::CShellExtClassFactory() + { + m_cRef = 0L; + + g_cRefThisDll++; + } + + CShellExtClassFactory::~CShellExtClassFactory() + { + g_cRefThisDll--; + } + + STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid, + LPVOID FAR *ppv) + { + *ppv = NULL; + + // Any interface on this object is the object pointer + + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) + { + *ppv = (LPCLASSFACTORY)this; + + AddRef(); + + return NOERROR; + } + + return E_NOINTERFACE; + } + + STDMETHODIMP_(ULONG) CShellExtClassFactory::AddRef() + { + return ++m_cRef; + } + + STDMETHODIMP_(ULONG) CShellExtClassFactory::Release() + { + if (--m_cRef) + return m_cRef; + + delete this; + + return 0L; + } + + STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, + REFIID riid, + LPVOID *ppvObj) + { + *ppvObj = NULL; + + // Shell extensions typically don't support aggregation (inheritance) + + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + // Create the main shell extension object. The shell will then call + // QueryInterface with IID_IShellExtInit--this is how shell extensions are + // initialized. + + LPCSHELLEXT pShellExt = new CShellExt(); //Create the CShellExt object + + if (NULL == pShellExt) + return E_OUTOFMEMORY; + + return pShellExt->QueryInterface(riid, ppvObj); + } + + + STDMETHODIMP CShellExtClassFactory::LockServer(BOOL fLock) + { + return NOERROR; + } + + // *********************** CShellExt ************************* + CShellExt::CShellExt() + { + m_cRef = 0L; + m_pDataObj = NULL; + + g_cRefThisDll++; + } + + CShellExt::~CShellExt() + { + if (m_pDataObj) + m_pDataObj->Release(); + + g_cRefThisDll--; + } + + STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv) + { + *ppv = NULL; + + if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown)) + { + *ppv = (LPSHELLEXTINIT)this; + } + else if (IsEqualIID(riid, IID_IContextMenu)) + { + *ppv = (LPCONTEXTMENU)this; + } + + if (*ppv) + { + AddRef(); + + return NOERROR; + } + + return E_NOINTERFACE; + } + + STDMETHODIMP_(ULONG) CShellExt::AddRef() + { + return ++m_cRef; + } + + STDMETHODIMP_(ULONG) CShellExt::Release() + { + + if (--m_cRef) + return m_cRef; + + delete this; + + return 0L; + } + + + // + // FUNCTION: CShellExt::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY) + // + // PURPOSE: Called by the shell when initializing a context menu or property + // sheet extension. + // + // PARAMETERS: + // pIDFolder - Specifies the parent folder + // pDataObj - Spefifies the set of items selected in that folder. + // hRegKey - Specifies the type of the focused item in the selection. + // + // RETURN VALUE: + // + // NOERROR in all cases. + // + // COMMENTS: Note that at the time this function is called, we don't know + // (or care) what type of shell extension is being initialized. + // It could be a context menu or a property sheet. + // + + STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder, + LPDATAOBJECT pDataObj, + HKEY hRegKey) + { + // Initialize can be called more than once + HRESULT hres = 0; + + if (m_pDataObj) + m_pDataObj->Release(); + + // duplicate the object pointer and registry handle + + if (pDataObj) + { + m_pDataObj = pDataObj; + pDataObj->AddRef(); + } + + return NOERROR; + } + + + // + // FUNCTION: CShellExt::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT) + // + // PURPOSE: Called by the shell just before the context menu is displayed. + // This is where you add your specific menu items. + // + // PARAMETERS: + // hMenu - Handle to the context menu + // indexMenu - Index of where to begin inserting menu items + // idCmdFirst - Lowest value for new menu ID's + // idCmtLast - Highest value for new menu ID's + // uFlags - Specifies the context of the menu event + // + // RETURN VALUE: + // + // + // COMMENTS: + // + + STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) + { + UINT idCmd = idCmdFirst; + BOOL bAppendItems=TRUE; + + hres = m_pDataObj->GetData(&fmte, &medium); + if (medium.hGlobal) + cbFiles = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, 0, 0); + + // InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); + + if (cbFiles > 1) + { + InsertMenu(hMenu, + indexMenu++, + MF_STRING|MF_BYPOSITION, + idCmd++, + "Edit with multiple &Vims"); + + InsertMenu(hMenu, + indexMenu++, + MF_STRING|MF_BYPOSITION, + idCmd++, + "Edit with single &Vim"); + } + else + { + InsertMenu(hMenu, + indexMenu++, + MF_STRING|MF_BYPOSITION, + idCmd++, + "Edit with &Vim"); + } + + // InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); + + // Must return number of menu items we added. + return ResultFromShort(idCmd-idCmdFirst); + } + + // + // FUNCTION: CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO) + // + // PURPOSE: Called by the shell after the user has selected on of the + // menu items that was added in QueryContextMenu(). + // + // PARAMETERS: + // lpcmi - Pointer to an CMINVOKECOMMANDINFO structure + // + // RETURN VALUE: + // + // + // COMMENTS: + // + + STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) + { + HRESULT hr = E_INVALIDARG; + + // If HIWORD(lpcmi->lpVerb) then we have been called programmatically + // and lpVerb is a command that should be invoked. Otherwise, the shell + // has called us, and LOWORD(lpcmi->lpVerb) is the menu ID the user has + // selected. Actually, it's (menu ID - idCmdFirst) from QueryContextMenu(). + if (!HIWORD(lpcmi->lpVerb)) + { + UINT idCmd = LOWORD(lpcmi->lpVerb); + + switch(idCmd) + { + case 0: + hr = InvokeGvim(lpcmi->hwnd, + lpcmi->lpDirectory, + lpcmi->lpVerb, + lpcmi->lpParameters, + lpcmi->nShow); + break; + case 1: + hr = InvokeSingleGvim(lpcmi->hwnd, + lpcmi->lpDirectory, + lpcmi->lpVerb, + lpcmi->lpParameters, + lpcmi->nShow); + break; + } + } + return hr; + } + + STDMETHODIMP CShellExt::GetCommandString(UINT idCmd, + UINT uFlags, + UINT FAR *reserved, + LPSTR pszName, + UINT cchMax) + { + switch (idCmd) + { + case 0: + lstrcpy(pszName, "Edits the selected file(s) with Vim"); + break; + } + + return NOERROR; + } + + static void + getGvimName(char *name) + { + HKEY keyhandle; + DWORD hlen; + + /* Get the location of gvim.exe from the registry. */ + name[0] = 0; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, + KEY_READ, &keyhandle) == ERROR_SUCCESS) + { + hlen = MAX_PATH; + if (RegQueryValueEx(keyhandle, "path", 0, NULL, (BYTE *)name, &hlen) + != ERROR_SUCCESS) + name[0] = 0; + else + name[hlen] = 0; + RegCloseKey(keyhandle); + } + if (name[0] == 0) + strcpy(name, "gvim.exe"); + } + + STDMETHODIMP CShellExt::InvokeGvim(HWND hParent, + LPCSTR pszWorkingDir, + LPCSTR pszCmd, + LPCSTR pszParam, + int iShowCmd) + { + char m_szFileUserClickedOn[MAX_PATH]; + char cmdStr[MAX_PATH]; + + UINT i; + for (i = 0; i < cbFiles; i++) + { + DragQueryFile((HDROP)medium.hGlobal, + i, + m_szFileUserClickedOn, + sizeof(m_szFileUserClickedOn)); + + getGvimName(cmdStr); + strcat(cmdStr, " \""); + + if ((strlen(cmdStr) + strlen(m_szFileUserClickedOn) + 2) < MAX_PATH) + { + strcat(cmdStr, m_szFileUserClickedOn); + strcat(cmdStr, "\""); + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + // Start the child process. + if (!CreateProcess(NULL, // No module name (use command line). + cmdStr, // Command line. + NULL, // Process handle not inheritable. + NULL, // Thread handle not inheritable. + FALSE, // Set handle inheritance to FALSE. + 0, // No creation flags. + NULL, // Use parent's environment block. + NULL, // Use parent's starting directory. + &si, // Pointer to STARTUPINFO structure. + &pi) // Pointer to PROCESS_INFORMATION structure. + ) + { + MessageBox(hParent, "Error creating process: Check if gvim.exe is in your path!", "gvimext.dll error", MB_OK); + } + } + else + { + MessageBox(hParent, "Path length too long!", "gvimext.dll error", MB_OK); + } + } + + return NOERROR; + } + + + STDMETHODIMP CShellExt::InvokeSingleGvim(HWND hParent, + LPCSTR pszWorkingDir, + LPCSTR pszCmd, + LPCSTR pszParam, + int iShowCmd) + { + char m_szFileUserClickedOn[MAX_PATH]; + char cmdStr[MAX_PATH]; + UINT i; + + getGvimName(cmdStr); + for (i = 0; i < cbFiles; i++) + { + DragQueryFile((HDROP)medium.hGlobal, + i, + m_szFileUserClickedOn, + sizeof(m_szFileUserClickedOn)); + + if ((strlen(cmdStr) + strlen(m_szFileUserClickedOn) + 4) < MAX_PATH) + { + strcat(cmdStr, " \""); + strcat(cmdStr, m_szFileUserClickedOn); + strcat(cmdStr, "\""); + } + else + { + MessageBox(hParent, "Path length too long or too many files selected!", "gvimext.dll error", MB_OK); + + return NOERROR; + } + } + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + // Start the child process. + if (!CreateProcess(NULL, // No module name (use command line). + cmdStr, // Command line. + NULL, // Process handle not inheritable. + NULL, // Thread handle not inheritable. + FALSE, // Set handle inheritance to FALSE. + 0, // No creation flags. + NULL, // Use parent's environment block. + NULL, // Use parent's starting directory. + &si, // Pointer to STARTUPINFO structure. + &pi) // Pointer to PROCESS_INFORMATION structure. + ) + { + MessageBox(hParent, "Error creating process: Check if gvim.exe is in your path!", "gvimext.dll error", MB_OK); + } + + return NOERROR; + } diff -crN ../vim-5.6a.26/GvimExt/gvimext.def GvimExt/gvimext.def *** ../vim-5.6a.26/GvimExt/gvimext.def Thu Jan 1 01:00:00 1970 --- GvimExt/gvimext.def Fri Jan 14 17:03:08 2000 *************** *** 0 **** --- 1,8 ---- + ;gvimdef.def : Declares the module parameters for the DLL. + + LIBRARY gvimext + DESCRIPTION 'Vim Shell Extension' + + EXPORTS + DllCanUnloadNow private + DllGetClassObject private diff -crN ../vim-5.6a.26/GvimExt/gvimext.h GvimExt/gvimext.h *** ../vim-5.6a.26/GvimExt/gvimext.h Thu Jan 1 01:00:00 1970 --- GvimExt/gvimext.h Wed Jan 12 12:13:56 2000 *************** *** 0 **** --- 1,152 ---- + /* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved gvimext by Tianmiao Hu + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + */ + + /* + * If you have any questions or any suggestions concerning gvimext, please + * contact Tianmiao Hu: tianmiao@acm.org. + */ + + #if !defined(AFX_STDAFX_H__3389658B_AD83_11D3_9C1E_0090278BBD99__INCLUDED_) + #define AFX_STDAFX_H__3389658B_AD83_11D3_9C1E_0090278BBD99__INCLUDED_ + + #if _MSC_VER > 1000 + #pragma once + #endif // _MSC_VER > 1000 + + // Insert your headers here + // #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + + //-------------------------------------------------------------- + // common user interface routines + // + // + //-------------------------------------------------------------- + + #ifndef STRICT + #define STRICT + #endif + + #define INC_OLE2 // WIN32, get ole2 from windows.h + + #include + #include + #include + + #define ResultFromShort(i) ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, (USHORT)(i))) + + // Initialize GUIDs (should be done only and at-least once per DLL/EXE) + // + #pragma data_seg(".text") + #define INITGUID + #include + #include + + // + // The class ID of this Shell extension class. + // + // class id: {51EEE242-AD87-11d3-9C1E-0090278BBD99} + // + // + // NOTE!!! If you use this shell extension as a starting point, + // you MUST change the GUID below. Simply run UUIDGEN.EXE + // to generate a new GUID. + // + + // {51EEE242-AD87-11d3-9C1E-0090278BBD99} + // static const GUID <> = + // { 0x51eee242, 0xad87, 0x11d3, { 0x9c, 0x1e, 0x0, 0x90, 0x27, 0x8b, 0xbd, 0x99 } }; + // + // + + // {51EEE242-AD87-11d3-9C1E-0090278BBD99} + // IMPLEMENT_OLECREATE(<>, <>, + // 0x51eee242, 0xad87, 0x11d3, 0x9c, 0x1e, 0x0, 0x90, 0x27, 0x8b, 0xbd, 0x99); + // + + // {51EEE242-AD87-11d3-9C1E-0090278BBD99} -- this is the registry format + DEFINE_GUID(CLSID_ShellExtension, 0x51eee242, 0xad87, 0x11d3, 0x9c, 0x1e, 0x0, 0x90, 0x27, 0x8b, 0xbd, 0x99); + + + // this class factory object creates context menu handlers for windows 32 shell + class CShellExtClassFactory : public IClassFactory + { + protected: + ULONG m_cRef; + + public: + CShellExtClassFactory(); + ~CShellExtClassFactory(); + + //IUnknown members + STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + //IClassFactory members + STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *); + STDMETHODIMP LockServer(BOOL); + + }; + typedef CShellExtClassFactory *LPCSHELLEXTCLASSFACTORY; + + // this is the actual OLE Shell context menu handler + class CShellExt : public IContextMenu, + IShellExtInit + { + public: + + protected: + ULONG m_cRef; + LPDATAOBJECT m_pDataObj; + + STDMETHODIMP InvokeGvim(HWND hParent, + LPCSTR pszWorkingDir, + LPCSTR pszCmd, + LPCSTR pszParam, + int iShowCmd); + + STDMETHODIMP InvokeSingleGvim(HWND hParent, + LPCSTR pszWorkingDir, + LPCSTR pszCmd, + LPCSTR pszParam, + int iShowCmd); + + public: + CShellExt(); + ~CShellExt(); + + //IUnknown members + STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + //IShell members + STDMETHODIMP QueryContextMenu(HMENU hMenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags); + + STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi); + + STDMETHODIMP GetCommandString(UINT idCmd, + UINT uFlags, + UINT FAR *reserved, + LPSTR pszName, + UINT cchMax); + + //IShellExtInit methods + STDMETHODIMP Initialize(LPCITEMIDLIST pIDFolder, + LPDATAOBJECT pDataObj, + HKEY hKeyID); + }; + + typedef CShellExt *LPCSHELLEXT; + #pragma data_seg() + + #endif diff -crN ../vim-5.6a.26/GvimExt/gvimext.inf GvimExt/gvimext.inf *** ../vim-5.6a.26/GvimExt/gvimext.inf Thu Jan 1 01:00:00 1970 --- GvimExt/gvimext.inf Fri Jan 14 16:46:13 2000 *************** *** 0 **** --- 1,22 ---- + [Version] + Signature="$Windows NT$"" + Provider="Tianmiao" + + [Manufacture] + + [DefaultInstall] + AddReg=ThisDll.Add.Reg + + [DefaultUninstall] + DelReg=ThisDLL.Add.Reg + + [ThisDll.Add.Reg] + HKCR,CLSID\{51EEE242-AD87-11d3-9C1E-0090278BBD99} + HKCR,CLSID\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\InProcServer32 + HKCR,*\shellex\ContextMenuHandlers\gvim + HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved",{51EEE242-AD87-11d3-9C1E-0090278BBD99} + HKLM,Software\Vim\Gvim + HKLM,"Software\Microsoft\Windows\CurrentVersion\Uninstall\Vim 5.6" + + [Strings] + ThisDll="gvimext.dll" diff -crN ../vim-5.6a.26/GvimExt/gvimext.rc GvimExt/gvimext.rc *** ../vim-5.6a.26/GvimExt/gvimext.rc Thu Jan 1 01:00:00 1970 --- GvimExt/gvimext.rc Mon Jan 10 20:02:11 2000 *************** *** 0 **** --- 1,109 ---- + //Microsoft Developer Studio generated resource script. + // + #include "resource.h" + + #define APSTUDIO_READONLY_SYMBOLS + ///////////////////////////////////////////////////////////////////////////// + // + // Generated from the TEXTINCLUDE 2 resource. + // + #include "afxres.h" + + ///////////////////////////////////////////////////////////////////////////// + #undef APSTUDIO_READONLY_SYMBOLS + + ///////////////////////////////////////////////////////////////////////////// + // English (U.S.) resources + + #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) + #ifdef _WIN32 + LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + #pragma code_page(1252) + #endif //_WIN32 + + #ifndef _MAC + ///////////////////////////////////////////////////////////////////////////// + // + // Version + // + + VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL + #ifdef _DEBUG + FILEFLAGS 0x3L + #else + FILEFLAGS 0x2L + #endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Developed using COM architecture!\0" + VALUE "CompanyName", "Tianmiao Hu's Developer Studio\0" + VALUE "FileDescription", "A small project for the context menu of gvim!\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "gvim righ-click menu extension\0" + VALUE "LegalCopyright", "Copyright © 1999 Tianmiao Hu\0" + VALUE "LegalTrademarks", "Tianmiao Hu's Gvim Context Menu Extension\0" + VALUE "OriginalFilename", "gvimext.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Tianmiao Hu's gvimext context menu extension\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END + END + + #endif // !_MAC + + + #ifdef APSTUDIO_INVOKED + ///////////////////////////////////////////////////////////////////////////// + // + // TEXTINCLUDE + // + + 1 TEXTINCLUDE DISCARDABLE + BEGIN + "resource.h\0" + END + + 2 TEXTINCLUDE DISCARDABLE + BEGIN + "#include ""afxres.h""\r\n" + "\0" + END + + 3 TEXTINCLUDE DISCARDABLE + BEGIN + "\r\n" + "\0" + END + + #endif // APSTUDIO_INVOKED + + #endif // English (U.S.) resources + ///////////////////////////////////////////////////////////////////////////// + + + + #ifndef APSTUDIO_INVOKED + ///////////////////////////////////////////////////////////////////////////// + // + // Generated from the TEXTINCLUDE 3 resource. + // + + + ///////////////////////////////////////////////////////////////////////////// + #endif // not APSTUDIO_INVOKED + diff -crN ../vim-5.6a.26/GvimExt/resource.h GvimExt/resource.h *** ../vim-5.6a.26/GvimExt/resource.h Thu Jan 1 01:00:00 1970 --- GvimExt/resource.h Mon Jan 10 20:02:29 2000 *************** *** 0 **** --- 1,15 ---- + //{{NO_DEPENDENCIES}} + // Microsoft Developer Studio generated include file. + // Used by gvimext.rc + // + + // Next default values for new objects + // + #ifdef APSTUDIO_INVOKED + #ifndef APSTUDIO_READONLY_SYMBOLS + #define _APS_NEXT_RESOURCE_VALUE 101 + #define _APS_NEXT_COMMAND_VALUE 40001 + #define _APS_NEXT_CONTROL_VALUE 1000 + #define _APS_NEXT_SYMED_VALUE 101 + #endif + #endif diff -crN ../vim-5.6a.26/GvimExt/uninst.bat GvimExt/uninst.bat *** ../vim-5.6a.26/GvimExt/uninst.bat Thu Jan 1 01:00:00 1970 --- GvimExt/uninst.bat Mon Jan 10 20:02:34 2000 *************** *** 0 **** --- 1 ---- + rundll32.exe setupapi,InstallHinfSection DefaultUninstall 128 %1 *** ../vim-5.6a.26/runtime/doc/gui_w32.txt Mon Dec 20 09:59:30 1999 --- runtime/doc/gui_w32.txt Fri Jan 14 16:17:32 2000 *************** *** 1,4 **** ! *gui_w32.txt* For Vim version 5.6a. Last change: 1999 Oct 17 VIM REFERENCE MANUAL by Bram Moolenaar --- 1,4 ---- ! *gui_w32.txt* For Vim version 5.6a. Last change: 2000 Jan 01 VIM REFERENCE MANUAL by Bram Moolenaar *************** *** 77,88 **** Another method, which also works When you put Vim in another directory (e.g., when you have got a new version): ! 1. Put focus on a file you want Vim to use with 2. ! 3. ! 4. ! 5. Browse to the (new) location of Vim and click ! 6. checked 7. *send-to-menu* *sendto* --- 77,88 ---- Another method, which also works When you put Vim in another directory (e.g., when you have got a new version): ! 1. select a file you want to use Vim with 2. ! 3. select "Open With..." menu entry ! 4. click "Other..." ! 5. browse to the (new) location of Vim and click "Open" ! 6. make "Always Use this program..." checked 7. *send-to-menu* *sendto* *************** *** 103,133 **** A more drastic approach is to install an "Edit with Vim" entry in the popup menu for the right mouse button. With this you can edit any file with Vim. *install-registry* ! You can add this in an easy way by using the "install.exe" program. It will ! add two registry entries for you. - You can also do this by hand: 1. Start the registry editor with "regedit". ! 2. Add two keys: ! key value ~ ! HKEY_CLASSES_ROOT\*\shell\Vim Edit with &Vim ! HKEY_CLASSES_ROOT\*\shell\Vim\command {path}\gvim.exe "%L" ! ! Replace {path} with the path that leads to gvim.exe. ! Don't forget the double quotes around %L, file names with a space won't ! work. ! ! NOTE: Problems have been reported with using this in combination with the ! MS-Office taskbar. This appears to be a problem in MS-Office. Don't ! use this if you want to use the MS-Office taskbar. To remove "Edit with Vim" from the popup menu, just remove the registry ! entries mentioned above. ! If you notice that this entry overrules other file type associatons, set those ! associations again by hand (using Windows Explorer, see above). This only ! seems to happen on some Windows NT versions (Windows bug?). Procedure: 1. Find the name of the file type. This can be done by starting the registry editor, and searching for the extension in \\HKEY_CLASSES_ROOT 2. In a Windows Explorer, use View/Options/File Types. Search for the file --- 103,159 ---- A more drastic approach is to install an "Edit with Vim" entry in the popup menu for the right mouse button. With this you can edit any file with Vim. + This can co-exist with the file associations mentioned above. The difference + is that the file associations will make starting Vim the default action. With + the "Edit with Vim" menu entry you can keep the existing file association for + double clicking on the file, and edit the file with Vim when you want. For + example, you can associate "*.mak" with your make program. You can execute + the makefile by double clicking it and use the "Edit with Vim" entry to edit + the makefile. + + You can select any files and right-click to see a menu option called "Edit + with gvim". Chosing this menu option will invoke gvim with the file you have + selected. If you select multiple files, you will find two gvim-related menu + options: + "Edit with multiple gvims" -- one gvim for each file in the selection + "Edit with single gvim" -- one gvim for all the files in the selection + *install-registry* ! You can add the "Edit with Vim" menu entry in an easy way by using the ! "install.exe" program. It will add several registry entries for you. ! ! You can also do this by hand. This is complicated! Use the install.exe if ! you can. 1. Start the registry editor with "regedit". ! 2. Add these keys: ! key value name value ~ ! HKEY_CLASSES_ROOT\CLSID\{51EEE242-AD87-11d3-9C1E-0090278BBD99} ! {default} Vim Shell Extension ! HKEY_CLASSES_ROOT\CLSID\{51EEE242-AD87-11d3-9C1E-0090278BBD99}\InProcServer32 ! {default} {path}\gvimext.dll ! ThreadingModel Apartment ! HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\gvim ! {default} {51EEE242-AD87-11d3-9C1E-0090278BBD99} ! HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved ! {51EEE242-AD87-11d3-9C1E-0090278BBD99} ! Vim Shell Extension ! HKEY_LOCAL_MACHINE\Software\Vim\Gvim ! path {path}\gvim.exe ! HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\vim 5.6 ! DisplayName Vim 5.6: Edit with Vim popup menu entry ! UninstallString {path}\uninstal.exe ! ! Replace {path} with the path that leads to the executable. ! Don't type {default}, this is the value for the key itself. To remove "Edit with Vim" from the popup menu, just remove the registry ! entries mentioned above. The "uninstal.exe" program can do this for you. You ! can also use the entry in the Windows standard "Add/Remove Programs" list. ! If you notice that this entry overrules other file type associations, set ! those associations again by hand (using Windows Explorer, see above). This ! only seems to happen on some Windows NT versions (Windows bug?). Procedure: 1. Find the name of the file type. This can be done by starting the registry editor, and searching for the extension in \\HKEY_CLASSES_ROOT 2. In a Windows Explorer, use View/Options/File Types. Search for the file *** ../vim-5.6a.26/src/version.c Fri Jan 14 22:30:09 2000 --- src/version.c Fri Jan 14 22:37:01 2000 *************** *** 420,421 **** --- 420,423 ---- { /* Add new patch number below this line */ + /**/ + 27, /**/ -- hundred-and-one symptoms of being an internet addict: 174. You know what a listserv is. --/-/---- Bram Moolenaar ---- Bram@moolenaar.net ---- Bram@vim.org ---\-\-- \ \ www.vim.org/iccf www.moolenaar.net www.vim.org / /