#! /usr/local/bin/perl -w

use strict;

my @charsets = (
  { name => "Latin-1", file => "iso-8859-1.txt", abbr => "1",
    descr => "Latin-1 (ISO-8859-1: Western European)" },
  { name => "Latin-2", file => "iso-8859-2.txt", abbr => "2",
    descr => "Latin-2 (ISO-8859-2: Central European)" },
  { name => "Latin-3", file => "iso-8859-3.txt", abbr => "3",
    descr => "Latin-3 (ISO-8859-3: South European and Esperanto)" },
  { name => "Latin-4", file => "iso-8859-4.txt", abbr => "4",
    descr => "Latin-4 (ISO-8859-4: Baltic, old)" },
  { name => "Latin-5", file => "iso-8859-9.txt", abbr => "5",
    descr => "Latin-5 (ISO-8859-9: Turkish)" },
  { name => "Latin-6", file => "iso-8859-10.txt", abbr => "6",
    descr => "Latin-6 (ISO-8859-10: Nordic)" },
  { name => "Latin-7", file => "iso-8859-13.txt", abbr => "7",
    descr => "Latin-7 (ISO-8859-13: Baltic, new)" },
  { name => "Latin-8", file => "iso-8859-14.txt", abbr => "8",
    descr => "Latin-8 (ISO-8859-14: Celtic)" },
  { name => "Latin-9", file => "iso-8859-15.txt", abbr => "9",
    descr => "Latin-9 (ISO-8859-15: Revised Western European)" },
  { name => "DEC-MCS", file => "dec-mcs.txt", abbr => "D",
    descr => "<abbr>DEC</abbr> Multilingual Character Set" },
  { name => "CP1252", file => "cp1252.txt", abbr => "w",
    descr => "Codepage 1252 (Microsoft Windows Western European)" },
  { name => "CP1250", file => "cp1250.txt", abbr => "w2",
    descr => "Codepage 1250 (Microsoft Windows Central European)" },
  { name => "CP1254", file => "cp1254.txt", abbr => "w5",
    descr => "Codepage 1254 (Microsoft Windows Turkish)" },
  { name => "CP1257", file => "cp1257.txt", abbr => "w7",
    descr => "Codepage 1257 (Microsoft Windows Baltic)" },
  { name => "CP1258", file => "cp1258.txt", abbr => "wv",
    descr => "Codepage 1258 (Microsoft Windows Vietnamese)" },
  { name => "CP437", file => "cp437.txt", abbr => "*",
    descr => "Codepage 437 (<abbr>IBM</abbr>-<abbr>PC</abbr>: default)" },
  { name => "CP775", file => "cp775.txt", abbr => "*b",
    descr => "Codepage 775 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Baltic)" },
  { name => "CP850", file => "cp850.txt", abbr => "*w",
    descr => "Codepage 850 (<abbr>IBM</abbr>-<abbr>PC</abbr>: European)" },
  { name => "CP852", file => "cp852.txt", abbr => "*e",
    descr => "Codepage 852 (<abbr>IBM</abbr>-<abbr>PC</abbr>: East European)" },
  { name => "CP857", file => "cp857.txt", abbr => "*t",
    descr => "Codepage 857 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Turkish)" },
  { name => "CP860", file => "cp860.txt", abbr => "*p",
    descr => "Codepage 860 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Portuguese)" },
  { name => "CP861", file => "cp861.txt", abbr => "*i",
    descr => "Codepage 861 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Icelandic)" },
  { name => "CP863", file => "cp863.txt", abbr => "*q",
    descr => "Codepage 863 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Canadian French)" },
  { name => "CP865", file => "cp865.txt", abbr => "*n",
    descr => "Codepage 865 (<abbr>IBM</abbr>-<abbr>PC</abbr>: Nordic European)" },
  { name => "Mac-Roman", file => "mac-roman.txt", abbr => "M",
    descr => "Macintosh Roman" },
  { name => "Mac-Icelandic", file => "mac-iceland.txt", abbr => "Mi",
    descr => "Macintosh Icelandic" },
  { name => "Mac-Turkish", file => "mac-turkish.txt", abbr => "Mt",
    descr => "Macintosh Turkish" },
  { name => "Mac-Central-European", file => "mac-centeuro.txt", abbr => "Me",
    descr => "Macintosh Central European" },
  { name => "Mac-Croatian", file => "mac-croatian.txt", abbr => "Mc",
    descr => "Macintosh Croatian" },
  { name => "Mac-Romanian", file => "mac-romanian.txt", abbr => "Mr",
    descr => "Macintosh Romanian" },
);

