Index: tools/wrc/Makefile.in
===================================================================
RCS file: /home/wine/wine/tools/wrc/Makefile.in,v
retrieving revision 1.28
diff -u -r1.28 Makefile.in
--- tools/wrc/Makefile.in	1 Sep 2003 23:59:41 -0000	1.28
+++ tools/wrc/Makefile.in	5 Oct 2003 03:08:53 -0000
@@ -15,6 +15,7 @@
 	genres.c \
 	newstruc.c \
 	readres.c \
+	translation.c \
 	utils.c \
 	wrc.c \
 	writeres.c
Index: tools/wrc/wrc.c
===================================================================
RCS file: /home/wine/wine/tools/wrc/wrc.c,v
retrieving revision 1.36
diff -u -r1.36 wrc.c
--- tools/wrc/wrc.c	18 Aug 2003 19:48:58 -0000	1.36
+++ tools/wrc/wrc.c	5 Oct 2003 03:08:53 -0000
@@ -39,6 +39,7 @@
 #include "utils.h"
 #include "readres.h"
 #include "dumpres.h"
+#include "translation.h"
 #include "genres.h"
 #include "newstruc.h"
 #include "parser.h"
@@ -97,6 +98,7 @@
 	"    * 0x08 Preprocessor messages\n"
 	"    * 0x10 Preprocessor lex messages\n"
 	"    * 0x20 Preprocessor yacc trace\n"
+	"    * 0x40 Verify translations\n"
 	"If no input filename is given and the output name is not overridden\n"
 	"with -o, then the output is written to \"wrc.tab.res\"\n"
 	;
@@ -123,6 +125,7 @@
  * debuglevel & DEBUGLEVEL_PPMSG	Preprocessor messages
  * debuglevel & DEBUGLEVEL_PPLEX	Preprocessor lex trace
  * debuglevel & DEBUGLEVEL_PPTRACE	Preprocessor yacc trace
+ * debuglevel & DEBUGLEVEL_TRANSLATION	Verify translations
  */
 int debuglevel = DEBUGLEVEL_NONE;
 
@@ -453,6 +456,12 @@
 
 	if(debuglevel & DEBUGLEVEL_DUMP)
 		dump_resources(resource_top);
+
+	if(debuglevel & DEBUGLEVEL_TRANSLATION)
+	{
+		verify_translations(resource_top);
+		exit(0);
+	}
 
 	/* Convert the internal lists to binary data */
 	resources2res(resource_top);
Index: tools/wrc/wrc.h
===================================================================
RCS file: /home/wine/wine/tools/wrc/wrc.h,v
retrieving revision 1.31
diff -u -r1.31 wrc.h
--- tools/wrc/wrc.h	5 Sep 2003 23:15:40 -0000	1.31
+++ tools/wrc/wrc.h	5 Oct 2003 03:08:53 -0000
@@ -45,6 +45,7 @@
 #define DEBUGLEVEL_PPMSG	0x0008
 #define DEBUGLEVEL_PPLEX	0x0010
 #define DEBUGLEVEL_PPTRACE	0x0020
+#define DEBUGLEVEL_TRANSLATION	0x0040
 
 extern int win32;
 extern int create_res;
