translation.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. /*
  2. * Copyright 2003 Vincent Béron
  3. * Copyright 2007, 2008 Mikolaj Zalewski
  4. *
  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.
  9. *
  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.
  14. *
  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
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <assert.h>
  22. #include "../tools.h"
  23. #include "dumpres.h"
  24. #include "utils.h"
  25. #include "wrc.h"
  26. #define MASTER_LANGUAGE LANG_ENGLISH
  27. #define MASTER_SUBLANGUAGE SUBLANG_ENGLISH_US
  28. #define NB_LANG 0x94
  29. enum lang_type_e {
  30. lang_type_master = 0,
  31. lang_type_neutral,
  32. lang_type_normal
  33. };
  34. static language_t get_language(resource_t *resource) {
  35. switch(resource->type) {
  36. case res_acc:
  37. return *resource->res.acc->lvc.language;
  38. case res_bmp:
  39. return *resource->res.bmp->data->lvc.language;
  40. case res_cur:
  41. return *resource->res.cur->lvc.language;
  42. case res_curg:
  43. return *resource->res.curg->lvc.language;
  44. case res_dlg:
  45. return *resource->res.dlg->lvc.language;
  46. case res_fnt:
  47. return *resource->res.fnt->data->lvc.language;
  48. case res_fntdir:
  49. return *resource->res.fnd->data->lvc.language;
  50. case res_ico:
  51. return *resource->res.ico->lvc.language;
  52. case res_icog:
  53. return *resource->res.icog->lvc.language;
  54. case res_men:
  55. return *resource->res.men->lvc.language;
  56. case res_rdt:
  57. return *resource->res.rdt->data->lvc.language;
  58. case res_stt:
  59. return *resource->res.stt->lvc.language;
  60. case res_usr:
  61. return *resource->res.usr->data->lvc.language;
  62. case res_msg:
  63. return *resource->res.msg->data->lvc.language;
  64. case res_ver:
  65. return *resource->res.ver->lvc.language;
  66. case res_dlginit:
  67. return *resource->res.dlgi->data->lvc.language;
  68. case res_toolbar:
  69. return *resource->res.tbt->lvc.language;
  70. case res_anicur:
  71. case res_aniico:
  72. return *resource->res.ani->data->lvc.language;
  73. case res_html:
  74. return *resource->res.html->data->lvc.language;
  75. default:
  76. /* Not supposed to reach here */
  77. fprintf(stderr, "Not supposed to reach here (get_language_id())\n");
  78. abort();
  79. }
  80. }
  81. static int get_language_id(resource_t *resource) {
  82. return get_language(resource).id;
  83. }
  84. static int compare_lang(language_t lang1, language_t lang2)
  85. {
  86. return memcmp(&lang1, &lang2, sizeof(language_t));
  87. }
  88. #if 0
  89. #define PRETTYPRINTLANG(langid) \
  90. if(LANG_##langid == lid) { \
  91. return #langid; \
  92. }
  93. static const char *get_language_name(int lid) {
  94. PRETTYPRINTLANG(NEUTRAL)
  95. PRETTYPRINTLANG(AFRIKAANS)
  96. PRETTYPRINTLANG(ALBANIAN)
  97. PRETTYPRINTLANG(ARABIC)
  98. PRETTYPRINTLANG(ARMENIAN)
  99. PRETTYPRINTLANG(ASSAMESE)
  100. PRETTYPRINTLANG(AZERI)
  101. PRETTYPRINTLANG(BASQUE)
  102. PRETTYPRINTLANG(BELARUSIAN)
  103. PRETTYPRINTLANG(BENGALI)
  104. PRETTYPRINTLANG(BULGARIAN)
  105. PRETTYPRINTLANG(CATALAN)
  106. PRETTYPRINTLANG(CHINESE)
  107. PRETTYPRINTLANG(CROATIAN)
  108. PRETTYPRINTLANG(CZECH)
  109. PRETTYPRINTLANG(DANISH)
  110. PRETTYPRINTLANG(DIVEHI)
  111. PRETTYPRINTLANG(DUTCH)
  112. PRETTYPRINTLANG(ENGLISH)
  113. PRETTYPRINTLANG(ESTONIAN)
  114. PRETTYPRINTLANG(FAEROESE)
  115. PRETTYPRINTLANG(FARSI)
  116. PRETTYPRINTLANG(FINNISH)
  117. PRETTYPRINTLANG(FRENCH)
  118. PRETTYPRINTLANG(GALICIAN)
  119. PRETTYPRINTLANG(GEORGIAN)
  120. PRETTYPRINTLANG(GERMAN)
  121. PRETTYPRINTLANG(GREEK)
  122. PRETTYPRINTLANG(GUJARATI)
  123. PRETTYPRINTLANG(HEBREW)
  124. PRETTYPRINTLANG(HINDI)
  125. PRETTYPRINTLANG(HUNGARIAN)
  126. PRETTYPRINTLANG(ICELANDIC)
  127. PRETTYPRINTLANG(INDONESIAN)
  128. PRETTYPRINTLANG(IRISH)
  129. PRETTYPRINTLANG(ITALIAN)
  130. PRETTYPRINTLANG(JAPANESE)
  131. PRETTYPRINTLANG(KANNADA)
  132. PRETTYPRINTLANG(KASHMIRI)
  133. PRETTYPRINTLANG(KAZAK)
  134. PRETTYPRINTLANG(KONKANI)
  135. PRETTYPRINTLANG(KOREAN)
  136. PRETTYPRINTLANG(KYRGYZ)
  137. PRETTYPRINTLANG(LATVIAN)
  138. PRETTYPRINTLANG(LITHUANIAN)
  139. PRETTYPRINTLANG(MACEDONIAN)
  140. PRETTYPRINTLANG(MALAY)
  141. PRETTYPRINTLANG(MALAYALAM)
  142. PRETTYPRINTLANG(MANIPURI)
  143. PRETTYPRINTLANG(MARATHI)
  144. PRETTYPRINTLANG(MONGOLIAN)
  145. PRETTYPRINTLANG(NEPALI)
  146. PRETTYPRINTLANG(NORWEGIAN)
  147. PRETTYPRINTLANG(ORIYA)
  148. PRETTYPRINTLANG(POLISH)
  149. PRETTYPRINTLANG(PORTUGUESE)
  150. PRETTYPRINTLANG(PUNJABI)
  151. PRETTYPRINTLANG(ROMANIAN)
  152. PRETTYPRINTLANG(RUSSIAN)
  153. PRETTYPRINTLANG(SANSKRIT)
  154. PRETTYPRINTLANG(SERBIAN)
  155. PRETTYPRINTLANG(SINDHI)
  156. PRETTYPRINTLANG(SLOVAK)
  157. PRETTYPRINTLANG(SLOVENIAN)
  158. PRETTYPRINTLANG(SPANISH)
  159. PRETTYPRINTLANG(SWAHILI)
  160. PRETTYPRINTLANG(SWEDISH)
  161. PRETTYPRINTLANG(SYRIAC)
  162. PRETTYPRINTLANG(TAMIL)
  163. PRETTYPRINTLANG(TATAR)
  164. PRETTYPRINTLANG(TELUGU)
  165. PRETTYPRINTLANG(THAI)
  166. PRETTYPRINTLANG(TURKISH)
  167. PRETTYPRINTLANG(UKRAINIAN)
  168. PRETTYPRINTLANG(URDU)
  169. PRETTYPRINTLANG(UZBEK)
  170. PRETTYPRINTLANG(VIETNAMESE)
  171. PRETTYPRINTLANG(SCOTTISH_GAELIC)
  172. PRETTYPRINTLANG(MALTESE)
  173. PRETTYPRINTLANG(MAORI)
  174. PRETTYPRINTLANG(RHAETO_ROMANCE)
  175. PRETTYPRINTLANG(SAAMI)
  176. PRETTYPRINTLANG(SORBIAN)
  177. PRETTYPRINTLANG(SUTU)
  178. PRETTYPRINTLANG(TSONGA)
  179. PRETTYPRINTLANG(TSWANA)
  180. PRETTYPRINTLANG(VENDA)
  181. PRETTYPRINTLANG(XHOSA)
  182. PRETTYPRINTLANG(ZULU)
  183. PRETTYPRINTLANG(ESPERANTO)
  184. PRETTYPRINTLANG(WALON)
  185. PRETTYPRINTLANG(CORNISH)
  186. PRETTYPRINTLANG(WELSH)
  187. PRETTYPRINTLANG(BRETON)
  188. return "Unknown language";
  189. }
  190. #endif
  191. static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
  192. int different = 0;
  193. event_t *ev1 = NULL, *ev2 = NULL;
  194. if(((accelerator1->memopt != accelerator2->memopt) ||
  195. (accelerator1->lvc.version != accelerator2->lvc.version) ||
  196. (accelerator1->lvc.characts != accelerator2->lvc.characts)))
  197. different = 1;
  198. ev1 = accelerator1->events;
  199. ev2 = accelerator2->events;
  200. while(!different && ev1 && ev2) {
  201. if(!different &&
  202. ((ev1->id != ev2->id) ||
  203. (ev1->flags != ev2->flags)))
  204. different = 1;
  205. ev1 = ev1->next;
  206. ev2 = ev2->next;
  207. }
  208. if(!different &&
  209. ((ev1 && !ev2) || (!ev1 && ev2)))
  210. different = 1;
  211. return different;
  212. }
  213. static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
  214. int different = 0;
  215. if(((bitmap1->memopt != bitmap2->memopt) ||
  216. (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
  217. (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
  218. different = 1;
  219. return different;
  220. }
  221. static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
  222. int different = 0;
  223. if(((cursor1->id != cursor2->id) ||
  224. (cursor1->width != cursor2->width) ||
  225. (cursor1->height != cursor2->height) ||
  226. (cursor1->xhot != cursor2->xhot) ||
  227. (cursor1->yhot != cursor2->yhot)))
  228. different = 1;
  229. if(!different &&
  230. ((cursor1->lvc.version != cursor2->lvc.version) ||
  231. (cursor1->lvc.characts != cursor2->lvc.characts)))
  232. different = 1;
  233. return different;
  234. }
  235. static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
  236. int different = 0;
  237. cursor_t *cursor1 = NULL, *cursor2 = NULL;
  238. if(((cursor_group1->memopt != cursor_group2->memopt) ||
  239. (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
  240. (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
  241. different = 1;
  242. if(!different &&
  243. (cursor_group1->ncursor != cursor_group2->ncursor))
  244. different = 1;
  245. if(!different) {
  246. cursor1 = cursor_group1->cursorlist;
  247. cursor2 = cursor_group2->cursorlist;
  248. while(!different && cursor1 && cursor2) {
  249. different = compare_cursor(cursor1, cursor2);
  250. cursor1 = cursor1->next;
  251. cursor2 = cursor2->next;
  252. }
  253. if(!different &&
  254. ((cursor1 && !cursor2) ||
  255. (!cursor1 && cursor2)))
  256. different = 1;
  257. }
  258. return different;
  259. }
  260. static int compare_control(control_t *control1, control_t *control2) {
  261. int different = 0;
  262. char *nameid = NULL;
  263. int ignore_style;
  264. if(((control1 && !control2) || (!control1 && control2)))
  265. different = 1;
  266. if(different || !control1 || !control2)
  267. return different;
  268. nameid = strdup(get_nameid_str(control1->ctlclass));
  269. if(strcmp(nameid, get_nameid_str(control2->ctlclass)))
  270. different = 1;
  271. free(nameid);
  272. if (different)
  273. return different;
  274. /* allow the translators to set some styles */
  275. ignore_style = 0;
  276. if (control1->ctlclass->type == name_ord && control1->ctlclass->name.i_name == CT_BUTTON)
  277. ignore_style = 0x2000; /* BS_MULTILINE*/
  278. if((control1->id != control2->id))
  279. different = 1;
  280. if(!different && control1->gotstyle && control2->gotstyle) {
  281. if((!control1->style || !control2->style) ||
  282. (control1->style->and_mask || control2->style->and_mask) ||
  283. ((control1->style->or_mask & ~ignore_style) != (control2->style->or_mask & ~ignore_style)))
  284. different = 1;
  285. } else if(!different &&
  286. ((control1->gotstyle && !control2->gotstyle) ||
  287. (!control1->gotstyle && control2->gotstyle)))
  288. different = 1;
  289. if(!different && control1->gotexstyle && control2->gotexstyle) {
  290. if((!control1->exstyle || !control2->exstyle) ||
  291. (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
  292. (control1->exstyle->or_mask != control2->exstyle->or_mask))
  293. different = 1;
  294. } else if(!different &&
  295. ((control1->gotexstyle && !control2->gotexstyle) ||
  296. (!control1->gotexstyle && control2->gotexstyle)))
  297. different = 1;
  298. if(!different && control1->gothelpid && control2->gothelpid) {
  299. if(control1->helpid != control2->helpid)
  300. different = 1;
  301. } else if(!different &&
  302. ((control1->gothelpid && !control2->gothelpid) ||
  303. (!control1->gothelpid && control2->gothelpid)))
  304. different = 1;
  305. return different;
  306. }
  307. static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
  308. int different = 0;
  309. char *nameid = NULL;
  310. control_t *ctrl1, *ctrl2;
  311. if(((dialog1->memopt != dialog2->memopt) ||
  312. (dialog1->lvc.version != dialog2->lvc.version) ||
  313. (dialog1->lvc.characts != dialog2->lvc.characts)))
  314. different = 1;
  315. if(!different && dialog1->gotstyle && dialog2->gotstyle) {
  316. if((!dialog1->style || !dialog2->style) ||
  317. (dialog1->style->and_mask || dialog2->style->and_mask) ||
  318. (dialog1->style->or_mask != dialog2->style->or_mask))
  319. different = 1;
  320. } else if(!different &&
  321. ((dialog1->gotstyle && !dialog2->gotstyle) ||
  322. (!dialog1->gotstyle && dialog2->gotstyle)))
  323. different = 1;
  324. if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
  325. if((!dialog1->exstyle || !dialog2->exstyle) ||
  326. (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
  327. (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
  328. different = 1;
  329. } else if(!different &&
  330. ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
  331. (!dialog1->gotexstyle && dialog2->gotexstyle)))
  332. different = 1;
  333. if(!different && dialog1->gothelpid && dialog2->gothelpid) {
  334. if(dialog1->helpid != dialog2->helpid)
  335. different = 1;
  336. } else if(!different &&
  337. ((dialog1->gothelpid && !dialog2->gothelpid) ||
  338. (!dialog1->gothelpid && dialog2->gothelpid)))
  339. different = 1;
  340. nameid = strdup(get_nameid_str(dialog1->menu));
  341. if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
  342. different = 1;
  343. free(nameid);
  344. nameid = strdup(get_nameid_str(dialog1->dlgclass));
  345. if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
  346. different = 1;
  347. free(nameid);
  348. ctrl1 = dialog1->controls;
  349. ctrl2 = dialog2->controls;
  350. while(!different && (ctrl1 || ctrl2))
  351. {
  352. different = compare_control(ctrl1, ctrl2);
  353. if (ctrl1) ctrl1 = ctrl1->next;
  354. if (ctrl2) ctrl2 = ctrl2->next;
  355. }
  356. return different;
  357. }
  358. static int compare_font(font_t *font1, font_t *font2) {
  359. int different = 0;
  360. if(((font1->memopt != font2->memopt) ||
  361. (font1->data->lvc.version != font2->data->lvc.version) ||
  362. (font1->data->lvc.characts != font2->data->lvc.characts)))
  363. different = 1;
  364. return different;
  365. }
  366. static int compare_fontdir(fontdir_t *fontdir1, fontdir_t *fontdir2) {
  367. int different = 0;
  368. if(((fontdir1->memopt != fontdir2->memopt) ||
  369. (fontdir1->data->lvc.version != fontdir2->data->lvc.version) ||
  370. (fontdir1->data->lvc.characts != fontdir2->data->lvc.characts)))
  371. different = 1;
  372. return different;
  373. }
  374. static int compare_icon(icon_t *icon1, icon_t *icon2) {
  375. int different = 0;
  376. if(((icon1->id != icon2->id) ||
  377. (icon1->width != icon2->width) ||
  378. (icon1->height != icon2->height)))
  379. different = 1;
  380. if(!different &&
  381. ((icon1->lvc.version != icon2->lvc.version) ||
  382. (icon1->lvc.characts != icon2->lvc.characts)))
  383. different = 1;
  384. return different;
  385. }
  386. static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
  387. int different = 0;
  388. icon_t *icon1 = NULL, *icon2 = NULL;
  389. if(((icon_group1->memopt != icon_group2->memopt) ||
  390. (icon_group1->lvc.version != icon_group2->lvc.version) ||
  391. (icon_group1->lvc.characts != icon_group2->lvc.characts)))
  392. different = 1;
  393. if(!different &&
  394. (icon_group1->nicon != icon_group2->nicon))
  395. different = 1;
  396. if(!different) {
  397. icon1 = icon_group1->iconlist;
  398. icon2 = icon_group2->iconlist;
  399. while(!different && icon1 && icon2) {
  400. different = compare_icon(icon1, icon2);
  401. icon1 = icon1->next;
  402. icon2 = icon2->next;
  403. }
  404. if(!different &&
  405. ((icon1 && !icon2) ||
  406. (!icon1 && icon2)))
  407. different = 1;
  408. }
  409. return different;
  410. }
  411. static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
  412. int different = 0;
  413. while(!different && menu_item1 && menu_item2) {
  414. if(menu_item1->popup && menu_item2->popup) {
  415. if(!different && menu_item1->gotid && menu_item2->gotid) {
  416. if(menu_item1->id != menu_item2->id)
  417. different = 1;
  418. } else if(!different &&
  419. ((menu_item1->gotid && !menu_item2->gotid) ||
  420. (!menu_item1->gotid && menu_item2->gotid)))
  421. different = 1;
  422. if(!different && menu_item1->gottype && menu_item2->gottype) {
  423. if(menu_item1->type != menu_item2->type)
  424. different = 1;
  425. } else if(!different &&
  426. ((menu_item1->gottype && !menu_item2->gottype) ||
  427. (!menu_item1->gottype && menu_item2->gottype)))
  428. different = 1;
  429. if(!different && menu_item1->gotstate && menu_item2->gotstate) {
  430. if(menu_item1->state != menu_item2->state)
  431. different = 1;
  432. } else if(!different &&
  433. ((menu_item1->gotstate && !menu_item2->gotstate) ||
  434. (!menu_item1->gotstate && menu_item2->gotstate)))
  435. different = 1;
  436. if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
  437. if(menu_item1->helpid != menu_item2->helpid)
  438. different = 1;
  439. } else if(!different &&
  440. ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
  441. (!menu_item1->gothelpid && menu_item2->gothelpid)))
  442. different = 1;
  443. if(!different)
  444. different = compare_menu_item(menu_item1->popup, menu_item2->popup);
  445. } else if(!menu_item1->popup && !menu_item2->popup) {
  446. if(menu_item1->name && menu_item2->name) {
  447. if(!different && menu_item1->gotid && menu_item2->gotid) {
  448. if(menu_item1->id != menu_item2->id)
  449. different = 1;
  450. } else if(!different &&
  451. ((menu_item1->gotid && !menu_item2->gotid) ||
  452. (!menu_item1->gotid && menu_item2->gotid)))
  453. different = 1;
  454. if(!different && menu_item1->gottype && menu_item2->gottype) {
  455. if(menu_item1->type != menu_item2->type)
  456. different = 1;
  457. } else if(!different &&
  458. ((menu_item1->gottype && !menu_item2->gottype) ||
  459. (!menu_item1->gottype && menu_item2->gottype)))
  460. different = 1;
  461. if(!different && menu_item1->gotstate && menu_item2->gotstate) {
  462. if(menu_item1->state != menu_item2->state)
  463. different = 1;
  464. } else if(!different &&
  465. ((menu_item1->gotstate && !menu_item2->gotstate) ||
  466. (!menu_item1->gotstate && menu_item2->gotstate)))
  467. different = 1;
  468. if(!different && menu_item1->gothelpid && menu_item2->gothelpid) {
  469. if(menu_item1->helpid != menu_item2->helpid)
  470. different = 1;
  471. } else if(!different &&
  472. ((menu_item1->gothelpid && !menu_item2->gothelpid) ||
  473. (!menu_item1->gothelpid && menu_item2->gothelpid)))
  474. different = 1;
  475. } else if((menu_item1->name && !menu_item2->name) ||
  476. (!menu_item1->name && menu_item2->name))
  477. different = 1;
  478. } else
  479. different = 1;
  480. menu_item1 = menu_item1->next;
  481. menu_item2 = menu_item2->next;
  482. }
  483. if(!different &&
  484. ((menu_item1 && !menu_item2) ||
  485. (!menu_item1 && menu_item2)))
  486. different = 1;
  487. return different;
  488. }
  489. static int compare_menu(menu_t *menu1, menu_t *menu2) {
  490. int different = 0;
  491. if(((menu1->memopt != menu2->memopt) ||
  492. (menu1->lvc.version != menu2->lvc.version) ||
  493. (menu1->lvc.characts != menu2->lvc.characts)))
  494. different = 1;
  495. if(!different)
  496. different = compare_menu_item(menu1->items, menu2->items);
  497. return different;
  498. }
  499. static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
  500. int different = 0;
  501. if(((rcdata1->memopt != rcdata2->memopt) ||
  502. (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
  503. (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
  504. different = 1;
  505. return different;
  506. }
  507. static int compare_html(html_t *rcdata1, html_t *rcdata2) {
  508. int different = 0;
  509. if(((rcdata1->memopt != rcdata2->memopt) ||
  510. (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
  511. (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
  512. different = 1;
  513. return different;
  514. }
  515. static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
  516. int different = 0;
  517. int i;
  518. while(!different && stringtable1 && stringtable2) {
  519. if((stringtable1->memopt != stringtable2->memopt) ||
  520. (stringtable1->lvc.version != stringtable2->lvc.version) ||
  521. (stringtable1->lvc.characts != stringtable2->lvc.characts))
  522. different = 1;
  523. if(!different) {
  524. if((stringtable1->nentries != stringtable2->nentries) ||
  525. (stringtable1->idbase != stringtable2->idbase))
  526. different = 1;
  527. else
  528. for(i = 0 ; i < stringtable1->nentries; i++)
  529. if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
  530. (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
  531. (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
  532. (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
  533. different = 1;
  534. break;
  535. }
  536. }
  537. stringtable1 = stringtable1->next;
  538. stringtable2 = stringtable2->next;
  539. }
  540. return different;
  541. }
  542. static int compare_user(user_t *user1, user_t *user2) {
  543. int different = 0;
  544. char *nameid = NULL;
  545. if(((user1->memopt != user2->memopt) ||
  546. (user1->data->lvc.version != user2->data->lvc.version) ||
  547. (user1->data->lvc.characts != user2->data->lvc.characts)))
  548. different = 1;
  549. nameid = strdup(get_nameid_str(user1->type));
  550. if(!different && strcmp(nameid, get_nameid_str(user2->type)))
  551. different = 1;
  552. free(nameid);
  553. return different;
  554. }
  555. static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
  556. int different = 0;
  557. if(((messagetable1->memopt != messagetable2->memopt) ||
  558. (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
  559. (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
  560. different = 1;
  561. return different;
  562. }
  563. static int compare_string(string_t *string1, string_t *string2) {
  564. int different = 0;
  565. if(((string1->size != string2->size) ||
  566. (string1->type != string2->type)))
  567. different = 1;
  568. if(!different) {
  569. if(string1->type == str_char)
  570. different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
  571. else if(string1->type == str_unicode)
  572. different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
  573. else
  574. different = 1;
  575. }
  576. return different;
  577. }
  578. static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
  579. static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
  580. int different = 0;
  581. int i = 0;
  582. if (ver_value1->type == ver_value2->type) {
  583. switch(ver_value1->type) {
  584. case val_str:
  585. if(ver_value1->key && ver_value2->key)
  586. different = compare_string(ver_value1->key, ver_value2->key);
  587. else if(((ver_value1->key && !ver_value2->key) ||
  588. (!ver_value1->key && ver_value2->key)))
  589. different = 1;
  590. break;
  591. case val_words:
  592. if(ver_value1->key && ver_value2->key)
  593. different = compare_string(ver_value1->key, ver_value2->key);
  594. else if(((ver_value1->key && !ver_value2->key) ||
  595. (!ver_value1->key && ver_value2->key)))
  596. different = 1;
  597. if(!different && ver_value1->value.words && ver_value2->value.words) {
  598. if(ver_value1->value.words->nwords != ver_value2->value.words->nwords)
  599. different = 1;
  600. if(!different)
  601. for(i = 0; i < ver_value1->value.words->nwords; i++) {
  602. if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
  603. different = 1;
  604. break;
  605. }
  606. }
  607. } else if(!different &&
  608. ((ver_value1->value.words && !ver_value2->value.words) ||
  609. (!ver_value1->value.words && ver_value2->value.words)))
  610. different = 1;
  611. break;
  612. case val_block:
  613. if(ver_value1->value.block && ver_value2->value.block)
  614. different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
  615. else if(((ver_value1->value.block && !ver_value2->value.block) ||
  616. (!ver_value1->value.block && ver_value2->value.block)))
  617. different = 1;
  618. break;
  619. default:
  620. different = 1;
  621. }
  622. } else
  623. different = 1;
  624. return different;
  625. }
  626. static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
  627. int different = 0;
  628. ver_value_t *ver_value1 = ver_block1->values, *ver_value2 = ver_block2->values;
  629. while(!different && ver_value1 && ver_value2) {
  630. different = compare_ver_value(ver_value1, ver_value2);
  631. ver_value1 = ver_value1->next;
  632. ver_value2 = ver_value2->next;
  633. }
  634. if(!different &&
  635. ((ver_value1 && !ver_value2) ||
  636. (!ver_value1 && ver_value2)))
  637. different = 1;
  638. return different;
  639. }
  640. static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
  641. int different = 0;
  642. ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
  643. if(((versioninfo1->memopt != versioninfo2->memopt) ||
  644. (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
  645. (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
  646. different = 1;
  647. if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
  648. if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
  649. (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
  650. (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
  651. (versioninfo1->filever_min2 != versioninfo2->filever_min2))
  652. different = 1;
  653. } else if(!different &&
  654. ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
  655. (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
  656. different = 1;
  657. if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
  658. if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
  659. (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
  660. (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
  661. (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
  662. different = 1;
  663. } else if(!different &&
  664. ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
  665. (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
  666. different = 1;
  667. if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
  668. if(versioninfo1->fileos != versioninfo2->fileos)
  669. different = 1;
  670. } else if(!different &&
  671. ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
  672. (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
  673. different = 1;
  674. if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
  675. if(versioninfo1->fileflags != versioninfo2->fileflags)
  676. different = 1;
  677. } else if(!different &&
  678. ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
  679. (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
  680. different = 1;
  681. if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
  682. if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
  683. different = 1;
  684. } else if(!different &&
  685. ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
  686. (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
  687. different = 1;
  688. if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
  689. if(versioninfo1->filetype != versioninfo2->filetype)
  690. different = 1;
  691. } else if(!different &&
  692. ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
  693. (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
  694. different = 1;
  695. if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
  696. if(versioninfo1->filesubtype != versioninfo2->filesubtype)
  697. different = 1;
  698. } else if(!different &&
  699. ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
  700. (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
  701. different = 1;
  702. if(!different) {
  703. ver_block1 = versioninfo1->blocks;
  704. ver_block2 = versioninfo2->blocks;
  705. while(!different && ver_block1 && ver_block2) {
  706. different = compare_ver_block(ver_block1, ver_block2);
  707. ver_block1 = ver_block1->next;
  708. ver_block2 = ver_block2->next;
  709. }
  710. if(!different &&
  711. ((ver_block1 && !ver_block2) ||
  712. (!ver_block1 && ver_block2)))
  713. different = 1;
  714. }
  715. return different;
  716. }
  717. static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
  718. int different = 0;
  719. if(((dlginit1->memopt != dlginit2->memopt) ||
  720. (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
  721. (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
  722. different = 1;
  723. return different;
  724. }
  725. static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
  726. int different = 0;
  727. while(!different && toolbar_item1 && toolbar_item2) {
  728. if((toolbar_item1->id && !toolbar_item2->id) ||
  729. (!toolbar_item1->id && toolbar_item2->id))
  730. different = 1;
  731. toolbar_item1 = toolbar_item1->next;
  732. toolbar_item2 = toolbar_item2->next;
  733. }
  734. if(!different &&
  735. ((toolbar_item1 && !toolbar_item2) ||
  736. (!toolbar_item1 && toolbar_item2)))
  737. different = 1;
  738. return different;
  739. }
  740. static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
  741. int different = 0;
  742. if(((toolbar1->memopt != toolbar2->memopt) ||
  743. (toolbar1->lvc.version != toolbar2->lvc.version) ||
  744. (toolbar1->lvc.characts != toolbar2->lvc.characts)))
  745. different = 1;
  746. if(!different)
  747. different = compare_toolbar_item(toolbar1->items, toolbar2->items);
  748. return different;
  749. }
  750. static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
  751. int different = 0;
  752. if(((ani_curico1->memopt != ani_curico2->memopt) ||
  753. (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
  754. (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
  755. different = 1;
  756. return different;
  757. }
  758. static int compare(resource_t *resource1, resource_t *resource2) {
  759. switch(resource1->type) {
  760. case res_acc:
  761. return compare_accelerator(resource1->res.acc, resource2->res.acc);
  762. case res_bmp:
  763. return compare_bitmap(resource1->res.bmp, resource2->res.bmp);
  764. case res_cur:
  765. return compare_cursor(resource1->res.cur, resource2->res.cur);
  766. case res_curg:
  767. return compare_cursor_group(resource1->res.curg, resource2->res.curg);
  768. case res_dlg:
  769. return compare_dialog(resource1->res.dlg, resource2->res.dlg);
  770. case res_fnt:
  771. return compare_font(resource1->res.fnt, resource2->res.fnt);
  772. case res_fntdir:
  773. return compare_fontdir(resource1->res.fnd, resource2->res.fnd);
  774. case res_ico:
  775. return compare_icon(resource1->res.ico, resource2->res.ico);
  776. case res_icog:
  777. return compare_icon_group(resource1->res.icog, resource2->res.icog);
  778. case res_men:
  779. return compare_menu(resource1->res.men, resource2->res.men);
  780. case res_rdt:
  781. return compare_rcdata(resource1->res.rdt, resource2->res.rdt);
  782. case res_stt:
  783. return compare_stringtable(resource1->res.stt, resource2->res.stt);
  784. case res_usr:
  785. return compare_user(resource1->res.usr, resource2->res.usr);
  786. case res_html:
  787. return compare_html(resource1->res.html, resource2->res.html);
  788. case res_msg:
  789. return compare_messagetable(resource1->res.msg, resource2->res.msg);
  790. case res_ver:
  791. return compare_versioninfo(resource1->res.ver, resource2->res.ver);
  792. case res_dlginit:
  793. return compare_dlginit(resource1->res.dlgi, resource2->res.dlgi);
  794. case res_toolbar:
  795. return compare_toolbar(resource1->res.tbt, resource2->res.tbt);
  796. case res_anicur:
  797. case res_aniico:
  798. return compare_ani_curico(resource1->res.ani, resource2->res.ani);
  799. default:
  800. /* Not supposed to reach here */
  801. fprintf(stderr, "Not supposed to reach here (compare())\n");
  802. abort();
  803. return -1;
  804. }
  805. }
  806. typedef struct resource_lang_node
  807. {
  808. language_t lang;
  809. resource_t *res;
  810. struct resource_lang_node *next;
  811. } resource_lang_node_t;
  812. typedef struct resource_id_node
  813. {
  814. name_id_t *id;
  815. resource_lang_node_t *langs;
  816. struct resource_id_node *next;
  817. } resource_id_node_t;
  818. static struct
  819. {
  820. int enabled;
  821. struct resource_id_node *ids;
  822. } verify_tab[res_usr+1];
  823. static void add_resource(resource_t *res)
  824. {
  825. resource_id_node_t *idnode;
  826. resource_lang_node_t *langnode;
  827. if (!verify_tab[res->type].enabled)
  828. {
  829. fprintf(stderr, "ERR: Report this: unknown resource type parsed %08x\n", res->type);
  830. return;
  831. }
  832. for (idnode = verify_tab[res->type].ids; idnode; idnode = idnode->next)
  833. if (compare_name_id(idnode->id, res->name) == 0)
  834. break;
  835. if (idnode == NULL)
  836. {
  837. idnode = xmalloc(sizeof(resource_id_node_t));
  838. idnode->id = res->name;
  839. idnode->langs = NULL;
  840. idnode->next = verify_tab[res->type].ids;
  841. verify_tab[res->type].ids = idnode;
  842. }
  843. for (langnode = idnode->langs; langnode; langnode = langnode->next)
  844. if (compare_lang(langnode->lang, get_language(res)) == 0)
  845. {
  846. fprintf(stderr, "ERR: resource %s [type %x] language %03x:%02x duplicated!\n",
  847. get_nameid_str(res->name), res->type, langnode->lang.id, langnode->lang.sub);
  848. return;
  849. }
  850. langnode = xmalloc(sizeof(resource_lang_node_t));
  851. langnode->res = res;
  852. langnode->lang = get_language(res);
  853. langnode->next = idnode->langs;
  854. idnode->langs = langnode;
  855. }
  856. static void setup_tabs(void)
  857. {
  858. int i;
  859. for (i = 0; i <= res_usr; i++)
  860. switch(i) {
  861. case res_acc:
  862. case res_bmp:
  863. case res_cur:
  864. case res_curg:
  865. case res_dlg:
  866. case res_fnt:
  867. case res_fntdir:
  868. case res_ico:
  869. case res_icog:
  870. case res_men:
  871. case res_rdt:
  872. case res_stt:
  873. case res_usr:
  874. case res_msg:
  875. case res_ver:
  876. case res_dlginit:
  877. case res_toolbar:
  878. case res_anicur:
  879. case res_aniico:
  880. case res_html:
  881. verify_tab[i].enabled = 1;
  882. break;
  883. }
  884. }
  885. static const char *get_typename_for_int(int type) {
  886. resource_t res;
  887. res.type = type;
  888. return get_typename(&res);
  889. }
  890. static resource_t *find_main(int type, name_id_t *id, resource_lang_node_t *langnode)
  891. {
  892. resource_t *neutral = NULL, *en = NULL, *en_US = NULL;
  893. for (; langnode; langnode = langnode->next)
  894. {
  895. if (langnode->lang.id == LANG_NEUTRAL && langnode->lang.sub == SUBLANG_NEUTRAL)
  896. neutral = langnode->res;
  897. if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == SUBLANG_NEUTRAL)
  898. en = langnode->res;
  899. if (langnode->lang.id == MASTER_LANGUAGE && langnode->lang.sub == MASTER_SUBLANGUAGE)
  900. en_US = langnode->res;
  901. }
  902. if (neutral != NULL && (en != NULL || en_US != NULL))
  903. {
  904. fprintf(stderr, "INFO: Resource %04x/%s has both NEUTRAL and MASTER language translation\n",
  905. type, get_nameid_str(id));
  906. }
  907. if (en_US != NULL) return en_US;
  908. if (en != NULL) return en;
  909. return neutral;
  910. }
  911. void verify_translations(resource_t *top) {
  912. resource_t *curr = top;
  913. resource_id_node_t *idnode;
  914. resource_lang_node_t *langnode;
  915. int type;
  916. setup_tabs();
  917. while (curr)
  918. {
  919. add_resource(curr);
  920. curr = curr->next;
  921. }
  922. for (type = 0; type <= res_usr; type++)
  923. {
  924. printf("TYPE NEXT [%s]\n", get_typename_for_int(type));
  925. for (idnode = verify_tab[type].ids; idnode; idnode = idnode->next)
  926. {
  927. resource_t *mainres;
  928. printf("RESOURCE [%s]\n", get_nameid_str(idnode->id));
  929. mainres = find_main(type, idnode->id, idnode->langs);
  930. if (!mainres)
  931. {
  932. fprintf(stderr, "ERR: resource %04x/%s has translation(s) but not available in NEUTRAL or MASTER language\n",
  933. type, get_nameid_str(idnode->id));
  934. for (langnode = idnode->langs; langnode; langnode = langnode->next)
  935. printf("EXTRA %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
  936. continue;
  937. }
  938. if (get_language_id(mainres) == LANG_NEUTRAL && idnode->langs->next == NULL) {
  939. printf("NOTRANSL\n");
  940. continue;
  941. }
  942. for (langnode = idnode->langs; langnode; langnode = langnode->next)
  943. {
  944. printf("EXIST %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
  945. if (compare(langnode->res, mainres))
  946. {
  947. printf("DIFF %03x:%02x\n", langnode->lang.id, langnode->lang.sub);
  948. }
  949. }
  950. }
  951. }
  952. }