# HG changeset patch
# User Michael Stahl <mst@openoffice.org>
# Date 1303140563 0
# Node ID 63097700fafde0b9c5d6f30736882f02dbe2a375
# Parent  aea559b340040418c909b14aabda490858b4abf0
rtftok01: writerfilter: support for font-dependent text encodings

diff --git a/writerfilter/source/rtftok/RTFDocumentImpl.cxx b/writerfilter/source/rtftok/RTFDocumentImpl.cxx
--- a/writerfilter/source/rtftok/RTFDocumentImpl.cxx
+++ b/writerfilter/source/rtftok/RTFDocumentImpl.cxx
@@ -335,6 +335,8 @@
 };
 
 
+typedef ::std::map<sal_Int32, rtl_TextEncoding> FontTable_t;
+
 static char
 lcl_HexDigit(char const c)
 {
@@ -476,6 +478,17 @@
 fprintf(stderr, "RTFScannerHandlerImpl::SetUnicodeCharacters: %d\n", uc);
         GetCurrentGroup().m_UnicodeCharacters = uc;
     }
+    void SetFontTable(FontTable_t const& rFontTable) {
+        m_FontTable = rFontTable;
+    }
+    void SetEncodingToFont(const sal_Int32 i) {
+        FontTable_t::const_iterator const iter(m_FontTable.find(i));
+        if (m_FontTable.end() != iter) {
+            SetEncoding(iter->second);
+        } else {
+            OSL_TRACE("RTFScannerHandlerImpl: invalid font: %d", i);
+        }
+    }
 
 private:
     void checkStrings()
@@ -505,10 +518,95 @@
     unsigned int m_NegativeCharacters;
     ::std::stack< ::std::pair<int, RTFDestination::Pointer_t> > m_Destinations;
     ::std::stack< RTFGroup > m_Groups;
+    FontTable_t m_FontTable;
 };
 
 
 
+static sal_uInt32
+lcl_CharsetToCodePage(sal_Int32 const charset)
+{
+    switch (charset)
+    {
+        case 0:
+            return 1252;    // ANSI
+        case 1:
+            return 0;       // Default
+        case 2:
+            return 42;      // Symbol
+        case 77:
+            return 10000;   // Mac Roman
+        case 78:
+            return 10001;   // Mac Shift Jis
+        case 79:
+            return 10003;   // Mac Hangul
+        case 80:
+            return 10008;   // Mac GB2312
+        case 81:
+            return 10002;   // Mac Big5
+#if 0
+        case 82:
+            return ;        // Mac Johab (old)
+#endif
+        case 83:
+            return 10005;   // Mac Hebrew
+        case 84:
+            return 10004;   // Mac Arabic
+        case 85:
+            return 10006;   // Mac Greek
+        case 86:
+            return 10081;   // Mac Turkish
+        case 87:
+            return 10021;   // Mac Thai
+        case 88:
+            return 10029;   // Mac East Europe
+        case 89:
+            return 10007;   // Mac Russian
+        case 128:
+            return 932;     // Shift JIS
+        case 129:
+            return 949;     // Hangul
+        case 130:
+            return 1361;    // Johab
+        case 134:
+            return 936;     // GB2312
+        case 136:
+            return 950;     // Big5
+        case 161:
+            return 1253;    // Greek
+        case 162:
+            return 1254;    // Turkish
+        case 163:
+            return 1258;    // Vietnamese
+        case 177:
+            return 1255;    // Hebrew
+        case 178:
+            return 1256;    // Arabic
+#if 0
+        case 179:
+            return ;        // Arabic Traditional (old)
+        case 180:
+            return ;        // Arabic user (old)
+        case 181:
+            return ;        // Hebrew user (old)
+#endif
+        case 186:
+            return 1257;    // Baltic
+        case 204:
+            return 1251;    // Russian
+        case 222:
+            return 874;     // Thai
+        case 238:
+            return 1250;    // Eastern European
+        case 254:
+            return 437;     // PC 437
+        case 255:
+            return 850;     // OEM
+        default:
+            OSL_TRACE("unsupported fcharset: %d", charset);
+            return -1;
+    }
+}
 
 class RTFDestinationFontTable
     : public RTFDestination
