--- gtk/compose-parse.py.ORIGINAL	2009-01-12 01:36:41.000000000 +0000
+++ gtk/compose-parse.py	2009-01-12 01:51:46.000000000 +0000
@@ -12,7 +12,7 @@
 
 from re			import findall, match, split, sub
 from string		import atoi
-from unicodedata	import normalize
+from unicodedata	import normalize, decimal
 from urllib 		import urlretrieve
 from os.path		import isfile, getsize
 from copy 		import copy
@@ -22,14 +22,15 @@
 
 # We grab files off the web, left and right.
 URL_COMPOSE = 'http://gitweb.freedesktop.org/?p=xorg/lib/libX11.git;a=blob_plain;f=nls/en_US.UTF-8/Compose.pre'
-URL_KEYSYMSTXT = "http://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt"
-URL_GDKKEYSYMSH = "http://svn.gnome.org/svn/gtk%2B/trunk/gdk/gdkkeysyms.h"
+URL_KEYSYMSTXT = 'http://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt'
+URL_GDKKEYSYMSH = 'http://svn.gnome.org/svn/gtk%2B/trunk/gdk/gdkkeysyms.h'
 URL_UNICODEDATATXT = 'http://www.unicode.org/Public/5.0.0/ucd/UnicodeData.txt'
-FILENAME_COMPOSE_SUPPLEMENTARY = 'gtk-compose-lookaside.txt'
+URL_GTKOLDSEQUENCES = 'http://simos.info/pub/GTKOLDSEQUENCES.txt'
+FILENAME_COMPOSE_LOOKASIDE = 'gtk-compose-lookaside.txt'
 
 # We currently support keysyms of size 2; once upstream xorg gets sorted, 
 # we might produce some tables with size 2 and some with size 4.
-SIZEOFINT = 2
+SIZEOFINT = 4
 
 # Current max compose sequence length; in case it gets increased.
 WIDTHOFCOMPOSETABLE = 5
@@ -37,6 +38,10 @@
 keysymdatabase = {}
 keysymunicodedatabase = {}
 unicodedatabase = {}
+gtkoldsequences = {}
+multisequences = {}
+multisequence_maxseqlen = 0
+multisequence_maxvallen = 0
 
 headerfile_start = """/* GTK - The GIMP Tool Kit
  * Copyright (C) 2007, 2008 GNOME Foundation
@@ -106,13 +111,51 @@
  * that depend on the locale or selected input method.
  */
 
-static const guint16 gtk_compose_seqs_compact[] = {"""
+static const guint32 gtk_compose_seqs_compact[] = {"""
 
 headerfile_end = """};
 
 #endif /* __GTK_IM_CONTEXT_SIMPLE_SEQS_H__ */
 """
 
+multipleseqs_file_start = """/* GTK - The GIMP Tool Kit
+ * Copyright (C) 2007, 2008 GNOME Foundation
+ *
+ * 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 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.
+ */
+
+/* This file is gtkimcontextsimplemultiseqs.h.
+ * This table is for compose sequences that produce two or more characters.
+ * These sequences where extracted from the upstream Compose file from X.Org.
+ * This file was generated with http://svn.gnome.org/svn/gtk+/trunk/gtk/compose-parse.py
+ *
+ * The table is composed of two parts, $compose_max_sequence_len columns for
+ * the sequence, and $compose_max_codepoint_len columns for the printed character.
+ * We pad with 0 for any missing keys or characters.
+ * The number of sequences is $compose_multi_index_size.
+ */
+"""
+
+multipleseqs_file_middle = """
+static const guint32 gtk_compose_seqs_multi[] = {"""
+
+multipleseqs_file_end = """};
+"""
+
+
 def stringtohex(str): return atoi(str, 16)
 
 def factorial(n): 
@@ -147,67 +190,92 @@
 
 def usage():
 	print """compose-parse available parameters:
-	-h, --help		this craft
-	-s, --statistics	show overall statistics (both algorithmic, non-algorithmic)
 	-a, --algorithmic	show sequences saved with algorithmic optimisation
+	-e, --gtk-expanded	when used with --gtk, create file that repeats first column; not usable in GTK+
 	-g, --gtk		show entries that go to GTK+
-	-u, --unicodedatatxt	show compose sequences derived from UnicodeData.txt (from unicode.org)
-	-v, --verbose		show verbose output
-        -p, --plane1		show plane1 compose sequences
+	-h, --help		this craft
+        -m, --multiple		shows compose sequences that result to >1 unicode characters
 	-n, --numeric		when used with --gtk, create file with numeric values only
