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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef _EXPORT_HXX
21 : #define _EXPORT_HXX
22 :
23 : #include "sal/config.h"
24 :
25 : #include <cstddef>
26 : #include <fstream>
27 :
28 : #ifndef L10NTOOLS_DIRECTORY_HXX
29 : #define L10NTOOLS_DIRECTORY_HXX
30 : #include <l10ntools/directory.hxx>
31 : #endif
32 :
33 : #include <osl/file.hxx>
34 : #include <osl/file.h>
35 :
36 : #include <boost/unordered_map.hpp>
37 : #include <iterator> /* std::iterator*/
38 : #include <set> /* std::set*/
39 : #include <vector> /* std::vector*/
40 : #include <queue>
41 : #include <string>
42 :
43 : #include <unistd.h>
44 : #ifdef WNT
45 : #include <direct.h>
46 : #endif
47 :
48 : #define NO_TRANSLATE_ISO "x-no-translate"
49 :
50 : class PFormEntrys;
51 : class MergeData;
52 :
53 : typedef boost::unordered_map<rtl::OString, rtl::OString, rtl::OStringHash>
54 : OStringHashMap;
55 :
56 : typedef boost::unordered_map<rtl::OString, bool, rtl::OStringHash>
57 : OStringBoolHashMap;
58 :
59 : typedef boost::unordered_map<rtl::OString, PFormEntrys*, rtl::OStringHash>
60 : PFormEntrysHashMap;
61 :
62 : typedef boost::unordered_map<rtl::OString, MergeData*, rtl::OStringHash>
63 : MergeDataHashMap;
64 :
65 : #define SOURCE_LANGUAGE rtl::OString(RTL_CONSTASCII_STRINGPARAM("en-US"))
66 : #define X_COMMENT rtl::OString(RTL_CONSTASCII_STRINGPARAM("x-comment"))
67 : #define LIST_REFID "LIST_REFID"
68 :
69 : typedef OStringHashMap ExportListEntry;
70 : typedef ::std::vector< ExportListEntry* > ExportListBase;
71 :
72 : //
73 : // class ExportList
74 : //
75 :
76 2 : class ExportList
77 : {
78 : private:
79 : ExportListBase maList;
80 : std::size_t nSourceLanguageListEntryCount;
81 :
82 : public:
83 2 : ExportList() { nSourceLanguageListEntryCount = 0; }
84 2 : std::size_t GetSourceLanguageListEntryCount() { return nSourceLanguageListEntryCount; }
85 17 : void NewSourceLanguageListEntry() { nSourceLanguageListEntryCount++; }
86 36 : size_t size() const { return maList.size(); }
87 17 : void push_back( ExportListEntry* item ) { maList.push_back( item ); }
88 :
89 55 : ExportListEntry* operator [] ( size_t i )
90 : {
91 55 : return ( i < maList.size() ) ? maList[ i ] : NULL;
92 : }
93 : };
94 :
95 : #define REFID_NONE 0xFFFF
96 :
97 : //
98 : // struct ResData
99 : //
100 :
101 : /******************************************************************************
102 : * Purpose: holds mandatory data to export a single res (used with ResStack)
103 : ******************************************************************************/
104 :
105 : #define ID_LEVEL_NULL 0x0000
106 : #define ID_LEVEL_AUTOID 0x0001
107 : #define ID_LEVEL_TEXT 0x0002
108 : #define ID_LEVEL_FIELDNAME 0x0003
109 : #define ID_LEVEL_ACCESSPATH 0x0004
110 : #define ID_LEVEL_IDENTIFIER 0x0005
111 : #define ID_LEVEL_LISTINDEX 0x0006
112 :
113 : class ResData
114 : {
115 : public:
116 : ~ResData();
117 : sal_Bool SetId(const rtl::OString &rId, sal_uInt16 nLevel);
118 :
119 : sal_Int32 nWidth;
120 : sal_uInt16 nChildIndex;
121 : sal_uInt16 nIdLevel;
122 : sal_Bool bChild;
123 : sal_Bool bChildWithText;
124 :
125 : sal_Bool bText;
126 : sal_Bool bHelpText;
127 : sal_Bool bQuickHelpText;
128 : sal_Bool bTitle;
129 : sal_Bool bList;
130 :
131 : sal_Bool bRestMerged;
132 :
133 : rtl::OString sResTyp;
134 : rtl::OString sId;
135 : rtl::OString sGId;
136 : rtl::OString sHelpId;
137 : rtl::OString sFilename;
138 :
139 : OStringHashMap sText;
140 : sal_uInt16 nTextRefId;
141 :
142 : OStringHashMap sHelpText;
143 : sal_uInt16 nHelpTextRefId;
144 :
145 : OStringHashMap sQuickHelpText;
146 : sal_uInt16 nQuickHelpTextRefId;
147 :
148 : OStringHashMap sTitle;
149 : sal_uInt16 nTitleRefId;
150 :
151 : rtl::OString sTextTyp;
152 :
153 : ExportList *pStringList;
154 : ExportList *pUIEntries;
155 : ExportList *pItemList;
156 : ExportList *pFilterList;
157 : ExportList *pPairedList;
158 :
159 : rtl::OString sPForm;
160 :
161 0 : ResData(const rtl::OString &rPF, const rtl::OString &rGId)
162 : :
163 : nWidth( 0 ),
164 : nChildIndex( 0 ),
165 : nIdLevel( ID_LEVEL_NULL ),
166 : bChild( sal_False ),
167 : bChildWithText( sal_False ),
168 : bText( sal_False ),
169 : bHelpText( sal_False ),
170 : bQuickHelpText( sal_False ),
171 : bTitle( sal_False ),
172 : bList( sal_False ),
173 : bRestMerged( sal_False ),
174 : sGId( rGId ),
175 : nTextRefId( REFID_NONE ),
176 : nHelpTextRefId( REFID_NONE ),
177 : nQuickHelpTextRefId( REFID_NONE ),
178 : nTitleRefId( REFID_NONE ),
179 : sTextTyp( "Text" ),
180 : pStringList( NULL ),
181 : pUIEntries( NULL ),
182 : pItemList( NULL ),
183 : pFilterList( NULL ),
184 : pPairedList( NULL ),
185 0 : sPForm( rPF )
186 : {
187 0 : sGId = sGId.replaceAll("\r", rtl::OString());
188 0 : sPForm = sPForm.replaceAll("\r", rtl::OString());
189 0 : }
190 :
191 861 : ResData(const rtl::OString &rPF, const rtl::OString &rGId , const rtl::OString &rFilename)
192 : :
193 : nWidth( 0 ),
194 : nChildIndex( 0 ),
195 : nIdLevel( ID_LEVEL_NULL ),
196 : bChild( sal_False ),
197 : bChildWithText( sal_False ),
198 : bText( sal_False ),
199 : bHelpText( sal_False ),
200 : bQuickHelpText( sal_False ),
201 : bTitle( sal_False ),
202 : bList( sal_False ),
203 : bRestMerged( sal_False ),
204 : sGId( rGId ),
205 : sFilename( rFilename ),
206 : nTextRefId( REFID_NONE ),
207 : nHelpTextRefId( REFID_NONE ),
208 : nQuickHelpTextRefId( REFID_NONE ),
209 : nTitleRefId( REFID_NONE ),
210 : sTextTyp( "Text" ),
211 : pStringList( NULL ),
212 : pUIEntries( NULL ),
213 : pItemList( NULL ),
214 : pFilterList( NULL ),
215 : pPairedList( NULL ),
216 861 : sPForm( rPF )
217 : {
218 861 : sGId = sGId.replaceAll("\r", rtl::OString());
219 861 : sPForm = sPForm.replaceAll("\r", rtl::OString());
220 861 : }
221 : };
222 :
223 :
224 : //
225 : // class Export
226 : //
227 :
228 : /******************************************************************************
229 : * Purpose: syntax check and export of *.src, called from lexer
230 : ******************************************************************************/
231 :
232 : #define LIST_NON 0x0000
233 : #define LIST_STRING 0x0001
234 : #define LIST_FILTER 0x0002
235 : #define LIST_ITEM 0x0004
236 : #define LIST_PAIRED 0x0005
237 : #define LIST_UIENTRIES 0x0008
238 : #define STRING_TYP_TEXT 0x0010
239 : #define STRING_TYP_HELPTEXT 0x0020
240 : #define STRING_TYP_QUICKHELPTEXT 0x0040
241 : #define STRING_TYP_TITLE 0x0080
242 :
243 : #define MERGE_MODE_NORMAL 0x0000
244 : #define MERGE_MODE_LIST 0x0001
245 :
246 : typedef ::std::vector< ResData* > ResStack;
247 : // forwards
248 : class WordTransformer;
249 : class ParserQueue;
250 :
251 : //result type of handleArguments()
252 63 : struct HandledArgs
253 : {
254 : OString m_sPrj;
255 : OString m_sPrjRoot;
256 : OString m_sInputFile;
257 : OString m_sOutputFile;
258 : OString m_sMergeSrc;
259 : OString m_sLanguages;
260 : bool m_bMergeMode;
261 42 : HandledArgs()
262 : : m_sPrj( OString() )
263 : , m_sPrjRoot( OString() )
264 : , m_sInputFile( OString() )
265 : , m_sOutputFile( OString() )
266 : , m_sMergeSrc( OString() )
267 : , m_sLanguages( OString() )
268 42 : , m_bMergeMode( false )
269 42 : {}
270 : };
271 :
272 : class Export
273 : {
274 : private:
275 : WordTransformer *pWordTransformer;
276 :
277 : std::ofstream aOutput;
278 :
279 : ResStack aResStack; // stack for parsing recursive
280 :
281 : rtl::OString sActPForm; // hold cur. system
282 :
283 : sal_Bool bDefine; // cur. res. in a define?
284 : sal_Bool bNextMustBeDefineEOL; // define but no \ at lineend
285 : std::size_t nLevel; // res. recursiv? how deep?
286 : sal_uInt16 nList; // cur. res. is String- or FilterList
287 : rtl::OString m_sListLang;
288 : std::size_t nListIndex;
289 : std::size_t nListLevel;
290 : bool bSkipFile;
291 : rtl::OString sProject;
292 : rtl::OString sRoot;
293 : sal_Bool bMergeMode;
294 : rtl::OString sMergeSrc;
295 : rtl::OString sLastListLine;
296 : sal_Bool bError; // any errors while export?
297 : sal_Bool bReadOver;
298 : sal_Bool bDontWriteOutput;
299 : rtl::OString sLastTextTyp;
300 : static bool isInitialized;
301 : rtl::OString sFilename;
302 :
303 :
304 : public:
305 : ParserQueue* pParseQueue; // public ?
306 : static rtl::OString sLanguages; // public ?
307 :
308 : static bool handleArguments(int argc, char * argv[], HandledArgs& o_aHandledArgs);
309 : static void writeUsage(const OString& rName, const OString& rFileType);
310 :
311 : static void InitLanguages( bool bMergeMode = false );
312 : static void InitForcedLanguages( bool bMergeMode = false );
313 : static std::vector<rtl::OString> GetLanguages();
314 :
315 : static void SetLanguages( std::vector<rtl::OString> val );
316 : static void RemoveUTF8ByteOrderMarker( rtl::OString &rString );
317 : static bool hasUTF8ByteOrderMarker( const rtl::OString &rString );
318 : static rtl::OString QuoteHTML( rtl::OString const &rString );
319 :
320 : static rtl::OString UnquoteHTML( rtl::OString const &rString );
321 :
322 : static bool isSourceLanguage(const rtl::OString &rLanguage);
323 : static bool isAllowed(const rtl::OString &rLanguage);
324 :
325 : static void Languages( std::vector<rtl::OString>::const_iterator& begin , std::vector<rtl::OString>::const_iterator& end );
326 :
327 : private:
328 : static std::vector<rtl::OString> aLanguages;
329 : static std::vector<rtl::OString> aForcedLanguages;
330 :
331 : sal_Bool WriteData( ResData *pResData, sal_Bool bCreateNew = sal_False );// called befor dest. cur ResData
332 : sal_Bool WriteExportList( ResData *pResData, ExportList *pExportList,
333 : const rtl::OString &rTyp, sal_Bool bCreateNew = sal_False );
334 :
335 : rtl::OString MergePairedList( rtl::OString const & sLine , rtl::OString const & sText );
336 :
337 : rtl::OString FullId(); // creates cur. GID
338 :
339 : rtl::OString GetPairedListID(const rtl::OString & rText);
340 : rtl::OString GetPairedListString(const rtl::OString& rText);
341 : rtl::OString StripList(const rtl::OString& rText);
342 :
343 : void InsertListEntry(const rtl::OString &rText, const rtl::OString &rLine);
344 : void CleanValue( rtl::OString &rValue );
345 : rtl::OString GetText(const rtl::OString &rSource, int nToken);
346 :
347 : sal_Bool PrepareTextToMerge(rtl::OString &rText, sal_uInt16 nTyp,
348 : rtl::OString &rLangIndex, ResData *pResData);
349 : void ResData2Output( PFormEntrys *pEntry, sal_uInt16 nType, const rtl::OString& rTextType );
350 : void MergeRest( ResData *pResData, sal_uInt16 nMode = MERGE_MODE_NORMAL );
351 : void ConvertMergeContent( rtl::OString &rText );
352 :
353 : void WriteToMerged(const rtl::OString &rText , bool bSDFContent);
354 : void SetChildWithText();
355 :
356 : void CutComment( rtl::OString &rText );
357 :
358 : public:
359 : Export(const rtl::OString &rOutput);
360 : Export(const rtl::OString &rMergeSource, const rtl::OString &rOutput);
361 : ~Export();
362 :
363 : void Init();
364 : int Execute( int nToken, const char * pToken ); // called from lexer
365 0 : void SetError() { bError = sal_True; }
366 14 : sal_Bool GetError() { return bError; }
367 : };
368 :
369 :
370 : //
371 : // class PFormEntrys
372 : //
373 :
374 : /******************************************************************************
375 : * Purpose: holds information of data to merge (one pform)
376 : ******************************************************************************/
377 :
378 : class PFormEntrys
379 : {
380 : friend class MergeDataFile;
381 : private:
382 : rtl::OString data_; //TODO
383 : rtl::OString sHelpText; // empty string
384 : OStringHashMap sText;
385 : OStringBoolHashMap bTextFirst;
386 : OStringHashMap sQuickHelpText;
387 : OStringBoolHashMap bQuickHelpTextFirst;
388 : OStringHashMap sTitle;
389 : OStringBoolHashMap bTitleFirst;
390 :
391 : public:
392 0 : PFormEntrys( const rtl::OString &rPForm ) : data_( rPForm ) {};
393 0 : void InsertEntry(const rtl::OString &rId, const rtl::OString &rText,
394 : const rtl::OString &rQuickHelpText, const rtl::OString &rTitle)
395 : {
396 :
397 0 : sText[ rId ] = rText;
398 0 : bTextFirst[ rId ] = true;
399 0 : sQuickHelpText[ rId ] = rQuickHelpText;
400 0 : bQuickHelpTextFirst[ rId ] = true;
401 0 : sTitle[ rId ] = rTitle;
402 0 : bTitleFirst[ rId ] = true;
403 0 : }
404 : sal_Bool GetText( rtl::OString &rReturn, sal_uInt16 nTyp, const rtl::OString &nLangIndex, sal_Bool bDel = sal_False );
405 : sal_Bool GetTransex3Text( rtl::OString &rReturn, sal_uInt16 nTyp, const rtl::OString &nLangIndex, sal_Bool bDel = sal_False );
406 :
407 : };
408 :
409 : //
410 : // class MergeData
411 : //
412 :
413 : /******************************************************************************
414 : * Purpose: holds information of data to merge (one resource)
415 : ******************************************************************************/
416 :
417 : class MergeDataFile;
418 :
419 : class MergeData
420 : {
421 : public:
422 : rtl::OString sTyp;
423 : rtl::OString sGID;
424 : rtl::OString sLID;
425 : rtl::OString sFilename;
426 : PFormEntrysHashMap aMap;
427 : public:
428 0 : MergeData( const rtl::OString &rTyp, const rtl::OString &rGID, const rtl::OString &rLID , const rtl::OString &rFilename )
429 0 : : sTyp( rTyp ), sGID( rGID ), sLID( rLID ) , sFilename( rFilename ) {};
430 : ~MergeData();
431 : PFormEntrys* GetPFormEntries();
432 :
433 : void Insert( PFormEntrys* pfEntrys );
434 : PFormEntrys* GetPFObject( const rtl::OString &rPFO );
435 :
436 : sal_Bool operator==( ResData *pData );
437 : };
438 :
439 : //
440 : // class MergeDataFile
441 : //
442 :
443 : /******************************************************************************
444 : * Purpose: holds information of data to merge
445 : ******************************************************************************/
446 :
447 : class MergeDataFile
448 : {
449 : private:
450 : rtl::OString sErrorLog;
451 : MergeDataHashMap aMap;
452 : std::set<rtl::OString> aLanguageSet;
453 :
454 : MergeData *GetMergeData( ResData *pResData , bool bCaseSensitve = false );
455 : void InsertEntry(const rtl::OString &rTYP, const rtl::OString &rGID,
456 : const rtl::OString &rLID, const rtl::OString &rPFO,
457 : const rtl::OString &nLang, const rtl::OString &rTEXT,
458 : const rtl::OString &rQHTEXT, const rtl::OString &rTITLE,
459 : const rtl::OString &sFilename, bool bCaseSensitive);
460 : public:
461 : explicit MergeDataFile(
462 : const rtl::OString &rFileName, const rtl::OString& rFile,
463 : bool bCaseSensitive, bool bWithQtz = true );
464 : ~MergeDataFile();
465 :
466 :
467 : std::vector<rtl::OString> GetLanguages() const;
468 0 : const MergeDataHashMap& getMap() const { return aMap; }
469 :
470 : PFormEntrys *GetPFormEntrys( ResData *pResData );
471 : PFormEntrys *GetPFormEntrysCaseSensitive( ResData *pResData );
472 :
473 : static rtl::OString CreateKey(const rtl::OString& rTYP, const rtl::OString& rGID,
474 : const rtl::OString& rLID, const rtl::OString& rFilename , bool bCaseSensitive = false);
475 : };
476 :
477 :
478 159665 : class QueueEntry
479 : {
480 : public:
481 31933 : QueueEntry(int nTypVal, const rtl::OString &rLineVal)
482 31933 : : nTyp(nTypVal), sLine(rLineVal)
483 : {
484 31933 : }
485 : int nTyp;
486 : rtl::OString sLine;
487 : };
488 :
489 : class ParserQueue
490 : {
491 : public:
492 :
493 : ParserQueue( Export& aExportObj );
494 : ~ParserQueue();
495 :
496 : inline void Push( const QueueEntry& aEntry );
497 : bool bCurrentIsM; // public ?
498 : bool bNextIsM; // public ?
499 : bool bLastWasM; // public ?
500 : bool bMflag; // public ?
501 :
502 : void Close();
503 : private:
504 : // Future / Next
505 : std::queue<QueueEntry>* aQueueNext;
506 : // Current
507 : std::queue<QueueEntry>* aQueueCur;
508 : // Ref
509 : std::queue<QueueEntry>* aQref;
510 :
511 : Export& aExport;
512 : bool bStart;
513 :
514 : inline void Pop( std::queue<QueueEntry>& aQueue );
515 :
516 : };
517 : #endif
518 :
519 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|