You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
8.0 KiB
345 lines
8.0 KiB
/*
|
|
This file is part of the KDE project
|
|
Copyright (C) 2001 Ewald Snel <ewald@rambo.its.tudelft.nl>
|
|
Copyright (C) 2001 Tomasz Grobelny <grotk@poczta.onet.pl>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <tqdatetime.h>
|
|
#include <tqtextcodec.h>
|
|
#include <tqcolor.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include "rtfimport_dom.h"
|
|
|
|
/**
|
|
* Escape the special XML characters and be careful to catch any unallowed control character
|
|
*/
|
|
TQString CheckAndEscapeXmlText(const TQString& strText)
|
|
{
|
|
TQString strReturn(strText);
|
|
TQChar ch;
|
|
|
|
for (uint i=0; i<strReturn.length(); i++)
|
|
{
|
|
ch = strReturn[i];
|
|
const int test = ch.unicode();
|
|
|
|
// The i+= is for the additional characters
|
|
if (test == 38) { strReturn.replace(i, 1, "&"); i+=4; } // &
|
|
else if (test == 60) { strReturn.replace(i, 1, "<"); i+=3; } // <
|
|
else if (test == 62) { strReturn.replace(i, 1, ">"); i+=3; } // >
|
|
else if (test == 34) { strReturn.replace(i, 1, """); i+=5; } // "
|
|
else if (test == 39) { strReturn.replace(i, 1, "'"); i+=5; } // '
|
|
else if (test >= 32) continue; // Normal character (from space on)
|
|
else if ((test == 9) || (test == 10) || (test == 13) ) continue; // Allowed control characters: TAB, LF, CR
|
|
else
|
|
{
|
|
// An unallowed control character:
|
|
// - could be a bug in the RTF file
|
|
// - could be not supported encoding.
|
|
// In any case, we must replace this character.
|
|
kdDebug(30515) << "Control character in XML stream: " << test << endl;
|
|
strReturn.replace(i, 1, '?'); // Replacement character
|
|
}
|
|
}
|
|
|
|
return strReturn;
|
|
}
|
|
|
|
|
|
DomNode::DomNode()
|
|
{
|
|
clear(0);
|
|
}
|
|
|
|
/**
|
|
* Creates a new document.
|
|
* @param doctype the document type (tag)
|
|
*/
|
|
DomNode::DomNode( const char *doctype )
|
|
{
|
|
documentLevel = 1;
|
|
hasChildren = false;
|
|
hasAttributes = false;
|
|
str += "<?xml version = '1.0' encoding = 'UTF-8'?><!DOCTYPE " ;
|
|
str += doctype;
|
|
str += " >\n<";
|
|
str += doctype;
|
|
}
|
|
|
|
/**
|
|
* Creates a new document node (no memory allocation).
|
|
* @param level the document depth of the node
|
|
*/
|
|
void DomNode::clear( int level )
|
|
{
|
|
str = TQString();
|
|
documentLevel = level;
|
|
hasChildren = true;
|
|
hasAttributes = false;
|
|
}
|
|
|
|
/**
|
|
* Adds a new node.
|
|
* @param name the name of the new node (tag)
|
|
*/
|
|
void DomNode::addNode( const char *name )
|
|
{
|
|
closeTag( true );
|
|
str += " <";
|
|
str += name;
|
|
hasChildren = false;
|
|
++documentLevel;
|
|
}
|
|
|
|
/**
|
|
* Adds a text node.
|
|
* @param text the text to write into the document node
|
|
*/
|
|
void DomNode::addTextNode( const char *text, TQTextCodec* codec )
|
|
{
|
|
closeTag( false );
|
|
|
|
if (!codec)
|
|
{
|
|
kdError(30515) << "No TQTextCodec available!" << endl;
|
|
return;
|
|
}
|
|
|
|
str += CheckAndEscapeXmlText(codec->toUnicode(text));
|
|
|
|
}
|
|
|
|
/**
|
|
* Add border to existing frameset (see KWord DTD).
|
|
*/
|
|
void DomNode::addBorder( int id, const TQColor &color, int style, double width )
|
|
{
|
|
char attr[16];
|
|
sprintf( attr, "%cRed", id );
|
|
setAttribute( attr, color.red() );
|
|
sprintf( attr, "%cGreen", id );
|
|
setAttribute( attr, color.green() );
|
|
sprintf( attr, "%cBlue", id );
|
|
setAttribute( attr, color.blue() );
|
|
sprintf( attr, "%cStyle", id );
|
|
setAttribute( attr, style );
|
|
sprintf( attr, "%cWidth", id );
|
|
setAttribute( attr, width );
|
|
}
|
|
|
|
/**
|
|
* Add color attributes to document node.
|
|
* @param color the color
|
|
*/
|
|
void DomNode::addColor( const TQColor &color )
|
|
{
|
|
setAttribute( "red", color.red() );
|
|
setAttribute( "green", color.green() );
|
|
setAttribute( "blue", color.blue() );
|
|
}
|
|
|
|
/**
|
|
* Add rectangle attributes to document node.
|
|
*/
|
|
void DomNode::addRect( int left, int top, int right, int bottom )
|
|
{
|
|
setAttribute( "left", .05*left );
|
|
setAttribute( "top", .05*top );
|
|
setAttribute( "right", .05*right );
|
|
setAttribute( "bottom", .05*bottom );
|
|
}
|
|
|
|
/**
|
|
* Add pixmap or clipart key.
|
|
* @param dt date/time
|
|
* @param filename the filename of the image
|
|
* @param name the relative path to the image in the store (optional)
|
|
*/
|
|
void DomNode::addKey( const TQDateTime& dt, const TQString& filename, const TQString& name )
|
|
{
|
|
const TQDate date ( dt.date() );
|
|
const TQTime time ( dt.time() );
|
|
|
|
addNode( "KEY" );
|
|
setAttribute( "filename", CheckAndEscapeXmlText(filename) );
|
|
setAttribute( "year", date.year() );
|
|
setAttribute( "month", date.month() );
|
|
setAttribute( "day", date.day() );
|
|
setAttribute( "hour", time.hour() );
|
|
setAttribute( "minute", time.minute() );
|
|
setAttribute( "second", time.second() );
|
|
setAttribute( "msec", time.msec() );
|
|
|
|
if (!name.isEmpty())
|
|
{
|
|
setAttribute( "name", CheckAndEscapeXmlText(name) );
|
|
}
|
|
closeNode( "KEY" );
|
|
}
|
|
|
|
/**
|
|
* Add frameset to document (see KWord DTD).
|
|
*/
|
|
void DomNode::addFrameSet( const char *name, int frameType, int frameInfo )
|
|
{
|
|
addNode( "FRAMESET" );
|
|
setAttribute( "name", name );
|
|
setAttribute( "frameType", frameType );
|
|
setAttribute( "frameInfo", frameInfo );
|
|
setAttribute( "removable", 0 );
|
|
setAttribute( "visible", 1 );
|
|
}
|
|
|
|
/**
|
|
* Add frame to existing frameset (see KWord DTD).
|
|
*/
|
|
void DomNode::addFrame( int left, int top, int right, int bottom,
|
|
int autoCreateNewFrame, int newFrameBehaviour,
|
|
int sheetSide )
|
|
{
|
|
addNode( "FRAME" );
|
|
addRect( left, top, right, bottom );
|
|
setAttribute( "runaround", 1 );
|
|
setAttribute( "runaroundGap", 2 );
|
|
setAttribute( "autoCreateNewFrame", autoCreateNewFrame );
|
|
setAttribute( "newFrameBehaviour", newFrameBehaviour );
|
|
setAttribute( "sheetSide", sheetSide );
|
|
}
|
|
|
|
/**
|
|
* Sets a new attribute to a string value.
|
|
*/
|
|
void DomNode::setAttribute( const TQString& attribute, const TQString& value )
|
|
{
|
|
str += ' ';
|
|
str += attribute;
|
|
str += '=';
|
|
str += '"';
|
|
str += CheckAndEscapeXmlText( value );
|
|
str += '"';
|
|
hasAttributes = true;
|
|
}
|
|
|
|
/**
|
|
* Sets a new attribute to an integer value.
|
|
*/
|
|
void DomNode::setAttribute( const char *attribute, int value )
|
|
{
|
|
char strvalue[32];
|
|
sprintf( strvalue, "%d", value );
|
|
setAttribute( attribute, (const char *)strvalue );
|
|
}
|
|
|
|
/**
|
|
* Sets a new attribute to a double value.
|
|
*/
|
|
void DomNode::setAttribute( const char *attribute, double value )
|
|
{
|
|
char strvalue[32];
|
|
sprintf( strvalue, "%f", value );
|
|
setAttribute( attribute, (const char *)strvalue );
|
|
}
|
|
|
|
/**
|
|
* Closes a document node.
|
|
* @param name the node (tag) to close
|
|
*/
|
|
void DomNode::closeNode( const char *name )
|
|
{
|
|
if (!hasChildren)
|
|
{
|
|
str += '/';
|
|
}
|
|
else
|
|
{
|
|
str += "</";
|
|
str += name;
|
|
}
|
|
str += ">\n";
|
|
|
|
--documentLevel;
|
|
for (int i=documentLevel-1; i>0; i--)
|
|
{
|
|
str += ' ';
|
|
}
|
|
hasChildren = true;
|
|
}
|
|
|
|
/**
|
|
* Closes the current XML tag (if open).
|
|
* @param nl add a newline
|
|
*/
|
|
void DomNode::closeTag( bool nl )
|
|
{
|
|
if (!hasChildren)
|
|
{
|
|
str += '>';
|
|
|
|
if (nl)
|
|
{
|
|
str += '\n';
|
|
|
|
for (int i=documentLevel-1; i>0; i--)
|
|
{
|
|
str += ' ';
|
|
}
|
|
}
|
|
hasChildren = true;
|
|
}
|
|
hasAttributes = false;
|
|
}
|
|
|
|
/**
|
|
* Appends a child node.
|
|
* @param child the node to append to this document node
|
|
*/
|
|
void DomNode::appendNode( const DomNode &child )
|
|
{
|
|
const TQString childStr ( child.toString() );
|
|
closeTag( (childStr.length() >= 2 && (childStr[0] == '<' || childStr[1] == '<')) );
|
|
str += childStr;
|
|
}
|
|
|
|
/**
|
|
* Appends XML text to node
|
|
*/
|
|
void DomNode::append( const TQString& _str)
|
|
{
|
|
str += _str;
|
|
}
|
|
|
|
void DomNode::append( const TQCString& cstr)
|
|
{
|
|
str += TQString::fromUtf8(cstr);
|
|
}
|
|
|
|
void DomNode::append( const char ch)
|
|
{
|
|
str += ch;
|
|
}
|
|
|
|
/**
|
|
* Returns true if node is empty.
|
|
*/
|
|
bool DomNode::isEmpty( void ) const
|
|
{
|
|
return str.isEmpty();
|
|
}
|
|
|
|
/**
|
|
* Returns the data of the document node.
|
|
*/
|
|
TQString DomNode::toString( void ) const
|
|
{
|
|
return str;
|
|
}
|