Sebastian,

Sebastian Moors wrote:
Oh, no problem. I think the zombie stuff is more important, so qtxml can

I've attached 2 patches... but wanted to discuss something about them.

  * Patch A:  Implements TinyXML compatability mode
    for reading songs

  * Patch B:  Adds "xф" to tutorial_georgyporgy.h2song
    title to text patch A.  When read in, it should be interpreted
    as the UTF-8 sequence for the Cyrillic letter EF "ф".

However, this only adds the compatability mode for reading a _song_. To implement it for all the other files will require copying the code to several places.

What if we do sort of a factory like this:

    QDomDocument doc = LocalFileMng::openXmlDocument( filename );

The static function LocalFileMng::openXmlDocument() can do any redirection or filtering that we need.

What do you think?

Peace,
Gabriel
diff --git a/libs/hydrogen/include/hydrogen/LocalFileMng.h b/libs/hydrogen/include/hydrogen/LocalFileMng.h
index d62e035..62c7530 100644
--- a/libs/hydrogen/include/hydrogen/LocalFileMng.h
+++ b/libs/hydrogen/include/hydrogen/LocalFileMng.h
@@ -90,6 +90,7 @@ public:
 	static float readXmlFloat( QDomNode , const QString& nodeName, float defaultValue, bool bCanBeEmpty = false, bool bShouldExists = true , bool tinyXmlCompatMode = false);
 	static int readXmlInt( QDomNode , const QString& nodeName, int defaultValue, bool bCanBeEmpty = false, bool bShouldExists = true , bool tinyXmlCompatMode = false);
 	static bool readXmlBool( QDomNode , const QString& nodeName, bool defaultValue, bool bShouldExists = true , bool tinyXmlCompatMode = false );
+	static void convertFromTinyXMLString( QByteArray* str );
 	static bool checkTinyXMLCompatMode( const QString& filename );
 
 private:
diff --git a/libs/hydrogen/src/local_file_mgr.cpp b/libs/hydrogen/src/local_file_mgr.cpp
index 036ab18..c5a5f57 100644
--- a/libs/hydrogen/src/local_file_mgr.cpp
+++ b/libs/hydrogen/src/local_file_mgr.cpp
@@ -42,6 +42,7 @@
 #include <cstdlib>
 #include <cassert>
 #include <sys/stat.h>
+#include <ctype.h>
 
 #include <QDir>
 #include <QApplication>
@@ -1194,6 +1195,59 @@ void LocalFileMng::writeXmlBool( QDomNode parent, const QString& name, bool valu
 	}
 }
 
