/src/ki18n/src/i18n/gettext.h
Line | Count | Source |
1 | | /* Convenience header for conditional use of GNU <libintl.h>. |
2 | | SPDX-FileCopyrightText: 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc. |
3 | | |
4 | | SPDX-License-Identifier: LGPL-2.0-or-later |
5 | | */ |
6 | | // clang-format off |
7 | | #ifndef _LIBGETTEXT_H |
8 | | #define _LIBGETTEXT_H 1 |
9 | | |
10 | | /* Get declarations of GNU message catalog functions. */ |
11 | | # include <libintl.h> |
12 | | // libintl.h redefines inline which causes MSVC to abort compilation with the message |
13 | | // fatal error C1189: #error : The C++ Standard Library forbids macroizing keywords |
14 | | #undef inline |
15 | | |
16 | | /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by |
17 | | the gettext() and ngettext() macros. This is an alternative to calling |
18 | | textdomain(), and is useful for libraries. */ |
19 | | # ifdef DEFAULT_TEXT_DOMAIN |
20 | | # undef gettext |
21 | | # define gettext(Msgid) \ |
22 | | dgettext (DEFAULT_TEXT_DOMAIN, Msgid) |
23 | | # undef ngettext |
24 | | # define ngettext(Msgid1, Msgid2, N) \ |
25 | | dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) |
26 | | # endif |
27 | | |
28 | | /* The separator between msgctxt and msgid in a .mo file. */ |
29 | | #define GETTEXT_CONTEXT_GLUE "\004" |
30 | | |
31 | | /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a |
32 | | MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be |
33 | | short and rarely need to change. |
34 | | The letter 'p' stands for 'particular' or 'special'. */ |
35 | | #ifdef DEFAULT_TEXT_DOMAIN |
36 | | # define pgettext(Msgctxt, Msgid) \ |
37 | | pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid) |
38 | | #else |
39 | | # define pgettext(Msgctxt, Msgid) \ |
40 | | pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid) |
41 | | #endif |
42 | | #define dpgettext(Domainname, Msgctxt, Msgid) \ |
43 | | pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid) |
44 | | |
45 | | #ifdef __GNUC__ |
46 | | __inline |
47 | | #else |
48 | | #ifdef __cplusplus |
49 | | inline |
50 | | #endif |
51 | | #endif |
52 | | static const char * |
53 | | pgettext_aux(const char *domain, |
54 | | const char *msg_ctxt_id, const char *msgid) |
55 | 0 | { |
56 | 0 | const char *translation = dgettext(domain, msg_ctxt_id); |
57 | 0 | if (translation == msg_ctxt_id) { |
58 | 0 | return msgid; |
59 | 0 | } else { |
60 | 0 | return translation; |
61 | 0 | } |
62 | 0 | } |
63 | | |
64 | | /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID |
65 | | can be arbitrary expressions. But for string literals these macros are |
66 | | less efficient than those above. */ |
67 | | |
68 | | #include <string.h> |
69 | | |
70 | | #ifndef __STRICT_ANSI__ |
71 | | #define __STRICT_ANSI__ |
72 | | #define __STRICT_ANSI_FORCED__ |
73 | | #endif |
74 | | |
75 | | #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ |
76 | | (__STRICT_ANSI__ - 0 == 0) && (__GNUC__ >= 3 || __GNUG__ >= 2 /* || __STDC_VERSION__ >= 199901L */ ) |
77 | | |
78 | | #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS |
79 | | #include <stdlib.h> |
80 | | #endif |
81 | | |
82 | | #define pgettext_expr(Msgctxt, Msgid) \ |
83 | | dpgettext_expr (NULL, Msgctxt, Msgid) |
84 | | #define dpgettext_expr(Domainname, Msgctxt, Msgid) \ |
85 | 0 | dpgettext_expr (Domainname, Msgctxt, Msgid) |
86 | | |
87 | | #ifdef __GNUC__ |
88 | | __inline |
89 | | #else |
90 | | #ifdef __cplusplus |
91 | | inline |
92 | | #endif |
93 | | #endif |
94 | | static const char * |
95 | | dpgettext_expr(const char *domain, |
96 | | const char *msgctxt, const char *msgid) |
97 | 0 | { |
98 | 0 | size_t msgctxt_len = strlen(msgctxt) + 1; |
99 | 0 | size_t msgid_len = strlen(msgid) + 1; |
100 | 0 | const char *translation; |
101 | 0 | int translation_found; |
102 | | #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS |
103 | | char msg_ctxt_id[msgctxt_len + msgid_len]; |
104 | | #else |
105 | 0 | char buf[1024]; |
106 | 0 | char *msg_ctxt_id = |
107 | 0 | (msgctxt_len + msgid_len <= sizeof(buf) |
108 | 0 | ? buf |
109 | 0 | : (char *) malloc(msgctxt_len + msgid_len)); |
110 | 0 | if (msg_ctxt_id != nullptr) |
111 | 0 | #endif |
112 | 0 | { |
113 | 0 | memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1); |
114 | 0 | msg_ctxt_id[msgctxt_len - 1] = '\004'; |
115 | 0 | memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len); |
116 | 0 | translation = dgettext(domain, msg_ctxt_id); |
117 | | /* Test must occur before msg_ctxt_id freed */ |
118 | 0 | translation_found = translation != msg_ctxt_id; |
119 | 0 | #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS |
120 | 0 | if (msg_ctxt_id != buf) { |
121 | 0 | free(msg_ctxt_id); |
122 | 0 | } |
123 | 0 | #endif |
124 | 0 | if (translation_found) { |
125 | 0 | return translation; |
126 | 0 | } |
127 | 0 | } |
128 | 0 | return msgid; |
129 | 0 | } |
130 | | |
131 | | #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ |
132 | | dnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N) |
133 | | #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ |
134 | 0 | dnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N) |
135 | | |
136 | | #ifdef __GNUC__ |
137 | | __inline |
138 | | #else |
139 | | #ifdef __cplusplus |
140 | | inline |
141 | | #endif |
142 | | #endif |
143 | | static const char * |
144 | | dnpgettext_expr(const char *domain, |
145 | | const char *msgctxt, const char *msgid, |
146 | | const char *msgid_plural, unsigned long int n) |
147 | 0 | { |
148 | 0 | size_t msgctxt_len = strlen(msgctxt) + 1; |
149 | 0 | size_t msgid_len = strlen(msgid) + 1; |
150 | 0 | const char *translation; |
151 | 0 | int translation_found; |
152 | | #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS |
153 | | char msg_ctxt_id[msgctxt_len + msgid_len]; |
154 | | #else |
155 | 0 | char buf[1024]; |
156 | 0 | char *msg_ctxt_id = |
157 | 0 | (msgctxt_len + msgid_len <= sizeof(buf) |
158 | 0 | ? buf |
159 | 0 | : (char *) malloc(msgctxt_len + msgid_len)); |
160 | 0 | if (msg_ctxt_id != nullptr) |
161 | 0 | #endif |
162 | 0 | { |
163 | 0 | memcpy(msg_ctxt_id, msgctxt, msgctxt_len - 1); |
164 | 0 | msg_ctxt_id[msgctxt_len - 1] = '\004'; |
165 | 0 | memcpy(msg_ctxt_id + msgctxt_len, msgid, msgid_len); |
166 | 0 | translation = dngettext(domain, msg_ctxt_id, msgid_plural, n); |
167 | | /* Test must occur before msg_ctxt_id freed */ |
168 | 0 | translation_found = !(translation == msg_ctxt_id || translation == msgid_plural); |
169 | 0 | #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS |
170 | 0 | if (msg_ctxt_id != buf) { |
171 | 0 | free(msg_ctxt_id); |
172 | 0 | } |
173 | 0 | #endif |
174 | 0 | if (translation_found) { |
175 | 0 | return translation; |
176 | 0 | } |
177 | 0 | } |
178 | 0 | return (n == 1 ? msgid : msgid_plural); |
179 | 0 | } |
180 | | |
181 | | #ifdef __STRICT_ANSI_FORCED__ |
182 | | #undef __STRICT_ANSI__ |
183 | | #undef __STRICT_ANSI_FORCED__ |
184 | | #endif |
185 | | |
186 | | #endif /* _LIBGETTEXT_H */ |
187 | | // clang-format on |