cmdline (merge-intel): support ctrl-w in librte_cmdline
[libcmdline.git] / src / lib / cmdline_rdline.c
index 287c7d8..91217be 100644 (file)
@@ -1,3 +1,37 @@
+/*-
+ * Copyright (c) <2010>, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 /*
  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
  * All rights reserved.
@@ -36,7 +70,7 @@
 #include "cmdline_rdline.h"
 
 static void rdline_puts(struct rdline *rdl, const char *buf);
-static void rdline_miniprintf(struct rdline *rdl, 
+static void rdline_miniprintf(struct rdline *rdl,
                              const char *buf, unsigned int val);
 
 #ifndef NO_RDLINE_HISTORY
@@ -51,13 +85,14 @@ static unsigned int rdline_get_history_size(struct rdline *rdl);
 static int
 isblank2(char c)
 {
-       if (c == ' ' || 
+       if (c == ' ' ||
            c == '\t' )
                return 1;
        return 0;
 }
 
-void rdline_init(struct rdline *rdl, 
+void
+rdline_init(struct rdline *rdl,
                 rdline_write_char_t *write_char,
                 rdline_validate_t *validate,
                 rdline_complete_t *complete)
@@ -89,17 +124,23 @@ rdline_newline(struct rdline *rdl, const char *prompt)
                rdl->write_char(rdl, rdl->prompt[i]);
        rdl->status = RDLINE_RUNNING;
 
-#ifndef NO_RDLINE_HISTORY 
+#ifndef NO_RDLINE_HISTORY
        rdl->history_cur_line = -1;
 #endif /* !NO_RDLINE_HISTORY */
 }
 
-void 
+void
 rdline_stop(struct rdline *rdl)
 {
        rdl->status = RDLINE_INIT;
 }
 
+void
+rdline_quit(struct rdline *rdl)
+{
+       rdl->status = RDLINE_EXITED;
+}
+
 void
 rdline_restart(struct rdline *rdl)
 {
@@ -123,22 +164,25 @@ rdline_get_buffer(struct rdline *rdl)
 }
 
 static void
