diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2015-03-12 04:19:11 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2015-03-12 04:19:11 +0100 |
commit | 4dced2c9d230b88e910e46a78e3e559792520ae1 (patch) | |
tree | e6c9c358ed1a70193178b8327b256ca8b01a8680 | |
parent | 7ceabb232364a4dca0d2418ad1b0dfd01168b145 (diff) | |
download | sciteco-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.cpp | 83 | ||||
-rw-r--r-- | src/interface-curses.h | 4 |
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); |