138889Sjdp/* resrc.c -- read and write Windows rc files. 2218822Sdim Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007 3218822Sdim Free Software Foundation, Inc. 438889Sjdp Written by Ian Lance Taylor, Cygnus Support. 5218822Sdim Rewritten by Kai Tietz, Onevision. 638889Sjdp 738889Sjdp This file is part of GNU Binutils. 838889Sjdp 938889Sjdp This program is free software; you can redistribute it and/or modify 1038889Sjdp it under the terms of the GNU General Public License as published by 1138889Sjdp the Free Software Foundation; either version 2 of the License, or 1238889Sjdp (at your option) any later version. 1338889Sjdp 1438889Sjdp This program is distributed in the hope that it will be useful, 1538889Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1638889Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1738889Sjdp GNU General Public License for more details. 1838889Sjdp 1938889Sjdp You should have received a copy of the GNU General Public License 2038889Sjdp along with this program; if not, write to the Free Software 21218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 22218822Sdim 02110-1301, USA. */ 2338889Sjdp 2438889Sjdp/* This file contains functions that read and write Windows rc files. 2538889Sjdp These are text files that represent resources. */ 2638889Sjdp 27218822Sdim#include "sysdep.h" 2838889Sjdp#include "bfd.h" 2938889Sjdp#include "bucomm.h" 3038889Sjdp#include "libiberty.h" 3189857Sobrien#include "safe-ctype.h" 3238889Sjdp#include "windres.h" 3338889Sjdp 3438889Sjdp#include <assert.h> 3560484Sobrien#include <errno.h> 3638889Sjdp#include <sys/stat.h> 3760484Sobrien#ifdef HAVE_UNISTD_H 3860484Sobrien#include <unistd.h> 3960484Sobrien#endif 4038889Sjdp 4160484Sobrien#ifdef HAVE_SYS_WAIT_H 4260484Sobrien#include <sys/wait.h> 4360484Sobrien#else /* ! HAVE_SYS_WAIT_H */ 4460484Sobrien#if ! defined (_WIN32) || defined (__CYGWIN__) 4560484Sobrien#ifndef WIFEXITED 4660484Sobrien#define WIFEXITED(w) (((w)&0377) == 0) 4760484Sobrien#endif 4860484Sobrien#ifndef WIFSIGNALED 4960484Sobrien#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) 5060484Sobrien#endif 5160484Sobrien#ifndef WTERMSIG 5260484Sobrien#define WTERMSIG(w) ((w) & 0177) 5360484Sobrien#endif 5460484Sobrien#ifndef WEXITSTATUS 5560484Sobrien#define WEXITSTATUS(w) (((w) >> 8) & 0377) 5660484Sobrien#endif 5760484Sobrien#else /* defined (_WIN32) && ! defined (__CYGWIN__) */ 5860484Sobrien#ifndef WIFEXITED 5960484Sobrien#define WIFEXITED(w) (((w) & 0xff) == 0) 6060484Sobrien#endif 6160484Sobrien#ifndef WIFSIGNALED 6260484Sobrien#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) 6360484Sobrien#endif 6460484Sobrien#ifndef WTERMSIG 6560484Sobrien#define WTERMSIG(w) ((w) & 0x7f) 6660484Sobrien#endif 6760484Sobrien#ifndef WEXITSTATUS 6860484Sobrien#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) 6960484Sobrien#endif 7060484Sobrien#endif /* defined (_WIN32) && ! defined (__CYGWIN__) */ 7160484Sobrien#endif /* ! HAVE_SYS_WAIT_H */ 7260484Sobrien 7360484Sobrien#ifndef STDOUT_FILENO 7460484Sobrien#define STDOUT_FILENO 1 7560484Sobrien#endif 76104834Sobrien 7760484Sobrien#if defined (_WIN32) && ! defined (__CYGWIN__) 7838889Sjdp#define popen _popen 7938889Sjdp#define pclose _pclose 8038889Sjdp#endif 8138889Sjdp 8238889Sjdp/* The default preprocessor. */ 8338889Sjdp 8477298Sobrien#define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED" 8538889Sjdp 8638889Sjdp/* We read the directory entries in a cursor or icon file into 8738889Sjdp instances of this structure. */ 8838889Sjdp 8938889Sjdpstruct icondir 9038889Sjdp{ 9138889Sjdp /* Width of image. */ 92218822Sdim bfd_byte width; 9338889Sjdp /* Height of image. */ 94218822Sdim bfd_byte height; 9538889Sjdp /* Number of colors in image. */ 96218822Sdim bfd_byte colorcount; 9738889Sjdp union 9838889Sjdp { 9938889Sjdp struct 10038889Sjdp { 10138889Sjdp /* Color planes. */ 10238889Sjdp unsigned short planes; 10338889Sjdp /* Bits per pixel. */ 10438889Sjdp unsigned short bits; 10538889Sjdp } icon; 10638889Sjdp struct 10738889Sjdp { 10838889Sjdp /* X coordinate of hotspot. */ 10938889Sjdp unsigned short xhotspot; 11038889Sjdp /* Y coordinate of hotspot. */ 11138889Sjdp unsigned short yhotspot; 11238889Sjdp } cursor; 11338889Sjdp } u; 11438889Sjdp /* Bytes in image. */ 11538889Sjdp unsigned long bytes; 11638889Sjdp /* File offset of image. */ 11738889Sjdp unsigned long offset; 11838889Sjdp}; 11938889Sjdp 12038889Sjdp/* The name of the rc file we are reading. */ 12138889Sjdp 12238889Sjdpchar *rc_filename; 12338889Sjdp 12438889Sjdp/* The line number in the rc file. */ 12538889Sjdp 12638889Sjdpint rc_lineno; 12738889Sjdp 12838889Sjdp/* The pipe we are reading from, so that we can close it if we exit. */ 12938889Sjdp 130218822SdimFILE *cpp_pipe; 13138889Sjdp 13260484Sobrien/* The temporary file used if we're not using popen, so we can delete it 13360484Sobrien if we exit. */ 13460484Sobrien 13560484Sobrienstatic char *cpp_temp_file; 13660484Sobrien 13799461Sobrien/* Input stream is either a file or a pipe. */ 13860484Sobrien 13960484Sobrienstatic enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type; 14060484Sobrien 14138889Sjdp/* As we read the rc file, we attach information to this structure. */ 14238889Sjdp 143218822Sdimstatic rc_res_directory *resources; 14438889Sjdp 14538889Sjdp/* The number of cursor resources we have written out. */ 14638889Sjdp 14738889Sjdpstatic int cursors; 14838889Sjdp 14938889Sjdp/* The number of font resources we have written out. */ 15038889Sjdp 15138889Sjdpstatic int fonts; 15238889Sjdp 15338889Sjdp/* Font directory information. */ 15438889Sjdp 155218822Sdimrc_fontdir *fontdirs; 15638889Sjdp 15738889Sjdp/* Resource info to use for fontdirs. */ 15838889Sjdp 159218822Sdimrc_res_res_info fontdirs_resinfo; 16038889Sjdp 16138889Sjdp/* The number of icon resources we have written out. */ 16238889Sjdp 16338889Sjdpstatic int icons; 16438889Sjdp 165218822Sdim/* The windres target bfd . */ 16638889Sjdp 167218822Sdimstatic windres_bfd wrtarget = 168218822Sdim{ 169218822Sdim (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET 170218822Sdim}; 171218822Sdim 172218822Sdim/* Local functions for rcdata based resource definitions. */ 173218822Sdim 174218822Sdimstatic void define_font_rcdata (rc_res_id, const rc_res_res_info *, 175218822Sdim rc_rcdata_item *); 176218822Sdimstatic void define_icon_rcdata (rc_res_id, const rc_res_res_info *, 177218822Sdim rc_rcdata_item *); 178218822Sdimstatic void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *, 179218822Sdim rc_rcdata_item *); 180218822Sdimstatic void define_cursor_rcdata (rc_res_id, const rc_res_res_info *, 181218822Sdim rc_rcdata_item *); 182218822Sdimstatic void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *, 183218822Sdim rc_rcdata_item *); 184218822Sdimstatic void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *, 185218822Sdim rc_rcdata_item *); 186218822Sdimstatic rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *); 187218822Sdimstatic bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *); 188218822Sdim 189130561Sobrienstatic int run_cmd (char *, const char *); 190130561Sobrienstatic FILE *open_input_stream (char *); 191130561Sobrienstatic FILE *look_for_default 192130561Sobrien (char *, const char *, int, const char *, const char *); 193130561Sobrienstatic void close_input_stream (void); 194130561Sobrienstatic void unexpected_eof (const char *); 195130561Sobrienstatic int get_word (FILE *, const char *); 196130561Sobrienstatic unsigned long get_long (FILE *, const char *); 197218822Sdimstatic void get_data (FILE *, bfd_byte *, rc_uint_type, const char *); 198130561Sobrienstatic void define_fontdirs (void); 19938889Sjdp 20099461Sobrien/* Run `cmd' and redirect the output to `redir'. */ 20160484Sobrien 20260484Sobrienstatic int 203130561Sobrienrun_cmd (char *cmd, const char *redir) 20460484Sobrien{ 20560484Sobrien char *s; 20660484Sobrien int pid, wait_status, retcode; 20760484Sobrien int i; 20860484Sobrien const char **argv; 20960484Sobrien char *errmsg_fmt, *errmsg_arg; 21060484Sobrien char *temp_base = choose_temp_base (); 21160484Sobrien int in_quote; 21260484Sobrien char sep; 21360484Sobrien int redir_handle = -1; 21460484Sobrien int stdout_save = -1; 21560484Sobrien 21660484Sobrien /* Count the args. */ 21760484Sobrien i = 0; 218104834Sobrien 21960484Sobrien for (s = cmd; *s; s++) 22060484Sobrien if (*s == ' ') 22160484Sobrien i++; 222104834Sobrien 22360484Sobrien i++; 22460484Sobrien argv = alloca (sizeof (char *) * (i + 3)); 22560484Sobrien i = 0; 22660484Sobrien s = cmd; 227104834Sobrien 22860484Sobrien while (1) 22960484Sobrien { 23060484Sobrien while (*s == ' ' && *s != 0) 23160484Sobrien s++; 232104834Sobrien 23360484Sobrien if (*s == 0) 23460484Sobrien break; 235104834Sobrien 23660484Sobrien in_quote = (*s == '\'' || *s == '"'); 23760484Sobrien sep = (in_quote) ? *s++ : ' '; 23860484Sobrien argv[i++] = s; 239104834Sobrien 24060484Sobrien while (*s != sep && *s != 0) 24160484Sobrien s++; 242104834Sobrien 24360484Sobrien if (*s == 0) 24460484Sobrien break; 245104834Sobrien 24660484Sobrien *s++ = 0; 247104834Sobrien 24860484Sobrien if (in_quote) 249104834Sobrien s++; 25060484Sobrien } 25160484Sobrien argv[i++] = NULL; 25260484Sobrien 25360484Sobrien /* Setup the redirection. We can't use the usual fork/exec and redirect 25460484Sobrien since we may be running on non-POSIX Windows host. */ 25560484Sobrien 25660484Sobrien fflush (stdout); 25760484Sobrien fflush (stderr); 25860484Sobrien 25960484Sobrien /* Open temporary output file. */ 26060484Sobrien redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666); 26160484Sobrien if (redir_handle == -1) 262104834Sobrien fatal (_("can't open temporary file `%s': %s"), redir, 263104834Sobrien strerror (errno)); 26460484Sobrien 26560484Sobrien /* Duplicate the stdout file handle so it can be restored later. */ 26660484Sobrien stdout_save = dup (STDOUT_FILENO); 26760484Sobrien if (stdout_save == -1) 26860484Sobrien fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno)); 26960484Sobrien 27060484Sobrien /* Redirect stdout to our output file. */ 27160484Sobrien dup2 (redir_handle, STDOUT_FILENO); 27260484Sobrien 27360484Sobrien pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, 27460484Sobrien &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); 27560484Sobrien 27660484Sobrien /* Restore stdout to its previous setting. */ 27760484Sobrien dup2 (stdout_save, STDOUT_FILENO); 27860484Sobrien 279130561Sobrien /* Close response file. */ 28060484Sobrien close (redir_handle); 28160484Sobrien 28260484Sobrien if (pid == -1) 28360484Sobrien { 28460484Sobrien fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno)); 28560484Sobrien return 1; 28660484Sobrien } 28760484Sobrien 28860484Sobrien retcode = 0; 28960484Sobrien pid = pwait (pid, &wait_status, 0); 290104834Sobrien 29160484Sobrien if (pid == -1) 29260484Sobrien { 29360484Sobrien fatal (_("wait: %s"), strerror (errno)); 29460484Sobrien retcode = 1; 29560484Sobrien } 29660484Sobrien else if (WIFSIGNALED (wait_status)) 29760484Sobrien { 29860484Sobrien fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); 29960484Sobrien retcode = 1; 30060484Sobrien } 30160484Sobrien else if (WIFEXITED (wait_status)) 30260484Sobrien { 30360484Sobrien if (WEXITSTATUS (wait_status) != 0) 30460484Sobrien { 305104834Sobrien fatal (_("%s exited with status %d"), cmd, 30660484Sobrien WEXITSTATUS (wait_status)); 30760484Sobrien retcode = 1; 30860484Sobrien } 30960484Sobrien } 31060484Sobrien else 31160484Sobrien retcode = 1; 312104834Sobrien 31360484Sobrien return retcode; 31460484Sobrien} 31560484Sobrien 31660484Sobrienstatic FILE * 317130561Sobrienopen_input_stream (char *cmd) 31860484Sobrien{ 31960484Sobrien if (istream_type == ISTREAM_FILE) 32060484Sobrien { 32160484Sobrien char *fileprefix; 32260484Sobrien 32360484Sobrien fileprefix = choose_temp_base (); 32460484Sobrien cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5); 32560484Sobrien sprintf (cpp_temp_file, "%s.irc", fileprefix); 32660484Sobrien free (fileprefix); 32760484Sobrien 32860484Sobrien if (run_cmd (cmd, cpp_temp_file)) 32960484Sobrien fatal (_("can't execute `%s': %s"), cmd, strerror (errno)); 33060484Sobrien 33160484Sobrien cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);; 33260484Sobrien if (cpp_pipe == NULL) 333104834Sobrien fatal (_("can't open temporary file `%s': %s"), 33460484Sobrien cpp_temp_file, strerror (errno)); 335104834Sobrien 33660484Sobrien if (verbose) 337104834Sobrien fprintf (stderr, 33860484Sobrien _("Using temporary file `%s' to read preprocessor output\n"), 33960484Sobrien cpp_temp_file); 34060484Sobrien } 34160484Sobrien else 34260484Sobrien { 34360484Sobrien cpp_pipe = popen (cmd, FOPEN_RT); 34460484Sobrien if (cpp_pipe == NULL) 345104834Sobrien fatal (_("can't popen `%s': %s"), cmd, strerror (errno)); 34660484Sobrien if (verbose) 34760484Sobrien fprintf (stderr, _("Using popen to read preprocessor output\n")); 34860484Sobrien } 34960484Sobrien 35060484Sobrien xatexit (close_input_stream); 35160484Sobrien return cpp_pipe; 35260484Sobrien} 35360484Sobrien 354218822Sdim/* Determine if FILENAME contains special characters that 355218822Sdim can cause problems unless the entire filename is quoted. */ 35660484Sobrien 357218822Sdimstatic int 358218822Sdimfilename_need_quotes (const char *filename) 359218822Sdim{ 360218822Sdim if (filename == NULL || (filename[0] == '-' && filename[1] == 0)) 361218822Sdim return 0; 362218822Sdim 363218822Sdim while (*filename != 0) 364218822Sdim { 365218822Sdim switch (*filename) 366218822Sdim { 367218822Sdim case '&': 368218822Sdim case ' ': 369218822Sdim case '<': 370218822Sdim case '>': 371218822Sdim case '|': 372218822Sdim case '%': 373218822Sdim return 1; 374218822Sdim } 375218822Sdim ++filename; 376218822Sdim } 377218822Sdim return 0; 378218822Sdim} 379218822Sdim 380218822Sdim/* Look for the preprocessor program. */ 381218822Sdim 38260484Sobrienstatic FILE * 383130561Sobrienlook_for_default (char *cmd, const char *prefix, int end_prefix, 384130561Sobrien const char *preprocargs, const char *filename) 38560484Sobrien{ 38660484Sobrien char *space; 38760484Sobrien int found; 38860484Sobrien struct stat s; 389218822Sdim const char *fnquotes = (filename_need_quotes (filename) ? "\"" : ""); 39060484Sobrien 39160484Sobrien strcpy (cmd, prefix); 39260484Sobrien 39360484Sobrien sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR); 39460484Sobrien space = strchr (cmd + end_prefix, ' '); 39560484Sobrien if (space) 39660484Sobrien *space = 0; 39760484Sobrien 39860484Sobrien if ( 39960484Sobrien#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32) 40060484Sobrien strchr (cmd, '\\') || 40160484Sobrien#endif 40260484Sobrien strchr (cmd, '/')) 40360484Sobrien { 40460484Sobrien found = (stat (cmd, &s) == 0 40560484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 40660484Sobrien || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0 40760484Sobrien#endif 40860484Sobrien ); 40960484Sobrien 41060484Sobrien if (! found) 41160484Sobrien { 41260484Sobrien if (verbose) 41360484Sobrien fprintf (stderr, _("Tried `%s'\n"), cmd); 41460484Sobrien return NULL; 41560484Sobrien } 41660484Sobrien } 41760484Sobrien 41860484Sobrien strcpy (cmd, prefix); 41960484Sobrien 420218822Sdim sprintf (cmd + end_prefix, "%s %s %s%s%s", 421218822Sdim DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes); 42260484Sobrien 42360484Sobrien if (verbose) 42460484Sobrien fprintf (stderr, _("Using `%s'\n"), cmd); 42560484Sobrien 42660484Sobrien cpp_pipe = open_input_stream (cmd); 42760484Sobrien return cpp_pipe; 42860484Sobrien} 42960484Sobrien 43038889Sjdp/* Read an rc file. */ 43138889Sjdp 432218822Sdimrc_res_directory * 433130561Sobrienread_rc_file (const char *filename, const char *preprocessor, 434130561Sobrien const char *preprocargs, int language, int use_temp_file) 43538889Sjdp{ 43638889Sjdp char *cmd; 437218822Sdim const char *fnquotes = (filename_need_quotes (filename) ? "\"" : ""); 43838889Sjdp 43960484Sobrien istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE; 44038889Sjdp 44138889Sjdp if (preprocargs == NULL) 44238889Sjdp preprocargs = ""; 44338889Sjdp if (filename == NULL) 44438889Sjdp filename = "-"; 44538889Sjdp 44660484Sobrien if (preprocessor) 44760484Sobrien { 44860484Sobrien cmd = xmalloc (strlen (preprocessor) 44960484Sobrien + strlen (preprocargs) 45060484Sobrien + strlen (filename) 451218822Sdim + strlen (fnquotes) * 2 45260484Sobrien + 10); 453218822Sdim sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs, 454218822Sdim fnquotes, filename, fnquotes); 45538889Sjdp 45660484Sobrien cpp_pipe = open_input_stream (cmd); 45760484Sobrien } 45860484Sobrien else 45960484Sobrien { 46060484Sobrien char *dash, *slash, *cp; 46160484Sobrien 46260484Sobrien preprocessor = DEFAULT_PREPROCESSOR; 46360484Sobrien 46460484Sobrien cmd = xmalloc (strlen (program_name) 46560484Sobrien + strlen (preprocessor) 46660484Sobrien + strlen (preprocargs) 46760484Sobrien + strlen (filename) 468218822Sdim + strlen (fnquotes) * 2 46960484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 47060484Sobrien + strlen (EXECUTABLE_SUFFIX) 47160484Sobrien#endif 47260484Sobrien + 10); 47360484Sobrien 47460484Sobrien 47560484Sobrien dash = slash = 0; 47660484Sobrien for (cp = program_name; *cp; cp++) 47760484Sobrien { 47860484Sobrien if (*cp == '-') 47960484Sobrien dash = cp; 48060484Sobrien if ( 48160484Sobrien#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32) 48260484Sobrien *cp == ':' || *cp == '\\' || 48360484Sobrien#endif 48460484Sobrien *cp == '/') 48560484Sobrien { 48660484Sobrien slash = cp; 48760484Sobrien dash = 0; 48860484Sobrien } 48960484Sobrien } 49060484Sobrien 49160484Sobrien cpp_pipe = 0; 49260484Sobrien 49360484Sobrien if (dash) 49460484Sobrien { 49560484Sobrien /* First, try looking for a prefixed gcc in the windres 49660484Sobrien directory, with the same prefix as windres */ 49760484Sobrien 498218822Sdim cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1, 49960484Sobrien preprocargs, filename); 50060484Sobrien } 50160484Sobrien 502218822Sdim if (slash && ! cpp_pipe) 50360484Sobrien { 50460484Sobrien /* Next, try looking for a gcc in the same directory as 50560484Sobrien that windres */ 50660484Sobrien 507218822Sdim cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1, 50860484Sobrien preprocargs, filename); 50960484Sobrien } 51060484Sobrien 511218822Sdim if (! cpp_pipe) 51260484Sobrien { 51360484Sobrien /* Sigh, try the default */ 51460484Sobrien 51560484Sobrien cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename); 51660484Sobrien } 51760484Sobrien 51860484Sobrien } 519104834Sobrien 52038889Sjdp free (cmd); 52138889Sjdp 52238889Sjdp rc_filename = xstrdup (filename); 52338889Sjdp rc_lineno = 1; 52438889Sjdp if (language != -1) 52538889Sjdp rcparse_set_language (language); 52638889Sjdp yyparse (); 52799461Sobrien rcparse_discard_strings (); 52838889Sjdp 52960484Sobrien close_input_stream (); 530104834Sobrien 53138889Sjdp if (fontdirs != NULL) 53238889Sjdp define_fontdirs (); 53338889Sjdp 53438889Sjdp free (rc_filename); 53538889Sjdp rc_filename = NULL; 53638889Sjdp 53738889Sjdp return resources; 53838889Sjdp} 53938889Sjdp 54060484Sobrien/* Close the input stream if it is open. */ 54138889Sjdp 54260484Sobrienstatic void 543130561Sobrienclose_input_stream (void) 54438889Sjdp{ 54560484Sobrien if (istream_type == ISTREAM_FILE) 54660484Sobrien { 54760484Sobrien if (cpp_pipe != NULL) 54860484Sobrien fclose (cpp_pipe); 54960484Sobrien 55060484Sobrien if (cpp_temp_file != NULL) 55160484Sobrien { 55260484Sobrien int errno_save = errno; 553104834Sobrien 55460484Sobrien unlink (cpp_temp_file); 55560484Sobrien errno = errno_save; 55660484Sobrien free (cpp_temp_file); 55760484Sobrien } 55860484Sobrien } 55960484Sobrien else 56060484Sobrien { 56160484Sobrien if (cpp_pipe != NULL) 56260484Sobrien pclose (cpp_pipe); 56360484Sobrien } 56460484Sobrien 56599461Sobrien /* Since this is also run via xatexit, safeguard. */ 56660484Sobrien cpp_pipe = NULL; 56760484Sobrien cpp_temp_file = NULL; 56838889Sjdp} 56938889Sjdp 57038889Sjdp/* Report an error while reading an rc file. */ 57138889Sjdp 57238889Sjdpvoid 573130561Sobrienyyerror (const char *msg) 57438889Sjdp{ 57538889Sjdp fatal ("%s:%d: %s", rc_filename, rc_lineno, msg); 57638889Sjdp} 57738889Sjdp 57838889Sjdp/* Issue a warning while reading an rc file. */ 57938889Sjdp 58038889Sjdpvoid 581130561Sobrienrcparse_warning (const char *msg) 58238889Sjdp{ 58360484Sobrien fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg); 58438889Sjdp} 58538889Sjdp 58638889Sjdp/* Die if we get an unexpected end of file. */ 58738889Sjdp 58838889Sjdpstatic void 589130561Sobrienunexpected_eof (const char *msg) 59038889Sjdp{ 59160484Sobrien fatal (_("%s: unexpected EOF"), msg); 59238889Sjdp} 59338889Sjdp 59438889Sjdp/* Read a 16 bit word from a file. The data is assumed to be little 59538889Sjdp endian. */ 59638889Sjdp 59738889Sjdpstatic int 598130561Sobrienget_word (FILE *e, const char *msg) 59938889Sjdp{ 60038889Sjdp int b1, b2; 60138889Sjdp 60238889Sjdp b1 = getc (e); 60338889Sjdp b2 = getc (e); 60438889Sjdp if (feof (e)) 60538889Sjdp unexpected_eof (msg); 60638889Sjdp return ((b2 & 0xff) << 8) | (b1 & 0xff); 60738889Sjdp} 60838889Sjdp 60938889Sjdp/* Read a 32 bit word from a file. The data is assumed to be little 61038889Sjdp endian. */ 61138889Sjdp 61238889Sjdpstatic unsigned long 613130561Sobrienget_long (FILE *e, const char *msg) 61438889Sjdp{ 61538889Sjdp int b1, b2, b3, b4; 61638889Sjdp 61738889Sjdp b1 = getc (e); 61838889Sjdp b2 = getc (e); 61938889Sjdp b3 = getc (e); 62038889Sjdp b4 = getc (e); 62138889Sjdp if (feof (e)) 62238889Sjdp unexpected_eof (msg); 62338889Sjdp return (((((((b4 & 0xff) << 8) 62438889Sjdp | (b3 & 0xff)) << 8) 62538889Sjdp | (b2 & 0xff)) << 8) 62638889Sjdp | (b1 & 0xff)); 62738889Sjdp} 62838889Sjdp 62938889Sjdp/* Read data from a file. This is a wrapper to do error checking. */ 63038889Sjdp 63138889Sjdpstatic void 632218822Sdimget_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg) 63338889Sjdp{ 634218822Sdim rc_uint_type got; // $$$d 63538889Sjdp 636218822Sdim got = (rc_uint_type) fread (p, 1, c, e); 63738889Sjdp if (got == c) 63838889Sjdp return; 63938889Sjdp 640218822Sdim fatal (_("%s: read of %lu returned %lu"), msg, (long) c, (long) got); 64138889Sjdp} 64238889Sjdp 64338889Sjdp/* Define an accelerator resource. */ 64438889Sjdp 64538889Sjdpvoid 646218822Sdimdefine_accelerator (rc_res_id id, const rc_res_res_info *resinfo, 647218822Sdim rc_accelerator *data) 64838889Sjdp{ 649218822Sdim rc_res_resource *r; 65038889Sjdp 65160484Sobrien r = define_standard_resource (&resources, RT_ACCELERATOR, id, 65238889Sjdp resinfo->language, 0); 65338889Sjdp r->type = RES_TYPE_ACCELERATOR; 65438889Sjdp r->u.acc = data; 65538889Sjdp r->res_info = *resinfo; 65638889Sjdp} 65738889Sjdp 65838889Sjdp/* Define a bitmap resource. Bitmap data is stored in a file. The 65938889Sjdp first 14 bytes of the file are a standard header, which is not 66038889Sjdp included in the resource data. */ 66138889Sjdp 66238889Sjdp#define BITMAP_SKIP (14) 66338889Sjdp 66438889Sjdpvoid 665218822Sdimdefine_bitmap (rc_res_id id, const rc_res_res_info *resinfo, 666130561Sobrien const char *filename) 66738889Sjdp{ 66838889Sjdp FILE *e; 66938889Sjdp char *real_filename; 67038889Sjdp struct stat s; 671218822Sdim bfd_byte *data; 672218822Sdim rc_uint_type i; 673218822Sdim rc_res_resource *r; 67438889Sjdp 67538889Sjdp e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename); 67638889Sjdp 67738889Sjdp if (stat (real_filename, &s) < 0) 67860484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 67938889Sjdp strerror (errno)); 68038889Sjdp 681218822Sdim data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP); 68238889Sjdp 68338889Sjdp for (i = 0; i < BITMAP_SKIP; i++) 68438889Sjdp getc (e); 68538889Sjdp 68638889Sjdp get_data (e, data, s.st_size - BITMAP_SKIP, real_filename); 68738889Sjdp 68838889Sjdp fclose (e); 68938889Sjdp free (real_filename); 69038889Sjdp 69138889Sjdp r = define_standard_resource (&resources, RT_BITMAP, id, 69238889Sjdp resinfo->language, 0); 69338889Sjdp 69438889Sjdp r->type = RES_TYPE_BITMAP; 69538889Sjdp r->u.data.length = s.st_size - BITMAP_SKIP; 69638889Sjdp r->u.data.data = data; 69738889Sjdp r->res_info = *resinfo; 69838889Sjdp} 69938889Sjdp 70038889Sjdp/* Define a cursor resource. A cursor file may contain a set of 70138889Sjdp bitmaps, each representing the same cursor at various different 70238889Sjdp resolutions. They each get written out with a different ID. The 70338889Sjdp real cursor resource is then a group resource which can be used to 70438889Sjdp select one of the actual cursors. */ 70538889Sjdp 70638889Sjdpvoid 707218822Sdimdefine_cursor (rc_res_id id, const rc_res_res_info *resinfo, 708130561Sobrien const char *filename) 70938889Sjdp{ 71038889Sjdp FILE *e; 71138889Sjdp char *real_filename; 71238889Sjdp int type, count, i; 71338889Sjdp struct icondir *icondirs; 71438889Sjdp int first_cursor; 715218822Sdim rc_res_resource *r; 716218822Sdim rc_group_cursor *first, **pp; 71738889Sjdp 71838889Sjdp e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename); 71938889Sjdp 72038889Sjdp /* A cursor file is basically an icon file. The start of the file 72138889Sjdp is a three word structure. The first word is ignored. The 72238889Sjdp second word is the type of data. The third word is the number of 72338889Sjdp entries. */ 72438889Sjdp 72538889Sjdp get_word (e, real_filename); 72638889Sjdp type = get_word (e, real_filename); 72738889Sjdp count = get_word (e, real_filename); 72838889Sjdp if (type != 2) 72960484Sobrien fatal (_("cursor file `%s' does not contain cursor data"), real_filename); 73038889Sjdp 73138889Sjdp /* Read in the icon directory entries. */ 73238889Sjdp 73338889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 73438889Sjdp 73538889Sjdp for (i = 0; i < count; i++) 73638889Sjdp { 73738889Sjdp icondirs[i].width = getc (e); 73838889Sjdp icondirs[i].height = getc (e); 73938889Sjdp icondirs[i].colorcount = getc (e); 74038889Sjdp getc (e); 74138889Sjdp icondirs[i].u.cursor.xhotspot = get_word (e, real_filename); 74238889Sjdp icondirs[i].u.cursor.yhotspot = get_word (e, real_filename); 74338889Sjdp icondirs[i].bytes = get_long (e, real_filename); 74438889Sjdp icondirs[i].offset = get_long (e, real_filename); 74538889Sjdp 74638889Sjdp if (feof (e)) 74738889Sjdp unexpected_eof (real_filename); 74838889Sjdp } 74938889Sjdp 75038889Sjdp /* Define each cursor as a unique resource. */ 75138889Sjdp 75238889Sjdp first_cursor = cursors; 75338889Sjdp 75438889Sjdp for (i = 0; i < count; i++) 75538889Sjdp { 756218822Sdim bfd_byte *data; 757218822Sdim rc_res_id name; 758218822Sdim rc_cursor *c; 75938889Sjdp 76038889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 76160484Sobrien fatal (_("%s: fseek to %lu failed: %s"), real_filename, 76238889Sjdp icondirs[i].offset, strerror (errno)); 76338889Sjdp 764218822Sdim data = (bfd_byte *) res_alloc (icondirs[i].bytes); 76538889Sjdp 76638889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 76738889Sjdp 768218822Sdim c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); 76938889Sjdp c->xhotspot = icondirs[i].u.cursor.xhotspot; 77038889Sjdp c->yhotspot = icondirs[i].u.cursor.yhotspot; 77138889Sjdp c->length = icondirs[i].bytes; 77238889Sjdp c->data = data; 77338889Sjdp 77438889Sjdp ++cursors; 77538889Sjdp 77638889Sjdp name.named = 0; 77738889Sjdp name.u.id = cursors; 77838889Sjdp 77938889Sjdp r = define_standard_resource (&resources, RT_CURSOR, name, 78038889Sjdp resinfo->language, 0); 78138889Sjdp r->type = RES_TYPE_CURSOR; 78238889Sjdp r->u.cursor = c; 78338889Sjdp r->res_info = *resinfo; 78438889Sjdp } 78538889Sjdp 78638889Sjdp fclose (e); 78738889Sjdp free (real_filename); 78838889Sjdp 78938889Sjdp /* Define a cursor group resource. */ 79038889Sjdp 79138889Sjdp first = NULL; 79238889Sjdp pp = &first; 79338889Sjdp for (i = 0; i < count; i++) 79438889Sjdp { 795218822Sdim rc_group_cursor *cg; 79638889Sjdp 797218822Sdim cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor)); 79838889Sjdp cg->next = NULL; 79938889Sjdp cg->width = icondirs[i].width; 80038889Sjdp cg->height = 2 * icondirs[i].height; 80138889Sjdp 80238889Sjdp /* FIXME: What should these be set to? */ 80338889Sjdp cg->planes = 1; 80438889Sjdp cg->bits = 1; 80538889Sjdp 80638889Sjdp cg->bytes = icondirs[i].bytes + 4; 80738889Sjdp cg->index = first_cursor + i + 1; 80838889Sjdp 80938889Sjdp *pp = cg; 81038889Sjdp pp = &(*pp)->next; 81138889Sjdp } 81238889Sjdp 81338889Sjdp free (icondirs); 81438889Sjdp 81538889Sjdp r = define_standard_resource (&resources, RT_GROUP_CURSOR, id, 81638889Sjdp resinfo->language, 0); 81738889Sjdp r->type = RES_TYPE_GROUP_CURSOR; 81838889Sjdp r->u.group_cursor = first; 81938889Sjdp r->res_info = *resinfo; 82038889Sjdp} 82138889Sjdp 82238889Sjdp/* Define a dialog resource. */ 82338889Sjdp 82438889Sjdpvoid 825218822Sdimdefine_dialog (rc_res_id id, const rc_res_res_info *resinfo, 826218822Sdim const rc_dialog *dialog) 82738889Sjdp{ 828218822Sdim rc_dialog *copy; 829218822Sdim rc_res_resource *r; 83038889Sjdp 831218822Sdim copy = (rc_dialog *) res_alloc (sizeof *copy); 83238889Sjdp *copy = *dialog; 83338889Sjdp 83438889Sjdp r = define_standard_resource (&resources, RT_DIALOG, id, 83538889Sjdp resinfo->language, 0); 83638889Sjdp r->type = RES_TYPE_DIALOG; 83738889Sjdp r->u.dialog = copy; 83838889Sjdp r->res_info = *resinfo; 83938889Sjdp} 84038889Sjdp 84138889Sjdp/* Define a dialog control. This does not define a resource, but 84238889Sjdp merely allocates and fills in a structure. */ 84338889Sjdp 844218822Sdimrc_dialog_control * 845218822Sdimdefine_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x, 846218822Sdim rc_uint_type y, rc_uint_type width, rc_uint_type height, 847218822Sdim const rc_res_id class, rc_uint_type style, 848218822Sdim rc_uint_type exstyle) 84938889Sjdp{ 850218822Sdim rc_dialog_control *n; 85138889Sjdp 852218822Sdim n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control)); 85338889Sjdp n->next = NULL; 85438889Sjdp n->id = id; 85538889Sjdp n->style = style; 85638889Sjdp n->exstyle = exstyle; 85738889Sjdp n->x = x; 85838889Sjdp n->y = y; 85938889Sjdp n->width = width; 86038889Sjdp n->height = height; 861218822Sdim n->class = class; 862130561Sobrien n->text = iid; 86338889Sjdp n->data = NULL; 86438889Sjdp n->help = 0; 86538889Sjdp 86638889Sjdp return n; 86738889Sjdp} 86838889Sjdp 869218822Sdimrc_dialog_control * 870218822Sdimdefine_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x, 871218822Sdim rc_uint_type y, rc_uint_type style, 872218822Sdim rc_uint_type exstyle, rc_uint_type help, 873218822Sdim rc_rcdata_item *data, rc_dialog_ex *ex) 87477298Sobrien{ 875218822Sdim rc_dialog_control *n; 876218822Sdim rc_res_id tid; 877218822Sdim rc_res_id cid; 878130561Sobrien 87977298Sobrien if (style == 0) 88077298Sobrien style = SS_ICON | WS_CHILD | WS_VISIBLE; 881130561Sobrien res_string_to_id (&tid, ""); 882218822Sdim cid.named = 0; 883218822Sdim cid.u.id = CTL_STATIC; 884218822Sdim n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle); 88577298Sobrien n->text = iid; 886218822Sdim if (help && ! ex) 88777298Sobrien rcparse_warning (_("help ID requires DIALOGEX")); 888218822Sdim if (data && ! ex) 88977298Sobrien rcparse_warning (_("control data requires DIALOGEX")); 89077298Sobrien n->help = help; 89177298Sobrien n->data = data; 89277298Sobrien 89377298Sobrien return n; 89477298Sobrien} 89577298Sobrien 89638889Sjdp/* Define a font resource. */ 89738889Sjdp 89838889Sjdpvoid 899218822Sdimdefine_font (rc_res_id id, const rc_res_res_info *resinfo, 900130561Sobrien const char *filename) 90138889Sjdp{ 90238889Sjdp FILE *e; 90338889Sjdp char *real_filename; 90438889Sjdp struct stat s; 905218822Sdim bfd_byte *data; 906218822Sdim rc_res_resource *r; 90738889Sjdp long offset; 90838889Sjdp long fontdatalength; 909218822Sdim bfd_byte *fontdata; 910218822Sdim rc_fontdir *fd; 91138889Sjdp const char *device, *face; 912218822Sdim rc_fontdir **pp; 91338889Sjdp 91438889Sjdp e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); 91538889Sjdp 91638889Sjdp if (stat (real_filename, &s) < 0) 917218822Sdim fatal (_("stat failed on font file `%s': %s"), real_filename, 91838889Sjdp strerror (errno)); 91938889Sjdp 920218822Sdim data = (bfd_byte *) res_alloc (s.st_size); 92138889Sjdp 92238889Sjdp get_data (e, data, s.st_size, real_filename); 92338889Sjdp 92438889Sjdp fclose (e); 92538889Sjdp free (real_filename); 92638889Sjdp 92738889Sjdp r = define_standard_resource (&resources, RT_FONT, id, 92838889Sjdp resinfo->language, 0); 92938889Sjdp 93038889Sjdp r->type = RES_TYPE_FONT; 93138889Sjdp r->u.data.length = s.st_size; 93238889Sjdp r->u.data.data = data; 93338889Sjdp r->res_info = *resinfo; 93438889Sjdp 93538889Sjdp /* For each font resource, we must add an entry in the FONTDIR 93638889Sjdp resource. The FONTDIR resource includes some strings in the font 93738889Sjdp file. To find them, we have to do some magic on the data we have 93838889Sjdp read. */ 93938889Sjdp 94038889Sjdp offset = ((((((data[47] << 8) 94138889Sjdp | data[46]) << 8) 94238889Sjdp | data[45]) << 8) 94338889Sjdp | data[44]); 94438889Sjdp if (offset > 0 && offset < s.st_size) 94538889Sjdp device = (char *) data + offset; 94638889Sjdp else 94738889Sjdp device = ""; 94838889Sjdp 94938889Sjdp offset = ((((((data[51] << 8) 95038889Sjdp | data[50]) << 8) 95138889Sjdp | data[49]) << 8) 95238889Sjdp | data[48]); 95338889Sjdp if (offset > 0 && offset < s.st_size) 95438889Sjdp face = (char *) data + offset; 95538889Sjdp else 95638889Sjdp face = ""; 95738889Sjdp 95838889Sjdp ++fonts; 95938889Sjdp 96038889Sjdp fontdatalength = 58 + strlen (device) + strlen (face); 961218822Sdim fontdata = (bfd_byte *) res_alloc (fontdatalength); 96238889Sjdp memcpy (fontdata, data, 56); 96338889Sjdp strcpy ((char *) fontdata + 56, device); 96438889Sjdp strcpy ((char *) fontdata + 57 + strlen (device), face); 96538889Sjdp 966218822Sdim fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir)); 96738889Sjdp fd->next = NULL; 96838889Sjdp fd->index = fonts; 96938889Sjdp fd->length = fontdatalength; 97038889Sjdp fd->data = fontdata; 97138889Sjdp 97238889Sjdp for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next) 97338889Sjdp ; 97438889Sjdp *pp = fd; 97538889Sjdp 97638889Sjdp /* For the single fontdirs resource, we always use the resource 97738889Sjdp information of the last font. I don't know what else to do. */ 97838889Sjdp fontdirs_resinfo = *resinfo; 97938889Sjdp} 98038889Sjdp 981218822Sdimstatic void 982218822Sdimdefine_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo, 983218822Sdim rc_rcdata_item *data) 984218822Sdim{ 985218822Sdim rc_res_resource *r; 986218822Sdim rc_uint_type len_data; 987218822Sdim bfd_byte *pb_data; 988218822Sdim 989218822Sdim r = define_standard_resource (&resources, RT_FONT, id, 990218822Sdim resinfo->language, 0); 991218822Sdim 992218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 993218822Sdim 994218822Sdim r->type = RES_TYPE_FONT; 995218822Sdim r->u.data.length = len_data; 996218822Sdim r->u.data.data = pb_data; 997218822Sdim r->res_info = *resinfo; 998218822Sdim} 999218822Sdim 100038889Sjdp/* Define the fontdirs resource. This is called after the entire rc 100138889Sjdp file has been parsed, if any font resources were seen. */ 100238889Sjdp 100338889Sjdpstatic void 1004130561Sobriendefine_fontdirs (void) 100538889Sjdp{ 1006218822Sdim rc_res_resource *r; 1007218822Sdim rc_res_id id; 100838889Sjdp 100938889Sjdp id.named = 0; 101038889Sjdp id.u.id = 1; 101138889Sjdp 101238889Sjdp r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0); 101338889Sjdp 101438889Sjdp r->type = RES_TYPE_FONTDIR; 101538889Sjdp r->u.fontdir = fontdirs; 101638889Sjdp r->res_info = fontdirs_resinfo; 101738889Sjdp} 101838889Sjdp 1019218822Sdimstatic bfd_byte * 1020218822Sdimrcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen) 1021218822Sdim{ 1022218822Sdim const rc_rcdata_item *d; 1023218822Sdim bfd_byte *ret = NULL, *pret; 1024218822Sdim rc_uint_type len = 0; 1025218822Sdim 1026218822Sdim for (d = data; d != NULL; d = d->next) 1027218822Sdim len += rcdata_copy (d, NULL); 1028218822Sdim if (len != 0) 1029218822Sdim { 1030218822Sdim ret = pret = (bfd_byte *) res_alloc (len); 1031218822Sdim for (d = data; d != NULL; d = d->next) 1032218822Sdim pret += rcdata_copy (d, pret); 1033218822Sdim } 1034218822Sdim if (plen) 1035218822Sdim *plen = len; 1036218822Sdim return ret; 1037218822Sdim} 1038218822Sdim 1039218822Sdimstatic void 1040218822Sdimdefine_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo, 1041218822Sdim rc_rcdata_item *data) 1042218822Sdim{ 1043218822Sdim rc_res_resource *r; 1044218822Sdim rc_fontdir *fd, *fd_first, *fd_cur; 1045218822Sdim rc_uint_type len_data; 1046218822Sdim bfd_byte *pb_data; 1047218822Sdim rc_uint_type c; 1048218822Sdim 1049218822Sdim fd_cur = fd_first = NULL; 1050218822Sdim r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0); 1051218822Sdim 1052218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1053218822Sdim 1054218822Sdim if (pb_data) 1055218822Sdim { 1056218822Sdim rc_uint_type off = 2; 1057218822Sdim c = windres_get_16 (&wrtarget, pb_data, len_data); 1058218822Sdim for (; c > 0; c--) 1059218822Sdim { 1060218822Sdim size_t len; 1061218822Sdim rc_uint_type safe_pos = off; 1062218822Sdim const struct bin_fontdir_item *bfi; 1063218822Sdim 1064218822Sdim bfi = (const struct bin_fontdir_item *) pb_data + off; 1065218822Sdim fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir)); 1066218822Sdim fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off); 1067218822Sdim fd->data = pb_data + off; 1068218822Sdim off += 56; 1069218822Sdim len = strlen ((char *) bfi->device_name) + 1; 1070218822Sdim off += (rc_uint_type) len; 1071218822Sdim off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1; 1072218822Sdim fd->length = (off - safe_pos); 1073218822Sdim fd->next = NULL; 1074218822Sdim if (fd_first == NULL) 1075218822Sdim fd_first = fd; 1076218822Sdim else 1077218822Sdim fd_cur->next = fd; 1078218822Sdim fd_cur = fd; 1079218822Sdim } 1080218822Sdim } 1081218822Sdim r->type = RES_TYPE_FONTDIR; 1082218822Sdim r->u.fontdir = fd_first; 1083218822Sdim r->res_info = *resinfo; 1084218822Sdim} 1085218822Sdim 1086218822Sdimstatic void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo, 1087218822Sdim rc_rcdata_item *data) 1088218822Sdim{ 1089218822Sdim rc_res_resource *r; 1090218822Sdim rc_uint_type len_data; 1091218822Sdim bfd_byte *pb_data; 1092218822Sdim 1093218822Sdim r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0); 1094218822Sdim 1095218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1096218822Sdim r->type = RES_TYPE_MESSAGETABLE; 1097218822Sdim r->u.data.length = len_data; 1098218822Sdim r->u.data.data = pb_data; 1099218822Sdim r->res_info = *resinfo; 1100218822Sdim} 1101218822Sdim 110238889Sjdp/* Define an icon resource. An icon file may contain a set of 110338889Sjdp bitmaps, each representing the same icon at various different 110438889Sjdp resolutions. They each get written out with a different ID. The 110538889Sjdp real icon resource is then a group resource which can be used to 110638889Sjdp select one of the actual icon bitmaps. */ 110738889Sjdp 110838889Sjdpvoid 1109218822Sdimdefine_icon (rc_res_id id, const rc_res_res_info *resinfo, 1110130561Sobrien const char *filename) 111138889Sjdp{ 111238889Sjdp FILE *e; 111338889Sjdp char *real_filename; 111438889Sjdp int type, count, i; 111538889Sjdp struct icondir *icondirs; 111638889Sjdp int first_icon; 1117218822Sdim rc_res_resource *r; 1118218822Sdim rc_group_icon *first, **pp; 111938889Sjdp 112038889Sjdp e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename); 112138889Sjdp 112238889Sjdp /* The start of an icon file is a three word structure. The first 112338889Sjdp word is ignored. The second word is the type of data. The third 112438889Sjdp word is the number of entries. */ 112538889Sjdp 112638889Sjdp get_word (e, real_filename); 112738889Sjdp type = get_word (e, real_filename); 112838889Sjdp count = get_word (e, real_filename); 112938889Sjdp if (type != 1) 113060484Sobrien fatal (_("icon file `%s' does not contain icon data"), real_filename); 113138889Sjdp 113238889Sjdp /* Read in the icon directory entries. */ 113338889Sjdp 113438889Sjdp icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); 113538889Sjdp 113638889Sjdp for (i = 0; i < count; i++) 113738889Sjdp { 113838889Sjdp icondirs[i].width = getc (e); 113938889Sjdp icondirs[i].height = getc (e); 114038889Sjdp icondirs[i].colorcount = getc (e); 114138889Sjdp getc (e); 114238889Sjdp icondirs[i].u.icon.planes = get_word (e, real_filename); 114338889Sjdp icondirs[i].u.icon.bits = get_word (e, real_filename); 114438889Sjdp icondirs[i].bytes = get_long (e, real_filename); 114538889Sjdp icondirs[i].offset = get_long (e, real_filename); 114638889Sjdp 114738889Sjdp if (feof (e)) 114838889Sjdp unexpected_eof (real_filename); 114938889Sjdp } 115038889Sjdp 115138889Sjdp /* Define each icon as a unique resource. */ 115238889Sjdp 115338889Sjdp first_icon = icons; 115438889Sjdp 115538889Sjdp for (i = 0; i < count; i++) 115638889Sjdp { 1157218822Sdim bfd_byte *data; 1158218822Sdim rc_res_id name; 115938889Sjdp 116038889Sjdp if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) 116160484Sobrien fatal (_("%s: fseek to %lu failed: %s"), real_filename, 116238889Sjdp icondirs[i].offset, strerror (errno)); 116338889Sjdp 1164218822Sdim data = (bfd_byte *) res_alloc (icondirs[i].bytes); 116538889Sjdp 116638889Sjdp get_data (e, data, icondirs[i].bytes, real_filename); 116738889Sjdp 116838889Sjdp ++icons; 116938889Sjdp 117038889Sjdp name.named = 0; 117138889Sjdp name.u.id = icons; 117238889Sjdp 117338889Sjdp r = define_standard_resource (&resources, RT_ICON, name, 117438889Sjdp resinfo->language, 0); 117538889Sjdp r->type = RES_TYPE_ICON; 117638889Sjdp r->u.data.length = icondirs[i].bytes; 117738889Sjdp r->u.data.data = data; 117838889Sjdp r->res_info = *resinfo; 117938889Sjdp } 118038889Sjdp 118138889Sjdp fclose (e); 118238889Sjdp free (real_filename); 118338889Sjdp 118438889Sjdp /* Define an icon group resource. */ 118538889Sjdp 118638889Sjdp first = NULL; 118738889Sjdp pp = &first; 118838889Sjdp for (i = 0; i < count; i++) 118938889Sjdp { 1190218822Sdim rc_group_icon *cg; 119138889Sjdp 119238889Sjdp /* For some reason, at least in some files the planes and bits 119338889Sjdp are zero. We instead set them from the color. This is 119438889Sjdp copied from rcl. */ 119538889Sjdp 1196218822Sdim cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); 119738889Sjdp cg->next = NULL; 119838889Sjdp cg->width = icondirs[i].width; 119938889Sjdp cg->height = icondirs[i].height; 120038889Sjdp cg->colors = icondirs[i].colorcount; 120138889Sjdp 1202130561Sobrien if (icondirs[i].u.icon.planes) 1203130561Sobrien cg->planes = icondirs[i].u.icon.planes; 1204130561Sobrien else 1205130561Sobrien cg->planes = 1; 120638889Sjdp 1207130561Sobrien if (icondirs[i].u.icon.bits) 1208130561Sobrien cg->bits = icondirs[i].u.icon.bits; 1209130561Sobrien else 1210130561Sobrien { 1211130561Sobrien cg->bits = 0; 1212130561Sobrien 1213130561Sobrien while ((1L << cg->bits) < cg->colors) 1214130561Sobrien ++cg->bits; 1215130561Sobrien } 1216130561Sobrien 121738889Sjdp cg->bytes = icondirs[i].bytes; 121838889Sjdp cg->index = first_icon + i + 1; 121938889Sjdp 122038889Sjdp *pp = cg; 122138889Sjdp pp = &(*pp)->next; 122238889Sjdp } 122338889Sjdp 122438889Sjdp free (icondirs); 122538889Sjdp 122638889Sjdp r = define_standard_resource (&resources, RT_GROUP_ICON, id, 122738889Sjdp resinfo->language, 0); 122838889Sjdp r->type = RES_TYPE_GROUP_ICON; 122938889Sjdp r->u.group_icon = first; 123038889Sjdp r->res_info = *resinfo; 123138889Sjdp} 123238889Sjdp 1233218822Sdimstatic void 1234218822Sdimdefine_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo, 1235218822Sdim rc_rcdata_item *data) 1236218822Sdim{ 1237218822Sdim rc_res_resource *r; 1238218822Sdim rc_group_icon *cg, *first, *cur; 1239218822Sdim rc_uint_type len_data; 1240218822Sdim bfd_byte *pb_data; 1241218822Sdim 1242218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1243218822Sdim 1244218822Sdim cur = NULL; 1245218822Sdim first = NULL; 1246218822Sdim 1247218822Sdim while (len_data >= 6) 1248218822Sdim { 1249218822Sdim int c, i; 1250218822Sdim unsigned short type; 1251218822Sdim type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); 1252218822Sdim if (type != 1) 1253218822Sdim fatal (_("unexpected group icon type %d"), type); 1254218822Sdim c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); 1255218822Sdim len_data -= 6; 1256218822Sdim pb_data += 6; 1257218822Sdim 1258218822Sdim for (i = 0; i < c; i++) 1259218822Sdim { 1260218822Sdim if (len_data < 14) 1261218822Sdim fatal ("too small group icon rcdata"); 1262218822Sdim cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); 1263218822Sdim cg->next = NULL; 1264218822Sdim cg->width = pb_data[0]; 1265218822Sdim cg->height = pb_data[1]; 1266218822Sdim cg->colors = pb_data[2]; 1267218822Sdim cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); 1268218822Sdim cg->bits = windres_get_16 (&wrtarget, pb_data + 6, len_data - 6); 1269218822Sdim cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8); 1270218822Sdim cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12); 1271218822Sdim if (! first) 1272218822Sdim first = cg; 1273218822Sdim else 1274218822Sdim cur->next = cg; 1275218822Sdim cur = cg; 1276218822Sdim pb_data += 14; 1277218822Sdim len_data -= 14; 1278218822Sdim } 1279218822Sdim } 1280218822Sdim r = define_standard_resource (&resources, RT_GROUP_ICON, id, 1281218822Sdim resinfo->language, 0); 1282218822Sdim r->type = RES_TYPE_GROUP_ICON; 1283218822Sdim r->u.group_icon = first; 1284218822Sdim r->res_info = *resinfo; 1285218822Sdim} 1286218822Sdim 1287218822Sdimstatic void 1288218822Sdimdefine_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo, 1289218822Sdim rc_rcdata_item *data) 1290218822Sdim{ 1291218822Sdim rc_res_resource *r; 1292218822Sdim rc_group_cursor *cg, *first, *cur; 1293218822Sdim rc_uint_type len_data; 1294218822Sdim bfd_byte *pb_data; 1295218822Sdim 1296218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1297218822Sdim 1298218822Sdim first = cur = NULL; 1299218822Sdim 1300218822Sdim while (len_data >= 6) 1301218822Sdim { 1302218822Sdim int c, i; 1303218822Sdim unsigned short type; 1304218822Sdim type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); 1305218822Sdim if (type != 2) 1306218822Sdim fatal (_("unexpected group cursor type %d"), type); 1307218822Sdim c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); 1308218822Sdim len_data -= 6; 1309218822Sdim pb_data += 6; 1310218822Sdim 1311218822Sdim for (i = 0; i < c; i++) 1312218822Sdim { 1313218822Sdim if (len_data < 14) 1314218822Sdim fatal ("too small group icon rcdata"); 1315218822Sdim cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor)); 1316218822Sdim cg->next = NULL; 1317218822Sdim cg->width = windres_get_16 (&wrtarget, pb_data, len_data); 1318218822Sdim cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); 1319218822Sdim cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4); 1320218822Sdim cg->bits = windres_get_16 (&wrtarget, pb_data + 6, len_data - 6); 1321218822Sdim cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8); 1322218822Sdim cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12); 1323218822Sdim if (! first) 1324218822Sdim first = cg; 1325218822Sdim else 1326218822Sdim cur->next = cg; 1327218822Sdim cur = cg; 1328218822Sdim pb_data += 14; 1329218822Sdim len_data -= 14; 1330218822Sdim } 1331218822Sdim } 1332218822Sdim 1333218822Sdim r = define_standard_resource (&resources, RT_GROUP_ICON, id, 1334218822Sdim resinfo->language, 0); 1335218822Sdim r->type = RES_TYPE_GROUP_CURSOR; 1336218822Sdim r->u.group_cursor = first; 1337218822Sdim r->res_info = *resinfo; 1338218822Sdim} 1339218822Sdim 1340218822Sdimstatic void 1341218822Sdimdefine_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo, 1342218822Sdim rc_rcdata_item *data) 1343218822Sdim{ 1344218822Sdim rc_cursor *c; 1345218822Sdim rc_res_resource *r; 1346218822Sdim rc_uint_type len_data; 1347218822Sdim bfd_byte *pb_data; 1348218822Sdim 1349218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1350218822Sdim 1351218822Sdim c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); 1352218822Sdim c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data); 1353218822Sdim c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2); 1354218822Sdim c->length = len_data - BIN_CURSOR_SIZE; 1355218822Sdim c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE); 1356218822Sdim 1357218822Sdim r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0); 1358218822Sdim r->type = RES_TYPE_CURSOR; 1359218822Sdim r->u.cursor = c; 1360218822Sdim r->res_info = *resinfo; 1361218822Sdim} 1362218822Sdim 1363218822Sdimstatic void 1364218822Sdimdefine_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo, 1365218822Sdim rc_rcdata_item *data) 1366218822Sdim{ 1367218822Sdim rc_res_resource *r; 1368218822Sdim rc_uint_type len_data; 1369218822Sdim bfd_byte *pb_data; 1370218822Sdim 1371218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1372218822Sdim 1373218822Sdim r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0); 1374218822Sdim r->type = RES_TYPE_BITMAP; 1375218822Sdim r->u.data.length = len_data; 1376218822Sdim r->u.data.data = pb_data; 1377218822Sdim r->res_info = *resinfo; 1378218822Sdim} 1379218822Sdim 1380218822Sdimstatic void 1381218822Sdimdefine_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo, 1382218822Sdim rc_rcdata_item *data) 1383218822Sdim{ 1384218822Sdim rc_res_resource *r; 1385218822Sdim rc_uint_type len_data; 1386218822Sdim bfd_byte *pb_data; 1387218822Sdim 1388218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1389218822Sdim 1390218822Sdim r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0); 1391218822Sdim r->type = RES_TYPE_ICON; 1392218822Sdim r->u.data.length = len_data; 1393218822Sdim r->u.data.data = pb_data; 1394218822Sdim r->res_info = *resinfo; 1395218822Sdim} 1396218822Sdim 139738889Sjdp/* Define a menu resource. */ 139838889Sjdp 139938889Sjdpvoid 1400218822Sdimdefine_menu (rc_res_id id, const rc_res_res_info *resinfo, 1401218822Sdim rc_menuitem *menuitems) 140238889Sjdp{ 1403218822Sdim rc_menu *m; 1404218822Sdim rc_res_resource *r; 140538889Sjdp 1406218822Sdim m = (rc_menu *) res_alloc (sizeof (rc_menu)); 140738889Sjdp m->items = menuitems; 140838889Sjdp m->help = 0; 140938889Sjdp 141038889Sjdp r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0); 141138889Sjdp r->type = RES_TYPE_MENU; 141238889Sjdp r->u.menu = m; 141338889Sjdp r->res_info = *resinfo; 141438889Sjdp} 141538889Sjdp 141638889Sjdp/* Define a menu item. This does not define a resource, but merely 141738889Sjdp allocates and fills in a structure. */ 141838889Sjdp 1419218822Sdimrc_menuitem * 1420218822Sdimdefine_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type, 1421218822Sdim rc_uint_type state, rc_uint_type help, 1422218822Sdim rc_menuitem *menuitems) 142338889Sjdp{ 1424218822Sdim rc_menuitem *mi; 142538889Sjdp 1426218822Sdim mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem)); 142738889Sjdp mi->next = NULL; 142838889Sjdp mi->type = type; 142938889Sjdp mi->state = state; 143038889Sjdp mi->id = menuid; 1431218822Sdim mi->text = unichar_dup (text); 143238889Sjdp mi->help = help; 143338889Sjdp mi->popup = menuitems; 143438889Sjdp return mi; 143538889Sjdp} 143638889Sjdp 143738889Sjdp/* Define a messagetable resource. */ 143838889Sjdp 143938889Sjdpvoid 1440218822Sdimdefine_messagetable (rc_res_id id, const rc_res_res_info *resinfo, 1441130561Sobrien const char *filename) 144238889Sjdp{ 144338889Sjdp FILE *e; 144438889Sjdp char *real_filename; 144538889Sjdp struct stat s; 1446218822Sdim bfd_byte *data; 1447218822Sdim rc_res_resource *r; 144838889Sjdp 144938889Sjdp e = open_file_search (filename, FOPEN_RB, "messagetable file", 145038889Sjdp &real_filename); 145138889Sjdp 145238889Sjdp if (stat (real_filename, &s) < 0) 145360484Sobrien fatal (_("stat failed on bitmap file `%s': %s"), real_filename, 145438889Sjdp strerror (errno)); 145538889Sjdp 1456218822Sdim data = (bfd_byte *) res_alloc (s.st_size); 145738889Sjdp 145838889Sjdp get_data (e, data, s.st_size, real_filename); 145938889Sjdp 146038889Sjdp fclose (e); 146138889Sjdp free (real_filename); 146238889Sjdp 146338889Sjdp r = define_standard_resource (&resources, RT_MESSAGETABLE, id, 146438889Sjdp resinfo->language, 0); 146538889Sjdp 146638889Sjdp r->type = RES_TYPE_MESSAGETABLE; 146738889Sjdp r->u.data.length = s.st_size; 146838889Sjdp r->u.data.data = data; 146938889Sjdp r->res_info = *resinfo; 147038889Sjdp} 147138889Sjdp 147238889Sjdp/* Define an rcdata resource. */ 147338889Sjdp 147438889Sjdpvoid 1475218822Sdimdefine_rcdata (rc_res_id id, const rc_res_res_info *resinfo, 1476218822Sdim rc_rcdata_item *data) 147738889Sjdp{ 1478218822Sdim rc_res_resource *r; 147938889Sjdp 148038889Sjdp r = define_standard_resource (&resources, RT_RCDATA, id, 148138889Sjdp resinfo->language, 0); 148238889Sjdp r->type = RES_TYPE_RCDATA; 148338889Sjdp r->u.rcdata = data; 148438889Sjdp r->res_info = *resinfo; 148538889Sjdp} 148638889Sjdp 148738889Sjdp/* Create an rcdata item holding a string. */ 148838889Sjdp 1489218822Sdimrc_rcdata_item * 1490218822Sdimdefine_rcdata_string (const char *string, rc_uint_type len) 149138889Sjdp{ 1492218822Sdim rc_rcdata_item *ri; 149338889Sjdp char *s; 149438889Sjdp 1495218822Sdim ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 149638889Sjdp ri->next = NULL; 149738889Sjdp ri->type = RCDATA_STRING; 149838889Sjdp ri->u.string.length = len; 149938889Sjdp s = (char *) res_alloc (len); 150038889Sjdp memcpy (s, string, len); 150138889Sjdp ri->u.string.s = s; 150238889Sjdp 150338889Sjdp return ri; 150438889Sjdp} 150538889Sjdp 1506218822Sdim/* Create an rcdata item holding a unicode string. */ 1507218822Sdim 1508218822Sdimrc_rcdata_item * 1509218822Sdimdefine_rcdata_unistring (const unichar *string, rc_uint_type len) 1510218822Sdim{ 1511218822Sdim rc_rcdata_item *ri; 1512218822Sdim unichar *s; 1513218822Sdim 1514218822Sdim ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 1515218822Sdim ri->next = NULL; 1516218822Sdim ri->type = RCDATA_WSTRING; 1517218822Sdim ri->u.wstring.length = len; 1518218822Sdim s = (unichar *) res_alloc (len * sizeof (unichar)); 1519218822Sdim memcpy (s, string, len * sizeof (unichar)); 1520218822Sdim ri->u.wstring.w = s; 1521218822Sdim 1522218822Sdim return ri; 1523218822Sdim} 1524218822Sdim 152538889Sjdp/* Create an rcdata item holding a number. */ 152638889Sjdp 1527218822Sdimrc_rcdata_item * 1528218822Sdimdefine_rcdata_number (rc_uint_type val, int dword) 152938889Sjdp{ 1530218822Sdim rc_rcdata_item *ri; 153138889Sjdp 1532218822Sdim ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 153338889Sjdp ri->next = NULL; 153438889Sjdp ri->type = dword ? RCDATA_DWORD : RCDATA_WORD; 153538889Sjdp ri->u.word = val; 153638889Sjdp 153738889Sjdp return ri; 153838889Sjdp} 153938889Sjdp 154038889Sjdp/* Define a stringtable resource. This is called for each string 154138889Sjdp which appears in a STRINGTABLE statement. */ 154238889Sjdp 154338889Sjdpvoid 1544218822Sdimdefine_stringtable (const rc_res_res_info *resinfo, 1545218822Sdim rc_uint_type stringid, const unichar *string) 154638889Sjdp{ 1547218822Sdim rc_res_id id; 1548218822Sdim rc_res_resource *r; 154938889Sjdp 155038889Sjdp id.named = 0; 155138889Sjdp id.u.id = (stringid >> 4) + 1; 155238889Sjdp r = define_standard_resource (&resources, RT_STRING, id, 155338889Sjdp resinfo->language, 1); 155438889Sjdp 155538889Sjdp if (r->type == RES_TYPE_UNINITIALIZED) 155638889Sjdp { 155738889Sjdp int i; 155838889Sjdp 155938889Sjdp r->type = RES_TYPE_STRINGTABLE; 1560218822Sdim r->u.stringtable = ((rc_stringtable *) 1561218822Sdim res_alloc (sizeof (rc_stringtable))); 156238889Sjdp for (i = 0; i < 16; i++) 156338889Sjdp { 156438889Sjdp r->u.stringtable->strings[i].length = 0; 156538889Sjdp r->u.stringtable->strings[i].string = NULL; 156638889Sjdp } 156738889Sjdp 156838889Sjdp r->res_info = *resinfo; 156938889Sjdp } 157038889Sjdp 1571218822Sdim r->u.stringtable->strings[stringid & 0xf].length = unichar_len (string); 1572218822Sdim r->u.stringtable->strings[stringid & 0xf].string = unichar_dup (string); 157338889Sjdp} 157438889Sjdp 1575218822Sdimvoid 1576218822Sdimdefine_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height, 1577218822Sdim rc_toolbar_item *items) 1578218822Sdim{ 1579218822Sdim rc_toolbar *t; 1580218822Sdim rc_res_resource *r; 1581218822Sdim 1582218822Sdim t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); 1583218822Sdim t->button_width = width; 1584218822Sdim t->button_height = height; 1585218822Sdim t->nitems = 0; 1586218822Sdim t->items = items; 1587218822Sdim while (items != NULL) 1588218822Sdim { 1589218822Sdim t->nitems+=1; 1590218822Sdim items = items->next; 1591218822Sdim } 1592218822Sdim r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0); 1593218822Sdim r->type = RES_TYPE_TOOLBAR; 1594218822Sdim r->u.toolbar = t; 1595218822Sdim r->res_info = *resinfo; 1596218822Sdim} 1597218822Sdim 159838889Sjdp/* Define a user data resource where the data is in the rc file. */ 159938889Sjdp 160038889Sjdpvoid 1601218822Sdimdefine_user_data (rc_res_id id, rc_res_id type, 1602218822Sdim const rc_res_res_info *resinfo, 1603218822Sdim rc_rcdata_item *data) 160438889Sjdp{ 1605218822Sdim rc_res_id ids[3]; 1606218822Sdim rc_res_resource *r; 1607218822Sdim bfd_byte *pb_data; 1608218822Sdim rc_uint_type len_data; 160938889Sjdp 1610218822Sdim /* We have to check if the binary data is parsed specially. */ 1611218822Sdim if (type.named == 0) 1612218822Sdim { 1613218822Sdim switch (type.u.id) 1614218822Sdim { 1615218822Sdim case RT_FONTDIR: 1616218822Sdim define_fontdir_rcdata (id, resinfo, data); 1617218822Sdim return; 1618218822Sdim case RT_FONT: 1619218822Sdim define_font_rcdata (id, resinfo, data); 1620218822Sdim return; 1621218822Sdim case RT_ICON: 1622218822Sdim define_icon_rcdata (id, resinfo, data); 1623218822Sdim return; 1624218822Sdim case RT_BITMAP: 1625218822Sdim define_bitmap_rcdata (id, resinfo, data); 1626218822Sdim return; 1627218822Sdim case RT_CURSOR: 1628218822Sdim define_cursor_rcdata (id, resinfo, data); 1629218822Sdim return; 1630218822Sdim case RT_GROUP_ICON: 1631218822Sdim define_group_icon_rcdata (id, resinfo, data); 1632218822Sdim return; 1633218822Sdim case RT_GROUP_CURSOR: 1634218822Sdim define_group_cursor_rcdata (id, resinfo, data); 1635218822Sdim return; 1636218822Sdim case RT_MESSAGETABLE: 1637218822Sdim define_messagetable_rcdata (id, resinfo, data); 1638218822Sdim return; 1639218822Sdim default: 1640218822Sdim /* Treat as normal user-data. */ 1641218822Sdim break; 1642218822Sdim } 1643218822Sdim } 164438889Sjdp ids[0] = type; 164538889Sjdp ids[1] = id; 164638889Sjdp ids[2].named = 0; 164738889Sjdp ids[2].u.id = resinfo->language; 164838889Sjdp 1649218822Sdim r = define_resource (& resources, 3, ids, 0); 165038889Sjdp r->type = RES_TYPE_USERDATA; 1651218822Sdim r->u.userdata = ((rc_rcdata_item *) 1652218822Sdim res_alloc (sizeof (rc_rcdata_item))); 1653218822Sdim r->u.userdata->next = NULL; 1654218822Sdim r->u.userdata->type = RCDATA_BUFFER; 1655218822Sdim pb_data = rcdata_render_as_buffer (data, &len_data); 1656218822Sdim r->u.userdata->u.buffer.length = len_data; 1657218822Sdim r->u.userdata->u.buffer.data = pb_data; 165838889Sjdp r->res_info = *resinfo; 165938889Sjdp} 166038889Sjdp 1661218822Sdimvoid 1662218822Sdimdefine_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo, 1663218822Sdim const char *filename) 1664218822Sdim{ 1665218822Sdim rc_rcdata_item *ri; 1666218822Sdim FILE *e; 1667218822Sdim char *real_filename; 1668218822Sdim struct stat s; 1669218822Sdim bfd_byte *data; 1670218822Sdim 1671218822Sdim e = open_file_search (filename, FOPEN_RB, "file", &real_filename); 1672218822Sdim 1673218822Sdim 1674218822Sdim if (stat (real_filename, &s) < 0) 1675218822Sdim fatal (_("stat failed on file `%s': %s"), real_filename, 1676218822Sdim strerror (errno)); 1677218822Sdim 1678218822Sdim data = (bfd_byte *) res_alloc (s.st_size); 1679218822Sdim 1680218822Sdim get_data (e, data, s.st_size, real_filename); 1681218822Sdim 1682218822Sdim fclose (e); 1683218822Sdim free (real_filename); 1684218822Sdim 1685218822Sdim ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 1686218822Sdim ri->next = NULL; 1687218822Sdim ri->type = RCDATA_BUFFER; 1688218822Sdim ri->u.buffer.length = s.st_size; 1689218822Sdim ri->u.buffer.data = data; 1690218822Sdim 1691218822Sdim define_rcdata (id, resinfo, ri); 1692218822Sdim} 1693218822Sdim 169438889Sjdp/* Define a user data resource where the data is in a file. */ 169538889Sjdp 169638889Sjdpvoid 1697218822Sdimdefine_user_file (rc_res_id id, rc_res_id type, 1698218822Sdim const rc_res_res_info *resinfo, const char *filename) 169938889Sjdp{ 170038889Sjdp FILE *e; 170138889Sjdp char *real_filename; 170238889Sjdp struct stat s; 1703218822Sdim bfd_byte *data; 1704218822Sdim rc_res_id ids[3]; 1705218822Sdim rc_res_resource *r; 170638889Sjdp 1707218822Sdim e = open_file_search (filename, FOPEN_RB, "file", &real_filename); 170838889Sjdp 170938889Sjdp if (stat (real_filename, &s) < 0) 1710218822Sdim fatal (_("stat failed on file `%s': %s"), real_filename, 171138889Sjdp strerror (errno)); 171238889Sjdp 1713218822Sdim data = (bfd_byte *) res_alloc (s.st_size); 171438889Sjdp 171538889Sjdp get_data (e, data, s.st_size, real_filename); 171638889Sjdp 171738889Sjdp fclose (e); 171838889Sjdp free (real_filename); 171938889Sjdp 172038889Sjdp ids[0] = type; 172138889Sjdp ids[1] = id; 172238889Sjdp ids[2].named = 0; 172338889Sjdp ids[2].u.id = resinfo->language; 172438889Sjdp 172538889Sjdp r = define_resource (&resources, 3, ids, 0); 172638889Sjdp r->type = RES_TYPE_USERDATA; 1727218822Sdim r->u.userdata = ((rc_rcdata_item *) 1728218822Sdim res_alloc (sizeof (rc_rcdata_item))); 172938889Sjdp r->u.userdata->next = NULL; 173038889Sjdp r->u.userdata->type = RCDATA_BUFFER; 173138889Sjdp r->u.userdata->u.buffer.length = s.st_size; 173238889Sjdp r->u.userdata->u.buffer.data = data; 173338889Sjdp r->res_info = *resinfo; 173438889Sjdp} 173538889Sjdp 173638889Sjdp/* Define a versioninfo resource. */ 173738889Sjdp 173838889Sjdpvoid 1739218822Sdimdefine_versioninfo (rc_res_id id, rc_uint_type language, 1740218822Sdim rc_fixed_versioninfo *fixedverinfo, 1741218822Sdim rc_ver_info *verinfo) 174238889Sjdp{ 1743218822Sdim rc_res_resource *r; 174438889Sjdp 174538889Sjdp r = define_standard_resource (&resources, RT_VERSION, id, language, 0); 174638889Sjdp r->type = RES_TYPE_VERSIONINFO; 1747218822Sdim r->u.versioninfo = ((rc_versioninfo *) 1748218822Sdim res_alloc (sizeof (rc_versioninfo))); 174938889Sjdp r->u.versioninfo->fixed = fixedverinfo; 175038889Sjdp r->u.versioninfo->var = verinfo; 175138889Sjdp r->res_info.language = language; 175238889Sjdp} 175338889Sjdp 175438889Sjdp/* Add string version info to a list of version information. */ 175538889Sjdp 1756218822Sdimrc_ver_info * 1757218822Sdimappend_ver_stringfileinfo (rc_ver_info *verinfo, const char *language, 1758218822Sdim rc_ver_stringinfo *strings) 175938889Sjdp{ 1760218822Sdim rc_ver_info *vi, **pp; 176138889Sjdp 1762218822Sdim vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); 176338889Sjdp vi->next = NULL; 176438889Sjdp vi->type = VERINFO_STRING; 1765218822Sdim unicode_from_ascii ((rc_uint_type *) NULL, &vi->u.string.language, language); 176638889Sjdp vi->u.string.strings = strings; 176738889Sjdp 176838889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 176938889Sjdp ; 177038889Sjdp *pp = vi; 177138889Sjdp 177238889Sjdp return verinfo; 177338889Sjdp} 177438889Sjdp 177538889Sjdp/* Add variable version info to a list of version information. */ 177638889Sjdp 1777218822Sdimrc_ver_info * 1778218822Sdimappend_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key, 1779218822Sdim rc_ver_varinfo *var) 178038889Sjdp{ 1781218822Sdim rc_ver_info *vi, **pp; 178238889Sjdp 1783218822Sdim vi = (rc_ver_info *) res_alloc (sizeof *vi); 178438889Sjdp vi->next = NULL; 178538889Sjdp vi->type = VERINFO_VAR; 1786218822Sdim vi->u.var.key = unichar_dup (key); 178738889Sjdp vi->u.var.var = var; 178838889Sjdp 178938889Sjdp for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) 179038889Sjdp ; 179138889Sjdp *pp = vi; 179238889Sjdp 179338889Sjdp return verinfo; 179438889Sjdp} 179538889Sjdp 179638889Sjdp/* Append version string information to a list. */ 179738889Sjdp 1798218822Sdimrc_ver_stringinfo * 1799218822Sdimappend_verval (rc_ver_stringinfo *strings, const unichar *key, 1800218822Sdim const unichar *value) 180138889Sjdp{ 1802218822Sdim rc_ver_stringinfo *vs, **pp; 180338889Sjdp 1804218822Sdim vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); 180538889Sjdp vs->next = NULL; 1806218822Sdim vs->key = unichar_dup (key); 1807218822Sdim vs->value = unichar_dup (value); 180838889Sjdp 180938889Sjdp for (pp = &strings; *pp != NULL; pp = &(*pp)->next) 181038889Sjdp ; 181138889Sjdp *pp = vs; 181238889Sjdp 181338889Sjdp return strings; 181438889Sjdp} 181538889Sjdp 181638889Sjdp/* Append version variable information to a list. */ 181738889Sjdp 1818218822Sdimrc_ver_varinfo * 1819218822Sdimappend_vertrans (rc_ver_varinfo *var, rc_uint_type language, 1820218822Sdim rc_uint_type charset) 182138889Sjdp{ 1822218822Sdim rc_ver_varinfo *vv, **pp; 182338889Sjdp 1824218822Sdim vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); 182538889Sjdp vv->next = NULL; 182638889Sjdp vv->language = language; 182738889Sjdp vv->charset = charset; 182838889Sjdp 182938889Sjdp for (pp = &var; *pp != NULL; pp = &(*pp)->next) 183038889Sjdp ; 183138889Sjdp *pp = vv; 183238889Sjdp 183338889Sjdp return var; 183438889Sjdp} 183538889Sjdp 183638889Sjdp/* Local functions used to write out an rc file. */ 183738889Sjdp 1838130561Sobrienstatic void indent (FILE *, int); 1839218822Sdimstatic void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *, 1840218822Sdim const rc_res_id *, rc_uint_type *, int); 1841218822Sdimstatic void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *, 1842218822Sdim const rc_res_id *, rc_uint_type *, int); 1843218822Sdimstatic void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *, 1844218822Sdim const rc_res_resource *, rc_uint_type *); 1845218822Sdimstatic void write_rc_accelerators (FILE *, const rc_accelerator *); 1846218822Sdimstatic void write_rc_cursor (FILE *, const rc_cursor *); 1847218822Sdimstatic void write_rc_group_cursor (FILE *, const rc_group_cursor *); 1848218822Sdimstatic void write_rc_dialog (FILE *, const rc_dialog *); 1849218822Sdimstatic void write_rc_dialog_control (FILE *, const rc_dialog_control *); 1850218822Sdimstatic void write_rc_fontdir (FILE *, const rc_fontdir *); 1851218822Sdimstatic void write_rc_group_icon (FILE *, const rc_group_icon *); 1852218822Sdimstatic void write_rc_menu (FILE *, const rc_menu *, int); 1853218822Sdimstatic void write_rc_toolbar (FILE *, const rc_toolbar *); 1854218822Sdimstatic void write_rc_menuitems (FILE *, const rc_menuitem *, int, int); 1855218822Sdimstatic void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *); 185638889Sjdp 1857218822Sdimstatic void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int); 1858218822Sdimstatic void write_rc_rcdata (FILE *, const rc_rcdata_item *, int); 1859218822Sdimstatic void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *); 1860218822Sdimstatic void write_rc_versioninfo (FILE *, const rc_versioninfo *); 1861218822Sdim 186238889Sjdp/* Indent a given number of spaces. */ 186338889Sjdp 186438889Sjdpstatic void 1865130561Sobrienindent (FILE *e, int c) 186638889Sjdp{ 186738889Sjdp int i; 186838889Sjdp 186938889Sjdp for (i = 0; i < c; i++) 187038889Sjdp putc (' ', e); 187138889Sjdp} 187238889Sjdp 187338889Sjdp/* Dump the resources we have read in the format of an rc file. 187438889Sjdp 1875218822Sdim Reasoned by the fact, that some resources need to be stored into file and 1876218822Sdim refer to that file, we use the user-data model for that to express it binary 1877218822Sdim without the need to store it somewhere externally. */ 187838889Sjdp 187938889Sjdpvoid 1880218822Sdimwrite_rc_file (const char *filename, const rc_res_directory *resources) 188138889Sjdp{ 188238889Sjdp FILE *e; 1883218822Sdim rc_uint_type language; 188438889Sjdp 188538889Sjdp if (filename == NULL) 188638889Sjdp e = stdout; 188738889Sjdp else 188838889Sjdp { 188938889Sjdp e = fopen (filename, FOPEN_WT); 189038889Sjdp if (e == NULL) 189160484Sobrien fatal (_("can't open `%s' for output: %s"), filename, strerror (errno)); 189238889Sjdp } 189338889Sjdp 1894218822Sdim language = (rc_uint_type) ((bfd_signed_vma) -1); 1895218822Sdim write_rc_directory (e, resources, (const rc_res_id *) NULL, 1896218822Sdim (const rc_res_id *) NULL, &language, 1); 189738889Sjdp} 189838889Sjdp 189938889Sjdp/* Write out a directory. E is the file to write to. RD is the 190038889Sjdp directory. TYPE is a pointer to the level 1 ID which serves as the 190138889Sjdp resource type. NAME is a pointer to the level 2 ID which serves as 190238889Sjdp an individual resource name. LANGUAGE is a pointer to the current 190338889Sjdp language. LEVEL is the level in the tree. */ 190438889Sjdp 190538889Sjdpstatic void 1906218822Sdimwrite_rc_directory (FILE *e, const rc_res_directory *rd, 1907218822Sdim const rc_res_id *type, const rc_res_id *name, 1908218822Sdim rc_uint_type *language, int level) 190938889Sjdp{ 1910218822Sdim const rc_res_entry *re; 191138889Sjdp 191238889Sjdp /* Print out some COFF information that rc files can't represent. */ 1913218822Sdim if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0) 1914218822Sdim { 1915218822Sdim wr_printcomment (e, "COFF information not part of RC"); 191638889Sjdp if (rd->time != 0) 1917218822Sdim wr_printcomment (e, "Time stamp: %u", rd->time); 191838889Sjdp if (rd->characteristics != 0) 1919218822Sdim wr_printcomment (e, "Characteristics: %u", rd->characteristics); 192038889Sjdp if (rd->major != 0 || rd->minor != 0) 1921218822Sdim wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor); 1922218822Sdim } 192338889Sjdp 192438889Sjdp for (re = rd->entries; re != NULL; re = re->next) 192538889Sjdp { 192638889Sjdp switch (level) 192738889Sjdp { 192838889Sjdp case 1: 192938889Sjdp /* If we're at level 1, the key of this resource is the 193038889Sjdp type. This normally duplicates the information we have 193138889Sjdp stored with the resource itself, but we need to remember 193238889Sjdp the type if this is a user define resource type. */ 193338889Sjdp type = &re->id; 193438889Sjdp break; 193538889Sjdp 193638889Sjdp case 2: 193738889Sjdp /* If we're at level 2, the key of this resource is the name 193899461Sobrien we are going to use in the rc printout. */ 193938889Sjdp name = &re->id; 194038889Sjdp break; 194138889Sjdp 194238889Sjdp case 3: 194338889Sjdp /* If we're at level 3, then this key represents a language. 194438889Sjdp Use it to update the current language. */ 194538889Sjdp if (! re->id.named 194660484Sobrien && re->id.u.id != (unsigned long) (unsigned int) *language 194738889Sjdp && (re->id.u.id & 0xffff) == re->id.u.id) 194838889Sjdp { 1949218822Sdim wr_print (e, "LANGUAGE %u, %u\n", 1950104834Sobrien re->id.u.id & ((1 << SUBLANG_SHIFT) - 1), 195199461Sobrien (re->id.u.id >> SUBLANG_SHIFT) & 0xff); 195238889Sjdp *language = re->id.u.id; 195338889Sjdp } 195438889Sjdp break; 195538889Sjdp 195638889Sjdp default: 195738889Sjdp break; 195838889Sjdp } 195938889Sjdp 196038889Sjdp if (re->subdir) 196138889Sjdp write_rc_subdir (e, re, type, name, language, level); 196238889Sjdp else 196338889Sjdp { 196438889Sjdp if (level == 3) 196538889Sjdp { 196638889Sjdp /* This is the normal case: the three levels are 196738889Sjdp TYPE/NAME/LANGUAGE. NAME will have been set at level 196838889Sjdp 2, and represents the name to use. We probably just 196938889Sjdp set LANGUAGE, and it will probably match what the 197038889Sjdp resource itself records if anything. */ 197138889Sjdp write_rc_resource (e, type, name, re->u.res, language); 197238889Sjdp } 197338889Sjdp else 197438889Sjdp { 1975218822Sdim wr_printcomment (e, "Resource at unexpected level %d", level); 1976218822Sdim write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res, 197738889Sjdp language); 197838889Sjdp } 197938889Sjdp } 198038889Sjdp } 1981218822Sdim if (rd->entries == NULL) 1982218822Sdim { 1983218822Sdim wr_print_flush (e); 1984218822Sdim } 198538889Sjdp} 198638889Sjdp 198738889Sjdp/* Write out a subdirectory entry. E is the file to write to. RE is 198838889Sjdp the subdirectory entry. TYPE and NAME are pointers to higher level 198938889Sjdp IDs, or NULL. LANGUAGE is a pointer to the current language. 199038889Sjdp LEVEL is the level in the tree. */ 199138889Sjdp 199238889Sjdpstatic void 1993218822Sdimwrite_rc_subdir (FILE *e, const rc_res_entry *re, 1994218822Sdim const rc_res_id *type, const rc_res_id *name, 1995218822Sdim rc_uint_type *language, int level) 199638889Sjdp{ 199738889Sjdp fprintf (e, "\n"); 199838889Sjdp switch (level) 199938889Sjdp { 200038889Sjdp case 1: 2001218822Sdim wr_printcomment (e, "Type: "); 200238889Sjdp if (re->id.named) 200338889Sjdp res_id_print (e, re->id, 1); 200438889Sjdp else 200538889Sjdp { 200638889Sjdp const char *s; 200738889Sjdp 200838889Sjdp switch (re->id.u.id) 200938889Sjdp { 201038889Sjdp case RT_CURSOR: s = "cursor"; break; 201138889Sjdp case RT_BITMAP: s = "bitmap"; break; 201238889Sjdp case RT_ICON: s = "icon"; break; 201338889Sjdp case RT_MENU: s = "menu"; break; 201438889Sjdp case RT_DIALOG: s = "dialog"; break; 201538889Sjdp case RT_STRING: s = "stringtable"; break; 201638889Sjdp case RT_FONTDIR: s = "fontdir"; break; 201738889Sjdp case RT_FONT: s = "font"; break; 201860484Sobrien case RT_ACCELERATOR: s = "accelerators"; break; 201938889Sjdp case RT_RCDATA: s = "rcdata"; break; 202038889Sjdp case RT_MESSAGETABLE: s = "messagetable"; break; 202138889Sjdp case RT_GROUP_CURSOR: s = "group cursor"; break; 202238889Sjdp case RT_GROUP_ICON: s = "group icon"; break; 202338889Sjdp case RT_VERSION: s = "version"; break; 202438889Sjdp case RT_DLGINCLUDE: s = "dlginclude"; break; 202538889Sjdp case RT_PLUGPLAY: s = "plugplay"; break; 202638889Sjdp case RT_VXD: s = "vxd"; break; 202738889Sjdp case RT_ANICURSOR: s = "anicursor"; break; 202838889Sjdp case RT_ANIICON: s = "aniicon"; break; 2029218822Sdim case RT_TOOLBAR: s = "toolbar"; break; 2030218822Sdim case RT_HTML: s = "html"; break; 203138889Sjdp default: s = NULL; break; 203238889Sjdp } 203338889Sjdp 203438889Sjdp if (s != NULL) 203538889Sjdp fprintf (e, "%s", s); 203638889Sjdp else 203738889Sjdp res_id_print (e, re->id, 1); 203838889Sjdp } 203938889Sjdp break; 204038889Sjdp 204138889Sjdp case 2: 2042218822Sdim wr_printcomment (e, "Name: "); 204338889Sjdp res_id_print (e, re->id, 1); 204438889Sjdp break; 204538889Sjdp 204638889Sjdp case 3: 2047218822Sdim wr_printcomment (e, "Language: "); 204838889Sjdp res_id_print (e, re->id, 1); 204938889Sjdp break; 205038889Sjdp 205138889Sjdp default: 2052218822Sdim wr_printcomment (e, "Level %d: ", level); 205338889Sjdp res_id_print (e, re->id, 1); 2054104834Sobrien } 205538889Sjdp 205638889Sjdp write_rc_directory (e, re->u.dir, type, name, language, level + 1); 205738889Sjdp} 205838889Sjdp 205938889Sjdp/* Write out a single resource. E is the file to write to. TYPE is a 206038889Sjdp pointer to the type of the resource. NAME is a pointer to the name 206138889Sjdp of the resource; it will be NULL if there is a level mismatch. RES 206238889Sjdp is the resource data. LANGUAGE is a pointer to the current 206338889Sjdp language. */ 206438889Sjdp 206538889Sjdpstatic void 2066218822Sdimwrite_rc_resource (FILE *e, const rc_res_id *type, 2067218822Sdim const rc_res_id *name, const rc_res_resource *res, 2068218822Sdim rc_uint_type *language) 206938889Sjdp{ 207038889Sjdp const char *s; 207138889Sjdp int rt; 207238889Sjdp int menuex = 0; 207338889Sjdp 207438889Sjdp switch (res->type) 207538889Sjdp { 207638889Sjdp default: 207738889Sjdp abort (); 207838889Sjdp 207938889Sjdp case RES_TYPE_ACCELERATOR: 2080218822Sdim s = "ACCELERATORS"; 208160484Sobrien rt = RT_ACCELERATOR; 208238889Sjdp break; 208338889Sjdp 208438889Sjdp case RES_TYPE_BITMAP: 2085218822Sdim s = "2 /* RT_BITMAP */"; 208638889Sjdp rt = RT_BITMAP; 208738889Sjdp break; 208838889Sjdp 208938889Sjdp case RES_TYPE_CURSOR: 2090218822Sdim s = "1 /* RT_CURSOR */"; 209138889Sjdp rt = RT_CURSOR; 209238889Sjdp break; 209338889Sjdp 209438889Sjdp case RES_TYPE_GROUP_CURSOR: 2095218822Sdim s = "12 /* RT_GROUP_CURSOR */"; 209638889Sjdp rt = RT_GROUP_CURSOR; 209738889Sjdp break; 209838889Sjdp 209938889Sjdp case RES_TYPE_DIALOG: 210038889Sjdp if (extended_dialog (res->u.dialog)) 210138889Sjdp s = "DIALOGEX"; 210238889Sjdp else 210338889Sjdp s = "DIALOG"; 210438889Sjdp rt = RT_DIALOG; 210538889Sjdp break; 210638889Sjdp 210738889Sjdp case RES_TYPE_FONT: 2108218822Sdim s = "8 /* RT_FONT */"; 210938889Sjdp rt = RT_FONT; 211038889Sjdp break; 211138889Sjdp 211238889Sjdp case RES_TYPE_FONTDIR: 2113218822Sdim s = "7 /* RT_FONTDIR */"; 211438889Sjdp rt = RT_FONTDIR; 211538889Sjdp break; 211638889Sjdp 211738889Sjdp case RES_TYPE_ICON: 2118218822Sdim s = "3 /* RT_ICON */"; 211938889Sjdp rt = RT_ICON; 212038889Sjdp break; 212138889Sjdp 212238889Sjdp case RES_TYPE_GROUP_ICON: 2123218822Sdim s = "14 /* RT_GROUP_ICON */"; 212438889Sjdp rt = RT_GROUP_ICON; 212538889Sjdp break; 212638889Sjdp 212738889Sjdp case RES_TYPE_MENU: 212838889Sjdp if (extended_menu (res->u.menu)) 212938889Sjdp { 213038889Sjdp s = "MENUEX"; 213138889Sjdp menuex = 1; 213238889Sjdp } 213338889Sjdp else 213438889Sjdp { 213538889Sjdp s = "MENU"; 213638889Sjdp menuex = 0; 213738889Sjdp } 213838889Sjdp rt = RT_MENU; 213938889Sjdp break; 214038889Sjdp 214138889Sjdp case RES_TYPE_MESSAGETABLE: 2142218822Sdim s = "11 /* RT_MESSAGETABLE */"; 214338889Sjdp rt = RT_MESSAGETABLE; 214438889Sjdp break; 214538889Sjdp 214638889Sjdp case RES_TYPE_RCDATA: 214738889Sjdp s = "RCDATA"; 214838889Sjdp rt = RT_RCDATA; 214938889Sjdp break; 215038889Sjdp 215138889Sjdp case RES_TYPE_STRINGTABLE: 215238889Sjdp s = "STRINGTABLE"; 215338889Sjdp rt = RT_STRING; 215438889Sjdp break; 215538889Sjdp 215638889Sjdp case RES_TYPE_USERDATA: 215738889Sjdp s = NULL; 215838889Sjdp rt = 0; 215938889Sjdp break; 216038889Sjdp 216138889Sjdp case RES_TYPE_VERSIONINFO: 216238889Sjdp s = "VERSIONINFO"; 216338889Sjdp rt = RT_VERSION; 216438889Sjdp break; 2165218822Sdim 2166218822Sdim case RES_TYPE_TOOLBAR: 2167218822Sdim s = "TOOLBAR"; 2168218822Sdim rt = RT_TOOLBAR; 2169218822Sdim break; 217038889Sjdp } 217138889Sjdp 217238889Sjdp if (rt != 0 217338889Sjdp && type != NULL 217460484Sobrien && (type->named || type->u.id != (unsigned long) rt)) 217538889Sjdp { 2176218822Sdim wr_printcomment (e, "Unexpected resource type mismatch: "); 217738889Sjdp res_id_print (e, *type, 1); 217838889Sjdp fprintf (e, " != %d", rt); 217938889Sjdp } 218038889Sjdp 218138889Sjdp if (res->coff_info.codepage != 0) 2182218822Sdim wr_printcomment (e, "Code page: %u", res->coff_info.codepage); 218338889Sjdp if (res->coff_info.reserved != 0) 2184218822Sdim wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved); 218538889Sjdp 2186218822Sdim wr_print (e, "\n"); 2187218822Sdim if (rt == RT_STRING) 2188218822Sdim ; 2189218822Sdim else 2190218822Sdim { 219138889Sjdp if (name != NULL) 2192218822Sdim res_id_print (e, *name, 1); 219338889Sjdp else 219438889Sjdp fprintf (e, "??Unknown-Name??"); 2195218822Sdim fprintf (e, " "); 2196218822Sdim } 219738889Sjdp 219838889Sjdp if (s != NULL) 219938889Sjdp fprintf (e, "%s", s); 220038889Sjdp else if (type != NULL) 2201218822Sdim { 2202218822Sdim if (type->named == 0) 2203218822Sdim { 2204218822Sdim#define PRINT_RT_NAME(NAME) case NAME: \ 2205218822Sdim fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \ 2206218822Sdim break 2207218822Sdim 2208218822Sdim switch (type->u.id) 2209218822Sdim { 2210218822Sdim default: 221138889Sjdp res_id_print (e, *type, 0); 2212218822Sdim break; 2213218822Sdim 2214218822Sdim PRINT_RT_NAME(RT_MANIFEST); 2215218822Sdim PRINT_RT_NAME(RT_ANICURSOR); 2216218822Sdim PRINT_RT_NAME(RT_ANIICON); 2217218822Sdim PRINT_RT_NAME(RT_RCDATA); 2218218822Sdim PRINT_RT_NAME(RT_ICON); 2219218822Sdim PRINT_RT_NAME(RT_CURSOR); 2220218822Sdim PRINT_RT_NAME(RT_BITMAP); 2221218822Sdim PRINT_RT_NAME(RT_PLUGPLAY); 2222218822Sdim PRINT_RT_NAME(RT_VXD); 2223218822Sdim PRINT_RT_NAME(RT_FONT); 2224218822Sdim PRINT_RT_NAME(RT_FONTDIR); 2225218822Sdim PRINT_RT_NAME(RT_HTML); 2226218822Sdim PRINT_RT_NAME(RT_MESSAGETABLE); 2227218822Sdim PRINT_RT_NAME(RT_DLGINCLUDE); 2228218822Sdim PRINT_RT_NAME(RT_DLGINIT); 2229218822Sdim } 2230218822Sdim#undef PRINT_RT_NAME 2231218822Sdim } 2232218822Sdim else 2233218822Sdim res_id_print (e, *type, 1); 2234218822Sdim } 223538889Sjdp else 223638889Sjdp fprintf (e, "??Unknown-Type??"); 223738889Sjdp 223838889Sjdp if (res->res_info.memflags != 0) 223938889Sjdp { 224038889Sjdp if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0) 224138889Sjdp fprintf (e, " MOVEABLE"); 224238889Sjdp if ((res->res_info.memflags & MEMFLAG_PURE) != 0) 224338889Sjdp fprintf (e, " PURE"); 224438889Sjdp if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0) 224538889Sjdp fprintf (e, " PRELOAD"); 224638889Sjdp if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0) 224738889Sjdp fprintf (e, " DISCARDABLE"); 224838889Sjdp } 224938889Sjdp 225038889Sjdp if (res->type == RES_TYPE_DIALOG) 225138889Sjdp { 2252218822Sdim fprintf (e, " %d, %d, %d, %d", 2253218822Sdim (int) res->u.dialog->x, (int) res->u.dialog->y, 2254218822Sdim (int) res->u.dialog->width, (int) res->u.dialog->height); 225538889Sjdp if (res->u.dialog->ex != NULL 225638889Sjdp && res->u.dialog->ex->help != 0) 2257218822Sdim fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help); 225838889Sjdp } 2259218822Sdim else if (res->type == RES_TYPE_TOOLBAR) 2260218822Sdim { 2261218822Sdim fprintf (e, " %d, %d", (int) res->u.toolbar->button_width, 2262218822Sdim (int) res->u.toolbar->button_height); 2263218822Sdim } 226438889Sjdp 226538889Sjdp fprintf (e, "\n"); 226638889Sjdp 226738889Sjdp if ((res->res_info.language != 0 && res->res_info.language != *language) 226838889Sjdp || res->res_info.characteristics != 0 226938889Sjdp || res->res_info.version != 0) 227038889Sjdp { 227138889Sjdp int modifiers; 227238889Sjdp 227338889Sjdp switch (res->type) 227438889Sjdp { 227538889Sjdp case RES_TYPE_ACCELERATOR: 227638889Sjdp case RES_TYPE_DIALOG: 227738889Sjdp case RES_TYPE_MENU: 227838889Sjdp case RES_TYPE_RCDATA: 227938889Sjdp case RES_TYPE_STRINGTABLE: 228038889Sjdp modifiers = 1; 228138889Sjdp break; 228238889Sjdp 228338889Sjdp default: 228438889Sjdp modifiers = 0; 228538889Sjdp break; 228638889Sjdp } 228738889Sjdp 228838889Sjdp if (res->res_info.language != 0 && res->res_info.language != *language) 228938889Sjdp fprintf (e, "%sLANGUAGE %d, %d\n", 229038889Sjdp modifiers ? "// " : "", 2291218822Sdim (int) res->res_info.language & ((1<<SUBLANG_SHIFT)-1), 2292218822Sdim (int) (res->res_info.language >> SUBLANG_SHIFT) & 0xff); 229338889Sjdp if (res->res_info.characteristics != 0) 2294218822Sdim fprintf (e, "%sCHARACTERISTICS %u\n", 229538889Sjdp modifiers ? "// " : "", 2296218822Sdim (unsigned int) res->res_info.characteristics); 229738889Sjdp if (res->res_info.version != 0) 2298218822Sdim fprintf (e, "%sVERSION %u\n", 229938889Sjdp modifiers ? "// " : "", 2300218822Sdim (unsigned int) res->res_info.version); 230138889Sjdp } 230238889Sjdp 230338889Sjdp switch (res->type) 230438889Sjdp { 230538889Sjdp default: 230638889Sjdp abort (); 230738889Sjdp 230838889Sjdp case RES_TYPE_ACCELERATOR: 230938889Sjdp write_rc_accelerators (e, res->u.acc); 231038889Sjdp break; 231138889Sjdp 231238889Sjdp case RES_TYPE_CURSOR: 231338889Sjdp write_rc_cursor (e, res->u.cursor); 231438889Sjdp break; 231538889Sjdp 231638889Sjdp case RES_TYPE_GROUP_CURSOR: 231738889Sjdp write_rc_group_cursor (e, res->u.group_cursor); 231838889Sjdp break; 231938889Sjdp 232038889Sjdp case RES_TYPE_DIALOG: 232138889Sjdp write_rc_dialog (e, res->u.dialog); 232238889Sjdp break; 232338889Sjdp 232438889Sjdp case RES_TYPE_FONTDIR: 232538889Sjdp write_rc_fontdir (e, res->u.fontdir); 232638889Sjdp break; 232738889Sjdp 232838889Sjdp case RES_TYPE_GROUP_ICON: 232938889Sjdp write_rc_group_icon (e, res->u.group_icon); 233038889Sjdp break; 233138889Sjdp 233238889Sjdp case RES_TYPE_MENU: 233338889Sjdp write_rc_menu (e, res->u.menu, menuex); 233438889Sjdp break; 233538889Sjdp 233638889Sjdp case RES_TYPE_RCDATA: 233738889Sjdp write_rc_rcdata (e, res->u.rcdata, 0); 233838889Sjdp break; 233938889Sjdp 234038889Sjdp case RES_TYPE_STRINGTABLE: 234138889Sjdp write_rc_stringtable (e, name, res->u.stringtable); 234238889Sjdp break; 234338889Sjdp 234438889Sjdp case RES_TYPE_USERDATA: 234538889Sjdp write_rc_rcdata (e, res->u.userdata, 0); 234638889Sjdp break; 234738889Sjdp 2348218822Sdim case RES_TYPE_TOOLBAR: 2349218822Sdim write_rc_toolbar (e, res->u.toolbar); 2350218822Sdim break; 2351218822Sdim 235238889Sjdp case RES_TYPE_VERSIONINFO: 235338889Sjdp write_rc_versioninfo (e, res->u.versioninfo); 235438889Sjdp break; 235538889Sjdp 235638889Sjdp case RES_TYPE_BITMAP: 235738889Sjdp case RES_TYPE_FONT: 235838889Sjdp case RES_TYPE_ICON: 2359218822Sdim write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0); 2360218822Sdim break; 236138889Sjdp case RES_TYPE_MESSAGETABLE: 2362218822Sdim write_rc_messagetable (e, res->u.data.length, res->u.data.data); 236338889Sjdp break; 236438889Sjdp } 236538889Sjdp} 236638889Sjdp 236738889Sjdp/* Write out accelerator information. */ 236838889Sjdp 236938889Sjdpstatic void 2370218822Sdimwrite_rc_accelerators (FILE *e, const rc_accelerator *accelerators) 237138889Sjdp{ 2372218822Sdim const rc_accelerator *acc; 237338889Sjdp 237438889Sjdp fprintf (e, "BEGIN\n"); 237538889Sjdp for (acc = accelerators; acc != NULL; acc = acc->next) 237638889Sjdp { 237738889Sjdp int printable; 237838889Sjdp 237938889Sjdp fprintf (e, " "); 238038889Sjdp 238138889Sjdp if ((acc->key & 0x7f) == acc->key 238289857Sobrien && ISPRINT (acc->key) 238338889Sjdp && (acc->flags & ACC_VIRTKEY) == 0) 238438889Sjdp { 2385218822Sdim fprintf (e, "\"%c\"", (char) acc->key); 238638889Sjdp printable = 1; 238738889Sjdp } 238838889Sjdp else 238938889Sjdp { 2390218822Sdim fprintf (e, "%d", (int) acc->key); 239138889Sjdp printable = 0; 239238889Sjdp } 239338889Sjdp 2394218822Sdim fprintf (e, ", %d", (int) acc->id); 239538889Sjdp 239638889Sjdp if (! printable) 239738889Sjdp { 239838889Sjdp if ((acc->flags & ACC_VIRTKEY) != 0) 239938889Sjdp fprintf (e, ", VIRTKEY"); 240038889Sjdp else 240138889Sjdp fprintf (e, ", ASCII"); 240238889Sjdp } 240338889Sjdp 240438889Sjdp if ((acc->flags & ACC_SHIFT) != 0) 240538889Sjdp fprintf (e, ", SHIFT"); 240638889Sjdp if ((acc->flags & ACC_CONTROL) != 0) 240738889Sjdp fprintf (e, ", CONTROL"); 240838889Sjdp if ((acc->flags & ACC_ALT) != 0) 240938889Sjdp fprintf (e, ", ALT"); 241038889Sjdp 241138889Sjdp fprintf (e, "\n"); 241238889Sjdp } 241338889Sjdp 241438889Sjdp fprintf (e, "END\n"); 241538889Sjdp} 241638889Sjdp 241738889Sjdp/* Write out cursor information. This would normally be in a separate 241838889Sjdp file, which the rc file would include. */ 241938889Sjdp 242038889Sjdpstatic void 2421218822Sdimwrite_rc_cursor (FILE *e, const rc_cursor *cursor) 242238889Sjdp{ 2423218822Sdim fprintf (e, "BEGIN\n"); 2424218822Sdim indent (e, 2); 2425218822Sdim fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d. */\n", 2426218822Sdim (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot, 2427218822Sdim (int) cursor->xhotspot, (int) cursor->yhotspot); 2428218822Sdim write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data, 2429218822Sdim 0, 0, 0); 2430218822Sdim fprintf (e, "END\n"); 243138889Sjdp} 243238889Sjdp 243338889Sjdp/* Write out group cursor data. This would normally be built from the 243438889Sjdp cursor data. */ 243538889Sjdp 243638889Sjdpstatic void 2437218822Sdimwrite_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor) 243838889Sjdp{ 2439218822Sdim const rc_group_cursor *gc; 2440218822Sdim int c; 244138889Sjdp 2442218822Sdim for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++) 2443218822Sdim ; 2444218822Sdim fprintf (e, "BEGIN\n"); 2445218822Sdim 2446218822Sdim indent (e, 2); 2447218822Sdim fprintf (e, "0, 2, %d%s\t /* Having %d items. */\n", c, (c != 0 ? "," : ""), c); 2448218822Sdim indent (e, 4); 2449218822Sdim fprintf (e, "/* width, height, planes, bits, bytes, index. */\n"); 2450218822Sdim 2451218822Sdim for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++) 245238889Sjdp { 2453218822Sdim indent (e, 4); 2454218822Sdim fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n", 2455218822Sdim (int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits, 2456218822Sdim (unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c); 2457218822Sdim fprintf (e, "/* width: %d; height %d; planes %d; bits %d. */\n", 2458218822Sdim (int) gc->width, (int) gc->height, (int) gc->planes, 2459218822Sdim (int) gc->bits); 246038889Sjdp } 2461218822Sdim fprintf (e, "END\n"); 246238889Sjdp} 246338889Sjdp 246438889Sjdp/* Write dialog data. */ 246538889Sjdp 246638889Sjdpstatic void 2467218822Sdimwrite_rc_dialog (FILE *e, const rc_dialog *dialog) 246838889Sjdp{ 2469218822Sdim const rc_dialog_control *control; 247038889Sjdp 2471218822Sdim fprintf (e, "STYLE 0x%x\n", dialog->style); 247299461Sobrien 247338889Sjdp if (dialog->exstyle != 0) 2474218822Sdim fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle); 247599461Sobrien 247638889Sjdp if ((dialog->class.named && dialog->class.u.n.length > 0) 247738889Sjdp || dialog->class.u.id != 0) 247838889Sjdp { 247938889Sjdp fprintf (e, "CLASS "); 248099461Sobrien res_id_print (e, dialog->class, 1); 248138889Sjdp fprintf (e, "\n"); 248238889Sjdp } 248399461Sobrien 248438889Sjdp if (dialog->caption != NULL) 248538889Sjdp { 2486218822Sdim fprintf (e, "CAPTION "); 2487218822Sdim unicode_print_quoted (e, dialog->caption, -1); 2488218822Sdim fprintf (e, "\n"); 248938889Sjdp } 249099461Sobrien 249138889Sjdp if ((dialog->menu.named && dialog->menu.u.n.length > 0) 249238889Sjdp || dialog->menu.u.id != 0) 249338889Sjdp { 249438889Sjdp fprintf (e, "MENU "); 249538889Sjdp res_id_print (e, dialog->menu, 0); 249638889Sjdp fprintf (e, "\n"); 249738889Sjdp } 249899461Sobrien 249938889Sjdp if (dialog->font != NULL) 250038889Sjdp { 2501218822Sdim fprintf (e, "FONT %d, ", (int) dialog->pointsize); 2502218822Sdim unicode_print_quoted (e, dialog->font, -1); 250338889Sjdp if (dialog->ex != NULL 250499461Sobrien && (dialog->ex->weight != 0 250599461Sobrien || dialog->ex->italic != 0 250699461Sobrien || dialog->ex->charset != 1)) 250799461Sobrien fprintf (e, ", %d, %d, %d", 2508218822Sdim (int) dialog->ex->weight, 2509218822Sdim (int) dialog->ex->italic, 2510218822Sdim (int) dialog->ex->charset); 251138889Sjdp fprintf (e, "\n"); 251238889Sjdp } 251338889Sjdp 251438889Sjdp fprintf (e, "BEGIN\n"); 251538889Sjdp 251638889Sjdp for (control = dialog->controls; control != NULL; control = control->next) 251738889Sjdp write_rc_dialog_control (e, control); 251838889Sjdp 251938889Sjdp fprintf (e, "END\n"); 252038889Sjdp} 252138889Sjdp 252238889Sjdp/* For each predefined control keyword, this table provides the class 252338889Sjdp and the style. */ 252438889Sjdp 252538889Sjdpstruct control_info 252638889Sjdp{ 252738889Sjdp const char *name; 252838889Sjdp unsigned short class; 252938889Sjdp unsigned long style; 253038889Sjdp}; 253138889Sjdp 253238889Sjdpstatic const struct control_info control_info[] = 253338889Sjdp{ 253438889Sjdp { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE }, 253538889Sjdp { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX }, 253638889Sjdp { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON }, 253738889Sjdp { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX }, 253838889Sjdp { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 }, 253938889Sjdp { "CTEXT", CTL_STATIC, SS_CENTER }, 254038889Sjdp { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON }, 254138889Sjdp { "EDITTEXT", CTL_EDIT, (unsigned long) -1 }, 254238889Sjdp { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX }, 254338889Sjdp { "ICON", CTL_STATIC, SS_ICON }, 254438889Sjdp { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 }, 254538889Sjdp { "LTEXT", CTL_STATIC, SS_LEFT }, 254638889Sjdp { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX }, 254738889Sjdp { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON }, 254838889Sjdp { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON }, 254938889Sjdp { "RTEXT", CTL_STATIC, SS_RIGHT }, 255038889Sjdp { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 }, 255138889Sjdp { "STATE3", CTL_BUTTON, BS_3STATE }, 255238889Sjdp /* It's important that USERBUTTON come after all the other button 255338889Sjdp types, so that it won't be matched too early. */ 255438889Sjdp { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 }, 255538889Sjdp { NULL, 0, 0 } 255638889Sjdp}; 255738889Sjdp 255838889Sjdp/* Write a dialog control. */ 255938889Sjdp 256038889Sjdpstatic void 2561218822Sdimwrite_rc_dialog_control (FILE *e, const rc_dialog_control *control) 256238889Sjdp{ 256338889Sjdp const struct control_info *ci; 256438889Sjdp 256538889Sjdp fprintf (e, " "); 256638889Sjdp 256738889Sjdp if (control->class.named) 256838889Sjdp ci = NULL; 256938889Sjdp else 257038889Sjdp { 257138889Sjdp for (ci = control_info; ci->name != NULL; ++ci) 257238889Sjdp if (ci->class == control->class.u.id 257338889Sjdp && (ci->style == (unsigned long) -1 257438889Sjdp || ci->style == (control->style & 0xff))) 257538889Sjdp break; 257638889Sjdp } 257760484Sobrien if (ci == NULL) 257860484Sobrien fprintf (e, "CONTROL"); 257960484Sobrien else if (ci->name != NULL) 258038889Sjdp fprintf (e, "%s", ci->name); 258138889Sjdp else 2582218822Sdim { 258338889Sjdp fprintf (e, "CONTROL"); 2584218822Sdim ci = NULL; 2585218822Sdim } 2586104834Sobrien 258738889Sjdp if (control->text.named || control->text.u.id != 0) 258838889Sjdp { 258938889Sjdp fprintf (e, " "); 259038889Sjdp res_id_print (e, control->text, 1); 259138889Sjdp fprintf (e, ","); 259238889Sjdp } 259338889Sjdp 2594218822Sdim fprintf (e, " %d, ", (int) control->id); 259538889Sjdp 259660484Sobrien if (ci == NULL) 259738889Sjdp { 259860484Sobrien if (control->class.named) 259960484Sobrien fprintf (e, "\""); 260038889Sjdp res_id_print (e, control->class, 0); 260160484Sobrien if (control->class.named) 260260484Sobrien fprintf (e, "\""); 2603218822Sdim fprintf (e, ", 0x%x, ", (unsigned int) control->style); 260438889Sjdp } 260538889Sjdp 2606218822Sdim fprintf (e, "%d, %d", (int) control->x, (int) control->y); 260738889Sjdp 260838889Sjdp if (control->style != SS_ICON 260938889Sjdp || control->exstyle != 0 261038889Sjdp || control->width != 0 261138889Sjdp || control->height != 0 261238889Sjdp || control->help != 0) 261338889Sjdp { 2614218822Sdim fprintf (e, ", %d, %d", (int) control->width, (int) control->height); 261538889Sjdp 261638889Sjdp /* FIXME: We don't need to print the style if it is the default. 261738889Sjdp More importantly, in certain cases we actually need to turn 261838889Sjdp off parts of the forced style, by using NOT. */ 2619218822Sdim if (ci != NULL) 2620218822Sdim fprintf (e, ", 0x%x", (unsigned int) control->style); 262138889Sjdp 262238889Sjdp if (control->exstyle != 0 || control->help != 0) 2623218822Sdim fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle, 2624218822Sdim (unsigned int) control->help); 262538889Sjdp } 262638889Sjdp 262738889Sjdp fprintf (e, "\n"); 262838889Sjdp 262938889Sjdp if (control->data != NULL) 263038889Sjdp write_rc_rcdata (e, control->data, 2); 263138889Sjdp} 263238889Sjdp 263338889Sjdp/* Write out font directory data. This would normally be built from 263438889Sjdp the font data. */ 263538889Sjdp 263638889Sjdpstatic void 2637218822Sdimwrite_rc_fontdir (FILE *e, const rc_fontdir *fontdir) 263838889Sjdp{ 2639218822Sdim const rc_fontdir *fc; 2640218822Sdim int c; 264138889Sjdp 2642218822Sdim for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++) 2643218822Sdim ; 2644218822Sdim fprintf (e, "BEGIN\n"); 2645218822Sdim indent (e, 2); 2646218822Sdim fprintf (e, "%d%s\t /* Has %d elements. */\n", c, (c != 0 ? "," : ""), c); 2647218822Sdim for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++) 264838889Sjdp { 2649218822Sdim indent (e, 4); 2650218822Sdim fprintf (e, "%d,\t/* Font no %d with index %d. */\n", 2651218822Sdim (int) fc->index, c, (int) fc->index); 2652218822Sdim write_rc_datablock (e, (rc_uint_type) fc->length - 2, 2653218822Sdim (const bfd_byte *) fc->data + 4,fc->next != NULL, 2654218822Sdim 0, 0); 265538889Sjdp } 2656218822Sdim fprintf (e, "END\n"); 265738889Sjdp} 265838889Sjdp 265938889Sjdp/* Write out group icon data. This would normally be built from the 266038889Sjdp icon data. */ 266138889Sjdp 266238889Sjdpstatic void 2663218822Sdimwrite_rc_group_icon (FILE *e, const rc_group_icon *group_icon) 266438889Sjdp{ 2665218822Sdim const rc_group_icon *gi; 2666218822Sdim int c; 266738889Sjdp 2668218822Sdim for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++) 2669218822Sdim ; 2670218822Sdim 2671218822Sdim fprintf (e, "BEGIN\n"); 2672218822Sdim indent (e, 2); 2673218822Sdim fprintf (e, " 0, 1, %d%s\t /* Has %d elements. */\n", c, (c != 0 ? "," : ""), c); 2674218822Sdim 2675218822Sdim indent (e, 4); 2676218822Sdim fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index. */\n"); 2677218822Sdim for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++) 267838889Sjdp { 2679218822Sdim indent (e, 4); 2680218822Sdim fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d. */\n", 2681218822Sdim gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits, 2682218822Sdim (unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c); 268338889Sjdp } 2684218822Sdim fprintf (e, "END\n"); 268538889Sjdp} 268638889Sjdp 268738889Sjdp/* Write out a menu resource. */ 268838889Sjdp 268938889Sjdpstatic void 2690218822Sdimwrite_rc_menu (FILE *e, const rc_menu *menu, int menuex) 269138889Sjdp{ 269238889Sjdp if (menu->help != 0) 2693218822Sdim fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help); 269438889Sjdp write_rc_menuitems (e, menu->items, menuex, 0); 269538889Sjdp} 269638889Sjdp 2697218822Sdimstatic void 2698218822Sdimwrite_rc_toolbar (FILE *e, const rc_toolbar *tb) 2699218822Sdim{ 2700218822Sdim rc_toolbar_item *it; 2701218822Sdim indent (e, 0); 2702218822Sdim fprintf (e, "BEGIN\n"); 2703218822Sdim it = tb->items; 2704218822Sdim while(it != NULL) 2705218822Sdim { 2706218822Sdim indent (e, 2); 2707218822Sdim if (it->id.u.id == 0) 2708218822Sdim fprintf (e, "SEPARATOR\n"); 2709218822Sdim else 2710218822Sdim fprintf (e, "BUTTON %d\n", (int) it->id.u.id); 2711218822Sdim it = it->next; 2712218822Sdim } 2713218822Sdim indent (e, 0); 2714218822Sdim fprintf (e, "END\n"); 2715218822Sdim} 2716218822Sdim 271738889Sjdp/* Write out menuitems. */ 271838889Sjdp 271938889Sjdpstatic void 2720218822Sdimwrite_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex, 2721130561Sobrien int ind) 272238889Sjdp{ 2723218822Sdim const rc_menuitem *mi; 272438889Sjdp 272538889Sjdp indent (e, ind); 272638889Sjdp fprintf (e, "BEGIN\n"); 272738889Sjdp 272838889Sjdp for (mi = menuitems; mi != NULL; mi = mi->next) 272938889Sjdp { 273038889Sjdp indent (e, ind + 2); 273138889Sjdp 273238889Sjdp if (mi->popup == NULL) 273338889Sjdp fprintf (e, "MENUITEM"); 273438889Sjdp else 273538889Sjdp fprintf (e, "POPUP"); 273638889Sjdp 273738889Sjdp if (! menuex 273838889Sjdp && mi->popup == NULL 273938889Sjdp && mi->text == NULL 274038889Sjdp && mi->type == 0 274138889Sjdp && mi->id == 0) 274238889Sjdp { 274338889Sjdp fprintf (e, " SEPARATOR\n"); 274438889Sjdp continue; 274538889Sjdp } 274638889Sjdp 274738889Sjdp if (mi->text == NULL) 274838889Sjdp fprintf (e, " \"\""); 274938889Sjdp else 275038889Sjdp { 2751218822Sdim fprintf (e, " "); 2752218822Sdim unicode_print_quoted (e, mi->text, -1); 275338889Sjdp } 275438889Sjdp 275538889Sjdp if (! menuex) 275638889Sjdp { 275738889Sjdp if (mi->popup == NULL) 2758218822Sdim fprintf (e, ", %d", (int) mi->id); 275938889Sjdp 276038889Sjdp if ((mi->type & MENUITEM_CHECKED) != 0) 276138889Sjdp fprintf (e, ", CHECKED"); 276238889Sjdp if ((mi->type & MENUITEM_GRAYED) != 0) 276338889Sjdp fprintf (e, ", GRAYED"); 276438889Sjdp if ((mi->type & MENUITEM_HELP) != 0) 276538889Sjdp fprintf (e, ", HELP"); 276638889Sjdp if ((mi->type & MENUITEM_INACTIVE) != 0) 276738889Sjdp fprintf (e, ", INACTIVE"); 276838889Sjdp if ((mi->type & MENUITEM_MENUBARBREAK) != 0) 276938889Sjdp fprintf (e, ", MENUBARBREAK"); 277038889Sjdp if ((mi->type & MENUITEM_MENUBREAK) != 0) 277138889Sjdp fprintf (e, ", MENUBREAK"); 277238889Sjdp } 277338889Sjdp else 277438889Sjdp { 277538889Sjdp if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0) 277638889Sjdp { 2777218822Sdim fprintf (e, ", %d", (int) mi->id); 277838889Sjdp if (mi->type != 0 || mi->state != 0 || mi->help != 0) 277938889Sjdp { 2780218822Sdim fprintf (e, ", %u", (unsigned int) mi->type); 278138889Sjdp if (mi->state != 0 || mi->help != 0) 278238889Sjdp { 2783218822Sdim fprintf (e, ", %u", (unsigned int) mi->state); 278438889Sjdp if (mi->help != 0) 2785218822Sdim fprintf (e, ", %u", (unsigned int) mi->help); 278638889Sjdp } 278738889Sjdp } 278838889Sjdp } 278938889Sjdp } 279038889Sjdp 279138889Sjdp fprintf (e, "\n"); 279238889Sjdp 279338889Sjdp if (mi->popup != NULL) 279438889Sjdp write_rc_menuitems (e, mi->popup, menuex, ind + 2); 279538889Sjdp } 279638889Sjdp 279738889Sjdp indent (e, ind); 279838889Sjdp fprintf (e, "END\n"); 279938889Sjdp} 280038889Sjdp 2801218822Sdimstatic int 2802218822Sdimtest_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data) 2803218822Sdim{ 2804218822Sdim rc_uint_type i; 2805218822Sdim if ((length & 1) != 0) 2806218822Sdim return 0; 280738889Sjdp 2808218822Sdim for (i = 0; i < length; i += 2) 2809218822Sdim { 2810218822Sdim if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length) 2811218822Sdim return 0; 2812218822Sdim if (data[i] == 0xff && data[i + 1] == 0xff) 2813218822Sdim return 0; 2814218822Sdim } 2815218822Sdim return 1; 2816218822Sdim} 2817218822Sdim 2818218822Sdimstatic int 2819218822Sdimtest_rc_datablock_text (rc_uint_type length, const bfd_byte *data) 2820218822Sdim{ 2821218822Sdim int has_nl; 2822218822Sdim rc_uint_type c; 2823218822Sdim rc_uint_type i; 2824218822Sdim 2825218822Sdim if (length <= 1) 2826218822Sdim return 0; 2827218822Sdim 2828218822Sdim has_nl = 0; 2829218822Sdim for (i = 0, c = 0; i < length; i++) 2830218822Sdim { 2831218822Sdim if (! ISPRINT (data[i]) && data[i] != '\n' 2832218822Sdim && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n') 2833218822Sdim && data[i] != '\t' 2834218822Sdim && ! (data[i] == 0 && (i + 1) != length)) 2835218822Sdim { 2836218822Sdim if (data[i] <= 7) 2837218822Sdim return 0; 2838218822Sdim c++; 2839218822Sdim } 2840218822Sdim else if (data[i] == '\n') has_nl++; 2841218822Sdim } 2842218822Sdim if (length > 80 && ! has_nl) 2843218822Sdim return 0; 2844218822Sdim c = (((c * 10000) + (i / 100) - 1)) / i; 2845218822Sdim if (c >= 150) 2846218822Sdim return 0; 2847218822Sdim return 1; 2848218822Sdim} 2849218822Sdim 285038889Sjdpstatic void 2851218822Sdimwrite_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data) 285238889Sjdp{ 2853218822Sdim int has_error = 0; 2854218822Sdim const struct bin_messagetable *mt; 285538889Sjdp fprintf (e, "BEGIN\n"); 285638889Sjdp 2857218822Sdim write_rc_datablock (e, length, data, 0, 0, 0); 285838889Sjdp 2859218822Sdim fprintf (e, "\n"); 2860218822Sdim wr_printcomment (e, "MC syntax dump"); 2861218822Sdim if (length < BIN_MESSAGETABLE_SIZE) 2862218822Sdim has_error = 1; 2863218822Sdim else 2864218822Sdim do { 2865218822Sdim rc_uint_type m, i; 2866218822Sdim mt = (const struct bin_messagetable *) data; 2867218822Sdim m = windres_get_32 (&wrtarget, mt->cblocks, length); 2868218822Sdim if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) 286938889Sjdp { 2870218822Sdim has_error = 1; 287138889Sjdp break; 2872218822Sdim } 2873218822Sdim for (i = 0; i < m; i++) 2874218822Sdim { 2875218822Sdim rc_uint_type low, high, offset; 2876218822Sdim const struct bin_messagetable_item *mti; 287738889Sjdp 2878218822Sdim low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); 2879218822Sdim high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); 2880218822Sdim offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); 2881218822Sdim while (low <= high) 2882218822Sdim { 2883218822Sdim rc_uint_type elen, flags; 2884218822Sdim if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) 2885218822Sdim { 2886218822Sdim has_error = 1; 288738889Sjdp break; 2888218822Sdim } 2889218822Sdim mti = (const struct bin_messagetable_item *) &data[offset]; 2890218822Sdim elen = windres_get_16 (&wrtarget, mti->length, 2); 2891218822Sdim flags = windres_get_16 (&wrtarget, mti->flags, 2); 2892218822Sdim if ((offset + elen) > length) 2893218822Sdim { 2894218822Sdim has_error = 1; 2895218822Sdim break; 2896218822Sdim } 2897218822Sdim wr_printcomment (e, "MessageId = 0x%x", low); 2898218822Sdim wr_printcomment (e, ""); 2899218822Sdim if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) 2900218822Sdim unicode_print (e, (const unichar *) mti->data, 2901218822Sdim (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); 2902218822Sdim else 2903218822Sdim ascii_print (e, (const char *) mti->data, 2904218822Sdim (elen - BIN_MESSAGETABLE_ITEM_SIZE)); 2905218822Sdim wr_printcomment (e,""); 2906218822Sdim ++low; 2907218822Sdim offset += elen; 2908218822Sdim } 2909218822Sdim } 2910218822Sdim } while (0); 2911218822Sdim if (has_error) 2912218822Sdim wr_printcomment (e, "Illegal data"); 2913218822Sdim wr_print_flush (e); 2914218822Sdim fprintf (e, "END\n"); 2915218822Sdim} 291638889Sjdp 2917218822Sdimstatic void 2918218822Sdimwrite_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next, 2919218822Sdim int hasblock, int show_comment) 2920218822Sdim{ 2921218822Sdim int plen; 2922218822Sdim 2923218822Sdim if (hasblock) 2924218822Sdim fprintf (e, "BEGIN\n"); 2925218822Sdim 2926218822Sdim if (show_comment == -1) 292738889Sjdp { 2928218822Sdim if (test_rc_datablock_text(length, data)) 2929218822Sdim { 2930218822Sdim rc_uint_type i, c; 2931218822Sdim for (i = 0; i < length;) 2932218822Sdim { 2933218822Sdim indent (e, 2); 2934218822Sdim fprintf (e, "\""); 293538889Sjdp 2936218822Sdim for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++) 2937218822Sdim ; 2938218822Sdim if (i < length && data[i] == '\n') 2939218822Sdim ++i, ++c; 2940218822Sdim ascii_print (e, (const char *) &data[i - c], c); 294138889Sjdp fprintf (e, "\""); 2942218822Sdim if (i < length) 2943218822Sdim fprintf (e, "\n"); 2944218822Sdim } 2945218822Sdim 2946218822Sdim if (i == 0) 294738889Sjdp { 2948218822Sdim indent (e, 2); 2949218822Sdim fprintf (e, "\"\""); 295038889Sjdp } 2951218822Sdim if (has_next) 2952218822Sdim fprintf (e, ","); 2953218822Sdim fprintf (e, "\n"); 2954218822Sdim if (hasblock) 2955218822Sdim fprintf (e, "END\n"); 2956218822Sdim return; 295738889Sjdp } 2958218822Sdim if (test_rc_datablock_unicode (length, data)) 2959218822Sdim { 2960218822Sdim rc_uint_type i, c; 2961218822Sdim for (i = 0; i < length;) 2962218822Sdim { 2963218822Sdim const unichar *u; 296438889Sjdp 2965218822Sdim u = (const unichar *) &data[i]; 2966218822Sdim indent (e, 2); 296738889Sjdp fprintf (e, "L\""); 2968218822Sdim 2969218822Sdim for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2) 2970218822Sdim ; 2971218822Sdim if (i < length && u[c] == '\n') 2972218822Sdim i += 2, ++c; 2973218822Sdim unicode_print (e, u, c); 297438889Sjdp fprintf (e, "\""); 2975218822Sdim if (i < length) 2976218822Sdim fprintf (e, "\n"); 2977218822Sdim } 297838889Sjdp 2979218822Sdim if (i == 0) 298038889Sjdp { 2981218822Sdim indent (e, 2); 2982218822Sdim fprintf (e, "L\"\""); 2983218822Sdim } 2984218822Sdim if (has_next) 2985218822Sdim fprintf (e, ","); 2986218822Sdim fprintf (e, "\n"); 2987218822Sdim if (hasblock) 2988218822Sdim fprintf (e, "END\n"); 2989218822Sdim return; 2990218822Sdim } 299138889Sjdp 2992218822Sdim show_comment = 0; 2993218822Sdim } 299438889Sjdp 2995218822Sdim if (length != 0) 299638889Sjdp { 2997218822Sdim rc_uint_type i, max_row; 2998218822Sdim int first = 1; 299938889Sjdp 3000218822Sdim max_row = (show_comment ? 4 : 8); 3001218822Sdim indent (e, 2); 3002218822Sdim for (i = 0; i + 3 < length;) 300338889Sjdp { 3004218822Sdim rc_uint_type k; 3005218822Sdim rc_uint_type comment_start; 3006218822Sdim 3007218822Sdim comment_start = i; 3008218822Sdim 3009218822Sdim if (! first) 3010218822Sdim indent (e, 2); 3011218822Sdim 3012218822Sdim for (k = 0; k < max_row && i + 3 < length; k++, i += 4) 301360484Sobrien { 3014218822Sdim if (k == 0) 3015218822Sdim plen = fprintf (e, "0x%lxL", 3016218822Sdim (long) windres_get_32 (&wrtarget, data + i, length - i)); 301760484Sobrien else 3018218822Sdim plen = fprintf (e, " 0x%lxL", 3019218822Sdim (long) windres_get_32 (&wrtarget, data + i, length - i)) - 1; 3020218822Sdim if (has_next || (i + 4) < length) 302160484Sobrien { 3022218822Sdim if (plen>0 && plen < 11) 3023218822Sdim indent (e, 11 - plen); 3024218822Sdim fprintf (e, ","); 302560484Sobrien } 302660484Sobrien } 3027218822Sdim if (show_comment) 3028218822Sdim { 3029218822Sdim fprintf (e, "\t/* "); 3030218822Sdim ascii_print (e, (const char *) &data[comment_start], i - comment_start); 3031218822Sdim fprintf (e, ". */"); 303238889Sjdp } 303360484Sobrien fprintf (e, "\n"); 303460484Sobrien first = 0; 303538889Sjdp } 303638889Sjdp 3037218822Sdim if (i + 1 < length) 303838889Sjdp { 303960484Sobrien if (! first) 3040218822Sdim indent (e, 2); 3041218822Sdim plen = fprintf (e, "0x%x", 3042218822Sdim (int) windres_get_16 (&wrtarget, data + i, length - i)); 3043218822Sdim if (has_next || i + 2 < length) 304438889Sjdp { 3045218822Sdim if (plen > 0 && plen < 11) 3046218822Sdim indent (e, 11 - plen); 3047218822Sdim fprintf (e, ","); 304860484Sobrien } 3049218822Sdim if (show_comment) 3050218822Sdim { 3051218822Sdim fprintf (e, "\t/* "); 3052218822Sdim ascii_print (e, (const char *) &data[i], 2); 3053218822Sdim fprintf (e, ". */"); 305438889Sjdp } 305560484Sobrien fprintf (e, "\n"); 305638889Sjdp i += 2; 305760484Sobrien first = 0; 305838889Sjdp } 305938889Sjdp 3060218822Sdim if (i < length) 306138889Sjdp { 306260484Sobrien if (! first) 3063218822Sdim indent (e, 2); 3064218822Sdim fprintf (e, "\""); 3065218822Sdim ascii_print (e, (const char *) &data[i], 1); 3066218822Sdim fprintf (e, "\""); 3067218822Sdim if (has_next) 306860484Sobrien fprintf (e, ","); 306960484Sobrien fprintf (e, "\n"); 307060484Sobrien first = 0; 307138889Sjdp } 3072218822Sdim } 3073218822Sdim if (hasblock) 3074218822Sdim fprintf (e, "END\n"); 3075218822Sdim} 307638889Sjdp 3077218822Sdim/* Write out an rcdata resource. This is also used for other types of 3078218822Sdim resources that need to print arbitrary data. */ 3079218822Sdim 3080218822Sdimstatic void 3081218822Sdimwrite_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind) 3082218822Sdim{ 3083218822Sdim const rc_rcdata_item *ri; 3084218822Sdim 3085218822Sdim indent (e, ind); 3086218822Sdim fprintf (e, "BEGIN\n"); 3087218822Sdim 3088218822Sdim for (ri = rcdata; ri != NULL; ri = ri->next) 3089218822Sdim { 3090218822Sdim if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0) 3091218822Sdim continue; 3092218822Sdim 3093218822Sdim switch (ri->type) 3094218822Sdim { 3095218822Sdim default: 3096218822Sdim abort (); 3097218822Sdim 3098218822Sdim case RCDATA_WORD: 3099218822Sdim indent (e, ind + 2); 3100218822Sdim fprintf (e, "%ld", (long) (ri->u.word & 0xffff)); 3101218822Sdim break; 3102218822Sdim 3103218822Sdim case RCDATA_DWORD: 3104218822Sdim indent (e, ind + 2); 3105218822Sdim fprintf (e, "%luL", (unsigned long) ri->u.dword); 3106218822Sdim break; 3107218822Sdim 3108218822Sdim case RCDATA_STRING: 3109218822Sdim indent (e, ind + 2); 3110218822Sdim fprintf (e, "\""); 3111218822Sdim ascii_print (e, ri->u.string.s, ri->u.string.length); 3112218822Sdim fprintf (e, "\""); 3113218822Sdim break; 3114218822Sdim 3115218822Sdim case RCDATA_WSTRING: 3116218822Sdim indent (e, ind + 2); 3117218822Sdim fprintf (e, "L\""); 3118218822Sdim unicode_print (e, ri->u.wstring.w, ri->u.wstring.length); 3119218822Sdim fprintf (e, "\""); 3120218822Sdim break; 3121218822Sdim 3122218822Sdim case RCDATA_BUFFER: 3123218822Sdim write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length, 3124218822Sdim (const bfd_byte *) ri->u.buffer.data, 3125218822Sdim ri->next != NULL, 0, -1); 312638889Sjdp break; 312738889Sjdp } 312838889Sjdp 312960484Sobrien if (ri->type != RCDATA_BUFFER) 313060484Sobrien { 313160484Sobrien if (ri->next != NULL) 313260484Sobrien fprintf (e, ","); 313360484Sobrien fprintf (e, "\n"); 313460484Sobrien } 313538889Sjdp } 313638889Sjdp 313738889Sjdp indent (e, ind); 313838889Sjdp fprintf (e, "END\n"); 313938889Sjdp} 314038889Sjdp 314138889Sjdp/* Write out a stringtable resource. */ 314238889Sjdp 314338889Sjdpstatic void 3144218822Sdimwrite_rc_stringtable (FILE *e, const rc_res_id *name, 3145218822Sdim const rc_stringtable *stringtable) 314638889Sjdp{ 3147218822Sdim rc_uint_type offset; 314838889Sjdp int i; 314938889Sjdp 315038889Sjdp if (name != NULL && ! name->named) 315138889Sjdp offset = (name->u.id - 1) << 4; 315238889Sjdp else 315338889Sjdp { 3154218822Sdim fprintf (e, "/* %s string table name. */\n", 315538889Sjdp name == NULL ? "Missing" : "Invalid"); 315638889Sjdp offset = 0; 315738889Sjdp } 315838889Sjdp 315938889Sjdp fprintf (e, "BEGIN\n"); 316038889Sjdp 316138889Sjdp for (i = 0; i < 16; i++) 316238889Sjdp { 316338889Sjdp if (stringtable->strings[i].length != 0) 316438889Sjdp { 3165218822Sdim fprintf (e, " %lu, ", (long) offset + i); 3166218822Sdim unicode_print_quoted (e, stringtable->strings[i].string, 316738889Sjdp stringtable->strings[i].length); 3168218822Sdim fprintf (e, "\n"); 316938889Sjdp } 317038889Sjdp } 317138889Sjdp 317238889Sjdp fprintf (e, "END\n"); 317338889Sjdp} 317438889Sjdp 317538889Sjdp/* Write out a versioninfo resource. */ 317638889Sjdp 317738889Sjdpstatic void 3178218822Sdimwrite_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo) 317938889Sjdp{ 3180218822Sdim const rc_fixed_versioninfo *f; 3181218822Sdim const rc_ver_info *vi; 318238889Sjdp 318338889Sjdp f = versioninfo->fixed; 318438889Sjdp if (f->file_version_ms != 0 || f->file_version_ls != 0) 3185218822Sdim fprintf (e, " FILEVERSION %u, %u, %u, %u\n", 3186218822Sdim (unsigned int) ((f->file_version_ms >> 16) & 0xffff), 3187218822Sdim (unsigned int) (f->file_version_ms & 0xffff), 3188218822Sdim (unsigned int) ((f->file_version_ls >> 16) & 0xffff), 3189218822Sdim (unsigned int) (f->file_version_ls & 0xffff)); 319038889Sjdp if (f->product_version_ms != 0 || f->product_version_ls != 0) 3191218822Sdim fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n", 3192218822Sdim (unsigned int) ((f->product_version_ms >> 16) & 0xffff), 3193218822Sdim (unsigned int) (f->product_version_ms & 0xffff), 3194218822Sdim (unsigned int) ((f->product_version_ls >> 16) & 0xffff), 3195218822Sdim (unsigned int) (f->product_version_ls & 0xffff)); 319638889Sjdp if (f->file_flags_mask != 0) 3197218822Sdim fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask); 319838889Sjdp if (f->file_flags != 0) 3199218822Sdim fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags); 320038889Sjdp if (f->file_os != 0) 3201218822Sdim fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os); 320238889Sjdp if (f->file_type != 0) 3203218822Sdim fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type); 320438889Sjdp if (f->file_subtype != 0) 3205218822Sdim fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype); 320638889Sjdp if (f->file_date_ms != 0 || f->file_date_ls != 0) 3207218822Sdim fprintf (e, "/* Date: %u, %u. */\n", 3208218822Sdim (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls); 320938889Sjdp 321038889Sjdp fprintf (e, "BEGIN\n"); 321138889Sjdp 321238889Sjdp for (vi = versioninfo->var; vi != NULL; vi = vi->next) 321338889Sjdp { 321438889Sjdp switch (vi->type) 321538889Sjdp { 321638889Sjdp case VERINFO_STRING: 321738889Sjdp { 3218218822Sdim const rc_ver_stringinfo *vs; 321938889Sjdp 322038889Sjdp fprintf (e, " BLOCK \"StringFileInfo\"\n"); 322138889Sjdp fprintf (e, " BEGIN\n"); 3222218822Sdim fprintf (e, " BLOCK "); 3223218822Sdim unicode_print_quoted (e, vi->u.string.language, -1); 3224218822Sdim fprintf (e, "\n"); 322538889Sjdp fprintf (e, " BEGIN\n"); 322638889Sjdp 322738889Sjdp for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) 322838889Sjdp { 3229218822Sdim fprintf (e, " VALUE "); 3230218822Sdim unicode_print_quoted (e, vs->key, -1); 3231218822Sdim fprintf (e, ", "); 3232218822Sdim unicode_print_quoted (e, vs->value, -1); 3233218822Sdim fprintf (e, "\n"); 323438889Sjdp } 323538889Sjdp 323638889Sjdp fprintf (e, " END\n"); 323738889Sjdp fprintf (e, " END\n"); 323838889Sjdp break; 323938889Sjdp } 324038889Sjdp 324138889Sjdp case VERINFO_VAR: 324238889Sjdp { 3243218822Sdim const rc_ver_varinfo *vv; 324438889Sjdp 324538889Sjdp fprintf (e, " BLOCK \"VarFileInfo\"\n"); 324638889Sjdp fprintf (e, " BEGIN\n"); 3247218822Sdim fprintf (e, " VALUE "); 3248218822Sdim unicode_print_quoted (e, vi->u.var.key, -1); 324938889Sjdp 325038889Sjdp for (vv = vi->u.var.var; vv != NULL; vv = vv->next) 325138889Sjdp fprintf (e, ", 0x%x, %d", (unsigned int) vv->language, 3252218822Sdim (int) vv->charset); 325338889Sjdp 325438889Sjdp fprintf (e, "\n END\n"); 325538889Sjdp 325638889Sjdp break; 325738889Sjdp } 325838889Sjdp } 325938889Sjdp } 326038889Sjdp 326138889Sjdp fprintf (e, "END\n"); 326238889Sjdp} 326338889Sjdp 3264218822Sdimstatic rc_uint_type 3265218822Sdimrcdata_copy (const rc_rcdata_item *src, bfd_byte *dst) 326638889Sjdp{ 3267218822Sdim if (! src) 3268218822Sdim return 0; 3269218822Sdim switch (src->type) 327038889Sjdp { 3271218822Sdim case RCDATA_WORD: 3272218822Sdim if (dst) 3273218822Sdim windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word); 3274218822Sdim return 2; 3275218822Sdim case RCDATA_DWORD: 3276218822Sdim if (dst) 3277218822Sdim windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword); 3278218822Sdim return 4; 3279218822Sdim case RCDATA_STRING: 3280218822Sdim if (dst && src->u.string.length) 3281218822Sdim memcpy (dst, src->u.string.s, src->u.string.length); 3282218822Sdim return (rc_uint_type) src->u.string.length; 3283218822Sdim case RCDATA_WSTRING: 3284218822Sdim if (dst && src->u.wstring.length) 3285218822Sdim memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar)); 3286218822Sdim return (rc_uint_type) (src->u.wstring.length * sizeof (unichar)); 3287218822Sdim case RCDATA_BUFFER: 3288218822Sdim if (dst && src->u.buffer.length) 3289218822Sdim memcpy (dst, src->u.buffer.data, src->u.buffer.length); 3290218822Sdim return (rc_uint_type) src->u.buffer.length; 3291218822Sdim default: 3292218822Sdim abort (); 329338889Sjdp } 3294218822Sdim /* Never reached. */ 3295218822Sdim return 0; 329638889Sjdp} 3297