my %htmlentities = (
  160=>"nbsp",  161=>"iexcl",  162=>"cent",  163=>"pound",
  164=>"curren",  165=>"yen",  166=>"brvbar",  167=>"sect",
  168=>"uml",  169=>"copy",  170=>"ordf",  171=>"laquo",
  172=>"not",  173=>"shy",  174=>"reg",  175=>"macr",
  176=>"deg",  177=>"plusmn",  178=>"sup2",  179=>"sup3",
  180=>"acute",  181=>"micro",  182=>"para",  183=>"middot",
  184=>"cedil",  185=>"sup1",  186=>"ordm",  187=>"raquo",
  188=>"frac14",  189=>"frac12",  190=>"frac34",  191=>"iquest",
  192=>"Agrave",  193=>"Aacute",  194=>"Acirc",  195=>"Atilde",
  196=>"Auml",  197=>"Aring",  198=>"AElig",  199=>"Ccedil",
  200=>"Egrave",  201=>"Eacute",  202=>"Ecirc",  203=>"Euml",
  204=>"Igrave",  205=>"Iacute",  206=>"Icirc",  207=>"Iuml",
  208=>"ETH",  209=>"Ntilde",  210=>"Ograve",  211=>"Oacute",
  212=>"Ocirc",  213=>"Otilde",  214=>"Ouml",  215=>"times",
  216=>"Oslash",  217=>"Ugrave",  218=>"Uacute",  219=>"Ucirc",
  220=>"Uuml",  221=>"Yacute",  222=>"THORN",  223=>"szlig",
  224=>"agrave",  225=>"aacute",  226=>"acirc",  227=>"atilde",
  228=>"auml",  229=>"aring",  230=>"aelig",  231=>"ccedil",
  232=>"egrave",  233=>"eacute",  234=>"ecirc",  235=>"euml",
  236=>"igrave",  237=>"iacute",  238=>"icirc",  239=>"iuml",
  240=>"eth",  241=>"ntilde",  242=>"ograve",  243=>"oacute",
  244=>"ocirc",  245=>"otilde",  246=>"ouml",  247=>"divide",
  248=>"oslash",  249=>"ugrave",  250=>"uacute",  251=>"ucirc",
  252=>"uuml",  253=>"yacute",  254=>"thorn",  255=>"yuml",
  338=>"OElig",  339=>"oelig",  352=>"Scaron",  353=>"scaron",
  376=>"Yuml",  710=>"circ",  732=>"tilde",  8194=>"ensp",
  8195=>"emsp",  8201=>"thinsp",  8204=>"zwnj",  8205=>"zwj",
  8206=>"lrm",  8207=>"rlm",  8211=>"ndash",  8212=>"mdash",
  8216=>"lsquo",  8217=>"rsquo",  8218=>"sbquo",  8220=>"ldquo",
  8221=>"rdquo",  8222=>"bdquo",  8224=>"dagger",  8225=>"Dagger",
  8240=>"permil",  8249=>"lsaquo",  8250=>"rsaquo",  8364=>"euro",
  402=>"fnof",  913=>"Alpha",  914=>"Beta",  915=>"Gamma",
  916=>"Delta",  917=>"Epsilon",  918=>"Zeta",  919=>"Eta",
  920=>"Theta",  921=>"Iota",  922=>"Kappa",  923=>"Lambda",
  924=>"Mu",  925=>"Nu",  926=>"Xi",  927=>"Omicron",
  928=>"Pi",  929=>"Rho",  931=>"Sigma",  932=>"Tau",
  933=>"Upsilon",  934=>"Phi",  935=>"Chi",  936=>"Psi",
  937=>"Omega",  945=>"alpha",  946=>"beta",  947=>"gamma",
  948=>"delta",  949=>"epsilon",  950=>"zeta",  951=>"eta",
  952=>"theta",  953=>"iota",  954=>"kappa",  955=>"lambda",
  956=>"mu",  957=>"nu",  958=>"xi",  959=>"omicron",
  960=>"pi",  961=>"rho",  962=>"sigmaf",  963=>"sigma",
  964=>"tau",  965=>"upsilon",  966=>"phi",  967=>"chi",
  968=>"psi",  969=>"omega",  977=>"thetasym",  978=>"upsih",
  982=>"piv",  8226=>"bull",  8230=>"hellip",  8242=>"prime",
  8243=>"Prime",  8254=>"oline",  8260=>"frasl",  8472=>"weierp",
  8465=>"image",  8476=>"real",  8482=>"trade",  8501=>"alefsym",
  8592=>"larr",  8593=>"uarr",  8594=>"rarr",  8595=>"darr",
  8596=>"harr",  8629=>"crarr",  8656=>"lArr",  8657=>"uArr",
  8658=>"rArr",  8659=>"dArr",  8660=>"hArr",  8704=>"forall",
  8706=>"part",  8707=>"exist",  8709=>"empty",  8711=>"nabla",
  8712=>"isin",  8713=>"notin",  8715=>"ni",  8719=>"prod",
  8721=>"sum",  8722=>"minus",  8727=>"lowast",  8730=>"radic",
  8733=>"prop",  8734=>"infin",  8736=>"ang",  8743=>"and",
  8744=>"or",  8745=>"cap",  8746=>"cup",  8747=>"int",
  8756=>"there4",  8764=>"sim",  8773=>"cong",  8776=>"asymp",
  8800=>"ne",  8801=>"equiv",  8804=>"le",  8805=>"ge",
  8834=>"sub",  8835=>"sup",  8836=>"nsub",  8838=>"sube",
  8839=>"supe",  8853=>"oplus",  8855=>"otimes",  8869=>"perp",
  8901=>"sdot",  8968=>"lceil",  8969=>"rceil",  8970=>"lfloor",
  8971=>"rfloor",  9001=>"lang",  9002=>"rang",  9674=>"loz",
  9824=>"spades",  9827=>"clubs",  9829=>"hearts",  9830=>"diams",
);

