1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998 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 void close_pipe
PARAMS ((void));
116 static void unexpected_eof
PARAMS ((const char *));
117 static int get_word
PARAMS ((FILE *, const char *));
118 static unsigned long get_long
PARAMS ((FILE *, const char *));
120 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
121 static void define_fontdirs
PARAMS ((void));
123 /* look for the preprocessor program */
126 look_for_default (cmd
, prefix
, end_prefix
, preprocargs
, filename
)
133 char *path
= getenv ("PATH");
138 strcpy (cmd
, prefix
);
140 sprintf (cmd
+end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
141 space
= strchr (cmd
+end_prefix
, ' ');
145 if (strchr (cmd
, '/'))
147 found
= stat (cmd
, &s
);
152 fprintf (stderr
, "Tried `%s'\n", cmd
);
157 strcpy (cmd
, prefix
);
159 sprintf (cmd
+end_prefix
, "%s %s %s",
160 DEFAULT_PREPROCESSOR
, preprocargs
, filename
);
163 fprintf (stderr
, "Using `%s'\n", cmd
);
165 cpp_pipe
= popen (cmd
, FOPEN_RT
);
169 /* Read an rc file. */
171 struct res_directory
*
172 read_rc_file (filename
, preprocessor
, preprocargs
, language
)
173 const char *filename
;
174 const char *preprocessor
;
175 const char *preprocargs
;
180 if (preprocargs
== NULL
)
182 if (filename
== NULL
)
187 cmd
= xmalloc (strlen (preprocessor
)
188 + strlen (preprocargs
)
191 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
193 cpp_pipe
= popen (cmd
, FOPEN_RT
);
197 char *dash
, *slash
, *cp
;
199 preprocessor
= DEFAULT_PREPROCESSOR
;
201 cmd
= xmalloc (strlen (program_name
)
202 + strlen (preprocessor
)
203 + strlen (preprocargs
)
209 for (cp
=program_name
; *cp
; cp
++)
214 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
215 *cp
== ':' || *cp
== '\\' ||
228 /* First, try looking for a prefixed gcc in the windres
229 directory, with the same prefix as windres */
231 cpp_pipe
= look_for_default (cmd
, program_name
, dash
-program_name
+1,
232 preprocargs
, filename
);
235 if (slash
&& !cpp_pipe
)
237 /* Next, try looking for a gcc in the same directory as
240 cpp_pipe
= look_for_default (cmd
, program_name
, slash
-program_name
+1,
241 preprocargs
, filename
);
246 /* Sigh, try the default */
248 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
252 if (cpp_pipe
== NULL
)
253 fatal (_("can't popen `%s': %s"), cmd
, strerror (errno
));
256 xatexit (close_pipe
);
258 rc_filename
= xstrdup (filename
);
261 rcparse_set_language (language
);
265 if (pclose (cpp_pipe
) != 0)
266 fprintf (stderr
, _("%s: warning: preprocessor failed\n"), program_name
);
269 if (fontdirs
!= NULL
)
278 /* Close the pipe if it is open. This is called via xatexit. */
283 if (cpp_pipe
!= NULL
)
287 /* Report an error while reading an rc file. */
293 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
296 /* Issue a warning while reading an rc file. */
299 rcparse_warning (msg
)
302 fprintf (stderr
, "%s:%d: %s\n", rc_filename
, rc_lineno
, msg
);
305 /* Die if we get an unexpected end of file. */
311 fatal (_("%s: unexpected EOF"), msg
);
314 /* Read a 16 bit word from a file. The data is assumed to be little
327 unexpected_eof (msg
);
328 return ((b2
& 0xff) << 8) | (b1
& 0xff);
331 /* Read a 32 bit word from a file. The data is assumed to be little
346 unexpected_eof (msg
);
347 return (((((((b4
& 0xff) << 8)
353 /* Read data from a file. This is a wrapper to do error checking. */
356 get_data (e
, p
, c
, msg
)
364 got
= fread (p
, 1, c
, e
);
368 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
371 /* Define an accelerator resource. */
374 define_accelerator (id
, resinfo
, data
)
376 const struct res_res_info
*resinfo
;
377 struct accelerator
*data
;
379 struct res_resource
*r
;
381 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
382 resinfo
->language
, 0);
383 r
->type
= RES_TYPE_ACCELERATOR
;
385 r
->res_info
= *resinfo
;
388 /* Define a bitmap resource. Bitmap data is stored in a file. The
389 first 14 bytes of the file are a standard header, which is not
390 included in the resource data. */
392 #define BITMAP_SKIP (14)
395 define_bitmap (id
, resinfo
, filename
)
397 const struct res_res_info
*resinfo
;
398 const char *filename
;
405 struct res_resource
*r
;
407 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
409 if (stat (real_filename
, &s
) < 0)
410 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
413 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
415 for (i
= 0; i
< BITMAP_SKIP
; i
++)
418 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
421 free (real_filename
);
423 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
424 resinfo
->language
, 0);
426 r
->type
= RES_TYPE_BITMAP
;
427 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
428 r
->u
.data
.data
= data
;
429 r
->res_info
= *resinfo
;
432 /* Define a cursor resource. A cursor file may contain a set of
433 bitmaps, each representing the same cursor at various different
434 resolutions. They each get written out with a different ID. The
435 real cursor resource is then a group resource which can be used to
436 select one of the actual cursors. */
439 define_cursor (id
, resinfo
, filename
)
441 const struct res_res_info
*resinfo
;
442 const char *filename
;
447 struct icondir
*icondirs
;
449 struct res_resource
*r
;
450 struct group_cursor
*first
, **pp
;
452 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
454 /* A cursor file is basically an icon file. The start of the file
455 is a three word structure. The first word is ignored. The
456 second word is the type of data. The third word is the number of
459 get_word (e
, real_filename
);
460 type
= get_word (e
, real_filename
);
461 count
= get_word (e
, real_filename
);
463 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
465 /* Read in the icon directory entries. */
467 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
469 for (i
= 0; i
< count
; i
++)
471 icondirs
[i
].width
= getc (e
);
472 icondirs
[i
].height
= getc (e
);
473 icondirs
[i
].colorcount
= getc (e
);
475 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
476 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
477 icondirs
[i
].bytes
= get_long (e
, real_filename
);
478 icondirs
[i
].offset
= get_long (e
, real_filename
);
481 unexpected_eof (real_filename
);
484 /* Define each cursor as a unique resource. */
486 first_cursor
= cursors
;
488 for (i
= 0; i
< count
; i
++)
494 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
495 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
496 icondirs
[i
].offset
, strerror (errno
));
498 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
500 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
502 c
= (struct cursor
*) res_alloc (sizeof *c
);
503 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
504 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
505 c
->length
= icondirs
[i
].bytes
;
513 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
514 resinfo
->language
, 0);
515 r
->type
= RES_TYPE_CURSOR
;
517 r
->res_info
= *resinfo
;
521 free (real_filename
);
523 /* Define a cursor group resource. */
527 for (i
= 0; i
< count
; i
++)
529 struct group_cursor
*cg
;
531 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
533 cg
->width
= icondirs
[i
].width
;
534 cg
->height
= 2 * icondirs
[i
].height
;
536 /* FIXME: What should these be set to? */
540 cg
->bytes
= icondirs
[i
].bytes
+ 4;
541 cg
->index
= first_cursor
+ i
+ 1;
549 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
550 resinfo
->language
, 0);
551 r
->type
= RES_TYPE_GROUP_CURSOR
;
552 r
->u
.group_cursor
= first
;
553 r
->res_info
= *resinfo
;
556 /* Define a dialog resource. */
559 define_dialog (id
, resinfo
, dialog
)
561 const struct res_res_info
*resinfo
;
562 const struct dialog
*dialog
;
565 struct res_resource
*r
;
567 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
570 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
571 resinfo
->language
, 0);
572 r
->type
= RES_TYPE_DIALOG
;
574 r
->res_info
= *resinfo
;
577 /* Define a dialog control. This does not define a resource, but
578 merely allocates and fills in a structure. */
580 struct dialog_control
*
581 define_control (text
, id
, x
, y
, width
, height
, class, style
, exstyle
)
587 unsigned long height
;
590 unsigned long exstyle
;
592 struct dialog_control
*n
;
594 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
598 n
->exstyle
= exstyle
;
604 n
->class.u
.id
= class;
606 res_string_to_id (&n
->text
, text
);
618 /* Define a font resource. */
621 define_font (id
, resinfo
, filename
)
623 const struct res_res_info
*resinfo
;
624 const char *filename
;
630 struct res_resource
*r
;
633 unsigned char *fontdata
;
635 const char *device
, *face
;
638 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
640 if (stat (real_filename
, &s
) < 0)
641 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
644 data
= (unsigned char *) res_alloc (s
.st_size
);
646 get_data (e
, data
, s
.st_size
, real_filename
);
649 free (real_filename
);
651 r
= define_standard_resource (&resources
, RT_FONT
, id
,
652 resinfo
->language
, 0);
654 r
->type
= RES_TYPE_FONT
;
655 r
->u
.data
.length
= s
.st_size
;
656 r
->u
.data
.data
= data
;
657 r
->res_info
= *resinfo
;
659 /* For each font resource, we must add an entry in the FONTDIR
660 resource. The FONTDIR resource includes some strings in the font
661 file. To find them, we have to do some magic on the data we have
664 offset
= ((((((data
[47] << 8)
668 if (offset
> 0 && offset
< s
.st_size
)
669 device
= (char *) data
+ offset
;
673 offset
= ((((((data
[51] << 8)
677 if (offset
> 0 && offset
< s
.st_size
)
678 face
= (char *) data
+ offset
;
684 fontdatalength
= 58 + strlen (device
) + strlen (face
);
685 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
686 memcpy (fontdata
, data
, 56);
687 strcpy ((char *) fontdata
+ 56, device
);
688 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
690 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
693 fd
->length
= fontdatalength
;
696 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
700 /* For the single fontdirs resource, we always use the resource
701 information of the last font. I don't know what else to do. */
702 fontdirs_resinfo
= *resinfo
;
705 /* Define the fontdirs resource. This is called after the entire rc
706 file has been parsed, if any font resources were seen. */
711 struct res_resource
*r
;
717 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
719 r
->type
= RES_TYPE_FONTDIR
;
720 r
->u
.fontdir
= fontdirs
;
721 r
->res_info
= fontdirs_resinfo
;
724 /* Define an icon resource. An icon file may contain a set of
725 bitmaps, each representing the same icon at various different
726 resolutions. They each get written out with a different ID. The
727 real icon resource is then a group resource which can be used to
728 select one of the actual icon bitmaps. */
731 define_icon (id
, resinfo
, filename
)
733 const struct res_res_info
*resinfo
;
734 const char *filename
;
739 struct icondir
*icondirs
;
741 struct res_resource
*r
;
742 struct group_icon
*first
, **pp
;
744 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
746 /* The start of an icon file is a three word structure. The first
747 word is ignored. The second word is the type of data. The third
748 word is the number of entries. */
750 get_word (e
, real_filename
);
751 type
= get_word (e
, real_filename
);
752 count
= get_word (e
, real_filename
);
754 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
756 /* Read in the icon directory entries. */
758 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
760 for (i
= 0; i
< count
; i
++)
762 icondirs
[i
].width
= getc (e
);
763 icondirs
[i
].height
= getc (e
);
764 icondirs
[i
].colorcount
= getc (e
);
766 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
767 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
768 icondirs
[i
].bytes
= get_long (e
, real_filename
);
769 icondirs
[i
].offset
= get_long (e
, real_filename
);
772 unexpected_eof (real_filename
);
775 /* Define each icon as a unique resource. */
779 for (i
= 0; i
< count
; i
++)
784 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
785 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
786 icondirs
[i
].offset
, strerror (errno
));
788 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
790 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
797 r
= define_standard_resource (&resources
, RT_ICON
, name
,
798 resinfo
->language
, 0);
799 r
->type
= RES_TYPE_ICON
;
800 r
->u
.data
.length
= icondirs
[i
].bytes
;
801 r
->u
.data
.data
= data
;
802 r
->res_info
= *resinfo
;
806 free (real_filename
);
808 /* Define an icon group resource. */
812 for (i
= 0; i
< count
; i
++)
814 struct group_icon
*cg
;
816 /* For some reason, at least in some files the planes and bits
817 are zero. We instead set them from the color. This is
820 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
822 cg
->width
= icondirs
[i
].width
;
823 cg
->height
= icondirs
[i
].height
;
824 cg
->colors
= icondirs
[i
].colorcount
;
828 while ((1 << cg
->bits
) < cg
->colors
)
831 cg
->bytes
= icondirs
[i
].bytes
;
832 cg
->index
= first_icon
+ i
+ 1;
840 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
841 resinfo
->language
, 0);
842 r
->type
= RES_TYPE_GROUP_ICON
;
843 r
->u
.group_icon
= first
;
844 r
->res_info
= *resinfo
;
847 /* Define a menu resource. */
850 define_menu (id
, resinfo
, menuitems
)
852 const struct res_res_info
*resinfo
;
853 struct menuitem
*menuitems
;
856 struct res_resource
*r
;
858 m
= (struct menu
*) res_alloc (sizeof *m
);
859 m
->items
= menuitems
;
862 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
863 r
->type
= RES_TYPE_MENU
;
865 r
->res_info
= *resinfo
;
868 /* Define a menu item. This does not define a resource, but merely
869 allocates and fills in a structure. */
872 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
878 struct menuitem
*menuitems
;
882 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
890 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
892 mi
->popup
= menuitems
;
896 /* Define a messagetable resource. */
899 define_messagetable (id
, resinfo
, filename
)
901 const struct res_res_info
*resinfo
;
902 const char *filename
;
908 struct res_resource
*r
;
910 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
913 if (stat (real_filename
, &s
) < 0)
914 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
917 data
= (unsigned char *) res_alloc (s
.st_size
);
919 get_data (e
, data
, s
.st_size
, real_filename
);
922 free (real_filename
);
924 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
925 resinfo
->language
, 0);
927 r
->type
= RES_TYPE_MESSAGETABLE
;
928 r
->u
.data
.length
= s
.st_size
;
929 r
->u
.data
.data
= data
;
930 r
->res_info
= *resinfo
;
933 /* Define an rcdata resource. */
936 define_rcdata (id
, resinfo
, data
)
938 const struct res_res_info
*resinfo
;
939 struct rcdata_item
*data
;
941 struct res_resource
*r
;
943 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
944 resinfo
->language
, 0);
945 r
->type
= RES_TYPE_RCDATA
;
947 r
->res_info
= *resinfo
;
950 /* Create an rcdata item holding a string. */
953 define_rcdata_string (string
, len
)
957 struct rcdata_item
*ri
;
960 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
962 ri
->type
= RCDATA_STRING
;
963 ri
->u
.string
.length
= len
;
964 s
= (char *) res_alloc (len
);
965 memcpy (s
, string
, len
);
971 /* Create an rcdata item holding a number. */
974 define_rcdata_number (val
, dword
)
978 struct rcdata_item
*ri
;
980 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
982 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
988 /* Define a stringtable resource. This is called for each string
989 which appears in a STRINGTABLE statement. */
992 define_stringtable (resinfo
, stringid
, string
)
993 const struct res_res_info
*resinfo
;
994 unsigned long stringid
;
998 struct res_resource
*r
;
1001 id
.u
.id
= (stringid
>> 4) + 1;
1002 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1003 resinfo
->language
, 1);
1005 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1009 r
->type
= RES_TYPE_STRINGTABLE
;
1010 r
->u
.stringtable
= ((struct stringtable
*)
1011 res_alloc (sizeof (struct stringtable
)));
1012 for (i
= 0; i
< 16; i
++)
1014 r
->u
.stringtable
->strings
[i
].length
= 0;
1015 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1018 r
->res_info
= *resinfo
;
1021 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1022 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1026 /* Define a user data resource where the data is in the rc file. */
1029 define_user_data (id
, type
, resinfo
, data
)
1032 const struct res_res_info
*resinfo
;
1033 struct rcdata_item
*data
;
1035 struct res_id ids
[3];
1036 struct res_resource
*r
;
1041 ids
[2].u
.id
= resinfo
->language
;
1043 r
= define_resource (&resources
, 3, ids
, 0);
1044 r
->type
= RES_TYPE_USERDATA
;
1045 r
->u
.userdata
= data
;
1046 r
->res_info
= *resinfo
;
1049 /* Define a user data resource where the data is in a file. */
1052 define_user_file (id
, type
, resinfo
, filename
)
1055 const struct res_res_info
*resinfo
;
1056 const char *filename
;
1059 char *real_filename
;
1061 unsigned char *data
;
1062 struct res_id ids
[3];
1063 struct res_resource
*r
;
1065 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1067 if (stat (real_filename
, &s
) < 0)
1068 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1071 data
= (unsigned char *) res_alloc (s
.st_size
);
1073 get_data (e
, data
, s
.st_size
, real_filename
);
1076 free (real_filename
);
1081 ids
[2].u
.id
= resinfo
->language
;
1083 r
= define_resource (&resources
, 3, ids
, 0);
1084 r
->type
= RES_TYPE_USERDATA
;
1085 r
->u
.userdata
= ((struct rcdata_item
*)
1086 res_alloc (sizeof (struct rcdata_item
)));
1087 r
->u
.userdata
->next
= NULL
;
1088 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1089 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1090 r
->u
.userdata
->u
.buffer
.data
= data
;
1091 r
->res_info
= *resinfo
;
1094 /* Define a versioninfo resource. */
1097 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1100 struct fixed_versioninfo
*fixedverinfo
;
1101 struct ver_info
*verinfo
;
1103 struct res_resource
*r
;
1105 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1106 r
->type
= RES_TYPE_VERSIONINFO
;
1107 r
->u
.versioninfo
= ((struct versioninfo
*)
1108 res_alloc (sizeof (struct versioninfo
)));
1109 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1110 r
->u
.versioninfo
->var
= verinfo
;
1111 r
->res_info
.language
= language
;
1114 /* Add string version info to a list of version information. */
1117 append_ver_stringfileinfo (verinfo
, language
, strings
)
1118 struct ver_info
*verinfo
;
1119 const char *language
;
1120 struct ver_stringinfo
*strings
;
1122 struct ver_info
*vi
, **pp
;
1124 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1126 vi
->type
= VERINFO_STRING
;
1127 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1128 vi
->u
.string
.strings
= strings
;
1130 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1137 /* Add variable version info to a list of version information. */
1140 append_ver_varfileinfo (verinfo
, key
, var
)
1141 struct ver_info
*verinfo
;
1143 struct ver_varinfo
*var
;
1145 struct ver_info
*vi
, **pp
;
1147 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1149 vi
->type
= VERINFO_VAR
;
1150 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1151 vi
->u
.var
.var
= var
;
1153 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1160 /* Append version string information to a list. */
1162 struct ver_stringinfo
*
1163 append_verval (strings
, key
, value
)
1164 struct ver_stringinfo
*strings
;
1168 struct ver_stringinfo
*vs
, **pp
;
1170 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1172 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1173 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1175 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1182 /* Append version variable information to a list. */
1184 struct ver_varinfo
*
1185 append_vertrans (var
, language
, charset
)
1186 struct ver_varinfo
*var
;
1187 unsigned long language
;
1188 unsigned long charset
;
1190 struct ver_varinfo
*vv
, **pp
;
1192 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1194 vv
->language
= language
;
1195 vv
->charset
= charset
;
1197 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1204 /* Local functions used to write out an rc file. */
1206 static void indent
PARAMS ((FILE *, int));
1207 static void write_rc_directory
1208 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1209 const struct res_id
*, int *, int));
1210 static void write_rc_subdir
1211 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1212 const struct res_id
*, int *, int));
1213 static void write_rc_resource
1214 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1215 const struct res_resource
*, int *));
1216 static void write_rc_accelerators
1217 PARAMS ((FILE *, const struct accelerator
*));
1218 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1219 static void write_rc_group_cursor
1220 PARAMS ((FILE *, const struct group_cursor
*));
1221 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1222 static void write_rc_dialog_control
1223 PARAMS ((FILE *, const struct dialog_control
*));
1224 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1225 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1226 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1227 static void write_rc_menuitems
1228 PARAMS ((FILE *, const struct menuitem
*, int, int));
1229 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1230 static void write_rc_stringtable
1231 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1232 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1233 static void write_rc_filedata
1234 PARAMS ((FILE *, unsigned long, const unsigned char *));
1236 /* Indent a given number of spaces. */
1245 for (i
= 0; i
< c
; i
++)
1249 /* Dump the resources we have read in the format of an rc file.
1251 Actually, we don't use the format of an rc file, because it's way
1252 too much of a pain--for example, we'd have to write icon resources
1253 into a file and refer to that file. We just generate a readable
1254 format that kind of looks like an rc file, and is useful for
1255 understanding the contents of a resource file. Someday we may want
1256 to generate an rc file which the rc compiler can read; if that day
1257 comes, this code will have to be fixed up. */
1260 write_rc_file (filename
, resources
)
1261 const char *filename
;
1262 const struct res_directory
*resources
;
1267 if (filename
== NULL
)
1271 e
= fopen (filename
, FOPEN_WT
);
1273 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1277 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1278 (const struct res_id
*) NULL
, &language
, 1);
1281 /* Write out a directory. E is the file to write to. RD is the
1282 directory. TYPE is a pointer to the level 1 ID which serves as the
1283 resource type. NAME is a pointer to the level 2 ID which serves as
1284 an individual resource name. LANGUAGE is a pointer to the current
1285 language. LEVEL is the level in the tree. */
1288 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1290 const struct res_directory
*rd
;
1291 const struct res_id
*type
;
1292 const struct res_id
*name
;
1296 const struct res_entry
*re
;
1298 /* Print out some COFF information that rc files can't represent. */
1301 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1302 if (rd
->characteristics
!= 0)
1303 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1304 if (rd
->major
!= 0 || rd
->minor
!= 0)
1305 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1307 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1312 /* If we're at level 1, the key of this resource is the
1313 type. This normally duplicates the information we have
1314 stored with the resource itself, but we need to remember
1315 the type if this is a user define resource type. */
1320 /* If we're at level 2, the key of this resource is the name
1321 we are going to use in the rc printout. */
1326 /* If we're at level 3, then this key represents a language.
1327 Use it to update the current language. */
1329 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1330 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1332 fprintf (e
, "LANGUAGE %lu, %lu\n",
1333 re
->id
.u
.id
& 0xff, (re
->id
.u
.id
>> 8) & 0xff);
1334 *language
= re
->id
.u
.id
;
1343 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1348 /* This is the normal case: the three levels are
1349 TYPE/NAME/LANGUAGE. NAME will have been set at level
1350 2, and represents the name to use. We probably just
1351 set LANGUAGE, and it will probably match what the
1352 resource itself records if anything. */
1353 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1357 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1358 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1365 /* Write out a subdirectory entry. E is the file to write to. RE is
1366 the subdirectory entry. TYPE and NAME are pointers to higher level
1367 IDs, or NULL. LANGUAGE is a pointer to the current language.
1368 LEVEL is the level in the tree. */
1371 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1373 const struct res_entry
*re
;
1374 const struct res_id
*type
;
1375 const struct res_id
*name
;
1383 fprintf (e
, "// Type: ");
1385 res_id_print (e
, re
->id
, 1);
1390 switch (re
->id
.u
.id
)
1392 case RT_CURSOR
: s
= "cursor"; break;
1393 case RT_BITMAP
: s
= "bitmap"; break;
1394 case RT_ICON
: s
= "icon"; break;
1395 case RT_MENU
: s
= "menu"; break;
1396 case RT_DIALOG
: s
= "dialog"; break;
1397 case RT_STRING
: s
= "stringtable"; break;
1398 case RT_FONTDIR
: s
= "fontdir"; break;
1399 case RT_FONT
: s
= "font"; break;
1400 case RT_ACCELERATOR
: s
= "accelerators"; break;
1401 case RT_RCDATA
: s
= "rcdata"; break;
1402 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1403 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1404 case RT_GROUP_ICON
: s
= "group icon"; break;
1405 case RT_VERSION
: s
= "version"; break;
1406 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1407 case RT_PLUGPLAY
: s
= "plugplay"; break;
1408 case RT_VXD
: s
= "vxd"; break;
1409 case RT_ANICURSOR
: s
= "anicursor"; break;
1410 case RT_ANIICON
: s
= "aniicon"; break;
1411 default: s
= NULL
; break;
1415 fprintf (e
, "%s", s
);
1417 res_id_print (e
, re
->id
, 1);
1423 fprintf (e
, "// Name: ");
1424 res_id_print (e
, re
->id
, 1);
1429 fprintf (e
, "// Language: ");
1430 res_id_print (e
, re
->id
, 1);
1435 fprintf (e
, "// Level %d: ", level
);
1436 res_id_print (e
, re
->id
, 1);
1440 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1443 /* Write out a single resource. E is the file to write to. TYPE is a
1444 pointer to the type of the resource. NAME is a pointer to the name
1445 of the resource; it will be NULL if there is a level mismatch. RES
1446 is the resource data. LANGUAGE is a pointer to the current
1450 write_rc_resource (e
, type
, name
, res
, language
)
1452 const struct res_id
*type
;
1453 const struct res_id
*name
;
1454 const struct res_resource
*res
;
1468 case RES_TYPE_ACCELERATOR
:
1470 rt
= RT_ACCELERATOR
;
1473 case RES_TYPE_BITMAP
:
1478 case RES_TYPE_CURSOR
:
1483 case RES_TYPE_GROUP_CURSOR
:
1485 rt
= RT_GROUP_CURSOR
;
1488 case RES_TYPE_DIALOG
:
1489 if (extended_dialog (res
->u
.dialog
))
1501 case RES_TYPE_FONTDIR
:
1511 case RES_TYPE_GROUP_ICON
:
1517 if (extended_menu (res
->u
.menu
))
1530 case RES_TYPE_MESSAGETABLE
:
1532 rt
= RT_MESSAGETABLE
;
1535 case RES_TYPE_RCDATA
:
1540 case RES_TYPE_STRINGTABLE
:
1545 case RES_TYPE_USERDATA
:
1550 case RES_TYPE_VERSIONINFO
:
1558 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1560 fprintf (e
, "// Unexpected resource type mismatch: ");
1561 res_id_print (e
, *type
, 1);
1562 fprintf (e
, " != %d", rt
);
1565 if (res
->coff_info
.codepage
!= 0)
1566 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1567 if (res
->coff_info
.reserved
!= 0)
1568 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1571 res_id_print (e
, *name
, 0);
1573 fprintf (e
, "??Unknown-Name??");
1577 fprintf (e
, "%s", s
);
1578 else if (type
!= NULL
)
1579 res_id_print (e
, *type
, 0);
1581 fprintf (e
, "??Unknown-Type??");
1583 if (res
->res_info
.memflags
!= 0)
1585 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1586 fprintf (e
, " MOVEABLE");
1587 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1588 fprintf (e
, " PURE");
1589 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1590 fprintf (e
, " PRELOAD");
1591 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1592 fprintf (e
, " DISCARDABLE");
1595 if (res
->type
== RES_TYPE_DIALOG
)
1597 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1598 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1599 if (res
->u
.dialog
->ex
!= NULL
1600 && res
->u
.dialog
->ex
->help
!= 0)
1601 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1606 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1607 || res
->res_info
.characteristics
!= 0
1608 || res
->res_info
.version
!= 0)
1614 case RES_TYPE_ACCELERATOR
:
1615 case RES_TYPE_DIALOG
:
1617 case RES_TYPE_RCDATA
:
1618 case RES_TYPE_STRINGTABLE
:
1627 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1628 fprintf (e
, "%sLANGUAGE %d, %d\n",
1629 modifiers
? "// " : "",
1630 res
->res_info
.language
& 0xff,
1631 (res
->res_info
.language
>> 8) & 0xff);
1632 if (res
->res_info
.characteristics
!= 0)
1633 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1634 modifiers
? "// " : "",
1635 res
->res_info
.characteristics
);
1636 if (res
->res_info
.version
!= 0)
1637 fprintf (e
, "%sVERSION %lu\n",
1638 modifiers
? "// " : "",
1639 res
->res_info
.version
);
1647 case RES_TYPE_ACCELERATOR
:
1648 write_rc_accelerators (e
, res
->u
.acc
);
1651 case RES_TYPE_CURSOR
:
1652 write_rc_cursor (e
, res
->u
.cursor
);
1655 case RES_TYPE_GROUP_CURSOR
:
1656 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1659 case RES_TYPE_DIALOG
:
1660 write_rc_dialog (e
, res
->u
.dialog
);
1663 case RES_TYPE_FONTDIR
:
1664 write_rc_fontdir (e
, res
->u
.fontdir
);
1667 case RES_TYPE_GROUP_ICON
:
1668 write_rc_group_icon (e
, res
->u
.group_icon
);
1672 write_rc_menu (e
, res
->u
.menu
, menuex
);
1675 case RES_TYPE_RCDATA
:
1676 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1679 case RES_TYPE_STRINGTABLE
:
1680 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1683 case RES_TYPE_USERDATA
:
1684 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1687 case RES_TYPE_VERSIONINFO
:
1688 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1691 case RES_TYPE_BITMAP
:
1694 case RES_TYPE_MESSAGETABLE
:
1695 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1700 /* Write out accelerator information. */
1703 write_rc_accelerators (e
, accelerators
)
1705 const struct accelerator
*accelerators
;
1707 const struct accelerator
*acc
;
1709 fprintf (e
, "BEGIN\n");
1710 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1716 if ((acc
->key
& 0x7f) == acc
->key
1717 && isprint ((unsigned char) acc
->key
)
1718 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1720 fprintf (e
, "\"%c\"", acc
->key
);
1725 fprintf (e
, "%d", acc
->key
);
1729 fprintf (e
, ", %d", acc
->id
);
1733 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1734 fprintf (e
, ", VIRTKEY");
1736 fprintf (e
, ", ASCII");
1739 if ((acc
->flags
& ACC_SHIFT
) != 0)
1740 fprintf (e
, ", SHIFT");
1741 if ((acc
->flags
& ACC_CONTROL
) != 0)
1742 fprintf (e
, ", CONTROL");
1743 if ((acc
->flags
& ACC_ALT
) != 0)
1744 fprintf (e
, ", ALT");
1749 fprintf (e
, "END\n");
1752 /* Write out cursor information. This would normally be in a separate
1753 file, which the rc file would include. */
1756 write_rc_cursor (e
, cursor
)
1758 const struct cursor
*cursor
;
1760 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
1762 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
1765 /* Write out group cursor data. This would normally be built from the
1769 write_rc_group_cursor (e
, group_cursor
)
1771 const struct group_cursor
*group_cursor
;
1773 const struct group_cursor
*gc
;
1775 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
1777 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
1778 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
1779 fprintf (e
, "// data bytes: %lu; index: %d\n",
1780 gc
->bytes
, gc
->index
);
1784 /* Write dialog data. */
1787 write_rc_dialog (e
, dialog
)
1789 const struct dialog
*dialog
;
1791 const struct dialog_control
*control
;
1793 if (dialog
->style
!= 0)
1794 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
1795 if (dialog
->exstyle
!= 0)
1796 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
1797 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
1798 || dialog
->class.u
.id
!= 0)
1800 fprintf (e
, "CLASS ");
1801 res_id_print (e
, dialog
->class, 0);
1804 if (dialog
->caption
!= NULL
)
1806 fprintf (e
, "CAPTION \"");
1807 unicode_print (e
, dialog
->caption
, -1);
1808 fprintf (e
, "\"\n");
1810 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
1811 || dialog
->menu
.u
.id
!= 0)
1813 fprintf (e
, "MENU ");
1814 res_id_print (e
, dialog
->menu
, 0);
1817 if (dialog
->font
!= NULL
)
1819 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
1820 unicode_print (e
, dialog
->font
, -1);
1822 if (dialog
->ex
!= NULL
1823 && (dialog
->ex
->weight
!= 0 || dialog
->ex
->italic
!= 0))
1824 fprintf (e
, ", %d, %d", dialog
->ex
->weight
, dialog
->ex
->italic
);
1828 fprintf (e
, "BEGIN\n");
1830 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
1831 write_rc_dialog_control (e
, control
);
1833 fprintf (e
, "END\n");
1836 /* For each predefined control keyword, this table provides the class
1842 unsigned short class;
1843 unsigned long style
;
1846 static const struct control_info control_info
[] =
1848 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
1849 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
1850 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
1851 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
1852 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
1853 { "CTEXT", CTL_STATIC
, SS_CENTER
},
1854 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
1855 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
1856 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
1857 { "ICON", CTL_STATIC
, SS_ICON
},
1858 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
1859 { "LTEXT", CTL_STATIC
, SS_LEFT
},
1860 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
1861 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
1862 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
1863 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
1864 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
1865 { "STATE3", CTL_BUTTON
, BS_3STATE
},
1866 /* It's important that USERBUTTON come after all the other button
1867 types, so that it won't be matched too early. */
1868 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
1872 /* Write a dialog control. */
1875 write_rc_dialog_control (e
, control
)
1877 const struct dialog_control
*control
;
1879 const struct control_info
*ci
;
1883 if (control
->class.named
)
1887 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
1888 if (ci
->class == control
->class.u
.id
1889 && (ci
->style
== (unsigned long) -1
1890 || ci
->style
== (control
->style
& 0xff)))
1894 fprintf (e
, "CONTROL");
1895 else if (ci
->name
!= NULL
)
1896 fprintf (e
, "%s", ci
->name
);
1898 fprintf (e
, "CONTROL");
1900 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
1903 res_id_print (e
, control
->text
, 1);
1907 fprintf (e
, " %d, ", control
->id
);
1911 if (control
->class.named
)
1913 res_id_print (e
, control
->class, 0);
1914 if (control
->class.named
)
1916 fprintf (e
, ", 0x%lx, ", control
->style
);
1919 fprintf (e
, "%d, %d", control
->x
, control
->y
);
1921 if (control
->style
!= SS_ICON
1922 || control
->exstyle
!= 0
1923 || control
->width
!= 0
1924 || control
->height
!= 0
1925 || control
->help
!= 0)
1927 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
1929 /* FIXME: We don't need to print the style if it is the default.
1930 More importantly, in certain cases we actually need to turn
1931 off parts of the forced style, by using NOT. */
1932 fprintf (e
, ", 0x%lx", control
->style
);
1934 if (control
->exstyle
!= 0 || control
->help
!= 0)
1935 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
1940 if (control
->data
!= NULL
)
1941 write_rc_rcdata (e
, control
->data
, 2);
1944 /* Write out font directory data. This would normally be built from
1948 write_rc_fontdir (e
, fontdir
)
1950 const struct fontdir
*fontdir
;
1952 const struct fontdir
*fc
;
1954 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
1956 fprintf (e
, "// Font index: %d\n", fc
->index
);
1957 write_rc_filedata (e
, fc
->length
, fc
->data
);
1961 /* Write out group icon data. This would normally be built from the
1965 write_rc_group_icon (e
, group_icon
)
1967 const struct group_icon
*group_icon
;
1969 const struct group_icon
*gi
;
1971 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
1973 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1974 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
1975 fprintf (e
, "// data bytes: %lu; index: %d\n",
1976 gi
->bytes
, gi
->index
);
1980 /* Write out a menu resource. */
1983 write_rc_menu (e
, menu
, menuex
)
1985 const struct menu
*menu
;
1988 if (menu
->help
!= 0)
1989 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
1990 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
1993 /* Write out menuitems. */
1996 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
1998 const struct menuitem
*menuitems
;
2002 const struct menuitem
*mi
;
2005 fprintf (e
, "BEGIN\n");
2007 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2009 indent (e
, ind
+ 2);
2011 if (mi
->popup
== NULL
)
2012 fprintf (e
, "MENUITEM");
2014 fprintf (e
, "POPUP");
2017 && mi
->popup
== NULL
2022 fprintf (e
, " SEPARATOR\n");
2026 if (mi
->text
== NULL
)
2027 fprintf (e
, " \"\"");
2031 unicode_print (e
, mi
->text
, -1);
2037 if (mi
->popup
== NULL
)
2038 fprintf (e
, ", %d", mi
->id
);
2040 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2041 fprintf (e
, ", CHECKED");
2042 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2043 fprintf (e
, ", GRAYED");
2044 if ((mi
->type
& MENUITEM_HELP
) != 0)
2045 fprintf (e
, ", HELP");
2046 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2047 fprintf (e
, ", INACTIVE");
2048 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2049 fprintf (e
, ", MENUBARBREAK");
2050 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2051 fprintf (e
, ", MENUBREAK");
2055 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2057 fprintf (e
, ", %d", mi
->id
);
2058 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2060 fprintf (e
, ", %lu", mi
->type
);
2061 if (mi
->state
!= 0 || mi
->help
!= 0)
2063 fprintf (e
, ", %lu", mi
->state
);
2065 fprintf (e
, ", %lu", mi
->help
);
2073 if (mi
->popup
!= NULL
)
2074 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2078 fprintf (e
, "END\n");
2081 /* Write out an rcdata resource. This is also used for other types of
2082 resources that need to print arbitrary data. */
2085 write_rc_rcdata (e
, rcdata
, ind
)
2087 const struct rcdata_item
*rcdata
;
2090 const struct rcdata_item
*ri
;
2093 fprintf (e
, "BEGIN\n");
2095 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2097 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2100 indent (e
, ind
+ 2);
2108 fprintf (e
, "%d", ri
->u
.word
);
2112 fprintf (e
, "%luL", ri
->u
.dword
);
2122 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2124 if (isprint ((unsigned char) *s
))
2127 fprintf (e
, "\\%03o", *s
);
2133 case RCDATA_WSTRING
:
2135 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2144 /* Assume little endian data. */
2147 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2151 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2152 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2153 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2154 | ri
->u
.buffer
.data
[i
]);
2160 indent (e
, ind
+ 2);
2162 fprintf (e
, "%luL", l
);
2165 if (i
+ 1 < ri
->u
.buffer
.length
)
2169 i
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2175 indent (e
, ind
+ 2);
2177 fprintf (e
, "%d", i
);
2181 if (i
< ri
->u
.buffer
.length
)
2188 indent (e
, ind
+ 2);
2190 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2191 && isprint (ri
->u
.buffer
.data
[i
]))
2192 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2194 fprintf (e
, "\"\%03o\"", ri
->u
.buffer
.data
[i
]);
2201 if (ri
->next
!= NULL
)
2207 fprintf (e
, "END\n");
2210 /* Write out a stringtable resource. */
2213 write_rc_stringtable (e
, name
, stringtable
)
2215 const struct res_id
*name
;
2216 const struct stringtable
*stringtable
;
2218 unsigned long offset
;
2221 if (name
!= NULL
&& ! name
->named
)
2222 offset
= (name
->u
.id
- 1) << 4;
2225 fprintf (e
, "// %s string table name\n",
2226 name
== NULL
? "Missing" : "Invalid");
2230 fprintf (e
, "BEGIN\n");
2232 for (i
= 0; i
< 16; i
++)
2234 if (stringtable
->strings
[i
].length
!= 0)
2236 fprintf (e
, " %lu, \"", offset
+ i
);
2237 unicode_print (e
, stringtable
->strings
[i
].string
,
2238 stringtable
->strings
[i
].length
);
2239 fprintf (e
, "\"\n");
2243 fprintf (e
, "END\n");
2246 /* Write out a versioninfo resource. */
2249 write_rc_versioninfo (e
, versioninfo
)
2251 const struct versioninfo
*versioninfo
;
2253 const struct fixed_versioninfo
*f
;
2254 const struct ver_info
*vi
;
2256 f
= versioninfo
->fixed
;
2257 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2258 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2259 (f
->file_version_ms
>> 16) & 0xffff,
2260 f
->file_version_ms
& 0xffff,
2261 (f
->file_version_ls
>> 16) & 0xffff,
2262 f
->file_version_ls
& 0xffff);
2263 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2264 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2265 (f
->product_version_ms
>> 16) & 0xffff,
2266 f
->product_version_ms
& 0xffff,
2267 (f
->product_version_ls
>> 16) & 0xffff,
2268 f
->product_version_ls
& 0xffff);
2269 if (f
->file_flags_mask
!= 0)
2270 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2271 if (f
->file_flags
!= 0)
2272 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2273 if (f
->file_os
!= 0)
2274 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2275 if (f
->file_type
!= 0)
2276 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2277 if (f
->file_subtype
!= 0)
2278 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2279 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2280 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2282 fprintf (e
, "BEGIN\n");
2284 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2288 case VERINFO_STRING
:
2290 const struct ver_stringinfo
*vs
;
2292 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2293 fprintf (e
, " BEGIN\n");
2294 fprintf (e
, " BLOCK \"");
2295 unicode_print (e
, vi
->u
.string
.language
, -1);
2296 fprintf (e
, "\"\n");
2297 fprintf (e
, " BEGIN\n");
2299 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2301 fprintf (e
, " VALUE \"");
2302 unicode_print (e
, vs
->key
, -1);
2303 fprintf (e
, "\", \"");
2304 unicode_print (e
, vs
->value
, -1);
2305 fprintf (e
, "\"\n");
2308 fprintf (e
, " END\n");
2309 fprintf (e
, " END\n");
2315 const struct ver_varinfo
*vv
;
2317 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2318 fprintf (e
, " BEGIN\n");
2319 fprintf (e
, " VALUE \"");
2320 unicode_print (e
, vi
->u
.var
.key
, -1);
2323 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2324 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2327 fprintf (e
, "\n END\n");
2334 fprintf (e
, "END\n");
2337 /* Write out data which would normally be read from a file. */
2340 write_rc_filedata (e
, length
, data
)
2342 unsigned long length
;
2343 const unsigned char *data
;
2347 for (i
= 0; i
+ 15 < length
; i
+= 16)
2349 fprintf (e
, "// %4lx: ", i
);
2350 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2351 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2352 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2353 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2354 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2355 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2360 fprintf (e
, "// %4lx:", i
);
2363 fprintf (e
, " %02x", data
[i
]);