genres.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. /*
  2. * Generate .res format from a resource-tree
  3. *
  4. * Copyright 1998 Bertho A. Stultiens
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. *
  20. * History:
  21. * 05-May-2000 BS - Added code to support endian conversions. The
  22. * extra functions also aid unaligned access, but
  23. * this is not yet implemented.
  24. * 25-May-1998 BS - Added simple unicode -> char conversion for resource
  25. * names in .s and .h files.
  26. */
  27. #include "config.h"
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <stdarg.h>
  32. #include <assert.h>
  33. #include <ctype.h>
  34. #include "../tools.h"
  35. #include "wrc.h"
  36. #include "utils.h"
  37. #include "windef.h"
  38. #include "winbase.h"
  39. #include "wingdi.h"
  40. #include "winuser.h"
  41. unsigned char *output_buffer = NULL;
  42. size_t output_buffer_pos = 0;
  43. size_t output_buffer_size = 0;
  44. static void set_word(int ofs, unsigned int w)
  45. {
  46. output_buffer[ofs+0] = w;
  47. output_buffer[ofs+1] = w >> 8;
  48. }
  49. static void set_dword(int ofs, unsigned int d)
  50. {
  51. output_buffer[ofs+0] = d;
  52. output_buffer[ofs+1] = d >> 8;
  53. output_buffer[ofs+2] = d >> 16;
  54. output_buffer[ofs+3] = d >> 24;
  55. }
  56. static unsigned int get_dword(int ofs)
  57. {
  58. return (output_buffer[ofs+3] << 24)
  59. | (output_buffer[ofs+2] << 16)
  60. | (output_buffer[ofs+1] << 8)
  61. | output_buffer[ofs+0];
  62. }
  63. static void set_res_size(int tag)
  64. {
  65. set_dword( tag, output_buffer_pos - tag - get_dword(tag) );
  66. }
  67. /*
  68. *****************************************************************************
  69. * Function : string_to_upper
  70. * Syntax : void string_to_upper(string_t *str)
  71. *****************************************************************************
  72. */
  73. static void string_to_upper(string_t *str)
  74. {
  75. int i;
  76. switch (str->type)
  77. {
  78. case str_char:
  79. for (i = 0; i < str->size; i++)
  80. if (str->str.cstr[i] >= 'a' && str->str.cstr[i] <= 'z') str->str.cstr[i] -= 32;
  81. break;
  82. case str_unicode:
  83. for (i = 0; i < str->size; i++)
  84. if (str->str.wstr[i] >= 'a' && str->str.wstr[i] <= 'z') str->str.wstr[i] -= 32;
  85. break;
  86. }
  87. }
  88. static int parse_accel_string( const string_t *key, int flags )
  89. {
  90. int keycode = 0;
  91. switch (key->type)
  92. {
  93. case str_char:
  94. if (key->str.cstr[0] == '#') return 0; /* ignore message contexts */
  95. if((flags & WRC_AF_VIRTKEY) &&
  96. !((key->str.cstr[0] >= 'A' && key->str.cstr[0] <= 'Z') ||
  97. (key->str.cstr[0] >= '0' && key->str.cstr[0] <= '9')))
  98. {
  99. print_location( &key->loc );
  100. error("VIRTKEY code is not equal to ascii value\n");
  101. }
  102. if(key->str.cstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0)
  103. {
  104. print_location( &key->loc );
  105. error("Cannot use both '^' and CONTROL modifier\n");
  106. }
  107. else if(key->str.cstr[0] == '^')
  108. {
  109. if (key->str.cstr[1] >= 'a' && key->str.cstr[1] <= 'z')
  110. keycode = key->str.cstr[1] - 'a' + 1;
  111. else if (key->str.cstr[1] >= 'A' && key->str.cstr[1] <= 'Z')
  112. keycode = key->str.cstr[1] - 'A' + 1;
  113. else
  114. {
  115. print_location( &key->loc );
  116. error("Control-code out of range\n");
  117. }
  118. }
  119. else
  120. keycode = key->str.cstr[0];
  121. break;
  122. case str_unicode:
  123. if (key->str.wstr[0] == '#') return 0; /* ignore message contexts */
  124. if((flags & WRC_AF_VIRTKEY) &&
  125. !((key->str.wstr[0] >= 'A' && key->str.wstr[0] <= 'Z') ||
  126. (key->str.wstr[0] >= '0' && key->str.wstr[0] <= '9')))
  127. {
  128. print_location( &key->loc );
  129. error("VIRTKEY code is not equal to ascii value\n");
  130. }
  131. if(key->str.wstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0)
  132. {
  133. print_location( &key->loc );
  134. error("Cannot use both '^' and CONTROL modifier\n");
  135. }
  136. else if(key->str.wstr[0] == '^')
  137. {
  138. if (key->str.wstr[1] >= 'a' && key->str.wstr[1] <= 'z')
  139. keycode = key->str.wstr[1] - 'a' + 1;
  140. else if (key->str.wstr[1] >= 'A' && key->str.wstr[1] <= 'Z')
  141. keycode = key->str.wstr[1] - 'A' + 1;
  142. else
  143. {
  144. print_location( &key->loc );
  145. error("Control-code out of range\n");
  146. }
  147. }
  148. else
  149. keycode = key->str.wstr[0];
  150. break;
  151. }
  152. return keycode;
  153. }
  154. /*
  155. *****************************************************************************
  156. * Function : put_string
  157. * Input :
  158. * str - String to put
  159. * isterm - The string is '\0' terminated (disregard the string's
  160. * size member)
  161. *****************************************************************************
  162. */
  163. static void put_string(const string_t *str, int isterm, const language_t *lang)
  164. {
  165. int cnt, codepage;
  166. if (win32)
  167. {
  168. string_t *newstr;
  169. if (lang) codepage = get_language_codepage( lang->id, lang->sub );
  170. else codepage = get_language_codepage( 0, 0 );
  171. assert( codepage != -1 );
  172. newstr = convert_string_unicode( str, codepage );
  173. if (str->type == str_char && check_valid_utf8( str, codepage ))
  174. {
  175. print_location( &str->loc );
  176. warning( "string \"%s\" seems to be UTF-8 but codepage %u is in use, maybe use --utf8?\n",
  177. str->str.cstr, codepage );
  178. }
  179. if (!isterm) put_word(newstr->size);
  180. for(cnt = 0; cnt < newstr->size; cnt++)
  181. {
  182. WCHAR c = newstr->str.wstr[cnt];
  183. if (isterm && !c) break;
  184. put_word(c);
  185. }
  186. if (isterm) put_word(0);
  187. free_string(newstr);
  188. }
  189. else
  190. {
  191. assert( str->type == str_char );
  192. if (!isterm) put_byte(str->size);
  193. for(cnt = 0; cnt < str->size; cnt++)
  194. {
  195. char c = str->str.cstr[cnt];
  196. if (isterm && !c) break;
  197. put_byte(c);
  198. }
  199. if (isterm) put_byte(0);
  200. }
  201. }
  202. /*
  203. *****************************************************************************
  204. * Function : put_name_id
  205. *****************************************************************************
  206. */
  207. static void put_name_id(name_id_t *nid, int upcase, const language_t *lang)
  208. {
  209. switch (nid->type)
  210. {
  211. case name_ord:
  212. if(win32)
  213. put_word(0xffff);
  214. else
  215. put_byte(0xff);
  216. put_word((WORD)nid->name.i_name);
  217. break;
  218. case name_str:
  219. if(upcase)
  220. string_to_upper(nid->name.s_name);
  221. put_string(nid->name.s_name, TRUE, lang);
  222. break;
  223. }
  224. }
  225. /*
  226. *****************************************************************************
  227. * Function : put_lvc
  228. *****************************************************************************
  229. */
  230. static void put_lvc(lvc_t *lvc)
  231. {
  232. if(lvc && lvc->language)
  233. put_word(MAKELANGID(lvc->language->id, lvc->language->sub));
  234. else
  235. put_word(0); /* Neutral */
  236. if(lvc && lvc->version)
  237. put_dword(*lvc->version);
  238. else
  239. put_dword(0);
  240. if(lvc && lvc->characts)
  241. put_dword(*lvc->characts);
  242. else
  243. put_dword(0);
  244. }
  245. /*
  246. *****************************************************************************
  247. * Function : put_res_header
  248. * Input :
  249. * type - Resource identifier
  250. * name - Resource's name
  251. * memopt - Resource's memory options to write
  252. * lvc - Language, version and characteristics (win32 only)
  253. * Output : An index to the resource size field. The resource size field
  254. * contains the header size upon exit.
  255. *****************************************************************************
  256. */
  257. static int put_res_header(int type, name_id_t *name, DWORD memopt, lvc_t *lvc)
  258. {
  259. int tag = output_buffer_pos;
  260. if(win32)
  261. {
  262. put_dword(0); /* We will overwrite these later */
  263. put_dword(0);
  264. put_word(0xffff); /* ResType */
  265. put_word(type);
  266. put_name_id(name, TRUE, lvc->language); /* ResName */
  267. align_output(4);
  268. put_dword(0); /* DataVersion */
  269. put_word(memopt); /* Memory options */
  270. put_lvc(lvc); /* Language, version and characts */
  271. set_dword(tag + 0, output_buffer_pos - tag);
  272. set_dword(tag + 4, output_buffer_pos - tag); /* Set HeaderSize */
  273. }
  274. else /* win16 */
  275. {
  276. put_byte(0xff); /* ResType */
  277. put_word(type);
  278. put_name_id(name, TRUE, NULL); /* ResName */
  279. put_word(memopt); /* Memory options */
  280. tag = output_buffer_pos;
  281. put_dword(4); /* ResSize overwritten later*/
  282. }
  283. return tag;
  284. }
  285. /*
  286. *****************************************************************************
  287. * Function : accelerator2res
  288. * Input :
  289. * name - Name/ordinal of the resource
  290. * acc - The accelerator descriptor
  291. *****************************************************************************
  292. */
  293. static void accelerator2res(name_id_t *name, accelerator_t *acc)
  294. {
  295. int restag;
  296. event_t *ev;
  297. restag = put_res_header(WRC_RT_ACCELERATOR, name, acc->memopt, &acc->lvc);
  298. if(win32)
  299. {
  300. for (ev = acc->events; ev; ev = ev->next)
  301. {
  302. int key = ev->key;
  303. if (ev->str) key = parse_accel_string( ev->str, ev->flags );
  304. put_word(ev->flags | (ev->next ? 0 : 0x80));
  305. put_word(key);
  306. put_word(ev->id);
  307. align_output(4);
  308. }
  309. }
  310. else /* win16 */
  311. {
  312. for (ev = acc->events; ev; ev = ev->next)
  313. {
  314. int key = ev->key;
  315. if (ev->str) key = parse_accel_string( ev->str, ev->flags );
  316. put_byte(ev->flags | (ev->next ? 0 : 0x80));
  317. put_word(key);
  318. put_word(ev->id);
  319. }
  320. }
  321. set_res_size(restag);
  322. }
  323. /*
  324. *****************************************************************************
  325. * Function : dialog2res
  326. * Input :
  327. * name - Name/ordinal of the resource
  328. * dlg - The dialog descriptor
  329. *****************************************************************************
  330. */
  331. static void dialog2res(name_id_t *name, dialog_t *dlg)
  332. {
  333. int restag;
  334. control_t *ctrl;
  335. int nctrl;
  336. restag = put_res_header(WRC_RT_DIALOG, name, dlg->memopt, &dlg->lvc);
  337. for (ctrl = dlg->controls, nctrl = 0; ctrl; ctrl = ctrl->next) nctrl++;
  338. if(win32)
  339. {
  340. if (dlg->is_ex)
  341. {
  342. /* FIXME: MS doc says that the first word must contain 0xffff
  343. * and the second 0x0001 to signal a DLGTEMPLATEEX. Borland's
  344. * compiler reverses the two words.
  345. * I don't know which one to choose, but I write it as Mr. B
  346. * writes it.
  347. */
  348. put_word(1); /* Signature */
  349. put_word(0xffff); /* DlgVer */
  350. put_dword(dlg->gothelpid ? dlg->helpid : 0);
  351. put_dword(dlg->gotexstyle ? dlg->exstyle->or_mask : 0);
  352. put_dword(dlg->gotstyle ? dlg->style->or_mask : WS_POPUPWINDOW);
  353. }
  354. else
  355. {
  356. put_dword(dlg->style->or_mask);
  357. put_dword(dlg->gotexstyle ? dlg->exstyle->or_mask : 0);
  358. }
  359. put_word(nctrl);
  360. put_word(dlg->x);
  361. put_word(dlg->y);
  362. put_word(dlg->width);
  363. put_word(dlg->height);
  364. if(dlg->menu)
  365. put_name_id(dlg->menu, FALSE, dlg->lvc.language);
  366. else
  367. put_word(0);
  368. if(dlg->dlgclass)
  369. put_name_id(dlg->dlgclass, FALSE, dlg->lvc.language);
  370. else
  371. put_word(0);
  372. if(dlg->title)
  373. put_string(dlg->title, TRUE, dlg->lvc.language);
  374. else
  375. put_word(0);
  376. if(dlg->font)
  377. {
  378. put_word(dlg->font->size);
  379. if (dlg->is_ex)
  380. {
  381. put_word(dlg->font->weight);
  382. /* FIXME: ? TRUE should be sufficient to say that it's
  383. * italic, but Borland's compiler says it's 0x0101.
  384. * I just copy it here, and hope for the best.
  385. */
  386. put_word(dlg->font->italic ? 0x0101 : 0);
  387. }
  388. put_string(dlg->font->name, TRUE, dlg->lvc.language);
  389. }
  390. else if (dlg->style->or_mask & DS_SETFONT) put_word( 0x7fff );
  391. align_output(4);
  392. for (ctrl = dlg->controls; ctrl; ctrl = ctrl->next)
  393. {
  394. if (dlg->is_ex)
  395. {
  396. put_dword(ctrl->gothelpid ? ctrl->helpid : 0);
  397. put_dword(ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0);
  398. /* FIXME: what is default control style? */
  399. put_dword(ctrl->gotstyle ? ctrl->style->or_mask : WS_CHILD | WS_VISIBLE);
  400. }
  401. else
  402. {
  403. /* FIXME: what is default control style? */
  404. put_dword(ctrl->gotstyle ? ctrl->style->or_mask: WS_CHILD);
  405. put_dword(ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0);
  406. }
  407. put_word(ctrl->x);
  408. put_word(ctrl->y);
  409. put_word(ctrl->width);
  410. put_word(ctrl->height);
  411. if (dlg->is_ex)
  412. put_dword(ctrl->id);
  413. else
  414. put_word(ctrl->id);
  415. put_name_id(ctrl->ctlclass, FALSE, dlg->lvc.language);
  416. if(ctrl->title)
  417. put_name_id(ctrl->title, FALSE, dlg->lvc.language);
  418. else
  419. put_word(0);
  420. if(ctrl->extra)
  421. {
  422. put_word(ctrl->extra->size);
  423. put_data(ctrl->extra->data, ctrl->extra->size);
  424. }
  425. else
  426. put_word(0);
  427. if(ctrl->next)
  428. align_output(4);
  429. }
  430. }
  431. else /* win16 */
  432. {
  433. restag = put_res_header(WRC_RT_DIALOG, name, dlg->memopt, NULL);
  434. put_dword(dlg->gotstyle ? dlg->style->or_mask : WS_POPUPWINDOW);
  435. put_byte(nctrl);
  436. put_word(dlg->x);
  437. put_word(dlg->y);
  438. put_word(dlg->width);
  439. put_word(dlg->height);
  440. if(dlg->menu)
  441. put_name_id(dlg->menu, TRUE, NULL);
  442. else
  443. put_byte(0);
  444. if(dlg->dlgclass)
  445. put_name_id(dlg->dlgclass, TRUE, NULL);
  446. else
  447. put_byte(0);
  448. if(dlg->title)
  449. put_string(dlg->title, TRUE, NULL);
  450. else
  451. put_byte(0);
  452. if(dlg->font)
  453. {
  454. put_word(dlg->font->size);
  455. put_string(dlg->font->name, TRUE, NULL);
  456. }
  457. for (ctrl = dlg->controls; ctrl; ctrl = ctrl->next)
  458. {
  459. put_word(ctrl->x);
  460. put_word(ctrl->y);
  461. put_word(ctrl->width);
  462. put_word(ctrl->height);
  463. put_word(ctrl->id);
  464. put_dword(ctrl->gotstyle ? ctrl->style->or_mask: WS_CHILD);
  465. if(ctrl->ctlclass->type == name_ord
  466. && ctrl->ctlclass->name.i_name >= 0x80
  467. && ctrl->ctlclass->name.i_name <= 0x85)
  468. put_byte(ctrl->ctlclass->name.i_name);
  469. else if(ctrl->ctlclass->type == name_str)
  470. put_name_id(ctrl->ctlclass, FALSE, NULL);
  471. else
  472. error("Unknown control-class %04x\n", ctrl->ctlclass->name.i_name);
  473. if(ctrl->title)
  474. put_name_id(ctrl->title, FALSE, NULL);
  475. else
  476. put_byte(0);
  477. /* FIXME: What is this extra byte doing here? */
  478. put_byte(0);
  479. }
  480. }
  481. set_res_size(restag);
  482. }
  483. /*
  484. *****************************************************************************
  485. * Function : menuitem2res
  486. * Remarks : Self recursive
  487. *****************************************************************************
  488. */
  489. static void menuitem2res(menu_item_t *menitem, const language_t *lang)
  490. {
  491. menu_item_t *itm = menitem;
  492. while(itm)
  493. {
  494. put_word(itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0));
  495. if(!itm->popup)
  496. put_word(itm->id);
  497. if(itm->name)
  498. put_string(itm->name, TRUE, lang);
  499. else
  500. {
  501. if (win32) put_word(0);
  502. else put_byte(0);
  503. }
  504. if(itm->popup)
  505. menuitem2res(itm->popup, lang);
  506. itm = itm->next;
  507. }
  508. }
  509. /*
  510. *****************************************************************************
  511. * Function : menuexitem2res
  512. * Remarks : Self recursive
  513. *****************************************************************************
  514. */
  515. static void menuexitem2res(menu_item_t *menitem, const language_t *lang)
  516. {
  517. menu_item_t *itm = menitem;
  518. assert(win32 != 0);
  519. while(itm)
  520. {
  521. put_dword(itm->gottype ? itm->type : 0);
  522. put_dword(itm->gotstate ? itm->state : 0);
  523. put_dword(itm->gotid ? itm->id : 0);
  524. put_word((itm->popup ? 0x01 : 0) | (!itm->next ? MF_END : 0));
  525. if(itm->name)
  526. put_string(itm->name, TRUE, lang);
  527. else
  528. put_word(0);
  529. align_output(4);
  530. if(itm->popup)
  531. {
  532. put_dword(itm->gothelpid ? itm->helpid : 0);
  533. menuexitem2res(itm->popup, lang);
  534. }
  535. itm = itm->next;
  536. }
  537. }
  538. /*
  539. *****************************************************************************
  540. * Function : menu2res
  541. * Input :
  542. * name - Name/ordinal of the resource
  543. * menex - The menuex descriptor
  544. *****************************************************************************
  545. */
  546. static void menu2res(name_id_t *name, menu_t *men)
  547. {
  548. int restag;
  549. assert(name != NULL);
  550. assert(men != NULL);
  551. restag = put_res_header(WRC_RT_MENU, name, men->memopt, &men->lvc);
  552. if(win32)
  553. {
  554. if (men->is_ex)
  555. {
  556. put_word(1); /* Menuheader: Version */
  557. put_word(4); /* Offset */
  558. put_dword(0); /* HelpId */
  559. align_output(4);
  560. menuexitem2res(men->items, men->lvc.language);
  561. }
  562. else
  563. {
  564. put_dword(0); /* Menuheader: Version and HeaderSize */
  565. menuitem2res(men->items, men->lvc.language);
  566. }
  567. }
  568. else /* win16 */
  569. {
  570. put_dword(0); /* Menuheader: Version and HeaderSize */
  571. menuitem2res(men->items, NULL);
  572. }
  573. set_res_size(restag);
  574. }
  575. /*
  576. *****************************************************************************
  577. * Function : cursorgroup2res
  578. * Input :
  579. * name - Name/ordinal of the resource
  580. * curg - The cursor descriptor
  581. *****************************************************************************
  582. */
  583. static void cursorgroup2res(name_id_t *name, cursor_group_t *curg)
  584. {
  585. int restag;
  586. cursor_t *cur;
  587. restag = put_res_header(WRC_RT_GROUP_CURSOR, name, curg->memopt, &curg->lvc);
  588. put_word(0); /* Reserved */
  589. /* FIXME: The ResType in the NEWHEADER structure should
  590. * contain 14 according to the MS win32 doc. This is
  591. * not the case with the BRC compiler and I really doubt
  592. * the latter. Putting one here is compliant to win16 spec,
  593. * but who knows the true value?
  594. */
  595. put_word(2); /* ResType */
  596. put_word(curg->ncursor);
  597. #if 0
  598. for(cur = curg->cursorlist; cur; cur = cur->next)
  599. #else
  600. cur = curg->cursorlist;
  601. while(cur->next)
  602. cur = cur->next;
  603. for(; cur; cur = cur->prev)
  604. #endif
  605. {
  606. put_word(cur->width);
  607. /* FIXME: The height of a cursor is half the size of
  608. * the bitmap's height. BRC puts the height from the
  609. * BITMAPINFOHEADER here instead of the cursorfile's
  610. * height. MS doesn't seem to care...
  611. */
  612. put_word(cur->height);
  613. /* FIXME: The next two are reversed in BRC and I don't
  614. * know why. Probably a bug. But, we can safely ignore
  615. * it because win16 does not support color cursors.
  616. * A warning should have been generated by the parser.
  617. */
  618. put_word(cur->planes);
  619. put_word(cur->bits);
  620. /* FIXME: The +4 is the hotspot in the cursor resource.
  621. * However, I could not find this in the documentation.
  622. * The hotspot bytes must either be included or MS
  623. * doesn't care.
  624. */
  625. put_dword(cur->data->size +4);
  626. put_word(cur->id);
  627. }
  628. set_res_size(restag);
  629. }
  630. /*
  631. *****************************************************************************
  632. * Function : cursor2res
  633. * Input :
  634. * cur - The cursor descriptor
  635. *****************************************************************************
  636. */
  637. static void cursor2res(cursor_t *cur)
  638. {
  639. int restag;
  640. name_id_t name;
  641. name.type = name_ord;
  642. name.name.i_name = cur->id;
  643. restag = put_res_header(WRC_RT_CURSOR, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &cur->lvc);
  644. put_word(cur->xhot);
  645. put_word(cur->yhot);
  646. put_data(cur->data->data, cur->data->size);
  647. set_res_size(restag);
  648. }
  649. /*
  650. *****************************************************************************
  651. * Function : icongroup2res
  652. * Input :
  653. * name - Name/ordinal of the resource
  654. * icog - The icon group descriptor
  655. *****************************************************************************
  656. */
  657. static void icongroup2res(name_id_t *name, icon_group_t *icog)
  658. {
  659. int restag;
  660. icon_t *ico;
  661. restag = put_res_header(WRC_RT_GROUP_ICON, name, icog->memopt, &icog->lvc);
  662. put_word(0); /* Reserved */
  663. /* FIXME: The ResType in the NEWHEADER structure should
  664. * contain 14 according to the MS win32 doc. This is
  665. * not the case with the BRC compiler and I really doubt
  666. * the latter. Putting one here is compliant to win16 spec,
  667. * but who knows the true value?
  668. */
  669. put_word(1); /* ResType */
  670. put_word(icog->nicon);
  671. for(ico = icog->iconlist; ico; ico = ico->next)
  672. {
  673. put_byte(ico->width);
  674. put_byte(ico->height);
  675. put_byte(ico->nclr);
  676. put_byte(0); /* Reserved */
  677. put_word(ico->planes);
  678. put_word(ico->bits);
  679. put_dword(ico->data->size);
  680. put_word(ico->id);
  681. }
  682. set_res_size(restag);
  683. }
  684. /*
  685. *****************************************************************************
  686. * Function : icon2res
  687. * Input :
  688. * ico - The icon descriptor
  689. *****************************************************************************
  690. */
  691. static void icon2res(icon_t *ico)
  692. {
  693. int restag;
  694. name_id_t name;
  695. name.type = name_ord;
  696. name.name.i_name = ico->id;
  697. restag = put_res_header(WRC_RT_ICON, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &ico->lvc);
  698. put_data(ico->data->data, ico->data->size);
  699. set_res_size(restag);
  700. }
  701. /*
  702. *****************************************************************************
  703. * Function : anicurico2res
  704. * Input :
  705. * name - Name/ordinal of the resource
  706. * ani - The animated object descriptor
  707. * Remarks : There are rumors that win311 could handle animated stuff.
  708. * That is why they are generated for both win16 and win32
  709. * compile.
  710. *****************************************************************************
  711. */
  712. static void anicur2res(name_id_t *name, ani_curico_t *ani)
  713. {
  714. int restag = put_res_header(WRC_RT_ANICURSOR, name, ani->memopt, NULL);
  715. put_data(ani->data->data, ani->data->size);
  716. set_res_size(restag);
  717. }
  718. static void aniico2res(name_id_t *name, ani_curico_t *ani)
  719. {
  720. int restag = put_res_header(WRC_RT_ANIICON, name, ani->memopt, NULL);
  721. put_data(ani->data->data, ani->data->size);
  722. set_res_size(restag);
  723. }
  724. /*
  725. *****************************************************************************
  726. * Function : bitmap2res
  727. * Input :
  728. * name - Name/ordinal of the resource
  729. * bmp - The bitmap descriptor
  730. *****************************************************************************
  731. */
  732. static void bitmap2res(name_id_t *name, bitmap_t *bmp)
  733. {
  734. int restag = put_res_header(WRC_RT_BITMAP, name, bmp->memopt, &bmp->data->lvc);
  735. if(bmp->data->data[0] == 'B'
  736. && bmp->data->data[1] == 'M'
  737. && ((BITMAPFILEHEADER *)bmp->data->data)->bfSize == bmp->data->size
  738. && bmp->data->size >= sizeof(BITMAPFILEHEADER))
  739. {
  740. /* The File header is still attached, don't write it */
  741. put_data((BITMAPFILEHEADER *)bmp->data->data + 1, bmp->data->size - sizeof(BITMAPFILEHEADER));
  742. }
  743. else
  744. {
  745. put_data(bmp->data->data, bmp->data->size);
  746. }
  747. set_res_size(restag);
  748. }
  749. /*
  750. *****************************************************************************
  751. * Function : font2res
  752. * Input :
  753. * name - Name/ordinal of the resource
  754. * fnt - The font descriptor
  755. * Remarks : The data has been prepared just after parsing.
  756. *****************************************************************************
  757. */
  758. static void font2res(name_id_t *name, font_t *fnt)
  759. {
  760. int restag = put_res_header(WRC_RT_FONT, name, fnt->memopt, &fnt->data->lvc);
  761. put_data(fnt->data->data, fnt->data->size);
  762. set_res_size(restag);
  763. }
  764. /*
  765. *****************************************************************************
  766. * Function : fontdir2res
  767. * Input :
  768. * name - Name/ordinal of the resource
  769. * fntdir - The fontdir descriptor
  770. * Remarks : The data has been prepared just after parsing.
  771. *****************************************************************************
  772. */
  773. static void fontdir2res(name_id_t *name, fontdir_t *fnd)
  774. {
  775. int restag = put_res_header(WRC_RT_FONTDIR, name, fnd->memopt, &fnd->data->lvc);
  776. put_data(fnd->data->data, fnd->data->size);
  777. set_res_size(restag);
  778. }
  779. /*
  780. *****************************************************************************
  781. * Function : html2res
  782. * Input :
  783. * name - Name/ordinal of the resource
  784. * rdt - The html descriptor
  785. *****************************************************************************
  786. */
  787. static void html2res(name_id_t *name, html_t *html)
  788. {
  789. int restag = put_res_header(WRC_RT_HTML, name, html->memopt, &html->data->lvc);
  790. put_data(html->data->data, html->data->size);
  791. set_res_size(restag);
  792. }
  793. /*
  794. *****************************************************************************
  795. * Function : rcdata2res
  796. * Input :
  797. * name - Name/ordinal of the resource
  798. * rdt - The rcdata descriptor
  799. *****************************************************************************
  800. */
  801. static void rcdata2res(name_id_t *name, rcdata_t *rdt)
  802. {
  803. int restag = put_res_header(WRC_RT_RCDATA, name, rdt->memopt, &rdt->data->lvc);
  804. put_data(rdt->data->data, rdt->data->size);
  805. set_res_size(restag);
  806. }
  807. /*
  808. *****************************************************************************
  809. * Function : messagetable2res
  810. * Input :
  811. * name - Name/ordinal of the resource
  812. * msg - The messagetable descriptor
  813. *****************************************************************************
  814. */
  815. static void messagetable2res(name_id_t *name, messagetable_t *msg)
  816. {
  817. int restag = put_res_header(WRC_RT_MESSAGETABLE, name, msg->memopt, &msg->data->lvc);
  818. put_data(msg->data->data, msg->data->size);
  819. set_res_size(restag);
  820. }
  821. /*
  822. *****************************************************************************
  823. * Function : stringtable2res
  824. * Input :
  825. * stt - The stringtable descriptor
  826. *****************************************************************************
  827. */
  828. static void stringtable2res(stringtable_t *stt)
  829. {
  830. name_id_t name;
  831. int i;
  832. int restag;
  833. for(; stt; stt = stt->next)
  834. {
  835. if(!stt->nentries)
  836. {
  837. warning("Empty internal stringtable\n");
  838. continue;
  839. }
  840. name.type = name_ord;
  841. name.name.i_name = (stt->idbase >> 4) + 1;
  842. restag = put_res_header(WRC_RT_STRING, &name, stt->memopt, &stt->lvc);
  843. for(i = 0; i < stt->nentries; i++)
  844. {
  845. if(stt->entries[i].str && stt->entries[i].str->size)
  846. {
  847. put_string(stt->entries[i].str, FALSE, stt->lvc.language);
  848. }
  849. else
  850. {
  851. if (win32)
  852. put_word(0);
  853. else
  854. put_byte(0);
  855. }
  856. }
  857. set_res_size(restag);
  858. }
  859. }
  860. /*
  861. *****************************************************************************
  862. * Function : user2res
  863. * Input :
  864. * name - Name/ordinal of the resource
  865. * usr - The userresource descriptor
  866. *****************************************************************************
  867. */
  868. static void user2res(name_id_t *name, user_t *usr)
  869. {
  870. int tag = output_buffer_pos;
  871. if(win32)
  872. {
  873. put_dword(0); /* We will overwrite these later */
  874. put_dword(0);
  875. put_name_id(usr->type, TRUE, usr->data->lvc.language);
  876. put_name_id(name, TRUE, usr->data->lvc.language); /* ResName */
  877. align_output(4);
  878. put_dword(0); /* DataVersion */
  879. put_word(usr->memopt); /* Memory options */
  880. put_lvc(&usr->data->lvc); /* Language, version and characts */
  881. set_dword(tag + 0, output_buffer_pos - tag);
  882. set_dword(tag + 4, output_buffer_pos - tag); /* Set HeaderSize */
  883. }
  884. else /* win16 */
  885. {
  886. put_name_id(usr->type, TRUE, NULL);
  887. put_name_id(name, TRUE, NULL); /* ResName */
  888. put_word(usr->memopt); /* Memory options */
  889. tag = output_buffer_pos;
  890. put_dword(4); /* ResSize overwritten later*/
  891. }
  892. put_data(usr->data->data, usr->data->size);
  893. set_res_size(tag);
  894. }
  895. /*
  896. *****************************************************************************
  897. * Function : versionblock2res
  898. * Input :
  899. * blk - The version block to be written
  900. * Remarks : Self recursive
  901. *****************************************************************************
  902. */
  903. static void versionblock2res(ver_block_t *blk, int level, const language_t *lang)
  904. {
  905. ver_value_t *val;
  906. int blksizetag;
  907. int valblksizetag;
  908. int valvalsizetag;
  909. int tag;
  910. int i;
  911. blksizetag = output_buffer_pos;
  912. put_word(0); /* Will be overwritten later */
  913. put_word(0);
  914. if(win32)
  915. put_word(0); /* level ? */
  916. put_string(blk->name, TRUE, NULL);
  917. align_output(4);
  918. for(val = blk->values; val; val = val->next)
  919. {
  920. switch(val->type)
  921. {
  922. case val_str:
  923. valblksizetag = output_buffer_pos;
  924. put_word(0); /* Will be overwritten later */
  925. valvalsizetag = output_buffer_pos;
  926. put_word(0); /* Will be overwritten later */
  927. if(win32)
  928. {
  929. put_word(level);
  930. }
  931. put_string(val->key, TRUE, NULL);
  932. align_output(4);
  933. tag = output_buffer_pos;
  934. put_string(val->value.str, TRUE, lang);
  935. if(win32)
  936. set_word(valvalsizetag, (output_buffer_pos - tag) >> 1);
  937. else
  938. set_word(valvalsizetag, output_buffer_pos - tag);
  939. set_word(valblksizetag, output_buffer_pos - valblksizetag);
  940. align_output(4);
  941. break;
  942. case val_words:
  943. valblksizetag = output_buffer_pos;
  944. put_word(0); /* Will be overwritten later */
  945. valvalsizetag = output_buffer_pos;
  946. put_word(0); /* Will be overwritten later */
  947. if(win32)
  948. {
  949. put_word(level);
  950. }
  951. put_string(val->key, TRUE, NULL);
  952. align_output(4);
  953. tag = output_buffer_pos;
  954. for(i = 0; i < val->value.words->nwords; i++)
  955. {
  956. put_word(val->value.words->words[i]);
  957. }
  958. set_word(valvalsizetag, output_buffer_pos - tag);
  959. set_word(valblksizetag, output_buffer_pos - valblksizetag);
  960. align_output(4);
  961. break;
  962. case val_block:
  963. versionblock2res(val->value.block, level+1, lang);
  964. break;
  965. }
  966. }
  967. /* Set blocksize */
  968. set_word(blksizetag, output_buffer_pos - blksizetag);
  969. }
  970. /*
  971. *****************************************************************************
  972. * Function : versioninfo2res
  973. * Input :
  974. * name - Name/ordinal of the resource
  975. * ver - The versioninfo descriptor
  976. *****************************************************************************
  977. */
  978. static void versioninfo2res(name_id_t *name, versioninfo_t *ver)
  979. {
  980. static const char info[] = "VS_VERSION_INFO";
  981. unsigned int i;
  982. int restag, rootblocksizetag, valsizetag, tag;
  983. ver_block_t *blk;
  984. restag = put_res_header(WRC_RT_VERSION, name, ver->memopt, &ver->lvc);
  985. rootblocksizetag = output_buffer_pos;
  986. put_word(0); /* BlockSize filled in later */
  987. valsizetag = output_buffer_pos;
  988. put_word(0); /* ValueSize filled in later*/
  989. if(win32)
  990. {
  991. put_word(0); /* Tree-level ? */
  992. for (i = 0; i < sizeof(info); i++) put_word(info[i]);
  993. align_output(4);
  994. }
  995. else
  996. {
  997. for (i = 0; i < sizeof(info); i++) put_byte(info[i]);
  998. }
  999. tag = output_buffer_pos;
  1000. put_dword(VS_FFI_SIGNATURE);
  1001. put_dword(VS_FFI_STRUCVERSION);
  1002. put_dword((ver->filever_maj1 << 16) + (ver->filever_maj2 & 0xffff));
  1003. put_dword((ver->filever_min1 << 16) + (ver->filever_min2 & 0xffff));
  1004. put_dword((ver->prodver_maj1 << 16) + (ver->prodver_maj2 & 0xffff));
  1005. put_dword((ver->prodver_min1 << 16) + (ver->prodver_min2 & 0xffff));
  1006. put_dword(ver->fileflagsmask);
  1007. put_dword(ver->fileflags);
  1008. put_dword(ver->fileos);
  1009. put_dword(ver->filetype);
  1010. put_dword(ver->filesubtype);
  1011. put_dword(0); /* FileDateMS */
  1012. put_dword(0); /* FileDateLS */
  1013. /* Set ValueSize */
  1014. set_word(valsizetag, output_buffer_pos - tag);
  1015. /* Descend into the blocks */
  1016. for(blk = ver->blocks; blk; blk = blk->next)
  1017. versionblock2res(blk, 0, win32 ? ver->lvc.language : NULL);
  1018. /* Set root block's size */
  1019. set_word(rootblocksizetag, output_buffer_pos - rootblocksizetag);
  1020. set_res_size(restag);
  1021. }
  1022. /*
  1023. *****************************************************************************
  1024. * Function : toolbar2res
  1025. * Input :
  1026. * name - Name/ordinal of the resource
  1027. * toolbar - The toolbar descriptor
  1028. *****************************************************************************
  1029. */
  1030. static void toolbar2res(name_id_t *name, toolbar_t *toolbar)
  1031. {
  1032. toolbar_item_t *itm;
  1033. int restag;
  1034. if (!win32) return;
  1035. restag = put_res_header(WRC_RT_TOOLBAR, name, toolbar->memopt, &toolbar->lvc);
  1036. put_word(1); /* Menuheader: Version */
  1037. put_word(toolbar->button_width); /* (in pixels?) */
  1038. put_word(toolbar->button_height); /* (in pixels?) */
  1039. put_word(toolbar->nitems);
  1040. align_output(4);
  1041. for (itm = toolbar->items; itm; itm = itm->next) put_word(itm->id);
  1042. set_res_size(restag);
  1043. }
  1044. /*
  1045. *****************************************************************************
  1046. * Function : dlginit2res
  1047. * Input :
  1048. * name - Name/ordinal of the resource
  1049. * rdt - The dlginit descriptor
  1050. *****************************************************************************
  1051. */
  1052. static void dlginit2res(name_id_t *name, dlginit_t *dit)
  1053. {
  1054. int restag = put_res_header(WRC_RT_DLGINIT, name, dit->memopt, &dit->data->lvc);
  1055. put_data(dit->data->data, dit->data->size);
  1056. set_res_size(restag);
  1057. }
  1058. /*
  1059. *****************************************************************************
  1060. * Function : write_resfile
  1061. * Syntax : void write_resfile(char *outname, resource_t *top)
  1062. * Input :
  1063. * outname - Filename to write to
  1064. * top - The resource-tree to convert
  1065. *****************************************************************************
  1066. */
  1067. void write_resfile(char *outname, resource_t *top)
  1068. {
  1069. init_output_buffer();
  1070. if(win32)
  1071. {
  1072. /* Put an empty resource first to signal win32 format */
  1073. put_dword(0); /* ResSize */
  1074. put_dword(0x00000020); /* HeaderSize */
  1075. put_word(0xffff); /* ResType */
  1076. put_word(0);
  1077. put_word(0xffff); /* ResName */
  1078. put_word(0);
  1079. put_dword(0); /* DataVersion */
  1080. put_word(0); /* Memory options */
  1081. put_word(0); /* Language */
  1082. put_dword(0); /* Version */
  1083. put_dword(0); /* Characteristics */
  1084. }
  1085. for ( ; top; top = top->next)
  1086. {
  1087. switch(top->type)
  1088. {
  1089. case res_acc: accelerator2res(top->name, top->res.acc); break;
  1090. case res_bmp: bitmap2res(top->name, top->res.bmp); break;
  1091. case res_cur: cursor2res(top->res.cur); break;
  1092. case res_curg: cursorgroup2res(top->name, top->res.curg); break;
  1093. case res_dlg: dialog2res(top->name, top->res.dlg); break;
  1094. case res_fnt: font2res(top->name, top->res.fnt); break;
  1095. case res_fntdir: fontdir2res(top->name, top->res.fnd); break;
  1096. case res_ico: icon2res(top->res.ico); break;
  1097. case res_icog: icongroup2res(top->name, top->res.icog); break;
  1098. case res_men: menu2res(top->name, top->res.men); break;
  1099. case res_html: html2res(top->name, top->res.html); break;
  1100. case res_rdt: rcdata2res(top->name, top->res.rdt); break;
  1101. case res_stt: stringtable2res(top->res.stt); break;
  1102. case res_usr: user2res(top->name, top->res.usr); break;
  1103. case res_msg: messagetable2res(top->name, top->res.msg); break;
  1104. case res_ver: versioninfo2res(top->name, top->res.ver); break;
  1105. case res_toolbar: toolbar2res(top->name, top->res.tbt); break;
  1106. case res_dlginit: dlginit2res(top->name, top->res.dlgi); break;
  1107. case res_anicur: anicur2res(top->name, top->res.ani); break;
  1108. case res_aniico: aniico2res(top->name, top->res.ani); break;
  1109. default: assert(0);
  1110. }
  1111. if (win32) align_output( 4 );
  1112. }
  1113. flush_output_buffer( outname );
  1114. }