|  | /* | 
|  | * Generate .res format from a resource-tree | 
|  | * | 
|  | * Copyright 1998 Bertho A. Stultiens | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | * | 
|  | * History: | 
|  | * 05-May-2000 BS	- Added code to support endian conversions. The | 
|  | * 			  extra functions also aid unaligned access, but | 
|  | * 			  this is not yet implemented. | 
|  | * 25-May-1998 BS	- Added simple unicode -> char conversion for resource | 
|  | *			  names in .s and .h files. | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  | #include <stdarg.h> | 
|  | #include <assert.h> | 
|  | #include <ctype.h> | 
|  |  | 
|  | #include "wrc.h" | 
|  | #include "genres.h" | 
|  | #include "utils.h" | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "wingdi.h" | 
|  | #include "winuser.h" | 
|  | #include "wine/unicode.h" | 
|  |  | 
|  | #define SetResSize(res, tag)	set_dword((res), (tag), (res)->size - get_dword((res), (tag))) | 
|  |  | 
|  | res_t *new_res(void) | 
|  | { | 
|  | res_t *r; | 
|  | r = xmalloc(sizeof(res_t)); | 
|  | r->allocsize = RES_BLOCKSIZE; | 
|  | r->size = 0; | 
|  | r->dataidx = 0; | 
|  | r->data = xmalloc(RES_BLOCKSIZE); | 
|  | return r; | 
|  | } | 
|  |  | 
|  | res_t *grow_res(res_t *r, unsigned int add) | 
|  | { | 
|  | r->allocsize += add; | 
|  | r->data = xrealloc(r->data, r->allocsize); | 
|  | return r; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: put_byte | 
|  | *		  put_word | 
|  | *		  put_dword | 
|  | * Syntax	: void put_byte(res_t *res, unsigned c) | 
|  | *		  void put_word(res_t *res, unsigned w) | 
|  | *		  void put_dword(res_t *res, unsigned d) | 
|  | * Input	: | 
|  | *	res	- Binary resource to put the data in | 
|  | *	c, w, d	- Data to put | 
|  | * Output	: nop | 
|  | * Description	: Put primitives that put an item in the binary resource. | 
|  | *		  The data array grows automatically. | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | void put_byte(res_t *res, unsigned c) | 
|  | { | 
|  | if(res->allocsize - res->size < sizeof(char)) | 
|  | grow_res(res, RES_BLOCKSIZE); | 
|  | res->data[res->size] = (char)c; | 
|  | res->size += sizeof(char); | 
|  | } | 
|  |  | 
|  | void put_word(res_t *res, unsigned w) | 
|  | { | 
|  | if(res->allocsize - res->size < sizeof(WORD)) | 
|  | grow_res(res, RES_BLOCKSIZE); | 
|  | switch(byteorder) | 
|  | { | 
|  | #ifdef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_BIG: | 
|  | res->data[res->size+0] = HIBYTE(w); | 
|  | res->data[res->size+1] = LOBYTE(w); | 
|  | break; | 
|  |  | 
|  | #ifndef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_LITTLE: | 
|  | res->data[res->size+1] = HIBYTE(w); | 
|  | res->data[res->size+0] = LOBYTE(w); | 
|  | break; | 
|  | } | 
|  | res->size += sizeof(WORD); | 
|  | } | 
|  |  | 
|  | void put_dword(res_t *res, unsigned d) | 
|  | { | 
|  | if(res->allocsize - res->size < sizeof(DWORD)) | 
|  | grow_res(res, RES_BLOCKSIZE); | 
|  | switch(byteorder) | 
|  | { | 
|  | #ifdef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_BIG: | 
|  | res->data[res->size+0] = HIBYTE(HIWORD(d)); | 
|  | res->data[res->size+1] = LOBYTE(HIWORD(d)); | 
|  | res->data[res->size+2] = HIBYTE(LOWORD(d)); | 
|  | res->data[res->size+3] = LOBYTE(LOWORD(d)); | 
|  | break; | 
|  |  | 
|  | #ifndef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_LITTLE: | 
|  | res->data[res->size+3] = HIBYTE(HIWORD(d)); | 
|  | res->data[res->size+2] = LOBYTE(HIWORD(d)); | 
|  | res->data[res->size+1] = HIBYTE(LOWORD(d)); | 
|  | res->data[res->size+0] = LOBYTE(LOWORD(d)); | 
|  | break; | 
|  | } | 
|  | res->size += sizeof(DWORD); | 
|  | } | 
|  |  | 
|  | static void put_pad(res_t *res) | 
|  | { | 
|  | while(res->size & 0x3) | 
|  | put_byte(res, 0); | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: set_word | 
|  | *		  set_dword | 
|  | * Syntax	: void set_word(res_t *res, int ofs, unsigned w) | 
|  | *		  void set_dword(res_t *res, int ofs, unsigned d) | 
|  | * Input	: | 
|  | *	res	- Binary resource to put the data in | 
|  | *	ofs	- Byte offset in data-array | 
|  | *	w, d	- Data to put | 
|  | * Output	: nop | 
|  | * Description	: Set the value of a binary resource data array to a | 
|  | * 		  specific value. | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void set_word(res_t *res, int ofs, unsigned w) | 
|  | { | 
|  | switch(byteorder) | 
|  | { | 
|  | #ifdef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_BIG: | 
|  | res->data[ofs+0] = HIBYTE(w); | 
|  | res->data[ofs+1] = LOBYTE(w); | 
|  | break; | 
|  |  | 
|  | #ifndef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_LITTLE: | 
|  | res->data[ofs+1] = HIBYTE(w); | 
|  | res->data[ofs+0] = LOBYTE(w); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void set_dword(res_t *res, int ofs, unsigned d) | 
|  | { | 
|  | switch(byteorder) | 
|  | { | 
|  | #ifdef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_BIG: | 
|  | res->data[ofs+0] = HIBYTE(HIWORD(d)); | 
|  | res->data[ofs+1] = LOBYTE(HIWORD(d)); | 
|  | res->data[ofs+2] = HIBYTE(LOWORD(d)); | 
|  | res->data[ofs+3] = LOBYTE(LOWORD(d)); | 
|  | break; | 
|  |  | 
|  | #ifndef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_LITTLE: | 
|  | res->data[ofs+3] = HIBYTE(HIWORD(d)); | 
|  | res->data[ofs+2] = LOBYTE(HIWORD(d)); | 
|  | res->data[ofs+1] = HIBYTE(LOWORD(d)); | 
|  | res->data[ofs+0] = LOBYTE(LOWORD(d)); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: get_dword | 
|  | * Input	: | 
|  | *	res	- Binary resource to put the data in | 
|  | *	ofs	- Byte offset in data-array | 
|  | * Output	: The data in native endian | 
|  | * Description	: Get the value of a binary resource data array in native | 
|  | * 		  endian. | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static DWORD get_dword(res_t *res, int ofs) | 
|  | { | 
|  | switch(byteorder) | 
|  | { | 
|  | #ifdef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_BIG: | 
|  | return   (res->data[ofs+0] << 24) | 
|  | | (res->data[ofs+1] << 16) | 
|  | | (res->data[ofs+2] <<  8) | 
|  | |  res->data[ofs+3]; | 
|  |  | 
|  | #ifndef WORDS_BIGENDIAN | 
|  | default: | 
|  | #endif | 
|  | case WRC_BO_LITTLE: | 
|  | return   (res->data[ofs+3] << 24) | 
|  | | (res->data[ofs+2] << 16) | 
|  | | (res->data[ofs+1] <<  8) | 
|  | |  res->data[ofs+0]; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: string_to_upper | 
|  | * Syntax	: void string_to_upper(string_t *str) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: | 
|  | * Remarks	: FIXME: codepages... | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void string_to_upper(string_t *str) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | if(str->type == str_char) | 
|  | { | 
|  | for (i = 0; i < str->size; i++) str->str.cstr[i] = toupper((unsigned char)str->str.cstr[i]); | 
|  | } | 
|  | else if(str->type == str_unicode) | 
|  | { | 
|  | for (i = 0; i < str->size; i++) str->str.wstr[i] = toupperW(str->str.wstr[i]); | 
|  | } | 
|  | else | 
|  | { | 
|  | internal_error(__FILE__, __LINE__, "Invalid string type %d\n", str->type); | 
|  | } | 
|  | } | 
|  |  | 
|  | static int parse_accel_string( const string_t *key, int flags ) | 
|  | { | 
|  | int keycode; | 
|  |  | 
|  | if(key->type == str_char) | 
|  | { | 
|  | if (key->str.cstr[0] == '#') return 0;  /* ignore message contexts */ | 
|  | if((flags & WRC_AF_VIRTKEY) && | 
|  | !((key->str.cstr[0] >= 'A' && key->str.cstr[0] <= 'Z') || | 
|  | (key->str.cstr[0] >= '0' && key->str.cstr[0] <= '9'))) | 
|  | { | 
|  | print_location( &key->loc ); | 
|  | error("VIRTKEY code is not equal to ascii value\n"); | 
|  | } | 
|  |  | 
|  | if(key->str.cstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0) | 
|  | { | 
|  | print_location( &key->loc ); | 
|  | error("Cannot use both '^' and CONTROL modifier\n"); | 
|  | } | 
|  | else if(key->str.cstr[0] == '^') | 
|  | { | 
|  | keycode = toupper((unsigned char)key->str.cstr[1]) - '@'; | 
|  | if(keycode >= ' ') | 
|  | { | 
|  | print_location( &key->loc ); | 
|  | error("Control-code out of range\n"); | 
|  | } | 
|  | } | 
|  | else | 
|  | keycode = key->str.cstr[0]; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (key->str.wstr[0] == '#') return 0;  /* ignore message contexts */ | 
|  | if((flags & WRC_AF_VIRTKEY) && | 
|  | !((key->str.wstr[0] >= 'A' && key->str.wstr[0] <= 'Z') || | 
|  | (key->str.wstr[0] >= '0' && key->str.wstr[0] <= '9'))) | 
|  | { | 
|  | print_location( &key->loc ); | 
|  | error("VIRTKEY code is not equal to ascii value\n"); | 
|  | } | 
|  | if(key->str.wstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0) | 
|  | { | 
|  | print_location( &key->loc ); | 
|  | error("Cannot use both '^' and CONTROL modifier\n"); | 
|  | } | 
|  | else if(key->str.wstr[0] == '^') | 
|  | { | 
|  | keycode = toupperW(key->str.wstr[1]) - '@'; | 
|  | if(keycode >= ' ') | 
|  | { | 
|  | print_location( &key->loc ); | 
|  | error("Control-code out of range\n"); | 
|  | } | 
|  | } | 
|  | else | 
|  | keycode = key->str.wstr[0]; | 
|  | } | 
|  | return keycode; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: put_string | 
|  | * Syntax	: void put_string(res_t *res, string_t *str, enum str_e type, | 
|  | *				  int isterm, const language_t *lang) | 
|  | * Input	: | 
|  | *	res	- Binary resource to put the data in | 
|  | *	str	- String to put | 
|  | *	type	- Data has to be written in either str_char or str_unicode | 
|  | *	isterm	- The string is '\0' terminated (disregard the string's | 
|  | *		  size member) | 
|  | * Output	: nop | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void put_string(res_t *res, const string_t *str, enum str_e type, int isterm, | 
|  | const language_t *lang) | 
|  | { | 
|  | int cnt, codepage; | 
|  | string_t *newstr; | 
|  |  | 
|  | assert(res != NULL); | 
|  | assert(str != NULL); | 
|  |  | 
|  | if (lang) codepage = get_language_codepage( lang->id, lang->sub ); | 
|  | else codepage = get_language_codepage( 0, 0 ); | 
|  |  | 
|  | assert( codepage != -1 ); | 
|  |  | 
|  | newstr = convert_string(str, type, codepage); | 
|  | if (type == str_unicode) | 
|  | { | 
|  | if (str->type == str_char) | 
|  | { | 
|  | if (!check_unicode_conversion( str, newstr, codepage )) | 
|  | { | 
|  | print_location( &str->loc ); | 
|  | error( "String %s does not convert identically to Unicode and back in codepage %d. " | 
|  | "Try using a Unicode string instead\n", str->str.cstr, codepage ); | 
|  | } | 
|  | if (check_valid_utf8( str, codepage )) | 
|  | { | 
|  | print_location( &str->loc ); | 
|  | warning( "string \"%s\" seems to be UTF-8 but codepage %u is in use.\n", | 
|  | str->str.cstr, codepage ); | 
|  | } | 
|  | } | 
|  | if (!isterm) put_word(res, newstr->size); | 
|  | for(cnt = 0; cnt < newstr->size; cnt++) | 
|  | { | 
|  | WCHAR c = newstr->str.wstr[cnt]; | 
|  | if (isterm && !c) break; | 
|  | put_word(res, c); | 
|  | } | 
|  | if (isterm) put_word(res, 0); | 
|  | } | 
|  | else  /* str_char */ | 
|  | { | 
|  | if (!isterm) put_byte(res, newstr->size); | 
|  | for(cnt = 0; cnt < newstr->size; cnt++) | 
|  | { | 
|  | char c = newstr->str.cstr[cnt]; | 
|  | if (isterm && !c) break; | 
|  | put_byte(res, c); | 
|  | } | 
|  | if (isterm) put_byte(res, 0); | 
|  | } | 
|  | free_string(newstr); | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: put_name_id | 
|  | * Syntax	: void put_name_id(res_t *res, name_id_t *nid, int upcase, const language_t *lang) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void put_name_id(res_t *res, name_id_t *nid, int upcase, const language_t *lang) | 
|  | { | 
|  | if(nid->type == name_ord) | 
|  | { | 
|  | if(win32) | 
|  | put_word(res, 0xffff); | 
|  | else | 
|  | put_byte(res, 0xff); | 
|  | put_word(res, (WORD)nid->name.i_name); | 
|  | } | 
|  | else if(nid->type == name_str) | 
|  | { | 
|  | if(upcase) | 
|  | string_to_upper(nid->name.s_name); | 
|  | put_string(res, nid->name.s_name, win32 ? str_unicode : str_char, TRUE, lang); | 
|  | } | 
|  | else | 
|  | { | 
|  | internal_error(__FILE__, __LINE__, "Invalid name_id type %d\n", nid->type); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: put_lvc | 
|  | * Syntax	: void put_lvc(res_t *res, lvc_t *lvc) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void put_lvc(res_t *res, lvc_t *lvc) | 
|  | { | 
|  | if(lvc && lvc->language) | 
|  | put_word(res, MAKELANGID(lvc->language->id, lvc->language->sub)); | 
|  | else | 
|  | put_word(res, 0);	/* Neutral */ | 
|  | if(lvc && lvc->version) | 
|  | put_dword(res, *(lvc->version)); | 
|  | else | 
|  | put_dword(res, 0); | 
|  | if(lvc && lvc->characts) | 
|  | put_dword(res, *(lvc->characts)); | 
|  | else | 
|  | put_dword(res, 0); | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: put_raw_data | 
|  | * Syntax	: void put_raw_data(res_t *res, raw_data_t *raw, int offset) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void put_raw_data(res_t *res, raw_data_t *raw, int offset) | 
|  | { | 
|  | unsigned int wsize = raw->size - offset; | 
|  | if(res->allocsize - res->size < wsize) | 
|  | grow_res(res, wsize); | 
|  | memcpy(&(res->data[res->size]), raw->data + offset, wsize); | 
|  | res->size += wsize; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: put_res_header | 
|  | * Syntax	: input_res_header(res_t *res, int type, name_id_t *ntype, | 
|  | *				    name_id_t *name, DWORD memopt, lvc_t *lvc) | 
|  | * | 
|  | * Input	: | 
|  | *	res	- Binary resource descriptor to write to | 
|  | *	type	- Resource identifier (if ntype == NULL) | 
|  | *	ntype	- Name id of type | 
|  | *	name	- Resource's name | 
|  | *	memopt	- Resource's memory options to write | 
|  | *	lvc	- Language, version and characteristics (win32 only) | 
|  | * Output	: An index to the resource size field. The resource size field | 
|  | *		  contains the header size upon exit. | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static int put_res_header(res_t *res, int type, name_id_t *ntype, name_id_t *name, | 
|  | DWORD memopt, lvc_t *lvc) | 
|  | { | 
|  | if(win32) | 
|  | { | 
|  | put_dword(res, 0);		/* We will overwrite these later */ | 
|  | put_dword(res, 0); | 
|  | if(!ntype) | 
|  | { | 
|  | put_word(res, 0xffff);		/* ResType */ | 
|  | put_word(res, type); | 
|  | } | 
|  | else | 
|  | put_name_id(res, ntype, TRUE, lvc->language); | 
|  | put_name_id(res, name, TRUE, lvc->language); /* ResName */ | 
|  | put_pad(res); | 
|  | put_dword(res, 0);		/* DataVersion */ | 
|  | put_word(res, memopt);		/* Memory options */ | 
|  | put_lvc(res, lvc);		/* Language, version and characts */ | 
|  | set_dword(res, 0*sizeof(DWORD), res->size);	/* Set preliminary resource */ | 
|  | set_dword(res, 1*sizeof(DWORD), res->size);	/* Set HeaderSize */ | 
|  | res->dataidx = res->size; | 
|  | return 0; | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | int tag; | 
|  | if(!ntype) | 
|  | { | 
|  | put_byte(res, 0xff);		/* ResType */ | 
|  | put_word(res, type); | 
|  | } | 
|  | else | 
|  | put_name_id(res, ntype, TRUE, NULL); | 
|  | put_name_id(res, name, TRUE, NULL); /* ResName */ | 
|  | put_word(res, memopt);		/* Memory options */ | 
|  | tag = res->size; | 
|  | put_dword(res, 0);		/* ResSize overwritten later*/ | 
|  | set_dword(res, tag, res->size); | 
|  | res->dataidx = res->size; | 
|  | return tag; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: accelerator2res | 
|  | * Syntax	: res_t *accelerator2res(name_id_t *name, accelerator_t *acc) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	acc	- The accelerator descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *accelerator2res(name_id_t *name, accelerator_t *acc) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | event_t *ev; | 
|  | assert(name != NULL); | 
|  | assert(acc != NULL); | 
|  |  | 
|  | ev = acc->events; | 
|  | res = new_res(); | 
|  | if(win32) | 
|  | { | 
|  | restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, &(acc->lvc)); | 
|  | while(ev) | 
|  | { | 
|  | int key = ev->key; | 
|  | if (ev->str) key = parse_accel_string( ev->str, ev->flags ); | 
|  | put_word(res, ev->flags | (ev->next ? 0 : 0x80)); | 
|  | put_word(res, key); | 
|  | put_word(res, ev->id); | 
|  | put_word(res, 0);	/* Padding */ | 
|  | ev = ev->next; | 
|  | } | 
|  | put_pad(res); | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, NULL); | 
|  | while(ev) | 
|  | { | 
|  | int key = ev->key; | 
|  | if (ev->str) key = parse_accel_string( ev->str, ev->flags ); | 
|  | put_byte(res, ev->flags | (ev->next ? 0 : 0x80)); | 
|  | put_word(res, key); | 
|  | put_word(res, ev->id); | 
|  | ev = ev->next; | 
|  | } | 
|  | } | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: dialog2res | 
|  | * Syntax	: res_t *dialog2res(name_id_t *name, dialog_t *dlg) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	dlg	- The dialog descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *dialog2res(name_id_t *name, dialog_t *dlg) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | control_t *ctrl; | 
|  | int tag_nctrl; | 
|  | int nctrl = 0; | 
|  | assert(name != NULL); | 
|  | assert(dlg != NULL); | 
|  |  | 
|  | ctrl = dlg->controls; | 
|  | res = new_res(); | 
|  | if(win32) | 
|  | { | 
|  | restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, &(dlg->lvc)); | 
|  |  | 
|  | if (dlg->is_ex) | 
|  | { | 
|  | /* FIXME: MS doc says that the first word must contain 0xffff | 
|  | * and the second 0x0001 to signal a DLGTEMPLATEEX. Borland's | 
|  | * compiler reverses the two words. | 
|  | * I don't know which one to choose, but I write it as Mr. B | 
|  | * writes it. | 
|  | */ | 
|  | put_word(res, 1);		/* Signature */ | 
|  | put_word(res, 0xffff);		/* DlgVer */ | 
|  | put_dword(res, dlg->gothelpid ? dlg->helpid : 0); | 
|  | put_dword(res, dlg->gotexstyle ? dlg->exstyle->or_mask : 0); | 
|  | put_dword(res, dlg->gotstyle ? dlg->style->or_mask : WS_POPUPWINDOW); | 
|  | } | 
|  | else | 
|  | { | 
|  | put_dword(res, dlg->style->or_mask); | 
|  | put_dword(res, dlg->gotexstyle ? dlg->exstyle->or_mask : 0); | 
|  | } | 
|  | tag_nctrl = res->size; | 
|  | put_word(res, 0);		/* Number of controls */ | 
|  | put_word(res, dlg->x); | 
|  | put_word(res, dlg->y); | 
|  | put_word(res, dlg->width); | 
|  | put_word(res, dlg->height); | 
|  | if(dlg->menu) | 
|  | put_name_id(res, dlg->menu, TRUE, dlg->lvc.language); | 
|  | else | 
|  | put_word(res, 0); | 
|  | if(dlg->dlgclass) | 
|  | put_name_id(res, dlg->dlgclass, TRUE, dlg->lvc.language); | 
|  | else | 
|  | put_word(res, 0); | 
|  | if(dlg->title) | 
|  | put_string(res, dlg->title, str_unicode, TRUE, dlg->lvc.language); | 
|  | else | 
|  | put_word(res, 0); | 
|  | if(dlg->font) | 
|  | { | 
|  | put_word(res, dlg->font->size); | 
|  | if (dlg->is_ex) | 
|  | { | 
|  | put_word(res, dlg->font->weight); | 
|  | /* FIXME: ? TRUE should be sufficient to say that it's | 
|  | * italic, but Borland's compiler says it's 0x0101. | 
|  | * I just copy it here, and hope for the best. | 
|  | */ | 
|  | put_word(res, dlg->font->italic ? 0x0101 : 0); | 
|  | } | 
|  | put_string(res, dlg->font->name, str_unicode, TRUE, dlg->lvc.language); | 
|  | } | 
|  |  | 
|  | put_pad(res); | 
|  | while(ctrl) | 
|  | { | 
|  | if (dlg->is_ex) | 
|  | { | 
|  | put_dword(res, ctrl->gothelpid ? ctrl->helpid : 0); | 
|  | put_dword(res, ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0); | 
|  | /* FIXME: what is default control style? */ | 
|  | put_dword(res, ctrl->gotstyle ? ctrl->style->or_mask : WS_CHILD | WS_VISIBLE); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* FIXME: what is default control style? */ | 
|  | put_dword(res, ctrl->gotstyle ? ctrl->style->or_mask: WS_CHILD); | 
|  | put_dword(res, ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0); | 
|  | } | 
|  | put_word(res, ctrl->x); | 
|  | put_word(res, ctrl->y); | 
|  | put_word(res, ctrl->width); | 
|  | put_word(res, ctrl->height); | 
|  | if (dlg->is_ex) | 
|  | put_dword(res, ctrl->id); | 
|  | else | 
|  | put_word(res, ctrl->id); | 
|  | if(ctrl->ctlclass) | 
|  | put_name_id(res, ctrl->ctlclass, TRUE, dlg->lvc.language); | 
|  | else | 
|  | internal_error(__FILE__, __LINE__, "Control has no control-class\n"); | 
|  | if(ctrl->title) | 
|  | put_name_id(res, ctrl->title, FALSE, dlg->lvc.language); | 
|  | else | 
|  | put_word(res, 0); | 
|  | if(ctrl->extra) | 
|  | { | 
|  | put_word(res, ctrl->extra->size+2); | 
|  | put_pad(res); | 
|  | put_raw_data(res, ctrl->extra, 0); | 
|  | } | 
|  | else | 
|  | put_word(res, 0); | 
|  |  | 
|  | if(ctrl->next) | 
|  | put_pad(res); | 
|  | nctrl++; | 
|  | ctrl = ctrl->next; | 
|  | } | 
|  | /* Set number of controls */ | 
|  | set_word(res, tag_nctrl, (WORD)nctrl); | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, NULL); | 
|  |  | 
|  | put_dword(res, dlg->gotstyle ? dlg->style->or_mask : WS_POPUPWINDOW); | 
|  | tag_nctrl = res->size; | 
|  | put_byte(res, 0);		/* Number of controls */ | 
|  | put_word(res, dlg->x); | 
|  | put_word(res, dlg->y); | 
|  | put_word(res, dlg->width); | 
|  | put_word(res, dlg->height); | 
|  | if(dlg->menu) | 
|  | put_name_id(res, dlg->menu, TRUE, NULL); | 
|  | else | 
|  | put_byte(res, 0); | 
|  | if(dlg->dlgclass) | 
|  | put_name_id(res, dlg->dlgclass, TRUE, NULL); | 
|  | else | 
|  | put_byte(res, 0); | 
|  | if(dlg->title) | 
|  | put_string(res, dlg->title, str_char, TRUE, NULL); | 
|  | else | 
|  | put_byte(res, 0); | 
|  | if(dlg->font) | 
|  | { | 
|  | put_word(res, dlg->font->size); | 
|  | put_string(res, dlg->font->name, str_char, TRUE, NULL); | 
|  | } | 
|  |  | 
|  | while(ctrl) | 
|  | { | 
|  | put_word(res, ctrl->x); | 
|  | put_word(res, ctrl->y); | 
|  | put_word(res, ctrl->width); | 
|  | put_word(res, ctrl->height); | 
|  | put_word(res, ctrl->id); | 
|  | put_dword(res, ctrl->gotstyle ? ctrl->style->or_mask: WS_CHILD); | 
|  | if(ctrl->ctlclass) | 
|  | { | 
|  | if(ctrl->ctlclass->type == name_ord | 
|  | && ctrl->ctlclass->name.i_name >= 0x80 | 
|  | && ctrl->ctlclass->name.i_name <= 0x85) | 
|  | put_byte(res, ctrl->ctlclass->name.i_name); | 
|  | else if(ctrl->ctlclass->type == name_str) | 
|  | put_name_id(res, ctrl->ctlclass, FALSE, NULL); | 
|  | else | 
|  | error("Unknown control-class %04x\n", ctrl->ctlclass->name.i_name); | 
|  | } | 
|  | else | 
|  | internal_error(__FILE__, __LINE__, "Control has no control-class\n"); | 
|  | if(ctrl->title) | 
|  | put_name_id(res, ctrl->title, FALSE, NULL); | 
|  | else | 
|  | put_byte(res, 0); | 
|  |  | 
|  | /* FIXME: What is this extra byte doing here? */ | 
|  | put_byte(res, 0); | 
|  |  | 
|  | nctrl++; | 
|  | ctrl = ctrl->next; | 
|  | } | 
|  | /* Set number of controls */ | 
|  | ((char *)res->data)[tag_nctrl] = (char)nctrl; | 
|  | } | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: menuitem2res | 
|  | * Syntax	: void menuitem2res(res_t *res, menu_item_t *item) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: | 
|  | * Remarks	: Self recursive | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void menuitem2res(res_t *res, menu_item_t *menitem, const language_t *lang) | 
|  | { | 
|  | menu_item_t *itm = menitem; | 
|  | if(win32) | 
|  | { | 
|  | while(itm) | 
|  | { | 
|  | put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0)); | 
|  | if(!itm->popup) | 
|  | put_word(res, itm->id); | 
|  | if(itm->name) | 
|  | put_string(res, itm->name, str_unicode, TRUE, lang); | 
|  | else | 
|  | put_word(res, 0); | 
|  | if(itm->popup) | 
|  | menuitem2res(res, itm->popup, lang); | 
|  | itm = itm->next; | 
|  | } | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | while(itm) | 
|  | { | 
|  | put_word(res, itm->state | (itm->popup ? MF_POPUP : 0) | (!itm->next ? MF_END : 0)); | 
|  | if(!itm->popup) | 
|  | put_word(res, itm->id); | 
|  | if(itm->name) | 
|  | put_string(res, itm->name, str_char, TRUE, lang); | 
|  | else | 
|  | put_byte(res, 0); | 
|  | if(itm->popup) | 
|  | menuitem2res(res, itm->popup, lang); | 
|  | itm = itm->next; | 
|  | } | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: menuexitem2res | 
|  | * Syntax	: void menuexitem2res(res_t *res, menuex_item_t *item) | 
|  | * Input	: | 
|  | * Output	: nop | 
|  | * Description	: | 
|  | * Remarks	: Self recursive | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void menuexitem2res(res_t *res, menu_item_t *menitem, const language_t *lang) | 
|  | { | 
|  | menu_item_t *itm = menitem; | 
|  | assert(win32 != 0); | 
|  | while(itm) | 
|  | { | 
|  | put_dword(res, itm->gottype ? itm->type : 0); | 
|  | put_dword(res, itm->gotstate ? itm->state : 0); | 
|  | put_dword(res, itm->gotid ? itm->id : 0);	/* FIXME: Docu. says word */ | 
|  | put_word(res, (itm->popup ? 0x01 : 0) | (!itm->next ? MF_END : 0)); | 
|  | if(itm->name) | 
|  | put_string(res, itm->name, str_unicode, TRUE, lang); | 
|  | else | 
|  | put_word(res, 0); | 
|  | put_pad(res); | 
|  | if(itm->popup) | 
|  | { | 
|  | put_dword(res, itm->gothelpid ? itm->helpid : 0); | 
|  | menuexitem2res(res, itm->popup, lang); | 
|  | } | 
|  | itm = itm->next; | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: menu2res | 
|  | * Syntax	: res_t *menu2res(name_id_t *name, menu_t *men) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	menex	- The menuex descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *menu2res(name_id_t *name, menu_t *men) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(men != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | if(win32) | 
|  | { | 
|  | restag = put_res_header(res, WRC_RT_MENU, NULL, name, men->memopt, &(men->lvc)); | 
|  |  | 
|  | if (men->is_ex) | 
|  | { | 
|  | put_word(res, 1);		/* Menuheader: Version */ | 
|  | put_word(res, 4);		/* Offset */ | 
|  | put_dword(res, 0);		/* HelpId */ | 
|  | put_pad(res); | 
|  | menuexitem2res(res, men->items, men->lvc.language); | 
|  | } | 
|  | else | 
|  | { | 
|  | put_dword(res, 0);		/* Menuheader: Version and HeaderSize */ | 
|  | menuitem2res(res, men->items, men->lvc.language); | 
|  | } | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | put_pad(res); | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | restag = put_res_header(res, WRC_RT_MENU, NULL, name, men->memopt, NULL); | 
|  |  | 
|  | put_dword(res, 0);		/* Menuheader: Version and HeaderSize */ | 
|  | menuitem2res(res, men->items, NULL); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: cursorgroup2res | 
|  | * Syntax	: res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	curg	- The cursor descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *cursorgroup2res(name_id_t *name, cursor_group_t *curg) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | cursor_t *cur; | 
|  | assert(name != NULL); | 
|  | assert(curg != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_GROUP_CURSOR, NULL, name, curg->memopt, &(curg->lvc)); | 
|  | if(win32) | 
|  | { | 
|  | put_word(res, 0);	/* Reserved */ | 
|  | /* FIXME: The ResType in the NEWHEADER structure should | 
|  | * contain 14 according to the MS win32 doc. This is | 
|  | * not the case with the BRC compiler and I really doubt | 
|  | * the latter. Putting one here is compliant to win16 spec, | 
|  | * but who knows the true value? | 
|  | */ | 
|  | put_word(res, 2);	/* ResType */ | 
|  | put_word(res, curg->ncursor); | 
|  | #if 0 | 
|  | for(cur = curg->cursorlist; cur; cur = cur->next) | 
|  | #else | 
|  | cur = curg->cursorlist; | 
|  | while(cur->next) | 
|  | cur = cur->next; | 
|  | for(; cur; cur = cur->prev) | 
|  | #endif | 
|  | { | 
|  | put_word(res, cur->width); | 
|  | /* FIXME: The height of a cursor is half the size of | 
|  | * the bitmap's height. BRC puts the height from the | 
|  | * BITMAPINFOHEADER here instead of the cursorfile's | 
|  | * height. MS doesn't seem to care... | 
|  | */ | 
|  | put_word(res, cur->height); | 
|  | /* FIXME: The next two are reversed in BRC and I don't | 
|  | * know why. Probably a bug. But, we can safely ignore | 
|  | * it because win16 does not support color cursors. | 
|  | * A warning should have been generated by the parser. | 
|  | */ | 
|  | put_word(res, cur->planes); | 
|  | put_word(res, cur->bits); | 
|  | /* FIXME: The +4 is the hotspot in the cursor resource. | 
|  | * However, I could not find this in the documentation. | 
|  | * The hotspot bytes must either be included or MS | 
|  | * doesn't care. | 
|  | */ | 
|  | put_dword(res, cur->data->size +4); | 
|  | put_word(res, cur->id); | 
|  | } | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | put_word(res, 0);	/* Reserved */ | 
|  | put_word(res, 2);	/* ResType */ | 
|  | put_word(res, curg->ncursor); | 
|  | #if 0 | 
|  | for(cur = curg->cursorlist; cur; cur = cur->next) | 
|  | #else | 
|  | cur = curg->cursorlist; | 
|  | while(cur->next) | 
|  | cur = cur->next; | 
|  | for(; cur; cur = cur->prev) | 
|  | #endif | 
|  | { | 
|  | put_word(res, cur->width); | 
|  | /* FIXME: The height of a cursor is half the size of | 
|  | * the bitmap's height. BRC puts the height from the | 
|  | * BITMAPINFOHEADER here instead of the cursorfile's | 
|  | * height. MS doesn't seem to care... | 
|  | */ | 
|  | put_word(res, cur->height); | 
|  | /* FIXME: The next two are reversed in BRC and I don't | 
|  | * know why. Probably a bug. But, we can safely ignore | 
|  | * it because win16 does not support color cursors. | 
|  | * A warning should have been generated by the parser. | 
|  | */ | 
|  | put_word(res, cur->planes); | 
|  | put_word(res, cur->bits); | 
|  | /* FIXME: The +4 is the hotspot in the cursor resource. | 
|  | * However, I could not find this in the documentation. | 
|  | * The hotspot bytes must either be included or MS | 
|  | * doesn't care. | 
|  | */ | 
|  | put_dword(res, cur->data->size +4); | 
|  | put_word(res, cur->id); | 
|  | } | 
|  | } | 
|  | SetResSize(res, restag);	/* Set ResourceSize */ | 
|  | if(win32) | 
|  | put_pad(res); | 
|  |  | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: cursor2res | 
|  | * Syntax	: res_t *cursor2res(cursor_t *cur) | 
|  | * Input	: | 
|  | *	cur	- The cursor descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *cursor2res(cursor_t *cur) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | name_id_t name; | 
|  |  | 
|  | assert(cur != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | name.type = name_ord; | 
|  | name.name.i_name = cur->id; | 
|  | restag = put_res_header(res, WRC_RT_CURSOR, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &(cur->lvc)); | 
|  | put_word(res, cur->xhot); | 
|  | put_word(res, cur->yhot); | 
|  | put_raw_data(res, cur->data, 0); | 
|  |  | 
|  | SetResSize(res, restag);	/* Set ResourceSize */ | 
|  | if(win32) | 
|  | put_pad(res); | 
|  |  | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: icongroup2res | 
|  | * Syntax	: res_t *icongroup2res(name_id_t *name, icon_group_t *icog) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	icog	- The icon group descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *icongroup2res(name_id_t *name, icon_group_t *icog) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | icon_t *ico; | 
|  | assert(name != NULL); | 
|  | assert(icog != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_GROUP_ICON, NULL, name, icog->memopt, &(icog->lvc)); | 
|  | if(win32) | 
|  | { | 
|  | put_word(res, 0);	/* Reserved */ | 
|  | /* FIXME: The ResType in the NEWHEADER structure should | 
|  | * contain 14 according to the MS win32 doc. This is | 
|  | * not the case with the BRC compiler and I really doubt | 
|  | * the latter. Putting one here is compliant to win16 spec, | 
|  | * but who knows the true value? | 
|  | */ | 
|  | put_word(res, 1);	/* ResType */ | 
|  | put_word(res, icog->nicon); | 
|  | for(ico = icog->iconlist; ico; ico = ico->next) | 
|  | { | 
|  | put_byte(res, ico->width); | 
|  | put_byte(res, ico->height); | 
|  | put_byte(res, ico->nclr); | 
|  | put_byte(res, 0);	/* Reserved */ | 
|  | put_word(res, ico->planes); | 
|  | put_word(res, ico->bits); | 
|  | put_dword(res, ico->data->size); | 
|  | put_word(res, ico->id); | 
|  | } | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | put_word(res, 0);	/* Reserved */ | 
|  | put_word(res, 1);	/* ResType */ | 
|  | put_word(res, icog->nicon); | 
|  | for(ico = icog->iconlist; ico; ico = ico->next) | 
|  | { | 
|  | put_byte(res, ico->width); | 
|  | put_byte(res, ico->height); | 
|  | put_byte(res, ico->nclr); | 
|  | put_byte(res, 0);	/* Reserved */ | 
|  | put_word(res, ico->planes); | 
|  | put_word(res, ico->bits); | 
|  | put_dword(res, ico->data->size); | 
|  | put_word(res, ico->id); | 
|  | } | 
|  | } | 
|  | SetResSize(res, restag);	/* Set ResourceSize */ | 
|  | if(win32) | 
|  | put_pad(res); | 
|  |  | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: icon2res | 
|  | * Syntax	: res_t *icon2res(icon_t *ico) | 
|  | * Input	: | 
|  | *	ico	- The icon descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *icon2res(icon_t *ico) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | name_id_t name; | 
|  |  | 
|  | assert(ico != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | name.type = name_ord; | 
|  | name.name.i_name = ico->id; | 
|  | restag = put_res_header(res, WRC_RT_ICON, NULL, &name, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, &(ico->lvc)); | 
|  | put_raw_data(res, ico->data, 0); | 
|  |  | 
|  | SetResSize(res, restag);	/* Set ResourceSize */ | 
|  | if(win32) | 
|  | put_pad(res); | 
|  |  | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: anicurico2res | 
|  | * Syntax	: res_t *anicurico2res(name_id_t *name, ani_curico_t *ani) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	ani	- The animated object descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: The endian of the object's structures have been converted | 
|  | * 		  by the loader. | 
|  | * 		  There are rumors that win311 could handle animated stuff. | 
|  | * 		  That is why they are generated for both win16 and win32 | 
|  | * 		  compile. | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *anicurico2res(name_id_t *name, ani_curico_t *ani, enum res_e type) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(ani != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, type == res_anicur ? WRC_RT_ANICURSOR : WRC_RT_ANIICON, | 
|  | NULL, name, ani->memopt, NULL); | 
|  | put_raw_data(res, ani->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: bitmap2res | 
|  | * Syntax	: res_t *bitmap2res(name_id_t *name, bitmap_t *bmp) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	bmp	- The bitmap descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: The endian of the bitmap structures have been converted | 
|  | * 		  by the loader. | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *bitmap2res(name_id_t *name, bitmap_t *bmp) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(bmp != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_BITMAP, NULL, name, bmp->memopt, &(bmp->data->lvc)); | 
|  | if(bmp->data->data[0] == 'B' | 
|  | && bmp->data->data[1] == 'M' | 
|  | && ((BITMAPFILEHEADER *)bmp->data->data)->bfSize == bmp->data->size | 
|  | && bmp->data->size >= sizeof(BITMAPFILEHEADER)) | 
|  | { | 
|  | /* The File header is still attached, don't write it */ | 
|  | put_raw_data(res, bmp->data, sizeof(BITMAPFILEHEADER)); | 
|  | } | 
|  | else | 
|  | { | 
|  | put_raw_data(res, bmp->data, 0); | 
|  | } | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: font2res | 
|  | * Syntax	: res_t *font2res(name_id_t *name, font_t *fnt) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	fnt	- The font descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: The data has been prepared just after parsing. | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *font2res(name_id_t *name, font_t *fnt) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(fnt != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_FONT, NULL, name, fnt->memopt, &(fnt->data->lvc)); | 
|  | put_raw_data(res, fnt->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: fontdir2res | 
|  | * Syntax	: res_t *fontdir2res(name_id_t *name, fontdir_t *fnd) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	fntdir	- The fontdir descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: The data has been prepared just after parsing. | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *fontdir2res(name_id_t *name, fontdir_t *fnd) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(fnd != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_FONTDIR, NULL, name, fnd->memopt, &(fnd->data->lvc)); | 
|  | put_raw_data(res, fnd->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: html2res | 
|  | * Syntax	: res_t *html2res(name_id_t *name, html_t *html) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	rdt	- The html descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *html2res(name_id_t *name, html_t *html) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(html != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_HTML, NULL, name, html->memopt, &(html->data->lvc)); | 
|  | put_raw_data(res, html->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: rcdata2res | 
|  | * Syntax	: res_t *rcdata2res(name_id_t *name, rcdata_t *rdt) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	rdt	- The rcdata descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *rcdata2res(name_id_t *name, rcdata_t *rdt) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(rdt != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_RCDATA, NULL, name, rdt->memopt, &(rdt->data->lvc)); | 
|  | put_raw_data(res, rdt->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: messagetable2res | 
|  | * Syntax	: res_t *messagetable2res(name_id_t *name, messagetable_t *msg) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	msg	- The messagetable descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: The data has been converted to the appropriate endian | 
|  | *		  after it was parsed. | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *messagetable2res(name_id_t *name, messagetable_t *msg) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(msg != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_MESSAGETABLE, NULL, name, msg->memopt, &(msg->data->lvc)); | 
|  | put_raw_data(res, msg->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: stringtable2res | 
|  | * Syntax	: res_t *stringtable2res(stringtable_t *stt) | 
|  | * Input	: | 
|  | *	stt	- The stringtable descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *stringtable2res(stringtable_t *stt) | 
|  | { | 
|  | res_t *res; | 
|  | name_id_t name; | 
|  | int i; | 
|  | int restag; | 
|  | DWORD lastsize = 0; | 
|  |  | 
|  | assert(stt != NULL); | 
|  | res = new_res(); | 
|  |  | 
|  | for(; stt; stt = stt->next) | 
|  | { | 
|  | if(!stt->nentries) | 
|  | { | 
|  | warning("Empty internal stringtable\n"); | 
|  | continue; | 
|  | } | 
|  | name.type = name_ord; | 
|  | name.name.i_name = (stt->idbase >> 4) + 1; | 
|  | restag = put_res_header(res, WRC_RT_STRING, NULL, &name, stt->memopt, win32 ? &(stt->lvc) : NULL); | 
|  | for(i = 0; i < stt->nentries; i++) | 
|  | { | 
|  | if(stt->entries[i].str && stt->entries[i].str->size) | 
|  | { | 
|  | put_string(res, stt->entries[i].str, win32 ? str_unicode : str_char, | 
|  | FALSE, win32 ? stt->lvc.language : NULL); | 
|  | } | 
|  | else | 
|  | { | 
|  | if (win32) | 
|  | put_word(res, 0); | 
|  | else | 
|  | put_byte(res, 0); | 
|  | } | 
|  | } | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag - lastsize); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | lastsize = res->size; | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: user2res | 
|  | * Syntax	: res_t *user2res(name_id_t *name, user_t *usr) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	usr	- The userresource descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *user2res(name_id_t *name, user_t *usr) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(usr != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, 0, usr->type, name, usr->memopt, &(usr->data->lvc)); | 
|  | put_raw_data(res, usr->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: versionblock2res | 
|  | * Syntax	: void versionblock2res(res_t *res, ver_block_t *blk) | 
|  | * Input	: | 
|  | *	res	- Binary resource to write to | 
|  | *	blk	- The version block to be written | 
|  | * Output	: | 
|  | * Description	: | 
|  | * Remarks	: Self recursive | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void versionblock2res(res_t *res, ver_block_t *blk, int level, const language_t *lang) | 
|  | { | 
|  | ver_value_t *val; | 
|  | int blksizetag; | 
|  | int valblksizetag; | 
|  | int valvalsizetag; | 
|  | int tag; | 
|  | int i; | 
|  |  | 
|  | blksizetag = res->size; | 
|  | put_word(res, 0);	/* Will be overwritten later */ | 
|  | put_word(res, 0); | 
|  | if(win32) | 
|  | put_word(res, 0);	/* level ? */ | 
|  | put_string(res, blk->name, win32 ? str_unicode : str_char, TRUE, lang); | 
|  | put_pad(res); | 
|  | for(val = blk->values; val; val = val->next) | 
|  | { | 
|  | if(val->type == val_str) | 
|  | { | 
|  | valblksizetag = res->size; | 
|  | put_word(res, 0);	/* Will be overwritten later */ | 
|  | valvalsizetag = res->size; | 
|  | put_word(res, 0);	/* Will be overwritten later */ | 
|  | if(win32) | 
|  | { | 
|  | put_word(res, level); | 
|  | } | 
|  | put_string(res, val->key, win32 ? str_unicode : str_char, TRUE, lang); | 
|  | put_pad(res); | 
|  | tag = res->size; | 
|  | put_string(res, val->value.str, win32 ? str_unicode : str_char, TRUE, lang); | 
|  | if(win32) | 
|  | set_word(res, valvalsizetag, (WORD)((res->size - tag) >> 1)); | 
|  | else | 
|  | set_word(res, valvalsizetag, (WORD)(res->size - tag)); | 
|  | set_word(res, valblksizetag, (WORD)(res->size - valblksizetag)); | 
|  | put_pad(res); | 
|  | } | 
|  | else if(val->type == val_words) | 
|  | { | 
|  | valblksizetag = res->size; | 
|  | put_word(res, 0);	/* Will be overwritten later */ | 
|  | valvalsizetag = res->size; | 
|  | put_word(res, 0);	/* Will be overwritten later */ | 
|  | if(win32) | 
|  | { | 
|  | put_word(res, level); | 
|  | } | 
|  | put_string(res, val->key, win32 ? str_unicode : str_char, TRUE, lang); | 
|  | put_pad(res); | 
|  | tag = res->size; | 
|  | for(i = 0; i < val->value.words->nwords; i++) | 
|  | { | 
|  | put_word(res, val->value.words->words[i]); | 
|  | } | 
|  | set_word(res, valvalsizetag, (WORD)(res->size - tag)); | 
|  | set_word(res, valblksizetag, (WORD)(res->size - valblksizetag)); | 
|  | put_pad(res); | 
|  | } | 
|  | else if(val->type == val_block) | 
|  | { | 
|  | versionblock2res(res, val->value.block, level+1, lang); | 
|  | } | 
|  | else | 
|  | { | 
|  | internal_error(__FILE__, __LINE__, "Invalid value indicator %d in VERSIONINFO\n", val->type); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Set blocksize */ | 
|  | set_word(res, blksizetag, (WORD)(res->size - blksizetag)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: versioninfo2res | 
|  | * Syntax	: res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	ver	- The versioninfo descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver) | 
|  | { | 
|  | int restag; | 
|  | int rootblocksizetag; | 
|  | int valsizetag; | 
|  | int tag; | 
|  | res_t *res; | 
|  | string_t vsvi; | 
|  | ver_block_t *blk; | 
|  |  | 
|  | assert(name != NULL); | 
|  | assert(ver != NULL); | 
|  |  | 
|  | vsvi.type = str_char; | 
|  | vsvi.str.cstr = xstrdup("VS_VERSION_INFO"); | 
|  | vsvi.size = 15; /* Excl. termination */ | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_VERSION, NULL, name, ver->memopt, &(ver->lvc)); | 
|  | rootblocksizetag = res->size; | 
|  | put_word(res, 0);	/* BlockSize filled in later */ | 
|  | valsizetag = res->size; | 
|  | put_word(res, 0);	/* ValueSize filled in later*/ | 
|  | if(win32) | 
|  | put_word(res, 0);	/* Tree-level ? */ | 
|  | put_string(res, &vsvi, win32 ? str_unicode : str_char, | 
|  | TRUE, win32 ? ver->lvc.language : NULL); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | tag = res->size; | 
|  | put_dword(res, VS_FFI_SIGNATURE); | 
|  | put_dword(res, VS_FFI_STRUCVERSION); | 
|  | put_dword(res, (ver->filever_maj1 << 16) + (ver->filever_maj2 & 0xffff)); | 
|  | put_dword(res, (ver->filever_min1 << 16) + (ver->filever_min2 & 0xffff)); | 
|  | put_dword(res, (ver->prodver_maj1 << 16) + (ver->prodver_maj2 & 0xffff)); | 
|  | put_dword(res, (ver->prodver_min1 << 16) + (ver->prodver_min2 & 0xffff)); | 
|  | put_dword(res, ver->fileflagsmask); | 
|  | put_dword(res, ver->fileflags); | 
|  | put_dword(res, ver->fileos); | 
|  | put_dword(res, ver->filetype); | 
|  | put_dword(res, ver->filesubtype); | 
|  | put_dword(res, 0);		/* FileDateMS */ | 
|  | put_dword(res, 0);		/* FileDateLS */ | 
|  | /* Set ValueSize */ | 
|  | set_word(res, valsizetag, (WORD)(res->size - tag)); | 
|  | /* Descend into the blocks */ | 
|  | for(blk = ver->blocks; blk; blk = blk->next) | 
|  | versionblock2res(res, blk, 0, win32 ? ver->lvc.language : NULL); | 
|  | /* Set root block's size */ | 
|  | set_word(res, rootblocksizetag, (WORD)(res->size - rootblocksizetag)); | 
|  |  | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  |  | 
|  | free(vsvi.str.cstr); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: toolbaritem2res | 
|  | * Syntax	: void toolbaritem2res(res_t *res, toolbar_item_t *tbitem) | 
|  | * Input	: | 
|  | * Output	: nop | 
|  | * Description	: | 
|  | * Remarks	: Self recursive | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static void toolbaritem2res(res_t *res, toolbar_item_t *tbitem) | 
|  | { | 
|  | toolbar_item_t *itm = tbitem; | 
|  | assert(win32 != 0); | 
|  | while(itm) | 
|  | { | 
|  | put_word(res, itm->id); | 
|  | itm = itm->next; | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: toolbar2res | 
|  | * Syntax	: res_t *toolbar2res(name_id_t *name, toolbar_t *toolbar) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	toolbar	- The toolbar descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *toolbar2res(name_id_t *name, toolbar_t *toolbar) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(toolbar != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | if(win32) | 
|  | { | 
|  | restag = put_res_header(res, WRC_RT_TOOLBAR, NULL, name, toolbar->memopt, &(toolbar->lvc)); | 
|  |  | 
|  | put_word(res, 1);		/* Menuheader: Version */ | 
|  | put_word(res, toolbar->button_width); /* (in pixels?) */ | 
|  | put_word(res, toolbar->button_height); /* (in pixels?) */ | 
|  | put_word(res, toolbar->nitems); | 
|  | put_pad(res); | 
|  | toolbaritem2res(res, toolbar->items); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | put_pad(res); | 
|  | } | 
|  | else /* win16 */ | 
|  | { | 
|  | /* Do not generate anything in 16-bit mode */ | 
|  | free(res->data); | 
|  | free(res); | 
|  | return NULL; | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: dlginit2res | 
|  | * Syntax	: res_t *dlginit2res(name_id_t *name, dlginit_t *dit) | 
|  | * Input	: | 
|  | *	name	- Name/ordinal of the resource | 
|  | *	rdt	- The dlginit descriptor | 
|  | * Output	: New .res format structure | 
|  | * Description	: | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | static res_t *dlginit2res(name_id_t *name, dlginit_t *dit) | 
|  | { | 
|  | int restag; | 
|  | res_t *res; | 
|  | assert(name != NULL); | 
|  | assert(dit != NULL); | 
|  |  | 
|  | res = new_res(); | 
|  | restag = put_res_header(res, WRC_RT_DLGINIT, NULL, name, dit->memopt, &(dit->data->lvc)); | 
|  | put_raw_data(res, dit->data, 0); | 
|  | /* Set ResourceSize */ | 
|  | SetResSize(res, restag); | 
|  | if(win32) | 
|  | put_pad(res); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: prep_nid_for_label | 
|  | * Syntax	: char *prep_nid_for_label(const name_id_t *nid) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: Converts a resource name into the first 32 (or less) | 
|  | *		  characters of the name with conversions. | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | #define MAXNAMELEN	32 | 
|  | char *prep_nid_for_label(const name_id_t *nid) | 
|  | { | 
|  | static char buf[MAXNAMELEN+1]; | 
|  |  | 
|  | assert(nid != NULL); | 
|  |  | 
|  | if(nid->type == name_str && nid->name.s_name->type == str_unicode) | 
|  | { | 
|  | WCHAR *sptr; | 
|  | int i; | 
|  | sptr = nid->name.s_name->str.wstr; | 
|  | buf[0] = '\0'; | 
|  | for(i = 0; *sptr && i < MAXNAMELEN; i++) | 
|  | { | 
|  | if((unsigned)*sptr < 0x80 && isprint(*sptr & 0xff)) | 
|  | buf[i] = *sptr++; | 
|  | else | 
|  | warning("Resourcename (str_unicode) contain unprintable characters or invalid translation, ignored\n"); | 
|  | } | 
|  | buf[i] = '\0'; | 
|  | } | 
|  | else if(nid->type == name_str && nid->name.s_name->type == str_char) | 
|  | { | 
|  | char *cptr; | 
|  | int i; | 
|  | cptr = nid->name.s_name->str.cstr; | 
|  | buf[0] = '\0'; | 
|  | for(i = 0; *cptr && i < MAXNAMELEN; i++) | 
|  | { | 
|  | if((unsigned)*cptr < 0x80 && isprint(*cptr & 0xff)) | 
|  | buf[i] = *cptr++; | 
|  | else | 
|  | warning("Resourcename (str_char) contain unprintable characters, ignored\n"); | 
|  | } | 
|  | buf[i] = '\0'; | 
|  | } | 
|  | else if(nid->type == name_ord) | 
|  | { | 
|  | sprintf(buf, "%u", nid->name.i_name); | 
|  | } | 
|  | else | 
|  | { | 
|  | internal_error(__FILE__, __LINE__, "Resource name_id with invalid type %d\n", nid->type); | 
|  | } | 
|  | return buf; | 
|  | } | 
|  | #undef MAXNAMELEN | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: make_c_name | 
|  | * Syntax	: char *make_c_name(const char *base, const name_id_t *nid, const language_t *lan) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: Converts a resource name into a valid c-identifier in the | 
|  | *		  form "_base_nid". | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | char *make_c_name(const char *base, const name_id_t *nid, const language_t *lan) | 
|  | { | 
|  | char *buf = prep_nid_for_label(nid); | 
|  | return strmake( "_%s_%s_%d", base, buf, lan ? MAKELANGID(lan->id, lan->sub) : 0); | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: get_c_typename | 
|  | * Syntax	: const char *get_c_typename(enum res_e type) | 
|  | * Input	: | 
|  | * Output	: | 
|  | * Description	: Convert resource enum to char string to be used in c-name | 
|  | *		  creation. | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | const char *get_c_typename(enum res_e type) | 
|  | { | 
|  | switch(type) | 
|  | { | 
|  | case res_acc:	return "Acc"; | 
|  | case res_anicur:return "AniCur"; | 
|  | case res_aniico:return "AniIco"; | 
|  | case res_bmp:	return "Bmp"; | 
|  | case res_cur:	return "Cur"; | 
|  | case res_curg:	return "CurGrp"; | 
|  | case res_dlg:	return "Dlg"; | 
|  | case res_fnt:	return "Fnt"; | 
|  | case res_fntdir:return "FntDir"; | 
|  | case res_ico:	return "Ico"; | 
|  | case res_icog:	return "IcoGrp"; | 
|  | case res_men:	return "Men"; | 
|  | case res_rdt:	return "RCDat"; | 
|  | case res_stt:	return "StrTab"; | 
|  | case res_usr:	return "Usr"; | 
|  | case res_msg:	return "MsgTab"; | 
|  | case res_ver:	return "VerInf"; | 
|  | case res_toolbar:	return "TlBr"; | 
|  | case res_dlginit: return "DlgInit"; | 
|  | default:	return "Oops"; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | ***************************************************************************** | 
|  | * Function	: resources2res | 
|  | * Syntax	: void resources2res(resource_t *top) | 
|  | * Input	: | 
|  | *	top	- The resource-tree to convert | 
|  | * Output	: | 
|  | * Description	: Convert logical resource descriptors into binary data | 
|  | * Remarks	: | 
|  | ***************************************************************************** | 
|  | */ | 
|  | void resources2res(resource_t *top) | 
|  | { | 
|  | while(top) | 
|  | { | 
|  | switch(top->type) | 
|  | { | 
|  | case res_acc: | 
|  | if(!top->binres) | 
|  | top->binres = accelerator2res(top->name, top->res.acc); | 
|  | break; | 
|  | case res_bmp: | 
|  | if(!top->binres) | 
|  | top->binres = bitmap2res(top->name, top->res.bmp); | 
|  | break; | 
|  | case res_cur: | 
|  | if(!top->binres) | 
|  | top->binres = cursor2res(top->res.cur); | 
|  | break; | 
|  | case res_curg: | 
|  | if(!top->binres) | 
|  | top->binres = cursorgroup2res(top->name, top->res.curg); | 
|  | break; | 
|  | case res_dlg: | 
|  | if(!top->binres) | 
|  | top->binres = dialog2res(top->name, top->res.dlg); | 
|  | break; | 
|  | case res_fnt: | 
|  | if(!top->binres) | 
|  | top->binres = font2res(top->name, top->res.fnt); | 
|  | break; | 
|  | case res_fntdir: | 
|  | if(!top->binres) | 
|  | top->binres = fontdir2res(top->name, top->res.fnd); | 
|  | break; | 
|  | case res_ico: | 
|  | if(!top->binres) | 
|  | top->binres = icon2res(top->res.ico); | 
|  | break; | 
|  | case res_icog: | 
|  | if(!top->binres) | 
|  | top->binres = icongroup2res(top->name, top->res.icog); | 
|  | break; | 
|  | case res_men: | 
|  | if(!top->binres) | 
|  | top->binres = menu2res(top->name, top->res.men); | 
|  | break; | 
|  | case res_html: | 
|  | if(!top->binres) | 
|  | top->binres = html2res(top->name, top->res.html); | 
|  | break; | 
|  | case res_rdt: | 
|  | if(!top->binres) | 
|  | top->binres = rcdata2res(top->name, top->res.rdt); | 
|  | break; | 
|  | case res_stt: | 
|  | if(!top->binres) | 
|  | top->binres = stringtable2res(top->res.stt); | 
|  | break; | 
|  | case res_usr: | 
|  | if(!top->binres) | 
|  | top->binres = user2res(top->name, top->res.usr); | 
|  | break; | 
|  | case res_msg: | 
|  | if(!top->binres) | 
|  | top->binres = messagetable2res(top->name, top->res.msg); | 
|  | break; | 
|  | case res_ver: | 
|  | if(!top->binres) | 
|  | top->binres = versioninfo2res(top->name, top->res.ver); | 
|  | break; | 
|  | case res_toolbar: | 
|  | if(!top->binres) | 
|  | top->binres = toolbar2res(top->name, top->res.tbt); | 
|  | break; | 
|  | case res_dlginit: | 
|  | if(!top->binres) | 
|  | top->binres = dlginit2res(top->name, top->res.dlgi); | 
|  | break; | 
|  | case res_anicur: | 
|  | case res_aniico: | 
|  | if(!top->binres) | 
|  | top->binres = anicurico2res(top->name, top->res.ani, top->type); | 
|  | break; | 
|  | default: | 
|  | internal_error(__FILE__, __LINE__, "Unknown resource type encountered %d in binary res generation\n", top->type); | 
|  | } | 
|  | top->c_name = make_c_name(get_c_typename(top->type), top->name, top->lan); | 
|  | top = top->next; | 
|  | } | 
|  | } |