1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 /* This file contains functions that read and write Windows rc files.
23 These are text files that represent resources. */
27 #include "libiberty.h"
28 #include "safe-ctype.h"
38 #ifdef HAVE_SYS_WAIT_H
40 #else /* ! HAVE_SYS_WAIT_H */
41 #if ! defined (_WIN32) || defined (__CYGWIN__)
43 #define WIFEXITED(w) (((w)&0377) == 0)
46 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
49 #define WTERMSIG(w) ((w) & 0177)
52 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
54 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
56 #define WIFEXITED(w) (((w) & 0xff) == 0)
59 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
62 #define WTERMSIG(w) ((w) & 0x7f)
65 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
67 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
68 #endif /* ! HAVE_SYS_WAIT_H */
71 #define STDOUT_FILENO 1
74 #if defined (_WIN32) && ! defined (__CYGWIN__)
76 #define pclose _pclose
79 /* The default preprocessor. */
81 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
83 /* We read the directory entries in a cursor or icon file into
84 instances of this structure. */
90 /* Height of image. */
92 /* Number of colors in image. */
93 unsigned char colorcount
;
99 unsigned short planes
;
100 /* Bits per pixel. */
105 /* X coordinate of hotspot. */
106 unsigned short xhotspot
;
107 /* Y coordinate of hotspot. */
108 unsigned short yhotspot
;
111 /* Bytes in image. */
113 /* File offset of image. */
114 unsigned long offset
;
117 /* The name of the rc file we are reading. */
121 /* The line number in the rc file. */
125 /* The pipe we are reading from, so that we can close it if we exit. */
127 static FILE *cpp_pipe
;
129 /* The temporary file used if we're not using popen, so we can delete it
132 static char *cpp_temp_file
;
134 /* Input stream is either a file or a pipe. */
136 static enum {ISTREAM_PIPE
, ISTREAM_FILE
} istream_type
;
138 /* As we read the rc file, we attach information to this structure. */
140 static struct res_directory
*resources
;
142 /* The number of cursor resources we have written out. */
146 /* The number of font resources we have written out. */
150 /* Font directory information. */
152 struct fontdir
*fontdirs
;
154 /* Resource info to use for fontdirs. */
156 struct res_res_info fontdirs_resinfo
;
158 /* The number of icon resources we have written out. */
162 /* Local functions. */
164 static int run_cmd
PARAMS ((char *, const char *));
165 static FILE *open_input_stream
PARAMS ((char *));
166 static FILE *look_for_default
PARAMS ((char *, const char *, int,
167 const char *, const char *));
168 static void close_input_stream
PARAMS ((void));
169 static void unexpected_eof
PARAMS ((const char *));
170 static int get_word
PARAMS ((FILE *, const char *));
171 static unsigned long get_long
PARAMS ((FILE *, const char *));
173 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
174 static void define_fontdirs
PARAMS ((void));
176 /* Run `cmd' and redirect the output to `redir'. */
184 int pid
, wait_status
, retcode
;
187 char *errmsg_fmt
, *errmsg_arg
;
188 char *temp_base
= choose_temp_base ();
191 int redir_handle
= -1;
192 int stdout_save
= -1;
194 /* Count the args. */
197 for (s
= cmd
; *s
; s
++)
202 argv
= alloca (sizeof (char *) * (i
+ 3));
208 while (*s
== ' ' && *s
!= 0)
214 in_quote
= (*s
== '\'' || *s
== '"');
215 sep
= (in_quote
) ? *s
++ : ' ';
218 while (*s
!= sep
&& *s
!= 0)
231 /* Setup the redirection. We can't use the usual fork/exec and redirect
232 since we may be running on non-POSIX Windows host. */
237 /* Open temporary output file. */
238 redir_handle
= open (redir
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
239 if (redir_handle
== -1)
240 fatal (_("can't open temporary file `%s': %s"), redir
,
243 /* Duplicate the stdout file handle so it can be restored later. */
244 stdout_save
= dup (STDOUT_FILENO
);
245 if (stdout_save
== -1)
246 fatal (_("can't redirect stdout: `%s': %s"), redir
, strerror (errno
));
248 /* Redirect stdout to our output file. */
249 dup2 (redir_handle
, STDOUT_FILENO
);
251 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
252 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
254 /* Restore stdout to its previous setting. */
255 dup2 (stdout_save
, STDOUT_FILENO
);
257 /* Close reponse file. */
258 close (redir_handle
);
262 fatal (_("%s %s: %s"), errmsg_fmt
, errmsg_arg
, strerror (errno
));
267 pid
= pwait (pid
, &wait_status
, 0);
271 fatal (_("wait: %s"), strerror (errno
));
274 else if (WIFSIGNALED (wait_status
))
276 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status
));
279 else if (WIFEXITED (wait_status
))
281 if (WEXITSTATUS (wait_status
) != 0)
283 fatal (_("%s exited with status %d"), cmd
,
284 WEXITSTATUS (wait_status
));
295 open_input_stream (cmd
)
298 if (istream_type
== ISTREAM_FILE
)
302 fileprefix
= choose_temp_base ();
303 cpp_temp_file
= (char *) xmalloc (strlen (fileprefix
) + 5);
304 sprintf (cpp_temp_file
, "%s.irc", fileprefix
);
307 if (run_cmd (cmd
, cpp_temp_file
))
308 fatal (_("can't execute `%s': %s"), cmd
, strerror (errno
));
310 cpp_pipe
= fopen (cpp_temp_file
, FOPEN_RT
);;
311 if (cpp_pipe
== NULL
)
312 fatal (_("can't open temporary file `%s': %s"),
313 cpp_temp_file
, strerror (errno
));
317 _("Using temporary file `%s' to read preprocessor output\n"),
322 cpp_pipe
= popen (cmd
, FOPEN_RT
);
323 if (cpp_pipe
== NULL
)
324 fatal (_("can't popen `%s': %s"), cmd
, strerror (errno
));
326 fprintf (stderr
, _("Using popen to read preprocessor output\n"));
329 xatexit (close_input_stream
);
333 /* look for the preprocessor program */
336 look_for_default (cmd
, prefix
, end_prefix
, preprocargs
, filename
)
340 const char *preprocargs
;
341 const char *filename
;
347 strcpy (cmd
, prefix
);
349 sprintf (cmd
+ end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
350 space
= strchr (cmd
+ end_prefix
, ' ');
355 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
356 strchr (cmd
, '\\') ||
360 found
= (stat (cmd
, &s
) == 0
361 #ifdef HAVE_EXECUTABLE_SUFFIX
362 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
369 fprintf (stderr
, _("Tried `%s'\n"), cmd
);
374 strcpy (cmd
, prefix
);
376 sprintf (cmd
+ end_prefix
, "%s %s %s",
377 DEFAULT_PREPROCESSOR
, preprocargs
, filename
);
380 fprintf (stderr
, _("Using `%s'\n"), cmd
);
382 cpp_pipe
= open_input_stream (cmd
);
386 /* Read an rc file. */
388 struct res_directory
*
389 read_rc_file (filename
, preprocessor
, preprocargs
, language
, use_temp_file
)
390 const char *filename
;
391 const char *preprocessor
;
392 const char *preprocargs
;
398 istream_type
= (use_temp_file
) ? ISTREAM_FILE
: ISTREAM_PIPE
;
400 if (preprocargs
== NULL
)
402 if (filename
== NULL
)
407 cmd
= xmalloc (strlen (preprocessor
)
408 + strlen (preprocargs
)
411 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
413 cpp_pipe
= open_input_stream (cmd
);
417 char *dash
, *slash
, *cp
;
419 preprocessor
= DEFAULT_PREPROCESSOR
;
421 cmd
= xmalloc (strlen (program_name
)
422 + strlen (preprocessor
)
423 + strlen (preprocargs
)
425 #ifdef HAVE_EXECUTABLE_SUFFIX
426 + strlen (EXECUTABLE_SUFFIX
)
432 for (cp
= program_name
; *cp
; cp
++)
437 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
438 *cp
== ':' || *cp
== '\\' ||
451 /* First, try looking for a prefixed gcc in the windres
452 directory, with the same prefix as windres */
454 cpp_pipe
= look_for_default (cmd
, program_name
, dash
-program_name
+1,
455 preprocargs
, filename
);
458 if (slash
&& !cpp_pipe
)
460 /* Next, try looking for a gcc in the same directory as
463 cpp_pipe
= look_for_default (cmd
, program_name
, slash
-program_name
+1,
464 preprocargs
, filename
);
469 /* Sigh, try the default */
471 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
478 rc_filename
= xstrdup (filename
);
481 rcparse_set_language (language
);
484 rcparse_discard_strings ();
486 close_input_stream ();
488 if (fontdirs
!= NULL
)
497 /* Close the input stream if it is open. */
500 close_input_stream ()
502 if (istream_type
== ISTREAM_FILE
)
504 if (cpp_pipe
!= NULL
)
507 if (cpp_temp_file
!= NULL
)
509 int errno_save
= errno
;
511 unlink (cpp_temp_file
);
513 free (cpp_temp_file
);
518 if (cpp_pipe
!= NULL
)
522 /* Since this is also run via xatexit, safeguard. */
524 cpp_temp_file
= NULL
;
527 /* Report an error while reading an rc file. */
533 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
536 /* Issue a warning while reading an rc file. */
539 rcparse_warning (msg
)
542 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
545 /* Die if we get an unexpected end of file. */
551 fatal (_("%s: unexpected EOF"), msg
);
554 /* Read a 16 bit word from a file. The data is assumed to be little
567 unexpected_eof (msg
);
568 return ((b2
& 0xff) << 8) | (b1
& 0xff);
571 /* Read a 32 bit word from a file. The data is assumed to be little
586 unexpected_eof (msg
);
587 return (((((((b4
& 0xff) << 8)
593 /* Read data from a file. This is a wrapper to do error checking. */
596 get_data (e
, p
, c
, msg
)
604 got
= fread (p
, 1, c
, e
);
608 fatal (_("%s: read of %lu returned %lu"), msg
, c
, got
);
611 /* Define an accelerator resource. */
614 define_accelerator (id
, resinfo
, data
)
616 const struct res_res_info
*resinfo
;
617 struct accelerator
*data
;
619 struct res_resource
*r
;
621 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
622 resinfo
->language
, 0);
623 r
->type
= RES_TYPE_ACCELERATOR
;
625 r
->res_info
= *resinfo
;
628 /* Define a bitmap resource. Bitmap data is stored in a file. The
629 first 14 bytes of the file are a standard header, which is not
630 included in the resource data. */
632 #define BITMAP_SKIP (14)
635 define_bitmap (id
, resinfo
, filename
)
637 const struct res_res_info
*resinfo
;
638 const char *filename
;
645 struct res_resource
*r
;
647 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
649 if (stat (real_filename
, &s
) < 0)
650 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
653 data
= (unsigned char *) res_alloc (s
.st_size
- BITMAP_SKIP
);
655 for (i
= 0; i
< BITMAP_SKIP
; i
++)
658 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
661 free (real_filename
);
663 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
664 resinfo
->language
, 0);
666 r
->type
= RES_TYPE_BITMAP
;
667 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
668 r
->u
.data
.data
= data
;
669 r
->res_info
= *resinfo
;
672 /* Define a cursor resource. A cursor file may contain a set of
673 bitmaps, each representing the same cursor at various different
674 resolutions. They each get written out with a different ID. The
675 real cursor resource is then a group resource which can be used to
676 select one of the actual cursors. */
679 define_cursor (id
, resinfo
, filename
)
681 const struct res_res_info
*resinfo
;
682 const char *filename
;
687 struct icondir
*icondirs
;
689 struct res_resource
*r
;
690 struct group_cursor
*first
, **pp
;
692 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
694 /* A cursor file is basically an icon file. The start of the file
695 is a three word structure. The first word is ignored. The
696 second word is the type of data. The third word is the number of
699 get_word (e
, real_filename
);
700 type
= get_word (e
, real_filename
);
701 count
= get_word (e
, real_filename
);
703 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
705 /* Read in the icon directory entries. */
707 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
709 for (i
= 0; i
< count
; i
++)
711 icondirs
[i
].width
= getc (e
);
712 icondirs
[i
].height
= getc (e
);
713 icondirs
[i
].colorcount
= getc (e
);
715 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
716 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
717 icondirs
[i
].bytes
= get_long (e
, real_filename
);
718 icondirs
[i
].offset
= get_long (e
, real_filename
);
721 unexpected_eof (real_filename
);
724 /* Define each cursor as a unique resource. */
726 first_cursor
= cursors
;
728 for (i
= 0; i
< count
; i
++)
734 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
735 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
736 icondirs
[i
].offset
, strerror (errno
));
738 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
740 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
742 c
= (struct cursor
*) res_alloc (sizeof *c
);
743 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
744 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
745 c
->length
= icondirs
[i
].bytes
;
753 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
754 resinfo
->language
, 0);
755 r
->type
= RES_TYPE_CURSOR
;
757 r
->res_info
= *resinfo
;
761 free (real_filename
);
763 /* Define a cursor group resource. */
767 for (i
= 0; i
< count
; i
++)
769 struct group_cursor
*cg
;
771 cg
= (struct group_cursor
*) res_alloc (sizeof *cg
);
773 cg
->width
= icondirs
[i
].width
;
774 cg
->height
= 2 * icondirs
[i
].height
;
776 /* FIXME: What should these be set to? */
780 cg
->bytes
= icondirs
[i
].bytes
+ 4;
781 cg
->index
= first_cursor
+ i
+ 1;
789 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
790 resinfo
->language
, 0);
791 r
->type
= RES_TYPE_GROUP_CURSOR
;
792 r
->u
.group_cursor
= first
;
793 r
->res_info
= *resinfo
;
796 /* Define a dialog resource. */
799 define_dialog (id
, resinfo
, dialog
)
801 const struct res_res_info
*resinfo
;
802 const struct dialog
*dialog
;
805 struct res_resource
*r
;
807 copy
= (struct dialog
*) res_alloc (sizeof *copy
);
810 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
811 resinfo
->language
, 0);
812 r
->type
= RES_TYPE_DIALOG
;
814 r
->res_info
= *resinfo
;
817 /* Define a dialog control. This does not define a resource, but
818 merely allocates and fills in a structure. */
820 struct dialog_control
*
821 define_control (iid
, id
, x
, y
, width
, height
, class, style
, exstyle
)
822 const struct res_id iid
;
827 unsigned long height
;
830 unsigned long exstyle
;
832 struct dialog_control
*n
;
834 n
= (struct dialog_control
*) res_alloc (sizeof *n
);
838 n
->exstyle
= exstyle
;
844 n
->class.u
.id
= class;
852 struct dialog_control
*
853 define_icon_control (iid
, id
, x
, y
, style
, exstyle
, help
, data
, ex
)
859 unsigned long exstyle
;
861 struct rcdata_item
*data
;
862 struct dialog_ex
*ex
;
864 struct dialog_control
*n
;
868 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
869 res_string_to_id (&tid
, "");
870 n
= define_control (tid
, id
, x
, y
, 0, 0, CTL_STATIC
, style
, exstyle
);
873 rcparse_warning (_("help ID requires DIALOGEX"));
875 rcparse_warning (_("control data requires DIALOGEX"));
882 /* Define a font resource. */
885 define_font (id
, resinfo
, filename
)
887 const struct res_res_info
*resinfo
;
888 const char *filename
;
894 struct res_resource
*r
;
897 unsigned char *fontdata
;
899 const char *device
, *face
;
902 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
904 if (stat (real_filename
, &s
) < 0)
905 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
908 data
= (unsigned char *) res_alloc (s
.st_size
);
910 get_data (e
, data
, s
.st_size
, real_filename
);
913 free (real_filename
);
915 r
= define_standard_resource (&resources
, RT_FONT
, id
,
916 resinfo
->language
, 0);
918 r
->type
= RES_TYPE_FONT
;
919 r
->u
.data
.length
= s
.st_size
;
920 r
->u
.data
.data
= data
;
921 r
->res_info
= *resinfo
;
923 /* For each font resource, we must add an entry in the FONTDIR
924 resource. The FONTDIR resource includes some strings in the font
925 file. To find them, we have to do some magic on the data we have
928 offset
= ((((((data
[47] << 8)
932 if (offset
> 0 && offset
< s
.st_size
)
933 device
= (char *) data
+ offset
;
937 offset
= ((((((data
[51] << 8)
941 if (offset
> 0 && offset
< s
.st_size
)
942 face
= (char *) data
+ offset
;
948 fontdatalength
= 58 + strlen (device
) + strlen (face
);
949 fontdata
= (unsigned char *) res_alloc (fontdatalength
);
950 memcpy (fontdata
, data
, 56);
951 strcpy ((char *) fontdata
+ 56, device
);
952 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
954 fd
= (struct fontdir
*) res_alloc (sizeof *fd
);
957 fd
->length
= fontdatalength
;
960 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
964 /* For the single fontdirs resource, we always use the resource
965 information of the last font. I don't know what else to do. */
966 fontdirs_resinfo
= *resinfo
;
969 /* Define the fontdirs resource. This is called after the entire rc
970 file has been parsed, if any font resources were seen. */
975 struct res_resource
*r
;
981 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
983 r
->type
= RES_TYPE_FONTDIR
;
984 r
->u
.fontdir
= fontdirs
;
985 r
->res_info
= fontdirs_resinfo
;
988 /* Define an icon resource. An icon file may contain a set of
989 bitmaps, each representing the same icon at various different
990 resolutions. They each get written out with a different ID. The
991 real icon resource is then a group resource which can be used to
992 select one of the actual icon bitmaps. */
995 define_icon (id
, resinfo
, filename
)
997 const struct res_res_info
*resinfo
;
998 const char *filename
;
1001 char *real_filename
;
1003 struct icondir
*icondirs
;
1005 struct res_resource
*r
;
1006 struct group_icon
*first
, **pp
;
1008 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
1010 /* The start of an icon file is a three word structure. The first
1011 word is ignored. The second word is the type of data. The third
1012 word is the number of entries. */
1014 get_word (e
, real_filename
);
1015 type
= get_word (e
, real_filename
);
1016 count
= get_word (e
, real_filename
);
1018 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1020 /* Read in the icon directory entries. */
1022 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1024 for (i
= 0; i
< count
; i
++)
1026 icondirs
[i
].width
= getc (e
);
1027 icondirs
[i
].height
= getc (e
);
1028 icondirs
[i
].colorcount
= getc (e
);
1030 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1031 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1032 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1033 icondirs
[i
].offset
= get_long (e
, real_filename
);
1036 unexpected_eof (real_filename
);
1039 /* Define each icon as a unique resource. */
1043 for (i
= 0; i
< count
; i
++)
1045 unsigned char *data
;
1048 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1049 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1050 icondirs
[i
].offset
, strerror (errno
));
1052 data
= (unsigned char *) res_alloc (icondirs
[i
].bytes
);
1054 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1061 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1062 resinfo
->language
, 0);
1063 r
->type
= RES_TYPE_ICON
;
1064 r
->u
.data
.length
= icondirs
[i
].bytes
;
1065 r
->u
.data
.data
= data
;
1066 r
->res_info
= *resinfo
;
1070 free (real_filename
);
1072 /* Define an icon group resource. */
1076 for (i
= 0; i
< count
; i
++)
1078 struct group_icon
*cg
;
1080 /* For some reason, at least in some files the planes and bits
1081 are zero. We instead set them from the color. This is
1084 cg
= (struct group_icon
*) res_alloc (sizeof *cg
);
1086 cg
->width
= icondirs
[i
].width
;
1087 cg
->height
= icondirs
[i
].height
;
1088 cg
->colors
= icondirs
[i
].colorcount
;
1092 while ((1 << cg
->bits
) < cg
->colors
)
1095 cg
->bytes
= icondirs
[i
].bytes
;
1096 cg
->index
= first_icon
+ i
+ 1;
1104 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1105 resinfo
->language
, 0);
1106 r
->type
= RES_TYPE_GROUP_ICON
;
1107 r
->u
.group_icon
= first
;
1108 r
->res_info
= *resinfo
;
1111 /* Define a menu resource. */
1114 define_menu (id
, resinfo
, menuitems
)
1116 const struct res_res_info
*resinfo
;
1117 struct menuitem
*menuitems
;
1120 struct res_resource
*r
;
1122 m
= (struct menu
*) res_alloc (sizeof *m
);
1123 m
->items
= menuitems
;
1126 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1127 r
->type
= RES_TYPE_MENU
;
1129 r
->res_info
= *resinfo
;
1132 /* Define a menu item. This does not define a resource, but merely
1133 allocates and fills in a structure. */
1136 define_menuitem (text
, menuid
, type
, state
, help
, menuitems
)
1140 unsigned long state
;
1142 struct menuitem
*menuitems
;
1144 struct menuitem
*mi
;
1146 mi
= (struct menuitem
*) res_alloc (sizeof *mi
);
1154 unicode_from_ascii ((int *) NULL
, &mi
->text
, text
);
1156 mi
->popup
= menuitems
;
1160 /* Define a messagetable resource. */
1163 define_messagetable (id
, resinfo
, filename
)
1165 const struct res_res_info
*resinfo
;
1166 const char *filename
;
1169 char *real_filename
;
1171 unsigned char *data
;
1172 struct res_resource
*r
;
1174 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1177 if (stat (real_filename
, &s
) < 0)
1178 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1181 data
= (unsigned char *) res_alloc (s
.st_size
);
1183 get_data (e
, data
, s
.st_size
, real_filename
);
1186 free (real_filename
);
1188 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1189 resinfo
->language
, 0);
1191 r
->type
= RES_TYPE_MESSAGETABLE
;
1192 r
->u
.data
.length
= s
.st_size
;
1193 r
->u
.data
.data
= data
;
1194 r
->res_info
= *resinfo
;
1197 /* Define an rcdata resource. */
1200 define_rcdata (id
, resinfo
, data
)
1202 const struct res_res_info
*resinfo
;
1203 struct rcdata_item
*data
;
1205 struct res_resource
*r
;
1207 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1208 resinfo
->language
, 0);
1209 r
->type
= RES_TYPE_RCDATA
;
1211 r
->res_info
= *resinfo
;
1214 /* Create an rcdata item holding a string. */
1216 struct rcdata_item
*
1217 define_rcdata_string (string
, len
)
1221 struct rcdata_item
*ri
;
1224 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1226 ri
->type
= RCDATA_STRING
;
1227 ri
->u
.string
.length
= len
;
1228 s
= (char *) res_alloc (len
);
1229 memcpy (s
, string
, len
);
1235 /* Create an rcdata item holding a number. */
1237 struct rcdata_item
*
1238 define_rcdata_number (val
, dword
)
1242 struct rcdata_item
*ri
;
1244 ri
= (struct rcdata_item
*) res_alloc (sizeof *ri
);
1246 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1252 /* Define a stringtable resource. This is called for each string
1253 which appears in a STRINGTABLE statement. */
1256 define_stringtable (resinfo
, stringid
, string
)
1257 const struct res_res_info
*resinfo
;
1258 unsigned long stringid
;
1262 struct res_resource
*r
;
1265 id
.u
.id
= (stringid
>> 4) + 1;
1266 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1267 resinfo
->language
, 1);
1269 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1273 r
->type
= RES_TYPE_STRINGTABLE
;
1274 r
->u
.stringtable
= ((struct stringtable
*)
1275 res_alloc (sizeof (struct stringtable
)));
1276 for (i
= 0; i
< 16; i
++)
1278 r
->u
.stringtable
->strings
[i
].length
= 0;
1279 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1282 r
->res_info
= *resinfo
;
1285 unicode_from_ascii (&r
->u
.stringtable
->strings
[stringid
& 0xf].length
,
1286 &r
->u
.stringtable
->strings
[stringid
& 0xf].string
,
1290 /* Define a user data resource where the data is in the rc file. */
1293 define_user_data (id
, type
, resinfo
, data
)
1296 const struct res_res_info
*resinfo
;
1297 struct rcdata_item
*data
;
1299 struct res_id ids
[3];
1300 struct res_resource
*r
;
1305 ids
[2].u
.id
= resinfo
->language
;
1307 r
= define_resource (&resources
, 3, ids
, 0);
1308 r
->type
= RES_TYPE_USERDATA
;
1309 r
->u
.userdata
= data
;
1310 r
->res_info
= *resinfo
;
1313 /* Define a user data resource where the data is in a file. */
1316 define_user_file (id
, type
, resinfo
, filename
)
1319 const struct res_res_info
*resinfo
;
1320 const char *filename
;
1323 char *real_filename
;
1325 unsigned char *data
;
1326 struct res_id ids
[3];
1327 struct res_resource
*r
;
1329 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
1331 if (stat (real_filename
, &s
) < 0)
1332 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1335 data
= (unsigned char *) res_alloc (s
.st_size
);
1337 get_data (e
, data
, s
.st_size
, real_filename
);
1340 free (real_filename
);
1345 ids
[2].u
.id
= resinfo
->language
;
1347 r
= define_resource (&resources
, 3, ids
, 0);
1348 r
->type
= RES_TYPE_USERDATA
;
1349 r
->u
.userdata
= ((struct rcdata_item
*)
1350 res_alloc (sizeof (struct rcdata_item
)));
1351 r
->u
.userdata
->next
= NULL
;
1352 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1353 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1354 r
->u
.userdata
->u
.buffer
.data
= data
;
1355 r
->res_info
= *resinfo
;
1358 /* Define a versioninfo resource. */
1361 define_versioninfo (id
, language
, fixedverinfo
, verinfo
)
1364 struct fixed_versioninfo
*fixedverinfo
;
1365 struct ver_info
*verinfo
;
1367 struct res_resource
*r
;
1369 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1370 r
->type
= RES_TYPE_VERSIONINFO
;
1371 r
->u
.versioninfo
= ((struct versioninfo
*)
1372 res_alloc (sizeof (struct versioninfo
)));
1373 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1374 r
->u
.versioninfo
->var
= verinfo
;
1375 r
->res_info
.language
= language
;
1378 /* Add string version info to a list of version information. */
1381 append_ver_stringfileinfo (verinfo
, language
, strings
)
1382 struct ver_info
*verinfo
;
1383 const char *language
;
1384 struct ver_stringinfo
*strings
;
1386 struct ver_info
*vi
, **pp
;
1388 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1390 vi
->type
= VERINFO_STRING
;
1391 unicode_from_ascii ((int *) NULL
, &vi
->u
.string
.language
, language
);
1392 vi
->u
.string
.strings
= strings
;
1394 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1401 /* Add variable version info to a list of version information. */
1404 append_ver_varfileinfo (verinfo
, key
, var
)
1405 struct ver_info
*verinfo
;
1407 struct ver_varinfo
*var
;
1409 struct ver_info
*vi
, **pp
;
1411 vi
= (struct ver_info
*) res_alloc (sizeof *vi
);
1413 vi
->type
= VERINFO_VAR
;
1414 unicode_from_ascii ((int *) NULL
, &vi
->u
.var
.key
, key
);
1415 vi
->u
.var
.var
= var
;
1417 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1424 /* Append version string information to a list. */
1426 struct ver_stringinfo
*
1427 append_verval (strings
, key
, value
)
1428 struct ver_stringinfo
*strings
;
1432 struct ver_stringinfo
*vs
, **pp
;
1434 vs
= (struct ver_stringinfo
*) res_alloc (sizeof *vs
);
1436 unicode_from_ascii ((int *) NULL
, &vs
->key
, key
);
1437 unicode_from_ascii ((int *) NULL
, &vs
->value
, value
);
1439 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1446 /* Append version variable information to a list. */
1448 struct ver_varinfo
*
1449 append_vertrans (var
, language
, charset
)
1450 struct ver_varinfo
*var
;
1451 unsigned long language
;
1452 unsigned long charset
;
1454 struct ver_varinfo
*vv
, **pp
;
1456 vv
= (struct ver_varinfo
*) res_alloc (sizeof *vv
);
1458 vv
->language
= language
;
1459 vv
->charset
= charset
;
1461 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1468 /* Local functions used to write out an rc file. */
1470 static void indent
PARAMS ((FILE *, int));
1471 static void write_rc_directory
1472 PARAMS ((FILE *, const struct res_directory
*, const struct res_id
*,
1473 const struct res_id
*, int *, int));
1474 static void write_rc_subdir
1475 PARAMS ((FILE *, const struct res_entry
*, const struct res_id
*,
1476 const struct res_id
*, int *, int));
1477 static void write_rc_resource
1478 PARAMS ((FILE *, const struct res_id
*, const struct res_id
*,
1479 const struct res_resource
*, int *));
1480 static void write_rc_accelerators
1481 PARAMS ((FILE *, const struct accelerator
*));
1482 static void write_rc_cursor
PARAMS ((FILE *, const struct cursor
*));
1483 static void write_rc_group_cursor
1484 PARAMS ((FILE *, const struct group_cursor
*));
1485 static void write_rc_dialog
PARAMS ((FILE *, const struct dialog
*));
1486 static void write_rc_dialog_control
1487 PARAMS ((FILE *, const struct dialog_control
*));
1488 static void write_rc_fontdir
PARAMS ((FILE *, const struct fontdir
*));
1489 static void write_rc_group_icon
PARAMS ((FILE *, const struct group_icon
*));
1490 static void write_rc_menu
PARAMS ((FILE *, const struct menu
*, int));
1491 static void write_rc_menuitems
1492 PARAMS ((FILE *, const struct menuitem
*, int, int));
1493 static void write_rc_rcdata
PARAMS ((FILE *, const struct rcdata_item
*, int));
1494 static void write_rc_stringtable
1495 PARAMS ((FILE *, const struct res_id
*, const struct stringtable
*));
1496 static void write_rc_versioninfo
PARAMS ((FILE *, const struct versioninfo
*));
1497 static void write_rc_filedata
1498 PARAMS ((FILE *, unsigned long, const unsigned char *));
1500 /* Indent a given number of spaces. */
1509 for (i
= 0; i
< c
; i
++)
1513 /* Dump the resources we have read in the format of an rc file.
1515 Actually, we don't use the format of an rc file, because it's way
1516 too much of a pain--for example, we'd have to write icon resources
1517 into a file and refer to that file. We just generate a readable
1518 format that kind of looks like an rc file, and is useful for
1519 understanding the contents of a resource file. Someday we may want
1520 to generate an rc file which the rc compiler can read; if that day
1521 comes, this code will have to be fixed up. */
1524 write_rc_file (filename
, resources
)
1525 const char *filename
;
1526 const struct res_directory
*resources
;
1531 if (filename
== NULL
)
1535 e
= fopen (filename
, FOPEN_WT
);
1537 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1541 write_rc_directory (e
, resources
, (const struct res_id
*) NULL
,
1542 (const struct res_id
*) NULL
, &language
, 1);
1545 /* Write out a directory. E is the file to write to. RD is the
1546 directory. TYPE is a pointer to the level 1 ID which serves as the
1547 resource type. NAME is a pointer to the level 2 ID which serves as
1548 an individual resource name. LANGUAGE is a pointer to the current
1549 language. LEVEL is the level in the tree. */
1552 write_rc_directory (e
, rd
, type
, name
, language
, level
)
1554 const struct res_directory
*rd
;
1555 const struct res_id
*type
;
1556 const struct res_id
*name
;
1560 const struct res_entry
*re
;
1562 /* Print out some COFF information that rc files can't represent. */
1565 fprintf (e
, "// Time stamp: %lu\n", rd
->time
);
1566 if (rd
->characteristics
!= 0)
1567 fprintf (e
, "// Characteristics: %lu\n", rd
->characteristics
);
1568 if (rd
->major
!= 0 || rd
->minor
!= 0)
1569 fprintf (e
, "// Version: %d %d\n", rd
->major
, rd
->minor
);
1571 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1576 /* If we're at level 1, the key of this resource is the
1577 type. This normally duplicates the information we have
1578 stored with the resource itself, but we need to remember
1579 the type if this is a user define resource type. */
1584 /* If we're at level 2, the key of this resource is the name
1585 we are going to use in the rc printout. */
1590 /* If we're at level 3, then this key represents a language.
1591 Use it to update the current language. */
1593 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1594 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1596 fprintf (e
, "LANGUAGE %lu, %lu\n",
1597 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1598 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
1599 *language
= re
->id
.u
.id
;
1608 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1613 /* This is the normal case: the three levels are
1614 TYPE/NAME/LANGUAGE. NAME will have been set at level
1615 2, and represents the name to use. We probably just
1616 set LANGUAGE, and it will probably match what the
1617 resource itself records if anything. */
1618 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1622 fprintf (e
, "// Resource at unexpected level %d\n", level
);
1623 write_rc_resource (e
, type
, (struct res_id
*) NULL
, re
->u
.res
,
1630 /* Write out a subdirectory entry. E is the file to write to. RE is
1631 the subdirectory entry. TYPE and NAME are pointers to higher level
1632 IDs, or NULL. LANGUAGE is a pointer to the current language.
1633 LEVEL is the level in the tree. */
1636 write_rc_subdir (e
, re
, type
, name
, language
, level
)
1638 const struct res_entry
*re
;
1639 const struct res_id
*type
;
1640 const struct res_id
*name
;
1648 fprintf (e
, "// Type: ");
1650 res_id_print (e
, re
->id
, 1);
1655 switch (re
->id
.u
.id
)
1657 case RT_CURSOR
: s
= "cursor"; break;
1658 case RT_BITMAP
: s
= "bitmap"; break;
1659 case RT_ICON
: s
= "icon"; break;
1660 case RT_MENU
: s
= "menu"; break;
1661 case RT_DIALOG
: s
= "dialog"; break;
1662 case RT_STRING
: s
= "stringtable"; break;
1663 case RT_FONTDIR
: s
= "fontdir"; break;
1664 case RT_FONT
: s
= "font"; break;
1665 case RT_ACCELERATOR
: s
= "accelerators"; break;
1666 case RT_RCDATA
: s
= "rcdata"; break;
1667 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1668 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1669 case RT_GROUP_ICON
: s
= "group icon"; break;
1670 case RT_VERSION
: s
= "version"; break;
1671 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1672 case RT_PLUGPLAY
: s
= "plugplay"; break;
1673 case RT_VXD
: s
= "vxd"; break;
1674 case RT_ANICURSOR
: s
= "anicursor"; break;
1675 case RT_ANIICON
: s
= "aniicon"; break;
1676 default: s
= NULL
; break;
1680 fprintf (e
, "%s", s
);
1682 res_id_print (e
, re
->id
, 1);
1688 fprintf (e
, "// Name: ");
1689 res_id_print (e
, re
->id
, 1);
1694 fprintf (e
, "// Language: ");
1695 res_id_print (e
, re
->id
, 1);
1700 fprintf (e
, "// Level %d: ", level
);
1701 res_id_print (e
, re
->id
, 1);
1705 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
1708 /* Write out a single resource. E is the file to write to. TYPE is a
1709 pointer to the type of the resource. NAME is a pointer to the name
1710 of the resource; it will be NULL if there is a level mismatch. RES
1711 is the resource data. LANGUAGE is a pointer to the current
1715 write_rc_resource (e
, type
, name
, res
, language
)
1717 const struct res_id
*type
;
1718 const struct res_id
*name
;
1719 const struct res_resource
*res
;
1733 case RES_TYPE_ACCELERATOR
:
1735 rt
= RT_ACCELERATOR
;
1738 case RES_TYPE_BITMAP
:
1743 case RES_TYPE_CURSOR
:
1748 case RES_TYPE_GROUP_CURSOR
:
1750 rt
= RT_GROUP_CURSOR
;
1753 case RES_TYPE_DIALOG
:
1754 if (extended_dialog (res
->u
.dialog
))
1766 case RES_TYPE_FONTDIR
:
1776 case RES_TYPE_GROUP_ICON
:
1782 if (extended_menu (res
->u
.menu
))
1795 case RES_TYPE_MESSAGETABLE
:
1797 rt
= RT_MESSAGETABLE
;
1800 case RES_TYPE_RCDATA
:
1805 case RES_TYPE_STRINGTABLE
:
1810 case RES_TYPE_USERDATA
:
1815 case RES_TYPE_VERSIONINFO
:
1823 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
1825 fprintf (e
, "// Unexpected resource type mismatch: ");
1826 res_id_print (e
, *type
, 1);
1827 fprintf (e
, " != %d", rt
);
1830 if (res
->coff_info
.codepage
!= 0)
1831 fprintf (e
, "// Code page: %lu\n", res
->coff_info
.codepage
);
1832 if (res
->coff_info
.reserved
!= 0)
1833 fprintf (e
, "// COFF reserved value: %lu\n", res
->coff_info
.reserved
);
1836 res_id_print (e
, *name
, 0);
1838 fprintf (e
, "??Unknown-Name??");
1842 fprintf (e
, "%s", s
);
1843 else if (type
!= NULL
)
1844 res_id_print (e
, *type
, 0);
1846 fprintf (e
, "??Unknown-Type??");
1848 if (res
->res_info
.memflags
!= 0)
1850 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
1851 fprintf (e
, " MOVEABLE");
1852 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
1853 fprintf (e
, " PURE");
1854 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
1855 fprintf (e
, " PRELOAD");
1856 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
1857 fprintf (e
, " DISCARDABLE");
1860 if (res
->type
== RES_TYPE_DIALOG
)
1862 fprintf (e
, " %d, %d, %d, %d", res
->u
.dialog
->x
, res
->u
.dialog
->y
,
1863 res
->u
.dialog
->width
, res
->u
.dialog
->height
);
1864 if (res
->u
.dialog
->ex
!= NULL
1865 && res
->u
.dialog
->ex
->help
!= 0)
1866 fprintf (e
, ", %lu", res
->u
.dialog
->ex
->help
);
1871 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1872 || res
->res_info
.characteristics
!= 0
1873 || res
->res_info
.version
!= 0)
1879 case RES_TYPE_ACCELERATOR
:
1880 case RES_TYPE_DIALOG
:
1882 case RES_TYPE_RCDATA
:
1883 case RES_TYPE_STRINGTABLE
:
1892 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
1893 fprintf (e
, "%sLANGUAGE %d, %d\n",
1894 modifiers
? "// " : "",
1895 res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
1896 (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
1897 if (res
->res_info
.characteristics
!= 0)
1898 fprintf (e
, "%sCHARACTERISTICS %lu\n",
1899 modifiers
? "// " : "",
1900 res
->res_info
.characteristics
);
1901 if (res
->res_info
.version
!= 0)
1902 fprintf (e
, "%sVERSION %lu\n",
1903 modifiers
? "// " : "",
1904 res
->res_info
.version
);
1912 case RES_TYPE_ACCELERATOR
:
1913 write_rc_accelerators (e
, res
->u
.acc
);
1916 case RES_TYPE_CURSOR
:
1917 write_rc_cursor (e
, res
->u
.cursor
);
1920 case RES_TYPE_GROUP_CURSOR
:
1921 write_rc_group_cursor (e
, res
->u
.group_cursor
);
1924 case RES_TYPE_DIALOG
:
1925 write_rc_dialog (e
, res
->u
.dialog
);
1928 case RES_TYPE_FONTDIR
:
1929 write_rc_fontdir (e
, res
->u
.fontdir
);
1932 case RES_TYPE_GROUP_ICON
:
1933 write_rc_group_icon (e
, res
->u
.group_icon
);
1937 write_rc_menu (e
, res
->u
.menu
, menuex
);
1940 case RES_TYPE_RCDATA
:
1941 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
1944 case RES_TYPE_STRINGTABLE
:
1945 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
1948 case RES_TYPE_USERDATA
:
1949 write_rc_rcdata (e
, res
->u
.userdata
, 0);
1952 case RES_TYPE_VERSIONINFO
:
1953 write_rc_versioninfo (e
, res
->u
.versioninfo
);
1956 case RES_TYPE_BITMAP
:
1959 case RES_TYPE_MESSAGETABLE
:
1960 write_rc_filedata (e
, res
->u
.data
.length
, res
->u
.data
.data
);
1965 /* Write out accelerator information. */
1968 write_rc_accelerators (e
, accelerators
)
1970 const struct accelerator
*accelerators
;
1972 const struct accelerator
*acc
;
1974 fprintf (e
, "BEGIN\n");
1975 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
1981 if ((acc
->key
& 0x7f) == acc
->key
1982 && ISPRINT (acc
->key
)
1983 && (acc
->flags
& ACC_VIRTKEY
) == 0)
1985 fprintf (e
, "\"%c\"", acc
->key
);
1990 fprintf (e
, "%d", acc
->key
);
1994 fprintf (e
, ", %d", acc
->id
);
1998 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
1999 fprintf (e
, ", VIRTKEY");
2001 fprintf (e
, ", ASCII");
2004 if ((acc
->flags
& ACC_SHIFT
) != 0)
2005 fprintf (e
, ", SHIFT");
2006 if ((acc
->flags
& ACC_CONTROL
) != 0)
2007 fprintf (e
, ", CONTROL");
2008 if ((acc
->flags
& ACC_ALT
) != 0)
2009 fprintf (e
, ", ALT");
2014 fprintf (e
, "END\n");
2017 /* Write out cursor information. This would normally be in a separate
2018 file, which the rc file would include. */
2021 write_rc_cursor (e
, cursor
)
2023 const struct cursor
*cursor
;
2025 fprintf (e
, "// Hotspot: x: %d; y: %d\n", cursor
->xhotspot
,
2027 write_rc_filedata (e
, cursor
->length
, cursor
->data
);
2030 /* Write out group cursor data. This would normally be built from the
2034 write_rc_group_cursor (e
, group_cursor
)
2036 const struct group_cursor
*group_cursor
;
2038 const struct group_cursor
*gc
;
2040 for (gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
)
2042 fprintf (e
, "// width: %d; height %d; planes %d; bits %d\n",
2043 gc
->width
, gc
->height
, gc
->planes
, gc
->bits
);
2044 fprintf (e
, "// data bytes: %lu; index: %d\n",
2045 gc
->bytes
, gc
->index
);
2049 /* Write dialog data. */
2052 write_rc_dialog (e
, dialog
)
2054 const struct dialog
*dialog
;
2056 const struct dialog_control
*control
;
2058 fprintf (e
, "STYLE 0x%lx\n", dialog
->style
);
2060 if (dialog
->exstyle
!= 0)
2061 fprintf (e
, "EXSTYLE 0x%lx\n", dialog
->exstyle
);
2063 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2064 || dialog
->class.u
.id
!= 0)
2066 fprintf (e
, "CLASS ");
2067 res_id_print (e
, dialog
->class, 1);
2071 if (dialog
->caption
!= NULL
)
2073 fprintf (e
, "CAPTION \"");
2074 unicode_print (e
, dialog
->caption
, -1);
2075 fprintf (e
, "\"\n");
2078 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2079 || dialog
->menu
.u
.id
!= 0)
2081 fprintf (e
, "MENU ");
2082 res_id_print (e
, dialog
->menu
, 0);
2086 if (dialog
->font
!= NULL
)
2088 fprintf (e
, "FONT %d, \"", dialog
->pointsize
);
2089 unicode_print (e
, dialog
->font
, -1);
2091 if (dialog
->ex
!= NULL
2092 && (dialog
->ex
->weight
!= 0
2093 || dialog
->ex
->italic
!= 0
2094 || dialog
->ex
->charset
!= 1))
2095 fprintf (e
, ", %d, %d, %d",
2096 dialog
->ex
->weight
, dialog
->ex
->italic
, dialog
->ex
->charset
);
2100 fprintf (e
, "BEGIN\n");
2102 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2103 write_rc_dialog_control (e
, control
);
2105 fprintf (e
, "END\n");
2108 /* For each predefined control keyword, this table provides the class
2114 unsigned short class;
2115 unsigned long style
;
2118 static const struct control_info control_info
[] =
2120 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2121 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2122 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2123 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2124 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2125 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2126 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2127 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2128 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2129 { "ICON", CTL_STATIC
, SS_ICON
},
2130 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2131 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2132 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2133 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2134 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2135 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2136 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2137 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2138 /* It's important that USERBUTTON come after all the other button
2139 types, so that it won't be matched too early. */
2140 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2144 /* Write a dialog control. */
2147 write_rc_dialog_control (e
, control
)
2149 const struct dialog_control
*control
;
2151 const struct control_info
*ci
;
2155 if (control
->class.named
)
2159 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2160 if (ci
->class == control
->class.u
.id
2161 && (ci
->style
== (unsigned long) -1
2162 || ci
->style
== (control
->style
& 0xff)))
2166 fprintf (e
, "CONTROL");
2167 else if (ci
->name
!= NULL
)
2168 fprintf (e
, "%s", ci
->name
);
2170 fprintf (e
, "CONTROL");
2172 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2175 res_id_print (e
, control
->text
, 1);
2179 fprintf (e
, " %d, ", control
->id
);
2183 if (control
->class.named
)
2185 res_id_print (e
, control
->class, 0);
2186 if (control
->class.named
)
2188 fprintf (e
, ", 0x%lx, ", control
->style
);
2191 fprintf (e
, "%d, %d", control
->x
, control
->y
);
2193 if (control
->style
!= SS_ICON
2194 || control
->exstyle
!= 0
2195 || control
->width
!= 0
2196 || control
->height
!= 0
2197 || control
->help
!= 0)
2199 fprintf (e
, ", %d, %d", control
->width
, control
->height
);
2201 /* FIXME: We don't need to print the style if it is the default.
2202 More importantly, in certain cases we actually need to turn
2203 off parts of the forced style, by using NOT. */
2204 fprintf (e
, ", 0x%lx", control
->style
);
2206 if (control
->exstyle
!= 0 || control
->help
!= 0)
2207 fprintf (e
, ", 0x%lx, %lu", control
->exstyle
, control
->help
);
2212 if (control
->data
!= NULL
)
2213 write_rc_rcdata (e
, control
->data
, 2);
2216 /* Write out font directory data. This would normally be built from
2220 write_rc_fontdir (e
, fontdir
)
2222 const struct fontdir
*fontdir
;
2224 const struct fontdir
*fc
;
2226 for (fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
)
2228 fprintf (e
, "// Font index: %d\n", fc
->index
);
2229 write_rc_filedata (e
, fc
->length
, fc
->data
);
2233 /* Write out group icon data. This would normally be built from the
2237 write_rc_group_icon (e
, group_icon
)
2239 const struct group_icon
*group_icon
;
2241 const struct group_icon
*gi
;
2243 for (gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
)
2245 fprintf (e
, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2246 gi
->width
, gi
->height
, gi
->colors
, gi
->planes
, gi
->bits
);
2247 fprintf (e
, "// data bytes: %lu; index: %d\n",
2248 gi
->bytes
, gi
->index
);
2252 /* Write out a menu resource. */
2255 write_rc_menu (e
, menu
, menuex
)
2257 const struct menu
*menu
;
2260 if (menu
->help
!= 0)
2261 fprintf (e
, "// Help ID: %lu\n", menu
->help
);
2262 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2265 /* Write out menuitems. */
2268 write_rc_menuitems (e
, menuitems
, menuex
, ind
)
2270 const struct menuitem
*menuitems
;
2274 const struct menuitem
*mi
;
2277 fprintf (e
, "BEGIN\n");
2279 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2281 indent (e
, ind
+ 2);
2283 if (mi
->popup
== NULL
)
2284 fprintf (e
, "MENUITEM");
2286 fprintf (e
, "POPUP");
2289 && mi
->popup
== NULL
2294 fprintf (e
, " SEPARATOR\n");
2298 if (mi
->text
== NULL
)
2299 fprintf (e
, " \"\"");
2303 unicode_print (e
, mi
->text
, -1);
2309 if (mi
->popup
== NULL
)
2310 fprintf (e
, ", %d", mi
->id
);
2312 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2313 fprintf (e
, ", CHECKED");
2314 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2315 fprintf (e
, ", GRAYED");
2316 if ((mi
->type
& MENUITEM_HELP
) != 0)
2317 fprintf (e
, ", HELP");
2318 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2319 fprintf (e
, ", INACTIVE");
2320 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2321 fprintf (e
, ", MENUBARBREAK");
2322 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2323 fprintf (e
, ", MENUBREAK");
2327 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2329 fprintf (e
, ", %d", mi
->id
);
2330 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2332 fprintf (e
, ", %lu", mi
->type
);
2333 if (mi
->state
!= 0 || mi
->help
!= 0)
2335 fprintf (e
, ", %lu", mi
->state
);
2337 fprintf (e
, ", %lu", mi
->help
);
2345 if (mi
->popup
!= NULL
)
2346 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2350 fprintf (e
, "END\n");
2353 /* Write out an rcdata resource. This is also used for other types of
2354 resources that need to print arbitrary data. */
2357 write_rc_rcdata (e
, rcdata
, ind
)
2359 const struct rcdata_item
*rcdata
;
2362 const struct rcdata_item
*ri
;
2365 fprintf (e
, "BEGIN\n");
2367 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
2369 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
2372 indent (e
, ind
+ 2);
2380 fprintf (e
, "%d", ri
->u
.word
);
2384 fprintf (e
, "%luL", ri
->u
.dword
);
2394 for (i
= 0; i
< ri
->u
.string
.length
; i
++)
2399 fprintf (e
, "\\%03o", *s
);
2405 case RCDATA_WSTRING
:
2407 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
2416 /* Assume little endian data. */
2419 for (i
= 0; i
+ 3 < ri
->u
.buffer
.length
; i
+= 4)
2425 indent (e
, ind
+ 2);
2426 l
= ((((((ri
->u
.buffer
.data
[i
+ 3] << 8)
2427 | ri
->u
.buffer
.data
[i
+ 2]) << 8)
2428 | ri
->u
.buffer
.data
[i
+ 1]) << 8)
2429 | ri
->u
.buffer
.data
[i
]);
2430 fprintf (e
, "%luL", l
);
2431 if (i
+ 4 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2433 for (j
= 0; j
< 4; ++j
)
2434 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2435 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2439 fprintf (e
, "\t// ");
2440 for (j
= 0; j
< 4; ++j
)
2442 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2443 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2446 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2448 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2456 if (i
+ 1 < ri
->u
.buffer
.length
)
2462 indent (e
, ind
+ 2);
2463 s
= (ri
->u
.buffer
.data
[i
+ 1] << 8) | ri
->u
.buffer
.data
[i
];
2464 fprintf (e
, "%d", s
);
2465 if (i
+ 2 < ri
->u
.buffer
.length
|| ri
->next
!= NULL
)
2467 for (j
= 0; j
< 2; ++j
)
2468 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
])
2469 && ri
->u
.buffer
.data
[i
+ j
] != 0)
2473 fprintf (e
, "\t// ");
2474 for (j
= 0; j
< 2; ++j
)
2476 if (! ISPRINT (ri
->u
.buffer
.data
[i
+ j
]))
2477 fprintf (e
, "\\%03o", ri
->u
.buffer
.data
[i
+ j
]);
2480 if (ri
->u
.buffer
.data
[i
+ j
] == '\\')
2482 fprintf (e
, "%c", ri
->u
.buffer
.data
[i
+ j
]);
2491 if (i
< ri
->u
.buffer
.length
)
2494 indent (e
, ind
+ 2);
2495 if ((ri
->u
.buffer
.data
[i
] & 0x7f) == ri
->u
.buffer
.data
[i
]
2496 && ISPRINT (ri
->u
.buffer
.data
[i
]))
2497 fprintf (e
, "\"%c\"", ri
->u
.buffer
.data
[i
]);
2499 fprintf (e
, "\"\\%03o\"", ri
->u
.buffer
.data
[i
]);
2500 if (ri
->next
!= NULL
)
2510 if (ri
->type
!= RCDATA_BUFFER
)
2512 if (ri
->next
!= NULL
)
2519 fprintf (e
, "END\n");
2522 /* Write out a stringtable resource. */
2525 write_rc_stringtable (e
, name
, stringtable
)
2527 const struct res_id
*name
;
2528 const struct stringtable
*stringtable
;
2530 unsigned long offset
;
2533 if (name
!= NULL
&& ! name
->named
)
2534 offset
= (name
->u
.id
- 1) << 4;
2537 fprintf (e
, "// %s string table name\n",
2538 name
== NULL
? "Missing" : "Invalid");
2542 fprintf (e
, "BEGIN\n");
2544 for (i
= 0; i
< 16; i
++)
2546 if (stringtable
->strings
[i
].length
!= 0)
2548 fprintf (e
, " %lu, \"", offset
+ i
);
2549 unicode_print (e
, stringtable
->strings
[i
].string
,
2550 stringtable
->strings
[i
].length
);
2551 fprintf (e
, "\"\n");
2555 fprintf (e
, "END\n");
2558 /* Write out a versioninfo resource. */
2561 write_rc_versioninfo (e
, versioninfo
)
2563 const struct versioninfo
*versioninfo
;
2565 const struct fixed_versioninfo
*f
;
2566 const struct ver_info
*vi
;
2568 f
= versioninfo
->fixed
;
2569 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
2570 fprintf (e
, " FILEVERSION %lu, %lu, %lu, %lu\n",
2571 (f
->file_version_ms
>> 16) & 0xffff,
2572 f
->file_version_ms
& 0xffff,
2573 (f
->file_version_ls
>> 16) & 0xffff,
2574 f
->file_version_ls
& 0xffff);
2575 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
2576 fprintf (e
, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2577 (f
->product_version_ms
>> 16) & 0xffff,
2578 f
->product_version_ms
& 0xffff,
2579 (f
->product_version_ls
>> 16) & 0xffff,
2580 f
->product_version_ls
& 0xffff);
2581 if (f
->file_flags_mask
!= 0)
2582 fprintf (e
, " FILEFLAGSMASK 0x%lx\n", f
->file_flags_mask
);
2583 if (f
->file_flags
!= 0)
2584 fprintf (e
, " FILEFLAGS 0x%lx\n", f
->file_flags
);
2585 if (f
->file_os
!= 0)
2586 fprintf (e
, " FILEOS 0x%lx\n", f
->file_os
);
2587 if (f
->file_type
!= 0)
2588 fprintf (e
, " FILETYPE 0x%lx\n", f
->file_type
);
2589 if (f
->file_subtype
!= 0)
2590 fprintf (e
, " FILESUBTYPE 0x%lx\n", f
->file_subtype
);
2591 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
2592 fprintf (e
, "// Date: %lu, %lu\n", f
->file_date_ms
, f
->file_date_ls
);
2594 fprintf (e
, "BEGIN\n");
2596 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2600 case VERINFO_STRING
:
2602 const struct ver_stringinfo
*vs
;
2604 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
2605 fprintf (e
, " BEGIN\n");
2606 fprintf (e
, " BLOCK \"");
2607 unicode_print (e
, vi
->u
.string
.language
, -1);
2608 fprintf (e
, "\"\n");
2609 fprintf (e
, " BEGIN\n");
2611 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2613 fprintf (e
, " VALUE \"");
2614 unicode_print (e
, vs
->key
, -1);
2615 fprintf (e
, "\", \"");
2616 unicode_print (e
, vs
->value
, -1);
2617 fprintf (e
, "\"\n");
2620 fprintf (e
, " END\n");
2621 fprintf (e
, " END\n");
2627 const struct ver_varinfo
*vv
;
2629 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
2630 fprintf (e
, " BEGIN\n");
2631 fprintf (e
, " VALUE \"");
2632 unicode_print (e
, vi
->u
.var
.key
, -1);
2635 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2636 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
2639 fprintf (e
, "\n END\n");
2646 fprintf (e
, "END\n");
2649 /* Write out data which would normally be read from a file. */
2652 write_rc_filedata (e
, length
, data
)
2654 unsigned long length
;
2655 const unsigned char *data
;
2659 for (i
= 0; i
+ 15 < length
; i
+= 16)
2661 fprintf (e
, "// %4lx: ", i
);
2662 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2663 data
[i
+ 0], data
[i
+ 1], data
[i
+ 2], data
[i
+ 3],
2664 data
[i
+ 4], data
[i
+ 5], data
[i
+ 6], data
[i
+ 7]);
2665 fprintf (e
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2666 data
[i
+ 8], data
[i
+ 9], data
[i
+ 10], data
[i
+ 11],
2667 data
[i
+ 12], data
[i
+ 13], data
[i
+ 14], data
[i
+ 15]);
2672 fprintf (e
, "// %4lx:", i
);
2675 fprintf (e
, " %02x", data
[i
]);