aboutsummaryrefslogtreecommitdiff
path: root/vis.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-09-08 10:26:45 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-09-08 10:26:45 +0200
commitcaab3855eaafdfef6083ff99416a1b6346a0cc18 (patch)
treed9dff0b60eb444dd876e3a84852acf3e77bd6001 /vis.c
parent16cc6025a0bef7875a9f3426077beecc71cabde6 (diff)
downloadvis-caab3855eaafdfef6083ff99416a1b6346a0cc18.tar.gz
vis-caab3855eaafdfef6083ff99416a1b6346a0cc18.tar.xz
Add user prompt infrastructure
This is implemented by means of an one line height editor window and a set of custom key bindings.
Diffstat (limited to 'vis.c')
-rw-r--r--vis.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/vis.c b/vis.c
index e593cc3..8487a69 100644
--- a/vis.c
+++ b/vis.c
@@ -1,4 +1,6 @@
+#define _BSD_SOURCE
#include <stdlib.h>
+#include <string.h>
#include "vis.h"
#include "util.h"
@@ -12,6 +14,13 @@ static void vis_search_backward(Vis *vis, Regex *regex);
static void vis_windows_arrange_horizontal(Vis *vis);
static void vis_windows_arrange_vertical(Vis *vis);
+static Prompt *vis_prompt_new();
+static void vis_prompt_free(Prompt *prompt);
+static void vis_prompt_clear(Prompt *prompt);
+static void vis_prompt_resize(Prompt *prompt, int width, int height);
+static void vis_prompt_move(Prompt *prompt, int x, int y);
+static void vis_prompt_draw(Prompt *prompt);
+static void vis_prompt_update(Prompt *prompt);
static void vis_window_resize(VisWin *win, int width, int height) {
window_resize(win->win, width, win->statuswin ? height - 1 : height);
@@ -163,6 +172,12 @@ void vis_window_vsplit(Vis *vis, const char *filename) {
void vis_resize(Vis *vis, int width, int height) {
vis->width = width;
vis->height = height;
+ if (vis->prompt->active) {
+ vis->height--;
+ vis_prompt_resize(vis->prompt, vis->width, 1);
+ vis_prompt_move(vis->prompt, 0, vis->height);
+ vis_prompt_draw(vis->prompt);
+ }
vis_draw(vis);
}
@@ -268,6 +283,8 @@ void vis_update(Vis *vis) {
if (vis->win->statuswin)
wnoutrefresh(vis->win->statuswin);
+ if (vis->prompt && vis->prompt->active)
+ vis_prompt_update(vis->prompt);
window_update(vis->win->win);
}
@@ -333,6 +350,10 @@ Vis *vis_new(int width, int height) {
Vis *vis = calloc(1, sizeof(Vis));
if (!vis)
return NULL;
+ if (!(vis->prompt = vis_prompt_new())) {
+ vis_free(vis);
+ return NULL;
+ }
vis->width = width;
vis->height = height;
vis->windows_arrange = vis_windows_arrange_horizontal;
@@ -344,6 +365,7 @@ void vis_free(Vis *vis) {
next = win->next;
vis_window_free(win);
}
+ vis_prompt_free(vis->prompt);
free(vis);
}
@@ -382,3 +404,107 @@ void vis_delete(Vis *vis, size_t pos, size_t len) {
text_delete(vis->win->text, pos, len);
vis_windows_invalidate(vis, pos, pos + len);
}
+
+
+static void vis_prompt_free(Prompt *prompt) {
+ if (!prompt)
+ return;
+ vis_window_free(prompt->win);
+ if (prompt->titlewin)
+ delwin(prompt->titlewin);
+ free(prompt->title);
+ free(prompt);
+}
+
+static Prompt *vis_prompt_new() {
+ Text *text = text_load(NULL);
+ if (!text)
+ return NULL;
+ Prompt *prompt = calloc(1, sizeof(Prompt));
+ if (!prompt)
+ goto err;
+
+ if (!(prompt->win = calloc(1, sizeof(VisWin))))
+ goto err;
+
+ if (!(prompt->win->win = window_new(text)))
+ goto err;
+
+ prompt->win->text = text;
+
+ if (!(prompt->titlewin = newwin(0, 0, 0, 0)))
+ goto err;
+
+ return prompt;
+err:
+ if (!prompt || !prompt->win)
+ text_free(text);
+ vis_prompt_free(prompt);
+ return NULL;
+}
+
+static void vis_prompt_resize(Prompt *prompt, int width, int height) {
+ size_t title_width = strlen(prompt->title);
+ wresize(prompt->titlewin, height, title_width);
+ vis_window_resize(prompt->win, width - title_width, height);
+}
+
+static void vis_prompt_move(Prompt *prompt, int x, int y) {
+ size_t title_width = strlen(prompt->title);
+ mvwin(prompt->titlewin, y, x);
+ vis_window_move(prompt->win, x + title_width, y);
+}
+
+void vis_prompt_show(Vis *vis, const char *title) {
+ Prompt *prompt = vis->prompt;
+ if (prompt->active)
+ return;
+ prompt->active = true;
+ prompt->editor = vis->win;
+ vis->win = prompt->win;
+ free(prompt->title);
+ prompt->title = strdup(title);
+ vis_resize(vis, vis->width, vis->height);
+}
+
+static void vis_prompt_draw(Prompt *prompt) {
+ mvwaddstr(prompt->titlewin, 0, 0, prompt->title);
+}
+
+static void vis_prompt_update(Prompt *prompt) {
+ wnoutrefresh(prompt->titlewin);
+}
+
+static void vis_prompt_clear(Prompt *prompt) {
+ Text *text = prompt->win->text;
+ while (text_undo(text));
+}
+
+void vis_prompt_hide(Vis *vis) {
+ Prompt *prompt = vis->prompt;
+ if (!prompt->active)
+ return;
+ prompt->active = false;
+ vis->win = prompt->editor;
+ prompt->editor = NULL;
+ vis->height++;
+ vis_prompt_clear(prompt);
+ vis_draw(vis);
+}
+
+void vis_prompt_set(Vis *vis, const char *line) {
+ Text *text = vis->prompt->win->text;
+ vis_prompt_clear(vis->prompt);
+ text_insert_raw(text, 0, line, strlen(line));
+ vis_window_draw(vis->prompt->win);
+}
+
+char *vis_prompt_get(Vis *vis) {
+ Text *text = vis->prompt->win->text;
+ char *buf = malloc(text_size(text) + 1);
+ if (!buf)
+ return NULL;
+ size_t len = text_bytes_get(text, 0, text_size(text), buf);
+ buf[len] = '\0';
+ return buf;
+}