📄 textserv.cpp
字号:
{
_fModified = FALSE;
}
_fSaved = FALSE; // ITextDocument isn't Saved
// Adjust text limit if necessary
TxSetMaxToMaxText();
return S_OK;
}
/////////////////////////// ITextServices Methods ////////////////////////////////
/*
* @doc EXTERNAL
*
* CTxtEdit::TxSendMessage (msg, wparam, lparam, plresult)
*
* @mfunc
* Used by window host to forward messages sent to its window to the
* text services.
*
* @rdesc
* NOERROR Message was processed, and some action taken <nl>
* S_FALSE Message was not processed. Typically indicates that caller
* should process message, maybe by calling DefWindowProc <nl>
* S_MSG_KEYIGNORED Message processed, but no action was taken <nl>
* E_OUTOFMEMORY <nl>
*
* @comm
* Note that two return values are passed back from this function.
* <p plresult> is the return value that should be passed back from a
* window proc. However, in some cases, the returned LRESULT does not
* contain enough information. For example, to implement cursoring
* around controls, it's useful to know if a keystroke (such as right
* arrow) was processed, but ignored (e.g. the caret is already at the
* rightmost position in the the text). In these cases, extra
* information may be returned via the returned HRESULT.
*
* WM_CHAR and WM_KEYDOWN should return S_MSG_KEYIGNORED when a key or
* char has been recognized but had no effect given the current state,
* e.g., a VK_RIGHT key when the insertion point is already at the end of
* the document). This is used by Forms3 to pass the key up the visual
* hierarchy, so that for example, focus moves to the next control in the
* TAB order.
*
* This includes the following cases:
*
* 1. Any key trying to move the insertion point beyond the end of the
* document; or before the begining of the document.
*
* 2. Any key trying to move the insertion point beyond the last line or
* before the first line.
*
* 3. Any insertion of character (WM_CHAR) that would move the insertion
* point past the maximum length of the control.
*/
HRESULT CTxtEdit::TxSendMessage (
UINT msg, //@parm Message id
WPARAM wparam, //@parm WPARAM from window's message
LPARAM lparam, //@parm LPARAM from window's message
LRESULT *plresult ) //@parm Where to put message's return LRESULT
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEEXTERN, "CTxtEdit::TxSendMessage");
HRESULT hr = S_OK;
LRESULT lres = 0;
CObjectMgr *pobjmgr;
extern UINT gWM_MouseRoller; // New Magellan msg ID.
START_PROFILING
CCallMgr callmgr(this);
CGenUndoBuilder undobldr(this, UB_AUTOCOMMIT );
#ifdef MACPORTREMOVEIT
// PowerMac's cannot set breakpoints on a running application and have
// no way to stop the running appliation.This code allows one to
// stop the executable when the user holds down the option key and
// a break point has been set in the indicated spot below. -jOn
BOOL fMacBreak = GetAsyncKeyState(VK_OPTION)<0;// Is user holding OPTION?
if ( fMacBreak )
{ // any old statement will due.
fMacBreak = TRUE; // Set a break point here for stopping the Mac.
}
#endif // MACPORTREMOVE
if ( gWM_MouseRoller == msg ) // map Magellan msg.
{
// convert wparam to correspond to the wparam for the system.
// Unfortunately, this isn't done automatically for us.
short zdelta = (short)(long)wparam;
wparam = MAKELONG(0, zdelta);
msg = WM_MOUSEWHEEL;
}
if (IsIMEComposition())
{
// During IME Composition, there are some messages we should
// not handle. Also, there are other messages we need to handle by
// terminating the IME composition first.
// For WM_KEYDOWN, this is handled inside edit.c OnTxKeyDown().
switch(msg)
{
case WM_COPY:
case WM_CUT:
#ifndef NODROPFILES
case WM_DROPFILES:
#endif
case EM_REDO:
return S_OK; // Just ignore these
case EM_UNDO:
case WM_UNDO:
// just terminate and exist for undo cases
_ime->TerminateIMEComposition(*this, CIme::TERMINATE_NORMAL);
return S_OK;
case EM_REPLACESEL:
case WM_SETTEXT:
case WM_CLEAR:
case EM_STREAMIN:
// these messages are used to reset our state, so reset
// IME as well
_ime->TerminateIMEComposition(*this, CIme::TERMINATE_FORCECANCEL);
break;
// GuyBark JupiterJ 49220: Pressing the Alt key with another
// key should not result in the string being determined.
#ifndef PWD_JUPITER
case WM_SYSKEYDOWN:
// Don't terminate IME composition on VK_PROCESSKEY (F10) since Japanese
// IME will process the F10 key
if ( wparam == VK_PROCESSKEY )
break;
// otherwise we want to terminate the IME
#endif // ! PWD_JUPITER
case EM_SETWORDBREAKPROC:
case WM_PASTE:
case EM_PASTESPECIAL:
// GuyBark JupiterJ IME: Ignore dlbclk when undetermined text exists.
case WM_LBUTTONDBLCLK:
return hr;
#ifndef PWD_JUPITER // GuyBark: In JupiterJ, a button down does NOT terminate the composition.
case WM_LBUTTONDOWN:
#ifndef NOMAGELLAN
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
#endif
#endif // ! PWD_JUPITER
case EM_SCROLL:
case EM_SCROLLCARET:
case WM_VSCROLL:
case WM_HSCROLL:
case WM_KILLFOCUS:
// Windows CE Tools #37200
// TODO: Don't stream out the IME data at all -- right now all the
// IME data will be streamed out along with the text in the control.
// case EM_STREAMOUT:
case EM_SETREADONLY:
case EM_SETSEL:
case EM_EXSETSEL:
case EM_SETPARAFORMAT:
case EM_SETCHARFORMAT:
#ifndef PEGASUS
case WM_INPUTLANGCHANGEREQUEST:
#endif
_ime->TerminateIMEComposition(*this, CIme::TERMINATE_NORMAL);
}
}
switch(msg)
{
case EM_CANPASTE:
// we don't check for protection here, as RichEdit 1.0
// doesn't
lres = _ldte.CanPaste(NULL, (CLIPFORMAT) wparam, RECO_PASTE);
break;
case EM_CANUNDO:
if( _pundo )
{
lres = _pundo->CanUndo();
}
break;
case EM_CANREDO:
if( _predo )
{
lres = _predo->CanUndo();
}
break;
case EM_GETUNDONAME:
if( _pundo )
{
lres = _pundo->GetNameIDFromAE(wparam);
}
break;
case EM_GETREDONAME:
if( _predo )
{
lres = _predo->GetNameIDFromAE(wparam);
}
break;
case EM_STOPGROUPTYPING:
if( _pundo )
{
// we'll only stop group typing iff wparam
// is zero (meaning stop regardless) _or_ if
// wparam matches the merge anti event.
//
// This feature allows clients to say that only
// a specific anti-event should close out it's
// "fuzzy" state. Note that currently, only the
// merge anti-event has this fuzzy state.
if( !wparam ||
(IAntiEvent *)wparam == _pundo->GetMergeAntiEvent() )
{
_pundo->StopGroupTyping();
}
}
break;
#ifndef TARGET_NT
case WM_IME_REQUEST:
// GuyBark JupiterJ 49850: Must handle this if we're going to reconvert.
// #9560 fix 1999/2/24 by v-tetsus
{
CTxtSelection * const psel = GetSel();
if (NULL == psel)
{
hr = E_OUTOFMEMORY;
break;
}
DWORD i;
DWORD cpMin, cpMax, cch;
cpMin = psel->GetCpMin();
cpMax = psel->GetCpMost();
cch = cpMax - cpMin;
CTxtPtr tp(this, cpMin);
LPTSTR pText = new TCHAR[cch+1];
if(tp.GetText(cch, pText) >= 0){
for(i=0 ; i < cch ; i++){
if(pText[i] < 0x20){
OnSetSel(cpMin, cpMin + i);
break;
}
}
}
delete[] pText;
}
// #9560 fix 1999/2/24 by v-tetsus
lres = IMEHandleRequest(wparam, lparam, this);
break;
#endif // !TARGET_NT
case WM_IME_STARTCOMPOSITION: // IME has begun interpreting user input
// The third parameter to IsntProectedOrReadOnly is the code for
// regular WM_KEYDOWN lparam because the lparam for
// WM_IME_STARTCOMPOSITION is not valid.
hr = StartCompositionGlue (
*this,
IsntProtectedOrReadOnly(WM_KEYDOWN, VK_PROCESSKEY, 0x01e001L),
undobldr );
break;
case WM_IME_COMPOSITION: // State of user's input has changed
hr = CompositionStringGlue ( lparam, *this, undobldr );
break;
case WM_IME_ENDCOMPOSITION: // User has OK'd IME conversions
hr = EndCompositionGlue ( *this, undobldr );
break;
case WM_IME_NOTIFY: // Candidate window state change info, etc.
hr = IMENotifyGlue ( wparam, lparam, *this );
break;
case WM_IME_COMPOSITIONFULL: // Level 2 comp string about to overflow.
IMECompositionFull ( *this );
hr = S_FALSE;
break;
case WM_IME_CHAR: // 2 byte character, usually FE.
if ( IsIMEComposition() && _ime->IgnoreIMECharMsg() )
{
hr = NOERROR;
break;
}
else
{
TCHAR unicodeConvert;
BYTE bytes[2];
bytes[0] = wparam >> 8; // Interchange DBCS bytes in endian
bytes[1] = wparam; // independent fashion (use byte array)
CTxtSelection *psel = GetSel();
if (NULL == psel)
{
hr = E_OUTOFMEMORY;
break;
}
// need to convert both single-byte KANA and DBC
if (!bytes[0] || IsDBCSLeadByte(bytes[0]))
{
if( UnicodeFromMbcs((LPWSTR)&unicodeConvert, 1,
bytes[0] == 0 ? (LPCSTR)&bytes[1] : (LPCSTR)bytes,
bytes[0] == 0 ? 1 : 2,
GetKeyboardCodePage()) == 1 )
wparam = unicodeConvert;
}
CIme::CheckKeyboardFontMatching ( GetKeyboardCodePage(), *this, NULL );
psel->SetDualFontMode(TRUE);
} // **** Fall through to WM_CHAR *****
case WM_CHAR:
#if defined(WIN95_IMEDEBUG) && !defined(MACPORT)
if ((WORD)wparam == 0x40 && // Shift-2 toggles forceLevel2
(GetKeyState(VK_SHIFT) & 0x8000))
{
forceLevel2 = !forceLevel2;
}
#endif
// for Japanese, if Kana mode is on,
// Kana characters (single byte Japanese char) are coming in via WM_CHAR.
// Also, for Win95 system and Own host, wparam has been translated already
// (in remain.cpp)
if (_fKANAMode && WM_CHAR == msg &&
!(fInOurHost() && VER_PLATFORM_WIN32_WINDOWS == dwPlatformId))
{
// check if this is a single byte character.
TCHAR unicodeConvert;
BYTE bytes[2];
bytes[0] = wparam >> 8; // Interchange DBCS bytes in endian
bytes[1] = wparam; // independent fashion (use byte array)
if (!bytes[0])
{
if( UnicodeFromMbcs((LPWSTR)&unicodeConvert, 1,
(LPCSTR)&bytes[1], 1, GetKeyboardCodePage()) == 1 )
wparam = unicodeConvert;
}
}
lres = hr = OnTxChar((WORD) wparam, (DWORD) lparam, &undobldr);
#ifdef PWD_JUPITER
// GuyBark: Try to match what Word97 does.
// Say the user has just added a CR, on a line with a Heading level style.
// In Word97 and PWord in Outline View, we stay at the current heading level,
// so that's ok. But in Normal view, Word97 will start the next line in the
// Normal style. PWord currently maintains the Heading level. So change this,
// such that PWord will start the next line in the Normal style too.
// Has the user added a CR?
if(wparam == VK_RETURN)
{
// Are we in Normal View?
if(!IsInOutlineView())
{
LONG cch;
// GuyBark Jupiter 42376:
// Only do this is the caret is at the end of the line!
// If the new line added following the insertion of the
// CR is zero length, then we know the CR was added at
// the end of the previous line.
if((TxLineLength((LONG)-1, &cch) == S_OK) && (cch == 0))
{
// Get the current selection and the range to be changed to
// Normal style. This will always be a zero-length selection,
// but we still need to do this to get the caret position.
CTxtSelection * psel = GetSelNC();
CTxtRange rg(*psel);
CPFRunPtr rp(rg);
// Don't do anything, if style is already Normal.
if(rp.GetOutlineLevel() != 1)
{
// FUTURE: The undo of the CR addition now takes two steps
// due to this extra promotion here. One day this should
// me merged into a single undo.
// Now change to Normal style.
hr = rg.Promote(0, &undobldr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -