diff -uNr qt-x11-free-3.2.3.org/src/codecs/qtextcodec.cpp qt-x11-free-3.2.3/src/codecs/qtextcodec.cpp
--- qt-x11-free-3.2.3.org/src/codecs/qtextcodec.cpp	2003-11-10 19:21:48.000000000 +0900
+++ qt-x11-free-3.2.3/src/codecs/qtextcodec.cpp	2004-06-20 15:41:58.000000000 +0900
@@ -2158,6 +2158,7 @@
 
     // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; ( cut -c25- < TIS-620 ; cat /tmp/digits ) | awk '/^x[89ABCDEF]/{ print $1, $2 }' | sed -e 's/<U/0x/' -e 's/>//' | sort | uniq -w4 | cut -c5- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/tis-620
     { "TIS-620", "ISO 8859-11", 2259, // Thai character set mib enum taken from tis620 (which is byte by byte equivalent)
+	    /*
 	{ 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
 	  0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
 	  0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
@@ -2174,7 +2175,32 @@
 	  0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
 	  0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
 	  0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD } },
+	  */
+    /* add more glyphs from windows-874 http://orwell.ru/test/CP/_?cp874 */
+	{ 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD,
+	  0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+
+	  0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+	  0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
+
+	  0xFFFD, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
+	  0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
+
+	  0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
+	  0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
+
+	  0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
+	  0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
+
+	  0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
+	  0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F,
 
+	  0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
+	  0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
+
+	  0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
+	  0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD } },
+	
     /*
       Name: hp-roman8                                  [HP-PCL5,RFC1345,KXS2]
       MIBenum: 2004
diff -uNr qt-x11-free-3.2.3.org/src/kernel/qrichtext.cpp qt-x11-free-3.2.3/src/kernel/qrichtext.cpp
--- qt-x11-free-3.2.3.org/src/kernel/qrichtext.cpp	2003-11-10 19:21:59.000000000 +0900
+++ qt-x11-free-3.2.3/src/kernel/qrichtext.cpp	2004-06-20 15:39:33.000000000 +0900
@@ -5777,6 +5777,36 @@
 	// we break at w pixels and the current char would exceed that
 	// or - we break at a column and the current character would
 	// exceed that.
+
+        // Thai no-space vowels and tonemarks check
+        //printf("QTextFormatterBreakInWords::format            len is: %d\n",len);
+        //printf("QTextFormatterBreakInWords::format            col is: %d\n",col);
+
+        int isNoSpace = 0;
+        if ( c->c.row() == 0x0e ) {
+          // Thai
+          unsigned char col = c->c.cell();
+          if ( col == 0x31 ||
+               col == 0x34 ||
+               col == 0x35 ||
+               col == 0x36 ||
+               col == 0x37 ||
+               col == 0x38 ||
+               col == 0x39 ||
+               col == 0x3a ||
+               col == 0x47 ||
+               col == 0x48 ||
+               col == 0x49 ||
+               col == 0x4a ||
+               col == 0x4b ||
+               col == 0x4c ||
+               col == 0x4d ||
+               col == 0x4e ) {
+            isNoSpace = 1;
+          }
+        }
+        col -= isNoSpace;
+
 	if ( lastWasHardBreak || lastWasOwnLineCustomItem ||
 	     ( wrapEnabled &&
 	       ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) &&
diff -uNr qt-x11-free-3.2.3.org/src/kernel/qscriptengine_x11.cpp qt-x11-free-3.2.3/src/kernel/qscriptengine_x11.cpp
--- qt-x11-free-3.2.3.org/src/kernel/qscriptengine_x11.cpp	2003-11-10 19:22:02.000000000 +0900
+++ qt-x11-free-3.2.3/src/kernel/qscriptengine_x11.cpp	2004-06-20 15:38:46.000000000 +0900
@@ -1843,8 +1843,72 @@
 //
 // --------------------------------------------------------------------------------------------------------------------------------------------
 
+#include <qtextcodec.h>
+#include <qlibrary.h>
 
 
+static void thaiWordBreaks(const QChar *string, const int len, QCharAttributes *attributes)
+{
+    typedef int (*th_brk_def)(const char*, int[], int);
+    static QTextCodec *thaiCodec = QTextCodec::codecForMib(2259);
+    static th_brk_def th_brk = 0;
+
+    /* load libthai dynamically */
+    if (!th_brk && thaiCodec) {
+        th_brk = (th_brk_def)QLibrary::resolve("thai", "th_brk");
+        if (!th_brk)
+            thaiCodec = 0;
+    }
+
+    if (!th_brk)
+        return;
+
+    QCString cstr = thaiCodec->fromUnicode( QConstString(string, len).string());
+
+    int brp[128];
+    int *break_positions = brp;
+    int numbreaks = th_brk(cstr.data(), break_positions, 128);
+    if (numbreaks > 128) {
+        break_positions = new int[numbreaks];
+        numbreaks = th_brk(cstr.data(),break_positions, numbreaks);
+    }
+
+    for (int i = 1; i < len; ++i)
+        attributes[i].softBreak = FALSE;
+
+    /* beginning of string is always breakable */
+    attributes[0].softBreak = TRUE;
+
+    for (int i = 0; i < numbreaks; ++i)
+        attributes[break_positions[i]].softBreak = TRUE;
+
+    if (break_positions != brp)
+        delete [] break_positions;
+}
+
+
+static void thai_attributes( int script, const QString &text, int from, int len, QCharAttributes *attributes )
+{
+    const QChar *uc = text.unicode() + from;
+    attributes += from;
+
+    QCharAttributes *a = attributes;
+    for ( int i = 0; i < len; i++ ) {
+	QChar::Category cat = ::category( *uc );
+	a->whiteSpace = (cat == QChar::Separator_Space) && (uc->unicode() != 0xa0);
+	a->charStop = (cat != QChar::Mark_NonSpacing);
+        // if we don't know any better, every charstop is a possible line break.
+	a->softBreak = a->charStop;
+	a->wordStop = FALSE;
+	a->invalid = FALSE;
+	++uc;
+	++a;
+    }
+
+    if (script == QFont::Thai)
+        thaiWordBreaks(text.unicode() + from, len, attributes);
+}
+
 
 // --------------------------------------------------------------------------------------------------------------------------------------------
 //
