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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #define MASTER_LANGUAGE LANG_ENGLISH
34 static int present_resources[res_usr+1];
35 static char *res_names[res_usr+1];
36 static int nb_resources[res_usr+1][lang_type_normal+1];
37 static resource_t **list_resources[res_usr+1][lang_type_normal+1];
39 static int get_language_id(resource_t *resource) {
40 switch(resource->type) {
42 return resource->res.acc->lvc.language->id;
44 return resource->res.bmp->data->lvc.language->id;
46 return resource->res.cur->lvc.language->id;
48 return resource->res.curg->lvc.language->id;
50 return resource->res.dlg->lvc.language->id;
52 return resource->res.dlgex->lvc.language->id;
54 return resource->res.fnt->data->lvc.language->id;
56 return resource->res.fnd->data->lvc.language->id;
58 return resource->res.ico->lvc.language->id;
60 return resource->res.icog->lvc.language->id;
62 return resource->res.men->lvc.language->id;
64 return resource->res.menex->lvc.language->id;
66 return resource->res.rdt->data->lvc.language->id;
68 return resource->res.stt->lvc.language->id;
70 return resource->res.usr->data->lvc.language->id;
72 return resource->res.msg->data->lvc.language->id;
74 return resource->res.ver->lvc.language->id;
76 return resource->res.dlgi->data->lvc.language->id;
78 return resource->res.tbt->lvc.language->id;
81 return resource->res.ani->data->lvc.language->id;
83 /* Not supposed to reach here */
84 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
90 static void add_resource(resource_t *resource) {
91 enum lang_type_e lang_type;
92 enum res_e res_type = resource->type;
93 int lid = get_language_id(resource);
95 if(lid == MASTER_LANGUAGE) {
96 lang_type = lang_type_master;
97 } else if(lid == LANG_NEUTRAL) {
98 lang_type = lang_type_neutral;
100 lang_type = lang_type_normal;
102 nb_resources[res_type][lang_type]++;
103 list_resources[res_type][lang_type] = realloc(list_resources[res_type][lang_type], nb_resources[res_type][lang_type]*sizeof(resource_t *));
104 list_resources[res_type][lang_type][nb_resources[res_type][lang_type]-1] = resource;
109 #define PRETTYPRINTLANG(langid) \
110 if(LANG_##langid == lid) { \
114 static const char *get_language_name(int lid) {
115 PRETTYPRINTLANG(NEUTRAL)
116 PRETTYPRINTLANG(AFRIKAANS)
117 PRETTYPRINTLANG(ALBANIAN)
118 PRETTYPRINTLANG(ARABIC)
119 PRETTYPRINTLANG(ARMENIAN)
120 PRETTYPRINTLANG(ASSAMESE)
121 PRETTYPRINTLANG(AZERI)
122 PRETTYPRINTLANG(BASQUE)
123 PRETTYPRINTLANG(BELARUSIAN)
124 PRETTYPRINTLANG(BENGALI)
125 PRETTYPRINTLANG(BULGARIAN)
126 PRETTYPRINTLANG(CATALAN)
127 PRETTYPRINTLANG(CHINESE)
128 PRETTYPRINTLANG(CROATIAN)
129 PRETTYPRINTLANG(CZECH)
130 PRETTYPRINTLANG(DANISH)
131 PRETTYPRINTLANG(DIVEHI)
132 PRETTYPRINTLANG(DUTCH)
133 PRETTYPRINTLANG(ENGLISH)
134 PRETTYPRINTLANG(ESTONIAN)
135 PRETTYPRINTLANG(FAEROESE)
136 PRETTYPRINTLANG(FARSI)
137 PRETTYPRINTLANG(FINNISH)
138 PRETTYPRINTLANG(FRENCH)
139 PRETTYPRINTLANG(GALICIAN)
140 PRETTYPRINTLANG(GEORGIAN)
141 PRETTYPRINTLANG(GERMAN)
142 PRETTYPRINTLANG(GREEK)
143 PRETTYPRINTLANG(GUJARATI)
144 PRETTYPRINTLANG(HEBREW)
145 PRETTYPRINTLANG(HINDI)
146 PRETTYPRINTLANG(HUNGARIAN)
147 PRETTYPRINTLANG(ICELANDIC)
148 PRETTYPRINTLANG(INDONESIAN)
149 PRETTYPRINTLANG(ITALIAN)
150 PRETTYPRINTLANG(JAPANESE)
151 PRETTYPRINTLANG(KANNADA)
152 PRETTYPRINTLANG(KASHMIRI)
153 PRETTYPRINTLANG(KAZAK)
154 PRETTYPRINTLANG(KONKANI)
155 PRETTYPRINTLANG(KOREAN)
156 PRETTYPRINTLANG(KYRGYZ)
157 PRETTYPRINTLANG(LATVIAN)
158 PRETTYPRINTLANG(LITHUANIAN)
159 PRETTYPRINTLANG(MACEDONIAN)
160 PRETTYPRINTLANG(MALAY)
161 PRETTYPRINTLANG(MALAYALAM)
162 PRETTYPRINTLANG(MANIPURI)
163 PRETTYPRINTLANG(MARATHI)
164 PRETTYPRINTLANG(MONGOLIAN)
165 PRETTYPRINTLANG(NEPALI)
166 PRETTYPRINTLANG(NORWEGIAN)
167 PRETTYPRINTLANG(ORIYA)
168 PRETTYPRINTLANG(POLISH)
169 PRETTYPRINTLANG(PORTUGUESE)
170 PRETTYPRINTLANG(PUNJABI)
171 PRETTYPRINTLANG(ROMANIAN)
172 PRETTYPRINTLANG(RUSSIAN)
173 PRETTYPRINTLANG(SANSKRIT)
174 PRETTYPRINTLANG(SERBIAN)
175 PRETTYPRINTLANG(SINDHI)
176 PRETTYPRINTLANG(SLOVAK)
177 PRETTYPRINTLANG(SLOVENIAN)
178 PRETTYPRINTLANG(SPANISH)
179 PRETTYPRINTLANG(SWAHILI)
180 PRETTYPRINTLANG(SWEDISH)
181 PRETTYPRINTLANG(SYRIAC)
182 PRETTYPRINTLANG(TAMIL)
183 PRETTYPRINTLANG(TATAR)
184 PRETTYPRINTLANG(TELUGU)
185 PRETTYPRINTLANG(THAI)
186 PRETTYPRINTLANG(TURKISH)
187 PRETTYPRINTLANG(UKRAINIAN)
188 PRETTYPRINTLANG(URDU)
189 PRETTYPRINTLANG(UZBEK)
190 PRETTYPRINTLANG(VIETNAMESE)
191 PRETTYPRINTLANG(GAELIC)
192 PRETTYPRINTLANG(MALTESE)
193 PRETTYPRINTLANG(MAORI)
194 PRETTYPRINTLANG(RHAETO_ROMANCE)
195 PRETTYPRINTLANG(SAAMI)
196 PRETTYPRINTLANG(SORBIAN)
197 PRETTYPRINTLANG(SUTU)
198 PRETTYPRINTLANG(TSONGA)
199 PRETTYPRINTLANG(TSWANA)
200 PRETTYPRINTLANG(VENDA)
201 PRETTYPRINTLANG(XHOSA)
202 PRETTYPRINTLANG(ZULU)
203 PRETTYPRINTLANG(ESPERANTO)
204 PRETTYPRINTLANG(WALON)
205 PRETTYPRINTLANG(CORNISH)
206 PRETTYPRINTLANG(WELSH)
207 PRETTYPRINTLANG(BRETON)
208 return "Unknown language";
212 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
214 event_t *ev1 = NULL, *ev2 = NULL;
216 ((accelerator1->memopt != accelerator2->memopt) ||
217 (accelerator1->lvc.version != accelerator2->lvc.version) ||
218 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
220 ev1 = accelerator1->events;
221 ev2 = accelerator2->events;
222 while(!different && ev1 && ev2) {
224 ((ev1->id != ev2->id) ||
225 (ev1->flags != ev2->flags)))
231 ((ev1 && !ev2) || (!ev1 && ev2)))
236 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
239 ((bitmap1->memopt != bitmap2->memopt) ||
240 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
241 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
246 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
249 ((cursor1->id != cursor2->id) ||
250 (cursor1->width != cursor2->width) ||
251 (cursor1->height != cursor2->height) ||
252 (cursor1->xhot != cursor2->xhot) ||
253 (cursor1->yhot != cursor2->yhot)))
256 ((cursor1->lvc.version != cursor2->lvc.version) ||
257 (cursor1->lvc.characts != cursor2->lvc.characts)))
262 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
264 cursor_t *cursor1 = NULL, *cursor2 = NULL;
266 ((cursor_group1->memopt != cursor_group2->memopt) ||
267 (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
268 (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
271 (cursor_group1->ncursor != cursor_group2->ncursor))
274 cursor1 = cursor_group1->cursorlist;
275 cursor2 = cursor_group2->cursorlist;
276 while(!different && cursor1 && cursor2) {
277 different = compare_cursor(cursor1, cursor2);
278 cursor1 = cursor1->next;
279 cursor2 = cursor2->next;
282 ((cursor1 && !cursor2) ||
283 (!cursor1 && cursor2)))
289 static int compare_control(control_t *control1, control_t *control2) {
293 ((control1 && !control2) ||
294 (!control1 && control2)))
296 if(different || !control1 || !control2)
298 nameid = strdup(get_nameid_str(control1->ctlclass));
299 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
303 (control1->id != control2->id))
305 if(!different && control1->gotstyle && control2->gotstyle) {
306 if((!control1->style || !control2->style) ||
307 (control1->style->and_mask || control2->style->and_mask) ||
308 (control1->style->or_mask != control2->style->or_mask))
310 } else if(!different &&
311 ((control1->gotstyle && !control2->gotstyle) ||
312 (!control1->gotstyle && control2->gotstyle)))
314 if(!different && control1->gotexstyle && control2->gotexstyle) {
315 if((!control1->exstyle || !control2->exstyle) ||
316 (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
317 (control1->exstyle->or_mask != control2->exstyle->or_mask))
319 } else if(!different &&
320 ((control1->gotexstyle && !control2->gotexstyle) ||
321 (!control1->gotexstyle && control2->gotexstyle)))
323 if(!different && control1->gothelpid && control2->gothelpid) {
324 if(control1->helpid != control2->helpid)
326 } else if(!different &&
327 ((control1->gothelpid && !control2->gothelpid) ||
328 (!control1->gothelpid && control2->gothelpid)))
333 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
337 ((dialog1->memopt != dialog2->memopt) ||
338 (dialog1->lvc.version != dialog2->lvc.version) ||
339 (dialog1->lvc.characts != dialog2->lvc.characts)))
341 if(!different && dialog1->gotstyle && dialog2->gotstyle) {
342 if((!dialog1->style || !dialog2->style) ||
343 (dialog1->style->and_mask || dialog2->style->and_mask) ||
344 (dialog1->style->or_mask != dialog2->style->or_mask))
346 } else if(!different &&
347 ((dialog1->gotstyle && !dialog2->gotstyle) ||
348 (!dialog1->gotstyle && dialog2->gotstyle)))
350 if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
351 if((!dialog1->exstyle || !dialog2->exstyle) ||
352 (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
353 (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
355 } else if(!different &&
356 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
357 (!dialog1->gotexstyle && dialog2->gotexstyle)))
359 nameid = strdup(get_nameid_str(dialog1->menu));
360 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
363 nameid = strdup(get_nameid_str(dialog1->dlgclass));
364 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
368 different = compare_control(dialog1->controls, dialog2->controls);
372 static int compare_dialogex(dialogex_t *dialogex1, dialogex_t *dialogex2) {
376 ((dialogex1->memopt != dialogex2->memopt) ||
377 (dialogex1->lvc.version != dialogex2->lvc.version) ||
378 (dialogex1->lvc.characts != dialogex2->lvc.characts)))
380 if(!different && dialogex1->gotstyle && dialogex2->gotstyle) {
381 if((!dialogex1->style || !dialogex2->style) ||
382 (dialogex1->style->and_mask || dialogex2->style->and_mask) ||
383 (dialogex1->style->or_mask != dialogex2->style->or_mask))
385 } else if(!different &&
386 ((dialogex1->gotstyle && !dialogex2->gotstyle) ||
387 (!dialogex1->gotstyle && dialogex2->gotstyle)))
389 if(!different && dialogex1->gotexstyle && dialogex2->gotexstyle) {
390 if((!dialogex1->exstyle || !dialogex2->exstyle) ||
391 (dialogex1->exstyle->and_mask || dialogex2->exstyle->and_mask) ||
392 (dialogex1->exstyle->or_mask != dialogex2->exstyle->or_mask))
394 } else if(!different &&
395 ((dialogex1->gotexstyle && !dialogex2->gotexstyle) ||
396 (!dialogex1->gotexstyle && dialogex2->gotexstyle)))
398 if(!different && dialogex1->gothelpid && dialogex2->gothelpid) {
399 if(dialogex1->helpid != dialogex2->helpid)
401 } else if(!different &&
402 ((dialogex1->gothelpid && !dialogex2->gothelpid) ||
403 (!dialogex1->gothelpid && dialogex2->gothelpid)))
405 nameid = strdup(get_nameid_str(dialogex1->menu));
406 if(!different && strcmp(nameid, get_nameid_str(dialogex2->menu)))
409 nameid = strdup(get_nameid_str(dialogex1->dlgclass));
410 if(!different && strcmp(nameid, get_nameid_str(dialogex2->dlgclass)))
414 different = compare_control(dialogex1->controls, dialogex2->controls);
418 static int compare_font(font_t *font1, font_t *font2) {
421 ((font1->memopt != font2->memopt) ||
422 (font1->data->lvc.version != font2->data->lvc.version) ||
423 (font1->data->lvc.characts != font2->data->lvc.characts)))
428 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
431 ((fontdir1->memopt != fontdir2->memopt) ||
432 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
433 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
438 static int compare_icon(icon_t *icon1, icon_t *icon2) {
441 ((icon1->id != icon2->id) ||
442 (icon1->width != icon2->width) ||
443 (icon1->height != icon2->height)))
446 ((icon1->lvc.version != icon2->lvc.version) ||
447 (icon1->lvc.characts != icon2->lvc.characts)))
452 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
454 icon_t *icon1 = NULL, *icon2 = NULL;
456 ((icon_group1->memopt != icon_group2->memopt) ||
457 (icon_group1->lvc.version != icon_group2->lvc.version) ||
458 (icon_group1->lvc.characts != icon_group2->lvc.characts)))
461 (icon_group1->nicon != icon_group2->nicon))
464 icon1 = icon_group1->iconlist;
465 icon2 = icon_group2->iconlist;
466 while(!different && icon1 && icon2) {
467 different = compare_icon(icon1, icon2);
472 ((icon1 && !icon2) ||
479 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
481 while(!different && menu_item1 && menu_item2) {
482 if(menu_item1->popup && menu_item2->popup)
483 different = compare_menu_item(menu_item1->popup, menu_item2->popup);
484 else if(!menu_item1->popup && !menu_item2->popup) {
485 if(menu_item1->name && menu_item2->name) {
486 if((menu_item1->id != menu_item2->id) ||
487 (menu_item1->state != menu_item2->state))
489 } else if((menu_item1->name && !menu_item2->name) ||
490 (!menu_item1->name && menu_item2->name))
494 menu_item1 = menu_item1->next;
495 menu_item2 = menu_item2->next;
498 ((menu_item1 && !menu_item2) ||
499 (!menu_item1 && menu_item2)))
504 static int compare_menu(menu_t *menu1, menu_t *menu2) {
507 ((menu1->memopt != menu2->memopt) ||
508 (menu1->lvc.version != menu2->lvc.version) ||
509 (menu1->lvc.characts != menu2->lvc.characts)))
512 different = compare_menu_item(menu1->items, menu2->items);
516 static int compare_menuex_item(menuex_item_t *menuex_item1, menuex_item_t *menuex_item2) {
518 while(!different && menuex_item1 && menuex_item2) {
519 if(menuex_item1->popup && menuex_item2->popup) {
520 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
521 if(menuex_item1->id != menuex_item2->id)
523 } else if(!different &&
524 ((menuex_item1->gotid && !menuex_item2->gotid) ||
525 (!menuex_item2->gotid && menuex_item2->gotid)))
527 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
528 if(menuex_item1->type != menuex_item2->type)
530 } else if(!different &&
531 ((menuex_item1->gottype && !menuex_item2->gottype) ||
532 (!menuex_item2->gottype && menuex_item2->gottype)))
534 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
535 if(menuex_item1->state != menuex_item2->state)
537 } else if(!different &&
538 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
539 (!menuex_item2->gotstate && menuex_item2->gotstate)))
541 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
542 if(menuex_item1->helpid != menuex_item2->helpid)
544 } else if(!different &&
545 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
546 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
549 different = compare_menuex_item(menuex_item1->popup, menuex_item2->popup);
550 } else if(!menuex_item1->popup && !menuex_item2->popup) {
551 if(menuex_item1->name && menuex_item2->name) {
552 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
553 if(menuex_item1->id != menuex_item2->id)
555 } else if(!different &&
556 ((menuex_item1->gotid && !menuex_item2->gotid) ||
557 (!menuex_item2->gotid && menuex_item2->gotid)))
559 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
560 if(menuex_item1->type != menuex_item2->type)
562 } else if(!different &&
563 ((menuex_item1->gottype && !menuex_item2->gottype) ||
564 (!menuex_item2->gottype && menuex_item2->gottype)))
566 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
567 if(menuex_item1->state != menuex_item2->state)
569 } else if(!different &&
570 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
571 (!menuex_item2->gotstate && menuex_item2->gotstate)))
573 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
574 if(menuex_item1->helpid != menuex_item2->helpid)
576 } else if(!different &&
577 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
578 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
580 } else if((menuex_item1->name && !menuex_item2->name) ||
581 (!menuex_item1->name && menuex_item2->name))
585 menuex_item1 = menuex_item1->next;
586 menuex_item2 = menuex_item2->next;
589 ((menuex_item1 && !menuex_item2) ||
590 (!menuex_item1 && menuex_item2)))
595 static int compare_menuex(menuex_t *menuex1, menuex_t *menuex2) {
598 ((menuex1->memopt != menuex2->memopt) ||
599 (menuex1->lvc.version != menuex2->lvc.version) ||
600 (menuex1->lvc.characts != menuex2->lvc.characts)))
603 different = compare_menuex_item(menuex1->items, menuex2->items);
607 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
610 ((rcdata1->memopt != rcdata2->memopt) ||
611 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
612 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
617 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
620 while(!different && stringtable1 && stringtable2) {
621 if((stringtable1->memopt != stringtable2->memopt) ||
622 (stringtable1->lvc.version != stringtable2->lvc.version) ||
623 (stringtable1->lvc.characts != stringtable2->lvc.characts))
626 if((stringtable1->nentries != stringtable2->nentries) ||
627 (stringtable1->idbase != stringtable2->idbase))
630 for(i = 0 ; i < stringtable1->nentries; i++)
631 if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
632 (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
633 (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
634 (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
639 stringtable1 = stringtable1->next;
640 stringtable2 = stringtable2->next;
645 static int compare_user(user_t *user1, user_t *user2) {
649 ((user1->memopt != user2->memopt) ||
650 (user1->data->lvc.version != user2->data->lvc.version) ||
651 (user1->data->lvc.characts != user2->data->lvc.characts)))
653 nameid = strdup(get_nameid_str(user1->type));
654 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
660 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
663 ((messagetable1->memopt != messagetable2->memopt) ||
664 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
665 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
670 static int compare_string(string_t *string1, string_t *string2) {
673 ((string1->size != string2->size) ||
674 (string1->type != string2->type)))
677 if(string1->type == str_char)
678 different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
679 else if(string1->type == str_unicode)
680 different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
687 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
689 static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
693 (ver_value1->type == ver_value2->type)) {
694 switch(ver_value1->type) {
696 if(!different && ver_value1->key && ver_value2->key)
697 different = compare_string(ver_value1->key, ver_value2->key);
698 else if(!different &&
699 ((ver_value1->key && !ver_value2->key) ||
700 (!ver_value1->key && ver_value2->key)))
704 if(!different && ver_value1->key && ver_value2->key)
705 different = compare_string(ver_value1->key, ver_value2->key);
706 else if(!different &&
707 ((ver_value1->key && !ver_value2->key) ||
708 (!ver_value1->key && ver_value2->key)))
710 if(!different && ver_value1->value.words && ver_value2->value.words) {
712 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
715 for(i = 0; i < ver_value1->value.words->nwords; i++) {
716 if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
721 } else if(!different &&
722 ((ver_value1->value.words && !ver_value2->value.words) ||
723 (!ver_value1->value.words && ver_value2->value.words)))
727 if(!different && ver_value1->value.block && ver_value2->value.block)
728 different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
729 else if(!different &&
730 ((ver_value1->value.block && !ver_value2->value.block) ||
731 (!ver_value1->value.block && ver_value2->value.block)))
742 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
744 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
746 ver_value1 = ver_block1->values;
747 ver_value2 = ver_block2->values;
748 while(!different && ver_value1 && ver_value2) {
749 different = compare_ver_value(ver_value1, ver_value2);
750 ver_value1 = ver_value1->next;
751 ver_value2 = ver_value2->next;
754 ((ver_value1 && !ver_value2) ||
755 (!ver_value1 && ver_value2)))
761 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
763 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
765 ((versioninfo1->memopt != versioninfo2->memopt) ||
766 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
767 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
769 if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
770 if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
771 (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
772 (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
773 (versioninfo1->filever_min2 != versioninfo2->filever_min2))
775 } else if(!different &&
776 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
777 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
779 if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
780 if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
781 (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
782 (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
783 (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
785 } else if(!different &&
786 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
787 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
789 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
790 if(versioninfo1->fileos != versioninfo2->fileos)
792 } else if(!different &&
793 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
794 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
796 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
797 if(versioninfo1->fileflags != versioninfo2->fileflags)
799 } else if(!different &&
800 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
801 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
803 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
804 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
806 } else if(!different &&
807 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
808 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
810 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
811 if(versioninfo1->filetype != versioninfo2->filetype)
813 } else if(!different &&
814 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
815 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
817 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
818 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
820 } else if(!different &&
821 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
822 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
825 ver_block1 = versioninfo1->blocks;
826 ver_block2 = versioninfo2->blocks;
827 while(!different && ver_block1 && ver_block2) {
828 different = compare_ver_block(ver_block1, ver_block2);
829 ver_block1 = ver_block1->next;
830 ver_block2 = ver_block2->next;
833 ((ver_block1 && !ver_block2) ||
834 (ver_block1 && !ver_block2)))
840 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
843 ((dlginit1->memopt != dlginit2->memopt) ||
844 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
845 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
850 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
852 while(!different && toolbar_item1 && toolbar_item2) {
853 if((toolbar_item1->id && !toolbar_item2->id) ||
854 (!toolbar_item1->id && toolbar_item2->id))
856 toolbar_item1 = toolbar_item1->next;
857 toolbar_item2 = toolbar_item2->next;
860 ((toolbar_item1 && !toolbar_item2) ||
861 (!toolbar_item1 && toolbar_item2)))
866 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
869 ((toolbar1->memopt != toolbar2->memopt) ||
870 (toolbar1->lvc.version != toolbar2->lvc.version) ||
871 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
874 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
878 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
881 ((ani_curico1->memopt != ani_curico2->memopt) ||
882 (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
883 (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
888 static int compare(resource_t *resource1, resource_t *resource2) {
889 switch(resource1->type) {
891 return compare_accelerator(resource1->res.acc, resource2->res.acc);
893 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
895 return compare_cursor(resource1->res.cur, resource2->res.cur);
897 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
899 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
901 return compare_dialogex(resource1->res.dlgex, resource2->res.dlgex);
903 return compare_font(resource1->res.fnt, resource2->res.fnt);
905 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
907 return compare_icon(resource1->res.ico, resource2->res.ico);
909 return compare_icon_group(resource1->res.icog, resource2->res.icog);
911 return compare_menu(resource1->res.men, resource2->res.men);
913 return compare_menuex(resource1->res.menex, resource2->res.menex);
915 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
917 return compare_stringtable(resource1->res.stt, resource2->res.stt);
919 return compare_user(resource1->res.usr, resource2->res.usr);
921 return compare_messagetable(resource1->res.msg, resource2->res.msg);
923 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
925 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
927 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
930 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
932 /* Not supposed to reach here */
933 fprintf(stderr, "Not supposed to reach here (compare())\n");
939 void verify_translations(resource_t *top) {
940 enum lang_type_e lang_type;
946 int nb_problems, last_problem;
947 int complete, needs_work, partial;
948 resource_t *next = top;
950 for(res_type = res_0; res_type <= res_usr; res_type++) {
951 present_resources[res_type] = 0;
952 for(lang_type = lang_type_master; lang_type <= lang_type_normal; lang_type++) {
953 nb_resources[res_type][lang_type] = 0;
954 list_resources[res_type][lang_type] = NULL;
984 fprintf(stderr, "Report this: unknown resource type parsed %08x\n", next->type);
988 present_resources[res_acc] = 1;
989 res_names[res_acc] = strdup("accelerator");
990 present_resources[res_bmp] = 1;
991 res_names[res_bmp] = strdup("bitmap");
992 present_resources[res_cur] = 1;
993 res_names[res_cur] = strdup("cursor");
994 present_resources[res_curg] = 1;
995 res_names[res_curg] = strdup("cursor_group");
996 present_resources[res_dlg] = 1;
997 res_names[res_dlg] = strdup("dialog");
998 present_resources[res_dlgex] = 1;
999 res_names[res_dlgex] = strdup("dialogex");
1000 present_resources[res_fnt] = 1;
1001 res_names[res_fnt] = strdup("font");
1002 present_resources[res_fntdir] = 1;
1003 res_names[res_fntdir] = strdup("fontdir");
1004 present_resources[res_ico] = 1;
1005 res_names[res_ico] = strdup("icon");
1006 present_resources[res_icog] = 1;
1007 res_names[res_icog] = strdup("icon_group");
1008 present_resources[res_men] = 1;
1009 res_names[res_men] = strdup("menu");
1010 present_resources[res_menex] = 1;
1011 res_names[res_menex] = strdup("menuex");
1012 present_resources[res_rdt] = 1;
1013 res_names[res_rdt] = strdup("rcdata");
1014 present_resources[res_stt] = 1;
1015 res_names[res_stt] = strdup("stringtable");
1016 present_resources[res_usr] = 1;
1017 res_names[res_usr] = strdup("user");
1018 present_resources[res_msg] = 1;
1019 res_names[res_msg] = strdup("messagetable");
1020 present_resources[res_ver] = 1;
1021 res_names[res_ver] = strdup("versioninfo");
1022 present_resources[res_dlginit] = 1;
1023 res_names[res_dlginit] = strdup("dlginit");
1024 present_resources[res_toolbar] = 1;
1025 res_names[res_toolbar] = strdup("toolbar");
1026 present_resources[res_anicur] = 1;
1027 res_names[res_anicur] = strdup("ani_cursor");
1028 present_resources[res_aniico] = 1;
1029 res_names[res_aniico] = strdup("ani_icon");
1031 for(res_type = res_0; res_type <= res_usr; res_type++) {
1032 if(!present_resources[res_type]) {
1035 if(nb_resources[res_type][lang_type_normal] > 0) {
1036 if(nb_resources[res_type][lang_type_master] && nb_resources[res_type][lang_type_neutral]) {
1037 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1038 fprintf(stderr, "There are both a NEUTRAL and a MASTER version for %s, along with additional localized versions. The NEUTRAL versions will not be checked against other versions.\n", res_names[res_type]);
1039 } else if(nb_resources[res_type][lang_type_neutral]) {
1040 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1041 fprintf(stderr, "There are no MASTER version, but there are some NEUTRAL versions for %s, so will use those instead of MASTER for comparison.\n", res_names[res_type]);
1042 list_resources[res_type][lang_type_master] = list_resources[res_type][lang_type_neutral];
1043 nb_resources[res_type][lang_type_master] = nb_resources[res_type][lang_type_neutral];
1044 } else if(!nb_resources[res_type][lang_type_master]) {
1045 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1046 fprintf(stderr, "There are no NEUTRAL nor MASTER versions for %s, but there are some other localized versions. No comparison will be done at all.\n", res_names[res_type]);
1049 if(nb_resources[res_type][lang_type_master] && nb_resources[res_type][lang_type_neutral]) {
1050 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1051 fprintf(stderr, "There are both a NEUTRAL and a MASTER versions for %s, but no other localized version. No comparison will be done at all.\n", res_names[res_type]);
1052 } else if(nb_resources[res_type][lang_type_master]) {
1053 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1054 fprintf(stderr, "There are only MASTER versions for %s. No comparison will be done at all.\n", res_names[res_type]);
1055 } else if(nb_resources[res_type][lang_type_neutral]) {
1056 /* fprintf(stderr, "There are only NEUTRAL versions for %s. No comparison will be done at all.\n", res_names[res_type]); */
1058 /* fprintf(stderr, "There are no versions at all for %s. No comparison will be done at all.\n", res_names[res_type]); */
1062 presence = malloc(nb_resources[res_type][lang_type_master]*sizeof(int *));
1063 for(i = 0; i < nb_resources[res_type][lang_type_master]; i++) {
1064 presence[i] = calloc(NB_LANG, sizeof(int));
1065 presence[i][MASTER_LANGUAGE] = -1;
1068 for(i = 0; i < nb_resources[res_type][lang_type_normal]; i++) {
1069 for(j = 0; j < nb_resources[res_type][lang_type_master]; j++) {
1070 nameid = strdup(get_nameid_str(list_resources[res_type][lang_type_normal][i]->name));
1071 if(!strcmp(nameid, get_nameid_str(list_resources[res_type][lang_type_master][j]->name))) {
1072 if(compare(list_resources[res_type][lang_type_normal][i], list_resources[res_type][lang_type_master][j])) {
1073 presence[j][get_language_id(list_resources[res_type][lang_type_normal][i])] = 2;
1074 /* fprintf(stderr, "Differences in type %s, ID %s, for language %s\n", res_names[res_type], nameid, get_language_name(get_language_id(list_resources[res_type][lang_type_normal][i]))); */
1076 presence[j][get_language_id(list_resources[res_type][lang_type_normal][i])] = 1;
1083 problems = malloc(sizeof(char *));
1084 problems[0] = strdup("");
1087 for(i = 0; i < NB_LANG; i++) {
1091 for(j = 0; j < nb_resources[res_type][lang_type_master]; j++) {
1092 if(presence[j][i]) {
1094 if(presence[j][i] == 2) {
1096 problems = realloc(problems, (++nb_problems+1)*sizeof(char *));
1097 problems[nb_problems] = malloc(strlen(get_nameid_str(list_resources[res_type][lang_type_master][j]->name)) + 9);
1098 sprintf(problems[nb_problems], "DIFF %s %02x", get_nameid_str(list_resources[res_type][lang_type_master][j]->name), i);
1099 if(last_problem == i) {
1100 problems[nb_problems-1] = realloc(problems[nb_problems-1], strlen(problems[nb_problems-1]) + 3);
1101 strcat(problems[nb_problems-1], " \\");
1108 problems = realloc(problems, (++nb_problems+1)*sizeof(char *));
1109 problems[nb_problems] = malloc(strlen(get_nameid_str(list_resources[res_type][lang_type_master][j]->name)) + 8);
1110 sprintf(problems[nb_problems], "ABS %s %02x", get_nameid_str(list_resources[res_type][lang_type_master][j]->name), i);
1111 if(last_problem == i) {
1112 problems[nb_problems-1] = realloc(problems[nb_problems-1], strlen(problems[nb_problems-1]) + 3);
1113 strcat(problems[nb_problems-1], " \\");
1119 if(complete && partial && !needs_work) {
1120 /* Support is complete, no need to do anything */
1121 /* fprintf(stderr, "Support for language %s is complete for %s.\n", get_language_name(i), res_names[res_type]); */
1123 } else if(complete && partial && needs_work) {
1124 /* Support is incomplete (differing resources), needs work */
1125 /* fprintf(stderr, "Support for language %s is incomplete (differing resources) for %s.\n", get_language_name(i), res_names[res_type]); */
1127 } else if(!complete && partial && !needs_work) {
1128 /* Support is incomplete (missing resources), needs work */
1129 /* fprintf(stderr, "Support for language %s is incomplete (missing resources) for %s.\n", get_language_name(i), res_names[res_type]); */
1131 } else if(!complete && partial && needs_work) {
1132 /* Support is incomplete (missing and differing resources), needs work */
1133 /* fprintf(stderr, "Support for language %s is incomplete (missing and differing resources) for %s.\n", get_language_name(i), res_names[res_type]); */
1135 } else if(!complete && !partial) {
1136 /* Support is totally absent, might be interesting to do */
1137 /* fprintf(stderr, "Support for language %s is absent for %s.\n", get_language_name(i), res_names[res_type]); */
1140 /* Support is not relevant, no need to do anything */
1141 /* fprintf(stderr, "Support for language %s is not relevant for %s.\n", get_language_name(i), res_names[res_type]); */
1146 for(i = 1; i <= nb_problems; i++) {
1147 printf("%s\n", problems[i]);
1152 for(i = 0; i < nb_resources[res_type][lang_type_master]; i++)