Bug Summary

File:rootdir/src/amuled.cpp
Warning:line 196, column 6
The 1st argument to 'dup' is -1 but should be >= 0

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name amuled.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -D USE_WX_EXTENSIONS -I /usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.2 -I /usr/include/wx-3.2 -D _FILE_OFFSET_BITS=64 -D WXUSINGDLL -D __WXGTK__ -D wxUSE_GUI=0 -I /usr/include/upnp -D ENABLE_UPNP=1 -I ./libs -I libs -I ./include -D AMULE_DAEMON -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-register -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-14-161821-17216-1 -x c++ amuled.cpp

amuled.cpp

1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5//
6// Any parts of this program derived from the xMule, lMule or eMule project,
7// or contributed by third-party developers are copyrighted by their
8// respective authors.
9//
10// This program is free software; you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation; either version 2 of the License, or
13// (at your option) any later version.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23//
24
25
26#include "amule.h" // Interface declarations.
27
28#include <include/common/EventIDs.h>
29
30#include "config.h" // Needed for HAVE_SYS_RESOURCE_H, etc
31
32
33// Include the necessary headers for select(2), properly guarded
34#if defined HAVE_SYS_SELECT_H1 && !defined __IRIX__
35# include <sys/select.h>
36#else
37# ifdef HAVE_SYS_TIME_H1
38# include <sys/time.h>
39# endif
40# ifdef HAVE_SYS_TYPES_H1
41# include <sys/types.h>
42# endif
43# ifdef HAVE_UNISTD_H1
44# include <unistd.h>
45# endif
46#endif
47
48#include <wx/utils.h>
49
50#include "Preferences.h" // Needed for CPreferences
51#include "PartFile.h" // Needed for CPartFile
52#include "Logger.h"
53#include <common/Format.h>
54#include "InternalEvents.h" // Needed for wxEVT_*
55#include "ThreadTasks.h"
56#include "GuiEvents.h" // Needed for EVT_MULE_NOTIFY
57#include "Timer.h" // Needed for EVT_MULE_TIMER
58
59#include "ClientUDPSocket.h" // Do_not_auto_remove (forward declaration not enough)
60#include "ListenSocket.h" // Do_not_auto_remove (forward declaration not enough)
61
62
63#ifdef HAVE_SYS_RESOURCE_H1
64#include <sys/resource.h> // Do_not_auto_remove
65#endif
66
67#ifndef __WINDOWS__
68 #ifdef HAVE_SYS_WAIT_H1
69 #include <sys/wait.h> // Do_not_auto_remove
70 #endif
71 #include <wx/ffile.h>
72#endif
73
74BEGIN_EVENT_TABLE(CamuleDaemonApp, wxAppConsole)const wxEventTable CamuleDaemonApp::sm_eventTable = { &wxAppConsole
::sm_eventTable, &CamuleDaemonApp::sm_eventTableEntries[0
] }; const wxEventTable *CamuleDaemonApp::GetEventTable() const
{ return &CamuleDaemonApp::sm_eventTable; } wxEventHashTable
CamuleDaemonApp::sm_eventHashTable(CamuleDaemonApp::sm_eventTable
); wxEventHashTable &CamuleDaemonApp::GetEventHashTable()
const { return CamuleDaemonApp::sm_eventHashTable; } const wxEventTableEntry
CamuleDaemonApp::sm_eventTableEntries[] = {
75
76#ifndef ASIO_SOCKETS1
77 //
78 // Socket handlers
79 //
80
81 // Listen Socket
82 EVT_SOCKET(ID_LISTENSOCKET_EVENT, CamuleDaemonApp::ListenSocketHandler)
83
84 // UDP Socket (servers)
85 EVT_SOCKET(ID_SERVERUDPSOCKET_EVENT, CamuleDaemonApp::UDPSocketHandler)
86 // UDP Socket (clients)
87 EVT_SOCKET(ID_CLIENTUDPSOCKET_EVENT, CamuleDaemonApp::UDPSocketHandler)
88#endif
89
90 // Socket timer (TCP)
91 EVT_MULE_TIMER(ID_SERVER_RETRY_TIMER_EVENT, CamuleDaemonApp::OnTCPTimer)wxEventTableEntry(MULE_EVT_TIMER, ID_SERVER_RETRY_TIMER_EVENT
, -1, wxNewEventTableFunctor(MULE_EVT_TIMER, (wxObjectEventFunction
) (wxEventFunction) static_cast<MuleTimerEventFunction>
(&CamuleDaemonApp::OnTCPTimer)), (wxObject*) __null),
92
93 // Core timer
94 EVT_MULE_TIMER(ID_CORE_TIMER_EVENT, CamuleDaemonApp::OnCoreTimer)wxEventTableEntry(MULE_EVT_TIMER, ID_CORE_TIMER_EVENT, -1, wxNewEventTableFunctor
(MULE_EVT_TIMER, (wxObjectEventFunction) (wxEventFunction) static_cast
<MuleTimerEventFunction>(&CamuleDaemonApp::OnCoreTimer
)), (wxObject*) __null),
95
96 EVT_MULE_NOTIFY(CamuleDaemonApp::OnNotifyEvent)wxEventTableEntry(MULE_EVT_NOTIFY, -1, -1, wxNewEventTableFunctor
(MULE_EVT_NOTIFY, (wxObjectEventFunction) (wxEventFunction) static_cast
<MuleNotifyEventFunction>(&CamuleDaemonApp::OnNotifyEvent
)), (wxObject*) __null),
97
98 // Async dns handling
99 EVT_MULE_INTERNAL(wxEVT_CORE_UDP_DNS_DONE, -1, CamuleDaemonApp::OnUDPDnsDone)wxEventTableEntry(wxEVT_CORE_UDP_DNS_DONE, -1, -1, wxNewEventTableFunctor
(wxEVT_CORE_UDP_DNS_DONE, (wxObjectEventFunction) (wxEventFunction
) static_cast<MuleInternalEventFunction>(&CamuleDaemonApp
::OnUDPDnsDone)), (wxObject*) __null),
100
101 EVT_MULE_INTERNAL(wxEVT_CORE_SOURCE_DNS_DONE, -1, CamuleDaemonApp::OnSourceDnsDone)wxEventTableEntry(wxEVT_CORE_SOURCE_DNS_DONE, -1, -1, wxNewEventTableFunctor
(wxEVT_CORE_SOURCE_DNS_DONE, (wxObjectEventFunction) (wxEventFunction
) static_cast<MuleInternalEventFunction>(&CamuleDaemonApp
::OnSourceDnsDone)), (wxObject*) __null),
102
103 EVT_MULE_INTERNAL(wxEVT_CORE_SERVER_DNS_DONE, -1, CamuleDaemonApp::OnServerDnsDone)wxEventTableEntry(wxEVT_CORE_SERVER_DNS_DONE, -1, -1, wxNewEventTableFunctor
(wxEVT_CORE_SERVER_DNS_DONE, (wxObjectEventFunction) (wxEventFunction
) static_cast<MuleInternalEventFunction>(&CamuleDaemonApp
::OnServerDnsDone)), (wxObject*) __null),
104
105 // Hash ended notifier
106 EVT_MULE_HASHING(CamuleDaemonApp::OnFinishedHashing)wxEventTableEntry(MULE_EVT_HASHING, -1, -1, wxNewEventTableFunctor
(MULE_EVT_HASHING, (wxObjectEventFunction) (wxEventFunction) static_cast
<MuleHashingEventFunction>(&CamuleDaemonApp::OnFinishedHashing
)), (wxObject*) __null),
107 EVT_MULE_AICH_HASHING(CamuleDaemonApp::OnFinishedAICHHashing)wxEventTableEntry(MULE_EVT_AICH_HASHING, -1, -1, wxNewEventTableFunctor
(MULE_EVT_AICH_HASHING, (wxObjectEventFunction) (wxEventFunction
) static_cast<MuleHashingEventFunction>(&CamuleDaemonApp
::OnFinishedAICHHashing)), (wxObject*) __null),
108
109 // File completion ended notifier
110 EVT_MULE_FILE_COMPLETED(CamuleDaemonApp::OnFinishedCompletion)wxEventTableEntry(MULE_EVT_FILE_COMPLETED, -1, -1, wxNewEventTableFunctor
(MULE_EVT_FILE_COMPLETED, (wxObjectEventFunction) (wxEventFunction
) static_cast<MuleCompletionEventFunction>(&CamuleDaemonApp
::OnFinishedCompletion)), (wxObject*) __null),
111
112 // HTTPDownload finished
113 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleDaemonApp::OnFinishedHTTPDownload)wxEventTableEntry(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, -1, wxNewEventTableFunctor
(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, (wxObjectEventFunction) (
wxEventFunction) static_cast<MuleInternalEventFunction>
(&CamuleDaemonApp::OnFinishedHTTPDownload)), (wxObject*) __null
),
114
115 // Disk space preallocation finished
116 EVT_MULE_ALLOC_FINISHED(CamuleDaemonApp::OnFinishedAllocation)wxEventTableEntry(MULE_EVT_ALLOC_FINISHED, -1, -1, wxNewEventTableFunctor
(MULE_EVT_ALLOC_FINISHED, (wxObjectEventFunction) (wxEventFunction
) static_cast<MuleAllocFinishedEventFunction>(&CamuleDaemonApp
::OnFinishedAllocation)), (wxObject*) __null),
117END_EVENT_TABLE()wxEventTableEntry(wxEVT_NULL, 0, 0, __null, __null) };
118
119IMPLEMENT_APP(CamuleDaemonApp)int main(int argc, char **argv) { ; ; return wxEntry(argc, argv
); } CamuleDaemonApp& wxGetApp() { return *static_cast<
CamuleDaemonApp*>(wxAppConsole::GetInstance()); } wxAppConsole
*wxCreateApp() { wxAppConsole::CheckBuildOptions("3" "." "2"
" (" "wchar_t" ",compiler with C++ ABI compatible with gcc 4"
",wx containers" ",compatible with 3.0" ")", "your program")
; return new CamuleDaemonApp; } wxAppInitializer wxTheAppInitializer
((wxAppInitializerFunction) wxCreateApp);
120
121#ifdef __WINDOWS__
122//
123// CTRL-C-Handler
124// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms685049%28v=vs.85%29.aspx
125//
126static BOOL CtrlHandler(DWORD fdwCtrlType)
127{
128 switch (fdwCtrlType) {
129 case CTRL_C_EVENT:
130 case CTRL_CLOSE_EVENT:
131 case CTRL_BREAK_EVENT:
132 // handle these
133 AddLogLineNS(wxT("Received break event, exit main loop"))theLogger.AddLogLine(L"amuled.cpp", 133, false, logStandard, L"Received break event, exit main loop"
, true)
;
134 theApp->ExitMainLoop();
135 return TRUE1;
136 break;
137 case CTRL_LOGOFF_EVENT:
138 case CTRL_SHUTDOWN_EVENT:
139 default:
140 // don't handle these
141 return FALSE0;
142 break;
143 }
144}
145
146#endif // __WINDOWS__
147
148
149int CamuleDaemonApp::OnRun()
150{
151 if (!thePrefs::AcceptExternalConnections()) {
152 AddLogLineCS(_("ERROR: aMule daemon cannot be used when external connections are disabled. To enable External Connections, use either a normal aMule, start amuled with the option --ec-config or set the key \"AcceptExternalConnections\" to 1 in the file ~/.aMule/amule.conf"))theLogger.AddLogLine(L"amuled.cpp", 152, true, logStandard, wxGetTranslation
(("ERROR: aMule daemon cannot be used when external connections are disabled. To enable External Connections, use either a normal aMule, start amuled with the option --ec-config or set the key \"AcceptExternalConnections\" to 1 in the file ~/.aMule/amule.conf"
)), true)
;
153 return 0;
154 } else if (thePrefs::ECPassword().IsEmpty()) {
155 AddLogLineCS(_("ERROR: A valid password is required to use external connections, and aMule daemon cannot be used without external connections. To run aMule daemon, you must set the \"ECPassword\" field in the file ~/.aMule/amule.conf with an appropriate value. Execute amuled with the flag --ec-config to set the password. More information can be found at http://wiki.amule.org"))theLogger.AddLogLine(L"amuled.cpp", 155, true, logStandard, wxGetTranslation
(("ERROR: A valid password is required to use external connections, and aMule daemon cannot be used without external connections. To run aMule daemon, you must set the \"ECPassword\" field in the file ~/.aMule/amule.conf with an appropriate value. Execute amuled with the flag --ec-config to set the password. More information can be found at http://wiki.amule.org"
)), true)
;
156 return 0;
157 }
158
159#ifdef __WINDOWS__
160 SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE1);
161#endif // __WINDOWS__
162
163 return wxAppwxAppConsole::OnRun();
164}
165
166bool CamuleDaemonApp::OnInit()
167{
168 if ( !CamuleApp::OnInit() ) {
169 return false;
170 }
171 AddLogLineNS(_("amuled: OnInit - starting timer"))theLogger.AddLogLine(L"amuled.cpp", 171, false, logStandard, wxGetTranslation
(("amuled: OnInit - starting timer")), true)
;
172 core_timer = new CTimer(this,ID_CORE_TIMER_EVENT);
173 core_timer->Start(CORE_TIMER_PERIOD300);
174 glob_prefs->GetCategory(0)->title = GetCatTitle(thePrefs::GetAllcatFilter());
175 glob_prefs->GetCategory(0)->path = thePrefs::GetIncomingDir();
176
177 return true;
178}
179
180int CamuleDaemonApp::InitGui(bool ,wxString &)
181{
182#ifndef __WINDOWS__
183 if ( !enable_daemon_fork ) {
1
Assuming field 'enable_daemon_fork' is true
2
Taking false branch
184 return 0;
185 }
186 AddLogLineNS(_("amuled: forking to background - see you"))theLogger.AddLogLine(L"amuled.cpp", 186, false, logStandard, wxGetTranslation
(("amuled: forking to background - see you")), true)
;
187 theLogger.SetEnabledStdoutLog(false);
188 //
189 // fork to background and detach from controlling tty
190 // while redirecting stdout to /dev/null
191 //
192 for(int i_fd = 0;i_fd < 3; i_fd++) {
3
Loop condition is true. Entering loop body
4
Loop condition is true. Entering loop body
5
Loop condition is true. Entering loop body
6
Loop condition is false. Execution continues on line 195
193 close(i_fd);
194 }
195 int fd = open("/dev/null",O_RDWR02);
7
Assuming that 'open' fails
8
'fd' initialized here
196 if (dup(fd)){} // prevent GCC warning
9
The 1st argument to 'dup' is -1 but should be >= 0
197 if (dup(fd)){}
198 pid_t pid = fork();
199
200 wxASSERT(pid != -1)do { if ( pid != -1 ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("amuled.cpp", 200, __FUNCTION__, "pid != -1", (const
char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false; asm
volatile ("int $3"); } } while ( (void)0, 0 )
;
201
202 if ( pid ) {
203 exit(0);
204 } else {
205 pid = setsid();
206 //
207 // Create a Pid file with the Pid of the Child, so any daemon-manager
208 // can easily manage the process
209 //
210 if (!m_PidFile.IsEmpty()) {
211 wxString temp = CFormat(wxT("%d\n")L"%d\n") % pid;
212 wxFFile ff(m_PidFile, wxT("w")L"w");
213 if (!ff.Error()) {
214 ff.Write(temp);
215 ff.Close();
216 } else {
217 AddLogLineNS(_("Cannot Create Pid File"))theLogger.AddLogLine(L"amuled.cpp", 217, false, logStandard, wxGetTranslation
(("Cannot Create Pid File")), true)
;
218 }
219 }
220 }
221
222#endif
223 return 0;
224}
225
226bool CamuleDaemonApp::Initialize(int& argc_, wxChar **argv_)
227{
228 if ( !wxAppConsole::Initialize(argc_, argv_) ) {
229 return false;
230 }
231
232#ifdef __UNIX__1
233 wxString encName;
234#if wxUSE_INTL1
235 // if a non default locale is set,
236 // assume that the user wants his
237 // filenames in this locale too
238 encName = wxLocale::GetSystemEncodingName().Upper();
239
240 // But don't consider ASCII in this case.
241 if ( !encName.empty() ) {
242 if ( encName == wxT("US-ASCII")L"US-ASCII" ) {
243 // This means US-ASCII when returned
244 // from GetEncodingFromName().
245 encName.clear();
246 }
247 }
248#endif // wxUSE_INTL
249
250 // in this case, UTF-8 is used by default.
251 if ( encName.empty() ) {
252 encName = wxT("UTF-8")L"UTF-8";
253 }
254
255 static wxConvBrokenFileNames fileconv(encName);
256 wxConvFileName = &fileconv;
257#endif // __UNIX__
258
259 return true;
260}
261
262int CamuleDaemonApp::OnExit()
263{
264 ShutDown();
265 delete core_timer;
266 return CamuleApp::OnExit();
267}
268
269
270int CamuleDaemonApp::ShowAlert(wxString msg, wxString title, int flags)
271{
272 if ( flags | wxICON_ERROR0x00000200 ) {
273 title = CFormat(_("ERROR: %s")wxGetTranslation(("ERROR: %s"))) % title;
274 }
275 AddLogLineCS(title + wxT(" ") + msg)theLogger.AddLogLine(L"amuled.cpp", 275, true, logStandard, title
+ L" " + msg, true)
;
276
277 return 0; // That's neither yes nor no, ok, cancel
278}
279
280// File_checked_for_headers

/usr/include/wx-3.2/wx/translation.h

1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/translation.h
3// Purpose: Internationalization and localisation for wxWidgets
4// Author: Vadim Zeitlin, Vaclav Slavik,
5// Michael N. Filippov <michael@idisys.iae.nsk.su>
6// Created: 2010-04-23
7// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8// (c) 2010 Vaclav Slavik <vslavik@fastmail.fm>
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifndef _WX_TRANSLATION_H_
13#define _WX_TRANSLATION_H_
14
15#include "wx/defs.h"
16#include "wx/string.h"
17
18#if wxUSE_INTL1
19
20#include "wx/buffer.h"
21#include "wx/language.h"
22#include "wx/hashmap.h"
23#include "wx/strconv.h"
24#include "wx/scopedptr.h"
25
26// ============================================================================
27// global decls
28// ============================================================================
29
30// ----------------------------------------------------------------------------
31// macros
32// ----------------------------------------------------------------------------
33
34// gettext() style macros (notice that xgettext should be invoked with
35// --keyword="_" --keyword="wxPLURAL:1,2" options
36// to extract the strings from the sources)
37#ifndef WXINTL_NO_GETTEXT_MACRO
38#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
39 #define _(s)wxGetTranslation((s)) wxGetTranslation((s))
40#else
41 #define _(s)wxGetTranslation((s)) wxGetTranslation(wxASCII_STR(s)wxString::FromAscii(s))
42#endif
43 #define wxPLURAL(sing, plur, n)wxGetTranslation((sing), (plur), n) wxGetTranslation((sing), (plur), n)
44#endif
45
46// wx-specific macro for translating strings in the given context: if you use
47// them, you need to also add
48// --keyword="wxGETTEXT_IN_CONTEXT:1c,2" --keyword="wxGETTEXT_IN_CONTEXT_PLURAL:1c,2,3"
49// options to xgettext invocation.
50#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
51#define wxGETTEXT_IN_CONTEXT(c, s)wxGetTranslation((s), wxString(), c) \
52 wxGetTranslation((s), wxString(), c)
53#else
54#define wxGETTEXT_IN_CONTEXT(c, s)wxGetTranslation((s), wxString(), c) \
55 wxGetTranslation(wxASCII_STR(s)wxString::FromAscii(s), wxString(), c)
56#endif
57#define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n)wxGetTranslation((sing), (plur), n, wxString(), c) \
58 wxGetTranslation((sing), (plur), n, wxString(), c)
59
60// another one which just marks the strings for extraction, but doesn't
61// perform the translation (use -kwxTRANSLATE with xgettext!)
62#define wxTRANSLATE(str)str str
63
64// another one which just marks the strings, with a context, for extraction,
65// but doesn't perform the translation (use -kwxTRANSLATE_IN_CONTEXT:1c,2 with
66// xgettext!)
67#define wxTRANSLATE_IN_CONTEXT(c, str)str str
68
69// ----------------------------------------------------------------------------
70// forward decls
71// ----------------------------------------------------------------------------
72
73class WXDLLIMPEXP_FWD_BASE wxArrayString;
74class WXDLLIMPEXP_FWD_BASE wxTranslationsLoader;
75class WXDLLIMPEXP_FWD_BASE wxLocale;
76
77class wxPluralFormsCalculator;
78wxDECLARE_SCOPED_PTR(wxPluralFormsCalculator, wxPluralFormsCalculatorPtr)class wxPluralFormsCalculatorPtr { private: wxPluralFormsCalculator
* m_ptr; wxPluralFormsCalculatorPtr(wxPluralFormsCalculatorPtr
const &); wxPluralFormsCalculatorPtr & operator=(wxPluralFormsCalculatorPtr
const &); public: explicit wxPluralFormsCalculatorPtr(wxPluralFormsCalculator
* ptr = __null) : m_ptr(ptr) { } ~wxPluralFormsCalculatorPtr
(); void reset(wxPluralFormsCalculator * ptr = __null); wxPluralFormsCalculator
*release() { wxPluralFormsCalculator *ptr = m_ptr; m_ptr = __null
; return ptr; } wxPluralFormsCalculator & operator*() const
{ do { if ( m_ptr != __null ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/translation.h"
, 78, __FUNCTION__, "m_ptr != __null", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return *m_ptr; } wxPluralFormsCalculator * operator
->() const { do { if ( m_ptr != __null ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/translation.h"
, 78, __FUNCTION__, "m_ptr != __null", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return m_ptr; } wxPluralFormsCalculator * get
() const { return m_ptr; } void swap(wxPluralFormsCalculatorPtr
& ot) { wxPluralFormsCalculator * tmp = ot.m_ptr; ot.m_ptr
= m_ptr; m_ptr = tmp; } };
79
80// ----------------------------------------------------------------------------
81// wxMsgCatalog corresponds to one loaded message catalog.
82// ----------------------------------------------------------------------------
83
84class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxMsgCatalog
85{
86public:
87 // Ctor is protected, because CreateFromXXX functions must be used,
88 // but destruction should be unrestricted
89#if !wxUSE_UNICODE1
90 ~wxMsgCatalog();
91#endif
92
93 // load the catalog from disk or from data; caller is responsible for
94 // deleting them if not NULL
95 static wxMsgCatalog *CreateFromFile(const wxString& filename,
96 const wxString& domain);
97
98 static wxMsgCatalog *CreateFromData(const wxScopedCharBuffer& data,
99 const wxString& domain);
100
101 // get name of the catalog
102 wxString GetDomain() const { return m_domain; }
103
104 // get the translated string: returns NULL if not found
105 const wxString *GetString(const wxString& sz, unsigned n = UINT_MAX(2147483647 *2U +1U), const wxString& ct = wxEmptyString) const;
106
107protected:
108 wxMsgCatalog(const wxString& domain)
109 : m_pNext(NULL__null), m_domain(domain)
110#if !wxUSE_UNICODE1
111 , m_conv(NULL__null)
112#endif
113 {}
114
115private:
116 // variable pointing to the next element in a linked list (or NULL)
117 wxMsgCatalog *m_pNext;
118 friend class wxTranslations;
119
120 wxStringToStringHashMap m_messages; // all messages in the catalog
121 wxString m_domain; // name of the domain
122
123#if !wxUSE_UNICODE1
124 // the conversion corresponding to this catalog charset if we installed it
125 // as the global one
126 wxCSConv *m_conv;
127#endif
128
129 wxPluralFormsCalculatorPtr m_pluralFormsCalculator;
130};
131
132// ----------------------------------------------------------------------------
133// wxTranslations: message catalogs
134// ----------------------------------------------------------------------------
135
136// this class allows to get translations for strings
137class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxTranslations
138{
139public:
140 wxTranslations();
141 ~wxTranslations();
142
143 // returns current translations object, may return NULL
144 static wxTranslations *Get();
145 // sets current translations object (takes ownership; may be NULL)
146 static void Set(wxTranslations *t);
147
148 // changes loader to non-default one; takes ownership of 'loader'
149 void SetLoader(wxTranslationsLoader *loader);
150
151 void SetLanguage(wxLanguage lang);
152 void SetLanguage(const wxString& lang);
153
154 // get languages available for this app
155 wxArrayString GetAvailableTranslations(const wxString& domain) const;
156
157#if wxABI_VERSION( 3 * 10000 + 2 * 100 + 99 ) >= 30203
158 // find best available translation language for given domain
159 wxString GetBestAvailableTranslation(const wxString& domain);
160#endif // wxABI_VERSION >= 3.2.3
161
162 wxString GetBestTranslation(const wxString& domain, wxLanguage msgIdLanguage);
163 wxString GetBestTranslation(const wxString& domain,
164 const wxString& msgIdLanguage = wxASCII_STR("en")wxString::FromAscii("en"));
165
166#if wxABI_VERSION( 3 * 10000 + 2 * 100 + 99 ) >= 30203
167 // add catalog for the given domain returning true if it could be found by
168 // wxTranslationsLoader
169 bool AddAvailableCatalog(const wxString& domain);
170#endif // wxABI_VERSION >= 3.2.3
171#if wxABI_VERSION( 3 * 10000 + 2 * 100 + 99 ) >= 30206
172 bool AddAvailableCatalog(const wxString& domain, wxLanguage msgIdLanguage);
173#endif // wxABI_VERSION >= 3.2.5
174
175 // add standard wxWidgets catalog ("wxstd")
176 bool AddStdCatalog();
177
178 // add catalog with given domain name and language, looking it up via
179 // wxTranslationsLoader -- unlike AddAvailableCatalog(), this function also
180 // returns true if this catalog is not needed at all because msgIdLanguage
181 // is an acceptable language to use directly
182 bool AddCatalog(const wxString& domain,
183 wxLanguage msgIdLanguage = wxLANGUAGE_ENGLISH_US);
184#if !wxUSE_UNICODE1
185 bool AddCatalog(const wxString& domain,
186 wxLanguage msgIdLanguage,
187 const wxString& msgIdCharset);
188#endif
189
190 // check if the given catalog is loaded
191 bool IsLoaded(const wxString& domain) const;
192
193 // access to translations
194 const wxString *GetTranslatedString(const wxString& origString,
195 const wxString& domain = wxEmptyString,
196 const wxString& context = wxEmptyString) const;
197 const wxString *GetTranslatedString(const wxString& origString,
198 unsigned n,
199 const wxString& domain = wxEmptyString,
200 const wxString& context = wxEmptyString) const;
201
202 wxString GetHeaderValue(const wxString& header,
203 const wxString& domain = wxEmptyString) const;
204
205 // this is hack to work around a problem with wxGetTranslation() which
206 // returns const wxString& and not wxString, so when it returns untranslated
207 // string, it needs to have a copy of it somewhere
208 static const wxString& GetUntranslatedString(const wxString& str);
209
210private:
211 enum Translations
212 {
213 Translations_NotNeeded = -1,
214 Translations_NotFound = 0,
215 Translations_Found = 1
216 };
217
218 Translations DoAddCatalog(const wxString& domain, wxLanguage msgIdLanguage);
219
220 // perform loading of the catalog via m_loader
221 bool LoadCatalog(const wxString& domain, const wxString& lang, const wxString& msgIdLang);
222
223 // find catalog by name in a linked list, return NULL if !found
224 wxMsgCatalog *FindCatalog(const wxString& domain) const;
225
226 // same as Set(), without taking ownership; only for wxLocale
227 static void SetNonOwned(wxTranslations *t);
228 friend class wxLocale;
229
230 wxString DoGetBestAvailableTranslation(const wxString& domain, const wxString& additionalAvailableLanguage);
231
232private:
233 wxString m_lang;
234 wxTranslationsLoader *m_loader;
235
236 wxMsgCatalog *m_pMsgCat; // pointer to linked list of catalogs
237
238 // In addition to keeping all the catalogs in the linked list, we also
239 // store them in a hash map indexed by the domain name to allow finding
240 // them by name efficiently.
241 WX_DECLARE_HASH_MAP(wxString, wxMsgCatalog *, wxStringHash, wxStringEqual, wxMsgCatalogMap)class wxMsgCatalogMap_wxImplementation_Pair { public: typedef
wxString first_type; typedef wxMsgCatalog * second_type; typedef
wxString t1; typedef wxMsgCatalog * t2; typedef const wxString
const_t1; typedef const wxMsgCatalog * const_t2; wxMsgCatalogMap_wxImplementation_Pair
(const const_t1& f, const const_t2& s) : first(const_cast
<t1&>(f)), second(const_cast<t2&>(s)) {} t1
first; t2 second; }; class wxMsgCatalogMap_wxImplementation_KeyEx
{ typedef wxString key_type; typedef wxMsgCatalogMap_wxImplementation_Pair
pair_type; typedef const key_type const_key_type; typedef const
pair_type const_pair_type; typedef const_key_type& const_key_reference
; typedef const_pair_type& const_pair_reference; public: wxMsgCatalogMap_wxImplementation_KeyEx
() { } const_key_reference operator()( const_pair_reference pair
) const { return pair.first; }}; class wxMsgCatalogMap_wxImplementation_HashTable
: protected _wxHashTableBase2 { public: typedef wxString key_type
; typedef wxMsgCatalogMap_wxImplementation_Pair value_type; typedef
wxStringHash hasher; typedef wxStringEqual key_equal; typedef
size_t size_type; typedef ptrdiff_t difference_type; typedef
value_type* pointer; typedef const value_type* const_pointer
; typedef value_type& reference; typedef const value_type
& const_reference; typedef const wxString const_key_type;
typedef const wxMsgCatalogMap_wxImplementation_Pair const_mapped_type
; public: typedef wxMsgCatalogMap_wxImplementation_KeyEx key_extractor
; typedef wxMsgCatalogMap_wxImplementation_HashTable Self; protected
: _wxHashTable_NodeBase** m_table; size_t m_tableBuckets; size_t
m_items; hasher m_hasher; key_equal m_equals; key_extractor m_getKey
; public: struct Node:public _wxHashTable_NodeBase { public: Node
( const value_type& value ) : m_value( value ) {} Node* next
() { return static_cast<Node*>(m_next); } value_type m_value
; }; protected: static void DeleteNode( _wxHashTable_NodeBase
* node ) { delete static_cast<Node*>(node); } public: class
Iterator { public: Node* m_node; Self* m_ht; Iterator() : m_node
(__null), m_ht(__null) {} Iterator( Node* node, const Self* ht
) : m_node(node), m_ht(const_cast<Self*>(ht)) {} bool operator
==( const Iterator& it ) const { return m_node == it.m_node
; } bool operator !=( const Iterator& it ) const { return
m_node != it.m_node; } protected: Node* GetNextNode() { size_type
bucket = GetBucketForNode(m_ht,m_node); for( size_type i = bucket
+ 1; i < m_ht->m_tableBuckets; ++i ) { if( m_ht->m_table
[i] ) return static_cast<Node*>(m_ht->m_table[i]); }
return __null; } void PlusPlus() { Node* next = m_node->next
(); m_node = next ? next : GetNextNode(); } }; friend class Iterator
; public: class iterator : public Iterator { public: iterator
() : Iterator() {} iterator( Node* node, Self* ht ) : Iterator
( node, ht ) {} iterator& operator++() { PlusPlus(); return
*this; } iterator operator++(int) { iterator it=*this;PlusPlus
();return it; } reference operator *() const { return m_node->
m_value; } pointer operator ->() const { return &(m_node
->m_value); } }; class const_iterator : public Iterator { public
: const_iterator() : Iterator() {} const_iterator(iterator i)
: Iterator(i) {} const_iterator( Node* node, const Self* ht )
: Iterator(node, const_cast<Self*>(ht)) {} const_iterator
& operator++() { PlusPlus();return *this; } const_iterator
operator++(int) { const_iterator it=*this;PlusPlus();return it
; } const_reference operator *() const { return m_node->m_value
; } const_pointer operator ->() const { return &(m_node
->m_value); } }; wxMsgCatalogMap_wxImplementation_HashTable
( size_type sz = 10, const hasher& hfun = hasher(), const
key_equal& k_eq = key_equal(), const key_extractor& k_ex
= key_extractor() ) : m_tableBuckets( GetNextPrime( (unsigned
long) sz ) ), m_items( 0 ), m_hasher( hfun ), m_equals( k_eq
), m_getKey( k_ex ) { m_table = (_wxHashTable_NodeBase**)AllocTable
(m_tableBuckets); } wxMsgCatalogMap_wxImplementation_HashTable
( const Self& ht ) : m_table(__null), m_tableBuckets( 0 )
, m_items( ht.m_items ), m_hasher( ht.m_hasher ), m_equals( ht
.m_equals ), m_getKey( ht.m_getKey ) { HashCopy( ht ); } const
Self& operator=( const Self& ht ) { if (&ht != this
) { clear(); m_hasher = ht.m_hasher; m_equals = ht.m_equals; m_getKey
= ht.m_getKey; m_items = ht.m_items; HashCopy( ht ); } return
*this; } ~wxMsgCatalogMap_wxImplementation_HashTable() { clear
(); FreeTable(m_table); } hasher hash_funct() { return m_hasher
; } key_equal key_eq() { return m_equals; } void clear() { DeleteNodes
(m_tableBuckets, m_table, DeleteNode); m_items = 0; } size_type
size() const { return m_items; } size_type max_size() const {
return size_type(-1); } bool empty() const { return size() ==
0; } const_iterator end() const { return const_iterator(__null
, this); } iterator end() { return iterator(__null, this); } const_iterator
begin() const { return const_iterator(static_cast<Node*>
(GetFirstNode(m_tableBuckets, m_table)), this); } iterator begin
() { return iterator(static_cast<Node*>(GetFirstNode(m_tableBuckets
, m_table)), this); } size_type erase( const const_key_type&
key ) { _wxHashTable_NodeBase** node = GetNodePtr(key); if( !
node ) return 0; --m_items; _wxHashTable_NodeBase* temp = (*node
)->m_next; delete static_cast<Node*>(*node); (*node)
= temp; if( never_shrink( m_tableBuckets, m_items ) ) ResizeTable
( GetPreviousPrime( (unsigned long) m_tableBuckets ) - 1 ); return
1; } protected: static size_type GetBucketForNode( Self* ht,
Node* node ) { return ht->m_hasher( ht->m_getKey( node
->m_value ) ) % ht->m_tableBuckets; } static Node* CopyNode
( Node* node ) { return new Node( *node ); } Node* GetOrCreateNode
( const value_type& value, bool& created ) { const const_key_type
& key = m_getKey( value ); size_t bucket = m_hasher( key )
% m_tableBuckets; Node* node = static_cast<Node*>(m_table
[bucket]); while( node ) { if( m_equals( m_getKey( node->m_value
), key ) ) { created = false; return node; } node = node->
next(); } created = true; return CreateNode( value, bucket); }
Node * CreateNode( const value_type& value, size_t bucket
) { Node* node = new Node( value ); node->m_next = m_table
[bucket]; m_table[bucket] = node; ++m_items; if( grow_lf70( m_tableBuckets
, m_items ) ) ResizeTable( m_tableBuckets ); return node; } void
CreateNode( const value_type& value ) { CreateNode(value
, m_hasher( m_getKey(value) ) % m_tableBuckets ); } _wxHashTable_NodeBase
** GetNodePtr(const const_key_type& key) const { size_t bucket
= m_hasher( key ) % m_tableBuckets; _wxHashTable_NodeBase** node
= &m_table[bucket]; while( *node ) { if (m_equals(m_getKey
(static_cast<Node*>(*node)->m_value), key)) return node
; node = &(*node)->m_next; } return __null; } Node* GetNode
( const const_key_type& key ) const { size_t bucket = m_hasher
( key ) % m_tableBuckets; Node* node = static_cast<Node*>
(m_table[bucket]); while( node ) { if( m_equals( m_getKey( node
->m_value ), key ) ) return node; node = node->next(); }
return __null; } void ResizeTable( size_t newSize ) { newSize
= GetNextPrime( (unsigned long)newSize ); _wxHashTable_NodeBase
** srcTable = m_table; size_t srcBuckets = m_tableBuckets; m_table
= (_wxHashTable_NodeBase**)AllocTable( newSize ); m_tableBuckets
= newSize; CopyHashTable( srcTable, srcBuckets, this, m_table
, (BucketFromNode)GetBucketForNode, (ProcessNode)&DummyProcessNode
); FreeTable(srcTable); } void HashCopy( const Self& ht )
{ ResizeTable( ht.size() ); CopyHashTable( ht.m_table, ht.m_tableBuckets
, (_wxHashTableBase2*)this, m_table, (BucketFromNode)GetBucketForNode
, (ProcessNode)CopyNode ); } }; class wxMsgCatalogMap:public wxMsgCatalogMap_wxImplementation_HashTable
{ public: typedef wxMsgCatalog * mapped_type; class Insert_Result
{ public: typedef iterator first_type; typedef bool second_type
; typedef iterator t1; typedef bool t2; typedef const iterator
const_t1; typedef const bool const_t2; Insert_Result(const const_t1
& f, const const_t2& s) : first(const_cast<t1&
>(f)), second(const_cast<t2&>(s)) {} t1 first; t2
second; }; explicit wxMsgCatalogMap( size_type hint = 100, hasher
hf = hasher(), key_equal eq = key_equal() ) : wxMsgCatalogMap_wxImplementation_HashTable
( hint, hf, eq, wxMsgCatalogMap_wxImplementation_KeyEx() ) {}
mapped_type& operator[]( const const_key_type& key )
{ bool created; return GetOrCreateNode( wxMsgCatalogMap_wxImplementation_Pair
( key, mapped_type() ), created)->m_value.second; } const_iterator
find( const const_key_type& key ) const { return const_iterator
( GetNode( key ), this ); } iterator find( const const_key_type
& key ) { return iterator( GetNode( key ), this ); } Insert_Result
insert( const value_type& v ) { bool created; Node *node
= GetOrCreateNode( wxMsgCatalogMap_wxImplementation_Pair( v.
first, v.second ), created); return Insert_Result(iterator(node
, this), created); } size_type erase( const key_type& k )
{ return wxMsgCatalogMap_wxImplementation_HashTable::erase( k
); } void erase( const iterator& it ) { erase( (*it).first
); } size_type count( const const_key_type& key ) { return
GetNode( key ) ? 1u : 0u; } }
;
242 wxMsgCatalogMap m_catalogMap;
243};
244
245
246// abstraction of translations discovery and loading
247class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxTranslationsLoader
248{
249public:
250 wxTranslationsLoader() {}
251 virtual ~wxTranslationsLoader() {}
252
253 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
254 const wxString& lang) = 0;
255
256 virtual wxArrayString GetAvailableTranslations(const wxString& domain) const = 0;
257};
258
259
260// standard wxTranslationsLoader implementation, using filesystem
261class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxFileTranslationsLoader
262 : public wxTranslationsLoader
263{
264public:
265 static void AddCatalogLookupPathPrefix(const wxString& prefix);
266
267 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
268 const wxString& lang) wxOVERRIDEoverride;
269
270 virtual wxArrayString GetAvailableTranslations(const wxString& domain) const wxOVERRIDEoverride;
271};
272
273
274#ifdef __WINDOWS__
275// loads translations from win32 resources
276class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxResourceTranslationsLoader
277 : public wxTranslationsLoader
278{
279public:
280 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
281 const wxString& lang) wxOVERRIDEoverride;
282
283 virtual wxArrayString GetAvailableTranslations(const wxString& domain) const wxOVERRIDEoverride;
284
285protected:
286 // returns resource type to use for translations
287 virtual wxString GetResourceType() const { return wxASCII_STR("MOFILE")wxString::FromAscii("MOFILE"); }
288
289 // returns module to load resources from
290 virtual WXHINSTANCE GetModule() const { return NULL__null; }
291};
292#endif // __WINDOWS__
293
294
295// ----------------------------------------------------------------------------
296// global functions
297// ----------------------------------------------------------------------------
298
299// get the translation of the string in the current locale
300inline const wxString& wxGetTranslation(const wxString& str,
301 const wxString& domain = wxString(),
302 const wxString& context = wxString())
303{
304 wxTranslations *trans = wxTranslations::Get();
305 const wxString *transStr = trans ? trans->GetTranslatedString(str, domain, context)
306 : NULL__null;
307 if ( transStr )
308 return *transStr;
309 else
310 // NB: this function returns reference to a string, so we have to keep
311 // a copy of it somewhere
312 return wxTranslations::GetUntranslatedString(str);
313}
314
315inline const wxString& wxGetTranslation(const wxString& str1,
316 const wxString& str2,
317 unsigned n,
318 const wxString& domain = wxString(),
319 const wxString& context = wxString())
320{
321 wxTranslations *trans = wxTranslations::Get();
322 const wxString *transStr = trans ? trans->GetTranslatedString(str1, n, domain, context)
323 : NULL__null;
324 if ( transStr )
325 return *transStr;
326 else
327 // NB: this function returns reference to a string, so we have to keep
328 // a copy of it somewhere
329 return n == 1
330 ? wxTranslations::GetUntranslatedString(str1)
331 : wxTranslations::GetUntranslatedString(str2);
332}
333
334#ifdef wxNO_IMPLICIT_WXSTRING_ENCODING
335
336/*
337 * It must always be possible to call wxGetTranslation() with const
338 * char* arguments.
339 */
340inline const wxString& wxGetTranslation(const char *str,
341 const char *domain = "",
342 const char *context = "") {
343 const wxMBConv &conv = wxConvWhateverWorkswxGet_wxConvWhateverWorks();
344 return wxGetTranslation(wxString(str, conv), wxString(domain, conv),
345 wxString(context, conv));
346}
347
348inline const wxString& wxGetTranslation(const char *str1,
349 const char *str2,
350 unsigned n,
351 const char *domain = "",
352 const char *context = "") {
353 const wxMBConv &conv = wxConvWhateverWorkswxGet_wxConvWhateverWorks();
354 return wxGetTranslation(wxString(str1, conv), wxString(str2, conv), n,
355 wxString(domain, conv),
356 wxString(context, conv));
357}
358
359#endif // wxNO_IMPLICIT_WXSTRING_ENCODING
360
361#else // !wxUSE_INTL
362
363// the macros should still be defined - otherwise compilation would fail
364
365#if !defined(WXINTL_NO_GETTEXT_MACRO)
366 #if !defined(_)
367#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
368 #define _(s)wxGetTranslation((s)) (s)
369#else
370 #define _(s)wxGetTranslation((s)) wxASCII_STR(s)wxString::FromAscii(s)
371#endif
372 #endif
373 #define wxPLURAL(sing, plur, n)wxGetTranslation((sing), (plur), n) ((n) == 1 ? (sing) : (plur))
374 #define wxGETTEXT_IN_CONTEXT(c, s)wxGetTranslation((s), wxString(), c) (s)
375 #define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n)wxGetTranslation((sing), (plur), n, wxString(), c) wxPLURAL(sing, plur, n)wxGetTranslation((sing), (plur), n)
376#endif
377
378#define wxTRANSLATE(str)str str
379#define wxTRANSLATE_IN_CONTEXT(c, str)str str
380
381// NB: we use a template here in order to avoid using
382// wxLocale::GetUntranslatedString() above, which would be required if
383// we returned const wxString&; this way, the compiler should be able to
384// optimize wxGetTranslation() away
385
386template<typename TString>
387inline TString wxGetTranslation(TString str)
388 { return str; }
389
390template<typename TString, typename TDomain>
391inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain))
392 { return str; }
393
394template<typename TString, typename TDomain, typename TContext>
395inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain), TContext WXUNUSED(context))
396 { return str; }
397
398template<typename TString, typename TDomain>
399inline TString wxGetTranslation(TString str1, TString str2, size_t n)
400 { return n == 1 ? str1 : str2; }
401
402template<typename TString, typename TDomain>
403inline TString wxGetTranslation(TString str1, TString str2, size_t n,
404 TDomain WXUNUSED(domain))
405 { return n == 1 ? str1 : str2; }
406
407template<typename TString, typename TDomain, typename TContext>
408inline TString wxGetTranslation(TString str1, TString str2, size_t n,
409 TDomain WXUNUSED(domain),
410 TContext WXUNUSED(context))
411 { return n == 1 ? str1 : str2; }
412
413#endif // wxUSE_INTL/!wxUSE_INTL
414
415// define this one just in case it occurs somewhere (instead of preferred
416// wxTRANSLATE) too
417#if !defined(WXINTL_NO_GETTEXT_MACRO)
418 #if !defined(gettext_noop)
419 #define gettext_noop(str)(str) (str)
420 #endif
421 #if !defined(N_)
422 #define N_(s)(s) (s)
423 #endif
424#endif
425
426#endif // _WX_TRANSLATION_H_