Click here to Skip to main content
15,896,557 members
Articles / Programming Languages / C#

NRTFTree - A class library for RTF processing in C#

Rate me:
Please Sign up or sign in to vote.
4.50/5 (42 votes)
7 Sep 2007LGPL33 min read 480K   22.4K   161  
Class library to manage RTF files.
using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using Net.Sgoliver.NRtfTree;

namespace Pruebas
{
	#region Clases Auxiliares y Enumeraciones

	/*****************************************************************************
	 * Clase:		EstadoRtf
	 * Autor:		Sgoliver
	 * Fecha:		13/03/2005
	 * Descripci�n: 
	 * ***************************************************************************/
	public class EstadoRtf
	{
		public bool negrita;		//Fuente negrita
		public bool cursiva;		//Fuente cursiva
		public bool subrayado;		//Fuente subrayada

		public string fuente;		//Tipo de fuente
		public int tamFuente;		//Tama�o de fuente
		public Color color;			//Color de fuente

		public EstadoRtf(string fue, int tam, Color col, bool neg, bool cur, bool sub)
		{
			fuente = fue;
			tamFuente = tam;
			color = col;

			negrita   = neg;
			cursiva   = cur;
			subrayado = sub;
		}
	}

	#endregion


	public class TraductorRtf
	{
		#region Atributos privados

		private RtfTree		tree;			//Analizador para el documento RTF

		private ArrayList	tFuentes;		//Tabla de fuentes  (array de string)
		private ArrayList	tColores;		//Tabla de colores  (array de Color)

		private ArrayList	estados;		//Pila de estados del documento  (array de EstadoRtf)
		private EstadoRtf	estadoActual;	//Estado flujo RTF actual

		#endregion

		#region Constructores

		public TraductorRtf(string rutaRTF)
		{
			tFuentes = new ArrayList(100);
			tColores = new ArrayList(100);

			estados = new ArrayList();

			tree = new RtfTree();

			tree.LoadRtfFile(rutaRTF);
		}

		#endregion

		#region M�todos P�blicos

		public string traducir()
		{
			string res = "";

			tFuentes = extraerFuentes();

			tColores = extraerColores();

			res = traducirTexto();

			return res;
		}

		public string traducirTexto()
		{
			string res = "<html><head></head><body>";

			//Se establece el estado inicial por defecto
			estadoActual = new EstadoRtf((string)tFuentes[0],10,(Color)tColores[0],false,false,false);

			//Fuente por defecto
			res += "<font face='" + estadoActual.fuente + "' size='" + estadoActual.tamFuente + "' color='" + toHTMLColor(estadoActual.color) + "'>";

			//Se busca el indice del primer nodo perteneciente al texto
			bool grupoEnc = false;	//Encontrado alg�n grupo
			bool enc = false;		//Encontrado el comienzo del texto
			int i = 0;

			RtfTreeNode nodo = new RtfTreeNode();

			while(!enc && i < tree.RootNode.FirstChild.ChildNodes.Count)
			{
				nodo = tree.RootNode.FirstChild.ChildNodes[i];

				if(!grupoEnc)
				{
					if(nodo.NodeType == RTF_NODE_TYPE.GROUP)
						grupoEnc = true;
				}
				else  //grupoEnc == true
				{
					if(nodo.NodeType != RTF_NODE_TYPE.GROUP)
						enc = true;
				}

				i++;
			}

			int primerNodoTexto = i - 1;

			//Inmersion
			res += traducirTexto(tree.RootNode.FirstChild, primerNodoTexto);

			res += "</font></body></html>";

			return res;
		}

		public string traducirTexto(RtfTreeNode curNode, int prim)
		{
			string res = "";

			//Grupo actual
			RtfTreeNode nprin = curNode;

			RtfTreeNode nodo = new RtfTreeNode();

			for(int i = prim; i < nprin.ChildNodes.Count; i++)
			{
				nodo = nprin.ChildNodes[i];

				if(nodo.NodeType == RTF_NODE_TYPE.GROUP)
				{
					//Se apila el estado actual
					estados.Add(estadoActual);

					//Se crea un nueo estado inicial
					estadoActual = new EstadoRtf((string)tFuentes[0],10,(Color)tColores[0],false,false,false);	

					res += traducirTexto(nodo,0);

					//Se desapila el estado anterior
					estadoActual = (EstadoRtf)estados[estados.Count-1];
					estados.RemoveAt(estados.Count-1);
				}
				else if(nodo.NodeType == RTF_NODE_TYPE.CONTROL)
				{
					if(nodo.NodeKey == "'")
					{
						res += inicioFormato();
						res += (char)nodo.Parameter;
						res += finFormato();
					}
				}
				else if(nodo.NodeType == RTF_NODE_TYPE.KEYWORD)
				{
					switch(nodo.NodeKey)
					{
						case "f":  //Tipo de fuente
							estadoActual.fuente = (string)tFuentes[nodo.Parameter];
							break;
						case "cf":  //Color de fuente
							estadoActual.color = (Color)tColores[nodo.Parameter];
							break;
						case "fs":	//Tama�o de fuente
							estadoActual.tamFuente = nodo.Parameter;
							break;
						case "b":	//Negrita
							if(!nodo.HasParameter || nodo.Parameter == 1) 
								estadoActual.negrita = true;
							else
								estadoActual.negrita = false;
							break;
						case "i":	//Cursiva
							if(!nodo.HasParameter || nodo.Parameter == 1) 
								estadoActual.cursiva = true;
							else
								estadoActual.cursiva = false;
							break;
						case "ul":	//Subrayado ON
							estadoActual.subrayado = true;
							break;
						case "ulnone":	//Subrayado OFF
							estadoActual.subrayado = false;
							break;
						case "par":	//Nuevo p�rrafo
							res += "<br>";
							break;
					}
				}
				else if(nodo.NodeType == RTF_NODE_TYPE.TEXT)
				{
					res += inicioFormato();
					res += nodo.NodeKey;
					res += finFormato();
				}
			}

			return res;
		}

