1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
6 This file is part of GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 /* This file contains functions that read and write Windows rc files.
24 These are text files that represent resources. */
28 #include "libiberty.h"
29 #include "safe-ctype.h"
39 #ifdef HAVE_SYS_WAIT_H
41 #else /* ! HAVE_SYS_WAIT_H */
42 #if ! defined (_WIN32) || defined (__CYGWIN__)
44 #define WIFEXITED(w) (((w)&0377) == 0)
47 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
50 #define WTERMSIG(w) ((w) & 0177)
53 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
55 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
57 #define WIFEXITED(w) (((w) & 0xff) == 0)
60 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
63 #define WTERMSIG(w) ((w) & 0x7f)
66 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
68 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
69 #endif /* ! HAVE_SYS_WAIT_H */
72 #define STDOUT_FILENO 1
75 #if defined (_WIN32) && ! defined (__CYGWIN__)
77 #define pclose _pclose
80 /* The default preprocessor. */
82 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
84 /* We read the directory entries in a cursor or icon file into
85 instances of this structure. */
91 /* Height of image. */
93 /* Number of colors in image. */
94 unsigned char colorcount
;
100 unsigned short planes
;
101 /* Bits per pixel. */
106 /* X coordinate of hotspot. */
107 unsigned short xhotspot
;
108 /* Y coordinate of hotspot. */
109 unsigned short yhotspot
;
112 /* Bytes in image. */
114 /* File offset of image. */
115 unsigned long offset
;
118 /* The name of the rc file we are reading. */
122 /* The line number in the rc file. */
126 /* The pipe we are reading from, so that we can close it if we exit. */
128 static FILE *cpp_pipe
;
130 /* The temporary file used if we're not using popen, so we can delete it
133 static char *cpp_temp_file
;
135 /* Input stream is either a file or a pipe. */
137 static enum {ISTREAM_PIPE
, ISTREAM_FILE
} istream_type
;
139 /* As we read the rc file, we attach information to this structure. */
141 static struct res_directory
*resources
;
143 /* The number of cursor resources we have written out. */
147 /* The number of font resources we have written out. */
151 /* Font directory information. */
153 struct fontdir
*fontdirs
;
155 /* Resource info to use for fontdirs. */
157 struct res_res_info fontdirs_resinfo
;
159 /* The number of icon resources we have written out. */
163 /* Local functions. */
165 static int run_cmd (char *, const char *);
166 static FILE *open_input_stream (char *);
167 static FILE *look_for_default
168 (char *, const char *, int, const char *, const char *);
169 static void close_input_stream (void);
170 static void unexpected_eof (const char *);
171 static int get_word (FILE *, const char *);
172 static unsigned long get_long (FILE *, const char *);
173 static void get_data (FILE *, unsigned char *, unsigned long, const char *);
174 static void define_fontdirs (void);
176 /* Run `cmd' and redirect the output to `redir'. */
179 run_cmd (char *cmd
, const char *redir
)
182 int pid
, wait_status
, retcode
;
185 char *errmsg_fmt
, *errmsg_arg
;
186 char *temp_base
= choose_temp_base ();
189 int redir_handle
= -1;
190 int stdout_save
= -1;
192 /* Count the args. */
195 for (s
= cmd
; *s
; s
++)
200 argv
= alloca (sizeof (char *) * (i
+ 3));
206 while (*s
== ' ' && *s
!= 0)
212 in_quote
= (*s
== '\'' || *s
== '"');
213 sep
= (in_quote
) ? *s
++ : ' ';
216 while (*s
!= sep
&& *s
!= 0)
229 /* Setup the redirection. We can't use the usual fork/exec and redirect
230 since we may be running on non-POSIX Windows host. */
235 /* Open temporary output file. */
236 redir_handle
= open (redir
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
237 if (redir_handle
== -1)
238 fatal (_("can't open temporary file `%s': %s"), redir
,
241 /* Duplicate the stdout file handle so it can be restored later. */
242 stdout_save
= dup (STDOUT_FILENO
);
243 if (stdout_save
== -1)
244 fatal (_("can't redirect stdout: `%s': %s"), redir
, strerror (errno
));
246 /* Redirect stdout to our output file. */
247 dup2 (redir_handle
, STDOUT_FILENO
);
249 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
250 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
252 /* Restore stdout to its previous setting. */
253 dup2 (stdout_save
, STDOUT_FILENO
);
255 /* Close response file. */
256 close (redir_handle
);
260 fatal (_("%s %s: %s"), errmsg_fmt
, errmsg_arg
, strerror (errno
));
265 pid
= pwait (pid
, &wait_status
, 0);
269 fatal (_("wait: %s"), strerror (errno
));
272 else if (WIFSIGNALED (wait_status
))
274 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status
));
277 else if (WIFEXITED (wait_status
))
279 if (WEXITSTATUS (wait_status
) != 0)
281 fatal (_("%s exited with status %d"), cmd
,
282 WEXITSTATUS (wait_status
));
293 open_input_stream (char *cmd
)
295 if (istream_type
== ISTREAM_FILE
)
299 fileprefix
= choose_temp_base ();
300 cpp_temp_file
= (char *) xmalloc (strlen (fileprefix
) + 5);
301 sprintf (cpp_temp_file
, "%s.irc", fileprefix
);
304 if (run_cmd (cmd
, cpp_temp_file
))
305 fatal (_("can't execute `%s': %s"), cmd
, strerror (errno
));
307 cpp_pipe
= fopen (cpp_temp_file
, FOPEN_RT
);;
308 if (cpp_pipe
== NULL
)
309 fatal (_("can't open temporary file `%s': %s"),
310 cpp_temp_file
, strerror (errno
));
314 _("Using temporary file `%s' to read preprocessor output\n"),
319 cpp_pipe
= popen (cmd
, FOPEN_RT
);
320 if (cpp_pipe
== NULL
)
321 fatal (_("can't popen `%s': %s"), cmd
, strerror (errno
));
323 fprintf (stderr
, _("Using popen to read preprocessor output\n"));
326 xatexit (close_input_stream
);
330 /* look for the preprocessor program */
333 look_for_default (char *cmd
, const char *prefix
, int end_prefix
,
334 const char *preprocargs
, const char *filename
)
340 strcpy (cmd
, prefix
);
342 sprintf (cmd
+ end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
343 space
= strchr (cmd
+ end_prefix
, ' ');
348 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
349 strchr (cmd
, '\\') ||
353 found
= (stat (cmd
, &s
) == 0
354 #ifdef HAVE_EXECUTABLE_SUFFIX
355 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
362 fprintf (stderr
, _("Tried `%s'\n"), cmd
);
367 strcpy (cmd
, prefix
);
369 sprintf (cmd
+ end_prefix
, "%s %s %s",
370 DEFAULT_PREPROCESSOR
, preprocargs
, filename
);
373 fprintf (stderr
, _("Using `%s'\n"), cmd
);
375 cpp_pipe
= open_input_stream (cmd
);
379 /* Read an rc file. */
381 struct res_directory
*
382 read_rc_file (const char *filename
, const char *preprocessor
,
383 const char *preprocargs
, int language
, int use_temp_file
)
387 istream_type
= (use_temp_file
) ? ISTREAM_FILE
: ISTREAM_PIPE
;
389 if (preprocargs
== NULL
)
391 if (filename
== NULL
)
396 cmd
= xmalloc (strlen (preprocessor
)
397 + strlen (preprocargs
)
400 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
402 cpp_pipe
= open_input_stream (cmd
);
406 char *dash
, *slash
, *cp
;
408 preprocessor
= DEFAULT_PREPROCESSOR
;
410 cmd
= xmalloc (strlen (program_name
)
411 + strlen (preprocessor
)
412 + strlen (preprocargs
)
414 #ifdef HAVE_EXECUTABLE_SUFFIX
415 + strlen (EXECUTABLE_SUFFIX
)
421 for (cp
= program_name
; *cp
; cp
++)
426 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
427 *cp
== ':' || *cp
== '\\' ||
440 /* First, try looking for a prefixed gcc in the windres
441 directory, with the same prefix as windres */
443 cpp_pipe
= look_for_default (cmd
, program_name
, dash
-program_name
+1,
444 preprocargs
, filename
);
447 if (slash
&& !cpp_pipe
)
449 /* Next, try looking for a gcc in the same directory as
452 cpp_pipe
= look_for_default (cmd
, program_name
, slash
-program_name
+1,
453 preprocargs
, filename
);
458 /* Sigh, try the default */
460 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
467 rc_filename
= xstrdup (filename
);
470 rcparse_set_language (language
);
473 rcparse_discard_strings ();
475 close_input_stream ();
477 if (fontdirs
!= NULL
)
486 /* Close the input stream if it is open. */
489 close_input_stream (void)
491 if (istream_type
== ISTREAM_FILE
)
493 if (cpp_pipe
!= NULL
)
496 if (cpp_temp_file
!= NULL
)
498 int errno_save
= errno
;
500 unlink (cpp_temp_file
);
502 free (cpp_temp_file
);
507 if (cpp_pipe
!= NULL
)
511 /* Since this is also run via xatexit, safeguard. */
513 cpp_temp_file
= NULL
;
516 /* Report an error while reading an rc file. */
519 yyerror (const char *msg
)
521 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
524 /* Issue a warning while reading an rc file. */
527 rcparse_warning (const char *msg
)
529 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
532 /* Die if we get an unexpected end of file. */
535 unexpected_eof (const char *msg
)
537 fatal (_("%s: unexpected EOF"), msg
);
540 /* Read a 16 bit word from a file. The data is assumed to be little
544 get_word (FILE *e
, const char *msg
)
551 unexpected_eof (msg
);
552 return ((b2
& 0xff) << 8) | (b1
& 0xff);
555 /* Read a 32 bit word from a file. The data is assumed to be little
559 get_long (FILE *e
, const char *msg
)
568 unexpected_eof (msg
);
569 return (((((((b4
& 0xff) << 8)
575 /* Read data from a file. This is a wrapper to do error checking. */
578 get_data (FILE *e
, unsigned char *p
, unsigned long c
, const char *msg
)
582 got
= fread (p
, 1, c
, e
);
586 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
589 /* Define an accelerator resource. */
592 define_accelerator (struct res_id id
, const struct res_res_info
*resinfo
,
593 struct accelerator
*data
)
595 struct res_resource
*r
;
597 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
598 resinfo
->language
, 0);
599 r
->type
= RES_TYPE_ACCELERATOR
;
601 r
->res_info
= *resinfo
;
604 /* Define a bitmap resource. Bitmap data is stored in a file. The
605 first 14 bytes of the file are a standard header, which is not
606 included in the resource data. */
608 #define BITMAP_SKIP (14)
611 define_bitmap (struct res_id id
, const struct res_res_info
*resinfo
,
612 const char *filename
)
619 struct res_resource
*r
;
621 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
623 if (stat (real_filename
, &s
) < 0)
624 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
627 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
629 for (i
= 0; i
< BITMAP_SKIP
; i
++)
632 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
635 free (real_filename
);
637 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
638 resinfo
->language
, 0);
640 r
->type
= RES_TYPE_BITMAP
;
641 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
642 r
->u
.data
.data
= data
;
643 r
->res_info
= *resinfo
;
646 /* Define a cursor resource. A cursor file may contain a set of
647 bitmaps, each representing the same cursor at various different
648 resolutions. They each get written out with a different ID. The
649 real cursor resource is then a group resource which can be used to
650 select one of the actual cursors. */
653 define_cursor (struct res_id id
, const struct res_res_info
*resinfo
,
654 const char *filename
)
659 struct icondir
*icondirs
;
661 struct res_resource
*r
;
662 struct group_cursor
*first
, **pp
;
664 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
666 /* A cursor file is basically an icon file. The start of the file
667 is a three word structure. The first word is ignored. The
668 second word is the type of data. The third word is the number of
671 get_word (e
, real_filename
);
672 type
= get_word (e
, real_filename
);
673 count
= get_word (e
, real_filename
);
675 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
677 /* Read in the icon directory entries. */
679 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
681 for (i
= 0; i
< count
; i
++)
683 icondirs
[i
].width
= getc (e
);
684 icondirs
[i
].height
= getc (e
);
685 icondirs
[i
].colorcount
= getc (e
);
687 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
688 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
689 icondirs
[i
].bytes
= get_long (e
, real_filename
);
690 icondirs
[i
].offset
= get_long (e
, real_filename
);
693 unexpected_eof (real_filename
);
696 /* Define each cursor as a unique resource. */
698 first_cursor
= cursors
;
700 for (i
= 0; i
< count
; i
++)
706 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
707 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
708 icondirs
[i
].offset
, strerror (errno
));
710 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
712 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
714 c
= (struct cursor
*) res_alloc (sizeof *c
);
715 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
716 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
717 c
->length
= icondirs
[i
].bytes
;
725 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
726 resinfo
->language
, 0);
727 r
->type
= RES_TYPE_CURSOR
;
729 r
->res_info
= *resinfo
;
733 free (real_filename
);
735 /* Define a cursor group resource. */
739 for (i
= 0; i
< count
; i
++)
741 struct group_cursor
*cg
;
743 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
745 cg
->width
= icondirs
[i
].width
;
746 cg
->height
= 2 * icondirs
[i
].height
;
748 /* FIXME: What should these be set to? */
752 cg
->bytes
= icondirs
[i
].bytes
+ 4;
753 cg
->index
= first_cursor
+ i
+ 1;
761 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
762 resinfo
->language
, 0);
763 r
->type
= RES_TYPE_GROUP_CURSOR
;
764 r
->u
.group_cursor
= first
;
765 r
->res_info
= *resinfo
;
768 /* Define a dialog resource. */
771 define_dialog (struct res_id id
, const struct res_res_info
*resinfo
,
772 const struct dialog
*dialog
)
775 struct res_resource
*r
;
777 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
780 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
781 resinfo
->language
, 0);
782 r
->type
= RES_TYPE_DIALOG
;
784 r
->res_info
= *resinfo
;
787 /* Define a dialog control. This does not define a resource, but
788 merely allocates and fills in a structure. */
790 struct dialog_control
*
791 define_control (const struct res_id iid
, unsigned long id
, unsigned long x
,
792 unsigned long y
, unsigned long width
, unsigned long height
,
793 unsigned long class, unsigned long style
,
794 unsigned long exstyle
)
796 struct dialog_control
*n
;
798 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
802 n
->exstyle
= exstyle
;
808 n
->class.u
.id
= class;
816 struct dialog_control
*
817 define_icon_control (struct res_id iid
, unsigned long id
, unsigned long x
,
818 unsigned long y
, unsigned long style
,
819 unsigned long exstyle
, unsigned long help
,
820 struct rcdata_item
*data
, struct dialog_ex
*ex
)
822 struct dialog_control
*n
;
826 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
827 res_string_to_id (&tid
, "");
828 n
= define_control (tid
, id
, x
, y
, 0, 0, CTL_STATIC
, style
, exstyle
);
831 rcparse_warning (_("help ID requires DIALOGEX"));
833 rcparse_warning (_("control data requires DIALOGEX"));
840 /* Define a font resource. */
843 define_font (struct res_id id
, const struct res_res_info
*resinfo
,
844 const char *filename
)
850 struct res_resource
*r
;
853 unsigned char *fontdata
;
855 const char *device
, *face
;
858 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
860 if (stat (real_filename
, &s
) < 0)
861 fatal (_("stat failed on font file `%s': %s"), real_filename
,
864 data
= (unsigned char *) res_alloc (s
.st_size
);
866 get_data (e
, data
, s
.st_size
, real_filename
);
869 free (real_filename
);
871 r
= define_standard_resource (&resources
, RT_FONT
, id
,
872 resinfo
->language
, 0);
874 r
->type
= RES_TYPE_FONT
;
875 r
->u
.data
.length
= s
.st_size
;
876 r
->u
.data
.data
= data
;
877 r
->res_info
= *resinfo
;
879 /* For each font resource, we must add an entry in the FONTDIR
880 resource. The FONTDIR resource includes some strings in the font
881 file. To find them, we have to do some magic on the data we have
884 offset
= ((((((data
[47] << 8)
888 if (offset
> 0 && offset
< s
.st_size
)
889 device
= (char *) data
+ offset
;
893 offset
= ((((((data
[51] << 8)
897 if (offset
> 0 && offset
< s
.st_size
)
898 face
= (char *) data
+ offset
;
904 fontdatalength
= 58 + strlen (device
) + strlen (face
);
905 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
906 memcpy (fontdata
, data
, 56);
907 strcpy ((char *) fontdata
+ 56, device
);
908 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
910 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
913 fd
->length
= fontdatalength
;
916 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
920 /* For the single fontdirs resource, we always use the resource
921 information of the last font. I don't know what else to do. */
922 fontdirs_resinfo
= *resinfo
;
925 /* Define the fontdirs resource. This is called after the entire rc
926 file has been parsed, if any font resources were seen. */
929 define_fontdirs (void)
931 struct res_resource
*r
;
937 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
939 r
->type
= RES_TYPE_FONTDIR
;
940 r
->u
.fontdir
= fontdirs
;
941 r
->res_info
= fontdirs_resinfo
;
944 /* Define an icon resource. An icon file may contain a set of
945 bitmaps, each representing the same icon at various different
946 resolutions. They each get written out with a different ID. The
947 real icon resource is then a group resource which can be used to
948 select one of the actual icon bitmaps. */
951 define_icon (struct res_id id
, const struct res_res_info
*resinfo
,
952 const char *filename
)
957 struct icondir
*icondirs
;
959 struct res_resource
*r
;
960 struct group_icon
*first
, **pp
;
962 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
964 /* The start of an icon file is a three word structure. The first
965 word is ignored. The second word is the type of data. The third
966 word is the number of entries. */
968 get_word (e
, real_filename
);
969 type
= get_word (e
, real_filename
);
970 count
= get_word (e
, real_filename
);
972 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
974 /* Read in the icon directory entries. */
976 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
978 for (i
= 0; i
< count
; i
++)
980 icondirs
[i
].width
= getc (e
);
981 icondirs
[i
].height
= getc (e
);
982 icondirs
[i
].colorcount
= getc (e
);
984 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
985 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
986 icondirs
[i
].bytes
= get_long (e
, real_filename
);
987 icondirs
[i
].offset
= get_long (e
, real_filename
);
990 unexpected_eof (real_filename
);
993 /* Define each icon as a unique resource. */
997 for (i
= 0; i
< count
; i
++)
1002 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1003 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1004 icondirs
[i
].offset
, strerror (errno
));
1006 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1008 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1015 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1016 resinfo
->language
, 0);
1017 r
->type
= RES_TYPE_ICON
;
1018 r
->u
.data
.length
= icondirs
[i
].bytes
;
1019 r
->u
.data
.data
= data
;
1020 r
->res_info
= *resinfo
;
1024 free (real_filename
);
1026 /* Define an icon group resource. */
1030 for (i
= 0; i
< count
; i
++)
1032 struct group_icon
*cg
;
1034 /* For some reason, at least in some files the planes and bits
1035 are zero. We instead set them from the color. This is
1038 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1040 cg
->width
= icondirs
[i
].width
;
1041 cg
->height
= icondirs
[i
].height
;
1042 cg
->colors
= icondirs
[i
].colorcount
;
1044 if (icondirs
[i
].u
.icon
.planes
)
1045 cg
->planes
= icondirs
[i
].u
.icon
.planes
;
1049 if (icondirs
[i
].u
.icon
.bits
)
1050 cg
->bits
= icondirs
[i
].u
.icon
.bits
;
1055 while ((1L << cg
->bits
) < cg
->colors
)
1059 cg
->bytes
= icondirs
[i
].bytes
;
1060 cg
->index
= first_icon
+ i
+ 1;
1068 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1069 resinfo
->language
, 0);
1070 r
->type
= RES_TYPE_GROUP_ICON
;
1071 r
->u
.group_icon
= first
;
1072 r
->res_info
= *resinfo
;
1075 /* Define a menu resource. */
1078 define_menu (struct res_id id
, const struct res_res_info
*resinfo
,
1079 struct menuitem
*menuitems
)
1082 struct res_resource
*r
;
1084 m
= (struct menu
*) res_alloc (sizeof *m
);
1085 m
->items
= menuitems
;
1088 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1089 r
->type
= RES_TYPE_MENU
;
1091 r
->res_info
= *resinfo
;
1094 /* Define a menu item. This does not define a resource, but merely
1095 allocates and fills in a structure. */
1098 define_menuitem (const char *text
, int menuid
, unsigned long type
,
1099 unsigned long state
, unsigned long help
,
1100 struct menuitem
*menuitems
)
1102 struct menuitem
*mi
;
1104 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1112 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1114 mi
->popup
= menuitems
;
1118 /* Define a messagetable resource. */
1121 define_messagetable (struct res_id id
, const struct res_res_info
*resinfo
,
1122 const char *filename
)
1125 char *real_filename
;
1127 unsigned char *data
;
1128 struct res_resource
*r
;
1130 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1133 if (stat (real_filename
, &s
) < 0)
1134 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1137 data
= (unsigned char *) res_alloc (s
.st_size
);
1139 get_data (e
, data
, s
.st_size
, real_filename
);
1142 free (real_filename
);
1144 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1145 resinfo
->language
, 0);
1147 r
->type
= RES_TYPE_MESSAGETABLE
;
1148 r
->u
.data
.length
= s
.st_size
;
1149 r
->u
.data
.data
= data
;
1150 r
->res_info
= *resinfo
;
1153 /* Define an rcdata resource. */
1156 define_rcdata (struct res_id id
, const struct res_res_info
*resinfo
,
1157 struct rcdata_item
*data
)
1159 struct res_resource
*r
;
1161 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1162 resinfo
->language
, 0);
1163 r
->type
= RES_TYPE_RCDATA
;
1165 r
->res_info
= *resinfo
;
1168 /* Create an rcdata item holding a string. */
1170 struct rcdata_item
*
1171 define_rcdata_string (const char *string
, unsigned long len
)
1173 struct rcdata_item
*ri
;
1176 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1178 ri
->type
= RCDATA_STRING
;
1179 ri
->u
.string
.length
= len
;
1180 s
= (char *) res_alloc (len
);
1181 memcpy (s
, string
, len
);
1187 /* Create an rcdata item holding a number. */
1189 struct rcdata_item
*
1190 define_rcdata_number (unsigned long val
, int dword
)
1192 struct rcdata_item
*ri
;
1194 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1196 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1202 /* Define a stringtable resource. This is called for each string
1203 which appears in a STRINGTABLE statement. */
1206 define_stringtable (const struct res_res_info
*resinfo
,
1207 unsigned long stringid
, const char *string
)
1210 struct res_resource
*r
;
1213 id
.u
.id
= (stringid
>> 4) + 1;
1214 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1215 resinfo
->language
, 1);
1217 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1221 r
->type
= RES_TYPE_STRINGTABLE
;
1222 r
->u
.stringtable
= ((struct stringtable
*)
1223 res_alloc (sizeof (struct stringtable
)));
1224 for (i
= 0; i
< 16; i
++)
1226 r
->u
.stringtable
->strings
[i
].length
= 0;
1227 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1230 r
->res_info
= *resinfo
;
1233 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1234 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1238 /* Define a user data resource where the data is in the rc file. */
1241 define_user_data (struct res_id id
, struct res_id type
,
1242 const struct res_res_info
*resinfo
,
1243 struct rcdata_item
*data
)
1245 struct res_id ids
[3];
1246 struct res_resource
*r
;
1251 ids
[2].u
.id
= resinfo
->language
;
1253 r
= define_resource (& resources
, 3, ids
, 0);
1254 r
->type
= RES_TYPE_USERDATA
;
1255 r
->u
.userdata
= data
;
1256 r
->res_info
= *resinfo
;
1260 define_rcdata_file (struct res_id id
, const struct res_res_info
*resinfo
,
1261 const char *filename
)
1263 struct rcdata_item
*ri
;
1265 char *real_filename
;
1267 unsigned char *data
;
1269 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1272 if (stat (real_filename
, &s
) < 0)
1273 fatal (_("stat failed on file `%s': %s"), real_filename
,
1276 data
= (unsigned char *) res_alloc (s
.st_size
);
1278 get_data (e
, data
, s
.st_size
, real_filename
);
1281 free (real_filename
);
1283 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1285 ri
->type
= RCDATA_BUFFER
;
1286 ri
->u
.buffer
.length
= s
.st_size
;
1287 ri
->u
.buffer
.data
= data
;
1289 define_rcdata (id
, resinfo
, ri
);
1292 /* Define a user data resource where the data is in a file. */
1295 define_user_file (struct res_id id
, struct res_id type
,
1296 const struct res_res_info
*resinfo
, const char *filename
)
1299 char *real_filename
;
1301 unsigned char *data
;
1302 struct res_id ids
[3];
1303 struct res_resource
*r
;
1305 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1307 if (stat (real_filename
, &s
) < 0)
1308 fatal (_("stat failed on file `%s': %s"), real_filename
,
1311 data
= (unsigned char *) res_alloc (s
.st_size
);
1313 get_data (e
, data
, s
.st_size
, real_filename
);
1316 free (real_filename
);
1321 ids
[2].u
.id
= resinfo
->language
;
1323 r
= define_resource (&resources
, 3, ids
, 0);
1324 r
->type
= RES_TYPE_USERDATA
;
1325 r
->u
.userdata
= ((struct rcdata_item
*)
1326 res_alloc (sizeof (struct rcdata_item
)));
1327 r
->u
.userdata
->next
= NULL
;
1328 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1329 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1330 r
->u
.userdata
->u
.buffer
.data
= data
;
1331 r
->res_info
= *resinfo
;
1334 /* Define a versioninfo resource. */
1337 define_versioninfo (struct res_id id
, int language
,
1338 struct fixed_versioninfo
*fixedverinfo
,
1339 struct ver_info
*verinfo
)
1341 struct res_resource
*r
;
1343 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1344 r
->type
= RES_TYPE_VERSIONINFO
;
1345 r
->u
.versioninfo
= ((struct versioninfo
*)
1346 res_alloc (sizeof (struct versioninfo
)));
1347 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1348 r
->u
.versioninfo
->var
= verinfo
;
1349 r
->res_info
.language
= language
;
1352 /* Add string version info to a list of version information. */
1355 append_ver_stringfileinfo (struct ver_info
*verinfo
, const char *language
,
1356 struct ver_stringinfo
*strings
)
1358 struct ver_info
*vi
, **pp
;
1360 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1362 vi
->type
= VERINFO_STRING
;
1363 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1364 vi
->u
.string
.strings
= strings
;
1366 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1373 /* Add variable version info to a list of version information. */
1376 append_ver_varfileinfo (struct ver_info
*verinfo
, const char *key
,
1377 struct ver_varinfo
*var
)
1379 struct ver_info
*vi
, **pp
;
1381 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1383 vi
->type
= VERINFO_VAR
;
1384 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1385 vi
->u
.var
.var
= var
;
1387 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1394 /* Append version string information to a list. */
1396 struct ver_stringinfo
*
1397 append_verval (struct ver_stringinfo
*strings
, const char *key
,
1400 struct ver_stringinfo
*vs
, **pp
;
1402 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1404 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1405 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1407 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1414 /* Append version variable information to a list. */
1416 struct ver_varinfo
*
1417 append_vertrans (struct ver_varinfo
*var
, unsigned long language
,
1418 unsigned long charset
)
1420 struct ver_varinfo
*vv
, **pp
;
1422 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1424 vv
->language
= language
;
1425 vv
->charset
= charset
;
1427 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1434 /* Local functions used to write out an rc file. */
1436 static void indent (FILE *, int);
1437 static void write_rc_directory
1438 (FILE *, const struct res_directory
*, const struct res_id
*,
1439 const struct res_id
*, int *, int);
1440 static void write_rc_subdir
1441 (FILE *, const struct res_entry
*, const struct res_id
*,
1442 const struct res_id
*, int *, int);
1443 static void write_rc_resource
1444 (FILE *, const struct res_id
*, const struct res_id
*,
1445 const struct res_resource
*, int *);
1446 static void write_rc_accelerators (FILE *, const struct accelerator
*);
1447 static void write_rc_cursor (FILE *, const struct cursor
*);
1448 static void write_rc_group_cursor (FILE *, const struct group_cursor
*);
1449 static void write_rc_dialog (FILE *, const struct dialog
*);
1450 static void write_rc_dialog_control (FILE *, const struct dialog_control
*);
1451 static void write_rc_fontdir (FILE *, const struct fontdir
*);
1452 static void write_rc_group_icon (FILE *, const struct group_icon
*);
1453 static void write_rc_menu (FILE *, const struct menu
*, int);
1454 static void write_rc_menuitems (FILE *, const struct menuitem
*, int, int);
1455 static void write_rc_rcdata (FILE *, const struct rcdata_item
*, int);
1456 static void write_rc_stringtable
1457 (FILE *, const struct res_id
*, const struct stringtable
*);
1458 static void write_rc_versioninfo (FILE *, const struct versioninfo
*);
1459 static void write_rc_filedata (FILE *, unsigned long, const unsigned char *);
1461 /* Indent a given number of spaces. */
1464 indent (FILE *e
, int c
)
1468 for (i
= 0; i
< c
; i
++)
1472 /* Dump the resources we have read in the format of an rc file.
1474 Actually, we don't use the format of an rc file, because it's way
1475 too much of a pain--for example, we'd have to write icon resources
1476 into a file and refer to that file. We just generate a readable
1477 format that kind of looks like an rc file, and is useful for
1478 understanding the contents of a resource file. Someday we may want
1479 to generate an rc file which the rc compiler can read; if that day
1480 comes, this code will have to be fixed up. */
1483 write_rc_file (const char *filename
, const struct res_directory
*resources
)
1488 if (filename
== NULL
)
1492 e
= fopen (filename
, FOPEN_WT
);
1494 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1498 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1499 (const struct res_id
*) NULL
, &language
, 1);
1502 /* Write out a directory. E is the file to write to. RD is the
1503 directory. TYPE is a pointer to the level 1 ID which serves as the
1504 resource type. NAME is a pointer to the level 2 ID which serves as
1505 an individual resource name. LANGUAGE is a pointer to the current
1506 language. LEVEL is the level in the tree. */
1509 write_rc_directory (FILE *e
, const struct res_directory
*rd
,
1510 const struct res_id
*type
, const struct res_id
*name
,
1511 int *language
, int level
)
1513 const struct res_entry
*re
;
1515 /* Print out some COFF information that rc files can't represent. */
1518 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1519 if (rd
->characteristics
!= 0)
1520 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1521 if (rd
->major
!= 0 || rd
->minor
!= 0)
1522 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1524 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1529 /* If we're at level 1, the key of this resource is the
1530 type. This normally duplicates the information we have
1531 stored with the resource itself, but we need to remember
1532 the type if this is a user define resource type. */
1537 /* If we're at level 2, the key of this resource is the name
1538 we are going to use in the rc printout. */
1543 /* If we're at level 3, then this key represents a language.
1544 Use it to update the current language. */
1546 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1547 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1549 fprintf (e
, "LANGUAGE %lu, %lu\n",
1550 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1551 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
1552 *language
= re
->id
.u
.id
;
1561 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1566 /* This is the normal case: the three levels are
1567 TYPE/NAME/LANGUAGE. NAME will have been set at level
1568 2, and represents the name to use. We probably just
1569 set LANGUAGE, and it will probably match what the
1570 resource itself records if anything. */
1571 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1575 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1576 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1583 /* Write out a subdirectory entry. E is the file to write to. RE is
1584 the subdirectory entry. TYPE and NAME are pointers to higher level
1585 IDs, or NULL. LANGUAGE is a pointer to the current language.
1586 LEVEL is the level in the tree. */
1589 write_rc_subdir (FILE *e
, const struct res_entry
*re
,
1590 const struct res_id
*type
, const struct res_id
*name
,
1591 int *language
, int level
)
1597 fprintf (e
, "// Type: ");
1599 res_id_print (e
, re
->id
, 1);
1604 switch (re
->id
.u
.id
)
1606 case RT_CURSOR
: s
= "cursor"; break;
1607 case RT_BITMAP
: s
= "bitmap"; break;
1608 case RT_ICON
: s
= "icon"; break;
1609 case RT_MENU
: s
= "menu"; break;
1610 case RT_DIALOG
: s
= "dialog"; break;
1611 case RT_STRING
: s
= "stringtable"; break;
1612 case RT_FONTDIR
: s
= "fontdir"; break;
1613 case RT_FONT
: s
= "font"; break;
1614 case RT_ACCELERATOR
: s
= "accelerators"; break;
1615 case RT_RCDATA
: s
= "rcdata"; break;
1616 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1617 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1618 case RT_GROUP_ICON
: s
= "group icon"; break;
1619 case RT_VERSION
: s
= "version"; break;
1620 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1621 case RT_PLUGPLAY
: s
= "plugplay"; break;
1622 case RT_VXD
: s
= "vxd"; break;
1623 case RT_ANICURSOR
: s
= "anicursor"; break;
1624 case RT_ANIICON
: s
= "aniicon"; break;
1625 default: s
= NULL
; break;
1629 fprintf (e
, "%s", s
);
1631 res_id_print (e
, re
->id
, 1);
1637 fprintf (e
, "// Name: ");
1638 res_id_print (e
, re
->id
, 1);
1643 fprintf (e
, "// Language: ");
1644 res_id_print (e
, re
->id
, 1);
1649 fprintf (e
, "// Level %d: ", level
);
1650 res_id_print (e
, re
->id
, 1);
1654 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1657 /* Write out a single resource. E is the file to write to. TYPE is a
1658 pointer to the type of the resource. NAME is a pointer to the name
1659 of the resource; it will be NULL if there is a level mismatch. RES
1660 is the resource data. LANGUAGE is a pointer to the current
1664 write_rc_resource (FILE *e
, const struct res_id
*type
,
1665 const struct res_id
*name
, const struct res_resource
*res
,
1679 case RES_TYPE_ACCELERATOR
:
1681 rt
= RT_ACCELERATOR
;
1684 case RES_TYPE_BITMAP
:
1689 case RES_TYPE_CURSOR
:
1694 case RES_TYPE_GROUP_CURSOR
:
1696 rt
= RT_GROUP_CURSOR
;
1699 case RES_TYPE_DIALOG
:
1700 if (extended_dialog (res
->u
.dialog
))
1712 case RES_TYPE_FONTDIR
:
1722 case RES_TYPE_GROUP_ICON
:
1728 if (extended_menu (res
->u
.menu
))
1741 case RES_TYPE_MESSAGETABLE
:
1743 rt
= RT_MESSAGETABLE
;
1746 case RES_TYPE_RCDATA
:
1751 case RES_TYPE_STRINGTABLE
:
1756 case RES_TYPE_USERDATA
:
1761 case RES_TYPE_VERSIONINFO
:
1769 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1771 fprintf (e
, "// Unexpected resource type mismatch: ");
1772 res_id_print (e
, *type
, 1);
1773 fprintf (e
, " != %d", rt
);
1776 if (res
->coff_info
.codepage
!= 0)
1777 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1778 if (res
->coff_info
.reserved
!= 0)
1779 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1782 res_id_print (e
, *name
, 0);
1784 fprintf (e
, "??Unknown-Name??");
1788 fprintf (e
, "%s", s
);
1789 else if (type
!= NULL
)
1790 res_id_print (e
, *type
, 0);
1792 fprintf (e
, "??Unknown-Type??");
1794 if (res
->res_info
.memflags
!= 0)
1796 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1797 fprintf (e
, " MOVEABLE");
1798 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1799 fprintf (e
, " PURE");
1800 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1801 fprintf (e
, " PRELOAD");
1802 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1803 fprintf (e
, " DISCARDABLE");
1806 if (res
->type
== RES_TYPE_DIALOG
)
1808 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1809 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1810 if (res
->u
.dialog
->ex
!= NULL
1811 && res
->u
.dialog
->ex
->help
!= 0)
1812 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1817 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1818 || res
->res_info
.characteristics
!= 0
1819 || res
->res_info
.version
!= 0)
1825 case RES_TYPE_ACCELERATOR
:
1826 case RES_TYPE_DIALOG
:
1828 case RES_TYPE_RCDATA
:
1829 case RES_TYPE_STRINGTABLE
:
1838 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1839 fprintf (e
, "%sLANGUAGE %d, %d\n",
1840 modifiers
? "// " : "",
1841 res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
1842 (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
1843 if (res
->res_info
.characteristics
!= 0)
1844 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1845 modifiers
? "// " : "",
1846 res
->res_info
.characteristics
);
1847 if (res
->res_info
.version
!= 0)
1848 fprintf (e
, "%sVERSION %lu\n",
1849 modifiers
? "// " : "",
1850 res
->res_info
.version
);
1858 case RES_TYPE_ACCELERATOR
:
1859 write_rc_accelerators (e
, res
->u
.acc
);
1862 case RES_TYPE_CURSOR
:
1863 write_rc_cursor (e
, res
->u
.cursor
);
1866 case RES_TYPE_GROUP_CURSOR
:
1867 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1870 case RES_TYPE_DIALOG
:
1871 write_rc_dialog (e
, res
->u
.dialog
);
1874 case RES_TYPE_FONTDIR
:
1875 write_rc_fontdir (e
, res
->u
.fontdir
);
1878 case RES_TYPE_GROUP_ICON
:
1879 write_rc_group_icon (e
, res
->u
.group_icon
);
1883 write_rc_menu (e
, res
->u
.menu
, menuex
);
1886 case RES_TYPE_RCDATA
:
1887 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1890 case RES_TYPE_STRINGTABLE
:
1891 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1894 case RES_TYPE_USERDATA
:
1895 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1898 case RES_TYPE_VERSIONINFO
:
1899 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1902 case RES_TYPE_BITMAP
:
1905 case RES_TYPE_MESSAGETABLE
:
1906 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1911 /* Write out accelerator information. */
1914 write_rc_accelerators (FILE *e
, const struct accelerator
*accelerators
)
1916 const struct accelerator
*acc
;
1918 fprintf (e
, "BEGIN\n");
1919 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1925 if ((acc
->key
& 0x7f) == acc
->key
1926 && ISPRINT (acc
->key
)
1927 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1929 fprintf (e
, "\"%c\"", acc
->key
);
1934 fprintf (e
, "%d", acc
->key
);
1938 fprintf (e
, ", %d", acc
->id
);
1942 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1943 fprintf (e
, ", VIRTKEY");
1945 fprintf (e
, ", ASCII");
1948 if ((acc
->flags
& ACC_SHIFT
) != 0)
1949 fprintf (e
, ", SHIFT");
1950 if ((acc
->flags
& ACC_CONTROL
) != 0)
1951 fprintf (e
, ", CONTROL");
1952 if ((acc
->flags
& ACC_ALT
) != 0)
1953 fprintf (e
, ", ALT");
1958 fprintf (e
, "END\n");
1961 /* Write out cursor information. This would normally be in a separate
1962 file, which the rc file would include. */
1965 write_rc_cursor (FILE *e
, const struct cursor
*cursor
)
1967 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
1969 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
1972 /* Write out group cursor data. This would normally be built from the
1976 write_rc_group_cursor (FILE *e
, const struct group_cursor
*group_cursor
)
1978 const struct group_cursor
*gc
;
1980 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
1982 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
1983 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
1984 fprintf (e
, "// data bytes: %lu; index: %d\n",
1985 gc
->bytes
, gc
->index
);
1989 /* Write dialog data. */
1992 write_rc_dialog (FILE *e
, const struct dialog
*dialog
)
1994 const struct dialog_control
*control
;
1996 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
1998 if (dialog
->exstyle
!= 0)
1999 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
2001 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2002 || dialog
->class.u
.id
!= 0)
2004 fprintf (e
, "CLASS ");
2005 res_id_print (e
, dialog
->class, 1);
2009 if (dialog
->caption
!= NULL
)
2011 fprintf (e
, "CAPTION \"");
2012 unicode_print (e
, dialog
->caption
, -1);
2013 fprintf (e
, "\"\n");
2016 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2017 || dialog
->menu
.u
.id
!= 0)
2019 fprintf (e
, "MENU ");
2020 res_id_print (e
, dialog
->menu
, 0);
2024 if (dialog
->font
!= NULL
)
2026 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
2027 unicode_print (e
, dialog
->font
, -1);
2029 if (dialog
->ex
!= NULL
2030 && (dialog
->ex
->weight
!= 0
2031 || dialog
->ex
->italic
!= 0
2032 || dialog
->ex
->charset
!= 1))
2033 fprintf (e
, ", %d, %d, %d",
2034 dialog
->ex
->weight
, dialog
->ex
->italic
, dialog
->ex
->charset
);
2038 fprintf (e
, "BEGIN\n");
2040 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2041 write_rc_dialog_control (e
, control
);
2043 fprintf (e
, "END\n");
2046 /* For each predefined control keyword, this table provides the class
2052 unsigned short class;
2053 unsigned long style
;
2056 static const struct control_info control_info
[] =
2058 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2059 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2060 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2061 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2062 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2063 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2064 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2065 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2066 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2067 { "ICON", CTL_STATIC
, SS_ICON
},
2068 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2069 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2070 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2071 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2072 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2073 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2074 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2075 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2076 /* It's important that USERBUTTON come after all the other button
2077 types, so that it won't be matched too early. */
2078 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2082 /* Write a dialog control. */
2085 write_rc_dialog_control (FILE *e
, const struct dialog_control
*control
)
2087 const struct control_info
*ci
;
2091 if (control
->class.named
)
2095 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2096 if (ci
->class == control
->class.u
.id
2097 && (ci
->style
== (unsigned long) -1
2098 || ci
->style
== (control
->style
& 0xff)))
2102 fprintf (e
, "CONTROL");
2103 else if (ci
->name
!= NULL
)
2104 fprintf (e
, "%s", ci
->name
);
2106 fprintf (e
, "CONTROL");
2108 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2111 res_id_print (e
, control
->text
, 1);
2115 fprintf (e
, " %d, ", control
->id
);
2119 if (control
->class.named
)
2121 res_id_print (e
, control
->class, 0);
2122 if (control
->class.named
)
2124 fprintf (e
, ", 0x%lx, ", control
->style
);
2127 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2129 if (control
->style
!= SS_ICON
2130 || control
->exstyle
!= 0
2131 || control
->width
!= 0
2132 || control
->height
!= 0
2133 || control
->help
!= 0)
2135 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2137 /* FIXME: We don't need to print the style if it is the default.
2138 More importantly, in certain cases we actually need to turn
2139 off parts of the forced style, by using NOT. */
2140 fprintf (e
, ", 0x%lx", control
->style
);
2142 if (control
->exstyle
!= 0 || control
->help
!= 0)
2143 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2148 if (control
->data
!= NULL
)
2149 write_rc_rcdata (e
, control
->data
, 2);
2152 /* Write out font directory data. This would normally be built from
2156 write_rc_fontdir (FILE *e
, const struct fontdir
*fontdir
)
2158 const struct fontdir
*fc
;
2160 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2162 fprintf (e
, "// Font index: %d\n", fc
->index
);
2163 write_rc_filedata (e
, fc
->length
, fc
->data
);
2167 /* Write out group icon data. This would normally be built from the
2171 write_rc_group_icon (FILE *e
, const struct group_icon
*group_icon
)
2173 const struct group_icon
*gi
;
2175 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2177 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2178 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2179 fprintf (e
, "// data bytes: %lu; index: %d\n",
2180 gi
->bytes
, gi
->index
);
2184 /* Write out a menu resource. */
2187 write_rc_menu (FILE *e
, const struct menu
*menu
, int menuex
)
2189 if (menu
->help
!= 0)
2190 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2191 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2194 /* Write out menuitems. */
2197 write_rc_menuitems (FILE *e
, const struct menuitem
*menuitems
, int menuex
,
2200 const struct menuitem
*mi
;
2203 fprintf (e
, "BEGIN\n");
2205 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2207 indent (e
, ind
+ 2);
2209 if (mi
->popup
== NULL
)
2210 fprintf (e
, "MENUITEM");
2212 fprintf (e
, "POPUP");
2215 && mi
->popup
== NULL
2220 fprintf (e
, " SEPARATOR\n");
2224 if (mi
->text
== NULL
)
2225 fprintf (e
, " \"\"");
2229 unicode_print (e
, mi
->text
, -1);
2235 if (mi
->popup
== NULL
)
2236 fprintf (e
, ", %d", mi
->id
);
2238 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2239 fprintf (e
, ", CHECKED");
2240 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2241 fprintf (e
, ", GRAYED");
2242 if ((mi
->type
& MENUITEM_HELP
) != 0)
2243 fprintf (e
, ", HELP");
2244 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2245 fprintf (e
, ", INACTIVE");
2246 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2247 fprintf (e
, ", MENUBARBREAK");
2248 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2249 fprintf (e
, ", MENUBREAK");
2253 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2255 fprintf (e
, ", %d", mi
->id
);
2256 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2258 fprintf (e
, ", %lu", mi
->type
);
2259 if (mi
->state
!= 0 || mi
->help
!= 0)
2261 fprintf (e
, ", %lu", mi
->state
);
2263 fprintf (e
, ", %lu", mi
->help
);
2271 if (mi
->popup
!= NULL
)
2272 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2276 fprintf (e
, "END\n");
2279 /* Write out an rcdata resource. This is also used for other types of
2280 resources that need to print arbitrary data. */
2283 write_rc_rcdata (FILE *e
, const struct rcdata_item
*rcdata
, int ind
)
2285 const struct rcdata_item
*ri
;
2288 fprintf (e
, "BEGIN\n");
2290 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2292 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2295 indent (e
, ind
+ 2);
2303 fprintf (e
, "%d", ri
->u
.word
);
2307 fprintf (e
, "%luL", ri
->u
.dword
);
2317 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2322 fprintf (e
, "\\%03o", *s
);
2328 case RCDATA_WSTRING
:
2330 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2339 /* Assume little endian data. */
2342 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2348 indent (e
, ind
+ 2);
2349 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2350 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2351 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2352 | ri
->u
.buffer
.data
[i
]);
2353 fprintf (e
, "%luL", l
);
2354 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2356 for (j
= 0; j
< 4; ++j
)
2357 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2358 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2362 fprintf (e
, "\t// ");
2363 for (j
= 0; j
< 4; ++j
)
2365 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2366 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2369 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2371 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2379 if (i
+ 1 < ri
->u
.buffer
.length
)
2385 indent (e
, ind
+ 2);
2386 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2387 fprintf (e
, "%d", s
);
2388 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2390 for (j
= 0; j
< 2; ++j
)
2391 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2392 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2396 fprintf (e
, "\t// ");
2397 for (j
= 0; j
< 2; ++j
)
2399 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2400 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2403 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2405 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2414 if (i
< ri
->u
.buffer
.length
)
2417 indent (e
, ind
+ 2);
2418 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2419 && ISPRINT (ri
->u
.buffer
.data
[i
]))
2420 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2422 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2423 if (ri
->next
!= NULL
)
2433 if (ri
->type
!= RCDATA_BUFFER
)
2435 if (ri
->next
!= NULL
)
2442 fprintf (e
, "END\n");
2445 /* Write out a stringtable resource. */
2448 write_rc_stringtable (FILE *e
, const struct res_id
*name
,
2449 const struct stringtable
*stringtable
)
2451 unsigned long offset
;
2454 if (name
!= NULL
&& ! name
->named
)
2455 offset
= (name
->u
.id
- 1) << 4;
2458 fprintf (e
, "// %s string table name\n",
2459 name
== NULL
? "Missing" : "Invalid");
2463 fprintf (e
, "BEGIN\n");
2465 for (i
= 0; i
< 16; i
++)
2467 if (stringtable
->strings
[i
].length
!= 0)
2469 fprintf (e
, " %lu, \"", offset
+ i
);
2470 unicode_print (e
, stringtable
->strings
[i
].string
,
2471 stringtable
->strings
[i
].length
);
2472 fprintf (e
, "\"\n");
2476 fprintf (e
, "END\n");
2479 /* Write out a versioninfo resource. */
2482 write_rc_versioninfo (FILE *e
, const struct versioninfo
*versioninfo
)
2484 const struct fixed_versioninfo
*f
;
2485 const struct ver_info
*vi
;
2487 f
= versioninfo
->fixed
;
2488 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2489 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2490 (f
->file_version_ms
>> 16) & 0xffff,
2491 f
->file_version_ms
& 0xffff,
2492 (f
->file_version_ls
>> 16) & 0xffff,
2493 f
->file_version_ls
& 0xffff);
2494 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2495 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2496 (f
->product_version_ms
>> 16) & 0xffff,
2497 f
->product_version_ms
& 0xffff,
2498 (f
->product_version_ls
>> 16) & 0xffff,
2499 f
->product_version_ls
& 0xffff);
2500 if (f
->file_flags_mask
!= 0)
2501 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2502 if (f
->file_flags
!= 0)
2503 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2504 if (f
->file_os
!= 0)
2505 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2506 if (f
->file_type
!= 0)
2507 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2508 if (f
->file_subtype
!= 0)
2509 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2510 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2511 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2513 fprintf (e
, "BEGIN\n");
2515 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2519 case VERINFO_STRING
:
2521 const struct ver_stringinfo
*vs
;
2523 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2524 fprintf (e
, " BEGIN\n");
2525 fprintf (e
, " BLOCK \"");
2526 unicode_print (e
, vi
->u
.string
.language
, -1);
2527 fprintf (e
, "\"\n");
2528 fprintf (e
, " BEGIN\n");
2530 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2532 fprintf (e
, " VALUE \"");
2533 unicode_print (e
, vs
->key
, -1);
2534 fprintf (e
, "\", \"");
2535 unicode_print (e
, vs
->value
, -1);
2536 fprintf (e
, "\"\n");
2539 fprintf (e
, " END\n");
2540 fprintf (e
, " END\n");
2546 const struct ver_varinfo
*vv
;
2548 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2549 fprintf (e
, " BEGIN\n");
2550 fprintf (e
, " VALUE \"");
2551 unicode_print (e
, vi
->u
.var
.key
, -1);
2554 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2555 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2558 fprintf (e
, "\n END\n");
2565 fprintf (e
, "END\n");
2568 /* Write out data which would normally be read from a file. */
2571 write_rc_filedata (FILE *e
, unsigned long length
, const unsigned char *data
)
2575 for (i
= 0; i
+ 15 < length
; i
+= 16)
2577 fprintf (e
, "// %4lx: ", i
);
2578 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2579 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2580 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2581 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2582 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2583 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2588 fprintf (e
, "// %4lx:", i
);
2591 fprintf (e
, " %02x", data
[i
]);