resrc.c revision 130561
138889Sjdp/* resrc.c -- read and write Windows rc files. 2130561Sobrien Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 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" 2889857Sobrien#include "safe-ctype.h" 2938889Sjdp#include "windres.h" 3038889Sjdp 3138889Sjdp#include <assert.h> 3260484Sobrien#include <errno.h> 3338889Sjdp#include <sys/stat.h> 3460484Sobrien#ifdef HAVE_UNISTD_H 3560484Sobrien#include <unistd.h> 3660484Sobrien#endif 3738889Sjdp 3860484Sobrien#ifdef HAVE_SYS_WAIT_H 3960484Sobrien#include <sys/wait.h> 4060484Sobrien#else /* ! HAVE_SYS_WAIT_H */ 4160484Sobrien#if ! defined (_WIN32) || defined (__CYGWIN__) 4260484Sobrien#ifndef WIFEXITED 4360484Sobrien#define WIFEXITED(w) (((w)&0377) == 0) 4460484Sobrien#endif 4560484Sobrien#ifndef WIFSIGNALED 4660484Sobrien#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) 4760484Sobrien#endif 4860484Sobrien#ifndef WTERMSIG 4960484Sobrien#define WTERMSIG(w) ((w) & 0177) 5060484Sobrien#endif 5160484Sobrien#ifndef WEXITSTATUS 5260484Sobrien#define WEXITSTATUS(w) (((w) >> 8) & 0377) 5360484Sobrien#endif 5460484Sobrien#else /* defined (_WIN32) && ! defined (__CYGWIN__) */ 5560484Sobrien#ifndef WIFEXITED 5660484Sobrien#define WIFEXITED(w) (((w) & 0xff) == 0) 5760484Sobrien#endif 5860484Sobrien#ifndef WIFSIGNALED 5960484Sobrien#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) 6060484Sobrien#endif 6160484Sobrien#ifndef WTERMSIG 6260484Sobrien#define WTERMSIG(w) ((w) & 0x7f) 6360484Sobrien#endif 6460484Sobrien#ifndef WEXITSTATUS 6560484Sobrien#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) 6660484Sobrien#endif 6760484Sobrien#endif /* defined (_WIN32) && ! defined (__CYGWIN__) */ 6860484Sobrien#endif /* ! HAVE_SYS_WAIT_H */ 6960484Sobrien 7060484Sobrien#ifndef STDOUT_FILENO 7160484Sobrien#define STDOUT_FILENO 1 7260484Sobrien#endif 73104834Sobrien 7460484Sobrien#if defined (_WIN32) && ! defined (__CYGWIN__) 7538889Sjdp#define popen _popen 7638889Sjdp#define pclose _pclose 7738889Sjdp#endif 7838889Sjdp 7938889Sjdp/* The default preprocessor. */ 8038889Sjdp 8177298Sobrien#define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED" 8238889Sjdp 8338889Sjdp/* We read the directory entries in a cursor or icon file into 8438889Sjdp instances of this structure. */ 8538889Sjdp 8638889Sjdpstruct icondir 8738889Sjdp{ 8838889Sjdp /* Width of image. */ 8938889Sjdp unsigned char width; 9038889Sjdp /* Height of image. */ 9138889Sjdp unsigned char height; 9238889Sjdp /* Number of colors in image. */ 9338889Sjdp unsigned char colorcount; 9438889Sjdp union 9538889Sjdp { 9638889Sjdp struct 9738889Sjdp { 9838889Sjdp /* Color planes. */ 9938889Sjdp unsigned short planes; 10038889Sjdp /* Bits per pixel. */ 10138889Sjdp unsigned short bits; 10238889Sjdp } icon; 10338889Sjdp struct 10438889Sjdp { 10538889Sjdp /* X coordinate of hotspot. */ 10638889Sjdp unsigned short xhotspot; 10738889Sjdp /* Y coordinate of hotspot. */ 10838889Sjdp unsigned short yhotspot; 10938889Sjdp } cursor; 11038889Sjdp } u; 11138889Sjdp /* Bytes in image. */ 11238889Sjdp unsigned long bytes; 11338889Sjdp /* File offset of image. */ 11438889Sjdp unsigned long offset; 11538889Sjdp}; 11638889Sjdp 11738889Sjdp/* The name of the rc file we are reading. */ 11838889Sjdp 11938889Sjdpchar *rc_filename; 12038889Sjdp 12138889Sjdp/* The line number in the rc file. */ 12238889Sjdp 12338889Sjdpint rc_lineno; 12438889Sjdp 12538889Sjdp/* The pipe we are reading from, so that we can close it if we exit. */ 12638889Sjdp 12738889Sjdpstatic FILE *cpp_pipe; 12838889Sjdp 12960484Sobrien/* The temporary file used if we're not using popen, so we can delete it 13060484Sobrien if we exit. */ 13160484Sobrien 13260484Sobrienstatic char *cpp_temp_file; 13360484Sobrien 13499461Sobrien/* Input stream is either a file or a pipe. */ 13560484Sobrien 13660484Sobrienstatic enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type; 13760484Sobrien 13838889Sjdp/* As we read the rc file, we attach information to this structure. */ 13938889Sjdp 14038889Sjdpstatic struct res_directory *resources; 14138889Sjdp 14238889Sjdp/* The number of cursor resources we have written out. */ 14338889Sjdp 14438889Sjdpstatic int cursors; 14538889Sjdp 14638889Sjdp/* The number of font resources we have written out. */ 14738889Sjdp 14838889Sjdpstatic int fonts; 14938889Sjdp 15038889Sjdp/* Font directory information. */ 15138889Sjdp 15238889Sjdpstruct fontdir *fontdirs; 15338889Sjdp 15438889Sjdp/* Resource info to use for fontdirs. */ 15538889Sjdp 15638889Sjdpstruct res_res_info fontdirs_resinfo; 15738889Sjdp 15838889Sjdp/* The number of icon resources we have written out. */ 15938889Sjdp 16038889Sjdpstatic int icons; 16138889Sjdp 16238889Sjdp/* Local functions. */ 16338889Sjdp 164130561Sobrienstatic int run_cmd (char *, const char *); 165130561Sobrienstatic FILE *open_input_stream (char *); 166130561Sobrienstatic FILE *look_for_default 167130561Sobrien (char *, const char *, int, const char *, const char *); 168130561Sobrienstatic void close_input_stream (void); 169130561Sobrienstatic void unexpected_eof (const char *); 170130561Sobrienstatic int get_word (FILE *, const char *); 171130561Sobrienstatic unsigned long get_long (FILE *, const char *); 172130561Sobrienstatic void get_data (FILE *, unsigned char *, unsigned long, const char *); 173130561Sobrienstatic void define_fontdirs (void); 17438889Sjdp 17599461Sobrien/* Run `cmd' and redirect the output to `redir'. */ 17660484Sobrien 17760484Sobrienstatic int 178130561Sobrienrun_cmd (char *cmd, const char *redir) 17960484Sobrien{ 18060484Sobrien char *s; 18160484Sobrien int pid, wait_status, retcode; 18260484Sobrien int i; 18360484Sobrien const char **argv; 18460484Sobrien char *errmsg_fmt, *errmsg_arg; 18560484Sobrien char *temp_base = choose_temp_base (); 18660484Sobrien int in_quote; 18760484Sobrien char sep; 18860484Sobrien int redir_handle = -1; 18960484Sobrien int stdout_save = -1; 19060484Sobrien 19160484Sobrien /* Count the args. */ 19260484Sobrien i = 0; 193104834Sobrien 19460484Sobrien for (s = cmd; *s; s++) 19560484Sobrien if (*s == ' ') 19660484Sobrien i++; 197104834Sobrien 19860484Sobrien i++; 19960484Sobrien argv = alloca (sizeof (char *) * (i + 3)); 20060484Sobrien i = 0; 20160484Sobrien s = cmd; 202104834Sobrien 20360484Sobrien while (1) 20460484Sobrien { 20560484Sobrien while (*s == ' ' && *s != 0) 20660484Sobrien s++; 207104834Sobrien 20860484Sobrien if (*s == 0) 20960484Sobrien break; 210104834Sobrien 21160484Sobrien in_quote = (*s == '\'' || *s == '"'); 21260484Sobrien sep = (in_quote) ? *s++ : ' '; 21360484Sobrien argv[i++] = s; 214104834Sobrien 21560484Sobrien while (*s != sep && *s != 0) 21660484Sobrien s++; 217104834Sobrien 21860484Sobrien if (*s == 0) 21960484Sobrien break; 220104834Sobrien 22160484Sobrien *s++ = 0; 222104834Sobrien 22360484Sobrien if (in_quote) 224104834Sobrien s++; 22560484Sobrien } 22660484Sobrien argv[i++] = NULL; 22760484Sobrien 22860484Sobrien /* Setup the redirection. We can't use the usual fork/exec and redirect 22960484Sobrien since we may be running on non-POSIX Windows host. */ 23060484Sobrien 23160484Sobrien fflush (stdout); 23260484Sobrien fflush (stderr); 23360484Sobrien 23460484Sobrien /* Open temporary output file. */ 23560484Sobrien redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666); 23660484Sobrien if (redir_handle == -1) 237104834Sobrien fatal (_("can't open temporary file `%s': %s"), redir, 238104834Sobrien strerror (errno)); 23960484Sobrien 24060484Sobrien /* Duplicate the stdout file handle so it can be restored later. */ 24160484Sobrien stdout_save = dup (STDOUT_FILENO); 24260484Sobrien if (stdout_save == -1) 24360484Sobrien fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno)); 24460484Sobrien 24560484Sobrien /* Redirect stdout to our output file. */ 24660484Sobrien dup2 (redir_handle, STDOUT_FILENO); 24760484Sobrien 24860484Sobrien pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, 24960484Sobrien &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); 25060484Sobrien 25160484Sobrien /* Restore stdout to its previous setting. */ 25260484Sobrien dup2 (stdout_save, STDOUT_FILENO); 25360484Sobrien 254130561Sobrien /* Close response file. */ 25560484Sobrien close (redir_handle); 25660484Sobrien 25760484Sobrien if (pid == -1) 25860484Sobrien { 25960484Sobrien fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno)); 26060484Sobrien return 1; 26160484Sobrien } 26260484Sobrien 26360484Sobrien retcode = 0; 26460484Sobrien pid = pwait (pid, &wait_status, 0); 265104834Sobrien 26660484Sobrien if (pid == -1) 26760484Sobrien { 26860484Sobrien fatal (_("wait: %s"), strerror (errno)); 26960484Sobrien retcode = 1; 27060484Sobrien } 27160484Sobrien else if (WIFSIGNALED (wait_status)) 27260484Sobrien { 27360484Sobrien fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); 27460484Sobrien retcode = 1; 27560484Sobrien } 27660484Sobrien else if (WIFEXITED (wait_status)) 27760484Sobrien { 27860484Sobrien if (WEXITSTATUS (wait_status) != 0) 27960484Sobrien { 280104834Sobrien fatal (_("%s exited with status %d"), cmd, 28160484Sobrien WEXITSTATUS (wait_status)); 28260484Sobrien retcode = 1; 28360484Sobrien } 28460484Sobrien } 28560484Sobrien else 28660484Sobrien retcode = 1; 287104834Sobrien 28860484Sobrien return retcode; 28960484Sobrien} 29060484Sobrien 29160484Sobrienstatic FILE * 292130561Sobrienopen_input_stream (char *cmd) 29360484Sobrien{ 29460484Sobrien if (istream_type == ISTREAM_FILE) 29560484Sobrien { 29660484Sobrien char *fileprefix; 29760484Sobrien 29860484Sobrien fileprefix = choose_temp_base (); 29960484Sobrien cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5); 30060484Sobrien sprintf (cpp_temp_file, "%s.irc", fileprefix); 30160484Sobrien free (fileprefix); 30260484Sobrien 30360484Sobrien if (run_cmd (cmd, cpp_temp_file)) 30460484Sobrien fatal (_("can't execute `%s': %s"), cmd, strerror (errno)); 30560484Sobrien 30660484Sobrien cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);; 30760484Sobrien if (cpp_pipe == NULL) 308104834Sobrien fatal (_("can't open temporary file `%s': %s"), 30960484Sobrien cpp_temp_file, strerror (errno)); 310104834Sobrien 31160484Sobrien if (verbose) 312104834Sobrien fprintf (stderr, 31360484Sobrien _("Using temporary file `%s' to read preprocessor output\n"), 31460484Sobrien cpp_temp_file); 31560484Sobrien } 31660484Sobrien else 31760484Sobrien { 31860484Sobrien cpp_pipe = popen (cmd, FOPEN_RT); 31960484Sobrien if (cpp_pipe == NULL) 320104834Sobrien fatal (_("can't popen `%s': %s"), cmd, strerror (errno)); 32160484Sobrien if (verbose) 32260484Sobrien fprintf (stderr, _("Using popen to read preprocessor output\n")); 32360484Sobrien } 32460484Sobrien 32560484Sobrien xatexit (close_input_stream); 32660484Sobrien return cpp_pipe; 32760484Sobrien} 32860484Sobrien 32960484Sobrien/* look for the preprocessor program */ 33060484Sobrien 33160484Sobrienstatic FILE * 332130561Sobrienlook_for_default (char *cmd, const char *prefix, int end_prefix, 333130561Sobrien const char *preprocargs, const char *filename) 33460484Sobrien{ 33560484Sobrien char *space; 33660484Sobrien int found; 33760484Sobrien struct stat s; 33860484Sobrien 33960484Sobrien strcpy (cmd, prefix); 34060484Sobrien 34160484Sobrien sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR); 34260484Sobrien space = strchr (cmd + end_prefix, ' '); 34360484Sobrien if (space) 34460484Sobrien *space = 0; 34560484Sobrien 34660484Sobrien if ( 34760484Sobrien#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32) 34860484Sobrien strchr (cmd, '\\') || 34960484Sobrien#endif 35060484Sobrien strchr (cmd, '/')) 35160484Sobrien { 35260484Sobrien found = (stat (cmd, &s) == 0 35360484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 35460484Sobrien || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0 35560484Sobrien#endif 35660484Sobrien ); 35760484Sobrien 35860484Sobrien if (! found) 35960484Sobrien { 36060484Sobrien if (verbose) 36160484Sobrien fprintf (stderr, _("Tried `%s'\n"), cmd); 36260484Sobrien return NULL; 36360484Sobrien } 36460484Sobrien } 36560484Sobrien 36660484Sobrien strcpy (cmd, prefix); 36760484Sobrien 36860484Sobrien sprintf (cmd + end_prefix, "%s %s %s", 36960484Sobrien DEFAULT_PREPROCESSOR, preprocargs, filename); 37060484Sobrien 37160484Sobrien if (verbose) 37260484Sobrien fprintf (stderr, _("Using `%s'\n"), cmd); 37360484Sobrien 37460484Sobrien cpp_pipe = open_input_stream (cmd); 37560484Sobrien return cpp_pipe; 37660484Sobrien} 37760484Sobrien 37838889Sjdp/* Read an rc file. */ 37938889Sjdp 38038889Sjdpstruct res_directory * 381130561Sobrienread_rc_file (const char *filename, const char *preprocessor, 382130561Sobrien const char *preprocargs, int language, int use_temp_file) 38338889Sjdp{ 38438889Sjdp char *cmd; 38538889Sjdp 38660484Sobrien istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE; 38738889Sjdp 38838889Sjdp if (preprocargs == NULL) 38938889Sjdp preprocargs = ""; 39038889Sjdp if (filename == NULL) 39138889Sjdp filename = "-"; 39238889Sjdp 39360484Sobrien if (preprocessor) 39460484Sobrien { 39560484Sobrien cmd = xmalloc (strlen (preprocessor) 39660484Sobrien + strlen (preprocargs) 39760484Sobrien + strlen (filename) 39860484Sobrien + 10); 39960484Sobrien sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename); 40038889Sjdp 40160484Sobrien cpp_pipe = open_input_stream (cmd); 40260484Sobrien } 40360484Sobrien else 40460484Sobrien { 40560484Sobrien char *dash, *slash, *cp; 40660484Sobrien 40760484Sobrien preprocessor = DEFAULT_PREPROCESSOR; 40860484Sobrien 40960484Sobrien cmd = xmalloc (strlen (program_name) 41060484Sobrien + strlen (preprocessor) 41160484Sobrien + strlen (preprocargs) 41260484Sobrien + strlen (filename) 41360484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 41460484Sobrien + strlen (EXECUTABLE_SUFFIX) 41560484Sobrien#endif 41660484Sobrien + 10); 41760484Sobrien 41860484Sobrien 41960484Sobrien dash = slash = 0; 42060484Sobrien for (cp = program_name; *cp; cp++) 42160484Sobrien { 42260484Sobrien if (*cp == '-') 42360484Sobrien dash = cp; 42460484Sobrien if ( 42560484Sobrien#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32) 42660484Sobrien *cp == ':' || *cp == '\\' || 42760484Sobrien#endif 42860484Sobrien *cp == '/') 42960484Sobrien { 43060484Sobrien slash = cp; 43160484Sobrien dash = 0; 43260484Sobrien } 43360484Sobrien } 43460484Sobrien 43560484Sobrien cpp_pipe = 0; 43660484Sobrien 43760484Sobrien if (dash) 43860484Sobrien { 43960484Sobrien /* First, try looking for a prefixed gcc in the windres 44060484Sobrien directory, with the same prefix as windres */ 44160484Sobrien 44260484Sobrien cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1, 44360484Sobrien preprocargs, filename); 44460484Sobrien } 44560484Sobrien 44660484Sobrien if (slash && !cpp_pipe) 44760484Sobrien { 44860484Sobrien /* Next, try looking for a gcc in the same directory as 44960484Sobrien that windres */ 45060484Sobrien 45160484Sobrien cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1, 45260484Sobrien preprocargs, filename); 45360484Sobrien } 45460484Sobrien 45560484Sobrien if (!cpp_pipe) 45660484Sobrien { 45760484Sobrien /* Sigh, try the default */ 45860484Sobrien 45960484Sobrien cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename); 46060484Sobrien } 46160484Sobrien 46260484Sobrien } 463104834Sobrien 46438889Sjdp free (cmd); 46538889Sjdp 46638889Sjdp rc_filename = xstrdup (filename); 46738889Sjdp rc_lineno = 1; 46838889Sjdp if (language != -1) 46938889Sjdp rcparse_set_language (language); 47038889Sjdp yyin = cpp_pipe; 47138889Sjdp yyparse (); 47299461Sobrien rcparse_discard_strings (); 47338889Sjdp 47460484Sobrien close_input_stream (); 475104834Sobrien 47638889Sjdp if (fontdirs != NULL) 47738889Sjdp define_fontdirs (); 47838889Sjdp 47938889Sjdp free (rc_filename); 48038889Sjdp rc_filename = NULL; 48138889Sjdp 48238889Sjdp return resources; 48338889Sjdp} 48438889Sjdp 48560484Sobrien/* Close the input stream if it is open. */ 48638889Sjdp 48760484Sobrienstatic void 488130561Sobrienclose_input_stream (void) 48938889Sjdp{ 49060484Sobrien if (istream_type == ISTREAM_FILE) 49160484Sobrien { 49260484Sobrien if (cpp_pipe != NULL) 49360484Sobrien fclose (cpp_pipe); 49460484Sobrien 49560484Sobrien if (cpp_temp_file != NULL) 49660484Sobrien { 49760484Sobrien int errno_save = errno; 498104834Sobrien 49960484Sobrien unlink (cpp_temp_file); 50060484Sobrien errno = errno_save; 50160484Sobrien free (cpp_temp_file); 50260484Sobrien } 50360484Sobrien } 50460484Sobrien else 50560484Sobrien { 50660484Sobrien if (cpp_pipe != NULL) 50760484Sobrien pclose (cpp_pipe); 50860484Sobrien } 50960484Sobrien 51099461Sobrien /* Since this is also run via xatexit, safeguard. */ 51160484Sobrien cpp_pipe = NULL; 51260484Sobrien cpp_temp_file = NULL; 51338889Sjdp} 51438889Sjdp 51538889Sjdp/* Report an error while reading an rc file. */ 51638889Sjdp 51738889Sjdpvoid 518130561Sobrienyyerror (const char *msg) 51938889Sjdp{ 52038889Sjdp fatal ("%s:%d: %s", rc_filename, rc_lineno, msg); 52138889Sjdp} 52238889Sjdp 52338889Sjdp/* Issue a warning while reading an rc file. */ 52438889Sjdp 52538889Sjdpvoid 526130561Sobrienrcparse_warning (const char *msg) 52738889Sjdp{ 52860484Sobrien fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg); 52938889Sjdp} 53038889Sjdp 53138889Sjdp/* Die if we get an unexpected end of file. */ 53238889Sjdp 53338889Sjdpstatic void 534130561Sobrienunexpected_eof (const char *msg) 53538889Sjdp{ 53660484Sobrien fatal (_("%s: unexpected EOF"), msg); 53738889Sjdp} 53838889Sjdp 53938889Sjdp/* Read a 16 bit word from a file. The data is assumed to be little 54038889Sjdp endian. */ 54138889Sjdp 54238889Sjdpstatic int 543130561Sobrienget_word (FILE *e, const char *msg) 54438889Sjdp{ 54538889Sjdp int b1, b2; 54638889Sjdp 54738889Sjdp b1 = getc (e); 54838889Sjdp b2 = getc (e); 54938889Sjdp if (feof (e)) 55038889Sjdp unexpected_eof (msg); 55138889Sjdp return ((b2 & 0xff) << 8) | (b1 & 0xff); 55238889Sjdp} 55338889Sjdp 55438889Sjdp/* Read a 32 bit word from a file. The data is assumed to be little 55538889Sjdp endian. */ 55638889Sjdp 55738889Sjdpstatic unsigned long 558130561Sobrienget_long (FILE *e, const char *msg) 55938889Sjdp{ 56038889Sjdp int b1, b2, b3, b4; 56138889Sjdp 56238889Sjdp b1 = getc (e); 56338889Sjdp b2 = getc (e); 56438889Sjdp b3 = getc (e); 56538889Sjdp b4 = getc (e); 56638889Sjdp if (feof (e)) 56738889Sjdp unexpected_eof (msg); 56838889Sjdp return (((((((b4 & 0xff) << 8) 56938889Sjdp | (b3 & 0xff)) << 8) 57038889Sjdp | (b2 & 0xff)) << 8) 57138889Sjdp | (b1 & 0xff)); 57238889Sjdp} 57338889Sjdp 57438889Sjdp/* Read data from a file. This is a wrapper to do error checking. */ 57538889Sjdp 57638889Sjdpstatic void 577130561Sobrienget_data (FILE *e, unsigned char *p, unsigned long c, const char *msg) 57838889Sjdp{ 57938889Sjdp unsigned long got; 58038889Sjdp 58138889Sjdp got = fread (p, 1, c, e); 58238889Sjdp if (got == c) 58338889Sjdp return; 58438889Sjdp 58560484Sobrien fatal (_("%s: read of %lu returned %lu"), msg, c, got); 58638889Sjdp} 58738889Sjdp 58838889Sjdp/* Define an accelerator resource. */ 58938889Sjdp 59038889Sjdpvoid 591130561Sobriendefine_accelerator (struct res_id id, const struct res_res_info *resinfo, 592130561Sobrien struct accelerator *data) 59338889Sjdp{ 59438889Sjdp struct res_resource *r; 59538889Sjdp 59660484Sobrien r = define_standard_resource (&resources, RT_ACCELERATOR, id, 59738889Sjdp resinfo->language, 0); 59838889Sjdp r->type = RES_TYPE_ACCELERATOR; 59938889Sjdp r->u.acc = data; 60038889Sjdp r->res_info = *resinfo; 60138889Sjdp} 60238889Sjdp 60338889Sjdp/* Define a bitmap resource. Bitmap data is stored in a file. The 60438889Sjdp first 14 bytes of the file are a standard header, which is not 60538889Sjdp included in the resource data. */ 60638889Sjdp 60738889Sjdp#define BITMAP_SKIP (14) 60838889Sjdp 60938889Sjdpvoid 610130561Sobriendefine_bitmap (struct res_id id, const struct res_res_info *resinfo, 611130561Sobrien const char *filename) 61238889Sjdp{ 61338889Sjdp FILE *e; 61438889Sjdp char *real_filename; 61538889Sjdp struct stat s; 61638889Sjdp unsigned char *data; 61738889Sjdp int i; 61838889Sjdp struct res_resource *r; 61938889Sjdp 62038889Sjdp e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename); 62138889Sjdp 62238889Sjdp if (stat (real_filename, &s) < 0) 62360484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 62438889Sjdp strerror (errno)); 62538889Sjdp 62638889Sjdp data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP); 62738889Sjdp 62838889Sjdp for (i = 0; i < BITMAP_SKIP; i++) 62938889Sjdp getc (e); 63038889Sjdp 63138889Sjdp get_data (e, data, s.st_size - BITMAP_SKIP, real_filename); 63238889Sjdp 63338889Sjdp fclose (e); 63438889Sjdp free (real_filename); 63538889Sjdp 63638889Sjdp r = define_standard_resource (&resources, RT_BITMAP, id, 63738889Sjdp resinfo->language, 0); 63838889Sjdp 63938889Sjdp r->type = RES_TYPE_BITMAP; 64038889Sjdp r->u.data.length = s.st_size - BITMAP_SKIP; 64138889Sjdp r->u.data.data = data; 64238889Sjdp r->res_info = *resinfo; 64338889Sjdp} 64438889Sjdp 64538889Sjdp/* Define a cursor resource. A cursor file may contain a set of 64638889Sjdp bitmaps, each representing the same cursor at various different 64738889Sjdp resolutions. They each get written out with a different ID. The 64838889Sjdp real cursor resource is then a group resource which can be used to 64938889Sjdp select one of the actual cursors. */ 65038889Sjdp 65138889Sjdpvoid 652130561Sobriendefine_cursor (struct res_id id, const struct res_res_info *resinfo, 653130561Sobrien const char *filename) 65438889Sjdp{ 65538889Sjdp FILE *e; 65638889Sjdp char *real_filename; 65738889Sjdp int type, count, i; 65838889Sjdp struct icondir *icondirs; 65938889Sjdp int first_cursor; 66038889Sjdp struct res_resource *r; 66138889Sjdp struct group_cursor *first, **pp; 66238889Sjdp 66338889Sjdp e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename); 66438889Sjdp 66538889Sjdp /* A cursor file is basically an icon file. The start of the file 66638889Sjdp is a three word structure. The first word is ignored. The 66738889Sjdp second word is the type of data. The third word is the number of 66838889Sjdp entries. */ 66938889Sjdp 67038889Sjdp get_word (e, real_filename); 67138889Sjdp type = get_word (e, real_filename); 67238889Sjdp count = get_word (e, real_filename); 67338889Sjdp if (type != 2) 67460484Sobrien fatal (_("cursor file `%s' does not contain cursor data"), real_filename); 67538889Sjdp 67638889Sjdp /* Read in the icon directory entries. */ 67738889Sjdp 67838889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 67938889Sjdp 68038889Sjdp for (i = 0; i < count; i++) 68138889Sjdp { 68238889Sjdp icondirs[i].width = getc (e); 68338889Sjdp icondirs[i].height = getc (e); 68438889Sjdp icondirs[i].colorcount = getc (e); 68538889Sjdp getc (e); 68638889Sjdp icondirs[i].u.cursor.xhotspot = get_word (e, real_filename); 68738889Sjdp icondirs[i].u.cursor.yhotspot = get_word (e, real_filename); 68838889Sjdp icondirs[i].bytes = get_long (e, real_filename); 68938889Sjdp icondirs[i].offset = get_long (e, real_filename); 69038889Sjdp 69138889Sjdp if (feof (e)) 69238889Sjdp unexpected_eof (real_filename); 69338889Sjdp } 69438889Sjdp 69538889Sjdp /* Define each cursor as a unique resource. */ 69638889Sjdp 69738889Sjdp first_cursor = cursors; 69838889Sjdp 69938889Sjdp for (i = 0; i < count; i++) 70038889Sjdp { 70138889Sjdp unsigned char *data; 70238889Sjdp struct res_id name; 70338889Sjdp struct cursor *c; 70438889Sjdp 70538889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 70660484Sobrien fatal (_("%s: fseek to %lu failed: %s"), real_filename, 70738889Sjdp icondirs[i].offset, strerror (errno)); 70838889Sjdp 70938889Sjdp data = (unsigned char *) res_alloc (icondirs[i].bytes); 71038889Sjdp 71138889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 71238889Sjdp 71338889Sjdp c = (struct cursor *) res_alloc (sizeof *c); 71438889Sjdp c->xhotspot = icondirs[i].u.cursor.xhotspot; 71538889Sjdp c->yhotspot = icondirs[i].u.cursor.yhotspot; 71638889Sjdp c->length = icondirs[i].bytes; 71738889Sjdp c->data = data; 71838889Sjdp 71938889Sjdp ++cursors; 72038889Sjdp 72138889Sjdp name.named = 0; 72238889Sjdp name.u.id = cursors; 72338889Sjdp 72438889Sjdp r = define_standard_resource (&resources, RT_CURSOR, name, 72538889Sjdp resinfo->language, 0); 72638889Sjdp r->type = RES_TYPE_CURSOR; 72738889Sjdp r->u.cursor = c; 72838889Sjdp r->res_info = *resinfo; 72938889Sjdp } 73038889Sjdp 73138889Sjdp fclose (e); 73238889Sjdp free (real_filename); 73338889Sjdp 73438889Sjdp /* Define a cursor group resource. */ 73538889Sjdp 73638889Sjdp first = NULL; 73738889Sjdp pp = &first; 73838889Sjdp for (i = 0; i < count; i++) 73938889Sjdp { 74038889Sjdp struct group_cursor *cg; 74138889Sjdp 74238889Sjdp cg = (struct group_cursor *) res_alloc (sizeof *cg); 74338889Sjdp cg->next = NULL; 74438889Sjdp cg->width = icondirs[i].width; 74538889Sjdp cg->height = 2 * icondirs[i].height; 74638889Sjdp 74738889Sjdp /* FIXME: What should these be set to? */ 74838889Sjdp cg->planes = 1; 74938889Sjdp cg->bits = 1; 75038889Sjdp 75138889Sjdp cg->bytes = icondirs[i].bytes + 4; 75238889Sjdp cg->index = first_cursor + i + 1; 75338889Sjdp 75438889Sjdp *pp = cg; 75538889Sjdp pp = &(*pp)->next; 75638889Sjdp } 75738889Sjdp 75838889Sjdp free (icondirs); 75938889Sjdp 76038889Sjdp r = define_standard_resource (&resources, RT_GROUP_CURSOR, id, 76138889Sjdp resinfo->language, 0); 76238889Sjdp r->type = RES_TYPE_GROUP_CURSOR; 76338889Sjdp r->u.group_cursor = first; 76438889Sjdp r->res_info = *resinfo; 76538889Sjdp} 76638889Sjdp 76738889Sjdp/* Define a dialog resource. */ 76838889Sjdp 76938889Sjdpvoid 770130561Sobriendefine_dialog (struct res_id id, const struct res_res_info *resinfo, 771130561Sobrien const struct dialog *dialog) 77238889Sjdp{ 77338889Sjdp struct dialog *copy; 77438889Sjdp struct res_resource *r; 77538889Sjdp 77638889Sjdp copy = (struct dialog *) res_alloc (sizeof *copy); 77738889Sjdp *copy = *dialog; 77838889Sjdp 77938889Sjdp r = define_standard_resource (&resources, RT_DIALOG, id, 78038889Sjdp resinfo->language, 0); 78138889Sjdp r->type = RES_TYPE_DIALOG; 78238889Sjdp r->u.dialog = copy; 78338889Sjdp r->res_info = *resinfo; 78438889Sjdp} 78538889Sjdp 78638889Sjdp/* Define a dialog control. This does not define a resource, but 78738889Sjdp merely allocates and fills in a structure. */ 78838889Sjdp 78938889Sjdpstruct dialog_control * 790130561Sobriendefine_control (const struct res_id iid, unsigned long id, unsigned long x, 791130561Sobrien unsigned long y, unsigned long width, unsigned long height, 792130561Sobrien unsigned long class, unsigned long style, 793130561Sobrien unsigned long exstyle) 79438889Sjdp{ 79538889Sjdp struct dialog_control *n; 79638889Sjdp 79738889Sjdp n = (struct dialog_control *) res_alloc (sizeof *n); 79838889Sjdp n->next = NULL; 79938889Sjdp n->id = id; 80038889Sjdp n->style = style; 80138889Sjdp n->exstyle = exstyle; 80238889Sjdp n->x = x; 80338889Sjdp n->y = y; 80438889Sjdp n->width = width; 80538889Sjdp n->height = height; 80638889Sjdp n->class.named = 0; 80738889Sjdp n->class.u.id = class; 808130561Sobrien n->text = iid; 80938889Sjdp n->data = NULL; 81038889Sjdp n->help = 0; 81138889Sjdp 81238889Sjdp return n; 81338889Sjdp} 81438889Sjdp 81577298Sobrienstruct dialog_control * 816130561Sobriendefine_icon_control (struct res_id iid, unsigned long id, unsigned long x, 817130561Sobrien unsigned long y, unsigned long style, 818130561Sobrien unsigned long exstyle, unsigned long help, 819130561Sobrien struct rcdata_item *data, struct dialog_ex *ex) 82077298Sobrien{ 82177298Sobrien struct dialog_control *n; 822130561Sobrien struct res_id tid; 823130561Sobrien 82477298Sobrien if (style == 0) 82577298Sobrien style = SS_ICON | WS_CHILD | WS_VISIBLE; 826130561Sobrien res_string_to_id (&tid, ""); 827130561Sobrien n = define_control (tid, id, x, y, 0, 0, CTL_STATIC, style, exstyle); 82877298Sobrien n->text = iid; 82977298Sobrien if (help && !ex) 83077298Sobrien rcparse_warning (_("help ID requires DIALOGEX")); 83177298Sobrien if (data && !ex) 83277298Sobrien rcparse_warning (_("control data requires DIALOGEX")); 83377298Sobrien n->help = help; 83477298Sobrien n->data = data; 83577298Sobrien 83677298Sobrien return n; 83777298Sobrien} 83877298Sobrien 83938889Sjdp/* Define a font resource. */ 84038889Sjdp 84138889Sjdpvoid 842130561Sobriendefine_font (struct res_id id, const struct res_res_info *resinfo, 843130561Sobrien const char *filename) 84438889Sjdp{ 84538889Sjdp FILE *e; 84638889Sjdp char *real_filename; 84738889Sjdp struct stat s; 84838889Sjdp unsigned char *data; 84938889Sjdp struct res_resource *r; 85038889Sjdp long offset; 85138889Sjdp long fontdatalength; 85238889Sjdp unsigned char *fontdata; 85338889Sjdp struct fontdir *fd; 85438889Sjdp const char *device, *face; 85538889Sjdp struct fontdir **pp; 85638889Sjdp 85738889Sjdp e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); 85838889Sjdp 85938889Sjdp if (stat (real_filename, &s) < 0) 86060484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 86138889Sjdp strerror (errno)); 86238889Sjdp 86338889Sjdp data = (unsigned char *) res_alloc (s.st_size); 86438889Sjdp 86538889Sjdp get_data (e, data, s.st_size, real_filename); 86638889Sjdp 86738889Sjdp fclose (e); 86838889Sjdp free (real_filename); 86938889Sjdp 87038889Sjdp r = define_standard_resource (&resources, RT_FONT, id, 87138889Sjdp resinfo->language, 0); 87238889Sjdp 87338889Sjdp r->type = RES_TYPE_FONT; 87438889Sjdp r->u.data.length = s.st_size; 87538889Sjdp r->u.data.data = data; 87638889Sjdp r->res_info = *resinfo; 87738889Sjdp 87838889Sjdp /* For each font resource, we must add an entry in the FONTDIR 87938889Sjdp resource. The FONTDIR resource includes some strings in the font 88038889Sjdp file. To find them, we have to do some magic on the data we have 88138889Sjdp read. */ 88238889Sjdp 88338889Sjdp offset = ((((((data[47] << 8) 88438889Sjdp | data[46]) << 8) 88538889Sjdp | data[45]) << 8) 88638889Sjdp | data[44]); 88738889Sjdp if (offset > 0 && offset < s.st_size) 88838889Sjdp device = (char *) data + offset; 88938889Sjdp else 89038889Sjdp device = ""; 89138889Sjdp 89238889Sjdp offset = ((((((data[51] << 8) 89338889Sjdp | data[50]) << 8) 89438889Sjdp | data[49]) << 8) 89538889Sjdp | data[48]); 89638889Sjdp if (offset > 0 && offset < s.st_size) 89738889Sjdp face = (char *) data + offset; 89838889Sjdp else 89938889Sjdp face = ""; 90038889Sjdp 90138889Sjdp ++fonts; 90238889Sjdp 90338889Sjdp fontdatalength = 58 + strlen (device) + strlen (face); 90438889Sjdp fontdata = (unsigned char *) res_alloc (fontdatalength); 90538889Sjdp memcpy (fontdata, data, 56); 90638889Sjdp strcpy ((char *) fontdata + 56, device); 90738889Sjdp strcpy ((char *) fontdata + 57 + strlen (device), face); 90838889Sjdp 90938889Sjdp fd = (struct fontdir *) res_alloc (sizeof *fd); 91038889Sjdp fd->next = NULL; 91138889Sjdp fd->index = fonts; 91238889Sjdp fd->length = fontdatalength; 91338889Sjdp fd->data = fontdata; 91438889Sjdp 91538889Sjdp for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next) 91638889Sjdp ; 91738889Sjdp *pp = fd; 91838889Sjdp 91938889Sjdp /* For the single fontdirs resource, we always use the resource 92038889Sjdp information of the last font. I don't know what else to do. */ 92138889Sjdp fontdirs_resinfo = *resinfo; 92238889Sjdp} 92338889Sjdp 92438889Sjdp/* Define the fontdirs resource. This is called after the entire rc 92538889Sjdp file has been parsed, if any font resources were seen. */ 92638889Sjdp 92738889Sjdpstatic void 928130561Sobriendefine_fontdirs (void) 92938889Sjdp{ 93038889Sjdp struct res_resource *r; 93138889Sjdp struct res_id id; 93238889Sjdp 93338889Sjdp id.named = 0; 93438889Sjdp id.u.id = 1; 93538889Sjdp 93638889Sjdp r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0); 93738889Sjdp 93838889Sjdp r->type = RES_TYPE_FONTDIR; 93938889Sjdp r->u.fontdir = fontdirs; 94038889Sjdp r->res_info = fontdirs_resinfo; 94138889Sjdp} 94238889Sjdp 94338889Sjdp/* Define an icon resource. An icon file may contain a set of 94438889Sjdp bitmaps, each representing the same icon at various different 94538889Sjdp resolutions. They each get written out with a different ID. The 94638889Sjdp real icon resource is then a group resource which can be used to 94738889Sjdp select one of the actual icon bitmaps. */ 94838889Sjdp 94938889Sjdpvoid 950130561Sobriendefine_icon (struct res_id id, const struct res_res_info *resinfo, 951130561Sobrien const char *filename) 95238889Sjdp{ 95338889Sjdp FILE *e; 95438889Sjdp char *real_filename; 95538889Sjdp int type, count, i; 95638889Sjdp struct icondir *icondirs; 95738889Sjdp int first_icon; 95838889Sjdp struct res_resource *r; 95938889Sjdp struct group_icon *first, **pp; 96038889Sjdp 96138889Sjdp e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename); 96238889Sjdp 96338889Sjdp /* The start of an icon file is a three word structure. The first 96438889Sjdp word is ignored. The second word is the type of data. The third 96538889Sjdp word is the number of entries. */ 96638889Sjdp 96738889Sjdp get_word (e, real_filename); 96838889Sjdp type = get_word (e, real_filename); 96938889Sjdp count = get_word (e, real_filename); 97038889Sjdp if (type != 1) 97160484Sobrien fatal (_("icon file `%s' does not contain icon data"), real_filename); 97238889Sjdp 97338889Sjdp /* Read in the icon directory entries. */ 97438889Sjdp 97538889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 97638889Sjdp 97738889Sjdp for (i = 0; i < count; i++) 97838889Sjdp { 97938889Sjdp icondirs[i].width = getc (e); 98038889Sjdp icondirs[i].height = getc (e); 98138889Sjdp icondirs[i].colorcount = getc (e); 98238889Sjdp getc (e); 98338889Sjdp icondirs[i].u.icon.planes = get_word (e, real_filename); 98438889Sjdp icondirs[i].u.icon.bits = get_word (e, real_filename); 98538889Sjdp icondirs[i].bytes = get_long (e, real_filename); 98638889Sjdp icondirs[i].offset = get_long (e, real_filename); 98738889Sjdp 98838889Sjdp if (feof (e)) 98938889Sjdp unexpected_eof (real_filename); 99038889Sjdp } 99138889Sjdp 99238889Sjdp /* Define each icon as a unique resource. */ 99338889Sjdp 99438889Sjdp first_icon = icons; 99538889Sjdp 99638889Sjdp for (i = 0; i < count; i++) 99738889Sjdp { 99838889Sjdp unsigned char *data; 99938889Sjdp struct res_id name; 100038889Sjdp 100138889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 100260484Sobrien fatal (_("%s: fseek to %lu failed: %s"), real_filename, 100338889Sjdp icondirs[i].offset, strerror (errno)); 100438889Sjdp 100538889Sjdp data = (unsigned char *) res_alloc (icondirs[i].bytes); 100638889Sjdp 100738889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 100838889Sjdp 100938889Sjdp ++icons; 101038889Sjdp 101138889Sjdp name.named = 0; 101238889Sjdp name.u.id = icons; 101338889Sjdp 101438889Sjdp r = define_standard_resource (&resources, RT_ICON, name, 101538889Sjdp resinfo->language, 0); 101638889Sjdp r->type = RES_TYPE_ICON; 101738889Sjdp r->u.data.length = icondirs[i].bytes; 101838889Sjdp r->u.data.data = data; 101938889Sjdp r->res_info = *resinfo; 102038889Sjdp } 102138889Sjdp 102238889Sjdp fclose (e); 102338889Sjdp free (real_filename); 102438889Sjdp 102538889Sjdp /* Define an icon group resource. */ 102638889Sjdp 102738889Sjdp first = NULL; 102838889Sjdp pp = &first; 102938889Sjdp for (i = 0; i < count; i++) 103038889Sjdp { 103138889Sjdp struct group_icon *cg; 103238889Sjdp 103338889Sjdp /* For some reason, at least in some files the planes and bits 103438889Sjdp are zero. We instead set them from the color. This is 103538889Sjdp copied from rcl. */ 103638889Sjdp 103738889Sjdp cg = (struct group_icon *) res_alloc (sizeof *cg); 103838889Sjdp cg->next = NULL; 103938889Sjdp cg->width = icondirs[i].width; 104038889Sjdp cg->height = icondirs[i].height; 104138889Sjdp cg->colors = icondirs[i].colorcount; 104238889Sjdp 1043130561Sobrien if (icondirs[i].u.icon.planes) 1044130561Sobrien cg->planes = icondirs[i].u.icon.planes; 1045130561Sobrien else 1046130561Sobrien cg->planes = 1; 104738889Sjdp 1048130561Sobrien if (icondirs[i].u.icon.bits) 1049130561Sobrien cg->bits = icondirs[i].u.icon.bits; 1050130561Sobrien else 1051130561Sobrien { 1052130561Sobrien cg->bits = 0; 1053130561Sobrien 1054130561Sobrien while ((1L << cg->bits) < cg->colors) 1055130561Sobrien ++cg->bits; 1056130561Sobrien } 1057130561Sobrien 105838889Sjdp cg->bytes = icondirs[i].bytes; 105938889Sjdp cg->index = first_icon + i + 1; 106038889Sjdp 106138889Sjdp *pp = cg; 106238889Sjdp pp = &(*pp)->next; 106338889Sjdp } 106438889Sjdp 106538889Sjdp free (icondirs); 106638889Sjdp 106738889Sjdp r = define_standard_resource (&resources, RT_GROUP_ICON, id, 106838889Sjdp resinfo->language, 0); 106938889Sjdp r->type = RES_TYPE_GROUP_ICON; 107038889Sjdp r->u.group_icon = first; 107138889Sjdp r->res_info = *resinfo; 107238889Sjdp} 107338889Sjdp 107438889Sjdp/* Define a menu resource. */ 107538889Sjdp 107638889Sjdpvoid 1077130561Sobriendefine_menu (struct res_id id, const struct res_res_info *resinfo, 1078130561Sobrien struct menuitem *menuitems) 107938889Sjdp{ 108038889Sjdp struct menu *m; 108138889Sjdp struct res_resource *r; 108238889Sjdp 108338889Sjdp m = (struct menu *) res_alloc (sizeof *m); 108438889Sjdp m->items = menuitems; 108538889Sjdp m->help = 0; 108638889Sjdp 108738889Sjdp r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0); 108838889Sjdp r->type = RES_TYPE_MENU; 108938889Sjdp r->u.menu = m; 109038889Sjdp r->res_info = *resinfo; 109138889Sjdp} 109238889Sjdp 109338889Sjdp/* Define a menu item. This does not define a resource, but merely 109438889Sjdp allocates and fills in a structure. */ 109538889Sjdp 109638889Sjdpstruct menuitem * 1097130561Sobriendefine_menuitem (const char *text, int menuid, unsigned long type, 1098130561Sobrien unsigned long state, unsigned long help, 1099130561Sobrien struct menuitem *menuitems) 110038889Sjdp{ 110138889Sjdp struct menuitem *mi; 110238889Sjdp 110338889Sjdp mi = (struct menuitem *) res_alloc (sizeof *mi); 110438889Sjdp mi->next = NULL; 110538889Sjdp mi->type = type; 110638889Sjdp mi->state = state; 110738889Sjdp mi->id = menuid; 110838889Sjdp if (text == NULL) 110938889Sjdp mi->text = NULL; 111038889Sjdp else 111138889Sjdp unicode_from_ascii ((int *) NULL, &mi->text, text); 111238889Sjdp mi->help = help; 111338889Sjdp mi->popup = menuitems; 111438889Sjdp return mi; 111538889Sjdp} 111638889Sjdp 111738889Sjdp/* Define a messagetable resource. */ 111838889Sjdp 111938889Sjdpvoid 1120130561Sobriendefine_messagetable (struct res_id id, const struct res_res_info *resinfo, 1121130561Sobrien const char *filename) 112238889Sjdp{ 112338889Sjdp FILE *e; 112438889Sjdp char *real_filename; 112538889Sjdp struct stat s; 112638889Sjdp unsigned char *data; 112738889Sjdp struct res_resource *r; 112838889Sjdp 112938889Sjdp e = open_file_search (filename, FOPEN_RB, "messagetable file", 113038889Sjdp &real_filename); 113138889Sjdp 113238889Sjdp if (stat (real_filename, &s) < 0) 113360484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 113438889Sjdp strerror (errno)); 113538889Sjdp 113638889Sjdp data = (unsigned char *) res_alloc (s.st_size); 113738889Sjdp 113838889Sjdp get_data (e, data, s.st_size, real_filename); 113938889Sjdp 114038889Sjdp fclose (e); 114138889Sjdp free (real_filename); 114238889Sjdp 114338889Sjdp r = define_standard_resource (&resources, RT_MESSAGETABLE, id, 114438889Sjdp resinfo->language, 0); 114538889Sjdp 114638889Sjdp r->type = RES_TYPE_MESSAGETABLE; 114738889Sjdp r->u.data.length = s.st_size; 114838889Sjdp r->u.data.data = data; 114938889Sjdp r->res_info = *resinfo; 115038889Sjdp} 115138889Sjdp 115238889Sjdp/* Define an rcdata resource. */ 115338889Sjdp 115438889Sjdpvoid 1155130561Sobriendefine_rcdata (struct res_id id, const struct res_res_info *resinfo, 1156130561Sobrien struct rcdata_item *data) 115738889Sjdp{ 115838889Sjdp struct res_resource *r; 115938889Sjdp 116038889Sjdp r = define_standard_resource (&resources, RT_RCDATA, id, 116138889Sjdp resinfo->language, 0); 116238889Sjdp r->type = RES_TYPE_RCDATA; 116338889Sjdp r->u.rcdata = data; 116438889Sjdp r->res_info = *resinfo; 116538889Sjdp} 116638889Sjdp 116738889Sjdp/* Create an rcdata item holding a string. */ 116838889Sjdp 116938889Sjdpstruct rcdata_item * 1170130561Sobriendefine_rcdata_string (const char *string, unsigned long len) 117138889Sjdp{ 117238889Sjdp struct rcdata_item *ri; 117338889Sjdp char *s; 117438889Sjdp 117538889Sjdp ri = (struct rcdata_item *) res_alloc (sizeof *ri); 117638889Sjdp ri->next = NULL; 117738889Sjdp ri->type = RCDATA_STRING; 117838889Sjdp ri->u.string.length = len; 117938889Sjdp s = (char *) res_alloc (len); 118038889Sjdp memcpy (s, string, len); 118138889Sjdp ri->u.string.s = s; 118238889Sjdp 118338889Sjdp return ri; 118438889Sjdp} 118538889Sjdp 118638889Sjdp/* Create an rcdata item holding a number. */ 118738889Sjdp 118838889Sjdpstruct rcdata_item * 1189130561Sobriendefine_rcdata_number (unsigned long val, int dword) 119038889Sjdp{ 119138889Sjdp struct rcdata_item *ri; 119238889Sjdp 119338889Sjdp ri = (struct rcdata_item *) res_alloc (sizeof *ri); 119438889Sjdp ri->next = NULL; 119538889Sjdp ri->type = dword ? RCDATA_DWORD : RCDATA_WORD; 119638889Sjdp ri->u.word = val; 119738889Sjdp 119838889Sjdp return ri; 119938889Sjdp} 120038889Sjdp 120138889Sjdp/* Define a stringtable resource. This is called for each string 120238889Sjdp which appears in a STRINGTABLE statement. */ 120338889Sjdp 120438889Sjdpvoid 1205130561Sobriendefine_stringtable (const struct res_res_info *resinfo, 1206130561Sobrien unsigned long stringid, const char *string) 120738889Sjdp{ 120838889Sjdp struct res_id id; 120938889Sjdp struct res_resource *r; 121038889Sjdp 121138889Sjdp id.named = 0; 121238889Sjdp id.u.id = (stringid >> 4) + 1; 121338889Sjdp r = define_standard_resource (&resources, RT_STRING, id, 121438889Sjdp resinfo->language, 1); 121538889Sjdp 121638889Sjdp if (r->type == RES_TYPE_UNINITIALIZED) 121738889Sjdp { 121838889Sjdp int i; 121938889Sjdp 122038889Sjdp r->type = RES_TYPE_STRINGTABLE; 122138889Sjdp r->u.stringtable = ((struct stringtable *) 122238889Sjdp res_alloc (sizeof (struct stringtable))); 122338889Sjdp for (i = 0; i < 16; i++) 122438889Sjdp { 122538889Sjdp r->u.stringtable->strings[i].length = 0; 122638889Sjdp r->u.stringtable->strings[i].string = NULL; 122738889Sjdp } 122838889Sjdp 122938889Sjdp r->res_info = *resinfo; 123038889Sjdp } 123138889Sjdp 123238889Sjdp unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length, 123338889Sjdp &r->u.stringtable->strings[stringid & 0xf].string, 123438889Sjdp string); 123538889Sjdp} 123638889Sjdp 123738889Sjdp/* Define a user data resource where the data is in the rc file. */ 123838889Sjdp 123938889Sjdpvoid 1240130561Sobriendefine_user_data (struct res_id id, struct res_id type, 1241130561Sobrien const struct res_res_info *resinfo, 1242130561Sobrien struct rcdata_item *data) 124338889Sjdp{ 124438889Sjdp struct res_id ids[3]; 124538889Sjdp struct res_resource *r; 124638889Sjdp 124738889Sjdp ids[0] = type; 124838889Sjdp ids[1] = id; 124938889Sjdp ids[2].named = 0; 125038889Sjdp ids[2].u.id = resinfo->language; 125138889Sjdp 125238889Sjdp r = define_resource (&resources, 3, ids, 0); 125338889Sjdp r->type = RES_TYPE_USERDATA; 125438889Sjdp r->u.userdata = data; 125538889Sjdp r->res_info = *resinfo; 125638889Sjdp} 125738889Sjdp 125838889Sjdp/* Define a user data resource where the data is in a file. */ 125938889Sjdp 126038889Sjdpvoid 1261130561Sobriendefine_user_file (struct res_id id, struct res_id type, 1262130561Sobrien const struct res_res_info *resinfo, const char *filename) 126338889Sjdp{ 126438889Sjdp FILE *e; 126538889Sjdp char *real_filename; 126638889Sjdp struct stat s; 126738889Sjdp unsigned char *data; 126838889Sjdp struct res_id ids[3]; 126938889Sjdp struct res_resource *r; 127038889Sjdp 127138889Sjdp e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); 127238889Sjdp 127338889Sjdp if (stat (real_filename, &s) < 0) 127460484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 127538889Sjdp strerror (errno)); 127638889Sjdp 127738889Sjdp data = (unsigned char *) res_alloc (s.st_size); 127838889Sjdp 127938889Sjdp get_data (e, data, s.st_size, real_filename); 128038889Sjdp 128138889Sjdp fclose (e); 128238889Sjdp free (real_filename); 128338889Sjdp 128438889Sjdp ids[0] = type; 128538889Sjdp ids[1] = id; 128638889Sjdp ids[2].named = 0; 128738889Sjdp ids[2].u.id = resinfo->language; 128838889Sjdp 128938889Sjdp r = define_resource (&resources, 3, ids, 0); 129038889Sjdp r->type = RES_TYPE_USERDATA; 129138889Sjdp r->u.userdata = ((struct rcdata_item *) 129238889Sjdp res_alloc (sizeof (struct rcdata_item))); 129338889Sjdp r->u.userdata->next = NULL; 129438889Sjdp r->u.userdata->type = RCDATA_BUFFER; 129538889Sjdp r->u.userdata->u.buffer.length = s.st_size; 129638889Sjdp r->u.userdata->u.buffer.data = data; 129738889Sjdp r->res_info = *resinfo; 129838889Sjdp} 129938889Sjdp 130038889Sjdp/* Define a versioninfo resource. */ 130138889Sjdp 130238889Sjdpvoid 1303130561Sobriendefine_versioninfo (struct res_id id, int language, 1304130561Sobrien struct fixed_versioninfo *fixedverinfo, 1305130561Sobrien struct ver_info *verinfo) 130638889Sjdp{ 130738889Sjdp struct res_resource *r; 130838889Sjdp 130938889Sjdp r = define_standard_resource (&resources, RT_VERSION, id, language, 0); 131038889Sjdp r->type = RES_TYPE_VERSIONINFO; 131138889Sjdp r->u.versioninfo = ((struct versioninfo *) 131238889Sjdp res_alloc (sizeof (struct versioninfo))); 131338889Sjdp r->u.versioninfo->fixed = fixedverinfo; 131438889Sjdp r->u.versioninfo->var = verinfo; 131538889Sjdp r->res_info.language = language; 131638889Sjdp} 131738889Sjdp 131838889Sjdp/* Add string version info to a list of version information. */ 131938889Sjdp 132038889Sjdpstruct ver_info * 1321130561Sobrienappend_ver_stringfileinfo (struct ver_info *verinfo, const char *language, 1322130561Sobrien struct ver_stringinfo *strings) 132338889Sjdp{ 132438889Sjdp struct ver_info *vi, **pp; 132538889Sjdp 132638889Sjdp vi = (struct ver_info *) res_alloc (sizeof *vi); 132738889Sjdp vi->next = NULL; 132838889Sjdp vi->type = VERINFO_STRING; 132938889Sjdp unicode_from_ascii ((int *) NULL, &vi->u.string.language, language); 133038889Sjdp vi->u.string.strings = strings; 133138889Sjdp 133238889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 133338889Sjdp ; 133438889Sjdp *pp = vi; 133538889Sjdp 133638889Sjdp return verinfo; 133738889Sjdp} 133838889Sjdp 133938889Sjdp/* Add variable version info to a list of version information. */ 134038889Sjdp 134138889Sjdpstruct ver_info * 1342130561Sobrienappend_ver_varfileinfo (struct ver_info *verinfo, const char *key, 1343130561Sobrien struct ver_varinfo *var) 134438889Sjdp{ 134538889Sjdp struct ver_info *vi, **pp; 134638889Sjdp 134738889Sjdp vi = (struct ver_info *) res_alloc (sizeof *vi); 134838889Sjdp vi->next = NULL; 134938889Sjdp vi->type = VERINFO_VAR; 135038889Sjdp unicode_from_ascii ((int *) NULL, &vi->u.var.key, key); 135138889Sjdp vi->u.var.var = var; 135238889Sjdp 135338889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 135438889Sjdp ; 135538889Sjdp *pp = vi; 135638889Sjdp 135738889Sjdp return verinfo; 135838889Sjdp} 135938889Sjdp 136038889Sjdp/* Append version string information to a list. */ 136138889Sjdp 136238889Sjdpstruct ver_stringinfo * 1363130561Sobrienappend_verval (struct ver_stringinfo *strings, const char *key, 1364130561Sobrien const char *value) 136538889Sjdp{ 136638889Sjdp struct ver_stringinfo *vs, **pp; 136738889Sjdp 136838889Sjdp vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); 136938889Sjdp vs->next = NULL; 137038889Sjdp unicode_from_ascii ((int *) NULL, &vs->key, key); 137138889Sjdp unicode_from_ascii ((int *) NULL, &vs->value, value); 137238889Sjdp 137338889Sjdp for (pp = &strings; *pp != NULL; pp = &(*pp)->next) 137438889Sjdp ; 137538889Sjdp *pp = vs; 137638889Sjdp 137738889Sjdp return strings; 137838889Sjdp} 137938889Sjdp 138038889Sjdp/* Append version variable information to a list. */ 138138889Sjdp 138238889Sjdpstruct ver_varinfo * 1383130561Sobrienappend_vertrans (struct ver_varinfo *var, unsigned long language, 1384130561Sobrien unsigned long charset) 138538889Sjdp{ 138638889Sjdp struct ver_varinfo *vv, **pp; 138738889Sjdp 138838889Sjdp vv = (struct ver_varinfo *) res_alloc (sizeof *vv); 138938889Sjdp vv->next = NULL; 139038889Sjdp vv->language = language; 139138889Sjdp vv->charset = charset; 139238889Sjdp 139338889Sjdp for (pp = &var; *pp != NULL; pp = &(*pp)->next) 139438889Sjdp ; 139538889Sjdp *pp = vv; 139638889Sjdp 139738889Sjdp return var; 139838889Sjdp} 139938889Sjdp 140038889Sjdp/* Local functions used to write out an rc file. */ 140138889Sjdp 1402130561Sobrienstatic void indent (FILE *, int); 140338889Sjdpstatic void write_rc_directory 1404130561Sobrien (FILE *, const struct res_directory *, const struct res_id *, 1405130561Sobrien const struct res_id *, int *, int); 140638889Sjdpstatic void write_rc_subdir 1407130561Sobrien (FILE *, const struct res_entry *, const struct res_id *, 1408130561Sobrien const struct res_id *, int *, int); 140938889Sjdpstatic void write_rc_resource 1410130561Sobrien (FILE *, const struct res_id *, const struct res_id *, 1411130561Sobrien const struct res_resource *, int *); 1412130561Sobrienstatic void write_rc_accelerators (FILE *, const struct accelerator *); 1413130561Sobrienstatic void write_rc_cursor (FILE *, const struct cursor *); 1414130561Sobrienstatic void write_rc_group_cursor (FILE *, const struct group_cursor *); 1415130561Sobrienstatic void write_rc_dialog (FILE *, const struct dialog *); 1416130561Sobrienstatic void write_rc_dialog_control (FILE *, const struct dialog_control *); 1417130561Sobrienstatic void write_rc_fontdir (FILE *, const struct fontdir *); 1418130561Sobrienstatic void write_rc_group_icon (FILE *, const struct group_icon *); 1419130561Sobrienstatic void write_rc_menu (FILE *, const struct menu *, int); 1420130561Sobrienstatic void write_rc_menuitems (FILE *, const struct menuitem *, int, int); 1421130561Sobrienstatic void write_rc_rcdata (FILE *, const struct rcdata_item *, int); 142238889Sjdpstatic void write_rc_stringtable 1423130561Sobrien (FILE *, const struct res_id *, const struct stringtable *); 1424130561Sobrienstatic void write_rc_versioninfo (FILE *, const struct versioninfo *); 1425130561Sobrienstatic void write_rc_filedata (FILE *, unsigned long, const unsigned char *); 142638889Sjdp 142738889Sjdp/* Indent a given number of spaces. */ 142838889Sjdp 142938889Sjdpstatic void 1430130561Sobrienindent (FILE *e, int c) 143138889Sjdp{ 143238889Sjdp int i; 143338889Sjdp 143438889Sjdp for (i = 0; i < c; i++) 143538889Sjdp putc (' ', e); 143638889Sjdp} 143738889Sjdp 143838889Sjdp/* Dump the resources we have read in the format of an rc file. 143938889Sjdp 144038889Sjdp Actually, we don't use the format of an rc file, because it's way 144138889Sjdp too much of a pain--for example, we'd have to write icon resources 144238889Sjdp into a file and refer to that file. We just generate a readable 144338889Sjdp format that kind of looks like an rc file, and is useful for 144438889Sjdp understanding the contents of a resource file. Someday we may want 144538889Sjdp to generate an rc file which the rc compiler can read; if that day 144638889Sjdp comes, this code will have to be fixed up. */ 144738889Sjdp 144838889Sjdpvoid 1449130561Sobrienwrite_rc_file (const char *filename, const struct res_directory *resources) 145038889Sjdp{ 145138889Sjdp FILE *e; 145238889Sjdp int language; 145338889Sjdp 145438889Sjdp if (filename == NULL) 145538889Sjdp e = stdout; 145638889Sjdp else 145738889Sjdp { 145838889Sjdp e = fopen (filename, FOPEN_WT); 145938889Sjdp if (e == NULL) 146060484Sobrien fatal (_("can't open `%s' for output: %s"), filename, strerror (errno)); 146138889Sjdp } 146238889Sjdp 146338889Sjdp language = -1; 146438889Sjdp write_rc_directory (e, resources, (const struct res_id *) NULL, 146538889Sjdp (const struct res_id *) NULL, &language, 1); 146638889Sjdp} 146738889Sjdp 146838889Sjdp/* Write out a directory. E is the file to write to. RD is the 146938889Sjdp directory. TYPE is a pointer to the level 1 ID which serves as the 147038889Sjdp resource type. NAME is a pointer to the level 2 ID which serves as 147138889Sjdp an individual resource name. LANGUAGE is a pointer to the current 147238889Sjdp language. LEVEL is the level in the tree. */ 147338889Sjdp 147438889Sjdpstatic void 1475130561Sobrienwrite_rc_directory (FILE *e, const struct res_directory *rd, 1476130561Sobrien const struct res_id *type, const struct res_id *name, 1477130561Sobrien int *language, int level) 147838889Sjdp{ 147938889Sjdp const struct res_entry *re; 148038889Sjdp 148138889Sjdp /* Print out some COFF information that rc files can't represent. */ 148238889Sjdp 148338889Sjdp if (rd->time != 0) 148438889Sjdp fprintf (e, "// Time stamp: %lu\n", rd->time); 148538889Sjdp if (rd->characteristics != 0) 148638889Sjdp fprintf (e, "// Characteristics: %lu\n", rd->characteristics); 148738889Sjdp if (rd->major != 0 || rd->minor != 0) 148838889Sjdp fprintf (e, "// Version: %d %d\n", rd->major, rd->minor); 148938889Sjdp 149038889Sjdp for (re = rd->entries; re != NULL; re = re->next) 149138889Sjdp { 149238889Sjdp switch (level) 149338889Sjdp { 149438889Sjdp case 1: 149538889Sjdp /* If we're at level 1, the key of this resource is the 149638889Sjdp type. This normally duplicates the information we have 149738889Sjdp stored with the resource itself, but we need to remember 149838889Sjdp the type if this is a user define resource type. */ 149938889Sjdp type = &re->id; 150038889Sjdp break; 150138889Sjdp 150238889Sjdp case 2: 150338889Sjdp /* If we're at level 2, the key of this resource is the name 150499461Sobrien we are going to use in the rc printout. */ 150538889Sjdp name = &re->id; 150638889Sjdp break; 150738889Sjdp 150838889Sjdp case 3: 150938889Sjdp /* If we're at level 3, then this key represents a language. 151038889Sjdp Use it to update the current language. */ 151138889Sjdp if (! re->id.named 151260484Sobrien && re->id.u.id != (unsigned long) (unsigned int) *language 151338889Sjdp && (re->id.u.id & 0xffff) == re->id.u.id) 151438889Sjdp { 151538889Sjdp fprintf (e, "LANGUAGE %lu, %lu\n", 1516104834Sobrien re->id.u.id & ((1 << SUBLANG_SHIFT) - 1), 151799461Sobrien (re->id.u.id >> SUBLANG_SHIFT) & 0xff); 151838889Sjdp *language = re->id.u.id; 151938889Sjdp } 152038889Sjdp break; 152138889Sjdp 152238889Sjdp default: 152338889Sjdp break; 152438889Sjdp } 152538889Sjdp 152638889Sjdp if (re->subdir) 152738889Sjdp write_rc_subdir (e, re, type, name, language, level); 152838889Sjdp else 152938889Sjdp { 153038889Sjdp if (level == 3) 153138889Sjdp { 153238889Sjdp /* This is the normal case: the three levels are 153338889Sjdp TYPE/NAME/LANGUAGE. NAME will have been set at level 153438889Sjdp 2, and represents the name to use. We probably just 153538889Sjdp set LANGUAGE, and it will probably match what the 153638889Sjdp resource itself records if anything. */ 153738889Sjdp write_rc_resource (e, type, name, re->u.res, language); 153838889Sjdp } 153938889Sjdp else 154038889Sjdp { 154138889Sjdp fprintf (e, "// Resource at unexpected level %d\n", level); 154238889Sjdp write_rc_resource (e, type, (struct res_id *) NULL, re->u.res, 154338889Sjdp language); 154438889Sjdp } 154538889Sjdp } 154638889Sjdp } 154738889Sjdp} 154838889Sjdp 154938889Sjdp/* Write out a subdirectory entry. E is the file to write to. RE is 155038889Sjdp the subdirectory entry. TYPE and NAME are pointers to higher level 155138889Sjdp IDs, or NULL. LANGUAGE is a pointer to the current language. 155238889Sjdp LEVEL is the level in the tree. */ 155338889Sjdp 155438889Sjdpstatic void 1555130561Sobrienwrite_rc_subdir (FILE *e, const struct res_entry *re, 1556130561Sobrien const struct res_id *type, const struct res_id *name, 1557130561Sobrien int *language, int level) 155838889Sjdp{ 155938889Sjdp fprintf (e, "\n"); 156038889Sjdp switch (level) 156138889Sjdp { 156238889Sjdp case 1: 156338889Sjdp fprintf (e, "// Type: "); 156438889Sjdp if (re->id.named) 156538889Sjdp res_id_print (e, re->id, 1); 156638889Sjdp else 156738889Sjdp { 156838889Sjdp const char *s; 156938889Sjdp 157038889Sjdp switch (re->id.u.id) 157138889Sjdp { 157238889Sjdp case RT_CURSOR: s = "cursor"; break; 157338889Sjdp case RT_BITMAP: s = "bitmap"; break; 157438889Sjdp case RT_ICON: s = "icon"; break; 157538889Sjdp case RT_MENU: s = "menu"; break; 157638889Sjdp case RT_DIALOG: s = "dialog"; break; 157738889Sjdp case RT_STRING: s = "stringtable"; break; 157838889Sjdp case RT_FONTDIR: s = "fontdir"; break; 157938889Sjdp case RT_FONT: s = "font"; break; 158060484Sobrien case RT_ACCELERATOR: s = "accelerators"; break; 158138889Sjdp case RT_RCDATA: s = "rcdata"; break; 158238889Sjdp case RT_MESSAGETABLE: s = "messagetable"; break; 158338889Sjdp case RT_GROUP_CURSOR: s = "group cursor"; break; 158438889Sjdp case RT_GROUP_ICON: s = "group icon"; break; 158538889Sjdp case RT_VERSION: s = "version"; break; 158638889Sjdp case RT_DLGINCLUDE: s = "dlginclude"; break; 158738889Sjdp case RT_PLUGPLAY: s = "plugplay"; break; 158838889Sjdp case RT_VXD: s = "vxd"; break; 158938889Sjdp case RT_ANICURSOR: s = "anicursor"; break; 159038889Sjdp case RT_ANIICON: s = "aniicon"; break; 159138889Sjdp default: s = NULL; break; 159238889Sjdp } 159338889Sjdp 159438889Sjdp if (s != NULL) 159538889Sjdp fprintf (e, "%s", s); 159638889Sjdp else 159738889Sjdp res_id_print (e, re->id, 1); 159838889Sjdp } 159938889Sjdp fprintf (e, "\n"); 160038889Sjdp break; 160138889Sjdp 160238889Sjdp case 2: 160338889Sjdp fprintf (e, "// Name: "); 160438889Sjdp res_id_print (e, re->id, 1); 160538889Sjdp fprintf (e, "\n"); 160638889Sjdp break; 160738889Sjdp 160838889Sjdp case 3: 160938889Sjdp fprintf (e, "// Language: "); 161038889Sjdp res_id_print (e, re->id, 1); 161138889Sjdp fprintf (e, "\n"); 161238889Sjdp break; 161338889Sjdp 161438889Sjdp default: 161538889Sjdp fprintf (e, "// Level %d: ", level); 161638889Sjdp res_id_print (e, re->id, 1); 161738889Sjdp fprintf (e, "\n"); 1618104834Sobrien } 161938889Sjdp 162038889Sjdp write_rc_directory (e, re->u.dir, type, name, language, level + 1); 162138889Sjdp} 162238889Sjdp 162338889Sjdp/* Write out a single resource. E is the file to write to. TYPE is a 162438889Sjdp pointer to the type of the resource. NAME is a pointer to the name 162538889Sjdp of the resource; it will be NULL if there is a level mismatch. RES 162638889Sjdp is the resource data. LANGUAGE is a pointer to the current 162738889Sjdp language. */ 162838889Sjdp 162938889Sjdpstatic void 1630130561Sobrienwrite_rc_resource (FILE *e, const struct res_id *type, 1631130561Sobrien const struct res_id *name, const struct res_resource *res, 1632130561Sobrien int *language) 163338889Sjdp{ 163438889Sjdp const char *s; 163538889Sjdp int rt; 163638889Sjdp int menuex = 0; 163738889Sjdp 163838889Sjdp fprintf (e, "\n"); 163938889Sjdp 164038889Sjdp switch (res->type) 164138889Sjdp { 164238889Sjdp default: 164338889Sjdp abort (); 164438889Sjdp 164538889Sjdp case RES_TYPE_ACCELERATOR: 164638889Sjdp s = "ACCELERATOR"; 164760484Sobrien rt = RT_ACCELERATOR; 164838889Sjdp break; 164938889Sjdp 165038889Sjdp case RES_TYPE_BITMAP: 165138889Sjdp s = "BITMAP"; 165238889Sjdp rt = RT_BITMAP; 165338889Sjdp break; 165438889Sjdp 165538889Sjdp case RES_TYPE_CURSOR: 165638889Sjdp s = "CURSOR"; 165738889Sjdp rt = RT_CURSOR; 165838889Sjdp break; 165938889Sjdp 166038889Sjdp case RES_TYPE_GROUP_CURSOR: 166138889Sjdp s = "GROUP_CURSOR"; 166238889Sjdp rt = RT_GROUP_CURSOR; 166338889Sjdp break; 166438889Sjdp 166538889Sjdp case RES_TYPE_DIALOG: 166638889Sjdp if (extended_dialog (res->u.dialog)) 166738889Sjdp s = "DIALOGEX"; 166838889Sjdp else 166938889Sjdp s = "DIALOG"; 167038889Sjdp rt = RT_DIALOG; 167138889Sjdp break; 167238889Sjdp 167338889Sjdp case RES_TYPE_FONT: 167438889Sjdp s = "FONT"; 167538889Sjdp rt = RT_FONT; 167638889Sjdp break; 167738889Sjdp 167838889Sjdp case RES_TYPE_FONTDIR: 167938889Sjdp s = "FONTDIR"; 168038889Sjdp rt = RT_FONTDIR; 168138889Sjdp break; 168238889Sjdp 168338889Sjdp case RES_TYPE_ICON: 168438889Sjdp s = "ICON"; 168538889Sjdp rt = RT_ICON; 168638889Sjdp break; 168738889Sjdp 168838889Sjdp case RES_TYPE_GROUP_ICON: 168938889Sjdp s = "GROUP_ICON"; 169038889Sjdp rt = RT_GROUP_ICON; 169138889Sjdp break; 169238889Sjdp 169338889Sjdp case RES_TYPE_MENU: 169438889Sjdp if (extended_menu (res->u.menu)) 169538889Sjdp { 169638889Sjdp s = "MENUEX"; 169738889Sjdp menuex = 1; 169838889Sjdp } 169938889Sjdp else 170038889Sjdp { 170138889Sjdp s = "MENU"; 170238889Sjdp menuex = 0; 170338889Sjdp } 170438889Sjdp rt = RT_MENU; 170538889Sjdp break; 170638889Sjdp 170738889Sjdp case RES_TYPE_MESSAGETABLE: 170838889Sjdp s = "MESSAGETABLE"; 170938889Sjdp rt = RT_MESSAGETABLE; 171038889Sjdp break; 171138889Sjdp 171238889Sjdp case RES_TYPE_RCDATA: 171338889Sjdp s = "RCDATA"; 171438889Sjdp rt = RT_RCDATA; 171538889Sjdp break; 171638889Sjdp 171738889Sjdp case RES_TYPE_STRINGTABLE: 171838889Sjdp s = "STRINGTABLE"; 171938889Sjdp rt = RT_STRING; 172038889Sjdp break; 172138889Sjdp 172238889Sjdp case RES_TYPE_USERDATA: 172338889Sjdp s = NULL; 172438889Sjdp rt = 0; 172538889Sjdp break; 172638889Sjdp 172738889Sjdp case RES_TYPE_VERSIONINFO: 172838889Sjdp s = "VERSIONINFO"; 172938889Sjdp rt = RT_VERSION; 173038889Sjdp break; 173138889Sjdp } 173238889Sjdp 173338889Sjdp if (rt != 0 173438889Sjdp && type != NULL 173560484Sobrien && (type->named || type->u.id != (unsigned long) rt)) 173638889Sjdp { 173738889Sjdp fprintf (e, "// Unexpected resource type mismatch: "); 173838889Sjdp res_id_print (e, *type, 1); 173938889Sjdp fprintf (e, " != %d", rt); 174038889Sjdp } 174138889Sjdp 174238889Sjdp if (res->coff_info.codepage != 0) 174338889Sjdp fprintf (e, "// Code page: %lu\n", res->coff_info.codepage); 174438889Sjdp if (res->coff_info.reserved != 0) 174538889Sjdp fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved); 174638889Sjdp 174738889Sjdp if (name != NULL) 174838889Sjdp res_id_print (e, *name, 0); 174938889Sjdp else 175038889Sjdp fprintf (e, "??Unknown-Name??"); 175138889Sjdp 175238889Sjdp fprintf (e, " "); 175338889Sjdp if (s != NULL) 175438889Sjdp fprintf (e, "%s", s); 175538889Sjdp else if (type != NULL) 175638889Sjdp res_id_print (e, *type, 0); 175738889Sjdp else 175838889Sjdp fprintf (e, "??Unknown-Type??"); 175938889Sjdp 176038889Sjdp if (res->res_info.memflags != 0) 176138889Sjdp { 176238889Sjdp if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0) 176338889Sjdp fprintf (e, " MOVEABLE"); 176438889Sjdp if ((res->res_info.memflags & MEMFLAG_PURE) != 0) 176538889Sjdp fprintf (e, " PURE"); 176638889Sjdp if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0) 176738889Sjdp fprintf (e, " PRELOAD"); 176838889Sjdp if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0) 176938889Sjdp fprintf (e, " DISCARDABLE"); 177038889Sjdp } 177138889Sjdp 177238889Sjdp if (res->type == RES_TYPE_DIALOG) 177338889Sjdp { 177438889Sjdp fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y, 177538889Sjdp res->u.dialog->width, res->u.dialog->height); 177638889Sjdp if (res->u.dialog->ex != NULL 177738889Sjdp && res->u.dialog->ex->help != 0) 177838889Sjdp fprintf (e, ", %lu", res->u.dialog->ex->help); 177938889Sjdp } 178038889Sjdp 178138889Sjdp fprintf (e, "\n"); 178238889Sjdp 178338889Sjdp if ((res->res_info.language != 0 && res->res_info.language != *language) 178438889Sjdp || res->res_info.characteristics != 0 178538889Sjdp || res->res_info.version != 0) 178638889Sjdp { 178738889Sjdp int modifiers; 178838889Sjdp 178938889Sjdp switch (res->type) 179038889Sjdp { 179138889Sjdp case RES_TYPE_ACCELERATOR: 179238889Sjdp case RES_TYPE_DIALOG: 179338889Sjdp case RES_TYPE_MENU: 179438889Sjdp case RES_TYPE_RCDATA: 179538889Sjdp case RES_TYPE_STRINGTABLE: 179638889Sjdp modifiers = 1; 179738889Sjdp break; 179838889Sjdp 179938889Sjdp default: 180038889Sjdp modifiers = 0; 180138889Sjdp break; 180238889Sjdp } 180338889Sjdp 180438889Sjdp if (res->res_info.language != 0 && res->res_info.language != *language) 180538889Sjdp fprintf (e, "%sLANGUAGE %d, %d\n", 180638889Sjdp modifiers ? "// " : "", 180789857Sobrien res->res_info.language & ((1<<SUBLANG_SHIFT)-1), 180889857Sobrien (res->res_info.language >> SUBLANG_SHIFT) & 0xff); 180938889Sjdp if (res->res_info.characteristics != 0) 181038889Sjdp fprintf (e, "%sCHARACTERISTICS %lu\n", 181138889Sjdp modifiers ? "// " : "", 181238889Sjdp res->res_info.characteristics); 181338889Sjdp if (res->res_info.version != 0) 181438889Sjdp fprintf (e, "%sVERSION %lu\n", 181538889Sjdp modifiers ? "// " : "", 181638889Sjdp res->res_info.version); 181738889Sjdp } 181838889Sjdp 181938889Sjdp switch (res->type) 182038889Sjdp { 182138889Sjdp default: 182238889Sjdp abort (); 182338889Sjdp 182438889Sjdp case RES_TYPE_ACCELERATOR: 182538889Sjdp write_rc_accelerators (e, res->u.acc); 182638889Sjdp break; 182738889Sjdp 182838889Sjdp case RES_TYPE_CURSOR: 182938889Sjdp write_rc_cursor (e, res->u.cursor); 183038889Sjdp break; 183138889Sjdp 183238889Sjdp case RES_TYPE_GROUP_CURSOR: 183338889Sjdp write_rc_group_cursor (e, res->u.group_cursor); 183438889Sjdp break; 183538889Sjdp 183638889Sjdp case RES_TYPE_DIALOG: 183738889Sjdp write_rc_dialog (e, res->u.dialog); 183838889Sjdp break; 183938889Sjdp 184038889Sjdp case RES_TYPE_FONTDIR: 184138889Sjdp write_rc_fontdir (e, res->u.fontdir); 184238889Sjdp break; 184338889Sjdp 184438889Sjdp case RES_TYPE_GROUP_ICON: 184538889Sjdp write_rc_group_icon (e, res->u.group_icon); 184638889Sjdp break; 184738889Sjdp 184838889Sjdp case RES_TYPE_MENU: 184938889Sjdp write_rc_menu (e, res->u.menu, menuex); 185038889Sjdp break; 185138889Sjdp 185238889Sjdp case RES_TYPE_RCDATA: 185338889Sjdp write_rc_rcdata (e, res->u.rcdata, 0); 185438889Sjdp break; 185538889Sjdp 185638889Sjdp case RES_TYPE_STRINGTABLE: 185738889Sjdp write_rc_stringtable (e, name, res->u.stringtable); 185838889Sjdp break; 185938889Sjdp 186038889Sjdp case RES_TYPE_USERDATA: 186138889Sjdp write_rc_rcdata (e, res->u.userdata, 0); 186238889Sjdp break; 186338889Sjdp 186438889Sjdp case RES_TYPE_VERSIONINFO: 186538889Sjdp write_rc_versioninfo (e, res->u.versioninfo); 186638889Sjdp break; 186738889Sjdp 186838889Sjdp case RES_TYPE_BITMAP: 186938889Sjdp case RES_TYPE_FONT: 187038889Sjdp case RES_TYPE_ICON: 187138889Sjdp case RES_TYPE_MESSAGETABLE: 187238889Sjdp write_rc_filedata (e, res->u.data.length, res->u.data.data); 187338889Sjdp break; 187438889Sjdp } 187538889Sjdp} 187638889Sjdp 187738889Sjdp/* Write out accelerator information. */ 187838889Sjdp 187938889Sjdpstatic void 1880130561Sobrienwrite_rc_accelerators (FILE *e, const struct accelerator *accelerators) 188138889Sjdp{ 188238889Sjdp const struct accelerator *acc; 188338889Sjdp 188438889Sjdp fprintf (e, "BEGIN\n"); 188538889Sjdp for (acc = accelerators; acc != NULL; acc = acc->next) 188638889Sjdp { 188738889Sjdp int printable; 188838889Sjdp 188938889Sjdp fprintf (e, " "); 189038889Sjdp 189138889Sjdp if ((acc->key & 0x7f) == acc->key 189289857Sobrien && ISPRINT (acc->key) 189338889Sjdp && (acc->flags & ACC_VIRTKEY) == 0) 189438889Sjdp { 189538889Sjdp fprintf (e, "\"%c\"", acc->key); 189638889Sjdp printable = 1; 189738889Sjdp } 189838889Sjdp else 189938889Sjdp { 190038889Sjdp fprintf (e, "%d", acc->key); 190138889Sjdp printable = 0; 190238889Sjdp } 190338889Sjdp 190438889Sjdp fprintf (e, ", %d", acc->id); 190538889Sjdp 190638889Sjdp if (! printable) 190738889Sjdp { 190838889Sjdp if ((acc->flags & ACC_VIRTKEY) != 0) 190938889Sjdp fprintf (e, ", VIRTKEY"); 191038889Sjdp else 191138889Sjdp fprintf (e, ", ASCII"); 191238889Sjdp } 191338889Sjdp 191438889Sjdp if ((acc->flags & ACC_SHIFT) != 0) 191538889Sjdp fprintf (e, ", SHIFT"); 191638889Sjdp if ((acc->flags & ACC_CONTROL) != 0) 191738889Sjdp fprintf (e, ", CONTROL"); 191838889Sjdp if ((acc->flags & ACC_ALT) != 0) 191938889Sjdp fprintf (e, ", ALT"); 192038889Sjdp 192138889Sjdp fprintf (e, "\n"); 192238889Sjdp } 192338889Sjdp 192438889Sjdp fprintf (e, "END\n"); 192538889Sjdp} 192638889Sjdp 192738889Sjdp/* Write out cursor information. This would normally be in a separate 192838889Sjdp file, which the rc file would include. */ 192938889Sjdp 193038889Sjdpstatic void 1931130561Sobrienwrite_rc_cursor (FILE *e, const struct cursor *cursor) 193238889Sjdp{ 193338889Sjdp fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot, 193438889Sjdp cursor->yhotspot); 193538889Sjdp write_rc_filedata (e, cursor->length, cursor->data); 193638889Sjdp} 193738889Sjdp 193838889Sjdp/* Write out group cursor data. This would normally be built from the 193938889Sjdp cursor data. */ 194038889Sjdp 194138889Sjdpstatic void 1942130561Sobrienwrite_rc_group_cursor (FILE *e, const struct group_cursor *group_cursor) 194338889Sjdp{ 194438889Sjdp const struct group_cursor *gc; 194538889Sjdp 194638889Sjdp for (gc = group_cursor; gc != NULL; gc = gc->next) 194738889Sjdp { 194838889Sjdp fprintf (e, "// width: %d; height %d; planes %d; bits %d\n", 194938889Sjdp gc->width, gc->height, gc->planes, gc->bits); 195038889Sjdp fprintf (e, "// data bytes: %lu; index: %d\n", 195138889Sjdp gc->bytes, gc->index); 195238889Sjdp } 195338889Sjdp} 195438889Sjdp 195538889Sjdp/* Write dialog data. */ 195638889Sjdp 195738889Sjdpstatic void 1958130561Sobrienwrite_rc_dialog (FILE *e, const struct dialog *dialog) 195938889Sjdp{ 196038889Sjdp const struct dialog_control *control; 196138889Sjdp 196299461Sobrien fprintf (e, "STYLE 0x%lx\n", dialog->style); 196399461Sobrien 196438889Sjdp if (dialog->exstyle != 0) 196538889Sjdp fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle); 196699461Sobrien 196738889Sjdp if ((dialog->class.named && dialog->class.u.n.length > 0) 196838889Sjdp || dialog->class.u.id != 0) 196938889Sjdp { 197038889Sjdp fprintf (e, "CLASS "); 197199461Sobrien res_id_print (e, dialog->class, 1); 197238889Sjdp fprintf (e, "\n"); 197338889Sjdp } 197499461Sobrien 197538889Sjdp if (dialog->caption != NULL) 197638889Sjdp { 197738889Sjdp fprintf (e, "CAPTION \""); 197838889Sjdp unicode_print (e, dialog->caption, -1); 197938889Sjdp fprintf (e, "\"\n"); 198038889Sjdp } 198199461Sobrien 198238889Sjdp if ((dialog->menu.named && dialog->menu.u.n.length > 0) 198338889Sjdp || dialog->menu.u.id != 0) 198438889Sjdp { 198538889Sjdp fprintf (e, "MENU "); 198638889Sjdp res_id_print (e, dialog->menu, 0); 198738889Sjdp fprintf (e, "\n"); 198838889Sjdp } 198999461Sobrien 199038889Sjdp if (dialog->font != NULL) 199138889Sjdp { 199238889Sjdp fprintf (e, "FONT %d, \"", dialog->pointsize); 199338889Sjdp unicode_print (e, dialog->font, -1); 199438889Sjdp fprintf (e, "\""); 199538889Sjdp if (dialog->ex != NULL 199699461Sobrien && (dialog->ex->weight != 0 199799461Sobrien || dialog->ex->italic != 0 199899461Sobrien || dialog->ex->charset != 1)) 199999461Sobrien fprintf (e, ", %d, %d, %d", 200099461Sobrien dialog->ex->weight, dialog->ex->italic, dialog->ex->charset); 200138889Sjdp fprintf (e, "\n"); 200238889Sjdp } 200338889Sjdp 200438889Sjdp fprintf (e, "BEGIN\n"); 200538889Sjdp 200638889Sjdp for (control = dialog->controls; control != NULL; control = control->next) 200738889Sjdp write_rc_dialog_control (e, control); 200838889Sjdp 200938889Sjdp fprintf (e, "END\n"); 201038889Sjdp} 201138889Sjdp 201238889Sjdp/* For each predefined control keyword, this table provides the class 201338889Sjdp and the style. */ 201438889Sjdp 201538889Sjdpstruct control_info 201638889Sjdp{ 201738889Sjdp const char *name; 201838889Sjdp unsigned short class; 201938889Sjdp unsigned long style; 202038889Sjdp}; 202138889Sjdp 202238889Sjdpstatic const struct control_info control_info[] = 202338889Sjdp{ 202438889Sjdp { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE }, 202538889Sjdp { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX }, 202638889Sjdp { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON }, 202738889Sjdp { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX }, 202838889Sjdp { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 }, 202938889Sjdp { "CTEXT", CTL_STATIC, SS_CENTER }, 203038889Sjdp { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON }, 203138889Sjdp { "EDITTEXT", CTL_EDIT, (unsigned long) -1 }, 203238889Sjdp { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX }, 203338889Sjdp { "ICON", CTL_STATIC, SS_ICON }, 203438889Sjdp { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 }, 203538889Sjdp { "LTEXT", CTL_STATIC, SS_LEFT }, 203638889Sjdp { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX }, 203738889Sjdp { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON }, 203838889Sjdp { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON }, 203938889Sjdp { "RTEXT", CTL_STATIC, SS_RIGHT }, 204038889Sjdp { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 }, 204138889Sjdp { "STATE3", CTL_BUTTON, BS_3STATE }, 204238889Sjdp /* It's important that USERBUTTON come after all the other button 204338889Sjdp types, so that it won't be matched too early. */ 204438889Sjdp { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 }, 204538889Sjdp { NULL, 0, 0 } 204638889Sjdp}; 204738889Sjdp 204838889Sjdp/* Write a dialog control. */ 204938889Sjdp 205038889Sjdpstatic void 2051130561Sobrienwrite_rc_dialog_control (FILE *e, const struct dialog_control *control) 205238889Sjdp{ 205338889Sjdp const struct control_info *ci; 205438889Sjdp 205538889Sjdp fprintf (e, " "); 205638889Sjdp 205738889Sjdp if (control->class.named) 205838889Sjdp ci = NULL; 205938889Sjdp else 206038889Sjdp { 206138889Sjdp for (ci = control_info; ci->name != NULL; ++ci) 206238889Sjdp if (ci->class == control->class.u.id 206338889Sjdp && (ci->style == (unsigned long) -1 206438889Sjdp || ci->style == (control->style & 0xff))) 206538889Sjdp break; 206638889Sjdp } 206760484Sobrien if (ci == NULL) 206860484Sobrien fprintf (e, "CONTROL"); 206960484Sobrien else if (ci->name != NULL) 207038889Sjdp fprintf (e, "%s", ci->name); 207138889Sjdp else 207238889Sjdp fprintf (e, "CONTROL"); 2073104834Sobrien 207438889Sjdp if (control->text.named || control->text.u.id != 0) 207538889Sjdp { 207638889Sjdp fprintf (e, " "); 207738889Sjdp res_id_print (e, control->text, 1); 207838889Sjdp fprintf (e, ","); 207938889Sjdp } 208038889Sjdp 208138889Sjdp fprintf (e, " %d, ", control->id); 208238889Sjdp 208360484Sobrien if (ci == NULL) 208438889Sjdp { 208560484Sobrien if (control->class.named) 208660484Sobrien fprintf (e, "\""); 208738889Sjdp res_id_print (e, control->class, 0); 208860484Sobrien if (control->class.named) 208960484Sobrien fprintf (e, "\""); 209038889Sjdp fprintf (e, ", 0x%lx, ", control->style); 209138889Sjdp } 209238889Sjdp 209338889Sjdp fprintf (e, "%d, %d", control->x, control->y); 209438889Sjdp 209538889Sjdp if (control->style != SS_ICON 209638889Sjdp || control->exstyle != 0 209738889Sjdp || control->width != 0 209838889Sjdp || control->height != 0 209938889Sjdp || control->help != 0) 210038889Sjdp { 210138889Sjdp fprintf (e, ", %d, %d", control->width, control->height); 210238889Sjdp 210338889Sjdp /* FIXME: We don't need to print the style if it is the default. 210438889Sjdp More importantly, in certain cases we actually need to turn 210538889Sjdp off parts of the forced style, by using NOT. */ 210638889Sjdp fprintf (e, ", 0x%lx", control->style); 210738889Sjdp 210838889Sjdp if (control->exstyle != 0 || control->help != 0) 210938889Sjdp fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help); 211038889Sjdp } 211138889Sjdp 211238889Sjdp fprintf (e, "\n"); 211338889Sjdp 211438889Sjdp if (control->data != NULL) 211538889Sjdp write_rc_rcdata (e, control->data, 2); 211638889Sjdp} 211738889Sjdp 211838889Sjdp/* Write out font directory data. This would normally be built from 211938889Sjdp the font data. */ 212038889Sjdp 212138889Sjdpstatic void 2122130561Sobrienwrite_rc_fontdir (FILE *e, const struct fontdir *fontdir) 212338889Sjdp{ 212438889Sjdp const struct fontdir *fc; 212538889Sjdp 212638889Sjdp for (fc = fontdir; fc != NULL; fc = fc->next) 212738889Sjdp { 212838889Sjdp fprintf (e, "// Font index: %d\n", fc->index); 212938889Sjdp write_rc_filedata (e, fc->length, fc->data); 213038889Sjdp } 213138889Sjdp} 213238889Sjdp 213338889Sjdp/* Write out group icon data. This would normally be built from the 213438889Sjdp icon data. */ 213538889Sjdp 213638889Sjdpstatic void 2137130561Sobrienwrite_rc_group_icon (FILE *e, const struct group_icon *group_icon) 213838889Sjdp{ 213938889Sjdp const struct group_icon *gi; 214038889Sjdp 214138889Sjdp for (gi = group_icon; gi != NULL; gi = gi->next) 214238889Sjdp { 214338889Sjdp fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n", 214438889Sjdp gi->width, gi->height, gi->colors, gi->planes, gi->bits); 214538889Sjdp fprintf (e, "// data bytes: %lu; index: %d\n", 214638889Sjdp gi->bytes, gi->index); 214738889Sjdp } 214838889Sjdp} 214938889Sjdp 215038889Sjdp/* Write out a menu resource. */ 215138889Sjdp 215238889Sjdpstatic void 2153130561Sobrienwrite_rc_menu (FILE *e, const struct menu *menu, int menuex) 215438889Sjdp{ 215538889Sjdp if (menu->help != 0) 215638889Sjdp fprintf (e, "// Help ID: %lu\n", menu->help); 215738889Sjdp write_rc_menuitems (e, menu->items, menuex, 0); 215838889Sjdp} 215938889Sjdp 216038889Sjdp/* Write out menuitems. */ 216138889Sjdp 216238889Sjdpstatic void 2163130561Sobrienwrite_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex, 2164130561Sobrien int ind) 216538889Sjdp{ 216638889Sjdp const struct menuitem *mi; 216738889Sjdp 216838889Sjdp indent (e, ind); 216938889Sjdp fprintf (e, "BEGIN\n"); 217038889Sjdp 217138889Sjdp for (mi = menuitems; mi != NULL; mi = mi->next) 217238889Sjdp { 217338889Sjdp indent (e, ind + 2); 217438889Sjdp 217538889Sjdp if (mi->popup == NULL) 217638889Sjdp fprintf (e, "MENUITEM"); 217738889Sjdp else 217838889Sjdp fprintf (e, "POPUP"); 217938889Sjdp 218038889Sjdp if (! menuex 218138889Sjdp && mi->popup == NULL 218238889Sjdp && mi->text == NULL 218338889Sjdp && mi->type == 0 218438889Sjdp && mi->id == 0) 218538889Sjdp { 218638889Sjdp fprintf (e, " SEPARATOR\n"); 218738889Sjdp continue; 218838889Sjdp } 218938889Sjdp 219038889Sjdp if (mi->text == NULL) 219138889Sjdp fprintf (e, " \"\""); 219238889Sjdp else 219338889Sjdp { 219438889Sjdp fprintf (e, " \""); 219538889Sjdp unicode_print (e, mi->text, -1); 219638889Sjdp fprintf (e, "\""); 219738889Sjdp } 219838889Sjdp 219938889Sjdp if (! menuex) 220038889Sjdp { 220138889Sjdp if (mi->popup == NULL) 220238889Sjdp fprintf (e, ", %d", mi->id); 220338889Sjdp 220438889Sjdp if ((mi->type & MENUITEM_CHECKED) != 0) 220538889Sjdp fprintf (e, ", CHECKED"); 220638889Sjdp if ((mi->type & MENUITEM_GRAYED) != 0) 220738889Sjdp fprintf (e, ", GRAYED"); 220838889Sjdp if ((mi->type & MENUITEM_HELP) != 0) 220938889Sjdp fprintf (e, ", HELP"); 221038889Sjdp if ((mi->type & MENUITEM_INACTIVE) != 0) 221138889Sjdp fprintf (e, ", INACTIVE"); 221238889Sjdp if ((mi->type & MENUITEM_MENUBARBREAK) != 0) 221338889Sjdp fprintf (e, ", MENUBARBREAK"); 221438889Sjdp if ((mi->type & MENUITEM_MENUBREAK) != 0) 221538889Sjdp fprintf (e, ", MENUBREAK"); 221638889Sjdp } 221738889Sjdp else 221838889Sjdp { 221938889Sjdp if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0) 222038889Sjdp { 222138889Sjdp fprintf (e, ", %d", mi->id); 222238889Sjdp if (mi->type != 0 || mi->state != 0 || mi->help != 0) 222338889Sjdp { 222438889Sjdp fprintf (e, ", %lu", mi->type); 222538889Sjdp if (mi->state != 0 || mi->help != 0) 222638889Sjdp { 222738889Sjdp fprintf (e, ", %lu", mi->state); 222838889Sjdp if (mi->help != 0) 222938889Sjdp fprintf (e, ", %lu", mi->help); 223038889Sjdp } 223138889Sjdp } 223238889Sjdp } 223338889Sjdp } 223438889Sjdp 223538889Sjdp fprintf (e, "\n"); 223638889Sjdp 223738889Sjdp if (mi->popup != NULL) 223838889Sjdp write_rc_menuitems (e, mi->popup, menuex, ind + 2); 223938889Sjdp } 224038889Sjdp 224138889Sjdp indent (e, ind); 224238889Sjdp fprintf (e, "END\n"); 224338889Sjdp} 224438889Sjdp 224538889Sjdp/* Write out an rcdata resource. This is also used for other types of 224638889Sjdp resources that need to print arbitrary data. */ 224738889Sjdp 224838889Sjdpstatic void 2249130561Sobrienwrite_rc_rcdata (FILE *e, const struct rcdata_item *rcdata, int ind) 225038889Sjdp{ 225138889Sjdp const struct rcdata_item *ri; 225238889Sjdp 225338889Sjdp indent (e, ind); 225438889Sjdp fprintf (e, "BEGIN\n"); 225538889Sjdp 225638889Sjdp for (ri = rcdata; ri != NULL; ri = ri->next) 225738889Sjdp { 225838889Sjdp if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0) 225938889Sjdp continue; 226038889Sjdp 226138889Sjdp indent (e, ind + 2); 226238889Sjdp 226338889Sjdp switch (ri->type) 226438889Sjdp { 226538889Sjdp default: 226638889Sjdp abort (); 226738889Sjdp 226838889Sjdp case RCDATA_WORD: 226938889Sjdp fprintf (e, "%d", ri->u.word); 227038889Sjdp break; 227138889Sjdp 227238889Sjdp case RCDATA_DWORD: 227338889Sjdp fprintf (e, "%luL", ri->u.dword); 227438889Sjdp break; 227538889Sjdp 227638889Sjdp case RCDATA_STRING: 227738889Sjdp { 227838889Sjdp const char *s; 227938889Sjdp unsigned long i; 228038889Sjdp 228138889Sjdp fprintf (e, "\""); 228238889Sjdp s = ri->u.string.s; 228338889Sjdp for (i = 0; i < ri->u.string.length; i++) 228438889Sjdp { 228589857Sobrien if (ISPRINT (*s)) 228638889Sjdp putc (*s, e); 228738889Sjdp else 228838889Sjdp fprintf (e, "\\%03o", *s); 228938889Sjdp } 229038889Sjdp fprintf (e, "\""); 229138889Sjdp break; 229238889Sjdp } 229338889Sjdp 229438889Sjdp case RCDATA_WSTRING: 229538889Sjdp fprintf (e, "L\""); 229638889Sjdp unicode_print (e, ri->u.wstring.w, ri->u.wstring.length); 229738889Sjdp fprintf (e, "\""); 229838889Sjdp break; 229938889Sjdp 230038889Sjdp case RCDATA_BUFFER: 230138889Sjdp { 230238889Sjdp unsigned long i; 230338889Sjdp int first; 230438889Sjdp 230538889Sjdp /* Assume little endian data. */ 230638889Sjdp 230738889Sjdp first = 1; 230838889Sjdp for (i = 0; i + 3 < ri->u.buffer.length; i += 4) 230938889Sjdp { 231038889Sjdp unsigned long l; 231160484Sobrien int j; 231238889Sjdp 231360484Sobrien if (! first) 231460484Sobrien indent (e, ind + 2); 231538889Sjdp l = ((((((ri->u.buffer.data[i + 3] << 8) 231638889Sjdp | ri->u.buffer.data[i + 2]) << 8) 231738889Sjdp | ri->u.buffer.data[i + 1]) << 8) 231838889Sjdp | ri->u.buffer.data[i]); 231960484Sobrien fprintf (e, "%luL", l); 232060484Sobrien if (i + 4 < ri->u.buffer.length || ri->next != NULL) 232160484Sobrien fprintf (e, ","); 232260484Sobrien for (j = 0; j < 4; ++j) 232389857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j]) 232460484Sobrien && ri->u.buffer.data[i + j] != 0) 232560484Sobrien break; 232660484Sobrien if (j >= 4) 232738889Sjdp { 232860484Sobrien fprintf (e, "\t// "); 232960484Sobrien for (j = 0; j < 4; ++j) 233060484Sobrien { 233189857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j])) 233260484Sobrien fprintf (e, "\\%03o", ri->u.buffer.data[i + j]); 233360484Sobrien else 233460484Sobrien { 233560484Sobrien if (ri->u.buffer.data[i + j] == '\\') 233660484Sobrien fprintf (e, "\\"); 233760484Sobrien fprintf (e, "%c", ri->u.buffer.data[i + j]); 233860484Sobrien } 233960484Sobrien } 234038889Sjdp } 234160484Sobrien fprintf (e, "\n"); 234260484Sobrien first = 0; 234338889Sjdp } 234438889Sjdp 234538889Sjdp if (i + 1 < ri->u.buffer.length) 234638889Sjdp { 234760484Sobrien int s; 234860484Sobrien int j; 234938889Sjdp 235060484Sobrien if (! first) 235160484Sobrien indent (e, ind + 2); 235260484Sobrien s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i]; 235360484Sobrien fprintf (e, "%d", s); 235460484Sobrien if (i + 2 < ri->u.buffer.length || ri->next != NULL) 235560484Sobrien fprintf (e, ","); 235660484Sobrien for (j = 0; j < 2; ++j) 235789857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j]) 235860484Sobrien && ri->u.buffer.data[i + j] != 0) 235960484Sobrien break; 236060484Sobrien if (j >= 2) 236138889Sjdp { 236260484Sobrien fprintf (e, "\t// "); 236360484Sobrien for (j = 0; j < 2; ++j) 236460484Sobrien { 236589857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j])) 236660484Sobrien fprintf (e, "\\%03o", ri->u.buffer.data[i + j]); 236760484Sobrien else 236860484Sobrien { 236960484Sobrien if (ri->u.buffer.data[i + j] == '\\') 237060484Sobrien fprintf (e, "\\"); 237160484Sobrien fprintf (e, "%c", ri->u.buffer.data[i + j]); 237260484Sobrien } 237360484Sobrien } 237438889Sjdp } 237560484Sobrien fprintf (e, "\n"); 237638889Sjdp i += 2; 237760484Sobrien first = 0; 237838889Sjdp } 237938889Sjdp 238038889Sjdp if (i < ri->u.buffer.length) 238138889Sjdp { 238260484Sobrien if (! first) 238360484Sobrien indent (e, ind + 2); 238438889Sjdp if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i] 238589857Sobrien && ISPRINT (ri->u.buffer.data[i])) 238638889Sjdp fprintf (e, "\"%c\"", ri->u.buffer.data[i]); 238738889Sjdp else 238860484Sobrien fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]); 238960484Sobrien if (ri->next != NULL) 239060484Sobrien fprintf (e, ","); 239160484Sobrien fprintf (e, "\n"); 239260484Sobrien first = 0; 239338889Sjdp } 239438889Sjdp 239538889Sjdp break; 239638889Sjdp } 239738889Sjdp } 239838889Sjdp 239960484Sobrien if (ri->type != RCDATA_BUFFER) 240060484Sobrien { 240160484Sobrien if (ri->next != NULL) 240260484Sobrien fprintf (e, ","); 240360484Sobrien fprintf (e, "\n"); 240460484Sobrien } 240538889Sjdp } 240638889Sjdp 240738889Sjdp indent (e, ind); 240838889Sjdp fprintf (e, "END\n"); 240938889Sjdp} 241038889Sjdp 241138889Sjdp/* Write out a stringtable resource. */ 241238889Sjdp 241338889Sjdpstatic void 2414130561Sobrienwrite_rc_stringtable (FILE *e, const struct res_id *name, 2415130561Sobrien const struct stringtable *stringtable) 241638889Sjdp{ 241738889Sjdp unsigned long offset; 241838889Sjdp int i; 241938889Sjdp 242038889Sjdp if (name != NULL && ! name->named) 242138889Sjdp offset = (name->u.id - 1) << 4; 242238889Sjdp else 242338889Sjdp { 242438889Sjdp fprintf (e, "// %s string table name\n", 242538889Sjdp name == NULL ? "Missing" : "Invalid"); 242638889Sjdp offset = 0; 242738889Sjdp } 242838889Sjdp 242938889Sjdp fprintf (e, "BEGIN\n"); 243038889Sjdp 243138889Sjdp for (i = 0; i < 16; i++) 243238889Sjdp { 243338889Sjdp if (stringtable->strings[i].length != 0) 243438889Sjdp { 243538889Sjdp fprintf (e, " %lu, \"", offset + i); 243638889Sjdp unicode_print (e, stringtable->strings[i].string, 243738889Sjdp stringtable->strings[i].length); 243838889Sjdp fprintf (e, "\"\n"); 243938889Sjdp } 244038889Sjdp } 244138889Sjdp 244238889Sjdp fprintf (e, "END\n"); 244338889Sjdp} 244438889Sjdp 244538889Sjdp/* Write out a versioninfo resource. */ 244638889Sjdp 244738889Sjdpstatic void 2448130561Sobrienwrite_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo) 244938889Sjdp{ 245038889Sjdp const struct fixed_versioninfo *f; 245138889Sjdp const struct ver_info *vi; 245238889Sjdp 245338889Sjdp f = versioninfo->fixed; 245438889Sjdp if (f->file_version_ms != 0 || f->file_version_ls != 0) 245538889Sjdp fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n", 245638889Sjdp (f->file_version_ms >> 16) & 0xffff, 245738889Sjdp f->file_version_ms & 0xffff, 245838889Sjdp (f->file_version_ls >> 16) & 0xffff, 245938889Sjdp f->file_version_ls & 0xffff); 246038889Sjdp if (f->product_version_ms != 0 || f->product_version_ls != 0) 246138889Sjdp fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n", 246238889Sjdp (f->product_version_ms >> 16) & 0xffff, 246338889Sjdp f->product_version_ms & 0xffff, 246438889Sjdp (f->product_version_ls >> 16) & 0xffff, 246538889Sjdp f->product_version_ls & 0xffff); 246638889Sjdp if (f->file_flags_mask != 0) 246738889Sjdp fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask); 246838889Sjdp if (f->file_flags != 0) 246938889Sjdp fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags); 247038889Sjdp if (f->file_os != 0) 247138889Sjdp fprintf (e, " FILEOS 0x%lx\n", f->file_os); 247238889Sjdp if (f->file_type != 0) 247338889Sjdp fprintf (e, " FILETYPE 0x%lx\n", f->file_type); 247438889Sjdp if (f->file_subtype != 0) 247538889Sjdp fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype); 247638889Sjdp if (f->file_date_ms != 0 || f->file_date_ls != 0) 247738889Sjdp fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls); 247838889Sjdp 247938889Sjdp fprintf (e, "BEGIN\n"); 248038889Sjdp 248138889Sjdp for (vi = versioninfo->var; vi != NULL; vi = vi->next) 248238889Sjdp { 248338889Sjdp switch (vi->type) 248438889Sjdp { 248538889Sjdp case VERINFO_STRING: 248638889Sjdp { 248738889Sjdp const struct ver_stringinfo *vs; 248838889Sjdp 248938889Sjdp fprintf (e, " BLOCK \"StringFileInfo\"\n"); 249038889Sjdp fprintf (e, " BEGIN\n"); 249138889Sjdp fprintf (e, " BLOCK \""); 249238889Sjdp unicode_print (e, vi->u.string.language, -1); 249338889Sjdp fprintf (e, "\"\n"); 249438889Sjdp fprintf (e, " BEGIN\n"); 249538889Sjdp 249638889Sjdp for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) 249738889Sjdp { 249838889Sjdp fprintf (e, " VALUE \""); 249938889Sjdp unicode_print (e, vs->key, -1); 250038889Sjdp fprintf (e, "\", \""); 250138889Sjdp unicode_print (e, vs->value, -1); 250238889Sjdp fprintf (e, "\"\n"); 250338889Sjdp } 250438889Sjdp 250538889Sjdp fprintf (e, " END\n"); 250638889Sjdp fprintf (e, " END\n"); 250738889Sjdp break; 250838889Sjdp } 250938889Sjdp 251038889Sjdp case VERINFO_VAR: 251138889Sjdp { 251238889Sjdp const struct ver_varinfo *vv; 251338889Sjdp 251438889Sjdp fprintf (e, " BLOCK \"VarFileInfo\"\n"); 251538889Sjdp fprintf (e, " BEGIN\n"); 251638889Sjdp fprintf (e, " VALUE \""); 251738889Sjdp unicode_print (e, vi->u.var.key, -1); 251838889Sjdp fprintf (e, "\""); 251938889Sjdp 252038889Sjdp for (vv = vi->u.var.var; vv != NULL; vv = vv->next) 252138889Sjdp fprintf (e, ", 0x%x, %d", (unsigned int) vv->language, 252238889Sjdp vv->charset); 252338889Sjdp 252438889Sjdp fprintf (e, "\n END\n"); 252538889Sjdp 252638889Sjdp break; 252738889Sjdp } 252838889Sjdp } 252938889Sjdp } 253038889Sjdp 253138889Sjdp fprintf (e, "END\n"); 253238889Sjdp} 253338889Sjdp 253438889Sjdp/* Write out data which would normally be read from a file. */ 253538889Sjdp 253638889Sjdpstatic void 2537130561Sobrienwrite_rc_filedata (FILE *e, unsigned long length, const unsigned char *data) 253838889Sjdp{ 253938889Sjdp unsigned long i; 254038889Sjdp 254138889Sjdp for (i = 0; i + 15 < length; i += 16) 254238889Sjdp { 254338889Sjdp fprintf (e, "// %4lx: ", i); 254438889Sjdp fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ", 254538889Sjdp data[i + 0], data[i + 1], data[i + 2], data[i + 3], 254638889Sjdp data[i + 4], data[i + 5], data[i + 6], data[i + 7]); 254738889Sjdp fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n", 254838889Sjdp data[i + 8], data[i + 9], data[i + 10], data[i + 11], 254938889Sjdp data[i + 12], data[i + 13], data[i + 14], data[i + 15]); 255038889Sjdp } 255138889Sjdp 255238889Sjdp if (i < length) 255338889Sjdp { 255438889Sjdp fprintf (e, "// %4lx:", i); 255538889Sjdp while (i < length) 255638889Sjdp { 255738889Sjdp fprintf (e, " %02x", data[i]); 255838889Sjdp ++i; 255938889Sjdp } 256038889Sjdp fprintf (e, "\n"); 256138889Sjdp } 256238889Sjdp} 2563