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

📄 rtf2htmlconverter.cpp

📁 管理项目进度工具的原代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			DWORD r=0,g=0,b=0;
			COLORREF ref=m_arrColors[lActColor];
			r=GetRValue(ref);
			g=GetGValue(ref);
			b=GetBValue(ref);
			CString strHTMLColor;
			strHTMLColor.Format("#%02x%02x%02x",r,g,b);
			m_strActFontColor = strHTMLColor;
		}
	}
	//font size
	strTestTag="fs";
	if ((pElement->m_enNodeType==CHTMLElement::c_nodInvalid)&&(strRTFTag.GetLength()>=strTestTag.GetLength())&&(strRTFTag.Left(strTestTag.GetLength())==strTestTag)) 
	{   
		pElement->m_enNodeType=CHTMLElement::c_nodHTMLBegin;
		pElement->m_strNodeText= "font";
		m_strActFontSize = strRTFTag;
		m_strActFontSize.Delete(0, strTestTag.GetLength());
		ASSERT(m_strActFontSize.GetLength()>0); //Invalid RTF
		m_strActFontSize=LongToString(StringToLong(m_strActFontSize)/2); //RTF stores the doubled font size
	}
	//font name
	strTestTag="f";  //f+number
	if ((pElement->m_enNodeType==CHTMLElement::c_nodInvalid)&&(strRTFTag.GetLength()>=strTestTag.GetLength())&&(strRTFTag.Left(strTestTag.GetLength())==strTestTag)&&(strRTFTag.Mid(1).SpanIncluding("01234567890")==strRTFTag.Mid(1))) 
	{   
		CString strActFontDsgn = strRTFTag;
		pElement->m_enNodeType=CHTMLElement::c_nodHTMLBegin;
		pElement->m_strNodeText= "font";
		ASSERT(strActFontDsgn.GetLength()>0); //Invalid RTF
		CString strActFontName;
		BOOL bFound=m_mapFontNames.Lookup(strActFontDsgn,strActFontName);
		ASSERT(bFound); //Font not found in font table, don't change font
		if (bFound) m_strActFontName=strActFontName;
	}
	
	//New font tag ?
	if ((pElement->m_enNodeType==CHTMLElement::c_nodHTMLBegin)&&(pElement->m_strNodeText=="font")) 
	{
		BOOL bMustClose=FALSE;
		//Look if we first must close paragraph
		for (int iLastElements=m_arrHTMLElements.GetSize()-1;iLastElements>=0;iLastElements--) 
		{
			CHTMLElement* pElementTest = m_arrHTMLElements[iLastElements];
			if ((pElementTest->m_enNodeType==CHTMLElement::c_nodHTMLEnd)&&(pElementTest->m_strNodeText=="font")) break; //everything is OK
			if ((pElementTest->m_enNodeType==CHTMLElement::c_nodHTMLBegin)&&(pElementTest->m_strNodeText=="font")) 
			{
				bMustClose=TRUE;
				break; //everything is OK
			}
		}
		if (bMustClose) 
		{
			//Insert Closing </p>
			CHTMLElement* pElementClose = new CHTMLElement();
			pElementClose->m_enNodeType=CHTMLElement::c_nodHTMLEnd;
			pElementClose->m_strNodeText = "font";
			m_arrHTMLElements.Add(pElementClose);
		}
		//Set font tag options
		pElement->m_mapParams.SetAt("color", "\""+m_strActFontColor+"\"");
		pElement->m_mapParams.SetAt("style", "\"font-size: "+m_strActFontSize+"pt; font-family:"+m_strActFontName+";\"");
	}
	if (pElement->m_enNodeType!=CHTMLElement::c_nodInvalid) 
		m_arrHTMLElements.Add(pElement);
	else
		delete pElement;
}