-	-e, --gtk-expanded	when used with --gtk, create file that repeats first column; not usable in GTK+
+        -p, --plane1		show plane1 compose sequences
+	-q, --quiet   	 	do not show verbose output (default is verbose)
+        -r, --regression	shows compose sequences that used to exist in pre-update, but are not found in Xorg's Compose.
+	-s, --statistics	show overall statistics (both algorithmic, non-algorithmic)
+	-u, --unicodedatatxt	show compose sequences derived from UnicodeData.txt (from unicode.org)
+	-w, --warnings		show some non-fatal warnings (useful for maintainer)
 
 	Default is to show statistics.
 	"""
 
 try: 
-	opts, args = getopt.getopt(sys.argv[1:], "pvgashune", ["help", "algorithmic", "statistics", "unicodedatatxt", 
-		"stats", "gtk", "verbose", "plane1", "numeric", "gtk-expanded"])
+	opts, args = getopt.getopt(sys.argv[1:], "aeghmnpqrsuw", 
+		[ "algorithmic", "gtk-expanded", "gtk", "help", "multiple",
+		  "numeric", "plane1", "quiet", "regression", 
+		  "stats", "statistics", "unicodedatatxt", "warnings"])
 except: 
 	usage()
 	sys.exit(2)
 
-opt_statistics = False
 opt_algorithmic = False
+opt_gtkexpanded = False
 opt_gtk = False
-opt_unicodedatatxt = False
-opt_verbose = False
-opt_plane1 = False
+opt_multiple = False
 opt_numeric = False
-opt_gtkexpanded = False
+opt_plane1 = False
+opt_quiet = False
+opt_regression = False
+opt_statistics = False
+opt_unicodedatatxt = False
+opt_warnings = False
+
+no_options = True
 
 for o, a in opts:
+	if o in ("-a", "--algorithmic"):
+		opt_algorithmic = True
+		no_options = False
+	if o in ("-e", "--gtk-expanded"):
+		opt_gtkexpanded = True
+		no_options = False
+	if o in ("-g", "--gtk"):
+		opt_gtk = True
+		no_options = False
 	if o in ("-h", "--help"):
 		usage()
 		sys.exit()
+	if o in ("-m", "--multiple"):
+		opt_multiple = True
+		no_options = False
+	if o in ("-n", "--numeric"):
+		opt_numeric = True
+		no_options = False
+	if o in ("-p", "--plane1"):
+		opt_plane1 = True
+		no_options = False
+	if o in ("-q", "--quiet"):
+		opt_quiet = True
+		no_options = False
+	if o in ("-r", "--regression"):
+		opt_regression = True
+		no_options = False
 	if o in ("-s", "--statistics"):
 		opt_statistics = True
-	if o in ("-a", "--algorithmic"):
-		opt_algorithmic = True
-	if o in ("-g", "--gtk"):
-		opt_gtk = True	
 	if o in ("-u", "--unicodedatatxt"):
 		opt_unicodedatatxt = True
-	if o in ("-v", "--verbose"):
-		opt_verbose = True
-	if o in ("-p", "--plane1"):
-		opt_plane1 = True
-	if o in ("-n", "--numeric"):
-		opt_numeric = True
-	if o in ("-e", "--gtk-expanded"):
-		opt_gtkexpanded = True
+		no_options = False
+	if o in ("-w", "--warnings"):
+		opt_warnings = True
 
-if not opt_algorithmic and not opt_gtk and not opt_unicodedatatxt:
+if no_options:
 	opt_statistics = True
 
 def download_hook(blocks_transferred, block_size, file_size):
 	""" A download hook to provide some feedback when downloading """
 	if blocks_transferred == 0:
 		if file_size > 0:
-			if opt_verbose:
+			if not opt_quiet:
 				print "Downloading", file_size, "bytes: ",
 		else:	
-			if opt_verbose:
+			if not opt_quiet:
 				print "Downloading: ",
 	sys.stdout.write('#')
 	sys.stdout.flush()
@@ -218,7 +286,7 @@
 	""" Borks on failure """
 	localfilename = url.split('/')[-1]
         if not isfile(localfilename) or getsize(localfilename) <= 0:
-		if opt_verbose:
+		if not opt_quiet:
 			print "Downloading ", url, "..."
 		try: 
 			urlretrieve(url, localfilename, download_hook)
@@ -230,7 +298,7 @@
 			sys.exit(-1)
 		print " done."
         else:
-		if opt_verbose:
+		if not opt_quiet:
                 	print "Using cached file for ", url
 	return localfilename
 
@@ -281,16 +349,35 @@
 	""" Patch up the keysymdb with some of our own stuff """
 
 	""" This is for a missing keysym from the currently upstream file """
-	keysymdb['dead_stroke'] = 0x338
+	#keysymdb['dead_stroke'] = 0x338
 
 	""" This is for a missing keysym from the currently upstream file """
-	###keysymdb['dead_belowring'] = 0x323
-	###keysymdb['dead_belowmacron'] = 0x331
-	###keysymdb['dead_belowcircumflex'] = 0x32d
-	###keysymdb['dead_belowtilde'] = 0x330
-	###keysymdb['dead_belowbreve'] = 0x32e
-	###keysymdb['dead_belowdiaeresis'] = 0x324
-
+	keysymdb['dead_belowdiaeresis'] = 0x324
+	keysymdb['dead_belowring'] 	= 0x325
+	keysymdb['dead_belowcomma'] 	= 0x326
+	keysymdb['dead_belowcircumflex']= 0x32d
+	keysymdb['dead_belowbreve'] 	= 0x32e
+	keysymdb['dead_belowtilde'] 	= 0x330
+	keysymdb['dead_belowmacron'] 	= 0x331
+	"""
+	keysymdb['KP_Multiply']   	= 0x02a
+	keysymdb['KP_Add']        	= 0x02b
+	keysymdb['KP_Separator']  	= 0x02c
+	keysymdb['KP_Subtract']   	= 0x02d
+	keysymdb['KP_Decimal']    	= 0x02e
+	keysymdb['KP_Divide']     	= 0x02f
+	keysymdb['KP_0']          	= 0x030
+	keysymdb['KP_1']          	= 0x031
+	keysymdb['KP_2']          	= 0x032
+	keysymdb['KP_3']          	= 0x033
+	keysymdb['KP_4']          	= 0x034
+	keysymdb['KP_5']          	= 0x035
+	keysymdb['KP_6']          	= 0x036
+	keysymdb['KP_7']          	= 0x037
+	keysymdb['KP_8']          	= 0x038
+	keysymdb['KP_9']          	= 0x039
+	keysymdb['KP_Equal']      	= 0x03d
+	"""
 	""" This is^Wwas preferential treatment for Greek """
 	# keysymdb['dead_tilde'] = 0x342  		
 	""" This is^was preferential treatment for Greek """
@@ -337,21 +424,51 @@
 
 	""" Patch up the keysymdb with some of our own stuff """
 	""" This is for a missing keysym from the currently upstream file """
-	###keysymdb['dead_belowring'] = 0x323
-	###keysymdb['dead_belowmacron'] = 0x331
-	###keysymdb['dead_belowcircumflex'] = 0x32d
-	###keysymdb['dead_belowtilde'] = 0x330
-	###keysymdb['dead_belowbreve'] = 0x32e
-	###keysymdb['dead_belowdiaeresis'] = 0x324
-
+	keysymdb['dead_belowdiaeresis'] = 0x324
+	keysymdb['dead_belowring'] 	= 0x325
+	keysymdb['dead_belowcomma'] 	= 0x326
+	keysymdb['dead_belowcircumflex']= 0x32d
+	keysymdb['dead_belowbreve'] 	= 0x32e
+	keysymdb['dead_belowtilde'] 	= 0x330
+	keysymdb['dead_belowmacron'] 	= 0x331
+	"""
+	keysymdb['KP_Multiply']   	= 0x02a
+	keysymdb['KP_Add']        	= 0x02b
+	keysymdb['KP_Separator']  	= 0x02c
+	keysymdb['KP_Subtract']   	= 0x02d
+	keysymdb['KP_Decimal']    	= 0x02e
+	keysymdb['KP_Divide']     	= 0x02f
+	keysymdb['KP_0']          	= 0x030
+	keysymdb['KP_1']          	= 0x031
+	keysymdb['KP_2']          	= 0x032
+	keysymdb['KP_3']          	= 0x033
+	keysymdb['KP_4']          	= 0x034
+	keysymdb['KP_5']          	= 0x035
+	keysymdb['KP_6']          	= 0x036
+	keysymdb['KP_7']          	= 0x037
+	keysymdb['KP_8']          	= 0x038
+	keysymdb['KP_9']          	= 0x039
+	keysymdb['KP_Equal']      	= 0x03d
+	"""
 	""" This is preferential treatment for Greek """
 	""" => we get more savings if used for Greek """
 	# keysymdb['dead_tilde'] = 0x342  		
 	""" This is preferential treatment for Greek """
 	# keysymdb['combining_tilde'] = 0x342	
 
+	keysymdb['zerosubscript'] 	= 0x2080
+	keysymdb['onesubscript'] 	= 0x2081
+	keysymdb['twosubscript'] 	= 0x2082
+	keysymdb['threesubscript'] 	= 0x2083
+	keysymdb['foursubscript'] 	= 0x2084
+	keysymdb['fivesubscript'] 	= 0x2085
+	keysymdb['sixsubscript'] 	= 0x2086
+	keysymdb['sevensubscript'] 	= 0x2087
+	keysymdb['eightsubscript'] 	= 0x2088
+	keysymdb['ninesubscript'] 	= 0x2089
+
 	""" This is for a missing keysym from Markus Kuhn's db """
