I've started over again on a patch I sent in a few weeks ago. I still have not 
profiled this, for lack of time and training. This patch can be committed 
with (I believe) no effect on other code.

Since QTextDocument returns a full HTML document from its toHtml() method, I 
have used regular expressions to strip it off <html> and </html>, <body> and 
</body>, and everything between and including <head> and </head>. This leaves 
some tags like <p> and <font>, which I believe are OK to still be around. I 
could only test it on AIM, so I don't know how other protocols behave to 
different tags.

When I gave my last patch, I included constructors using QTextDocument* and 
QString for the body parameter. I was told not to do this, so this patch only 
had QString body constructors. I believe that both types of constructor can 
be useful, however, because something like ChatTextEditPart can give Message 
a QTextDocument* without ever needing to convert to QString and back again. 
However, in every other case, QString is used for the body, so it's not so 
significant.

I cleaned up the doxygen comments in the header file, but I haven't figured 
out how to generate apidox, so I don't know if the parse correctly.

I've been working on this with developer snapshot 3, and the diff is to svn 
trunk, so I hope the committer will work out what I did and what I didn't do, 
except, since I'm afraid to mess with the diff files. (see hints below)

Also, sorry there's two diff files. I couldn't use svn diff so this was the 
easiest thing next to a recursive diff.

~Charles Connell

Notes to committer

I modified my code to use the same functions as are in the svn code, but there 
are differences in implementation. Here are some details:
- I added isRightToLeft to Message::Private, but not the isRightToLeft() 
function to Message, which is already in svn, and should stay there
- I made meaningful changes to setBody(QString,...), doSetBody(QString,...), 
plainBody(), escapedBody(), parsedBody()
- I added the functions setBody (QTextDocument*,...), 
doSetBody(QTextDocument*,...), QTextDocument* body()
- The did not make changes to unescape(), makeRegExp(), parseLinks(), those 
were made by someone else and should be left as they are in svn
--- kopete-devel-svn/kopete/libkopete/kopetemessage.h	2007-04-06 20:06:22.000000000 -0400
+++ kopete-devel/kopete/libkopete/kopetemessage.h	2007-04-06 18:09:54.000000000 -0400
@@ -35,6 +35,7 @@
 
 
 class QDateTime;
