2 * Generate .res format from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
6 * 25-May-1998 BS - Added simple unicode -> char conversion for resource
7 * names in .s and .h files.
21 #define SetResSize(res, tag) *(DWORD *)&((res)->data[(tag)]) = \
22 (res)->size - *(DWORD *)&((res)->data[(tag)])
27 r = (res_t *)xmalloc(sizeof(res_t));
28 r->allocsize = RES_BLOCKSIZE;
30 r->data = (char *)xmalloc(RES_BLOCKSIZE);
34 res_t *grow_res(res_t *r, int add)
37 r->data = (char *)xrealloc(r->data, r->allocsize);
42 *****************************************************************************
46 * Syntax : void put_byte(res_t *res, unsigned c)
47 * void put_word(res_t *res, unsigned w)
48 * void put_dword(res_t *res, unsigned d)
50 * res - Binary resource to put the data in
51 * c, w, d - Data to put
53 * Description : Put primitives that put an item in the binary resource.
54 * The data array grows automatically.
56 *****************************************************************************
58 void put_byte(res_t *res, unsigned c)
60 if(res->allocsize - res->size < sizeof(char))
61 grow_res(res, RES_BLOCKSIZE);
62 *(char *)&(res->data[res->size]) = (char)c;
63 res->size += sizeof(char);
66 void put_word(res_t *res, unsigned w)
68 if(res->allocsize - res->size < sizeof(WORD))
69 grow_res(res, RES_BLOCKSIZE);
70 *(WORD *)&(res->data[res->size]) = (WORD)w;
71 res->size += sizeof(WORD);
74 void put_dword(res_t *res, unsigned d)
76 if(res->allocsize - res->size < sizeof(DWORD))
77 grow_res(res, RES_BLOCKSIZE);
78 *(DWORD *)&(res->data[res->size]) = (DWORD)d;
79 res->size += sizeof(DWORD);
82 void put_pad(res_t *res)
84 while(res->size & 0x3)
89 *****************************************************************************
90 * Function : string_to_upper
91 * Syntax : void string_to_upper(string_t *str)
95 * Remarks : FIXME: codepages...
96 *****************************************************************************
98 void string_to_upper(string_t *str)
100 if(str->type == str_char)
102 char *cptr = str->str.cstr;
104 *cptr = (char)toupper(*cptr);
106 else if(str->type == str_unicode)
108 short *sptr = str->str.wstr;
111 *sptr = (short)toupper(*sptr);
115 internal_error(__FILE__, __LINE__, "Invalid string type %d", str->type);
120 *****************************************************************************
121 * Function : put_string
122 * Syntax : void put_string(res_t *res, string_t *str, enum str_e type,
125 * res - Binary resource to put the data in
126 * str - String to put
127 * type - Data has to be written in either str_char or str_unicode
128 * isterm - The string is '\0' terminated (disregard the string's
133 *****************************************************************************
135 void put_string(res_t *res, string_t *str, enum str_e type, int isterm)
141 if(!isterm && str->size == 0)
143 warning("String length is zero, not written");
147 if(str->type == str_unicode && type == str_unicode)
149 for(cnt = 0; cnt < str->size; cnt++)
151 c = str->str.wstr[cnt];
156 if(isterm && (str->size == 0 || (cnt == str->size && c)))
159 else if(str->type == str_char && type == str_char)
161 for(cnt = 0; cnt < str->size; cnt++)
163 c = str->str.cstr[cnt];
168 if(isterm && (str->size == 0 || (cnt == str->size && c)))
171 else if(str->type == str_unicode && type == str_char)
173 for(cnt = 0; cnt < str->size; cnt++)
175 c = str->str.wstr[cnt];
180 if(isterm && (str->size == 0 || (cnt == str->size && c)))
183 else /* str->type == str_char && type == str_unicode */
185 for(cnt = 0; cnt < str->size; cnt++)
187 c = str->str.cstr[cnt];
188 put_word(res, c & 0xff);
192 if(isterm && (str->size == 0 || (cnt == str->size && c)))
198 *****************************************************************************
199 * Function : put_name_id
200 * Syntax : void put_name_id(res_t *res, name_id_t *nid, int upcase)
205 *****************************************************************************
207 void put_name_id(res_t *res, name_id_t *nid, int upcase)
209 if(nid->type == name_ord)
212 put_word(res, 0xffff);
215 put_word(res, (WORD)nid->name.i_name);
217 else if(nid->type == name_str)
220 string_to_upper(nid->name.s_name);
221 put_string(res, nid->name.s_name, win32 ? str_unicode : str_char, TRUE);
225 internal_error(__FILE__, __LINE__, "Invalid name_id type %d", nid->type);
230 *****************************************************************************
232 * Syntax : void put_lvc(res_t *res, lvc_t *lvc)
237 *****************************************************************************
239 void put_lvc(res_t *res, lvc_t *lvc)
241 if(lvc && lvc->language)
242 put_word(res, MAKELANGID(lvc->language->id, lvc->language->sub));
244 put_word(res, 0); /* Neutral */
245 if(lvc && lvc->version)
246 put_dword(res, *(lvc->version));
249 if(lvc && lvc->characts)
250 put_dword(res, *(lvc->characts));
256 *****************************************************************************
257 * Function : put_raw_data
258 * Syntax : void put_raw_data(res_t *res, raw_data_t *raw, int offset)
263 *****************************************************************************
265 void put_raw_data(res_t *res, raw_data_t *raw, int offset)
267 int wsize = raw->size - offset;
268 if(res->allocsize - res->size < wsize)
269 grow_res(res, wsize);
270 memcpy(&(res->data[res->size]), raw->data + offset, wsize);
275 *****************************************************************************
276 * Function : put_res_header
277 * Syntax : intput_res_header(res_t *res, int type, name_id_t *ntype,
278 * name_id_t *name, DWORD memopt, lvc_t *lvc)
281 * res - Binary resource descriptor to write to
282 * type - Resource identifier (if ntype == NULL)
283 * ntype - Name id of type
284 * name - Resource's name
285 * memopt - Resource's memory options to write
286 * lvc - Language, version and characteristics (win32 only)
287 * Output : An index to the resource size field. The resource size field
288 * contains the header size upon exit.
291 *****************************************************************************
293 int put_res_header(res_t *res, int type, name_id_t *ntype, name_id_t *name,
294 DWORD memopt, lvc_t *lvc)
298 put_dword(res, 0); /* We will overwrite these later */
302 put_word(res, 0xffff); /* ResType */
306 put_name_id(res, ntype, TRUE);
307 put_name_id(res, name, TRUE); /* ResName */
309 put_dword(res, 0); /* DataVersion */
310 put_word(res, memopt); /* Memory options */
311 put_lvc(res, lvc); /* Language, version and characts */
312 ((DWORD *)res->data)[0] = res->size; /* Set preliminary resource */
313 ((DWORD *)res->data)[1] = res->size; /* Set HeaderSize */
314 res->dataidx = res->size;
322 put_byte(res, 0xff); /* ResType */
326 put_name_id(res, ntype, TRUE);
327 put_name_id(res, name, TRUE); /* ResName */
328 put_word(res, memopt); /* Memory options */
330 put_dword(res, 0); /* ResSize overwritten later*/
331 *(DWORD *)&(res->data[tag]) = res->size;
332 res->dataidx = res->size;
338 *****************************************************************************
339 * Function : accelerator2res
340 * Syntax : res_t *accelerator2res(name_id_t *name, accelerator_t *acc)
342 * name - Name/ordinal of the resource
343 * acc - The accelerator descriptor
344 * Output : New .res format structure
347 *****************************************************************************
349 res_t *accelerator2res(name_id_t *name, accelerator_t *acc)
354 assert(name != NULL);
361 restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, &(acc->lvc));
364 put_word(res, ev->flags | (ev->next ? 0 : 0x80));
365 put_word(res, ev->key);
366 put_word(res, ev->id);
367 put_word(res, 0); /* Padding */
374 restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, NULL);
377 put_byte(res, ev->flags | (ev->next ? 0 : 0x80));
378 put_word(res, ev->key);
379 put_word(res, ev->id);
383 /* Set ResourceSize */
384 SetResSize(res, restag);
389 *****************************************************************************
390 * Function : dialog2res
391 * Syntax : res_t *dialog2res(name_id_t *name, dialog_t *dlg)
393 * name - Name/ordinal of the resource
394 * dlg - The dialog descriptor
395 * Output : New .res format structure
398 *****************************************************************************
400 res_t *dialog2res(name_id_t *name, dialog_t *dlg)
407 assert(name != NULL);
410 ctrl = dlg->controls;
414 restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, &(dlg->lvc));
416 put_dword(res, dlg->style);
417 put_dword(res, dlg->gotexstyle ? dlg->exstyle : 0);
418 tag_nctrl = res->size;
419 put_word(res, 0); /* Number of controls */
420 put_word(res, dlg->x);
421 put_word(res, dlg->y);
422 put_word(res, dlg->width);
423 put_word(res, dlg->height);
425 put_name_id(res, dlg->menu, TRUE);
429 put_name_id(res, dlg->dlgclass, TRUE);
433 put_string(res, dlg->title, str_unicode, TRUE);
438 put_word(res, dlg->font->size);
439 put_string(res, dlg->font->name, str_unicode, TRUE);
445 /* FIXME: what is default control style? */
446 put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD);
447 put_dword(res, ctrl->gotexstyle ? ctrl->exstyle : 0);
448 put_word(res, ctrl->x);
449 put_word(res, ctrl->y);
450 put_word(res, ctrl->width);
451 put_word(res, ctrl->height);
452 put_word(res, ctrl->id);
454 put_name_id(res, ctrl->ctlclass, TRUE);
456 internal_error(__FILE__, __LINE__, "Control has no control-class");
458 put_string(res, ctrl->title, str_unicode, TRUE);
463 put_word(res, ctrl->extra->size+2);
465 put_raw_data(res, ctrl->extra, 0);
475 /* Set number of controls */
476 *(WORD *)&((char *)res->data)[tag_nctrl] = (WORD)nctrl;
480 restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, NULL);
482 put_dword(res, dlg->gotstyle ? dlg->style : WS_POPUPWINDOW);
483 tag_nctrl = res->size;
484 put_byte(res, 0); /* Number of controls */
485 put_word(res, dlg->x);
486 put_word(res, dlg->y);
487 put_word(res, dlg->width);
488 put_word(res, dlg->height);
490 put_name_id(res, dlg->menu, TRUE);
494 put_name_id(res, dlg->dlgclass, TRUE);
498 put_string(res, dlg->title, str_char, TRUE);
503 put_word(res, dlg->font->size);
504 put_string(res, dlg->font->name, str_char, TRUE);
509 put_word(res, ctrl->x);
510 put_word(res, ctrl->y);
511 put_word(res, ctrl->width);
512 put_word(res, ctrl->height);
513 put_word(res, ctrl->id);
514 put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD);
517 if(ctrl->ctlclass->type == name_ord
518 && ctrl->ctlclass->name.i_name >= 0x80
519 && ctrl->ctlclass->name.i_name <= 0x85)
520 put_byte(res, ctrl->ctlclass->name.i_name);
521 else if(ctrl->ctlclass->type == name_str)
522 put_name_id(res, ctrl->ctlclass, FALSE);
524 error("Unknown control-class %04x", ctrl->ctlclass->name.i_name);
527 internal_error(__FILE__, __LINE__, "Control has no control-class");
529 put_string(res, ctrl->title, str_char, TRUE);
533 /* FIXME: What is this extra byte doing here? */
539 /* Set number of controls */
540 ((char *)res->data)[tag_nctrl] = (char)nctrl;
542 /* Set ResourceSize */
543 SetResSize(res, restag);
548 *****************************************************************************
549 * Function : dialogex2res
550 * Syntax : res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
552 * name - Name/ordinal of the resource
553 * dlgex - The dialogex descriptor
554 * Output : New .res format structure
557 *****************************************************************************
559 res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
566 assert(name != NULL);
567 assert(dlgex != NULL);
569 ctrl = dlgex->controls;
573 restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlgex->memopt, &(dlgex->lvc));
575 /* FIXME: MS doc says thet the first word must contain 0xffff
576 * and the second 0x0001 to signal a DLGTEMPLATEEX. Borland's
577 * compiler reverses the two words.
578 * I don't know which one to choose, but I write it as Mr. B
581 put_word(res, 1); /* Signature */
582 put_word(res, 0xffff); /* DlgVer */
583 put_dword(res, dlgex->gothelpid ? dlgex->helpid : 0);
584 put_dword(res, dlgex->gotexstyle ? dlgex->exstyle : 0);
585 put_dword(res, dlgex->gotstyle ? dlgex->style : WS_POPUPWINDOW);
586 tag_nctrl = res->size;
587 put_word(res, 0); /* Number of controls */
588 put_word(res, dlgex->x);
589 put_word(res, dlgex->y);
590 put_word(res, dlgex->width);
591 put_word(res, dlgex->height);
593 put_name_id(res, dlgex->menu, TRUE);
597 put_name_id(res, dlgex->dlgclass, TRUE);
601 put_string(res, dlgex->title, str_unicode, TRUE);
606 put_word(res, dlgex->font->size);
607 put_word(res, dlgex->font->weight);
608 /* FIXME: ? TRUE should be sufficient to say that its
609 * italic, but Borland's compiler says its 0x0101.
610 * I just copy it here, and hope for the best.
612 put_word(res, dlgex->font->italic ? 0x0101 : 0);
613 put_string(res, dlgex->font->name, str_unicode, TRUE);
619 put_dword(res, ctrl->gothelpid ? ctrl->helpid : 0);
620 put_dword(res, ctrl->gotexstyle ? ctrl->exstyle : 0);
621 /* FIXME: what is default control style? */
622 put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD | WS_VISIBLE);
623 put_word(res, ctrl->x);
624 put_word(res, ctrl->y);
625 put_word(res, ctrl->width);
626 put_word(res, ctrl->height);
627 put_word(res, ctrl->id);
628 /* FIXME: Pad is _NOT_ documented!?! */
631 put_name_id(res, ctrl->ctlclass, TRUE);
633 internal_error(__FILE__, __LINE__, "Control has no control-class");
635 put_string(res, ctrl->title, str_unicode, TRUE);
641 put_word(res, ctrl->extra->size);
642 put_raw_data(res, ctrl->extra, 0);
651 /* Set number of controls */
652 *(WORD *)&((char *)res->data)[tag_nctrl] = (WORD)nctrl;
653 /* Set ResourceSize */
654 SetResSize(res, restag);
659 /* Do not generate anything in 16-bit mode */
668 *****************************************************************************
669 * Function : menuitem2res
670 * Syntax : void menuitem2res(res_t *res, menu_item_t *item)
674 * Remarks : Self recursive
675 *****************************************************************************
677 void menuitem2res(res_t *res, menu_item_t *menitem)
679 menu_item_t *itm = menitem;
684 put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0));
686 put_word(res, itm->id);
688 put_string(res, itm->name, str_unicode, TRUE);
692 menuitem2res(res, itm->popup);
700 put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0));
702 put_word(res, itm->id);
704 put_string(res, itm->name, str_char, TRUE);
708 menuitem2res(res, itm->popup);
716 *****************************************************************************
717 * Function : menu2res
718 * Syntax : res_t *menu2res(name_id_t *name, menu_t *men)
720 * name - Name/ordinal of the resource
721 * men - The menu descriptor
722 * Output : New .res format structure
725 *****************************************************************************
727 res_t *menu2res(name_id_t *name, menu_t *men)
731 assert(name != NULL);
735 restag = put_res_header(res, WRC_RT_MENU, NULL, name, men->memopt, win32 ? &(men->lvc) : NULL);
737 put_dword(res, 0); /* Menuheader: Version and HeaderSize */
738 menuitem2res(res, men->items);
739 /* Set ResourceSize */
740 SetResSize(res, restag);
747 *****************************************************************************
748 * Function : menuexitem2res
749 * Syntax : void menuexitem2res(res_t *res, menuex_item_t *item)
753 * Remarks : Self recursive
754 *****************************************************************************
756 void menuexitem2res(res_t *res, menuex_item_t *menitem)
758 menuex_item_t *itm = menitem;
762 put_dword(res, itm->gottype ? itm->type : 0);
763 put_dword(res, itm->gotstate ? itm->state : 0);
764 put_dword(res, itm->gotid ? itm->id : 0); /* FIXME: Docu. says word */
765 put_word(res, (itm->popup ? 0x01 : 0) | (!itm->next ? MF_END : 0));
767 put_string(res, itm->name, str_unicode, TRUE);
773 put_dword(res, itm->gothelpid ? itm->helpid : 0);
774 menuexitem2res(res, itm->popup);
782 *****************************************************************************
783 * Function : menuex2res
784 * Syntax : res_t *menuex2res(name_id_t *name, menuex_t *menex)
786 * name - Name/ordinal of the resource
787 * menex - The menuex descriptor
788 * Output : New .res format structure
791 *****************************************************************************
793 res_t *menuex2res(name_id_t *name, menuex_t *menex)
797 assert(name != NULL);
798 assert(menex != NULL);
803 restag = put_res_header(res, WRC_RT_MENU, NULL, name, menex->memopt, &(menex->lvc));
805 put_word(res, 1); /* Menuheader: Version */
806 put_word(res, 4); /* Offset */
807 put_dword(res, 0); /* HelpId */
809 menuexitem2res(res, menex->items);
810 /* Set ResourceSize */
811 SetResSize(res, restag);
816 /* Do not generate anything in 16-bit mode */
825 *****************************************************************************
826 * Function : cursorgroup2res
827 * Syntax : res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg)
829 * name - Name/ordinal of the resource
830 * curg - The cursor descriptor
831 * Output : New .res format structure
834 *****************************************************************************
836 res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg)
841 assert(name != NULL);
842 assert(curg != NULL);
845 restag = put_res_header(res, WRC_RT_GROUP_CURSOR, NULL, name, curg->memopt, &(curg->lvc));
848 put_word(res, 0); /* Reserved */
849 /* FIXME: The ResType in the NEWHEADER structure should
850 * contain 14 according to the MS win32 doc. This is
851 * not the case with the BRC compiler and I really doubt
852 * the latter. Putting one here is compliant to win16 spec,
853 * but who knows the true value?
855 put_word(res, 2); /* ResType */
856 put_word(res, curg->ncursor);
858 for(cur = curg->cursorlist; cur; cur = cur->next)
860 cur = curg->cursorlist;
863 for(; cur; cur = cur->prev)
866 put_word(res, cur->width);
867 /* FIXME: The height of a cursor is half the size of
868 * the bitmap's height. BRC puts the height from the
869 * BITMAPINFOHEADER here instead of the cursorfile's
870 * height. MS doesn't seem to care...
872 put_word(res, cur->height);
873 /* FIXME: The next two are reversed in BRC and I don't
874 * know why. Probably a bug. But, we can safely ignore
875 * it because win16 does not support color cursors.
876 * A warning should have been generated by the parser.
878 put_word(res, cur->planes);
879 put_word(res, cur->bits);
880 /* FIXME: The +4 is the hotspot in the cursor resource.
881 * However, I cound not find this in the documentation.
882 * The hotspot bytes must either be included or MS
885 put_dword(res, cur->data->size +4);
886 put_word(res, cur->id);
891 put_word(res, 0); /* Reserved */
892 put_word(res, 2); /* ResType */
893 put_word(res, curg->ncursor);
895 for(cur = curg->cursorlist; cur; cur = cur->next)
897 cur = curg->cursorlist;
900 for(; cur; cur = cur->prev)
903 put_word(res, cur->width);
904 /* FIXME: The height of a cursor is half the size of
905 * the bitmap's height. BRC puts the height from the
906 * BITMAPINFOHEADER here instead of the cursorfile's
907 * height. MS doesn't seem to care...
909 put_word(res, cur->height);
910 /* FIXME: The next two are reversed in BRC and I don't
911 * know why. Probably a bug. But, we can safely ignore
912 * it because win16 does not support color cursors.
913 * A warning should have been generated by the parser.
915 put_word(res, cur->planes);
916 put_word(res, cur->bits);
917 /* FIXME: The +4 is the hotspot in the cursor resource.
918 * However, I cound not find this in the documentation.
919 * The hotspot bytes must either be included or MS
922 put_dword(res, cur->data->size +4);
923 put_word(res, cur->id);
926 SetResSize(res, restag); /* Set ResourceSize */
934 *****************************************************************************
935 * Function : cursor2res
936 * Syntax : res_t *cursor2res(cursor_t *cur)
938 * cur - The cursor descriptor
939 * Output : New .res format structure
942 *****************************************************************************
944 res_t *cursor2res(cursor_t *cur)
953 name.type = name_ord;
954 name.name.i_name = cur->id;
955 restag = put_res_header(res, WRC_RT_CURSOR, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &(cur->lvc));
956 put_word(res, cur->xhot);
957 put_word(res, cur->yhot);
958 put_raw_data(res, cur->data, 0);
960 SetResSize(res, restag); /* Set ResourceSize */
968 *****************************************************************************
969 * Function : icongroup2res
970 * Syntax : res_t *icongroup2res(name_id_t *name, icon_group_t *icog)
972 * name - Name/ordinal of the resource
973 * icog - The icon group descriptor
974 * Output : New .res format structure
977 *****************************************************************************
979 res_t *icongroup2res(name_id_t *name, icon_group_t *icog)
984 assert(name != NULL);
985 assert(icog != NULL);
988 restag = put_res_header(res, WRC_RT_GROUP_ICON, NULL, name, icog->memopt, &(icog->lvc));
991 put_word(res, 0); /* Reserved */
992 /* FIXME: The ResType in the NEWHEADER structure should
993 * contain 14 according to the MS win32 doc. This is
994 * not the case with the BRC compiler and I really doubt
995 * the latter. Putting one here is compliant to win16 spec,
996 * but who knows the true value?
998 put_word(res, 1); /* ResType */
999 put_word(res, icog->nicon);
1000 for(ico = icog->iconlist; ico; ico = ico->next)
1002 put_byte(res, ico->width);
1003 put_byte(res, ico->height);
1004 put_byte(res, ico->nclr);
1005 put_byte(res, 0); /* Reserved */
1006 put_word(res, ico->planes);
1007 put_word(res, ico->bits);
1008 put_dword(res, ico->data->size);
1009 put_word(res, ico->id);
1014 put_word(res, 0); /* Reserved */
1015 put_word(res, 1); /* ResType */
1016 put_word(res, icog->nicon);
1017 for(ico = icog->iconlist; ico; ico = ico->next)
1019 put_byte(res, ico->width);
1020 put_byte(res, ico->height);
1021 put_byte(res, ico->nclr);
1022 put_byte(res, 0); /* Reserved */
1023 put_word(res, ico->planes);
1024 put_word(res, ico->bits);
1025 put_dword(res, ico->data->size);
1026 put_word(res, ico->id);
1029 SetResSize(res, restag); /* Set ResourceSize */
1037 *****************************************************************************
1038 * Function : icon2res
1039 * Syntax : res_t *icon2res(icon_t *ico)
1041 * ico - The icon descriptor
1042 * Output : New .res format structure
1045 *****************************************************************************
1047 res_t *icon2res(icon_t *ico)
1053 assert(ico != NULL);
1056 name.type = name_ord;
1057 name.name.i_name = ico->id;
1058 restag = put_res_header(res, WRC_RT_ICON, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &(ico->lvc));
1059 put_raw_data(res, ico->data, 0);
1061 SetResSize(res, restag); /* Set ResourceSize */
1069 *****************************************************************************
1070 * Function : bitmap2res
1071 * Syntax : res_t *bitmap2res(name_id_t *name, bitmap_t *bmp)
1073 * name - Name/ordinal of the resource
1074 * bmp - The bitmap descriptor
1075 * Output : New .res format structure
1078 *****************************************************************************
1080 res_t *bitmap2res(name_id_t *name, bitmap_t *bmp)
1084 assert(name != NULL);
1085 assert(bmp != NULL);
1090 restag = put_res_header(res, WRC_RT_BITMAP, NULL, name, bmp->memopt, NULL);
1092 if(bmp->data->data[0] == 'B'
1093 && bmp->data->data[1] == 'M'
1094 && ((BITMAPFILEHEADER *)bmp->data->data)->bfSize == bmp->data->size
1095 && bmp->data->size >= sizeof(BITMAPFILEHEADER))
1097 /* The File header is still attached, don't write it */
1098 put_raw_data(res, bmp->data, sizeof(BITMAPFILEHEADER));
1102 put_raw_data(res, bmp->data, 0);
1105 /* Set ResourceSize */
1106 SetResSize(res, restag);
1115 *****************************************************************************
1116 * Function : font2res
1117 * Syntax : res_t *font2res(name_id_t *name, font_t *fnt)
1119 * name - Name/ordinal of the resource
1120 * fnt - The font descriptor
1121 * Output : New .res format structure
1124 *****************************************************************************
1126 res_t *font2res(name_id_t *name, font_t *fnt)
1128 assert(name != NULL);
1129 assert(fnt != NULL);
1130 warning("Fonts not yet implemented");
1135 *****************************************************************************
1136 * Function : rcdata2res
1137 * Syntax : res_t *rcdata2res(name_id_t *name, rcdata_t *rdt)
1139 * name - Name/ordinal of the resource
1140 * rdt - The rcdata descriptor
1141 * Output : New .res format structure
1144 *****************************************************************************
1146 res_t *rcdata2res(name_id_t *name, rcdata_t *rdt)
1150 assert(name != NULL);
1151 assert(rdt != NULL);
1154 restag = put_res_header(res, WRC_RT_RCDATA, NULL, name, rdt->memopt, NULL);
1155 put_raw_data(res, rdt->data, 0);
1156 /* Set ResourceSize */
1157 SetResSize(res, restag);
1164 *****************************************************************************
1165 * Function : messagetable2res
1166 * Syntax : res_t *messagetable2res(name_id_t *name, messagetable_t *msg)
1168 * name - Name/ordinal of the resource
1169 * msg - The messagetable descriptor
1170 * Output : New .res format structure
1173 *****************************************************************************
1175 res_t *messagetable2res(name_id_t *name, messagetable_t *msg)
1177 assert(name != NULL);
1178 assert(msg != NULL);
1179 warning("Messagetable not yet implemented");
1184 *****************************************************************************
1185 * Function : stringtable2res
1186 * Syntax : res_t *stringtable2res(stringtable_t *stt)
1188 * stt - The stringtable descriptor
1189 * Output : New .res format structure
1192 *****************************************************************************
1194 res_t *stringtable2res(stringtable_t *stt)
1202 assert(stt != NULL);
1205 for(; stt; stt = stt->next)
1209 warning("Empty internal stringtable");
1212 name.type = name_ord;
1213 name.name.i_name = (stt->idbase >> 4) + 1;
1214 restag = put_res_header(res, WRC_RT_STRING, NULL, &name, stt->memopt, win32 ? &(stt->lvc) : NULL);
1215 for(i = 0; i < stt->nentries; i++)
1217 if(stt->entries[i].str)
1220 put_word(res, stt->entries[i].str->size);
1222 put_byte(res, stt->entries[i].str->size);
1223 put_string(res, stt->entries[i].str, win32 ? str_unicode : str_char, FALSE);
1233 /* Set ResourceSize */
1234 SetResSize(res, restag - lastsize);
1237 lastsize = res->size;
1243 *****************************************************************************
1244 * Function : user2res
1245 * Syntax : res_t *user2res(name_id_t *name, user_t *usr)
1247 * name - Name/ordinal of the resource
1248 * usr - The userresource descriptor
1249 * Output : New .res format structure
1252 *****************************************************************************
1254 res_t *user2res(name_id_t *name, user_t *usr)
1258 assert(name != NULL);
1259 assert(usr != NULL);
1262 restag = put_res_header(res, 0, usr->type, name, usr->memopt, NULL);
1263 put_raw_data(res, usr->data, 0);
1264 /* Set ResourceSize */
1265 SetResSize(res, restag);
1272 *****************************************************************************
1273 * Function : versionblock2res
1274 * Syntax : void versionblock2res(res_t *res, ver_block_t *blk)
1276 * res - Binary resource to write to
1277 * blk - The version block to be written
1280 * Remarks : Self recursive
1281 *****************************************************************************
1283 void versionblock2res(res_t *res, ver_block_t *blk, int level)
1292 blksizetag = res->size;
1293 put_word(res, 0); /* Will be overwritten later */
1296 put_word(res, 0); /* level ? */
1297 put_string(res, blk->name, win32 ? str_unicode : str_char, TRUE);
1299 for(val = blk->values; val; val = val->next)
1301 if(val->type == val_str)
1303 valblksizetag = res->size;
1304 put_word(res, 0); /* Will be overwritten later */
1305 valvalsizetag = res->size;
1306 put_word(res, 0); /* Will be overwritten later */
1309 put_word(res, level);
1311 put_string(res, val->key, win32 ? str_unicode : str_char, TRUE);
1314 put_string(res, val->value.str, win32 ? str_unicode : str_char, TRUE);
1316 *(WORD *)&(res->data[valvalsizetag]) = (WORD)((res->size - tag) >> 1);
1318 *(WORD *)&(res->data[valvalsizetag]) = (WORD)(res->size - tag);
1319 *(WORD *)&(res->data[valblksizetag]) = (WORD)(res->size - valblksizetag);
1322 else if(val->type == val_words)
1324 valblksizetag = res->size;
1325 put_word(res, 0); /* Will be overwritten later */
1326 valvalsizetag = res->size;
1327 put_word(res, 0); /* Will be overwritten later */
1330 put_word(res, level);
1332 put_string(res, val->key, win32 ? str_unicode : str_char, TRUE);
1335 for(i = 0; i < val->value.words->nwords; i++)
1337 put_word(res, val->value.words->words[i]);
1339 *(WORD *)&(res->data[valvalsizetag]) = (WORD)(res->size - tag);
1340 *(WORD *)&(res->data[valblksizetag]) = (WORD)(res->size - valblksizetag);
1343 else if(val->type == val_block)
1345 versionblock2res(res, val->value.block, level+1);
1349 internal_error(__FILE__, __LINE__, "Invalid value indicator %d in VERSIONINFO", val->type);
1354 *(WORD *)&(res->data[blksizetag]) = (WORD)(res->size - blksizetag);
1358 *****************************************************************************
1359 * Function : versioninfo2res
1360 * Syntax : res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver)
1362 * name - Name/ordinal of the resource
1363 * ver - The versioninfo descriptor
1364 * Output : New .res format structure
1367 *****************************************************************************
1369 res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver)
1372 int rootblocksizetag;
1379 assert(name != NULL);
1380 assert(ver != NULL);
1382 vsvi.type = str_char;
1383 vsvi.str.cstr = "VS_VERSION_INFO";
1384 vsvi.size = 15; /* Excl. termination */
1387 restag = put_res_header(res, WRC_RT_VERSION, NULL, name, WRC_MO_MOVEABLE | WRC_MO_PURE, NULL);
1388 rootblocksizetag = res->size;
1389 put_word(res, 0); /* BlockSize filled in later */
1390 valsizetag = res->size;
1391 put_word(res, 0); /* ValueSize filled in later*/
1393 put_word(res, 0); /* Tree-level ? */
1394 put_string(res, &vsvi, win32 ? str_unicode : str_char, TRUE);
1398 put_dword(res, VS_FFI_SIGNATURE);
1399 put_dword(res, VS_FFI_STRUCVERSION);
1400 put_dword(res, (ver->filever_maj1 << 16) + (ver->filever_maj2 & 0xffff));
1401 put_dword(res, (ver->filever_min1 << 16) + (ver->filever_min2 & 0xffff));
1402 put_dword(res, (ver->prodver_maj1 << 16) + (ver->prodver_maj2 & 0xffff));
1403 put_dword(res, (ver->prodver_min1 << 16) + (ver->prodver_min2 & 0xffff));
1404 put_dword(res, ver->fileflagsmask);
1405 put_dword(res, ver->fileflags);
1406 put_dword(res, ver->fileos);
1407 put_dword(res, ver->filetype);
1408 put_dword(res, ver->filesubtype);
1409 put_dword(res, 0); /* FileDateMS */
1410 put_dword(res, 0); /* FileDateLS */
1412 *(WORD *)&(res->data[valsizetag]) = (WORD)(res->size - tag);
1413 /* Descend into the blocks */
1414 for(blk = ver->blocks; blk; blk = blk->next)
1415 versionblock2res(res, blk, 0);
1416 /* Set root block's size */
1417 *(WORD *)&(res->data[rootblocksizetag]) = (WORD)(res->size - rootblocksizetag);
1419 SetResSize(res, restag);
1427 *****************************************************************************
1428 * Function : toolbaritem2res
1429 * Syntax : void toolbaritem2res(res_t *res, toolbar_item_t *tbitem)
1433 * Remarks : Self recursive
1434 *****************************************************************************
1436 void toolbaritem2res(res_t *res, toolbar_item_t *tbitem)
1438 toolbar_item_t *itm = tbitem;
1442 put_word(res, itm->id);
1449 *****************************************************************************
1450 * Function : toolbar2res
1451 * Syntax : res_t *toolbar2res(name_id_t *name, toolbar_t *toolbar)
1453 * name - Name/ordinal of the resource
1454 * toolbar - The toolbar descriptor
1455 * Output : New .res format structure
1458 *****************************************************************************
1460 res_t *toolbar2res(name_id_t *name, toolbar_t *toolbar)
1464 assert(name != NULL);
1465 assert(toolbar != NULL);
1470 restag = put_res_header(res, WRC_RT_TOOLBAR, NULL, name, toolbar->memopt, &(toolbar->lvc));
1472 put_word(res, 1); /* Menuheader: Version */
1473 put_word(res, toolbar->button_width); /* (in pixels?) */
1474 put_word(res, toolbar->button_height); /* (in pixels?) */
1475 put_word(res, toolbar->nitems);
1477 toolbaritem2res(res, toolbar->items);
1478 /* Set ResourceSize */
1479 SetResSize(res, restag);
1484 /* Do not generate anything in 16-bit mode */
1493 *****************************************************************************
1494 * Function : prep_nid_for_label
1495 * Syntax : char *prep_nid_for_label(name_id_t *nid)
1498 * Description : Converts a resource name into the first 32 (or less)
1499 * characters of the name with conversions.
1501 *****************************************************************************
1503 #define MAXNAMELEN 32
1504 char *prep_nid_for_label(name_id_t *nid)
1506 static char buf[MAXNAMELEN+1];
1508 assert(nid != NULL);
1510 if(nid->type == name_str && nid->name.s_name->type == str_unicode)
1514 sptr = nid->name.s_name->str.wstr;
1516 for(i = 0; *sptr && i < MAXNAMELEN; i++)
1518 if((unsigned)*sptr < 0x80 && isprint((char)*sptr))
1521 warning("Resourcename (str_unicode) contain unprintable characters or invalid translation, ignored");
1525 else if(nid->type == name_str && nid->name.s_name->type == str_char)
1529 cptr = nid->name.s_name->str.cstr;
1531 for(i = 0; *cptr && i < MAXNAMELEN; i++)
1533 if((unsigned)*cptr < 0x80 && isprint(*cptr))
1536 warning("Resourcename (str_char) contain unprintable characters, ignored");
1540 else if(nid->type == name_ord)
1542 sprintf(buf, "%u", nid->name.i_name);
1546 internal_error(__FILE__, __LINE__, "Resource name_id with invalid type %d", nid->type);
1553 *****************************************************************************
1554 * Function : make_c_name
1555 * Syntax : char *make_c_name(char *base, name_id_t *nid, language_t *lan)
1558 * Description : Converts a resource name into a valid c-identifier in the
1561 *****************************************************************************
1563 char *make_c_name(char *base, name_id_t *nid, language_t *lan)
1570 sprintf(lanbuf, "%d", lan ? MAKELANGID(lan->id, lan->sub) : 0);
1571 buf = prep_nid_for_label(nid);
1572 nlen = strlen(buf) + strlen(lanbuf);
1573 nlen += strlen(base) + 4; /* three time '_' and '\0' */
1574 ret = (char *)xmalloc(nlen);
1580 strcat(ret, lanbuf);
1585 *****************************************************************************
1586 * Function : get_c_typename
1587 * Syntax : char *get_c_typename(enum res_e type)
1590 * Description : Convert resource enum to char string to be used in c-name
1593 *****************************************************************************
1595 char *get_c_typename(enum res_e type)
1599 case res_acc: return "Acc";
1600 case res_bmp: return "Bmp";
1601 case res_cur: return "Cur";
1602 case res_curg: return "CurGrp";
1604 case res_dlgex: return "Dlg";
1605 case res_fnt: return "Fnt";
1606 case res_ico: return "Ico";
1607 case res_icog: return "IcoGrp";
1609 case res_menex: return "Men";
1610 case res_rdt: return "RCDat";
1611 case res_stt: return "StrTab";
1612 case res_usr: return "Usr";
1613 case res_msg: return "MsgTab";
1614 case res_ver: return "VerInf";
1615 case res_toolbar: return "TlBr";
1616 default: return "Oops";
1621 *****************************************************************************
1622 * Function : resources2res
1623 * Syntax : void resources2res(resource_t *top)
1625 * top - The resource-tree to convert
1627 * Description : Convert logical resource descriptors into binary data
1629 *****************************************************************************
1631 void resources2res(resource_t *top)
1639 top->binres = accelerator2res(top->name, top->res.acc);
1643 top->binres = bitmap2res(top->name, top->res.bmp);
1647 top->binres = cursor2res(top->res.cur);
1651 top->binres = cursorgroup2res(top->name, top->res.curg);
1655 top->binres = dialog2res(top->name, top->res.dlg);
1659 top->binres = dialogex2res(top->name, top->res.dlgex);
1663 top->binres = font2res(top->name, top->res.fnt);
1667 top->binres = icon2res(top->res.ico);
1671 top->binres = icongroup2res(top->name, top->res.icog);
1675 top->binres = menu2res(top->name, top->res.men);
1679 top->binres = menuex2res(top->name, top->res.menex);
1683 top->binres = rcdata2res(top->name, top->res.rdt);
1687 top->binres = stringtable2res(top->res.stt);
1691 top->binres = user2res(top->name, top->res.usr);
1695 top->binres = messagetable2res(top->name, top->res.msg);
1699 top->binres = versioninfo2res(top->name, top->res.ver);
1703 top->binres = toolbar2res(top->name, top->res.tbt);
1706 internal_error(__FILE__, __LINE__, "Unknown resource type encountered %d in binary res generation", top->type);
1708 top->c_name = make_c_name(get_c_typename(top->type), top->name, top->lan);