-	keysymdb['dead_stroke'] = 0x338
+	keysymdb['dead_stroke'] = 0xFE63
 	""" This is for a missing keysym from Markus Kuhn's db """
 	keysymdb['Oslash'] = 0x0d8		
 
@@ -363,8 +480,43 @@
 	""" Allows to import Multi_key sequences """
 	keysymdb['Multi_key'] = 0xff20
 
+	""" New keysym (no corresponding Unicode character) """
+	#keysymdb['dead_currency'] = 0xfe6f
+
 	return keysymdb
 
+def process_gtkoldsequences():
+	""" Grabs and opens the keysyms.txt file that Markus Kuhn maintains """
+	""" This file keeps a record between keysyms <-> unicode chars """
+	filename_gtkoldsequences = download_file(URL_GTKOLDSEQUENCES)
+	try: 
+		gtkoldsequencestxt = open(filename_gtkoldsequences, 'r')
+	except IOError, (errno, strerror):
+		print "I/O error(%s): %s" % (errno, strerror)
+		sys.exit(-1)
+	except:
+		print "Unexpected error: ", sys.exc_info()[0]
+		sys.exit(-1)
+
+	""" Parse the gtkoldsequences.txt file and place content in gtkoldsequences """
+	linenum = 0
+	for line in gtkoldsequencestxt.readlines():
+		line = line.strip()
+		components = split('\s+', line)
+		if len(components) < 6:
+			print "Invalid line in %(filename)s: %(line)s'"\
+			% {'line': line, 'filename': filename_keysymstxt }
+			print "Was expecting 6 items in the line"
+			sys.exit(-1)
+		components[5] = atoi(components[5], 16)
+		sequence = components[0:6]
+		sequence.append(False)
+		if not gtkoldsequences.has_key(components[5]):
+			gtkoldsequences[components[5]] = []
+		gtkoldsequences[components[5]].append(sequence)
+	gtkoldsequencestxt.close()
+	return gtkoldsequences
+
 def keysymvalue(keysym, file = "n/a", linenum = 0):
 	""" Extracts a value from the keysym """
 	""" Find the value of keysym, using the data from keysyms """
