⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtfwrit.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	if(!fInTable && (pPF->dxOffset &&
		!PutCtrlWord(CWF_VAL, i_fi, -pPF->dxOffset)	||
		pPF->dxStartIndent + pPF->dxOffset &&
		!PutCtrlWord(CWF_VAL, i_li, pPF->dxStartIndent + pPF->dxOffset) ||
		pPF->dxRightIndent	  &&
		!PutCtrlWord(CWF_VAL, i_ri, pPF->dxRightIndent)))
	{
		goto CleanUp;
	}
	if (pPF->dySpaceBefore	  &&
		!PutCtrlWord(CWF_VAL, i_sb, pPF->dySpaceBefore) ||
		pPF->dySpaceAfter	  &&
		!PutCtrlWord(CWF_VAL, i_sa, pPF->dySpaceAfter))
	{
		goto CleanUp;
	}

	if (dwRule)									// Special line spacing active
	{
		i = 0;									// Default "At Least" or
		if (dwRule == tomLineSpaceExactly)		//  "Exactly" line spacing
			dy = -abs(dy);						// Use negative for "Exactly"

		else if(dwRule == tomLineSpaceMultiple)	// RichEdit uses 20 units/line
		{										// RTF uses 240 units/line
			i++;
			dy *= 12;							
		}

		else if (dwRule != tomLineSpaceAtLeast && dy > 0)
		{
			i++;								// Multiple line spacing
			if (dwRule <= tomLineSpaceDouble)	// 240 units per line
				dy = 120 * (dwRule + 2);
		}
		if (!PutCtrlWord(CWF_VAL, i_sl, dy) ||
			!PutCtrlWord(CWF_VAL, i_slmult, i))
		{
			goto CleanUp;
		}
	}

	dwEffects = pPF->wEffects & ((1 << CPFEFFECTS) - 1);
	for(c = CPFEFFECTS; dwEffects && c--;		// Output PARAFORMAT2 effects
		dwEffects >>= 1)	
	{
		// rgiszPFEffects[] contains PF effect keywords in the
		//  order max PFE_xx to min PFE-xx

		AssertSz(rgiszPFEffects[2] == i_hyphpar,
			"CRTFWrite::WriteParaFormat(): rgiszPFEffects is out-of-sync with PFE_XXX");
		// \hyphpar has opposite logic to our PFE_DONOTHYPHEN so we emit
		// \hyphpar0 to toggle the property off

		if (dwEffects & 1 &&
			!PutCtrlWord((c == 2) ? CWF_VAL : CWF_STR, rgiszPFEffects[c], 0))
		{
			goto CleanUp;
		}				
	}
	
	if (!fInTable && IN_RANGE(PFA_RIGHT, pPF->wAlignment, PFA_JUSTIFY) &&
		!PutCtrlWord(CWF_STR, rgiszAlignment[pPF->wAlignment - 1]))
	{
		goto CleanUp;
	}

	for (i = 0; i < cTab; i++)
	{
		pPF->GetTab(i, &tabPos, &tabAlign, &tabLead);
		AssertSz (tabAlign <= tomAlignBar && tabLead <= 5,
			"CRTFWrite::WriteParaFormat: illegal tab leader/alignment");

		i_t = i_tb;								// Default \tb (bar tab)
		if (tabAlign != tomAlignBar)			// It isn't a bar tab
		{
			i_t = i_tx;							// Use \tx for tabPos
			if (tabAlign &&						// Put nonleft alignment
				!PutCtrlWord(CWF_STR, rgiszTabAlign[tabAlign-1]))
			{
				goto CleanUp;
			}
		}
		if (tabLead &&							// Put nonzero tab leader
			!PutCtrlWord(CWF_STR, rgiszTabLead[tabLead-1]) ||
			!PutCtrlWord(CWF_VAL, i_t, tabPos))
		{
			goto CleanUp;
		}
	}

CleanUp:
	return _ecParseError;
}

/*
 *	CRTFWrite::WriteText(cwch, lpcwstr, nCodePage, fIsDBCS)
 *
 *	@mfunc
 *		Write out <p cwch> chars from the Unicode text string <p lpcwstr> taking care to
 *		escape any special chars.  The Unicode text string is scanned for characters which
 *		map directly to RTF strings, and the surrounding chunks of Unicode are written
 *		by calling WriteTextChunk.
 *
 *	@rdesc
 *		EC	The error code
 */
