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 "helper.hxx"
22 : #include "common.hxx"
23 : #include "po.hxx"
24 : #include "treemerge.hxx"
25 :
26 :
27 : namespace
28 : {
29 : // Extract strings from nodes on all level recursively
30 0 : static void lcl_ExtractLevel(
31 : const xmlDocPtr pSource, const xmlNodePtr pRoot,
32 : const xmlChar* pNodeName, PoOfstream& rPOStream )
33 : {
34 0 : if( !pRoot->children )
35 : {
36 0 : return;
37 : }
38 0 : for( xmlNodePtr pCurrent = pRoot->children->next;
39 : pCurrent; pCurrent = pCurrent->next)
40 : {
41 0 : if (!xmlStrcmp(pCurrent->name, pNodeName))
42 : {
43 0 : xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
44 : xmlChar* pText =
45 0 : xmlGetProp(pCurrent, (const xmlChar*)("title"));
46 :
47 : common::writePoEntry(
48 : "Treex", rPOStream, pSource->name, helper::xmlStrToOString( pNodeName ),
49 0 : helper::xmlStrToOString( pID ), OString(), OString(), helper::xmlStrToOString( pText ));
50 :
51 0 : xmlFree( pID );
52 0 : xmlFree( pText );
53 :
54 : lcl_ExtractLevel(
55 : pSource, pCurrent, (const xmlChar *)("node"),
56 0 : rPOStream );
57 : }
58 : }
59 : }
60 :
61 : // Update id and content of the topic
62 0 : static xmlNodePtr lcl_UpdateTopic(
63 : const xmlNodePtr pCurrent, const OString& rXhpRoot )
64 : {
65 0 : xmlNodePtr pReturn = pCurrent;
66 0 : xmlChar* pID = xmlGetProp(pReturn, (const xmlChar*)("id"));
67 : const OString sID =
68 0 : helper::xmlStrToOString( pID );
69 0 : xmlFree( pID );
70 :
71 0 : const sal_Int32 nFirstSlash = sID.indexOf('/');
72 : // Update id attribute of topic
73 : {
74 : OString sNewID =
75 0 : sID.copy( 0, nFirstSlash + 1 ) +
76 0 : rXhpRoot.copy( rXhpRoot.lastIndexOf('/') + 1 ) +
77 0 : sID.copy( sID.indexOf( '/', nFirstSlash + 1 ) );
78 : xmlSetProp(
79 : pReturn, (const xmlChar*)("id"),
80 0 : reinterpret_cast<const xmlChar*>(sNewID.getStr()));
81 : }
82 :
83 : const OString sXhpPath =
84 0 : rXhpRoot +
85 0 : sID.copy(sID.indexOf('/', nFirstSlash + 1));
86 0 : xmlDocPtr pXhpFile = xmlParseFile( sXhpPath.getStr() );
87 : // if xhpfile is missing than put this topic into comment
88 0 : if ( !pXhpFile )
89 : {
90 0 : xmlNodePtr pTemp = pReturn;
91 : xmlChar* sNewID =
92 0 : xmlGetProp(pReturn, (const xmlChar*)("id"));
93 : xmlChar* sComment =
94 0 : xmlStrcat( xmlCharStrdup("removed "), sNewID );
95 0 : pReturn = xmlNewComment( sComment );
96 0 : xmlReplaceNode( pTemp, pReturn );
97 0 : xmlFree( pTemp );
98 0 : xmlFree( sNewID );
99 0 : xmlFree( sComment );
100 : }
101 : // update topic's content on the basis of xhpfile's title
102 : else
103 : {
104 0 : xmlNodePtr pXhpNode = xmlDocGetRootElement( pXhpFile );
105 0 : for( pXhpNode = pXhpNode->children;
106 : pXhpNode; pXhpNode = pXhpNode->children )
107 : {
108 0 : while( pXhpNode->type != XML_ELEMENT_NODE )
109 : {
110 0 : pXhpNode = pXhpNode->next;
111 : }
112 0 : if(!xmlStrcmp(pXhpNode->name, (const xmlChar *)("title")))
113 : {
114 : xmlChar* sTitle =
115 0 : xmlNodeListGetString(pXhpFile, pXhpNode->children, 1);
116 : OString sNewTitle =
117 : helper::xmlStrToOString( sTitle ).
118 : replaceAll("$[officename]","%PRODUCTNAME").
119 0 : replaceAll("$[officeversion]","%PRODUCTVERSION");
120 : xmlNodeSetContent(
121 : pReturn,
122 : xmlEncodeSpecialChars( NULL,
123 : reinterpret_cast<const xmlChar*>(
124 0 : sNewTitle.getStr() )));
125 0 : xmlFree( sTitle );
126 0 : break;
127 : }
128 : }
129 0 : if( !pXhpNode )
130 : {
131 : std::cerr
132 0 : << "Treex error: Cannot find title in "
133 0 : << sXhpPath.getStr() << std::endl;
134 0 : return 0;
135 : }
136 0 : xmlFree( pXhpFile );
137 0 : xmlCleanupParser();
138 : }
139 0 : return pReturn;
140 : }
141 : // Localize title attribute of help_section and node tags
142 0 : static void lcl_MergeLevel(
143 : xmlDocPtr io_pSource, const xmlNodePtr pRoot,
144 : const xmlChar * pNodeName, MergeDataFile* pMergeDataFile,
145 : const OString& rLang, const OString& rXhpRoot )
146 : {
147 0 : if( !pRoot->children )
148 : {
149 0 : return;
150 : }
151 0 : for( xmlNodePtr pCurrent = pRoot->children;
152 : pCurrent; pCurrent = pCurrent->next)
153 : {
154 0 : if( !xmlStrcmp(pCurrent->name, pNodeName) )
155 : {
156 0 : if( rLang != "en-US" )
157 : {
158 0 : OString sNewText;
159 0 : xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
160 : ResData aResData(
161 : helper::xmlStrToOString( pID ),
162 0 : static_cast<OString>(io_pSource->name) );
163 0 : xmlFree( pID );
164 0 : aResData.sResTyp = helper::xmlStrToOString( pNodeName );
165 0 : if( pMergeDataFile )
166 : {
167 : MergeEntrys* pEntrys =
168 0 : pMergeDataFile->GetMergeEntrys( &aResData );
169 0 : if( pEntrys )
170 : {
171 0 : pEntrys->GetText( sNewText, STRING_TYP_TEXT, rLang );
172 : }
173 : }
174 0 : else if( rLang == "qtz" )
175 : {
176 0 : xmlChar* pText = xmlGetProp(pCurrent, (const xmlChar*)("title"));
177 0 : const OString sOriginText = helper::xmlStrToOString(pText);
178 0 : xmlFree( pText );
179 0 : sNewText = MergeEntrys::GetQTZText(aResData, sOriginText);
180 : }
181 0 : if( !sNewText.isEmpty() )
182 : {
183 : xmlSetProp(
184 : pCurrent, (const xmlChar*)("title"),
185 0 : (const xmlChar*)(sNewText.getStr()));
186 0 : }
187 : }
188 :
189 : lcl_MergeLevel(
190 : io_pSource, pCurrent, (const xmlChar *)("node"),
191 0 : pMergeDataFile, rLang, rXhpRoot );
192 : }
193 0 : else if( !xmlStrcmp(pCurrent->name, (const xmlChar *)("topic")) )
194 : {
195 0 : pCurrent = lcl_UpdateTopic( pCurrent, rXhpRoot );
196 : }
197 : }
198 : }
199 : }
200 :
201 0 : TreeParser::TreeParser(
202 : const OString& rInputFile, const OString& rLang )
203 : : m_pSource( 0 )
204 : , m_sLang( rLang )
205 0 : , m_bIsInitialized( false )
206 : {
207 0 : m_pSource = xmlParseFile( rInputFile.getStr() );
208 0 : if ( !m_pSource ) {
209 : std::cerr
210 0 : << "Treex error: Cannot open source file: "
211 0 : << rInputFile.getStr() << std::endl;
212 0 : return;
213 : }
214 0 : if( !m_pSource->name )
215 : {
216 0 : m_pSource->name = static_cast<char *>(xmlMalloc(strlen(rInputFile.getStr())+1));
217 0 : strcpy( m_pSource->name, rInputFile.getStr() );
218 : }
219 0 : m_bIsInitialized = true;
220 : }
221 :
222 0 : TreeParser::~TreeParser()
223 : {
224 0 : }
225 :
226 0 : void TreeParser::Extract( const OString& rPOFile )
227 : {
228 : assert( m_bIsInitialized );
229 0 : PoOfstream aPOStream( rPOFile, PoOfstream::APP );
230 0 : if( !aPOStream.isOpen() )
231 : {
232 : std::cerr
233 0 : << "Treex error: Cannot open po file for extract: "
234 0 : << rPOFile.getStr() << std::endl;
235 0 : return;
236 : }
237 :
238 0 : xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
239 : lcl_ExtractLevel(
240 : m_pSource, pRootNode, (const xmlChar *)("help_section"),
241 0 : aPOStream );
242 :
243 0 : xmlFreeDoc( m_pSource );
244 0 : xmlCleanupParser();
245 0 : aPOStream.close();
246 0 : m_bIsInitialized = false;
247 : }
248 :
249 0 : void TreeParser::Merge(
250 : const OString &rMergeSrc, const OString &rDestinationFile,
251 : const OString &rXhpRoot )
252 : {
253 : assert( m_bIsInitialized );
254 :
255 0 : const xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
256 0 : MergeDataFile* pMergeDataFile = 0;
257 0 : if( m_sLang != "qtz" && m_sLang != "en-US" )
258 : {
259 : pMergeDataFile = new MergeDataFile(
260 0 : rMergeSrc, static_cast<OString>( m_pSource->name ), false, false );
261 0 : const std::vector<OString> vLanguages = pMergeDataFile->GetLanguages();
262 0 : if( vLanguages.size()>=1 && vLanguages[0] != m_sLang )
263 : {
264 : std::cerr
265 : << ("Treex error: given language conflicts with language of"
266 0 : " Mergedata file: ")
267 0 : << m_sLang.getStr() << " - "
268 0 : << vLanguages[0].getStr() << std::endl;
269 0 : delete pMergeDataFile;
270 0 : return;
271 0 : }
272 : }
273 : lcl_MergeLevel(
274 : m_pSource, pRootNode, (const xmlChar *)("help_section"),
275 0 : pMergeDataFile, m_sLang, rXhpRoot );
276 :
277 0 : delete pMergeDataFile;
278 0 : xmlSaveFile( rDestinationFile.getStr(), m_pSource );
279 0 : xmlFreeDoc( m_pSource );
280 0 : xmlCleanupParser();
281 0 : m_bIsInitialized = false;
282 0 : }
283 :
284 :
285 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|