source: branches/gcc-kmk/tools/wrc/newstruc.c@ 21836

Last change on this file since 21836 was 21745, checked in by dmik, 14 years ago

Build Wine RC tool.

It is necesasry for .orc files which are Windows resource files.

File size: 33.6 KB
Line 
1/*
2 * Create dynamic new structures of various types
3 * and some utils in that trend.
4 *
5 * Copyright 1998 Bertho A. Stultiens
6 *
7 */
8
9#include "config.h"
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <assert.h>
15#include <ctype.h>
16
17#include "wrc.h"
18#include "newstruc.h"
19#include "utils.h"
20#include "parser.h"
21
22#include "wingdi.h" /* for BITMAPINFOHEADER */
23
24/* Generate new_* functions that have no parameters (NOTE: no ';') */
25__NEW_STRUCT_FUNC(dialog)
26__NEW_STRUCT_FUNC(dialogex)
27__NEW_STRUCT_FUNC(name_id)
28__NEW_STRUCT_FUNC(menu)
29__NEW_STRUCT_FUNC(menuex)
30__NEW_STRUCT_FUNC(menu_item)
31__NEW_STRUCT_FUNC(menuex_item)
32__NEW_STRUCT_FUNC(control)
33__NEW_STRUCT_FUNC(icon)
34__NEW_STRUCT_FUNC(cursor)
35__NEW_STRUCT_FUNC(versioninfo)
36__NEW_STRUCT_FUNC(ver_value)
37__NEW_STRUCT_FUNC(ver_block)
38__NEW_STRUCT_FUNC(stt_entry)
39__NEW_STRUCT_FUNC(accelerator)
40__NEW_STRUCT_FUNC(event)
41__NEW_STRUCT_FUNC(raw_data)
42__NEW_STRUCT_FUNC(lvc)
43__NEW_STRUCT_FUNC(res_count)
44__NEW_STRUCT_FUNC(string)
45__NEW_STRUCT_FUNC(toolbar_item)
46__NEW_STRUCT_FUNC(ani_any)
47
48/* New instances for all types of structures */
49/* Very inefficient (in size), but very functional :-]
50 * Especially for type-checking.
51 */
52resource_t *new_resource(enum res_e t, void *res, int memopt, language_t *lan)
53{
54 resource_t *r = (resource_t *)xmalloc(sizeof(resource_t));
55 r->type = t;
56 r->res.overlay = res;
57 r->memopt = memopt;
58 r->lan = lan;
59 return r;
60}
61
62version_t *new_version(DWORD v)
63{
64 version_t *vp = (version_t *)xmalloc(sizeof(version_t));
65 *vp = v;
66 return vp;
67}
68
69characts_t *new_characts(DWORD c)
70{
71 characts_t *cp = (characts_t *)xmalloc(sizeof(characts_t));
72 *cp = c;
73 return cp;
74}
75
76language_t *new_language(int id, int sub)
77{
78 language_t *lan = (language_t *)xmalloc(sizeof(language_t));
79 lan->id = id;
80 lan->sub = sub;
81 return lan;
82}
83
84language_t *dup_language(language_t *l)
85{
86 if(!l) return NULL;
87 return new_language(l->id, l->sub);
88}
89
90version_t *dup_version(version_t *v)
91{
92 if(!v) return NULL;
93 return new_version(*v);
94}
95
96characts_t *dup_characts(characts_t *c)
97{
98 if(!c) return NULL;
99 return new_characts(*c);
100}
101
102rcdata_t *new_rcdata(raw_data_t *rd, int *memopt)
103{
104 rcdata_t *rc = (rcdata_t *)xmalloc(sizeof(rcdata_t));
105 rc->data = rd;
106 if(memopt)
107 {
108 rc->memopt = *memopt;
109 free(memopt);
110 }
111 else
112 rc->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
113 return rc;
114}
115
116font_id_t *new_font_id(int size, string_t *face, int weight, int italic)
117{
118 font_id_t *fid = (font_id_t *)xmalloc(sizeof(font_id_t));
119 fid->name = face;
120 fid->size = size;
121 fid->weight = weight;
122 fid->italic = italic;
123 return fid;
124}
125
126user_t *new_user(name_id_t *type, raw_data_t *rd, int *memopt)
127{
128 user_t *usr = (user_t *)xmalloc(sizeof(user_t));
129 usr->data = rd;
130 if(memopt)
131 {
132 usr->memopt = *memopt;
133 free(memopt);
134 }
135 else
136 usr->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
137 usr->type = type;
138 return usr;
139}
140
141font_t *new_font(raw_data_t *rd, int *memopt)
142{
143 font_t *fnt = (font_t *)xmalloc(sizeof(font_t));
144 fnt->data = rd;
145 if(memopt)
146 {
147 fnt->memopt = *memopt;
148 free(memopt);
149 }
150 else
151 fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
152 return fnt;
153}
154
155fontdir_t *new_fontdir(raw_data_t *rd, int *memopt)
156{
157 fontdir_t *fnd = (fontdir_t *)xmalloc(sizeof(fontdir_t));
158 fnd->data = rd;
159 if(memopt)
160 {
161 fnd->memopt = *memopt;
162 free(memopt);
163 }
164 else
165 fnd->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
166 return fnd;
167}
168
169
170/*
171 * Convert bitmaps to proper endian
172 */
173static void convert_bitmap_swap_v3(BITMAPINFOHEADER *bih)
174{
175 bih->biSize = BYTESWAP_DWORD(bih->biSize);
176 bih->biWidth = BYTESWAP_DWORD(bih->biWidth);
177 bih->biHeight = BYTESWAP_DWORD(bih->biHeight);
178 bih->biPlanes = BYTESWAP_WORD(bih->biPlanes);
179 bih->biBitCount = BYTESWAP_WORD(bih->biBitCount);
180 bih->biCompression = BYTESWAP_DWORD(bih->biCompression);
181 bih->biSizeImage = BYTESWAP_DWORD(bih->biSizeImage);
182 bih->biXPelsPerMeter = BYTESWAP_DWORD(bih->biXPelsPerMeter);
183 bih->biYPelsPerMeter = BYTESWAP_DWORD(bih->biYPelsPerMeter);
184 bih->biClrUsed = BYTESWAP_DWORD(bih->biClrUsed);
185 bih->biClrImportant = BYTESWAP_DWORD(bih->biClrImportant);
186}
187
188static void convert_bitmap_swap_v4(BITMAPV4HEADER *b4h)
189{
190 convert_bitmap_swap_v3((BITMAPINFOHEADER *)b4h);
191 b4h->bV4RedMask = BYTESWAP_DWORD(b4h->bV4RedMask);
192 b4h->bV4GreenMask = BYTESWAP_DWORD(b4h->bV4GreenMask);
193 b4h->bV4BlueMask = BYTESWAP_DWORD(b4h->bV4BlueMask);
194 b4h->bV4AlphaMask = BYTESWAP_DWORD(b4h->bV4AlphaMask);
195 b4h->bV4CSType = BYTESWAP_DWORD(b4h->bV4CSType);
196 b4h->bV4Endpoints.ciexyzRed.ciexyzX = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzX);
197 b4h->bV4Endpoints.ciexyzRed.ciexyzY = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzY);
198 b4h->bV4Endpoints.ciexyzRed.ciexyzZ = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzZ);
199 b4h->bV4Endpoints.ciexyzGreen.ciexyzX = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzX);
200 b4h->bV4Endpoints.ciexyzGreen.ciexyzY = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzY);
201 b4h->bV4Endpoints.ciexyzGreen.ciexyzZ = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzZ);
202 b4h->bV4Endpoints.ciexyzBlue.ciexyzX = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzX);
203 b4h->bV4Endpoints.ciexyzBlue.ciexyzY = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzY);
204 b4h->bV4Endpoints.ciexyzBlue.ciexyzZ = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzZ);
205 b4h->bV4GammaRed = BYTESWAP_DWORD(b4h->bV4GammaRed);
206 b4h->bV4GammaGreen = BYTESWAP_DWORD(b4h->bV4GammaGreen);
207 b4h->bV4GammaBlue = BYTESWAP_DWORD(b4h->bV4GammaBlue);
208}
209
210#define FL_SIGBE 0x01
211#define FL_SIZEBE 0x02
212#define FL_V4 0x04
213static int convert_bitmap(char *data, int size)
214{
215 BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)data;
216 BITMAPV4HEADER *b4h = (BITMAPV4HEADER *)data;
217 int type = 0;
218#ifdef WORDS_BIGENDIAN
219 DWORD bisizel = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
220 DWORD b4sizel = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
221 DWORD bisizeb = sizeof(BITMAPINFOHEADER);
222 DWORD b4sizeb = sizeof(BITMAPV4HEADER);
223#else
224 DWORD bisizel = sizeof(BITMAPINFOHEADER);
225 DWORD b4sizel = sizeof(BITMAPV4HEADER);
226 DWORD bisizeb = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
227 DWORD b4sizeb = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
228#endif
229
230 if(data[0] == 'B' && data[1] == 'M')
231 {
232 /* Little endian signature */
233 bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER));
234 b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER));
235 }
236 else if(data[0] == 'M' && data[1] == 'B')
237 {
238 type |= FL_SIGBE; /* Big endian signature */
239 bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER));
240 b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER));
241 }
242
243 if(bih->biSize == bisizel)
244 {
245 /* Little endian */
246 }
247 else if(bih->biSize == b4sizel)
248 {
249 type |= FL_V4;
250 }
251 else if(bih->biSize == bisizeb)
252 {
253 type |= FL_SIZEBE;
254 }
255 else if(bih->biSize == b4sizeb)
256 {
257 type |= FL_SIZEBE | FL_V4;
258 }
259#if defined(__WIN32OS2__)
260 else if(bih->biSize == sizeof(BITMAPCOREHEADER))
261 {
262 /* Little endian */
263 }
264#endif
265 else
266 type = -1;
267
268 switch(type)
269 {
270 default:
271 break;
272 case FL_SIZEBE:
273 case FL_SIZEBE | FL_V4:
274 yywarning("Bitmap v%c signature little-endian, but size big-endian", type & FL_V4 ? '4' : '3');
275 break;
276 case FL_SIGBE:
277 case FL_SIGBE | FL_V4:
278 yywarning("Bitmap v%c signature big-endian, but size little-endian", type & FL_V4 ? '4' : '3');
279 break;
280 case -1:
281 yyerror("Invalid bitmap format");
282 break;
283 }
284
285 switch(byteorder)
286 {
287#ifdef WORDS_BIGENDIAN
288 default:
289#endif
290 case WRC_BO_BIG:
291 if(!(type & FL_SIZEBE))
292 {
293 if(type & FL_V4)
294 convert_bitmap_swap_v4(b4h);
295 else
296 convert_bitmap_swap_v3(bih);
297 }
298 break;
299#ifndef WORDS_BIGENDIAN
300 default:
301#endif
302 case WRC_BO_LITTLE:
303 if(type & FL_SIZEBE)
304 {
305 if(type & FL_V4)
306 convert_bitmap_swap_v4(b4h);
307 else
308 convert_bitmap_swap_v3(bih);
309 }
310 break;
311 }
312
313 if(size && (void *)data != (void *)bih)
314 {
315 /* We have the fileheader still attached, remove it */
316 memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER));
317 return sizeof(BITMAPFILEHEADER);
318 }
319 return 0;
320}
321#undef FL_SIGBE
322#undef FL_SIZEBE
323#undef FL_V4
324
325/*
326 * Cursor and icon splitter functions used when allocating
327 * cursor- and icon-groups.
328 */
329typedef struct {
330 language_t lan;
331 int id;
332} id_alloc_t;
333
334static int get_new_id(id_alloc_t **list, int *n, language_t *lan)
335{
336 int i;
337 assert(lan != NULL);
338 assert(list != NULL);
339 assert(n != NULL);
340
341 if(!*list)
342 {
343 *list = (id_alloc_t *)xmalloc(sizeof(id_alloc_t));
344 *n = 1;
345 (*list)[0].lan = *lan;
346 (*list)[0].id = 1;
347 return 1;
348 }
349
350 for(i = 0; i < *n; i++)
351 {
352 if((*list)[i].lan.id == lan->id && (*list)[i].lan.sub == lan->sub)
353 return ++((*list)[i].id);
354 }
355
356 *list = (id_alloc_t *)xrealloc(*list, sizeof(id_alloc_t) * (*n+1));
357 (*list)[*n].lan = *lan;
358 (*list)[*n].id = 1;
359 *n += 1;
360 return 1;
361}
362
363static int alloc_icon_id(language_t *lan)
364{
365 static id_alloc_t *idlist = NULL;
366 static int nid = 0;
367
368 return get_new_id(&idlist, &nid, lan);
369}
370
371static int alloc_cursor_id(language_t *lan)
372{
373 static id_alloc_t *idlist = NULL;
374 static int nid = 0;
375
376 return get_new_id(&idlist, &nid, lan);
377}
378
379static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico)
380{
381 int cnt;
382 int i;
383 icon_t *ico;
384 icon_t *list = NULL;
385 icon_header_t *ih = (icon_header_t *)rd->data;
386 int swap = 0;
387
388 if(ih->type == 1)
389 swap = 0;
390 else if(BYTESWAP_WORD(ih->type) == 1)
391 swap = 1;
392 else
393 yyerror("Icon resource data has invalid type id %d", ih->type);
394
395 cnt = swap ? BYTESWAP_WORD(ih->count) : ih->count;
396 for(i = 0; i < cnt; i++)
397 {
398 icon_dir_entry_t ide;
399 BITMAPINFOHEADER info;
400 memcpy(&ide, rd->data + sizeof(icon_header_t)
401 + i*sizeof(icon_dir_entry_t), sizeof(ide));
402
403 ico = new_icon();
404 ico->id = alloc_icon_id(icog->lvc.language);
405 ico->lvc = icog->lvc;
406 if(swap)
407 {
408 ide.offset = BYTESWAP_DWORD(ide.offset);
409 ide.ressize= BYTESWAP_DWORD(ide.ressize);
410 }
411 if(ide.offset > rd->size
412 || ide.offset + ide.ressize > rd->size)
413 yyerror("Icon resource data corrupt");
414 ico->width = ide.width;
415 ico->height = ide.height;
416 ico->nclr = ide.nclr;
417 ico->planes = swap ? BYTESWAP_WORD(ide.planes) : ide.planes;
418 ico->bits = swap ? BYTESWAP_WORD(ide.bits) : ide.bits;
419 convert_bitmap((char *)rd->data + ide.offset, 0);
420 memcpy(&info, rd->data + ide.offset, sizeof(info));
421 if(!ico->planes)
422 {
423 /* Argh! They did not fill out the resdir structure */
424 /* The bitmap is in destination byteorder. We want native for our structures */
425 switch(byteorder)
426 {
427#ifdef WORDS_BIGENDIAN
428 case WRC_BO_LITTLE:
429#else
430 case WRC_BO_BIG:
431#endif
432 ico->planes = BYTESWAP_WORD(info.biPlanes);
433 break;
434 default:
435 ico->planes = info.biPlanes;
436 }
437 }
438 if(!ico->bits)
439 {
440 /* Argh! They did not fill out the resdir structure */
441 /* The bitmap is in destination byteorder. We want native for our structures */
442 switch(byteorder)
443 {
444#ifdef WORDS_BIGENDIAN
445 case WRC_BO_LITTLE:
446#else
447 case WRC_BO_BIG:
448#endif
449 ico->bits = BYTESWAP_WORD(info.biBitCount);
450 break;
451 default:
452 ico->bits = info.biBitCount;
453 }
454 }
455 ico->data = new_raw_data();
456 copy_raw_data(ico->data, rd, ide.offset, ide.ressize);
457 if(!list)
458 {
459 list = ico;
460 }
461 else
462 {
463 ico->next = list;
464 list->prev = ico;
465 list = ico;
466 }
467 }
468 icog->iconlist = list;
469 *nico = cnt;
470}
471
472static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur)
473{
474 int cnt;
475 int i;
476 cursor_t *cur;
477 cursor_t *list = NULL;
478 cursor_header_t *ch = (cursor_header_t *)rd->data;
479 int swap = 0;
480
481 if(ch->type == 2)
482 swap = 0;
483 else if(BYTESWAP_WORD(ch->type) == 2)
484 swap = 1;
485 else
486 yyerror("Cursor resource data has invalid type id %d", ch->type);
487 cnt = swap ? BYTESWAP_WORD(ch->count) : ch->count;
488 for(i = 0; i < cnt; i++)
489 {
490 cursor_dir_entry_t cde;
491 BITMAPINFOHEADER info;
492 memcpy(&cde, rd->data + sizeof(cursor_header_t)
493 + i*sizeof(cursor_dir_entry_t), sizeof(cde));
494
495 cur = new_cursor();
496 cur->id = alloc_cursor_id(curg->lvc.language);
497 cur->lvc = curg->lvc;
498 if(swap)
499 {
500 cde.offset = BYTESWAP_DWORD(cde.offset);
501 cde.ressize= BYTESWAP_DWORD(cde.ressize);
502 }
503 if(cde.offset > rd->size
504 || cde.offset + cde.ressize > rd->size)
505 yyerror("Cursor resource data corrupt");
506 cur->width = cde.width;
507 cur->height = cde.height;
508 cur->nclr = cde.nclr;
509 convert_bitmap((char *)rd->data + cde.offset, 0);
510 memcpy(&info, rd->data + cde.offset, sizeof(info));
511 /* The bitmap is in destination byteorder. We want native for our structures */
512 switch(byteorder)
513 {
514#ifdef WORDS_BIGENDIAN
515 case WRC_BO_LITTLE:
516#else
517 case WRC_BO_BIG:
518#endif
519 cur->planes = BYTESWAP_WORD(info.biPlanes);
520 cur->bits = BYTESWAP_WORD(info.biBitCount);
521 break;
522 default:
523 cur->planes = info.biPlanes;
524 cur->bits = info.biBitCount;
525 }
526 if(!win32 && (cur->planes != 1 || cur->bits != 1))
527 yywarning("Win16 cursor contains colors");
528 cur->xhot = swap ? BYTESWAP_WORD(cde.xhot) : cde.xhot;
529 cur->yhot = swap ? BYTESWAP_WORD(cde.yhot) : cde.yhot;
530 cur->data = new_raw_data();
531 copy_raw_data(cur->data, rd, cde.offset, cde.ressize);
532 if(!list)
533 {
534 list = cur;
535 }
536 else
537 {
538 cur->next = list;
539 list->prev = cur;
540 list = cur;
541 }
542 }
543 curg->cursorlist = list;
544 *ncur = cnt;
545}
546
547
548icon_group_t *new_icon_group(raw_data_t *rd, int *memopt)
549{
550 icon_group_t *icog = (icon_group_t *)xmalloc(sizeof(icon_group_t));
551 if(memopt)
552 {
553 icog->memopt = *memopt;
554 free(memopt);
555 }
556 else
557 icog->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
558 icog->lvc = rd->lvc;
559 split_icons(rd, icog, &(icog->nicon));
560 free(rd->data);
561 free(rd);
562 return icog;
563}
564
565cursor_group_t *new_cursor_group(raw_data_t *rd, int *memopt)
566{
567 cursor_group_t *curg = (cursor_group_t *)xmalloc(sizeof(cursor_group_t));
568 if(memopt)
569 {
570 curg->memopt = *memopt;
571 free(memopt);
572 }
573 else
574 curg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
575 curg->lvc = rd->lvc;
576 split_cursors(rd, curg, &(curg->ncursor));
577 free(rd->data);
578 free(rd);
579 return curg;
580}
581
582/*
583 * Animated cursors and icons
584 *
585 * The format of animated cursors and icons is yet another example
586 * of bad design by "The Company". The entire RIFF structure is
587 * flawed by design because it is inconsistent and single minded:
588 * - some tags have lengths attached, others don't. The use of these
589 * non-length tags is absolutely unclear;
590 * - the content of "icon" tags can be both icons and cursors;
591 * - tags lack proper alignment constraints. It seems that everything
592 * is 16bit aligned, but I could not find that in any docu. Just be
593 * prepared to eat anything;
594 * - there are no strict constraints on tag-nesting and the organization
595 * is highly illogical;
596 *
597 * Anyhow, here is the basic structure:
598 * "RIFF" { dword taglength }
599 * "ACON" // What does it do?
600 * "LIST" { dword taglength }
601 * "INFO" // And what does this do?
602 * "INAM" { dword taglength } // Icon/cursor name
603 * {inam data}
604 * "IART" { dword taglength } // The artist
605 * {iart data}
606 * "fram" // Is followed by "icon"s
607 * "icon" { dword taglength } // First frame
608 * { icon/cursor data }
609 * "icon" { dword taglength } // Second frame
610 * { icon/cursor data }
611 * ... // ...
612 * "anih" { dword taglength } // Header structure
613 * { aniheader_t structure }
614 * "rate" { dword taglength } // The rate for each frame
615 * { `steps' dwords }
616 * "seq " { dword taglength } // The frame blit-order
617 * { `steps' dwords }
618 *
619 * Tag length are bytelength without the header and length field (i.e. -8).
620 * The "LIST" tag may occur several times and may encapsulate different
621 * tags. The `steps' is the number of "icon" tags found (actually the
622 * number of steps specified in the aniheader_t structure). The "seq "uence
623 * tag can be ommitted, in which case the sequence is equal to the sequence
624 * of "icon"s found in the file. Also "rate" may be ommitted, in which case
625 * the default from the aniheader_t structure is used.
626 *
627 * An animated cursor puts `.cur' formatted files into each "icon" tag,
628 * whereas animated icons contain `.ico' formatted files.
629 *
630 * Note about the code: Yes, it can be shorter/compressed. Some tags can be
631 * dealt with in the same code. However, this version shows what is going on
632 * and is better debug-able.
633 */
634static const char riff[4] = "RIFF";
635static const char acon[4] = "ACON";
636static const char list[4] = "LIST";
637static const char info[4] = "INFO";
638static const char inam[4] = "INAM";
639static const char iart[4] = "IART";
640static const char fram[4] = "fram";
641static const char icon[4] = "icon";
642static const char anih[4] = "anih";
643static const char rate[4] = "rate";
644static const char seq[4] = "seq ";
645
646#define NEXT_TAG(p) ((riff_tag_t *)(((char *)p) + (isswapped ? BYTESWAP_DWORD(p->size) : p->size) + sizeof(*p)))
647
648static void handle_ani_icon(riff_tag_t *rtp, enum res_e type, int isswapped)
649{
650 cursor_dir_entry_t *cdp;
651 cursor_header_t *chp;
652 int count;
653 int ctype;
654 int i;
655 static int once = 0; /* This will trigger only once per file! */
656 const char *anistr = type == res_aniico ? "icon" : "cursor";
657 /* Notes:
658 * Both cursor and icon directories are similar
659 * Both cursor and icon headers are similar
660 */
661
662 chp = (cursor_header_t *)(rtp+1);
663 cdp = (cursor_dir_entry_t *)(chp+1);
664 count = isswapped ? BYTESWAP_WORD(chp->count) : chp->count;
665 ctype = isswapped ? BYTESWAP_WORD(chp->type) : chp->type;
666 chp->reserved = BYTESWAP_WORD(chp->reserved);
667 chp->type = BYTESWAP_WORD(chp->type);
668 chp->count = BYTESWAP_WORD(chp->count);
669
670 if(type == res_anicur && ctype != 2 && !once)
671 {
672 yywarning("Animated cursor contains invalid \"icon\" tag cursor-file (%d->%s)",
673 ctype,
674 ctype == 1 ? "icontype" : "?");
675 once++;
676 }
677 else if(type == res_aniico && ctype != 1 && !once)
678 {
679 yywarning("Animated icon contains invalid \"icon\" tag icon-file (%d->%s)",
680 ctype,
681 ctype == 2 ? "cursortype" : "?");
682 once++;
683 }
684 else if(ctype != 1 && ctype != 2 && !once)
685 {
686 yywarning("Animated %s contains invalid \"icon\" tag file-type (%d; neither icon nor cursor)", anistr, ctype);
687 once++;
688 }
689
690 for(i = 0; i < count; i++)
691 {
692 DWORD ofs = isswapped ? BYTESWAP_DWORD(cdp[i].offset) : cdp[i].offset;
693 DWORD sze = isswapped ? BYTESWAP_DWORD(cdp[i].ressize) : cdp[i].ressize;
694 if(ofs > rtp->size || ofs+sze > rtp->size)
695 yyerror("Animated %s's data corrupt", anistr);
696 convert_bitmap((char *)chp + ofs, 0);
697 cdp[i].xhot = BYTESWAP_WORD(cdp->xhot);
698 cdp[i].yhot = BYTESWAP_WORD(cdp->yhot);
699 cdp[i].ressize = BYTESWAP_DWORD(cdp->ressize);
700 cdp[i].offset = BYTESWAP_DWORD(cdp->offset);
701 }
702}
703
704static void handle_ani_list(riff_tag_t *lst, enum res_e type, int isswapped)
705{
706 riff_tag_t *rtp = lst+1; /* Skip the "LIST" tag */
707
708 while((char *)rtp < (char *)lst + lst->size + sizeof(*lst))
709 {
710 if(!memcmp(rtp->tag, info, sizeof(info)))
711 {
712 rtp = (riff_tag_t *)(((char *)rtp) + 4);
713 }
714 else if(!memcmp(rtp->tag, inam, sizeof(inam)))
715 {
716 /* Ignore the icon/cursor name; its a string */
717 rtp = NEXT_TAG(rtp);
718 }
719 else if(!memcmp(rtp->tag, iart, sizeof(iart)))
720 {
721 /* Ignore the author's name; its a string */
722 rtp = NEXT_TAG(rtp);
723 }
724 else if(!memcmp(rtp->tag, fram, sizeof(fram)))
725 {
726 /* This should be followed by "icon"s, but we
727 * simply ignore this because it is pure
728 * non-information.
729 */
730 rtp = (riff_tag_t *)(((char *)rtp) + 4);
731 }
732 else if(!memcmp(rtp->tag, icon, sizeof(icon)))
733 {
734 handle_ani_icon(rtp, type, isswapped);
735 rtp = NEXT_TAG(rtp);
736 }
737 else
738 internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file",
739 isprint(rtp->tag[0]) ? rtp->tag[0] : '.',
740 isprint(rtp->tag[1]) ? rtp->tag[1] : '.',
741 isprint(rtp->tag[2]) ? rtp->tag[2] : '.',
742 isprint(rtp->tag[3]) ? rtp->tag[3] : '.');
743
744 /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */
745 if((DWORD)rtp & 1)
746 rtp = (riff_tag_t*)((char*)rtp + 1);
747 }
748}
749
750ani_curico_t *new_ani_curico(enum res_e type, raw_data_t *rd, int *memopt)
751{
752 ani_curico_t *ani = (ani_curico_t *)xmalloc(sizeof(ani_curico_t));
753 riff_tag_t *rtp;
754 int isswapped = 0;
755 int doswap;
756 const char *anistr = type == res_aniico ? "icon" : "cursor";
757
758 assert(!memcmp(rd->data, riff, sizeof(riff)));
759 assert(type == res_anicur || type == res_aniico);
760
761 rtp = (riff_tag_t *)rd->data;
762
763 if(BYTESWAP_DWORD(rtp->size) + 2*sizeof(DWORD) == rd->size)
764 isswapped = 1;
765 else if(rtp->size + 2*sizeof(DWORD) == rd->size)
766 isswapped = 0;
767 else
768 yyerror("Animated %s has an invalid RIFF length", anistr);
769
770 switch(byteorder)
771 {
772#ifdef WORDS_BIGENDIAN
773 case WRC_BO_LITTLE:
774#else
775 case WRC_BO_BIG:
776#endif
777 doswap = !isswapped;
778 break;
779 default:
780 doswap = isswapped;
781 }
782
783 /*
784 * When to swap what:
785 * isswapped | doswap |
786 * ----------+--------+---------------------------------
787 * 0 | 0 | read native; don't convert
788 * 1 | 0 | read swapped size; don't convert
789 * 0 | 1 | read native; convert
790 * 1 | 1 | read swapped size; convert
791 * Reading swapped size if necessary to calculate in native
792 * format. E.g. a little-endian source on a big-endian
793 * processor.
794 */
795 if(doswap)
796 {
797 /* We only go through the RIFF file if we need to swap
798 * bytes in words/dwords. Else we couldn't care less
799 * what the file contains. This is consistent with
800 * MS' rc.exe, which doesn't complain at all, eventhough
801 * the fileformat might not be entirely correct.
802 */
803 rtp++; /* Skip the "RIFF" tag */
804
805 while((char *)rtp < (char *)rd->data + rd->size)
806 {
807 if(!memcmp(rtp->tag, acon, sizeof(acon)))
808 {
809 rtp = (riff_tag_t *)(((char *)rtp) + 4);
810 }
811 else if(!memcmp(rtp->tag, list, sizeof(list)))
812 {
813 handle_ani_list(rtp, type, isswapped);
814 rtp = NEXT_TAG(rtp);
815 }
816 else if(!memcmp(rtp->tag, anih, sizeof(anih)))
817 {
818 aniheader_t *ahp = (aniheader_t *)((char *)(rtp+1));
819 ahp->structsize = BYTESWAP_DWORD(ahp->structsize);
820 ahp->frames = BYTESWAP_DWORD(ahp->frames);
821 ahp->steps = BYTESWAP_DWORD(ahp->steps);
822 ahp->cx = BYTESWAP_DWORD(ahp->cx);
823 ahp->cy = BYTESWAP_DWORD(ahp->cy);
824 ahp->bitcount = BYTESWAP_DWORD(ahp->bitcount);
825 ahp->planes = BYTESWAP_DWORD(ahp->planes);
826 ahp->rate = BYTESWAP_DWORD(ahp->rate);
827 ahp->flags = BYTESWAP_DWORD(ahp->flags);
828 rtp = NEXT_TAG(rtp);
829 }
830 else if(!memcmp(rtp->tag, rate, sizeof(rate)))
831 {
832 int cnt = rtp->size / sizeof(DWORD);
833 DWORD *dwp = (DWORD *)(rtp+1);
834 int i;
835 for(i = 0; i < cnt; i++)
836 dwp[i] = BYTESWAP_DWORD(dwp[i]);
837 rtp = NEXT_TAG(rtp);
838 }
839 else if(!memcmp(rtp->tag, seq, sizeof(seq)))
840 {
841 int cnt = rtp->size / sizeof(DWORD);
842 DWORD *dwp = (DWORD *)(rtp+1);
843 int i;
844 for(i = 0; i < cnt; i++)
845 dwp[i] = BYTESWAP_DWORD(dwp[i]);
846 rtp = NEXT_TAG(rtp);
847 }
848 else
849 internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file",
850 isprint(rtp->tag[0]) ? rtp->tag[0] : '.',
851 isprint(rtp->tag[1]) ? rtp->tag[1] : '.',
852 isprint(rtp->tag[2]) ? rtp->tag[2] : '.',
853 isprint(rtp->tag[3]) ? rtp->tag[3] : '.');
854
855 /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */
856 if((DWORD)rtp & 1)
857 rtp = (riff_tag_t*)((char*)rtp + 1);
858 }
859
860 /* We must end correctly here */
861 if((char *)rtp != (char *)rd->data + rd->size)
862 yyerror("Animated %s contains invalid field size(s)", anistr);
863 }
864
865 ani->data = rd;
866 if(memopt)
867 {
868 ani->memopt = *memopt;
869 free(memopt);
870 }
871 else
872 ani->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
873 return ani;
874}
875#undef NEXT_TAG
876
877/* Bitmaps */
878bitmap_t *new_bitmap(raw_data_t *rd, int *memopt)
879{
880 bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t));
881
882 bmp->data = rd;
883 if(memopt)
884 {
885 bmp->memopt = *memopt;
886 free(memopt);
887 }
888 else
889 bmp->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
890 rd->size -= convert_bitmap(rd->data, rd->size);
891 return bmp;
892}
893
894ver_words_t *new_ver_words(int i)
895{
896 ver_words_t *w = (ver_words_t *)xmalloc(sizeof(ver_words_t));
897 w->words = (WORD *)xmalloc(sizeof(WORD));
898 w->words[0] = (WORD)i;
899 w->nwords = 1;
900 return w;
901}
902
903ver_words_t *add_ver_words(ver_words_t *w, int i)
904{
905 w->words = (WORD *)xrealloc(w->words, (w->nwords+1) * sizeof(WORD));
906 w->words[w->nwords] = (WORD)i;
907 w->nwords++;
908 return w;
909}
910
911#define MSGTAB_BAD_PTR(p, b, l, r) (((l) - ((char *)(p) - (char *)(b))) > (r))
912messagetable_t *new_messagetable(raw_data_t *rd, int *memopt)
913{
914 messagetable_t *msg = (messagetable_t *)xmalloc(sizeof(messagetable_t));
915 msgtab_block_t *mbp;
916 DWORD nblk;
917 DWORD i;
918 WORD lo;
919 WORD hi;
920
921 msg->data = rd;
922 if(memopt)
923 {
924 msg->memopt = *memopt;
925 free(memopt);
926 }
927 else
928 msg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
929
930 if(rd->size < sizeof(DWORD))
931 yyerror("Invalid messagetable, size too small");
932
933 nblk = *(DWORD *)rd->data;
934 lo = WRC_LOWORD(nblk);
935 hi = WRC_HIWORD(nblk);
936
937 /* FIXME:
938 * This test will fail for all n*2^16 blocks in the messagetable.
939 * However, no sane person would want to have so many blocks
940 * and have a table of megabytes attached.
941 * So, I will assume that we have less than 2^16 blocks in the table
942 * and all will just work out fine. Otherwise, we would need to test
943 * the ID, offset and length (and flag) fields to be very sure.
944 */
945 if(hi && lo)
946 internal_error(__FILE__, __LINE__, "Messagetable contains more than 65535 blocks; cannot determine endian");
947 if(!hi && !lo)
948 yyerror("Invalid messagetable block count 0");
949
950 if(!hi && lo) /* Messagetable byteorder == native byteorder */
951 {
952#ifdef WORDS_BIGENDIAN
953 if(byteorder != WRC_BO_LITTLE) goto out;
954#else
955 if(byteorder != WRC_BO_BIG) goto out;
956#endif
957 /* Resource byteorder != native byteorder */
958
959 mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]);
960 if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp)))
961 yyerror("Messagetable's blocks are outside of defined data");
962 for(i = 0; i < nblk; i++)
963 {
964 msgtab_entry_t *mep, *next_mep;
965 DWORD id;
966
967 mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset);
968
969 for(id = mbp[i].idlo; id <= mbp[i].idhi; id++)
970 {
971 if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length))
972 yyerror("Messagetable's data for block %d, ID 0x%08lx is outside of defined data", (int)i, id);
973 if(mep->flags == 1) /* Docu says 'flags == 0x0001' for unicode */
974 {
975 WORD *wp = (WORD *)&mep[1];
976 int l = mep->length/2 - 2; /* Length included header */
977 int n;
978
979 if(mep->length & 1)
980 yyerror("Message 0x%08lx is unicode (block %d), but has odd length (%d)", id, (int)i, mep->length);
981 for(n = 0; n < l; n++)
982 wp[n] = BYTESWAP_WORD(wp[n]);
983
984 }
985 next_mep = (msgtab_entry_t *)(((char *)mep) + mep->length);
986 mep->length = BYTESWAP_WORD(mep->length);
987 mep->flags = BYTESWAP_WORD(mep->flags);
988 mep = next_mep;
989 }
990
991 mbp[i].idlo = BYTESWAP_DWORD(mbp[i].idlo);
992 mbp[i].idhi = BYTESWAP_DWORD(mbp[i].idhi);
993 mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset);
994 }
995 }
996 if(hi && !lo) /* Messagetable byteorder != native byteorder */
997 {
998#ifdef WORDS_BIGENDIAN
999 if(byteorder == WRC_BO_LITTLE) goto out;
1000#else
1001 if(byteorder == WRC_BO_BIG) goto out;
1002#endif
1003 /* Resource byteorder == native byteorder */
1004
1005 mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]);
1006 nblk = BYTESWAP_DWORD(nblk);
1007 if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp)))
1008 yyerror("Messagetable's blocks are outside of defined data");
1009 for(i = 0; i < nblk; i++)
1010 {
1011 msgtab_entry_t *mep;
1012 DWORD id;
1013
1014 mbp[i].idlo = BYTESWAP_DWORD(mbp[i].idlo);
1015 mbp[i].idhi = BYTESWAP_DWORD(mbp[i].idhi);
1016 mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset);
1017 mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset);
1018
1019 for(id = mbp[i].idlo; id <= mbp[i].idhi; id++)
1020 {
1021 mep->length = BYTESWAP_WORD(mep->length);
1022 mep->flags = BYTESWAP_WORD(mep->flags);
1023
1024 if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length))
1025 yyerror("Messagetable's data for block %d, ID 0x%08lx is outside of defined data", (int)i, id);
1026 if(mep->flags == 1) /* Docu says 'flags == 0x0001' for unicode */
1027 {
1028 WORD *wp = (WORD *)&mep[1];
1029 int l = mep->length/2 - 2; /* Length included header */
1030 int n;
1031
1032 if(mep->length & 1)
1033 yyerror("Message 0x%08lx is unicode (block %d), but has odd length (%d)", id, (int)i, mep->length);
1034 for(n = 0; n < l; n++)
1035 wp[n] = BYTESWAP_WORD(wp[n]);
1036
1037 }
1038 mep = (msgtab_entry_t *)(((char *)mep) + mep->length);
1039 }
1040 }
1041 }
1042
1043 out:
1044 return msg;
1045}
1046#undef MSGTAB_BAD_PTR
1047
1048void copy_raw_data(raw_data_t *dst, raw_data_t *src, unsigned int offs, int len)
1049{
1050 assert(offs <= src->size);
1051 assert(offs + len <= src->size);
1052 if(!dst->data)
1053 {
1054 dst->data = (char *)xmalloc(len);
1055 dst->size = 0;
1056 }
1057 else
1058 dst->data = (char *)xrealloc(dst->data, dst->size + len);
1059 /* dst->size holds the offset to copy to */
1060 memcpy(dst->data + dst->size, src->data + offs, len);
1061 dst->size += len;
1062}
1063
1064int *new_int(int i)
1065{
1066 int *ip = (int *)xmalloc(sizeof(int));
1067 *ip = i;
1068 return ip;
1069}
1070
1071stringtable_t *new_stringtable(lvc_t *lvc)
1072{
1073 stringtable_t *stt = (stringtable_t *)xmalloc(sizeof(stringtable_t));
1074
1075 if(lvc)
1076 stt->lvc = *lvc;
1077
1078 return stt;
1079}
1080
1081toolbar_t *new_toolbar(int button_width, int button_height, toolbar_item_t *items, int nitems)
1082{
1083 toolbar_t *tb = (toolbar_t *)xmalloc(sizeof(toolbar_t));
1084 tb->button_width = button_width;
1085 tb->button_height = button_height;
1086 tb->nitems = nitems;
1087 tb->items = items;
1088 return tb;
1089}
1090
1091dlginit_t *new_dlginit(raw_data_t *rd, int *memopt)
1092{
1093 dlginit_t *di = (dlginit_t *)xmalloc(sizeof(dlginit_t));
1094 di->data = rd;
1095 if(memopt)
1096 {
1097 di->memopt = *memopt;
1098 free(memopt);
1099 }
1100 else
1101 di->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1102
1103 return di;
1104}
1105
1106style_pair_t *new_style_pair(style_t *style, style_t *exstyle)
1107{
1108 style_pair_t *sp = (style_pair_t *)xmalloc(sizeof(style_pair_t));
1109 sp->style = style;
1110 sp->exstyle = exstyle;
1111 return sp;
1112}
1113
1114style_t *new_style(DWORD or_mask, DWORD and_mask)
1115{
1116 style_t *st = (style_t *)xmalloc(sizeof(style_t));
1117 st->or_mask = or_mask;
1118 st->and_mask = and_mask;
1119 return st;
1120}
1121
Note: See TracBrowser for help on using the repository browser.