summaryrefslogtreecommitdiffstats
path: root/src/doveadm/doveadm-print-pager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/doveadm/doveadm-print-pager.c')
-rw-r--r--src/doveadm/doveadm-print-pager.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-print-pager.c b/src/doveadm/doveadm-print-pager.c
new file mode 100644
index 0000000..3e14383
--- /dev/null
+++ b/src/doveadm/doveadm-print-pager.c
@@ -0,0 +1,113 @@
+/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "ostream.h"
+#include "doveadm-print-private.h"
+
+struct doveadm_print_pager_header {
+ const char *title;
+ enum doveadm_print_header_flags flags;
+};
+
+struct doveadm_print_pager_context {
+ pool_t pool;
+ ARRAY(struct doveadm_print_pager_header) headers;
+ unsigned int header_idx;
+
+ bool streaming:1;
+ bool first_page:1;
+};
+
+static struct doveadm_print_pager_context *ctx;
+
+static void
+doveadm_print_pager_header(const struct doveadm_print_header *hdr)
+{
+ struct doveadm_print_pager_header *fhdr;
+
+ fhdr = array_append_space(&ctx->headers);
+ fhdr->flags = hdr->flags;
+ fhdr->title = p_strdup(ctx->pool, hdr->title);
+}
+
+static void pager_next_hdr(void)
+{
+ if (++ctx->header_idx == array_count(&ctx->headers)) {
+ ctx->header_idx = 0;
+ }
+}
+
+static void doveadm_print_pager_print(const char *value)
+{
+ const struct doveadm_print_pager_header *hdr =
+ array_idx(&ctx->headers, ctx->header_idx);
+
+ if (ctx->header_idx == 0 && !ctx->first_page) {
+ o_stream_nsend(doveadm_print_ostream, "\f\n", 2);
+ }
+ ctx->first_page = FALSE;
+ if ((hdr->flags & DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE) == 0) {
+ o_stream_nsend_str(doveadm_print_ostream, hdr->title);
+ o_stream_nsend(doveadm_print_ostream, ": ", 2);
+ }
+ o_stream_nsend_str(doveadm_print_ostream, value);
+ o_stream_nsend(doveadm_print_ostream, "\n", 1);
+ pager_next_hdr();
+}
+
+static void
+doveadm_print_pager_print_stream(const unsigned char *value, size_t size)
+{
+ const struct doveadm_print_pager_header *hdr =
+ array_idx(&ctx->headers, ctx->header_idx);
+
+ if (!ctx->streaming) {
+ ctx->streaming = TRUE;
+ if ((hdr->flags & DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE) == 0) {
+ o_stream_nsend_str(doveadm_print_ostream, hdr->title);
+ o_stream_nsend(doveadm_print_ostream, ":\n", 2);
+ }
+ }
+ o_stream_nsend(doveadm_print_ostream, value, size);
+ if (size == 0) {
+ pager_next_hdr();
+ ctx->streaming = FALSE;
+ }
+}
+
+static void doveadm_print_pager_init(void)
+{
+ pool_t pool;
+
+ pool = pool_alloconly_create("doveadm print pager", 1024);
+ ctx = p_new(pool, struct doveadm_print_pager_context, 1);
+ ctx->pool = pool;
+ ctx->first_page = TRUE;
+ p_array_init(&ctx->headers, pool, 16);
+}
+
+static void doveadm_print_pager_flush(void)
+{
+ if (ctx->header_idx != 0) {
+ o_stream_nsend(doveadm_print_ostream, "\n", 1);
+ ctx->header_idx = 0;
+ }
+}
+
+static void doveadm_print_pager_deinit(void)
+{
+ pool_unref(&ctx->pool);
+ ctx = NULL;
+}
+
+struct doveadm_print_vfuncs doveadm_print_pager_vfuncs = {
+ DOVEADM_PRINT_TYPE_PAGER,
+
+ doveadm_print_pager_init,
+ doveadm_print_pager_deinit,
+ doveadm_print_pager_header,
+ doveadm_print_pager_print,
+ doveadm_print_pager_print_stream,
+ doveadm_print_pager_flush
+};