diff options
Diffstat (limited to 'src/VisVim/Commands.cpp')
-rw-r--r-- | src/VisVim/Commands.cpp | 710 |
1 files changed, 0 insertions, 710 deletions
diff --git a/src/VisVim/Commands.cpp b/src/VisVim/Commands.cpp deleted file mode 100644 index d2c3f838c8..0000000000 --- a/src/VisVim/Commands.cpp +++ /dev/null @@ -1,710 +0,0 @@ -#include "stdafx.h" -#include <comdef.h> // For _bstr_t -#include "VisVim.h" -#include "Commands.h" -#include "OleAut.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; - -#endif - - -// Change directory before opening file? -#define CD_SOURCE 0 // Cd to source path -#define CD_SOURCE_PARENT 1 // Cd to parent directory of source path -#define CD_NONE 2 // No cd - - -static BOOL g_bEnableVim = TRUE; // Vim enabled -static BOOL g_bDevStudioEditor = FALSE; // Open file in Dev Studio editor simultaneously -static BOOL g_bNewTabs = FALSE; -static int g_ChangeDir = CD_NONE; // CD after file open? - -static void VimSetEnableState(BOOL bEnableState); -static BOOL VimOpenFile(BSTR& FileName, long LineNr); -static DISPID VimGetDispatchId(COleAutomationControl& VimOle, char* Method); -static void VimErrDiag(COleAutomationControl& VimOle); -static void VimChangeDir(COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName); -static void DebugMsg(char* Msg, char* Arg = NULL); - - -///////////////////////////////////////////////////////////////////////////// -// CCommands - -CCommands::CCommands() -{ - // m_pApplication == NULL; M$ Code generation bug!!! - m_pApplication = NULL; - m_pApplicationEventsObj = NULL; - m_pDebuggerEventsObj = NULL; -} - -CCommands::~CCommands() -{ - ASSERT(m_pApplication != NULL); - if (m_pApplication) - { - m_pApplication->Release(); - m_pApplication = NULL; - } -} - -void CCommands::SetApplicationObject(IApplication * pApplication) -{ - // This function assumes pApplication has already been AddRef'd - // for us, which CDSAddIn did in its QueryInterface call - // just before it called us. - m_pApplication = pApplication; - if (! m_pApplication) - return; - - // Create Application event handlers - XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj); - if (! m_pApplicationEventsObj) - { - ReportInternalError("XApplicationEventsObj::CreateInstance"); - return; - } - m_pApplicationEventsObj->AddRef(); - m_pApplicationEventsObj->Connect(m_pApplication); - m_pApplicationEventsObj->m_pCommands = this; - -#ifdef NEVER - // Create Debugger event handler - CComPtr < IDispatch > pDebugger; - if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger)) - && pDebugger != NULL) - { - XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj); - m_pDebuggerEventsObj->AddRef(); - m_pDebuggerEventsObj->Connect(pDebugger); - m_pDebuggerEventsObj->m_pCommands = this; - } -#endif - - // Get settings from registry HKEY_CURRENT_USER\Software\Vim\VisVim - HKEY hAppKey = GetAppKey("Vim"); - if (hAppKey) - { - HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim"); - if (hSectionKey) - { - g_bEnableVim = GetRegistryInt(hSectionKey, "EnableVim", - g_bEnableVim); - g_bDevStudioEditor = GetRegistryInt(hSectionKey, - "DevStudioEditor", g_bDevStudioEditor); - g_bNewTabs = GetRegistryInt(hSectionKey, "NewTabs", - g_bNewTabs); - g_ChangeDir = GetRegistryInt(hSectionKey, "ChangeDir", - g_ChangeDir); - RegCloseKey(hSectionKey); - } - RegCloseKey(hAppKey); - } -} - -void CCommands::UnadviseFromEvents() -{ - ASSERT(m_pApplicationEventsObj != NULL); - if (m_pApplicationEventsObj) - { - m_pApplicationEventsObj->Disconnect(m_pApplication); - m_pApplicationEventsObj->Release(); - m_pApplicationEventsObj = NULL; - } - -#ifdef NEVER - if (m_pDebuggerEventsObj) - { - // Since we were able to connect to the Debugger events, we - // should be able to access the Debugger object again to - // unadvise from its events (thus the VERIFY_OK below--see - // stdafx.h). - CComPtr < IDispatch > pDebugger; - VERIFY_OK(m_pApplication->get_Debugger(&pDebugger)); - ASSERT(pDebugger != NULL); - m_pDebuggerEventsObj->Disconnect(pDebugger); - m_pDebuggerEventsObj->Release(); - m_pDebuggerEventsObj = NULL; - } -#endif -} - - -///////////////////////////////////////////////////////////////////////////// -// Event handlers - -// Application events - -HRESULT CCommands::XApplicationEvents::BeforeBuildStart() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -// The open document event handle is the place where the real interface work -// is done. -// Vim gets called from here. -// -HRESULT CCommands::XApplicationEvents::DocumentOpen(IDispatch * theDocument) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (! g_bEnableVim) - // Vim not enabled or empty command line entered - return S_OK; - - // First get the current file name and line number - - // Get the document object - CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(theDocument); - if (! pDoc) - return S_OK; - - BSTR FileName; - long LineNr = -1; - - // Get the document name - if (FAILED(pDoc->get_FullName(&FileName))) - return S_OK; - - LPDISPATCH pDispSel; - - // Get a selection object dispatch pointer - if (SUCCEEDED(pDoc->get_Selection(&pDispSel))) - { - // Get the selection object - CComQIPtr < ITextSelection, &IID_ITextSelection > pSel(pDispSel); - - if (pSel) - // Get the selection line number - pSel->get_CurrentLine(&LineNr); - - pDispSel->Release(); - } - - // Open the file in Vim and position to the current line - if (VimOpenFile(FileName, LineNr)) - { - if (! g_bDevStudioEditor) - { - // Close the document in developer studio - CComVariant vSaveChanges = dsSaveChangesPrompt; - DsSaveStatus Saved; - - pDoc->Close(vSaveChanges, &Saved); - } - } - - // We're done here - SysFreeString(FileName); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch * theDocument) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch * theDocument) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch * theDocument) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (! g_bEnableVim) - // Vim not enabled or empty command line entered - return S_OK; - - // First get the current file name and line number - - CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(theDocument); - if (! pDoc) - return S_OK; - - BSTR FileName; - HRESULT hr; - - hr = pDoc->get_FullName(&FileName); - if (FAILED(hr)) - return S_OK; - - // Open the file in Vim and position to the current line - if (VimOpenFile(FileName, 0)) - { - if (! g_bDevStudioEditor) - { - // Close the document in developer studio - CComVariant vSaveChanges = dsSaveChangesPrompt; - DsSaveStatus Saved; - - pDoc->Close(vSaveChanges, &Saved); - } - } - - SysFreeString(FileName); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch * theWindow) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch * theWindow) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::WorkspaceOpen() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::WorkspaceClose() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -HRESULT CCommands::XApplicationEvents::NewWorkspace() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - -// Debugger event - -HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch * pBreakpoint) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - return S_OK; -} - - -///////////////////////////////////////////////////////////////////////////// -// VisVim dialog - -class CMainDialog : public CDialog -{ - public: - CMainDialog(CWnd * pParent = NULL); // Standard constructor - - //{{AFX_DATA(CMainDialog) - enum { IDD = IDD_ADDINMAIN }; - int m_ChangeDir; - BOOL m_bDevStudioEditor; - BOOL m_bNewTabs; - //}}AFX_DATA - - //{{AFX_VIRTUAL(CMainDialog) - protected: - virtual void DoDataExchange(CDataExchange * pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - protected: - //{{AFX_MSG(CMainDialog) - afx_msg void OnEnable(); - afx_msg void OnDisable(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -CMainDialog::CMainDialog(CWnd * pParent /* =NULL */ ) - : CDialog(CMainDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CMainDialog) - m_ChangeDir = -1; - m_bDevStudioEditor = FALSE; - m_bNewTabs = FALSE; - //}}AFX_DATA_INIT -} - -void CMainDialog::DoDataExchange(CDataExchange * pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CMainDialog) - DDX_Radio(pDX, IDC_CD_SOURCE_PATH, m_ChangeDir); - DDX_Check(pDX, IDC_DEVSTUDIO_EDITOR, m_bDevStudioEditor); - DDX_Check(pDX, IDC_NEW_TABS, m_bNewTabs); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CMainDialog, CDialog) - //{{AFX_MSG_MAP(CMainDialog) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - -///////////////////////////////////////////////////////////////////////////// -// CCommands methods - -STDMETHODIMP CCommands::VisVimDialog() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // Use m_pApplication to access the Developer Studio Application - // object, - // and VERIFY_OK to see error strings in DEBUG builds of your add-in - // (see stdafx.h) - - VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE)); - - CMainDialog Dlg; - - Dlg.m_bDevStudioEditor = g_bDevStudioEditor; - Dlg.m_bNewTabs = g_bNewTabs; - Dlg.m_ChangeDir = g_ChangeDir; - if (Dlg.DoModal() == IDOK) - { - g_bDevStudioEditor = Dlg.m_bDevStudioEditor; - g_bNewTabs = Dlg.m_bNewTabs; - g_ChangeDir = Dlg.m_ChangeDir; - - // Save settings to registry HKEY_CURRENT_USER\Software\Vim\VisVim - HKEY hAppKey = GetAppKey("Vim"); - if (hAppKey) - { - HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim"); - if (hSectionKey) - { - WriteRegistryInt(hSectionKey, "DevStudioEditor", - g_bDevStudioEditor); - WriteRegistryInt(hSectionKey, "NewTabs", - g_bNewTabs); - WriteRegistryInt(hSectionKey, "ChangeDir", g_ChangeDir); - RegCloseKey(hSectionKey); - } - RegCloseKey(hAppKey); - } - } - - VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE)); - return S_OK; -} - -STDMETHODIMP CCommands::VisVimEnable() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - VimSetEnableState(true); - return S_OK; -} - -STDMETHODIMP CCommands::VisVimDisable() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - VimSetEnableState(false); - return S_OK; -} - -STDMETHODIMP CCommands::VisVimToggle() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - VimSetEnableState(! g_bEnableVim); - return S_OK; -} - -STDMETHODIMP CCommands::VisVimLoad() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // Use m_pApplication to access the Developer Studio Application object, - // and VERIFY_OK to see error strings in DEBUG builds of your add-in - // (see stdafx.h) - - CComBSTR bStr; - // Define dispatch pointers for document and selection objects - CComPtr < IDispatch > pDispDoc, pDispSel; - - // Get a document object dispatch pointer - VERIFY_OK(m_pApplication->get_ActiveDocument(&pDispDoc)); - if (! pDispDoc) - return S_OK; - - BSTR FileName; - long LineNr = -1; - - // Get the document object - CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(pDispDoc); - - if (! pDoc) - return S_OK; - - // Get the document name - if (FAILED(pDoc->get_FullName(&FileName))) - return S_OK; - - // Get a selection object dispatch pointer - if (SUCCEEDED(pDoc->get_Selection(&pDispSel))) - { - // Get the selection object - CComQIPtr < ITextSelection, &IID_ITextSelection > pSel(pDispSel); - - if (pSel) - // Get the selection line number - pSel->get_CurrentLine(&LineNr); - } - - // Open the file in Vim - VimOpenFile(FileName, LineNr); - - SysFreeString(FileName); - return S_OK; -} - - -// -// Here we do the actual processing and communication with Vim -// - -// Set the enable state and save to registry -// -static void VimSetEnableState(BOOL bEnableState) -{ - g_bEnableVim = bEnableState; - HKEY hAppKey = GetAppKey("Vim"); - if (hAppKey) - { - HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim"); - if (hSectionKey) - WriteRegistryInt(hSectionKey, "EnableVim", g_bEnableVim); - RegCloseKey(hAppKey); - } -} - -// Open the file 'FileName' in Vim and goto line 'LineNr' -// 'FileName' is expected to contain an absolute DOS path including the drive -// letter. -// 'LineNr' must contain a valid line number or 0, e. g. for a new file -// -static BOOL VimOpenFile(BSTR& FileName, long LineNr) -{ - - // OLE automation object for com. with Vim - // When the object goes out of scope, its destructor destroys the OLE - // connection; - // This is important to avoid blocking the object - // (in this memory corruption would be likely when terminating Vim - // while still running DevStudio). - // So keep this object local! - COleAutomationControl VimOle; - - // :cd D:/Src2/VisVim/ - // - // Get a dispatch id for the SendKeys method of Vim; - // enables connection to Vim if necessary - DISPID DispatchId; - DispatchId = VimGetDispatchId(VimOle, "SendKeys"); - if (! DispatchId) - // OLE error, can't obtain dispatch id - goto OleError; - - OLECHAR Buf[MAX_OLE_STR]; - char FileNameTmp[MAX_OLE_STR]; - char VimCmd[MAX_OLE_STR]; - char *s, *p; - - // Prepend CTRL-\ CTRL-N to exit insert mode - VimCmd[0] = 0x1c; - VimCmd[1] = 0x0e; - VimCmd[2] = 0; - -#ifdef SINGLE_WINDOW - // Update the current file in Vim if it has been modified. - // Disabled, because it could write the file when you don't want to. - sprintf(VimCmd + 2, ":up\n"); -#endif - if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf))) - goto OleError; - - // Change Vim working directory to where the file is if desired - if (g_ChangeDir != CD_NONE) - VimChangeDir(VimOle, DispatchId, FileName); - - // Make Vim open the file. - // In the filename convert all \ to /, put a \ before a space. - if (g_bNewTabs) - { - sprintf(VimCmd, ":tab drop "); - s = VimCmd + 10; - } - else - { - sprintf(VimCmd, ":drop "); - s = VimCmd + 6; - } - sprintf(FileNameTmp, "%S", (char *)FileName); - for (p = FileNameTmp; *p != '\0' && s < VimCmd + MAX_OLE_STR - 4; ++p) - if (*p == '\\') - *s++ = '/'; - else - { - if (*p == ' ') - *s++ = '\\'; - *s++ = *p; - } - *s++ = '\n'; - *s = '\0'; - - if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf))) - goto OleError; - - if (LineNr > 0) - { - // Goto line - sprintf(VimCmd, ":%ld\n", LineNr); - if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf))) - goto OleError; - } - - // Make Vim come to the foreground - if (! VimOle.Method("SetForeground")) - VimOle.ErrDiag(); - - // We're done - return true; - - OleError: - // There was an OLE error - // Check if it's the "unknown class string" error - VimErrDiag(VimOle); - return false; -} - -// Return the dispatch id for the Vim method 'Method' -// Create the Vim OLE object if necessary -// Returns a valid dispatch id or null on error -// -static DISPID VimGetDispatchId(COleAutomationControl& VimOle, char* Method) -{ - // Initialize Vim OLE connection if not already done - if (! VimOle.IsCreated()) - { - if (! VimOle.CreateObject("Vim.Application")) - return NULL; - } - - // Get the dispatch id for the SendKeys method. - // By doing this, we are checking if Vim is still there... - DISPID DispatchId = VimOle.GetDispatchId("SendKeys"); - if (! DispatchId) - { - // We can't get a dispatch id. - // This means that probably Vim has been terminated. - // Don't issue an error message here, instead - // destroy the OLE object and try to connect once more - // - // In fact, this should never happen, because the OLE aut. object - // should not be kept long enough to allow the user to terminate Vim - // to avoid memory corruption (why the heck is there no system garbage - // collection for those damned OLE memory chunks???). - VimOle.DeleteObject(); - if (! VimOle.CreateObject("Vim.Application")) - // If this create fails, it's time for an error msg - return NULL; - - if (! (DispatchId = VimOle.GetDispatchId("SendKeys"))) - // There is something wrong... - return NULL; - } - - return DispatchId; -} - -// Output an error message for an OLE error -// Check on the classstring error, which probably means Vim wasn't registered. -// -static void VimErrDiag(COleAutomationControl& VimOle) -{ - SCODE sc = GetScode(VimOle.GetResult()); - if (sc == CO_E_CLASSSTRING) - { - char Buf[256]; - sprintf(Buf, "There is no registered OLE automation server named " - "\"Vim.Application\".\n" - "Use the OLE-enabled version of Vim with VisVim and " - "make sure to register Vim by running \"vim -register\"."); - MessageBox(NULL, Buf, "OLE Error", MB_OK); - } - else - VimOle.ErrDiag(); -} - -// Change directory to the directory the file 'FileName' is in or its parent -// directory according to the setting of the global 'g_ChangeDir': -// 'FileName' is expected to contain an absolute DOS path including the drive -// letter. -// CD_NONE -// CD_SOURCE_PATH -// CD_SOURCE_PARENT -// -static void VimChangeDir(COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName) -{ - // Do a :cd first - - // Get the path name of the file ("dir/") - CString StrFileName = FileName; - char Drive[_MAX_DRIVE]; - char Dir[_MAX_DIR]; - char DirUnix[_MAX_DIR * 2]; - char *s, *t; - - _splitpath(StrFileName, Drive, Dir, NULL, NULL); - - // Convert to Unix path name format, escape spaces. - t = DirUnix; - for (s = Dir; *s; ++s) - if (*s == '\\') - *t++ = '/'; - else - { - if (*s == ' ') - *t++ = '\\'; - *t++ = *s; - } - *t = '\0'; - - - // Construct the cd command; append /.. if cd to parent - // directory and not in root directory - OLECHAR Buf[MAX_OLE_STR]; - char VimCmd[MAX_OLE_STR]; - - sprintf(VimCmd, ":cd %s%s%s\n", Drive, DirUnix, - g_ChangeDir == CD_SOURCE_PARENT && DirUnix[1] ? ".." : ""); - VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf)); -} - -#ifdef _DEBUG -// Print out a debug message -// -static void DebugMsg(char* Msg, char* Arg) -{ - char Buf[400]; - sprintf(Buf, Msg, Arg); - AfxMessageBox(Buf); -} -#endif |