resrc.c revision 38889
138889Sjdp/* resrc.c -- read and write Windows rc files. 238889Sjdp Copyright 1997, 1998 Free Software Foundation, Inc. 338889Sjdp Written by Ian Lance Taylor, Cygnus Support. 438889Sjdp 538889Sjdp This file is part of GNU Binutils. 638889Sjdp 738889Sjdp This program is free software; you can redistribute it and/or modify 838889Sjdp it under the terms of the GNU General Public License as published by 938889Sjdp the Free Software Foundation; either version 2 of the License, or 1038889Sjdp (at your option) any later version. 1138889Sjdp 1238889Sjdp This program is distributed in the hope that it will be useful, 1338889Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1438889Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1538889Sjdp GNU General Public License for more details. 1638889Sjdp 1738889Sjdp You should have received a copy of the GNU General Public License 1838889Sjdp along with this program; if not, write to the Free Software 1938889Sjdp Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 2038889Sjdp 02111-1307, USA. */ 2138889Sjdp 2238889Sjdp/* This file contains functions that read and write Windows rc files. 2338889Sjdp These are text files that represent resources. */ 2438889Sjdp 2538889Sjdp#include "bfd.h" 2638889Sjdp#include "bucomm.h" 2738889Sjdp#include "libiberty.h" 2838889Sjdp#include "windres.h" 2938889Sjdp 3038889Sjdp#include <assert.h> 3138889Sjdp#include <ctype.h> 3238889Sjdp#include <sys/stat.h> 3338889Sjdp 3438889Sjdp#if defined (_WIN32) && ! defined (__CYGWIN32__) 3538889Sjdp#define popen _popen 3638889Sjdp#define pclose _pclose 3738889Sjdp#endif 3838889Sjdp 3938889Sjdp/* The default preprocessor. */ 4038889Sjdp 4138889Sjdp#define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED" 4238889Sjdp 4338889Sjdp/* We read the directory entries in a cursor or icon file into 4438889Sjdp instances of this structure. */ 4538889Sjdp 4638889Sjdpstruct icondir 4738889Sjdp{ 4838889Sjdp /* Width of image. */ 4938889Sjdp unsigned char width; 5038889Sjdp /* Height of image. */ 5138889Sjdp unsigned char height; 5238889Sjdp /* Number of colors in image. */ 5338889Sjdp unsigned char colorcount; 5438889Sjdp union 5538889Sjdp { 5638889Sjdp struct 5738889Sjdp { 5838889Sjdp /* Color planes. */ 5938889Sjdp unsigned short planes; 6038889Sjdp /* Bits per pixel. */ 6138889Sjdp unsigned short bits; 6238889Sjdp } icon; 6338889Sjdp struct 6438889Sjdp { 6538889Sjdp /* X coordinate of hotspot. */ 6638889Sjdp unsigned short xhotspot; 6738889Sjdp /* Y coordinate of hotspot. */ 6838889Sjdp unsigned short yhotspot; 6938889Sjdp } cursor; 7038889Sjdp } u; 7138889Sjdp /* Bytes in image. */ 7238889Sjdp unsigned long bytes; 7338889Sjdp /* File offset of image. */ 7438889Sjdp unsigned long offset; 7538889Sjdp}; 7638889Sjdp 7738889Sjdp/* The name of the rc file we are reading. */ 7838889Sjdp 7938889Sjdpchar *rc_filename; 8038889Sjdp 8138889Sjdp/* The line number in the rc file. */ 8238889Sjdp 8338889Sjdpint rc_lineno; 8438889Sjdp 8538889Sjdp/* The pipe we are reading from, so that we can close it if we exit. */ 8638889Sjdp 8738889Sjdpstatic FILE *cpp_pipe; 8838889Sjdp 8938889Sjdp/* As we read the rc file, we attach information to this structure. */ 9038889Sjdp 9138889Sjdpstatic struct res_directory *resources; 9238889Sjdp 9338889Sjdp/* The number of cursor resources we have written out. */ 9438889Sjdp 9538889Sjdpstatic int cursors; 9638889Sjdp 9738889Sjdp/* The number of font resources we have written out. */ 9838889Sjdp 9938889Sjdpstatic int fonts; 10038889Sjdp 10138889Sjdp/* Font directory information. */ 10238889Sjdp 10338889Sjdpstruct fontdir *fontdirs; 10438889Sjdp 10538889Sjdp/* Resource info to use for fontdirs. */ 10638889Sjdp 10738889Sjdpstruct res_res_info fontdirs_resinfo; 10838889Sjdp 10938889Sjdp/* The number of icon resources we have written out. */ 11038889Sjdp 11138889Sjdpstatic int icons; 11238889Sjdp 11338889Sjdp/* Local functions. */ 11438889Sjdp 11538889Sjdpstatic void close_pipe PARAMS ((void)); 11638889Sjdpstatic void unexpected_eof PARAMS ((const char *)); 11738889Sjdpstatic int get_word PARAMS ((FILE *, const char *)); 11838889Sjdpstatic unsigned long get_long PARAMS ((FILE *, const char *)); 11938889Sjdpstatic void get_data 12038889Sjdp PARAMS ((FILE *, unsigned char *, unsigned long, const char *)); 12138889Sjdpstatic void define_fontdirs PARAMS ((void)); 12238889Sjdp 12338889Sjdp/* Read an rc file. */ 12438889Sjdp 12538889Sjdpstruct res_directory * 12638889Sjdpread_rc_file (filename, preprocessor, preprocargs, language) 12738889Sjdp const char *filename; 12838889Sjdp const char *preprocessor; 12938889Sjdp const char *preprocargs; 13038889Sjdp int language; 13138889Sjdp{ 13238889Sjdp char *cmd; 13338889Sjdp 13438889Sjdp if (preprocessor == NULL) 13538889Sjdp preprocessor = DEFAULT_PREPROCESSOR; 13638889Sjdp 13738889Sjdp if (preprocargs == NULL) 13838889Sjdp preprocargs = ""; 13938889Sjdp if (filename == NULL) 14038889Sjdp filename = "-"; 14138889Sjdp 14238889Sjdp cmd = xmalloc (strlen (preprocessor) 14338889Sjdp + strlen (preprocargs) 14438889Sjdp + strlen (filename) 14538889Sjdp + 10); 14638889Sjdp sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename); 14738889Sjdp 14838889Sjdp cpp_pipe = popen (cmd, FOPEN_RT); 14938889Sjdp if (cpp_pipe == NULL) 15038889Sjdp fatal ("can't popen `%s': %s", cmd, strerror (errno)); 15138889Sjdp free (cmd); 15238889Sjdp 15338889Sjdp xatexit (close_pipe); 15438889Sjdp 15538889Sjdp rc_filename = xstrdup (filename); 15638889Sjdp rc_lineno = 1; 15738889Sjdp if (language != -1) 15838889Sjdp rcparse_set_language (language); 15938889Sjdp yyin = cpp_pipe; 16038889Sjdp yyparse (); 16138889Sjdp 16238889Sjdp if (pclose (cpp_pipe) != 0) 16338889Sjdp fprintf (stderr, "%s: warning: preprocessor failed\n", program_name); 16438889Sjdp cpp_pipe = NULL; 16538889Sjdp 16638889Sjdp if (fontdirs != NULL) 16738889Sjdp define_fontdirs (); 16838889Sjdp 16938889Sjdp free (rc_filename); 17038889Sjdp rc_filename = NULL; 17138889Sjdp 17238889Sjdp return resources; 17338889Sjdp} 17438889Sjdp 17538889Sjdp/* Close the pipe if it is open. This is called via xatexit. */ 17638889Sjdp 17738889Sjdpvoid 17838889Sjdpclose_pipe () 17938889Sjdp{ 18038889Sjdp if (cpp_pipe != NULL) 18138889Sjdp pclose (cpp_pipe); 18238889Sjdp} 18338889Sjdp 18438889Sjdp/* Report an error while reading an rc file. */ 18538889Sjdp 18638889Sjdpvoid 18738889Sjdpyyerror (msg) 18838889Sjdp const char *msg; 18938889Sjdp{ 19038889Sjdp fatal ("%s:%d: %s", rc_filename, rc_lineno, msg); 19138889Sjdp} 19238889Sjdp 19338889Sjdp/* Issue a warning while reading an rc file. */ 19438889Sjdp 19538889Sjdpvoid 19638889Sjdprcparse_warning (msg) 19738889Sjdp const char *msg; 19838889Sjdp{ 19938889Sjdp fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg); 20038889Sjdp} 20138889Sjdp 20238889Sjdp/* Die if we get an unexpected end of file. */ 20338889Sjdp 20438889Sjdpstatic void 20538889Sjdpunexpected_eof (msg) 20638889Sjdp const char *msg; 20738889Sjdp{ 20838889Sjdp fatal ("%s: unexpected EOF", msg); 20938889Sjdp} 21038889Sjdp 21138889Sjdp/* Read a 16 bit word from a file. The data is assumed to be little 21238889Sjdp endian. */ 21338889Sjdp 21438889Sjdpstatic int 21538889Sjdpget_word (e, msg) 21638889Sjdp FILE *e; 21738889Sjdp const char *msg; 21838889Sjdp{ 21938889Sjdp int b1, b2; 22038889Sjdp 22138889Sjdp b1 = getc (e); 22238889Sjdp b2 = getc (e); 22338889Sjdp if (feof (e)) 22438889Sjdp unexpected_eof (msg); 22538889Sjdp return ((b2 & 0xff) << 8) | (b1 & 0xff); 22638889Sjdp} 22738889Sjdp 22838889Sjdp/* Read a 32 bit word from a file. The data is assumed to be little 22938889Sjdp endian. */ 23038889Sjdp 23138889Sjdpstatic unsigned long 23238889Sjdpget_long (e, msg) 23338889Sjdp FILE *e; 23438889Sjdp const char *msg; 23538889Sjdp{ 23638889Sjdp int b1, b2, b3, b4; 23738889Sjdp 23838889Sjdp b1 = getc (e); 23938889Sjdp b2 = getc (e); 24038889Sjdp b3 = getc (e); 24138889Sjdp b4 = getc (e); 24238889Sjdp if (feof (e)) 24338889Sjdp unexpected_eof (msg); 24438889Sjdp return (((((((b4 & 0xff) << 8) 24538889Sjdp | (b3 & 0xff)) << 8) 24638889Sjdp | (b2 & 0xff)) << 8) 24738889Sjdp | (b1 & 0xff)); 24838889Sjdp} 24938889Sjdp 25038889Sjdp/* Read data from a file. This is a wrapper to do error checking. */ 25138889Sjdp 25238889Sjdpstatic void 25338889Sjdpget_data (e, p, c, msg) 25438889Sjdp FILE *e; 25538889Sjdp unsigned char *p; 25638889Sjdp unsigned long c; 25738889Sjdp const char *msg; 25838889Sjdp{ 25938889Sjdp unsigned long got; 26038889Sjdp 26138889Sjdp got = fread (p, 1, c, e); 26238889Sjdp if (got == c) 26338889Sjdp return; 26438889Sjdp 26538889Sjdp fatal ("%s: read of %lu returned %lu", msg, c, got); 26638889Sjdp} 26738889Sjdp 26838889Sjdp/* Define an accelerator resource. */ 26938889Sjdp 27038889Sjdpvoid 27138889Sjdpdefine_accelerator (id, resinfo, data) 27238889Sjdp struct res_id id; 27338889Sjdp const struct res_res_info *resinfo; 27438889Sjdp struct accelerator *data; 27538889Sjdp{ 27638889Sjdp struct res_resource *r; 27738889Sjdp 27838889Sjdp r = define_standard_resource (&resources, RT_ACCELERATORS, id, 27938889Sjdp resinfo->language, 0); 28038889Sjdp r->type = RES_TYPE_ACCELERATOR; 28138889Sjdp r->u.acc = data; 28238889Sjdp r->res_info = *resinfo; 28338889Sjdp} 28438889Sjdp 28538889Sjdp/* Define a bitmap resource. Bitmap data is stored in a file. The 28638889Sjdp first 14 bytes of the file are a standard header, which is not 28738889Sjdp included in the resource data. */ 28838889Sjdp 28938889Sjdp#define BITMAP_SKIP (14) 29038889Sjdp 29138889Sjdpvoid 29238889Sjdpdefine_bitmap (id, resinfo, filename) 29338889Sjdp struct res_id id; 29438889Sjdp const struct res_res_info *resinfo; 29538889Sjdp const char *filename; 29638889Sjdp{ 29738889Sjdp FILE *e; 29838889Sjdp char *real_filename; 29938889Sjdp struct stat s; 30038889Sjdp unsigned char *data; 30138889Sjdp int i; 30238889Sjdp struct res_resource *r; 30338889Sjdp 30438889Sjdp e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename); 30538889Sjdp 30638889Sjdp if (stat (real_filename, &s) < 0) 30738889Sjdp fatal ("stat failed on bitmap file `%s': %s", real_filename, 30838889Sjdp strerror (errno)); 30938889Sjdp 31038889Sjdp data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP); 31138889Sjdp 31238889Sjdp for (i = 0; i < BITMAP_SKIP; i++) 31338889Sjdp getc (e); 31438889Sjdp 31538889Sjdp get_data (e, data, s.st_size - BITMAP_SKIP, real_filename); 31638889Sjdp 31738889Sjdp fclose (e); 31838889Sjdp free (real_filename); 31938889Sjdp 32038889Sjdp r = define_standard_resource (&resources, RT_BITMAP, id, 32138889Sjdp resinfo->language, 0); 32238889Sjdp 32338889Sjdp r->type = RES_TYPE_BITMAP; 32438889Sjdp r->u.data.length = s.st_size - BITMAP_SKIP; 32538889Sjdp r->u.data.data = data; 32638889Sjdp r->res_info = *resinfo; 32738889Sjdp} 32838889Sjdp 32938889Sjdp/* Define a cursor resource. A cursor file may contain a set of 33038889Sjdp bitmaps, each representing the same cursor at various different 33138889Sjdp resolutions. They each get written out with a different ID. The 33238889Sjdp real cursor resource is then a group resource which can be used to 33338889Sjdp select one of the actual cursors. */ 33438889Sjdp 33538889Sjdpvoid 33638889Sjdpdefine_cursor (id, resinfo, filename) 33738889Sjdp struct res_id id; 33838889Sjdp const struct res_res_info *resinfo; 33938889Sjdp const char *filename; 34038889Sjdp{ 34138889Sjdp FILE *e; 34238889Sjdp char *real_filename; 34338889Sjdp int type, count, i; 34438889Sjdp struct icondir *icondirs; 34538889Sjdp int first_cursor; 34638889Sjdp struct res_resource *r; 34738889Sjdp struct group_cursor *first, **pp; 34838889Sjdp 34938889Sjdp e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename); 35038889Sjdp 35138889Sjdp /* A cursor file is basically an icon file. The start of the file 35238889Sjdp is a three word structure. The first word is ignored. The 35338889Sjdp second word is the type of data. The third word is the number of 35438889Sjdp entries. */ 35538889Sjdp 35638889Sjdp get_word (e, real_filename); 35738889Sjdp type = get_word (e, real_filename); 35838889Sjdp count = get_word (e, real_filename); 35938889Sjdp if (type != 2) 36038889Sjdp fatal ("cursor file `%s' does not contain cursor data", real_filename); 36138889Sjdp 36238889Sjdp /* Read in the icon directory entries. */ 36338889Sjdp 36438889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 36538889Sjdp 36638889Sjdp for (i = 0; i < count; i++) 36738889Sjdp { 36838889Sjdp icondirs[i].width = getc (e); 36938889Sjdp icondirs[i].height = getc (e); 37038889Sjdp icondirs[i].colorcount = getc (e); 37138889Sjdp getc (e); 37238889Sjdp icondirs[i].u.cursor.xhotspot = get_word (e, real_filename); 37338889Sjdp icondirs[i].u.cursor.yhotspot = get_word (e, real_filename); 37438889Sjdp icondirs[i].bytes = get_long (e, real_filename); 37538889Sjdp icondirs[i].offset = get_long (e, real_filename); 37638889Sjdp 37738889Sjdp if (feof (e)) 37838889Sjdp unexpected_eof (real_filename); 37938889Sjdp } 38038889Sjdp 38138889Sjdp /* Define each cursor as a unique resource. */ 38238889Sjdp 38338889Sjdp first_cursor = cursors; 38438889Sjdp 38538889Sjdp for (i = 0; i < count; i++) 38638889Sjdp { 38738889Sjdp unsigned char *data; 38838889Sjdp struct res_id name; 38938889Sjdp struct cursor *c; 39038889Sjdp 39138889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 39238889Sjdp fatal ("%s: fseek to %lu failed: %s", real_filename, 39338889Sjdp icondirs[i].offset, strerror (errno)); 39438889Sjdp 39538889Sjdp data = (unsigned char *) res_alloc (icondirs[i].bytes); 39638889Sjdp 39738889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 39838889Sjdp 39938889Sjdp c = (struct cursor *) res_alloc (sizeof *c); 40038889Sjdp c->xhotspot = icondirs[i].u.cursor.xhotspot; 40138889Sjdp c->yhotspot = icondirs[i].u.cursor.yhotspot; 40238889Sjdp c->length = icondirs[i].bytes; 40338889Sjdp c->data = data; 40438889Sjdp 40538889Sjdp ++cursors; 40638889Sjdp 40738889Sjdp name.named = 0; 40838889Sjdp name.u.id = cursors; 40938889Sjdp 41038889Sjdp r = define_standard_resource (&resources, RT_CURSOR, name, 41138889Sjdp resinfo->language, 0); 41238889Sjdp r->type = RES_TYPE_CURSOR; 41338889Sjdp r->u.cursor = c; 41438889Sjdp r->res_info = *resinfo; 41538889Sjdp } 41638889Sjdp 41738889Sjdp fclose (e); 41838889Sjdp free (real_filename); 41938889Sjdp 42038889Sjdp /* Define a cursor group resource. */ 42138889Sjdp 42238889Sjdp first = NULL; 42338889Sjdp pp = &first; 42438889Sjdp for (i = 0; i < count; i++) 42538889Sjdp { 42638889Sjdp struct group_cursor *cg; 42738889Sjdp 42838889Sjdp cg = (struct group_cursor *) res_alloc (sizeof *cg); 42938889Sjdp cg->next = NULL; 43038889Sjdp cg->width = icondirs[i].width; 43138889Sjdp cg->height = 2 * icondirs[i].height; 43238889Sjdp 43338889Sjdp /* FIXME: What should these be set to? */ 43438889Sjdp cg->planes = 1; 43538889Sjdp cg->bits = 1; 43638889Sjdp 43738889Sjdp cg->bytes = icondirs[i].bytes + 4; 43838889Sjdp cg->index = first_cursor + i + 1; 43938889Sjdp 44038889Sjdp *pp = cg; 44138889Sjdp pp = &(*pp)->next; 44238889Sjdp } 44338889Sjdp 44438889Sjdp free (icondirs); 44538889Sjdp 44638889Sjdp r = define_standard_resource (&resources, RT_GROUP_CURSOR, id, 44738889Sjdp resinfo->language, 0); 44838889Sjdp r->type = RES_TYPE_GROUP_CURSOR; 44938889Sjdp r->u.group_cursor = first; 45038889Sjdp r->res_info = *resinfo; 45138889Sjdp} 45238889Sjdp 45338889Sjdp/* Define a dialog resource. */ 45438889Sjdp 45538889Sjdpvoid 45638889Sjdpdefine_dialog (id, resinfo, dialog) 45738889Sjdp struct res_id id; 45838889Sjdp const struct res_res_info *resinfo; 45938889Sjdp const struct dialog *dialog; 46038889Sjdp{ 46138889Sjdp struct dialog *copy; 46238889Sjdp struct res_resource *r; 46338889Sjdp 46438889Sjdp copy = (struct dialog *) res_alloc (sizeof *copy); 46538889Sjdp *copy = *dialog; 46638889Sjdp 46738889Sjdp r = define_standard_resource (&resources, RT_DIALOG, id, 46838889Sjdp resinfo->language, 0); 46938889Sjdp r->type = RES_TYPE_DIALOG; 47038889Sjdp r->u.dialog = copy; 47138889Sjdp r->res_info = *resinfo; 47238889Sjdp} 47338889Sjdp 47438889Sjdp/* Define a dialog control. This does not define a resource, but 47538889Sjdp merely allocates and fills in a structure. */ 47638889Sjdp 47738889Sjdpstruct dialog_control * 47838889Sjdpdefine_control (text, id, x, y, width, height, class, style, exstyle) 47938889Sjdp const char *text; 48038889Sjdp unsigned long id; 48138889Sjdp unsigned long x; 48238889Sjdp unsigned long y; 48338889Sjdp unsigned long width; 48438889Sjdp unsigned long height; 48538889Sjdp unsigned long class; 48638889Sjdp unsigned long style; 48738889Sjdp unsigned long exstyle; 48838889Sjdp{ 48938889Sjdp struct dialog_control *n; 49038889Sjdp 49138889Sjdp n = (struct dialog_control *) res_alloc (sizeof *n); 49238889Sjdp n->next = NULL; 49338889Sjdp n->id = id; 49438889Sjdp n->style = style; 49538889Sjdp n->exstyle = exstyle; 49638889Sjdp n->x = x; 49738889Sjdp n->y = y; 49838889Sjdp n->width = width; 49938889Sjdp n->height = height; 50038889Sjdp n->class.named = 0; 50138889Sjdp n->class.u.id = class; 50238889Sjdp if (text != NULL) 50338889Sjdp res_string_to_id (&n->text, text); 50438889Sjdp else 50538889Sjdp { 50638889Sjdp n->text.named = 0; 50738889Sjdp n->text.u.id = 0; 50838889Sjdp } 50938889Sjdp n->data = NULL; 51038889Sjdp n->help = 0; 51138889Sjdp 51238889Sjdp return n; 51338889Sjdp} 51438889Sjdp 51538889Sjdp/* Define a font resource. */ 51638889Sjdp 51738889Sjdpvoid 51838889Sjdpdefine_font (id, resinfo, filename) 51938889Sjdp struct res_id id; 52038889Sjdp const struct res_res_info *resinfo; 52138889Sjdp const char *filename; 52238889Sjdp{ 52338889Sjdp FILE *e; 52438889Sjdp char *real_filename; 52538889Sjdp struct stat s; 52638889Sjdp unsigned char *data; 52738889Sjdp struct res_resource *r; 52838889Sjdp long offset; 52938889Sjdp long fontdatalength; 53038889Sjdp unsigned char *fontdata; 53138889Sjdp struct fontdir *fd; 53238889Sjdp const char *device, *face; 53338889Sjdp struct fontdir **pp; 53438889Sjdp 53538889Sjdp e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); 53638889Sjdp 53738889Sjdp if (stat (real_filename, &s) < 0) 53838889Sjdp fatal ("stat failed on bitmap file `%s': %s", real_filename, 53938889Sjdp strerror (errno)); 54038889Sjdp 54138889Sjdp data = (unsigned char *) res_alloc (s.st_size); 54238889Sjdp 54338889Sjdp get_data (e, data, s.st_size, real_filename); 54438889Sjdp 54538889Sjdp fclose (e); 54638889Sjdp free (real_filename); 54738889Sjdp 54838889Sjdp r = define_standard_resource (&resources, RT_FONT, id, 54938889Sjdp resinfo->language, 0); 55038889Sjdp 55138889Sjdp r->type = RES_TYPE_FONT; 55238889Sjdp r->u.data.length = s.st_size; 55338889Sjdp r->u.data.data = data; 55438889Sjdp r->res_info = *resinfo; 55538889Sjdp 55638889Sjdp /* For each font resource, we must add an entry in the FONTDIR 55738889Sjdp resource. The FONTDIR resource includes some strings in the font 55838889Sjdp file. To find them, we have to do some magic on the data we have 55938889Sjdp read. */ 56038889Sjdp 56138889Sjdp offset = ((((((data[47] << 8) 56238889Sjdp | data[46]) << 8) 56338889Sjdp | data[45]) << 8) 56438889Sjdp | data[44]); 56538889Sjdp if (offset > 0 && offset < s.st_size) 56638889Sjdp device = (char *) data + offset; 56738889Sjdp else 56838889Sjdp device = ""; 56938889Sjdp 57038889Sjdp offset = ((((((data[51] << 8) 57138889Sjdp | data[50]) << 8) 57238889Sjdp | data[49]) << 8) 57338889Sjdp | data[48]); 57438889Sjdp if (offset > 0 && offset < s.st_size) 57538889Sjdp face = (char *) data + offset; 57638889Sjdp else 57738889Sjdp face = ""; 57838889Sjdp 57938889Sjdp ++fonts; 58038889Sjdp 58138889Sjdp fontdatalength = 58 + strlen (device) + strlen (face); 58238889Sjdp fontdata = (unsigned char *) res_alloc (fontdatalength); 58338889Sjdp memcpy (fontdata, data, 56); 58438889Sjdp strcpy ((char *) fontdata + 56, device); 58538889Sjdp strcpy ((char *) fontdata + 57 + strlen (device), face); 58638889Sjdp 58738889Sjdp fd = (struct fontdir *) res_alloc (sizeof *fd); 58838889Sjdp fd->next = NULL; 58938889Sjdp fd->index = fonts; 59038889Sjdp fd->length = fontdatalength; 59138889Sjdp fd->data = fontdata; 59238889Sjdp 59338889Sjdp for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next) 59438889Sjdp ; 59538889Sjdp *pp = fd; 59638889Sjdp 59738889Sjdp /* For the single fontdirs resource, we always use the resource 59838889Sjdp information of the last font. I don't know what else to do. */ 59938889Sjdp fontdirs_resinfo = *resinfo; 60038889Sjdp} 60138889Sjdp 60238889Sjdp/* Define the fontdirs resource. This is called after the entire rc 60338889Sjdp file has been parsed, if any font resources were seen. */ 60438889Sjdp 60538889Sjdpstatic void 60638889Sjdpdefine_fontdirs () 60738889Sjdp{ 60838889Sjdp struct res_resource *r; 60938889Sjdp struct res_id id; 61038889Sjdp 61138889Sjdp id.named = 0; 61238889Sjdp id.u.id = 1; 61338889Sjdp 61438889Sjdp r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0); 61538889Sjdp 61638889Sjdp r->type = RES_TYPE_FONTDIR; 61738889Sjdp r->u.fontdir = fontdirs; 61838889Sjdp r->res_info = fontdirs_resinfo; 61938889Sjdp} 62038889Sjdp 62138889Sjdp/* Define an icon resource. An icon file may contain a set of 62238889Sjdp bitmaps, each representing the same icon at various different 62338889Sjdp resolutions. They each get written out with a different ID. The 62438889Sjdp real icon resource is then a group resource which can be used to 62538889Sjdp select one of the actual icon bitmaps. */ 62638889Sjdp 62738889Sjdpvoid 62838889Sjdpdefine_icon (id, resinfo, filename) 62938889Sjdp struct res_id id; 63038889Sjdp const struct res_res_info *resinfo; 63138889Sjdp const char *filename; 63238889Sjdp{ 63338889Sjdp FILE *e; 63438889Sjdp char *real_filename; 63538889Sjdp int type, count, i; 63638889Sjdp struct icondir *icondirs; 63738889Sjdp int first_icon; 63838889Sjdp struct res_resource *r; 63938889Sjdp struct group_icon *first, **pp; 64038889Sjdp 64138889Sjdp e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename); 64238889Sjdp 64338889Sjdp /* The start of an icon file is a three word structure. The first 64438889Sjdp word is ignored. The second word is the type of data. The third 64538889Sjdp word is the number of entries. */ 64638889Sjdp 64738889Sjdp get_word (e, real_filename); 64838889Sjdp type = get_word (e, real_filename); 64938889Sjdp count = get_word (e, real_filename); 65038889Sjdp if (type != 1) 65138889Sjdp fatal ("icon file `%s' does not contain icon data", real_filename); 65238889Sjdp 65338889Sjdp /* Read in the icon directory entries. */ 65438889Sjdp 65538889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 65638889Sjdp 65738889Sjdp for (i = 0; i < count; i++) 65838889Sjdp { 65938889Sjdp icondirs[i].width = getc (e); 66038889Sjdp icondirs[i].height = getc (e); 66138889Sjdp icondirs[i].colorcount = getc (e); 66238889Sjdp getc (e); 66338889Sjdp icondirs[i].u.icon.planes = get_word (e, real_filename); 66438889Sjdp icondirs[i].u.icon.bits = get_word (e, real_filename); 66538889Sjdp icondirs[i].bytes = get_long (e, real_filename); 66638889Sjdp icondirs[i].offset = get_long (e, real_filename); 66738889Sjdp 66838889Sjdp if (feof (e)) 66938889Sjdp unexpected_eof (real_filename); 67038889Sjdp } 67138889Sjdp 67238889Sjdp /* Define each icon as a unique resource. */ 67338889Sjdp 67438889Sjdp first_icon = icons; 67538889Sjdp 67638889Sjdp for (i = 0; i < count; i++) 67738889Sjdp { 67838889Sjdp unsigned char *data; 67938889Sjdp struct res_id name; 68038889Sjdp 68138889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 68238889Sjdp fatal ("%s: fseek to %lu failed: %s", real_filename, 68338889Sjdp icondirs[i].offset, strerror (errno)); 68438889Sjdp 68538889Sjdp data = (unsigned char *) res_alloc (icondirs[i].bytes); 68638889Sjdp 68738889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 68838889Sjdp 68938889Sjdp ++icons; 69038889Sjdp 69138889Sjdp name.named = 0; 69238889Sjdp name.u.id = icons; 69338889Sjdp 69438889Sjdp r = define_standard_resource (&resources, RT_ICON, name, 69538889Sjdp resinfo->language, 0); 69638889Sjdp r->type = RES_TYPE_ICON; 69738889Sjdp r->u.data.length = icondirs[i].bytes; 69838889Sjdp r->u.data.data = data; 69938889Sjdp r->res_info = *resinfo; 70038889Sjdp } 70138889Sjdp 70238889Sjdp fclose (e); 70338889Sjdp free (real_filename); 70438889Sjdp 70538889Sjdp /* Define an icon group resource. */ 70638889Sjdp 70738889Sjdp first = NULL; 70838889Sjdp pp = &first; 70938889Sjdp for (i = 0; i < count; i++) 71038889Sjdp { 71138889Sjdp struct group_icon *cg; 71238889Sjdp 71338889Sjdp /* For some reason, at least in some files the planes and bits 71438889Sjdp are zero. We instead set them from the color. This is 71538889Sjdp copied from rcl. */ 71638889Sjdp 71738889Sjdp cg = (struct group_icon *) res_alloc (sizeof *cg); 71838889Sjdp cg->next = NULL; 71938889Sjdp cg->width = icondirs[i].width; 72038889Sjdp cg->height = icondirs[i].height; 72138889Sjdp cg->colors = icondirs[i].colorcount; 72238889Sjdp 72338889Sjdp cg->planes = 1; 72438889Sjdp cg->bits = 0; 72538889Sjdp while ((1 << cg->bits) < cg->colors) 72638889Sjdp ++cg->bits; 72738889Sjdp 72838889Sjdp cg->bytes = icondirs[i].bytes; 72938889Sjdp cg->index = first_icon + i + 1; 73038889Sjdp 73138889Sjdp *pp = cg; 73238889Sjdp pp = &(*pp)->next; 73338889Sjdp } 73438889Sjdp 73538889Sjdp free (icondirs); 73638889Sjdp 73738889Sjdp r = define_standard_resource (&resources, RT_GROUP_ICON, id, 73838889Sjdp resinfo->language, 0); 73938889Sjdp r->type = RES_TYPE_GROUP_ICON; 74038889Sjdp r->u.group_icon = first; 74138889Sjdp r->res_info = *resinfo; 74238889Sjdp} 74338889Sjdp 74438889Sjdp/* Define a menu resource. */ 74538889Sjdp 74638889Sjdpvoid 74738889Sjdpdefine_menu (id, resinfo, menuitems) 74838889Sjdp struct res_id id; 74938889Sjdp const struct res_res_info *resinfo; 75038889Sjdp struct menuitem *menuitems; 75138889Sjdp{ 75238889Sjdp struct menu *m; 75338889Sjdp struct res_resource *r; 75438889Sjdp 75538889Sjdp m = (struct menu *) res_alloc (sizeof *m); 75638889Sjdp m->items = menuitems; 75738889Sjdp m->help = 0; 75838889Sjdp 75938889Sjdp r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0); 76038889Sjdp r->type = RES_TYPE_MENU; 76138889Sjdp r->u.menu = m; 76238889Sjdp r->res_info = *resinfo; 76338889Sjdp} 76438889Sjdp 76538889Sjdp/* Define a menu item. This does not define a resource, but merely 76638889Sjdp allocates and fills in a structure. */ 76738889Sjdp 76838889Sjdpstruct menuitem * 76938889Sjdpdefine_menuitem (text, menuid, type, state, help, menuitems) 77038889Sjdp const char *text; 77138889Sjdp int menuid; 77238889Sjdp unsigned long type; 77338889Sjdp unsigned long state; 77438889Sjdp unsigned long help; 77538889Sjdp struct menuitem *menuitems; 77638889Sjdp{ 77738889Sjdp struct menuitem *mi; 77838889Sjdp 77938889Sjdp mi = (struct menuitem *) res_alloc (sizeof *mi); 78038889Sjdp mi->next = NULL; 78138889Sjdp mi->type = type; 78238889Sjdp mi->state = state; 78338889Sjdp mi->id = menuid; 78438889Sjdp if (text == NULL) 78538889Sjdp mi->text = NULL; 78638889Sjdp else 78738889Sjdp unicode_from_ascii ((int *) NULL, &mi->text, text); 78838889Sjdp mi->help = help; 78938889Sjdp mi->popup = menuitems; 79038889Sjdp return mi; 79138889Sjdp} 79238889Sjdp 79338889Sjdp/* Define a messagetable resource. */ 79438889Sjdp 79538889Sjdpvoid 79638889Sjdpdefine_messagetable (id, resinfo, filename) 79738889Sjdp struct res_id id; 79838889Sjdp const struct res_res_info *resinfo; 79938889Sjdp const char *filename; 80038889Sjdp{ 80138889Sjdp FILE *e; 80238889Sjdp char *real_filename; 80338889Sjdp struct stat s; 80438889Sjdp unsigned char *data; 80538889Sjdp struct res_resource *r; 80638889Sjdp 80738889Sjdp e = open_file_search (filename, FOPEN_RB, "messagetable file", 80838889Sjdp &real_filename); 80938889Sjdp 81038889Sjdp if (stat (real_filename, &s) < 0) 81138889Sjdp fatal ("stat failed on bitmap file `%s': %s", real_filename, 81238889Sjdp strerror (errno)); 81338889Sjdp 81438889Sjdp data = (unsigned char *) res_alloc (s.st_size); 81538889Sjdp 81638889Sjdp get_data (e, data, s.st_size, real_filename); 81738889Sjdp 81838889Sjdp fclose (e); 81938889Sjdp free (real_filename); 82038889Sjdp 82138889Sjdp r = define_standard_resource (&resources, RT_MESSAGETABLE, id, 82238889Sjdp resinfo->language, 0); 82338889Sjdp 82438889Sjdp r->type = RES_TYPE_MESSAGETABLE; 82538889Sjdp r->u.data.length = s.st_size; 82638889Sjdp r->u.data.data = data; 82738889Sjdp r->res_info = *resinfo; 82838889Sjdp} 82938889Sjdp 83038889Sjdp/* Define an rcdata resource. */ 83138889Sjdp 83238889Sjdpvoid 83338889Sjdpdefine_rcdata (id, resinfo, data) 83438889Sjdp struct res_id id; 83538889Sjdp const struct res_res_info *resinfo; 83638889Sjdp struct rcdata_item *data; 83738889Sjdp{ 83838889Sjdp struct res_resource *r; 83938889Sjdp 84038889Sjdp r = define_standard_resource (&resources, RT_RCDATA, id, 84138889Sjdp resinfo->language, 0); 84238889Sjdp r->type = RES_TYPE_RCDATA; 84338889Sjdp r->u.rcdata = data; 84438889Sjdp r->res_info = *resinfo; 84538889Sjdp} 84638889Sjdp 84738889Sjdp/* Create an rcdata item holding a string. */ 84838889Sjdp 84938889Sjdpstruct rcdata_item * 85038889Sjdpdefine_rcdata_string (string, len) 85138889Sjdp const char *string; 85238889Sjdp unsigned long len; 85338889Sjdp{ 85438889Sjdp struct rcdata_item *ri; 85538889Sjdp char *s; 85638889Sjdp 85738889Sjdp ri = (struct rcdata_item *) res_alloc (sizeof *ri); 85838889Sjdp ri->next = NULL; 85938889Sjdp ri->type = RCDATA_STRING; 86038889Sjdp ri->u.string.length = len; 86138889Sjdp s = (char *) res_alloc (len); 86238889Sjdp memcpy (s, string, len); 86338889Sjdp ri->u.string.s = s; 86438889Sjdp 86538889Sjdp return ri; 86638889Sjdp} 86738889Sjdp 86838889Sjdp/* Create an rcdata item holding a number. */ 86938889Sjdp 87038889Sjdpstruct rcdata_item * 87138889Sjdpdefine_rcdata_number (val, dword) 87238889Sjdp unsigned long val; 87338889Sjdp int dword; 87438889Sjdp{ 87538889Sjdp struct rcdata_item *ri; 87638889Sjdp 87738889Sjdp ri = (struct rcdata_item *) res_alloc (sizeof *ri); 87838889Sjdp ri->next = NULL; 87938889Sjdp ri->type = dword ? RCDATA_DWORD : RCDATA_WORD; 88038889Sjdp ri->u.word = val; 88138889Sjdp 88238889Sjdp return ri; 88338889Sjdp} 88438889Sjdp 88538889Sjdp/* Define a stringtable resource. This is called for each string 88638889Sjdp which appears in a STRINGTABLE statement. */ 88738889Sjdp 88838889Sjdpvoid 88938889Sjdpdefine_stringtable (resinfo, stringid, string) 89038889Sjdp const struct res_res_info *resinfo; 89138889Sjdp unsigned long stringid; 89238889Sjdp const char *string; 89338889Sjdp{ 89438889Sjdp struct res_id id; 89538889Sjdp struct res_resource *r; 89638889Sjdp 89738889Sjdp id.named = 0; 89838889Sjdp id.u.id = (stringid >> 4) + 1; 89938889Sjdp r = define_standard_resource (&resources, RT_STRING, id, 90038889Sjdp resinfo->language, 1); 90138889Sjdp 90238889Sjdp if (r->type == RES_TYPE_UNINITIALIZED) 90338889Sjdp { 90438889Sjdp int i; 90538889Sjdp 90638889Sjdp r->type = RES_TYPE_STRINGTABLE; 90738889Sjdp r->u.stringtable = ((struct stringtable *) 90838889Sjdp res_alloc (sizeof (struct stringtable))); 90938889Sjdp for (i = 0; i < 16; i++) 91038889Sjdp { 91138889Sjdp r->u.stringtable->strings[i].length = 0; 91238889Sjdp r->u.stringtable->strings[i].string = NULL; 91338889Sjdp } 91438889Sjdp 91538889Sjdp r->res_info = *resinfo; 91638889Sjdp } 91738889Sjdp 91838889Sjdp unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length, 91938889Sjdp &r->u.stringtable->strings[stringid & 0xf].string, 92038889Sjdp string); 92138889Sjdp} 92238889Sjdp 92338889Sjdp/* Define a user data resource where the data is in the rc file. */ 92438889Sjdp 92538889Sjdpvoid 92638889Sjdpdefine_user_data (id, type, resinfo, data) 92738889Sjdp struct res_id id; 92838889Sjdp struct res_id type; 92938889Sjdp const struct res_res_info *resinfo; 93038889Sjdp struct rcdata_item *data; 93138889Sjdp{ 93238889Sjdp struct res_id ids[3]; 93338889Sjdp struct res_resource *r; 93438889Sjdp 93538889Sjdp ids[0] = type; 93638889Sjdp ids[1] = id; 93738889Sjdp ids[2].named = 0; 93838889Sjdp ids[2].u.id = resinfo->language; 93938889Sjdp 94038889Sjdp r = define_resource (&resources, 3, ids, 0); 94138889Sjdp r->type = RES_TYPE_USERDATA; 94238889Sjdp r->u.userdata = data; 94338889Sjdp r->res_info = *resinfo; 94438889Sjdp} 94538889Sjdp 94638889Sjdp/* Define a user data resource where the data is in a file. */ 94738889Sjdp 94838889Sjdpvoid 94938889Sjdpdefine_user_file (id, type, resinfo, filename) 95038889Sjdp struct res_id id; 95138889Sjdp struct res_id type; 95238889Sjdp const struct res_res_info *resinfo; 95338889Sjdp const char *filename; 95438889Sjdp{ 95538889Sjdp FILE *e; 95638889Sjdp char *real_filename; 95738889Sjdp struct stat s; 95838889Sjdp unsigned char *data; 95938889Sjdp struct res_id ids[3]; 96038889Sjdp struct res_resource *r; 96138889Sjdp 96238889Sjdp e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); 96338889Sjdp 96438889Sjdp if (stat (real_filename, &s) < 0) 96538889Sjdp fatal ("stat failed on bitmap file `%s': %s", real_filename, 96638889Sjdp strerror (errno)); 96738889Sjdp 96838889Sjdp data = (unsigned char *) res_alloc (s.st_size); 96938889Sjdp 97038889Sjdp get_data (e, data, s.st_size, real_filename); 97138889Sjdp 97238889Sjdp fclose (e); 97338889Sjdp free (real_filename); 97438889Sjdp 97538889Sjdp ids[0] = type; 97638889Sjdp ids[1] = id; 97738889Sjdp ids[2].named = 0; 97838889Sjdp ids[2].u.id = resinfo->language; 97938889Sjdp 98038889Sjdp r = define_resource (&resources, 3, ids, 0); 98138889Sjdp r->type = RES_TYPE_USERDATA; 98238889Sjdp r->u.userdata = ((struct rcdata_item *) 98338889Sjdp res_alloc (sizeof (struct rcdata_item))); 98438889Sjdp r->u.userdata->next = NULL; 98538889Sjdp r->u.userdata->type = RCDATA_BUFFER; 98638889Sjdp r->u.userdata->u.buffer.length = s.st_size; 98738889Sjdp r->u.userdata->u.buffer.data = data; 98838889Sjdp r->res_info = *resinfo; 98938889Sjdp} 99038889Sjdp 99138889Sjdp/* Define a versioninfo resource. */ 99238889Sjdp 99338889Sjdpvoid 99438889Sjdpdefine_versioninfo (id, language, fixedverinfo, verinfo) 99538889Sjdp struct res_id id; 99638889Sjdp int language; 99738889Sjdp struct fixed_versioninfo *fixedverinfo; 99838889Sjdp struct ver_info *verinfo; 99938889Sjdp{ 100038889Sjdp struct res_resource *r; 100138889Sjdp 100238889Sjdp r = define_standard_resource (&resources, RT_VERSION, id, language, 0); 100338889Sjdp r->type = RES_TYPE_VERSIONINFO; 100438889Sjdp r->u.versioninfo = ((struct versioninfo *) 100538889Sjdp res_alloc (sizeof (struct versioninfo))); 100638889Sjdp r->u.versioninfo->fixed = fixedverinfo; 100738889Sjdp r->u.versioninfo->var = verinfo; 100838889Sjdp r->res_info.language = language; 100938889Sjdp} 101038889Sjdp 101138889Sjdp/* Add string version info to a list of version information. */ 101238889Sjdp 101338889Sjdpstruct ver_info * 101438889Sjdpappend_ver_stringfileinfo (verinfo, language, strings) 101538889Sjdp struct ver_info *verinfo; 101638889Sjdp const char *language; 101738889Sjdp struct ver_stringinfo *strings; 101838889Sjdp{ 101938889Sjdp struct ver_info *vi, **pp; 102038889Sjdp 102138889Sjdp vi = (struct ver_info *) res_alloc (sizeof *vi); 102238889Sjdp vi->next = NULL; 102338889Sjdp vi->type = VERINFO_STRING; 102438889Sjdp unicode_from_ascii ((int *) NULL, &vi->u.string.language, language); 102538889Sjdp vi->u.string.strings = strings; 102638889Sjdp 102738889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 102838889Sjdp ; 102938889Sjdp *pp = vi; 103038889Sjdp 103138889Sjdp return verinfo; 103238889Sjdp} 103338889Sjdp 103438889Sjdp/* Add variable version info to a list of version information. */ 103538889Sjdp 103638889Sjdpstruct ver_info * 103738889Sjdpappend_ver_varfileinfo (verinfo, key, var) 103838889Sjdp struct ver_info *verinfo; 103938889Sjdp const char *key; 104038889Sjdp struct ver_varinfo *var; 104138889Sjdp{ 104238889Sjdp struct ver_info *vi, **pp; 104338889Sjdp 104438889Sjdp vi = (struct ver_info *) res_alloc (sizeof *vi); 104538889Sjdp vi->next = NULL; 104638889Sjdp vi->type = VERINFO_VAR; 104738889Sjdp unicode_from_ascii ((int *) NULL, &vi->u.var.key, key); 104838889Sjdp vi->u.var.var = var; 104938889Sjdp 105038889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 105138889Sjdp ; 105238889Sjdp *pp = vi; 105338889Sjdp 105438889Sjdp return verinfo; 105538889Sjdp} 105638889Sjdp 105738889Sjdp/* Append version string information to a list. */ 105838889Sjdp 105938889Sjdpstruct ver_stringinfo * 106038889Sjdpappend_verval (strings, key, value) 106138889Sjdp struct ver_stringinfo *strings; 106238889Sjdp const char *key; 106338889Sjdp const char *value; 106438889Sjdp{ 106538889Sjdp struct ver_stringinfo *vs, **pp; 106638889Sjdp 106738889Sjdp vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); 106838889Sjdp vs->next = NULL; 106938889Sjdp unicode_from_ascii ((int *) NULL, &vs->key, key); 107038889Sjdp unicode_from_ascii ((int *) NULL, &vs->value, value); 107138889Sjdp 107238889Sjdp for (pp = &strings; *pp != NULL; pp = &(*pp)->next) 107338889Sjdp ; 107438889Sjdp *pp = vs; 107538889Sjdp 107638889Sjdp return strings; 107738889Sjdp} 107838889Sjdp 107938889Sjdp/* Append version variable information to a list. */ 108038889Sjdp 108138889Sjdpstruct ver_varinfo * 108238889Sjdpappend_vertrans (var, language, charset) 108338889Sjdp struct ver_varinfo *var; 108438889Sjdp unsigned long language; 108538889Sjdp unsigned long charset; 108638889Sjdp{ 108738889Sjdp struct ver_varinfo *vv, **pp; 108838889Sjdp 108938889Sjdp vv = (struct ver_varinfo *) res_alloc (sizeof *vv); 109038889Sjdp vv->next = NULL; 109138889Sjdp vv->language = language; 109238889Sjdp vv->charset = charset; 109338889Sjdp 109438889Sjdp for (pp = &var; *pp != NULL; pp = &(*pp)->next) 109538889Sjdp ; 109638889Sjdp *pp = vv; 109738889Sjdp 109838889Sjdp return var; 109938889Sjdp} 110038889Sjdp 110138889Sjdp/* Local functions used to write out an rc file. */ 110238889Sjdp 110338889Sjdpstatic void indent PARAMS ((FILE *, int)); 110438889Sjdpstatic void write_rc_directory 110538889Sjdp PARAMS ((FILE *, const struct res_directory *, const struct res_id *, 110638889Sjdp const struct res_id *, int *, int)); 110738889Sjdpstatic void write_rc_subdir 110838889Sjdp PARAMS ((FILE *, const struct res_entry *, const struct res_id *, 110938889Sjdp const struct res_id *, int *, int)); 111038889Sjdpstatic void write_rc_resource 111138889Sjdp PARAMS ((FILE *, const struct res_id *, const struct res_id *, 111238889Sjdp const struct res_resource *, int *)); 111338889Sjdpstatic void write_rc_accelerators 111438889Sjdp PARAMS ((FILE *, const struct accelerator *)); 111538889Sjdpstatic void write_rc_cursor PARAMS ((FILE *, const struct cursor *)); 111638889Sjdpstatic void write_rc_group_cursor 111738889Sjdp PARAMS ((FILE *, const struct group_cursor *)); 111838889Sjdpstatic void write_rc_dialog PARAMS ((FILE *, const struct dialog *)); 111938889Sjdpstatic void write_rc_dialog_control 112038889Sjdp PARAMS ((FILE *, const struct dialog_control *)); 112138889Sjdpstatic void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *)); 112238889Sjdpstatic void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *)); 112338889Sjdpstatic void write_rc_menu PARAMS ((FILE *, const struct menu *, int)); 112438889Sjdpstatic void write_rc_menuitems 112538889Sjdp PARAMS ((FILE *, const struct menuitem *, int, int)); 112638889Sjdpstatic void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int)); 112738889Sjdpstatic void write_rc_stringtable 112838889Sjdp PARAMS ((FILE *, const struct res_id *, const struct stringtable *)); 112938889Sjdpstatic void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *)); 113038889Sjdpstatic void write_rc_filedata 113138889Sjdp PARAMS ((FILE *, unsigned long, const unsigned char *)); 113238889Sjdp 113338889Sjdp/* Indent a given number of spaces. */ 113438889Sjdp 113538889Sjdpstatic void 113638889Sjdpindent (e, c) 113738889Sjdp FILE *e; 113838889Sjdp int c; 113938889Sjdp{ 114038889Sjdp int i; 114138889Sjdp 114238889Sjdp for (i = 0; i < c; i++) 114338889Sjdp putc (' ', e); 114438889Sjdp} 114538889Sjdp 114638889Sjdp/* Dump the resources we have read in the format of an rc file. 114738889Sjdp 114838889Sjdp Actually, we don't use the format of an rc file, because it's way 114938889Sjdp too much of a pain--for example, we'd have to write icon resources 115038889Sjdp into a file and refer to that file. We just generate a readable 115138889Sjdp format that kind of looks like an rc file, and is useful for 115238889Sjdp understanding the contents of a resource file. Someday we may want 115338889Sjdp to generate an rc file which the rc compiler can read; if that day 115438889Sjdp comes, this code will have to be fixed up. */ 115538889Sjdp 115638889Sjdpvoid 115738889Sjdpwrite_rc_file (filename, resources) 115838889Sjdp const char *filename; 115938889Sjdp const struct res_directory *resources; 116038889Sjdp{ 116138889Sjdp FILE *e; 116238889Sjdp int language; 116338889Sjdp 116438889Sjdp if (filename == NULL) 116538889Sjdp e = stdout; 116638889Sjdp else 116738889Sjdp { 116838889Sjdp e = fopen (filename, FOPEN_WT); 116938889Sjdp if (e == NULL) 117038889Sjdp fatal ("can't open `%s' for output: %s", filename, strerror (errno)); 117138889Sjdp } 117238889Sjdp 117338889Sjdp language = -1; 117438889Sjdp write_rc_directory (e, resources, (const struct res_id *) NULL, 117538889Sjdp (const struct res_id *) NULL, &language, 1); 117638889Sjdp} 117738889Sjdp 117838889Sjdp/* Write out a directory. E is the file to write to. RD is the 117938889Sjdp directory. TYPE is a pointer to the level 1 ID which serves as the 118038889Sjdp resource type. NAME is a pointer to the level 2 ID which serves as 118138889Sjdp an individual resource name. LANGUAGE is a pointer to the current 118238889Sjdp language. LEVEL is the level in the tree. */ 118338889Sjdp 118438889Sjdpstatic void 118538889Sjdpwrite_rc_directory (e, rd, type, name, language, level) 118638889Sjdp FILE *e; 118738889Sjdp const struct res_directory *rd; 118838889Sjdp const struct res_id *type; 118938889Sjdp const struct res_id *name; 119038889Sjdp int *language; 119138889Sjdp int level; 119238889Sjdp{ 119338889Sjdp const struct res_entry *re; 119438889Sjdp 119538889Sjdp /* Print out some COFF information that rc files can't represent. */ 119638889Sjdp 119738889Sjdp if (rd->time != 0) 119838889Sjdp fprintf (e, "// Time stamp: %lu\n", rd->time); 119938889Sjdp if (rd->characteristics != 0) 120038889Sjdp fprintf (e, "// Characteristics: %lu\n", rd->characteristics); 120138889Sjdp if (rd->major != 0 || rd->minor != 0) 120238889Sjdp fprintf (e, "// Version: %d %d\n", rd->major, rd->minor); 120338889Sjdp 120438889Sjdp for (re = rd->entries; re != NULL; re = re->next) 120538889Sjdp { 120638889Sjdp switch (level) 120738889Sjdp { 120838889Sjdp case 1: 120938889Sjdp /* If we're at level 1, the key of this resource is the 121038889Sjdp type. This normally duplicates the information we have 121138889Sjdp stored with the resource itself, but we need to remember 121238889Sjdp the type if this is a user define resource type. */ 121338889Sjdp type = &re->id; 121438889Sjdp break; 121538889Sjdp 121638889Sjdp case 2: 121738889Sjdp /* If we're at level 2, the key of this resource is the name 121838889Sjdp we are going to use in the rc printout. */ 121938889Sjdp name = &re->id; 122038889Sjdp break; 122138889Sjdp 122238889Sjdp case 3: 122338889Sjdp /* If we're at level 3, then this key represents a language. 122438889Sjdp Use it to update the current language. */ 122538889Sjdp if (! re->id.named 122638889Sjdp && re->id.u.id != *language 122738889Sjdp && (re->id.u.id & 0xffff) == re->id.u.id) 122838889Sjdp { 122938889Sjdp fprintf (e, "LANGUAGE %lu, %lu\n", 123038889Sjdp re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff); 123138889Sjdp *language = re->id.u.id; 123238889Sjdp } 123338889Sjdp break; 123438889Sjdp 123538889Sjdp default: 123638889Sjdp break; 123738889Sjdp } 123838889Sjdp 123938889Sjdp if (re->subdir) 124038889Sjdp write_rc_subdir (e, re, type, name, language, level); 124138889Sjdp else 124238889Sjdp { 124338889Sjdp if (level == 3) 124438889Sjdp { 124538889Sjdp /* This is the normal case: the three levels are 124638889Sjdp TYPE/NAME/LANGUAGE. NAME will have been set at level 124738889Sjdp 2, and represents the name to use. We probably just 124838889Sjdp set LANGUAGE, and it will probably match what the 124938889Sjdp resource itself records if anything. */ 125038889Sjdp write_rc_resource (e, type, name, re->u.res, language); 125138889Sjdp } 125238889Sjdp else 125338889Sjdp { 125438889Sjdp fprintf (e, "// Resource at unexpected level %d\n", level); 125538889Sjdp write_rc_resource (e, type, (struct res_id *) NULL, re->u.res, 125638889Sjdp language); 125738889Sjdp } 125838889Sjdp } 125938889Sjdp } 126038889Sjdp} 126138889Sjdp 126238889Sjdp/* Write out a subdirectory entry. E is the file to write to. RE is 126338889Sjdp the subdirectory entry. TYPE and NAME are pointers to higher level 126438889Sjdp IDs, or NULL. LANGUAGE is a pointer to the current language. 126538889Sjdp LEVEL is the level in the tree. */ 126638889Sjdp 126738889Sjdpstatic void 126838889Sjdpwrite_rc_subdir (e, re, type, name, language, level) 126938889Sjdp FILE *e; 127038889Sjdp const struct res_entry *re; 127138889Sjdp const struct res_id *type; 127238889Sjdp const struct res_id *name; 127338889Sjdp int *language; 127438889Sjdp int level; 127538889Sjdp{ 127638889Sjdp fprintf (e, "\n"); 127738889Sjdp switch (level) 127838889Sjdp { 127938889Sjdp case 1: 128038889Sjdp fprintf (e, "// Type: "); 128138889Sjdp if (re->id.named) 128238889Sjdp res_id_print (e, re->id, 1); 128338889Sjdp else 128438889Sjdp { 128538889Sjdp const char *s; 128638889Sjdp 128738889Sjdp switch (re->id.u.id) 128838889Sjdp { 128938889Sjdp case RT_CURSOR: s = "cursor"; break; 129038889Sjdp case RT_BITMAP: s = "bitmap"; break; 129138889Sjdp case RT_ICON: s = "icon"; break; 129238889Sjdp case RT_MENU: s = "menu"; break; 129338889Sjdp case RT_DIALOG: s = "dialog"; break; 129438889Sjdp case RT_STRING: s = "stringtable"; break; 129538889Sjdp case RT_FONTDIR: s = "fontdir"; break; 129638889Sjdp case RT_FONT: s = "font"; break; 129738889Sjdp case RT_ACCELERATORS: s = "accelerators"; break; 129838889Sjdp case RT_RCDATA: s = "rcdata"; break; 129938889Sjdp case RT_MESSAGETABLE: s = "messagetable"; break; 130038889Sjdp case RT_GROUP_CURSOR: s = "group cursor"; break; 130138889Sjdp case RT_GROUP_ICON: s = "group icon"; break; 130238889Sjdp case RT_VERSION: s = "version"; break; 130338889Sjdp case RT_DLGINCLUDE: s = "dlginclude"; break; 130438889Sjdp case RT_PLUGPLAY: s = "plugplay"; break; 130538889Sjdp case RT_VXD: s = "vxd"; break; 130638889Sjdp case RT_ANICURSOR: s = "anicursor"; break; 130738889Sjdp case RT_ANIICON: s = "aniicon"; break; 130838889Sjdp default: s = NULL; break; 130938889Sjdp } 131038889Sjdp 131138889Sjdp if (s != NULL) 131238889Sjdp fprintf (e, "%s", s); 131338889Sjdp else 131438889Sjdp res_id_print (e, re->id, 1); 131538889Sjdp } 131638889Sjdp fprintf (e, "\n"); 131738889Sjdp break; 131838889Sjdp 131938889Sjdp case 2: 132038889Sjdp fprintf (e, "// Name: "); 132138889Sjdp res_id_print (e, re->id, 1); 132238889Sjdp fprintf (e, "\n"); 132338889Sjdp break; 132438889Sjdp 132538889Sjdp case 3: 132638889Sjdp fprintf (e, "// Language: "); 132738889Sjdp res_id_print (e, re->id, 1); 132838889Sjdp fprintf (e, "\n"); 132938889Sjdp break; 133038889Sjdp 133138889Sjdp default: 133238889Sjdp fprintf (e, "// Level %d: ", level); 133338889Sjdp res_id_print (e, re->id, 1); 133438889Sjdp fprintf (e, "\n"); 133538889Sjdp } 133638889Sjdp 133738889Sjdp write_rc_directory (e, re->u.dir, type, name, language, level + 1); 133838889Sjdp} 133938889Sjdp 134038889Sjdp/* Write out a single resource. E is the file to write to. TYPE is a 134138889Sjdp pointer to the type of the resource. NAME is a pointer to the name 134238889Sjdp of the resource; it will be NULL if there is a level mismatch. RES 134338889Sjdp is the resource data. LANGUAGE is a pointer to the current 134438889Sjdp language. */ 134538889Sjdp 134638889Sjdpstatic void 134738889Sjdpwrite_rc_resource (e, type, name, res, language) 134838889Sjdp FILE *e; 134938889Sjdp const struct res_id *type; 135038889Sjdp const struct res_id *name; 135138889Sjdp const struct res_resource *res; 135238889Sjdp int *language; 135338889Sjdp{ 135438889Sjdp const char *s; 135538889Sjdp int rt; 135638889Sjdp int menuex = 0; 135738889Sjdp 135838889Sjdp fprintf (e, "\n"); 135938889Sjdp 136038889Sjdp switch (res->type) 136138889Sjdp { 136238889Sjdp default: 136338889Sjdp abort (); 136438889Sjdp 136538889Sjdp case RES_TYPE_ACCELERATOR: 136638889Sjdp s = "ACCELERATOR"; 136738889Sjdp rt = RT_ACCELERATORS; 136838889Sjdp break; 136938889Sjdp 137038889Sjdp case RES_TYPE_BITMAP: 137138889Sjdp s = "BITMAP"; 137238889Sjdp rt = RT_BITMAP; 137338889Sjdp break; 137438889Sjdp 137538889Sjdp case RES_TYPE_CURSOR: 137638889Sjdp s = "CURSOR"; 137738889Sjdp rt = RT_CURSOR; 137838889Sjdp break; 137938889Sjdp 138038889Sjdp case RES_TYPE_GROUP_CURSOR: 138138889Sjdp s = "GROUP_CURSOR"; 138238889Sjdp rt = RT_GROUP_CURSOR; 138338889Sjdp break; 138438889Sjdp 138538889Sjdp case RES_TYPE_DIALOG: 138638889Sjdp if (extended_dialog (res->u.dialog)) 138738889Sjdp s = "DIALOGEX"; 138838889Sjdp else 138938889Sjdp s = "DIALOG"; 139038889Sjdp rt = RT_DIALOG; 139138889Sjdp break; 139238889Sjdp 139338889Sjdp case RES_TYPE_FONT: 139438889Sjdp s = "FONT"; 139538889Sjdp rt = RT_FONT; 139638889Sjdp break; 139738889Sjdp 139838889Sjdp case RES_TYPE_FONTDIR: 139938889Sjdp s = "FONTDIR"; 140038889Sjdp rt = RT_FONTDIR; 140138889Sjdp break; 140238889Sjdp 140338889Sjdp case RES_TYPE_ICON: 140438889Sjdp s = "ICON"; 140538889Sjdp rt = RT_ICON; 140638889Sjdp break; 140738889Sjdp 140838889Sjdp case RES_TYPE_GROUP_ICON: 140938889Sjdp s = "GROUP_ICON"; 141038889Sjdp rt = RT_GROUP_ICON; 141138889Sjdp break; 141238889Sjdp 141338889Sjdp case RES_TYPE_MENU: 141438889Sjdp if (extended_menu (res->u.menu)) 141538889Sjdp { 141638889Sjdp s = "MENUEX"; 141738889Sjdp menuex = 1; 141838889Sjdp } 141938889Sjdp else 142038889Sjdp { 142138889Sjdp s = "MENU"; 142238889Sjdp menuex = 0; 142338889Sjdp } 142438889Sjdp rt = RT_MENU; 142538889Sjdp break; 142638889Sjdp 142738889Sjdp case RES_TYPE_MESSAGETABLE: 142838889Sjdp s = "MESSAGETABLE"; 142938889Sjdp rt = RT_MESSAGETABLE; 143038889Sjdp break; 143138889Sjdp 143238889Sjdp case RES_TYPE_RCDATA: 143338889Sjdp s = "RCDATA"; 143438889Sjdp rt = RT_RCDATA; 143538889Sjdp break; 143638889Sjdp 143738889Sjdp case RES_TYPE_STRINGTABLE: 143838889Sjdp s = "STRINGTABLE"; 143938889Sjdp rt = RT_STRING; 144038889Sjdp break; 144138889Sjdp 144238889Sjdp case RES_TYPE_USERDATA: 144338889Sjdp s = NULL; 144438889Sjdp rt = 0; 144538889Sjdp break; 144638889Sjdp 144738889Sjdp case RES_TYPE_VERSIONINFO: 144838889Sjdp s = "VERSIONINFO"; 144938889Sjdp rt = RT_VERSION; 145038889Sjdp break; 145138889Sjdp } 145238889Sjdp 145338889Sjdp if (rt != 0 145438889Sjdp && type != NULL 145538889Sjdp && (type->named || type->u.id != rt)) 145638889Sjdp { 145738889Sjdp fprintf (e, "// Unexpected resource type mismatch: "); 145838889Sjdp res_id_print (e, *type, 1); 145938889Sjdp fprintf (e, " != %d", rt); 146038889Sjdp } 146138889Sjdp 146238889Sjdp if (res->coff_info.codepage != 0) 146338889Sjdp fprintf (e, "// Code page: %lu\n", res->coff_info.codepage); 146438889Sjdp if (res->coff_info.reserved != 0) 146538889Sjdp fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved); 146638889Sjdp 146738889Sjdp if (name != NULL) 146838889Sjdp res_id_print (e, *name, 0); 146938889Sjdp else 147038889Sjdp fprintf (e, "??Unknown-Name??"); 147138889Sjdp 147238889Sjdp fprintf (e, " "); 147338889Sjdp if (s != NULL) 147438889Sjdp fprintf (e, "%s", s); 147538889Sjdp else if (type != NULL) 147638889Sjdp res_id_print (e, *type, 0); 147738889Sjdp else 147838889Sjdp fprintf (e, "??Unknown-Type??"); 147938889Sjdp 148038889Sjdp if (res->res_info.memflags != 0) 148138889Sjdp { 148238889Sjdp if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0) 148338889Sjdp fprintf (e, " MOVEABLE"); 148438889Sjdp if ((res->res_info.memflags & MEMFLAG_PURE) != 0) 148538889Sjdp fprintf (e, " PURE"); 148638889Sjdp if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0) 148738889Sjdp fprintf (e, " PRELOAD"); 148838889Sjdp if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0) 148938889Sjdp fprintf (e, " DISCARDABLE"); 149038889Sjdp } 149138889Sjdp 149238889Sjdp if (res->type == RES_TYPE_DIALOG) 149338889Sjdp { 149438889Sjdp fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y, 149538889Sjdp res->u.dialog->width, res->u.dialog->height); 149638889Sjdp if (res->u.dialog->ex != NULL 149738889Sjdp && res->u.dialog->ex->help != 0) 149838889Sjdp fprintf (e, ", %lu", res->u.dialog->ex->help); 149938889Sjdp } 150038889Sjdp 150138889Sjdp fprintf (e, "\n"); 150238889Sjdp 150338889Sjdp if ((res->res_info.language != 0 && res->res_info.language != *language) 150438889Sjdp || res->res_info.characteristics != 0 150538889Sjdp || res->res_info.version != 0) 150638889Sjdp { 150738889Sjdp int modifiers; 150838889Sjdp 150938889Sjdp switch (res->type) 151038889Sjdp { 151138889Sjdp case RES_TYPE_ACCELERATOR: 151238889Sjdp case RES_TYPE_DIALOG: 151338889Sjdp case RES_TYPE_MENU: 151438889Sjdp case RES_TYPE_RCDATA: 151538889Sjdp case RES_TYPE_STRINGTABLE: 151638889Sjdp modifiers = 1; 151738889Sjdp break; 151838889Sjdp 151938889Sjdp default: 152038889Sjdp modifiers = 0; 152138889Sjdp break; 152238889Sjdp } 152338889Sjdp 152438889Sjdp if (res->res_info.language != 0 && res->res_info.language != *language) 152538889Sjdp fprintf (e, "%sLANGUAGE %d, %d\n", 152638889Sjdp modifiers ? "// " : "", 152738889Sjdp res->res_info.language & 0xff, 152838889Sjdp (res->res_info.language >> 8) & 0xff); 152938889Sjdp if (res->res_info.characteristics != 0) 153038889Sjdp fprintf (e, "%sCHARACTERISTICS %lu\n", 153138889Sjdp modifiers ? "// " : "", 153238889Sjdp res->res_info.characteristics); 153338889Sjdp if (res->res_info.version != 0) 153438889Sjdp fprintf (e, "%sVERSION %lu\n", 153538889Sjdp modifiers ? "// " : "", 153638889Sjdp res->res_info.version); 153738889Sjdp } 153838889Sjdp 153938889Sjdp switch (res->type) 154038889Sjdp { 154138889Sjdp default: 154238889Sjdp abort (); 154338889Sjdp 154438889Sjdp case RES_TYPE_ACCELERATOR: 154538889Sjdp write_rc_accelerators (e, res->u.acc); 154638889Sjdp break; 154738889Sjdp 154838889Sjdp case RES_TYPE_CURSOR: 154938889Sjdp write_rc_cursor (e, res->u.cursor); 155038889Sjdp break; 155138889Sjdp 155238889Sjdp case RES_TYPE_GROUP_CURSOR: 155338889Sjdp write_rc_group_cursor (e, res->u.group_cursor); 155438889Sjdp break; 155538889Sjdp 155638889Sjdp case RES_TYPE_DIALOG: 155738889Sjdp write_rc_dialog (e, res->u.dialog); 155838889Sjdp break; 155938889Sjdp 156038889Sjdp case RES_TYPE_FONTDIR: 156138889Sjdp write_rc_fontdir (e, res->u.fontdir); 156238889Sjdp break; 156338889Sjdp 156438889Sjdp case RES_TYPE_GROUP_ICON: 156538889Sjdp write_rc_group_icon (e, res->u.group_icon); 156638889Sjdp break; 156738889Sjdp 156838889Sjdp case RES_TYPE_MENU: 156938889Sjdp write_rc_menu (e, res->u.menu, menuex); 157038889Sjdp break; 157138889Sjdp 157238889Sjdp case RES_TYPE_RCDATA: 157338889Sjdp write_rc_rcdata (e, res->u.rcdata, 0); 157438889Sjdp break; 157538889Sjdp 157638889Sjdp case RES_TYPE_STRINGTABLE: 157738889Sjdp write_rc_stringtable (e, name, res->u.stringtable); 157838889Sjdp break; 157938889Sjdp 158038889Sjdp case RES_TYPE_USERDATA: 158138889Sjdp write_rc_rcdata (e, res->u.userdata, 0); 158238889Sjdp break; 158338889Sjdp 158438889Sjdp case RES_TYPE_VERSIONINFO: 158538889Sjdp write_rc_versioninfo (e, res->u.versioninfo); 158638889Sjdp break; 158738889Sjdp 158838889Sjdp case RES_TYPE_BITMAP: 158938889Sjdp case RES_TYPE_FONT: 159038889Sjdp case RES_TYPE_ICON: 159138889Sjdp case RES_TYPE_MESSAGETABLE: 159238889Sjdp write_rc_filedata (e, res->u.data.length, res->u.data.data); 159338889Sjdp break; 159438889Sjdp } 159538889Sjdp} 159638889Sjdp 159738889Sjdp/* Write out accelerator information. */ 159838889Sjdp 159938889Sjdpstatic void 160038889Sjdpwrite_rc_accelerators (e, accelerators) 160138889Sjdp FILE *e; 160238889Sjdp const struct accelerator *accelerators; 160338889Sjdp{ 160438889Sjdp const struct accelerator *acc; 160538889Sjdp 160638889Sjdp fprintf (e, "BEGIN\n"); 160738889Sjdp for (acc = accelerators; acc != NULL; acc = acc->next) 160838889Sjdp { 160938889Sjdp int printable; 161038889Sjdp 161138889Sjdp fprintf (e, " "); 161238889Sjdp 161338889Sjdp if ((acc->key & 0x7f) == acc->key 161438889Sjdp && isprint ((unsigned char) acc->key) 161538889Sjdp && (acc->flags & ACC_VIRTKEY) == 0) 161638889Sjdp { 161738889Sjdp fprintf (e, "\"%c\"", acc->key); 161838889Sjdp printable = 1; 161938889Sjdp } 162038889Sjdp else 162138889Sjdp { 162238889Sjdp fprintf (e, "%d", acc->key); 162338889Sjdp printable = 0; 162438889Sjdp } 162538889Sjdp 162638889Sjdp fprintf (e, ", %d", acc->id); 162738889Sjdp 162838889Sjdp if (! printable) 162938889Sjdp { 163038889Sjdp if ((acc->flags & ACC_VIRTKEY) != 0) 163138889Sjdp fprintf (e, ", VIRTKEY"); 163238889Sjdp else 163338889Sjdp fprintf (e, ", ASCII"); 163438889Sjdp } 163538889Sjdp 163638889Sjdp if ((acc->flags & ACC_SHIFT) != 0) 163738889Sjdp fprintf (e, ", SHIFT"); 163838889Sjdp if ((acc->flags & ACC_CONTROL) != 0) 163938889Sjdp fprintf (e, ", CONTROL"); 164038889Sjdp if ((acc->flags & ACC_ALT) != 0) 164138889Sjdp fprintf (e, ", ALT"); 164238889Sjdp 164338889Sjdp fprintf (e, "\n"); 164438889Sjdp } 164538889Sjdp 164638889Sjdp fprintf (e, "END\n"); 164738889Sjdp} 164838889Sjdp 164938889Sjdp/* Write out cursor information. This would normally be in a separate 165038889Sjdp file, which the rc file would include. */ 165138889Sjdp 165238889Sjdpstatic void 165338889Sjdpwrite_rc_cursor (e, cursor) 165438889Sjdp FILE *e; 165538889Sjdp const struct cursor *cursor; 165638889Sjdp{ 165738889Sjdp fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot, 165838889Sjdp cursor->yhotspot); 165938889Sjdp write_rc_filedata (e, cursor->length, cursor->data); 166038889Sjdp} 166138889Sjdp 166238889Sjdp/* Write out group cursor data. This would normally be built from the 166338889Sjdp cursor data. */ 166438889Sjdp 166538889Sjdpstatic void 166638889Sjdpwrite_rc_group_cursor (e, group_cursor) 166738889Sjdp FILE *e; 166838889Sjdp const struct group_cursor *group_cursor; 166938889Sjdp{ 167038889Sjdp const struct group_cursor *gc; 167138889Sjdp 167238889Sjdp for (gc = group_cursor; gc != NULL; gc = gc->next) 167338889Sjdp { 167438889Sjdp fprintf (e, "// width: %d; height %d; planes %d; bits %d\n", 167538889Sjdp gc->width, gc->height, gc->planes, gc->bits); 167638889Sjdp fprintf (e, "// data bytes: %lu; index: %d\n", 167738889Sjdp gc->bytes, gc->index); 167838889Sjdp } 167938889Sjdp} 168038889Sjdp 168138889Sjdp/* Write dialog data. */ 168238889Sjdp 168338889Sjdpstatic void 168438889Sjdpwrite_rc_dialog (e, dialog) 168538889Sjdp FILE *e; 168638889Sjdp const struct dialog *dialog; 168738889Sjdp{ 168838889Sjdp const struct dialog_control *control; 168938889Sjdp 169038889Sjdp if (dialog->style != 0) 169138889Sjdp fprintf (e, "STYLE 0x%lx\n", dialog->style); 169238889Sjdp if (dialog->exstyle != 0) 169338889Sjdp fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle); 169438889Sjdp if ((dialog->class.named && dialog->class.u.n.length > 0) 169538889Sjdp || dialog->class.u.id != 0) 169638889Sjdp { 169738889Sjdp fprintf (e, "CLASS "); 169838889Sjdp res_id_print (e, dialog->class, 0); 169938889Sjdp fprintf (e, "\n"); 170038889Sjdp } 170138889Sjdp if (dialog->caption != NULL) 170238889Sjdp { 170338889Sjdp fprintf (e, "CAPTION \""); 170438889Sjdp unicode_print (e, dialog->caption, -1); 170538889Sjdp fprintf (e, "\"\n"); 170638889Sjdp } 170738889Sjdp if ((dialog->menu.named && dialog->menu.u.n.length > 0) 170838889Sjdp || dialog->menu.u.id != 0) 170938889Sjdp { 171038889Sjdp fprintf (e, "MENU "); 171138889Sjdp res_id_print (e, dialog->menu, 0); 171238889Sjdp fprintf (e, "\n"); 171338889Sjdp } 171438889Sjdp if (dialog->font != NULL) 171538889Sjdp { 171638889Sjdp fprintf (e, "FONT %d, \"", dialog->pointsize); 171738889Sjdp unicode_print (e, dialog->font, -1); 171838889Sjdp fprintf (e, "\""); 171938889Sjdp if (dialog->ex != NULL 172038889Sjdp && (dialog->ex->weight != 0 || dialog->ex->italic != 0)) 172138889Sjdp fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic); 172238889Sjdp fprintf (e, "\n"); 172338889Sjdp } 172438889Sjdp 172538889Sjdp fprintf (e, "BEGIN\n"); 172638889Sjdp 172738889Sjdp for (control = dialog->controls; control != NULL; control = control->next) 172838889Sjdp write_rc_dialog_control (e, control); 172938889Sjdp 173038889Sjdp fprintf (e, "END\n"); 173138889Sjdp} 173238889Sjdp 173338889Sjdp/* For each predefined control keyword, this table provides the class 173438889Sjdp and the style. */ 173538889Sjdp 173638889Sjdpstruct control_info 173738889Sjdp{ 173838889Sjdp const char *name; 173938889Sjdp unsigned short class; 174038889Sjdp unsigned long style; 174138889Sjdp}; 174238889Sjdp 174338889Sjdpstatic const struct control_info control_info[] = 174438889Sjdp{ 174538889Sjdp { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE }, 174638889Sjdp { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX }, 174738889Sjdp { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON }, 174838889Sjdp { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX }, 174938889Sjdp { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 }, 175038889Sjdp { "CTEXT", CTL_STATIC, SS_CENTER }, 175138889Sjdp { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON }, 175238889Sjdp { "EDITTEXT", CTL_EDIT, (unsigned long) -1 }, 175338889Sjdp { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX }, 175438889Sjdp { "ICON", CTL_STATIC, SS_ICON }, 175538889Sjdp { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 }, 175638889Sjdp { "LTEXT", CTL_STATIC, SS_LEFT }, 175738889Sjdp { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX }, 175838889Sjdp { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON }, 175938889Sjdp { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON }, 176038889Sjdp { "RTEXT", CTL_STATIC, SS_RIGHT }, 176138889Sjdp { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 }, 176238889Sjdp { "STATE3", CTL_BUTTON, BS_3STATE }, 176338889Sjdp /* It's important that USERBUTTON come after all the other button 176438889Sjdp types, so that it won't be matched too early. */ 176538889Sjdp { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 }, 176638889Sjdp { NULL, 0, 0 } 176738889Sjdp}; 176838889Sjdp 176938889Sjdp/* Write a dialog control. */ 177038889Sjdp 177138889Sjdpstatic void 177238889Sjdpwrite_rc_dialog_control (e, control) 177338889Sjdp FILE *e; 177438889Sjdp const struct dialog_control *control; 177538889Sjdp{ 177638889Sjdp const struct control_info *ci; 177738889Sjdp 177838889Sjdp fprintf (e, " "); 177938889Sjdp 178038889Sjdp if (control->class.named) 178138889Sjdp ci = NULL; 178238889Sjdp else 178338889Sjdp { 178438889Sjdp for (ci = control_info; ci->name != NULL; ++ci) 178538889Sjdp if (ci->class == control->class.u.id 178638889Sjdp && (ci->style == (unsigned long) -1 178738889Sjdp || ci->style == (control->style & 0xff))) 178838889Sjdp break; 178938889Sjdp } 179038889Sjdp 179138889Sjdp if (ci->name != NULL) 179238889Sjdp fprintf (e, "%s", ci->name); 179338889Sjdp else 179438889Sjdp fprintf (e, "CONTROL"); 179538889Sjdp 179638889Sjdp if (control->text.named || control->text.u.id != 0) 179738889Sjdp { 179838889Sjdp fprintf (e, " "); 179938889Sjdp res_id_print (e, control->text, 1); 180038889Sjdp fprintf (e, ","); 180138889Sjdp } 180238889Sjdp 180338889Sjdp fprintf (e, " %d, ", control->id); 180438889Sjdp 180538889Sjdp if (ci->name == NULL) 180638889Sjdp { 180738889Sjdp res_id_print (e, control->class, 0); 180838889Sjdp fprintf (e, ", 0x%lx, ", control->style); 180938889Sjdp } 181038889Sjdp 181138889Sjdp fprintf (e, "%d, %d", control->x, control->y); 181238889Sjdp 181338889Sjdp if (control->style != SS_ICON 181438889Sjdp || control->exstyle != 0 181538889Sjdp || control->width != 0 181638889Sjdp || control->height != 0 181738889Sjdp || control->help != 0) 181838889Sjdp { 181938889Sjdp fprintf (e, ", %d, %d", control->width, control->height); 182038889Sjdp 182138889Sjdp /* FIXME: We don't need to print the style if it is the default. 182238889Sjdp More importantly, in certain cases we actually need to turn 182338889Sjdp off parts of the forced style, by using NOT. */ 182438889Sjdp fprintf (e, ", 0x%lx", control->style); 182538889Sjdp 182638889Sjdp if (control->exstyle != 0 || control->help != 0) 182738889Sjdp fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help); 182838889Sjdp } 182938889Sjdp 183038889Sjdp fprintf (e, "\n"); 183138889Sjdp 183238889Sjdp if (control->data != NULL) 183338889Sjdp write_rc_rcdata (e, control->data, 2); 183438889Sjdp} 183538889Sjdp 183638889Sjdp/* Write out font directory data. This would normally be built from 183738889Sjdp the font data. */ 183838889Sjdp 183938889Sjdpstatic void 184038889Sjdpwrite_rc_fontdir (e, fontdir) 184138889Sjdp FILE *e; 184238889Sjdp const struct fontdir *fontdir; 184338889Sjdp{ 184438889Sjdp const struct fontdir *fc; 184538889Sjdp 184638889Sjdp for (fc = fontdir; fc != NULL; fc = fc->next) 184738889Sjdp { 184838889Sjdp fprintf (e, "// Font index: %d\n", fc->index); 184938889Sjdp write_rc_filedata (e, fc->length, fc->data); 185038889Sjdp } 185138889Sjdp} 185238889Sjdp 185338889Sjdp/* Write out group icon data. This would normally be built from the 185438889Sjdp icon data. */ 185538889Sjdp 185638889Sjdpstatic void 185738889Sjdpwrite_rc_group_icon (e, group_icon) 185838889Sjdp FILE *e; 185938889Sjdp const struct group_icon *group_icon; 186038889Sjdp{ 186138889Sjdp const struct group_icon *gi; 186238889Sjdp 186338889Sjdp for (gi = group_icon; gi != NULL; gi = gi->next) 186438889Sjdp { 186538889Sjdp fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n", 186638889Sjdp gi->width, gi->height, gi->colors, gi->planes, gi->bits); 186738889Sjdp fprintf (e, "// data bytes: %lu; index: %d\n", 186838889Sjdp gi->bytes, gi->index); 186938889Sjdp } 187038889Sjdp} 187138889Sjdp 187238889Sjdp/* Write out a menu resource. */ 187338889Sjdp 187438889Sjdpstatic void 187538889Sjdpwrite_rc_menu (e, menu, menuex) 187638889Sjdp FILE *e; 187738889Sjdp const struct menu *menu; 187838889Sjdp int menuex; 187938889Sjdp{ 188038889Sjdp if (menu->help != 0) 188138889Sjdp fprintf (e, "// Help ID: %lu\n", menu->help); 188238889Sjdp write_rc_menuitems (e, menu->items, menuex, 0); 188338889Sjdp} 188438889Sjdp 188538889Sjdp/* Write out menuitems. */ 188638889Sjdp 188738889Sjdpstatic void 188838889Sjdpwrite_rc_menuitems (e, menuitems, menuex, ind) 188938889Sjdp FILE *e; 189038889Sjdp const struct menuitem *menuitems; 189138889Sjdp int menuex; 189238889Sjdp int ind; 189338889Sjdp{ 189438889Sjdp const struct menuitem *mi; 189538889Sjdp 189638889Sjdp indent (e, ind); 189738889Sjdp fprintf (e, "BEGIN\n"); 189838889Sjdp 189938889Sjdp for (mi = menuitems; mi != NULL; mi = mi->next) 190038889Sjdp { 190138889Sjdp indent (e, ind + 2); 190238889Sjdp 190338889Sjdp if (mi->popup == NULL) 190438889Sjdp fprintf (e, "MENUITEM"); 190538889Sjdp else 190638889Sjdp fprintf (e, "POPUP"); 190738889Sjdp 190838889Sjdp if (! menuex 190938889Sjdp && mi->popup == NULL 191038889Sjdp && mi->text == NULL 191138889Sjdp && mi->type == 0 191238889Sjdp && mi->id == 0) 191338889Sjdp { 191438889Sjdp fprintf (e, " SEPARATOR\n"); 191538889Sjdp continue; 191638889Sjdp } 191738889Sjdp 191838889Sjdp if (mi->text == NULL) 191938889Sjdp fprintf (e, " \"\""); 192038889Sjdp else 192138889Sjdp { 192238889Sjdp fprintf (e, " \""); 192338889Sjdp unicode_print (e, mi->text, -1); 192438889Sjdp fprintf (e, "\""); 192538889Sjdp } 192638889Sjdp 192738889Sjdp if (! menuex) 192838889Sjdp { 192938889Sjdp if (mi->popup == NULL) 193038889Sjdp fprintf (e, ", %d", mi->id); 193138889Sjdp 193238889Sjdp if ((mi->type & MENUITEM_CHECKED) != 0) 193338889Sjdp fprintf (e, ", CHECKED"); 193438889Sjdp if ((mi->type & MENUITEM_GRAYED) != 0) 193538889Sjdp fprintf (e, ", GRAYED"); 193638889Sjdp if ((mi->type & MENUITEM_HELP) != 0) 193738889Sjdp fprintf (e, ", HELP"); 193838889Sjdp if ((mi->type & MENUITEM_INACTIVE) != 0) 193938889Sjdp fprintf (e, ", INACTIVE"); 194038889Sjdp if ((mi->type & MENUITEM_MENUBARBREAK) != 0) 194138889Sjdp fprintf (e, ", MENUBARBREAK"); 194238889Sjdp if ((mi->type & MENUITEM_MENUBREAK) != 0) 194338889Sjdp fprintf (e, ", MENUBREAK"); 194438889Sjdp } 194538889Sjdp else 194638889Sjdp { 194738889Sjdp if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0) 194838889Sjdp { 194938889Sjdp fprintf (e, ", %d", mi->id); 195038889Sjdp if (mi->type != 0 || mi->state != 0 || mi->help != 0) 195138889Sjdp { 195238889Sjdp fprintf (e, ", %lu", mi->type); 195338889Sjdp if (mi->state != 0 || mi->help != 0) 195438889Sjdp { 195538889Sjdp fprintf (e, ", %lu", mi->state); 195638889Sjdp if (mi->help != 0) 195738889Sjdp fprintf (e, ", %lu", mi->help); 195838889Sjdp } 195938889Sjdp } 196038889Sjdp } 196138889Sjdp } 196238889Sjdp 196338889Sjdp fprintf (e, "\n"); 196438889Sjdp 196538889Sjdp if (mi->popup != NULL) 196638889Sjdp write_rc_menuitems (e, mi->popup, menuex, ind + 2); 196738889Sjdp } 196838889Sjdp 196938889Sjdp indent (e, ind); 197038889Sjdp fprintf (e, "END\n"); 197138889Sjdp} 197238889Sjdp 197338889Sjdp/* Write out an rcdata resource. This is also used for other types of 197438889Sjdp resources that need to print arbitrary data. */ 197538889Sjdp 197638889Sjdpstatic void 197738889Sjdpwrite_rc_rcdata (e, rcdata, ind) 197838889Sjdp FILE *e; 197938889Sjdp const struct rcdata_item *rcdata; 198038889Sjdp int ind; 198138889Sjdp{ 198238889Sjdp const struct rcdata_item *ri; 198338889Sjdp 198438889Sjdp indent (e, ind); 198538889Sjdp fprintf (e, "BEGIN\n"); 198638889Sjdp 198738889Sjdp for (ri = rcdata; ri != NULL; ri = ri->next) 198838889Sjdp { 198938889Sjdp if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0) 199038889Sjdp continue; 199138889Sjdp 199238889Sjdp indent (e, ind + 2); 199338889Sjdp 199438889Sjdp switch (ri->type) 199538889Sjdp { 199638889Sjdp default: 199738889Sjdp abort (); 199838889Sjdp 199938889Sjdp case RCDATA_WORD: 200038889Sjdp fprintf (e, "%d", ri->u.word); 200138889Sjdp break; 200238889Sjdp 200338889Sjdp case RCDATA_DWORD: 200438889Sjdp fprintf (e, "%luL", ri->u.dword); 200538889Sjdp break; 200638889Sjdp 200738889Sjdp case RCDATA_STRING: 200838889Sjdp { 200938889Sjdp const char *s; 201038889Sjdp unsigned long i; 201138889Sjdp 201238889Sjdp fprintf (e, "\""); 201338889Sjdp s = ri->u.string.s; 201438889Sjdp for (i = 0; i < ri->u.string.length; i++) 201538889Sjdp { 201638889Sjdp if (isprint (*s)) 201738889Sjdp putc (*s, e); 201838889Sjdp else 201938889Sjdp fprintf (e, "\\%03o", *s); 202038889Sjdp } 202138889Sjdp fprintf (e, "\""); 202238889Sjdp break; 202338889Sjdp } 202438889Sjdp 202538889Sjdp case RCDATA_WSTRING: 202638889Sjdp fprintf (e, "L\""); 202738889Sjdp unicode_print (e, ri->u.wstring.w, ri->u.wstring.length); 202838889Sjdp fprintf (e, "\""); 202938889Sjdp break; 203038889Sjdp 203138889Sjdp case RCDATA_BUFFER: 203238889Sjdp { 203338889Sjdp unsigned long i; 203438889Sjdp int first; 203538889Sjdp 203638889Sjdp /* Assume little endian data. */ 203738889Sjdp 203838889Sjdp first = 1; 203938889Sjdp for (i = 0; i + 3 < ri->u.buffer.length; i += 4) 204038889Sjdp { 204138889Sjdp unsigned long l; 204238889Sjdp 204338889Sjdp l = ((((((ri->u.buffer.data[i + 3] << 8) 204438889Sjdp | ri->u.buffer.data[i + 2]) << 8) 204538889Sjdp | ri->u.buffer.data[i + 1]) << 8) 204638889Sjdp | ri->u.buffer.data[i]); 204738889Sjdp if (first) 204838889Sjdp first = 0; 204938889Sjdp else 205038889Sjdp { 205138889Sjdp fprintf (e, ",\n"); 205238889Sjdp indent (e, ind + 2); 205338889Sjdp } 205438889Sjdp fprintf (e, "%luL", l); 205538889Sjdp } 205638889Sjdp 205738889Sjdp if (i + 1 < ri->u.buffer.length) 205838889Sjdp { 205938889Sjdp int i; 206038889Sjdp 206138889Sjdp i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i]; 206238889Sjdp if (first) 206338889Sjdp first = 0; 206438889Sjdp else 206538889Sjdp { 206638889Sjdp fprintf (e, ",\n"); 206738889Sjdp indent (e, ind + 2); 206838889Sjdp } 206938889Sjdp fprintf (e, "%d", i); 207038889Sjdp i += 2; 207138889Sjdp } 207238889Sjdp 207338889Sjdp if (i < ri->u.buffer.length) 207438889Sjdp { 207538889Sjdp if (first) 207638889Sjdp first = 0; 207738889Sjdp else 207838889Sjdp { 207938889Sjdp fprintf (e, ",\n"); 208038889Sjdp indent (e, ind + 2); 208138889Sjdp } 208238889Sjdp if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i] 208338889Sjdp && isprint (ri->u.buffer.data[i])) 208438889Sjdp fprintf (e, "\"%c\"", ri->u.buffer.data[i]); 208538889Sjdp else 208638889Sjdp fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]); 208738889Sjdp } 208838889Sjdp 208938889Sjdp break; 209038889Sjdp } 209138889Sjdp } 209238889Sjdp 209338889Sjdp if (ri->next != NULL) 209438889Sjdp fprintf (e, ","); 209538889Sjdp fprintf (e, "\n"); 209638889Sjdp } 209738889Sjdp 209838889Sjdp indent (e, ind); 209938889Sjdp fprintf (e, "END\n"); 210038889Sjdp} 210138889Sjdp 210238889Sjdp/* Write out a stringtable resource. */ 210338889Sjdp 210438889Sjdpstatic void 210538889Sjdpwrite_rc_stringtable (e, name, stringtable) 210638889Sjdp FILE *e; 210738889Sjdp const struct res_id *name; 210838889Sjdp const struct stringtable *stringtable; 210938889Sjdp{ 211038889Sjdp unsigned long offset; 211138889Sjdp int i; 211238889Sjdp 211338889Sjdp if (name != NULL && ! name->named) 211438889Sjdp offset = (name->u.id - 1) << 4; 211538889Sjdp else 211638889Sjdp { 211738889Sjdp fprintf (e, "// %s string table name\n", 211838889Sjdp name == NULL ? "Missing" : "Invalid"); 211938889Sjdp offset = 0; 212038889Sjdp } 212138889Sjdp 212238889Sjdp fprintf (e, "BEGIN\n"); 212338889Sjdp 212438889Sjdp for (i = 0; i < 16; i++) 212538889Sjdp { 212638889Sjdp if (stringtable->strings[i].length != 0) 212738889Sjdp { 212838889Sjdp fprintf (e, " %lu, \"", offset + i); 212938889Sjdp unicode_print (e, stringtable->strings[i].string, 213038889Sjdp stringtable->strings[i].length); 213138889Sjdp fprintf (e, "\"\n"); 213238889Sjdp } 213338889Sjdp } 213438889Sjdp 213538889Sjdp fprintf (e, "END\n"); 213638889Sjdp} 213738889Sjdp 213838889Sjdp/* Write out a versioninfo resource. */ 213938889Sjdp 214038889Sjdpstatic void 214138889Sjdpwrite_rc_versioninfo (e, versioninfo) 214238889Sjdp FILE *e; 214338889Sjdp const struct versioninfo *versioninfo; 214438889Sjdp{ 214538889Sjdp const struct fixed_versioninfo *f; 214638889Sjdp const struct ver_info *vi; 214738889Sjdp 214838889Sjdp f = versioninfo->fixed; 214938889Sjdp if (f->file_version_ms != 0 || f->file_version_ls != 0) 215038889Sjdp fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n", 215138889Sjdp (f->file_version_ms >> 16) & 0xffff, 215238889Sjdp f->file_version_ms & 0xffff, 215338889Sjdp (f->file_version_ls >> 16) & 0xffff, 215438889Sjdp f->file_version_ls & 0xffff); 215538889Sjdp if (f->product_version_ms != 0 || f->product_version_ls != 0) 215638889Sjdp fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n", 215738889Sjdp (f->product_version_ms >> 16) & 0xffff, 215838889Sjdp f->product_version_ms & 0xffff, 215938889Sjdp (f->product_version_ls >> 16) & 0xffff, 216038889Sjdp f->product_version_ls & 0xffff); 216138889Sjdp if (f->file_flags_mask != 0) 216238889Sjdp fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask); 216338889Sjdp if (f->file_flags != 0) 216438889Sjdp fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags); 216538889Sjdp if (f->file_os != 0) 216638889Sjdp fprintf (e, " FILEOS 0x%lx\n", f->file_os); 216738889Sjdp if (f->file_type != 0) 216838889Sjdp fprintf (e, " FILETYPE 0x%lx\n", f->file_type); 216938889Sjdp if (f->file_subtype != 0) 217038889Sjdp fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype); 217138889Sjdp if (f->file_date_ms != 0 || f->file_date_ls != 0) 217238889Sjdp fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls); 217338889Sjdp 217438889Sjdp fprintf (e, "BEGIN\n"); 217538889Sjdp 217638889Sjdp for (vi = versioninfo->var; vi != NULL; vi = vi->next) 217738889Sjdp { 217838889Sjdp switch (vi->type) 217938889Sjdp { 218038889Sjdp case VERINFO_STRING: 218138889Sjdp { 218238889Sjdp const struct ver_stringinfo *vs; 218338889Sjdp 218438889Sjdp fprintf (e, " BLOCK \"StringFileInfo\"\n"); 218538889Sjdp fprintf (e, " BEGIN\n"); 218638889Sjdp fprintf (e, " BLOCK \""); 218738889Sjdp unicode_print (e, vi->u.string.language, -1); 218838889Sjdp fprintf (e, "\"\n"); 218938889Sjdp fprintf (e, " BEGIN\n"); 219038889Sjdp 219138889Sjdp for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) 219238889Sjdp { 219338889Sjdp fprintf (e, " VALUE \""); 219438889Sjdp unicode_print (e, vs->key, -1); 219538889Sjdp fprintf (e, "\", \""); 219638889Sjdp unicode_print (e, vs->value, -1); 219738889Sjdp fprintf (e, "\"\n"); 219838889Sjdp } 219938889Sjdp 220038889Sjdp fprintf (e, " END\n"); 220138889Sjdp fprintf (e, " END\n"); 220238889Sjdp break; 220338889Sjdp } 220438889Sjdp 220538889Sjdp case VERINFO_VAR: 220638889Sjdp { 220738889Sjdp const struct ver_varinfo *vv; 220838889Sjdp 220938889Sjdp fprintf (e, " BLOCK \"VarFileInfo\"\n"); 221038889Sjdp fprintf (e, " BEGIN\n"); 221138889Sjdp fprintf (e, " VALUE \""); 221238889Sjdp unicode_print (e, vi->u.var.key, -1); 221338889Sjdp fprintf (e, "\""); 221438889Sjdp 221538889Sjdp for (vv = vi->u.var.var; vv != NULL; vv = vv->next) 221638889Sjdp fprintf (e, ", 0x%x, %d", (unsigned int) vv->language, 221738889Sjdp vv->charset); 221838889Sjdp 221938889Sjdp fprintf (e, "\n END\n"); 222038889Sjdp 222138889Sjdp break; 222238889Sjdp } 222338889Sjdp } 222438889Sjdp } 222538889Sjdp 222638889Sjdp fprintf (e, "END\n"); 222738889Sjdp} 222838889Sjdp 222938889Sjdp/* Write out data which would normally be read from a file. */ 223038889Sjdp 223138889Sjdpstatic void 223238889Sjdpwrite_rc_filedata (e, length, data) 223338889Sjdp FILE *e; 223438889Sjdp unsigned long length; 223538889Sjdp const unsigned char *data; 223638889Sjdp{ 223738889Sjdp unsigned long i; 223838889Sjdp 223938889Sjdp for (i = 0; i + 15 < length; i += 16) 224038889Sjdp { 224138889Sjdp fprintf (e, "// %4lx: ", i); 224238889Sjdp fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ", 224338889Sjdp data[i + 0], data[i + 1], data[i + 2], data[i + 3], 224438889Sjdp data[i + 4], data[i + 5], data[i + 6], data[i + 7]); 224538889Sjdp fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n", 224638889Sjdp data[i + 8], data[i + 9], data[i + 10], data[i + 11], 224738889Sjdp data[i + 12], data[i + 13], data[i + 14], data[i + 15]); 224838889Sjdp } 224938889Sjdp 225038889Sjdp if (i < length) 225138889Sjdp { 225238889Sjdp fprintf (e, "// %4lx:", i); 225338889Sjdp while (i < length) 225438889Sjdp { 225538889Sjdp fprintf (e, " %02x", data[i]); 225638889Sjdp ++i; 225738889Sjdp } 225838889Sjdp fprintf (e, "\n"); 225938889Sjdp } 226038889Sjdp} 2261