lok: add character parameter to renderFont
[LibreOffice.git] / l10ntools / source / localize.cxx
blobe9130afa57645c3bee0de8803964653ef4241cbd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "sal/config.h"
22 #include <cstddef>
23 #include <cstdlib>
24 #include <iostream>
25 #include <string>
26 #include <vector>
27 #include <algorithm>
29 #include "osl/file.h"
30 #include "osl/file.hxx"
31 #include "osl/thread.h"
32 #include "rtl/string.h"
33 #include "rtl/string.hxx"
34 #include "rtl/textcvt.h"
35 #include "rtl/strbuf.hxx"
36 #include "rtl/ustring.h"
37 #include "rtl/ustring.hxx"
38 #include "sal/macros.h"
39 #include "sal/main.h"
40 #include "sal/types.h"
42 #include "po.hxx"
44 using namespace std;
46 namespace {
48 struct AsciiString {
49 char const * string;
50 sal_Int32 length;
53 bool matchList(
54 const OUString& rUrl, const AsciiString* pList, size_t nLength)
56 for (size_t i = 0; i != nLength; ++i) {
57 if (rUrl.endsWithAsciiL(pList[i].string, pList[i].length)) {
58 return true;
61 return false;
64 bool passesNegativeList(const OUString& rUrl) {
65 static const AsciiString list[] = {
66 { RTL_CONSTASCII_STRINGPARAM("/dictionaries.xcu") },
67 { RTL_CONSTASCII_STRINGPARAM(
68 "/dictionaries/da_DK/help/da/help.tree") },
69 { RTL_CONSTASCII_STRINGPARAM(
70 "/dictionaries/da_DK/help/da/"
71 "org.openoffice.da.hunspell.dictionaries/page1.xhp") },
72 { RTL_CONSTASCII_STRINGPARAM(
73 "/dictionaries/da_DK/help/da/"
74 "org.openoffice.da.hunspell.dictionaries/page2.xhp") },
75 { RTL_CONSTASCII_STRINGPARAM(
76 "/dictionaries/hu_HU/help/hu/help.tree") },
77 { RTL_CONSTASCII_STRINGPARAM(
78 "/dictionaries/hu_HU/help/hu/"
79 "org.openoffice.hu.hunspell.dictionaries/page1.xhp") },
80 { RTL_CONSTASCII_STRINGPARAM(
81 "/officecfg/registry/data/org/openoffice/Office/"
82 "Accelerators.xcu") }
84 return !matchList(rUrl, list, SAL_N_ELEMENTS(list));
87 bool passesPositiveList(const OUString& rUrl) {
88 static const AsciiString list[] = {
89 { RTL_CONSTASCII_STRINGPARAM("/description.xml") }
91 return matchList(rUrl, list, SAL_N_ELEMENTS(list));
94 void handleCommand(
95 const OString& rInPath, const OString& rOutPath,
96 const OString& rExecutable)
98 OStringBuffer buf(OString(getenv("WORKDIR_FOR_BUILD")));
99 buf.append("/LinkTarget/Executable/");
100 buf.append(rExecutable);
101 buf.append(" -i ");
102 buf.append(rInPath);
103 buf.append(" -o ");
104 buf.append(rOutPath);
106 const OString cmd = buf.makeStringAndClear();
107 if (system(cmd.getStr()) != 0)
109 cerr << "Error: Failed to execute " << cmd.getStr() << '\n';
110 throw false; //TODO
114 void InitPoFile(
115 const OString& rProject, const OString& rInPath,
116 const OString& rPotDir, const OString& rOutPath )
118 //Create directory for po file
120 OUString outDir =
121 OStringToOUString(
122 rPotDir.copy(0,rPotDir.lastIndexOf('/')), RTL_TEXTENCODING_UTF8);
123 OUString outDirUrl;
124 if (osl::FileBase::getFileURLFromSystemPath(outDir, outDirUrl)
125 != osl::FileBase::E_None)
127 cerr
128 << ("Error: Cannot convert pathname to URL in " __FILE__
129 ", in line ")
130 << __LINE__ << "\n outDir: "
131 << OUStringToOString(outDir, RTL_TEXTENCODING_ASCII_US).getStr()
132 << "\n";
133 throw false; //TODO
135 osl::Directory::createPath(outDirUrl);
138 //Add header to the po file
139 PoOfstream aPoOutPut;
140 aPoOutPut.open(rOutPath.getStr());
141 if (!aPoOutPut.isOpen())
143 cerr
144 << "Error: Cannot open po file "
145 << rOutPath.getStr() << "\n";
146 throw false; //TODO
149 const sal_Int32 nProjectInd = rInPath.indexOf(rProject);
150 const OString relativPath =
151 rInPath.copy(nProjectInd, rInPath.lastIndexOf('/')- nProjectInd);
153 PoHeader aTmp(relativPath);
154 aPoOutPut.writeHeader(aTmp);
155 aPoOutPut.close();
158 bool handleFile(
159 const OString& rProject, const OUString& rUrl,
160 const OString& rPotDir, bool bInitPoFile )
162 struct Command {
163 char const * extension;
164 sal_Int32 extensionLength;
165 OString executable;
166 bool positive;
168 static Command const commands[] = {
169 { RTL_CONSTASCII_STRINGPARAM(".src"), "transex3", false },
170 { RTL_CONSTASCII_STRINGPARAM(".hrc"), "transex3", true },
171 { RTL_CONSTASCII_STRINGPARAM(".ulf"), "ulfex", false },
172 { RTL_CONSTASCII_STRINGPARAM(".xcu"), "cfgex", false },
173 { RTL_CONSTASCII_STRINGPARAM(".xrm"), "xrmex", false },
174 { RTL_CONSTASCII_STRINGPARAM("description.xml"), "xrmex", true },
175 { RTL_CONSTASCII_STRINGPARAM(".xhp"), "helpex", false },
176 { RTL_CONSTASCII_STRINGPARAM(".properties"), "propex", false },
177 { RTL_CONSTASCII_STRINGPARAM(".ui"), "uiex", false },
178 { RTL_CONSTASCII_STRINGPARAM(".tree"), "treex", false } };
179 for (size_t i = 0; i != SAL_N_ELEMENTS(commands); ++i)
181 if (rUrl.endsWithAsciiL(
182 commands[i].extension, commands[i].extensionLength) &&
183 (commands[i].executable != "propex" || rUrl.indexOf("en_US") != -1))
185 if (commands[i].positive ? passesPositiveList(rUrl) : passesNegativeList(rUrl))
187 //Get input file path
188 OString sInPath;
190 OUString sInPathTmp;
191 if (osl::FileBase::getSystemPathFromFileURL(rUrl, sInPathTmp) !=
192 osl::FileBase::E_None)
194 cerr << "osl::FileBase::getSystemPathFromFileURL(" << rUrl << ") failed\n";
195 throw false; //TODO
197 sInPath = OUStringToOString( sInPathTmp, RTL_TEXTENCODING_UTF8 );
199 OString sOutPath = rPotDir.concat(".pot");
201 if ( bInitPoFile )
203 InitPoFile(rProject, sInPath, rPotDir, sOutPath);
205 handleCommand(sInPath, sOutPath, commands[i].executable);
206 return true;
208 break;
211 return false;
214 void handleFilesOfDir(
215 std::vector<OUString>& aFiles, const OString& rProject,
216 const OString& rPotDir )
218 ///Handle files in lexical order
219 std::sort(aFiles.begin(), aFiles.end());
221 typedef std::vector<OUString>::const_iterator citer_t;
223 bool bFirstLocFile = true; ///< First file in directory which needs localization
225 for( citer_t aIt = aFiles.begin(); aIt != aFiles.end(); ++aIt )
227 if (handleFile( rProject, *aIt, rPotDir, bFirstLocFile))
229 bFirstLocFile = false;
233 if( !bFirstLocFile )
235 //Delete pot file if it contain only the header
236 OString sPotFile = rPotDir.concat(".pot");
237 PoIfstream aPOStream( sPotFile );
238 PoEntry aPO;
239 aPOStream.readEntry( aPO );
240 bool bDel = aPOStream.eof();
241 aPOStream.close();
242 if( bDel )
244 if ( system(OString("rm " + sPotFile).getStr()) != 0 )
246 cerr
247 << "Error: Cannot remove entryless pot file: "
248 << sPotFile.getStr() << "\n";
249 throw false; //TODO
255 bool includeProject(const OString& rProject) {
256 static const char *projects[] = {
257 "accessibility",
258 "avmedia",
259 "basctl",
260 "basic",
261 "chart2",
262 "connectivity",
263 "cui",
264 "dbaccess",
265 "desktop",
266 "dictionaries",
267 "editeng",
268 "extensions",
269 "extras",
270 "filter",
271 "forms",
272 "formula",
273 "fpicker",
274 "framework",
275 "helpcontent2",
276 "instsetoo_native",
277 "librelogo",
278 "mysqlc",
279 "nlpsolver",
280 "officecfg",
281 "readlicense_oo",
282 "reportbuilder",
283 "reportdesign",
284 "sc",
285 "scaddins",
286 "sccomp",
287 "scp2",
288 "sd",
289 "sdext",
290 "setup_native",
291 "sfx2",
292 "shell",
293 "starmath",
294 "svl",
295 "svtools",
296 "svx",
297 "sw",
298 "swext",
299 "sysui",
300 "tubes",
301 "uui",
302 "vcl",
303 "wizards",
304 "xmlsecurity" };
305 for (size_t i = 0; i != SAL_N_ELEMENTS(projects); ++i) {
306 if (rProject == projects[i]) {
307 return true;
310 return false;
313 /// Handle one directory in the hierarchy.
315 /// Ignores symlinks and instead explicitly descends into clone/* or src/*,
316 /// as the Cygwin symlinks are not supported by osl::Directory on Windows.
318 /// @param rUrl the absolute file URL of this directory
320 /// @param nLevel 0 if this is either the root directory that contains the
321 /// projects or one of the clone/* or src/* directories that contain the
322 /// additional projects; -1 if this is the clone directory; 1 if this
323 /// is a project directory; 2 if this is a directory inside a project
325 /// @param rProject the name of the project (empty and ignored if nLevel <= 0)
326 /// @param rPotDir the path of pot directory
327 void handleDirectory(
328 const OUString& rUrl, int nLevel,
329 const OString& rProject, const OString& rPotDir)
331 osl::Directory dir(rUrl);
332 if (dir.open() != osl::FileBase::E_None) {
333 cerr
334 << "Error: Cannot open directory: " << rUrl << '\n';
335 throw false; //TODO
337 std::vector<OUString> aFileNames;
338 for (;;) {
339 osl::DirectoryItem item;
340 osl::FileBase::RC e = dir.getNextItem(item);
341 if (e == osl::FileBase::E_NOENT) {
342 break;
344 if (e != osl::FileBase::E_None) {
345 cerr << "Error: Cannot read directory\n";
346 throw false; //TODO
348 osl::FileStatus stat(
349 osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName
350 | osl_FileStatus_Mask_FileURL);
351 if (item.getFileStatus(stat) != osl::FileBase::E_None) {
352 cerr << "Error: Cannot get file status\n";
353 throw false; //TODO
355 const OString sDirName =
356 OUStringToOString(stat.getFileName(),RTL_TEXTENCODING_UTF8);
357 switch (nLevel) {
358 case -1: // the clone or src directory
359 if (stat.getFileType() == osl::FileStatus::Directory) {
360 handleDirectory(
361 stat.getFileURL(), 0, OString(), rPotDir);
363 break;
364 case 0: // a root directory
365 if (stat.getFileType() == osl::FileStatus::Directory) {
366 if (includeProject(sDirName)) {
367 handleDirectory(
368 stat.getFileURL(), 1, sDirName, rPotDir.concat("/").concat(sDirName));
369 } else if ( sDirName == "clone" ||
370 sDirName == "src" )
372 handleDirectory( stat.getFileURL(), -1, OString(), rPotDir);
375 break;
376 default:
377 if (stat.getFileType() == osl::FileStatus::Directory)
379 handleDirectory(
380 stat.getFileURL(), 2, rProject, rPotDir.concat("/").concat(sDirName));
382 else
384 aFileNames.push_back(stat.getFileURL());
386 break;
390 if( !aFileNames.empty() )
392 handleFilesOfDir( aFileNames, rProject, rPotDir );
395 if (dir.close() != osl::FileBase::E_None) {
396 cerr << "Error: Cannot close directory\n";
397 throw false; //TODO
400 //Remove empty pot directory
401 OUString sPoPath =
402 OStringToOUString(
403 rPotDir.copy(0,rPotDir.lastIndexOf('/')), RTL_TEXTENCODING_UTF8);
404 OUString sPoUrl;
405 if (osl::FileBase::getFileURLFromSystemPath(sPoPath, sPoUrl)
406 != osl::FileBase::E_None)
408 cerr
409 << ("Error: Cannot convert pathname to URL in " __FILE__
410 ", in line ")
411 << __LINE__ << "\n"
412 << OUStringToOString(sPoPath, RTL_TEXTENCODING_UTF8).getStr()
413 << "\n";
414 throw false; //TODO
416 osl::Directory::remove(sPoUrl);
419 void handleProjects(char * sSourceRoot, char const * sDestRoot)
421 OUString root16;
422 if (!rtl_convertStringToUString(
423 &root16.pData, sSourceRoot, rtl_str_getLength(sSourceRoot),
424 osl_getThreadTextEncoding(),
425 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
426 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
427 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
429 cerr << "Error: Cannot convert pathname to UTF-16\n";
430 throw false; //TODO
432 OUString rootUrl;
433 if (osl::FileBase::getFileURLFromSystemPath(root16, rootUrl)
434 != osl::FileBase::E_None)
436 cerr
437 << ("Error: Cannot convert pathname to URL in " __FILE__
438 ", in line ")
439 << __LINE__ << "\n root16: "
440 << OUStringToOString(root16, RTL_TEXTENCODING_ASCII_US).getStr()
441 << "\n";
442 throw false; //TODO
444 handleDirectory(rootUrl, 0, OString(), OString(sDestRoot));
448 SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
452 if (argc != 3)
454 cerr
455 << ("localize (c)2001 by Sun Microsystems\n\n"
456 "As part of the L10N framework, localize extracts en-US\n"
457 "strings for translation out of the toplevel modules defined\n"
458 "in projects array in l10ntools/source/localize.cxx.\n\n"
459 "Syntax: localize <source-root> <outfile>\n");
460 exit(EXIT_FAILURE);
462 handleProjects(argv[1],argv[2]);
464 catch (std::exception& e)
466 cerr << "exception: " << e.what() << std::endl;
467 return EXIT_FAILURE;
469 catch (bool) //TODO
471 return EXIT_FAILURE;
473 return EXIT_SUCCESS;
476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */