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
28 #define MASTER_LANGUAGE LANG_ENGLISH
29 #define MASTER_SUBLANGUAGE SUBLANG_ENGLISH_US
38 static language_t get_language(resource_t *resource) {
39 switch(resource->type) {
41 return *resource->res.acc->lvc.language;
43 return *resource->res.bmp->data->lvc.language;
45 return *resource->res.cur->lvc.language;
47 return *resource->res.curg->lvc.language;
49 return *resource->res.dlg->lvc.language;
51 return *resource->res.dlgex->lvc.language;
53 return *resource->res.fnt->data->lvc.language;
55 return *resource->res.fnd->data->lvc.language;
57 return *resource->res.ico->lvc.language;
59 return *resource->res.icog->lvc.language;
61 return *resource->res.men->lvc.language;
63 return *resource->res.menex->lvc.language;
65 return *resource->res.rdt->data->lvc.language;
67 return *resource->res.stt->lvc.language;
69 return *resource->res.usr->data->lvc.language;
71 return *resource->res.msg->data->lvc.language;
73 return *resource->res.ver->lvc.language;
75 return *resource->res.dlgi->data->lvc.language;
77 return *resource->res.tbt->lvc.language;
80 return *resource->res.ani->data->lvc.language;
82 return *resource->res.html->data->lvc.language;
84 /* Not supposed to reach here */
85 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
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));
101 #define PRETTYPRINTLANG(langid) \
102 if(LANG_##langid == lid) { \
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";
204 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
206 event_t *ev1 = NULL, *ev2 = NULL;
208 ((accelerator1->memopt != accelerator2->memopt) ||
209 (accelerator1->lvc.version != accelerator2->lvc.version) ||
210 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
212 ev1 = accelerator1->events;
213 ev2 = accelerator2->events;
214 while(!different && ev1 && ev2) {
216 ((ev1->id != ev2->id) ||
217 (ev1->flags != ev2->flags)))
223 ((ev1 && !ev2) || (!ev1 && ev2)))
228 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
231 ((bitmap1->memopt != bitmap2->memopt) ||
232 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
233 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
238 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
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)))
248 ((cursor1->lvc.version != cursor2->lvc.version) ||
249 (cursor1->lvc.characts != cursor2->lvc.characts)))
254 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
256 cursor_t *cursor1 = NULL, *cursor2 = NULL;
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)))
263 (cursor_group1->ncursor != cursor_group2->ncursor))
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;
274 ((cursor1 && !cursor2) ||
275 (!cursor1 && cursor2)))
281 static int compare_control(control_t *control1, control_t *control2) {
286 ((control1 && !control2) ||
287 (!control1 && control2)))
289 if(different || !control1 || !control2)
291 nameid = strdup(get_nameid_str(control1->ctlclass));
292 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
298 /* allow the translators to set some styles */
300 if (control1->ctlclass->type == name_ord && control1->ctlclass->name.i_name == CT_BUTTON)
301 ignore_style = 0x2000; /* BS_MULTILINE*/
304 (control1->id != control2->id))
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)))
311 } else if(!different &&
312 ((control1->gotstyle && !control2->gotstyle) ||
313 (!control1->gotstyle && control2->gotstyle)))
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))
320 } else if(!different &&
321 ((control1->gotexstyle && !control2->gotexstyle) ||
322 (!control1->gotexstyle && control2->gotexstyle)))
324 if(!different && control1->gothelpid && control2->gothelpid) {
325 if(control1->helpid != control2->helpid)
327 } else if(!different &&
328 ((control1->gothelpid && !control2->gothelpid) ||
329 (!control1->gothelpid && control2->gothelpid)))
334 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
337 control_t *ctrl1, *ctrl2;
339 ((dialog1->memopt != dialog2->memopt) ||
340 (dialog1->lvc.version != dialog2->lvc.version) ||
341 (dialog1->lvc.characts != dialog2->lvc.characts)))
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))
348 } else if(!different &&
349 ((dialog1->gotstyle && !dialog2->gotstyle) ||
350 (!dialog1->gotstyle && dialog2->gotstyle)))
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))
357 } else if(!different &&
358 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
359 (!dialog1->gotexstyle && dialog2->gotexstyle)))
361 nameid = strdup(get_nameid_str(dialog1->menu));
362 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
365 nameid = strdup(get_nameid_str(dialog1->dlgclass));
366 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
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;
381 static int compare_dialogex(dialogex_t *dialogex1, dialogex_t *dialogex2) {
384 control_t *ctrl1, *ctrl2;
386 ((dialogex1->memopt != dialogex2->memopt) ||
387 (dialogex1->lvc.version != dialogex2->lvc.version) ||
388 (dialogex1->lvc.characts != dialogex2->lvc.characts)))
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))
395 } else if(!different &&
396 ((dialogex1->gotstyle && !dialogex2->gotstyle) ||
397 (!dialogex1->gotstyle && dialogex2->gotstyle)))
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))
404 } else if(!different &&
405 ((dialogex1->gotexstyle && !dialogex2->gotexstyle) ||
406 (!dialogex1->gotexstyle && dialogex2->gotexstyle)))
408 if(!different && dialogex1->gothelpid && dialogex2->gothelpid) {
409 if(dialogex1->helpid != dialogex2->helpid)
411 } else if(!different &&
412 ((dialogex1->gothelpid && !dialogex2->gothelpid) ||
413 (!dialogex1->gothelpid && dialogex2->gothelpid)))
415 nameid = strdup(get_nameid_str(dialogex1->menu));
416 if(!different && strcmp(nameid, get_nameid_str(dialogex2->menu)))
419 nameid = strdup(get_nameid_str(dialogex1->dlgclass));
420 if(!different && strcmp(nameid, get_nameid_str(dialogex2->dlgclass)))
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;
435 static int compare_font(font_t *font1, font_t *font2) {
438 ((font1->memopt != font2->memopt) ||
439 (font1->data->lvc.version != font2->data->lvc.version) ||
440 (font1->data->lvc.characts != font2->data->lvc.characts)))
445 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
448 ((fontdir1->memopt != fontdir2->memopt) ||
449 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
450 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
455 static int compare_icon(icon_t *icon1, icon_t *icon2) {
458 ((icon1->id != icon2->id) ||
459 (icon1->width != icon2->width) ||
460 (icon1->height != icon2->height)))
463 ((icon1->lvc.version != icon2->lvc.version) ||
464 (icon1->lvc.characts != icon2->lvc.characts)))
469 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
471 icon_t *icon1 = NULL, *icon2 = NULL;
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)))
478 (icon_group1->nicon != icon_group2->nicon))
481 icon1 = icon_group1->iconlist;
482 icon2 = icon_group2->iconlist;
483 while(!different && icon1 && icon2) {
484 different = compare_icon(icon1, icon2);
489 ((icon1 && !icon2) ||
496 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
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))
506 } else if((menu_item1->name && !menu_item2->name) ||
507 (!menu_item1->name && menu_item2->name))
511 menu_item1 = menu_item1->next;
512 menu_item2 = menu_item2->next;
515 ((menu_item1 && !menu_item2) ||
516 (!menu_item1 && menu_item2)))
521 static int compare_menu(menu_t *menu1, menu_t *menu2) {
524 ((menu1->memopt != menu2->memopt) ||
525 (menu1->lvc.version != menu2->lvc.version) ||
526 (menu1->lvc.characts != menu2->lvc.characts)))
529 different = compare_menu_item(menu1->items, menu2->items);
533 static int compare_menuex_item(menuex_item_t *menuex_item1, menuex_item_t *menuex_item2) {
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)
540 } else if(!different &&
541 ((menuex_item1->gotid && !menuex_item2->gotid) ||
542 (!menuex_item2->gotid && menuex_item2->gotid)))
544 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
545 if(menuex_item1->type != menuex_item2->type)
547 } else if(!different &&
548 ((menuex_item1->gottype && !menuex_item2->gottype) ||
549 (!menuex_item2->gottype && menuex_item2->gottype)))
551 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
552 if(menuex_item1->state != menuex_item2->state)
554 } else if(!different &&
555 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
556 (!menuex_item2->gotstate && menuex_item2->gotstate)))
558 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
559 if(menuex_item1->helpid != menuex_item2->helpid)
561 } else if(!different &&
562 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
563 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
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)
572 } else if(!different &&
573 ((menuex_item1->gotid && !menuex_item2->gotid) ||
574 (!menuex_item2->gotid && menuex_item2->gotid)))
576 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
577 if(menuex_item1->type != menuex_item2->type)
579 } else if(!different &&
580 ((menuex_item1->gottype && !menuex_item2->gottype) ||
581 (!menuex_item2->gottype && menuex_item2->gottype)))
583 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
584 if(menuex_item1->state != menuex_item2->state)
586 } else if(!different &&
587 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
588 (!menuex_item2->gotstate && menuex_item2->gotstate)))
590 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
591 if(menuex_item1->helpid != menuex_item2->helpid)
593 } else if(!different &&
594 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
595 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
597 } else if((menuex_item1->name && !menuex_item2->name) ||
598 (!menuex_item1->name && menuex_item2->name))
602 menuex_item1 = menuex_item1->next;
603 menuex_item2 = menuex_item2->next;
606 ((menuex_item1 && !menuex_item2) ||
607 (!menuex_item1 && menuex_item2)))
612 static int compare_menuex(menuex_t *menuex1, menuex_t *menuex2) {
615 ((menuex1->memopt != menuex2->memopt) ||
616 (menuex1->lvc.version != menuex2->lvc.version) ||
617 (menuex1->lvc.characts != menuex2->lvc.characts)))
620 different = compare_menuex_item(menuex1->items, menuex2->items);
624 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
627 ((rcdata1->memopt != rcdata2->memopt) ||
628 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
629 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
634 static int compare_html(html_t *rcdata1, html_t *rcdata2) {
637 ((rcdata1->memopt != rcdata2->memopt) ||
638 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
639 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
644 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
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))
653 if((stringtable1->nentries != stringtable2->nentries) ||
654 (stringtable1->idbase != stringtable2->idbase))
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)) {
666 stringtable1 = stringtable1->next;
667 stringtable2 = stringtable2->next;
672 static int compare_user(user_t *user1, user_t *user2) {
676 ((user1->memopt != user2->memopt) ||
677 (user1->data->lvc.version != user2->data->lvc.version) ||
678 (user1->data->lvc.characts != user2->data->lvc.characts)))
680 nameid = strdup(get_nameid_str(user1->type));
681 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
687 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
690 ((messagetable1->memopt != messagetable2->memopt) ||
691 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
692 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
697 static int compare_string(string_t *string1, string_t *string2) {
700 ((string1->size != string2->size) ||
701 (string1->type != string2->type)))
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));
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) {
720 (ver_value1->type == ver_value2->type)) {
721 switch(ver_value1->type) {
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)))
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)))
737 if(!different && ver_value1->value.words && ver_value2->value.words) {
739 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
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]) {
748 } else if(!different &&
749 ((ver_value1->value.words && !ver_value2->value.words) ||
750 (!ver_value1->value.words && ver_value2->value.words)))
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)))
769 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
771 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
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;
781 ((ver_value1 && !ver_value2) ||
782 (!ver_value1 && ver_value2)))
788 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
790 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
792 ((versioninfo1->memopt != versioninfo2->memopt) ||
793 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
794 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
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))
802 } else if(!different &&
803 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
804 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
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))
812 } else if(!different &&
813 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
814 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
816 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
817 if(versioninfo1->fileos != versioninfo2->fileos)
819 } else if(!different &&
820 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
821 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
823 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
824 if(versioninfo1->fileflags != versioninfo2->fileflags)
826 } else if(!different &&
827 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
828 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
830 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
831 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
833 } else if(!different &&
834 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
835 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
837 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
838 if(versioninfo1->filetype != versioninfo2->filetype)
840 } else if(!different &&
841 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
842 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
844 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
845 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
847 } else if(!different &&
848 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
849 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
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;
860 ((ver_block1 && !ver_block2) ||
861 (!ver_block1 && ver_block2)))
867 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
870 ((dlginit1->memopt != dlginit2->memopt) ||
871 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
872 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
877 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
879 while(!different && toolbar_item1 && toolbar_item2) {
880 if((toolbar_item1->id && !toolbar_item2->id) ||
881 (!toolbar_item1->id && toolbar_item2->id))
883 toolbar_item1 = toolbar_item1->next;
884 toolbar_item2 = toolbar_item2->next;
887 ((toolbar_item1 && !toolbar_item2) ||
888 (!toolbar_item1 && toolbar_item2)))
893 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
896 ((toolbar1->memopt != toolbar2->memopt) ||
897 (toolbar1->lvc.version != toolbar2->lvc.version) ||
898 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
901 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
905 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
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)))
915 static int compare(resource_t *resource1, resource_t *resource2) {
916 switch(resource1->type) {
918 return compare_accelerator(resource1->res.acc, resource2->res.acc);
920 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
922 return compare_cursor(resource1->res.cur, resource2->res.cur);
924 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
926 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
928 return compare_dialogex(resource1->res.dlgex, resource2->res.dlgex);
930 return compare_font(resource1->res.fnt, resource2->res.fnt);
932 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
934 return compare_icon(resource1->res.ico, resource2->res.ico);
936 return compare_icon_group(resource1->res.icog, resource2->res.icog);
938 return compare_menu(resource1->res.men, resource2->res.men);
940 return compare_menuex(resource1->res.menex, resource2->res.menex);
942 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
944 return compare_stringtable(resource1->res.stt, resource2->res.stt);
946 return compare_user(resource1->res.usr, resource2->res.usr);
948 return compare_html(resource1->res.html, resource2->res.html);
950 return compare_messagetable(resource1->res.msg, resource2->res.msg);
952 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
954 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
956 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
959 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
961 /* Not supposed to reach here */
962 fprintf(stderr, "Not supposed to reach here (compare())\n");
968 typedef struct resource_lang_node
972 struct resource_lang_node *next;
973 } resource_lang_node_t;
975 typedef struct resource_id_node
978 resource_lang_node_t *langs;
979 struct resource_id_node *next;
980 } resource_id_node_t;
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);
998 for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
999 if (compare_name_id(idnode->id, res->name) == 0)
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);
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)
1030 for (i = 0; i <= res_usr; i++)
1054 verify_tab[i].enabled = 1;
1059 static const char *get_typename_for_int(int 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)
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;
1089 void verify_translations(resource_t *top) {
1090 resource_t *curr = top;
1091 resource_id_node_t *idnode;
1092 resource_lang_node_t *langnode;
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);
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);
1120 if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
1121 printf("NOTRANSL\n");
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);