afh: Initialize audio format handlers only once.
[paraslash.git] / interactive.c
index a18d82b717846d1deeec01c3dcaf88587837bc43..43cb99f2781979e74b66eef640fadb7878f30aeb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2011-2013 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -31,6 +31,7 @@ struct i9e_private {
        char empty_line[1000];
        struct task task;
        struct btr_node *stdout_btrn;
+       bool last_write_was_status;
        bool line_handler_running;
        bool input_eof;
        bool caught_sigint;
@@ -271,6 +272,7 @@ static void clear_bottom_line(void)
        rl_redisplay();
        wipe_bottom_line(); /* wipe out the prompt */
        rl_insert_text(text);
+       free(text);
        rl_point = point;
 }
 
@@ -289,29 +291,33 @@ static bool input_available(void)
 static void i9e_line_handler(char *line)
 {
        int ret;
+       struct btr_node *dummy;
 
+       if (!line) {
+               i9ep->input_eof = true;
+               return;
+       }
+       if (!*line)
+               goto free_line;
+       rl_set_prompt("");
+       dummy = btr_new_node(&(struct btr_node_description)
+               EMBRACE(.name = "dummy line handler"));
+       i9e_attach_to_stdout(dummy);
        ret = i9ep->ici->line_handler(line);
        if (ret < 0)
                PARA_WARNING_LOG("%s\n", para_strerror(-ret));
-       rl_set_prompt("");
-       if (line) {
-               if (!*line)
-                       rl_set_prompt(i9ep->ici->prompt);
-               else
-                       add_history(line);
-               free(line);
-       } else {
-               rl_set_prompt("");
-               i9ep->input_eof = true;
-       }
+       add_history(line);
+       btr_remove_node(&dummy);
+free_line:
+       free(line);
 }
 
-static void i9e_post_select(__a_unused struct sched *s, struct task *t)
+static int i9e_post_select(__a_unused struct sched *s, __a_unused struct task *t)
 {
        int ret;
        struct i9e_client_info *ici = i9ep->ici;
        char *buf;
-       size_t sz;
+       size_t sz, consumed = 0;
 
        ret = -E_I9E_EOF;
        if (i9ep->input_eof)
@@ -333,16 +339,24 @@ static void i9e_post_select(__a_unused struct sched *s, struct task *t)
        }
        if (ret == 0)
                goto out;
+again:
        sz = btr_next_buffer(i9ep->stdout_btrn, &buf);
        if (sz == 0)
                goto out;
+       if (i9ep->last_write_was_status)
+               fprintf(i9ep->stderr_stream, "\n");
+       i9ep->last_write_was_status = false;
        ret = xwrite(ici->fds[1], buf, sz);
        if (ret < 0)
                goto rm_btrn;
        btr_consume(i9ep->stdout_btrn, ret);
+       consumed += ret;
+       if (ret == sz && consumed < 10000)
+               goto again;
        goto out;
 rm_btrn:
        if (i9ep->stdout_btrn) {
+               wipe_bottom_line();
                btr_remove_node(&i9ep->stdout_btrn);
                rl_set_keymap(i9ep->standard_km);
                rl_set_prompt(i9ep->ici->prompt);
@@ -352,7 +366,7 @@ rm_btrn:
                wipe_bottom_line();
 out:
        i9ep->caught_sigint = false;
-       t->error = ret;
+       return ret;
 }
 
 static void i9e_pre_select(struct sched *s, __a_unused struct task *t)
@@ -503,6 +517,41 @@ __printf_2_3 void i9e_log(int ll, const char* fmt,...)
        vfprintf(i9ep->stderr_stream, fmt, argp);
        va_end(argp);
        reset_line_state();
+       i9ep->last_write_was_status = false;
+}
+
+/**
+ * Print the current status to stderr.
+ *
+ * \param buf The text to print.
+ * \param len The number of bytes in \a buf.
+ *
+ * This clears the bottom line, moves to the beginning of the line and prints
+ * the given text. If the length of this text exceeds the width of the
+ * terminal, the text is shortened by leaving out a part in the middle.
+ */
+void ie9_print_status_bar(char *buf, unsigned len)
+{
+       size_t x = i9ep->num_columns, y = (x - 4) / 2;
+
+       assert(x >= 6);
+       if (len > x) {
+               buf[y] = '\0';
+               fprintf(i9ep->stderr_stream, "\r%s", buf);
+               fprintf(i9ep->stderr_stream, " .. ");
+               fprintf(i9ep->stderr_stream, "%s", buf + len - y);
+       } else {
+               char scratch[1000];
+
+               y = x - len;
+               scratch[0] = '\r';
+               strcpy(scratch + 1, buf);
+               memset(scratch + 1 + len, ' ', y);
+               scratch[1 + len + y] = '\r';
+               scratch[2 + len + y] = '\0';
+               fprintf(i9ep->stderr_stream, "\r%s", scratch);
+       }
+       i9ep->last_write_was_status = true;
 }
 
 /**