2 * Copyright 2003 Vincent BĂ©ron
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define MASTER_LANGUAGE LANG_ENGLISH
28 #define MASTER_SUBLANGUAGE SUBLANG_ENGLISH_US
37 static language_t get_language(resource_t *resource) {
38 switch(resource->type) {
40 return *resource->res.acc->lvc.language;
42 return *resource->res.bmp->data->lvc.language;
44 return *resource->res.cur->lvc.language;
46 return *resource->res.curg->lvc.language;
48 return *resource->res.dlg->lvc.language;
50 return *resource->res.dlgex->lvc.language;
52 return *resource->res.fnt->data->lvc.language;
54 return *resource->res.fnd->data->lvc.language;
56 return *resource->res.ico->lvc.language;
58 return *resource->res.icog->lvc.language;
60 return *resource->res.men->lvc.language;
62 return *resource->res.menex->lvc.language;
64 return *resource->res.rdt->data->lvc.language;
66 return *resource->res.stt->lvc.language;
68 return *resource->res.usr->data->lvc.language;
70 return *resource->res.msg->data->lvc.language;
72 return *resource->res.ver->lvc.language;
74 return *resource->res.dlgi->data->lvc.language;
76 return *resource->res.tbt->lvc.language;
79 return *resource->res.ani->data->lvc.language;
81 return *resource->res.html->data->lvc.language;
83 /* Not supposed to reach here */
84 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
89 static int get_language_id(resource_t *resource) {
90 return get_language(resource).id;
93 static int compare_lang(language_t lang1, language_t lang2)
95 return memcmp(&lang1, &lang2, sizeof(language_t));
100 #define PRETTYPRINTLANG(langid) \
101 if(LANG_##langid == lid) { \
105 static const char *get_language_name(int lid) {
106 PRETTYPRINTLANG(NEUTRAL)
107 PRETTYPRINTLANG(AFRIKAANS)
108 PRETTYPRINTLANG(ALBANIAN)
109 PRETTYPRINTLANG(ARABIC)
110 PRETTYPRINTLANG(ARMENIAN)
111 PRETTYPRINTLANG(ASSAMESE)
112 PRETTYPRINTLANG(AZERI)
113 PRETTYPRINTLANG(BASQUE)
114 PRETTYPRINTLANG(BELARUSIAN)
115 PRETTYPRINTLANG(BENGALI)
116 PRETTYPRINTLANG(BULGARIAN)
117 PRETTYPRINTLANG(CATALAN)
118 PRETTYPRINTLANG(CHINESE)
119 PRETTYPRINTLANG(CROATIAN)
120 PRETTYPRINTLANG(CZECH)
121 PRETTYPRINTLANG(DANISH)
122 PRETTYPRINTLANG(DIVEHI)
123 PRETTYPRINTLANG(DUTCH)
124 PRETTYPRINTLANG(ENGLISH)
125 PRETTYPRINTLANG(ESTONIAN)
126 PRETTYPRINTLANG(FAEROESE)
127 PRETTYPRINTLANG(FARSI)
128 PRETTYPRINTLANG(FINNISH)
129 PRETTYPRINTLANG(FRENCH)
130 PRETTYPRINTLANG(GALICIAN)
131 PRETTYPRINTLANG(GEORGIAN)
132 PRETTYPRINTLANG(GERMAN)
133 PRETTYPRINTLANG(GREEK)
134 PRETTYPRINTLANG(GUJARATI)
135 PRETTYPRINTLANG(HEBREW)
136 PRETTYPRINTLANG(HINDI)
137 PRETTYPRINTLANG(HUNGARIAN)
138 PRETTYPRINTLANG(ICELANDIC)
139 PRETTYPRINTLANG(INDONESIAN)
140 PRETTYPRINTLANG(ITALIAN)
141 PRETTYPRINTLANG(JAPANESE)
142 PRETTYPRINTLANG(KANNADA)
143 PRETTYPRINTLANG(KASHMIRI)
144 PRETTYPRINTLANG(KAZAK)
145 PRETTYPRINTLANG(KONKANI)
146 PRETTYPRINTLANG(KOREAN)
147 PRETTYPRINTLANG(KYRGYZ)
148 PRETTYPRINTLANG(LATVIAN)
149 PRETTYPRINTLANG(LITHUANIAN)
150 PRETTYPRINTLANG(MACEDONIAN)
151 PRETTYPRINTLANG(MALAY)
152 PRETTYPRINTLANG(MALAYALAM)
153 PRETTYPRINTLANG(MANIPURI)
154 PRETTYPRINTLANG(MARATHI)
155 PRETTYPRINTLANG(MONGOLIAN)
156 PRETTYPRINTLANG(NEPALI)
157 PRETTYPRINTLANG(NORWEGIAN)
158 PRETTYPRINTLANG(ORIYA)
159 PRETTYPRINTLANG(POLISH)
160 PRETTYPRINTLANG(PORTUGUESE)
161 PRETTYPRINTLANG(PUNJABI)
162 PRETTYPRINTLANG(ROMANIAN)
163 PRETTYPRINTLANG(RUSSIAN)
164 PRETTYPRINTLANG(SANSKRIT)
165 PRETTYPRINTLANG(SERBIAN)
166 PRETTYPRINTLANG(SINDHI)
167 PRETTYPRINTLANG(SLOVAK)
168 PRETTYPRINTLANG(SLOVENIAN)
169 PRETTYPRINTLANG(SPANISH)
170 PRETTYPRINTLANG(SWAHILI)
171 PRETTYPRINTLANG(SWEDISH)
172 PRETTYPRINTLANG(SYRIAC)
173 PRETTYPRINTLANG(TAMIL)
174 PRETTYPRINTLANG(TATAR)
175 PRETTYPRINTLANG(TELUGU)
176 PRETTYPRINTLANG(THAI)
177 PRETTYPRINTLANG(TURKISH)
178 PRETTYPRINTLANG(UKRAINIAN)
179 PRETTYPRINTLANG(URDU)
180 PRETTYPRINTLANG(UZBEK)
181 PRETTYPRINTLANG(VIETNAMESE)
182 PRETTYPRINTLANG(GAELIC)
183 PRETTYPRINTLANG(MALTESE)
184 PRETTYPRINTLANG(MAORI)
185 PRETTYPRINTLANG(RHAETO_ROMANCE)
186 PRETTYPRINTLANG(SAAMI)
187 PRETTYPRINTLANG(SORBIAN)
188 PRETTYPRINTLANG(SUTU)
189 PRETTYPRINTLANG(TSONGA)
190 PRETTYPRINTLANG(TSWANA)
191 PRETTYPRINTLANG(VENDA)
192 PRETTYPRINTLANG(XHOSA)
193 PRETTYPRINTLANG(ZULU)
194 PRETTYPRINTLANG(ESPERANTO)
195 PRETTYPRINTLANG(WALON)
196 PRETTYPRINTLANG(CORNISH)
197 PRETTYPRINTLANG(WELSH)
198 PRETTYPRINTLANG(BRETON)
199 return "Unknown language";
203 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
205 event_t *ev1 = NULL, *ev2 = NULL;
207 ((accelerator1->memopt != accelerator2->memopt) ||
208 (accelerator1->lvc.version != accelerator2->lvc.version) ||
209 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
211 ev1 = accelerator1->events;
212 ev2 = accelerator2->events;
213 while(!different && ev1 && ev2) {
215 ((ev1->id != ev2->id) ||
216 (ev1->flags != ev2->flags)))
222 ((ev1 && !ev2) || (!ev1 && ev2)))
227 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
230 ((bitmap1->memopt != bitmap2->memopt) ||
231 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
232 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
237 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
240 ((cursor1->id != cursor2->id) ||
241 (cursor1->width != cursor2->width) ||
242 (cursor1->height != cursor2->height) ||
243 (cursor1->xhot != cursor2->xhot) ||
244 (cursor1->yhot != cursor2->yhot)))
247 ((cursor1->lvc.version != cursor2->lvc.version) ||
248 (cursor1->lvc.characts != cursor2->lvc.characts)))
253 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
255 cursor_t *cursor1 = NULL, *cursor2 = NULL;
257 ((cursor_group1->memopt != cursor_group2->memopt) ||
258 (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
259 (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
262 (cursor_group1->ncursor != cursor_group2->ncursor))
265 cursor1 = cursor_group1->cursorlist;
266 cursor2 = cursor_group2->cursorlist;
267 while(!different && cursor1 && cursor2) {
268 different = compare_cursor(cursor1, cursor2);
269 cursor1 = cursor1->next;
270 cursor2 = cursor2->next;
273 ((cursor1 && !cursor2) ||
274 (!cursor1 && cursor2)))
280 static int compare_control(control_t *control1, control_t *control2) {
284 ((control1 && !control2) ||
285 (!control1 && control2)))
287 if(different || !control1 || !control2)
289 nameid = strdup(get_nameid_str(control1->ctlclass));
290 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
294 (control1->id != control2->id))
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 != control2->style->or_mask))
301 } else if(!different &&
302 ((control1->gotstyle && !control2->gotstyle) ||
303 (!control1->gotstyle && control2->gotstyle)))
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))
310 } else if(!different &&
311 ((control1->gotexstyle && !control2->gotexstyle) ||
312 (!control1->gotexstyle && control2->gotexstyle)))
314 if(!different && control1->gothelpid && control2->gothelpid) {
315 if(control1->helpid != control2->helpid)
317 } else if(!different &&
318 ((control1->gothelpid && !control2->gothelpid) ||
319 (!control1->gothelpid && control2->gothelpid)))
324 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
328 ((dialog1->memopt != dialog2->memopt) ||
329 (dialog1->lvc.version != dialog2->lvc.version) ||
330 (dialog1->lvc.characts != dialog2->lvc.characts)))
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))
337 } else if(!different &&
338 ((dialog1->gotstyle && !dialog2->gotstyle) ||
339 (!dialog1->gotstyle && dialog2->gotstyle)))
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))
346 } else if(!different &&
347 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
348 (!dialog1->gotexstyle && dialog2->gotexstyle)))
350 nameid = strdup(get_nameid_str(dialog1->menu));
351 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
354 nameid = strdup(get_nameid_str(dialog1->dlgclass));
355 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
359 different = compare_control(dialog1->controls, dialog2->controls);
363 static int compare_dialogex(dialogex_t *dialogex1, dialogex_t *dialogex2) {
367 ((dialogex1->memopt != dialogex2->memopt) ||
368 (dialogex1->lvc.version != dialogex2->lvc.version) ||
369 (dialogex1->lvc.characts != dialogex2->lvc.characts)))
371 if(!different && dialogex1->gotstyle && dialogex2->gotstyle) {
372 if((!dialogex1->style || !dialogex2->style) ||
373 (dialogex1->style->and_mask || dialogex2->style->and_mask) ||
374 (dialogex1->style->or_mask != dialogex2->style->or_mask))
376 } else if(!different &&
377 ((dialogex1->gotstyle && !dialogex2->gotstyle) ||
378 (!dialogex1->gotstyle && dialogex2->gotstyle)))
380 if(!different && dialogex1->gotexstyle && dialogex2->gotexstyle) {
381 if((!dialogex1->exstyle || !dialogex2->exstyle) ||
382 (dialogex1->exstyle->and_mask || dialogex2->exstyle->and_mask) ||
383 (dialogex1->exstyle->or_mask != dialogex2->exstyle->or_mask))
385 } else if(!different &&
386 ((dialogex1->gotexstyle && !dialogex2->gotexstyle) ||
387 (!dialogex1->gotexstyle && dialogex2->gotexstyle)))
389 if(!different && dialogex1->gothelpid && dialogex2->gothelpid) {
390 if(dialogex1->helpid != dialogex2->helpid)
392 } else if(!different &&
393 ((dialogex1->gothelpid && !dialogex2->gothelpid) ||
394 (!dialogex1->gothelpid && dialogex2->gothelpid)))
396 nameid = strdup(get_nameid_str(dialogex1->menu));
397 if(!different && strcmp(nameid, get_nameid_str(dialogex2->menu)))
400 nameid = strdup(get_nameid_str(dialogex1->dlgclass));
401 if(!different && strcmp(nameid, get_nameid_str(dialogex2->dlgclass)))
405 different = compare_control(dialogex1->controls, dialogex2->controls);
409 static int compare_font(font_t *font1, font_t *font2) {
412 ((font1->memopt != font2->memopt) ||
413 (font1->data->lvc.version != font2->data->lvc.version) ||
414 (font1->data->lvc.characts != font2->data->lvc.characts)))
419 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
422 ((fontdir1->memopt != fontdir2->memopt) ||
423 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
424 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
429 static int compare_icon(icon_t *icon1, icon_t *icon2) {
432 ((icon1->id != icon2->id) ||
433 (icon1->width != icon2->width) ||
434 (icon1->height != icon2->height)))
437 ((icon1->lvc.version != icon2->lvc.version) ||
438 (icon1->lvc.characts != icon2->lvc.characts)))
443 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
445 icon_t *icon1 = NULL, *icon2 = NULL;
447 ((icon_group1->memopt != icon_group2->memopt) ||
448 (icon_group1->lvc.version != icon_group2->lvc.version) ||
449 (icon_group1->lvc.characts != icon_group2->lvc.characts)))
452 (icon_group1->nicon != icon_group2->nicon))
455 icon1 = icon_group1->iconlist;
456 icon2 = icon_group2->iconlist;
457 while(!different && icon1 && icon2) {
458 different = compare_icon(icon1, icon2);
463 ((icon1 && !icon2) ||
470 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
472 while(!different && menu_item1 && menu_item2) {
473 if(menu_item1->popup && menu_item2->popup)
474 different = compare_menu_item(menu_item1->popup, menu_item2->popup);
475 else if(!menu_item1->popup && !menu_item2->popup) {
476 if(menu_item1->name && menu_item2->name) {
477 if((menu_item1->id != menu_item2->id) ||
478 (menu_item1->state != menu_item2->state))
480 } else if((menu_item1->name && !menu_item2->name) ||
481 (!menu_item1->name && menu_item2->name))
485 menu_item1 = menu_item1->next;
486 menu_item2 = menu_item2->next;
489 ((menu_item1 && !menu_item2) ||
490 (!menu_item1 && menu_item2)))
495 static int compare_menu(menu_t *menu1, menu_t *menu2) {
498 ((menu1->memopt != menu2->memopt) ||
499 (menu1->lvc.version != menu2->lvc.version) ||
500 (menu1->lvc.characts != menu2->lvc.characts)))
503 different = compare_menu_item(menu1->items, menu2->items);
507 static int compare_menuex_item(menuex_item_t *menuex_item1, menuex_item_t *menuex_item2) {
509 while(!different && menuex_item1 && menuex_item2) {
510 if(menuex_item1->popup && menuex_item2->popup) {
511 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
512 if(menuex_item1->id != menuex_item2->id)
514 } else if(!different &&
515 ((menuex_item1->gotid && !menuex_item2->gotid) ||
516 (!menuex_item2->gotid && menuex_item2->gotid)))
518 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
519 if(menuex_item1->type != menuex_item2->type)
521 } else if(!different &&
522 ((menuex_item1->gottype && !menuex_item2->gottype) ||
523 (!menuex_item2->gottype && menuex_item2->gottype)))
525 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
526 if(menuex_item1->state != menuex_item2->state)
528 } else if(!different &&
529 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
530 (!menuex_item2->gotstate && menuex_item2->gotstate)))
532 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
533 if(menuex_item1->helpid != menuex_item2->helpid)
535 } else if(!different &&
536 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
537 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
540 different = compare_menuex_item(menuex_item1->popup, menuex_item2->popup);
541 } else if(!menuex_item1->popup && !menuex_item2->popup) {
542 if(menuex_item1->name && menuex_item2->name) {
543 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
544 if(menuex_item1->id != menuex_item2->id)
546 } else if(!different &&
547 ((menuex_item1->gotid && !menuex_item2->gotid) ||
548 (!menuex_item2->gotid && menuex_item2->gotid)))
550 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
551 if(menuex_item1->type != menuex_item2->type)
553 } else if(!different &&
554 ((menuex_item1->gottype && !menuex_item2->gottype) ||
555 (!menuex_item2->gottype && menuex_item2->gottype)))
557 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
558 if(menuex_item1->state != menuex_item2->state)
560 } else if(!different &&
561 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
562 (!menuex_item2->gotstate && menuex_item2->gotstate)))
564 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
565 if(menuex_item1->helpid != menuex_item2->helpid)
567 } else if(!different &&
568 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
569 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
571 } else if((menuex_item1->name && !menuex_item2->name) ||
572 (!menuex_item1->name && menuex_item2->name))
576 menuex_item1 = menuex_item1->next;
577 menuex_item2 = menuex_item2->next;
580 ((menuex_item1 && !menuex_item2) ||
581 (!menuex_item1 && menuex_item2)))
586 static int compare_menuex(menuex_t *menuex1, menuex_t *menuex2) {
589 ((menuex1->memopt != menuex2->memopt) ||
590 (menuex1->lvc.version != menuex2->lvc.version) ||
591 (menuex1->lvc.characts != menuex2->lvc.characts)))
594 different = compare_menuex_item(menuex1->items, menuex2->items);
598 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
601 ((rcdata1->memopt != rcdata2->memopt) ||
602 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
603 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
608 static int compare_html(html_t *rcdata1, html_t *rcdata2) {
611 ((rcdata1->memopt != rcdata2->memopt) ||
612 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
613 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
618 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
621 while(!different && stringtable1 && stringtable2) {
622 if((stringtable1->memopt != stringtable2->memopt) ||
623 (stringtable1->lvc.version != stringtable2->lvc.version) ||
624 (stringtable1->lvc.characts != stringtable2->lvc.characts))
627 if((stringtable1->nentries != stringtable2->nentries) ||
628 (stringtable1->idbase != stringtable2->idbase))
631 for(i = 0 ; i < stringtable1->nentries; i++)
632 if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
633 (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
634 (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
635 (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
640 stringtable1 = stringtable1->next;
641 stringtable2 = stringtable2->next;
646 static int compare_user(user_t *user1, user_t *user2) {
650 ((user1->memopt != user2->memopt) ||
651 (user1->data->lvc.version != user2->data->lvc.version) ||
652 (user1->data->lvc.characts != user2->data->lvc.characts)))
654 nameid = strdup(get_nameid_str(user1->type));
655 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
661 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
664 ((messagetable1->memopt != messagetable2->memopt) ||
665 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
666 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
671 static int compare_string(string_t *string1, string_t *string2) {
674 ((string1->size != string2->size) ||
675 (string1->type != string2->type)))
678 if(string1->type == str_char)
679 different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
680 else if(string1->type == str_unicode)
681 different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
688 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
690 static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
694 (ver_value1->type == ver_value2->type)) {
695 switch(ver_value1->type) {
697 if(!different && ver_value1->key && ver_value2->key)
698 different = compare_string(ver_value1->key, ver_value2->key);
699 else if(!different &&
700 ((ver_value1->key && !ver_value2->key) ||
701 (!ver_value1->key && ver_value2->key)))
705 if(!different && ver_value1->key && ver_value2->key)
706 different = compare_string(ver_value1->key, ver_value2->key);
707 else if(!different &&
708 ((ver_value1->key && !ver_value2->key) ||
709 (!ver_value1->key && ver_value2->key)))
711 if(!different && ver_value1->value.words && ver_value2->value.words) {
713 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
716 for(i = 0; i < ver_value1->value.words->nwords; i++) {
717 if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
722 } else if(!different &&
723 ((ver_value1->value.words && !ver_value2->value.words) ||
724 (!ver_value1->value.words && ver_value2->value.words)))
728 if(!different && ver_value1->value.block && ver_value2->value.block)
729 different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
730 else if(!different &&
731 ((ver_value1->value.block && !ver_value2->value.block) ||
732 (!ver_value1->value.block && ver_value2->value.block)))
743 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
745 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
747 ver_value1 = ver_block1->values;
748 ver_value2 = ver_block2->values;
749 while(!different && ver_value1 && ver_value2) {
750 different = compare_ver_value(ver_value1, ver_value2);
751 ver_value1 = ver_value1->next;
752 ver_value2 = ver_value2->next;
755 ((ver_value1 && !ver_value2) ||
756 (!ver_value1 && ver_value2)))
762 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
764 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
766 ((versioninfo1->memopt != versioninfo2->memopt) ||
767 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
768 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
770 if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
771 if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
772 (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
773 (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
774 (versioninfo1->filever_min2 != versioninfo2->filever_min2))
776 } else if(!different &&
777 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
778 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
780 if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
781 if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
782 (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
783 (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
784 (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
786 } else if(!different &&
787 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
788 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
790 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
791 if(versioninfo1->fileos != versioninfo2->fileos)
793 } else if(!different &&
794 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
795 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
797 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
798 if(versioninfo1->fileflags != versioninfo2->fileflags)
800 } else if(!different &&
801 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
802 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
804 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
805 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
807 } else if(!different &&
808 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
809 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
811 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
812 if(versioninfo1->filetype != versioninfo2->filetype)
814 } else if(!different &&
815 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
816 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
818 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
819 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
821 } else if(!different &&
822 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
823 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
826 ver_block1 = versioninfo1->blocks;
827 ver_block2 = versioninfo2->blocks;
828 while(!different && ver_block1 && ver_block2) {
829 different = compare_ver_block(ver_block1, ver_block2);
830 ver_block1 = ver_block1->next;
831 ver_block2 = ver_block2->next;
834 ((ver_block1 && !ver_block2) ||
835 (!ver_block1 && ver_block2)))
841 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
844 ((dlginit1->memopt != dlginit2->memopt) ||
845 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
846 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
851 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
853 while(!different && toolbar_item1 && toolbar_item2) {
854 if((toolbar_item1->id && !toolbar_item2->id) ||
855 (!toolbar_item1->id && toolbar_item2->id))
857 toolbar_item1 = toolbar_item1->next;
858 toolbar_item2 = toolbar_item2->next;
861 ((toolbar_item1 && !toolbar_item2) ||
862 (!toolbar_item1 && toolbar_item2)))
867 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
870 ((toolbar1->memopt != toolbar2->memopt) ||
871 (toolbar1->lvc.version != toolbar2->lvc.version) ||
872 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
875 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
879 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
882 ((ani_curico1->memopt != ani_curico2->memopt) ||
883 (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
884 (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
889 static int compare(resource_t *resource1, resource_t *resource2) {
890 switch(resource1->type) {
892 return compare_accelerator(resource1->res.acc, resource2->res.acc);
894 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
896 return compare_cursor(resource1->res.cur, resource2->res.cur);
898 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
900 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
902 return compare_dialogex(resource1->res.dlgex, resource2->res.dlgex);
904 return compare_font(resource1->res.fnt, resource2->res.fnt);
906 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
908 return compare_icon(resource1->res.ico, resource2->res.ico);
910 return compare_icon_group(resource1->res.icog, resource2->res.icog);
912 return compare_menu(resource1->res.men, resource2->res.men);
914 return compare_menuex(resource1->res.menex, resource2->res.menex);
916 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
918 return compare_stringtable(resource1->res.stt, resource2->res.stt);
920 return compare_user(resource1->res.usr, resource2->res.usr);
922 return compare_html(resource1->res.html, resource2->res.html);
924 return compare_messagetable(resource1->res.msg, resource2->res.msg);
926 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
928 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
930 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
933 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
935 /* Not supposed to reach here */
936 fprintf(stderr, "Not supposed to reach here (compare())\n");
942 static void dump_stringtable(resource_t *res)
944 stringtable_t *stt = res->res.stt;
948 assert((stt->idbase%16) == 0);
949 assert(stt->nentries == 16);
950 for (j = 0; j < stt->nentries; j++)
952 stt_entry_t *entry = &stt->entries[j];
953 language_t *lang = stt->lvc.language;
960 newstr = convert_string(entry->str, str_unicode, get_language_codepage(lang->id, lang->sub));
961 printf("%02x%02x", newstr->size & 0xff, (newstr->size >> 8) & 0xff);
962 wstr = newstr->str.wstr;
963 for (k = 0; k < newstr->size; k++)
964 printf("%02x%02x", wstr[k] & 0xff, wstr[k] >> 8);
973 static void dump(resource_t *res)
978 dump_stringtable(res);
985 typedef struct resource_lang_node
989 struct resource_lang_node *next;
990 } resource_lang_node_t;
992 typedef struct resource_id_node
995 resource_lang_node_t *langs;
996 struct resource_id_node *next;
997 } resource_id_node_t;
1002 struct resource_id_node *ids;
1003 } verify_tab[res_usr+1];
1005 static void add_resource(resource_t *res)
1007 resource_id_node_t *idnode;
1008 resource_lang_node_t *langnode;
1009 if (!verify_tab[res->type].enabled)
1011 fprintf(stderr, "ERR: Report this: unknown resource type parsed %08x\n", res->type);
1015 for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
1016 if (compare_name_id(idnode->id, res->name) == 0)
1021 idnode = xmalloc(sizeof(resource_id_node_t));
1022 idnode->id = res->name;
1023 idnode->langs = NULL;
1024 idnode->next = verify_tab[res->type].ids;
1025 verify_tab[res->type].ids = idnode;
1028 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1029 if (compare_lang(langnode->lang, get_language(res)) == 0)
1031 fprintf(stderr, "ERR: resource %s [type %x] language %03x:%02x duplicated!\n",
1032 get_nameid_str(res->name), res->type, langnode->lang.id, langnode->lang.sub);
1036 langnode = xmalloc(sizeof(resource_lang_node_t));
1037 langnode->res = res;
1038 langnode->lang = get_language(res);
1039 langnode->next = idnode->langs;
1040 idnode->langs = langnode;
1043 static void setup_tabs(void)
1047 for (i = 0; i <= res_usr; i++)
1071 verify_tab[i].enabled = 1;
1076 static const char *get_typename_for_int(int type) {
1079 return get_typename(&res);
1082 static resource_t *find_main(int type, name_id_t *id, resource_lang_node_t *langnode)
1084 resource_t *neutral = NULL, *en = NULL, *en_US = NULL;
1085 for (; langnode; langnode = langnode->next)
1087 if (langnode->lang.id == LANG_NEUTRAL && langnode->lang.sub == SUBLANG_NEUTRAL)
1088 neutral = langnode->res;
1089 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == SUBLANG_NEUTRAL)
1091 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == MASTER_SUBLANGUAGE)
1092 en_US = langnode->res;
1095 if (neutral != NULL && (en != NULL || en_US != NULL))
1097 fprintf(stderr, "INFO: Resource %04x/%s has both NEUTRAL and MASTER language translarion\n",
1098 type, get_nameid_str(id));
1101 if (en_US != NULL) return en_US;
1102 if (en != NULL) return en;
1106 void verify_translations(resource_t *top) {
1107 resource_t *curr = top;
1108 resource_id_node_t *idnode;
1109 resource_lang_node_t *langnode;
1119 for (type = 0; type <= res_usr; type++)
1121 printf("TYPE NEXT [%s]\n", get_typename_for_int(type));
1122 for (idnode = verify_tab[type].ids; idnode; idnode = idnode->next)
1124 resource_t *mainres;
1125 printf("RESOURCE [%s]\n", get_nameid_str(idnode->id));
1127 mainres = find_main(type, idnode->id, idnode->langs);
1130 fprintf(stderr, "ERR: resource %04x/%s has translation(s) but not available in NEUTRAL or MASTER language\n",
1131 type, get_nameid_str(idnode->id));
1132 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1133 printf("EXTRA %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1137 if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
1138 printf("NOTRANSL\n");
1142 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1144 printf("EXIST %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1145 dump(langnode->res);
1146 if (compare(langnode->res, mainres))
1148 printf("DIFF %03x:%02x\n", langnode->lang.id, langnode->lang.sub);