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