aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-15 19:52:31 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-15 19:52:31 +0100
commit51e123544bff3ca0bdd8f6ba6a1c507b57071ca4 (patch)
tree0b3c68e7520dc310a49cee0b6dc1abd042143224
parent5fe8298dec3736a2169719af9f0edf8592f3f7b6 (diff)
downloadsciteco-51e123544bff3ca0bdd8f6ba6a1c507b57071ca4.tar.gz
support stdio for curses interface
* ./sciteco commandline help works now * messages issued during batch-mode macro processing are written to stdout/stderr * output can be redirected
-rw-r--r--interface-gtk.cpp26
-rw-r--r--interface-gtk.h4
-rw-r--r--interface-ncurses.cpp39
-rw-r--r--interface-ncurses.h7
-rw-r--r--interface.h18
-rw-r--r--main.cpp24
6 files changed, 86 insertions, 32 deletions
diff --git a/interface-gtk.cpp b/interface-gtk.cpp
index d049045..38100fe 100644
--- a/interface-gtk.cpp
+++ b/interface-gtk.cpp
@@ -73,7 +73,7 @@ InterfaceGtk::InterfaceGtk()
}
void
-InterfaceGtk::msg(MessageType type, const gchar *fmt, ...)
+InterfaceGtk::vmsg(MessageType type, const gchar *fmt, va_list ap)
{
static const GtkMessageType type2gtk[] = {
/* [MSG_USER] = */ GTK_MESSAGE_OTHER,
@@ -82,27 +82,13 @@ InterfaceGtk::msg(MessageType type, const gchar *fmt, ...)
/* [MSG_ERROR] = */ GTK_MESSAGE_ERROR
};
- va_list ap;
+ va_list aq;
gchar buf[255];
- va_start(ap, fmt);
- g_vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
-
- switch (type) {
- case MSG_USER:
- g_printf("%s\n", buf);
- break;
- case MSG_INFO:
- g_printf("Info: %s\n", buf);
- break;
- case MSG_WARNING:
- g_fprintf(stderr, "Warning: %s\n", buf);
- break;
- case MSG_ERROR:
- g_fprintf(stderr, "Error: %s\n", buf);
- break;
- }
+ va_copy(aq, ap);
+ stdio_vmsg(type, fmt, ap);
+ g_vsnprintf(buf, sizeof(buf), fmt, aq);
+ va_end(aq);
gtk_info_bar_set_message_type(GTK_INFO_BAR(info_widget),
type2gtk[type]);
diff --git a/interface-gtk.h b/interface-gtk.h
index 95a58d7..5b48ef6 100644
--- a/interface-gtk.h
+++ b/interface-gtk.h
@@ -1,6 +1,8 @@
#ifndef __INTERFACE_GTK_H
#define __INTERFACE_GTK_H
+#include <stdarg.h>
+
#include <glib.h>
#include <gtk/gtk.h>
@@ -31,7 +33,7 @@ public:
gtk_parse_args(&argc, &argv);
}
- void msg(MessageType type, const gchar *fmt, ...) G_GNUC_PRINTF(3, 4);
+ void vmsg(MessageType type, const gchar *fmt, va_list ap);
inline sptr_t
ssm(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0)
diff --git a/interface-ncurses.cpp b/interface-ncurses.cpp
index 48dbec6..904ae6c 100644
--- a/interface-ncurses.cpp
+++ b/interface-ncurses.cpp
@@ -1,9 +1,11 @@
#include <string.h>
+#include <stdio.h>
#include <stdarg.h>
#include <locale.h>
#include <glib.h>
#include <glib/gprintf.h>
+#include <glib/gstdio.h>
#include <ncurses.h>
@@ -30,7 +32,17 @@ InterfaceNCurses::InterfaceNCurses()
: popup_window(NULL), popup_list(NULL),
popup_list_longest(0), popup_list_length(0)
{
- initscr();
+ /*
+ * Prevent the initial redraw and any escape sequences that may
+ * clobber 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!)
+ */
+ screen_tty = g_fopen("/dev/tty", "r+b");
+ screen = newterm(NULL, screen_tty, screen_tty);
+ set_term(screen);
+
raw();
cbreak();
noecho();
@@ -53,10 +65,12 @@ InterfaceNCurses::InterfaceNCurses()
msg(MSG_USER, " ");
cmdline_update();
+
+ endwin();
}
void
-InterfaceNCurses::msg(MessageType type, const gchar *fmt, ...)
+InterfaceNCurses::vmsg(MessageType type, const gchar *fmt, va_list ap)
{
static const short type2colorid[] = {
SCI_COLOR_PAIR(COLOR_BLACK, COLOR_WHITE), /* MSG_USER */
@@ -65,13 +79,14 @@ InterfaceNCurses::msg(MessageType type, const gchar *fmt, ...)
SCI_COLOR_PAIR(COLOR_BLACK, COLOR_RED) /* MSG_ERROR */
};
- va_list ap;
+ if (isendwin()) { /* batch mode */
+ stdio_vmsg(type, fmt, ap);
+ return;
+ }
wmove(msg_window, 0, 0);
wbkgdset(msg_window, ' ' | COLOR_PAIR(type2colorid[type]));
- va_start(ap, fmt);
vw_printw(msg_window, fmt, ap);
- va_end(ap);
wclrtoeol(msg_window);
wrefresh(msg_window);
@@ -152,17 +167,22 @@ InterfaceNCurses::popup_show(void)
void
InterfaceNCurses::popup_clear(void)
{
+ if (!popup_window)
+ return;
+
scintilla_refresh(sci);
redrawwin(msg_window);
wrefresh(msg_window);
- if (popup_window)
- delwin(popup_window);
+ delwin(popup_window);
popup_window = NULL;
}
void
InterfaceNCurses::event_loop(void)
{
+ /* in commandline (visual) mode, enforce redraw */
+ wrefresh(curscr);
+
for (;;) {
int key;
@@ -212,7 +232,10 @@ InterfaceNCurses::~InterfaceNCurses()
if (popup_list)
g_slist_free(popup_list);
- endwin();
+ if (!isendwin())
+ endwin();
+ delscreen(screen);
+ fclose(screen_tty);
}
/*
diff --git a/interface-ncurses.h b/interface-ncurses.h
index a9bcad5..9b938a2 100644
--- a/interface-ncurses.h
+++ b/interface-ncurses.h
@@ -1,6 +1,8 @@
#ifndef __INTERFACE_NCURSES_H
#define __INTERFACE_NCURSES_H
+#include <stdarg.h>
+
#include <glib.h>
#include <ncurses.h>
@@ -11,6 +13,9 @@
#include "interface.h"
extern class InterfaceNCurses : public Interface {
+ SCREEN *screen;
+ FILE *screen_tty;
+
Scintilla *sci;
WINDOW *sci_window;
@@ -26,7 +31,7 @@ public:
InterfaceNCurses();
~InterfaceNCurses();
- void msg(MessageType type, const gchar *fmt, ...) G_GNUC_PRINTF(3, 4);
+ void vmsg(MessageType type, const gchar *fmt, va_list ap);
inline sptr_t
ssm(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0)
diff --git a/interface.h b/interface.h
index 6e43392..f84649a 100644
--- a/interface.h
+++ b/interface.h
@@ -1,6 +1,8 @@
#ifndef __INTERFACE_H
#define __INTERFACE_H
+#include <stdarg.h>
+
#include <glib.h>
#include <Scintilla.h>
@@ -28,8 +30,16 @@ public:
MSG_WARNING,
MSG_ERROR
};
- virtual void msg(MessageType type, const gchar *fmt, ...)
- G_GNUC_PRINTF(3, 4) = 0;
+ virtual void vmsg(MessageType type, const gchar *fmt, va_list ap) = 0;
+ inline void
+ msg(MessageType type, const gchar *fmt, ...) G_GNUC_PRINTF(3, 4)
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vmsg(type, fmt, ap);
+ va_end(ap);
+ }
virtual sptr_t ssm(unsigned int iMessage,
uptr_t wParam = 0, sptr_t lParam = 0) = 0;
@@ -48,6 +58,10 @@ public:
/* main entry point */
virtual void event_loop(void) = 0;
+
+protected:
+ /* see main.cpp */
+ void stdio_vmsg(MessageType type, const gchar *fmt, va_list ap);
};
#ifdef INTERFACE_GTK
diff --git a/main.cpp b/main.cpp
index f551450..300d2f8 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,3 +1,4 @@
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -19,6 +20,29 @@
static gchar *mung_file = NULL;
+void
+Interface::stdio_vmsg(MessageType type, const gchar *fmt, va_list ap)
+{
+ gchar buf[255];
+
+ g_vsnprintf(buf, sizeof(buf), fmt, ap);
+
+ switch (type) {
+ case MSG_USER:
+ g_printf("%s\n", buf);
+ break;
+ case MSG_INFO:
+ g_printf("Info: %s\n", buf);
+ break;
+ case MSG_WARNING:
+ g_fprintf(stderr, "Warning: %s\n", buf);
+ break;
+ case MSG_ERROR:
+ g_fprintf(stderr, "Error: %s\n", buf);
+ break;
+ }
+}
+
static inline void
process_options(int &argc, char **&argv)
{