--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "kernel.h"
+static char line_buf[256];
+static int line_col = 0;
+static int esc_flag = 0;
+
+static int line_min = 30;
+static int line_max = 76;
+static FILE *out_f = stdout;
+
+void tty_init (FILE *out, int min, int max)
+{
+ out_f = out;
+ if (min > 0)
+ line_min = min;
+ if (max > 2)
+ line_max = max;
+ line_col = 0;
+ esc_flag = 0;
+}
+
+static void flush (void)
+{
+ int j;
+
+ for (j = 0; j<line_col; j++)
+ putc (line_buf[j], out_f);
+ putc ('\n', out_f);
+ line_col = 0;
+}
+
+static void split (int ch)
+{
+ int i = line_col, j;
+
+ while (1)
+ if (line_buf[--i] == ' ')
+ {
+ int extra = 0;
+
+ for (j = 0; j<i; j++)
+ {
+#if 1
+ if (j>1 && line_buf[j] >= 'A'&& line_buf[j] <= 'Z'
+ && line_buf[j-1] == ' '
+ && (line_buf[j-2] == '.' || line_buf[j-2] == ';')
+ && extra < line_max-i )
+ {
+ extra++;
+ putc (' ', out_f);
+ }
+#endif
+ putc (line_buf[j], out_f);
+ }
+ putc ('\n', out_f);
+ j = 0;
+ ++i;
+ while (i < line_col)
+ line_buf[j++] = line_buf[i++];
+ line_col = j;
+ break;
+ }
+ else if (i < line_min)
+ flush ();
+}
+
+static void escape (int ch)
+{
+ switch (ch)
+ {
+ case 'n':
+ if (line_col >= line_max)
+ split (' ');
+ else
+ flush ();
+ break;
+ case 't':
+ do
+ line_buf[line_col++] = ' ';
+ while (line_col & 7);
+ break;
+ case 's':
+ line_buf[line_col++] = ' ';
+ break;
+ default:
+ line_buf[line_col++] = ch;
+ }
+}
+
+void tty_emit (int ch)
+{
+ if (esc_flag)
+ {
+ escape (ch);
+ esc_flag = 0;
+ }
+ else if (ch == '\\')
+ esc_flag = 1;
+ else if (ch == '\n')
+ flush ();
+ else if (line_col || ch != ' ')
+ {
+ line_buf[line_col++] = ch;
+ if (line_col >= line_max)
+ split (ch);
+ }
+}