home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
vile-src.zip
/
vile-8.1
/
visvile
/
commands.cpp
next >
Wrap
C/C++ Source or Header
|
1998-09-07
|
14KB
|
485 lines
// Commands.cpp : implementation file
//
#include "stdafx.h"
#include "VisVile.h"
#include "Commands.h"
#include <initguid.h>
#include "oleauto.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <direct.h>
#include <io.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static char workspace_cwd[FILENAME_MAX + 1];
typedef struct openfile_opts_struct
{
BOOL goto_line_number; /* T -> extract document line number from
* current docu selection.
*/
BOOL ck_document_error; /* T -> If can't open document, report
* error, else assume that error indicates
* attempt to open non-TEXT document.
*/
BOOL honor_addin_state; /* T -> If addin disabled, do nothing. */
BOOL never_close; /* T -> regardless of current configuration,
* don't close the devstudio editor's copy
* of the open document.
*/
} OPENFILE_OPTS;
/////////////////////////////////////////////////////////////////////////////
// CCommands
CCommands::CCommands()
{
m_pApplication = NULL;
m_pApplicationEventsObj = NULL;
m_pDebuggerEventsObj = NULL;
}
CCommands::~CCommands()
{
if (m_pApplication)
m_pApplication->Release();
}
BOOL CCommands::SetApplicationObject(IApplication* pApplication)
{
// This function assumes pApplication has already been AddRef'd
// for us, which CDSAddIn did in its QueryInterface call
// just before it called us.
m_pApplication = pApplication;
// Create Application event handlers
XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj);
if (m_pApplicationEventsObj)
{
m_pApplicationEventsObj->AddRef();
m_pApplicationEventsObj->Connect(m_pApplication);
m_pApplicationEventsObj->m_pCommands = this;
}
else
return (FALSE);
#ifdef WANT_DEBUGGER_EVENTS
// Create Debugger event handler
// FIXME -- stupid code, assumes no errors
CComPtr<IDispatch> pDebugger;
if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger))
&& pDebugger != NULL)
{
XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj);
m_pDebuggerEventsObj->AddRef();
m_pDebuggerEventsObj->Connect(pDebugger);
m_pDebuggerEventsObj->m_pCommands = this;
}
#endif
return (TRUE);
}
void CCommands::UnadviseFromEvents()
{
if (m_pApplicationEventsObj)
{
m_pApplicationEventsObj->Disconnect(m_pApplication);
m_pApplicationEventsObj->Release();
m_pApplicationEventsObj = NULL;
}
#ifdef WANT_DEBUGGER_EVENTS
if (m_pDebuggerEventsObj != NULL)
{
// Since we were able to connect to the Debugger events, we
// should be able to access the Debugger object again to
// unadvise from its events (thus the VERIFY_OK below--see stdafx.h).
CComPtr<IDispatch> pDebugger;
VERIFY_OK(m_pApplication->get_Debugger(&pDebugger));
ASSERT (pDebugger != NULL);
m_pDebuggerEventsObj->Disconnect(pDebugger);
m_pDebuggerEventsObj->Release();
m_pDebuggerEventsObj = NULL;
}
#endif
}
/////////////////////////////////////////////////////////////////////////////
// Event handlers
static void
save_workspace_cwd(void)
{
if (_getcwd(workspace_cwd, sizeof(workspace_cwd)) == NULL)
workspace_cwd[0] = '\0'; // I suppose this might happen
}
static HRESULT
fetch_workspace_logname(CCommands *cmdp, char *file)
{
BSTR bstr_prjname;
HRESULT hr;
CComPtr <IDispatch> pDispProj;
hr = cmdp->GetApplicationObject()->get_ActiveProject(&pDispProj);
if (FAILED(hr))
return (ReportLastError(hr));
CComQIPtr < IGenericProject, &IID_IGenericProject > pProj(pDispProj);
if (! pProj)
{
::MessageBox(NULL,
"Unexpected OLE error: Unable to access current project object",
PROGNAM,
MB_OK|MB_ICONSTOP);
return (E_UNEXPECTED);
}
hr = pProj->get_Name(&bstr_prjname);
if (FAILED(hr))
return (ReportLastError(hr));
sprintf(file, "%S.plg", bstr_prjname);
SysFreeString(bstr_prjname);
if (workspace_cwd[0] == '\0')
save_workspace_cwd(); // as a side effect, update workspace cwd
// when necessary (should not be necessary).
return (hr);
}
static HRESULT
unexpected_docu_error(void)
{
::MessageBox(NULL,
"Unexpected OLE error: VisVile->DevStudio document connection failed.",
PROGNAM,
MB_OK|MB_ICONSTOP);
return (E_UNEXPECTED);
}
static HRESULT
openfile(IDispatch *theDocument, OPENFILE_OPTS *opts)
{
BSTR filename;
HRESULT hr;
long lineno = -1;
if (opts->honor_addin_state && ! visvile_opts.enabled)
return (S_OK);
// Process file _if_ a Text Document
CComQIPtr < IGenericDocument, &IID_IGenericDocument > pGenDoc(theDocument);
if (! pGenDoc)
return ((opts->ck_document_error) ? unexpected_docu_error() : S_OK);
else
{
BSTR doc_type;
int not_text;
hr = pGenDoc->get_Type(&doc_type);
if (FAILED(hr))
return (ReportLastError(hr));
not_text = (wcscmp(doc_type, L"Text") != 0);
SysFreeString(doc_type);
if (not_text)
return (S_OK);
}
// Okay, get the text document object
CComQIPtr < ITextDocument, &IID_ITextDocument > pDoc(theDocument);
if (! pDoc)
return ((opts->ck_document_error) ? unexpected_docu_error() : S_OK);
// Get the document name
hr = pDoc->get_FullName(&filename);
if (FAILED(hr))
return (ReportLastError(hr));
if (opts->goto_line_number)
{
LPDISPATCH pDispSel;
// Get a selection object dispatch pointer
if (SUCCEEDED (pDoc->get_Selection(&pDispSel)))
{
// Get the selection object
CComQIPtr < ITextSelection, &IID_ITextSelection > pSel (pDispSel);
if (pSel) // Get the selection line number
pSel->get_CurrentLine(&lineno);
pDispSel->Release();
}
// Else winvile will open file at BOF.
}
if (! opts->never_close && visvile_opts.close_ds_doc)
{
// Close the document in developer studio
CComVariant vSaveChanges = dsSaveChangesPrompt;
DsSaveStatus Saved;
pDoc->Close(vSaveChanges, &Saved);
}
// Open the file in Winvile and position to the selected line
hr = pVile->FileOpen(filename, lineno);
SysFreeString(filename);
if (FAILED(hr))
ReportLastError(hr);
return (hr);
}
// Application events
HRESULT CCommands::XApplicationEvents::BeforeBuildStart()
{
HRESULT hr = S_OK;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (visvile_opts.enabled)
{
if (visvile_opts.write_buffers)
{
/*
* The following cryptic vile command flushes all modified
* buffers to disk and does not prompt for user response.
*
* Note: because DevStudio decides what files need to be
* rebuilt _before_ this event is fired, the "write_buffers"
* option isn't quite as useful as it might seem. As a
* workaround, press the "build" button/key (F7) twice :-) .
* See ../doc/visvile.doc for further details.
*/
hr = pVile->VileCmd("1:ww\n", FALSE, FALSE);
if (FAILED(hr))
ReportLastError(hr);
}
if (visvile_opts.sync_errbuf)
{
char logpath[FILENAME_MAX + 1], file[FILENAME_MAX + 1];
/*
* The build log (activated from the Tools -> Options -> Build
* dialog box) may be accessed using this path:
*
* <workspace_cwd>\\<workspace_logname>
*/
hr = fetch_workspace_logname(m_pCommands, file);
if (SUCCEEDED(hr))
{
sprintf(logpath, "%s\\%s", workspace_cwd, file);
/*
* Nuke old logfile to ensure that the "wait-file" winvile
* command invoked by BuildFinish() below picks up a fresh
* logfile.
*/
(void) remove(logpath);
}
}
}
return (hr);
}
HRESULT
CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings)
{
HRESULT hr = S_OK;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (visvile_opts.enabled &&
visvile_opts.sync_errbuf &&
(nNumErrors || nNumWarnings))
{
char cmd[FILENAME_MAX * 5 + 1],
path[FILENAME_MAX + 1],
file[FILENAME_MAX + 1];
/*
* Suck the current active project's build log into winvile's error
* buffer. If the build log doesn't exist, the user will be annoyed
* by an editor that pops up an empty buffer :-) .
*
* The build log (activated from the Tools -> Options -> Build dialog
* box) may be accessed using this path:
*
* <workspace_cwd>\\<workspace_logname>
*/
hr = fetch_workspace_logname(m_pCommands, file);
if (SUCCEEDED(hr))
{
sprintf(path, "%s\\%s", workspace_cwd, file);
sprintf(cmd,
":e [History]\n:kill %s\n:wait-file %s\n:view %s\n:error-buffer %s\n",
file,
path,
path,
file);
pVile->VileCmd(cmd, TRUE, TRUE);
}
}
return (hr);
}
HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return S_OK;
}
HRESULT
CCommands::XApplicationEvents::DocumentOpen(IDispatch* theDocument)
{
OPENFILE_OPTS opts;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
opts.goto_line_number = TRUE;
opts.ck_document_error = TRUE;
opts.honor_addin_state = TRUE;
opts.never_close = FALSE;
return (openfile(theDocument, &opts));
}
HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch* theDocument)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return S_OK;
}
HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch* theDocument)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return S_OK;
}
HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch* theDocument)
{
OPENFILE_OPTS opts;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
opts.goto_line_number = FALSE;
opts.ck_document_error = TRUE;
opts.honor_addin_state = TRUE;
opts.never_close = FALSE;
return (openfile(theDocument, &opts));
}
HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch* theWindow)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return S_OK;
}
HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch* theWindow)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return S_OK;
}
HRESULT CCommands::XApplicationEvents::WorkspaceOpen()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
save_workspace_cwd();
return (S_OK);
}
HRESULT CCommands::XApplicationEvents::WorkspaceClose()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
workspace_cwd[0] = '\0'; // Erase saved cwd.
return (S_OK);
}
HRESULT CCommands::XApplicationEvents::NewWorkspace()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
save_workspace_cwd();
return (S_OK);
}
// Debugger event
HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch* pBreakpoint)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CCommands methods
STDMETHODIMP CCommands::VisVileConfig()
{
CConfigDlg Dlg;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
m_pApplication->EnableModeless(VARIANT_FALSE);
if (Dlg.DoModal() == IDOK)
{
visvile_regdata_dirty(); // Be sloppy & assume user changed cfg.
visvile_opts.cd_doc_dir = Dlg.m_cd_doc_dir;
visvile_opts.close_ds_doc = Dlg.m_close_ds_doc;
visvile_opts.enabled = Dlg.m_enabled;
visvile_opts.sync_errbuf = Dlg.m_sync_errbuf;
visvile_opts.write_buffers = Dlg.m_write_buffers;
}
m_pApplication->EnableModeless(VARIANT_TRUE);
return S_OK;
}
STDMETHODIMP CCommands::VisVileEnable()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (! visvile_opts.enabled)
{
visvile_opts.enabled = TRUE;
visvile_regdata_dirty();
}
return S_OK;
}
STDMETHODIMP CCommands::VisVileDisable()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (visvile_opts.enabled)
{
visvile_opts.enabled = FALSE;
visvile_regdata_dirty();
}
return S_OK;
}
STDMETHODIMP CCommands::VisVileOpenDoc()
{
HRESULT hr;
OPENFILE_OPTS opts;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Define dispatch pointers for document and selection objects
CComPtr < IDispatch > pDispDoc;
// Get a document object dispatch pointer
hr = m_pApplication->get_ActiveDocument(&pDispDoc);
if (FAILED(hr))
return (ReportLastError(hr));
opts.goto_line_number = TRUE;
opts.ck_document_error = FALSE;
opts.honor_addin_state = FALSE;
opts.never_close = TRUE;
return (openfile(pDispDoc, &opts));
}