From 4e93cbf496c82926f42c0eaf270920f126ace3f8 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Mon, 11 Dec 2006 18:48:44 +0100 Subject: [PATCH] Added the keybinding ('R' by default) for reading documents out using the festival program. ELinks automatically scrolls down when read line is at the bottom of the page. Press 'R' for start or stop reading. --- configure.in | 6 +- src/config/actions-main.inc | 1 + src/config/kbdbind.c | 1 + src/main/main.c | 5 ++ src/viewer/action.c | 7 ++ src/viewer/text/Makefile | 2 +- src/viewer/text/festival.c | 155 ++++++++++++++++++++++++++++++++++++ src/viewer/text/festival.h | 22 +++++ src/viewer/text/link.c | 4 + 9 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 src/viewer/text/festival.c create mode 100644 src/viewer/text/festival.h diff --git a/configure.in b/configure.in index 4ee940a9..8c1e2c5c 100644 --- a/configure.in +++ b/configure.in @@ -93,6 +93,9 @@ if test "x$CONFIG_DOC" != xno; then fi fi +AC_PATH_PROGS(FESTIVAL, "festival", [/usr/bin/festival]) +AC_SUBST(FESTIVAL) +AC_DEFINE_UNQUOTED(FESTIVAL, "$FESTIVAL", [Festival]) AC_SUBST(ASCIIDOC_FLAGS) AC_SUBST(CONFIG_ASCIIDOC) AC_SUBST(CONFIG_POD2HTML) @@ -283,7 +286,7 @@ AC_CHECK_FUNCS(strcasecmp strncasecmp strcasestr strstr strchr strrchr) AC_CHECK_FUNCS(memmove bcopy stpcpy strdup index isdigit mempcpy memrchr) AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf) AC_CHECK_FUNCS(getifaddrs getpwnam inet_pton inet_ntop) -AC_CHECK_FUNCS(fflush fsync fseeko ftello sigaction) +AC_CHECK_FUNCS(fflush fork fsync fseeko ftello sigaction) AC_CHECK_FUNCS(gettimeofday clock_gettime) AC_HAVE_FUNCS(cygwin_conv_to_full_win32_path) @@ -1334,6 +1337,7 @@ EL_ARG_ENABLE(CONFIG_SMALL, small, [Small binary], EL_ARG_ENABLE(CONFIG_UTF8, utf-8, [UTF-8], [ --enable-utf-8 enable UTF-8 support]) +EL_LOG_CONFIG(FESTIVAL, [festival], []) AC_ARG_ENABLE(weehoofooboomookerchoo, [ diff --git a/src/config/actions-main.inc b/src/config/actions-main.inc index 9626c9dd..939943dc 100644 --- a/src/config/actions-main.inc +++ b/src/config/actions-main.inc @@ -85,6 +85,7 @@ ACTION_(MAIN, "save-as", SAVE_AS, N__("Save the current document in source form" ACTION_(MAIN, "save-formatted", SAVE_FORMATTED, N__("Save the current document in formatted form"), ACTION_RESTRICT_ANONYMOUS | ACTION_REQUIRE_VIEW_STATE | ACTION_REQUIRE_LOCATION), ACTION_(MAIN, "save-options", SAVE_OPTIONS, N__("Save options"), ACTION_RESTRICT_ANONYMOUS), ACTION_(MAIN, "save-url-as", SAVE_URL_AS, N__("Save URL as"), ACTION_RESTRICT_ANONYMOUS), +ACTION_(MAIN, "say-text", SAY_TEXT, N__("Reads out the document"), ACTION_REQUIRE_VIEW_STATE), ACTION_(MAIN, "scroll-down", SCROLL_DOWN, N__("Scroll down"), ACTION_REQUIRE_VIEW_STATE), ACTION_(MAIN, "scroll-left", SCROLL_LEFT, N__("Scroll left"), ACTION_REQUIRE_VIEW_STATE), ACTION_(MAIN, "scroll-right", SCROLL_RIGHT, N__("Scroll right"), ACTION_REQUIRE_VIEW_STATE), diff --git a/src/config/kbdbind.c b/src/config/kbdbind.c index 378ba8fa..1aafe614 100644 --- a/src/config/kbdbind.c +++ b/src/config/kbdbind.c @@ -662,6 +662,7 @@ static struct default_kb default_main_keymap[] = { { { 'N', KBD_MOD_CTRL }, ACT_MAIN_SCROLL_DOWN }, { { 'P', KBD_MOD_CTRL }, ACT_MAIN_SCROLL_UP }, { { 'Q', KBD_MOD_NONE }, ACT_MAIN_REALLY_QUIT }, + { { 'R', KBD_MOD_NONE }, ACT_MAIN_SAY_TEXT }, { { 'R', KBD_MOD_CTRL }, ACT_MAIN_RELOAD }, { { 'T', KBD_MOD_NONE }, ACT_MAIN_OPEN_LINK_IN_NEW_TAB_IN_BACKGROUND }, { { 'W', KBD_MOD_NONE }, ACT_MAIN_TOGGLE_WRAP_TEXT }, diff --git a/src/main/main.c b/src/main/main.c index 5901665f..cbf29a18 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -52,6 +52,7 @@ #include "util/memdebug.h" #include "util/memory.h" #include "viewer/dump/dump.h" +#include "viewer/text/festival.h" #include "viewer/text/marks.h" struct program program; @@ -109,6 +110,10 @@ init(void) int fd = -1; enum retval ret; +#ifdef HAVE_FORK + festival.in = -1; + festival.out = -1; +#endif init_osdep(); check_cwd(); diff --git a/src/viewer/action.c b/src/viewer/action.c index 3089a19f..662dd50d 100644 --- a/src/viewer/action.c +++ b/src/viewer/action.c @@ -39,6 +39,7 @@ #include "session/task.h" #include "viewer/action.h" #include "viewer/text/draw.h" +#include "viewer/text/festival.h" #include "viewer/text/form.h" #include "viewer/text/link.h" #include "viewer/text/search.h" @@ -472,6 +473,12 @@ do_action(struct session *ses, enum main_action action_id, int verbose) save_url_as(ses); break; + case ACT_MAIN_SAY_TEXT: +#ifdef HAVE_FORK + run_festival(ses, doc_view); +#endif + break; + case ACT_MAIN_SCROLL_DOWN: status = scroll_down(ses, doc_view); break; diff --git a/src/viewer/text/Makefile b/src/viewer/text/Makefile index 06190f1e..1a843a7b 100644 --- a/src/viewer/text/Makefile +++ b/src/viewer/text/Makefile @@ -3,6 +3,6 @@ include $(top_builddir)/Makefile.config OBJS-$(CONFIG_MARKS) += marks.o -OBJS = draw.o form.o link.o search.o textarea.o view.o vs.o +OBJS = draw.o festival.o form.o link.o search.o textarea.o view.o vs.o include $(top_srcdir)/Makefile.lib diff --git a/src/viewer/text/festival.c b/src/viewer/text/festival.c new file mode 100644 index 00000000..0e95c5f9 --- /dev/null +++ b/src/viewer/text/festival.c @@ -0,0 +1,155 @@ +/* festival */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_FORK + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "elinks.h" + +#include "document/document.h" +#include "document/view.h" +#include "main/select.h" +#include "osdep/osdep.h" +#include "protocol/common.h" +#include "util/box.h" +#include "util/string.h" +#include "viewer/action.h" +#include "viewer/text/draw.h" +#include "viewer/text/festival.h" +#include "viewer/text/vs.h" + +struct fest festival; + + +static void read_from_festival(struct fest *); +static void write_to_festival(struct fest *); + +static void +read_from_festival(struct fest *fest) +{ + while (1) { + unsigned char input[512]; + int r = safe_read(fest->in, input, 512); + + if (r <= 0) break; + + if (input[r - 1] == ' ') { + write_to_festival(fest); + break; + } + } + set_handlers(fest->in, (select_handler_T) read_from_festival, + NULL, NULL, fest); +} + +static void +write_to_festival(struct fest *fest) +{ + struct string buf; + int i, w; + int len; + struct document_view *doc_view = fest->doc_view; + struct document *doc = doc_view->document; + struct screen_char *data; + + if (fest->line >= doc->height) + fest->running = 0; + if (!fest->running) + return; + + len = doc->data[fest->line].length; + int_upper_bound(&len, 512); + + if (!init_string(&buf)) + return; + + data = doc->data[fest->line].chars; + add_to_string(&buf, "(SayText \""); + for (i = 0; i < len; i++) { + unsigned char ch = (unsigned char)data[i].data; + + if (ch == '"' || ch == '\\') + add_char_to_string(&buf, '\\'); + add_char_to_string(&buf, ch); + } + add_to_string(&buf, "\")\n"); + + w = safe_write(fest->out, buf.source, buf.length); + if (w >= 0) { + if (fest->line > doc_view->vs->y + doc_view->box.height) { + move_page_down(doc_view->session, doc_view); + refresh_view(doc_view->session, doc_view, 0); + } + fest->line++; + } + done_string(&buf); +} + +static int +init_festival(void) +{ + int in_pipe[2] = {-1, -1}; + int out_pipe[2] = {-1, -1}; + pid_t cpid; + + if (access(FESTIVAL, X_OK)) + return 1; + + if (c_pipe(in_pipe) || c_pipe(out_pipe)) { + if (in_pipe[0] >= 0) close(in_pipe[0]); + if (in_pipe[1] >= 0) close(in_pipe[1]); + if (out_pipe[0] >= 0) close(out_pipe[0]); + if (out_pipe[1] >= 0) close(out_pipe[1]); + return 1; + } + + cpid = fork(); + if (cpid == -1) { + close(in_pipe[0]); + close(in_pipe[1]); + close(out_pipe[0]); + close(out_pipe[1]); + return 1; + } + if (!cpid) { + dup2(out_pipe[1], 1); + dup2(in_pipe[0], 0); + close(out_pipe[0]); + close(in_pipe[1]); + close(2); + close_all_non_term_fd(); + execl(FESTIVAL, "festival", "-i", NULL); + _exit(0); + } else { + close(out_pipe[1]); + close(in_pipe[0]); + festival.in = out_pipe[0]; + festival.out = in_pipe[1]; + set_handlers(festival.in, (select_handler_T) read_from_festival, + NULL, NULL, &festival); + return 0; + } +} + +void +run_festival(struct session *ses, struct document_view *doc_view) +{ + if (festival.in == -1 && init_festival()) + return; + + festival.doc_view = doc_view; + festival.line = doc_view->vs->y; + festival.running = !festival.running; + + if (festival.running) { + write_to_festival(&festival); + } +} +#endif diff --git a/src/viewer/text/festival.h b/src/viewer/text/festival.h new file mode 100644 index 00000000..d0631bdc --- /dev/null +++ b/src/viewer/text/festival.h @@ -0,0 +1,22 @@ + +#ifndef EL__VIEWER_TEXT_FESTIVAL_H +#define EL__VIEWER_TEXT_FESTIVAL_H + +struct session; +struct document_view; + +struct fest { + struct document_view *doc_view; + int line; + int in; + int out; + unsigned int running:1; +}; + +#ifdef HAVE_FORK +extern struct fest festival; + +void run_festival(struct session *, struct document_view *); +#endif + +#endif diff --git a/src/viewer/text/link.c b/src/viewer/text/link.c index 40e65e03..43928149 100644 --- a/src/viewer/text/link.c +++ b/src/viewer/text/link.c @@ -38,6 +38,7 @@ #include "util/memory.h" #include "util/string.h" #include "viewer/action.h" +#include "viewer/text/festival.h" #include "viewer/text/form.h" #include "viewer/text/link.h" #include "viewer/text/search.h" @@ -984,6 +985,9 @@ goto_current_link(struct session *ses, struct document_view *doc_view, int do_re } done_uri(uri); +#ifdef HAVE_FORK + festival.line = 0; +#endif return link; }