1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002 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
PARAMS ((char *, const char *));
165 static FILE *open_input_stream
PARAMS ((char *));
166 static FILE *look_for_default
PARAMS ((char *, const char *, int,
167 const char *, const char *));
168 static void close_input_stream
PARAMS ((void));
169 static void unexpected_eof
PARAMS ((const char *));
170 static int get_word
PARAMS ((FILE *, const char *));
171 static unsigned long get_long
PARAMS ((FILE *, const char *));
173 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
174 static void define_fontdirs
PARAMS ((void));
176 /* Run `cmd' and redirect the output to `redir'. */
184 int pid
, wait_status
, retcode
;
187 char *errmsg_fmt
, *errmsg_arg
;
188 char *temp_base
= choose_temp_base ();
191 int redir_handle
= -1;
192 int stdout_save
= -1;
194 /* Count the args. */
197 for (s
= cmd
; *s
; s
++)
202 argv
= alloca (sizeof (char *) * (i
+ 3));
208 while (*s
== ' ' && *s
!= 0)
214 in_quote
= (*s
== '\'' || *s
== '"');
215 sep
= (in_quote
) ? *s
++ : ' ';
218 while (*s
!= sep
&& *s
!= 0)
231 /* Setup the redirection. We can't use the usual fork/exec and redirect
232 since we may be running on non-POSIX Windows host. */
237 /* Open temporary output file. */
238 redir_handle
= open (redir
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
239 if (redir_handle
== -1)
240 fatal (_("can't open temporary file `%s': %s"), redir
,
243 /* Duplicate the stdout file handle so it can be restored later. */
244 stdout_save
= dup (STDOUT_FILENO
);
245 if (stdout_save
== -1)
246 fatal (_("can't redirect stdout: `%s': %s"), redir
, strerror (errno
));
248 /* Redirect stdout to our output file. */
249 dup2 (redir_handle
, STDOUT_FILENO
);
251 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
252 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
254 /* Restore stdout to its previous setting. */
255 dup2 (stdout_save
, STDOUT_FILENO
);
257 /* Close reponse file. */
258 close (redir_handle
);
262 fatal (_("%s %s: %s"), errmsg_fmt
, errmsg_arg
, strerror (errno
));
267 pid
= pwait (pid
, &wait_status
, 0);
271 fatal (_("wait: %s"), strerror (errno
));
274 else if (WIFSIGNALED (wait_status
))
276 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status
));
279 else if (WIFEXITED (wait_status
))
281 if (WEXITSTATUS (wait_status
) != 0)
283 fatal (_("%s exited with status %d"), cmd
,
284 WEXITSTATUS (wait_status
));
295 open_input_stream (cmd
)
298 if (istream_type
== ISTREAM_FILE
)
302 fileprefix
= choose_temp_base ();
303 cpp_temp_file
= (char *) xmalloc (strlen (fileprefix
) + 5);
304 sprintf (cpp_temp_file
, "%s.irc", fileprefix
);
307 if (run_cmd (cmd
, cpp_temp_file
))
308 fatal (_("can't execute `%s': %s"), cmd
, strerror (errno
));
310 cpp_pipe
= fopen (cpp_temp_file
, FOPEN_RT
);;
311 if (cpp_pipe
== NULL
)
312 fatal (_("can't open temporary file `%s': %s"),
313 cpp_temp_file
, strerror (errno
));
317 _("Using temporary file `%s' to read preprocessor output\n"),
322 cpp_pipe
= popen (cmd
, FOPEN_RT
);
323 if (cpp_pipe
== NULL
)
324 fatal (_("can't popen `%s': %s"), cmd
, strerror (errno
));
326 fprintf (stderr
, _("Using popen to read preprocessor output\n"));
329 xatexit (close_input_stream
);
333 /* look for the preprocessor program */
336 look_for_default (cmd
, prefix
, end_prefix
, preprocargs
, filename
)
340 const char *preprocargs
;
341 const char *filename
;
347 strcpy (cmd
, prefix
);
349 sprintf (cmd
+ end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
350 space
= strchr (cmd
+ end_prefix
, ' ');
355 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
356 strchr (cmd
, '\\') ||
360 found
= (stat (cmd
, &s
) == 0
361 #ifdef HAVE_EXECUTABLE_SUFFIX
362 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
369 fprintf (stderr
, _("Tried `%s'\n"), cmd
);
374 strcpy (cmd
, prefix
);
376 sprintf (cmd
+ end_prefix
, "%s %s %s",
377 DEFAULT_PREPROCESSOR
, preprocargs
, filename
);
380 fprintf (stderr
, _("Using `%s'\n"), cmd
);
382 cpp_pipe
= open_input_stream (cmd
);
386 /* Read an rc file. */
388 struct res_directory
*
389 read_rc_file (filename
, preprocessor
, preprocargs
, language
, use_temp_file
)
390 const char *filename
;
391 const char *preprocessor
;
392 const char *preprocargs
;
398 istream_type
= (use_temp_file
) ? ISTREAM_FILE
: ISTREAM_PIPE
;
400 if (preprocargs
== NULL
)
402 if (filename
== NULL
)
407 cmd
= xmalloc (strlen (preprocessor
)
408 + strlen (preprocargs
)
411 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
413 cpp_pipe
= open_input_stream (cmd
);
417 char *dash
, *slash
, *cp
;
419 preprocessor
= DEFAULT_PREPROCESSOR
;
421 cmd
= xmalloc (strlen (program_name
)
422 + strlen (preprocessor
)
423 + strlen (preprocargs
)
425 #ifdef HAVE_EXECUTABLE_SUFFIX
426 + strlen (EXECUTABLE_SUFFIX
)
432 for (cp
= program_name
; *cp
; cp
++)
437 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
438 *cp
== ':' || *cp
== '\\' ||
451 /* First, try looking for a prefixed gcc in the windres
452 directory, with the same prefix as windres */
454 cpp_pipe
= look_for_default (cmd
, program_name
, dash
-program_name
+1,
455 preprocargs
, filename
);
458 if (slash
&& !cpp_pipe
)
460 /* Next, try looking for a gcc in the same directory as
463 cpp_pipe
= look_for_default (cmd
, program_name
, slash
-program_name
+1,
464 preprocargs
, filename
);
469 /* Sigh, try the default */
471 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
478 rc_filename
= xstrdup (filename
);
481 rcparse_set_language (language
);
485 close_input_stream ();
487 if (fontdirs
!= NULL
)
496 /* Close the input stream if it is open. */
499 close_input_stream ()
501 if (istream_type
== ISTREAM_FILE
)
503 if (cpp_pipe
!= NULL
)
506 if (cpp_temp_file
!= NULL
)
508 int errno_save
= errno
;
510 unlink (cpp_temp_file
);
512 free (cpp_temp_file
);
517 if (cpp_pipe
!= NULL
)
521 /* Since this is also run via xatexit, safeguard. */
523 cpp_temp_file
= NULL
;
526 /* Report an error while reading an rc file. */
532 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
535 /* Issue a warning while reading an rc file. */
538 rcparse_warning (msg
)
541 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
544 /* Die if we get an unexpected end of file. */
550 fatal (_("%s: unexpected EOF"), msg
);
553 /* Read a 16 bit word from a file. The data is assumed to be little
566 unexpected_eof (msg
);
567 return ((b2
& 0xff) << 8) | (b1
& 0xff);
570 /* Read a 32 bit word from a file. The data is assumed to be little
585 unexpected_eof (msg
);
586 return (((((((b4
& 0xff) << 8)
592 /* Read data from a file. This is a wrapper to do error checking. */
595 get_data (e
, p
, c
, msg
)
603 got
= fread (p
, 1, c
, e
);
607 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
610 /* Define an accelerator resource. */
613 define_accelerator (id
, resinfo
, data
)
615 const struct res_res_info
*resinfo
;
616 struct accelerator
*data
;
618 struct res_resource
*r
;
620 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
621 resinfo
->language
, 0);
622 r
->type
= RES_TYPE_ACCELERATOR
;
624 r
->res_info
= *resinfo
;
627 /* Define a bitmap resource. Bitmap data is stored in a file. The
628 first 14 bytes of the file are a standard header, which is not
629 included in the resource data. */
631 #define BITMAP_SKIP (14)
634 define_bitmap (id
, resinfo
, filename
)
636 const struct res_res_info
*resinfo
;
637 const char *filename
;
644 struct res_resource
*r
;
646 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
648 if (stat (real_filename
, &s
) < 0)
649 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
652 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
654 for (i
= 0; i
< BITMAP_SKIP
; i
++)
657 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
660 free (real_filename
);
662 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
663 resinfo
->language
, 0);
665 r
->type
= RES_TYPE_BITMAP
;
666 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
667 r
->u
.data
.data
= data
;
668 r
->res_info
= *resinfo
;
671 /* Define a cursor resource. A cursor file may contain a set of
672 bitmaps, each representing the same cursor at various different
673 resolutions. They each get written out with a different ID. The
674 real cursor resource is then a group resource which can be used to
675 select one of the actual cursors. */
678 define_cursor (id
, resinfo
, filename
)
680 const struct res_res_info
*resinfo
;
681 const char *filename
;
686 struct icondir
*icondirs
;
688 struct res_resource
*r
;
689 struct group_cursor
*first
, **pp
;
691 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
693 /* A cursor file is basically an icon file. The start of the file
694 is a three word structure. The first word is ignored. The
695 second word is the type of data. The third word is the number of
698 get_word (e
, real_filename
);
699 type
= get_word (e
, real_filename
);
700 count
= get_word (e
, real_filename
);
702 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
704 /* Read in the icon directory entries. */
706 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
708 for (i
= 0; i
< count
; i
++)
710 icondirs
[i
].width
= getc (e
);
711 icondirs
[i
].height
= getc (e
);
712 icondirs
[i
].colorcount
= getc (e
);
714 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
715 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
716 icondirs
[i
].bytes
= get_long (e
, real_filename
);
717 icondirs
[i
].offset
= get_long (e
, real_filename
);
720 unexpected_eof (real_filename
);
723 /* Define each cursor as a unique resource. */
725 first_cursor
= cursors
;
727 for (i
= 0; i
< count
; i
++)
733 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
734 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
735 icondirs
[i
].offset
, strerror (errno
));
737 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
739 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
741 c
= (struct cursor
*) res_alloc (sizeof *c
);
742 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
743 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
744 c
->length
= icondirs
[i
].bytes
;
752 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
753 resinfo
->language
, 0);
754 r
->type
= RES_TYPE_CURSOR
;
756 r
->res_info
= *resinfo
;
760 free (real_filename
);
762 /* Define a cursor group resource. */
766 for (i
= 0; i
< count
; i
++)
768 struct group_cursor
*cg
;
770 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
772 cg
->width
= icondirs
[i
].width
;
773 cg
->height
= 2 * icondirs
[i
].height
;
775 /* FIXME: What should these be set to? */
779 cg
->bytes
= icondirs
[i
].bytes
+ 4;
780 cg
->index
= first_cursor
+ i
+ 1;
788 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
789 resinfo
->language
, 0);
790 r
->type
= RES_TYPE_GROUP_CURSOR
;
791 r
->u
.group_cursor
= first
;
792 r
->res_info
= *resinfo
;
795 /* Define a dialog resource. */
798 define_dialog (id
, resinfo
, dialog
)
800 const struct res_res_info
*resinfo
;
801 const struct dialog
*dialog
;
804 struct res_resource
*r
;
806 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
809 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
810 resinfo
->language
, 0);
811 r
->type
= RES_TYPE_DIALOG
;
813 r
->res_info
= *resinfo
;
816 /* Define a dialog control. This does not define a resource, but
817 merely allocates and fills in a structure. */
819 struct dialog_control
*
820 define_control (text
, id
, x
, y
, width
, height
, class, style
, exstyle
)
826 unsigned long height
;
829 unsigned long exstyle
;
831 struct dialog_control
*n
;
833 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
837 n
->exstyle
= exstyle
;
843 n
->class.u
.id
= class;
846 res_string_to_id (&n
->text
, text
);
853 struct dialog_control
*
854 define_icon_control (iid
, id
, x
, y
, style
, exstyle
, help
, data
, ex
)
860 unsigned long exstyle
;
862 struct rcdata_item
*data
;
863 struct dialog_ex
*ex
;
865 struct dialog_control
*n
;
867 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
868 n
= define_control (0, id
, x
, y
, 0, 0, CTL_STATIC
, style
, exstyle
);
871 rcparse_warning (_("help ID requires DIALOGEX"));
873 rcparse_warning (_("control data requires DIALOGEX"));
880 /* Define a font resource. */
883 define_font (id
, resinfo
, filename
)
885 const struct res_res_info
*resinfo
;
886 const char *filename
;
892 struct res_resource
*r
;
895 unsigned char *fontdata
;
897 const char *device
, *face
;
900 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
902 if (stat (real_filename
, &s
) < 0)
903 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
906 data
= (unsigned char *) res_alloc (s
.st_size
);
908 get_data (e
, data
, s
.st_size
, real_filename
);
911 free (real_filename
);
913 r
= define_standard_resource (&resources
, RT_FONT
, id
,
914 resinfo
->language
, 0);
916 r
->type
= RES_TYPE_FONT
;
917 r
->u
.data
.length
= s
.st_size
;
918 r
->u
.data
.data
= data
;
919 r
->res_info
= *resinfo
;
921 /* For each font resource, we must add an entry in the FONTDIR
922 resource. The FONTDIR resource includes some strings in the font
923 file. To find them, we have to do some magic on the data we have
926 offset
= ((((((data
[47] << 8)
930 if (offset
> 0 && offset
< s
.st_size
)
931 device
= (char *) data
+ offset
;
935 offset
= ((((((data
[51] << 8)
939 if (offset
> 0 && offset
< s
.st_size
)
940 face
= (char *) data
+ offset
;
946 fontdatalength
= 58 + strlen (device
) + strlen (face
);
947 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
948 memcpy (fontdata
, data
, 56);
949 strcpy ((char *) fontdata
+ 56, device
);
950 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
952 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
955 fd
->length
= fontdatalength
;
958 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
962 /* For the single fontdirs resource, we always use the resource
963 information of the last font. I don't know what else to do. */
964 fontdirs_resinfo
= *resinfo
;
967 /* Define the fontdirs resource. This is called after the entire rc
968 file has been parsed, if any font resources were seen. */
973 struct res_resource
*r
;
979 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
981 r
->type
= RES_TYPE_FONTDIR
;
982 r
->u
.fontdir
= fontdirs
;
983 r
->res_info
= fontdirs_resinfo
;
986 /* Define an icon resource. An icon file may contain a set of
987 bitmaps, each representing the same icon at various different
988 resolutions. They each get written out with a different ID. The
989 real icon resource is then a group resource which can be used to
990 select one of the actual icon bitmaps. */
993 define_icon (id
, resinfo
, filename
)
995 const struct res_res_info
*resinfo
;
996 const char *filename
;
1001 struct icondir
*icondirs
;
1003 struct res_resource
*r
;
1004 struct group_icon
*first
, **pp
;
1006 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
1008 /* The start of an icon file is a three word structure. The first
1009 word is ignored. The second word is the type of data. The third
1010 word is the number of entries. */
1012 get_word (e
, real_filename
);
1013 type
= get_word (e
, real_filename
);
1014 count
= get_word (e
, real_filename
);
1016 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1018 /* Read in the icon directory entries. */
1020 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1022 for (i
= 0; i
< count
; i
++)
1024 icondirs
[i
].width
= getc (e
);
1025 icondirs
[i
].height
= getc (e
);
1026 icondirs
[i
].colorcount
= getc (e
);
1028 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1029 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1030 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1031 icondirs
[i
].offset
= get_long (e
, real_filename
);
1034 unexpected_eof (real_filename
);
1037 /* Define each icon as a unique resource. */
1041 for (i
= 0; i
< count
; i
++)
1043 unsigned char *data
;
1046 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1047 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1048 icondirs
[i
].offset
, strerror (errno
));
1050 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1052 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1059 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1060 resinfo
->language
, 0);
1061 r
->type
= RES_TYPE_ICON
;
1062 r
->u
.data
.length
= icondirs
[i
].bytes
;
1063 r
->u
.data
.data
= data
;
1064 r
->res_info
= *resinfo
;
1068 free (real_filename
);
1070 /* Define an icon group resource. */
1074 for (i
= 0; i
< count
; i
++)
1076 struct group_icon
*cg
;
1078 /* For some reason, at least in some files the planes and bits
1079 are zero. We instead set them from the color. This is
1082 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1084 cg
->width
= icondirs
[i
].width
;
1085 cg
->height
= icondirs
[i
].height
;
1086 cg
->colors
= icondirs
[i
].colorcount
;
1090 while ((1 << cg
->bits
) < cg
->colors
)
1093 cg
->bytes
= icondirs
[i
].bytes
;
1094 cg
->index
= first_icon
+ i
+ 1;
1102 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1103 resinfo
->language
, 0);
1104 r
->type
= RES_TYPE_GROUP_ICON
;
1105 r
->u
.group_icon
= first
;
1106 r
->res_info
= *resinfo
;
1109 /* Define a menu resource. */
1112 define_menu (id
, resinfo
, menuitems
)
1114 const struct res_res_info
*resinfo
;
1115 struct menuitem
*menuitems
;
1118 struct res_resource
*r
;
1120 m
= (struct menu
*) res_alloc (sizeof *m
);
1121 m
->items
= menuitems
;
1124 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1125 r
->type
= RES_TYPE_MENU
;
1127 r
->res_info
= *resinfo
;
1130 /* Define a menu item. This does not define a resource, but merely
1131 allocates and fills in a structure. */
1134 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
1138 unsigned long state
;
1140 struct menuitem
*menuitems
;
1142 struct menuitem
*mi
;
1144 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1152 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1154 mi
->popup
= menuitems
;
1158 /* Define a messagetable resource. */
1161 define_messagetable (id
, resinfo
, filename
)
1163 const struct res_res_info
*resinfo
;
1164 const char *filename
;
1167 char *real_filename
;
1169 unsigned char *data
;
1170 struct res_resource
*r
;
1172 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1175 if (stat (real_filename
, &s
) < 0)
1176 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1179 data
= (unsigned char *) res_alloc (s
.st_size
);
1181 get_data (e
, data
, s
.st_size
, real_filename
);
1184 free (real_filename
);
1186 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1187 resinfo
->language
, 0);
1189 r
->type
= RES_TYPE_MESSAGETABLE
;
1190 r
->u
.data
.length
= s
.st_size
;
1191 r
->u
.data
.data
= data
;
1192 r
->res_info
= *resinfo
;
1195 /* Define an rcdata resource. */
1198 define_rcdata (id
, resinfo
, data
)
1200 const struct res_res_info
*resinfo
;
1201 struct rcdata_item
*data
;
1203 struct res_resource
*r
;
1205 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1206 resinfo
->language
, 0);
1207 r
->type
= RES_TYPE_RCDATA
;
1209 r
->res_info
= *resinfo
;
1212 /* Create an rcdata item holding a string. */
1214 struct rcdata_item
*
1215 define_rcdata_string (string
, len
)
1219 struct rcdata_item
*ri
;
1222 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1224 ri
->type
= RCDATA_STRING
;
1225 ri
->u
.string
.length
= len
;
1226 s
= (char *) res_alloc (len
);
1227 memcpy (s
, string
, len
);
1233 /* Create an rcdata item holding a number. */
1235 struct rcdata_item
*
1236 define_rcdata_number (val
, dword
)
1240 struct rcdata_item
*ri
;
1242 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1244 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1250 /* Define a stringtable resource. This is called for each string
1251 which appears in a STRINGTABLE statement. */
1254 define_stringtable (resinfo
, stringid
, string
)
1255 const struct res_res_info
*resinfo
;
1256 unsigned long stringid
;
1260 struct res_resource
*r
;
1263 id
.u
.id
= (stringid
>> 4) + 1;
1264 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1265 resinfo
->language
, 1);
1267 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1271 r
->type
= RES_TYPE_STRINGTABLE
;
1272 r
->u
.stringtable
= ((struct stringtable
*)
1273 res_alloc (sizeof (struct stringtable
)));
1274 for (i
= 0; i
< 16; i
++)
1276 r
->u
.stringtable
->strings
[i
].length
= 0;
1277 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1280 r
->res_info
= *resinfo
;
1283 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1284 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1288 /* Define a user data resource where the data is in the rc file. */
1291 define_user_data (id
, type
, resinfo
, data
)
1294 const struct res_res_info
*resinfo
;
1295 struct rcdata_item
*data
;
1297 struct res_id ids
[3];
1298 struct res_resource
*r
;
1303 ids
[2].u
.id
= resinfo
->language
;
1305 r
= define_resource (&resources
, 3, ids
, 0);
1306 r
->type
= RES_TYPE_USERDATA
;
1307 r
->u
.userdata
= data
;
1308 r
->res_info
= *resinfo
;
1311 /* Define a user data resource where the data is in a file. */
1314 define_user_file (id
, type
, resinfo
, filename
)
1317 const struct res_res_info
*resinfo
;
1318 const char *filename
;
1321 char *real_filename
;
1323 unsigned char *data
;
1324 struct res_id ids
[3];
1325 struct res_resource
*r
;
1327 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1329 if (stat (real_filename
, &s
) < 0)
1330 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1333 data
= (unsigned char *) res_alloc (s
.st_size
);
1335 get_data (e
, data
, s
.st_size
, real_filename
);
1338 free (real_filename
);
1343 ids
[2].u
.id
= resinfo
->language
;
1345 r
= define_resource (&resources
, 3, ids
, 0);
1346 r
->type
= RES_TYPE_USERDATA
;
1347 r
->u
.userdata
= ((struct rcdata_item
*)
1348 res_alloc (sizeof (struct rcdata_item
)));
1349 r
->u
.userdata
->next
= NULL
;
1350 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1351 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1352 r
->u
.userdata
->u
.buffer
.data
= data
;
1353 r
->res_info
= *resinfo
;
1356 /* Define a versioninfo resource. */
1359 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1362 struct fixed_versioninfo
*fixedverinfo
;
1363 struct ver_info
*verinfo
;
1365 struct res_resource
*r
;
1367 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1368 r
->type
= RES_TYPE_VERSIONINFO
;
1369 r
->u
.versioninfo
= ((struct versioninfo
*)
1370 res_alloc (sizeof (struct versioninfo
)));
1371 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1372 r
->u
.versioninfo
->var
= verinfo
;
1373 r
->res_info
.language
= language
;
1376 /* Add string version info to a list of version information. */
1379 append_ver_stringfileinfo (verinfo
, language
, strings
)
1380 struct ver_info
*verinfo
;
1381 const char *language
;
1382 struct ver_stringinfo
*strings
;
1384 struct ver_info
*vi
, **pp
;
1386 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1388 vi
->type
= VERINFO_STRING
;
1389 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1390 vi
->u
.string
.strings
= strings
;
1392 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1399 /* Add variable version info to a list of version information. */
1402 append_ver_varfileinfo (verinfo
, key
, var
)
1403 struct ver_info
*verinfo
;
1405 struct ver_varinfo
*var
;
1407 struct ver_info
*vi
, **pp
;
1409 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1411 vi
->type
= VERINFO_VAR
;
1412 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1413 vi
->u
.var
.var
= var
;
1415 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1422 /* Append version string information to a list. */
1424 struct ver_stringinfo
*
1425 append_verval (strings
, key
, value
)
1426 struct ver_stringinfo
*strings
;
1430 struct ver_stringinfo
*vs
, **pp
;
1432 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1434 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1435 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1437 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1444 /* Append version variable information to a list. */
1446 struct ver_varinfo
*
1447 append_vertrans (var
, language
, charset
)
1448 struct ver_varinfo
*var
;
1449 unsigned long language
;
1450 unsigned long charset
;
1452 struct ver_varinfo
*vv
, **pp
;
1454 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1456 vv
->language
= language
;
1457 vv
->charset
= charset
;
1459 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1466 /* Local functions used to write out an rc file. */
1468 static void indent
PARAMS ((FILE *, int));
1469 static void write_rc_directory
1470 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1471 const struct res_id
*, int *, int));
1472 static void write_rc_subdir
1473 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1474 const struct res_id
*, int *, int));
1475 static void write_rc_resource
1476 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1477 const struct res_resource
*, int *));
1478 static void write_rc_accelerators
1479 PARAMS ((FILE *, const struct accelerator
*));
1480 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1481 static void write_rc_group_cursor
1482 PARAMS ((FILE *, const struct group_cursor
*));
1483 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1484 static void write_rc_dialog_control
1485 PARAMS ((FILE *, const struct dialog_control
*));
1486 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1487 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1488 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1489 static void write_rc_menuitems
1490 PARAMS ((FILE *, const struct menuitem
*, int, int));
1491 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1492 static void write_rc_stringtable
1493 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1494 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1495 static void write_rc_filedata
1496 PARAMS ((FILE *, unsigned long, const unsigned char *));
1498 /* Indent a given number of spaces. */
1507 for (i
= 0; i
< c
; i
++)
1511 /* Dump the resources we have read in the format of an rc file.
1513 Actually, we don't use the format of an rc file, because it's way
1514 too much of a pain--for example, we'd have to write icon resources
1515 into a file and refer to that file. We just generate a readable
1516 format that kind of looks like an rc file, and is useful for
1517 understanding the contents of a resource file. Someday we may want
1518 to generate an rc file which the rc compiler can read; if that day
1519 comes, this code will have to be fixed up. */
1522 write_rc_file (filename
, resources
)
1523 const char *filename
;
1524 const struct res_directory
*resources
;
1529 if (filename
== NULL
)
1533 e
= fopen (filename
, FOPEN_WT
);
1535 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1539 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1540 (const struct res_id
*) NULL
, &language
, 1);
1543 /* Write out a directory. E is the file to write to. RD is the
1544 directory. TYPE is a pointer to the level 1 ID which serves as the
1545 resource type. NAME is a pointer to the level 2 ID which serves as
1546 an individual resource name. LANGUAGE is a pointer to the current
1547 language. LEVEL is the level in the tree. */
1550 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1552 const struct res_directory
*rd
;
1553 const struct res_id
*type
;
1554 const struct res_id
*name
;
1558 const struct res_entry
*re
;
1560 /* Print out some COFF information that rc files can't represent. */
1563 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1564 if (rd
->characteristics
!= 0)
1565 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1566 if (rd
->major
!= 0 || rd
->minor
!= 0)
1567 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1569 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1574 /* If we're at level 1, the key of this resource is the
1575 type. This normally duplicates the information we have
1576 stored with the resource itself, but we need to remember
1577 the type if this is a user define resource type. */
1582 /* If we're at level 2, the key of this resource is the name
1583 we are going to use in the rc printout. */
1588 /* If we're at level 3, then this key represents a language.
1589 Use it to update the current language. */
1591 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1592 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1594 fprintf (e
, "LANGUAGE %lu, %lu\n",
1595 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1596 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
1597 *language
= re
->id
.u
.id
;
1606 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1611 /* This is the normal case: the three levels are
1612 TYPE/NAME/LANGUAGE. NAME will have been set at level
1613 2, and represents the name to use. We probably just
1614 set LANGUAGE, and it will probably match what the
1615 resource itself records if anything. */
1616 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1620 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1621 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1628 /* Write out a subdirectory entry. E is the file to write to. RE is
1629 the subdirectory entry. TYPE and NAME are pointers to higher level
1630 IDs, or NULL. LANGUAGE is a pointer to the current language.
1631 LEVEL is the level in the tree. */
1634 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1636 const struct res_entry
*re
;
1637 const struct res_id
*type
;
1638 const struct res_id
*name
;
1646 fprintf (e
, "// Type: ");
1648 res_id_print (e
, re
->id
, 1);
1653 switch (re
->id
.u
.id
)
1655 case RT_CURSOR
: s
= "cursor"; break;
1656 case RT_BITMAP
: s
= "bitmap"; break;
1657 case RT_ICON
: s
= "icon"; break;
1658 case RT_MENU
: s
= "menu"; break;
1659 case RT_DIALOG
: s
= "dialog"; break;
1660 case RT_STRING
: s
= "stringtable"; break;
1661 case RT_FONTDIR
: s
= "fontdir"; break;
1662 case RT_FONT
: s
= "font"; break;
1663 case RT_ACCELERATOR
: s
= "accelerators"; break;
1664 case RT_RCDATA
: s
= "rcdata"; break;
1665 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1666 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1667 case RT_GROUP_ICON
: s
= "group icon"; break;
1668 case RT_VERSION
: s
= "version"; break;
1669 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1670 case RT_PLUGPLAY
: s
= "plugplay"; break;
1671 case RT_VXD
: s
= "vxd"; break;
1672 case RT_ANICURSOR
: s
= "anicursor"; break;
1673 case RT_ANIICON
: s
= "aniicon"; break;
1674 default: s
= NULL
; break;
1678 fprintf (e
, "%s", s
);
1680 res_id_print (e
, re
->id
, 1);
1686 fprintf (e
, "// Name: ");
1687 res_id_print (e
, re
->id
, 1);
1692 fprintf (e
, "// Language: ");
1693 res_id_print (e
, re
->id
, 1);
1698 fprintf (e
, "// Level %d: ", level
);
1699 res_id_print (e
, re
->id
, 1);
1703 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1706 /* Write out a single resource. E is the file to write to. TYPE is a
1707 pointer to the type of the resource. NAME is a pointer to the name
1708 of the resource; it will be NULL if there is a level mismatch. RES
1709 is the resource data. LANGUAGE is a pointer to the current
1713 write_rc_resource (e
, type
, name
, res
, language
)
1715 const struct res_id
*type
;
1716 const struct res_id
*name
;
1717 const struct res_resource
*res
;
1731 case RES_TYPE_ACCELERATOR
:
1733 rt
= RT_ACCELERATOR
;
1736 case RES_TYPE_BITMAP
:
1741 case RES_TYPE_CURSOR
:
1746 case RES_TYPE_GROUP_CURSOR
:
1748 rt
= RT_GROUP_CURSOR
;
1751 case RES_TYPE_DIALOG
:
1752 if (extended_dialog (res
->u
.dialog
))
1764 case RES_TYPE_FONTDIR
:
1774 case RES_TYPE_GROUP_ICON
:
1780 if (extended_menu (res
->u
.menu
))
1793 case RES_TYPE_MESSAGETABLE
:
1795 rt
= RT_MESSAGETABLE
;
1798 case RES_TYPE_RCDATA
:
1803 case RES_TYPE_STRINGTABLE
:
1808 case RES_TYPE_USERDATA
:
1813 case RES_TYPE_VERSIONINFO
:
1821 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1823 fprintf (e
, "// Unexpected resource type mismatch: ");
1824 res_id_print (e
, *type
, 1);
1825 fprintf (e
, " != %d", rt
);
1828 if (res
->coff_info
.codepage
!= 0)
1829 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1830 if (res
->coff_info
.reserved
!= 0)
1831 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1834 res_id_print (e
, *name
, 0);
1836 fprintf (e
, "??Unknown-Name??");
1840 fprintf (e
, "%s", s
);
1841 else if (type
!= NULL
)
1842 res_id_print (e
, *type
, 0);
1844 fprintf (e
, "??Unknown-Type??");
1846 if (res
->res_info
.memflags
!= 0)
1848 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1849 fprintf (e
, " MOVEABLE");
1850 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1851 fprintf (e
, " PURE");
1852 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1853 fprintf (e
, " PRELOAD");
1854 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1855 fprintf (e
, " DISCARDABLE");
1858 if (res
->type
== RES_TYPE_DIALOG
)
1860 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1861 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1862 if (res
->u
.dialog
->ex
!= NULL
1863 && res
->u
.dialog
->ex
->help
!= 0)
1864 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1869 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1870 || res
->res_info
.characteristics
!= 0
1871 || res
->res_info
.version
!= 0)
1877 case RES_TYPE_ACCELERATOR
:
1878 case RES_TYPE_DIALOG
:
1880 case RES_TYPE_RCDATA
:
1881 case RES_TYPE_STRINGTABLE
:
1890 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1891 fprintf (e
, "%sLANGUAGE %d, %d\n",
1892 modifiers
? "// " : "",
1893 res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
1894 (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
1895 if (res
->res_info
.characteristics
!= 0)
1896 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1897 modifiers
? "// " : "",
1898 res
->res_info
.characteristics
);
1899 if (res
->res_info
.version
!= 0)
1900 fprintf (e
, "%sVERSION %lu\n",
1901 modifiers
? "// " : "",
1902 res
->res_info
.version
);
1910 case RES_TYPE_ACCELERATOR
:
1911 write_rc_accelerators (e
, res
->u
.acc
);
1914 case RES_TYPE_CURSOR
:
1915 write_rc_cursor (e
, res
->u
.cursor
);
1918 case RES_TYPE_GROUP_CURSOR
:
1919 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1922 case RES_TYPE_DIALOG
:
1923 write_rc_dialog (e
, res
->u
.dialog
);
1926 case RES_TYPE_FONTDIR
:
1927 write_rc_fontdir (e
, res
->u
.fontdir
);
1930 case RES_TYPE_GROUP_ICON
:
1931 write_rc_group_icon (e
, res
->u
.group_icon
);
1935 write_rc_menu (e
, res
->u
.menu
, menuex
);
1938 case RES_TYPE_RCDATA
:
1939 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1942 case RES_TYPE_STRINGTABLE
:
1943 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1946 case RES_TYPE_USERDATA
:
1947 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1950 case RES_TYPE_VERSIONINFO
:
1951 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1954 case RES_TYPE_BITMAP
:
1957 case RES_TYPE_MESSAGETABLE
:
1958 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1963 /* Write out accelerator information. */
1966 write_rc_accelerators (e
, accelerators
)
1968 const struct accelerator
*accelerators
;
1970 const struct accelerator
*acc
;
1972 fprintf (e
, "BEGIN\n");
1973 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1979 if ((acc
->key
& 0x7f) == acc
->key
1980 && ISPRINT (acc
->key
)
1981 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1983 fprintf (e
, "\"%c\"", acc
->key
);
1988 fprintf (e
, "%d", acc
->key
);
1992 fprintf (e
, ", %d", acc
->id
);
1996 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1997 fprintf (e
, ", VIRTKEY");
1999 fprintf (e
, ", ASCII");
2002 if ((acc
->flags
& ACC_SHIFT
) != 0)
2003 fprintf (e
, ", SHIFT");
2004 if ((acc
->flags
& ACC_CONTROL
) != 0)
2005 fprintf (e
, ", CONTROL");
2006 if ((acc
->flags
& ACC_ALT
) != 0)
2007 fprintf (e
, ", ALT");
2012 fprintf (e
, "END\n");
2015 /* Write out cursor information. This would normally be in a separate
2016 file, which the rc file would include. */
2019 write_rc_cursor (e
, cursor
)
2021 const struct cursor
*cursor
;
2023 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
2025 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
2028 /* Write out group cursor data. This would normally be built from the
2032 write_rc_group_cursor (e
, group_cursor
)
2034 const struct group_cursor
*group_cursor
;
2036 const struct group_cursor
*gc
;
2038 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
2040 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
2041 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
2042 fprintf (e
, "// data bytes: %lu; index: %d\n",
2043 gc
->bytes
, gc
->index
);
2047 /* Write dialog data. */
2050 write_rc_dialog (e
, dialog
)
2052 const struct dialog
*dialog
;
2054 const struct dialog_control
*control
;
2056 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
2058 if (dialog
->exstyle
!= 0)
2059 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
2061 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2062 || dialog
->class.u
.id
!= 0)
2064 fprintf (e
, "CLASS ");
2065 res_id_print (e
, dialog
->class, 1);
2069 if (dialog
->caption
!= NULL
)
2071 fprintf (e
, "CAPTION \"");
2072 unicode_print (e
, dialog
->caption
, -1);
2073 fprintf (e
, "\"\n");
2076 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2077 || dialog
->menu
.u
.id
!= 0)
2079 fprintf (e
, "MENU ");
2080 res_id_print (e
, dialog
->menu
, 0);
2084 if (dialog
->font
!= NULL
)
2086 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
2087 unicode_print (e
, dialog
->font
, -1);
2089 if (dialog
->ex
!= NULL
2090 && (dialog
->ex
->weight
!= 0
2091 || dialog
->ex
->italic
!= 0
2092 || dialog
->ex
->charset
!= 1))
2093 fprintf (e
, ", %d, %d, %d",
2094 dialog
->ex
->weight
, dialog
->ex
->italic
, dialog
->ex
->charset
);
2098 fprintf (e
, "BEGIN\n");
2100 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2101 write_rc_dialog_control (e
, control
);
2103 fprintf (e
, "END\n");
2106 /* For each predefined control keyword, this table provides the class
2112 unsigned short class;
2113 unsigned long style
;
2116 static const struct control_info control_info
[] =
2118 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2119 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2120 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2121 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2122 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2123 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2124 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2125 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2126 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2127 { "ICON", CTL_STATIC
, SS_ICON
},
2128 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2129 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2130 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2131 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2132 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2133 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2134 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2135 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2136 /* It's important that USERBUTTON come after all the other button
2137 types, so that it won't be matched too early. */
2138 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2142 /* Write a dialog control. */
2145 write_rc_dialog_control (e
, control
)
2147 const struct dialog_control
*control
;
2149 const struct control_info
*ci
;
2153 if (control
->class.named
)
2157 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2158 if (ci
->class == control
->class.u
.id
2159 && (ci
->style
== (unsigned long) -1
2160 || ci
->style
== (control
->style
& 0xff)))
2164 fprintf (e
, "CONTROL");
2165 else if (ci
->name
!= NULL
)
2166 fprintf (e
, "%s", ci
->name
);
2168 fprintf (e
, "CONTROL");
2170 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2173 res_id_print (e
, control
->text
, 1);
2177 fprintf (e
, " %d, ", control
->id
);
2181 if (control
->class.named
)
2183 res_id_print (e
, control
->class, 0);
2184 if (control
->class.named
)
2186 fprintf (e
, ", 0x%lx, ", control
->style
);
2189 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2191 if (control
->style
!= SS_ICON
2192 || control
->exstyle
!= 0
2193 || control
->width
!= 0
2194 || control
->height
!= 0
2195 || control
->help
!= 0)
2197 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2199 /* FIXME: We don't need to print the style if it is the default.
2200 More importantly, in certain cases we actually need to turn
2201 off parts of the forced style, by using NOT. */
2202 fprintf (e
, ", 0x%lx", control
->style
);
2204 if (control
->exstyle
!= 0 || control
->help
!= 0)
2205 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2210 if (control
->data
!= NULL
)
2211 write_rc_rcdata (e
, control
->data
, 2);
2214 /* Write out font directory data. This would normally be built from
2218 write_rc_fontdir (e
, fontdir
)
2220 const struct fontdir
*fontdir
;
2222 const struct fontdir
*fc
;
2224 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2226 fprintf (e
, "// Font index: %d\n", fc
->index
);
2227 write_rc_filedata (e
, fc
->length
, fc
->data
);
2231 /* Write out group icon data. This would normally be built from the
2235 write_rc_group_icon (e
, group_icon
)
2237 const struct group_icon
*group_icon
;
2239 const struct group_icon
*gi
;
2241 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2243 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2244 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2245 fprintf (e
, "// data bytes: %lu; index: %d\n",
2246 gi
->bytes
, gi
->index
);
2250 /* Write out a menu resource. */
2253 write_rc_menu (e
, menu
, menuex
)
2255 const struct menu
*menu
;
2258 if (menu
->help
!= 0)
2259 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2260 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2263 /* Write out menuitems. */
2266 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
2268 const struct menuitem
*menuitems
;
2272 const struct menuitem
*mi
;
2275 fprintf (e
, "BEGIN\n");
2277 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2279 indent (e
, ind
+ 2);
2281 if (mi
->popup
== NULL
)
2282 fprintf (e
, "MENUITEM");
2284 fprintf (e
, "POPUP");
2287 && mi
->popup
== NULL
2292 fprintf (e
, " SEPARATOR\n");
2296 if (mi
->text
== NULL
)
2297 fprintf (e
, " \"\"");
2301 unicode_print (e
, mi
->text
, -1);
2307 if (mi
->popup
== NULL
)
2308 fprintf (e
, ", %d", mi
->id
);
2310 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2311 fprintf (e
, ", CHECKED");
2312 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2313 fprintf (e
, ", GRAYED");
2314 if ((mi
->type
& MENUITEM_HELP
) != 0)
2315 fprintf (e
, ", HELP");
2316 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2317 fprintf (e
, ", INACTIVE");
2318 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2319 fprintf (e
, ", MENUBARBREAK");
2320 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2321 fprintf (e
, ", MENUBREAK");
2325 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2327 fprintf (e
, ", %d", mi
->id
);
2328 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2330 fprintf (e
, ", %lu", mi
->type
);
2331 if (mi
->state
!= 0 || mi
->help
!= 0)
2333 fprintf (e
, ", %lu", mi
->state
);
2335 fprintf (e
, ", %lu", mi
->help
);
2343 if (mi
->popup
!= NULL
)
2344 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2348 fprintf (e
, "END\n");
2351 /* Write out an rcdata resource. This is also used for other types of
2352 resources that need to print arbitrary data. */
2355 write_rc_rcdata (e
, rcdata
, ind
)
2357 const struct rcdata_item
*rcdata
;
2360 const struct rcdata_item
*ri
;
2363 fprintf (e
, "BEGIN\n");
2365 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2367 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2370 indent (e
, ind
+ 2);
2378 fprintf (e
, "%d", ri
->u
.word
);
2382 fprintf (e
, "%luL", ri
->u
.dword
);
2392 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2397 fprintf (e
, "\\%03o", *s
);
2403 case RCDATA_WSTRING
:
2405 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2414 /* Assume little endian data. */
2417 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2423 indent (e
, ind
+ 2);
2424 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2425 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2426 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2427 | ri
->u
.buffer
.data
[i
]);
2428 fprintf (e
, "%luL", l
);
2429 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2431 for (j
= 0; j
< 4; ++j
)
2432 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2433 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2437 fprintf (e
, "\t// ");
2438 for (j
= 0; j
< 4; ++j
)
2440 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2441 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2444 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2446 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2454 if (i
+ 1 < ri
->u
.buffer
.length
)
2460 indent (e
, ind
+ 2);
2461 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2462 fprintf (e
, "%d", s
);
2463 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2465 for (j
= 0; j
< 2; ++j
)
2466 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2467 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2471 fprintf (e
, "\t// ");
2472 for (j
= 0; j
< 2; ++j
)
2474 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2475 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2478 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2480 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2489 if (i
< ri
->u
.buffer
.length
)
2492 indent (e
, ind
+ 2);
2493 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2494 && ISPRINT (ri
->u
.buffer
.data
[i
]))
2495 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2497 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2498 if (ri
->next
!= NULL
)
2508 if (ri
->type
!= RCDATA_BUFFER
)
2510 if (ri
->next
!= NULL
)
2517 fprintf (e
, "END\n");
2520 /* Write out a stringtable resource. */
2523 write_rc_stringtable (e
, name
, stringtable
)
2525 const struct res_id
*name
;
2526 const struct stringtable
*stringtable
;
2528 unsigned long offset
;
2531 if (name
!= NULL
&& ! name
->named
)
2532 offset
= (name
->u
.id
- 1) << 4;
2535 fprintf (e
, "// %s string table name\n",
2536 name
== NULL
? "Missing" : "Invalid");
2540 fprintf (e
, "BEGIN\n");
2542 for (i
= 0; i
< 16; i
++)
2544 if (stringtable
->strings
[i
].length
!= 0)
2546 fprintf (e
, " %lu, \"", offset
+ i
);
2547 unicode_print (e
, stringtable
->strings
[i
].string
,
2548 stringtable
->strings
[i
].length
);
2549 fprintf (e
, "\"\n");
2553 fprintf (e
, "END\n");
2556 /* Write out a versioninfo resource. */
2559 write_rc_versioninfo (e
, versioninfo
)
2561 const struct versioninfo
*versioninfo
;
2563 const struct fixed_versioninfo
*f
;
2564 const struct ver_info
*vi
;
2566 f
= versioninfo
->fixed
;
2567 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2568 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2569 (f
->file_version_ms
>> 16) & 0xffff,
2570 f
->file_version_ms
& 0xffff,
2571 (f
->file_version_ls
>> 16) & 0xffff,
2572 f
->file_version_ls
& 0xffff);
2573 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2574 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2575 (f
->product_version_ms
>> 16) & 0xffff,
2576 f
->product_version_ms
& 0xffff,
2577 (f
->product_version_ls
>> 16) & 0xffff,
2578 f
->product_version_ls
& 0xffff);
2579 if (f
->file_flags_mask
!= 0)
2580 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2581 if (f
->file_flags
!= 0)
2582 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2583 if (f
->file_os
!= 0)
2584 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2585 if (f
->file_type
!= 0)
2586 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2587 if (f
->file_subtype
!= 0)
2588 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2589 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2590 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2592 fprintf (e
, "BEGIN\n");
2594 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2598 case VERINFO_STRING
:
2600 const struct ver_stringinfo
*vs
;
2602 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2603 fprintf (e
, " BEGIN\n");
2604 fprintf (e
, " BLOCK \"");
2605 unicode_print (e
, vi
->u
.string
.language
, -1);
2606 fprintf (e
, "\"\n");
2607 fprintf (e
, " BEGIN\n");
2609 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2611 fprintf (e
, " VALUE \"");
2612 unicode_print (e
, vs
->key
, -1);
2613 fprintf (e
, "\", \"");
2614 unicode_print (e
, vs
->value
, -1);
2615 fprintf (e
, "\"\n");
2618 fprintf (e
, " END\n");
2619 fprintf (e
, " END\n");
2625 const struct ver_varinfo
*vv
;
2627 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2628 fprintf (e
, " BEGIN\n");
2629 fprintf (e
, " VALUE \"");
2630 unicode_print (e
, vi
->u
.var
.key
, -1);
2633 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2634 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2637 fprintf (e
, "\n END\n");
2644 fprintf (e
, "END\n");
2647 /* Write out data which would normally be read from a file. */
2650 write_rc_filedata (e
, length
, data
)
2652 unsigned long length
;
2653 const unsigned char *data
;
2657 for (i
= 0; i
+ 15 < length
; i
+= 16)
2659 fprintf (e
, "// %4lx: ", i
);
2660 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2661 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2662 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2663 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2664 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2665 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2670 fprintf (e
, "// %4lx:", i
);
2673 fprintf (e
, " %02x", data
[i
]);