		public string inicioFormato()
		{
			string res = "";

			//Fuente (tipo, tama�o y color)
			res += "<font face='" + estadoActual.fuente + "' size='" + estadoActual.tamFuente/8 + "' color='" + toHTMLColor(estadoActual.color) + "'>";

			//Negrita, Cursiva, Subrayado
			if(estadoActual.negrita)
				res += "<b>";

			if(estadoActual.cursiva)
				res += "<i>";

			if(estadoActual.subrayado)
				res += "<u>";

			return res;
		}

		public string finFormato()
		{
			string res = "";

			//Negrita, Cursiva, Subrayado
			if(estadoActual.negrita)
				res += "</b>";

			if(estadoActual.cursiva)
				res += "</i>";

			if(estadoActual.subrayado)
				res += "</u>";

			//Fuente
			res += "</font>";

			return res;
		}

		public string toHTMLColor(Color actColor)
		{
			return "#"+intToHex(actColor.R,2)+intToHex(actColor.G,2)+intToHex(actColor.B,2);
		}

		public string intToHex(int hexint)
		{
			int counter,reminder;
			string hexstr;

			counter=1;
			hexstr="";

			while (hexint+15>Math.Pow(16,counter-1))
			{
				reminder=(int)(hexint%Math.Pow(16,counter));
				reminder=(int)(reminder/Math.Pow(16,counter-1));

				if (reminder<=9)
				{
					hexstr=hexstr+(char)(reminder+48);
				}
				else
				{
					hexstr=hexstr+(char)(reminder+55);
				}

				hexint-=reminder;
				counter++;
			}

			return ReverseString(hexstr);
		}

		public String ReverseString(String inStr)
		{
			string outStr;
			int counter;
			outStr="";

			for (counter=inStr.Length-1;counter>=0;counter--)
			{
				outStr=outStr+inStr[counter];
			}

			return outStr;
		}

		public String intToHex(int hexint,int length)
		{
			string hexstr,ret;
			int counter;

			hexstr=intToHex(hexint);
			ret="";

			if (hexstr.Length<length)
			{
				for (counter=0;counter<(length-hexstr.Length);counter++)
				{
					ret=ret+"0";
				}
			}

			return ret+hexstr;
		}


		public ArrayList extraerFuentes()
		{
			ArrayList tabla = new ArrayList();

			//Nodo raiz del documento
			RtfTreeNode root = tree.RootNode;

			//Grupo principal del documento
			RtfTreeNode nprin = root.FirstChild;  

			//Buscamos la tabla de fuentes en el �rbol
			bool enc = false;
			int i = 0;
			RtfTreeNode ntf = new RtfTreeNode();  //Nodo con la tabla de fuentes

			while(!enc && i < nprin.ChildNodes.Count)
			{
				if(nprin.ChildNodes[i].NodeType == RTF_NODE_TYPE.GROUP &&
				   nprin.ChildNodes[i].FirstChild.NodeKey == "fonttbl" )
				{
					enc = true;
					ntf = nprin.ChildNodes[i];
				}

				i++;
			}

			//Rellenamos el array de fuentes
			for(int j=1; j < ntf.ChildNodes.Count; j++)
			{
				RtfTreeNode fuente = ntf.ChildNodes[j];

				string nombreFuente = null;

				foreach(RtfTreeNode nodo in fuente.ChildNodes)
				{
					if(nodo.NodeType == RTF_NODE_TYPE.TEXT)
						nombreFuente = nodo.NodeKey.Substring(0,nodo.NodeKey.Length-1);
				}

				tabla.Add(nombreFuente);
			}

			return tabla;
		}

		public ArrayList extraerColores()
		{
			ArrayList tabla = new ArrayList();

			//Nodo raiz del documento
			RtfTreeNode root = tree.RootNode;

			//Grupo principal del documento
			RtfTreeNode nprin = root.FirstChild;  

			//Buscamos la tabla de colores en el �rbol
			bool enc = false;
			int i = 0;
			RtfTreeNode ntc = new RtfTreeNode();  //Nodo con la tabla de fuentes

			while(!enc && i < nprin.ChildNodes.Count)
			{
				if(nprin.ChildNodes[i].NodeType == RTF_NODE_TYPE.GROUP &&
					nprin.ChildNodes[i].FirstChild.NodeKey == "colortbl" )
				{
					enc = true;
					ntc = nprin.ChildNodes[i];
				}

				i++;
			}

			//Rellenamos el array de colores
			int rojo = 0;
			int verde = 0;
			int azul = 0;

			for(int j=1; j < ntc.ChildNodes.Count; j++)
			{
				RtfTreeNode nodo = ntc.ChildNodes[j];

				if(nodo.NodeType == RTF_NODE_TYPE.TEXT && nodo.NodeKey == ";")
				{
					tabla.Add(Color.FromArgb(rojo,verde,azul));

					rojo = 0;
					verde = 0;
					azul = 0;
				}
				else if(nodo.NodeType == RTF_NODE_TYPE.KEYWORD)
				{
					switch(nodo.NodeKey)
					{
						case "red":
							rojo = nodo.Parameter;
							break;
						case "green":
							verde = nodo.Parameter;
							break;
						case "blue":
							azul = nodo.Parameter;
							break;
					}
				}
			}

			return tabla;
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Web Developer
Spain Spain
Currently, i work for a great consulting company as a software developer.

My homepage is:
http://www.sgoliver.net

Comments and Discussions