ime.cpp

来自「Windows CE 6.0 Word Application 源码」· C++ 代码 · 共 2,215 行 · 第 1/5 页

CPP
2,215
字号

		DWORD				cpMin = psel->GetCpMin();
		DWORD				cpMax = psel->GetCpMost();
		const				CCharFormat	*pCF;
		LONG				iFormat;

		if (cpMin != cpMax)
		{
			// for selection, we need to get the character format at cpMin+1
			CTxtRange rg( &ed, cpMin+1, 0 );
			iFormat = rg.Get_iCF ();

			psel->Set_iCF( iFormat );
		}
		else
			iFormat = psel->Get_iCF ();

		// get current Char format
		pCF = ed.GetCharFormat(iFormat);
		ReleaseFormats(iFormat, -1);

 		// if current font is not set correctly,
		// change to a font preferred by current keyboard.
		if ( pCF && ((UINT)GetCodePage(pCF->bCharSet) != cp))
		{
			psel->CheckChangeFont ( &ed, TRUE, (WORD)GetKeyboardLCID(), cp );
		}
	}
	
	if (piFormat)
		*piFormat = psel ? psel->Get_iCF () : -1;
}

/*
 *	INT CIme::GetCompositionStringInfo( HIMC hIMC, DWORD dwIndex,
 *			  WCHAR *uniCompStr, INT cchMax, BYTE *attrib, INT cbAttrib
 *			  LONG cchAttrib )
 *
 *	@mfunc
 *		For WM_IME_COMPOSITION string processing to get the requested
 *		composition string, by type, and convert it to Unicode.
 *
 *	@devnote
 *		We must use ImmGetCompositionStringA because W is not supported
 *		on Win95.
 *		
 *	@rdesc
 *		INT-cch of the Unicode composition string.
 *		Out param in UniCompStr.
 */
