- 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;
 }