riched20: Initialize ed->reOle in ME_MakeEditor().
[wine/multimedia.git] / tools / wrc / translation.c
blob00ad268b87ed5903e7a95f0f2daa372f4966c403
1 /*
2 * Copyright 2003 Vincent BĂ©ron
3 * Copyright 2007, 2008 Mikolaj Zalewski
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <assert.h>
24 #include "dumpres.h"
25 #include "utils.h"
26 #include "wrc.h"
28 #define MASTER_LANGUAGE LANG_ENGLISH
29 #define MASTER_SUBLANGUAGE SUBLANG_ENGLISH_US
30 #define NB_LANG 0x94
32 enum lang_type_e {
33 lang_type_master = 0,
34 lang_type_neutral,
35 lang_type_normal
38 static language_t get_language(resource_t *resource) {
39 switch(resource->type) {
40 case res_acc:
41 return *resource->res.acc->lvc.language;
42 case res_bmp:
43 return *resource->res.bmp->data->lvc.language;
44 case res_cur:
45 return *resource->res.cur->lvc.language;
46 case res_curg:
47 return *resource->res.curg->lvc.language;
48 case res_dlg:
49 return *resource->res.dlg->lvc.language;
50 case res_fnt:
51 return *resource->res.fnt->data->lvc.language;
52 case res_fntdir:
53 return *resource->res.fnd->data->lvc.language;
54 case res_ico:
55 return *resource->res.ico->lvc.language;
56 case res_icog:
57 return *resource->res.icog->lvc.language;
58 case res_men:
59 return *resource->res.men->lvc.language;
60 case res_rdt:
61 return *resource->res.rdt->data->lvc.language;
62 case res_stt:
63 return *resource->res.stt->lvc.language;
64 case res_usr:
65 return *resource->res.usr->data->lvc.language;
66 case res_msg:
67 return *resource->res.msg->data->lvc.language;
68 case res_ver:
69 return *resource->res.ver->lvc.language;
70 case res_dlginit:
71 return *resource->res.dlgi->data->lvc.language;
72 case res_toolbar:
73 return *resource->res.tbt->lvc.language;
74 case res_anicur:
75 case res_aniico:
76 return *resource->res.ani->data->lvc.language;
77 case res_html:
78 return *resource->res.html->data->lvc.language;
79 default:
80 /* Not supposed to reach here */
81 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
82 abort();
86 static int get_language_id(resource_t *resource) {
87 return get_language(resource).id;
90 static int compare_lang(language_t lang1, language_t lang2)
92 return memcmp(&lang1, &lang2, sizeof(language_t));
95 #if 0
97 #define PRETTYPRINTLANG(langid) \
98 if(LANG_##langid == lid) { \
99 return #langid; \
102 static const char *get_language_name(int lid) {
103 PRETTYPRINTLANG(NEUTRAL)
104 PRETTYPRINTLANG(AFRIKAANS)
105 PRETTYPRINTLANG(ALBANIAN)
106 PRETTYPRINTLANG(ARABIC)
107 PRETTYPRINTLANG(ARMENIAN)
108 PRETTYPRINTLANG(ASSAMESE)
109 PRETTYPRINTLANG(AZERI)
110 PRETTYPRINTLANG(BASQUE)
111 PRETTYPRINTLANG(BELARUSIAN)
112 PRETTYPRINTLANG(BENGALI)
113 PRETTYPRINTLANG(BULGARIAN)
114 PRETTYPRINTLANG(CATALAN)
115 PRETTYPRINTLANG(CHINESE)
116 PRETTYPRINTLANG(CROATIAN)
117 PRETTYPRINTLANG(CZECH)
118 PRETTYPRINTLANG(DANISH)
119 PRETTYPRINTLANG(DIVEHI)
120 PRETTYPRINTLANG(DUTCH)
121 PRETTYPRINTLANG(ENGLISH)
122 PRETTYPRINTLANG(ESTONIAN)
123 PRETTYPRINTLANG(FAEROESE)
124 PRETTYPRINTLANG(FARSI)
125 PRETTYPRINTLANG(FINNISH)
126 PRETTYPRINTLANG(FRENCH)
127 PRETTYPRINTLANG(GALICIAN)
128 PRETTYPRINTLANG(GEORGIAN)
129 PRETTYPRINTLANG(GERMAN)
130 PRETTYPRINTLANG(GREEK)
131 PRETTYPRINTLANG(GUJARATI)
132 PRETTYPRINTLANG(HEBREW)
133 PRETTYPRINTLANG(HINDI)
134 PRETTYPRINTLANG(HUNGARIAN)
135 PRETTYPRINTLANG(ICELANDIC)
136 PRETTYPRINTLANG(INDONESIAN)
137 PRETTYPRINTLANG(IRISH)
138 PRETTYPRINTLANG(ITALIAN)
139 PRETTYPRINTLANG(JAPANESE)
140 PRETTYPRINTLANG(KANNADA)
141 PRETTYPRINTLANG(KASHMIRI)
142 PRETTYPRINTLANG(KAZAK)
143 PRETTYPRINTLANG(KONKANI)
144 PRETTYPRINTLANG(KOREAN)
145 PRETTYPRINTLANG(KYRGYZ)
146 PRETTYPRINTLANG(LATVIAN)
147 PRETTYPRINTLANG(LITHUANIAN)
148 PRETTYPRINTLANG(MACEDONIAN)
149 PRETTYPRINTLANG(MALAY)
150 PRETTYPRINTLANG(MALAYALAM)
151 PRETTYPRINTLANG(MANIPURI)
152 PRETTYPRINTLANG(MARATHI)
153 PRETTYPRINTLANG(MONGOLIAN)
154 PRETTYPRINTLANG(NEPALI)
155 PRETTYPRINTLANG(NORWEGIAN)
156 PRETTYPRINTLANG(ORIYA)
157 PRETTYPRINTLANG(POLISH)
158 PRETTYPRINTLANG(PORTUGUESE)
159 PRETTYPRINTLANG(PUNJABI)
160 PRETTYPRINTLANG(ROMANIAN)
161 PRETTYPRINTLANG(RUSSIAN)
162 PRETTYPRINTLANG(SANSKRIT)
163 PRETTYPRINTLANG(SERBIAN)
164 PRETTYPRINTLANG(SINDHI)
165 PRETTYPRINTLANG(SLOVAK)
166 PRETTYPRINTLANG(SLOVENIAN)
167 PRETTYPRINTLANG(SPANISH)
168 PRETTYPRINTLANG(SWAHILI)
169 PRETTYPRINTLANG(SWEDISH)
170 PRETTYPRINTLANG(SYRIAC)
171 PRETTYPRINTLANG(TAMIL)
172 PRETTYPRINTLANG(TATAR)
173 PRETTYPRINTLANG(TELUGU)
174 PRETTYPRINTLANG(THAI)
175 PRETTYPRINTLANG(TURKISH)
176 PRETTYPRINTLANG(UKRAINIAN)
177 PRETTYPRINTLANG(URDU)
178 PRETTYPRINTLANG(UZBEK)
179 PRETTYPRINTLANG(VIETNAMESE)
180 PRETTYPRINTLANG(SCOTTISH_GAELIC)
181 PRETTYPRINTLANG(MALTESE)
182 PRETTYPRINTLANG(MAORI)
183 PRETTYPRINTLANG(RHAETO_ROMANCE)
184 PRETTYPRINTLANG(SAAMI)
185 PRETTYPRINTLANG(SORBIAN)
186 PRETTYPRINTLANG(SUTU)
187 PRETTYPRINTLANG(TSONGA)
188 PRETTYPRINTLANG(TSWANA)
189 PRETTYPRINTLANG(VENDA)
190 PRETTYPRINTLANG(XHOSA)
191 PRETTYPRINTLANG(ZULU)
192 PRETTYPRINTLANG(ESPERANTO)
193 PRETTYPRINTLANG(WALON)
194 PRETTYPRINTLANG(CORNISH)
195 PRETTYPRINTLANG(WELSH)
196 PRETTYPRINTLANG(BRETON)
197 return "Unknown language";
199 #endif
201 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
202 int different = 0;
203 event_t *ev1 = NULL, *ev2 = NULL;
204 if(!different &&
205 ((accelerator1->memopt != accelerator2->memopt) ||
206 (accelerator1->lvc.version != accelerator2->lvc.version) ||
207 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
208 different = 1;
209 ev1 = accelerator1->events;
210 ev2 = accelerator2->events;
211 while(!different && ev1 && ev2) {
212 if(!different &&
213 ((ev1->id != ev2->id) ||
214 (ev1->flags != ev2->flags)))
215 different = 1;
216 ev1 = ev1->next;
217 ev2 = ev2->next;
219 if(!different &&
220 ((ev1 && !ev2) || (!ev1 && ev2)))
221 different = 1;
222 return different;
225 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
226 int different = 0;
227 if(!different &&
228 ((bitmap1->memopt != bitmap2->memopt) ||
229 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
230 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
231 different = 1;
232 return different;
235 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
236 int different = 0;
237 if(!different &&
238 ((cursor1->id != cursor2->id) ||
239 (cursor1->width != cursor2->width) ||
240 (cursor1->height != cursor2->height) ||
241 (cursor1->xhot != cursor2->xhot) ||
242 (cursor1->yhot != cursor2->yhot)))
243 different = 1;
244 if(!different &&
245 ((cursor1->lvc.version != cursor2->lvc.version) ||
246 (cursor1->lvc.characts != cursor2->lvc.characts)))
247 different = 1;
248 return different;
251 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
252 int different = 0;
253 cursor_t *cursor1 = NULL, *cursor2 = NULL;
254 if(!different &&
255 ((cursor_group1->memopt != cursor_group2->memopt) ||
256 (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
257 (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
258 different = 1;
259 if(!different &&
260 (cursor_group1->ncursor != cursor_group2->ncursor))
261 different = 1;
262 if(!different) {
263 cursor1 = cursor_group1->cursorlist;
264 cursor2 = cursor_group2->cursorlist;
265 while(!different && cursor1 && cursor2) {
266 different = compare_cursor(cursor1, cursor2);
267 cursor1 = cursor1->next;
268 cursor2 = cursor2->next;
270 if(!different &&
271 ((cursor1 && !cursor2) ||
272 (!cursor1 && cursor2)))
273 different = 1;
275 return different;
278 static int compare_control(control_t *control1, control_t *control2) {
279 int different = 0;
280 char *nameid = NULL;
281 int ignore_style;
282 if(!different &&
283 ((control1 && !control2) ||
284 (!control1 && control2)))
285 different = 1;
286 if(different || !control1 || !control2)
287 return different;
288 nameid = strdup(get_nameid_str(control1->ctlclass));
289 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
290 different = 1;
291 free(nameid);
292 if (different)
293 return different;
295 /* allow the translators to set some styles */
296 ignore_style = 0;
297 if (control1->ctlclass->type == name_ord && control1->ctlclass->name.i_name == CT_BUTTON)
298 ignore_style = 0x2000; /* BS_MULTILINE*/
300 if(!different &&
301 (control1->id != control2->id))
302 different = 1;
303 if(!different && control1->gotstyle && control2->gotstyle) {
304 if((!control1->style || !control2->style) ||
305 (control1->style->and_mask || control2->style->and_mask) ||
306 ((control1->style->or_mask & ~ignore_style) != (control2->style->or_mask & ~ignore_style)))
307 different = 1;
308 } else if(!different &&
309 ((control1->gotstyle && !control2->gotstyle) ||
310 (!control1->gotstyle && control2->gotstyle)))
311 different = 1;
312 if(!different && control1->gotexstyle && control2->gotexstyle) {
313 if((!control1->exstyle || !control2->exstyle) ||
314 (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
315 (control1->exstyle->or_mask != control2->exstyle->or_mask))
316 different = 1;
317 } else if(!different &&
318 ((control1->gotexstyle && !control2->gotexstyle) ||
319 (!control1->gotexstyle && control2->gotexstyle)))
320 different = 1;
321 if(!different && control1->gothelpid && control2->gothelpid) {
322 if(control1->helpid != control2->helpid)
323 different = 1;
324 } else if(!different &&
325 ((control1->gothelpid && !control2->gothelpid) ||
326 (!control1->gothelpid && control2->gothelpid)))
327 different = 1;
328 return different;
331 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
332 int different = 0;
333 char *nameid = NULL;
334 control_t *ctrl1, *ctrl2;
335 if(!different &&
336 ((dialog1->memopt != dialog2->memopt) ||
337 (dialog1->lvc.version != dialog2->lvc.version) ||
338 (dialog1->lvc.characts != dialog2->lvc.characts)))
339 different = 1;
340 if(!different && dialog1->gotstyle && dialog2->gotstyle) {
341 if((!dialog1->style || !dialog2->style) ||
342 (dialog1->style->and_mask || dialog2->style->and_mask) ||
343 (dialog1->style->or_mask != dialog2->style->or_mask))
344 different = 1;
345 } else if(!different &&
346 ((dialog1->gotstyle && !dialog2->gotstyle) ||
347 (!dialog1->gotstyle && dialog2->gotstyle)))
348 different = 1;
349 if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
350 if((!dialog1->exstyle || !dialog2->exstyle) ||
351 (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
352 (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
353 different = 1;
354 } else if(!different &&
355 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
356 (!dialog1->gotexstyle && dialog2->gotexstyle)))
357 different = 1;
358 if(!different && dialog1->gothelpid && dialog2->gothelpid) {
359 if(dialog1->helpid != dialog2->helpid)
360 different = 1;
361 } else if(!different &&
362 ((dialog1->gothelpid && !dialog2->gothelpid) ||
363 (!dialog1->gothelpid && dialog2->gothelpid)))
364 different = 1;
365 nameid = strdup(get_nameid_str(dialog1->menu));
366 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
367 different = 1;
368 free(nameid);
369 nameid = strdup(get_nameid_str(dialog1->dlgclass));
370 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
371 different = 1;
372 free(nameid);
374 ctrl1 = dialog1->controls;
375 ctrl2 = dialog2->controls;
376 while(!different && (ctrl1 || ctrl2))
378 different = compare_control(ctrl1, ctrl2);
379 if (ctrl1) ctrl1 = ctrl1->next;
380 if (ctrl2) ctrl2 = ctrl2->next;
382 return different;
385 static int compare_font(font_t *font1, font_t *font2) {
386 int different = 0;
387 if(!different &&
388 ((font1->memopt != font2->memopt) ||
389 (font1->data->lvc.version != font2->data->lvc.version) ||
390 (font1->data->lvc.characts != font2->data->lvc.characts)))
391 different = 1;
392 return different;
395 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
396 int different = 0;
397 if(!different &&
398 ((fontdir1->memopt != fontdir2->memopt) ||
399 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
400 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
401 different = 1;
402 return different;
405 static int compare_icon(icon_t *icon1, icon_t *icon2) {
406 int different = 0;
407 if(!different &&
408 ((icon1->id != icon2->id) ||
409 (icon1->width != icon2->width) ||
410 (icon1->height != icon2->height)))
411 different = 1;
412 if(!different &&
413 ((icon1->lvc.version != icon2->lvc.version) ||
414 (icon1->lvc.characts != icon2->lvc.characts)))
415 different = 1;
416 return different;
419 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
420 int different = 0;
421 icon_t *icon1 = NULL, *icon2 = NULL;
422 if(!different &&
423 ((icon_group1->memopt != icon_group2->memopt) ||
424 (icon_group1->lvc.version != icon_group2->lvc.version) ||
425 (icon_group1->lvc.characts != icon_group2->lvc.characts)))
426 different = 1;
427 if(!different &&
428 (icon_group1->nicon != icon_group2->nicon))
429 different = 1;
430 if(!different) {
431 icon1 = icon_group1->iconlist;
432 icon2 = icon_group2->iconlist;
433 while(!different && icon1 && icon2) {
434 different = compare_icon(icon1, icon2);
435 icon1 = icon1->next;
436 icon2 = icon2->next;
438 if(!different &&
439 ((icon1 && !icon2) ||
440 (!icon1 && icon2)))
441 different = 1;
443 return different;
446 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
447 int different = 0;
448 while(!different && menu_item1 && menu_item2) {
449 if(menu_item1->popup && menu_item2->popup) {
450 if(!different && menu_item1->gotid && menu_item2->gotid) {
451 if(menu_item1->id != menu_item2->id)
452 different = 1;
453 } else if(!different &&
454 ((menu_item1->gotid && !menu_item2->gotid) ||
455 (!menu_item1->gotid && menu_item2->gotid)))
456 different = 1;
457 if(!different && menu_item1->gottype && menu_item2->gottype) {
458 if(menu_item1->type != menu_item2->type)
459 different = 1;
460 } else if(!different &&
461 ((menu_item1->gottype && !menu_item2->gottype) ||
462 (!menu_item1->gottype && menu_item2->gottype)))
463 different = 1;
464 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
465 if(menu_item1->state != menu_item2->state)
466 different = 1;
467 } else if(!different &&
468 ((menu_item1->gotstate && !menu_item2->gotstate) ||
469 (!menu_item1->gotstate && menu_item2->gotstate)))
470 different = 1;
471 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
472 if(menu_item1->helpid != menu_item2->helpid)
473 different = 1;
474 } else if(!different &&
475 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
476 (!menu_item1->gothelpid && menu_item2->gothelpid)))
477 different = 1;
478 if(!different)
479 different = compare_menu_item(menu_item1->popup, menu_item2->popup);
480 } else if(!menu_item1->popup && !menu_item2->popup) {
481 if(menu_item1->name && menu_item2->name) {
482 if(!different && menu_item1->gotid && menu_item2->gotid) {
483 if(menu_item1->id != menu_item2->id)
484 different = 1;
485 } else if(!different &&
486 ((menu_item1->gotid && !menu_item2->gotid) ||
487 (!menu_item1->gotid && menu_item2->gotid)))
488 different = 1;
489 if(!different && menu_item1->gottype && menu_item2->gottype) {
490 if(menu_item1->type != menu_item2->type)
491 different = 1;
492 } else if(!different &&
493 ((menu_item1->gottype && !menu_item2->gottype) ||
494 (!menu_item1->gottype && menu_item2->gottype)))
495 different = 1;
496 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
497 if(menu_item1->state != menu_item2->state)
498 different = 1;
499 } else if(!different &&
500 ((menu_item1->gotstate && !menu_item2->gotstate) ||
501 (!menu_item1->gotstate && menu_item2->gotstate)))
502 different = 1;
503 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
504 if(menu_item1->helpid != menu_item2->helpid)
505 different = 1;
506 } else if(!different &&
507 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
508 (!menu_item1->gothelpid && menu_item2->gothelpid)))
509 different = 1;
510 } else if((menu_item1->name && !menu_item2->name) ||
511 (!menu_item1->name && menu_item2->name))
512 different = 1;
513 } else
514 different = 1;
515 menu_item1 = menu_item1->next;
516 menu_item2 = menu_item2->next;
518 if(!different &&
519 ((menu_item1 && !menu_item2) ||
520 (!menu_item1 && menu_item2)))
521 different = 1;
522 return different;
525 static int compare_menu(menu_t *menu1, menu_t *menu2) {
526 int different = 0;
527 if(!different &&
528 ((menu1->memopt != menu2->memopt) ||
529 (menu1->lvc.version != menu2->lvc.version) ||
530 (menu1->lvc.characts != menu2->lvc.characts)))
531 different = 1;
532 if(!different)
533 different = compare_menu_item(menu1->items, menu2->items);
534 return different;
537 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
538 int different = 0;
539 if(!different &&
540 ((rcdata1->memopt != rcdata2->memopt) ||
541 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
542 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
543 different = 1;
544 return different;
547 static int compare_html(html_t *rcdata1, html_t *rcdata2) {
548 int different = 0;
549 if(!different &&
550 ((rcdata1->memopt != rcdata2->memopt) ||
551 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
552 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
553 different = 1;
554 return different;
557 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
558 int different = 0;
559 int i;
560 while(!different && stringtable1 && stringtable2) {
561 if((stringtable1->memopt != stringtable2->memopt) ||
562 (stringtable1->lvc.version != stringtable2->lvc.version) ||
563 (stringtable1->lvc.characts != stringtable2->lvc.characts))
564 different = 1;
565 if(!different) {
566 if((stringtable1->nentries != stringtable2->nentries) ||
567 (stringtable1->idbase != stringtable2->idbase))
568 different = 1;
569 else
570 for(i = 0 ; i < stringtable1->nentries; i++)
571 if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
572 (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
573 (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
574 (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
575 different = 1;
576 break;
579 stringtable1 = stringtable1->next;
580 stringtable2 = stringtable2->next;
582 return different;
585 static int compare_user(user_t *user1, user_t *user2) {
586 int different = 0;
587 char *nameid = NULL;
588 if(!different &&
589 ((user1->memopt != user2->memopt) ||
590 (user1->data->lvc.version != user2->data->lvc.version) ||
591 (user1->data->lvc.characts != user2->data->lvc.characts)))
592 different = 1;
593 nameid = strdup(get_nameid_str(user1->type));
594 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
595 different = 1;
596 free(nameid);
597 return different;
600 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
601 int different = 0;
602 if(!different &&
603 ((messagetable1->memopt != messagetable2->memopt) ||
604 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
605 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
606 different = 1;
607 return different;
610 static int compare_string(string_t *string1, string_t *string2) {
611 int different = 0;
612 if(!different &&
613 ((string1->size != string2->size) ||
614 (string1->type != string2->type)))
615 different = 1;
616 if(!different) {
617 if(string1->type == str_char)
618 different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
619 else if(string1->type == str_unicode)
620 different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
621 else
622 different = 1;
624 return different;
627 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
629 static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
630 int different = 0;
631 int i = 0;
632 if(!different &&
633 (ver_value1->type == ver_value2->type)) {
634 switch(ver_value1->type) {
635 case val_str:
636 if(!different && ver_value1->key && ver_value2->key)
637 different = compare_string(ver_value1->key, ver_value2->key);
638 else if(!different &&
639 ((ver_value1->key && !ver_value2->key) ||
640 (!ver_value1->key && ver_value2->key)))
641 different = 1;
642 break;
643 case val_words:
644 if(!different && ver_value1->key && ver_value2->key)
645 different = compare_string(ver_value1->key, ver_value2->key);
646 else if(!different &&
647 ((ver_value1->key && !ver_value2->key) ||
648 (!ver_value1->key && ver_value2->key)))
649 different = 1;
650 if(!different && ver_value1->value.words && ver_value2->value.words) {
651 if(!different &&
652 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
653 different = 1;
654 if(!different)
655 for(i = 0; i < ver_value1->value.words->nwords; i++) {
656 if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
657 different = 1;
658 break;
661 } else if(!different &&
662 ((ver_value1->value.words && !ver_value2->value.words) ||
663 (!ver_value1->value.words && ver_value2->value.words)))
664 different = 1;
665 break;
666 case val_block:
667 if(!different && ver_value1->value.block && ver_value2->value.block)
668 different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
669 else if(!different &&
670 ((ver_value1->value.block && !ver_value2->value.block) ||
671 (!ver_value1->value.block && ver_value2->value.block)))
672 different = 1;
673 break;
674 default:
675 different = 1;
677 } else
678 different = 1;
679 return different;
682 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
683 int different = 0;
684 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
685 if(!different) {
686 ver_value1 = ver_block1->values;
687 ver_value2 = ver_block2->values;
688 while(!different && ver_value1 && ver_value2) {
689 different = compare_ver_value(ver_value1, ver_value2);
690 ver_value1 = ver_value1->next;
691 ver_value2 = ver_value2->next;
693 if(!different &&
694 ((ver_value1 && !ver_value2) ||
695 (!ver_value1 && ver_value2)))
696 different = 1;
698 return different;
701 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
702 int different = 0;
703 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
704 if(!different &&
705 ((versioninfo1->memopt != versioninfo2->memopt) ||
706 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
707 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
708 different = 1;
709 if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
710 if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
711 (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
712 (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
713 (versioninfo1->filever_min2 != versioninfo2->filever_min2))
714 different = 1;
715 } else if(!different &&
716 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
717 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
718 different = 1;
719 if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
720 if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
721 (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
722 (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
723 (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
724 different = 1;
725 } else if(!different &&
726 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
727 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
728 different = 1;
729 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
730 if(versioninfo1->fileos != versioninfo2->fileos)
731 different = 1;
732 } else if(!different &&
733 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
734 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
735 different = 1;
736 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
737 if(versioninfo1->fileflags != versioninfo2->fileflags)
738 different = 1;
739 } else if(!different &&
740 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
741 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
742 different = 1;
743 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
744 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
745 different = 1;
746 } else if(!different &&
747 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
748 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
749 different = 1;
750 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
751 if(versioninfo1->filetype != versioninfo2->filetype)
752 different = 1;
753 } else if(!different &&
754 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
755 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
756 different = 1;
757 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
758 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
759 different = 1;
760 } else if(!different &&
761 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
762 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
763 different = 1;
764 if(!different) {
765 ver_block1 = versioninfo1->blocks;
766 ver_block2 = versioninfo2->blocks;
767 while(!different && ver_block1 && ver_block2) {
768 different = compare_ver_block(ver_block1, ver_block2);
769 ver_block1 = ver_block1->next;
770 ver_block2 = ver_block2->next;
772 if(!different &&
773 ((ver_block1 && !ver_block2) ||
774 (!ver_block1 && ver_block2)))
775 different = 1;
777 return different;
780 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
781 int different = 0;
782 if(!different &&
783 ((dlginit1->memopt != dlginit2->memopt) ||
784 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
785 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
786 different = 1;
787 return different;
790 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
791 int different = 0;
792 while(!different && toolbar_item1 && toolbar_item2) {
793 if((toolbar_item1->id && !toolbar_item2->id) ||
794 (!toolbar_item1->id && toolbar_item2->id))
795 different = 1;
796 toolbar_item1 = toolbar_item1->next;
797 toolbar_item2 = toolbar_item2->next;
799 if(!different &&
800 ((toolbar_item1 && !toolbar_item2) ||
801 (!toolbar_item1 && toolbar_item2)))
802 different = 1;
803 return different;
806 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
807 int different = 0;
808 if(!different &&
809 ((toolbar1->memopt != toolbar2->memopt) ||
810 (toolbar1->lvc.version != toolbar2->lvc.version) ||
811 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
812 different = 1;
813 if(!different)
814 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
815 return different;
818 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
819 int different = 0;
820 if(!different &&
821 ((ani_curico1->memopt != ani_curico2->memopt) ||
822 (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
823 (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
824 different = 1;
825 return different;
828 static int compare(resource_t *resource1, resource_t *resource2) {
829 switch(resource1->type) {
830 case res_acc:
831 return compare_accelerator(resource1->res.acc, resource2->res.acc);
832 case res_bmp:
833 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
834 case res_cur:
835 return compare_cursor(resource1->res.cur, resource2->res.cur);
836 case res_curg:
837 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
838 case res_dlg:
839 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
840 case res_fnt:
841 return compare_font(resource1->res.fnt, resource2->res.fnt);
842 case res_fntdir:
843 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
844 case res_ico:
845 return compare_icon(resource1->res.ico, resource2->res.ico);
846 case res_icog:
847 return compare_icon_group(resource1->res.icog, resource2->res.icog);
848 case res_men:
849 return compare_menu(resource1->res.men, resource2->res.men);
850 case res_rdt:
851 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
852 case res_stt:
853 return compare_stringtable(resource1->res.stt, resource2->res.stt);
854 case res_usr:
855 return compare_user(resource1->res.usr, resource2->res.usr);
856 case res_html:
857 return compare_html(resource1->res.html, resource2->res.html);
858 case res_msg:
859 return compare_messagetable(resource1->res.msg, resource2->res.msg);
860 case res_ver:
861 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
862 case res_dlginit:
863 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
864 case res_toolbar:
865 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
866 case res_anicur:
867 case res_aniico:
868 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
869 default:
870 /* Not supposed to reach here */
871 fprintf(stderr, "Not supposed to reach here (compare())\n");
872 abort();
873 return -1;
877 typedef struct resource_lang_node
879 language_t lang;
880 resource_t *res;
881 struct resource_lang_node *next;
882 } resource_lang_node_t;
884 typedef struct resource_id_node
886 name_id_t *id;
887 resource_lang_node_t *langs;
888 struct resource_id_node *next;
889 } resource_id_node_t;
891 static struct
893 int enabled;
894 struct resource_id_node *ids;
895 } verify_tab[res_usr+1];
897 static void add_resource(resource_t *res)
899 resource_id_node_t *idnode;
900 resource_lang_node_t *langnode;
901 if (!verify_tab[res->type].enabled)
903 fprintf(stderr, "ERR: Report this: unknown resource type parsed %08x\n", res->type);
904 return;
907 for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
908 if (compare_name_id(idnode->id, res->name) == 0)
909 break;
911 if (idnode == NULL)
913 idnode = xmalloc(sizeof(resource_id_node_t));
914 idnode->id = res->name;
915 idnode->langs = NULL;
916 idnode->next = verify_tab[res->type].ids;
917 verify_tab[res->type].ids = idnode;
920 for (langnode = idnode->langs; langnode; langnode = langnode->next)
921 if (compare_lang(langnode->lang, get_language(res)) == 0)
923 fprintf(stderr, "ERR: resource %s [type %x] language %03x:%02x duplicated!\n",
924 get_nameid_str(res->name), res->type, langnode->lang.id, langnode->lang.sub);
925 return;
928 langnode = xmalloc(sizeof(resource_lang_node_t));
929 langnode->res = res;
930 langnode->lang = get_language(res);
931 langnode->next = idnode->langs;
932 idnode->langs = langnode;
935 static void setup_tabs(void)
937 int i;
939 for (i = 0; i <= res_usr; i++)
940 switch(i) {
941 case res_acc:
942 case res_bmp:
943 case res_cur:
944 case res_curg:
945 case res_dlg:
946 case res_fnt:
947 case res_fntdir:
948 case res_ico:
949 case res_icog:
950 case res_men:
951 case res_rdt:
952 case res_stt:
953 case res_usr:
954 case res_msg:
955 case res_ver:
956 case res_dlginit:
957 case res_toolbar:
958 case res_anicur:
959 case res_aniico:
960 case res_html:
961 verify_tab[i].enabled = 1;
962 break;
966 static const char *get_typename_for_int(int type) {
967 resource_t res;
968 res.type = type;
969 return get_typename(&res);
972 static resource_t *find_main(int type, name_id_t *id, resource_lang_node_t *langnode)
974 resource_t *neutral = NULL, *en = NULL, *en_US = NULL;
975 for (; langnode; langnode = langnode->next)
977 if (langnode->lang.id == LANG_NEUTRAL && langnode->lang.sub == SUBLANG_NEUTRAL)
978 neutral = langnode->res;
979 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == SUBLANG_NEUTRAL)
980 en = langnode->res;
981 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == MASTER_SUBLANGUAGE)
982 en_US = langnode->res;
985 if (neutral != NULL && (en != NULL || en_US != NULL))
987 fprintf(stderr, "INFO: Resource %04x/%s has both NEUTRAL and MASTER language translation\n",
988 type, get_nameid_str(id));
991 if (en_US != NULL) return en_US;
992 if (en != NULL) return en;
993 return neutral;
996 void verify_translations(resource_t *top) {
997 resource_t *curr = top;
998 resource_id_node_t *idnode;
999 resource_lang_node_t *langnode;
1000 int type;
1002 setup_tabs();
1003 while (curr)
1005 add_resource(curr);
1006 curr = curr->next;
1009 for (type = 0; type <= res_usr; type++)
1011 printf("TYPE NEXT [%s]\n", get_typename_for_int(type));
1012 for (idnode = verify_tab[type].ids; idnode; idnode = idnode->next)
1014 resource_t *mainres;
1015 printf("RESOURCE [%s]\n", get_nameid_str(idnode->id));
1017 mainres = find_main(type, idnode->id, idnode->langs);
1018 if (!mainres)
1020 fprintf(stderr, "ERR: resource %04x/%s has translation(s) but not available in NEUTRAL or MASTER language\n",
1021 type, get_nameid_str(idnode->id));
1022 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1023 printf("EXTRA %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1024 continue;
1027 if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
1028 printf("NOTRANSL\n");
1029 continue;
1032 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1034 printf("EXIST %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1035 if (compare(langnode->res, mainres))
1037 printf("DIFF %03x:%02x\n", langnode->lang.id, langnode->lang.sub);