+/* Convert (in-place) an XML escape sequence into a literal byte,
+ * rather than the character it actually refers to.
+ */
+void LocalFileMng::convertFromTinyXMLString( QByteArray* str )
+{
+	/* When TinyXML encountered a non-ASCII character, it would
+	 * simply write the character as "&#xx;" -- where "xx" is
+	 * the hex character code.  However, this doesn't respect
+	 * any encodings (e.g. UTF-8, UTF-16).  In XML, &#xx; literally
+	 * means "the Unicode character # xx."  However, in a UTF-8
+	 * sequence, this could be an escape character that tells
+	 * whether we have a 2, 3, or 4-byte UTF-8 sequence.
+	 *
+	 * For example, the UTF-8 sequence 0xD184 was being written
+	 * by TinyXML as "&#xD1;&#x84;".  However, this is the UTF-8
+	 * sequence for the cyrillic small letter EF (which looks
+	 * kind of like a thorn or a greek phi).  This letter, in
+	 * XML, should be saved as &#x00000444;, or even literally
+	 * (no escaping).  As a consequence, when &#xD1; is read
+	 * by an XML parser, it will be interpreted as capital N
+	 * with a tilde (~).  Then &#x84; will be interpreted as
+	 * an unknown or control character.
+	 *
+	 * So, when we know that TinyXML wrote the file, we can
+	 * simply exchange these hex sequences to literal bytes.
+	 */
+	int pos = 0;
+
+	pos = str->indexOf("&#x");
+	while( pos != -1 ) {
+		if( isxdigit(str->at(pos+3))
+		    && isxdigit(str->at(pos+4))
+		    && (str->at(pos+5) == ';') ) {
+			char w1 = str->at(pos+3);
+			char w2 = str->at(pos+4);
+
+			w1 = tolower(w1) - 0x30;  // '0' = 0x30
+			if( w1 > 9 ) w1 -= 0x27;  // '9' = 0x39, 'a' = 0x61
+			w1 = (w1 & 0xF);
+
+			w2 = tolower(w2) - 0x30;  // '0' = 0x30
+			if( w2 > 9 ) w2 -= 0x27;  // '9' = 0x39, 'a' = 0x61
+			w2 = (w2 & 0xF);
+
+			char ch = (w1 << 4) | w2;
+			(*str)[pos] = ch;
+			++pos;
+			str->remove(pos, 5);
+		}
+		pos = str->indexOf("&#x");
+	}
+}
+
 bool LocalFileMng::checkTinyXMLCompatMode( const QString& filename )
 {
 	/*
@@ -1208,10 +1262,14 @@ bool LocalFileMng::checkTinyXMLCompatMode( const QString& filename )
 		return false;
 
 	QString line = file.readLine();
-	if ( ! line.startsWith( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" )){
-		return true;
-	} else  {
+	file.close();
+	if ( line.startsWith( "<?xml" )){
 		return false;
+	} else  {
+		_WARNINGLOG( QString("File '%1' is being read in "
+				    "TinyXML compatability mode")
+			    .arg(filename) );
+		return true;
 	}
 
 
diff --git a/libs/hydrogen/src/song.cpp b/libs/hydrogen/src/song.cpp
index 2021a07..763dd76 100644
--- a/libs/hydrogen/src/song.cpp
+++ b/libs/hydrogen/src/song.cpp
@@ -247,21 +247,44 @@ Song* SongReader::readSong( const QString& filename )
 	}
 
 
+	bool TinyXMLCompat = LocalFileMng::checkTinyXMLCompatMode( filename );
+
 	QDomDocument doc( "song" );
 	QFile file( filename );
 
 	if ( !file.open(QIODevice::ReadOnly) )
 		return NULL;
 
-	if ( !doc.setContent( &file ) ) {
+	if( TinyXMLCompat ) {
+	    QString enc = QTextCodec::codecForLocale()->name();
+	    if( enc == QString("System") ) {
+		    enc = "UTF-8";
+	    }
+	    QByteArray line;
+	    QByteArray buf = QString("<?xml version='1.0' encoding='%1' ?>\n")
+		.arg( enc )
+		.toLocal8Bit();
+
+	    INFOLOG( QString("Using '%1' encoding for TinyXML file").arg(enc) );
+
+	    while( !file.atEnd() ) {
+		line = file.readLine();
+		LocalFileMng::convertFromTinyXMLString( &line );
+		buf += line;
+	    }
+
+	    if( ! doc.setContent( buf ) ) {
 		file.close();
 		return NULL;
-	}
-	file.close();
+	    }
 
-	if (LocalFileMng::checkTinyXMLCompatMode( filename )){
-		ERRORLOG( "old xml file!!!!" );
+	} else {
+	    if( ! doc.setContent( &file ) ) {
+		file.close();
+		return NULL;
+	    }
 	}
+	file.close();
 
 	QDomNodeList nodeList = doc.elementsByTagName( "song" );
 	
diff --git a/data/demo_songs/tutorial_georgyporgy.h2song b/data/demo_songs/tutorial_georgyporgy.h2song
index 2d47e34..3befcbe 100644
--- a/data/demo_songs/tutorial_georgyporgy.h2song
+++ b/data/demo_songs/tutorial_georgyporgy.h2song
@@ -3,7 +3,7 @@
     <bpm>98</bpm>
     <volume>0.5</volume>
     <metronomeVolume>0.5</metronomeVolume>
-    <name>Georgy porgy</name>
+    <name>x&#xD1;&#x84;Georgy porgy</name>
     <author>Toto</author>
     <notes>Drummer: Jeff Porcaro</notes>
     <loopEnabled>false</loopEnabled>
------------------------------------------------------------------------------
_______________________________________________
Hydrogen-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/hydrogen-devel

Reply via email to