+class QTextDocument;
 
 namespace Kopete {
 
@@ -79,7 +80,7 @@ public:
 	 *  show into the chatview, with Emoticons, and URLs
 	 * - Crypted is used only by Jabber and the Cryptography plugin
 	 */
-	enum MessageFormat{ PlainText = 0x01 , RichText =0x02 , ParsedHTML = 0x04|RichText , Crypted = 0x08|PlainText};
+	enum MessageFormat{ PlainText = 0x01 , RichText = 0x02 , ParsedHTML = 0x04|RichText, Crypted = 0x08|PlainText};
 
 	/**
 	 * Specifies the type of the message.
@@ -195,97 +196,111 @@ public:
 	Message & operator=( const Message &other );
 
 	/**
-	 * Accessor method for the timestamp of the message
+	 * @brief Accessor method for the timestamp of the message
 	 * @return The message's timestamp
 	 */
 	QDateTime timestamp() const;
 
 	/**
-	 * Accessor method for the Contact that sent this message
+	 * @brief Accessor method for the Contact that sent this message
 	 * @return The Contact who sent this message
 	 */
 	const Contact * from() const;
 
 	/**
-	 * Accessor method for the Contacts that this message was sent to
+	 * @brief Accessor method for the Contacts that this message was sent to
 	 * @return Pointer list of the Contacts this message was sent to
 	 */
 	QList<Contact*> to() const;
 
 	/**
-	 * @return the @ref MessageType of this message
+	 * @brief Accessor method for the message type
+	 * @return The type of the message
+	 * @see MessageType
 	 */
 	MessageType type() const;
 
 	/**
-	 * @return the view plugin you would prefer to use to read this message. If
-	 *	null, Kopete will use the user's preferred plugin.
+	 * @brief Accessor method for the preferred plugin
+	 * If null, Kopete will use the user's preferred plugin.
+	 * @return The preferred plugin
 	 */
 	QString requestedPlugin() const;
 
 	/**
-	 * Accessor method for the foreground color
+	 * @brief Accessor method for the foreground color
 	 * @return The message's foreground color
 	 */
 	QColor fg() const;
 
 	/**
-	 * Accessor method for the background color of the message
+	 * @brief Accessor method for the background color of the message
 	 * @return The message's background color
 	 */
 	QColor bg() const;
 
 	/**
-	 * Accessor method for the font of the message
+	 * @brief Accessor method for the font of the message
 	 * @return The message's font
 	 */
 	QFont font() const;
 
 	/**
-	 * Accessor method for the subject of the message
+	 * @brief Accessor method for the subject of the message
 	 * @return The message subject
 	 */
 	QString subject() const;
 
 	/**
-	 * Accessor method for the format of the message
+	 * @brief Accessor method for the body of the message
+	 * This is used internaly, to modify it make a copy of it with QTextDocument::clone()
+	 * @return The message body
+	 */
+	const QTextDocument *body() const;
+
+	/**
+	 * @brief Accessor method for the format of the message
 	 * @return The message format
 	 */
 	MessageFormat format() const;
 
 	/**
-	 * Accessor method for the direction of the message
+	 * @brief Accessor method for the direction of the message
 	 * @return The message direction
 	 */
 	MessageDirection direction() const;
 
 	/**
 	 * @brief Accessor method for the importance
+	 * @see setImportance
 	 * @return The message importance (low/normal/highlight)
 	 */
 	MessageImportance importance() const;
 
 	/**
 	 * @brief Set the importance.
-	 * @see importance
+	 * @see importance and @see MessageImportance
 	 * @param importance The message importance to set
 	 */
 	void setImportance(MessageImportance importance);
 
 	/**
-	 * Sets the foreground color for the message
+	 * @brief Sets the foreground color for the message
+	 * @see fg
 	 * @param color The color
 	 */
 	void setFg( const QColor &color );
 
 	/**
-	 * Sets the background color for the message
+	 * @brief Sets the background color for the message
+	 * @see bg
 	 * @param color The color
 	 */
 	void setBg( const QColor &color );
 
 	/**
-	 * Sets the font for the message
+	 * @brief Sets the font for the message
+	 * @see font
 	 * @param font The font
 	 */
 	void setFont( const QFont &font );
@@ -299,13 +314,21 @@ public:
 	void setBody( const QString &body, MessageFormat format = PlainText );
 
 	/**
-	 * Get the message body back as plain text
+	 * @brief Sets the body of the message
+	 *
+	 * @param body The body
+	 * @param format The format of the message, @see MessageFormat
+	 */
+	void setBody( const QTextDocument *body, MessageFormat format = PlainText );
+
+	/**
+	 * @brief Get the message body back as plain text
 	 * @return The message body as plain text
 	 */
 	QString plainBody() const;
 
 	/**
-	 * Get the message body as escaped (X)HTML format.
+	 * @brief Get the message body as escaped (X)HTML format.
 	 * That means every HTML special char (\>, \<, \&, ...) is escaped to the HTML entity (\&lt;, \&gt;, ...)
 	 * and newlines (\\n) are converted to \<br /\>
 	 * @return The message body as escaped text
@@ -313,14 +336,14 @@ public:
 	QString escapedBody() const;
 
 	/**
-	 * Get the message body as parsed HTML with Emoticons, and URL parsed
-	 * this should be ready to be shown in the chatwindow.
+	 * @brief Get the message body as parsed HTML with Emoticons, and URL parsed
+	 * This should be ready to be shown in the chatwindow.
 	 * @return The HTML and Emoticon parsed message body
 	 */
 	QString parsedBody() const;
 
 	/**
-	 * Get the related  message manager.
+	 * Get the related message manager.
 	 * If it is not set, returns 0L.
 	 *
 	 * The @ref ChatSession is only set if the message is already passed by the manager.
@@ -329,75 +352,70 @@ public:
 	 ChatSession *manager() const ;
 
 	 /**
-	  * set the messagemanager for this message.
-	  * should be only used by the manager itself
+	  * @brief Set the messagemanager for this message.
+	  * Should be only used by the manager itself. @see manager
+	  * @param manager The chat session
 	  */
-	 void setManager(ChatSession *);
+	 void setManager(ChatSession * manager);
 
 	/**
-	 * Enables the use of a background for a message
+	 * @brief Enables the use of a background for a message
+	 * @see bgOverride
 	 * @param enable A flag to indicate if the background should be enabled or disabled.
 	 */
 	void setBgOverride( bool enable );
 
 	/**
-	 * Enables the use of a foreground for a message
+	 * @brief Enables the use of a foreground for a message
+	 * @see fgOverride
 	 * @param enable A flag to indicate if the foreground should be enabled or disabled.
 	 */
 	void setFgOverride( bool enable );
 
 	/**
-	 * Enables the use of a RTF formatting for a message
+	 * @brief Enables the use of a RTF formatting for a message
+	 * @see rtfOverride
 	 * @param enable A flag to indicate if the RTF formatting should be enabled or disabled.
 	 */
 	void setRtfOverride( bool enable );
 
 	/**
-	 * Return HTML style attribute for this message.
+	 * @brief Return HTML style attribute for this message.
 	 * @return A string formatted like this: "style=attr"
 	 */
 	QString getHtmlStyleAttribute() const;
 	
 	/**
-	 * @return the list of classes
-	 * 
-	 * class are used to give different notification on a message.  But are also used in the chatwindow as html class 
+	 * @return The list of classes
+	 * Class are used to give different notification on a message. They are also used in the chatwindow as an HTML class 
 	 */
 	QStringList classes() const;
 	
 	/**
-	 * add a class
+	 * @brief Add a class
 	 * @see classes
+	 * @param class class to add
 	 */
 	void addClass(const QString& classe);
 	
 	/**
-	 * set the classes
+	 * @brief Set the classes
 	 * @see classes
+	 * @param classes The new classes
 	 */
 	void setClasses(const QStringList &classes);
 
 public:  /* static helpers */
 
 	/**
-	* Unescapes a string, removing XML entity references and returns a plain text.
-	*
-	* Note that this method is *VERY* expensive when called on rich text bodies,
-	* use with care!
-	*
+	* Unescapes a string, removing XML entity references
 	* @param xml The string you want to unescape
+	* @return The escaped string
 	*/
 	static QString unescape( const QString &xml );
 
 	/**
-	 * Indicate whether the string is right-to-left (Arabic or Hebrew are bidi locales)
-	 * or "normal" left-to-right. Calculating RTL on rich text is expensive, and
-	 * isRightToLeft() therefore uses a cached value.
-	 */
-	bool isRightToLeft() const;
-
-	/**
-	 * @brief Transform a pleintext message to an html.
+	 * @brief Transform a plaintext message into HTML.
 	 * it escape main entity like &gt; &lt; add some &lt;br /&gt; or &amp;nbsp;
 	 */
 	static QString escape( const QString & );
@@ -412,20 +430,34 @@ public:  /* static helpers */
 	 * @param success Optional pointer to a bool you want updated on success. "Success"
 	 *	is defined as a successful decoding using either UTF8 or the codec you
 	 *	provided. If a guess has to be taken, success will be false.
+	 * @return The decoded string
+
 	 */
 	static QString decodeString( const QByteArray &message,
  		const QTextCodec *providedCodec = 0L, bool *success = 0L );
 
 private:
+	class Private;
+	QSharedDataPointer<Private> d;
+
 	/**
 	 * Called internally by @ref setBody() and the constructor
 	 * Basically @ref setBody() without detach
+	 * @internal
 	 */
 	void doSetBody( const QString &body, MessageFormat format = PlainText );
 
-	class Private;
-	QSharedDataPointer<Private> d;
+	/**
+	 * Called internally by @ref setBody() and the constructor
+	 * Basically @ref setBody() without detach
+	 * @internal
+	 */
+	void doSetBody (const QTextDocument *body, MessageFormat format = PlainText);
 
+	/**
+	 * Called internally in rich text handling
+	 * @internal
+	 */
 	static QString parseLinks( const QString &message, MessageFormat format );
 };
 
