//	FindinSite-CD-JS search code
//	Copyright (C) 2019 PHD Computer Consultants Ltd
//
//	Alter current version below
//		7.016	29-Apr-2019
//      7.016   29-Apr-2019 isUnicodeSeparator uses separatorRanges to match Findex
//      7.016   26-Apr-2019 toUnicodeLowerCaseNormalise renamed and enhanced to match Findex
//
//	The search database JS files can be loaded in two ways:
//	A:	Specify a list of files in a global array named findinsitedbs, eg specified in a JS file like this
//				<script src="search_dbs.js"></script>
//			whose contents looks like this:
//				var findinsitedbs = [
//					{ src:"db1.js", id:"varname"},
//				]
//			The script file paths have findinsite.config.baseurl prepended - this allows the script to be loaded correctly from different directories
//	B:	Use one or more script tags in the calling page like this:
//				<script async class="findinsitedb" src="db1.js" id="dbvarname" data-baseurl="" data-weight=""></script>
//			The script must be after this file is included - and async is optional but recommended
//			If you need to specify a path to prepend to the search results, give id and data-baseurl.
//
//	Usage:	var results = findinsite.search(params);
//													where params.search = 'search words'
//																params.showProgress = optional function to show progress
//																params.searchDone = required function to show results
//													and findinsite.databases[n].selected determines if a subset is searched
//					searchDone is called with results as follows:
//					{	error:			false or string
//						expression:	array of SearchWord-s { wordfound:true|false, given:string, w:array of synonyms etc }
//						hits:				array of [pageno,db,relevance] - subtact 1 from pageno to get index into db.pages
//						narrative:	null or array of strings
//
//	Currently requires jQuery to handle events triggered by database load(s)
//	Alternative approach is outlined here: http://blog.garstasio.com/you-dont-need-jquery/events/

////////////////////////////////////////////
// Missing:								stop words
//												wild cards
//												222 in wizard
//												??? here
// Deliberately missing:	different cases
// Suggestions:						suggested words
// Added:									cope if word not found

/*global window,jQuery */
/*global fisLogging,fisFreezeDb */
/*jshint bitwise: false*/
/*jslint continue: true, plusplus: true, todo: true, vars: true, white: true */

