/* AbiWord * Copyright (C) 2001 Sean Young * Copyright (C) 2001 Hubert Figuiere * Copyright (C) 2001 Dom Lachowicz * Copyright (C) 2010-2011 Ingo Brueckl * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Documentation at http://www.msxnet.org/word2rtf/formats/write * */ #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef _MSC_VER typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #else #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif #endif #include "ie_imp_MSWrite.h" #include "ap_Args.h" #include "fg_Graphic.h" #include "ie_impGraphic.h" #include "ut_assert.h" #include "ut_locale.h" #include "ut_types.h" #include "xap_Module.h" #ifdef ABI_PLUGIN_BUILTIN #define abi_plugin_register abipgn_mswrite_register #define abi_plugin_unregister abipgn_mswrite_unregister #define abi_plugin_supports_version abipgn_mswrite_supports_version #define ABI_BUILTIN_FAR_CALL extern "C" #else #define ABI_BUILTIN_FAR_CALL ABI_FAR_CALL ABI_PLUGIN_DECLARE("MSWrite") #endif // we use a reference-counted sniffer static IE_Imp_MSWrite_Sniffer *m_sniffer = 0; /********************************************************************** * Plugin Registration * **********************************************************************/ ABI_BUILTIN_FAR_CALL int abi_plugin_register (XAP_ModuleInfo *mi) { if (!m_sniffer) m_sniffer = new IE_Imp_MSWrite_Sniffer(); mi->name = "MSWrite Importer"; mi->desc = "Import Microsoft Write Documents"; mi->version = ABI_VERSION_STRING; mi->author = "Sean Young, Ingo Brückl"; mi->usage = "No Usage"; IE_Imp::registerImporter(m_sniffer); return 1; } ABI_BUILTIN_FAR_CALL int abi_plugin_unregister (XAP_ModuleInfo *mi) { mi->name = 0; mi->desc = 0; mi->version = 0; mi->author = 0; mi->usage = 0; UT_ASSERT(m_sniffer); IE_Imp::unregisterImporter(m_sniffer); DELETEP(m_sniffer); return 1; } ABI_BUILTIN_FAR_CALL int abi_plugin_supports_version (UT_uint32 major, UT_uint32 minor, UT_uint32 release) { UT_UNUSED(major); UT_UNUSED(minor); UT_UNUSED(release); return 1; } /********************************************************************** * File Sniffer * **********************************************************************/ // supported suffix static const IE_SuffixConfidence IE_Imp_MSWrite_Sniffer__SuffixConfidence[] = { {"wri", UT_CONFIDENCE_PERFECT}, {"", UT_CONFIDENCE_ZILCH} }; IE_Imp_MSWrite_Sniffer::IE_Imp_MSWrite_Sniffer () : IE_ImpSniffer("AbiMSWrite::MSWrite") { } bool IE_Imp_MSWrite_Sniffer::getDlgLabels (const char **szDesc, const char **szSuffixList, IEFileType *ft) { *szDesc = "Microsoft Write (.wri)"; *szSuffixList = "*.wri"; *ft = getFileType(); return true; } const IE_SuffixConfidence *IE_Imp_MSWrite_Sniffer::getSuffixConfidence () { return IE_Imp_MSWrite_Sniffer__SuffixConfidence; } UT_Confidence_t IE_Imp_MSWrite_Sniffer::recognizeContents (const char *szBuf, UT_uint32 iNumbytes) { if (iNumbytes > 8) { if ((szBuf[0] == static_cast(0x31) || szBuf[0] == static_cast(0x32)) && szBuf[1] == static_cast(0xbe) && szBuf[2] == static_cast(0) && szBuf[3] == static_cast(0) && szBuf[4] == static_cast(0) && szBuf[5] == static_cast(0xab)) return UT_CONFIDENCE_PERFECT; } return UT_CONFIDENCE_ZILCH; } UT_Error IE_Imp_MSWrite_Sniffer::constructImporter (PD_Document *pDocument, IE_Imp **ppie) { IE_Imp_MSWrite *p = new IE_Imp_MSWrite(pDocument); *ppie = p; return UT_OK; } /********************************************************************** * MSWrite File Structures * **********************************************************************/ static const wri_struct WRI_FILE_HEADER[] = { /* value, data, size, type, name */ /* word no. */ {0, NULL, 2, CT_VALUE, "wIdent"}, // 0 {0, NULL, 2, CT_VALUE, "dty"}, // 1 {0, NULL, 2, CT_VALUE, "wTool"}, // 2 {0, NULL, 2, CT_VALUE, "reserved1"}, // 3 {0, NULL, 2, CT_VALUE, "reserved2"}, // 4 {0, NULL, 2, CT_VALUE, "reserved3"}, // 5 {0, NULL, 2, CT_VALUE, "reserved4"}, // 6 {0, NULL, 4, CT_VALUE, "fcMac"}, // 7-8 {0, NULL, 2, CT_VALUE, "pnPara"}, // 9 {0, NULL, 2, CT_VALUE, "pnFntb"}, // 10 {0, NULL, 2, CT_VALUE, "pnSep"}, // 11 {0, NULL, 2, CT_VALUE, "pnSetb"}, // 12 {0, NULL, 2, CT_VALUE, "pnPgtb"}, // 13 {0, NULL, 2, CT_VALUE, "pnFfntb"}, // 14 {0, NULL, 64, CT_IGNORE, "szSsht"}, // 15-47 {0, NULL, 2, CT_VALUE, "pnMac"}, // 48 {0, NULL, 0, CT_IGNORE, NULL} // EOF }; static const wri_struct WRI_PICTURE_HEADER[] = { /* value, data, size, type, name */ /* word no. */ // METAFILEPICT structure {0, NULL, 2, CT_VALUE, "mm"}, // 0 {0, NULL, 2, CT_VALUE, "xExt"}, // 1 {0, NULL, 2, CT_VALUE, "yExt"}, // 2 {0, NULL, 2, CT_IGNORE, "hMF"}, // 3 // end of METAFILEPICT structure {0, NULL, 2, CT_VALUE, "dxaOffset"}, // 4 {0, NULL, 2, CT_VALUE, "dxaSize"}, // 5 {0, NULL, 2, CT_VALUE, "dyaSize"}, // 6 {0, NULL, 2, CT_VALUE, "cbOldSize"}, // 7 // BITMAP structure {0, NULL, 2, CT_VALUE, "bmType"}, // 8 {0, NULL, 2, CT_VALUE, "bmWidth"}, // 9 {0, NULL, 2, CT_VALUE, "bmHeight"}, // 10 {0, NULL, 2, CT_VALUE, "bmWidthBytes"}, // 11 {0, NULL, 1, CT_VALUE, "bmPlanes"}, // 12 {0, NULL, 1, CT_VALUE, "bmBitsPixel"}, // 12.5 {0, NULL, 4, CT_VALUE, "bmBits"}, // 13-14 // end of BITMAP structure {0, NULL, 2, CT_VALUE, "cbHeader"}, // 15 {0, NULL, 4, CT_VALUE, "cbSize"}, // 16-17 {0, NULL, 2, CT_VALUE, "mx"}, // 18 {0, NULL, 2, CT_VALUE, "my"}, // 19 {0, NULL, 0, CT_IGNORE, NULL} // EOF }; static const wri_struct WRI_OLE_HEADER[] = { /* value, data, size, type, name */ /* word no. */ {0, NULL, 2, CT_VALUE, "mm"}, // 0 {0, NULL, 4, CT_IGNORE, "not_used"}, // 1-2 {0, NULL, 2, CT_VALUE, "objectType"}, // 3 {0, NULL, 2, CT_VALUE, "dxaOffset"}, // 4 {0, NULL, 2, CT_VALUE, "dxaSize"}, // 5 {0, NULL, 2, CT_VALUE, "dyaSize"}, // 6 {0, NULL, 2, CT_IGNORE, "not_used2"}, // 7 {0, NULL, 4, CT_VALUE, "dwDataSize"}, // 8-9 {0, NULL, 4, CT_IGNORE, "not_used3"}, // 10-11 {0, NULL, 4, CT_VALUE, "dwObjNum"}, // 12-13 {0, NULL, 2, CT_VALUE, "not_used4"}, // 14 {0, NULL, 2, CT_VALUE, "cbHeader"}, // 15 {0, NULL, 4, CT_IGNORE, "not_used5"}, // 16-17 {0, NULL, 2, CT_VALUE, "mx"}, // 18 {0, NULL, 2, CT_VALUE, "my"}, // 19 {0, NULL, 0, CT_IGNORE, NULL} // EOF }; #define PIC_OR_OLE_HEADER_SIZE 40 // common size of both header types // OLE1.0 structure offsets #define OLE_Version 0 #define OLE_FormatID 4 #define OLE_ClassNameLength 8 #define OLE_ClassNameString 12 // variable length // offsets relative to empty ClassNameString #define OLE_TopicNameLength 12 #define OLE_TopicNameString 16 // offsets relative to empty ClassNameString and TopicNameString #define OLE_ItemNameLength 16 #define OLE_ItemNameString 20 // offsets relative to empty ClassNameString and TopicNameString and ItemNameString #define OLE_ObjDataSize 20 #define OLE_Object 24 #define OLE_MF_Reserved 24 #define OLE_MF_Object 32 // Bitmap16 structure offsets #define BM16_Type 0 #define BM16_Width 2 #define BM16_Height 4 #define BM16_WidthBytes 6 #define BM16_Planes 8 #define BM16_BitsPixel 9 #define BM16_Bits 10 /********************************************************************** * MSWrite Importer * **********************************************************************/ IE_Imp_MSWrite::IE_Imp_MSWrite (PD_Document *pDocument) : IE_Imp(pDocument), default_codepage("CP1252"), hasHeader(false), hasFooter(false), wri_fonts(0), wri_fonts_count(0), pic_nr(0), lf(false) { setProps(AP_Args::m_impProps); const std::string propCP = getProperty("mswrite-codepage"); if (!propCP.empty()) default_codepage = propCP.c_str(); wri_file_header = static_cast(malloc(sizeof(WRI_FILE_HEADER))); memcpy(wri_file_header, WRI_FILE_HEADER, sizeof(WRI_FILE_HEADER)); wri_picture_header = static_cast(malloc(sizeof(WRI_PICTURE_HEADER))); memcpy(wri_picture_header, WRI_PICTURE_HEADER, sizeof(WRI_PICTURE_HEADER)); wri_ole_header = static_cast(malloc(sizeof(WRI_OLE_HEADER))); memcpy(wri_ole_header, WRI_OLE_HEADER, sizeof(WRI_OLE_HEADER)); } IE_Imp_MSWrite::~IE_Imp_MSWrite() { free_wri_struct(wri_file_header); free(wri_file_header); free(wri_picture_header); free(wri_ole_header); } /********************************************************************** * MSWrite Importer (file loading) * **********************************************************************/ UT_Error IE_Imp_MSWrite::_loadFile (GsfInput *input) { UT_Error result; mFile = (GsfInput *) g_object_ref(G_OBJECT(input)); if (!mFile) return UT_ERROR; result = parse_file(); g_object_unref(G_OBJECT(mFile)); return result; } UT_Error IE_Imp_MSWrite::parse_file () { int id, size; UT_Byte *thetext; if (!read_wri_struct(wri_file_header, mFile)) return UT_ERROR; id = wri_struct_value(wri_file_header, "wIdent"); if (id == 0137062) { // okay, but expect OLE objects } else if (id != 0137061) { fprintf(stderr, "parse_file: Not a write file!\n"); return UT_ERROR; } if (wri_struct_value(wri_file_header, "wTool") != 0125400) { fprintf(stderr, "parse_file: Not a write file!\n"); return UT_ERROR; } size = wri_struct_value(wri_file_header, "fcMac") - 0x80; thetext = static_cast(malloc(size)); if (!thetext) { fprintf(stderr, "parse_file: Out of memory!\n"); return UT_ERROR; } if (gsf_input_seek(mFile, 0x80, G_SEEK_SET)) { perror("parse_file: Can't seek data!"); return UT_ERROR; } gsf_input_read(mFile, size, thetext); if (!read_ffntb()) { free(thetext); return UT_ERROR; } mData.truncate(0); mData.append(thetext, size); free(thetext); read_sep(); read_pap(All); if (hasHeader) { _append_hdrftr(header); read_pap(Header); if (!page1Header) _append_hdrftr(headerfirst); // an empty one } if (hasFooter) { _append_hdrftr(footer); read_pap(Footer); if (!page1Footer) _append_hdrftr(footerfirst); // an empty one } free_ffntb(); return UT_OK; } /********************************************************************** * MSWrite Importer (font handling) * **********************************************************************/ bool IE_Imp_MSWrite::read_ffntb () { int pnFfntb, pnMac, fonts_count = 0, cbFfn, fflen; unsigned char buf[2], ffid; wri_font *fonts; char *ffn; pnFfntb = wri_struct_value(wri_file_header, "pnFfntb"); pnMac = wri_struct_value(wri_file_header, "pnMac"); // if pnFfntb is the same as pnMac, there are no fonts if (pnFfntb == pnMac) return true; if (gsf_input_seek(mFile, pnFfntb++ * 0x80, G_SEEK_SET)) { perror("read_ffntb: Can't seek FFNTB!"); return false; } // the first two bytes are the number of fonts if (!gsf_input_read(mFile, 2, buf)) { perror("read_ffntb: Can't read FFNTB!"); return false; } wri_fonts_count = READ_WORD(buf); while (true) { if (!gsf_input_read(mFile, 2, buf)) { perror("read_ffntb: Can't read cbFfn!"); wri_fonts_count = fonts_count; free_ffntb(); return false; } cbFfn = READ_WORD(buf); if (cbFfn == 0) break; if (cbFfn == 0xffff) { if (gsf_input_seek(mFile, pnFfntb++ * 0x80, G_SEEK_SET)) { perror("read_ffntb: Can't seek next FFNTB!"); wri_fonts_count = fonts_count; free_ffntb(); return false; } continue; } // add one more font fonts = (wri_font *) realloc(wri_fonts, (fonts_count + 1) * sizeof(wri_font)); if (!fonts) { fprintf(stderr, "read_ffntb: Out of memory!\n"); wri_fonts_count = fonts_count; free_ffntb(); return false; } wri_fonts = fonts; // This is the font family identifier. It can either be FF_DONTCARE, // FF_ROMAN, FF_SWISS, FF_MODERN, FF_SCRIPT or FF_DECORATIVE. These // are defined in , but I don't know what to do with them. if (!gsf_input_read(mFile, 1, &ffid)) { perror("read_ffntb: Can't read ffid!"); wri_fonts_count = fonts_count; free_ffntb(); return false; } wri_fonts[fonts_count].ffid = ffid; cbFfn--; // we've already read ffid ffn = static_cast(malloc(cbFfn)); if (!ffn) { fprintf(stderr, "read_ffntb: Out of memory!\n"); wri_fonts_count = fonts_count; free_ffntb(); return false; } if (!gsf_input_read(mFile, cbFfn, (guint8 *) ffn)) { perror("read_ffntb: Can't read szFfn!"); wri_fonts_count = fonts_count + 1; free_ffntb(); return false; } wri_fonts[fonts_count].codepage = get_codepage(ffn, &fflen); ffn[fflen] = 0; wri_fonts[fonts_count].name = ffn; fonts_count++; } if (fonts_count != wri_fonts_count) { wri_fonts_count = fonts_count; fprintf(stderr, "read_ffntb: Wrong number of fonts.\n"); } return true; } void IE_Imp_MSWrite::free_ffntb () { for (int i = 0; i < wri_fonts_count; i++) { free((void *) wri_fonts[i].name); wri_fonts[i].name = NULL; } free(wri_fonts); wri_fonts = NULL; } /********************************************************************** * MSWrite Importer (section property) * **********************************************************************/ bool IE_Imp_MSWrite::read_sep () { int pnSep, pnSetb; int yaMac, xaMac, yaTop, dyaText, dxaText, rStartPage, yaHeader, yaFooter; int cch, yaBot; unsigned char sep[0x80]; pnSep = wri_struct_value(wri_file_header, "pnSep"); pnSetb = wri_struct_value(wri_file_header, "pnSetb"); // default SEP values yaMac = 15840; xaMac = 12240; yaTop = 1440; dyaText = 12960; dxaText = 8640; xaLeft = 1800; rStartPage = 0xFFFF; yaHeader = 1080; yaFooter = 15760; // if the section properties differ from the defaults, get them if (pnSep != pnSetb) { gsf_input_seek(mFile, pnSep * 0x80, G_SEEK_SET); gsf_input_read(mFile, 0x80, sep); cch = *sep; if (cch >= 4) yaMac = READ_WORD(sep + 3); if (cch >= 6) xaMac = READ_WORD(sep + 5); if (cch >= 8) rStartPage = READ_WORD(sep + 7); if (cch >= 10) yaTop = READ_WORD(sep + 9); if (cch >= 12) dyaText = READ_WORD(sep + 11); if (cch >= 14) xaLeft = READ_WORD(sep + 13); if (cch >= 16) dxaText = READ_WORD(sep + 15); if (cch >= 20) yaHeader = READ_WORD(sep + 19); if (cch >= 22) yaFooter = READ_WORD(sep + 21); } yaBot = yaMac - yaTop - dyaText; xaRight = xaMac - xaLeft - dxaText; UT_String properties; UT_LocaleTransactor lt(LC_NUMERIC, "C"); UT_String_sprintf(properties, "page-margin-header:%.4fin; " "page-margin-right:%.4fin; " "page-margin-left:%.4fin; " "page-margin-top:%.4fin; " "page-margin-bottom:%.4fin; " "page-margin-footer:%.4fin", static_cast(yaHeader) / 1440.0, static_cast(xaRight) / 1440.0, static_cast(xaLeft) / 1440.0, static_cast(yaTop) / 1440.0, static_cast(yaBot) / 1440.0, static_cast(yaMac - yaFooter) / 1440.0); if (rStartPage & 0x8000) rStartPage = -0x10000 + rStartPage; if (rStartPage >= 0) { UT_String tmp; UT_String_sprintf(tmp, "; section-restart:1" "; section-restart-value:%d", rStartPage); properties += tmp; } const gchar *attributes[11]; attributes[0] = PT_PROPS_ATTRIBUTE_NAME; attributes[1] = properties.c_str(); attributes[2] = PT_HEADERFIRST_ATTRIBUTE_NAME; attributes[3] = "0"; attributes[4] = PT_HEADER_ATTRIBUTE_NAME; attributes[5] = "1"; attributes[6] = PT_FOOTERFIRST_ATTRIBUTE_NAME; attributes[7] = "2"; attributes[8] = PT_FOOTER_ATTRIBUTE_NAME; attributes[9] = "3"; attributes[10] = NULL; appendStrux(PTX_Section, attributes); return true; } /********************************************************************** * MSWrite Importer (paragraph property) * **********************************************************************/ bool IE_Imp_MSWrite::read_pap (pap_t process) { static const char *text_align[] = {"left", "center", "right", "justify"}; int fcMac, pnPara, fcFirst, cfod, fc, fcLim; unsigned char page[0x80]; UT_String properties, tmp, lastprops; fcMac = wri_struct_value(wri_file_header, "fcMac"); pnPara = wri_struct_value(wri_file_header, "pnPara"); fcFirst = 0x80; while (true) { gsf_input_seek(mFile, pnPara++ * 0x80, G_SEEK_SET); gsf_input_read(mFile, 0x80, page); cfod = page[0x7f]; fc = READ_DWORD(page); if (fc != fcFirst) fprintf(stderr, "read_pap: fcFirst wrong.\n"); // read all FODs (format descriptors) for (int fod = 0; fod < cfod; fod++) { int bfprop, cch; int jc, dxaRight, dxaLeft, dxaLeft1, dyaLine, fGraphics; int rhcPage, rHeaderFooter, rhcFirst; int tabs, dxaTab[14], jcTab[14]; // read a FOD (format descriptor) fcLim = READ_DWORD(page + 4 + fod * 6); bfprop = READ_WORD(page + 8 + fod * 6); // default PAP values jc = 0; dxaRight = dxaLeft = dxaLeft1 = 0; dyaLine = 240; fGraphics = 0; rhcPage = rHeaderFooter = rhcFirst = 0; tabs = 0; // if the PAP FPROPs (formatting properties) differ from the defaults, get them if (bfprop != 0xffff && bfprop + (cch = page[bfprop + 4]) < 0x80) { if (cch >= 2) jc = page[bfprop + 6] & 3; if (cch >= 6) dxaRight = READ_WORD(page + bfprop + 9); if (cch >= 8) dxaLeft = READ_WORD(page + bfprop + 11); if (cch >= 10) dxaLeft1 = READ_WORD(page + bfprop + 13); if (cch >= 12) dyaLine = READ_WORD(page + bfprop + 15); if (cch >= 17) { rhcPage = page[bfprop + 21] & 1; rHeaderFooter = page[bfprop + 21] & 6; rhcFirst = page[bfprop + 21] & 8; fGraphics = page[bfprop + 21] & 0x10; } for (int n = 0; n < 14; n++) { if (cch >= 4 * (n + 1) + 26) { dxaTab[tabs] = READ_WORD(page + bfprop + n * 4 + 27); jcTab[tabs] = page[bfprop + n * 4 + 29] & 3; tabs++; } } if (dxaRight & 0x8000) dxaRight = -0x10000 + dxaRight; if (dxaLeft & 0x8000) dxaLeft = -0x10000 + dxaLeft; if (dxaLeft1 & 0x8000) dxaLeft1 = -0x10000 + dxaLeft1; if (dyaLine < 240) dyaLine = 240; if (process == All && rHeaderFooter) { if (rhcPage) { if (!hasFooter) { hasFooter = true; page1Footer = rhcFirst; } } else { if (!hasHeader) { hasHeader = true; page1Header = rhcFirst; } } } } if ((process == All && !rHeaderFooter) || (rHeaderFooter && ((process == Header && !rhcPage) || (process == Footer && rhcPage)))) { UT_LocaleTransactor lt(LC_NUMERIC, "C"); UT_String_sprintf(properties, "text-align:%s; line-height:%.1f", text_align[jc], static_cast(dyaLine) / 240.0); if (tabs) { properties += "; tabstops:"; for (int n = 0; n < tabs; n++) { UT_String_sprintf(tmp, "%.4fin/%c0", static_cast(dxaTab[n]) / 1440.0, jcTab[n] ? 'D' : 'L'); properties += tmp; if (n != tabs - 1) properties += ","; } } if (process == Header || process == Footer) { // For reasons unknown, the left and right margins from the paper // are included in the indents of the headers and footers. dxaLeft -= xaLeft; dxaRight -= xaRight; } if (dxaLeft1) { UT_String_sprintf(tmp, "; text-indent:%.4fin", static_cast(dxaLeft1) / 1440.0); properties += tmp; } if (dxaLeft) { UT_String_sprintf(tmp, "; margin-left:%.4fin", static_cast(dxaLeft) / 1440.0); properties += tmp; } if (dxaRight) { UT_String_sprintf(tmp, "; margin-right:%.4fin", static_cast(dxaRight) / 1440.0); properties += tmp; } // new attributes, only if there was a line feed or FPROPs have changed if (lf || strcmp(properties.c_str(), lastprops.c_str()) != 0) { const gchar *attributes[3]; attributes[0] = PT_PROPS_ATTRIBUTE_NAME; attributes[1] = properties.c_str(); attributes[2] = NULL; appendStrux(PTX_Block, attributes); lastprops = properties; } if (fGraphics) read_pic(fcFirst, fcLim - fcFirst); else read_txt(fcFirst, fcLim - 1); } fcFirst = fcLim; if (fcLim >= fcMac) return true; } } } /********************************************************************** * MSWrite Importer (text handling) * **********************************************************************/ bool IE_Imp_MSWrite::read_txt (int from, int to) { static const char *currcp; int fcMac, pnChar, fcFirst, cfod, fc, fcLim; unsigned char page[0x80]; UT_String properties, tmp; int dataLen = static_cast(mData.getLength()); fcMac = wri_struct_value(wri_file_header, "fcMac"); pnChar = (fcMac + 127) / 128; fcFirst = 0x80; while (true) { gsf_input_seek(mFile, pnChar++ * 0x80, G_SEEK_SET); gsf_input_read(mFile, 0x80, page); cfod = page[0x7f]; fc = READ_DWORD(page); if (fc != fcFirst) fprintf(stderr, "read_txt: fcFirst wrong.\n"); // read all FODs (format descriptors) for (int fod = 0; fod < cfod; fod++) { int bfprop, cch, ftc, hps, fBold, fItalic, fUline, hpsPos; // read a FOD (format descriptor) fcLim = READ_DWORD(page + 4 + fod * 6); bfprop = READ_WORD(page + 8 + fod * 6); // default CHP values ftc = 0; hps = 24; fBold = fItalic = fUline = hpsPos = 0; // if the CHP FPROPs (formatting properties) differ from the defaults, get them if (bfprop != 0xffff && bfprop + (cch = page[bfprop + 4]) < 0x80) { if (cch >= 2) ftc = page[bfprop + 6] >> 2; if (cch >= 5) ftc |= (page[bfprop + 9] & 3) << 6; if (cch >= 3) hps = page[bfprop + 7]; if (cch >= 2) fBold = page[bfprop + 6] & 1; if (cch >= 2) fItalic = page[bfprop + 6] & 2; if (cch >= 4) fUline = page[bfprop + 8] & 1; if (cch >= 6) hpsPos = page[bfprop + 10]; } if (ftc >= wri_fonts_count) { fprintf(stderr, "read_txt: Wrong font code.\n"); ftc = wri_fonts_count - 1; } if (from < fcLim && to >= fcFirst) { UT_LocaleTransactor lt(LC_NUMERIC, "C"); UT_String_sprintf(properties, "font-weight:%s", fBold ? "bold" : "normal"); if (hps != 24) { UT_String_sprintf(tmp, "; font-size:%dpt", hps / 2); properties += tmp; } if (fItalic) properties += "; font-style:italic"; if (fUline) properties += "; text-decoration:underline"; if (hpsPos) { UT_String_sprintf(tmp, "; text-position:%s", hpsPos < 128 ? "superscript" : "subscript"); properties += tmp; } if (wri_fonts_count) { UT_String_sprintf(tmp, "; font-family:%s", wri_fonts[ftc].name); properties += tmp; } if (wri_fonts[ftc].codepage != currcp /*sic!*/) { set_codepage(wri_fonts[ftc].codepage); currcp = wri_fonts[ftc].codepage; } mText.clear(); while (fcFirst <= from && from < fcLim && from <= to && from - 0x80 < dataLen) translate_char(*mData.getPointer(from++ - 0x80), mText); // new attributes, only if there was text if (mText.size() > 0) { const gchar *attributes[5]; const UT_UCS4Char *text = mText.ucs4_str(), *p = text; size_t txtLen; attributes[0] = PT_PROPS_ATTRIBUTE_NAME; attributes[1] = properties.c_str(); attributes[2] = NULL; appendFmt(attributes); // check for page number (should only be in header or footer) while (*p && *p != (UT_UCS4Char) 0x01) p++; if (*p) { if (p - text) appendSpan(text, p - text); attributes[2] = PT_TYPE_ATTRIBUTE_NAME; attributes[3] = "page_number"; attributes[4] = NULL; appendObject(PTO_Field, attributes); txtLen = mText.size() - (p - text) - 1; p++; } else { txtLen = mText.size(); p = text; } if (txtLen) appendSpan(p, txtLen); } } fcFirst = fcLim; if (fcLim >= fcMac || fcFirst > to) return true; } } } /********************************************************************** * MSWrite Importer (character translation) * **********************************************************************/ static struct ffn_suff_cp { const char *suffix; const char *codepage; } const ffn_suff_cp_tbl[] = { {"\x03 CE", "CP1250"}, {"\x04 Cyr", "CP1251"}, {"\x06 Greek", "CP1253"}, {"\x04 Tur", "CP1254"}, {"\x09 (Hebrew)", "CP1255"}, {"\x09 (Arabic)", "CP1256"}, {"\x07 Baltic", "CP1257"}, {NULL, NULL} }; inline const char *IE_Imp_MSWrite::get_codepage (const char *facename, int *facelen) { const struct ffn_suff_cp *f = ffn_suff_cp_tbl; int l = strlen(facename); while (f->suffix) { if (*f->suffix < l) { if (g_ascii_strcasecmp(&f->suffix[1], &facename[l - *f->suffix]) == 0) { *facelen = l - *f->suffix; return f->codepage; } } f++; } *facelen = l; return default_codepage; } inline void IE_Imp_MSWrite::set_codepage (const char *charset) { charconv.setInCharset(charset); } inline void IE_Imp_MSWrite::translate_char (const UT_Byte ch, UT_UCS4String &buf) { UT_UCS4Char uch = ch; lf = false; switch (ch) { case 9: buf += UCS_TAB; break; case 12: buf += UCS_FF; break; case 10: // line feed lf = true; case 13: // carriage return case 31: // soft hyphen break; default: if (ch & 0x80) charconv.mbtowc(uch, ch); buf += uch; break; } } /********************************************************************** * MSWrite Importer (picture handling) * **********************************************************************/ bool IE_Imp_MSWrite::read_pic (int from, int size) { // 8 bit colormap (plus one extra color only in the 4 bit colormap) static const UT_Byte bgr_palette[257][4] = { {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x80, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00}, {0x00, 0x20, 0x00, 0x00}, {0x40, 0x20, 0x00, 0x00}, {0x80, 0x20, 0x00, 0x00}, {0xff, 0x20, 0x00, 0x00}, {0x00, 0x40, 0x00, 0x00}, {0x40, 0x40, 0x00, 0x00}, {0x80, 0x40, 0x00, 0x00}, {0xff, 0x40, 0x00, 0x00}, {0x00, 0x60, 0x00, 0x00}, {0x40, 0x60, 0x00, 0x00}, {0x80, 0x60, 0x00, 0x00}, {0xff, 0x60, 0x00, 0x00}, {0x00, 0x80, 0x00, 0x00}, {0x40, 0x80, 0x00, 0x00}, {0x80, 0x80, 0x00, 0x00}, {0xff, 0x80, 0x00, 0x00}, {0x00, 0xa0, 0x00, 0x00}, {0x40, 0xa0, 0x00, 0x00}, {0x80, 0xa0, 0x00, 0x00}, {0xff, 0xa0, 0x00, 0x00}, {0x00, 0xc0, 0x00, 0x00}, {0x40, 0xc0, 0x00, 0x00}, {0x80, 0xc0, 0x00, 0x00}, {0xff, 0xc0, 0x00, 0x00}, {0x00, 0xff, 0x00, 0x00}, {0x40, 0xff, 0x00, 0x00}, {0x80, 0xff, 0x00, 0x00}, {0xff, 0xff, 0x00, 0x00}, {0x00, 0x00, 0x20, 0x00}, {0x40, 0x00, 0x20, 0x00}, {0x80, 0x00, 0x20, 0x00}, {0xff, 0x00, 0x20, 0x00}, {0x00, 0x20, 0x20, 0x00}, {0x40, 0x20, 0x20, 0x00}, {0x80, 0x20, 0x20, 0x00}, {0xff, 0x20, 0x20, 0x00}, {0x00, 0x40, 0x20, 0x00}, {0x40, 0x40, 0x20, 0x00}, {0x80, 0x40, 0x20, 0x00}, {0xff, 0x40, 0x20, 0x00}, {0x00, 0x60, 0x20, 0x00}, {0x40, 0x60, 0x20, 0x00}, {0x80, 0x60, 0x20, 0x00}, {0xff, 0x60, 0x20, 0x00}, {0x00, 0x80, 0x20, 0x00}, {0x40, 0x80, 0x20, 0x00}, {0x80, 0x80, 0x20, 0x00}, {0xff, 0x80, 0x20, 0x00}, {0x00, 0xa0, 0x20, 0x00}, {0x40, 0xa0, 0x20, 0x00}, {0x80, 0xa0, 0x20, 0x00}, {0xff, 0xa0, 0x20, 0x00}, {0x00, 0xc0, 0x20, 0x00}, {0x40, 0xc0, 0x20, 0x00}, {0x80, 0xc0, 0x20, 0x00}, {0xff, 0xc0, 0x20, 0x00}, {0x00, 0xff, 0x20, 0x00}, {0x40, 0xff, 0x20, 0x00}, {0x80, 0xff, 0x20, 0x00}, {0xff, 0xff, 0x20, 0x00}, {0x00, 0x00, 0x40, 0x00}, {0x40, 0x00, 0x40, 0x00}, {0x80, 0x00, 0x40, 0x00}, {0xff, 0x00, 0x40, 0x00}, {0x00, 0x20, 0x40, 0x00}, {0x40, 0x20, 0x40, 0x00}, {0x80, 0x20, 0x40, 0x00}, {0xff, 0x20, 0x40, 0x00}, {0x00, 0x40, 0x40, 0x00}, {0x40, 0x40, 0x40, 0x00}, {0x80, 0x40, 0x40, 0x00}, {0xff, 0x40, 0x40, 0x00}, {0x00, 0x60, 0x40, 0x00}, {0x40, 0x60, 0x40, 0x00}, {0x80, 0x60, 0x40, 0x00}, {0xff, 0x60, 0x40, 0x00}, {0x00, 0x80, 0x40, 0x00}, {0x40, 0x80, 0x40, 0x00}, {0x80, 0x80, 0x40, 0x00}, {0xff, 0x80, 0x40, 0x00}, {0x00, 0xa0, 0x40, 0x00}, {0x40, 0xa0, 0x40, 0x00}, {0x80, 0xa0, 0x40, 0x00}, {0xff, 0xa0, 0x40, 0x00}, {0x00, 0xc0, 0x40, 0x00}, {0x40, 0xc0, 0x40, 0x00}, {0x80, 0xc0, 0x40, 0x00}, {0xff, 0xc0, 0x40, 0x00}, {0x00, 0xff, 0x40, 0x00}, {0x40, 0xff, 0x40, 0x00}, {0x80, 0xff, 0x40, 0x00}, {0xff, 0xff, 0x40, 0x00}, {0x00, 0x00, 0x60, 0x00}, {0x40, 0x00, 0x60, 0x00}, {0x80, 0x00, 0x60, 0x00}, {0xff, 0x00, 0x60, 0x00}, {0x00, 0x20, 0x60, 0x00}, {0x40, 0x20, 0x60, 0x00}, {0x80, 0x20, 0x60, 0x00}, {0xff, 0x20, 0x60, 0x00}, {0x00, 0x40, 0x60, 0x00}, {0x40, 0x40, 0x60, 0x00}, {0x80, 0x40, 0x60, 0x00}, {0xff, 0x40, 0x60, 0x00}, {0x00, 0x60, 0x60, 0x00}, {0x40, 0x60, 0x60, 0x00}, {0x80, 0x60, 0x60, 0x00}, {0xff, 0x60, 0x60, 0x00}, {0x00, 0x80, 0x60, 0x00}, {0x40, 0x80, 0x60, 0x00}, {0x80, 0x80, 0x60, 0x00}, {0xff, 0x80, 0x60, 0x00}, {0x00, 0xa0, 0x60, 0x00}, {0x40, 0xa0, 0x60, 0x00}, {0x80, 0xa0, 0x60, 0x00}, {0xff, 0xa0, 0x60, 0x00}, {0x00, 0xc0, 0x60, 0x00}, {0x40, 0xc0, 0x60, 0x00}, {0x80, 0xc0, 0x60, 0x00}, {0xff, 0xc0, 0x60, 0x00}, {0x00, 0xff, 0x60, 0x00}, {0x40, 0xff, 0x60, 0x00}, {0x80, 0xff, 0x60, 0x00}, {0xff, 0xff, 0x60, 0x00}, {0x00, 0x00, 0x80, 0x00}, {0x40, 0x00, 0x80, 0x00}, {0x80, 0x00, 0x80, 0x00}, {0xff, 0x00, 0x80, 0x00}, {0x00, 0x20, 0x80, 0x00}, {0x40, 0x20, 0x80, 0x00}, {0x80, 0x20, 0x80, 0x00}, {0xff, 0x20, 0x80, 0x00}, {0x00, 0x40, 0x80, 0x00}, {0x40, 0x40, 0x80, 0x00}, {0x80, 0x40, 0x80, 0x00}, {0xff, 0x40, 0x80, 0x00}, {0x00, 0x60, 0x80, 0x00}, {0x40, 0x60, 0x80, 0x00}, {0x80, 0x60, 0x80, 0x00}, {0xff, 0x60, 0x80, 0x00}, {0x00, 0x80, 0x80, 0x00}, {0x40, 0x80, 0x80, 0x00}, {0x80, 0x80, 0x80, 0x00}, {0xff, 0x80, 0x80, 0x00}, {0x00, 0xa0, 0x80, 0x00}, {0x40, 0xa0, 0x80, 0x00}, {0x80, 0xa0, 0x80, 0x00}, {0xff, 0xa0, 0x80, 0x00}, {0x00, 0xc0, 0x80, 0x00}, {0x40, 0xc0, 0x80, 0x00}, {0x80, 0xc0, 0x80, 0x00}, {0xff, 0xc0, 0x80, 0x00}, {0x00, 0xff, 0x80, 0x00}, {0x40, 0xff, 0x80, 0x00}, {0x80, 0xff, 0x80, 0x00}, {0xff, 0xff, 0x80, 0x00}, {0x00, 0x00, 0xa0, 0x00}, {0x40, 0x00, 0xa0, 0x00}, {0x80, 0x00, 0xa0, 0x00}, {0xff, 0x00, 0xa0, 0x00}, {0x00, 0x20, 0xa0, 0x00}, {0x40, 0x20, 0xa0, 0x00}, {0x80, 0x20, 0xa0, 0x00}, {0xff, 0x20, 0xa0, 0x00}, {0x00, 0x40, 0xa0, 0x00}, {0x40, 0x40, 0xa0, 0x00}, {0x80, 0x40, 0xa0, 0x00}, {0xff, 0x40, 0xa0, 0x00}, {0x00, 0x60, 0xa0, 0x00}, {0x40, 0x60, 0xa0, 0x00}, {0x80, 0x60, 0xa0, 0x00}, {0xff, 0x60, 0xa0, 0x00}, {0x00, 0x80, 0xa0, 0x00}, {0x40, 0x80, 0xa0, 0x00}, {0x80, 0x80, 0xa0, 0x00}, {0xff, 0x80, 0xa0, 0x00}, {0x00, 0xa0, 0xa0, 0x00}, {0x40, 0xa0, 0xa0, 0x00}, {0x80, 0xa0, 0xa0, 0x00}, {0xff, 0xa0, 0xa0, 0x00}, {0x00, 0xc0, 0xa0, 0x00}, {0x40, 0xc0, 0xa0, 0x00}, {0x80, 0xc0, 0xa0, 0x00}, {0xff, 0xc0, 0xa0, 0x00}, {0x00, 0xff, 0xa0, 0x00}, {0x40, 0xff, 0xa0, 0x00}, {0x80, 0xff, 0xa0, 0x00}, {0xff, 0xff, 0xa0, 0x00}, {0x00, 0x00, 0xc0, 0x00}, {0x40, 0x00, 0xc0, 0x00}, {0x80, 0x00, 0xc0, 0x00}, {0xff, 0x00, 0xc0, 0x00}, {0x00, 0x20, 0xc0, 0x00}, {0x40, 0x20, 0xc0, 0x00}, {0x80, 0x20, 0xc0, 0x00}, {0xff, 0x20, 0xc0, 0x00}, {0x00, 0x40, 0xc0, 0x00}, {0x40, 0x40, 0xc0, 0x00}, {0x80, 0x40, 0xc0, 0x00}, {0xff, 0x40, 0xc0, 0x00}, {0x00, 0x60, 0xc0, 0x00}, {0x40, 0x60, 0xc0, 0x00}, {0x80, 0x60, 0xc0, 0x00}, {0xff, 0x60, 0xc0, 0x00}, {0x00, 0x80, 0xc0, 0x00}, {0x40, 0x80, 0xc0, 0x00}, {0x80, 0x80, 0xc0, 0x00}, {0xff, 0x80, 0xc0, 0x00}, {0x00, 0xa0, 0xc0, 0x00}, {0x40, 0xa0, 0xc0, 0x00}, {0x80, 0xa0, 0xc0, 0x00}, {0xff, 0xa0, 0xc0, 0x00}, {0x00, 0xc0, 0xc0, 0x00}, {0x40, 0xc0, 0xc0, 0x00}, {0x80, 0xc0, 0xc0, 0x00}, {0xff, 0xc0, 0xc0, 0x00}, {0x00, 0xff, 0xc0, 0x00}, {0x40, 0xff, 0xc0, 0x00}, {0x80, 0xff, 0xc0, 0x00}, {0xff, 0xff, 0xc0, 0x00}, {0x00, 0x00, 0xff, 0x00}, {0x40, 0x00, 0xff, 0x00}, {0x80, 0x00, 0xff, 0x00}, {0xff, 0x00, 0xff, 0x00}, {0x00, 0x20, 0xff, 0x00}, {0x40, 0x20, 0xff, 0x00}, {0x80, 0x20, 0xff, 0x00}, {0xff, 0x20, 0xff, 0x00}, {0x00, 0x40, 0xff, 0x00}, {0x40, 0x40, 0xff, 0x00}, {0x80, 0x40, 0xff, 0x00}, {0xff, 0x40, 0xff, 0x00}, {0x00, 0x60, 0xff, 0x00}, {0x40, 0x60, 0xff, 0x00}, {0x80, 0x60, 0xff, 0x00}, {0xff, 0x60, 0xff, 0x00}, {0x00, 0x80, 0xff, 0x00}, {0x40, 0x80, 0xff, 0x00}, {0x80, 0x80, 0xff, 0x00}, {0xff, 0x80, 0xff, 0x00}, {0x00, 0xa0, 0xff, 0x00}, {0x40, 0xa0, 0xff, 0x00}, {0x80, 0xa0, 0xff, 0x00}, {0xff, 0xa0, 0xff, 0x00}, {0x00, 0xc0, 0xff, 0x00}, {0x40, 0xc0, 0xff, 0x00}, {0x80, 0xc0, 0xff, 0x00}, {0xff, 0xc0, 0xff, 0x00}, {0x00, 0xff, 0xff, 0x00}, {0x40, 0xff, 0xff, 0x00}, {0x80, 0xff, 0xff, 0x00}, {0xff, 0xff, 0xff, 0x00}, {0xc0, 0xc0, 0xc0, 0x00} // a color only in the 4 bit colormap }; // indices (of the 8 bit colormap above) for the 4 bit colormap static const int c16idx[16] = { 0, 128, 16, 144, 2, 130, 18, 256, 146, 224, 28, 252, 3, 227, 31, 255 }; // structs without alignment #pragma pack(push) #pragma pack(1) struct { char bfType[2]; uint32_t bfSize; uint32_t bfReserved; uint32_t bfOffBits; } bmpheader; struct { uint32_t header_sz; uint32_t width; uint32_t height; uint16_t nplanes; uint16_t bitspp; uint32_t compress_type; uint32_t bmp_bytesz; uint32_t hres; uint32_t vres; uint32_t ncolors; uint32_t nimpcolors; } bmpinfo; #pragma pack(pop) unsigned char page[0x80]; int mm, cbHeader, cbSize, bmBitsPixel, objectType; int colorPaletteLen = 0, bmW = 0, bmH = 0; int chunk, filler, written, ole_offset, formatID, objLen, bhSize, bppOff; wri_struct *write_pic = NULL; UT_ByteBuf pic; IEGraphicFileType iegft = IEGFT_Unknown; const char *msg = NULL, *className = ""; FG_Graphic *graphic = NULL; if (size < PIC_OR_OLE_HEADER_SIZE + OLE_ClassNameString) { fprintf(stderr, "read_pic: Size error, type 1!\n"); return false; } // prepare bmp file header memset(&bmpheader, 0, sizeof(bmpheader)); bmpheader.bfType[0] = 'B'; bmpheader.bfType[1] = 'M'; memset(&bmpinfo, 0, sizeof(bmpinfo)); gsf_input_seek(mFile, from, G_SEEK_SET); gsf_input_read(mFile, sizeof(page), page); mm = READ_WORD(page); switch (mm) { case 0x88: // wmf file case 0xe3: // bitmap write_pic = wri_picture_header; read_wri_struct_mem(write_pic, page); cbHeader = wri_struct_value(write_pic, "cbHeader"); cbSize = wri_struct_value(write_pic, "cbSize"); if (size < cbHeader + cbSize) { msg = "read_pic: Size error, type 2!\n"; break; } if (mm == 0xe3) // bitmap needs header { if ((bmBitsPixel = wri_struct_value(write_pic, "bmBitsPixel")) < 16) colorPaletteLen = (1 << bmBitsPixel) << 2; if (colorPaletteLen != 8) { msg = "read_pic: Color palette error!\n"; break; } // make a bitmap file header WRITE_DWORD(bmpheader.bfOffBits, sizeof(bmpheader) + sizeof(bmpinfo) + colorPaletteLen); pic.append(reinterpret_cast(&bmpheader), sizeof(bmpheader)); bmW = wri_struct_value(write_pic, "bmWidth"); bmH = wri_struct_value(write_pic, "bmHeight"); if (bmH & 0x8000) bmH = -0x10000 + bmH; WRITE_DWORD(bmpinfo.header_sz, sizeof(bmpinfo)); WRITE_DWORD(bmpinfo.width, bmW); WRITE_DWORD(bmpinfo.height, -bmH); WRITE_WORD(bmpinfo.nplanes, wri_struct_value(write_pic, "bmPlanes")); WRITE_WORD(bmpinfo.bitspp, bmBitsPixel); pic.append(reinterpret_cast(&bmpinfo), sizeof(bmpinfo)); // add monochrome colormap pic.append(bgr_palette[0], colorPaletteLen >> 1); pic.append(bgr_palette[255], colorPaletteLen >> 1); chunk = wri_struct_value(write_pic, "bmWidthBytes"); filler = (4 - (chunk & 3)) & 3; } else { iegft = IEGFT_WMF; chunk = cbSize; filler = 0; } written = 0; while (written < cbSize) { // append data pic.append(mData.getPointer(from - 0x80 + cbHeader + written), chunk); for (int i = 0; i < filler; i++) pic.append(reinterpret_cast("\x00"), 1); written += chunk; } break; case 0xe4: // ole object write_pic = wri_ole_header; read_wri_struct_mem(write_pic, page); objectType = wri_struct_value(write_pic, "objectType"); cbHeader = wri_struct_value(write_pic, "cbHeader"); if ((ole_offset = READ_DWORD(page + cbHeader + OLE_ClassNameLength)) > 0) className = reinterpret_cast(page + cbHeader + OLE_ClassNameString); if ((formatID = READ_DWORD(page + cbHeader + OLE_FormatID)) == 1 || formatID == 2) { if (size < cbHeader + OLE_TopicNameString + ole_offset) { msg = "read_pic: Size error, type 3!\n"; break; } ole_offset += READ_DWORD(page + cbHeader + OLE_TopicNameLength + ole_offset); if (size < cbHeader + OLE_ItemNameString + ole_offset) { msg = "read_pic: Size error, type 4!\n"; break; } ole_offset += READ_DWORD(page + cbHeader + OLE_ItemNameLength + ole_offset); } objLen = READ_DWORD(page + cbHeader + OLE_ObjDataSize + ole_offset); if (strcmp(className, "METAFILEPICT") == 0) { iegft = IEGFT_WMF; ole_offset += OLE_MF_Object - OLE_Object; objLen -= OLE_MF_Object - OLE_Object; objectType = 2; // we can go embedded now } if (size <= cbHeader + OLE_Object + ole_offset || cbHeader + OLE_Object + ole_offset > 0x80 || size < cbHeader + OLE_Object + ole_offset + objLen) { msg = "read_pic: Size error, type 5!\n"; break; } // static if (objectType == 1) { if (strcmp(className, "DIB") == 0) { bhSize = READ_DWORD(page + cbHeader + OLE_Object + ole_offset); bppOff = (bhSize == 12 ? 10 : 14); // different header info types if ((bmBitsPixel = READ_WORD(page + cbHeader + OLE_Object + ole_offset + bppOff)) < 16) colorPaletteLen = (1 << bmBitsPixel) << 2; // make a bitmap file header WRITE_DWORD(bmpheader.bfOffBits, sizeof(bmpheader) + bhSize + colorPaletteLen); pic.append(reinterpret_cast(&bmpheader), sizeof(bmpheader)); objectType = 2; // we can go embedded now } if (strcmp(className, "BITMAP") == 0) { if ((bmBitsPixel = *(page + cbHeader + OLE_Object + ole_offset + BM16_BitsPixel)) < 16) colorPaletteLen = (1 << bmBitsPixel) << 2; // make a bitmap file header WRITE_DWORD(bmpheader.bfOffBits, sizeof(bmpheader) + sizeof(bmpinfo) + colorPaletteLen); pic.append(reinterpret_cast(&bmpheader), sizeof(bmpheader)); bmH = READ_WORD(page + cbHeader + OLE_Object + ole_offset + BM16_Height); if (bmH & 0x8000) bmH = -0x10000 + bmH; WRITE_DWORD(bmpinfo.header_sz, sizeof(bmpinfo)); WRITE_DWORD(bmpinfo.width, READ_WORD(page + cbHeader + OLE_Object + ole_offset + BM16_Width)); WRITE_DWORD(bmpinfo.height, bmH); WRITE_WORD(bmpinfo.nplanes, *(page + cbHeader + OLE_Object + ole_offset + BM16_Planes)); WRITE_WORD(bmpinfo.bitspp, bmBitsPixel); pic.append(reinterpret_cast(&bmpinfo), sizeof(bmpinfo)); // add corresponding colormap switch (bmBitsPixel) { case 1: pic.append(bgr_palette[0], colorPaletteLen >> 1); pic.append(bgr_palette[255], colorPaletteLen >> 1); break; case 4: for (int i = 0; i < 16; i++) pic.append(bgr_palette[c16idx[i]], 4); break; case 8: pic.append(bgr_palette[0], colorPaletteLen); break; } ole_offset += BM16_Bits; objectType = 2; // we can go embedded now } } // embedded if (objectType == 2) pic.append(mData.getPointer(from - 0x80 + cbHeader + OLE_Object + ole_offset), objLen); break; } // let's see... if (pic.getLength()) { // ...whether it's a picture if (IE_ImpGraphic::loadGraphic(pic, iegft, &graphic) != UT_OK || !graphic) msg = "read_pic: Picture load error or no picture!\n"; else { int dxaOffset, dxaSize, dyaSize, mx, my; const gchar *attributes[5]; UT_String properties, id; UT_LocaleTransactor lt(LC_NUMERIC, "C"); dxaOffset = wri_struct_value(write_pic, "dxaOffset"); if (dxaOffset & 0x8000) dxaOffset = -0x10000 + dxaOffset; if (dxaOffset) { UT_String_sprintf(properties, "margin-left:%.4fin", static_cast(dxaOffset) / 1440.0); attributes[0] = PT_PROPS_ATTRIBUTE_NAME; attributes[1] = properties.c_str(); attributes[2] = NULL; appendStrux(PTX_Block, attributes); } dxaSize = wri_struct_value(write_pic, "dxaSize"); dyaSize = wri_struct_value(write_pic, "dyaSize"); if (dxaSize == 0) dxaSize = wri_struct_value(write_pic, "xExt"); if (dyaSize == 0) dyaSize = wri_struct_value(write_pic, "yExt"); if (dxaSize & 0x8000) dxaSize = -0x10000 + dxaSize; if (dyaSize & 0x8000) dyaSize = -0x10000 + dyaSize; mx = wri_struct_value(write_pic, "mx"); my = wri_struct_value(write_pic, "my"); // 0xe3 picture sizes aren't reliable, so we recalculate them // (1 pixel = 15 twips) if (mm == 0xe3) { dxaSize = bmW * 15; dyaSize = (bmH < 0 ? -bmH : bmH) * 15; } UT_String_sprintf(properties, "width:%.4fin; height:%.4fin", static_cast(mx) / 1000.0 * static_cast(dxaSize) / 1440.0, static_cast(my) / 1000.0 * static_cast(dyaSize) / 1440.0); UT_String_sprintf(id, "image%u", ++pic_nr); attributes[0] = PT_PROPS_ATTRIBUTE_NAME; attributes[1] = properties.c_str(); attributes[2] = "dataid"; attributes[3] = id.c_str(); attributes[4] = NULL; appendObject(PTO_Image, attributes); getDoc()->createDataItem(id.c_str(), false, graphic->getBuffer(), graphic->getMimeType(), NULL); } } DELETEP(graphic); if (write_pic) free_wri_struct(write_pic); if (msg) fprintf(stderr, msg); return (msg ? false : true); } /********************************************************************** * MSWrite Importer (header and footer opening) * **********************************************************************/ void IE_Imp_MSWrite::_append_hdrftr (hdrftr_t which) { const gchar *attributes[5]; attributes[0] = PT_ID_ATTRIBUTE_NAME; attributes[2] = PT_TYPE_ATTRIBUTE_NAME; attributes[4] = NULL; switch (which) { case headerfirst: attributes[1] = "0"; attributes[3] = "header-first"; break; case header: attributes[1] = "1"; attributes[3] = "header"; break; case footerfirst: attributes[1] = "2"; attributes[3] = "footer-first"; break; case footer: attributes[1] = "3"; attributes[3] = "footer"; break; } appendStrux(PTX_Section, attributes); }