@@ -378,9 +530,8 @@
        	elif keysym[:2] == '0x' and match('[0-9a-fA-F]+$', keysym[2:]):
 		return atoi(keysym[2:], 16)
 	else:
-        	#print 'UNKNOWN{%(keysym)s}' % { "keysym": keysym }
-               	return -1
-		#sys.exit(-1)
+        	print 'keysymvalue: UNKNOWN{%(keysym)s}' % { "keysym": keysym }
+               	sys.exit(-1)
 
 def keysymunicodevalue(keysym, file = "n/a", linenum = 0):
 	""" Extracts a value from the keysym """
@@ -395,7 +546,7 @@
        	elif keysym[:2] == '0x' and match('[0-9a-fA-F]+$', keysym[2:]):
 		return atoi(keysym[2:], 16)
 	else:
-        	print 'UNKNOWN{%(keysym)s}' % { "keysym": keysym }
+        	print 'keysymunicodevalue: UNKNOWN{%(keysym)s}' % { "keysym": keysym }
                	sys.exit(-1)
 
 def rename_combining(seq):
@@ -407,9 +558,20 @@
 			filtered_sequence.append(ks)
 	return filtered_sequence
 
+def check_if_sequence_exists(allsequences, seq):
+	seq_len = len(seq)
+	for s in allsequences:
+		if seq_len == len(s):
+			for i in range(seq_len - 1):
+				if seq[i] != s[i]:
+					return False
+			if i == seq_len - 1:
+				return True
+	return False
 
 keysymunicodedatabase = process_keysymstxt()
 keysymdatabase = process_gdkkeysymsh()
