This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / binutils / resrc.c
1 /* resrc.c -- read and write Windows rc files.
2    Copyright 1997 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Cygnus Support.
4
5    This file is part of GNU Binutils.
6
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.
11
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.
16
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.  */
21
22 /* This file contains function that read and write Windows rc files.
23    These are text files that represent resources.  */
24
25 #include "bfd.h"
26 #include "bucomm.h"
27 #include "libiberty.h"
28 #include "windres.h"
29
30 #include <assert.h>
31 #include <ctype.h>
32 #include <sys/stat.h>
33
34 /* The default preprocessor.  */
35
36 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
37
38 /* We read the directory entries in a cursor or icon file into
39    instances of this structure.  */
40
41 struct icondir
42 {
43   /* Width of image.  */
44   unsigned char width;
45   /* Height of image.  */
46   unsigned char height;
47   /* Number of colors in image.  */
48   unsigned char colorcount;
49   union
50   {
51     struct
52     {
53       /* Color planes.  */
54       unsigned short planes;
55       /* Bits per pixel.  */
56       unsigned short bits;
57     } icon;
58     struct
59     {
60       /* X coordinate of hotspot.  */
61       unsigned short xhotspot;
62       /* Y coordinate of hotspot.  */
63       unsigned short yhotspot;
64     } cursor;
65   } u;
66   /* Bytes in image.  */
67   unsigned long bytes;
68   /* File offset of image.  */
69   unsigned long offset;
70 };
71
72 /* The name of the rc file we are reading.  */
73
74 char *rc_filename;
75
76 /* The line number in the rc file.  */
77
78 int rc_lineno;
79
80 /* The pipe we are reading from, so that we can close it if we exit.  */
81
82 static FILE *cpp_pipe;
83
84 /* As we read the rc file, we attach information to this structure.  */
85
86 static struct res_directory *resources;
87
88 /* The number of cursor resources we have written out.  */
89
90 static int cursors;
91
92 /* The number of font resources we have written out.  */
93
94 static int fonts;
95
96 /* Font directory information.  */
97
98 struct fontdir *fontdirs;
99
100 /* Resource info to use for fontdirs.  */
101
102 struct res_res_info fontdirs_resinfo;
103
104 /* The number of icon resources we have written out.  */
105
106 static int icons;
107
108 /* Local functions.  */
109
110 static void close_pipe PARAMS ((void));
111 static void unexpected_eof PARAMS ((const char *));
112 static int get_word PARAMS ((FILE *, const char *));
113 static unsigned long get_long PARAMS ((FILE *, const char *));
114 static void get_data
115   PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
116 static void define_fontdirs PARAMS ((void));
117 \f
118 /* Read an rc file.  */
119
120 struct res_directory *
121 read_rc_file (filename, preprocessor, preprocargs, language)
122      const char *filename;
123      const char *preprocessor;
124      const char *preprocargs;
125      int language;
126 {
127   char *cmd;
128
129   if (preprocessor == NULL)
130     preprocessor = DEFAULT_PREPROCESSOR;
131
132   if (preprocargs == NULL)
133     preprocargs = "";
134   if (filename == NULL)
135     filename = "-";
136
137   cmd = xmalloc (strlen (preprocessor)
138                  + strlen (preprocargs)
139                  + strlen (filename)
140                  + 10);
141   sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
142
143   cpp_pipe = popen (cmd, FOPEN_RT);
144   if (cpp_pipe == NULL)
145     fatal ("can't popen `%s': %s", cmd, strerror (errno));
146   free (cmd);
147
148   xatexit (close_pipe);
149
150   rc_filename = xstrdup (filename);
151   rc_lineno = 1;
152   if (language != -1)
153     rcparse_set_language (language);
154   yyin = cpp_pipe;
155   yyparse ();
156
157   if (pclose (cpp_pipe) != 0)
158     fprintf (stderr, "%s: warning: preprocessor failed\n", program_name);
159   cpp_pipe = NULL;
160
161   if (fontdirs != NULL)
162     define_fontdirs ();
163
164   free (rc_filename);
165   rc_filename = NULL;
166
167   return resources;
168 }
169
170 /* Close the pipe if it is open.  This is called via xatexit.  */
171
172 void
173 close_pipe ()
174 {
175   if (cpp_pipe != NULL)
176     pclose (cpp_pipe);
177 }
178
179 /* Report an error while reading an rc file.  */
180
181 void
182 yyerror (msg)
183      const char *msg;
184 {
185   fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
186 }
187
188 /* Issue a warning while reading an rc file.  */
189
190 void
191 rcparse_warning (msg)
192      const char *msg;
193 {
194   fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
195 }
196
197 /* Die if we get an unexpected end of file.  */
198
199 static void
200 unexpected_eof (msg)
201      const char *msg;
202 {
203   fatal ("%s: unexpected EOF", msg);
204 }
205
206 /* Read a 16 bit word from a file.  The data is assumed to be little
207    endian.  */
208
209 static int
210 get_word (e, msg)
211      FILE *e;
212      const char *msg;
213 {
214   int b1, b2;
215
216   b1 = getc (e);
217   b2 = getc (e);
218   if (feof (e))
219     unexpected_eof (msg);
220   return ((b2 & 0xff) << 8) | (b1 & 0xff);
221 }
222
223 /* Read a 32 bit word from a file.  The data is assumed to be little
224    endian.  */
225
226 static unsigned long
227 get_long (e, msg)
228      FILE *e;
229      const char *msg;
230 {
231   int b1, b2, b3, b4;
232
233   b1 = getc (e);
234   b2 = getc (e);
235   b3 = getc (e);
236   b4 = getc (e);
237   if (feof (e))
238     unexpected_eof (msg);
239   return (((((((b4 & 0xff) << 8)
240               | (b3 & 0xff)) << 8)
241             | (b2 & 0xff)) << 8)
242           | (b1 & 0xff));
243 }
244
245 /* Read data from a file.  This is a wrapper to do error checking.  */
246
247 static void
248 get_data (e, p, c, msg)
249      FILE *e;
250      unsigned char *p;
251      unsigned long c;
252      const char *msg;
253 {
254   unsigned long got;
255
256   got = fread (p, 1, c, e);
257   if (got == c)
258     return;
259
260   fatal ("%s: read of %lu returned %lu", msg, c, got);
261 }
262 \f
263 /* Define an accelerator resource.  */
264
265 void
266 define_accelerator (id, resinfo, data)
267      struct res_id id;
268      const struct res_res_info *resinfo;
269      struct accelerator *data;
270 {
271   struct res_resource *r;
272
273   r = define_standard_resource (&resources, RT_ACCELERATORS, id,
274                                 resinfo->language, 0);
275   r->type = RES_TYPE_ACCELERATOR;
276   r->u.acc = data;
277   r->res_info = *resinfo;
278 }
279
280 /* Define a bitmap resource.  Bitmap data is stored in a file.  The
281    first 14 bytes of the file are a standard header, which is not
282    included in the resource data.  */
283
284 #define BITMAP_SKIP (14)
285
286 void
287 define_bitmap (id, resinfo, filename)
288      struct res_id id;
289      const struct res_res_info *resinfo;
290      const char *filename;
291 {
292   FILE *e;
293   char *real_filename;
294   struct stat s;
295   unsigned char *data;
296   int i;
297   struct res_resource *r;
298
299   e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
300
301   if (stat (real_filename, &s) < 0)
302     fatal ("stat failed on bitmap file `%s': %s", real_filename,
303            strerror (errno));
304
305   data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
306
307   for (i = 0; i < BITMAP_SKIP; i++)
308     getc (e);
309
310   get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
311
312   fclose (e);
313   free (real_filename);
314
315   r = define_standard_resource (&resources, RT_BITMAP, id,
316                                 resinfo->language, 0);
317
318   r->type = RES_TYPE_BITMAP;
319   r->u.data.length = s.st_size - BITMAP_SKIP;
320   r->u.data.data = data;
321   r->res_info = *resinfo;
322 }
323
324 /* Define a cursor resource.  A cursor file may contain a set of
325    bitmaps, each representing the same cursor at various different
326    resolutions.  They each get written out with a different ID.  The
327    real cursor resource is then a group resource which can be used to
328    select one of the actual cursors.  */
329
330 void
331 define_cursor (id, resinfo, filename)
332      struct res_id id;
333      const struct res_res_info *resinfo;
334      const char *filename;
335 {
336   FILE *e;
337   char *real_filename;
338   int type, count, i;
339   struct icondir *icondirs;
340   int first_cursor;
341   struct res_resource *r;
342   struct group_cursor *first, **pp;
343
344   e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
345
346   /* A cursor file is basically an icon file.  The start of the file
347      is a three word structure.  The first word is ignored.  The
348      second word is the type of data.  The third word is the number of
349      entries.  */
350
351   get_word (e, real_filename);
352   type = get_word (e, real_filename);
353   count = get_word (e, real_filename);
354   if (type != 2)
355     fatal ("cursor file `%s' does not contain cursor data", real_filename);
356
357   /* Read in the icon directory entries.  */
358
359   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
360
361   for (i = 0; i < count; i++)
362     {
363       icondirs[i].width = getc (e);
364       icondirs[i].height = getc (e);
365       icondirs[i].colorcount = getc (e);
366       getc (e);
367       icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
368       icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
369       icondirs[i].bytes = get_long (e, real_filename);
370       icondirs[i].offset = get_long (e, real_filename);
371
372       if (feof (e))
373         unexpected_eof (real_filename);
374     }
375
376   /* Define each cursor as a unique resource.  */
377
378   first_cursor = cursors;
379
380   for (i = 0; i < count; i++)
381     {
382       unsigned char *data;
383       struct res_id name;
384       struct cursor *c;
385
386       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
387         fatal ("%s: fseek to %lu failed: %s", real_filename,
388                icondirs[i].offset, strerror (errno));
389
390       data = (unsigned char *) res_alloc (icondirs[i].bytes);
391
392       get_data (e, data, icondirs[i].bytes, real_filename);
393
394       c = (struct cursor *) res_alloc (sizeof *c);
395       c->xhotspot = icondirs[i].u.cursor.xhotspot;
396       c->yhotspot = icondirs[i].u.cursor.yhotspot;
397       c->length = icondirs[i].bytes;
398       c->data = data;
399
400       ++cursors;
401
402       name.named = 0;
403       name.u.id = cursors;
404
405       r = define_standard_resource (&resources, RT_CURSOR, name,
406                                     resinfo->language, 0);
407       r->type = RES_TYPE_CURSOR;
408       r->u.cursor = c;
409       r->res_info = *resinfo;
410     }
411
412   fclose (e);
413   free (real_filename);
414
415   /* Define a cursor group resource.  */
416
417   first = NULL;
418   pp = &first;
419   for (i = 0; i < count; i++)
420     {
421       struct group_cursor *cg;
422
423       cg = (struct group_cursor *) res_alloc (sizeof *cg);
424       cg->next = NULL;
425       cg->width = icondirs[i].width;
426       cg->height = 2 * icondirs[i].height;
427
428       /* FIXME: What should these be set to?  */
429       cg->planes = 1;
430       cg->bits = 1;
431
432       cg->bytes = icondirs[i].bytes + 4;
433       cg->index = first_cursor + i + 1;
434
435       *pp = cg;
436       pp = &(*pp)->next;
437     }
438
439   free (icondirs);
440
441   r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
442                                 resinfo->language, 0);
443   r->type = RES_TYPE_GROUP_CURSOR;
444   r->u.group_cursor = first;
445   r->res_info = *resinfo;
446 }
447
448 /* Define a dialog resource.  */
449
450 void
451 define_dialog (id, resinfo, dialog)
452      struct res_id id;
453      const struct res_res_info *resinfo;
454      const struct dialog *dialog;
455 {
456   struct dialog *copy;
457   struct res_resource *r;
458
459   copy = (struct dialog *) res_alloc (sizeof *copy);
460   *copy = *dialog;
461
462   r = define_standard_resource (&resources, RT_DIALOG, id,
463                                 resinfo->language, 0);
464   r->type = RES_TYPE_DIALOG;
465   r->u.dialog = copy;
466   r->res_info = *resinfo;
467 }
468
469 /* Define a dialog control.  This does not define a resource, but
470    merely allocates and fills in a structure.  */
471
472 struct dialog_control *
473 define_control (text, id, x, y, width, height, class, style, exstyle)
474      const char *text;
475      unsigned long id;
476      unsigned long x;
477      unsigned long y;
478      unsigned long width;
479      unsigned long height;
480      unsigned long class;
481      unsigned long style;
482      unsigned long exstyle;
483 {
484   struct dialog_control *n;
485
486   n = (struct dialog_control *) res_alloc (sizeof *n);
487   n->next = NULL;
488   n->id = id;
489   n->style = style;
490   n->exstyle = exstyle;
491   n->x = x;
492   n->y = y;
493   n->width = width;
494   n->height = height;
495   n->class.named = 0;
496   n->class.u.id = class;
497   if (text != NULL)
498     res_string_to_id (&n->text, text);
499   else
500     {
501       n->text.named = 0;
502       n->text.u.id = 0;
503     }
504   n->data = NULL;
505   n->help = 0;
506
507   return n;
508 }
509
510 /* Define a font resource.  */
511
512 void
513 define_font (id, resinfo, filename)
514      struct res_id id;
515      const struct res_res_info *resinfo;
516      const char *filename;
517 {
518   FILE *e;
519   char *real_filename;
520   struct stat s;
521   unsigned char *data;
522   struct res_resource *r;
523   long offset;
524   long fontdatalength;
525   unsigned char *fontdata;
526   struct fontdir *fd;
527   const char *device, *face;
528   struct fontdir **pp;
529
530   e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
531
532   if (stat (real_filename, &s) < 0)
533     fatal ("stat failed on bitmap file `%s': %s", real_filename,
534            strerror (errno));
535
536   data = (unsigned char *) res_alloc (s.st_size);
537
538   get_data (e, data, s.st_size, real_filename);
539
540   fclose (e);
541   free (real_filename);
542
543   r = define_standard_resource (&resources, RT_FONT, id,
544                                 resinfo->language, 0);
545
546   r->type = RES_TYPE_FONT;
547   r->u.data.length = s.st_size;
548   r->u.data.data = data;
549   r->res_info = *resinfo;
550
551   /* For each font resource, we must add an entry in the FONTDIR
552      resource.  The FONTDIR resource includes some strings in the font
553      file.  To find them, we have to do some magic on the data we have
554      read.  */
555
556   offset = ((((((data[47] << 8)
557                 | data[46]) << 8)
558               | data[45]) << 8)
559             | data[44]);
560   if (offset > 0 && offset < s.st_size)
561     device = (char *) data + offset;
562   else
563     device = "";
564
565   offset = ((((((data[51] << 8)
566                 | data[50]) << 8)
567               | data[49]) << 8)
568             | data[48]);
569   if (offset > 0 && offset < s.st_size)
570     face = (char *) data + offset;
571   else
572     face = "";
573
574   ++fonts;
575
576   fontdatalength = 58 + strlen (device) + strlen (face);
577   fontdata = (unsigned char *) res_alloc (fontdatalength);
578   memcpy (fontdata, data, 56);
579   strcpy ((char *) fontdata + 56, device);
580   strcpy ((char *) fontdata + 57 + strlen (device), face);
581
582   fd = (struct fontdir *) res_alloc (sizeof *fd);
583   fd->next = NULL;
584   fd->index = fonts;
585   fd->length = fontdatalength;
586   fd->data = fontdata;
587
588   for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
589     ;
590   *pp = fd;
591
592   /* For the single fontdirs resource, we always use the resource
593      information of the last font.  I don't know what else to do.  */
594   fontdirs_resinfo = *resinfo;
595 }
596
597 /* Define the fontdirs resource.  This is called after the entire rc
598    file has been parsed, if any font resources were seen.  */
599
600 static void
601 define_fontdirs ()
602 {
603   struct res_resource *r;
604   struct res_id id;
605
606   id.named = 0;
607   id.u.id = 1;
608
609   r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
610
611   r->type = RES_TYPE_FONTDIR;
612   r->u.fontdir = fontdirs;
613   r->res_info = fontdirs_resinfo;
614 }
615
616 /* Define an icon resource.  An icon file may contain a set of
617    bitmaps, each representing the same icon at various different
618    resolutions.  They each get written out with a different ID.  The
619    real icon resource is then a group resource which can be used to
620    select one of the actual icon bitmaps.  */
621
622 void
623 define_icon (id, resinfo, filename)
624      struct res_id id;
625      const struct res_res_info *resinfo;
626      const char *filename;
627 {
628   FILE *e;
629   char *real_filename;
630   int type, count, i;
631   struct icondir *icondirs;
632   int first_icon;
633   struct res_resource *r;
634   struct group_icon *first, **pp;
635
636   e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
637
638   /* The start of an icon file is a three word structure.  The first
639      word is ignored.  The second word is the type of data.  The third
640      word is the number of entries.  */
641
642   get_word (e, real_filename);
643   type = get_word (e, real_filename);
644   count = get_word (e, real_filename);
645   if (type != 1)
646     fatal ("icon file `%s' does not contain icon data", real_filename);
647
648   /* Read in the icon directory entries.  */
649
650   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
651
652   for (i = 0; i < count; i++)
653     {
654       icondirs[i].width = getc (e);
655       icondirs[i].height = getc (e);
656       icondirs[i].colorcount = getc (e);
657       getc (e);
658       icondirs[i].u.icon.planes = get_word (e, real_filename);
659       icondirs[i].u.icon.bits = get_word (e, real_filename);
660       icondirs[i].bytes = get_long (e, real_filename);
661       icondirs[i].offset = get_long (e, real_filename);
662
663       if (feof (e))
664         unexpected_eof (real_filename);
665     }
666
667   /* Define each icon as a unique resource.  */
668
669   first_icon = icons;
670
671   for (i = 0; i < count; i++)
672     {
673       unsigned char *data;
674       struct res_id name;
675
676       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
677         fatal ("%s: fseek to %lu failed: %s", real_filename,
678                icondirs[i].offset, strerror (errno));
679
680       data = (unsigned char *) res_alloc (icondirs[i].bytes);
681
682       get_data (e, data, icondirs[i].bytes, real_filename);
683
684       ++icons;
685
686       name.named = 0;
687       name.u.id = icons;
688
689       r = define_standard_resource (&resources, RT_ICON, name,
690                                     resinfo->language, 0);
691       r->type = RES_TYPE_ICON;
692       r->u.data.length = icondirs[i].bytes;
693       r->u.data.data = data;
694       r->res_info = *resinfo;
695     }
696
697   fclose (e);
698   free (real_filename);
699
700   /* Define an icon group resource.  */
701
702   first = NULL;
703   pp = &first;
704   for (i = 0; i < count; i++)
705     {
706       struct group_icon *cg;
707
708       /* For some reason, at least in some files the planes and bits
709          are zero.  We instead set them from the color.  This is
710          copied from rcl.  */
711
712       cg = (struct group_icon *) res_alloc (sizeof *cg);
713       cg->next = NULL;
714       cg->width = icondirs[i].width;
715       cg->height = icondirs[i].height;
716       cg->colors = icondirs[i].colorcount;
717
718       cg->planes = 1;
719       cg->bits = 0;
720       while ((1 << cg->bits) < cg->colors)
721         ++cg->bits;
722
723       cg->bytes = icondirs[i].bytes;
724       cg->index = first_icon + i + 1;
725
726       *pp = cg;
727       pp = &(*pp)->next;
728     }
729
730   free (icondirs);
731
732   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
733                                 resinfo->language, 0);
734   r->type = RES_TYPE_GROUP_ICON;
735   r->u.group_icon = first;
736   r->res_info = *resinfo;
737 }
738
739 /* Define a menu resource.  */
740
741 void
742 define_menu (id, resinfo, menuitems)
743      struct res_id id;
744      const struct res_res_info *resinfo;
745      struct menuitem *menuitems;
746 {
747   struct menu *m;
748   struct res_resource *r;
749
750   m = (struct menu *) res_alloc (sizeof *m);
751   m->items = menuitems;
752   m->help = 0;
753
754   r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
755   r->type = RES_TYPE_MENU;
756   r->u.menu = m;
757   r->res_info = *resinfo;
758 }
759
760 /* Define a menu item.  This does not define a resource, but merely
761    allocates and fills in a structure.  */
762
763 struct menuitem *
764 define_menuitem (text, menuid, type, state, help, menuitems)
765      const char *text;
766      int menuid;
767      unsigned long type;
768      unsigned long state;
769      unsigned long help;
770      struct menuitem *menuitems;
771 {
772   struct menuitem *mi;
773
774   mi = (struct menuitem *) res_alloc (sizeof *mi);
775   mi->next = NULL;
776   mi->type = type;
777   mi->state = state;
778   mi->id = menuid;
779   if (text == NULL)
780     mi->text = NULL;
781   else
782     unicode_from_ascii ((int *) NULL, &mi->text, text);
783   mi->help = help;
784   mi->popup = menuitems;
785   return mi;
786 }
787
788 /* Define a messagetable resource.  */
789
790 void
791 define_messagetable (id, resinfo, filename)
792      struct res_id id;
793      const struct res_res_info *resinfo;
794      const char *filename;
795 {
796   FILE *e;
797   char *real_filename;
798   struct stat s;
799   unsigned char *data;
800   struct res_resource *r;
801
802   e = open_file_search (filename, FOPEN_RB, "messagetable file",
803                         &real_filename);
804
805   if (stat (real_filename, &s) < 0)
806     fatal ("stat failed on bitmap file `%s': %s", real_filename,
807            strerror (errno));
808
809   data = (unsigned char *) res_alloc (s.st_size);
810
811   get_data (e, data, s.st_size, real_filename);
812
813   fclose (e);
814   free (real_filename);
815
816   r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
817                                 resinfo->language, 0);
818
819   r->type = RES_TYPE_MESSAGETABLE;
820   r->u.data.length = s.st_size;
821   r->u.data.data = data;
822   r->res_info = *resinfo;
823 }
824
825 /* Define an rcdata resource.  */
826
827 void
828 define_rcdata (id, resinfo, data)
829      struct res_id id;
830      const struct res_res_info *resinfo;
831      struct rcdata_item *data;
832 {
833   struct res_resource *r;
834
835   r = define_standard_resource (&resources, RT_RCDATA, id,
836                                 resinfo->language, 0);
837   r->type = RES_TYPE_RCDATA;
838   r->u.rcdata = data;
839   r->res_info = *resinfo;
840 }
841
842 /* Create an rcdata item holding a string.  */
843
844 struct rcdata_item *
845 define_rcdata_string (string, len)
846      const char *string;
847      unsigned long len;
848 {
849   struct rcdata_item *ri;
850   char *s;
851
852   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
853   ri->next = NULL;
854   ri->type = RCDATA_STRING;
855   ri->u.string.length = len;
856   s = (char *) res_alloc (len);
857   memcpy (s, string, len);
858   ri->u.string.s = s;
859
860   return ri;
861 }
862
863 /* Create an rcdata item holding a number.  */
864
865 struct rcdata_item *
866 define_rcdata_number (val, dword)
867      unsigned long val;
868      int dword;
869 {
870   struct rcdata_item *ri;
871
872   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
873   ri->next = NULL;
874   ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
875   ri->u.word = val;
876
877   return ri;
878 }
879
880 /* Define a stringtable resource.  This is called for each string
881    which appears in a STRINGTABLE statement.  */
882
883 void
884 define_stringtable (resinfo, stringid, string)
885      const struct res_res_info *resinfo;
886      unsigned long stringid;
887      const char *string;
888 {
889   struct res_id id;
890   struct res_resource *r;
891
892   id.named = 0;
893   id.u.id = stringid >> 4;
894   r = define_standard_resource (&resources, RT_STRING, id,
895                                 resinfo->language, 1);
896
897   if (r->type == RES_TYPE_UNINITIALIZED)
898     {
899       int i;
900
901       r->type = RES_TYPE_STRINGTABLE;
902       r->u.stringtable = ((struct stringtable *)
903                           res_alloc (sizeof (struct stringtable)));
904       for (i = 0; i < 16; i++)
905         {
906           r->u.stringtable->strings[i].length = 0;
907           r->u.stringtable->strings[i].string = NULL;
908         }
909
910       r->res_info = *resinfo;
911     }
912
913   unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
914                       &r->u.stringtable->strings[stringid & 0xf].string,
915                       string);
916 }
917
918 /* Define a user data resource where the data is in the rc file.  */
919
920 void
921 define_user_data (id, type, resinfo, data)
922      struct res_id id;
923      struct res_id type;
924      const struct res_res_info *resinfo;
925      struct rcdata_item *data;
926 {
927   struct res_id ids[3];
928   struct res_resource *r;
929
930   ids[0] = type;
931   ids[1] = id;
932   ids[2].named = 0;
933   ids[2].u.id = resinfo->language;
934
935   r = define_resource (&resources, 3, ids, 0);
936   r->type = RES_TYPE_USERDATA;
937   r->u.userdata = data;
938   r->res_info = *resinfo;
939 }
940
941 /* Define a user data resource where the data is in a file.  */
942
943 void
944 define_user_file (id, type, resinfo, filename)
945      struct res_id id;
946      struct res_id type;
947      const struct res_res_info *resinfo;
948      const char *filename;
949 {
950   FILE *e;
951   char *real_filename;
952   struct stat s;
953   unsigned char *data;
954   struct res_id ids[3];
955   struct res_resource *r;
956
957   e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
958
959   if (stat (real_filename, &s) < 0)
960     fatal ("stat failed on bitmap file `%s': %s", real_filename,
961            strerror (errno));
962
963   data = (unsigned char *) res_alloc (s.st_size);
964
965   get_data (e, data, s.st_size, real_filename);
966
967   fclose (e);
968   free (real_filename);
969
970   ids[0] = type;
971   ids[1] = id;
972   ids[2].named = 0;
973   ids[2].u.id = resinfo->language;
974
975   r = define_resource (&resources, 3, ids, 0);
976   r->type = RES_TYPE_USERDATA;
977   r->u.userdata = ((struct rcdata_item *)
978                    res_alloc (sizeof (struct rcdata_item)));
979   r->u.userdata->next = NULL;
980   r->u.userdata->type = RCDATA_BUFFER;
981   r->u.userdata->u.buffer.length = s.st_size;
982   r->u.userdata->u.buffer.data = data;
983   r->res_info = *resinfo;
984 }
985
986 /* Define a versioninfo resource.  */
987
988 void
989 define_versioninfo (id, language, fixedverinfo, verinfo)
990      struct res_id id;
991      int language;
992      struct fixed_versioninfo *fixedverinfo;
993      struct ver_info *verinfo;
994 {
995   struct res_resource *r;
996
997   r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
998   r->type = RES_TYPE_VERSIONINFO;
999   r->u.versioninfo = ((struct versioninfo *)
1000                       res_alloc (sizeof (struct versioninfo)));
1001   r->u.versioninfo->fixed = fixedverinfo;
1002   r->u.versioninfo->var = verinfo;
1003   r->res_info.language = language;
1004 }
1005
1006 /* Add string version info to a list of version information.  */
1007
1008 struct ver_info *
1009 append_ver_stringfileinfo (verinfo, language, strings)
1010      struct ver_info *verinfo;
1011      const char *language;
1012      struct ver_stringinfo *strings;
1013 {
1014   struct ver_info *vi, **pp;
1015
1016   vi = (struct ver_info *) res_alloc (sizeof *vi);
1017   vi->next = NULL;
1018   vi->type = VERINFO_STRING;
1019   unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1020   vi->u.string.strings = strings;
1021
1022   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1023     ;
1024   *pp = vi;
1025
1026   return verinfo;
1027 }
1028
1029 /* Add variable version info to a list of version information.  */
1030
1031 struct ver_info *
1032 append_ver_varfileinfo (verinfo, key, var)
1033      struct ver_info *verinfo;
1034      const char *key;
1035      struct ver_varinfo *var;
1036 {
1037   struct ver_info *vi, **pp;
1038
1039   vi = (struct ver_info *) res_alloc (sizeof *vi);
1040   vi->next = NULL;
1041   vi->type = VERINFO_VAR;
1042   unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1043   vi->u.var.var = var;
1044
1045   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1046     ;
1047   *pp = vi;
1048
1049   return verinfo;
1050 }
1051
1052 /* Append version string information to a list.  */
1053
1054 struct ver_stringinfo *
1055 append_verval (strings, key, value)
1056      struct ver_stringinfo *strings;
1057      const char *key;
1058      const char *value;
1059 {
1060   struct ver_stringinfo *vs, **pp;
1061
1062   vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1063   vs->next = NULL;
1064   unicode_from_ascii ((int *) NULL, &vs->key, key);
1065   unicode_from_ascii ((int *) NULL, &vs->value, value);
1066
1067   for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1068     ;
1069   *pp = vs;
1070
1071   return strings;
1072 }
1073
1074 /* Append version variable information to a list.  */
1075
1076 struct ver_varinfo *
1077 append_vertrans (var, language, charset)
1078      struct ver_varinfo *var;
1079      unsigned long language;
1080      unsigned long charset;
1081 {
1082   struct ver_varinfo *vv, **pp;
1083
1084   vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1085   vv->next = NULL;
1086   vv->language = language;
1087   vv->charset = charset;
1088
1089   for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1090     ;
1091   *pp = vv;
1092
1093   return var;
1094 }
1095 \f
1096 /* Local functions used to write out an rc file.  */
1097
1098 static void indent PARAMS ((FILE *, int));
1099 static void write_rc_directory
1100   PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1101            const struct res_id *, int *, int));
1102 static void write_rc_subdir
1103   PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1104            const struct res_id *, int *, int));
1105 static void write_rc_resource
1106   PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1107            const struct res_resource *, int *));
1108 static void write_rc_accelerators
1109   PARAMS ((FILE *, const struct accelerator *));
1110 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1111 static void write_rc_group_cursor
1112   PARAMS ((FILE *, const struct group_cursor *));
1113 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1114 static void write_rc_dialog_control
1115   PARAMS ((FILE *, const struct dialog_control *));
1116 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1117 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1118 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1119 static void write_rc_menuitems
1120   PARAMS ((FILE *, const struct menuitem *, int, int));
1121 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1122 static void write_rc_stringtable
1123   PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1124 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1125 static void write_rc_filedata
1126   PARAMS ((FILE *, unsigned long, const unsigned char *));
1127
1128 /* Indent a given number of spaces.  */
1129
1130 static void
1131 indent (e, c)
1132      FILE *e;
1133      int c;
1134 {
1135   int i;
1136
1137   for (i = 0; i < c; i++)
1138     putc (' ', e);
1139 }
1140
1141 /* Dump the resources we have read in the format of an rc file.
1142
1143    Actually, we don't use the format of an rc file, because it's way
1144    too much of a pain--for example, we'd have to write icon resources
1145    into a file and refer to that file.  We just generate a readable
1146    format that kind of looks like an rc file, and is useful for
1147    understanding the contents of a resource file.  Someday we may want
1148    to generate an rc file which the rc compiler can read; if that day
1149    comes, this code will have to be fixed up.  */
1150
1151 void
1152 write_rc_file (filename, resources)
1153      const char *filename;
1154      const struct res_directory *resources;
1155 {
1156   FILE *e;
1157   int language;
1158
1159   if (filename == NULL)
1160     e = stdout;
1161   else
1162     {
1163       e = fopen (filename, FOPEN_WT);
1164       if (e == NULL)
1165         fatal ("can't open `%s' for output: %s", filename, strerror (errno));
1166     }
1167
1168   language = -1;
1169   write_rc_directory (e, resources, (const struct res_id *) NULL,
1170                       (const struct res_id *) NULL, &language, 1);
1171 }
1172
1173 /* Write out a directory.  E is the file to write to.  RD is the
1174    directory.  TYPE is a pointer to the level 1 ID which serves as the
1175    resource type.  NAME is a pointer to the level 2 ID which serves as
1176    an individual resource name.  LANGUAGE is a pointer to the current
1177    language.  LEVEL is the level in the tree.  */
1178
1179 static void
1180 write_rc_directory (e, rd, type, name, language, level)
1181      FILE *e;
1182      const struct res_directory *rd;
1183      const struct res_id *type;
1184      const struct res_id *name;
1185      int *language;
1186      int level;
1187 {
1188   const struct res_entry *re;
1189
1190   /* Print out some COFF information that rc files can't represent.  */
1191
1192   if (rd->time != 0)
1193     fprintf (e, "// Time stamp: %lu\n", rd->time);
1194   if (rd->characteristics != 0)
1195     fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1196   if (rd->major != 0 || rd->minor != 0)
1197     fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1198
1199   for (re = rd->entries;  re != NULL; re = re->next)
1200     {
1201       switch (level)
1202         {
1203         case 1:
1204           /* If we're at level 1, the key of this resource is the
1205              type.  This normally duplicates the information we have
1206              stored with the resource itself, but we need to remember
1207              the type if this is a user define resource type.  */
1208           type = &re->id;
1209           break;
1210
1211         case 2:
1212           /* If we're at level 2, the key of this resource is the name
1213              we are going to use in the rc printout. */
1214           name = &re->id;
1215           break;
1216
1217         case 3:
1218           /* If we're at level 3, then this key represents a language.
1219              Use it to update the current language.  */
1220           if (! re->id.named
1221               && re->id.u.id != *language
1222               && (re->id.u.id & 0xffff) == re->id.u.id)
1223             {
1224               fprintf (e, "LANGUAGE %lu, %lu\n",
1225                        re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1226               *language = re->id.u.id;
1227             }
1228           break;
1229
1230         default:
1231           break;
1232         }
1233
1234       if (re->subdir)
1235         write_rc_subdir (e, re, type, name, language, level);
1236       else
1237         {
1238           if (level == 3)
1239             {
1240               /* This is the normal case: the three levels are
1241                  TYPE/NAME/LANGUAGE.  NAME will have been set at level
1242                  2, and represents the name to use.  We probably just
1243                  set LANGUAGE, and it will probably match what the
1244                  resource itself records if anything.  */
1245               write_rc_resource (e, type, name, re->u.res, language);
1246             }
1247           else
1248             {
1249               fprintf (e, "// Resource at unexpected level %d\n", level);
1250               write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1251                                  language);
1252             }
1253         }
1254     }
1255 }
1256
1257 /* Write out a subdirectory entry.  E is the file to write to.  RE is
1258    the subdirectory entry.  TYPE and NAME are pointers to higher level
1259    IDs, or NULL.  LANGUAGE is a pointer to the current language.
1260    LEVEL is the level in the tree.  */
1261
1262 static void
1263 write_rc_subdir (e, re, type, name, language, level)
1264      FILE *e;
1265      const struct res_entry *re;
1266      const struct res_id *type;
1267      const struct res_id *name;
1268      int *language;
1269      int level;
1270 {
1271   fprintf (e, "\n");
1272   switch (level)
1273     {
1274     case 1:
1275       fprintf (e, "// Type: ");
1276       if (re->id.named)
1277         res_id_print (e, re->id, 1);
1278       else
1279         {
1280           const char *s;
1281
1282           switch (re->id.u.id)
1283             {
1284             case RT_CURSOR: s = "cursor"; break;
1285             case RT_BITMAP: s = "bitmap"; break;
1286             case RT_ICON: s = "icon"; break;
1287             case RT_MENU: s = "menu"; break;
1288             case RT_DIALOG: s = "dialog"; break;
1289             case RT_STRING: s = "stringtable"; break;
1290             case RT_FONTDIR: s = "fontdir"; break;
1291             case RT_FONT: s = "font"; break;
1292             case RT_ACCELERATORS: s = "accelerators"; break;
1293             case RT_RCDATA: s = "rcdata"; break;
1294             case RT_MESSAGETABLE: s = "messagetable"; break;
1295             case RT_GROUP_CURSOR: s = "group cursor"; break;
1296             case RT_GROUP_ICON: s = "group icon"; break;
1297             case RT_VERSION: s = "version"; break;
1298             case RT_DLGINCLUDE: s = "dlginclude"; break;
1299             case RT_PLUGPLAY: s = "plugplay"; break;
1300             case RT_VXD: s = "vxd"; break;
1301             case RT_ANICURSOR: s = "anicursor"; break;
1302             case RT_ANIICON: s = "aniicon"; break;
1303             default: s = NULL; break;
1304             }
1305
1306           if (s != NULL)
1307             fprintf (e, "%s", s);
1308           else
1309             res_id_print (e, re->id, 1);
1310         }
1311       fprintf (e, "\n");
1312       break;
1313
1314     case 2:
1315       fprintf (e, "// Name: ");
1316       res_id_print (e, re->id, 1);
1317       fprintf (e, "\n");
1318       break;
1319
1320     case 3:
1321       fprintf (e, "// Language: ");
1322       res_id_print (e, re->id, 1);
1323       fprintf (e, "\n");
1324       break;
1325
1326     default:
1327       fprintf (e, "// Level %d: ", level);
1328       res_id_print (e, re->id, 1);
1329       fprintf (e, "\n");
1330     }           
1331
1332   write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1333 }
1334
1335 /* Write out a single resource.  E is the file to write to.  TYPE is a
1336    pointer to the type of the resource.  NAME is a pointer to the name
1337    of the resource; it will be NULL if there is a level mismatch.  RES
1338    is the resource data.  LANGUAGE is a pointer to the current
1339    language.  */
1340
1341 static void
1342 write_rc_resource (e, type, name, res, language)
1343      FILE *e;
1344      const struct res_id *type;
1345      const struct res_id *name;
1346      const struct res_resource *res;
1347      int *language;
1348 {
1349   const char *s;
1350   int rt;
1351   int menuex = 0;
1352
1353   fprintf (e, "\n");
1354
1355   switch (res->type)
1356     {
1357     default:
1358       abort ();
1359
1360     case RES_TYPE_ACCELERATOR:
1361       s = "ACCELERATOR";
1362       rt = RT_ACCELERATORS;
1363       break;
1364
1365     case RES_TYPE_BITMAP:
1366       s = "BITMAP";
1367       rt = RT_BITMAP;
1368       break;
1369
1370     case RES_TYPE_CURSOR:
1371       s = "CURSOR";
1372       rt = RT_CURSOR;
1373       break;
1374
1375     case RES_TYPE_GROUP_CURSOR:
1376       s = "GROUP_CURSOR";
1377       rt = RT_GROUP_CURSOR;
1378       break;
1379
1380     case RES_TYPE_DIALOG:
1381       if (extended_dialog (res->u.dialog))
1382         s = "DIALOGEX";
1383       else
1384         s = "DIALOG";
1385       rt = RT_DIALOG;
1386       break;
1387
1388     case RES_TYPE_FONT:
1389       s = "FONT";
1390       rt = RT_FONT;
1391       break;
1392
1393     case RES_TYPE_FONTDIR:
1394       s = "FONTDIR";
1395       rt = RT_FONTDIR;
1396       break;
1397
1398     case RES_TYPE_ICON:
1399       s = "ICON";
1400       rt = RT_ICON;
1401       break;
1402
1403     case RES_TYPE_GROUP_ICON:
1404       s = "GROUP_ICON";
1405       rt = RT_GROUP_ICON;
1406       break;
1407
1408     case RES_TYPE_MENU:
1409       if (extended_menu (res->u.menu))
1410         {
1411           s = "MENUEX";
1412           menuex = 1;
1413         }
1414       else
1415         {
1416           s = "MENU";
1417           menuex = 0;
1418         }
1419       rt = RT_MENU;
1420       break;
1421
1422     case RES_TYPE_MESSAGETABLE:
1423       s = "MESSAGETABLE";
1424       rt = RT_MESSAGETABLE;
1425       break;
1426
1427     case RES_TYPE_RCDATA:
1428       s = "RCDATA";
1429       rt = RT_RCDATA;
1430       break;
1431
1432     case RES_TYPE_STRINGTABLE:
1433       s = "STRINGTABLE";
1434       rt = RT_STRING;
1435       break;
1436
1437     case RES_TYPE_USERDATA:
1438       s = NULL;
1439       rt = 0;
1440       break;
1441
1442     case RES_TYPE_VERSIONINFO:
1443       s = "VERSIONINFO";
1444       rt = RT_VERSION;
1445       break;
1446     }
1447
1448   if (rt != 0
1449       && type != NULL
1450       && (type->named || type->u.id != rt))
1451     {
1452       fprintf (e, "// Unexpected resource type mismatch: ");
1453       res_id_print (e, *type, 1);
1454       fprintf (e, " != %d", rt);
1455     }
1456
1457   if (res->coff_info.codepage != 0)
1458     fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1459   if (res->coff_info.reserved != 0)
1460     fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1461
1462   if (name != NULL)
1463     res_id_print (e, *name, 0);
1464   else
1465     fprintf (e, "??Unknown-Name??");
1466
1467   fprintf (e, " ");
1468   if (s != NULL)
1469     fprintf (e, "%s", s);
1470   else if (type != NULL)
1471     res_id_print (e, *type, 0);
1472   else
1473     fprintf (e, "??Unknown-Type??");
1474
1475   if (res->res_info.memflags != 0)
1476     {
1477       if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1478         fprintf (e, " MOVEABLE");
1479       if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1480         fprintf (e, " PURE");
1481       if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1482         fprintf (e, " PRELOAD");
1483       if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1484         fprintf (e, " DISCARDABLE");
1485     }
1486
1487   if (res->type == RES_TYPE_DIALOG)
1488     {
1489       fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1490                res->u.dialog->width, res->u.dialog->height);
1491       if (res->u.dialog->ex != NULL
1492           && res->u.dialog->ex->help != 0)
1493         fprintf (e, ", %lu", res->u.dialog->ex->help);
1494     }
1495
1496   fprintf (e, "\n");
1497
1498   if ((res->res_info.language != 0 && res->res_info.language != *language)
1499       || res->res_info.characteristics != 0
1500       || res->res_info.version != 0)
1501     {
1502       int modifiers;
1503
1504       switch (res->type)
1505         {
1506         case RES_TYPE_ACCELERATOR:
1507         case RES_TYPE_DIALOG:
1508         case RES_TYPE_MENU:
1509         case RES_TYPE_RCDATA:
1510         case RES_TYPE_STRINGTABLE:
1511           modifiers = 1;
1512           break;
1513
1514         default:
1515           modifiers = 0;
1516           break;
1517         }
1518
1519       if (res->res_info.language != 0 && res->res_info.language != *language)
1520         fprintf (e, "%sLANGUAGE %d, %d\n",
1521                  modifiers ? "// " : "",
1522                  res->res_info.language & 0xff,
1523                  (res->res_info.language >> 8) & 0xff);
1524       if (res->res_info.characteristics != 0)
1525         fprintf (e, "%sCHARACTERISTICS %lu\n",
1526                  modifiers ? "// " : "",
1527                  res->res_info.characteristics);
1528       if (res->res_info.version != 0)
1529         fprintf (e, "%sVERSION %lu\n",
1530                  modifiers ? "// " : "",
1531                  res->res_info.version);
1532     }
1533
1534   switch (res->type)
1535     {
1536     default:
1537       abort ();
1538
1539     case RES_TYPE_ACCELERATOR:
1540       write_rc_accelerators (e, res->u.acc);
1541       break;
1542
1543     case RES_TYPE_CURSOR:
1544       write_rc_cursor (e, res->u.cursor);
1545       break;
1546
1547     case RES_TYPE_GROUP_CURSOR:
1548       write_rc_group_cursor (e, res->u.group_cursor);
1549       break;
1550
1551     case RES_TYPE_DIALOG:
1552       write_rc_dialog (e, res->u.dialog);
1553       break;
1554
1555     case RES_TYPE_FONTDIR:
1556       write_rc_fontdir (e, res->u.fontdir);
1557       break;
1558
1559     case RES_TYPE_GROUP_ICON:
1560       write_rc_group_icon (e, res->u.group_icon);
1561       break;
1562
1563     case RES_TYPE_MENU:
1564       write_rc_menu (e, res->u.menu, menuex);
1565       break;
1566
1567     case RES_TYPE_RCDATA:
1568       write_rc_rcdata (e, res->u.rcdata, 0);
1569       break;
1570
1571     case RES_TYPE_STRINGTABLE:
1572       write_rc_stringtable (e, name, res->u.stringtable);
1573       break;
1574
1575     case RES_TYPE_USERDATA:
1576       write_rc_rcdata (e, res->u.userdata, 0);
1577       break;
1578
1579     case RES_TYPE_VERSIONINFO:
1580       write_rc_versioninfo (e, res->u.versioninfo);
1581       break;
1582
1583     case RES_TYPE_BITMAP:
1584     case RES_TYPE_FONT:
1585     case RES_TYPE_ICON:
1586     case RES_TYPE_MESSAGETABLE:
1587       write_rc_filedata (e, res->u.data.length, res->u.data.data);
1588       break;
1589     }
1590 }
1591
1592 /* Write out accelerator information.  */
1593
1594 static void
1595 write_rc_accelerators (e, accelerators)
1596      FILE *e;
1597      const struct accelerator *accelerators;
1598 {
1599   const struct accelerator *acc;
1600
1601   fprintf (e, "BEGIN\n");
1602   for (acc = accelerators; acc != NULL; acc = acc->next)
1603     {
1604       int printable;
1605
1606       fprintf (e, "  ");
1607
1608       if ((acc->key & 0x7f) == acc->key
1609           && isprint ((unsigned char) acc->key)
1610           && (acc->flags & ACC_VIRTKEY) == 0)
1611         {
1612           fprintf (e, "\"%c\"", acc->key);
1613           printable = 1;
1614         }
1615       else
1616         {
1617           fprintf (e, "%d", acc->key);
1618           printable = 0;
1619         }
1620
1621       fprintf (e, ", %d", acc->id);
1622
1623       if (! printable)
1624         {
1625           if ((acc->flags & ACC_VIRTKEY) != 0)
1626             fprintf (e, ", VIRTKEY");
1627           else
1628             fprintf (e, ", ASCII");
1629         }
1630
1631       if ((acc->flags & ACC_SHIFT) != 0)
1632         fprintf (e, ", SHIFT");
1633       if ((acc->flags & ACC_CONTROL) != 0)
1634         fprintf (e, ", CONTROL");
1635       if ((acc->flags & ACC_ALT) != 0)
1636         fprintf (e, ", ALT");
1637
1638       fprintf (e, "\n");
1639     }
1640
1641   fprintf (e, "END\n");
1642 }
1643
1644 /* Write out cursor information.  This would normally be in a separate
1645    file, which the rc file would include.  */
1646
1647 static void
1648 write_rc_cursor (e, cursor)
1649      FILE *e;
1650      const struct cursor *cursor;
1651 {
1652   fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1653            cursor->yhotspot);
1654   write_rc_filedata (e, cursor->length, cursor->data);
1655 }
1656
1657 /* Write out group cursor data.  This would normally be built from the
1658    cursor data.  */
1659
1660 static void
1661 write_rc_group_cursor (e, group_cursor)
1662      FILE *e;
1663      const struct group_cursor *group_cursor;
1664 {
1665   const struct group_cursor *gc;
1666
1667   for (gc = group_cursor; gc != NULL; gc = gc->next)
1668     {
1669       fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1670              gc->width, gc->height, gc->planes, gc->bits);
1671       fprintf (e, "// data bytes: %lu; index: %d\n",
1672                gc->bytes, gc->index);
1673     }
1674 }
1675
1676 /* Write dialog data.  */
1677
1678 static void
1679 write_rc_dialog (e, dialog)
1680      FILE *e;
1681      const struct dialog *dialog;
1682 {
1683   const struct dialog_control *control;
1684
1685   if (dialog->style != 0)
1686     fprintf (e, "STYLE 0x%lx\n", dialog->style);
1687   if (dialog->exstyle != 0)
1688     fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1689   if (dialog->class.named || dialog->class.u.id != 0)
1690     {
1691       fprintf (e, "CLASS ");
1692       res_id_print (e, dialog->class, 0);
1693       fprintf (e, "\n");
1694     }
1695   if (dialog->caption != NULL)
1696     {
1697       fprintf (e, "CAPTION \"");
1698       unicode_print (e, dialog->caption, -1);
1699       fprintf (e, "\"\n");
1700     }
1701   if (dialog->menu.named || dialog->menu.u.id != 0)
1702     {
1703       fprintf (e, "MENU ");
1704       res_id_print (e, dialog->menu, 0);
1705       fprintf (e, "\n");
1706     }
1707   if (dialog->font != NULL)
1708     {
1709       fprintf (e, "FONT %d, \"", dialog->pointsize);
1710       unicode_print (e, dialog->font, -1);
1711       fprintf (e, "\"");
1712       if (dialog->ex != NULL
1713           && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
1714         fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
1715       fprintf (e, "\n");
1716     }
1717
1718   fprintf (e, "BEGIN\n");
1719
1720   for (control = dialog->controls; control != NULL; control = control->next)
1721     write_rc_dialog_control (e, control);
1722
1723   fprintf (e, "END\n");
1724 }
1725
1726 /* For each predefined control keyword, this table provides the class
1727    and the style.  */
1728
1729 struct control_info
1730 {
1731   const char *name;
1732   unsigned short class;
1733   unsigned long style;
1734 };
1735
1736 static const struct control_info control_info[] =
1737 {
1738   { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
1739   { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
1740   { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
1741   { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
1742   { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
1743   { "CTEXT", CTL_STATIC, SS_CENTER },
1744   { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
1745   { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
1746   { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
1747   { "ICON", CTL_STATIC, SS_ICON },
1748   { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
1749   { "LTEXT", CTL_STATIC, SS_LEFT },
1750   { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
1751   { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
1752   { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
1753   { "RTEXT", CTL_STATIC, SS_RIGHT },
1754   { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
1755   { "STATE3", CTL_BUTTON, BS_3STATE },
1756   /* It's important that USERBUTTON come after all the other button
1757      types, so that it won't be matched too early.  */
1758   { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
1759   { NULL, 0, 0 }
1760 };
1761
1762 /* Write a dialog control.  */
1763
1764 static void
1765 write_rc_dialog_control (e, control)
1766      FILE *e;
1767      const struct dialog_control *control;
1768 {
1769   const struct control_info *ci;
1770
1771   fprintf (e, "  ");
1772
1773   if (control->class.named)
1774     ci = NULL;
1775   else
1776     {
1777       for (ci = control_info; ci->name != NULL; ++ci)
1778         if (ci->class == control->class.u.id
1779             && (ci->style == (unsigned long) -1
1780                 || ci->style == (control->style & 0xff)))
1781           break;
1782     }
1783
1784   if (ci->name != NULL)
1785     fprintf (e, "%s", ci->name);
1786   else
1787     fprintf (e, "CONTROL");
1788   
1789   if (control->text.named || control->text.u.id != 0)
1790     {
1791       fprintf (e, " ");
1792       res_id_print (e, control->text, 1);
1793       fprintf (e, ",");
1794     }
1795
1796   fprintf (e, " %d, ", control->id);
1797
1798   if (ci->name == NULL)
1799     {
1800       res_id_print (e, control->class, 0);
1801       fprintf (e, ", 0x%lx, ", control->style);
1802     }
1803
1804   fprintf (e, "%d, %d", control->x, control->y);
1805
1806   if (control->style != SS_ICON
1807       || control->exstyle != 0
1808       || control->width != 0
1809       || control->height != 0
1810       || control->help != 0)
1811     {
1812       fprintf (e, ", %d, %d", control->width, control->height);
1813
1814       /* FIXME: We don't need to print the style if it is the default.
1815          More importantly, in certain cases we actually need to turn
1816          off parts of the forced style, by using NOT.  */
1817       fprintf (e, ", 0x%lx", control->style);
1818
1819       if (control->exstyle != 0 || control->help != 0)
1820         fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1821     }
1822
1823   fprintf (e, "\n");
1824
1825   if (control->data != NULL)
1826     write_rc_rcdata (e, control->data, 2);
1827 }
1828
1829 /* Write out font directory data.  This would normally be built from
1830    the font data.  */
1831
1832 static void
1833 write_rc_fontdir (e, fontdir)
1834      FILE *e;
1835      const struct fontdir *fontdir;
1836 {
1837   const struct fontdir *fc;
1838
1839   for (fc = fontdir; fc != NULL; fc = fc->next)
1840     {
1841       fprintf (e, "// Font index: %d\n", fc->index);
1842       write_rc_filedata (e, fc->length, fc->data);
1843     }
1844 }
1845
1846 /* Write out group icon data.  This would normally be built from the
1847    icon data.  */
1848
1849 static void
1850 write_rc_group_icon (e, group_icon)
1851      FILE *e;
1852      const struct group_icon *group_icon;
1853 {
1854   const struct group_icon *gi;
1855
1856   for (gi = group_icon; gi != NULL; gi = gi->next)
1857     {
1858       fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1859                gi->width, gi->height, gi->colors, gi->planes, gi->bits);
1860       fprintf (e, "// data bytes: %lu; index: %d\n",
1861                gi->bytes, gi->index);
1862     }
1863 }
1864
1865 /* Write out a menu resource.  */
1866
1867 static void
1868 write_rc_menu (e, menu, menuex)
1869      FILE *e;
1870      const struct menu *menu;
1871      int menuex;
1872 {
1873   if (menu->help != 0)
1874     fprintf (e, "// Help ID: %lu\n", menu->help);
1875   write_rc_menuitems (e, menu->items, menuex, 0);
1876 }
1877
1878 /* Write out menuitems.  */
1879
1880 static void
1881 write_rc_menuitems (e, menuitems, menuex, ind)
1882      FILE *e;
1883      const struct menuitem *menuitems;
1884      int menuex;
1885      int ind;
1886 {
1887   const struct menuitem *mi;
1888
1889   indent (e, ind);
1890   fprintf (e, "BEGIN\n");
1891
1892   for (mi = menuitems; mi != NULL; mi = mi->next)
1893     {
1894       indent (e, ind + 2);
1895
1896       if (mi->popup == NULL)
1897         fprintf (e, "MENUITEM");
1898       else
1899         fprintf (e, "POPUP");
1900
1901       if (! menuex
1902           && mi->popup == NULL
1903           && mi->text == NULL
1904           && mi->type == 0
1905           && mi->id == 0)
1906         {
1907           fprintf (e, " SEPARATOR\n");
1908           continue;
1909         }
1910
1911       if (mi->text == NULL)
1912         fprintf (e, " \"\"");
1913       else
1914         {
1915           fprintf (e, " \"");
1916           unicode_print (e, mi->text, -1);
1917           fprintf (e, "\"");
1918         }
1919
1920       if (! menuex)
1921         {
1922           if (mi->popup == NULL)
1923             fprintf (e, ", %d", mi->id);
1924
1925           if ((mi->type & MENUITEM_CHECKED) != 0)
1926             fprintf (e, ", CHECKED");
1927           if ((mi->type & MENUITEM_GRAYED) != 0)
1928             fprintf (e, ", GRAYED");
1929           if ((mi->type & MENUITEM_HELP) != 0)
1930             fprintf (e, ", HELP");
1931           if ((mi->type & MENUITEM_INACTIVE) != 0)
1932             fprintf (e, ", INACTIVE");
1933           if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
1934             fprintf (e, ", MENUBARBREAK");
1935           if ((mi->type & MENUITEM_MENUBREAK) != 0)
1936             fprintf (e, ", MENUBREAK");
1937         }
1938       else
1939         {
1940           if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
1941             {
1942               fprintf (e, ", %d", mi->id);
1943               if (mi->type != 0 || mi->state != 0 || mi->help != 0)
1944                 {
1945                   fprintf (e, ", %lu", mi->type);
1946                   if (mi->state != 0 || mi->help != 0)
1947                     {
1948                       fprintf (e, ", %lu", mi->state);
1949                       if (mi->help != 0)
1950                         fprintf (e, ", %lu", mi->help);
1951                     }
1952                 }
1953             }
1954         }
1955
1956       fprintf (e, "\n");
1957
1958       if (mi->popup != NULL)
1959         write_rc_menuitems (e, mi->popup, menuex, ind + 2);
1960     }
1961
1962   indent (e, ind);
1963   fprintf (e, "END\n");
1964 }
1965
1966 /* Write out an rcdata resource.  This is also used for other types of
1967    resources that need to print arbitrary data.  */
1968
1969 static void
1970 write_rc_rcdata (e, rcdata, ind)
1971      FILE *e;
1972      const struct rcdata_item *rcdata;
1973      int ind;
1974 {
1975   const struct rcdata_item *ri;
1976
1977   indent (e, ind);
1978   fprintf (e, "BEGIN\n");
1979
1980   for (ri = rcdata; ri != NULL; ri = ri->next)
1981     {
1982       if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
1983         continue;
1984
1985       indent (e, ind + 2);
1986
1987       switch (ri->type)
1988         {
1989         default:
1990           abort ();
1991
1992         case RCDATA_WORD:
1993           fprintf (e, "%d", ri->u.word);
1994           break;
1995
1996         case RCDATA_DWORD:
1997           fprintf (e, "%luL", ri->u.dword);
1998           break;
1999
2000         case RCDATA_STRING:
2001           {
2002             const char *s;
2003             unsigned long i;
2004
2005             fprintf (e, "\"");
2006             s = ri->u.string.s;
2007             for (i = 0; i < ri->u.string.length; i++)
2008               {
2009                 if (isprint (*s))
2010                   putc (*s, e);
2011                 else
2012                   fprintf (e, "\\%03o", *s);
2013               }
2014             fprintf (e, "\"");
2015             break;
2016           }
2017
2018         case RCDATA_WSTRING:
2019           fprintf (e, "L\"");
2020           unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2021           fprintf (e, "\"");
2022           break;
2023
2024         case RCDATA_BUFFER:
2025           {
2026             unsigned long i;
2027             int first;
2028
2029             /* Assume little endian data.  */
2030
2031             first = 1;
2032             for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2033               {
2034                 unsigned long l;
2035
2036                 l = ((((((ri->u.buffer.data[i + 3] << 8)
2037                          | ri->u.buffer.data[i + 2]) << 8)
2038                        | ri->u.buffer.data[i + 1]) << 8)
2039                      | ri->u.buffer.data[i]);
2040                 if (first)
2041                   first = 0;
2042                 else
2043                   {
2044                     fprintf (e, ",\n");
2045                     indent (e, ind + 2);
2046                   }
2047                 fprintf (e, "%luL", l);
2048               }
2049
2050             if (i + 1 < ri->u.buffer.length)
2051               {
2052                 int i;
2053
2054                 i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2055                 if (first)
2056                   first = 0;
2057                 else
2058                   {
2059                     fprintf (e, ",\n");
2060                     indent (e, ind + 2);
2061                   }
2062                 fprintf (e, "%d", i);
2063                 i += 2;
2064               }
2065
2066             if (i < ri->u.buffer.length)
2067               {
2068                 if (first)
2069                   first = 0;
2070                 else
2071                   {
2072                     fprintf (e, ",\n");
2073                     indent (e, ind + 2);
2074                   }
2075                 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2076                     && isprint (ri->u.buffer.data[i]))
2077                   fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2078                 else
2079                   fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
2080               }
2081
2082             break;
2083           }
2084         }
2085
2086       if (ri->next != NULL)
2087         fprintf (e, ",");
2088       fprintf (e, "\n");
2089     }
2090
2091   indent (e, ind);
2092   fprintf (e, "END\n");
2093 }
2094
2095 /* Write out a stringtable resource.  */
2096
2097 static void
2098 write_rc_stringtable (e, name, stringtable)
2099      FILE *e;
2100      const struct res_id *name;
2101      const struct stringtable *stringtable;
2102 {
2103   unsigned long offset;
2104   int i;
2105
2106   if (name != NULL && ! name->named)
2107     offset = name->u.id << 4;
2108   else
2109     {
2110       fprintf (e, "// %s string table name\n",
2111                name == NULL ? "Missing" : "Invalid");
2112       offset = 0;
2113     }
2114
2115   fprintf (e, "BEGIN\n");
2116
2117   for (i = 0; i < 16; i++)
2118     {
2119       if (stringtable->strings[i].length != 0)
2120         {
2121           fprintf (e, "  %lu, \"", offset + i);
2122           unicode_print (e, stringtable->strings[i].string,
2123                          stringtable->strings[i].length);
2124           fprintf (e, "\"\n");
2125         }
2126     }
2127
2128   fprintf (e, "END\n");
2129 }
2130
2131 /* Write out a versioninfo resource.  */
2132
2133 static void
2134 write_rc_versioninfo (e, versioninfo)
2135      FILE *e;
2136      const struct versioninfo *versioninfo;
2137 {
2138   const struct fixed_versioninfo *f;
2139   const struct ver_info *vi;
2140
2141   f = versioninfo->fixed;
2142   if (f->file_version_ms != 0 || f->file_version_ls != 0)
2143     fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2144              (f->file_version_ms >> 16) & 0xffff,
2145              f->file_version_ms & 0xffff,
2146              (f->file_version_ls >> 16) & 0xffff,
2147              f->file_version_ls & 0xffff);
2148   if (f->product_version_ms != 0 || f->product_version_ls != 0)
2149     fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2150              (f->product_version_ms >> 16) & 0xffff,
2151              f->product_version_ms & 0xffff,
2152              (f->product_version_ls >> 16) & 0xffff,
2153              f->product_version_ls & 0xffff);
2154   if (f->file_flags_mask != 0)
2155     fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2156   if (f->file_flags != 0)
2157     fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2158   if (f->file_os != 0)
2159     fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2160   if (f->file_type != 0)
2161     fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2162   if (f->file_subtype != 0)
2163     fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2164   if (f->file_date_ms != 0 || f->file_date_ls != 0)
2165     fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2166
2167   fprintf (e, "BEGIN\n");
2168
2169   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2170     {
2171       switch (vi->type)
2172         {
2173         case VERINFO_STRING:
2174           {
2175             const struct ver_stringinfo *vs;
2176
2177             fprintf (e, "  BLOCK \"StringFileInfo\"\n");
2178             fprintf (e, "  BEGIN\n");
2179             fprintf (e, "    BLOCK \"");
2180             unicode_print (e, vi->u.string.language, -1);
2181             fprintf (e, "\"\n");
2182             fprintf (e, "    BEGIN\n");
2183
2184             for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2185               {
2186                 fprintf (e, "      VALUE \"");
2187                 unicode_print (e, vs->key, -1);
2188                 fprintf (e, "\", \"");
2189                 unicode_print (e, vs->value, -1);
2190                 fprintf (e, "\"\n");
2191               }
2192
2193             fprintf (e, "    END\n");
2194             fprintf (e, "  END\n");
2195             break;
2196           }
2197
2198         case VERINFO_VAR:
2199           {
2200             const struct ver_varinfo *vv;
2201
2202             fprintf (e, "  BLOCK \"VarFileInfo\"\n");
2203             fprintf (e, "  BEGIN\n");
2204             fprintf (e, "    VALUE \"");
2205             unicode_print (e, vi->u.var.key, -1);
2206             fprintf (e, "\"");
2207
2208             for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2209               fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2210                        vv->charset);
2211
2212             fprintf (e, "\n  END\n");
2213
2214             break;
2215           }
2216         }
2217     }
2218
2219   fprintf (e, "END\n");
2220 }
2221
2222 /* Write out data which would normally be read from a file.  */
2223
2224 static void
2225 write_rc_filedata (e, length, data)
2226      FILE *e;
2227      unsigned long length;
2228      const unsigned char *data;
2229 {
2230   unsigned long i;
2231
2232   for (i = 0; i + 15 < length; i += 16)
2233     {
2234       fprintf (e, "// %4lx: ", i);
2235       fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2236                data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2237                data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2238       fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2239                data[i +  8], data[i +  9], data[i + 10], data[i + 11],
2240                data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2241     }
2242
2243   if (i < length)
2244     {
2245       fprintf (e, "// %4lx:", i);
2246       while (i < length)
2247         {
2248           fprintf (e, " %02x", data[i]);
2249           ++i;
2250         }
2251       fprintf (e, "\n");
2252     }
2253 }