Mercurial > vim
annotate src/VisVim/Commands.cpp @ 20606:7d5bd5affd11
Added tag v8.2.0856 for changeset 503886f64d5fdb88c4518a883d37bdabe807519b
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 31 May 2020 13:15:04 +0200 |
parents | 1759d0ec0a6f |
children |
rev | line source |
---|---|
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 | |
16356
1759d0ec0a6f
patch 8.1.1183: typos in VisVim comments
Bram Moolenaar <Bram@vim.org>
parents:
9199
diff
changeset
|
58 // for us, which CDSAddIn did in its 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 | |
16356
1759d0ec0a6f
patch 8.1.1183: typos in VisVim comments
Bram Moolenaar <Bram@vim.org>
parents:
9199
diff
changeset
|
507 // When the object goes out of scope, its destructor destroys the OLE |
1220 | 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 | |
9199
665d10cb3e6b
commit https://github.com/vim/vim/commit/ea0345901cc2af29f9c5dd0d9d8a818d5f96a63b
Christian Brabandt <cb@256bit.org>
parents:
3012
diff
changeset
|
578 sprintf(VimCmd, ":%ld\n", LineNr); |
1852 | 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 | |
16356
1759d0ec0a6f
patch 8.1.1183: typos in VisVim comments
Bram Moolenaar <Bram@vim.org>
parents:
9199
diff
changeset
|
656 // Change directory to the directory the file 'FileName' is in or its parent |
7 | 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 |