INT CIme::GetCompositionStringInfo(
	HIMC hIMC,			// @parm IME context provided by host.
	DWORD dwIndex,		// @parm The type of composition string.
	WCHAR *uniCompStr,	// @parm Out param, unicode result string.
	INT   cchUniCompStr,// @parm The cch for the Out param.
	BYTE *pattrib,		// @parm Out param, If attribute info is needed.
	INT   cchAttrib,	// @parm The cch of the attribute info.
	LONG *pcursorCP,	// @parm Out param, returns the CP of cusor.
	LONG *pcchAttrib )	// @parm how many attributes returned.
{
	TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CIme::GetCompositionStringInfo");

    // Pay close attention to cbXXX v. cchXXX in this routine.  One
    // wrinkle:  The attributes returned are an array of BYTEs, one per
    // character in the string - so for pattrib cb==cch.

	BYTE				compStr[sizeof(WCHAR)*256], attribInfo[256];	// Fix for WinCEOS RAID #15245
	INT					j, cbUniCompStr, cbAttrib, cbCompStr, cchCompStr, cbAttribRet, cursor;

#ifndef PWD_JUPITER
	INT					i, iMax;
#endif // PWD_JUPITER

	Assert ( hIMC );
	Assert ( uniCompStr );
    Assert ( cchUniCompStr >= 0 );
    Assert ( !pattrib || cchAttrib >= 0 );

	if ( pcursorCP )								// Init cursor out param.
		*pcursorCP = -1;
	if ( pcchAttrib )
		*pcchAttrib = 0;

    cbUniCompStr = cchUniCompStr * sizeof(WCHAR);
    cbAttrib = cchAttrib * sizeof(WCHAR);
    cbAttribRet = -1;
													// Get composition string.

	cbCompStr = pImmGetCompositionString( hIMC, dwIndex, compStr, sizeof(compStr)-1 );	// Fix for WinCEOS RAID #15245
                    // (ImmGetCompositionString takes size of compStr
                    // in bytes even for Unicode, returns size in bytes)
	if ( cbCompStr > 0 )							// If valid data.
	{
        // GuyBark Jupiter:
        // ImmGetCompositionStringA() doesn't exist on the device. So use the
        // wide version of it, and don't do any of the mbcs->wide stuff here.

#ifndef PWD_JUPITER
        // Convert to unicode
		cchCompStr = UnicodeFromMbcs( uniCompStr, cchUniCompStr,
										(CHAR *) compStr, cbCompStr );
#else
        // We already have the unicode string.
        memcpy((LPBYTE)uniCompStr, (LPBYTE)compStr, min(cbUniCompStr,min(cbCompStr, (INT)(sizeof(WCHAR)*256))));

        // Return number of characters.
        cchCompStr = cbCompStr / sizeof(WCHAR);

#endif // PWD_JUPITER

		if ( pattrib || pcursorCP )					// Need cursor or attribs?
		{
													// Get DBCS Cursor cp.
			cursor = pImmGetCompositionString( hIMC, GCS_CURSORPOS, NULL, 0 );

            if ( pattrib )
            {
                                                    // Get DBCS attributes.
                cbAttribRet = pImmGetCompositionString( hIMC, GCS_COMPATTR,
                                                        attribInfo, 255 );
            }

        // GuyBark Jupiter:
        // ImmGetCompositionStringA() doesn't exist on the device. So use the
        // wide version of it, and don't do any of the mbcs->wide stuff here.
#ifndef PWD_JUPITER
													// MultiToWide conversion.
			iMax = max ( cursor, cbAttribRet );
			if ( NULL == pattrib )
                cbAttrib = cbAttribRet;
			for (i = 0, j = 0; i <= iMax && j < cbAttrib; i++, j++ )
			{
				if ( cursor == i )					// Cursor from DBCS.
					cursor = j;

				if ( IsDBCSLeadByte( compStr[i] ) )
					i++;

                // shouldn't this be j instead of i??
				if ( pattrib && i < cbAttribRet )		// Attrib from DBCS.
					*pattrib++ = attribInfo[i];
			}
            j--;                                    // back off from last byte
                                                    // attrib cch==unicode cch
			Assert ( 0 >= cbAttribRet || j == cchCompStr );   // ??
#else
            // Return attribute array.
            if ( pattrib )
            {
                if ( cbAttribRet >= 0)
                {
                    j = min(cbAttribRet, min(cbAttrib,256));
                    memcpy(pattrib, attribInfo, j);
                }
            }
#endif // PWD_JUPITER

			if ( cursor >= 0 && pcursorCP  )			// If client needs cursor
				*pcursorCP = cursor;					//  or pcchAttrib.
			if ( cbAttribRet >= 0 && pcchAttrib )
				*pcchAttrib = j;
		}
	}
	else
	{
		if ( pcursorCP  )			
			*pcursorCP = 0;
		cchCompStr = 0;
	}

	return cchCompStr;
}

/*
 *	void CIme::SetCompositionFont ( CTxtEdit &ed, BOOL *pbUnderLineMode )
 *
 *	@mfunc
 *		Important for level 2 IME so that the composition window
 *		has the correct font. The lfw to lfa copy is due to the fact that
 *		Win95 does not support the W)ide call.
 *		It is also important for both level 2 and level 3 IME so that
 *		the candidate list window has the proper. font.
 */