--- kopete-devel-svn/kopete/libkopete/kopetemessage.cpp	2007-04-06 20:06:21.000000000 -0400
+++ kopete-devel/kopete/libkopete/kopetemessage.cpp	2007-04-07 10:17:59.000000000 -0400
@@ -27,7 +27,6 @@
 #include <QByteArray>
 #include <QSharedData>
 #include <QPointer>
-#include <QtCore/QLatin1String>
 
 #include <kdebug.h>
 #include <klocale.h>
@@ -53,6 +52,8 @@ public:
 	Private( const QDateTime &timeStamp, const Contact *from, const ContactPtrList &to,
 	         const QString &subject, MessageDirection direction,
 	         const QString &requestedPlugin, MessageType type );
+	Private (const Private &other);
+	~Private ();
 
 	QPointer<Contact> from;
 	ContactPtrList to;
@@ -73,31 +74,61 @@ public:
 
 	QColor fgColor;
 	QColor bgColor;
-	QString body;
+	QPointer<QTextDocument> body;
 	QString subject;
 };
 
 Message::Private::Private( const QDateTime &timeStamp, const Contact *from,
 		const ContactPtrList &to, const QString &subject,
 		MessageDirection direction, const QString &requestedPlugin, MessageType type )
-: from( const_cast<Contact*>(from) ), to( to ), manager( 0 ), direction( direction ), format( PlainText ), type( type ),
-	requestedPlugin( requestedPlugin ), importance( (to.count() <= 1) ? Normal : Low ),
-	bgOverride( false ), fgOverride( false ), rtfOverride( false ), isRightToLeft( false ),
-	timeStamp( timeStamp ), body( QString::null ), subject( subject )
+	: from( const_cast<Contact*>(from) ), to(to), manager(0), direction(direction), format(PlainText), type(type)
+	, requestedPlugin(requestedPlugin), importance( (to.count() <= 1) ? Normal : Low ), bgOverride(false), fgOverride(false)
+	, rtfOverride(false), timeStamp(timeStamp), body(new QTextDocument()), subject(subject)
 {
 }
 
