-rw-r--r-- | development/translation/opie-lupdate/fetchtr.cpp | 55 | ||||
-rw-r--r-- | development/translation/opie-lupdate/main.cpp | 11 | ||||
-rw-r--r-- | development/translation/opie-lupdate/merge.cpp | 6 | ||||
-rw-r--r-- | development/translation/opie-lupdate/numberh.cpp | 28 | ||||
-rw-r--r-- | development/translation/opie-lupdate/sametexth.cpp | 6 | ||||
-rw-r--r-- | development/translation/shared/metatranslator.cpp | 34 | ||||
-rw-r--r-- | development/translation/shared/metatranslator.h | 16 | ||||
-rw-r--r-- | development/translation/shared/opie.h | 2 | ||||
-rw-r--r-- | development/translation/shared/proparser.cpp | 111 | ||||
-rw-r--r-- | development/translation/shared/proparser.h | 8 |
10 files changed, 228 insertions, 49 deletions
diff --git a/development/translation/opie-lupdate/fetchtr.cpp b/development/translation/opie-lupdate/fetchtr.cpp index d1f5881..a137628 100644 --- a/development/translation/opie-lupdate/fetchtr.cpp +++ b/development/translation/opie-lupdate/fetchtr.cpp | |||
@@ -1,466 +1,501 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #include <metatranslator.h> | 27 | #include <metatranslator.h> |
22 | 28 | ||
23 | #include <qfile.h> | 29 | #include <qfile.h> |
24 | #include <qregexp.h> | 30 | #include <qregexp.h> |
25 | #include <qstring.h> | 31 | #include <qstring.h> |
26 | #include <qtextstream.h> | 32 | #include <qtextstream.h> |
27 | #include <qvaluestack.h> | 33 | #include <qvaluestack.h> |
28 | #include <qxml.h> | 34 | #include <qxml.h> |
29 | 35 | ||
30 | #include <ctype.h> | 36 | #include <ctype.h> |
31 | #include <errno.h> | 37 | #include <errno.h> |
32 | #include <stdio.h> | 38 | #include <stdio.h> |
33 | #include <string.h> | 39 | #include <string.h> |
34 | 40 | ||
35 | /* qmake ignore Q_OBJECT */ | 41 | /* qmake ignore Q_OBJECT */ |
36 | 42 | ||
37 | static const char MagicComment[] = "TRANSLATOR "; | 43 | static const char MagicComment[] = "TRANSLATOR "; |
38 | 44 | ||
39 | static QMap<QCString, int> needs_Q_OBJECT; | 45 | static QMap<QCString, int> needs_Q_OBJECT; |
40 | static QMap<QCString, int> lacks_Q_OBJECT; | 46 | static QMap<QCString, int> lacks_Q_OBJECT; |
41 | 47 | ||
42 | /* | 48 | /* |
43 | The first part of this source file is the C++ tokenizer. We skip | 49 | The first part of this source file is the C++ tokenizer. We skip |
44 | most of C++; the only tokens that interest us are defined here. | 50 | most of C++; the only tokens that interest us are defined here. |
45 | Thus, the code fragment | 51 | Thus, the code fragment |
46 | 52 | ||
47 | int main() | 53 | int main() |
48 | { | 54 | { |
49 | printf( "Hello, world!\n" ); | 55 | printf( "Hello, world!\n" ); |
50 | return 0; | 56 | return 0; |
51 | } | 57 | } |
52 | 58 | ||
53 | is broken down into the following tokens (Tok_ omitted): | 59 | is broken down into the following tokens (Tok_ omitted): |
54 | 60 | ||
55 | Ident Ident LeftParen RightParen | 61 | Ident Ident LeftParen RightParen |
56 | LeftBrace | 62 | LeftBrace |
57 | Ident LeftParen String RightParen Semicolon | 63 | Ident LeftParen String RightParen Semicolon |
58 | return Semicolon | 64 | return Semicolon |
59 | RightBrace. | 65 | RightBrace. |
60 | 66 | ||
61 | The 0 doesn't produce any token. | 67 | The 0 doesn't produce any token. |
62 | */ | 68 | */ |
63 | 69 | ||
64 | enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr, | 70 | enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr, |
65 | Tok_trUtf8, Tok_translate, Tok_Q_OBJECT, Tok_Ident, | 71 | Tok_trUtf8, Tok_translate, Tok_Q_OBJECT, Tok_Ident, |
66 | Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, | 72 | Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, |
67 | Tok_Gulbrandsen, Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen, | 73 | Tok_Gulbrandsen, Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen, |
68 | Tok_RightParen, Tok_Comma, Tok_Semicolon }; | 74 | Tok_RightParen, Tok_Comma, Tok_Semicolon }; |
69 | 75 | ||
70 | /* | 76 | /* |
71 | The tokenizer maintains the following global variables. The names | 77 | The tokenizer maintains the following global variables. The names |
72 | should be self-explanatory. | 78 | should be self-explanatory. |
73 | */ | 79 | */ |
74 | static QCString yyFileName; | 80 | static QCString yyFileName; |
75 | static int yyCh; | 81 | static int yyCh; |
76 | static char yyIdent[128]; | 82 | static char yyIdent[128]; |
77 | static size_t yyIdentLen; | 83 | static size_t yyIdentLen; |
78 | static char yyComment[65536]; | 84 | static char yyComment[65536]; |
79 | static size_t yyCommentLen; | 85 | static size_t yyCommentLen; |
80 | static char yyString[16384]; | 86 | static char yyString[16384]; |
81 | static size_t yyStringLen; | 87 | static size_t yyStringLen; |
82 | static QValueStack<int> yySavedBraceDepth; | 88 | static QValueStack<int> yySavedBraceDepth; |
89 | static QValueStack<int> yySavedParenDepth; | ||
83 | static int yyBraceDepth; | 90 | static int yyBraceDepth; |
84 | static int yyParenDepth; | 91 | static int yyParenDepth; |
85 | static int yyLineNo; | 92 | static int yyLineNo; |
86 | static int yyCurLineNo; | 93 | static int yyCurLineNo; |
94 | static int yyBraceLineNo; | ||
95 | static int yyParenLineNo; | ||
87 | 96 | ||
88 | // the file to read from (if reading from a file) | 97 | // the file to read from (if reading from a file) |
89 | static FILE *yyInFile; | 98 | static FILE *yyInFile; |
90 | 99 | ||
91 | // the string to read from and current position in the string (otherwise) | 100 | // the string to read from and current position in the string (otherwise) |
92 | static QString yyInStr; | 101 | static QString yyInStr; |
93 | static int yyInPos; | 102 | static int yyInPos; |
94 | 103 | ||
95 | static int (*getChar)(); | 104 | static int (*getChar)(); |
96 | 105 | ||
97 | static int getCharFromFile() | 106 | static int getCharFromFile() |
98 | { | 107 | { |
99 | int c = getc( yyInFile ); | 108 | int c = getc( yyInFile ); |
100 | if ( c == '\n' ) | 109 | if ( c == '\n' ) |
101 | yyCurLineNo++; | 110 | yyCurLineNo++; |
102 | return c; | 111 | return c; |
103 | } | 112 | } |
104 | 113 | ||
105 | static int getCharFromString() | 114 | static int getCharFromString() |
106 | { | 115 | { |
107 | if ( yyInPos == (int) yyInStr.length() ) { | 116 | if ( yyInPos == (int) yyInStr.length() ) { |
108 | return EOF; | 117 | return EOF; |
109 | } else { | 118 | } else { |
110 | return yyInStr[yyInPos++].latin1(); | 119 | return yyInStr[yyInPos++].latin1(); |
111 | } | 120 | } |
112 | } | 121 | } |
113 | 122 | ||
114 | static void startTokenizer( const char *fileName, int (*getCharFunc)() ) | 123 | static void startTokenizer( const char *fileName, int (*getCharFunc)() ) |
115 | { | 124 | { |
116 | yyInPos = 0; | 125 | yyInPos = 0; |
117 | getChar = getCharFunc; | 126 | getChar = getCharFunc; |
118 | 127 | ||
119 | yyFileName = fileName; | 128 | yyFileName = fileName; |
120 | yyCh = getChar(); | 129 | yyCh = getChar(); |
121 | yySavedBraceDepth.clear(); | 130 | yySavedBraceDepth.clear(); |
131 | yySavedParenDepth.clear(); | ||
122 | yyBraceDepth = 0; | 132 | yyBraceDepth = 0; |
123 | yyParenDepth = 0; | 133 | yyParenDepth = 0; |
124 | yyCurLineNo = 1; | 134 | yyCurLineNo = 1; |
135 | yyBraceLineNo = 1; | ||
136 | yyParenLineNo = 1; | ||
125 | } | 137 | } |
126 | 138 | ||
127 | static int getToken() | 139 | static int getToken() |
128 | { | 140 | { |
129 | const char tab[] = "abfnrtv"; | 141 | const char tab[] = "abfnrtv"; |
130 | const char backTab[] = "\a\b\f\n\r\t\v"; | 142 | const char backTab[] = "\a\b\f\n\r\t\v"; |
131 | uint n; | 143 | uint n; |
132 | 144 | ||
133 | yyIdentLen = 0; | 145 | yyIdentLen = 0; |
134 | yyCommentLen = 0; | 146 | yyCommentLen = 0; |
135 | yyStringLen = 0; | 147 | yyStringLen = 0; |
136 | 148 | ||
137 | while ( yyCh != EOF ) { | 149 | while ( yyCh != EOF ) { |
138 | yyLineNo = yyCurLineNo; | 150 | yyLineNo = yyCurLineNo; |
139 | 151 | ||
140 | if ( isalpha(yyCh) || yyCh == '_' ) { | 152 | if ( isalpha(yyCh) || yyCh == '_' ) { |
141 | do { | 153 | do { |
142 | if ( yyIdentLen < sizeof(yyIdent) - 1 ) | 154 | if ( yyIdentLen < sizeof(yyIdent) - 1 ) |
143 | yyIdent[yyIdentLen++] = (char) yyCh; | 155 | yyIdent[yyIdentLen++] = (char) yyCh; |
144 | yyCh = getChar(); | 156 | yyCh = getChar(); |
145 | } while ( isalnum(yyCh) || yyCh == '_' ); | 157 | } while ( isalnum(yyCh) || yyCh == '_' ); |
146 | yyIdent[yyIdentLen] = '\0'; | 158 | yyIdent[yyIdentLen] = '\0'; |
147 | 159 | ||
148 | switch ( yyIdent[0] ) { | 160 | switch ( yyIdent[0] ) { |
149 | case 'Q': | 161 | case 'Q': |
150 | if ( strcmp(yyIdent + 1, "_OBJECT") == 0 ) { | 162 | if ( strcmp(yyIdent + 1, "_OBJECT") == 0 ) { |
151 | return Tok_Q_OBJECT; | 163 | return Tok_Q_OBJECT; |
152 | } else if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) { | 164 | } else if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) { |
153 | return Tok_tr; | 165 | return Tok_tr; |
154 | } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) { | 166 | } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) { |
155 | return Tok_translate; | 167 | return Tok_translate; |
156 | } | 168 | } |
157 | break; | 169 | break; |
158 | case 'T': | 170 | case 'T': |
159 | // TR() for when all else fails | 171 | // TR() for when all else fails |
160 | if ( qstricmp(yyIdent + 1, "R") == 0 ) | 172 | if ( qstricmp(yyIdent + 1, "R") == 0 ) |
161 | return Tok_tr; | 173 | return Tok_tr; |
162 | break; | 174 | break; |
163 | case 'c': | 175 | case 'c': |
164 | if ( strcmp(yyIdent + 1, "lass") == 0 ) | 176 | if ( strcmp(yyIdent + 1, "lass") == 0 ) |
165 | return Tok_class; | 177 | return Tok_class; |
166 | break; | 178 | break; |
179 | case 'f': | ||
180 | /* | ||
181 | QTranslator::findMessage() has the same parameters as | ||
182 | QApplication::translate(). | ||
183 | */ | ||
184 | if ( strcmp(yyIdent + 1, "indMessage") == 0 ) | ||
185 | return Tok_translate; | ||
186 | break; | ||
187 | case 'i': | ||
188 | /* FOR KDE APPS */ | ||
189 | if ( strcmp( yyIdent + 1, "8n") == 0 ) | ||
190 | return Tok_translate; | ||
191 | break; | ||
167 | case 'n': | 192 | case 'n': |
168 | if ( strcmp(yyIdent + 1, "amespace") == 0 ) | 193 | if ( strcmp(yyIdent + 1, "amespace") == 0 ) |
169 | return Tok_namespace; | 194 | return Tok_namespace; |
170 | break; | 195 | break; |
171 | case 'r': | 196 | case 'r': |
172 | if ( strcmp(yyIdent + 1, "eturn") == 0 ) | 197 | if ( strcmp(yyIdent + 1, "eturn") == 0 ) |
173 | return Tok_return; | 198 | return Tok_return; |
174 | break; | 199 | break; |
175 | case 's': | 200 | case 's': |
176 | if ( strcmp(yyIdent + 1, "truct") == 0 ) | 201 | if ( strcmp(yyIdent + 1, "truct") == 0 ) |
177 | return Tok_class; | 202 | return Tok_class; |
178 | break; | 203 | break; |
179 | case 'i': | ||
180 | if( strcmp(yyIdent + 1, "18n") == 0 ) | ||
181 | return Tok_tr; | ||
182 | case 't': | 204 | case 't': |
183 | if ( strcmp(yyIdent + 1, "r") == 0 ) { | 205 | if ( strcmp(yyIdent + 1, "r") == 0 ) { |
184 | return Tok_tr; | 206 | return Tok_tr; |
185 | } else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) { | 207 | } else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) { |
186 | return Tok_trUtf8; | 208 | return Tok_trUtf8; |
187 | } else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) { | 209 | } else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) { |
188 | return Tok_translate; | 210 | return Tok_translate; |
189 | } | 211 | } |
190 | } | 212 | } |
191 | return Tok_Ident; | 213 | return Tok_Ident; |
192 | } else { | 214 | } else { |
193 | switch ( yyCh ) { | 215 | switch ( yyCh ) { |
194 | case '#': | 216 | case '#': |
195 | /* | 217 | /* |
196 | Early versions of lupdate complained about | 218 | Early versions of lupdate complained about |
197 | unbalanced braces in the following code: | 219 | unbalanced braces in the following code: |
198 | 220 | ||
199 | #ifdef ALPHA | 221 | #ifdef ALPHA |
200 | while ( beta ) { | 222 | while ( beta ) { |
201 | #else | 223 | #else |
202 | while ( gamma ) { | 224 | while ( gamma ) { |
203 | #endif | 225 | #endif |
204 | delta; | 226 | delta; |
205 | } | 227 | } |
206 | 228 | ||
207 | The code contains, indeed, two opening braces for | 229 | The code contains, indeed, two opening braces for |
208 | one closing brace; yet there's no reason to panic. | 230 | one closing brace; yet there's no reason to panic. |
209 | 231 | ||
210 | The solution is to remember yyBraceDepth as it was | 232 | The solution is to remember yyBraceDepth as it was |
211 | when #if, #ifdef or #ifndef was met, and to set | 233 | when #if, #ifdef or #ifndef was met, and to set |
212 | yyBraceDepth to that value when meeting #elif or | 234 | yyBraceDepth to that value when meeting #elif or |
213 | #else. | 235 | #else. |
214 | */ | 236 | */ |
215 | do { | 237 | do { |
216 | yyCh = getChar(); | 238 | yyCh = getChar(); |
217 | } while ( isspace(yyCh) && yyCh != '\n' ); | 239 | } while ( isspace(yyCh) && yyCh != '\n' ); |
218 | 240 | ||
219 | switch ( yyCh ) { | 241 | switch ( yyCh ) { |
220 | case 'i': | 242 | case 'i': |
221 | yyCh = getChar(); | 243 | yyCh = getChar(); |
222 | if ( yyCh == 'f' ) { | 244 | if ( yyCh == 'f' ) { |
223 | // if, ifdef, ifndef | 245 | // if, ifdef, ifndef |
224 | yySavedBraceDepth.push( yyBraceDepth ); | 246 | yySavedBraceDepth.push( yyBraceDepth ); |
247 | yySavedParenDepth.push( yyParenDepth ); | ||
225 | } | 248 | } |
226 | break; | 249 | break; |
227 | case 'e': | 250 | case 'e': |
228 | yyCh = getChar(); | 251 | yyCh = getChar(); |
229 | if ( yyCh == 'l' ) { | 252 | if ( yyCh == 'l' ) { |
230 | // elif, else | 253 | // elif, else |
231 | if ( !yySavedBraceDepth.isEmpty() ) | 254 | if ( !yySavedBraceDepth.isEmpty() ) { |
232 | yyBraceDepth = yySavedBraceDepth.top(); | 255 | yyBraceDepth = yySavedBraceDepth.top(); |
256 | yyParenDepth = yySavedParenDepth.top(); | ||
257 | } | ||
233 | } else if ( yyCh == 'n' ) { | 258 | } else if ( yyCh == 'n' ) { |
234 | // endif | 259 | // endif |
235 | if ( !yySavedBraceDepth.isEmpty() ) | 260 | if ( !yySavedBraceDepth.isEmpty() ) { |
236 | yySavedBraceDepth.pop(); | 261 | yySavedBraceDepth.pop(); |
262 | yySavedParenDepth.pop(); | ||
263 | } | ||
237 | } | 264 | } |
238 | } | 265 | } |
239 | while ( isalnum(yyCh) || yyCh == '_' ) | 266 | while ( isalnum(yyCh) || yyCh == '_' ) |
240 | yyCh = getChar(); | 267 | yyCh = getChar(); |
241 | break; | 268 | break; |
242 | case '/': | 269 | case '/': |
243 | yyCh = getChar(); | 270 | yyCh = getChar(); |
244 | if ( yyCh == '/' ) { | 271 | if ( yyCh == '/' ) { |
245 | do { | 272 | do { |
246 | yyCh = getChar(); | 273 | yyCh = getChar(); |
247 | } while ( yyCh != EOF && yyCh != '\n' ); | 274 | } while ( yyCh != EOF && yyCh != '\n' ); |
248 | } else if ( yyCh == '*' ) { | 275 | } else if ( yyCh == '*' ) { |
249 | bool metAster = FALSE; | 276 | bool metAster = FALSE; |
250 | bool metAsterSlash = FALSE; | 277 | bool metAsterSlash = FALSE; |
251 | 278 | ||
252 | while ( !metAsterSlash ) { | 279 | while ( !metAsterSlash ) { |
253 | yyCh = getChar(); | 280 | yyCh = getChar(); |
254 | if ( yyCh == EOF ) { | 281 | if ( yyCh == EOF ) { |
255 | fprintf( stderr, | 282 | fprintf( stderr, |
256 | "%s: Unterminated C++ comment starting at" | 283 | "%s: Unterminated C++ comment starting at" |
257 | " line %d\n", | 284 | " line %d\n", |
258 | (const char *) yyFileName, yyLineNo ); | 285 | (const char *) yyFileName, yyLineNo ); |
259 | yyComment[yyCommentLen] = '\0'; | 286 | yyComment[yyCommentLen] = '\0'; |
260 | return Tok_Comment; | 287 | return Tok_Comment; |
261 | } | 288 | } |
262 | if ( yyCommentLen < sizeof(yyComment) - 1 ) | 289 | if ( yyCommentLen < sizeof(yyComment) - 1 ) |
263 | yyComment[yyCommentLen++] = (char) yyCh; | 290 | yyComment[yyCommentLen++] = (char) yyCh; |
264 | 291 | ||
265 | if ( yyCh == '*' ) | 292 | if ( yyCh == '*' ) |
266 | metAster = TRUE; | 293 | metAster = TRUE; |
267 | else if ( metAster && yyCh == '/' ) | 294 | else if ( metAster && yyCh == '/' ) |
268 | metAsterSlash = TRUE; | 295 | metAsterSlash = TRUE; |
269 | else | 296 | else |
270 | metAster = FALSE; | 297 | metAster = FALSE; |
271 | } | 298 | } |
272 | yyCh = getChar(); | 299 | yyCh = getChar(); |
273 | yyCommentLen -= 2; | 300 | yyCommentLen -= 2; |
274 | yyComment[yyCommentLen] = '\0'; | 301 | yyComment[yyCommentLen] = '\0'; |
275 | return Tok_Comment; | 302 | return Tok_Comment; |
276 | } | 303 | } |
277 | break; | 304 | break; |
278 | case '"': | 305 | case '"': |
279 | yyCh = getChar(); | 306 | yyCh = getChar(); |
280 | 307 | ||
281 | while ( yyCh != EOF && yyCh != '\n' && yyCh != '"' ) { | 308 | while ( yyCh != EOF && yyCh != '\n' && yyCh != '"' ) { |
282 | if ( yyCh == '\\' ) { | 309 | if ( yyCh == '\\' ) { |
283 | yyCh = getChar(); | 310 | yyCh = getChar(); |
284 | 311 | ||
285 | if ( yyCh == '\n' ) { | 312 | if ( yyCh == '\n' ) { |
286 | yyCh = getChar(); | 313 | yyCh = getChar(); |
287 | } else if ( yyCh == 'x' ) { | 314 | } else if ( yyCh == 'x' ) { |
288 | QCString hex = "0"; | 315 | QCString hex = "0"; |
289 | 316 | ||
290 | yyCh = getChar(); | 317 | yyCh = getChar(); |
291 | while ( isxdigit(yyCh) ) { | 318 | while ( isxdigit(yyCh) ) { |
292 | hex += (char) yyCh; | 319 | hex += (char) yyCh; |
293 | yyCh = getChar(); | 320 | yyCh = getChar(); |
294 | } | 321 | } |
295 | sscanf( hex, "%x", &n ); | 322 | sscanf( hex, "%x", &n ); |
296 | if ( yyStringLen < sizeof(yyString) - 1 ) | 323 | if ( yyStringLen < sizeof(yyString) - 1 ) |
297 | yyString[yyStringLen++] = (char) n; | 324 | yyString[yyStringLen++] = (char) n; |
298 | } else if ( yyCh >= '0' && yyCh < '8' ) { | 325 | } else if ( yyCh >= '0' && yyCh < '8' ) { |
299 | QCString oct = ""; | 326 | QCString oct = ""; |
300 | 327 | ||
301 | do { | 328 | do { |
302 | oct += (char) yyCh; | 329 | oct += (char) yyCh; |
303 | yyCh = getChar(); | 330 | yyCh = getChar(); |
304 | } while ( yyCh >= '0' && yyCh < '8' ); | 331 | } while ( yyCh >= '0' && yyCh < '8' ); |
305 | sscanf( oct, "%o", &n ); | 332 | sscanf( oct, "%o", &n ); |
306 | if ( yyStringLen < sizeof(yyString) - 1 ) | 333 | if ( yyStringLen < sizeof(yyString) - 1 ) |
307 | yyString[yyStringLen++] = (char) n; | 334 | yyString[yyStringLen++] = (char) n; |
308 | } else { | 335 | } else { |
309 | const char *p = strchr( tab, yyCh ); | 336 | const char *p = strchr( tab, yyCh ); |
310 | if ( yyStringLen < sizeof(yyString) - 1 ) | 337 | if ( yyStringLen < sizeof(yyString) - 1 ) |
311 | yyString[yyStringLen++] = ( p == 0 ) ? | 338 | yyString[yyStringLen++] = ( p == 0 ) ? |
312 | (char) yyCh : backTab[p - tab]; | 339 | (char) yyCh : backTab[p - tab]; |
313 | yyCh = getChar(); | 340 | yyCh = getChar(); |
314 | } | 341 | } |
315 | } else { | 342 | } else { |
316 | if ( yyStringLen < sizeof(yyString) - 1 ) | 343 | if ( yyStringLen < sizeof(yyString) - 1 ) |
317 | yyString[yyStringLen++] = (char) yyCh; | 344 | yyString[yyStringLen++] = (char) yyCh; |
318 | yyCh = getChar(); | 345 | yyCh = getChar(); |
319 | } | 346 | } |
320 | } | 347 | } |
321 | yyString[yyStringLen] = '\0'; | 348 | yyString[yyStringLen] = '\0'; |
322 | 349 | ||
323 | if ( yyCh != '"' ) | 350 | if ( yyCh != '"' ) |
324 | qWarning( "%s:%d: Unterminated C++ string", | 351 | qWarning( "%s:%d: Unterminated C++ string", |
325 | (const char *) yyFileName, yyLineNo ); | 352 | (const char *) yyFileName, yyLineNo ); |
326 | 353 | ||
327 | if ( yyCh == EOF ) { | 354 | if ( yyCh == EOF ) { |
328 | return Tok_Eof; | 355 | return Tok_Eof; |
329 | } else { | 356 | } else { |
330 | yyCh = getChar(); | 357 | yyCh = getChar(); |
331 | return Tok_String; | 358 | return Tok_String; |
332 | } | 359 | } |
333 | break; | 360 | break; |
334 | case '-': | 361 | case '-': |
335 | yyCh = getChar(); | 362 | yyCh = getChar(); |
336 | if ( yyCh == '>' ) { | 363 | if ( yyCh == '>' ) { |
337 | yyCh = getChar(); | 364 | yyCh = getChar(); |
338 | return Tok_Arrow; | 365 | return Tok_Arrow; |
339 | } | 366 | } |
340 | break; | 367 | break; |
341 | case ':': | 368 | case ':': |
342 | yyCh = getChar(); | 369 | yyCh = getChar(); |
343 | if ( yyCh == ':' ) { | 370 | if ( yyCh == ':' ) { |
344 | yyCh = getChar(); | 371 | yyCh = getChar(); |
345 | return Tok_Gulbrandsen; | 372 | return Tok_Gulbrandsen; |
346 | } | 373 | } |
347 | return Tok_Colon; | 374 | return Tok_Colon; |
348 | case '\'': | 375 | case '\'': |
349 | yyCh = getChar(); | 376 | yyCh = getChar(); |
350 | if ( yyCh == '\\' ) | 377 | if ( yyCh == '\\' ) |
351 | yyCh = getChar(); | 378 | yyCh = getChar(); |
352 | 379 | ||
353 | do { | 380 | do { |
354 | yyCh = getChar(); | 381 | yyCh = getChar(); |
355 | } while ( yyCh != EOF && yyCh != '\'' ); | 382 | } while ( yyCh != EOF && yyCh != '\'' ); |
356 | yyCh = getChar(); | 383 | yyCh = getChar(); |
357 | break; | 384 | break; |
358 | case '{': | 385 | case '{': |
386 | if (yyBraceDepth == 0) | ||
387 | yyBraceLineNo = yyCurLineNo; | ||
359 | yyBraceDepth++; | 388 | yyBraceDepth++; |
360 | yyCh = getChar(); | 389 | yyCh = getChar(); |
361 | return Tok_LeftBrace; | 390 | return Tok_LeftBrace; |
362 | case '}': | 391 | case '}': |
392 | if (yyBraceDepth == 0) | ||
393 | yyBraceLineNo = yyCurLineNo; | ||
363 | yyBraceDepth--; | 394 | yyBraceDepth--; |
364 | yyCh = getChar(); | 395 | yyCh = getChar(); |
365 | return Tok_RightBrace; | 396 | return Tok_RightBrace; |
366 | case '(': | 397 | case '(': |
398 | if (yyParenDepth == 0) | ||
399 | yyParenLineNo = yyCurLineNo; | ||
367 | yyParenDepth++; | 400 | yyParenDepth++; |
368 | yyCh = getChar(); | 401 | yyCh = getChar(); |
369 | return Tok_LeftParen; | 402 | return Tok_LeftParen; |
370 | case ')': | 403 | case ')': |
404 | if (yyParenDepth == 0) | ||
405 | yyParenLineNo = yyCurLineNo; | ||
371 | yyParenDepth--; | 406 | yyParenDepth--; |
372 | yyCh = getChar(); | 407 | yyCh = getChar(); |
373 | return Tok_RightParen; | 408 | return Tok_RightParen; |
374 | case ',': | 409 | case ',': |
375 | yyCh = getChar(); | 410 | yyCh = getChar(); |
376 | return Tok_Comma; | 411 | return Tok_Comma; |
377 | case ';': | 412 | case ';': |
378 | yyCh = getChar(); | 413 | yyCh = getChar(); |
379 | return Tok_Semicolon; | 414 | return Tok_Semicolon; |
380 | default: | 415 | default: |
381 | yyCh = getChar(); | 416 | yyCh = getChar(); |
382 | } | 417 | } |
383 | } | 418 | } |
384 | } | 419 | } |
385 | return Tok_Eof; | 420 | return Tok_Eof; |
386 | } | 421 | } |
387 | 422 | ||
388 | /* | 423 | /* |
389 | The second part of this source file is the parser. It accomplishes | 424 | The second part of this source file is the parser. It accomplishes |
390 | a very easy task: It finds all strings inside a tr() or translate() | 425 | a very easy task: It finds all strings inside a tr() or translate() |
391 | call, and possibly finds out the context of the call. It supports | 426 | call, and possibly finds out the context of the call. It supports |
392 | three cases: (1) the context is specified, as in | 427 | three cases: (1) the context is specified, as in |
393 | FunnyDialog::tr("Hello") or translate("FunnyDialog", "Hello"); | 428 | FunnyDialog::tr("Hello") or translate("FunnyDialog", "Hello"); |
394 | (2) the call appears within an inlined function; (3) the call | 429 | (2) the call appears within an inlined function; (3) the call |
395 | appears within a function defined outside the class definition. | 430 | appears within a function defined outside the class definition. |
396 | */ | 431 | */ |
397 | 432 | ||
398 | static int yyTok; | 433 | static int yyTok; |
399 | 434 | ||
400 | static bool match( int t ) | 435 | static bool match( int t ) |
401 | { | 436 | { |
402 | bool matches = ( yyTok == t ); | 437 | bool matches = ( yyTok == t ); |
403 | if ( matches ) | 438 | if ( matches ) |
404 | yyTok = getToken(); | 439 | yyTok = getToken(); |
405 | return matches; | 440 | return matches; |
406 | } | 441 | } |
407 | 442 | ||
408 | static bool matchString( QCString *s ) | 443 | static bool matchString( QCString *s ) |
409 | { | 444 | { |
410 | bool matches = ( yyTok == Tok_String ); | 445 | bool matches = ( yyTok == Tok_String ); |
411 | *s = ""; | 446 | *s = ""; |
412 | while ( yyTok == Tok_String ) { | 447 | while ( yyTok == Tok_String ) { |
413 | *s += yyString; | 448 | *s += yyString; |
414 | yyTok = getToken(); | 449 | yyTok = getToken(); |
415 | } | 450 | } |
416 | return matches; | 451 | return matches; |
417 | } | 452 | } |
418 | 453 | ||
419 | static bool matchEncoding( bool *utf8 ) | 454 | static bool matchEncoding( bool *utf8 ) |
420 | { | 455 | { |
421 | if ( yyTok == Tok_Ident ) { | 456 | if ( yyTok == Tok_Ident ) { |
422 | if ( strcmp(yyIdent, "QApplication") == 0 ) { | 457 | if ( strcmp(yyIdent, "QApplication") == 0 ) { |
423 | yyTok = getToken(); | 458 | yyTok = getToken(); |
424 | if ( yyTok == Tok_Gulbrandsen ) | 459 | if ( yyTok == Tok_Gulbrandsen ) |
425 | yyTok = getToken(); | 460 | yyTok = getToken(); |
426 | } | 461 | } |
427 | *utf8 = QString( yyIdent ).endsWith( QString("UTF8") ); | 462 | *utf8 = QString( yyIdent ).endsWith( QString("UTF8") ); |
428 | yyTok = getToken(); | 463 | yyTok = getToken(); |
429 | return TRUE; | 464 | return TRUE; |
430 | } else { | 465 | } else { |
431 | return FALSE; | 466 | return FALSE; |
432 | } | 467 | } |
433 | } | 468 | } |
434 | 469 | ||
435 | static void parse( MetaTranslator *tor, const char *initialContext, | 470 | static void parse( MetaTranslator *tor, const char *initialContext, |
436 | const char *defaultContext ) | 471 | const char *defaultContext ) |
437 | { | 472 | { |
438 | QMap<QCString, QCString> qualifiedContexts; | 473 | QMap<QCString, QCString> qualifiedContexts; |
439 | QStringList namespaces; | 474 | QStringList namespaces; |
440 | QCString context; | 475 | QCString context; |
441 | QCString text; | 476 | QCString text; |
442 | QCString com; | 477 | QCString com; |
443 | QCString functionContext = initialContext; | 478 | QCString functionContext = initialContext; |
444 | QCString prefix; | 479 | QCString prefix; |
445 | bool utf8 = FALSE; | 480 | bool utf8 = FALSE; |
446 | bool missing_Q_OBJECT = FALSE; | 481 | bool missing_Q_OBJECT = FALSE; |
447 | 482 | ||
448 | yyTok = getToken(); | 483 | yyTok = getToken(); |
449 | while ( yyTok != Tok_Eof ) { | 484 | while ( yyTok != Tok_Eof ) { |
450 | switch ( yyTok ) { | 485 | switch ( yyTok ) { |
451 | case Tok_class: | 486 | case Tok_class: |
452 | /* | 487 | /* |
453 | Partial support for inlined functions. | 488 | Partial support for inlined functions. |
454 | */ | 489 | */ |
455 | yyTok = getToken(); | 490 | yyTok = getToken(); |
456 | if ( yyBraceDepth == (int) namespaces.count() && | 491 | if ( yyBraceDepth == (int) namespaces.count() && |
457 | yyParenDepth == 0 ) { | 492 | yyParenDepth == 0 ) { |
458 | do { | 493 | do { |
459 | /* | 494 | /* |
460 | This code should execute only once, but we play | 495 | This code should execute only once, but we play |
461 | safe with impure definitions such as | 496 | safe with impure definitions such as |
462 | 'class Q_EXPORT QMessageBox', in which case | 497 | 'class Q_EXPORT QMessageBox', in which case |
463 | 'QMessageBox' is the class name, not 'Q_EXPORT'. | 498 | 'QMessageBox' is the class name, not 'Q_EXPORT'. |
464 | */ | 499 | */ |
465 | functionContext = yyIdent; | 500 | functionContext = yyIdent; |
466 | yyTok = getToken(); | 501 | yyTok = getToken(); |
@@ -528,200 +563,200 @@ static void parse( MetaTranslator *tor, const char *initialContext, | |||
528 | utf8 = FALSE; | 563 | utf8 = FALSE; |
529 | yyTok = getToken(); | 564 | yyTok = getToken(); |
530 | if ( match(Tok_LeftParen) && | 565 | if ( match(Tok_LeftParen) && |
531 | matchString(&context) && | 566 | matchString(&context) && |
532 | match(Tok_Comma) && | 567 | match(Tok_Comma) && |
533 | matchString(&text) ) { | 568 | matchString(&text) ) { |
534 | com = ""; | 569 | com = ""; |
535 | if ( match(Tok_RightParen) || | 570 | if ( match(Tok_RightParen) || |
536 | (match(Tok_Comma) && | 571 | (match(Tok_Comma) && |
537 | matchString(&com) && | 572 | matchString(&com) && |
538 | (match(Tok_RightParen) || | 573 | (match(Tok_RightParen) || |
539 | match(Tok_Comma) && | 574 | match(Tok_Comma) && |
540 | matchEncoding(&utf8) && | 575 | matchEncoding(&utf8) && |
541 | match(Tok_RightParen))) ) | 576 | match(Tok_RightParen))) ) |
542 | tor->insert( MetaTranslatorMessage(context, text, com, | 577 | tor->insert( MetaTranslatorMessage(context, text, com, |
543 | QString::null, utf8) ); | 578 | QString::null, utf8) ); |
544 | } | 579 | } |
545 | break; | 580 | break; |
546 | case Tok_Q_OBJECT: | 581 | case Tok_Q_OBJECT: |
547 | missing_Q_OBJECT = FALSE; | 582 | missing_Q_OBJECT = FALSE; |
548 | yyTok = getToken(); | 583 | yyTok = getToken(); |
549 | break; | 584 | break; |
550 | case Tok_Ident: | 585 | case Tok_Ident: |
551 | if ( !prefix.isNull() ) | 586 | if ( !prefix.isNull() ) |
552 | prefix += "::"; | 587 | prefix += "::"; |
553 | prefix += yyIdent; | 588 | prefix += yyIdent; |
554 | yyTok = getToken(); | 589 | yyTok = getToken(); |
555 | if ( yyTok != Tok_Gulbrandsen ) | 590 | if ( yyTok != Tok_Gulbrandsen ) |
556 | prefix = (const char *) 0; | 591 | prefix = (const char *) 0; |
557 | break; | 592 | break; |
558 | case Tok_Comment: | 593 | case Tok_Comment: |
559 | com = yyComment; | 594 | com = yyComment; |
560 | com = com.simplifyWhiteSpace(); | 595 | com = com.simplifyWhiteSpace(); |
561 | if ( com.left(sizeof(MagicComment) - 1) == MagicComment ) { | 596 | if ( com.left(sizeof(MagicComment) - 1) == MagicComment ) { |
562 | com.remove( 0, sizeof(MagicComment) - 1 ); | 597 | com.remove( 0, sizeof(MagicComment) - 1 ); |
563 | int k = com.find( ' ' ); | 598 | int k = com.find( ' ' ); |
564 | if ( k == -1 ) { | 599 | if ( k == -1 ) { |
565 | context = com; | 600 | context = com; |
566 | } else { | 601 | } else { |
567 | context = com.left( k ); | 602 | context = com.left( k ); |
568 | com.remove( 0, k + 1 ); | 603 | com.remove( 0, k + 1 ); |
569 | tor->insert( MetaTranslatorMessage(context, "", com, | 604 | tor->insert( MetaTranslatorMessage(context, "", com, |
570 | QString::null, FALSE) ); | 605 | QString::null, FALSE) ); |
571 | } | 606 | } |
572 | 607 | ||
573 | /* | 608 | /* |
574 | Provide a backdoor for people using "using | 609 | Provide a backdoor for people using "using |
575 | namespace". See the manual for details. | 610 | namespace". See the manual for details. |
576 | */ | 611 | */ |
577 | k = 0; | 612 | k = 0; |
578 | while ( (k = context.find("::", k)) != -1 ) { | 613 | while ( (k = context.find("::", k)) != -1 ) { |
579 | qualifiedContexts.insert( context.mid(k + 2), context ); | 614 | qualifiedContexts.insert( context.mid(k + 2), context ); |
580 | k++; | 615 | k++; |
581 | } | 616 | } |
582 | } | 617 | } |
583 | yyTok = getToken(); | 618 | yyTok = getToken(); |
584 | break; | 619 | break; |
585 | case Tok_Arrow: | 620 | case Tok_Arrow: |
586 | yyTok = getToken(); | 621 | yyTok = getToken(); |
587 | if ( yyTok == Tok_tr || yyTok == Tok_trUtf8 ) | 622 | if ( yyTok == Tok_tr || yyTok == Tok_trUtf8 ) |
588 | qWarning( "%s:%d: Cannot invoke tr() like this", | 623 | qWarning( "%s:%d: Cannot invoke tr() like this", |
589 | (const char *) yyFileName, yyLineNo ); | 624 | (const char *) yyFileName, yyLineNo ); |
590 | break; | 625 | break; |
591 | case Tok_Gulbrandsen: | 626 | case Tok_Gulbrandsen: |
592 | // at top level? | 627 | // at top level? |
593 | if ( yyBraceDepth == (int) namespaces.count() && yyParenDepth == 0 ) | 628 | if ( yyBraceDepth == (int) namespaces.count() && yyParenDepth == 0 ) |
594 | functionContext = prefix; | 629 | functionContext = prefix; |
595 | yyTok = getToken(); | 630 | yyTok = getToken(); |
596 | break; | 631 | break; |
597 | case Tok_RightBrace: | 632 | case Tok_RightBrace: |
598 | case Tok_Semicolon: | 633 | case Tok_Semicolon: |
599 | if ( yyBraceDepth >= 0 && | 634 | if ( yyBraceDepth >= 0 && |
600 | yyBraceDepth + 1 == (int) namespaces.count() ) | 635 | yyBraceDepth + 1 == (int) namespaces.count() ) |
601 | namespaces.remove( namespaces.fromLast() ); | 636 | namespaces.remove( namespaces.fromLast() ); |
602 | if ( yyBraceDepth == (int) namespaces.count() ) { | 637 | if ( yyBraceDepth == (int) namespaces.count() ) { |
603 | if ( missing_Q_OBJECT ) { | 638 | if ( missing_Q_OBJECT ) { |
604 | if ( needs_Q_OBJECT.contains(functionContext) ) { | 639 | if ( needs_Q_OBJECT.contains(functionContext) ) { |
605 | qWarning( "%s:%d: Class '%s' lacks Q_OBJECT macro", | 640 | qWarning( "%s:%d: Class '%s' lacks Q_OBJECT macro", |
606 | (const char *) yyFileName, yyLineNo, | 641 | (const char *) yyFileName, yyLineNo, |
607 | (const char *) functionContext ); | 642 | (const char *) functionContext ); |
608 | } else { | 643 | } else { |
609 | lacks_Q_OBJECT.insert( functionContext, 0 ); | 644 | lacks_Q_OBJECT.insert( functionContext, 0 ); |
610 | } | 645 | } |
611 | } | 646 | } |
612 | functionContext = defaultContext; | 647 | functionContext = defaultContext; |
613 | missing_Q_OBJECT = FALSE; | 648 | missing_Q_OBJECT = FALSE; |
614 | } | 649 | } |
615 | yyTok = getToken(); | 650 | yyTok = getToken(); |
616 | break; | 651 | break; |
617 | default: | 652 | default: |
618 | yyTok = getToken(); | 653 | yyTok = getToken(); |
619 | } | 654 | } |
620 | } | 655 | } |
621 | 656 | ||
622 | if ( yyBraceDepth != 0 ) | 657 | if ( yyBraceDepth != 0 ) |
623 | fprintf( stderr, | 658 | fprintf( stderr, |
624 | "%s: Unbalanced braces in C++ code (or abuse of the C++" | 659 | "%s:%d: Unbalanced braces in C++ code (or abuse of the C++" |
625 | " preprocessor)\n", | 660 | " preprocessor)\n", |
626 | (const char *) yyFileName ); | 661 | (const char *)yyFileName, yyBraceLineNo ); |
627 | if ( yyParenDepth != 0 ) | 662 | else if ( yyParenDepth != 0 ) |
628 | fprintf( stderr, | 663 | fprintf( stderr, |
629 | "%s: Unbalanced parentheses in C++ code (or abuse of the C++" | 664 | "%s:%d: Unbalanced parentheses in C++ code (or abuse of the C++" |
630 | " preprocessor)\n", | 665 | " preprocessor)\n", |
631 | (const char *) yyFileName ); | 666 | (const char *)yyFileName, yyParenLineNo ); |
632 | } | 667 | } |
633 | 668 | ||
634 | void fetchtr_cpp( const char *fileName, MetaTranslator *tor, | 669 | void fetchtr_cpp( const char *fileName, MetaTranslator *tor, |
635 | const char *defaultContext, bool mustExist ) | 670 | const char *defaultContext, bool mustExist ) |
636 | { | 671 | { |
637 | yyInFile = fopen( fileName, "r" ); | 672 | yyInFile = fopen( fileName, "r" ); |
638 | if ( yyInFile == 0 ) { | 673 | if ( yyInFile == 0 ) { |
639 | if ( mustExist ) | 674 | if ( mustExist ) |
640 | fprintf( stderr, | 675 | fprintf( stderr, |
641 | "lupdate error: Cannot open C++ source file '%s': %s\n", | 676 | "lupdate error: Cannot open C++ source file '%s': %s\n", |
642 | fileName, strerror(errno) ); | 677 | fileName, strerror(errno) ); |
643 | return; | 678 | return; |
644 | } | 679 | } |
645 | 680 | ||
646 | startTokenizer( fileName, getCharFromFile ); | 681 | startTokenizer( fileName, getCharFromFile ); |
647 | parse( tor, 0, defaultContext ); | 682 | parse( tor, 0, defaultContext ); |
648 | fclose( yyInFile ); | 683 | fclose( yyInFile ); |
649 | } | 684 | } |
650 | 685 | ||
651 | /* | 686 | /* |
652 | In addition to C++, we support Qt Designer UI files. | 687 | In addition to C++, we support Qt Designer UI files. |
653 | */ | 688 | */ |
654 | 689 | ||
655 | /* | 690 | /* |
656 | Fetches tr() calls in C++ code in UI files (inside "<function>" | 691 | Fetches tr() calls in C++ code in UI files (inside "<function>" |
657 | tag). This mechanism is obsolete. | 692 | tag). This mechanism is obsolete. |
658 | */ | 693 | */ |
659 | void fetchtr_inlined_cpp( const char *fileName, const QString& in, | 694 | void fetchtr_inlined_cpp( const char *fileName, const QString& in, |
660 | MetaTranslator *tor, const char *context ) | 695 | MetaTranslator *tor, const char *context ) |
661 | { | 696 | { |
662 | yyInStr = in; | 697 | yyInStr = in; |
663 | startTokenizer( fileName, getCharFromString ); | 698 | startTokenizer( fileName, getCharFromString ); |
664 | parse( tor, context, 0 ); | 699 | parse( tor, context, 0 ); |
665 | yyInStr = QString::null; | 700 | yyInStr = QString::null; |
666 | } | 701 | } |
667 | 702 | ||
668 | class UiHandler : public QXmlDefaultHandler | 703 | class UiHandler : public QXmlDefaultHandler |
669 | { | 704 | { |
670 | public: | 705 | public: |
671 | UiHandler( MetaTranslator *translator, const char *fileName ) | 706 | UiHandler( MetaTranslator *translator, const char *fileName ) |
672 | : tor( translator ), fname( fileName ), comment( "" ) { } | 707 | : tor( translator ), fname( fileName ), comment( "" ) { } |
673 | 708 | ||
674 | virtual bool startElement( const QString& namespaceURI, | 709 | virtual bool startElement( const QString& namespaceURI, |
675 | const QString& localName, const QString& qName, | 710 | const QString& localName, const QString& qName, |
676 | const QXmlAttributes& atts ); | 711 | const QXmlAttributes& atts ); |
677 | virtual bool endElement( const QString& namespaceURI, | 712 | virtual bool endElement( const QString& namespaceURI, |
678 | const QString& localName, const QString& qName ); | 713 | const QString& localName, const QString& qName ); |
679 | virtual bool characters( const QString& ch ); | 714 | virtual bool characters( const QString& ch ); |
680 | virtual bool fatalError( const QXmlParseException& exception ); | 715 | virtual bool fatalError( const QXmlParseException& exception ); |
681 | 716 | ||
682 | private: | 717 | private: |
683 | void flush(); | 718 | void flush(); |
684 | 719 | ||
685 | MetaTranslator *tor; | 720 | MetaTranslator *tor; |
686 | QCString fname; | 721 | QCString fname; |
687 | QString context; | 722 | QString context; |
688 | QString source; | 723 | QString source; |
689 | QString comment; | 724 | QString comment; |
690 | 725 | ||
691 | QString accum; | 726 | QString accum; |
692 | }; | 727 | }; |
693 | 728 | ||
694 | bool UiHandler::startElement( const QString& /* namespaceURI */, | 729 | bool UiHandler::startElement( const QString& /* namespaceURI */, |
695 | const QString& /* localName */, | 730 | const QString& /* localName */, |
696 | const QString& qName, | 731 | const QString& qName, |
697 | const QXmlAttributes& atts ) | 732 | const QXmlAttributes& atts ) |
698 | { | 733 | { |
699 | if ( qName == QString("item") ) { | 734 | if ( qName == QString("item") ) { |
700 | flush(); | 735 | flush(); |
701 | if ( !atts.value(QString("text")).isEmpty() ) | 736 | if ( !atts.value(QString("text")).isEmpty() ) |
702 | source = atts.value( QString("text") ); | 737 | source = atts.value( QString("text") ); |
703 | } else if ( qName == QString("string") ) { | 738 | } else if ( qName == QString("string") ) { |
704 | flush(); | 739 | flush(); |
705 | } | 740 | } |
706 | accum.truncate( 0 ); | 741 | accum.truncate( 0 ); |
707 | return TRUE; | 742 | return TRUE; |
708 | } | 743 | } |
709 | 744 | ||
710 | bool UiHandler::endElement( const QString& /* namespaceURI */, | 745 | bool UiHandler::endElement( const QString& /* namespaceURI */, |
711 | const QString& /* localName */, | 746 | const QString& /* localName */, |
712 | const QString& qName ) | 747 | const QString& qName ) |
713 | { | 748 | { |
714 | accum.replace( QRegExp(QString("\r\n")), "\n" ); | 749 | accum.replace( QRegExp(QString("\r\n")), "\n" ); |
715 | 750 | ||
716 | if ( qName == QString("class") ) { | 751 | if ( qName == QString("class") ) { |
717 | if ( context.isEmpty() ) | 752 | if ( context.isEmpty() ) |
718 | context = accum; | 753 | context = accum; |
719 | } else if ( qName == QString("string") ) { | 754 | } else if ( qName == QString("string") ) { |
720 | source = accum; | 755 | source = accum; |
721 | } else if ( qName == QString("comment") ) { | 756 | } else if ( qName == QString("comment") ) { |
722 | comment = accum; | 757 | comment = accum; |
723 | flush(); | 758 | flush(); |
724 | } else if ( qName == QString("function") ) { | 759 | } else if ( qName == QString("function") ) { |
725 | fetchtr_inlined_cpp( (const char *) fname, accum, tor, | 760 | fetchtr_inlined_cpp( (const char *) fname, accum, tor, |
726 | context.latin1() ); | 761 | context.latin1() ); |
727 | } else { | 762 | } else { |
diff --git a/development/translation/opie-lupdate/main.cpp b/development/translation/opie-lupdate/main.cpp index ce65e7a..bf16fd7 100644 --- a/development/translation/opie-lupdate/main.cpp +++ b/development/translation/opie-lupdate/main.cpp | |||
@@ -1,215 +1,224 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** Copyright (C) 2003 zecke | 3 | ** Copyright (C) 2003 zecke |
4 | ** | 4 | ** |
5 | ** This file is part of Qt Linguist. | 5 | ** This file is part of Qt Linguist. |
6 | ** | 6 | ** |
7 | ** This file may be distributed and/or modified under the terms of the | 7 | ** This file may be distributed and/or modified under the terms of the |
8 | ** GNU General Public License version 2 as published by the Free Software | 8 | ** GNU General Public License version 2 as published by the Free Software |
9 | ** Foundation and appearing in the file LICENSE.GPL included in the | 9 | ** Foundation and appearing in the file LICENSE.GPL included in the |
10 | ** packaging of this file. | 10 | ** packaging of this file. |
11 | ** | 11 | ** |
12 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 12 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
13 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 13 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
14 | ** | 14 | ** |
15 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 15 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
16 | ** | 16 | ** |
17 | ** Contact info@trolltech.com if any conditions of this licensing are | 17 | ** Contact info@trolltech.com if any conditions of this licensing are |
18 | ** not clear to you. | 18 | ** not clear to you. |
19 | ** | 19 | ** |
20 | **********************************************************************/ | 20 | **********************************************************************/ |
21 | 21 | ||
22 | #include <metatranslator.h> | 22 | #include <metatranslator.h> |
23 | #include <proparser.h> | 23 | #include <proparser.h> |
24 | #include <opie.h> | 24 | #include <opie.h> |
25 | 25 | ||
26 | #include <qfile.h> | 26 | #include <qfile.h> |
27 | #include <qfileinfo.h> | 27 | #include <qfileinfo.h> |
28 | #include <qstring.h> | 28 | #include <qstring.h> |
29 | #include <qstringlist.h> | 29 | #include <qstringlist.h> |
30 | #include <qtextstream.h> | 30 | #include <qtextstream.h> |
31 | 31 | ||
32 | #include <errno.h> | 32 | #include <errno.h> |
33 | #include <string.h> | 33 | #include <string.h> |
34 | 34 | ||
35 | // defined in fetchtr.cpp | 35 | // defined in fetchtr.cpp |
36 | extern void fetchtr_cpp( const char *fileName, MetaTranslator *tor, | 36 | extern void fetchtr_cpp( const char *fileName, MetaTranslator *tor, |
37 | const char *defaultContext, bool mustExist ); | 37 | const char *defaultContext, bool mustExist ); |
38 | extern void fetchtr_ui( const char *fileName, MetaTranslator *tor, | 38 | extern void fetchtr_ui( const char *fileName, MetaTranslator *tor, |
39 | const char *defaultContext, bool mustExist ); | 39 | const char *defaultContext, bool mustExist ); |
40 | 40 | ||
41 | // defined in merge.cpp | 41 | // defined in merge.cpp |
42 | extern void merge( MetaTranslator *tor, const MetaTranslator *virginTor, | 42 | extern void merge( MetaTranslator *tor, const MetaTranslator *virginTor, |
43 | bool verbose ); | 43 | bool verbose ); |
44 | 44 | ||
45 | typedef QValueList<MetaTranslatorMessage> TML; | 45 | typedef QValueList<MetaTranslatorMessage> TML; |
46 | 46 | ||
47 | static const char* LUPDATE_VERSION = "0.1"; | 47 | static const char* LUPDATE_VERSION = "0.1"; |
48 | 48 | ||
49 | static void printUsage() | 49 | static void printUsage() |
50 | { | 50 | { |
51 | fprintf( stderr, "Usage:\n" | 51 | fprintf( stderr, "Usage:\n" |
52 | " opie-lupdate [options] project-file\n" | 52 | " opie-lupdate [options] project-file\n" |
53 | " opie-lupdate [options] source-files -ts ts-files\n" | 53 | " opie-lupdate [options] source-files -ts ts-files\n" |
54 | "Options:\n" | 54 | "Options:\n" |
55 | " -opie The OPIE base dir if not supplied $OPIEDIR will be taken\n" | 55 | " -opie The OPIE base dir if not supplied $OPIEDIR will be taken\n" |
56 | " -help Display this information and exit\n" | 56 | " -help Display this information and exit\n" |
57 | " -noobsolete\n" | 57 | " -noobsolete\n" |
58 | " Drop all obsolete strings\n" | 58 | " Drop all obsolete strings\n" |
59 | " -verbose\n" | 59 | " -verbose\n" |
60 | " Explain what is being done\n" | 60 | " Explain what is being done\n" |
61 | " -version\n" | 61 | " -version\n" |
62 | " Display the version of lupdate and exit\n" ); | 62 | " Display the version of lupdate and exit\n" ); |
63 | } | 63 | } |
64 | 64 | ||
65 | /*static QString opie_escape( const QString& str ) { | ||
66 | QString ret = str.stripWhiteSpace(); | ||
67 | qWarning(ret); | ||
68 | if ( ret.startsWith("$$(OPIEDIR)") ) | ||
69 | ret = ret.replace("$$(OPIEDIR)", OPIE::self()->opieDir() ); | ||
70 | qWarning(ret); | ||
71 | return ret; | ||
72 | }*/ | ||
73 | |||
65 | static void updateTsFiles( const MetaTranslator& fetchedTor, | 74 | static void updateTsFiles( const MetaTranslator& fetchedTor, |
66 | const QString& opiedir, | 75 | const QString& opiedir, |
67 | const QStringList& languages, | 76 | const QStringList& languages, |
68 | const QString& basename, | 77 | const QString& basename, |
69 | const QString& codec, | 78 | const QString& codec, |
70 | bool noObsolete, bool verbose ) | 79 | bool noObsolete, bool verbose ) |
71 | { | 80 | { |
72 | QStringList::ConstIterator it = languages.begin(); | 81 | QStringList::ConstIterator it = languages.begin(); |
73 | for ( ; it != languages.end(); ++it ) { | 82 | for ( ; it != languages.end(); ++it ) { |
74 | QString fileName = opiedir + "/i18n/" + (*it) + "/" + basename; | 83 | QString fileName = opiedir + "/i18n/" + (*it) + "/" + basename; |
75 | MetaTranslator tor; | 84 | MetaTranslator tor; |
76 | tor.load( fileName ); | 85 | tor.load( fileName ); |
77 | if ( !codec.isEmpty() ) | 86 | if ( !codec.isEmpty() ) |
78 | tor.setCodec( codec ); | 87 | tor.setCodec( codec ); |
79 | if ( verbose ) | 88 | if ( verbose ) |
80 | fprintf( stderr, "Updating '%s'...\n", fileName.latin1() ); | 89 | fprintf( stderr, "Updating '%s'...\n", fileName.latin1() ); |
81 | merge( &tor, &fetchedTor, verbose ); | 90 | merge( &tor, &fetchedTor, verbose ); |
82 | if ( noObsolete ) | 91 | if ( noObsolete ) |
83 | tor.stripObsoleteMessages(); | 92 | tor.stripObsoleteMessages(); |
84 | tor.stripEmptyContexts(); | 93 | tor.stripEmptyContexts(); |
85 | if ( !tor.save(fileName) ) | 94 | if ( !tor.save(fileName) ) |
86 | fprintf( stderr, "lupdate error: Cannot save '%s': %s\n", | 95 | fprintf( stderr, "lupdate error: Cannot save '%s': %s\n", |
87 | fileName.latin1(), strerror(errno) ); | 96 | fileName.latin1(), strerror(errno) ); |
88 | } | 97 | } |
89 | } | 98 | } |
90 | 99 | ||
91 | int main( int argc, char **argv ) | 100 | int main( int argc, char **argv ) |
92 | { | 101 | { |
93 | QString defaultContext = "@default"; | 102 | QString defaultContext = "@default"; |
94 | MetaTranslator fetchedTor; | 103 | MetaTranslator fetchedTor; |
95 | QCString codec; | 104 | QCString codec; |
96 | QStringList tsFileNames; | 105 | QStringList tsFileNames; |
97 | QString opiedir; | 106 | QString opiedir; |
98 | QString translationBase; | 107 | QString translationBase; |
99 | QString target; | 108 | QString target; |
100 | 109 | ||
101 | bool verbose = FALSE; | 110 | bool verbose = FALSE; |
102 | bool noObsolete = FALSE; | 111 | bool noObsolete = FALSE; |
103 | bool metSomething = FALSE; | 112 | bool metSomething = FALSE; |
104 | bool isLib = FALSE; | 113 | bool isLib = FALSE; |
105 | int numFiles = 0; | 114 | int numFiles = 0; |
106 | 115 | ||
107 | int i; | 116 | int i; |
108 | 117 | ||
109 | QStringList languageList = OPIE::self()->languageList(opiedir); | 118 | QStringList languageList = OPIE::self()->languageList(opiedir); |
110 | 119 | ||
111 | for ( i = 1; i < argc; i++ ) { | 120 | for ( i = 1; i < argc; i++ ) { |
112 | if ( qstrcmp(argv[i], "-help") == 0 ) { | 121 | if ( qstrcmp(argv[i], "-help") == 0 ) { |
113 | printUsage(); | 122 | printUsage(); |
114 | return 0; | 123 | return 0; |
115 | } else if ( qstrcmp(argv[i], "-noobsolete") == 0 ) { | 124 | } else if ( qstrcmp(argv[i], "-noobsolete") == 0 ) { |
116 | noObsolete = TRUE; | 125 | noObsolete = TRUE; |
117 | continue; | 126 | continue; |
118 | } else if ( qstrcmp(argv[i], "-verbose") == 0 ) { | 127 | } else if ( qstrcmp(argv[i], "-verbose") == 0 ) { |
119 | verbose = TRUE; | 128 | verbose = TRUE; |
120 | continue; | 129 | continue; |
121 | } else if ( qstrcmp(argv[i], "-version") == 0 ) { | 130 | } else if ( qstrcmp(argv[i], "-version") == 0 ) { |
122 | fprintf( stderr, "lupdate version %s\n", LUPDATE_VERSION ); | 131 | fprintf( stderr, "lupdate version %s\n", LUPDATE_VERSION ); |
123 | return 0; | 132 | return 0; |
124 | } else if ( qstrcmp(argv[i], "-opie") == 0 ) { | 133 | } else if ( qstrcmp(argv[i], "-opie") == 0 ) { |
125 | if( i+1 < argc ) { | 134 | if( i+1 < argc ) { |
126 | opiedir = argv[i+1]; | 135 | opiedir = argv[i+1]; |
127 | languageList = OPIE::self()->languageList(opiedir); | 136 | languageList = OPIE::self()->languageList(opiedir); |
128 | } | 137 | } |
129 | i++; // UGLY but we want to skip the next argument | 138 | i++; // UGLY but we want to skip the next argument |
130 | continue; | 139 | continue; |
131 | } | 140 | } |
132 | 141 | ||
133 | numFiles++; | 142 | numFiles++; |
134 | 143 | ||
135 | QString fullText; | 144 | QString fullText; |
136 | 145 | ||
137 | QFile f( argv[i] ); | 146 | QFile f( argv[i] ); |
138 | if ( !f.open(IO_ReadOnly) ) { | 147 | if ( !f.open(IO_ReadOnly) ) { |
139 | fprintf( stderr, "lupdate error: Cannot open file '%s': %s\n", | 148 | fprintf( stderr, "lupdate error: Cannot open file '%s': %s\n", |
140 | argv[i], strerror(errno) ); | 149 | argv[i], strerror(errno) ); |
141 | return 1; | 150 | return 1; |
142 | } | 151 | } |
143 | 152 | ||
144 | QTextStream t( &f ); | 153 | QTextStream t( &f ); |
145 | fullText = t.read(); | 154 | fullText = t.read(); |
146 | f.close(); | 155 | f.close(); |
147 | 156 | ||
148 | fetchedTor = MetaTranslator(); | 157 | fetchedTor = MetaTranslator(); |
149 | codec.truncate( 0 ); | 158 | codec.truncate( 0 ); |
150 | tsFileNames.clear(); | 159 | tsFileNames.clear(); |
151 | isLib = FALSE; | 160 | isLib = FALSE; |
152 | 161 | ||
153 | QMap<QString, QString> tagMap = proFileTagMap( fullText ); | 162 | QMap<QString, QString> tagMap = proFileTagMap( fullText, OPIE::self()->opieDir() ); |
154 | QMap<QString, QString>::Iterator it; | 163 | QMap<QString, QString>::Iterator it; |
155 | 164 | ||
156 | for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { | 165 | for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { |
157 | QStringList toks = QStringList::split( ' ', it.data() ); | 166 | QStringList toks = QStringList::split( ' ', it.data() ); |
158 | QStringList::Iterator t; | 167 | QStringList::Iterator t; |
159 | 168 | ||
160 | for ( t = toks.begin(); t != toks.end(); ++t ) { | 169 | for ( t = toks.begin(); t != toks.end(); ++t ) { |
161 | if ( it.key() == "HEADERS" || it.key() == "SOURCES" ) { | 170 | if ( it.key() == "HEADERS" || it.key() == "SOURCES" ) { |
162 | fetchtr_cpp( *t, &fetchedTor, defaultContext, TRUE ); | 171 | fetchtr_cpp( *t, &fetchedTor, defaultContext, TRUE ); |
163 | metSomething = TRUE; | 172 | metSomething = TRUE; |
164 | } else if ( it.key() == "INTERFACES" || | 173 | } else if ( it.key() == "INTERFACES" || |
165 | it.key() == "FORMS" ) { | 174 | it.key() == "FORMS" ) { |
166 | fetchtr_ui( *t, &fetchedTor, defaultContext, TRUE ); | 175 | fetchtr_ui( *t, &fetchedTor, defaultContext, TRUE ); |
167 | fetchtr_cpp( *t + ".h", &fetchedTor, defaultContext, | 176 | fetchtr_cpp( *t + ".h", &fetchedTor, defaultContext, |
168 | FALSE ); | 177 | FALSE ); |
169 | metSomething = TRUE; | 178 | metSomething = TRUE; |
170 | } else if ( it.key() == "TRANSLATIONS" ) { | 179 | } else if ( it.key() == "TRANSLATIONS" ) { |
171 | // we do not care for that attribute anymore | 180 | // we do not care for that attribute anymore |
172 | //tsFileNames.append( *t ); | 181 | //tsFileNames.append( *t ); |
173 | metSomething = TRUE; | 182 | metSomething = TRUE; |
174 | } else if ( it.key() == "CODEC" ) { | 183 | } else if ( it.key() == "CODEC" ) { |
175 | codec = (*t).latin1(); | 184 | codec = (*t).latin1(); |
176 | } else if ( it.key() == "TARGET" ) { | 185 | } else if ( it.key() == "TARGET" ) { |
177 | target = *t; | 186 | target = *t; |
178 | metSomething = TRUE; | 187 | metSomething = TRUE; |
179 | } else if ( it.key() == "TEMPLATE" ) { | 188 | } else if ( it.key() == "TEMPLATE" ) { |
180 | if ( (*t).stripWhiteSpace().lower() == "lib" ) | 189 | if ( (*t).stripWhiteSpace().lower() == "lib" ) |
181 | isLib = true; | 190 | isLib = true; |
182 | } | 191 | } |
183 | } | 192 | } |
184 | } | 193 | } |
185 | /** | 194 | /** |
186 | * We know the $OPIEDIR or have opiedir | 195 | * We know the $OPIEDIR or have opiedir |
187 | * we've a list of languages (de,en,gb,foo,bar) | 196 | * we've a list of languages (de,en,gb,foo,bar) |
188 | * we've got the TARGET and we no it's the lib | 197 | * we've got the TARGET and we no it's the lib |
189 | * so let's do that | 198 | * so let's do that |
190 | * $OPIEDIR/language[i]/ifLibAppendLib$TARGET.ts | 199 | * $OPIEDIR/language[i]/ifLibAppendLib$TARGET.ts |
191 | */ | 200 | */ |
192 | qWarning("TARGET %s IsLib:%d", target.latin1(), isLib ); | 201 | qWarning("TARGET %s IsLib:%d", target.latin1(), isLib ); |
193 | qWarning("LANGS %s", languageList.join(";").latin1() ); | 202 | qWarning("LANGS %s", languageList.join(";").latin1() ); |
194 | qWarning("OPIEDIR %s", OPIE::self()->opieDir(opiedir).latin1() ); | 203 | qWarning("OPIEDIR %s", OPIE::self()->opieDir(opiedir).latin1() ); |
195 | if (isLib ) | 204 | if (isLib ) |
196 | target.prepend("lib"); | 205 | target.prepend("lib"); |
197 | target += ".ts"; | 206 | target += ".ts"; |
198 | updateTsFiles( fetchedTor, OPIE::self()->opieDir(opiedir), | 207 | updateTsFiles( fetchedTor, OPIE::self()->opieDir(opiedir), |
199 | languageList, target, codec, noObsolete, verbose ); | 208 | languageList, target, codec, noObsolete, verbose ); |
200 | 209 | ||
201 | if ( !metSomething ) { | 210 | if ( !metSomething ) { |
202 | fprintf( stderr, | 211 | fprintf( stderr, |
203 | "lupdate warning: File '%s' does not look like a" | 212 | "lupdate warning: File '%s' does not look like a" |
204 | " project file\n", | 213 | " project file\n", |
205 | argv[i] ); | 214 | argv[i] ); |
206 | } | 215 | } |
207 | 216 | ||
208 | } | 217 | } |
209 | 218 | ||
210 | if ( numFiles == 0 ) { | 219 | if ( numFiles == 0 ) { |
211 | printUsage(); | 220 | printUsage(); |
212 | return 1; | 221 | return 1; |
213 | } | 222 | } |
214 | return 0; | 223 | return 0; |
215 | } | 224 | } |
diff --git a/development/translation/opie-lupdate/merge.cpp b/development/translation/opie-lupdate/merge.cpp index a96104e..3001d4b 100644 --- a/development/translation/opie-lupdate/merge.cpp +++ b/development/translation/opie-lupdate/merge.cpp | |||
@@ -1,110 +1,116 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #include <metatranslator.h> | 27 | #include <metatranslator.h> |
22 | 28 | ||
23 | // defined in numberh.cpp | 29 | // defined in numberh.cpp |
24 | extern void applyNumberHeuristic( MetaTranslator *tor, bool verbose ); | 30 | extern void applyNumberHeuristic( MetaTranslator *tor, bool verbose ); |
25 | // defined in sametexth.cpp | 31 | // defined in sametexth.cpp |
26 | extern void applySameTextHeuristic( MetaTranslator *tor, bool verbose ); | 32 | extern void applySameTextHeuristic( MetaTranslator *tor, bool verbose ); |
27 | 33 | ||
28 | typedef QValueList<MetaTranslatorMessage> TML; | 34 | typedef QValueList<MetaTranslatorMessage> TML; |
29 | 35 | ||
30 | /* | 36 | /* |
31 | Merges two MetaTranslator objects into the first one. The first one | 37 | Merges two MetaTranslator objects into the first one. The first one |
32 | is a set of source texts and translations for a previous version of | 38 | is a set of source texts and translations for a previous version of |
33 | the internationalized program; the second one is a set of fresh | 39 | the internationalized program; the second one is a set of fresh |
34 | source texts newly extracted from the source code, without any | 40 | source texts newly extracted from the source code, without any |
35 | translation yet. | 41 | translation yet. |
36 | */ | 42 | */ |
37 | 43 | ||
38 | void merge( MetaTranslator *tor, const MetaTranslator *virginTor, bool verbose ) | 44 | void merge( MetaTranslator *tor, const MetaTranslator *virginTor, bool verbose ) |
39 | { | 45 | { |
40 | int known = 0; | 46 | int known = 0; |
41 | int neww = 0; | 47 | int neww = 0; |
42 | int obsoleted = 0; | 48 | int obsoleted = 0; |
43 | TML all = tor->messages(); | 49 | TML all = tor->messages(); |
44 | TML::Iterator it; | 50 | TML::Iterator it; |
45 | 51 | ||
46 | /* | 52 | /* |
47 | The types of all the messages from the vernacular translator | 53 | The types of all the messages from the vernacular translator |
48 | are updated according to the virgin translator. | 54 | are updated according to the virgin translator. |
49 | */ | 55 | */ |
50 | for ( it = all.begin(); it != all.end(); ++it ) { | 56 | for ( it = all.begin(); it != all.end(); ++it ) { |
51 | MetaTranslatorMessage::Type newType; | 57 | MetaTranslatorMessage::Type newType; |
52 | MetaTranslatorMessage m = *it; | 58 | MetaTranslatorMessage m = *it; |
53 | 59 | ||
54 | // skip context comment | 60 | // skip context comment |
55 | if ( !QCString((*it).sourceText()).isEmpty() ) { | 61 | if ( !QCString((*it).sourceText()).isEmpty() ) { |
56 | if ( !virginTor->contains((*it).context(), (*it).sourceText(), | 62 | if ( !virginTor->contains((*it).context(), (*it).sourceText(), |
57 | (*it).comment()) ) { | 63 | (*it).comment()) ) { |
58 | newType = MetaTranslatorMessage::Obsolete; | 64 | newType = MetaTranslatorMessage::Obsolete; |
59 | if ( m.type() != MetaTranslatorMessage::Obsolete ) | 65 | if ( m.type() != MetaTranslatorMessage::Obsolete ) |
60 | obsoleted++; | 66 | obsoleted++; |
61 | } else { | 67 | } else { |
62 | switch ( m.type() ) { | 68 | switch ( m.type() ) { |
63 | case MetaTranslatorMessage::Finished: | 69 | case MetaTranslatorMessage::Finished: |
64 | newType = MetaTranslatorMessage::Finished; | 70 | newType = MetaTranslatorMessage::Finished; |
65 | known++; | 71 | known++; |
66 | break; | 72 | break; |
67 | case MetaTranslatorMessage::Unfinished: | 73 | case MetaTranslatorMessage::Unfinished: |
68 | newType = MetaTranslatorMessage::Unfinished; | 74 | newType = MetaTranslatorMessage::Unfinished; |
69 | known++; | 75 | known++; |
70 | break; | 76 | break; |
71 | case MetaTranslatorMessage::Obsolete: | 77 | case MetaTranslatorMessage::Obsolete: |
72 | newType = MetaTranslatorMessage::Unfinished; | 78 | newType = MetaTranslatorMessage::Unfinished; |
73 | neww++; | 79 | neww++; |
74 | } | 80 | } |
75 | } | 81 | } |
76 | 82 | ||
77 | if ( newType != m.type() ) { | 83 | if ( newType != m.type() ) { |
78 | m.setType( newType ); | 84 | m.setType( newType ); |
79 | tor->insert( m ); | 85 | tor->insert( m ); |
80 | } | 86 | } |
81 | } | 87 | } |
82 | } | 88 | } |
83 | 89 | ||
84 | /* | 90 | /* |
85 | Messages found only in the virgin translator are added to the | 91 | Messages found only in the virgin translator are added to the |
86 | vernacular translator. Among these are all the context comments. | 92 | vernacular translator. Among these are all the context comments. |
87 | */ | 93 | */ |
88 | all = virginTor->messages(); | 94 | all = virginTor->messages(); |
89 | 95 | ||
90 | for ( it = all.begin(); it != all.end(); ++it ) { | 96 | for ( it = all.begin(); it != all.end(); ++it ) { |
91 | if ( !tor->contains((*it).context(), (*it).sourceText(), | 97 | if ( !tor->contains((*it).context(), (*it).sourceText(), |
92 | (*it).comment()) ) { | 98 | (*it).comment()) ) { |
93 | tor->insert( *it ); | 99 | tor->insert( *it ); |
94 | if ( !QCString((*it).sourceText()).isEmpty() ) | 100 | if ( !QCString((*it).sourceText()).isEmpty() ) |
95 | neww++; | 101 | neww++; |
96 | } | 102 | } |
97 | } | 103 | } |
98 | 104 | ||
99 | /* | 105 | /* |
100 | The same-text heuristic handles cases where a message has an | 106 | The same-text heuristic handles cases where a message has an |
101 | obsolete counterpart with a different context or comment. | 107 | obsolete counterpart with a different context or comment. |
102 | */ | 108 | */ |
103 | applySameTextHeuristic( tor, verbose ); | 109 | applySameTextHeuristic( tor, verbose ); |
104 | 110 | ||
105 | /* | 111 | /* |
106 | The number heuristic handles cases where a message has an | 112 | The number heuristic handles cases where a message has an |
107 | obsolete counterpart with mostly numbers differing in the | 113 | obsolete counterpart with mostly numbers differing in the |
108 | source text. | 114 | source text. |
109 | */ | 115 | */ |
110 | applyNumberHeuristic( tor, verbose ); | 116 | applyNumberHeuristic( tor, verbose ); |
diff --git a/development/translation/opie-lupdate/numberh.cpp b/development/translation/opie-lupdate/numberh.cpp index f7b7bf8..2f12c3d 100644 --- a/development/translation/opie-lupdate/numberh.cpp +++ b/development/translation/opie-lupdate/numberh.cpp | |||
@@ -1,235 +1,241 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #include <metatranslator.h> | 27 | #include <metatranslator.h> |
22 | 28 | ||
23 | #include <qmemarray.h> | 29 | #include <qmemarray.h> |
24 | #include <qcstring.h> | 30 | #include <qcstring.h> |
25 | #include <qmap.h> | 31 | #include <qmap.h> |
26 | #include <qstringlist.h> | 32 | #include <qstringlist.h> |
27 | 33 | ||
28 | #include <ctype.h> | 34 | #include <ctype.h> |
29 | 35 | ||
30 | typedef QMap<QCString, MetaTranslatorMessage> TMM; | 36 | typedef QMap<QCString, MetaTranslatorMessage> TMM; |
31 | typedef QValueList<MetaTranslatorMessage> TML; | 37 | typedef QValueList<MetaTranslatorMessage> TML; |
32 | 38 | ||
33 | static bool isDigitFriendly( int c ) | 39 | static bool isDigitFriendly( int c ) |
34 | { | 40 | { |
35 | return ispunct( c ) || isspace( c ); | 41 | return ispunct((uchar)c) || isspace((uchar)c); |
36 | } | 42 | } |
37 | 43 | ||
38 | static int numberLength( const char *s ) | 44 | static int numberLength( const char *s ) |
39 | { | 45 | { |
40 | int i = 0; | 46 | int i = 0; |
41 | 47 | ||
42 | if ( isdigit(s[0]) ) { | 48 | if ( isdigit((uchar)s[0]) ) { |
43 | do { | 49 | do { |
44 | i++; | 50 | i++; |
45 | } while ( isdigit(s[i]) || | 51 | } while (isdigit((uchar)s[i]) || |
46 | (isDigitFriendly(s[i]) && | 52 | (isDigitFriendly(s[i]) && |
47 | (isdigit(s[i + 1]) || | 53 | (isdigit((uchar)s[i + 1]) || |
48 | (isDigitFriendly(s[i + 1]) && isdigit(s[i + 2])))) ); | 54 | (isDigitFriendly(s[i + 1]) && isdigit((uchar)s[i + 2]))))); |
49 | } | 55 | } |
50 | return i; | 56 | return i; |
51 | } | 57 | } |
52 | 58 | ||
53 | /* | 59 | /* |
54 | Returns a version of 'key' where all numbers have been replaced by zeroes. If | 60 | Returns a version of 'key' where all numbers have been replaced by zeroes. If |
55 | there were none, returns "". | 61 | there were none, returns "". |
56 | */ | 62 | */ |
57 | static QCString zeroKey( const char *key ) | 63 | static QCString zeroKey( const char *key ) |
58 | { | 64 | { |
59 | QCString zeroed( strlen(key) + 1 ); | 65 | QCString zeroed( strlen(key) + 1 ); |
60 | char *z = zeroed.data(); | 66 | char *z = zeroed.data(); |
61 | int i = 0, j = 0; | 67 | int i = 0, j = 0; |
62 | int len; | 68 | int len; |
63 | bool metSomething = FALSE; | 69 | bool metSomething = FALSE; |
64 | 70 | ||
65 | while ( key[i] != '\0' ) { | 71 | while ( key[i] != '\0' ) { |
66 | len = numberLength( key + i ); | 72 | len = numberLength( key + i ); |
67 | if ( len > 0 ) { | 73 | if ( len > 0 ) { |
68 | i += len; | 74 | i += len; |
69 | z[j++] = '0'; | 75 | z[j++] = '0'; |
70 | metSomething = TRUE; | 76 | metSomething = TRUE; |
71 | } else { | 77 | } else { |
72 | z[j++] = key[i++]; | 78 | z[j++] = key[i++]; |
73 | } | 79 | } |
74 | } | 80 | } |
75 | z[j] = '\0'; | 81 | z[j] = '\0'; |
76 | 82 | ||
77 | if ( metSomething ) | 83 | if ( metSomething ) |
78 | return zeroed; | 84 | return zeroed; |
79 | else | 85 | else |
80 | return ""; | 86 | return ""; |
81 | } | 87 | } |
82 | 88 | ||
83 | static QString translationAttempt( const QString& oldTranslation, | 89 | static QString translationAttempt( const QString& oldTranslation, |
84 | const char *oldSource, | 90 | const char *oldSource, |
85 | const char *newSource ) | 91 | const char *newSource ) |
86 | { | 92 | { |
87 | int p = zeroKey( oldSource ).contains( '0' ); | 93 | int p = zeroKey( oldSource ).contains( '0' ); |
88 | int oldSourceLen = qstrlen( oldSource ); | 94 | int oldSourceLen = qstrlen( oldSource ); |
89 | QString attempt; | 95 | QString attempt; |
90 | QStringList oldNumbers; | 96 | QStringList oldNumbers; |
91 | QStringList newNumbers; | 97 | QStringList newNumbers; |
92 | QMemArray<bool> met( p ); | 98 | QMemArray<bool> met( p ); |
93 | QMemArray<int> matchedYet( p ); | 99 | QMemArray<int> matchedYet( p ); |
94 | int i, j; | 100 | int i, j; |
95 | int k = 0, ell, best; | 101 | int k = 0, ell, best; |
96 | int m, n; | 102 | int m, n; |
97 | int pass; | 103 | int pass; |
98 | 104 | ||
99 | /* | 105 | /* |
100 | This algorithm is hard to follow, so we'll consider an example | 106 | This algorithm is hard to follow, so we'll consider an example |
101 | all along: oldTranslation is "XeT 3.0", oldSource is "TeX 3.0" | 107 | all along: oldTranslation is "XeT 3.0", oldSource is "TeX 3.0" |
102 | and newSource is "XeT 3.1". | 108 | and newSource is "XeT 3.1". |
103 | 109 | ||
104 | First, we set up two tables: oldNumbers and newNumbers. In our | 110 | First, we set up two tables: oldNumbers and newNumbers. In our |
105 | example, oldNumber[0] is "3.0" and newNumber[0] is "3.1". | 111 | example, oldNumber[0] is "3.0" and newNumber[0] is "3.1". |
106 | */ | 112 | */ |
107 | for ( i = 0, j = 0; i < oldSourceLen; i++, j++ ) { | 113 | for ( i = 0, j = 0; i < oldSourceLen; i++, j++ ) { |
108 | m = numberLength( oldSource + i ); | 114 | m = numberLength( oldSource + i ); |
109 | n = numberLength( newSource + j ); | 115 | n = numberLength( newSource + j ); |
110 | if ( m > 0 ) { | 116 | if ( m > 0 ) { |
111 | oldNumbers.append( QCString(oldSource + i, m + 1) ); | 117 | oldNumbers.append( QCString(oldSource + i, m + 1) ); |
112 | newNumbers.append( QCString(newSource + j, n + 1) ); | 118 | newNumbers.append( QCString(newSource + j, n + 1) ); |
113 | i += m; | 119 | i += m; |
114 | j += n; | 120 | j += n; |
115 | met[k] = FALSE; | 121 | met[k] = FALSE; |
116 | matchedYet[k] = 0; | 122 | matchedYet[k] = 0; |
117 | k++; | 123 | k++; |
118 | } | 124 | } |
119 | } | 125 | } |
120 | 126 | ||
121 | /* | 127 | /* |
122 | We now go over the old translation, "XeT 3.0", one letter at a | 128 | We now go over the old translation, "XeT 3.0", one letter at a |
123 | time, looking for numbers found in oldNumbers. Whenever such a | 129 | time, looking for numbers found in oldNumbers. Whenever such a |
124 | number is met, it is replaced with its newNumber equivalent. In | 130 | number is met, it is replaced with its newNumber equivalent. In |
125 | our example, the "3.0" of "XeT 3.0" becomes "3.1". | 131 | our example, the "3.0" of "XeT 3.0" becomes "3.1". |
126 | */ | 132 | */ |
127 | for ( i = 0; i < (int) oldTranslation.length(); i++ ) { | 133 | for ( i = 0; i < (int) oldTranslation.length(); i++ ) { |
128 | attempt += oldTranslation[i]; | 134 | attempt += oldTranslation[i]; |
129 | for ( k = 0; k < p; k++ ) { | 135 | for ( k = 0; k < p; k++ ) { |
130 | if ( oldTranslation[i] == oldNumbers[k][matchedYet[k]] ) | 136 | if ( oldTranslation[i] == oldNumbers[k][matchedYet[k]] ) |
131 | matchedYet[k]++; | 137 | matchedYet[k]++; |
132 | else | 138 | else |
133 | matchedYet[k] = 0; | 139 | matchedYet[k] = 0; |
134 | } | 140 | } |
135 | 141 | ||
136 | /* | 142 | /* |
137 | Let's find out if the last character ended a match. We make | 143 | Let's find out if the last character ended a match. We make |
138 | two passes over the data. In the first pass, we try to | 144 | two passes over the data. In the first pass, we try to |
139 | match only numbers that weren't matched yet; if that fails, | 145 | match only numbers that weren't matched yet; if that fails, |
140 | the second pass does the trick. This is useful in some | 146 | the second pass does the trick. This is useful in some |
141 | suspicious cases, flagged below. | 147 | suspicious cases, flagged below. |
142 | */ | 148 | */ |
143 | for ( pass = 0; pass < 2; pass++ ) { | 149 | for ( pass = 0; pass < 2; pass++ ) { |
144 | best = p; // an impossible value | 150 | best = p; // an impossible value |
145 | for ( k = 0; k < p; k++ ) { | 151 | for ( k = 0; k < p; k++ ) { |
146 | if ( (!met[k] || pass > 0) && | 152 | if ( (!met[k] || pass > 0) && |
147 | matchedYet[k] == (int) oldNumbers[k].length() && | 153 | matchedYet[k] == (int) oldNumbers[k].length() && |
148 | numberLength(oldTranslation.latin1() + (i + 1) - | 154 | numberLength(oldTranslation.latin1() + (i + 1) - |
149 | matchedYet[k]) == matchedYet[k] ) { | 155 | matchedYet[k]) == matchedYet[k] ) { |
150 | // the longer the better | 156 | // the longer the better |
151 | if ( best == p || matchedYet[k] > matchedYet[best] ) | 157 | if ( best == p || matchedYet[k] > matchedYet[best] ) |
152 | best = k; | 158 | best = k; |
153 | } | 159 | } |
154 | } | 160 | } |
155 | if ( best != p ) { | 161 | if ( best != p ) { |
156 | attempt.truncate( attempt.length() - matchedYet[best] ); | 162 | attempt.truncate( attempt.length() - matchedYet[best] ); |
157 | attempt += newNumbers[best]; | 163 | attempt += newNumbers[best]; |
158 | met[best] = TRUE; | 164 | met[best] = TRUE; |
159 | for ( k = 0; k < p; k++ ) | 165 | for ( k = 0; k < p; k++ ) |
160 | matchedYet[k] = 0; | 166 | matchedYet[k] = 0; |
161 | break; | 167 | break; |
162 | } | 168 | } |
163 | } | 169 | } |
164 | } | 170 | } |
165 | 171 | ||
166 | /* | 172 | /* |
167 | We flag two kinds of suspicious cases. They are identified as | 173 | We flag two kinds of suspicious cases. They are identified as |
168 | such with comments such as "{2000?}" at the end. | 174 | such with comments such as "{2000?}" at the end. |
169 | 175 | ||
170 | Example of the first kind: old source text "TeX 3.0" translated | 176 | Example of the first kind: old source text "TeX 3.0" translated |
171 | as "XeT 2.0" is flagged "TeX 2.0 {3.0?}", no matter what the | 177 | as "XeT 2.0" is flagged "TeX 2.0 {3.0?}", no matter what the |
172 | new text is. | 178 | new text is. |
173 | */ | 179 | */ |
174 | for ( k = 0; k < p; k++ ) { | 180 | for ( k = 0; k < p; k++ ) { |
175 | if ( !met[k] ) | 181 | if ( !met[k] ) |
176 | attempt += QString( " {" ) + newNumbers[k] + QString( "?}" ); | 182 | attempt += QString( " {" ) + newNumbers[k] + QString( "?}" ); |
177 | } | 183 | } |
178 | 184 | ||
179 | /* | 185 | /* |
180 | Example of the second kind: "1 of 1" translated as "1 af 1", | 186 | Example of the second kind: "1 of 1" translated as "1 af 1", |
181 | with new source text "1 of 2", generates "1 af 2 {1 or 2?}" | 187 | with new source text "1 of 2", generates "1 af 2 {1 or 2?}" |
182 | because it's not clear which of "1 af 2" and "2 af 1" is right. | 188 | because it's not clear which of "1 af 2" and "2 af 1" is right. |
183 | */ | 189 | */ |
184 | for ( k = 0; k < p; k++ ) { | 190 | for ( k = 0; k < p; k++ ) { |
185 | for ( ell = 0; ell < p; ell++ ) { | 191 | for ( ell = 0; ell < p; ell++ ) { |
186 | if ( k != ell && oldNumbers[k] == oldNumbers[ell] && | 192 | if ( k != ell && oldNumbers[k] == oldNumbers[ell] && |
187 | newNumbers[k] < newNumbers[ell] ) | 193 | newNumbers[k] < newNumbers[ell] ) |
188 | attempt += QString( " {" ) + newNumbers[k] + QString( " or " ) + | 194 | attempt += QString( " {" ) + newNumbers[k] + QString( " or " ) + |
189 | newNumbers[ell] + QString( "?}" ); | 195 | newNumbers[ell] + QString( "?}" ); |
190 | } | 196 | } |
191 | } | 197 | } |
192 | return attempt; | 198 | return attempt; |
193 | } | 199 | } |
194 | 200 | ||
195 | /* | 201 | /* |
196 | Augments a MetaTranslator with translations easily derived from | 202 | Augments a MetaTranslator with translations easily derived from |
197 | similar existing (probably obsolete) translations. | 203 | similar existing (probably obsolete) translations. |
198 | 204 | ||
199 | For example, if "TeX 3.0" is translated as "XeT 3.0" and "TeX 3.1" | 205 | For example, if "TeX 3.0" is translated as "XeT 3.0" and "TeX 3.1" |
200 | has no translation, "XeT 3.1" is added to the translator and is | 206 | has no translation, "XeT 3.1" is added to the translator and is |
201 | marked Unfinished. | 207 | marked Unfinished. |
202 | */ | 208 | */ |
203 | void applyNumberHeuristic( MetaTranslator *tor, bool verbose ) | 209 | void applyNumberHeuristic( MetaTranslator *tor, bool verbose ) |
204 | { | 210 | { |
205 | TMM translated, untranslated; | 211 | TMM translated, untranslated; |
206 | TMM::Iterator t, u; | 212 | TMM::Iterator t, u; |
207 | TML all = tor->messages(); | 213 | TML all = tor->messages(); |
208 | TML::Iterator it; | 214 | TML::Iterator it; |
209 | int inserted = 0; | 215 | int inserted = 0; |
210 | 216 | ||
211 | for ( it = all.begin(); it != all.end(); ++it ) { | 217 | for ( it = all.begin(); it != all.end(); ++it ) { |
212 | if ( (*it).type() == MetaTranslatorMessage::Unfinished ) { | 218 | if ( (*it).type() == MetaTranslatorMessage::Unfinished ) { |
213 | if ( (*it).translation().isEmpty() ) | 219 | if ( (*it).translation().isEmpty() ) |
214 | untranslated.insert( zeroKey((*it).sourceText()), *it ); | 220 | untranslated.insert(QCString((*it).context()) + "\n" + (*it).sourceText() + "\n" |
221 | + (*it).comment(), *it); | ||
215 | } else if ( !(*it).translation().isEmpty() ) { | 222 | } else if ( !(*it).translation().isEmpty() ) { |
216 | translated.insert( zeroKey((*it).sourceText()), *it ); | 223 | translated.insert( zeroKey((*it).sourceText()), *it ); |
217 | } | 224 | } |
218 | } | 225 | } |
219 | 226 | ||
220 | for ( u = untranslated.begin(); u != untranslated.end(); ++u ) { | 227 | for ( u = untranslated.begin(); u != untranslated.end(); ++u ) { |
221 | t = translated.find( u.key() ); | 228 | t = translated.find( zeroKey((*u).sourceText()) ); |
222 | if ( t != translated.end() && !t.key().isEmpty() && | 229 | if ( t != translated.end() && !t.key().isEmpty() && |
223 | qstrcmp((*t).sourceText(), (*u).sourceText()) != 0 ) { | 230 | qstrcmp((*t).sourceText(), (*u).sourceText()) != 0 ) { |
224 | MetaTranslatorMessage m( *u ); | 231 | MetaTranslatorMessage m( *u ); |
225 | m.setTranslation( translationAttempt((*t).translation(), | 232 | m.setTranslation(translationAttempt((*t).translation(), (*t).sourceText(), |
226 | (*t).sourceText(), | 233 | (*u).sourceText())); |
227 | (*u).sourceText()) ); | ||
228 | tor->insert( m ); | 234 | tor->insert( m ); |
229 | inserted++; | 235 | inserted++; |
230 | } | 236 | } |
231 | } | 237 | } |
232 | if ( verbose && inserted != 0 ) | 238 | if ( verbose && inserted != 0 ) |
233 | fprintf( stderr, " number heuristic provided %d translation%s\n", | 239 | fprintf( stderr, " number heuristic provided %d translation%s\n", |
234 | inserted, inserted == 1 ? "" : "s" ); | 240 | inserted, inserted == 1 ? "" : "s" ); |
235 | } | 241 | } |
diff --git a/development/translation/opie-lupdate/sametexth.cpp b/development/translation/opie-lupdate/sametexth.cpp index 574cfd5..80909b3 100644 --- a/development/translation/opie-lupdate/sametexth.cpp +++ b/development/translation/opie-lupdate/sametexth.cpp | |||
@@ -1,84 +1,90 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #include <metatranslator.h> | 27 | #include <metatranslator.h> |
22 | 28 | ||
23 | #include <qcstring.h> | 29 | #include <qcstring.h> |
24 | #include <qmap.h> | 30 | #include <qmap.h> |
25 | 31 | ||
26 | typedef QMap<QCString, MetaTranslatorMessage> TMM; | 32 | typedef QMap<QCString, MetaTranslatorMessage> TMM; |
27 | typedef QValueList<MetaTranslatorMessage> TML; | 33 | typedef QValueList<MetaTranslatorMessage> TML; |
28 | 34 | ||
29 | /* | 35 | /* |
30 | Augments a MetaTranslator with trivially derived translations. | 36 | Augments a MetaTranslator with trivially derived translations. |
31 | 37 | ||
32 | For example, if "Enabled:" is consistendly translated as "Eingeschaltet:" no | 38 | For example, if "Enabled:" is consistendly translated as "Eingeschaltet:" no |
33 | matter the context or the comment, "Eingeschaltet:" is added as the | 39 | matter the context or the comment, "Eingeschaltet:" is added as the |
34 | translation of any untranslated "Enabled:" text and is marked Unfinished. | 40 | translation of any untranslated "Enabled:" text and is marked Unfinished. |
35 | */ | 41 | */ |
36 | 42 | ||
37 | void applySameTextHeuristic( MetaTranslator *tor, bool verbose ) | 43 | void applySameTextHeuristic( MetaTranslator *tor, bool verbose ) |
38 | { | 44 | { |
39 | TMM translated; | 45 | TMM translated; |
40 | TMM avoid; | 46 | TMM avoid; |
41 | TMM::Iterator t; | 47 | TMM::Iterator t; |
42 | TML untranslated; | 48 | TML untranslated; |
43 | TML::Iterator u; | 49 | TML::Iterator u; |
44 | TML all = tor->messages(); | 50 | TML all = tor->messages(); |
45 | TML::Iterator it; | 51 | TML::Iterator it; |
46 | int inserted = 0; | 52 | int inserted = 0; |
47 | 53 | ||
48 | for ( it = all.begin(); it != all.end(); ++it ) { | 54 | for ( it = all.begin(); it != all.end(); ++it ) { |
49 | if ( (*it).type() == MetaTranslatorMessage::Unfinished ) { | 55 | if ( (*it).type() == MetaTranslatorMessage::Unfinished ) { |
50 | if ( (*it).translation().isEmpty() ) | 56 | if ( (*it).translation().isEmpty() ) |
51 | untranslated.append( *it ); | 57 | untranslated.append( *it ); |
52 | } else { | 58 | } else { |
53 | QCString key = (*it).sourceText(); | 59 | QCString key = (*it).sourceText(); |
54 | t = translated.find( key ); | 60 | t = translated.find( key ); |
55 | if ( t != translated.end() ) { | 61 | if ( t != translated.end() ) { |
56 | /* | 62 | /* |
57 | The same source text is translated at least two | 63 | The same source text is translated at least two |
58 | different ways. Do nothing then. | 64 | different ways. Do nothing then. |
59 | */ | 65 | */ |
60 | if ( (*t).translation() != (*it).translation() ) { | 66 | if ( (*t).translation() != (*it).translation() ) { |
61 | translated.remove( key ); | 67 | translated.remove( key ); |
62 | avoid.insert( key, *it ); | 68 | avoid.insert( key, *it ); |
63 | } | 69 | } |
64 | } else if ( !avoid.contains(key) && | 70 | } else if ( !avoid.contains(key) && |
65 | !(*it).translation().isEmpty() ) { | 71 | !(*it).translation().isEmpty() ) { |
66 | translated.insert( key, *it ); | 72 | translated.insert( key, *it ); |
67 | } | 73 | } |
68 | } | 74 | } |
69 | } | 75 | } |
70 | 76 | ||
71 | for ( u = untranslated.begin(); u != untranslated.end(); ++u ) { | 77 | for ( u = untranslated.begin(); u != untranslated.end(); ++u ) { |
72 | QCString key = (*u).sourceText(); | 78 | QCString key = (*u).sourceText(); |
73 | t = translated.find( key ); | 79 | t = translated.find( key ); |
74 | if ( t != translated.end() ) { | 80 | if ( t != translated.end() ) { |
75 | MetaTranslatorMessage m( *u ); | 81 | MetaTranslatorMessage m( *u ); |
76 | m.setTranslation( (*t).translation() ); | 82 | m.setTranslation( (*t).translation() ); |
77 | tor->insert( m ); | 83 | tor->insert( m ); |
78 | inserted++; | 84 | inserted++; |
79 | } | 85 | } |
80 | } | 86 | } |
81 | if ( verbose && inserted != 0 ) | 87 | if ( verbose && inserted != 0 ) |
82 | fprintf( stderr, " same-text heuristic provided %d translation%s\n", | 88 | fprintf( stderr, " same-text heuristic provided %d translation%s\n", |
83 | inserted, inserted == 1 ? "" : "s" ); | 89 | inserted, inserted == 1 ? "" : "s" ); |
84 | } | 90 | } |
diff --git a/development/translation/shared/metatranslator.cpp b/development/translation/shared/metatranslator.cpp index a01e1eb..51270c5 100644 --- a/development/translation/shared/metatranslator.cpp +++ b/development/translation/shared/metatranslator.cpp | |||
@@ -1,586 +1,596 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #include "metatranslator.h" | 27 | #include "metatranslator.h" |
22 | 28 | ||
23 | #include <qapplication.h> | 29 | #include <qapplication.h> |
24 | #include <qcstring.h> | 30 | #include <qcstring.h> |
25 | #include <qfile.h> | 31 | #include <qfile.h> |
26 | #include <qmessagebox.h> | 32 | #include <qmessagebox.h> |
27 | #include <qtextcodec.h> | 33 | #include <qtextcodec.h> |
28 | #include <qtextstream.h> | 34 | #include <qtextstream.h> |
29 | #include <qxml.h> | 35 | #include <qxml.h> |
30 | 36 | ||
31 | static bool encodingIsUtf8( const QXmlAttributes& atts ) | 37 | static bool encodingIsUtf8( const QXmlAttributes& atts ) |
32 | { | 38 | { |
33 | for ( int i = 0; i < atts.length(); i++ ) { | 39 | for ( int i = 0; i < atts.length(); i++ ) { |
34 | // utf8="true" is a pre-3.0 syntax | 40 | // utf8="true" is a pre-3.0 syntax |
35 | if ( atts.qName(i) == QString("utf8") ) { | 41 | if ( atts.qName(i) == QString("utf8") ) { |
36 | return ( atts.value(i) == QString("true") ); | 42 | return ( atts.value(i) == QString("true") ); |
37 | } else if ( atts.qName(i) == QString("encoding") ) { | 43 | } else if ( atts.qName(i) == QString("encoding") ) { |
38 | return ( atts.value(i) == QString("UTF-8") ); | 44 | return ( atts.value(i) == QString("UTF-8") ); |
39 | } | 45 | } |
40 | } | 46 | } |
41 | return FALSE; | 47 | return FALSE; |
42 | } | 48 | } |
43 | 49 | ||
44 | class TsHandler : public QXmlDefaultHandler | 50 | class TsHandler : public QXmlDefaultHandler |
45 | { | 51 | { |
46 | public: | 52 | public: |
47 | TsHandler( MetaTranslator *translator ) | 53 | TsHandler( MetaTranslator *translator ) |
48 | : tor( translator ), type( MetaTranslatorMessage::Finished ), | 54 | : tor( translator ), type( MetaTranslatorMessage::Finished ), |
49 | inMessage( FALSE ), ferrorCount( 0 ), contextIsUtf8( FALSE ), | 55 | inMessage( FALSE ), ferrorCount( 0 ), contextIsUtf8( FALSE ), |
50 | messageIsUtf8( FALSE ) { } | 56 | messageIsUtf8( FALSE ) { } |
51 | 57 | ||
52 | virtual bool startElement( const QString& namespaceURI, | 58 | virtual bool startElement( const QString& namespaceURI, |
53 | const QString& localName, const QString& qName, | 59 | const QString& localName, const QString& qName, |
54 | const QXmlAttributes& atts ); | 60 | const QXmlAttributes& atts ); |
55 | virtual bool endElement( const QString& namespaceURI, | 61 | virtual bool endElement( const QString& namespaceURI, |
56 | const QString& localName, const QString& qName ); | 62 | const QString& localName, const QString& qName ); |
57 | virtual bool characters( const QString& ch ); | 63 | virtual bool characters( const QString& ch ); |
58 | virtual bool fatalError( const QXmlParseException& exception ); | 64 | virtual bool fatalError( const QXmlParseException& exception ); |
59 | 65 | ||
60 | private: | 66 | private: |
61 | MetaTranslator *tor; | 67 | MetaTranslator *tor; |
62 | MetaTranslatorMessage::Type type; | 68 | MetaTranslatorMessage::Type type; |
63 | bool inMessage; | 69 | bool inMessage; |
64 | QString context; | 70 | QString context; |
65 | QString source; | 71 | QString source; |
66 | QString comment; | 72 | QString comment; |
67 | QString translation; | 73 | QString translation; |
68 | 74 | ||
69 | QString accum; | 75 | QString accum; |
70 | int ferrorCount; | 76 | int ferrorCount; |
71 | bool contextIsUtf8; | 77 | bool contextIsUtf8; |
72 | bool messageIsUtf8; | 78 | bool messageIsUtf8; |
73 | }; | 79 | }; |
74 | 80 | ||
75 | bool TsHandler::startElement( const QString& /* namespaceURI */, | 81 | bool TsHandler::startElement( const QString& /* namespaceURI */, |
76 | const QString& /* localName */, | 82 | const QString& /* localName */, |
77 | const QString& qName, | 83 | const QString& qName, |
78 | const QXmlAttributes& atts ) | 84 | const QXmlAttributes& atts ) |
79 | { | 85 | { |
80 | if ( qName == QString("byte") ) { | 86 | if ( qName == QString("byte") ) { |
81 | for ( int i = 0; i < atts.length(); i++ ) { | 87 | for ( int i = 0; i < atts.length(); i++ ) { |
82 | if ( atts.qName(i) == QString("value") ) { | 88 | if ( atts.qName(i) == QString("value") ) { |
83 | QString value = atts.value( i ); | 89 | QString value = atts.value( i ); |
84 | int base = 10; | 90 | int base = 10; |
85 | if ( value.startsWith("x") ) { | 91 | if ( value.startsWith("x") ) { |
86 | base = 16; | 92 | base = 16; |
87 | value = value.mid( 1 ); | 93 | value = value.mid( 1 ); |
88 | } | 94 | } |
89 | int n = value.toUInt( 0, base ); | 95 | int n = value.toUInt( 0, base ); |
90 | if ( n != 0 ) | 96 | if ( n != 0 ) |
91 | accum += QChar( n ); | 97 | accum += QChar( n ); |
92 | } | 98 | } |
93 | } | 99 | } |
94 | } else { | 100 | } else { |
95 | if ( qName == QString("context") ) { | 101 | if ( qName == QString("context") ) { |
96 | context.truncate( 0 ); | 102 | context.truncate( 0 ); |
97 | source.truncate( 0 ); | 103 | source.truncate( 0 ); |
98 | comment.truncate( 0 ); | 104 | comment.truncate( 0 ); |
99 | translation.truncate( 0 ); | 105 | translation.truncate( 0 ); |
100 | contextIsUtf8 = encodingIsUtf8( atts ); | 106 | contextIsUtf8 = encodingIsUtf8( atts ); |
101 | } else if ( qName == QString("message") ) { | 107 | } else if ( qName == QString("message") ) { |
102 | inMessage = TRUE; | 108 | inMessage = TRUE; |
103 | type = MetaTranslatorMessage::Finished; | 109 | type = MetaTranslatorMessage::Finished; |
104 | source.truncate( 0 ); | 110 | source.truncate( 0 ); |
105 | comment.truncate( 0 ); | 111 | comment.truncate( 0 ); |
106 | translation.truncate( 0 ); | 112 | translation.truncate( 0 ); |
107 | messageIsUtf8 = encodingIsUtf8( atts ); | 113 | messageIsUtf8 = encodingIsUtf8( atts ); |
108 | } else if ( qName == QString("translation") ) { | 114 | } else if ( qName == QString("translation") ) { |
109 | for ( int i = 0; i < atts.length(); i++ ) { | 115 | for ( int i = 0; i < atts.length(); i++ ) { |
110 | if ( atts.qName(i) == QString("type") ) { | 116 | if ( atts.qName(i) == QString("type") ) { |
111 | if ( atts.value(i) == QString("unfinished") ) | 117 | if ( atts.value(i) == QString("unfinished") ) |
112 | type = MetaTranslatorMessage::Unfinished; | 118 | type = MetaTranslatorMessage::Unfinished; |
113 | else if ( atts.value(i) == QString("obsolete") ) | 119 | else if ( atts.value(i) == QString("obsolete") ) |
114 | type = MetaTranslatorMessage::Obsolete; | 120 | type = MetaTranslatorMessage::Obsolete; |
115 | else | 121 | else |
116 | type = MetaTranslatorMessage::Finished; | 122 | type = MetaTranslatorMessage::Finished; |
117 | } | 123 | } |
118 | } | 124 | } |
119 | } | 125 | } |
120 | accum.truncate( 0 ); | 126 | accum.truncate( 0 ); |
121 | } | 127 | } |
122 | return TRUE; | 128 | return TRUE; |
123 | } | 129 | } |
124 | 130 | ||
125 | bool TsHandler::endElement( const QString& /* namespaceURI */, | 131 | bool TsHandler::endElement( const QString& /* namespaceURI */, |
126 | const QString& /* localName */, | 132 | const QString& /* localName */, |
127 | const QString& qName ) | 133 | const QString& qName ) |
128 | { | 134 | { |
129 | if ( qName == QString("codec") || qName == QString("defaultcodec") ) { | 135 | if ( qName == QString("codec") || qName == QString("defaultcodec") ) { |
130 | // "codec" is a pre-3.0 syntax | 136 | // "codec" is a pre-3.0 syntax |
131 | tor->setCodec( accum ); | 137 | tor->setCodec( accum ); |
132 | } else if ( qName == QString("name") ) { | 138 | } else if ( qName == QString("name") ) { |
133 | context = accum; | 139 | context = accum; |
134 | } else if ( qName == QString("source") ) { | 140 | } else if ( qName == QString("source") ) { |
135 | source = accum; | 141 | source = accum; |
136 | } else if ( qName == QString("comment") ) { | 142 | } else if ( qName == QString("comment") ) { |
137 | if ( inMessage ) { | 143 | if ( inMessage ) { |
138 | comment = accum; | 144 | comment = accum; |
139 | } else { | 145 | } else { |
140 | if ( contextIsUtf8 ) | 146 | if ( contextIsUtf8 ) |
141 | tor->insert( MetaTranslatorMessage(context.utf8(), "", | 147 | tor->insert( MetaTranslatorMessage(context.utf8(), |
148 | ContextComment, | ||
142 | accum.utf8(), QString::null, TRUE, | 149 | accum.utf8(), QString::null, TRUE, |
143 | MetaTranslatorMessage::Unfinished) ); | 150 | MetaTranslatorMessage::Unfinished) ); |
144 | else | 151 | else |
145 | tor->insert( MetaTranslatorMessage(context.ascii(), "", | 152 | tor->insert( MetaTranslatorMessage(context.ascii(), |
153 | ContextComment, | ||
146 | accum.ascii(), QString::null, FALSE, | 154 | accum.ascii(), QString::null, FALSE, |
147 | MetaTranslatorMessage::Unfinished) ); | 155 | MetaTranslatorMessage::Unfinished) ); |
148 | } | 156 | } |
149 | } else if ( qName == QString("translation") ) { | 157 | } else if ( qName == QString("translation") ) { |
150 | translation = accum; | 158 | translation = accum; |
151 | } else if ( qName == QString("message") ) { | 159 | } else if ( qName == QString("message") ) { |
152 | if ( messageIsUtf8 ) | 160 | if ( messageIsUtf8 ) |
153 | tor->insert( MetaTranslatorMessage(context.utf8(), source.utf8(), | 161 | tor->insert( MetaTranslatorMessage(context.utf8(), source.utf8(), |
154 | comment.utf8(), translation, | 162 | comment.utf8(), translation, |
155 | TRUE, type) ); | 163 | TRUE, type) ); |
156 | else | 164 | else |
157 | tor->insert( MetaTranslatorMessage(context.ascii(), source.ascii(), | 165 | tor->insert( MetaTranslatorMessage(context.ascii(), source.ascii(), |
158 | comment.ascii(), translation, | 166 | comment.ascii(), translation, |
159 | FALSE, type) ); | 167 | FALSE, type) ); |
160 | inMessage = FALSE; | 168 | inMessage = FALSE; |
161 | } | 169 | } |
162 | return TRUE; | 170 | return TRUE; |
163 | } | 171 | } |
164 | 172 | ||
165 | bool TsHandler::characters( const QString& ch ) | 173 | bool TsHandler::characters( const QString& ch ) |
166 | { | 174 | { |
167 | QString t = ch; | 175 | QString t = ch; |
168 | t.replace( "\r", "" ); | 176 | t.replace( "\r", "" ); |
169 | accum += t; | 177 | accum += t; |
170 | return TRUE; | 178 | return TRUE; |
171 | } | 179 | } |
172 | 180 | ||
173 | bool TsHandler::fatalError( const QXmlParseException& exception ) | 181 | bool TsHandler::fatalError( const QXmlParseException& exception ) |
174 | { | 182 | { |
175 | if ( ferrorCount++ == 0 ) { | 183 | if ( ferrorCount++ == 0 ) { |
176 | QString msg; | 184 | QString msg; |
177 | msg.sprintf( "Parse error at line %d, column %d (%s).", | 185 | msg.sprintf( "Parse error at line %d, column %d (%s).", |
178 | exception.lineNumber(), exception.columnNumber(), | 186 | exception.lineNumber(), exception.columnNumber(), |
179 | exception.message().latin1() ); | 187 | exception.message().latin1() ); |
180 | if ( qApp == 0 ) | 188 | if ( qApp == 0 ) |
181 | fprintf( stderr, "XML error: %s\n", msg.latin1() ); | 189 | fprintf( stderr, "XML error: %s\n", msg.latin1() ); |
182 | else | 190 | else |
183 | QMessageBox::information( qApp->mainWidget(), | 191 | QMessageBox::information( qApp->mainWidget(), |
184 | QObject::tr("Qt Linguist"), msg ); | 192 | QObject::tr("Qt Linguist"), msg ); |
185 | } | 193 | } |
186 | return FALSE; | 194 | return FALSE; |
187 | } | 195 | } |
188 | 196 | ||
189 | static QString numericEntity( int ch ) | 197 | static QString numericEntity( int ch ) |
190 | { | 198 | { |
191 | return QString( ch <= 0x20 ? "<byte value=\"x%1\"/>" : "&#x%1;" ) | 199 | return QString( ch <= 0x20 ? "<byte value=\"x%1\"/>" : "&#x%1;" ) |
192 | .arg( ch, 0, 16 ); | 200 | .arg( ch, 0, 16 ); |
193 | } | 201 | } |
194 | 202 | ||
195 | static QString protect( const QCString& str ) | 203 | static QString protect( const QCString& str ) |
196 | { | 204 | { |
197 | QString result; | 205 | QString result; |
198 | int len = (int) str.length(); | 206 | int len = (int) str.length(); |
199 | for ( int k = 0; k < len; k++ ) { | 207 | for ( int k = 0; k < len; k++ ) { |
200 | switch( str[k] ) { | 208 | switch( str[k] ) { |
201 | case '\"': | 209 | case '\"': |
202 | result += QString( """ ); | 210 | result += QString( """ ); |
203 | break; | 211 | break; |
204 | case '&': | 212 | case '&': |
205 | result += QString( "&" ); | 213 | result += QString( "&" ); |
206 | break; | 214 | break; |
207 | case '>': | 215 | case '>': |
208 | result += QString( ">" ); | 216 | result += QString( ">" ); |
209 | break; | 217 | break; |
210 | case '<': | 218 | case '<': |
211 | result += QString( "<" ); | 219 | result += QString( "<" ); |
212 | break; | 220 | break; |
213 | case '\'': | 221 | case '\'': |
214 | result += QString( "'" ); | 222 | result += QString( "'" ); |
215 | break; | 223 | break; |
216 | default: | 224 | default: |
217 | if ( (uchar) str[k] < 0x20 && str[k] != '\n' ) | 225 | if ( (uchar) str[k] < 0x20 && str[k] != '\n' ) |
218 | result += numericEntity( (uchar) str[k] ); | 226 | result += numericEntity( (uchar) str[k] ); |
219 | else | 227 | else |
220 | result += str[k]; | 228 | result += str[k]; |
221 | } | 229 | } |
222 | } | 230 | } |
223 | return result; | 231 | return result; |
224 | } | 232 | } |
225 | 233 | ||
226 | static QString evilBytes( const QCString& str, bool utf8 ) | 234 | static QString evilBytes( const QCString& str, bool utf8 ) |
227 | { | 235 | { |
228 | if ( utf8 ) { | 236 | if ( utf8 ) { |
229 | return protect( str ); | 237 | return protect( str ); |
230 | } else { | 238 | } else { |
231 | QString result; | 239 | QString result; |
232 | QCString t = protect( str ).latin1(); | 240 | QCString t = protect( str ).latin1(); |
233 | int len = (int) t.length(); | 241 | int len = (int) t.length(); |
234 | for ( int k = 0; k < len; k++ ) { | 242 | for ( int k = 0; k < len; k++ ) { |
235 | if ( (uchar) t[k] >= 0x7f ) | 243 | if ( (uchar) t[k] >= 0x7f ) |
236 | result += numericEntity( (uchar) t[k] ); | 244 | result += numericEntity( (uchar) t[k] ); |
237 | else | 245 | else |
238 | result += QChar( t[k] ); | 246 | result += QChar( t[k] ); |
239 | } | 247 | } |
240 | return result; | 248 | return result; |
241 | } | 249 | } |
242 | } | 250 | } |
243 | 251 | ||
244 | MetaTranslatorMessage::MetaTranslatorMessage() | 252 | MetaTranslatorMessage::MetaTranslatorMessage() |
245 | : utfeight( FALSE ), ty( Unfinished ) | 253 | : utfeight( FALSE ), ty( Unfinished ) |
246 | { | 254 | { |
247 | } | 255 | } |
248 | 256 | ||
249 | MetaTranslatorMessage::MetaTranslatorMessage( const char *context, | 257 | MetaTranslatorMessage::MetaTranslatorMessage( const char *context, |
250 | const char *sourceText, | 258 | const char *sourceText, |
251 | const char *comment, | 259 | const char *comment, |
252 | const QString& translation, | 260 | const QString& translation, |
253 | bool utf8, Type type ) | 261 | bool utf8, Type type ) |
254 | : QTranslatorMessage( context, sourceText, comment, translation ), | 262 | : QTranslatorMessage( context, sourceText, comment, translation ), |
255 | utfeight( FALSE ), ty( type ) | 263 | utfeight( FALSE ), ty( type ) |
256 | { | 264 | { |
257 | /* | 265 | /* |
258 | Don't use UTF-8 if it makes no difference. UTF-8 should be | 266 | Don't use UTF-8 if it makes no difference. UTF-8 should be |
259 | reserved for the real problematic case: non-ASCII (possibly | 267 | reserved for the real problematic case: non-ASCII (possibly |
260 | non-Latin-1) characters in .ui files. | 268 | non-Latin-1) characters in .ui files. |
261 | */ | 269 | */ |
262 | if ( utf8 ) { | 270 | if ( utf8 ) { |
263 | if ( sourceText != 0 ) { | 271 | if ( sourceText != 0 ) { |
264 | int i = 0; | 272 | int i = 0; |
265 | while ( sourceText[i] != '\0' ) { | 273 | while ( sourceText[i] != '\0' ) { |
266 | if ( (uchar) sourceText[i] >= 0x80 ) { | 274 | if ( (uchar) sourceText[i] >= 0x80 ) { |
267 | utfeight = TRUE; | 275 | utfeight = TRUE; |
268 | break; | 276 | break; |
269 | } | 277 | } |
270 | i++; | 278 | i++; |
271 | } | 279 | } |
272 | } | 280 | } |
273 | if ( !utfeight && comment != 0 ) { | 281 | if ( !utfeight && comment != 0 ) { |
274 | int i = 0; | 282 | int i = 0; |
275 | while ( comment[i] != '\0' ) { | 283 | while ( comment[i] != '\0' ) { |
276 | if ( (uchar) comment[i] >= 0x80 ) { | 284 | if ( (uchar) comment[i] >= 0x80 ) { |
277 | utfeight = TRUE; | 285 | utfeight = TRUE; |
278 | break; | 286 | break; |
279 | } | 287 | } |
280 | i++; | 288 | i++; |
281 | } | 289 | } |
282 | } | 290 | } |
283 | } | 291 | } |
284 | } | 292 | } |
285 | 293 | ||
286 | MetaTranslatorMessage::MetaTranslatorMessage( const MetaTranslatorMessage& m ) | 294 | MetaTranslatorMessage::MetaTranslatorMessage( const MetaTranslatorMessage& m ) |
287 | : QTranslatorMessage( m ), utfeight( m.utfeight ), ty( m.ty ) | 295 | : QTranslatorMessage( m ), utfeight( m.utfeight ), ty( m.ty ) |
288 | { | 296 | { |
289 | } | 297 | } |
290 | 298 | ||
291 | MetaTranslatorMessage& MetaTranslatorMessage::operator=( | 299 | MetaTranslatorMessage& MetaTranslatorMessage::operator=( |
292 | const MetaTranslatorMessage& m ) | 300 | const MetaTranslatorMessage& m ) |
293 | { | 301 | { |
294 | QTranslatorMessage::operator=( m ); | 302 | QTranslatorMessage::operator=( m ); |
295 | utfeight = m.utfeight; | 303 | utfeight = m.utfeight; |
296 | ty = m.ty; | 304 | ty = m.ty; |
297 | return *this; | 305 | return *this; |
298 | } | 306 | } |
299 | 307 | ||
300 | bool MetaTranslatorMessage::operator==( const MetaTranslatorMessage& m ) const | 308 | bool MetaTranslatorMessage::operator==( const MetaTranslatorMessage& m ) const |
301 | { | 309 | { |
302 | return qstrcmp( context(), m.context() ) == 0 && | 310 | return qstrcmp( context(), m.context() ) == 0 && |
303 | qstrcmp( sourceText(), m.sourceText() ) == 0 && | 311 | qstrcmp( sourceText(), m.sourceText() ) == 0 && |
304 | qstrcmp( comment(), m.comment() ) == 0; | 312 | qstrcmp( comment(), m.comment() ) == 0; |
305 | } | 313 | } |
306 | 314 | ||
307 | bool MetaTranslatorMessage::operator<( const MetaTranslatorMessage& m ) const | 315 | bool MetaTranslatorMessage::operator<( const MetaTranslatorMessage& m ) const |
308 | { | 316 | { |
309 | int delta = qstrcmp( context(), m.context() ); | 317 | int delta = qstrcmp( context(), m.context() ); |
310 | if ( delta == 0 ) | 318 | if ( delta == 0 ) |
311 | delta = qstrcmp( sourceText(), m.sourceText() ); | 319 | delta = qstrcmp( sourceText(), m.sourceText() ); |
312 | if ( delta == 0 ) | 320 | if ( delta == 0 ) |
313 | delta = qstrcmp( comment(), m.comment() ); | 321 | delta = qstrcmp( comment(), m.comment() ); |
314 | return delta < 0; | 322 | return delta < 0; |
315 | } | 323 | } |
316 | 324 | ||
317 | MetaTranslator::MetaTranslator() | 325 | MetaTranslator::MetaTranslator() |
318 | : codecName( "ISO-8859-1" ), codec( 0 ) | ||
319 | { | 326 | { |
327 | clear(); | ||
320 | } | 328 | } |
321 | 329 | ||
322 | MetaTranslator::MetaTranslator( const MetaTranslator& tor ) | 330 | MetaTranslator::MetaTranslator( const MetaTranslator& tor ) |
323 | : mm( tor.mm ), codecName( tor.codecName ), codec( tor.codec ) | 331 | : mm( tor.mm ), codecName( tor.codecName ), codec( tor.codec ) |
324 | { | 332 | { |
325 | |||
326 | } | 333 | } |
327 | 334 | ||
328 | MetaTranslator& MetaTranslator::operator=( const MetaTranslator& tor ) | 335 | MetaTranslator& MetaTranslator::operator=( const MetaTranslator& tor ) |
329 | { | 336 | { |
330 | mm = tor.mm; | 337 | mm = tor.mm; |
331 | codecName = tor.codecName; | 338 | codecName = tor.codecName; |
332 | codec = tor.codec; | 339 | codec = tor.codec; |
333 | return *this; | 340 | return *this; |
334 | } | 341 | } |
335 | 342 | ||
336 | bool MetaTranslator::load( const QString& filename ) | 343 | void MetaTranslator::clear() |
337 | { | 344 | { |
338 | mm.clear(); | 345 | mm.clear(); |
346 | codecName = "ISO-8859-1"; | ||
347 | codec = 0; | ||
348 | } | ||
339 | 349 | ||
350 | bool MetaTranslator::load( const QString& filename ) | ||
351 | { | ||
340 | QFile f( filename ); | 352 | QFile f( filename ); |
341 | if ( !f.open(IO_ReadOnly) ) | 353 | if ( !f.open(IO_ReadOnly) ) |
342 | return FALSE; | 354 | return FALSE; |
343 | 355 | ||
344 | QTextStream t( &f ); | 356 | QTextStream t( &f ); |
345 | QXmlInputSource in( t ); | 357 | QXmlInputSource in( t ); |
346 | QXmlSimpleReader reader; | 358 | QXmlSimpleReader reader; |
347 | // don't click on these! | ||
348 | reader.setFeature( "http://xml.org/sax/features/namespaces", FALSE ); | 359 | reader.setFeature( "http://xml.org/sax/features/namespaces", FALSE ); |
349 | reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", TRUE ); | 360 | reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", TRUE ); |
350 | reader.setFeature( "http://trolltech.com/xml/features/report-whitespace" | 361 | reader.setFeature( "http://trolltech.com/xml/features/report-whitespace" |
351 | "-only-CharData", FALSE ); | 362 | "-only-CharData", FALSE ); |
352 | QXmlDefaultHandler *hand = new TsHandler( this ); | 363 | QXmlDefaultHandler *hand = new TsHandler( this ); |
353 | reader.setContentHandler( hand ); | 364 | reader.setContentHandler( hand ); |
354 | reader.setErrorHandler( hand ); | 365 | reader.setErrorHandler( hand ); |
355 | 366 | ||
356 | bool ok = reader.parse( in ); | 367 | bool ok = reader.parse( in ); |
357 | reader.setContentHandler( 0 ); | 368 | reader.setContentHandler( 0 ); |
358 | reader.setErrorHandler( 0 ); | 369 | reader.setErrorHandler( 0 ); |
359 | delete hand; | 370 | delete hand; |
360 | f.close(); | 371 | f.close(); |
361 | if ( !ok ) | ||
362 | mm.clear(); | ||
363 | return ok; | 372 | return ok; |
364 | } | 373 | } |
365 | 374 | ||
366 | bool MetaTranslator::save( const QString& filename ) const | 375 | bool MetaTranslator::save( const QString& filename ) const |
367 | { | 376 | { |
368 | QFile f( filename ); | 377 | QFile f( filename ); |
369 | if ( !f.open(IO_WriteOnly) ) | 378 | if ( !f.open(IO_WriteOnly) ) |
370 | return FALSE; | 379 | return FALSE; |
371 | 380 | ||
372 | QTextStream t( &f ); | 381 | QTextStream t( &f ); |
373 | t.setCodec( QTextCodec::codecForName("ISO-8859-1") ); | 382 | t.setCodec( QTextCodec::codecForName("ISO-8859-1") ); |
374 | 383 | ||
375 | t << "<!DOCTYPE TS><TS>\n"; | 384 | t << "<!DOCTYPE TS><TS>\n"; |
376 | if ( codecName != "ISO-8859-1" ) | 385 | if ( codecName != "ISO-8859-1" ) |
377 | t << "<defaultcodec>" << codecName << "</defaultcodec>\n"; | 386 | t << "<defaultcodec>" << codecName << "</defaultcodec>\n"; |
378 | TMM::ConstIterator m = mm.begin(); | 387 | TMM::ConstIterator m = mm.begin(); |
379 | while ( m != mm.end() ) { | 388 | while ( m != mm.end() ) { |
380 | TMMInv inv; | 389 | TMMInv inv; |
381 | TMMInv::Iterator i; | 390 | TMMInv::Iterator i; |
382 | bool contextIsUtf8 = m.key().utf8(); | 391 | bool contextIsUtf8 = m.key().utf8(); |
383 | QCString context = m.key().context(); | 392 | QCString context = m.key().context(); |
384 | QCString comment = ""; | 393 | QCString comment = ""; |
385 | 394 | ||
386 | do { | 395 | do { |
387 | if ( QCString(m.key().sourceText()).isEmpty() ) { | 396 | if ( QCString(m.key().sourceText()) == ContextComment ) { |
388 | if ( m.key().type() != MetaTranslatorMessage::Obsolete ) { | 397 | if ( m.key().type() != MetaTranslatorMessage::Obsolete ) { |
389 | contextIsUtf8 = m.key().utf8(); | 398 | contextIsUtf8 = m.key().utf8(); |
390 | comment = QCString( m.key().comment() ); | 399 | comment = QCString( m.key().comment() ); |
391 | } | 400 | } |
392 | } else { | 401 | } else { |
393 | inv.insert( *m, m.key() ); | 402 | inv.insert( *m, m.key() ); |
394 | } | 403 | } |
395 | } while ( ++m != mm.end() && QCString(m.key().context()) == context ); | 404 | } while ( ++m != mm.end() && QCString(m.key().context()) == context ); |
396 | 405 | ||
397 | t << "<context"; | 406 | t << "<context"; |
398 | if ( contextIsUtf8 ) | 407 | if ( contextIsUtf8 ) |
399 | t << " encoding=\"UTF-8\""; | 408 | t << " encoding=\"UTF-8\""; |
400 | t << ">\n"; | 409 | t << ">\n"; |
401 | t << " <name>" << evilBytes( context, contextIsUtf8 ) | 410 | t << " <name>" << evilBytes( context, contextIsUtf8 ) |
402 | << "</name>\n"; | 411 | << "</name>\n"; |
403 | if ( !comment.isEmpty() ) | 412 | if ( !comment.isEmpty() ) |
404 | t << " <comment>" << evilBytes( comment, contextIsUtf8 ) | 413 | t << " <comment>" << evilBytes( comment, contextIsUtf8 ) |
405 | << "</comment>\n"; | 414 | << "</comment>\n"; |
406 | 415 | ||
407 | for ( i = inv.begin(); i != inv.end(); ++i ) { | 416 | for ( i = inv.begin(); i != inv.end(); ++i ) { |
408 | // no need for such noise | 417 | // no need for such noise |
409 | if ( (*i).type() == MetaTranslatorMessage::Obsolete && | 418 | if ( (*i).type() == MetaTranslatorMessage::Obsolete && |
410 | (*i).translation().isEmpty() ) | 419 | (*i).translation().isEmpty() ) |
411 | continue; | 420 | continue; |
412 | 421 | ||
413 | t << " <message"; | 422 | t << " <message"; |
414 | if ( (*i).utf8() ) | 423 | if ( (*i).utf8() ) |
415 | t << " encoding=\"UTF-8\""; | 424 | t << " encoding=\"UTF-8\""; |
416 | t << ">\n" | 425 | t << ">\n" |
417 | << " <source>" << evilBytes( (*i).sourceText(), | 426 | << " <source>" << evilBytes( (*i).sourceText(), |
418 | (*i).utf8() ) | 427 | (*i).utf8() ) |
419 | << "</source>\n"; | 428 | << "</source>\n"; |
420 | if ( !QCString((*i).comment()).isEmpty() ) | 429 | if ( !QCString((*i).comment()).isEmpty() ) |
421 | t << " <comment>" << evilBytes( (*i).comment(), | 430 | t << " <comment>" << evilBytes( (*i).comment(), |
422 | (*i).utf8() ) | 431 | (*i).utf8() ) |
423 | << "</comment>\n"; | 432 | << "</comment>\n"; |
424 | t << " <translation"; | 433 | t << " <translation"; |
425 | if ( (*i).type() == MetaTranslatorMessage::Unfinished ) | 434 | if ( (*i).type() == MetaTranslatorMessage::Unfinished ) |
426 | t << " type=\"unfinished\""; | 435 | t << " type=\"unfinished\""; |
427 | else if ( (*i).type() == MetaTranslatorMessage::Obsolete ) | 436 | else if ( (*i).type() == MetaTranslatorMessage::Obsolete ) |
428 | t << " type=\"obsolete\""; | 437 | t << " type=\"obsolete\""; |
429 | t << ">" << protect( (*i).translation().utf8() ) | 438 | t << ">" << protect( (*i).translation().utf8() ) |
430 | << "</translation>\n"; | 439 | << "</translation>\n"; |
431 | t << " </message>\n"; | 440 | t << " </message>\n"; |
432 | } | 441 | } |
433 | t << "</context>\n"; | 442 | t << "</context>\n"; |
434 | } | 443 | } |
435 | t << "</TS>\n"; | 444 | t << "</TS>\n"; |
436 | f.close(); | 445 | f.close(); |
437 | return TRUE; | 446 | return TRUE; |
438 | } | 447 | } |
439 | 448 | ||
440 | bool MetaTranslator::release( const QString& filename, bool verbose ) const | 449 | bool MetaTranslator::release( const QString& filename, bool verbose, |
450 | QTranslator::SaveMode mode ) const | ||
441 | { | 451 | { |
442 | QTranslator tor( 0 ); | 452 | QTranslator tor( 0 ); |
443 | int finished = 0; | 453 | int finished = 0; |
444 | int unfinished = 0; | 454 | int unfinished = 0; |
445 | int untranslated = 0; | 455 | int untranslated = 0; |
446 | TMM::ConstIterator m; | 456 | TMM::ConstIterator m; |
447 | 457 | ||
448 | for ( m = mm.begin(); m != mm.end(); ++m ) { | 458 | for ( m = mm.begin(); m != mm.end(); ++m ) { |
449 | if ( m.key().type() != MetaTranslatorMessage::Obsolete ) { | 459 | if ( m.key().type() != MetaTranslatorMessage::Obsolete ) { |
450 | if ( m.key().translation().isEmpty() ) { | 460 | if ( m.key().translation().isEmpty() ) { |
451 | untranslated++; | 461 | untranslated++; |
452 | } else { | 462 | } else { |
453 | if ( m.key().type() == MetaTranslatorMessage::Unfinished ) | 463 | if ( m.key().type() == MetaTranslatorMessage::Unfinished ) |
454 | unfinished++; | 464 | unfinished++; |
455 | else | 465 | else |
456 | finished++; | 466 | finished++; |
457 | 467 | ||
458 | QCString context = m.key().context(); | 468 | QCString context = m.key().context(); |
459 | QCString sourceText = m.key().sourceText(); | 469 | QCString sourceText = m.key().sourceText(); |
460 | QCString comment = m.key().comment(); | 470 | QCString comment = m.key().comment(); |
461 | QString translation = m.key().translation(); | 471 | QString translation = m.key().translation(); |
462 | 472 | ||
463 | /* | 473 | /* |
464 | Drop the comment in (context, sourceText, comment), | 474 | Drop the comment in (context, sourceText, comment), |
465 | unless (context, sourceText, "") already exists, or | 475 | unless (context, sourceText, "") already exists, or |
466 | unless we already dropped the comment of (context, | 476 | unless we already dropped the comment of (context, |
467 | sourceText, comment0). | 477 | sourceText, comment0). |
468 | */ | 478 | */ |
469 | if ( comment.isEmpty() | 479 | if ( comment.isEmpty() |
470 | || contains(context, sourceText, "") | 480 | || contains(context, sourceText, "") |
471 | || !tor.findMessage(context, sourceText, "").translation() | 481 | || !tor.findMessage(context, sourceText, "").translation() |
472 | .isNull() ) { | 482 | .isNull() ) { |
473 | tor.insert( m.key() ); | 483 | tor.insert( m.key() ); |
474 | } else { | 484 | } else { |
475 | tor.insert( QTranslatorMessage(context, sourceText, "", | 485 | tor.insert( QTranslatorMessage(context, sourceText, "", |
476 | translation) ); | 486 | translation) ); |
477 | } | 487 | } |
478 | } | 488 | } |
479 | } | 489 | } |
480 | } | 490 | } |
481 | 491 | ||
482 | bool saved = tor.save( filename, QTranslator::Stripped ); | 492 | bool saved = tor.save( filename, mode ); |
483 | if ( saved && verbose ) | 493 | if ( saved && verbose ) |
484 | fprintf( stderr, | 494 | fprintf( stderr, |
485 | " %d finished, %d unfinished and %d untranslated messages\n", | 495 | " %d finished, %d unfinished and %d untranslated messages\n", |
486 | finished, unfinished, untranslated ); | 496 | finished, unfinished, untranslated ); |
487 | 497 | ||
488 | return saved; | 498 | return saved; |
489 | } | 499 | } |
490 | 500 | ||
491 | bool MetaTranslator::contains( const char *context, const char *sourceText, | 501 | bool MetaTranslator::contains( const char *context, const char *sourceText, |
492 | const char *comment ) const | 502 | const char *comment ) const |
493 | { | 503 | { |
494 | return mm.find( MetaTranslatorMessage(context, sourceText, comment) ) != | 504 | return mm.find( MetaTranslatorMessage(context, sourceText, comment) ) != |
495 | mm.end(); | 505 | mm.end(); |
496 | } | 506 | } |
497 | 507 | ||
498 | void MetaTranslator::insert( const MetaTranslatorMessage& m ) | 508 | void MetaTranslator::insert( const MetaTranslatorMessage& m ) |
499 | { | 509 | { |
500 | int pos = mm.count(); | 510 | int pos = mm.count(); |
501 | TMM::Iterator n = mm.find( m ); | 511 | TMM::Iterator n = mm.find( m ); |
502 | if ( n != mm.end() ) | 512 | if ( n != mm.end() ) |
503 | pos = *n; | 513 | pos = *n; |
504 | mm.replace( m, pos ); | 514 | mm.replace( m, pos ); |
505 | } | 515 | } |
506 | 516 | ||
507 | void MetaTranslator::stripObsoleteMessages() | 517 | void MetaTranslator::stripObsoleteMessages() |
508 | { | 518 | { |
509 | TMM newmm; | 519 | TMM newmm; |
510 | 520 | ||
511 | TMM::Iterator m = mm.begin(); | 521 | TMM::Iterator m = mm.begin(); |
512 | while ( m != mm.end() ) { | 522 | while ( m != mm.end() ) { |
513 | if ( m.key().type() != MetaTranslatorMessage::Obsolete ) | 523 | if ( m.key().type() != MetaTranslatorMessage::Obsolete ) |
514 | newmm.insert( m.key(), *m ); | 524 | newmm.insert( m.key(), *m ); |
515 | ++m; | 525 | ++m; |
516 | } | 526 | } |
517 | mm = newmm; | 527 | mm = newmm; |
518 | } | 528 | } |
519 | 529 | ||
520 | void MetaTranslator::stripEmptyContexts() | 530 | void MetaTranslator::stripEmptyContexts() |
521 | { | 531 | { |
522 | TMM newmm; | 532 | TMM newmm; |
523 | 533 | ||
524 | TMM::Iterator m = mm.begin(); | 534 | TMM::Iterator m = mm.begin(); |
525 | while ( m != mm.end() ) { | 535 | while ( m != mm.end() ) { |
526 | if ( QCString(m.key().sourceText()).isEmpty() ) { | 536 | if ( QCString(m.key().sourceText()) == ContextComment ) { |
527 | TMM::Iterator n = m; | 537 | TMM::Iterator n = m; |
528 | ++n; | 538 | ++n; |
529 | // the context comment is followed by other messages | 539 | // the context comment is followed by other messages |
530 | if ( n != newmm.end() && | 540 | if ( n != newmm.end() && |
531 | qstrcmp(m.key().context(), n.key().context()) == 0 ) | 541 | qstrcmp(m.key().context(), n.key().context()) == 0 ) |
532 | newmm.insert( m.key(), *m ); | 542 | newmm.insert( m.key(), *m ); |
533 | } else { | 543 | } else { |
534 | newmm.insert( m.key(), *m ); | 544 | newmm.insert( m.key(), *m ); |
535 | } | 545 | } |
536 | ++m; | 546 | ++m; |
537 | } | 547 | } |
538 | mm = newmm; | 548 | mm = newmm; |
539 | } | 549 | } |
540 | 550 | ||
541 | void MetaTranslator::setCodec( const char *name ) | 551 | void MetaTranslator::setCodec( const char *name ) |
542 | { | 552 | { |
543 | const int latin1 = 4; | 553 | const int latin1 = 4; |
544 | 554 | ||
545 | codecName = name; | 555 | codecName = name; |
546 | codec = QTextCodec::codecForName( name ); | 556 | codec = QTextCodec::codecForName( name ); |
547 | if ( codec == 0 || codec->mibEnum() == latin1 ) | 557 | if ( codec == 0 || codec->mibEnum() == latin1 ) |
548 | codec = 0; | 558 | codec = 0; |
549 | } | 559 | } |
550 | 560 | ||
551 | QString MetaTranslator::toUnicode( const char *str, bool utf8 ) const | 561 | QString MetaTranslator::toUnicode( const char *str, bool utf8 ) const |
552 | { | 562 | { |
553 | if ( utf8 ) | 563 | if ( utf8 ) |
554 | return QString::fromUtf8( str ); | 564 | return QString::fromUtf8( str ); |
555 | else if ( codec == 0 ) | 565 | else if ( codec == 0 ) |
556 | return QString( str ); | 566 | return QString( str ); |
557 | else | 567 | else |
558 | return codec->toUnicode( str ); | 568 | return codec->toUnicode( str ); |
559 | } | 569 | } |
560 | 570 | ||
561 | QValueList<MetaTranslatorMessage> MetaTranslator::messages() const | 571 | QValueList<MetaTranslatorMessage> MetaTranslator::messages() const |
562 | { | 572 | { |
563 | int n = mm.count(); | 573 | int n = mm.count(); |
564 | TMM::ConstIterator *t = new TMM::ConstIterator[n + 1]; | 574 | TMM::ConstIterator *t = new TMM::ConstIterator[n + 1]; |
565 | TMM::ConstIterator m; | 575 | TMM::ConstIterator m; |
566 | for ( m = mm.begin(); m != mm.end(); ++m ) | 576 | for ( m = mm.begin(); m != mm.end(); ++m ) |
567 | t[*m] = m; | 577 | t[*m] = m; |
568 | 578 | ||
569 | QValueList<MetaTranslatorMessage> val; | 579 | QValueList<MetaTranslatorMessage> val; |
570 | for ( int i = 0; i < n; i++ ) | 580 | for ( int i = 0; i < n; i++ ) |
571 | val.append( t[i].key() ); | 581 | val.append( t[i].key() ); |
572 | 582 | ||
573 | delete[] t; | 583 | delete[] t; |
574 | return val; | 584 | return val; |
575 | } | 585 | } |
576 | 586 | ||
577 | QValueList<MetaTranslatorMessage> MetaTranslator::translatedMessages() const | 587 | QValueList<MetaTranslatorMessage> MetaTranslator::translatedMessages() const |
578 | { | 588 | { |
579 | QValueList<MetaTranslatorMessage> val; | 589 | QValueList<MetaTranslatorMessage> val; |
580 | TMM::ConstIterator m; | 590 | TMM::ConstIterator m; |
581 | for ( m = mm.begin(); m != mm.end(); ++m ) { | 591 | for ( m = mm.begin(); m != mm.end(); ++m ) { |
582 | if ( m.key().type() == MetaTranslatorMessage::Finished ) | 592 | if ( m.key().type() == MetaTranslatorMessage::Finished ) |
583 | val.append( m.key() ); | 593 | val.append( m.key() ); |
584 | } | 594 | } |
585 | return val; | 595 | return val; |
586 | } | 596 | } |
diff --git a/development/translation/shared/metatranslator.h b/development/translation/shared/metatranslator.h index d35b202..a13f462 100644 --- a/development/translation/shared/metatranslator.h +++ b/development/translation/shared/metatranslator.h | |||
@@ -1,99 +1,113 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #ifndef METATRANSLATOR_H | 27 | #ifndef METATRANSLATOR_H |
22 | #define METATRANSLATOR_H | 28 | #define METATRANSLATOR_H |
23 | 29 | ||
24 | #include <qmap.h> | 30 | #include <qmap.h> |
25 | #include <qstring.h> | 31 | #include <qstring.h> |
26 | #include <qtranslator.h> | 32 | #include <qtranslator.h> |
27 | #include <qvaluelist.h> | 33 | #include <qvaluelist.h> |
28 | 34 | ||
29 | class QTextCodec; | 35 | class QTextCodec; |
30 | 36 | ||
31 | class MetaTranslatorMessage : public QTranslatorMessage | 37 | class MetaTranslatorMessage : public QTranslatorMessage |
32 | { | 38 | { |
33 | public: | 39 | public: |
34 | enum Type { Unfinished, Finished, Obsolete }; | 40 | enum Type { Unfinished, Finished, Obsolete }; |
35 | 41 | ||
36 | MetaTranslatorMessage(); | 42 | MetaTranslatorMessage(); |
37 | MetaTranslatorMessage( const char *context, const char *sourceText, | 43 | MetaTranslatorMessage( const char *context, const char *sourceText, |
38 | const char *comment, | 44 | const char *comment, |
39 | const QString& translation = QString::null, | 45 | const QString& translation = QString::null, |
40 | bool utf8 = FALSE, Type type = Unfinished ); | 46 | bool utf8 = FALSE, Type type = Unfinished ); |
41 | MetaTranslatorMessage( const MetaTranslatorMessage& m ); | 47 | MetaTranslatorMessage( const MetaTranslatorMessage& m ); |
42 | 48 | ||
43 | MetaTranslatorMessage& operator=( const MetaTranslatorMessage& m ); | 49 | MetaTranslatorMessage& operator=( const MetaTranslatorMessage& m ); |
44 | 50 | ||
45 | void setType( Type nt ) { ty = nt; } | 51 | void setType( Type nt ) { ty = nt; } |
46 | Type type() const { return ty; } | 52 | Type type() const { return ty; } |
47 | bool utf8() const { return utfeight; } | 53 | bool utf8() const { return utfeight; } |
48 | 54 | ||
49 | bool operator==( const MetaTranslatorMessage& m ) const; | 55 | bool operator==( const MetaTranslatorMessage& m ) const; |
50 | bool operator!=( const MetaTranslatorMessage& m ) const | 56 | bool operator!=( const MetaTranslatorMessage& m ) const |
51 | { return !operator==( m ); } | 57 | { return !operator==( m ); } |
52 | bool operator<( const MetaTranslatorMessage& m ) const; | 58 | bool operator<( const MetaTranslatorMessage& m ) const; |
53 | bool operator<=( const MetaTranslatorMessage& m ) | 59 | bool operator<=( const MetaTranslatorMessage& m ) |
54 | { return !operator>( m ); } | 60 | { return !operator>( m ); } |
55 | bool operator>( const MetaTranslatorMessage& m ) const | 61 | bool operator>( const MetaTranslatorMessage& m ) const |
56 | { return this->operator<( m ); } | 62 | { return this->operator<( m ); } |
57 | bool operator>=( const MetaTranslatorMessage& m ) const | 63 | bool operator>=( const MetaTranslatorMessage& m ) const |
58 | { return !operator<( m ); } | 64 | { return !operator<( m ); } |
59 | 65 | ||
60 | private: | 66 | private: |
61 | bool utfeight; | 67 | bool utfeight; |
62 | Type ty; | 68 | Type ty; |
63 | }; | 69 | }; |
64 | 70 | ||
65 | class MetaTranslator | 71 | class MetaTranslator |
66 | { | 72 | { |
67 | public: | 73 | public: |
68 | MetaTranslator(); | 74 | MetaTranslator(); |
69 | MetaTranslator( const MetaTranslator& tor ); | 75 | MetaTranslator( const MetaTranslator& tor ); |
70 | 76 | ||
71 | MetaTranslator& operator=( const MetaTranslator& tor ); | 77 | MetaTranslator& operator=( const MetaTranslator& tor ); |
72 | 78 | ||
79 | void clear(); | ||
73 | bool load( const QString& filename ); | 80 | bool load( const QString& filename ); |
74 | bool save( const QString& filename ) const; | 81 | bool save( const QString& filename ) const; |
75 | bool release( const QString& filename, bool verbose = FALSE ) const; | 82 | bool release( const QString& filename, bool verbose = FALSE, |
83 | QTranslator::SaveMode mode = QTranslator::Stripped ) const; | ||
76 | 84 | ||
77 | bool contains( const char *context, const char *sourceText, | 85 | bool contains( const char *context, const char *sourceText, |
78 | const char *comment ) const; | 86 | const char *comment ) const; |
79 | void insert( const MetaTranslatorMessage& m ); | 87 | void insert( const MetaTranslatorMessage& m ); |
80 | 88 | ||
81 | void stripObsoleteMessages(); | 89 | void stripObsoleteMessages(); |
82 | void stripEmptyContexts(); | 90 | void stripEmptyContexts(); |
83 | 91 | ||
84 | void setCodec( const char *name ); | 92 | void setCodec( const char *name ); |
85 | QString toUnicode( const char *str, bool utf8 ) const; | 93 | QString toUnicode( const char *str, bool utf8 ) const; |
86 | 94 | ||
87 | QValueList<MetaTranslatorMessage> messages() const; | 95 | QValueList<MetaTranslatorMessage> messages() const; |
88 | QValueList<MetaTranslatorMessage> translatedMessages() const; | 96 | QValueList<MetaTranslatorMessage> translatedMessages() const; |
89 | 97 | ||
90 | private: | 98 | private: |
91 | typedef QMap<MetaTranslatorMessage, int> TMM; | 99 | typedef QMap<MetaTranslatorMessage, int> TMM; |
92 | typedef QMap<int, MetaTranslatorMessage> TMMInv; | 100 | typedef QMap<int, MetaTranslatorMessage> TMMInv; |
93 | 101 | ||
94 | TMM mm; | 102 | TMM mm; |
95 | QCString codecName; | 103 | QCString codecName; |
96 | QTextCodec *codec; | 104 | QTextCodec *codec; |
97 | }; | 105 | }; |
98 | 106 | ||
107 | /* | ||
108 | This is a quick hack. The proper way to handle this would be | ||
109 | to extend MetaTranslator's interface. | ||
110 | */ | ||
111 | #define ContextComment "QT_LINGUIST_INTERNAL_CONTEXT_COMMENT" | ||
112 | |||
99 | #endif | 113 | #endif |
diff --git a/development/translation/shared/opie.h b/development/translation/shared/opie.h index 4646bb0..28b2a61 100644 --- a/development/translation/shared/opie.h +++ b/development/translation/shared/opie.h | |||
@@ -1,21 +1,21 @@ | |||
1 | #ifndef OPIE_H | 1 | #ifndef OPIE_H |
2 | #define OPIE_H | 2 | #define OPIE_H |
3 | 3 | ||
4 | #include <qstring.h> | 4 | #include <qstring.h> |
5 | #include <qstringlist.h> | 5 | #include <qstringlist.h> |
6 | 6 | ||
7 | class OPIE { | 7 | class OPIE { |
8 | public: | 8 | public: |
9 | static OPIE* self(); | 9 | static OPIE* self(); |
10 | /** get the list of languages */ | 10 | /** get the list of languages */ |
11 | QStringList languageList(const QString& opiedir = QString::null)const; | 11 | QStringList languageList(const QString& opiedir = QString::null)const; |
12 | QString opieDir(const QString& opieDir)const; | 12 | QString opieDir(const QString& opieDir = QString::null)const; |
13 | 13 | ||
14 | private: | 14 | private: |
15 | OPIE(); | 15 | OPIE(); |
16 | ~OPIE(); | 16 | ~OPIE(); |
17 | static OPIE* m_self; | 17 | static OPIE* m_self; |
18 | 18 | ||
19 | }; | 19 | }; |
20 | 20 | ||
21 | #endif | 21 | #endif |
diff --git a/development/translation/shared/proparser.cpp b/development/translation/shared/proparser.cpp index 21d2f86..f616c5a 100644 --- a/development/translation/shared/proparser.cpp +++ b/development/translation/shared/proparser.cpp | |||
@@ -1,87 +1,174 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #include "proparser.h" | 27 | #include "proparser.h" |
22 | 28 | ||
29 | #include <qfile.h> | ||
23 | #include <qregexp.h> | 30 | #include <qregexp.h> |
24 | #include <qstringlist.h> | 31 | #include <qstringlist.h> |
32 | #include <qtextstream.h> | ||
33 | |||
34 | #ifdef Q_OS_UNIX | ||
35 | #include <unistd.h> | ||
36 | #endif | ||
37 | |||
38 | #ifdef Q_OS_WIN32 | ||
39 | #define QT_POPEN _popen | ||
40 | #else | ||
41 | #define QT_POPEN popen | ||
42 | #endif | ||
43 | |||
44 | QString loadFile( const QString &fileName ) | ||
45 | { | ||
46 | QFile file( fileName ); | ||
47 | if ( !file.open(IO_ReadOnly) ) { | ||
48 | fprintf( stderr, "error: Cannot load '%s': %s\n", | ||
49 | file.name().latin1(), | ||
50 | file.errorString().latin1() ); | ||
51 | return QString(); | ||
52 | } | ||
53 | |||
54 | QTextStream in( &file ); | ||
55 | return in.read(); | ||
56 | } | ||
25 | 57 | ||
26 | QMap<QString, QString> proFileTagMap( const QString& text ) | 58 | QMap<QString, QString> proFileTagMap( const QString& text, const QString& opieDir ) |
27 | { | 59 | { |
28 | QString t = text; | 60 | QString t = text; |
29 | 61 | ||
30 | /* | 62 | /* |
63 | Process include() commands. | ||
64 | */ | ||
65 | QRegExp callToInclude("include\\s*\\(\\s*([^()\\s]+)\\s*\\)"); | ||
66 | int i = 0; | ||
67 | while ( (i = callToInclude.search(t, i)) != -1 ) { | ||
68 | QString after = loadFile( callToInclude.cap(1) ); | ||
69 | t.replace( i, callToInclude.matchedLength(), after ); | ||
70 | i += after.length(); | ||
71 | } | ||
72 | |||
73 | /* | ||
31 | Strip comments, merge lines ending with backslash, add | 74 | Strip comments, merge lines ending with backslash, add |
32 | spaces around '=' and '+=', replace '\n' with ';', and | 75 | spaces around '=' and '+=', replace '\n' with ';', and |
33 | simplify white spaces. | 76 | simplify white spaces. |
34 | */ | 77 | */ |
35 | t.replace( QRegExp(QString("#[^\n]$")), QString(" ") ); | 78 | t.replace( QRegExp(QString("#[^\n]*\n")), QString(" ") ); |
36 | t.replace( QRegExp(QString("\\\\\\s*\n")), QString(" ") ); | 79 | t.replace( QRegExp(QString("\\\\[^\n\\S]*\n")), QString(" ") ); |
37 | t.replace( "=", QString(" = ") ); | 80 | t.replace( "=", QString(" = ") ); |
38 | t.replace( "+ =", QString(" += ") ); | 81 | t.replace( "+ =", QString(" += ") ); |
39 | t.replace( "\n", QString(";") ); | 82 | t.replace( "\n", QString(";") ); |
40 | t = t.simplifyWhiteSpace(); | 83 | t = t.simplifyWhiteSpace(); |
41 | 84 | ||
85 | /* | ||
86 | Populate tagMap with 'key = value' entries. | ||
87 | */ | ||
42 | QMap<QString, QString> tagMap; | 88 | QMap<QString, QString> tagMap; |
43 | |||
44 | QStringList lines = QStringList::split( QChar(';'), t ); | 89 | QStringList lines = QStringList::split( QChar(';'), t ); |
45 | QStringList::Iterator line; | 90 | QStringList::Iterator line; |
46 | for ( line = lines.begin(); line != lines.end(); ++line ) { | 91 | for ( line = lines.begin(); line != lines.end(); ++line ) { |
47 | QStringList toks = QStringList::split( QChar(' '), *line ); | 92 | QStringList toks = QStringList::split( QChar(' '), *line ); |
48 | 93 | ||
49 | if ( toks.count() >= 3 && | 94 | if ( toks.count() >= 3 && |
50 | (toks[1] == QString("=") || toks[1] == QString("+=")) ) { | 95 | (toks[1] == QString("=") || toks[1] == QString("+=")) ) { |
51 | QString tag = toks.first(); | 96 | QString tag = toks.first(); |
52 | int k = tag.findRev( QChar(':') ); // as in 'unix:' | 97 | int k = tag.findRev( QChar(':') ); // as in 'unix:' |
53 | if ( k != -1 ) | 98 | if ( k != -1 ) |
54 | tag = tag.mid( k + 1 ); | 99 | tag = tag.mid( k + 1 ); |
55 | toks.remove( toks.begin() ); | 100 | toks.remove( toks.begin() ); |
56 | 101 | ||
57 | QString action = toks.first(); | 102 | QString action = toks.first(); |
58 | toks.remove( toks.begin() ); | 103 | toks.remove( toks.begin() ); |
59 | 104 | ||
60 | if ( tagMap.contains(tag) ) { | 105 | if ( tagMap.contains(tag) ) { |
61 | if ( action == QString("=") ) | 106 | if ( action == QString("=") ) |
62 | tagMap.replace( tag, toks.join(QChar(' ')) ); | 107 | tagMap.replace( tag, toks.join(QChar(' ')) ); |
63 | else | 108 | else |
64 | tagMap[tag] += QChar( ' ' ) + toks.join( QChar(' ') ); | 109 | tagMap[tag] += QChar( ' ' ) + toks.join( QChar(' ') ); |
65 | } else { | 110 | } else { |
66 | tagMap[tag] = toks.join( QChar(' ') ); | 111 | tagMap[tag] = toks.join( QChar(' ') ); |
67 | } | 112 | } |
68 | } | 113 | } |
69 | } | 114 | } |
70 | 115 | ||
71 | QRegExp var( "\\$\\$[a-zA-Z0-9_]+" ); | 116 | /* |
117 | Expand $$variables within the 'value' part of a 'key = value' | ||
118 | pair. | ||
119 | */ | ||
120 | QRegExp var( "\\$\\$[({]?([a-zA-Z0-9_]+)[)}]?" ); | ||
72 | QMap<QString, QString>::Iterator it; | 121 | QMap<QString, QString>::Iterator it; |
73 | for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { | 122 | for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { |
74 | int i = 0; | 123 | int i = 0; |
75 | 124 | while ( (i = var.search((*it), i)) != -1 ) { | |
76 | while ( (i = var.search(it.data(), i)) != -1 ) { | ||
77 | int len = var.matchedLength(); | 125 | int len = var.matchedLength(); |
78 | QString invocation = (*it).mid( i + 2, len - 2 ); | 126 | QString invocation = var.cap(1); |
79 | QString after; | 127 | QString after; |
80 | if ( tagMap.contains(invocation) ) | 128 | |
81 | after = tagMap[invocation]; | 129 | if ( invocation == "system" ) { |
82 | (*it).replace( i, len, after ); | 130 | // skip system(); it will be handled in the next pass |
131 | ++i; | ||
132 | } else if ( invocation == "OPIEDIR") { | ||
133 | (*it).replace( i, len, opieDir ); | ||
134 | }else { | ||
135 | if ( tagMap.contains(invocation) ) | ||
136 | after = tagMap[invocation]; | ||
137 | (*it).replace( i, len, after ); | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | Execute system() calls. | ||
144 | */ | ||
145 | QRegExp callToSystem( "\\$\\$system\\s*\\(([^()]*)\\)" ); | ||
146 | for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { | ||
147 | int i = 0; | ||
148 | while ( (i = callToSystem.search((*it), i)) != -1 ) { | ||
149 | /* | ||
150 | This code is stolen from qmake's project.cpp file. | ||
151 | Ideally we would use the same parser, so we wouldn't | ||
152 | have this code duplication. | ||
153 | */ | ||
154 | QString after; | ||
155 | char buff[256]; | ||
156 | FILE *proc = QT_POPEN( callToSystem.cap(1).latin1(), "r" ); | ||
157 | while ( proc && !feof(proc) ) { | ||
158 | int read_in = fread( buff, 1, 255, proc ); | ||
159 | if ( !read_in ) | ||
160 | break; | ||
161 | for ( int i = 0; i < read_in; i++ ) { | ||
162 | if ( buff[i] == '\n' || buff[i] == '\t' ) | ||
163 | buff[i] = ' '; | ||
164 | } | ||
165 | buff[read_in] = '\0'; | ||
166 | after += buff; | ||
167 | } | ||
168 | (*it).replace( i, callToSystem.matchedLength(), after ); | ||
83 | i += after.length(); | 169 | i += after.length(); |
84 | } | 170 | } |
85 | } | 171 | } |
172 | |||
86 | return tagMap; | 173 | return tagMap; |
87 | } | 174 | } |
diff --git a/development/translation/shared/proparser.h b/development/translation/shared/proparser.h index 6a61d90..e5678d6 100644 --- a/development/translation/shared/proparser.h +++ b/development/translation/shared/proparser.h | |||
@@ -1,29 +1,35 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | 2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Qt Linguist. | 4 | ** This file is part of Qt Linguist. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
12 | ** licenses may use this file in accordance with the Qt Commercial License | ||
13 | ** Agreement provided with the Software. | ||
14 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 15 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 16 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 17 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 18 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
19 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
20 | ** information about Qt Commercial License Agreements. | ||
15 | ** | 21 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 22 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 23 | ** not clear to you. |
18 | ** | 24 | ** |
19 | **********************************************************************/ | 25 | **********************************************************************/ |
20 | 26 | ||
21 | #ifndef PROPARSER_H | 27 | #ifndef PROPARSER_H |
22 | #define PROPARSER_H | 28 | #define PROPARSER_H |
23 | 29 | ||
24 | #include <qmap.h> | 30 | #include <qmap.h> |
25 | #include <qstring.h> | 31 | #include <qstring.h> |
26 | 32 | ||
27 | QMap<QString, QString> proFileTagMap( const QString& text ); | 33 | QMap<QString, QString> proFileTagMap( const QString& text, const QString& = QString::null ); |
28 | 34 | ||
29 | #endif | 35 | #endif |