EC CRTFWrite::WriteText(
	LONG		cwch,					// @parm # chars in buffer
	LPCWSTR 	lpcwstr,				// @parm Pointer to text
	INT			nCodePage,				// @parm code page to use to convert to DBCS
	BOOL		fIsDBCS)				// @parm indicates whether lpcwstr is a Unicode string
										//		or a DBCS string stuffed into a WSTR
{
	TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::WriteText");

	WCHAR *pwchScan;
	WCHAR *pwchStart;

	if (_fBulletPending)
	{
		_fBulletPending = FALSE;
		if(!_nNumber)
		{
			if(!printF(szBulletGroup, _symbolFont))
				goto CleanUp;
		}
		else if(!_pPF->IsNumberSuppressed())
		{
			WCHAR szNumber[CCHMAXNUMTOSTR];
			_pPF->NumToStr(szNumber, ++_nNumber);
			if (!printF(szBeginNumberGroup, _nFont) ||
				WritePcData(szNumber, _cpg, FALSE)	||
				!printF(szEndNumberGroup))
			{
				goto CleanUp;
			}
		}
	}
	if(_fCheckInTable)
	{
		CheckInTable(TRUE);
		if(_ecParseError)
			goto CleanUp;
	}

	pwchScan = const_cast<LPWSTR>(lpcwstr);
	pwchStart = pwchScan;
	if(_CF.bCharSet == SYMBOL_CHARSET)
	{
		pwchScan += cwch;
		cwch = 0;
	}

	// Step through the Unicode buffer, weeding out characters that have  
	// known translations to RTF strings
	while(cwch-- > 0)
	{
		WCHAR	wch = *pwchScan;

		// If this is a string for which the MultiByteToUnicode conversion
		// failed, the buffer will be filled with ANSI bytes stuffed into
		// wchar's (one per).  In this case, we don't want to map trail bytes
		// to RTF strings.
		if(fIsDBCS && IsLeadByte(wch, nCodePage))
		{
#ifdef PWD_JUPITER
		   // GuyBark JupiterJ:
		   // If there is no trailing byte then that wasn't really a
		   // lead byte. It was probably an extended ansi character 
		   // which incorrectly had a FE font applied to it.
		   if(cwch > 0)
		   {
#endif // PWD_JUPITER
			    Assert(cwch);
			    cwch--;
			    pwchScan += 2;
			    continue;
#ifdef PWD_JUPITER
		   }
#endif // PWD_JUPITER
		}

		// if the char is one for which there is an appropriate RTF string
		// write the preceding chars and output the RTF string

		if(!IN_RANGE(' ', wch, 'Z') &&
		   !IN_RANGE('a', wch, 'z') &&
		   !IN_RANGE(chOptionalHyphen + 1, wch, ENSPACE - 1) &&
#ifdef PWD_JUPITER
        // GuyBark Jupiter: Handle the special character for CRLF in table cells.
		   (wch <= BULLET || wch == PWD_CRLFINCELL) &&
#else
		   wch <= BULLET &&
#endif // PWD_JUPITER
		   MapsToRTFKeywordW(wch))
		{
			if (pwchScan != pwchStart &&
				WriteTextChunk(pwchScan - pwchStart, pwchStart, nCodePage, 
									fIsDBCS))
			{
				goto CleanUp;
			}

			// map the char(s) to the RTF string
			int cwchUsed = MapToRTFKeyword(pwchScan, cwch, MAPTOKWD_UNICODE);

			cwch -= cwchUsed;
			pwchScan += cwchUsed;

			// start of next run of unprocessed chars is one past current char
			pwchStart = pwchScan + 1;

#ifdef TARGET_NT // V-GUYB: Don;t change device code at this late stage.
    		if(cwch)
            {
	    		_fCheckInTable = FALSE;
            }
#endif // TARGET_NT

		}
		pwchScan++;
	}

	// write the last chunk
	if (pwchScan != pwchStart &&
		WriteTextChunk(pwchScan - pwchStart, pwchStart, nCodePage, fIsDBCS))
	{
		goto CleanUp;
	}

CleanUp:
	return _ecParseError;
}

/*
 *	CRTFWrite::WriteTextChunk(cwch, lpcwstr, nCodePage, fIsDBCS)
 *
 *	@mfunc
 *		Write out <p cwch> chars from the Unicode text string <p lpcwstr> taking care to
 *		escape any special chars.  Unicode chars which cannot be converted to
 *		DBCS chars using the supplied codepage, <p nCodePage>, are written using the
 *		\u RTF tag.
 *
 *	@rdesc
 *		EC				The error code
 */