void CIme::SetCompositionFont (
	CTxtEdit &ed, 		 		// @parm the containing text edit.
	BOOL	 *pbUnderLineMode)	// @parm the original char Underline mode
{
	TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CIme::SetCompositionFont" );
													
#ifndef MACPORT
	
	HIMC 				hIMC = ed.TxImmGetContext();// Get host's IME context.

	CTxtSelection		*psel;						// Selection.

	HDC					hdc;
	CCcs				*pccs;						// Font cache.
	LOGFONTW			lfw;
#ifndef PWD_JUPITER
	LOGFONTA			lfa;
#endif // PWD_JUPITER

	if ( hIMC )
	{												
		hdc 	= ed.TxGetDC();					
		if ( hdc )									//  the selection.
		{
			psel	= ed.GetSel();					// Get the font cache for
			if ( psel )
			{
				const	CCharFormat	*pCF;
				
				pCF = ed.GetCharFormat(_iFormatSave);

				if ( pCF )
				{
					BOOL	bFontOK = TRUE;

					if ( !ed.IsRich())
					{
						// We haven't done any font matching for plain text control,
						// check if this font maches current keyboard codepage.
						// If they don't match, we don't want to call ImmSetCompositionFont
						// or else the Candidate list will show garbage.
						if ( (UINT)GetCodePage(pCF->bCharSet) != GetKeyboardCodePage() )
							bFontOK = FALSE;
					}

					if ( bFontOK )
					{
#ifdef PWD_JUPITER
                        // GuyBark: Make sure the candidate window is displaying a J font.
                        CCharFormat CFj;

                        memcpy(&CFj, pCF, sizeof(CCharFormat));
                        CFj.bCharSet = GetCharSet(GetKeyboardCodePage());

                        pccs = fc().GetCcs(hdc, &CFj, ed._pdp->GetZoomNumerator(),
                            ed._pdp->GetZoomDenominator(), GetDeviceCaps(hdc, LOGPIXELSY));
#else
						pccs = fc().GetCcs(hdc, pCF, ed._pdp->GetZoomNumerator(),
							ed._pdp->GetZoomDenominator(), GetDeviceCaps(hdc, LOGPIXELSY));
#endif // PWD_JUPITER

						if( pccs )							// If font cache exist...
						{		
							lfw = pccs->_lf;				// Note: W to A copy.

                            // GuyBark: On the device, there is no ansi version of ImmSetCompositionFont().
#ifndef PWD_JUPITER
							memcpy(&lfa, &lfw, sizeof(lfa) - sizeof(lfa.lfFaceName));
	    					MbcsFromUnicode(
	    						lfa.lfFaceName, sizeof(lfa.lfFaceName), lfw.lfFaceName,
								-1, CP_ACP, UN_NOOBJECTS);

							// WinCE RAID #7183 fix.
							if(_imeLevel != IME_LEVEL_3){
							pImmSetCompositionFont( hIMC, &lfa );	
							}
#else
							// WinCE RAID #7183 fix.
							if(_imeLevel != IME_LEVEL_3){
							pImmSetCompositionFont( hIMC, &lfw );	
							}
#endif
							pccs->Release();
						}
					}

					if (pbUnderLineMode)
					{
						*pbUnderLineMode = (pCF->dwEffects & CFE_UNDERLINE);
					}
				}
			}
			ed.TxReleaseDC( hdc );
		}

		ed.TxImmReleaseContext( hIMC );				// Done with IME context.
	}
#endif
}

/*
 *	void CIme::SetCompositionForm ( CTxtEdit &ed )
 *
 *	@mfunc
 *		Important for level 2 IME so that the composition window
 *		is positioned correctly.
 *
 *	@comm
 *		We go through a lot of work to get the correct height. This requires
 *		getting information from the font cache and the selection.
 */