void CRTF_HTMLConverter::R2H_GetRTFTags(const CString& strRTFSource, CStringArray& arrTgt)
{
	//Go thru RTF main string
	for (int iStrPos=0;iStrPos<strRTFSource.GetLength();iStrPos++) 
	{
		CString strChTest=strRTFSource[iStrPos];
		if (strChTest=="\\") 
		{
			CString strTag=R2H_GetRTFTag(strRTFSource, iStrPos);
			arrTgt.Add(strTag);
			iStrPos+=strTag.GetLength();
			if (((iStrPos+1)<strRTFSource.GetLength())&&(strRTFSource[iStrPos+1]==' ')) iStrPos++; //Ignore Blank after Tag
		}
	} //loop thru string
}


//! Gets the created HTML elements as HTML text
void CRTF_HTMLConverter::R2H_GetHTMLElements(CString& strHTML)
{
	strHTML="";

	// remove invalid trailing elements
	int iElemCount = m_arrHTMLElements.GetSize();

	while (iElemCount--)
	{
		CHTMLElement* pElem = m_arrHTMLElements[iElemCount];

		if (pElem->m_enNodeType==CHTMLElement::c_nodHTMLEnd) 
		{
			iElemCount++; // we want this element
			break;
		}
		else if (pElem->m_enNodeType==CHTMLElement::c_nodText) 
		{
			CString sText = pElem->m_strNodeText;
			sText.TrimLeft();
			sText.TrimRight();

			if (!sText.IsEmpty() && sText != "br" && sText != "\n" && sText != "\r\n")
			{
				iElemCount++; // we want this element
				break;
			}
		}
	}

	// Loop thru what's remaining of the HTML elements
	CMap<CString, LPCTSTR, int, int> mapOpenTags;

	for (int iElem=0;iElem<iElemCount;iElem++) 
	{
		CHTMLElement* pElem = m_arrHTMLElements[iElem];
		CString sElem;

		if (pElem->m_enNodeType==CHTMLElement::c_nodHTMLBegin) 
		{
			// look ahead so that we can strip out empty tag pairs (typically 'font')
			bool bEmpty = false;

			if (iElem + 1 < m_arrHTMLElements.GetSize()) 
			{
				CHTMLElement* pElemNext = m_arrHTMLElements[iElem + 1];

				if (pElemNext->m_enNodeType==CHTMLElement::c_nodHTMLEnd &&
					pElemNext->m_strNodeText == pElem->m_strNodeText)
				{
					TRACE ("CRTF_HTMLConverter::R2H_GetHTMLElements(removing '%s')\n", pElemNext->m_strNodeText);
					bEmpty = true;
				}
			}

			if (bEmpty)
				iElem++; // remove end tag too
			else
			{
				// keep track of opentags
				int nCount = 0;

				mapOpenTags.Lookup(pElem->m_strNodeText, nCount);
				mapOpenTags[pElem->m_strNodeText] = ++nCount;

				// HTML element open tag
				sElem = "<";
				sElem += pElem->m_strNodeText;

				// HTML element parameters (<font param1="test" param2="hugo">
				POSITION pos = pElem->m_mapParams.GetStartPosition();

				while (pos) 
				{
					CString strKey, strValue;
					pElem->m_mapParams.GetNextAssoc(pos, strKey, strValue);

					sElem+= " "+strKey+" = "+strValue;
				}
				sElem+= ">";
			}
		} 
		else if (pElem->m_enNodeType==CHTMLElement::c_nodHTMLEnd)
		{
			sElem.Format("</%s>", pElem->m_strNodeText);

			// decrement open tag count
			int nCount = 0;

			mapOpenTags.Lookup(pElem->m_strNodeText, nCount);

			if (nCount > 0)
				mapOpenTags[pElem->m_strNodeText] = --nCount;
		} 
		else if (pElem->m_enNodeType==CHTMLElement::c_nodText) 
		{
			sElem = pElem->m_strNodeText;        
		} 
		else 
		{
			ASSERT(FALSE); //internal error (wrong html tag)
		}

		if (!sElem.IsEmpty())
		{
//			TRACE ("CRTF_HTMLConverter::R2H_GetHTMLElements(adding '%s')\n", sElem);
			strHTML += sElem;
		}
	}

	// any open tags remaining?
	POSITION pos = mapOpenTags.GetStartPosition();

	while (pos)
	{
		CString sTag, sClose;
		int nCount = 0;
		mapOpenTags.GetNextAssoc(pos, sTag, nCount);

		if (nCount && sTag != "br")
		{
			sClose.Format("</%s>", sTag);

			while (nCount--)
				strHTML += sClose;
		}
	}

	if (strHTML.GetLength() < 210)
		TRACE ("CRTF_HTMLConverter::R2H_GetHTMLElements(%s)\n", strHTML);
}