EC CRTFWrite::WriteTextChunk(
	LONG		cwch,					// @parm # chars in buffer
	LPCWSTR 	lpcwstr,				// @parm Pointer to text
	INT			nCodePage,				// @parm code page to use to convert to DBCS
	BOOL		fIsDBCS)				// @parm indicates whether lpcwstr is a Unicode string
										//		or a DBCS string stuffed into a WSTR
{
	// FUTURE(BradO):  There is alot of commonality b/t this routine and
	//	WritePcData.  We should re-examine these routines and consider 
	//	combining them into a common routine.

	TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::WriteTextChunk");

	BYTE 	b;
	LONG	cbAnsi;
	LONG	cbAnsiBufferSize;
	BYTE *	pbAnsiBuffer;
	BYTE *	pbAnsi;
	BOOL 	fUsedDefault = FALSE;
	BOOL	fMultiByte;
	BOOL 	fMissingCodePage = FALSE;

#ifdef PWD_JUPITER
    // GuyBark: If we're going to output J text below, then we must make
    // sure a J font is current for the text chunk. RichEdit and Word97 
    // don;t care, as they look at the unicode, but Word95 relies on the
    // MBCS equivalent of the unicode. While Word95 and Word97 always have
    // a J font selected for the run, the Word converters may not.
    BOOL    bSetJFont = FALSE;
#endif // PWD_JUPITER

	// When WideCharToMultiByte fails to convert a char, the following default
	// char is used as a placeholder in the string being converted

	// GuyBark JupiterJ 50783:
	// Originally we were passing a default character os '\0' through to 
	// WideCharToMultiByte(). But the OS code says, if the codepage is FE,
	// then the MBCS we may end up getting is either one or two bytes
	// depending on what the second byte if the default character is. But
	// we shouldn't have to care what the second byte is. If the first 
	// byte is zero (ie the low byte) then we can't have supplied a DBCS
	// character. Anyway, pass in two zero bytes here.
	const char szDBCSDefault[2] = {0, 0};

	// Allocate temp buffer for ANSI text we convert to
	cbAnsiBufferSize = cachBufferMost * (nCodePage == CP_UTF8 ? 3 : MB_LEN_MAX);
	if (!_pbAnsiBuffer)
	{
		// If the code page was CP_UTF8, it will always be CP_UTF8 for this instance
		_pbAnsiBuffer = (BYTE *)PvAlloc(cbAnsiBufferSize, GMEM_FIXED);
		if (!_pbAnsiBuffer)
			goto RAMError;
	}
	pbAnsiBuffer = _pbAnsiBuffer;

	// Convert Unicode (or fIsDBCS) buffer to ANSI 
	if(fIsDBCS)
	{
		// Supply some bogus code page which will force direct conversion
		// from wchar to bytes (losing high byte of wchar).
		// Also, don't want to use default char replacement in this case.
		cbAnsi = WCTMB(INVALID_CODEPAGE, 0, lpcwstr, cwch, 
						(char *)pbAnsiBuffer, cbAnsiBufferSize,
						NULL, NULL, NULL);
	}
	else
	{
		cbAnsi = WCTMB(nCodePage, 0, lpcwstr, cwch, 
						(char *)pbAnsiBuffer, cbAnsiBufferSize,
						szDBCSDefault, &fUsedDefault,
						&fMissingCodePage);
	}
	Assert(cbAnsi > 0);

	pbAnsi = pbAnsiBuffer;
	fMultiByte = (cbAnsi > cwch) || fIsDBCS || fMissingCodePage;

	while (!_ecParseError && cbAnsi-- > 0)
	{
		b = *pbAnsi;

		// Compare ASCII chars to their Unicode counterparts to check
		// that we're in sync
		AssertSz(cwch <= 0 || *lpcwstr > 127 || b == *lpcwstr, 
			"CRTFWrite::WriteText: Unicode and DBCS strings out of sync");

		// FUTURE(BradO):  MurrayS made a clever change to this code which
		//	caused the RTF writer to output the \uN tag for all ASCII characters
		//	greater than 0x7F.  This change was necessitated by the behaviour
		// 	of WCTMB whereby Unicode chars which should fail the conversion to ANSI
		//	are converted to some "best-match" for the codepage
		//	(ex.  alpha's convert to 'a' with cpg==1252).
		//
		//	This change was pulled out at the request of Outlook, but should
		// 	be considered for RE2.1.  This change can be found in version 75 of
		//	this file.  Note: NT 5.0 plans to introduce the flag
		//  WC_NO_BEST_FIT_CHARS, which should make our current algorithm output
		//  \uN values whenever the system cannot convert a character correctly.

		if (!IN_RANGE(' ', b, 'z') && !IN_RANGE('A', b, 'Z') &&
			MapsToRTFKeywordA(b))
		{
			int cchUsed = MapToRTFKeyword(pbAnsi, cbAnsi, MAPTOKWD_ANSI);
			cbAnsi -= cchUsed;
			pbAnsi += cchUsed;
		}
		else if(nCodePage == CP_UTF8)
		{
			PutChar(b);								// Output 1st byte in any
			if(b >= 0xC0)							//  case. At least 2-byte
			{										// At least 2-byte lead
				pbAnsi++;							//  byte, so output a
				Assert(cbAnsi && IN_RANGE(0x80, *pbAnsi, 0xBF));
				cbAnsi--;							//  trail byte
				PutChar(*pbAnsi);
				if(b >= 0xE0)						// 3-byte lead byte, so
				{									//  output another trail
					pbAnsi++;						//  byte
					Assert(cbAnsi && IN_RANGE(0x80, *pbAnsi, 0xBF));
					cbAnsi--;
					PutChar(*pbAnsi);
				}
			}
		}
		else if(fMultiByte && cbAnsi && IsLeadByte(b, nCodePage))
		{
#ifdef PWD_JUPITER
            // GuyBark: If we have the UNICODE value for the character, output it here.
            // Then follow it by the MBCS value. This allows the output RTF file to
            // be more portable later, if it's read on a system that doesn't have the
            // required code page for the MBCS.
            if(!fIsDBCS)
            {
                // If this is a lead byte, then we will try to output a DBCS value.
                // This means the UNICODE will ALWAYS be followed by 2 MBCS values.
                int cb = 2;

                // Is the current \ucN value good to use?
                if(cb != _UnicodeBytesPerChar)
                {
                    // No, so set up \uc2
            	    if(!PutCtrlWord(CWF_VAL, i_uc, cb))
                    {
                        goto CleanUp;
                    }

                    _UnicodeBytesPerChar = cb;
                }

                // Now output the unicode value.
                if(!PutCtrlWord(CWF_VAL, i_u, (int)*lpcwstr))
                {
                    goto CleanUp;
                }
            }

            // If the code page is missing, then the pbAnsi buffer was artifically
            // created to hold one byte per character. In which case we never want
            // to jump two bytes per character.
            if(!fMissingCodePage)
            {
#endif // PWD_JUPITER
		        pbAnsi++;								// Output DBCS pair
			    cbAnsi--;
#ifdef PWD_JUPITER
            }
#endif // PWD_JUPITER

			if(fIsDBCS)
			{
				lpcwstr++;
				cwch--;
			}
			printF(szEscape2CharFmt, b, *pbAnsi);
		}
		else 
		{
            // GuyBark 3/10/98 17827:
            // If the character being output is not a character from the lower character set
            // of an ansi font, then output it with the matching unicode token. Otherwise we 
            // have problems preserving characters from non-existing fonts. The
            // following test means that we will write out the unicode more often than we 
            // need too, but that just means the output rtf is pretty darn portable.

#ifdef PWD_JUPITER
            if(*lpcwstr != (WCHAR)b)
            {
                // The unicode char value is not the same as the equivalent ansi value.

                // GuyBark: 3/27/97 This is what we'd do if we're were happy always writing
                // the non-unicode representation as one byte, (ie with the \uc1 token).
                // But some unicode values we output here can only be represented as double
                // byte, so we will need to \uc2 token in this case.
/*
                if(!PutCtrlWord(CWF_VAL, i_u, ((cwch > 0) ? (int)*lpcwstr : TEXT('?'))) ||
                    !printF(szEscapeCharFmt, b))
                {
                    goto CleanUp;
                }
*/
                int  cb, nCodePageUse = nCodePage;
                BYTE sza[2] = {0};

                // If we're outputting J text here, we must make sure a J font is selected.

                // IMPORTANT: This check was originally added to make sure J text is output 
                // with a font with the J code page. This worked around a problem with the
                // Office converters, whereby J text may still the 1252 code page selected.
                // This workaround is never needed here now, as we trap this problem during
                // the stream in process instead. Keep this code here anyway in case the 
                // stream in failed to recognize the problem.

                if((_pwdDefaultJFont != -1) &&  // We have a J 

⌨️ 快捷键说明

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