aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2015-03-12 04:19:11 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2015-03-12 04:19:11 +0100
commit4dced2c9d230b88e910e46a78e3e559792520ae1 (patch)
treee6c9c358ed1a70193178b8327b256ca8b01a8680
parent7ceabb232364a4dca0d2418ad1b0dfd01168b145 (diff)
downloadsciteco-4dced2c9d230b88e910e46a78e3e559792520ae1.tar.gz
improved ncurses batch mode initialization
* I now understand better why the old initialization worked ;-) By not calling initscr(), we could prevent some terminal setup and screen clearing usually performed which would interfere with with having a clean stdout stream. However the Curses screen was still basically attached to the terminal. * That's why there was screen flickering in urxvt when calling sciteco (even in batch mode). Also that's why calling batch-mode SciTECO did not work from other Curses programs (including SciTECO). * The new implementation directs Curses at /dev/null, so it will completely stay away from /dev/tty. * /dev/tty is associated with the Curses screen only when the interactive mode is initialized. This works elegantly via freopen() - there's no need to create a new Curses screen. * This does currently not work on PDCurses where the batch mode will still initscr() followed by endwin(). I should investigate how newterm() behaves there - especially on Windows.
-rw-r--r--src/interface-curses.cpp83
-rw-r--r--src/interface-curses.h4
2 files changed, 65 insertions, 22 deletions
diff --git a/src/interface-curses.cpp b/src/interface-curses.cpp
index 5502542..cc6ccd1 100644
--- a/src/interface-curses.cpp
+++ b/src/interface-curses.cpp
@@ -21,8 +21,10 @@
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <stdarg.h>
#include <locale.h>
+#include <errno.h>
#include <glib.h>
#include <glib/gprintf.h>
@@ -99,10 +101,7 @@ ViewCurses::initialize_impl(void)
void
InterfaceCurses::main_impl(int &argc, char **&argv)
{
- init_screen();
- cbreak();
- noecho();
- curs_set(0); /* Scintilla draws its own cursor */
+ init_batch();
setlocale(LC_CTYPE, ""); /* for displaying UTF-8 characters properly */
@@ -115,48 +114,81 @@ InterfaceCurses::main_impl(int &argc, char **&argv)
#ifdef EMSCRIPTEN
nodelay(cmdline_window, TRUE);
-#else
-#ifndef PDCURSES_WIN32A
+#elif !defined(PDCURSES_WIN32A)
/* workaround: endwin() is somewhat broken in the win32a port */
endwin();
#endif
-#endif
}
-#ifdef __PDCURSES__ /* Any PDCurses */
+#if defined(__PDCURSES__) || !defined(G_OS_UNIX)
void
-InterfaceCurses::init_screen(void)
+InterfaceCurses::init_batch(void)
{
#ifdef PDCURSES_WIN32A
/* enables window resizing on Win32a port */
PDC_set_resize_limits(25, 0xFFFF, 80, 0xFFFF);
#endif
+ /*
+ * PDCurses does not seem to support redirecting
+ * the terminal to arbitrary files, so the
+ * newterm() hack for UNIX/ncurses does not
+ * work here.
+ */
initscr();
+}
- screen_tty = NULL;
- screen = NULL;
+void
+InterfaceCurses::init_interactive(void)
+{
+ /*
+ * Nothing to do, we are already controlling the
+ * terminal.
+ */
}
-#else
+#else /* UNIX, no PDCurses */
void
-InterfaceCurses::init_screen(void)
+InterfaceCurses::init_batch(void)
{
/*
- * Prevent the initial redraw and any escape sequences that may
- * interfere with stdout, so we may use the terminal in
- * cooked mode, for commandline help and batch processing.
- * Scintilla must be initialized for batch processing to work.
- * (Frankly I have no idea why this works!)
+ * This sets stdscr to a new screen associated
+ * with /dev/null.
+ * This way we get ncurses to leave the current
+ * controlling tty alone, while still initializing
+ * Curses (required by Scintilla and thus for
+ * batch processing).
*/
- screen_tty = g_fopen("/dev/tty", "r+b");
+ screen_tty = g_fopen("/dev/null", "r+b");
+ g_assert(screen_tty != NULL);
screen = newterm(NULL, screen_tty, screen_tty);
- set_term(screen);
+ def_shell_mode();
}
-#endif /* !__PDCURSES__ */
+void
+InterfaceCurses::init_interactive(void)
+{
+ /*
+ * To initialize interactive mode, we
+ * reopen the file opened for Curses in init_batch()
+ * with the current controlling terminal device
+ * (see tty(4)).
+ * Should also work with newterm(), but this
+ * seems more elegant.
+ */
+ if (!g_freopen("/dev/tty", "r+b", screen_tty)) {
+ /* no controlling terminal, process detached? */
+ g_fprintf(stderr, "Error initializing interactice mode: %s\n",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ def_shell_mode();
+}
+
+#endif
void
InterfaceCurses::resize_all_windows(void)
@@ -622,6 +654,15 @@ InterfaceCurses::event_loop_impl(void)
{
static const Cmdline empty_cmdline;
+ /*
+ * Initialize Curses for interactive mode
+ */
+ init_interactive();
+
+ cbreak();
+ noecho();
+ curs_set(0); /* Scintilla draws its own cursor */
+
/* initial refresh */
/* FIXME: this does wrefresh() internally */
current_view->refresh();
diff --git a/src/interface-curses.h b/src/interface-curses.h
index 2a83bcc..5da7e56 100644
--- a/src/interface-curses.h
+++ b/src/interface-curses.h
@@ -147,7 +147,9 @@ public:
void event_loop_impl(void);
private:
- void init_screen(void);
+ void init_batch(void);
+ void init_interactive(void);
+
void resize_all_windows(void);
void draw_info(void);