+gtkoldsequences = process_gtkoldsequences()
 
 """ Grab and open the compose file from upstream """
 filename_compose = download_file(URL_COMPOSE)
@@ -422,24 +584,24 @@
 	print "Unexpected error: ", sys.exc_info()[0]
 	sys.exit(-1)
 
-""" Look if there is a lookaside (supplementary) compose file in the current
+""" Look if there is a lookaside compose file in the current
     directory, and if so, open, then merge with upstream Compose file.
 """
 try:
-        composefile_lookaside = open(FILENAME_COMPOSE_SUPPLEMENTARY, 'r')
+	composefile_lookaside = open(FILENAME_COMPOSE_LOOKASIDE, 'r')
 except IOError, (errno, strerror):
-        if not opt_quiet:
-                print "I/O error(%s): %s" % (errno, strerror)
-                print "Did not find lookaside compose file. Continuing..."
+	if not opt_quiet:
+		print "I/O error(%s): %s" % (errno, strerror)
+		print "Did not find the lookaside compose file %s. Continuing..." % (FILENAME_LOOKASIDE)
 except:
         print "Unexpected error: ", sys.exc_info()[0]
         sys.exit(-1)
 
 xorg_compose_sequences_raw = []
 for seq in composefile.readlines():
-        xorg_compose_sequences_raw.append(seq)
+	xorg_compose_sequences_raw.append(seq)
 for seq in composefile_lookaside.readlines():
-        xorg_compose_sequences_raw.append(seq)
+	xorg_compose_sequences_raw.append(seq)
 
 """ Parse the compose file in  xorg_compose_sequences"""
 xorg_compose_sequences = []
@@ -451,7 +613,6 @@
 	if line is "" or match("^XCOMM", line) or match("^#", line):
 		continue
 
-	#line = line[:-1]
 	components = split(':', line)
 	if len(components) != 2:
 		print "Invalid line %(linenum_compose)d in %(filename)s: No sequence\
@@ -464,57 +625,75 @@
 	values = split('\s+', val)
 	unichar_temp = split('"', values[0])
 	unichar = unichar_temp[1]
-	if len(values) == 1:
-		continue
-	codepointstr = values[1]
-	if values[1] == '#':
-		# No codepoints that are >1 characters yet.
-		continue
+	if len(unichar.decode('utf-8')) > 1:
+		if unichar[0] != '\\': 	# Ignore escaped characters.
+			# No codepoints that are >1 characters yet.
+			# plane1 multiple
+			multiseq = []
+			# print 'Multiple:', 
+			for item in raw_sequence:
+				# print item,
+				multiseq.append(item)
+			if multisequence_maxseqlen < len(raw_sequence):
+				multisequence_maxseqlen = len(raw_sequence)
+			# print len(unichar.decode('utf-8')), 
+			multicodepoint = []
+			for item in unichar.decode('utf-8'):
+				# print "U%04X " % ord(item),
+				multicodepoint.append("U%04X" % ord(item))
+			if multisequence_maxvallen < len(unichar.decode('utf-8')):
+				multisequence_maxvallen = len(unichar.decode('utf-8'))
+			# print
+			multisequences[unichar.decode('utf-8')] = [multiseq, multicodepoint]
+			continue
+	#if len(values) == 1:
+		# print "SKIPPING PLANE1:", len(unichar.decode('utf-8')), tuple(values[0])
+	#	continue
+	#print values, tuple(unichar)
+	try:
+		codepointstr = values[1]
+	except IndexError:
+		codepointstr = 'U' + str(ord(unichar.decode('utf-8')[0]))
 	if raw_sequence[0][0] == 'U' and match('[0-9a-fA-F]+$', raw_sequence[0][1:]):
 		raw_sequence[0] = '0x' + raw_sequence[0][1:]
 	if codepointstr[0] == 'U' and match('[0-9a-fA-F]+$', codepointstr[1:]):
 		codepoint = atoi(codepointstr[1:], 16)
 	elif keysymunicodedatabase.has_key(codepointstr):
-		if keysymdatabase[codepointstr] != keysymunicodedatabase[codepointstr]:
-			print "DIFFERENCE: 0x%(a)X 0x%(b)X" % { "a": keysymdatabase[codepointstr], "b": keysymunicodedatabase[codepointstr]},
-			print raw_sequence, codepointstr
-		codepoint = keysymunicodedatabase[codepointstr]
+		try: 
+			if keysymdatabase[codepointstr] != keysymunicodedatabase[codepointstr]:
+				if opt_warnings:
+					print "DIFFERENCE (nonfatal): 0x%(a)X 0x%(b)X" % { "a": keysymdatabase[codepointstr], 
+									"b": keysymunicodedatabase[codepointstr]},
+					print raw_sequence, codepointstr
+			else:
+				codepoint = keysymunicodedatabase[codepointstr]
+		except KeyError:
+			if opt_warnings:
+				print "KEYERROR (nonfatal): ", codepointstr
+			codepoint = keysymunicodedatabase[codepointstr]
 	else:
 		print
-		print "Invalid codepoint at line %(linenum_compose)d in %(filename)s:\
-		 %(line)s" % { "linenum_compose": linenum_compose, "filename": filename_compose, "line": line }
+		print "Invalid codepoint %(cp)s at line %(linenum_compose)d in %(filename)s:\
+		 %(line)s" % { "cp": codepointstr, "linenum_compose": linenum_compose, "filename": filename_compose, "line": line }
 		exit(-1)
 	sequence = rename_combining(raw_sequence)
+	if "dead_currency" in sequence:
+		continue
 	reject_this = False
 	for i in sequence:
 		if keysymvalue(i) > 0xFFFF:
 			reject_this = True
 			if opt_plane1:
-				print sequence
-			break
-		if keysymvalue(i) < 0:
-			reject_this = True
+				print 'Plane1:', sequence
 			break
 	if reject_this:
 		continue
-	if "U0342" in sequence or \
-		"U0313" in sequence or \
-		"U0314" in sequence or \
-		"0x0313" in sequence or \
-		"0x0342" in sequence or \
-		"0x0314" in sequence:
-		continue
-	if "dead_belowring" in sequence or\
-		"dead_belowcomma" in sequence or\
-		"dead_belowmacron" in sequence or\
-		"dead_belowtilde" in sequence or\
-		"dead_belowbreve" in sequence or\
-		"dead_belowdiaeresis" in sequence or\
-		"dead_belowcircumflex" in sequence:
+	for i in range(len(sequence)):
+		if sequence[i] == "0x0342":
+			sequence[i] = "dead_tilde"
+	if "U0313" in sequence or "U0314" in sequence or "0x0313" in sequence or "0x0314" in sequence:
 		continue
-	#for i in range(len(sequence)):
-	#	if sequence[i] == "0x0342":
-	#		sequence[i] = "dead_tilde"
+	""" This is temporary filtering, because we need to get an updated Compose file with less sequences """
 	if "Multi_key" not in sequence:
 		""" Ignore for now >0xFFFF keysyms """
 		if codepoint < 0xFFFF:
@@ -529,24 +708,7 @@
 				not_normalised = True
 				skipping_this = False
 				for i in range(0, len(sequence)):
-					""" If the sequence has dead_tilde and is for Greek, we don't do algorithmically 
-					    because of lack of dead_perispomeni (i.e. conflict)
-					"""
 					bc = basechar
-					"""if sequence[-1] == "dead_tilde" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
-						skipping_this = True
-						break
-					if sequence[-1] == "dead_horn" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
-						skipping_this = True
-						break
-					if sequence[-1] == "dead_ogonek" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
-						skipping_this = True
-						break
-					if sequence[-1] == "dead_psili":
-						sequence[i] = "dead_horn"
-					if sequence[-1] == "dead_dasia":
-						sequence[-1] = "dead_ogonek"
-					"""
 					unisequence.append(unichr(keysymunicodevalue(sequence.pop(), filename_compose, linenum_compose)))
 					
 				if skipping_this:
@@ -567,6 +729,9 @@
 					counter += 1
 				if not_normalised:
 					original_sequence.append(codepoint)
+					if check_if_sequence_exists(xorg_compose_sequences, original_sequence):
+						if not opt_quiet:
+							print "Got duplicate sequence:", original_sequence
 					xorg_compose_sequences.append(original_sequence)
 					""" print xorg_compose_sequences[-1] """
 					
@@ -578,6 +743,9 @@
 			exit(-1)
 	else:
 		sequence.append(codepoint)
+		if check_if_sequence_exists(xorg_compose_sequences, sequence):
+			if not opt_quiet:
+				print "Got duplicate sequence:", sequence
 		xorg_compose_sequences.append(sequence)
 		""" print xorg_compose_sequences[-1] """
 
@@ -703,14 +871,13 @@
 	if ch >= 0x370 and ch <= 0x3ff or ch >= 0x1f00 and ch <= 0x1fff:
 		num_algorithmic_greek += 1
 		
-
 if opt_algorithmic:
 	for sequence in xorg_compose_sequences_algorithmic_uniqued:
 		letter = "".join(sequence[-1:])
 		print '0x%(cp)04X, %(uni)c, seq: [ <0x%(base)04X>,' % { 'cp': ord(unicode(letter)), 'uni': letter, 'base': sequence[-2] },
 		for elem in sequence[:-2]:
 			print "<0x%(keysym)04X>," % { 'keysym': elem },
-		""" Yeah, verified... We just want to keep the output similar to -u, so we can compare/sort easily """
+		# Yeah, verified... We just want to keep the output similar to -u, so we can compare/sort easily 
 		print "], recomposed as", letter, "verified"
 
 def num_of_keysyms(seq):
@@ -799,7 +966,7 @@
 	numdecomposition = map(stringtohex, decomposition)
 	return map(redecompose, numdecomposition)
 
-def process_unicodedata_file(verbose = False):
+def process_unicodedata_file(quiet = False):
 	""" Grab from wget http://www.unicode.org/Public/UNIDATA/UnicodeData.txt """
 	filename_unicodedatatxt = download_file(URL_UNICODEDATATXT)
 	try: 
