summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--development/translation/opie-lupdate/fetchtr.cpp55
-rw-r--r--development/translation/opie-lupdate/main.cpp11
-rw-r--r--development/translation/opie-lupdate/merge.cpp6
-rw-r--r--development/translation/opie-lupdate/numberh.cpp28
-rw-r--r--development/translation/opie-lupdate/sametexth.cpp6
-rw-r--r--development/translation/shared/metatranslator.cpp34
-rw-r--r--development/translation/shared/metatranslator.h16
-rw-r--r--development/translation/shared/opie.h2
-rw-r--r--development/translation/shared/proparser.cpp111
-rw-r--r--development/translation/shared/proparser.h8
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,46 +1,52 @@
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
37static const char MagicComment[] = "TRANSLATOR "; 43static const char MagicComment[] = "TRANSLATOR ";
38 44
39static QMap<QCString, int> needs_Q_OBJECT; 45static QMap<QCString, int> needs_Q_OBJECT;
40static QMap<QCString, int> lacks_Q_OBJECT; 46static 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
@@ -51,218 +57,239 @@ static QMap<QCString, int> lacks_Q_OBJECT;
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
64enum { Tok_Eof, Tok_class, Tok_namespace, Tok_return, Tok_tr, 70enum { 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*/
74static QCString yyFileName; 80static QCString yyFileName;
75static int yyCh; 81static int yyCh;
76static char yyIdent[128]; 82static char yyIdent[128];
77static size_t yyIdentLen; 83static size_t yyIdentLen;
78static char yyComment[65536]; 84static char yyComment[65536];
79static size_t yyCommentLen; 85static size_t yyCommentLen;
80static char yyString[16384]; 86static char yyString[16384];
81static size_t yyStringLen; 87static size_t yyStringLen;
82static QValueStack<int> yySavedBraceDepth; 88static QValueStack<int> yySavedBraceDepth;
89static QValueStack<int> yySavedParenDepth;
83static int yyBraceDepth; 90static int yyBraceDepth;
84static int yyParenDepth; 91static int yyParenDepth;
85static int yyLineNo; 92static int yyLineNo;
86static int yyCurLineNo; 93static int yyCurLineNo;
94static int yyBraceLineNo;
95static 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)
89static FILE *yyInFile; 98static 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)
92static QString yyInStr; 101static QString yyInStr;
93static int yyInPos; 102static int yyInPos;
94 103
95static int (*getChar)(); 104static int (*getChar)();
96 105
97static int getCharFromFile() 106static 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
105static int getCharFromString() 114static 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
114static void startTokenizer( const char *fileName, int (*getCharFunc)() ) 123static 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
127static int getToken() 139static 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;
@@ -327,76 +354,84 @@ static int getToken()
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
398static int yyTok; 433static int yyTok;
399 434
400static bool match( int t ) 435static bool match( int t )
401{ 436{
402 bool matches = ( yyTok == t ); 437 bool matches = ( yyTok == t );
@@ -592,72 +627,72 @@ static void parse( MetaTranslator *tor, const char *initialContext,
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
634void fetchtr_cpp( const char *fileName, MetaTranslator *tor, 669void 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*/
659void fetchtr_inlined_cpp( const char *fileName, const QString& in, 694void 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 );
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
@@ -33,64 +33,73 @@
33#include <string.h> 33#include <string.h>
34 34
35// defined in fetchtr.cpp 35// defined in fetchtr.cpp
36extern void fetchtr_cpp( const char *fileName, MetaTranslator *tor, 36extern void fetchtr_cpp( const char *fileName, MetaTranslator *tor,
37 const char *defaultContext, bool mustExist ); 37 const char *defaultContext, bool mustExist );
38extern void fetchtr_ui( const char *fileName, MetaTranslator *tor, 38extern 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
42extern void merge( MetaTranslator *tor, const MetaTranslator *virginTor, 42extern void merge( MetaTranslator *tor, const MetaTranslator *virginTor,
43 bool verbose ); 43 bool verbose );
44 44
45typedef QValueList<MetaTranslatorMessage> TML; 45typedef QValueList<MetaTranslatorMessage> TML;
46 46
47static const char* LUPDATE_VERSION = "0.1"; 47static const char* LUPDATE_VERSION = "0.1";
48 48
49static void printUsage() 49static 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
65static void updateTsFiles( const MetaTranslator& fetchedTor, 74static 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
91int main( int argc, char **argv ) 100int 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;
@@ -121,65 +130,65 @@ int main( int argc, char **argv )
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 /**
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,46 +1,52 @@
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
24extern void applyNumberHeuristic( MetaTranslator *tor, bool verbose ); 30extern void applyNumberHeuristic( MetaTranslator *tor, bool verbose );
25// defined in sametexth.cpp 31// defined in sametexth.cpp
26extern void applySameTextHeuristic( MetaTranslator *tor, bool verbose ); 32extern void applySameTextHeuristic( MetaTranslator *tor, bool verbose );
27 33
28typedef QValueList<MetaTranslatorMessage> TML; 34typedef 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
38void merge( MetaTranslator *tor, const MetaTranslator *virginTor, bool verbose ) 44void 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 /*
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,80 +1,86 @@
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
30typedef QMap<QCString, MetaTranslatorMessage> TMM; 36typedef QMap<QCString, MetaTranslatorMessage> TMM;
31typedef QValueList<MetaTranslatorMessage> TML; 37typedef QValueList<MetaTranslatorMessage> TML;
32 38
33static bool isDigitFriendly( int c ) 39static bool isDigitFriendly( int c )
34{ 40{
35 return ispunct( c ) || isspace( c ); 41 return ispunct((uchar)c) || isspace((uchar)c);
36} 42}
37 43
38static int numberLength( const char *s ) 44static 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*/
57static QCString zeroKey( const char *key ) 63static 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 "";
@@ -182,54 +188,54 @@ static QString translationAttempt( const QString& oldTranslation,
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*/
203void applyNumberHeuristic( MetaTranslator *tor, bool verbose ) 209void 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,46 +1,52 @@
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
26typedef QMap<QCString, MetaTranslatorMessage> TMM; 32typedef QMap<QCString, MetaTranslatorMessage> TMM;
27typedef QValueList<MetaTranslatorMessage> TML; 33typedef 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
37void applySameTextHeuristic( MetaTranslator *tor, bool verbose ) 43void 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;
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,46 +1,52 @@
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
31static bool encodingIsUtf8( const QXmlAttributes& atts ) 37static 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
44class TsHandler : public QXmlDefaultHandler 50class TsHandler : public QXmlDefaultHandler
45{ 51{
46public: 52public:
@@ -109,69 +115,71 @@ bool TsHandler::startElement( const QString& /* namespaceURI */,
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
125bool TsHandler::endElement( const QString& /* namespaceURI */, 131bool 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
165bool TsHandler::characters( const QString& ch ) 173bool 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
173bool TsHandler::fatalError( const QXmlParseException& exception ) 181bool 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).",
@@ -286,273 +294,275 @@ MetaTranslatorMessage::MetaTranslatorMessage( const char *context,
286MetaTranslatorMessage::MetaTranslatorMessage( const MetaTranslatorMessage& m ) 294MetaTranslatorMessage::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
291MetaTranslatorMessage& MetaTranslatorMessage::operator=( 299MetaTranslatorMessage& 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
300bool MetaTranslatorMessage::operator==( const MetaTranslatorMessage& m ) const 308bool 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
307bool MetaTranslatorMessage::operator<( const MetaTranslatorMessage& m ) const 315bool 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
317MetaTranslator::MetaTranslator() 325MetaTranslator::MetaTranslator()
318 : codecName( "ISO-8859-1" ), codec( 0 )
319{ 326{
327 clear();
320} 328}
321 329
322MetaTranslator::MetaTranslator( const MetaTranslator& tor ) 330MetaTranslator::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
328MetaTranslator& MetaTranslator::operator=( const MetaTranslator& tor ) 335MetaTranslator& 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
336bool MetaTranslator::load( const QString& filename ) 343void MetaTranslator::clear()
337{ 344{
338 mm.clear(); 345 mm.clear();
346 codecName = "ISO-8859-1";
347 codec = 0;
348}
339 349
350bool 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
366bool MetaTranslator::save( const QString& filename ) const 375bool 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
440bool MetaTranslator::release( const QString& filename, bool verbose ) const 449bool 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
491bool MetaTranslator::contains( const char *context, const char *sourceText, 501bool 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
498void MetaTranslator::insert( const MetaTranslatorMessage& m ) 508void 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
507void MetaTranslator::stripObsoleteMessages() 517void 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
520void MetaTranslator::stripEmptyContexts() 530void 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
541void MetaTranslator::setCodec( const char *name ) 551void 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
551QString MetaTranslator::toUnicode( const char *str, bool utf8 ) const 561QString 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 );
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
29class QTextCodec; 35class QTextCodec;
30 36
31class MetaTranslatorMessage : public QTranslatorMessage 37class MetaTranslatorMessage : public QTranslatorMessage
32{ 38{
33public: 39public:
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
60private: 66private:
61 bool utfeight; 67 bool utfeight;
62 Type ty; 68 Type ty;
63}; 69};
64 70
65class MetaTranslator 71class MetaTranslator
66{ 72{
67public: 73public:
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
90private: 98private:
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
7class OPIE { 7class OPIE {
8public: 8public:
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
14private: 14private:
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
44QString 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
26QMap<QString, QString> proFileTagMap( const QString& text ) 58QMap<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
27QMap<QString, QString> proFileTagMap( const QString& text ); 33QMap<QString, QString> proFileTagMap( const QString& text, const QString& = QString::null );
28 34
29#endif 35#endif