1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999 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 functions that read and write Windows rc files.
23 These are text files that represent resources. */
27 #include "libiberty.h"
34 #if defined (_WIN32) && ! defined (__CYGWIN32__)
36 #define pclose _pclose
39 /* The default preprocessor. */
41 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
43 /* We read the directory entries in a cursor or icon file into
44 instances of this structure. */
50 /* Height of image. */
52 /* Number of colors in image. */
53 unsigned char colorcount
;
59 unsigned short planes
;
65 /* X coordinate of hotspot. */
66 unsigned short xhotspot
;
67 /* Y coordinate of hotspot. */
68 unsigned short yhotspot
;
73 /* File offset of image. */
77 /* The name of the rc file we are reading. */
81 /* The line number in the rc file. */
85 /* The pipe we are reading from, so that we can close it if we exit. */
87 static FILE *cpp_pipe
;
89 /* As we read the rc file, we attach information to this structure. */
91 static struct res_directory
*resources
;
93 /* The number of cursor resources we have written out. */
97 /* The number of font resources we have written out. */
101 /* Font directory information. */
103 struct fontdir
*fontdirs
;
105 /* Resource info to use for fontdirs. */
107 struct res_res_info fontdirs_resinfo
;
109 /* The number of icon resources we have written out. */
113 /* Local functions. */
115 static FILE *look_for_default
PARAMS ((char *, const char *, int,
116 const char *, const char *));
117 static void close_pipe
PARAMS ((void));
118 static void unexpected_eof
PARAMS ((const char *));
119 static int get_word
PARAMS ((FILE *, const char *));
120 static unsigned long get_long
PARAMS ((FILE *, const char *));
122 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
123 static void define_fontdirs
PARAMS ((void));
125 /* look for the preprocessor program */
128 look_for_default (cmd
, prefix
, end_prefix
, preprocargs
, filename
)
132 const char *preprocargs
;
133 const char *filename
;
139 strcpy (cmd
, prefix
);
141 sprintf (cmd
+ end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
142 space
= strchr (cmd
+ end_prefix
, ' ');
146 if (strchr (cmd
, '/'))
148 found
= (stat (cmd
, &s
) == 0
149 #ifdef HAVE_EXECUTABLE_SUFFIX
150 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
157 fprintf (stderr
, "Tried `%s'\n", cmd
);
162 strcpy (cmd
, prefix
);
164 sprintf (cmd
+ end_prefix
, "%s %s %s",
165 DEFAULT_PREPROCESSOR
, preprocargs
, filename
);
168 fprintf (stderr
, "Using `%s'\n", cmd
);
170 cpp_pipe
= popen (cmd
, FOPEN_RT
);
174 /* Read an rc file. */
176 struct res_directory
*
177 read_rc_file (filename
, preprocessor
, preprocargs
, language
)
178 const char *filename
;
179 const char *preprocessor
;
180 const char *preprocargs
;
185 if (preprocargs
== NULL
)
187 if (filename
== NULL
)
192 cmd
= xmalloc (strlen (preprocessor
)
193 + strlen (preprocargs
)
196 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
198 cpp_pipe
= popen (cmd
, FOPEN_RT
);
202 char *dash
, *slash
, *cp
;
204 preprocessor
= DEFAULT_PREPROCESSOR
;
206 cmd
= xmalloc (strlen (program_name
)
207 + strlen (preprocessor
)
208 + strlen (preprocargs
)
210 #ifdef HAVE_EXECUTABLE_SUFFIX
211 + strlen (EXECUTABLE_SUFFIX
)
217 for (cp
= program_name
; *cp
; cp
++)
222 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
223 *cp
== ':' || *cp
== '\\' ||
236 /* First, try looking for a prefixed gcc in the windres
237 directory, with the same prefix as windres */
239 cpp_pipe
= look_for_default (cmd
, program_name
, dash
-program_name
+1,
240 preprocargs
, filename
);
243 if (slash
&& !cpp_pipe
)
245 /* Next, try looking for a gcc in the same directory as
248 cpp_pipe
= look_for_default (cmd
, program_name
, slash
-program_name
+1,
249 preprocargs
, filename
);
254 /* Sigh, try the default */
256 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
260 if (cpp_pipe
== NULL
)
261 fatal (_("can't popen `%s': %s"), cmd
, strerror (errno
));
264 xatexit (close_pipe
);
266 rc_filename
= xstrdup (filename
);
269 rcparse_set_language (language
);
273 if (pclose (cpp_pipe
) != 0)
274 fprintf (stderr
, _("%s: warning: preprocessor failed\n"), program_name
);
277 if (fontdirs
!= NULL
)
286 /* Close the pipe if it is open. This is called via xatexit. */
291 if (cpp_pipe
!= NULL
)
295 /* Report an error while reading an rc file. */
301 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
304 /* Issue a warning while reading an rc file. */
307 rcparse_warning (msg
)
310 fprintf (stderr
, "%s:%d: %s\n", rc_filename
, rc_lineno
, msg
);
313 /* Die if we get an unexpected end of file. */
319 fatal (_("%s: unexpected EOF"), msg
);
322 /* Read a 16 bit word from a file. The data is assumed to be little
335 unexpected_eof (msg
);
336 return ((b2
& 0xff) << 8) | (b1
& 0xff);
339 /* Read a 32 bit word from a file. The data is assumed to be little
354 unexpected_eof (msg
);
355 return (((((((b4
& 0xff) << 8)
361 /* Read data from a file. This is a wrapper to do error checking. */
364 get_data (e
, p
, c
, msg
)
372 got
= fread (p
, 1, c
, e
);
376 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
379 /* Define an accelerator resource. */
382 define_accelerator (id
, resinfo
, data
)
384 const struct res_res_info
*resinfo
;
385 struct accelerator
*data
;
387 struct res_resource
*r
;
389 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
390 resinfo
->language
, 0);
391 r
->type
= RES_TYPE_ACCELERATOR
;
393 r
->res_info
= *resinfo
;
396 /* Define a bitmap resource. Bitmap data is stored in a file. The
397 first 14 bytes of the file are a standard header, which is not
398 included in the resource data. */
400 #define BITMAP_SKIP (14)
403 define_bitmap (id
, resinfo
, filename
)
405 const struct res_res_info
*resinfo
;
406 const char *filename
;
413 struct res_resource
*r
;
415 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
417 if (stat (real_filename
, &s
) < 0)
418 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
421 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
423 for (i
= 0; i
< BITMAP_SKIP
; i
++)
426 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
429 free (real_filename
);
431 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
432 resinfo
->language
, 0);
434 r
->type
= RES_TYPE_BITMAP
;
435 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
436 r
->u
.data
.data
= data
;
437 r
->res_info
= *resinfo
;
440 /* Define a cursor resource. A cursor file may contain a set of
441 bitmaps, each representing the same cursor at various different
442 resolutions. They each get written out with a different ID. The
443 real cursor resource is then a group resource which can be used to
444 select one of the actual cursors. */
447 define_cursor (id
, resinfo
, filename
)
449 const struct res_res_info
*resinfo
;
450 const char *filename
;
455 struct icondir
*icondirs
;
457 struct res_resource
*r
;
458 struct group_cursor
*first
, **pp
;
460 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
462 /* A cursor file is basically an icon file. The start of the file
463 is a three word structure. The first word is ignored. The
464 second word is the type of data. The third word is the number of
467 get_word (e
, real_filename
);
468 type
= get_word (e
, real_filename
);
469 count
= get_word (e
, real_filename
);
471 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
473 /* Read in the icon directory entries. */
475 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
477 for (i
= 0; i
< count
; i
++)
479 icondirs
[i
].width
= getc (e
);
480 icondirs
[i
].height
= getc (e
);
481 icondirs
[i
].colorcount
= getc (e
);
483 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
484 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
485 icondirs
[i
].bytes
= get_long (e
, real_filename
);
486 icondirs
[i
].offset
= get_long (e
, real_filename
);
489 unexpected_eof (real_filename
);
492 /* Define each cursor as a unique resource. */
494 first_cursor
= cursors
;
496 for (i
= 0; i
< count
; i
++)
502 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
503 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
504 icondirs
[i
].offset
, strerror (errno
));
506 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
508 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
510 c
= (struct cursor
*) res_alloc (sizeof *c
);
511 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
512 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
513 c
->length
= icondirs
[i
].bytes
;
521 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
522 resinfo
->language
, 0);
523 r
->type
= RES_TYPE_CURSOR
;
525 r
->res_info
= *resinfo
;
529 free (real_filename
);
531 /* Define a cursor group resource. */
535 for (i
= 0; i
< count
; i
++)
537 struct group_cursor
*cg
;
539 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
541 cg
->width
= icondirs
[i
].width
;
542 cg
->height
= 2 * icondirs
[i
].height
;
544 /* FIXME: What should these be set to? */
548 cg
->bytes
= icondirs
[i
].bytes
+ 4;
549 cg
->index
= first_cursor
+ i
+ 1;
557 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
558 resinfo
->language
, 0);
559 r
->type
= RES_TYPE_GROUP_CURSOR
;
560 r
->u
.group_cursor
= first
;
561 r
->res_info
= *resinfo
;
564 /* Define a dialog resource. */
567 define_dialog (id
, resinfo
, dialog
)
569 const struct res_res_info
*resinfo
;
570 const struct dialog
*dialog
;
573 struct res_resource
*r
;
575 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
578 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
579 resinfo
->language
, 0);
580 r
->type
= RES_TYPE_DIALOG
;
582 r
->res_info
= *resinfo
;
585 /* Define a dialog control. This does not define a resource, but
586 merely allocates and fills in a structure. */
588 struct dialog_control
*
589 define_control (text
, id
, x
, y
, width
, height
, class, style
, exstyle
)
595 unsigned long height
;
598 unsigned long exstyle
;
600 struct dialog_control
*n
;
602 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
606 n
->exstyle
= exstyle
;
612 n
->class.u
.id
= class;
614 res_string_to_id (&n
->text
, text
);
626 /* Define a font resource. */
629 define_font (id
, resinfo
, filename
)
631 const struct res_res_info
*resinfo
;
632 const char *filename
;
638 struct res_resource
*r
;
641 unsigned char *fontdata
;
643 const char *device
, *face
;
646 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
648 if (stat (real_filename
, &s
) < 0)
649 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
652 data
= (unsigned char *) res_alloc (s
.st_size
);
654 get_data (e
, data
, s
.st_size
, real_filename
);
657 free (real_filename
);
659 r
= define_standard_resource (&resources
, RT_FONT
, id
,
660 resinfo
->language
, 0);
662 r
->type
= RES_TYPE_FONT
;
663 r
->u
.data
.length
= s
.st_size
;
664 r
->u
.data
.data
= data
;
665 r
->res_info
= *resinfo
;
667 /* For each font resource, we must add an entry in the FONTDIR
668 resource. The FONTDIR resource includes some strings in the font
669 file. To find them, we have to do some magic on the data we have
672 offset
= ((((((data
[47] << 8)
676 if (offset
> 0 && offset
< s
.st_size
)
677 device
= (char *) data
+ offset
;
681 offset
= ((((((data
[51] << 8)
685 if (offset
> 0 && offset
< s
.st_size
)
686 face
= (char *) data
+ offset
;
692 fontdatalength
= 58 + strlen (device
) + strlen (face
);
693 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
694 memcpy (fontdata
, data
, 56);
695 strcpy ((char *) fontdata
+ 56, device
);
696 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
698 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
701 fd
->length
= fontdatalength
;
704 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
708 /* For the single fontdirs resource, we always use the resource
709 information of the last font. I don't know what else to do. */
710 fontdirs_resinfo
= *resinfo
;
713 /* Define the fontdirs resource. This is called after the entire rc
714 file has been parsed, if any font resources were seen. */
719 struct res_resource
*r
;
725 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
727 r
->type
= RES_TYPE_FONTDIR
;
728 r
->u
.fontdir
= fontdirs
;
729 r
->res_info
= fontdirs_resinfo
;
732 /* Define an icon resource. An icon file may contain a set of
733 bitmaps, each representing the same icon at various different
734 resolutions. They each get written out with a different ID. The
735 real icon resource is then a group resource which can be used to
736 select one of the actual icon bitmaps. */
739 define_icon (id
, resinfo
, filename
)
741 const struct res_res_info
*resinfo
;
742 const char *filename
;
747 struct icondir
*icondirs
;
749 struct res_resource
*r
;
750 struct group_icon
*first
, **pp
;
752 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
754 /* The start of an icon file is a three word structure. The first
755 word is ignored. The second word is the type of data. The third
756 word is the number of entries. */
758 get_word (e
, real_filename
);
759 type
= get_word (e
, real_filename
);
760 count
= get_word (e
, real_filename
);
762 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
764 /* Read in the icon directory entries. */
766 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
768 for (i
= 0; i
< count
; i
++)
770 icondirs
[i
].width
= getc (e
);
771 icondirs
[i
].height
= getc (e
);
772 icondirs
[i
].colorcount
= getc (e
);
774 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
775 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
776 icondirs
[i
].bytes
= get_long (e
, real_filename
);
777 icondirs
[i
].offset
= get_long (e
, real_filename
);
780 unexpected_eof (real_filename
);
783 /* Define each icon as a unique resource. */
787 for (i
= 0; i
< count
; i
++)
792 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
793 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
794 icondirs
[i
].offset
, strerror (errno
));
796 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
798 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
805 r
= define_standard_resource (&resources
, RT_ICON
, name
,
806 resinfo
->language
, 0);
807 r
->type
= RES_TYPE_ICON
;
808 r
->u
.data
.length
= icondirs
[i
].bytes
;
809 r
->u
.data
.data
= data
;
810 r
->res_info
= *resinfo
;
814 free (real_filename
);
816 /* Define an icon group resource. */
820 for (i
= 0; i
< count
; i
++)
822 struct group_icon
*cg
;
824 /* For some reason, at least in some files the planes and bits
825 are zero. We instead set them from the color. This is
828 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
830 cg
->width
= icondirs
[i
].width
;
831 cg
->height
= icondirs
[i
].height
;
832 cg
->colors
= icondirs
[i
].colorcount
;
836 while ((1 << cg
->bits
) < cg
->colors
)
839 cg
->bytes
= icondirs
[i
].bytes
;
840 cg
->index
= first_icon
+ i
+ 1;
848 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
849 resinfo
->language
, 0);
850 r
->type
= RES_TYPE_GROUP_ICON
;
851 r
->u
.group_icon
= first
;
852 r
->res_info
= *resinfo
;
855 /* Define a menu resource. */
858 define_menu (id
, resinfo
, menuitems
)
860 const struct res_res_info
*resinfo
;
861 struct menuitem
*menuitems
;
864 struct res_resource
*r
;
866 m
= (struct menu
*) res_alloc (sizeof *m
);
867 m
->items
= menuitems
;
870 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
871 r
->type
= RES_TYPE_MENU
;
873 r
->res_info
= *resinfo
;
876 /* Define a menu item. This does not define a resource, but merely
877 allocates and fills in a structure. */
880 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
886 struct menuitem
*menuitems
;
890 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
898 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
900 mi
->popup
= menuitems
;
904 /* Define a messagetable resource. */
907 define_messagetable (id
, resinfo
, filename
)
909 const struct res_res_info
*resinfo
;
910 const char *filename
;
916 struct res_resource
*r
;
918 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
921 if (stat (real_filename
, &s
) < 0)
922 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
925 data
= (unsigned char *) res_alloc (s
.st_size
);
927 get_data (e
, data
, s
.st_size
, real_filename
);
930 free (real_filename
);
932 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
933 resinfo
->language
, 0);
935 r
->type
= RES_TYPE_MESSAGETABLE
;
936 r
->u
.data
.length
= s
.st_size
;
937 r
->u
.data
.data
= data
;
938 r
->res_info
= *resinfo
;
941 /* Define an rcdata resource. */
944 define_rcdata (id
, resinfo
, data
)
946 const struct res_res_info
*resinfo
;
947 struct rcdata_item
*data
;
949 struct res_resource
*r
;
951 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
952 resinfo
->language
, 0);
953 r
->type
= RES_TYPE_RCDATA
;
955 r
->res_info
= *resinfo
;
958 /* Create an rcdata item holding a string. */
961 define_rcdata_string (string
, len
)
965 struct rcdata_item
*ri
;
968 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
970 ri
->type
= RCDATA_STRING
;
971 ri
->u
.string
.length
= len
;
972 s
= (char *) res_alloc (len
);
973 memcpy (s
, string
, len
);
979 /* Create an rcdata item holding a number. */
982 define_rcdata_number (val
, dword
)
986 struct rcdata_item
*ri
;
988 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
990 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
996 /* Define a stringtable resource. This is called for each string
997 which appears in a STRINGTABLE statement. */
1000 define_stringtable (resinfo
, stringid
, string
)
1001 const struct res_res_info
*resinfo
;
1002 unsigned long stringid
;
1006 struct res_resource
*r
;
1009 id
.u
.id
= (stringid
>> 4) + 1;
1010 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1011 resinfo
->language
, 1);
1013 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1017 r
->type
= RES_TYPE_STRINGTABLE
;
1018 r
->u
.stringtable
= ((struct stringtable
*)
1019 res_alloc (sizeof (struct stringtable
)));
1020 for (i
= 0; i
< 16; i
++)
1022 r
->u
.stringtable
->strings
[i
].length
= 0;
1023 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1026 r
->res_info
= *resinfo
;
1029 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1030 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1034 /* Define a user data resource where the data is in the rc file. */
1037 define_user_data (id
, type
, resinfo
, data
)
1040 const struct res_res_info
*resinfo
;
1041 struct rcdata_item
*data
;
1043 struct res_id ids
[3];
1044 struct res_resource
*r
;
1049 ids
[2].u
.id
= resinfo
->language
;
1051 r
= define_resource (&resources
, 3, ids
, 0);
1052 r
->type
= RES_TYPE_USERDATA
;
1053 r
->u
.userdata
= data
;
1054 r
->res_info
= *resinfo
;
1057 /* Define a user data resource where the data is in a file. */
1060 define_user_file (id
, type
, resinfo
, filename
)
1063 const struct res_res_info
*resinfo
;
1064 const char *filename
;
1067 char *real_filename
;
1069 unsigned char *data
;
1070 struct res_id ids
[3];
1071 struct res_resource
*r
;
1073 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1075 if (stat (real_filename
, &s
) < 0)
1076 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1079 data
= (unsigned char *) res_alloc (s
.st_size
);
1081 get_data (e
, data
, s
.st_size
, real_filename
);
1084 free (real_filename
);
1089 ids
[2].u
.id
= resinfo
->language
;
1091 r
= define_resource (&resources
, 3, ids
, 0);
1092 r
->type
= RES_TYPE_USERDATA
;
1093 r
->u
.userdata
= ((struct rcdata_item
*)
1094 res_alloc (sizeof (struct rcdata_item
)));
1095 r
->u
.userdata
->next
= NULL
;
1096 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1097 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1098 r
->u
.userdata
->u
.buffer
.data
= data
;
1099 r
->res_info
= *resinfo
;
1102 /* Define a versioninfo resource. */
1105 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1108 struct fixed_versioninfo
*fixedverinfo
;
1109 struct ver_info
*verinfo
;
1111 struct res_resource
*r
;
1113 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1114 r
->type
= RES_TYPE_VERSIONINFO
;
1115 r
->u
.versioninfo
= ((struct versioninfo
*)
1116 res_alloc (sizeof (struct versioninfo
)));
1117 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1118 r
->u
.versioninfo
->var
= verinfo
;
1119 r
->res_info
.language
= language
;
1122 /* Add string version info to a list of version information. */
1125 append_ver_stringfileinfo (verinfo
, language
, strings
)
1126 struct ver_info
*verinfo
;
1127 const char *language
;
1128 struct ver_stringinfo
*strings
;
1130 struct ver_info
*vi
, **pp
;
1132 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1134 vi
->type
= VERINFO_STRING
;
1135 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1136 vi
->u
.string
.strings
= strings
;
1138 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1145 /* Add variable version info to a list of version information. */
1148 append_ver_varfileinfo (verinfo
, key
, var
)
1149 struct ver_info
*verinfo
;
1151 struct ver_varinfo
*var
;
1153 struct ver_info
*vi
, **pp
;
1155 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1157 vi
->type
= VERINFO_VAR
;
1158 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1159 vi
->u
.var
.var
= var
;
1161 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1168 /* Append version string information to a list. */
1170 struct ver_stringinfo
*
1171 append_verval (strings
, key
, value
)
1172 struct ver_stringinfo
*strings
;
1176 struct ver_stringinfo
*vs
, **pp
;
1178 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1180 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1181 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1183 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1190 /* Append version variable information to a list. */
1192 struct ver_varinfo
*
1193 append_vertrans (var
, language
, charset
)
1194 struct ver_varinfo
*var
;
1195 unsigned long language
;
1196 unsigned long charset
;
1198 struct ver_varinfo
*vv
, **pp
;
1200 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1202 vv
->language
= language
;
1203 vv
->charset
= charset
;
1205 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1212 /* Local functions used to write out an rc file. */
1214 static void indent
PARAMS ((FILE *, int));
1215 static void write_rc_directory
1216 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1217 const struct res_id
*, int *, int));
1218 static void write_rc_subdir
1219 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1220 const struct res_id
*, int *, int));
1221 static void write_rc_resource
1222 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1223 const struct res_resource
*, int *));
1224 static void write_rc_accelerators
1225 PARAMS ((FILE *, const struct accelerator
*));
1226 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1227 static void write_rc_group_cursor
1228 PARAMS ((FILE *, const struct group_cursor
*));
1229 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1230 static void write_rc_dialog_control
1231 PARAMS ((FILE *, const struct dialog_control
*));
1232 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1233 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1234 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1235 static void write_rc_menuitems
1236 PARAMS ((FILE *, const struct menuitem
*, int, int));
1237 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1238 static void write_rc_stringtable
1239 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1240 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1241 static void write_rc_filedata
1242 PARAMS ((FILE *, unsigned long, const unsigned char *));
1244 /* Indent a given number of spaces. */
1253 for (i
= 0; i
< c
; i
++)
1257 /* Dump the resources we have read in the format of an rc file.
1259 Actually, we don't use the format of an rc file, because it's way
1260 too much of a pain--for example, we'd have to write icon resources
1261 into a file and refer to that file. We just generate a readable
1262 format that kind of looks like an rc file, and is useful for
1263 understanding the contents of a resource file. Someday we may want
1264 to generate an rc file which the rc compiler can read; if that day
1265 comes, this code will have to be fixed up. */
1268 write_rc_file (filename
, resources
)
1269 const char *filename
;
1270 const struct res_directory
*resources
;
1275 if (filename
== NULL
)
1279 e
= fopen (filename
, FOPEN_WT
);
1281 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1285 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1286 (const struct res_id
*) NULL
, &language
, 1);
1289 /* Write out a directory. E is the file to write to. RD is the
1290 directory. TYPE is a pointer to the level 1 ID which serves as the
1291 resource type. NAME is a pointer to the level 2 ID which serves as
1292 an individual resource name. LANGUAGE is a pointer to the current
1293 language. LEVEL is the level in the tree. */
1296 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1298 const struct res_directory
*rd
;
1299 const struct res_id
*type
;
1300 const struct res_id
*name
;
1304 const struct res_entry
*re
;
1306 /* Print out some COFF information that rc files can't represent. */
1309 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1310 if (rd
->characteristics
!= 0)
1311 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1312 if (rd
->major
!= 0 || rd
->minor
!= 0)
1313 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1315 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1320 /* If we're at level 1, the key of this resource is the
1321 type. This normally duplicates the information we have
1322 stored with the resource itself, but we need to remember
1323 the type if this is a user define resource type. */
1328 /* If we're at level 2, the key of this resource is the name
1329 we are going to use in the rc printout. */
1334 /* If we're at level 3, then this key represents a language.
1335 Use it to update the current language. */
1337 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1338 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1340 fprintf (e
, "LANGUAGE %lu, %lu\n",
1341 re
->id
.u
.id
& 0xff, (re
->id
.u
.id
>> 8) & 0xff);
1342 *language
= re
->id
.u
.id
;
1351 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1356 /* This is the normal case: the three levels are
1357 TYPE/NAME/LANGUAGE. NAME will have been set at level
1358 2, and represents the name to use. We probably just
1359 set LANGUAGE, and it will probably match what the
1360 resource itself records if anything. */
1361 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1365 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1366 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1373 /* Write out a subdirectory entry. E is the file to write to. RE is
1374 the subdirectory entry. TYPE and NAME are pointers to higher level
1375 IDs, or NULL. LANGUAGE is a pointer to the current language.
1376 LEVEL is the level in the tree. */
1379 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1381 const struct res_entry
*re
;
1382 const struct res_id
*type
;
1383 const struct res_id
*name
;
1391 fprintf (e
, "// Type: ");
1393 res_id_print (e
, re
->id
, 1);
1398 switch (re
->id
.u
.id
)
1400 case RT_CURSOR
: s
= "cursor"; break;
1401 case RT_BITMAP
: s
= "bitmap"; break;
1402 case RT_ICON
: s
= "icon"; break;
1403 case RT_MENU
: s
= "menu"; break;
1404 case RT_DIALOG
: s
= "dialog"; break;
1405 case RT_STRING
: s
= "stringtable"; break;
1406 case RT_FONTDIR
: s
= "fontdir"; break;
1407 case RT_FONT
: s
= "font"; break;
1408 case RT_ACCELERATOR
: s
= "accelerators"; break;
1409 case RT_RCDATA
: s
= "rcdata"; break;
1410 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1411 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1412 case RT_GROUP_ICON
: s
= "group icon"; break;
1413 case RT_VERSION
: s
= "version"; break;
1414 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1415 case RT_PLUGPLAY
: s
= "plugplay"; break;
1416 case RT_VXD
: s
= "vxd"; break;
1417 case RT_ANICURSOR
: s
= "anicursor"; break;
1418 case RT_ANIICON
: s
= "aniicon"; break;
1419 default: s
= NULL
; break;
1423 fprintf (e
, "%s", s
);
1425 res_id_print (e
, re
->id
, 1);
1431 fprintf (e
, "// Name: ");
1432 res_id_print (e
, re
->id
, 1);
1437 fprintf (e
, "// Language: ");
1438 res_id_print (e
, re
->id
, 1);
1443 fprintf (e
, "// Level %d: ", level
);
1444 res_id_print (e
, re
->id
, 1);
1448 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1451 /* Write out a single resource. E is the file to write to. TYPE is a
1452 pointer to the type of the resource. NAME is a pointer to the name
1453 of the resource; it will be NULL if there is a level mismatch. RES
1454 is the resource data. LANGUAGE is a pointer to the current
1458 write_rc_resource (e
, type
, name
, res
, language
)
1460 const struct res_id
*type
;
1461 const struct res_id
*name
;
1462 const struct res_resource
*res
;
1476 case RES_TYPE_ACCELERATOR
:
1478 rt
= RT_ACCELERATOR
;
1481 case RES_TYPE_BITMAP
:
1486 case RES_TYPE_CURSOR
:
1491 case RES_TYPE_GROUP_CURSOR
:
1493 rt
= RT_GROUP_CURSOR
;
1496 case RES_TYPE_DIALOG
:
1497 if (extended_dialog (res
->u
.dialog
))
1509 case RES_TYPE_FONTDIR
:
1519 case RES_TYPE_GROUP_ICON
:
1525 if (extended_menu (res
->u
.menu
))
1538 case RES_TYPE_MESSAGETABLE
:
1540 rt
= RT_MESSAGETABLE
;
1543 case RES_TYPE_RCDATA
:
1548 case RES_TYPE_STRINGTABLE
:
1553 case RES_TYPE_USERDATA
:
1558 case RES_TYPE_VERSIONINFO
:
1566 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1568 fprintf (e
, "// Unexpected resource type mismatch: ");
1569 res_id_print (e
, *type
, 1);
1570 fprintf (e
, " != %d", rt
);
1573 if (res
->coff_info
.codepage
!= 0)
1574 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1575 if (res
->coff_info
.reserved
!= 0)
1576 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1579 res_id_print (e
, *name
, 0);
1581 fprintf (e
, "??Unknown-Name??");
1585 fprintf (e
, "%s", s
);
1586 else if (type
!= NULL
)
1587 res_id_print (e
, *type
, 0);
1589 fprintf (e
, "??Unknown-Type??");
1591 if (res
->res_info
.memflags
!= 0)
1593 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1594 fprintf (e
, " MOVEABLE");
1595 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1596 fprintf (e
, " PURE");
1597 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1598 fprintf (e
, " PRELOAD");
1599 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1600 fprintf (e
, " DISCARDABLE");
1603 if (res
->type
== RES_TYPE_DIALOG
)
1605 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1606 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1607 if (res
->u
.dialog
->ex
!= NULL
1608 && res
->u
.dialog
->ex
->help
!= 0)
1609 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1614 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1615 || res
->res_info
.characteristics
!= 0
1616 || res
->res_info
.version
!= 0)
1622 case RES_TYPE_ACCELERATOR
:
1623 case RES_TYPE_DIALOG
:
1625 case RES_TYPE_RCDATA
:
1626 case RES_TYPE_STRINGTABLE
:
1635 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1636 fprintf (e
, "%sLANGUAGE %d, %d\n",
1637 modifiers
? "// " : "",
1638 res
->res_info
.language
& 0xff,
1639 (res
->res_info
.language
>> 8) & 0xff);
1640 if (res
->res_info
.characteristics
!= 0)
1641 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1642 modifiers
? "// " : "",
1643 res
->res_info
.characteristics
);
1644 if (res
->res_info
.version
!= 0)
1645 fprintf (e
, "%sVERSION %lu\n",
1646 modifiers
? "// " : "",
1647 res
->res_info
.version
);
1655 case RES_TYPE_ACCELERATOR
:
1656 write_rc_accelerators (e
, res
->u
.acc
);
1659 case RES_TYPE_CURSOR
:
1660 write_rc_cursor (e
, res
->u
.cursor
);
1663 case RES_TYPE_GROUP_CURSOR
:
1664 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1667 case RES_TYPE_DIALOG
:
1668 write_rc_dialog (e
, res
->u
.dialog
);
1671 case RES_TYPE_FONTDIR
:
1672 write_rc_fontdir (e
, res
->u
.fontdir
);
1675 case RES_TYPE_GROUP_ICON
:
1676 write_rc_group_icon (e
, res
->u
.group_icon
);
1680 write_rc_menu (e
, res
->u
.menu
, menuex
);
1683 case RES_TYPE_RCDATA
:
1684 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1687 case RES_TYPE_STRINGTABLE
:
1688 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1691 case RES_TYPE_USERDATA
:
1692 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1695 case RES_TYPE_VERSIONINFO
:
1696 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1699 case RES_TYPE_BITMAP
:
1702 case RES_TYPE_MESSAGETABLE
:
1703 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1708 /* Write out accelerator information. */
1711 write_rc_accelerators (e
, accelerators
)
1713 const struct accelerator
*accelerators
;
1715 const struct accelerator
*acc
;
1717 fprintf (e
, "BEGIN\n");
1718 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1724 if ((acc
->key
& 0x7f) == acc
->key
1725 && isprint ((unsigned char) acc
->key
)
1726 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1728 fprintf (e
, "\"%c\"", acc
->key
);
1733 fprintf (e
, "%d", acc
->key
);
1737 fprintf (e
, ", %d", acc
->id
);
1741 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1742 fprintf (e
, ", VIRTKEY");
1744 fprintf (e
, ", ASCII");
1747 if ((acc
->flags
& ACC_SHIFT
) != 0)
1748 fprintf (e
, ", SHIFT");
1749 if ((acc
->flags
& ACC_CONTROL
) != 0)
1750 fprintf (e
, ", CONTROL");
1751 if ((acc
->flags
& ACC_ALT
) != 0)
1752 fprintf (e
, ", ALT");
1757 fprintf (e
, "END\n");
1760 /* Write out cursor information. This would normally be in a separate
1761 file, which the rc file would include. */
1764 write_rc_cursor (e
, cursor
)
1766 const struct cursor
*cursor
;
1768 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
1770 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
1773 /* Write out group cursor data. This would normally be built from the
1777 write_rc_group_cursor (e
, group_cursor
)
1779 const struct group_cursor
*group_cursor
;
1781 const struct group_cursor
*gc
;
1783 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
1785 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
1786 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
1787 fprintf (e
, "// data bytes: %lu; index: %d\n",
1788 gc
->bytes
, gc
->index
);
1792 /* Write dialog data. */
1795 write_rc_dialog (e
, dialog
)
1797 const struct dialog
*dialog
;
1799 const struct dialog_control
*control
;
1801 if (dialog
->style
!= 0)
1802 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
1803 if (dialog
->exstyle
!= 0)
1804 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
1805 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
1806 || dialog
->class.u
.id
!= 0)
1808 fprintf (e
, "CLASS ");
1809 res_id_print (e
, dialog
->class, 0);
1812 if (dialog
->caption
!= NULL
)
1814 fprintf (e
, "CAPTION \"");
1815 unicode_print (e
, dialog
->caption
, -1);
1816 fprintf (e
, "\"\n");
1818 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
1819 || dialog
->menu
.u
.id
!= 0)
1821 fprintf (e
, "MENU ");
1822 res_id_print (e
, dialog
->menu
, 0);
1825 if (dialog
->font
!= NULL
)
1827 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
1828 unicode_print (e
, dialog
->font
, -1);
1830 if (dialog
->ex
!= NULL
1831 && (dialog
->ex
->weight
!= 0 || dialog
->ex
->italic
!= 0))
1832 fprintf (e
, ", %d, %d", dialog
->ex
->weight
, dialog
->ex
->italic
);
1836 fprintf (e
, "BEGIN\n");
1838 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
1839 write_rc_dialog_control (e
, control
);
1841 fprintf (e
, "END\n");
1844 /* For each predefined control keyword, this table provides the class
1850 unsigned short class;
1851 unsigned long style
;
1854 static const struct control_info control_info
[] =
1856 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
1857 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
1858 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
1859 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
1860 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
1861 { "CTEXT", CTL_STATIC
, SS_CENTER
},
1862 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
1863 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
1864 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
1865 { "ICON", CTL_STATIC
, SS_ICON
},
1866 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
1867 { "LTEXT", CTL_STATIC
, SS_LEFT
},
1868 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
1869 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
1870 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
1871 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
1872 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
1873 { "STATE3", CTL_BUTTON
, BS_3STATE
},
1874 /* It's important that USERBUTTON come after all the other button
1875 types, so that it won't be matched too early. */
1876 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
1880 /* Write a dialog control. */
1883 write_rc_dialog_control (e
, control
)
1885 const struct dialog_control
*control
;
1887 const struct control_info
*ci
;
1891 if (control
->class.named
)
1895 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
1896 if (ci
->class == control
->class.u
.id
1897 && (ci
->style
== (unsigned long) -1
1898 || ci
->style
== (control
->style
& 0xff)))
1902 fprintf (e
, "CONTROL");
1903 else if (ci
->name
!= NULL
)
1904 fprintf (e
, "%s", ci
->name
);
1906 fprintf (e
, "CONTROL");
1908 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
1911 res_id_print (e
, control
->text
, 1);
1915 fprintf (e
, " %d, ", control
->id
);
1919 if (control
->class.named
)
1921 res_id_print (e
, control
->class, 0);
1922 if (control
->class.named
)
1924 fprintf (e
, ", 0x%lx, ", control
->style
);
1927 fprintf (e
, "%d, %d", control
->x
, control
->y
);
1929 if (control
->style
!= SS_ICON
1930 || control
->exstyle
!= 0
1931 || control
->width
!= 0
1932 || control
->height
!= 0
1933 || control
->help
!= 0)
1935 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
1937 /* FIXME: We don't need to print the style if it is the default.
1938 More importantly, in certain cases we actually need to turn
1939 off parts of the forced style, by using NOT. */
1940 fprintf (e
, ", 0x%lx", control
->style
);
1942 if (control
->exstyle
!= 0 || control
->help
!= 0)
1943 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
1948 if (control
->data
!= NULL
)
1949 write_rc_rcdata (e
, control
->data
, 2);
1952 /* Write out font directory data. This would normally be built from
1956 write_rc_fontdir (e
, fontdir
)
1958 const struct fontdir
*fontdir
;
1960 const struct fontdir
*fc
;
1962 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
1964 fprintf (e
, "// Font index: %d\n", fc
->index
);
1965 write_rc_filedata (e
, fc
->length
, fc
->data
);
1969 /* Write out group icon data. This would normally be built from the
1973 write_rc_group_icon (e
, group_icon
)
1975 const struct group_icon
*group_icon
;
1977 const struct group_icon
*gi
;
1979 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
1981 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1982 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
1983 fprintf (e
, "// data bytes: %lu; index: %d\n",
1984 gi
->bytes
, gi
->index
);
1988 /* Write out a menu resource. */
1991 write_rc_menu (e
, menu
, menuex
)
1993 const struct menu
*menu
;
1996 if (menu
->help
!= 0)
1997 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
1998 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2001 /* Write out menuitems. */
2004 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
2006 const struct menuitem
*menuitems
;
2010 const struct menuitem
*mi
;
2013 fprintf (e
, "BEGIN\n");
2015 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2017 indent (e
, ind
+ 2);
2019 if (mi
->popup
== NULL
)
2020 fprintf (e
, "MENUITEM");
2022 fprintf (e
, "POPUP");
2025 && mi
->popup
== NULL
2030 fprintf (e
, " SEPARATOR\n");
2034 if (mi
->text
== NULL
)
2035 fprintf (e
, " \"\"");
2039 unicode_print (e
, mi
->text
, -1);
2045 if (mi
->popup
== NULL
)
2046 fprintf (e
, ", %d", mi
->id
);
2048 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2049 fprintf (e
, ", CHECKED");
2050 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2051 fprintf (e
, ", GRAYED");
2052 if ((mi
->type
& MENUITEM_HELP
) != 0)
2053 fprintf (e
, ", HELP");
2054 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2055 fprintf (e
, ", INACTIVE");
2056 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2057 fprintf (e
, ", MENUBARBREAK");
2058 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2059 fprintf (e
, ", MENUBREAK");
2063 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2065 fprintf (e
, ", %d", mi
->id
);
2066 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2068 fprintf (e
, ", %lu", mi
->type
);
2069 if (mi
->state
!= 0 || mi
->help
!= 0)
2071 fprintf (e
, ", %lu", mi
->state
);
2073 fprintf (e
, ", %lu", mi
->help
);
2081 if (mi
->popup
!= NULL
)
2082 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2086 fprintf (e
, "END\n");
2089 /* Write out an rcdata resource. This is also used for other types of
2090 resources that need to print arbitrary data. */
2093 write_rc_rcdata (e
, rcdata
, ind
)
2095 const struct rcdata_item
*rcdata
;
2098 const struct rcdata_item
*ri
;
2101 fprintf (e
, "BEGIN\n");
2103 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2105 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2108 indent (e
, ind
+ 2);
2116 fprintf (e
, "%d", ri
->u
.word
);
2120 fprintf (e
, "%luL", ri
->u
.dword
);
2130 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2132 if (isprint ((unsigned char) *s
))
2135 fprintf (e
, "\\%03o", *s
);
2141 case RCDATA_WSTRING
:
2143 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2152 /* Assume little endian data. */
2155 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2161 indent (e
, ind
+ 2);
2162 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2163 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2164 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2165 | ri
->u
.buffer
.data
[i
]);
2166 fprintf (e
, "%luL", l
);
2167 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2169 for (j
= 0; j
< 4; ++j
)
2170 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2171 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2175 fprintf (e
, "\t// ");
2176 for (j
= 0; j
< 4; ++j
)
2178 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2179 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2182 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2184 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2192 if (i
+ 1 < ri
->u
.buffer
.length
)
2198 indent (e
, ind
+ 2);
2199 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2200 fprintf (e
, "%d", s
);
2201 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2203 for (j
= 0; j
< 2; ++j
)
2204 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2205 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2209 fprintf (e
, "\t// ");
2210 for (j
= 0; j
< 2; ++j
)
2212 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2213 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2216 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2218 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2227 if (i
< ri
->u
.buffer
.length
)
2230 indent (e
, ind
+ 2);
2231 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2232 && isprint (ri
->u
.buffer
.data
[i
]))
2233 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2235 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2236 if (ri
->next
!= NULL
)
2246 if (ri
->type
!= RCDATA_BUFFER
)
2248 if (ri
->next
!= NULL
)
2255 fprintf (e
, "END\n");
2258 /* Write out a stringtable resource. */
2261 write_rc_stringtable (e
, name
, stringtable
)
2263 const struct res_id
*name
;
2264 const struct stringtable
*stringtable
;
2266 unsigned long offset
;
2269 if (name
!= NULL
&& ! name
->named
)
2270 offset
= (name
->u
.id
- 1) << 4;
2273 fprintf (e
, "// %s string table name\n",
2274 name
== NULL
? "Missing" : "Invalid");
2278 fprintf (e
, "BEGIN\n");
2280 for (i
= 0; i
< 16; i
++)
2282 if (stringtable
->strings
[i
].length
!= 0)
2284 fprintf (e
, " %lu, \"", offset
+ i
);
2285 unicode_print (e
, stringtable
->strings
[i
].string
,
2286 stringtable
->strings
[i
].length
);
2287 fprintf (e
, "\"\n");
2291 fprintf (e
, "END\n");
2294 /* Write out a versioninfo resource. */
2297 write_rc_versioninfo (e
, versioninfo
)
2299 const struct versioninfo
*versioninfo
;
2301 const struct fixed_versioninfo
*f
;
2302 const struct ver_info
*vi
;
2304 f
= versioninfo
->fixed
;
2305 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2306 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2307 (f
->file_version_ms
>> 16) & 0xffff,
2308 f
->file_version_ms
& 0xffff,
2309 (f
->file_version_ls
>> 16) & 0xffff,
2310 f
->file_version_ls
& 0xffff);
2311 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2312 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2313 (f
->product_version_ms
>> 16) & 0xffff,
2314 f
->product_version_ms
& 0xffff,
2315 (f
->product_version_ls
>> 16) & 0xffff,
2316 f
->product_version_ls
& 0xffff);
2317 if (f
->file_flags_mask
!= 0)
2318 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2319 if (f
->file_flags
!= 0)
2320 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2321 if (f
->file_os
!= 0)
2322 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2323 if (f
->file_type
!= 0)
2324 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2325 if (f
->file_subtype
!= 0)
2326 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2327 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2328 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2330 fprintf (e
, "BEGIN\n");
2332 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2336 case VERINFO_STRING
:
2338 const struct ver_stringinfo
*vs
;
2340 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2341 fprintf (e
, " BEGIN\n");
2342 fprintf (e
, " BLOCK \"");
2343 unicode_print (e
, vi
->u
.string
.language
, -1);
2344 fprintf (e
, "\"\n");
2345 fprintf (e
, " BEGIN\n");
2347 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2349 fprintf (e
, " VALUE \"");
2350 unicode_print (e
, vs
->key
, -1);
2351 fprintf (e
, "\", \"");
2352 unicode_print (e
, vs
->value
, -1);
2353 fprintf (e
, "\"\n");
2356 fprintf (e
, " END\n");
2357 fprintf (e
, " END\n");
2363 const struct ver_varinfo
*vv
;
2365 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2366 fprintf (e
, " BEGIN\n");
2367 fprintf (e
, " VALUE \"");
2368 unicode_print (e
, vi
->u
.var
.key
, -1);
2371 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2372 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2375 fprintf (e
, "\n END\n");
2382 fprintf (e
, "END\n");
2385 /* Write out data which would normally be read from a file. */
2388 write_rc_filedata (e
, length
, data
)
2390 unsigned long length
;
2391 const unsigned char *data
;
2395 for (i
= 0; i
+ 15 < length
; i
+= 16)
2397 fprintf (e
, "// %4lx: ", i
);
2398 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2399 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2400 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2401 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2402 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2403 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2408 fprintf (e
, "// %4lx:", i
);
2411 fprintf (e
, " %02x", data
[i
]);