xref: /vim-8.2.3635/src/VisVim/Commands.cpp (revision b49e3563)
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