home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 February / PCWorld_2000-02_cd.bin / live / usr / share / xterm / unicode / convmap.pl next >
Perl Script  |  1999-09-19  |  6KB  |  178 lines

  1. #!/usr/bin/perl
  2. # Generate keysym2ucs.c file
  3. #
  4. # $XFree86: xc/programs/xterm/unicode/convmap.pl,v 1.4 1999/07/11 08:49:53 dawes Exp $
  5.  
  6. sub utf8 ($) {
  7.     my $c = shift(@_);
  8.  
  9.     if ($c < 0x80) {
  10.         return sprintf("%c", $c);
  11.     } elsif ($c < 0x800) {
  12.         return sprintf("%c%c", 0xc0 | ($c >> 6), 0x80 | ($c & 0x3f));
  13.     } elsif ($c < 0x10000) {
  14.         return sprintf("%c%c%c",
  15.                        0xe0 |  ($c >> 12),
  16.                        0x80 | (($c >>  6) & 0x3f),
  17.                        0x80 | ( $c        & 0x3f));
  18.     } elsif ($c < 0x200000) {
  19.         return sprintf("%c%c%c%c",
  20.                        0xf0 |  ($c >> 18),
  21.                        0x80 | (($c >> 12) & 0x3f),
  22.                        0x80 | (($c >>  6) & 0x3f),
  23.                        0x80 | ( $c        & 0x3f));
  24.     } elsif ($c < 0x4000000) {
  25.         return sprintf("%c%c%c%c%c",
  26.                        0xf8 |  ($c >> 24),
  27.                        0x80 | (($c >> 18) & 0x3f),
  28.                        0x80 | (($c >> 12) & 0x3f),
  29.                        0x80 | (($c >>  6) & 0x3f),
  30.                        0x80 | ( $c        & 0x3f));
  31.  
  32.     } elsif ($c < 0x80000000) {
  33.         return sprintf("%c%c%c%c%c%c",
  34.                        0xfe |  ($c >> 30),
  35.                        0x80 | (($c >> 24) & 0x3f),
  36.                        0x80 | (($c >> 18) & 0x3f),
  37.                        0x80 | (($c >> 12) & 0x3f),
  38.                        0x80 | (($c >> 6)  & 0x3f),
  39.                        0x80 | ( $c        & 0x3f));
  40.     } else {
  41.         return utf8(0xfffd);
  42.     }
  43. }
  44.  
  45. $unicodedata = "UnicodeData-Latest.txt";
  46.  
  47. # read list of all Unicode names
  48. if (!open(UDATA, $unicodedata) && !open(UDATA, "$unicodedata")) {
  49.     die ("Can't open Unicode database '$unicodedata':\n$!\n\n" .
  50.          "Please make sure that you have downloaded the file\n" .
  51.          "ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData-Latest.txt\n");
  52. }
  53. while (<UDATA>) {
  54.     if (/^([0-9,A-F]{4});([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*)$/) {
  55.         $name{hex($1)} = $2;
  56.     } else {
  57.         die("Syntax error in line '$_' in file '$unicodedata'");
  58.     }
  59. }
  60. close(UDATA);
  61.  
  62. # read mapping (from http://wsinwp07.win.tue.nl:1234/unicode/keysym.map)
  63. open(LIST, "<keysym.map") || die ("Can't open map file:\n$!\n");
  64. while (<LIST>) {
  65.     if (/^0x([0-9a-f]{4})\s+U([0-9a-f]{4})\s*(\#.*)?$/){
  66.         $keysym = hex($1);
  67.         $ucs = hex($2);
  68.         $keysym_to_ucs{$keysym} = $ucs;
  69.     } elsif (/^\s*\#/ || /^\s*$/) {
  70.     } else {
  71.         die("Syntax error in 'list' in line\n$_\n");
  72.     }
  73. }
  74. close(LIST);
  75.  
  76. # read entries in keysymdef.h
  77. open(LIST, "</usr/include/X11/keysymdef.h") || die ("Can't open keysymdef.h:\n$!\n");
  78. while (<LIST>) {
  79.     if (/^\#define\s+XK_([A-Za-z_0-9]+)\s+0x([0-9a-fA-F]+)\s*(\/.*)?$/) {
  80.     next if /\/\* deprecated \*\//;
  81.     $keysymname = $1;
  82.     $keysym = hex($2);
  83.     $keysym_to_keysymname{$keysym} = $keysymname;
  84.     }
  85. }
  86. close(LIST);
  87.  
  88. print <<EOT;
  89. /* \$XFree86\$
  90.  * This module converts keysym values into the corresponding ISO 10646-1
  91.  * (UCS, Unicode) values.
  92.  *
  93.  * The array keysymtab[] contains pairs of X11 keysym values for graphical
  94.  * characters and the corresponding Unicode value. The function
  95.  * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
  96.  * therefore keysymtab[] must remain SORTED by keysym value.
  97.  *
  98.  * The keysym -> UTF-8 conversion will hopefully one day be provided
  99.  * by Xlib via XmbLookupString() and should ideally not have to be
  100.  * done in X applications. But we are not there yet.
  101.  *
  102.  * We allow to represent any UCS character in the range U+00000000 to
  103.  * U+00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
  104.  * This admittedly does not cover the entire 31-bit space of UCS, but
  105.  * it does cover all of the characters up to U+10FFFF, which can be
  106.  * represented by UTF-16, and more, and it is very unlikely that higher
  107.  * UCS codes will ever be assigned by ISO. So to get Unicode character
  108.  * U+ABCD you can directly use keysym 0x1000abcd.
  109.  *
  110.  * NOTE: The comments in the table below contain the actual character
  111.  * encoded in UTF-8, so for viewing and editing best use an editor in
  112.  * UTF-8 mode.
  113.  *
  114.  * Author: Markus G. Kuhn <mkuhn\@acm.org>, University of Cambridge, June 1999
  115.  *
  116.  * Special thanks to Richard Verhoeven <river\@win.tue.nl> for preparing
  117.  * an initial draft of the mapping table.
  118.  *
  119.  * This software is in the public domain. Share and enjoy!
  120.  */
  121.  
  122. #include "keysym2ucs.h"
  123.  
  124. struct codepair {
  125.   unsigned short keysym;
  126.   unsigned short ucs;
  127. } keysymtab[] = {
  128. EOT
  129.  
  130. for $keysym (sort {$a <=> $b} keys(%keysym_to_keysymname)) {
  131.     $ucs = $keysym_to_ucs{$keysym};
  132.     next if $keysym >= 0xf000 || $keysym < 0x100;
  133.     if ($ucs) {
  134.     printf("  { 0x%04x, 0x%04x }, /*%28s %s %s */\n",
  135.            $keysym, $ucs, $keysym_to_keysymname{$keysym}, utf8($ucs),
  136.            defined($name{$ucs}) ? $name{$ucs} : "???" );
  137.     } else {
  138.     printf("/*  0x%04x   %39s ? ??? */\n",
  139.            $keysym, $keysym_to_keysymname{$keysym});
  140.     }
  141. }
  142.  
  143. print <<EOT;
  144. };
  145.  
  146. long keysym2ucs(KeySym keysym)
  147. {
  148.     int min = 0;
  149.     int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
  150.     int mid;
  151.  
  152.     /* first check for Latin-1 characters (1:1 mapping) */
  153.     if ((keysym >= 0x0020 && keysym <= 0x007e) ||
  154.         (keysym >= 0x00a0 && keysym <= 0x00ff))
  155.         return keysym;
  156.  
  157.     /* also check for directly encoded 24-bit UCS characters */
  158.     if ((keysym & 0xff000000) == 0x01000000)
  159.     return keysym & 0x00ffffff;
  160.  
  161.     /* binary search in table */
  162.     while (max >= min) {
  163.     mid = (min + max) / 2;
  164.     if (keysymtab[mid].keysym < keysym)
  165.         min = mid + 1;
  166.     else if (keysymtab[mid].keysym > keysym)
  167.         max = mid - 1;
  168.     else {
  169.         /* found it */
  170.         return keysymtab[mid].ucs;
  171.     }
  172.     }
  173.  
  174.     /* no matching Unicode value found */
  175.     return -1;
  176. }
  177. EOT
  178.