@@ -864,7 +1031,7 @@
 				if ch >= 0x370 and ch <= 0x3ff or ch >= 0x1f00 and ch <= 0x1fff:
 					counter_entries_greek += 1
 					counter_combinations_greek += factorial(len(decomposedsequence)-1)
-				if verbose:
+				if not quiet and 0:
 					print "0x%(cp)04X, %(uni)c, seq:" % { 'cp':item, 'uni':unichr(item) },
 					print "[",
 					for elem in decomposedsequence:
@@ -873,7 +1040,7 @@
 					if unichr(item) == recomposedchar:
 						print "verified"
 	
-	if verbose == False:
+	if not quiet:
 		print "Unicode statistics from UnicodeData.txt"
 		print "Number of entries that can be algorithmically produced     :", counter_entries
 		print "  of which are for Greek                                   :", counter_entries_greek
@@ -886,6 +1053,95 @@
 if opt_unicodedatatxt:
 	process_unicodedata_file(True)
 
+def is_composed(seq):
+	unisequence = []
+	not_normalised = True
+	for i in range(len(seq[:-1])):
+		if seq[i+1] == 'EMPTY' or i == 4:
+			break
+		# print ' adding(%(a)s)%(b)s' % { 'a': i, 'b': unichr(keysymunicodevalue(seq[i])) }
+		unisequence.append(unichr(keysymunicodevalue(seq[i], filename_compose)))
+	basechar = seq[i]
+	# print ' basechar:', basechar, unichr(keysymunicodevalue(basechar))
+		
+	if i != 0:
+		for perm in all_permutations(unisequence):
+			# normalized = normalize('NFC', unichr(keysymunicodevalue(basechar)) + "".join(perm))
+			normalized = normalize('NFC', "".join(perm))
+			if len(normalized) == 1:
+				# print " NORMALISED"
+				return True
+			else:
+				pass
+				# print " NOT normalised", normalized
+	return False
+
+if opt_regression:
+	for seq in xorg_compose_sequences: # foreach xorg_compose_sequence [dead_acute, a, 291]
+		if gtkoldsequences.has_key(seq[-1]): # if 219:
+			seqexpanded = []
+			for i in range(len(seq) - 1):
+				seqexpanded.append(seq[i])
+			for i in range(len(seq) - 1, 5):
+				seqexpanded.append('EMPTY')
+			seqexpanded.append(seq[-1])
+			## print "Got common codepoint 0x%(a)04X %(b)s" % { 'a': int(seq[-1]), 'b': seqexpanded }
+			for subseqi in range(len(gtkoldsequences[seq[-1]])):#[[dead_acute,a,0,0,0,291, False],[dead_acute,e,0,0,0,296,False]]
+				wematched = True
+				## print " ", "           comparing with", gtkoldsequences[seqexpanded[-1]][subseqi]
+				for i in range(len(seqexpanded) - 1):
+					## print "  ", i, seqexpanded[i], "with", gtkoldsequences[seq[-1]][subseqi][i]
+					if seqexpanded[i] != gtkoldsequences[seqexpanded[-1]][subseqi][i]:
+						if keysymvalue(seqexpanded[i]) != keysymvalue(gtkoldsequences[seqexpanded[-1]][subseqi][i]):
+							wematched = False
+							break
+			
+				if wematched:
+					gtkoldsequences[seq[-1]][subseqi][-1] = True
+					## print "MATCH                    ", gtkoldsequences[seq[-1]][subseqi]
+					break
+			## print
+	seq_counter = 0
+	for cp in gtkoldsequences.keys():
+		for seq in gtkoldsequences[cp]:
+			if seq[-1] == False:
+				if is_composed(seq[:-1]):
+					pass
+					# print "WAS_COMPOSED", seq
+				else:
+					for s in seq[:-2]:
+						if s == 'EMPTY':
+							print "0",
+						else:
+							print "<%(a)s>" % { 'a': s },
+					print "\t\t\t: \"%(a)c\" U%(b)04X" % { 'a': unichr(seq[-2]), 'b': seq[-2] }
+					seq_counter += 1
+					#print " ORPHAN", seq, "0x%04X" % seq[-2]
+	print "XCOMM We have", seq_counter, "sequences"
+
+def convert_unotation_to_hex(var):
+	return "0x%04X" % atoi(var[1:], 16)
+
+if opt_multiple:
+	print multipleseqs_file_start
+	print "static const gint compose_multi_max_sequence_len = %d;" % multisequence_maxseqlen
+	print "static const gint compose_multi_max_codepoint_len = %d;" % multisequence_maxvallen
+	# Index size can be deduced. Duh.
+	# print "static const gint compose_multi_index_size = %d;" % len(multisequences)
+	print multipleseqs_file_middle
+	for i in multisequences:
+		(seqs, vals) = multisequences[i]
+		for s in range(len(seqs)):
+			print '%6s,' % convert_unotation_to_hex(seqs[s]),
+		for s in range(len(seqs), multisequence_maxseqlen):
+			print '     0,',
+		for s in range(len(vals)):
+			print '%6s,' % convert_unotation_to_hex(vals[s]),
+		for s in range(len(vals), multisequence_maxvallen):
+			print '     0,',
+		print
+	print multipleseqs_file_end
+
 if opt_statistics:
 	print
 	print "Total number of compose sequences (from file)              :", len(xorg_compose_sequences) + len(xorg_compose_sequences_algorithmic)
