1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_shell.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include <tools/presys.h>
28*b1cdbd2cSJim Jagielski #if defined _MSC_VER
29*b1cdbd2cSJim Jagielski #pragma warning(push, 1)
30*b1cdbd2cSJim Jagielski #endif
31*b1cdbd2cSJim Jagielski #include <windows.h>
32*b1cdbd2cSJim Jagielski #if defined _MSC_VER
33*b1cdbd2cSJim Jagielski #pragma warning(pop)
34*b1cdbd2cSJim Jagielski #endif
35*b1cdbd2cSJim Jagielski #include <tools/postsys.h>
36*b1cdbd2cSJim Jagielski 
37*b1cdbd2cSJim Jagielski #define VCL_NEED_BASETSD
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski #include "cmdline.hxx"
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski #include "osl/thread.h"
42*b1cdbd2cSJim Jagielski #include "osl/process.h"
43*b1cdbd2cSJim Jagielski #include "osl/file.hxx"
44*b1cdbd2cSJim Jagielski #include "sal/main.h"
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski #include "tools/config.hxx"
47*b1cdbd2cSJim Jagielski #include "i18npool/mslangid.hxx"
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski #include <iostream>
50*b1cdbd2cSJim Jagielski #include <fstream>
51*b1cdbd2cSJim Jagielski #include <map>
52*b1cdbd2cSJim Jagielski #include <sstream>
53*b1cdbd2cSJim Jagielski #include <iterator>
54*b1cdbd2cSJim Jagielski #include <algorithm>
55*b1cdbd2cSJim Jagielski #include <string>
56*b1cdbd2cSJim Jagielski 
57*b1cdbd2cSJim Jagielski namespace /* private */
58*b1cdbd2cSJim Jagielski {
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski using rtl::OUString;
61*b1cdbd2cSJim Jagielski using rtl::OString;
62*b1cdbd2cSJim Jagielski 
63*b1cdbd2cSJim Jagielski //###########################################
ShowUsage()64*b1cdbd2cSJim Jagielski void ShowUsage()
65*b1cdbd2cSJim Jagielski {
66*b1cdbd2cSJim Jagielski 	std::cout << "Usage: -ulf ulf_file -rc rc_output_file -rct rc_template_file -rch rch_file -rcf rcf_file" << std::endl;
67*b1cdbd2cSJim Jagielski 	std::cout << "-ulf Name of the ulf file" << std::endl;
68*b1cdbd2cSJim Jagielski 	std::cout << "-rc  Name of the resulting resource file" << std::endl;
69*b1cdbd2cSJim Jagielski 	std::cout << "-rct Name of the resource template file" << std::endl;
70*b1cdbd2cSJim Jagielski 	std::cout << "-rch Name of the resource file header" << std::endl;
71*b1cdbd2cSJim Jagielski 	std::cout << "-rcf Name of the resource file footer" << std::endl;
72*b1cdbd2cSJim Jagielski }
73*b1cdbd2cSJim Jagielski 
74*b1cdbd2cSJim Jagielski //###########################################
OStringToOUString(const OString & str)75*b1cdbd2cSJim Jagielski inline OUString OStringToOUString(const OString& str)
76*b1cdbd2cSJim Jagielski { return rtl::OStringToOUString(str, osl_getThreadTextEncoding()); }
77*b1cdbd2cSJim Jagielski 
78*b1cdbd2cSJim Jagielski //###########################################
OUStringToOString(const OUString & str)79*b1cdbd2cSJim Jagielski inline OString OUStringToOString(const OUString& str)
80*b1cdbd2cSJim Jagielski { return rtl::OUStringToOString(str, osl_getThreadTextEncoding()); }
81*b1cdbd2cSJim Jagielski 
82*b1cdbd2cSJim Jagielski //###########################################
83*b1cdbd2cSJim Jagielski /** Get the directory where the module
84*b1cdbd2cSJim Jagielski     is located as system directory, the
85*b1cdbd2cSJim Jagielski     returned directory has a trailing '\'  */
get_module_path()86*b1cdbd2cSJim Jagielski OUString get_module_path()
87*b1cdbd2cSJim Jagielski {
88*b1cdbd2cSJim Jagielski     OUString cwd_url;
89*b1cdbd2cSJim Jagielski     OUString module_path;
90*b1cdbd2cSJim Jagielski     if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData))
91*b1cdbd2cSJim Jagielski         osl::FileBase::getSystemPathFromFileURL(cwd_url, module_path);
92*b1cdbd2cSJim Jagielski 
93*b1cdbd2cSJim Jagielski     return module_path;
94*b1cdbd2cSJim Jagielski }
95*b1cdbd2cSJim Jagielski 
96*b1cdbd2cSJim Jagielski //###########################################
97*b1cdbd2cSJim Jagielski /** Make the absolute directory of a base and
98*b1cdbd2cSJim Jagielski 	a relative directory, if the relative
99*b1cdbd2cSJim Jagielski 	directory is absolute the the relative
100*b1cdbd2cSJim Jagielski 	directory will be returned unchanged.
101*b1cdbd2cSJim Jagielski 	Base and relative directory should be
102*b1cdbd2cSJim Jagielski 	system paths the returned directory is
103*b1cdbd2cSJim Jagielski 	a system path too */
get_absolute_path(const OUString & BaseDir,const OUString & RelDir)104*b1cdbd2cSJim Jagielski OUString get_absolute_path(
105*b1cdbd2cSJim Jagielski 	const OUString& BaseDir, const OUString& RelDir)
106*b1cdbd2cSJim Jagielski {
107*b1cdbd2cSJim Jagielski     OUString base_url;
108*b1cdbd2cSJim Jagielski     OUString rel_url;
109*b1cdbd2cSJim Jagielski 
110*b1cdbd2cSJim Jagielski     osl::FileBase::getFileURLFromSystemPath(BaseDir, base_url);
111*b1cdbd2cSJim Jagielski     osl::FileBase::getFileURLFromSystemPath(RelDir, rel_url);
112*b1cdbd2cSJim Jagielski 
113*b1cdbd2cSJim Jagielski     OUString abs_url;
114*b1cdbd2cSJim Jagielski     osl::FileBase::getAbsoluteFileURL(base_url, rel_url, abs_url);
115*b1cdbd2cSJim Jagielski 
116*b1cdbd2cSJim Jagielski     OUString abs_sys_path;
117*b1cdbd2cSJim Jagielski     osl::FileBase::getSystemPathFromFileURL(abs_url, abs_sys_path);
118*b1cdbd2cSJim Jagielski 
119*b1cdbd2cSJim Jagielski     return abs_sys_path;
120*b1cdbd2cSJim Jagielski }
121*b1cdbd2cSJim Jagielski 
122*b1cdbd2cSJim Jagielski //###########################################
get_absolute_file_path(const std::string & file_name)123*b1cdbd2cSJim Jagielski OString get_absolute_file_path(const std::string& file_name)
124*b1cdbd2cSJim Jagielski {
125*b1cdbd2cSJim Jagielski     OUString fp = get_absolute_path(
126*b1cdbd2cSJim Jagielski         get_module_path(), OStringToOUString(file_name.c_str()));
127*b1cdbd2cSJim Jagielski     return OUStringToOString(fp);
128*b1cdbd2cSJim Jagielski }
129*b1cdbd2cSJim Jagielski 
130*b1cdbd2cSJim Jagielski //###########################################
131*b1cdbd2cSJim Jagielski /** A helper class, enables stream exceptions
132*b1cdbd2cSJim Jagielski 	on construction, restors the old exception
133*b1cdbd2cSJim Jagielski 	state on destruction */
134*b1cdbd2cSJim Jagielski class StreamExceptionsEnabler
135*b1cdbd2cSJim Jagielski {
136*b1cdbd2cSJim Jagielski public:
StreamExceptionsEnabler(std::ios & iostrm,std::ios::iostate NewIos=std::ios::failbit|std::ios::badbit)137*b1cdbd2cSJim Jagielski 	explicit StreamExceptionsEnabler(
138*b1cdbd2cSJim Jagielski 		std::ios& iostrm,
139*b1cdbd2cSJim Jagielski 		std::ios::iostate NewIos = std::ios::failbit | std::ios::badbit) :
140*b1cdbd2cSJim Jagielski 		m_IoStrm(iostrm),
141*b1cdbd2cSJim Jagielski 		m_OldIos(m_IoStrm.exceptions())
142*b1cdbd2cSJim Jagielski 	{
143*b1cdbd2cSJim Jagielski 		m_IoStrm.exceptions(NewIos);
144*b1cdbd2cSJim Jagielski 	}
145*b1cdbd2cSJim Jagielski 
~StreamExceptionsEnabler()146*b1cdbd2cSJim Jagielski 	~StreamExceptionsEnabler()
147*b1cdbd2cSJim Jagielski 	{
148*b1cdbd2cSJim Jagielski 		m_IoStrm.exceptions(m_OldIos);
149*b1cdbd2cSJim Jagielski 	}
150*b1cdbd2cSJim Jagielski private:
151*b1cdbd2cSJim Jagielski 	std::ios& m_IoStrm;
152*b1cdbd2cSJim Jagielski 	std::ios::iostate m_OldIos;
153*b1cdbd2cSJim Jagielski };
154*b1cdbd2cSJim Jagielski 
155*b1cdbd2cSJim Jagielski typedef std::vector<std::string> string_container_t;
156*b1cdbd2cSJim Jagielski 
157*b1cdbd2cSJim Jagielski //###########################################
158*b1cdbd2cSJim Jagielski class iso_lang_identifier
159*b1cdbd2cSJim Jagielski {
160*b1cdbd2cSJim Jagielski public:
iso_lang_identifier()161*b1cdbd2cSJim Jagielski     iso_lang_identifier() {};
162*b1cdbd2cSJim Jagielski 
iso_lang_identifier(const OString & str)163*b1cdbd2cSJim Jagielski     iso_lang_identifier(const OString& str) :
164*b1cdbd2cSJim Jagielski         lang_(str)
165*b1cdbd2cSJim Jagielski     { init(); }
166*b1cdbd2cSJim Jagielski 
iso_lang_identifier(const std::string & str)167*b1cdbd2cSJim Jagielski     iso_lang_identifier(const std::string& str) :
168*b1cdbd2cSJim Jagielski         lang_(str.c_str())
169*b1cdbd2cSJim Jagielski     { init(); }
170*b1cdbd2cSJim Jagielski 
language() const171*b1cdbd2cSJim Jagielski     OString language() const
172*b1cdbd2cSJim Jagielski     { return lang_; }
173*b1cdbd2cSJim Jagielski 
country() const174*b1cdbd2cSJim Jagielski     OString country() const
175*b1cdbd2cSJim Jagielski     { return country_; }
176*b1cdbd2cSJim Jagielski 
make_OString() const177*b1cdbd2cSJim Jagielski     OString make_OString() const
178*b1cdbd2cSJim Jagielski     { return lang_ + "-" + country_; }
179*b1cdbd2cSJim Jagielski 
make_std_string() const180*b1cdbd2cSJim Jagielski     std::string make_std_string() const
181*b1cdbd2cSJim Jagielski     {
182*b1cdbd2cSJim Jagielski         OString tmp(lang_ + "-" + country_);
183*b1cdbd2cSJim Jagielski         return tmp.getStr();
184*b1cdbd2cSJim Jagielski     }
185*b1cdbd2cSJim Jagielski 
186*b1cdbd2cSJim Jagielski private:
init()187*b1cdbd2cSJim Jagielski     void init()
188*b1cdbd2cSJim Jagielski     {
189*b1cdbd2cSJim Jagielski         sal_Int32 idx = lang_.indexOf("-");
190*b1cdbd2cSJim Jagielski 
191*b1cdbd2cSJim Jagielski         if (idx > -1)
192*b1cdbd2cSJim Jagielski         {
193*b1cdbd2cSJim Jagielski             country_ = lang_.copy(idx + 1);
194*b1cdbd2cSJim Jagielski             lang_ = lang_.copy(0, idx);
195*b1cdbd2cSJim Jagielski         }
196*b1cdbd2cSJim Jagielski     }
197*b1cdbd2cSJim Jagielski 
198*b1cdbd2cSJim Jagielski private:
199*b1cdbd2cSJim Jagielski     OString lang_;
200*b1cdbd2cSJim Jagielski     OString country_;
201*b1cdbd2cSJim Jagielski };
202*b1cdbd2cSJim Jagielski 
203*b1cdbd2cSJim Jagielski //###########################################
204*b1cdbd2cSJim Jagielski /** Convert a OUString to the MS resource
205*b1cdbd2cSJim Jagielski     file format string e.g.
206*b1cdbd2cSJim Jagielski 	OUString -> L"\x1A00\x2200\x3400" */
make_winrc_unicode_string(const OUString & str)207*b1cdbd2cSJim Jagielski std::string make_winrc_unicode_string(const OUString& str)
208*b1cdbd2cSJim Jagielski {
209*b1cdbd2cSJim Jagielski 	std::ostringstream oss;
210*b1cdbd2cSJim Jagielski 	oss << "L\"";
211*b1cdbd2cSJim Jagielski 
212*b1cdbd2cSJim Jagielski 	size_t length = str.getLength();
213*b1cdbd2cSJim Jagielski 	const sal_Unicode* pchr = str.getStr();
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski 	for (size_t i = 0; i < length; i++)
216*b1cdbd2cSJim Jagielski 		oss << "\\x" << std::hex << (int)*pchr++;
217*b1cdbd2cSJim Jagielski 
218*b1cdbd2cSJim Jagielski 	oss << "\"";
219*b1cdbd2cSJim Jagielski 	return oss.str();
220*b1cdbd2cSJim Jagielski }
221*b1cdbd2cSJim Jagielski 
222*b1cdbd2cSJim Jagielski //###########################################
make_winrc_unicode_string(const std::string & str)223*b1cdbd2cSJim Jagielski std::string make_winrc_unicode_string(const std::string& str)
224*b1cdbd2cSJim Jagielski {
225*b1cdbd2cSJim Jagielski     return make_winrc_unicode_string(
226*b1cdbd2cSJim Jagielski         OUString::createFromAscii(str.c_str()));
227*b1cdbd2cSJim Jagielski }
228*b1cdbd2cSJim Jagielski 
229*b1cdbd2cSJim Jagielski //################################################
230*b1cdbd2cSJim Jagielski /** A replacement table contains pairs of
231*b1cdbd2cSJim Jagielski     placeholders and the appropriate substitute */
232*b1cdbd2cSJim Jagielski class Substitutor
233*b1cdbd2cSJim Jagielski {
234*b1cdbd2cSJim Jagielski private:
235*b1cdbd2cSJim Jagielski 	typedef std::map<std::string, std::string> replacement_table_t;
236*b1cdbd2cSJim Jagielski 	typedef std::map<std::string, replacement_table_t*> iso_lang_replacement_table_t;
237*b1cdbd2cSJim Jagielski 
238*b1cdbd2cSJim Jagielski public:
239*b1cdbd2cSJim Jagielski 	typedef iso_lang_replacement_table_t::iterator iterator;
240*b1cdbd2cSJim Jagielski 	typedef iso_lang_replacement_table_t::const_iterator const_iterator;
241*b1cdbd2cSJim Jagielski 
begin()242*b1cdbd2cSJim Jagielski     iterator begin()
243*b1cdbd2cSJim Jagielski     { return iso_lang_replacement_table_.begin(); }
244*b1cdbd2cSJim Jagielski 
end()245*b1cdbd2cSJim Jagielski     iterator end()
246*b1cdbd2cSJim Jagielski     { return iso_lang_replacement_table_.end(); }
247*b1cdbd2cSJim Jagielski 
248*b1cdbd2cSJim Jagielski public:
249*b1cdbd2cSJim Jagielski 
Substitutor()250*b1cdbd2cSJim Jagielski 	Substitutor() {};
251*b1cdbd2cSJim Jagielski 
~Substitutor()252*b1cdbd2cSJim Jagielski 	~Substitutor()
253*b1cdbd2cSJim Jagielski 	{
254*b1cdbd2cSJim Jagielski 		iso_lang_replacement_table_t::iterator iter_end = iso_lang_replacement_table_.end();
255*b1cdbd2cSJim Jagielski 		iso_lang_replacement_table_t::iterator iter = iso_lang_replacement_table_.begin();
256*b1cdbd2cSJim Jagielski 
257*b1cdbd2cSJim Jagielski 		for( /* no init */; iter != iter_end; ++iter)
258*b1cdbd2cSJim Jagielski 			delete iter->second;
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski 		iso_lang_replacement_table_.clear();
261*b1cdbd2cSJim Jagielski 	}
262*b1cdbd2cSJim Jagielski 
set_language(const iso_lang_identifier & iso_lang)263*b1cdbd2cSJim Jagielski 	void set_language(const iso_lang_identifier& iso_lang)
264*b1cdbd2cSJim Jagielski 	{
265*b1cdbd2cSJim Jagielski 		active_iso_lang_ = iso_lang;
266*b1cdbd2cSJim Jagielski 	}
267*b1cdbd2cSJim Jagielski 
268*b1cdbd2cSJim Jagielski 	// If Text is a placeholder substitute it with
269*b1cdbd2cSJim Jagielski 	//its substitute else leave it unchanged
substitute(std::string & Text)270*b1cdbd2cSJim Jagielski 	void substitute(std::string& Text)
271*b1cdbd2cSJim Jagielski 	{
272*b1cdbd2cSJim Jagielski 		replacement_table_t* prt = get_replacement_table(active_iso_lang_.make_std_string());
273*b1cdbd2cSJim Jagielski 		OSL_ASSERT(prt);
274*b1cdbd2cSJim Jagielski 		replacement_table_t::iterator iter = prt->find(Text);
275*b1cdbd2cSJim Jagielski 		if (iter != prt->end())
276*b1cdbd2cSJim Jagielski 			Text = iter->second;
277*b1cdbd2cSJim Jagielski 	}
278*b1cdbd2cSJim Jagielski 
add_substitution(const std::string & Placeholder,const std::string & Substitute)279*b1cdbd2cSJim Jagielski 	void add_substitution(
280*b1cdbd2cSJim Jagielski 		const std::string& Placeholder, const std::string& Substitute)
281*b1cdbd2cSJim Jagielski 	{
282*b1cdbd2cSJim Jagielski 		replacement_table_t* prt = get_replacement_table(active_iso_lang_.make_std_string());
283*b1cdbd2cSJim Jagielski 		OSL_ASSERT(prt);
284*b1cdbd2cSJim Jagielski 		prt->insert(std::make_pair(Placeholder, Substitute));
285*b1cdbd2cSJim Jagielski 	}
286*b1cdbd2cSJim Jagielski 
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski private:
289*b1cdbd2cSJim Jagielski 	// Return the replacement table for the iso lang id
290*b1cdbd2cSJim Jagielski 	// create a new one if not already present
get_replacement_table(const std::string & iso_lang)291*b1cdbd2cSJim Jagielski 	replacement_table_t* get_replacement_table(const std::string& iso_lang)
292*b1cdbd2cSJim Jagielski 	{
293*b1cdbd2cSJim Jagielski 		iso_lang_replacement_table_t::iterator iter =
294*b1cdbd2cSJim Jagielski 		    iso_lang_replacement_table_.find(iso_lang);
295*b1cdbd2cSJim Jagielski 
296*b1cdbd2cSJim Jagielski 		replacement_table_t* prt = NULL;
297*b1cdbd2cSJim Jagielski 
298*b1cdbd2cSJim Jagielski 		if (iso_lang_replacement_table_.end() == iter)
299*b1cdbd2cSJim Jagielski 		{
300*b1cdbd2cSJim Jagielski 			prt = new replacement_table_t();
301*b1cdbd2cSJim Jagielski 			iso_lang_replacement_table_.insert(std::make_pair(iso_lang, prt));
302*b1cdbd2cSJim Jagielski 		}
303*b1cdbd2cSJim Jagielski 		else
304*b1cdbd2cSJim Jagielski 		{
305*b1cdbd2cSJim Jagielski 			prt = iter->second;
306*b1cdbd2cSJim Jagielski 		}
307*b1cdbd2cSJim Jagielski 		return prt;
308*b1cdbd2cSJim Jagielski 	}
309*b1cdbd2cSJim Jagielski 
310*b1cdbd2cSJim Jagielski private:
311*b1cdbd2cSJim Jagielski 	iso_lang_replacement_table_t iso_lang_replacement_table_;
312*b1cdbd2cSJim Jagielski 	iso_lang_identifier active_iso_lang_;
313*b1cdbd2cSJim Jagielski };
314*b1cdbd2cSJim Jagielski 
315*b1cdbd2cSJim Jagielski typedef std::map< unsigned short , std::string , std::less< unsigned short > > shortmap;
316*b1cdbd2cSJim Jagielski 
317*b1cdbd2cSJim Jagielski //###########################################
add_group_entries(Config & aConfig,const ByteString & GroupName,Substitutor & Substitutor)318*b1cdbd2cSJim Jagielski void add_group_entries(
319*b1cdbd2cSJim Jagielski 	Config& aConfig,
320*b1cdbd2cSJim Jagielski 	const ByteString& GroupName,
321*b1cdbd2cSJim Jagielski 	Substitutor& Substitutor)
322*b1cdbd2cSJim Jagielski {
323*b1cdbd2cSJim Jagielski 	OSL_ASSERT(aConfig.HasGroup(GroupName));
324*b1cdbd2cSJim Jagielski 
325*b1cdbd2cSJim Jagielski 	aConfig.SetGroup(GroupName);
326*b1cdbd2cSJim Jagielski 	size_t key_count = aConfig.GetKeyCount();
327*b1cdbd2cSJim Jagielski     shortmap map;
328*b1cdbd2cSJim Jagielski 
329*b1cdbd2cSJim Jagielski 	for (size_t i = 0; i < key_count; i++)
330*b1cdbd2cSJim Jagielski 	{
331*b1cdbd2cSJim Jagielski 		ByteString iso_lang = aConfig.GetKeyName(sal::static_int_cast<USHORT>(i));
332*b1cdbd2cSJim Jagielski 		ByteString key_value_utf8 = aConfig.ReadKey(sal::static_int_cast<USHORT>(i));
333*b1cdbd2cSJim Jagielski         iso_lang_identifier myiso_lang( iso_lang );
334*b1cdbd2cSJim Jagielski         LanguageType ltype = MsLangId::convertIsoNamesToLanguage(myiso_lang.language(), myiso_lang.country());
335*b1cdbd2cSJim Jagielski         if(  ( ltype & 0x0200 ) == 0 && map[ ltype ].empty()  )
336*b1cdbd2cSJim Jagielski         {
337*b1cdbd2cSJim Jagielski             Substitutor.set_language(iso_lang_identifier(iso_lang));
338*b1cdbd2cSJim Jagielski 
339*b1cdbd2cSJim Jagielski 		    key_value_utf8.EraseLeadingAndTrailingChars('\"');
340*b1cdbd2cSJim Jagielski 
341*b1cdbd2cSJim Jagielski 		    OUString key_value_utf16 =
342*b1cdbd2cSJim Jagielski 			    rtl::OStringToOUString(key_value_utf8, RTL_TEXTENCODING_UTF8);
343*b1cdbd2cSJim Jagielski 
344*b1cdbd2cSJim Jagielski 		    Substitutor.add_substitution(
345*b1cdbd2cSJim Jagielski 			    GroupName.GetBuffer(), make_winrc_unicode_string(key_value_utf16));
346*b1cdbd2cSJim Jagielski             map[ static_cast<unsigned short>(ltype) ] = std::string( iso_lang.GetBuffer() );
347*b1cdbd2cSJim Jagielski         }
348*b1cdbd2cSJim Jagielski         else
349*b1cdbd2cSJim Jagielski         {
350*b1cdbd2cSJim Jagielski             if( !map[ ltype ].empty() )
351*b1cdbd2cSJim Jagielski             {
352*b1cdbd2cSJim Jagielski                 printf("ERROR: Duplicated ms id %d found for the languages %s and %s !!!! This does not work in microsoft resources\nPlease remove one!\n", ltype , map[ ltype ].c_str() , iso_lang.GetBuffer());
353*b1cdbd2cSJim Jagielski                 exit( -1 );
354*b1cdbd2cSJim Jagielski             }
355*b1cdbd2cSJim Jagielski         }
356*b1cdbd2cSJim Jagielski 	}
357*b1cdbd2cSJim Jagielski }
358*b1cdbd2cSJim Jagielski 
359*b1cdbd2cSJim Jagielski //###########################################
read_ulf_file(const std::string & FileName,Substitutor & Substitutor)360*b1cdbd2cSJim Jagielski void read_ulf_file(const std::string& FileName, Substitutor& Substitutor)
361*b1cdbd2cSJim Jagielski {
362*b1cdbd2cSJim Jagielski     // work-around for #i32420#
363*b1cdbd2cSJim Jagielski 
364*b1cdbd2cSJim Jagielski     // as the Config class is currently not able to deal correctly with
365*b1cdbd2cSJim Jagielski     // UTF8 files starting with a byte-order-mark we create a copy of the
366*b1cdbd2cSJim Jagielski     // original file without the byte-order-mark
367*b1cdbd2cSJim Jagielski     rtl::OUString tmpfile_url;
368*b1cdbd2cSJim Jagielski     osl_createTempFile(NULL, NULL, &tmpfile_url.pData);
369*b1cdbd2cSJim Jagielski 
370*b1cdbd2cSJim Jagielski     rtl::OUString tmpfile_sys;
371*b1cdbd2cSJim Jagielski     osl::FileBase::getSystemPathFromFileURL(tmpfile_url, tmpfile_sys);
372*b1cdbd2cSJim Jagielski 
373*b1cdbd2cSJim Jagielski     std::ifstream in(FileName.c_str());
374*b1cdbd2cSJim Jagielski     std::ofstream out(OUStringToOString(tmpfile_sys).getStr());
375*b1cdbd2cSJim Jagielski 
376*b1cdbd2cSJim Jagielski     try
377*b1cdbd2cSJim Jagielski     {
378*b1cdbd2cSJim Jagielski         StreamExceptionsEnabler sexc_out(out);
379*b1cdbd2cSJim Jagielski         StreamExceptionsEnabler sexc_in(in);
380*b1cdbd2cSJim Jagielski 
381*b1cdbd2cSJim Jagielski         //skip the byte-order-mark 0xEF 0xBB 0xBF, identifying UTF8 files
382*b1cdbd2cSJim Jagielski         unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
383*b1cdbd2cSJim Jagielski         char buff[3];
384*b1cdbd2cSJim Jagielski         in.read(&buff[0], 3);
385*b1cdbd2cSJim Jagielski 
386*b1cdbd2cSJim Jagielski         if (memcmp(buff, BOM, 3) != 0)
387*b1cdbd2cSJim Jagielski             in.seekg(0);
388*b1cdbd2cSJim Jagielski 
389*b1cdbd2cSJim Jagielski         std::string line;
390*b1cdbd2cSJim Jagielski         while (std::getline(in, line))
391*b1cdbd2cSJim Jagielski             out << line << std::endl;
392*b1cdbd2cSJim Jagielski     }
393*b1cdbd2cSJim Jagielski     catch (const std::ios::failure&)
394*b1cdbd2cSJim Jagielski     {
395*b1cdbd2cSJim Jagielski         if (!in.eof())
396*b1cdbd2cSJim Jagielski             throw;
397*b1cdbd2cSJim Jagielski     }
398*b1cdbd2cSJim Jagielski 
399*b1cdbd2cSJim Jagielski 	//Config config(OStringToOUString(FileName.c_str()).getStr());
400*b1cdbd2cSJim Jagielski 
401*b1cdbd2cSJim Jagielski 	// end work-around for #i32420#
402*b1cdbd2cSJim Jagielski 
403*b1cdbd2cSJim Jagielski 	Config config(tmpfile_url.getStr());
404*b1cdbd2cSJim Jagielski 	size_t grpcnt = config.GetGroupCount();
405*b1cdbd2cSJim Jagielski 	for (size_t i = 0; i < grpcnt; i++)
406*b1cdbd2cSJim Jagielski 		add_group_entries(config, config.GetGroupName(sal::static_int_cast<USHORT>(i)), Substitutor);
407*b1cdbd2cSJim Jagielski }
408*b1cdbd2cSJim Jagielski 
409*b1cdbd2cSJim Jagielski //###########################################
read_file(const std::string & fname,string_container_t & string_container)410*b1cdbd2cSJim Jagielski void read_file(
411*b1cdbd2cSJim Jagielski     const std::string& fname,
412*b1cdbd2cSJim Jagielski     string_container_t& string_container)
413*b1cdbd2cSJim Jagielski {
414*b1cdbd2cSJim Jagielski     std::ifstream file(fname.c_str());
415*b1cdbd2cSJim Jagielski 	StreamExceptionsEnabler sexc(file);
416*b1cdbd2cSJim Jagielski 
417*b1cdbd2cSJim Jagielski 	try
418*b1cdbd2cSJim Jagielski 	{
419*b1cdbd2cSJim Jagielski 		std::string line;
420*b1cdbd2cSJim Jagielski 		while (std::getline(file, line))
421*b1cdbd2cSJim Jagielski 			string_container.push_back(line);
422*b1cdbd2cSJim Jagielski 	}
423*b1cdbd2cSJim Jagielski 	catch(const std::ios::failure&)
424*b1cdbd2cSJim Jagielski 	{
425*b1cdbd2cSJim Jagielski 		if (!file.eof())
426*b1cdbd2cSJim Jagielski 			throw;
427*b1cdbd2cSJim Jagielski 	}
428*b1cdbd2cSJim Jagielski }
429*b1cdbd2cSJim Jagielski 
430*b1cdbd2cSJim Jagielski //###########################################
431*b1cdbd2cSJim Jagielski /** A simple helper function that appens the
432*b1cdbd2cSJim Jagielski     content of one file to another one  */
concatenate_files(std::ostream & os,std::istream & is)433*b1cdbd2cSJim Jagielski void concatenate_files(std::ostream& os, std::istream& is)
434*b1cdbd2cSJim Jagielski {
435*b1cdbd2cSJim Jagielski 	StreamExceptionsEnabler os_sexc(os);
436*b1cdbd2cSJim Jagielski 	StreamExceptionsEnabler is_sexc(is);
437*b1cdbd2cSJim Jagielski 
438*b1cdbd2cSJim Jagielski 	try
439*b1cdbd2cSJim Jagielski 	{
440*b1cdbd2cSJim Jagielski 		std::string line;
441*b1cdbd2cSJim Jagielski 		while (std::getline(is, line))
442*b1cdbd2cSJim Jagielski 		    os << line << std::endl;
443*b1cdbd2cSJim Jagielski 	}
444*b1cdbd2cSJim Jagielski 	catch(const std::ios::failure&)
445*b1cdbd2cSJim Jagielski 	{
446*b1cdbd2cSJim Jagielski 		if (!is.eof())
447*b1cdbd2cSJim Jagielski 			throw;
448*b1cdbd2cSJim Jagielski 	}
449*b1cdbd2cSJim Jagielski }
450*b1cdbd2cSJim Jagielski 
451*b1cdbd2cSJim Jagielski //###########################################
is_placeholder(const std::string & str)452*b1cdbd2cSJim Jagielski bool is_placeholder(const std::string& str)
453*b1cdbd2cSJim Jagielski {
454*b1cdbd2cSJim Jagielski     return ((str.length() > 1) &&
455*b1cdbd2cSJim Jagielski             ('%' == str[0]) &&
456*b1cdbd2cSJim Jagielski             ('%' == str[str.length() - 1]));
457*b1cdbd2cSJim Jagielski }
458*b1cdbd2cSJim Jagielski 
459*b1cdbd2cSJim Jagielski //###########################################
start_language_section(std::ostream_iterator<std::string> & ostream_iter,const iso_lang_identifier & iso_lang)460*b1cdbd2cSJim Jagielski void start_language_section(
461*b1cdbd2cSJim Jagielski     std::ostream_iterator<std::string>& ostream_iter, const iso_lang_identifier& iso_lang)
462*b1cdbd2cSJim Jagielski {
463*b1cdbd2cSJim Jagielski     ostream_iter = std::string();
464*b1cdbd2cSJim Jagielski 
465*b1cdbd2cSJim Jagielski     std::string lang_section("LANGUAGE ");
466*b1cdbd2cSJim Jagielski 
467*b1cdbd2cSJim Jagielski     LanguageType ltype = MsLangId::convertIsoNamesToLanguage(iso_lang.language(), iso_lang.country());
468*b1cdbd2cSJim Jagielski 
469*b1cdbd2cSJim Jagielski     char buff[10];
470*b1cdbd2cSJim Jagielski     int primLangID = PRIMARYLANGID(ltype);
471*b1cdbd2cSJim Jagielski     int subLangID = SUBLANGID(ltype);
472*b1cdbd2cSJim Jagielski     // Our resources are normaly not sub language dependant.
473*b1cdbd2cSJim Jagielski     // Esp. for spanish we don't want to distinguish between trad.
474*b1cdbd2cSJim Jagielski     // and internatinal sorting ( which leads to two different sub languages )
475*b1cdbd2cSJim Jagielski     // Setting the sub language to neutral allows us to use one
476*b1cdbd2cSJim Jagielski     // stringlist for all spanish variants ( see #123126# )
477*b1cdbd2cSJim Jagielski     if ( ( primLangID == LANG_SPANISH ) &&
478*b1cdbd2cSJim Jagielski          ( subLangID == SUBLANG_SPANISH ) )
479*b1cdbd2cSJim Jagielski         subLangID = SUBLANG_NEUTRAL;
480*b1cdbd2cSJim Jagielski 
481*b1cdbd2cSJim Jagielski     _itoa(primLangID, buff, 16);
482*b1cdbd2cSJim Jagielski     lang_section += std::string("0x") + std::string(buff);
483*b1cdbd2cSJim Jagielski 
484*b1cdbd2cSJim Jagielski     lang_section += std::string(" , ");
485*b1cdbd2cSJim Jagielski 
486*b1cdbd2cSJim Jagielski     _itoa(subLangID, buff, 16);
487*b1cdbd2cSJim Jagielski 
488*b1cdbd2cSJim Jagielski     lang_section += std::string("0x") + std::string(buff);
489*b1cdbd2cSJim Jagielski     ostream_iter = lang_section;
490*b1cdbd2cSJim Jagielski }
491*b1cdbd2cSJim Jagielski 
492*b1cdbd2cSJim Jagielski //###########################################
493*b1cdbd2cSJim Jagielski /** Iterate all languages in the substitutor,
494*b1cdbd2cSJim Jagielski 	replace the all placeholder and append the
495*b1cdbd2cSJim Jagielski 	result to the output file */
inflate_rc_template_to_file(std::ostream & os,const string_container_t & rctmpl,Substitutor & substitutor)496*b1cdbd2cSJim Jagielski void inflate_rc_template_to_file(
497*b1cdbd2cSJim Jagielski 	std::ostream& os, const string_container_t& rctmpl, Substitutor& substitutor)
498*b1cdbd2cSJim Jagielski {
499*b1cdbd2cSJim Jagielski 	StreamExceptionsEnabler sexc(os);
500*b1cdbd2cSJim Jagielski 
501*b1cdbd2cSJim Jagielski 	Substitutor::const_iterator iter = substitutor.begin();
502*b1cdbd2cSJim Jagielski 	Substitutor::const_iterator iter_end = substitutor.end();
503*b1cdbd2cSJim Jagielski 
504*b1cdbd2cSJim Jagielski 	std::ostream_iterator<std::string> oi(os, "\n");
505*b1cdbd2cSJim Jagielski 
506*b1cdbd2cSJim Jagielski 	for ( /**/ ;iter != iter_end; ++iter)
507*b1cdbd2cSJim Jagielski 	{
508*b1cdbd2cSJim Jagielski 		substitutor.set_language(iso_lang_identifier(iter->first));
509*b1cdbd2cSJim Jagielski 
510*b1cdbd2cSJim Jagielski 		string_container_t::const_iterator rct_iter	= rctmpl.begin();
511*b1cdbd2cSJim Jagielski 		string_container_t::const_iterator rct_iter_end = rctmpl.end();
512*b1cdbd2cSJim Jagielski 
513*b1cdbd2cSJim Jagielski         if (!rctmpl.empty())
514*b1cdbd2cSJim Jagielski             start_language_section(oi, iter->first);
515*b1cdbd2cSJim Jagielski 
516*b1cdbd2cSJim Jagielski 		for ( /**/ ;rct_iter != rct_iter_end; ++rct_iter)
517*b1cdbd2cSJim Jagielski 		{
518*b1cdbd2cSJim Jagielski 			std::istringstream iss(*rct_iter);
519*b1cdbd2cSJim Jagielski 			std::string line;
520*b1cdbd2cSJim Jagielski 
521*b1cdbd2cSJim Jagielski 			while (iss)
522*b1cdbd2cSJim Jagielski 			{
523*b1cdbd2cSJim Jagielski 				std::string token;
524*b1cdbd2cSJim Jagielski 				iss >> token;
525*b1cdbd2cSJim Jagielski 				substitutor.substitute(token);
526*b1cdbd2cSJim Jagielski 
527*b1cdbd2cSJim Jagielski 				// #110274# HACK for partially merged
528*b1cdbd2cSJim Jagielski 				// *.lng files where some strings have
529*b1cdbd2cSJim Jagielski 				// a particular language that others
530*b1cdbd2cSJim Jagielski 				// don't have in order to keep the
531*b1cdbd2cSJim Jagielski 				// build
532*b1cdbd2cSJim Jagielski 				if (is_placeholder(token))
533*b1cdbd2cSJim Jagielski                     token = make_winrc_unicode_string(token);
534*b1cdbd2cSJim Jagielski 
535*b1cdbd2cSJim Jagielski 				line += token;
536*b1cdbd2cSJim Jagielski 				line += " ";
537*b1cdbd2cSJim Jagielski 			}
538*b1cdbd2cSJim Jagielski 			oi = line;
539*b1cdbd2cSJim Jagielski 		}
540*b1cdbd2cSJim Jagielski 	}
541*b1cdbd2cSJim Jagielski }
542*b1cdbd2cSJim Jagielski 
543*b1cdbd2cSJim Jagielski } // namespace /* private */
544*b1cdbd2cSJim Jagielski 
545*b1cdbd2cSJim Jagielski //####################################################
546*b1cdbd2cSJim Jagielski /* MAIN
547*b1cdbd2cSJim Jagielski    The file names provided via command line should be
548*b1cdbd2cSJim Jagielski    absolute or relative to the directory of this module.
549*b1cdbd2cSJim Jagielski 
550*b1cdbd2cSJim Jagielski    Algo:
551*b1cdbd2cSJim Jagielski    1. read the ulf file and initialize the substitutor
552*b1cdbd2cSJim Jagielski    2. read the resource template file
553*b1cdbd2cSJim Jagielski    3. create the output file and append the header
554*b1cdbd2cSJim Jagielski    4. inflate the resource template to the output file
555*b1cdbd2cSJim Jagielski       for every language using the substitutor
556*b1cdbd2cSJim Jagielski    5. append the footer
557*b1cdbd2cSJim Jagielski */
558*b1cdbd2cSJim Jagielski #define MAKE_ABSOLUTE(s) (get_absolute_file_path((s)).getStr())
559*b1cdbd2cSJim Jagielski #define ULF_FILE(c)    MAKE_ABSOLUTE((c).get_arg("-ulf"))
560*b1cdbd2cSJim Jagielski #define RC_TEMPLATE(c) MAKE_ABSOLUTE((c).get_arg("-rct"))
561*b1cdbd2cSJim Jagielski #define RC_FILE(c)     MAKE_ABSOLUTE((c).get_arg("-rc"))
562*b1cdbd2cSJim Jagielski #define RC_HEADER(c)   MAKE_ABSOLUTE((c).get_arg("-rch"))
563*b1cdbd2cSJim Jagielski #define RC_FOOTER(c)   MAKE_ABSOLUTE((c).get_arg("-rcf"))
564*b1cdbd2cSJim Jagielski 
SAL_IMPLEMENT_MAIN_WITH_ARGS(argc,argv)565*b1cdbd2cSJim Jagielski SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
566*b1cdbd2cSJim Jagielski {
567*b1cdbd2cSJim Jagielski 	try
568*b1cdbd2cSJim Jagielski 	{
569*b1cdbd2cSJim Jagielski 		CommandLine cmdline(argc, argv);
570*b1cdbd2cSJim Jagielski 
571*b1cdbd2cSJim Jagielski 		Substitutor substitutor;
572*b1cdbd2cSJim Jagielski 		read_ulf_file(ULF_FILE(cmdline), substitutor);
573*b1cdbd2cSJim Jagielski 
574*b1cdbd2cSJim Jagielski         string_container_t rc_tmpl;
575*b1cdbd2cSJim Jagielski 		read_file(RC_TEMPLATE(cmdline), rc_tmpl);
576*b1cdbd2cSJim Jagielski 
577*b1cdbd2cSJim Jagielski 		std::ofstream rc_file(RC_FILE(cmdline));
578*b1cdbd2cSJim Jagielski         std::ifstream in_header(RC_HEADER(cmdline));
579*b1cdbd2cSJim Jagielski 		concatenate_files(rc_file, in_header);
580*b1cdbd2cSJim Jagielski 
581*b1cdbd2cSJim Jagielski 		inflate_rc_template_to_file(rc_file, rc_tmpl, substitutor);
582*b1cdbd2cSJim Jagielski 
583*b1cdbd2cSJim Jagielski         std::ifstream in_footer(RC_FOOTER(cmdline));
584*b1cdbd2cSJim Jagielski 		concatenate_files(rc_file, in_footer);
585*b1cdbd2cSJim Jagielski 	}
586*b1cdbd2cSJim Jagielski 	catch(const std::ios::failure& ex)
587*b1cdbd2cSJim Jagielski 	{
588*b1cdbd2cSJim Jagielski 		std::cout << ex.what() << std::endl;
589*b1cdbd2cSJim Jagielski 	}
590*b1cdbd2cSJim Jagielski 	catch(std::exception& ex)
591*b1cdbd2cSJim Jagielski 	{
592*b1cdbd2cSJim Jagielski 		std::cout << ex.what() << std::endl;
593*b1cdbd2cSJim Jagielski 		ShowUsage();
594*b1cdbd2cSJim Jagielski 	}
595*b1cdbd2cSJim Jagielski 	catch(...)
596*b1cdbd2cSJim Jagielski 	{
597*b1cdbd2cSJim Jagielski 		std::cout << "Unexpected error..." << std::endl;
598*b1cdbd2cSJim Jagielski 	}
599*b1cdbd2cSJim Jagielski 	return 0;
600*b1cdbd2cSJim Jagielski }
601*b1cdbd2cSJim Jagielski 
602