Release 1.3.7.
[wine/gsoc-2012-control.git] / tools / wrc / translation.c
blob20e8346308f559d3fc7780627af288db6d1d523b
1 /*
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
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <assert.h>
24 #include "dumpres.h"
25 #include "utils.h"
26 #include "wrc.h"
28 #define MASTER_LANGUAGE LANG_ENGLISH
29 #define MASTER_SUBLANGUAGE SUBLANG_ENGLISH_US
30 #define NB_LANG 0x94
32 enum lang_type_e {
33 lang_type_master = 0,
34 lang_type_neutral,
35 lang_type_normal
38 static language_t get_language(resource_t *resource) {
39 switch(resource->type) {
40 case res_acc:
41 return *resource->res.acc->lvc.language;
42 case res_bmp:
43 return *resource->res.bmp->data->lvc.language;
44 case res_cur:
45 return *resource->res.cur->lvc.language;
46 case res_curg:
47 return *resource->res.curg->lvc.language;
48 case res_dlg:
49 return *resource->res.dlg->lvc.language;
50 case res_fnt:
51 return *resource->res.fnt->data->lvc.language;
52 case res_fntdir:
53 return *resource->res.fnd->data->lvc.language;
54 case res_ico:
55 return *resource->res.ico->lvc.language;
56 case res_icog:
57 return *resource->res.icog->lvc.language;
58 case res_men:
59 return *resource->res.men->lvc.language;
60 case res_rdt:
61 return *resource->res.rdt->data->lvc.language;
62 case res_stt:
63 return *resource->res.stt->lvc.language;
64 case res_usr:
65 return *resource->res.usr->data->lvc.language;
66 case res_msg:
67 return *resource->res.msg->data->lvc.language;
68 case res_ver:
69 return *resource->res.ver->lvc.language;
70 case res_dlginit:
71 return *resource->res.dlgi->data->lvc.language;
72 case res_toolbar:
73 return *resource->res.tbt->lvc.language;
74 case res_anicur:
75 case res_aniico:
76 return *resource->res.ani->data->lvc.language;
77 case res_html:
78 return *resource->res.html->data->lvc.language;
79 default:
80 /* Not supposed to reach here */
81 fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
82 abort();
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));
95 #if 0
97 #define PRETTYPRINTLANG(langid) \
98 if(LANG_##langid == lid) { \
99 return #langid; \
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";
198 #endif
200 static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
201 int different = 0;
202 event_t *ev1 = NULL, *ev2 = NULL;
203 if(!different &&
204 ((accelerator1->memopt != accelerator2->memopt) ||
205 (accelerator1->lvc.version != accelerator2->lvc.version) ||
206 (accelerator1->lvc.characts != accelerator2->lvc.characts)))
207 different = 1;
208 ev1 = accelerator1->events;
209 ev2 = accelerator2->events;
210 while(!different && ev1 && ev2) {
211 if(!different &&
212 ((ev1->id != ev2->id) ||
213 (ev1->flags != ev2->flags)))
214 different = 1;
215 ev1 = ev1->next;
216 ev2 = ev2->next;
218 if(!different &&
219 ((ev1 && !ev2) || (!ev1 && ev2)))
220 different = 1;
221 return different;
224 static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
225 int different = 0;
226 if(!different &&
227 ((bitmap1->memopt != bitmap2->memopt) ||
228 (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
229 (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
230 different = 1;
231 return different;
234 static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
235 int different = 0;
236 if(!different &&
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)))
242 different = 1;
243 if(!different &&
244 ((cursor1->lvc.version != cursor2->lvc.version) ||
245 (cursor1->lvc.characts != cursor2->lvc.characts)))
246 different = 1;
247 return different;
250 static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
251 int different = 0;
252 cursor_t *cursor1 = NULL, *cursor2 = NULL;
253 if(!different &&
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)))
257 different = 1;
258 if(!different &&
259 (cursor_group1->ncursor != cursor_group2->ncursor))
260 different = 1;
261 if(!different) {
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;
269 if(!different &&
270 ((cursor1 && !cursor2) ||
271 (!cursor1 && cursor2)))
272 different = 1;
274 return different;
277 static int compare_control(control_t *control1, control_t *control2) {
278 int different = 0;
279 char *nameid = NULL;
280 int ignore_style;
281 if(!different &&
282 ((control1 && !control2) ||
283 (!control1 && control2)))
284 different = 1;
285 if(different || !control1 || !control2)
286 return different;
287 nameid = strdup(get_nameid_str(control1->ctlclass));
288 if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
289 different = 1;
290 free(nameid);
291 if (different)
292 return different;
294 /* allow the translators to set some styles */
295 ignore_style = 0;
296 if (control1->ctlclass->type == name_ord && control1->ctlclass->name.i_name == CT_BUTTON)
297 ignore_style = 0x2000; /* BS_MULTILINE*/
299 if(!different &&
300 (control1->id != control2->id))
301 different = 1;
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)))
306 different = 1;
307 } else if(!different &&
308 ((control1->gotstyle && !control2->gotstyle) ||
309 (!control1->gotstyle && control2->gotstyle)))
310 different = 1;
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))
315 different = 1;
316 } else if(!different &&
317 ((control1->gotexstyle && !control2->gotexstyle) ||
318 (!control1->gotexstyle && control2->gotexstyle)))
319 different = 1;
320 if(!different && control1->gothelpid && control2->gothelpid) {
321 if(control1->helpid != control2->helpid)
322 different = 1;
323 } else if(!different &&
324 ((control1->gothelpid && !control2->gothelpid) ||
325 (!control1->gothelpid && control2->gothelpid)))
326 different = 1;
327 return different;
330 static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
331 int different = 0;
332 char *nameid = NULL;
333 control_t *ctrl1, *ctrl2;
334 if(!different &&
335 ((dialog1->memopt != dialog2->memopt) ||
336 (dialog1->lvc.version != dialog2->lvc.version) ||
337 (dialog1->lvc.characts != dialog2->lvc.characts)))
338 different = 1;
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))
343 different = 1;
344 } else if(!different &&
345 ((dialog1->gotstyle && !dialog2->gotstyle) ||
346 (!dialog1->gotstyle && dialog2->gotstyle)))
347 different = 1;
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))
352 different = 1;
353 } else if(!different &&
354 ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
355 (!dialog1->gotexstyle && dialog2->gotexstyle)))
356 different = 1;
357 if(!different && dialog1->gothelpid && dialog2->gothelpid) {
358 if(dialog1->helpid != dialog2->helpid)
359 different = 1;
360 } else if(!different &&
361 ((dialog1->gothelpid && !dialog2->gothelpid) ||
362 (!dialog1->gothelpid && dialog2->gothelpid)))
363 different = 1;
364 nameid = strdup(get_nameid_str(dialog1->menu));
365 if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
366 different = 1;
367 free(nameid);
368 nameid = strdup(get_nameid_str(dialog1->dlgclass));
369 if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
370 different = 1;
371 free(nameid);
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;
381 return different;
384 static int compare_font(font_t *font1, font_t *font2) {
385 int different = 0;
386 if(!different &&
387 ((font1->memopt != font2->memopt) ||
388 (font1->data->lvc.version != font2->data->lvc.version) ||
389 (font1->data->lvc.characts != font2->data->lvc.characts)))
390 different = 1;
391 return different;
394 static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
395 int different = 0;
396 if(!different &&
397 ((fontdir1->memopt != fontdir2->memopt) ||
398 (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
399 (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
400 different = 1;
401 return different;
404 static int compare_icon(icon_t *icon1, icon_t *icon2) {
405 int different = 0;
406 if(!different &&
407 ((icon1->id != icon2->id) ||
408 (icon1->width != icon2->width) ||
409 (icon1->height != icon2->height)))
410 different = 1;
411 if(!different &&
412 ((icon1->lvc.version != icon2->lvc.version) ||
413 (icon1->lvc.characts != icon2->lvc.characts)))
414 different = 1;
415 return different;
418 static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
419 int different = 0;
420 icon_t *icon1 = NULL, *icon2 = NULL;
421 if(!different &&
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)))
425 different = 1;
426 if(!different &&
427 (icon_group1->nicon != icon_group2->nicon))
428 different = 1;
429 if(!different) {
430 icon1 = icon_group1->iconlist;
431 icon2 = icon_group2->iconlist;
432 while(!different && icon1 && icon2) {
433 different = compare_icon(icon1, icon2);
434 icon1 = icon1->next;
435 icon2 = icon2->next;
437 if(!different &&
438 ((icon1 && !icon2) ||
439 (!icon1 && icon2)))
440 different = 1;
442 return different;
445 static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
446 int different = 0;
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)
451 different = 1;
452 } else if(!different &&
453 ((menu_item1->gotid && !menu_item2->gotid) ||
454 (!menu_item1->gotid && menu_item2->gotid)))
455 different = 1;
456 if(!different && menu_item1->gottype && menu_item2->gottype) {
457 if(menu_item1->type != menu_item2->type)
458 different = 1;
459 } else if(!different &&
460 ((menu_item1->gottype && !menu_item2->gottype) ||
461 (!menu_item1->gottype && menu_item2->gottype)))
462 different = 1;
463 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
464 if(menu_item1->state != menu_item2->state)
465 different = 1;
466 } else if(!different &&
467 ((menu_item1->gotstate && !menu_item2->gotstate) ||
468 (!menu_item1->gotstate && menu_item2->gotstate)))
469 different = 1;
470 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
471 if(menu_item1->helpid != menu_item2->helpid)
472 different = 1;
473 } else if(!different &&
474 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
475 (!menu_item1->gothelpid && menu_item2->gothelpid)))
476 different = 1;
477 if(!different)
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)
483 different = 1;
484 } else if(!different &&
485 ((menu_item1->gotid && !menu_item2->gotid) ||
486 (!menu_item1->gotid && menu_item2->gotid)))
487 different = 1;
488 if(!different && menu_item1->gottype && menu_item2->gottype) {
489 if(menu_item1->type != menu_item2->type)
490 different = 1;
491 } else if(!different &&
492 ((menu_item1->gottype && !menu_item2->gottype) ||
493 (!menu_item1->gottype && menu_item2->gottype)))
494 different = 1;
495 if(!different && menu_item1->gotstate && menu_item2->gotstate) {
496 if(menu_item1->state != menu_item2->state)
497 different = 1;
498 } else if(!different &&
499 ((menu_item1->gotstate && !menu_item2->gotstate) ||
500 (!menu_item1->gotstate && menu_item2->gotstate)))
501 different = 1;
502 if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
503 if(menu_item1->helpid != menu_item2->helpid)
504 different = 1;
505 } else if(!different &&
506 ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
507 (!menu_item1->gothelpid && menu_item2->gothelpid)))
508 different = 1;
509 } else if((menu_item1->name && !menu_item2->name) ||
510 (!menu_item1->name && menu_item2->name))
511 different = 1;
512 } else
513 different = 1;
514 menu_item1 = menu_item1->next;
515 menu_item2 = menu_item2->next;
517 if(!different &&
518 ((menu_item1 && !menu_item2) ||
519 (!menu_item1 && menu_item2)))
520 different = 1;
521 return different;
524 static int compare_menu(menu_t *menu1, menu_t *menu2) {
525 int different = 0;
526 if(!different &&
527 ((menu1->memopt != menu2->memopt) ||
528 (menu1->lvc.version != menu2->lvc.version) ||
529 (menu1->lvc.characts != menu2->lvc.characts)))
530 different = 1;
531 if(!different)
532 different = compare_menu_item(menu1->items, menu2->items);
533 return different;
536 static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
537 int different = 0;
538 if(!different &&
539 ((rcdata1->memopt != rcdata2->memopt) ||
540 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
541 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
542 different = 1;
543 return different;
546 static int compare_html(html_t *rcdata1, html_t *rcdata2) {
547 int different = 0;
548 if(!different &&
549 ((rcdata1->memopt != rcdata2->memopt) ||
550 (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
551 (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
552 different = 1;
553 return different;
556 static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
557 int different = 0;
558 int i;
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))
563 different = 1;
564 if(!different) {
565 if((stringtable1->nentries != stringtable2->nentries) ||
566 (stringtable1->idbase != stringtable2->idbase))
567 different = 1;
568 else
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)) {
574 different = 1;
575 break;
578 stringtable1 = stringtable1->next;
579 stringtable2 = stringtable2->next;
581 return different;
584 static int compare_user(user_t *user1, user_t *user2) {
585 int different = 0;
586 char *nameid = NULL;
587 if(!different &&
588 ((user1->memopt != user2->memopt) ||
589 (user1->data->lvc.version != user2->data->lvc.version) ||
590 (user1->data->lvc.characts != user2->data->lvc.characts)))
591 different = 1;
592 nameid = strdup(get_nameid_str(user1->type));
593 if(!different && strcmp(nameid, get_nameid_str(user2->type)))
594 different = 1;
595 free(nameid);
596 return different;
599 static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
600 int different = 0;
601 if(!different &&
602 ((messagetable1->memopt != messagetable2->memopt) ||
603 (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
604 (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
605 different = 1;
606 return different;
609 static int compare_string(string_t *string1, string_t *string2) {
610 int different = 0;
611 if(!different &&
612 ((string1->size != string2->size) ||
613 (string1->type != string2->type)))
614 different = 1;
615 if(!different) {
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));
620 else
621 different = 1;
623 return different;
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) {
629 int different = 0;
630 int i = 0;
631 if(!different &&
632 (ver_value1->type == ver_value2->type)) {
633 switch(ver_value1->type) {
634 case val_str:
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)))
640 different = 1;
641 break;
642 case val_words:
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)))
648 different = 1;
649 if(!different && ver_value1->value.words && ver_value2->value.words) {
650 if(!different &&
651 (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
652 different = 1;
653 if(!different)
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]) {
656 different = 1;
657 break;
660 } else if(!different &&
661 ((ver_value1->value.words && !ver_value2->value.words) ||
662 (!ver_value1->value.words && ver_value2->value.words)))
663 different = 1;
664 break;
665 case val_block:
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)))
671 different = 1;
672 break;
673 default:
674 different = 1;
676 } else
677 different = 1;
678 return different;
681 static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
682 int different = 0;
683 ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
684 if(!different) {
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;
692 if(!different &&
693 ((ver_value1 && !ver_value2) ||
694 (!ver_value1 && ver_value2)))
695 different = 1;
697 return different;
700 static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
701 int different = 0;
702 ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
703 if(!different &&
704 ((versioninfo1->memopt != versioninfo2->memopt) ||
705 (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
706 (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
707 different = 1;
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))
713 different = 1;
714 } else if(!different &&
715 ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
716 (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
717 different = 1;
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))
723 different = 1;
724 } else if(!different &&
725 ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
726 (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
727 different = 1;
728 if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
729 if(versioninfo1->fileos != versioninfo2->fileos)
730 different = 1;
731 } else if(!different &&
732 ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
733 (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
734 different = 1;
735 if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
736 if(versioninfo1->fileflags != versioninfo2->fileflags)
737 different = 1;
738 } else if(!different &&
739 ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
740 (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
741 different = 1;
742 if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
743 if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
744 different = 1;
745 } else if(!different &&
746 ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
747 (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
748 different = 1;
749 if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
750 if(versioninfo1->filetype != versioninfo2->filetype)
751 different = 1;
752 } else if(!different &&
753 ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
754 (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
755 different = 1;
756 if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
757 if(versioninfo1->filesubtype != versioninfo2->filesubtype)
758 different = 1;
759 } else if(!different &&
760 ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
761 (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
762 different = 1;
763 if(!different) {
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;
771 if(!different &&
772 ((ver_block1 && !ver_block2) ||
773 (!ver_block1 && ver_block2)))
774 different = 1;
776 return different;
779 static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
780 int different = 0;
781 if(!different &&
782 ((dlginit1->memopt != dlginit2->memopt) ||
783 (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
784 (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
785 different = 1;
786 return different;
789 static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
790 int different = 0;
791 while(!different && toolbar_item1 && toolbar_item2) {
792 if((toolbar_item1->id && !toolbar_item2->id) ||
793 (!toolbar_item1->id && toolbar_item2->id))
794 different = 1;
795 toolbar_item1 = toolbar_item1->next;
796 toolbar_item2 = toolbar_item2->next;
798 if(!different &&
799 ((toolbar_item1 && !toolbar_item2) ||
800 (!toolbar_item1 && toolbar_item2)))
801 different = 1;
802 return different;
805 static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
806 int different = 0;
807 if(!different &&
808 ((toolbar1->memopt != toolbar2->memopt) ||
809 (toolbar1->lvc.version != toolbar2->lvc.version) ||
810 (toolbar1->lvc.characts != toolbar2->lvc.characts)))
811 different = 1;
812 if(!different)
813 different = compare_toolbar_item(toolbar1->items, toolbar2->items);
814 return different;
817 static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
818 int different = 0;
819 if(!different &&
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)))
823 different = 1;
824 return different;
827 static int compare(resource_t *resource1, resource_t *resource2) {
828 switch(resource1->type) {
829 case res_acc:
830 return compare_accelerator(resource1->res.acc, resource2->res.acc);
831 case res_bmp:
832 return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
833 case res_cur:
834 return compare_cursor(resource1->res.cur, resource2->res.cur);
835 case res_curg:
836 return compare_cursor_group(resource1->res.curg, resource2->res.curg);
837 case res_dlg:
838 return compare_dialog(resource1->res.dlg, resource2->res.dlg);
839 case res_fnt:
840 return compare_font(resource1->res.fnt, resource2->res.fnt);
841 case res_fntdir:
842 return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
843 case res_ico:
844 return compare_icon(resource1->res.ico, resource2->res.ico);
845 case res_icog:
846 return compare_icon_group(resource1->res.icog, resource2->res.icog);
847 case res_men:
848 return compare_menu(resource1->res.men, resource2->res.men);
849 case res_rdt:
850 return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
851 case res_stt:
852 return compare_stringtable(resource1->res.stt, resource2->res.stt);
853 case res_usr:
854 return compare_user(resource1->res.usr, resource2->res.usr);
855 case res_html:
856 return compare_html(resource1->res.html, resource2->res.html);
857 case res_msg:
858 return compare_messagetable(resource1->res.msg, resource2->res.msg);
859 case res_ver:
860 return compare_versioninfo(resource1->res.ver, resource2->res.ver);
861 case res_dlginit:
862 return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
863 case res_toolbar:
864 return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
865 case res_anicur:
866 case res_aniico:
867 return compare_ani_curico(resource1->res.ani, resource2->res.ani);
868 default:
869 /* Not supposed to reach here */
870 fprintf(stderr, "Not supposed to reach here (compare())\n");
871 abort();
872 return -1;
876 typedef struct resource_lang_node
878 language_t lang;
879 resource_t *res;
880 struct resource_lang_node *next;
881 } resource_lang_node_t;
883 typedef struct resource_id_node
885 name_id_t *id;
886 resource_lang_node_t *langs;
887 struct resource_id_node *next;
888 } resource_id_node_t;
890 static struct
892 int enabled;
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);
903 return;
906 for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
907 if (compare_name_id(idnode->id, res->name) == 0)
908 break;
910 if (idnode == NULL)
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);
924 return;
927 langnode = xmalloc(sizeof(resource_lang_node_t));
928 langnode->res = res;
929 langnode->lang = get_language(res);
930 langnode->next = idnode->langs;
931 idnode->langs = langnode;
934 static void setup_tabs(void)
936 int i;
938 for (i = 0; i <= res_usr; i++)
939 switch(i) {
940 case res_acc:
941 case res_bmp:
942 case res_cur:
943 case res_curg:
944 case res_dlg:
945 case res_fnt:
946 case res_fntdir:
947 case res_ico:
948 case res_icog:
949 case res_men:
950 case res_rdt:
951 case res_stt:
952 case res_usr:
953 case res_msg:
954 case res_ver:
955 case res_dlginit:
956 case res_toolbar:
957 case res_anicur:
958 case res_aniico:
959 case res_html:
960 verify_tab[i].enabled = 1;
961 break;
965 static const char *get_typename_for_int(int type) {
966 resource_t res;
967 res.type = 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)
979 en = langnode->res;
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 translarion\n",
987 type, get_nameid_str(id));
990 if (en_US != NULL) return en_US;
991 if (en != NULL) return en;
992 return neutral;
995 void verify_translations(resource_t *top) {
996 resource_t *curr = top;
997 resource_id_node_t *idnode;
998 resource_lang_node_t *langnode;
999 int type;
1001 setup_tabs();
1002 while (curr)
1004 add_resource(curr);
1005 curr = curr->next;
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);
1017 if (!mainres)
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);
1023 continue;
1026 if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
1027 printf("NOTRANSL\n");
1028 continue;
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);