if (rdl->pager_buf != NULL) {
if (cmd == VT100_STD_CHAR && c == 'q') {
rdline_asyncpager_reset(rdl);
- // call cb()
+ if (rdl->pager_cb != NULL) {
+ rdl->pager_cb(rdl, rdl->pager_arg);
+ rdl->pager_cb = NULL;
+ }
if (rdl->pager_buf == NULL)
return RDLINE_RES_VALIDATED;
}
if (rdline_pager_next_page(rdl) == 0) {
rdline_asyncpager_reset(rdl);
- // call cb()
+ if (rdl->pager_cb != NULL) {
+ rdl->pager_cb(rdl, rdl->pager_arg);
+ rdl->pager_cb = NULL;
+ }
if (rdl->pager_buf == NULL)
return RDLINE_RES_VALIDATED;
}
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;
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)
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;
rdline_asyncpager_reset(rdl);
return RDLINE_RES_EXITED;
}
- if (rdl->pager_buf != NULL) {
- // XXX set cb
+ if (rdl->pager_buf != NULL)
return RDLINE_RES_SUCCESS;
- }
+ else
+ rdline_asyncpager_reset(rdl);
+
rdl->status = RDLINE_INIT;
#else
if (rdl->status == RDLINE_EXITED)
break;
#endif /* !NO_RDLINE_HISTORY */
-
default:
break;
}
}
/* 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;
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, ...)
{
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 */
#define RDLINE_VT100_BUF_SIZE 8
#define RDLINE_HISTORY_BUF_SIZE BUFSIZ
#define RDLINE_HISTORY_MAX_LINE 64
-#define RDLINE_MAX_LINES 39
+#define RDLINE_MAX_LINES 23
enum rdline_status {
RDLINE_INIT,
* help. The first argument is an opaque pointer. The other args
* are buffer and size.
*/
-typedef ssize_t (rdline_write_t)(const struct rdline *, void *, size_t);
+typedef ssize_t (rdline_write_t)(struct rdline *, void *, size_t);
typedef void (rdline_validate_t)(struct rdline *rdl,
typedef int (rdline_help_t)(struct rdline *rdl, const char *buf,
rdline_write_t *write, void *opaque);
+typedef void (rdline_asyncpager_cb_t)(struct rdline *, void *);
+
struct rdline {
enum rdline_status status;
int fd_in;
int pager_len; /* total len of buffer */
int pager_off; /* offset of next data */
int pager_lines; /* number of lines displayed */
+ rdline_asyncpager_cb_t *pager_cb;
+ void *pager_arg;
#endif
};
char *rdline_get_history_item(struct rdline *rdl, unsigned int i);
#ifndef NO_PAGER
+/**
+ * Write data asynchronously (using pager if needed)
+ *
+ * If there is enough place to print data on the current page, it is
+ * printed synchronously. Else, a temporary buffer is allocated and
+ * the data is stored in it. When the main rdline is called again, the
+ * pager is flushed before parsing any other commands.
+ *
+ * @param rdl
+ * The rdline descriptor
+ * @param buf
+ * Buffer to be sent
+ * @param len
+ * Length of buffer to be sent
+ * @return
+ * On success, the number of bytes written is returned (zero
+ * indicates nothing was written). On error, -1 is returned, and
+ * errno is set appropriately
+ */
+ssize_t rdline_asyncpager_write(struct rdline *rdl, void *buf, size_t len);
+
/**
* Print data asynchronously (using pager if needed)
*
* output to strings). On error, a negative value is returned.
*/
int rdline_asyncpager_printf(struct rdline *rdl, const char *fmt, ...);
+
+/**
+ * Set the callback for the pager
+ *
+ * If there is some data in the pager to be printed, set a callback
+ * function that will be called when all the data will be printed. If
+ * the pager is empty, don't do anything and return -1.
+ * @param rdl
+ * The rdline descriptor
+ * @return
+ * - 0 if there is some data in the pager buffer and the callback
+ * is loaded
+ * - -1 if there is no data in pager buffer (in this case the callback
+ * is not called)
+ */
+int rdline_asyncpager_set_cb(struct rdline *rdl, rdline_asyncpager_cb_t *cb,
+ void *arg);
#endif