aboutsummaryrefslogtreecommitdiff
path: root/editor.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-03-30 23:04:54 +0200
committerMarc André Tanner <mat@brain-dump.org>2015-04-03 23:52:06 +0200
commit9915b9fd0b8e59bda9e334eb9485c473b06055c9 (patch)
tree768f0a04df7e6cfc6d1379de8f19d1d4acdbf3a2 /editor.c
parentb3b1abc76a832e53159b1191120bef56fe3a7041 (diff)
downloadvis-9915b9fd0b8e59bda9e334eb9485c473b06055c9.tar.gz
vis-9915b9fd0b8e59bda9e334eb9485c473b06055c9.tar.xz
Preliminary user interface separation
In theory only ui-curses.[hc] should depend on curses, however in practice keyboard input is still handled in vis.c. Furthermore the syntax definitions as well as keyboard bindings and selection code in window.c still depends on some curses constants. There is also a slight regression in that the window status bar does not show the current mode name. This and related global state should be eliminated in the future.
Diffstat (limited to 'editor.c')
-rw-r--r--editor.c388
1 files changed, 59 insertions, 329 deletions
diff --git a/editor.c b/editor.c
index a8330d6..668062c 100644
--- a/editor.c
+++ b/editor.c
@@ -5,91 +5,12 @@
#include "editor.h"
#include "util.h"
-#ifdef NCURSES_VERSION
-# ifndef NCURSES_EXT_COLORS
-# define NCURSES_EXT_COLORS 0
-# endif
-# if !NCURSES_EXT_COLORS
-# define MAX_COLOR_PAIRS 256
-# endif
-#endif
-#ifndef MAX_COLOR_PAIRS
-# define MAX_COLOR_PAIRS COLOR_PAIRS
-#endif
-
static EditorWin *editor_window_new_text(Editor *ed, Text *text);
-static void editor_window_free(Editor *ed, EditorWin *win);
+static void editor_window_free(EditorWin *win);
static void editor_windows_invalidate(Editor *ed, size_t start, size_t end);
-static void editor_window_draw(EditorWin *win);
-static void windows_arrange_horizontal(Editor *ed);
-static void windows_arrange_vertical(Editor *ed);
-
-static Prompt *editor_prompt_new();
-static void editor_prompt_free(Prompt *prompt);
-static void editor_prompt_clear(Prompt *prompt);
-static void editor_prompt_resize(Prompt *prompt, int width, int height);
-static void editor_prompt_move(Prompt *prompt, int x, int y);
-static void editor_prompt_draw(Prompt *prompt);
-static void editor_prompt_update(Prompt *prompt);
-static void editor_info_draw(Editor *ed);
-
-static void editor_window_resize(EditorWin *win, int width, int height) {
- window_resize(win->win, width, win->statuswin ? height - 1 : height);
- if (win->statuswin)
- wresize(win->statuswin, 1, width);
- win->width = width;
- win->height = height;
-}
-
-static void editor_window_move(EditorWin *win, int x, int y) {
- window_move(win->win, x, y);
- if (win->statuswin)
- mvwin(win->statuswin, y + win->height - 1, x);
-}
-
-static void editor_window_statusbar_draw(EditorWin *win) {
- if (win->statuswin && win->editor->statusbar)
- win->editor->statusbar(win);
-}
-
-static void editor_window_cursor_moved(Win *winwin, void *data) {
- EditorWin *win = data;
- Filerange sel = window_selection_get(winwin);
- if (text_range_valid(&sel) && sel.start != sel.end) {
- text_mark_intern_set(win->text, MARK_SELECTION_START, sel.start);
- text_mark_intern_set(win->text, MARK_SELECTION_END, sel.end);
- }
- editor_window_statusbar_draw(win);
-}
-void editor_statusbar_set(Editor *ed, void (*statusbar)(EditorWin*)) {
- ed->statusbar = statusbar;
-}
-
-static void windows_arrange_horizontal(Editor *ed) {
- int n = 0, x = 0, y = 0;
- for (EditorWin *win = ed->windows; win; win = win->next)
- n++;
- int height = ed->height / MAX(1, n);
- for (EditorWin *win = ed->windows; win; win = win->next) {
- editor_window_resize(win, ed->width, win->next ? height : ed->height - y);
- editor_window_move(win, x, y);
- y += height;
- }
-}
-
-static void windows_arrange_vertical(Editor *ed) {
- int n = 0, x = 0, y = 0;
- for (EditorWin *win = ed->windows; win; win = win->next)
- n++;
- int width = (ed->width / MAX(1, n)) - 1;
- for (EditorWin *win = ed->windows; win; win = win->next) {
- editor_window_resize(win, win->next ? width : ed->width - x, ed->height);
- editor_window_move(win, x, y);
- x += width;
- if (win->next)
- mvvline(0, x++, ACS_VLINE, ed->height);
- }
+void editor_windows_arrange(Editor *ed, enum UiLayout layout) {
+ ed->ui->arrange(ed->ui, layout);
}
bool editor_window_reload(EditorWin *win) {
@@ -115,16 +36,6 @@ bool editor_window_reload(EditorWin *win) {
return true;
}
-void editor_windows_arrange_vertical(Editor *ed) {
- ed->windows_arrange = windows_arrange_vertical;
- editor_draw(ed);
-}
-
-void editor_windows_arrange_horizontal(Editor *ed) {
- ed->windows_arrange = windows_arrange_horizontal;
- editor_draw(ed);
-}
-
bool editor_window_split(EditorWin *original) {
EditorWin *win = editor_window_new_text(original->editor, original->text);
if (!win)
@@ -201,18 +112,8 @@ size_t editor_window_changelist_next(EditorWin *win) {
return win->changelist.pos;
}
-void editor_resize(Editor *ed, int width, int height) {
- ed->width = width;
- ed->height = height;
- if (ed->info[0]) {
- ed->height--;
- } else if (ed->prompt->active) {
- ed->height--;
- editor_prompt_resize(ed->prompt, ed->width, 1);
- editor_prompt_move(ed->prompt, 0, ed->height);
- editor_prompt_draw(ed->prompt);
- }
- editor_draw(ed);
+void editor_resize(Editor *ed) {
+ ed->ui->resize(ed->ui);
}
void editor_window_next(Editor *ed) {
@@ -222,8 +123,7 @@ void editor_window_next(Editor *ed) {
ed->win = ed->win->next;
if (!ed->win)
ed->win = ed->windows;
- editor_window_statusbar_draw(sel);
- editor_window_statusbar_draw(ed->win);
+ ed->ui->window_focus(ed->win->ui);
}
void editor_window_prev(Editor *ed) {
@@ -233,8 +133,7 @@ void editor_window_prev(Editor *ed) {
ed->win = ed->win->prev;
if (!ed->win)
for (ed->win = ed->windows; ed->win->next; ed->win = ed->win->next);
- editor_window_statusbar_draw(sel);
- editor_window_statusbar_draw(ed->win);
+ ed->ui->window_focus(ed->win->ui);
}
static void editor_windows_invalidate(Editor *ed, size_t start, size_t end) {
@@ -243,10 +142,10 @@ static void editor_windows_invalidate(Editor *ed, size_t start, size_t end) {
Filerange view = window_viewport_get(win->win);
if ((view.start <= start && start <= view.end) ||
(view.start <= end && end <= view.end))
- editor_window_draw(win);
+ win->ui->draw(win->ui);
}
}
- editor_window_draw(ed->win);
+ ed->win->ui->draw(ed->win->ui);
}
int editor_tabwidth_get(Editor *ed) {
@@ -268,7 +167,7 @@ bool editor_syntax_load(Editor *ed, Syntax *syntaxes, Color *colors) {
for (Color *color = colors; color && color->fg; color++) {
if (color->attr == 0)
color->attr = A_NORMAL;
- color->attr |= COLOR_PAIR(editor_color_get(color->fg, color->bg));
+ color->attr |= COLOR_PAIR(ed->ui->color_get(color->fg, color->bg));
}
for (Syntax *syn = syntaxes; syn && syn->name; syn++) {
@@ -303,49 +202,24 @@ void editor_syntax_unload(Editor *ed) {
ed->syntaxes = NULL;
}
-static void editor_window_draw(EditorWin *win) {
- // TODO window_draw draw should restore cursor position
- window_draw(win->win);
- window_cursor_to(win->win, window_cursor_get(win->win));
-}
-
void editor_draw(Editor *ed) {
- erase();
- if (ed->windows) {
- ed->windows_arrange(ed);
- for (EditorWin *win = ed->windows; win; win = win->next) {
- if (ed->win != win)
- editor_window_draw(win);
- }
- editor_window_draw(ed->win);
- }
- if (ed->info[0])
- editor_info_draw(ed);
- wnoutrefresh(stdscr);
+ ed->ui->draw(ed->ui);
}
void editor_update(Editor *ed) {
- for (EditorWin *win = ed->windows; win; win = win->next) {
- if (ed->win != win) {
- if (win->statuswin)
- wnoutrefresh(win->statuswin);
- window_update(win->win);
- }
- }
+ ed->ui->update(ed->ui);
+}
- if (ed->win->statuswin)
- wnoutrefresh(ed->win->statuswin);
- if (ed->prompt && ed->prompt->active)
- editor_prompt_update(ed->prompt);
- window_update(ed->win->win);
+void editor_suspend(Editor *ed) {
+ ed->ui->suspend(ed->ui);
}
-static void editor_window_free(Editor *ed, EditorWin *win) {
+static void editor_window_free(EditorWin *win) {
if (!win)
return;
- window_free(win->win);
- if (win->statuswin)
- delwin(win->statuswin);
+ Editor *ed = win->editor;
+ if (ed && ed->ui)
+ ed->ui->window_free(win->ui);
ringbuf_free(win->jumplist);
bool needed = false;
for (EditorWin *w = ed ? ed->windows : NULL; w; w = w->next) {
@@ -365,14 +239,13 @@ static EditorWin *editor_window_new_text(Editor *ed, Text *text) {
return NULL;
win->editor = ed;
win->text = text;
- win->win = window_new(win->text);
- win->statuswin = newwin(1, ed->width, 0, 0);
win->jumplist = ringbuf_alloc(31);
- if (!win->win || !win->statuswin) {
- editor_window_free(ed, win);
+ win->ui = ed->ui->window_new(ed->ui, text);
+ if (!win->jumplist || !win->ui) {
+ editor_window_free(win);
return NULL;
}
- window_cursor_watch(win->win, editor_window_cursor_moved, win);
+ win->win = win->ui->view_get(win->ui);
window_tabwidth_set(win->win, ed->tabwidth);
if (ed->windows)
ed->windows->prev = win;
@@ -380,6 +253,7 @@ static EditorWin *editor_window_new_text(Editor *ed, Text *text) {
win->prev = NULL;
ed->windows = win;
ed->win = win;
+ ed->ui->window_focus(win->ui);
return win;
}
@@ -441,38 +315,41 @@ bool editor_window_new_fd(Editor *ed, int fd) {
return true;
}
-static void editor_window_detach(Editor *ed, EditorWin *win) {
+void editor_window_close(EditorWin *win) {
+ Editor *ed = win->editor;
if (win->prev)
win->prev->next = win->next;
if (win->next)
win->next->prev = win->prev;
if (ed->windows == win)
ed->windows = win->next;
- win->next = win->prev = NULL;
-}
-
-void editor_window_close(EditorWin *win) {
- Editor *ed = win->editor;
if (ed->win == win)
ed->win = win->next ? win->next : win->prev;
- editor_window_detach(ed, win);
- editor_window_free(ed, win);
+ if (ed->win)
+ ed->ui->window_focus(ed->win->ui);
+ editor_window_free(win);
editor_draw(ed);
}
-Editor *editor_new(int width, int height) {
+Editor *editor_new(Ui *ui) {
+ if (!ui)
+ return NULL;
Editor *ed = calloc(1, sizeof(Editor));
if (!ed)
return NULL;
- if (!(ed->prompt = editor_prompt_new()))
+ ed->ui = ui;
+ ed->ui->init(ed->ui, ed);
+ ed->tabwidth = 8;
+ ed->expandtab = false;
+ if (!(ed->prompt = calloc(1, sizeof(EditorWin))))
+ goto err;
+ if (!(ed->prompt->text = text_load(NULL)))
+ goto err;
+ if (!(ed->prompt->ui = ed->ui->prompt_new(ed->ui, ed->prompt->text)))
goto err;
if (!(ed->search_pattern = text_regex_new()))
goto err;
- ed->width = width;
- ed->height = height;
- ed->tabwidth = 8;
- ed->expandtab = false;
- ed->windows_arrange = windows_arrange_horizontal;
+ ed->prompt->win = ed->prompt->ui->view_get(ed->prompt->ui);
return ed;
err:
editor_free(ed);
@@ -484,11 +361,12 @@ void editor_free(Editor *ed) {
return;
while (ed->windows)
editor_window_close(ed->windows);
- editor_prompt_free(ed->prompt);
+ editor_window_free(ed->prompt);
text_regex_free(ed->search_pattern);
for (int i = 0; i < REG_LAST; i++)
register_free(&ed->registers[i]);
editor_syntax_unload(ed);
+ ed->ui->free(ed->ui);
free(ed);
}
@@ -528,187 +406,39 @@ void editor_delete(Editor *ed, size_t pos, size_t len) {
editor_windows_invalidate(ed, pos, pos + len);
}
-static void editor_prompt_free(Prompt *prompt) {
- if (!prompt)
- return;
- editor_window_free(NULL, prompt->win);
- if (prompt->titlewin)
- delwin(prompt->titlewin);
- free(prompt->title);
- free(prompt);
-}
-
-static Prompt *editor_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(EditorWin))))
- 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);
- editor_prompt_free(prompt);
- return NULL;
-}
-
-static void editor_prompt_resize(Prompt *prompt, int width, int height) {
- size_t title_width = strlen(prompt->title);
- wresize(prompt->titlewin, height, title_width);
- editor_window_resize(prompt->win, width - title_width, height);
-}
-
-static void editor_prompt_move(Prompt *prompt, int x, int y) {
- size_t title_width = strlen(prompt->title);
- mvwin(prompt->titlewin, y, x);
- editor_window_move(prompt->win, x + title_width, y);
-}
-
void editor_prompt_show(Editor *ed, const char *title, const char *text) {
- Prompt *prompt = ed->prompt;
- if (prompt->active)
+ if (ed->prompt_window)
return;
- prompt->active = true;
- prompt->editor = ed->win;
- free(prompt->title);
- prompt->title = strdup(title);
- text_insert(prompt->win->text, 0, text, strlen(text));
- window_cursor_to(prompt->win->win, text_size(prompt->win->text));
- ed->win = prompt->win;
- editor_resize(ed, ed->width, ed->height);
-}
-
-static void editor_prompt_draw(Prompt *prompt) {
- mvwaddstr(prompt->titlewin, 0, 0, prompt->title);
-}
-
-static void editor_prompt_update(Prompt *prompt) {
- wnoutrefresh(prompt->titlewin);
-}
-
-static void editor_prompt_clear(Prompt *prompt) {
- Text *text = prompt->win->text;
- while (text_undo(text) != EPOS);
- window_cursor_to(prompt->win->win, 0);
+ ed->prompt_window = ed->win;
+ ed->win = ed->prompt;
+ ed->prompt_type = title[0];
+ ed->ui->prompt(ed->ui, title, text);
}
void editor_prompt_hide(Editor *ed) {
- Prompt *prompt = ed->prompt;
- if (!prompt->active)
+ if (!ed->prompt_window)
return;
- prompt->active = false;
- ed->win = prompt->editor;
- prompt->editor = NULL;
- ed->height++;
- editor_prompt_clear(prompt);
- editor_draw(ed);
-}
-
-void editor_prompt_set(Editor *ed, const char *line) {
- Text *text = ed->prompt->win->text;
- editor_prompt_clear(ed->prompt);
- text_insert(text, 0, line, strlen(line));
- editor_window_draw(ed->prompt->win);
+ ed->ui->prompt_hide(ed->ui);
+ ed->win = ed->prompt_window;
+ ed->prompt_window = NULL;
}
char *editor_prompt_get(Editor *ed) {
- Text *text = ed->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;
+ return ed->ui->prompt_input(ed->ui);
}
void editor_info_show(Editor *ed, const char *msg, ...) {
va_list ap;
va_start(ap, msg);
- vsnprintf(ed->info, sizeof(ed->info), msg, ap);
+ ed->ui->info(ed->ui, msg, ap);
va_end(ap);
- editor_resize(ed, ed->width, ed->height);
}
void editor_info_hide(Editor *ed) {
- if (!ed->info[0])
- return;
- ed->info[0] = '\0';
- ed->height++;
- editor_draw(ed);
+ ed->ui->info_hide(ed->ui);
}
-static void editor_info_draw(Editor *ed) {
- attrset(A_BOLD);
- mvaddstr(ed->height, 0, ed->info);
-}
-
-static unsigned int color_hash(short fg, short bg)
-{
- if (fg == -1)
- fg = COLORS;
- if (bg == -1)
- bg = COLORS + 1;
- return fg * (COLORS + 2) + bg;
-}
-
-short editor_color_get(short fg, short bg)
-{
- static bool has_default_colors;
- static short *color2palette, default_fg, default_bg;
- static short color_pairs_max, color_pair_current;
-
- if (!color2palette) {
- pair_content(0, &default_fg, &default_bg);
- if (default_fg == -1)
- default_fg = COLOR_WHITE;
- if (default_bg == -1)
- default_bg = COLOR_BLACK;
- has_default_colors = (use_default_colors() == OK);
- color_pairs_max = MIN(COLOR_PAIRS, MAX_COLOR_PAIRS);
- if (COLORS)
- color2palette = calloc((COLORS + 2) * (COLORS + 2), sizeof(short));
- }
-
- if (fg >= COLORS)
- fg = default_fg;
- if (bg >= COLORS)
- bg = default_bg;
-
- if (!has_default_colors) {
- if (fg == -1)
- fg = default_fg;
- if (bg == -1)
- bg = default_bg;
- }
-
- if (!color2palette || (fg == -1 && bg == -1))
- return 0;
-
- unsigned int index = color_hash(fg, bg);
- if (color2palette[index] == 0) {
- short oldfg, oldbg;
- if (++color_pair_current >= color_pairs_max)
- color_pair_current = 1;
- pair_content(color_pair_current, &oldfg, &oldbg);
- unsigned int old_index = color_hash(oldfg, oldbg);
- if (init_pair(color_pair_current, fg, bg) == OK) {
- color2palette[old_index] = 0;
- color2palette[index] = color_pair_current;
- }
- }
-
- return color2palette[index];
+void editor_window_options(EditorWin *win, enum UiOption options) {
+ win->ui->options(win->ui, options);
}
+