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
24 #define MASTER_LANGUAGE LANG_ENGLISH
33 static int present_resources[res_usr+1];
34 static char *res_names[res_usr+1];
35 static int nb_resources[res_usr+1][lang_type_normal+1];
36 static resource_t **list_resources[res_usr+1][lang_type_normal+1];
38 static int get_language_id(resource_t *resource) {
39 switch(resource->type) {
41 return resource->res.acc->lvc.language->id;
43 return resource->res.bmp->data->lvc.language->id;
45 return resource->res.cur->lvc.language->id;
47 return resource->res.curg->lvc.language->id;
49 return resource->res.dlg->lvc.language->id;
51 return resource->res.dlgex->lvc.language->id;
53 return resource->res.fnt->data->lvc.language->id;
55 return resource->res.fnd->data->lvc.language->id;
57 return resource->res.ico->lvc.language->id;
59 return resource->res.icog->lvc.language->id;
61 return resource->res.men->lvc.language->id;
63 return resource->res.menex->lvc.language->id;
65 return resource->res.rdt->data->lvc.language->id;
67 return resource->res.stt->lvc.language->id;
69 return resource->res.usr->data->lvc.language->id;
71 return resource->res.msg->data->lvc.language->id;
73 return resource->res.ver->lvc.language->id;
75 return resource->res.dlgi->data->lvc.language->id;
77 return resource->res.tbt->lvc.language->id;
80 return resource->res.ani->data->lvc.language->id;
82 /* Not supposed to reach here */
83 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
89 static void add_resource(resource_t *resource) {
90 enum lang_type_e lang_type;
91 enum res_e res_type = resource->type;
92 int lid = get_language_id(resource);
94 if(lid == MASTER_LANGUAGE) {
95 lang_type = lang_type_master;
96 } else if(lid == LANG_NEUTRAL) {
97 lang_type = lang_type_neutral;
99 lang_type = lang_type_normal;
101 nb_resources[res_type][lang_type]++;
102 list_resources[res_type][lang_type] = realloc(list_resources[res_type][lang_type], nb_resources[res_type][lang_type]*sizeof(resource_t *));
103 list_resources[res_type][lang_type][nb_resources[res_type][lang_type]-1] = resource;
108 #define PRETTYPRINTLANG(langid) \
109 if(LANG_##langid == lid) { \
113 static const char *get_language_name(int lid) {
114 PRETTYPRINTLANG(NEUTRAL)
115 PRETTYPRINTLANG(AFRIKAANS)
116 PRETTYPRINTLANG(ALBANIAN)
117 PRETTYPRINTLANG(ARABIC)
118 PRETTYPRINTLANG(ARMENIAN)
119 PRETTYPRINTLANG(ASSAMESE)
120 PRETTYPRINTLANG(AZERI)
121 PRETTYPRINTLANG(BASQUE)
122 PRETTYPRINTLANG(BELARUSIAN)
123 PRETTYPRINTLANG(BENGALI)
124 PRETTYPRINTLANG(BULGARIAN)
125 PRETTYPRINTLANG(CATALAN)
126 PRETTYPRINTLANG(CHINESE)
127 PRETTYPRINTLANG(CROATIAN)
128 PRETTYPRINTLANG(CZECH)
129 PRETTYPRINTLANG(DANISH)
130 PRETTYPRINTLANG(DIVEHI)
131 PRETTYPRINTLANG(DUTCH)
132 PRETTYPRINTLANG(ENGLISH)
133 PRETTYPRINTLANG(ESTONIAN)
134 PRETTYPRINTLANG(FAEROESE)
135 PRETTYPRINTLANG(FARSI)
136 PRETTYPRINTLANG(FINNISH)
137 PRETTYPRINTLANG(FRENCH)
138 PRETTYPRINTLANG(GALICIAN)
139 PRETTYPRINTLANG(GEORGIAN)
140 PRETTYPRINTLANG(GERMAN)
141 PRETTYPRINTLANG(GREEK)
142 PRETTYPRINTLANG(GUJARATI)
143 PRETTYPRINTLANG(HEBREW)
144 PRETTYPRINTLANG(HINDI)
145 PRETTYPRINTLANG(HUNGARIAN)
146 PRETTYPRINTLANG(ICELANDIC)
147 PRETTYPRINTLANG(INDONESIAN)
148 PRETTYPRINTLANG(ITALIAN)
149 PRETTYPRINTLANG(JAPANESE)
150 PRETTYPRINTLANG(KANNADA)
151 PRETTYPRINTLANG(KASHMIRI)
152 PRETTYPRINTLANG(KAZAK)
153 PRETTYPRINTLANG(KONKANI)
154 PRETTYPRINTLANG(KOREAN)
155 PRETTYPRINTLANG(KYRGYZ)
156 PRETTYPRINTLANG(LATVIAN)
157 PRETTYPRINTLANG(LITHUANIAN)
158 PRETTYPRINTLANG(MACEDONIAN)
159 PRETTYPRINTLANG(MALAY)
160 PRETTYPRINTLANG(MALAYALAM)
161 PRETTYPRINTLANG(MANIPURI)
162 PRETTYPRINTLANG(MARATHI)
163 PRETTYPRINTLANG(MONGOLIAN)
164 PRETTYPRINTLANG(NEPALI)
165 PRETTYPRINTLANG(NORWEGIAN)
166 PRETTYPRINTLANG(ORIYA)
167 PRETTYPRINTLANG(POLISH)
168 PRETTYPRINTLANG(PORTUGUESE)
169 PRETTYPRINTLANG(PUNJABI)
170 PRETTYPRINTLANG(ROMANIAN)
171 PRETTYPRINTLANG(RUSSIAN)
172 PRETTYPRINTLANG(SANSKRIT)
173 PRETTYPRINTLANG(SERBIAN)
174 PRETTYPRINTLANG(SINDHI)
175 PRETTYPRINTLANG(SLOVAK)
176 PRETTYPRINTLANG(SLOVENIAN)
177 PRETTYPRINTLANG(SPANISH)
178 PRETTYPRINTLANG(SWAHILI)
179 PRETTYPRINTLANG(SWEDISH)
180 PRETTYPRINTLANG(SYRIAC)
181 PRETTYPRINTLANG(TAMIL)
182 PRETTYPRINTLANG(TATAR)
183 PRETTYPRINTLANG(TELUGU)
184 PRETTYPRINTLANG(THAI)
185 PRETTYPRINTLANG(TURKISH)
186 PRETTYPRINTLANG(UKRAINIAN)
187 PRETTYPRINTLANG(URDU)
188 PRETTYPRINTLANG(UZBEK)
189 PRETTYPRINTLANG(VIETNAMESE)
190 PRETTYPRINTLANG(GAELIC)
191 PRETTYPRINTLANG(MALTESE)
192 PRETTYPRINTLANG(MAORI)
193 PRETTYPRINTLANG(RHAETO_ROMANCE)
194 PRETTYPRINTLANG(SAAMI)
195 PRETTYPRINTLANG(SORBIAN)
196 PRETTYPRINTLANG(SUTU)
197 PRETTYPRINTLANG(TSONGA)
198 PRETTYPRINTLANG(TSWANA)
199 PRETTYPRINTLANG(VENDA)
200 PRETTYPRINTLANG(XHOSA)
201 PRETTYPRINTLANG(ZULU)
202 PRETTYPRINTLANG(ESPERANTO)
203 PRETTYPRINTLANG(WALON)
204 PRETTYPRINTLANG(CORNISH)
205 PRETTYPRINTLANG(WELSH)
206 PRETTYPRINTLANG(BRETON)
207 return "Unkown language";
211 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
213 event_t *ev1 = NULL, *ev2 = NULL;
215 ((accelerator1->memopt != accelerator2->memopt) ||
216 (accelerator1->lvc.version != accelerator2->lvc.version) ||
217 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
219 ev1 = accelerator1->events;
220 ev2 = accelerator2->events;
221 while(!different && ev1 && ev2) {
223 ((ev1->id != ev2->id) ||
224 (ev1->flags != ev2->flags)))
230 ((ev1 && !ev2) || (!ev1 && ev2)))
235 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
238 ((bitmap1->memopt != bitmap2->memopt) ||
239 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
240 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
245 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
248 ((cursor1->id != cursor2->id) ||
249 (cursor1->width != cursor2->width) ||
250 (cursor1->height != cursor2->height) ||
251 (cursor1->xhot != cursor2->xhot) ||
252 (cursor1->yhot != cursor2->yhot)))
255 ((cursor1->lvc.version != cursor2->lvc.version) ||
256 (cursor1->lvc.characts != cursor2->lvc.characts)))
261 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
263 cursor_t *cursor1 = NULL, *cursor2 = NULL;
265 ((cursor_group1->memopt != cursor_group2->memopt) ||
266 (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
267 (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
270 (cursor_group1->ncursor != cursor_group2->ncursor))
273 cursor1 = cursor_group1->cursorlist;
274 cursor2 = cursor_group2->cursorlist;
275 while(!different && cursor1 && cursor2) {
276 different = compare_cursor(cursor1, cursor2);
277 cursor1 = cursor1->next;
278 cursor2 = cursor2->next;
281 ((cursor1 && !cursor2) ||
282 (!cursor1 && cursor2)))
288 static int compare_control(control_t *control1, control_t *control2) {
292 ((control1 && !control2) ||
293 (!control1 && control2)))
295 if(different || !control1 || !control2)
297 nameid = strdup(get_nameid_str(control1->ctlclass));
298 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
302 (control1->id != control2->id))
304 if(!different && control1->gotstyle && control2->gotstyle) {
305 if((!control1->style || !control2->style) ||
306 (control1->style->and_mask || control2->style->and_mask) ||
307 (control1->style->or_mask != control2->style->or_mask))
309 } else if(!different &&
310 ((control1->gotstyle && !control2->gotstyle) ||
311 (!control1->gotstyle && control2->gotstyle)))
313 if(!different && control1->gotexstyle && control2->gotexstyle) {
314 if((!control1->exstyle || !control2->exstyle) ||
315 (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
316 (control1->exstyle->or_mask != control2->exstyle->or_mask))
318 } else if(!different &&
319 ((control1->gotexstyle && !control2->gotexstyle) ||
320 (!control1->gotexstyle && control2->gotexstyle)))
322 if(!different && control1->gothelpid && control2->gothelpid) {
323 if(control1->helpid != control2->helpid)
325 } else if(!different &&
326 ((control1->gothelpid && !control2->gothelpid) ||
327 (!control1->gothelpid && control2->gothelpid)))
332 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
336 ((dialog1->memopt != dialog2->memopt) ||
337 (dialog1->lvc.version != dialog2->lvc.version) ||
338 (dialog1->lvc.characts != dialog2->lvc.characts)))
340 if(!different && dialog1->gotstyle && dialog2->gotstyle) {
341 if((!dialog1->style || !dialog2->style) ||
342 (dialog1->style->and_mask || dialog2->style->and_mask) ||
343 (dialog1->style->or_mask != dialog2->style->or_mask))
345 } else if(!different &&
346 ((dialog1->gotstyle && !dialog2->gotstyle) ||
347 (!dialog1->gotstyle && dialog2->gotstyle)))
349 if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
350 if((!dialog1->exstyle || !dialog2->exstyle) ||
351 (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
352 (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
354 } else if(!different &&
355 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
356 (!dialog1->gotexstyle && dialog2->gotexstyle)))
358 nameid = strdup(get_nameid_str(dialog1->menu));
359 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
362 nameid = strdup(get_nameid_str(dialog1->dlgclass));
363 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
367 different = compare_control(dialog1->controls, dialog2->controls);
371 static int compare_dialogex(dialogex_t *dialogex1, dialogex_t *dialogex2) {
375 ((dialogex1->memopt != dialogex2->memopt) ||
376 (dialogex1->lvc.version != dialogex2->lvc.version) ||
377 (dialogex1->lvc.characts != dialogex2->lvc.characts)))
379 if(!different && dialogex1->gotstyle && dialogex2->gotstyle) {
380 if((!dialogex1->style || !dialogex2->style) ||
381 (dialogex1->style->and_mask || dialogex2->style->and_mask) ||
382 (dialogex1->style->or_mask != dialogex2->style->or_mask))
384 } else if(!different &&
385 ((dialogex1->gotstyle && !dialogex2->gotstyle) ||
386 (!dialogex1->gotstyle && dialogex2->gotstyle)))
388 if(!different && dialogex1->gotexstyle && dialogex2->gotexstyle) {
389 if((!dialogex1->exstyle || !dialogex2->exstyle) ||
390 (dialogex1->exstyle->and_mask || dialogex2->exstyle->and_mask) ||
391 (dialogex1->exstyle->or_mask != dialogex2->exstyle->or_mask))
393 } else if(!different &&
394 ((dialogex1->gotexstyle && !dialogex2->gotexstyle) ||
395 (!dialogex1->gotexstyle && dialogex2->gotexstyle)))
397 if(!different && dialogex1->gothelpid && dialogex2->gothelpid) {
398 if(dialogex1->helpid != dialogex2->helpid)
400 } else if(!different &&
401 ((dialogex1->gothelpid && !dialogex2->gothelpid) ||
402 (!dialogex1->gothelpid && dialogex2->gothelpid)))
404 nameid = strdup(get_nameid_str(dialogex1->menu));
405 if(!different && strcmp(nameid, get_nameid_str(dialogex2->menu)))
408 nameid = strdup(get_nameid_str(dialogex1->dlgclass));
409 if(!different && strcmp(nameid, get_nameid_str(dialogex2->dlgclass)))
413 different = compare_control(dialogex1->controls, dialogex2->controls);
417 static int compare_font(font_t *font1, font_t *font2) {
420 ((font1->memopt != font2->memopt) ||
421 (font1->data->lvc.version != font2->data->lvc.version) ||
422 (font1->data->lvc.characts != font2->data->lvc.characts)))
427 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
430 ((fontdir1->memopt != fontdir2->memopt) ||
431 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
432 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
437 static int compare_icon(icon_t *icon1, icon_t *icon2) {
440 ((icon1->id != icon2->id) ||
441 (icon1->width != icon2->width) ||
442 (icon1->height != icon2->height)))
445 ((icon1->lvc.version != icon2->lvc.version) ||
446 (icon1->lvc.characts != icon2->lvc.characts)))
451 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
453 icon_t *icon1 = NULL, *icon2 = NULL;
455 ((icon_group1->memopt != icon_group2->memopt) ||
456 (icon_group1->lvc.version != icon_group2->lvc.version) ||
457 (icon_group1->lvc.characts != icon_group2->lvc.characts)))
460 (icon_group1->nicon != icon_group2->nicon))
463 icon1 = icon_group1->iconlist;
464 icon2 = icon_group2->iconlist;
465 while(!different && icon1 && icon2) {
466 different = compare_icon(icon1, icon2);
471 ((icon1 && !icon2) ||
478 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
480 while(!different && menu_item1 && menu_item2) {
481 if(menu_item1->popup && menu_item2->popup)
482 different = compare_menu_item(menu_item1->popup, menu_item2->popup);
483 else if(!menu_item1->popup && !menu_item2->popup) {
484 if(menu_item1->name && menu_item2->name) {
485 if((menu_item1->id != menu_item2->id) ||
486 (menu_item1->state != menu_item2->state))
488 } else if((menu_item1->name && !menu_item2->name) ||
489 (!menu_item1->name && menu_item2->name))
493 menu_item1 = menu_item1->next;
494 menu_item2 = menu_item2->next;
497 ((menu_item1 && !menu_item2) ||
498 (!menu_item1 && menu_item2)))
503 static int compare_menu(menu_t *menu1, menu_t *menu2) {
506 ((menu1->memopt != menu2->memopt) ||
507 (menu1->lvc.version != menu2->lvc.version) ||
508 (menu1->lvc.characts != menu2->lvc.characts)))
511 different = compare_menu_item(menu1->items, menu2->items);
515 static int compare_menuex_item(menuex_item_t *menuex_item1, menuex_item_t *menuex_item2) {
517 while(!different && menuex_item1 && menuex_item2) {
518 if(menuex_item1->popup && menuex_item2->popup) {
519 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
520 if(menuex_item1->id != menuex_item2->id)
522 } else if(!different &&
523 ((menuex_item1->gotid && !menuex_item2->gotid) ||
524 (!menuex_item2->gotid && menuex_item2->gotid)))
526 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
527 if(menuex_item1->type != menuex_item2->type)
529 } else if(!different &&
530 ((menuex_item1->gottype && !menuex_item2->gottype) ||
531 (!menuex_item2->gottype && menuex_item2->gottype)))
533 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
534 if(menuex_item1->state != menuex_item2->state)
536 } else if(!different &&
537 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
538 (!menuex_item2->gotstate && menuex_item2->gotstate)))
540 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
541 if(menuex_item1->helpid != menuex_item2->helpid)
543 } else if(!different &&
544 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
545 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
548 different = compare_menuex_item(menuex_item1->popup, menuex_item2->popup);
549 } else if(!menuex_item1->popup && !menuex_item2->popup) {
550 if(menuex_item1->name && menuex_item2->name) {
551 if(!different && menuex_item1->gotid && menuex_item2->gotid) {
552 if(menuex_item1->id != menuex_item2->id)
554 } else if(!different &&
555 ((menuex_item1->gotid && !menuex_item2->gotid) ||
556 (!menuex_item2->gotid && menuex_item2->gotid)))
558 if(!different && menuex_item1->gottype && menuex_item2->gottype) {
559 if(menuex_item1->type != menuex_item2->type)
561 } else if(!different &&
562 ((menuex_item1->gottype && !menuex_item2->gottype) ||
563 (!menuex_item2->gottype && menuex_item2->gottype)))
565 if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
566 if(menuex_item1->state != menuex_item2->state)
568 } else if(!different &&
569 ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
570 (!menuex_item2->gotstate && menuex_item2->gotstate)))
572 if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
573 if(menuex_item1->helpid != menuex_item2->helpid)
575 } else if(!different &&
576 ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
577 (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
579 } else if((menuex_item1->name && !menuex_item2->name) ||
580 (!menuex_item1->name && menuex_item2->name))
584 menuex_item1 = menuex_item1->next;
585 menuex_item2 = menuex_item2->next;
588 ((menuex_item1 && !menuex_item2) ||
589 (!menuex_item1 && menuex_item2)))
594 static int compare_menuex(menuex_t *menuex1, menuex_t *menuex2) {
597 ((menuex1->memopt != menuex2->memopt) ||
598 (menuex1->lvc.version != menuex2->lvc.version) ||
599 (menuex1->lvc.characts != menuex2->lvc.characts)))
602 different = compare_menuex_item(menuex1->items, menuex2->items);
606 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
609 ((rcdata1->memopt != rcdata2->memopt) ||
610 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
611 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
616 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
619 while(!different && stringtable1 && stringtable2) {
620 if((stringtable1->memopt != stringtable2->memopt) ||
621 (stringtable1->lvc.version != stringtable2->lvc.version) ||
622 (stringtable1->lvc.characts != stringtable2->lvc.characts))
625 if((stringtable1->nentries != stringtable2->nentries) ||
626 (stringtable1->idbase != stringtable2->idbase))
629 for(i = 0 ; i < stringtable1->nentries; i++)
630 if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
631 (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
632 (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
633 (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
638 stringtable1 = stringtable1->next;
639 stringtable2 = stringtable2->next;
644 static int compare_user(user_t *user1, user_t *user2) {
648 ((user1->memopt != user2->memopt) ||
649 (user1->data->lvc.version != user2->data->lvc.version) ||
650 (user1->data->lvc.characts != user2->data->lvc.characts)))
652 nameid = strdup(get_nameid_str(user1->type));
653 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
659 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
662 ((messagetable1->memopt != messagetable2->memopt) ||
663 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
664 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
669 static int compare_string(string_t *string1, string_t *string2) {
672 ((string1->size != string2->size) ||
673 (string1->type != string2->type)))
676 if(string1->type == str_char)
677 different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
678 else if(string1->type == str_unicode)
679 different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
686 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
688 static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
692 (ver_value1->type == ver_value2->type)) {
693 switch(ver_value1->type) {
695 if(!different && ver_value1->key && ver_value2->key)
696 different = compare_string(ver_value1->key, ver_value2->key);
697 else if(!different &&
698 ((ver_value1->key && !ver_value2->key) ||
699 (!ver_value1->key && ver_value2->key)))
703 if(!different && ver_value1->key && ver_value2->key)
704 different = compare_string(ver_value1->key, ver_value2->key);
705 else if(!different &&
706 ((ver_value1->key && !ver_value2->key) ||
707 (!ver_value1->key && ver_value2->key)))
709 if(!different && ver_value1->value.words && ver_value2->value.words) {
711 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
714 for(i = 0; i < ver_value1->value.words->nwords; i++) {
715 if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
720 } else if(!different &&
721 ((ver_value1->value.words && !ver_value2->value.words) ||
722 (!ver_value1->value.words && ver_value2->value.words)))
726 if(!different && ver_value1->value.block && ver_value2->value.block)
727 different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
728 else if(!different &&
729 ((ver_value1->value.block && !ver_value2->value.block) ||
730 (!ver_value1->value.block && ver_value2->value.block)))
741 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
743 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
745 ver_value1 = ver_block1->values;
746 ver_value2 = ver_block2->values;
747 while(!different && ver_value1 && ver_value2) {
748 different = compare_ver_value(ver_value1, ver_value2);
749 ver_value1 = ver_value1->next;
750 ver_value2 = ver_value2->next;
753 ((ver_value1 && !ver_value2) ||
754 (!ver_value1 && ver_value2)))
760 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
762 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
764 ((versioninfo1->memopt != versioninfo2->memopt) ||
765 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
766 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
768 if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
769 if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
770 (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
771 (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
772 (versioninfo1->filever_min2 != versioninfo2->filever_min2))
774 } else if(!different &&
775 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
776 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
778 if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
779 if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
780 (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
781 (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
782 (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
784 } else if(!different &&
785 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
786 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
788 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
789 if(versioninfo1->fileos != versioninfo2->fileos)
791 } else if(!different &&
792 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
793 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
795 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
796 if(versioninfo1->fileflags != versioninfo2->fileflags)
798 } else if(!different &&
799 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
800 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
802 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
803 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
805 } else if(!different &&
806 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
807 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
809 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
810 if(versioninfo1->filetype != versioninfo2->filetype)
812 } else if(!different &&
813 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
814 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
816 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
817 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
819 } else if(!different &&
820 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
821 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
824 ver_block1 = versioninfo1->blocks;
825 ver_block2 = versioninfo2->blocks;
826 while(!different && ver_block1 && ver_block2) {
827 different = compare_ver_block(ver_block1, ver_block2);
828 ver_block1 = ver_block1->next;
829 ver_block2 = ver_block2->next;
832 ((ver_block1 && !ver_block2) ||
833 (ver_block1 && !ver_block2)))
839 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
842 ((dlginit1->memopt != dlginit2->memopt) ||
843 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
844 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
849 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
851 while(!different && toolbar_item1 && toolbar_item2) {
852 if((toolbar_item1->id && !toolbar_item2->id) ||
853 (!toolbar_item1->id && toolbar_item2->id))
855 toolbar_item1 = toolbar_item1->next;
856 toolbar_item2 = toolbar_item2->next;
859 ((toolbar_item1 && !toolbar_item2) ||
860 (!toolbar_item1 && toolbar_item2)))
865 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
868 ((toolbar1->memopt != toolbar2->memopt) ||
869 (toolbar1->lvc.version != toolbar2->lvc.version) ||
870 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
873 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
877 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
880 ((ani_curico1->memopt != ani_curico2->memopt) ||
881 (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
882 (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
887 static int compare(resource_t *resource1, resource_t *resource2) {
888 switch(resource1->type) {
890 return compare_accelerator(resource1->res.acc, resource2->res.acc);
892 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
894 return compare_cursor(resource1->res.cur, resource2->res.cur);
896 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
898 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
900 return compare_dialogex(resource1->res.dlgex, resource2->res.dlgex);
902 return compare_font(resource1->res.fnt, resource2->res.fnt);
904 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
906 return compare_icon(resource1->res.ico, resource2->res.ico);
908 return compare_icon_group(resource1->res.icog, resource2->res.icog);
910 return compare_menu(resource1->res.men, resource2->res.men);
912 return compare_menuex(resource1->res.menex, resource2->res.menex);
914 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
916 return compare_stringtable(resource1->res.stt, resource2->res.stt);
918 return compare_user(resource1->res.usr, resource2->res.usr);
920 return compare_messagetable(resource1->res.msg, resource2->res.msg);
922 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
924 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
926 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
929 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
931 /* Not supposed to reach here */
932 fprintf(stderr, "Not supposed to reach here (compare())\n");
938 void verify_translations(resource_t *top) {
939 enum lang_type_e lang_type;
945 int nb_problems, last_problem;
946 int complete, needs_work, partial;
947 resource_t *next = top;
949 for(res_type = res_0; res_type <= res_usr; res_type++) {
950 present_resources[res_type] = 0;
951 for(lang_type = lang_type_master; lang_type <= lang_type_normal; lang_type++) {
952 nb_resources[res_type][lang_type] = 0;
953 list_resources[res_type][lang_type] = NULL;
983 fprintf(stderr, "Report this: unkown resource type parsed %08x\n", next->type);
987 present_resources[res_acc] = 1;
988 res_names[res_acc] = strdup("accelerator");
989 present_resources[res_bmp] = 1;
990 res_names[res_bmp] = strdup("bitmap");
991 present_resources[res_cur] = 1;
992 res_names[res_cur] = strdup("cursor");
993 present_resources[res_curg] = 1;
994 res_names[res_curg] = strdup("cursor_group");
995 present_resources[res_dlg] = 1;
996 res_names[res_dlg] = strdup("dialog");
997 present_resources[res_dlgex] = 1;
998 res_names[res_dlgex] = strdup("dialogex");
999 present_resources[res_fnt] = 1;
1000 res_names[res_fnt] = strdup("font");
1001 present_resources[res_fntdir] = 1;
1002 res_names[res_fntdir] = strdup("fontdir");
1003 present_resources[res_ico] = 1;
1004 res_names[res_ico] = strdup("icon");
1005 present_resources[res_icog] = 1;
1006 res_names[res_icog] = strdup("icon_group");
1007 present_resources[res_men] = 1;
1008 res_names[res_men] = strdup("menu");
1009 present_resources[res_menex] = 1;
1010 res_names[res_menex] = strdup("menuex");
1011 present_resources[res_rdt] = 1;
1012 res_names[res_rdt] = strdup("rcdata");
1013 present_resources[res_stt] = 1;
1014 res_names[res_stt] = strdup("stringtable");
1015 present_resources[res_usr] = 1;
1016 res_names[res_usr] = strdup("user");
1017 present_resources[res_msg] = 1;
1018 res_names[res_msg] = strdup("messagetable");
1019 present_resources[res_ver] = 1;
1020 res_names[res_ver] = strdup("versioninfo");
1021 present_resources[res_dlginit] = 1;
1022 res_names[res_dlginit] = strdup("dlginit");
1023 present_resources[res_toolbar] = 1;
1024 res_names[res_toolbar] = strdup("toolbar");
1025 present_resources[res_anicur] = 1;
1026 res_names[res_anicur] = strdup("ani_cursor");
1027 present_resources[res_aniico] = 1;
1028 res_names[res_aniico] = strdup("ani_icon");
1030 for(res_type = res_0; res_type <= res_usr; res_type++) {
1031 if(!present_resources[res_type]) {
1034 if(nb_resources[res_type][lang_type_normal] > 0) {
1035 if(nb_resources[res_type][lang_type_master] && nb_resources[res_type][lang_type_neutral]) {
1036 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1037 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]);
1038 } else if(nb_resources[res_type][lang_type_neutral]) {
1039 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1040 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]);
1041 list_resources[res_type][lang_type_master] = list_resources[res_type][lang_type_neutral];
1042 nb_resources[res_type][lang_type_master] = nb_resources[res_type][lang_type_neutral];
1043 } else if(!nb_resources[res_type][lang_type_master]) {
1044 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1045 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]);
1048 if(nb_resources[res_type][lang_type_master] && nb_resources[res_type][lang_type_neutral]) {
1049 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1050 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]);
1051 } else if(nb_resources[res_type][lang_type_master]) {
1052 fprintf(stderr, "Type %s:\n", res_names[res_type]);
1053 fprintf(stderr, "There are only MASTER versions for %s. No comparison will be done at all.\n", res_names[res_type]);
1054 } else if(nb_resources[res_type][lang_type_neutral]) {
1055 /* fprintf(stderr, "There are only NEUTRAL versions for %s. No comparison will be done at all.\n", res_names[res_type]); */
1057 /* fprintf(stderr, "There are no versions at all for %s. No comparison will be done at all.\n", res_names[res_type]); */
1061 presence = malloc(nb_resources[res_type][lang_type_master]*sizeof(int *));
1062 for(i = 0; i < nb_resources[res_type][lang_type_master]; i++) {
1063 presence[i] = calloc(NB_LANG, sizeof(int));
1064 presence[i][MASTER_LANGUAGE] = -1;
1067 for(i = 0; i < nb_resources[res_type][lang_type_normal]; i++) {
1068 for(j = 0; j < nb_resources[res_type][lang_type_master]; j++) {
1069 nameid = strdup(get_nameid_str(list_resources[res_type][lang_type_normal][i]->name));
1070 if(!strcmp(nameid, get_nameid_str(list_resources[res_type][lang_type_master][j]->name))) {
1071 if(compare(list_resources[res_type][lang_type_normal][i], list_resources[res_type][lang_type_master][j])) {
1072 presence[j][get_language_id(list_resources[res_type][lang_type_normal][i])] = 2;
1073 /* 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]))); */
1075 presence[j][get_language_id(list_resources[res_type][lang_type_normal][i])] = 1;
1082 problems = malloc(sizeof(char *));
1083 problems[0] = strdup("");
1086 for(i = 0; i < NB_LANG; i++) {
1090 for(j = 0; j < nb_resources[res_type][lang_type_master]; j++) {
1091 if(presence[j][i]) {
1093 if(presence[j][i] == 2) {
1095 problems = realloc(problems, (++nb_problems+1)*sizeof(char *));
1096 problems[nb_problems] = malloc(strlen(get_nameid_str(list_resources[res_type][lang_type_master][j]->name)) + 9);
1097 sprintf(problems[nb_problems], "DIFF %s %02x", get_nameid_str(list_resources[res_type][lang_type_master][j]->name), i);
1098 if(last_problem == i) {
1099 problems[nb_problems-1] = realloc(problems[nb_problems-1], strlen(problems[nb_problems-1]) + 3);
1100 strcat(problems[nb_problems-1], " \\");
1107 problems = realloc(problems, (++nb_problems+1)*sizeof(char *));
1108 problems[nb_problems] = malloc(strlen(get_nameid_str(list_resources[res_type][lang_type_master][j]->name)) + 8);
1109 sprintf(problems[nb_problems], "ABS %s %02x", get_nameid_str(list_resources[res_type][lang_type_master][j]->name), i);
1110 if(last_problem == i) {
1111 problems[nb_problems-1] = realloc(problems[nb_problems-1], strlen(problems[nb_problems-1]) + 3);
1112 strcat(problems[nb_problems-1], " \\");
1118 if(complete && partial && !needs_work) {
1119 /* Support is complete, no need to do anything */
1120 /* fprintf(stderr, "Support for language %s is complete for %s.\n", get_language_name(i), res_names[res_type]); */
1122 } else if(complete && partial && needs_work) {
1123 /* Support is incomplete (differing resources), needs work */
1124 /* fprintf(stderr, "Support for language %s is incomplete (differing resources) for %s.\n", get_language_name(i), res_names[res_type]); */
1126 } else if(!complete && partial && !needs_work) {
1127 /* Support is incomplete (missing resources), needs work */
1128 /* fprintf(stderr, "Support for language %s is incomplete (missing resources) for %s.\n", get_language_name(i), res_names[res_type]); */
1130 } else if(!complete && partial && needs_work) {
1131 /* Support is incomplete (missing and differing resources), needs work */
1132 /* fprintf(stderr, "Support for language %s is incomplete (missing and differing resources) for %s.\n", get_language_name(i), res_names[res_type]); */
1134 } else if(!complete && !partial) {
1135 /* Support is totally absent, might be interesting to do */
1136 /* fprintf(stderr, "Support for language %s is absent for %s.\n", get_language_name(i), res_names[res_type]); */
1139 /* Support is not relevant, no need to do anything */
1140 /* fprintf(stderr, "Support for language %s is not relevant for %s.\n", get_language_name(i), res_names[res_type]); */
1145 for(i = 1; i <= nb_problems; i++) {
1146 printf("%s\n", problems[i]);
1151 for(i = 0; i < nb_resources[res_type][lang_type_master]; i++)