--- /dev/null	2002-08-30 19:31:37.000000000 -0400
+++ tools/wrc/translation.c	2003-10-04 22:21:48.000000000 -0400
@@ -0,0 +1,799 @@
+/*
+ * Copyright 2003 Vincent Béron
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "translation.h"
+
+int master_language = LANG_ENGLISH;
+
+KEEP_RESOURCE(accelerator)
+KEEP_RESOURCE_RAW(bitmap)
+KEEP_RESOURCE(cursor)
+KEEP_RESOURCE(cursor_group)
+KEEP_RESOURCE(dialog)
+KEEP_RESOURCE(dialogex)
+KEEP_RESOURCE_RAW(font)
+KEEP_RESOURCE(icon)
+KEEP_RESOURCE(icon_group)
+KEEP_RESOURCE(menu)
+KEEP_RESOURCE(menuex)
+KEEP_RESOURCE_RAW(rcdata)
+KEEP_RESOURCE(stringtable)
+KEEP_RESOURCE_RAW(user)
+KEEP_RESOURCE_RAW(messagetable)
+KEEP_RESOURCE(versioninfo)
+KEEP_RESOURCE_RAW(dlginit)
+KEEP_RESOURCE(toolbar)
+KEEP_RESOURCE_RAW(ani_curico)
+
+static int compare_accelerator(accelerator_t *accelerator1, accelerator_t *accelerator2) {
+	int different = 0;
+	event_t *ev1 = NULL, *ev2 = NULL;
+	if(!different &&
+	   ((accelerator1->memopt != accelerator2->memopt) ||
+	   (accelerator1->lvc.version != accelerator2->lvc.version) ||
+	   (accelerator1->lvc.characts != accelerator2->lvc.characts)))
+		different = 1;
+	ev1 = accelerator1->events;
+	ev2 = accelerator2->events;
+	while(!different && ev1 && ev2) {
+		if(!different &&
+		   ((ev1->id != ev2->id) ||
+		   (ev1->flags != ev2->flags)))
+			different = 1;
+		ev1 = ev1->next;
+		ev2 = ev2->next;
+	}
+	if(!different &&
+	   ((ev1 && !ev2) || (!ev1 && ev2)))
+		different = 1;
+	return different;
+}
+
+static int compare_bitmap(bitmap_t *bitmap1, bitmap_t *bitmap2) {
+	int different = 0;
+	if(!different &&
+	   ((bitmap1->memopt != bitmap2->memopt) ||
+	   (bitmap1->data->lvc.version != bitmap2->data->lvc.version) ||
+	   (bitmap1->data->lvc.characts != bitmap2->data->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+static int compare_cursor(cursor_t *cursor1, cursor_t *cursor2) {
+	int different = 0;
+	if(!different &&
+	   ((cursor1->id != cursor2->id) ||
+	   (cursor1->width != cursor2->width) ||
+	   (cursor1->height != cursor2->height) ||
+	   (cursor1->xhot != cursor2->xhot) ||
+	   (cursor1->yhot != cursor2->yhot)))
+		different = 1;
+	if(!different &&
+	   ((cursor1->lvc.version != cursor2->lvc.version) ||
+	   (cursor1->lvc.characts != cursor2->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+static int compare_cursor_group(cursor_group_t *cursor_group1, cursor_group_t *cursor_group2) {
+	int different = 0;
+	cursor_t *cursor1 = NULL, *cursor2 = NULL;
+	if(!different &&
+	   ((cursor_group1->memopt != cursor_group2->memopt) ||
+	   (cursor_group1->lvc.version != cursor_group2->lvc.version) ||
+	   (cursor_group1->lvc.characts != cursor_group2->lvc.characts)))
+		different = 1;
+	if(!different &&
+	   (cursor_group1->ncursor != cursor_group2->ncursor))
+		different = 1;
+	if(!different) {
+		cursor1 = cursor_group1->cursorlist;
+		cursor2 = cursor_group2->cursorlist;
+		while(!different && cursor1 && cursor2) {
+			different = compare_cursor(cursor1, cursor2);
+			cursor1 = cursor1->next;
+			cursor2 = cursor2->next;
+		}
+		if(!different &&
+		   ((cursor1 && !cursor2) ||
+		   (!cursor1 && cursor2)))
+			different = 1;
+	}
+	return different;
+}
+
+static int compare_control(control_t *control1, control_t *control2) {
+	int different = 0;
+	char *nameid = NULL;
+	if(!different &&
+		((control1 && !control2) ||
+		(!control1 && control2)))
+			different = 1;
+	if(different || !control1 || !control2)
+		return different;
+	nameid = strdup(get_nameid_str(control1->ctlclass));
+	if(!different && strcmp(nameid, get_nameid_str(control2->ctlclass)))
+		different = 1;
+	free(nameid);
+	if(!different && 
+	   (control1->id != control2->id))
+		different = 1;
+	if(!different && control1->gotstyle && control2->gotstyle) {
+		if((!control1->style || !control2->style) ||
+		   (control1->style->and_mask || control2->style->and_mask) ||
+		   (control1->style->or_mask != control2->style->or_mask))
+			different = 1;
+	} else if(!different &&
+		  ((control1->gotstyle && !control2->gotstyle) ||
+		  (!control1->gotstyle && control2->gotstyle)))
+			different = 1;
+	if(!different && control1->gotexstyle && control2->gotexstyle) {
+		if((!control1->exstyle || !control2->exstyle) ||
+		   (control1->exstyle->and_mask || control2->exstyle->and_mask) ||
+		   (control1->exstyle->or_mask != control2->exstyle->or_mask))
+			different = 1;
+	} else if(!different &&
+		  ((control1->gotexstyle && !control2->gotexstyle) ||
+		  (!control1->gotexstyle && control2->gotexstyle)))
+			different = 1;
+	if(!different && control1->gothelpid && control2->gothelpid) {
+		if(control1->helpid != control2->helpid)
+			different = 1;
+	} else if(!different &&
+		  ((control1->gothelpid && !control2->gothelpid) ||
+		  (!control1->gothelpid && control2->gothelpid)))
+			different = 1;
+	return different;
+}
+
+static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
+	int different = 0;
+	char *nameid = NULL;
+	if(!different &&
+	   ((dialog1->memopt != dialog2->memopt) ||
+	   (dialog1->lvc.version != dialog2->lvc.version) ||
+	   (dialog1->lvc.characts != dialog2->lvc.characts)))
+		different = 1;
+	if(!different && dialog1->gotstyle && dialog2->gotstyle) {
+		if((!dialog1->style || !dialog2->style) ||
+		   (dialog1->style->and_mask || dialog2->style->and_mask) ||
+		   (dialog1->style->or_mask != dialog2->style->or_mask))
+			different = 1;
+	} else if(!different &&
+		  ((dialog1->gotstyle && !dialog2->gotstyle) ||
+		  (!dialog1->gotstyle && dialog2->gotstyle)))
+			different = 1;
+	if(!different && dialog1->gotexstyle && dialog2->gotexstyle) {
+		if((!dialog1->exstyle || !dialog2->exstyle) ||
+		   (dialog1->exstyle->and_mask || dialog2->exstyle->and_mask) ||
+		   (dialog1->exstyle->or_mask != dialog2->exstyle->or_mask))
+			different = 1;
+	} else if(!different &&
+		  ((dialog1->gotexstyle && !dialog2->gotexstyle) ||
+		  (!dialog1->gotexstyle && dialog2->gotexstyle)))
+			different = 1;
+	nameid = strdup(get_nameid_str(dialog1->menu));
+	if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
+		different = 1;
+	free(nameid);
+	nameid = strdup(get_nameid_str(dialog1->dlgclass));
+	if(!different && strcmp(nameid, get_nameid_str(dialog2->dlgclass)))
+		different = 1;
+	free(nameid);
+	if(!different)
+		different = compare_control(dialog1->controls, dialog2->controls);
+	return different;
+}
+
+static int compare_dialogex(dialogex_t *dialogex1, dialogex_t *dialogex2) {
+	int different = 0;
+	char *nameid = NULL;
+	if(!different &&
+	   ((dialogex1->memopt != dialogex2->memopt) ||
+	   (dialogex1->lvc.version != dialogex2->lvc.version) ||
+	   (dialogex1->lvc.characts != dialogex2->lvc.characts)))
+		different = 1;
+	if(!different && dialogex1->gotstyle && dialogex2->gotstyle) {
+		if((!dialogex1->style || !dialogex2->style) ||
+		   (dialogex1->style->and_mask || dialogex2->style->and_mask) ||
+		   (dialogex1->style->or_mask != dialogex2->style->or_mask))
+			different = 1;
+	} else if(!different &&
+		  ((dialogex1->gotstyle && !dialogex2->gotstyle) ||
+		  (!dialogex1->gotstyle && dialogex2->gotstyle)))
+			different = 1;
+	if(!different && dialogex1->gotexstyle && dialogex2->gotexstyle) {
+		if((!dialogex1->exstyle || !dialogex2->exstyle) ||
+		   (dialogex1->exstyle->and_mask || dialogex2->exstyle->and_mask) ||
+		   (dialogex1->exstyle->or_mask != dialogex2->exstyle->or_mask))
+			different = 1;
+	} else if(!different &&
+		  ((dialogex1->gotexstyle && !dialogex2->gotexstyle) ||
+		  (!dialogex1->gotexstyle && dialogex2->gotexstyle)))
+			different = 1;
+	if(!different && dialogex1->gothelpid && dialogex2->gothelpid) {
+		if(dialogex1->helpid != dialogex2->helpid)
+			different = 1;
+	} else if(!different &&
+		  ((dialogex1->gothelpid && !dialogex2->gothelpid) ||
+		  (!dialogex1->gothelpid && dialogex2->gothelpid)))
+			different = 1;
+	nameid = strdup(get_nameid_str(dialogex1->menu));
+	if(!different && strcmp(nameid, get_nameid_str(dialogex2->menu)))
+		different = 1;
+	free(nameid);
+	nameid = strdup(get_nameid_str(dialogex1->dlgclass));
+	if(!different && strcmp(nameid, get_nameid_str(dialogex2->dlgclass)))
+		different = 1;
+	free(nameid);
+	if(!different)
+		different = compare_control(dialogex1->controls, dialogex2->controls);
+	return different;
+}
+
+static int compare_font(font_t *font1, font_t *font2) {
+	int different = 0;
+	if(!different &&
+	   ((font1->memopt != font2->memopt) ||
+	   (font1->data->lvc.version != font2->data->lvc.version) ||
+	   (font1->data->lvc.characts != font2->data->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+static int compare_icon(icon_t *icon1, icon_t *icon2) {
+	int different = 0;
+	if(!different &&
+	   ((icon1->id != icon2->id) ||
+	   (icon1->width != icon2->width) ||
+	   (icon1->height != icon2->height)))
+		different = 1;
+	if(!different &&
+	   ((icon1->lvc.version != icon2->lvc.version) ||
+	   (icon1->lvc.characts != icon2->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+static int compare_icon_group(icon_group_t *icon_group1, icon_group_t *icon_group2) {
+	int different = 0;
+	icon_t *icon1 = NULL, *icon2 = NULL;
+	if(!different &&
+	   ((icon_group1->memopt != icon_group2->memopt) ||
+	   (icon_group1->lvc.version != icon_group2->lvc.version) ||
+	   (icon_group1->lvc.characts != icon_group2->lvc.characts)))
+		different = 1;
+	if(!different &&
+	   (icon_group1->nicon != icon_group2->nicon))
+		different = 1;
+	if(!different) {
+		icon1 = icon_group1->iconlist;
+		icon2 = icon_group2->iconlist;
+		while(!different && icon1 && icon2) {
+			different = compare_icon(icon1, icon2);
+			icon1 = icon1->next;
+			icon2 = icon2->next;
+		}
+		if(!different &&
+		   ((icon1 && !icon2) ||
+		   (!icon1 && icon2)))
+			different = 1;
+	}
+	return different;
+}
+
+static int compare_menu_item(menu_item_t *menu_item1, menu_item_t *menu_item2) {
+	int different = 0;
+	while(!different && menu_item1 && menu_item2) {
+		if(menu_item1->popup && menu_item2->popup)
+			different = compare_menu_item(menu_item1->popup, menu_item2->popup);
+		else if(!menu_item1->popup && !menu_item2->popup) {
+			if(menu_item1->name && menu_item2->name) {
+				if((menu_item1->id != menu_item2->id) ||
+				   (menu_item1->state != menu_item2->state))
+					different = 1;
+			} else if((menu_item1->name && !menu_item2->name) ||
+				  (!menu_item1->name && menu_item2->name))
+					different = 1;
+		} else
+			different = 1;
+		menu_item1 = menu_item1->next;
+		menu_item2 = menu_item2->next;
+	}
+	if(!different &&
+	   ((menu_item1 && !menu_item2) ||
+	   (!menu_item1 && menu_item2)))
+		different = 1;
+	return different;
+}
+
+static int compare_menu(menu_t *menu1, menu_t *menu2) {
+	int different = 0;
+	if(!different &&
+	   ((menu1->memopt != menu2->memopt) ||
+	   (menu1->lvc.version != menu2->lvc.version) ||
+	   (menu1->lvc.characts != menu2->lvc.characts)))
+		different = 1;
+	if(!different)
+		different = compare_menu_item(menu1->items, menu2->items);
+	return different;
+}
+
+static int compare_menuex_item(menuex_item_t *menuex_item1, menuex_item_t *menuex_item2) {
+	int different = 0;
+	while(!different && menuex_item1 && menuex_item2) {
+		if(menuex_item1->popup && menuex_item2->popup) {
+			if(!different && menuex_item1->gotid && menuex_item2->gotid) {
+				if(menuex_item1->id != menuex_item2->id)
+					different = 1;
+			} else if(!different &&
+				  ((menuex_item1->gotid && !menuex_item2->gotid) ||
+				  (!menuex_item2->gotid && menuex_item2->gotid)))
+					different = 1;
+			if(!different && menuex_item1->gottype && menuex_item2->gottype) {
+				if(menuex_item1->type != menuex_item2->type)
+					different = 1;
+			} else if(!different &&
+				  ((menuex_item1->gottype && !menuex_item2->gottype) ||
+				  (!menuex_item2->gottype && menuex_item2->gottype)))
+					different = 1;
+			if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
+				if(menuex_item1->state != menuex_item2->state)
+					different = 1;
+			} else if(!different &&
+				  ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
+				  (!menuex_item2->gotstate && menuex_item2->gotstate)))
+					different = 1;
+			if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
+				if(menuex_item1->helpid != menuex_item2->helpid)
+					different = 1;
+			} else if(!different &&
+				  ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
+				  (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
+					different = 1;
+			if(!different)
+				different = compare_menuex_item(menuex_item1->popup, menuex_item2->popup);
+		} else if(!menuex_item1->popup && !menuex_item2->popup) {
+			if(menuex_item1->name && menuex_item2->name) {
+				if(!different && menuex_item1->gotid && menuex_item2->gotid) {
+					if(menuex_item1->id != menuex_item2->id)
+						different = 1;
+				} else if(!different &&
+					  ((menuex_item1->gotid && !menuex_item2->gotid) ||
+					  (!menuex_item2->gotid && menuex_item2->gotid)))
+						different = 1;
+				if(!different && menuex_item1->gottype && menuex_item2->gottype) {
+					if(menuex_item1->type != menuex_item2->type)
+						different = 1;
+				} else if(!different &&
+					  ((menuex_item1->gottype && !menuex_item2->gottype) ||
+					  (!menuex_item2->gottype && menuex_item2->gottype)))
+						different = 1;
+				if(!different && menuex_item1->gotstate && menuex_item2->gotstate) {
+					if(menuex_item1->state != menuex_item2->state)
+						different = 1;
+				} else if(!different &&
+					  ((menuex_item1->gotstate && !menuex_item2->gotstate) ||
+					  (!menuex_item2->gotstate && menuex_item2->gotstate)))
+						different = 1;
+				if(!different && menuex_item1->gothelpid && menuex_item2->gothelpid) {
+					if(menuex_item1->helpid != menuex_item2->helpid)
+						different = 1;
+				} else if(!different &&
+					  ((menuex_item1->gothelpid && !menuex_item2->gothelpid) ||
+					  (!menuex_item2->gothelpid && menuex_item2->gothelpid)))
+						different = 1;
+			} else if((menuex_item1->name && !menuex_item2->name) ||
+				  (!menuex_item1->name && menuex_item2->name))
+					different = 1;
+		} else
+			different = 1;
+		menuex_item1 = menuex_item1->next;
+		menuex_item2 = menuex_item2->next;
+	}
+	if(!different &&
+	   ((menuex_item1 && !menuex_item2) ||
+	   (!menuex_item1 && menuex_item2)))
+		different = 1;
+	return different;
+}
+
+static int compare_menuex(menuex_t *menuex1, menuex_t *menuex2) {
+	int different = 0;
+	if(!different &&
+	   ((menuex1->memopt != menuex2->memopt) ||
+	   (menuex1->lvc.version != menuex2->lvc.version) ||
+	   (menuex1->lvc.characts != menuex2->lvc.characts)))
+		different = 1;
+	if(!different)
+		different = compare_menuex_item(menuex1->items, menuex2->items);
+	return different;
+}
+
+static int compare_rcdata(rcdata_t *rcdata1, rcdata_t *rcdata2) {
+	int different = 0;
+	if(!different &&
+	   ((rcdata1->memopt != rcdata2->memopt) ||
+	   (rcdata1->data->lvc.version != rcdata2->data->lvc.version) ||
+	   (rcdata1->data->lvc.characts != rcdata2->data->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+static int compare_stringtable(stringtable_t *stringtable1, stringtable_t *stringtable2) {
+	int different = 0;
+	int i;
+	while(!different && stringtable1 && stringtable2) {
+		if((stringtable1->memopt != stringtable2->memopt) ||
+		   (stringtable1->lvc.version != stringtable2->lvc.version) ||
+		   (stringtable1->lvc.characts != stringtable2->lvc.characts))
+			different = 1;
+		if(!different) {
+			if((stringtable1->nentries != stringtable2->nentries) ||
+			   (stringtable1->idbase != stringtable2->idbase))
+				different = 1;
+			else
+				for(i = 0 ; i < stringtable1->nentries; i++)
+					if((stringtable1->entries[i].id != stringtable2->entries[i].id) ||
+					   (stringtable1->entries[i].memopt != stringtable2->entries[i].memopt) ||
+					   (stringtable1->entries[i].str && !stringtable2->entries[i].str) ||
+					   (!stringtable1->entries[i].str && stringtable2->entries[i].str)) {
+						different = 1;
+						break;
+					}
+		}
+		stringtable1 = stringtable1->next;
+		stringtable2 = stringtable2->next;
+	}
+	return different;
+}
+
+static int compare_user(user_t *user1, user_t *user2) {
+	int different = 0;
+	char *nameid = NULL;
+	if(!different &&
+	   ((user1->memopt != user2->memopt) ||
+	   (user1->data->lvc.version != user2->data->lvc.version) ||
+	   (user1->data->lvc.characts != user2->data->lvc.characts)))
+		different = 1;
+	nameid = strdup(get_nameid_str(user1->type));
+	if(!different && strcmp(nameid, get_nameid_str(user2->type)))
+		different = 1;
+	free(nameid);
+	return different;
+}
+
+static int compare_messagetable(messagetable_t *messagetable1, messagetable_t *messagetable2) {
+	int different = 0;
+	if(!different &&
+	   ((messagetable1->memopt != messagetable2->memopt) ||
+	   (messagetable1->data->lvc.version != messagetable2->data->lvc.version) ||
+	   (messagetable1->data->lvc.characts != messagetable2->data->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+static int compare_string(string_t *string1, string_t *string2) {
+	int different = 0;
+	if(!different &&
+	   ((string1->size != string2->size) ||
+	   (string1->type != string2->type)))
+		different = 1;
+	if(!different) {
+		if(string1->type == str_char)
+			different = memcmp(string1->str.cstr, string2->str.cstr, string1->size);
+		else if(string1->type == str_unicode)
+			different = memcmp(string1->str.wstr, string2->str.wstr, string1->size*sizeof(WCHAR));
+		else
+			different = 1;
+	}
+	return different;
+}
+
+static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2);
+
+static int compare_ver_value(ver_value_t *ver_value1, ver_value_t *ver_value2) {
+	int different = 0;
+	int i = 0;
+	if(!different &&
+	   (ver_value1->type == ver_value2->type)) {
+		switch(ver_value1->type) {
+			case val_str:
+				if(!different && ver_value1->key && ver_value2->key)
+					different = compare_string(ver_value1->key, ver_value2->key);
+				else if(!different &&
+					((ver_value1->key && !ver_value2->key) ||
+					(!ver_value1->key && ver_value2->key)))
+						different = 1;
+				break;
+			case val_words:
+				if(!different && ver_value1->key && ver_value2->key)
+					different = compare_string(ver_value1->key, ver_value2->key);
+				else if(!different &&
+					((ver_value1->key && !ver_value2->key) ||
+					(!ver_value1->key && ver_value2->key)))
+						different = 1;
+				if(!different && ver_value1->value.words && ver_value2->value.words) {
+					if(!different &&
+					   (ver_value1->value.words->nwords != ver_value2->value.words->nwords))
+						different = 1;
+					if(!different)
+						for(i = 0; i < ver_value1->value.words->nwords; i++) {
+							if(ver_value1->value.words->words[i] != ver_value2->value.words->words[i]) {
+								different = 1;
+								break;
+							}
+						}
+				} else if(!different &&
+					  ((ver_value1->value.words && !ver_value2->value.words) ||
+					  (!ver_value1->value.words && ver_value2->value.words)))
+						different = 1;
+				break;
+			case val_block:
+				if(!different && ver_value1->value.block && ver_value2->value.block)
+					different = compare_ver_block(ver_value1->value.block, ver_value2->value.block);
+				else if(!different &&
+					((ver_value1->value.block && !ver_value2->value.block) ||
+					(!ver_value1->value.block && ver_value2->value.block)))
+						different = 1;
+				break;
+			default:
+				different = 1;
+		}
+	} else
+		different = 1;
+	return different;
+}
+
+static int compare_ver_block(ver_block_t *ver_block1, ver_block_t *ver_block2) {
+	int different = 0;
+	ver_value_t *ver_value1 = NULL, *ver_value2 = NULL;
+	if(!different) {
+		ver_value1 = ver_block1->values;
+		ver_value2 = ver_block2->values;
+		while(!different && ver_value1 && ver_value2) {
+			different = compare_ver_value(ver_value1, ver_value2);
+			ver_value1 = ver_value1->next;
+			ver_value2 = ver_value2->next;
+		}
+		if(!different &&
+		   ((ver_value1 && !ver_value2) ||
+		   (!ver_value1 && ver_value2)))
+			different = 1;
+	}
+	return different;
+}
+
+static int compare_versioninfo(versioninfo_t *versioninfo1, versioninfo_t *versioninfo2) {
+	int different = 0;
+	ver_block_t *ver_block1 = NULL, *ver_block2 = NULL;
+	if(!different &&
+	   ((versioninfo1->memopt != versioninfo2->memopt) ||
+	   (versioninfo1->lvc.version != versioninfo2->lvc.version) ||
+	   (versioninfo1->lvc.characts != versioninfo2->lvc.characts)))
+		different = 1;
+	if(!different && versioninfo1->gotit.fv && versioninfo2->gotit.fv) {
+		if((versioninfo1->filever_maj1 != versioninfo2->filever_maj1) ||
+		   (versioninfo1->filever_maj2 != versioninfo2->filever_maj2) ||
+		   (versioninfo1->filever_min1 != versioninfo2->filever_min1) ||
+		   (versioninfo1->filever_min2 != versioninfo2->filever_min2))
+			different = 1;
+	} else if(!different &&
+		  ((versioninfo1->gotit.fv && !versioninfo2->gotit.fv) ||
+		  (!versioninfo1->gotit.fv && versioninfo2->gotit.fv)))
+			different = 1;
+	if(!different && versioninfo1->gotit.pv && versioninfo2->gotit.pv) {
+		if((versioninfo1->prodver_maj1 != versioninfo2->prodver_maj1) ||
+		   (versioninfo1->prodver_maj2 != versioninfo2->prodver_maj2) ||
+		   (versioninfo1->prodver_min1 != versioninfo2->prodver_min1) ||
+		   (versioninfo1->prodver_min2 != versioninfo2->prodver_min2))
+			different = 1;
+	} else if(!different &&
+		  ((versioninfo1->gotit.pv && !versioninfo2->gotit.pv) ||
+		  (!versioninfo1->gotit.pv && versioninfo2->gotit.pv)))
+			different = 1;
+	if(!different && versioninfo1->gotit.fo && versioninfo2->gotit.fo) {
+		if(versioninfo1->fileos != versioninfo2->fileos)
+			different = 1;
+	} else if(!different &&
+		  ((versioninfo1->gotit.fo && !versioninfo2->gotit.fo) ||
+		  (!versioninfo1->gotit.fo && versioninfo2->gotit.fo)))
+			different = 1;
+	if(!different && versioninfo1->gotit.ff && versioninfo2->gotit.ff) {
+		if(versioninfo1->fileflags != versioninfo2->fileflags)
+			different = 1;
+	} else if(!different &&
+		  ((versioninfo1->gotit.ff && !versioninfo2->gotit.ff) ||
+		  (!versioninfo1->gotit.ff && versioninfo2->gotit.ff)))
+			different = 1;
+	if(!different && versioninfo1->gotit.ffm && versioninfo2->gotit.ffm) {
+		if(versioninfo1->fileflagsmask != versioninfo2->fileflagsmask)
+			different = 1;
+	} else if(!different &&
+		  ((versioninfo1->gotit.ffm && !versioninfo2->gotit.ffm) ||
+		  (!versioninfo1->gotit.ffm && versioninfo2->gotit.ffm)))
+			different = 1;
+	if(!different && versioninfo1->gotit.ft && versioninfo2->gotit.ft) {
+		if(versioninfo1->filetype != versioninfo2->filetype)
+			different = 1;
+	} else if(!different &&
+		  ((versioninfo1->gotit.ft && !versioninfo2->gotit.ft) ||
+		  (!versioninfo1->gotit.ft && versioninfo2->gotit.ft)))
+			different = 1;
+	if(!different && versioninfo1->gotit.fst && versioninfo2->gotit.fst) {
+		if(versioninfo1->filesubtype != versioninfo2->filesubtype)
+			different = 1;
+	} else if(!different &&
+		  ((versioninfo1->gotit.fst && !versioninfo2->gotit.fst) ||
+		  (!versioninfo1->gotit.fst && versioninfo2->gotit.fst)))
+			different = 1;
+	if(!different) {
+		ver_block1 = versioninfo1->blocks;
+		ver_block2 = versioninfo2->blocks;
+		while(!different && ver_block1 && ver_block2) {
+			different = compare_ver_block(ver_block1, ver_block2);
+			ver_block1 = ver_block1->next;
+			ver_block2 = ver_block2->next;
+		}
+		if(!different &&
+		   ((ver_block1 && !ver_block2) ||
+		   (ver_block1 && !ver_block2)))
+			different = 1;
+	}
+	return different;
+}
+
+static int compare_dlginit(dlginit_t *dlginit1, dlginit_t *dlginit2) {
+	int different = 0;
+	if(!different &&
+	   ((dlginit1->memopt != dlginit2->memopt) ||
+	   (dlginit1->data->lvc.version != dlginit2->data->lvc.version) ||
+	   (dlginit1->data->lvc.characts != dlginit2->data->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+static int compare_toolbar_item(toolbar_item_t *toolbar_item1, toolbar_item_t *toolbar_item2) {
+	int different = 0;
+	while(!different && toolbar_item1 && toolbar_item2) {
+		if((toolbar_item1->id && !toolbar_item2->id) ||
+		   (!toolbar_item1->id && toolbar_item2->id))
+			different = 1;
+		toolbar_item1 = toolbar_item1->next;
+		toolbar_item2 = toolbar_item2->next;
+	}
+	if(!different &&
+	   ((toolbar_item1 && !toolbar_item2) ||
+	   (!toolbar_item1 && toolbar_item2)))
+		different = 1;
+	return different;
+}
+
+static int compare_toolbar(toolbar_t *toolbar1, toolbar_t *toolbar2) {
+	int different = 0;
+	if(!different &&
+	   ((toolbar1->memopt != toolbar2->memopt) ||
+	   (toolbar1->lvc.version != toolbar2->lvc.version) ||
+	   (toolbar1->lvc.characts != toolbar2->lvc.characts)))
+		different = 1;
+	if(!different)
+		different = compare_toolbar_item(toolbar1->items, toolbar2->items);
+	return different;
+}
+
+static int compare_ani_curico(ani_curico_t *ani_curico1, ani_curico_t *ani_curico2) {
+	int different = 0;
+	if(!different &&
+	   ((ani_curico1->memopt != ani_curico2->memopt) ||
+	   (ani_curico1->data->lvc.version != ani_curico2->data->lvc.version) ||
+	   (ani_curico1->data->lvc.characts != ani_curico2->data->lvc.characts)))
+		different = 1;
+	return different;
+}
+
+void verify_translations(resource_t *top) {
+	DEFINE_VARIABLES_TRANSLATION
+	resource_t *next = top;
+	while(next) {
+		switch(next->type) {
+			case res_acc:
+				add_accelerator(next, next->res.acc);
+				break;
+			case res_bmp:
+				add_bitmap(next, next->res.bmp);
+				break;
+			case res_cur:
+				add_cursor(next, next->res.cur);
+				break;
+			case res_curg:
+				add_cursor_group(next, next->res.curg);
+				break;
+			case res_dlg:
+				add_dialog(next, next->res.dlg);
+				break;
+			case res_dlgex:
+				add_dialogex(next, next->res.dlgex);
+				break;
+			case res_fnt:
+				add_font(next, next->res.fnt);
+				break;
+			case res_ico:
+				add_icon(next, next->res.ico);
+				break;
+			case res_icog:
+				add_icon_group(next, next->res.icog);
+				break;
+			case res_men:
+				add_menu(next, next->res.men);
+				break;
+			case res_menex:
+				add_menuex(next, next->res.menex);
+				break;
+			case res_rdt:
+				add_rcdata(next, next->res.rdt);
+				break;
+			case res_stt:
+				add_stringtable(next, next->res.stt);
+				break;
+			case res_usr:
+				add_user(next, next->res.usr);
+				break;
+			case res_msg:
+				add_messagetable(next, next->res.msg);
+				break;
+			case res_ver:
+				add_versioninfo(next, next->res.ver);
+				break;
+			case res_dlginit:
+				add_dlginit(next, next->res.dlgi);
+				break;
+			case res_toolbar:
+				add_toolbar(next, next->res.tbt);
+				break;
+			case res_anicur:
+			case res_aniico:
+				add_ani_curico(next, next->res.ani);
+				break;
+			default:
+				fprintf(stderr, "Report this: unkown resource type parsed %08x\n", next->type);
+		}
+		next = next->next;
+	}
+	CHECK_TRANSLATION(accelerator)
+	CHECK_TRANSLATION_RAW(bitmap)
+	CHECK_TRANSLATION(cursor)
+	CHECK_TRANSLATION(cursor_group)
+	CHECK_TRANSLATION(dialog)
+	CHECK_TRANSLATION(dialogex)
+	CHECK_TRANSLATION_RAW(font)
+	CHECK_TRANSLATION(icon)
+	CHECK_TRANSLATION(icon_group)
+	CHECK_TRANSLATION(menu)
+	CHECK_TRANSLATION(menuex)
+	CHECK_TRANSLATION_RAW(rcdata)
+	CHECK_TRANSLATION(stringtable)
+	CHECK_TRANSLATION_RAW(user)
+	CHECK_TRANSLATION_RAW(messagetable)
+	CHECK_TRANSLATION(versioninfo)
+	CHECK_TRANSLATION_RAW(dlginit)
+	CHECK_TRANSLATION(toolbar)
+	CHECK_TRANSLATION_RAW(ani_curico)
+}
--- /dev/null	2002-08-30 19:31:37.000000000 -0400
+++ tools/wrc/translation.h	2003-10-04 22:25:02.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ * Verification of resources translations prototypes
+ *
+ * Copyright 2003 Vincent Béron
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WRC_TRANSLATION_H
+#define __WRC_TRANSLATION_H
+
+#include <string.h>
+
+#include "dumpres.h"
+
+#define KEEP_RESOURCE_COMMON(type, lang_id) \
+	int nb_list_##type = 0; \
+	int nb_master_##type = 0; \
+	int nb_neutral_##type = 0; \
+	resource_t **list_resource_##type = NULL; \
+	resource_t **master_resource_##type = NULL; \
+	resource_t **neutral_resource_##type = NULL; \
+	type##_t **list_##type = NULL; \
+	type##_t **master_##type = NULL; \
+	type##_t **neutral_##type = NULL; \
+	static void add_##type(resource_t *resource, type##_t *type) { \
+		if(type lang_id->lvc.language->id == master_language) { \
+			ADD_RESOURCE(type, master) \
+		} else if(type lang_id->lvc.language->id == LANG_NEUTRAL) { \
+			ADD_RESOURCE(type, neutral) \
+		} else { \
+			ADD_RESOURCE(type, list) \
+		} \
+	}
+
+#define ADD_RESOURCE(type, list) { \
+	nb_##list##_##type++; \
+	list##_##type = realloc(list##_##type, nb_##list##_##type*sizeof(type##_t *)); \
+	list##_##type[nb_##list##_##type-1] = type; \
+	list##_resource_##type = realloc(list##_resource_##type, nb_##list##_##type*sizeof(resource_t *)); \
+	list##_resource_##type[nb_##list##_##type-1] = resource; \
+	}
+
+#define KEEP_RESOURCE(type) \
+	KEEP_RESOURCE_COMMON(type, )
+
+#define KEEP_RESOURCE_RAW(type) \
+	KEEP_RESOURCE_COMMON(type, ->data)
+
+#define DEFINE_VARIABLES_TRANSLATION \
+	int i, j; \
+	char *nameid;
+
+#define ENSURE_MASTER_PRESENT(type) \
+	if(nb_list_##type > 0) { \
+		if(nb_master_##type && nb_neutral_##type) { \
+			fprintf(stderr, "There are both a NEUTRAL and a MASTER versions for %s, along with additional localized versions.\n", #type); \
+		} else if(nb_neutral_##type) { \
+			fprintf(stderr, "There are no MASTER version, but there are some NEUTRAL versions for %s, so will use those instead of MASTER.\n", #type); \
+			master_resource_##type = neutral_resource_##type; \
+			master_##type = neutral_##type; \
+			nb_master_##type = nb_neutral_##type; \
+		} else if(!nb_master_##type) { \
+			fprintf(stderr, "There are no NEUTRAL nor MASTER version for %s, but there are some other localized versions.\n", #type); \
+		} \
+	} else { \
+		if(nb_master_##type && nb_neutral_##type) { \
+			fprintf(stderr, "There are both a NEUTRAL and a MASTER versions for %s, but no other localized version.\n", #type); \
+		} else if(nb_master_##type) { \
+			fprintf(stderr, "There are only MASTER versions for %s.\n", #type); \
+		} else if(nb_neutral_##type) { \
+			fprintf(stderr, "There are only NEUTRAL versions for %s.\n", #type); \
+		} \
+	}
+/*Ne pas juste flusher des ressources, les ajouter à une des listes*/
+
+#define CHECK_DIFFERENCES(type, lang_id) \
+	for(i = 0; i < nb_list_##type; i++) { \
+		for(j = 0; j < nb_master_##type; j++) { \
+			nameid = strdup(get_nameid_str(list_resource_##type[i]->name)); \
+			if(!strcmp(nameid, get_nameid_str(master_resource_##type[j]->name))) { \
+				if(compare_##type(list_##type[i], master_##type[j])) { \
+					fprintf(stderr, "Differences in type %s, ID %s, for language %x\n", #type, nameid, list_##type[i]lang_id->lvc.language->id); \
+				} \
+			} \
+			free(nameid); \
+		} \
+	}
+
+#define CHECK_TRANSLATION(type) \
+	ENSURE_MASTER_PRESENT(type) \
+	CHECK_DIFFERENCES(type, )
+
+#define CHECK_TRANSLATION_RAW(type) \
+	ENSURE_MASTER_PRESENT(type) \
+	CHECK_DIFFERENCES(type, ->data)
+/*Langues manquantes*/
+
+/*Afficher le nom des langues plutôt que le numéro*/
+
+void verify_translations(resource_t *top);
+
+#endif