int CRTF_HTMLConverter::GetCodePage(const CString& sRtf)
{
	const CString CPGTAG("\\ansicpg");

	int nFind = sRtf.Find(CPGTAG);

	if (nFind != -1)
		return atoi((LPCTSTR)sRtf + (nFind + CPGTAG.GetLength()));

	return -1;
}

BOOL CRTF_HTMLConverter::HasMultiByteChars(const CString& sRtf)
{
//	return FALSE;
	const CString MULTIBYTETAG("\\'");

	return (sRtf.Find(MULTIBYTETAG) >= 0);
}

void CRTF_HTMLConverter::R2H_CreateHTMLElements(const CString& strRTFSource)
{
	//Go thru RTF main string
	CString strCurrentText;
	for (int iStrPos=0;iStrPos<strRTFSource.GetLength();iStrPos++) 
	{
		CString strChTest=strRTFSource[iStrPos];
#ifdef _DEBUG
		const char* szPos = (LPCTSTR)strRTFSource + iStrPos;
#endif

		if (strChTest=="\\") 
		{
			// check for multi-byte char
/*
			if (strRTFSource.Find(MULTIBYTETAG, iStrPos) == iStrPos)
			{
				// extract next two elements as a single wide char
				CString sLow = strRTFSource.Mid(iStrPos + 2, 2);
				CString sHigh = strRTFSource.Mid(iStrPos + 6, 2);

				wchar_t wChar = (WORD)strtol(sHigh + sLow, NULL, 16);
				CString sChar = Misc::WideToMultiByte(wChar);

				strCurrentText += sChar;

				iStrPos += 7;
				continue;
			}
*/

			//New tag
			if (strCurrentText!="") 
			{
				CHTMLElement* pElement = new CHTMLElement();
				pElement->m_enNodeType=CHTMLElement::c_nodText;
				pElement->m_strNodeText = strCurrentText;
				m_arrHTMLElements.Add(pElement);
				strCurrentText="";
			}
			CString strTag=R2H_GetRTFTag(strRTFSource, iStrPos);
			R2H_InterpretTag(strTag);         
			iStrPos+=strTag.GetLength();
			if (((iStrPos+1)<strRTFSource.GetLength())&&(strRTFSource[iStrPos+1]==' ')) 
				iStrPos++; //Ignore Blank after Tag
		} 
		else if (strChTest=="\n" || strChTest=="\r")
		{
			// line endings
			strCurrentText+=strChTest;
		}
		else
		{
			//Normal character
			strCurrentText+=CHtmlCharMap::ConvertToRep(strChTest);
		}
	} //loop thru string
	
	//Add last text
	if (strCurrentText!="") 
	{
		CHTMLElement* pElement = new CHTMLElement();
		pElement->m_enNodeType=CHTMLElement::c_nodText;
		pElement->m_strNodeText = strCurrentText;
		m_arrHTMLElements.Add(pElement);
		strCurrentText="";
	}
}

