1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 /* This file contains functions that read and write Windows rc files.
23 These are text files that represent resources. */
27 #include "libiberty.h"
38 #ifdef HAVE_SYS_WAIT_H
40 #else /* ! HAVE_SYS_WAIT_H */
41 #if ! defined (_WIN32) || defined (__CYGWIN__)
43 #define WIFEXITED(w) (((w)&0377) == 0)
46 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
49 #define WTERMSIG(w) ((w) & 0177)
52 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
54 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
56 #define WIFEXITED(w) (((w) & 0xff) == 0)
59 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
62 #define WTERMSIG(w) ((w) & 0x7f)
65 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
67 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
68 #endif /* ! HAVE_SYS_WAIT_H */
70 #if defined (_WIN32) && ! defined (__CYGWIN32__)
72 #define STDOUT_FILENO 1
75 #if defined (_WIN32) && ! defined (__CYGWIN__)
77 #define pclose _pclose
80 /* The default preprocessor. */
82 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
84 /* We read the directory entries in a cursor or icon file into
85 instances of this structure. */
91 /* Height of image. */
93 /* Number of colors in image. */
94 unsigned char colorcount;
100 unsigned short planes;
101 /* Bits per pixel. */
106 /* X coordinate of hotspot. */
107 unsigned short xhotspot;
108 /* Y coordinate of hotspot. */
109 unsigned short yhotspot;
112 /* Bytes in image. */
114 /* File offset of image. */
115 unsigned long offset;
118 /* The name of the rc file we are reading. */
122 /* The line number in the rc file. */
126 /* The pipe we are reading from, so that we can close it if we exit. */
128 static FILE *cpp_pipe;
130 /* The temporary file used if we're not using popen, so we can delete it
133 static char *cpp_temp_file;
135 /* Input stream is either a file or a pipe. */
137 static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
139 /* As we read the rc file, we attach information to this structure. */
141 static struct res_directory *resources;
143 /* The number of cursor resources we have written out. */
147 /* The number of font resources we have written out. */
151 /* Font directory information. */
153 struct fontdir *fontdirs;
155 /* Resource info to use for fontdirs. */
157 struct res_res_info fontdirs_resinfo;
159 /* The number of icon resources we have written out. */
163 /* Local functions. */
165 static int run_cmd PARAMS ((char *, const char *));
166 static FILE *open_input_stream PARAMS ((char *));
167 static FILE *look_for_default PARAMS ((char *, const char *, int,
168 const char *, const char *));
169 static void close_input_stream PARAMS ((void));
170 static void unexpected_eof PARAMS ((const char *));
171 static int get_word PARAMS ((FILE *, const char *));
172 static unsigned long get_long PARAMS ((FILE *, const char *));
174 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
175 static void define_fontdirs PARAMS ((void));
177 /* Run `cmd' and redirect the output to `redir'. */
185 int pid, wait_status, retcode;
188 char *errmsg_fmt, *errmsg_arg;
189 char *temp_base = choose_temp_base ();
192 int redir_handle = -1;
193 int stdout_save = -1;
195 /* Count the args. */
198 for (s = cmd; *s; s++)
203 argv = alloca (sizeof (char *) * (i + 3));
209 while (*s == ' ' && *s != 0)
215 in_quote = (*s == '\'' || *s == '"');
216 sep = (in_quote) ? *s++ : ' ';
219 while (*s != sep && *s != 0)
232 /* Setup the redirection. We can't use the usual fork/exec and redirect
233 since we may be running on non-POSIX Windows host. */
238 /* Open temporary output file. */
239 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
240 if (redir_handle == -1)
241 fatal (_("can't open temporary file `%s': %s"), redir,
244 /* Duplicate the stdout file handle so it can be restored later. */
245 stdout_save = dup (STDOUT_FILENO);
246 if (stdout_save == -1)
247 fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
249 /* Redirect stdout to our output file. */
250 dup2 (redir_handle, STDOUT_FILENO);
252 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
253 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
255 /* Restore stdout to its previous setting. */
256 dup2 (stdout_save, STDOUT_FILENO);
258 /* Close reponse file. */
259 close (redir_handle);
263 fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
268 pid = pwait (pid, &wait_status, 0);
272 fatal (_("wait: %s"), strerror (errno));
275 else if (WIFSIGNALED (wait_status))
277 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
280 else if (WIFEXITED (wait_status))
282 if (WEXITSTATUS (wait_status) != 0)
284 fatal (_("%s exited with status %d"), cmd,
285 WEXITSTATUS (wait_status));
296 open_input_stream (cmd)
299 if (istream_type == ISTREAM_FILE)
303 fileprefix = choose_temp_base ();
304 cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
305 sprintf (cpp_temp_file, "%s.irc", fileprefix);
308 if (run_cmd (cmd, cpp_temp_file))
309 fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
311 cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
312 if (cpp_pipe == NULL)
313 fatal (_("can't open temporary file `%s': %s"),
314 cpp_temp_file, strerror (errno));
318 _("Using temporary file `%s' to read preprocessor output\n"),
323 cpp_pipe = popen (cmd, FOPEN_RT);
324 if (cpp_pipe == NULL)
325 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
327 fprintf (stderr, _("Using popen to read preprocessor output\n"));
330 xatexit (close_input_stream);
334 /* look for the preprocessor program */
337 look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
341 const char *preprocargs;
342 const char *filename;
348 strcpy (cmd, prefix);
350 sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
351 space = strchr (cmd + end_prefix, ' ');
356 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
357 strchr (cmd, '\\') ||
361 found = (stat (cmd, &s) == 0
362 #ifdef HAVE_EXECUTABLE_SUFFIX
363 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
370 fprintf (stderr, _("Tried `%s'\n"), cmd);
375 strcpy (cmd, prefix);
377 sprintf (cmd + end_prefix, "%s %s %s",
378 DEFAULT_PREPROCESSOR, preprocargs, filename);
381 fprintf (stderr, _("Using `%s'\n"), cmd);
383 cpp_pipe = open_input_stream (cmd);
387 /* Read an rc file. */
389 struct res_directory *
390 read_rc_file (filename, preprocessor, preprocargs, language, use_temp_file)
391 const char *filename;
392 const char *preprocessor;
393 const char *preprocargs;
399 istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
401 if (preprocargs == NULL)
403 if (filename == NULL)
408 cmd = xmalloc (strlen (preprocessor)
409 + strlen (preprocargs)
412 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
414 cpp_pipe = open_input_stream (cmd);
418 char *dash, *slash, *cp;
420 preprocessor = DEFAULT_PREPROCESSOR;
422 cmd = xmalloc (strlen (program_name)
423 + strlen (preprocessor)
424 + strlen (preprocargs)
426 #ifdef HAVE_EXECUTABLE_SUFFIX
427 + strlen (EXECUTABLE_SUFFIX)
433 for (cp = program_name; *cp; cp++)
438 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
439 *cp == ':' || *cp == '\\' ||
452 /* First, try looking for a prefixed gcc in the windres
453 directory, with the same prefix as windres */
455 cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
456 preprocargs, filename);
459 if (slash && !cpp_pipe)
461 /* Next, try looking for a gcc in the same directory as
464 cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
465 preprocargs, filename);
470 /* Sigh, try the default */
472 cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
479 rc_filename = xstrdup (filename);
482 rcparse_set_language (language);
486 close_input_stream ();
488 if (fontdirs != NULL)
497 /* Close the input stream if it is open. */
500 close_input_stream ()
502 if (cpp_pipe != NULL)
505 if (istream_type == ISTREAM_FILE)
507 if (cpp_pipe != NULL)
510 if (cpp_temp_file != NULL)
512 int errno_save = errno;
514 unlink (cpp_temp_file);
516 free (cpp_temp_file);
521 if (cpp_pipe != NULL)
525 /* Since this is also run via xatexit, safeguard. */
527 cpp_temp_file = NULL;
530 /* Report an error while reading an rc file. */
536 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
539 /* Issue a warning while reading an rc file. */
542 rcparse_warning (msg)
545 fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
548 /* Die if we get an unexpected end of file. */
554 fatal (_("%s: unexpected EOF"), msg);
557 /* Read a 16 bit word from a file. The data is assumed to be little
570 unexpected_eof (msg);
571 return ((b2 & 0xff) << 8) | (b1 & 0xff);
574 /* Read a 32 bit word from a file. The data is assumed to be little
589 unexpected_eof (msg);
590 return (((((((b4 & 0xff) << 8)
596 /* Read data from a file. This is a wrapper to do error checking. */
599 get_data (e, p, c, msg)
607 got = fread (p, 1, c, e);
611 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
614 /* Define an accelerator resource. */
617 define_accelerator (id, resinfo, data)
619 const struct res_res_info *resinfo;
620 struct accelerator *data;
622 struct res_resource *r;
624 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
625 resinfo->language, 0);
626 r->type = RES_TYPE_ACCELERATOR;
628 r->res_info = *resinfo;
631 /* Define a bitmap resource. Bitmap data is stored in a file. The
632 first 14 bytes of the file are a standard header, which is not
633 included in the resource data. */
635 #define BITMAP_SKIP (14)
638 define_bitmap (id, resinfo, filename)
640 const struct res_res_info *resinfo;
641 const char *filename;
648 struct res_resource *r;
650 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
652 if (stat (real_filename, &s) < 0)
653 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
656 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
658 for (i = 0; i < BITMAP_SKIP; i++)
661 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
664 free (real_filename);
666 r = define_standard_resource (&resources, RT_BITMAP, id,
667 resinfo->language, 0);
669 r->type = RES_TYPE_BITMAP;
670 r->u.data.length = s.st_size - BITMAP_SKIP;
671 r->u.data.data = data;
672 r->res_info = *resinfo;
675 /* Define a cursor resource. A cursor file may contain a set of
676 bitmaps, each representing the same cursor at various different
677 resolutions. They each get written out with a different ID. The
678 real cursor resource is then a group resource which can be used to
679 select one of the actual cursors. */
682 define_cursor (id, resinfo, filename)
684 const struct res_res_info *resinfo;
685 const char *filename;
690 struct icondir *icondirs;
692 struct res_resource *r;
693 struct group_cursor *first, **pp;
695 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
697 /* A cursor file is basically an icon file. The start of the file
698 is a three word structure. The first word is ignored. The
699 second word is the type of data. The third word is the number of
702 get_word (e, real_filename);
703 type = get_word (e, real_filename);
704 count = get_word (e, real_filename);
706 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
708 /* Read in the icon directory entries. */
710 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
712 for (i = 0; i < count; i++)
714 icondirs[i].width = getc (e);
715 icondirs[i].height = getc (e);
716 icondirs[i].colorcount = getc (e);
718 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
719 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
720 icondirs[i].bytes = get_long (e, real_filename);
721 icondirs[i].offset = get_long (e, real_filename);
724 unexpected_eof (real_filename);
727 /* Define each cursor as a unique resource. */
729 first_cursor = cursors;
731 for (i = 0; i < count; i++)
737 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
738 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
739 icondirs[i].offset, strerror (errno));
741 data = (unsigned char *) res_alloc (icondirs[i].bytes);
743 get_data (e, data, icondirs[i].bytes, real_filename);
745 c = (struct cursor *) res_alloc (sizeof *c);
746 c->xhotspot = icondirs[i].u.cursor.xhotspot;
747 c->yhotspot = icondirs[i].u.cursor.yhotspot;
748 c->length = icondirs[i].bytes;
756 r = define_standard_resource (&resources, RT_CURSOR, name,
757 resinfo->language, 0);
758 r->type = RES_TYPE_CURSOR;
760 r->res_info = *resinfo;
764 free (real_filename);
766 /* Define a cursor group resource. */
770 for (i = 0; i < count; i++)
772 struct group_cursor *cg;
774 cg = (struct group_cursor *) res_alloc (sizeof *cg);
776 cg->width = icondirs[i].width;
777 cg->height = 2 * icondirs[i].height;
779 /* FIXME: What should these be set to? */
783 cg->bytes = icondirs[i].bytes + 4;
784 cg->index = first_cursor + i + 1;
792 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
793 resinfo->language, 0);
794 r->type = RES_TYPE_GROUP_CURSOR;
795 r->u.group_cursor = first;
796 r->res_info = *resinfo;
799 /* Define a dialog resource. */
802 define_dialog (id, resinfo, dialog)
804 const struct res_res_info *resinfo;
805 const struct dialog *dialog;
808 struct res_resource *r;
810 copy = (struct dialog *) res_alloc (sizeof *copy);
813 r = define_standard_resource (&resources, RT_DIALOG, id,
814 resinfo->language, 0);
815 r->type = RES_TYPE_DIALOG;
817 r->res_info = *resinfo;
820 /* Define a dialog control. This does not define a resource, but
821 merely allocates and fills in a structure. */
823 struct dialog_control *
824 define_control (text, id, x, y, width, height, class, style, exstyle)
830 unsigned long height;
833 unsigned long exstyle;
835 struct dialog_control *n;
837 n = (struct dialog_control *) res_alloc (sizeof *n);
841 n->exstyle = exstyle;
847 n->class.u.id = class;
849 res_string_to_id (&n->text, text);
861 /* Define a font resource. */
864 define_font (id, resinfo, filename)
866 const struct res_res_info *resinfo;
867 const char *filename;
873 struct res_resource *r;
876 unsigned char *fontdata;
878 const char *device, *face;
881 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
883 if (stat (real_filename, &s) < 0)
884 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
887 data = (unsigned char *) res_alloc (s.st_size);
889 get_data (e, data, s.st_size, real_filename);
892 free (real_filename);
894 r = define_standard_resource (&resources, RT_FONT, id,
895 resinfo->language, 0);
897 r->type = RES_TYPE_FONT;
898 r->u.data.length = s.st_size;
899 r->u.data.data = data;
900 r->res_info = *resinfo;
902 /* For each font resource, we must add an entry in the FONTDIR
903 resource. The FONTDIR resource includes some strings in the font
904 file. To find them, we have to do some magic on the data we have
907 offset = ((((((data[47] << 8)
911 if (offset > 0 && offset < s.st_size)
912 device = (char *) data + offset;
916 offset = ((((((data[51] << 8)
920 if (offset > 0 && offset < s.st_size)
921 face = (char *) data + offset;
927 fontdatalength = 58 + strlen (device) + strlen (face);
928 fontdata = (unsigned char *) res_alloc (fontdatalength);
929 memcpy (fontdata, data, 56);
930 strcpy ((char *) fontdata + 56, device);
931 strcpy ((char *) fontdata + 57 + strlen (device), face);
933 fd = (struct fontdir *) res_alloc (sizeof *fd);
936 fd->length = fontdatalength;
939 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
943 /* For the single fontdirs resource, we always use the resource
944 information of the last font. I don't know what else to do. */
945 fontdirs_resinfo = *resinfo;
948 /* Define the fontdirs resource. This is called after the entire rc
949 file has been parsed, if any font resources were seen. */
954 struct res_resource *r;
960 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
962 r->type = RES_TYPE_FONTDIR;
963 r->u.fontdir = fontdirs;
964 r->res_info = fontdirs_resinfo;
967 /* Define an icon resource. An icon file may contain a set of
968 bitmaps, each representing the same icon at various different
969 resolutions. They each get written out with a different ID. The
970 real icon resource is then a group resource which can be used to
971 select one of the actual icon bitmaps. */
974 define_icon (id, resinfo, filename)
976 const struct res_res_info *resinfo;
977 const char *filename;
982 struct icondir *icondirs;
984 struct res_resource *r;
985 struct group_icon *first, **pp;
987 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
989 /* The start of an icon file is a three word structure. The first
990 word is ignored. The second word is the type of data. The third
991 word is the number of entries. */
993 get_word (e, real_filename);
994 type = get_word (e, real_filename);
995 count = get_word (e, real_filename);
997 fatal (_("icon file `%s' does not contain icon data"), real_filename);
999 /* Read in the icon directory entries. */
1001 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
1003 for (i = 0; i < count; i++)
1005 icondirs[i].width = getc (e);
1006 icondirs[i].height = getc (e);
1007 icondirs[i].colorcount = getc (e);
1009 icondirs[i].u.icon.planes = get_word (e, real_filename);
1010 icondirs[i].u.icon.bits = get_word (e, real_filename);
1011 icondirs[i].bytes = get_long (e, real_filename);
1012 icondirs[i].offset = get_long (e, real_filename);
1015 unexpected_eof (real_filename);
1018 /* Define each icon as a unique resource. */
1022 for (i = 0; i < count; i++)
1024 unsigned char *data;
1027 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1028 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1029 icondirs[i].offset, strerror (errno));
1031 data = (unsigned char *) res_alloc (icondirs[i].bytes);
1033 get_data (e, data, icondirs[i].bytes, real_filename);
1040 r = define_standard_resource (&resources, RT_ICON, name,
1041 resinfo->language, 0);
1042 r->type = RES_TYPE_ICON;
1043 r->u.data.length = icondirs[i].bytes;
1044 r->u.data.data = data;
1045 r->res_info = *resinfo;
1049 free (real_filename);
1051 /* Define an icon group resource. */
1055 for (i = 0; i < count; i++)
1057 struct group_icon *cg;
1059 /* For some reason, at least in some files the planes and bits
1060 are zero. We instead set them from the color. This is
1063 cg = (struct group_icon *) res_alloc (sizeof *cg);
1065 cg->width = icondirs[i].width;
1066 cg->height = icondirs[i].height;
1067 cg->colors = icondirs[i].colorcount;
1071 while ((1 << cg->bits) < cg->colors)
1074 cg->bytes = icondirs[i].bytes;
1075 cg->index = first_icon + i + 1;
1083 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1084 resinfo->language, 0);
1085 r->type = RES_TYPE_GROUP_ICON;
1086 r->u.group_icon = first;
1087 r->res_info = *resinfo;
1090 /* Define a menu resource. */
1093 define_menu (id, resinfo, menuitems)
1095 const struct res_res_info *resinfo;
1096 struct menuitem *menuitems;
1099 struct res_resource *r;
1101 m = (struct menu *) res_alloc (sizeof *m);
1102 m->items = menuitems;
1105 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1106 r->type = RES_TYPE_MENU;
1108 r->res_info = *resinfo;
1111 /* Define a menu item. This does not define a resource, but merely
1112 allocates and fills in a structure. */
1115 define_menuitem (text, menuid, type, state, help, menuitems)
1119 unsigned long state;
1121 struct menuitem *menuitems;
1123 struct menuitem *mi;
1125 mi = (struct menuitem *) res_alloc (sizeof *mi);
1133 unicode_from_ascii ((int *) NULL, &mi->text, text);
1135 mi->popup = menuitems;
1139 /* Define a messagetable resource. */
1142 define_messagetable (id, resinfo, filename)
1144 const struct res_res_info *resinfo;
1145 const char *filename;
1148 char *real_filename;
1150 unsigned char *data;
1151 struct res_resource *r;
1153 e = open_file_search (filename, FOPEN_RB, "messagetable file",
1156 if (stat (real_filename, &s) < 0)
1157 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1160 data = (unsigned char *) res_alloc (s.st_size);
1162 get_data (e, data, s.st_size, real_filename);
1165 free (real_filename);
1167 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1168 resinfo->language, 0);
1170 r->type = RES_TYPE_MESSAGETABLE;
1171 r->u.data.length = s.st_size;
1172 r->u.data.data = data;
1173 r->res_info = *resinfo;
1176 /* Define an rcdata resource. */
1179 define_rcdata (id, resinfo, data)
1181 const struct res_res_info *resinfo;
1182 struct rcdata_item *data;
1184 struct res_resource *r;
1186 r = define_standard_resource (&resources, RT_RCDATA, id,
1187 resinfo->language, 0);
1188 r->type = RES_TYPE_RCDATA;
1190 r->res_info = *resinfo;
1193 /* Create an rcdata item holding a string. */
1195 struct rcdata_item *
1196 define_rcdata_string (string, len)
1200 struct rcdata_item *ri;
1203 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1205 ri->type = RCDATA_STRING;
1206 ri->u.string.length = len;
1207 s = (char *) res_alloc (len);
1208 memcpy (s, string, len);
1214 /* Create an rcdata item holding a number. */
1216 struct rcdata_item *
1217 define_rcdata_number (val, dword)
1221 struct rcdata_item *ri;
1223 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1225 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1231 /* Define a stringtable resource. This is called for each string
1232 which appears in a STRINGTABLE statement. */
1235 define_stringtable (resinfo, stringid, string)
1236 const struct res_res_info *resinfo;
1237 unsigned long stringid;
1241 struct res_resource *r;
1244 id.u.id = (stringid >> 4) + 1;
1245 r = define_standard_resource (&resources, RT_STRING, id,
1246 resinfo->language, 1);
1248 if (r->type == RES_TYPE_UNINITIALIZED)
1252 r->type = RES_TYPE_STRINGTABLE;
1253 r->u.stringtable = ((struct stringtable *)
1254 res_alloc (sizeof (struct stringtable)));
1255 for (i = 0; i < 16; i++)
1257 r->u.stringtable->strings[i].length = 0;
1258 r->u.stringtable->strings[i].string = NULL;
1261 r->res_info = *resinfo;
1264 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
1265 &r->u.stringtable->strings[stringid & 0xf].string,
1269 /* Define a user data resource where the data is in the rc file. */
1272 define_user_data (id, type, resinfo, data)
1275 const struct res_res_info *resinfo;
1276 struct rcdata_item *data;
1278 struct res_id ids[3];
1279 struct res_resource *r;
1284 ids[2].u.id = resinfo->language;
1286 r = define_resource (&resources, 3, ids, 0);
1287 r->type = RES_TYPE_USERDATA;
1288 r->u.userdata = data;
1289 r->res_info = *resinfo;
1292 /* Define a user data resource where the data is in a file. */
1295 define_user_file (id, type, resinfo, filename)
1298 const struct res_res_info *resinfo;
1299 const char *filename;
1302 char *real_filename;
1304 unsigned char *data;
1305 struct res_id ids[3];
1306 struct res_resource *r;
1308 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
1310 if (stat (real_filename, &s) < 0)
1311 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1314 data = (unsigned char *) res_alloc (s.st_size);
1316 get_data (e, data, s.st_size, real_filename);
1319 free (real_filename);
1324 ids[2].u.id = resinfo->language;
1326 r = define_resource (&resources, 3, ids, 0);
1327 r->type = RES_TYPE_USERDATA;
1328 r->u.userdata = ((struct rcdata_item *)
1329 res_alloc (sizeof (struct rcdata_item)));
1330 r->u.userdata->next = NULL;
1331 r->u.userdata->type = RCDATA_BUFFER;
1332 r->u.userdata->u.buffer.length = s.st_size;
1333 r->u.userdata->u.buffer.data = data;
1334 r->res_info = *resinfo;
1337 /* Define a versioninfo resource. */
1340 define_versioninfo (id, language, fixedverinfo, verinfo)
1343 struct fixed_versioninfo *fixedverinfo;
1344 struct ver_info *verinfo;
1346 struct res_resource *r;
1348 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1349 r->type = RES_TYPE_VERSIONINFO;
1350 r->u.versioninfo = ((struct versioninfo *)
1351 res_alloc (sizeof (struct versioninfo)));
1352 r->u.versioninfo->fixed = fixedverinfo;
1353 r->u.versioninfo->var = verinfo;
1354 r->res_info.language = language;
1357 /* Add string version info to a list of version information. */
1360 append_ver_stringfileinfo (verinfo, language, strings)
1361 struct ver_info *verinfo;
1362 const char *language;
1363 struct ver_stringinfo *strings;
1365 struct ver_info *vi, **pp;
1367 vi = (struct ver_info *) res_alloc (sizeof *vi);
1369 vi->type = VERINFO_STRING;
1370 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1371 vi->u.string.strings = strings;
1373 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1380 /* Add variable version info to a list of version information. */
1383 append_ver_varfileinfo (verinfo, key, var)
1384 struct ver_info *verinfo;
1386 struct ver_varinfo *var;
1388 struct ver_info *vi, **pp;
1390 vi = (struct ver_info *) res_alloc (sizeof *vi);
1392 vi->type = VERINFO_VAR;
1393 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1394 vi->u.var.var = var;
1396 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1403 /* Append version string information to a list. */
1405 struct ver_stringinfo *
1406 append_verval (strings, key, value)
1407 struct ver_stringinfo *strings;
1411 struct ver_stringinfo *vs, **pp;
1413 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1415 unicode_from_ascii ((int *) NULL, &vs->key, key);
1416 unicode_from_ascii ((int *) NULL, &vs->value, value);
1418 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1425 /* Append version variable information to a list. */
1427 struct ver_varinfo *
1428 append_vertrans (var, language, charset)
1429 struct ver_varinfo *var;
1430 unsigned long language;
1431 unsigned long charset;
1433 struct ver_varinfo *vv, **pp;
1435 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1437 vv->language = language;
1438 vv->charset = charset;
1440 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1447 /* Local functions used to write out an rc file. */
1449 static void indent PARAMS ((FILE *, int));
1450 static void write_rc_directory
1451 PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1452 const struct res_id *, int *, int));
1453 static void write_rc_subdir
1454 PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1455 const struct res_id *, int *, int));
1456 static void write_rc_resource
1457 PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1458 const struct res_resource *, int *));
1459 static void write_rc_accelerators
1460 PARAMS ((FILE *, const struct accelerator *));
1461 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1462 static void write_rc_group_cursor
1463 PARAMS ((FILE *, const struct group_cursor *));
1464 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1465 static void write_rc_dialog_control
1466 PARAMS ((FILE *, const struct dialog_control *));
1467 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1468 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1469 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1470 static void write_rc_menuitems
1471 PARAMS ((FILE *, const struct menuitem *, int, int));
1472 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1473 static void write_rc_stringtable
1474 PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1475 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1476 static void write_rc_filedata
1477 PARAMS ((FILE *, unsigned long, const unsigned char *));
1479 /* Indent a given number of spaces. */
1488 for (i = 0; i < c; i++)
1492 /* Dump the resources we have read in the format of an rc file.
1494 Actually, we don't use the format of an rc file, because it's way
1495 too much of a pain--for example, we'd have to write icon resources
1496 into a file and refer to that file. We just generate a readable
1497 format that kind of looks like an rc file, and is useful for
1498 understanding the contents of a resource file. Someday we may want
1499 to generate an rc file which the rc compiler can read; if that day
1500 comes, this code will have to be fixed up. */
1503 write_rc_file (filename, resources)
1504 const char *filename;
1505 const struct res_directory *resources;
1510 if (filename == NULL)
1514 e = fopen (filename, FOPEN_WT);
1516 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1520 write_rc_directory (e, resources, (const struct res_id *) NULL,
1521 (const struct res_id *) NULL, &language, 1);
1524 /* Write out a directory. E is the file to write to. RD is the
1525 directory. TYPE is a pointer to the level 1 ID which serves as the
1526 resource type. NAME is a pointer to the level 2 ID which serves as
1527 an individual resource name. LANGUAGE is a pointer to the current
1528 language. LEVEL is the level in the tree. */
1531 write_rc_directory (e, rd, type, name, language, level)
1533 const struct res_directory *rd;
1534 const struct res_id *type;
1535 const struct res_id *name;
1539 const struct res_entry *re;
1541 /* Print out some COFF information that rc files can't represent. */
1544 fprintf (e, "// Time stamp: %lu\n", rd->time);
1545 if (rd->characteristics != 0)
1546 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1547 if (rd->major != 0 || rd->minor != 0)
1548 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1550 for (re = rd->entries; re != NULL; re = re->next)
1555 /* If we're at level 1, the key of this resource is the
1556 type. This normally duplicates the information we have
1557 stored with the resource itself, but we need to remember
1558 the type if this is a user define resource type. */
1563 /* If we're at level 2, the key of this resource is the name
1564 we are going to use in the rc printout. */
1569 /* If we're at level 3, then this key represents a language.
1570 Use it to update the current language. */
1572 && re->id.u.id != (unsigned long) (unsigned int) *language
1573 && (re->id.u.id & 0xffff) == re->id.u.id)
1575 fprintf (e, "LANGUAGE %lu, %lu\n",
1576 re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1577 *language = re->id.u.id;
1586 write_rc_subdir (e, re, type, name, language, level);
1591 /* This is the normal case: the three levels are
1592 TYPE/NAME/LANGUAGE. NAME will have been set at level
1593 2, and represents the name to use. We probably just
1594 set LANGUAGE, and it will probably match what the
1595 resource itself records if anything. */
1596 write_rc_resource (e, type, name, re->u.res, language);
1600 fprintf (e, "// Resource at unexpected level %d\n", level);
1601 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1608 /* Write out a subdirectory entry. E is the file to write to. RE is
1609 the subdirectory entry. TYPE and NAME are pointers to higher level
1610 IDs, or NULL. LANGUAGE is a pointer to the current language.
1611 LEVEL is the level in the tree. */
1614 write_rc_subdir (e, re, type, name, language, level)
1616 const struct res_entry *re;
1617 const struct res_id *type;
1618 const struct res_id *name;
1626 fprintf (e, "// Type: ");
1628 res_id_print (e, re->id, 1);
1633 switch (re->id.u.id)
1635 case RT_CURSOR: s = "cursor"; break;
1636 case RT_BITMAP: s = "bitmap"; break;
1637 case RT_ICON: s = "icon"; break;
1638 case RT_MENU: s = "menu"; break;
1639 case RT_DIALOG: s = "dialog"; break;
1640 case RT_STRING: s = "stringtable"; break;
1641 case RT_FONTDIR: s = "fontdir"; break;
1642 case RT_FONT: s = "font"; break;
1643 case RT_ACCELERATOR: s = "accelerators"; break;
1644 case RT_RCDATA: s = "rcdata"; break;
1645 case RT_MESSAGETABLE: s = "messagetable"; break;
1646 case RT_GROUP_CURSOR: s = "group cursor"; break;
1647 case RT_GROUP_ICON: s = "group icon"; break;
1648 case RT_VERSION: s = "version"; break;
1649 case RT_DLGINCLUDE: s = "dlginclude"; break;
1650 case RT_PLUGPLAY: s = "plugplay"; break;
1651 case RT_VXD: s = "vxd"; break;
1652 case RT_ANICURSOR: s = "anicursor"; break;
1653 case RT_ANIICON: s = "aniicon"; break;
1654 default: s = NULL; break;
1658 fprintf (e, "%s", s);
1660 res_id_print (e, re->id, 1);
1666 fprintf (e, "// Name: ");
1667 res_id_print (e, re->id, 1);
1672 fprintf (e, "// Language: ");
1673 res_id_print (e, re->id, 1);
1678 fprintf (e, "// Level %d: ", level);
1679 res_id_print (e, re->id, 1);
1683 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1686 /* Write out a single resource. E is the file to write to. TYPE is a
1687 pointer to the type of the resource. NAME is a pointer to the name
1688 of the resource; it will be NULL if there is a level mismatch. RES
1689 is the resource data. LANGUAGE is a pointer to the current
1693 write_rc_resource (e, type, name, res, language)
1695 const struct res_id *type;
1696 const struct res_id *name;
1697 const struct res_resource *res;
1711 case RES_TYPE_ACCELERATOR:
1713 rt = RT_ACCELERATOR;
1716 case RES_TYPE_BITMAP:
1721 case RES_TYPE_CURSOR:
1726 case RES_TYPE_GROUP_CURSOR:
1728 rt = RT_GROUP_CURSOR;
1731 case RES_TYPE_DIALOG:
1732 if (extended_dialog (res->u.dialog))
1744 case RES_TYPE_FONTDIR:
1754 case RES_TYPE_GROUP_ICON:
1760 if (extended_menu (res->u.menu))
1773 case RES_TYPE_MESSAGETABLE:
1775 rt = RT_MESSAGETABLE;
1778 case RES_TYPE_RCDATA:
1783 case RES_TYPE_STRINGTABLE:
1788 case RES_TYPE_USERDATA:
1793 case RES_TYPE_VERSIONINFO:
1801 && (type->named || type->u.id != (unsigned long) rt))
1803 fprintf (e, "// Unexpected resource type mismatch: ");
1804 res_id_print (e, *type, 1);
1805 fprintf (e, " != %d", rt);
1808 if (res->coff_info.codepage != 0)
1809 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1810 if (res->coff_info.reserved != 0)
1811 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1814 res_id_print (e, *name, 0);
1816 fprintf (e, "??Unknown-Name??");
1820 fprintf (e, "%s", s);
1821 else if (type != NULL)
1822 res_id_print (e, *type, 0);
1824 fprintf (e, "??Unknown-Type??");
1826 if (res->res_info.memflags != 0)
1828 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1829 fprintf (e, " MOVEABLE");
1830 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1831 fprintf (e, " PURE");
1832 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1833 fprintf (e, " PRELOAD");
1834 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1835 fprintf (e, " DISCARDABLE");
1838 if (res->type == RES_TYPE_DIALOG)
1840 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1841 res->u.dialog->width, res->u.dialog->height);
1842 if (res->u.dialog->ex != NULL
1843 && res->u.dialog->ex->help != 0)
1844 fprintf (e, ", %lu", res->u.dialog->ex->help);
1849 if ((res->res_info.language != 0 && res->res_info.language != *language)
1850 || res->res_info.characteristics != 0
1851 || res->res_info.version != 0)
1857 case RES_TYPE_ACCELERATOR:
1858 case RES_TYPE_DIALOG:
1860 case RES_TYPE_RCDATA:
1861 case RES_TYPE_STRINGTABLE:
1870 if (res->res_info.language != 0 && res->res_info.language != *language)
1871 fprintf (e, "%sLANGUAGE %d, %d\n",
1872 modifiers ? "// " : "",
1873 res->res_info.language & 0xff,
1874 (res->res_info.language >> 8) & 0xff);
1875 if (res->res_info.characteristics != 0)
1876 fprintf (e, "%sCHARACTERISTICS %lu\n",
1877 modifiers ? "// " : "",
1878 res->res_info.characteristics);
1879 if (res->res_info.version != 0)
1880 fprintf (e, "%sVERSION %lu\n",
1881 modifiers ? "// " : "",
1882 res->res_info.version);
1890 case RES_TYPE_ACCELERATOR:
1891 write_rc_accelerators (e, res->u.acc);
1894 case RES_TYPE_CURSOR:
1895 write_rc_cursor (e, res->u.cursor);
1898 case RES_TYPE_GROUP_CURSOR:
1899 write_rc_group_cursor (e, res->u.group_cursor);
1902 case RES_TYPE_DIALOG:
1903 write_rc_dialog (e, res->u.dialog);
1906 case RES_TYPE_FONTDIR:
1907 write_rc_fontdir (e, res->u.fontdir);
1910 case RES_TYPE_GROUP_ICON:
1911 write_rc_group_icon (e, res->u.group_icon);
1915 write_rc_menu (e, res->u.menu, menuex);
1918 case RES_TYPE_RCDATA:
1919 write_rc_rcdata (e, res->u.rcdata, 0);
1922 case RES_TYPE_STRINGTABLE:
1923 write_rc_stringtable (e, name, res->u.stringtable);
1926 case RES_TYPE_USERDATA:
1927 write_rc_rcdata (e, res->u.userdata, 0);
1930 case RES_TYPE_VERSIONINFO:
1931 write_rc_versioninfo (e, res->u.versioninfo);
1934 case RES_TYPE_BITMAP:
1937 case RES_TYPE_MESSAGETABLE:
1938 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1943 /* Write out accelerator information. */
1946 write_rc_accelerators (e, accelerators)
1948 const struct accelerator *accelerators;
1950 const struct accelerator *acc;
1952 fprintf (e, "BEGIN\n");
1953 for (acc = accelerators; acc != NULL; acc = acc->next)
1959 if ((acc->key & 0x7f) == acc->key
1960 && isprint ((unsigned char) acc->key)
1961 && (acc->flags & ACC_VIRTKEY) == 0)
1963 fprintf (e, "\"%c\"", acc->key);
1968 fprintf (e, "%d", acc->key);
1972 fprintf (e, ", %d", acc->id);
1976 if ((acc->flags & ACC_VIRTKEY) != 0)
1977 fprintf (e, ", VIRTKEY");
1979 fprintf (e, ", ASCII");
1982 if ((acc->flags & ACC_SHIFT) != 0)
1983 fprintf (e, ", SHIFT");
1984 if ((acc->flags & ACC_CONTROL) != 0)
1985 fprintf (e, ", CONTROL");
1986 if ((acc->flags & ACC_ALT) != 0)
1987 fprintf (e, ", ALT");
1992 fprintf (e, "END\n");
1995 /* Write out cursor information. This would normally be in a separate
1996 file, which the rc file would include. */
1999 write_rc_cursor (e, cursor)
2001 const struct cursor *cursor;
2003 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
2005 write_rc_filedata (e, cursor->length, cursor->data);
2008 /* Write out group cursor data. This would normally be built from the
2012 write_rc_group_cursor (e, group_cursor)
2014 const struct group_cursor *group_cursor;
2016 const struct group_cursor *gc;
2018 for (gc = group_cursor; gc != NULL; gc = gc->next)
2020 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
2021 gc->width, gc->height, gc->planes, gc->bits);
2022 fprintf (e, "// data bytes: %lu; index: %d\n",
2023 gc->bytes, gc->index);
2027 /* Write dialog data. */
2030 write_rc_dialog (e, dialog)
2032 const struct dialog *dialog;
2034 const struct dialog_control *control;
2036 if (dialog->style != 0)
2037 fprintf (e, "STYLE 0x%lx\n", dialog->style);
2038 if (dialog->exstyle != 0)
2039 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
2040 if ((dialog->class.named && dialog->class.u.n.length > 0)
2041 || dialog->class.u.id != 0)
2043 fprintf (e, "CLASS ");
2044 res_id_print (e, dialog->class, 0);
2047 if (dialog->caption != NULL)
2049 fprintf (e, "CAPTION \"");
2050 unicode_print (e, dialog->caption, -1);
2051 fprintf (e, "\"\n");
2053 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2054 || dialog->menu.u.id != 0)
2056 fprintf (e, "MENU ");
2057 res_id_print (e, dialog->menu, 0);
2060 if (dialog->font != NULL)
2062 fprintf (e, "FONT %d, \"", dialog->pointsize);
2063 unicode_print (e, dialog->font, -1);
2065 if (dialog->ex != NULL
2066 && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
2067 fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
2071 fprintf (e, "BEGIN\n");
2073 for (control = dialog->controls; control != NULL; control = control->next)
2074 write_rc_dialog_control (e, control);
2076 fprintf (e, "END\n");
2079 /* For each predefined control keyword, this table provides the class
2085 unsigned short class;
2086 unsigned long style;
2089 static const struct control_info control_info[] =
2091 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2092 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2093 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2094 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2095 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2096 { "CTEXT", CTL_STATIC, SS_CENTER },
2097 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2098 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2099 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2100 { "ICON", CTL_STATIC, SS_ICON },
2101 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2102 { "LTEXT", CTL_STATIC, SS_LEFT },
2103 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2104 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2105 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2106 { "RTEXT", CTL_STATIC, SS_RIGHT },
2107 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2108 { "STATE3", CTL_BUTTON, BS_3STATE },
2109 /* It's important that USERBUTTON come after all the other button
2110 types, so that it won't be matched too early. */
2111 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2115 /* Write a dialog control. */
2118 write_rc_dialog_control (e, control)
2120 const struct dialog_control *control;
2122 const struct control_info *ci;
2126 if (control->class.named)
2130 for (ci = control_info; ci->name != NULL; ++ci)
2131 if (ci->class == control->class.u.id
2132 && (ci->style == (unsigned long) -1
2133 || ci->style == (control->style & 0xff)))
2137 fprintf (e, "CONTROL");
2138 else if (ci->name != NULL)
2139 fprintf (e, "%s", ci->name);
2141 fprintf (e, "CONTROL");
2143 if (control->text.named || control->text.u.id != 0)
2146 res_id_print (e, control->text, 1);
2150 fprintf (e, " %d, ", control->id);
2154 if (control->class.named)
2156 res_id_print (e, control->class, 0);
2157 if (control->class.named)
2159 fprintf (e, ", 0x%lx, ", control->style);
2162 fprintf (e, "%d, %d", control->x, control->y);
2164 if (control->style != SS_ICON
2165 || control->exstyle != 0
2166 || control->width != 0
2167 || control->height != 0
2168 || control->help != 0)
2170 fprintf (e, ", %d, %d", control->width, control->height);
2172 /* FIXME: We don't need to print the style if it is the default.
2173 More importantly, in certain cases we actually need to turn
2174 off parts of the forced style, by using NOT. */
2175 fprintf (e, ", 0x%lx", control->style);
2177 if (control->exstyle != 0 || control->help != 0)
2178 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
2183 if (control->data != NULL)
2184 write_rc_rcdata (e, control->data, 2);
2187 /* Write out font directory data. This would normally be built from
2191 write_rc_fontdir (e, fontdir)
2193 const struct fontdir *fontdir;
2195 const struct fontdir *fc;
2197 for (fc = fontdir; fc != NULL; fc = fc->next)
2199 fprintf (e, "// Font index: %d\n", fc->index);
2200 write_rc_filedata (e, fc->length, fc->data);
2204 /* Write out group icon data. This would normally be built from the
2208 write_rc_group_icon (e, group_icon)
2210 const struct group_icon *group_icon;
2212 const struct group_icon *gi;
2214 for (gi = group_icon; gi != NULL; gi = gi->next)
2216 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2217 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
2218 fprintf (e, "// data bytes: %lu; index: %d\n",
2219 gi->bytes, gi->index);
2223 /* Write out a menu resource. */
2226 write_rc_menu (e, menu, menuex)
2228 const struct menu *menu;
2231 if (menu->help != 0)
2232 fprintf (e, "// Help ID: %lu\n", menu->help);
2233 write_rc_menuitems (e, menu->items, menuex, 0);
2236 /* Write out menuitems. */
2239 write_rc_menuitems (e, menuitems, menuex, ind)
2241 const struct menuitem *menuitems;
2245 const struct menuitem *mi;
2248 fprintf (e, "BEGIN\n");
2250 for (mi = menuitems; mi != NULL; mi = mi->next)
2252 indent (e, ind + 2);
2254 if (mi->popup == NULL)
2255 fprintf (e, "MENUITEM");
2257 fprintf (e, "POPUP");
2260 && mi->popup == NULL
2265 fprintf (e, " SEPARATOR\n");
2269 if (mi->text == NULL)
2270 fprintf (e, " \"\"");
2274 unicode_print (e, mi->text, -1);
2280 if (mi->popup == NULL)
2281 fprintf (e, ", %d", mi->id);
2283 if ((mi->type & MENUITEM_CHECKED) != 0)
2284 fprintf (e, ", CHECKED");
2285 if ((mi->type & MENUITEM_GRAYED) != 0)
2286 fprintf (e, ", GRAYED");
2287 if ((mi->type & MENUITEM_HELP) != 0)
2288 fprintf (e, ", HELP");
2289 if ((mi->type & MENUITEM_INACTIVE) != 0)
2290 fprintf (e, ", INACTIVE");
2291 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2292 fprintf (e, ", MENUBARBREAK");
2293 if ((mi->type & MENUITEM_MENUBREAK) != 0)
2294 fprintf (e, ", MENUBREAK");
2298 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2300 fprintf (e, ", %d", mi->id);
2301 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2303 fprintf (e, ", %lu", mi->type);
2304 if (mi->state != 0 || mi->help != 0)
2306 fprintf (e, ", %lu", mi->state);
2308 fprintf (e, ", %lu", mi->help);
2316 if (mi->popup != NULL)
2317 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2321 fprintf (e, "END\n");
2324 /* Write out an rcdata resource. This is also used for other types of
2325 resources that need to print arbitrary data. */
2328 write_rc_rcdata (e, rcdata, ind)
2330 const struct rcdata_item *rcdata;
2333 const struct rcdata_item *ri;
2336 fprintf (e, "BEGIN\n");
2338 for (ri = rcdata; ri != NULL; ri = ri->next)
2340 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
2343 indent (e, ind + 2);
2351 fprintf (e, "%d", ri->u.word);
2355 fprintf (e, "%luL", ri->u.dword);
2365 for (i = 0; i < ri->u.string.length; i++)
2367 if (isprint ((unsigned char) *s))
2370 fprintf (e, "\\%03o", *s);
2376 case RCDATA_WSTRING:
2378 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2387 /* Assume little endian data. */
2390 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2396 indent (e, ind + 2);
2397 l = ((((((ri->u.buffer.data[i + 3] << 8)
2398 | ri->u.buffer.data[i + 2]) << 8)
2399 | ri->u.buffer.data[i + 1]) << 8)
2400 | ri->u.buffer.data[i]);
2401 fprintf (e, "%luL", l);
2402 if (i + 4 < ri->u.buffer.length || ri->next != NULL)
2404 for (j = 0; j < 4; ++j)
2405 if (! isprint (ri->u.buffer.data[i + j])
2406 && ri->u.buffer.data[i + j] != 0)
2410 fprintf (e, "\t// ");
2411 for (j = 0; j < 4; ++j)
2413 if (! isprint (ri->u.buffer.data[i + j]))
2414 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2417 if (ri->u.buffer.data[i + j] == '\\')
2419 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2427 if (i + 1 < ri->u.buffer.length)
2433 indent (e, ind + 2);
2434 s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2435 fprintf (e, "%d", s);
2436 if (i + 2 < ri->u.buffer.length || ri->next != NULL)
2438 for (j = 0; j < 2; ++j)
2439 if (! isprint (ri->u.buffer.data[i + j])
2440 && ri->u.buffer.data[i + j] != 0)
2444 fprintf (e, "\t// ");
2445 for (j = 0; j < 2; ++j)
2447 if (! isprint (ri->u.buffer.data[i + j]))
2448 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2451 if (ri->u.buffer.data[i + j] == '\\')
2453 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2462 if (i < ri->u.buffer.length)
2465 indent (e, ind + 2);
2466 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2467 && isprint (ri->u.buffer.data[i]))
2468 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2470 fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
2471 if (ri->next != NULL)
2481 if (ri->type != RCDATA_BUFFER)
2483 if (ri->next != NULL)
2490 fprintf (e, "END\n");
2493 /* Write out a stringtable resource. */
2496 write_rc_stringtable (e, name, stringtable)
2498 const struct res_id *name;
2499 const struct stringtable *stringtable;
2501 unsigned long offset;
2504 if (name != NULL && ! name->named)
2505 offset = (name->u.id - 1) << 4;
2508 fprintf (e, "// %s string table name\n",
2509 name == NULL ? "Missing" : "Invalid");
2513 fprintf (e, "BEGIN\n");
2515 for (i = 0; i < 16; i++)
2517 if (stringtable->strings[i].length != 0)
2519 fprintf (e, " %lu, \"", offset + i);
2520 unicode_print (e, stringtable->strings[i].string,
2521 stringtable->strings[i].length);
2522 fprintf (e, "\"\n");
2526 fprintf (e, "END\n");
2529 /* Write out a versioninfo resource. */
2532 write_rc_versioninfo (e, versioninfo)
2534 const struct versioninfo *versioninfo;
2536 const struct fixed_versioninfo *f;
2537 const struct ver_info *vi;
2539 f = versioninfo->fixed;
2540 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2541 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2542 (f->file_version_ms >> 16) & 0xffff,
2543 f->file_version_ms & 0xffff,
2544 (f->file_version_ls >> 16) & 0xffff,
2545 f->file_version_ls & 0xffff);
2546 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2547 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2548 (f->product_version_ms >> 16) & 0xffff,
2549 f->product_version_ms & 0xffff,
2550 (f->product_version_ls >> 16) & 0xffff,
2551 f->product_version_ls & 0xffff);
2552 if (f->file_flags_mask != 0)
2553 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2554 if (f->file_flags != 0)
2555 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2556 if (f->file_os != 0)
2557 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2558 if (f->file_type != 0)
2559 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2560 if (f->file_subtype != 0)
2561 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2562 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2563 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2565 fprintf (e, "BEGIN\n");
2567 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2571 case VERINFO_STRING:
2573 const struct ver_stringinfo *vs;
2575 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2576 fprintf (e, " BEGIN\n");
2577 fprintf (e, " BLOCK \"");
2578 unicode_print (e, vi->u.string.language, -1);
2579 fprintf (e, "\"\n");
2580 fprintf (e, " BEGIN\n");
2582 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2584 fprintf (e, " VALUE \"");
2585 unicode_print (e, vs->key, -1);
2586 fprintf (e, "\", \"");
2587 unicode_print (e, vs->value, -1);
2588 fprintf (e, "\"\n");
2591 fprintf (e, " END\n");
2592 fprintf (e, " END\n");
2598 const struct ver_varinfo *vv;
2600 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2601 fprintf (e, " BEGIN\n");
2602 fprintf (e, " VALUE \"");
2603 unicode_print (e, vi->u.var.key, -1);
2606 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2607 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2610 fprintf (e, "\n END\n");
2617 fprintf (e, "END\n");
2620 /* Write out data which would normally be read from a file. */
2623 write_rc_filedata (e, length, data)
2625 unsigned long length;
2626 const unsigned char *data;
2630 for (i = 0; i + 15 < length; i += 16)
2632 fprintf (e, "// %4lx: ", i);
2633 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2634 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2635 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2636 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2637 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2638 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2643 fprintf (e, "// %4lx:", i);
2646 fprintf (e, " %02x", data[i]);