/* AbiWord * Copyright (C) 2000 AbiSource, Inc. * * 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. */ #include #include #include #include #include "ap_Convert.h" #include "xap_App.h" #include "ie_exp.h" #include "ie_imp.h" #include "ut_types.h" #include "ut_string.h" #include "ut_string_class.h" #include "ut_misc.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "gr_DrawArgs.h" #include "gr_Graphics.h" #include "fv_View.h" #include "fl_BlockLayout.h" #include "ap_EditMethods.h" // needed for convertToPNG #include "ie_impGraphic.h" #include "ut_bytebuf.h" #include "ie_mailmerge.h" ////////////////////////////////////////////////////////////////// AP_Convert::AP_Convert(int inVerbose) : m_iVerbose(inVerbose) { } AP_Convert::~AP_Convert(void) { } void AP_Convert::setMergeSource (const char * source) { m_mergeSource = source; } ///////////////////////////////////////////////////////////////// class ABI_EXPORT Save_MailMerge_Listener : public IE_MailMerge::IE_MailMerge_Listener { public: explicit Save_MailMerge_Listener (PD_Document * pDoc, const UT_UTF8String & szOut, IEFileType out_ieft, const UT_UTF8String & szExpProps) : IE_MailMerge::IE_MailMerge_Listener (), m_doc (pDoc), m_szFile(szOut), m_count(0), m_ieft(out_ieft), m_expProps(szExpProps) { } virtual ~Save_MailMerge_Listener () { } virtual PD_Document* getMergeDocument () const { return m_doc; } virtual bool fireUpdate () { if (!m_doc) return false; UT_UTF8String out_file (UT_UTF8String_sprintf("%s-%d", m_szFile.utf8_str(), m_count++)); if (UT_OK == static_cast(m_doc)->saveAs (out_file.utf8_str(), m_ieft, m_expProps.utf8_str())) return true; return false; } private: PD_Document *m_doc; UT_UTF8String m_szFile; UT_uint32 m_count; IEFileType m_ieft; UT_UTF8String m_expProps; }; class ABI_EXPORT Print_MailMerge_Listener : public IE_MailMerge::IE_MailMerge_Listener { public: explicit Print_MailMerge_Listener (PD_Document * pd, GR_Graphics * pGraphics, const UT_UTF8String & szFile) : IE_MailMerge::IE_MailMerge_Listener (), m_doc (pd), m_szFile(szFile), m_pGraphics(pGraphics), m_bPrintedFirstPage(false), m_iter(1) { } virtual ~Print_MailMerge_Listener () { if (m_bPrintedFirstPage) m_pGraphics->endPrint(); } virtual PD_Document* getMergeDocument () const { return m_doc; } virtual bool fireUpdate () { FL_DocLayout *pDocLayout = new FL_DocLayout(m_doc,m_pGraphics); FV_View printView(XAP_App::getApp(),0,pDocLayout); //pDocLayout->setView (&printView); pDocLayout->fillLayouts(); pDocLayout->formatAll(); pDocLayout->recalculateTOCFields(); if (!m_bPrintedFirstPage) if (m_pGraphics->startPrint()) m_bPrintedFirstPage = true; if (m_bPrintedFirstPage) { dg_DrawArgs da; memset(&da, 0, sizeof(da)); da.pG = m_pGraphics; for (UT_sint32 k = 1; (k <= pDocLayout->countPages()); k++) { UT_uint32 iHeight = pDocLayout->getHeight() / pDocLayout->countPages(); m_pGraphics->m_iRasterPosition = (k-1)*iHeight; m_pGraphics->startPage(m_szFile.utf8_str(), m_iter++, printView.getPageSize().isPortrait(), pDocLayout->getWidth(), iHeight); printView.draw(k-1, &da); } } DELETEP(pDocLayout); // sure, we'll process more data if it exists return true; } private: PD_Document *m_doc; UT_UTF8String m_szFile; GR_Graphics * m_pGraphics; bool m_bPrintedFirstPage; UT_uint32 m_iter; }; static UT_Error handleMerge(const char * szMailMergeFile, IE_MailMerge::IE_MailMerge_Listener & listener){ IE_MailMerge * pie = NULL; UT_Error errorCode = IE_MailMerge::constructMerger(szMailMergeFile, IEMT_Unknown, &pie); if (!errorCode) { pie->setListener (&listener); errorCode = pie->mergeFile (szMailMergeFile); DELETEP(pie); } return errorCode; } ///////////////////////////////////////////////////////////////// static IEFileType getImportFileType(const char * szSuffixOrMime) { IEFileType ieft = IEFT_Unknown; if(szSuffixOrMime && *szSuffixOrMime) { IE_Imp::fileTypeForMimetype(szSuffixOrMime); if(ieft == IEFT_Unknown) { UT_String suffix; if(*szSuffixOrMime != '.') suffix = "."; suffix += szSuffixOrMime; ieft = IE_Imp::fileTypeForSuffix(suffix.c_str()); } } return ieft; } static IEFileType getExportFileType(const char * szSuffixOrMime) { IEFileType ieft = IEFT_Unknown; if(szSuffixOrMime && *szSuffixOrMime) { IE_Exp::fileTypeForMimetype(szSuffixOrMime); if(ieft == IEFT_Unknown) { UT_String suffix; if(*szSuffixOrMime != '.') suffix = "."; suffix += szSuffixOrMime; ieft = IE_Exp::fileTypeForSuffix(suffix.c_str()); } } return ieft; } bool AP_Convert::convertTo(const char * szSourceFilename, IEFileType sourceFormat, const char * szTargetFilename, IEFileType targetFormat) { UT_Error error = UT_OK; UT_return_val_if_fail(targetFormat != IEFT_Unknown, false); UT_return_val_if_fail(szSourceFilename != NULL, false); UT_return_val_if_fail(szTargetFilename != NULL, false); PD_Document * pNewDoc = new PD_Document(); UT_return_val_if_fail(pNewDoc, false); char * uri = UT_go_shell_arg_to_uri (szSourceFilename); error = pNewDoc->readFromFile(uri, sourceFormat, m_impProps.utf8_str()); g_free (uri); if (!UT_IS_IE_SUCCESS(error)) { switch (error) { case UT_INVALIDFILENAME: if (m_iVerbose > 0) fprintf(stderr, "AbiWord: [%s] is not a valid file name.\n", szSourceFilename); break; case UT_IE_NOMEMORY: if (m_iVerbose > 0) fprintf(stderr, "AbiWord: Arrrgh... I don't have enough memory!\n"); break; case UT_NOPIECETABLE: // TODO default: if (m_iVerbose > 0) fprintf(stderr, "AbiWord: could not open the file [%s]\n", szSourceFilename); } UNREFP(pNewDoc); return (error == UT_OK); } if (m_mergeSource.size()) { uri = UT_go_shell_arg_to_uri (szTargetFilename); IE_MailMerge::IE_MailMerge_Listener * listener = new Save_MailMerge_Listener (pNewDoc, uri, targetFormat, m_expProps); g_free(uri); uri = UT_go_shell_arg_to_uri (m_mergeSource.utf8_str()); handleMerge (uri, *listener); g_free (uri); DELETEP(listener); } else { uri = UT_go_shell_arg_to_uri (szTargetFilename); error = static_cast(pNewDoc)->saveAs(uri, targetFormat, m_expProps.utf8_str()); g_free(uri); switch (error) { case UT_OK: if (m_iVerbose > 1) printf("AbiWord: [%s] -> [%s]\tConversion ok!\n", szSourceFilename, szTargetFilename); break; case UT_SAVE_EXPORTERROR: if (m_iVerbose > 0) fprintf(stderr, "AbiWord: Uch! Are you sure that you've specified a valid exporter?\n"); break; case UT_SAVE_WRITEERROR: if (m_iVerbose > 0) fprintf(stderr, "AbiWord: Uch! Could not write the file [%s]\n", szTargetFilename); break; default: if (m_iVerbose > 0) fprintf(stderr, "AbiWord: could not write the file [%s]\n", szTargetFilename); break; } } UNREFP(pNewDoc); return UT_IS_IE_SUCCESS(error); } bool AP_Convert::convertTo(const char * szFilename, const char * szSourceSuffixOrMime, const char * szTargetFilename, const char * szTargetSuffixOrMime) { return convertTo(szFilename, getImportFileType(szSourceSuffixOrMime), szTargetFilename, getExportFileType(szTargetSuffixOrMime)); } bool AP_Convert::convertTo(const char * szFilename, const char * szSourceSuffixOrMime, const char * szTargetSuffixOrMime) { UT_return_val_if_fail(szTargetSuffixOrMime, false); UT_return_val_if_fail(strlen(szTargetSuffixOrMime)>0, false); UT_String ext; IEFileType ieft = IEFT_Unknown; UT_String file; // maybe it is a mime type. try that first ieft = IE_Exp::fileTypeForMimetype(szTargetSuffixOrMime); if(ieft != IEFT_Unknown) { ext = IE_Exp::preferredSuffixForFileType(ieft).utf8_str(); } else { std::string suffix = UT_pathSuffix(szTargetSuffixOrMime); if (!suffix.empty()) { // suffix is ".txt" or ".html" ieft = IE_Exp::fileTypeForSuffix(suffix.c_str()); // szTargetSuffixOrMime is something like "file://home/dom/foo.html", so use it as our target filename if (suffix.size() != strlen(szTargetSuffixOrMime)) file = szTargetSuffixOrMime; } else { // assume that szSourceSuffixOrMime is "txt" or "html" ext = "."; ext += szTargetSuffixOrMime; ieft = IE_Exp::fileTypeForSuffix(ext.c_str()); } // unknown suffix and mime type if(ieft == IEFT_Unknown) return false; } if (file.empty()) { char * fileDup = g_strdup ( szFilename ); char *tmp = strrchr(fileDup, '.'); if (tmp != NULL) *tmp = '\0'; file = fileDup; file += ext; FREEP(fileDup); } return convertTo(szFilename, getImportFileType(szSourceSuffixOrMime), file.c_str(), ieft); } void AP_Convert::setVerbose(int level) { if ((level >= 0) && (level <= 2)) m_iVerbose = level; } bool AP_Convert::print(const char * szFile, GR_Graphics * pGraphics, const char * szFileExtensionOrMime) { // get the current document PD_Document *pDoc = new PD_Document(); UT_Error err; char * uri = UT_go_shell_arg_to_uri (szFile); IEFileType ieft = getImportFileType(szFileExtensionOrMime); err = pDoc->readFromFile(uri, ieft, m_impProps.utf8_str()); g_free(uri); if( err != UT_OK) { fprintf(stderr, "AbiWord: Error importing file. [%s] Could not print \n", szFile); UNREFP(pDoc); return false; } if (m_mergeSource.size()){ IE_MailMerge::IE_MailMerge_Listener * listener = new Print_MailMerge_Listener(pDoc, pGraphics, szFile); uri = UT_go_shell_arg_to_uri (m_mergeSource.utf8_str()); handleMerge (uri, *listener); g_free (uri); DELETEP(listener); } else { // create a new layout and view object for the doc FL_DocLayout *pDocLayout = new FL_DocLayout(pDoc,pGraphics); FV_View printView(XAP_App::getApp(),0,pDocLayout); pDocLayout->setView (&printView); pDocLayout->fillLayouts(); pDocLayout->formatAll(); pDocLayout->recalculateTOCFields(); bool bCollate = true; UT_sint32 nCopies = 1; std::set pages; std::map props_map; UT_parse_properties(m_expProps.utf8_str(), props_map); if (props_map.find("collate") != props_map.end()) { bCollate = UT_parseBool(props_map["collate"].c_str(), true); } if (props_map.find("copies") != props_map.end()) { nCopies = atoi(props_map["copies"].c_str()); if (nCopies <= 0) nCopies = 1; } if (props_map.find("pages") != props_map.end()) { char **page_descriptions; page_descriptions = g_strsplit(props_map["pages"].c_str(), ",", -1); int i = 0; while (page_descriptions[i] != NULL) { char *description = page_descriptions[i]; i++; int start_page, end_page; if (2 == sscanf(description, "%d-%d", &start_page, &end_page)) { } else if (1 == sscanf(description, "%d", &start_page)) { end_page = start_page; } else { // invalid page specification continue; } for (int pageno = start_page; pageno <= end_page; pageno++) { if ((pageno > 0) && (pageno <= (int)pDocLayout->countPages())) pages.insert(pageno); } } g_strfreev(page_descriptions); } if (pages.empty()) { for (UT_sint32 i = 1; i <= pDocLayout->countPages(); i++) { pages.insert(i); } } if(!s_actuallyPrint (pDoc, pGraphics, &printView, szFile, nCopies, bCollate, pDocLayout->getWidth(), pDocLayout->getHeight() / pDocLayout->countPages(), pages)) err = UT_SAVE_WRITEERROR; DELETEP(pDocLayout); } UNREFP(pDoc); return (err == UT_OK); } bool AP_Convert::printFirstPage(GR_Graphics * pGraphics,PD_Document * pDoc) { // create a new layout and view object for the doc FL_DocLayout *pDocLayout = new FL_DocLayout(pDoc,pGraphics); FV_View printView(XAP_App::getApp(),0,pDocLayout); pDocLayout->setView (&printView); pDocLayout->fillLayouts(); pDocLayout->formatAll(); bool success = s_actuallyPrint (pDoc, pGraphics, &printView, "pngThumb", 1, true, pDocLayout->getWidth(), pDocLayout->getHeight() / pDocLayout->countPages(), 1, 1); DELETEP(pDocLayout); return success; }