@@ 194,7 194,8 @@ int levenshtein_distance(const char *a, const char* b) {
}
int MAX_DIST = 3; // Is this ideal?
-char *select_link(char **links, char *command) {
+char **links = NULL;
+char *select_link(char *command) {
// Pass 1, min distance
int score = INT_MAX;
for (int i = 0; strcmp(links[i], " ") != 0; i++) {
@@ 210,7 211,7 @@ char *select_link(char **links, char *command) {
// Pass 3: Retrieve answer
for (int i = 0; strcmp(links[i], " ") != 0; i += 3) {
- if (command[0] != '\0') {// "" to read entire link table...
+ if (command[0] != '\0' || command[0] == '\n') {// "" to read entire link table...
if (score < levenshtein_distance(command, links[i]) &&
score < levenshtein_distance(command, links[i+1]) &&
score < levenshtein_distance(command, links[i+2])) continue;
@@ 229,103 230,150 @@ char *select_link(char **links, char *command) {
struct termios stored_settings, no_echo;
int read_keyboard = 0;
-int speak_finalize(char *ssml, char **links, char **out_link) {
- while (read_keyboard) {
- if (out_link != NULL && *out_link != NULL) return 0;
-
- if (getc(stdin) == '\033') {
- char mark[200];
- char fallback[200];
- espeak_Cancel();
- char c = getc(stdin);
- if (c == 0 || c == -1 || c == '\033' || c == 'q') goto close; // skip [
- switch (getc(stdin)) {
- case 'A':
- // 🠕
- if (in_table) {
- tablerow--;
- if (tablerow > 0) {
- sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol);
- speak(ssml, mark, NULL);
- break;
- } else in_table = 0;
- }
- section_no--;
- sprintf(mark, "-rhaps-section%i", section_no);
- speak(ssml, section_no > 0 ? mark : NULL, NULL);
- break;
- case 'B':
- // 🠗
- if (in_table) {
- tablerow++;
+
+void read_page(char *uri, int read_input);
+gboolean read_stdin(GIOChannel *source, GIOCondition condition, gpointer data) {
+ char *ssml = data;
+
+ if (getc(stdin) == '\033') {
+ char mark[200];
+ char fallback[200];
+ espeak_Cancel();
+ char c = getc(stdin);
+ if (c == 0 || c == -1 || c == '\033' || c == 'q') return 1; // skip [
+ switch (getc(stdin)) {
+ case 'A':
+ // 🠕
+ if (in_table) {
+ tablerow--;
+ if (tablerow > 0) {
sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol);
- sprintf(fallback, "-rhaps-section%i", section_no+1);
- speak(ssml, mark, fallback);
- break; // FIXME What if that mark doesn't exist?
- }
- section_no++;
- sprintf(mark, "-rhaps-section%i", section_no);
- speak(ssml, section_no > 0 ? mark : NULL, NULL);
- break;
- case 'C':
- // ➔
- if (in_table) {
- tablecol++;
+ speak(ssml, mark, NULL);
+ break;
+ } else in_table = 0;
+ }
+ section_no--;
+ sprintf(mark, "-rhaps-section%i", section_no);
+ speak(ssml, section_no > 0 ? mark : NULL, NULL);
+ break;
+ case 'B':
+ // 🠗
+ if (in_table) {
+ tablerow++;
+ sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol);
+ sprintf(fallback, "-rhaps-section%i", section_no+1);
+ speak(ssml, mark, fallback);
+ break; // FIXME What if that mark doesn't exist?
+ }
+ section_no++;
+ sprintf(mark, "-rhaps-section%i", section_no);
+ speak(ssml, section_no > 0 ? mark : NULL, NULL);
+ break;
+ case 'C':
+ // ➔
+ if (in_table) {
+ tablecol++;
+ sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol);
+ sprintf(fallback, "-rhaps-paragraph%i", paragraph_no+1);
+ speak(ssml, mark, fallback);
+ break; // FIXME What if that mark doesn't exist?
+ }
+ paragraph_no++;
+ sprintf(mark, "-rhaps-paragraph%i", paragraph_no);
+ speak(ssml, paragraph_no > 0 ? mark : NULL, NULL);
+ break;
+ case 'D':
+ // 🠔
+ if (in_table) {
+ tablecol--;
+ if (tablecol > 0) {
sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol);
- sprintf(fallback, "-rhaps-paragraph%i", paragraph_no+1);
- speak(ssml, mark, fallback);
- break; // FIXME What if that mark doesn't exist?
- }
- paragraph_no++;
- sprintf(mark, "-rhaps-paragraph%i", paragraph_no);
- speak(ssml, paragraph_no > 0 ? mark : NULL, NULL);
- break;
- case 'D':
- // 🠔
- if (in_table) {
- tablecol--;
- if (tablecol > 0) {
- sprintf(mark, "-rhaps-tablecell%i:%ix%i", tableno, tablerow, tablecol);
- speak(ssml, mark, NULL);
- break;
- } else in_table = 0;
- }
- paragraph_no--;
- sprintf(mark, "-rhaps-paragraph%i", paragraph_no);
- speak(ssml, paragraph_no > 0 ? mark : NULL, NULL);
- break;
+ speak(ssml, mark, NULL);
+ break;
+ } else in_table = 0;
}
- } else {
- // Read in a line
- tcsetattr(0, TCSANOW, &stored_settings);
- char *line = NULL;
- size_t len = 0;
- if (getline(&line, &len, stdin) < 0)
- fprintf(stderr, "Failed to read stdin line!\n");
- else if (*line == '\n') {
- espeak_Cancel();
- return 0;
- } else if (out_link != NULL)
- *out_link = select_link(links, line);
- tcsetattr(0, TCSANOW, &no_echo);
+ paragraph_no--;
+ sprintf(mark, "-rhaps-paragraph%i", paragraph_no);
+ speak(ssml, paragraph_no > 0 ? mark : NULL, NULL);
+ break;
+ }
+ } else {
+ // Read in a line, with full terminal emulator i18n.
+ tcsetattr(0, TCSANOW, &stored_settings);
+ char *line = NULL;
+ size_t len = 0;
+ if (getline(&line, &len, stdin) < 0) {
+ fprintf(stderr, "Failed to read stdin line!\n");
+ return TRUE;
}
+ tcsetattr(0, TCSANOW, &no_echo);
+ read_page(select_link(line), 1);
+ return FALSE;
}
- espeak_ng_STATUS result = espeak_ng_Synchronize();
- if (result != ENS_OK) {
- espeak_ng_PrintStatusCodeMessage(result, stderr, context);
- return 4;
+ return TRUE;
+}
+
+int speak_finalize(char *ssml) {
+ while (read_keyboard) {
+ if (!read_stdin(NULL, 0, ssml)) return 0;
}
close:
- if (path_wav != NULL) sf_close(fd_wav);
- espeak_ng_Terminate();
return 0;
}
/* Main driver */
-void write_links(FILE *dest, char **links) {
+int speak_err = 0;
+struct session *session = NULL;
+struct page *referer = NULL;
+
+int use_espeak = 0;
+char *logpath = NULL;
+char *mimes = "text/html text/xml application/xml application/xhtml+xml text/plain";
+FILE *fd_ssml = NULL;
+FILE *fd_links = NULL;
+
+void write_links() {
for (int i = 0; strcmp(links[i], " ") != 0; i++) {
- fprintf(dest, "%s%c", links[i], (i % 3) == 2 ? '\n' : '\t');
+ fprintf(fd_links, "%s%c", links[i], (i % 3) == 2 ? '\n' : '\t');
+ }
+}
+
+void read_page(char *uri, int read_input) {
+ for (int i = 0; strcmp(links[i], " ") != 0; i++) free(links[i]);
+ free(links);
+
+ if (use_espeak && speak_err == 0) speak_text(uri, espeakRATE, 10);
+ #ifdef WITH_SPEECHD
+ else if (spd_conn != NULL) spd_say(spd_conn, SPD_MESSAGE, uri);
+ #endif
+ else printf("%s\n", uri);
+
+ struct page *page = c_fetchURL(session, mimes, referer, uri);
+ referer = page;
+ char *ssml = c_renderDoc(session, page, use_espeak);
+ links = c_extractLinks(page);
+
+ if (logpath != NULL) c_writeLog(logpath, session);
+
+ if (fd_ssml != NULL) fprintf(fd_ssml, "%s\n", ssml);
+ if (read_keyboard && strcmp(uri, "about:welcome")) select_link("");
+ if (fd_links != NULL) write_links(fd_links, links);
+ if (use_espeak & speak_err == 0) speak(ssml, "main", NULL);
+ #ifdef WITH_SPEECHD
+ if (spd_conn != NULL) spd_say(spd_conn, SPD_MESSAGE, ssml);
+ #endif
+
+ c_freePage(page);
+ free(uri);
+
+ if (read_input) {
+ g_io_add_watch(g_io_channel_unix_new(0), G_IO_IN|G_IO_HUP, read_stdin, ssml);
+ // if (use_espeak & speak_err == 0) speak_err = speak_finalize(ssml);
+ } else {
+ free(ssml);
+ for (int i = 0; strcmp(links[i], " ") != 0; i++) free(links[i]);
+ free(links);
}
}
@@ 340,16 388,10 @@ FILE *parse_opt_file() {
}
int main(int argc, char **argv) {
- int speak_err = 0;
hs_init(&argc, &argv);
gst_init(&argc, &argv);
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
- char *mimes = "text/html text/xml application/xml application/xhtml+xml text/plain";
- char *logpath = NULL;
- FILE *fd_ssml = NULL;
- FILE *fd_links = NULL;
- int use_espeak = 0;
tcgetattr(0, &stored_settings);
#ifdef WITH_SPEECHD
SPDConnection *spd_conn = NULL;
@@ 462,53 504,30 @@ int main(int argc, char **argv) {
if (dist != 3) return 11;
#endif
- struct session *session = c_newSession();
- struct page *referer = c_initialReferer();
+ session = c_newSession();
+ if (logpath != NULL) session = c_enableLogging(session);
+ referer = c_initialReferer();
if (use_espeak) speak_err = speak_initialize();
- char *ssml, **links, *uri;
if (optind >= argc) {
// No URLs specified, restore previous session or goto about:welcome
- uri = c_lastVisited("about:welcome");
- goto read_uri;
- }
- for (int i = optind; i < argc; i++) {
- uri = argv[i];
-
-read_uri:
- if (use_espeak && speak_err == 0) speak_text(uri, espeakRATE, 10);
- #ifdef WITH_SPEECHD
- else if (spd_conn != NULL) spd_say(spd_conn, SPD_MESSAGE, uri);
- #endif
- else printf("%s\n", argv[i]);
-
- if (logpath != NULL) session = c_enableLogging(session);
+ read_page(c_lastVisited("about:welcome"), 1);
+ } else for (int i = optind; i < argc; i++) read_page(argv[i], i+1 == argc);
- struct page *page = c_fetchURL(session, mimes, referer, uri);
- ssml = c_renderDoc(session, page, use_espeak);
- links = c_extractLinks(page);
-
- if (logpath != NULL) c_writeLog(logpath, session);
-
- if (fd_ssml != NULL) fprintf(fd_ssml, "%s\n", ssml);
- if (read_keyboard && strcmp(uri, "about:welcome")) select_link(links, "");
- if (fd_links != NULL) write_links(fd_links, links);
- if (use_espeak & speak_err == 0) speak(ssml, "main", NULL);
- #ifdef WITH_SPEECHD
- if (spd_conn != NULL) spd_say(spd_conn, SPD_MESSAGE, ssml);
- #endif
-
- c_freePage(page);
- }
-
- uri = NULL;
- if (use_espeak & speak_err == 0) speak_err = speak_finalize(ssml, links, &uri);
- if (uri != NULL) goto read_uri;
+ g_main_loop_run(loop);
#ifdef WITH_SPEECHD
if (spd_conn != NULL) spd_close(spd_conn);
#endif
+ espeak_ng_STATUS result = espeak_ng_Synchronize();
+ if (result != ENS_OK) {
+ espeak_ng_PrintStatusCodeMessage(result, stderr, context);
+ return 4;
+ }
+ if (path_wav != NULL) sf_close(fd_wav);
+ espeak_ng_Terminate();
+
c_freePage(referer);
c_freeSession(session);
hs_exit();