function dec2hex ( textString ) {
 return (textString+0).toString(16).toUpperCase();
}

function convertCP2Char ( textString ) {
  var outputString = '';
  textString = textString.replace(/^\s+/, '');
  if (textString.length == 0) { return ''; }
  textString = textString.replace(/\s+/g, ' ');
  var listArray = textString.split(' ');
  for ( var i = 0; i < listArray.length; i++ ) {
    var n = parseInt(listArray[i], 16);
    if (n <= 0xFFFF) {
		
      outputString += String.fromCharCode(n);
    } else if (n <= 0x10FFFF) {
      n -= 0x10000
      outputString += String.fromCharCode(0xD800 | (n >> 10)) + String.fromCharCode(0xDC00 | (n & 0x3FF));
    } else {
      outputString += 'convertCP2Char error: Code point out of range: '+dec2hex(n);
    }
  }
  return( outputString );
}

function convertPercent2Char ( textString ) {
	CPstring = '';
	var outputString = "";
	var compte = 0;
	var n = 0;
	// remove all leading spaces
	textString = textString.replace(/^\s+/, '');
	if (textString.length == 0) { return ""; }
	// normalize all multiple spaces to a single space - note: there shouldn't be any spaces!
	textString = textString.replace(/\s+/g, ' ');
	// convert the whole string to percent escaped forms (to reduce work in coding)
	for ( var j = 0; j < textString.length; j++ ) {
		if (textString.charAt(j) == '%') { outputString += textString.slice(j, j+3); j += 2; }
		else { outputString += '%'+dec2hex(textString.charCodeAt(j)); }
	}
	
	textString = outputString; 
	outputString = '';
	var listArray = textString.split('%');
	for ( var i = 1; i < listArray.length; i++ ) { 
		var b = parseInt(listArray[i], 16);   // alert('b:'+dec2hex(b));
		switch (compte) {
			case 0:
				if (0 <= b && b <= 0x7F) {  // 0xxxxxxx
					outputString += dec2hex(b) + ' '; 
				} else if (0xC0 <= b && b <= 0xDF) {  // 110xxxxx
					compte = 1;
					n = b & 0x1F; 
				} else if (0xE0 <= b && b <= 0xEF) {  // 1110xxxx
					compte = 2;
					n = b & 0xF; 
				} else if (0xF0 <= b && b <= 0xF7) {  // 11110xxx
					compte = 3;
					n = b & 0x7; 
				} else {
					outputString += '!erreur ' + dec2hex(b) + '! ';
				}
				break;
			case 1:
				if (b < 0x80 || b > 0xBF) {
					outputString += '!erreur ' + dec2hex(b) + '! ';
				}
				compte--;
				outputString += dec2hex((n << 6) | (b-0x80)) + ' ';
				n = 0;
				break;
			case 2: case 3:
				if (b < 0x80 || b > 0xBF) {
					outputString += '!erreur ' + dec2hex(b) + '! ';
				}
				n = (n << 6) | (b-0x80);
				compte--;
				break;
		}
	}
	CPstring = outputString.replace(/ $/, '');
	return convertCP2Char( CPstring );
}
