1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 /* This file contains function that read and write Windows rc files.
23 These are text files that represent resources. */
27 #include "libiberty.h"
34 /* The default preprocessor. */
36 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
38 /* We read the directory entries in a cursor or icon file into
39 instances of this structure. */
45 /* Height of image. */
47 /* Number of colors in image. */
48 unsigned char colorcount
;
54 unsigned short planes
;
60 /* X coordinate of hotspot. */
61 unsigned short xhotspot
;
62 /* Y coordinate of hotspot. */
63 unsigned short yhotspot
;
68 /* File offset of image. */
72 /* The name of the rc file we are reading. */
76 /* The line number in the rc file. */
80 /* The pipe we are reading from, so that we can close it if we exit. */
82 static FILE *cpp_pipe
;
84 /* As we read the rc file, we attach information to this structure. */
86 static struct res_directory
*resources
;
88 /* The number of cursor resources we have written out. */
92 /* The number of font resources we have written out. */
96 /* Font directory information. */
98 struct fontdir
*fontdirs
;
100 /* Resource info to use for fontdirs. */
102 struct res_res_info fontdirs_resinfo
;
104 /* The number of icon resources we have written out. */
108 /* Local functions. */
110 static void close_pipe
PARAMS ((void));
111 static void unexpected_eof
PARAMS ((const char *));
112 static int get_word
PARAMS ((FILE *, const char *));
113 static unsigned long get_long
PARAMS ((FILE *, const char *));
115 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
116 static void define_fontdirs
PARAMS ((void));
118 /* Read an rc file. */
120 struct res_directory
*
121 read_rc_file (filename
, preprocessor
, preprocargs
, language
)
122 const char *filename
;
123 const char *preprocessor
;
124 const char *preprocargs
;
129 if (preprocessor
== NULL
)
130 preprocessor
= DEFAULT_PREPROCESSOR
;
132 if (preprocargs
== NULL
)
134 if (filename
== NULL
)
137 cmd
= xmalloc (strlen (preprocessor
)
138 + strlen (preprocargs
)
141 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
143 cpp_pipe
= popen (cmd
, FOPEN_RT
);
144 if (cpp_pipe
== NULL
)
145 fatal ("can't popen `%s': %s", cmd
, strerror (errno
));
147 xatexit (close_pipe
);
149 rc_filename
= xstrdup (filename
);
152 rcparse_set_language (language
);
156 if (pclose (cpp_pipe
) != 0)
157 fprintf (stderr
, "%s: warning: preprocessor failed\n", program_name
);
160 if (fontdirs
!= NULL
)
169 /* Close the pipe if it is open. This is called via xatexit. */
174 if (cpp_pipe
!= NULL
)
178 /* Report an error while reading an rc file. */
184 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
187 /* Issue a warning while reading an rc file. */
190 rcparse_warning (msg
)
193 fprintf (stderr
, "%s:%d: %s\n", rc_filename
, rc_lineno
, msg
);
196 /* Die if we get an unexpected end of file. */
202 fatal ("%s: unexpected EOF", msg
);
205 /* Read a 16 bit word from a file. The data is assumed to be little
218 unexpected_eof (msg
);
219 return ((b2
& 0xff) << 8) | (b1
& 0xff);
222 /* Read a 32 bit word from a file. The data is assumed to be little
237 unexpected_eof (msg
);
238 return (((((((b4
& 0xff) << 8)
244 /* Read data from a file. This is a wrapper to do error checking. */
247 get_data (e
, p
, c
, msg
)
255 got
= fread (p
, 1, c
, e
);
259 fatal ("%s: read of %lu returned %lu", msg
, c
, got
);
262 /* Define an accelerator resource. */
265 define_accelerator (id
, resinfo
, data
)
267 const struct res_res_info
*resinfo
;
268 struct accelerator
*data
;
270 struct res_resource
*r
;
272 r
= define_standard_resource (&resources
, RT_ACCELERATORS
, id
,
273 resinfo
->language
, 0);
274 r
->type
= RES_TYPE_ACCELERATOR
;
276 r
->res_info
= *resinfo
;
279 /* Define a bitmap resource. Bitmap data is stored in a file. The
280 first 14 bytes of the file are a standard header, which is not
281 included in the resource data. */
283 #define BITMAP_SKIP (14)
286 define_bitmap (id
, resinfo
, filename
)
288 const struct res_res_info
*resinfo
;
289 const char *filename
;
296 struct res_resource
*r
;
298 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
300 if (stat (real_filename
, &s
) < 0)
301 fatal ("stat failed on bitmap file `%s': %s", real_filename
,
304 data
= (unsigned char *) xmalloc (s
.st_size
- BITMAP_SKIP
);
306 for (i
= 0; i
< BITMAP_SKIP
; i
++)
309 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
312 free (real_filename
);
314 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
315 resinfo
->language
, 0);
317 r
->type
= RES_TYPE_BITMAP
;
318 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
319 r
->u
.data
.data
= data
;
320 r
->res_info
= *resinfo
;
323 /* Define a cursor resource. A cursor file may contain a set of
324 bitmaps, each representing the same cursor at various different
325 resolutions. They each get written out with a different ID. The
326 real cursor resource is then a group resource which can be used to
327 select one of the actual cursors. */
330 define_cursor (id
, resinfo
, filename
)
332 const struct res_res_info
*resinfo
;
333 const char *filename
;
338 struct icondir
*icondirs
;
340 struct res_resource
*r
;
341 struct group_cursor
*first
, **pp
;
343 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
345 /* A cursor file is basically an icon file. The start of the file
346 is a three word structure. The first word is ignored. The
347 second word is the type of data. The third word is the number of
350 get_word (e
, real_filename
);
351 type
= get_word (e
, real_filename
);
352 count
= get_word (e
, real_filename
);
354 fatal ("cursor file `%s' does not contain cursor data", real_filename
);
356 /* Read in the icon directory entries. */
358 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
360 for (i
= 0; i
< count
; i
++)
362 icondirs
[i
].width
= getc (e
);
363 icondirs
[i
].height
= getc (e
);
364 icondirs
[i
].colorcount
= getc (e
);
366 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
367 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
368 icondirs
[i
].bytes
= get_long (e
, real_filename
);
369 icondirs
[i
].offset
= get_long (e
, real_filename
);
372 unexpected_eof (real_filename
);
375 /* Define each cursor as a unique resource. */
377 first_cursor
= cursors
;
379 for (i
= 0; i
< count
; i
++)
385 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
386 fatal ("%s: fseek to %lu failed: %s", real_filename
,
387 icondirs
[i
].offset
, strerror (errno
));
389 data
= (unsigned char *) xmalloc (icondirs
[i
].bytes
);
391 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
393 c
= (struct cursor
*) xmalloc (sizeof *c
);
394 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
395 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
396 c
->length
= icondirs
[i
].bytes
;
404 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
405 resinfo
->language
, 0);
406 r
->type
= RES_TYPE_CURSOR
;
408 r
->res_info
= *resinfo
;
412 free (real_filename
);
414 /* Define a cursor group resource. */
418 for (i
= 0; i
< count
; i
++)
420 struct group_cursor
*cg
;
422 /* These manipulations of icondirs into cg are copied from rcl. */
424 cg
= (struct group_cursor
*) xmalloc (sizeof *cg
);
426 cg
->width
= icondirs
[i
].width
;
427 cg
->height
= 2 * icondirs
[i
].height
;
430 cg
->bytes
= icondirs
[i
].bytes
+ 8;
431 cg
->index
= first_cursor
+ i
+ 1;
437 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
438 resinfo
->language
, 0);
439 r
->type
= RES_TYPE_GROUP_CURSOR
;
440 r
->u
.group_cursor
= first
;
441 r
->res_info
= *resinfo
;
444 /* Define a dialog resource. */
447 define_dialog (id
, resinfo
, dialog
)
449 const struct res_res_info
*resinfo
;
450 const struct dialog
*dialog
;
453 struct res_resource
*r
;
455 copy
= (struct dialog
*) xmalloc (sizeof *copy
);
458 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
459 resinfo
->language
, 0);
460 r
->type
= RES_TYPE_DIALOG
;
462 r
->res_info
= *resinfo
;
465 /* Define a dialog control. This does not define a resource, but
466 merely allocates and fills in a structure. */
468 struct dialog_control
*
469 define_control (text
, id
, x
, y
, width
, height
, class, style
, exstyle
)
475 unsigned long height
;
478 unsigned long exstyle
;
480 struct dialog_control
*n
;
482 n
= (struct dialog_control
*) xmalloc (sizeof *n
);
486 n
->exstyle
= exstyle
;
492 n
->class.u
.id
= class;
494 res_string_to_id (&n
->text
, text
);
507 /* Define a font resource. */
510 define_font (id
, resinfo
, filename
)
512 const struct res_res_info
*resinfo
;
513 const char *filename
;
519 struct res_resource
*r
;
522 const char *device
, *face
;
525 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
527 if (stat (real_filename
, &s
) < 0)
528 fatal ("stat failed on bitmap file `%s': %s", real_filename
,
531 data
= (unsigned char *) xmalloc (s
.st_size
);
533 get_data (e
, data
, s
.st_size
, real_filename
);
536 free (real_filename
);
538 r
= define_standard_resource (&resources
, RT_FONT
, id
,
539 resinfo
->language
, 0);
541 r
->type
= RES_TYPE_FONT
;
542 r
->u
.data
.length
= s
.st_size
;
543 r
->u
.data
.data
= data
;
544 r
->res_info
= *resinfo
;
546 /* For each font resource, we must add an entry in the FONTDIR
547 resource. The FONTDIR resource includes some strings in the font
548 file. To find them, we have to do some magic on the data we have
551 offset
= ((((((data
[47] << 8)
555 if (offset
> 0 && offset
< s
.st_size
)
556 device
= (char *) data
+ offset
;
560 offset
= ((((((data
[51] << 8)
564 if (offset
> 0 && offset
< s
.st_size
)
565 face
= (char *) data
+ offset
;
571 fd
= (struct fontdir
*) xmalloc (sizeof *fd
);
574 fd
->length
= 58 + strlen (device
) + strlen (face
);
575 fd
->data
= (unsigned char *) xmalloc (fd
->length
);
577 memcpy (fd
->data
, data
, 56);
578 strcpy ((char *) fd
->data
+ 56, device
);
579 strcpy ((char *) fd
->data
+ 57 + strlen (device
), face
);
581 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
585 /* For the single fontdirs resource, we always use the resource
586 information of the last font. I don't know what else to do. */
587 fontdirs_resinfo
= *resinfo
;
590 /* Define the fontdirs resource. This is called after the entire rc
591 file has been parsed, if any font resources were seen. */
596 struct res_resource
*r
;
602 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
604 r
->type
= RES_TYPE_FONTDIR
;
605 r
->u
.fontdir
= fontdirs
;
606 r
->res_info
= fontdirs_resinfo
;
609 /* Define an icon resource. An icon file may contain a set of
610 bitmaps, each representing the same icon at various different
611 resolutions. They each get written out with a different ID. The
612 real icon resource is then a group resource which can be used to
613 select one of the actual icon bitmaps. */
616 define_icon (id
, resinfo
, filename
)
618 const struct res_res_info
*resinfo
;
619 const char *filename
;
624 struct icondir
*icondirs
;
626 struct res_resource
*r
;
627 struct group_icon
*first
, **pp
;
629 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
631 /* The start of an icon file is a three word structure. The first
632 word is ignored. The second word is the type of data. The third
633 word is the number of entries. */
635 get_word (e
, real_filename
);
636 type
= get_word (e
, real_filename
);
637 count
= get_word (e
, real_filename
);
639 fatal ("icon file `%s' does not contain icon data", real_filename
);
641 /* Read in the icon directory entries. */
643 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
645 for (i
= 0; i
< count
; i
++)
647 icondirs
[i
].width
= getc (e
);
648 icondirs
[i
].height
= getc (e
);
649 icondirs
[i
].colorcount
= getc (e
);
651 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
652 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
653 icondirs
[i
].bytes
= get_long (e
, real_filename
);
654 icondirs
[i
].offset
= get_long (e
, real_filename
);
657 unexpected_eof (real_filename
);
660 /* Define each icon as a unique resource. */
664 for (i
= 0; i
< count
; i
++)
669 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
670 fatal ("%s: fseek to %lu failed: %s", real_filename
,
671 icondirs
[i
].offset
, strerror (errno
));
673 data
= (unsigned char *) xmalloc (icondirs
[i
].bytes
);
675 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
682 r
= define_standard_resource (&resources
, RT_ICON
, name
,
683 resinfo
->language
, 0);
684 r
->type
= RES_TYPE_ICON
;
685 r
->u
.data
.length
= icondirs
[i
].bytes
;
686 r
->u
.data
.data
= data
;
687 r
->res_info
= *resinfo
;
691 free (real_filename
);
693 /* Define an icon group resource. */
697 for (i
= 0; i
< count
; i
++)
699 struct group_icon
*cg
;
701 /* FIXME: rcl sets planes and bits based on colors, rather than
702 just copying the values from the file. */
704 cg
= (struct group_icon
*) xmalloc (sizeof *cg
);
706 cg
->width
= icondirs
[i
].width
;
707 cg
->height
= icondirs
[i
].height
;
708 cg
->colors
= icondirs
[i
].colorcount
;
709 cg
->planes
= icondirs
[i
].u
.icon
.planes
;
710 cg
->bits
= icondirs
[i
].u
.icon
.bits
;
711 cg
->bytes
= icondirs
[i
].bytes
;
712 cg
->index
= first_icon
+ i
+ 1;
718 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
719 resinfo
->language
, 0);
720 r
->type
= RES_TYPE_GROUP_ICON
;
721 r
->u
.group_icon
= first
;
722 r
->res_info
= *resinfo
;
725 /* Define a menu resource. */
728 define_menu (id
, resinfo
, menuitems
)
730 const struct res_res_info
*resinfo
;
731 struct menuitem
*menuitems
;
733 struct res_resource
*r
;
735 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
736 r
->type
= RES_TYPE_MENU
;
737 r
->u
.menu
= menuitems
;
738 r
->res_info
= *resinfo
;
741 /* Define a menu item. This does not define a resource, but merely
742 allocates and fills in a structure. */
745 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
751 struct menuitem
*menuitems
;
755 mi
= (struct menuitem
*) xmalloc (sizeof *mi
);
762 mi
->popup
= menuitems
;
766 /* Define a messagetable resource. */
769 define_messagetable (id
, resinfo
, filename
)
771 const struct res_res_info
*resinfo
;
772 const char *filename
;
778 struct res_resource
*r
;
780 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
783 if (stat (real_filename
, &s
) < 0)
784 fatal ("stat failed on bitmap file `%s': %s", real_filename
,
787 data
= (unsigned char *) xmalloc (s
.st_size
);
789 get_data (e
, data
, s
.st_size
, real_filename
);
792 free (real_filename
);
794 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
795 resinfo
->language
, 0);
797 r
->type
= RES_TYPE_MESSAGETABLE
;
798 r
->u
.data
.length
= s
.st_size
;
799 r
->u
.data
.data
= data
;
800 r
->res_info
= *resinfo
;
803 /* Define an rcdata resource. */
806 define_rcdata (id
, resinfo
, data
)
808 const struct res_res_info
*resinfo
;
809 struct rcdata_data
*data
;
811 struct res_resource
*r
;
813 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
814 resinfo
->language
, 0);
815 r
->type
= RES_TYPE_RCDATA
;
817 r
->res_info
= *resinfo
;
820 /* Add an rcdata_item to an rcdata resource. */
823 append_rcdata_item (data
, item
)
824 struct rcdata_data
*data
;
825 struct rcdata_item
*item
;
829 data
= (struct rcdata_data
*) xmalloc (sizeof *data
);
835 data
->last
->next
= item
;
842 /* Add a string to an rcdata resource. */
845 append_rcdata_string (data
, string
)
846 struct rcdata_data
*data
;
849 struct rcdata_item
*ri
;
851 ri
= (struct rcdata_item
*) xmalloc (sizeof *ri
);
853 ri
->type
= RCDATA_STRING
;
854 ri
->u
.string
= string
;
856 return append_rcdata_item (data
, ri
);
859 /* Add a number to an rcdata resource. */
862 append_rcdata_number (data
, val
, dword
)
863 struct rcdata_data
*data
;
867 struct rcdata_item
*ri
;
869 ri
= (struct rcdata_item
*) xmalloc (sizeof *ri
);
871 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
874 return append_rcdata_item (data
, ri
);
877 /* Define a stringtable resource. This is called for each string
878 which appears in a STRINGTABLE statement. */
881 define_stringtable (resinfo
, stringid
, string
)
882 const struct res_res_info
*resinfo
;
883 unsigned long stringid
;
887 struct res_resource
*r
;
890 id
.u
.id
= stringid
>> 4;
891 r
= define_standard_resource (&resources
, RT_STRING
, id
,
892 resinfo
->language
, 1);
894 if (r
->type
== RES_TYPE_UNINITIALIZED
)
898 r
->type
= RES_TYPE_STRINGTABLE
;
899 r
->u
.stringtable
= ((struct stringtable
*)
900 xmalloc (sizeof (struct stringtable
)));
901 for (i
= 0; i
< 16; i
++)
903 r
->u
.stringtable
->strings
[i
].length
= 0;
904 r
->u
.stringtable
->strings
[i
].string
= NULL
;
907 r
->res_info
= *resinfo
;
910 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
911 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
916 /* Define a user data resource where the data is in the rc file. */
919 define_user_data (id
, type
, resinfo
, data
)
922 const struct res_res_info
*resinfo
;
923 struct rcdata_data
*data
;
925 struct res_id ids
[3];
926 struct res_resource
*r
;
931 ids
[2].u
.id
= resinfo
->language
;
933 r
= define_resource (&resources
, 3, ids
, 0);
934 r
->type
= RES_TYPE_USERDATA
;
935 r
->u
.userdata
= data
;
936 r
->res_info
= *resinfo
;
939 /* Define a user data resource where the data is in a file. */
942 define_user_file (id
, type
, resinfo
, filename
)
945 const struct res_res_info
*resinfo
;
946 const char *filename
;
952 struct res_id ids
[3];
953 struct res_resource
*r
;
955 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
957 if (stat (real_filename
, &s
) < 0)
958 fatal ("stat failed on bitmap file `%s': %s", real_filename
,
961 data
= (unsigned char *) xmalloc (s
.st_size
);
963 get_data (e
, data
, s
.st_size
, real_filename
);
966 free (real_filename
);
971 ids
[2].u
.id
= resinfo
->language
;
973 r
= define_resource (&resources
, 3, ids
, 0);
974 r
->type
= RES_TYPE_USERDATA
;
975 r
->u
.userdata
= ((struct rcdata_data
*)
976 xmalloc (sizeof (struct rcdata_data
)));
977 r
->u
.userdata
->first
= ((struct rcdata_item
*)
978 xmalloc (sizeof (struct rcdata_item
)));
979 r
->u
.userdata
->last
= r
->u
.userdata
->first
;
980 r
->u
.userdata
->first
->next
= NULL
;
981 r
->u
.userdata
->first
->type
= RCDATA_BUFFER
;
982 r
->u
.userdata
->first
->u
.buffer
.length
= s
.st_size
;
983 r
->u
.userdata
->first
->u
.buffer
.data
= data
;
984 r
->res_info
= *resinfo
;
987 /* Define a versioninfo resource. */
990 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
993 struct fixed_versioninfo
*fixedverinfo
;
994 struct ver_info
*verinfo
;
996 struct res_resource
*r
;
998 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
999 r
->type
= RES_TYPE_VERSIONINFO
;
1000 r
->u
.versioninfo
= ((struct versioninfo
*)
1001 xmalloc (sizeof (struct versioninfo
)));
1002 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1003 r
->u
.versioninfo
->var
= verinfo
;
1004 r
->res_info
.language
= language
;
1007 /* Add string version info to a list of version information. */
1010 append_ver_stringfileinfo (verinfo
, language
, strings
)
1011 struct ver_info
*verinfo
;
1013 struct ver_stringinfo
*strings
;
1015 struct ver_info
*vi
, **pp
;
1017 vi
= (struct ver_info
*) xmalloc (sizeof *vi
);
1019 vi
->type
= VERINFO_STRING
;
1020 unicode_from_ascii ((unsigned short *) NULL
, &vi
->u
.string
.language
,
1023 vi
->u
.string
.strings
= strings
;
1025 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1032 /* Add variable version info to a list of version information. */
1035 append_ver_varfileinfo (verinfo
, key
, var
)
1036 struct ver_info
*verinfo
;
1038 struct ver_varinfo
*var
;
1040 struct ver_info
*vi
, **pp
;
1042 vi
= (struct ver_info
*) xmalloc (sizeof *vi
);
1044 vi
->type
= VERINFO_VAR
;
1045 unicode_from_ascii ((unsigned short *) NULL
, &vi
->u
.var
.key
, key
);
1047 vi
->u
.var
.var
= var
;
1049 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1056 /* Append version string information to a list. */
1058 struct ver_stringinfo
*
1059 append_verval (strings
, key
, value
)
1060 struct ver_stringinfo
*strings
;
1064 struct ver_stringinfo
*vs
, **pp
;
1066 vs
= (struct ver_stringinfo
*) xmalloc (sizeof *vs
);
1068 unicode_from_ascii ((unsigned short *) NULL
, &vs
->key
, key
);
1070 unicode_from_ascii ((unsigned short *) NULL
, &vs
->value
, value
);
1073 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1080 /* Append version variable information to a list. */
1082 struct ver_varinfo
*
1083 append_vertrans (var
, language
, charset
)
1084 struct ver_varinfo
*var
;
1085 unsigned long language
;
1086 unsigned long charset
;
1088 struct ver_varinfo
*vv
, **pp
;
1090 vv
= (struct ver_varinfo
*) xmalloc (sizeof *vv
);
1092 vv
->language
= language
;
1093 vv
->charset
= charset
;
1095 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1102 /* Local functions used to write out an rc file. */
1104 static void indent
PARAMS ((FILE *, int));
1105 static void write_rc_directory
1106 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1107 const struct res_id
*, int *, int));
1108 static void write_rc_subdir
1109 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1110 const struct res_id
*, int *, int));
1111 static void write_rc_resource
1112 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1113 const struct res_resource
*, int *));
1114 static void write_rc_accelerators
1115 PARAMS ((FILE *, const struct accelerator
*));
1116 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1117 static void write_rc_group_cursor
1118 PARAMS ((FILE *, const struct group_cursor
*));
1119 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1120 static void write_rc_dialog_control
1121 PARAMS ((FILE *, const struct dialog_control
*));
1122 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1123 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1124 static void write_rc_menu
PARAMS ((FILE *, const struct menuitem
*, int, int));
1125 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_data
*, int));
1126 static void write_rc_stringtable
1127 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1128 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1129 static void write_rc_filedata
1130 PARAMS ((FILE *, unsigned long, const unsigned char *));
1132 /* Indent a given number of spaces. */
1141 for (i
= 0; i
< c
; i
++)
1145 /* Dump the resources we have read in the format of an rc file.
1147 Actually, we don't use the format of an rc file, because it's way
1148 too much of a pain--for example, we'd have to write icon resources
1149 into a file and refer to that file. We just generate a readable
1150 format that kind of looks like an rc file, and is useful for
1151 understanding the contents of a resource file. Someday we may want
1152 to generate an rc file which the rc compiler can read; if that day
1153 comes, this code will have to be fixed up. */
1156 write_rc_file (filename
, resources
)
1157 const char *filename
;
1158 const struct res_directory
*resources
;
1163 if (filename
== NULL
)
1167 e
= fopen (filename
, FOPEN_WT
);
1169 fatal ("can't open `%s' for output: %s", filename
, strerror (errno
));
1173 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1174 (const struct res_id
*) NULL
, &language
, 1);
1177 /* Write out a directory. E is the file to write to. RD is the
1178 directory. TYPE is a pointer to the level 1 ID which serves as the
1179 resource type. NAME is a pointer to the level 2 ID which serves as
1180 an individual resource name. LANGUAGE is a pointer to the current
1181 language. LEVEL is the level in the tree. */
1184 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1186 const struct res_directory
*rd
;
1187 const struct res_id
*type
;
1188 const struct res_id
*name
;
1192 const struct res_entry
*re
;
1194 /* Print out some COFF information that rc files can't represent. */
1197 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1198 if (rd
->characteristics
!= 0)
1199 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1200 if (rd
->major
!= 0 || rd
->minor
!= 0)
1201 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1203 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1208 /* If we're at level 1, the key of this resource is the
1209 type. This normally duplicates the information we have
1210 stored with the resource itself, but we need to remember
1211 the type if this is a user define resource type. */
1216 /* If we're at level 2, the key of this resource is the name
1217 we are going to use in the rc printout. */
1222 /* If we're at level 3, then this key represents a language.
1223 Use it to update the current language. */
1225 && re
->id
.u
.id
!= *language
1226 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1228 fprintf (e
, "LANGUAGE %lu, %lu\n",
1229 re
->id
.u
.id
& 0xff, (re
->id
.u
.id
>> 8) & 0xff);
1230 *language
= re
->id
.u
.id
;
1239 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1244 /* This is the normal case: the three levels are
1245 TYPE/NAME/LANGUAGE. NAME will have been set at level
1246 2, and represents the name to use. We probably just
1247 set LANGUAGE, and it will probably match what the
1248 resource itself records if anything. */
1249 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1253 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1254 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1261 /* Write out a subdirectory entry. E is the file to write to. RE is
1262 the subdirectory entry. TYPE and NAME are pointers to higher level
1263 IDs, or NULL. LANGUAGE is a pointer to the current language.
1264 LEVEL is the level in the tree. */
1267 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1269 const struct res_entry
*re
;
1270 const struct res_id
*type
;
1271 const struct res_id
*name
;
1279 fprintf (e
, "// Type: ");
1281 res_id_print (e
, re
->id
, 1);
1286 switch (re
->id
.u
.id
)
1288 case RT_CURSOR
: s
= "cursor"; break;
1289 case RT_BITMAP
: s
= "bitmap"; break;
1290 case RT_ICON
: s
= "icon"; break;
1291 case RT_MENU
: s
= "menu"; break;
1292 case RT_DIALOG
: s
= "dialog"; break;
1293 case RT_STRING
: s
= "stringtable"; break;
1294 case RT_FONTDIR
: s
= "fontdir"; break;
1295 case RT_FONT
: s
= "font"; break;
1296 case RT_ACCELERATORS
: s
= "accelerators"; break;
1297 case RT_RCDATA
: s
= "rcdata"; break;
1298 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1299 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1300 case RT_GROUP_ICON
: s
= "group icon"; break;
1301 case RT_VERSION
: s
= "version"; break;
1302 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1303 case RT_PLUGPLAY
: s
= "plugplay"; break;
1304 case RT_VXD
: s
= "vxd"; break;
1305 case RT_ANICURSOR
: s
= "anicursor"; break;
1306 case RT_ANIICON
: s
= "aniicon"; break;
1307 default: s
= NULL
; break;
1311 fprintf (e
, "%s", s
);
1313 res_id_print (e
, re
->id
, 1);
1319 fprintf (e
, "// Name: ");
1320 res_id_print (e
, re
->id
, 1);
1325 fprintf (e
, "// Language: ");
1326 res_id_print (e
, re
->id
, 1);
1331 fprintf (e
, "// Level %d: ", level
);
1332 res_id_print (e
, re
->id
, 1);
1336 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1339 /* Write out a single resource. E is the file to write to. TYPE is a
1340 pointer to the type of the resource. NAME is a pointer to the name
1341 of the resource; it will be NULL if there is a level mismatch. RES
1342 is the resource data. LANGUAGE is a pointer to the current
1346 write_rc_resource (e
, type
, name
, res
, language
)
1348 const struct res_id
*type
;
1349 const struct res_id
*name
;
1350 const struct res_resource
*res
;
1364 case RES_TYPE_ACCELERATOR
:
1366 rt
= RT_ACCELERATORS
;
1369 case RES_TYPE_BITMAP
:
1374 case RES_TYPE_CURSOR
:
1379 case RES_TYPE_GROUP_CURSOR
:
1381 rt
= RT_GROUP_CURSOR
;
1384 case RES_TYPE_DIALOG
:
1385 if (extended_dialog (res
->u
.dialog
))
1397 case RES_TYPE_FONTDIR
:
1407 case RES_TYPE_GROUP_ICON
:
1413 if (extended_menu (res
->u
.menu
))
1426 case RES_TYPE_MESSAGETABLE
:
1428 rt
= RT_MESSAGETABLE
;
1431 case RES_TYPE_RCDATA
:
1436 case RES_TYPE_STRINGTABLE
:
1441 case RES_TYPE_USERDATA
:
1446 case RES_TYPE_VERSIONINFO
:
1454 && (type
->named
|| type
->u
.id
!= rt
))
1456 fprintf (e
, "// Unexpected resource type mismatch: ");
1457 res_id_print (e
, *type
, 1);
1458 fprintf (e
, " != %d", rt
);
1461 if (res
->coff_info
.codepage
!= 0)
1462 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1463 if (res
->coff_info
.reserved
!= 0)
1464 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1467 res_id_print (e
, *name
, 0);
1469 fprintf (e
, "??Unknown-Name??");
1473 fprintf (e
, "%s", s
);
1474 else if (type
!= NULL
)
1475 res_id_print (e
, *type
, 0);
1477 fprintf (e
, "??Unknown-Type??");
1479 if (res
->res_info
.memflags
!= 0)
1481 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1482 fprintf (e
, " MOVEABLE");
1483 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1484 fprintf (e
, " PURE");
1485 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1486 fprintf (e
, " PRELOAD");
1487 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1488 fprintf (e
, " DISCARDABLE");
1491 if (res
->type
== RES_TYPE_DIALOG
)
1493 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1494 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1495 if (res
->u
.dialog
->ex
!= NULL
1496 && res
->u
.dialog
->ex
->help
!= 0)
1497 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1502 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1503 || res
->res_info
.characteristics
!= 0
1504 || res
->res_info
.version
!= 0)
1510 case RES_TYPE_ACCELERATOR
:
1511 case RES_TYPE_DIALOG
:
1513 case RES_TYPE_RCDATA
:
1514 case RES_TYPE_STRINGTABLE
:
1523 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1524 fprintf (e
, "%sLANGUAGE %d, %d\n",
1525 modifiers
? "// " : "",
1526 res
->res_info
.language
& 0xff,
1527 (res
->res_info
.language
>> 8) & 0xff);
1528 if (res
->res_info
.characteristics
!= 0)
1529 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1530 modifiers
? "// " : "",
1531 res
->res_info
.characteristics
);
1532 if (res
->res_info
.version
!= 0)
1533 fprintf (e
, "%sVERSION %lu\n",
1534 modifiers
? "// " : "",
1535 res
->res_info
.version
);
1543 case RES_TYPE_ACCELERATOR
:
1544 write_rc_accelerators (e
, res
->u
.acc
);
1547 case RES_TYPE_CURSOR
:
1548 write_rc_cursor (e
, res
->u
.cursor
);
1551 case RES_TYPE_GROUP_CURSOR
:
1552 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1555 case RES_TYPE_DIALOG
:
1556 write_rc_dialog (e
, res
->u
.dialog
);
1559 case RES_TYPE_FONTDIR
:
1560 write_rc_fontdir (e
, res
->u
.fontdir
);
1563 case RES_TYPE_GROUP_ICON
:
1564 write_rc_group_icon (e
, res
->u
.group_icon
);
1568 write_rc_menu (e
, res
->u
.menu
, menuex
, 0);
1571 case RES_TYPE_RCDATA
:
1572 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1575 case RES_TYPE_STRINGTABLE
:
1576 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1579 case RES_TYPE_USERDATA
:
1580 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1583 case RES_TYPE_VERSIONINFO
:
1584 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1587 case RES_TYPE_BITMAP
:
1590 case RES_TYPE_MESSAGETABLE
:
1591 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1596 /* Write out accelerator information. */
1599 write_rc_accelerators (e
, accelerators
)
1601 const struct accelerator
*accelerators
;
1603 const struct accelerator
*acc
;
1605 fprintf (e
, "BEGIN\n");
1606 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1612 if ((acc
->key
& 0x7f) == acc
->key
1613 && isprint ((unsigned char) acc
->key
)
1614 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1616 fprintf (e
, "\"%c\"", acc
->key
);
1621 fprintf (e
, "%d", acc
->key
);
1625 fprintf (e
, ", %d", acc
->id
);
1629 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1630 fprintf (e
, ", VIRTKEY");
1632 fprintf (e
, ", ASCII");
1635 if ((acc
->flags
& ACC_SHIFT
) != 0)
1636 fprintf (e
, ", SHIFT");
1637 if ((acc
->flags
& ACC_CONTROL
) != 0)
1638 fprintf (e
, ", CONTROL");
1639 if ((acc
->flags
& ACC_ALT
) != 0)
1640 fprintf (e
, ", ALT");
1645 fprintf (e
, "END\n");
1648 /* Write out cursor information. This would normally be in a separate
1649 file, which the rc file would include. */
1652 write_rc_cursor (e
, cursor
)
1654 const struct cursor
*cursor
;
1656 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
1658 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
1661 /* Write out group cursor data. This would normally be built from the
1665 write_rc_group_cursor (e
, group_cursor
)
1667 const struct group_cursor
*group_cursor
;
1669 const struct group_cursor
*gc
;
1671 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
1673 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
1674 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
1675 fprintf (e
, "// data bytes: %lu; index: %d\n",
1676 gc
->bytes
, gc
->index
);
1680 /* Write dialog data. */
1683 write_rc_dialog (e
, dialog
)
1685 const struct dialog
*dialog
;
1687 const struct dialog_control
*control
;
1689 if (dialog
->style
!= 0)
1690 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
1691 if (dialog
->exstyle
!= 0)
1692 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
1693 if (dialog
->class.named
|| dialog
->class.u
.id
!= 0)
1695 fprintf (e
, "CLASS ");
1696 res_id_print (e
, dialog
->class, 0);
1699 if (dialog
->caption
!= NULL
)
1700 fprintf (e
, "CAPTION \"%s\"\n", dialog
->caption
);
1701 if (dialog
->menu
.named
|| dialog
->menu
.u
.id
!= 0)
1703 fprintf (e
, "MENU ");
1704 res_id_print (e
, dialog
->menu
, 0);
1707 if (dialog
->font
!= NULL
)
1709 fprintf (e
, "FONT %d, \"%s\"", dialog
->pointsize
, dialog
->font
);
1710 if (dialog
->ex
!= NULL
1711 && (dialog
->ex
->weight
!= 0 || dialog
->ex
->italic
!= 0))
1712 fprintf (e
, ", %d, %d", dialog
->ex
->weight
, dialog
->ex
->italic
);
1716 fprintf (e
, "BEGIN\n");
1718 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
1719 write_rc_dialog_control (e
, control
);
1721 fprintf (e
, "END\n");
1724 /* For each predefined control keyword, this table provides the class
1730 unsigned short class;
1731 unsigned long style
;
1734 static const struct control_info control_info
[] =
1736 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
1737 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
1738 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
1739 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
1740 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
1741 { "CTEXT", CTL_STATIC
, SS_CENTER
},
1742 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
1743 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
1744 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
1745 { "ICON", CTL_STATIC
, SS_ICON
},
1746 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
1747 { "LTEXT", CTL_STATIC
, SS_LEFT
},
1748 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
1749 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
1750 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
1751 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
1752 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
1753 { "STATE3", CTL_BUTTON
, BS_3STATE
},
1754 /* It's important that USERBUTTON come after all the other button
1755 types, so that it won't be matched too early. */
1756 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
1760 /* Write a dialog control. */
1763 write_rc_dialog_control (e
, control
)
1765 const struct dialog_control
*control
;
1767 const struct control_info
*ci
;
1771 if (control
->class.named
)
1775 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
1776 if (ci
->class == control
->class.u
.id
1777 && (ci
->style
== (unsigned long) -1
1778 || ci
->style
== (control
->style
& 0xff)))
1782 if (ci
->name
!= NULL
)
1783 fprintf (e
, "%s", ci
->name
);
1785 fprintf (e
, "CONTROL");
1787 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
1790 res_id_print (e
, control
->text
, 1);
1794 fprintf (e
, " %d, ", control
->id
);
1796 if (ci
->name
== NULL
)
1798 res_id_print (e
, control
->class, 0);
1799 fprintf (e
, ", 0x%lx, ", control
->style
);
1802 fprintf (e
, "%d, %d", control
->x
, control
->y
);
1804 if (control
->style
!= SS_ICON
1805 || control
->exstyle
!= 0
1806 || control
->width
!= 0
1807 || control
->height
!= 0
1808 || control
->help
!= 0)
1810 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
1812 /* FIXME: We don't need to print the style if it is the default.
1813 More importantly, in certain cases we actually need to turn
1814 off parts of the forced style, by using NOT. */
1815 fprintf (e
, ", 0x%lx", control
->style
);
1817 if (control
->exstyle
!= 0 || control
->help
!= 0)
1818 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
1823 if (control
->data
!= NULL
)
1824 write_rc_rcdata (e
, control
->data
, 2);
1827 /* Write out font directory data. This would normally be built from
1831 write_rc_fontdir (e
, fontdir
)
1833 const struct fontdir
*fontdir
;
1835 const struct fontdir
*fc
;
1837 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
1839 fprintf (e
, "// Font index: %d\n", fc
->index
);
1840 write_rc_filedata (e
, fc
->length
, fc
->data
);
1844 /* Write out group icon data. This would normally be built from the
1848 write_rc_group_icon (e
, group_icon
)
1850 const struct group_icon
*group_icon
;
1852 const struct group_icon
*gi
;
1854 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
1856 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1857 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
1858 fprintf (e
, "// data bytes: %lu; index: %d\n",
1859 gi
->bytes
, gi
->index
);
1863 /* Write out a menu resource. */
1866 write_rc_menu (e
, menuitems
, menuex
, ind
)
1868 const struct menuitem
*menuitems
;
1872 const struct menuitem
*mi
;
1875 fprintf (e
, "BEGIN\n");
1877 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
1879 indent (e
, ind
+ 2);
1881 if (mi
->popup
== NULL
)
1882 fprintf (e
, "MENUITEM");
1884 fprintf (e
, "POPUP");
1887 && mi
->popup
== NULL
1892 fprintf (e
, " SEPARATOR\n");
1896 if (mi
->text
== NULL
)
1897 fprintf (e
, " \"\"");
1899 fprintf (e
, " \"%s\"", mi
->text
);
1903 if (mi
->popup
== NULL
)
1904 fprintf (e
, ", %d", mi
->id
);
1906 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
1907 fprintf (e
, ", CHECKED");
1908 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
1909 fprintf (e
, ", GRAYED");
1910 if ((mi
->type
& MENUITEM_HELP
) != 0)
1911 fprintf (e
, ", HELP");
1912 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
1913 fprintf (e
, ", INACTIVE");
1914 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
1915 fprintf (e
, ", MENUBARBREAK");
1916 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
1917 fprintf (e
, ", MENUBREAK");
1921 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
1923 fprintf (e
, ", %d", mi
->id
);
1924 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
1926 fprintf (e
, ", %lu", mi
->type
);
1927 if (mi
->state
!= 0 || mi
->help
!= 0)
1929 fprintf (e
, ", %lu", mi
->state
);
1931 fprintf (e
, ", %lu", mi
->help
);
1939 if (mi
->popup
!= NULL
)
1940 write_rc_menu (e
, mi
->popup
, menuex
, ind
+ 2);
1944 fprintf (e
, "END\n");
1947 /* Write out an rcdata resource. This is also used for other types of
1948 resources that need to print arbitrary data. */
1951 write_rc_rcdata (e
, rcdata
, ind
)
1953 const struct rcdata_data
*rcdata
;
1956 const struct rcdata_item
*ri
;
1959 fprintf (e
, "BEGIN\n");
1961 for (ri
= rcdata
->first
; ri
!= NULL
; ri
= ri
->next
)
1963 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
1966 indent (e
, ind
+ 2);
1974 fprintf (e
, "%d", ri
->u
.word
);
1978 fprintf (e
, "%luL", ri
->u
.dword
);
1982 fprintf (e
, "\"%s\"", ri
->u
.string
);
1985 case RCDATA_WSTRING
:
1987 unicode_print (e
, ri
->u
.wstring
, -1);
1996 /* Assume little endian data. */
1999 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2003 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2004 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2005 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2006 | ri
->u
.buffer
.data
[i
]);
2014 fprintf (e
, "%luL", l
);
2017 if (i
+ 1 < ri
->u
.buffer
.length
)
2021 i
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2029 fprintf (e
, "%d", i
);
2033 if (i
< ri
->u
.buffer
.length
)
2042 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2043 && isprint (ri
->u
.buffer
.data
[i
]))
2044 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2046 fprintf (e
, "\"\%03o\"", ri
->u
.buffer
.data
[i
]);
2053 if (ri
->next
!= NULL
)
2059 fprintf (e
, "END\n");
2062 /* Write out a stringtable resource. */
2065 write_rc_stringtable (e
, name
, stringtable
)
2067 const struct res_id
*name
;
2068 const struct stringtable
*stringtable
;
2070 unsigned long offset
;
2073 if (name
!= NULL
&& ! name
->named
)
2074 offset
= name
->u
.id
<< 4;
2077 fprintf (e
, "// %s string table name\n",
2078 name
== NULL
? "Missing" : "Invalid");
2082 fprintf (e
, "BEGIN\n");
2084 for (i
= 0; i
< 16; i
++)
2086 if (stringtable
->strings
[i
].length
!= 0)
2088 fprintf (e
, " %lu, \"", offset
+ i
);
2089 unicode_print (e
, stringtable
->strings
[i
].string
,
2090 stringtable
->strings
[i
].length
);
2091 fprintf (e
, "\"\n");
2095 fprintf (e
, "END\n");
2098 /* Write out a versioninfo resource. */
2101 write_rc_versioninfo (e
, versioninfo
)
2103 const struct versioninfo
*versioninfo
;
2105 const struct fixed_versioninfo
*f
;
2106 const struct ver_info
*vi
;
2108 f
= versioninfo
->fixed
;
2109 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2110 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2111 (f
->file_version_ms
>> 16) & 0xffff,
2112 f
->file_version_ms
& 0xffff,
2113 (f
->file_version_ls
>> 16) & 0xffff,
2114 f
->file_version_ls
& 0xffff);
2115 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2116 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2117 (f
->product_version_ms
>> 16) & 0xffff,
2118 f
->product_version_ms
& 0xffff,
2119 (f
->product_version_ls
>> 16) & 0xffff,
2120 f
->product_version_ls
& 0xffff);
2121 if (f
->file_flags_mask
!= 0)
2122 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2123 if (f
->file_flags
!= 0)
2124 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2125 if (f
->file_os
!= 0)
2126 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2127 if (f
->file_type
!= 0)
2128 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2129 if (f
->file_subtype
!= 0)
2130 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2131 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2132 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2134 fprintf (e
, "BEGIN\n");
2136 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2140 case VERINFO_STRING
:
2142 const struct ver_stringinfo
*vs
;
2144 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2145 fprintf (e
, " BEGIN\n");
2146 fprintf (e
, " BLOCK \"");
2147 unicode_print (e
, vi
->u
.string
.language
, -1);
2148 fprintf (e
, "\"\n");
2149 fprintf (e
, " BEGIN\n");
2151 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2153 fprintf (e
, " VALUE \"");
2154 unicode_print (e
, vs
->key
, -1);
2155 fprintf (e
, "\", \"");
2156 unicode_print (e
, vs
->value
, -1);
2157 fprintf (e
, "\"\n");
2160 fprintf (e
, " END\n");
2161 fprintf (e
, " END\n");
2167 const struct ver_varinfo
*vv
;
2169 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2170 fprintf (e
, " BEGIN\n");
2171 fprintf (e
, " VALUE \"");
2172 unicode_print (e
, vi
->u
.var
.key
, -1);
2175 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2176 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2179 fprintf (e
, "\n END\n");
2186 fprintf (e
, "END\n");
2189 /* Write out data which would normally be read from a file. */
2192 write_rc_filedata (e
, length
, data
)
2194 unsigned long length
;
2195 const unsigned char *data
;
2199 for (i
= 0; i
+ 15 < length
; i
+= 16)
2201 fprintf (e
, "// %4lx: ", i
);
2202 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2203 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2204 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2205 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2206 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2207 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2212 fprintf (e
, "// %4lx:", i
);
2215 fprintf (e
, " %02x", data
[i
]);