You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

keysym2ucs.c 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* $XFree86$
  2. * This module converts keysym values into the corresponding ISO 10646
  3. * (UCS, Unicode) values.
  4. *
  5. * The keysym -> UTF-8 conversion will hopefully one day be provided
  6. * by Xlib via XmbLookupString() and should ideally not have to be
  7. * done in X applications. But we are not there yet.
  8. *
  9. * We allow to represent any UCS character in the range U-00000000 to
  10. * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
  11. * This admittedly does not cover the entire 31-bit space of UCS, but
  12. * it does cover all of the characters up to U-10FFFF, which can be
  13. * represented by UTF-16, and more, and it is very unlikely that higher
  14. * UCS codes will ever be assigned by ISO. So to get Unicode character
  15. * U+ABCD you can directly use keysym 0x0100abcd.
  16. *
  17. * Author: Markus G. Kuhn <http://www.cl.cam.ac.uk/~mgk25/>,
  18. * University of Cambridge, April 2001
  19. *
  20. * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
  21. * an initial draft of the mapping table.
  22. *
  23. * This software is in the public domain. Share and enjoy!
  24. */
  25. #include "keysym2ucs.h"
  26. #include "keyucsmap.h"
  27. #define NoSymbol 0
  28. struct combiningpair {
  29. unsigned short spacing;
  30. unsigned short combining;
  31. };
  32. static const struct codepair deadtab[] = {
  33. { 0xfe50, 0x0300 }, /* dead_grave ` COMBINING GRAVE ACCENT */
  34. { 0xfe51, 0x0301 }, /* dead_acute ´ COMBINING ACUTE ACCENT */
  35. { 0xfe52, 0x0302 }, /* dead_circumflex ^ COMBINING CIRCUMFLEX ACCENT */
  36. { 0xfe53, 0x0303 }, /* dead_tilde ~ COMBINING TILDE */
  37. { 0xfe54, 0x0304 }, /* dead_macron ¯ COMBINING MACRON */
  38. { 0xfe55, 0x0306 }, /* dead_breve ˘ COMBINING BREVE */
  39. { 0xfe56, 0x0307 }, /* dead_abovedot ˙ COMBINING DOT ABOVE */
  40. { 0xfe57, 0x0308 }, /* dead_diaeresis ¨ COMBINING DIAERESIS */
  41. { 0xfe58, 0x030a }, /* dead_abovering ˚ COMBINING RING ABOVE */
  42. { 0xfe59, 0x030b }, /* dead_doubleacute ˝ COMBINING DOUBLE ACUTE ACCENT */
  43. { 0xfe5a, 0x030c }, /* dead_caron ˇ COMBINING CARON */
  44. { 0xfe5b, 0x0327 }, /* dead_cedilla ¸ COMBINING CEDILLA */
  45. { 0xfe5c, 0x0328 }, /* dead_ogonek ¸ COMBINING OGONEK */
  46. { 0xfe5d, 0x0345 }, /* dead_iota ͺ COMBINING GREEK YPOGEGRAMMENI */
  47. { 0xfe5e, 0x3099 }, /* dead_voiced_sound ゛ COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK */
  48. { 0xfe5f, 0x309a }, /* dead_semivoiced_sound ゜ COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
  49. { 0xfe60, 0x0323 }, /* dead_belowdot . COMBINING DOT BELOW */
  50. };
  51. static const struct combiningpair combinetab[] = {
  52. { 0x0060, 0x0300 }, /* GRAVE ACCENT ` COMBINING GRAVE ACCENT */
  53. { 0x00b4, 0x0301 }, /* ACUTE ACCENT ´ COMBINING ACUTE ACCENT */
  54. { 0x0027, 0x0301 }, /* APOSTROPHE ' COMBINING ACUTE ACCENT */
  55. { 0x0384, 0x0301 }, /* GREEK TONOS ΄ COMBINING ACUTE ACCENT */
  56. { 0x005e, 0x0302 }, /* CIRCUMFLEX ACCENT ^ COMBINING CIRCUMFLEX ACCENT */
  57. { 0x007e, 0x0303 }, /* TILDE ~ COMBINING TILDE */
  58. { 0x00af, 0x0304 }, /* MACRON ¯ COMBINING MACRON */
  59. { 0x02d8, 0x0306 }, /* BREVE ˘ COMBINING BREVE */
  60. { 0x02d9, 0x0307 }, /* DOT ABOVE ˙ COMBINING DOT ABOVE */
  61. { 0x00a8, 0x0308 }, /* DIAERESIS ¨ COMBINING DIAERESIS */
  62. { 0x0022, 0x0308 }, /* QUOTATION MARK " COMBINING DIAERESIS */
  63. { 0x02da, 0x030a }, /* RING ABOVE ˚ COMBINING RING ABOVE */
  64. { 0x00b0, 0x030a }, /* DEGREE SIGN ° COMBINING RING ABOVE */
  65. { 0x02dd, 0x030b }, /* DOUBLE ACUTE ACCENT ˝ COMBINING DOUBLE ACUTE ACCENT */
  66. { 0x02c7, 0x030c }, /* CARON ˇ COMBINING CARON */
  67. { 0x00b8, 0x0327 }, /* CEDILLA ¸ COMBINING CEDILLA */
  68. { 0x02db, 0x0328 }, /* OGONEK ¸ COMBINING OGONEK */
  69. { 0x037a, 0x0345 }, /* GREEK YPOGEGRAMMENI ͺ COMBINING GREEK YPOGEGRAMMENI */
  70. { 0x309b, 0x3099 }, /* KATAKANA-HIRAGANA VOICED SOUND MARK ゛COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK */
  71. { 0x309c, 0x309a }, /* KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK ゜COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
  72. { 0x002e, 0x0323 }, /* FULL STOP . COMBINING DOT BELOW */
  73. { 0x0385, 0x0344 }, /* GREEK DIALYTIKA TONOS ΅ COMBINING GREEK DIALYTIKA TONOS */
  74. };
  75. static unsigned find_ucs(unsigned keysym,
  76. const struct codepair *table, int entries)
  77. {
  78. int min = 0;
  79. int max = entries - 1;
  80. int mid;
  81. /* binary search in table */
  82. while (max >= min) {
  83. mid = (min + max) / 2;
  84. if (table[mid].keysym < keysym)
  85. min = mid + 1;
  86. else if (table[mid].keysym > keysym)
  87. max = mid - 1;
  88. else {
  89. /* found it */
  90. return table[mid].ucs;
  91. }
  92. }
  93. return -1;
  94. }
  95. static unsigned find_sym(unsigned ucs,
  96. const struct codepair *table, int entries)
  97. {
  98. int cur = 0;
  99. int max = entries - 1;
  100. /* linear search in table */
  101. while (cur <= max) {
  102. if (table[cur].ucs == ucs)
  103. return table[cur].keysym;
  104. cur++;
  105. }
  106. return NoSymbol;
  107. }
  108. unsigned keysym2ucs(unsigned keysym)
  109. {
  110. unsigned ucs;
  111. /* first check for Latin-1 characters (1:1 mapping) */
  112. if ((keysym >= 0x0020 && keysym <= 0x007e) ||
  113. (keysym >= 0x00a0 && keysym <= 0x00ff))
  114. return keysym;
  115. /* also check for directly encoded 24-bit UCS characters */
  116. if ((keysym & 0xff000000) == 0x01000000)
  117. return keysym & 0x00ffffff;
  118. /* normal key? */
  119. ucs = find_ucs(keysym, keysymtab,
  120. sizeof(keysymtab) / sizeof(struct codepair));
  121. if (ucs != (unsigned)-1)
  122. return ucs;
  123. /* dead key? */
  124. ucs = find_ucs(keysym, deadtab,
  125. sizeof(deadtab) / sizeof(struct codepair));
  126. if (ucs != (unsigned)-1)
  127. return ucs;
  128. /* no matching Unicode value found */
  129. return -1;
  130. }
  131. unsigned ucs2keysym(unsigned ucs)
  132. {
  133. unsigned keysym;
  134. /* first check for Latin-1 characters (1:1 mapping) */
  135. if ((ucs >= 0x0020 && ucs <= 0x007e) ||
  136. (ucs >= 0x00a0 && ucs <= 0x00ff))
  137. return ucs;
  138. /* normal key? */
  139. keysym = find_sym(ucs, keysymtab,
  140. sizeof(keysymtab) / sizeof(struct codepair));
  141. if (keysym != NoSymbol)
  142. return keysym;
  143. /* dead key? */
  144. keysym = find_sym(ucs, deadtab,
  145. sizeof(deadtab) / sizeof(struct codepair));
  146. if (keysym != NoSymbol)
  147. return keysym;
  148. /* us the directly encoded 24-bit UCS character */
  149. if ((ucs & 0xff000000) == 0)
  150. return ucs | 0x01000000;
  151. /* no matching keysym value found */
  152. return NoSymbol;
  153. }
  154. unsigned ucs2combining(unsigned spacing)
  155. {
  156. int cur = 0;
  157. int max = sizeof(combinetab) / sizeof(struct combiningpair) - 1;
  158. /* linear search in table */
  159. while (cur <= max) {
  160. if (combinetab[cur].spacing == spacing)
  161. return combinetab[cur].combining;
  162. cur++;
  163. }
  164. /* no matching Unicode value found */
  165. return -1;
  166. }