--- /dev/null
+/*\r
+ * ldisc.c: PuTTY line discipline. Sits between the input coming\r
+ * from keypresses in the window, and the output channel leading to\r
+ * the back end. Implements echo and/or local line editing,\r
+ * depending on what's currently configured.\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <ctype.h>\r
+\r
+#include "putty.h"\r
+#include "terminal.h"\r
+#include "ldisc.h"\r
+\r
+void lpage_send(void *handle,\r
+ int codepage, char *buf, int len, int interactive)\r
+{\r
+ Ldisc ldisc = (Ldisc)handle;\r
+ wchar_t *widebuffer = 0;\r
+ int widesize = 0;\r
+ int wclen;\r
+\r
+ if (codepage < 0) {\r
+ ldisc_send(ldisc, buf, len, interactive);\r
+ return;\r
+ }\r
+\r
+ widesize = len * 2;\r
+ widebuffer = snewn(widesize, wchar_t);\r
+\r
+ wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);\r
+ luni_send(ldisc, widebuffer, wclen, interactive);\r
+\r
+ sfree(widebuffer);\r
+}\r
+\r
+void luni_send(void *handle, wchar_t * widebuf, int len, int interactive)\r
+{\r
+ Ldisc ldisc = (Ldisc)handle;\r
+ int ratio = (in_utf(ldisc->term))?3:1;\r
+ char *linebuffer;\r
+ int linesize;\r
+ int i;\r
+ char *p;\r
+\r
+ linesize = len * ratio * 2;\r
+ linebuffer = snewn(linesize, char);\r
+\r
+ if (in_utf(ldisc->term)) {\r
+ /* UTF is a simple algorithm */\r
+ for (p = linebuffer, i = 0; i < len; i++) {\r
+ unsigned long ch = widebuf[i];\r
+\r
+ if ((ch & 0xF800) == 0xD800) {\r
+#ifdef PLATFORM_IS_UTF16\r
+ if (i+1 < len) {\r
+ unsigned long ch2 = widebuf[i+1];\r
+ if ((ch & 0xFC00) == 0xD800 &&\r
+ (ch2 & 0xFC00) == 0xDC00) {\r
+ ch = 0x10000 + ((ch & 0x3FF) << 10) + (ch2 & 0x3FF);\r
+ i++;\r
+ }\r
+ } else\r
+#endif\r
+ {\r
+ /* Unrecognised UTF-16 sequence */\r
+ ch = '.';\r
+ }\r
+ }\r
+\r
+ if (ch < 0x80) {\r
+ *p++ = (char) (ch);\r
+ } else if (ch < 0x800) {\r
+ *p++ = (char) (0xC0 | (ch >> 6));\r
+ *p++ = (char) (0x80 | (ch & 0x3F));\r
+ } else if (ch < 0x10000) {\r
+ *p++ = (char) (0xE0 | (ch >> 12));\r
+ *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));\r
+ *p++ = (char) (0x80 | (ch & 0x3F));\r
+ } else {\r
+ *p++ = (char) (0xF0 | (ch >> 18));\r
+ *p++ = (char) (0x80 | ((ch >> 12) & 0x3F));\r
+ *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));\r
+ *p++ = (char) (0x80 | (ch & 0x3F));\r
+ }\r
+ }\r
+ } else {\r
+ int rv;\r
+ rv = wc_to_mb(ldisc->term->ucsdata->line_codepage, 0, widebuf, len,\r
+ linebuffer, linesize, NULL, NULL, ldisc->term->ucsdata);\r
+ if (rv >= 0)\r
+ p = linebuffer + rv;\r
+ else\r
+ p = linebuffer;\r
+ }\r
+ if (p > linebuffer)\r
+ ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);\r
+\r
+ sfree(linebuffer);\r
+}\r