/* AbiWord * Copyright (C) 2001 AbiSource, Inc. * Copyright (C) 2002-2004 Marc Maurer (j.m.maurer@student.utwente.nl) * Copyright (C) 2002-2005 William Lachance (william.lachance@sympatico.ca) * * 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. */ /* See bug 1764 * "This product is not manufactured, approved, or supported by * Corel Corporation or Corel Corporation Limited." */ #include #include #include #include #include #include #include #include #include #include "ut_types.h" #include "ut_string.h" #include "ut_string_class.h" #include "ut_units.h" #include "ut_growbuf.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "ut_math.h" // for rint (font size) #include "ut_rand.h" #include "xap_Frame.h" #include "xap_EncodingManager.h" #include "pd_Document.h" #include "pt_Types.h" #include "fl_AutoLists.h" #include "fl_AutoNum.h" #include "ap_Strings.h" #include "ie_imp_WordPerfect.h" #include "ie_impexp_WordPerfect.h" // This should probably be defined in pt_Types.h static const UT_uint32 PT_MAX_ATTRIBUTES = 8; ABI_ListDefinition::ABI_ListDefinition(int iOutlineHash) : m_iOutlineHash(iOutlineHash) { for(int i=0; i(szBuf), iNumbytes, false)); GSFInputStream gsfInput(input); WPDConfidence confidence = WPDocument::isFileFormatSupported(&gsfInput, true); g_object_unref(input); switch (confidence) { case WPD_CONFIDENCE_NONE: // libwpd > 0.7.1 reports POOR if the text file is plain text (that _could_ be a WP4x document) // however, we'll let the text importer handle such cases case WPD_CONFIDENCE_POOR: return UT_CONFIDENCE_ZILCH; return UT_CONFIDENCE_POOR; case WPD_CONFIDENCE_LIKELY: return UT_CONFIDENCE_SOSO; case WPD_CONFIDENCE_GOOD: return UT_CONFIDENCE_GOOD; case WPD_CONFIDENCE_EXCELLENT: return UT_CONFIDENCE_PERFECT; default: return UT_CONFIDENCE_ZILCH; } } UT_Confidence_t IE_Imp_WordPerfect_Sniffer::recognizeSuffix (const char * szSuffix) { // We recognize both word documents and their template versions if (!UT_stricmp(szSuffix,".wpd") || !UT_stricmp(szSuffix, ".wp")) return UT_CONFIDENCE_PERFECT; return UT_CONFIDENCE_ZILCH; } UT_Error IE_Imp_WordPerfect_Sniffer::constructImporter (PD_Document * pDocument, IE_Imp ** ppie) { *ppie = new IE_Imp_WordPerfect(pDocument); return UT_OK; } bool IE_Imp_WordPerfect_Sniffer::getDlgLabels (const char ** pszDesc, const char ** pszSuffixList, IEFileType * ft) { *pszDesc = "WordPerfect (.wpd, .wp)"; *pszSuffixList = "*.wpd; *.wp"; *ft = getFileType(); return true; } /****************************************************************************/ /****************************************************************************/ IE_Imp_WordPerfect::IE_Imp_WordPerfect(PD_Document * pDocument) : IE_Imp (pDocument), m_bParagraphChanged(false), m_bParagraphInSection(false), m_bInSection(false), m_bSectionChanged(false), m_leftMargin(0.0f), m_rightMargin(0.0f), m_headerId(-1), m_footerId(-1), m_nextFreeId(0), m_leftMarginOffset(0.0f), m_rightMarginOffset(0.0f), m_pCurrentListDefinition(NULL), m_iCurrentListLevel(0), m_bInCell(false), m_bHdrFtrOpenCount(0) { } IE_Imp_WordPerfect::~IE_Imp_WordPerfect() { //UT_HASH_PURGEDATA(ABI_ListDefinition *,&m_listStylesHash,delete); } UT_Error IE_Imp_WordPerfect::importFile(const char * szFilename) { gsf_init (); GError *err; GsfInput * input; input = GSF_INPUT(gsf_input_stdio_new (szFilename, &err)); if (input == NULL) { g_return_val_if_fail (err != NULL, 1); g_warning ("'%s' error: %s", szFilename, err->message); g_error_free (err); return 1; } GSFInputStream gsfInput(input); WPDResult error = WPDocument::parse(&gsfInput, static_cast(this)); gsf_shutdown(); if (error != WPD_OK) { UT_DEBUGMSG(("AbiWordPerfect: ERROR: %i!\n", (int)error)); return UT_IE_IMPORTERROR; } return UT_OK; } void IE_Imp_WordPerfect::pasteFromBuffer (PD_DocumentRange *, unsigned char *, unsigned int, const char *) { // nada } void IE_Imp_WordPerfect::setDocumentMetaData(const WPXPropertyList &propList) { if (propList["dc:author"]) getDoc()->setMetaDataProp(PD_META_KEY_CREATOR, propList["dc:author"]->getStr().cstr()); if (propList["dc:subject"]) getDoc()->setMetaDataProp(PD_META_KEY_SUBJECT, propList["dc:subject"]->getStr().cstr()); if (propList["dc:publisher"]) getDoc()->setMetaDataProp(PD_META_KEY_PUBLISHER, propList["dc:publisher"]->getStr().cstr()); if (propList["dc:type"]) getDoc()->setMetaDataProp(PD_META_KEY_TYPE, propList["dc:category"]->getStr().cstr()); if (propList["libwpd:keywords"]) getDoc()->setMetaDataProp(PD_META_KEY_KEYWORDS, propList["libwpd:keywords"]->getStr().cstr()); if (propList["dc:language"]) getDoc()->setMetaDataProp(PD_META_KEY_LANGUAGE, propList["dc:language"]->getStr().cstr()); if (propList["libwpd:abstract"]) getDoc()->setMetaDataProp(PD_META_KEY_DESCRIPTION, propList["libwpd:abstract"]->getStr().cstr()); } void IE_Imp_WordPerfect::startDocument() { UT_DEBUGMSG(("AbiWordPerfect: startDocument\n")); } void IE_Imp_WordPerfect::endDocument() { UT_DEBUGMSG(("AbiWordPerfect: endDocument\n")); } void IE_Imp_WordPerfect::openPageSpan(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: openPageSpan\n")); float marginLeft = 0.0f, marginRight = 0.0f; if (propList["fo:margin-left"]) marginLeft = propList["fo:margin-left"]->getFloat(); if (propList["fo:margin-right"]) marginRight = propList["fo:margin-right"]->getFloat(); if ( marginLeft != m_leftMargin || marginRight != m_rightMargin //|| //marginTop != m_marginBottom "" //marginBottom != m_marginBottom ) { m_leftMargin = marginLeft; m_rightMargin = marginRight; // margin properties are section properties in AbiWord m_bSectionChanged; } } void IE_Imp_WordPerfect::openHeader(const WPXPropertyList &propList) { m_bHdrFtrOpenCount++; /* TODO: THIS CODE IS NOT!!!! USEFULL! - DON'T TOUCH IT - MARCM UT_String propBuffer; switch (headerFooterType) { case HEADER: m_headerId = m_nextFreeId; UT_String_sprintf(propBuffer,"id:%d; listid:0; parentid=0; type=header", m_headerId); break; case FOOTER: m_footerId = m_nextFreeId; UT_String_sprintf(propBuffer,"id:%d; listid:0; parentid=0; type=footer", m_footerId); break; default: UT_ASSERT(SHOULD_NOT_HAPPEN); break; } const XML_Char* propsArray[3]; propsArray[0] = "props"; propsArray[1] = propBuffer.c_str(); propsArray[2] = NULL; X_CheckDocumentError(appendStrux(PTX_Section, propsArray)); m_bInSection = true; m_bSectionChanged = false;*/ } void IE_Imp_WordPerfect::closeHeader() { m_bHdrFtrOpenCount--; /* TODO: THIS CODE IS NOT!!!! USEFULL! - DON'T TOUCH IT - MARCM m_nextFreeId++; */ } void IE_Imp_WordPerfect::openFooter(const WPXPropertyList &propList) { m_bHdrFtrOpenCount++; // see above comments re: openHeader } void IE_Imp_WordPerfect::closeFooter() { m_bHdrFtrOpenCount--; // see above comments re: closeHeader } void IE_Imp_WordPerfect::openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: openParagraph()\n")); // for now, we always append these options float marginTop = 0.0f, marginBottom = 0.0f; float marginLeft = 0.0f, marginRight = 0.0f, textIndent = 0.0f; if (propList["fo:margin-top"]) marginTop = propList["fo:margin-top"]->getFloat(); if (propList["fo:margin-bottom"]) marginBottom = propList["fo:margin-bottom"]->getFloat(); if (propList["fo:margin-left"]) marginLeft = propList["fo:margin-left"]->getFloat(); if (propList["fo:margin-right"]) marginRight = propList["fo:margin-right"]->getFloat(); if (propList["fo:text-indent"]) textIndent = propList["fo:text-indent"]->getFloat(); m_topMargin = marginTop; m_bottomMargin = marginBottom; m_leftMarginOffset = marginLeft; m_rightMarginOffset = marginRight; m_textIndent = textIndent; UT_String propBuffer; propBuffer += "text-align:"; if (propList["fo:text-align"]) { // AbiWord follows xsl:fo, except here, for some reason.. if (propList["fo:text-align"]->getStr() == "end") propBuffer += "right"; else propBuffer += propList["fo:text-align"]->getStr().cstr(); } else propBuffer += "left"; float lineSpacing = 1.0f; if (propList["fo:line-height"]) lineSpacing = propList["fo:line-height"]->getFloat(); UT_String tmpBuffer; UT_String_sprintf(tmpBuffer, "; margin-top:%.4fin; margin-bottom:%.4fin; margin-left:%.4fin; margin-right:%.4fin; text-indent:%.4fin; line-height:%.4f", m_topMargin, m_bottomMargin, m_leftMarginOffset, m_rightMarginOffset, m_textIndent, lineSpacing); propBuffer += tmpBuffer; UT_DEBUGMSG(("AbiWordPerfect: Appending paragraph properties: %s\n", propBuffer.c_str())); const XML_Char* propsArray[3]; propsArray[0] = "props"; propsArray[1] = propBuffer.c_str(); propsArray[2] = NULL; X_CheckDocumentError(appendStrux(PTX_Block, propsArray)); if (propList["fo:break-before"]) { if (strcmp(propList["fo:break-before"]->getStr().cstr(), "page") == 0) { UT_UCS4Char ucs = UCS_FF; X_CheckDocumentError(appendSpan(&ucs,1)); } else if (strcmp(propList["fo:break-before"]->getStr().cstr(), "column") == 0) { UT_UCS4Char ucs = UCS_VTAB; X_CheckDocumentError(appendSpan(&ucs,1)); } } } void IE_Imp_WordPerfect::openSpan(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: Appending current text properties\n")); XML_Char* pProps = "props"; UT_String propBuffer; UT_String tempBuffer; // bold propBuffer += "font-weight:"; propBuffer += (propList["fo:font-weight"] ? propList["fo:font-weight"]->getStr().cstr() : "normal"); // italic propBuffer += "; font-style:"; propBuffer += (propList["fo:font-style"] ? propList["fo:font-style"]->getStr().cstr() : "normal"); // superscript or subscript if (propList["style:text-position"]) { propBuffer += "; text-position:"; if (strncmp(propList["style:text-position"]->getStr().cstr(), "super", 5) == 0) propBuffer += "superscript"; else propBuffer += "subscript"; } if (propList["style:text-underline"] || propList["style:text-crossing-out"]) { propBuffer += "; text-decoration:"; if (propList["style:text-underline"]) propBuffer += "underline "; if (propList["style:text-crossing-out"]) propBuffer += "line-through"; } if (propList["style:font-name"]) { propBuffer += "; font-family:"; propBuffer += propList["style:font-name"]->getStr().cstr(); } // font face if (propList["fo:font-size"]) { propBuffer += "; font-size:"; propBuffer += propList["fo:font-size"]->getStr().cstr(); } if (propList["fo:color"]) { propBuffer += "; color:"; propBuffer += propList["fo:color"]->getStr().cstr(); } if (propList["style:text-background-color"]) { propBuffer += "; bgcolor:"; propBuffer += propList["style:text-background-color"]->getStr().cstr(); } UT_DEBUGMSG(("AbiWordPerfect: Appending span format: %s\n", propBuffer.c_str())); const XML_Char* propsArray[5]; propsArray[0] = pProps; propsArray[1] = propBuffer.c_str(); propsArray[2] = NULL; X_CheckDocumentError(appendFmt(propsArray)); } void IE_Imp_WordPerfect::openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: openSection\n")); // TODO: support spaceAfter if (propList["fo:margin-left"]) m_leftMargin = propList["fo:margin-left"]->getFloat(); if (propList["fo:margin-right"]) m_rightMargin = propList["fo:margin-right"]->getFloat(); _appendSection((columns.count() == 0) ? 1 : columns.count(), m_leftMargin, m_rightMargin); } void IE_Imp_WordPerfect::insertTab() { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: insertTab\n")); UT_UCS4Char ucs = UCS_TAB; X_CheckDocumentError(appendSpan(&ucs,1)); } void IE_Imp_WordPerfect::insertText(const WPXString &text) { if (m_bHdrFtrOpenCount) return; // HACK if (text.len()) { UT_DEBUGMSG(("AbiWordPerfect: insertText\n")); UT_UCS4String ucs4(text.cstr()); X_CheckDocumentError(appendSpan(ucs4.ucs4_str(), ucs4.length())); } } void IE_Imp_WordPerfect::insertLineBreak() { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: insertLineBreak\n")); UT_UCSChar ucs = UCS_LF; X_CheckDocumentError(appendSpan(&ucs,1)); } void IE_Imp_WordPerfect::defineOrderedListLevel(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: defineOrderedListLevel\n")); int listID = 0, startingNumber = 0, level = 1; char listType = '1'; UT_UTF8String textBeforeNumber, textAfterNumber; if (propList["libwpd:id"]) listID = propList["libwpd:id"]->getInt(); if (propList["text:start-value"]) startingNumber = propList["text:start-value"]->getInt(); if (propList["libwpd:level"]) level = propList["libwpd:level"]->getInt(); if (propList["style:num-prefix"]) textBeforeNumber += propList["style:num-prefix"]->getStr().cstr(); if (propList["style:num-suffix"]) textAfterNumber += propList["style:num-suffix"]->getStr().cstr(); if (propList["style:num-format"]) { listType = propList["style:num-format"]->getStr().cstr()[0]; } if (!m_pCurrentListDefinition || m_pCurrentListDefinition->getOutlineHash() != listID || (m_pCurrentListDefinition->getLevelNumber(level) != startingNumber && level == 1)) { if (m_pCurrentListDefinition) delete (m_pCurrentListDefinition); m_pCurrentListDefinition = new ABI_ListDefinition(listID); } if (!m_pCurrentListDefinition->getListID(level)) { m_pCurrentListDefinition->setListType(level, listType); m_pCurrentListDefinition->setListID(level, UT_rand()); _updateDocumentOrderedListDefinition(m_pCurrentListDefinition, level, listType, textBeforeNumber, textAfterNumber, startingNumber); } } void IE_Imp_WordPerfect::defineUnorderedListLevel(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: defineUnorderedListLevel\n")); int listID = 0, level = 1; WPXString textBeforeNumber, textAfterNumber; if (propList["libwpd:id"]) listID = propList["libwpd:id"]->getInt(); if (propList["libwpd:level"]) level = propList["libwpd:level"]->getInt(); if (!m_pCurrentListDefinition || m_pCurrentListDefinition->getOutlineHash() != listID) { if (m_pCurrentListDefinition) delete (m_pCurrentListDefinition); m_pCurrentListDefinition = new ABI_ListDefinition(listID); } if (!m_pCurrentListDefinition->getListID(level)) { m_pCurrentListDefinition->setListID(level, UT_rand()); _updateDocumentUnorderedListDefinition(m_pCurrentListDefinition, level); } } //void IE_Imp_WordPerfect::openOrderedListLevel(const int listID) void IE_Imp_WordPerfect::openOrderedListLevel(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: openOrderedListLevel\n")); m_iCurrentListLevel++; } void IE_Imp_WordPerfect::closeOrderedListLevel() { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: closeOrderedListLevel (level: %i)\n", m_iCurrentListLevel)); UT_ASSERT(m_iCurrentListLevel > 0); // every time we close a list level, the level above it is normally renumbered to start at "1" // again. this code takes care of that. if (m_iCurrentListLevel < (WP6_NUM_LIST_LEVELS-1)) m_pCurrentListDefinition->setLevelNumber(m_iCurrentListLevel + 1, 0); m_iCurrentListLevel--; } void IE_Imp_WordPerfect::openUnorderedListLevel(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: openUNorderedListLevel\n")); m_iCurrentListLevel++; } void IE_Imp_WordPerfect::closeUnorderedListLevel() { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: closeUnorderedListLevel (level: %i)\n", m_iCurrentListLevel)); UT_ASSERT(m_iCurrentListLevel > 0); m_iCurrentListLevel--; } // ASSUMPTION: We assume that unordered lists will always pass a number of "0". unpredictable behaviour // may result otherwise void IE_Imp_WordPerfect::openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: openListElement\n")); UT_ASSERT(m_pCurrentListDefinition); // FIXME: ABI_LISTS_IMPORT throw an exception back to libwpd, if this fails // Paragraph properties for our list element UT_String szListID; UT_String szParentID; UT_String szLevel; UT_String_sprintf(szListID,"%d",m_pCurrentListDefinition->getListID(m_iCurrentListLevel)); if (m_iCurrentListLevel > 1) UT_String_sprintf(szParentID,"%d", m_pCurrentListDefinition->getListID((m_iCurrentListLevel-1))); else UT_String_sprintf(szParentID,"0"); UT_String_sprintf(szLevel,"%d", m_iCurrentListLevel); const XML_Char* listAttribs[PT_MAX_ATTRIBUTES*2 + 1]; UT_uint32 attribsCount=0; listAttribs[attribsCount++] = PT_LISTID_ATTRIBUTE_NAME; listAttribs[attribsCount++] = szListID.c_str(); listAttribs[attribsCount++] = PT_PARENTID_ATTRIBUTE_NAME; listAttribs[attribsCount++] = szParentID.c_str(); listAttribs[attribsCount++] = PT_LEVEL_ATTRIBUTE_NAME; listAttribs[attribsCount++] = szLevel.c_str(); // Now handle the Abi List properties UT_String propBuffer; UT_String tempBuffer; UT_String_sprintf(tempBuffer,"list-style:%i;", m_pCurrentListDefinition->getListType(m_iCurrentListLevel)); propBuffer += tempBuffer; #if 0 // FIXME: writing the list delimiter is kind of tricky and silly (because wordperfect wants to define // it within the document, while abi wants to (sensibly probably) define it in the list definition) // (we reset it each time but only for numbered lists) if (listDefinition->isLevelNumbered(m_iCurrentListLevel)) { UT_DEBUGMSG(("WordPerfect: Appending this list delim: %s\n", m_rightListDelim.c_str())); listDefinition->setListRightDelimText(m_iCurrentListLevel, m_rightListDelim.c_str()); X_CheckWordPerfectError(_updateDocumentListDefinition(listDefinition, m_iCurrentListLevel)); } #endif if (m_pCurrentListDefinition->getListType(m_iCurrentListLevel) == BULLETED_LIST) UT_String_sprintf(tempBuffer, "field-font:Symbol; "); else UT_String_sprintf(tempBuffer, "field-font:NULL; "); m_pCurrentListDefinition->incrementLevelNumber(m_iCurrentListLevel); propBuffer += tempBuffer; UT_String_sprintf(tempBuffer, "start-value:%i; ", 1); propBuffer += tempBuffer; if (propList["fo:text-indent"]) { UT_String_sprintf(tempBuffer, "text-indent:%s; ", propList["fo:text-indent"]->getStr().cstr()); propBuffer += tempBuffer; } if (propList["fo:margin-left"]) { UT_String_sprintf(tempBuffer, "margin-left:%s", propList["fo:margin-left"]->getStr().cstr()); propBuffer += tempBuffer; } listAttribs[attribsCount++] = PT_PROPS_ATTRIBUTE_NAME; listAttribs[attribsCount++] = propBuffer.c_str(); listAttribs[attribsCount++] = NULL; X_CheckDocumentError(appendStrux(PTX_Block, listAttribs)); // hang text off of a list label getDoc()->appendFmtMark(); UT_DEBUGMSG(("WordPerfect: LISTS - Appended a list tag def'n (character props)\n")); // append a list field label const XML_Char* fielddef[5]; fielddef[0] ="type"; fielddef[1] = "list_label"; fielddef[2] = NULL; X_CheckDocumentError(appendObject(PTO_Field,fielddef)); UT_DEBUGMSG(("WordPerfect: LISTS - Appended a field def'n\n")); // insert a tab UT_UCS4Char ucs = UCS_TAB; X_CheckDocumentError(appendSpan(&ucs,1)); } void IE_Imp_WordPerfect::openFootnote(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK const XML_Char** propsArray = NULL; UT_String footnoteId; UT_String_sprintf(footnoteId,"%i",UT_rand()); propsArray = static_cast(UT_calloc(7, sizeof(XML_Char *))); propsArray [0] = "type"; propsArray [1] = "footnote_ref"; propsArray [2] = "footnote-id"; propsArray [3] = footnoteId.c_str(); propsArray [4] = NULL; propsArray [5] = NULL; propsArray [6] = NULL; X_CheckDocumentError(appendObject(PTO_Field, propsArray)); const XML_Char * attribs[3] ={"footnote-id", footnoteId.c_str(), NULL}; X_CheckDocumentError(appendStrux(PTX_SectionFootnote,attribs)); X_CheckDocumentError(appendStrux(PTX_Block,NULL)); propsArray = static_cast(UT_calloc(7, sizeof(XML_Char *))); propsArray [0] = "type"; propsArray [1] = "footnote_anchor"; propsArray [2] = "footnote-id"; propsArray [3] = footnoteId.c_str(); propsArray [4] = NULL; propsArray [5] = NULL; propsArray [6] = NULL; X_CheckDocumentError(appendObject(PTO_Field, propsArray)); } void IE_Imp_WordPerfect::closeFootnote() { if (m_bHdrFtrOpenCount) return; // HACK X_CheckDocumentError(appendStrux(PTX_EndFootnote,NULL)); } void IE_Imp_WordPerfect::openEndnote(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK const XML_Char** propsArray = NULL; UT_String endnoteId; UT_String_sprintf(endnoteId,"%i",UT_rand()); propsArray = static_cast(UT_calloc(7, sizeof(XML_Char *))); propsArray [0] = "type"; propsArray [1] = "endnote_ref"; propsArray [2] = "endnote-id"; propsArray [3] = endnoteId.c_str(); propsArray [4] = NULL; propsArray [5] = NULL; propsArray [6] = NULL; X_CheckDocumentError(appendObject(PTO_Field, propsArray)); const XML_Char * attribs[3] ={"endnote-id", endnoteId.c_str(), NULL}; X_CheckDocumentError(appendStrux(PTX_SectionEndnote,attribs)); X_CheckDocumentError(appendStrux(PTX_Block,NULL)); propsArray = static_cast(UT_calloc(7, sizeof(XML_Char *))); propsArray [0] = "type"; propsArray [1] = "endnote_anchor"; propsArray [2] = "endnote-id"; propsArray [3] = endnoteId.c_str(); propsArray [4] = NULL; propsArray [5] = NULL; propsArray [6] = NULL; X_CheckDocumentError(appendObject(PTO_Field, propsArray)); } void IE_Imp_WordPerfect::closeEndnote() { if (m_bHdrFtrOpenCount) return; // HACK X_CheckDocumentError(appendStrux(PTX_EndEndnote,NULL)); } void IE_Imp_WordPerfect::openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns) { if (m_bHdrFtrOpenCount) return; // HACK // TODO: handle 'marginLeftOffset' and 'marginRightOffset' UT_DEBUGMSG(("AbiWordPerfect: openTable\n")); UT_String propBuffer; if (propList["table:align"]) { // no need to support left: default behaviour //if (strcmp(propList["table:align"]->getStr().cstr(), "right")) // abiword does not support this I think //if (strcmp(propList["table:align"]->getStr().cstr(), "center")) // abiword does not support this I think //if (strcmp(propList["table:align"]->getStr().cstr(), "margins")) // abiword does not support this I think if (strcmp(propList["table:align"]->getStr().cstr(), "margins")) { if (propList["fo:margin-left"]) UT_String_sprintf(propBuffer, "table-column-leftpos:%s; ", propList["fo:margin-left"]->getStr().cstr()); } } propBuffer += "table-column-props:"; WPXPropertyListVector::Iter i(columns); for (i.rewind(); i.next();) { UT_String tmpBuffer; if (i()["style:column-width"]) UT_String_sprintf(tmpBuffer, "%s/", i()["style:column-width"]->getStr().cstr()); propBuffer += tmpBuffer; } const XML_Char* propsArray[3]; propsArray[0] = "props"; propsArray[1] = propBuffer.c_str(); propsArray[2] = NULL; X_CheckDocumentError(appendStrux(PTX_SectionTable, propsArray)); } void IE_Imp_WordPerfect::openTableRow(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: openRow\n")); if (m_bInCell) { X_CheckDocumentError(appendStrux(PTX_EndCell, NULL)); } m_bInCell = false; } void IE_Imp_WordPerfect::openTableCell(const WPXPropertyList &propList) { if (m_bHdrFtrOpenCount) return; // HACK int col =0, row = 0, colSpan = 0, rowSpan = 0; if (propList["libwpd:column"]) col = propList["libwpd:column"]->getInt(); if (propList["libwpd:row"]) row = propList["libwpd:row"]->getInt(); if (propList["table:number-columns-spanned"]) colSpan = propList["table:number-columns-spanned"]->getInt(); if (propList["table:number-rows-spanned"]) rowSpan = propList["table:number-rows-spanned"]->getInt(); UT_DEBUGMSG(("AbiWordPerfect: openCell(col: %d, row: %d, colSpan: %d, rowSpan: %d\n", col, row, colSpan, rowSpan)); if (m_bInCell) { X_CheckDocumentError(appendStrux(PTX_EndCell, NULL)); } UT_String propBuffer; UT_String_sprintf(propBuffer, "left-attach:%d; right-attach:%d; top-attach:%d; bot-attach:%d", col, col+colSpan, row, row+rowSpan); UT_String borderStyle; // we only support bg-style:1 for now bool borderLeftSolid = false; bool borderRightSolid = false; bool borderTopSolid = false; bool borderBottomSolid = false; if (propList["fo:border-left"]) borderLeftSolid = strncmp(propList["fo:border-left"]->getStr().cstr(), "0.0inch", 7); if (propList["fo:border-right"]) borderRightSolid = strncmp(propList["fo:border-right"]->getStr().cstr(), "0.0inch", 7); if (propList["fo:border-top"]) borderTopSolid = strncmp(propList["fo:border-top"]->getStr().cstr(), "0.0inch", 7); if (propList["fo:border-bottom"]) borderBottomSolid = strncmp(propList["fo:border-bottom"]->getStr().cstr(), "0.0inch", 7); UT_String_sprintf(borderStyle, "; left-style:%s; right-style:%s; top-style:%s; bot-style:%s", (borderLeftSolid ? "solid" : "none"), (borderRightSolid ? "solid" : "none"), (borderTopSolid ? "solid" : "none"), (borderBottomSolid ? "solid" : "none")); propBuffer += borderStyle; // we only support bg-style:1 for now if (propList["fo:background-color"]) { UT_String bgCol; UT_String_sprintf(bgCol, "; bg-style:1; background-color:%s", &(propList["fo:background-color"]->getStr().cstr()[1])); propBuffer += bgCol; } UT_DEBUGMSG(("AbiWordPerfect: Inserting a Cell definition: %s\n", propBuffer.c_str())); const XML_Char* propsArray[3]; propsArray[0] = "props"; propsArray[1] = propBuffer.c_str(); propsArray[2] = NULL; X_CheckDocumentError(appendStrux(PTX_SectionCell, propsArray)); m_bInCell = true; } void IE_Imp_WordPerfect::closeTable() { if (m_bHdrFtrOpenCount) return; // HACK UT_DEBUGMSG(("AbiWordPerfect: Closing table\n")); if (m_bInCell) { X_CheckDocumentError(appendStrux(PTX_EndCell, NULL)); } X_CheckDocumentError(appendStrux(PTX_EndTable, NULL)); m_bInCell = false; // we need to open a new paragraph after a table, since libwpd does NOT do it // FIXME: NEED TO PASS THE CURRENT PROPERTIES INSTEAD OF NULL // NOTE: THIS SUCKS......... X_CheckDocumentError(appendStrux(PTX_Block, NULL)); } UT_Error IE_Imp_WordPerfect::_appendSection(int numColumns, const float marginLeft, const float marginRight) { UT_DEBUGMSG(("AbiWordPerfect: Appending section\n")); UT_String myProps("") ; setlocale(LC_NUMERIC, "C"); myProps += UT_String_sprintf("columns:%d; page-margin-left:%.4fin; page-margin-right:%.4fin", numColumns, marginLeft, marginRight); setlocale(LC_NUMERIC, NULL); XML_Char * propsArray[3]; propsArray[0] = "props"; propsArray[1] = const_cast(reinterpret_cast(myProps.c_str())); propsArray[2] = NULL ; X_CheckDocumentError(appendStrux(PTX_Section, (const XML_Char**)propsArray)); m_bInSection = true; m_leftMargin = marginLeft; m_rightMargin = marginRight; m_bSectionChanged = false; return UT_OK; } // NB: AbiWord-2.0 doesn't properly support nested lists with different nested styles: only "1" style // really looks proper. We hack around this be only using the style given at level "1" // NB: AbiWord-2.0 doesn't properly support setting list delimeters at levels greater than 1, // we hack around this by using only "plain" (e.g.: NULL) list delimeters on levels greater than 1. UT_Error IE_Imp_WordPerfect::_updateDocumentOrderedListDefinition(ABI_ListDefinition *pListDefinition, int iLevel, const char listType, const UT_UTF8String &sTextBeforeNumber, const UT_UTF8String &sTextAfterNumber, int iStartingNumber) { UT_DEBUGMSG(("AbiWordPerfect: Updating document list definition (iLevel: %i)\n", iLevel)); if (iLevel > 1) UT_DEBUGMSG(("WLACH: Parent's list id is.. %i\n", pListDefinition->getListID((iLevel-1)))); // finally, set the document's list identification info.. fl_AutoNum * pAuto = getDoc()->getListByID(pListDefinition->getListID(iLevel)); // not in document yet, we should create a list for it if (pAuto == NULL) { UT_DEBUGMSG(("AbiWordPerfect: pAuto is NULL: creating a list\n", iLevel)); if (iLevel > 1) { pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel), pListDefinition->getListID((iLevel-1)), pListDefinition->getListType(1), iStartingNumber, const_cast(reinterpret_cast("%L")), ".", getDoc(), NULL); } else { UT_UTF8String sNumberingString; UT_UTF8String sNumber("%L", (size_t)0); sNumberingString += sTextBeforeNumber; sNumberingString += sNumber; sNumberingString += sTextAfterNumber; pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel), 0, pListDefinition->getListType(iLevel), iStartingNumber, const_cast(reinterpret_cast(sNumberingString.utf8_str())), ".", getDoc(), NULL); } getDoc()->addList(pAuto); } // we should update what we have else { UT_DEBUGMSG(("AbiWordPerfect: pAuto already exists\n", iLevel)); } pAuto->fixHierarchy(); return UT_OK; } UT_Error IE_Imp_WordPerfect::_updateDocumentUnorderedListDefinition(ABI_ListDefinition *pListDefinition, int iLevel) { UT_DEBUGMSG(("AbiWordPerfect: Updating document list definition (iLevel: %i)\n", iLevel)); // finally, set the document's list identification info.. fl_AutoNum * pAuto = getDoc()->getListByID(pListDefinition->getListID(iLevel)); // not in document yet, we should create a list for it if (pAuto == NULL) { UT_DEBUGMSG(("AbiWordPerfect: pAuto is NULL: creating a list\n", iLevel)); if (iLevel > 1) { pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel), pListDefinition->getListID((iLevel-1)), pListDefinition->getListType(1), 0, const_cast(reinterpret_cast("%L")), ".", getDoc(), NULL); } else pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel), 0, pListDefinition->getListType(iLevel), 0, const_cast(reinterpret_cast("%L")), ".", getDoc(), NULL); getDoc()->addList(pAuto); } // we should update what we have else { UT_DEBUGMSG(("AbiWordPerfect: pAuto already exists\n", iLevel)); } pAuto->fixHierarchy(); return UT_OK; }