1071d4279SBram Moolenaar #include "stdafx.h"
2071d4279SBram Moolenaar #include <comdef.h> // For _bstr_t
3071d4279SBram Moolenaar #include "VisVim.h"
4071d4279SBram Moolenaar #include "Commands.h"
5071d4279SBram Moolenaar #include "OleAut.h"
6071d4279SBram Moolenaar
7071d4279SBram Moolenaar #ifdef _DEBUG
8071d4279SBram Moolenaar #define new DEBUG_NEW
9071d4279SBram Moolenaar #undef THIS_FILE
10071d4279SBram Moolenaar static char THIS_FILE[] = __FILE__;
11071d4279SBram Moolenaar
12071d4279SBram Moolenaar #endif
13071d4279SBram Moolenaar
14071d4279SBram Moolenaar
15071d4279SBram Moolenaar // Change directory before opening file?
16071d4279SBram Moolenaar #define CD_SOURCE 0 // Cd to source path
17071d4279SBram Moolenaar #define CD_SOURCE_PARENT 1 // Cd to parent directory of source path
18071d4279SBram Moolenaar #define CD_NONE 2 // No cd
19071d4279SBram Moolenaar
20071d4279SBram Moolenaar
21071d4279SBram Moolenaar static BOOL g_bEnableVim = TRUE; // Vim enabled
22071d4279SBram Moolenaar static BOOL g_bDevStudioEditor = FALSE; // Open file in Dev Studio editor simultaneously
2399133038SBram Moolenaar static BOOL g_bNewTabs = FALSE;
24071d4279SBram Moolenaar static int g_ChangeDir = CD_NONE; // CD after file open?
25071d4279SBram Moolenaar
26071d4279SBram Moolenaar static void VimSetEnableState(BOOL bEnableState);
27071d4279SBram Moolenaar static BOOL VimOpenFile(BSTR& FileName, long LineNr);
28071d4279SBram Moolenaar static DISPID VimGetDispatchId(COleAutomationControl& VimOle, char* Method);
29071d4279SBram Moolenaar static void VimErrDiag(COleAutomationControl& VimOle);
30071d4279SBram Moolenaar static void VimChangeDir(COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName);
31071d4279SBram Moolenaar static void DebugMsg(char* Msg, char* Arg = NULL);
32071d4279SBram Moolenaar
33071d4279SBram Moolenaar
34071d4279SBram Moolenaar /////////////////////////////////////////////////////////////////////////////
35071d4279SBram Moolenaar // CCommands
36071d4279SBram Moolenaar
CCommands()37071d4279SBram Moolenaar CCommands::CCommands()
38071d4279SBram Moolenaar {
39071d4279SBram Moolenaar // m_pApplication == NULL; M$ Code generation bug!!!
40071d4279SBram Moolenaar m_pApplication = NULL;
41071d4279SBram Moolenaar m_pApplicationEventsObj = NULL;
42071d4279SBram Moolenaar m_pDebuggerEventsObj = NULL;
43071d4279SBram Moolenaar }
44071d4279SBram Moolenaar
~CCommands()45071d4279SBram Moolenaar CCommands::~CCommands()
46071d4279SBram Moolenaar {
47071d4279SBram Moolenaar ASSERT(m_pApplication != NULL);
48071d4279SBram Moolenaar if (m_pApplication)
49071d4279SBram Moolenaar {
50071d4279SBram Moolenaar m_pApplication->Release();
51071d4279SBram Moolenaar m_pApplication = NULL;
52071d4279SBram Moolenaar }
53071d4279SBram Moolenaar }
54071d4279SBram Moolenaar
SetApplicationObject(IApplication * pApplication)55071d4279SBram Moolenaar void CCommands::SetApplicationObject(IApplication * pApplication)
56071d4279SBram Moolenaar {
57071d4279SBram Moolenaar // This function assumes pApplication has already been AddRef'd
58*b49e3563SBram Moolenaar // for us, which CDSAddIn did in its QueryInterface call
59071d4279SBram Moolenaar // just before it called us.
60071d4279SBram Moolenaar m_pApplication = pApplication;
61071d4279SBram Moolenaar if (! m_pApplication)
62071d4279SBram Moolenaar return;
63071d4279SBram Moolenaar
64071d4279SBram Moolenaar // Create Application event handlers
65071d4279SBram Moolenaar XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj);
66071d4279SBram Moolenaar if (! m_pApplicationEventsObj)
67071d4279SBram Moolenaar {
68071d4279SBram Moolenaar ReportInternalError("XApplicationEventsObj::CreateInstance");
69071d4279SBram Moolenaar return;
70071d4279SBram Moolenaar }
71071d4279SBram Moolenaar m_pApplicationEventsObj->AddRef();
72071d4279SBram Moolenaar m_pApplicationEventsObj->Connect(m_pApplication);
73071d4279SBram Moolenaar m_pApplicationEventsObj->m_pCommands = this;
74071d4279SBram Moolenaar
75071d4279SBram Moolenaar #ifdef NEVER
76071d4279SBram Moolenaar // Create Debugger event handler
77071d4279SBram Moolenaar CComPtr < IDispatch > pDebugger;
78071d4279SBram Moolenaar if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger))
79071d4279SBram Moolenaar && pDebugger != NULL)
80071d4279SBram Moolenaar {
81071d4279SBram Moolenaar XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj);
82071d4279SBram Moolenaar m_pDebuggerEventsObj->AddRef();
83071d4279SBram Moolenaar m_pDebuggerEventsObj->Connect(pDebugger);
84071d4279SBram Moolenaar m_pDebuggerEventsObj->m_pCommands = this;
85071d4279SBram Moolenaar }
86071d4279SBram Moolenaar #endif
87071d4279SBram Moolenaar
88071d4279SBram Moolenaar // Get settings from registry HKEY_CURRENT_USER\Software\Vim\VisVim
89071d4279SBram Moolenaar HKEY hAppKey = GetAppKey("Vim");
90071d4279SBram Moolenaar if (hAppKey)
91071d4279SBram Moolenaar {
92071d4279SBram Moolenaar HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim");
93071d4279SBram Moolenaar if (hSectionKey)
94071d4279SBram Moolenaar {
95071d4279SBram Moolenaar g_bEnableVim = GetRegistryInt(hSectionKey, "EnableVim",
96071d4279SBram Moolenaar g_bEnableVim);
9799133038SBram Moolenaar g_bDevStudioEditor = GetRegistryInt(hSectionKey,
9899133038SBram Moolenaar "DevStudioEditor", g_bDevStudioEditor);
9999133038SBram Moolenaar g_bNewTabs = GetRegistryInt(hSectionKey, "NewTabs",
10099133038SBram Moolenaar g_bNewTabs);
101071d4279SBram Moolenaar g_ChangeDir = GetRegistryInt(hSectionKey, "ChangeDir",
102071d4279SBram Moolenaar g_ChangeDir);
103071d4279SBram Moolenaar RegCloseKey(hSectionKey);
104071d4279SBram Moolenaar }
105071d4279SBram Moolenaar RegCloseKey(hAppKey);
106071d4279SBram Moolenaar }
107071d4279SBram Moolenaar }
108071d4279SBram Moolenaar
UnadviseFromEvents()109071d4279SBram Moolenaar void CCommands::UnadviseFromEvents()
110071d4279SBram Moolenaar {
111071d4279SBram Moolenaar ASSERT(m_pApplicationEventsObj != NULL);
112071d4279SBram Moolenaar if (m_pApplicationEventsObj)
113071d4279SBram Moolenaar {
114071d4279SBram Moolenaar m_pApplicationEventsObj->Disconnect(m_pApplication);
115071d4279SBram Moolenaar m_pApplicationEventsObj->Release();
116071d4279SBram Moolenaar m_pApplicationEventsObj = NULL;
117071d4279SBram Moolenaar }
118071d4279SBram Moolenaar
119071d4279SBram Moolenaar #ifdef NEVER
120071d4279SBram Moolenaar if (m_pDebuggerEventsObj)
121071d4279SBram Moolenaar {
122071d4279SBram Moolenaar // Since we were able to connect to the Debugger events, we
123071d4279SBram Moolenaar // should be able to access the Debugger object again to
124071d4279SBram Moolenaar // unadvise from its events (thus the VERIFY_OK below--see
125071d4279SBram Moolenaar // stdafx.h).
126071d4279SBram Moolenaar CComPtr < IDispatch > pDebugger;
127071d4279SBram Moolenaar VERIFY_OK(m_pApplication->get_Debugger(&pDebugger));
128071d4279SBram Moolenaar ASSERT(pDebugger != NULL);
129071d4279SBram Moolenaar m_pDebuggerEventsObj->Disconnect(pDebugger);
130071d4279SBram Moolenaar m_pDebuggerEventsObj->Release();
131071d4279SBram Moolenaar m_pDebuggerEventsObj = NULL;
132071d4279SBram Moolenaar }
133071d4279SBram Moolenaar #endif
134071d4279SBram Moolenaar }
135071d4279SBram Moolenaar
136071d4279SBram Moolenaar
137071d4279SBram Moolenaar /////////////////////////////////////////////////////////////////////////////
138071d4279SBram Moolenaar // Event handlers
139071d4279SBram Moolenaar
140071d4279SBram Moolenaar // Application events
141071d4279SBram Moolenaar
BeforeBuildStart()142071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::BeforeBuildStart()
143071d4279SBram Moolenaar {
144071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
145071d4279SBram Moolenaar return S_OK;
146071d4279SBram Moolenaar }
147071d4279SBram Moolenaar
BuildFinish(long nNumErrors,long nNumWarnings)148071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings)
149071d4279SBram Moolenaar {
150071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
151071d4279SBram Moolenaar return S_OK;
152071d4279SBram Moolenaar }
153071d4279SBram Moolenaar
BeforeApplicationShutDown()154071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown()
155071d4279SBram Moolenaar {
156071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
157071d4279SBram Moolenaar return S_OK;
158071d4279SBram Moolenaar }
159071d4279SBram Moolenaar
160071d4279SBram Moolenaar // The open document event handle is the place where the real interface work
161071d4279SBram Moolenaar // is done.
162071d4279SBram Moolenaar // Vim gets called from here.
163071d4279SBram Moolenaar //
DocumentOpen(IDispatch * theDocument)164071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::DocumentOpen(IDispatch * theDocument)
165071d4279SBram Moolenaar {
166071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
167071d4279SBram Moolenaar
168071d4279SBram Moolenaar if (! g_bEnableVim)
169071d4279SBram Moolenaar // Vim not enabled or empty command line entered
170071d4279SBram Moolenaar return S_OK;
171071d4279SBram Moolenaar
172071d4279SBram Moolenaar // First get the current file name and line number
173071d4279SBram Moolenaar
174071d4279SBram Moolenaar // Get the document object
175071d4279SBram Moolenaar CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(theDocument);
176071d4279SBram Moolenaar if (! pDoc)
177071d4279SBram Moolenaar return S_OK;
178071d4279SBram Moolenaar
179071d4279SBram Moolenaar BSTR FileName;
180071d4279SBram Moolenaar long LineNr = -1;
181071d4279SBram Moolenaar
182071d4279SBram Moolenaar // Get the document name
183071d4279SBram Moolenaar if (FAILED(pDoc->get_FullName(&FileName)))
184071d4279SBram Moolenaar return S_OK;
185071d4279SBram Moolenaar
186071d4279SBram Moolenaar LPDISPATCH pDispSel;
187071d4279SBram Moolenaar
188071d4279SBram Moolenaar // Get a selection object dispatch pointer
189071d4279SBram Moolenaar if (SUCCEEDED(pDoc->get_Selection(&pDispSel)))
190071d4279SBram Moolenaar {
191071d4279SBram Moolenaar // Get the selection object
192071d4279SBram Moolenaar CComQIPtr < ITextSelection, &IID_ITextSelection > pSel(pDispSel);
193071d4279SBram Moolenaar
194071d4279SBram Moolenaar if (pSel)
195071d4279SBram Moolenaar // Get the selection line number
196071d4279SBram Moolenaar pSel->get_CurrentLine(&LineNr);
197071d4279SBram Moolenaar
198071d4279SBram Moolenaar pDispSel->Release();
199071d4279SBram Moolenaar }
200071d4279SBram Moolenaar
201071d4279SBram Moolenaar // Open the file in Vim and position to the current line
202071d4279SBram Moolenaar if (VimOpenFile(FileName, LineNr))
203071d4279SBram Moolenaar {
204071d4279SBram Moolenaar if (! g_bDevStudioEditor)
205071d4279SBram Moolenaar {
206071d4279SBram Moolenaar // Close the document in developer studio
207071d4279SBram Moolenaar CComVariant vSaveChanges = dsSaveChangesPrompt;
208071d4279SBram Moolenaar DsSaveStatus Saved;
209071d4279SBram Moolenaar
210071d4279SBram Moolenaar pDoc->Close(vSaveChanges, &Saved);
211071d4279SBram Moolenaar }
212071d4279SBram Moolenaar }
213071d4279SBram Moolenaar
214071d4279SBram Moolenaar // We're done here
215071d4279SBram Moolenaar SysFreeString(FileName);
216071d4279SBram Moolenaar return S_OK;
217071d4279SBram Moolenaar }
218071d4279SBram Moolenaar
BeforeDocumentClose(IDispatch * theDocument)219071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch * theDocument)
220071d4279SBram Moolenaar {
221071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
222071d4279SBram Moolenaar return S_OK;
223071d4279SBram Moolenaar }
224071d4279SBram Moolenaar
DocumentSave(IDispatch * theDocument)225071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch * theDocument)
226071d4279SBram Moolenaar {
227071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
228071d4279SBram Moolenaar return S_OK;
229071d4279SBram Moolenaar }
230071d4279SBram Moolenaar
NewDocument(IDispatch * theDocument)231071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch * theDocument)
232071d4279SBram Moolenaar {
233071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
234071d4279SBram Moolenaar
235071d4279SBram Moolenaar if (! g_bEnableVim)
236071d4279SBram Moolenaar // Vim not enabled or empty command line entered
237071d4279SBram Moolenaar return S_OK;
238071d4279SBram Moolenaar
239071d4279SBram Moolenaar // First get the current file name and line number
240071d4279SBram Moolenaar
241071d4279SBram Moolenaar CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(theDocument);
242071d4279SBram Moolenaar if (! pDoc)
243071d4279SBram Moolenaar return S_OK;
244071d4279SBram Moolenaar
245071d4279SBram Moolenaar BSTR FileName;
246071d4279SBram Moolenaar HRESULT hr;
247071d4279SBram Moolenaar
248071d4279SBram Moolenaar hr = pDoc->get_FullName(&FileName);
249071d4279SBram Moolenaar if (FAILED(hr))
250071d4279SBram Moolenaar return S_OK;
251071d4279SBram Moolenaar
252071d4279SBram Moolenaar // Open the file in Vim and position to the current line
253071d4279SBram Moolenaar if (VimOpenFile(FileName, 0))
254071d4279SBram Moolenaar {
255071d4279SBram Moolenaar if (! g_bDevStudioEditor)
256071d4279SBram Moolenaar {
257071d4279SBram Moolenaar // Close the document in developer studio
258071d4279SBram Moolenaar CComVariant vSaveChanges = dsSaveChangesPrompt;
259071d4279SBram Moolenaar DsSaveStatus Saved;
260071d4279SBram Moolenaar
261071d4279SBram Moolenaar pDoc->Close(vSaveChanges, &Saved);
262071d4279SBram Moolenaar }
263071d4279SBram Moolenaar }
264071d4279SBram Moolenaar
265071d4279SBram Moolenaar SysFreeString(FileName);
266071d4279SBram Moolenaar return S_OK;
267071d4279SBram Moolenaar }
268071d4279SBram Moolenaar
WindowActivate(IDispatch * theWindow)269071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch * theWindow)
270071d4279SBram Moolenaar {
271071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
272071d4279SBram Moolenaar return S_OK;
273071d4279SBram Moolenaar }
274071d4279SBram Moolenaar
WindowDeactivate(IDispatch * theWindow)275071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch * theWindow)
276071d4279SBram Moolenaar {
277071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
278071d4279SBram Moolenaar return S_OK;
279071d4279SBram Moolenaar }
280071d4279SBram Moolenaar
WorkspaceOpen()281071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::WorkspaceOpen()
282071d4279SBram Moolenaar {
283071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
284071d4279SBram Moolenaar return S_OK;
285071d4279SBram Moolenaar }
286071d4279SBram Moolenaar
WorkspaceClose()287071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::WorkspaceClose()
288071d4279SBram Moolenaar {
289071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
290071d4279SBram Moolenaar return S_OK;
291071d4279SBram Moolenaar }
292071d4279SBram Moolenaar
NewWorkspace()293071d4279SBram Moolenaar HRESULT CCommands::XApplicationEvents::NewWorkspace()
294071d4279SBram Moolenaar {
295071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
296071d4279SBram Moolenaar return S_OK;
297071d4279SBram Moolenaar }
298071d4279SBram Moolenaar
299071d4279SBram Moolenaar // Debugger event
300071d4279SBram Moolenaar
BreakpointHit(IDispatch * pBreakpoint)301071d4279SBram Moolenaar HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch * pBreakpoint)
302071d4279SBram Moolenaar {
303071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
304071d4279SBram Moolenaar return S_OK;
305071d4279SBram Moolenaar }
306071d4279SBram Moolenaar
307071d4279SBram Moolenaar
308071d4279SBram Moolenaar /////////////////////////////////////////////////////////////////////////////
309071d4279SBram Moolenaar // VisVim dialog
310071d4279SBram Moolenaar
311071d4279SBram Moolenaar class CMainDialog : public CDialog
312071d4279SBram Moolenaar {
313071d4279SBram Moolenaar public:
314071d4279SBram Moolenaar CMainDialog(CWnd * pParent = NULL); // Standard constructor
315071d4279SBram Moolenaar
316071d4279SBram Moolenaar //{{AFX_DATA(CMainDialog)
317071d4279SBram Moolenaar enum { IDD = IDD_ADDINMAIN };
318071d4279SBram Moolenaar int m_ChangeDir;
319071d4279SBram Moolenaar BOOL m_bDevStudioEditor;
32099133038SBram Moolenaar BOOL m_bNewTabs;
321071d4279SBram Moolenaar //}}AFX_DATA
322071d4279SBram Moolenaar
323071d4279SBram Moolenaar //{{AFX_VIRTUAL(CMainDialog)
324071d4279SBram Moolenaar protected:
325071d4279SBram Moolenaar virtual void DoDataExchange(CDataExchange * pDX); // DDX/DDV support
326071d4279SBram Moolenaar //}}AFX_VIRTUAL
327071d4279SBram Moolenaar
328071d4279SBram Moolenaar protected:
329071d4279SBram Moolenaar //{{AFX_MSG(CMainDialog)
330071d4279SBram Moolenaar afx_msg void OnEnable();
331071d4279SBram Moolenaar afx_msg void OnDisable();
332071d4279SBram Moolenaar //}}AFX_MSG
333071d4279SBram Moolenaar DECLARE_MESSAGE_MAP()
334071d4279SBram Moolenaar };
335071d4279SBram Moolenaar
CMainDialog(CWnd * pParent)336071d4279SBram Moolenaar CMainDialog::CMainDialog(CWnd * pParent /* =NULL */ )
337071d4279SBram Moolenaar : CDialog(CMainDialog::IDD, pParent)
338071d4279SBram Moolenaar {
339071d4279SBram Moolenaar //{{AFX_DATA_INIT(CMainDialog)
340071d4279SBram Moolenaar m_ChangeDir = -1;
341071d4279SBram Moolenaar m_bDevStudioEditor = FALSE;
34299133038SBram Moolenaar m_bNewTabs = FALSE;
343071d4279SBram Moolenaar //}}AFX_DATA_INIT
344071d4279SBram Moolenaar }
345071d4279SBram Moolenaar
DoDataExchange(CDataExchange * pDX)346071d4279SBram Moolenaar void CMainDialog::DoDataExchange(CDataExchange * pDX)
347071d4279SBram Moolenaar {
348071d4279SBram Moolenaar CDialog::DoDataExchange(pDX);
349071d4279SBram Moolenaar //{{AFX_DATA_MAP(CMainDialog)
350071d4279SBram Moolenaar DDX_Radio(pDX, IDC_CD_SOURCE_PATH, m_ChangeDir);
351071d4279SBram Moolenaar DDX_Check(pDX, IDC_DEVSTUDIO_EDITOR, m_bDevStudioEditor);
35299133038SBram Moolenaar DDX_Check(pDX, IDC_NEW_TABS, m_bNewTabs);
353071d4279SBram Moolenaar //}}AFX_DATA_MAP
354071d4279SBram Moolenaar }
355071d4279SBram Moolenaar
BEGIN_MESSAGE_MAP(CMainDialog,CDialog)356071d4279SBram Moolenaar BEGIN_MESSAGE_MAP(CMainDialog, CDialog)
357071d4279SBram Moolenaar //{{AFX_MSG_MAP(CMainDialog)
358071d4279SBram Moolenaar //}}AFX_MSG_MAP
359071d4279SBram Moolenaar END_MESSAGE_MAP()
360071d4279SBram Moolenaar
361071d4279SBram Moolenaar
362071d4279SBram Moolenaar /////////////////////////////////////////////////////////////////////////////
363071d4279SBram Moolenaar // CCommands methods
364071d4279SBram Moolenaar
365071d4279SBram Moolenaar STDMETHODIMP CCommands::VisVimDialog()
366071d4279SBram Moolenaar {
367071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
368071d4279SBram Moolenaar
369071d4279SBram Moolenaar // Use m_pApplication to access the Developer Studio Application
370071d4279SBram Moolenaar // object,
371071d4279SBram Moolenaar // and VERIFY_OK to see error strings in DEBUG builds of your add-in
372071d4279SBram Moolenaar // (see stdafx.h)
373071d4279SBram Moolenaar
374071d4279SBram Moolenaar VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
375071d4279SBram Moolenaar
376071d4279SBram Moolenaar CMainDialog Dlg;
377071d4279SBram Moolenaar
378071d4279SBram Moolenaar Dlg.m_bDevStudioEditor = g_bDevStudioEditor;
37999133038SBram Moolenaar Dlg.m_bNewTabs = g_bNewTabs;
380071d4279SBram Moolenaar Dlg.m_ChangeDir = g_ChangeDir;
381071d4279SBram Moolenaar if (Dlg.DoModal() == IDOK)
382071d4279SBram Moolenaar {
383071d4279SBram Moolenaar g_bDevStudioEditor = Dlg.m_bDevStudioEditor;
38499133038SBram Moolenaar g_bNewTabs = Dlg.m_bNewTabs;
385071d4279SBram Moolenaar g_ChangeDir = Dlg.m_ChangeDir;
386071d4279SBram Moolenaar
387071d4279SBram Moolenaar // Save settings to registry HKEY_CURRENT_USER\Software\Vim\VisVim
388071d4279SBram Moolenaar HKEY hAppKey = GetAppKey("Vim");
389071d4279SBram Moolenaar if (hAppKey)
390071d4279SBram Moolenaar {
391071d4279SBram Moolenaar HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim");
392071d4279SBram Moolenaar if (hSectionKey)
393071d4279SBram Moolenaar {
394071d4279SBram Moolenaar WriteRegistryInt(hSectionKey, "DevStudioEditor",
395071d4279SBram Moolenaar g_bDevStudioEditor);
39699133038SBram Moolenaar WriteRegistryInt(hSectionKey, "NewTabs",
39799133038SBram Moolenaar g_bNewTabs);
398071d4279SBram Moolenaar WriteRegistryInt(hSectionKey, "ChangeDir", g_ChangeDir);
399071d4279SBram Moolenaar RegCloseKey(hSectionKey);
400071d4279SBram Moolenaar }
401071d4279SBram Moolenaar RegCloseKey(hAppKey);
402071d4279SBram Moolenaar }
403071d4279SBram Moolenaar }
404071d4279SBram Moolenaar
405071d4279SBram Moolenaar VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
406071d4279SBram Moolenaar return S_OK;
407071d4279SBram Moolenaar }
408071d4279SBram Moolenaar
VisVimEnable()409071d4279SBram Moolenaar STDMETHODIMP CCommands::VisVimEnable()
410071d4279SBram Moolenaar {
411071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
412071d4279SBram Moolenaar VimSetEnableState(true);
413071d4279SBram Moolenaar return S_OK;
414071d4279SBram Moolenaar }
415071d4279SBram Moolenaar
VisVimDisable()416071d4279SBram Moolenaar STDMETHODIMP CCommands::VisVimDisable()
417071d4279SBram Moolenaar {
418071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
419071d4279SBram Moolenaar VimSetEnableState(false);
420071d4279SBram Moolenaar return S_OK;
421071d4279SBram Moolenaar }
422071d4279SBram Moolenaar
VisVimToggle()423071d4279SBram Moolenaar STDMETHODIMP CCommands::VisVimToggle()
424071d4279SBram Moolenaar {
425071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
426071d4279SBram Moolenaar VimSetEnableState(! g_bEnableVim);
427071d4279SBram Moolenaar return S_OK;
428071d4279SBram Moolenaar }
429071d4279SBram Moolenaar
VisVimLoad()430071d4279SBram Moolenaar STDMETHODIMP CCommands::VisVimLoad()
431071d4279SBram Moolenaar {
432071d4279SBram Moolenaar AFX_MANAGE_STATE(AfxGetStaticModuleState());
433071d4279SBram Moolenaar
434071d4279SBram Moolenaar // Use m_pApplication to access the Developer Studio Application object,
435071d4279SBram Moolenaar // and VERIFY_OK to see error strings in DEBUG builds of your add-in
436071d4279SBram Moolenaar // (see stdafx.h)
437071d4279SBram Moolenaar
438071d4279SBram Moolenaar CComBSTR bStr;
439071d4279SBram Moolenaar // Define dispatch pointers for document and selection objects
440071d4279SBram Moolenaar CComPtr < IDispatch > pDispDoc, pDispSel;
441071d4279SBram Moolenaar
442071d4279SBram Moolenaar // Get a document object dispatch pointer
443071d4279SBram Moolenaar VERIFY_OK(m_pApplication->get_ActiveDocument(&pDispDoc));
444071d4279SBram Moolenaar if (! pDispDoc)
445071d4279SBram Moolenaar return S_OK;
446071d4279SBram Moolenaar
447071d4279SBram Moolenaar BSTR FileName;
448071d4279SBram Moolenaar long LineNr = -1;
449071d4279SBram Moolenaar
450071d4279SBram Moolenaar // Get the document object
451071d4279SBram Moolenaar CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(pDispDoc);
452071d4279SBram Moolenaar
453071d4279SBram Moolenaar if (! pDoc)
454071d4279SBram Moolenaar return S_OK;
455071d4279SBram Moolenaar
456071d4279SBram Moolenaar // Get the document name
457071d4279SBram Moolenaar if (FAILED(pDoc->get_FullName(&FileName)))
458071d4279SBram Moolenaar return S_OK;
459071d4279SBram Moolenaar
460071d4279SBram Moolenaar // Get a selection object dispatch pointer
461071d4279SBram Moolenaar if (SUCCEEDED(pDoc->get_Selection(&pDispSel)))
462071d4279SBram Moolenaar {
463071d4279SBram Moolenaar // Get the selection object
464071d4279SBram Moolenaar CComQIPtr < ITextSelection, &IID_ITextSelection > pSel(pDispSel);
465071d4279SBram Moolenaar
466071d4279SBram Moolenaar if (pSel)
467071d4279SBram Moolenaar // Get the selection line number
468071d4279SBram Moolenaar pSel->get_CurrentLine(&LineNr);
469071d4279SBram Moolenaar }
470071d4279SBram Moolenaar
471071d4279SBram Moolenaar // Open the file in Vim
472071d4279SBram Moolenaar VimOpenFile(FileName, LineNr);
473071d4279SBram Moolenaar
474071d4279SBram Moolenaar SysFreeString(FileName);
475071d4279SBram Moolenaar return S_OK;
476071d4279SBram Moolenaar }
477071d4279SBram Moolenaar
478071d4279SBram Moolenaar
479071d4279SBram Moolenaar //
480071d4279SBram Moolenaar // Here we do the actual processing and communication with Vim
481071d4279SBram Moolenaar //
482071d4279SBram Moolenaar
483071d4279SBram Moolenaar // Set the enable state and save to registry
484071d4279SBram Moolenaar //
VimSetEnableState(BOOL bEnableState)485071d4279SBram Moolenaar static void VimSetEnableState(BOOL bEnableState)
486071d4279SBram Moolenaar {
487071d4279SBram Moolenaar g_bEnableVim = bEnableState;
488071d4279SBram Moolenaar HKEY hAppKey = GetAppKey("Vim");
489071d4279SBram Moolenaar if (hAppKey)
490071d4279SBram Moolenaar {
491071d4279SBram Moolenaar HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim");
492071d4279SBram Moolenaar if (hSectionKey)
493071d4279SBram Moolenaar WriteRegistryInt(hSectionKey, "EnableVim", g_bEnableVim);
494071d4279SBram Moolenaar RegCloseKey(hAppKey);
495071d4279SBram Moolenaar }
496071d4279SBram Moolenaar }
497071d4279SBram Moolenaar
498071d4279SBram Moolenaar // Open the file 'FileName' in Vim and goto line 'LineNr'
499071d4279SBram Moolenaar // 'FileName' is expected to contain an absolute DOS path including the drive
500071d4279SBram Moolenaar // letter.
501071d4279SBram Moolenaar // 'LineNr' must contain a valid line number or 0, e. g. for a new file
502071d4279SBram Moolenaar //
VimOpenFile(BSTR & FileName,long LineNr)503071d4279SBram Moolenaar static BOOL VimOpenFile(BSTR& FileName, long LineNr)
504071d4279SBram Moolenaar {
505071d4279SBram Moolenaar
506071d4279SBram Moolenaar // OLE automation object for com. with Vim
507*b49e3563SBram Moolenaar // When the object goes out of scope, its destructor destroys the OLE
508e590119eSBram Moolenaar // connection;
509e590119eSBram Moolenaar // This is important to avoid blocking the object
510071d4279SBram Moolenaar // (in this memory corruption would be likely when terminating Vim
511071d4279SBram Moolenaar // while still running DevStudio).
512071d4279SBram Moolenaar // So keep this object local!
513071d4279SBram Moolenaar COleAutomationControl VimOle;
514071d4279SBram Moolenaar
515071d4279SBram Moolenaar // :cd D:/Src2/VisVim/
516071d4279SBram Moolenaar //
517071d4279SBram Moolenaar // Get a dispatch id for the SendKeys method of Vim;
518071d4279SBram Moolenaar // enables connection to Vim if necessary
519071d4279SBram Moolenaar DISPID DispatchId;
520071d4279SBram Moolenaar DispatchId = VimGetDispatchId(VimOle, "SendKeys");
521071d4279SBram Moolenaar if (! DispatchId)
522071d4279SBram Moolenaar // OLE error, can't obtain dispatch id
523071d4279SBram Moolenaar goto OleError;
524071d4279SBram Moolenaar
525071d4279SBram Moolenaar OLECHAR Buf[MAX_OLE_STR];
526071d4279SBram Moolenaar char FileNameTmp[MAX_OLE_STR];
527071d4279SBram Moolenaar char VimCmd[MAX_OLE_STR];
528071d4279SBram Moolenaar char *s, *p;
529071d4279SBram Moolenaar
530071d4279SBram Moolenaar // Prepend CTRL-\ CTRL-N to exit insert mode
531071d4279SBram Moolenaar VimCmd[0] = 0x1c;
532071d4279SBram Moolenaar VimCmd[1] = 0x0e;
533071d4279SBram Moolenaar VimCmd[2] = 0;
534071d4279SBram Moolenaar
535071d4279SBram Moolenaar #ifdef SINGLE_WINDOW
536071d4279SBram Moolenaar // Update the current file in Vim if it has been modified.
537071d4279SBram Moolenaar // Disabled, because it could write the file when you don't want to.
538071d4279SBram Moolenaar sprintf(VimCmd + 2, ":up\n");
539071d4279SBram Moolenaar #endif
540071d4279SBram Moolenaar if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf)))
541071d4279SBram Moolenaar goto OleError;
542071d4279SBram Moolenaar
543071d4279SBram Moolenaar // Change Vim working directory to where the file is if desired
544071d4279SBram Moolenaar if (g_ChangeDir != CD_NONE)
545071d4279SBram Moolenaar VimChangeDir(VimOle, DispatchId, FileName);
546071d4279SBram Moolenaar
547071d4279SBram Moolenaar // Make Vim open the file.
548071d4279SBram Moolenaar // In the filename convert all \ to /, put a \ before a space.
54999133038SBram Moolenaar if (g_bNewTabs)
55099133038SBram Moolenaar {
55199133038SBram Moolenaar sprintf(VimCmd, ":tab drop ");
55217fb0e89SBram Moolenaar s = VimCmd + 10;
55399133038SBram Moolenaar }
55499133038SBram Moolenaar else
55599133038SBram Moolenaar {
556071d4279SBram Moolenaar sprintf(VimCmd, ":drop ");
557071d4279SBram Moolenaar s = VimCmd + 6;
55899133038SBram Moolenaar }
55999133038SBram Moolenaar sprintf(FileNameTmp, "%S", (char *)FileName);
56017fb0e89SBram Moolenaar for (p = FileNameTmp; *p != '\0' && s < VimCmd + MAX_OLE_STR - 4; ++p)
561071d4279SBram Moolenaar if (*p == '\\')
562071d4279SBram Moolenaar *s++ = '/';
563071d4279SBram Moolenaar else
564071d4279SBram Moolenaar {
565071d4279SBram Moolenaar if (*p == ' ')
566071d4279SBram Moolenaar *s++ = '\\';
567071d4279SBram Moolenaar *s++ = *p;
568071d4279SBram Moolenaar }
569071d4279SBram Moolenaar *s++ = '\n';
570071d4279SBram Moolenaar *s = '\0';
571071d4279SBram Moolenaar
572071d4279SBram Moolenaar if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf)))
573071d4279SBram Moolenaar goto OleError;
574071d4279SBram Moolenaar
575071d4279SBram Moolenaar if (LineNr > 0)
576071d4279SBram Moolenaar {
577071d4279SBram Moolenaar // Goto line
578ea034590SBram Moolenaar sprintf(VimCmd, ":%ld\n", LineNr);
579071d4279SBram Moolenaar if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf)))
580071d4279SBram Moolenaar goto OleError;
581071d4279SBram Moolenaar }
582071d4279SBram Moolenaar
583071d4279SBram Moolenaar // Make Vim come to the foreground
584071d4279SBram Moolenaar if (! VimOle.Method("SetForeground"))
585071d4279SBram Moolenaar VimOle.ErrDiag();
586071d4279SBram Moolenaar
587071d4279SBram Moolenaar // We're done
588071d4279SBram Moolenaar return true;
589071d4279SBram Moolenaar
590071d4279SBram Moolenaar OleError:
591071d4279SBram Moolenaar // There was an OLE error
592071d4279SBram Moolenaar // Check if it's the "unknown class string" error
593071d4279SBram Moolenaar VimErrDiag(VimOle);
594071d4279SBram Moolenaar return false;
595071d4279SBram Moolenaar }
596071d4279SBram Moolenaar
597071d4279SBram Moolenaar // Return the dispatch id for the Vim method 'Method'
598071d4279SBram Moolenaar // Create the Vim OLE object if necessary
599071d4279SBram Moolenaar // Returns a valid dispatch id or null on error
600071d4279SBram Moolenaar //
VimGetDispatchId(COleAutomationControl & VimOle,char * Method)601071d4279SBram Moolenaar static DISPID VimGetDispatchId(COleAutomationControl& VimOle, char* Method)
602071d4279SBram Moolenaar {
603071d4279SBram Moolenaar // Initialize Vim OLE connection if not already done
604071d4279SBram Moolenaar if (! VimOle.IsCreated())
605071d4279SBram Moolenaar {
606071d4279SBram Moolenaar if (! VimOle.CreateObject("Vim.Application"))
607071d4279SBram Moolenaar return NULL;
608071d4279SBram Moolenaar }
609071d4279SBram Moolenaar
610071d4279SBram Moolenaar // Get the dispatch id for the SendKeys method.
611071d4279SBram Moolenaar // By doing this, we are checking if Vim is still there...
612071d4279SBram Moolenaar DISPID DispatchId = VimOle.GetDispatchId("SendKeys");
613071d4279SBram Moolenaar if (! DispatchId)
614071d4279SBram Moolenaar {
615071d4279SBram Moolenaar // We can't get a dispatch id.
616071d4279SBram Moolenaar // This means that probably Vim has been terminated.
617071d4279SBram Moolenaar // Don't issue an error message here, instead
618071d4279SBram Moolenaar // destroy the OLE object and try to connect once more
619071d4279SBram Moolenaar //
620071d4279SBram Moolenaar // In fact, this should never happen, because the OLE aut. object
621071d4279SBram Moolenaar // should not be kept long enough to allow the user to terminate Vim
622071d4279SBram Moolenaar // to avoid memory corruption (why the heck is there no system garbage
623071d4279SBram Moolenaar // collection for those damned OLE memory chunks???).
624071d4279SBram Moolenaar VimOle.DeleteObject();
625071d4279SBram Moolenaar if (! VimOle.CreateObject("Vim.Application"))
626071d4279SBram Moolenaar // If this create fails, it's time for an error msg
627071d4279SBram Moolenaar return NULL;
628071d4279SBram Moolenaar
629071d4279SBram Moolenaar if (! (DispatchId = VimOle.GetDispatchId("SendKeys")))
630071d4279SBram Moolenaar // There is something wrong...
631071d4279SBram Moolenaar return NULL;
632071d4279SBram Moolenaar }
633071d4279SBram Moolenaar
634071d4279SBram Moolenaar return DispatchId;
635071d4279SBram Moolenaar }
636071d4279SBram Moolenaar
637071d4279SBram Moolenaar // Output an error message for an OLE error
638071d4279SBram Moolenaar // Check on the classstring error, which probably means Vim wasn't registered.
639071d4279SBram Moolenaar //
VimErrDiag(COleAutomationControl & VimOle)640071d4279SBram Moolenaar static void VimErrDiag(COleAutomationControl& VimOle)
641071d4279SBram Moolenaar {
642071d4279SBram Moolenaar SCODE sc = GetScode(VimOle.GetResult());
643071d4279SBram Moolenaar if (sc == CO_E_CLASSSTRING)
644071d4279SBram Moolenaar {
645071d4279SBram Moolenaar char Buf[256];
646071d4279SBram Moolenaar sprintf(Buf, "There is no registered OLE automation server named "
647071d4279SBram Moolenaar "\"Vim.Application\".\n"
648071d4279SBram Moolenaar "Use the OLE-enabled version of Vim with VisVim and "
649071d4279SBram Moolenaar "make sure to register Vim by running \"vim -register\".");
650071d4279SBram Moolenaar MessageBox(NULL, Buf, "OLE Error", MB_OK);
651071d4279SBram Moolenaar }
652071d4279SBram Moolenaar else
653071d4279SBram Moolenaar VimOle.ErrDiag();
654071d4279SBram Moolenaar }
655071d4279SBram Moolenaar
656*b49e3563SBram Moolenaar // Change directory to the directory the file 'FileName' is in or its parent
657071d4279SBram Moolenaar // directory according to the setting of the global 'g_ChangeDir':
658071d4279SBram Moolenaar // 'FileName' is expected to contain an absolute DOS path including the drive
659071d4279SBram Moolenaar // letter.
660071d4279SBram Moolenaar // CD_NONE
661071d4279SBram Moolenaar // CD_SOURCE_PATH
662071d4279SBram Moolenaar // CD_SOURCE_PARENT
663071d4279SBram Moolenaar //
VimChangeDir(COleAutomationControl & VimOle,DISPID DispatchId,BSTR & FileName)664071d4279SBram Moolenaar static void VimChangeDir(COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName)
665071d4279SBram Moolenaar {
666071d4279SBram Moolenaar // Do a :cd first
667071d4279SBram Moolenaar
668071d4279SBram Moolenaar // Get the path name of the file ("dir/")
669071d4279SBram Moolenaar CString StrFileName = FileName;
670071d4279SBram Moolenaar char Drive[_MAX_DRIVE];
671071d4279SBram Moolenaar char Dir[_MAX_DIR];
672071d4279SBram Moolenaar char DirUnix[_MAX_DIR * 2];
673071d4279SBram Moolenaar char *s, *t;
674071d4279SBram Moolenaar
675071d4279SBram Moolenaar _splitpath(StrFileName, Drive, Dir, NULL, NULL);
676071d4279SBram Moolenaar
677071d4279SBram Moolenaar // Convert to Unix path name format, escape spaces.
678071d4279SBram Moolenaar t = DirUnix;
679071d4279SBram Moolenaar for (s = Dir; *s; ++s)
680071d4279SBram Moolenaar if (*s == '\\')
681071d4279SBram Moolenaar *t++ = '/';
682071d4279SBram Moolenaar else
683071d4279SBram Moolenaar {
684071d4279SBram Moolenaar if (*s == ' ')
685071d4279SBram Moolenaar *t++ = '\\';
686071d4279SBram Moolenaar *t++ = *s;
687071d4279SBram Moolenaar }
688071d4279SBram Moolenaar *t = '\0';
689071d4279SBram Moolenaar
690071d4279SBram Moolenaar
691071d4279SBram Moolenaar // Construct the cd command; append /.. if cd to parent
692071d4279SBram Moolenaar // directory and not in root directory
693071d4279SBram Moolenaar OLECHAR Buf[MAX_OLE_STR];
694071d4279SBram Moolenaar char VimCmd[MAX_OLE_STR];
695071d4279SBram Moolenaar
696071d4279SBram Moolenaar sprintf(VimCmd, ":cd %s%s%s\n", Drive, DirUnix,
697071d4279SBram Moolenaar g_ChangeDir == CD_SOURCE_PARENT && DirUnix[1] ? ".." : "");
698071d4279SBram Moolenaar VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf));
699071d4279SBram Moolenaar }
700071d4279SBram Moolenaar
701071d4279SBram Moolenaar #ifdef _DEBUG
702071d4279SBram Moolenaar // Print out a debug message
703071d4279SBram Moolenaar //
DebugMsg(char * Msg,char * Arg)704071d4279SBram Moolenaar static void DebugMsg(char* Msg, char* Arg)
705071d4279SBram Moolenaar {
706071d4279SBram Moolenaar char Buf[400];
707071d4279SBram Moolenaar sprintf(Buf, Msg, Arg);
708071d4279SBram Moolenaar AfxMessageBox(Buf);
709071d4279SBram Moolenaar }
710071d4279SBram Moolenaar #endif
711