Correct usage of a scratch array in X11DRV_PolyBezier.
[wine.git] / tools / wrc / readres.c
blob776c6595be6dc5bfa0b0ca6c20824a61a125624b
1 /*
2 * Read a .res file and create a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
6 */
8 #include "config.h"
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <assert.h>
15 #include "wrc.h"
16 #include "readres.h"
17 #include "newstruc.h"
18 #include "utils.h"
19 #include "genres.h"
21 struct resheader32 {
22 DWORD ressize; /* 0 */
23 DWORD hdrsize; /* 0x20 */
24 WORD restype1; /* 0xffff */
25 WORD restype2; /* 0 */
26 WORD resname1; /* 0xffff */
27 WORD resname2; /* 0 */
28 DWORD dversion; /* 0 */
29 WORD memopt; /* 0 */
30 WORD language; /* 0 */
31 DWORD version; /* 0 */
32 DWORD characts; /* 0 */
33 } emptyheader = {0, 0x20, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0};
36 *****************************************************************************
37 * Function :
38 * Syntax :
39 * Input :
40 * Output :
41 * Description :
42 * Remarks :
43 *****************************************************************************
46 *****************************************************************************
47 * Function :
48 * Syntax :
49 * Input :
50 * Output :
51 * Description :
52 * Remarks :
53 *****************************************************************************
56 *****************************************************************************
57 * Function :
58 * Syntax :
59 * Input :
60 * Output :
61 * Description :
62 * Remarks :
63 *****************************************************************************
65 int read_data(FILE *fp, size_t size, void *buf)
67 int r;
68 int pos = ftell(fp);
69 r = fread(buf, 1, size, fp);
70 if(r == size)
71 return 0;
72 if(r == 0 && ftell(fp) - pos > 0)
73 return 1;
74 else
75 return -1;
79 *****************************************************************************
80 * Function :
81 * Syntax :
82 * Input :
83 * Output :
84 * Description :
85 * Remarks :
86 *****************************************************************************
88 enum res_e res_type_from_id(name_id_t *nid)
90 if(nid->type == name_str)
91 return res_usr;
93 if(nid->type != name_ord)
94 internal_error(__FILE__, __LINE__, "Invalid name_id descriptor %d", nid->type);
96 switch(nid->name.i_name)
98 case WRC_RT_CURSOR: return res_cur;
99 case WRC_RT_BITMAP: return res_bmp;
100 case WRC_RT_ICON: return res_ico;
101 case WRC_RT_MENU: return res_men;
102 case WRC_RT_DIALOG: return res_dlg;
103 case WRC_RT_STRING: return res_stt;
104 case WRC_RT_FONTDIR: return res_fntdir;
105 case WRC_RT_FONT: return res_fnt;
106 case WRC_RT_ACCELERATOR: return res_acc;
107 case WRC_RT_RCDATA: return res_rdt;
108 case WRC_RT_MESSAGETABLE: return res_msg;
109 case WRC_RT_GROUP_CURSOR: return res_curg;
110 case WRC_RT_GROUP_ICON: return res_icog;
111 case WRC_RT_VERSION: return res_ver;
112 case WRC_RT_TOOLBAR: return res_toolbar;
114 default:
115 case WRC_RT_DLGINCLUDE:
116 case WRC_RT_PLUGPLAY:
117 case WRC_RT_VXD:
118 case WRC_RT_ANICURSOR:
119 case WRC_RT_ANIICON:
120 warning("Cannot be sure of resource type, using usertype settings");
121 return res_usr;
126 *****************************************************************************
127 * Function :
128 * Syntax :
129 * Input :
130 * Output :
131 * Description :
132 * Remarks :
133 *****************************************************************************
135 #define get_word(idx) (*((WORD *)(&res->data[idx])))
136 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
138 resource_t *read_res32(FILE *fp)
140 static char wrong_format[] = "Wrong resfile format (32bit)";
141 DWORD ressize;
142 DWORD hdrsize;
143 DWORD totsize;
144 WORD memopt;
145 WORD language;
146 int err;
147 res_t *res;
148 resource_t *rsc;
149 resource_t *tail = NULL;
150 resource_t *list = NULL;
151 name_id_t *type = NULL;
152 name_id_t *name = NULL;
153 int idx;
154 enum res_e res_type;
155 user_t *usrres;
157 while(1)
159 /* Get headersize and resource size */
160 err = read_data(fp, sizeof(ressize), &ressize);
161 if(err < 0)
162 break;
163 else if(err > 0)
164 error(wrong_format);
165 err = read_data(fp, sizeof(hdrsize), &hdrsize);
166 if(err)
167 error(wrong_format);
169 /* Align sizes and compute total size */
170 totsize = hdrsize;
171 if(hdrsize & 3)
173 warning("Hu? .res header needed alignment (anything can happen now)");
174 totsize += 4 - (hdrsize & 3);
176 totsize += ressize;
177 if(ressize & 3)
178 totsize += 4 - (ressize & 3);
180 /* Read in entire data-block */
181 fseek(fp, -8, SEEK_CUR);
182 res = new_res();
183 if(res->allocsize < totsize)
184 grow_res(res, totsize - res->allocsize + 8);
185 err = read_data(fp, totsize, res->data);
186 if(err)
187 error(wrong_format);
189 res->dataidx = hdrsize;
190 res->size = hdrsize + ressize;
192 /* Analyse the content of the header */
193 idx = 8;
194 /* Get restype */
195 if(get_word(idx) == 0xffff)
197 idx += sizeof(WORD);
198 type = new_name_id();
199 type->type = name_ord;
200 type->name.i_name = get_word(idx);
201 idx += sizeof(WORD);
203 else if(get_word(idx) == 0)
205 error("ResType name has zero length (32 bit)");
207 else
209 int tag = idx;
210 string_t *str;
211 while(1)
213 idx += sizeof(WORD);
214 if(!get_word(idx))
215 break;
217 idx += sizeof(WORD);
218 str = new_string();
219 str->type = str_unicode;
220 str->size = (idx - tag) / 2;
221 str->str.wstr = (short *)xmalloc(idx-tag+2);
222 memcpy(str->str.wstr, &res->data[tag], idx-tag);
223 str->str.wstr[str->size] = 0;
224 type = new_name_id();
225 type->type = name_str;
226 type->name.s_name = str;
228 /* Get resname */
229 if(get_word(idx) == 0xffff)
231 idx += sizeof(WORD);
232 name = new_name_id();
233 name->type = name_ord;
234 name->name.i_name = get_word(idx);
235 idx += sizeof(WORD);
237 else if(get_word(idx) == 0)
239 error("ResName name has zero length (32 bit)");
241 else
243 int tag = idx;
244 string_t *str;
245 while(1)
247 idx += sizeof(WORD);
248 if(!get_word(idx))
249 break;
251 idx += sizeof(WORD);
252 str = new_string();
253 str->type = str_unicode;
254 str->size = (idx - tag) / 2;
255 str->str.wstr = (short *)xmalloc(idx-tag+2);
256 memcpy(str->str.wstr, &res->data[tag], idx-tag);
257 str->str.wstr[str->size] = 0;
258 name = new_name_id();
259 name->type = name_str;
260 name->name.s_name = str;
263 /* align */
264 if(idx & 0x3)
265 idx += 4 - (idx & 3);
267 idx += sizeof(DWORD); /* Skip DataVersion */
268 memopt = get_word(idx);
269 idx += sizeof(WORD);
270 language = get_word(idx);
272 /* Build a resource_t list */
273 res_type = res_type_from_id(type);
274 if(res_type == res_usr)
276 /* User-type has custom ResType for .[s|h] generation */
277 usrres = new_user(type, NULL, new_int(memopt));
279 else
280 usrres = NULL;
281 rsc = new_resource(res_type,
282 usrres,
283 memopt,
284 new_language(PRIMARYLANGID(language),
285 SUBLANGID(language)));
286 rsc->binres = res;
287 rsc->name = name;
288 rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
289 if(!list)
291 list = rsc;
292 tail = rsc;
294 else
296 rsc->prev = tail;
297 tail->next = rsc;
298 tail = rsc;
301 return list;
305 *****************************************************************************
306 * Function :
307 * Syntax :
308 * Input :
309 * Output :
310 * Description :
311 * Remarks :
312 *****************************************************************************
314 resource_t *read_res16(FILE *fp)
316 internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files");
317 return NULL;
321 *****************************************************************************
322 * Function : read_resfile
323 * Syntax : resource_t *read_resfile(char *inname)
324 * Input :
325 * Output :
326 * Description :
327 * Remarks :
328 *****************************************************************************
330 resource_t *read_resfile(char *inname)
332 FILE *fp;
333 struct resheader32 rh;
334 int is32bit;
335 resource_t *top;
337 fp = fopen(inname, "rb");
338 if(!fp)
339 error("Could not open inputfile %s", inname);
341 /* Determine 16 or 32 bit .res file */
342 if(fread(&rh, 1, sizeof(rh), fp) != sizeof(rh))
343 is32bit = 0;
344 else
346 if(!memcmp(&emptyheader, &rh, sizeof(rh)))
347 is32bit = 1;
348 else
349 is32bit = 0;
352 if(is32bit && !win32)
353 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
355 if(!is32bit && win32)
356 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
358 if(!is32bit)
360 fseek(fp, 0, SEEK_SET);
361 top = read_res16(fp);
363 else
365 top = read_res32(fp);
368 fclose(fp);
370 return top;