CRTF_HTMLConverter::CRTFNode CRTF_HTMLConverter::R2H_BuildTree(const CString& strSource, CRTFNode* pNodeParent)
{
	//Initializing   
	CString strName;
	
	//Extract Node's Name
	if ((strSource.GetLength()>2)&&(strSource[0]=='{')&&(strSource[1]=='\\')) 
	{
		for (int iStrPos=2;iStrPos<strSource.GetLength();iStrPos++) 
		{
			CString strChTest=strSource[iStrPos];
			if (strChTest.SpanIncluding(" {}\\\r")!="") 
			{
				break;
			} 
			else 
			{
				strName+=strChTest;
			}
		}
	} 
	else 
	{
		//Invalid RTF Node. RTF Nodes must start with a { and then contain a \NAME identifier
		ASSERT(FALSE);
		return CRTFNode();
	}
	
	//Extract pure text
	CString strNodeText=strSource;
	strNodeText.Delete(0,1);
	strNodeText.Delete(strNodeText.GetLength()-1, 1);
	
	//Add node into tree
	CRTFNodeA nodeA;
	nodeA.m_strCode = strSource;
	nodeA.m_strName = strName;
	CRTFNode nodeThis;
	if (pNodeParent) 
	{
		nodeThis = pNodeParent->AddNode(nodeA);      
	} 
	else 
	{
		nodeThis = m_RTFTree->AddNode(nodeA);
	} 
	
	//Looking for children
	CString strNodeNew; 
	CString strThisCode;
	long lLevel=0; //# Of opened '{'
	int iStrPos;

	for (iStrPos=0;iStrPos<strNodeText.GetLength();iStrPos++) 
	{
		CString strChTest=strNodeText[iStrPos];
		if (strChTest=="{") 
		{
			//New element
			if (lLevel==0) 
			{
				strNodeNew="";
			} 
			// else Nested Element, will be added during recurse

			lLevel++;
		}

		if (lLevel>0) 
		{ 
			strNodeNew+=strChTest;
		} 
		else 
		{
			strThisCode+=strChTest;
		}
		if (strChTest=="}") 
		{
			ASSERT(lLevel>0); //Invalid RTF, more closing } than opening 磠
			lLevel--;
			if (lLevel==0) 
			{
				//Recurse (new Sub-Node (child) ready
				R2H_BuildTree(strNodeNew,&nodeThis);
			}  
			// else Nested Element, will be added during recurse
		}
	} //loop thru string
	ASSERT(lLevel==0); //Invalid RTF, more opening { than closing }
	
	//Get the plain text (without \)
	CString strPlain;
	for (iStrPos=0;iStrPos<strNodeText.GetLength();iStrPos++) 
	{
		CString strChTest=strNodeText[iStrPos];
		if (strChTest=="\\") 
		{
			CString strTag=R2H_GetRTFTag(strNodeText, iStrPos);
			iStrPos+=strTag.GetLength();
			if (((iStrPos+1)<strNodeText.GetLength())&&(strNodeText[iStrPos+1]==' ')) 
				iStrPos++; //Ignore Blank after Tag
		} 
		else 
		{
			strPlain+=strChTest;
		}
	} //loop thru string
	
	nodeThis->m_strPlain=strPlain;
	nodeThis->m_strThisCode = strThisCode;
	return nodeThis;
}

CString& operator<< ( CString& os, CRTF_HTMLConverter& conv )
{
	//For streaming operations
	if (conv.m_enMode==CRTF_HTMLConverter::c_modRTF2HTML) 
	{
		os = conv.m_strHTML;
	} 
	else 
	{
		os = conv.m_strHTML;
	}
	return os;
}

CString& operator>> ( CString& is, CRTF_HTMLConverter& conv )
{
	//For streaming operations
	CString strTemp;
	strTemp = is;
	//RTF->HTML
	if (conv.m_enMode==CRTF_HTMLConverter::c_modRTF2HTML) 
	{
		conv.m_strRTF = strTemp;
		conv.ConvertRTF2HTML(TRUE);
	}
	return is;
}

CRTF_HTMLConverter::CHTMLElement::CHTMLElement(THTMLNodeType type, LPCTSTR szText)
	: m_enNodeType(type), m_strNodeText(szText)
{
}

⌨️ 快捷键说明

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