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;
851 res_string_to_id (&n
->text
, text
);
863 /* Define a font resource. */
866 define_font (id
, resinfo
, filename
)
868 const struct res_res_info
*resinfo
;
869 const char *filename
;
875 struct res_resource
*r
;
878 unsigned char *fontdata
;
880 const char *device
, *face
;
883 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
885 if (stat (real_filename
, &s
) < 0)
886 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
889 data
= (unsigned char *) res_alloc (s
.st_size
);
891 get_data (e
, data
, s
.st_size
, real_filename
);
894 free (real_filename
);
896 r
= define_standard_resource (&resources
, RT_FONT
, id
,
897 resinfo
->language
, 0);
899 r
->type
= RES_TYPE_FONT
;
900 r
->u
.data
.length
= s
.st_size
;
901 r
->u
.data
.data
= data
;
902 r
->res_info
= *resinfo
;
904 /* For each font resource, we must add an entry in the FONTDIR
905 resource. The FONTDIR resource includes some strings in the font
906 file. To find them, we have to do some magic on the data we have
909 offset
= ((((((data
[47] << 8)
913 if (offset
> 0 && offset
< s
.st_size
)
914 device
= (char *) data
+ offset
;
918 offset
= ((((((data
[51] << 8)
922 if (offset
> 0 && offset
< s
.st_size
)
923 face
= (char *) data
+ offset
;
929 fontdatalength
= 58 + strlen (device
) + strlen (face
);
930 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
931 memcpy (fontdata
, data
, 56);
932 strcpy ((char *) fontdata
+ 56, device
);
933 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
935 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
938 fd
->length
= fontdatalength
;
941 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
945 /* For the single fontdirs resource, we always use the resource
946 information of the last font. I don't know what else to do. */
947 fontdirs_resinfo
= *resinfo
;
950 /* Define the fontdirs resource. This is called after the entire rc
951 file has been parsed, if any font resources were seen. */
956 struct res_resource
*r
;
962 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
964 r
->type
= RES_TYPE_FONTDIR
;
965 r
->u
.fontdir
= fontdirs
;
966 r
->res_info
= fontdirs_resinfo
;
969 /* Define an icon resource. An icon file may contain a set of
970 bitmaps, each representing the same icon at various different
971 resolutions. They each get written out with a different ID. The
972 real icon resource is then a group resource which can be used to
973 select one of the actual icon bitmaps. */
976 define_icon (id
, resinfo
, filename
)
978 const struct res_res_info
*resinfo
;
979 const char *filename
;
984 struct icondir
*icondirs
;
986 struct res_resource
*r
;
987 struct group_icon
*first
, **pp
;
989 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
991 /* The start of an icon file is a three word structure. The first
992 word is ignored. The second word is the type of data. The third
993 word is the number of entries. */
995 get_word (e
, real_filename
);
996 type
= get_word (e
, real_filename
);
997 count
= get_word (e
, real_filename
);
999 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1001 /* Read in the icon directory entries. */
1003 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1005 for (i
= 0; i
< count
; i
++)
1007 icondirs
[i
].width
= getc (e
);
1008 icondirs
[i
].height
= getc (e
);
1009 icondirs
[i
].colorcount
= getc (e
);
1011 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1012 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1013 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1014 icondirs
[i
].offset
= get_long (e
, real_filename
);
1017 unexpected_eof (real_filename
);
1020 /* Define each icon as a unique resource. */
1024 for (i
= 0; i
< count
; i
++)
1026 unsigned char *data
;
1029 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1030 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1031 icondirs
[i
].offset
, strerror (errno
));
1033 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1035 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1042 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1043 resinfo
->language
, 0);
1044 r
->type
= RES_TYPE_ICON
;
1045 r
->u
.data
.length
= icondirs
[i
].bytes
;
1046 r
->u
.data
.data
= data
;
1047 r
->res_info
= *resinfo
;
1051 free (real_filename
);
1053 /* Define an icon group resource. */
1057 for (i
= 0; i
< count
; i
++)
1059 struct group_icon
*cg
;
1061 /* For some reason, at least in some files the planes and bits
1062 are zero. We instead set them from the color. This is
1065 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1067 cg
->width
= icondirs
[i
].width
;
1068 cg
->height
= icondirs
[i
].height
;
1069 cg
->colors
= icondirs
[i
].colorcount
;
1073 while ((1 << cg
->bits
) < cg
->colors
)
1076 cg
->bytes
= icondirs
[i
].bytes
;
1077 cg
->index
= first_icon
+ i
+ 1;
1085 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1086 resinfo
->language
, 0);
1087 r
->type
= RES_TYPE_GROUP_ICON
;
1088 r
->u
.group_icon
= first
;
1089 r
->res_info
= *resinfo
;
1092 /* Define a menu resource. */
1095 define_menu (id
, resinfo
, menuitems
)
1097 const struct res_res_info
*resinfo
;
1098 struct menuitem
*menuitems
;
1101 struct res_resource
*r
;
1103 m
= (struct menu
*) res_alloc (sizeof *m
);
1104 m
->items
= menuitems
;
1107 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1108 r
->type
= RES_TYPE_MENU
;
1110 r
->res_info
= *resinfo
;
1113 /* Define a menu item. This does not define a resource, but merely
1114 allocates and fills in a structure. */
1117 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
1121 unsigned long state
;
1123 struct menuitem
*menuitems
;
1125 struct menuitem
*mi
;
1127 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1135 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1137 mi
->popup
= menuitems
;
1141 /* Define a messagetable resource. */
1144 define_messagetable (id
, resinfo
, filename
)
1146 const struct res_res_info
*resinfo
;
1147 const char *filename
;
1150 char *real_filename
;
1152 unsigned char *data
;
1153 struct res_resource
*r
;
1155 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1158 if (stat (real_filename
, &s
) < 0)
1159 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1162 data
= (unsigned char *) res_alloc (s
.st_size
);
1164 get_data (e
, data
, s
.st_size
, real_filename
);
1167 free (real_filename
);
1169 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1170 resinfo
->language
, 0);
1172 r
->type
= RES_TYPE_MESSAGETABLE
;
1173 r
->u
.data
.length
= s
.st_size
;
1174 r
->u
.data
.data
= data
;
1175 r
->res_info
= *resinfo
;
1178 /* Define an rcdata resource. */
1181 define_rcdata (id
, resinfo
, data
)
1183 const struct res_res_info
*resinfo
;
1184 struct rcdata_item
*data
;
1186 struct res_resource
*r
;
1188 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1189 resinfo
->language
, 0);
1190 r
->type
= RES_TYPE_RCDATA
;
1192 r
->res_info
= *resinfo
;
1195 /* Create an rcdata item holding a string. */
1197 struct rcdata_item
*
1198 define_rcdata_string (string
, len
)
1202 struct rcdata_item
*ri
;
1205 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1207 ri
->type
= RCDATA_STRING
;
1208 ri
->u
.string
.length
= len
;
1209 s
= (char *) res_alloc (len
);
1210 memcpy (s
, string
, len
);
1216 /* Create an rcdata item holding a number. */
1218 struct rcdata_item
*
1219 define_rcdata_number (val
, dword
)
1223 struct rcdata_item
*ri
;
1225 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1227 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1233 /* Define a stringtable resource. This is called for each string
1234 which appears in a STRINGTABLE statement. */
1237 define_stringtable (resinfo
, stringid
, string
)
1238 const struct res_res_info
*resinfo
;
1239 unsigned long stringid
;
1243 struct res_resource
*r
;
1246 id
.u
.id
= (stringid
>> 4) + 1;
1247 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1248 resinfo
->language
, 1);
1250 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1254 r
->type
= RES_TYPE_STRINGTABLE
;
1255 r
->u
.stringtable
= ((struct stringtable
*)
1256 res_alloc (sizeof (struct stringtable
)));
1257 for (i
= 0; i
< 16; i
++)
1259 r
->u
.stringtable
->strings
[i
].length
= 0;
1260 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1263 r
->res_info
= *resinfo
;
1266 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1267 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1271 /* Define a user data resource where the data is in the rc file. */
1274 define_user_data (id
, type
, resinfo
, data
)
1277 const struct res_res_info
*resinfo
;
1278 struct rcdata_item
*data
;
1280 struct res_id ids
[3];
1281 struct res_resource
*r
;
1286 ids
[2].u
.id
= resinfo
->language
;
1288 r
= define_resource (&resources
, 3, ids
, 0);
1289 r
->type
= RES_TYPE_USERDATA
;
1290 r
->u
.userdata
= data
;
1291 r
->res_info
= *resinfo
;
1294 /* Define a user data resource where the data is in a file. */
1297 define_user_file (id
, type
, resinfo
, filename
)
1300 const struct res_res_info
*resinfo
;
1301 const char *filename
;
1304 char *real_filename
;
1306 unsigned char *data
;
1307 struct res_id ids
[3];
1308 struct res_resource
*r
;
1310 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1312 if (stat (real_filename
, &s
) < 0)
1313 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1316 data
= (unsigned char *) res_alloc (s
.st_size
);
1318 get_data (e
, data
, s
.st_size
, real_filename
);
1321 free (real_filename
);
1326 ids
[2].u
.id
= resinfo
->language
;
1328 r
= define_resource (&resources
, 3, ids
, 0);
1329 r
->type
= RES_TYPE_USERDATA
;
1330 r
->u
.userdata
= ((struct rcdata_item
*)
1331 res_alloc (sizeof (struct rcdata_item
)));
1332 r
->u
.userdata
->next
= NULL
;
1333 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1334 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1335 r
->u
.userdata
->u
.buffer
.data
= data
;
1336 r
->res_info
= *resinfo
;
1339 /* Define a versioninfo resource. */
1342 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1345 struct fixed_versioninfo
*fixedverinfo
;
1346 struct ver_info
*verinfo
;
1348 struct res_resource
*r
;
1350 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1351 r
->type
= RES_TYPE_VERSIONINFO
;
1352 r
->u
.versioninfo
= ((struct versioninfo
*)
1353 res_alloc (sizeof (struct versioninfo
)));
1354 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1355 r
->u
.versioninfo
->var
= verinfo
;
1356 r
->res_info
.language
= language
;
1359 /* Add string version info to a list of version information. */
1362 append_ver_stringfileinfo (verinfo
, language
, strings
)
1363 struct ver_info
*verinfo
;
1364 const char *language
;
1365 struct ver_stringinfo
*strings
;
1367 struct ver_info
*vi
, **pp
;
1369 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1371 vi
->type
= VERINFO_STRING
;
1372 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1373 vi
->u
.string
.strings
= strings
;
1375 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1382 /* Add variable version info to a list of version information. */
1385 append_ver_varfileinfo (verinfo
, key
, var
)
1386 struct ver_info
*verinfo
;
1388 struct ver_varinfo
*var
;
1390 struct ver_info
*vi
, **pp
;
1392 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1394 vi
->type
= VERINFO_VAR
;
1395 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1396 vi
->u
.var
.var
= var
;
1398 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1405 /* Append version string information to a list. */
1407 struct ver_stringinfo
*
1408 append_verval (strings
, key
, value
)
1409 struct ver_stringinfo
*strings
;
1413 struct ver_stringinfo
*vs
, **pp
;
1415 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1417 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1418 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1420 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1427 /* Append version variable information to a list. */
1429 struct ver_varinfo
*
1430 append_vertrans (var
, language
, charset
)
1431 struct ver_varinfo
*var
;
1432 unsigned long language
;
1433 unsigned long charset
;
1435 struct ver_varinfo
*vv
, **pp
;
1437 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1439 vv
->language
= language
;
1440 vv
->charset
= charset
;
1442 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1449 /* Local functions used to write out an rc file. */
1451 static void indent
PARAMS ((FILE *, int));
1452 static void write_rc_directory
1453 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1454 const struct res_id
*, int *, int));
1455 static void write_rc_subdir
1456 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1457 const struct res_id
*, int *, int));
1458 static void write_rc_resource
1459 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1460 const struct res_resource
*, int *));
1461 static void write_rc_accelerators
1462 PARAMS ((FILE *, const struct accelerator
*));
1463 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1464 static void write_rc_group_cursor
1465 PARAMS ((FILE *, const struct group_cursor
*));
1466 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1467 static void write_rc_dialog_control
1468 PARAMS ((FILE *, const struct dialog_control
*));
1469 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1470 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1471 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1472 static void write_rc_menuitems
1473 PARAMS ((FILE *, const struct menuitem
*, int, int));
1474 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1475 static void write_rc_stringtable
1476 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1477 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1478 static void write_rc_filedata
1479 PARAMS ((FILE *, unsigned long, const unsigned char *));
1481 /* Indent a given number of spaces. */
1490 for (i
= 0; i
< c
; i
++)
1494 /* Dump the resources we have read in the format of an rc file.
1496 Actually, we don't use the format of an rc file, because it's way
1497 too much of a pain--for example, we'd have to write icon resources
1498 into a file and refer to that file. We just generate a readable
1499 format that kind of looks like an rc file, and is useful for
1500 understanding the contents of a resource file. Someday we may want
1501 to generate an rc file which the rc compiler can read; if that day
1502 comes, this code will have to be fixed up. */
1505 write_rc_file (filename
, resources
)
1506 const char *filename
;
1507 const struct res_directory
*resources
;
1512 if (filename
== NULL
)
1516 e
= fopen (filename
, FOPEN_WT
);
1518 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1522 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1523 (const struct res_id
*) NULL
, &language
, 1);
1526 /* Write out a directory. E is the file to write to. RD is the
1527 directory. TYPE is a pointer to the level 1 ID which serves as the
1528 resource type. NAME is a pointer to the level 2 ID which serves as
1529 an individual resource name. LANGUAGE is a pointer to the current
1530 language. LEVEL is the level in the tree. */
1533 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1535 const struct res_directory
*rd
;
1536 const struct res_id
*type
;
1537 const struct res_id
*name
;
1541 const struct res_entry
*re
;
1543 /* Print out some COFF information that rc files can't represent. */
1546 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1547 if (rd
->characteristics
!= 0)
1548 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1549 if (rd
->major
!= 0 || rd
->minor
!= 0)
1550 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1552 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1557 /* If we're at level 1, the key of this resource is the
1558 type. This normally duplicates the information we have
1559 stored with the resource itself, but we need to remember
1560 the type if this is a user define resource type. */
1565 /* If we're at level 2, the key of this resource is the name
1566 we are going to use in the rc printout. */
1571 /* If we're at level 3, then this key represents a language.
1572 Use it to update the current language. */
1574 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1575 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1577 fprintf (e
, "LANGUAGE %lu, %lu\n",
1578 re
->id
.u
.id
& 0xff, (re
->id
.u
.id
>> 8) & 0xff);
1579 *language
= re
->id
.u
.id
;
1588 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1593 /* This is the normal case: the three levels are
1594 TYPE/NAME/LANGUAGE. NAME will have been set at level
1595 2, and represents the name to use. We probably just
1596 set LANGUAGE, and it will probably match what the
1597 resource itself records if anything. */
1598 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1602 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1603 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1610 /* Write out a subdirectory entry. E is the file to write to. RE is
1611 the subdirectory entry. TYPE and NAME are pointers to higher level
1612 IDs, or NULL. LANGUAGE is a pointer to the current language.
1613 LEVEL is the level in the tree. */
1616 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1618 const struct res_entry
*re
;
1619 const struct res_id
*type
;
1620 const struct res_id
*name
;
1628 fprintf (e
, "// Type: ");
1630 res_id_print (e
, re
->id
, 1);
1635 switch (re
->id
.u
.id
)
1637 case RT_CURSOR
: s
= "cursor"; break;
1638 case RT_BITMAP
: s
= "bitmap"; break;
1639 case RT_ICON
: s
= "icon"; break;
1640 case RT_MENU
: s
= "menu"; break;
1641 case RT_DIALOG
: s
= "dialog"; break;
1642 case RT_STRING
: s
= "stringtable"; break;
1643 case RT_FONTDIR
: s
= "fontdir"; break;
1644 case RT_FONT
: s
= "font"; break;
1645 case RT_ACCELERATOR
: s
= "accelerators"; break;
1646 case RT_RCDATA
: s
= "rcdata"; break;
1647 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1648 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1649 case RT_GROUP_ICON
: s
= "group icon"; break;
1650 case RT_VERSION
: s
= "version"; break;
1651 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1652 case RT_PLUGPLAY
: s
= "plugplay"; break;
1653 case RT_VXD
: s
= "vxd"; break;
1654 case RT_ANICURSOR
: s
= "anicursor"; break;
1655 case RT_ANIICON
: s
= "aniicon"; break;
1656 default: s
= NULL
; break;
1660 fprintf (e
, "%s", s
);
1662 res_id_print (e
, re
->id
, 1);
1668 fprintf (e
, "// Name: ");
1669 res_id_print (e
, re
->id
, 1);
1674 fprintf (e
, "// Language: ");
1675 res_id_print (e
, re
->id
, 1);
1680 fprintf (e
, "// Level %d: ", level
);
1681 res_id_print (e
, re
->id
, 1);
1685 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1688 /* Write out a single resource. E is the file to write to. TYPE is a
1689 pointer to the type of the resource. NAME is a pointer to the name
1690 of the resource; it will be NULL if there is a level mismatch. RES
1691 is the resource data. LANGUAGE is a pointer to the current
1695 write_rc_resource (e
, type
, name
, res
, language
)
1697 const struct res_id
*type
;
1698 const struct res_id
*name
;
1699 const struct res_resource
*res
;
1713 case RES_TYPE_ACCELERATOR
:
1715 rt
= RT_ACCELERATOR
;
1718 case RES_TYPE_BITMAP
:
1723 case RES_TYPE_CURSOR
:
1728 case RES_TYPE_GROUP_CURSOR
:
1730 rt
= RT_GROUP_CURSOR
;
1733 case RES_TYPE_DIALOG
:
1734 if (extended_dialog (res
->u
.dialog
))
1746 case RES_TYPE_FONTDIR
:
1756 case RES_TYPE_GROUP_ICON
:
1762 if (extended_menu (res
->u
.menu
))
1775 case RES_TYPE_MESSAGETABLE
:
1777 rt
= RT_MESSAGETABLE
;
1780 case RES_TYPE_RCDATA
:
1785 case RES_TYPE_STRINGTABLE
:
1790 case RES_TYPE_USERDATA
:
1795 case RES_TYPE_VERSIONINFO
:
1803 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1805 fprintf (e
, "// Unexpected resource type mismatch: ");
1806 res_id_print (e
, *type
, 1);
1807 fprintf (e
, " != %d", rt
);
1810 if (res
->coff_info
.codepage
!= 0)
1811 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1812 if (res
->coff_info
.reserved
!= 0)
1813 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1816 res_id_print (e
, *name
, 0);
1818 fprintf (e
, "??Unknown-Name??");
1822 fprintf (e
, "%s", s
);
1823 else if (type
!= NULL
)
1824 res_id_print (e
, *type
, 0);
1826 fprintf (e
, "??Unknown-Type??");
1828 if (res
->res_info
.memflags
!= 0)
1830 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1831 fprintf (e
, " MOVEABLE");
1832 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1833 fprintf (e
, " PURE");
1834 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1835 fprintf (e
, " PRELOAD");
1836 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1837 fprintf (e
, " DISCARDABLE");
1840 if (res
->type
== RES_TYPE_DIALOG
)
1842 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1843 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1844 if (res
->u
.dialog
->ex
!= NULL
1845 && res
->u
.dialog
->ex
->help
!= 0)
1846 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1851 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1852 || res
->res_info
.characteristics
!= 0
1853 || res
->res_info
.version
!= 0)
1859 case RES_TYPE_ACCELERATOR
:
1860 case RES_TYPE_DIALOG
:
1862 case RES_TYPE_RCDATA
:
1863 case RES_TYPE_STRINGTABLE
:
1872 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1873 fprintf (e
, "%sLANGUAGE %d, %d\n",
1874 modifiers
? "// " : "",
1875 res
->res_info
.language
& 0xff,
1876 (res
->res_info
.language
>> 8) & 0xff);
1877 if (res
->res_info
.characteristics
!= 0)
1878 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1879 modifiers
? "// " : "",
1880 res
->res_info
.characteristics
);
1881 if (res
->res_info
.version
!= 0)
1882 fprintf (e
, "%sVERSION %lu\n",
1883 modifiers
? "// " : "",
1884 res
->res_info
.version
);
1892 case RES_TYPE_ACCELERATOR
:
1893 write_rc_accelerators (e
, res
->u
.acc
);
1896 case RES_TYPE_CURSOR
:
1897 write_rc_cursor (e
, res
->u
.cursor
);
1900 case RES_TYPE_GROUP_CURSOR
:
1901 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1904 case RES_TYPE_DIALOG
:
1905 write_rc_dialog (e
, res
->u
.dialog
);
1908 case RES_TYPE_FONTDIR
:
1909 write_rc_fontdir (e
, res
->u
.fontdir
);
1912 case RES_TYPE_GROUP_ICON
:
1913 write_rc_group_icon (e
, res
->u
.group_icon
);
1917 write_rc_menu (e
, res
->u
.menu
, menuex
);
1920 case RES_TYPE_RCDATA
:
1921 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1924 case RES_TYPE_STRINGTABLE
:
1925 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1928 case RES_TYPE_USERDATA
:
1929 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1932 case RES_TYPE_VERSIONINFO
:
1933 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1936 case RES_TYPE_BITMAP
:
1939 case RES_TYPE_MESSAGETABLE
:
1940 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1945 /* Write out accelerator information. */
1948 write_rc_accelerators (e
, accelerators
)
1950 const struct accelerator
*accelerators
;
1952 const struct accelerator
*acc
;
1954 fprintf (e
, "BEGIN\n");
1955 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1961 if ((acc
->key
& 0x7f) == acc
->key
1962 && isprint ((unsigned char) acc
->key
)
1963 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1965 fprintf (e
, "\"%c\"", acc
->key
);
1970 fprintf (e
, "%d", acc
->key
);
1974 fprintf (e
, ", %d", acc
->id
);
1978 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1979 fprintf (e
, ", VIRTKEY");
1981 fprintf (e
, ", ASCII");
1984 if ((acc
->flags
& ACC_SHIFT
) != 0)
1985 fprintf (e
, ", SHIFT");
1986 if ((acc
->flags
& ACC_CONTROL
) != 0)
1987 fprintf (e
, ", CONTROL");
1988 if ((acc
->flags
& ACC_ALT
) != 0)
1989 fprintf (e
, ", ALT");
1994 fprintf (e
, "END\n");
1997 /* Write out cursor information. This would normally be in a separate
1998 file, which the rc file would include. */
2001 write_rc_cursor (e
, cursor
)
2003 const struct cursor
*cursor
;
2005 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
2007 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
2010 /* Write out group cursor data. This would normally be built from the
2014 write_rc_group_cursor (e
, group_cursor
)
2016 const struct group_cursor
*group_cursor
;
2018 const struct group_cursor
*gc
;
2020 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
2022 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
2023 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
2024 fprintf (e
, "// data bytes: %lu; index: %d\n",
2025 gc
->bytes
, gc
->index
);
2029 /* Write dialog data. */
2032 write_rc_dialog (e
, dialog
)
2034 const struct dialog
*dialog
;
2036 const struct dialog_control
*control
;
2038 if (dialog
->style
!= 0)
2039 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
2040 if (dialog
->exstyle
!= 0)
2041 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
2042 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2043 || dialog
->class.u
.id
!= 0)
2045 fprintf (e
, "CLASS ");
2046 res_id_print (e
, dialog
->class, 0);
2049 if (dialog
->caption
!= NULL
)
2051 fprintf (e
, "CAPTION \"");
2052 unicode_print (e
, dialog
->caption
, -1);
2053 fprintf (e
, "\"\n");
2055 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2056 || dialog
->menu
.u
.id
!= 0)
2058 fprintf (e
, "MENU ");
2059 res_id_print (e
, dialog
->menu
, 0);
2062 if (dialog
->font
!= NULL
)
2064 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
2065 unicode_print (e
, dialog
->font
, -1);
2067 if (dialog
->ex
!= NULL
2068 && (dialog
->ex
->weight
!= 0 || dialog
->ex
->italic
!= 0))
2069 fprintf (e
, ", %d, %d", dialog
->ex
->weight
, dialog
->ex
->italic
);
2073 fprintf (e
, "BEGIN\n");
2075 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2076 write_rc_dialog_control (e
, control
);
2078 fprintf (e
, "END\n");
2081 /* For each predefined control keyword, this table provides the class
2087 unsigned short class;
2088 unsigned long style
;
2091 static const struct control_info control_info
[] =
2093 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2094 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2095 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2096 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2097 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2098 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2099 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2100 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2101 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2102 { "ICON", CTL_STATIC
, SS_ICON
},
2103 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2104 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2105 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2106 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2107 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2108 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2109 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2110 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2111 /* It's important that USERBUTTON come after all the other button
2112 types, so that it won't be matched too early. */
2113 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2117 /* Write a dialog control. */
2120 write_rc_dialog_control (e
, control
)
2122 const struct dialog_control
*control
;
2124 const struct control_info
*ci
;
2128 if (control
->class.named
)
2132 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2133 if (ci
->class == control
->class.u
.id
2134 && (ci
->style
== (unsigned long) -1
2135 || ci
->style
== (control
->style
& 0xff)))
2139 fprintf (e
, "CONTROL");
2140 else if (ci
->name
!= NULL
)
2141 fprintf (e
, "%s", ci
->name
);
2143 fprintf (e
, "CONTROL");
2145 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2148 res_id_print (e
, control
->text
, 1);
2152 fprintf (e
, " %d, ", control
->id
);
2156 if (control
->class.named
)
2158 res_id_print (e
, control
->class, 0);
2159 if (control
->class.named
)
2161 fprintf (e
, ", 0x%lx, ", control
->style
);
2164 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2166 if (control
->style
!= SS_ICON
2167 || control
->exstyle
!= 0
2168 || control
->width
!= 0
2169 || control
->height
!= 0
2170 || control
->help
!= 0)
2172 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2174 /* FIXME: We don't need to print the style if it is the default.
2175 More importantly, in certain cases we actually need to turn
2176 off parts of the forced style, by using NOT. */
2177 fprintf (e
, ", 0x%lx", control
->style
);
2179 if (control
->exstyle
!= 0 || control
->help
!= 0)
2180 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2185 if (control
->data
!= NULL
)
2186 write_rc_rcdata (e
, control
->data
, 2);
2189 /* Write out font directory data. This would normally be built from
2193 write_rc_fontdir (e
, fontdir
)
2195 const struct fontdir
*fontdir
;
2197 const struct fontdir
*fc
;
2199 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2201 fprintf (e
, "// Font index: %d\n", fc
->index
);
2202 write_rc_filedata (e
, fc
->length
, fc
->data
);
2206 /* Write out group icon data. This would normally be built from the
2210 write_rc_group_icon (e
, group_icon
)
2212 const struct group_icon
*group_icon
;
2214 const struct group_icon
*gi
;
2216 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2218 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2219 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2220 fprintf (e
, "// data bytes: %lu; index: %d\n",
2221 gi
->bytes
, gi
->index
);
2225 /* Write out a menu resource. */
2228 write_rc_menu (e
, menu
, menuex
)
2230 const struct menu
*menu
;
2233 if (menu
->help
!= 0)
2234 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2235 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2238 /* Write out menuitems. */
2241 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
2243 const struct menuitem
*menuitems
;
2247 const struct menuitem
*mi
;
2250 fprintf (e
, "BEGIN\n");
2252 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2254 indent (e
, ind
+ 2);
2256 if (mi
->popup
== NULL
)
2257 fprintf (e
, "MENUITEM");
2259 fprintf (e
, "POPUP");
2262 && mi
->popup
== NULL
2267 fprintf (e
, " SEPARATOR\n");
2271 if (mi
->text
== NULL
)
2272 fprintf (e
, " \"\"");
2276 unicode_print (e
, mi
->text
, -1);
2282 if (mi
->popup
== NULL
)
2283 fprintf (e
, ", %d", mi
->id
);
2285 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2286 fprintf (e
, ", CHECKED");
2287 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2288 fprintf (e
, ", GRAYED");
2289 if ((mi
->type
& MENUITEM_HELP
) != 0)
2290 fprintf (e
, ", HELP");
2291 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2292 fprintf (e
, ", INACTIVE");
2293 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2294 fprintf (e
, ", MENUBARBREAK");
2295 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2296 fprintf (e
, ", MENUBREAK");
2300 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2302 fprintf (e
, ", %d", mi
->id
);
2303 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2305 fprintf (e
, ", %lu", mi
->type
);
2306 if (mi
->state
!= 0 || mi
->help
!= 0)
2308 fprintf (e
, ", %lu", mi
->state
);
2310 fprintf (e
, ", %lu", mi
->help
);
2318 if (mi
->popup
!= NULL
)
2319 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2323 fprintf (e
, "END\n");
2326 /* Write out an rcdata resource. This is also used for other types of
2327 resources that need to print arbitrary data. */
2330 write_rc_rcdata (e
, rcdata
, ind
)
2332 const struct rcdata_item
*rcdata
;
2335 const struct rcdata_item
*ri
;
2338 fprintf (e
, "BEGIN\n");
2340 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2342 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2345 indent (e
, ind
+ 2);
2353 fprintf (e
, "%d", ri
->u
.word
);
2357 fprintf (e
, "%luL", ri
->u
.dword
);
2367 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2369 if (isprint ((unsigned char) *s
))
2372 fprintf (e
, "\\%03o", *s
);
2378 case RCDATA_WSTRING
:
2380 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2389 /* Assume little endian data. */
2392 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2398 indent (e
, ind
+ 2);
2399 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2400 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2401 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2402 | ri
->u
.buffer
.data
[i
]);
2403 fprintf (e
, "%luL", l
);
2404 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2406 for (j
= 0; j
< 4; ++j
)
2407 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2408 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2412 fprintf (e
, "\t// ");
2413 for (j
= 0; j
< 4; ++j
)
2415 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2416 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2419 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2421 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2429 if (i
+ 1 < ri
->u
.buffer
.length
)
2435 indent (e
, ind
+ 2);
2436 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2437 fprintf (e
, "%d", s
);
2438 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2440 for (j
= 0; j
< 2; ++j
)
2441 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2442 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2446 fprintf (e
, "\t// ");
2447 for (j
= 0; j
< 2; ++j
)
2449 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2450 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2453 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2455 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2464 if (i
< ri
->u
.buffer
.length
)
2467 indent (e
, ind
+ 2);
2468 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2469 && isprint (ri
->u
.buffer
.data
[i
]))
2470 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2472 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2473 if (ri
->next
!= NULL
)
2483 if (ri
->type
!= RCDATA_BUFFER
)
2485 if (ri
->next
!= NULL
)
2492 fprintf (e
, "END\n");
2495 /* Write out a stringtable resource. */
2498 write_rc_stringtable (e
, name
, stringtable
)
2500 const struct res_id
*name
;
2501 const struct stringtable
*stringtable
;
2503 unsigned long offset
;
2506 if (name
!= NULL
&& ! name
->named
)
2507 offset
= (name
->u
.id
- 1) << 4;
2510 fprintf (e
, "// %s string table name\n",
2511 name
== NULL
? "Missing" : "Invalid");
2515 fprintf (e
, "BEGIN\n");
2517 for (i
= 0; i
< 16; i
++)
2519 if (stringtable
->strings
[i
].length
!= 0)
2521 fprintf (e
, " %lu, \"", offset
+ i
);
2522 unicode_print (e
, stringtable
->strings
[i
].string
,
2523 stringtable
->strings
[i
].length
);
2524 fprintf (e
, "\"\n");
2528 fprintf (e
, "END\n");
2531 /* Write out a versioninfo resource. */
2534 write_rc_versioninfo (e
, versioninfo
)
2536 const struct versioninfo
*versioninfo
;
2538 const struct fixed_versioninfo
*f
;
2539 const struct ver_info
*vi
;
2541 f
= versioninfo
->fixed
;
2542 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2543 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2544 (f
->file_version_ms
>> 16) & 0xffff,
2545 f
->file_version_ms
& 0xffff,
2546 (f
->file_version_ls
>> 16) & 0xffff,
2547 f
->file_version_ls
& 0xffff);
2548 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2549 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2550 (f
->product_version_ms
>> 16) & 0xffff,
2551 f
->product_version_ms
& 0xffff,
2552 (f
->product_version_ls
>> 16) & 0xffff,
2553 f
->product_version_ls
& 0xffff);
2554 if (f
->file_flags_mask
!= 0)
2555 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2556 if (f
->file_flags
!= 0)
2557 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2558 if (f
->file_os
!= 0)
2559 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2560 if (f
->file_type
!= 0)
2561 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2562 if (f
->file_subtype
!= 0)
2563 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2564 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2565 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2567 fprintf (e
, "BEGIN\n");
2569 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2573 case VERINFO_STRING
:
2575 const struct ver_stringinfo
*vs
;
2577 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2578 fprintf (e
, " BEGIN\n");
2579 fprintf (e
, " BLOCK \"");
2580 unicode_print (e
, vi
->u
.string
.language
, -1);
2581 fprintf (e
, "\"\n");
2582 fprintf (e
, " BEGIN\n");
2584 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2586 fprintf (e
, " VALUE \"");
2587 unicode_print (e
, vs
->key
, -1);
2588 fprintf (e
, "\", \"");
2589 unicode_print (e
, vs
->value
, -1);
2590 fprintf (e
, "\"\n");
2593 fprintf (e
, " END\n");
2594 fprintf (e
, " END\n");
2600 const struct ver_varinfo
*vv
;
2602 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2603 fprintf (e
, " BEGIN\n");
2604 fprintf (e
, " VALUE \"");
2605 unicode_print (e
, vi
->u
.var
.key
, -1);
2608 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2609 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2612 fprintf (e
, "\n END\n");
2619 fprintf (e
, "END\n");
2622 /* Write out data which would normally be read from a file. */
2625 write_rc_filedata (e
, length
, data
)
2627 unsigned long length
;
2628 const unsigned char *data
;
2632 for (i
= 0; i
+ 15 < length
; i
+= 16)
2634 fprintf (e
, "// %4lx: ", i
);
2635 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2636 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2637 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2638 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2639 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2640 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2645 fprintf (e
, "// %4lx:", i
);
2648 fprintf (e
, " %02x", data
[i
]);