my %uni_names;

open F, "< UnicodeData-3.0.0.txt";
while ( <F> ) {
    die "Badly formed Unicode data"
	unless /^([0-9A-F]{4})\;(.*?)\;/;
    my $chr = hex($1);
    $uni_names{$chr} = $2;
}
close F;

my %csdata;

my ($csr, $cs);

foreach $csr ( @charsets ) {
    $cs = $csr->{name};
    my $fn = $csr->{file};
    open F, "< $fn";
    while ( <F> ) {
	die "Badly formed line"
	    unless /^(0+|0x[0-9a-f]+)\s+(0+|0x[0-9a-f]+)$/;
	my $num = hex($1);  my $val = hex($2);
	$csdata{$cs}{$val} = sprintf("%02x", $num);
    }
    close F;
}

sub doletter {
    my $chr = shift;
    my $k = 0;
    my $s = "";
    return unless defined($uni_names{$chr});
    return unless $uni_names{$chr} =~ /(LETTER|LIGATURE)/;
    $s = "<tr>\n";
    $s .= sprintf("<td>%04x</td>",$chr);
    $s .= "<td>";
    if (defined($htmlentities{$chr})) {
	$s .= "&$htmlentities{$chr};";
    } else {
	$s .= "&#$chr;";
    }
    $s .= "</td>";
    $s .= "<td class=\"uniname\">$uni_names{$chr}</td>\n";
    my ($csr, $cs);
    foreach $csr ( @charsets ) {
	$cs = $csr->{name};
	$s .= "<td>";
	if ( defined($csdata{$cs}{$chr}) ) {
	    $s .= $csdata{$cs}{$chr};
	    $k = 1;
	}
	$s .= "</td>";
    }
    $s .= "\n";
    $s .= "</tr>\n";
    print $s if $k;
}

my $chr;

print << '__EOF__';
<?xml version="1.0" encoding="us-ascii"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">


<head>

<title>Reverse Charset Table of Latin Characters</title>

<meta name="description" content="A table of Latin characters found in various common character sets and their relation to Unicode" lang="en" />

<meta name="keywords" content="Unicode, HTML, internationalization, i18n, character set, ISO-10646-1, ISO-8859" lang="en" />

<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />

<meta http-equiv="Content-Language" content="en" />

<style type="text/css">
.uniname { font-family: sans-serif; font-size: 40% }
</style>

</head>


<body>


<h1>Reverse Charset Table of Latin Characters</h1>


<h2>Summary</h2>

<p>This table lists the Latin characters found in a certain number of
common character sets.  Each character line gives the Unicode
hexadecimal code of the character, the character itself (if your
browser is capable of handling it), the Unicode name, and the
hexadecimal code of the character in each one of the charsets that is
capable of encoding it.</p>

<p>Characters are listed in Unicode order.  Note that the many Latin
characters found in Unicode but in none of the described character
sets are <em>not</em> listed.</p>

<p>The character sets are given by abbreviation below.</p>


__EOF__

print "<h2>Abbreviations used</h2>\n\n<dl>\n";
foreach $csr ( @charsets ) {
    print "<dt>$csr->{abbr}</dt>";
    print "<dd>$csr->{descr}</dd>\n";
}
print "</dl>\n\n\n";

print "<h2>Reverse Latin table</h2>\n\n<table border=\"1\">\n";

print "<tr>\n<th>Hex</th><th>C</th><th>Name</th>\n";
foreach $csr ( @charsets ) {
    print "<th>$csr->{abbr}</th>";
}
print "\n";
print "</tr>\n";

for ( $chr = 0xc0 ; $chr < 0x234 ; $chr++ ) {
    doletter($chr);
}

for ( $chr = 0x1e00 ; $chr < 0x1efa ; $chr++ ) {
    doletter($chr);
}

print "</table>\n\n\n</body>\n</html>\n";
