Delete bogus R_PCLONG. Tidy R_*.
[binutils.git] / binutils / resrc.c
blob8ed6a5d158d2d4207f94bba39516cfac3870b973
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
20 02111-1307, USA. */
22 /* This file contains functions that read and write Windows rc files.
23 These are text files that represent resources. */
25 #include "bfd.h"
26 #include "bucomm.h"
27 #include "libiberty.h"
28 #include "windres.h"
30 #include <assert.h>
31 #include <ctype.h>
32 #include <sys/stat.h>
34 #if defined (_WIN32) && ! defined (__CYGWIN32__)
35 #define popen _popen
36 #define pclose _pclose
37 #endif
39 /* The default preprocessor. */
41 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
43 /* We read the directory entries in a cursor or icon file into
44 instances of this structure. */
46 struct icondir
48 /* Width of image. */
49 unsigned char width;
50 /* Height of image. */
51 unsigned char height;
52 /* Number of colors in image. */
53 unsigned char colorcount;
54 union
56 struct
58 /* Color planes. */
59 unsigned short planes;
60 /* Bits per pixel. */
61 unsigned short bits;
62 } icon;
63 struct
65 /* X coordinate of hotspot. */
66 unsigned short xhotspot;
67 /* Y coordinate of hotspot. */
68 unsigned short yhotspot;
69 } cursor;
70 } u;
71 /* Bytes in image. */
72 unsigned long bytes;
73 /* File offset of image. */
74 unsigned long offset;
77 /* The name of the rc file we are reading. */
79 char *rc_filename;
81 /* The line number in the rc file. */
83 int rc_lineno;
85 /* The pipe we are reading from, so that we can close it if we exit. */
87 static FILE *cpp_pipe;
89 /* As we read the rc file, we attach information to this structure. */
91 static struct res_directory *resources;
93 /* The number of cursor resources we have written out. */
95 static int cursors;
97 /* The number of font resources we have written out. */
99 static int fonts;
101 /* Font directory information. */
103 struct fontdir *fontdirs;
105 /* Resource info to use for fontdirs. */
107 struct res_res_info fontdirs_resinfo;
109 /* The number of icon resources we have written out. */
111 static int icons;
113 /* Local functions. */
115 static FILE *look_for_default PARAMS ((char *, const char *, int,
116 const char *, const char *));
117 static void close_pipe PARAMS ((void));
118 static void unexpected_eof PARAMS ((const char *));
119 static int get_word PARAMS ((FILE *, const char *));
120 static unsigned long get_long PARAMS ((FILE *, const char *));
121 static void get_data
122 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
123 static void define_fontdirs PARAMS ((void));
125 /* look for the preprocessor program */
127 static FILE *
128 look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
129 char *cmd;
130 const char *prefix;
131 int end_prefix;
132 const char *preprocargs;
133 const char *filename;
135 char *space;
136 int found;
137 struct stat s;
139 strcpy (cmd, prefix);
141 sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
142 space = strchr (cmd + end_prefix, ' ');
143 if (space)
144 *space = 0;
146 if (strchr (cmd, '/'))
148 found = (stat (cmd, &s) == 0
149 #ifdef HAVE_EXECUTABLE_SUFFIX
150 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
151 #endif
154 if (! found)
156 if (verbose)
157 fprintf (stderr, "Tried `%s'\n", cmd);
158 return NULL;
162 strcpy (cmd, prefix);
164 sprintf (cmd + end_prefix, "%s %s %s",
165 DEFAULT_PREPROCESSOR, preprocargs, filename);
167 if (verbose)
168 fprintf (stderr, "Using `%s'\n", cmd);
170 cpp_pipe = popen (cmd, FOPEN_RT);
171 return cpp_pipe;
174 /* Read an rc file. */
176 struct res_directory *
177 read_rc_file (filename, preprocessor, preprocargs, language)
178 const char *filename;
179 const char *preprocessor;
180 const char *preprocargs;
181 int language;
183 char *cmd;
185 if (preprocargs == NULL)
186 preprocargs = "";
187 if (filename == NULL)
188 filename = "-";
190 if (preprocessor)
192 cmd = xmalloc (strlen (preprocessor)
193 + strlen (preprocargs)
194 + strlen (filename)
195 + 10);
196 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
198 cpp_pipe = popen (cmd, FOPEN_RT);
200 else
202 char *dash, *slash, *cp;
204 preprocessor = DEFAULT_PREPROCESSOR;
206 cmd = xmalloc (strlen (program_name)
207 + strlen (preprocessor)
208 + strlen (preprocargs)
209 + strlen (filename)
210 #ifdef HAVE_EXECUTABLE_SUFFIX
211 + strlen (EXECUTABLE_SUFFIX)
212 #endif
213 + 10);
216 dash = slash = 0;
217 for (cp = program_name; *cp; cp++)
219 if (*cp == '-')
220 dash = cp;
221 if (
222 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
223 *cp == ':' || *cp == '\\' ||
224 #endif
225 *cp == '/')
227 slash = cp;
228 dash = 0;
232 cpp_pipe = 0;
234 if (dash)
236 /* First, try looking for a prefixed gcc in the windres
237 directory, with the same prefix as windres */
239 cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
240 preprocargs, filename);
243 if (slash && !cpp_pipe)
245 /* Next, try looking for a gcc in the same directory as
246 that windres */
248 cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
249 preprocargs, filename);
252 if (!cpp_pipe)
254 /* Sigh, try the default */
256 cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
260 if (cpp_pipe == NULL)
261 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
262 free (cmd);
264 xatexit (close_pipe);
266 rc_filename = xstrdup (filename);
267 rc_lineno = 1;
268 if (language != -1)
269 rcparse_set_language (language);
270 yyin = cpp_pipe;
271 yyparse ();
273 if (pclose (cpp_pipe) != 0)
274 fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name);
275 cpp_pipe = NULL;
277 if (fontdirs != NULL)
278 define_fontdirs ();
280 free (rc_filename);
281 rc_filename = NULL;
283 return resources;
286 /* Close the pipe if it is open. This is called via xatexit. */
288 void
289 close_pipe ()
291 if (cpp_pipe != NULL)
292 pclose (cpp_pipe);
295 /* Report an error while reading an rc file. */
297 void
298 yyerror (msg)
299 const char *msg;
301 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
304 /* Issue a warning while reading an rc file. */
306 void
307 rcparse_warning (msg)
308 const char *msg;
310 fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
313 /* Die if we get an unexpected end of file. */
315 static void
316 unexpected_eof (msg)
317 const char *msg;
319 fatal (_("%s: unexpected EOF"), msg);
322 /* Read a 16 bit word from a file. The data is assumed to be little
323 endian. */
325 static int
326 get_word (e, msg)
327 FILE *e;
328 const char *msg;
330 int b1, b2;
332 b1 = getc (e);
333 b2 = getc (e);
334 if (feof (e))
335 unexpected_eof (msg);
336 return ((b2 & 0xff) << 8) | (b1 & 0xff);
339 /* Read a 32 bit word from a file. The data is assumed to be little
340 endian. */
342 static unsigned long
343 get_long (e, msg)
344 FILE *e;
345 const char *msg;
347 int b1, b2, b3, b4;
349 b1 = getc (e);
350 b2 = getc (e);
351 b3 = getc (e);
352 b4 = getc (e);
353 if (feof (e))
354 unexpected_eof (msg);
355 return (((((((b4 & 0xff) << 8)
356 | (b3 & 0xff)) << 8)
357 | (b2 & 0xff)) << 8)
358 | (b1 & 0xff));
361 /* Read data from a file. This is a wrapper to do error checking. */
363 static void
364 get_data (e, p, c, msg)
365 FILE *e;
366 unsigned char *p;
367 unsigned long c;
368 const char *msg;
370 unsigned long got;
372 got = fread (p, 1, c, e);
373 if (got == c)
374 return;
376 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
379 /* Define an accelerator resource. */
381 void
382 define_accelerator (id, resinfo, data)
383 struct res_id id;
384 const struct res_res_info *resinfo;
385 struct accelerator *data;
387 struct res_resource *r;
389 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
390 resinfo->language, 0);
391 r->type = RES_TYPE_ACCELERATOR;
392 r->u.acc = data;
393 r->res_info = *resinfo;
396 /* Define a bitmap resource. Bitmap data is stored in a file. The
397 first 14 bytes of the file are a standard header, which is not
398 included in the resource data. */
400 #define BITMAP_SKIP (14)
402 void
403 define_bitmap (id, resinfo, filename)
404 struct res_id id;
405 const struct res_res_info *resinfo;
406 const char *filename;
408 FILE *e;
409 char *real_filename;
410 struct stat s;
411 unsigned char *data;
412 int i;
413 struct res_resource *r;
415 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
417 if (stat (real_filename, &s) < 0)
418 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
419 strerror (errno));
421 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
423 for (i = 0; i < BITMAP_SKIP; i++)
424 getc (e);
426 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
428 fclose (e);
429 free (real_filename);
431 r = define_standard_resource (&resources, RT_BITMAP, id,
432 resinfo->language, 0);
434 r->type = RES_TYPE_BITMAP;
435 r->u.data.length = s.st_size - BITMAP_SKIP;
436 r->u.data.data = data;
437 r->res_info = *resinfo;
440 /* Define a cursor resource. A cursor file may contain a set of
441 bitmaps, each representing the same cursor at various different
442 resolutions. They each get written out with a different ID. The
443 real cursor resource is then a group resource which can be used to
444 select one of the actual cursors. */
446 void
447 define_cursor (id, resinfo, filename)
448 struct res_id id;
449 const struct res_res_info *resinfo;
450 const char *filename;
452 FILE *e;
453 char *real_filename;
454 int type, count, i;
455 struct icondir *icondirs;
456 int first_cursor;
457 struct res_resource *r;
458 struct group_cursor *first, **pp;
460 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
462 /* A cursor file is basically an icon file. The start of the file
463 is a three word structure. The first word is ignored. The
464 second word is the type of data. The third word is the number of
465 entries. */
467 get_word (e, real_filename);
468 type = get_word (e, real_filename);
469 count = get_word (e, real_filename);
470 if (type != 2)
471 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
473 /* Read in the icon directory entries. */
475 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
477 for (i = 0; i < count; i++)
479 icondirs[i].width = getc (e);
480 icondirs[i].height = getc (e);
481 icondirs[i].colorcount = getc (e);
482 getc (e);
483 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
484 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
485 icondirs[i].bytes = get_long (e, real_filename);
486 icondirs[i].offset = get_long (e, real_filename);
488 if (feof (e))
489 unexpected_eof (real_filename);
492 /* Define each cursor as a unique resource. */
494 first_cursor = cursors;
496 for (i = 0; i < count; i++)
498 unsigned char *data;
499 struct res_id name;
500 struct cursor *c;
502 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
503 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
504 icondirs[i].offset, strerror (errno));
506 data = (unsigned char *) res_alloc (icondirs[i].bytes);
508 get_data (e, data, icondirs[i].bytes, real_filename);
510 c = (struct cursor *) res_alloc (sizeof *c);
511 c->xhotspot = icondirs[i].u.cursor.xhotspot;
512 c->yhotspot = icondirs[i].u.cursor.yhotspot;
513 c->length = icondirs[i].bytes;
514 c->data = data;
516 ++cursors;
518 name.named = 0;
519 name.u.id = cursors;
521 r = define_standard_resource (&resources, RT_CURSOR, name,
522 resinfo->language, 0);
523 r->type = RES_TYPE_CURSOR;
524 r->u.cursor = c;
525 r->res_info = *resinfo;
528 fclose (e);
529 free (real_filename);
531 /* Define a cursor group resource. */
533 first = NULL;
534 pp = &first;
535 for (i = 0; i < count; i++)
537 struct group_cursor *cg;
539 cg = (struct group_cursor *) res_alloc (sizeof *cg);
540 cg->next = NULL;
541 cg->width = icondirs[i].width;
542 cg->height = 2 * icondirs[i].height;
544 /* FIXME: What should these be set to? */
545 cg->planes = 1;
546 cg->bits = 1;
548 cg->bytes = icondirs[i].bytes + 4;
549 cg->index = first_cursor + i + 1;
551 *pp = cg;
552 pp = &(*pp)->next;
555 free (icondirs);
557 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
558 resinfo->language, 0);
559 r->type = RES_TYPE_GROUP_CURSOR;
560 r->u.group_cursor = first;
561 r->res_info = *resinfo;
564 /* Define a dialog resource. */
566 void
567 define_dialog (id, resinfo, dialog)
568 struct res_id id;
569 const struct res_res_info *resinfo;
570 const struct dialog *dialog;
572 struct dialog *copy;
573 struct res_resource *r;
575 copy = (struct dialog *) res_alloc (sizeof *copy);
576 *copy = *dialog;
578 r = define_standard_resource (&resources, RT_DIALOG, id,
579 resinfo->language, 0);
580 r->type = RES_TYPE_DIALOG;
581 r->u.dialog = copy;
582 r->res_info = *resinfo;
585 /* Define a dialog control. This does not define a resource, but
586 merely allocates and fills in a structure. */
588 struct dialog_control *
589 define_control (text, id, x, y, width, height, class, style, exstyle)
590 const char *text;
591 unsigned long id;
592 unsigned long x;
593 unsigned long y;
594 unsigned long width;
595 unsigned long height;
596 unsigned long class;
597 unsigned long style;
598 unsigned long exstyle;
600 struct dialog_control *n;
602 n = (struct dialog_control *) res_alloc (sizeof *n);
603 n->next = NULL;
604 n->id = id;
605 n->style = style;
606 n->exstyle = exstyle;
607 n->x = x;
608 n->y = y;
609 n->width = width;
610 n->height = height;
611 n->class.named = 0;
612 n->class.u.id = class;
613 if (text != NULL)
614 res_string_to_id (&n->text, text);
615 else
617 n->text.named = 0;
618 n->text.u.id = 0;
620 n->data = NULL;
621 n->help = 0;
623 return n;
626 /* Define a font resource. */
628 void
629 define_font (id, resinfo, filename)
630 struct res_id id;
631 const struct res_res_info *resinfo;
632 const char *filename;
634 FILE *e;
635 char *real_filename;
636 struct stat s;
637 unsigned char *data;
638 struct res_resource *r;
639 long offset;
640 long fontdatalength;
641 unsigned char *fontdata;
642 struct fontdir *fd;
643 const char *device, *face;
644 struct fontdir **pp;
646 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
648 if (stat (real_filename, &s) < 0)
649 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
650 strerror (errno));
652 data = (unsigned char *) res_alloc (s.st_size);
654 get_data (e, data, s.st_size, real_filename);
656 fclose (e);
657 free (real_filename);
659 r = define_standard_resource (&resources, RT_FONT, id,
660 resinfo->language, 0);
662 r->type = RES_TYPE_FONT;
663 r->u.data.length = s.st_size;
664 r->u.data.data = data;
665 r->res_info = *resinfo;
667 /* For each font resource, we must add an entry in the FONTDIR
668 resource. The FONTDIR resource includes some strings in the font
669 file. To find them, we have to do some magic on the data we have
670 read. */
672 offset = ((((((data[47] << 8)
673 | data[46]) << 8)
674 | data[45]) << 8)
675 | data[44]);
676 if (offset > 0 && offset < s.st_size)
677 device = (char *) data + offset;
678 else
679 device = "";
681 offset = ((((((data[51] << 8)
682 | data[50]) << 8)
683 | data[49]) << 8)
684 | data[48]);
685 if (offset > 0 && offset < s.st_size)
686 face = (char *) data + offset;
687 else
688 face = "";
690 ++fonts;
692 fontdatalength = 58 + strlen (device) + strlen (face);
693 fontdata = (unsigned char *) res_alloc (fontdatalength);
694 memcpy (fontdata, data, 56);
695 strcpy ((char *) fontdata + 56, device);
696 strcpy ((char *) fontdata + 57 + strlen (device), face);
698 fd = (struct fontdir *) res_alloc (sizeof *fd);
699 fd->next = NULL;
700 fd->index = fonts;
701 fd->length = fontdatalength;
702 fd->data = fontdata;
704 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
706 *pp = fd;
708 /* For the single fontdirs resource, we always use the resource
709 information of the last font. I don't know what else to do. */
710 fontdirs_resinfo = *resinfo;
713 /* Define the fontdirs resource. This is called after the entire rc
714 file has been parsed, if any font resources were seen. */
716 static void
717 define_fontdirs ()
719 struct res_resource *r;
720 struct res_id id;
722 id.named = 0;
723 id.u.id = 1;
725 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
727 r->type = RES_TYPE_FONTDIR;
728 r->u.fontdir = fontdirs;
729 r->res_info = fontdirs_resinfo;
732 /* Define an icon resource. An icon file may contain a set of
733 bitmaps, each representing the same icon at various different
734 resolutions. They each get written out with a different ID. The
735 real icon resource is then a group resource which can be used to
736 select one of the actual icon bitmaps. */
738 void
739 define_icon (id, resinfo, filename)
740 struct res_id id;
741 const struct res_res_info *resinfo;
742 const char *filename;
744 FILE *e;
745 char *real_filename;
746 int type, count, i;
747 struct icondir *icondirs;
748 int first_icon;
749 struct res_resource *r;
750 struct group_icon *first, **pp;
752 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
754 /* The start of an icon file is a three word structure. The first
755 word is ignored. The second word is the type of data. The third
756 word is the number of entries. */
758 get_word (e, real_filename);
759 type = get_word (e, real_filename);
760 count = get_word (e, real_filename);
761 if (type != 1)
762 fatal (_("icon file `%s' does not contain icon data"), real_filename);
764 /* Read in the icon directory entries. */
766 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
768 for (i = 0; i < count; i++)
770 icondirs[i].width = getc (e);
771 icondirs[i].height = getc (e);
772 icondirs[i].colorcount = getc (e);
773 getc (e);
774 icondirs[i].u.icon.planes = get_word (e, real_filename);
775 icondirs[i].u.icon.bits = get_word (e, real_filename);
776 icondirs[i].bytes = get_long (e, real_filename);
777 icondirs[i].offset = get_long (e, real_filename);
779 if (feof (e))
780 unexpected_eof (real_filename);
783 /* Define each icon as a unique resource. */
785 first_icon = icons;
787 for (i = 0; i < count; i++)
789 unsigned char *data;
790 struct res_id name;
792 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
793 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
794 icondirs[i].offset, strerror (errno));
796 data = (unsigned char *) res_alloc (icondirs[i].bytes);
798 get_data (e, data, icondirs[i].bytes, real_filename);
800 ++icons;
802 name.named = 0;
803 name.u.id = icons;
805 r = define_standard_resource (&resources, RT_ICON, name,
806 resinfo->language, 0);
807 r->type = RES_TYPE_ICON;
808 r->u.data.length = icondirs[i].bytes;
809 r->u.data.data = data;
810 r->res_info = *resinfo;
813 fclose (e);
814 free (real_filename);
816 /* Define an icon group resource. */
818 first = NULL;
819 pp = &first;
820 for (i = 0; i < count; i++)
822 struct group_icon *cg;
824 /* For some reason, at least in some files the planes and bits
825 are zero. We instead set them from the color. This is
826 copied from rcl. */
828 cg = (struct group_icon *) res_alloc (sizeof *cg);
829 cg->next = NULL;
830 cg->width = icondirs[i].width;
831 cg->height = icondirs[i].height;
832 cg->colors = icondirs[i].colorcount;
834 cg->planes = 1;
835 cg->bits = 0;
836 while ((1 << cg->bits) < cg->colors)
837 ++cg->bits;
839 cg->bytes = icondirs[i].bytes;
840 cg->index = first_icon + i + 1;
842 *pp = cg;
843 pp = &(*pp)->next;
846 free (icondirs);
848 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
849 resinfo->language, 0);
850 r->type = RES_TYPE_GROUP_ICON;
851 r->u.group_icon = first;
852 r->res_info = *resinfo;
855 /* Define a menu resource. */
857 void
858 define_menu (id, resinfo, menuitems)
859 struct res_id id;
860 const struct res_res_info *resinfo;
861 struct menuitem *menuitems;
863 struct menu *m;
864 struct res_resource *r;
866 m = (struct menu *) res_alloc (sizeof *m);
867 m->items = menuitems;
868 m->help = 0;
870 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
871 r->type = RES_TYPE_MENU;
872 r->u.menu = m;
873 r->res_info = *resinfo;
876 /* Define a menu item. This does not define a resource, but merely
877 allocates and fills in a structure. */
879 struct menuitem *
880 define_menuitem (text, menuid, type, state, help, menuitems)
881 const char *text;
882 int menuid;
883 unsigned long type;
884 unsigned long state;
885 unsigned long help;
886 struct menuitem *menuitems;
888 struct menuitem *mi;
890 mi = (struct menuitem *) res_alloc (sizeof *mi);
891 mi->next = NULL;
892 mi->type = type;
893 mi->state = state;
894 mi->id = menuid;
895 if (text == NULL)
896 mi->text = NULL;
897 else
898 unicode_from_ascii ((int *) NULL, &mi->text, text);
899 mi->help = help;
900 mi->popup = menuitems;
901 return mi;
904 /* Define a messagetable resource. */
906 void
907 define_messagetable (id, resinfo, filename)
908 struct res_id id;
909 const struct res_res_info *resinfo;
910 const char *filename;
912 FILE *e;
913 char *real_filename;
914 struct stat s;
915 unsigned char *data;
916 struct res_resource *r;
918 e = open_file_search (filename, FOPEN_RB, "messagetable file",
919 &real_filename);
921 if (stat (real_filename, &s) < 0)
922 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
923 strerror (errno));
925 data = (unsigned char *) res_alloc (s.st_size);
927 get_data (e, data, s.st_size, real_filename);
929 fclose (e);
930 free (real_filename);
932 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
933 resinfo->language, 0);
935 r->type = RES_TYPE_MESSAGETABLE;
936 r->u.data.length = s.st_size;
937 r->u.data.data = data;
938 r->res_info = *resinfo;
941 /* Define an rcdata resource. */
943 void
944 define_rcdata (id, resinfo, data)
945 struct res_id id;
946 const struct res_res_info *resinfo;
947 struct rcdata_item *data;
949 struct res_resource *r;
951 r = define_standard_resource (&resources, RT_RCDATA, id,
952 resinfo->language, 0);
953 r->type = RES_TYPE_RCDATA;
954 r->u.rcdata = data;
955 r->res_info = *resinfo;
958 /* Create an rcdata item holding a string. */
960 struct rcdata_item *
961 define_rcdata_string (string, len)
962 const char *string;
963 unsigned long len;
965 struct rcdata_item *ri;
966 char *s;
968 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
969 ri->next = NULL;
970 ri->type = RCDATA_STRING;
971 ri->u.string.length = len;
972 s = (char *) res_alloc (len);
973 memcpy (s, string, len);
974 ri->u.string.s = s;
976 return ri;
979 /* Create an rcdata item holding a number. */
981 struct rcdata_item *
982 define_rcdata_number (val, dword)
983 unsigned long val;
984 int dword;
986 struct rcdata_item *ri;
988 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
989 ri->next = NULL;
990 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
991 ri->u.word = val;
993 return ri;
996 /* Define a stringtable resource. This is called for each string
997 which appears in a STRINGTABLE statement. */
999 void
1000 define_stringtable (resinfo, stringid, string)
1001 const struct res_res_info *resinfo;
1002 unsigned long stringid;
1003 const char *string;
1005 struct res_id id;
1006 struct res_resource *r;
1008 id.named = 0;
1009 id.u.id = (stringid >> 4) + 1;
1010 r = define_standard_resource (&resources, RT_STRING, id,
1011 resinfo->language, 1);
1013 if (r->type == RES_TYPE_UNINITIALIZED)
1015 int i;
1017 r->type = RES_TYPE_STRINGTABLE;
1018 r->u.stringtable = ((struct stringtable *)
1019 res_alloc (sizeof (struct stringtable)));
1020 for (i = 0; i < 16; i++)
1022 r->u.stringtable->strings[i].length = 0;
1023 r->u.stringtable->strings[i].string = NULL;
1026 r->res_info = *resinfo;
1029 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
1030 &r->u.stringtable->strings[stringid & 0xf].string,
1031 string);
1034 /* Define a user data resource where the data is in the rc file. */
1036 void
1037 define_user_data (id, type, resinfo, data)
1038 struct res_id id;
1039 struct res_id type;
1040 const struct res_res_info *resinfo;
1041 struct rcdata_item *data;
1043 struct res_id ids[3];
1044 struct res_resource *r;
1046 ids[0] = type;
1047 ids[1] = id;
1048 ids[2].named = 0;
1049 ids[2].u.id = resinfo->language;
1051 r = define_resource (&resources, 3, ids, 0);
1052 r->type = RES_TYPE_USERDATA;
1053 r->u.userdata = data;
1054 r->res_info = *resinfo;
1057 /* Define a user data resource where the data is in a file. */
1059 void
1060 define_user_file (id, type, resinfo, filename)
1061 struct res_id id;
1062 struct res_id type;
1063 const struct res_res_info *resinfo;
1064 const char *filename;
1066 FILE *e;
1067 char *real_filename;
1068 struct stat s;
1069 unsigned char *data;
1070 struct res_id ids[3];
1071 struct res_resource *r;
1073 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
1075 if (stat (real_filename, &s) < 0)
1076 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1077 strerror (errno));
1079 data = (unsigned char *) res_alloc (s.st_size);
1081 get_data (e, data, s.st_size, real_filename);
1083 fclose (e);
1084 free (real_filename);
1086 ids[0] = type;
1087 ids[1] = id;
1088 ids[2].named = 0;
1089 ids[2].u.id = resinfo->language;
1091 r = define_resource (&resources, 3, ids, 0);
1092 r->type = RES_TYPE_USERDATA;
1093 r->u.userdata = ((struct rcdata_item *)
1094 res_alloc (sizeof (struct rcdata_item)));
1095 r->u.userdata->next = NULL;
1096 r->u.userdata->type = RCDATA_BUFFER;
1097 r->u.userdata->u.buffer.length = s.st_size;
1098 r->u.userdata->u.buffer.data = data;
1099 r->res_info = *resinfo;
1102 /* Define a versioninfo resource. */
1104 void
1105 define_versioninfo (id, language, fixedverinfo, verinfo)
1106 struct res_id id;
1107 int language;
1108 struct fixed_versioninfo *fixedverinfo;
1109 struct ver_info *verinfo;
1111 struct res_resource *r;
1113 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1114 r->type = RES_TYPE_VERSIONINFO;
1115 r->u.versioninfo = ((struct versioninfo *)
1116 res_alloc (sizeof (struct versioninfo)));
1117 r->u.versioninfo->fixed = fixedverinfo;
1118 r->u.versioninfo->var = verinfo;
1119 r->res_info.language = language;
1122 /* Add string version info to a list of version information. */
1124 struct ver_info *
1125 append_ver_stringfileinfo (verinfo, language, strings)
1126 struct ver_info *verinfo;
1127 const char *language;
1128 struct ver_stringinfo *strings;
1130 struct ver_info *vi, **pp;
1132 vi = (struct ver_info *) res_alloc (sizeof *vi);
1133 vi->next = NULL;
1134 vi->type = VERINFO_STRING;
1135 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1136 vi->u.string.strings = strings;
1138 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1140 *pp = vi;
1142 return verinfo;
1145 /* Add variable version info to a list of version information. */
1147 struct ver_info *
1148 append_ver_varfileinfo (verinfo, key, var)
1149 struct ver_info *verinfo;
1150 const char *key;
1151 struct ver_varinfo *var;
1153 struct ver_info *vi, **pp;
1155 vi = (struct ver_info *) res_alloc (sizeof *vi);
1156 vi->next = NULL;
1157 vi->type = VERINFO_VAR;
1158 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1159 vi->u.var.var = var;
1161 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1163 *pp = vi;
1165 return verinfo;
1168 /* Append version string information to a list. */
1170 struct ver_stringinfo *
1171 append_verval (strings, key, value)
1172 struct ver_stringinfo *strings;
1173 const char *key;
1174 const char *value;
1176 struct ver_stringinfo *vs, **pp;
1178 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1179 vs->next = NULL;
1180 unicode_from_ascii ((int *) NULL, &vs->key, key);
1181 unicode_from_ascii ((int *) NULL, &vs->value, value);
1183 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1185 *pp = vs;
1187 return strings;
1190 /* Append version variable information to a list. */
1192 struct ver_varinfo *
1193 append_vertrans (var, language, charset)
1194 struct ver_varinfo *var;
1195 unsigned long language;
1196 unsigned long charset;
1198 struct ver_varinfo *vv, **pp;
1200 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1201 vv->next = NULL;
1202 vv->language = language;
1203 vv->charset = charset;
1205 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1207 *pp = vv;
1209 return var;
1212 /* Local functions used to write out an rc file. */
1214 static void indent PARAMS ((FILE *, int));
1215 static void write_rc_directory
1216 PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1217 const struct res_id *, int *, int));
1218 static void write_rc_subdir
1219 PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1220 const struct res_id *, int *, int));
1221 static void write_rc_resource
1222 PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1223 const struct res_resource *, int *));
1224 static void write_rc_accelerators
1225 PARAMS ((FILE *, const struct accelerator *));
1226 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1227 static void write_rc_group_cursor
1228 PARAMS ((FILE *, const struct group_cursor *));
1229 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1230 static void write_rc_dialog_control
1231 PARAMS ((FILE *, const struct dialog_control *));
1232 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1233 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1234 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1235 static void write_rc_menuitems
1236 PARAMS ((FILE *, const struct menuitem *, int, int));
1237 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1238 static void write_rc_stringtable
1239 PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1240 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1241 static void write_rc_filedata
1242 PARAMS ((FILE *, unsigned long, const unsigned char *));
1244 /* Indent a given number of spaces. */
1246 static void
1247 indent (e, c)
1248 FILE *e;
1249 int c;
1251 int i;
1253 for (i = 0; i < c; i++)
1254 putc (' ', e);
1257 /* Dump the resources we have read in the format of an rc file.
1259 Actually, we don't use the format of an rc file, because it's way
1260 too much of a pain--for example, we'd have to write icon resources
1261 into a file and refer to that file. We just generate a readable
1262 format that kind of looks like an rc file, and is useful for
1263 understanding the contents of a resource file. Someday we may want
1264 to generate an rc file which the rc compiler can read; if that day
1265 comes, this code will have to be fixed up. */
1267 void
1268 write_rc_file (filename, resources)
1269 const char *filename;
1270 const struct res_directory *resources;
1272 FILE *e;
1273 int language;
1275 if (filename == NULL)
1276 e = stdout;
1277 else
1279 e = fopen (filename, FOPEN_WT);
1280 if (e == NULL)
1281 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1284 language = -1;
1285 write_rc_directory (e, resources, (const struct res_id *) NULL,
1286 (const struct res_id *) NULL, &language, 1);
1289 /* Write out a directory. E is the file to write to. RD is the
1290 directory. TYPE is a pointer to the level 1 ID which serves as the
1291 resource type. NAME is a pointer to the level 2 ID which serves as
1292 an individual resource name. LANGUAGE is a pointer to the current
1293 language. LEVEL is the level in the tree. */
1295 static void
1296 write_rc_directory (e, rd, type, name, language, level)
1297 FILE *e;
1298 const struct res_directory *rd;
1299 const struct res_id *type;
1300 const struct res_id *name;
1301 int *language;
1302 int level;
1304 const struct res_entry *re;
1306 /* Print out some COFF information that rc files can't represent. */
1308 if (rd->time != 0)
1309 fprintf (e, "// Time stamp: %lu\n", rd->time);
1310 if (rd->characteristics != 0)
1311 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1312 if (rd->major != 0 || rd->minor != 0)
1313 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1315 for (re = rd->entries; re != NULL; re = re->next)
1317 switch (level)
1319 case 1:
1320 /* If we're at level 1, the key of this resource is the
1321 type. This normally duplicates the information we have
1322 stored with the resource itself, but we need to remember
1323 the type if this is a user define resource type. */
1324 type = &re->id;
1325 break;
1327 case 2:
1328 /* If we're at level 2, the key of this resource is the name
1329 we are going to use in the rc printout. */
1330 name = &re->id;
1331 break;
1333 case 3:
1334 /* If we're at level 3, then this key represents a language.
1335 Use it to update the current language. */
1336 if (! re->id.named
1337 && re->id.u.id != (unsigned long) (unsigned int) *language
1338 && (re->id.u.id & 0xffff) == re->id.u.id)
1340 fprintf (e, "LANGUAGE %lu, %lu\n",
1341 re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1342 *language = re->id.u.id;
1344 break;
1346 default:
1347 break;
1350 if (re->subdir)
1351 write_rc_subdir (e, re, type, name, language, level);
1352 else
1354 if (level == 3)
1356 /* This is the normal case: the three levels are
1357 TYPE/NAME/LANGUAGE. NAME will have been set at level
1358 2, and represents the name to use. We probably just
1359 set LANGUAGE, and it will probably match what the
1360 resource itself records if anything. */
1361 write_rc_resource (e, type, name, re->u.res, language);
1363 else
1365 fprintf (e, "// Resource at unexpected level %d\n", level);
1366 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1367 language);
1373 /* Write out a subdirectory entry. E is the file to write to. RE is
1374 the subdirectory entry. TYPE and NAME are pointers to higher level
1375 IDs, or NULL. LANGUAGE is a pointer to the current language.
1376 LEVEL is the level in the tree. */
1378 static void
1379 write_rc_subdir (e, re, type, name, language, level)
1380 FILE *e;
1381 const struct res_entry *re;
1382 const struct res_id *type;
1383 const struct res_id *name;
1384 int *language;
1385 int level;
1387 fprintf (e, "\n");
1388 switch (level)
1390 case 1:
1391 fprintf (e, "// Type: ");
1392 if (re->id.named)
1393 res_id_print (e, re->id, 1);
1394 else
1396 const char *s;
1398 switch (re->id.u.id)
1400 case RT_CURSOR: s = "cursor"; break;
1401 case RT_BITMAP: s = "bitmap"; break;
1402 case RT_ICON: s = "icon"; break;
1403 case RT_MENU: s = "menu"; break;
1404 case RT_DIALOG: s = "dialog"; break;
1405 case RT_STRING: s = "stringtable"; break;
1406 case RT_FONTDIR: s = "fontdir"; break;
1407 case RT_FONT: s = "font"; break;
1408 case RT_ACCELERATOR: s = "accelerators"; break;
1409 case RT_RCDATA: s = "rcdata"; break;
1410 case RT_MESSAGETABLE: s = "messagetable"; break;
1411 case RT_GROUP_CURSOR: s = "group cursor"; break;
1412 case RT_GROUP_ICON: s = "group icon"; break;
1413 case RT_VERSION: s = "version"; break;
1414 case RT_DLGINCLUDE: s = "dlginclude"; break;
1415 case RT_PLUGPLAY: s = "plugplay"; break;
1416 case RT_VXD: s = "vxd"; break;
1417 case RT_ANICURSOR: s = "anicursor"; break;
1418 case RT_ANIICON: s = "aniicon"; break;
1419 default: s = NULL; break;
1422 if (s != NULL)
1423 fprintf (e, "%s", s);
1424 else
1425 res_id_print (e, re->id, 1);
1427 fprintf (e, "\n");
1428 break;
1430 case 2:
1431 fprintf (e, "// Name: ");
1432 res_id_print (e, re->id, 1);
1433 fprintf (e, "\n");
1434 break;
1436 case 3:
1437 fprintf (e, "// Language: ");
1438 res_id_print (e, re->id, 1);
1439 fprintf (e, "\n");
1440 break;
1442 default:
1443 fprintf (e, "// Level %d: ", level);
1444 res_id_print (e, re->id, 1);
1445 fprintf (e, "\n");
1448 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1451 /* Write out a single resource. E is the file to write to. TYPE is a
1452 pointer to the type of the resource. NAME is a pointer to the name
1453 of the resource; it will be NULL if there is a level mismatch. RES
1454 is the resource data. LANGUAGE is a pointer to the current
1455 language. */
1457 static void
1458 write_rc_resource (e, type, name, res, language)
1459 FILE *e;
1460 const struct res_id *type;
1461 const struct res_id *name;
1462 const struct res_resource *res;
1463 int *language;
1465 const char *s;
1466 int rt;
1467 int menuex = 0;
1469 fprintf (e, "\n");
1471 switch (res->type)
1473 default:
1474 abort ();
1476 case RES_TYPE_ACCELERATOR:
1477 s = "ACCELERATOR";
1478 rt = RT_ACCELERATOR;
1479 break;
1481 case RES_TYPE_BITMAP:
1482 s = "BITMAP";
1483 rt = RT_BITMAP;
1484 break;
1486 case RES_TYPE_CURSOR:
1487 s = "CURSOR";
1488 rt = RT_CURSOR;
1489 break;
1491 case RES_TYPE_GROUP_CURSOR:
1492 s = "GROUP_CURSOR";
1493 rt = RT_GROUP_CURSOR;
1494 break;
1496 case RES_TYPE_DIALOG:
1497 if (extended_dialog (res->u.dialog))
1498 s = "DIALOGEX";
1499 else
1500 s = "DIALOG";
1501 rt = RT_DIALOG;
1502 break;
1504 case RES_TYPE_FONT:
1505 s = "FONT";
1506 rt = RT_FONT;
1507 break;
1509 case RES_TYPE_FONTDIR:
1510 s = "FONTDIR";
1511 rt = RT_FONTDIR;
1512 break;
1514 case RES_TYPE_ICON:
1515 s = "ICON";
1516 rt = RT_ICON;
1517 break;
1519 case RES_TYPE_GROUP_ICON:
1520 s = "GROUP_ICON";
1521 rt = RT_GROUP_ICON;
1522 break;
1524 case RES_TYPE_MENU:
1525 if (extended_menu (res->u.menu))
1527 s = "MENUEX";
1528 menuex = 1;
1530 else
1532 s = "MENU";
1533 menuex = 0;
1535 rt = RT_MENU;
1536 break;
1538 case RES_TYPE_MESSAGETABLE:
1539 s = "MESSAGETABLE";
1540 rt = RT_MESSAGETABLE;
1541 break;
1543 case RES_TYPE_RCDATA:
1544 s = "RCDATA";
1545 rt = RT_RCDATA;
1546 break;
1548 case RES_TYPE_STRINGTABLE:
1549 s = "STRINGTABLE";
1550 rt = RT_STRING;
1551 break;
1553 case RES_TYPE_USERDATA:
1554 s = NULL;
1555 rt = 0;
1556 break;
1558 case RES_TYPE_VERSIONINFO:
1559 s = "VERSIONINFO";
1560 rt = RT_VERSION;
1561 break;
1564 if (rt != 0
1565 && type != NULL
1566 && (type->named || type->u.id != (unsigned long) rt))
1568 fprintf (e, "// Unexpected resource type mismatch: ");
1569 res_id_print (e, *type, 1);
1570 fprintf (e, " != %d", rt);
1573 if (res->coff_info.codepage != 0)
1574 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1575 if (res->coff_info.reserved != 0)
1576 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1578 if (name != NULL)
1579 res_id_print (e, *name, 0);
1580 else
1581 fprintf (e, "??Unknown-Name??");
1583 fprintf (e, " ");
1584 if (s != NULL)
1585 fprintf (e, "%s", s);
1586 else if (type != NULL)
1587 res_id_print (e, *type, 0);
1588 else
1589 fprintf (e, "??Unknown-Type??");
1591 if (res->res_info.memflags != 0)
1593 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1594 fprintf (e, " MOVEABLE");
1595 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1596 fprintf (e, " PURE");
1597 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1598 fprintf (e, " PRELOAD");
1599 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1600 fprintf (e, " DISCARDABLE");
1603 if (res->type == RES_TYPE_DIALOG)
1605 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1606 res->u.dialog->width, res->u.dialog->height);
1607 if (res->u.dialog->ex != NULL
1608 && res->u.dialog->ex->help != 0)
1609 fprintf (e, ", %lu", res->u.dialog->ex->help);
1612 fprintf (e, "\n");
1614 if ((res->res_info.language != 0 && res->res_info.language != *language)
1615 || res->res_info.characteristics != 0
1616 || res->res_info.version != 0)
1618 int modifiers;
1620 switch (res->type)
1622 case RES_TYPE_ACCELERATOR:
1623 case RES_TYPE_DIALOG:
1624 case RES_TYPE_MENU:
1625 case RES_TYPE_RCDATA:
1626 case RES_TYPE_STRINGTABLE:
1627 modifiers = 1;
1628 break;
1630 default:
1631 modifiers = 0;
1632 break;
1635 if (res->res_info.language != 0 && res->res_info.language != *language)
1636 fprintf (e, "%sLANGUAGE %d, %d\n",
1637 modifiers ? "// " : "",
1638 res->res_info.language & 0xff,
1639 (res->res_info.language >> 8) & 0xff);
1640 if (res->res_info.characteristics != 0)
1641 fprintf (e, "%sCHARACTERISTICS %lu\n",
1642 modifiers ? "// " : "",
1643 res->res_info.characteristics);
1644 if (res->res_info.version != 0)
1645 fprintf (e, "%sVERSION %lu\n",
1646 modifiers ? "// " : "",
1647 res->res_info.version);
1650 switch (res->type)
1652 default:
1653 abort ();
1655 case RES_TYPE_ACCELERATOR:
1656 write_rc_accelerators (e, res->u.acc);
1657 break;
1659 case RES_TYPE_CURSOR:
1660 write_rc_cursor (e, res->u.cursor);
1661 break;
1663 case RES_TYPE_GROUP_CURSOR:
1664 write_rc_group_cursor (e, res->u.group_cursor);
1665 break;
1667 case RES_TYPE_DIALOG:
1668 write_rc_dialog (e, res->u.dialog);
1669 break;
1671 case RES_TYPE_FONTDIR:
1672 write_rc_fontdir (e, res->u.fontdir);
1673 break;
1675 case RES_TYPE_GROUP_ICON:
1676 write_rc_group_icon (e, res->u.group_icon);
1677 break;
1679 case RES_TYPE_MENU:
1680 write_rc_menu (e, res->u.menu, menuex);
1681 break;
1683 case RES_TYPE_RCDATA:
1684 write_rc_rcdata (e, res->u.rcdata, 0);
1685 break;
1687 case RES_TYPE_STRINGTABLE:
1688 write_rc_stringtable (e, name, res->u.stringtable);
1689 break;
1691 case RES_TYPE_USERDATA:
1692 write_rc_rcdata (e, res->u.userdata, 0);
1693 break;
1695 case RES_TYPE_VERSIONINFO:
1696 write_rc_versioninfo (e, res->u.versioninfo);
1697 break;
1699 case RES_TYPE_BITMAP:
1700 case RES_TYPE_FONT:
1701 case RES_TYPE_ICON:
1702 case RES_TYPE_MESSAGETABLE:
1703 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1704 break;
1708 /* Write out accelerator information. */
1710 static void
1711 write_rc_accelerators (e, accelerators)
1712 FILE *e;
1713 const struct accelerator *accelerators;
1715 const struct accelerator *acc;
1717 fprintf (e, "BEGIN\n");
1718 for (acc = accelerators; acc != NULL; acc = acc->next)
1720 int printable;
1722 fprintf (e, " ");
1724 if ((acc->key & 0x7f) == acc->key
1725 && isprint ((unsigned char) acc->key)
1726 && (acc->flags & ACC_VIRTKEY) == 0)
1728 fprintf (e, "\"%c\"", acc->key);
1729 printable = 1;
1731 else
1733 fprintf (e, "%d", acc->key);
1734 printable = 0;
1737 fprintf (e, ", %d", acc->id);
1739 if (! printable)
1741 if ((acc->flags & ACC_VIRTKEY) != 0)
1742 fprintf (e, ", VIRTKEY");
1743 else
1744 fprintf (e, ", ASCII");
1747 if ((acc->flags & ACC_SHIFT) != 0)
1748 fprintf (e, ", SHIFT");
1749 if ((acc->flags & ACC_CONTROL) != 0)
1750 fprintf (e, ", CONTROL");
1751 if ((acc->flags & ACC_ALT) != 0)
1752 fprintf (e, ", ALT");
1754 fprintf (e, "\n");
1757 fprintf (e, "END\n");
1760 /* Write out cursor information. This would normally be in a separate
1761 file, which the rc file would include. */
1763 static void
1764 write_rc_cursor (e, cursor)
1765 FILE *e;
1766 const struct cursor *cursor;
1768 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1769 cursor->yhotspot);
1770 write_rc_filedata (e, cursor->length, cursor->data);
1773 /* Write out group cursor data. This would normally be built from the
1774 cursor data. */
1776 static void
1777 write_rc_group_cursor (e, group_cursor)
1778 FILE *e;
1779 const struct group_cursor *group_cursor;
1781 const struct group_cursor *gc;
1783 for (gc = group_cursor; gc != NULL; gc = gc->next)
1785 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1786 gc->width, gc->height, gc->planes, gc->bits);
1787 fprintf (e, "// data bytes: %lu; index: %d\n",
1788 gc->bytes, gc->index);
1792 /* Write dialog data. */
1794 static void
1795 write_rc_dialog (e, dialog)
1796 FILE *e;
1797 const struct dialog *dialog;
1799 const struct dialog_control *control;
1801 if (dialog->style != 0)
1802 fprintf (e, "STYLE 0x%lx\n", dialog->style);
1803 if (dialog->exstyle != 0)
1804 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1805 if ((dialog->class.named && dialog->class.u.n.length > 0)
1806 || dialog->class.u.id != 0)
1808 fprintf (e, "CLASS ");
1809 res_id_print (e, dialog->class, 0);
1810 fprintf (e, "\n");
1812 if (dialog->caption != NULL)
1814 fprintf (e, "CAPTION \"");
1815 unicode_print (e, dialog->caption, -1);
1816 fprintf (e, "\"\n");
1818 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
1819 || dialog->menu.u.id != 0)
1821 fprintf (e, "MENU ");
1822 res_id_print (e, dialog->menu, 0);
1823 fprintf (e, "\n");
1825 if (dialog->font != NULL)
1827 fprintf (e, "FONT %d, \"", dialog->pointsize);
1828 unicode_print (e, dialog->font, -1);
1829 fprintf (e, "\"");
1830 if (dialog->ex != NULL
1831 && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
1832 fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
1833 fprintf (e, "\n");
1836 fprintf (e, "BEGIN\n");
1838 for (control = dialog->controls; control != NULL; control = control->next)
1839 write_rc_dialog_control (e, control);
1841 fprintf (e, "END\n");
1844 /* For each predefined control keyword, this table provides the class
1845 and the style. */
1847 struct control_info
1849 const char *name;
1850 unsigned short class;
1851 unsigned long style;
1854 static const struct control_info control_info[] =
1856 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
1857 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
1858 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
1859 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
1860 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
1861 { "CTEXT", CTL_STATIC, SS_CENTER },
1862 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
1863 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
1864 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
1865 { "ICON", CTL_STATIC, SS_ICON },
1866 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
1867 { "LTEXT", CTL_STATIC, SS_LEFT },
1868 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
1869 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
1870 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
1871 { "RTEXT", CTL_STATIC, SS_RIGHT },
1872 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
1873 { "STATE3", CTL_BUTTON, BS_3STATE },
1874 /* It's important that USERBUTTON come after all the other button
1875 types, so that it won't be matched too early. */
1876 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
1877 { NULL, 0, 0 }
1880 /* Write a dialog control. */
1882 static void
1883 write_rc_dialog_control (e, control)
1884 FILE *e;
1885 const struct dialog_control *control;
1887 const struct control_info *ci;
1889 fprintf (e, " ");
1891 if (control->class.named)
1892 ci = NULL;
1893 else
1895 for (ci = control_info; ci->name != NULL; ++ci)
1896 if (ci->class == control->class.u.id
1897 && (ci->style == (unsigned long) -1
1898 || ci->style == (control->style & 0xff)))
1899 break;
1901 if (ci == NULL)
1902 fprintf (e, "CONTROL");
1903 else if (ci->name != NULL)
1904 fprintf (e, "%s", ci->name);
1905 else
1906 fprintf (e, "CONTROL");
1908 if (control->text.named || control->text.u.id != 0)
1910 fprintf (e, " ");
1911 res_id_print (e, control->text, 1);
1912 fprintf (e, ",");
1915 fprintf (e, " %d, ", control->id);
1917 if (ci == NULL)
1919 if (control->class.named)
1920 fprintf (e, "\"");
1921 res_id_print (e, control->class, 0);
1922 if (control->class.named)
1923 fprintf (e, "\"");
1924 fprintf (e, ", 0x%lx, ", control->style);
1927 fprintf (e, "%d, %d", control->x, control->y);
1929 if (control->style != SS_ICON
1930 || control->exstyle != 0
1931 || control->width != 0
1932 || control->height != 0
1933 || control->help != 0)
1935 fprintf (e, ", %d, %d", control->width, control->height);
1937 /* FIXME: We don't need to print the style if it is the default.
1938 More importantly, in certain cases we actually need to turn
1939 off parts of the forced style, by using NOT. */
1940 fprintf (e, ", 0x%lx", control->style);
1942 if (control->exstyle != 0 || control->help != 0)
1943 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1946 fprintf (e, "\n");
1948 if (control->data != NULL)
1949 write_rc_rcdata (e, control->data, 2);
1952 /* Write out font directory data. This would normally be built from
1953 the font data. */
1955 static void
1956 write_rc_fontdir (e, fontdir)
1957 FILE *e;
1958 const struct fontdir *fontdir;
1960 const struct fontdir *fc;
1962 for (fc = fontdir; fc != NULL; fc = fc->next)
1964 fprintf (e, "// Font index: %d\n", fc->index);
1965 write_rc_filedata (e, fc->length, fc->data);
1969 /* Write out group icon data. This would normally be built from the
1970 icon data. */
1972 static void
1973 write_rc_group_icon (e, group_icon)
1974 FILE *e;
1975 const struct group_icon *group_icon;
1977 const struct group_icon *gi;
1979 for (gi = group_icon; gi != NULL; gi = gi->next)
1981 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1982 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
1983 fprintf (e, "// data bytes: %lu; index: %d\n",
1984 gi->bytes, gi->index);
1988 /* Write out a menu resource. */
1990 static void
1991 write_rc_menu (e, menu, menuex)
1992 FILE *e;
1993 const struct menu *menu;
1994 int menuex;
1996 if (menu->help != 0)
1997 fprintf (e, "// Help ID: %lu\n", menu->help);
1998 write_rc_menuitems (e, menu->items, menuex, 0);
2001 /* Write out menuitems. */
2003 static void
2004 write_rc_menuitems (e, menuitems, menuex, ind)
2005 FILE *e;
2006 const struct menuitem *menuitems;
2007 int menuex;
2008 int ind;
2010 const struct menuitem *mi;
2012 indent (e, ind);
2013 fprintf (e, "BEGIN\n");
2015 for (mi = menuitems; mi != NULL; mi = mi->next)
2017 indent (e, ind + 2);
2019 if (mi->popup == NULL)
2020 fprintf (e, "MENUITEM");
2021 else
2022 fprintf (e, "POPUP");
2024 if (! menuex
2025 && mi->popup == NULL
2026 && mi->text == NULL
2027 && mi->type == 0
2028 && mi->id == 0)
2030 fprintf (e, " SEPARATOR\n");
2031 continue;
2034 if (mi->text == NULL)
2035 fprintf (e, " \"\"");
2036 else
2038 fprintf (e, " \"");
2039 unicode_print (e, mi->text, -1);
2040 fprintf (e, "\"");
2043 if (! menuex)
2045 if (mi->popup == NULL)
2046 fprintf (e, ", %d", mi->id);
2048 if ((mi->type & MENUITEM_CHECKED) != 0)
2049 fprintf (e, ", CHECKED");
2050 if ((mi->type & MENUITEM_GRAYED) != 0)
2051 fprintf (e, ", GRAYED");
2052 if ((mi->type & MENUITEM_HELP) != 0)
2053 fprintf (e, ", HELP");
2054 if ((mi->type & MENUITEM_INACTIVE) != 0)
2055 fprintf (e, ", INACTIVE");
2056 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2057 fprintf (e, ", MENUBARBREAK");
2058 if ((mi->type & MENUITEM_MENUBREAK) != 0)
2059 fprintf (e, ", MENUBREAK");
2061 else
2063 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2065 fprintf (e, ", %d", mi->id);
2066 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2068 fprintf (e, ", %lu", mi->type);
2069 if (mi->state != 0 || mi->help != 0)
2071 fprintf (e, ", %lu", mi->state);
2072 if (mi->help != 0)
2073 fprintf (e, ", %lu", mi->help);
2079 fprintf (e, "\n");
2081 if (mi->popup != NULL)
2082 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2085 indent (e, ind);
2086 fprintf (e, "END\n");
2089 /* Write out an rcdata resource. This is also used for other types of
2090 resources that need to print arbitrary data. */
2092 static void
2093 write_rc_rcdata (e, rcdata, ind)
2094 FILE *e;
2095 const struct rcdata_item *rcdata;
2096 int ind;
2098 const struct rcdata_item *ri;
2100 indent (e, ind);
2101 fprintf (e, "BEGIN\n");
2103 for (ri = rcdata; ri != NULL; ri = ri->next)
2105 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
2106 continue;
2108 indent (e, ind + 2);
2110 switch (ri->type)
2112 default:
2113 abort ();
2115 case RCDATA_WORD:
2116 fprintf (e, "%d", ri->u.word);
2117 break;
2119 case RCDATA_DWORD:
2120 fprintf (e, "%luL", ri->u.dword);
2121 break;
2123 case RCDATA_STRING:
2125 const char *s;
2126 unsigned long i;
2128 fprintf (e, "\"");
2129 s = ri->u.string.s;
2130 for (i = 0; i < ri->u.string.length; i++)
2132 if (isprint ((unsigned char) *s))
2133 putc (*s, e);
2134 else
2135 fprintf (e, "\\%03o", *s);
2137 fprintf (e, "\"");
2138 break;
2141 case RCDATA_WSTRING:
2142 fprintf (e, "L\"");
2143 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2144 fprintf (e, "\"");
2145 break;
2147 case RCDATA_BUFFER:
2149 unsigned long i;
2150 int first;
2152 /* Assume little endian data. */
2154 first = 1;
2155 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2157 unsigned long l;
2158 int j;
2160 if (! first)
2161 indent (e, ind + 2);
2162 l = ((((((ri->u.buffer.data[i + 3] << 8)
2163 | ri->u.buffer.data[i + 2]) << 8)
2164 | ri->u.buffer.data[i + 1]) << 8)
2165 | ri->u.buffer.data[i]);
2166 fprintf (e, "%luL", l);
2167 if (i + 4 < ri->u.buffer.length || ri->next != NULL)
2168 fprintf (e, ",");
2169 for (j = 0; j < 4; ++j)
2170 if (! isprint (ri->u.buffer.data[i + j])
2171 && ri->u.buffer.data[i + j] != 0)
2172 break;
2173 if (j >= 4)
2175 fprintf (e, "\t// ");
2176 for (j = 0; j < 4; ++j)
2178 if (! isprint (ri->u.buffer.data[i + j]))
2179 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2180 else
2182 if (ri->u.buffer.data[i + j] == '\\')
2183 fprintf (e, "\\");
2184 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2188 fprintf (e, "\n");
2189 first = 0;
2192 if (i + 1 < ri->u.buffer.length)
2194 int s;
2195 int j;
2197 if (! first)
2198 indent (e, ind + 2);
2199 s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2200 fprintf (e, "%d", s);
2201 if (i + 2 < ri->u.buffer.length || ri->next != NULL)
2202 fprintf (e, ",");
2203 for (j = 0; j < 2; ++j)
2204 if (! isprint (ri->u.buffer.data[i + j])
2205 && ri->u.buffer.data[i + j] != 0)
2206 break;
2207 if (j >= 2)
2209 fprintf (e, "\t// ");
2210 for (j = 0; j < 2; ++j)
2212 if (! isprint (ri->u.buffer.data[i + j]))
2213 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2214 else
2216 if (ri->u.buffer.data[i + j] == '\\')
2217 fprintf (e, "\\");
2218 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2222 fprintf (e, "\n");
2223 i += 2;
2224 first = 0;
2227 if (i < ri->u.buffer.length)
2229 if (! first)
2230 indent (e, ind + 2);
2231 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2232 && isprint (ri->u.buffer.data[i]))
2233 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2234 else
2235 fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
2236 if (ri->next != NULL)
2237 fprintf (e, ",");
2238 fprintf (e, "\n");
2239 first = 0;
2242 break;
2246 if (ri->type != RCDATA_BUFFER)
2248 if (ri->next != NULL)
2249 fprintf (e, ",");
2250 fprintf (e, "\n");
2254 indent (e, ind);
2255 fprintf (e, "END\n");
2258 /* Write out a stringtable resource. */
2260 static void
2261 write_rc_stringtable (e, name, stringtable)
2262 FILE *e;
2263 const struct res_id *name;
2264 const struct stringtable *stringtable;
2266 unsigned long offset;
2267 int i;
2269 if (name != NULL && ! name->named)
2270 offset = (name->u.id - 1) << 4;
2271 else
2273 fprintf (e, "// %s string table name\n",
2274 name == NULL ? "Missing" : "Invalid");
2275 offset = 0;
2278 fprintf (e, "BEGIN\n");
2280 for (i = 0; i < 16; i++)
2282 if (stringtable->strings[i].length != 0)
2284 fprintf (e, " %lu, \"", offset + i);
2285 unicode_print (e, stringtable->strings[i].string,
2286 stringtable->strings[i].length);
2287 fprintf (e, "\"\n");
2291 fprintf (e, "END\n");
2294 /* Write out a versioninfo resource. */
2296 static void
2297 write_rc_versioninfo (e, versioninfo)
2298 FILE *e;
2299 const struct versioninfo *versioninfo;
2301 const struct fixed_versioninfo *f;
2302 const struct ver_info *vi;
2304 f = versioninfo->fixed;
2305 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2306 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2307 (f->file_version_ms >> 16) & 0xffff,
2308 f->file_version_ms & 0xffff,
2309 (f->file_version_ls >> 16) & 0xffff,
2310 f->file_version_ls & 0xffff);
2311 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2312 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2313 (f->product_version_ms >> 16) & 0xffff,
2314 f->product_version_ms & 0xffff,
2315 (f->product_version_ls >> 16) & 0xffff,
2316 f->product_version_ls & 0xffff);
2317 if (f->file_flags_mask != 0)
2318 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2319 if (f->file_flags != 0)
2320 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2321 if (f->file_os != 0)
2322 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2323 if (f->file_type != 0)
2324 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2325 if (f->file_subtype != 0)
2326 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2327 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2328 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2330 fprintf (e, "BEGIN\n");
2332 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2334 switch (vi->type)
2336 case VERINFO_STRING:
2338 const struct ver_stringinfo *vs;
2340 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2341 fprintf (e, " BEGIN\n");
2342 fprintf (e, " BLOCK \"");
2343 unicode_print (e, vi->u.string.language, -1);
2344 fprintf (e, "\"\n");
2345 fprintf (e, " BEGIN\n");
2347 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2349 fprintf (e, " VALUE \"");
2350 unicode_print (e, vs->key, -1);
2351 fprintf (e, "\", \"");
2352 unicode_print (e, vs->value, -1);
2353 fprintf (e, "\"\n");
2356 fprintf (e, " END\n");
2357 fprintf (e, " END\n");
2358 break;
2361 case VERINFO_VAR:
2363 const struct ver_varinfo *vv;
2365 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2366 fprintf (e, " BEGIN\n");
2367 fprintf (e, " VALUE \"");
2368 unicode_print (e, vi->u.var.key, -1);
2369 fprintf (e, "\"");
2371 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2372 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2373 vv->charset);
2375 fprintf (e, "\n END\n");
2377 break;
2382 fprintf (e, "END\n");
2385 /* Write out data which would normally be read from a file. */
2387 static void
2388 write_rc_filedata (e, length, data)
2389 FILE *e;
2390 unsigned long length;
2391 const unsigned char *data;
2393 unsigned long i;
2395 for (i = 0; i + 15 < length; i += 16)
2397 fprintf (e, "// %4lx: ", i);
2398 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2399 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2400 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2401 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2402 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2403 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2406 if (i < length)
2408 fprintf (e, "// %4lx:", i);
2409 while (i < length)
2411 fprintf (e, " %02x", data[i]);
2412 ++i;
2414 fprintf (e, "\n");