Initial revision
[binutils.git] / binutils / resrc.c
blob9ba3c11780726be0a30dcb3a5e1e0610b8089377
1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998 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 void close_pipe PARAMS ((void));
116 static void unexpected_eof PARAMS ((const char *));
117 static int get_word PARAMS ((FILE *, const char *));
118 static unsigned long get_long PARAMS ((FILE *, const char *));
119 static void get_data
120 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
121 static void define_fontdirs PARAMS ((void));
123 /* Read an rc file. */
125 struct res_directory *
126 read_rc_file (filename, preprocessor, preprocargs, language)
127 const char *filename;
128 const char *preprocessor;
129 const char *preprocargs;
130 int language;
132 char *cmd;
134 if (preprocessor == NULL)
135 preprocessor = DEFAULT_PREPROCESSOR;
137 if (preprocargs == NULL)
138 preprocargs = "";
139 if (filename == NULL)
140 filename = "-";
142 cmd = xmalloc (strlen (preprocessor)
143 + strlen (preprocargs)
144 + strlen (filename)
145 + 10);
146 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
148 cpp_pipe = popen (cmd, FOPEN_RT);
149 if (cpp_pipe == NULL)
150 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
151 free (cmd);
153 xatexit (close_pipe);
155 rc_filename = xstrdup (filename);
156 rc_lineno = 1;
157 if (language != -1)
158 rcparse_set_language (language);
159 yyin = cpp_pipe;
160 yyparse ();
162 if (pclose (cpp_pipe) != 0)
163 fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name);
164 cpp_pipe = NULL;
166 if (fontdirs != NULL)
167 define_fontdirs ();
169 free (rc_filename);
170 rc_filename = NULL;
172 return resources;
175 /* Close the pipe if it is open. This is called via xatexit. */
177 void
178 close_pipe ()
180 if (cpp_pipe != NULL)
181 pclose (cpp_pipe);
184 /* Report an error while reading an rc file. */
186 void
187 yyerror (msg)
188 const char *msg;
190 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
193 /* Issue a warning while reading an rc file. */
195 void
196 rcparse_warning (msg)
197 const char *msg;
199 fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
202 /* Die if we get an unexpected end of file. */
204 static void
205 unexpected_eof (msg)
206 const char *msg;
208 fatal (_("%s: unexpected EOF"), msg);
211 /* Read a 16 bit word from a file. The data is assumed to be little
212 endian. */
214 static int
215 get_word (e, msg)
216 FILE *e;
217 const char *msg;
219 int b1, b2;
221 b1 = getc (e);
222 b2 = getc (e);
223 if (feof (e))
224 unexpected_eof (msg);
225 return ((b2 & 0xff) << 8) | (b1 & 0xff);
228 /* Read a 32 bit word from a file. The data is assumed to be little
229 endian. */
231 static unsigned long
232 get_long (e, msg)
233 FILE *e;
234 const char *msg;
236 int b1, b2, b3, b4;
238 b1 = getc (e);
239 b2 = getc (e);
240 b3 = getc (e);
241 b4 = getc (e);
242 if (feof (e))
243 unexpected_eof (msg);
244 return (((((((b4 & 0xff) << 8)
245 | (b3 & 0xff)) << 8)
246 | (b2 & 0xff)) << 8)
247 | (b1 & 0xff));
250 /* Read data from a file. This is a wrapper to do error checking. */
252 static void
253 get_data (e, p, c, msg)
254 FILE *e;
255 unsigned char *p;
256 unsigned long c;
257 const char *msg;
259 unsigned long got;
261 got = fread (p, 1, c, e);
262 if (got == c)
263 return;
265 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
268 /* Define an accelerator resource. */
270 void
271 define_accelerator (id, resinfo, data)
272 struct res_id id;
273 const struct res_res_info *resinfo;
274 struct accelerator *data;
276 struct res_resource *r;
278 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
279 resinfo->language, 0);
280 r->type = RES_TYPE_ACCELERATOR;
281 r->u.acc = data;
282 r->res_info = *resinfo;
285 /* Define a bitmap resource. Bitmap data is stored in a file. The
286 first 14 bytes of the file are a standard header, which is not
287 included in the resource data. */
289 #define BITMAP_SKIP (14)
291 void
292 define_bitmap (id, resinfo, filename)
293 struct res_id id;
294 const struct res_res_info *resinfo;
295 const char *filename;
297 FILE *e;
298 char *real_filename;
299 struct stat s;
300 unsigned char *data;
301 int i;
302 struct res_resource *r;
304 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
306 if (stat (real_filename, &s) < 0)
307 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
308 strerror (errno));
310 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
312 for (i = 0; i < BITMAP_SKIP; i++)
313 getc (e);
315 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
317 fclose (e);
318 free (real_filename);
320 r = define_standard_resource (&resources, RT_BITMAP, id,
321 resinfo->language, 0);
323 r->type = RES_TYPE_BITMAP;
324 r->u.data.length = s.st_size - BITMAP_SKIP;
325 r->u.data.data = data;
326 r->res_info = *resinfo;
329 /* Define a cursor resource. A cursor file may contain a set of
330 bitmaps, each representing the same cursor at various different
331 resolutions. They each get written out with a different ID. The
332 real cursor resource is then a group resource which can be used to
333 select one of the actual cursors. */
335 void
336 define_cursor (id, resinfo, filename)
337 struct res_id id;
338 const struct res_res_info *resinfo;
339 const char *filename;
341 FILE *e;
342 char *real_filename;
343 int type, count, i;
344 struct icondir *icondirs;
345 int first_cursor;
346 struct res_resource *r;
347 struct group_cursor *first, **pp;
349 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
351 /* A cursor file is basically an icon file. The start of the file
352 is a three word structure. The first word is ignored. The
353 second word is the type of data. The third word is the number of
354 entries. */
356 get_word (e, real_filename);
357 type = get_word (e, real_filename);
358 count = get_word (e, real_filename);
359 if (type != 2)
360 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
362 /* Read in the icon directory entries. */
364 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
366 for (i = 0; i < count; i++)
368 icondirs[i].width = getc (e);
369 icondirs[i].height = getc (e);
370 icondirs[i].colorcount = getc (e);
371 getc (e);
372 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
373 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
374 icondirs[i].bytes = get_long (e, real_filename);
375 icondirs[i].offset = get_long (e, real_filename);
377 if (feof (e))
378 unexpected_eof (real_filename);
381 /* Define each cursor as a unique resource. */
383 first_cursor = cursors;
385 for (i = 0; i < count; i++)
387 unsigned char *data;
388 struct res_id name;
389 struct cursor *c;
391 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
392 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
393 icondirs[i].offset, strerror (errno));
395 data = (unsigned char *) res_alloc (icondirs[i].bytes);
397 get_data (e, data, icondirs[i].bytes, real_filename);
399 c = (struct cursor *) res_alloc (sizeof *c);
400 c->xhotspot = icondirs[i].u.cursor.xhotspot;
401 c->yhotspot = icondirs[i].u.cursor.yhotspot;
402 c->length = icondirs[i].bytes;
403 c->data = data;
405 ++cursors;
407 name.named = 0;
408 name.u.id = cursors;
410 r = define_standard_resource (&resources, RT_CURSOR, name,
411 resinfo->language, 0);
412 r->type = RES_TYPE_CURSOR;
413 r->u.cursor = c;
414 r->res_info = *resinfo;
417 fclose (e);
418 free (real_filename);
420 /* Define a cursor group resource. */
422 first = NULL;
423 pp = &first;
424 for (i = 0; i < count; i++)
426 struct group_cursor *cg;
428 cg = (struct group_cursor *) res_alloc (sizeof *cg);
429 cg->next = NULL;
430 cg->width = icondirs[i].width;
431 cg->height = 2 * icondirs[i].height;
433 /* FIXME: What should these be set to? */
434 cg->planes = 1;
435 cg->bits = 1;
437 cg->bytes = icondirs[i].bytes + 4;
438 cg->index = first_cursor + i + 1;
440 *pp = cg;
441 pp = &(*pp)->next;
444 free (icondirs);
446 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
447 resinfo->language, 0);
448 r->type = RES_TYPE_GROUP_CURSOR;
449 r->u.group_cursor = first;
450 r->res_info = *resinfo;
453 /* Define a dialog resource. */
455 void
456 define_dialog (id, resinfo, dialog)
457 struct res_id id;
458 const struct res_res_info *resinfo;
459 const struct dialog *dialog;
461 struct dialog *copy;
462 struct res_resource *r;
464 copy = (struct dialog *) res_alloc (sizeof *copy);
465 *copy = *dialog;
467 r = define_standard_resource (&resources, RT_DIALOG, id,
468 resinfo->language, 0);
469 r->type = RES_TYPE_DIALOG;
470 r->u.dialog = copy;
471 r->res_info = *resinfo;
474 /* Define a dialog control. This does not define a resource, but
475 merely allocates and fills in a structure. */
477 struct dialog_control *
478 define_control (text, id, x, y, width, height, class, style, exstyle)
479 const char *text;
480 unsigned long id;
481 unsigned long x;
482 unsigned long y;
483 unsigned long width;
484 unsigned long height;
485 unsigned long class;
486 unsigned long style;
487 unsigned long exstyle;
489 struct dialog_control *n;
491 n = (struct dialog_control *) res_alloc (sizeof *n);
492 n->next = NULL;
493 n->id = id;
494 n->style = style;
495 n->exstyle = exstyle;
496 n->x = x;
497 n->y = y;
498 n->width = width;
499 n->height = height;
500 n->class.named = 0;
501 n->class.u.id = class;
502 if (text != NULL)
503 res_string_to_id (&n->text, text);
504 else
506 n->text.named = 0;
507 n->text.u.id = 0;
509 n->data = NULL;
510 n->help = 0;
512 return n;
515 /* Define a font resource. */
517 void
518 define_font (id, resinfo, filename)
519 struct res_id id;
520 const struct res_res_info *resinfo;
521 const char *filename;
523 FILE *e;
524 char *real_filename;
525 struct stat s;
526 unsigned char *data;
527 struct res_resource *r;
528 long offset;
529 long fontdatalength;
530 unsigned char *fontdata;
531 struct fontdir *fd;
532 const char *device, *face;
533 struct fontdir **pp;
535 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
537 if (stat (real_filename, &s) < 0)
538 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
539 strerror (errno));
541 data = (unsigned char *) res_alloc (s.st_size);
543 get_data (e, data, s.st_size, real_filename);
545 fclose (e);
546 free (real_filename);
548 r = define_standard_resource (&resources, RT_FONT, id,
549 resinfo->language, 0);
551 r->type = RES_TYPE_FONT;
552 r->u.data.length = s.st_size;
553 r->u.data.data = data;
554 r->res_info = *resinfo;
556 /* For each font resource, we must add an entry in the FONTDIR
557 resource. The FONTDIR resource includes some strings in the font
558 file. To find them, we have to do some magic on the data we have
559 read. */
561 offset = ((((((data[47] << 8)
562 | data[46]) << 8)
563 | data[45]) << 8)
564 | data[44]);
565 if (offset > 0 && offset < s.st_size)
566 device = (char *) data + offset;
567 else
568 device = "";
570 offset = ((((((data[51] << 8)
571 | data[50]) << 8)
572 | data[49]) << 8)
573 | data[48]);
574 if (offset > 0 && offset < s.st_size)
575 face = (char *) data + offset;
576 else
577 face = "";
579 ++fonts;
581 fontdatalength = 58 + strlen (device) + strlen (face);
582 fontdata = (unsigned char *) res_alloc (fontdatalength);
583 memcpy (fontdata, data, 56);
584 strcpy ((char *) fontdata + 56, device);
585 strcpy ((char *) fontdata + 57 + strlen (device), face);
587 fd = (struct fontdir *) res_alloc (sizeof *fd);
588 fd->next = NULL;
589 fd->index = fonts;
590 fd->length = fontdatalength;
591 fd->data = fontdata;
593 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
595 *pp = fd;
597 /* For the single fontdirs resource, we always use the resource
598 information of the last font. I don't know what else to do. */
599 fontdirs_resinfo = *resinfo;
602 /* Define the fontdirs resource. This is called after the entire rc
603 file has been parsed, if any font resources were seen. */
605 static void
606 define_fontdirs ()
608 struct res_resource *r;
609 struct res_id id;
611 id.named = 0;
612 id.u.id = 1;
614 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
616 r->type = RES_TYPE_FONTDIR;
617 r->u.fontdir = fontdirs;
618 r->res_info = fontdirs_resinfo;
621 /* Define an icon resource. An icon file may contain a set of
622 bitmaps, each representing the same icon at various different
623 resolutions. They each get written out with a different ID. The
624 real icon resource is then a group resource which can be used to
625 select one of the actual icon bitmaps. */
627 void
628 define_icon (id, resinfo, filename)
629 struct res_id id;
630 const struct res_res_info *resinfo;
631 const char *filename;
633 FILE *e;
634 char *real_filename;
635 int type, count, i;
636 struct icondir *icondirs;
637 int first_icon;
638 struct res_resource *r;
639 struct group_icon *first, **pp;
641 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
643 /* The start of an icon file is a three word structure. The first
644 word is ignored. The second word is the type of data. The third
645 word is the number of entries. */
647 get_word (e, real_filename);
648 type = get_word (e, real_filename);
649 count = get_word (e, real_filename);
650 if (type != 1)
651 fatal (_("icon file `%s' does not contain icon data"), real_filename);
653 /* Read in the icon directory entries. */
655 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
657 for (i = 0; i < count; i++)
659 icondirs[i].width = getc (e);
660 icondirs[i].height = getc (e);
661 icondirs[i].colorcount = getc (e);
662 getc (e);
663 icondirs[i].u.icon.planes = get_word (e, real_filename);
664 icondirs[i].u.icon.bits = get_word (e, real_filename);
665 icondirs[i].bytes = get_long (e, real_filename);
666 icondirs[i].offset = get_long (e, real_filename);
668 if (feof (e))
669 unexpected_eof (real_filename);
672 /* Define each icon as a unique resource. */
674 first_icon = icons;
676 for (i = 0; i < count; i++)
678 unsigned char *data;
679 struct res_id name;
681 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
682 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
683 icondirs[i].offset, strerror (errno));
685 data = (unsigned char *) res_alloc (icondirs[i].bytes);
687 get_data (e, data, icondirs[i].bytes, real_filename);
689 ++icons;
691 name.named = 0;
692 name.u.id = icons;
694 r = define_standard_resource (&resources, RT_ICON, name,
695 resinfo->language, 0);
696 r->type = RES_TYPE_ICON;
697 r->u.data.length = icondirs[i].bytes;
698 r->u.data.data = data;
699 r->res_info = *resinfo;
702 fclose (e);
703 free (real_filename);
705 /* Define an icon group resource. */
707 first = NULL;
708 pp = &first;
709 for (i = 0; i < count; i++)
711 struct group_icon *cg;
713 /* For some reason, at least in some files the planes and bits
714 are zero. We instead set them from the color. This is
715 copied from rcl. */
717 cg = (struct group_icon *) res_alloc (sizeof *cg);
718 cg->next = NULL;
719 cg->width = icondirs[i].width;
720 cg->height = icondirs[i].height;
721 cg->colors = icondirs[i].colorcount;
723 cg->planes = 1;
724 cg->bits = 0;
725 while ((1 << cg->bits) < cg->colors)
726 ++cg->bits;
728 cg->bytes = icondirs[i].bytes;
729 cg->index = first_icon + i + 1;
731 *pp = cg;
732 pp = &(*pp)->next;
735 free (icondirs);
737 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
738 resinfo->language, 0);
739 r->type = RES_TYPE_GROUP_ICON;
740 r->u.group_icon = first;
741 r->res_info = *resinfo;
744 /* Define a menu resource. */
746 void
747 define_menu (id, resinfo, menuitems)
748 struct res_id id;
749 const struct res_res_info *resinfo;
750 struct menuitem *menuitems;
752 struct menu *m;
753 struct res_resource *r;
755 m = (struct menu *) res_alloc (sizeof *m);
756 m->items = menuitems;
757 m->help = 0;
759 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
760 r->type = RES_TYPE_MENU;
761 r->u.menu = m;
762 r->res_info = *resinfo;
765 /* Define a menu item. This does not define a resource, but merely
766 allocates and fills in a structure. */
768 struct menuitem *
769 define_menuitem (text, menuid, type, state, help, menuitems)
770 const char *text;
771 int menuid;
772 unsigned long type;
773 unsigned long state;
774 unsigned long help;
775 struct menuitem *menuitems;
777 struct menuitem *mi;
779 mi = (struct menuitem *) res_alloc (sizeof *mi);
780 mi->next = NULL;
781 mi->type = type;
782 mi->state = state;
783 mi->id = menuid;
784 if (text == NULL)
785 mi->text = NULL;
786 else
787 unicode_from_ascii ((int *) NULL, &mi->text, text);
788 mi->help = help;
789 mi->popup = menuitems;
790 return mi;
793 /* Define a messagetable resource. */
795 void
796 define_messagetable (id, resinfo, filename)
797 struct res_id id;
798 const struct res_res_info *resinfo;
799 const char *filename;
801 FILE *e;
802 char *real_filename;
803 struct stat s;
804 unsigned char *data;
805 struct res_resource *r;
807 e = open_file_search (filename, FOPEN_RB, "messagetable file",
808 &real_filename);
810 if (stat (real_filename, &s) < 0)
811 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
812 strerror (errno));
814 data = (unsigned char *) res_alloc (s.st_size);
816 get_data (e, data, s.st_size, real_filename);
818 fclose (e);
819 free (real_filename);
821 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
822 resinfo->language, 0);
824 r->type = RES_TYPE_MESSAGETABLE;
825 r->u.data.length = s.st_size;
826 r->u.data.data = data;
827 r->res_info = *resinfo;
830 /* Define an rcdata resource. */
832 void
833 define_rcdata (id, resinfo, data)
834 struct res_id id;
835 const struct res_res_info *resinfo;
836 struct rcdata_item *data;
838 struct res_resource *r;
840 r = define_standard_resource (&resources, RT_RCDATA, id,
841 resinfo->language, 0);
842 r->type = RES_TYPE_RCDATA;
843 r->u.rcdata = data;
844 r->res_info = *resinfo;
847 /* Create an rcdata item holding a string. */
849 struct rcdata_item *
850 define_rcdata_string (string, len)
851 const char *string;
852 unsigned long len;
854 struct rcdata_item *ri;
855 char *s;
857 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
858 ri->next = NULL;
859 ri->type = RCDATA_STRING;
860 ri->u.string.length = len;
861 s = (char *) res_alloc (len);
862 memcpy (s, string, len);
863 ri->u.string.s = s;
865 return ri;
868 /* Create an rcdata item holding a number. */
870 struct rcdata_item *
871 define_rcdata_number (val, dword)
872 unsigned long val;
873 int dword;
875 struct rcdata_item *ri;
877 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
878 ri->next = NULL;
879 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
880 ri->u.word = val;
882 return ri;
885 /* Define a stringtable resource. This is called for each string
886 which appears in a STRINGTABLE statement. */
888 void
889 define_stringtable (resinfo, stringid, string)
890 const struct res_res_info *resinfo;
891 unsigned long stringid;
892 const char *string;
894 struct res_id id;
895 struct res_resource *r;
897 id.named = 0;
898 id.u.id = (stringid >> 4) + 1;
899 r = define_standard_resource (&resources, RT_STRING, id,
900 resinfo->language, 1);
902 if (r->type == RES_TYPE_UNINITIALIZED)
904 int i;
906 r->type = RES_TYPE_STRINGTABLE;
907 r->u.stringtable = ((struct stringtable *)
908 res_alloc (sizeof (struct stringtable)));
909 for (i = 0; i < 16; i++)
911 r->u.stringtable->strings[i].length = 0;
912 r->u.stringtable->strings[i].string = NULL;
915 r->res_info = *resinfo;
918 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
919 &r->u.stringtable->strings[stringid & 0xf].string,
920 string);
923 /* Define a user data resource where the data is in the rc file. */
925 void
926 define_user_data (id, type, resinfo, data)
927 struct res_id id;
928 struct res_id type;
929 const struct res_res_info *resinfo;
930 struct rcdata_item *data;
932 struct res_id ids[3];
933 struct res_resource *r;
935 ids[0] = type;
936 ids[1] = id;
937 ids[2].named = 0;
938 ids[2].u.id = resinfo->language;
940 r = define_resource (&resources, 3, ids, 0);
941 r->type = RES_TYPE_USERDATA;
942 r->u.userdata = data;
943 r->res_info = *resinfo;
946 /* Define a user data resource where the data is in a file. */
948 void
949 define_user_file (id, type, resinfo, filename)
950 struct res_id id;
951 struct res_id type;
952 const struct res_res_info *resinfo;
953 const char *filename;
955 FILE *e;
956 char *real_filename;
957 struct stat s;
958 unsigned char *data;
959 struct res_id ids[3];
960 struct res_resource *r;
962 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
964 if (stat (real_filename, &s) < 0)
965 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
966 strerror (errno));
968 data = (unsigned char *) res_alloc (s.st_size);
970 get_data (e, data, s.st_size, real_filename);
972 fclose (e);
973 free (real_filename);
975 ids[0] = type;
976 ids[1] = id;
977 ids[2].named = 0;
978 ids[2].u.id = resinfo->language;
980 r = define_resource (&resources, 3, ids, 0);
981 r->type = RES_TYPE_USERDATA;
982 r->u.userdata = ((struct rcdata_item *)
983 res_alloc (sizeof (struct rcdata_item)));
984 r->u.userdata->next = NULL;
985 r->u.userdata->type = RCDATA_BUFFER;
986 r->u.userdata->u.buffer.length = s.st_size;
987 r->u.userdata->u.buffer.data = data;
988 r->res_info = *resinfo;
991 /* Define a versioninfo resource. */
993 void
994 define_versioninfo (id, language, fixedverinfo, verinfo)
995 struct res_id id;
996 int language;
997 struct fixed_versioninfo *fixedverinfo;
998 struct ver_info *verinfo;
1000 struct res_resource *r;
1002 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1003 r->type = RES_TYPE_VERSIONINFO;
1004 r->u.versioninfo = ((struct versioninfo *)
1005 res_alloc (sizeof (struct versioninfo)));
1006 r->u.versioninfo->fixed = fixedverinfo;
1007 r->u.versioninfo->var = verinfo;
1008 r->res_info.language = language;
1011 /* Add string version info to a list of version information. */
1013 struct ver_info *
1014 append_ver_stringfileinfo (verinfo, language, strings)
1015 struct ver_info *verinfo;
1016 const char *language;
1017 struct ver_stringinfo *strings;
1019 struct ver_info *vi, **pp;
1021 vi = (struct ver_info *) res_alloc (sizeof *vi);
1022 vi->next = NULL;
1023 vi->type = VERINFO_STRING;
1024 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1025 vi->u.string.strings = strings;
1027 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1029 *pp = vi;
1031 return verinfo;
1034 /* Add variable version info to a list of version information. */
1036 struct ver_info *
1037 append_ver_varfileinfo (verinfo, key, var)
1038 struct ver_info *verinfo;
1039 const char *key;
1040 struct ver_varinfo *var;
1042 struct ver_info *vi, **pp;
1044 vi = (struct ver_info *) res_alloc (sizeof *vi);
1045 vi->next = NULL;
1046 vi->type = VERINFO_VAR;
1047 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1048 vi->u.var.var = var;
1050 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1052 *pp = vi;
1054 return verinfo;
1057 /* Append version string information to a list. */
1059 struct ver_stringinfo *
1060 append_verval (strings, key, value)
1061 struct ver_stringinfo *strings;
1062 const char *key;
1063 const char *value;
1065 struct ver_stringinfo *vs, **pp;
1067 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1068 vs->next = NULL;
1069 unicode_from_ascii ((int *) NULL, &vs->key, key);
1070 unicode_from_ascii ((int *) NULL, &vs->value, value);
1072 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1074 *pp = vs;
1076 return strings;
1079 /* Append version variable information to a list. */
1081 struct ver_varinfo *
1082 append_vertrans (var, language, charset)
1083 struct ver_varinfo *var;
1084 unsigned long language;
1085 unsigned long charset;
1087 struct ver_varinfo *vv, **pp;
1089 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1090 vv->next = NULL;
1091 vv->language = language;
1092 vv->charset = charset;
1094 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1096 *pp = vv;
1098 return var;
1101 /* Local functions used to write out an rc file. */
1103 static void indent PARAMS ((FILE *, int));
1104 static void write_rc_directory
1105 PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1106 const struct res_id *, int *, int));
1107 static void write_rc_subdir
1108 PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1109 const struct res_id *, int *, int));
1110 static void write_rc_resource
1111 PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1112 const struct res_resource *, int *));
1113 static void write_rc_accelerators
1114 PARAMS ((FILE *, const struct accelerator *));
1115 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1116 static void write_rc_group_cursor
1117 PARAMS ((FILE *, const struct group_cursor *));
1118 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1119 static void write_rc_dialog_control
1120 PARAMS ((FILE *, const struct dialog_control *));
1121 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1122 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1123 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1124 static void write_rc_menuitems
1125 PARAMS ((FILE *, const struct menuitem *, int, int));
1126 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1127 static void write_rc_stringtable
1128 PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1129 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1130 static void write_rc_filedata
1131 PARAMS ((FILE *, unsigned long, const unsigned char *));
1133 /* Indent a given number of spaces. */
1135 static void
1136 indent (e, c)
1137 FILE *e;
1138 int c;
1140 int i;
1142 for (i = 0; i < c; i++)
1143 putc (' ', e);
1146 /* Dump the resources we have read in the format of an rc file.
1148 Actually, we don't use the format of an rc file, because it's way
1149 too much of a pain--for example, we'd have to write icon resources
1150 into a file and refer to that file. We just generate a readable
1151 format that kind of looks like an rc file, and is useful for
1152 understanding the contents of a resource file. Someday we may want
1153 to generate an rc file which the rc compiler can read; if that day
1154 comes, this code will have to be fixed up. */
1156 void
1157 write_rc_file (filename, resources)
1158 const char *filename;
1159 const struct res_directory *resources;
1161 FILE *e;
1162 int language;
1164 if (filename == NULL)
1165 e = stdout;
1166 else
1168 e = fopen (filename, FOPEN_WT);
1169 if (e == NULL)
1170 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1173 language = -1;
1174 write_rc_directory (e, resources, (const struct res_id *) NULL,
1175 (const struct res_id *) NULL, &language, 1);
1178 /* Write out a directory. E is the file to write to. RD is the
1179 directory. TYPE is a pointer to the level 1 ID which serves as the
1180 resource type. NAME is a pointer to the level 2 ID which serves as
1181 an individual resource name. LANGUAGE is a pointer to the current
1182 language. LEVEL is the level in the tree. */
1184 static void
1185 write_rc_directory (e, rd, type, name, language, level)
1186 FILE *e;
1187 const struct res_directory *rd;
1188 const struct res_id *type;
1189 const struct res_id *name;
1190 int *language;
1191 int level;
1193 const struct res_entry *re;
1195 /* Print out some COFF information that rc files can't represent. */
1197 if (rd->time != 0)
1198 fprintf (e, "// Time stamp: %lu\n", rd->time);
1199 if (rd->characteristics != 0)
1200 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1201 if (rd->major != 0 || rd->minor != 0)
1202 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1204 for (re = rd->entries; re != NULL; re = re->next)
1206 switch (level)
1208 case 1:
1209 /* If we're at level 1, the key of this resource is the
1210 type. This normally duplicates the information we have
1211 stored with the resource itself, but we need to remember
1212 the type if this is a user define resource type. */
1213 type = &re->id;
1214 break;
1216 case 2:
1217 /* If we're at level 2, the key of this resource is the name
1218 we are going to use in the rc printout. */
1219 name = &re->id;
1220 break;
1222 case 3:
1223 /* If we're at level 3, then this key represents a language.
1224 Use it to update the current language. */
1225 if (! re->id.named
1226 && re->id.u.id != (unsigned long) (unsigned int) *language
1227 && (re->id.u.id & 0xffff) == re->id.u.id)
1229 fprintf (e, "LANGUAGE %lu, %lu\n",
1230 re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1231 *language = re->id.u.id;
1233 break;
1235 default:
1236 break;
1239 if (re->subdir)
1240 write_rc_subdir (e, re, type, name, language, level);
1241 else
1243 if (level == 3)
1245 /* This is the normal case: the three levels are
1246 TYPE/NAME/LANGUAGE. NAME will have been set at level
1247 2, and represents the name to use. We probably just
1248 set LANGUAGE, and it will probably match what the
1249 resource itself records if anything. */
1250 write_rc_resource (e, type, name, re->u.res, language);
1252 else
1254 fprintf (e, "// Resource at unexpected level %d\n", level);
1255 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1256 language);
1262 /* Write out a subdirectory entry. E is the file to write to. RE is
1263 the subdirectory entry. TYPE and NAME are pointers to higher level
1264 IDs, or NULL. LANGUAGE is a pointer to the current language.
1265 LEVEL is the level in the tree. */
1267 static void
1268 write_rc_subdir (e, re, type, name, language, level)
1269 FILE *e;
1270 const struct res_entry *re;
1271 const struct res_id *type;
1272 const struct res_id *name;
1273 int *language;
1274 int level;
1276 fprintf (e, "\n");
1277 switch (level)
1279 case 1:
1280 fprintf (e, "// Type: ");
1281 if (re->id.named)
1282 res_id_print (e, re->id, 1);
1283 else
1285 const char *s;
1287 switch (re->id.u.id)
1289 case RT_CURSOR: s = "cursor"; break;
1290 case RT_BITMAP: s = "bitmap"; break;
1291 case RT_ICON: s = "icon"; break;
1292 case RT_MENU: s = "menu"; break;
1293 case RT_DIALOG: s = "dialog"; break;
1294 case RT_STRING: s = "stringtable"; break;
1295 case RT_FONTDIR: s = "fontdir"; break;
1296 case RT_FONT: s = "font"; break;
1297 case RT_ACCELERATOR: s = "accelerators"; break;
1298 case RT_RCDATA: s = "rcdata"; break;
1299 case RT_MESSAGETABLE: s = "messagetable"; break;
1300 case RT_GROUP_CURSOR: s = "group cursor"; break;
1301 case RT_GROUP_ICON: s = "group icon"; break;
1302 case RT_VERSION: s = "version"; break;
1303 case RT_DLGINCLUDE: s = "dlginclude"; break;
1304 case RT_PLUGPLAY: s = "plugplay"; break;
1305 case RT_VXD: s = "vxd"; break;
1306 case RT_ANICURSOR: s = "anicursor"; break;
1307 case RT_ANIICON: s = "aniicon"; break;
1308 default: s = NULL; break;
1311 if (s != NULL)
1312 fprintf (e, "%s", s);
1313 else
1314 res_id_print (e, re->id, 1);
1316 fprintf (e, "\n");
1317 break;
1319 case 2:
1320 fprintf (e, "// Name: ");
1321 res_id_print (e, re->id, 1);
1322 fprintf (e, "\n");
1323 break;
1325 case 3:
1326 fprintf (e, "// Language: ");
1327 res_id_print (e, re->id, 1);
1328 fprintf (e, "\n");
1329 break;
1331 default:
1332 fprintf (e, "// Level %d: ", level);
1333 res_id_print (e, re->id, 1);
1334 fprintf (e, "\n");
1337 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1340 /* Write out a single resource. E is the file to write to. TYPE is a
1341 pointer to the type of the resource. NAME is a pointer to the name
1342 of the resource; it will be NULL if there is a level mismatch. RES
1343 is the resource data. LANGUAGE is a pointer to the current
1344 language. */
1346 static void
1347 write_rc_resource (e, type, name, res, language)
1348 FILE *e;
1349 const struct res_id *type;
1350 const struct res_id *name;
1351 const struct res_resource *res;
1352 int *language;
1354 const char *s;
1355 int rt;
1356 int menuex = 0;
1358 fprintf (e, "\n");
1360 switch (res->type)
1362 default:
1363 abort ();
1365 case RES_TYPE_ACCELERATOR:
1366 s = "ACCELERATOR";
1367 rt = RT_ACCELERATOR;
1368 break;
1370 case RES_TYPE_BITMAP:
1371 s = "BITMAP";
1372 rt = RT_BITMAP;
1373 break;
1375 case RES_TYPE_CURSOR:
1376 s = "CURSOR";
1377 rt = RT_CURSOR;
1378 break;
1380 case RES_TYPE_GROUP_CURSOR:
1381 s = "GROUP_CURSOR";
1382 rt = RT_GROUP_CURSOR;
1383 break;
1385 case RES_TYPE_DIALOG:
1386 if (extended_dialog (res->u.dialog))
1387 s = "DIALOGEX";
1388 else
1389 s = "DIALOG";
1390 rt = RT_DIALOG;
1391 break;
1393 case RES_TYPE_FONT:
1394 s = "FONT";
1395 rt = RT_FONT;
1396 break;
1398 case RES_TYPE_FONTDIR:
1399 s = "FONTDIR";
1400 rt = RT_FONTDIR;
1401 break;
1403 case RES_TYPE_ICON:
1404 s = "ICON";
1405 rt = RT_ICON;
1406 break;
1408 case RES_TYPE_GROUP_ICON:
1409 s = "GROUP_ICON";
1410 rt = RT_GROUP_ICON;
1411 break;
1413 case RES_TYPE_MENU:
1414 if (extended_menu (res->u.menu))
1416 s = "MENUEX";
1417 menuex = 1;
1419 else
1421 s = "MENU";
1422 menuex = 0;
1424 rt = RT_MENU;
1425 break;
1427 case RES_TYPE_MESSAGETABLE:
1428 s = "MESSAGETABLE";
1429 rt = RT_MESSAGETABLE;
1430 break;
1432 case RES_TYPE_RCDATA:
1433 s = "RCDATA";
1434 rt = RT_RCDATA;
1435 break;
1437 case RES_TYPE_STRINGTABLE:
1438 s = "STRINGTABLE";
1439 rt = RT_STRING;
1440 break;
1442 case RES_TYPE_USERDATA:
1443 s = NULL;
1444 rt = 0;
1445 break;
1447 case RES_TYPE_VERSIONINFO:
1448 s = "VERSIONINFO";
1449 rt = RT_VERSION;
1450 break;
1453 if (rt != 0
1454 && type != NULL
1455 && (type->named || type->u.id != (unsigned long) rt))
1457 fprintf (e, "// Unexpected resource type mismatch: ");
1458 res_id_print (e, *type, 1);
1459 fprintf (e, " != %d", rt);
1462 if (res->coff_info.codepage != 0)
1463 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1464 if (res->coff_info.reserved != 0)
1465 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1467 if (name != NULL)
1468 res_id_print (e, *name, 0);
1469 else
1470 fprintf (e, "??Unknown-Name??");
1472 fprintf (e, " ");
1473 if (s != NULL)
1474 fprintf (e, "%s", s);
1475 else if (type != NULL)
1476 res_id_print (e, *type, 0);
1477 else
1478 fprintf (e, "??Unknown-Type??");
1480 if (res->res_info.memflags != 0)
1482 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1483 fprintf (e, " MOVEABLE");
1484 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1485 fprintf (e, " PURE");
1486 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1487 fprintf (e, " PRELOAD");
1488 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1489 fprintf (e, " DISCARDABLE");
1492 if (res->type == RES_TYPE_DIALOG)
1494 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1495 res->u.dialog->width, res->u.dialog->height);
1496 if (res->u.dialog->ex != NULL
1497 && res->u.dialog->ex->help != 0)
1498 fprintf (e, ", %lu", res->u.dialog->ex->help);
1501 fprintf (e, "\n");
1503 if ((res->res_info.language != 0 && res->res_info.language != *language)
1504 || res->res_info.characteristics != 0
1505 || res->res_info.version != 0)
1507 int modifiers;
1509 switch (res->type)
1511 case RES_TYPE_ACCELERATOR:
1512 case RES_TYPE_DIALOG:
1513 case RES_TYPE_MENU:
1514 case RES_TYPE_RCDATA:
1515 case RES_TYPE_STRINGTABLE:
1516 modifiers = 1;
1517 break;
1519 default:
1520 modifiers = 0;
1521 break;
1524 if (res->res_info.language != 0 && res->res_info.language != *language)
1525 fprintf (e, "%sLANGUAGE %d, %d\n",
1526 modifiers ? "// " : "",
1527 res->res_info.language & 0xff,
1528 (res->res_info.language >> 8) & 0xff);
1529 if (res->res_info.characteristics != 0)
1530 fprintf (e, "%sCHARACTERISTICS %lu\n",
1531 modifiers ? "// " : "",
1532 res->res_info.characteristics);
1533 if (res->res_info.version != 0)
1534 fprintf (e, "%sVERSION %lu\n",
1535 modifiers ? "// " : "",
1536 res->res_info.version);
1539 switch (res->type)
1541 default:
1542 abort ();
1544 case RES_TYPE_ACCELERATOR:
1545 write_rc_accelerators (e, res->u.acc);
1546 break;
1548 case RES_TYPE_CURSOR:
1549 write_rc_cursor (e, res->u.cursor);
1550 break;
1552 case RES_TYPE_GROUP_CURSOR:
1553 write_rc_group_cursor (e, res->u.group_cursor);
1554 break;
1556 case RES_TYPE_DIALOG:
1557 write_rc_dialog (e, res->u.dialog);
1558 break;
1560 case RES_TYPE_FONTDIR:
1561 write_rc_fontdir (e, res->u.fontdir);
1562 break;
1564 case RES_TYPE_GROUP_ICON:
1565 write_rc_group_icon (e, res->u.group_icon);
1566 break;
1568 case RES_TYPE_MENU:
1569 write_rc_menu (e, res->u.menu, menuex);
1570 break;
1572 case RES_TYPE_RCDATA:
1573 write_rc_rcdata (e, res->u.rcdata, 0);
1574 break;
1576 case RES_TYPE_STRINGTABLE:
1577 write_rc_stringtable (e, name, res->u.stringtable);
1578 break;
1580 case RES_TYPE_USERDATA:
1581 write_rc_rcdata (e, res->u.userdata, 0);
1582 break;
1584 case RES_TYPE_VERSIONINFO:
1585 write_rc_versioninfo (e, res->u.versioninfo);
1586 break;
1588 case RES_TYPE_BITMAP:
1589 case RES_TYPE_FONT:
1590 case RES_TYPE_ICON:
1591 case RES_TYPE_MESSAGETABLE:
1592 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1593 break;
1597 /* Write out accelerator information. */
1599 static void
1600 write_rc_accelerators (e, accelerators)
1601 FILE *e;
1602 const struct accelerator *accelerators;
1604 const struct accelerator *acc;
1606 fprintf (e, "BEGIN\n");
1607 for (acc = accelerators; acc != NULL; acc = acc->next)
1609 int printable;
1611 fprintf (e, " ");
1613 if ((acc->key & 0x7f) == acc->key
1614 && isprint ((unsigned char) acc->key)
1615 && (acc->flags & ACC_VIRTKEY) == 0)
1617 fprintf (e, "\"%c\"", acc->key);
1618 printable = 1;
1620 else
1622 fprintf (e, "%d", acc->key);
1623 printable = 0;
1626 fprintf (e, ", %d", acc->id);
1628 if (! printable)
1630 if ((acc->flags & ACC_VIRTKEY) != 0)
1631 fprintf (e, ", VIRTKEY");
1632 else
1633 fprintf (e, ", ASCII");
1636 if ((acc->flags & ACC_SHIFT) != 0)
1637 fprintf (e, ", SHIFT");
1638 if ((acc->flags & ACC_CONTROL) != 0)
1639 fprintf (e, ", CONTROL");
1640 if ((acc->flags & ACC_ALT) != 0)
1641 fprintf (e, ", ALT");
1643 fprintf (e, "\n");
1646 fprintf (e, "END\n");
1649 /* Write out cursor information. This would normally be in a separate
1650 file, which the rc file would include. */
1652 static void
1653 write_rc_cursor (e, cursor)
1654 FILE *e;
1655 const struct cursor *cursor;
1657 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1658 cursor->yhotspot);
1659 write_rc_filedata (e, cursor->length, cursor->data);
1662 /* Write out group cursor data. This would normally be built from the
1663 cursor data. */
1665 static void
1666 write_rc_group_cursor (e, group_cursor)
1667 FILE *e;
1668 const struct group_cursor *group_cursor;
1670 const struct group_cursor *gc;
1672 for (gc = group_cursor; gc != NULL; gc = gc->next)
1674 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1675 gc->width, gc->height, gc->planes, gc->bits);
1676 fprintf (e, "// data bytes: %lu; index: %d\n",
1677 gc->bytes, gc->index);
1681 /* Write dialog data. */
1683 static void
1684 write_rc_dialog (e, dialog)
1685 FILE *e;
1686 const struct dialog *dialog;
1688 const struct dialog_control *control;
1690 if (dialog->style != 0)
1691 fprintf (e, "STYLE 0x%lx\n", dialog->style);
1692 if (dialog->exstyle != 0)
1693 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1694 if ((dialog->class.named && dialog->class.u.n.length > 0)
1695 || dialog->class.u.id != 0)
1697 fprintf (e, "CLASS ");
1698 res_id_print (e, dialog->class, 0);
1699 fprintf (e, "\n");
1701 if (dialog->caption != NULL)
1703 fprintf (e, "CAPTION \"");
1704 unicode_print (e, dialog->caption, -1);
1705 fprintf (e, "\"\n");
1707 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
1708 || dialog->menu.u.id != 0)
1710 fprintf (e, "MENU ");
1711 res_id_print (e, dialog->menu, 0);
1712 fprintf (e, "\n");
1714 if (dialog->font != NULL)
1716 fprintf (e, "FONT %d, \"", dialog->pointsize);
1717 unicode_print (e, dialog->font, -1);
1718 fprintf (e, "\"");
1719 if (dialog->ex != NULL
1720 && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
1721 fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
1722 fprintf (e, "\n");
1725 fprintf (e, "BEGIN\n");
1727 for (control = dialog->controls; control != NULL; control = control->next)
1728 write_rc_dialog_control (e, control);
1730 fprintf (e, "END\n");
1733 /* For each predefined control keyword, this table provides the class
1734 and the style. */
1736 struct control_info
1738 const char *name;
1739 unsigned short class;
1740 unsigned long style;
1743 static const struct control_info control_info[] =
1745 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
1746 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
1747 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
1748 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
1749 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
1750 { "CTEXT", CTL_STATIC, SS_CENTER },
1751 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
1752 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
1753 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
1754 { "ICON", CTL_STATIC, SS_ICON },
1755 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
1756 { "LTEXT", CTL_STATIC, SS_LEFT },
1757 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
1758 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
1759 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
1760 { "RTEXT", CTL_STATIC, SS_RIGHT },
1761 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
1762 { "STATE3", CTL_BUTTON, BS_3STATE },
1763 /* It's important that USERBUTTON come after all the other button
1764 types, so that it won't be matched too early. */
1765 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
1766 { NULL, 0, 0 }
1769 /* Write a dialog control. */
1771 static void
1772 write_rc_dialog_control (e, control)
1773 FILE *e;
1774 const struct dialog_control *control;
1776 const struct control_info *ci;
1778 fprintf (e, " ");
1780 if (control->class.named)
1781 ci = NULL;
1782 else
1784 for (ci = control_info; ci->name != NULL; ++ci)
1785 if (ci->class == control->class.u.id
1786 && (ci->style == (unsigned long) -1
1787 || ci->style == (control->style & 0xff)))
1788 break;
1790 if (ci == NULL)
1791 fprintf (e, "CONTROL");
1792 else if (ci->name != NULL)
1793 fprintf (e, "%s", ci->name);
1794 else
1795 fprintf (e, "CONTROL");
1797 if (control->text.named || control->text.u.id != 0)
1799 fprintf (e, " ");
1800 res_id_print (e, control->text, 1);
1801 fprintf (e, ",");
1804 fprintf (e, " %d, ", control->id);
1806 if (ci == NULL)
1808 if (control->class.named)
1809 fprintf (e, "\"");
1810 res_id_print (e, control->class, 0);
1811 if (control->class.named)
1812 fprintf (e, "\"");
1813 fprintf (e, ", 0x%lx, ", control->style);
1816 fprintf (e, "%d, %d", control->x, control->y);
1818 if (control->style != SS_ICON
1819 || control->exstyle != 0
1820 || control->width != 0
1821 || control->height != 0
1822 || control->help != 0)
1824 fprintf (e, ", %d, %d", control->width, control->height);
1826 /* FIXME: We don't need to print the style if it is the default.
1827 More importantly, in certain cases we actually need to turn
1828 off parts of the forced style, by using NOT. */
1829 fprintf (e, ", 0x%lx", control->style);
1831 if (control->exstyle != 0 || control->help != 0)
1832 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1835 fprintf (e, "\n");
1837 if (control->data != NULL)
1838 write_rc_rcdata (e, control->data, 2);
1841 /* Write out font directory data. This would normally be built from
1842 the font data. */
1844 static void
1845 write_rc_fontdir (e, fontdir)
1846 FILE *e;
1847 const struct fontdir *fontdir;
1849 const struct fontdir *fc;
1851 for (fc = fontdir; fc != NULL; fc = fc->next)
1853 fprintf (e, "// Font index: %d\n", fc->index);
1854 write_rc_filedata (e, fc->length, fc->data);
1858 /* Write out group icon data. This would normally be built from the
1859 icon data. */
1861 static void
1862 write_rc_group_icon (e, group_icon)
1863 FILE *e;
1864 const struct group_icon *group_icon;
1866 const struct group_icon *gi;
1868 for (gi = group_icon; gi != NULL; gi = gi->next)
1870 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1871 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
1872 fprintf (e, "// data bytes: %lu; index: %d\n",
1873 gi->bytes, gi->index);
1877 /* Write out a menu resource. */
1879 static void
1880 write_rc_menu (e, menu, menuex)
1881 FILE *e;
1882 const struct menu *menu;
1883 int menuex;
1885 if (menu->help != 0)
1886 fprintf (e, "// Help ID: %lu\n", menu->help);
1887 write_rc_menuitems (e, menu->items, menuex, 0);
1890 /* Write out menuitems. */
1892 static void
1893 write_rc_menuitems (e, menuitems, menuex, ind)
1894 FILE *e;
1895 const struct menuitem *menuitems;
1896 int menuex;
1897 int ind;
1899 const struct menuitem *mi;
1901 indent (e, ind);
1902 fprintf (e, "BEGIN\n");
1904 for (mi = menuitems; mi != NULL; mi = mi->next)
1906 indent (e, ind + 2);
1908 if (mi->popup == NULL)
1909 fprintf (e, "MENUITEM");
1910 else
1911 fprintf (e, "POPUP");
1913 if (! menuex
1914 && mi->popup == NULL
1915 && mi->text == NULL
1916 && mi->type == 0
1917 && mi->id == 0)
1919 fprintf (e, " SEPARATOR\n");
1920 continue;
1923 if (mi->text == NULL)
1924 fprintf (e, " \"\"");
1925 else
1927 fprintf (e, " \"");
1928 unicode_print (e, mi->text, -1);
1929 fprintf (e, "\"");
1932 if (! menuex)
1934 if (mi->popup == NULL)
1935 fprintf (e, ", %d", mi->id);
1937 if ((mi->type & MENUITEM_CHECKED) != 0)
1938 fprintf (e, ", CHECKED");
1939 if ((mi->type & MENUITEM_GRAYED) != 0)
1940 fprintf (e, ", GRAYED");
1941 if ((mi->type & MENUITEM_HELP) != 0)
1942 fprintf (e, ", HELP");
1943 if ((mi->type & MENUITEM_INACTIVE) != 0)
1944 fprintf (e, ", INACTIVE");
1945 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
1946 fprintf (e, ", MENUBARBREAK");
1947 if ((mi->type & MENUITEM_MENUBREAK) != 0)
1948 fprintf (e, ", MENUBREAK");
1950 else
1952 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
1954 fprintf (e, ", %d", mi->id);
1955 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
1957 fprintf (e, ", %lu", mi->type);
1958 if (mi->state != 0 || mi->help != 0)
1960 fprintf (e, ", %lu", mi->state);
1961 if (mi->help != 0)
1962 fprintf (e, ", %lu", mi->help);
1968 fprintf (e, "\n");
1970 if (mi->popup != NULL)
1971 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
1974 indent (e, ind);
1975 fprintf (e, "END\n");
1978 /* Write out an rcdata resource. This is also used for other types of
1979 resources that need to print arbitrary data. */
1981 static void
1982 write_rc_rcdata (e, rcdata, ind)
1983 FILE *e;
1984 const struct rcdata_item *rcdata;
1985 int ind;
1987 const struct rcdata_item *ri;
1989 indent (e, ind);
1990 fprintf (e, "BEGIN\n");
1992 for (ri = rcdata; ri != NULL; ri = ri->next)
1994 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
1995 continue;
1997 indent (e, ind + 2);
1999 switch (ri->type)
2001 default:
2002 abort ();
2004 case RCDATA_WORD:
2005 fprintf (e, "%d", ri->u.word);
2006 break;
2008 case RCDATA_DWORD:
2009 fprintf (e, "%luL", ri->u.dword);
2010 break;
2012 case RCDATA_STRING:
2014 const char *s;
2015 unsigned long i;
2017 fprintf (e, "\"");
2018 s = ri->u.string.s;
2019 for (i = 0; i < ri->u.string.length; i++)
2021 if (isprint ((unsigned char) *s))
2022 putc (*s, e);
2023 else
2024 fprintf (e, "\\%03o", *s);
2026 fprintf (e, "\"");
2027 break;
2030 case RCDATA_WSTRING:
2031 fprintf (e, "L\"");
2032 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2033 fprintf (e, "\"");
2034 break;
2036 case RCDATA_BUFFER:
2038 unsigned long i;
2039 int first;
2041 /* Assume little endian data. */
2043 first = 1;
2044 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2046 unsigned long l;
2048 l = ((((((ri->u.buffer.data[i + 3] << 8)
2049 | ri->u.buffer.data[i + 2]) << 8)
2050 | ri->u.buffer.data[i + 1]) << 8)
2051 | ri->u.buffer.data[i]);
2052 if (first)
2053 first = 0;
2054 else
2056 fprintf (e, ",\n");
2057 indent (e, ind + 2);
2059 fprintf (e, "%luL", l);
2062 if (i + 1 < ri->u.buffer.length)
2064 int i;
2066 i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2067 if (first)
2068 first = 0;
2069 else
2071 fprintf (e, ",\n");
2072 indent (e, ind + 2);
2074 fprintf (e, "%d", i);
2075 i += 2;
2078 if (i < ri->u.buffer.length)
2080 if (first)
2081 first = 0;
2082 else
2084 fprintf (e, ",\n");
2085 indent (e, ind + 2);
2087 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2088 && isprint (ri->u.buffer.data[i]))
2089 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2090 else
2091 fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
2094 break;
2098 if (ri->next != NULL)
2099 fprintf (e, ",");
2100 fprintf (e, "\n");
2103 indent (e, ind);
2104 fprintf (e, "END\n");
2107 /* Write out a stringtable resource. */
2109 static void
2110 write_rc_stringtable (e, name, stringtable)
2111 FILE *e;
2112 const struct res_id *name;
2113 const struct stringtable *stringtable;
2115 unsigned long offset;
2116 int i;
2118 if (name != NULL && ! name->named)
2119 offset = (name->u.id - 1) << 4;
2120 else
2122 fprintf (e, "// %s string table name\n",
2123 name == NULL ? "Missing" : "Invalid");
2124 offset = 0;
2127 fprintf (e, "BEGIN\n");
2129 for (i = 0; i < 16; i++)
2131 if (stringtable->strings[i].length != 0)
2133 fprintf (e, " %lu, \"", offset + i);
2134 unicode_print (e, stringtable->strings[i].string,
2135 stringtable->strings[i].length);
2136 fprintf (e, "\"\n");
2140 fprintf (e, "END\n");
2143 /* Write out a versioninfo resource. */
2145 static void
2146 write_rc_versioninfo (e, versioninfo)
2147 FILE *e;
2148 const struct versioninfo *versioninfo;
2150 const struct fixed_versioninfo *f;
2151 const struct ver_info *vi;
2153 f = versioninfo->fixed;
2154 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2155 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2156 (f->file_version_ms >> 16) & 0xffff,
2157 f->file_version_ms & 0xffff,
2158 (f->file_version_ls >> 16) & 0xffff,
2159 f->file_version_ls & 0xffff);
2160 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2161 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2162 (f->product_version_ms >> 16) & 0xffff,
2163 f->product_version_ms & 0xffff,
2164 (f->product_version_ls >> 16) & 0xffff,
2165 f->product_version_ls & 0xffff);
2166 if (f->file_flags_mask != 0)
2167 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2168 if (f->file_flags != 0)
2169 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2170 if (f->file_os != 0)
2171 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2172 if (f->file_type != 0)
2173 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2174 if (f->file_subtype != 0)
2175 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2176 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2177 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2179 fprintf (e, "BEGIN\n");
2181 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2183 switch (vi->type)
2185 case VERINFO_STRING:
2187 const struct ver_stringinfo *vs;
2189 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2190 fprintf (e, " BEGIN\n");
2191 fprintf (e, " BLOCK \"");
2192 unicode_print (e, vi->u.string.language, -1);
2193 fprintf (e, "\"\n");
2194 fprintf (e, " BEGIN\n");
2196 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2198 fprintf (e, " VALUE \"");
2199 unicode_print (e, vs->key, -1);
2200 fprintf (e, "\", \"");
2201 unicode_print (e, vs->value, -1);
2202 fprintf (e, "\"\n");
2205 fprintf (e, " END\n");
2206 fprintf (e, " END\n");
2207 break;
2210 case VERINFO_VAR:
2212 const struct ver_varinfo *vv;
2214 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2215 fprintf (e, " BEGIN\n");
2216 fprintf (e, " VALUE \"");
2217 unicode_print (e, vi->u.var.key, -1);
2218 fprintf (e, "\"");
2220 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2221 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2222 vv->charset);
2224 fprintf (e, "\n END\n");
2226 break;
2231 fprintf (e, "END\n");
2234 /* Write out data which would normally be read from a file. */
2236 static void
2237 write_rc_filedata (e, length, data)
2238 FILE *e;
2239 unsigned long length;
2240 const unsigned char *data;
2242 unsigned long i;
2244 for (i = 0; i + 15 < length; i += 16)
2246 fprintf (e, "// %4lx: ", i);
2247 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2248 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2249 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2250 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2251 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2252 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2255 if (i < length)
2257 fprintf (e, "// %4lx:", i);
2258 while (i < length)
2260 fprintf (e, " %02x", data[i]);
2261 ++i;
2263 fprintf (e, "\n");