X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=src%2Flib%2Fcmdline_rdline.c;h=785a23cd024b64f4f7a16613c4040eaf6e8cf0a6;hb=568d6d51fc9e6e2d8842fc1abe63c23de503f8bc;hp=16fda433dafc15ec0678cbe3390a462ff9ef3d1e;hpb=3e6cc1d7b682f75a75034602f003c3e9f8a8d3ad;p=libcmdline.git diff --git a/src/lib/cmdline_rdline.c b/src/lib/cmdline_rdline.c index 16fda43..785a23c 100644 --- a/src/lib/cmdline_rdline.c +++ b/src/lib/cmdline_rdline.c @@ -107,7 +107,7 @@ rdline_init(struct rdline *rdl, rdl->validate = validate; rdl->complete = complete; rdl->help = help; - rdl->status = RDLINE_INIT; + rdl->status = RDLINE_STOPPED; #ifndef NO_RDLINE_HISTORY cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); #endif /* !NO_RDLINE_HISTORY */ @@ -135,7 +135,7 @@ rdline_newline(struct rdline *rdl, const char *prompt) void rdline_stop(struct rdline *rdl) { - rdl->status = RDLINE_INIT; + rdl->status = RDLINE_STOPPED; } void @@ -214,20 +214,30 @@ rdline_parse_char(struct rdline *rdl, char c) #ifndef NO_PAGER /* display asynchrounous printf if any */ if (rdl->pager_buf != NULL) { - if (cmd == VT100_STD_CHAR && c == 'q') { - rdline_asyncpager_reset(rdl); - // call cb() - if (rdl->pager_buf == NULL) - return RDLINE_RES_VALIDATED; - } - if (rdline_pager_next_page(rdl) == 0) { + /* user ask to exit pager, or last page is displayed*/ + if ((cmd == VT100_STD_CHAR && c == 'q') || + rdline_pager_next_page(rdl) == 0) { + int ret; + + ret = rdl->pager_ret; rdline_asyncpager_reset(rdl); - // call cb() - if (rdl->pager_buf == NULL) - return RDLINE_RES_VALIDATED; + if (rdl->pager_cb != NULL) { + rdl->pager_cb(rdl, rdl->pager_arg); + rdl->pager_cb = NULL; + } + /* maybe the pager was reloaded in the + * callback */ + if (rdl->pager_buf != NULL) + return RDLINE_RES_SUCCESS; + + /* else, redisplay prompt and return the saved status */ + rdline_redisplay(rdl); + return ret; } - /* async printf was called in cb() */ + + /* Some pages remain, lines were displayed in + * rdline_pager_next_page() */ return RDLINE_RES_SUCCESS; } #endif @@ -394,12 +404,14 @@ rdline_parse_char(struct rdline *rdl, char c) cirbuf_align_left(&rdl->left); rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; rdline_printf(rdl, "\r\n"); - rdl->help(rdl, rdl->left_buf, rdline_write, rdl); #ifndef NO_PAGER - if (rdl->pager_buf != NULL) { - // XXX set cb + rdl->help(rdl, rdl->left_buf, rdline_asyncpager_write, rdl); + if (rdl->pager_buf != NULL) return RDLINE_RES_SUCCESS; - } + else + rdline_asyncpager_reset(rdl); +#else + rdl->help(rdl, rdl->left_buf, rdline_write, rdl); #endif rdline_redisplay(rdl); break; @@ -407,7 +419,7 @@ rdline_parse_char(struct rdline *rdl, char c) case CMDLINE_KEY_TAB: { char tmp_buf[CMDLINE_MAX_TOKEN_SIZE]; - int ret; //, curline = 0; + int ret; unsigned int tmp_size; if (rdl->complete == NULL) @@ -425,12 +437,15 @@ rdline_parse_char(struct rdline *rdl, char c) cirbuf_align_left(&rdl->left); rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; rdline_printf(rdl, "\r\n"); - rdl->help(rdl, rdl->left_buf, rdline_write, rdl); #ifndef NO_PAGER - if (rdl->pager_buf != NULL) { - // XXX set cb + rdl->help(rdl, rdl->left_buf, rdline_asyncpager_write, + rdl); + if (rdl->pager_buf != NULL) return RDLINE_RES_SUCCESS; - } + else + rdline_asyncpager_reset(rdl); +#else + rdl->help(rdl, rdl->left_buf, rdline_write, rdl); #endif rdline_redisplay(rdl); break; @@ -451,10 +466,15 @@ rdline_parse_char(struct rdline *rdl, char c) } case CMDLINE_KEY_RETURN: - case CMDLINE_KEY_RETURN2: + case CMDLINE_KEY_RETURN2: { + char tmp; + while (!CIRBUF_IS_EMPTY(&rdl->right) && + (tmp = cirbuf_get_head(&rdl->right))) { + cirbuf_del_head(&rdl->right); + cirbuf_add_tail(&rdl->left, tmp); + } cirbuf_align_left(&rdl->left); - rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\n'; - rdl->left_buf[CIRBUF_GET_LEN(&rdl->left) + 1] = '\0'; + rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; rdline_printf(rdl, "\r\n"); #ifndef NO_RDLINE_HISTORY if (rdl->history_cur_line != -1) @@ -462,24 +482,29 @@ rdline_parse_char(struct rdline *rdl, char c) #endif if (rdl->validate) - rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2); + rdl->validate(rdl, rdl->left_buf, + CIRBUF_GET_LEN(&rdl->left)+2); #ifndef NO_PAGER /* user may have stopped rdline */ if (rdl->status == RDLINE_EXITED) { rdline_asyncpager_reset(rdl); return RDLINE_RES_EXITED; } + /* there is something in pager buffer, save + * return value that will be return once + * paging is finished */ if (rdl->pager_buf != NULL) { - // XXX set cb + rdl->pager_ret = RDLINE_RES_VALIDATED; return RDLINE_RES_SUCCESS; } - rdl->status = RDLINE_INIT; + + rdline_asyncpager_reset(rdl); #else if (rdl->status == RDLINE_EXITED) return RDLINE_RES_EXITED; #endif return RDLINE_RES_VALIDATED; - + } #ifndef NO_RDLINE_HISTORY case CMDLINE_KEY_UP_ARR: case CMDLINE_KEY_CTRL_P: @@ -521,7 +546,6 @@ rdline_parse_char(struct rdline *rdl, char c) break; #endif /* !NO_RDLINE_HISTORY */ - default: break; } @@ -767,6 +791,9 @@ rdline_asyncpager_reset(struct rdline *rdl) rdl->pager_lines = 0; rdl->pager_len = 0; rdl->pager_off = 0; + rdl->pager_cb = NULL; + rdl->pager_arg = NULL; + rdl->pager_ret = RDLINE_RES_SUCCESS; } /* Return the offset of the i-th occurence of char c in string s. If @@ -828,9 +855,11 @@ rdline_pager_next_page(struct rdline *rdl) } /* push data in pager */ -static int -rdline_pager_push(struct rdline *rdl, char *s, int len) +ssize_t +rdline_asyncpager_write(struct rdline *rdl, void *buf, size_t len) { + char *s = buf; + /* display as many lines as we can */ if (rdl->pager_lines < RDLINE_MAX_LINES) { int lines = RDLINE_MAX_LINES - rdl->pager_lines; @@ -865,8 +894,7 @@ rdline_pager_push(struct rdline *rdl, char *s, int len) return 0; } -/* XXX we should have a specific return value when displaying will be - * asynchronous, we may also have a callback */ +/* Print data asynchronously (using pager if needed) */ int rdline_asyncpager_printf(struct rdline *rdl, const char *fmt, ...) { @@ -888,8 +916,19 @@ rdline_asyncpager_printf(struct rdline *rdl, const char *fmt, ...) if (n >= BUFSIZ) n = BUFSIZ-1; if (n > 0) - rdline_pager_push(rdl, buf, n); + rdline_asyncpager_write(rdl, buf, n); free(buf); return n; } + +int rdline_asyncpager_set_cb(struct rdline *rdl, rdline_asyncpager_cb_t *cb, + void *arg) +{ + if (rdl->pager_buf == NULL) + return -1; + + rdl->pager_cb = cb; + rdl->pager_arg = arg; + return 0; +} #endif /* !NO_PAGER */