resrc.c revision 104834
138889Sjdp/* resrc.c -- read and write Windows rc files. 299461Sobrien Copyright 1997, 1998, 1999, 2000, 2001, 2002 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 16460484Sobrienstatic int run_cmd PARAMS ((char *, const char *)); 16560484Sobrienstatic FILE *open_input_stream PARAMS ((char *)); 16660484Sobrienstatic FILE *look_for_default PARAMS ((char *, const char *, int, 16760484Sobrien const char *, const char *)); 16860484Sobrienstatic void close_input_stream PARAMS ((void)); 16938889Sjdpstatic void unexpected_eof PARAMS ((const char *)); 17038889Sjdpstatic int get_word PARAMS ((FILE *, const char *)); 17138889Sjdpstatic unsigned long get_long PARAMS ((FILE *, const char *)); 17238889Sjdpstatic void get_data 17338889Sjdp PARAMS ((FILE *, unsigned char *, unsigned long, const char *)); 17438889Sjdpstatic void define_fontdirs PARAMS ((void)); 17538889Sjdp 17699461Sobrien/* Run `cmd' and redirect the output to `redir'. */ 17760484Sobrien 17860484Sobrienstatic int 17960484Sobrienrun_cmd (cmd, redir) 18060484Sobrien char *cmd; 18160484Sobrien const char *redir; 18260484Sobrien{ 18360484Sobrien char *s; 18460484Sobrien int pid, wait_status, retcode; 18560484Sobrien int i; 18660484Sobrien const char **argv; 18760484Sobrien char *errmsg_fmt, *errmsg_arg; 18860484Sobrien char *temp_base = choose_temp_base (); 18960484Sobrien int in_quote; 19060484Sobrien char sep; 19160484Sobrien int redir_handle = -1; 19260484Sobrien int stdout_save = -1; 19360484Sobrien 19460484Sobrien /* Count the args. */ 19560484Sobrien i = 0; 196104834Sobrien 19760484Sobrien for (s = cmd; *s; s++) 19860484Sobrien if (*s == ' ') 19960484Sobrien i++; 200104834Sobrien 20160484Sobrien i++; 20260484Sobrien argv = alloca (sizeof (char *) * (i + 3)); 20360484Sobrien i = 0; 20460484Sobrien s = cmd; 205104834Sobrien 20660484Sobrien while (1) 20760484Sobrien { 20860484Sobrien while (*s == ' ' && *s != 0) 20960484Sobrien s++; 210104834Sobrien 21160484Sobrien if (*s == 0) 21260484Sobrien break; 213104834Sobrien 21460484Sobrien in_quote = (*s == '\'' || *s == '"'); 21560484Sobrien sep = (in_quote) ? *s++ : ' '; 21660484Sobrien argv[i++] = s; 217104834Sobrien 21860484Sobrien while (*s != sep && *s != 0) 21960484Sobrien s++; 220104834Sobrien 22160484Sobrien if (*s == 0) 22260484Sobrien break; 223104834Sobrien 22460484Sobrien *s++ = 0; 225104834Sobrien 22660484Sobrien if (in_quote) 227104834Sobrien s++; 22860484Sobrien } 22960484Sobrien argv[i++] = NULL; 23060484Sobrien 23160484Sobrien /* Setup the redirection. We can't use the usual fork/exec and redirect 23260484Sobrien since we may be running on non-POSIX Windows host. */ 23360484Sobrien 23460484Sobrien fflush (stdout); 23560484Sobrien fflush (stderr); 23660484Sobrien 23760484Sobrien /* Open temporary output file. */ 23860484Sobrien redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666); 23960484Sobrien if (redir_handle == -1) 240104834Sobrien fatal (_("can't open temporary file `%s': %s"), redir, 241104834Sobrien strerror (errno)); 24260484Sobrien 24360484Sobrien /* Duplicate the stdout file handle so it can be restored later. */ 24460484Sobrien stdout_save = dup (STDOUT_FILENO); 24560484Sobrien if (stdout_save == -1) 24660484Sobrien fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno)); 24760484Sobrien 24860484Sobrien /* Redirect stdout to our output file. */ 24960484Sobrien dup2 (redir_handle, STDOUT_FILENO); 25060484Sobrien 25160484Sobrien pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, 25260484Sobrien &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); 25360484Sobrien 25460484Sobrien /* Restore stdout to its previous setting. */ 25560484Sobrien dup2 (stdout_save, STDOUT_FILENO); 25660484Sobrien 25760484Sobrien /* Close reponse file. */ 25860484Sobrien close (redir_handle); 25960484Sobrien 26060484Sobrien if (pid == -1) 26160484Sobrien { 26260484Sobrien fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno)); 26360484Sobrien return 1; 26460484Sobrien } 26560484Sobrien 26660484Sobrien retcode = 0; 26760484Sobrien pid = pwait (pid, &wait_status, 0); 268104834Sobrien 26960484Sobrien if (pid == -1) 27060484Sobrien { 27160484Sobrien fatal (_("wait: %s"), strerror (errno)); 27260484Sobrien retcode = 1; 27360484Sobrien } 27460484Sobrien else if (WIFSIGNALED (wait_status)) 27560484Sobrien { 27660484Sobrien fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); 27760484Sobrien retcode = 1; 27860484Sobrien } 27960484Sobrien else if (WIFEXITED (wait_status)) 28060484Sobrien { 28160484Sobrien if (WEXITSTATUS (wait_status) != 0) 28260484Sobrien { 283104834Sobrien fatal (_("%s exited with status %d"), cmd, 28460484Sobrien WEXITSTATUS (wait_status)); 28560484Sobrien retcode = 1; 28660484Sobrien } 28760484Sobrien } 28860484Sobrien else 28960484Sobrien retcode = 1; 290104834Sobrien 29160484Sobrien return retcode; 29260484Sobrien} 29360484Sobrien 29460484Sobrienstatic FILE * 29560484Sobrienopen_input_stream (cmd) 29660484Sobrien char *cmd; 29760484Sobrien{ 29860484Sobrien if (istream_type == ISTREAM_FILE) 29960484Sobrien { 30060484Sobrien char *fileprefix; 30160484Sobrien 30260484Sobrien fileprefix = choose_temp_base (); 30360484Sobrien cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5); 30460484Sobrien sprintf (cpp_temp_file, "%s.irc", fileprefix); 30560484Sobrien free (fileprefix); 30660484Sobrien 30760484Sobrien if (run_cmd (cmd, cpp_temp_file)) 30860484Sobrien fatal (_("can't execute `%s': %s"), cmd, strerror (errno)); 30960484Sobrien 31060484Sobrien cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);; 31160484Sobrien if (cpp_pipe == NULL) 312104834Sobrien fatal (_("can't open temporary file `%s': %s"), 31360484Sobrien cpp_temp_file, strerror (errno)); 314104834Sobrien 31560484Sobrien if (verbose) 316104834Sobrien fprintf (stderr, 31760484Sobrien _("Using temporary file `%s' to read preprocessor output\n"), 31860484Sobrien cpp_temp_file); 31960484Sobrien } 32060484Sobrien else 32160484Sobrien { 32260484Sobrien cpp_pipe = popen (cmd, FOPEN_RT); 32360484Sobrien if (cpp_pipe == NULL) 324104834Sobrien fatal (_("can't popen `%s': %s"), cmd, strerror (errno)); 32560484Sobrien if (verbose) 32660484Sobrien fprintf (stderr, _("Using popen to read preprocessor output\n")); 32760484Sobrien } 32860484Sobrien 32960484Sobrien xatexit (close_input_stream); 33060484Sobrien return cpp_pipe; 33160484Sobrien} 33260484Sobrien 33360484Sobrien/* look for the preprocessor program */ 33460484Sobrien 33560484Sobrienstatic FILE * 33660484Sobrienlook_for_default (cmd, prefix, end_prefix, preprocargs, filename) 33760484Sobrien char *cmd; 33860484Sobrien const char *prefix; 33960484Sobrien int end_prefix; 34060484Sobrien const char *preprocargs; 34160484Sobrien const char *filename; 34260484Sobrien{ 34360484Sobrien char *space; 34460484Sobrien int found; 34560484Sobrien struct stat s; 34660484Sobrien 34760484Sobrien strcpy (cmd, prefix); 34860484Sobrien 34960484Sobrien sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR); 35060484Sobrien space = strchr (cmd + end_prefix, ' '); 35160484Sobrien if (space) 35260484Sobrien *space = 0; 35360484Sobrien 35460484Sobrien if ( 35560484Sobrien#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32) 35660484Sobrien strchr (cmd, '\\') || 35760484Sobrien#endif 35860484Sobrien strchr (cmd, '/')) 35960484Sobrien { 36060484Sobrien found = (stat (cmd, &s) == 0 36160484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 36260484Sobrien || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0 36360484Sobrien#endif 36460484Sobrien ); 36560484Sobrien 36660484Sobrien if (! found) 36760484Sobrien { 36860484Sobrien if (verbose) 36960484Sobrien fprintf (stderr, _("Tried `%s'\n"), cmd); 37060484Sobrien return NULL; 37160484Sobrien } 37260484Sobrien } 37360484Sobrien 37460484Sobrien strcpy (cmd, prefix); 37560484Sobrien 37660484Sobrien sprintf (cmd + end_prefix, "%s %s %s", 37760484Sobrien DEFAULT_PREPROCESSOR, preprocargs, filename); 37860484Sobrien 37960484Sobrien if (verbose) 38060484Sobrien fprintf (stderr, _("Using `%s'\n"), cmd); 38160484Sobrien 38260484Sobrien cpp_pipe = open_input_stream (cmd); 38360484Sobrien return cpp_pipe; 38460484Sobrien} 38560484Sobrien 38638889Sjdp/* Read an rc file. */ 38738889Sjdp 38838889Sjdpstruct res_directory * 38960484Sobrienread_rc_file (filename, preprocessor, preprocargs, language, use_temp_file) 39038889Sjdp const char *filename; 39138889Sjdp const char *preprocessor; 39238889Sjdp const char *preprocargs; 39338889Sjdp int language; 39460484Sobrien int use_temp_file; 39538889Sjdp{ 39638889Sjdp char *cmd; 39738889Sjdp 39860484Sobrien istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE; 39938889Sjdp 40038889Sjdp if (preprocargs == NULL) 40138889Sjdp preprocargs = ""; 40238889Sjdp if (filename == NULL) 40338889Sjdp filename = "-"; 40438889Sjdp 40560484Sobrien if (preprocessor) 40660484Sobrien { 40760484Sobrien cmd = xmalloc (strlen (preprocessor) 40860484Sobrien + strlen (preprocargs) 40960484Sobrien + strlen (filename) 41060484Sobrien + 10); 41160484Sobrien sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename); 41238889Sjdp 41360484Sobrien cpp_pipe = open_input_stream (cmd); 41460484Sobrien } 41560484Sobrien else 41660484Sobrien { 41760484Sobrien char *dash, *slash, *cp; 41860484Sobrien 41960484Sobrien preprocessor = DEFAULT_PREPROCESSOR; 42060484Sobrien 42160484Sobrien cmd = xmalloc (strlen (program_name) 42260484Sobrien + strlen (preprocessor) 42360484Sobrien + strlen (preprocargs) 42460484Sobrien + strlen (filename) 42560484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 42660484Sobrien + strlen (EXECUTABLE_SUFFIX) 42760484Sobrien#endif 42860484Sobrien + 10); 42960484Sobrien 43060484Sobrien 43160484Sobrien dash = slash = 0; 43260484Sobrien for (cp = program_name; *cp; cp++) 43360484Sobrien { 43460484Sobrien if (*cp == '-') 43560484Sobrien dash = cp; 43660484Sobrien if ( 43760484Sobrien#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32) 43860484Sobrien *cp == ':' || *cp == '\\' || 43960484Sobrien#endif 44060484Sobrien *cp == '/') 44160484Sobrien { 44260484Sobrien slash = cp; 44360484Sobrien dash = 0; 44460484Sobrien } 44560484Sobrien } 44660484Sobrien 44760484Sobrien cpp_pipe = 0; 44860484Sobrien 44960484Sobrien if (dash) 45060484Sobrien { 45160484Sobrien /* First, try looking for a prefixed gcc in the windres 45260484Sobrien directory, with the same prefix as windres */ 45360484Sobrien 45460484Sobrien cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1, 45560484Sobrien preprocargs, filename); 45660484Sobrien } 45760484Sobrien 45860484Sobrien if (slash && !cpp_pipe) 45960484Sobrien { 46060484Sobrien /* Next, try looking for a gcc in the same directory as 46160484Sobrien that windres */ 46260484Sobrien 46360484Sobrien cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1, 46460484Sobrien preprocargs, filename); 46560484Sobrien } 46660484Sobrien 46760484Sobrien if (!cpp_pipe) 46860484Sobrien { 46960484Sobrien /* Sigh, try the default */ 47060484Sobrien 47160484Sobrien cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename); 47260484Sobrien } 47360484Sobrien 47460484Sobrien } 475104834Sobrien 47638889Sjdp free (cmd); 47738889Sjdp 47838889Sjdp rc_filename = xstrdup (filename); 47938889Sjdp rc_lineno = 1; 48038889Sjdp if (language != -1) 48138889Sjdp rcparse_set_language (language); 48238889Sjdp yyin = cpp_pipe; 48338889Sjdp yyparse (); 48499461Sobrien rcparse_discard_strings (); 48538889Sjdp 48660484Sobrien close_input_stream (); 487104834Sobrien 48838889Sjdp if (fontdirs != NULL) 48938889Sjdp define_fontdirs (); 49038889Sjdp 49138889Sjdp free (rc_filename); 49238889Sjdp rc_filename = NULL; 49338889Sjdp 49438889Sjdp return resources; 49538889Sjdp} 49638889Sjdp 49760484Sobrien/* Close the input stream if it is open. */ 49838889Sjdp 49960484Sobrienstatic void 50060484Sobrienclose_input_stream () 50138889Sjdp{ 50260484Sobrien if (istream_type == ISTREAM_FILE) 50360484Sobrien { 50460484Sobrien if (cpp_pipe != NULL) 50560484Sobrien fclose (cpp_pipe); 50660484Sobrien 50760484Sobrien if (cpp_temp_file != NULL) 50860484Sobrien { 50960484Sobrien int errno_save = errno; 510104834Sobrien 51160484Sobrien unlink (cpp_temp_file); 51260484Sobrien errno = errno_save; 51360484Sobrien free (cpp_temp_file); 51460484Sobrien } 51560484Sobrien } 51660484Sobrien else 51760484Sobrien { 51860484Sobrien if (cpp_pipe != NULL) 51960484Sobrien pclose (cpp_pipe); 52060484Sobrien } 52160484Sobrien 52299461Sobrien /* Since this is also run via xatexit, safeguard. */ 52360484Sobrien cpp_pipe = NULL; 52460484Sobrien cpp_temp_file = NULL; 52538889Sjdp} 52638889Sjdp 52738889Sjdp/* Report an error while reading an rc file. */ 52838889Sjdp 52938889Sjdpvoid 53038889Sjdpyyerror (msg) 53138889Sjdp const char *msg; 53238889Sjdp{ 53338889Sjdp fatal ("%s:%d: %s", rc_filename, rc_lineno, msg); 53438889Sjdp} 53538889Sjdp 53638889Sjdp/* Issue a warning while reading an rc file. */ 53738889Sjdp 53838889Sjdpvoid 53938889Sjdprcparse_warning (msg) 54038889Sjdp const char *msg; 54138889Sjdp{ 54260484Sobrien fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg); 54338889Sjdp} 54438889Sjdp 54538889Sjdp/* Die if we get an unexpected end of file. */ 54638889Sjdp 54738889Sjdpstatic void 54838889Sjdpunexpected_eof (msg) 54938889Sjdp const char *msg; 55038889Sjdp{ 55160484Sobrien fatal (_("%s: unexpected EOF"), msg); 55238889Sjdp} 55338889Sjdp 55438889Sjdp/* Read a 16 bit word from a file. The data is assumed to be little 55538889Sjdp endian. */ 55638889Sjdp 55738889Sjdpstatic int 55838889Sjdpget_word (e, msg) 55938889Sjdp FILE *e; 56038889Sjdp const char *msg; 56138889Sjdp{ 56238889Sjdp int b1, b2; 56338889Sjdp 56438889Sjdp b1 = getc (e); 56538889Sjdp b2 = getc (e); 56638889Sjdp if (feof (e)) 56738889Sjdp unexpected_eof (msg); 56838889Sjdp return ((b2 & 0xff) << 8) | (b1 & 0xff); 56938889Sjdp} 57038889Sjdp 57138889Sjdp/* Read a 32 bit word from a file. The data is assumed to be little 57238889Sjdp endian. */ 57338889Sjdp 57438889Sjdpstatic unsigned long 57538889Sjdpget_long (e, msg) 57638889Sjdp FILE *e; 57738889Sjdp const char *msg; 57838889Sjdp{ 57938889Sjdp int b1, b2, b3, b4; 58038889Sjdp 58138889Sjdp b1 = getc (e); 58238889Sjdp b2 = getc (e); 58338889Sjdp b3 = getc (e); 58438889Sjdp b4 = getc (e); 58538889Sjdp if (feof (e)) 58638889Sjdp unexpected_eof (msg); 58738889Sjdp return (((((((b4 & 0xff) << 8) 58838889Sjdp | (b3 & 0xff)) << 8) 58938889Sjdp | (b2 & 0xff)) << 8) 59038889Sjdp | (b1 & 0xff)); 59138889Sjdp} 59238889Sjdp 59338889Sjdp/* Read data from a file. This is a wrapper to do error checking. */ 59438889Sjdp 59538889Sjdpstatic void 59638889Sjdpget_data (e, p, c, msg) 59738889Sjdp FILE *e; 59838889Sjdp unsigned char *p; 59938889Sjdp unsigned long c; 60038889Sjdp const char *msg; 60138889Sjdp{ 60238889Sjdp unsigned long got; 60338889Sjdp 60438889Sjdp got = fread (p, 1, c, e); 60538889Sjdp if (got == c) 60638889Sjdp return; 60738889Sjdp 60860484Sobrien fatal (_("%s: read of %lu returned %lu"), msg, c, got); 60938889Sjdp} 61038889Sjdp 61138889Sjdp/* Define an accelerator resource. */ 61238889Sjdp 61338889Sjdpvoid 61438889Sjdpdefine_accelerator (id, resinfo, data) 61538889Sjdp struct res_id id; 61638889Sjdp const struct res_res_info *resinfo; 61738889Sjdp struct accelerator *data; 61838889Sjdp{ 61938889Sjdp struct res_resource *r; 62038889Sjdp 62160484Sobrien r = define_standard_resource (&resources, RT_ACCELERATOR, id, 62238889Sjdp resinfo->language, 0); 62338889Sjdp r->type = RES_TYPE_ACCELERATOR; 62438889Sjdp r->u.acc = data; 62538889Sjdp r->res_info = *resinfo; 62638889Sjdp} 62738889Sjdp 62838889Sjdp/* Define a bitmap resource. Bitmap data is stored in a file. The 62938889Sjdp first 14 bytes of the file are a standard header, which is not 63038889Sjdp included in the resource data. */ 63138889Sjdp 63238889Sjdp#define BITMAP_SKIP (14) 63338889Sjdp 63438889Sjdpvoid 63538889Sjdpdefine_bitmap (id, resinfo, filename) 63638889Sjdp struct res_id id; 63738889Sjdp const struct res_res_info *resinfo; 63838889Sjdp const char *filename; 63938889Sjdp{ 64038889Sjdp FILE *e; 64138889Sjdp char *real_filename; 64238889Sjdp struct stat s; 64338889Sjdp unsigned char *data; 64438889Sjdp int i; 64538889Sjdp struct res_resource *r; 64638889Sjdp 64738889Sjdp e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename); 64838889Sjdp 64938889Sjdp if (stat (real_filename, &s) < 0) 65060484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 65138889Sjdp strerror (errno)); 65238889Sjdp 65338889Sjdp data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP); 65438889Sjdp 65538889Sjdp for (i = 0; i < BITMAP_SKIP; i++) 65638889Sjdp getc (e); 65738889Sjdp 65838889Sjdp get_data (e, data, s.st_size - BITMAP_SKIP, real_filename); 65938889Sjdp 66038889Sjdp fclose (e); 66138889Sjdp free (real_filename); 66238889Sjdp 66338889Sjdp r = define_standard_resource (&resources, RT_BITMAP, id, 66438889Sjdp resinfo->language, 0); 66538889Sjdp 66638889Sjdp r->type = RES_TYPE_BITMAP; 66738889Sjdp r->u.data.length = s.st_size - BITMAP_SKIP; 66838889Sjdp r->u.data.data = data; 66938889Sjdp r->res_info = *resinfo; 67038889Sjdp} 67138889Sjdp 67238889Sjdp/* Define a cursor resource. A cursor file may contain a set of 67338889Sjdp bitmaps, each representing the same cursor at various different 67438889Sjdp resolutions. They each get written out with a different ID. The 67538889Sjdp real cursor resource is then a group resource which can be used to 67638889Sjdp select one of the actual cursors. */ 67738889Sjdp 67838889Sjdpvoid 67938889Sjdpdefine_cursor (id, resinfo, filename) 68038889Sjdp struct res_id id; 68138889Sjdp const struct res_res_info *resinfo; 68238889Sjdp const char *filename; 68338889Sjdp{ 68438889Sjdp FILE *e; 68538889Sjdp char *real_filename; 68638889Sjdp int type, count, i; 68738889Sjdp struct icondir *icondirs; 68838889Sjdp int first_cursor; 68938889Sjdp struct res_resource *r; 69038889Sjdp struct group_cursor *first, **pp; 69138889Sjdp 69238889Sjdp e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename); 69338889Sjdp 69438889Sjdp /* A cursor file is basically an icon file. The start of the file 69538889Sjdp is a three word structure. The first word is ignored. The 69638889Sjdp second word is the type of data. The third word is the number of 69738889Sjdp entries. */ 69838889Sjdp 69938889Sjdp get_word (e, real_filename); 70038889Sjdp type = get_word (e, real_filename); 70138889Sjdp count = get_word (e, real_filename); 70238889Sjdp if (type != 2) 70360484Sobrien fatal (_("cursor file `%s' does not contain cursor data"), real_filename); 70438889Sjdp 70538889Sjdp /* Read in the icon directory entries. */ 70638889Sjdp 70738889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 70838889Sjdp 70938889Sjdp for (i = 0; i < count; i++) 71038889Sjdp { 71138889Sjdp icondirs[i].width = getc (e); 71238889Sjdp icondirs[i].height = getc (e); 71338889Sjdp icondirs[i].colorcount = getc (e); 71438889Sjdp getc (e); 71538889Sjdp icondirs[i].u.cursor.xhotspot = get_word (e, real_filename); 71638889Sjdp icondirs[i].u.cursor.yhotspot = get_word (e, real_filename); 71738889Sjdp icondirs[i].bytes = get_long (e, real_filename); 71838889Sjdp icondirs[i].offset = get_long (e, real_filename); 71938889Sjdp 72038889Sjdp if (feof (e)) 72138889Sjdp unexpected_eof (real_filename); 72238889Sjdp } 72338889Sjdp 72438889Sjdp /* Define each cursor as a unique resource. */ 72538889Sjdp 72638889Sjdp first_cursor = cursors; 72738889Sjdp 72838889Sjdp for (i = 0; i < count; i++) 72938889Sjdp { 73038889Sjdp unsigned char *data; 73138889Sjdp struct res_id name; 73238889Sjdp struct cursor *c; 73338889Sjdp 73438889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 73560484Sobrien fatal (_("%s: fseek to %lu failed: %s"), real_filename, 73638889Sjdp icondirs[i].offset, strerror (errno)); 73738889Sjdp 73838889Sjdp data = (unsigned char *) res_alloc (icondirs[i].bytes); 73938889Sjdp 74038889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 74138889Sjdp 74238889Sjdp c = (struct cursor *) res_alloc (sizeof *c); 74338889Sjdp c->xhotspot = icondirs[i].u.cursor.xhotspot; 74438889Sjdp c->yhotspot = icondirs[i].u.cursor.yhotspot; 74538889Sjdp c->length = icondirs[i].bytes; 74638889Sjdp c->data = data; 74738889Sjdp 74838889Sjdp ++cursors; 74938889Sjdp 75038889Sjdp name.named = 0; 75138889Sjdp name.u.id = cursors; 75238889Sjdp 75338889Sjdp r = define_standard_resource (&resources, RT_CURSOR, name, 75438889Sjdp resinfo->language, 0); 75538889Sjdp r->type = RES_TYPE_CURSOR; 75638889Sjdp r->u.cursor = c; 75738889Sjdp r->res_info = *resinfo; 75838889Sjdp } 75938889Sjdp 76038889Sjdp fclose (e); 76138889Sjdp free (real_filename); 76238889Sjdp 76338889Sjdp /* Define a cursor group resource. */ 76438889Sjdp 76538889Sjdp first = NULL; 76638889Sjdp pp = &first; 76738889Sjdp for (i = 0; i < count; i++) 76838889Sjdp { 76938889Sjdp struct group_cursor *cg; 77038889Sjdp 77138889Sjdp cg = (struct group_cursor *) res_alloc (sizeof *cg); 77238889Sjdp cg->next = NULL; 77338889Sjdp cg->width = icondirs[i].width; 77438889Sjdp cg->height = 2 * icondirs[i].height; 77538889Sjdp 77638889Sjdp /* FIXME: What should these be set to? */ 77738889Sjdp cg->planes = 1; 77838889Sjdp cg->bits = 1; 77938889Sjdp 78038889Sjdp cg->bytes = icondirs[i].bytes + 4; 78138889Sjdp cg->index = first_cursor + i + 1; 78238889Sjdp 78338889Sjdp *pp = cg; 78438889Sjdp pp = &(*pp)->next; 78538889Sjdp } 78638889Sjdp 78738889Sjdp free (icondirs); 78838889Sjdp 78938889Sjdp r = define_standard_resource (&resources, RT_GROUP_CURSOR, id, 79038889Sjdp resinfo->language, 0); 79138889Sjdp r->type = RES_TYPE_GROUP_CURSOR; 79238889Sjdp r->u.group_cursor = first; 79338889Sjdp r->res_info = *resinfo; 79438889Sjdp} 79538889Sjdp 79638889Sjdp/* Define a dialog resource. */ 79738889Sjdp 79838889Sjdpvoid 79938889Sjdpdefine_dialog (id, resinfo, dialog) 80038889Sjdp struct res_id id; 80138889Sjdp const struct res_res_info *resinfo; 80238889Sjdp const struct dialog *dialog; 80338889Sjdp{ 80438889Sjdp struct dialog *copy; 80538889Sjdp struct res_resource *r; 80638889Sjdp 80738889Sjdp copy = (struct dialog *) res_alloc (sizeof *copy); 80838889Sjdp *copy = *dialog; 80938889Sjdp 81038889Sjdp r = define_standard_resource (&resources, RT_DIALOG, id, 81138889Sjdp resinfo->language, 0); 81238889Sjdp r->type = RES_TYPE_DIALOG; 81338889Sjdp r->u.dialog = copy; 81438889Sjdp r->res_info = *resinfo; 81538889Sjdp} 81638889Sjdp 81738889Sjdp/* Define a dialog control. This does not define a resource, but 81838889Sjdp merely allocates and fills in a structure. */ 81938889Sjdp 82038889Sjdpstruct dialog_control * 82138889Sjdpdefine_control (text, id, x, y, width, height, class, style, exstyle) 82238889Sjdp const char *text; 82338889Sjdp unsigned long id; 82438889Sjdp unsigned long x; 82538889Sjdp unsigned long y; 82638889Sjdp unsigned long width; 82738889Sjdp unsigned long height; 82838889Sjdp unsigned long class; 82938889Sjdp unsigned long style; 83038889Sjdp unsigned long exstyle; 83138889Sjdp{ 83238889Sjdp struct dialog_control *n; 83338889Sjdp 83438889Sjdp n = (struct dialog_control *) res_alloc (sizeof *n); 83538889Sjdp n->next = NULL; 83638889Sjdp n->id = id; 83738889Sjdp n->style = style; 83838889Sjdp n->exstyle = exstyle; 83938889Sjdp n->x = x; 84038889Sjdp n->y = y; 84138889Sjdp n->width = width; 84238889Sjdp n->height = height; 84338889Sjdp n->class.named = 0; 84438889Sjdp n->class.u.id = class; 84577298Sobrien if (text == NULL) 84677298Sobrien text = ""; 84777298Sobrien res_string_to_id (&n->text, text); 84838889Sjdp n->data = NULL; 84938889Sjdp n->help = 0; 85038889Sjdp 85138889Sjdp return n; 85238889Sjdp} 85338889Sjdp 85477298Sobrienstruct dialog_control * 85577298Sobriendefine_icon_control (iid, id, x, y, style, exstyle, help, data, ex) 85677298Sobrien struct res_id iid; 85777298Sobrien unsigned long id; 85877298Sobrien unsigned long x; 85977298Sobrien unsigned long y; 86077298Sobrien unsigned long style; 86177298Sobrien unsigned long exstyle; 86277298Sobrien unsigned long help; 86377298Sobrien struct rcdata_item *data; 86477298Sobrien struct dialog_ex *ex; 86577298Sobrien{ 86677298Sobrien struct dialog_control *n; 86777298Sobrien if (style == 0) 86877298Sobrien style = SS_ICON | WS_CHILD | WS_VISIBLE; 86977298Sobrien n = define_control (0, id, x, y, 0, 0, CTL_STATIC, style, exstyle); 87077298Sobrien n->text = iid; 87177298Sobrien if (help && !ex) 87277298Sobrien rcparse_warning (_("help ID requires DIALOGEX")); 87377298Sobrien if (data && !ex) 87477298Sobrien rcparse_warning (_("control data requires DIALOGEX")); 87577298Sobrien n->help = help; 87677298Sobrien n->data = data; 87777298Sobrien 87877298Sobrien return n; 87977298Sobrien} 88077298Sobrien 88138889Sjdp/* Define a font resource. */ 88238889Sjdp 88338889Sjdpvoid 88438889Sjdpdefine_font (id, resinfo, filename) 88538889Sjdp struct res_id id; 88638889Sjdp const struct res_res_info *resinfo; 88738889Sjdp const char *filename; 88838889Sjdp{ 88938889Sjdp FILE *e; 89038889Sjdp char *real_filename; 89138889Sjdp struct stat s; 89238889Sjdp unsigned char *data; 89338889Sjdp struct res_resource *r; 89438889Sjdp long offset; 89538889Sjdp long fontdatalength; 89638889Sjdp unsigned char *fontdata; 89738889Sjdp struct fontdir *fd; 89838889Sjdp const char *device, *face; 89938889Sjdp struct fontdir **pp; 90038889Sjdp 90138889Sjdp e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); 90238889Sjdp 90338889Sjdp if (stat (real_filename, &s) < 0) 90460484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 90538889Sjdp strerror (errno)); 90638889Sjdp 90738889Sjdp data = (unsigned char *) res_alloc (s.st_size); 90838889Sjdp 90938889Sjdp get_data (e, data, s.st_size, real_filename); 91038889Sjdp 91138889Sjdp fclose (e); 91238889Sjdp free (real_filename); 91338889Sjdp 91438889Sjdp r = define_standard_resource (&resources, RT_FONT, id, 91538889Sjdp resinfo->language, 0); 91638889Sjdp 91738889Sjdp r->type = RES_TYPE_FONT; 91838889Sjdp r->u.data.length = s.st_size; 91938889Sjdp r->u.data.data = data; 92038889Sjdp r->res_info = *resinfo; 92138889Sjdp 92238889Sjdp /* For each font resource, we must add an entry in the FONTDIR 92338889Sjdp resource. The FONTDIR resource includes some strings in the font 92438889Sjdp file. To find them, we have to do some magic on the data we have 92538889Sjdp read. */ 92638889Sjdp 92738889Sjdp offset = ((((((data[47] << 8) 92838889Sjdp | data[46]) << 8) 92938889Sjdp | data[45]) << 8) 93038889Sjdp | data[44]); 93138889Sjdp if (offset > 0 && offset < s.st_size) 93238889Sjdp device = (char *) data + offset; 93338889Sjdp else 93438889Sjdp device = ""; 93538889Sjdp 93638889Sjdp offset = ((((((data[51] << 8) 93738889Sjdp | data[50]) << 8) 93838889Sjdp | data[49]) << 8) 93938889Sjdp | data[48]); 94038889Sjdp if (offset > 0 && offset < s.st_size) 94138889Sjdp face = (char *) data + offset; 94238889Sjdp else 94338889Sjdp face = ""; 94438889Sjdp 94538889Sjdp ++fonts; 94638889Sjdp 94738889Sjdp fontdatalength = 58 + strlen (device) + strlen (face); 94838889Sjdp fontdata = (unsigned char *) res_alloc (fontdatalength); 94938889Sjdp memcpy (fontdata, data, 56); 95038889Sjdp strcpy ((char *) fontdata + 56, device); 95138889Sjdp strcpy ((char *) fontdata + 57 + strlen (device), face); 95238889Sjdp 95338889Sjdp fd = (struct fontdir *) res_alloc (sizeof *fd); 95438889Sjdp fd->next = NULL; 95538889Sjdp fd->index = fonts; 95638889Sjdp fd->length = fontdatalength; 95738889Sjdp fd->data = fontdata; 95838889Sjdp 95938889Sjdp for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next) 96038889Sjdp ; 96138889Sjdp *pp = fd; 96238889Sjdp 96338889Sjdp /* For the single fontdirs resource, we always use the resource 96438889Sjdp information of the last font. I don't know what else to do. */ 96538889Sjdp fontdirs_resinfo = *resinfo; 96638889Sjdp} 96738889Sjdp 96838889Sjdp/* Define the fontdirs resource. This is called after the entire rc 96938889Sjdp file has been parsed, if any font resources were seen. */ 97038889Sjdp 97138889Sjdpstatic void 97238889Sjdpdefine_fontdirs () 97338889Sjdp{ 97438889Sjdp struct res_resource *r; 97538889Sjdp struct res_id id; 97638889Sjdp 97738889Sjdp id.named = 0; 97838889Sjdp id.u.id = 1; 97938889Sjdp 98038889Sjdp r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0); 98138889Sjdp 98238889Sjdp r->type = RES_TYPE_FONTDIR; 98338889Sjdp r->u.fontdir = fontdirs; 98438889Sjdp r->res_info = fontdirs_resinfo; 98538889Sjdp} 98638889Sjdp 98738889Sjdp/* Define an icon resource. An icon file may contain a set of 98838889Sjdp bitmaps, each representing the same icon at various different 98938889Sjdp resolutions. They each get written out with a different ID. The 99038889Sjdp real icon resource is then a group resource which can be used to 99138889Sjdp select one of the actual icon bitmaps. */ 99238889Sjdp 99338889Sjdpvoid 99438889Sjdpdefine_icon (id, resinfo, filename) 99538889Sjdp struct res_id id; 99638889Sjdp const struct res_res_info *resinfo; 99738889Sjdp const char *filename; 99838889Sjdp{ 99938889Sjdp FILE *e; 100038889Sjdp char *real_filename; 100138889Sjdp int type, count, i; 100238889Sjdp struct icondir *icondirs; 100338889Sjdp int first_icon; 100438889Sjdp struct res_resource *r; 100538889Sjdp struct group_icon *first, **pp; 100638889Sjdp 100738889Sjdp e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename); 100838889Sjdp 100938889Sjdp /* The start of an icon file is a three word structure. The first 101038889Sjdp word is ignored. The second word is the type of data. The third 101138889Sjdp word is the number of entries. */ 101238889Sjdp 101338889Sjdp get_word (e, real_filename); 101438889Sjdp type = get_word (e, real_filename); 101538889Sjdp count = get_word (e, real_filename); 101638889Sjdp if (type != 1) 101760484Sobrien fatal (_("icon file `%s' does not contain icon data"), real_filename); 101838889Sjdp 101938889Sjdp /* Read in the icon directory entries. */ 102038889Sjdp 102138889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 102238889Sjdp 102338889Sjdp for (i = 0; i < count; i++) 102438889Sjdp { 102538889Sjdp icondirs[i].width = getc (e); 102638889Sjdp icondirs[i].height = getc (e); 102738889Sjdp icondirs[i].colorcount = getc (e); 102838889Sjdp getc (e); 102938889Sjdp icondirs[i].u.icon.planes = get_word (e, real_filename); 103038889Sjdp icondirs[i].u.icon.bits = get_word (e, real_filename); 103138889Sjdp icondirs[i].bytes = get_long (e, real_filename); 103238889Sjdp icondirs[i].offset = get_long (e, real_filename); 103338889Sjdp 103438889Sjdp if (feof (e)) 103538889Sjdp unexpected_eof (real_filename); 103638889Sjdp } 103738889Sjdp 103838889Sjdp /* Define each icon as a unique resource. */ 103938889Sjdp 104038889Sjdp first_icon = icons; 104138889Sjdp 104238889Sjdp for (i = 0; i < count; i++) 104338889Sjdp { 104438889Sjdp unsigned char *data; 104538889Sjdp struct res_id name; 104638889Sjdp 104738889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 104860484Sobrien fatal (_("%s: fseek to %lu failed: %s"), real_filename, 104938889Sjdp icondirs[i].offset, strerror (errno)); 105038889Sjdp 105138889Sjdp data = (unsigned char *) res_alloc (icondirs[i].bytes); 105238889Sjdp 105338889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 105438889Sjdp 105538889Sjdp ++icons; 105638889Sjdp 105738889Sjdp name.named = 0; 105838889Sjdp name.u.id = icons; 105938889Sjdp 106038889Sjdp r = define_standard_resource (&resources, RT_ICON, name, 106138889Sjdp resinfo->language, 0); 106238889Sjdp r->type = RES_TYPE_ICON; 106338889Sjdp r->u.data.length = icondirs[i].bytes; 106438889Sjdp r->u.data.data = data; 106538889Sjdp r->res_info = *resinfo; 106638889Sjdp } 106738889Sjdp 106838889Sjdp fclose (e); 106938889Sjdp free (real_filename); 107038889Sjdp 107138889Sjdp /* Define an icon group resource. */ 107238889Sjdp 107338889Sjdp first = NULL; 107438889Sjdp pp = &first; 107538889Sjdp for (i = 0; i < count; i++) 107638889Sjdp { 107738889Sjdp struct group_icon *cg; 107838889Sjdp 107938889Sjdp /* For some reason, at least in some files the planes and bits 108038889Sjdp are zero. We instead set them from the color. This is 108138889Sjdp copied from rcl. */ 108238889Sjdp 108338889Sjdp cg = (struct group_icon *) res_alloc (sizeof *cg); 108438889Sjdp cg->next = NULL; 108538889Sjdp cg->width = icondirs[i].width; 108638889Sjdp cg->height = icondirs[i].height; 108738889Sjdp cg->colors = icondirs[i].colorcount; 108838889Sjdp 108938889Sjdp cg->planes = 1; 109038889Sjdp cg->bits = 0; 109138889Sjdp while ((1 << cg->bits) < cg->colors) 109238889Sjdp ++cg->bits; 109338889Sjdp 109438889Sjdp cg->bytes = icondirs[i].bytes; 109538889Sjdp cg->index = first_icon + i + 1; 109638889Sjdp 109738889Sjdp *pp = cg; 109838889Sjdp pp = &(*pp)->next; 109938889Sjdp } 110038889Sjdp 110138889Sjdp free (icondirs); 110238889Sjdp 110338889Sjdp r = define_standard_resource (&resources, RT_GROUP_ICON, id, 110438889Sjdp resinfo->language, 0); 110538889Sjdp r->type = RES_TYPE_GROUP_ICON; 110638889Sjdp r->u.group_icon = first; 110738889Sjdp r->res_info = *resinfo; 110838889Sjdp} 110938889Sjdp 111038889Sjdp/* Define a menu resource. */ 111138889Sjdp 111238889Sjdpvoid 111338889Sjdpdefine_menu (id, resinfo, menuitems) 111438889Sjdp struct res_id id; 111538889Sjdp const struct res_res_info *resinfo; 111638889Sjdp struct menuitem *menuitems; 111738889Sjdp{ 111838889Sjdp struct menu *m; 111938889Sjdp struct res_resource *r; 112038889Sjdp 112138889Sjdp m = (struct menu *) res_alloc (sizeof *m); 112238889Sjdp m->items = menuitems; 112338889Sjdp m->help = 0; 112438889Sjdp 112538889Sjdp r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0); 112638889Sjdp r->type = RES_TYPE_MENU; 112738889Sjdp r->u.menu = m; 112838889Sjdp r->res_info = *resinfo; 112938889Sjdp} 113038889Sjdp 113138889Sjdp/* Define a menu item. This does not define a resource, but merely 113238889Sjdp allocates and fills in a structure. */ 113338889Sjdp 113438889Sjdpstruct menuitem * 113538889Sjdpdefine_menuitem (text, menuid, type, state, help, menuitems) 113638889Sjdp const char *text; 113738889Sjdp int menuid; 113838889Sjdp unsigned long type; 113938889Sjdp unsigned long state; 114038889Sjdp unsigned long help; 114138889Sjdp struct menuitem *menuitems; 114238889Sjdp{ 114338889Sjdp struct menuitem *mi; 114438889Sjdp 114538889Sjdp mi = (struct menuitem *) res_alloc (sizeof *mi); 114638889Sjdp mi->next = NULL; 114738889Sjdp mi->type = type; 114838889Sjdp mi->state = state; 114938889Sjdp mi->id = menuid; 115038889Sjdp if (text == NULL) 115138889Sjdp mi->text = NULL; 115238889Sjdp else 115338889Sjdp unicode_from_ascii ((int *) NULL, &mi->text, text); 115438889Sjdp mi->help = help; 115538889Sjdp mi->popup = menuitems; 115638889Sjdp return mi; 115738889Sjdp} 115838889Sjdp 115938889Sjdp/* Define a messagetable resource. */ 116038889Sjdp 116138889Sjdpvoid 116238889Sjdpdefine_messagetable (id, resinfo, filename) 116338889Sjdp struct res_id id; 116438889Sjdp const struct res_res_info *resinfo; 116538889Sjdp const char *filename; 116638889Sjdp{ 116738889Sjdp FILE *e; 116838889Sjdp char *real_filename; 116938889Sjdp struct stat s; 117038889Sjdp unsigned char *data; 117138889Sjdp struct res_resource *r; 117238889Sjdp 117338889Sjdp e = open_file_search (filename, FOPEN_RB, "messagetable file", 117438889Sjdp &real_filename); 117538889Sjdp 117638889Sjdp if (stat (real_filename, &s) < 0) 117760484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 117838889Sjdp strerror (errno)); 117938889Sjdp 118038889Sjdp data = (unsigned char *) res_alloc (s.st_size); 118138889Sjdp 118238889Sjdp get_data (e, data, s.st_size, real_filename); 118338889Sjdp 118438889Sjdp fclose (e); 118538889Sjdp free (real_filename); 118638889Sjdp 118738889Sjdp r = define_standard_resource (&resources, RT_MESSAGETABLE, id, 118838889Sjdp resinfo->language, 0); 118938889Sjdp 119038889Sjdp r->type = RES_TYPE_MESSAGETABLE; 119138889Sjdp r->u.data.length = s.st_size; 119238889Sjdp r->u.data.data = data; 119338889Sjdp r->res_info = *resinfo; 119438889Sjdp} 119538889Sjdp 119638889Sjdp/* Define an rcdata resource. */ 119738889Sjdp 119838889Sjdpvoid 119938889Sjdpdefine_rcdata (id, resinfo, data) 120038889Sjdp struct res_id id; 120138889Sjdp const struct res_res_info *resinfo; 120238889Sjdp struct rcdata_item *data; 120338889Sjdp{ 120438889Sjdp struct res_resource *r; 120538889Sjdp 120638889Sjdp r = define_standard_resource (&resources, RT_RCDATA, id, 120738889Sjdp resinfo->language, 0); 120838889Sjdp r->type = RES_TYPE_RCDATA; 120938889Sjdp r->u.rcdata = data; 121038889Sjdp r->res_info = *resinfo; 121138889Sjdp} 121238889Sjdp 121338889Sjdp/* Create an rcdata item holding a string. */ 121438889Sjdp 121538889Sjdpstruct rcdata_item * 121638889Sjdpdefine_rcdata_string (string, len) 121738889Sjdp const char *string; 121838889Sjdp unsigned long len; 121938889Sjdp{ 122038889Sjdp struct rcdata_item *ri; 122138889Sjdp char *s; 122238889Sjdp 122338889Sjdp ri = (struct rcdata_item *) res_alloc (sizeof *ri); 122438889Sjdp ri->next = NULL; 122538889Sjdp ri->type = RCDATA_STRING; 122638889Sjdp ri->u.string.length = len; 122738889Sjdp s = (char *) res_alloc (len); 122838889Sjdp memcpy (s, string, len); 122938889Sjdp ri->u.string.s = s; 123038889Sjdp 123138889Sjdp return ri; 123238889Sjdp} 123338889Sjdp 123438889Sjdp/* Create an rcdata item holding a number. */ 123538889Sjdp 123638889Sjdpstruct rcdata_item * 123738889Sjdpdefine_rcdata_number (val, dword) 123838889Sjdp unsigned long val; 123938889Sjdp int dword; 124038889Sjdp{ 124138889Sjdp struct rcdata_item *ri; 124238889Sjdp 124338889Sjdp ri = (struct rcdata_item *) res_alloc (sizeof *ri); 124438889Sjdp ri->next = NULL; 124538889Sjdp ri->type = dword ? RCDATA_DWORD : RCDATA_WORD; 124638889Sjdp ri->u.word = val; 124738889Sjdp 124838889Sjdp return ri; 124938889Sjdp} 125038889Sjdp 125138889Sjdp/* Define a stringtable resource. This is called for each string 125238889Sjdp which appears in a STRINGTABLE statement. */ 125338889Sjdp 125438889Sjdpvoid 125538889Sjdpdefine_stringtable (resinfo, stringid, string) 125638889Sjdp const struct res_res_info *resinfo; 125738889Sjdp unsigned long stringid; 125838889Sjdp const char *string; 125938889Sjdp{ 126038889Sjdp struct res_id id; 126138889Sjdp struct res_resource *r; 126238889Sjdp 126338889Sjdp id.named = 0; 126438889Sjdp id.u.id = (stringid >> 4) + 1; 126538889Sjdp r = define_standard_resource (&resources, RT_STRING, id, 126638889Sjdp resinfo->language, 1); 126738889Sjdp 126838889Sjdp if (r->type == RES_TYPE_UNINITIALIZED) 126938889Sjdp { 127038889Sjdp int i; 127138889Sjdp 127238889Sjdp r->type = RES_TYPE_STRINGTABLE; 127338889Sjdp r->u.stringtable = ((struct stringtable *) 127438889Sjdp res_alloc (sizeof (struct stringtable))); 127538889Sjdp for (i = 0; i < 16; i++) 127638889Sjdp { 127738889Sjdp r->u.stringtable->strings[i].length = 0; 127838889Sjdp r->u.stringtable->strings[i].string = NULL; 127938889Sjdp } 128038889Sjdp 128138889Sjdp r->res_info = *resinfo; 128238889Sjdp } 128338889Sjdp 128438889Sjdp unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length, 128538889Sjdp &r->u.stringtable->strings[stringid & 0xf].string, 128638889Sjdp string); 128738889Sjdp} 128838889Sjdp 128938889Sjdp/* Define a user data resource where the data is in the rc file. */ 129038889Sjdp 129138889Sjdpvoid 129238889Sjdpdefine_user_data (id, type, resinfo, data) 129338889Sjdp struct res_id id; 129438889Sjdp struct res_id type; 129538889Sjdp const struct res_res_info *resinfo; 129638889Sjdp struct rcdata_item *data; 129738889Sjdp{ 129838889Sjdp struct res_id ids[3]; 129938889Sjdp struct res_resource *r; 130038889Sjdp 130138889Sjdp ids[0] = type; 130238889Sjdp ids[1] = id; 130338889Sjdp ids[2].named = 0; 130438889Sjdp ids[2].u.id = resinfo->language; 130538889Sjdp 130638889Sjdp r = define_resource (&resources, 3, ids, 0); 130738889Sjdp r->type = RES_TYPE_USERDATA; 130838889Sjdp r->u.userdata = data; 130938889Sjdp r->res_info = *resinfo; 131038889Sjdp} 131138889Sjdp 131238889Sjdp/* Define a user data resource where the data is in a file. */ 131338889Sjdp 131438889Sjdpvoid 131538889Sjdpdefine_user_file (id, type, resinfo, filename) 131638889Sjdp struct res_id id; 131738889Sjdp struct res_id type; 131838889Sjdp const struct res_res_info *resinfo; 131938889Sjdp const char *filename; 132038889Sjdp{ 132138889Sjdp FILE *e; 132238889Sjdp char *real_filename; 132338889Sjdp struct stat s; 132438889Sjdp unsigned char *data; 132538889Sjdp struct res_id ids[3]; 132638889Sjdp struct res_resource *r; 132738889Sjdp 132838889Sjdp e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); 132938889Sjdp 133038889Sjdp if (stat (real_filename, &s) < 0) 133160484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 133238889Sjdp strerror (errno)); 133338889Sjdp 133438889Sjdp data = (unsigned char *) res_alloc (s.st_size); 133538889Sjdp 133638889Sjdp get_data (e, data, s.st_size, real_filename); 133738889Sjdp 133838889Sjdp fclose (e); 133938889Sjdp free (real_filename); 134038889Sjdp 134138889Sjdp ids[0] = type; 134238889Sjdp ids[1] = id; 134338889Sjdp ids[2].named = 0; 134438889Sjdp ids[2].u.id = resinfo->language; 134538889Sjdp 134638889Sjdp r = define_resource (&resources, 3, ids, 0); 134738889Sjdp r->type = RES_TYPE_USERDATA; 134838889Sjdp r->u.userdata = ((struct rcdata_item *) 134938889Sjdp res_alloc (sizeof (struct rcdata_item))); 135038889Sjdp r->u.userdata->next = NULL; 135138889Sjdp r->u.userdata->type = RCDATA_BUFFER; 135238889Sjdp r->u.userdata->u.buffer.length = s.st_size; 135338889Sjdp r->u.userdata->u.buffer.data = data; 135438889Sjdp r->res_info = *resinfo; 135538889Sjdp} 135638889Sjdp 135738889Sjdp/* Define a versioninfo resource. */ 135838889Sjdp 135938889Sjdpvoid 136038889Sjdpdefine_versioninfo (id, language, fixedverinfo, verinfo) 136138889Sjdp struct res_id id; 136238889Sjdp int language; 136338889Sjdp struct fixed_versioninfo *fixedverinfo; 136438889Sjdp struct ver_info *verinfo; 136538889Sjdp{ 136638889Sjdp struct res_resource *r; 136738889Sjdp 136838889Sjdp r = define_standard_resource (&resources, RT_VERSION, id, language, 0); 136938889Sjdp r->type = RES_TYPE_VERSIONINFO; 137038889Sjdp r->u.versioninfo = ((struct versioninfo *) 137138889Sjdp res_alloc (sizeof (struct versioninfo))); 137238889Sjdp r->u.versioninfo->fixed = fixedverinfo; 137338889Sjdp r->u.versioninfo->var = verinfo; 137438889Sjdp r->res_info.language = language; 137538889Sjdp} 137638889Sjdp 137738889Sjdp/* Add string version info to a list of version information. */ 137838889Sjdp 137938889Sjdpstruct ver_info * 138038889Sjdpappend_ver_stringfileinfo (verinfo, language, strings) 138138889Sjdp struct ver_info *verinfo; 138238889Sjdp const char *language; 138338889Sjdp struct ver_stringinfo *strings; 138438889Sjdp{ 138538889Sjdp struct ver_info *vi, **pp; 138638889Sjdp 138738889Sjdp vi = (struct ver_info *) res_alloc (sizeof *vi); 138838889Sjdp vi->next = NULL; 138938889Sjdp vi->type = VERINFO_STRING; 139038889Sjdp unicode_from_ascii ((int *) NULL, &vi->u.string.language, language); 139138889Sjdp vi->u.string.strings = strings; 139238889Sjdp 139338889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 139438889Sjdp ; 139538889Sjdp *pp = vi; 139638889Sjdp 139738889Sjdp return verinfo; 139838889Sjdp} 139938889Sjdp 140038889Sjdp/* Add variable version info to a list of version information. */ 140138889Sjdp 140238889Sjdpstruct ver_info * 140338889Sjdpappend_ver_varfileinfo (verinfo, key, var) 140438889Sjdp struct ver_info *verinfo; 140538889Sjdp const char *key; 140638889Sjdp struct ver_varinfo *var; 140738889Sjdp{ 140838889Sjdp struct ver_info *vi, **pp; 140938889Sjdp 141038889Sjdp vi = (struct ver_info *) res_alloc (sizeof *vi); 141138889Sjdp vi->next = NULL; 141238889Sjdp vi->type = VERINFO_VAR; 141338889Sjdp unicode_from_ascii ((int *) NULL, &vi->u.var.key, key); 141438889Sjdp vi->u.var.var = var; 141538889Sjdp 141638889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 141738889Sjdp ; 141838889Sjdp *pp = vi; 141938889Sjdp 142038889Sjdp return verinfo; 142138889Sjdp} 142238889Sjdp 142338889Sjdp/* Append version string information to a list. */ 142438889Sjdp 142538889Sjdpstruct ver_stringinfo * 142638889Sjdpappend_verval (strings, key, value) 142738889Sjdp struct ver_stringinfo *strings; 142838889Sjdp const char *key; 142938889Sjdp const char *value; 143038889Sjdp{ 143138889Sjdp struct ver_stringinfo *vs, **pp; 143238889Sjdp 143338889Sjdp vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); 143438889Sjdp vs->next = NULL; 143538889Sjdp unicode_from_ascii ((int *) NULL, &vs->key, key); 143638889Sjdp unicode_from_ascii ((int *) NULL, &vs->value, value); 143738889Sjdp 143838889Sjdp for (pp = &strings; *pp != NULL; pp = &(*pp)->next) 143938889Sjdp ; 144038889Sjdp *pp = vs; 144138889Sjdp 144238889Sjdp return strings; 144338889Sjdp} 144438889Sjdp 144538889Sjdp/* Append version variable information to a list. */ 144638889Sjdp 144738889Sjdpstruct ver_varinfo * 144838889Sjdpappend_vertrans (var, language, charset) 144938889Sjdp struct ver_varinfo *var; 145038889Sjdp unsigned long language; 145138889Sjdp unsigned long charset; 145238889Sjdp{ 145338889Sjdp struct ver_varinfo *vv, **pp; 145438889Sjdp 145538889Sjdp vv = (struct ver_varinfo *) res_alloc (sizeof *vv); 145638889Sjdp vv->next = NULL; 145738889Sjdp vv->language = language; 145838889Sjdp vv->charset = charset; 145938889Sjdp 146038889Sjdp for (pp = &var; *pp != NULL; pp = &(*pp)->next) 146138889Sjdp ; 146238889Sjdp *pp = vv; 146338889Sjdp 146438889Sjdp return var; 146538889Sjdp} 146638889Sjdp 146738889Sjdp/* Local functions used to write out an rc file. */ 146838889Sjdp 146938889Sjdpstatic void indent PARAMS ((FILE *, int)); 147038889Sjdpstatic void write_rc_directory 147138889Sjdp PARAMS ((FILE *, const struct res_directory *, const struct res_id *, 147238889Sjdp const struct res_id *, int *, int)); 147338889Sjdpstatic void write_rc_subdir 147438889Sjdp PARAMS ((FILE *, const struct res_entry *, const struct res_id *, 147538889Sjdp const struct res_id *, int *, int)); 147638889Sjdpstatic void write_rc_resource 147738889Sjdp PARAMS ((FILE *, const struct res_id *, const struct res_id *, 147838889Sjdp const struct res_resource *, int *)); 147938889Sjdpstatic void write_rc_accelerators 148038889Sjdp PARAMS ((FILE *, const struct accelerator *)); 148138889Sjdpstatic void write_rc_cursor PARAMS ((FILE *, const struct cursor *)); 148238889Sjdpstatic void write_rc_group_cursor 148338889Sjdp PARAMS ((FILE *, const struct group_cursor *)); 148438889Sjdpstatic void write_rc_dialog PARAMS ((FILE *, const struct dialog *)); 148538889Sjdpstatic void write_rc_dialog_control 148638889Sjdp PARAMS ((FILE *, const struct dialog_control *)); 148738889Sjdpstatic void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *)); 148838889Sjdpstatic void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *)); 148938889Sjdpstatic void write_rc_menu PARAMS ((FILE *, const struct menu *, int)); 149038889Sjdpstatic void write_rc_menuitems 149138889Sjdp PARAMS ((FILE *, const struct menuitem *, int, int)); 149238889Sjdpstatic void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int)); 149338889Sjdpstatic void write_rc_stringtable 149438889Sjdp PARAMS ((FILE *, const struct res_id *, const struct stringtable *)); 149538889Sjdpstatic void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *)); 149638889Sjdpstatic void write_rc_filedata 149738889Sjdp PARAMS ((FILE *, unsigned long, const unsigned char *)); 149838889Sjdp 149938889Sjdp/* Indent a given number of spaces. */ 150038889Sjdp 150138889Sjdpstatic void 150238889Sjdpindent (e, c) 150338889Sjdp FILE *e; 150438889Sjdp int c; 150538889Sjdp{ 150638889Sjdp int i; 150738889Sjdp 150838889Sjdp for (i = 0; i < c; i++) 150938889Sjdp putc (' ', e); 151038889Sjdp} 151138889Sjdp 151238889Sjdp/* Dump the resources we have read in the format of an rc file. 151338889Sjdp 151438889Sjdp Actually, we don't use the format of an rc file, because it's way 151538889Sjdp too much of a pain--for example, we'd have to write icon resources 151638889Sjdp into a file and refer to that file. We just generate a readable 151738889Sjdp format that kind of looks like an rc file, and is useful for 151838889Sjdp understanding the contents of a resource file. Someday we may want 151938889Sjdp to generate an rc file which the rc compiler can read; if that day 152038889Sjdp comes, this code will have to be fixed up. */ 152138889Sjdp 152238889Sjdpvoid 152338889Sjdpwrite_rc_file (filename, resources) 152438889Sjdp const char *filename; 152538889Sjdp const struct res_directory *resources; 152638889Sjdp{ 152738889Sjdp FILE *e; 152838889Sjdp int language; 152938889Sjdp 153038889Sjdp if (filename == NULL) 153138889Sjdp e = stdout; 153238889Sjdp else 153338889Sjdp { 153438889Sjdp e = fopen (filename, FOPEN_WT); 153538889Sjdp if (e == NULL) 153660484Sobrien fatal (_("can't open `%s' for output: %s"), filename, strerror (errno)); 153738889Sjdp } 153838889Sjdp 153938889Sjdp language = -1; 154038889Sjdp write_rc_directory (e, resources, (const struct res_id *) NULL, 154138889Sjdp (const struct res_id *) NULL, &language, 1); 154238889Sjdp} 154338889Sjdp 154438889Sjdp/* Write out a directory. E is the file to write to. RD is the 154538889Sjdp directory. TYPE is a pointer to the level 1 ID which serves as the 154638889Sjdp resource type. NAME is a pointer to the level 2 ID which serves as 154738889Sjdp an individual resource name. LANGUAGE is a pointer to the current 154838889Sjdp language. LEVEL is the level in the tree. */ 154938889Sjdp 155038889Sjdpstatic void 155138889Sjdpwrite_rc_directory (e, rd, type, name, language, level) 155238889Sjdp FILE *e; 155338889Sjdp const struct res_directory *rd; 155438889Sjdp const struct res_id *type; 155538889Sjdp const struct res_id *name; 155638889Sjdp int *language; 155738889Sjdp int level; 155838889Sjdp{ 155938889Sjdp const struct res_entry *re; 156038889Sjdp 156138889Sjdp /* Print out some COFF information that rc files can't represent. */ 156238889Sjdp 156338889Sjdp if (rd->time != 0) 156438889Sjdp fprintf (e, "// Time stamp: %lu\n", rd->time); 156538889Sjdp if (rd->characteristics != 0) 156638889Sjdp fprintf (e, "// Characteristics: %lu\n", rd->characteristics); 156738889Sjdp if (rd->major != 0 || rd->minor != 0) 156838889Sjdp fprintf (e, "// Version: %d %d\n", rd->major, rd->minor); 156938889Sjdp 157038889Sjdp for (re = rd->entries; re != NULL; re = re->next) 157138889Sjdp { 157238889Sjdp switch (level) 157338889Sjdp { 157438889Sjdp case 1: 157538889Sjdp /* If we're at level 1, the key of this resource is the 157638889Sjdp type. This normally duplicates the information we have 157738889Sjdp stored with the resource itself, but we need to remember 157838889Sjdp the type if this is a user define resource type. */ 157938889Sjdp type = &re->id; 158038889Sjdp break; 158138889Sjdp 158238889Sjdp case 2: 158338889Sjdp /* If we're at level 2, the key of this resource is the name 158499461Sobrien we are going to use in the rc printout. */ 158538889Sjdp name = &re->id; 158638889Sjdp break; 158738889Sjdp 158838889Sjdp case 3: 158938889Sjdp /* If we're at level 3, then this key represents a language. 159038889Sjdp Use it to update the current language. */ 159138889Sjdp if (! re->id.named 159260484Sobrien && re->id.u.id != (unsigned long) (unsigned int) *language 159338889Sjdp && (re->id.u.id & 0xffff) == re->id.u.id) 159438889Sjdp { 159538889Sjdp fprintf (e, "LANGUAGE %lu, %lu\n", 1596104834Sobrien re->id.u.id & ((1 << SUBLANG_SHIFT) - 1), 159799461Sobrien (re->id.u.id >> SUBLANG_SHIFT) & 0xff); 159838889Sjdp *language = re->id.u.id; 159938889Sjdp } 160038889Sjdp break; 160138889Sjdp 160238889Sjdp default: 160338889Sjdp break; 160438889Sjdp } 160538889Sjdp 160638889Sjdp if (re->subdir) 160738889Sjdp write_rc_subdir (e, re, type, name, language, level); 160838889Sjdp else 160938889Sjdp { 161038889Sjdp if (level == 3) 161138889Sjdp { 161238889Sjdp /* This is the normal case: the three levels are 161338889Sjdp TYPE/NAME/LANGUAGE. NAME will have been set at level 161438889Sjdp 2, and represents the name to use. We probably just 161538889Sjdp set LANGUAGE, and it will probably match what the 161638889Sjdp resource itself records if anything. */ 161738889Sjdp write_rc_resource (e, type, name, re->u.res, language); 161838889Sjdp } 161938889Sjdp else 162038889Sjdp { 162138889Sjdp fprintf (e, "// Resource at unexpected level %d\n", level); 162238889Sjdp write_rc_resource (e, type, (struct res_id *) NULL, re->u.res, 162338889Sjdp language); 162438889Sjdp } 162538889Sjdp } 162638889Sjdp } 162738889Sjdp} 162838889Sjdp 162938889Sjdp/* Write out a subdirectory entry. E is the file to write to. RE is 163038889Sjdp the subdirectory entry. TYPE and NAME are pointers to higher level 163138889Sjdp IDs, or NULL. LANGUAGE is a pointer to the current language. 163238889Sjdp LEVEL is the level in the tree. */ 163338889Sjdp 163438889Sjdpstatic void 163538889Sjdpwrite_rc_subdir (e, re, type, name, language, level) 163638889Sjdp FILE *e; 163738889Sjdp const struct res_entry *re; 163838889Sjdp const struct res_id *type; 163938889Sjdp const struct res_id *name; 164038889Sjdp int *language; 164138889Sjdp int level; 164238889Sjdp{ 164338889Sjdp fprintf (e, "\n"); 164438889Sjdp switch (level) 164538889Sjdp { 164638889Sjdp case 1: 164738889Sjdp fprintf (e, "// Type: "); 164838889Sjdp if (re->id.named) 164938889Sjdp res_id_print (e, re->id, 1); 165038889Sjdp else 165138889Sjdp { 165238889Sjdp const char *s; 165338889Sjdp 165438889Sjdp switch (re->id.u.id) 165538889Sjdp { 165638889Sjdp case RT_CURSOR: s = "cursor"; break; 165738889Sjdp case RT_BITMAP: s = "bitmap"; break; 165838889Sjdp case RT_ICON: s = "icon"; break; 165938889Sjdp case RT_MENU: s = "menu"; break; 166038889Sjdp case RT_DIALOG: s = "dialog"; break; 166138889Sjdp case RT_STRING: s = "stringtable"; break; 166238889Sjdp case RT_FONTDIR: s = "fontdir"; break; 166338889Sjdp case RT_FONT: s = "font"; break; 166460484Sobrien case RT_ACCELERATOR: s = "accelerators"; break; 166538889Sjdp case RT_RCDATA: s = "rcdata"; break; 166638889Sjdp case RT_MESSAGETABLE: s = "messagetable"; break; 166738889Sjdp case RT_GROUP_CURSOR: s = "group cursor"; break; 166838889Sjdp case RT_GROUP_ICON: s = "group icon"; break; 166938889Sjdp case RT_VERSION: s = "version"; break; 167038889Sjdp case RT_DLGINCLUDE: s = "dlginclude"; break; 167138889Sjdp case RT_PLUGPLAY: s = "plugplay"; break; 167238889Sjdp case RT_VXD: s = "vxd"; break; 167338889Sjdp case RT_ANICURSOR: s = "anicursor"; break; 167438889Sjdp case RT_ANIICON: s = "aniicon"; break; 167538889Sjdp default: s = NULL; break; 167638889Sjdp } 167738889Sjdp 167838889Sjdp if (s != NULL) 167938889Sjdp fprintf (e, "%s", s); 168038889Sjdp else 168138889Sjdp res_id_print (e, re->id, 1); 168238889Sjdp } 168338889Sjdp fprintf (e, "\n"); 168438889Sjdp break; 168538889Sjdp 168638889Sjdp case 2: 168738889Sjdp fprintf (e, "// Name: "); 168838889Sjdp res_id_print (e, re->id, 1); 168938889Sjdp fprintf (e, "\n"); 169038889Sjdp break; 169138889Sjdp 169238889Sjdp case 3: 169338889Sjdp fprintf (e, "// Language: "); 169438889Sjdp res_id_print (e, re->id, 1); 169538889Sjdp fprintf (e, "\n"); 169638889Sjdp break; 169738889Sjdp 169838889Sjdp default: 169938889Sjdp fprintf (e, "// Level %d: ", level); 170038889Sjdp res_id_print (e, re->id, 1); 170138889Sjdp fprintf (e, "\n"); 1702104834Sobrien } 170338889Sjdp 170438889Sjdp write_rc_directory (e, re->u.dir, type, name, language, level + 1); 170538889Sjdp} 170638889Sjdp 170738889Sjdp/* Write out a single resource. E is the file to write to. TYPE is a 170838889Sjdp pointer to the type of the resource. NAME is a pointer to the name 170938889Sjdp of the resource; it will be NULL if there is a level mismatch. RES 171038889Sjdp is the resource data. LANGUAGE is a pointer to the current 171138889Sjdp language. */ 171238889Sjdp 171338889Sjdpstatic void 171438889Sjdpwrite_rc_resource (e, type, name, res, language) 171538889Sjdp FILE *e; 171638889Sjdp const struct res_id *type; 171738889Sjdp const struct res_id *name; 171838889Sjdp const struct res_resource *res; 171938889Sjdp int *language; 172038889Sjdp{ 172138889Sjdp const char *s; 172238889Sjdp int rt; 172338889Sjdp int menuex = 0; 172438889Sjdp 172538889Sjdp fprintf (e, "\n"); 172638889Sjdp 172738889Sjdp switch (res->type) 172838889Sjdp { 172938889Sjdp default: 173038889Sjdp abort (); 173138889Sjdp 173238889Sjdp case RES_TYPE_ACCELERATOR: 173338889Sjdp s = "ACCELERATOR"; 173460484Sobrien rt = RT_ACCELERATOR; 173538889Sjdp break; 173638889Sjdp 173738889Sjdp case RES_TYPE_BITMAP: 173838889Sjdp s = "BITMAP"; 173938889Sjdp rt = RT_BITMAP; 174038889Sjdp break; 174138889Sjdp 174238889Sjdp case RES_TYPE_CURSOR: 174338889Sjdp s = "CURSOR"; 174438889Sjdp rt = RT_CURSOR; 174538889Sjdp break; 174638889Sjdp 174738889Sjdp case RES_TYPE_GROUP_CURSOR: 174838889Sjdp s = "GROUP_CURSOR"; 174938889Sjdp rt = RT_GROUP_CURSOR; 175038889Sjdp break; 175138889Sjdp 175238889Sjdp case RES_TYPE_DIALOG: 175338889Sjdp if (extended_dialog (res->u.dialog)) 175438889Sjdp s = "DIALOGEX"; 175538889Sjdp else 175638889Sjdp s = "DIALOG"; 175738889Sjdp rt = RT_DIALOG; 175838889Sjdp break; 175938889Sjdp 176038889Sjdp case RES_TYPE_FONT: 176138889Sjdp s = "FONT"; 176238889Sjdp rt = RT_FONT; 176338889Sjdp break; 176438889Sjdp 176538889Sjdp case RES_TYPE_FONTDIR: 176638889Sjdp s = "FONTDIR"; 176738889Sjdp rt = RT_FONTDIR; 176838889Sjdp break; 176938889Sjdp 177038889Sjdp case RES_TYPE_ICON: 177138889Sjdp s = "ICON"; 177238889Sjdp rt = RT_ICON; 177338889Sjdp break; 177438889Sjdp 177538889Sjdp case RES_TYPE_GROUP_ICON: 177638889Sjdp s = "GROUP_ICON"; 177738889Sjdp rt = RT_GROUP_ICON; 177838889Sjdp break; 177938889Sjdp 178038889Sjdp case RES_TYPE_MENU: 178138889Sjdp if (extended_menu (res->u.menu)) 178238889Sjdp { 178338889Sjdp s = "MENUEX"; 178438889Sjdp menuex = 1; 178538889Sjdp } 178638889Sjdp else 178738889Sjdp { 178838889Sjdp s = "MENU"; 178938889Sjdp menuex = 0; 179038889Sjdp } 179138889Sjdp rt = RT_MENU; 179238889Sjdp break; 179338889Sjdp 179438889Sjdp case RES_TYPE_MESSAGETABLE: 179538889Sjdp s = "MESSAGETABLE"; 179638889Sjdp rt = RT_MESSAGETABLE; 179738889Sjdp break; 179838889Sjdp 179938889Sjdp case RES_TYPE_RCDATA: 180038889Sjdp s = "RCDATA"; 180138889Sjdp rt = RT_RCDATA; 180238889Sjdp break; 180338889Sjdp 180438889Sjdp case RES_TYPE_STRINGTABLE: 180538889Sjdp s = "STRINGTABLE"; 180638889Sjdp rt = RT_STRING; 180738889Sjdp break; 180838889Sjdp 180938889Sjdp case RES_TYPE_USERDATA: 181038889Sjdp s = NULL; 181138889Sjdp rt = 0; 181238889Sjdp break; 181338889Sjdp 181438889Sjdp case RES_TYPE_VERSIONINFO: 181538889Sjdp s = "VERSIONINFO"; 181638889Sjdp rt = RT_VERSION; 181738889Sjdp break; 181838889Sjdp } 181938889Sjdp 182038889Sjdp if (rt != 0 182138889Sjdp && type != NULL 182260484Sobrien && (type->named || type->u.id != (unsigned long) rt)) 182338889Sjdp { 182438889Sjdp fprintf (e, "// Unexpected resource type mismatch: "); 182538889Sjdp res_id_print (e, *type, 1); 182638889Sjdp fprintf (e, " != %d", rt); 182738889Sjdp } 182838889Sjdp 182938889Sjdp if (res->coff_info.codepage != 0) 183038889Sjdp fprintf (e, "// Code page: %lu\n", res->coff_info.codepage); 183138889Sjdp if (res->coff_info.reserved != 0) 183238889Sjdp fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved); 183338889Sjdp 183438889Sjdp if (name != NULL) 183538889Sjdp res_id_print (e, *name, 0); 183638889Sjdp else 183738889Sjdp fprintf (e, "??Unknown-Name??"); 183838889Sjdp 183938889Sjdp fprintf (e, " "); 184038889Sjdp if (s != NULL) 184138889Sjdp fprintf (e, "%s", s); 184238889Sjdp else if (type != NULL) 184338889Sjdp res_id_print (e, *type, 0); 184438889Sjdp else 184538889Sjdp fprintf (e, "??Unknown-Type??"); 184638889Sjdp 184738889Sjdp if (res->res_info.memflags != 0) 184838889Sjdp { 184938889Sjdp if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0) 185038889Sjdp fprintf (e, " MOVEABLE"); 185138889Sjdp if ((res->res_info.memflags & MEMFLAG_PURE) != 0) 185238889Sjdp fprintf (e, " PURE"); 185338889Sjdp if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0) 185438889Sjdp fprintf (e, " PRELOAD"); 185538889Sjdp if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0) 185638889Sjdp fprintf (e, " DISCARDABLE"); 185738889Sjdp } 185838889Sjdp 185938889Sjdp if (res->type == RES_TYPE_DIALOG) 186038889Sjdp { 186138889Sjdp fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y, 186238889Sjdp res->u.dialog->width, res->u.dialog->height); 186338889Sjdp if (res->u.dialog->ex != NULL 186438889Sjdp && res->u.dialog->ex->help != 0) 186538889Sjdp fprintf (e, ", %lu", res->u.dialog->ex->help); 186638889Sjdp } 186738889Sjdp 186838889Sjdp fprintf (e, "\n"); 186938889Sjdp 187038889Sjdp if ((res->res_info.language != 0 && res->res_info.language != *language) 187138889Sjdp || res->res_info.characteristics != 0 187238889Sjdp || res->res_info.version != 0) 187338889Sjdp { 187438889Sjdp int modifiers; 187538889Sjdp 187638889Sjdp switch (res->type) 187738889Sjdp { 187838889Sjdp case RES_TYPE_ACCELERATOR: 187938889Sjdp case RES_TYPE_DIALOG: 188038889Sjdp case RES_TYPE_MENU: 188138889Sjdp case RES_TYPE_RCDATA: 188238889Sjdp case RES_TYPE_STRINGTABLE: 188338889Sjdp modifiers = 1; 188438889Sjdp break; 188538889Sjdp 188638889Sjdp default: 188738889Sjdp modifiers = 0; 188838889Sjdp break; 188938889Sjdp } 189038889Sjdp 189138889Sjdp if (res->res_info.language != 0 && res->res_info.language != *language) 189238889Sjdp fprintf (e, "%sLANGUAGE %d, %d\n", 189338889Sjdp modifiers ? "// " : "", 189489857Sobrien res->res_info.language & ((1<<SUBLANG_SHIFT)-1), 189589857Sobrien (res->res_info.language >> SUBLANG_SHIFT) & 0xff); 189638889Sjdp if (res->res_info.characteristics != 0) 189738889Sjdp fprintf (e, "%sCHARACTERISTICS %lu\n", 189838889Sjdp modifiers ? "// " : "", 189938889Sjdp res->res_info.characteristics); 190038889Sjdp if (res->res_info.version != 0) 190138889Sjdp fprintf (e, "%sVERSION %lu\n", 190238889Sjdp modifiers ? "// " : "", 190338889Sjdp res->res_info.version); 190438889Sjdp } 190538889Sjdp 190638889Sjdp switch (res->type) 190738889Sjdp { 190838889Sjdp default: 190938889Sjdp abort (); 191038889Sjdp 191138889Sjdp case RES_TYPE_ACCELERATOR: 191238889Sjdp write_rc_accelerators (e, res->u.acc); 191338889Sjdp break; 191438889Sjdp 191538889Sjdp case RES_TYPE_CURSOR: 191638889Sjdp write_rc_cursor (e, res->u.cursor); 191738889Sjdp break; 191838889Sjdp 191938889Sjdp case RES_TYPE_GROUP_CURSOR: 192038889Sjdp write_rc_group_cursor (e, res->u.group_cursor); 192138889Sjdp break; 192238889Sjdp 192338889Sjdp case RES_TYPE_DIALOG: 192438889Sjdp write_rc_dialog (e, res->u.dialog); 192538889Sjdp break; 192638889Sjdp 192738889Sjdp case RES_TYPE_FONTDIR: 192838889Sjdp write_rc_fontdir (e, res->u.fontdir); 192938889Sjdp break; 193038889Sjdp 193138889Sjdp case RES_TYPE_GROUP_ICON: 193238889Sjdp write_rc_group_icon (e, res->u.group_icon); 193338889Sjdp break; 193438889Sjdp 193538889Sjdp case RES_TYPE_MENU: 193638889Sjdp write_rc_menu (e, res->u.menu, menuex); 193738889Sjdp break; 193838889Sjdp 193938889Sjdp case RES_TYPE_RCDATA: 194038889Sjdp write_rc_rcdata (e, res->u.rcdata, 0); 194138889Sjdp break; 194238889Sjdp 194338889Sjdp case RES_TYPE_STRINGTABLE: 194438889Sjdp write_rc_stringtable (e, name, res->u.stringtable); 194538889Sjdp break; 194638889Sjdp 194738889Sjdp case RES_TYPE_USERDATA: 194838889Sjdp write_rc_rcdata (e, res->u.userdata, 0); 194938889Sjdp break; 195038889Sjdp 195138889Sjdp case RES_TYPE_VERSIONINFO: 195238889Sjdp write_rc_versioninfo (e, res->u.versioninfo); 195338889Sjdp break; 195438889Sjdp 195538889Sjdp case RES_TYPE_BITMAP: 195638889Sjdp case RES_TYPE_FONT: 195738889Sjdp case RES_TYPE_ICON: 195838889Sjdp case RES_TYPE_MESSAGETABLE: 195938889Sjdp write_rc_filedata (e, res->u.data.length, res->u.data.data); 196038889Sjdp break; 196138889Sjdp } 196238889Sjdp} 196338889Sjdp 196438889Sjdp/* Write out accelerator information. */ 196538889Sjdp 196638889Sjdpstatic void 196738889Sjdpwrite_rc_accelerators (e, accelerators) 196838889Sjdp FILE *e; 196938889Sjdp const struct accelerator *accelerators; 197038889Sjdp{ 197138889Sjdp const struct accelerator *acc; 197238889Sjdp 197338889Sjdp fprintf (e, "BEGIN\n"); 197438889Sjdp for (acc = accelerators; acc != NULL; acc = acc->next) 197538889Sjdp { 197638889Sjdp int printable; 197738889Sjdp 197838889Sjdp fprintf (e, " "); 197938889Sjdp 198038889Sjdp if ((acc->key & 0x7f) == acc->key 198189857Sobrien && ISPRINT (acc->key) 198238889Sjdp && (acc->flags & ACC_VIRTKEY) == 0) 198338889Sjdp { 198438889Sjdp fprintf (e, "\"%c\"", acc->key); 198538889Sjdp printable = 1; 198638889Sjdp } 198738889Sjdp else 198838889Sjdp { 198938889Sjdp fprintf (e, "%d", acc->key); 199038889Sjdp printable = 0; 199138889Sjdp } 199238889Sjdp 199338889Sjdp fprintf (e, ", %d", acc->id); 199438889Sjdp 199538889Sjdp if (! printable) 199638889Sjdp { 199738889Sjdp if ((acc->flags & ACC_VIRTKEY) != 0) 199838889Sjdp fprintf (e, ", VIRTKEY"); 199938889Sjdp else 200038889Sjdp fprintf (e, ", ASCII"); 200138889Sjdp } 200238889Sjdp 200338889Sjdp if ((acc->flags & ACC_SHIFT) != 0) 200438889Sjdp fprintf (e, ", SHIFT"); 200538889Sjdp if ((acc->flags & ACC_CONTROL) != 0) 200638889Sjdp fprintf (e, ", CONTROL"); 200738889Sjdp if ((acc->flags & ACC_ALT) != 0) 200838889Sjdp fprintf (e, ", ALT"); 200938889Sjdp 201038889Sjdp fprintf (e, "\n"); 201138889Sjdp } 201238889Sjdp 201338889Sjdp fprintf (e, "END\n"); 201438889Sjdp} 201538889Sjdp 201638889Sjdp/* Write out cursor information. This would normally be in a separate 201738889Sjdp file, which the rc file would include. */ 201838889Sjdp 201938889Sjdpstatic void 202038889Sjdpwrite_rc_cursor (e, cursor) 202138889Sjdp FILE *e; 202238889Sjdp const struct cursor *cursor; 202338889Sjdp{ 202438889Sjdp fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot, 202538889Sjdp cursor->yhotspot); 202638889Sjdp write_rc_filedata (e, cursor->length, cursor->data); 202738889Sjdp} 202838889Sjdp 202938889Sjdp/* Write out group cursor data. This would normally be built from the 203038889Sjdp cursor data. */ 203138889Sjdp 203238889Sjdpstatic void 203338889Sjdpwrite_rc_group_cursor (e, group_cursor) 203438889Sjdp FILE *e; 203538889Sjdp const struct group_cursor *group_cursor; 203638889Sjdp{ 203738889Sjdp const struct group_cursor *gc; 203838889Sjdp 203938889Sjdp for (gc = group_cursor; gc != NULL; gc = gc->next) 204038889Sjdp { 204138889Sjdp fprintf (e, "// width: %d; height %d; planes %d; bits %d\n", 204238889Sjdp gc->width, gc->height, gc->planes, gc->bits); 204338889Sjdp fprintf (e, "// data bytes: %lu; index: %d\n", 204438889Sjdp gc->bytes, gc->index); 204538889Sjdp } 204638889Sjdp} 204738889Sjdp 204838889Sjdp/* Write dialog data. */ 204938889Sjdp 205038889Sjdpstatic void 205138889Sjdpwrite_rc_dialog (e, dialog) 205238889Sjdp FILE *e; 205338889Sjdp const struct dialog *dialog; 205438889Sjdp{ 205538889Sjdp const struct dialog_control *control; 205638889Sjdp 205799461Sobrien fprintf (e, "STYLE 0x%lx\n", dialog->style); 205899461Sobrien 205938889Sjdp if (dialog->exstyle != 0) 206038889Sjdp fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle); 206199461Sobrien 206238889Sjdp if ((dialog->class.named && dialog->class.u.n.length > 0) 206338889Sjdp || dialog->class.u.id != 0) 206438889Sjdp { 206538889Sjdp fprintf (e, "CLASS "); 206699461Sobrien res_id_print (e, dialog->class, 1); 206738889Sjdp fprintf (e, "\n"); 206838889Sjdp } 206999461Sobrien 207038889Sjdp if (dialog->caption != NULL) 207138889Sjdp { 207238889Sjdp fprintf (e, "CAPTION \""); 207338889Sjdp unicode_print (e, dialog->caption, -1); 207438889Sjdp fprintf (e, "\"\n"); 207538889Sjdp } 207699461Sobrien 207738889Sjdp if ((dialog->menu.named && dialog->menu.u.n.length > 0) 207838889Sjdp || dialog->menu.u.id != 0) 207938889Sjdp { 208038889Sjdp fprintf (e, "MENU "); 208138889Sjdp res_id_print (e, dialog->menu, 0); 208238889Sjdp fprintf (e, "\n"); 208338889Sjdp } 208499461Sobrien 208538889Sjdp if (dialog->font != NULL) 208638889Sjdp { 208738889Sjdp fprintf (e, "FONT %d, \"", dialog->pointsize); 208838889Sjdp unicode_print (e, dialog->font, -1); 208938889Sjdp fprintf (e, "\""); 209038889Sjdp if (dialog->ex != NULL 209199461Sobrien && (dialog->ex->weight != 0 209299461Sobrien || dialog->ex->italic != 0 209399461Sobrien || dialog->ex->charset != 1)) 209499461Sobrien fprintf (e, ", %d, %d, %d", 209599461Sobrien dialog->ex->weight, dialog->ex->italic, dialog->ex->charset); 209638889Sjdp fprintf (e, "\n"); 209738889Sjdp } 209838889Sjdp 209938889Sjdp fprintf (e, "BEGIN\n"); 210038889Sjdp 210138889Sjdp for (control = dialog->controls; control != NULL; control = control->next) 210238889Sjdp write_rc_dialog_control (e, control); 210338889Sjdp 210438889Sjdp fprintf (e, "END\n"); 210538889Sjdp} 210638889Sjdp 210738889Sjdp/* For each predefined control keyword, this table provides the class 210838889Sjdp and the style. */ 210938889Sjdp 211038889Sjdpstruct control_info 211138889Sjdp{ 211238889Sjdp const char *name; 211338889Sjdp unsigned short class; 211438889Sjdp unsigned long style; 211538889Sjdp}; 211638889Sjdp 211738889Sjdpstatic const struct control_info control_info[] = 211838889Sjdp{ 211938889Sjdp { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE }, 212038889Sjdp { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX }, 212138889Sjdp { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON }, 212238889Sjdp { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX }, 212338889Sjdp { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 }, 212438889Sjdp { "CTEXT", CTL_STATIC, SS_CENTER }, 212538889Sjdp { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON }, 212638889Sjdp { "EDITTEXT", CTL_EDIT, (unsigned long) -1 }, 212738889Sjdp { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX }, 212838889Sjdp { "ICON", CTL_STATIC, SS_ICON }, 212938889Sjdp { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 }, 213038889Sjdp { "LTEXT", CTL_STATIC, SS_LEFT }, 213138889Sjdp { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX }, 213238889Sjdp { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON }, 213338889Sjdp { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON }, 213438889Sjdp { "RTEXT", CTL_STATIC, SS_RIGHT }, 213538889Sjdp { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 }, 213638889Sjdp { "STATE3", CTL_BUTTON, BS_3STATE }, 213738889Sjdp /* It's important that USERBUTTON come after all the other button 213838889Sjdp types, so that it won't be matched too early. */ 213938889Sjdp { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 }, 214038889Sjdp { NULL, 0, 0 } 214138889Sjdp}; 214238889Sjdp 214338889Sjdp/* Write a dialog control. */ 214438889Sjdp 214538889Sjdpstatic void 214638889Sjdpwrite_rc_dialog_control (e, control) 214738889Sjdp FILE *e; 214838889Sjdp const struct dialog_control *control; 214938889Sjdp{ 215038889Sjdp const struct control_info *ci; 215138889Sjdp 215238889Sjdp fprintf (e, " "); 215338889Sjdp 215438889Sjdp if (control->class.named) 215538889Sjdp ci = NULL; 215638889Sjdp else 215738889Sjdp { 215838889Sjdp for (ci = control_info; ci->name != NULL; ++ci) 215938889Sjdp if (ci->class == control->class.u.id 216038889Sjdp && (ci->style == (unsigned long) -1 216138889Sjdp || ci->style == (control->style & 0xff))) 216238889Sjdp break; 216338889Sjdp } 216460484Sobrien if (ci == NULL) 216560484Sobrien fprintf (e, "CONTROL"); 216660484Sobrien else if (ci->name != NULL) 216738889Sjdp fprintf (e, "%s", ci->name); 216838889Sjdp else 216938889Sjdp fprintf (e, "CONTROL"); 2170104834Sobrien 217138889Sjdp if (control->text.named || control->text.u.id != 0) 217238889Sjdp { 217338889Sjdp fprintf (e, " "); 217438889Sjdp res_id_print (e, control->text, 1); 217538889Sjdp fprintf (e, ","); 217638889Sjdp } 217738889Sjdp 217838889Sjdp fprintf (e, " %d, ", control->id); 217938889Sjdp 218060484Sobrien if (ci == NULL) 218138889Sjdp { 218260484Sobrien if (control->class.named) 218360484Sobrien fprintf (e, "\""); 218438889Sjdp res_id_print (e, control->class, 0); 218560484Sobrien if (control->class.named) 218660484Sobrien fprintf (e, "\""); 218738889Sjdp fprintf (e, ", 0x%lx, ", control->style); 218838889Sjdp } 218938889Sjdp 219038889Sjdp fprintf (e, "%d, %d", control->x, control->y); 219138889Sjdp 219238889Sjdp if (control->style != SS_ICON 219338889Sjdp || control->exstyle != 0 219438889Sjdp || control->width != 0 219538889Sjdp || control->height != 0 219638889Sjdp || control->help != 0) 219738889Sjdp { 219838889Sjdp fprintf (e, ", %d, %d", control->width, control->height); 219938889Sjdp 220038889Sjdp /* FIXME: We don't need to print the style if it is the default. 220138889Sjdp More importantly, in certain cases we actually need to turn 220238889Sjdp off parts of the forced style, by using NOT. */ 220338889Sjdp fprintf (e, ", 0x%lx", control->style); 220438889Sjdp 220538889Sjdp if (control->exstyle != 0 || control->help != 0) 220638889Sjdp fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help); 220738889Sjdp } 220838889Sjdp 220938889Sjdp fprintf (e, "\n"); 221038889Sjdp 221138889Sjdp if (control->data != NULL) 221238889Sjdp write_rc_rcdata (e, control->data, 2); 221338889Sjdp} 221438889Sjdp 221538889Sjdp/* Write out font directory data. This would normally be built from 221638889Sjdp the font data. */ 221738889Sjdp 221838889Sjdpstatic void 221938889Sjdpwrite_rc_fontdir (e, fontdir) 222038889Sjdp FILE *e; 222138889Sjdp const struct fontdir *fontdir; 222238889Sjdp{ 222338889Sjdp const struct fontdir *fc; 222438889Sjdp 222538889Sjdp for (fc = fontdir; fc != NULL; fc = fc->next) 222638889Sjdp { 222738889Sjdp fprintf (e, "// Font index: %d\n", fc->index); 222838889Sjdp write_rc_filedata (e, fc->length, fc->data); 222938889Sjdp } 223038889Sjdp} 223138889Sjdp 223238889Sjdp/* Write out group icon data. This would normally be built from the 223338889Sjdp icon data. */ 223438889Sjdp 223538889Sjdpstatic void 223638889Sjdpwrite_rc_group_icon (e, group_icon) 223738889Sjdp FILE *e; 223838889Sjdp const struct group_icon *group_icon; 223938889Sjdp{ 224038889Sjdp const struct group_icon *gi; 224138889Sjdp 224238889Sjdp for (gi = group_icon; gi != NULL; gi = gi->next) 224338889Sjdp { 224438889Sjdp fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n", 224538889Sjdp gi->width, gi->height, gi->colors, gi->planes, gi->bits); 224638889Sjdp fprintf (e, "// data bytes: %lu; index: %d\n", 224738889Sjdp gi->bytes, gi->index); 224838889Sjdp } 224938889Sjdp} 225038889Sjdp 225138889Sjdp/* Write out a menu resource. */ 225238889Sjdp 225338889Sjdpstatic void 225438889Sjdpwrite_rc_menu (e, menu, menuex) 225538889Sjdp FILE *e; 225638889Sjdp const struct menu *menu; 225738889Sjdp int menuex; 225838889Sjdp{ 225938889Sjdp if (menu->help != 0) 226038889Sjdp fprintf (e, "// Help ID: %lu\n", menu->help); 226138889Sjdp write_rc_menuitems (e, menu->items, menuex, 0); 226238889Sjdp} 226338889Sjdp 226438889Sjdp/* Write out menuitems. */ 226538889Sjdp 226638889Sjdpstatic void 226738889Sjdpwrite_rc_menuitems (e, menuitems, menuex, ind) 226838889Sjdp FILE *e; 226938889Sjdp const struct menuitem *menuitems; 227038889Sjdp int menuex; 227138889Sjdp int ind; 227238889Sjdp{ 227338889Sjdp const struct menuitem *mi; 227438889Sjdp 227538889Sjdp indent (e, ind); 227638889Sjdp fprintf (e, "BEGIN\n"); 227738889Sjdp 227838889Sjdp for (mi = menuitems; mi != NULL; mi = mi->next) 227938889Sjdp { 228038889Sjdp indent (e, ind + 2); 228138889Sjdp 228238889Sjdp if (mi->popup == NULL) 228338889Sjdp fprintf (e, "MENUITEM"); 228438889Sjdp else 228538889Sjdp fprintf (e, "POPUP"); 228638889Sjdp 228738889Sjdp if (! menuex 228838889Sjdp && mi->popup == NULL 228938889Sjdp && mi->text == NULL 229038889Sjdp && mi->type == 0 229138889Sjdp && mi->id == 0) 229238889Sjdp { 229338889Sjdp fprintf (e, " SEPARATOR\n"); 229438889Sjdp continue; 229538889Sjdp } 229638889Sjdp 229738889Sjdp if (mi->text == NULL) 229838889Sjdp fprintf (e, " \"\""); 229938889Sjdp else 230038889Sjdp { 230138889Sjdp fprintf (e, " \""); 230238889Sjdp unicode_print (e, mi->text, -1); 230338889Sjdp fprintf (e, "\""); 230438889Sjdp } 230538889Sjdp 230638889Sjdp if (! menuex) 230738889Sjdp { 230838889Sjdp if (mi->popup == NULL) 230938889Sjdp fprintf (e, ", %d", mi->id); 231038889Sjdp 231138889Sjdp if ((mi->type & MENUITEM_CHECKED) != 0) 231238889Sjdp fprintf (e, ", CHECKED"); 231338889Sjdp if ((mi->type & MENUITEM_GRAYED) != 0) 231438889Sjdp fprintf (e, ", GRAYED"); 231538889Sjdp if ((mi->type & MENUITEM_HELP) != 0) 231638889Sjdp fprintf (e, ", HELP"); 231738889Sjdp if ((mi->type & MENUITEM_INACTIVE) != 0) 231838889Sjdp fprintf (e, ", INACTIVE"); 231938889Sjdp if ((mi->type & MENUITEM_MENUBARBREAK) != 0) 232038889Sjdp fprintf (e, ", MENUBARBREAK"); 232138889Sjdp if ((mi->type & MENUITEM_MENUBREAK) != 0) 232238889Sjdp fprintf (e, ", MENUBREAK"); 232338889Sjdp } 232438889Sjdp else 232538889Sjdp { 232638889Sjdp if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0) 232738889Sjdp { 232838889Sjdp fprintf (e, ", %d", mi->id); 232938889Sjdp if (mi->type != 0 || mi->state != 0 || mi->help != 0) 233038889Sjdp { 233138889Sjdp fprintf (e, ", %lu", mi->type); 233238889Sjdp if (mi->state != 0 || mi->help != 0) 233338889Sjdp { 233438889Sjdp fprintf (e, ", %lu", mi->state); 233538889Sjdp if (mi->help != 0) 233638889Sjdp fprintf (e, ", %lu", mi->help); 233738889Sjdp } 233838889Sjdp } 233938889Sjdp } 234038889Sjdp } 234138889Sjdp 234238889Sjdp fprintf (e, "\n"); 234338889Sjdp 234438889Sjdp if (mi->popup != NULL) 234538889Sjdp write_rc_menuitems (e, mi->popup, menuex, ind + 2); 234638889Sjdp } 234738889Sjdp 234838889Sjdp indent (e, ind); 234938889Sjdp fprintf (e, "END\n"); 235038889Sjdp} 235138889Sjdp 235238889Sjdp/* Write out an rcdata resource. This is also used for other types of 235338889Sjdp resources that need to print arbitrary data. */ 235438889Sjdp 235538889Sjdpstatic void 235638889Sjdpwrite_rc_rcdata (e, rcdata, ind) 235738889Sjdp FILE *e; 235838889Sjdp const struct rcdata_item *rcdata; 235938889Sjdp int ind; 236038889Sjdp{ 236138889Sjdp const struct rcdata_item *ri; 236238889Sjdp 236338889Sjdp indent (e, ind); 236438889Sjdp fprintf (e, "BEGIN\n"); 236538889Sjdp 236638889Sjdp for (ri = rcdata; ri != NULL; ri = ri->next) 236738889Sjdp { 236838889Sjdp if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0) 236938889Sjdp continue; 237038889Sjdp 237138889Sjdp indent (e, ind + 2); 237238889Sjdp 237338889Sjdp switch (ri->type) 237438889Sjdp { 237538889Sjdp default: 237638889Sjdp abort (); 237738889Sjdp 237838889Sjdp case RCDATA_WORD: 237938889Sjdp fprintf (e, "%d", ri->u.word); 238038889Sjdp break; 238138889Sjdp 238238889Sjdp case RCDATA_DWORD: 238338889Sjdp fprintf (e, "%luL", ri->u.dword); 238438889Sjdp break; 238538889Sjdp 238638889Sjdp case RCDATA_STRING: 238738889Sjdp { 238838889Sjdp const char *s; 238938889Sjdp unsigned long i; 239038889Sjdp 239138889Sjdp fprintf (e, "\""); 239238889Sjdp s = ri->u.string.s; 239338889Sjdp for (i = 0; i < ri->u.string.length; i++) 239438889Sjdp { 239589857Sobrien if (ISPRINT (*s)) 239638889Sjdp putc (*s, e); 239738889Sjdp else 239838889Sjdp fprintf (e, "\\%03o", *s); 239938889Sjdp } 240038889Sjdp fprintf (e, "\""); 240138889Sjdp break; 240238889Sjdp } 240338889Sjdp 240438889Sjdp case RCDATA_WSTRING: 240538889Sjdp fprintf (e, "L\""); 240638889Sjdp unicode_print (e, ri->u.wstring.w, ri->u.wstring.length); 240738889Sjdp fprintf (e, "\""); 240838889Sjdp break; 240938889Sjdp 241038889Sjdp case RCDATA_BUFFER: 241138889Sjdp { 241238889Sjdp unsigned long i; 241338889Sjdp int first; 241438889Sjdp 241538889Sjdp /* Assume little endian data. */ 241638889Sjdp 241738889Sjdp first = 1; 241838889Sjdp for (i = 0; i + 3 < ri->u.buffer.length; i += 4) 241938889Sjdp { 242038889Sjdp unsigned long l; 242160484Sobrien int j; 242238889Sjdp 242360484Sobrien if (! first) 242460484Sobrien indent (e, ind + 2); 242538889Sjdp l = ((((((ri->u.buffer.data[i + 3] << 8) 242638889Sjdp | ri->u.buffer.data[i + 2]) << 8) 242738889Sjdp | ri->u.buffer.data[i + 1]) << 8) 242838889Sjdp | ri->u.buffer.data[i]); 242960484Sobrien fprintf (e, "%luL", l); 243060484Sobrien if (i + 4 < ri->u.buffer.length || ri->next != NULL) 243160484Sobrien fprintf (e, ","); 243260484Sobrien for (j = 0; j < 4; ++j) 243389857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j]) 243460484Sobrien && ri->u.buffer.data[i + j] != 0) 243560484Sobrien break; 243660484Sobrien if (j >= 4) 243738889Sjdp { 243860484Sobrien fprintf (e, "\t// "); 243960484Sobrien for (j = 0; j < 4; ++j) 244060484Sobrien { 244189857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j])) 244260484Sobrien fprintf (e, "\\%03o", ri->u.buffer.data[i + j]); 244360484Sobrien else 244460484Sobrien { 244560484Sobrien if (ri->u.buffer.data[i + j] == '\\') 244660484Sobrien fprintf (e, "\\"); 244760484Sobrien fprintf (e, "%c", ri->u.buffer.data[i + j]); 244860484Sobrien } 244960484Sobrien } 245038889Sjdp } 245160484Sobrien fprintf (e, "\n"); 245260484Sobrien first = 0; 245338889Sjdp } 245438889Sjdp 245538889Sjdp if (i + 1 < ri->u.buffer.length) 245638889Sjdp { 245760484Sobrien int s; 245860484Sobrien int j; 245938889Sjdp 246060484Sobrien if (! first) 246160484Sobrien indent (e, ind + 2); 246260484Sobrien s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i]; 246360484Sobrien fprintf (e, "%d", s); 246460484Sobrien if (i + 2 < ri->u.buffer.length || ri->next != NULL) 246560484Sobrien fprintf (e, ","); 246660484Sobrien for (j = 0; j < 2; ++j) 246789857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j]) 246860484Sobrien && ri->u.buffer.data[i + j] != 0) 246960484Sobrien break; 247060484Sobrien if (j >= 2) 247138889Sjdp { 247260484Sobrien fprintf (e, "\t// "); 247360484Sobrien for (j = 0; j < 2; ++j) 247460484Sobrien { 247589857Sobrien if (! ISPRINT (ri->u.buffer.data[i + j])) 247660484Sobrien fprintf (e, "\\%03o", ri->u.buffer.data[i + j]); 247760484Sobrien else 247860484Sobrien { 247960484Sobrien if (ri->u.buffer.data[i + j] == '\\') 248060484Sobrien fprintf (e, "\\"); 248160484Sobrien fprintf (e, "%c", ri->u.buffer.data[i + j]); 248260484Sobrien } 248360484Sobrien } 248438889Sjdp } 248560484Sobrien fprintf (e, "\n"); 248638889Sjdp i += 2; 248760484Sobrien first = 0; 248838889Sjdp } 248938889Sjdp 249038889Sjdp if (i < ri->u.buffer.length) 249138889Sjdp { 249260484Sobrien if (! first) 249360484Sobrien indent (e, ind + 2); 249438889Sjdp if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i] 249589857Sobrien && ISPRINT (ri->u.buffer.data[i])) 249638889Sjdp fprintf (e, "\"%c\"", ri->u.buffer.data[i]); 249738889Sjdp else 249860484Sobrien fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]); 249960484Sobrien if (ri->next != NULL) 250060484Sobrien fprintf (e, ","); 250160484Sobrien fprintf (e, "\n"); 250260484Sobrien first = 0; 250338889Sjdp } 250438889Sjdp 250538889Sjdp break; 250638889Sjdp } 250738889Sjdp } 250838889Sjdp 250960484Sobrien if (ri->type != RCDATA_BUFFER) 251060484Sobrien { 251160484Sobrien if (ri->next != NULL) 251260484Sobrien fprintf (e, ","); 251360484Sobrien fprintf (e, "\n"); 251460484Sobrien } 251538889Sjdp } 251638889Sjdp 251738889Sjdp indent (e, ind); 251838889Sjdp fprintf (e, "END\n"); 251938889Sjdp} 252038889Sjdp 252138889Sjdp/* Write out a stringtable resource. */ 252238889Sjdp 252338889Sjdpstatic void 252438889Sjdpwrite_rc_stringtable (e, name, stringtable) 252538889Sjdp FILE *e; 252638889Sjdp const struct res_id *name; 252738889Sjdp const struct stringtable *stringtable; 252838889Sjdp{ 252938889Sjdp unsigned long offset; 253038889Sjdp int i; 253138889Sjdp 253238889Sjdp if (name != NULL && ! name->named) 253338889Sjdp offset = (name->u.id - 1) << 4; 253438889Sjdp else 253538889Sjdp { 253638889Sjdp fprintf (e, "// %s string table name\n", 253738889Sjdp name == NULL ? "Missing" : "Invalid"); 253838889Sjdp offset = 0; 253938889Sjdp } 254038889Sjdp 254138889Sjdp fprintf (e, "BEGIN\n"); 254238889Sjdp 254338889Sjdp for (i = 0; i < 16; i++) 254438889Sjdp { 254538889Sjdp if (stringtable->strings[i].length != 0) 254638889Sjdp { 254738889Sjdp fprintf (e, " %lu, \"", offset + i); 254838889Sjdp unicode_print (e, stringtable->strings[i].string, 254938889Sjdp stringtable->strings[i].length); 255038889Sjdp fprintf (e, "\"\n"); 255138889Sjdp } 255238889Sjdp } 255338889Sjdp 255438889Sjdp fprintf (e, "END\n"); 255538889Sjdp} 255638889Sjdp 255738889Sjdp/* Write out a versioninfo resource. */ 255838889Sjdp 255938889Sjdpstatic void 256038889Sjdpwrite_rc_versioninfo (e, versioninfo) 256138889Sjdp FILE *e; 256238889Sjdp const struct versioninfo *versioninfo; 256338889Sjdp{ 256438889Sjdp const struct fixed_versioninfo *f; 256538889Sjdp const struct ver_info *vi; 256638889Sjdp 256738889Sjdp f = versioninfo->fixed; 256838889Sjdp if (f->file_version_ms != 0 || f->file_version_ls != 0) 256938889Sjdp fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n", 257038889Sjdp (f->file_version_ms >> 16) & 0xffff, 257138889Sjdp f->file_version_ms & 0xffff, 257238889Sjdp (f->file_version_ls >> 16) & 0xffff, 257338889Sjdp f->file_version_ls & 0xffff); 257438889Sjdp if (f->product_version_ms != 0 || f->product_version_ls != 0) 257538889Sjdp fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n", 257638889Sjdp (f->product_version_ms >> 16) & 0xffff, 257738889Sjdp f->product_version_ms & 0xffff, 257838889Sjdp (f->product_version_ls >> 16) & 0xffff, 257938889Sjdp f->product_version_ls & 0xffff); 258038889Sjdp if (f->file_flags_mask != 0) 258138889Sjdp fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask); 258238889Sjdp if (f->file_flags != 0) 258338889Sjdp fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags); 258438889Sjdp if (f->file_os != 0) 258538889Sjdp fprintf (e, " FILEOS 0x%lx\n", f->file_os); 258638889Sjdp if (f->file_type != 0) 258738889Sjdp fprintf (e, " FILETYPE 0x%lx\n", f->file_type); 258838889Sjdp if (f->file_subtype != 0) 258938889Sjdp fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype); 259038889Sjdp if (f->file_date_ms != 0 || f->file_date_ls != 0) 259138889Sjdp fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls); 259238889Sjdp 259338889Sjdp fprintf (e, "BEGIN\n"); 259438889Sjdp 259538889Sjdp for (vi = versioninfo->var; vi != NULL; vi = vi->next) 259638889Sjdp { 259738889Sjdp switch (vi->type) 259838889Sjdp { 259938889Sjdp case VERINFO_STRING: 260038889Sjdp { 260138889Sjdp const struct ver_stringinfo *vs; 260238889Sjdp 260338889Sjdp fprintf (e, " BLOCK \"StringFileInfo\"\n"); 260438889Sjdp fprintf (e, " BEGIN\n"); 260538889Sjdp fprintf (e, " BLOCK \""); 260638889Sjdp unicode_print (e, vi->u.string.language, -1); 260738889Sjdp fprintf (e, "\"\n"); 260838889Sjdp fprintf (e, " BEGIN\n"); 260938889Sjdp 261038889Sjdp for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) 261138889Sjdp { 261238889Sjdp fprintf (e, " VALUE \""); 261338889Sjdp unicode_print (e, vs->key, -1); 261438889Sjdp fprintf (e, "\", \""); 261538889Sjdp unicode_print (e, vs->value, -1); 261638889Sjdp fprintf (e, "\"\n"); 261738889Sjdp } 261838889Sjdp 261938889Sjdp fprintf (e, " END\n"); 262038889Sjdp fprintf (e, " END\n"); 262138889Sjdp break; 262238889Sjdp } 262338889Sjdp 262438889Sjdp case VERINFO_VAR: 262538889Sjdp { 262638889Sjdp const struct ver_varinfo *vv; 262738889Sjdp 262838889Sjdp fprintf (e, " BLOCK \"VarFileInfo\"\n"); 262938889Sjdp fprintf (e, " BEGIN\n"); 263038889Sjdp fprintf (e, " VALUE \""); 263138889Sjdp unicode_print (e, vi->u.var.key, -1); 263238889Sjdp fprintf (e, "\""); 263338889Sjdp 263438889Sjdp for (vv = vi->u.var.var; vv != NULL; vv = vv->next) 263538889Sjdp fprintf (e, ", 0x%x, %d", (unsigned int) vv->language, 263638889Sjdp vv->charset); 263738889Sjdp 263838889Sjdp fprintf (e, "\n END\n"); 263938889Sjdp 264038889Sjdp break; 264138889Sjdp } 264238889Sjdp } 264338889Sjdp } 264438889Sjdp 264538889Sjdp fprintf (e, "END\n"); 264638889Sjdp} 264738889Sjdp 264838889Sjdp/* Write out data which would normally be read from a file. */ 264938889Sjdp 265038889Sjdpstatic void 265138889Sjdpwrite_rc_filedata (e, length, data) 265238889Sjdp FILE *e; 265338889Sjdp unsigned long length; 265438889Sjdp const unsigned char *data; 265538889Sjdp{ 265638889Sjdp unsigned long i; 265738889Sjdp 265838889Sjdp for (i = 0; i + 15 < length; i += 16) 265938889Sjdp { 266038889Sjdp fprintf (e, "// %4lx: ", i); 266138889Sjdp fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ", 266238889Sjdp data[i + 0], data[i + 1], data[i + 2], data[i + 3], 266338889Sjdp data[i + 4], data[i + 5], data[i + 6], data[i + 7]); 266438889Sjdp fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n", 266538889Sjdp data[i + 8], data[i + 9], data[i + 10], data[i + 11], 266638889Sjdp data[i + 12], data[i + 13], data[i + 14], data[i + 15]); 266738889Sjdp } 266838889Sjdp 266938889Sjdp if (i < length) 267038889Sjdp { 267138889Sjdp fprintf (e, "// %4lx:", i); 267238889Sjdp while (i < length) 267338889Sjdp { 267438889Sjdp fprintf (e, " %02x", data[i]); 267538889Sjdp ++i; 267638889Sjdp } 267738889Sjdp fprintf (e, "\n"); 267838889Sjdp } 267938889Sjdp} 2680