1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
6 This file is part of GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
23 /* This file contains functions that read and write Windows rc files.
24 These are text files that represent resources. */
28 #include "libiberty.h"
29 #include "safe-ctype.h"
36 #ifdef HAVE_SYS_WAIT_H
38 #else /* ! HAVE_SYS_WAIT_H */
39 #if ! defined (_WIN32) || defined (__CYGWIN__)
41 #define WIFEXITED(w) (((w)&0377) == 0)
44 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
47 #define WTERMSIG(w) ((w) & 0177)
50 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
52 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
54 #define WIFEXITED(w) (((w) & 0xff) == 0)
57 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
60 #define WTERMSIG(w) ((w) & 0x7f)
63 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
65 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
66 #endif /* ! HAVE_SYS_WAIT_H */
69 #define STDOUT_FILENO 1
72 #if defined (_WIN32) && ! defined (__CYGWIN__)
74 #define pclose _pclose
77 /* The default preprocessor. */
79 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
81 /* We read the directory entries in a cursor or icon file into
82 instances of this structure. */
88 /* Height of image. */
90 /* Number of colors in image. */
91 unsigned char colorcount;
97 unsigned short planes;
103 /* X coordinate of hotspot. */
104 unsigned short xhotspot;
105 /* Y coordinate of hotspot. */
106 unsigned short yhotspot;
109 /* Bytes in image. */
111 /* File offset of image. */
112 unsigned long offset;
115 /* The name of the rc file we are reading. */
119 /* The line number in the rc file. */
123 /* The pipe we are reading from, so that we can close it if we exit. */
125 static FILE *cpp_pipe;
127 /* The temporary file used if we're not using popen, so we can delete it
130 static char *cpp_temp_file;
132 /* Input stream is either a file or a pipe. */
134 static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
136 /* As we read the rc file, we attach information to this structure. */
138 static struct res_directory *resources;
140 /* The number of cursor resources we have written out. */
144 /* The number of font resources we have written out. */
148 /* Font directory information. */
150 struct fontdir *fontdirs;
152 /* Resource info to use for fontdirs. */
154 struct res_res_info fontdirs_resinfo;
156 /* The number of icon resources we have written out. */
160 /* Local functions. */
162 static int run_cmd (char *, const char *);
163 static FILE *open_input_stream (char *);
164 static FILE *look_for_default
165 (char *, const char *, int, const char *, const char *);
166 static void close_input_stream (void);
167 static void unexpected_eof (const char *);
168 static int get_word (FILE *, const char *);
169 static unsigned long get_long (FILE *, const char *);
170 static void get_data (FILE *, unsigned char *, unsigned long, const char *);
171 static void define_fontdirs (void);
173 /* Run `cmd' and redirect the output to `redir'. */
176 run_cmd (char *cmd, const char *redir)
179 int pid, wait_status, retcode;
182 char *errmsg_fmt, *errmsg_arg;
183 char *temp_base = choose_temp_base ();
186 int redir_handle = -1;
187 int stdout_save = -1;
189 /* Count the args. */
192 for (s = cmd; *s; s++)
197 argv = alloca (sizeof (char *) * (i + 3));
203 while (*s == ' ' && *s != 0)
209 in_quote = (*s == '\'' || *s == '"');
210 sep = (in_quote) ? *s++ : ' ';
213 while (*s != sep && *s != 0)
226 /* Setup the redirection. We can't use the usual fork/exec and redirect
227 since we may be running on non-POSIX Windows host. */
232 /* Open temporary output file. */
233 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
234 if (redir_handle == -1)
235 fatal (_("can't open temporary file `%s': %s"), redir,
238 /* Duplicate the stdout file handle so it can be restored later. */
239 stdout_save = dup (STDOUT_FILENO);
240 if (stdout_save == -1)
241 fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
243 /* Redirect stdout to our output file. */
244 dup2 (redir_handle, STDOUT_FILENO);
246 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
247 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
249 /* Restore stdout to its previous setting. */
250 dup2 (stdout_save, STDOUT_FILENO);
252 /* Close response file. */
253 close (redir_handle);
257 fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
262 pid = pwait (pid, &wait_status, 0);
266 fatal (_("wait: %s"), strerror (errno));
269 else if (WIFSIGNALED (wait_status))
271 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
274 else if (WIFEXITED (wait_status))
276 if (WEXITSTATUS (wait_status) != 0)
278 fatal (_("%s exited with status %d"), cmd,
279 WEXITSTATUS (wait_status));
290 open_input_stream (char *cmd)
292 if (istream_type == ISTREAM_FILE)
296 fileprefix = choose_temp_base ();
297 cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
298 sprintf (cpp_temp_file, "%s.irc", fileprefix);
301 if (run_cmd (cmd, cpp_temp_file))
302 fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
304 cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
305 if (cpp_pipe == NULL)
306 fatal (_("can't open temporary file `%s': %s"),
307 cpp_temp_file, strerror (errno));
311 _("Using temporary file `%s' to read preprocessor output\n"),
316 cpp_pipe = popen (cmd, FOPEN_RT);
317 if (cpp_pipe == NULL)
318 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
320 fprintf (stderr, _("Using popen to read preprocessor output\n"));
323 xatexit (close_input_stream);
327 /* look for the preprocessor program */
330 look_for_default (char *cmd, const char *prefix, int end_prefix,
331 const char *preprocargs, const char *filename)
337 strcpy (cmd, prefix);
339 sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
340 space = strchr (cmd + end_prefix, ' ');
345 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
346 strchr (cmd, '\\') ||
350 found = (stat (cmd, &s) == 0
351 #ifdef HAVE_EXECUTABLE_SUFFIX
352 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
359 fprintf (stderr, _("Tried `%s'\n"), cmd);
364 strcpy (cmd, prefix);
366 sprintf (cmd + end_prefix, "%s %s %s",
367 DEFAULT_PREPROCESSOR, preprocargs, filename);
370 fprintf (stderr, _("Using `%s'\n"), cmd);
372 cpp_pipe = open_input_stream (cmd);
376 /* Read an rc file. */
378 struct res_directory *
379 read_rc_file (const char *filename, const char *preprocessor,
380 const char *preprocargs, int language, int use_temp_file)
384 istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
386 if (preprocargs == NULL)
388 if (filename == NULL)
393 cmd = xmalloc (strlen (preprocessor)
394 + strlen (preprocargs)
397 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
399 cpp_pipe = open_input_stream (cmd);
403 char *dash, *slash, *cp;
405 preprocessor = DEFAULT_PREPROCESSOR;
407 cmd = xmalloc (strlen (program_name)
408 + strlen (preprocessor)
409 + strlen (preprocargs)
411 #ifdef HAVE_EXECUTABLE_SUFFIX
412 + strlen (EXECUTABLE_SUFFIX)
418 for (cp = program_name; *cp; cp++)
423 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
424 *cp == ':' || *cp == '\\' ||
437 /* First, try looking for a prefixed gcc in the windres
438 directory, with the same prefix as windres */
440 cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
441 preprocargs, filename);
444 if (slash && !cpp_pipe)
446 /* Next, try looking for a gcc in the same directory as
449 cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
450 preprocargs, filename);
455 /* Sigh, try the default */
457 cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
464 rc_filename = xstrdup (filename);
467 rcparse_set_language (language);
470 rcparse_discard_strings ();
472 close_input_stream ();
474 if (fontdirs != NULL)
483 /* Close the input stream if it is open. */
486 close_input_stream (void)
488 if (istream_type == ISTREAM_FILE)
490 if (cpp_pipe != NULL)
493 if (cpp_temp_file != NULL)
495 int errno_save = errno;
497 unlink (cpp_temp_file);
499 free (cpp_temp_file);
504 if (cpp_pipe != NULL)
508 /* Since this is also run via xatexit, safeguard. */
510 cpp_temp_file = NULL;
513 /* Report an error while reading an rc file. */
516 yyerror (const char *msg)
518 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
521 /* Issue a warning while reading an rc file. */
524 rcparse_warning (const char *msg)
526 fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
529 /* Die if we get an unexpected end of file. */
532 unexpected_eof (const char *msg)
534 fatal (_("%s: unexpected EOF"), msg);
537 /* Read a 16 bit word from a file. The data is assumed to be little
541 get_word (FILE *e, const char *msg)
548 unexpected_eof (msg);
549 return ((b2 & 0xff) << 8) | (b1 & 0xff);
552 /* Read a 32 bit word from a file. The data is assumed to be little
556 get_long (FILE *e, const char *msg)
565 unexpected_eof (msg);
566 return (((((((b4 & 0xff) << 8)
572 /* Read data from a file. This is a wrapper to do error checking. */
575 get_data (FILE *e, unsigned char *p, unsigned long c, const char *msg)
579 got = fread (p, 1, c, e);
583 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
586 /* Define an accelerator resource. */
589 define_accelerator (struct res_id id, const struct res_res_info *resinfo,
590 struct accelerator *data)
592 struct res_resource *r;
594 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
595 resinfo->language, 0);
596 r->type = RES_TYPE_ACCELERATOR;
598 r->res_info = *resinfo;
601 /* Define a bitmap resource. Bitmap data is stored in a file. The
602 first 14 bytes of the file are a standard header, which is not
603 included in the resource data. */
605 #define BITMAP_SKIP (14)
608 define_bitmap (struct res_id id, const struct res_res_info *resinfo,
609 const char *filename)
616 struct res_resource *r;
618 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
620 if (stat (real_filename, &s) < 0)
621 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
624 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
626 for (i = 0; i < BITMAP_SKIP; i++)
629 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
632 free (real_filename);
634 r = define_standard_resource (&resources, RT_BITMAP, id,
635 resinfo->language, 0);
637 r->type = RES_TYPE_BITMAP;
638 r->u.data.length = s.st_size - BITMAP_SKIP;
639 r->u.data.data = data;
640 r->res_info = *resinfo;
643 /* Define a cursor resource. A cursor file may contain a set of
644 bitmaps, each representing the same cursor at various different
645 resolutions. They each get written out with a different ID. The
646 real cursor resource is then a group resource which can be used to
647 select one of the actual cursors. */
650 define_cursor (struct res_id id, const struct res_res_info *resinfo,
651 const char *filename)
656 struct icondir *icondirs;
658 struct res_resource *r;
659 struct group_cursor *first, **pp;
661 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
663 /* A cursor file is basically an icon file. The start of the file
664 is a three word structure. The first word is ignored. The
665 second word is the type of data. The third word is the number of
668 get_word (e, real_filename);
669 type = get_word (e, real_filename);
670 count = get_word (e, real_filename);
672 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
674 /* Read in the icon directory entries. */
676 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
678 for (i = 0; i < count; i++)
680 icondirs[i].width = getc (e);
681 icondirs[i].height = getc (e);
682 icondirs[i].colorcount = getc (e);
684 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
685 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
686 icondirs[i].bytes = get_long (e, real_filename);
687 icondirs[i].offset = get_long (e, real_filename);
690 unexpected_eof (real_filename);
693 /* Define each cursor as a unique resource. */
695 first_cursor = cursors;
697 for (i = 0; i < count; i++)
703 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
704 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
705 icondirs[i].offset, strerror (errno));
707 data = (unsigned char *) res_alloc (icondirs[i].bytes);
709 get_data (e, data, icondirs[i].bytes, real_filename);
711 c = (struct cursor *) res_alloc (sizeof *c);
712 c->xhotspot = icondirs[i].u.cursor.xhotspot;
713 c->yhotspot = icondirs[i].u.cursor.yhotspot;
714 c->length = icondirs[i].bytes;
722 r = define_standard_resource (&resources, RT_CURSOR, name,
723 resinfo->language, 0);
724 r->type = RES_TYPE_CURSOR;
726 r->res_info = *resinfo;
730 free (real_filename);
732 /* Define a cursor group resource. */
736 for (i = 0; i < count; i++)
738 struct group_cursor *cg;
740 cg = (struct group_cursor *) res_alloc (sizeof *cg);
742 cg->width = icondirs[i].width;
743 cg->height = 2 * icondirs[i].height;
745 /* FIXME: What should these be set to? */
749 cg->bytes = icondirs[i].bytes + 4;
750 cg->index = first_cursor + i + 1;
758 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
759 resinfo->language, 0);
760 r->type = RES_TYPE_GROUP_CURSOR;
761 r->u.group_cursor = first;
762 r->res_info = *resinfo;
765 /* Define a dialog resource. */
768 define_dialog (struct res_id id, const struct res_res_info *resinfo,
769 const struct dialog *dialog)
772 struct res_resource *r;
774 copy = (struct dialog *) res_alloc (sizeof *copy);
777 r = define_standard_resource (&resources, RT_DIALOG, id,
778 resinfo->language, 0);
779 r->type = RES_TYPE_DIALOG;
781 r->res_info = *resinfo;
784 /* Define a dialog control. This does not define a resource, but
785 merely allocates and fills in a structure. */
787 struct dialog_control *
788 define_control (const struct res_id iid, unsigned long id, unsigned long x,
789 unsigned long y, unsigned long width, unsigned long height,
790 unsigned long class, unsigned long style,
791 unsigned long exstyle)
793 struct dialog_control *n;
795 n = (struct dialog_control *) res_alloc (sizeof *n);
799 n->exstyle = exstyle;
805 n->class.u.id = class;
813 struct dialog_control *
814 define_icon_control (struct res_id iid, unsigned long id, unsigned long x,
815 unsigned long y, unsigned long style,
816 unsigned long exstyle, unsigned long help,
817 struct rcdata_item *data, struct dialog_ex *ex)
819 struct dialog_control *n;
823 style = SS_ICON | WS_CHILD | WS_VISIBLE;
824 res_string_to_id (&tid, "");
825 n = define_control (tid, id, x, y, 0, 0, CTL_STATIC, style, exstyle);
828 rcparse_warning (_("help ID requires DIALOGEX"));
830 rcparse_warning (_("control data requires DIALOGEX"));
837 /* Define a font resource. */
840 define_font (struct res_id id, const struct res_res_info *resinfo,
841 const char *filename)
847 struct res_resource *r;
850 unsigned char *fontdata;
852 const char *device, *face;
855 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
857 if (stat (real_filename, &s) < 0)
858 fatal (_("stat failed on font file `%s': %s"), real_filename,
861 data = (unsigned char *) res_alloc (s.st_size);
863 get_data (e, data, s.st_size, real_filename);
866 free (real_filename);
868 r = define_standard_resource (&resources, RT_FONT, id,
869 resinfo->language, 0);
871 r->type = RES_TYPE_FONT;
872 r->u.data.length = s.st_size;
873 r->u.data.data = data;
874 r->res_info = *resinfo;
876 /* For each font resource, we must add an entry in the FONTDIR
877 resource. The FONTDIR resource includes some strings in the font
878 file. To find them, we have to do some magic on the data we have
881 offset = ((((((data[47] << 8)
885 if (offset > 0 && offset < s.st_size)
886 device = (char *) data + offset;
890 offset = ((((((data[51] << 8)
894 if (offset > 0 && offset < s.st_size)
895 face = (char *) data + offset;
901 fontdatalength = 58 + strlen (device) + strlen (face);
902 fontdata = (unsigned char *) res_alloc (fontdatalength);
903 memcpy (fontdata, data, 56);
904 strcpy ((char *) fontdata + 56, device);
905 strcpy ((char *) fontdata + 57 + strlen (device), face);
907 fd = (struct fontdir *) res_alloc (sizeof *fd);
910 fd->length = fontdatalength;
913 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
917 /* For the single fontdirs resource, we always use the resource
918 information of the last font. I don't know what else to do. */
919 fontdirs_resinfo = *resinfo;
922 /* Define the fontdirs resource. This is called after the entire rc
923 file has been parsed, if any font resources were seen. */
926 define_fontdirs (void)
928 struct res_resource *r;
934 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
936 r->type = RES_TYPE_FONTDIR;
937 r->u.fontdir = fontdirs;
938 r->res_info = fontdirs_resinfo;
941 /* Define an icon resource. An icon file may contain a set of
942 bitmaps, each representing the same icon at various different
943 resolutions. They each get written out with a different ID. The
944 real icon resource is then a group resource which can be used to
945 select one of the actual icon bitmaps. */
948 define_icon (struct res_id id, const struct res_res_info *resinfo,
949 const char *filename)
954 struct icondir *icondirs;
956 struct res_resource *r;
957 struct group_icon *first, **pp;
959 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
961 /* The start of an icon file is a three word structure. The first
962 word is ignored. The second word is the type of data. The third
963 word is the number of entries. */
965 get_word (e, real_filename);
966 type = get_word (e, real_filename);
967 count = get_word (e, real_filename);
969 fatal (_("icon file `%s' does not contain icon data"), real_filename);
971 /* Read in the icon directory entries. */
973 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
975 for (i = 0; i < count; i++)
977 icondirs[i].width = getc (e);
978 icondirs[i].height = getc (e);
979 icondirs[i].colorcount = getc (e);
981 icondirs[i].u.icon.planes = get_word (e, real_filename);
982 icondirs[i].u.icon.bits = get_word (e, real_filename);
983 icondirs[i].bytes = get_long (e, real_filename);
984 icondirs[i].offset = get_long (e, real_filename);
987 unexpected_eof (real_filename);
990 /* Define each icon as a unique resource. */
994 for (i = 0; i < count; i++)
999 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1000 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1001 icondirs[i].offset, strerror (errno));
1003 data = (unsigned char *) res_alloc (icondirs[i].bytes);
1005 get_data (e, data, icondirs[i].bytes, real_filename);
1012 r = define_standard_resource (&resources, RT_ICON, name,
1013 resinfo->language, 0);
1014 r->type = RES_TYPE_ICON;
1015 r->u.data.length = icondirs[i].bytes;
1016 r->u.data.data = data;
1017 r->res_info = *resinfo;
1021 free (real_filename);
1023 /* Define an icon group resource. */
1027 for (i = 0; i < count; i++)
1029 struct group_icon *cg;
1031 /* For some reason, at least in some files the planes and bits
1032 are zero. We instead set them from the color. This is
1035 cg = (struct group_icon *) res_alloc (sizeof *cg);
1037 cg->width = icondirs[i].width;
1038 cg->height = icondirs[i].height;
1039 cg->colors = icondirs[i].colorcount;
1041 if (icondirs[i].u.icon.planes)
1042 cg->planes = icondirs[i].u.icon.planes;
1046 if (icondirs[i].u.icon.bits)
1047 cg->bits = icondirs[i].u.icon.bits;
1052 while ((1L << cg->bits) < cg->colors)
1056 cg->bytes = icondirs[i].bytes;
1057 cg->index = first_icon + i + 1;
1065 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1066 resinfo->language, 0);
1067 r->type = RES_TYPE_GROUP_ICON;
1068 r->u.group_icon = first;
1069 r->res_info = *resinfo;
1072 /* Define a menu resource. */
1075 define_menu (struct res_id id, const struct res_res_info *resinfo,
1076 struct menuitem *menuitems)
1079 struct res_resource *r;
1081 m = (struct menu *) res_alloc (sizeof *m);
1082 m->items = menuitems;
1085 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1086 r->type = RES_TYPE_MENU;
1088 r->res_info = *resinfo;
1091 /* Define a menu item. This does not define a resource, but merely
1092 allocates and fills in a structure. */
1095 define_menuitem (const char *text, int menuid, unsigned long type,
1096 unsigned long state, unsigned long help,
1097 struct menuitem *menuitems)
1099 struct menuitem *mi;
1101 mi = (struct menuitem *) res_alloc (sizeof *mi);
1109 unicode_from_ascii ((int *) NULL, &mi->text, text);
1111 mi->popup = menuitems;
1115 /* Define a messagetable resource. */
1118 define_messagetable (struct res_id id, const struct res_res_info *resinfo,
1119 const char *filename)
1122 char *real_filename;
1124 unsigned char *data;
1125 struct res_resource *r;
1127 e = open_file_search (filename, FOPEN_RB, "messagetable file",
1130 if (stat (real_filename, &s) < 0)
1131 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1134 data = (unsigned char *) res_alloc (s.st_size);
1136 get_data (e, data, s.st_size, real_filename);
1139 free (real_filename);
1141 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1142 resinfo->language, 0);
1144 r->type = RES_TYPE_MESSAGETABLE;
1145 r->u.data.length = s.st_size;
1146 r->u.data.data = data;
1147 r->res_info = *resinfo;
1150 /* Define an rcdata resource. */
1153 define_rcdata (struct res_id id, const struct res_res_info *resinfo,
1154 struct rcdata_item *data)
1156 struct res_resource *r;
1158 r = define_standard_resource (&resources, RT_RCDATA, id,
1159 resinfo->language, 0);
1160 r->type = RES_TYPE_RCDATA;
1162 r->res_info = *resinfo;
1165 /* Create an rcdata item holding a string. */
1167 struct rcdata_item *
1168 define_rcdata_string (const char *string, unsigned long len)
1170 struct rcdata_item *ri;
1173 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1175 ri->type = RCDATA_STRING;
1176 ri->u.string.length = len;
1177 s = (char *) res_alloc (len);
1178 memcpy (s, string, len);
1184 /* Create an rcdata item holding a number. */
1186 struct rcdata_item *
1187 define_rcdata_number (unsigned long val, int dword)
1189 struct rcdata_item *ri;
1191 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1193 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1199 /* Define a stringtable resource. This is called for each string
1200 which appears in a STRINGTABLE statement. */
1203 define_stringtable (const struct res_res_info *resinfo,
1204 unsigned long stringid, const char *string)
1207 struct res_resource *r;
1210 id.u.id = (stringid >> 4) + 1;
1211 r = define_standard_resource (&resources, RT_STRING, id,
1212 resinfo->language, 1);
1214 if (r->type == RES_TYPE_UNINITIALIZED)
1218 r->type = RES_TYPE_STRINGTABLE;
1219 r->u.stringtable = ((struct stringtable *)
1220 res_alloc (sizeof (struct stringtable)));
1221 for (i = 0; i < 16; i++)
1223 r->u.stringtable->strings[i].length = 0;
1224 r->u.stringtable->strings[i].string = NULL;
1227 r->res_info = *resinfo;
1230 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
1231 &r->u.stringtable->strings[stringid & 0xf].string,
1235 /* Define a user data resource where the data is in the rc file. */
1238 define_user_data (struct res_id id, struct res_id type,
1239 const struct res_res_info *resinfo,
1240 struct rcdata_item *data)
1242 struct res_id ids[3];
1243 struct res_resource *r;
1248 ids[2].u.id = resinfo->language;
1250 r = define_resource (& resources, 3, ids, 0);
1251 r->type = RES_TYPE_USERDATA;
1252 r->u.userdata = data;
1253 r->res_info = *resinfo;
1257 define_rcdata_file (struct res_id id, const struct res_res_info *resinfo,
1258 const char *filename)
1260 struct rcdata_item *ri;
1262 char *real_filename;
1264 unsigned char *data;
1266 e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1269 if (stat (real_filename, &s) < 0)
1270 fatal (_("stat failed on file `%s': %s"), real_filename,
1273 data = (unsigned char *) res_alloc (s.st_size);
1275 get_data (e, data, s.st_size, real_filename);
1278 free (real_filename);
1280 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1282 ri->type = RCDATA_BUFFER;
1283 ri->u.buffer.length = s.st_size;
1284 ri->u.buffer.data = data;
1286 define_rcdata (id, resinfo, ri);
1289 /* Define a user data resource where the data is in a file. */
1292 define_user_file (struct res_id id, struct res_id type,
1293 const struct res_res_info *resinfo, const char *filename)
1296 char *real_filename;
1298 unsigned char *data;
1299 struct res_id ids[3];
1300 struct res_resource *r;
1302 e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1304 if (stat (real_filename, &s) < 0)
1305 fatal (_("stat failed on file `%s': %s"), real_filename,
1308 data = (unsigned char *) res_alloc (s.st_size);
1310 get_data (e, data, s.st_size, real_filename);
1313 free (real_filename);
1318 ids[2].u.id = resinfo->language;
1320 r = define_resource (&resources, 3, ids, 0);
1321 r->type = RES_TYPE_USERDATA;
1322 r->u.userdata = ((struct rcdata_item *)
1323 res_alloc (sizeof (struct rcdata_item)));
1324 r->u.userdata->next = NULL;
1325 r->u.userdata->type = RCDATA_BUFFER;
1326 r->u.userdata->u.buffer.length = s.st_size;
1327 r->u.userdata->u.buffer.data = data;
1328 r->res_info = *resinfo;
1331 /* Define a versioninfo resource. */
1334 define_versioninfo (struct res_id id, int language,
1335 struct fixed_versioninfo *fixedverinfo,
1336 struct ver_info *verinfo)
1338 struct res_resource *r;
1340 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1341 r->type = RES_TYPE_VERSIONINFO;
1342 r->u.versioninfo = ((struct versioninfo *)
1343 res_alloc (sizeof (struct versioninfo)));
1344 r->u.versioninfo->fixed = fixedverinfo;
1345 r->u.versioninfo->var = verinfo;
1346 r->res_info.language = language;
1349 /* Add string version info to a list of version information. */
1352 append_ver_stringfileinfo (struct ver_info *verinfo, const char *language,
1353 struct ver_stringinfo *strings)
1355 struct ver_info *vi, **pp;
1357 vi = (struct ver_info *) res_alloc (sizeof *vi);
1359 vi->type = VERINFO_STRING;
1360 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1361 vi->u.string.strings = strings;
1363 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1370 /* Add variable version info to a list of version information. */
1373 append_ver_varfileinfo (struct ver_info *verinfo, const char *key,
1374 struct ver_varinfo *var)
1376 struct ver_info *vi, **pp;
1378 vi = (struct ver_info *) res_alloc (sizeof *vi);
1380 vi->type = VERINFO_VAR;
1381 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1382 vi->u.var.var = var;
1384 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1391 /* Append version string information to a list. */
1393 struct ver_stringinfo *
1394 append_verval (struct ver_stringinfo *strings, const char *key,
1397 struct ver_stringinfo *vs, **pp;
1399 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1401 unicode_from_ascii ((int *) NULL, &vs->key, key);
1402 unicode_from_ascii ((int *) NULL, &vs->value, value);
1404 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1411 /* Append version variable information to a list. */
1413 struct ver_varinfo *
1414 append_vertrans (struct ver_varinfo *var, unsigned long language,
1415 unsigned long charset)
1417 struct ver_varinfo *vv, **pp;
1419 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1421 vv->language = language;
1422 vv->charset = charset;
1424 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1431 /* Local functions used to write out an rc file. */
1433 static void indent (FILE *, int);
1434 static void write_rc_directory
1435 (FILE *, const struct res_directory *, const struct res_id *,
1436 const struct res_id *, int *, int);
1437 static void write_rc_subdir
1438 (FILE *, const struct res_entry *, const struct res_id *,
1439 const struct res_id *, int *, int);
1440 static void write_rc_resource
1441 (FILE *, const struct res_id *, const struct res_id *,
1442 const struct res_resource *, int *);
1443 static void write_rc_accelerators (FILE *, const struct accelerator *);
1444 static void write_rc_cursor (FILE *, const struct cursor *);
1445 static void write_rc_group_cursor (FILE *, const struct group_cursor *);
1446 static void write_rc_dialog (FILE *, const struct dialog *);
1447 static void write_rc_dialog_control (FILE *, const struct dialog_control *);
1448 static void write_rc_fontdir (FILE *, const struct fontdir *);
1449 static void write_rc_group_icon (FILE *, const struct group_icon *);
1450 static void write_rc_menu (FILE *, const struct menu *, int);
1451 static void write_rc_menuitems (FILE *, const struct menuitem *, int, int);
1452 static void write_rc_rcdata (FILE *, const struct rcdata_item *, int);
1453 static void write_rc_stringtable
1454 (FILE *, const struct res_id *, const struct stringtable *);
1455 static void write_rc_versioninfo (FILE *, const struct versioninfo *);
1456 static void write_rc_filedata (FILE *, unsigned long, const unsigned char *);
1458 /* Indent a given number of spaces. */
1461 indent (FILE *e, int c)
1465 for (i = 0; i < c; i++)
1469 /* Dump the resources we have read in the format of an rc file.
1471 Actually, we don't use the format of an rc file, because it's way
1472 too much of a pain--for example, we'd have to write icon resources
1473 into a file and refer to that file. We just generate a readable
1474 format that kind of looks like an rc file, and is useful for
1475 understanding the contents of a resource file. Someday we may want
1476 to generate an rc file which the rc compiler can read; if that day
1477 comes, this code will have to be fixed up. */
1480 write_rc_file (const char *filename, const struct res_directory *resources)
1485 if (filename == NULL)
1489 e = fopen (filename, FOPEN_WT);
1491 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1495 write_rc_directory (e, resources, (const struct res_id *) NULL,
1496 (const struct res_id *) NULL, &language, 1);
1499 /* Write out a directory. E is the file to write to. RD is the
1500 directory. TYPE is a pointer to the level 1 ID which serves as the
1501 resource type. NAME is a pointer to the level 2 ID which serves as
1502 an individual resource name. LANGUAGE is a pointer to the current
1503 language. LEVEL is the level in the tree. */
1506 write_rc_directory (FILE *e, const struct res_directory *rd,
1507 const struct res_id *type, const struct res_id *name,
1508 int *language, int level)
1510 const struct res_entry *re;
1512 /* Print out some COFF information that rc files can't represent. */
1515 fprintf (e, "// Time stamp: %lu\n", rd->time);
1516 if (rd->characteristics != 0)
1517 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1518 if (rd->major != 0 || rd->minor != 0)
1519 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1521 for (re = rd->entries; re != NULL; re = re->next)
1526 /* If we're at level 1, the key of this resource is the
1527 type. This normally duplicates the information we have
1528 stored with the resource itself, but we need to remember
1529 the type if this is a user define resource type. */
1534 /* If we're at level 2, the key of this resource is the name
1535 we are going to use in the rc printout. */
1540 /* If we're at level 3, then this key represents a language.
1541 Use it to update the current language. */
1543 && re->id.u.id != (unsigned long) (unsigned int) *language
1544 && (re->id.u.id & 0xffff) == re->id.u.id)
1546 fprintf (e, "LANGUAGE %lu, %lu\n",
1547 re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
1548 (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
1549 *language = re->id.u.id;
1558 write_rc_subdir (e, re, type, name, language, level);
1563 /* This is the normal case: the three levels are
1564 TYPE/NAME/LANGUAGE. NAME will have been set at level
1565 2, and represents the name to use. We probably just
1566 set LANGUAGE, and it will probably match what the
1567 resource itself records if anything. */
1568 write_rc_resource (e, type, name, re->u.res, language);
1572 fprintf (e, "// Resource at unexpected level %d\n", level);
1573 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1580 /* Write out a subdirectory entry. E is the file to write to. RE is
1581 the subdirectory entry. TYPE and NAME are pointers to higher level
1582 IDs, or NULL. LANGUAGE is a pointer to the current language.
1583 LEVEL is the level in the tree. */
1586 write_rc_subdir (FILE *e, const struct res_entry *re,
1587 const struct res_id *type, const struct res_id *name,
1588 int *language, int level)
1594 fprintf (e, "// Type: ");
1596 res_id_print (e, re->id, 1);
1601 switch (re->id.u.id)
1603 case RT_CURSOR: s = "cursor"; break;
1604 case RT_BITMAP: s = "bitmap"; break;
1605 case RT_ICON: s = "icon"; break;
1606 case RT_MENU: s = "menu"; break;
1607 case RT_DIALOG: s = "dialog"; break;
1608 case RT_STRING: s = "stringtable"; break;
1609 case RT_FONTDIR: s = "fontdir"; break;
1610 case RT_FONT: s = "font"; break;
1611 case RT_ACCELERATOR: s = "accelerators"; break;
1612 case RT_RCDATA: s = "rcdata"; break;
1613 case RT_MESSAGETABLE: s = "messagetable"; break;
1614 case RT_GROUP_CURSOR: s = "group cursor"; break;
1615 case RT_GROUP_ICON: s = "group icon"; break;
1616 case RT_VERSION: s = "version"; break;
1617 case RT_DLGINCLUDE: s = "dlginclude"; break;
1618 case RT_PLUGPLAY: s = "plugplay"; break;
1619 case RT_VXD: s = "vxd"; break;
1620 case RT_ANICURSOR: s = "anicursor"; break;
1621 case RT_ANIICON: s = "aniicon"; break;
1622 default: s = NULL; break;
1626 fprintf (e, "%s", s);
1628 res_id_print (e, re->id, 1);
1634 fprintf (e, "// Name: ");
1635 res_id_print (e, re->id, 1);
1640 fprintf (e, "// Language: ");
1641 res_id_print (e, re->id, 1);
1646 fprintf (e, "// Level %d: ", level);
1647 res_id_print (e, re->id, 1);
1651 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1654 /* Write out a single resource. E is the file to write to. TYPE is a
1655 pointer to the type of the resource. NAME is a pointer to the name
1656 of the resource; it will be NULL if there is a level mismatch. RES
1657 is the resource data. LANGUAGE is a pointer to the current
1661 write_rc_resource (FILE *e, const struct res_id *type,
1662 const struct res_id *name, const struct res_resource *res,
1676 case RES_TYPE_ACCELERATOR:
1678 rt = RT_ACCELERATOR;
1681 case RES_TYPE_BITMAP:
1686 case RES_TYPE_CURSOR:
1691 case RES_TYPE_GROUP_CURSOR:
1693 rt = RT_GROUP_CURSOR;
1696 case RES_TYPE_DIALOG:
1697 if (extended_dialog (res->u.dialog))
1709 case RES_TYPE_FONTDIR:
1719 case RES_TYPE_GROUP_ICON:
1725 if (extended_menu (res->u.menu))
1738 case RES_TYPE_MESSAGETABLE:
1740 rt = RT_MESSAGETABLE;
1743 case RES_TYPE_RCDATA:
1748 case RES_TYPE_STRINGTABLE:
1753 case RES_TYPE_USERDATA:
1758 case RES_TYPE_VERSIONINFO:
1766 && (type->named || type->u.id != (unsigned long) rt))
1768 fprintf (e, "// Unexpected resource type mismatch: ");
1769 res_id_print (e, *type, 1);
1770 fprintf (e, " != %d", rt);
1773 if (res->coff_info.codepage != 0)
1774 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1775 if (res->coff_info.reserved != 0)
1776 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1779 res_id_print (e, *name, 0);
1781 fprintf (e, "??Unknown-Name??");
1785 fprintf (e, "%s", s);
1786 else if (type != NULL)
1787 res_id_print (e, *type, 0);
1789 fprintf (e, "??Unknown-Type??");
1791 if (res->res_info.memflags != 0)
1793 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1794 fprintf (e, " MOVEABLE");
1795 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1796 fprintf (e, " PURE");
1797 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1798 fprintf (e, " PRELOAD");
1799 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1800 fprintf (e, " DISCARDABLE");
1803 if (res->type == RES_TYPE_DIALOG)
1805 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1806 res->u.dialog->width, res->u.dialog->height);
1807 if (res->u.dialog->ex != NULL
1808 && res->u.dialog->ex->help != 0)
1809 fprintf (e, ", %lu", res->u.dialog->ex->help);
1814 if ((res->res_info.language != 0 && res->res_info.language != *language)
1815 || res->res_info.characteristics != 0
1816 || res->res_info.version != 0)
1822 case RES_TYPE_ACCELERATOR:
1823 case RES_TYPE_DIALOG:
1825 case RES_TYPE_RCDATA:
1826 case RES_TYPE_STRINGTABLE:
1835 if (res->res_info.language != 0 && res->res_info.language != *language)
1836 fprintf (e, "%sLANGUAGE %d, %d\n",
1837 modifiers ? "// " : "",
1838 res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
1839 (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
1840 if (res->res_info.characteristics != 0)
1841 fprintf (e, "%sCHARACTERISTICS %lu\n",
1842 modifiers ? "// " : "",
1843 res->res_info.characteristics);
1844 if (res->res_info.version != 0)
1845 fprintf (e, "%sVERSION %lu\n",
1846 modifiers ? "// " : "",
1847 res->res_info.version);
1855 case RES_TYPE_ACCELERATOR:
1856 write_rc_accelerators (e, res->u.acc);
1859 case RES_TYPE_CURSOR:
1860 write_rc_cursor (e, res->u.cursor);
1863 case RES_TYPE_GROUP_CURSOR:
1864 write_rc_group_cursor (e, res->u.group_cursor);
1867 case RES_TYPE_DIALOG:
1868 write_rc_dialog (e, res->u.dialog);
1871 case RES_TYPE_FONTDIR:
1872 write_rc_fontdir (e, res->u.fontdir);
1875 case RES_TYPE_GROUP_ICON:
1876 write_rc_group_icon (e, res->u.group_icon);
1880 write_rc_menu (e, res->u.menu, menuex);
1883 case RES_TYPE_RCDATA:
1884 write_rc_rcdata (e, res->u.rcdata, 0);
1887 case RES_TYPE_STRINGTABLE:
1888 write_rc_stringtable (e, name, res->u.stringtable);
1891 case RES_TYPE_USERDATA:
1892 write_rc_rcdata (e, res->u.userdata, 0);
1895 case RES_TYPE_VERSIONINFO:
1896 write_rc_versioninfo (e, res->u.versioninfo);
1899 case RES_TYPE_BITMAP:
1902 case RES_TYPE_MESSAGETABLE:
1903 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1908 /* Write out accelerator information. */
1911 write_rc_accelerators (FILE *e, const struct accelerator *accelerators)
1913 const struct accelerator *acc;
1915 fprintf (e, "BEGIN\n");
1916 for (acc = accelerators; acc != NULL; acc = acc->next)
1922 if ((acc->key & 0x7f) == acc->key
1923 && ISPRINT (acc->key)
1924 && (acc->flags & ACC_VIRTKEY) == 0)
1926 fprintf (e, "\"%c\"", acc->key);
1931 fprintf (e, "%d", acc->key);
1935 fprintf (e, ", %d", acc->id);
1939 if ((acc->flags & ACC_VIRTKEY) != 0)
1940 fprintf (e, ", VIRTKEY");
1942 fprintf (e, ", ASCII");
1945 if ((acc->flags & ACC_SHIFT) != 0)
1946 fprintf (e, ", SHIFT");
1947 if ((acc->flags & ACC_CONTROL) != 0)
1948 fprintf (e, ", CONTROL");
1949 if ((acc->flags & ACC_ALT) != 0)
1950 fprintf (e, ", ALT");
1955 fprintf (e, "END\n");
1958 /* Write out cursor information. This would normally be in a separate
1959 file, which the rc file would include. */
1962 write_rc_cursor (FILE *e, const struct cursor *cursor)
1964 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1966 write_rc_filedata (e, cursor->length, cursor->data);
1969 /* Write out group cursor data. This would normally be built from the
1973 write_rc_group_cursor (FILE *e, const struct group_cursor *group_cursor)
1975 const struct group_cursor *gc;
1977 for (gc = group_cursor; gc != NULL; gc = gc->next)
1979 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1980 gc->width, gc->height, gc->planes, gc->bits);
1981 fprintf (e, "// data bytes: %lu; index: %d\n",
1982 gc->bytes, gc->index);
1986 /* Write dialog data. */
1989 write_rc_dialog (FILE *e, const struct dialog *dialog)
1991 const struct dialog_control *control;
1993 fprintf (e, "STYLE 0x%lx\n", dialog->style);
1995 if (dialog->exstyle != 0)
1996 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1998 if ((dialog->class.named && dialog->class.u.n.length > 0)
1999 || dialog->class.u.id != 0)
2001 fprintf (e, "CLASS ");
2002 res_id_print (e, dialog->class, 1);
2006 if (dialog->caption != NULL)
2008 fprintf (e, "CAPTION \"");
2009 unicode_print (e, dialog->caption, -1);
2010 fprintf (e, "\"\n");
2013 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2014 || dialog->menu.u.id != 0)
2016 fprintf (e, "MENU ");
2017 res_id_print (e, dialog->menu, 0);
2021 if (dialog->font != NULL)
2023 fprintf (e, "FONT %d, \"", dialog->pointsize);
2024 unicode_print (e, dialog->font, -1);
2026 if (dialog->ex != NULL
2027 && (dialog->ex->weight != 0
2028 || dialog->ex->italic != 0
2029 || dialog->ex->charset != 1))
2030 fprintf (e, ", %d, %d, %d",
2031 dialog->ex->weight, dialog->ex->italic, dialog->ex->charset);
2035 fprintf (e, "BEGIN\n");
2037 for (control = dialog->controls; control != NULL; control = control->next)
2038 write_rc_dialog_control (e, control);
2040 fprintf (e, "END\n");
2043 /* For each predefined control keyword, this table provides the class
2049 unsigned short class;
2050 unsigned long style;
2053 static const struct control_info control_info[] =
2055 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2056 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2057 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2058 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2059 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2060 { "CTEXT", CTL_STATIC, SS_CENTER },
2061 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2062 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2063 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2064 { "ICON", CTL_STATIC, SS_ICON },
2065 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2066 { "LTEXT", CTL_STATIC, SS_LEFT },
2067 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2068 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2069 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2070 { "RTEXT", CTL_STATIC, SS_RIGHT },
2071 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2072 { "STATE3", CTL_BUTTON, BS_3STATE },
2073 /* It's important that USERBUTTON come after all the other button
2074 types, so that it won't be matched too early. */
2075 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2079 /* Write a dialog control. */
2082 write_rc_dialog_control (FILE *e, const struct dialog_control *control)
2084 const struct control_info *ci;
2088 if (control->class.named)
2092 for (ci = control_info; ci->name != NULL; ++ci)
2093 if (ci->class == control->class.u.id
2094 && (ci->style == (unsigned long) -1
2095 || ci->style == (control->style & 0xff)))
2099 fprintf (e, "CONTROL");
2100 else if (ci->name != NULL)
2101 fprintf (e, "%s", ci->name);
2103 fprintf (e, "CONTROL");
2105 if (control->text.named || control->text.u.id != 0)
2108 res_id_print (e, control->text, 1);
2112 fprintf (e, " %d, ", control->id);
2116 if (control->class.named)
2118 res_id_print (e, control->class, 0);
2119 if (control->class.named)
2121 fprintf (e, ", 0x%lx, ", control->style);
2124 fprintf (e, "%d, %d", control->x, control->y);
2126 if (control->style != SS_ICON
2127 || control->exstyle != 0
2128 || control->width != 0
2129 || control->height != 0
2130 || control->help != 0)
2132 fprintf (e, ", %d, %d", control->width, control->height);
2134 /* FIXME: We don't need to print the style if it is the default.
2135 More importantly, in certain cases we actually need to turn
2136 off parts of the forced style, by using NOT. */
2137 fprintf (e, ", 0x%lx", control->style);
2139 if (control->exstyle != 0 || control->help != 0)
2140 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
2145 if (control->data != NULL)
2146 write_rc_rcdata (e, control->data, 2);
2149 /* Write out font directory data. This would normally be built from
2153 write_rc_fontdir (FILE *e, const struct fontdir *fontdir)
2155 const struct fontdir *fc;
2157 for (fc = fontdir; fc != NULL; fc = fc->next)
2159 fprintf (e, "// Font index: %d\n", fc->index);
2160 write_rc_filedata (e, fc->length, fc->data);
2164 /* Write out group icon data. This would normally be built from the
2168 write_rc_group_icon (FILE *e, const struct group_icon *group_icon)
2170 const struct group_icon *gi;
2172 for (gi = group_icon; gi != NULL; gi = gi->next)
2174 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2175 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
2176 fprintf (e, "// data bytes: %lu; index: %d\n",
2177 gi->bytes, gi->index);
2181 /* Write out a menu resource. */
2184 write_rc_menu (FILE *e, const struct menu *menu, int menuex)
2186 if (menu->help != 0)
2187 fprintf (e, "// Help ID: %lu\n", menu->help);
2188 write_rc_menuitems (e, menu->items, menuex, 0);
2191 /* Write out menuitems. */
2194 write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex,
2197 const struct menuitem *mi;
2200 fprintf (e, "BEGIN\n");
2202 for (mi = menuitems; mi != NULL; mi = mi->next)
2204 indent (e, ind + 2);
2206 if (mi->popup == NULL)
2207 fprintf (e, "MENUITEM");
2209 fprintf (e, "POPUP");
2212 && mi->popup == NULL
2217 fprintf (e, " SEPARATOR\n");
2221 if (mi->text == NULL)
2222 fprintf (e, " \"\"");
2226 unicode_print (e, mi->text, -1);
2232 if (mi->popup == NULL)
2233 fprintf (e, ", %d", mi->id);
2235 if ((mi->type & MENUITEM_CHECKED) != 0)
2236 fprintf (e, ", CHECKED");
2237 if ((mi->type & MENUITEM_GRAYED) != 0)
2238 fprintf (e, ", GRAYED");
2239 if ((mi->type & MENUITEM_HELP) != 0)
2240 fprintf (e, ", HELP");
2241 if ((mi->type & MENUITEM_INACTIVE) != 0)
2242 fprintf (e, ", INACTIVE");
2243 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2244 fprintf (e, ", MENUBARBREAK");
2245 if ((mi->type & MENUITEM_MENUBREAK) != 0)
2246 fprintf (e, ", MENUBREAK");
2250 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2252 fprintf (e, ", %d", mi->id);
2253 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2255 fprintf (e, ", %lu", mi->type);
2256 if (mi->state != 0 || mi->help != 0)
2258 fprintf (e, ", %lu", mi->state);
2260 fprintf (e, ", %lu", mi->help);
2268 if (mi->popup != NULL)
2269 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2273 fprintf (e, "END\n");
2276 /* Write out an rcdata resource. This is also used for other types of
2277 resources that need to print arbitrary data. */
2280 write_rc_rcdata (FILE *e, const struct rcdata_item *rcdata, int ind)
2282 const struct rcdata_item *ri;
2285 fprintf (e, "BEGIN\n");
2287 for (ri = rcdata; ri != NULL; ri = ri->next)
2289 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
2292 indent (e, ind + 2);
2300 fprintf (e, "%d", ri->u.word);
2304 fprintf (e, "%luL", ri->u.dword);
2314 for (i = 0; i < ri->u.string.length; i++)
2319 fprintf (e, "\\%03o", *s);
2325 case RCDATA_WSTRING:
2327 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2336 /* Assume little endian data. */
2339 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2345 indent (e, ind + 2);
2346 l = ((((((ri->u.buffer.data[i + 3] << 8)
2347 | ri->u.buffer.data[i + 2]) << 8)
2348 | ri->u.buffer.data[i + 1]) << 8)
2349 | ri->u.buffer.data[i]);
2350 fprintf (e, "%luL", l);
2351 if (i + 4 < ri->u.buffer.length || ri->next != NULL)
2353 for (j = 0; j < 4; ++j)
2354 if (! ISPRINT (ri->u.buffer.data[i + j])
2355 && ri->u.buffer.data[i + j] != 0)
2359 fprintf (e, "\t// ");
2360 for (j = 0; j < 4; ++j)
2362 if (! ISPRINT (ri->u.buffer.data[i + j]))
2363 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2366 if (ri->u.buffer.data[i + j] == '\\')
2368 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2376 if (i + 1 < ri->u.buffer.length)
2382 indent (e, ind + 2);
2383 s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2384 fprintf (e, "%d", s);
2385 if (i + 2 < ri->u.buffer.length || ri->next != NULL)
2387 for (j = 0; j < 2; ++j)
2388 if (! ISPRINT (ri->u.buffer.data[i + j])
2389 && ri->u.buffer.data[i + j] != 0)
2393 fprintf (e, "\t// ");
2394 for (j = 0; j < 2; ++j)
2396 if (! ISPRINT (ri->u.buffer.data[i + j]))
2397 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2400 if (ri->u.buffer.data[i + j] == '\\')
2402 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2411 if (i < ri->u.buffer.length)
2414 indent (e, ind + 2);
2415 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2416 && ISPRINT (ri->u.buffer.data[i]))
2417 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2419 fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
2420 if (ri->next != NULL)
2430 if (ri->type != RCDATA_BUFFER)
2432 if (ri->next != NULL)
2439 fprintf (e, "END\n");
2442 /* Write out a stringtable resource. */
2445 write_rc_stringtable (FILE *e, const struct res_id *name,
2446 const struct stringtable *stringtable)
2448 unsigned long offset;
2451 if (name != NULL && ! name->named)
2452 offset = (name->u.id - 1) << 4;
2455 fprintf (e, "// %s string table name\n",
2456 name == NULL ? "Missing" : "Invalid");
2460 fprintf (e, "BEGIN\n");
2462 for (i = 0; i < 16; i++)
2464 if (stringtable->strings[i].length != 0)
2466 fprintf (e, " %lu, \"", offset + i);
2467 unicode_print (e, stringtable->strings[i].string,
2468 stringtable->strings[i].length);
2469 fprintf (e, "\"\n");
2473 fprintf (e, "END\n");
2476 /* Write out a versioninfo resource. */
2479 write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo)
2481 const struct fixed_versioninfo *f;
2482 const struct ver_info *vi;
2484 f = versioninfo->fixed;
2485 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2486 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2487 (f->file_version_ms >> 16) & 0xffff,
2488 f->file_version_ms & 0xffff,
2489 (f->file_version_ls >> 16) & 0xffff,
2490 f->file_version_ls & 0xffff);
2491 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2492 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2493 (f->product_version_ms >> 16) & 0xffff,
2494 f->product_version_ms & 0xffff,
2495 (f->product_version_ls >> 16) & 0xffff,
2496 f->product_version_ls & 0xffff);
2497 if (f->file_flags_mask != 0)
2498 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2499 if (f->file_flags != 0)
2500 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2501 if (f->file_os != 0)
2502 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2503 if (f->file_type != 0)
2504 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2505 if (f->file_subtype != 0)
2506 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2507 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2508 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2510 fprintf (e, "BEGIN\n");
2512 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2516 case VERINFO_STRING:
2518 const struct ver_stringinfo *vs;
2520 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2521 fprintf (e, " BEGIN\n");
2522 fprintf (e, " BLOCK \"");
2523 unicode_print (e, vi->u.string.language, -1);
2524 fprintf (e, "\"\n");
2525 fprintf (e, " BEGIN\n");
2527 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2529 fprintf (e, " VALUE \"");
2530 unicode_print (e, vs->key, -1);
2531 fprintf (e, "\", \"");
2532 unicode_print (e, vs->value, -1);
2533 fprintf (e, "\"\n");
2536 fprintf (e, " END\n");
2537 fprintf (e, " END\n");
2543 const struct ver_varinfo *vv;
2545 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2546 fprintf (e, " BEGIN\n");
2547 fprintf (e, " VALUE \"");
2548 unicode_print (e, vi->u.var.key, -1);
2551 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2552 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2555 fprintf (e, "\n END\n");
2562 fprintf (e, "END\n");
2565 /* Write out data which would normally be read from a file. */
2568 write_rc_filedata (FILE *e, unsigned long length, const unsigned char *data)
2572 for (i = 0; i + 15 < length; i += 16)
2574 fprintf (e, "// %4lx: ", i);
2575 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2576 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2577 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2578 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2579 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2580 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2585 fprintf (e, "// %4lx:", i);
2588 fprintf (e, " %02x", data[i]);