ldiscucs.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * ldisc.c: PuTTY line discipline. Sits between the input coming
  3. * from keypresses in the window, and the output channel leading to
  4. * the back end. Implements echo and/or local line editing,
  5. * depending on what's currently configured.
  6. */
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include "putty.h"
  10. #include "terminal.h"
  11. #include "ldisc.h"
  12. void lpage_send(void *handle,
  13. int codepage, const char *buf, int len, int interactive)
  14. {
  15. Ldisc ldisc = (Ldisc)handle;
  16. wchar_t *widebuffer = 0;
  17. int widesize = 0;
  18. int wclen;
  19. if (codepage < 0) {
  20. ldisc_send(ldisc, buf, len, interactive);
  21. return;
  22. }
  23. widesize = len * 2;
  24. widebuffer = snewn(widesize, wchar_t);
  25. wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);
  26. luni_send(ldisc, widebuffer, wclen, interactive);
  27. sfree(widebuffer);
  28. }
  29. void luni_send(void *handle, const wchar_t *widebuf, int len, int interactive)
  30. {
  31. Ldisc ldisc = (Ldisc)handle;
  32. int ratio = (in_utf(ldisc->term))?3:1;
  33. char *linebuffer;
  34. int linesize;
  35. int i;
  36. char *p;
  37. linesize = len * ratio * 2;
  38. linebuffer = snewn(linesize, char);
  39. if (in_utf(ldisc->term)) {
  40. /* UTF is a simple algorithm */
  41. for (p = linebuffer, i = 0; i < len; i++) {
  42. unsigned long ch = widebuf[i];
  43. if (IS_SURROGATE(ch)) {
  44. #ifdef PLATFORM_IS_UTF16
  45. if (i+1 < len) {
  46. unsigned long ch2 = widebuf[i+1];
  47. if (IS_SURROGATE_PAIR(ch, ch2)) {
  48. ch = FROM_SURROGATES(ch, ch2);
  49. i++;
  50. }
  51. } else
  52. #endif
  53. {
  54. /* Unrecognised UTF-16 sequence */
  55. ch = '.';
  56. }
  57. }
  58. if (ch < 0x80) {
  59. *p++ = (char) (ch);
  60. } else if (ch < 0x800) {
  61. *p++ = (char) (0xC0 | (ch >> 6));
  62. *p++ = (char) (0x80 | (ch & 0x3F));
  63. } else if (ch < 0x10000) {
  64. *p++ = (char) (0xE0 | (ch >> 12));
  65. *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));
  66. *p++ = (char) (0x80 | (ch & 0x3F));
  67. } else {
  68. *p++ = (char) (0xF0 | (ch >> 18));
  69. *p++ = (char) (0x80 | ((ch >> 12) & 0x3F));
  70. *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));
  71. *p++ = (char) (0x80 | (ch & 0x3F));
  72. }
  73. }
  74. } else {
  75. int rv;
  76. rv = wc_to_mb(ldisc->term->ucsdata->line_codepage, 0, widebuf, len,
  77. linebuffer, linesize, NULL, NULL, ldisc->term->ucsdata);
  78. if (rv >= 0)
  79. p = linebuffer + rv;
  80. else
  81. p = linebuffer;
  82. }
  83. if (p > linebuffer)
  84. ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);
  85. sfree(linebuffer);
  86. }