mshtml: Remove superfluous semicolons.
[wine/wine64.git] / tools / wrc / translation.c
blob7262a65847663a86be8a3f18c807a3f8e244c3c5
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_dlgex:
51 return *resource->res.dlgex->lvc.language;
52 case res_fnt:
53 return *resource->res.fnt->data->lvc.language;
54 case res_fntdir:
55 return *resource->res.fnd->data->lvc.language;
56 case res_ico:
57 return *resource->res.ico->lvc.language;
58 case res_icog:
59 return *resource->res.icog->lvc.language;
60 case res_men:
61 return *resource->res.men->lvc.language;
62 case res_menex:
63 return *resource->res.menex->lvc.language;
64 case res_rdt:
65 return *resource->res.rdt->data->lvc.language;
66 case res_stt:
67 return *resource->res.stt->lvc.language;
68 case res_usr:
69 return *resource->res.usr->data->lvc.language;
70 case res_msg:
71 return *resource->res.msg->data->lvc.language;
72 case res_ver:
73 return *resource->res.ver->lvc.language;
74 case res_dlginit:
75 return *resource->res.dlgi->data->lvc.language;
76 case res_toolbar:
77 return *resource->res.tbt->lvc.language;
78 case res_anicur:
79 case res_aniico:
80 return *resource->res.ani->data->lvc.language;
81 case res_html:
82 return *resource->res.html->data->lvc.language;
83 default:
84 /* Not supposed to reach here */
85 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
86 abort();
90 static int get_language_id(resource_t *resource) {
91 return get_language(resource).id;
94 static int compare_lang(language_t lang1, language_t lang2)
96 return memcmp(&lang1, &lang2, sizeof(language_t));
99 #if 0
101 #define PRETTYPRINTLANG(langid) \
102 if(LANG_##langid == lid) { \
103 return #langid; \
106 static const char *get_language_name(int lid) {
107 PRETTYPRINTLANG(NEUTRAL)
108 PRETTYPRINTLANG(AFRIKAANS)
109 PRETTYPRINTLANG(ALBANIAN)
110 PRETTYPRINTLANG(ARABIC)
111 PRETTYPRINTLANG(ARMENIAN)
112 PRETTYPRINTLANG(ASSAMESE)
113 PRETTYPRINTLANG(AZERI)
114 PRETTYPRINTLANG(BASQUE)
115 PRETTYPRINTLANG(BELARUSIAN)
116 PRETTYPRINTLANG(BENGALI)
117 PRETTYPRINTLANG(BULGARIAN)
118 PRETTYPRINTLANG(CATALAN)
119 PRETTYPRINTLANG(CHINESE)
120 PRETTYPRINTLANG(CROATIAN)
121 PRETTYPRINTLANG(CZECH)
122 PRETTYPRINTLANG(DANISH)
123 PRETTYPRINTLANG(DIVEHI)
124 PRETTYPRINTLANG(DUTCH)
125 PRETTYPRINTLANG(ENGLISH)
126 PRETTYPRINTLANG(ESTONIAN)
127 PRETTYPRINTLANG(FAEROESE)
128 PRETTYPRINTLANG(FARSI)
129 PRETTYPRINTLANG(FINNISH)
130 PRETTYPRINTLANG(FRENCH)
131 PRETTYPRINTLANG(GALICIAN)
132 PRETTYPRINTLANG(GEORGIAN)
133 PRETTYPRINTLANG(GERMAN)
134 PRETTYPRINTLANG(GREEK)
135 PRETTYPRINTLANG(GUJARATI)
136 PRETTYPRINTLANG(HEBREW)
137 PRETTYPRINTLANG(HINDI)
138 PRETTYPRINTLANG(HUNGARIAN)
139 PRETTYPRINTLANG(ICELANDIC)
140 PRETTYPRINTLANG(INDONESIAN)
141 PRETTYPRINTLANG(ITALIAN)
142 PRETTYPRINTLANG(JAPANESE)
143 PRETTYPRINTLANG(KANNADA)
144 PRETTYPRINTLANG(KASHMIRI)
145 PRETTYPRINTLANG(KAZAK)
146 PRETTYPRINTLANG(KONKANI)
147 PRETTYPRINTLANG(KOREAN)
148 PRETTYPRINTLANG(KYRGYZ)
149 PRETTYPRINTLANG(LATVIAN)
150 PRETTYPRINTLANG(LITHUANIAN)
151 PRETTYPRINTLANG(MACEDONIAN)
152 PRETTYPRINTLANG(MALAY)
153 PRETTYPRINTLANG(MALAYALAM)
154 PRETTYPRINTLANG(MANIPURI)
155 PRETTYPRINTLANG(MARATHI)
156 PRETTYPRINTLANG(MONGOLIAN)
157 PRETTYPRINTLANG(NEPALI)
158 PRETTYPRINTLANG(NORWEGIAN)
159 PRETTYPRINTLANG(ORIYA)
160 PRETTYPRINTLANG(POLISH)
161 PRETTYPRINTLANG(PORTUGUESE)
162 PRETTYPRINTLANG(PUNJABI)
163 PRETTYPRINTLANG(ROMANIAN)
164 PRETTYPRINTLANG(RUSSIAN)
165 PRETTYPRINTLANG(SANSKRIT)
166 PRETTYPRINTLANG(SERBIAN)
167 PRETTYPRINTLANG(SINDHI)
168 PRETTYPRINTLANG(SLOVAK)
169 PRETTYPRINTLANG(SLOVENIAN)
170 PRETTYPRINTLANG(SPANISH)
171 PRETTYPRINTLANG(SWAHILI)
172 PRETTYPRINTLANG(SWEDISH)
173 PRETTYPRINTLANG(SYRIAC)
174 PRETTYPRINTLANG(TAMIL)
175 PRETTYPRINTLANG(TATAR)
176 PRETTYPRINTLANG(TELUGU)
177 PRETTYPRINTLANG(THAI)
178 PRETTYPRINTLANG(TURKISH)
179 PRETTYPRINTLANG(UKRAINIAN)
180 PRETTYPRINTLANG(URDU)
181 PRETTYPRINTLANG(UZBEK)
182 PRETTYPRINTLANG(VIETNAMESE)
183 PRETTYPRINTLANG(GAELIC)
184 PRETTYPRINTLANG(MALTESE)
185 PRETTYPRINTLANG(MAORI)
186 PRETTYPRINTLANG(RHAETO_ROMANCE)
187 PRETTYPRINTLANG(SAAMI)
188 PRETTYPRINTLANG(SORBIAN)
189 PRETTYPRINTLANG(SUTU)
190 PRETTYPRINTLANG(TSONGA)
191 PRETTYPRINTLANG(TSWANA)
192 PRETTYPRINTLANG(VENDA)
193 PRETTYPRINTLANG(XHOSA)
194 PRETTYPRINTLANG(ZULU)
195 PRETTYPRINTLANG(ESPERANTO)
196 PRETTYPRINTLANG(WALON)
197 PRETTYPRINTLANG(CORNISH)
198 PRETTYPRINTLANG(WELSH)
199 PRETTYPRINTLANG(BRETON)
200 return "Unknown language";
202 #endif
204 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
205 int different = 0;
206 event_t *ev1 = NULL, *ev2 = NULL;
207 if(!different &&
208 ((accelerator1->memopt != accelerator2->memopt) ||
209 (accelerator1->lvc.version != accelerator2->lvc.version) ||
210 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
211 different = 1;
212 ev1 = accelerator1->events;
213 ev2 = accelerator2->events;
214 while(!different && ev1 && ev2) {
215 if(!different &&
216 ((ev1->id != ev2->id) ||
217 (ev1->flags != ev2->flags)))
218 different = 1;
219 ev1 = ev1->next;
220 ev2 = ev2->next;
222 if(!different &&
223 ((ev1 && !ev2) || (!ev1 && ev2)))
224 different = 1;
225 return different;
228 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
229 int different = 0;
230 if(!different &&
231 ((bitmap1->memopt != bitmap2->memopt) ||
232 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
233 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
234 different = 1;
235 return different;
238 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
239 int different = 0;
240 if(!different &&
241 ((cursor1->id != cursor2->id) ||
242 (cursor1->width != cursor2->width) ||
243 (cursor1->height != cursor2->height) ||
244 (cursor1->xhot != cursor2->xhot) ||
245 (cursor1->yhot != cursor2->yhot)))
246 different = 1;
247 if(!different &&
248 ((cursor1->lvc.version != cursor2->lvc.version) ||
249 (cursor1->lvc.characts != cursor2->lvc.characts)))
250 different = 1;
251 return different;
254 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
255 int different = 0;
256 cursor_t *cursor1 = NULL, *cursor2 = NULL;
257 if(!different &&
258 ((cursor_group1->memopt != cursor_group2->memopt) ||
259 (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
260 (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
261 different = 1;
262 if(!different &&
263 (cursor_group1->ncursor != cursor_group2->ncursor))
264 different = 1;
265 if(!different) {
266 cursor1 = cursor_group1->cursorlist;
267 cursor2 = cursor_group2->cursorlist;
268 while(!different && cursor1 && cursor2) {
269 different = compare_cursor(cursor1, cursor2);
270 cursor1 = cursor1->next;
271 cursor2 = cursor2->next;
273 if(!different &&
274 ((cursor1 && !cursor2) ||
275 (!cursor1 && cursor2)))
276 different = 1;
278 return different;
281 static int compare_control(control_t *control1, control_t *control2) {
282 int different = 0;
283 char *nameid = NULL;
284 int ignore_style;
285 if(!different &&
286 ((control1 && !control2) ||
287 (!control1 && control2)))
288 different = 1;
289 if(different || !control1 || !control2)
290 return different;
291 nameid = strdup(get_nameid_str(control1->ctlclass));
292 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
293 different = 1;
294 free(nameid);
295 if (different)
296 return different;
298 /* allow the translators to set some styles */
299 ignore_style = 0;
300 if (control1->ctlclass->type == name_ord && control1->ctlclass->name.i_name == CT_BUTTON)
301 ignore_style = 0x2000; /* BS_MULTILINE*/
303 if(!different &&
304 (control1->id != control2->id))
305 different = 1;
306 if(!different && control1->gotstyle && control2->gotstyle) {
307 if((!control1->style || !control2->style) ||
308 (control1->style->and_mask || control2->style->and_mask) ||
309 ((control1->style->or_mask & ~ignore_style) != (control2->style->or_mask & ~ignore_style)))
310 different = 1;
311 } else if(!different &&
312 ((control1->gotstyle && !control2->gotstyle) ||
313 (!control1->gotstyle && control2->gotstyle)))
314 different = 1;
315 if(!different && control1->gotexstyle && control2->gotexstyle) {
316 if((!control1->exstyle || !control2->exstyle) ||
317 (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
318 (control1->exstyle->or_mask != control2->exstyle->or_mask))
319 different = 1;
320 } else if(!different &&
321 ((control1->gotexstyle && !control2->gotexstyle) ||
322 (!control1->gotexstyle && control2->gotexstyle)))
323 different = 1;
324 if(!different && control1->gothelpid && control2->gothelpid) {
325 if(control1->helpid != control2->helpid)
326 different = 1;
327 } else if(!different &&
328 ((control1->gothelpid && !control2->gothelpid) ||
329 (!control1->gothelpid && control2->gothelpid)))
330 different = 1;
331 return different;
334 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
335 int different = 0;
336 char *nameid = NULL;
337 control_t *ctrl1, *ctrl2;
338 if(!different &&
339 ((dialog1->memopt != dialog2->memopt) ||
340 (dialog1->lvc.version != dialog2->lvc.version) ||
341 (dialog1->lvc.characts != dialog2->lvc.characts)))
342 different = 1;
343 if(!different && dialog1->gotstyle && dialog2->gotstyle) {
344 if((!dialog1->style || !dialog2->style) ||
345 (dialog1->style->and_mask || dialog2->style->and_mask) ||
346 (dialog1->style->or_mask != dialog2->style->or_mask))
347 different = 1;
348 } else if(!different &&
349 ((dialog1->gotstyle && !dialog2->gotstyle) ||
350 (!dialog1->gotstyle && dialog2->gotstyle)))
351 different = 1;
352 if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
353 if((!dialog1->exstyle || !dialog2->exstyle) ||
354 (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
355 (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
356 different = 1;
357 } else if(!different &&
358 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
359 (!dialog1->gotexstyle && dialog2->gotexstyle)))
360 different = 1;
361 nameid = strdup(get_nameid_str(dialog1->menu));
362 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
363 different = 1;
364 free(nameid);
365 nameid = strdup(get_nameid_str(dialog1->dlgclass));
366 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
367 different = 1;
368 free(nameid);
370 ctrl1 = dialog1->controls;
371 ctrl2 = dialog2->controls;
372 while(!different && (ctrl1 || ctrl2))
374 different = compare_control(ctrl1, ctrl2);
375 if (ctrl1) ctrl1 = ctrl1->next;
376 if (ctrl2) ctrl2 = ctrl2->next;
378 return different;
381 static int compare_dialogex(dialogex_t *dialogex1, dialogex_t *dialogex2) {
382 int different = 0;
383 char *nameid = NULL;
384 control_t *ctrl1, *ctrl2;
385 if(!different &&
386 ((dialogex1->memopt != dialogex2->memopt) ||
387 (dialogex1->lvc.version != dialogex2->lvc.version) ||
388 (dialogex1->lvc.characts != dialogex2->lvc.characts)))
389 different = 1;
390 if(!different && dialogex1->gotstyle && dialogex2->gotstyle) {
391 if((!dialogex1->style || !dialogex2->style) ||
392 (dialogex1->style->and_mask || dialogex2->style->and_mask) ||
393 (dialogex1->style->or_mask != dialogex2->style->or_mask))
394 different = 1;
395 } else if(!different &&
396 ((dialogex1->gotstyle && !dialogex2->gotstyle) ||
397 (!dialogex1->gotstyle && dialogex2->gotstyle)))
398 different = 1;
399 if(!different && dialogex1->gotexstyle && dialogex2->gotexstyle) {
400 if((!dialogex1->exstyle || !dialogex2->exstyle) ||
401 (dialogex1->exstyle->and_mask || dialogex2->exstyle->and_mask) ||
402 (dialogex1->exstyle->or_mask != dialogex2->exstyle->or_mask))
403 different = 1;
404 } else if(!different &&
405 ((dialogex1->gotexstyle && !dialogex2->gotexstyle) ||
406 (!dialogex1->gotexstyle && dialogex2->gotexstyle)))
407 different = 1;
408 if(!different && dialogex1->gothelpid && dialogex2->gothelpid) {
409 if(dialogex1->helpid != dialogex2->helpid)
410 different = 1;
411 } else if(!different &&
412 ((dialogex1->gothelpid && !dialogex2->gothelpid) ||
413 (!dialogex1->gothelpid && dialogex2->gothelpid)))
414 different = 1;
415 nameid = strdup(get_nameid_str(dialogex1->menu));
416 if(!different && strcmp(nameid, get_nameid_str(dialogex2->menu)))
417 different = 1;
418 free(nameid);
419 nameid = strdup(get_nameid_str(dialogex1->dlgclass));
420 if(!different && strcmp(nameid, get_nameid_str(dialogex2->dlgclass)))
421 different = 1;
422 free(nameid);
424 ctrl1 = dialogex1->controls;
425 ctrl2 = dialogex2->controls;
426 while(!different && (ctrl1 || ctrl2))
428 different = compare_control(ctrl1, ctrl2);
429 if (ctrl1) ctrl1 = ctrl1->next;
430 if (ctrl2) ctrl2 = ctrl2->next;
432 return different;
435 static int compare_font(font_t *font1, font_t *font2) {
436 int different = 0;
437 if(!different &&
438 ((font1->memopt != font2->memopt) ||
439 (font1->data->lvc.version != font2->data->lvc.version) ||
440 (font1->data->lvc.characts != font2->data->lvc.characts)))
441 different = 1;
442 return different;
445 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
446 int different = 0;
447 if(!different &&
448 ((fontdir1->memopt != fontdir2->memopt) ||
449 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
450 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
451 different = 1;
452 return different;
455 static int compare_icon(icon_t *icon1, icon_t *icon2) {
456 int different = 0;
457 if(!different &&
458 ((icon1->id != icon2->id) ||
459 (icon1->width != icon2->width) ||
460 (icon1->height != icon2->height)))
461 different = 1;
462 if(!different &&
463 ((icon1->lvc.version != icon2->lvc.version) ||
464 (icon1->lvc.characts != icon2->lvc.characts)))
465 different = 1;
466 return different;
469 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
470 int different = 0;
471 icon_t *icon1 = NULL, *icon2 = NULL;
472 if(!different &&
473 ((icon_group1->memopt != icon_group2->memopt) ||
474 (icon_group1->lvc.version != icon_group2->lvc.version) ||
475 (icon_group1->lvc.characts != icon_group2->lvc.characts)))
476 different = 1;
477 if(!different &&
478 (icon_group1->nicon != icon_group2->nicon))
479 different = 1;
480 if(!different) {
481 icon1 = icon_group1->iconlist;
482 icon2 = icon_group2->iconlist;
483 while(!different && icon1 && icon2) {
484 different = compare_icon(icon1, icon2);
485 icon1 = icon1->next;
486 icon2 = icon2->next;
488 if(!different &&
489 ((icon1 && !icon2) ||
490 (!icon1 && icon2)))
491 different = 1;
493 return different;
496 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
497 int different = 0;
498 while(!different && menu_item1 && menu_item2) {
499 if(menu_item1->popup && menu_item2->popup)
500 different = compare_menu_item(menu_item1->popup, menu_item2->popup);
501 else if(!menu_item1->popup && !menu_item2->popup) {
502 if(menu_item1->name && menu_item2->name) {
503 if((menu_item1->id != menu_item2->id) ||
504 (menu_item1->state != menu_item2->state))
505 different = 1;
506 } else if((menu_item1->name && !menu_item2->name) ||
507 (!menu_item1->name && menu_item2->name))
508 different = 1;
509 } else
510 different = 1;
511 menu_item1 = menu_item1->next;
512 menu_item2 = menu_item2->next;
514 if(!different &&
515 ((menu_item1 && !menu_item2) ||
516 (!menu_item1 && menu_item2)))
517 different = 1;
518 return different;
521 static int compare_menu(menu_t *menu1, menu_t *menu2) {
522 int different = 0;
523 if(!different &&
524 ((menu1->memopt != menu2->memopt) ||
525 (menu1->lvc.version != menu2->lvc.version) ||
526 (menu1->lvc.characts != menu2->lvc.characts)))
527 different = 1;
528 if(!different)
529 different = compare_menu_item(menu1->items, menu2->items);
530 return different;
533 static int compare_menuex_item(menuex_item_t *menuex_item1, menuex_item_t *menuex_item2) {
534 int different = 0;
535 while(!different && menuex_item1 && menuex_item2) {
536 if(menuex_item1->popup && menuex_item2->popup) {
537 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
538 if(menuex_item1->id != menuex_item2->id)
539 different = 1;
540 } else if(!different &&
541 ((menuex_item1->gotid && !menuex_item2->gotid) ||
542 (!menuex_item2->gotid && menuex_item2->gotid)))
543 different = 1;
544 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
545 if(menuex_item1->type != menuex_item2->type)
546 different = 1;
547 } else if(!different &&
548 ((menuex_item1->gottype && !menuex_item2->gottype) ||
549 (!menuex_item2->gottype && menuex_item2->gottype)))
550 different = 1;
551 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
552 if(menuex_item1->state != menuex_item2->state)
553 different = 1;
554 } else if(!different &&
555 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
556 (!menuex_item2->gotstate && menuex_item2->gotstate)))
557 different = 1;
558 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
559 if(menuex_item1->helpid != menuex_item2->helpid)
560 different = 1;
561 } else if(!different &&
562 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
563 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
564 different = 1;
565 if(!different)
566 different = compare_menuex_item(menuex_item1->popup, menuex_item2->popup);
567 } else if(!menuex_item1->popup && !menuex_item2->popup) {
568 if(menuex_item1->name && menuex_item2->name) {
569 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
570 if(menuex_item1->id != menuex_item2->id)
571 different = 1;
572 } else if(!different &&
573 ((menuex_item1->gotid && !menuex_item2->gotid) ||
574 (!menuex_item2->gotid && menuex_item2->gotid)))
575 different = 1;
576 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
577 if(menuex_item1->type != menuex_item2->type)
578 different = 1;
579 } else if(!different &&
580 ((menuex_item1->gottype && !menuex_item2->gottype) ||
581 (!menuex_item2->gottype && menuex_item2->gottype)))
582 different = 1;
583 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
584 if(menuex_item1->state != menuex_item2->state)
585 different = 1;
586 } else if(!different &&
587 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
588 (!menuex_item2->gotstate && menuex_item2->gotstate)))
589 different = 1;
590 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
591 if(menuex_item1->helpid != menuex_item2->helpid)
592 different = 1;
593 } else if(!different &&
594 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
595 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
596 different = 1;
597 } else if((menuex_item1->name && !menuex_item2->name) ||
598 (!menuex_item1->name && menuex_item2->name))
599 different = 1;
600 } else
601 different = 1;
602 menuex_item1 = menuex_item1->next;
603 menuex_item2 = menuex_item2->next;
605 if(!different &&
606 ((menuex_item1 && !menuex_item2) ||
607 (!menuex_item1 && menuex_item2)))
608 different = 1;
609 return different;
612 static int compare_menuex(menuex_t *menuex1, menuex_t *menuex2) {
613 int different = 0;
614 if(!different &&
615 ((menuex1->memopt != menuex2->memopt) ||
616 (menuex1->lvc.version != menuex2->lvc.version) ||
617 (menuex1->lvc.characts != menuex2->lvc.characts)))
618 different = 1;
619 if(!different)
620 different = compare_menuex_item(menuex1->items, menuex2->items);
621 return different;
624 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
625 int different = 0;
626 if(!different &&
627 ((rcdata1->memopt != rcdata2->memopt) ||
628 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
629 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
630 different = 1;
631 return different;
634 static int compare_html(html_t *rcdata1, html_t *rcdata2) {
635 int different = 0;
636 if(!different &&
637 ((rcdata1->memopt != rcdata2->memopt) ||
638 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
639 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
640 different = 1;
641 return different;
644 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
645 int different = 0;
646 int i;
647 while(!different && stringtable1 && stringtable2) {
648 if((stringtable1->memopt != stringtable2->memopt) ||
649 (stringtable1->lvc.version != stringtable2->lvc.version) ||
650 (stringtable1->lvc.characts != stringtable2->lvc.characts))
651 different = 1;
652 if(!different) {
653 if((stringtable1->nentries != stringtable2->nentries) ||
654 (stringtable1->idbase != stringtable2->idbase))
655 different = 1;
656 else
657 for(i = 0 ; i < stringtable1->nentries; i++)
658 if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
659 (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
660 (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
661 (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
662 different = 1;
663 break;
666 stringtable1 = stringtable1->next;
667 stringtable2 = stringtable2->next;
669 return different;
672 static int compare_user(user_t *user1, user_t *user2) {
673 int different = 0;
674 char *nameid = NULL;
675 if(!different &&
676 ((user1->memopt != user2->memopt) ||
677 (user1->data->lvc.version != user2->data->lvc.version) ||
678 (user1->data->lvc.characts != user2->data->lvc.characts)))
679 different = 1;
680 nameid = strdup(get_nameid_str(user1->type));
681 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
682 different = 1;
683 free(nameid);
684 return different;
687 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
688 int different = 0;
689 if(!different &&
690 ((messagetable1->memopt != messagetable2->memopt) ||
691 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
692 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
693 different = 1;
694 return different;
697 static int compare_string(string_t *string1, string_t *string2) {
698 int different = 0;
699 if(!different &&
700 ((string1->size != string2->size) ||
701 (string1->type != string2->type)))
702 different = 1;
703 if(!different) {
704 if(string1->type == str_char)
705 different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
706 else if(string1->type == str_unicode)
707 different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
708 else
709 different = 1;
711 return different;
714 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
716 static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
717 int different = 0;
718 int i = 0;
719 if(!different &&
720 (ver_value1->type == ver_value2->type)) {
721 switch(ver_value1->type) {
722 case val_str:
723 if(!different && ver_value1->key && ver_value2->key)
724 different = compare_string(ver_value1->key, ver_value2->key);
725 else if(!different &&
726 ((ver_value1->key && !ver_value2->key) ||
727 (!ver_value1->key && ver_value2->key)))
728 different = 1;
729 break;
730 case val_words:
731 if(!different && ver_value1->key && ver_value2->key)
732 different = compare_string(ver_value1->key, ver_value2->key);
733 else if(!different &&
734 ((ver_value1->key && !ver_value2->key) ||
735 (!ver_value1->key && ver_value2->key)))
736 different = 1;
737 if(!different && ver_value1->value.words && ver_value2->value.words) {
738 if(!different &&
739 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
740 different = 1;
741 if(!different)
742 for(i = 0; i < ver_value1->value.words->nwords; i++) {
743 if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
744 different = 1;
745 break;
748 } else if(!different &&
749 ((ver_value1->value.words && !ver_value2->value.words) ||
750 (!ver_value1->value.words && ver_value2->value.words)))
751 different = 1;
752 break;
753 case val_block:
754 if(!different && ver_value1->value.block && ver_value2->value.block)
755 different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
756 else if(!different &&
757 ((ver_value1->value.block && !ver_value2->value.block) ||
758 (!ver_value1->value.block && ver_value2->value.block)))
759 different = 1;
760 break;
761 default:
762 different = 1;
764 } else
765 different = 1;
766 return different;
769 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
770 int different = 0;
771 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
772 if(!different) {
773 ver_value1 = ver_block1->values;
774 ver_value2 = ver_block2->values;
775 while(!different && ver_value1 && ver_value2) {
776 different = compare_ver_value(ver_value1, ver_value2);
777 ver_value1 = ver_value1->next;
778 ver_value2 = ver_value2->next;
780 if(!different &&
781 ((ver_value1 && !ver_value2) ||
782 (!ver_value1 && ver_value2)))
783 different = 1;
785 return different;
788 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
789 int different = 0;
790 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
791 if(!different &&
792 ((versioninfo1->memopt != versioninfo2->memopt) ||
793 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
794 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
795 different = 1;
796 if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
797 if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
798 (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
799 (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
800 (versioninfo1->filever_min2 != versioninfo2->filever_min2))
801 different = 1;
802 } else if(!different &&
803 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
804 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
805 different = 1;
806 if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
807 if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
808 (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
809 (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
810 (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
811 different = 1;
812 } else if(!different &&
813 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
814 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
815 different = 1;
816 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
817 if(versioninfo1->fileos != versioninfo2->fileos)
818 different = 1;
819 } else if(!different &&
820 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
821 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
822 different = 1;
823 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
824 if(versioninfo1->fileflags != versioninfo2->fileflags)
825 different = 1;
826 } else if(!different &&
827 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
828 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
829 different = 1;
830 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
831 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
832 different = 1;
833 } else if(!different &&
834 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
835 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
836 different = 1;
837 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
838 if(versioninfo1->filetype != versioninfo2->filetype)
839 different = 1;
840 } else if(!different &&
841 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
842 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
843 different = 1;
844 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
845 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
846 different = 1;
847 } else if(!different &&
848 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
849 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
850 different = 1;
851 if(!different) {
852 ver_block1 = versioninfo1->blocks;
853 ver_block2 = versioninfo2->blocks;
854 while(!different && ver_block1 && ver_block2) {
855 different = compare_ver_block(ver_block1, ver_block2);
856 ver_block1 = ver_block1->next;
857 ver_block2 = ver_block2->next;
859 if(!different &&
860 ((ver_block1 && !ver_block2) ||
861 (!ver_block1 && ver_block2)))
862 different = 1;
864 return different;
867 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
868 int different = 0;
869 if(!different &&
870 ((dlginit1->memopt != dlginit2->memopt) ||
871 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
872 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
873 different = 1;
874 return different;
877 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
878 int different = 0;
879 while(!different && toolbar_item1 && toolbar_item2) {
880 if((toolbar_item1->id && !toolbar_item2->id) ||
881 (!toolbar_item1->id && toolbar_item2->id))
882 different = 1;
883 toolbar_item1 = toolbar_item1->next;
884 toolbar_item2 = toolbar_item2->next;
886 if(!different &&
887 ((toolbar_item1 && !toolbar_item2) ||
888 (!toolbar_item1 && toolbar_item2)))
889 different = 1;
890 return different;
893 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
894 int different = 0;
895 if(!different &&
896 ((toolbar1->memopt != toolbar2->memopt) ||
897 (toolbar1->lvc.version != toolbar2->lvc.version) ||
898 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
899 different = 1;
900 if(!different)
901 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
902 return different;
905 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
906 int different = 0;
907 if(!different &&
908 ((ani_curico1->memopt != ani_curico2->memopt) ||
909 (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
910 (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
911 different = 1;
912 return different;
915 static int compare(resource_t *resource1, resource_t *resource2) {
916 switch(resource1->type) {
917 case res_acc:
918 return compare_accelerator(resource1->res.acc, resource2->res.acc);
919 case res_bmp:
920 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
921 case res_cur:
922 return compare_cursor(resource1->res.cur, resource2->res.cur);
923 case res_curg:
924 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
925 case res_dlg:
926 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
927 case res_dlgex:
928 return compare_dialogex(resource1->res.dlgex, resource2->res.dlgex);
929 case res_fnt:
930 return compare_font(resource1->res.fnt, resource2->res.fnt);
931 case res_fntdir:
932 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
933 case res_ico:
934 return compare_icon(resource1->res.ico, resource2->res.ico);
935 case res_icog:
936 return compare_icon_group(resource1->res.icog, resource2->res.icog);
937 case res_men:
938 return compare_menu(resource1->res.men, resource2->res.men);
939 case res_menex:
940 return compare_menuex(resource1->res.menex, resource2->res.menex);
941 case res_rdt:
942 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
943 case res_stt:
944 return compare_stringtable(resource1->res.stt, resource2->res.stt);
945 case res_usr:
946 return compare_user(resource1->res.usr, resource2->res.usr);
947 case res_html:
948 return compare_html(resource1->res.html, resource2->res.html);
949 case res_msg:
950 return compare_messagetable(resource1->res.msg, resource2->res.msg);
951 case res_ver:
952 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
953 case res_dlginit:
954 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
955 case res_toolbar:
956 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
957 case res_anicur:
958 case res_aniico:
959 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
960 default:
961 /* Not supposed to reach here */
962 fprintf(stderr, "Not supposed to reach here (compare())\n");
963 abort();
964 return -1;
968 typedef struct resource_lang_node
970 language_t lang;
971 resource_t *res;
972 struct resource_lang_node *next;
973 } resource_lang_node_t;
975 typedef struct resource_id_node
977 name_id_t *id;
978 resource_lang_node_t *langs;
979 struct resource_id_node *next;
980 } resource_id_node_t;
982 struct
984 int enabled;
985 struct resource_id_node *ids;
986 } verify_tab[res_usr+1];
988 static void add_resource(resource_t *res)
990 resource_id_node_t *idnode;
991 resource_lang_node_t *langnode;
992 if (!verify_tab[res->type].enabled)
994 fprintf(stderr, "ERR: Report this: unknown resource type parsed %08x\n", res->type);
995 return;
998 for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
999 if (compare_name_id(idnode->id, res->name) == 0)
1000 break;
1002 if (idnode == NULL)
1004 idnode = xmalloc(sizeof(resource_id_node_t));
1005 idnode->id = res->name;
1006 idnode->langs = NULL;
1007 idnode->next = verify_tab[res->type].ids;
1008 verify_tab[res->type].ids = idnode;
1011 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1012 if (compare_lang(langnode->lang, get_language(res)) == 0)
1014 fprintf(stderr, "ERR: resource %s [type %x] language %03x:%02x duplicated!\n",
1015 get_nameid_str(res->name), res->type, langnode->lang.id, langnode->lang.sub);
1016 return;
1019 langnode = xmalloc(sizeof(resource_lang_node_t));
1020 langnode->res = res;
1021 langnode->lang = get_language(res);
1022 langnode->next = idnode->langs;
1023 idnode->langs = langnode;
1026 static void setup_tabs(void)
1028 int i;
1030 for (i = 0; i <= res_usr; i++)
1031 switch(i) {
1032 case res_acc:
1033 case res_bmp:
1034 case res_cur:
1035 case res_curg:
1036 case res_dlg:
1037 case res_dlgex:
1038 case res_fnt:
1039 case res_fntdir:
1040 case res_ico:
1041 case res_icog:
1042 case res_men:
1043 case res_menex:
1044 case res_rdt:
1045 case res_stt:
1046 case res_usr:
1047 case res_msg:
1048 case res_ver:
1049 case res_dlginit:
1050 case res_toolbar:
1051 case res_anicur:
1052 case res_aniico:
1053 case res_html:
1054 verify_tab[i].enabled = 1;
1055 break;
1059 static const char *get_typename_for_int(int type) {
1060 resource_t res;
1061 res.type = type;
1062 return get_typename(&res);
1065 static resource_t *find_main(int type, name_id_t *id, resource_lang_node_t *langnode)
1067 resource_t *neutral = NULL, *en = NULL, *en_US = NULL;
1068 for (; langnode; langnode = langnode->next)
1070 if (langnode->lang.id == LANG_NEUTRAL && langnode->lang.sub == SUBLANG_NEUTRAL)
1071 neutral = langnode->res;
1072 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == SUBLANG_NEUTRAL)
1073 en = langnode->res;
1074 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == MASTER_SUBLANGUAGE)
1075 en_US = langnode->res;
1078 if (neutral != NULL && (en != NULL || en_US != NULL))
1080 fprintf(stderr, "INFO: Resource %04x/%s has both NEUTRAL and MASTER language translarion\n",
1081 type, get_nameid_str(id));
1084 if (en_US != NULL) return en_US;
1085 if (en != NULL) return en;
1086 return neutral;
1089 void verify_translations(resource_t *top) {
1090 resource_t *curr = top;
1091 resource_id_node_t *idnode;
1092 resource_lang_node_t *langnode;
1093 int type;
1095 setup_tabs();
1096 while (curr)
1098 add_resource(curr);
1099 curr = curr->next;
1102 for (type = 0; type <= res_usr; type++)
1104 printf("TYPE NEXT [%s]\n", get_typename_for_int(type));
1105 for (idnode = verify_tab[type].ids; idnode; idnode = idnode->next)
1107 resource_t *mainres;
1108 printf("RESOURCE [%s]\n", get_nameid_str(idnode->id));
1110 mainres = find_main(type, idnode->id, idnode->langs);
1111 if (!mainres)
1113 fprintf(stderr, "ERR: resource %04x/%s has translation(s) but not available in NEUTRAL or MASTER language\n",
1114 type, get_nameid_str(idnode->id));
1115 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1116 printf("EXTRA %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1117 continue;
1120 if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
1121 printf("NOTRANSL\n");
1122 continue;
1125 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1127 printf("EXIST %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1128 if (compare(langnode->res, mainres))
1130 printf("DIFF %03x:%02x\n", langnode->lang.id, langnode->lang.sub);