@@ -516,7 +614,9 @@
 public:
     explicit RTFDestinationFontTable(RTFScannerHandlerImpl & rHandler)
         : RTFDestination(rHandler)
+        , m_DefaultEncoding(rHandler.GetEncoding())
         , m_Level(1)
+        , m_Entry(m_DefaultEncoding)
     { }
     virtual ~RTFDestinationFontTable() { }
 
@@ -527,6 +627,23 @@
                 m_Entry.m_Index = ::rtl::OString(value).toInt32();
 fprintf(stderr, "read: \\f with: %d\n", m_Entry.m_Index);
             }
+            else if (!strcasecmp(token, "fcharset")) {
+                sal_Int32 const n( ::rtl::OString(value).toInt32() );
+                sal_uInt32 cp(lcl_CharsetToCodePage(n));
+                if (0 == cp) {
+                    m_Entry.m_Encoding = m_DefaultEncoding;
+                } else {
+                    rtl_TextEncoding const e(
+                        rtl_getTextEncodingFromWindowsCodePage(cp));
+                    m_Entry.m_Encoding = e;
+                }
+            }
+            else if (!strcasecmp(token, "cpg")) {
+                sal_Int32 const n( ::rtl::OString(value).toInt32() );
+                rtl_TextEncoding const e(
+                    rtl_getTextEncodingFromWindowsCodePage(n));
+                m_Entry.m_Encoding = e;
+            }
         }
     }
     virtual void lbrace()
@@ -541,12 +658,13 @@
             writerfilter::Reference<Table>::Pointer_t const pTable(
                     new RTFRefTable(m_Properties) );
             GetHandler().GetStream().table(NS_rtf::LN_FONTTABLE, pTable);
+            GetHandler().SetFontTable(m_FontTable);
         }
         else if (2 == m_Level) // end of font entry
         {
             ::rtl::OUString name(
-                ::rtl::OStringToOUString(m_Entry.m_Name,
-                    GetHandler().GetEncoding()).trim() );
+                ::rtl::OStringToOUString(m_Entry.m_Name, m_Entry.m_Encoding)
+                    .trim() );
             if (name.endsWithAsciiL(";", 1)) { // strip trailing ;
                 name = name.copy(0, name.getLength() - 1);
             }
@@ -565,8 +683,10 @@
                         new RTFRefProperties(attrmap) );
                 m_Properties.insert(
                         ::std::make_pair(m_Entry.m_Index, pProperties));
+                m_FontTable.insert(
+                        ::std::make_pair(m_Entry.m_Index, m_Entry.m_Encoding));
             }
-            m_Entry = Entry(); // reset
+            m_Entry = Entry(m_DefaultEncoding); // reset
         }
         --m_Level;
         OSL_ASSERT(m_Level >= 0);
@@ -582,12 +702,18 @@
     }
 
 private:
+    rtl_TextEncoding m_DefaultEncoding;
+    FontTable_t m_FontTable;
     RTFRefTable::Properties_t m_Properties;
     int m_Level;
     struct Entry {
         ::rtl::OString m_Name;
         int m_Index;
-        explicit Entry() : m_Index(-1) { }
+        rtl_TextEncoding m_Encoding;
+        explicit Entry(rtl_TextEncoding const e)
+            : m_Index(-1)
+            , m_Encoding(e)
+        { }
     } m_Entry;
 };
 
@@ -649,6 +775,10 @@
             sal_uInt8 const nl(0x0d);
             GetHandler().GetStream().text(& nl, sizeof(nl));
         }
+        else if (!strcasecmp(token, "f")) {
+            sal_Int32 const n( ::rtl::OString(value).toInt32() );
+            GetHandler().SetEncodingToFont(n);
+        }
 else fprintf(stderr, "RTFDestinationRTF::ctrl: ignoring control %s\n", token);
     }
 #if 0
