]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/resrc.c
19990502 sourceware import
[thirdparty/binutils-gdb.git] / binutils / resrc.c
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.
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 functions 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 #if defined (_WIN32) && ! defined (__CYGWIN32__)
35 #define popen _popen
36 #define pclose _pclose
37 #endif
38
39 /* The default preprocessor. */
40
41 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
42
43 /* We read the directory entries in a cursor or icon file into
44 instances of this structure. */
45
46 struct icondir
47 {
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
55 {
56 struct
57 {
58 /* Color planes. */
59 unsigned short planes;
60 /* Bits per pixel. */
61 unsigned short bits;
62 } icon;
63 struct
64 {
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;
75 };
76
77 /* The name of the rc file we are reading. */
78
79 char *rc_filename;
80
81 /* The line number in the rc file. */
82
83 int rc_lineno;
84
85 /* The pipe we are reading from, so that we can close it if we exit. */
86
87 static FILE *cpp_pipe;
88
89 /* As we read the rc file, we attach information to this structure. */
90
91 static struct res_directory *resources;
92
93 /* The number of cursor resources we have written out. */
94
95 static int cursors;
96
97 /* The number of font resources we have written out. */
98
99 static int fonts;
100
101 /* Font directory information. */
102
103 struct fontdir *fontdirs;
104
105 /* Resource info to use for fontdirs. */
106
107 struct res_res_info fontdirs_resinfo;
108
109 /* The number of icon resources we have written out. */
110
111 static int icons;
112
113 /* Local functions. */
114
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));
122 \f
123 /* Read an rc file. */
124
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;
131 {
132 char *cmd;
133
134 if (preprocessor == NULL)
135 preprocessor = DEFAULT_PREPROCESSOR;
136
137 if (preprocargs == NULL)
138 preprocargs = "";
139 if (filename == NULL)
140 filename = "-";
141
142 cmd = xmalloc (strlen (preprocessor)
143 + strlen (preprocargs)
144 + strlen (filename)
145 + 10);
146 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
147
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);
152
153 xatexit (close_pipe);
154
155 rc_filename = xstrdup (filename);
156 rc_lineno = 1;
157 if (language != -1)
158 rcparse_set_language (language);
159 yyin = cpp_pipe;
160 yyparse ();
161
162 if (pclose (cpp_pipe) != 0)
163 fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name);
164 cpp_pipe = NULL;
165
166 if (fontdirs != NULL)
167 define_fontdirs ();
168
169 free (rc_filename);
170 rc_filename = NULL;
171
172 return resources;
173 }
174
175 /* Close the pipe if it is open. This is called via xatexit. */
176
177 void
178 close_pipe ()
179 {
180 if (cpp_pipe != NULL)
181 pclose (cpp_pipe);
182 }
183
184 /* Report an error while reading an rc file. */
185
186 void
187 yyerror (msg)
188 const char *msg;
189 {
190 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
191 }
192
193 /* Issue a warning while reading an rc file. */
194
195 void
196 rcparse_warning (msg)
197 const char *msg;
198 {
199 fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
200 }
201
202 /* Die if we get an unexpected end of file. */
203
204 static void
205 unexpected_eof (msg)
206 const char *msg;
207 {
208 fatal (_("%s: unexpected EOF"), msg);
209 }
210
211 /* Read a 16 bit word from a file. The data is assumed to be little
212 endian. */
213
214 static int
215 get_word (e, msg)
216 FILE *e;
217 const char *msg;
218 {
219 int b1, b2;
220
221 b1 = getc (e);
222 b2 = getc (e);
223 if (feof (e))
224 unexpected_eof (msg);
225 return ((b2 & 0xff) << 8) | (b1 & 0xff);
226 }
227
228 /* Read a 32 bit word from a file. The data is assumed to be little
229 endian. */
230
231 static unsigned long
232 get_long (e, msg)
233 FILE *e;
234 const char *msg;
235 {
236 int b1, b2, b3, b4;
237
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));
248 }
249
250 /* Read data from a file. This is a wrapper to do error checking. */
251
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;
258 {
259 unsigned long got;
260
261 got = fread (p, 1, c, e);
262 if (got == c)
263 return;
264
265 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
266 }
267 \f
268 /* Define an accelerator resource. */
269
270 void
271 define_accelerator (id, resinfo, data)
272 struct res_id id;
273 const struct res_res_info *resinfo;
274 struct accelerator *data;
275 {
276 struct res_resource *r;
277
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;
283 }
284
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. */
288
289 #define BITMAP_SKIP (14)
290
291 void
292 define_bitmap (id, resinfo, filename)
293 struct res_id id;
294 const struct res_res_info *resinfo;
295 const char *filename;
296 {
297 FILE *e;
298 char *real_filename;
299 struct stat s;
300 unsigned char *data;
301 int i;
302 struct res_resource *r;
303
304 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
305
306 if (stat (real_filename, &s) < 0)
307 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
308 strerror (errno));
309
310 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
311
312 for (i = 0; i < BITMAP_SKIP; i++)
313 getc (e);
314
315 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
316
317 fclose (e);
318 free (real_filename);
319
320 r = define_standard_resource (&resources, RT_BITMAP, id,
321 resinfo->language, 0);
322
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;
327 }
328
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. */
334
335 void
336 define_cursor (id, resinfo, filename)
337 struct res_id id;
338 const struct res_res_info *resinfo;
339 const char *filename;
340 {
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;
348
349 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
350
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. */
355
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);
361
362 /* Read in the icon directory entries. */
363
364 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
365
366 for (i = 0; i < count; i++)
367 {
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);
376
377 if (feof (e))
378 unexpected_eof (real_filename);
379 }
380
381 /* Define each cursor as a unique resource. */
382
383 first_cursor = cursors;
384
385 for (i = 0; i < count; i++)
386 {
387 unsigned char *data;
388 struct res_id name;
389 struct cursor *c;
390
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));
394
395 data = (unsigned char *) res_alloc (icondirs[i].bytes);
396
397 get_data (e, data, icondirs[i].bytes, real_filename);
398
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;
404
405 ++cursors;
406
407 name.named = 0;
408 name.u.id = cursors;
409
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;
415 }
416
417 fclose (e);
418 free (real_filename);
419
420 /* Define a cursor group resource. */
421
422 first = NULL;
423 pp = &first;
424 for (i = 0; i < count; i++)
425 {
426 struct group_cursor *cg;
427
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;
432
433 /* FIXME: What should these be set to? */
434 cg->planes = 1;
435 cg->bits = 1;
436
437 cg->bytes = icondirs[i].bytes + 4;
438 cg->index = first_cursor + i + 1;
439
440 *pp = cg;
441 pp = &(*pp)->next;
442 }
443
444 free (icondirs);
445
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;
451 }
452
453 /* Define a dialog resource. */
454
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;
460 {
461 struct dialog *copy;
462 struct res_resource *r;
463
464 copy = (struct dialog *) res_alloc (sizeof *copy);
465 *copy = *dialog;
466
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;
472 }
473
474 /* Define a dialog control. This does not define a resource, but
475 merely allocates and fills in a structure. */
476
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;
488 {
489 struct dialog_control *n;
490
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
505 {
506 n->text.named = 0;
507 n->text.u.id = 0;
508 }
509 n->data = NULL;
510 n->help = 0;
511
512 return n;
513 }
514
515 /* Define a font resource. */
516
517 void
518 define_font (id, resinfo, filename)
519 struct res_id id;
520 const struct res_res_info *resinfo;
521 const char *filename;
522 {
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;
534
535 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
536
537 if (stat (real_filename, &s) < 0)
538 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
539 strerror (errno));
540
541 data = (unsigned char *) res_alloc (s.st_size);
542
543 get_data (e, data, s.st_size, real_filename);
544
545 fclose (e);
546 free (real_filename);
547
548 r = define_standard_resource (&resources, RT_FONT, id,
549 resinfo->language, 0);
550
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;
555
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. */
560
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 = "";
569
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 = "";
578
579 ++fonts;
580
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);
586
587 fd = (struct fontdir *) res_alloc (sizeof *fd);
588 fd->next = NULL;
589 fd->index = fonts;
590 fd->length = fontdatalength;
591 fd->data = fontdata;
592
593 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
594 ;
595 *pp = fd;
596
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;
600 }
601
602 /* Define the fontdirs resource. This is called after the entire rc
603 file has been parsed, if any font resources were seen. */
604
605 static void
606 define_fontdirs ()
607 {
608 struct res_resource *r;
609 struct res_id id;
610
611 id.named = 0;
612 id.u.id = 1;
613
614 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
615
616 r->type = RES_TYPE_FONTDIR;
617 r->u.fontdir = fontdirs;
618 r->res_info = fontdirs_resinfo;
619 }
620
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. */
626
627 void
628 define_icon (id, resinfo, filename)
629 struct res_id id;
630 const struct res_res_info *resinfo;
631 const char *filename;
632 {
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;
640
641 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
642
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. */
646
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);
652
653 /* Read in the icon directory entries. */
654
655 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
656
657 for (i = 0; i < count; i++)
658 {
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);
667
668 if (feof (e))
669 unexpected_eof (real_filename);
670 }
671
672 /* Define each icon as a unique resource. */
673
674 first_icon = icons;
675
676 for (i = 0; i < count; i++)
677 {
678 unsigned char *data;
679 struct res_id name;
680
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));
684
685 data = (unsigned char *) res_alloc (icondirs[i].bytes);
686
687 get_data (e, data, icondirs[i].bytes, real_filename);
688
689 ++icons;
690
691 name.named = 0;
692 name.u.id = icons;
693
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;
700 }
701
702 fclose (e);
703 free (real_filename);
704
705 /* Define an icon group resource. */
706
707 first = NULL;
708 pp = &first;
709 for (i = 0; i < count; i++)
710 {
711 struct group_icon *cg;
712
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. */
716
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;
722
723 cg->planes = 1;
724 cg->bits = 0;
725 while ((1 << cg->bits) < cg->colors)
726 ++cg->bits;
727
728 cg->bytes = icondirs[i].bytes;
729 cg->index = first_icon + i + 1;
730
731 *pp = cg;
732 pp = &(*pp)->next;
733 }
734
735 free (icondirs);
736
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;
742 }
743
744 /* Define a menu resource. */
745
746 void
747 define_menu (id, resinfo, menuitems)
748 struct res_id id;
749 const struct res_res_info *resinfo;
750 struct menuitem *menuitems;
751 {
752 struct menu *m;
753 struct res_resource *r;
754
755 m = (struct menu *) res_alloc (sizeof *m);
756 m->items = menuitems;
757 m->help = 0;
758
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;
763 }
764
765 /* Define a menu item. This does not define a resource, but merely
766 allocates and fills in a structure. */
767
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;
776 {
777 struct menuitem *mi;
778
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;
791 }
792
793 /* Define a messagetable resource. */
794
795 void
796 define_messagetable (id, resinfo, filename)
797 struct res_id id;
798 const struct res_res_info *resinfo;
799 const char *filename;
800 {
801 FILE *e;
802 char *real_filename;
803 struct stat s;
804 unsigned char *data;
805 struct res_resource *r;
806
807 e = open_file_search (filename, FOPEN_RB, "messagetable file",
808 &real_filename);
809
810 if (stat (real_filename, &s) < 0)
811 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
812 strerror (errno));
813
814 data = (unsigned char *) res_alloc (s.st_size);
815
816 get_data (e, data, s.st_size, real_filename);
817
818 fclose (e);
819 free (real_filename);
820
821 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
822 resinfo->language, 0);
823
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;
828 }
829
830 /* Define an rcdata resource. */
831
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;
837 {
838 struct res_resource *r;
839
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;
845 }
846
847 /* Create an rcdata item holding a string. */
848
849 struct rcdata_item *
850 define_rcdata_string (string, len)
851 const char *string;
852 unsigned long len;
853 {
854 struct rcdata_item *ri;
855 char *s;
856
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;
864
865 return ri;
866 }
867
868 /* Create an rcdata item holding a number. */
869
870 struct rcdata_item *
871 define_rcdata_number (val, dword)
872 unsigned long val;
873 int dword;
874 {
875 struct rcdata_item *ri;
876
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;
881
882 return ri;
883 }
884
885 /* Define a stringtable resource. This is called for each string
886 which appears in a STRINGTABLE statement. */
887
888 void
889 define_stringtable (resinfo, stringid, string)
890 const struct res_res_info *resinfo;
891 unsigned long stringid;
892 const char *string;
893 {
894 struct res_id id;
895 struct res_resource *r;
896
897 id.named = 0;
898 id.u.id = (stringid >> 4) + 1;
899 r = define_standard_resource (&resources, RT_STRING, id,
900 resinfo->language, 1);
901
902 if (r->type == RES_TYPE_UNINITIALIZED)
903 {
904 int i;
905
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++)
910 {
911 r->u.stringtable->strings[i].length = 0;
912 r->u.stringtable->strings[i].string = NULL;
913 }
914
915 r->res_info = *resinfo;
916 }
917
918 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
919 &r->u.stringtable->strings[stringid & 0xf].string,
920 string);
921 }
922
923 /* Define a user data resource where the data is in the rc file. */
924
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;
931 {
932 struct res_id ids[3];
933 struct res_resource *r;
934
935 ids[0] = type;
936 ids[1] = id;
937 ids[2].named = 0;
938 ids[2].u.id = resinfo->language;
939
940 r = define_resource (&resources, 3, ids, 0);
941 r->type = RES_TYPE_USERDATA;
942 r->u.userdata = data;
943 r->res_info = *resinfo;
944 }
945
946 /* Define a user data resource where the data is in a file. */
947
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;
954 {
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;
961
962 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
963
964 if (stat (real_filename, &s) < 0)
965 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
966 strerror (errno));
967
968 data = (unsigned char *) res_alloc (s.st_size);
969
970 get_data (e, data, s.st_size, real_filename);
971
972 fclose (e);
973 free (real_filename);
974
975 ids[0] = type;
976 ids[1] = id;
977 ids[2].named = 0;
978 ids[2].u.id = resinfo->language;
979
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;
989 }
990
991 /* Define a versioninfo resource. */
992
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;
999 {
1000 struct res_resource *r;
1001
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;
1009 }
1010
1011 /* Add string version info to a list of version information. */
1012
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;
1018 {
1019 struct ver_info *vi, **pp;
1020
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;
1026
1027 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1028 ;
1029 *pp = vi;
1030
1031 return verinfo;
1032 }
1033
1034 /* Add variable version info to a list of version information. */
1035
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;
1041 {
1042 struct ver_info *vi, **pp;
1043
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;
1049
1050 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1051 ;
1052 *pp = vi;
1053
1054 return verinfo;
1055 }
1056
1057 /* Append version string information to a list. */
1058
1059 struct ver_stringinfo *
1060 append_verval (strings, key, value)
1061 struct ver_stringinfo *strings;
1062 const char *key;
1063 const char *value;
1064 {
1065 struct ver_stringinfo *vs, **pp;
1066
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);
1071
1072 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1073 ;
1074 *pp = vs;
1075
1076 return strings;
1077 }
1078
1079 /* Append version variable information to a list. */
1080
1081 struct ver_varinfo *
1082 append_vertrans (var, language, charset)
1083 struct ver_varinfo *var;
1084 unsigned long language;
1085 unsigned long charset;
1086 {
1087 struct ver_varinfo *vv, **pp;
1088
1089 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1090 vv->next = NULL;
1091 vv->language = language;
1092 vv->charset = charset;
1093
1094 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1095 ;
1096 *pp = vv;
1097
1098 return var;
1099 }
1100 \f
1101 /* Local functions used to write out an rc file. */
1102
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 *));
1132
1133 /* Indent a given number of spaces. */
1134
1135 static void
1136 indent (e, c)
1137 FILE *e;
1138 int c;
1139 {
1140 int i;
1141
1142 for (i = 0; i < c; i++)
1143 putc (' ', e);
1144 }
1145
1146 /* Dump the resources we have read in the format of an rc file.
1147
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. */
1155
1156 void
1157 write_rc_file (filename, resources)
1158 const char *filename;
1159 const struct res_directory *resources;
1160 {
1161 FILE *e;
1162 int language;
1163
1164 if (filename == NULL)
1165 e = stdout;
1166 else
1167 {
1168 e = fopen (filename, FOPEN_WT);
1169 if (e == NULL)
1170 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1171 }
1172
1173 language = -1;
1174 write_rc_directory (e, resources, (const struct res_id *) NULL,
1175 (const struct res_id *) NULL, &language, 1);
1176 }
1177
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. */
1183
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;
1192 {
1193 const struct res_entry *re;
1194
1195 /* Print out some COFF information that rc files can't represent. */
1196
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);
1203
1204 for (re = rd->entries; re != NULL; re = re->next)
1205 {
1206 switch (level)
1207 {
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;
1215
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;
1221
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)
1228 {
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;
1232 }
1233 break;
1234
1235 default:
1236 break;
1237 }
1238
1239 if (re->subdir)
1240 write_rc_subdir (e, re, type, name, language, level);
1241 else
1242 {
1243 if (level == 3)
1244 {
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);
1251 }
1252 else
1253 {
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);
1257 }
1258 }
1259 }
1260 }
1261
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. */
1266
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;
1275 {
1276 fprintf (e, "\n");
1277 switch (level)
1278 {
1279 case 1:
1280 fprintf (e, "// Type: ");
1281 if (re->id.named)
1282 res_id_print (e, re->id, 1);
1283 else
1284 {
1285 const char *s;
1286
1287 switch (re->id.u.id)
1288 {
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;
1309 }
1310
1311 if (s != NULL)
1312 fprintf (e, "%s", s);
1313 else
1314 res_id_print (e, re->id, 1);
1315 }
1316 fprintf (e, "\n");
1317 break;
1318
1319 case 2:
1320 fprintf (e, "// Name: ");
1321 res_id_print (e, re->id, 1);
1322 fprintf (e, "\n");
1323 break;
1324
1325 case 3:
1326 fprintf (e, "// Language: ");
1327 res_id_print (e, re->id, 1);
1328 fprintf (e, "\n");
1329 break;
1330
1331 default:
1332 fprintf (e, "// Level %d: ", level);
1333 res_id_print (e, re->id, 1);
1334 fprintf (e, "\n");
1335 }
1336
1337 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1338 }
1339
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. */
1345
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;
1353 {
1354 const char *s;
1355 int rt;
1356 int menuex = 0;
1357
1358 fprintf (e, "\n");
1359
1360 switch (res->type)
1361 {
1362 default:
1363 abort ();
1364
1365 case RES_TYPE_ACCELERATOR:
1366 s = "ACCELERATOR";
1367 rt = RT_ACCELERATOR;
1368 break;
1369
1370 case RES_TYPE_BITMAP:
1371 s = "BITMAP";
1372 rt = RT_BITMAP;
1373 break;
1374
1375 case RES_TYPE_CURSOR:
1376 s = "CURSOR";
1377 rt = RT_CURSOR;
1378 break;
1379
1380 case RES_TYPE_GROUP_CURSOR:
1381 s = "GROUP_CURSOR";
1382 rt = RT_GROUP_CURSOR;
1383 break;
1384
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;
1392
1393 case RES_TYPE_FONT:
1394 s = "FONT";
1395 rt = RT_FONT;
1396 break;
1397
1398 case RES_TYPE_FONTDIR:
1399 s = "FONTDIR";
1400 rt = RT_FONTDIR;
1401 break;
1402
1403 case RES_TYPE_ICON:
1404 s = "ICON";
1405 rt = RT_ICON;
1406 break;
1407
1408 case RES_TYPE_GROUP_ICON:
1409 s = "GROUP_ICON";
1410 rt = RT_GROUP_ICON;
1411 break;
1412
1413 case RES_TYPE_MENU:
1414 if (extended_menu (res->u.menu))
1415 {
1416 s = "MENUEX";
1417 menuex = 1;
1418 }
1419 else
1420 {
1421 s = "MENU";
1422 menuex = 0;
1423 }
1424 rt = RT_MENU;
1425 break;
1426
1427 case RES_TYPE_MESSAGETABLE:
1428 s = "MESSAGETABLE";
1429 rt = RT_MESSAGETABLE;
1430 break;
1431
1432 case RES_TYPE_RCDATA:
1433 s = "RCDATA";
1434 rt = RT_RCDATA;
1435 break;
1436
1437 case RES_TYPE_STRINGTABLE:
1438 s = "STRINGTABLE";
1439 rt = RT_STRING;
1440 break;
1441
1442 case RES_TYPE_USERDATA:
1443 s = NULL;
1444 rt = 0;
1445 break;
1446
1447 case RES_TYPE_VERSIONINFO:
1448 s = "VERSIONINFO";
1449 rt = RT_VERSION;
1450 break;
1451 }
1452
1453 if (rt != 0
1454 && type != NULL
1455 && (type->named || type->u.id != (unsigned long) rt))
1456 {
1457 fprintf (e, "// Unexpected resource type mismatch: ");
1458 res_id_print (e, *type, 1);
1459 fprintf (e, " != %d", rt);
1460 }
1461
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);
1466
1467 if (name != NULL)
1468 res_id_print (e, *name, 0);
1469 else
1470 fprintf (e, "??Unknown-Name??");
1471
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??");
1479
1480 if (res->res_info.memflags != 0)
1481 {
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");
1490 }
1491
1492 if (res->type == RES_TYPE_DIALOG)
1493 {
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);
1499 }
1500
1501 fprintf (e, "\n");
1502
1503 if ((res->res_info.language != 0 && res->res_info.language != *language)
1504 || res->res_info.characteristics != 0
1505 || res->res_info.version != 0)
1506 {
1507 int modifiers;
1508
1509 switch (res->type)
1510 {
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;
1518
1519 default:
1520 modifiers = 0;
1521 break;
1522 }
1523
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);
1537 }
1538
1539 switch (res->type)
1540 {
1541 default:
1542 abort ();
1543
1544 case RES_TYPE_ACCELERATOR:
1545 write_rc_accelerators (e, res->u.acc);
1546 break;
1547
1548 case RES_TYPE_CURSOR:
1549 write_rc_cursor (e, res->u.cursor);
1550 break;
1551
1552 case RES_TYPE_GROUP_CURSOR:
1553 write_rc_group_cursor (e, res->u.group_cursor);
1554 break;
1555
1556 case RES_TYPE_DIALOG:
1557 write_rc_dialog (e, res->u.dialog);
1558 break;
1559
1560 case RES_TYPE_FONTDIR:
1561 write_rc_fontdir (e, res->u.fontdir);
1562 break;
1563
1564 case RES_TYPE_GROUP_ICON:
1565 write_rc_group_icon (e, res->u.group_icon);
1566 break;
1567
1568 case RES_TYPE_MENU:
1569 write_rc_menu (e, res->u.menu, menuex);
1570 break;
1571
1572 case RES_TYPE_RCDATA:
1573 write_rc_rcdata (e, res->u.rcdata, 0);
1574 break;
1575
1576 case RES_TYPE_STRINGTABLE:
1577 write_rc_stringtable (e, name, res->u.stringtable);
1578 break;
1579
1580 case RES_TYPE_USERDATA:
1581 write_rc_rcdata (e, res->u.userdata, 0);
1582 break;
1583
1584 case RES_TYPE_VERSIONINFO:
1585 write_rc_versioninfo (e, res->u.versioninfo);
1586 break;
1587
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;
1594 }
1595 }
1596
1597 /* Write out accelerator information. */
1598
1599 static void
1600 write_rc_accelerators (e, accelerators)
1601 FILE *e;
1602 const struct accelerator *accelerators;
1603 {
1604 const struct accelerator *acc;
1605
1606 fprintf (e, "BEGIN\n");
1607 for (acc = accelerators; acc != NULL; acc = acc->next)
1608 {
1609 int printable;
1610
1611 fprintf (e, " ");
1612
1613 if ((acc->key & 0x7f) == acc->key
1614 && isprint ((unsigned char) acc->key)
1615 && (acc->flags & ACC_VIRTKEY) == 0)
1616 {
1617 fprintf (e, "\"%c\"", acc->key);
1618 printable = 1;
1619 }
1620 else
1621 {
1622 fprintf (e, "%d", acc->key);
1623 printable = 0;
1624 }
1625
1626 fprintf (e, ", %d", acc->id);
1627
1628 if (! printable)
1629 {
1630 if ((acc->flags & ACC_VIRTKEY) != 0)
1631 fprintf (e, ", VIRTKEY");
1632 else
1633 fprintf (e, ", ASCII");
1634 }
1635
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");
1642
1643 fprintf (e, "\n");
1644 }
1645
1646 fprintf (e, "END\n");
1647 }
1648
1649 /* Write out cursor information. This would normally be in a separate
1650 file, which the rc file would include. */
1651
1652 static void
1653 write_rc_cursor (e, cursor)
1654 FILE *e;
1655 const struct cursor *cursor;
1656 {
1657 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1658 cursor->yhotspot);
1659 write_rc_filedata (e, cursor->length, cursor->data);
1660 }
1661
1662 /* Write out group cursor data. This would normally be built from the
1663 cursor data. */
1664
1665 static void
1666 write_rc_group_cursor (e, group_cursor)
1667 FILE *e;
1668 const struct group_cursor *group_cursor;
1669 {
1670 const struct group_cursor *gc;
1671
1672 for (gc = group_cursor; gc != NULL; gc = gc->next)
1673 {
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);
1678 }
1679 }
1680
1681 /* Write dialog data. */
1682
1683 static void
1684 write_rc_dialog (e, dialog)
1685 FILE *e;
1686 const struct dialog *dialog;
1687 {
1688 const struct dialog_control *control;
1689
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)
1696 {
1697 fprintf (e, "CLASS ");
1698 res_id_print (e, dialog->class, 0);
1699 fprintf (e, "\n");
1700 }
1701 if (dialog->caption != NULL)
1702 {
1703 fprintf (e, "CAPTION \"");
1704 unicode_print (e, dialog->caption, -1);
1705 fprintf (e, "\"\n");
1706 }
1707 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
1708 || dialog->menu.u.id != 0)
1709 {
1710 fprintf (e, "MENU ");
1711 res_id_print (e, dialog->menu, 0);
1712 fprintf (e, "\n");
1713 }
1714 if (dialog->font != NULL)
1715 {
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");
1723 }
1724
1725 fprintf (e, "BEGIN\n");
1726
1727 for (control = dialog->controls; control != NULL; control = control->next)
1728 write_rc_dialog_control (e, control);
1729
1730 fprintf (e, "END\n");
1731 }
1732
1733 /* For each predefined control keyword, this table provides the class
1734 and the style. */
1735
1736 struct control_info
1737 {
1738 const char *name;
1739 unsigned short class;
1740 unsigned long style;
1741 };
1742
1743 static const struct control_info control_info[] =
1744 {
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 }
1767 };
1768
1769 /* Write a dialog control. */
1770
1771 static void
1772 write_rc_dialog_control (e, control)
1773 FILE *e;
1774 const struct dialog_control *control;
1775 {
1776 const struct control_info *ci;
1777
1778 fprintf (e, " ");
1779
1780 if (control->class.named)
1781 ci = NULL;
1782 else
1783 {
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;
1789 }
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");
1796
1797 if (control->text.named || control->text.u.id != 0)
1798 {
1799 fprintf (e, " ");
1800 res_id_print (e, control->text, 1);
1801 fprintf (e, ",");
1802 }
1803
1804 fprintf (e, " %d, ", control->id);
1805
1806 if (ci == NULL)
1807 {
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);
1814 }
1815
1816 fprintf (e, "%d, %d", control->x, control->y);
1817
1818 if (control->style != SS_ICON
1819 || control->exstyle != 0
1820 || control->width != 0
1821 || control->height != 0
1822 || control->help != 0)
1823 {
1824 fprintf (e, ", %d, %d", control->width, control->height);
1825
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);
1830
1831 if (control->exstyle != 0 || control->help != 0)
1832 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1833 }
1834
1835 fprintf (e, "\n");
1836
1837 if (control->data != NULL)
1838 write_rc_rcdata (e, control->data, 2);
1839 }
1840
1841 /* Write out font directory data. This would normally be built from
1842 the font data. */
1843
1844 static void
1845 write_rc_fontdir (e, fontdir)
1846 FILE *e;
1847 const struct fontdir *fontdir;
1848 {
1849 const struct fontdir *fc;
1850
1851 for (fc = fontdir; fc != NULL; fc = fc->next)
1852 {
1853 fprintf (e, "// Font index: %d\n", fc->index);
1854 write_rc_filedata (e, fc->length, fc->data);
1855 }
1856 }
1857
1858 /* Write out group icon data. This would normally be built from the
1859 icon data. */
1860
1861 static void
1862 write_rc_group_icon (e, group_icon)
1863 FILE *e;
1864 const struct group_icon *group_icon;
1865 {
1866 const struct group_icon *gi;
1867
1868 for (gi = group_icon; gi != NULL; gi = gi->next)
1869 {
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);
1874 }
1875 }
1876
1877 /* Write out a menu resource. */
1878
1879 static void
1880 write_rc_menu (e, menu, menuex)
1881 FILE *e;
1882 const struct menu *menu;
1883 int menuex;
1884 {
1885 if (menu->help != 0)
1886 fprintf (e, "// Help ID: %lu\n", menu->help);
1887 write_rc_menuitems (e, menu->items, menuex, 0);
1888 }
1889
1890 /* Write out menuitems. */
1891
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;
1898 {
1899 const struct menuitem *mi;
1900
1901 indent (e, ind);
1902 fprintf (e, "BEGIN\n");
1903
1904 for (mi = menuitems; mi != NULL; mi = mi->next)
1905 {
1906 indent (e, ind + 2);
1907
1908 if (mi->popup == NULL)
1909 fprintf (e, "MENUITEM");
1910 else
1911 fprintf (e, "POPUP");
1912
1913 if (! menuex
1914 && mi->popup == NULL
1915 && mi->text == NULL
1916 && mi->type == 0
1917 && mi->id == 0)
1918 {
1919 fprintf (e, " SEPARATOR\n");
1920 continue;
1921 }
1922
1923 if (mi->text == NULL)
1924 fprintf (e, " \"\"");
1925 else
1926 {
1927 fprintf (e, " \"");
1928 unicode_print (e, mi->text, -1);
1929 fprintf (e, "\"");
1930 }
1931
1932 if (! menuex)
1933 {
1934 if (mi->popup == NULL)
1935 fprintf (e, ", %d", mi->id);
1936
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");
1949 }
1950 else
1951 {
1952 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
1953 {
1954 fprintf (e, ", %d", mi->id);
1955 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
1956 {
1957 fprintf (e, ", %lu", mi->type);
1958 if (mi->state != 0 || mi->help != 0)
1959 {
1960 fprintf (e, ", %lu", mi->state);
1961 if (mi->help != 0)
1962 fprintf (e, ", %lu", mi->help);
1963 }
1964 }
1965 }
1966 }
1967
1968 fprintf (e, "\n");
1969
1970 if (mi->popup != NULL)
1971 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
1972 }
1973
1974 indent (e, ind);
1975 fprintf (e, "END\n");
1976 }
1977
1978 /* Write out an rcdata resource. This is also used for other types of
1979 resources that need to print arbitrary data. */
1980
1981 static void
1982 write_rc_rcdata (e, rcdata, ind)
1983 FILE *e;
1984 const struct rcdata_item *rcdata;
1985 int ind;
1986 {
1987 const struct rcdata_item *ri;
1988
1989 indent (e, ind);
1990 fprintf (e, "BEGIN\n");
1991
1992 for (ri = rcdata; ri != NULL; ri = ri->next)
1993 {
1994 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
1995 continue;
1996
1997 indent (e, ind + 2);
1998
1999 switch (ri->type)
2000 {
2001 default:
2002 abort ();
2003
2004 case RCDATA_WORD:
2005 fprintf (e, "%d", ri->u.word);
2006 break;
2007
2008 case RCDATA_DWORD:
2009 fprintf (e, "%luL", ri->u.dword);
2010 break;
2011
2012 case RCDATA_STRING:
2013 {
2014 const char *s;
2015 unsigned long i;
2016
2017 fprintf (e, "\"");
2018 s = ri->u.string.s;
2019 for (i = 0; i < ri->u.string.length; i++)
2020 {
2021 if (isprint ((unsigned char) *s))
2022 putc (*s, e);
2023 else
2024 fprintf (e, "\\%03o", *s);
2025 }
2026 fprintf (e, "\"");
2027 break;
2028 }
2029
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;
2035
2036 case RCDATA_BUFFER:
2037 {
2038 unsigned long i;
2039 int first;
2040
2041 /* Assume little endian data. */
2042
2043 first = 1;
2044 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2045 {
2046 unsigned long l;
2047
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
2055 {
2056 fprintf (e, ",\n");
2057 indent (e, ind + 2);
2058 }
2059 fprintf (e, "%luL", l);
2060 }
2061
2062 if (i + 1 < ri->u.buffer.length)
2063 {
2064 int i;
2065
2066 i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2067 if (first)
2068 first = 0;
2069 else
2070 {
2071 fprintf (e, ",\n");
2072 indent (e, ind + 2);
2073 }
2074 fprintf (e, "%d", i);
2075 i += 2;
2076 }
2077
2078 if (i < ri->u.buffer.length)
2079 {
2080 if (first)
2081 first = 0;
2082 else
2083 {
2084 fprintf (e, ",\n");
2085 indent (e, ind + 2);
2086 }
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]);
2092 }
2093
2094 break;
2095 }
2096 }
2097
2098 if (ri->next != NULL)
2099 fprintf (e, ",");
2100 fprintf (e, "\n");
2101 }
2102
2103 indent (e, ind);
2104 fprintf (e, "END\n");
2105 }
2106
2107 /* Write out a stringtable resource. */
2108
2109 static void
2110 write_rc_stringtable (e, name, stringtable)
2111 FILE *e;
2112 const struct res_id *name;
2113 const struct stringtable *stringtable;
2114 {
2115 unsigned long offset;
2116 int i;
2117
2118 if (name != NULL && ! name->named)
2119 offset = (name->u.id - 1) << 4;
2120 else
2121 {
2122 fprintf (e, "// %s string table name\n",
2123 name == NULL ? "Missing" : "Invalid");
2124 offset = 0;
2125 }
2126
2127 fprintf (e, "BEGIN\n");
2128
2129 for (i = 0; i < 16; i++)
2130 {
2131 if (stringtable->strings[i].length != 0)
2132 {
2133 fprintf (e, " %lu, \"", offset + i);
2134 unicode_print (e, stringtable->strings[i].string,
2135 stringtable->strings[i].length);
2136 fprintf (e, "\"\n");
2137 }
2138 }
2139
2140 fprintf (e, "END\n");
2141 }
2142
2143 /* Write out a versioninfo resource. */
2144
2145 static void
2146 write_rc_versioninfo (e, versioninfo)
2147 FILE *e;
2148 const struct versioninfo *versioninfo;
2149 {
2150 const struct fixed_versioninfo *f;
2151 const struct ver_info *vi;
2152
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);
2178
2179 fprintf (e, "BEGIN\n");
2180
2181 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2182 {
2183 switch (vi->type)
2184 {
2185 case VERINFO_STRING:
2186 {
2187 const struct ver_stringinfo *vs;
2188
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");
2195
2196 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2197 {
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");
2203 }
2204
2205 fprintf (e, " END\n");
2206 fprintf (e, " END\n");
2207 break;
2208 }
2209
2210 case VERINFO_VAR:
2211 {
2212 const struct ver_varinfo *vv;
2213
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, "\"");
2219
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);
2223
2224 fprintf (e, "\n END\n");
2225
2226 break;
2227 }
2228 }
2229 }
2230
2231 fprintf (e, "END\n");
2232 }
2233
2234 /* Write out data which would normally be read from a file. */
2235
2236 static void
2237 write_rc_filedata (e, length, data)
2238 FILE *e;
2239 unsigned long length;
2240 const unsigned char *data;
2241 {
2242 unsigned long i;
2243
2244 for (i = 0; i + 15 < length; i += 16)
2245 {
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]);
2253 }
2254
2255 if (i < length)
2256 {
2257 fprintf (e, "// %4lx:", i);
2258 while (i < length)
2259 {
2260 fprintf (e, " %02x", data[i]);
2261 ++i;
2262 }
2263 fprintf (e, "\n");
2264 }
2265 }