+Message::Private::Private (const Message::Private &other)
+	: QSharedData (other)
+{
+	body = other.body->clone();
+	from = other.from;
+	to = other.to;
+	manager = other.manager;
+
+	direction = other.direction;
+	format = other.format;
+	type = other.type;
+	requestedPlugin = other.requestedPlugin;
+	importance = other.importance;
+	bgOverride = other.bgOverride;
+	fgOverride = other.fgOverride;
+	rtfOverride = other.rtfOverride;
+	isRightToLeft = other.isRightToLeft;
+	timeStamp = other.timeStamp;
+	font = other.font;
+	classes = other.classes;
+
+	fgColor = other.fgColor;
+	bgColor = other.bgColor;
+	subject = other.subject;
+}
+
+Message::Private::~Private ()
+{
+	delete body;
+}
+
 Message::Message()
-: d( new Private( QDateTime::currentDateTime(), 0L, ContactPtrList(), QString(), Internal,
-	QString(), TypeNormal ) )
+    : d( new Private( QDateTime::currentDateTime(), 0L, ContactPtrList(), QString(), Internal,
+	QString::null, TypeNormal ) )
 {
 }
 
 Message::Message( const Contact *fromKC, const QList<Contact*> &toKC, const QString &body,
 		  MessageDirection direction, MessageFormat f, const QString &requestedPlugin, MessageType type )
