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