+static int
+init_screen(
+#if HAVE_USE_WINDOW
+ SCREEN *sp GCC_UNUSED,
+#endif
+ void *arg)
+{
+ DITTO *target = (DITTO *) arg;
+ int high, wide;
+ int k;
+
+ cbreak();
+ noecho();
+ scrollok(stdscr, TRUE);
+ box(stdscr, 0, 0);
+
+ target->parents = typeCalloc(WINDOW *, (size_t) target->length);
+ target->windows = typeCalloc(WINDOW *, (size_t) target->length);
+ target->peeks = typeCalloc(PEEK, (size_t) target->length);
+
+ high = (LINES - 2) / target->length;
+ wide = (COLS - 2);
+ for (k = 0; k < target->length; ++k) {
+ WINDOW *outer = newwin(high, wide, 1 + (high * k), 1);
+ WINDOW *inner = derwin(outer, high - 2, wide - 2, 1, 1);
+
+ box(outer, 0, 0);
+ MvWAddStr(outer, 0, 2, target->titles[k]);
+ wnoutrefresh(outer);
+
+ scrollok(inner, TRUE);
+ keypad(inner, TRUE);
+#ifndef USE_PTHREADS
+ nodelay(inner, TRUE);
+#endif
+
+ target->parents[k] = outer;
+ target->windows[k] = inner;
+ }
+ doupdate();
+ return TRUE;
+}
+
+static void
+open_screen(DITTO * target, char **source, int length, int which1)
+{
+ if (which1 != 0) {
+ target->input =
+ target->output = open_tty(source[which1]);
+ } else {
+ target->input = stdin;
+ target->output = stdout;
+ }
+
+ target->which1 = which1;
+ target->titles = source;
+ target->length = length;
+ target->fifo.head = -1;
+ target->screen = newterm((char *) 0, /* assume $TERM is the same */
+ target->output,
+ target->input);
+
+ if (target->screen == 0)
+ failed("newterm");
+
+ (void) USING_SCREEN(target->screen, init_screen, target);
+}
+
+static int
+close_screen(
+#if HAVE_USE_WINDOW
+ SCREEN *sp GCC_UNUSED,
+#endif
+ void *arg GCC_UNUSED)
+{
+#if HAVE_USE_WINDOW
+ (void) sp;
+#endif
+ (void) arg;
+ return endwin();
+}
+
+/*
+ * Read data from the 'source' screen.
+ */
+static int
+read_screen(
+#if HAVE_USE_WINDOW
+ SCREEN *sp GCC_UNUSED,
+#endif
+ void *arg)
+{
+ DDATA *data = (DDATA *) arg;
+ DITTO *ditto = &(data->ditto[data->source]);
+ WINDOW *win = ditto->windows[data->source];
+ int ch = wgetch(win);
+
+ if (ch > 0 && ch < 256)
+ put_fifo(&(ditto->fifo), ch);
+ else
+ ch = ERR;
+
+ return ch;
+}
+
+/*
+ * Write all of the data that's in fifos for the 'target' screen.
+ */
+static int
+write_screen(
+#if HAVE_USE_WINDOW
+ SCREEN *sp GCC_UNUSED,
+#endif
+ void *arg GCC_UNUSED)
+{
+ DDATA *data = (DDATA *) arg;
+ DITTO *ditto = &(data->ditto[data->target]);
+ bool changed = FALSE;
+ int which;
+
+ for (which = 0; which < ditto->length; ++which) {
+ WINDOW *win = ditto->windows[which];
+ FIFO *fifo = &(data->ditto[which].fifo);
+ PEEK *peek = &(ditto->peeks[which]);
+ int ch;
+
+ while ((ch = peek_fifo(fifo, peek)) > 0) {
+ changed = TRUE;
+
+ waddch(win, (chtype) ch);
+ wnoutrefresh(win);
+ }
+ }
+
+ if (changed)
+ doupdate();
+ return OK;
+}
+
+static void
+show_ditto(DITTO * data, int count, DDATA * ddata)
+{
+ int n;
+
+ (void) data;
+ for (n = 0; n < count; n++) {
+ ddata->target = n;
+ USING_SCREEN(data[n].screen, write_screen, (void *) ddata);
+ }
+}
+
+#ifdef USE_PTHREADS
+static void *
+handle_screen(void *arg)
+{
+ DDATA ddata;
+ int ch;
+
+ memset(&ddata, 0, sizeof(ddata));
+ ddata.ditto = (DITTO *) arg;
+ ddata.source = ddata.ditto->which1;
+ ddata.ditto -= ddata.source; /* -> base of array */
+
+ for (;;) {
+ ch = read_screen(ddata.ditto->screen, &ddata);
+ if (ch == CTRL('D')) {
+ int later = (ddata.source ? ddata.source : -1);
+ int j;
+
+ for (j = ddata.ditto->length - 1; j > 0; --j) {
+ if (j != later) {
+ pthread_cancel(ddata.ditto[j].thread);
+ }
+ }
+ if (later > 0) {
+ pthread_cancel(ddata.ditto[later].thread);
+ }
+ break;
+ }
+ show_ditto(ddata.ditto, ddata.ditto->length, &ddata);
+ }
+ return NULL;
+}
+#endif
+