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

Last change on this file since 3669 was 3426, checked in by sandervl, 25 years ago

update with latest wine code

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