TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / tools / wrc / translation.c
blobbdbcb4342bd8644ebba6d24da6528dadd677a9be
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(((accelerator1->memopt != accelerator2->memopt) ||
205 (accelerator1->lvc.version != accelerator2->lvc.version) ||
206 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
207 different = 1;
208 ev1 = accelerator1->events;
209 ev2 = accelerator2->events;
210 while(!different && ev1 && ev2) {
211 if(!different &&
212 ((ev1->id != ev2->id) ||
213 (ev1->flags != ev2->flags)))
214 different = 1;
215 ev1 = ev1->next;
216 ev2 = ev2->next;
218 if(!different &&
219 ((ev1 && !ev2) || (!ev1 && ev2)))
220 different = 1;
221 return different;
224 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
225 int different = 0;
226 if(((bitmap1->memopt != bitmap2->memopt) ||
227 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
228 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
229 different = 1;
230 return different;
233 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
234 int different = 0;
235 if(((cursor1->id != cursor2->id) ||
236 (cursor1->width != cursor2->width) ||
237 (cursor1->height != cursor2->height) ||
238 (cursor1->xhot != cursor2->xhot) ||
239 (cursor1->yhot != cursor2->yhot)))
240 different = 1;
241 if(!different &&
242 ((cursor1->lvc.version != cursor2->lvc.version) ||
243 (cursor1->lvc.characts != cursor2->lvc.characts)))
244 different = 1;
245 return different;
248 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
249 int different = 0;
250 cursor_t *cursor1 = NULL, *cursor2 = NULL;
251 if(((cursor_group1->memopt != cursor_group2->memopt) ||
252 (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
253 (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
254 different = 1;
255 if(!different &&
256 (cursor_group1->ncursor != cursor_group2->ncursor))
257 different = 1;
258 if(!different) {
259 cursor1 = cursor_group1->cursorlist;
260 cursor2 = cursor_group2->cursorlist;
261 while(!different && cursor1 && cursor2) {
262 different = compare_cursor(cursor1, cursor2);
263 cursor1 = cursor1->next;
264 cursor2 = cursor2->next;
266 if(!different &&
267 ((cursor1 && !cursor2) ||
268 (!cursor1 && cursor2)))
269 different = 1;
271 return different;
274 static int compare_control(control_t *control1, control_t *control2) {
275 int different = 0;
276 char *nameid = NULL;
277 int ignore_style;
278 if(((control1 && !control2) || (!control1 && control2)))
279 different = 1;
280 if(different || !control1 || !control2)
281 return different;
282 nameid = strdup(get_nameid_str(control1->ctlclass));
283 if(strcmp(nameid, get_nameid_str(control2->ctlclass)))
284 different = 1;
285 free(nameid);
286 if (different)
287 return different;
289 /* allow the translators to set some styles */
290 ignore_style = 0;
291 if (control1->ctlclass->type == name_ord && control1->ctlclass->name.i_name == CT_BUTTON)
292 ignore_style = 0x2000; /* BS_MULTILINE*/
294 if((control1->id != control2->id))
295 different = 1;
296 if(!different && control1->gotstyle && control2->gotstyle) {
297 if((!control1->style || !control2->style) ||
298 (control1->style->and_mask || control2->style->and_mask) ||
299 ((control1->style->or_mask & ~ignore_style) != (control2->style->or_mask & ~ignore_style)))
300 different = 1;
301 } else if(!different &&
302 ((control1->gotstyle && !control2->gotstyle) ||
303 (!control1->gotstyle && control2->gotstyle)))
304 different = 1;
305 if(!different && control1->gotexstyle && control2->gotexstyle) {
306 if((!control1->exstyle || !control2->exstyle) ||
307 (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
308 (control1->exstyle->or_mask != control2->exstyle->or_mask))
309 different = 1;
310 } else if(!different &&
311 ((control1->gotexstyle && !control2->gotexstyle) ||
312 (!control1->gotexstyle && control2->gotexstyle)))
313 different = 1;
314 if(!different && control1->gothelpid && control2->gothelpid) {
315 if(control1->helpid != control2->helpid)
316 different = 1;
317 } else if(!different &&
318 ((control1->gothelpid && !control2->gothelpid) ||
319 (!control1->gothelpid && control2->gothelpid)))
320 different = 1;
321 return different;
324 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
325 int different = 0;
326 char *nameid = NULL;
327 control_t *ctrl1, *ctrl2;
328 if(((dialog1->memopt != dialog2->memopt) ||
329 (dialog1->lvc.version != dialog2->lvc.version) ||
330 (dialog1->lvc.characts != dialog2->lvc.characts)))
331 different = 1;
332 if(!different && dialog1->gotstyle && dialog2->gotstyle) {
333 if((!dialog1->style || !dialog2->style) ||
334 (dialog1->style->and_mask || dialog2->style->and_mask) ||
335 (dialog1->style->or_mask != dialog2->style->or_mask))
336 different = 1;
337 } else if(!different &&
338 ((dialog1->gotstyle && !dialog2->gotstyle) ||
339 (!dialog1->gotstyle && dialog2->gotstyle)))
340 different = 1;
341 if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
342 if((!dialog1->exstyle || !dialog2->exstyle) ||
343 (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
344 (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
345 different = 1;
346 } else if(!different &&
347 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
348 (!dialog1->gotexstyle && dialog2->gotexstyle)))
349 different = 1;
350 if(!different && dialog1->gothelpid && dialog2->gothelpid) {
351 if(dialog1->helpid != dialog2->helpid)
352 different = 1;
353 } else if(!different &&
354 ((dialog1->gothelpid && !dialog2->gothelpid) ||
355 (!dialog1->gothelpid && dialog2->gothelpid)))
356 different = 1;
357 nameid = strdup(get_nameid_str(dialog1->menu));
358 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
359 different = 1;
360 free(nameid);
361 nameid = strdup(get_nameid_str(dialog1->dlgclass));
362 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
363 different = 1;
364 free(nameid);
366 ctrl1 = dialog1->controls;
367 ctrl2 = dialog2->controls;
368 while(!different && (ctrl1 || ctrl2))
370 different = compare_control(ctrl1, ctrl2);
371 if (ctrl1) ctrl1 = ctrl1->next;
372 if (ctrl2) ctrl2 = ctrl2->next;
374 return different;
377 static int compare_font(font_t *font1, font_t *font2) {
378 int different = 0;
379 if(((font1->memopt != font2->memopt) ||
380 (font1->data->lvc.version != font2->data->lvc.version) ||
381 (font1->data->lvc.characts != font2->data->lvc.characts)))
382 different = 1;
383 return different;
386 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
387 int different = 0;
388 if(((fontdir1->memopt != fontdir2->memopt) ||
389 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
390 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
391 different = 1;
392 return different;
395 static int compare_icon(icon_t *icon1, icon_t *icon2) {
396 int different = 0;
397 if(((icon1->id != icon2->id) ||
398 (icon1->width != icon2->width) ||
399 (icon1->height != icon2->height)))
400 different = 1;
401 if(!different &&
402 ((icon1->lvc.version != icon2->lvc.version) ||
403 (icon1->lvc.characts != icon2->lvc.characts)))
404 different = 1;
405 return different;
408 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
409 int different = 0;
410 icon_t *icon1 = NULL, *icon2 = NULL;
411 if(((icon_group1->memopt != icon_group2->memopt) ||
412 (icon_group1->lvc.version != icon_group2->lvc.version) ||
413 (icon_group1->lvc.characts != icon_group2->lvc.characts)))
414 different = 1;
415 if(!different &&
416 (icon_group1->nicon != icon_group2->nicon))
417 different = 1;
418 if(!different) {
419 icon1 = icon_group1->iconlist;
420 icon2 = icon_group2->iconlist;
421 while(!different && icon1 && icon2) {
422 different = compare_icon(icon1, icon2);
423 icon1 = icon1->next;
424 icon2 = icon2->next;
426 if(!different &&
427 ((icon1 && !icon2) ||
428 (!icon1 && icon2)))
429 different = 1;
431 return different;
434 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
435 int different = 0;
436 while(!different && menu_item1 && menu_item2) {
437 if(menu_item1->popup && menu_item2->popup) {
438 if(!different && menu_item1->gotid && menu_item2->gotid) {
439 if(menu_item1->id != menu_item2->id)
440 different = 1;
441 } else if(!different &&
442 ((menu_item1->gotid && !menu_item2->gotid) ||
443 (!menu_item1->gotid && menu_item2->gotid)))
444 different = 1;
445 if(!different && menu_item1->gottype && menu_item2->gottype) {
446 if(menu_item1->type != menu_item2->type)
447 different = 1;
448 } else if(!different &&
449 ((menu_item1->gottype && !menu_item2->gottype) ||
450 (!menu_item1->gottype && menu_item2->gottype)))
451 different = 1;
452 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
453 if(menu_item1->state != menu_item2->state)
454 different = 1;
455 } else if(!different &&
456 ((menu_item1->gotstate && !menu_item2->gotstate) ||
457 (!menu_item1->gotstate && menu_item2->gotstate)))
458 different = 1;
459 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
460 if(menu_item1->helpid != menu_item2->helpid)
461 different = 1;
462 } else if(!different &&
463 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
464 (!menu_item1->gothelpid && menu_item2->gothelpid)))
465 different = 1;
466 if(!different)
467 different = compare_menu_item(menu_item1->popup, menu_item2->popup);
468 } else if(!menu_item1->popup && !menu_item2->popup) {
469 if(menu_item1->name && menu_item2->name) {
470 if(!different && menu_item1->gotid && menu_item2->gotid) {
471 if(menu_item1->id != menu_item2->id)
472 different = 1;
473 } else if(!different &&
474 ((menu_item1->gotid && !menu_item2->gotid) ||
475 (!menu_item1->gotid && menu_item2->gotid)))
476 different = 1;
477 if(!different && menu_item1->gottype && menu_item2->gottype) {
478 if(menu_item1->type != menu_item2->type)
479 different = 1;
480 } else if(!different &&
481 ((menu_item1->gottype && !menu_item2->gottype) ||
482 (!menu_item1->gottype && menu_item2->gottype)))
483 different = 1;
484 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
485 if(menu_item1->state != menu_item2->state)
486 different = 1;
487 } else if(!different &&
488 ((menu_item1->gotstate && !menu_item2->gotstate) ||
489 (!menu_item1->gotstate && menu_item2->gotstate)))
490 different = 1;
491 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
492 if(menu_item1->helpid != menu_item2->helpid)
493 different = 1;
494 } else if(!different &&
495 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
496 (!menu_item1->gothelpid && menu_item2->gothelpid)))
497 different = 1;
498 } else if((menu_item1->name && !menu_item2->name) ||
499 (!menu_item1->name && menu_item2->name))
500 different = 1;
501 } else
502 different = 1;
503 menu_item1 = menu_item1->next;
504 menu_item2 = menu_item2->next;
506 if(!different &&
507 ((menu_item1 && !menu_item2) ||
508 (!menu_item1 && menu_item2)))
509 different = 1;
510 return different;
513 static int compare_menu(menu_t *menu1, menu_t *menu2) {
514 int different = 0;
515 if(((menu1->memopt != menu2->memopt) ||
516 (menu1->lvc.version != menu2->lvc.version) ||
517 (menu1->lvc.characts != menu2->lvc.characts)))
518 different = 1;
519 if(!different)
520 different = compare_menu_item(menu1->items, menu2->items);
521 return different;
524 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
525 int different = 0;
526 if(((rcdata1->memopt != rcdata2->memopt) ||
527 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
528 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
529 different = 1;
530 return different;
533 static int compare_html(html_t *rcdata1, html_t *rcdata2) {
534 int different = 0;
535 if(((rcdata1->memopt != rcdata2->memopt) ||
536 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
537 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
538 different = 1;
539 return different;
542 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
543 int different = 0;
544 int i;
545 while(!different && stringtable1 && stringtable2) {
546 if((stringtable1->memopt != stringtable2->memopt) ||
547 (stringtable1->lvc.version != stringtable2->lvc.version) ||
548 (stringtable1->lvc.characts != stringtable2->lvc.characts))
549 different = 1;
550 if(!different) {
551 if((stringtable1->nentries != stringtable2->nentries) ||
552 (stringtable1->idbase != stringtable2->idbase))
553 different = 1;
554 else
555 for(i = 0 ; i < stringtable1->nentries; i++)
556 if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
557 (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
558 (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
559 (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
560 different = 1;
561 break;
564 stringtable1 = stringtable1->next;
565 stringtable2 = stringtable2->next;
567 return different;
570 static int compare_user(user_t *user1, user_t *user2) {
571 int different = 0;
572 char *nameid = NULL;
573 if(((user1->memopt != user2->memopt) ||
574 (user1->data->lvc.version != user2->data->lvc.version) ||
575 (user1->data->lvc.characts != user2->data->lvc.characts)))
576 different = 1;
577 nameid = strdup(get_nameid_str(user1->type));
578 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
579 different = 1;
580 free(nameid);
581 return different;
584 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
585 int different = 0;
586 if(((messagetable1->memopt != messagetable2->memopt) ||
587 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
588 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
589 different = 1;
590 return different;
593 static int compare_string(string_t *string1, string_t *string2) {
594 int different = 0;
595 if(((string1->size != string2->size) ||
596 (string1->type != string2->type)))
597 different = 1;
598 if(!different) {
599 if(string1->type == str_char)
600 different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
601 else if(string1->type == str_unicode)
602 different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
603 else
604 different = 1;
606 return different;
609 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
611 static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
612 int different = 0;
613 int i = 0;
614 if (ver_value1->type == ver_value2->type) {
615 switch(ver_value1->type) {
616 case val_str:
617 if(ver_value1->key && ver_value2->key)
618 different = compare_string(ver_value1->key, ver_value2->key);
619 else if(((ver_value1->key && !ver_value2->key) ||
620 (!ver_value1->key && ver_value2->key)))
621 different = 1;
622 break;
623 case val_words:
624 if(ver_value1->key && ver_value2->key)
625 different = compare_string(ver_value1->key, ver_value2->key);
626 else if(((ver_value1->key && !ver_value2->key) ||
627 (!ver_value1->key && ver_value2->key)))
628 different = 1;
629 if(!different && ver_value1->value.words && ver_value2->value.words) {
630 if(ver_value1->value.words->nwords != ver_value2->value.words->nwords)
631 different = 1;
632 if(!different)
633 for(i = 0; i < ver_value1->value.words->nwords; i++) {
634 if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
635 different = 1;
636 break;
639 } else if(!different &&
640 ((ver_value1->value.words && !ver_value2->value.words) ||
641 (!ver_value1->value.words && ver_value2->value.words)))
642 different = 1;
643 break;
644 case val_block:
645 if(ver_value1->value.block && ver_value2->value.block)
646 different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
647 else if(((ver_value1->value.block && !ver_value2->value.block) ||
648 (!ver_value1->value.block && ver_value2->value.block)))
649 different = 1;
650 break;
651 default:
652 different = 1;
654 } else
655 different = 1;
656 return different;
659 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
660 int different = 0;
661 ver_value_t *ver_value1 = ver_block1->values, *ver_value2 = ver_block2->values;
663 while(!different && ver_value1 && ver_value2) {
664 different = compare_ver_value(ver_value1, ver_value2);
665 ver_value1 = ver_value1->next;
666 ver_value2 = ver_value2->next;
668 if(!different &&
669 ((ver_value1 && !ver_value2) ||
670 (!ver_value1 && ver_value2)))
671 different = 1;
673 return different;
676 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
677 int different = 0;
678 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
679 if(((versioninfo1->memopt != versioninfo2->memopt) ||
680 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
681 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
682 different = 1;
683 if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
684 if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
685 (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
686 (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
687 (versioninfo1->filever_min2 != versioninfo2->filever_min2))
688 different = 1;
689 } else if(!different &&
690 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
691 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
692 different = 1;
693 if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
694 if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
695 (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
696 (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
697 (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
698 different = 1;
699 } else if(!different &&
700 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
701 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
702 different = 1;
703 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
704 if(versioninfo1->fileos != versioninfo2->fileos)
705 different = 1;
706 } else if(!different &&
707 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
708 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
709 different = 1;
710 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
711 if(versioninfo1->fileflags != versioninfo2->fileflags)
712 different = 1;
713 } else if(!different &&
714 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
715 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
716 different = 1;
717 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
718 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
719 different = 1;
720 } else if(!different &&
721 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
722 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
723 different = 1;
724 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
725 if(versioninfo1->filetype != versioninfo2->filetype)
726 different = 1;
727 } else if(!different &&
728 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
729 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
730 different = 1;
731 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
732 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
733 different = 1;
734 } else if(!different &&
735 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
736 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
737 different = 1;
738 if(!different) {
739 ver_block1 = versioninfo1->blocks;
740 ver_block2 = versioninfo2->blocks;
741 while(!different && ver_block1 && ver_block2) {
742 different = compare_ver_block(ver_block1, ver_block2);
743 ver_block1 = ver_block1->next;
744 ver_block2 = ver_block2->next;
746 if(!different &&
747 ((ver_block1 && !ver_block2) ||
748 (!ver_block1 && ver_block2)))
749 different = 1;
751 return different;
754 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
755 int different = 0;
756 if(((dlginit1->memopt != dlginit2->memopt) ||
757 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
758 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
759 different = 1;
760 return different;
763 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
764 int different = 0;
765 while(!different && toolbar_item1 && toolbar_item2) {
766 if((toolbar_item1->id && !toolbar_item2->id) ||
767 (!toolbar_item1->id && toolbar_item2->id))
768 different = 1;
769 toolbar_item1 = toolbar_item1->next;
770 toolbar_item2 = toolbar_item2->next;
772 if(!different &&
773 ((toolbar_item1 && !toolbar_item2) ||
774 (!toolbar_item1 && toolbar_item2)))
775 different = 1;
776 return different;
779 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
780 int different = 0;
781 if(((toolbar1->memopt != toolbar2->memopt) ||
782 (toolbar1->lvc.version != toolbar2->lvc.version) ||
783 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
784 different = 1;
785 if(!different)
786 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
787 return different;
790 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
791 int different = 0;
792 if(((ani_curico1->memopt != ani_curico2->memopt) ||
793 (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
794 (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
795 different = 1;
796 return different;
799 static int compare(resource_t *resource1, resource_t *resource2) {
800 switch(resource1->type) {
801 case res_acc:
802 return compare_accelerator(resource1->res.acc, resource2->res.acc);
803 case res_bmp:
804 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
805 case res_cur:
806 return compare_cursor(resource1->res.cur, resource2->res.cur);
807 case res_curg:
808 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
809 case res_dlg:
810 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
811 case res_fnt:
812 return compare_font(resource1->res.fnt, resource2->res.fnt);
813 case res_fntdir:
814 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
815 case res_ico:
816 return compare_icon(resource1->res.ico, resource2->res.ico);
817 case res_icog:
818 return compare_icon_group(resource1->res.icog, resource2->res.icog);
819 case res_men:
820 return compare_menu(resource1->res.men, resource2->res.men);
821 case res_rdt:
822 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
823 case res_stt:
824 return compare_stringtable(resource1->res.stt, resource2->res.stt);
825 case res_usr:
826 return compare_user(resource1->res.usr, resource2->res.usr);
827 case res_html:
828 return compare_html(resource1->res.html, resource2->res.html);
829 case res_msg:
830 return compare_messagetable(resource1->res.msg, resource2->res.msg);
831 case res_ver:
832 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
833 case res_dlginit:
834 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
835 case res_toolbar:
836 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
837 case res_anicur:
838 case res_aniico:
839 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
840 default:
841 /* Not supposed to reach here */
842 fprintf(stderr, "Not supposed to reach here (compare())\n");
843 abort();
844 return -1;
848 typedef struct resource_lang_node
850 language_t lang;
851 resource_t *res;
852 struct resource_lang_node *next;
853 } resource_lang_node_t;
855 typedef struct resource_id_node
857 name_id_t *id;
858 resource_lang_node_t *langs;
859 struct resource_id_node *next;
860 } resource_id_node_t;
862 static struct
864 int enabled;
865 struct resource_id_node *ids;
866 } verify_tab[res_usr+1];
868 static void add_resource(resource_t *res)
870 resource_id_node_t *idnode;
871 resource_lang_node_t *langnode;
872 if (!verify_tab[res->type].enabled)
874 fprintf(stderr, "ERR: Report this: unknown resource type parsed %08x\n", res->type);
875 return;
878 for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
879 if (compare_name_id(idnode->id, res->name) == 0)
880 break;
882 if (idnode == NULL)
884 idnode = xmalloc(sizeof(resource_id_node_t));
885 idnode->id = res->name;
886 idnode->langs = NULL;
887 idnode->next = verify_tab[res->type].ids;
888 verify_tab[res->type].ids = idnode;
891 for (langnode = idnode->langs; langnode; langnode = langnode->next)
892 if (compare_lang(langnode->lang, get_language(res)) == 0)
894 fprintf(stderr, "ERR: resource %s [type %x] language %03x:%02x duplicated!\n",
895 get_nameid_str(res->name), res->type, langnode->lang.id, langnode->lang.sub);
896 return;
899 langnode = xmalloc(sizeof(resource_lang_node_t));
900 langnode->res = res;
901 langnode->lang = get_language(res);
902 langnode->next = idnode->langs;
903 idnode->langs = langnode;
906 static void setup_tabs(void)
908 int i;
910 for (i = 0; i <= res_usr; i++)
911 switch(i) {
912 case res_acc:
913 case res_bmp:
914 case res_cur:
915 case res_curg:
916 case res_dlg:
917 case res_fnt:
918 case res_fntdir:
919 case res_ico:
920 case res_icog:
921 case res_men:
922 case res_rdt:
923 case res_stt:
924 case res_usr:
925 case res_msg:
926 case res_ver:
927 case res_dlginit:
928 case res_toolbar:
929 case res_anicur:
930 case res_aniico:
931 case res_html:
932 verify_tab[i].enabled = 1;
933 break;
937 static const char *get_typename_for_int(int type) {
938 resource_t res;
939 res.type = type;
940 return get_typename(&res);
943 static resource_t *find_main(int type, name_id_t *id, resource_lang_node_t *langnode)
945 resource_t *neutral = NULL, *en = NULL, *en_US = NULL;
946 for (; langnode; langnode = langnode->next)
948 if (langnode->lang.id == LANG_NEUTRAL && langnode->lang.sub == SUBLANG_NEUTRAL)
949 neutral = langnode->res;
950 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == SUBLANG_NEUTRAL)
951 en = langnode->res;
952 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == MASTER_SUBLANGUAGE)
953 en_US = langnode->res;
956 if (neutral != NULL && (en != NULL || en_US != NULL))
958 fprintf(stderr, "INFO: Resource %04x/%s has both NEUTRAL and MASTER language translation\n",
959 type, get_nameid_str(id));
962 if (en_US != NULL) return en_US;
963 if (en != NULL) return en;
964 return neutral;
967 void verify_translations(resource_t *top) {
968 resource_t *curr = top;
969 resource_id_node_t *idnode;
970 resource_lang_node_t *langnode;
971 int type;
973 setup_tabs();
974 while (curr)
976 add_resource(curr);
977 curr = curr->next;
980 for (type = 0; type <= res_usr; type++)
982 printf("TYPE NEXT [%s]\n", get_typename_for_int(type));
983 for (idnode = verify_tab[type].ids; idnode; idnode = idnode->next)
985 resource_t *mainres;
986 printf("RESOURCE [%s]\n", get_nameid_str(idnode->id));
988 mainres = find_main(type, idnode->id, idnode->langs);
989 if (!mainres)
991 fprintf(stderr, "ERR: resource %04x/%s has translation(s) but not available in NEUTRAL or MASTER language\n",
992 type, get_nameid_str(idnode->id));
993 for (langnode = idnode->langs; langnode; langnode = langnode->next)
994 printf("EXTRA %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
995 continue;
998 if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
999 printf("NOTRANSL\n");
1000 continue;
1003 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1005 printf("EXIST %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1006 if (compare(langnode->res, mainres))
1008 printf("DIFF %03x:%02x\n", langnode->lang.id, langnode->lang.sub);