@@ -902,16 +1158,16 @@
 	print "Not algorithmic (stats from Xorg Compose file)"
 	print "Number of sequences                                        :", len(xorg_compose_sequences) 
 	print "Flat array looks like                                      :", len(xorg_compose_sequences), "rows of 6 integers (2 bytes per int, or 12 bytes per row)"
-	print "Flat array would have taken up (in bytes)                  :", num_entries * 2 * 6, "bytes from the GTK+ library"
+	print "Flat array would have taken up (in bytes)                  :", num_entries * 4 * 6, "bytes from the GTK+ library"
 	print "Number of items in flat array                              :", len(xorg_compose_sequences) * 6
 	print "  of which are zeroes                                      :", zeroes, "or ", (100 * zeroes) / (len(xorg_compose_sequences) * 6), " per cent"
 	print "Number of different first items                            :", num_first_keysyms
-	print "Number of max bytes (if using flat array)                  :", num_entries * 2 * 6
-	print "Number of savings                                          :", zeroes * 2 - num_first_keysyms * 2 * 5
+	print "Number of max bytes (if using flat array)                  :", num_entries * 4 * 6
+	print "Number of savings                                          :", zeroes * 4 - num_first_keysyms * 4 * 5
 	print 
 	print "Memory needs if both algorithmic+optimised table in latest Xorg compose file"
-	print "                                                           :", num_entries * 2 * 6 - zeroes * 2 + num_first_keysyms * 2 * 5
+	print "                                                           :", num_entries * 4 * 6 - zeroes * 4 + num_first_keysyms * 4 * 5
 	print
-	print "Existing (old) implementation in GTK+"
+	print "Old implementation in GTK+"
 	print "Number of sequences in old gtkimcontextsimple.c            :", 691
-	print "The existing (old) implementation in GTK+ takes up         :", 691 * 2 * 12, "bytes"
+	print "The existing (old) implementation in GTK+ used to take up  :", 691 * 2 * 12, "bytes"
