LCOV - code coverage report
Current view: top level - libreoffice/l10ntools/source - treemerge.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 69 125 55.2 %
Date: 2012-12-27 Functions: 8 11 72.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <iostream>
      11             : #include <fstream>
      12             : #include <cassert>
      13             : #include <cstring>
      14             : 
      15             : #include <libxml/tree.h>
      16             : #include <libxml/parser.h>
      17             : #include <libxml/xmlmemory.h>
      18             : #include <libxml/xmlstring.h>
      19             : 
      20             : #include "export.hxx"
      21             : #include "common.hxx"
      22             : #include "treemerge.hxx"
      23             : 
      24             : 
      25             : namespace
      26             : {
      27             :     //Write out an sdf line
      28           0 :     static void lcl_WriteSDF(
      29             :         std::ofstream &aSDFStream, const OString& rText, const OString& rPrj,
      30             :         const OString& rActFileName, const OString& rID, const OString& rType )
      31             :     {
      32           0 :            OString sOutput( rPrj ); sOutput += "\t";
      33           0 :            sOutput += rActFileName;
      34           0 :            sOutput += "\t0\t";
      35           0 :            sOutput += rType; sOutput += "\t";
      36           0 :            sOutput += rID; sOutput += "\t\t\t\t0\ten-US\t";
      37           0 :            sOutput += rText; sOutput += "\t\t\t\t";
      38           0 :            aSDFStream << sOutput.getStr() << std::endl;
      39           0 :     }
      40             : 
      41             :     //Convert xmlChar* to OString
      42        1537 :     static OString lcl_xmlStrToOString( const xmlChar* pString )
      43             :     {
      44        1537 :         xmlChar* pTemp = xmlStrdup( pString );
      45             :         OString sResult =
      46        1537 :             static_cast<OString>(reinterpret_cast<sal_Char*>( pTemp ));
      47        1537 :         xmlFree( pTemp );
      48        1537 :         return sResult;
      49             :     }
      50             : 
      51             :     //Extract strings from nodes on all level recursively
      52           0 :     static void lcl_ExtractLevel(
      53             :         const xmlDocPtr pSource, const xmlNodePtr pRoot,
      54             :         const xmlChar* pNodeName, std::ofstream& rSDFStream,
      55             :         const OString& rPrj, const OString& rRoot )
      56             :     {
      57           0 :         if( !pRoot->children )
      58             :         {
      59           0 :             return;
      60             :         }
      61           0 :         for( xmlNodePtr pCurrent = pRoot->children->next;
      62             :             pCurrent; pCurrent = pCurrent->next)
      63             :         {
      64           0 :             if (!xmlStrcmp(pCurrent->name, pNodeName))
      65             :             {
      66           0 :                 xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
      67             :                 xmlChar* pText =
      68           0 :                     xmlGetProp(pCurrent, (const xmlChar*)("title"));
      69             :                 lcl_WriteSDF(
      70             :                     rSDFStream,
      71             :                     lcl_xmlStrToOString( pText ),
      72             :                     rPrj,
      73             :                     common::pathnameToken(
      74             :                     pSource->name, rRoot.getStr()),
      75             :                     lcl_xmlStrToOString( pID ),
      76           0 :                     lcl_xmlStrToOString( pNodeName ));
      77             : 
      78           0 :                 xmlFree( pID );
      79           0 :                 xmlFree( pText );
      80             : 
      81             :                 lcl_ExtractLevel(
      82             :                     pSource, pCurrent, (const xmlChar *)("node"),
      83           0 :                     rSDFStream, rPrj, rRoot );
      84             :             }
      85             :         }
      86             :     }
      87             : 
      88             :     //Update id and content of the topic
      89         769 :     static xmlNodePtr lcl_UpdateTopic(
      90             :         const xmlNodePtr pCurrent, const OString& rXhpRoot )
      91             :     {
      92         769 :         xmlNodePtr pReturn = pCurrent;
      93         769 :         xmlChar* pID = xmlGetProp(pReturn, (const xmlChar*)("id"));
      94             :         const OString sID =
      95         769 :             lcl_xmlStrToOString( pID );
      96         769 :         xmlFree( pID );
      97             : 
      98         769 :         const sal_Int32 nFirstSlash = sID.indexOf("/");
      99             :         //Update id attribute of topic
     100             :         {
     101             :             OString sNewID =
     102             :                 sID.copy( 0, nFirstSlash + 1 ) +
     103        1538 :                 rXhpRoot.copy( rXhpRoot.lastIndexOf("/") + 1 ) +
     104        2307 :                 sID.copy( sID.indexOf( "/", nFirstSlash + 1 ) );
     105             :             xmlSetProp(
     106             :                 pReturn, (const xmlChar*)("id"),
     107         769 :                 reinterpret_cast<const xmlChar*>(sNewID.getStr()));
     108             :         }
     109             : 
     110             :         const OString sXhpPath =
     111             :             rXhpRoot +
     112         769 :             sID.copy(sID.indexOf("/", nFirstSlash + 1));
     113         769 :         xmlDocPtr pXhpFile = xmlParseFile( sXhpPath.getStr() );
     114             :         //if xhpfile is missing than we put this topic into comment
     115         769 :         if ( !pXhpFile )
     116             :         {
     117           1 :             xmlNodePtr pTemp = pReturn;
     118             :             xmlChar* sNewID =
     119           1 :                 xmlGetProp(pReturn, (const xmlChar*)("id"));
     120             :             xmlChar* sComment =
     121           1 :                 xmlStrcat( xmlCharStrdup("removed "), sNewID );
     122           1 :             pReturn = xmlNewComment( sComment );
     123           1 :             xmlReplaceNode( pTemp, pReturn );
     124           1 :             xmlFree( pTemp );
     125           1 :             xmlFree( sNewID );
     126           1 :             xmlFree( sComment );
     127             :         }
     128             :         //update topic's content on the basis of xhpfile's title
     129             :         else
     130             :         {
     131         768 :             xmlNodePtr pXhpNode = xmlDocGetRootElement( pXhpFile );
     132        2304 :             for( pXhpNode = pXhpNode->children;
     133             :                 pXhpNode; pXhpNode = pXhpNode->children )
     134             :             {
     135        7466 :                 while( pXhpNode->type != XML_ELEMENT_NODE )
     136             :                 {
     137        2858 :                     pXhpNode = pXhpNode->next;
     138             :                 }
     139        2304 :                 if(!xmlStrcmp(pXhpNode->name, (const xmlChar *)("title")))
     140             :                 {
     141             :                     xmlChar* sTitle =
     142         768 :                         xmlNodeListGetString(pXhpFile, pXhpNode->children, 1);
     143             :                     OString sNewTitle =
     144             :                         lcl_xmlStrToOString( sTitle ).
     145             :                             replaceAll("$[officename]","%PRODUCTNAME").
     146         768 :                                 replaceAll("$[officeversion]","%PRODUCTVERSION");
     147             :                     xmlNodeSetContent(
     148             :                         pReturn,
     149             :                         xmlEncodeSpecialChars( NULL,
     150             :                             reinterpret_cast<const xmlChar*>(
     151         768 :                                 sNewTitle.getStr() )));
     152         768 :                     xmlFree( sTitle );
     153         768 :                     break;
     154             :                 }
     155             :             }
     156         768 :             if( !pXhpNode )
     157             :             {
     158             :                 std::cerr
     159           0 :                     << "Treex error: Cannot find title in "
     160           0 :                     << sXhpPath.getStr() << std::endl;
     161           0 :                 return 0;
     162             :             }
     163         768 :             xmlFree( pXhpFile );
     164         768 :             xmlCleanupParser();
     165             :         }
     166         769 :         return pReturn;
     167             :     }
     168             :     //Localize title attribute of help_section and node tags
     169         109 :     static void lcl_MergeLevel(
     170             :         xmlDocPtr io_pSource, const xmlNodePtr pRoot,
     171             :         const xmlChar * pNodeName, MergeDataFile* pMergeDataFile,
     172             :         const OString& rLang, const OString& rXhpRoot )
     173             :     {
     174         109 :         if( !pRoot->children )
     175             :         {
     176         109 :             return;
     177             :         }
     178        1976 :         for( xmlNodePtr pCurrent = pRoot->children;
     179             :             pCurrent; pCurrent = pCurrent->next)
     180             :         {
     181        1867 :             if( !xmlStrcmp(pCurrent->name, pNodeName) )
     182             :             {
     183         102 :                 if( pMergeDataFile )
     184             :                 {
     185           0 :                     xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
     186             :                     ResData  aResData(
     187             :                         "", lcl_xmlStrToOString( pID ),
     188           0 :                         static_cast<OString>(io_pSource->name) );
     189           0 :                     xmlFree( pID );
     190           0 :                     aResData.sResTyp = lcl_xmlStrToOString( pNodeName );
     191             :                     PFormEntrys* pEntrys =
     192           0 :                         pMergeDataFile->GetPFormEntrys( &aResData );
     193           0 :                     if( pEntrys )
     194             :                     {
     195           0 :                         OString sNewText;
     196           0 :                         pEntrys->GetText( sNewText, STRING_TYP_TEXT, rLang );
     197             :                         xmlSetProp(
     198             :                             pCurrent, (const xmlChar*)("title"),
     199           0 :                             (const xmlChar*)(sNewText.getStr()));
     200           0 :                     }
     201             :                 }
     202             :                 lcl_MergeLevel(
     203             :                     io_pSource, pCurrent, (const xmlChar *)("node"),
     204         102 :                     pMergeDataFile, rLang, rXhpRoot );
     205             :             }
     206        1765 :             else if( !xmlStrcmp(pCurrent->name, (const xmlChar *)("topic")) )
     207             :             {
     208         769 :                 pCurrent = lcl_UpdateTopic( pCurrent, rXhpRoot );
     209             :             }
     210             :         }
     211             :     }
     212             : }
     213             : 
     214             : //Parse tree file
     215           7 : TreeParser::TreeParser(
     216             :     const OString& rInputFile, const OString& rLang )
     217             :     : m_pSource( 0 )
     218             :     , m_sLang( rLang )
     219           7 :     , m_bIsInitialized( false )
     220             : {
     221           7 :     m_pSource = xmlParseFile( rInputFile.getStr() );
     222           7 :     if ( !m_pSource ) {
     223             :         std::cerr
     224           0 :             << "Treex error: Cannot open source file: "
     225           0 :             << rInputFile.getStr() << std::endl;
     226           7 :         return;
     227             :     }
     228           7 :     if( !m_pSource->name )
     229             :     {
     230           7 :         m_pSource->name = new char[strlen(rInputFile.getStr())+1];
     231           7 :         strcpy( m_pSource->name, rInputFile.getStr() );
     232             :     }
     233           7 :     m_bIsInitialized = true;
     234             : }
     235             : 
     236           7 : TreeParser::~TreeParser()
     237             : {
     238           7 : }
     239             : 
     240             : //Extract strings form source file
     241           0 : void TreeParser::Extract(
     242             :     const OString& rSDFFile, const OString& rPrj, const OString& rRoot )
     243             : {
     244             :     assert( m_bIsInitialized );
     245             :     std::ofstream aSDFStream(
     246           0 :         rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc );
     247           0 :     if( !aSDFStream.is_open() )
     248             :     {
     249             :         std::cerr
     250           0 :             << "Treex error: Cannot open sdffile for extract: "
     251           0 :             << rSDFFile.getStr() << std::endl;
     252           0 :         return;
     253             :     }
     254             : 
     255           0 :     xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
     256             :     lcl_ExtractLevel(
     257             :         m_pSource, pRootNode, (const xmlChar *)("help_section"),
     258           0 :         aSDFStream, rPrj, rRoot );
     259             : 
     260           0 :     xmlFreeDoc( m_pSource );
     261           0 :     xmlCleanupParser();
     262           0 :     aSDFStream.close();
     263           0 :     m_bIsInitialized = false;
     264             : }
     265             : 
     266             : //Merge strings to tree file and update reference to help files(xhp)
     267           7 : void TreeParser::Merge(
     268             :     const OString &rMergeSrc, const OString &rDestinationFile,
     269             :     const OString &rXhpRoot )
     270             : {
     271             :     assert( m_bIsInitialized );
     272             : 
     273           7 :     const xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
     274           7 :     if( m_sLang == "en-US" )
     275             :     {
     276             :         lcl_MergeLevel(
     277             :             m_pSource, pRootNode, (const xmlChar *)("help_section"),
     278           7 :             0, m_sLang, rXhpRoot );
     279             :     }
     280             :     else
     281             :     {
     282             :         MergeDataFile aMergeDataFile(
     283           0 :             rMergeSrc, static_cast<OString>( m_pSource->name ), false, false );
     284           0 :         const std::vector<OString> vLanguages = aMergeDataFile.GetLanguages();
     285           0 :         if( vLanguages.size()>=2 &&
     286           0 :             vLanguages[vLanguages[0]=="qtz" ? 0 : 1] != m_sLang )
     287             :         {
     288             :             std::cerr
     289           0 :                 << "Treex error: given language conflicts with "
     290           0 :                 << "language of Mergedata file: "
     291           0 :                 << m_sLang.getStr() << " - "
     292           0 :                 << vLanguages[vLanguages[0]=="qtz" ? 0 : 1].getStr() << std::endl;
     293           7 :             return;
     294             :         }
     295             :         lcl_MergeLevel(
     296             :             m_pSource, pRootNode, (const xmlChar *)("help_section"),
     297           0 :             &aMergeDataFile, m_sLang, rXhpRoot );
     298             :     }
     299             : 
     300           7 :     xmlSaveFile( rDestinationFile.getStr(), m_pSource );
     301           7 :     xmlFreeDoc( m_pSource );
     302           7 :     xmlCleanupParser();
     303           7 :     m_bIsInitialized = false;
     304          21 : }
     305             : 
     306             : 
     307             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10