-display_right_buffer(struct rdline *rdl)
+display_right_buffer(struct rdline *rdl, int force)
 {
        unsigned int i;
        char tmp;
 
+       if (!force && CIRBUF_IS_EMPTY(&rdl->right))
+               return;
+
        rdline_puts(rdl, vt100_clear_right);
-       if (!CIRBUF_IS_EMPTY(&rdl->right)) {
-               CIRBUF_FOREACH(&rdl->right, i, tmp) {
-                       rdl->write_char(rdl, tmp);
-               }
-               rdline_miniprintf(rdl, vt100_multi_left, 
-                                 CIRBUF_GET_LEN(&rdl->right));
+       CIRBUF_FOREACH(&rdl->right, i, tmp) {
+               rdl->write_char(rdl, tmp);
        }
+       if (!CIRBUF_IS_EMPTY(&rdl->right))
+               rdline_miniprintf(rdl, vt100_multi_left,
+                                 CIRBUF_GET_LEN(&rdl->right));
 }
 
-void rdline_redisplay(struct rdline *rdl)
+void
+rdline_redisplay(struct rdline *rdl)
 {
        unsigned int i;
        char tmp;
@@ -149,7 +193,7 @@ void rdline_redisplay(struct rdline *rdl)
        CIRBUF_FOREACH(&rdl->left, i, tmp) {
                rdl->write_char(rdl, tmp);
        }
-       display_right_buffer(rdl);
+       display_right_buffer(rdl, 1);
 }
 
 int
@@ -161,13 +205,15 @@ rdline_char_in(struct rdline *rdl, char c)
 #ifndef NO_RDLINE_HISTORY
        char *buf;
 #endif
-       
+
+       if (rdl->status == RDLINE_EXITED)
+               return RDLINE_RES_EXITED;
        if (rdl->status != RDLINE_RUNNING)
-               return -1;
+               return RDLINE_RES_NOT_RUNNING;
 
        cmd = vt100_parser(&rdl->vt100, c);
        if (cmd == -2)
-               return 0;
+               return RDLINE_RES_SUCCESS;
 
        if (cmd >= 0) {
                switch (cmd) {
@@ -192,47 +238,48 @@ rdline_char_in(struct rdline *rdl, char c)
                        break;
 
                case CMDLINE_KEY_WLEFT:
-                       while (! CIRBUF_IS_EMPTY(&rdl->left) && 
-                              (tmp = cirbuf_get_tail(&rdl->left)) && 
+                       while (! CIRBUF_IS_EMPTY(&rdl->left) &&
+                              (tmp = cirbuf_get_tail(&rdl->left)) &&
                               isblank2(tmp)) {
                                rdline_puts(rdl, vt100_left_arr);
                                cirbuf_del_tail(&rdl->left);
                                cirbuf_add_head(&rdl->right, tmp);
                        }
-                       while (! CIRBUF_IS_EMPTY(&rdl->left) && 
-                              (tmp = cirbuf_get_tail(&rdl->left)) && 
+                       while (! CIRBUF_IS_EMPTY(&rdl->left) &&
+                              (tmp = cirbuf_get_tail(&rdl->left)) &&
                               !isblank2(tmp)) {
                                rdline_puts(rdl, vt100_left_arr);
                                cirbuf_del_tail(&rdl->left);
                                cirbuf_add_head(&rdl->right, tmp);
-                       }                       
+                       }
                        break;
 
                case CMDLINE_KEY_WRIGHT:
-                       while (! CIRBUF_IS_EMPTY(&rdl->right) && 
-                              (tmp = cirbuf_get_head(&rdl->right)) && 
+                       while (! CIRBUF_IS_EMPTY(&rdl->right) &&
+                              (tmp = cirbuf_get_head(&rdl->right)) &&
                               isblank2(tmp)) {
                                rdline_puts(rdl, vt100_right_arr);
                                cirbuf_del_head(&rdl->right);
                                cirbuf_add_tail(&rdl->left, tmp);
                        }
-                       while (! CIRBUF_IS_EMPTY(&rdl->right) && 
-                              (tmp = cirbuf_get_head(&rdl->right)) && 
+                       while (! CIRBUF_IS_EMPTY(&rdl->right) &&
+                              (tmp = cirbuf_get_head(&rdl->right)) &&
                               !isblank2(tmp)) {
                                rdline_puts(rdl, vt100_right_arr);
                                cirbuf_del_head(&rdl->right);
                                cirbuf_add_tail(&rdl->left, tmp);
-                       }                       
+                       }
                        break;
 
                case CMDLINE_KEY_BKSPACE:
                        if(!cirbuf_del_tail_safe(&rdl->left)) {
                                rdline_puts(rdl, vt100_bs);
-                               display_right_buffer(rdl);
+                               display_right_buffer(rdl, 1);
                        }
                        break;
 
                case CMDLINE_KEY_META_BKSPACE:
+               case CMDLINE_KEY_CTRL_W:
                        while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) {
                                rdline_puts(rdl, vt100_bs);
                                cirbuf_del_tail(&rdl->left);
@@ -241,25 +288,25 @@ rdline_char_in(struct rdline *rdl, char c)
                                rdline_puts(rdl, vt100_bs);
                                cirbuf_del_tail(&rdl->left);
                        }
-                       display_right_buffer(rdl);
+                       display_right_buffer(rdl, 1);
                        break;
 
                case CMDLINE_KEY_SUPPR:
                case CMDLINE_KEY_CTRL_D:
-                       if (cmd == CMDLINE_KEY_CTRL_D && 
+                       if (cmd == CMDLINE_KEY_CTRL_D &&
                            CIRBUF_IS_EMPTY(&rdl->left) &&
                            CIRBUF_IS_EMPTY(&rdl->right)) {
-                               return -2;
+                               return RDLINE_RES_EOF;
                        }
                        if (!cirbuf_del_head_safe(&rdl->right)) {
-                               display_right_buffer(rdl);
+                               display_right_buffer(rdl, 1);
                        }
                        break;
 
                case CMDLINE_KEY_CTRL_A:
                        if (CIRBUF_IS_EMPTY(&rdl->left))
                                break;
-                       rdline_miniprintf(rdl, vt100_multi_left, 
+                       rdline_miniprintf(rdl, vt100_multi_left,
                                            CIRBUF_GET_LEN(&rdl->left));
                        while (! CIRBUF_IS_EMPTY(&rdl->left)) {
                                tmp = cirbuf_get_tail(&rdl->left);
@@ -271,7 +318,7 @@ rdline_char_in(struct rdline *rdl, char c)
                case CMDLINE_KEY_CTRL_E:
                        if (CIRBUF_IS_EMPTY(&rdl->right))
                                break;
-                       rdline_miniprintf(rdl, vt100_multi_right, 
+                       rdline_miniprintf(rdl, vt100_multi_right,
                                            CIRBUF_GET_LEN(&rdl->right));
                        while (! CIRBUF_IS_EMPTY(&rdl->right)) {
                                tmp = cirbuf_get_head(&rdl->right);
@@ -291,13 +338,13 @@ rdline_char_in(struct rdline *rdl, char c)
                case CMDLINE_KEY_CTRL_Y:
                        i=0;
                        while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) <
-                             RDLINE_BUF_SIZE && 
+                             RDLINE_BUF_SIZE &&
                              i < rdl->kill_size) {
                                cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]);
                                rdl->write_char(rdl, rdl->kill_buf[i]);
                                i++;
                        }
-                       display_right_buffer(rdl);
+                       display_right_buffer(rdl, 0);
                        break;
 #endif /* !NO_RDLINE_KILL_BUF */
 
@@ -313,12 +360,12 @@ rdline_char_in(struct rdline *rdl, char c)
                case CMDLINE_KEY_TAB:
                case CMDLINE_KEY_HELP:
                        cirbuf_align_left(&rdl->left);
-                       rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; 
+                       rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0';
                        if (rdl->complete) {
                                char tmp_buf[BUFSIZ];
                                int complete_state;
                                int ret;
-                               int tmp_size;
+                               unsigned int tmp_size;
 
                                if (cmd == CMDLINE_KEY_TAB)
                                        complete_state = 0;
@@ -331,22 +378,22 @@ rdline_char_in(struct rdline *rdl, char c)
                                                    &complete_state);
                                /* no completion or error */
                                if (ret <= 0) {
-                                       return 2;
+                                       return RDLINE_RES_COMPLETE;
                                }
 
                                tmp_size = strlen(tmp_buf);
                                /* add chars */
-                               if (ret == 2) {
+                               if (ret == RDLINE_RES_COMPLETE) {
                                        i=0;
                                        while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) <
-                                             RDLINE_BUF_SIZE && 
+                                             RDLINE_BUF_SIZE &&
                                              i < tmp_size) {
                                                cirbuf_add_tail(&rdl->left, tmp_buf[i]);
                                                rdl->write_char(rdl, tmp_buf[i]);
                                                i++;
                                        }
-                                       display_right_buffer(rdl);
-                                       return 2; /* ?? */
+                                       display_right_buffer(rdl, 1);
+                                       return RDLINE_RES_COMPLETE; /* ?? */
                                }
 
                                /* choice */
@@ -363,7 +410,7 @@ rdline_char_in(struct rdline *rdl, char c)
 
                                rdline_redisplay(rdl);
                        }
-                       return 2;
+                       return RDLINE_RES_COMPLETE;
 
                case CMDLINE_KEY_RETURN:
                case CMDLINE_KEY_RETURN2:
@@ -377,8 +424,11 @@ rdline_char_in(struct rdline *rdl, char c)
 
                        if (rdl->validate)
                                rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2);
-                       return 1;
-                       
+                       /* user may have stopped rdline */
+                       if (rdl->status == RDLINE_EXITED)
+                               return RDLINE_RES_EXITED;
+                       return RDLINE_RES_VALIDATED;
+
 #ifndef NO_RDLINE_HISTORY
                case CMDLINE_KEY_UP_ARR:
                        if (rdl->history_cur_line == 0) {
@@ -388,11 +438,11 @@ rdline_char_in(struct rdline *rdl, char c)
                                rdline_add_history(rdl, rdline_get_buffer(rdl));
                                rdl->history_cur_line = 0;
                        }
-                       
+
                        buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1);
                        if (!buf)
                                break;
-                       
+
                        rdl->history_cur_line ++;
                        vt100_init(&rdl->vt100);
                        cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
@@ -404,7 +454,7 @@ rdline_char_in(struct rdline *rdl, char c)
                case CMDLINE_KEY_DOWN_ARR:
                        if (rdl->history_cur_line - 1 < 0)
                                break;
-                       
+
                        rdl->history_cur_line --;
                        buf = rdline_get_history_item(rdl, rdl->history_cur_line);
                        if (!buf)
@@ -423,23 +473,23 @@ rdline_char_in(struct rdline *rdl, char c)
                        break;
                }
 
