- Bugfix: Corrected a SEGV in the rawdata handling. Mistakingly took the
address of a pointer instead of its value. This probably slipped in
during the merge of my tree into the winetree.
Lesson learned: always double check.
- Verified most resources so that win16 compile also generates correct
output for reversed endian.
- Implemented byte-ordering for resources. All resources can be forced
to be little-, big- or native endian with command-line option -B.
- Reading resources from .res-files are only accepted in native byte-
ordering so that no additional semantic analysis is required.
- Resource directory is still written in native-only format, including
the strings.
- Wrc is now installed through the makefile with 'make install' and also
uninstalled with 'make uninstall'.
- Wrote a man-page for better reference. The manpage also gets installed
and uninstalled.
- Cleaned up the namespace a bit by more agressive use of static.
diff --git a/tools/wrc/newstruc.c b/tools/wrc/newstruc.c
index 0e4d1f9..1120a67 100644
--- a/tools/wrc/newstruc.c
+++ b/tools/wrc/newstruc.c
@@ -18,6 +18,8 @@
#include "utils.h"
#include "parser.h"
+#include "wingdi.h" /* for BITMAPINFOHEADER */
+
/* Generate new_* functions that have no parameters (NOTE: no ';') */
__NEW_STRUCT_FUNC(dialog)
__NEW_STRUCT_FUNC(dialogex)
@@ -148,6 +150,382 @@
return fnt;
}
+
+/*
+ * Convert bitmaps to proper endian
+ */
+static void convert_bitmap_swap_v3(BITMAPINFOHEADER *bih)
+{
+ bih->biSize = BYTESWAP_DWORD(bih->biSize);
+ bih->biWidth = BYTESWAP_DWORD(bih->biWidth);
+ bih->biHeight = BYTESWAP_DWORD(bih->biHeight);
+ bih->biPlanes = BYTESWAP_WORD(bih->biPlanes);
+ bih->biBitCount = BYTESWAP_WORD(bih->biBitCount);
+ bih->biCompression = BYTESWAP_DWORD(bih->biCompression);
+ bih->biSizeImage = BYTESWAP_DWORD(bih->biSizeImage);
+ bih->biXPelsPerMeter = BYTESWAP_DWORD(bih->biXPelsPerMeter);
+ bih->biYPelsPerMeter = BYTESWAP_DWORD(bih->biYPelsPerMeter);
+ bih->biClrUsed = BYTESWAP_DWORD(bih->biClrUsed);
+ bih->biClrImportant = BYTESWAP_DWORD(bih->biClrImportant);
+}
+
+static void convert_bitmap_swap_v4(BITMAPV4HEADER *b4h)
+{
+ convert_bitmap_swap_v3((BITMAPINFOHEADER *)b4h);
+ b4h->bV4RedMask = BYTESWAP_DWORD(b4h->bV4RedMask);
+ b4h->bV4GreenMask = BYTESWAP_DWORD(b4h->bV4GreenMask);
+ b4h->bV4BlueMask = BYTESWAP_DWORD(b4h->bV4BlueMask);
+ b4h->bV4AlphaMask = BYTESWAP_DWORD(b4h->bV4AlphaMask);
+ b4h->bV4CSType = BYTESWAP_DWORD(b4h->bV4CSType);
+ b4h->bV4EndPoints.ciexyzRed.ciexyzX = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzRed.ciexyzX);
+ b4h->bV4EndPoints.ciexyzRed.ciexyzY = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzRed.ciexyzY);
+ b4h->bV4EndPoints.ciexyzRed.ciexyzZ = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzRed.ciexyzZ);
+ b4h->bV4EndPoints.ciexyzGreen.ciexyzX = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzGreen.ciexyzX);
+ b4h->bV4EndPoints.ciexyzGreen.ciexyzY = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzGreen.ciexyzY);
+ b4h->bV4EndPoints.ciexyzGreen.ciexyzZ = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzGreen.ciexyzZ);
+ b4h->bV4EndPoints.ciexyzBlue.ciexyzX = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzBlue.ciexyzX);
+ b4h->bV4EndPoints.ciexyzBlue.ciexyzY = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzBlue.ciexyzY);
+ b4h->bV4EndPoints.ciexyzBlue.ciexyzZ = BYTESWAP_DWORD(b4h->bV4EndPoints.ciexyzBlue.ciexyzZ);
+ b4h->bV4GammaRed = BYTESWAP_DWORD(b4h->bV4GammaRed);
+ b4h->bV4GammaGreen = BYTESWAP_DWORD(b4h->bV4GammaGreen);
+ b4h->bV4GammaBlue = BYTESWAP_DWORD(b4h->bV4GammaBlue);
+}
+
+#define FL_SIGBE 0x01
+#define FL_SIZEBE 0x02
+#define FL_V4 0x04
+static int convert_bitmap(char *data, int size)
+{
+ BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)data;
+ BITMAPV4HEADER *b4h = (BITMAPV4HEADER *)data;
+ int type = 0;
+#if BYTE_ORDER == BIG_ENDIAN
+ DWORD bisizel = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
+ DWORD b4sizel = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
+ DWORD bisizeb = sizeof(BITMAPINFOHEADER);
+ DWORD b4sizeb = sizeof(BITMAPV4HEADER);
+#else
+ DWORD bisizel = sizeof(BITMAPINFOHEADER);
+ DWORD b4sizel = sizeof(BITMAPV4HEADER);
+ DWORD bisizeb = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
+ DWORD b4sizeb = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
+#endif
+
+ if(data[0] == 'B' && data[1] == 'M')
+ {
+ /* Little endian signature */
+ bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER));
+ b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER));
+ }
+ else if(data[0] == 'M' && data[1] == 'B')
+ {
+ type |= FL_SIGBE; /* Big endian signature */
+ bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER));
+ b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER));
+ }
+
+ if(bih->biSize == bisizel)
+ {
+ /* Little endian */
+ }
+ else if(bih->biSize == b4sizel)
+ {
+ type |= FL_V4;
+ }
+ else if(bih->biSize == bisizeb)
+ {
+ type |= FL_SIZEBE;
+ }
+ else if(bih->biSize == b4sizeb)
+ {
+ type |= FL_SIZEBE | FL_V4;
+ }
+ else
+ type = -1;
+
+ switch(type)
+ {
+ default:
+ break;
+ case FL_SIZEBE:
+ case FL_SIZEBE | FL_V4:
+ yywarning("Bitmap v%c signature little-endian, but size big-endian", type & FL_V4 ? '4' : '3');
+ break;
+ case FL_SIGBE:
+ case FL_SIGBE | FL_V4:
+ yywarning("Bitmap v%c signature big-endian, but size little-endian", type & FL_V4 ? '4' : '3');
+ break;
+ case -1:
+ yyerror("Invalid bitmap format");
+ break;
+ }
+
+ switch(byteorder)
+ {
+#if BYTE_ORDER == BIG_ENDIAN
+ default:
+#endif
+ case WRC_BO_BIG:
+ if(!(type & FL_SIZEBE))
+ {
+ if(type & FL_V4)
+ convert_bitmap_swap_v4(b4h);
+ else
+ convert_bitmap_swap_v3(bih);
+ }
+ break;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ default:
+#endif
+ case WRC_BO_LITTLE:
+ if(type & FL_SIZEBE)
+ {
+ if(type & FL_V4)
+ convert_bitmap_swap_v4(b4h);
+ else
+ convert_bitmap_swap_v3(bih);
+ }
+ break;
+ }
+
+ if(size && (void *)data != (void *)bih)
+ {
+ /* We have the fileheader still attached, remove it */
+ memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER));
+ return sizeof(BITMAPFILEHEADER);
+ }
+ return 0;
+}
+#undef FL_SIGBE
+#undef FL_SIZEBE
+#undef FL_V4
+
+/*
+ * Cursor and icon splitter functions used when allocating
+ * cursor- and icon-groups.
+ */
+typedef struct {
+ language_t lan;
+ int id;
+} id_alloc_t;
+
+static int get_new_id(id_alloc_t **list, int *n, language_t *lan)
+{
+ int i;
+ assert(lan != NULL);
+ assert(list != NULL);
+ assert(n != NULL);
+
+ if(!*list)
+ {
+ *list = (id_alloc_t *)xmalloc(sizeof(id_alloc_t));
+ *n = 1;
+ (*list)[0].lan = *lan;
+ (*list)[0].id = 1;
+ return 1;
+ }
+
+ for(i = 0; i < *n; i++)
+ {
+ if((*list)[i].lan.id == lan->id && (*list)[i].lan.sub == lan->sub)
+ return ++((*list)[i].id);
+ }
+
+ *list = (id_alloc_t *)xrealloc(*list, sizeof(id_alloc_t) * (*n+1));
+ (*list)[*n].lan = *lan;
+ (*list)[*n].id = 1;
+ *n += 1;
+ return 1;
+}
+
+static int alloc_icon_id(language_t *lan)
+{
+ static id_alloc_t *idlist = NULL;
+ static int nid = 0;
+
+ return get_new_id(&idlist, &nid, lan);
+}
+
+static int alloc_cursor_id(language_t *lan)
+{
+ static id_alloc_t *idlist = NULL;
+ static int nid = 0;
+
+ return get_new_id(&idlist, &nid, lan);
+}
+
+static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico)
+{
+ int cnt;
+ int i;
+ icon_dir_entry_t *ide;
+ icon_t *ico;
+ icon_t *list = NULL;
+ icon_header_t *ih = (icon_header_t *)rd->data;
+ int swap = 0;
+
+ /* FIXME: Distinguish between normal and animated icons (RIFF format) */
+ if(ih->type == 1)
+ swap = 0;
+ else if(BYTESWAP_WORD(ih->type) == 1)
+ swap = 1;
+ else
+ yyerror("Icon resource data has invalid type id %d", ih->type);
+
+ cnt = swap ? BYTESWAP_WORD(ih->count) : ih->count;
+ ide = (icon_dir_entry_t *)((char *)rd->data + sizeof(icon_header_t));
+ for(i = 0; i < cnt; i++)
+ {
+ ico = new_icon();
+ ico->id = alloc_icon_id(icog->lvc.language);
+ ico->lvc.language = dup_language(icog->lvc.language);
+ if(swap)
+ {
+ ide[i].offset = BYTESWAP_DWORD(ide[i].offset);
+ ide[i].ressize= BYTESWAP_DWORD(ide[i].ressize);
+ }
+ if(ide[i].offset > rd->size
+ || ide[i].offset + ide[i].ressize > rd->size)
+ yyerror("Icon resource data corrupt");
+ ico->width = ide[i].width;
+ ico->height = ide[i].height;
+ ico->nclr = ide[i].nclr;
+ ico->planes = swap ? BYTESWAP_WORD(ide[i].planes) : ide[i].planes;
+ ico->bits = swap ? BYTESWAP_WORD(ide[i].bits) : ide[i].bits;
+ convert_bitmap((char *)rd->data + ide[i].offset, 0);
+ if(!ico->planes)
+ {
+ WORD planes;
+ /* Argh! They did not fill out the resdir structure */
+ planes = ((BITMAPINFOHEADER *)((char *)rd->data + ide[i].offset))->biPlanes;
+ /* The bitmap is in destination byteorder. We want native for our structures */
+ switch(byteorder)
+ {
+#if BYTE_ORDER == BIG_ENDIAN
+ case WRC_BO_LITTLE:
+#else
+ case WRC_BO_BIG:
+#endif
+ ico->planes = BYTESWAP_WORD(planes);
+ break;
+ default:
+ ico->planes = planes;
+ }
+ }
+ if(!ico->bits)
+ {
+ WORD bits;
+ /* Argh! They did not fill out the resdir structure */
+ bits = ((BITMAPINFOHEADER *)((char *)rd->data + ide[i].offset))->biBitCount;
+ /* The bitmap is in destination byteorder. We want native for our structures */
+ switch(byteorder)
+ {
+#if BYTE_ORDER == BIG_ENDIAN
+ case WRC_BO_LITTLE:
+#else
+ case WRC_BO_BIG:
+#endif
+ ico->bits = BYTESWAP_WORD(bits);
+ break;
+ default:
+ ico->bits = bits;
+ }
+ }
+ ico->data = new_raw_data();
+ copy_raw_data(ico->data, rd, ide[i].offset, ide[i].ressize);
+ if(!list)
+ {
+ list = ico;
+ }
+ else
+ {
+ ico->next = list;
+ list->prev = ico;
+ list = ico;
+ }
+ }
+ icog->iconlist = list;
+ *nico = cnt;
+}
+
+static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur)
+{
+ int cnt;
+ int i;
+ cursor_dir_entry_t *cde;
+ cursor_t *cur;
+ cursor_t *list = NULL;
+ cursor_header_t *ch = (cursor_header_t *)rd->data;
+ int swap = 0;
+
+ /* FIXME: Distinguish between normal and animated cursors (RIFF format)*/
+ if(ch->type == 2)
+ swap = 0;
+ else if(BYTESWAP_WORD(ch->type) == 2)
+ swap = 1;
+ else
+ yyerror("Cursor resource data has invalid type id %d", ch->type);
+ cnt = swap ? BYTESWAP_WORD(ch->count) : ch->count;
+ cde = (cursor_dir_entry_t *)((char *)rd->data + sizeof(cursor_header_t));
+ for(i = 0; i < cnt; i++)
+ {
+ WORD planes;
+ WORD bits;
+ cur = new_cursor();
+ cur->id = alloc_cursor_id(curg->lvc.language);
+ cur->lvc.language = dup_language(curg->lvc.language);
+ if(swap)
+ {
+ cde[i].offset = BYTESWAP_DWORD(cde[i].offset);
+ cde[i].ressize= BYTESWAP_DWORD(cde[i].ressize);
+ }
+ if(cde[i].offset > rd->size
+ || cde[i].offset + cde[i].ressize > rd->size)
+ yyerror("Cursor resource data corrupt");
+ cur->width = cde[i].width;
+ cur->height = cde[i].height;
+ cur->nclr = cde[i].nclr;
+ convert_bitmap((char *)rd->data + cde[i].offset, 0);
+ /* The next two are to support color cursors */
+ planes = ((BITMAPINFOHEADER *)((char *)rd->data + cde[i].offset))->biPlanes;
+ bits = ((BITMAPINFOHEADER *)((char *)rd->data + cde[i].offset))->biBitCount;
+ /* The bitmap is in destination byteorder. We want native for our structures */
+ switch(byteorder)
+ {
+#if BYTE_ORDER == BIG_ENDIAN
+ case WRC_BO_LITTLE:
+#else
+ case WRC_BO_BIG:
+#endif
+ cur->planes = BYTESWAP_WORD(planes);
+ cur->bits = BYTESWAP_WORD(bits);
+ break;
+ default:
+ cur->planes = planes;
+ cur->bits = bits;
+ }
+ if(!win32 && (cur->planes != 1 || cur->bits != 1))
+ yywarning("Win16 cursor contains colors");
+ cur->xhot = swap ? BYTESWAP_WORD(cde[i].xhot) : cde[i].xhot;
+ cur->yhot = swap ? BYTESWAP_WORD(cde[i].yhot) : cde[i].yhot;
+ cur->data = new_raw_data();
+ copy_raw_data(cur->data, rd, cde[i].offset, cde[i].ressize);
+ if(!list)
+ {
+ list = cur;
+ }
+ else
+ {
+ cur->next = list;
+ list->prev = cur;
+ list = cur;
+ }
+ }
+ curg->cursorlist = list;
+ *ncur = cnt;
+}
+
+
icon_group_t *new_icon_group(raw_data_t *rd, int *memopt)
{
icon_group_t *icog = (icon_group_t *)xmalloc(sizeof(icon_group_t));
@@ -185,6 +563,7 @@
bitmap_t *new_bitmap(raw_data_t *rd, int *memopt)
{
bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t));
+
bmp->data = rd;
if(memopt)
{
@@ -193,6 +572,7 @@
}
else
bmp->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
+ rd->size -= convert_bitmap(rd->data, rd->size);
return bmp;
}