/** @namespace */
var findinsite = function ($) {
	"use strict";

	// PRIVATE variables made PUBLIC at end

	var version = "v7.016";
	var versionDate = new Date(2019, 4 - 1, 29);	// Month in range 0..11

	var databases = [];	// dbs actually loaded, ie not findinsitedbs

	var config = {
		rules: false,
		baseurl: '',
		dbcount: 0
	};

	// PRIVATE variables and functions - some made public at end

  var isUnicodeSeparator, isUnicodeCharLatin, toUnicodeLowerCaseNormalise, doSearch, stringHashCode;

	var deferSearch = false;

	// MODULE WORKING VARIABLES: assumes we are not called re-entrantly
	var thisdb;				// current search database
	var showProgress;	// callback to show progress
	var searchDone;		// report results

	// Public variables/constants
	var OP_AND = 0x00;	// Acts as if AND isn't there
	var OP_NONE = OP_AND;
	var OP_OR = 0x01;
	var OP_NOT = 0x10;
	var OP_CONTIG = 0x20;

	var lcAND = "and";
	var lcOR = "or";
	var lcNOT = "not";

	/////////////////////////////////////
	/**
	 * Show message in console if global fisLogging defined.
	 *
	* @param {string} msg - Message to show
	* @private
	*/
	function log(msg) {
		if (typeof fisLogging !== 'undefined') {
			if (fisLogging && window.console && window.console.log) {
				window.console.log(new Date().toISOString() + " " + msg);
			}
		}
	}

	/////////////////////////////////////
	function showLoadingProgress() {
		if (!showProgress) { return; }
		var loadedDbcount = databases.length;
		if (loadedDbcount == config.dbcount) {
			showProgress("Searching");
		} else {
			showProgress("Loaded " + loadedDbcount + " of " + config.dbcount + " search databases");
		}
	}

	/////////////////////////////////////

	function getGlobalName(ofind) {
		try {
			for (var o in window) {
				if (window[o] === ofind) {
					return o;
				}
			}
		} catch (e) { }
		return null;
	}

	/////////////////////////////////////
	// Startup: initiate loading of databases if necessary
	$(function () {
		if ((typeof findinsitedbs !== 'undefined') && $.isArray(findinsitedbs)) {
			// findinsitedbs defines which database JS files to load
			findinsite.config.dbcount = findinsitedbs.length;

			for (var dbno = 0; dbno < findinsitedbs.length; dbno++) {
				// http://stackoverflow.com/a/25897833/1541015
				var dbdef = findinsitedbs[dbno];
				var s = document.createElement('script');
				s.type = "text/javascript";
				s.async = true;
				dbdef.src = findinsite.config.baseurl + dbdef.src;
				s.src = dbdef.src;
				s.id = dbdef.id;
				var baseurl = '';
				var endbaseurl = dbdef.src.lastIndexOf("/");
				if (endbaseurl !== -1) {
					baseurl = dbdef.src.substr(0, endbaseurl + 1);
				}
				s.setAttribute("data-baseurl", baseurl);
				s.setAttribute("data-weight", dbno);
				var fs = document.getElementsByTagName('script')[0];
				fs.parentNode.insertBefore(s, fs);
			}

		} else {
			// database JS files loaded by calling page
			findinsite.config.dbcount = $('.findinsitedb').length;
			if (findinsite.config.dbcount == 0) {

				if (window.console && window.console.log) {
					window.console.log("findinsite: no search database JS files defined.");
				}
				findinsite.config.dbcount = 1;
			}
			// All dbs may already have loaded, so:
			processIfAllDbsLoaded();
		}
	}
	);

	/////////////////////////////////////
	// Handle database loaded event
	// If search pending: when all databases loaded, do search
	$(document).on("findinsiteDbLoaded", function (e) {
		var db = e.db;
		db.selected = true;
		var dbno = databases.push(db) - 1;

		db.baseurl = $('#' + db.varname).data('baseurl');
		if (typeof db.baseurl === 'undefined') { db.baseurl = ""; }

		db.weight = $('#' + db.varname).data('weight');

		//console.log("fiscdjs: " + new Date().toISOString() + " db loaded " + db.varname + " - " + db.description + " - " + db.baseurl);
		showLoadingProgress();
		processIfAllDbsLoaded();
	});

	/////////////////////////////////////
	// If all expected databases loaded, trigger event and do any deferred search
	function processIfAllDbsLoaded() {
		if (databases.length == config.dbcount) {
			databases.sort(function (dba, dbb) { return dba.weight - dbb.weight });
			$.event.trigger({ type: "findinsiteDbAllLoaded" });
			if (deferSearch) {
				var params = deferSearch;
				deferSearch = false;
				search(params);
			}
		}
	}

	/////////////////////////////////////
	/*function arrayUnique(array) {
	var a = array.concat();
	for (var i = 0; i < a.length; ++i) {
	for (var j = i + 1; j < a.length; ++j) {
	if (a[i] === a[j]) {
	a.splice(j--, 1);
	}
	}
	}
	return a;
	}*/

	/////////////////////////////////////
	// Remove duplicate pagenos from given array
	//	each element either	[pageno,wordposn1...]
	//		From:	[[4, 370], [15, 814, 1779], [29, 1528, 1531, 2272], [34, 447, 3119, 3201], [42, 908], [15, 1715, 1732], [42, 799]]
	//		To:		[[4, 370], [15, 814, 1779, 1715, 1732], [29, 1528, 1531, 2272], [34, 447, 3119, 3201], [42, 908, 799]]
	//	or [pageno,wordcount]
	//		From:	[[4, 1], [15, 2], [29, 3], [34, 3], [42, 1], [15, 2], [42, 1]]
	//		To:		[[4, 1], [15, 4], [29, 3], [34, 3], [42, 2]]
	function plNormalise(arr) {
		var a, i, j, k;
		a = arr.concat();
		for (i = 0; i < a.length; i++) {
			for (j = i + 1; j < a.length; j++) {
				if (a[i][0] === a[j][0]) {
					if (thisdb.haswordposns) {	// merge word positions
						for (k = 1; k < a[j].length; k++) {
							a[i].push(a[j][k]);
						}
					} else {	// add word counts
						a[i][1] += a[j][1];
					}
					a.splice(j--, 1);
				}
			}
		}
		return a;
	}
	/////////////////////////////////////
	// Remove duplicate pagenos from given combined array
	//	each element either	[pageno,prio,wordposn1...]
	//		From:	[[4, 2, 370], [15, 3, 814, 1779], [29, 3, 1528, 1531, 2272], [34, 2, 447, 3119, 3201], [42, 2, 908], [15, 2, 1715, 1732], [42, 2, 799]]
	//		To:		[[4, 2, 370], [15, 2, 814, 1779, 1715, 1732], [29, 3, 1528, 1531, 2272], [34, 2, 447, 3119, 3201], [42, 2, 908, 799]]
	//	or [pageno,prio,wordcount]
	//		From:	[[4, 2, 1], [15, 3, 2], [29, 3, 3], [34, 2, 3], [42, 2, 1], [15, 2, 2], [42, 2, 1]]
	//		To:		[[4, 2, 1], [15, 2, 4], [29, 3, 3], [34, 2, 3], [42, 2, 2]]
	function plNormaliseAndSortPositions(arr) {
		var a, i, j, k, pp, pageno, prio;
		a = arr.concat();
		for (i = 0; i < a.length; i++) {
			for (j = i + 1; j < a.length; j++) {
				if (a[i][0] === a[j][0]) {
					a[i][1] = Math.min(a[i][1], a[j][1]);
					if (thisdb.haswordposns) {	// merge word positions
						for (k = 2; k < a[j].length; k++) {
							a[i].push(a[j][k]);
							pp = a[i].splice(0, 2);
							pageno = pp[0];
							prio = pp[1];
							a[i].sort(function (a, b) { return a - b; });
							a[i].unshift(pageno, prio);
						}
					} else {	// add word counts
						a[i][2] += a[j][2];
					}
					a.splice(j--, 1);
				}
			}
		}
		return a;
	}

	/////////////////////////////////////
	function deepArrayCopy(arr) {
		var rarr, ix;
		if (Object.prototype.toString.call(arr) !== "[object Array]") { return arr; }
		rarr = [];
		for (ix = 0; ix < arr.length; ix++) {
			rarr.push(deepArrayCopy(arr[ix]));
		}
		return rarr;
	}

	/////////////////////////////////////
	function deepFreezeArray(arr) {
		var ix;
		//log(typeof arr + " - " +arr);
		if (typeof arr !== "object") { return; }
		Object.freeze(arr);
		if (Object.prototype.toString.call(arr) !== "[object Array]") { return; }

		for (ix = 0; ix < arr.length; ix++) {
			deepFreezeArray(arr[ix]);
		}
	}

	/////////////////////////////////////
	var SearchWord = function (word, lcword, op, useRules) {
		if (typeof useRules === 'undefined') { useRules = true; }
		//log("SearchWord: "+word+ " op "+op+" rules "+useRules);
		this.given = word;
		this.op = op;
		this.wds = [lcword];
		this.wdsfound = [];
		this.anyfound = false;

		if (useRules) {
			if (config.rules) {
				config.rules.generate(lcword, this.wds);
			}
		}
		//log(this.w);
	};

	/////////////////////////////////////
	function storeWord(narrative, expression, word, op, incontig, useRules) {
    var lcword = toUnicodeLowerCaseNormalise(word);
		if (!incontig) {
			if (lcword == lcAND) {
				return op;
			}
			if (lcword == lcOR) {
				op = OP_OR;
				return op;
			}
			if (lcword == lcNOT) {
				op |= OP_NOT;
				return op;
			}
		}
		if ((expression.length === 0) && ((op & OP_OR) === OP_OR)) {
			narrative.push("Initial OR ignored");
			op &= ~OP_OR;
		}
		if ((op & OP_NOT) && incontig) {
			throw "NOT not permited before \"contiguous words\"";
		}

		if (incontig) { op |= OP_CONTIG; }
		expression.push(new SearchWord(word, lcword, op, useRules));
		return OP_NONE;
	}

	/////////////////////////////////////
	/**
   * Start search; call searchDone when done
   *
   * @param {object}	parameters
	 *		search				{text}			- Text to search for
	 *		showProgress	{function}	- Callback to show search progress
	 *		searchDone		{function}	- Callback to show results
   */

	function search(params) {
		if (typeof params.searchDone !== 'function') { return; }
		searchDone = params.searchDone;

		showProgress = false;
		if (typeof params.showProgress === 'function') { showProgress = params.showProgress; }

		try {
			doSearch(params);
		}
		catch (err) {
			searchDone({
				error: err
			});
		}
	}

	/////////////////////////////////////
	//	Search all available databases, one at a time then combine/sort results
	doSearch = function (params) {

		var given = params.search;
		deferSearch = false;

		if (databases.length > config.dbcount) {
			throw "Too many databases loaded: " + databases.length + ". Expected: " + config.dbcount;
		} else if (databases.length != config.dbcount) {
			deferSearch = params;
			showLoadingProgress();
			return;
		}

		if (!given) { given = ''; }
		//log("Search=" + given);
		given = given.trim();
		if (given.length === 0) { throw 'No search'; }

		var results = {
			error: false,
			hits: [],
			narrative: []
		};

		var isAllSearch = false;
		if (search === '*') {
			isAllSearch = true;
			results.expression = [{ given: given, wordfound: true }];
		}

		// Search each database, adding hits to results.hits
		var dbcount = databases.length;
		var anydbselected = false;
		for (var dbno = 0; dbno < dbcount; dbno++) {

			thisdb = databases[dbno];
			// 7.014 always search all databases, and then filter: if (!thisdb.selected) continue;
			anydbselected = true;
			searchOneDatabase(given, results, dbno);

		}
		if (!anydbselected) {
			results.error = "No subset selected";
		}

		// Sort to have hits with highest relevance first
		if (!isAllSearch) {
			results.hits.sort(function (a, b) {
				return b[2] - a[2];
			});
		}
		searchDone(results);
	};

	/////////////////////////////////////
	// Each database has a list of pages and a words hash table, with each entry like this:
	//	["word",[0,[[1,1214]]],[3,[[1,60,116],[11,60,116]]]],
	// where the word is followed by one or more priority-page-lists (ppl)
	// where	the priority is int 0 to 3
	//				followed by one or more page-lists
	// where page-list is either	[pageno,word position list...]		if thisdb.haswordposns	true
	//										or			[pageno,wordcount]																				false
	//
	// Search process is:
	//
	//	- If search is * then return all pages in database immediately
	//
	//	- Parse input into a series of SearchWord-s
	//		where searchWord.given is eg test 
	//		and		searchWord.wdsfound has alt-words that match by rule eg test tests tested testing unless given in single-quote eg 'test'
	//
	//	- For each SearchWord, for each alt-word, if alt-word in database, store ppl-s in searchWord.pl
	//
	//	- For each SearchWord, merge priority-page-lists to end up with searchWord.combined
	//			combined has array of	[pageno,prio,wordposn1...]
	//												or	[pageno,prio,totalwordcount]
	//
	//	- Merge the SearchWord.combined

	function searchOneDatabase(given, results, dbno) {
		var doFreeze, hashtableentries, allpageix, expr, word, chno, nch, useRules, eno, searchWord;
		var wno, lcword, hashcode, wordList, prioList, pr0no, plno, pln, prno, prlist, prio, foundprio, pr0list;
		var hitinfo, anyhits, tomerge, pageix, mergeix, pageno, mergepageno, merged, incontig;
		var i, pl, bestprio, totalwordcount;

		///////////////
		// Optionally freeze the db (to ensure that nothing is changed that will affect future searches)
		if ((typeof fisFreezeDb !== 'undefined') && fisFreezeDb) {
			doFreeze = true;
			if (Object.isFrozen && Object.isFrozen(thisdb)) {
				doFreeze = false;
			}
			if (doFreeze && Object.freeze) {
				log("FREEZE DB");
				Object.freeze(thisdb);
				deepFreezeArray(thisdb.pages);
				deepFreezeArray(thisdb.words);
			}
		}

		hashtableentries = thisdb.words.length;
		//console.log(thisdb.varname + " hashtableentries: " + hashtableentries);

		///////////////
		// HANDLE SEARCH FOR * SPECIALLY
		if (given === '*') {
			for (allpageix = 0; allpageix < thisdb.pages.length - 1; allpageix++) {	// Ignore last empty page
				results.hits.push([allpageix + 1, thisdb, 0]);
				//console.log(" ALL - " + JSON.stringify(allpageix + 1));
			}
			results.expression = [];
			var sw = new SearchWord('*', '*', OP_NONE, false);
			sw.anyfound = true;
			results.expression.push(sw);
			return;
		}

		///////////////
		// PARSE INPUT (ONCE ONLY)
		////// BuildSearchWords
		// ' \x27 ‘ \x2018 ’ \x2019	‘quote’
		// " \x22 “ \x201C ” \x201D	“quote”
		if (!results.expression) {
			expr = [];
			word = "";
			var op = OP_NONE;
			incontig = false;
			for (chno = 0; chno < given.length; chno++) {
				nch = given.charCodeAt(chno);
        //console.log("nch=" + nch + " - " + isUnicodeSeparator(nch));
				if (isUnicodeSeparator(nch)) {
					if (word.length === 0) {
						if (thisdb.haswordposns && (nch === 0x22 || nch === 0x201c)) {
							incontig = true;
						}
					}
					else if (word.length > 0) {
						useRules = true;
						var endcontig = false;
						if (thisdb.haswordposns && incontig && (nch === 0x22 || nch === 0x201d)) {
							endcontig = true;
						}
						// Check for words in single quotes, ie look for ' before start of current word or ‘ for ’
						if (nch === 0x27) {
							if ((chno > word.length) && (given.charCodeAt(chno - word.length - 1) === 0x27)) {
								useRules = false;
							}
						}
						if (nch === 0x2019) {
							if ((chno > word.length) && (given.charCodeAt(chno - word.length - 1) === 0x2018)) {
								useRules = false;
							}
						}
						//log("word=" + word + " - " + useRules);
						op = storeWord(results.narrative, expr, word, op, incontig, useRules);
						word = "";
						if (endcontig) { incontig = false; }
					}
				}
				else {
					if (!isUnicodeCharLatin(nch)) {
						if (word.length > 0) {
							op = storeWord(results.narrative, expr, word, op, incontig, useRules);
							word = "";
						}
					}
					word += String.fromCharCode(nch);
				}
			}
			if (word.length > 0) {
				//log("word=" + word);
				storeWord(results.narrative, expr, word, op, incontig);
			}
			results.expression = expr;
		}

		///////////////
		// FIND PAGE LISTS
		//log("FIND PAGE LISTS");
		// For each given search word
		for (eno = 0; eno < results.expression.length; eno++) {
			searchWord = results.expression[eno];
			searchWord.pl = [];
			var w = deepArrayCopy(searchWord.wds);
			searchWord.wordfound = false;
			//log(searchWord.given);

			// For each variant of each given word
			for (wno = 0; wno < w.length; wno++) {
				word = w[wno];

        lcword = toUnicodeLowerCaseNormalise(word);

				// look through hashtable for word
				hashcode = stringHashCode(lcword) % hashtableentries;
				do {
					wordList = thisdb.words[hashcode];
					//console.log(wordList);
					if (Object.prototype.toString.call(wordList) !== "[object Array]") {
						w.splice(wno, 1);
						wno--;
						break; // word not found
					}
					if (lcword === wordList[0]) {
						// word found
						// Copy and remove word from 1st element ie from ["quoted",[3,[[40,813]]]]
						prioList = wordList.slice(1);
						searchWord.pl.push(prioList);
						searchWord.wordfound = true;
						searchWord.anyfound = true;
						var inwdsfound = false;
						for (i = 0; i < searchWord.wdsfound.length; i++) {
							if (searchWord.wdsfound[i] === word) {
								inwdsfound = true;
							}
						}
						if (!inwdsfound) { searchWord.wdsfound.push(word); }
						break;
					}
					// No match, try next hash
					if (++hashcode === hashtableentries) {
						hashcode = 0;
					}
				}
				while (true);
			}
		}

		//log(expression);

		///////////////
		////// DoSearch

		// MERGE WORD PRIORITIES
		//log("MERGE WORD PRIORITIES");
		// For each given search word (into first word of each expression element)
		for (eno = 0; eno < results.expression.length; eno++) {
			searchWord = results.expression[eno];
			if (!searchWord.wordfound) {
				if (config.dbcount > 1) {
					return;	// Don't add any hits to results
				}
				continue;
			}
			searchWord.pr0 = deepArrayCopy(searchWord.pl[0]);
			if (searchWord.pl.length > 1) {
				// Merge subsequent alt-words into first alt-word
				//var plnono = 1;
				for (plno = 1; plno < searchWord.pl.length; plno++) {
					pln = searchWord.pl[plno];
					for (prno = 0; prno < pln.length; prno++) {
						prlist = pln[prno];
						prio = prlist[0];
						foundprio = false;
						for (pr0no = 0; pr0no < searchWord.pr0.length; pr0no++) {
							if (searchWord.pr0[pr0no][0] === prio) {
								// merge pagelists and ensure unique
								var concatted = searchWord.pr0[pr0no][1].concat(deepArrayCopy(prlist[1]));
								searchWord.pr0[pr0no][1] = plNormalise(concatted);
								foundprio = true;
								break;
							}
						}
						if (!foundprio) {
							searchWord.pr0.push(deepArrayCopy(prlist));
						}
					}
					// Remove this pl[plno]
					searchWord.pl.splice(plno, 1);
					plno--;
				}
				// Sort pageno lists
				for (pr0no = 0; pr0no < searchWord.pr0.length; pr0no++) {
					pr0list = searchWord.pr0[pr0no];
					pr0list[1].sort(function (a, b) { return a[0] - b[0]; });
				}
				// Sort priority lists
				searchWord.pr0.sort(function (a, b) { return a[0] - b[0]; }); // Sort by priority
			}

			////
			// Produce combined page list for this searchWord including best priority for each page
			//console.log("searchWord.pr0.length: " + searchWord.pr0.length);
			// combined has array of	[pageno,prio,wordposn1...]
			//										or	[pageno,prio,totalwordcount]
			searchWord.combined = [];
			for (pr0no = 0; pr0no < searchWord.pr0.length; pr0no++) {
				prio = searchWord.pr0[pr0no][0];
				pl = searchWord.pr0[pr0no][1];
				for (i = 0; i < pl.length; i++) {
					pl[i].splice(1, 0, prio);
				}
				// Then add onto end of combined
				searchWord.combined = searchWord.combined.concat(pl);
			}
			searchWord.combined = plNormaliseAndSortPositions(searchWord.combined);
			searchWord.combined.sort(function (a, b) { return a[0] - b[0]; });

		}

		///////////////
		////// MERGE PAGES
		//	Handle:	logical operations ie OR NOT
		//					contiguous words
		hitinfo = [];	// array of [pageno,bestprio,totalwordcount]
		anyhits = false;
		incontig = 0;
		var contigs = false;
		for (eno = 0; eno < results.expression.length; eno++) {
			searchWord = results.expression[eno];
			if (!searchWord.wordfound) { continue; }	// Carry on if word not found at all

			//console.log("MERGE: " + searchWord.given + " op:" + searchWord.op);

			if (searchWord.op & OP_CONTIG) {
				incontig++;
				if (incontig === 1) {
					contigs = searchWord.combined;	//	array of [pageno,prio,wordposn1...]
				}
			} else {
				incontig = 0;
				contigs = false;
			}

			if (searchWord.op & OP_NOT) {
				var notted = [];
				pageix = 0;
				pl = searchWord.combined[pageix];
				for (pageno = 1; pageno < thisdb.pages.length; pageno++) {	// Note start and end
					if (pl[0] == pageno) {
						if (++pageix < searchWord.combined.length) {
							pl = searchWord.combined[pageix];
						}
					}
					else {
						notted.push([pageno, 3, 0]);
					}
				}
				searchWord.combined = notted;
			}
			if (!anyhits) {
				for (pageix = 0; pageix < searchWord.combined.length; pageix++) {
					pl = searchWord.combined[pageix];
					totalwordcount = (thisdb.haswordposns ? pl.length - 2 : pl[2]);
					hitinfo.push([pl[0], pl[1], totalwordcount]);
				}
				anyhits = true;
				continue;
			}
			// go through hitinfo and tomerge to create merged, then set hitinfo to merged
			var isOr = (searchWord.op & OP_OR);
			tomerge = searchWord.combined;
			pageix = 0;
			mergeix = 0;
			merged = [];
			while ((pageix < hitinfo.length) && (mergeix < tomerge.length)) {
				pageno = hitinfo[pageix][0];
				mergepageno = tomerge[mergeix][0];
				if (pageno < mergepageno) {
					if (isOr) {
						merged.push([pageno, hitinfo[pageix][1], hitinfo[pageix][2]]);
					}
					pageix++;
					continue;
				}
				if (pageno > mergepageno) {
					if (isOr) {
						pl = tomerge[mergeix];
						totalwordcount = (thisdb.haswordposns ? pl.length - 2 : pl[2]);
						merged.push([mergepageno, tomerge[mergeix][1], totalwordcount]);
					}
					mergeix++;
					continue;
				}
				// pageno == mergepageno
				bestprio = Math.min(hitinfo[pageix][1], tomerge[mergeix][1]);

				var updatedContigs, contigfound;
				var totalwordcount2 = 0;
				if (incontig > 1) {
					var c1i = findConfig(pageno, contigs);														// [6,3,111,159,190,291,375]
					var c1 = contigs[c1i];
					totalwordcount2 = -(c1.length - 2);
					var c2i = findConfig(mergepageno, searchWord.combined);					// [6,0,17,70,112,265,292,372,388,459,477,520,555,592,671]
					var c2 = searchWord.combined[c2i];
					updatedContigs = [pageno, bestprio];												// [6,0,112,292]
					contigfound = false;
					var c2pno = 2;
					for (var c1pno = 2; c1pno < c1.length; c1pno++) {
						var c1p = c1[c1pno];
						while (c2pno < c2.length) {
							var c2p = c2[c2pno];
							if (c2p < c1p) {
								c2pno++;
							} else if (c2p == (c1p + 1)) {
								contigfound = true;
								updatedContigs.push(c2p);
								break;
							} else {
								break;
							}
						}
					}
					if (!contigfound) {
						pageix++;
						mergeix++;
						continue;
					} else {
						contigs[c1i] = updatedContigs;
						totalwordcount2 += updatedContigs.length - 2;
					}
				}

				if (!contigfound) {
					totalwordcount2 = (thisdb.haswordposns ? tomerge[mergeix].length - 2 : tomerge[mergeix][2]);
				}
				totalwordcount = hitinfo[pageix][2] + totalwordcount2;
				merged.push([pageno, bestprio, totalwordcount]);
				pageix++;
				mergeix++;
			}
			// If ORing then add in the ones we've missed
			if (isOr) {
				for (; pageix < hitinfo.length; pageix++) {
					merged.push([hitinfo[pageix][0], hitinfo[pageix][1], hitinfo[pageix][2]]);
				}
				for (; mergeix < tomerge.length; mergeix++) {
					pl = tomerge[mergeix];
					totalwordcount = (thisdb.haswordposns ? pl.length - 2 : pl[2]);
					merged.push([tomerge[mergeix][0], tomerge[mergeix][1], totalwordcount]);
				}
			}
			hitinfo = merged;
		}

		///////////////
		// Build results hits to return
		for (var hitno = 0; hitno < hitinfo.length; hitno++) {
			pageno = hitinfo[hitno][0];
			bestprio = hitinfo[hitno][1];
			totalwordcount = hitinfo[hitno][2];
			var relevance = (3 - bestprio) * 10000 + totalwordcount;
			results.hits.push([pageno, thisdb, relevance]);
		}
	}

	/////////////////////////////////////
	function findConfig(pageno, contigs) {
		for (var i = 0; i < contigs.length; i++) {
			if (contigs[i][0] === pageno) {
				return i;
			}
		}
		throw "findConfig " + pageno + " fail";
	}

	/////////////////////////////////////
  // 7.016: revamped to use separatorRanges to match Findex
  isUnicodeSeparator = function (nch) {
    var separatorRangesLen = separatorRanges.length;
    for (var i = 0; i < separatorRangesLen; i += 2) {
      var lowsep = separatorRanges[i];
      var highsep = separatorRanges[i+1];
      if (nch >= lowsep && nch <= highsep) return true;
      if (nch < lowsep) return false;
    }
    return true;
		// WAS return !isUnicodeLetter(nch) && !isUnicodeNumber(nch);
	};

  /////////////////////////////////////
  isUnicodeCharLatin = function (nch) {
    if (nch >= 0xFF01 && nch <= 0xFF5E) { // 7.016
      nch -= 0xFF01 + 0x0021;
    }
    return (nch <= 0x02A8) ||
      (nch >= 0x1E00 && nch < 0x1EF9) ||
      (nch >= 0x0374 && nch <= 0x03f5) ||
      (nch >= 0x0400 && nch <= 0x04ff) ||
      (nch >= 0x060C && nch <= 0x06FE) ||
      (nch >= 0xFB50 && nch <= 0xFDFB) ||
      (nch >= 0xFE70 && nch <= 0xFEFC);
  };

  /////////////////////////////////////
  // 7.016: do full LowerCase checking
  // include some CharCanon.CanonicaliseText handling, ie some MapUnicodeChar but not ExpandLigature
  var ToUnicodeLowerCaseNormaliseCh = function (nch) {
    var LowerCase = false;
    switch (nch >> 8) {
      case 0x00: if (nch >= 0x0041 && nch <= 0x005A)
        return nch + 0x0020;
        if (nch < 0x00C0) {
          return nch;
        }

        LowerCase = LowerCase00;
        break;

      case 0x01: LowerCase = LowerCase01; break;
      case 0x02: LowerCase = LowerCase02; break;
      case 0x03: LowerCase = LowerCase03; break;
      case 0x04: LowerCase = LowerCase04; break;
      case 0x05: LowerCase = LowerCase05; break;
      case 0x06: LowerCase = LowerCase06; break;		// 6.0
      case 0x09: LowerCase = LowerCase09; break;
      case 0x0A: LowerCase = LowerCase0A; break;
      case 0x0B: LowerCase = LowerCase0B; break;
      case 0x0C: LowerCase = LowerCase0C; break;
      case 0x0D: LowerCase = LowerCase0D; break;
      case 0x0E: LowerCase = LowerCase0E; break;
      case 0x0F: LowerCase = LowerCase0F; break;
      case 0x10: LowerCase = LowerCase10; break;
      case 0x1E: LowerCase = LowerCase1E; break;
      case 0x1F: LowerCase = LowerCase1F; break;
      case 0x20: LowerCase = LowerCase20; break;
      case 0x21: LowerCase = LowerCase21; break;
      case 0x22: LowerCase = LowerCase22; break;
      case 0x23: LowerCase = LowerCase23; break;
      case 0x24: LowerCase = LowerCase24; break;
      // 7.016 Don't normalise case 0x30:	LowerCase = LowerCase30; break; // Don't do this as these chars aren't equivalent
      case 0xF9: LowerCase = LowerCaseF9; break;
      case 0xFA: LowerCase = LowerCaseFA; break;
      case 0xFB: LowerCase = LowerCaseFB; break;
      case 0xFF:
        // Transform Japanese full width chars to LATIN equivalent. From CharCanon.TransformUchar
        if (nch >= 0xFF01 && nch <= 0xFF5E) {
          return nch - 0xFF01 + 0x0021;
        }
        return nch;

      default:
        return nch;
    }
    if (!LowerCase) return nch;
    var LowerCaseLen = LowerCase.length;
    for (var pno = 0; pno < LowerCaseLen; pno++)
    {
      if (nch === LowerCase[pno++]) {
        return LowerCase[pno];
      }
    }
    return nch;
  };

	/////////////////////////////////////
  toUnicodeLowerCaseNormalise = function (word) {
    var rv = '';
    for (var i = 0; i < word.length; i++) {
      rv += String.fromCharCode(ToUnicodeLowerCaseNormaliseCh(word.charCodeAt(i)));
    }
		return rv;
  };

	/////////////////////////////////////
	// Amended from http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery

	stringHashCode = function (val) {
		var hash = 0, i, chr, len;
		for (i = 0, len = val.length; i < len; i++) {
			chr = val.charCodeAt(i);
			hash = ((hash << 5) - hash) + chr;
			hash &= 0x7fffffff; // Convert to 32bit integer
		}
		return hash;
  };


	/////////////////////////////////////
  // 7.016 generated by Findex: used by isUnicodeSeparator. Pairs that indicate when chars are separators.
var separatorRanges = [
0x0,0x2F, 0x3A,0x40, 0x5B,0x60, 0x7B,0xA9, 0xAB,0xB4, 0xB6,0xB9, 0xBB,0xBF, 0xD7,0xD7, 0xF7,0xF7, 0x2C2,0x2C5, 0x2D2,0x2DF, 0x2E5,0x2EB, 0x2ED,0x2ED, 0x2EF,0x36F, 0x375,0x375, 0x378,0x379, 0x37E,0x385, 0x387,0x387, 0x38B,0x38B, 0x38D,0x38D, 0x3A2,0x3A2, 0x3F6,0x3F6, 0x482,0x489, 0x528,0x530, 0x557,0x558, 0x55A,0x560, 0x588,0x5CF, 0x5EB,0x5EF, 0x5F3,0x61F, 0x64B,0x65F, 0x66A,0x66D, 0x670,0x670, 0x6D4,0x6D4, 0x6D6,0x6E4, 0x6E7,0x6ED, 0x6FD,0x6FE, 0x700,0x70F, 0x711,0x711, 0x730,0x74C, 0x7A6,0x7B0, 0x7B2,0x7BF, 0x7EB,0x7F3, 0x7F6,0x7F9, 0x7FB,0x7FF, 0x816,0x819, 0x81B,0x823, 0x825,0x827, 0x829,0x83F, 0x859,0x89F, 0x8A1,0x8A1, 0x8AD,0x903, 0x93A,0x93C, 0x93E,0x94F, 0x951,0x957, 0x962,0x965, 0x970,0x970, 0x978,0x978, 0x980,0x984, 0x98D,0x98E, 0x991,0x992, 0x9A9,0x9A9, 0x9B1,0x9B1, 0x9B3,0x9B5, 0x9BA,0x9BC, 0x9BE,0x9CD, 0x9CF,0x9DB, 0x9DE,0x9DE, 0x9E2,0x9E5, 0x9F2,0xA04, 0xA0B,0xA0E, 0xA11,0xA12, 0xA29,0xA29, 0xA31,0xA31, 0xA34,0xA34, 0xA37,0xA37, 0xA3A,0xA58, 0xA5D,0xA5D, 0xA5F,0xA65, 0xA70,0xA71, 0xA75,0xA84, 0xA8E,0xA8E, 0xA92,0xA92, 0xAA9,0xAA9, 0xAB1,0xAB1, 0xAB4,0xAB4, 0xABA,0xABC, 0xABE,0xACF, 0xAD1,0xADF, 0xAE2,0xAE5, 0xAF0,0xB04, 0xB0D,0xB0E, 0xB11,0xB12, 0xB29,0xB29, 0xB31,0xB31, 0xB34,0xB34, 0xB3A,0xB3C, 0xB3E,0xB5B, 0xB5E,0xB5E, 0xB62,0xB65, 0xB70,0xB70, 0xB72,0xB82, 0xB84,0xB84, 0xB8B,0xB8D, 0xB91,0xB91, 0xB96,0xB98, 0xB9B,0xB9B, 0xB9D,0xB9D, 0xBA0,0xBA2, 0xBA5,0xBA7, 0xBAB,0xBAD, 0xBBA,0xBCF, 0xBD1,0xBE5, 0xBF0,0xC04, 0xC0D,0xC0D, 0xC11,0xC11, 0xC29,0xC29, 0xC34,0xC34, 0xC3A,0xC3C, 0xC3E,0xC57, 0xC5A,0xC5F, 0xC62,0xC65, 0xC70,0xC84, 0xC8D,0xC8D, 0xC91,0xC91, 0xCA9,0xCA9, 0xCB4,0xCB4, 0xCBA,0xCBC, 0xCBE,0xCDD, 0xCDF,0xCDF, 0xCE2,0xCE5, 0xCF0,0xCF0, 0xCF3,0xD04, 0xD0D,0xD0D, 0xD11,0xD11, 0xD3B,0xD3C, 0xD3E,0xD4D, 0xD4F,0xD5F, 0xD62,0xD65, 0xD70,0xD79, 0xD80,0xD84, 0xD97,0xD99, 0xDB2,0xDB2, 0xDBC,0xDBC, 0xDBE,0xDBF, 0xDC7,0xE00, 0xE31,0xE31, 0xE34,0xE3F, 0xE47,0xE4F, 0xE5A,0xE80, 0xE83,0xE83, 0xE85,0xE86, 0xE89,0xE89, 0xE8B,0xE8C, 0xE8E,0xE93, 0xE98,0xE98, 0xEA0,0xEA0, 0xEA4,0xEA4, 0xEA6,0xEA6, 0xEA8,0xEA9, 0xEAC,0xEAC, 0xEB1,0xEB1, 0xEB4,0xEBC, 0xEBE,0xEBF, 0xEC5,0xEC5, 0xEC7,0xECF, 0xEDA,0xEDB, 0xEE0,0xEFF, 0xF01,0xF1F, 0xF2A,0xF3F, 0xF48,0xF48, 0xF6D,0xF87, 0xF8D,0xFFF, 0x102B,0x103E, 0x104A,0x104F, 0x1056,0x1059, 0x105E,0x1060, 0x1062,0x1064, 0x1067,0x106D, 0x1071,0x1074, 0x1082,0x108D, 0x108F,0x108F, 0x109A,0x109F, 0x10C6,0x10C6, 0x10C8,0x10CC, 0x10CE,0x10CF, 0x10FB,0x10FB, 0x1249,0x1249, 0x124E,0x124F, 0x1257,0x1257, 0x1259,0x1259, 0x125E,0x125F, 0x1289,0x1289, 0x128E,0x128F, 0x12B1,0x12B1, 0x12B6,0x12B7, 0x12BF,0x12BF, 0x12C1,0x12C1, 0x12C6,0x12C7, 0x12D7,0x12D7, 0x1311,0x1311, 0x1316,0x1317, 0x135B,0x137F, 0x1390,0x139F, 0x13F5,0x1400, 0x166D,0x166E, 0x1680,0x1680, 0x169B,0x169F, 0x16EB,0x16FF, 0x170D,0x170D, 0x1712,0x171F, 0x1732,0x173F, 0x1752,0x175F, 0x176D,0x176D, 0x1771,0x177F, 0x17B4,0x17D6, 0x17D8,0x17DB, 0x17DD,0x17DF, 0x17EA,0x180F, 0x181A,0x181F, 0x1878,0x187F, 0x18A9,0x18A9, 0x18AB,0x18AF, 0x18F6,0x18FF, 0x191D,0x1945, 0x196E,0x196F, 0x1975,0x197F, 0x19AC,0x19C0, 0x19C8,0x19CF, 0x19DA,0x19FF, 0x1A17,0x1A1F, 0x1A55,0x1A7F, 0x1A8A,0x1A8F, 0x1A9A,0x1AA6, 0x1AA8,0x1B04, 0x1B34,0x1B44, 0x1B4C,0x1B4F, 0x1B5A,0x1B82, 0x1BA1,0x1BAD, 0x1BE6,0x1BFF, 0x1C24,0x1C3F, 0x1C4A,0x1C4C, 0x1C7E,0x1CE8, 0x1CED,0x1CED, 0x1CF2,0x1CF4, 0x1CF7,0x1CFF, 0x1DC0,0x1DFF, 0x1F16,0x1F17, 0x1F1E,0x1F1F, 0x1F46,0x1F47, 0x1F4E,0x1F4F, 0x1F58,0x1F58, 0x1F5A,0x1F5A, 0x1F5C,0x1F5C, 0x1F5E,0x1F5E, 0x1F7E,0x1F7F, 0x1FB5,0x1FB5, 0x1FBD,0x1FBD, 0x1FBF,0x1FC1, 0x1FC5,0x1FC5, 0x1FCD,0x1FCF, 0x1FD4,0x1FD5, 0x1FDC,0x1FDF, 0x1FED,0x1FF1, 0x1FF5,0x1FF5, 0x1FFD,0x2070, 0x2072,0x207E, 0x2080,0x208F, 0x209D,0x2101, 0x2103,0x2106, 0x2108,0x2109, 0x2114,0x2114, 0x2116,0x2118, 0x211E,0x2123, 0x2125,0x2125, 0x2127,0x2127, 0x2129,0x2129, 0x212E,0x212E, 0x213A,0x213B, 0x2140,0x2144, 0x214A,0x214D, 0x214F,0x2182, 0x2185,0x2BFF, 0x2C2F,0x2C2F, 0x2C5F,0x2C5F, 0x2CE5,0x2CEA, 0x2CEF,0x2CF1, 0x2CF4,0x2CFF, 0x2D26,0x2D26, 0x2D28,0x2D2C, 0x2D2E,0x2D2F, 0x2D68,0x2D6E, 0x2D70,0x2D7F, 0x2D97,0x2D9F, 0x2DA7,0x2DA7, 0x2DAF,0x2DAF, 0x2DB7,0x2DB7, 0x2DBF,0x2DBF, 0x2DC7,0x2DC7, 0x2DCF,0x2DCF, 0x2DD7,0x2DD7, 0x2DDF,0x2E2E, 0x2E30,0x3004, 0x3007,0x3030, 0x3036,0x303A, 0x303D,0x3040, 0x3097,0x309C, 0x30A0,0x30A0, 0x30FB,0x30FB, 0x3100,0x3104, 0x312E,0x3130, 0x318F,0x319F, 0x31BB,0x31EF, 0x3200,0x33FF, 0x4DB6,0x4DFF, 0x9FCD,0x9FFF, 0xA48D,0xA4CF, 0xA4FE,0xA4FF, 0xA60D,0xA60F, 0xA62C,0xA63F, 0xA66F,0xA67E, 0xA698,0xA69F, 0xA6E6,0xA716, 0xA720,0xA721, 0xA789,0xA78A, 0xA78F,0xA78F, 0xA794,0xA79F, 0xA7AB,0xA7F7, 0xA802,0xA802, 0xA806,0xA806, 0xA80B,0xA80B, 0xA823,0xA83F, 0xA874,0xA881, 0xA8B4,0xA8CF, 0xA8DA,0xA8F1, 0xA8F8,0xA8FA, 0xA8FC,0xA8FF, 0xA926,0xA92F, 0xA947,0xA95F, 0xA97D,0xA983, 0xA9B3,0xA9CE, 0xA9DA,0xA9FF, 0xAA29,0xAA3F, 0xAA43,0xAA43, 0xAA4C,0xAA4F, 0xAA5A,0xAA5F, 0xAA77,0xAA79, 0xAA7B,0xAA7F, 0xAAB0,0xAAB0, 0xAAB2,0xAAB4, 0xAAB7,0xAAB8, 0xAABE,0xAABF, 0xAAC1,0xAAC1, 0xAAC3,0xAADA, 0xAADE,0xAADF, 0xAAEB,0xAAF1, 0xAAF5,0xAB00, 0xAB07,0xAB08, 0xAB0F,0xAB10, 0xAB17,0xAB1F, 0xAB27,0xAB27, 0xAB2F,0xABBF, 0xABE3,0xABEF, 0xABFA,0xABFF, 0xD7A4,0xD7AF, 0xD7C7,0xD7CA, 0xD7FC,0xF8FF, 0xFA6E,0xFA6F, 0xFADA,0xFAFF, 0xFB07,0xFB12, 0xFB18,0xFB1C, 0xFB1E,0xFB1E, 0xFB29,0xFB29, 0xFB37,0xFB37, 0xFB3D,0xFB3D, 0xFB3F,0xFB3F, 0xFB42,0xFB42, 0xFB45,0xFB45, 0xFBB2,0xFBD2, 0xFD3E,0xFD4F, 0xFD90,0xFD91, 0xFDC8,0xFDEF, 0xFDFC,0xFE6F, 0xFE75,0xFE75, 0xFEFD,0xFF0F, 0xFF1A,0xFF20, 0xFF3B,0xFF40, 0xFF5B,0xFF65, 0xFFBF,0xFFC1, 0xFFC8,0xFFC9, 0xFFD0,0xFFD1, 0xFFD8,0xFFD9, 0xFFDD,0xFFFF
];

var LowerCase00 = [
  /*	Hand coded for efficiency
    0x0041, 0x0061,
    0x0042, 0x0062,
    0x0043, 0x0063,
    0x0044, 0x0064,
    0x0045, 0x0065,
    0x0046, 0x0066,
    0x0047, 0x0067,
    0x0048, 0x0068,
    0x0049, 0x0069,
    0x004A, 0x006A,
    0x004B, 0x006B,
    0x004C, 0x006C,
    0x004D, 0x006D,
    0x004E, 0x006E,
    0x004F, 0x006F,
    0x0050, 0x0070,
    0x0051, 0x0071,
    0x0052, 0x0072,
    0x0053, 0x0073,
    0x0054, 0x0074,
    0x0055, 0x0075,
    0x0056, 0x0076,
    0x0057, 0x0077,
    0x0058, 0x0078,
    0x0059, 0x0079,
    0x005A, 0x007A,
  */
  0x00C0, 0x0061,		// 0041 0300
  0x00C1, 0x0061,		// 0041 0301
  0x00C2, 0x0061,		// 0041 0302
  0x00C3, 0x0061,		// 0041 0303
  0x00C4, 0x0061,		// 0041 0308
  0x00C5, 0x0061,		// 0041 030A
  0x00C6, 0x00E6,
  0x00C7, 0x0063,		// 0043 0327
  0x00C8, 0x0065,		// 0045 0300
  0x00C9, 0x0065,		// 0045 0301
  0x00CA, 0x0065,		// 0045 0302
  0x00CB, 0x0065,		// 0045 0308
  0x00CC, 0x0069,		// 0049 0300
  0x00CD, 0x0069,		// 0049 0301
  0x00CE, 0x0069,		// 0049 0302
  0x00CF, 0x0069,		// 0049 0308
  0x00D0, 0x00F0,
  0x00D1, 0x006E,		// 004E 0303
  0x00D2, 0x006F,		// 004F 0300
  0x00D3, 0x006F,		// 004F 0301
  0x00D4, 0x006F,		// 004F 0302
  0x00D5, 0x006F,		// 004F 0303
  0x00D6, 0x006F,		// 004F 0308
  0x00D8, 0x00F8,
  0x00D9, 0x0075,		// 0055 0300
  0x00DA, 0x0075,		// 0055 0301
  0x00DB, 0x0075,		// 0055 0302
  0x00DC, 0x0075,		// 0055 0308
  0x00DD, 0x0079,		// 0059 0301
  0x00DE, 0x00FE,
  0x00E0, 0x0061,		// 0061 0300
  0x00E1, 0x0061,		// 0061 0301
  0x00E2, 0x0061,		// 0061 0302
  0x00E3, 0x0061,		// 0061 0303
  0x00E4, 0x0061,		// 0061 0308
  0x00E5, 0x0061,		// 0061 030A
  0x00E7, 0x0063,		// 0063 0327
  0x00E8, 0x0065,		// 0065 0300
  0x00E9, 0x0065,		// 0065 0301
  0x00EA, 0x0065,		// 0065 0302
  0x00EB, 0x0065,		// 0065 0308
  0x00EC, 0x0069,		// 0069 0300
  0x00ED, 0x0069,		// 0069 0301
  0x00EE, 0x0069,		// 0069 0302
  0x00EF, 0x0069,		// 0069 0308
  0x00F1, 0x006E,		// 006E 0303
  0x00F2, 0x006F,		// 006F 0300
  0x00F3, 0x006F,		// 006F 0301
  0x00F4, 0x006F,		// 006F 0302
  0x00F5, 0x006F,		// 006F 0303
  0x00F6, 0x006F,		// 006F 0308
  0x00F9, 0x0075,		// 0075 0300
  0x00FA, 0x0075,		// 0075 0301
  0x00FB, 0x0075,		// 0075 0302
  0x00FC, 0x0075,		// 0075 0308
  0x00FD, 0x0079,		// 0079 0301
  0x00FF, 0x0079,		// 0079 0308
];
  var LowerCase01 = [
    0x100, 0x061,		// 0041 0304
    0x101, 0x061,		// 0061 0304
    0x102, 0x061,		// 0041 0306
    0x103, 0x061,		// 0061 0306
    0x104, 0x061,		// 0041 0328
    0x105, 0x061,		// 0061 0328
    0x106, 0x063,		// 0043 0301
    0x107, 0x063,		// 0063 0301
    0x108, 0x063,		// 0043 0302
    0x109, 0x063,		// 0063 0302
    0x10A, 0x063,		// 0043 0307
    0x10B, 0x063,		// 0063 0307
    0x10C, 0x063,		// 0043 030C
    0x10D, 0x063,		// 0063 030C
    0x10E, 0x064,		// 0044 030C
    0x10F, 0x064,		// 0064 030C
    0x110, 0x111,
    0x112, 0x065,		// 0045 0304
    0x113, 0x065,		// 0065 0304
    0x114, 0x065,		// 0045 0306
    0x115, 0x065,		// 0065 0306
    0x116, 0x065,		// 0045 0307
    0x117, 0x065,		// 0065 0307
    0x118, 0x065,		// 0045 0328
    0x119, 0x065,		// 0065 0328
    0x11A, 0x065,		// 0045 030C
    0x11B, 0x065,		// 0065 030C
    0x11C, 0x067,		// 0047 0302
    0x11D, 0x067,		// 0067 0302
    0x11E, 0x067,		// 0047 0306
    0x11F, 0x067,		// 0067 0306
    0x120, 0x067,		// 0047 0307
    0x121, 0x067,		// 0067 0307
    0x122, 0x067,		// 0047 0327
    0x123, 0x067,		// 0067 0327
    0x124, 0x068,		// 0048 0302
    0x125, 0x068,		// 0068 0302
    0x126, 0x127,
    0x128, 0x069,		// 0049 0303
    0x129, 0x069,		// 0069 0303
    0x12A, 0x069,		// 0049 0304
    0x12B, 0x069,		// 0069 0304
    0x12C, 0x069,		// 0049 0306
    0x12D, 0x069,		// 0069 0306
    0x12E, 0x069,		// 0049 0328
    0x12F, 0x069,		// 0069 0328
    0x130, 0x069,		// 0049 0307
    0x132, 0x133,		// <compat> 0049 004A
    0x134, 0x06A,		// 004A 0302
    0x135, 0x06A,		// 006A 0302
    0x136, 0x06B,		// 004B 0327
    0x137, 0x06B,		// 006B 0327
    0x139, 0x06C,		// 004C 0301
    0x13A, 0x06C,		// 006C 0301
    0x13B, 0x06C,		// 004C 0327
    0x13C, 0x06C,		// 006C 0327
    0x13D, 0x06C,		// 004C 030C
    0x13E, 0x06C,		// 006C 030C
    0x13F, 0x140,		// <compat> 004C 00B7
    0x141, 0x142,
    0x143, 0x06E,		// 004E 0301
    0x144, 0x06E,		// 006E 0301
    0x145, 0x06E,		// 004E 0327
    0x146, 0x06E,		// 006E 0327
    0x147, 0x06E,		// 004E 030C
    0x148, 0x06E,		// 006E 030C
    0x14A, 0x14B,
    0x14C, 0x06F,		// 004F 0304
    0x14D, 0x06F,		// 006F 0304
    0x14E, 0x06F,		// 004F 0306
    0x14F, 0x06F,		// 006F 0306
    0x150, 0x06F,		// 004F 030B
    0x151, 0x06F,		// 006F 030B
    0x152, 0x153,
    0x154, 0x072,		// 0052 0301
    0x155, 0x072,		// 0072 0301
    0x156, 0x072,		// 0052 0327
    0x157, 0x072,		// 0072 0327
    0x158, 0x072,		// 0052 030C
    0x159, 0x072,		// 0072 030C
    0x15A, 0x073,		// 0053 0301
    0x15B, 0x073,		// 0073 0301
    0x15C, 0x073,		// 0053 0302
    0x15D, 0x073,		// 0073 0302
    0x15E, 0x073,		// 0053 0327
    0x15F, 0x073,		// 0073 0327
    0x160, 0x073,		// 0053 030C
    0x161, 0x073,		// 0073 030C
    0x162, 0x074,		// 0054 0327
    0x163, 0x074,		// 0074 0327
    0x164, 0x074,		// 0054 030C
    0x165, 0x074,		// 0074 030C
    0x166, 0x167,
    0x168, 0x075,		// 0055 0303
    0x169, 0x075,		// 0075 0303
    0x16A, 0x075,		// 0055 0304
    0x16B, 0x075,		// 0075 0304
    0x16C, 0x075,		// 0055 0306
    0x16D, 0x075,		// 0075 0306
    0x16E, 0x075,		// 0055 030A
    0x16F, 0x075,		// 0075 030A
    0x170, 0x075,		// 0055 030B
    0x171, 0x075,		// 0075 030B
    0x172, 0x075,		// 0055 0328
    0x173, 0x075,		// 0075 0328
    0x174, 0x077,		// 0057 0302
    0x175, 0x077,		// 0077 0302
    0x176, 0x079,		// 0059 0302
    0x177, 0x079,		// 0079 0302
    0x178, 0x079,		// 0059 0308
    0x179, 0x07A,		// 005A 0301
    0x17A, 0x07A,		// 007A 0301
    0x17B, 0x07A,		// 005A 0307
    0x17C, 0x07A,		// 007A 0307
    0x17D, 0x07A,		// 005A 030C
    0x17E, 0x07A,		// 007A 030C
    0x181, 0x253,
    0x182, 0x183,
    0x184, 0x185,
    0x186, 0x254,
    0x187, 0x188,
    0x189, 0x256,
    0x18A, 0x257,
    0x18B, 0x18C,
    0x18E, 0x1DD,
    0x18F, 0x259,
    0x190, 0x25B,
    0x191, 0x192,
    0x193, 0x260,
    0x194, 0x263,
    0x196, 0x269,
    0x197, 0x268,
    0x198, 0x199,
    0x19C, 0x26F,
    0x19D, 0x272,
    0x19F, 0x275,
    0x1A0, 0x06F,		// 004F 031B
    0x1A1, 0x06F,		// 006F 031B
    0x1A2, 0x1A3,
    0x1A4, 0x1A5,
    0x1A6, 0x280,
    0x1A7, 0x1A8,
    0x1A9, 0x283,
    0x1AC, 0x1AD,
    0x1AE, 0x288,
    0x1AF, 0x075,		// 0055 031B
    0x1B0, 0x075,		// 0075 031B
    0x1B1, 0x28A,
    0x1B2, 0x28B,
    0x1B3, 0x1B4,
    0x1B5, 0x1B6,
    0x1B7, 0x292,
    0x1B8, 0x1B9,
    0x1BC, 0x1BD,
    0x1C4, 0x1C6,		// <compat> 0044 017D
    0x1C5, 0x1C6,		// <compat> 0044 017E
    0x1C7, 0x1C9,		// <compat> 004C 004A
    0x1C8, 0x1C9,		// <compat> 004C 006A
    0x1CA, 0x1CC,		// <compat> 004E 004A
    0x1CB, 0x1CC,		// <compat> 004E 006A
    0x1CD, 0x061,		// 0041 030C
    0x1CE, 0x061,		// 0061 030C
    0x1CF, 0x069,		// 0049 030C
    0x1D0, 0x069,		// 0069 030C
    0x1D1, 0x06F,		// 004F 030C
    0x1D2, 0x06F,		// 006F 030C
    0x1D3, 0x075,		// 0055 030C
    0x1D4, 0x075,		// 0075 030C
    0x1D5, 0x075,		// 00DC 0304
    0x1D6, 0x075,		// 00FC 0304
    0x1D7, 0x075,		// 00DC 0301
    0x1D8, 0x075,		// 00FC 0301
    0x1D9, 0x075,		// 00DC 030C
    0x1DA, 0x075,		// 00FC 030C
    0x1DB, 0x075,		// 00DC 0300
    0x1DC, 0x075,		// 00FC 0300
    0x1DE, 0x061,		// 00C4 0304
    0x1DF, 0x061,		// 00E4 0304
    0x1E0, 0x061,		// 0041 0307 0304
    0x1E1, 0x061,		// 0061 0307 0304
    0x1E2, 0x0E6,		// 00C6 0304
    0x1E3, 0x0E6,		// 00E6 0304
    0x1E4, 0x1E5,
    0x1E6, 0x067,		// 0047 030C
    0x1E7, 0x067,		// 0067 030C
    0x1E8, 0x06B,		// 004B 030C
    0x1E9, 0x06B,		// 006B 030C
    0x1EA, 0x06F,		// 004F 0328
    0x1EB, 0x06F,		// 006F 0328
    0x1EC, 0x06F,		// 01EA 0304
    0x1ED, 0x06F,		// 01EB 0304
    0x1EE, 0x292,		// 01B7 030C
    0x1EF, 0x292,		// 0292 030C
    0x1F0, 0x06A,		// 006A 030C
    0x1F1, 0x1F3,		// <compat> 0044 005A
    0x1F2, 0x1F3,		// <compat> 0044 007A
    0x1F4, 0x067,		// 0047 0301
    0x1F5, 0x067,		// 0067 0301
    0x1FA, 0x061,		// 00C5 0301
    0x1FB, 0x061,		// 00E5 0301
    0x1FC, 0x0E6,		// 00C6 0301
    0x1FD, 0x0E6,		// 00E6 0301
    0x1FE, 0x0F8,		// 00D8 0301
    0x1FF, 0x0F8,		// 00F8 0301
  ];
  var LowerCase02 = [
    0x200, 0x061,		// 0041 030F
    0x201, 0x061,		// 0061 030F
    0x202, 0x061,		// 0041 0311
    0x203, 0x061,		// 0061 0311
    0x204, 0x065,		// 0045 030F
    0x205, 0x065,		// 0065 030F
    0x206, 0x065,		// 0045 0311
    0x207, 0x065,		// 0065 0311
    0x208, 0x069,		// 0049 030F
    0x209, 0x069,		// 0069 030F
    0x20A, 0x069,		// 0049 0311
    0x20B, 0x069,		// 0069 0311
    0x20C, 0x06F,		// 004F 030F
    0x20D, 0x06F,		// 006F 030F
    0x20E, 0x06F,		// 004F 0311
    0x20F, 0x06F,		// 006F 0311
    0x210, 0x072,		// 0052 030F
    0x211, 0x072,		// 0072 030F
    0x212, 0x072,		// 0052 0311
    0x213, 0x072,		// 0072 0311
    0x214, 0x075,		// 0055 030F
    0x215, 0x075,		// 0075 030F
    0x216, 0x075,		// 0055 0311
    0x217, 0x075,		// 0075 0311
  ];
  var LowerCase03 = [
    0x340, 0x300,		// 0300
    0x341, 0x301,		// 0301
    0x343, 0x313,		// 0313
    0x344, 0x308,		// 0308 0301
    0x374, 0x2B9,		// 02B9
    0x37E, 0x03B,		// 003B
    0x385, 0x0A8,		// 00A8 0301
    0x386, 0x3B1,		// 0391 0301
    0x387, 0x0B7,		// 00B7
    0x388, 0x3B5,		// 0395 0301
    0x389, 0x3B7,		// 0397 0301
    0x38A, 0x3B9,		// 0399 0301
    0x38C, 0x3BF,		// 039F 0301
    0x38E, 0x3C5,		// 03A5 0301
    0x38F, 0x3C9,		// 03A9 0301
    0x390, 0x3B9,		// 03CA 0301
    0x391, 0x3B1,
    0x392, 0x3B2,
    0x393, 0x3B3,
    0x394, 0x3B4,
    0x395, 0x3B5,
    0x396, 0x3B6,
    0x397, 0x3B7,
    0x398, 0x3B8,
    0x399, 0x3B9,
    0x39A, 0x3BA,
    0x39B, 0x3BB,
    0x39C, 0x3BC,
    0x39D, 0x3BD,
    0x39E, 0x3BE,
    0x39F, 0x3BF,
    0x3A0, 0x3C0,
    0x3A1, 0x3C1,
    0x3A3, 0x3C3,
    0x3A4, 0x3C4,
    0x3A5, 0x3C5,
    0x3A6, 0x3C6,
    0x3A7, 0x3C7,
    0x3A8, 0x3C8,
    0x3A9, 0x3C9,
    0x3AA, 0x3B9,		// 0399 0308
    0x3AB, 0x3C5,		// 03A5 0308
    0x3AC, 0x3B1,		// 03B1 0301
    0x3AD, 0x3B5,		// 03B5 0301
    0x3AE, 0x3B7,		// 03B7 0301
    0x3AF, 0x3B9,		// 03B9 0301
    0x3B0, 0x3C5,		// 03CB 0301
    0x3CA, 0x3B9,		// 03B9 0308
    0x3CB, 0x3C5,		// 03C5 0308
    0x3CC, 0x3BF,		// 03BF 0301
    0x3CD, 0x3C5,		// 03C5 0301
    0x3CE, 0x3C9,		// 03C9 0301
    0x3D3, 0x3D2,		// 03D2 0301
    0x3D4, 0x3D2,		// 03D2 0308
    0x3E2, 0x3E3,
    0x3E4, 0x3E5,
    0x3E6, 0x3E7,
    0x3E8, 0x3E9,
    0x3EA, 0x3EB,
    0x3EC, 0x3ED,
    0x3EE, 0x3EF,
  ];
  var LowerCase04 = [
    0x401, 0x435,		// 0415 0308
    0x402, 0x452,
    0x403, 0x433,		// 0413 0301
    0x404, 0x454,
    0x405, 0x455,
    0x406, 0x456,
    0x407, 0x456,		// 0406 0308
    0x408, 0x458,
    0x409, 0x459,
    0x40A, 0x45A,
    0x40B, 0x45B,
    0x40C, 0x43A,		// 041A 0301
    0x40E, 0x443,		// 0423 0306
    0x40F, 0x45F,
    0x410, 0x430,
    0x411, 0x431,
    0x412, 0x432,
    0x413, 0x433,
    0x414, 0x434,
    0x415, 0x435,
    0x416, 0x436,
    0x417, 0x437,
    0x418, 0x438,
    0x419, 0x438,		// 0418 0306
    0x41A, 0x43A,
    0x41B, 0x43B,
    0x41C, 0x43C,
    0x41D, 0x43D,
    0x41E, 0x43E,
    0x41F, 0x43F,
    0x420, 0x440,
    0x421, 0x441,
    0x422, 0x442,
    0x423, 0x443,
    0x424, 0x444,
    0x425, 0x445,
    0x426, 0x446,
    0x427, 0x447,
    0x428, 0x448,
    0x429, 0x449,
    0x42A, 0x44A,
    0x42B, 0x44B,
    0x42C, 0x44C,
    0x42D, 0x44D,
    0x42E, 0x44E,
    0x42F, 0x44F,
    0x439, 0x438,		// 0438 0306
    0x451, 0x435,		// 0435 0308
    0x453, 0x433,		// 0433 0301
    0x457, 0x456,		// 0456 0308
    0x45C, 0x43A,		// 043A 0301
    0x45E, 0x443,		// 0443 0306
    0x460, 0x461,
    0x462, 0x463,
    0x464, 0x465,
    0x466, 0x467,
    0x468, 0x469,
    0x46A, 0x46B,
    0x46C, 0x46D,
    0x46E, 0x46F,
    0x470, 0x471,
    0x472, 0x473,
    0x474, 0x475,
    0x476, 0x475,		// 0474 030F
    0x477, 0x475,		// 0475 030F
    0x478, 0x479,
    0x47A, 0x47B,
    0x47C, 0x47D,
    0x47E, 0x47F,
    0x480, 0x481,
    0x490, 0x491,
    0x492, 0x493,
    0x494, 0x495,
    0x496, 0x497,
    0x498, 0x499,
    0x49A, 0x49B,
    0x49C, 0x49D,
    0x49E, 0x49F,
    0x4A0, 0x4A1,
    0x4A2, 0x4A3,
    0x4A4, 0x4A5,
    0x4A6, 0x4A7,
    0x4A8, 0x4A9,
    0x4AA, 0x4AB,
    0x4AC, 0x4AD,
    0x4AE, 0x4AF,
    0x4B0, 0x4B1,
    0x4B2, 0x4B3,
    0x4B4, 0x4B5,
    0x4B6, 0x4B7,
    0x4B8, 0x4B9,
    0x4BA, 0x4BB,
    0x4BC, 0x4BD,
    0x4BE, 0x4BF,
    0x4C1, 0x436,		// 0416 0306
    0x4C2, 0x436,		// 0436 0306
    0x4C3, 0x4C4,
    0x4C7, 0x4C8,
    0x4CB, 0x4CC,
    0x4D0, 0x430,		// 0410 0306
    0x4D1, 0x430,		// 0430 0306
    0x4D2, 0x430,		// 0410 0308
    0x4D3, 0x430,		// 0430 0308
    0x4D4, 0x4D5,
    0x4D6, 0x435,		// 0415 0306
    0x4D7, 0x435,		// 0435 0306
    0x4D8, 0x4D9,
    0x4DA, 0x4D9,		// 04D8 0308
    0x4DB, 0x4D9,		// 04D9 0308
    0x4DC, 0x436,		// 0416 0308
    0x4DD, 0x436,		// 0436 0308
    0x4DE, 0x437,		// 0417 0308
    0x4DF, 0x437,		// 0437 0308
    0x4E0, 0x4E1,
    0x4E2, 0x438,		// 0418 0304
    0x4E3, 0x438,		// 0438 0304
    0x4E4, 0x438,		// 0418 0308
    0x4E5, 0x438,		// 0438 0308
    0x4E6, 0x43E,		// 041E 0308
    0x4E7, 0x43E,		// 043E 0308
    0x4E8, 0x4E9,
    0x4EA, 0x4E9,		// 04E8 0308
    0x4EB, 0x4E9,		// 04E9 0308
    0x4EE, 0x443,		// 0423 0304
    0x4EF, 0x443,		// 0443 0304
    0x4F0, 0x443,		// 0423 0308
    0x4F1, 0x443,		// 0443 0308
    0x4F2, 0x443,		// 0423 030B
    0x4F3, 0x443,		// 0443 030B
    0x4F4, 0x447,		// 0427 0308
    0x4F5, 0x447,		// 0447 0308
    0x4F8, 0x44B,		// 042B 0308
    0x4F9, 0x44B,		// 044B 0308
  ];
  var LowerCase05 = [
    0x531, 0x561,
    0x532, 0x562,
    0x533, 0x563,
    0x534, 0x564,
    0x535, 0x565,
    0x536, 0x566,
    0x537, 0x567,
    0x538, 0x568,
    0x539, 0x569,
    0x53A, 0x56A,
    0x53B, 0x56B,
    0x53C, 0x56C,
    0x53D, 0x56D,
    0x53E, 0x56E,
    0x53F, 0x56F,
    0x540, 0x570,
    0x541, 0x571,
    0x542, 0x572,
    0x543, 0x573,
    0x544, 0x574,
    0x545, 0x575,
    0x546, 0x576,
    0x547, 0x577,
    0x548, 0x578,
    0x549, 0x579,
    0x54A, 0x57A,
    0x54B, 0x57B,
    0x54C, 0x57C,
    0x54D, 0x57D,
    0x54E, 0x57E,
    0x54F, 0x57F,
    0x550, 0x580,
    0x551, 0x581,
    0x552, 0x582,
    0x553, 0x583,
    0x554, 0x584,
    0x555, 0x585,
    0x556, 0x586,
  ];
var LowerCase06 = [
  0x622, 0x627,
  0x623, 0x627,
  0x625, 0x627,
  0x649, 0x64A,
  0x647, 0x629,
  0x624, 0x648,
];
var LowerCase09 = [
  0x929, 0x928,		// 0928 093C
  0x931, 0x930,		// 0930 093C
  0x934, 0x933,		// 0933 093C
  0x958, 0x915,		// 0915 093C
  0x959, 0x916,		// 0916 093C
  0x95A, 0x917,		// 0917 093C
  0x95B, 0x91C,		// 091C 093C
  0x95C, 0x921,		// 0921 093C
  0x95D, 0x922,		// 0922 093C
  0x95E, 0x92B,		// 092B 093C
  0x95F, 0x92F,		// 092F 093C
  0x9B0, 0x9AC,		// 09AC 09BC
  0x9CB, 0x9C7,		// 09C7 09BE
  0x9CC, 0x9C7,		// 09C7 09D7
  0x9DC, 0x9A1,		// 09A1 09BC
  0x9DD, 0x9A2,		// 09A2 09BC
  0x9DF, 0x9AF,		// 09AF 09BC
];
var LowerCase0A = [
  0xA59, 0xA16,		// 0A16 0A3C
  0xA5A, 0xA17,		// 0A17 0A3C
  0xA5B, 0xA1C,		// 0A1C 0A3C
  0xA5C, 0xA21,		// 0A21 0A3C
  0xA5E, 0xA2B,		// 0A2B 0A3C
];
var LowerCase0B = [
  0xB48, 0xB47,		// 0B47 0B56
  0xB4B, 0xB47,		// 0B47 0B3E
  0xB4C, 0xB47,		// 0B47 0B57
  0xB5C, 0xB21,		// 0B21 0B3C
  0xB5D, 0xB22,		// 0B22 0B3C
  0xB5F, 0xB2F,		// 0B2F 0B3C
  0xB94, 0xB92,		// 0B92 0BD7
  0xBCA, 0xBC6,		// 0BC6 0BBE
  0xBCB, 0xBC7,		// 0BC7 0BBE
  0xBCC, 0xBC6,		// 0BC6 0BD7
];
var LowerCase0C = [
  0xC48, 0xC46,		// 0C46 0C56
  0xCC0, 0xCBF,		// 0CBF 0CD5
  0xCC7, 0xCC6,		// 0CC6 0CD5
  0xCC8, 0xCC6,		// 0CC6 0CD6
  0xCCA, 0xCC6,		// 0CC6 0CC2
  0xCCB, 0xCC6,		// 0CCA 0CD5
];
var LowerCase0D = [
  0xD4A, 0xD46,		// 0D46 0D3E
  0xD4B, 0xD47,		// 0D47 0D3E
  0xD4C, 0xD46,		// 0D46 0D57
];
var LowerCase0E = [
  0xE33, 0xE4D,		// 0E4D 0E32
  0xEB3, 0xECD,		// 0ECD 0EB2
];
var LowerCase0F = [
  0xF43, 0xF42,		// 0F42 0FB7
  0xF4D, 0xF4C,		// 0F4C 0FB7
  0xF52, 0xF51,		// 0F51 0FB7
  0xF57, 0xF56,		// 0F56 0FB7
  0xF5C, 0xF5B,		// 0F5B 0FB7
  0xF69, 0xF40,		// 0F40 0FB5
  0xF73, 0xF71,		// 0F71 0F72
  0xF75, 0xF71,		// 0F71 0F74
  0xF76, 0xFB2,		// 0FB2 0F80
  0xF78, 0xFB3,		// 0FB3 0F80
  0xF81, 0xF71,		// 0F71 0F80
  0xF93, 0xF92,		// 0F92 0FB7
  0xF9D, 0xF9C,		// 0F9C 0FB7
  0xFA2, 0xFA1,		// 0FA1 0FB7
  0xFA7, 0xFA6,		// 0FA6 0FB7
  0xFAC, 0xFAB,		// 0FAB 0FB7
  0xFB9, 0xF90,		// 0F90 0FB5
];
var LowerCase10 = [
  0x10A0, 0x10D0,
  0x10A1, 0x10D1,
  0x10A2, 0x10D2,
  0x10A3, 0x10D3,
  0x10A4, 0x10D4,
  0x10A5, 0x10D5,
  0x10A6, 0x10D6,
  0x10A7, 0x10D7,
  0x10A8, 0x10D8,
  0x10A9, 0x10D9,
  0x10AA, 0x10DA,
  0x10AB, 0x10DB,
  0x10AC, 0x10DC,
  0x10AD, 0x10DD,
  0x10AE, 0x10DE,
  0x10AF, 0x10DF,
  0x10B0, 0x10E0,
  0x10B1, 0x10E1,
  0x10B2, 0x10E2,
  0x10B3, 0x10E3,
  0x10B4, 0x10E4,
  0x10B5, 0x10E5,
  0x10B6, 0x10E6,
  0x10B7, 0x10E7,
  0x10B8, 0x10E8,
  0x10B9, 0x10E9,
  0x10BA, 0x10EA,
  0x10BB, 0x10EB,
  0x10BC, 0x10EC,
  0x10BD, 0x10ED,
  0x10BE, 0x10EE,
  0x10BF, 0x10EF,
  0x10C0, 0x10F0,
  0x10C1, 0x10F1,
  0x10C2, 0x10F2,
  0x10C3, 0x10F3,
  0x10C4, 0x10F4,
  0x10C5, 0x10F5,
];
var LowerCase1E = [
  0x1E00, 0x061,		// 0041 0325
  0x1E01, 0x061,		// 0061 0325
  0x1E02, 0x062,		// 0042 0307
  0x1E03, 0x062,		// 0062 0307
  0x1E04, 0x062,		// 0042 0323
  0x1E05, 0x062,		// 0062 0323
  0x1E06, 0x062,		// 0042 0331
  0x1E07, 0x062,		// 0062 0331
  0x1E08, 0x063,		// 00C7 0301
  0x1E09, 0x063,		// 00E7 0301
  0x1E0A, 0x064,		// 0044 0307
  0x1E0B, 0x064,		// 0064 0307
  0x1E0C, 0x064,		// 0044 0323
  0x1E0D, 0x064,		// 0064 0323
  0x1E0E, 0x064,		// 0044 0331
  0x1E0F, 0x064,		// 0064 0331
  0x1E10, 0x064,		// 0044 0327
  0x1E11, 0x064,		// 0064 0327
  0x1E12, 0x064,		// 0044 032D
  0x1E13, 0x064,		// 0064 032D
  0x1E14, 0x065,		// 0112 0300
  0x1E15, 0x065,		// 0113 0300
  0x1E16, 0x065,		// 0112 0301
  0x1E17, 0x065,		// 0113 0301
  0x1E18, 0x065,		// 0045 032D
  0x1E19, 0x065,		// 0065 032D
  0x1E1A, 0x065,		// 0045 0330
  0x1E1B, 0x065,		// 0065 0330
  0x1E1C, 0x065,		// 0045 0327 0306
  0x1E1D, 0x065,		// 0065 0327 0306
  0x1E1E, 0x066,		// 0046 0307
  0x1E1F, 0x066,		// 0066 0307
  0x1E20, 0x067,		// 0047 0304
  0x1E21, 0x067,		// 0067 0304
  0x1E22, 0x068,		// 0048 0307
  0x1E23, 0x068,		// 0068 0307
  0x1E24, 0x068,		// 0048 0323
  0x1E25, 0x068,		// 0068 0323
  0x1E26, 0x068,		// 0048 0308
  0x1E27, 0x068,		// 0068 0308
  0x1E28, 0x068,		// 0048 0327
  0x1E29, 0x068,		// 0068 0327
  0x1E2A, 0x068,		// 0048 032E
  0x1E2B, 0x068,		// 0068 032E
  0x1E2C, 0x069,		// 0049 0330
  0x1E2D, 0x069,		// 0069 0330
  0x1E2E, 0x069,		// 00CF 0301
  0x1E2F, 0x069,		// 00EF 0301
  0x1E30, 0x06B,		// 004B 0301
  0x1E31, 0x06B,		// 006B 0301
  0x1E32, 0x06B,		// 004B 0323
  0x1E33, 0x06B,		// 006B 0323
  0x1E34, 0x06B,		// 004B 0331
  0x1E35, 0x06B,		// 006B 0331
  0x1E36, 0x06C,		// 004C 0323
  0x1E37, 0x06C,		// 006C 0323
  0x1E38, 0x06C,		// 1E36 0304
  0x1E39, 0x06C,		// 1E37 0304
  0x1E3A, 0x06C,		// 004C 0331
  0x1E3B, 0x06C,		// 006C 0331
  0x1E3C, 0x06C,		// 004C 032D
  0x1E3D, 0x06C,		// 006C 032D
  0x1E3E, 0x06D,		// 004D 0301
  0x1E3F, 0x06D,		// 006D 0301
  0x1E40, 0x06D,		// 004D 0307
  0x1E41, 0x06D,		// 006D 0307
  0x1E42, 0x06D,		// 004D 0323
  0x1E43, 0x06D,		// 006D 0323
  0x1E44, 0x06E,		// 004E 0307
  0x1E45, 0x06E,		// 006E 0307
  0x1E46, 0x06E,		// 004E 0323
  0x1E47, 0x06E,		// 006E 0323
  0x1E48, 0x06E,		// 004E 0331
  0x1E49, 0x06E,		// 006E 0331
  0x1E4A, 0x06E,		// 004E 032D
  0x1E4B, 0x06E,		// 006E 032D
  0x1E4C, 0x06F,		// 00D5 0301
  0x1E4D, 0x06F,		// 00F5 0301
  0x1E4E, 0x06F,		// 00D5 0308
  0x1E4F, 0x06F,		// 00F5 0308
  0x1E50, 0x06F,		// 014C 0300
  0x1E51, 0x06F,		// 014D 0300
  0x1E52, 0x06F,		// 014C 0301
  0x1E53, 0x06F,		// 014D 0301
  0x1E54, 0x070,		// 0050 0301
  0x1E55, 0x070,		// 0070 0301
  0x1E56, 0x070,		// 0050 0307
  0x1E57, 0x070,		// 0070 0307
  0x1E58, 0x072,		// 0052 0307
  0x1E59, 0x072,		// 0072 0307
  0x1E5A, 0x072,		// 0052 0323
  0x1E5B, 0x072,		// 0072 0323
  0x1E5C, 0x072,		// 1E5A 0304
  0x1E5D, 0x072,		// 1E5B 0304
  0x1E5E, 0x072,		// 0052 0331
  0x1E5F, 0x072,		// 0072 0331
  0x1E60, 0x073,		// 0053 0307
  0x1E61, 0x073,		// 0073 0307
  0x1E62, 0x073,		// 0053 0323
  0x1E63, 0x073,		// 0073 0323
  0x1E64, 0x073,		// 015A 0307
  0x1E65, 0x073,		// 015B 0307
  0x1E66, 0x073,		// 0160 0307
  0x1E67, 0x073,		// 0161 0307
  0x1E68, 0x073,		// 1E62 0307
  0x1E69, 0x073,		// 1E63 0307
  0x1E6A, 0x074,		// 0054 0307
  0x1E6B, 0x074,		// 0074 0307
  0x1E6C, 0x074,		// 0054 0323
  0x1E6D, 0x074,		// 0074 0323
  0x1E6E, 0x074,		// 0054 0331
  0x1E6F, 0x074,		// 0074 0331
  0x1E70, 0x074,		// 0054 032D
  0x1E71, 0x074,		// 0074 032D
  0x1E72, 0x075,		// 0055 0324
  0x1E73, 0x075,		// 0075 0324
  0x1E74, 0x075,		// 0055 0330
  0x1E75, 0x075,		// 0075 0330
  0x1E76, 0x075,		// 0055 032D
  0x1E77, 0x075,		// 0075 032D
  0x1E78, 0x075,		// 0168 0301
  0x1E79, 0x075,		// 0169 0301
  0x1E7A, 0x075,		// 016A 0308
  0x1E7B, 0x075,		// 016B 0308
  0x1E7C, 0x076,		// 0056 0303
  0x1E7D, 0x076,		// 0076 0303
  0x1E7E, 0x076,		// 0056 0323
  0x1E7F, 0x076,		// 0076 0323
  0x1E80, 0x077,		// 0057 0300
  0x1E81, 0x077,		// 0077 0300
  0x1E82, 0x077,		// 0057 0301
  0x1E83, 0x077,		// 0077 0301
  0x1E84, 0x077,		// 0057 0308
  0x1E85, 0x077,		// 0077 0308
  0x1E86, 0x077,		// 0057 0307
  0x1E87, 0x077,		// 0077 0307
  0x1E88, 0x077,		// 0057 0323
  0x1E89, 0x077,		// 0077 0323
  0x1E8A, 0x078,		// 0058 0307
  0x1E8B, 0x078,		// 0078 0307
  0x1E8C, 0x078,		// 0058 0308
  0x1E8D, 0x078,		// 0078 0308
  0x1E8E, 0x079,		// 0059 0307
  0x1E8F, 0x079,		// 0079 0307
  0x1E90, 0x07A,		// 005A 0302
  0x1E91, 0x07A,		// 007A 0302
  0x1E92, 0x07A,		// 005A 0323
  0x1E93, 0x07A,		// 007A 0323
  0x1E94, 0x07A,		// 005A 0331
  0x1E95, 0x07A,		// 007A 0331
  0x1E96, 0x068,		// 0068 0331
  0x1E97, 0x074,		// 0074 0308
  0x1E98, 0x077,		// 0077 030A
  0x1E99, 0x079,		// 0079 030A
  0x1E9B, 0x17F,		// 017F 0307
  0x1EA0, 0x061,		// 0041 0323
  0x1EA1, 0x061,		// 0061 0323
  0x1EA2, 0x061,		// 0041 0309
  0x1EA3, 0x061,		// 0061 0309
  0x1EA4, 0x061,		// 00C2 0301
  0x1EA5, 0x061,		// 00E2 0301
  0x1EA6, 0x061,		// 00C2 0300
  0x1EA7, 0x061,		// 00E2 0300
  0x1EA8, 0x061,		// 00C2 0309
  0x1EA9, 0x061,		// 00E2 0309
  0x1EAA, 0x061,		// 00C2 0303
  0x1EAB, 0x061,		// 00E2 0303
  0x1EAC, 0x061,		// 1EA0 0302
  0x1EAD, 0x061,		// 1EA1 0302
  0x1EAE, 0x061,		// 0102 0301
  0x1EAF, 0x061,		// 0103 0301
  0x1EB0, 0x061,		// 0102 0300
  0x1EB1, 0x061,		// 0103 0300
  0x1EB2, 0x061,		// 0102 0309
  0x1EB3, 0x061,		// 0103 0309
  0x1EB4, 0x061,		// 0102 0303
  0x1EB5, 0x061,		// 0103 0303
  0x1EB6, 0x061,		// 1EA0 0306
  0x1EB7, 0x061,		// 1EA1 0306
  0x1EB8, 0x065,		// 0045 0323
  0x1EB9, 0x065,		// 0065 0323
  0x1EBA, 0x065,		// 0045 0309
  0x1EBB, 0x065,		// 0065 0309
  0x1EBC, 0x065,		// 0045 0303
  0x1EBD, 0x065,		// 0065 0303
  0x1EBE, 0x065,		// 00CA 0301
  0x1EBF, 0x065,		// 00EA 0301
  0x1EC0, 0x065,		// 00CA 0300
  0x1EC1, 0x065,		// 00EA 0300
  0x1EC2, 0x065,		// 00CA 0309
  0x1EC3, 0x065,		// 00EA 0309
  0x1EC4, 0x065,		// 00CA 0303
  0x1EC5, 0x065,		// 00EA 0303
  0x1EC6, 0x065,		// 1EB8 0302
  0x1EC7, 0x065,		// 1EB9 0302
  0x1EC8, 0x069,		// 0049 0309
  0x1EC9, 0x069,		// 0069 0309
  0x1ECA, 0x069,		// 0049 0323
  0x1ECB, 0x069,		// 0069 0323
  0x1ECC, 0x06F,		// 004F 0323
  0x1ECD, 0x06F,		// 006F 0323
  0x1ECE, 0x06F,		// 004F 0309
  0x1ECF, 0x06F,		// 006F 0309
  0x1ED0, 0x06F,		// 00D4 0301
  0x1ED1, 0x06F,		// 00F4 0301
  0x1ED2, 0x06F,		// 00D4 0300
  0x1ED3, 0x06F,		// 00F4 0300
  0x1ED4, 0x06F,		// 00D4 0309
  0x1ED5, 0x06F,		// 00F4 0309
  0x1ED6, 0x06F,		// 00D4 0303
  0x1ED7, 0x06F,		// 00F4 0303
  0x1ED8, 0x06F,		// 1ECC 0302
  0x1ED9, 0x06F,		// 1ECD 0302
  0x1EDA, 0x06F,		// 01A0 0301
  0x1EDB, 0x06F,		// 01A1 0301
  0x1EDC, 0x06F,		// 01A0 0300
  0x1EDD, 0x06F,		// 01A1 0300
  0x1EDE, 0x06F,		// 01A0 0309
  0x1EDF, 0x06F,		// 01A1 0309
  0x1EE0, 0x06F,		// 01A0 0303
  0x1EE1, 0x06F,		// 01A1 0303
  0x1EE2, 0x06F,		// 01A0 0323
  0x1EE3, 0x06F,		// 01A1 0323
  0x1EE4, 0x075,		// 0055 0323
  0x1EE5, 0x075,		// 0075 0323
  0x1EE6, 0x075,		// 0055 0309
  0x1EE7, 0x075,		// 0075 0309
  0x1EE8, 0x075,		// 01AF 0301
  0x1EE9, 0x075,		// 01B0 0301
  0x1EEA, 0x075,		// 01AF 0300
  0x1EEB, 0x075,		// 01B0 0300
  0x1EEC, 0x075,		// 01AF 0309
  0x1EED, 0x075,		// 01B0 0309
  0x1EEE, 0x075,		// 01AF 0303
  0x1EEF, 0x075,		// 01B0 0303
  0x1EF0, 0x075,		// 01AF 0323
  0x1EF1, 0x075,		// 01B0 0323
  0x1EF2, 0x079,		// 0059 0300
  0x1EF3, 0x079,		// 0079 0300
  0x1EF4, 0x079,		// 0059 0323
  0x1EF5, 0x079,		// 0079 0323
  0x1EF6, 0x079,		// 0059 0309
  0x1EF7, 0x079,		// 0079 0309
  0x1EF8, 0x079,		// 0059 0303
  0x1EF9, 0x079,		// 0079 0303
];
var LowerCase1F = [
  0x1F00, 0x3B1,		// 03B1 0313
  0x1F01, 0x3B1,		// 03B1 0314
  0x1F02, 0x3B1,		// 1F00 0300
  0x1F03, 0x3B1,		// 1F01 0300
  0x1F04, 0x3B1,		// 1F00 0301
  0x1F05, 0x3B1,		// 1F01 0301
  0x1F06, 0x3B1,		// 1F00 0342
  0x1F07, 0x3B1,		// 1F01 0342
  0x1F08, 0x3B1,		// 0391 0313
  0x1F09, 0x3B1,		// 0391 0314
  0x1F0A, 0x3B1,		// 1F08 0300
  0x1F0B, 0x3B1,		// 1F09 0300
  0x1F0C, 0x3B1,		// 1F08 0301
  0x1F0D, 0x3B1,		// 1F09 0301
  0x1F0E, 0x3B1,		// 1F08 0342
  0x1F0F, 0x3B1,		// 1F09 0342
  0x1F10, 0x3B5,		// 03B5 0313
  0x1F11, 0x3B5,		// 03B5 0314
  0x1F12, 0x3B5,		// 1F10 0300
  0x1F13, 0x3B5,		// 1F11 0300
  0x1F14, 0x3B5,		// 1F10 0301
  0x1F15, 0x3B5,		// 1F11 0301
  0x1F18, 0x3B5,		// 0395 0313
  0x1F19, 0x3B5,		// 0395 0314
  0x1F1A, 0x3B5,		// 1F18 0300
  0x1F1B, 0x3B5,		// 1F19 0300
  0x1F1C, 0x3B5,		// 1F18 0301
  0x1F1D, 0x3B5,		// 1F19 0301
  0x1F20, 0x3B7,		// 03B7 0313
  0x1F21, 0x3B7,		// 03B7 0314
  0x1F22, 0x3B7,		// 1F20 0300
  0x1F23, 0x3B7,		// 1F21 0300
  0x1F24, 0x3B7,		// 1F20 0301
  0x1F25, 0x3B7,		// 1F21 0301
  0x1F26, 0x3B7,		// 1F20 0342
  0x1F27, 0x3B7,		// 1F21 0342
  0x1F28, 0x3B7,		// 0397 0313
  0x1F29, 0x3B7,		// 0397 0314
  0x1F2A, 0x3B7,		// 1F28 0300
  0x1F2B, 0x3B7,		// 1F29 0300
  0x1F2C, 0x3B7,		// 1F28 0301
  0x1F2D, 0x3B7,		// 1F29 0301
  0x1F2E, 0x3B7,		// 1F28 0342
  0x1F2F, 0x3B7,		// 1F29 0342
  0x1F30, 0x3B9,		// 03B9 0313
  0x1F31, 0x3B9,		// 03B9 0314
  0x1F32, 0x3B9,		// 1F30 0300
  0x1F33, 0x3B9,		// 1F31 0300
  0x1F34, 0x3B9,		// 1F30 0301
  0x1F35, 0x3B9,		// 1F31 0301
  0x1F36, 0x3B9,		// 1F30 0342
  0x1F37, 0x3B9,		// 1F31 0342
  0x1F38, 0x3B9,		// 0399 0313
  0x1F39, 0x3B9,		// 0399 0314
  0x1F3A, 0x3B9,		// 1F38 0300
  0x1F3B, 0x3B9,		// 1F39 0300
  0x1F3C, 0x3B9,		// 1F38 0301
  0x1F3D, 0x3B9,		// 1F39 0301
  0x1F3E, 0x3B9,		// 1F38 0342
  0x1F3F, 0x3B9,		// 1F39 0342
  0x1F40, 0x3BF,		// 03BF 0313
  0x1F41, 0x3BF,		// 03BF 0314
  0x1F42, 0x3BF,		// 1F40 0300
  0x1F43, 0x3BF,		// 1F41 0300
  0x1F44, 0x3BF,		// 1F40 0301
  0x1F45, 0x3BF,		// 1F41 0301
  0x1F48, 0x3BF,		// 039F 0313
  0x1F49, 0x3BF,		// 039F 0314
  0x1F4A, 0x3BF,		// 1F48 0300
  0x1F4B, 0x3BF,		// 1F49 0300
  0x1F4C, 0x3BF,		// 1F48 0301
  0x1F4D, 0x3BF,		// 1F49 0301
  0x1F50, 0x3C5,		// 03C5 0313
  0x1F51, 0x3C5,		// 03C5 0314
  0x1F52, 0x3C5,		// 1F50 0300
  0x1F53, 0x3C5,		// 1F51 0300
  0x1F54, 0x3C5,		// 1F50 0301
  0x1F55, 0x3C5,		// 1F51 0301
  0x1F56, 0x3C5,		// 1F50 0342
  0x1F57, 0x3C5,		// 1F51 0342
  0x1F59, 0x3C5,		// 03A5 0314
  0x1F5B, 0x3C5,		// 1F59 0300
  0x1F5D, 0x3C5,		// 1F59 0301
  0x1F5F, 0x3C5,		// 1F59 0342
  0x1F60, 0x3C9,		// 03C9 0313
  0x1F61, 0x3C9,		// 03C9 0314
  0x1F62, 0x3C9,		// 1F60 0300
  0x1F63, 0x3C9,		// 1F61 0300
  0x1F64, 0x3C9,		// 1F60 0301
  0x1F65, 0x3C9,		// 1F61 0301
  0x1F66, 0x3C9,		// 1F60 0342
  0x1F67, 0x3C9,		// 1F61 0342
  0x1F68, 0x3C9,		// 03A9 0313
  0x1F69, 0x3C9,		// 03A9 0314
  0x1F6A, 0x3C9,		// 1F68 0300
  0x1F6B, 0x3C9,		// 1F69 0300
  0x1F6C, 0x3C9,		// 1F68 0301
  0x1F6D, 0x3C9,		// 1F69 0301
  0x1F6E, 0x3C9,		// 1F68 0342
  0x1F6F, 0x3C9,		// 1F69 0342
  0x1F70, 0x3B1,		// 03B1 0300
  0x1F71, 0x3B1,		// 03AC
  0x1F72, 0x3B5,		// 03B5 0300
  0x1F73, 0x3B5,		// 03AD
  0x1F74, 0x3B7,		// 03B7 0300
  0x1F75, 0x3B7,		// 03AE
  0x1F76, 0x3B9,		// 03B9 0300
  0x1F77, 0x3B9,		// 03AF
  0x1F78, 0x3BF,		// 03BF 0300
  0x1F79, 0x3BF,		// 03CC
  0x1F7A, 0x3C5,		// 03C5 0300
  0x1F7B, 0x3C5,		// 03CD
  0x1F7C, 0x3C9,		// 03C9 0300
  0x1F7D, 0x3C9,		// 03CE
  0x1F80, 0x3B1,		// 1F00 0345
  0x1F81, 0x3B1,		// 1F01 0345
  0x1F82, 0x3B1,		// 1F02 0345
  0x1F83, 0x3B1,		// 1F03 0345
  0x1F84, 0x3B1,		// 1F04 0345
  0x1F85, 0x3B1,		// 1F05 0345
  0x1F86, 0x3B1,		// 1F06 0345
  0x1F87, 0x3B1,		// 1F07 0345
  0x1F88, 0x3B1,		// 1F08 0345
  0x1F89, 0x3B1,		// 1F09 0345
  0x1F8A, 0x3B1,		// 1F0A 0345
  0x1F8B, 0x3B1,		// 1F0B 0345
  0x1F8C, 0x3B1,		// 1F0C 0345
  0x1F8D, 0x3B1,		// 1F0D 0345
  0x1F8E, 0x3B1,		// 1F0E 0345
  0x1F8F, 0x3B1,		// 1F0F 0345
  0x1F90, 0x3B7,		// 1F20 0345
  0x1F91, 0x3B7,		// 1F21 0345
  0x1F92, 0x3B7,		// 1F22 0345
  0x1F93, 0x3B7,		// 1F23 0345
  0x1F94, 0x3B7,		// 1F24 0345
  0x1F95, 0x3B7,		// 1F25 0345
  0x1F96, 0x3B7,		// 1F26 0345
  0x1F97, 0x3B7,		// 1F27 0345
  0x1F98, 0x3B7,		// 1F28 0345
  0x1F99, 0x3B7,		// 1F29 0345
  0x1F9A, 0x3B7,		// 1F2A 0345
  0x1F9B, 0x3B7,		// 1F2B 0345
  0x1F9C, 0x3B7,		// 1F2C 0345
  0x1F9D, 0x3B7,		// 1F2D 0345
  0x1F9E, 0x3B7,		// 1F2E 0345
  0x1F9F, 0x3B7,		// 1F2F 0345
  0x1FA0, 0x3C9,		// 1F60 0345
  0x1FA1, 0x3C9,		// 1F61 0345
  0x1FA2, 0x3C9,		// 1F62 0345
  0x1FA3, 0x3C9,		// 1F63 0345
  0x1FA4, 0x3C9,		// 1F64 0345
  0x1FA5, 0x3C9,		// 1F65 0345
  0x1FA6, 0x3C9,		// 1F66 0345
  0x1FA7, 0x3C9,		// 1F67 0345
  0x1FA8, 0x3C9,		// 1F68 0345
  0x1FA9, 0x3C9,		// 1F69 0345
  0x1FAA, 0x3C9,		// 1F6A 0345
  0x1FAB, 0x3C9,		// 1F6B 0345
  0x1FAC, 0x3C9,		// 1F6C 0345
  0x1FAD, 0x3C9,		// 1F6D 0345
  0x1FAE, 0x3C9,		// 1F6E 0345
  0x1FAF, 0x3C9,		// 1F6F 0345
  0x1FB0, 0x3B1,		// 03B1 0306
  0x1FB1, 0x3B1,		// 03B1 0304
  0x1FB2, 0x3B1,		// 1F70 0345
  0x1FB3, 0x3B1,		// 03B1 0345
  0x1FB4, 0x3B1,		// 03AC 0345
  0x1FB6, 0x3B1,		// 03B1 0342
  0x1FB7, 0x3B1,		// 1FB6 0345
  0x1FB8, 0x3B1,		// 0391 0306
  0x1FB9, 0x3B1,		// 0391 0304
  0x1FBA, 0x3B1,		// 0391 0300
  0x1FBB, 0x3B1,		// 0386
  0x1FBC, 0x3B1,		// 0391 0345
  0x1FBE, 0x3B9,		// 03B9
  0x1FC1, 0x0A8,		// 00A8 0342
  0x1FC2, 0x3B7,		// 1F74 0345
  0x1FC3, 0x3B7,		// 03B7 0345
  0x1FC4, 0x3B7,		// 03AE 0345
  0x1FC6, 0x3B7,		// 03B7 0342
  0x1FC7, 0x3B7,		// 1FC6 0345
  0x1FC8, 0x3B5,		// 0395 0300
  0x1FC9, 0x3B5,		// 0388
  0x1FCA, 0x3B7,		// 0397 0300
  0x1FCB, 0x3B7,		// 0389
  0x1FCC, 0x3B7,		// 0397 0345
  0x1FCD, 0x1FBF,		// 1FBF 0300
  0x1FCE, 0x1FBF,		// 1FBF 0301
  0x1FCF, 0x1FBF,		// 1FBF 0342
  0x1FD0, 0x3B9,		// 03B9 0306
  0x1FD1, 0x3B9,		// 03B9 0304
  0x1FD2, 0x3B9,		// 03CA 0300
  0x1FD3, 0x3B9,		// 0390
  0x1FD6, 0x3B9,		// 03B9 0342
  0x1FD7, 0x3B9,		// 03CA 0342
  0x1FD8, 0x3B9,		// 0399 0306
  0x1FD9, 0x3B9,		// 0399 0304
  0x1FDA, 0x3B9,		// 0399 0300
  0x1FDB, 0x3B9,		// 038A
  0x1FDD, 0x1FFE,		// 1FFE 0300
  0x1FDE, 0x1FFE,		// 1FFE 0301
  0x1FDF, 0x1FFE,		// 1FFE 0342
  0x1FE0, 0x3C5,		// 03C5 0306
  0x1FE1, 0x3C5,		// 03C5 0304
  0x1FE2, 0x3C5,		// 03CB 0300
  0x1FE3, 0x3C5,		// 03B0
  0x1FE4, 0x3C1,		// 03C1 0313
  0x1FE5, 0x3C1,		// 03C1 0314
  0x1FE6, 0x3C5,		// 03C5 0342
  0x1FE7, 0x3C5,		// 03CB 0342
  0x1FE8, 0x3C5,		// 03A5 0306
  0x1FE9, 0x3C5,		// 03A5 0304
  0x1FEA, 0x3C5,		// 03A5 0300
  0x1FEB, 0x3C5,		// 038E
  0x1FEC, 0x3C1,		// 03A1 0314
  0x1FED, 0x0A8,		// 00A8 0300
  0x1FEE, 0x0A8,		// 0385
  0x1FEF, 0x060,		// 0060
  0x1FF2, 0x3C9,		// 1F7C 0345
  0x1FF3, 0x3C9,		// 03C9 0345
  0x1FF4, 0x3C9,		// 03CE 0345
  0x1FF6, 0x3C9,		// 03C9 0342
  0x1FF7, 0x3C9,		// 1FF6 0345
  0x1FF8, 0x3BF,		// 039F 0300
  0x1FF9, 0x3BF,		// 038C
  0x1FFA, 0x3C9,		// 03A9 0300
  0x1FFB, 0x3C9,		// 038F
  0x1FFC, 0x3C9,		// 03A9 0345
  0x1FFD, 0x0B4,		// 00B4
];
var LowerCase20 = [
  0x2000, 0x2002,		// 2002
  0x2001, 0x2003,		// 2003
];
var LowerCase21 = [
  0x2126, 0x3C9,		// 03A9
  0x212A, 0x06B,		// 004B
  0x212B, 0x061,		// 00C5
  0x2160, 0x2170,		// <compat> 0049
  0x2161, 0x2171,		// <compat> 0049 0049
  0x2162, 0x2172,		// <compat> 0049 0049 0049
  0x2163, 0x2173,		// <compat> 0049 0056
  0x2164, 0x2174,		// <compat> 0056
  0x2165, 0x2175,		// <compat> 0056 0049
  0x2166, 0x2176,		// <compat> 0056 0049 0049
  0x2167, 0x2177,		// <compat> 0056 0049 0049 0049
  0x2168, 0x2178,		// <compat> 0049 0058
  0x2169, 0x2179,		// <compat> 0058
  0x216A, 0x217A,		// <compat> 0058 0049
  0x216B, 0x217B,		// <compat> 0058 0049 0049
  0x216C, 0x217C,		// <compat> 004C
  0x216D, 0x217D,		// <compat> 0043
  0x216E, 0x217E,		// <compat> 0044
  0x216F, 0x217F,		// <compat> 004D
];
var LowerCase22 = [
  0x2204, 0x2203,		// 2203 0338
  0x2209, 0x2208,		// 2208 0338
  0x220C, 0x220B,		// 220B 0338
  0x2224, 0x2223,		// 2223 0338
  0x2226, 0x2225,		// 2225 0338
  0x2241, 0x07E,		// 007E 0338
  0x2244, 0x2243,		// 2243 0338
  0x2247, 0x2245,		// 2245 0338
  0x2249, 0x2248,		// 2248 0338
  0x2260, 0x03D,		// 003D 0338
  0x2262, 0x2261,		// 2261 0338
  0x226D, 0x224D,		// 224D 0338
  0x226E, 0x03C,		// 003C 0338
  0x226F, 0x03E,		// 003E 0338
  0x2270, 0x2264,		// 2264 0338
  0x2271, 0x2265,		// 2265 0338
  0x2274, 0x2272,		// 2272 0338
  0x2275, 0x2273,		// 2273 0338
  0x2278, 0x2276,		// 2276 0338
  0x2279, 0x2277,		// 2277 0338
  0x2280, 0x227A,		// 227A 0338
  0x2281, 0x227B,		// 227B 0338
  0x2284, 0x2282,		// 2282 0338
  0x2285, 0x2283,		// 2283 0338
  0x2288, 0x2286,		// 2286 0338
  0x2289, 0x2287,		// 2287 0338
  0x22AC, 0x22A2,		// 22A2 0338
  0x22AD, 0x22A8,		// 22A8 0338
  0x22AE, 0x22A9,		// 22A9 0338
  0x22AF, 0x22AB,		// 22AB 0338
  0x22E0, 0x227C,		// 227C 0338
  0x22E1, 0x227D,		// 227D 0338
  0x22E2, 0x2291,		// 2291 0338
  0x22E3, 0x2292,		// 2292 0338
  0x22EA, 0x22B2,		// 22B2 0338
  0x22EB, 0x22B3,		// 22B3 0338
  0x22EC, 0x22B4,		// 22B4 0338
  0x22ED, 0x22B5,		// 22B5 0338
];
var LowerCase23 = [
  0x2329, 0x3008,		// 3008
  0x232A, 0x3009,		// 3009
];
var LowerCase24 = [
  0x24B6, 0x24D0,		// <circle> 0041
  0x24B7, 0x24D1,		// <circle> 0042
  0x24B8, 0x24D2,		// <circle> 0043
  0x24B9, 0x24D3,		// <circle> 0044
  0x24BA, 0x24D4,		// <circle> 0045
  0x24BB, 0x24D5,		// <circle> 0046
  0x24BC, 0x24D6,		// <circle> 0047
  0x24BD, 0x24D7,		// <circle> 0048
  0x24BE, 0x24D8,		// <circle> 0049
  0x24BF, 0x24D9,		// <circle> 004A
  0x24C0, 0x24DA,		// <circle> 004B
  0x24C1, 0x24DB,		// <circle> 004C
  0x24C2, 0x24DC,		// <circle> 004D
  0x24C3, 0x24DD,		// <circle> 004E
  0x24C4, 0x24DE,		// <circle> 004F
  0x24C5, 0x24DF,		// <circle> 0050
  0x24C6, 0x24E0,		// <circle> 0051
  0x24C7, 0x24E1,		// <circle> 0052
  0x24C8, 0x24E2,		// <circle> 0053
  0x24C9, 0x24E3,		// <circle> 0054
  0x24CA, 0x24E4,		// <circle> 0055
  0x24CB, 0x24E5,		// <circle> 0056
  0x24CC, 0x24E6,		// <circle> 0057
  0x24CD, 0x24E7,		// <circle> 0058
  0x24CE, 0x24E8,		// <circle> 0059
  0x24CF, 0x24E9,		// <circle> 005A
];
// 7.016 LowerCase30 removed as INCORRECT: Don't normalise these characters
var LowerCaseF9 = [
  0xF900, 0x8C48,		// 8C48
  0xF901, 0x66F4,		// 66F4
  0xF902, 0x8ECA,		// 8ECA
  0xF903, 0x8CC8,		// 8CC8
  0xF904, 0x6ED1,		// 6ED1
  0xF905, 0x4E32,		// 4E32
  0xF906, 0x53E5,		// 53E5
  0xF907, 0x9F9C,		// 9F9C
  0xF908, 0x9F9C,		// 9F9C
  0xF909, 0x5951,		// 5951
  0xF90A, 0x91D1,		// 91D1
  0xF90B, 0x5587,		// 5587
  0xF90C, 0x5948,		// 5948
  0xF90D, 0x61F6,		// 61F6
  0xF90E, 0x7669,		// 7669
  0xF90F, 0x7F85,		// 7F85
  0xF910, 0x863F,		// 863F
  0xF911, 0x87BA,		// 87BA
  0xF912, 0x88F8,		// 88F8
  0xF913, 0x908F,		// 908F
  0xF914, 0x6A02,		// 6A02
  0xF915, 0x6D1B,		// 6D1B
  0xF916, 0x70D9,		// 70D9
  0xF917, 0x73DE,		// 73DE
  0xF918, 0x843D,		// 843D
  0xF919, 0x916A,		// 916A
  0xF91A, 0x99F1,		// 99F1
  0xF91B, 0x4E82,		// 4E82
  0xF91C, 0x5375,		// 5375
  0xF91D, 0x6B04,		// 6B04
  0xF91E, 0x721B,		// 721B
  0xF91F, 0x862D,		// 862D
  0xF920, 0x9E1E,		// 9E1E
  0xF921, 0x5D50,		// 5D50
  0xF922, 0x6FEB,		// 6FEB
  0xF923, 0x85CD,		// 85CD
  0xF924, 0x8964,		// 8964
  0xF925, 0x62C9,		// 62C9
  0xF926, 0x81D8,		// 81D8
  0xF927, 0x881F,		// 881F
  0xF928, 0x5ECA,		// 5ECA
  0xF929, 0x6717,		// 6717
  0xF92A, 0x6D6A,		// 6D6A
  0xF92B, 0x72FC,		// 72FC
  0xF92C, 0x90CE,		// 90CE
  0xF92D, 0x4F86,		// 4F86
  0xF92E, 0x51B7,		// 51B7
  0xF92F, 0x52DE,		// 52DE
  0xF930, 0x64C4,		// 64C4
  0xF931, 0x6AD3,		// 6AD3
  0xF932, 0x7210,		// 7210
  0xF933, 0x76E7,		// 76E7
  0xF934, 0x8001,		// 8001
  0xF935, 0x8606,		// 8606
  0xF936, 0x865C,		// 865C
  0xF937, 0x8DEF,		// 8DEF
  0xF938, 0x9732,		// 9732
  0xF939, 0x9B6F,		// 9B6F
  0xF93A, 0x9DFA,		// 9DFA
  0xF93B, 0x788C,		// 788C
  0xF93C, 0x797F,		// 797F
  0xF93D, 0x7DA0,		// 7DA0
  0xF93E, 0x83C9,		// 83C9
  0xF93F, 0x9304,		// 9304
  0xF940, 0x9E7F,		// 9E7F
  0xF941, 0x8AD6,		// 8AD6
  0xF942, 0x58DF,		// 58DF
  0xF943, 0x5F04,		// 5F04
  0xF944, 0x7C60,		// 7C60
  0xF945, 0x807E,		// 807E
  0xF946, 0x7262,		// 7262
  0xF947, 0x78CA,		// 78CA
  0xF948, 0x8CC2,		// 8CC2
  0xF949, 0x96F7,		// 96F7
  0xF94A, 0x58D8,		// 58D8
  0xF94B, 0x5C62,		// 5C62
  0xF94C, 0x6A13,		// 6A13
  0xF94D, 0x6DDA,		// 6DDA
  0xF94E, 0x6F0F,		// 6F0F
  0xF94F, 0x7D2F,		// 7D2F
  0xF950, 0x7E37,		// 7E37
  0xF951, 0x96FB,		// 96FB
  0xF952, 0x52D2,		// 52D2
  0xF953, 0x808B,		// 808B
  0xF954, 0x51DC,		// 51DC
  0xF955, 0x51CC,		// 51CC
  0xF956, 0x7A1C,		// 7A1C
  0xF957, 0x7DBE,		// 7DBE
  0xF958, 0x83F1,		// 83F1
  0xF959, 0x9675,		// 9675
  0xF95A, 0x8B80,		// 8B80
  0xF95B, 0x62CF,		// 62CF
  0xF95C, 0x6A02,		// 6A02
  0xF95D, 0x8AFE,		// 8AFE
  0xF95E, 0x4E39,		// 4E39
  0xF95F, 0x5BE7,		// 5BE7
  0xF960, 0x6012,		// 6012
  0xF961, 0x7387,		// 7387
  0xF962, 0x7570,		// 7570
  0xF963, 0x5317,		// 5317
  0xF964, 0x78FB,		// 78FB
  0xF965, 0x4FBF,		// 4FBF
  0xF966, 0x5FA9,		// 5FA9
  0xF967, 0x4E0D,		// 4E0D
  0xF968, 0x6CCC,		// 6CCC
  0xF969, 0x6578,		// 6578
  0xF96A, 0x7D22,		// 7D22
  0xF96B, 0x53C3,		// 53C3
  0xF96C, 0x585E,		// 585E
  0xF96D, 0x7701,		// 7701
  0xF96E, 0x8449,		// 8449
  0xF96F, 0x8AAA,		// 8AAA
  0xF970, 0x6BBA,		// 6BBA
  0xF971, 0x8FB0,		// 8FB0
  0xF972, 0x6C88,		// 6C88
  0xF973, 0x62FE,		// 62FE
  0xF974, 0x82E5,		// 82E5
  0xF975, 0x63A0,		// 63A0
  0xF976, 0x7565,		// 7565
  0xF977, 0x4EAE,		// 4EAE
  0xF978, 0x5169,		// 5169
  0xF979, 0x51C9,		// 51C9
  0xF97A, 0x6881,		// 6881
  0xF97B, 0x7CE7,		// 7CE7
  0xF97C, 0x826F,		// 826F
  0xF97D, 0x8AD2,		// 8AD2
  0xF97E, 0x91CF,		// 91CF
  0xF97F, 0x52F5,		// 52F5
  0xF980, 0x5442,		// 5442
  0xF981, 0x5973,		// 5973
  0xF982, 0x5EEC,		// 5EEC
  0xF983, 0x65C5,		// 65C5
  0xF984, 0x6FFE,		// 6FFE
  0xF985, 0x792A,		// 792A
  0xF986, 0x95AD,		// 95AD
  0xF987, 0x9A6A,		// 9A6A
  0xF988, 0x9E97,		// 9E97
  0xF989, 0x9ECE,		// 9ECE
  0xF98A, 0x529B,		// 529B
  0xF98B, 0x66C6,		// 66C6
  0xF98C, 0x6B77,		// 6B77
  0xF98D, 0x8F62,		// 8F62
  0xF98E, 0x5E74,		// 5E74
  0xF98F, 0x6190,		// 6190
  0xF990, 0x6200,		// 6200
  0xF991, 0x649A,		// 649A
  0xF992, 0x6F23,		// 6F23
  0xF993, 0x7149,		// 7149
  0xF994, 0x7489,		// 7489
  0xF995, 0x79CA,		// 79CA
  0xF996, 0x7DF4,		// 7DF4
  0xF997, 0x806F,		// 806F
  0xF998, 0x8F26,		// 8F26
  0xF999, 0x84EE,		// 84EE
  0xF99A, 0x9023,		// 9023
  0xF99B, 0x934A,		// 934A
  0xF99C, 0x5217,		// 5217
  0xF99D, 0x52A3,		// 52A3
  0xF99E, 0x54BD,		// 54BD
  0xF99F, 0x70C8,		// 70C8
  0xF9A0, 0x88C2,		// 88C2
  0xF9A1, 0x8AAA,		// 8AAA
  0xF9A2, 0x5EC9,		// 5EC9
  0xF9A3, 0x5FF5,		// 5FF5
  0xF9A4, 0x637B,		// 637B
  0xF9A5, 0x6BAE,		// 6BAE
  0xF9A6, 0x7C3E,		// 7C3E
  0xF9A7, 0x7375,		// 7375
  0xF9A8, 0x4EE4,		// 4EE4
  0xF9A9, 0x56F9,		// 56F9
  0xF9AA, 0x5BE7,		// 5BE7
  0xF9AB, 0x5DBA,		// 5DBA
  0xF9AC, 0x601C,		// 601C
  0xF9AD, 0x73B2,		// 73B2
  0xF9AE, 0x7469,		// 7469
  0xF9AF, 0x7F9A,		// 7F9A
  0xF9B0, 0x8046,		// 8046
  0xF9B1, 0x9234,		// 9234
  0xF9B2, 0x96F6,		// 96F6
  0xF9B3, 0x9748,		// 9748
  0xF9B4, 0x9818,		// 9818
  0xF9B5, 0x4F8B,		// 4F8B
  0xF9B6, 0x79AE,		// 79AE
  0xF9B7, 0x91B4,		// 91B4
  0xF9B8, 0x96B8,		// 96B8
  0xF9B9, 0x60E1,		// 60E1
  0xF9BA, 0x4E86,		// 4E86
  0xF9BB, 0x50DA,		// 50DA
  0xF9BC, 0x5BEE,		// 5BEE
  0xF9BD, 0x5C3F,		// 5C3F
  0xF9BE, 0x6599,		// 6599
  0xF9BF, 0x6A02,		// 6A02
  0xF9C0, 0x71CE,		// 71CE
  0xF9C1, 0x7642,		// 7642
  0xF9C2, 0x84FC,		// 84FC
  0xF9C3, 0x907C,		// 907C
  0xF9C4, 0x9F8D,		// 9F8D
  0xF9C5, 0x6688,		// 6688
  0xF9C6, 0x962E,		// 962E
  0xF9C7, 0x5289,		// 5289
  0xF9C8, 0x677B,		// 677B
  0xF9C9, 0x67F3,		// 67F3
  0xF9CA, 0x6D41,		// 6D41
  0xF9CB, 0x6E9C,		// 6E9C
  0xF9CC, 0x7409,		// 7409
  0xF9CD, 0x7559,		// 7559
  0xF9CE, 0x786B,		// 786B
  0xF9CF, 0x7D10,		// 7D10
  0xF9D0, 0x985E,		// 985E
  0xF9D1, 0x516D,		// 516D
  0xF9D2, 0x622E,		// 622E
  0xF9D3, 0x9678,		// 9678
  0xF9D4, 0x502B,		// 502B
  0xF9D5, 0x5D19,		// 5D19
  0xF9D6, 0x6DEA,		// 6DEA
  0xF9D7, 0x8F2A,		// 8F2A
  0xF9D8, 0x5F8B,		// 5F8B
  0xF9D9, 0x6144,		// 6144
  0xF9DA, 0x6817,		// 6817
  0xF9DB, 0x7387,		// 7387
  0xF9DC, 0x9686,		// 9686
  0xF9DD, 0x5229,		// 5229
  0xF9DE, 0x540F,		// 540F
  0xF9DF, 0x5C65,		// 5C65
  0xF9E0, 0x6613,		// 6613
  0xF9E1, 0x674E,		// 674E
  0xF9E2, 0x68A8,		// 68A8
  0xF9E3, 0x6CE5,		// 6CE5
  0xF9E4, 0x7406,		// 7406
  0xF9E5, 0x75E2,		// 75E2
  0xF9E6, 0x7F79,		// 7F79
  0xF9E7, 0x88CF,		// 88CF
  0xF9E8, 0x88E1,		// 88E1
  0xF9E9, 0x91CC,		// 91CC
  0xF9EA, 0x96E2,		// 96E2
  0xF9EB, 0x533F,		// 533F
  0xF9EC, 0x6EBA,		// 6EBA
  0xF9ED, 0x541D,		// 541D
  0xF9EE, 0x71D0,		// 71D0
  0xF9EF, 0x7498,		// 7498
  0xF9F0, 0x85FA,		// 85FA
  0xF9F1, 0x96A3,		// 96A3
  0xF9F2, 0x9C57,		// 9C57
  0xF9F3, 0x9E9F,		// 9E9F
  0xF9F4, 0x6797,		// 6797
  0xF9F5, 0x6DCB,		// 6DCB
  0xF9F6, 0x81E8,		// 81E8
  0xF9F7, 0x7ACB,		// 7ACB
  0xF9F8, 0x7B20,		// 7B20
  0xF9F9, 0x7C92,		// 7C92
  0xF9FA, 0x72C0,		// 72C0
  0xF9FB, 0x7099,		// 7099
  0xF9FC, 0x8B58,		// 8B58
  0xF9FD, 0x4EC0,		// 4EC0
  0xF9FE, 0x8336,		// 8336
  0xF9FF, 0x523A,		// 523A
];
var LowerCaseFA = [
  0xFA00, 0x5207,		// 5207
  0xFA01, 0x5EA6,		// 5EA6
  0xFA02, 0x62D3,		// 62D3
  0xFA03, 0x7CD6,		// 7CD6
  0xFA04, 0x5B85,		// 5B85
  0xFA05, 0x6D1E,		// 6D1E
  0xFA06, 0x66B4,		// 66B4
  0xFA07, 0x8F3B,		// 8F3B
  0xFA08, 0x884C,		// 884C
  0xFA09, 0x964D,		// 964D
  0xFA0A, 0x898B,		// 898B
  0xFA0B, 0x5ED3,		// 5ED3
  0xFA0C, 0x5140,		// 5140
  0xFA0D, 0x55C0,		// 55C0
  0xFA10, 0x585A,		// 585A
  0xFA12, 0x6674,		// 6674
  0xFA15, 0x51DE,		// 51DE
  0xFA16, 0x732A,		// 732A
  0xFA17, 0x76CA,		// 76CA
  0xFA18, 0x793C,		// 793C
  0xFA19, 0x795E,		// 795E
  0xFA1A, 0x7965,		// 7965
  0xFA1B, 0x798F,		// 798F
  0xFA1C, 0x9756,		// 9756
  0xFA1D, 0x7CBE,		// 7CBE
  0xFA1E, 0x7FBD,		// 7FBD
  0xFA20, 0x8612,		// 8612
  0xFA22, 0x8AF8,		// 8AF8
  0xFA25, 0x9038,		// 9038
  0xFA26, 0x90FD,		// 90FD
  0xFA2A, 0x98EF,		// 98EF
  0xFA2B, 0x98FC,		// 98FC
  0xFA2C, 0x9928,		// 9928
  0xFA2D, 0x9DB4,		// 9DB4
];
var LowerCaseFB = [
  0xFB1F, 0x5F2,		// 05F2 05B7
  0xFB2A, 0x5E9,		// 05E9 05C1
  0xFB2B, 0x5E9,		// 05E9 05C2
  0xFB2C, 0x5E9,		// FB49 05C1
  0xFB2D, 0x5E9,		// FB49 05C2
  0xFB2E, 0x5D0,		// 05D0 05B7
  0xFB2F, 0x5D0,		// 05D0 05B8
  0xFB30, 0x5D0,		// 05D0 05BC
  0xFB31, 0x5D1,		// 05D1 05BC
  0xFB32, 0x5D2,		// 05D2 05BC
  0xFB33, 0x5D3,		// 05D3 05BC
  0xFB34, 0x5D4,		// 05D4 05BC
  0xFB35, 0x5D5,		// 05D5 05BC
  0xFB36, 0x5D6,		// 05D6 05BC
  0xFB38, 0x5D8,		// 05D8 05BC
  0xFB39, 0x5D9,		// 05D9 05BC
  0xFB3A, 0x5DA,		// 05DA 05BC
  0xFB3B, 0x5DB,		// 05DB 05BC
  0xFB3C, 0x5DC,		// 05DC 05BC
  0xFB3E, 0x5DE,		// 05DE 05BC
  0xFB40, 0x5E0,		// 05E0 05BC
  0xFB41, 0x5E1,		// 05E1 05BC
  0xFB43, 0x5E3,		// 05E3 05BC
  0xFB44, 0x5E4,		// 05E4 05BC
  0xFB46, 0x5E6,		// 05E6 05BC
  0xFB47, 0x5E7,		// 05E7 05BC
  0xFB48, 0x5E8,		// 05E8 05BC
  0xFB49, 0x5E9,		// 05E9 05BC
  0xFB4A, 0x5EA,		// 05EA 05BC
  0xFB4B, 0x5D5,		// 05D5 05B9
  0xFB4C, 0x5D1,		// 05D1 05BF
  0xFB4D, 0x5DB,		// 05DB 05BF
  0xFB4E, 0x5E4,		// 05E4 05BF
];
/// LowerCaseFF Not needed as already transformed to latin

	/////////////////////////////////////

	/////////////////////////////////////
	// PUBLIC methods
	return {
		version: version,
		versionDate: versionDate,
		search: search,
		config: config,
		databases: databases,
		OP_AND: OP_AND,
		OP_NONE: OP_NONE,
		OP_OR: OP_OR,
		OP_NOT: OP_NOT,
		OP_CONTIG: OP_CONTIG
	};
	/////////////////////////////////////
}(jQuery);