7
|
1 #include "stdafx.h"
|
|
2 #include <comdef.h> // For _bstr_t
|
|
3 #include "VisVim.h"
|
|
4 #include "Commands.h"
|
|
5 #include "OleAut.h"
|
|
6
|
|
7 #ifdef _DEBUG
|
|
8 #define new DEBUG_NEW
|
|
9 #undef THIS_FILE
|
|
10 static char THIS_FILE[] = __FILE__;
|
|
11
|
|
12 #endif
|
|
13
|
|
14
|
|
15 // Change directory before opening file?
|
|
16 #define CD_SOURCE 0 // Cd to source path
|
|
17 #define CD_SOURCE_PARENT 1 // Cd to parent directory of source path
|
|
18 #define CD_NONE 2 // No cd
|
|
19
|
|
20
|
|
21 static BOOL g_bEnableVim = TRUE; // Vim enabled
|
|
22 static BOOL g_bDevStudioEditor = FALSE; // Open file in Dev Studio editor simultaneously
|
1852
|
23 static BOOL g_bNewTabs = FALSE;
|
7
|
24 static int g_ChangeDir = CD_NONE; // CD after file open?
|
|
25
|
1852
|
26 static void VimSetEnableState(BOOL bEnableState);
|
|
27 static BOOL VimOpenFile(BSTR& FileName, long LineNr);
|
|
28 static DISPID VimGetDispatchId(COleAutomationControl& VimOle, char* Method);
|
|
29 static void VimErrDiag(COleAutomationControl& VimOle);
|
|
30 static void VimChangeDir(COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName);
|
|
31 static void DebugMsg(char* Msg, char* Arg = NULL);
|
7
|
32
|
|
33
|
|
34 /////////////////////////////////////////////////////////////////////////////
|
|
35 // CCommands
|
|
36
|
1852
|
37 CCommands::CCommands()
|
7
|
38 {
|
|
39 // m_pApplication == NULL; M$ Code generation bug!!!
|
|
40 m_pApplication = NULL;
|
|
41 m_pApplicationEventsObj = NULL;
|
|
42 m_pDebuggerEventsObj = NULL;
|
|
43 }
|
|
44
|
1852
|
45 CCommands::~CCommands()
|
7
|
46 {
|
1852
|
47 ASSERT(m_pApplication != NULL);
|
7
|
48 if (m_pApplication)
|
|
49 {
|
1852
|
50 m_pApplication->Release();
|
7
|
51 m_pApplication = NULL;
|
|
52 }
|
|
53 }
|
|
54
|
1852
|
55 void CCommands::SetApplicationObject(IApplication * pApplication)
|
7
|
56 {
|
|
57 // This function assumes pApplication has already been AddRef'd
|
1220
|
58 // for us, which CDSAddIn did in it's QueryInterface call
|
7
|
59 // just before it called us.
|
|
60 m_pApplication = pApplication;
|
|
61 if (! m_pApplication)
|
|
62 return;
|
|
63
|
|
64 // Create Application event handlers
|
1852
|
65 XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj);
|
7
|
66 if (! m_pApplicationEventsObj)
|
|
67 {
|
1852
|
68 ReportInternalError("XApplicationEventsObj::CreateInstance");
|
7
|
69 return;
|
|
70 }
|
1852
|
71 m_pApplicationEventsObj->AddRef();
|
|
72 m_pApplicationEventsObj->Connect(m_pApplication);
|
7
|
73 m_pApplicationEventsObj->m_pCommands = this;
|
|
74
|
|
75 #ifdef NEVER
|
|
76 // Create Debugger event handler
|
|
77 CComPtr < IDispatch > pDebugger;
|
1852
|
78 if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger))
|
7
|
79 && pDebugger != NULL)
|
|
80 {
|
1852
|
81 XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj);
|
|
82 m_pDebuggerEventsObj->AddRef();
|
|
83 m_pDebuggerEventsObj->Connect(pDebugger);
|
7
|
84 m_pDebuggerEventsObj->m_pCommands = this;
|
|
85 }
|
|
86 #endif
|
|
87
|
|
88 // Get settings from registry HKEY_CURRENT_USER\Software\Vim\VisVim
|
1852
|
89 HKEY hAppKey = GetAppKey("Vim");
|
7
|
90 if (hAppKey)
|
|
91 {
|
1852
|
92 HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim");
|
7
|
93 if (hSectionKey)
|
|
94 {
|
1852
|
95 g_bEnableVim = GetRegistryInt(hSectionKey, "EnableVim",
|
7
|
96 g_bEnableVim);
|
1852
|
97 g_bDevStudioEditor = GetRegistryInt(hSectionKey,
|
|
98 "DevStudioEditor", g_bDevStudioEditor);
|
|
99 g_bNewTabs = GetRegistryInt(hSectionKey, "NewTabs",
|
|
100 g_bNewTabs);
|
|
101 g_ChangeDir = GetRegistryInt(hSectionKey, "ChangeDir",
|
7
|
102 g_ChangeDir);
|
1852
|
103 RegCloseKey(hSectionKey);
|
7
|
104 }
|
1852
|
105 RegCloseKey(hAppKey);
|
7
|
106 }
|
|
107 }
|
|
108
|
1852
|
109 void CCommands::UnadviseFromEvents()
|
7
|
110 {
|
1852
|
111 ASSERT(m_pApplicationEventsObj != NULL);
|
7
|
112 if (m_pApplicationEventsObj)
|
|
113 {
|
1852
|
114 m_pApplicationEventsObj->Disconnect(m_pApplication);
|
|
115 m_pApplicationEventsObj->Release();
|
7
|
116 m_pApplicationEventsObj = NULL;
|
|
117 }
|
|
118
|
|
119 #ifdef NEVER
|
|
120 if (m_pDebuggerEventsObj)
|
|
121 {
|
|
122 // Since we were able to connect to the Debugger events, we
|
|
123 // should be able to access the Debugger object again to
|
|
124 // unadvise from its events (thus the VERIFY_OK below--see
|
|
125 // stdafx.h).
|
|
126 CComPtr < IDispatch > pDebugger;
|
1852
|
127 VERIFY_OK(m_pApplication->get_Debugger(&pDebugger));
|
|
128 ASSERT(pDebugger != NULL);
|
|
129 m_pDebuggerEventsObj->Disconnect(pDebugger);
|
|
130 m_pDebuggerEventsObj->Release();
|
7
|
131 m_pDebuggerEventsObj = NULL;
|
|
132 }
|
|
133 #endif
|
|
134 }
|
|
135
|
|
136
|
|
137 /////////////////////////////////////////////////////////////////////////////
|
|
138 // Event handlers
|
|
139
|
|
140 // Application events
|
|
141
|
1852
|
142 HRESULT CCommands::XApplicationEvents::BeforeBuildStart()
|
7
|
143 {
|
1852
|
144 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
145 return S_OK;
|
|
146 }
|
|
147
|
1852
|
148 HRESULT CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings)
|
7
|
149 {
|
1852
|
150 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
151 return S_OK;
|
|
152 }
|
|
153
|
1852
|
154 HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown()
|
7
|
155 {
|
1852
|
156 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
157 return S_OK;
|
|
158 }
|
|
159
|
|
160 // The open document event handle is the place where the real interface work
|
|
161 // is done.
|
|
162 // Vim gets called from here.
|
|
163 //
|
1852
|
164 HRESULT CCommands::XApplicationEvents::DocumentOpen(IDispatch * theDocument)
|
7
|
165 {
|
1852
|
166 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
167
|
|
168 if (! g_bEnableVim)
|
|
169 // Vim not enabled or empty command line entered
|
|
170 return S_OK;
|
|
171
|
|
172 // First get the current file name and line number
|
|
173
|
|
174 // Get the document object
|
1852
|
175 CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(theDocument);
|
7
|
176 if (! pDoc)
|
|
177 return S_OK;
|
|
178
|
|
179 BSTR FileName;
|
|
180 long LineNr = -1;
|
|
181
|
|
182 // Get the document name
|
1852
|
183 if (FAILED(pDoc->get_FullName(&FileName)))
|
7
|
184 return S_OK;
|
|
185
|
|
186 LPDISPATCH pDispSel;
|
|
187
|
|
188 // Get a selection object dispatch pointer
|
1852
|
189 if (SUCCEEDED(pDoc->get_Selection(&pDispSel)))
|
7
|
190 {
|
|
191 // Get the selection object
|
1852
|
192 CComQIPtr < ITextSelection, &IID_ITextSelection > pSel(pDispSel);
|
7
|
193
|
|
194 if (pSel)
|
|
195 // Get the selection line number
|
1852
|
196 pSel->get_CurrentLine(&LineNr);
|
7
|
197
|
1852
|
198 pDispSel->Release();
|
7
|
199 }
|
|
200
|
|
201 // Open the file in Vim and position to the current line
|
1852
|
202 if (VimOpenFile(FileName, LineNr))
|
7
|
203 {
|
|
204 if (! g_bDevStudioEditor)
|
|
205 {
|
|
206 // Close the document in developer studio
|
|
207 CComVariant vSaveChanges = dsSaveChangesPrompt;
|
|
208 DsSaveStatus Saved;
|
|
209
|
1852
|
210 pDoc->Close(vSaveChanges, &Saved);
|
7
|
211 }
|
|
212 }
|
|
213
|
|
214 // We're done here
|
1852
|
215 SysFreeString(FileName);
|
7
|
216 return S_OK;
|
|
217 }
|
|
218
|
1852
|
219 HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch * theDocument)
|
7
|
220 {
|
1852
|
221 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
222 return S_OK;
|
|
223 }
|
|
224
|
1852
|
225 HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch * theDocument)
|
7
|
226 {
|
1852
|
227 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
228 return S_OK;
|
|
229 }
|
|
230
|
1852
|
231 HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch * theDocument)
|
7
|
232 {
|
1852
|
233 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
234
|
|
235 if (! g_bEnableVim)
|
|
236 // Vim not enabled or empty command line entered
|
|
237 return S_OK;
|
|
238
|
|
239 // First get the current file name and line number
|
|
240
|
1852
|
241 CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(theDocument);
|
7
|
242 if (! pDoc)
|
|
243 return S_OK;
|
|
244
|
|
245 BSTR FileName;
|
|
246 HRESULT hr;
|
|
247
|
1852
|
248 hr = pDoc->get_FullName(&FileName);
|
|
249 if (FAILED(hr))
|
7
|
250 return S_OK;
|
|
251
|
|
252 // Open the file in Vim and position to the current line
|
1852
|
253 if (VimOpenFile(FileName, 0))
|
7
|
254 {
|
|
255 if (! g_bDevStudioEditor)
|
|
256 {
|
|
257 // Close the document in developer studio
|
|
258 CComVariant vSaveChanges = dsSaveChangesPrompt;
|
|
259 DsSaveStatus Saved;
|
|
260
|
1852
|
261 pDoc->Close(vSaveChanges, &Saved);
|
7
|
262 }
|
|
263 }
|
|
264
|
1852
|
265 SysFreeString(FileName);
|
7
|
266 return S_OK;
|
|
267 }
|
|
268
|
1852
|
269 HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch * theWindow)
|
7
|
270 {
|
1852
|
271 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
272 return S_OK;
|
|
273 }
|
|
274
|
1852
|
275 HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch * theWindow)
|
7
|
276 {
|
1852
|
277 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
278 return S_OK;
|
|
279 }
|
|
280
|
1852
|
281 HRESULT CCommands::XApplicationEvents::WorkspaceOpen()
|
7
|
282 {
|
1852
|
283 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
284 return S_OK;
|
|
285 }
|
|
286
|
1852
|
287 HRESULT CCommands::XApplicationEvents::WorkspaceClose()
|
7
|
288 {
|
1852
|
289 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
290 return S_OK;
|
|
291 }
|
|
292
|
1852
|
293 HRESULT CCommands::XApplicationEvents::NewWorkspace()
|
7
|
294 {
|
1852
|
295 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
296 return S_OK;
|
|
297 }
|
|
298
|
|
299 // Debugger event
|
|
300
|
1852
|
301 HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch * pBreakpoint)
|
7
|
302 {
|
1852
|
303 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
304 return S_OK;
|
|
305 }
|
|
306
|
|
307
|
|
308 /////////////////////////////////////////////////////////////////////////////
|
|
309 // VisVim dialog
|
|
310
|
|
311 class CMainDialog : public CDialog
|
|
312 {
|
|
313 public:
|
1852
|
314 CMainDialog(CWnd * pParent = NULL); // Standard constructor
|
7
|
315
|
|
316 //{{AFX_DATA(CMainDialog)
|
|
317 enum { IDD = IDD_ADDINMAIN };
|
|
318 int m_ChangeDir;
|
|
319 BOOL m_bDevStudioEditor;
|
1852
|
320 BOOL m_bNewTabs;
|
7
|
321 //}}AFX_DATA
|
|
322
|
|
323 //{{AFX_VIRTUAL(CMainDialog)
|
|
324 protected:
|
1852
|
325 virtual void DoDataExchange(CDataExchange * pDX); // DDX/DDV support
|
7
|
326 //}}AFX_VIRTUAL
|
|
327
|
|
328 protected:
|
|
329 //{{AFX_MSG(CMainDialog)
|
|
330 afx_msg void OnEnable();
|
|
331 afx_msg void OnDisable();
|
|
332 //}}AFX_MSG
|
1852
|
333 DECLARE_MESSAGE_MAP()
|
7
|
334 };
|
|
335
|
1852
|
336 CMainDialog::CMainDialog(CWnd * pParent /* =NULL */ )
|
|
337 : CDialog(CMainDialog::IDD, pParent)
|
7
|
338 {
|
|
339 //{{AFX_DATA_INIT(CMainDialog)
|
|
340 m_ChangeDir = -1;
|
|
341 m_bDevStudioEditor = FALSE;
|
1852
|
342 m_bNewTabs = FALSE;
|
7
|
343 //}}AFX_DATA_INIT
|
|
344 }
|
|
345
|
1852
|
346 void CMainDialog::DoDataExchange(CDataExchange * pDX)
|
7
|
347 {
|
1852
|
348 CDialog::DoDataExchange(pDX);
|
7
|
349 //{{AFX_DATA_MAP(CMainDialog)
|
|
350 DDX_Radio(pDX, IDC_CD_SOURCE_PATH, m_ChangeDir);
|
1852
|
351 DDX_Check(pDX, IDC_DEVSTUDIO_EDITOR, m_bDevStudioEditor);
|
|
352 DDX_Check(pDX, IDC_NEW_TABS, m_bNewTabs);
|
7
|
353 //}}AFX_DATA_MAP
|
|
354 }
|
|
355
|
1852
|
356 BEGIN_MESSAGE_MAP(CMainDialog, CDialog)
|
7
|
357 //{{AFX_MSG_MAP(CMainDialog)
|
|
358 //}}AFX_MSG_MAP
|
1852
|
359 END_MESSAGE_MAP()
|
7
|
360
|
|
361
|
|
362 /////////////////////////////////////////////////////////////////////////////
|
|
363 // CCommands methods
|
|
364
|
1852
|
365 STDMETHODIMP CCommands::VisVimDialog()
|
7
|
366 {
|
1852
|
367 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
368
|
|
369 // Use m_pApplication to access the Developer Studio Application
|
|
370 // object,
|
|
371 // and VERIFY_OK to see error strings in DEBUG builds of your add-in
|
|
372 // (see stdafx.h)
|
|
373
|
1852
|
374 VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
|
7
|
375
|
|
376 CMainDialog Dlg;
|
|
377
|
|
378 Dlg.m_bDevStudioEditor = g_bDevStudioEditor;
|
1852
|
379 Dlg.m_bNewTabs = g_bNewTabs;
|
7
|
380 Dlg.m_ChangeDir = g_ChangeDir;
|
1852
|
381 if (Dlg.DoModal() == IDOK)
|
7
|
382 {
|
|
383 g_bDevStudioEditor = Dlg.m_bDevStudioEditor;
|
1852
|
384 g_bNewTabs = Dlg.m_bNewTabs;
|
7
|
385 g_ChangeDir = Dlg.m_ChangeDir;
|
|
386
|
|
387 // Save settings to registry HKEY_CURRENT_USER\Software\Vim\VisVim
|
1852
|
388 HKEY hAppKey = GetAppKey("Vim");
|
7
|
389 if (hAppKey)
|
|
390 {
|
1852
|
391 HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim");
|
7
|
392 if (hSectionKey)
|
|
393 {
|
1852
|
394 WriteRegistryInt(hSectionKey, "DevStudioEditor",
|
7
|
395 g_bDevStudioEditor);
|
1852
|
396 WriteRegistryInt(hSectionKey, "NewTabs",
|
|
397 g_bNewTabs);
|
|
398 WriteRegistryInt(hSectionKey, "ChangeDir", g_ChangeDir);
|
|
399 RegCloseKey(hSectionKey);
|
7
|
400 }
|
1852
|
401 RegCloseKey(hAppKey);
|
7
|
402 }
|
|
403 }
|
|
404
|
1852
|
405 VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
|
7
|
406 return S_OK;
|
|
407 }
|
|
408
|
1852
|
409 STDMETHODIMP CCommands::VisVimEnable()
|
7
|
410 {
|
1852
|
411 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
412 VimSetEnableState(true);
|
7
|
413 return S_OK;
|
|
414 }
|
|
415
|
1852
|
416 STDMETHODIMP CCommands::VisVimDisable()
|
7
|
417 {
|
1852
|
418 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
419 VimSetEnableState(false);
|
7
|
420 return S_OK;
|
|
421 }
|
|
422
|
1852
|
423 STDMETHODIMP CCommands::VisVimToggle()
|
7
|
424 {
|
1852
|
425 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
426 VimSetEnableState(! g_bEnableVim);
|
7
|
427 return S_OK;
|
|
428 }
|
|
429
|
1852
|
430 STDMETHODIMP CCommands::VisVimLoad()
|
7
|
431 {
|
1852
|
432 AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
7
|
433
|
|
434 // Use m_pApplication to access the Developer Studio Application object,
|
|
435 // and VERIFY_OK to see error strings in DEBUG builds of your add-in
|
|
436 // (see stdafx.h)
|
|
437
|
|
438 CComBSTR bStr;
|
|
439 // Define dispatch pointers for document and selection objects
|
|
440 CComPtr < IDispatch > pDispDoc, pDispSel;
|
|
441
|
|
442 // Get a document object dispatch pointer
|
1852
|
443 VERIFY_OK(m_pApplication->get_ActiveDocument(&pDispDoc));
|
7
|
444 if (! pDispDoc)
|
|
445 return S_OK;
|
|
446
|
|
447 BSTR FileName;
|
|
448 long LineNr = -1;
|
|
449
|
|
450 // Get the document object
|
1852
|
451 CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(pDispDoc);
|
7
|
452
|
|
453 if (! pDoc)
|
|
454 return S_OK;
|
|
455
|
|
456 // Get the document name
|
1852
|
457 if (FAILED(pDoc->get_FullName(&FileName)))
|
7
|
458 return S_OK;
|
|
459
|
|
460 // Get a selection object dispatch pointer
|
1852
|
461 if (SUCCEEDED(pDoc->get_Selection(&pDispSel)))
|
7
|
462 {
|
|
463 // Get the selection object
|
1852
|
464 CComQIPtr < ITextSelection, &IID_ITextSelection > pSel(pDispSel);
|
7
|
465
|
|
466 if (pSel)
|
|
467 // Get the selection line number
|
1852
|
468 pSel->get_CurrentLine(&LineNr);
|
7
|
469 }
|
|
470
|
|
471 // Open the file in Vim
|
1852
|
472 VimOpenFile(FileName, LineNr);
|
7
|
473
|
1852
|
474 SysFreeString(FileName);
|
7
|
475 return S_OK;
|
|
476 }
|
|
477
|
|
478
|
|
479 //
|
|
480 // Here we do the actual processing and communication with Vim
|
|
481 //
|
|
482
|
|
483 // Set the enable state and save to registry
|
|
484 //
|
1852
|
485 static void VimSetEnableState(BOOL bEnableState)
|
7
|
486 {
|
|
487 g_bEnableVim = bEnableState;
|
1852
|
488 HKEY hAppKey = GetAppKey("Vim");
|
7
|
489 if (hAppKey)
|
|
490 {
|
1852
|
491 HKEY hSectionKey = GetSectionKey(hAppKey, "VisVim");
|
7
|
492 if (hSectionKey)
|
1852
|
493 WriteRegistryInt(hSectionKey, "EnableVim", g_bEnableVim);
|
|
494 RegCloseKey(hAppKey);
|
7
|
495 }
|
|
496 }
|
|
497
|
|
498 // Open the file 'FileName' in Vim and goto line 'LineNr'
|
|
499 // 'FileName' is expected to contain an absolute DOS path including the drive
|
|
500 // letter.
|
|
501 // 'LineNr' must contain a valid line number or 0, e. g. for a new file
|
|
502 //
|
1852
|
503 static BOOL VimOpenFile(BSTR& FileName, long LineNr)
|
7
|
504 {
|
|
505
|
|
506 // OLE automation object for com. with Vim
|
1220
|
507 // When the object goes out of scope, it's destructor destroys the OLE
|
|
508 // connection;
|
|
509 // This is important to avoid blocking the object
|
7
|
510 // (in this memory corruption would be likely when terminating Vim
|
|
511 // while still running DevStudio).
|
|
512 // So keep this object local!
|
|
513 COleAutomationControl VimOle;
|
|
514
|
|
515 // :cd D:/Src2/VisVim/
|
|
516 //
|
|
517 // Get a dispatch id for the SendKeys method of Vim;
|
|
518 // enables connection to Vim if necessary
|
|
519 DISPID DispatchId;
|
1852
|
520 DispatchId = VimGetDispatchId(VimOle, "SendKeys");
|
7
|
521 if (! DispatchId)
|
|
522 // OLE error, can't obtain dispatch id
|
|
523 goto OleError;
|
|
524
|
|
525 OLECHAR Buf[MAX_OLE_STR];
|
|
526 char FileNameTmp[MAX_OLE_STR];
|
|
527 char VimCmd[MAX_OLE_STR];
|
|
528 char *s, *p;
|
|
529
|
|
530 // Prepend CTRL-\ CTRL-N to exit insert mode
|
|
531 VimCmd[0] = 0x1c;
|
|
532 VimCmd[1] = 0x0e;
|
|
533 VimCmd[2] = 0;
|
|
534
|
|
535 #ifdef SINGLE_WINDOW
|
|
536 // Update the current file in Vim if it has been modified.
|
|
537 // Disabled, because it could write the file when you don't want to.
|
1852
|
538 sprintf(VimCmd + 2, ":up\n");
|
7
|
539 #endif
|
1852
|
540 if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf)))
|
7
|
541 goto OleError;
|
|
542
|
|
543 // Change Vim working directory to where the file is if desired
|
|
544 if (g_ChangeDir != CD_NONE)
|
1852
|
545 VimChangeDir(VimOle, DispatchId, FileName);
|
7
|
546
|
|
547 // Make Vim open the file.
|
|
548 // In the filename convert all \ to /, put a \ before a space.
|
1852
|
549 if (g_bNewTabs)
|
|
550 {
|
|
551 sprintf(VimCmd, ":tab drop ");
|
3012
|
552 s = VimCmd + 10;
|
1852
|
553 }
|
|
554 else
|
|
555 {
|
|
556 sprintf(VimCmd, ":drop ");
|
|
557 s = VimCmd + 6;
|
|
558 }
|
7
|
559 sprintf(FileNameTmp, "%S", (char *)FileName);
|
3012
|
560 for (p = FileNameTmp; *p != '\0' && s < VimCmd + MAX_OLE_STR - 4; ++p)
|
7
|
561 if (*p == '\\')
|
|
562 *s++ = '/';
|
|
563 else
|
|
564 {
|
|
565 if (*p == ' ')
|
|
566 *s++ = '\\';
|
|
567 *s++ = *p;
|
|
568 }
|
|
569 *s++ = '\n';
|
|
570 *s = '\0';
|
|
571
|
1852
|
572 if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf)))
|
7
|
573 goto OleError;
|
|
574
|
|
575 if (LineNr > 0)
|
|
576 {
|
|
577 // Goto line
|
1852
|
578 sprintf(VimCmd, ":%d\n", LineNr);
|
|
579 if (! VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf)))
|
7
|
580 goto OleError;
|
|
581 }
|
|
582
|
|
583 // Make Vim come to the foreground
|
1852
|
584 if (! VimOle.Method("SetForeground"))
|
|
585 VimOle.ErrDiag();
|
7
|
586
|
|
587 // We're done
|
|
588 return true;
|
|
589
|
|
590 OleError:
|
|
591 // There was an OLE error
|
|
592 // Check if it's the "unknown class string" error
|
1852
|
593 VimErrDiag(VimOle);
|
7
|
594 return false;
|
|
595 }
|
|
596
|
|
597 // Return the dispatch id for the Vim method 'Method'
|
|
598 // Create the Vim OLE object if necessary
|
|
599 // Returns a valid dispatch id or null on error
|
|
600 //
|
1852
|
601 static DISPID VimGetDispatchId(COleAutomationControl& VimOle, char* Method)
|
7
|
602 {
|
|
603 // Initialize Vim OLE connection if not already done
|
1852
|
604 if (! VimOle.IsCreated())
|
7
|
605 {
|
1852
|
606 if (! VimOle.CreateObject("Vim.Application"))
|
7
|
607 return NULL;
|
|
608 }
|
|
609
|
|
610 // Get the dispatch id for the SendKeys method.
|
|
611 // By doing this, we are checking if Vim is still there...
|
1852
|
612 DISPID DispatchId = VimOle.GetDispatchId("SendKeys");
|
7
|
613 if (! DispatchId)
|
|
614 {
|
|
615 // We can't get a dispatch id.
|
|
616 // This means that probably Vim has been terminated.
|
|
617 // Don't issue an error message here, instead
|
|
618 // destroy the OLE object and try to connect once more
|
|
619 //
|
|
620 // In fact, this should never happen, because the OLE aut. object
|
|
621 // should not be kept long enough to allow the user to terminate Vim
|
|
622 // to avoid memory corruption (why the heck is there no system garbage
|
|
623 // collection for those damned OLE memory chunks???).
|
1852
|
624 VimOle.DeleteObject();
|
|
625 if (! VimOle.CreateObject("Vim.Application"))
|
7
|
626 // If this create fails, it's time for an error msg
|
|
627 return NULL;
|
|
628
|
1852
|
629 if (! (DispatchId = VimOle.GetDispatchId("SendKeys")))
|
7
|
630 // There is something wrong...
|
|
631 return NULL;
|
|
632 }
|
|
633
|
|
634 return DispatchId;
|
|
635 }
|
|
636
|
|
637 // Output an error message for an OLE error
|
|
638 // Check on the classstring error, which probably means Vim wasn't registered.
|
|
639 //
|
1852
|
640 static void VimErrDiag(COleAutomationControl& VimOle)
|
7
|
641 {
|
1852
|
642 SCODE sc = GetScode(VimOle.GetResult());
|
7
|
643 if (sc == CO_E_CLASSSTRING)
|
|
644 {
|
|
645 char Buf[256];
|
1852
|
646 sprintf(Buf, "There is no registered OLE automation server named "
|
7
|
647 "\"Vim.Application\".\n"
|
|
648 "Use the OLE-enabled version of Vim with VisVim and "
|
|
649 "make sure to register Vim by running \"vim -register\".");
|
1852
|
650 MessageBox(NULL, Buf, "OLE Error", MB_OK);
|
7
|
651 }
|
|
652 else
|
1852
|
653 VimOle.ErrDiag();
|
7
|
654 }
|
|
655
|
|
656 // Change directory to the directory the file 'FileName' is in or it's parent
|
|
657 // directory according to the setting of the global 'g_ChangeDir':
|
|
658 // 'FileName' is expected to contain an absolute DOS path including the drive
|
|
659 // letter.
|
|
660 // CD_NONE
|
|
661 // CD_SOURCE_PATH
|
|
662 // CD_SOURCE_PARENT
|
|
663 //
|
1852
|
664 static void VimChangeDir(COleAutomationControl& VimOle, DISPID DispatchId, BSTR& FileName)
|
7
|
665 {
|
|
666 // Do a :cd first
|
|
667
|
|
668 // Get the path name of the file ("dir/")
|
|
669 CString StrFileName = FileName;
|
|
670 char Drive[_MAX_DRIVE];
|
|
671 char Dir[_MAX_DIR];
|
|
672 char DirUnix[_MAX_DIR * 2];
|
|
673 char *s, *t;
|
|
674
|
1852
|
675 _splitpath(StrFileName, Drive, Dir, NULL, NULL);
|
7
|
676
|
|
677 // Convert to Unix path name format, escape spaces.
|
|
678 t = DirUnix;
|
|
679 for (s = Dir; *s; ++s)
|
|
680 if (*s == '\\')
|
|
681 *t++ = '/';
|
|
682 else
|
|
683 {
|
|
684 if (*s == ' ')
|
|
685 *t++ = '\\';
|
|
686 *t++ = *s;
|
|
687 }
|
|
688 *t = '\0';
|
|
689
|
|
690
|
|
691 // Construct the cd command; append /.. if cd to parent
|
|
692 // directory and not in root directory
|
|
693 OLECHAR Buf[MAX_OLE_STR];
|
|
694 char VimCmd[MAX_OLE_STR];
|
|
695
|
1852
|
696 sprintf(VimCmd, ":cd %s%s%s\n", Drive, DirUnix,
|
7
|
697 g_ChangeDir == CD_SOURCE_PARENT && DirUnix[1] ? ".." : "");
|
1852
|
698 VimOle.Method(DispatchId, "s", TO_OLE_STR_BUF(VimCmd, Buf));
|
7
|
699 }
|
|
700
|
|
701 #ifdef _DEBUG
|
|
702 // Print out a debug message
|
|
703 //
|
1852
|
704 static void DebugMsg(char* Msg, char* Arg)
|
7
|
705 {
|
|
706 char Buf[400];
|
1852
|
707 sprintf(Buf, Msg, Arg);
|
|
708 AfxMessageBox(Buf);
|
7
|
709 }
|
|
710 #endif
|