1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 /* This file contains functions that read and write Windows rc files.
23 These are text files that represent resources. */
27 #include "libiberty.h"
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-header -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 (cpp_pipe
!= NULL
)
507 if (istream_type
== ISTREAM_FILE
)
509 if (cpp_pipe
!= NULL
)
512 if (cpp_temp_file
!= NULL
)
514 int errno_save
= errno
;
516 unlink (cpp_temp_file
);
518 free (cpp_temp_file
);
523 if (cpp_pipe
!= NULL
)
527 /* Since this is also run via xatexit, safeguard. */
529 cpp_temp_file
= NULL
;
532 /* Report an error while reading an rc file. */
538 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
541 /* Issue a warning while reading an rc file. */
544 rcparse_warning (msg
)
547 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
550 /* Die if we get an unexpected end of file. */
556 fatal (_("%s: unexpected EOF"), msg
);
559 /* Read a 16 bit word from a file. The data is assumed to be little
572 unexpected_eof (msg
);
573 return ((b2
& 0xff) << 8) | (b1
& 0xff);
576 /* Read a 32 bit word from a file. The data is assumed to be little
591 unexpected_eof (msg
);
592 return (((((((b4
& 0xff) << 8)
598 /* Read data from a file. This is a wrapper to do error checking. */
601 get_data (e
, p
, c
, msg
)
609 got
= fread (p
, 1, c
, e
);
613 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
616 /* Define an accelerator resource. */
619 define_accelerator (id
, resinfo
, data
)
621 const struct res_res_info
*resinfo
;
622 struct accelerator
*data
;
624 struct res_resource
*r
;
626 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
627 resinfo
->language
, 0);
628 r
->type
= RES_TYPE_ACCELERATOR
;
630 r
->res_info
= *resinfo
;
633 /* Define a bitmap resource. Bitmap data is stored in a file. The
634 first 14 bytes of the file are a standard header, which is not
635 included in the resource data. */
637 #define BITMAP_SKIP (14)
640 define_bitmap (id
, resinfo
, filename
)
642 const struct res_res_info
*resinfo
;
643 const char *filename
;
650 struct res_resource
*r
;
652 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
654 if (stat (real_filename
, &s
) < 0)
655 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
658 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
660 for (i
= 0; i
< BITMAP_SKIP
; i
++)
663 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
666 free (real_filename
);
668 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
669 resinfo
->language
, 0);
671 r
->type
= RES_TYPE_BITMAP
;
672 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
673 r
->u
.data
.data
= data
;
674 r
->res_info
= *resinfo
;
677 /* Define a cursor resource. A cursor file may contain a set of
678 bitmaps, each representing the same cursor at various different
679 resolutions. They each get written out with a different ID. The
680 real cursor resource is then a group resource which can be used to
681 select one of the actual cursors. */
684 define_cursor (id
, resinfo
, filename
)
686 const struct res_res_info
*resinfo
;
687 const char *filename
;
692 struct icondir
*icondirs
;
694 struct res_resource
*r
;
695 struct group_cursor
*first
, **pp
;
697 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
699 /* A cursor file is basically an icon file. The start of the file
700 is a three word structure. The first word is ignored. The
701 second word is the type of data. The third word is the number of
704 get_word (e
, real_filename
);
705 type
= get_word (e
, real_filename
);
706 count
= get_word (e
, real_filename
);
708 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
710 /* Read in the icon directory entries. */
712 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
714 for (i
= 0; i
< count
; i
++)
716 icondirs
[i
].width
= getc (e
);
717 icondirs
[i
].height
= getc (e
);
718 icondirs
[i
].colorcount
= getc (e
);
720 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
721 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
722 icondirs
[i
].bytes
= get_long (e
, real_filename
);
723 icondirs
[i
].offset
= get_long (e
, real_filename
);
726 unexpected_eof (real_filename
);
729 /* Define each cursor as a unique resource. */
731 first_cursor
= cursors
;
733 for (i
= 0; i
< count
; i
++)
739 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
740 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
741 icondirs
[i
].offset
, strerror (errno
));
743 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
745 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
747 c
= (struct cursor
*) res_alloc (sizeof *c
);
748 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
749 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
750 c
->length
= icondirs
[i
].bytes
;
758 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
759 resinfo
->language
, 0);
760 r
->type
= RES_TYPE_CURSOR
;
762 r
->res_info
= *resinfo
;
766 free (real_filename
);
768 /* Define a cursor group resource. */
772 for (i
= 0; i
< count
; i
++)
774 struct group_cursor
*cg
;
776 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
778 cg
->width
= icondirs
[i
].width
;
779 cg
->height
= 2 * icondirs
[i
].height
;
781 /* FIXME: What should these be set to? */
785 cg
->bytes
= icondirs
[i
].bytes
+ 4;
786 cg
->index
= first_cursor
+ i
+ 1;
794 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
795 resinfo
->language
, 0);
796 r
->type
= RES_TYPE_GROUP_CURSOR
;
797 r
->u
.group_cursor
= first
;
798 r
->res_info
= *resinfo
;
801 /* Define a dialog resource. */
804 define_dialog (id
, resinfo
, dialog
)
806 const struct res_res_info
*resinfo
;
807 const struct dialog
*dialog
;
810 struct res_resource
*r
;
812 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
815 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
816 resinfo
->language
, 0);
817 r
->type
= RES_TYPE_DIALOG
;
819 r
->res_info
= *resinfo
;
822 /* Define a dialog control. This does not define a resource, but
823 merely allocates and fills in a structure. */
825 struct dialog_control
*
826 define_control (text
, id
, x
, y
, width
, height
, class, style
, exstyle
)
832 unsigned long height
;
835 unsigned long exstyle
;
837 struct dialog_control
*n
;
839 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
843 n
->exstyle
= exstyle
;
849 n
->class.u
.id
= class;
852 res_string_to_id (&n
->text
, text
);
859 struct dialog_control
*
860 define_icon_control (iid
, id
, x
, y
, style
, exstyle
, help
, data
, ex
)
866 unsigned long exstyle
;
868 struct rcdata_item
*data
;
869 struct dialog_ex
*ex
;
871 struct dialog_control
*n
;
873 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
874 n
= define_control (0, id
, x
, y
, 0, 0, CTL_STATIC
, style
, exstyle
);
877 rcparse_warning (_("help ID requires DIALOGEX"));
879 rcparse_warning (_("control data requires DIALOGEX"));
886 /* Define a font resource. */
889 define_font (id
, resinfo
, filename
)
891 const struct res_res_info
*resinfo
;
892 const char *filename
;
898 struct res_resource
*r
;
901 unsigned char *fontdata
;
903 const char *device
, *face
;
906 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
908 if (stat (real_filename
, &s
) < 0)
909 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
912 data
= (unsigned char *) res_alloc (s
.st_size
);
914 get_data (e
, data
, s
.st_size
, real_filename
);
917 free (real_filename
);
919 r
= define_standard_resource (&resources
, RT_FONT
, id
,
920 resinfo
->language
, 0);
922 r
->type
= RES_TYPE_FONT
;
923 r
->u
.data
.length
= s
.st_size
;
924 r
->u
.data
.data
= data
;
925 r
->res_info
= *resinfo
;
927 /* For each font resource, we must add an entry in the FONTDIR
928 resource. The FONTDIR resource includes some strings in the font
929 file. To find them, we have to do some magic on the data we have
932 offset
= ((((((data
[47] << 8)
936 if (offset
> 0 && offset
< s
.st_size
)
937 device
= (char *) data
+ offset
;
941 offset
= ((((((data
[51] << 8)
945 if (offset
> 0 && offset
< s
.st_size
)
946 face
= (char *) data
+ offset
;
952 fontdatalength
= 58 + strlen (device
) + strlen (face
);
953 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
954 memcpy (fontdata
, data
, 56);
955 strcpy ((char *) fontdata
+ 56, device
);
956 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
958 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
961 fd
->length
= fontdatalength
;
964 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
968 /* For the single fontdirs resource, we always use the resource
969 information of the last font. I don't know what else to do. */
970 fontdirs_resinfo
= *resinfo
;
973 /* Define the fontdirs resource. This is called after the entire rc
974 file has been parsed, if any font resources were seen. */
979 struct res_resource
*r
;
985 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
987 r
->type
= RES_TYPE_FONTDIR
;
988 r
->u
.fontdir
= fontdirs
;
989 r
->res_info
= fontdirs_resinfo
;
992 /* Define an icon resource. An icon file may contain a set of
993 bitmaps, each representing the same icon at various different
994 resolutions. They each get written out with a different ID. The
995 real icon resource is then a group resource which can be used to
996 select one of the actual icon bitmaps. */
999 define_icon (id
, resinfo
, filename
)
1001 const struct res_res_info
*resinfo
;
1002 const char *filename
;
1005 char *real_filename
;
1007 struct icondir
*icondirs
;
1009 struct res_resource
*r
;
1010 struct group_icon
*first
, **pp
;
1012 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
1014 /* The start of an icon file is a three word structure. The first
1015 word is ignored. The second word is the type of data. The third
1016 word is the number of entries. */
1018 get_word (e
, real_filename
);
1019 type
= get_word (e
, real_filename
);
1020 count
= get_word (e
, real_filename
);
1022 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1024 /* Read in the icon directory entries. */
1026 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1028 for (i
= 0; i
< count
; i
++)
1030 icondirs
[i
].width
= getc (e
);
1031 icondirs
[i
].height
= getc (e
);
1032 icondirs
[i
].colorcount
= getc (e
);
1034 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1035 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1036 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1037 icondirs
[i
].offset
= get_long (e
, real_filename
);
1040 unexpected_eof (real_filename
);
1043 /* Define each icon as a unique resource. */
1047 for (i
= 0; i
< count
; i
++)
1049 unsigned char *data
;
1052 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1053 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1054 icondirs
[i
].offset
, strerror (errno
));
1056 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1058 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1065 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1066 resinfo
->language
, 0);
1067 r
->type
= RES_TYPE_ICON
;
1068 r
->u
.data
.length
= icondirs
[i
].bytes
;
1069 r
->u
.data
.data
= data
;
1070 r
->res_info
= *resinfo
;
1074 free (real_filename
);
1076 /* Define an icon group resource. */
1080 for (i
= 0; i
< count
; i
++)
1082 struct group_icon
*cg
;
1084 /* For some reason, at least in some files the planes and bits
1085 are zero. We instead set them from the color. This is
1088 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1090 cg
->width
= icondirs
[i
].width
;
1091 cg
->height
= icondirs
[i
].height
;
1092 cg
->colors
= icondirs
[i
].colorcount
;
1096 while ((1 << cg
->bits
) < cg
->colors
)
1099 cg
->bytes
= icondirs
[i
].bytes
;
1100 cg
->index
= first_icon
+ i
+ 1;
1108 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1109 resinfo
->language
, 0);
1110 r
->type
= RES_TYPE_GROUP_ICON
;
1111 r
->u
.group_icon
= first
;
1112 r
->res_info
= *resinfo
;
1115 /* Define a menu resource. */
1118 define_menu (id
, resinfo
, menuitems
)
1120 const struct res_res_info
*resinfo
;
1121 struct menuitem
*menuitems
;
1124 struct res_resource
*r
;
1126 m
= (struct menu
*) res_alloc (sizeof *m
);
1127 m
->items
= menuitems
;
1130 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1131 r
->type
= RES_TYPE_MENU
;
1133 r
->res_info
= *resinfo
;
1136 /* Define a menu item. This does not define a resource, but merely
1137 allocates and fills in a structure. */
1140 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
1144 unsigned long state
;
1146 struct menuitem
*menuitems
;
1148 struct menuitem
*mi
;
1150 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1158 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1160 mi
->popup
= menuitems
;
1164 /* Define a messagetable resource. */
1167 define_messagetable (id
, resinfo
, filename
)
1169 const struct res_res_info
*resinfo
;
1170 const char *filename
;
1173 char *real_filename
;
1175 unsigned char *data
;
1176 struct res_resource
*r
;
1178 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1181 if (stat (real_filename
, &s
) < 0)
1182 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1185 data
= (unsigned char *) res_alloc (s
.st_size
);
1187 get_data (e
, data
, s
.st_size
, real_filename
);
1190 free (real_filename
);
1192 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1193 resinfo
->language
, 0);
1195 r
->type
= RES_TYPE_MESSAGETABLE
;
1196 r
->u
.data
.length
= s
.st_size
;
1197 r
->u
.data
.data
= data
;
1198 r
->res_info
= *resinfo
;
1201 /* Define an rcdata resource. */
1204 define_rcdata (id
, resinfo
, data
)
1206 const struct res_res_info
*resinfo
;
1207 struct rcdata_item
*data
;
1209 struct res_resource
*r
;
1211 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1212 resinfo
->language
, 0);
1213 r
->type
= RES_TYPE_RCDATA
;
1215 r
->res_info
= *resinfo
;
1218 /* Create an rcdata item holding a string. */
1220 struct rcdata_item
*
1221 define_rcdata_string (string
, len
)
1225 struct rcdata_item
*ri
;
1228 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1230 ri
->type
= RCDATA_STRING
;
1231 ri
->u
.string
.length
= len
;
1232 s
= (char *) res_alloc (len
);
1233 memcpy (s
, string
, len
);
1239 /* Create an rcdata item holding a number. */
1241 struct rcdata_item
*
1242 define_rcdata_number (val
, dword
)
1246 struct rcdata_item
*ri
;
1248 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1250 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1256 /* Define a stringtable resource. This is called for each string
1257 which appears in a STRINGTABLE statement. */
1260 define_stringtable (resinfo
, stringid
, string
)
1261 const struct res_res_info
*resinfo
;
1262 unsigned long stringid
;
1266 struct res_resource
*r
;
1269 id
.u
.id
= (stringid
>> 4) + 1;
1270 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1271 resinfo
->language
, 1);
1273 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1277 r
->type
= RES_TYPE_STRINGTABLE
;
1278 r
->u
.stringtable
= ((struct stringtable
*)
1279 res_alloc (sizeof (struct stringtable
)));
1280 for (i
= 0; i
< 16; i
++)
1282 r
->u
.stringtable
->strings
[i
].length
= 0;
1283 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1286 r
->res_info
= *resinfo
;
1289 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1290 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1294 /* Define a user data resource where the data is in the rc file. */
1297 define_user_data (id
, type
, resinfo
, data
)
1300 const struct res_res_info
*resinfo
;
1301 struct rcdata_item
*data
;
1303 struct res_id ids
[3];
1304 struct res_resource
*r
;
1309 ids
[2].u
.id
= resinfo
->language
;
1311 r
= define_resource (&resources
, 3, ids
, 0);
1312 r
->type
= RES_TYPE_USERDATA
;
1313 r
->u
.userdata
= data
;
1314 r
->res_info
= *resinfo
;
1317 /* Define a user data resource where the data is in a file. */
1320 define_user_file (id
, type
, resinfo
, filename
)
1323 const struct res_res_info
*resinfo
;
1324 const char *filename
;
1327 char *real_filename
;
1329 unsigned char *data
;
1330 struct res_id ids
[3];
1331 struct res_resource
*r
;
1333 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1335 if (stat (real_filename
, &s
) < 0)
1336 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1339 data
= (unsigned char *) res_alloc (s
.st_size
);
1341 get_data (e
, data
, s
.st_size
, real_filename
);
1344 free (real_filename
);
1349 ids
[2].u
.id
= resinfo
->language
;
1351 r
= define_resource (&resources
, 3, ids
, 0);
1352 r
->type
= RES_TYPE_USERDATA
;
1353 r
->u
.userdata
= ((struct rcdata_item
*)
1354 res_alloc (sizeof (struct rcdata_item
)));
1355 r
->u
.userdata
->next
= NULL
;
1356 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1357 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1358 r
->u
.userdata
->u
.buffer
.data
= data
;
1359 r
->res_info
= *resinfo
;
1362 /* Define a versioninfo resource. */
1365 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1368 struct fixed_versioninfo
*fixedverinfo
;
1369 struct ver_info
*verinfo
;
1371 struct res_resource
*r
;
1373 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1374 r
->type
= RES_TYPE_VERSIONINFO
;
1375 r
->u
.versioninfo
= ((struct versioninfo
*)
1376 res_alloc (sizeof (struct versioninfo
)));
1377 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1378 r
->u
.versioninfo
->var
= verinfo
;
1379 r
->res_info
.language
= language
;
1382 /* Add string version info to a list of version information. */
1385 append_ver_stringfileinfo (verinfo
, language
, strings
)
1386 struct ver_info
*verinfo
;
1387 const char *language
;
1388 struct ver_stringinfo
*strings
;
1390 struct ver_info
*vi
, **pp
;
1392 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1394 vi
->type
= VERINFO_STRING
;
1395 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1396 vi
->u
.string
.strings
= strings
;
1398 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1405 /* Add variable version info to a list of version information. */
1408 append_ver_varfileinfo (verinfo
, key
, var
)
1409 struct ver_info
*verinfo
;
1411 struct ver_varinfo
*var
;
1413 struct ver_info
*vi
, **pp
;
1415 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1417 vi
->type
= VERINFO_VAR
;
1418 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1419 vi
->u
.var
.var
= var
;
1421 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1428 /* Append version string information to a list. */
1430 struct ver_stringinfo
*
1431 append_verval (strings
, key
, value
)
1432 struct ver_stringinfo
*strings
;
1436 struct ver_stringinfo
*vs
, **pp
;
1438 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1440 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1441 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1443 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1450 /* Append version variable information to a list. */
1452 struct ver_varinfo
*
1453 append_vertrans (var
, language
, charset
)
1454 struct ver_varinfo
*var
;
1455 unsigned long language
;
1456 unsigned long charset
;
1458 struct ver_varinfo
*vv
, **pp
;
1460 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1462 vv
->language
= language
;
1463 vv
->charset
= charset
;
1465 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1472 /* Local functions used to write out an rc file. */
1474 static void indent
PARAMS ((FILE *, int));
1475 static void write_rc_directory
1476 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1477 const struct res_id
*, int *, int));
1478 static void write_rc_subdir
1479 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1480 const struct res_id
*, int *, int));
1481 static void write_rc_resource
1482 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1483 const struct res_resource
*, int *));
1484 static void write_rc_accelerators
1485 PARAMS ((FILE *, const struct accelerator
*));
1486 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1487 static void write_rc_group_cursor
1488 PARAMS ((FILE *, const struct group_cursor
*));
1489 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1490 static void write_rc_dialog_control
1491 PARAMS ((FILE *, const struct dialog_control
*));
1492 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1493 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1494 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1495 static void write_rc_menuitems
1496 PARAMS ((FILE *, const struct menuitem
*, int, int));
1497 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1498 static void write_rc_stringtable
1499 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1500 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1501 static void write_rc_filedata
1502 PARAMS ((FILE *, unsigned long, const unsigned char *));
1504 /* Indent a given number of spaces. */
1513 for (i
= 0; i
< c
; i
++)
1517 /* Dump the resources we have read in the format of an rc file.
1519 Actually, we don't use the format of an rc file, because it's way
1520 too much of a pain--for example, we'd have to write icon resources
1521 into a file and refer to that file. We just generate a readable
1522 format that kind of looks like an rc file, and is useful for
1523 understanding the contents of a resource file. Someday we may want
1524 to generate an rc file which the rc compiler can read; if that day
1525 comes, this code will have to be fixed up. */
1528 write_rc_file (filename
, resources
)
1529 const char *filename
;
1530 const struct res_directory
*resources
;
1535 if (filename
== NULL
)
1539 e
= fopen (filename
, FOPEN_WT
);
1541 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1545 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1546 (const struct res_id
*) NULL
, &language
, 1);
1549 /* Write out a directory. E is the file to write to. RD is the
1550 directory. TYPE is a pointer to the level 1 ID which serves as the
1551 resource type. NAME is a pointer to the level 2 ID which serves as
1552 an individual resource name. LANGUAGE is a pointer to the current
1553 language. LEVEL is the level in the tree. */
1556 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1558 const struct res_directory
*rd
;
1559 const struct res_id
*type
;
1560 const struct res_id
*name
;
1564 const struct res_entry
*re
;
1566 /* Print out some COFF information that rc files can't represent. */
1569 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1570 if (rd
->characteristics
!= 0)
1571 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1572 if (rd
->major
!= 0 || rd
->minor
!= 0)
1573 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1575 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1580 /* If we're at level 1, the key of this resource is the
1581 type. This normally duplicates the information we have
1582 stored with the resource itself, but we need to remember
1583 the type if this is a user define resource type. */
1588 /* If we're at level 2, the key of this resource is the name
1589 we are going to use in the rc printout. */
1594 /* If we're at level 3, then this key represents a language.
1595 Use it to update the current language. */
1597 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1598 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1600 fprintf (e
, "LANGUAGE %lu, %lu\n",
1601 re
->id
.u
.id
& 0xff, (re
->id
.u
.id
>> 8) & 0xff);
1602 *language
= re
->id
.u
.id
;
1611 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1616 /* This is the normal case: the three levels are
1617 TYPE/NAME/LANGUAGE. NAME will have been set at level
1618 2, and represents the name to use. We probably just
1619 set LANGUAGE, and it will probably match what the
1620 resource itself records if anything. */
1621 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1625 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1626 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1633 /* Write out a subdirectory entry. E is the file to write to. RE is
1634 the subdirectory entry. TYPE and NAME are pointers to higher level
1635 IDs, or NULL. LANGUAGE is a pointer to the current language.
1636 LEVEL is the level in the tree. */
1639 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1641 const struct res_entry
*re
;
1642 const struct res_id
*type
;
1643 const struct res_id
*name
;
1651 fprintf (e
, "// Type: ");
1653 res_id_print (e
, re
->id
, 1);
1658 switch (re
->id
.u
.id
)
1660 case RT_CURSOR
: s
= "cursor"; break;
1661 case RT_BITMAP
: s
= "bitmap"; break;
1662 case RT_ICON
: s
= "icon"; break;
1663 case RT_MENU
: s
= "menu"; break;
1664 case RT_DIALOG
: s
= "dialog"; break;
1665 case RT_STRING
: s
= "stringtable"; break;
1666 case RT_FONTDIR
: s
= "fontdir"; break;
1667 case RT_FONT
: s
= "font"; break;
1668 case RT_ACCELERATOR
: s
= "accelerators"; break;
1669 case RT_RCDATA
: s
= "rcdata"; break;
1670 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1671 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1672 case RT_GROUP_ICON
: s
= "group icon"; break;
1673 case RT_VERSION
: s
= "version"; break;
1674 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1675 case RT_PLUGPLAY
: s
= "plugplay"; break;
1676 case RT_VXD
: s
= "vxd"; break;
1677 case RT_ANICURSOR
: s
= "anicursor"; break;
1678 case RT_ANIICON
: s
= "aniicon"; break;
1679 default: s
= NULL
; break;
1683 fprintf (e
, "%s", s
);
1685 res_id_print (e
, re
->id
, 1);
1691 fprintf (e
, "// Name: ");
1692 res_id_print (e
, re
->id
, 1);
1697 fprintf (e
, "// Language: ");
1698 res_id_print (e
, re
->id
, 1);
1703 fprintf (e
, "// Level %d: ", level
);
1704 res_id_print (e
, re
->id
, 1);
1708 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1711 /* Write out a single resource. E is the file to write to. TYPE is a
1712 pointer to the type of the resource. NAME is a pointer to the name
1713 of the resource; it will be NULL if there is a level mismatch. RES
1714 is the resource data. LANGUAGE is a pointer to the current
1718 write_rc_resource (e
, type
, name
, res
, language
)
1720 const struct res_id
*type
;
1721 const struct res_id
*name
;
1722 const struct res_resource
*res
;
1736 case RES_TYPE_ACCELERATOR
:
1738 rt
= RT_ACCELERATOR
;
1741 case RES_TYPE_BITMAP
:
1746 case RES_TYPE_CURSOR
:
1751 case RES_TYPE_GROUP_CURSOR
:
1753 rt
= RT_GROUP_CURSOR
;
1756 case RES_TYPE_DIALOG
:
1757 if (extended_dialog (res
->u
.dialog
))
1769 case RES_TYPE_FONTDIR
:
1779 case RES_TYPE_GROUP_ICON
:
1785 if (extended_menu (res
->u
.menu
))
1798 case RES_TYPE_MESSAGETABLE
:
1800 rt
= RT_MESSAGETABLE
;
1803 case RES_TYPE_RCDATA
:
1808 case RES_TYPE_STRINGTABLE
:
1813 case RES_TYPE_USERDATA
:
1818 case RES_TYPE_VERSIONINFO
:
1826 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1828 fprintf (e
, "// Unexpected resource type mismatch: ");
1829 res_id_print (e
, *type
, 1);
1830 fprintf (e
, " != %d", rt
);
1833 if (res
->coff_info
.codepage
!= 0)
1834 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1835 if (res
->coff_info
.reserved
!= 0)
1836 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1839 res_id_print (e
, *name
, 0);
1841 fprintf (e
, "??Unknown-Name??");
1845 fprintf (e
, "%s", s
);
1846 else if (type
!= NULL
)
1847 res_id_print (e
, *type
, 0);
1849 fprintf (e
, "??Unknown-Type??");
1851 if (res
->res_info
.memflags
!= 0)
1853 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1854 fprintf (e
, " MOVEABLE");
1855 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1856 fprintf (e
, " PURE");
1857 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1858 fprintf (e
, " PRELOAD");
1859 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1860 fprintf (e
, " DISCARDABLE");
1863 if (res
->type
== RES_TYPE_DIALOG
)
1865 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1866 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1867 if (res
->u
.dialog
->ex
!= NULL
1868 && res
->u
.dialog
->ex
->help
!= 0)
1869 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1874 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1875 || res
->res_info
.characteristics
!= 0
1876 || res
->res_info
.version
!= 0)
1882 case RES_TYPE_ACCELERATOR
:
1883 case RES_TYPE_DIALOG
:
1885 case RES_TYPE_RCDATA
:
1886 case RES_TYPE_STRINGTABLE
:
1895 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1896 fprintf (e
, "%sLANGUAGE %d, %d\n",
1897 modifiers
? "// " : "",
1898 res
->res_info
.language
& 0xff,
1899 (res
->res_info
.language
>> 8) & 0xff);
1900 if (res
->res_info
.characteristics
!= 0)
1901 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1902 modifiers
? "// " : "",
1903 res
->res_info
.characteristics
);
1904 if (res
->res_info
.version
!= 0)
1905 fprintf (e
, "%sVERSION %lu\n",
1906 modifiers
? "// " : "",
1907 res
->res_info
.version
);
1915 case RES_TYPE_ACCELERATOR
:
1916 write_rc_accelerators (e
, res
->u
.acc
);
1919 case RES_TYPE_CURSOR
:
1920 write_rc_cursor (e
, res
->u
.cursor
);
1923 case RES_TYPE_GROUP_CURSOR
:
1924 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1927 case RES_TYPE_DIALOG
:
1928 write_rc_dialog (e
, res
->u
.dialog
);
1931 case RES_TYPE_FONTDIR
:
1932 write_rc_fontdir (e
, res
->u
.fontdir
);
1935 case RES_TYPE_GROUP_ICON
:
1936 write_rc_group_icon (e
, res
->u
.group_icon
);
1940 write_rc_menu (e
, res
->u
.menu
, menuex
);
1943 case RES_TYPE_RCDATA
:
1944 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1947 case RES_TYPE_STRINGTABLE
:
1948 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1951 case RES_TYPE_USERDATA
:
1952 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1955 case RES_TYPE_VERSIONINFO
:
1956 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1959 case RES_TYPE_BITMAP
:
1962 case RES_TYPE_MESSAGETABLE
:
1963 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1968 /* Write out accelerator information. */
1971 write_rc_accelerators (e
, accelerators
)
1973 const struct accelerator
*accelerators
;
1975 const struct accelerator
*acc
;
1977 fprintf (e
, "BEGIN\n");
1978 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1984 if ((acc
->key
& 0x7f) == acc
->key
1985 && isprint ((unsigned char) acc
->key
)
1986 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1988 fprintf (e
, "\"%c\"", acc
->key
);
1993 fprintf (e
, "%d", acc
->key
);
1997 fprintf (e
, ", %d", acc
->id
);
2001 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
2002 fprintf (e
, ", VIRTKEY");
2004 fprintf (e
, ", ASCII");
2007 if ((acc
->flags
& ACC_SHIFT
) != 0)
2008 fprintf (e
, ", SHIFT");
2009 if ((acc
->flags
& ACC_CONTROL
) != 0)
2010 fprintf (e
, ", CONTROL");
2011 if ((acc
->flags
& ACC_ALT
) != 0)
2012 fprintf (e
, ", ALT");
2017 fprintf (e
, "END\n");
2020 /* Write out cursor information. This would normally be in a separate
2021 file, which the rc file would include. */
2024 write_rc_cursor (e
, cursor
)
2026 const struct cursor
*cursor
;
2028 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
2030 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
2033 /* Write out group cursor data. This would normally be built from the
2037 write_rc_group_cursor (e
, group_cursor
)
2039 const struct group_cursor
*group_cursor
;
2041 const struct group_cursor
*gc
;
2043 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
2045 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
2046 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
2047 fprintf (e
, "// data bytes: %lu; index: %d\n",
2048 gc
->bytes
, gc
->index
);
2052 /* Write dialog data. */
2055 write_rc_dialog (e
, dialog
)
2057 const struct dialog
*dialog
;
2059 const struct dialog_control
*control
;
2061 if (dialog
->style
!= 0)
2062 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
2063 if (dialog
->exstyle
!= 0)
2064 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
2065 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2066 || dialog
->class.u
.id
!= 0)
2068 fprintf (e
, "CLASS ");
2069 res_id_print (e
, dialog
->class, 0);
2072 if (dialog
->caption
!= NULL
)
2074 fprintf (e
, "CAPTION \"");
2075 unicode_print (e
, dialog
->caption
, -1);
2076 fprintf (e
, "\"\n");
2078 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2079 || dialog
->menu
.u
.id
!= 0)
2081 fprintf (e
, "MENU ");
2082 res_id_print (e
, dialog
->menu
, 0);
2085 if (dialog
->font
!= NULL
)
2087 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
2088 unicode_print (e
, dialog
->font
, -1);
2090 if (dialog
->ex
!= NULL
2091 && (dialog
->ex
->weight
!= 0 || dialog
->ex
->italic
!= 0))
2092 fprintf (e
, ", %d, %d", dialog
->ex
->weight
, dialog
->ex
->italic
);
2096 fprintf (e
, "BEGIN\n");
2098 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2099 write_rc_dialog_control (e
, control
);
2101 fprintf (e
, "END\n");
2104 /* For each predefined control keyword, this table provides the class
2110 unsigned short class;
2111 unsigned long style
;
2114 static const struct control_info control_info
[] =
2116 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2117 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2118 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2119 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2120 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2121 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2122 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2123 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2124 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2125 { "ICON", CTL_STATIC
, SS_ICON
},
2126 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2127 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2128 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2129 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2130 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2131 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2132 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2133 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2134 /* It's important that USERBUTTON come after all the other button
2135 types, so that it won't be matched too early. */
2136 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2140 /* Write a dialog control. */
2143 write_rc_dialog_control (e
, control
)
2145 const struct dialog_control
*control
;
2147 const struct control_info
*ci
;
2151 if (control
->class.named
)
2155 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2156 if (ci
->class == control
->class.u
.id
2157 && (ci
->style
== (unsigned long) -1
2158 || ci
->style
== (control
->style
& 0xff)))
2162 fprintf (e
, "CONTROL");
2163 else if (ci
->name
!= NULL
)
2164 fprintf (e
, "%s", ci
->name
);
2166 fprintf (e
, "CONTROL");
2168 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2171 res_id_print (e
, control
->text
, 1);
2175 fprintf (e
, " %d, ", control
->id
);
2179 if (control
->class.named
)
2181 res_id_print (e
, control
->class, 0);
2182 if (control
->class.named
)
2184 fprintf (e
, ", 0x%lx, ", control
->style
);
2187 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2189 if (control
->style
!= SS_ICON
2190 || control
->exstyle
!= 0
2191 || control
->width
!= 0
2192 || control
->height
!= 0
2193 || control
->help
!= 0)
2195 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2197 /* FIXME: We don't need to print the style if it is the default.
2198 More importantly, in certain cases we actually need to turn
2199 off parts of the forced style, by using NOT. */
2200 fprintf (e
, ", 0x%lx", control
->style
);
2202 if (control
->exstyle
!= 0 || control
->help
!= 0)
2203 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2208 if (control
->data
!= NULL
)
2209 write_rc_rcdata (e
, control
->data
, 2);
2212 /* Write out font directory data. This would normally be built from
2216 write_rc_fontdir (e
, fontdir
)
2218 const struct fontdir
*fontdir
;
2220 const struct fontdir
*fc
;
2222 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2224 fprintf (e
, "// Font index: %d\n", fc
->index
);
2225 write_rc_filedata (e
, fc
->length
, fc
->data
);
2229 /* Write out group icon data. This would normally be built from the
2233 write_rc_group_icon (e
, group_icon
)
2235 const struct group_icon
*group_icon
;
2237 const struct group_icon
*gi
;
2239 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2241 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2242 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2243 fprintf (e
, "// data bytes: %lu; index: %d\n",
2244 gi
->bytes
, gi
->index
);
2248 /* Write out a menu resource. */
2251 write_rc_menu (e
, menu
, menuex
)
2253 const struct menu
*menu
;
2256 if (menu
->help
!= 0)
2257 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2258 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2261 /* Write out menuitems. */
2264 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
2266 const struct menuitem
*menuitems
;
2270 const struct menuitem
*mi
;
2273 fprintf (e
, "BEGIN\n");
2275 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2277 indent (e
, ind
+ 2);
2279 if (mi
->popup
== NULL
)
2280 fprintf (e
, "MENUITEM");
2282 fprintf (e
, "POPUP");
2285 && mi
->popup
== NULL
2290 fprintf (e
, " SEPARATOR\n");
2294 if (mi
->text
== NULL
)
2295 fprintf (e
, " \"\"");
2299 unicode_print (e
, mi
->text
, -1);
2305 if (mi
->popup
== NULL
)
2306 fprintf (e
, ", %d", mi
->id
);
2308 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2309 fprintf (e
, ", CHECKED");
2310 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2311 fprintf (e
, ", GRAYED");
2312 if ((mi
->type
& MENUITEM_HELP
) != 0)
2313 fprintf (e
, ", HELP");
2314 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2315 fprintf (e
, ", INACTIVE");
2316 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2317 fprintf (e
, ", MENUBARBREAK");
2318 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2319 fprintf (e
, ", MENUBREAK");
2323 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2325 fprintf (e
, ", %d", mi
->id
);
2326 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2328 fprintf (e
, ", %lu", mi
->type
);
2329 if (mi
->state
!= 0 || mi
->help
!= 0)
2331 fprintf (e
, ", %lu", mi
->state
);
2333 fprintf (e
, ", %lu", mi
->help
);
2341 if (mi
->popup
!= NULL
)
2342 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2346 fprintf (e
, "END\n");
2349 /* Write out an rcdata resource. This is also used for other types of
2350 resources that need to print arbitrary data. */
2353 write_rc_rcdata (e
, rcdata
, ind
)
2355 const struct rcdata_item
*rcdata
;
2358 const struct rcdata_item
*ri
;
2361 fprintf (e
, "BEGIN\n");
2363 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2365 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2368 indent (e
, ind
+ 2);
2376 fprintf (e
, "%d", ri
->u
.word
);
2380 fprintf (e
, "%luL", ri
->u
.dword
);
2390 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2392 if (isprint ((unsigned char) *s
))
2395 fprintf (e
, "\\%03o", *s
);
2401 case RCDATA_WSTRING
:
2403 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2412 /* Assume little endian data. */
2415 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2421 indent (e
, ind
+ 2);
2422 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2423 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2424 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2425 | ri
->u
.buffer
.data
[i
]);
2426 fprintf (e
, "%luL", l
);
2427 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2429 for (j
= 0; j
< 4; ++j
)
2430 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2431 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2435 fprintf (e
, "\t// ");
2436 for (j
= 0; j
< 4; ++j
)
2438 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2439 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2442 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2444 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2452 if (i
+ 1 < ri
->u
.buffer
.length
)
2458 indent (e
, ind
+ 2);
2459 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2460 fprintf (e
, "%d", s
);
2461 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2463 for (j
= 0; j
< 2; ++j
)
2464 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2465 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2469 fprintf (e
, "\t// ");
2470 for (j
= 0; j
< 2; ++j
)
2472 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2473 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2476 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2478 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2487 if (i
< ri
->u
.buffer
.length
)
2490 indent (e
, ind
+ 2);
2491 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2492 && isprint (ri
->u
.buffer
.data
[i
]))
2493 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2495 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2496 if (ri
->next
!= NULL
)
2506 if (ri
->type
!= RCDATA_BUFFER
)
2508 if (ri
->next
!= NULL
)
2515 fprintf (e
, "END\n");
2518 /* Write out a stringtable resource. */
2521 write_rc_stringtable (e
, name
, stringtable
)
2523 const struct res_id
*name
;
2524 const struct stringtable
*stringtable
;
2526 unsigned long offset
;
2529 if (name
!= NULL
&& ! name
->named
)
2530 offset
= (name
->u
.id
- 1) << 4;
2533 fprintf (e
, "// %s string table name\n",
2534 name
== NULL
? "Missing" : "Invalid");
2538 fprintf (e
, "BEGIN\n");
2540 for (i
= 0; i
< 16; i
++)
2542 if (stringtable
->strings
[i
].length
!= 0)
2544 fprintf (e
, " %lu, \"", offset
+ i
);
2545 unicode_print (e
, stringtable
->strings
[i
].string
,
2546 stringtable
->strings
[i
].length
);
2547 fprintf (e
, "\"\n");
2551 fprintf (e
, "END\n");
2554 /* Write out a versioninfo resource. */
2557 write_rc_versioninfo (e
, versioninfo
)
2559 const struct versioninfo
*versioninfo
;
2561 const struct fixed_versioninfo
*f
;
2562 const struct ver_info
*vi
;
2564 f
= versioninfo
->fixed
;
2565 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2566 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2567 (f
->file_version_ms
>> 16) & 0xffff,
2568 f
->file_version_ms
& 0xffff,
2569 (f
->file_version_ls
>> 16) & 0xffff,
2570 f
->file_version_ls
& 0xffff);
2571 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2572 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2573 (f
->product_version_ms
>> 16) & 0xffff,
2574 f
->product_version_ms
& 0xffff,
2575 (f
->product_version_ls
>> 16) & 0xffff,
2576 f
->product_version_ls
& 0xffff);
2577 if (f
->file_flags_mask
!= 0)
2578 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2579 if (f
->file_flags
!= 0)
2580 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2581 if (f
->file_os
!= 0)
2582 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2583 if (f
->file_type
!= 0)
2584 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2585 if (f
->file_subtype
!= 0)
2586 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2587 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2588 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2590 fprintf (e
, "BEGIN\n");
2592 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2596 case VERINFO_STRING
:
2598 const struct ver_stringinfo
*vs
;
2600 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2601 fprintf (e
, " BEGIN\n");
2602 fprintf (e
, " BLOCK \"");
2603 unicode_print (e
, vi
->u
.string
.language
, -1);
2604 fprintf (e
, "\"\n");
2605 fprintf (e
, " BEGIN\n");
2607 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2609 fprintf (e
, " VALUE \"");
2610 unicode_print (e
, vs
->key
, -1);
2611 fprintf (e
, "\", \"");
2612 unicode_print (e
, vs
->value
, -1);
2613 fprintf (e
, "\"\n");
2616 fprintf (e
, " END\n");
2617 fprintf (e
, " END\n");
2623 const struct ver_varinfo
*vv
;
2625 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2626 fprintf (e
, " BEGIN\n");
2627 fprintf (e
, " VALUE \"");
2628 unicode_print (e
, vi
->u
.var
.key
, -1);
2631 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2632 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2635 fprintf (e
, "\n END\n");
2642 fprintf (e
, "END\n");
2645 /* Write out data which would normally be read from a file. */
2648 write_rc_filedata (e
, length
, data
)
2650 unsigned long length
;
2651 const unsigned char *data
;
2655 for (i
= 0; i
+ 15 < length
; i
+= 16)
2657 fprintf (e
, "// %4lx: ", i
);
2658 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2659 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2660 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2661 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2662 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2663 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2668 fprintf (e
, "// %4lx:", i
);
2671 fprintf (e
, " %02x", data
[i
]);