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
);
484 rcparse_discard_strings ();
486 close_input_stream ();
488 if (fontdirs
!= NULL
)
497 /* Close the input stream if it is open. */
500 close_input_stream ()
502 if (istream_type
== ISTREAM_FILE
)
504 if (cpp_pipe
!= NULL
)
507 if (cpp_temp_file
!= NULL
)
509 int errno_save
= errno
;
511 unlink (cpp_temp_file
);
513 free (cpp_temp_file
);
518 if (cpp_pipe
!= NULL
)
522 /* Since this is also run via xatexit, safeguard. */
524 cpp_temp_file
= NULL
;
527 /* Report an error while reading an rc file. */
533 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
536 /* Issue a warning while reading an rc file. */
539 rcparse_warning (msg
)
542 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
545 /* Die if we get an unexpected end of file. */
551 fatal (_("%s: unexpected EOF"), msg
);
554 /* Read a 16 bit word from a file. The data is assumed to be little
567 unexpected_eof (msg
);
568 return ((b2
& 0xff) << 8) | (b1
& 0xff);
571 /* Read a 32 bit word from a file. The data is assumed to be little
586 unexpected_eof (msg
);
587 return (((((((b4
& 0xff) << 8)
593 /* Read data from a file. This is a wrapper to do error checking. */
596 get_data (e
, p
, c
, msg
)
604 got
= fread (p
, 1, c
, e
);
608 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
611 /* Define an accelerator resource. */
614 define_accelerator (id
, resinfo
, data
)
616 const struct res_res_info
*resinfo
;
617 struct accelerator
*data
;
619 struct res_resource
*r
;
621 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
622 resinfo
->language
, 0);
623 r
->type
= RES_TYPE_ACCELERATOR
;
625 r
->res_info
= *resinfo
;
628 /* Define a bitmap resource. Bitmap data is stored in a file. The
629 first 14 bytes of the file are a standard header, which is not
630 included in the resource data. */
632 #define BITMAP_SKIP (14)
635 define_bitmap (id
, resinfo
, filename
)
637 const struct res_res_info
*resinfo
;
638 const char *filename
;
645 struct res_resource
*r
;
647 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
649 if (stat (real_filename
, &s
) < 0)
650 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
653 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
655 for (i
= 0; i
< BITMAP_SKIP
; i
++)
658 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
661 free (real_filename
);
663 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
664 resinfo
->language
, 0);
666 r
->type
= RES_TYPE_BITMAP
;
667 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
668 r
->u
.data
.data
= data
;
669 r
->res_info
= *resinfo
;
672 /* Define a cursor resource. A cursor file may contain a set of
673 bitmaps, each representing the same cursor at various different
674 resolutions. They each get written out with a different ID. The
675 real cursor resource is then a group resource which can be used to
676 select one of the actual cursors. */
679 define_cursor (id
, resinfo
, filename
)
681 const struct res_res_info
*resinfo
;
682 const char *filename
;
687 struct icondir
*icondirs
;
689 struct res_resource
*r
;
690 struct group_cursor
*first
, **pp
;
692 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
694 /* A cursor file is basically an icon file. The start of the file
695 is a three word structure. The first word is ignored. The
696 second word is the type of data. The third word is the number of
699 get_word (e
, real_filename
);
700 type
= get_word (e
, real_filename
);
701 count
= get_word (e
, real_filename
);
703 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
705 /* Read in the icon directory entries. */
707 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
709 for (i
= 0; i
< count
; i
++)
711 icondirs
[i
].width
= getc (e
);
712 icondirs
[i
].height
= getc (e
);
713 icondirs
[i
].colorcount
= getc (e
);
715 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
716 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
717 icondirs
[i
].bytes
= get_long (e
, real_filename
);
718 icondirs
[i
].offset
= get_long (e
, real_filename
);
721 unexpected_eof (real_filename
);
724 /* Define each cursor as a unique resource. */
726 first_cursor
= cursors
;
728 for (i
= 0; i
< count
; i
++)
734 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
735 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
736 icondirs
[i
].offset
, strerror (errno
));
738 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
740 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
742 c
= (struct cursor
*) res_alloc (sizeof *c
);
743 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
744 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
745 c
->length
= icondirs
[i
].bytes
;
753 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
754 resinfo
->language
, 0);
755 r
->type
= RES_TYPE_CURSOR
;
757 r
->res_info
= *resinfo
;
761 free (real_filename
);
763 /* Define a cursor group resource. */
767 for (i
= 0; i
< count
; i
++)
769 struct group_cursor
*cg
;
771 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
773 cg
->width
= icondirs
[i
].width
;
774 cg
->height
= 2 * icondirs
[i
].height
;
776 /* FIXME: What should these be set to? */
780 cg
->bytes
= icondirs
[i
].bytes
+ 4;
781 cg
->index
= first_cursor
+ i
+ 1;
789 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
790 resinfo
->language
, 0);
791 r
->type
= RES_TYPE_GROUP_CURSOR
;
792 r
->u
.group_cursor
= first
;
793 r
->res_info
= *resinfo
;
796 /* Define a dialog resource. */
799 define_dialog (id
, resinfo
, dialog
)
801 const struct res_res_info
*resinfo
;
802 const struct dialog
*dialog
;
805 struct res_resource
*r
;
807 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
810 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
811 resinfo
->language
, 0);
812 r
->type
= RES_TYPE_DIALOG
;
814 r
->res_info
= *resinfo
;
817 /* Define a dialog control. This does not define a resource, but
818 merely allocates and fills in a structure. */
820 struct dialog_control
*
821 define_control (text
, id
, x
, y
, width
, height
, class, style
, exstyle
)
827 unsigned long height
;
830 unsigned long exstyle
;
832 struct dialog_control
*n
;
834 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
838 n
->exstyle
= exstyle
;
844 n
->class.u
.id
= class;
847 res_string_to_id (&n
->text
, text
);
854 struct dialog_control
*
855 define_icon_control (iid
, id
, x
, y
, style
, exstyle
, help
, data
, ex
)
861 unsigned long exstyle
;
863 struct rcdata_item
*data
;
864 struct dialog_ex
*ex
;
866 struct dialog_control
*n
;
868 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
869 n
= define_control (0, id
, x
, y
, 0, 0, CTL_STATIC
, style
, exstyle
);
872 rcparse_warning (_("help ID requires DIALOGEX"));
874 rcparse_warning (_("control data requires DIALOGEX"));
881 /* Define a font resource. */
884 define_font (id
, resinfo
, filename
)
886 const struct res_res_info
*resinfo
;
887 const char *filename
;
893 struct res_resource
*r
;
896 unsigned char *fontdata
;
898 const char *device
, *face
;
901 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
903 if (stat (real_filename
, &s
) < 0)
904 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
907 data
= (unsigned char *) res_alloc (s
.st_size
);
909 get_data (e
, data
, s
.st_size
, real_filename
);
912 free (real_filename
);
914 r
= define_standard_resource (&resources
, RT_FONT
, id
,
915 resinfo
->language
, 0);
917 r
->type
= RES_TYPE_FONT
;
918 r
->u
.data
.length
= s
.st_size
;
919 r
->u
.data
.data
= data
;
920 r
->res_info
= *resinfo
;
922 /* For each font resource, we must add an entry in the FONTDIR
923 resource. The FONTDIR resource includes some strings in the font
924 file. To find them, we have to do some magic on the data we have
927 offset
= ((((((data
[47] << 8)
931 if (offset
> 0 && offset
< s
.st_size
)
932 device
= (char *) data
+ offset
;
936 offset
= ((((((data
[51] << 8)
940 if (offset
> 0 && offset
< s
.st_size
)
941 face
= (char *) data
+ offset
;
947 fontdatalength
= 58 + strlen (device
) + strlen (face
);
948 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
949 memcpy (fontdata
, data
, 56);
950 strcpy ((char *) fontdata
+ 56, device
);
951 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
953 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
956 fd
->length
= fontdatalength
;
959 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
963 /* For the single fontdirs resource, we always use the resource
964 information of the last font. I don't know what else to do. */
965 fontdirs_resinfo
= *resinfo
;
968 /* Define the fontdirs resource. This is called after the entire rc
969 file has been parsed, if any font resources were seen. */
974 struct res_resource
*r
;
980 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
982 r
->type
= RES_TYPE_FONTDIR
;
983 r
->u
.fontdir
= fontdirs
;
984 r
->res_info
= fontdirs_resinfo
;
987 /* Define an icon resource. An icon file may contain a set of
988 bitmaps, each representing the same icon at various different
989 resolutions. They each get written out with a different ID. The
990 real icon resource is then a group resource which can be used to
991 select one of the actual icon bitmaps. */
994 define_icon (id
, resinfo
, filename
)
996 const struct res_res_info
*resinfo
;
997 const char *filename
;
1000 char *real_filename
;
1002 struct icondir
*icondirs
;
1004 struct res_resource
*r
;
1005 struct group_icon
*first
, **pp
;
1007 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
1009 /* The start of an icon file is a three word structure. The first
1010 word is ignored. The second word is the type of data. The third
1011 word is the number of entries. */
1013 get_word (e
, real_filename
);
1014 type
= get_word (e
, real_filename
);
1015 count
= get_word (e
, real_filename
);
1017 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1019 /* Read in the icon directory entries. */
1021 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1023 for (i
= 0; i
< count
; i
++)
1025 icondirs
[i
].width
= getc (e
);
1026 icondirs
[i
].height
= getc (e
);
1027 icondirs
[i
].colorcount
= getc (e
);
1029 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1030 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1031 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1032 icondirs
[i
].offset
= get_long (e
, real_filename
);
1035 unexpected_eof (real_filename
);
1038 /* Define each icon as a unique resource. */
1042 for (i
= 0; i
< count
; i
++)
1044 unsigned char *data
;
1047 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1048 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1049 icondirs
[i
].offset
, strerror (errno
));
1051 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1053 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1060 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1061 resinfo
->language
, 0);
1062 r
->type
= RES_TYPE_ICON
;
1063 r
->u
.data
.length
= icondirs
[i
].bytes
;
1064 r
->u
.data
.data
= data
;
1065 r
->res_info
= *resinfo
;
1069 free (real_filename
);
1071 /* Define an icon group resource. */
1075 for (i
= 0; i
< count
; i
++)
1077 struct group_icon
*cg
;
1079 /* For some reason, at least in some files the planes and bits
1080 are zero. We instead set them from the color. This is
1083 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1085 cg
->width
= icondirs
[i
].width
;
1086 cg
->height
= icondirs
[i
].height
;
1087 cg
->colors
= icondirs
[i
].colorcount
;
1091 while ((1 << cg
->bits
) < cg
->colors
)
1094 cg
->bytes
= icondirs
[i
].bytes
;
1095 cg
->index
= first_icon
+ i
+ 1;
1103 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1104 resinfo
->language
, 0);
1105 r
->type
= RES_TYPE_GROUP_ICON
;
1106 r
->u
.group_icon
= first
;
1107 r
->res_info
= *resinfo
;
1110 /* Define a menu resource. */
1113 define_menu (id
, resinfo
, menuitems
)
1115 const struct res_res_info
*resinfo
;
1116 struct menuitem
*menuitems
;
1119 struct res_resource
*r
;
1121 m
= (struct menu
*) res_alloc (sizeof *m
);
1122 m
->items
= menuitems
;
1125 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1126 r
->type
= RES_TYPE_MENU
;
1128 r
->res_info
= *resinfo
;
1131 /* Define a menu item. This does not define a resource, but merely
1132 allocates and fills in a structure. */
1135 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
1139 unsigned long state
;
1141 struct menuitem
*menuitems
;
1143 struct menuitem
*mi
;
1145 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1153 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1155 mi
->popup
= menuitems
;
1159 /* Define a messagetable resource. */
1162 define_messagetable (id
, resinfo
, filename
)
1164 const struct res_res_info
*resinfo
;
1165 const char *filename
;
1168 char *real_filename
;
1170 unsigned char *data
;
1171 struct res_resource
*r
;
1173 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1176 if (stat (real_filename
, &s
) < 0)
1177 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1180 data
= (unsigned char *) res_alloc (s
.st_size
);
1182 get_data (e
, data
, s
.st_size
, real_filename
);
1185 free (real_filename
);
1187 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1188 resinfo
->language
, 0);
1190 r
->type
= RES_TYPE_MESSAGETABLE
;
1191 r
->u
.data
.length
= s
.st_size
;
1192 r
->u
.data
.data
= data
;
1193 r
->res_info
= *resinfo
;
1196 /* Define an rcdata resource. */
1199 define_rcdata (id
, resinfo
, data
)
1201 const struct res_res_info
*resinfo
;
1202 struct rcdata_item
*data
;
1204 struct res_resource
*r
;
1206 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1207 resinfo
->language
, 0);
1208 r
->type
= RES_TYPE_RCDATA
;
1210 r
->res_info
= *resinfo
;
1213 /* Create an rcdata item holding a string. */
1215 struct rcdata_item
*
1216 define_rcdata_string (string
, len
)
1220 struct rcdata_item
*ri
;
1223 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1225 ri
->type
= RCDATA_STRING
;
1226 ri
->u
.string
.length
= len
;
1227 s
= (char *) res_alloc (len
);
1228 memcpy (s
, string
, len
);
1234 /* Create an rcdata item holding a number. */
1236 struct rcdata_item
*
1237 define_rcdata_number (val
, dword
)
1241 struct rcdata_item
*ri
;
1243 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1245 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1251 /* Define a stringtable resource. This is called for each string
1252 which appears in a STRINGTABLE statement. */
1255 define_stringtable (resinfo
, stringid
, string
)
1256 const struct res_res_info
*resinfo
;
1257 unsigned long stringid
;
1261 struct res_resource
*r
;
1264 id
.u
.id
= (stringid
>> 4) + 1;
1265 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1266 resinfo
->language
, 1);
1268 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1272 r
->type
= RES_TYPE_STRINGTABLE
;
1273 r
->u
.stringtable
= ((struct stringtable
*)
1274 res_alloc (sizeof (struct stringtable
)));
1275 for (i
= 0; i
< 16; i
++)
1277 r
->u
.stringtable
->strings
[i
].length
= 0;
1278 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1281 r
->res_info
= *resinfo
;
1284 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1285 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1289 /* Define a user data resource where the data is in the rc file. */
1292 define_user_data (id
, type
, resinfo
, data
)
1295 const struct res_res_info
*resinfo
;
1296 struct rcdata_item
*data
;
1298 struct res_id ids
[3];
1299 struct res_resource
*r
;
1304 ids
[2].u
.id
= resinfo
->language
;
1306 r
= define_resource (&resources
, 3, ids
, 0);
1307 r
->type
= RES_TYPE_USERDATA
;
1308 r
->u
.userdata
= data
;
1309 r
->res_info
= *resinfo
;
1312 /* Define a user data resource where the data is in a file. */
1315 define_user_file (id
, type
, resinfo
, filename
)
1318 const struct res_res_info
*resinfo
;
1319 const char *filename
;
1322 char *real_filename
;
1324 unsigned char *data
;
1325 struct res_id ids
[3];
1326 struct res_resource
*r
;
1328 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1330 if (stat (real_filename
, &s
) < 0)
1331 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1334 data
= (unsigned char *) res_alloc (s
.st_size
);
1336 get_data (e
, data
, s
.st_size
, real_filename
);
1339 free (real_filename
);
1344 ids
[2].u
.id
= resinfo
->language
;
1346 r
= define_resource (&resources
, 3, ids
, 0);
1347 r
->type
= RES_TYPE_USERDATA
;
1348 r
->u
.userdata
= ((struct rcdata_item
*)
1349 res_alloc (sizeof (struct rcdata_item
)));
1350 r
->u
.userdata
->next
= NULL
;
1351 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1352 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1353 r
->u
.userdata
->u
.buffer
.data
= data
;
1354 r
->res_info
= *resinfo
;
1357 /* Define a versioninfo resource. */
1360 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1363 struct fixed_versioninfo
*fixedverinfo
;
1364 struct ver_info
*verinfo
;
1366 struct res_resource
*r
;
1368 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1369 r
->type
= RES_TYPE_VERSIONINFO
;
1370 r
->u
.versioninfo
= ((struct versioninfo
*)
1371 res_alloc (sizeof (struct versioninfo
)));
1372 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1373 r
->u
.versioninfo
->var
= verinfo
;
1374 r
->res_info
.language
= language
;
1377 /* Add string version info to a list of version information. */
1380 append_ver_stringfileinfo (verinfo
, language
, strings
)
1381 struct ver_info
*verinfo
;
1382 const char *language
;
1383 struct ver_stringinfo
*strings
;
1385 struct ver_info
*vi
, **pp
;
1387 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1389 vi
->type
= VERINFO_STRING
;
1390 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1391 vi
->u
.string
.strings
= strings
;
1393 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1400 /* Add variable version info to a list of version information. */
1403 append_ver_varfileinfo (verinfo
, key
, var
)
1404 struct ver_info
*verinfo
;
1406 struct ver_varinfo
*var
;
1408 struct ver_info
*vi
, **pp
;
1410 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1412 vi
->type
= VERINFO_VAR
;
1413 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1414 vi
->u
.var
.var
= var
;
1416 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1423 /* Append version string information to a list. */
1425 struct ver_stringinfo
*
1426 append_verval (strings
, key
, value
)
1427 struct ver_stringinfo
*strings
;
1431 struct ver_stringinfo
*vs
, **pp
;
1433 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1435 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1436 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1438 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1445 /* Append version variable information to a list. */
1447 struct ver_varinfo
*
1448 append_vertrans (var
, language
, charset
)
1449 struct ver_varinfo
*var
;
1450 unsigned long language
;
1451 unsigned long charset
;
1453 struct ver_varinfo
*vv
, **pp
;
1455 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1457 vv
->language
= language
;
1458 vv
->charset
= charset
;
1460 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1467 /* Local functions used to write out an rc file. */
1469 static void indent
PARAMS ((FILE *, int));
1470 static void write_rc_directory
1471 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1472 const struct res_id
*, int *, int));
1473 static void write_rc_subdir
1474 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1475 const struct res_id
*, int *, int));
1476 static void write_rc_resource
1477 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1478 const struct res_resource
*, int *));
1479 static void write_rc_accelerators
1480 PARAMS ((FILE *, const struct accelerator
*));
1481 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1482 static void write_rc_group_cursor
1483 PARAMS ((FILE *, const struct group_cursor
*));
1484 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1485 static void write_rc_dialog_control
1486 PARAMS ((FILE *, const struct dialog_control
*));
1487 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1488 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1489 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1490 static void write_rc_menuitems
1491 PARAMS ((FILE *, const struct menuitem
*, int, int));
1492 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1493 static void write_rc_stringtable
1494 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1495 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1496 static void write_rc_filedata
1497 PARAMS ((FILE *, unsigned long, const unsigned char *));
1499 /* Indent a given number of spaces. */
1508 for (i
= 0; i
< c
; i
++)
1512 /* Dump the resources we have read in the format of an rc file.
1514 Actually, we don't use the format of an rc file, because it's way
1515 too much of a pain--for example, we'd have to write icon resources
1516 into a file and refer to that file. We just generate a readable
1517 format that kind of looks like an rc file, and is useful for
1518 understanding the contents of a resource file. Someday we may want
1519 to generate an rc file which the rc compiler can read; if that day
1520 comes, this code will have to be fixed up. */
1523 write_rc_file (filename
, resources
)
1524 const char *filename
;
1525 const struct res_directory
*resources
;
1530 if (filename
== NULL
)
1534 e
= fopen (filename
, FOPEN_WT
);
1536 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1540 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1541 (const struct res_id
*) NULL
, &language
, 1);
1544 /* Write out a directory. E is the file to write to. RD is the
1545 directory. TYPE is a pointer to the level 1 ID which serves as the
1546 resource type. NAME is a pointer to the level 2 ID which serves as
1547 an individual resource name. LANGUAGE is a pointer to the current
1548 language. LEVEL is the level in the tree. */
1551 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1553 const struct res_directory
*rd
;
1554 const struct res_id
*type
;
1555 const struct res_id
*name
;
1559 const struct res_entry
*re
;
1561 /* Print out some COFF information that rc files can't represent. */
1564 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1565 if (rd
->characteristics
!= 0)
1566 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1567 if (rd
->major
!= 0 || rd
->minor
!= 0)
1568 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1570 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1575 /* If we're at level 1, the key of this resource is the
1576 type. This normally duplicates the information we have
1577 stored with the resource itself, but we need to remember
1578 the type if this is a user define resource type. */
1583 /* If we're at level 2, the key of this resource is the name
1584 we are going to use in the rc printout. */
1589 /* If we're at level 3, then this key represents a language.
1590 Use it to update the current language. */
1592 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1593 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1595 fprintf (e
, "LANGUAGE %lu, %lu\n",
1596 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1597 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
1598 *language
= re
->id
.u
.id
;
1607 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1612 /* This is the normal case: the three levels are
1613 TYPE/NAME/LANGUAGE. NAME will have been set at level
1614 2, and represents the name to use. We probably just
1615 set LANGUAGE, and it will probably match what the
1616 resource itself records if anything. */
1617 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1621 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1622 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1629 /* Write out a subdirectory entry. E is the file to write to. RE is
1630 the subdirectory entry. TYPE and NAME are pointers to higher level
1631 IDs, or NULL. LANGUAGE is a pointer to the current language.
1632 LEVEL is the level in the tree. */
1635 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1637 const struct res_entry
*re
;
1638 const struct res_id
*type
;
1639 const struct res_id
*name
;
1647 fprintf (e
, "// Type: ");
1649 res_id_print (e
, re
->id
, 1);
1654 switch (re
->id
.u
.id
)
1656 case RT_CURSOR
: s
= "cursor"; break;
1657 case RT_BITMAP
: s
= "bitmap"; break;
1658 case RT_ICON
: s
= "icon"; break;
1659 case RT_MENU
: s
= "menu"; break;
1660 case RT_DIALOG
: s
= "dialog"; break;
1661 case RT_STRING
: s
= "stringtable"; break;
1662 case RT_FONTDIR
: s
= "fontdir"; break;
1663 case RT_FONT
: s
= "font"; break;
1664 case RT_ACCELERATOR
: s
= "accelerators"; break;
1665 case RT_RCDATA
: s
= "rcdata"; break;
1666 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1667 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1668 case RT_GROUP_ICON
: s
= "group icon"; break;
1669 case RT_VERSION
: s
= "version"; break;
1670 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1671 case RT_PLUGPLAY
: s
= "plugplay"; break;
1672 case RT_VXD
: s
= "vxd"; break;
1673 case RT_ANICURSOR
: s
= "anicursor"; break;
1674 case RT_ANIICON
: s
= "aniicon"; break;
1675 default: s
= NULL
; break;
1679 fprintf (e
, "%s", s
);
1681 res_id_print (e
, re
->id
, 1);
1687 fprintf (e
, "// Name: ");
1688 res_id_print (e
, re
->id
, 1);
1693 fprintf (e
, "// Language: ");
1694 res_id_print (e
, re
->id
, 1);
1699 fprintf (e
, "// Level %d: ", level
);
1700 res_id_print (e
, re
->id
, 1);
1704 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1707 /* Write out a single resource. E is the file to write to. TYPE is a
1708 pointer to the type of the resource. NAME is a pointer to the name
1709 of the resource; it will be NULL if there is a level mismatch. RES
1710 is the resource data. LANGUAGE is a pointer to the current
1714 write_rc_resource (e
, type
, name
, res
, language
)
1716 const struct res_id
*type
;
1717 const struct res_id
*name
;
1718 const struct res_resource
*res
;
1732 case RES_TYPE_ACCELERATOR
:
1734 rt
= RT_ACCELERATOR
;
1737 case RES_TYPE_BITMAP
:
1742 case RES_TYPE_CURSOR
:
1747 case RES_TYPE_GROUP_CURSOR
:
1749 rt
= RT_GROUP_CURSOR
;
1752 case RES_TYPE_DIALOG
:
1753 if (extended_dialog (res
->u
.dialog
))
1765 case RES_TYPE_FONTDIR
:
1775 case RES_TYPE_GROUP_ICON
:
1781 if (extended_menu (res
->u
.menu
))
1794 case RES_TYPE_MESSAGETABLE
:
1796 rt
= RT_MESSAGETABLE
;
1799 case RES_TYPE_RCDATA
:
1804 case RES_TYPE_STRINGTABLE
:
1809 case RES_TYPE_USERDATA
:
1814 case RES_TYPE_VERSIONINFO
:
1822 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1824 fprintf (e
, "// Unexpected resource type mismatch: ");
1825 res_id_print (e
, *type
, 1);
1826 fprintf (e
, " != %d", rt
);
1829 if (res
->coff_info
.codepage
!= 0)
1830 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1831 if (res
->coff_info
.reserved
!= 0)
1832 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1835 res_id_print (e
, *name
, 0);
1837 fprintf (e
, "??Unknown-Name??");
1841 fprintf (e
, "%s", s
);
1842 else if (type
!= NULL
)
1843 res_id_print (e
, *type
, 0);
1845 fprintf (e
, "??Unknown-Type??");
1847 if (res
->res_info
.memflags
!= 0)
1849 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1850 fprintf (e
, " MOVEABLE");
1851 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1852 fprintf (e
, " PURE");
1853 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1854 fprintf (e
, " PRELOAD");
1855 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1856 fprintf (e
, " DISCARDABLE");
1859 if (res
->type
== RES_TYPE_DIALOG
)
1861 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1862 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1863 if (res
->u
.dialog
->ex
!= NULL
1864 && res
->u
.dialog
->ex
->help
!= 0)
1865 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1870 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1871 || res
->res_info
.characteristics
!= 0
1872 || res
->res_info
.version
!= 0)
1878 case RES_TYPE_ACCELERATOR
:
1879 case RES_TYPE_DIALOG
:
1881 case RES_TYPE_RCDATA
:
1882 case RES_TYPE_STRINGTABLE
:
1891 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1892 fprintf (e
, "%sLANGUAGE %d, %d\n",
1893 modifiers
? "// " : "",
1894 res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
1895 (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
1896 if (res
->res_info
.characteristics
!= 0)
1897 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1898 modifiers
? "// " : "",
1899 res
->res_info
.characteristics
);
1900 if (res
->res_info
.version
!= 0)
1901 fprintf (e
, "%sVERSION %lu\n",
1902 modifiers
? "// " : "",
1903 res
->res_info
.version
);
1911 case RES_TYPE_ACCELERATOR
:
1912 write_rc_accelerators (e
, res
->u
.acc
);
1915 case RES_TYPE_CURSOR
:
1916 write_rc_cursor (e
, res
->u
.cursor
);
1919 case RES_TYPE_GROUP_CURSOR
:
1920 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1923 case RES_TYPE_DIALOG
:
1924 write_rc_dialog (e
, res
->u
.dialog
);
1927 case RES_TYPE_FONTDIR
:
1928 write_rc_fontdir (e
, res
->u
.fontdir
);
1931 case RES_TYPE_GROUP_ICON
:
1932 write_rc_group_icon (e
, res
->u
.group_icon
);
1936 write_rc_menu (e
, res
->u
.menu
, menuex
);
1939 case RES_TYPE_RCDATA
:
1940 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1943 case RES_TYPE_STRINGTABLE
:
1944 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1947 case RES_TYPE_USERDATA
:
1948 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1951 case RES_TYPE_VERSIONINFO
:
1952 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1955 case RES_TYPE_BITMAP
:
1958 case RES_TYPE_MESSAGETABLE
:
1959 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1964 /* Write out accelerator information. */
1967 write_rc_accelerators (e
, accelerators
)
1969 const struct accelerator
*accelerators
;
1971 const struct accelerator
*acc
;
1973 fprintf (e
, "BEGIN\n");
1974 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1980 if ((acc
->key
& 0x7f) == acc
->key
1981 && ISPRINT (acc
->key
)
1982 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1984 fprintf (e
, "\"%c\"", acc
->key
);
1989 fprintf (e
, "%d", acc
->key
);
1993 fprintf (e
, ", %d", acc
->id
);
1997 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1998 fprintf (e
, ", VIRTKEY");
2000 fprintf (e
, ", ASCII");
2003 if ((acc
->flags
& ACC_SHIFT
) != 0)
2004 fprintf (e
, ", SHIFT");
2005 if ((acc
->flags
& ACC_CONTROL
) != 0)
2006 fprintf (e
, ", CONTROL");
2007 if ((acc
->flags
& ACC_ALT
) != 0)
2008 fprintf (e
, ", ALT");
2013 fprintf (e
, "END\n");
2016 /* Write out cursor information. This would normally be in a separate
2017 file, which the rc file would include. */
2020 write_rc_cursor (e
, cursor
)
2022 const struct cursor
*cursor
;
2024 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
2026 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
2029 /* Write out group cursor data. This would normally be built from the
2033 write_rc_group_cursor (e
, group_cursor
)
2035 const struct group_cursor
*group_cursor
;
2037 const struct group_cursor
*gc
;
2039 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
2041 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
2042 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
2043 fprintf (e
, "// data bytes: %lu; index: %d\n",
2044 gc
->bytes
, gc
->index
);
2048 /* Write dialog data. */
2051 write_rc_dialog (e
, dialog
)
2053 const struct dialog
*dialog
;
2055 const struct dialog_control
*control
;
2057 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
2059 if (dialog
->exstyle
!= 0)
2060 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
2062 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2063 || dialog
->class.u
.id
!= 0)
2065 fprintf (e
, "CLASS ");
2066 res_id_print (e
, dialog
->class, 1);
2070 if (dialog
->caption
!= NULL
)
2072 fprintf (e
, "CAPTION \"");
2073 unicode_print (e
, dialog
->caption
, -1);
2074 fprintf (e
, "\"\n");
2077 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2078 || dialog
->menu
.u
.id
!= 0)
2080 fprintf (e
, "MENU ");
2081 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
2092 || dialog
->ex
->italic
!= 0
2093 || dialog
->ex
->charset
!= 1))
2094 fprintf (e
, ", %d, %d, %d",
2095 dialog
->ex
->weight
, dialog
->ex
->italic
, dialog
->ex
->charset
);
2099 fprintf (e
, "BEGIN\n");
2101 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2102 write_rc_dialog_control (e
, control
);
2104 fprintf (e
, "END\n");
2107 /* For each predefined control keyword, this table provides the class
2113 unsigned short class;
2114 unsigned long style
;
2117 static const struct control_info control_info
[] =
2119 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2120 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2121 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2122 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2123 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2124 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2125 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2126 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2127 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2128 { "ICON", CTL_STATIC
, SS_ICON
},
2129 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2130 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2131 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2132 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2133 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2134 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2135 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2136 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2137 /* It's important that USERBUTTON come after all the other button
2138 types, so that it won't be matched too early. */
2139 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2143 /* Write a dialog control. */
2146 write_rc_dialog_control (e
, control
)
2148 const struct dialog_control
*control
;
2150 const struct control_info
*ci
;
2154 if (control
->class.named
)
2158 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2159 if (ci
->class == control
->class.u
.id
2160 && (ci
->style
== (unsigned long) -1
2161 || ci
->style
== (control
->style
& 0xff)))
2165 fprintf (e
, "CONTROL");
2166 else if (ci
->name
!= NULL
)
2167 fprintf (e
, "%s", ci
->name
);
2169 fprintf (e
, "CONTROL");
2171 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2174 res_id_print (e
, control
->text
, 1);
2178 fprintf (e
, " %d, ", control
->id
);
2182 if (control
->class.named
)
2184 res_id_print (e
, control
->class, 0);
2185 if (control
->class.named
)
2187 fprintf (e
, ", 0x%lx, ", control
->style
);
2190 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2192 if (control
->style
!= SS_ICON
2193 || control
->exstyle
!= 0
2194 || control
->width
!= 0
2195 || control
->height
!= 0
2196 || control
->help
!= 0)
2198 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2200 /* FIXME: We don't need to print the style if it is the default.
2201 More importantly, in certain cases we actually need to turn
2202 off parts of the forced style, by using NOT. */
2203 fprintf (e
, ", 0x%lx", control
->style
);
2205 if (control
->exstyle
!= 0 || control
->help
!= 0)
2206 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2211 if (control
->data
!= NULL
)
2212 write_rc_rcdata (e
, control
->data
, 2);
2215 /* Write out font directory data. This would normally be built from
2219 write_rc_fontdir (e
, fontdir
)
2221 const struct fontdir
*fontdir
;
2223 const struct fontdir
*fc
;
2225 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2227 fprintf (e
, "// Font index: %d\n", fc
->index
);
2228 write_rc_filedata (e
, fc
->length
, fc
->data
);
2232 /* Write out group icon data. This would normally be built from the
2236 write_rc_group_icon (e
, group_icon
)
2238 const struct group_icon
*group_icon
;
2240 const struct group_icon
*gi
;
2242 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2244 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2245 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2246 fprintf (e
, "// data bytes: %lu; index: %d\n",
2247 gi
->bytes
, gi
->index
);
2251 /* Write out a menu resource. */
2254 write_rc_menu (e
, menu
, menuex
)
2256 const struct menu
*menu
;
2259 if (menu
->help
!= 0)
2260 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2261 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2264 /* Write out menuitems. */
2267 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
2269 const struct menuitem
*menuitems
;
2273 const struct menuitem
*mi
;
2276 fprintf (e
, "BEGIN\n");
2278 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2280 indent (e
, ind
+ 2);
2282 if (mi
->popup
== NULL
)
2283 fprintf (e
, "MENUITEM");
2285 fprintf (e
, "POPUP");
2288 && mi
->popup
== NULL
2293 fprintf (e
, " SEPARATOR\n");
2297 if (mi
->text
== NULL
)
2298 fprintf (e
, " \"\"");
2302 unicode_print (e
, mi
->text
, -1);
2308 if (mi
->popup
== NULL
)
2309 fprintf (e
, ", %d", mi
->id
);
2311 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2312 fprintf (e
, ", CHECKED");
2313 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2314 fprintf (e
, ", GRAYED");
2315 if ((mi
->type
& MENUITEM_HELP
) != 0)
2316 fprintf (e
, ", HELP");
2317 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2318 fprintf (e
, ", INACTIVE");
2319 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2320 fprintf (e
, ", MENUBARBREAK");
2321 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2322 fprintf (e
, ", MENUBREAK");
2326 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2328 fprintf (e
, ", %d", mi
->id
);
2329 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2331 fprintf (e
, ", %lu", mi
->type
);
2332 if (mi
->state
!= 0 || mi
->help
!= 0)
2334 fprintf (e
, ", %lu", mi
->state
);
2336 fprintf (e
, ", %lu", mi
->help
);
2344 if (mi
->popup
!= NULL
)
2345 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2349 fprintf (e
, "END\n");
2352 /* Write out an rcdata resource. This is also used for other types of
2353 resources that need to print arbitrary data. */
2356 write_rc_rcdata (e
, rcdata
, ind
)
2358 const struct rcdata_item
*rcdata
;
2361 const struct rcdata_item
*ri
;
2364 fprintf (e
, "BEGIN\n");
2366 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2368 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2371 indent (e
, ind
+ 2);
2379 fprintf (e
, "%d", ri
->u
.word
);
2383 fprintf (e
, "%luL", ri
->u
.dword
);
2393 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2398 fprintf (e
, "\\%03o", *s
);
2404 case RCDATA_WSTRING
:
2406 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2415 /* Assume little endian data. */
2418 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2424 indent (e
, ind
+ 2);
2425 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2426 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2427 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2428 | ri
->u
.buffer
.data
[i
]);
2429 fprintf (e
, "%luL", l
);
2430 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2432 for (j
= 0; j
< 4; ++j
)
2433 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2434 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2438 fprintf (e
, "\t// ");
2439 for (j
= 0; j
< 4; ++j
)
2441 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2442 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2445 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2447 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2455 if (i
+ 1 < ri
->u
.buffer
.length
)
2461 indent (e
, ind
+ 2);
2462 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2463 fprintf (e
, "%d", s
);
2464 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2466 for (j
= 0; j
< 2; ++j
)
2467 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2468 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2472 fprintf (e
, "\t// ");
2473 for (j
= 0; j
< 2; ++j
)
2475 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2476 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2479 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2481 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2490 if (i
< ri
->u
.buffer
.length
)
2493 indent (e
, ind
+ 2);
2494 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2495 && ISPRINT (ri
->u
.buffer
.data
[i
]))
2496 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2498 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2499 if (ri
->next
!= NULL
)
2509 if (ri
->type
!= RCDATA_BUFFER
)
2511 if (ri
->next
!= NULL
)
2518 fprintf (e
, "END\n");
2521 /* Write out a stringtable resource. */
2524 write_rc_stringtable (e
, name
, stringtable
)
2526 const struct res_id
*name
;
2527 const struct stringtable
*stringtable
;
2529 unsigned long offset
;
2532 if (name
!= NULL
&& ! name
->named
)
2533 offset
= (name
->u
.id
- 1) << 4;
2536 fprintf (e
, "// %s string table name\n",
2537 name
== NULL
? "Missing" : "Invalid");
2541 fprintf (e
, "BEGIN\n");
2543 for (i
= 0; i
< 16; i
++)
2545 if (stringtable
->strings
[i
].length
!= 0)
2547 fprintf (e
, " %lu, \"", offset
+ i
);
2548 unicode_print (e
, stringtable
->strings
[i
].string
,
2549 stringtable
->strings
[i
].length
);
2550 fprintf (e
, "\"\n");
2554 fprintf (e
, "END\n");
2557 /* Write out a versioninfo resource. */
2560 write_rc_versioninfo (e
, versioninfo
)
2562 const struct versioninfo
*versioninfo
;
2564 const struct fixed_versioninfo
*f
;
2565 const struct ver_info
*vi
;
2567 f
= versioninfo
->fixed
;
2568 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2569 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2570 (f
->file_version_ms
>> 16) & 0xffff,
2571 f
->file_version_ms
& 0xffff,
2572 (f
->file_version_ls
>> 16) & 0xffff,
2573 f
->file_version_ls
& 0xffff);
2574 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2575 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2576 (f
->product_version_ms
>> 16) & 0xffff,
2577 f
->product_version_ms
& 0xffff,
2578 (f
->product_version_ls
>> 16) & 0xffff,
2579 f
->product_version_ls
& 0xffff);
2580 if (f
->file_flags_mask
!= 0)
2581 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2582 if (f
->file_flags
!= 0)
2583 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2584 if (f
->file_os
!= 0)
2585 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2586 if (f
->file_type
!= 0)
2587 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2588 if (f
->file_subtype
!= 0)
2589 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2590 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2591 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2593 fprintf (e
, "BEGIN\n");
2595 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2599 case VERINFO_STRING
:
2601 const struct ver_stringinfo
*vs
;
2603 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2604 fprintf (e
, " BEGIN\n");
2605 fprintf (e
, " BLOCK \"");
2606 unicode_print (e
, vi
->u
.string
.language
, -1);
2607 fprintf (e
, "\"\n");
2608 fprintf (e
, " BEGIN\n");
2610 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2612 fprintf (e
, " VALUE \"");
2613 unicode_print (e
, vs
->key
, -1);
2614 fprintf (e
, "\", \"");
2615 unicode_print (e
, vs
->value
, -1);
2616 fprintf (e
, "\"\n");
2619 fprintf (e
, " END\n");
2620 fprintf (e
, " END\n");
2626 const struct ver_varinfo
*vv
;
2628 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2629 fprintf (e
, " BEGIN\n");
2630 fprintf (e
, " VALUE \"");
2631 unicode_print (e
, vi
->u
.var
.key
, -1);
2634 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2635 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2638 fprintf (e
, "\n END\n");
2645 fprintf (e
, "END\n");
2648 /* Write out data which would normally be read from a file. */
2651 write_rc_filedata (e
, length
, data
)
2653 unsigned long length
;
2654 const unsigned char *data
;
2658 for (i
= 0; i
+ 15 < length
; i
+= 16)
2660 fprintf (e
, "// %4lx: ", i
);
2661 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2662 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2663 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2664 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2665 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2666 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2671 fprintf (e
, "// %4lx:", i
);
2674 fprintf (e
, " %02x", data
[i
]);