📄 tomdoc.cpp
字号:
*
* @rdesc
* HRESULT = (!ppSel) ? E_INVALIDARG :
* (if active selection exists) ? NOERROR : S_FALSE
*/
STDMETHODIMP CTxtEdit::GetSelection (
ITextSelection **ppSel) //@parm Out parm to receive selection pointer
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetSelection");
if(!ppSel)
return E_INVALIDARG;
CTxtSelection *psel = GetSel();
*ppSel = (ITextSelection *)psel;
if( psel )
{
(*ppSel)->AddRef();
return NOERROR;
}
return S_FALSE;
}
/*
* CTxtEdit::GetStoryCount(pCount)
*
* @mfunc
* Get count of stories in this document.
*
* @rdesc
* HRESULT = (!<p pCount>) ? E_INVALIDARG : NOERROR
*/
STDMETHODIMP CTxtEdit::GetStoryCount (
LONG *pCount) //@parm Out parm to receive count of stories
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetStoryCount");
if(!pCount)
return E_INVALIDARG;
*pCount = 1;
return NOERROR;
}
/*
* ITextDocument::GetStoryRanges(ITextStoryRanges **ppStories)
*
* @mfunc
* Property get method that gets the story collection object
* used to enumerate the stories in a document. Only invoke this
* method if GetStoryCount() returns a value greater than one.
*
* @rdesc
* HRESULT = (if Stories collection exists) ? NOERROR : E_NOTIMPL
*/
STDMETHODIMP CTxtEdit::GetStoryRanges (
ITextStoryRanges **ppStories) //@parm Out parm to receive stories ptr
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::GetStoryRanges");
return E_NOTIMPL;
}
/*
* ITextDocument::New()
*
* @mfunc
* Method that closes the current document and opens a document
* with a default name. If changes have been made in the current
* document since the last save and document file information exists,
* the current document is saved.
*
* @rdesc
* HRESULT = NOERROR
*/
STDMETHODIMP CTxtEdit::New ()
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::New");
CloseFile(TRUE); // Save and close file
return SetText(NULL, IGNORE_PROTECTION);
}
/*
* ITextDocument::Open(pVar, Flags, CodePage)
*
* @mfunc
* Method that opens the document specified by pVar.
*
* @rdesc
* HRESULT = (if success) ? NOERROR : E_OUTOFMEMORY
*
* @future
* Handle IStream
*/
STDMETHODIMP CTxtEdit::Open (
VARIANT * pVar, //@parm Filename or IStream
long Flags, //@parm Read/write, create, and share flags
long CodePage) //@parm Code page to use
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Open");
LONG cb; // Byte count for RTF check
EDITSTREAM es = {0, NOERROR, MyRead};
BOOL fReplaceSel = Flags & tomPasteFile;
HCURSOR hcur;
LRESULT lres;
TCHAR szType[cchRTFSig + 1];
if(!pVar || CodePage && CodePage != 1200 && !IsValidCodePage(CodePage))
return E_INVALIDARG; // IsValidCodePage(0) fails
// even tho CP_ACP = 0 (!)
if((Flags & 0xf) >= tomHTML) // RichEdit only handles auto,
return E_NOTIMPL; // plain text, & RTF formats
if(!fReplaceSel) // If not replacing selection,
New(); // save current file and
// delete current text
CDocInfo * pDocInfo = GetDocInfo();
if(!pDocInfo)
return E_OUTOFMEMORY;
pDocInfo->wCpg = (WORD)CodePage; // Save new code page and
pDocInfo->wFlags = (WORD)Flags & ~0xf0; // flags (w/o creation)
// Process access, share, and create flags
DWORD dwAccess = (Flags & tomReadOnly)
? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
if(Flags & tomShareDenyRead)
dwShare &= ~FILE_SHARE_READ;
if(Flags & tomShareDenyWrite)
dwShare &= ~FILE_SHARE_WRITE;
DWORD dwCreate = (Flags >> 4) & 0xf;
if(!dwCreate) // Flags nibble 2 must contain
dwCreate = OPEN_ALWAYS; // CreateFile's dwCreate
if(pVar->vt == VT_BSTR && pSysStringLen(pVar->bstrVal))
{
es.dwCookie = (DWORD)CreateFile(pVar->bstrVal, dwAccess, dwShare,
NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);
if((HANDLE)es.dwCookie == INVALID_HANDLE_VALUE)
return HRESULT_FROM_WIN32(GetLastError());
if(!fReplaceSel) // If not replacing selection,
{ // allocate new pName
pDocInfo->pName = pSysAllocString(pVar->bstrVal);
pDocInfo->hFile = (HANDLE)es.dwCookie;
pDocInfo->wFlags |= tomTruncateExisting; // Setup Saves
}
}
else
{
// FUTURE: check for IStream; if not, then fail
return E_INVALIDARG;
}
Flags &= 0xf; // Isolate conversion flags
// Get first few bytes of file to check for RTF and Unicode BOM
(*es.pfnCallback)(es.dwCookie, (LPBYTE)szType, cbRTFSig, &cb);
if(!Flags || Flags == tomRTF) // Auto or RTF file
{ // See if it's really RTF
Flags = tomRTF; // Suppose it is
if(cb != cbRTFSig || (memcmp(szRTFSig, szType, cbRTFSig) != 0))
Flags = tomText; // Not RTF, so use tomText
}
LONG j = 0; // Default rewind to 0
if (Flags == tomRTF) // RTF
Flags = SF_RTF; // Setup EM_STREAMIN for RTF
else
{ // If it starts with
if(cb > 1 && *(WORD *)szType == BOM) // Unicode byte-order mark
{ // (BOM) file is Unicode, so
pDocInfo->wCpg = 1200; // use Unicode code page and
j = 2; // bypass the BOM
}
Flags = SF_TEXT; // Setup EM_STREAMIN for text
}
SetFilePointer((HANDLE)es.dwCookie, j, NULL, FILE_BEGIN); // Rewind
if(fReplaceSel)
Flags |= SFF_SELECTION;
Flags |= SFF_KEEPDOCINFO;
hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
TxSendMessage(EM_STREAMIN, Flags, (LPARAM)&es, &lres);
SetCursor(hcur);
if(dwShare == (FILE_SHARE_READ | FILE_SHARE_WRITE) || fReplaceSel)
{ // Full sharing or replaced
CloseHandle((HANDLE)es.dwCookie); // selection, so close file
if(!fReplaceSel) // If replacing selection,
pDocInfo->hFile = NULL; // leave _pDocInfo->hFile
}
_fSaved = fReplaceSel ? FALSE : TRUE; // No changes yet unless
return (HRESULT)es.dwError;
}
/*
* ITextDocument::Range(long cpFirst, long cpLim, ITextRange **ppRange)
*
* @mfunc
* Method that gets a text range on the active story of the document
*
* @rdesc
* HRESULT = (!ppRange) ? E_INVALIDARG :
* (if success) ? NOERROR : E_OUTOFMEMORY
*/
STDMETHODIMP CTxtEdit::Range (
long cpFirst, //@parm Non active end of new range
long cpLim, //@parm Active end of new range
ITextRange ** ppRange) //@parm Out parm to receive range
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Range");
if(!ppRange)
return E_INVALIDARG;
*ppRange = new CTxtRange(this, cpFirst, cpFirst - cpLim);
if( *ppRange )
{
(*ppRange)->AddRef(); // CTxtRange() doesn't AddRef() because
return NOERROR; // it's used internally for things
} // besides TOM
return E_OUTOFMEMORY;
}
/*
* ITextDocument::RangeFromPoint(long x, long y, ITextRange **ppRange)
*
* @mfunc
* Method that gets the degenerate range corresponding (at or nearest)
* to the point with the screen coordinates x and y.
*
* @rdesc
* HRESULT = (!ppRange) ? E_INVALIDARG :
* (if out of RAM) ? E_OUTOFMEMORY :
* (if range exists) ? NOERROR : S_FALSE
*/
STDMETHODIMP CTxtEdit::RangeFromPoint (
long x, //@parm Horizontal coord of point to use
long y, //@parm Vertical coord of point to use
ITextRange **ppRange) //@parm Out parm to receive range
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::RangeFromPoint");
if(!ppRange)
return E_INVALIDARG;
*ppRange = (ITextRange *) new CTxtRange(this, 0, 0);
if(!*ppRange)
return E_OUTOFMEMORY;
(*ppRange)->AddRef(); // CTxtRange() doesn't AddRef()
return (*ppRange)->SetPoint(x, y, 0, 0);
}
/*
* ITextDocument::Redo(long Count, long *pCount)
*
* @mfunc
* Method to perform the redo operation Count times
*
* @rdesc
* HRESULT = (if Count redos performed) ? NOERROR : S_FALSE
*/
STDMETHODIMP CTxtEdit::Redo (
long Count, //@parm Number of redo operations to perform
long * pCount) //@parm Number of redo operations performed
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Redo");
CCallMgr callmgr(this);
LONG i = 0;
if (_predo)
{
// Freeze the display during the execution of the anti-events
CFreezeDisplay fd(_pdp);
for ( ; i < Count; i++)
PopAndExecuteAntiEvent(_predo, 0);
}
if(pCount)
*pCount = i;
return i == Count ? NOERROR : S_FALSE;
}
/*
* ITextDocument::Save(pVar, Flags, CodePage)
*
* @mfunc
* Method that saves this ITextDocument to the target pVar,
* which is a VARIANT that can be a filename, an IStream, or NULL. If
* NULL, the filename given by this document's name is used. It that,
* in turn, is NULL, the method fails. If pVar specifies a filename,
* that name should replace the current Name property.
*
* @rdesc
* HRESULT = (!pVar) ? E_INVALIDARG :
* (if success) ? NOERROR : E_FAIL
*
* @devnote
* This routine can be called with NULL arguments
*/
STDMETHODIMP CTxtEdit::Save (
VARIANT * pVar, //@parm Save target (filename or IStream)
long Flags, //@parm Read/write, create, and share flags
long CodePage) //@parm Code page to use
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Save");
LONG cb; // Byte count for writing Unicode BOM
EDITSTREAM es = {0, NOERROR, MyWrite};
BOOL fChange = FALSE; // No doc info change yet
HCURSOR hcur;
CDocInfo * pDocInfo = GetDocInfo();
WORD wBOM = BOM;
if(CodePage && CodePage != 1200 && !IsValidCodePage(CodePage) ||
(DWORD)Flags > 0x1fff)
{
return E_INVALIDARG;
}
if((Flags & 0xf) >= tomHTML) // RichEdit only handles auto,
return E_NOTIMPL; // plain text, & RTF formats
if(!pDocInfo) // Doc info doesn't exist
return E_OUTOFMEMORY;
if (pVar && pVar->vt == VT_BSTR && // Filename string
pVar->bstrVal &&
pSysStringLen(pVar->bstrVal) && // NonNULL filename specified
(!pDocInfo->pName ||
OLEstrcmp(pVar->bstrVal, pDocInfo->pName)))
{ // Filename differs
fChange = TRUE; // Force write to new file
CloseFile(FALSE); // Close current file; no save
pDocInfo->pName = pSysAllocString(pVar->bstrVal);
if( !pDocInfo->pName )
return E_OUTOFMEMORY;
pDocInfo->wFlags &= ~0xf0; // Kill previous create mode
}
DWORD flags = pDocInfo->wFlags;
if(!(Flags & 0xf)) // If convert flags are 0,
Flags |= flags & 0xf; // use values in doc info
if(!(Flags & 0xf0)) // If create flags are 0,
Flags |= flags & 0xf0; // use values in doc info
if(!(Flags & 0xf00)) // If share flags are 0,
Flags |= flags & 0xf00; // use values in doc info
if(!CodePage) // If code page is 0,
CodePage = pDocInfo->wCpg; // use code page in doc info
if((DWORD)Flags != flags || // If flags or code page
(WORD)CodePage != pDocInfo->wCpg) // changed, force write
{
fChange = TRUE;
}
pDocInfo->wCpg = (WORD)CodePage; // Save new code page and
pDocInfo->wFlags = (WORD)Flags; // flags
// yikes, nowhere to save. bail-out now.
if( !_pDocInfo->pName )
return E_FAIL;
if(_fSaved && !fChange) // No changes, so assume
return NOERROR; // saved file is up to date
// Process access, share, and create flags
DWORD dwAccess = (Flags & tomReadOnly)
? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
if(Flags & tomShareDenyRead)
dwShare &= ~FILE_SHARE_READ;
if(Flags & tomShareDenyWrite)
dwShare &= ~FILE_SHARE_WRITE;
DWORD dwCreate = (Flags >> 4) & 0xf;
if(!dwCreate)
dwCreate = CREATE_NEW;
if(pDocInfo->hFile)
{
CloseHandle(pDocInfo->hFile); // Close current file handle
pDocInfo->hFile = NULL;
}
es.dwCookie = (DWORD)CreateFile(pDocInfo->pName, dwAccess, dwShare, NULL,
dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);
if((HANDLE)es.dwCookie == INVALID_HANDLE_VALUE)
return HRESULT_FROM_WIN32(GetLastError());
pDocInfo->hFile = (HANDLE)es.dwCookie;
Flags &= 0xf; // Isolate conversion flags
if(Flags == tomRTF) // RTF
Flags = SF_RTF; // Setup EM_STREAMOUT for RTF
else
{ // If Unicode, start file with
if(pDocInfo->wCpg == 1200) // Unicode byte order mark
(*es.pfnCallback)(es.dwCookie, (LPBYTE)&wBOM, 2, &cb);
Flags = SF_TEXT; // Setup EM_STREAMOUT for text
}
hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
TxSendMessage(EM_STREAMOUT, Flags, (LPARAM)&es, NULL);
SetCursor(hcur);
if(dwShare == (FILE_SHARE_READ | FILE_SHARE_WRITE))
{ // Full sharing, so close
CloseHandle(pDocInfo->hFile); // current file handle
pDocInfo->hFile = NULL;
}
_fSaved = TRUE; // File is saved
return (HRESULT)es.dwError;
}
/*
* ITextDocument::SetDefaultTabStop (Value)
*
* @mfunc
* Property set method that sets the default tab stop to be
* used whenever the explicit tabs don't extend far enough.
*
* @rdesc
* HRESULT = (Value < 0) ? E_INVALIDARG : NOERROR
*/
STDMETHODIMP CTxtEdit::SetDefaultTabStop (
float Value) //@parm Out parm to receive default tab stop
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetDefaultTabStop");
if(Value < 0)
return E_INVALIDARG;
CDocInfo *pDocInfo = GetDocInfo();
if(!pDocInfo) // Doc info doesn't exist
return E_OUTOFMEMORY;
pDocInfo->dwDefaultTabStop = FPPTS_TO_TWIPS(Value);
return NOERROR;
}
/*
* ITextDocument::SetSaved (Value)
*
* @mfunc
* Property set method that sets whether this instance has been
* saved, i.e., no changes since last save
*
* @rdesc
* HRESULT = NOERROR
*/
STDMETHODIMP CTxtEdit::SetSaved (
long Value) //@parm New value of Saved property
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::SetSaved");
_fSaved = Value ? TRUE : FALSE;
return NOERROR;
}
/*
* ITextDocument::Undo(long Count, long *pCount)
*
* @mfunc
* Method to perform the undo operation Count times.
*
* @rdesc
* HRESULT = (if Count undos performed) ? NOERROR : S_FALSE
*/
STDMETHODIMP CTxtEdit::Undo (
long Count, //@parm Number of undo operations to perform
// 0 suspends undo processing
// -1 turns restores it
long * pCount) //@parm Number of undo operations performed
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtEdit::Undo");
CCallMgr callmgr(this);
LONG i = 0;
if (_pundo)
{
// Freeze the display during the execution of the anti-events
CFreezeDisplay fd(_pdp);
for ( ; i < Count; i++)
PopAndExecuteAntiEvent(_pundo, 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -