2 * Copyright 2003 Vincent BĂ©ron
3 * Copyright 2007, 2008 Mikolaj Zalewski
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #define MASTER_LANGUAGE LANG_ENGLISH
29 #define MASTER_SUBLANGUAGE SUBLANG_ENGLISH_US
38 static language_t
get_language(resource_t
*resource
) {
39 switch(resource
->type
) {
41 return *resource
->res
.acc
->lvc
.language
;
43 return *resource
->res
.bmp
->data
->lvc
.language
;
45 return *resource
->res
.cur
->lvc
.language
;
47 return *resource
->res
.curg
->lvc
.language
;
49 return *resource
->res
.dlg
->lvc
.language
;
51 return *resource
->res
.dlgex
->lvc
.language
;
53 return *resource
->res
.fnt
->data
->lvc
.language
;
55 return *resource
->res
.fnd
->data
->lvc
.language
;
57 return *resource
->res
.ico
->lvc
.language
;
59 return *resource
->res
.icog
->lvc
.language
;
61 return *resource
->res
.men
->lvc
.language
;
63 return *resource
->res
.menex
->lvc
.language
;
65 return *resource
->res
.rdt
->data
->lvc
.language
;
67 return *resource
->res
.stt
->lvc
.language
;
69 return *resource
->res
.usr
->data
->lvc
.language
;
71 return *resource
->res
.msg
->data
->lvc
.language
;
73 return *resource
->res
.ver
->lvc
.language
;
75 return *resource
->res
.dlgi
->data
->lvc
.language
;
77 return *resource
->res
.tbt
->lvc
.language
;
80 return *resource
->res
.ani
->data
->lvc
.language
;
82 return *resource
->res
.html
->data
->lvc
.language
;
84 /* Not supposed to reach here */
85 fprintf(stderr
, "Not supposed to reach here (get_language_id())\n");
90 static int get_language_id(resource_t
*resource
) {
91 return get_language(resource
).id
;
94 static int compare_lang(language_t lang1
, language_t lang2
)
96 return memcmp(&lang1
, &lang2
, sizeof(language_t
));
101 #define PRETTYPRINTLANG(langid) \
102 if(LANG_##langid == lid) { \
106 static const char *get_language_name(int lid
) {
107 PRETTYPRINTLANG(NEUTRAL
)
108 PRETTYPRINTLANG(AFRIKAANS
)
109 PRETTYPRINTLANG(ALBANIAN
)
110 PRETTYPRINTLANG(ARABIC
)
111 PRETTYPRINTLANG(ARMENIAN
)
112 PRETTYPRINTLANG(ASSAMESE
)
113 PRETTYPRINTLANG(AZERI
)
114 PRETTYPRINTLANG(BASQUE
)
115 PRETTYPRINTLANG(BELARUSIAN
)
116 PRETTYPRINTLANG(BENGALI
)
117 PRETTYPRINTLANG(BULGARIAN
)
118 PRETTYPRINTLANG(CATALAN
)
119 PRETTYPRINTLANG(CHINESE
)
120 PRETTYPRINTLANG(CROATIAN
)
121 PRETTYPRINTLANG(CZECH
)
122 PRETTYPRINTLANG(DANISH
)
123 PRETTYPRINTLANG(DIVEHI
)
124 PRETTYPRINTLANG(DUTCH
)
125 PRETTYPRINTLANG(ENGLISH
)
126 PRETTYPRINTLANG(ESTONIAN
)
127 PRETTYPRINTLANG(FAEROESE
)
128 PRETTYPRINTLANG(FARSI
)
129 PRETTYPRINTLANG(FINNISH
)
130 PRETTYPRINTLANG(FRENCH
)
131 PRETTYPRINTLANG(GALICIAN
)
132 PRETTYPRINTLANG(GEORGIAN
)
133 PRETTYPRINTLANG(GERMAN
)
134 PRETTYPRINTLANG(GREEK
)
135 PRETTYPRINTLANG(GUJARATI
)
136 PRETTYPRINTLANG(HEBREW
)
137 PRETTYPRINTLANG(HINDI
)
138 PRETTYPRINTLANG(HUNGARIAN
)
139 PRETTYPRINTLANG(ICELANDIC
)
140 PRETTYPRINTLANG(INDONESIAN
)
141 PRETTYPRINTLANG(ITALIAN
)
142 PRETTYPRINTLANG(JAPANESE
)
143 PRETTYPRINTLANG(KANNADA
)
144 PRETTYPRINTLANG(KASHMIRI
)
145 PRETTYPRINTLANG(KAZAK
)
146 PRETTYPRINTLANG(KONKANI
)
147 PRETTYPRINTLANG(KOREAN
)
148 PRETTYPRINTLANG(KYRGYZ
)
149 PRETTYPRINTLANG(LATVIAN
)
150 PRETTYPRINTLANG(LITHUANIAN
)
151 PRETTYPRINTLANG(MACEDONIAN
)
152 PRETTYPRINTLANG(MALAY
)
153 PRETTYPRINTLANG(MALAYALAM
)
154 PRETTYPRINTLANG(MANIPURI
)
155 PRETTYPRINTLANG(MARATHI
)
156 PRETTYPRINTLANG(MONGOLIAN
)
157 PRETTYPRINTLANG(NEPALI
)
158 PRETTYPRINTLANG(NORWEGIAN
)
159 PRETTYPRINTLANG(ORIYA
)
160 PRETTYPRINTLANG(POLISH
)
161 PRETTYPRINTLANG(PORTUGUESE
)
162 PRETTYPRINTLANG(PUNJABI
)
163 PRETTYPRINTLANG(ROMANIAN
)
164 PRETTYPRINTLANG(RUSSIAN
)
165 PRETTYPRINTLANG(SANSKRIT
)
166 PRETTYPRINTLANG(SERBIAN
)
167 PRETTYPRINTLANG(SINDHI
)
168 PRETTYPRINTLANG(SLOVAK
)
169 PRETTYPRINTLANG(SLOVENIAN
)
170 PRETTYPRINTLANG(SPANISH
)
171 PRETTYPRINTLANG(SWAHILI
)
172 PRETTYPRINTLANG(SWEDISH
)
173 PRETTYPRINTLANG(SYRIAC
)
174 PRETTYPRINTLANG(TAMIL
)
175 PRETTYPRINTLANG(TATAR
)
176 PRETTYPRINTLANG(TELUGU
)
177 PRETTYPRINTLANG(THAI
)
178 PRETTYPRINTLANG(TURKISH
)
179 PRETTYPRINTLANG(UKRAINIAN
)
180 PRETTYPRINTLANG(URDU
)
181 PRETTYPRINTLANG(UZBEK
)
182 PRETTYPRINTLANG(VIETNAMESE
)
183 PRETTYPRINTLANG(GAELIC
)
184 PRETTYPRINTLANG(MALTESE
)
185 PRETTYPRINTLANG(MAORI
)
186 PRETTYPRINTLANG(RHAETO_ROMANCE
)
187 PRETTYPRINTLANG(SAAMI
)
188 PRETTYPRINTLANG(SORBIAN
)
189 PRETTYPRINTLANG(SUTU
)
190 PRETTYPRINTLANG(TSONGA
)
191 PRETTYPRINTLANG(TSWANA
)
192 PRETTYPRINTLANG(VENDA
)
193 PRETTYPRINTLANG(XHOSA
)
194 PRETTYPRINTLANG(ZULU
)
195 PRETTYPRINTLANG(ESPERANTO
)
196 PRETTYPRINTLANG(WALON
)
197 PRETTYPRINTLANG(CORNISH
)
198 PRETTYPRINTLANG(WELSH
)
199 PRETTYPRINTLANG(BRETON
)
200 return "Unknown language";
204 static int compare_accelerator(accelerator_t
*accelerator1
, accelerator_t
*accelerator2
) {
206 event_t
*ev1
= NULL
, *ev2
= NULL
;
208 ((accelerator1
->memopt
!= accelerator2
->memopt
) ||
209 (accelerator1
->lvc
.version
!= accelerator2
->lvc
.version
) ||
210 (accelerator1
->lvc
.characts
!= accelerator2
->lvc
.characts
)))
212 ev1
= accelerator1
->events
;
213 ev2
= accelerator2
->events
;
214 while(!different
&& ev1
&& ev2
) {
216 ((ev1
->id
!= ev2
->id
) ||
217 (ev1
->flags
!= ev2
->flags
)))
223 ((ev1
&& !ev2
) || (!ev1
&& ev2
)))
228 static int compare_bitmap(bitmap_t
*bitmap1
, bitmap_t
*bitmap2
) {
231 ((bitmap1
->memopt
!= bitmap2
->memopt
) ||
232 (bitmap1
->data
->lvc
.version
!= bitmap2
->data
->lvc
.version
) ||
233 (bitmap1
->data
->lvc
.characts
!= bitmap2
->data
->lvc
.characts
)))
238 static int compare_cursor(cursor_t
*cursor1
, cursor_t
*cursor2
) {
241 ((cursor1
->id
!= cursor2
->id
) ||
242 (cursor1
->width
!= cursor2
->width
) ||
243 (cursor1
->height
!= cursor2
->height
) ||
244 (cursor1
->xhot
!= cursor2
->xhot
) ||
245 (cursor1
->yhot
!= cursor2
->yhot
)))
248 ((cursor1
->lvc
.version
!= cursor2
->lvc
.version
) ||
249 (cursor1
->lvc
.characts
!= cursor2
->lvc
.characts
)))
254 static int compare_cursor_group(cursor_group_t
*cursor_group1
, cursor_group_t
*cursor_group2
) {
256 cursor_t
*cursor1
= NULL
, *cursor2
= NULL
;
258 ((cursor_group1
->memopt
!= cursor_group2
->memopt
) ||
259 (cursor_group1
->lvc
.version
!= cursor_group2
->lvc
.version
) ||
260 (cursor_group1
->lvc
.characts
!= cursor_group2
->lvc
.characts
)))
263 (cursor_group1
->ncursor
!= cursor_group2
->ncursor
))
266 cursor1
= cursor_group1
->cursorlist
;
267 cursor2
= cursor_group2
->cursorlist
;
268 while(!different
&& cursor1
&& cursor2
) {
269 different
= compare_cursor(cursor1
, cursor2
);
270 cursor1
= cursor1
->next
;
271 cursor2
= cursor2
->next
;
274 ((cursor1
&& !cursor2
) ||
275 (!cursor1
&& cursor2
)))
281 static int compare_control(control_t
*control1
, control_t
*control2
) {
285 ((control1
&& !control2
) ||
286 (!control1
&& control2
)))
288 if(different
|| !control1
|| !control2
)
290 nameid
= strdup(get_nameid_str(control1
->ctlclass
));
291 if(!different
&& strcmp(nameid
, get_nameid_str(control2
->ctlclass
)))
295 (control1
->id
!= control2
->id
))
297 if(!different
&& control1
->gotstyle
&& control2
->gotstyle
) {
298 if((!control1
->style
|| !control2
->style
) ||
299 (control1
->style
->and_mask
|| control2
->style
->and_mask
) ||
300 (control1
->style
->or_mask
!= control2
->style
->or_mask
))
302 } else if(!different
&&
303 ((control1
->gotstyle
&& !control2
->gotstyle
) ||
304 (!control1
->gotstyle
&& control2
->gotstyle
)))
306 if(!different
&& control1
->gotexstyle
&& control2
->gotexstyle
) {
307 if((!control1
->exstyle
|| !control2
->exstyle
) ||
308 (control1
->exstyle
->and_mask
|| control2
->exstyle
->and_mask
) ||
309 (control1
->exstyle
->or_mask
!= control2
->exstyle
->or_mask
))
311 } else if(!different
&&
312 ((control1
->gotexstyle
&& !control2
->gotexstyle
) ||
313 (!control1
->gotexstyle
&& control2
->gotexstyle
)))
315 if(!different
&& control1
->gothelpid
&& control2
->gothelpid
) {
316 if(control1
->helpid
!= control2
->helpid
)
318 } else if(!different
&&
319 ((control1
->gothelpid
&& !control2
->gothelpid
) ||
320 (!control1
->gothelpid
&& control2
->gothelpid
)))
325 static int compare_dialog(dialog_t
*dialog1
, dialog_t
*dialog2
) {
328 control_t
*ctrl1
, *ctrl2
;
330 ((dialog1
->memopt
!= dialog2
->memopt
) ||
331 (dialog1
->lvc
.version
!= dialog2
->lvc
.version
) ||
332 (dialog1
->lvc
.characts
!= dialog2
->lvc
.characts
)))
334 if(!different
&& dialog1
->gotstyle
&& dialog2
->gotstyle
) {
335 if((!dialog1
->style
|| !dialog2
->style
) ||
336 (dialog1
->style
->and_mask
|| dialog2
->style
->and_mask
) ||
337 (dialog1
->style
->or_mask
!= dialog2
->style
->or_mask
))
339 } else if(!different
&&
340 ((dialog1
->gotstyle
&& !dialog2
->gotstyle
) ||
341 (!dialog1
->gotstyle
&& dialog2
->gotstyle
)))
343 if(!different
&& dialog1
->gotexstyle
&& dialog2
->gotexstyle
) {
344 if((!dialog1
->exstyle
|| !dialog2
->exstyle
) ||
345 (dialog1
->exstyle
->and_mask
|| dialog2
->exstyle
->and_mask
) ||
346 (dialog1
->exstyle
->or_mask
!= dialog2
->exstyle
->or_mask
))
348 } else if(!different
&&
349 ((dialog1
->gotexstyle
&& !dialog2
->gotexstyle
) ||
350 (!dialog1
->gotexstyle
&& dialog2
->gotexstyle
)))
352 nameid
= strdup(get_nameid_str(dialog1
->menu
));
353 if(!different
&& strcmp(nameid
, get_nameid_str(dialog2
->menu
)))
356 nameid
= strdup(get_nameid_str(dialog1
->dlgclass
));
357 if(!different
&& strcmp(nameid
, get_nameid_str(dialog2
->dlgclass
)))
361 ctrl1
= dialog1
->controls
;
362 ctrl2
= dialog2
->controls
;
363 while(!different
&& (ctrl1
|| ctrl2
))
365 different
= compare_control(ctrl1
, ctrl2
);
366 if (ctrl1
) ctrl1
= ctrl1
->next
;
367 if (ctrl2
) ctrl2
= ctrl2
->next
;
372 static int compare_dialogex(dialogex_t
*dialogex1
, dialogex_t
*dialogex2
) {
375 control_t
*ctrl1
, *ctrl2
;
377 ((dialogex1
->memopt
!= dialogex2
->memopt
) ||
378 (dialogex1
->lvc
.version
!= dialogex2
->lvc
.version
) ||
379 (dialogex1
->lvc
.characts
!= dialogex2
->lvc
.characts
)))
381 if(!different
&& dialogex1
->gotstyle
&& dialogex2
->gotstyle
) {
382 if((!dialogex1
->style
|| !dialogex2
->style
) ||
383 (dialogex1
->style
->and_mask
|| dialogex2
->style
->and_mask
) ||
384 (dialogex1
->style
->or_mask
!= dialogex2
->style
->or_mask
))
386 } else if(!different
&&
387 ((dialogex1
->gotstyle
&& !dialogex2
->gotstyle
) ||
388 (!dialogex1
->gotstyle
&& dialogex2
->gotstyle
)))
390 if(!different
&& dialogex1
->gotexstyle
&& dialogex2
->gotexstyle
) {
391 if((!dialogex1
->exstyle
|| !dialogex2
->exstyle
) ||
392 (dialogex1
->exstyle
->and_mask
|| dialogex2
->exstyle
->and_mask
) ||
393 (dialogex1
->exstyle
->or_mask
!= dialogex2
->exstyle
->or_mask
))
395 } else if(!different
&&
396 ((dialogex1
->gotexstyle
&& !dialogex2
->gotexstyle
) ||
397 (!dialogex1
->gotexstyle
&& dialogex2
->gotexstyle
)))
399 if(!different
&& dialogex1
->gothelpid
&& dialogex2
->gothelpid
) {
400 if(dialogex1
->helpid
!= dialogex2
->helpid
)
402 } else if(!different
&&
403 ((dialogex1
->gothelpid
&& !dialogex2
->gothelpid
) ||
404 (!dialogex1
->gothelpid
&& dialogex2
->gothelpid
)))
406 nameid
= strdup(get_nameid_str(dialogex1
->menu
));
407 if(!different
&& strcmp(nameid
, get_nameid_str(dialogex2
->menu
)))
410 nameid
= strdup(get_nameid_str(dialogex1
->dlgclass
));
411 if(!different
&& strcmp(nameid
, get_nameid_str(dialogex2
->dlgclass
)))
415 ctrl1
= dialogex1
->controls
;
416 ctrl2
= dialogex2
->controls
;
417 while(!different
&& (ctrl1
|| ctrl2
))
419 different
= compare_control(ctrl1
, ctrl2
);
420 if (ctrl1
) ctrl1
= ctrl1
->next
;
421 if (ctrl2
) ctrl2
= ctrl2
->next
;
426 static int compare_font(font_t
*font1
, font_t
*font2
) {
429 ((font1
->memopt
!= font2
->memopt
) ||
430 (font1
->data
->lvc
.version
!= font2
->data
->lvc
.version
) ||
431 (font1
->data
->lvc
.characts
!= font2
->data
->lvc
.characts
)))
436 static int compare_fontdir(fontdir_t
*fontdir1
, fontdir_t
*fontdir2
) {
439 ((fontdir1
->memopt
!= fontdir2
->memopt
) ||
440 (fontdir1
->data
->lvc
.version
!= fontdir2
->data
->lvc
.version
) ||
441 (fontdir1
->data
->lvc
.characts
!= fontdir2
->data
->lvc
.characts
)))
446 static int compare_icon(icon_t
*icon1
, icon_t
*icon2
) {
449 ((icon1
->id
!= icon2
->id
) ||
450 (icon1
->width
!= icon2
->width
) ||
451 (icon1
->height
!= icon2
->height
)))
454 ((icon1
->lvc
.version
!= icon2
->lvc
.version
) ||
455 (icon1
->lvc
.characts
!= icon2
->lvc
.characts
)))
460 static int compare_icon_group(icon_group_t
*icon_group1
, icon_group_t
*icon_group2
) {
462 icon_t
*icon1
= NULL
, *icon2
= NULL
;
464 ((icon_group1
->memopt
!= icon_group2
->memopt
) ||
465 (icon_group1
->lvc
.version
!= icon_group2
->lvc
.version
) ||
466 (icon_group1
->lvc
.characts
!= icon_group2
->lvc
.characts
)))
469 (icon_group1
->nicon
!= icon_group2
->nicon
))
472 icon1
= icon_group1
->iconlist
;
473 icon2
= icon_group2
->iconlist
;
474 while(!different
&& icon1
&& icon2
) {
475 different
= compare_icon(icon1
, icon2
);
480 ((icon1
&& !icon2
) ||
487 static int compare_menu_item(menu_item_t
*menu_item1
, menu_item_t
*menu_item2
) {
489 while(!different
&& menu_item1
&& menu_item2
) {
490 if(menu_item1
->popup
&& menu_item2
->popup
)
491 different
= compare_menu_item(menu_item1
->popup
, menu_item2
->popup
);
492 else if(!menu_item1
->popup
&& !menu_item2
->popup
) {
493 if(menu_item1
->name
&& menu_item2
->name
) {
494 if((menu_item1
->id
!= menu_item2
->id
) ||
495 (menu_item1
->state
!= menu_item2
->state
))
497 } else if((menu_item1
->name
&& !menu_item2
->name
) ||
498 (!menu_item1
->name
&& menu_item2
->name
))
502 menu_item1
= menu_item1
->next
;
503 menu_item2
= menu_item2
->next
;
506 ((menu_item1
&& !menu_item2
) ||
507 (!menu_item1
&& menu_item2
)))
512 static int compare_menu(menu_t
*menu1
, menu_t
*menu2
) {
515 ((menu1
->memopt
!= menu2
->memopt
) ||
516 (menu1
->lvc
.version
!= menu2
->lvc
.version
) ||
517 (menu1
->lvc
.characts
!= menu2
->lvc
.characts
)))
520 different
= compare_menu_item(menu1
->items
, menu2
->items
);
524 static int compare_menuex_item(menuex_item_t
*menuex_item1
, menuex_item_t
*menuex_item2
) {
526 while(!different
&& menuex_item1
&& menuex_item2
) {
527 if(menuex_item1
->popup
&& menuex_item2
->popup
) {
528 if(!different
&& menuex_item1
->gotid
&& menuex_item2
->gotid
) {
529 if(menuex_item1
->id
!= menuex_item2
->id
)
531 } else if(!different
&&
532 ((menuex_item1
->gotid
&& !menuex_item2
->gotid
) ||
533 (!menuex_item2
->gotid
&& menuex_item2
->gotid
)))
535 if(!different
&& menuex_item1
->gottype
&& menuex_item2
->gottype
) {
536 if(menuex_item1
->type
!= menuex_item2
->type
)
538 } else if(!different
&&
539 ((menuex_item1
->gottype
&& !menuex_item2
->gottype
) ||
540 (!menuex_item2
->gottype
&& menuex_item2
->gottype
)))
542 if(!different
&& menuex_item1
->gotstate
&& menuex_item2
->gotstate
) {
543 if(menuex_item1
->state
!= menuex_item2
->state
)
545 } else if(!different
&&
546 ((menuex_item1
->gotstate
&& !menuex_item2
->gotstate
) ||
547 (!menuex_item2
->gotstate
&& menuex_item2
->gotstate
)))
549 if(!different
&& menuex_item1
->gothelpid
&& menuex_item2
->gothelpid
) {
550 if(menuex_item1
->helpid
!= menuex_item2
->helpid
)
552 } else if(!different
&&
553 ((menuex_item1
->gothelpid
&& !menuex_item2
->gothelpid
) ||
554 (!menuex_item2
->gothelpid
&& menuex_item2
->gothelpid
)))
557 different
= compare_menuex_item(menuex_item1
->popup
, menuex_item2
->popup
);
558 } else if(!menuex_item1
->popup
&& !menuex_item2
->popup
) {
559 if(menuex_item1
->name
&& menuex_item2
->name
) {
560 if(!different
&& menuex_item1
->gotid
&& menuex_item2
->gotid
) {
561 if(menuex_item1
->id
!= menuex_item2
->id
)
563 } else if(!different
&&
564 ((menuex_item1
->gotid
&& !menuex_item2
->gotid
) ||
565 (!menuex_item2
->gotid
&& menuex_item2
->gotid
)))
567 if(!different
&& menuex_item1
->gottype
&& menuex_item2
->gottype
) {
568 if(menuex_item1
->type
!= menuex_item2
->type
)
570 } else if(!different
&&
571 ((menuex_item1
->gottype
&& !menuex_item2
->gottype
) ||
572 (!menuex_item2
->gottype
&& menuex_item2
->gottype
)))
574 if(!different
&& menuex_item1
->gotstate
&& menuex_item2
->gotstate
) {
575 if(menuex_item1
->state
!= menuex_item2
->state
)
577 } else if(!different
&&
578 ((menuex_item1
->gotstate
&& !menuex_item2
->gotstate
) ||
579 (!menuex_item2
->gotstate
&& menuex_item2
->gotstate
)))
581 if(!different
&& menuex_item1
->gothelpid
&& menuex_item2
->gothelpid
) {
582 if(menuex_item1
->helpid
!= menuex_item2
->helpid
)
584 } else if(!different
&&
585 ((menuex_item1
->gothelpid
&& !menuex_item2
->gothelpid
) ||
586 (!menuex_item2
->gothelpid
&& menuex_item2
->gothelpid
)))
588 } else if((menuex_item1
->name
&& !menuex_item2
->name
) ||
589 (!menuex_item1
->name
&& menuex_item2
->name
))
593 menuex_item1
= menuex_item1
->next
;
594 menuex_item2
= menuex_item2
->next
;
597 ((menuex_item1
&& !menuex_item2
) ||
598 (!menuex_item1
&& menuex_item2
)))
603 static int compare_menuex(menuex_t
*menuex1
, menuex_t
*menuex2
) {
606 ((menuex1
->memopt
!= menuex2
->memopt
) ||
607 (menuex1
->lvc
.version
!= menuex2
->lvc
.version
) ||
608 (menuex1
->lvc
.characts
!= menuex2
->lvc
.characts
)))
611 different
= compare_menuex_item(menuex1
->items
, menuex2
->items
);
615 static int compare_rcdata(rcdata_t
*rcdata1
, rcdata_t
*rcdata2
) {
618 ((rcdata1
->memopt
!= rcdata2
->memopt
) ||
619 (rcdata1
->data
->lvc
.version
!= rcdata2
->data
->lvc
.version
) ||
620 (rcdata1
->data
->lvc
.characts
!= rcdata2
->data
->lvc
.characts
)))
625 static int compare_html(html_t
*rcdata1
, html_t
*rcdata2
) {
628 ((rcdata1
->memopt
!= rcdata2
->memopt
) ||
629 (rcdata1
->data
->lvc
.version
!= rcdata2
->data
->lvc
.version
) ||
630 (rcdata1
->data
->lvc
.characts
!= rcdata2
->data
->lvc
.characts
)))
635 static int compare_stringtable(stringtable_t
*stringtable1
, stringtable_t
*stringtable2
) {
638 while(!different
&& stringtable1
&& stringtable2
) {
639 if((stringtable1
->memopt
!= stringtable2
->memopt
) ||
640 (stringtable1
->lvc
.version
!= stringtable2
->lvc
.version
) ||
641 (stringtable1
->lvc
.characts
!= stringtable2
->lvc
.characts
))
644 if((stringtable1
->nentries
!= stringtable2
->nentries
) ||
645 (stringtable1
->idbase
!= stringtable2
->idbase
))
648 for(i
= 0 ; i
< stringtable1
->nentries
; i
++)
649 if((stringtable1
->entries
[i
].id
!= stringtable2
->entries
[i
].id
) ||
650 (stringtable1
->entries
[i
].memopt
!= stringtable2
->entries
[i
].memopt
) ||
651 (stringtable1
->entries
[i
].str
&& !stringtable2
->entries
[i
].str
) ||
652 (!stringtable1
->entries
[i
].str
&& stringtable2
->entries
[i
].str
)) {
657 stringtable1
= stringtable1
->next
;
658 stringtable2
= stringtable2
->next
;
663 static int compare_user(user_t
*user1
, user_t
*user2
) {
667 ((user1
->memopt
!= user2
->memopt
) ||
668 (user1
->data
->lvc
.version
!= user2
->data
->lvc
.version
) ||
669 (user1
->data
->lvc
.characts
!= user2
->data
->lvc
.characts
)))
671 nameid
= strdup(get_nameid_str(user1
->type
));
672 if(!different
&& strcmp(nameid
, get_nameid_str(user2
->type
)))
678 static int compare_messagetable(messagetable_t
*messagetable1
, messagetable_t
*messagetable2
) {
681 ((messagetable1
->memopt
!= messagetable2
->memopt
) ||
682 (messagetable1
->data
->lvc
.version
!= messagetable2
->data
->lvc
.version
) ||
683 (messagetable1
->data
->lvc
.characts
!= messagetable2
->data
->lvc
.characts
)))
688 static int compare_string(string_t
*string1
, string_t
*string2
) {
691 ((string1
->size
!= string2
->size
) ||
692 (string1
->type
!= string2
->type
)))
695 if(string1
->type
== str_char
)
696 different
= memcmp(string1
->str
.cstr
, string2
->str
.cstr
, string1
->size
);
697 else if(string1
->type
== str_unicode
)
698 different
= memcmp(string1
->str
.wstr
, string2
->str
.wstr
, string1
->size
*sizeof(WCHAR
));
705 static int compare_ver_block(ver_block_t
*ver_block1
, ver_block_t
*ver_block2
);
707 static int compare_ver_value(ver_value_t
*ver_value1
, ver_value_t
*ver_value2
) {
711 (ver_value1
->type
== ver_value2
->type
)) {
712 switch(ver_value1
->type
) {
714 if(!different
&& ver_value1
->key
&& ver_value2
->key
)
715 different
= compare_string(ver_value1
->key
, ver_value2
->key
);
716 else if(!different
&&
717 ((ver_value1
->key
&& !ver_value2
->key
) ||
718 (!ver_value1
->key
&& ver_value2
->key
)))
722 if(!different
&& ver_value1
->key
&& ver_value2
->key
)
723 different
= compare_string(ver_value1
->key
, ver_value2
->key
);
724 else if(!different
&&
725 ((ver_value1
->key
&& !ver_value2
->key
) ||
726 (!ver_value1
->key
&& ver_value2
->key
)))
728 if(!different
&& ver_value1
->value
.words
&& ver_value2
->value
.words
) {
730 (ver_value1
->value
.words
->nwords
!= ver_value2
->value
.words
->nwords
))
733 for(i
= 0; i
< ver_value1
->value
.words
->nwords
; i
++) {
734 if(ver_value1
->value
.words
->words
[i
] != ver_value2
->value
.words
->words
[i
]) {
739 } else if(!different
&&
740 ((ver_value1
->value
.words
&& !ver_value2
->value
.words
) ||
741 (!ver_value1
->value
.words
&& ver_value2
->value
.words
)))
745 if(!different
&& ver_value1
->value
.block
&& ver_value2
->value
.block
)
746 different
= compare_ver_block(ver_value1
->value
.block
, ver_value2
->value
.block
);
747 else if(!different
&&
748 ((ver_value1
->value
.block
&& !ver_value2
->value
.block
) ||
749 (!ver_value1
->value
.block
&& ver_value2
->value
.block
)))
760 static int compare_ver_block(ver_block_t
*ver_block1
, ver_block_t
*ver_block2
) {
762 ver_value_t
*ver_value1
= NULL
, *ver_value2
= NULL
;
764 ver_value1
= ver_block1
->values
;
765 ver_value2
= ver_block2
->values
;
766 while(!different
&& ver_value1
&& ver_value2
) {
767 different
= compare_ver_value(ver_value1
, ver_value2
);
768 ver_value1
= ver_value1
->next
;
769 ver_value2
= ver_value2
->next
;
772 ((ver_value1
&& !ver_value2
) ||
773 (!ver_value1
&& ver_value2
)))
779 static int compare_versioninfo(versioninfo_t
*versioninfo1
, versioninfo_t
*versioninfo2
) {
781 ver_block_t
*ver_block1
= NULL
, *ver_block2
= NULL
;
783 ((versioninfo1
->memopt
!= versioninfo2
->memopt
) ||
784 (versioninfo1
->lvc
.version
!= versioninfo2
->lvc
.version
) ||
785 (versioninfo1
->lvc
.characts
!= versioninfo2
->lvc
.characts
)))
787 if(!different
&& versioninfo1
->gotit
.fv
&& versioninfo2
->gotit
.fv
) {
788 if((versioninfo1
->filever_maj1
!= versioninfo2
->filever_maj1
) ||
789 (versioninfo1
->filever_maj2
!= versioninfo2
->filever_maj2
) ||
790 (versioninfo1
->filever_min1
!= versioninfo2
->filever_min1
) ||
791 (versioninfo1
->filever_min2
!= versioninfo2
->filever_min2
))
793 } else if(!different
&&
794 ((versioninfo1
->gotit
.fv
&& !versioninfo2
->gotit
.fv
) ||
795 (!versioninfo1
->gotit
.fv
&& versioninfo2
->gotit
.fv
)))
797 if(!different
&& versioninfo1
->gotit
.pv
&& versioninfo2
->gotit
.pv
) {
798 if((versioninfo1
->prodver_maj1
!= versioninfo2
->prodver_maj1
) ||
799 (versioninfo1
->prodver_maj2
!= versioninfo2
->prodver_maj2
) ||
800 (versioninfo1
->prodver_min1
!= versioninfo2
->prodver_min1
) ||
801 (versioninfo1
->prodver_min2
!= versioninfo2
->prodver_min2
))
803 } else if(!different
&&
804 ((versioninfo1
->gotit
.pv
&& !versioninfo2
->gotit
.pv
) ||
805 (!versioninfo1
->gotit
.pv
&& versioninfo2
->gotit
.pv
)))
807 if(!different
&& versioninfo1
->gotit
.fo
&& versioninfo2
->gotit
.fo
) {
808 if(versioninfo1
->fileos
!= versioninfo2
->fileos
)
810 } else if(!different
&&
811 ((versioninfo1
->gotit
.fo
&& !versioninfo2
->gotit
.fo
) ||
812 (!versioninfo1
->gotit
.fo
&& versioninfo2
->gotit
.fo
)))
814 if(!different
&& versioninfo1
->gotit
.ff
&& versioninfo2
->gotit
.ff
) {
815 if(versioninfo1
->fileflags
!= versioninfo2
->fileflags
)
817 } else if(!different
&&
818 ((versioninfo1
->gotit
.ff
&& !versioninfo2
->gotit
.ff
) ||
819 (!versioninfo1
->gotit
.ff
&& versioninfo2
->gotit
.ff
)))
821 if(!different
&& versioninfo1
->gotit
.ffm
&& versioninfo2
->gotit
.ffm
) {
822 if(versioninfo1
->fileflagsmask
!= versioninfo2
->fileflagsmask
)
824 } else if(!different
&&
825 ((versioninfo1
->gotit
.ffm
&& !versioninfo2
->gotit
.ffm
) ||
826 (!versioninfo1
->gotit
.ffm
&& versioninfo2
->gotit
.ffm
)))
828 if(!different
&& versioninfo1
->gotit
.ft
&& versioninfo2
->gotit
.ft
) {
829 if(versioninfo1
->filetype
!= versioninfo2
->filetype
)
831 } else if(!different
&&
832 ((versioninfo1
->gotit
.ft
&& !versioninfo2
->gotit
.ft
) ||
833 (!versioninfo1
->gotit
.ft
&& versioninfo2
->gotit
.ft
)))
835 if(!different
&& versioninfo1
->gotit
.fst
&& versioninfo2
->gotit
.fst
) {
836 if(versioninfo1
->filesubtype
!= versioninfo2
->filesubtype
)
838 } else if(!different
&&
839 ((versioninfo1
->gotit
.fst
&& !versioninfo2
->gotit
.fst
) ||
840 (!versioninfo1
->gotit
.fst
&& versioninfo2
->gotit
.fst
)))
843 ver_block1
= versioninfo1
->blocks
;
844 ver_block2
= versioninfo2
->blocks
;
845 while(!different
&& ver_block1
&& ver_block2
) {
846 different
= compare_ver_block(ver_block1
, ver_block2
);
847 ver_block1
= ver_block1
->next
;
848 ver_block2
= ver_block2
->next
;
851 ((ver_block1
&& !ver_block2
) ||
852 (!ver_block1
&& ver_block2
)))
858 static int compare_dlginit(dlginit_t
*dlginit1
, dlginit_t
*dlginit2
) {
861 ((dlginit1
->memopt
!= dlginit2
->memopt
) ||
862 (dlginit1
->data
->lvc
.version
!= dlginit2
->data
->lvc
.version
) ||
863 (dlginit1
->data
->lvc
.characts
!= dlginit2
->data
->lvc
.characts
)))
868 static int compare_toolbar_item(toolbar_item_t
*toolbar_item1
, toolbar_item_t
*toolbar_item2
) {
870 while(!different
&& toolbar_item1
&& toolbar_item2
) {
871 if((toolbar_item1
->id
&& !toolbar_item2
->id
) ||
872 (!toolbar_item1
->id
&& toolbar_item2
->id
))
874 toolbar_item1
= toolbar_item1
->next
;
875 toolbar_item2
= toolbar_item2
->next
;
878 ((toolbar_item1
&& !toolbar_item2
) ||
879 (!toolbar_item1
&& toolbar_item2
)))
884 static int compare_toolbar(toolbar_t
*toolbar1
, toolbar_t
*toolbar2
) {
887 ((toolbar1
->memopt
!= toolbar2
->memopt
) ||
888 (toolbar1
->lvc
.version
!= toolbar2
->lvc
.version
) ||
889 (toolbar1
->lvc
.characts
!= toolbar2
->lvc
.characts
)))
892 different
= compare_toolbar_item(toolbar1
->items
, toolbar2
->items
);
896 static int compare_ani_curico(ani_curico_t
*ani_curico1
, ani_curico_t
*ani_curico2
) {
899 ((ani_curico1
->memopt
!= ani_curico2
->memopt
) ||
900 (ani_curico1
->data
->lvc
.version
!= ani_curico2
->data
->lvc
.version
) ||
901 (ani_curico1
->data
->lvc
.characts
!= ani_curico2
->data
->lvc
.characts
)))
906 static int compare(resource_t
*resource1
, resource_t
*resource2
) {
907 switch(resource1
->type
) {
909 return compare_accelerator(resource1
->res
.acc
, resource2
->res
.acc
);
911 return compare_bitmap(resource1
->res
.bmp
, resource2
->res
.bmp
);
913 return compare_cursor(resource1
->res
.cur
, resource2
->res
.cur
);
915 return compare_cursor_group(resource1
->res
.curg
, resource2
->res
.curg
);
917 return compare_dialog(resource1
->res
.dlg
, resource2
->res
.dlg
);
919 return compare_dialogex(resource1
->res
.dlgex
, resource2
->res
.dlgex
);
921 return compare_font(resource1
->res
.fnt
, resource2
->res
.fnt
);
923 return compare_fontdir(resource1
->res
.fnd
, resource2
->res
.fnd
);
925 return compare_icon(resource1
->res
.ico
, resource2
->res
.ico
);
927 return compare_icon_group(resource1
->res
.icog
, resource2
->res
.icog
);
929 return compare_menu(resource1
->res
.men
, resource2
->res
.men
);
931 return compare_menuex(resource1
->res
.menex
, resource2
->res
.menex
);
933 return compare_rcdata(resource1
->res
.rdt
, resource2
->res
.rdt
);
935 return compare_stringtable(resource1
->res
.stt
, resource2
->res
.stt
);
937 return compare_user(resource1
->res
.usr
, resource2
->res
.usr
);
939 return compare_html(resource1
->res
.html
, resource2
->res
.html
);
941 return compare_messagetable(resource1
->res
.msg
, resource2
->res
.msg
);
943 return compare_versioninfo(resource1
->res
.ver
, resource2
->res
.ver
);
945 return compare_dlginit(resource1
->res
.dlgi
, resource2
->res
.dlgi
);
947 return compare_toolbar(resource1
->res
.tbt
, resource2
->res
.tbt
);
950 return compare_ani_curico(resource1
->res
.ani
, resource2
->res
.ani
);
952 /* Not supposed to reach here */
953 fprintf(stderr
, "Not supposed to reach here (compare())\n");
959 static void dump_stringtable(resource_t
*res
)
961 stringtable_t
*stt
= res
->res
.stt
;
965 assert((stt
->idbase
%16) == 0);
966 assert(stt
->nentries
== 16);
967 for (j
= 0; j
< stt
->nentries
; j
++)
969 stt_entry_t
*entry
= &stt
->entries
[j
];
970 language_t
*lang
= stt
->lvc
.language
;
977 newstr
= convert_string(entry
->str
, str_unicode
, get_language_codepage(lang
->id
, lang
->sub
));
978 printf("%02x%02x", newstr
->size
& 0xff, (newstr
->size
>> 8) & 0xff);
979 wstr
= newstr
->str
.wstr
;
980 for (k
= 0; k
< newstr
->size
; k
++)
981 printf("%02x%02x", wstr
[k
] & 0xff, wstr
[k
] >> 8);
990 static void dump(resource_t
*res
)
995 dump_stringtable(res
);
1002 typedef struct resource_lang_node
1006 struct resource_lang_node
*next
;
1007 } resource_lang_node_t
;
1009 typedef struct resource_id_node
1012 resource_lang_node_t
*langs
;
1013 struct resource_id_node
*next
;
1014 } resource_id_node_t
;
1019 struct resource_id_node
*ids
;
1020 } verify_tab
[res_usr
+1];
1022 static void add_resource(resource_t
*res
)
1024 resource_id_node_t
*idnode
;
1025 resource_lang_node_t
*langnode
;
1026 if (!verify_tab
[res
->type
].enabled
)
1028 fprintf(stderr
, "ERR: Report this: unknown resource type parsed %08x\n", res
->type
);
1032 for (idnode
= verify_tab
[res
->type
].ids
; idnode
; idnode
= idnode
->next
)
1033 if (compare_name_id(idnode
->id
, res
->name
) == 0)
1038 idnode
= xmalloc(sizeof(resource_id_node_t
));
1039 idnode
->id
= res
->name
;
1040 idnode
->langs
= NULL
;
1041 idnode
->next
= verify_tab
[res
->type
].ids
;
1042 verify_tab
[res
->type
].ids
= idnode
;
1045 for (langnode
= idnode
->langs
; langnode
; langnode
= langnode
->next
)
1046 if (compare_lang(langnode
->lang
, get_language(res
)) == 0)
1048 fprintf(stderr
, "ERR: resource %s [type %x] language %03x:%02x duplicated!\n",
1049 get_nameid_str(res
->name
), res
->type
, langnode
->lang
.id
, langnode
->lang
.sub
);
1053 langnode
= xmalloc(sizeof(resource_lang_node_t
));
1054 langnode
->res
= res
;
1055 langnode
->lang
= get_language(res
);
1056 langnode
->next
= idnode
->langs
;
1057 idnode
->langs
= langnode
;
1060 static void setup_tabs(void)
1064 for (i
= 0; i
<= res_usr
; i
++)
1088 verify_tab
[i
].enabled
= 1;
1093 static const char *get_typename_for_int(int type
) {
1096 return get_typename(&res
);
1099 static resource_t
*find_main(int type
, name_id_t
*id
, resource_lang_node_t
*langnode
)
1101 resource_t
*neutral
= NULL
, *en
= NULL
, *en_US
= NULL
;
1102 for (; langnode
; langnode
= langnode
->next
)
1104 if (langnode
->lang
.id
== LANG_NEUTRAL
&& langnode
->lang
.sub
== SUBLANG_NEUTRAL
)
1105 neutral
= langnode
->res
;
1106 if (langnode
->lang
.id
== MASTER_LANGUAGE
&& langnode
->lang
.sub
== SUBLANG_NEUTRAL
)
1108 if (langnode
->lang
.id
== MASTER_LANGUAGE
&& langnode
->lang
.sub
== MASTER_SUBLANGUAGE
)
1109 en_US
= langnode
->res
;
1112 if (neutral
!= NULL
&& (en
!= NULL
|| en_US
!= NULL
))
1114 fprintf(stderr
, "INFO: Resource %04x/%s has both NEUTRAL and MASTER language translarion\n",
1115 type
, get_nameid_str(id
));
1118 if (en_US
!= NULL
) return en_US
;
1119 if (en
!= NULL
) return en
;
1123 void verify_translations(resource_t
*top
) {
1124 resource_t
*curr
= top
;
1125 resource_id_node_t
*idnode
;
1126 resource_lang_node_t
*langnode
;
1136 for (type
= 0; type
<= res_usr
; type
++)
1138 printf("TYPE NEXT [%s]\n", get_typename_for_int(type
));
1139 for (idnode
= verify_tab
[type
].ids
; idnode
; idnode
= idnode
->next
)
1141 resource_t
*mainres
;
1142 printf("RESOURCE [%s]\n", get_nameid_str(idnode
->id
));
1144 mainres
= find_main(type
, idnode
->id
, idnode
->langs
);
1147 fprintf(stderr
, "ERR: resource %04x/%s has translation(s) but not available in NEUTRAL or MASTER language\n",
1148 type
, get_nameid_str(idnode
->id
));
1149 for (langnode
= idnode
->langs
; langnode
; langnode
= langnode
->next
)
1150 printf("EXTRA %03x:%02x\n", langnode
->lang
.id
, langnode
->lang
.sub
);
1154 if (get_language_id(mainres
) == LANG_NEUTRAL
&& idnode
->langs
->next
== NULL
) {
1155 printf("NOTRANSL\n");
1159 for (langnode
= idnode
->langs
; langnode
; langnode
= langnode
->next
)
1161 printf("EXIST %03x:%02x\n", langnode
->lang
.id
, langnode
->lang
.sub
);
1162 dump(langnode
->res
);
1163 if (compare(langnode
->res
, mainres
))
1165 printf("DIFF %03x:%02x\n", langnode
->lang
.id
, langnode
->lang
.sub
);