@@ -2912,9 +2976,9 @@
 	// Sinhala,
     { indic_shape, indic_attributes },
 	// Thai,
-    { basic_shape, basic_attributes },
+    { basic_shape, thai_attributes },
 	// Lao,
-    { basic_shape, basic_attributes },
+    { basic_shape, thai_attributes },
 	// Tibetan,
     { tibetan_shape, tibetan_attributes },
 	// Myanmar,
diff -uNr qt-x11-free-3.2.3.org/src/kernel/qtextengine.cpp qt-x11-free-3.2.3/src/kernel/qtextengine.cpp
--- qt-x11-free-3.2.3.org/src/kernel/qtextengine.cpp	2003-11-10 19:22:03.000000000 +0900
+++ qt-x11-free-3.2.3/src/kernel/qtextengine.cpp	2004-06-20 15:37:39.000000000 +0900
@@ -786,16 +786,20 @@
 
     for (int i = 1; i < len; ++i) {
 	int ncls = lineBreakClass(uc[i]);
+        int tcls = ncls;
 
 	if (ncls == QUnicodeTables::LineBreak_SP || ncls == QUnicodeTables::LineBreak_CM) {
 	    charAttributes[i].softBreak = FALSE;
 	    continue;
 	}
-	if (ncls >= QUnicodeTables::LineBreak_SA) {
-	    // ### handle complex case
-	    ncls = QUnicodeTables::LineBreak_ID;
-	}
-	int brk = charAttributes[i].charStop ? breakTable[cls][ncls] : (int)Pbk;
+        if (cls == QUnicodeTables::LineBreak_SA && ncls == QUnicodeTables::LineBreak_SA)
+            // two complex chars (thai or lao), thai_attributes has already set this correctly
+            continue;
+
+	if (ncls >= QUnicodeTables::LineBreak_SA)
+	    tcls = QUnicodeTables::LineBreak_ID;
+
+	int brk = charAttributes[i].charStop ? breakTable[cls][tcls] : (int)Pbk;
 	if (brk == Ibk)
 	    charAttributes[i].softBreak = (lineBreakClass(uc[i-1]) == QUnicodeTables::LineBreak_SP);
 	else