-               return 0;
+               return RDLINE_RES_SUCCESS;
        }
-       
-       if (! isprint(c))
-               return 0;
+
+       if (!isprint((int)c))
+               return RDLINE_RES_SUCCESS;
 
        /* standard chars */
        if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE)
-               return 0;
-               
+               return RDLINE_RES_SUCCESS;
+
        if (cirbuf_add_tail_safe(&rdl->left, c))
-               return 0;
+               return RDLINE_RES_SUCCESS;
 
        rdl->write_char(rdl, c);
-       display_right_buffer(rdl);
+       display_right_buffer(rdl, 0);
 
-       return 0;
+       return RDLINE_RES_SUCCESS;
 }
 
 
@@ -515,7 +565,7 @@ rdline_get_history_item(struct rdline * rdl, unsigned int idx)
        return NULL;
 }
 
-int 
+int
 rdline_add_history(struct rdline * rdl, const char * buf)
 {
        unsigned int len, i;
@@ -537,7 +587,7 @@ rdline_add_history(struct rdline * rdl, const char * buf)
 
        cirbuf_add_buf_tail(&rdl->history, buf, len);
        cirbuf_add_tail(&rdl->history, 0);
-       
+
        return 0;
 }
 
@@ -559,7 +609,7 @@ char * rdline_get_history_item(struct rdline * rdl, unsigned int i) {return NULL
 
 /* STATIC USEFUL FUNCS */
 
-static void 
+static void
 rdline_puts(struct rdline * rdl, const char * buf)
 {
        char c;
@@ -569,7 +619,7 @@ rdline_puts(struct rdline * rdl, const char * buf)
 }
 
 /* a very very basic printf with one arg and one format 'u' */
-static void 
+static void
 rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val)
 {
        char c, started=0, div=100;
@@ -587,9 +637,9 @@ rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val)
                }
                /* val is never more than 255 */
                while (div) {
-                       c = val / div;
+                       c = (char)(val / div);
                        if (c || started) {
-                               rdl->write_char(rdl, c+'0');
+                               rdl->write_char(rdl, (char)(c+'0'));
                                started = 1;
                        }
                        val %= div;