1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 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"
28 #include "safe-ctype.h"
38 #ifdef HAVE_SYS_WAIT_H
40 #else /* ! HAVE_SYS_WAIT_H */
41 #if ! defined (_WIN32) || defined (__CYGWIN__)
43 #define WIFEXITED(w) (((w)&0377) == 0)
46 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
49 #define WTERMSIG(w) ((w) & 0177)
52 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
54 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
56 #define WIFEXITED(w) (((w) & 0xff) == 0)
59 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
62 #define WTERMSIG(w) ((w) & 0x7f)
65 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
67 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
68 #endif /* ! HAVE_SYS_WAIT_H */
71 #define STDOUT_FILENO 1
74 #if defined (_WIN32) && ! defined (__CYGWIN__)
76 #define pclose _pclose
79 /* The default preprocessor. */
81 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
83 /* We read the directory entries in a cursor or icon file into
84 instances of this structure. */
90 /* Height of image. */
92 /* Number of colors in image. */
93 unsigned char colorcount
;
99 unsigned short planes
;
100 /* Bits per pixel. */
105 /* X coordinate of hotspot. */
106 unsigned short xhotspot
;
107 /* Y coordinate of hotspot. */
108 unsigned short yhotspot
;
111 /* Bytes in image. */
113 /* File offset of image. */
114 unsigned long offset
;
117 /* The name of the rc file we are reading. */
121 /* The line number in the rc file. */
125 /* The pipe we are reading from, so that we can close it if we exit. */
127 static FILE *cpp_pipe
;
129 /* The temporary file used if we're not using popen, so we can delete it
132 static char *cpp_temp_file
;
134 /* Input stream is either a file or a pipe. */
136 static enum {ISTREAM_PIPE
, ISTREAM_FILE
} istream_type
;
138 /* As we read the rc file, we attach information to this structure. */
140 static struct res_directory
*resources
;
142 /* The number of cursor resources we have written out. */
146 /* The number of font resources we have written out. */
150 /* Font directory information. */
152 struct fontdir
*fontdirs
;
154 /* Resource info to use for fontdirs. */
156 struct res_res_info fontdirs_resinfo
;
158 /* The number of icon resources we have written out. */
162 /* Local functions. */
164 static int run_cmd (char *, const char *);
165 static FILE *open_input_stream (char *);
166 static FILE *look_for_default
167 (char *, const char *, int, const char *, const char *);
168 static void close_input_stream (void);
169 static void unexpected_eof (const char *);
170 static int get_word (FILE *, const char *);
171 static unsigned long get_long (FILE *, const char *);
172 static void get_data (FILE *, unsigned char *, unsigned long, const char *);
173 static void define_fontdirs (void);
175 /* Run `cmd' and redirect the output to `redir'. */
178 run_cmd (char *cmd
, const char *redir
)
181 int pid
, wait_status
, retcode
;
184 char *errmsg_fmt
, *errmsg_arg
;
185 char *temp_base
= choose_temp_base ();
188 int redir_handle
= -1;
189 int stdout_save
= -1;
191 /* Count the args. */
194 for (s
= cmd
; *s
; s
++)
199 argv
= alloca (sizeof (char *) * (i
+ 3));
205 while (*s
== ' ' && *s
!= 0)
211 in_quote
= (*s
== '\'' || *s
== '"');
212 sep
= (in_quote
) ? *s
++ : ' ';
215 while (*s
!= sep
&& *s
!= 0)
228 /* Setup the redirection. We can't use the usual fork/exec and redirect
229 since we may be running on non-POSIX Windows host. */
234 /* Open temporary output file. */
235 redir_handle
= open (redir
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
236 if (redir_handle
== -1)
237 fatal (_("can't open temporary file `%s': %s"), redir
,
240 /* Duplicate the stdout file handle so it can be restored later. */
241 stdout_save
= dup (STDOUT_FILENO
);
242 if (stdout_save
== -1)
243 fatal (_("can't redirect stdout: `%s': %s"), redir
, strerror (errno
));
245 /* Redirect stdout to our output file. */
246 dup2 (redir_handle
, STDOUT_FILENO
);
248 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
249 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
251 /* Restore stdout to its previous setting. */
252 dup2 (stdout_save
, STDOUT_FILENO
);
254 /* Close reponse file. */
255 close (redir_handle
);
259 fatal (_("%s %s: %s"), errmsg_fmt
, errmsg_arg
, strerror (errno
));
264 pid
= pwait (pid
, &wait_status
, 0);
268 fatal (_("wait: %s"), strerror (errno
));
271 else if (WIFSIGNALED (wait_status
))
273 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status
));
276 else if (WIFEXITED (wait_status
))
278 if (WEXITSTATUS (wait_status
) != 0)
280 fatal (_("%s exited with status %d"), cmd
,
281 WEXITSTATUS (wait_status
));
292 open_input_stream (char *cmd
)
294 if (istream_type
== ISTREAM_FILE
)
298 fileprefix
= choose_temp_base ();
299 cpp_temp_file
= (char *) xmalloc (strlen (fileprefix
) + 5);
300 sprintf (cpp_temp_file
, "%s.irc", fileprefix
);
303 if (run_cmd (cmd
, cpp_temp_file
))
304 fatal (_("can't execute `%s': %s"), cmd
, strerror (errno
));
306 cpp_pipe
= fopen (cpp_temp_file
, FOPEN_RT
);;
307 if (cpp_pipe
== NULL
)
308 fatal (_("can't open temporary file `%s': %s"),
309 cpp_temp_file
, strerror (errno
));
313 _("Using temporary file `%s' to read preprocessor output\n"),
318 cpp_pipe
= popen (cmd
, FOPEN_RT
);
319 if (cpp_pipe
== NULL
)
320 fatal (_("can't popen `%s': %s"), cmd
, strerror (errno
));
322 fprintf (stderr
, _("Using popen to read preprocessor output\n"));
325 xatexit (close_input_stream
);
329 /* look for the preprocessor program */
332 look_for_default (char *cmd
, const char *prefix
, int end_prefix
,
333 const char *preprocargs
, const char *filename
)
339 strcpy (cmd
, prefix
);
341 sprintf (cmd
+ end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
342 space
= strchr (cmd
+ end_prefix
, ' ');
347 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
348 strchr (cmd
, '\\') ||
352 found
= (stat (cmd
, &s
) == 0
353 #ifdef HAVE_EXECUTABLE_SUFFIX
354 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
361 fprintf (stderr
, _("Tried `%s'\n"), cmd
);
366 strcpy (cmd
, prefix
);
368 sprintf (cmd
+ end_prefix
, "%s %s %s",
369 DEFAULT_PREPROCESSOR
, preprocargs
, filename
);
372 fprintf (stderr
, _("Using `%s'\n"), cmd
);
374 cpp_pipe
= open_input_stream (cmd
);
378 /* Read an rc file. */
380 struct res_directory
*
381 read_rc_file (const char *filename
, const char *preprocessor
,
382 const char *preprocargs
, int language
, int use_temp_file
)
386 istream_type
= (use_temp_file
) ? ISTREAM_FILE
: ISTREAM_PIPE
;
388 if (preprocargs
== NULL
)
390 if (filename
== NULL
)
395 cmd
= xmalloc (strlen (preprocessor
)
396 + strlen (preprocargs
)
399 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
401 cpp_pipe
= open_input_stream (cmd
);
405 char *dash
, *slash
, *cp
;
407 preprocessor
= DEFAULT_PREPROCESSOR
;
409 cmd
= xmalloc (strlen (program_name
)
410 + strlen (preprocessor
)
411 + strlen (preprocargs
)
413 #ifdef HAVE_EXECUTABLE_SUFFIX
414 + strlen (EXECUTABLE_SUFFIX
)
420 for (cp
= program_name
; *cp
; cp
++)
425 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
426 *cp
== ':' || *cp
== '\\' ||
439 /* First, try looking for a prefixed gcc in the windres
440 directory, with the same prefix as windres */
442 cpp_pipe
= look_for_default (cmd
, program_name
, dash
-program_name
+1,
443 preprocargs
, filename
);
446 if (slash
&& !cpp_pipe
)
448 /* Next, try looking for a gcc in the same directory as
451 cpp_pipe
= look_for_default (cmd
, program_name
, slash
-program_name
+1,
452 preprocargs
, filename
);
457 /* Sigh, try the default */
459 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
466 rc_filename
= xstrdup (filename
);
469 rcparse_set_language (language
);
472 rcparse_discard_strings ();
474 close_input_stream ();
476 if (fontdirs
!= NULL
)
485 /* Close the input stream if it is open. */
488 close_input_stream (void)
490 if (istream_type
== ISTREAM_FILE
)
492 if (cpp_pipe
!= NULL
)
495 if (cpp_temp_file
!= NULL
)
497 int errno_save
= errno
;
499 unlink (cpp_temp_file
);
501 free (cpp_temp_file
);
506 if (cpp_pipe
!= NULL
)
510 /* Since this is also run via xatexit, safeguard. */
512 cpp_temp_file
= NULL
;
515 /* Report an error while reading an rc file. */
518 yyerror (const char *msg
)
520 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
523 /* Issue a warning while reading an rc file. */
526 rcparse_warning (const char *msg
)
528 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
531 /* Die if we get an unexpected end of file. */
534 unexpected_eof (const char *msg
)
536 fatal (_("%s: unexpected EOF"), msg
);
539 /* Read a 16 bit word from a file. The data is assumed to be little
543 get_word (FILE *e
, const char *msg
)
550 unexpected_eof (msg
);
551 return ((b2
& 0xff) << 8) | (b1
& 0xff);
554 /* Read a 32 bit word from a file. The data is assumed to be little
558 get_long (FILE *e
, const char *msg
)
567 unexpected_eof (msg
);
568 return (((((((b4
& 0xff) << 8)
574 /* Read data from a file. This is a wrapper to do error checking. */
577 get_data (FILE *e
, unsigned char *p
, unsigned long c
, const char *msg
)
581 got
= fread (p
, 1, c
, e
);
585 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
588 /* Define an accelerator resource. */
591 define_accelerator (struct res_id id
, const struct res_res_info
*resinfo
,
592 struct accelerator
*data
)
594 struct res_resource
*r
;
596 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
597 resinfo
->language
, 0);
598 r
->type
= RES_TYPE_ACCELERATOR
;
600 r
->res_info
= *resinfo
;
603 /* Define a bitmap resource. Bitmap data is stored in a file. The
604 first 14 bytes of the file are a standard header, which is not
605 included in the resource data. */
607 #define BITMAP_SKIP (14)
610 define_bitmap (struct res_id id
, const struct res_res_info
*resinfo
,
611 const char *filename
)
618 struct res_resource
*r
;
620 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
622 if (stat (real_filename
, &s
) < 0)
623 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
626 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
628 for (i
= 0; i
< BITMAP_SKIP
; i
++)
631 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
634 free (real_filename
);
636 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
637 resinfo
->language
, 0);
639 r
->type
= RES_TYPE_BITMAP
;
640 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
641 r
->u
.data
.data
= data
;
642 r
->res_info
= *resinfo
;
645 /* Define a cursor resource. A cursor file may contain a set of
646 bitmaps, each representing the same cursor at various different
647 resolutions. They each get written out with a different ID. The
648 real cursor resource is then a group resource which can be used to
649 select one of the actual cursors. */
652 define_cursor (struct res_id id
, const struct res_res_info
*resinfo
,
653 const char *filename
)
658 struct icondir
*icondirs
;
660 struct res_resource
*r
;
661 struct group_cursor
*first
, **pp
;
663 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
665 /* A cursor file is basically an icon file. The start of the file
666 is a three word structure. The first word is ignored. The
667 second word is the type of data. The third word is the number of
670 get_word (e
, real_filename
);
671 type
= get_word (e
, real_filename
);
672 count
= get_word (e
, real_filename
);
674 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
676 /* Read in the icon directory entries. */
678 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
680 for (i
= 0; i
< count
; i
++)
682 icondirs
[i
].width
= getc (e
);
683 icondirs
[i
].height
= getc (e
);
684 icondirs
[i
].colorcount
= getc (e
);
686 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
687 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
688 icondirs
[i
].bytes
= get_long (e
, real_filename
);
689 icondirs
[i
].offset
= get_long (e
, real_filename
);
692 unexpected_eof (real_filename
);
695 /* Define each cursor as a unique resource. */
697 first_cursor
= cursors
;
699 for (i
= 0; i
< count
; i
++)
705 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
706 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
707 icondirs
[i
].offset
, strerror (errno
));
709 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
711 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
713 c
= (struct cursor
*) res_alloc (sizeof *c
);
714 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
715 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
716 c
->length
= icondirs
[i
].bytes
;
724 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
725 resinfo
->language
, 0);
726 r
->type
= RES_TYPE_CURSOR
;
728 r
->res_info
= *resinfo
;
732 free (real_filename
);
734 /* Define a cursor group resource. */
738 for (i
= 0; i
< count
; i
++)
740 struct group_cursor
*cg
;
742 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
744 cg
->width
= icondirs
[i
].width
;
745 cg
->height
= 2 * icondirs
[i
].height
;
747 /* FIXME: What should these be set to? */
751 cg
->bytes
= icondirs
[i
].bytes
+ 4;
752 cg
->index
= first_cursor
+ i
+ 1;
760 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
761 resinfo
->language
, 0);
762 r
->type
= RES_TYPE_GROUP_CURSOR
;
763 r
->u
.group_cursor
= first
;
764 r
->res_info
= *resinfo
;
767 /* Define a dialog resource. */
770 define_dialog (struct res_id id
, const struct res_res_info
*resinfo
,
771 const struct dialog
*dialog
)
774 struct res_resource
*r
;
776 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
779 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
780 resinfo
->language
, 0);
781 r
->type
= RES_TYPE_DIALOG
;
783 r
->res_info
= *resinfo
;
786 /* Define a dialog control. This does not define a resource, but
787 merely allocates and fills in a structure. */
789 struct dialog_control
*
790 define_control (const struct res_id iid
, unsigned long id
, unsigned long x
,
791 unsigned long y
, unsigned long width
, unsigned long height
,
792 unsigned long class, unsigned long style
,
793 unsigned long exstyle
)
795 struct dialog_control
*n
;
797 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
801 n
->exstyle
= exstyle
;
807 n
->class.u
.id
= class;
815 struct dialog_control
*
816 define_icon_control (struct res_id iid
, unsigned long id
, unsigned long x
,
817 unsigned long y
, unsigned long style
,
818 unsigned long exstyle
, unsigned long help
,
819 struct rcdata_item
*data
, struct dialog_ex
*ex
)
821 struct dialog_control
*n
;
825 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
826 res_string_to_id (&tid
, "");
827 n
= define_control (tid
, id
, x
, y
, 0, 0, CTL_STATIC
, style
, exstyle
);
830 rcparse_warning (_("help ID requires DIALOGEX"));
832 rcparse_warning (_("control data requires DIALOGEX"));
839 /* Define a font resource. */
842 define_font (struct res_id id
, const struct res_res_info
*resinfo
,
843 const char *filename
)
849 struct res_resource
*r
;
852 unsigned char *fontdata
;
854 const char *device
, *face
;
857 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
859 if (stat (real_filename
, &s
) < 0)
860 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
863 data
= (unsigned char *) res_alloc (s
.st_size
);
865 get_data (e
, data
, s
.st_size
, real_filename
);
868 free (real_filename
);
870 r
= define_standard_resource (&resources
, RT_FONT
, id
,
871 resinfo
->language
, 0);
873 r
->type
= RES_TYPE_FONT
;
874 r
->u
.data
.length
= s
.st_size
;
875 r
->u
.data
.data
= data
;
876 r
->res_info
= *resinfo
;
878 /* For each font resource, we must add an entry in the FONTDIR
879 resource. The FONTDIR resource includes some strings in the font
880 file. To find them, we have to do some magic on the data we have
883 offset
= ((((((data
[47] << 8)
887 if (offset
> 0 && offset
< s
.st_size
)
888 device
= (char *) data
+ offset
;
892 offset
= ((((((data
[51] << 8)
896 if (offset
> 0 && offset
< s
.st_size
)
897 face
= (char *) data
+ offset
;
903 fontdatalength
= 58 + strlen (device
) + strlen (face
);
904 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
905 memcpy (fontdata
, data
, 56);
906 strcpy ((char *) fontdata
+ 56, device
);
907 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
909 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
912 fd
->length
= fontdatalength
;
915 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
919 /* For the single fontdirs resource, we always use the resource
920 information of the last font. I don't know what else to do. */
921 fontdirs_resinfo
= *resinfo
;
924 /* Define the fontdirs resource. This is called after the entire rc
925 file has been parsed, if any font resources were seen. */
928 define_fontdirs (void)
930 struct res_resource
*r
;
936 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
938 r
->type
= RES_TYPE_FONTDIR
;
939 r
->u
.fontdir
= fontdirs
;
940 r
->res_info
= fontdirs_resinfo
;
943 /* Define an icon resource. An icon file may contain a set of
944 bitmaps, each representing the same icon at various different
945 resolutions. They each get written out with a different ID. The
946 real icon resource is then a group resource which can be used to
947 select one of the actual icon bitmaps. */
950 define_icon (struct res_id id
, const struct res_res_info
*resinfo
,
951 const char *filename
)
956 struct icondir
*icondirs
;
958 struct res_resource
*r
;
959 struct group_icon
*first
, **pp
;
961 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
963 /* The start of an icon file is a three word structure. The first
964 word is ignored. The second word is the type of data. The third
965 word is the number of entries. */
967 get_word (e
, real_filename
);
968 type
= get_word (e
, real_filename
);
969 count
= get_word (e
, real_filename
);
971 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
973 /* Read in the icon directory entries. */
975 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
977 for (i
= 0; i
< count
; i
++)
979 icondirs
[i
].width
= getc (e
);
980 icondirs
[i
].height
= getc (e
);
981 icondirs
[i
].colorcount
= getc (e
);
983 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
984 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
985 icondirs
[i
].bytes
= get_long (e
, real_filename
);
986 icondirs
[i
].offset
= get_long (e
, real_filename
);
989 unexpected_eof (real_filename
);
992 /* Define each icon as a unique resource. */
996 for (i
= 0; i
< count
; i
++)
1001 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1002 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1003 icondirs
[i
].offset
, strerror (errno
));
1005 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1007 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1014 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1015 resinfo
->language
, 0);
1016 r
->type
= RES_TYPE_ICON
;
1017 r
->u
.data
.length
= icondirs
[i
].bytes
;
1018 r
->u
.data
.data
= data
;
1019 r
->res_info
= *resinfo
;
1023 free (real_filename
);
1025 /* Define an icon group resource. */
1029 for (i
= 0; i
< count
; i
++)
1031 struct group_icon
*cg
;
1033 /* For some reason, at least in some files the planes and bits
1034 are zero. We instead set them from the color. This is
1037 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1039 cg
->width
= icondirs
[i
].width
;
1040 cg
->height
= icondirs
[i
].height
;
1041 cg
->colors
= icondirs
[i
].colorcount
;
1045 while ((1 << cg
->bits
) < cg
->colors
)
1048 cg
->bytes
= icondirs
[i
].bytes
;
1049 cg
->index
= first_icon
+ i
+ 1;
1057 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1058 resinfo
->language
, 0);
1059 r
->type
= RES_TYPE_GROUP_ICON
;
1060 r
->u
.group_icon
= first
;
1061 r
->res_info
= *resinfo
;
1064 /* Define a menu resource. */
1067 define_menu (struct res_id id
, const struct res_res_info
*resinfo
,
1068 struct menuitem
*menuitems
)
1071 struct res_resource
*r
;
1073 m
= (struct menu
*) res_alloc (sizeof *m
);
1074 m
->items
= menuitems
;
1077 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1078 r
->type
= RES_TYPE_MENU
;
1080 r
->res_info
= *resinfo
;
1083 /* Define a menu item. This does not define a resource, but merely
1084 allocates and fills in a structure. */
1087 define_menuitem (const char *text
, int menuid
, unsigned long type
,
1088 unsigned long state
, unsigned long help
,
1089 struct menuitem
*menuitems
)
1091 struct menuitem
*mi
;
1093 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1101 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1103 mi
->popup
= menuitems
;
1107 /* Define a messagetable resource. */
1110 define_messagetable (struct res_id id
, const struct res_res_info
*resinfo
,
1111 const char *filename
)
1114 char *real_filename
;
1116 unsigned char *data
;
1117 struct res_resource
*r
;
1119 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1122 if (stat (real_filename
, &s
) < 0)
1123 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1126 data
= (unsigned char *) res_alloc (s
.st_size
);
1128 get_data (e
, data
, s
.st_size
, real_filename
);
1131 free (real_filename
);
1133 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1134 resinfo
->language
, 0);
1136 r
->type
= RES_TYPE_MESSAGETABLE
;
1137 r
->u
.data
.length
= s
.st_size
;
1138 r
->u
.data
.data
= data
;
1139 r
->res_info
= *resinfo
;
1142 /* Define an rcdata resource. */
1145 define_rcdata (struct res_id id
, const struct res_res_info
*resinfo
,
1146 struct rcdata_item
*data
)
1148 struct res_resource
*r
;
1150 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1151 resinfo
->language
, 0);
1152 r
->type
= RES_TYPE_RCDATA
;
1154 r
->res_info
= *resinfo
;
1157 /* Create an rcdata item holding a string. */
1159 struct rcdata_item
*
1160 define_rcdata_string (const char *string
, unsigned long len
)
1162 struct rcdata_item
*ri
;
1165 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1167 ri
->type
= RCDATA_STRING
;
1168 ri
->u
.string
.length
= len
;
1169 s
= (char *) res_alloc (len
);
1170 memcpy (s
, string
, len
);
1176 /* Create an rcdata item holding a number. */
1178 struct rcdata_item
*
1179 define_rcdata_number (unsigned long val
, int dword
)
1181 struct rcdata_item
*ri
;
1183 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1185 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1191 /* Define a stringtable resource. This is called for each string
1192 which appears in a STRINGTABLE statement. */
1195 define_stringtable (const struct res_res_info
*resinfo
,
1196 unsigned long stringid
, const char *string
)
1199 struct res_resource
*r
;
1202 id
.u
.id
= (stringid
>> 4) + 1;
1203 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1204 resinfo
->language
, 1);
1206 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1210 r
->type
= RES_TYPE_STRINGTABLE
;
1211 r
->u
.stringtable
= ((struct stringtable
*)
1212 res_alloc (sizeof (struct stringtable
)));
1213 for (i
= 0; i
< 16; i
++)
1215 r
->u
.stringtable
->strings
[i
].length
= 0;
1216 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1219 r
->res_info
= *resinfo
;
1222 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1223 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1227 /* Define a user data resource where the data is in the rc file. */
1230 define_user_data (struct res_id id
, struct res_id type
,
1231 const struct res_res_info
*resinfo
,
1232 struct rcdata_item
*data
)
1234 struct res_id ids
[3];
1235 struct res_resource
*r
;
1240 ids
[2].u
.id
= resinfo
->language
;
1242 r
= define_resource (&resources
, 3, ids
, 0);
1243 r
->type
= RES_TYPE_USERDATA
;
1244 r
->u
.userdata
= data
;
1245 r
->res_info
= *resinfo
;
1248 /* Define a user data resource where the data is in a file. */
1251 define_user_file (struct res_id id
, struct res_id type
,
1252 const struct res_res_info
*resinfo
, const char *filename
)
1255 char *real_filename
;
1257 unsigned char *data
;
1258 struct res_id ids
[3];
1259 struct res_resource
*r
;
1261 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1263 if (stat (real_filename
, &s
) < 0)
1264 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1267 data
= (unsigned char *) res_alloc (s
.st_size
);
1269 get_data (e
, data
, s
.st_size
, real_filename
);
1272 free (real_filename
);
1277 ids
[2].u
.id
= resinfo
->language
;
1279 r
= define_resource (&resources
, 3, ids
, 0);
1280 r
->type
= RES_TYPE_USERDATA
;
1281 r
->u
.userdata
= ((struct rcdata_item
*)
1282 res_alloc (sizeof (struct rcdata_item
)));
1283 r
->u
.userdata
->next
= NULL
;
1284 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1285 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1286 r
->u
.userdata
->u
.buffer
.data
= data
;
1287 r
->res_info
= *resinfo
;
1290 /* Define a versioninfo resource. */
1293 define_versioninfo (struct res_id id
, int language
,
1294 struct fixed_versioninfo
*fixedverinfo
,
1295 struct ver_info
*verinfo
)
1297 struct res_resource
*r
;
1299 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1300 r
->type
= RES_TYPE_VERSIONINFO
;
1301 r
->u
.versioninfo
= ((struct versioninfo
*)
1302 res_alloc (sizeof (struct versioninfo
)));
1303 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1304 r
->u
.versioninfo
->var
= verinfo
;
1305 r
->res_info
.language
= language
;
1308 /* Add string version info to a list of version information. */
1311 append_ver_stringfileinfo (struct ver_info
*verinfo
, const char *language
,
1312 struct ver_stringinfo
*strings
)
1314 struct ver_info
*vi
, **pp
;
1316 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1318 vi
->type
= VERINFO_STRING
;
1319 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1320 vi
->u
.string
.strings
= strings
;
1322 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1329 /* Add variable version info to a list of version information. */
1332 append_ver_varfileinfo (struct ver_info
*verinfo
, const char *key
,
1333 struct ver_varinfo
*var
)
1335 struct ver_info
*vi
, **pp
;
1337 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1339 vi
->type
= VERINFO_VAR
;
1340 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1341 vi
->u
.var
.var
= var
;
1343 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1350 /* Append version string information to a list. */
1352 struct ver_stringinfo
*
1353 append_verval (struct ver_stringinfo
*strings
, const char *key
,
1356 struct ver_stringinfo
*vs
, **pp
;
1358 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1360 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1361 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1363 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1370 /* Append version variable information to a list. */
1372 struct ver_varinfo
*
1373 append_vertrans (struct ver_varinfo
*var
, unsigned long language
,
1374 unsigned long charset
)
1376 struct ver_varinfo
*vv
, **pp
;
1378 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1380 vv
->language
= language
;
1381 vv
->charset
= charset
;
1383 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1390 /* Local functions used to write out an rc file. */
1392 static void indent (FILE *, int);
1393 static void write_rc_directory
1394 (FILE *, const struct res_directory
*, const struct res_id
*,
1395 const struct res_id
*, int *, int);
1396 static void write_rc_subdir
1397 (FILE *, const struct res_entry
*, const struct res_id
*,
1398 const struct res_id
*, int *, int);
1399 static void write_rc_resource
1400 (FILE *, const struct res_id
*, const struct res_id
*,
1401 const struct res_resource
*, int *);
1402 static void write_rc_accelerators (FILE *, const struct accelerator
*);
1403 static void write_rc_cursor (FILE *, const struct cursor
*);
1404 static void write_rc_group_cursor (FILE *, const struct group_cursor
*);
1405 static void write_rc_dialog (FILE *, const struct dialog
*);
1406 static void write_rc_dialog_control (FILE *, const struct dialog_control
*);
1407 static void write_rc_fontdir (FILE *, const struct fontdir
*);
1408 static void write_rc_group_icon (FILE *, const struct group_icon
*);
1409 static void write_rc_menu (FILE *, const struct menu
*, int);
1410 static void write_rc_menuitems (FILE *, const struct menuitem
*, int, int);
1411 static void write_rc_rcdata (FILE *, const struct rcdata_item
*, int);
1412 static void write_rc_stringtable
1413 (FILE *, const struct res_id
*, const struct stringtable
*);
1414 static void write_rc_versioninfo (FILE *, const struct versioninfo
*);
1415 static void write_rc_filedata (FILE *, unsigned long, const unsigned char *);
1417 /* Indent a given number of spaces. */
1420 indent (FILE *e
, int c
)
1424 for (i
= 0; i
< c
; i
++)
1428 /* Dump the resources we have read in the format of an rc file.
1430 Actually, we don't use the format of an rc file, because it's way
1431 too much of a pain--for example, we'd have to write icon resources
1432 into a file and refer to that file. We just generate a readable
1433 format that kind of looks like an rc file, and is useful for
1434 understanding the contents of a resource file. Someday we may want
1435 to generate an rc file which the rc compiler can read; if that day
1436 comes, this code will have to be fixed up. */
1439 write_rc_file (const char *filename
, const struct res_directory
*resources
)
1444 if (filename
== NULL
)
1448 e
= fopen (filename
, FOPEN_WT
);
1450 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1454 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1455 (const struct res_id
*) NULL
, &language
, 1);
1458 /* Write out a directory. E is the file to write to. RD is the
1459 directory. TYPE is a pointer to the level 1 ID which serves as the
1460 resource type. NAME is a pointer to the level 2 ID which serves as
1461 an individual resource name. LANGUAGE is a pointer to the current
1462 language. LEVEL is the level in the tree. */
1465 write_rc_directory (FILE *e
, const struct res_directory
*rd
,
1466 const struct res_id
*type
, const struct res_id
*name
,
1467 int *language
, int level
)
1469 const struct res_entry
*re
;
1471 /* Print out some COFF information that rc files can't represent. */
1474 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1475 if (rd
->characteristics
!= 0)
1476 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1477 if (rd
->major
!= 0 || rd
->minor
!= 0)
1478 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1480 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1485 /* If we're at level 1, the key of this resource is the
1486 type. This normally duplicates the information we have
1487 stored with the resource itself, but we need to remember
1488 the type if this is a user define resource type. */
1493 /* If we're at level 2, the key of this resource is the name
1494 we are going to use in the rc printout. */
1499 /* If we're at level 3, then this key represents a language.
1500 Use it to update the current language. */
1502 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1503 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1505 fprintf (e
, "LANGUAGE %lu, %lu\n",
1506 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1507 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
1508 *language
= re
->id
.u
.id
;
1517 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1522 /* This is the normal case: the three levels are
1523 TYPE/NAME/LANGUAGE. NAME will have been set at level
1524 2, and represents the name to use. We probably just
1525 set LANGUAGE, and it will probably match what the
1526 resource itself records if anything. */
1527 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1531 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1532 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1539 /* Write out a subdirectory entry. E is the file to write to. RE is
1540 the subdirectory entry. TYPE and NAME are pointers to higher level
1541 IDs, or NULL. LANGUAGE is a pointer to the current language.
1542 LEVEL is the level in the tree. */
1545 write_rc_subdir (FILE *e
, const struct res_entry
*re
,
1546 const struct res_id
*type
, const struct res_id
*name
,
1547 int *language
, int level
)
1553 fprintf (e
, "// Type: ");
1555 res_id_print (e
, re
->id
, 1);
1560 switch (re
->id
.u
.id
)
1562 case RT_CURSOR
: s
= "cursor"; break;
1563 case RT_BITMAP
: s
= "bitmap"; break;
1564 case RT_ICON
: s
= "icon"; break;
1565 case RT_MENU
: s
= "menu"; break;
1566 case RT_DIALOG
: s
= "dialog"; break;
1567 case RT_STRING
: s
= "stringtable"; break;
1568 case RT_FONTDIR
: s
= "fontdir"; break;
1569 case RT_FONT
: s
= "font"; break;
1570 case RT_ACCELERATOR
: s
= "accelerators"; break;
1571 case RT_RCDATA
: s
= "rcdata"; break;
1572 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1573 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1574 case RT_GROUP_ICON
: s
= "group icon"; break;
1575 case RT_VERSION
: s
= "version"; break;
1576 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1577 case RT_PLUGPLAY
: s
= "plugplay"; break;
1578 case RT_VXD
: s
= "vxd"; break;
1579 case RT_ANICURSOR
: s
= "anicursor"; break;
1580 case RT_ANIICON
: s
= "aniicon"; break;
1581 default: s
= NULL
; break;
1585 fprintf (e
, "%s", s
);
1587 res_id_print (e
, re
->id
, 1);
1593 fprintf (e
, "// Name: ");
1594 res_id_print (e
, re
->id
, 1);
1599 fprintf (e
, "// Language: ");
1600 res_id_print (e
, re
->id
, 1);
1605 fprintf (e
, "// Level %d: ", level
);
1606 res_id_print (e
, re
->id
, 1);
1610 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1613 /* Write out a single resource. E is the file to write to. TYPE is a
1614 pointer to the type of the resource. NAME is a pointer to the name
1615 of the resource; it will be NULL if there is a level mismatch. RES
1616 is the resource data. LANGUAGE is a pointer to the current
1620 write_rc_resource (FILE *e
, const struct res_id
*type
,
1621 const struct res_id
*name
, const struct res_resource
*res
,
1635 case RES_TYPE_ACCELERATOR
:
1637 rt
= RT_ACCELERATOR
;
1640 case RES_TYPE_BITMAP
:
1645 case RES_TYPE_CURSOR
:
1650 case RES_TYPE_GROUP_CURSOR
:
1652 rt
= RT_GROUP_CURSOR
;
1655 case RES_TYPE_DIALOG
:
1656 if (extended_dialog (res
->u
.dialog
))
1668 case RES_TYPE_FONTDIR
:
1678 case RES_TYPE_GROUP_ICON
:
1684 if (extended_menu (res
->u
.menu
))
1697 case RES_TYPE_MESSAGETABLE
:
1699 rt
= RT_MESSAGETABLE
;
1702 case RES_TYPE_RCDATA
:
1707 case RES_TYPE_STRINGTABLE
:
1712 case RES_TYPE_USERDATA
:
1717 case RES_TYPE_VERSIONINFO
:
1725 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1727 fprintf (e
, "// Unexpected resource type mismatch: ");
1728 res_id_print (e
, *type
, 1);
1729 fprintf (e
, " != %d", rt
);
1732 if (res
->coff_info
.codepage
!= 0)
1733 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1734 if (res
->coff_info
.reserved
!= 0)
1735 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1738 res_id_print (e
, *name
, 0);
1740 fprintf (e
, "??Unknown-Name??");
1744 fprintf (e
, "%s", s
);
1745 else if (type
!= NULL
)
1746 res_id_print (e
, *type
, 0);
1748 fprintf (e
, "??Unknown-Type??");
1750 if (res
->res_info
.memflags
!= 0)
1752 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1753 fprintf (e
, " MOVEABLE");
1754 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1755 fprintf (e
, " PURE");
1756 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1757 fprintf (e
, " PRELOAD");
1758 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1759 fprintf (e
, " DISCARDABLE");
1762 if (res
->type
== RES_TYPE_DIALOG
)
1764 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1765 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1766 if (res
->u
.dialog
->ex
!= NULL
1767 && res
->u
.dialog
->ex
->help
!= 0)
1768 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1773 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1774 || res
->res_info
.characteristics
!= 0
1775 || res
->res_info
.version
!= 0)
1781 case RES_TYPE_ACCELERATOR
:
1782 case RES_TYPE_DIALOG
:
1784 case RES_TYPE_RCDATA
:
1785 case RES_TYPE_STRINGTABLE
:
1794 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1795 fprintf (e
, "%sLANGUAGE %d, %d\n",
1796 modifiers
? "// " : "",
1797 res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
1798 (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
1799 if (res
->res_info
.characteristics
!= 0)
1800 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1801 modifiers
? "// " : "",
1802 res
->res_info
.characteristics
);
1803 if (res
->res_info
.version
!= 0)
1804 fprintf (e
, "%sVERSION %lu\n",
1805 modifiers
? "// " : "",
1806 res
->res_info
.version
);
1814 case RES_TYPE_ACCELERATOR
:
1815 write_rc_accelerators (e
, res
->u
.acc
);
1818 case RES_TYPE_CURSOR
:
1819 write_rc_cursor (e
, res
->u
.cursor
);
1822 case RES_TYPE_GROUP_CURSOR
:
1823 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1826 case RES_TYPE_DIALOG
:
1827 write_rc_dialog (e
, res
->u
.dialog
);
1830 case RES_TYPE_FONTDIR
:
1831 write_rc_fontdir (e
, res
->u
.fontdir
);
1834 case RES_TYPE_GROUP_ICON
:
1835 write_rc_group_icon (e
, res
->u
.group_icon
);
1839 write_rc_menu (e
, res
->u
.menu
, menuex
);
1842 case RES_TYPE_RCDATA
:
1843 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1846 case RES_TYPE_STRINGTABLE
:
1847 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1850 case RES_TYPE_USERDATA
:
1851 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1854 case RES_TYPE_VERSIONINFO
:
1855 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1858 case RES_TYPE_BITMAP
:
1861 case RES_TYPE_MESSAGETABLE
:
1862 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1867 /* Write out accelerator information. */
1870 write_rc_accelerators (FILE *e
, const struct accelerator
*accelerators
)
1872 const struct accelerator
*acc
;
1874 fprintf (e
, "BEGIN\n");
1875 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1881 if ((acc
->key
& 0x7f) == acc
->key
1882 && ISPRINT (acc
->key
)
1883 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1885 fprintf (e
, "\"%c\"", acc
->key
);
1890 fprintf (e
, "%d", acc
->key
);
1894 fprintf (e
, ", %d", acc
->id
);
1898 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1899 fprintf (e
, ", VIRTKEY");
1901 fprintf (e
, ", ASCII");
1904 if ((acc
->flags
& ACC_SHIFT
) != 0)
1905 fprintf (e
, ", SHIFT");
1906 if ((acc
->flags
& ACC_CONTROL
) != 0)
1907 fprintf (e
, ", CONTROL");
1908 if ((acc
->flags
& ACC_ALT
) != 0)
1909 fprintf (e
, ", ALT");
1914 fprintf (e
, "END\n");
1917 /* Write out cursor information. This would normally be in a separate
1918 file, which the rc file would include. */
1921 write_rc_cursor (FILE *e
, const struct cursor
*cursor
)
1923 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
1925 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
1928 /* Write out group cursor data. This would normally be built from the
1932 write_rc_group_cursor (FILE *e
, const struct group_cursor
*group_cursor
)
1934 const struct group_cursor
*gc
;
1936 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
1938 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
1939 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
1940 fprintf (e
, "// data bytes: %lu; index: %d\n",
1941 gc
->bytes
, gc
->index
);
1945 /* Write dialog data. */
1948 write_rc_dialog (FILE *e
, const struct dialog
*dialog
)
1950 const struct dialog_control
*control
;
1952 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
1954 if (dialog
->exstyle
!= 0)
1955 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
1957 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
1958 || dialog
->class.u
.id
!= 0)
1960 fprintf (e
, "CLASS ");
1961 res_id_print (e
, dialog
->class, 1);
1965 if (dialog
->caption
!= NULL
)
1967 fprintf (e
, "CAPTION \"");
1968 unicode_print (e
, dialog
->caption
, -1);
1969 fprintf (e
, "\"\n");
1972 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
1973 || dialog
->menu
.u
.id
!= 0)
1975 fprintf (e
, "MENU ");
1976 res_id_print (e
, dialog
->menu
, 0);
1980 if (dialog
->font
!= NULL
)
1982 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
1983 unicode_print (e
, dialog
->font
, -1);
1985 if (dialog
->ex
!= NULL
1986 && (dialog
->ex
->weight
!= 0
1987 || dialog
->ex
->italic
!= 0
1988 || dialog
->ex
->charset
!= 1))
1989 fprintf (e
, ", %d, %d, %d",
1990 dialog
->ex
->weight
, dialog
->ex
->italic
, dialog
->ex
->charset
);
1994 fprintf (e
, "BEGIN\n");
1996 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
1997 write_rc_dialog_control (e
, control
);
1999 fprintf (e
, "END\n");
2002 /* For each predefined control keyword, this table provides the class
2008 unsigned short class;
2009 unsigned long style
;
2012 static const struct control_info control_info
[] =
2014 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2015 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2016 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2017 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2018 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2019 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2020 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2021 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2022 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2023 { "ICON", CTL_STATIC
, SS_ICON
},
2024 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2025 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2026 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2027 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2028 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2029 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2030 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2031 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2032 /* It's important that USERBUTTON come after all the other button
2033 types, so that it won't be matched too early. */
2034 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2038 /* Write a dialog control. */
2041 write_rc_dialog_control (FILE *e
, const struct dialog_control
*control
)
2043 const struct control_info
*ci
;
2047 if (control
->class.named
)
2051 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2052 if (ci
->class == control
->class.u
.id
2053 && (ci
->style
== (unsigned long) -1
2054 || ci
->style
== (control
->style
& 0xff)))
2058 fprintf (e
, "CONTROL");
2059 else if (ci
->name
!= NULL
)
2060 fprintf (e
, "%s", ci
->name
);
2062 fprintf (e
, "CONTROL");
2064 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2067 res_id_print (e
, control
->text
, 1);
2071 fprintf (e
, " %d, ", control
->id
);
2075 if (control
->class.named
)
2077 res_id_print (e
, control
->class, 0);
2078 if (control
->class.named
)
2080 fprintf (e
, ", 0x%lx, ", control
->style
);
2083 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2085 if (control
->style
!= SS_ICON
2086 || control
->exstyle
!= 0
2087 || control
->width
!= 0
2088 || control
->height
!= 0
2089 || control
->help
!= 0)
2091 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2093 /* FIXME: We don't need to print the style if it is the default.
2094 More importantly, in certain cases we actually need to turn
2095 off parts of the forced style, by using NOT. */
2096 fprintf (e
, ", 0x%lx", control
->style
);
2098 if (control
->exstyle
!= 0 || control
->help
!= 0)
2099 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2104 if (control
->data
!= NULL
)
2105 write_rc_rcdata (e
, control
->data
, 2);
2108 /* Write out font directory data. This would normally be built from
2112 write_rc_fontdir (FILE *e
, const struct fontdir
*fontdir
)
2114 const struct fontdir
*fc
;
2116 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2118 fprintf (e
, "// Font index: %d\n", fc
->index
);
2119 write_rc_filedata (e
, fc
->length
, fc
->data
);
2123 /* Write out group icon data. This would normally be built from the
2127 write_rc_group_icon (FILE *e
, const struct group_icon
*group_icon
)
2129 const struct group_icon
*gi
;
2131 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2133 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2134 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2135 fprintf (e
, "// data bytes: %lu; index: %d\n",
2136 gi
->bytes
, gi
->index
);
2140 /* Write out a menu resource. */
2143 write_rc_menu (FILE *e
, const struct menu
*menu
, int menuex
)
2145 if (menu
->help
!= 0)
2146 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2147 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2150 /* Write out menuitems. */
2153 write_rc_menuitems (FILE *e
, const struct menuitem
*menuitems
, int menuex
,
2156 const struct menuitem
*mi
;
2159 fprintf (e
, "BEGIN\n");
2161 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2163 indent (e
, ind
+ 2);
2165 if (mi
->popup
== NULL
)
2166 fprintf (e
, "MENUITEM");
2168 fprintf (e
, "POPUP");
2171 && mi
->popup
== NULL
2176 fprintf (e
, " SEPARATOR\n");
2180 if (mi
->text
== NULL
)
2181 fprintf (e
, " \"\"");
2185 unicode_print (e
, mi
->text
, -1);
2191 if (mi
->popup
== NULL
)
2192 fprintf (e
, ", %d", mi
->id
);
2194 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2195 fprintf (e
, ", CHECKED");
2196 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2197 fprintf (e
, ", GRAYED");
2198 if ((mi
->type
& MENUITEM_HELP
) != 0)
2199 fprintf (e
, ", HELP");
2200 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2201 fprintf (e
, ", INACTIVE");
2202 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2203 fprintf (e
, ", MENUBARBREAK");
2204 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2205 fprintf (e
, ", MENUBREAK");
2209 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2211 fprintf (e
, ", %d", mi
->id
);
2212 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2214 fprintf (e
, ", %lu", mi
->type
);
2215 if (mi
->state
!= 0 || mi
->help
!= 0)
2217 fprintf (e
, ", %lu", mi
->state
);
2219 fprintf (e
, ", %lu", mi
->help
);
2227 if (mi
->popup
!= NULL
)
2228 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2232 fprintf (e
, "END\n");
2235 /* Write out an rcdata resource. This is also used for other types of
2236 resources that need to print arbitrary data. */
2239 write_rc_rcdata (FILE *e
, const struct rcdata_item
*rcdata
, int ind
)
2241 const struct rcdata_item
*ri
;
2244 fprintf (e
, "BEGIN\n");
2246 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2248 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2251 indent (e
, ind
+ 2);
2259 fprintf (e
, "%d", ri
->u
.word
);
2263 fprintf (e
, "%luL", ri
->u
.dword
);
2273 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2278 fprintf (e
, "\\%03o", *s
);
2284 case RCDATA_WSTRING
:
2286 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2295 /* Assume little endian data. */
2298 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2304 indent (e
, ind
+ 2);
2305 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2306 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2307 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2308 | ri
->u
.buffer
.data
[i
]);
2309 fprintf (e
, "%luL", l
);
2310 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2312 for (j
= 0; j
< 4; ++j
)
2313 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2314 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2318 fprintf (e
, "\t// ");
2319 for (j
= 0; j
< 4; ++j
)
2321 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2322 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2325 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2327 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2335 if (i
+ 1 < ri
->u
.buffer
.length
)
2341 indent (e
, ind
+ 2);
2342 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2343 fprintf (e
, "%d", s
);
2344 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2346 for (j
= 0; j
< 2; ++j
)
2347 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2348 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2352 fprintf (e
, "\t// ");
2353 for (j
= 0; j
< 2; ++j
)
2355 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2356 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2359 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2361 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2370 if (i
< ri
->u
.buffer
.length
)
2373 indent (e
, ind
+ 2);
2374 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2375 && ISPRINT (ri
->u
.buffer
.data
[i
]))
2376 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2378 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2379 if (ri
->next
!= NULL
)
2389 if (ri
->type
!= RCDATA_BUFFER
)
2391 if (ri
->next
!= NULL
)
2398 fprintf (e
, "END\n");
2401 /* Write out a stringtable resource. */
2404 write_rc_stringtable (FILE *e
, const struct res_id
*name
,
2405 const struct stringtable
*stringtable
)
2407 unsigned long offset
;
2410 if (name
!= NULL
&& ! name
->named
)
2411 offset
= (name
->u
.id
- 1) << 4;
2414 fprintf (e
, "// %s string table name\n",
2415 name
== NULL
? "Missing" : "Invalid");
2419 fprintf (e
, "BEGIN\n");
2421 for (i
= 0; i
< 16; i
++)
2423 if (stringtable
->strings
[i
].length
!= 0)
2425 fprintf (e
, " %lu, \"", offset
+ i
);
2426 unicode_print (e
, stringtable
->strings
[i
].string
,
2427 stringtable
->strings
[i
].length
);
2428 fprintf (e
, "\"\n");
2432 fprintf (e
, "END\n");
2435 /* Write out a versioninfo resource. */
2438 write_rc_versioninfo (FILE *e
, const struct versioninfo
*versioninfo
)
2440 const struct fixed_versioninfo
*f
;
2441 const struct ver_info
*vi
;
2443 f
= versioninfo
->fixed
;
2444 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2445 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2446 (f
->file_version_ms
>> 16) & 0xffff,
2447 f
->file_version_ms
& 0xffff,
2448 (f
->file_version_ls
>> 16) & 0xffff,
2449 f
->file_version_ls
& 0xffff);
2450 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2451 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2452 (f
->product_version_ms
>> 16) & 0xffff,
2453 f
->product_version_ms
& 0xffff,
2454 (f
->product_version_ls
>> 16) & 0xffff,
2455 f
->product_version_ls
& 0xffff);
2456 if (f
->file_flags_mask
!= 0)
2457 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2458 if (f
->file_flags
!= 0)
2459 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2460 if (f
->file_os
!= 0)
2461 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2462 if (f
->file_type
!= 0)
2463 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2464 if (f
->file_subtype
!= 0)
2465 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2466 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2467 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2469 fprintf (e
, "BEGIN\n");
2471 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2475 case VERINFO_STRING
:
2477 const struct ver_stringinfo
*vs
;
2479 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2480 fprintf (e
, " BEGIN\n");
2481 fprintf (e
, " BLOCK \"");
2482 unicode_print (e
, vi
->u
.string
.language
, -1);
2483 fprintf (e
, "\"\n");
2484 fprintf (e
, " BEGIN\n");
2486 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2488 fprintf (e
, " VALUE \"");
2489 unicode_print (e
, vs
->key
, -1);
2490 fprintf (e
, "\", \"");
2491 unicode_print (e
, vs
->value
, -1);
2492 fprintf (e
, "\"\n");
2495 fprintf (e
, " END\n");
2496 fprintf (e
, " END\n");
2502 const struct ver_varinfo
*vv
;
2504 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2505 fprintf (e
, " BEGIN\n");
2506 fprintf (e
, " VALUE \"");
2507 unicode_print (e
, vi
->u
.var
.key
, -1);
2510 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2511 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2514 fprintf (e
, "\n END\n");
2521 fprintf (e
, "END\n");
2524 /* Write out data which would normally be read from a file. */
2527 write_rc_filedata (FILE *e
, unsigned long length
, const unsigned char *data
)
2531 for (i
= 0; i
+ 15 < length
; i
+= 16)
2533 fprintf (e
, "// %4lx: ", i
);
2534 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2535 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2536 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2537 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2538 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2539 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2544 fprintf (e
, "// %4lx:", i
);
2547 fprintf (e
, " %02x", data
[i
]);