void CIme::SetCompositionForm (
	CTxtEdit &ed )	   	// @parm the containing text edit.
{
	TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CIme::SetCompositionForm" );
													
#ifndef MACPORT
	HIMC 				hIMC;

	CTxtSelection		*psel;						// Selection.

	HDC					hdc;
	
	LONG				iFormat;
	const CCharFormat	*pCF;
	CCcs				*pccs	= NULL;				// Font cache.

	COMPOSITIONFORM		cf;
	RECT				rcInset;

	
	if ( IME_LEVEL_2 == GetIMELevel() )
	{
		hIMC = ed.TxImmGetContext();				// Get host's IME context.
		
		if ( hIMC )
		{												
			psel	= ed.GetSel();					// Get the font cache for

			if (NULL == psel)
			{
			    AssertSz(psel, "Memory allocation eror in CIme::SetCompositionForm");
			    return;
			}    

			hdc 	= ed.TxGetDC();					
			if ( hdc )								//  the selection.
			{
				iFormat = psel->Get_iCF();
				pCF = ed.GetCharFormat(iFormat);
				ReleaseFormats(iFormat, -1);

				if ( pCF )
				{
					pccs = fc().GetCcs(hdc, pCF, ed._pdp->GetZoomNumerator(),
						ed._pdp->GetZoomDenominator(), GetDeviceCaps(hdc, LOGPIXELSY));
				}
				ed.TxReleaseDC( hdc );
			}

			// 1st line starts at caret
			if ( GetCaretPos( &cf.ptCurrentPos ) == FALSE
				|| cf.ptCurrentPos.x < 0  || cf.ptCurrentPos.y < 0 )
			{
				// Update the caret since the current caret is not visible
				if ( ed.fInplaceActive() )
				{	
					psel->UpdateCaret(TRUE);		// To force a scroll
					GetCaretPos( &cf.ptCurrentPos );
				}
			}

			if( pccs )								// If font cache exist...
			{										// Finer caret adjustment.
				if ( psel->GetCurrentDescent() >= 0 && psel->GetCaretHt() > 1 )
				{
					// Adjusted for the different in descents between current
					//  selected font and the current character.
					cf.ptCurrentPos.y += psel->GetCaretHt()
						+ (  pccs->_yDescent - psel->GetCurrentDescent()
						   - pccs->_yHeight );
				}
				pccs->Release();
			}

			// Bounding rect for the IME (lev 2) composition window, causing
			//  composition text to be wrapped within it.
			cf.dwStyle = CFS_RECT;
			ed.TxGetClientRect( &cf.rcArea );		// Set-up bounding rect.
			ed.TxGetViewInset( &rcInset, NULL );
			cf.rcArea.right 	-= rcInset.right;
			cf.rcArea.bottom 	-= rcInset.bottom;
			cf.rcArea.left 		+= rcInset.left;
			cf.rcArea.top 		+= rcInset.top;

			// Make sure the starting point is not
			// outside the rcArea.  This happens when
			// there is no text on the current line and the user
			// has selected a large font size.
			if (cf.ptCurrentPos.y < cf.rcArea.top)
				cf.ptCurrentPos.y = cf.rcArea.top;
			else if (cf.ptCurrentPos.y > cf.rcArea.bottom)
				cf.ptCurrentPos.y = cf.rcArea.bottom;

			if (cf.ptCurrentPos.x < cf.rcArea.left)
				cf.ptCurrentPos.x = cf.rcArea.left;
			else if (cf.ptCurrentPos.x > cf.rcArea.right)
				cf.ptCurrentPos.x = cf.rcArea.right;

			pImmSetCompositionWindow( hIMC, &cf );	// Set composition window.

			ed.TxImmReleaseContext( hIMC );				// Done with IME context.
		}
	}
#endif
}



/*
 *
 *	CIme::TerminateIMEComposition ( CTxtEdit &ed )
 *
 *	@mfunc	Terminate the IME Composition mode using CPS_COMPLETE
 *	@comm	The IME will generate WM_IME_COMPOSITION with the result string
 *
 */
void CIme::TerminateIMEComposition(
	CTxtEdit &ed, 			// @parm the containing text edit.
	TerminateMode mode)
{
	TRACEBEGIN(TRCSUBSYSFE, TRCSCOPEINTERN, "CIme::TerminateIMEComposition");
	DWORD dwTerminateMethod;

	HIMC hIMC = ed.TxImmGetContext();

	dwTerminateMethod = CPS_COMPLETE;
	if ( IME_LEVEL_2 == GetIMELevel()		// force cancel for near-caret IME
		 || mode == TERMINATE_FORCECANCEL	// caller wants force cancel
		 || ed._fIMECancelComplete )		// Client wants force cancel
	{
		dwTerminateMethod = CPS_CANCEL;
	}
	
	// force the IME to terminate the current session
	if (hIMC)
	{
		BOOL retCode;

		retCode = pImmNotifyIME( hIMC, NI_COMPOSITIONSTR,
			dwTerminateMethod, 0);
		
		if ( !retCode && !ed._fIMECancelComplete )
		{
			// CPS_COMPLETE fail, try CPS_CANCEL.  This happen with some ime which do not support
			// CPS_COMPLETE option (e.g. ABC IME version 4 with Win95 simplified Chinese)
			retCode = pImmNotifyIME( hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);

		}
		

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?