-: d( new Private( QDateTime::currentDateTime(), fromKC, toKC, QString::null, direction, requestedPlugin, type ) )
+    : d( new Private( QDateTime::currentDateTime(), fromKC, toKC, QString::null, direction, requestedPlugin, type ) )
 {
-	doSetBody( body, f );
+	doSetBody(body, f);
 }
 
 Message::Message( const Contact *fromKC, const Contact *toKC, const QString &body,
@@ -106,21 +137,21 @@ Message::Message( const Contact *fromKC,
 	QList<Contact*> to;
 	to.append((Kopete::Contact*)toKC);
 	d = new Private( QDateTime::currentDateTime(), fromKC, to, QString::null, direction, requestedPlugin, type );
-	doSetBody( body, f );
+	doSetBody(body, f);
 }
 
 Message::Message( const Contact *fromKC, const QList<Contact*> &toKC, const QString &body,
 		  const QString &subject, MessageDirection direction, MessageFormat f, const QString &requestedPlugin, MessageType type )
     : d( new Private( QDateTime::currentDateTime(), fromKC, toKC, subject, direction, requestedPlugin, type ) )
 {
-	doSetBody( body, f );
+	doSetBody(body, f);
 }
 
 Message::Message( const QDateTime &timeStamp, const Contact *fromKC, const QList<Contact*> &toKC,
 		  const QString &body, MessageDirection direction, MessageFormat f, const QString &requestedPlugin, MessageType type )
     : d( new Private( timeStamp, fromKC, toKC, QString::null, direction, requestedPlugin, type ) )
 {
-	doSetBody( body, f );
+	doSetBody(body, f);
 }
 
 
@@ -128,7 +159,7 @@ Message::Message( const QDateTime &timeS
 		  const QString &body, const QString &subject, MessageDirection direction, MessageFormat f, const QString &requestedPlugin, MessageType type )
     : d( new Private( timeStamp, fromKC, toKC, subject, direction, requestedPlugin, type ) )
 {
-	doSetBody( body, f );
+	doSetBody(body, f);
 }
 
 Message::Message( const Message &other )
@@ -178,50 +209,37 @@ void Message::setFont( const QFont &font
 	d->font = font;
 }
 
-void Message::doSetBody( const QString &_body, Message::MessageFormat f )
+void Message::setBody( const QString &body, MessageFormat f )
 {
-	QString body = _body;
-	//TODO: move that in ChatTextEditPart::contents
-	if( f == RichText )
-	{
-		//This is coming from the RichTextEditor component.
-		//Strip off the containing HTML document
-		body.replace( QRegExp( QLatin1String(".*<body[^>]*>(.*)</body>.*") ), QLatin1String("\\1") );
-
-		//Strip <p> tags
-		body.replace( QLatin1String("<p>"), QString() );
-
-		//Replace </p> with a <br/>
-		body.replace( QLatin1String("</p>"), QLatin1String("<br/>") );
-
-		//Remove trailing </br>
-		if ( body.endsWith( QLatin1String("<br/>") ) )
-			body.truncate( body.length() - 5 );
-	
-		body.remove( QLatin1String("\n") );
-		body.replace( QRegExp( QLatin1String( "\\s\\s" ) ), QLatin1String( " &nbsp;" ) );
-	}
-	/*
-	else if( f == ParsedHTML )
-	{
-		kWarning( 14000 ) << k_funcinfo << "using ParsedHTML which is internal !   message: " << body << kdBacktrace() << endl;
-	}*/
+	doSetBody (body, f);
+}
 
-	d->body = body;
+void Message::doSetBody (const QString &body, MessageFormat f)
+{
+	if (f == PlainText)
+		d->body->setPlainText(body);
+	else {
+		/*if( f == ParsedHTML )
+		{
+			kWarning( 14000 ) << k_funcinfo << "using ParsedHTML which is internal !   message: " << body << kdBacktrace() << endl;
+		}*/
+		d->body->setHtml(body);
+	}
 	d->format = f;
-
-	// unescaping is very expensive, do it only once and cache the result
-	d->isRightToLeft = ( f & RichText ? unescape( d->body ).isRightToLeft() : d->body.isRightToLeft() );
+	d->isRightToLeft = d->body->toPlainText().isRightToLeft();
 }
 
-void Message::setBody( const QString &body, MessageFormat f )
+void Message::setBody (const QTextDocument *_body, MessageFormat f)
 {
-	doSetBody( body, f );
+	doSetBody (_body, f);
 }
 
-bool Message::isRightToLeft() const
+void Message::doSetBody (const QTextDocument *body, MessageFormat f)
 {
-	return d->isRightToLeft;
+	delete d->body;
+	d->body = body->clone();          // delete the old body and replace it with a *copy* of the new one
+	d->format = f;
+	d->isRightToLeft = d->body->toPlainText().isRightToLeft();
 }
 
 void Message::setImportance(Message::MessageImportance i)
@@ -233,63 +251,21 @@ QString Message::unescape( const QString
 {
 	QString data = xml;
 
-	// Remove linebreak and multiple spaces. First return nbsp's to normal spaces :)
-	data = data.simplified();
+	//remove linebreak and multiple spaces
+	data.replace( QRegExp( QLatin1String( "\\s*[\n\r\t]+\\s*" ), Qt::CaseInsensitive ), QLatin1String(" " )) ;
 
-	int pos;
-	while ( ( pos = data.indexOf( '<' ) ) != -1 )
-	{
-		int endPos = data.indexOf( '>', pos + 1 );
-		if( endPos == -1 )
-			break;    // No more complete elements left
-
-		// Take the part between < and >, and extract the element name from that
-		int matchWidth = endPos - pos + 1;
-		QString match = data.mid( pos + 1, matchWidth - 2 ).simplified();
-		int elemEndPos = match.indexOf( ' ' );
-		QString elem = ( elemEndPos == -1 ? match.toLower() : match.left( elemEndPos ).toLower() );
-		if ( elem == QLatin1String( "img" ) )
-		{
-			// Replace smileys with their original text'
-			const QString attrTitle  = QLatin1String( "title=\"" );
-			int titlePos    = match.indexOf( attrTitle, elemEndPos );
-			int titleEndPos = match.indexOf( '"',       titlePos + attrTitle.length() );
-			if( titlePos == -1 || titleEndPos == -1 )
-			{
-				// Not a smiley but a normal <img>
-				// Don't update pos, we restart at this position :)
-				data.remove( pos, matchWidth );
-			}
-			else
-			{
-				QString orig = match.mid( titlePos + attrTitle.length(),
-					titleEndPos - titlePos - attrTitle.length() );
-				data.replace( pos, matchWidth, orig );
-				pos += orig.length();
-			}
-		}
-		else if ( elem == QLatin1String( "/p" ) || elem == QLatin1String( "/div" ) ||
-			elem == QLatin1String( "br" ) )
-		{
-			// Replace paragraph, div and line breaks with a newline
-			data.replace( pos, matchWidth, '\n' );
-			pos++;
-		}
-		else
-		{
-			// Remove all other elements entirely
-			// Don't update pos, we restart at this position :)
-			data.remove( pos, matchWidth );
-		}
-	}
+	data.replace( QRegExp( QLatin1String( "< *img[^>]*title=\"([^>\"]*)\"[^>]*>" ), Qt::CaseInsensitive ), QLatin1String( "\\1" ) );  //escape smeleys, return to the original code
+	data.replace( QRegExp( QLatin1String( "< */ *p[^>]*>" ), Qt::CaseInsensitive ), QLatin1String( "\n" ) );
+	data.replace( QRegExp( QLatin1String( "< */ *div[^>]*>" ), Qt::CaseInsensitive ), QLatin1String( "\n" ) );
+	data.replace( QRegExp( QLatin1String( "< *br */? *>" ), Qt::CaseInsensitive ), QLatin1String( "\n" ) );
+	data.replace( QRegExp( QLatin1String( "<[^>]*>" ) ), QString::null );
 
-	// Replace stuff starting with '&'
 	data.replace( QLatin1String( "&gt;" ), QLatin1String( ">" ) );
 	data.replace( QLatin1String( "&lt;" ), QLatin1String( "<" ) );
 	data.replace( QLatin1String( "&quot;" ), QLatin1String( "\"" ) );
 	data.replace( QLatin1String( "&nbsp;" ), QLatin1String( " " ) );
 	data.replace( QLatin1String( "&amp;" ), QLatin1String( "&" ) );
-	data.replace( QLatin1String( "&#160;" ), QLatin1String( " " ) );  //this one is used in jabber:  note, we should escape all &#xx;
+	data.replace( QString::fromLatin1( "&#160;" ), QString::fromLatin1( " " ) );  //this one is used in jabber:  note, we should escape all &#xx;
 
 	return data;
 }
@@ -309,61 +285,47 @@ QString Message::escape( const QString &
 	return html;
 }
 
-
-
 QString Message::plainBody() const
 {
-	QString body=d->body;
-	if( d->format & RichText )
-	{
-		body = unescape( body );
-	}
-	return body;
+	return d->body->toPlainText();
 }
 
 QString Message::escapedBody() const
 {
-	QString escapedBody=d->body;
-//	kDebug(14000) << k_funcinfo << escapedBody << " " << d->rtfOverride << endl;
-
-	if( d->format & PlainText )
-	{
-		escapedBody=escape( escapedBody );
-	}
-	else if( d->format & RichText && d->rtfOverride)
-	{
-		//remove the rich text
-		escapedBody = escape (unescape( escapedBody ) );
-	}
-
-	return escapedBody;
+//	kDebug(14010) << k_funcinfo << escapedBody() << " " << d->rtfOverride << endl;
+	QString html = d->body->toHtml();
+//	all this regex business is to take off the outer HTML document provided by QTextDocument
+//	remove the head
+	QRegExp badStuff ("<head[^<>]*>.*</head[^<>]*>");
+	html = html.remove (badStuff);
+//	remove the <html> and </html> tags
+	badStuff.setPattern ("</?html[^<>]*>");
+	html = html.remove (badStuff);
+//	remove the <body> and </body> tags
+	badStuff.setPattern ("</?body[^<>]*>");
+	html = html.remove (badStuff);
+//	remove newlines that may be present, since they end up being displayed in the chat window. real newlines are represented with <br>, so we know \n's are meaningless (I hope this is true, could anybody confirm? (C Connell))
+	html.remove ("\n");
+	return html;
 }
 
 QString Message::parsedBody() const
 {
 	//kDebug(14000) << k_funcinfo << "messageformat: " << d->format << endl;
-
-	if( d->format == ParsedHTML )
-	{
-		return d->body;
-	}
-	else
-	{
 #ifdef __GNUC__
 #warning Disable Emoticon parsing for now, it make QString cause a ASSERT error. (DarkShock)
 #endif
 #if 0
-		return Kopete::Emoticons::parseEmoticons(parseLinks(escapedBody(), RichText));
+	return Kopete::Emoticons::parseEmoticons(parseLinks(escapedBody(), RichText));
 #endif
-		return escapedBody();
-	}
+	return escapedBody();
 }
 
 static QString makeRegExp( const char *pattern )
 {
 	const QString urlChar = QLatin1String( "\\+\\-\\w\\./#@&;:=\\?~%_,\\!\\$\\*\\(\\)" );
-	const QString boundaryStart = QString( "(^|[^%1])(" ).arg( urlChar );
-	const QString boundaryEnd = QString( ")([^%1]|$)" ).arg( urlChar );
+	const QString boundaryStart = QString::fromLatin1( "(^|[^%1])(" ).arg( urlChar );
+	const QString boundaryEnd = QString::fromLatin1( ")([^%1]|$)" ).arg( urlChar );
 
 	return boundaryStart + QLatin1String(pattern) + boundaryEnd;
 }
@@ -406,9 +368,9 @@ QString Message::parseLinks( const QStri
 
 	// common subpatterns - may not contain matching parens!
 	const QString name = QLatin1String( "[\\w\\+\\-=_\\.]+" );
-	const QString userAndPassword = QString( "(?:%1(?::%1)?\\@)" ).arg( name );
+	const QString userAndPassword = QString::fromLatin1( "(?:%1(?::%1)?\\@)" ).arg( name );
 	const QString urlChar = QLatin1String( "\\+\\-\\w\\./#@&;:=\\?~%_,\\!\\$\\*\\(\\)" );
-	const QString urlSection = QString( "[%1]+" ).arg( urlChar );
+	const QString urlSection = QString::fromLatin1( "[%1]+" ).arg( urlChar );
 	const QString domain = QLatin1String( "[\\-\\w_]+(?:\\.[\\-\\w_]+)+" );
 
 	//Replace http/https/ftp links:
@@ -482,6 +444,11 @@ QString Message::subject() const
 	return d->subject;
 }
 
+const QTextDocument *Message::body() const
+{
+	return d->body;
+}
+
 Message::MessageFormat Message::format() const
 {
 	return d->format;

Attachment: pgpS8w7VJbjHR.pgp
Description: PGP signature

_______________________________________________
kopete-devel mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/kopete-devel

Reply via email to