2 * Copyright 2003 Vincent BĂ©ron
3 * Copyright 2007, 2008 Mikolaj Zalewski
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #define MASTER_LANGUAGE LANG_ENGLISH
29 #define MASTER_SUBLANGUAGE SUBLANG_ENGLISH_US
38 static language_t get_language(resource_t *resource) {
39 switch(resource->type) {
41 return *resource->res.acc->lvc.language;
43 return *resource->res.bmp->data->lvc.language;
45 return *resource->res.cur->lvc.language;
47 return *resource->res.curg->lvc.language;
49 return *resource->res.dlg->lvc.language;
51 return *resource->res.fnt->data->lvc.language;
53 return *resource->res.fnd->data->lvc.language;
55 return *resource->res.ico->lvc.language;
57 return *resource->res.icog->lvc.language;
59 return *resource->res.men->lvc.language;
61 return *resource->res.rdt->data->lvc.language;
63 return *resource->res.stt->lvc.language;
65 return *resource->res.usr->data->lvc.language;
67 return *resource->res.msg->data->lvc.language;
69 return *resource->res.ver->lvc.language;
71 return *resource->res.dlgi->data->lvc.language;
73 return *resource->res.tbt->lvc.language;
76 return *resource->res.ani->data->lvc.language;
78 return *resource->res.html->data->lvc.language;
80 /* Not supposed to reach here */
81 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
86 static int get_language_id(resource_t *resource) {
87 return get_language(resource).id;
90 static int compare_lang(language_t lang1, language_t lang2)
92 return memcmp(&lang1, &lang2, sizeof(language_t));
97 #define PRETTYPRINTLANG(langid) \
98 if(LANG_##langid == lid) { \
102 static const char *get_language_name(int lid) {
103 PRETTYPRINTLANG(NEUTRAL)
104 PRETTYPRINTLANG(AFRIKAANS)
105 PRETTYPRINTLANG(ALBANIAN)
106 PRETTYPRINTLANG(ARABIC)
107 PRETTYPRINTLANG(ARMENIAN)
108 PRETTYPRINTLANG(ASSAMESE)
109 PRETTYPRINTLANG(AZERI)
110 PRETTYPRINTLANG(BASQUE)
111 PRETTYPRINTLANG(BELARUSIAN)
112 PRETTYPRINTLANG(BENGALI)
113 PRETTYPRINTLANG(BULGARIAN)
114 PRETTYPRINTLANG(CATALAN)
115 PRETTYPRINTLANG(CHINESE)
116 PRETTYPRINTLANG(CROATIAN)
117 PRETTYPRINTLANG(CZECH)
118 PRETTYPRINTLANG(DANISH)
119 PRETTYPRINTLANG(DIVEHI)
120 PRETTYPRINTLANG(DUTCH)
121 PRETTYPRINTLANG(ENGLISH)
122 PRETTYPRINTLANG(ESTONIAN)
123 PRETTYPRINTLANG(FAEROESE)
124 PRETTYPRINTLANG(FARSI)
125 PRETTYPRINTLANG(FINNISH)
126 PRETTYPRINTLANG(FRENCH)
127 PRETTYPRINTLANG(GALICIAN)
128 PRETTYPRINTLANG(GEORGIAN)
129 PRETTYPRINTLANG(GERMAN)
130 PRETTYPRINTLANG(GREEK)
131 PRETTYPRINTLANG(GUJARATI)
132 PRETTYPRINTLANG(HEBREW)
133 PRETTYPRINTLANG(HINDI)
134 PRETTYPRINTLANG(HUNGARIAN)
135 PRETTYPRINTLANG(ICELANDIC)
136 PRETTYPRINTLANG(INDONESIAN)
137 PRETTYPRINTLANG(ITALIAN)
138 PRETTYPRINTLANG(JAPANESE)
139 PRETTYPRINTLANG(KANNADA)
140 PRETTYPRINTLANG(KASHMIRI)
141 PRETTYPRINTLANG(KAZAK)
142 PRETTYPRINTLANG(KONKANI)
143 PRETTYPRINTLANG(KOREAN)
144 PRETTYPRINTLANG(KYRGYZ)
145 PRETTYPRINTLANG(LATVIAN)
146 PRETTYPRINTLANG(LITHUANIAN)
147 PRETTYPRINTLANG(MACEDONIAN)
148 PRETTYPRINTLANG(MALAY)
149 PRETTYPRINTLANG(MALAYALAM)
150 PRETTYPRINTLANG(MANIPURI)
151 PRETTYPRINTLANG(MARATHI)
152 PRETTYPRINTLANG(MONGOLIAN)
153 PRETTYPRINTLANG(NEPALI)
154 PRETTYPRINTLANG(NORWEGIAN)
155 PRETTYPRINTLANG(ORIYA)
156 PRETTYPRINTLANG(POLISH)
157 PRETTYPRINTLANG(PORTUGUESE)
158 PRETTYPRINTLANG(PUNJABI)
159 PRETTYPRINTLANG(ROMANIAN)
160 PRETTYPRINTLANG(RUSSIAN)
161 PRETTYPRINTLANG(SANSKRIT)
162 PRETTYPRINTLANG(SERBIAN)
163 PRETTYPRINTLANG(SINDHI)
164 PRETTYPRINTLANG(SLOVAK)
165 PRETTYPRINTLANG(SLOVENIAN)
166 PRETTYPRINTLANG(SPANISH)
167 PRETTYPRINTLANG(SWAHILI)
168 PRETTYPRINTLANG(SWEDISH)
169 PRETTYPRINTLANG(SYRIAC)
170 PRETTYPRINTLANG(TAMIL)
171 PRETTYPRINTLANG(TATAR)
172 PRETTYPRINTLANG(TELUGU)
173 PRETTYPRINTLANG(THAI)
174 PRETTYPRINTLANG(TURKISH)
175 PRETTYPRINTLANG(UKRAINIAN)
176 PRETTYPRINTLANG(URDU)
177 PRETTYPRINTLANG(UZBEK)
178 PRETTYPRINTLANG(VIETNAMESE)
179 PRETTYPRINTLANG(GAELIC)
180 PRETTYPRINTLANG(MALTESE)
181 PRETTYPRINTLANG(MAORI)
182 PRETTYPRINTLANG(RHAETO_ROMANCE)
183 PRETTYPRINTLANG(SAAMI)
184 PRETTYPRINTLANG(SORBIAN)
185 PRETTYPRINTLANG(SUTU)
186 PRETTYPRINTLANG(TSONGA)
187 PRETTYPRINTLANG(TSWANA)
188 PRETTYPRINTLANG(VENDA)
189 PRETTYPRINTLANG(XHOSA)
190 PRETTYPRINTLANG(ZULU)
191 PRETTYPRINTLANG(ESPERANTO)
192 PRETTYPRINTLANG(WALON)
193 PRETTYPRINTLANG(CORNISH)
194 PRETTYPRINTLANG(WELSH)
195 PRETTYPRINTLANG(BRETON)
196 return "Unknown language";
200 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
202 event_t *ev1 = NULL, *ev2 = NULL;
204 ((accelerator1->memopt != accelerator2->memopt) ||
205 (accelerator1->lvc.version != accelerator2->lvc.version) ||
206 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
208 ev1 = accelerator1->events;
209 ev2 = accelerator2->events;
210 while(!different && ev1 && ev2) {
212 ((ev1->id != ev2->id) ||
213 (ev1->flags != ev2->flags)))
219 ((ev1 && !ev2) || (!ev1 && ev2)))
224 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
227 ((bitmap1->memopt != bitmap2->memopt) ||
228 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
229 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
234 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
237 ((cursor1->id != cursor2->id) ||
238 (cursor1->width != cursor2->width) ||
239 (cursor1->height != cursor2->height) ||
240 (cursor1->xhot != cursor2->xhot) ||
241 (cursor1->yhot != cursor2->yhot)))
244 ((cursor1->lvc.version != cursor2->lvc.version) ||
245 (cursor1->lvc.characts != cursor2->lvc.characts)))
250 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
252 cursor_t *cursor1 = NULL, *cursor2 = NULL;
254 ((cursor_group1->memopt != cursor_group2->memopt) ||
255 (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
256 (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
259 (cursor_group1->ncursor != cursor_group2->ncursor))
262 cursor1 = cursor_group1->cursorlist;
263 cursor2 = cursor_group2->cursorlist;
264 while(!different && cursor1 && cursor2) {
265 different = compare_cursor(cursor1, cursor2);
266 cursor1 = cursor1->next;
267 cursor2 = cursor2->next;
270 ((cursor1 && !cursor2) ||
271 (!cursor1 && cursor2)))
277 static int compare_control(control_t *control1, control_t *control2) {
282 ((control1 && !control2) ||
283 (!control1 && control2)))
285 if(different || !control1 || !control2)
287 nameid = strdup(get_nameid_str(control1->ctlclass));
288 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
294 /* allow the translators to set some styles */
296 if (control1->ctlclass->type == name_ord && control1->ctlclass->name.i_name == CT_BUTTON)
297 ignore_style = 0x2000; /* BS_MULTILINE*/
300 (control1->id != control2->id))
302 if(!different && control1->gotstyle && control2->gotstyle) {
303 if((!control1->style || !control2->style) ||
304 (control1->style->and_mask || control2->style->and_mask) ||
305 ((control1->style->or_mask & ~ignore_style) != (control2->style->or_mask & ~ignore_style)))
307 } else if(!different &&
308 ((control1->gotstyle && !control2->gotstyle) ||
309 (!control1->gotstyle && control2->gotstyle)))
311 if(!different && control1->gotexstyle && control2->gotexstyle) {
312 if((!control1->exstyle || !control2->exstyle) ||
313 (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
314 (control1->exstyle->or_mask != control2->exstyle->or_mask))
316 } else if(!different &&
317 ((control1->gotexstyle && !control2->gotexstyle) ||
318 (!control1->gotexstyle && control2->gotexstyle)))
320 if(!different && control1->gothelpid && control2->gothelpid) {
321 if(control1->helpid != control2->helpid)
323 } else if(!different &&
324 ((control1->gothelpid && !control2->gothelpid) ||
325 (!control1->gothelpid && control2->gothelpid)))
330 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
333 control_t *ctrl1, *ctrl2;
335 ((dialog1->memopt != dialog2->memopt) ||
336 (dialog1->lvc.version != dialog2->lvc.version) ||
337 (dialog1->lvc.characts != dialog2->lvc.characts)))
339 if(!different && dialog1->gotstyle && dialog2->gotstyle) {
340 if((!dialog1->style || !dialog2->style) ||
341 (dialog1->style->and_mask || dialog2->style->and_mask) ||
342 (dialog1->style->or_mask != dialog2->style->or_mask))
344 } else if(!different &&
345 ((dialog1->gotstyle && !dialog2->gotstyle) ||
346 (!dialog1->gotstyle && dialog2->gotstyle)))
348 if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
349 if((!dialog1->exstyle || !dialog2->exstyle) ||
350 (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
351 (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
353 } else if(!different &&
354 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
355 (!dialog1->gotexstyle && dialog2->gotexstyle)))
357 if(!different && dialog1->gothelpid && dialog2->gothelpid) {
358 if(dialog1->helpid != dialog2->helpid)
360 } else if(!different &&
361 ((dialog1->gothelpid && !dialog2->gothelpid) ||
362 (!dialog1->gothelpid && dialog2->gothelpid)))
364 nameid = strdup(get_nameid_str(dialog1->menu));
365 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
368 nameid = strdup(get_nameid_str(dialog1->dlgclass));
369 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
373 ctrl1 = dialog1->controls;
374 ctrl2 = dialog2->controls;
375 while(!different && (ctrl1 || ctrl2))
377 different = compare_control(ctrl1, ctrl2);
378 if (ctrl1) ctrl1 = ctrl1->next;
379 if (ctrl2) ctrl2 = ctrl2->next;
384 static int compare_font(font_t *font1, font_t *font2) {
387 ((font1->memopt != font2->memopt) ||
388 (font1->data->lvc.version != font2->data->lvc.version) ||
389 (font1->data->lvc.characts != font2->data->lvc.characts)))
394 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
397 ((fontdir1->memopt != fontdir2->memopt) ||
398 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
399 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
404 static int compare_icon(icon_t *icon1, icon_t *icon2) {
407 ((icon1->id != icon2->id) ||
408 (icon1->width != icon2->width) ||
409 (icon1->height != icon2->height)))
412 ((icon1->lvc.version != icon2->lvc.version) ||
413 (icon1->lvc.characts != icon2->lvc.characts)))
418 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
420 icon_t *icon1 = NULL, *icon2 = NULL;
422 ((icon_group1->memopt != icon_group2->memopt) ||
423 (icon_group1->lvc.version != icon_group2->lvc.version) ||
424 (icon_group1->lvc.characts != icon_group2->lvc.characts)))
427 (icon_group1->nicon != icon_group2->nicon))
430 icon1 = icon_group1->iconlist;
431 icon2 = icon_group2->iconlist;
432 while(!different && icon1 && icon2) {
433 different = compare_icon(icon1, icon2);
438 ((icon1 && !icon2) ||
445 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
447 while(!different && menu_item1 && menu_item2) {
448 if(menu_item1->popup && menu_item2->popup) {
449 if(!different && menu_item1->gotid && menu_item2->gotid) {
450 if(menu_item1->id != menu_item2->id)
452 } else if(!different &&
453 ((menu_item1->gotid && !menu_item2->gotid) ||
454 (!menu_item1->gotid && menu_item2->gotid)))
456 if(!different && menu_item1->gottype && menu_item2->gottype) {
457 if(menu_item1->type != menu_item2->type)
459 } else if(!different &&
460 ((menu_item1->gottype && !menu_item2->gottype) ||
461 (!menu_item1->gottype && menu_item2->gottype)))
463 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
464 if(menu_item1->state != menu_item2->state)
466 } else if(!different &&
467 ((menu_item1->gotstate && !menu_item2->gotstate) ||
468 (!menu_item1->gotstate && menu_item2->gotstate)))
470 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
471 if(menu_item1->helpid != menu_item2->helpid)
473 } else if(!different &&
474 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
475 (!menu_item1->gothelpid && menu_item2->gothelpid)))
478 different = compare_menu_item(menu_item1->popup, menu_item2->popup);
479 } else if(!menu_item1->popup && !menu_item2->popup) {
480 if(menu_item1->name && menu_item2->name) {
481 if(!different && menu_item1->gotid && menu_item2->gotid) {
482 if(menu_item1->id != menu_item2->id)
484 } else if(!different &&
485 ((menu_item1->gotid && !menu_item2->gotid) ||
486 (!menu_item1->gotid && menu_item2->gotid)))
488 if(!different && menu_item1->gottype && menu_item2->gottype) {
489 if(menu_item1->type != menu_item2->type)
491 } else if(!different &&
492 ((menu_item1->gottype && !menu_item2->gottype) ||
493 (!menu_item1->gottype && menu_item2->gottype)))
495 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
496 if(menu_item1->state != menu_item2->state)
498 } else if(!different &&
499 ((menu_item1->gotstate && !menu_item2->gotstate) ||
500 (!menu_item1->gotstate && menu_item2->gotstate)))
502 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
503 if(menu_item1->helpid != menu_item2->helpid)
505 } else if(!different &&
506 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
507 (!menu_item1->gothelpid && menu_item2->gothelpid)))
509 } else if((menu_item1->name && !menu_item2->name) ||
510 (!menu_item1->name && menu_item2->name))
514 menu_item1 = menu_item1->next;
515 menu_item2 = menu_item2->next;
518 ((menu_item1 && !menu_item2) ||
519 (!menu_item1 && menu_item2)))
524 static int compare_menu(menu_t *menu1, menu_t *menu2) {
527 ((menu1->memopt != menu2->memopt) ||
528 (menu1->lvc.version != menu2->lvc.version) ||
529 (menu1->lvc.characts != menu2->lvc.characts)))
532 different = compare_menu_item(menu1->items, menu2->items);
536 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
539 ((rcdata1->memopt != rcdata2->memopt) ||
540 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
541 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
546 static int compare_html(html_t *rcdata1, html_t *rcdata2) {
549 ((rcdata1->memopt != rcdata2->memopt) ||
550 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
551 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
556 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
559 while(!different && stringtable1 && stringtable2) {
560 if((stringtable1->memopt != stringtable2->memopt) ||
561 (stringtable1->lvc.version != stringtable2->lvc.version) ||
562 (stringtable1->lvc.characts != stringtable2->lvc.characts))
565 if((stringtable1->nentries != stringtable2->nentries) ||
566 (stringtable1->idbase != stringtable2->idbase))
569 for(i = 0 ; i < stringtable1->nentries; i++)
570 if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
571 (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
572 (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
573 (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
578 stringtable1 = stringtable1->next;
579 stringtable2 = stringtable2->next;
584 static int compare_user(user_t *user1, user_t *user2) {
588 ((user1->memopt != user2->memopt) ||
589 (user1->data->lvc.version != user2->data->lvc.version) ||
590 (user1->data->lvc.characts != user2->data->lvc.characts)))
592 nameid = strdup(get_nameid_str(user1->type));
593 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
599 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
602 ((messagetable1->memopt != messagetable2->memopt) ||
603 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
604 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
609 static int compare_string(string_t *string1, string_t *string2) {
612 ((string1->size != string2->size) ||
613 (string1->type != string2->type)))
616 if(string1->type == str_char)
617 different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
618 else if(string1->type == str_unicode)
619 different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
626 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
628 static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
632 (ver_value1->type == ver_value2->type)) {
633 switch(ver_value1->type) {
635 if(!different && ver_value1->key && ver_value2->key)
636 different = compare_string(ver_value1->key, ver_value2->key);
637 else if(!different &&
638 ((ver_value1->key && !ver_value2->key) ||
639 (!ver_value1->key && ver_value2->key)))
643 if(!different && ver_value1->key && ver_value2->key)
644 different = compare_string(ver_value1->key, ver_value2->key);
645 else if(!different &&
646 ((ver_value1->key && !ver_value2->key) ||
647 (!ver_value1->key && ver_value2->key)))
649 if(!different && ver_value1->value.words && ver_value2->value.words) {
651 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
654 for(i = 0; i < ver_value1->value.words->nwords; i++) {
655 if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
660 } else if(!different &&
661 ((ver_value1->value.words && !ver_value2->value.words) ||
662 (!ver_value1->value.words && ver_value2->value.words)))
666 if(!different && ver_value1->value.block && ver_value2->value.block)
667 different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
668 else if(!different &&
669 ((ver_value1->value.block && !ver_value2->value.block) ||
670 (!ver_value1->value.block && ver_value2->value.block)))
681 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
683 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
685 ver_value1 = ver_block1->values;
686 ver_value2 = ver_block2->values;
687 while(!different && ver_value1 && ver_value2) {
688 different = compare_ver_value(ver_value1, ver_value2);
689 ver_value1 = ver_value1->next;
690 ver_value2 = ver_value2->next;
693 ((ver_value1 && !ver_value2) ||
694 (!ver_value1 && ver_value2)))
700 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
702 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
704 ((versioninfo1->memopt != versioninfo2->memopt) ||
705 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
706 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
708 if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
709 if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
710 (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
711 (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
712 (versioninfo1->filever_min2 != versioninfo2->filever_min2))
714 } else if(!different &&
715 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
716 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
718 if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
719 if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
720 (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
721 (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
722 (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
724 } else if(!different &&
725 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
726 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
728 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
729 if(versioninfo1->fileos != versioninfo2->fileos)
731 } else if(!different &&
732 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
733 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
735 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
736 if(versioninfo1->fileflags != versioninfo2->fileflags)
738 } else if(!different &&
739 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
740 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
742 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
743 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
745 } else if(!different &&
746 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
747 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
749 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
750 if(versioninfo1->filetype != versioninfo2->filetype)
752 } else if(!different &&
753 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
754 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
756 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
757 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
759 } else if(!different &&
760 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
761 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
764 ver_block1 = versioninfo1->blocks;
765 ver_block2 = versioninfo2->blocks;
766 while(!different && ver_block1 && ver_block2) {
767 different = compare_ver_block(ver_block1, ver_block2);
768 ver_block1 = ver_block1->next;
769 ver_block2 = ver_block2->next;
772 ((ver_block1 && !ver_block2) ||
773 (!ver_block1 && ver_block2)))
779 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
782 ((dlginit1->memopt != dlginit2->memopt) ||
783 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
784 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
789 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
791 while(!different && toolbar_item1 && toolbar_item2) {
792 if((toolbar_item1->id && !toolbar_item2->id) ||
793 (!toolbar_item1->id && toolbar_item2->id))
795 toolbar_item1 = toolbar_item1->next;
796 toolbar_item2 = toolbar_item2->next;
799 ((toolbar_item1 && !toolbar_item2) ||
800 (!toolbar_item1 && toolbar_item2)))
805 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
808 ((toolbar1->memopt != toolbar2->memopt) ||
809 (toolbar1->lvc.version != toolbar2->lvc.version) ||
810 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
813 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
817 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
820 ((ani_curico1->memopt != ani_curico2->memopt) ||
821 (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
822 (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
827 static int compare(resource_t *resource1, resource_t *resource2) {
828 switch(resource1->type) {
830 return compare_accelerator(resource1->res.acc, resource2->res.acc);
832 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
834 return compare_cursor(resource1->res.cur, resource2->res.cur);
836 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
838 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
840 return compare_font(resource1->res.fnt, resource2->res.fnt);
842 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
844 return compare_icon(resource1->res.ico, resource2->res.ico);
846 return compare_icon_group(resource1->res.icog, resource2->res.icog);
848 return compare_menu(resource1->res.men, resource2->res.men);
850 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
852 return compare_stringtable(resource1->res.stt, resource2->res.stt);
854 return compare_user(resource1->res.usr, resource2->res.usr);
856 return compare_html(resource1->res.html, resource2->res.html);
858 return compare_messagetable(resource1->res.msg, resource2->res.msg);
860 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
862 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
864 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
867 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
869 /* Not supposed to reach here */
870 fprintf(stderr, "Not supposed to reach here (compare())\n");
876 typedef struct resource_lang_node
880 struct resource_lang_node *next;
881 } resource_lang_node_t;
883 typedef struct resource_id_node
886 resource_lang_node_t *langs;
887 struct resource_id_node *next;
888 } resource_id_node_t;
893 struct resource_id_node *ids;
894 } verify_tab[res_usr+1];
896 static void add_resource(resource_t *res)
898 resource_id_node_t *idnode;
899 resource_lang_node_t *langnode;
900 if (!verify_tab[res->type].enabled)
902 fprintf(stderr, "ERR: Report this: unknown resource type parsed %08x\n", res->type);
906 for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
907 if (compare_name_id(idnode->id, res->name) == 0)
912 idnode = xmalloc(sizeof(resource_id_node_t));
913 idnode->id = res->name;
914 idnode->langs = NULL;
915 idnode->next = verify_tab[res->type].ids;
916 verify_tab[res->type].ids = idnode;
919 for (langnode = idnode->langs; langnode; langnode = langnode->next)
920 if (compare_lang(langnode->lang, get_language(res)) == 0)
922 fprintf(stderr, "ERR: resource %s [type %x] language %03x:%02x duplicated!\n",
923 get_nameid_str(res->name), res->type, langnode->lang.id, langnode->lang.sub);
927 langnode = xmalloc(sizeof(resource_lang_node_t));
929 langnode->lang = get_language(res);
930 langnode->next = idnode->langs;
931 idnode->langs = langnode;
934 static void setup_tabs(void)
938 for (i = 0; i <= res_usr; i++)
960 verify_tab[i].enabled = 1;
965 static const char *get_typename_for_int(int type) {
968 return get_typename(&res);
971 static resource_t *find_main(int type, name_id_t *id, resource_lang_node_t *langnode)
973 resource_t *neutral = NULL, *en = NULL, *en_US = NULL;
974 for (; langnode; langnode = langnode->next)
976 if (langnode->lang.id == LANG_NEUTRAL && langnode->lang.sub == SUBLANG_NEUTRAL)
977 neutral = langnode->res;
978 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == SUBLANG_NEUTRAL)
980 if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == MASTER_SUBLANGUAGE)
981 en_US = langnode->res;
984 if (neutral != NULL && (en != NULL || en_US != NULL))
986 fprintf(stderr, "INFO: Resource %04x/%s has both NEUTRAL and MASTER language translation\n",
987 type, get_nameid_str(id));
990 if (en_US != NULL) return en_US;
991 if (en != NULL) return en;
995 void verify_translations(resource_t *top) {
996 resource_t *curr = top;
997 resource_id_node_t *idnode;
998 resource_lang_node_t *langnode;
1008 for (type = 0; type <= res_usr; type++)
1010 printf("TYPE NEXT [%s]\n", get_typename_for_int(type));
1011 for (idnode = verify_tab[type].ids; idnode; idnode = idnode->next)
1013 resource_t *mainres;
1014 printf("RESOURCE [%s]\n", get_nameid_str(idnode->id));
1016 mainres = find_main(type, idnode->id, idnode->langs);
1019 fprintf(stderr, "ERR: resource %04x/%s has translation(s) but not available in NEUTRAL or MASTER language\n",
1020 type, get_nameid_str(idnode->id));
1021 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1022 printf("EXTRA %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1026 if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
1027 printf("NOTRANSL\n");
1031 for (langnode = idnode->langs; langnode; langnode = langnode->next)
1033 printf("EXIST %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
1034 if (compare(langnode->res, mainres))
1036 printf("DIFF %03x:%02x\n", langnode->lang.id, langnode->lang.sub);