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
)
504 if (istream_type
== ISTREAM_FILE
)
506 if (cpp_pipe
!= NULL
)
509 if (cpp_temp_file
!= NULL
)
511 int errno_save
= errno
;
513 unlink (cpp_temp_file
);
515 free (cpp_temp_file
);
520 if (cpp_pipe
!= NULL
)
524 /* Since this is also run via xatexit, safeguard. */
526 cpp_temp_file
= NULL
;
529 /* Report an error while reading an rc file. */
535 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
538 /* Issue a warning while reading an rc file. */
541 rcparse_warning (msg
)
544 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
547 /* Die if we get an unexpected end of file. */
553 fatal (_("%s: unexpected EOF"), msg
);
556 /* Read a 16 bit word from a file. The data is assumed to be little
569 unexpected_eof (msg
);
570 return ((b2
& 0xff) << 8) | (b1
& 0xff);
573 /* Read a 32 bit word from a file. The data is assumed to be little
588 unexpected_eof (msg
);
589 return (((((((b4
& 0xff) << 8)
595 /* Read data from a file. This is a wrapper to do error checking. */
598 get_data (e
, p
, c
, msg
)
606 got
= fread (p
, 1, c
, e
);
610 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
613 /* Define an accelerator resource. */
616 define_accelerator (id
, resinfo
, data
)
618 const struct res_res_info
*resinfo
;
619 struct accelerator
*data
;
621 struct res_resource
*r
;
623 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
624 resinfo
->language
, 0);
625 r
->type
= RES_TYPE_ACCELERATOR
;
627 r
->res_info
= *resinfo
;
630 /* Define a bitmap resource. Bitmap data is stored in a file. The
631 first 14 bytes of the file are a standard header, which is not
632 included in the resource data. */
634 #define BITMAP_SKIP (14)
637 define_bitmap (id
, resinfo
, filename
)
639 const struct res_res_info
*resinfo
;
640 const char *filename
;
647 struct res_resource
*r
;
649 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
651 if (stat (real_filename
, &s
) < 0)
652 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
655 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
657 for (i
= 0; i
< BITMAP_SKIP
; i
++)
660 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
663 free (real_filename
);
665 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
666 resinfo
->language
, 0);
668 r
->type
= RES_TYPE_BITMAP
;
669 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
670 r
->u
.data
.data
= data
;
671 r
->res_info
= *resinfo
;
674 /* Define a cursor resource. A cursor file may contain a set of
675 bitmaps, each representing the same cursor at various different
676 resolutions. They each get written out with a different ID. The
677 real cursor resource is then a group resource which can be used to
678 select one of the actual cursors. */
681 define_cursor (id
, resinfo
, filename
)
683 const struct res_res_info
*resinfo
;
684 const char *filename
;
689 struct icondir
*icondirs
;
691 struct res_resource
*r
;
692 struct group_cursor
*first
, **pp
;
694 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
696 /* A cursor file is basically an icon file. The start of the file
697 is a three word structure. The first word is ignored. The
698 second word is the type of data. The third word is the number of
701 get_word (e
, real_filename
);
702 type
= get_word (e
, real_filename
);
703 count
= get_word (e
, real_filename
);
705 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
707 /* Read in the icon directory entries. */
709 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
711 for (i
= 0; i
< count
; i
++)
713 icondirs
[i
].width
= getc (e
);
714 icondirs
[i
].height
= getc (e
);
715 icondirs
[i
].colorcount
= getc (e
);
717 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
718 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
719 icondirs
[i
].bytes
= get_long (e
, real_filename
);
720 icondirs
[i
].offset
= get_long (e
, real_filename
);
723 unexpected_eof (real_filename
);
726 /* Define each cursor as a unique resource. */
728 first_cursor
= cursors
;
730 for (i
= 0; i
< count
; i
++)
736 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
737 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
738 icondirs
[i
].offset
, strerror (errno
));
740 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
742 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
744 c
= (struct cursor
*) res_alloc (sizeof *c
);
745 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
746 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
747 c
->length
= icondirs
[i
].bytes
;
755 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
756 resinfo
->language
, 0);
757 r
->type
= RES_TYPE_CURSOR
;
759 r
->res_info
= *resinfo
;
763 free (real_filename
);
765 /* Define a cursor group resource. */
769 for (i
= 0; i
< count
; i
++)
771 struct group_cursor
*cg
;
773 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
775 cg
->width
= icondirs
[i
].width
;
776 cg
->height
= 2 * icondirs
[i
].height
;
778 /* FIXME: What should these be set to? */
782 cg
->bytes
= icondirs
[i
].bytes
+ 4;
783 cg
->index
= first_cursor
+ i
+ 1;
791 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
792 resinfo
->language
, 0);
793 r
->type
= RES_TYPE_GROUP_CURSOR
;
794 r
->u
.group_cursor
= first
;
795 r
->res_info
= *resinfo
;
798 /* Define a dialog resource. */
801 define_dialog (id
, resinfo
, dialog
)
803 const struct res_res_info
*resinfo
;
804 const struct dialog
*dialog
;
807 struct res_resource
*r
;
809 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
812 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
813 resinfo
->language
, 0);
814 r
->type
= RES_TYPE_DIALOG
;
816 r
->res_info
= *resinfo
;
819 /* Define a dialog control. This does not define a resource, but
820 merely allocates and fills in a structure. */
822 struct dialog_control
*
823 define_control (text
, id
, x
, y
, width
, height
, class, style
, exstyle
)
829 unsigned long height
;
832 unsigned long exstyle
;
834 struct dialog_control
*n
;
836 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
840 n
->exstyle
= exstyle
;
846 n
->class.u
.id
= class;
848 res_string_to_id (&n
->text
, text
);
860 /* Define a font resource. */
863 define_font (id
, resinfo
, filename
)
865 const struct res_res_info
*resinfo
;
866 const char *filename
;
872 struct res_resource
*r
;
875 unsigned char *fontdata
;
877 const char *device
, *face
;
880 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
882 if (stat (real_filename
, &s
) < 0)
883 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
886 data
= (unsigned char *) res_alloc (s
.st_size
);
888 get_data (e
, data
, s
.st_size
, real_filename
);
891 free (real_filename
);
893 r
= define_standard_resource (&resources
, RT_FONT
, id
,
894 resinfo
->language
, 0);
896 r
->type
= RES_TYPE_FONT
;
897 r
->u
.data
.length
= s
.st_size
;
898 r
->u
.data
.data
= data
;
899 r
->res_info
= *resinfo
;
901 /* For each font resource, we must add an entry in the FONTDIR
902 resource. The FONTDIR resource includes some strings in the font
903 file. To find them, we have to do some magic on the data we have
906 offset
= ((((((data
[47] << 8)
910 if (offset
> 0 && offset
< s
.st_size
)
911 device
= (char *) data
+ offset
;
915 offset
= ((((((data
[51] << 8)
919 if (offset
> 0 && offset
< s
.st_size
)
920 face
= (char *) data
+ offset
;
926 fontdatalength
= 58 + strlen (device
) + strlen (face
);
927 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
928 memcpy (fontdata
, data
, 56);
929 strcpy ((char *) fontdata
+ 56, device
);
930 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
932 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
935 fd
->length
= fontdatalength
;
938 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
942 /* For the single fontdirs resource, we always use the resource
943 information of the last font. I don't know what else to do. */
944 fontdirs_resinfo
= *resinfo
;
947 /* Define the fontdirs resource. This is called after the entire rc
948 file has been parsed, if any font resources were seen. */
953 struct res_resource
*r
;
959 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
961 r
->type
= RES_TYPE_FONTDIR
;
962 r
->u
.fontdir
= fontdirs
;
963 r
->res_info
= fontdirs_resinfo
;
966 /* Define an icon resource. An icon file may contain a set of
967 bitmaps, each representing the same icon at various different
968 resolutions. They each get written out with a different ID. The
969 real icon resource is then a group resource which can be used to
970 select one of the actual icon bitmaps. */
973 define_icon (id
, resinfo
, filename
)
975 const struct res_res_info
*resinfo
;
976 const char *filename
;
981 struct icondir
*icondirs
;
983 struct res_resource
*r
;
984 struct group_icon
*first
, **pp
;
986 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
988 /* The start of an icon file is a three word structure. The first
989 word is ignored. The second word is the type of data. The third
990 word is the number of entries. */
992 get_word (e
, real_filename
);
993 type
= get_word (e
, real_filename
);
994 count
= get_word (e
, real_filename
);
996 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
998 /* Read in the icon directory entries. */
1000 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1002 for (i
= 0; i
< count
; i
++)
1004 icondirs
[i
].width
= getc (e
);
1005 icondirs
[i
].height
= getc (e
);
1006 icondirs
[i
].colorcount
= getc (e
);
1008 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1009 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1010 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1011 icondirs
[i
].offset
= get_long (e
, real_filename
);
1014 unexpected_eof (real_filename
);
1017 /* Define each icon as a unique resource. */
1021 for (i
= 0; i
< count
; i
++)
1023 unsigned char *data
;
1026 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1027 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1028 icondirs
[i
].offset
, strerror (errno
));
1030 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1032 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1039 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1040 resinfo
->language
, 0);
1041 r
->type
= RES_TYPE_ICON
;
1042 r
->u
.data
.length
= icondirs
[i
].bytes
;
1043 r
->u
.data
.data
= data
;
1044 r
->res_info
= *resinfo
;
1048 free (real_filename
);
1050 /* Define an icon group resource. */
1054 for (i
= 0; i
< count
; i
++)
1056 struct group_icon
*cg
;
1058 /* For some reason, at least in some files the planes and bits
1059 are zero. We instead set them from the color. This is
1062 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1064 cg
->width
= icondirs
[i
].width
;
1065 cg
->height
= icondirs
[i
].height
;
1066 cg
->colors
= icondirs
[i
].colorcount
;
1070 while ((1 << cg
->bits
) < cg
->colors
)
1073 cg
->bytes
= icondirs
[i
].bytes
;
1074 cg
->index
= first_icon
+ i
+ 1;
1082 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1083 resinfo
->language
, 0);
1084 r
->type
= RES_TYPE_GROUP_ICON
;
1085 r
->u
.group_icon
= first
;
1086 r
->res_info
= *resinfo
;
1089 /* Define a menu resource. */
1092 define_menu (id
, resinfo
, menuitems
)
1094 const struct res_res_info
*resinfo
;
1095 struct menuitem
*menuitems
;
1098 struct res_resource
*r
;
1100 m
= (struct menu
*) res_alloc (sizeof *m
);
1101 m
->items
= menuitems
;
1104 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1105 r
->type
= RES_TYPE_MENU
;
1107 r
->res_info
= *resinfo
;
1110 /* Define a menu item. This does not define a resource, but merely
1111 allocates and fills in a structure. */
1114 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
1118 unsigned long state
;
1120 struct menuitem
*menuitems
;
1122 struct menuitem
*mi
;
1124 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1132 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1134 mi
->popup
= menuitems
;
1138 /* Define a messagetable resource. */
1141 define_messagetable (id
, resinfo
, filename
)
1143 const struct res_res_info
*resinfo
;
1144 const char *filename
;
1147 char *real_filename
;
1149 unsigned char *data
;
1150 struct res_resource
*r
;
1152 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1155 if (stat (real_filename
, &s
) < 0)
1156 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1159 data
= (unsigned char *) res_alloc (s
.st_size
);
1161 get_data (e
, data
, s
.st_size
, real_filename
);
1164 free (real_filename
);
1166 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1167 resinfo
->language
, 0);
1169 r
->type
= RES_TYPE_MESSAGETABLE
;
1170 r
->u
.data
.length
= s
.st_size
;
1171 r
->u
.data
.data
= data
;
1172 r
->res_info
= *resinfo
;
1175 /* Define an rcdata resource. */
1178 define_rcdata (id
, resinfo
, data
)
1180 const struct res_res_info
*resinfo
;
1181 struct rcdata_item
*data
;
1183 struct res_resource
*r
;
1185 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1186 resinfo
->language
, 0);
1187 r
->type
= RES_TYPE_RCDATA
;
1189 r
->res_info
= *resinfo
;
1192 /* Create an rcdata item holding a string. */
1194 struct rcdata_item
*
1195 define_rcdata_string (string
, len
)
1199 struct rcdata_item
*ri
;
1202 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1204 ri
->type
= RCDATA_STRING
;
1205 ri
->u
.string
.length
= len
;
1206 s
= (char *) res_alloc (len
);
1207 memcpy (s
, string
, len
);
1213 /* Create an rcdata item holding a number. */
1215 struct rcdata_item
*
1216 define_rcdata_number (val
, dword
)
1220 struct rcdata_item
*ri
;
1222 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1224 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1230 /* Define a stringtable resource. This is called for each string
1231 which appears in a STRINGTABLE statement. */
1234 define_stringtable (resinfo
, stringid
, string
)
1235 const struct res_res_info
*resinfo
;
1236 unsigned long stringid
;
1240 struct res_resource
*r
;
1243 id
.u
.id
= (stringid
>> 4) + 1;
1244 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1245 resinfo
->language
, 1);
1247 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1251 r
->type
= RES_TYPE_STRINGTABLE
;
1252 r
->u
.stringtable
= ((struct stringtable
*)
1253 res_alloc (sizeof (struct stringtable
)));
1254 for (i
= 0; i
< 16; i
++)
1256 r
->u
.stringtable
->strings
[i
].length
= 0;
1257 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1260 r
->res_info
= *resinfo
;
1263 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1264 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1268 /* Define a user data resource where the data is in the rc file. */
1271 define_user_data (id
, type
, resinfo
, data
)
1274 const struct res_res_info
*resinfo
;
1275 struct rcdata_item
*data
;
1277 struct res_id ids
[3];
1278 struct res_resource
*r
;
1283 ids
[2].u
.id
= resinfo
->language
;
1285 r
= define_resource (&resources
, 3, ids
, 0);
1286 r
->type
= RES_TYPE_USERDATA
;
1287 r
->u
.userdata
= data
;
1288 r
->res_info
= *resinfo
;
1291 /* Define a user data resource where the data is in a file. */
1294 define_user_file (id
, type
, resinfo
, filename
)
1297 const struct res_res_info
*resinfo
;
1298 const char *filename
;
1301 char *real_filename
;
1303 unsigned char *data
;
1304 struct res_id ids
[3];
1305 struct res_resource
*r
;
1307 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1309 if (stat (real_filename
, &s
) < 0)
1310 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1313 data
= (unsigned char *) res_alloc (s
.st_size
);
1315 get_data (e
, data
, s
.st_size
, real_filename
);
1318 free (real_filename
);
1323 ids
[2].u
.id
= resinfo
->language
;
1325 r
= define_resource (&resources
, 3, ids
, 0);
1326 r
->type
= RES_TYPE_USERDATA
;
1327 r
->u
.userdata
= ((struct rcdata_item
*)
1328 res_alloc (sizeof (struct rcdata_item
)));
1329 r
->u
.userdata
->next
= NULL
;
1330 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1331 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1332 r
->u
.userdata
->u
.buffer
.data
= data
;
1333 r
->res_info
= *resinfo
;
1336 /* Define a versioninfo resource. */
1339 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1342 struct fixed_versioninfo
*fixedverinfo
;
1343 struct ver_info
*verinfo
;
1345 struct res_resource
*r
;
1347 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1348 r
->type
= RES_TYPE_VERSIONINFO
;
1349 r
->u
.versioninfo
= ((struct versioninfo
*)
1350 res_alloc (sizeof (struct versioninfo
)));
1351 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1352 r
->u
.versioninfo
->var
= verinfo
;
1353 r
->res_info
.language
= language
;
1356 /* Add string version info to a list of version information. */
1359 append_ver_stringfileinfo (verinfo
, language
, strings
)
1360 struct ver_info
*verinfo
;
1361 const char *language
;
1362 struct ver_stringinfo
*strings
;
1364 struct ver_info
*vi
, **pp
;
1366 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1368 vi
->type
= VERINFO_STRING
;
1369 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1370 vi
->u
.string
.strings
= strings
;
1372 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1379 /* Add variable version info to a list of version information. */
1382 append_ver_varfileinfo (verinfo
, key
, var
)
1383 struct ver_info
*verinfo
;
1385 struct ver_varinfo
*var
;
1387 struct ver_info
*vi
, **pp
;
1389 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1391 vi
->type
= VERINFO_VAR
;
1392 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1393 vi
->u
.var
.var
= var
;
1395 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1402 /* Append version string information to a list. */
1404 struct ver_stringinfo
*
1405 append_verval (strings
, key
, value
)
1406 struct ver_stringinfo
*strings
;
1410 struct ver_stringinfo
*vs
, **pp
;
1412 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1414 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1415 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1417 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1424 /* Append version variable information to a list. */
1426 struct ver_varinfo
*
1427 append_vertrans (var
, language
, charset
)
1428 struct ver_varinfo
*var
;
1429 unsigned long language
;
1430 unsigned long charset
;
1432 struct ver_varinfo
*vv
, **pp
;
1434 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1436 vv
->language
= language
;
1437 vv
->charset
= charset
;
1439 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1446 /* Local functions used to write out an rc file. */
1448 static void indent
PARAMS ((FILE *, int));
1449 static void write_rc_directory
1450 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1451 const struct res_id
*, int *, int));
1452 static void write_rc_subdir
1453 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1454 const struct res_id
*, int *, int));
1455 static void write_rc_resource
1456 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1457 const struct res_resource
*, int *));
1458 static void write_rc_accelerators
1459 PARAMS ((FILE *, const struct accelerator
*));
1460 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1461 static void write_rc_group_cursor
1462 PARAMS ((FILE *, const struct group_cursor
*));
1463 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1464 static void write_rc_dialog_control
1465 PARAMS ((FILE *, const struct dialog_control
*));
1466 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1467 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1468 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1469 static void write_rc_menuitems
1470 PARAMS ((FILE *, const struct menuitem
*, int, int));
1471 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1472 static void write_rc_stringtable
1473 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1474 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1475 static void write_rc_filedata
1476 PARAMS ((FILE *, unsigned long, const unsigned char *));
1478 /* Indent a given number of spaces. */
1487 for (i
= 0; i
< c
; i
++)
1491 /* Dump the resources we have read in the format of an rc file.
1493 Actually, we don't use the format of an rc file, because it's way
1494 too much of a pain--for example, we'd have to write icon resources
1495 into a file and refer to that file. We just generate a readable
1496 format that kind of looks like an rc file, and is useful for
1497 understanding the contents of a resource file. Someday we may want
1498 to generate an rc file which the rc compiler can read; if that day
1499 comes, this code will have to be fixed up. */
1502 write_rc_file (filename
, resources
)
1503 const char *filename
;
1504 const struct res_directory
*resources
;
1509 if (filename
== NULL
)
1513 e
= fopen (filename
, FOPEN_WT
);
1515 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1519 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1520 (const struct res_id
*) NULL
, &language
, 1);
1523 /* Write out a directory. E is the file to write to. RD is the
1524 directory. TYPE is a pointer to the level 1 ID which serves as the
1525 resource type. NAME is a pointer to the level 2 ID which serves as
1526 an individual resource name. LANGUAGE is a pointer to the current
1527 language. LEVEL is the level in the tree. */
1530 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1532 const struct res_directory
*rd
;
1533 const struct res_id
*type
;
1534 const struct res_id
*name
;
1538 const struct res_entry
*re
;
1540 /* Print out some COFF information that rc files can't represent. */
1543 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1544 if (rd
->characteristics
!= 0)
1545 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1546 if (rd
->major
!= 0 || rd
->minor
!= 0)
1547 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1549 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1554 /* If we're at level 1, the key of this resource is the
1555 type. This normally duplicates the information we have
1556 stored with the resource itself, but we need to remember
1557 the type if this is a user define resource type. */
1562 /* If we're at level 2, the key of this resource is the name
1563 we are going to use in the rc printout. */
1568 /* If we're at level 3, then this key represents a language.
1569 Use it to update the current language. */
1571 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1572 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1574 fprintf (e
, "LANGUAGE %lu, %lu\n",
1575 re
->id
.u
.id
& 0xff, (re
->id
.u
.id
>> 8) & 0xff);
1576 *language
= re
->id
.u
.id
;
1585 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1590 /* This is the normal case: the three levels are
1591 TYPE/NAME/LANGUAGE. NAME will have been set at level
1592 2, and represents the name to use. We probably just
1593 set LANGUAGE, and it will probably match what the
1594 resource itself records if anything. */
1595 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1599 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1600 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1607 /* Write out a subdirectory entry. E is the file to write to. RE is
1608 the subdirectory entry. TYPE and NAME are pointers to higher level
1609 IDs, or NULL. LANGUAGE is a pointer to the current language.
1610 LEVEL is the level in the tree. */
1613 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1615 const struct res_entry
*re
;
1616 const struct res_id
*type
;
1617 const struct res_id
*name
;
1625 fprintf (e
, "// Type: ");
1627 res_id_print (e
, re
->id
, 1);
1632 switch (re
->id
.u
.id
)
1634 case RT_CURSOR
: s
= "cursor"; break;
1635 case RT_BITMAP
: s
= "bitmap"; break;
1636 case RT_ICON
: s
= "icon"; break;
1637 case RT_MENU
: s
= "menu"; break;
1638 case RT_DIALOG
: s
= "dialog"; break;
1639 case RT_STRING
: s
= "stringtable"; break;
1640 case RT_FONTDIR
: s
= "fontdir"; break;
1641 case RT_FONT
: s
= "font"; break;
1642 case RT_ACCELERATOR
: s
= "accelerators"; break;
1643 case RT_RCDATA
: s
= "rcdata"; break;
1644 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1645 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1646 case RT_GROUP_ICON
: s
= "group icon"; break;
1647 case RT_VERSION
: s
= "version"; break;
1648 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1649 case RT_PLUGPLAY
: s
= "plugplay"; break;
1650 case RT_VXD
: s
= "vxd"; break;
1651 case RT_ANICURSOR
: s
= "anicursor"; break;
1652 case RT_ANIICON
: s
= "aniicon"; break;
1653 default: s
= NULL
; break;
1657 fprintf (e
, "%s", s
);
1659 res_id_print (e
, re
->id
, 1);
1665 fprintf (e
, "// Name: ");
1666 res_id_print (e
, re
->id
, 1);
1671 fprintf (e
, "// Language: ");
1672 res_id_print (e
, re
->id
, 1);
1677 fprintf (e
, "// Level %d: ", level
);
1678 res_id_print (e
, re
->id
, 1);
1682 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1685 /* Write out a single resource. E is the file to write to. TYPE is a
1686 pointer to the type of the resource. NAME is a pointer to the name
1687 of the resource; it will be NULL if there is a level mismatch. RES
1688 is the resource data. LANGUAGE is a pointer to the current
1692 write_rc_resource (e
, type
, name
, res
, language
)
1694 const struct res_id
*type
;
1695 const struct res_id
*name
;
1696 const struct res_resource
*res
;
1710 case RES_TYPE_ACCELERATOR
:
1712 rt
= RT_ACCELERATOR
;
1715 case RES_TYPE_BITMAP
:
1720 case RES_TYPE_CURSOR
:
1725 case RES_TYPE_GROUP_CURSOR
:
1727 rt
= RT_GROUP_CURSOR
;
1730 case RES_TYPE_DIALOG
:
1731 if (extended_dialog (res
->u
.dialog
))
1743 case RES_TYPE_FONTDIR
:
1753 case RES_TYPE_GROUP_ICON
:
1759 if (extended_menu (res
->u
.menu
))
1772 case RES_TYPE_MESSAGETABLE
:
1774 rt
= RT_MESSAGETABLE
;
1777 case RES_TYPE_RCDATA
:
1782 case RES_TYPE_STRINGTABLE
:
1787 case RES_TYPE_USERDATA
:
1792 case RES_TYPE_VERSIONINFO
:
1800 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1802 fprintf (e
, "// Unexpected resource type mismatch: ");
1803 res_id_print (e
, *type
, 1);
1804 fprintf (e
, " != %d", rt
);
1807 if (res
->coff_info
.codepage
!= 0)
1808 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1809 if (res
->coff_info
.reserved
!= 0)
1810 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1813 res_id_print (e
, *name
, 0);
1815 fprintf (e
, "??Unknown-Name??");
1819 fprintf (e
, "%s", s
);
1820 else if (type
!= NULL
)
1821 res_id_print (e
, *type
, 0);
1823 fprintf (e
, "??Unknown-Type??");
1825 if (res
->res_info
.memflags
!= 0)
1827 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1828 fprintf (e
, " MOVEABLE");
1829 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1830 fprintf (e
, " PURE");
1831 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1832 fprintf (e
, " PRELOAD");
1833 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1834 fprintf (e
, " DISCARDABLE");
1837 if (res
->type
== RES_TYPE_DIALOG
)
1839 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1840 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1841 if (res
->u
.dialog
->ex
!= NULL
1842 && res
->u
.dialog
->ex
->help
!= 0)
1843 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1848 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1849 || res
->res_info
.characteristics
!= 0
1850 || res
->res_info
.version
!= 0)
1856 case RES_TYPE_ACCELERATOR
:
1857 case RES_TYPE_DIALOG
:
1859 case RES_TYPE_RCDATA
:
1860 case RES_TYPE_STRINGTABLE
:
1869 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1870 fprintf (e
, "%sLANGUAGE %d, %d\n",
1871 modifiers
? "// " : "",
1872 res
->res_info
.language
& 0xff,
1873 (res
->res_info
.language
>> 8) & 0xff);
1874 if (res
->res_info
.characteristics
!= 0)
1875 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1876 modifiers
? "// " : "",
1877 res
->res_info
.characteristics
);
1878 if (res
->res_info
.version
!= 0)
1879 fprintf (e
, "%sVERSION %lu\n",
1880 modifiers
? "// " : "",
1881 res
->res_info
.version
);
1889 case RES_TYPE_ACCELERATOR
:
1890 write_rc_accelerators (e
, res
->u
.acc
);
1893 case RES_TYPE_CURSOR
:
1894 write_rc_cursor (e
, res
->u
.cursor
);
1897 case RES_TYPE_GROUP_CURSOR
:
1898 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1901 case RES_TYPE_DIALOG
:
1902 write_rc_dialog (e
, res
->u
.dialog
);
1905 case RES_TYPE_FONTDIR
:
1906 write_rc_fontdir (e
, res
->u
.fontdir
);
1909 case RES_TYPE_GROUP_ICON
:
1910 write_rc_group_icon (e
, res
->u
.group_icon
);
1914 write_rc_menu (e
, res
->u
.menu
, menuex
);
1917 case RES_TYPE_RCDATA
:
1918 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1921 case RES_TYPE_STRINGTABLE
:
1922 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1925 case RES_TYPE_USERDATA
:
1926 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1929 case RES_TYPE_VERSIONINFO
:
1930 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1933 case RES_TYPE_BITMAP
:
1936 case RES_TYPE_MESSAGETABLE
:
1937 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1942 /* Write out accelerator information. */
1945 write_rc_accelerators (e
, accelerators
)
1947 const struct accelerator
*accelerators
;
1949 const struct accelerator
*acc
;
1951 fprintf (e
, "BEGIN\n");
1952 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1958 if ((acc
->key
& 0x7f) == acc
->key
1959 && isprint ((unsigned char) acc
->key
)
1960 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1962 fprintf (e
, "\"%c\"", acc
->key
);
1967 fprintf (e
, "%d", acc
->key
);
1971 fprintf (e
, ", %d", acc
->id
);
1975 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1976 fprintf (e
, ", VIRTKEY");
1978 fprintf (e
, ", ASCII");
1981 if ((acc
->flags
& ACC_SHIFT
) != 0)
1982 fprintf (e
, ", SHIFT");
1983 if ((acc
->flags
& ACC_CONTROL
) != 0)
1984 fprintf (e
, ", CONTROL");
1985 if ((acc
->flags
& ACC_ALT
) != 0)
1986 fprintf (e
, ", ALT");
1991 fprintf (e
, "END\n");
1994 /* Write out cursor information. This would normally be in a separate
1995 file, which the rc file would include. */
1998 write_rc_cursor (e
, cursor
)
2000 const struct cursor
*cursor
;
2002 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
2004 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
2007 /* Write out group cursor data. This would normally be built from the
2011 write_rc_group_cursor (e
, group_cursor
)
2013 const struct group_cursor
*group_cursor
;
2015 const struct group_cursor
*gc
;
2017 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
2019 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
2020 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
2021 fprintf (e
, "// data bytes: %lu; index: %d\n",
2022 gc
->bytes
, gc
->index
);
2026 /* Write dialog data. */
2029 write_rc_dialog (e
, dialog
)
2031 const struct dialog
*dialog
;
2033 const struct dialog_control
*control
;
2035 if (dialog
->style
!= 0)
2036 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
2037 if (dialog
->exstyle
!= 0)
2038 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
2039 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2040 || dialog
->class.u
.id
!= 0)
2042 fprintf (e
, "CLASS ");
2043 res_id_print (e
, dialog
->class, 0);
2046 if (dialog
->caption
!= NULL
)
2048 fprintf (e
, "CAPTION \"");
2049 unicode_print (e
, dialog
->caption
, -1);
2050 fprintf (e
, "\"\n");
2052 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2053 || dialog
->menu
.u
.id
!= 0)
2055 fprintf (e
, "MENU ");
2056 res_id_print (e
, dialog
->menu
, 0);
2059 if (dialog
->font
!= NULL
)
2061 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
2062 unicode_print (e
, dialog
->font
, -1);
2064 if (dialog
->ex
!= NULL
2065 && (dialog
->ex
->weight
!= 0 || dialog
->ex
->italic
!= 0))
2066 fprintf (e
, ", %d, %d", dialog
->ex
->weight
, dialog
->ex
->italic
);
2070 fprintf (e
, "BEGIN\n");
2072 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2073 write_rc_dialog_control (e
, control
);
2075 fprintf (e
, "END\n");
2078 /* For each predefined control keyword, this table provides the class
2084 unsigned short class;
2085 unsigned long style
;
2088 static const struct control_info control_info
[] =
2090 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2091 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2092 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2093 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2094 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2095 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2096 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2097 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2098 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2099 { "ICON", CTL_STATIC
, SS_ICON
},
2100 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2101 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2102 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2103 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2104 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2105 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2106 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2107 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2108 /* It's important that USERBUTTON come after all the other button
2109 types, so that it won't be matched too early. */
2110 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2114 /* Write a dialog control. */
2117 write_rc_dialog_control (e
, control
)
2119 const struct dialog_control
*control
;
2121 const struct control_info
*ci
;
2125 if (control
->class.named
)
2129 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2130 if (ci
->class == control
->class.u
.id
2131 && (ci
->style
== (unsigned long) -1
2132 || ci
->style
== (control
->style
& 0xff)))
2136 fprintf (e
, "CONTROL");
2137 else if (ci
->name
!= NULL
)
2138 fprintf (e
, "%s", ci
->name
);
2140 fprintf (e
, "CONTROL");
2142 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2145 res_id_print (e
, control
->text
, 1);
2149 fprintf (e
, " %d, ", control
->id
);
2153 if (control
->class.named
)
2155 res_id_print (e
, control
->class, 0);
2156 if (control
->class.named
)
2158 fprintf (e
, ", 0x%lx, ", control
->style
);
2161 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2163 if (control
->style
!= SS_ICON
2164 || control
->exstyle
!= 0
2165 || control
->width
!= 0
2166 || control
->height
!= 0
2167 || control
->help
!= 0)
2169 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2171 /* FIXME: We don't need to print the style if it is the default.
2172 More importantly, in certain cases we actually need to turn
2173 off parts of the forced style, by using NOT. */
2174 fprintf (e
, ", 0x%lx", control
->style
);
2176 if (control
->exstyle
!= 0 || control
->help
!= 0)
2177 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2182 if (control
->data
!= NULL
)
2183 write_rc_rcdata (e
, control
->data
, 2);
2186 /* Write out font directory data. This would normally be built from
2190 write_rc_fontdir (e
, fontdir
)
2192 const struct fontdir
*fontdir
;
2194 const struct fontdir
*fc
;
2196 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2198 fprintf (e
, "// Font index: %d\n", fc
->index
);
2199 write_rc_filedata (e
, fc
->length
, fc
->data
);
2203 /* Write out group icon data. This would normally be built from the
2207 write_rc_group_icon (e
, group_icon
)
2209 const struct group_icon
*group_icon
;
2211 const struct group_icon
*gi
;
2213 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2215 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2216 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2217 fprintf (e
, "// data bytes: %lu; index: %d\n",
2218 gi
->bytes
, gi
->index
);
2222 /* Write out a menu resource. */
2225 write_rc_menu (e
, menu
, menuex
)
2227 const struct menu
*menu
;
2230 if (menu
->help
!= 0)
2231 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2232 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2235 /* Write out menuitems. */
2238 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
2240 const struct menuitem
*menuitems
;
2244 const struct menuitem
*mi
;
2247 fprintf (e
, "BEGIN\n");
2249 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2251 indent (e
, ind
+ 2);
2253 if (mi
->popup
== NULL
)
2254 fprintf (e
, "MENUITEM");
2256 fprintf (e
, "POPUP");
2259 && mi
->popup
== NULL
2264 fprintf (e
, " SEPARATOR\n");
2268 if (mi
->text
== NULL
)
2269 fprintf (e
, " \"\"");
2273 unicode_print (e
, mi
->text
, -1);
2279 if (mi
->popup
== NULL
)
2280 fprintf (e
, ", %d", mi
->id
);
2282 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2283 fprintf (e
, ", CHECKED");
2284 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2285 fprintf (e
, ", GRAYED");
2286 if ((mi
->type
& MENUITEM_HELP
) != 0)
2287 fprintf (e
, ", HELP");
2288 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2289 fprintf (e
, ", INACTIVE");
2290 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2291 fprintf (e
, ", MENUBARBREAK");
2292 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2293 fprintf (e
, ", MENUBREAK");
2297 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2299 fprintf (e
, ", %d", mi
->id
);
2300 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2302 fprintf (e
, ", %lu", mi
->type
);
2303 if (mi
->state
!= 0 || mi
->help
!= 0)
2305 fprintf (e
, ", %lu", mi
->state
);
2307 fprintf (e
, ", %lu", mi
->help
);
2315 if (mi
->popup
!= NULL
)
2316 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2320 fprintf (e
, "END\n");
2323 /* Write out an rcdata resource. This is also used for other types of
2324 resources that need to print arbitrary data. */
2327 write_rc_rcdata (e
, rcdata
, ind
)
2329 const struct rcdata_item
*rcdata
;
2332 const struct rcdata_item
*ri
;
2335 fprintf (e
, "BEGIN\n");
2337 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2339 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2342 indent (e
, ind
+ 2);
2350 fprintf (e
, "%d", ri
->u
.word
);
2354 fprintf (e
, "%luL", ri
->u
.dword
);
2364 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2366 if (isprint ((unsigned char) *s
))
2369 fprintf (e
, "\\%03o", *s
);
2375 case RCDATA_WSTRING
:
2377 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2386 /* Assume little endian data. */
2389 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2395 indent (e
, ind
+ 2);
2396 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2397 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2398 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2399 | ri
->u
.buffer
.data
[i
]);
2400 fprintf (e
, "%luL", l
);
2401 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2403 for (j
= 0; j
< 4; ++j
)
2404 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2405 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2409 fprintf (e
, "\t// ");
2410 for (j
= 0; j
< 4; ++j
)
2412 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2413 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2416 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2418 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2426 if (i
+ 1 < ri
->u
.buffer
.length
)
2432 indent (e
, ind
+ 2);
2433 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2434 fprintf (e
, "%d", s
);
2435 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2437 for (j
= 0; j
< 2; ++j
)
2438 if (! isprint (ri
->u
.buffer
.data
[i
+ j
])
2439 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2443 fprintf (e
, "\t// ");
2444 for (j
= 0; j
< 2; ++j
)
2446 if (! isprint (ri
->u
.buffer
.data
[i
+ j
]))
2447 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2450 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2452 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2461 if (i
< ri
->u
.buffer
.length
)
2464 indent (e
, ind
+ 2);
2465 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2466 && isprint (ri
->u
.buffer
.data
[i
]))
2467 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2469 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2470 if (ri
->next
!= NULL
)
2480 if (ri
->type
!= RCDATA_BUFFER
)
2482 if (ri
->next
!= NULL
)
2489 fprintf (e
, "END\n");
2492 /* Write out a stringtable resource. */
2495 write_rc_stringtable (e
, name
, stringtable
)
2497 const struct res_id
*name
;
2498 const struct stringtable
*stringtable
;
2500 unsigned long offset
;
2503 if (name
!= NULL
&& ! name
->named
)
2504 offset
= (name
->u
.id
- 1) << 4;
2507 fprintf (e
, "// %s string table name\n",
2508 name
== NULL
? "Missing" : "Invalid");
2512 fprintf (e
, "BEGIN\n");
2514 for (i
= 0; i
< 16; i
++)
2516 if (stringtable
->strings
[i
].length
!= 0)
2518 fprintf (e
, " %lu, \"", offset
+ i
);
2519 unicode_print (e
, stringtable
->strings
[i
].string
,
2520 stringtable
->strings
[i
].length
);
2521 fprintf (e
, "\"\n");
2525 fprintf (e
, "END\n");
2528 /* Write out a versioninfo resource. */
2531 write_rc_versioninfo (e
, versioninfo
)
2533 const struct versioninfo
*versioninfo
;
2535 const struct fixed_versioninfo
*f
;
2536 const struct ver_info
*vi
;
2538 f
= versioninfo
->fixed
;
2539 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2540 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2541 (f
->file_version_ms
>> 16) & 0xffff,
2542 f
->file_version_ms
& 0xffff,
2543 (f
->file_version_ls
>> 16) & 0xffff,
2544 f
->file_version_ls
& 0xffff);
2545 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2546 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2547 (f
->product_version_ms
>> 16) & 0xffff,
2548 f
->product_version_ms
& 0xffff,
2549 (f
->product_version_ls
>> 16) & 0xffff,
2550 f
->product_version_ls
& 0xffff);
2551 if (f
->file_flags_mask
!= 0)
2552 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2553 if (f
->file_flags
!= 0)
2554 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2555 if (f
->file_os
!= 0)
2556 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2557 if (f
->file_type
!= 0)
2558 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2559 if (f
->file_subtype
!= 0)
2560 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2561 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2562 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2564 fprintf (e
, "BEGIN\n");
2566 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2570 case VERINFO_STRING
:
2572 const struct ver_stringinfo
*vs
;
2574 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2575 fprintf (e
, " BEGIN\n");
2576 fprintf (e
, " BLOCK \"");
2577 unicode_print (e
, vi
->u
.string
.language
, -1);
2578 fprintf (e
, "\"\n");
2579 fprintf (e
, " BEGIN\n");
2581 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2583 fprintf (e
, " VALUE \"");
2584 unicode_print (e
, vs
->key
, -1);
2585 fprintf (e
, "\", \"");
2586 unicode_print (e
, vs
->value
, -1);
2587 fprintf (e
, "\"\n");
2590 fprintf (e
, " END\n");
2591 fprintf (e
, " END\n");
2597 const struct ver_varinfo
*vv
;
2599 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2600 fprintf (e
, " BEGIN\n");
2601 fprintf (e
, " VALUE \"");
2602 unicode_print (e
, vi
->u
.var
.key
, -1);
2605 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2606 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2609 fprintf (e
, "\n END\n");
2616 fprintf (e
, "END\n");
2619 /* Write out data which would normally be read from a file. */
2622 write_rc_filedata (e
, length
, data
)
2624 unsigned long length
;
2625 const unsigned char *data
;
2629 for (i
= 0; i
+ 15 < length
; i
+= 16)
2631 fprintf (e
, "// %4lx: ", i
);
2632 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2633 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2634 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2635 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2636 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2637 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2642 fprintf (e
, "// %4lx:", i
);
2645 fprintf (e
, " %02x", data
[i
]);