source: trunk/tools/wrc/genres.c@ 1036

Last change on this file since 1036 was 882, checked in by sandervl, 26 years ago

Created Wine port of wrc (using EMX/GCC)

File size: 44.6 KB
Line 
1/*
2 * Generate .res format from a resource-tree
3 *
4 * Copyright 1998 Bertho A. Stultiens
5 *
6 * 25-May-1998 BS - Added simple unicode -> char conversion for resource
7 * names in .s and .h files.
8 */
9
10#include "config.h"
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <assert.h>
16#include <ctype.h>
17
18#include "wrc.h"
19#include "genres.h"
20#include "utils.h"
21#include "winuser.h"
22
23#define SetResSize(res, tag) *(DWORD *)&((res)->data[(tag)]) = \
24 (res)->size - *(DWORD *)&((res)->data[(tag)])
25
26res_t *new_res(void)
27{
28 res_t *r;
29 r = (res_t *)xmalloc(sizeof(res_t));
30 r->allocsize = RES_BLOCKSIZE;
31 r->size = 0;
32 r->data = (char *)xmalloc(RES_BLOCKSIZE);
33 return r;
34}
35
36res_t *grow_res(res_t *r, int add)
37{
38 r->allocsize += add;
39 r->data = (char *)xrealloc(r->data, r->allocsize);
40 return r;
41}
42
43/*
44 *****************************************************************************
45 * Function : put_byte
46 * put_word
47 * put_dword
48 * Syntax : void put_byte(res_t *res, unsigned c)
49 * void put_word(res_t *res, unsigned w)
50 * void put_dword(res_t *res, unsigned d)
51 * Input :
52 * res - Binary resource to put the data in
53 * c, w, d - Data to put
54 * Output : nop
55 * Description : Put primitives that put an item in the binary resource.
56 * The data array grows automatically.
57 * Remarks :
58 *****************************************************************************
59*/
60void put_byte(res_t *res, unsigned c)
61{
62 if(res->allocsize - res->size < sizeof(char))
63 grow_res(res, RES_BLOCKSIZE);
64 *(char *)&(res->data[res->size]) = (char)c;
65 res->size += sizeof(char);
66}
67
68void put_word(res_t *res, unsigned w)
69{
70 if(res->allocsize - res->size < sizeof(WORD))
71 grow_res(res, RES_BLOCKSIZE);
72 *(WORD *)&(res->data[res->size]) = (WORD)w;
73 res->size += sizeof(WORD);
74}
75
76void put_dword(res_t *res, unsigned d)
77{
78 if(res->allocsize - res->size < sizeof(DWORD))
79 grow_res(res, RES_BLOCKSIZE);
80 *(DWORD *)&(res->data[res->size]) = (DWORD)d;
81 res->size += sizeof(DWORD);
82}
83
84void put_pad(res_t *res)
85{
86 while(res->size & 0x3)
87 put_byte(res, 0);
88}
89
90/*
91 *****************************************************************************
92 * Function : string_to_upper
93 * Syntax : void string_to_upper(string_t *str)
94 * Input :
95 * Output :
96 * Description :
97 * Remarks : FIXME: codepages...
98 *****************************************************************************
99*/
100void string_to_upper(string_t *str)
101{
102 if(str->type == str_char)
103 {
104 char *cptr = str->str.cstr;
105 for(; *cptr; cptr++)
106 *cptr = (char)toupper(*cptr);
107 }
108 else if(str->type == str_unicode)
109 {
110 short *sptr = str->str.wstr;
111 for(; *sptr; sptr++)
112 if(isalpha(*sptr))
113 *sptr = (short)toupper(*sptr);
114 }
115 else
116 {
117 internal_error(__FILE__, __LINE__, "Invalid string type %d", str->type);
118 }
119}
120
121/*
122 *****************************************************************************
123 * Function : put_string
124 * Syntax : void put_string(res_t *res, string_t *str, enum str_e type,
125 * int isterm)
126 * Input :
127 * res - Binary resource to put the data in
128 * str - String to put
129 * type - Data has to be written in either str_char or str_unicode
130 * isterm - The string is '\0' terminated (disregard the string's
131 * size member)
132 * Output : nop
133 * Description :
134 * Remarks :
135 *****************************************************************************
136*/
137void put_string(res_t *res, string_t *str, enum str_e type, int isterm)
138{
139 int cnt;
140 int c = !0;
141 assert(res != NULL);
142 assert(str != NULL);
143 if(!isterm && str->size == 0)
144 {
145 warning("String length is zero, not written");
146 return;
147 }
148
149 if(str->type == str_unicode && type == str_unicode)
150 {
151 for(cnt = 0; cnt < str->size; cnt++)
152 {
153 c = str->str.wstr[cnt];
154 put_word(res, c);
155 if(isterm && !c)
156 break;
157 }
158 if(isterm && (str->size == 0 || (cnt == str->size && c)))
159 put_word(res, 0);
160 }
161 else if(str->type == str_char && type == str_char)
162 {
163 for(cnt = 0; cnt < str->size; cnt++)
164 {
165 c = str->str.cstr[cnt];
166 put_byte(res, c);
167 if(isterm && !c)
168 break;
169 }
170 if(isterm && (str->size == 0 || (cnt == str->size && c)))
171 put_byte(res, 0);
172 }
173 else if(str->type == str_unicode && type == str_char)
174 {
175 for(cnt = 0; cnt < str->size; cnt++)
176 {
177 c = str->str.wstr[cnt];
178 put_byte(res, c);
179 if(isterm && !c)
180 break;
181 }
182 if(isterm && (str->size == 0 || (cnt == str->size && c)))
183 put_byte(res, 0);
184 }
185 else /* str->type == str_char && type == str_unicode */
186 {
187 for(cnt = 0; cnt < str->size; cnt++)
188 {
189 c = str->str.cstr[cnt];
190 put_word(res, c & 0xff);
191 if(isterm && !c)
192 break;
193 }
194 if(isterm && (str->size == 0 || (cnt == str->size && c)))
195 put_word(res, 0);
196 }
197}
198
199/*
200 *****************************************************************************
201 * Function : put_name_id
202 * Syntax : void put_name_id(res_t *res, name_id_t *nid, int upcase)
203 * Input :
204 * Output :
205 * Description :
206 * Remarks :
207 *****************************************************************************
208*/
209void put_name_id(res_t *res, name_id_t *nid, int upcase)
210{
211 if(nid->type == name_ord)
212 {
213 if(win32)
214 put_word(res, 0xffff);
215 else
216 put_byte(res, 0xff);
217 put_word(res, (WORD)nid->name.i_name);
218 }
219 else if(nid->type == name_str)
220 {
221 if(upcase)
222 string_to_upper(nid->name.s_name);
223 put_string(res, nid->name.s_name, win32 ? str_unicode : str_char, TRUE);
224 }
225 else
226 {
227 internal_error(__FILE__, __LINE__, "Invalid name_id type %d", nid->type);
228 }
229}
230
231/*
232 *****************************************************************************
233 * Function : put_lvc
234 * Syntax : void put_lvc(res_t *res, lvc_t *lvc)
235 * Input :
236 * Output :
237 * Description :
238 * Remarks :
239 *****************************************************************************
240*/
241void put_lvc(res_t *res, lvc_t *lvc)
242{
243 if(lvc && lvc->language)
244 put_word(res, MAKELANGID(lvc->language->id, lvc->language->sub));
245 else
246 put_word(res, 0); /* Neutral */
247 if(lvc && lvc->version)
248 put_dword(res, *(lvc->version));
249 else
250 put_dword(res, 0);
251 if(lvc && lvc->characts)
252 put_dword(res, *(lvc->characts));
253 else
254 put_dword(res, 0);
255}
256
257/*
258 *****************************************************************************
259 * Function : put_raw_data
260 * Syntax : void put_raw_data(res_t *res, raw_data_t *raw, int offset)
261 * Input :
262 * Output :
263 * Description :
264 * Remarks :
265 *****************************************************************************
266*/
267void put_raw_data(res_t *res, raw_data_t *raw, int offset)
268{
269 int wsize = raw->size - offset;
270 if(res->allocsize - res->size < wsize)
271 grow_res(res, wsize);
272 memcpy(&(res->data[res->size]), raw->data + offset, wsize);
273 res->size += wsize;
274}
275
276/*
277 *****************************************************************************
278 * Function : put_res_header
279 * Syntax : intput_res_header(res_t *res, int type, name_id_t *ntype,
280 * name_id_t *name, DWORD memopt, lvc_t *lvc)
281 *
282 * Input :
283 * res - Binary resource descriptor to write to
284 * type - Resource identifier (if ntype == NULL)
285 * ntype - Name id of type
286 * name - Resource's name
287 * memopt - Resource's memory options to write
288 * lvc - Language, version and characteristics (win32 only)
289 * Output : An index to the resource size field. The resource size field
290 * contains the header size upon exit.
291 * Description :
292 * Remarks :
293 *****************************************************************************
294*/
295int put_res_header(res_t *res, int type, name_id_t *ntype, name_id_t *name,
296 DWORD memopt, lvc_t *lvc)
297{
298 if(win32)
299 {
300 put_dword(res, 0); /* We will overwrite these later */
301 put_dword(res, 0);
302 if(!ntype)
303 {
304 put_word(res, 0xffff); /* ResType */
305 put_word(res, type);
306 }
307 else
308 put_name_id(res, ntype, TRUE);
309 put_name_id(res, name, TRUE); /* ResName */
310 put_pad(res);
311 put_dword(res, 0); /* DataVersion */
312 put_word(res, memopt); /* Memory options */
313 put_lvc(res, lvc); /* Language, version and characts */
314 ((DWORD *)res->data)[0] = res->size; /* Set preliminary resource */
315 ((DWORD *)res->data)[1] = res->size; /* Set HeaderSize */
316 res->dataidx = res->size;
317 return 0;
318 }
319 else /* win16 */
320 {
321 int tag;
322 if(!ntype)
323 {
324 put_byte(res, 0xff); /* ResType */
325 put_word(res, type);
326 }
327 else
328 put_name_id(res, ntype, TRUE);
329 put_name_id(res, name, TRUE); /* ResName */
330 put_word(res, memopt); /* Memory options */
331 tag = res->size;
332 put_dword(res, 0); /* ResSize overwritten later*/
333 *(DWORD *)&(res->data[tag]) = res->size;
334 res->dataidx = res->size;
335 return tag;
336 }
337}
338
339/*
340 *****************************************************************************
341 * Function : accelerator2res
342 * Syntax : res_t *accelerator2res(name_id_t *name, accelerator_t *acc)
343 * Input :
344 * name - Name/ordinal of the resource
345 * acc - The accelerator descriptor
346 * Output : New .res format structure
347 * Description :
348 * Remarks :
349 *****************************************************************************
350*/
351res_t *accelerator2res(name_id_t *name, accelerator_t *acc)
352{
353 int restag;
354 res_t *res;
355 event_t *ev;
356 assert(name != NULL);
357 assert(acc != NULL);
358
359 ev = acc->events;
360 res = new_res();
361 if(win32)
362 {
363 restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, &(acc->lvc));
364 while(ev)
365 {
366 put_word(res, ev->flags | (ev->next ? 0 : 0x80));
367 put_word(res, ev->key);
368 put_word(res, ev->id);
369 put_word(res, 0); /* Padding */
370 ev = ev->next;
371 }
372 put_pad(res);
373 }
374 else /* win16 */
375 {
376 restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, NULL);
377 while(ev)
378 {
379 put_byte(res, ev->flags | (ev->next ? 0 : 0x80));
380 put_word(res, ev->key);
381 put_word(res, ev->id);
382 ev = ev->next;
383 }
384 }
385 /* Set ResourceSize */
386 SetResSize(res, restag);
387 return res;
388}
389
390/*
391 *****************************************************************************
392 * Function : dialog2res
393 * Syntax : res_t *dialog2res(name_id_t *name, dialog_t *dlg)
394 * Input :
395 * name - Name/ordinal of the resource
396 * dlg - The dialog descriptor
397 * Output : New .res format structure
398 * Description :
399 * Remarks :
400 *****************************************************************************
401*/
402res_t *dialog2res(name_id_t *name, dialog_t *dlg)
403{
404 int restag;
405 res_t *res;
406 control_t *ctrl;
407 int tag_nctrl;
408 int nctrl = 0;
409 assert(name != NULL);
410 assert(dlg != NULL);
411
412 ctrl = dlg->controls;
413 res = new_res();
414 if(win32)
415 {
416 restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, &(dlg->lvc));
417
418 put_dword(res, dlg->style);
419 put_dword(res, dlg->gotexstyle ? dlg->exstyle : 0);
420 tag_nctrl = res->size;
421 put_word(res, 0); /* Number of controls */
422 put_word(res, dlg->x);
423 put_word(res, dlg->y);
424 put_word(res, dlg->width);
425 put_word(res, dlg->height);
426 if(dlg->menu)
427 put_name_id(res, dlg->menu, TRUE);
428 else
429 put_word(res, 0);
430 if(dlg->dlgclass)
431 put_name_id(res, dlg->dlgclass, TRUE);
432 else
433 put_word(res, 0);
434 if(dlg->title)
435 put_string(res, dlg->title, str_unicode, TRUE);
436 else
437 put_word(res, 0);
438 if(dlg->font)
439 {
440 put_word(res, dlg->font->size);
441 put_string(res, dlg->font->name, str_unicode, TRUE);
442 }
443
444 put_pad(res);
445 while(ctrl)
446 {
447 /* FIXME: what is default control style? */
448 put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD);
449 put_dword(res, ctrl->gotexstyle ? ctrl->exstyle : 0);
450 put_word(res, ctrl->x);
451 put_word(res, ctrl->y);
452 put_word(res, ctrl->width);
453 put_word(res, ctrl->height);
454 put_word(res, ctrl->id);
455 if(ctrl->ctlclass)
456 put_name_id(res, ctrl->ctlclass, TRUE);
457 else
458 internal_error(__FILE__, __LINE__, "Control has no control-class");
459 if(ctrl->title)
460 put_name_id(res, ctrl->title, FALSE);
461 else
462 put_word(res, 0);
463 if(ctrl->extra)
464 {
465 put_word(res, ctrl->extra->size+2);
466 put_pad(res);
467 put_raw_data(res, ctrl->extra, 0);
468 }
469 else
470 put_word(res, 0);
471
472 if(ctrl->next)
473 put_pad(res);
474 nctrl++;
475 ctrl = ctrl->next;
476 }
477 /* Set number of controls */
478 *(WORD *)&((char *)res->data)[tag_nctrl] = (WORD)nctrl;
479 }
480 else /* win16 */
481 {
482 restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, NULL);
483
484 put_dword(res, dlg->gotstyle ? dlg->style : WS_POPUPWINDOW);
485 tag_nctrl = res->size;
486 put_byte(res, 0); /* Number of controls */
487 put_word(res, dlg->x);
488 put_word(res, dlg->y);
489 put_word(res, dlg->width);
490 put_word(res, dlg->height);
491 if(dlg->menu)
492 put_name_id(res, dlg->menu, TRUE);
493 else
494 put_byte(res, 0);
495 if(dlg->dlgclass)
496 put_name_id(res, dlg->dlgclass, TRUE);
497 else
498 put_byte(res, 0);
499 if(dlg->title)
500 put_string(res, dlg->title, str_char, TRUE);
501 else
502 put_byte(res, 0);
503 if(dlg->font)
504 {
505 put_word(res, dlg->font->size);
506 put_string(res, dlg->font->name, str_char, TRUE);
507 }
508
509 while(ctrl)
510 {
511 put_word(res, ctrl->x);
512 put_word(res, ctrl->y);
513 put_word(res, ctrl->width);
514 put_word(res, ctrl->height);
515 put_word(res, ctrl->id);
516 put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD);
517 if(ctrl->ctlclass)
518 {
519 if(ctrl->ctlclass->type == name_ord
520 && ctrl->ctlclass->name.i_name >= 0x80
521 && ctrl->ctlclass->name.i_name <= 0x85)
522 put_byte(res, ctrl->ctlclass->name.i_name);
523 else if(ctrl->ctlclass->type == name_str)
524 put_name_id(res, ctrl->ctlclass, FALSE);
525 else
526 error("Unknown control-class %04x", ctrl->ctlclass->name.i_name);
527 }
528 else
529 internal_error(__FILE__, __LINE__, "Control has no control-class");
530 if(ctrl->title)
531 put_name_id(res, ctrl->title, FALSE);
532 else
533 put_byte(res, 0);
534
535 /* FIXME: What is this extra byte doing here? */
536 put_byte(res, 0);
537
538 nctrl++;
539 ctrl = ctrl->next;
540 }
541 /* Set number of controls */
542 ((char *)res->data)[tag_nctrl] = (char)nctrl;
543 }
544 /* Set ResourceSize */
545 SetResSize(res, restag);
546 return res;
547}
548
549/*
550 *****************************************************************************
551 * Function : dialogex2res
552 * Syntax : res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
553 * Input :
554 * name - Name/ordinal of the resource
555 * dlgex - The dialogex descriptor
556 * Output : New .res format structure
557 * Description :
558 * Remarks :
559 *****************************************************************************
560*/
561res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
562{
563 int restag;
564 res_t *res;
565 control_t *ctrl;
566 int tag_nctrl;
567 int nctrl = 0;
568 assert(name != NULL);
569 assert(dlgex != NULL);
570
571 ctrl = dlgex->controls;
572 res = new_res();
573 if(win32)
574 {
575 restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlgex->memopt, &(dlgex->lvc));
576
577 /* FIXME: MS doc says thet the first word must contain 0xffff
578 * and the second 0x0001 to signal a DLGTEMPLATEEX. Borland's
579 * compiler reverses the two words.
580 * I don't know which one to choose, but I write it as Mr. B
581 * writes it.
582 */
583 put_word(res, 1); /* Signature */
584 put_word(res, 0xffff); /* DlgVer */
585 put_dword(res, dlgex->gothelpid ? dlgex->helpid : 0);
586 put_dword(res, dlgex->gotexstyle ? dlgex->exstyle : 0);
587 put_dword(res, dlgex->gotstyle ? dlgex->style : WS_POPUPWINDOW);
588 tag_nctrl = res->size;
589 put_word(res, 0); /* Number of controls */
590 put_word(res, dlgex->x);
591 put_word(res, dlgex->y);
592 put_word(res, dlgex->width);
593 put_word(res, dlgex->height);
594 if(dlgex->menu)
595 put_name_id(res, dlgex->menu, TRUE);
596 else
597 put_word(res, 0);
598 if(dlgex->dlgclass)
599 put_name_id(res, dlgex->dlgclass, TRUE);
600 else
601 put_word(res, 0);
602 if(dlgex->title)
603 put_string(res, dlgex->title, str_unicode, TRUE);
604 else
605 put_word(res, 0);
606 if(dlgex->font)
607 {
608 put_word(res, dlgex->font->size);
609 put_word(res, dlgex->font->weight);
610 /* FIXME: ? TRUE should be sufficient to say that its
611 * italic, but Borland's compiler says its 0x0101.
612 * I just copy it here, and hope for the best.
613 */
614 put_word(res, dlgex->font->italic ? 0x0101 : 0);
615 put_string(res, dlgex->font->name, str_unicode, TRUE);
616 }
617
618 put_pad(res);
619 while(ctrl)
620 {
621 put_dword(res, ctrl->gothelpid ? ctrl->helpid : 0);
622 put_dword(res, ctrl->gotexstyle ? ctrl->exstyle : 0);
623 /* FIXME: what is default control style? */
624 put_dword(res, ctrl->gotstyle ? ctrl->style : WS_CHILD | WS_VISIBLE);
625 put_word(res, ctrl->x);
626 put_word(res, ctrl->y);
627 put_word(res, ctrl->width);
628 put_word(res, ctrl->height);
629 put_word(res, ctrl->id);
630 /* FIXME: Pad is _NOT_ documented!?! */
631 put_pad(res);
632 if(ctrl->ctlclass)
633 put_name_id(res, ctrl->ctlclass, TRUE);
634 else
635 internal_error(__FILE__, __LINE__, "Control has no control-class");
636 if(ctrl->title)
637 put_name_id(res, ctrl->title, FALSE);
638 else
639 put_word(res, 0);
640 if(ctrl->extra)
641 {
642 put_pad(res);
643 put_word(res, ctrl->extra->size);
644 put_raw_data(res, ctrl->extra, 0);
645 }
646 else
647 put_word(res, 0);
648
649 put_pad(res);
650 nctrl++;
651 ctrl = ctrl->next;
652 }
653 /* Set number of controls */
654 *(WORD *)&((char *)res->data)[tag_nctrl] = (WORD)nctrl;
655 /* Set ResourceSize */
656 SetResSize(res, restag);
657 put_pad(res);
658 }
659 else /* win16 */
660 {
661 /* Do not generate anything in 16-bit mode */
662 free(res->data);
663 free(res);
664 return NULL;
665 }
666 return res;
667}
668
669/*
670 *****************************************************************************
671 * Function : menuitem2res
672 * Syntax : void menuitem2res(res_t *res, menu_item_t *item)
673 * Input :
674 * Output :
675 * Description :
676 * Remarks : Self recursive
677 *****************************************************************************
678*/
679void menuitem2res(res_t *res, menu_item_t *menitem)
680{
681 menu_item_t *itm = menitem;
682 if(win32)
683 {
684 while(itm)
685 {
686 put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0));
687 if(!itm->popup)
688 put_word(res, itm->id);
689 if(itm->name)
690 put_string(res, itm->name, str_unicode, TRUE);
691 else
692 put_word(res, 0);
693 if(itm->popup)
694 menuitem2res(res, itm->popup);
695 itm = itm->next;
696 }
697 }
698 else /* win16 */
699 {
700 while(itm)
701 {
702 put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0));
703 if(!itm->popup)
704 put_word(res, itm->id);
705 if(itm->name)
706 put_string(res, itm->name, str_char, TRUE);
707 else
708 put_byte(res, 0);
709 if(itm->popup)
710 menuitem2res(res, itm->popup);
711 itm = itm->next;
712 }
713 }
714
715}
716
717/*
718 *****************************************************************************
719 * Function : menu2res
720 * Syntax : res_t *menu2res(name_id_t *name, menu_t *men)
721 * Input :
722 * name - Name/ordinal of the resource
723 * men - The menu descriptor
724 * Output : New .res format structure
725 * Description :
726 * Remarks :
727 *****************************************************************************
728*/
729res_t *menu2res(name_id_t *name, menu_t *men)
730{
731 int restag;
732 res_t *res;
733 assert(name != NULL);
734 assert(men != NULL);
735
736 res = new_res();
737 restag = put_res_header(res, WRC_RT_MENU, NULL, name, men->memopt, win32 ? &(men->lvc) : NULL);
738
739 put_dword(res, 0); /* Menuheader: Version and HeaderSize */
740 menuitem2res(res, men->items);
741 /* Set ResourceSize */
742 SetResSize(res, restag);
743 if(win32)
744 put_pad(res);
745 return res;
746}
747
748/*
749 *****************************************************************************
750 * Function : menuexitem2res
751 * Syntax : void menuexitem2res(res_t *res, menuex_item_t *item)
752 * Input :
753 * Output : nop
754 * Description :
755 * Remarks : Self recursive
756 *****************************************************************************
757*/
758void menuexitem2res(res_t *res, menuex_item_t *menitem)
759{
760 menuex_item_t *itm = menitem;
761 assert(win32 != 0);
762 while(itm)
763 {
764 put_dword(res, itm->gottype ? itm->type : 0);
765 put_dword(res, itm->gotstate ? itm->state : 0);
766 put_dword(res, itm->gotid ? itm->id : 0); /* FIXME: Docu. says word */
767 put_word(res, (itm->popup ? 0x01 : 0) | (!itm->next ? MF_END : 0));
768 if(itm->name)
769 put_string(res, itm->name, str_unicode, TRUE);
770 else
771 put_word(res, 0);
772 put_pad(res);
773 if(itm->popup)
774 {
775 put_dword(res, itm->gothelpid ? itm->helpid : 0);
776 menuexitem2res(res, itm->popup);
777 }
778 itm = itm->next;
779 }
780
781}
782
783/*
784 *****************************************************************************
785 * Function : menuex2res
786 * Syntax : res_t *menuex2res(name_id_t *name, menuex_t *menex)
787 * Input :
788 * name - Name/ordinal of the resource
789 * menex - The menuex descriptor
790 * Output : New .res format structure
791 * Description :
792 * Remarks :
793 *****************************************************************************
794*/
795res_t *menuex2res(name_id_t *name, menuex_t *menex)
796{
797 int restag;
798 res_t *res;
799 assert(name != NULL);
800 assert(menex != NULL);
801
802 res = new_res();
803 if(win32)
804 {
805 restag = put_res_header(res, WRC_RT_MENU, NULL, name, menex->memopt, &(menex->lvc));
806
807 put_word(res, 1); /* Menuheader: Version */
808 put_word(res, 4); /* Offset */
809 put_dword(res, 0); /* HelpId */
810 put_pad(res);
811 menuexitem2res(res, menex->items);
812 /* Set ResourceSize */
813 SetResSize(res, restag);
814 put_pad(res);
815 }
816 else /* win16 */
817 {
818 /* Do not generate anything in 16-bit mode */
819 free(res->data);
820 free(res);
821 return NULL;
822 }
823 return res;
824}
825
826/*
827 *****************************************************************************
828 * Function : cursorgroup2res
829 * Syntax : res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg)
830 * Input :
831 * name - Name/ordinal of the resource
832 * curg - The cursor descriptor
833 * Output : New .res format structure
834 * Description :
835 * Remarks :
836 *****************************************************************************
837*/
838res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg)
839{
840 int restag;
841 res_t *res;
842 cursor_t *cur;
843 assert(name != NULL);
844 assert(curg != NULL);
845
846 res = new_res();
847 restag = put_res_header(res, WRC_RT_GROUP_CURSOR, NULL, name, curg->memopt, &(curg->lvc));
848 if(win32)
849 {
850 put_word(res, 0); /* Reserved */
851 /* FIXME: The ResType in the NEWHEADER structure should
852 * contain 14 according to the MS win32 doc. This is
853 * not the case with the BRC compiler and I really doubt
854 * the latter. Putting one here is compliant to win16 spec,
855 * but who knows the true value?
856 */
857 put_word(res, 2); /* ResType */
858 put_word(res, curg->ncursor);
859#if 0
860 for(cur = curg->cursorlist; cur; cur = cur->next)
861#else
862 cur = curg->cursorlist;
863 while(cur->next)
864 cur = cur->next;
865 for(; cur; cur = cur->prev)
866#endif
867 {
868 put_word(res, cur->width);
869 /* FIXME: The height of a cursor is half the size of
870 * the bitmap's height. BRC puts the height from the
871 * BITMAPINFOHEADER here instead of the cursorfile's
872 * height. MS doesn't seem to care...
873 */
874 put_word(res, cur->height);
875 /* FIXME: The next two are reversed in BRC and I don't
876 * know why. Probably a bug. But, we can safely ignore
877 * it because win16 does not support color cursors.
878 * A warning should have been generated by the parser.
879 */
880 put_word(res, cur->planes);
881 put_word(res, cur->bits);
882 /* FIXME: The +4 is the hotspot in the cursor resource.
883 * However, I cound not find this in the documentation.
884 * The hotspot bytes must either be included or MS
885 * doesn't care.
886 */
887 put_dword(res, cur->data->size +4);
888 put_word(res, cur->id);
889 }
890 }
891 else /* win16 */
892 {
893 put_word(res, 0); /* Reserved */
894 put_word(res, 2); /* ResType */
895 put_word(res, curg->ncursor);
896#if 0
897 for(cur = curg->cursorlist; cur; cur = cur->next)
898#else
899 cur = curg->cursorlist;
900 while(cur->next)
901 cur = cur->next;
902 for(; cur; cur = cur->prev)
903#endif
904 {
905 put_word(res, cur->width);
906 /* FIXME: The height of a cursor is half the size of
907 * the bitmap's height. BRC puts the height from the
908 * BITMAPINFOHEADER here instead of the cursorfile's
909 * height. MS doesn't seem to care...
910 */
911 put_word(res, cur->height);
912 /* FIXME: The next two are reversed in BRC and I don't
913 * know why. Probably a bug. But, we can safely ignore
914 * it because win16 does not support color cursors.
915 * A warning should have been generated by the parser.
916 */
917 put_word(res, cur->planes);
918 put_word(res, cur->bits);
919 /* FIXME: The +4 is the hotspot in the cursor resource.
920 * However, I cound not find this in the documentation.
921 * The hotspot bytes must either be included or MS
922 * doesn't care.
923 */
924 put_dword(res, cur->data->size +4);
925 put_word(res, cur->id);
926 }
927 }
928 SetResSize(res, restag); /* Set ResourceSize */
929 if(win32)
930 put_pad(res);
931
932 return res;
933}
934
935/*
936 *****************************************************************************
937 * Function : cursor2res
938 * Syntax : res_t *cursor2res(cursor_t *cur)
939 * Input :
940 * cur - The cursor descriptor
941 * Output : New .res format structure
942 * Description :
943 * Remarks :
944 *****************************************************************************
945*/
946res_t *cursor2res(cursor_t *cur)
947{
948 int restag;
949 res_t *res;
950 name_id_t name;
951
952 assert(cur != NULL);
953
954 res = new_res();
955 name.type = name_ord;
956 name.name.i_name = cur->id;
957 restag = put_res_header(res, WRC_RT_CURSOR, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &(cur->lvc));
958 put_word(res, cur->xhot);
959 put_word(res, cur->yhot);
960 put_raw_data(res, cur->data, 0);
961
962 SetResSize(res, restag); /* Set ResourceSize */
963 if(win32)
964 put_pad(res);
965
966 return res;
967}
968
969/*
970 *****************************************************************************
971 * Function : icongroup2res
972 * Syntax : res_t *icongroup2res(name_id_t *name, icon_group_t *icog)
973 * Input :
974 * name - Name/ordinal of the resource
975 * icog - The icon group descriptor
976 * Output : New .res format structure
977 * Description :
978 * Remarks :
979 *****************************************************************************
980*/
981res_t *icongroup2res(name_id_t *name, icon_group_t *icog)
982{
983 int restag;
984 res_t *res;
985 icon_t *ico;
986 assert(name != NULL);
987 assert(icog != NULL);
988
989 res = new_res();
990 restag = put_res_header(res, WRC_RT_GROUP_ICON, NULL, name, icog->memopt, &(icog->lvc));
991 if(win32)
992 {
993 put_word(res, 0); /* Reserved */
994 /* FIXME: The ResType in the NEWHEADER structure should
995 * contain 14 according to the MS win32 doc. This is
996 * not the case with the BRC compiler and I really doubt
997 * the latter. Putting one here is compliant to win16 spec,
998 * but who knows the true value?
999 */
1000 put_word(res, 1); /* ResType */
1001 put_word(res, icog->nicon);
1002 for(ico = icog->iconlist; ico; ico = ico->next)
1003 {
1004 put_byte(res, ico->width);
1005 put_byte(res, ico->height);
1006 put_byte(res, ico->nclr);
1007 put_byte(res, 0); /* Reserved */
1008 put_word(res, ico->planes);
1009 put_word(res, ico->bits);
1010 put_dword(res, ico->data->size);
1011 put_word(res, ico->id);
1012 }
1013 }
1014 else /* win16 */
1015 {
1016 put_word(res, 0); /* Reserved */
1017 put_word(res, 1); /* ResType */
1018 put_word(res, icog->nicon);
1019 for(ico = icog->iconlist; ico; ico = ico->next)
1020 {
1021 put_byte(res, ico->width);
1022 put_byte(res, ico->height);
1023 put_byte(res, ico->nclr);
1024 put_byte(res, 0); /* Reserved */
1025 put_word(res, ico->planes);
1026 put_word(res, ico->bits);
1027 put_dword(res, ico->data->size);
1028 put_word(res, ico->id);
1029 }
1030 }
1031 SetResSize(res, restag); /* Set ResourceSize */
1032 if(win32)
1033 put_pad(res);
1034
1035 return res;
1036}
1037
1038/*
1039 *****************************************************************************
1040 * Function : icon2res
1041 * Syntax : res_t *icon2res(icon_t *ico)
1042 * Input :
1043 * ico - The icon descriptor
1044 * Output : New .res format structure
1045 * Description :
1046 * Remarks :
1047 *****************************************************************************
1048*/
1049res_t *icon2res(icon_t *ico)
1050{
1051 int restag;
1052 res_t *res;
1053 name_id_t name;
1054
1055 assert(ico != NULL);
1056
1057 res = new_res();
1058 name.type = name_ord;
1059 name.name.i_name = ico->id;
1060 restag = put_res_header(res, WRC_RT_ICON, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &(ico->lvc));
1061 put_raw_data(res, ico->data, 0);
1062
1063 SetResSize(res, restag); /* Set ResourceSize */
1064 if(win32)
1065 put_pad(res);
1066
1067 return res;
1068}
1069
1070/*
1071 *****************************************************************************
1072 * Function : bitmap2res
1073 * Syntax : res_t *bitmap2res(name_id_t *name, bitmap_t *bmp)
1074 * Input :
1075 * name - Name/ordinal of the resource
1076 * bmp - The bitmap descriptor
1077 * Output : New .res format structure
1078 * Description :
1079 * Remarks :
1080 *****************************************************************************
1081*/
1082res_t *bitmap2res(name_id_t *name, bitmap_t *bmp)
1083{
1084 int restag;
1085 res_t *res;
1086 assert(name != NULL);
1087 assert(bmp != NULL);
1088
1089 HEAPCHECK();
1090 res = new_res();
1091 HEAPCHECK();
1092 restag = put_res_header(res, WRC_RT_BITMAP, NULL, name, bmp->memopt, NULL);
1093 HEAPCHECK();
1094 if(bmp->data->data[0] == 'B'
1095 && bmp->data->data[1] == 'M'
1096 && ((BITMAPFILEHEADER *)bmp->data->data)->bfSize == bmp->data->size
1097 && bmp->data->size >= sizeof(BITMAPFILEHEADER))
1098 {
1099 /* The File header is still attached, don't write it */
1100 put_raw_data(res, bmp->data, sizeof(BITMAPFILEHEADER));
1101 }
1102 else
1103 {
1104 put_raw_data(res, bmp->data, 0);
1105 }
1106 HEAPCHECK();
1107 /* Set ResourceSize */
1108 SetResSize(res, restag);
1109 HEAPCHECK();
1110 if(win32)
1111 put_pad(res);
1112 HEAPCHECK();
1113 return res;
1114}
1115
1116/*
1117 *****************************************************************************
1118 * Function : font2res
1119 * Syntax : res_t *font2res(name_id_t *name, font_t *fnt)
1120 * Input :
1121 * name - Name/ordinal of the resource
1122 * fnt - The font descriptor
1123 * Output : New .res format structure
1124 * Description :
1125 * Remarks :
1126 *****************************************************************************
1127*/
1128res_t *font2res(name_id_t *name, font_t *fnt)
1129{
1130 assert(name != NULL);
1131 assert(fnt != NULL);
1132 warning("Fonts not yet implemented");
1133 return NULL;
1134}
1135
1136/*
1137 *****************************************************************************
1138 * Function : rcdata2res
1139 * Syntax : res_t *rcdata2res(name_id_t *name, rcdata_t *rdt)
1140 * Input :
1141 * name - Name/ordinal of the resource
1142 * rdt - The rcdata descriptor
1143 * Output : New .res format structure
1144 * Description :
1145 * Remarks :
1146 *****************************************************************************
1147*/
1148res_t *rcdata2res(name_id_t *name, rcdata_t *rdt)
1149{
1150 int restag;
1151 res_t *res;
1152 assert(name != NULL);
1153 assert(rdt != NULL);
1154
1155 res = new_res();
1156 restag = put_res_header(res, WRC_RT_RCDATA, NULL, name, rdt->memopt, NULL);
1157 put_raw_data(res, rdt->data, 0);
1158 /* Set ResourceSize */
1159 SetResSize(res, restag);
1160 if(win32)
1161 put_pad(res);
1162 return res;
1163}
1164
1165/*
1166 *****************************************************************************
1167 * Function : messagetable2res
1168 * Syntax : res_t *messagetable2res(name_id_t *name, messagetable_t *msg)
1169 * Input :
1170 * name - Name/ordinal of the resource
1171 * msg - The messagetable descriptor
1172 * Output : New .res format structure
1173 * Description :
1174 * Remarks :
1175 *****************************************************************************
1176*/
1177res_t *messagetable2res(name_id_t *name, messagetable_t *msg)
1178{
1179 assert(name != NULL);
1180 assert(msg != NULL);
1181 warning("Messagetable not yet implemented");
1182 return NULL;
1183}
1184
1185/*
1186 *****************************************************************************
1187 * Function : stringtable2res
1188 * Syntax : res_t *stringtable2res(stringtable_t *stt)
1189 * Input :
1190 * stt - The stringtable descriptor
1191 * Output : New .res format structure
1192 * Description :
1193 * Remarks :
1194 *****************************************************************************
1195*/
1196res_t *stringtable2res(stringtable_t *stt)
1197{
1198 res_t *res;
1199 name_id_t name;
1200 int i;
1201 int restag;
1202 DWORD lastsize = 0;
1203
1204 assert(stt != NULL);
1205 res = new_res();
1206
1207 for(; stt; stt = stt->next)
1208 {
1209 if(!stt->nentries)
1210 {
1211 warning("Empty internal stringtable");
1212 continue;
1213 }
1214 name.type = name_ord;
1215 name.name.i_name = (stt->idbase >> 4) + 1;
1216 restag = put_res_header(res, WRC_RT_STRING, NULL, &name, stt->memopt, win32 ? &(stt->lvc) : NULL);
1217 for(i = 0; i < stt->nentries; i++)
1218 {
1219 if(stt->entries[i].str)
1220 {
1221 if(win32)
1222 put_word(res, stt->entries[i].str->size);
1223 else
1224 put_byte(res, stt->entries[i].str->size);
1225 put_string(res, stt->entries[i].str, win32 ? str_unicode : str_char, FALSE);
1226 }
1227 else
1228 {
1229 if(win32)
1230 put_word(res, 0);
1231 else
1232 put_byte(res, 0);
1233 }
1234 }
1235 /* Set ResourceSize */
1236 SetResSize(res, restag - lastsize);
1237 if(win32)
1238 put_pad(res);
1239 lastsize = res->size;
1240 }
1241 return res;
1242}
1243
1244/*
1245 *****************************************************************************
1246 * Function : user2res
1247 * Syntax : res_t *user2res(name_id_t *name, user_t *usr)
1248 * Input :
1249 * name - Name/ordinal of the resource
1250 * usr - The userresource descriptor
1251 * Output : New .res format structure
1252 * Description :
1253 * Remarks :
1254 *****************************************************************************
1255*/
1256res_t *user2res(name_id_t *name, user_t *usr)
1257{
1258 int restag;
1259 res_t *res;
1260 assert(name != NULL);
1261 assert(usr != NULL);
1262
1263 res = new_res();
1264 restag = put_res_header(res, 0, usr->type, name, usr->memopt, NULL);
1265 put_raw_data(res, usr->data, 0);
1266 /* Set ResourceSize */
1267 SetResSize(res, restag);
1268 if(win32)
1269 put_pad(res);
1270 return res;
1271}
1272
1273/*
1274 *****************************************************************************
1275 * Function : versionblock2res
1276 * Syntax : void versionblock2res(res_t *res, ver_block_t *blk)
1277 * Input :
1278 * res - Binary resource to write to
1279 * blk - The version block to be written
1280 * Output :
1281 * Description :
1282 * Remarks : Self recursive
1283 *****************************************************************************
1284*/
1285void versionblock2res(res_t *res, ver_block_t *blk, int level)
1286{
1287 ver_value_t *val;
1288 int blksizetag;
1289 int valblksizetag;
1290 int valvalsizetag;
1291 int tag;
1292 int i;
1293
1294 blksizetag = res->size;
1295 put_word(res, 0); /* Will be overwritten later */
1296 put_word(res, 0);
1297 if(win32)
1298 put_word(res, 0); /* level ? */
1299 put_string(res, blk->name, win32 ? str_unicode : str_char, TRUE);
1300 put_pad(res);
1301 for(val = blk->values; val; val = val->next)
1302 {
1303 if(val->type == val_str)
1304 {
1305 valblksizetag = res->size;
1306 put_word(res, 0); /* Will be overwritten later */
1307 valvalsizetag = res->size;
1308 put_word(res, 0); /* Will be overwritten later */
1309 if(win32)
1310 {
1311 put_word(res, level);
1312 }
1313 put_string(res, val->key, win32 ? str_unicode : str_char, TRUE);
1314 put_pad(res);
1315 tag = res->size;
1316 put_string(res, val->value.str, win32 ? str_unicode : str_char, TRUE);
1317 if(win32)
1318 *(WORD *)&(res->data[valvalsizetag]) = (WORD)((res->size - tag) >> 1);
1319 else
1320 *(WORD *)&(res->data[valvalsizetag]) = (WORD)(res->size - tag);
1321 *(WORD *)&(res->data[valblksizetag]) = (WORD)(res->size - valblksizetag);
1322 put_pad(res);
1323 }
1324 else if(val->type == val_words)
1325 {
1326 valblksizetag = res->size;
1327 put_word(res, 0); /* Will be overwritten later */
1328 valvalsizetag = res->size;
1329 put_word(res, 0); /* Will be overwritten later */
1330 if(win32)
1331 {
1332 put_word(res, level);
1333 }
1334 put_string(res, val->key, win32 ? str_unicode : str_char, TRUE);
1335 put_pad(res);
1336 tag = res->size;
1337 for(i = 0; i < val->value.words->nwords; i++)
1338 {
1339 put_word(res, val->value.words->words[i]);
1340 }
1341 *(WORD *)&(res->data[valvalsizetag]) = (WORD)(res->size - tag);
1342 *(WORD *)&(res->data[valblksizetag]) = (WORD)(res->size - valblksizetag);
1343 put_pad(res);
1344 }
1345 else if(val->type == val_block)
1346 {
1347 versionblock2res(res, val->value.block, level+1);
1348 }
1349 else
1350 {
1351 internal_error(__FILE__, __LINE__, "Invalid value indicator %d in VERSIONINFO", val->type);
1352 }
1353 }
1354
1355 /* Set blocksize */
1356 *(WORD *)&(res->data[blksizetag]) = (WORD)(res->size - blksizetag);
1357}
1358
1359/*
1360 *****************************************************************************
1361 * Function : versioninfo2res
1362 * Syntax : res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver)
1363 * Input :
1364 * name - Name/ordinal of the resource
1365 * ver - The versioninfo descriptor
1366 * Output : New .res format structure
1367 * Description :
1368 * Remarks :
1369 *****************************************************************************
1370*/
1371res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver)
1372{
1373 int restag;
1374 int rootblocksizetag;
1375 int valsizetag;
1376 int tag;
1377 res_t *res;
1378 string_t vsvi;
1379 ver_block_t *blk;
1380
1381 assert(name != NULL);
1382 assert(ver != NULL);
1383
1384 vsvi.type = str_char;
1385 vsvi.str.cstr = "VS_VERSION_INFO";
1386 vsvi.size = 15; /* Excl. termination */
1387
1388 res = new_res();
1389 restag = put_res_header(res, WRC_RT_VERSION, NULL, name, WRC_MO_MOVEABLE | WRC_MO_PURE, NULL);
1390 rootblocksizetag = res->size;
1391 put_word(res, 0); /* BlockSize filled in later */
1392 valsizetag = res->size;
1393 put_word(res, 0); /* ValueSize filled in later*/
1394 if(win32)
1395 put_word(res, 0); /* Tree-level ? */
1396 put_string(res, &vsvi, win32 ? str_unicode : str_char, TRUE);
1397 if(win32)
1398 put_pad(res);
1399 tag = res->size;
1400 put_dword(res, VS_FFI_SIGNATURE);
1401 put_dword(res, VS_FFI_STRUCVERSION);
1402 put_dword(res, (ver->filever_maj1 << 16) + (ver->filever_maj2 & 0xffff));
1403 put_dword(res, (ver->filever_min1 << 16) + (ver->filever_min2 & 0xffff));
1404 put_dword(res, (ver->prodver_maj1 << 16) + (ver->prodver_maj2 & 0xffff));
1405 put_dword(res, (ver->prodver_min1 << 16) + (ver->prodver_min2 & 0xffff));
1406 put_dword(res, ver->fileflagsmask);
1407 put_dword(res, ver->fileflags);
1408 put_dword(res, ver->fileos);
1409 put_dword(res, ver->filetype);
1410 put_dword(res, ver->filesubtype);
1411 put_dword(res, 0); /* FileDateMS */
1412 put_dword(res, 0); /* FileDateLS */
1413 /* Set ValueSize */
1414 *(WORD *)&(res->data[valsizetag]) = (WORD)(res->size - tag);
1415 /* Descend into the blocks */
1416 for(blk = ver->blocks; blk; blk = blk->next)
1417 versionblock2res(res, blk, 0);
1418 /* Set root block's size */
1419 *(WORD *)&(res->data[rootblocksizetag]) = (WORD)(res->size - rootblocksizetag);
1420
1421 SetResSize(res, restag);
1422 if(win32)
1423 put_pad(res);
1424
1425 return res;
1426}
1427
1428/*
1429 *****************************************************************************
1430 * Function : toolbaritem2res
1431 * Syntax : void toolbaritem2res(res_t *res, toolbar_item_t *tbitem)
1432 * Input :
1433 * Output : nop
1434 * Description :
1435 * Remarks : Self recursive
1436 *****************************************************************************
1437*/
1438void toolbaritem2res(res_t *res, toolbar_item_t *tbitem)
1439{
1440 toolbar_item_t *itm = tbitem;
1441 assert(win32 != 0);
1442 while(itm)
1443 {
1444 put_word(res, itm->id);
1445 itm = itm->next;
1446 }
1447
1448}
1449
1450/*
1451 *****************************************************************************
1452 * Function : toolbar2res
1453 * Syntax : res_t *toolbar2res(name_id_t *name, toolbar_t *toolbar)
1454 * Input :
1455 * name - Name/ordinal of the resource
1456 * toolbar - The toolbar descriptor
1457 * Output : New .res format structure
1458 * Description :
1459 * Remarks :
1460 *****************************************************************************
1461*/
1462res_t *toolbar2res(name_id_t *name, toolbar_t *toolbar)
1463{
1464 int restag;
1465 res_t *res;
1466 assert(name != NULL);
1467 assert(toolbar != NULL);
1468
1469 res = new_res();
1470 if(win32)
1471 {
1472 restag = put_res_header(res, WRC_RT_TOOLBAR, NULL, name, toolbar->memopt, &(toolbar->lvc));
1473
1474 put_word(res, 1); /* Menuheader: Version */
1475 put_word(res, toolbar->button_width); /* (in pixels?) */
1476 put_word(res, toolbar->button_height); /* (in pixels?) */
1477 put_word(res, toolbar->nitems);
1478 put_pad(res);
1479 toolbaritem2res(res, toolbar->items);
1480 /* Set ResourceSize */
1481 SetResSize(res, restag);
1482 put_pad(res);
1483 }
1484 else /* win16 */
1485 {
1486 /* Do not generate anything in 16-bit mode */
1487 free(res->data);
1488 free(res);
1489 return NULL;
1490 }
1491 return res;
1492}
1493
1494/*
1495 *****************************************************************************
1496 * Function : dlginit2res
1497 * Syntax : res_t *dlginit2res(name_id_t *name, dlginit_t *dit)
1498 * Input :
1499 * name - Name/ordinal of the resource
1500 * rdt - The dlginit descriptor
1501 * Output : New .res format structure
1502 * Description :
1503 * Remarks :
1504 *****************************************************************************
1505*/
1506res_t *dlginit2res(name_id_t *name, dlginit_t *dit)
1507{
1508 int restag;
1509 res_t *res;
1510 assert(name != NULL);
1511 assert(dit != NULL);
1512
1513 res = new_res();
1514 restag = put_res_header(res, WRC_RT_DLGINIT, NULL, name, dit->memopt, &(dit->lvc));
1515 put_raw_data(res, dit->data, 0);
1516 /* Set ResourceSize */
1517 SetResSize(res, restag);
1518 if(win32)
1519 put_pad(res);
1520 return res;
1521}
1522
1523/*
1524 *****************************************************************************
1525 * Function : prep_nid_for_label
1526 * Syntax : char *prep_nid_for_label(name_id_t *nid)
1527 * Input :
1528 * Output :
1529 * Description : Converts a resource name into the first 32 (or less)
1530 * characters of the name with conversions.
1531 * Remarks :
1532 *****************************************************************************
1533*/
1534#define MAXNAMELEN 32
1535char *prep_nid_for_label(name_id_t *nid)
1536{
1537 static char buf[MAXNAMELEN+1];
1538
1539 assert(nid != NULL);
1540
1541 if(nid->type == name_str && nid->name.s_name->type == str_unicode)
1542 {
1543 short *sptr;
1544 int i;
1545 sptr = nid->name.s_name->str.wstr;
1546 buf[0] = '\0';
1547 for(i = 0; *sptr && i < MAXNAMELEN; i++)
1548 {
1549 if((unsigned)*sptr < 0x80 && isprint((char)*sptr))
1550 buf[i] = *sptr++;
1551 else
1552 warning("Resourcename (str_unicode) contain unprintable characters or invalid translation, ignored");
1553 }
1554 buf[i] = '\0';
1555 }
1556 else if(nid->type == name_str && nid->name.s_name->type == str_char)
1557 {
1558 char *cptr;
1559 int i;
1560 cptr = nid->name.s_name->str.cstr;
1561 buf[0] = '\0';
1562 for(i = 0; *cptr && i < MAXNAMELEN; i++)
1563 {
1564 if((unsigned)*cptr < 0x80 && isprint(*cptr))
1565 buf[i] = *cptr++;
1566 else
1567 warning("Resourcename (str_char) contain unprintable characters, ignored");
1568 }
1569 buf[i] = '\0';
1570 }
1571 else if(nid->type == name_ord)
1572 {
1573 sprintf(buf, "%u", nid->name.i_name);
1574 }
1575 else
1576 {
1577 internal_error(__FILE__, __LINE__, "Resource name_id with invalid type %d", nid->type);
1578 }
1579 return buf;
1580}
1581#undef MAXNAMELEN
1582
1583/*
1584 *****************************************************************************
1585 * Function : make_c_name
1586 * Syntax : char *make_c_name(char *base, name_id_t *nid, language_t *lan)
1587 * Input :
1588 * Output :
1589 * Description : Converts a resource name into a valid c-identifier in the
1590 * form "_base_nid".
1591 * Remarks :
1592 *****************************************************************************
1593*/
1594char *make_c_name(char *base, name_id_t *nid, language_t *lan)
1595{
1596 int nlen;
1597 char *buf;
1598 char *ret;
1599 char lanbuf[6];
1600
1601 sprintf(lanbuf, "%d", lan ? MAKELANGID(lan->id, lan->sub) : 0);
1602 buf = prep_nid_for_label(nid);
1603 nlen = strlen(buf) + strlen(lanbuf);
1604 nlen += strlen(base) + 4; /* three time '_' and '\0' */
1605 ret = (char *)xmalloc(nlen);
1606 strcpy(ret, "_");
1607 strcat(ret, base);
1608 strcat(ret, "_");
1609 strcat(ret, buf);
1610 strcat(ret, "_");
1611 strcat(ret, lanbuf);
1612 return ret;
1613}
1614
1615/*
1616 *****************************************************************************
1617 * Function : get_c_typename
1618 * Syntax : char *get_c_typename(enum res_e type)
1619 * Input :
1620 * Output :
1621 * Description : Convert resource enum to char string to be used in c-name
1622 * creation.
1623 * Remarks :
1624 *****************************************************************************
1625*/
1626char *get_c_typename(enum res_e type)
1627{
1628 switch(type)
1629 {
1630 case res_acc: return "Acc";
1631 case res_bmp: return "Bmp";
1632 case res_cur: return "Cur";
1633 case res_curg: return "CurGrp";
1634 case res_dlg:
1635 case res_dlgex: return "Dlg";
1636 case res_fnt: return "Fnt";
1637 case res_ico: return "Ico";
1638 case res_icog: return "IcoGrp";
1639 case res_men:
1640 case res_menex: return "Men";
1641 case res_rdt: return "RCDat";
1642 case res_stt: return "StrTab";
1643 case res_usr: return "Usr";
1644 case res_msg: return "MsgTab";
1645 case res_ver: return "VerInf";
1646 case res_toolbar: return "TlBr";
1647 case res_dlginit: return "DlgInit";
1648 default: return "Oops";
1649 }
1650}
1651
1652/*
1653 *****************************************************************************
1654 * Function : resources2res
1655 * Syntax : void resources2res(resource_t *top)
1656 * Input :
1657 * top - The resource-tree to convert
1658 * Output :
1659 * Description : Convert logical resource descriptors into binary data
1660 * Remarks :
1661 *****************************************************************************
1662*/
1663void resources2res(resource_t *top)
1664{
1665 while(top)
1666 {
1667 switch(top->type)
1668 {
1669 case res_acc:
1670 if(!top->binres)
1671 top->binres = accelerator2res(top->name, top->res.acc);
1672 break;
1673 case res_bmp:
1674 if(!top->binres)
1675 top->binres = bitmap2res(top->name, top->res.bmp);
1676 break;
1677 case res_cur:
1678 if(!top->binres)
1679 top->binres = cursor2res(top->res.cur);
1680 break;
1681 case res_curg:
1682 if(!top->binres)
1683 top->binres = cursorgroup2res(top->name, top->res.curg);
1684 break;
1685 case res_dlg:
1686 if(!top->binres)
1687 top->binres = dialog2res(top->name, top->res.dlg);
1688 break;
1689 case res_dlgex:
1690 if(!top->binres)
1691 top->binres = dialogex2res(top->name, top->res.dlgex);
1692 break;
1693 case res_fnt:
1694 if(!top->binres)
1695 top->binres = font2res(top->name, top->res.fnt);
1696 break;
1697 case res_ico:
1698 if(!top->binres)
1699 top->binres = icon2res(top->res.ico);
1700 break;
1701 case res_icog:
1702 if(!top->binres)
1703 top->binres = icongroup2res(top->name, top->res.icog);
1704 break;
1705 case res_men:
1706 if(!top->binres)
1707 top->binres = menu2res(top->name, top->res.men);
1708 break;
1709 case res_menex:
1710 if(!top->binres)
1711 top->binres = menuex2res(top->name, top->res.menex);
1712 break;
1713 case res_rdt:
1714 if(!top->binres)
1715 top->binres = rcdata2res(top->name, top->res.rdt);
1716 break;
1717 case res_stt:
1718 if(!top->binres)
1719 top->binres = stringtable2res(top->res.stt);
1720 break;
1721 case res_usr:
1722 if(!top->binres)
1723 top->binres = user2res(top->name, top->res.usr);
1724 break;
1725 case res_msg:
1726 if(!top->binres)
1727 top->binres = messagetable2res(top->name, top->res.msg);
1728 break;
1729 case res_ver:
1730 if(!top->binres)
1731 top->binres = versioninfo2res(top->name, top->res.ver);
1732 break;
1733 case res_toolbar:
1734 if(!top->binres)
1735 top->binres = toolbar2res(top->name, top->res.tbt);
1736 break;
1737 case res_dlginit:
1738 if(!top->binres)
1739 top->binres = dlginit2res(top->name, top->res.dlgi);
1740 break;
1741
1742 default:
1743 internal_error(__FILE__, __LINE__, "Unknown resource type encountered %d in binary res generation", top->type);
1744 }
1745 top->c_name = make_c_name(get_c_typename(top->type), top->name, top->lan);
1746 top = top->next;
1747 }
1748}
1749
Note: See TracBrowser for help on using the repository browser.