aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-04-05 10:10:47 +0200
committerMarc André Tanner <mat@brain-dump.org>2015-04-05 19:58:45 +0200
commit164527b74aa6cd04bd50c36399bc14ab90073bcf (patch)
tree53d61af1dc32bb5bfaaa94d06c02bfd521df2de8
parent1304c0680b8db9d8526eb36f0b563d534703338b (diff)
downloadvis-164527b74aa6cd04bd50c36399bc14ab90073bcf.tar.gz
vis-164527b74aa6cd04bd50c36399bc14ab90073bcf.tar.xz
Introduce new struct VisText
This adds yet another layer of indirection and stores vi related stuff which is associated with a given text but shared among all windows displaying it (e.g. marks). This will also help if one wants to keep texts arround which aren't currently displayed.
-rw-r--r--config.def.h8
-rw-r--r--editor.c151
-rw-r--r--editor.h43
-rw-r--r--text.c24
-rw-r--r--text.h6
-rw-r--r--vis.c109
-rw-r--r--window.c7
7 files changed, 178 insertions, 170 deletions
diff --git a/config.def.h b/config.def.h
index b8657a4..48feb08 100644
--- a/config.def.h
+++ b/config.def.h
@@ -457,7 +457,7 @@ static KeyBinding vis_mode_visual_line[] = {
static void vis_mode_visual_line_enter(Mode *old) {
Win *win = vis->win->win;
- window_cursor_to(win, text_line_begin(vis->win->text, window_cursor_get(win)));
+ window_cursor_to(win, text_line_begin(vis->win->text->data, window_cursor_get(win)));
if (!old->visual) {
window_selection_start(vis->win->win);
vis_modes[VIS_MODE_OPERATOR].parent = &vis_modes[VIS_MODE_TEXTOBJ];
@@ -559,11 +559,11 @@ static KeyBinding vis_mode_insert[] = {
static void vis_mode_insert_leave(Mode *old) {
/* make sure we can recover the current state after an editing operation */
- text_snapshot(vis->win->text);
+ text_snapshot(vis->win->text->data);
}
static void vis_mode_insert_idle(void) {
- text_snapshot(vis->win->text);
+ text_snapshot(vis->win->text->data);
}
static void vis_mode_insert_input(const char *str, size_t len) {
@@ -585,7 +585,7 @@ static KeyBinding vis_mode_replace[] = {
static void vis_mode_replace_leave(Mode *old) {
/* make sure we can recover the current state after an editing operation */
- text_snapshot(vis->win->text);
+ text_snapshot(vis->win->text->data);
}
static void vis_mode_replace_input(const char *str, size_t len) {
diff --git a/editor.c b/editor.c
index 668062c..93f347f 100644
--- a/editor.c
+++ b/editor.c
@@ -5,7 +5,9 @@
#include "editor.h"
#include "util.h"
-static EditorWin *editor_window_new_text(Editor *ed, Text *text);
+static void vis_text_free(Editor *ed, VisText *text);
+static VisText *vis_text_new(Editor *ed, const char *filename);
+static EditorWin *editor_window_new_text(Editor *ed, VisText *text);
static void editor_window_free(EditorWin *win);
static void editor_windows_invalidate(Editor *ed, size_t start, size_t end);
@@ -14,25 +16,16 @@ void editor_windows_arrange(Editor *ed, enum UiLayout layout) {
}
bool editor_window_reload(EditorWin *win) {
- const char *filename = text_filename_get(win->text);
+ const char *filename = text_filename_get(win->text->data);
/* can't reload unsaved file */
if (!filename)
return false;
- Text *text = text_load(filename);
+ VisText *text = vis_text_new(win->editor, filename);
if (!text)
return false;
- /* check wether the text is displayed in another window */
- bool needed = false;
- for (EditorWin *w = win->editor->windows; w; w = w->next) {
- if (w != win && w->text == win->text) {
- needed = true;
- break;
- }
- }
- if (!needed)
- text_free(win->text);
+ vis_text_free(win->editor, win->text);
win->text = text;
- window_reload(win->win, text);
+ window_reload(win->win, text->data);
return true;
}
@@ -41,6 +34,7 @@ bool editor_window_split(EditorWin *original) {
if (!win)
return false;
win->text = original->text;
+ win->text->refcount++;
window_syntax_set(win->win, window_syntax_get(original->win));
window_cursor_to(win->win, window_cursor_get(original->win));
editor_draw(win->editor);
@@ -48,7 +42,7 @@ bool editor_window_split(EditorWin *original) {
}
void editor_window_jumplist_add(EditorWin *win, size_t pos) {
- Mark mark = text_mark_set(win->text, pos);
+ Mark mark = text_mark_set(win->text->data, pos);
if (mark && win->jumplist)
ringbuf_add(win->jumplist, mark);
}
@@ -59,7 +53,7 @@ size_t editor_window_jumplist_prev(EditorWin *win) {
Mark mark = ringbuf_prev(win->jumplist);
if (!mark)
return cur;
- size_t pos = text_mark_get(win->text, mark);
+ size_t pos = text_mark_get(win->text->data, mark);
if (pos != EPOS && pos != cur)
return pos;
}
@@ -72,7 +66,7 @@ size_t editor_window_jumplist_next(EditorWin *win) {
Mark mark = ringbuf_next(win->jumplist);
if (!mark)
return cur;
- size_t pos = text_mark_get(win->text, mark);
+ size_t pos = text_mark_get(win->text->data, mark);
if (pos != EPOS && pos != cur)
return pos;
}
@@ -90,7 +84,7 @@ size_t editor_window_changelist_prev(EditorWin *win) {
win->changelist.index = 0;
else
win->changelist.index++;
- size_t newpos = text_history_get(win->text, win->changelist.index);
+ size_t newpos = text_history_get(win->text->data, win->changelist.index);
if (newpos == EPOS)
win->changelist.index--;
else
@@ -104,7 +98,7 @@ size_t editor_window_changelist_next(EditorWin *win) {
win->changelist.index = 0;
else if (win->changelist.index > 0)
win->changelist.index--;
- size_t newpos = text_history_get(win->text, win->changelist.index);
+ size_t newpos = text_history_get(win->text->data, win->changelist.index);
if (newpos == EPOS)
win->changelist.index++;
else
@@ -221,26 +215,17 @@ static void editor_window_free(EditorWin *win) {
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) {
- if (w->text == win->text) {
- needed = true;
- break;
- }
- }
- if (!needed)
- text_free(win->text);
free(win);
}
-static EditorWin *editor_window_new_text(Editor *ed, Text *text) {
+static EditorWin *editor_window_new_text(Editor *ed, VisText *text) {
EditorWin *win = calloc(1, sizeof(EditorWin));
if (!win)
return NULL;
win->editor = ed;
win->text = text;
win->jumplist = ringbuf_alloc(31);
- win->ui = ed->ui->window_new(ed->ui, text);
+ win->ui = ed->ui->window_new(ed->ui, text->data);
if (!win->jumplist || !win->ui) {
editor_window_free(win);
return NULL;
@@ -250,47 +235,79 @@ static EditorWin *editor_window_new_text(Editor *ed, Text *text) {
if (ed->windows)
ed->windows->prev = win;
win->next = ed->windows;
- win->prev = NULL;
ed->windows = win;
ed->win = win;
ed->ui->window_focus(win->ui);
return win;
}
-bool editor_window_new(Editor *ed, const char *filename) {
- Text *text = NULL;
- /* try to detect whether the same file is already open in another window
- * TODO: do this based on inodes */
- EditorWin *original = NULL;
+static void vis_text_free(Editor *ed, VisText *text) {
+ if (!text)
+ return;
+ if (--text->refcount > 0)
+ return;
+
+ text_free(text->data);
+
+ if (text->prev)
+ text->prev->next = text->next;
+ if (text->next)
+ text->next->prev = text->prev;
+ if (ed->texts == text)
+ ed->texts = text->next;
+ free(text);
+}
+
+static VisText *vis_text_new_text(Editor *ed, Text *data) {
+ VisText *text = calloc(1, sizeof(*text));
+ if (!text)
+ return NULL;
+ text->data = data;
+ text->refcount++;
+ if (ed->texts)
+ ed->texts->prev = text;
+ text->next = ed->texts;
+ ed->texts = text;
+ return text;
+}
+
+static VisText *vis_text_new(Editor *ed, const char *filename) {
if (filename) {
- for (EditorWin *win = ed->windows; win; win = win->next) {
- const char *f = text_filename_get(win->text);
+ /* try to detect whether the same file is already open in another window
+ * TODO: do this based on inodes */
+ for (VisText *txt = ed->texts; txt; txt = txt->next) {
+ const char *f = text_filename_get(txt->data);
if (f && strcmp(f, filename) == 0) {
- original = win;
- break;
+ txt->refcount++;
+ return txt;
}
}
}
- if (original)
- text = original->text;
- else
- text = text_load(filename && access(filename, F_OK) == 0 ? filename : NULL);
+ Text *data = text_load(filename && access(filename, F_OK) == 0 ? filename : NULL);
+ if (filename)
+ text_filename_set(data, filename);
+
+ VisText *text = vis_text_new_text(ed, data);
+ if (!text) {
+ text_free(data);
+ return NULL;
+ }
+
+ return text;
+}
+
+bool editor_window_new(Editor *ed, const char *filename) {
+ VisText *text = vis_text_new(ed, filename);
if (!text)
return false;
-
EditorWin *win = editor_window_new_text(ed, text);
if (!win) {
- if (!original)
- text_free(text);
+ vis_text_free(ed, text);
return false;
}
- if (original) {
- window_syntax_set(win->win, window_syntax_get(original->win));
- window_cursor_to(win->win, window_cursor_get(original->win));
- } else if (filename) {
- text_filename_set(text, filename);
+ if (filename) {
for (Syntax *syn = ed->syntaxes; syn && syn->name; syn++) {
if (!regexec(&syn->file_regex, filename, 0, NULL, 0)) {
window_syntax_set(win->win, syn);
@@ -305,18 +322,25 @@ bool editor_window_new(Editor *ed, const char *filename) {
}
bool editor_window_new_fd(Editor *ed, int fd) {
- Text *txt = text_load_fd(fd);
- if (!txt)
+ Text *data = text_load_fd(fd);
+ if (!data)
return false;
- EditorWin *win = editor_window_new_text(ed, txt);
- if (!win)
+ VisText *text = vis_text_new_text(ed, data);
+ if (!text) {
+ vis_text_free(ed, text);
return false;
- editor_draw(ed);
+ }
+ EditorWin *win = editor_window_new_text(ed, text);
+ if (!win) {
+ vis_text_free(ed, text);
+ return false;
+ }
return true;
}
void editor_window_close(EditorWin *win) {
Editor *ed = win->editor;
+ vis_text_free(ed, win->text);
if (win->prev)
win->prev->next = win->next;
if (win->next)
@@ -325,9 +349,9 @@ void editor_window_close(EditorWin *win) {
ed->windows = win->next;
if (ed->win == win)
ed->win = win->next ? win->next : win->prev;
+ editor_window_free(win);
if (ed->win)
ed->ui->window_focus(ed->win->ui);
- editor_window_free(win);
editor_draw(ed);
}
@@ -343,9 +367,11 @@ Editor *editor_new(Ui *ui) {
ed->expandtab = false;
if (!(ed->prompt = calloc(1, sizeof(EditorWin))))
goto err;
- if (!(ed->prompt->text = text_load(NULL)))
+ if (!(ed->prompt->text = calloc(1, sizeof(VisText))))
+ goto err;
+ if (!(ed->prompt->text->data = text_load(NULL)))
goto err;
- if (!(ed->prompt->ui = ed->ui->prompt_new(ed->ui, ed->prompt->text)))
+ if (!(ed->prompt->ui = ed->ui->prompt_new(ed->ui, ed->prompt->text->data)))
goto err;
if (!(ed->search_pattern = text_regex_new()))
goto err;
@@ -361,6 +387,7 @@ void editor_free(Editor *ed) {
return;
while (ed->windows)
editor_window_close(ed->windows);
+ vis_text_free(ed, ed->prompt->text);
editor_window_free(ed->prompt);
text_regex_free(ed->search_pattern);
for (int i = 0; i < REG_LAST; i++)
@@ -397,12 +424,12 @@ void editor_delete_key(Editor *ed) {
}
void editor_insert(Editor *ed, size_t pos, const char *c, size_t len) {
- text_insert(ed->win->text, pos, c, len);
+ text_insert(ed->win->text->data, pos, c, len);
editor_windows_invalidate(ed, pos, pos + len);
}
void editor_delete(Editor *ed, size_t pos, size_t len) {
- text_delete(ed->win->text, pos, len);
+ text_delete(ed->win->text->data, pos, len);
editor_windows_invalidate(ed, pos, pos + len);
}
diff --git a/editor.h b/editor.h
index ba7d3aa..9af1254 100644
--- a/editor.h
+++ b/editor.h
@@ -15,22 +15,6 @@ typedef struct EditorWin EditorWin;
#include "syntax.h"
#include "ring-buffer.h"
-
-typedef struct {
- size_t index; /* #number of changes */
- size_t pos; /* where the current change occured */
-} ChangeList;
-
-struct EditorWin {
- Editor *editor; /* editor instance to which this window belongs */
- UiWin *ui;
- Text *text; /* underlying text management */
- Win *win; /* window for the text area */
- RingBuffer *jumplist; /* LRU jump management */
- ChangeList changelist; /* state for iterating through least recently changes */
- EditorWin *prev, *next; /* neighbouring windows */
-};
-
enum Reg {
REG_a,
REG_b,
@@ -91,10 +75,37 @@ enum Mark {
MARK_z,
MARK_SELECTION_START,
MARK_SELECTION_END,
+ MARK_LAST,
+};
+
+
+typedef struct VisText VisText;
+
+struct VisText {
+ Text *data;
+ int refcount;
+ Mark marks[MARK_LAST];
+ VisText *next, *prev;
+};
+
+typedef struct {
+ size_t index; /* #number of changes */
+ size_t pos; /* where the current change occured */
+} ChangeList;
+
+struct EditorWin {
+ Editor *editor; /* editor instance to which this window belongs */
+ UiWin *ui;
+ VisText *text; /* underlying text management */
+ Win *win; /* window for the text area */
+ RingBuffer *jumplist; /* LRU jump management */
+ ChangeList changelist; /* state for iterating through least recently changes */
+ EditorWin *prev, *next; /* neighbouring windows */
};
struct Editor {
Ui *ui;
+ VisText *texts;
EditorWin *windows; /* list of windows */
EditorWin *win; /* currently active window */
Syntax *syntaxes; /* NULL terminated array of syntax definitions */
diff --git a/text.c b/text.c
index cd85734..553a3cb 100644
--- a/text.c
+++ b/text.c
@@ -118,7 +118,6 @@ struct Text {
struct stat info; /* stat as proped on load time */
int fd; /* the file descriptor of the original mmap-ed data */
LineCache lines; /* mapping between absolute pos in bytes and logical line breaks */
- Mark marks[32]; /* a mark is a pointer into an underlying buffer */
int newlines; /* 0: unknown, 1: \n, -1: \r\n */
};
@@ -1159,29 +1158,6 @@ size_t text_mark_get(Text *txt, Mark mark) {
return EPOS;
}
-void text_mark_intern_set(Text *txt, MarkIntern mark, size_t pos) {
- if (mark < 0 || mark >= LENGTH(txt->marks))
- return;
- txt->marks[mark] = text_mark_set(txt, pos);
-}
-
-size_t text_mark_intern_get(Text *txt, MarkIntern mark) {
- if (mark < 0 || mark >= LENGTH(txt->marks))
- return EPOS;
- return text_mark_get(txt, txt->marks[mark]);
-}
-
-void text_mark_intern_clear(Text *txt, MarkIntern mark) {
- if (mark < 0 || mark >= LENGTH(txt->marks))
- return;
- txt->marks[mark] = NULL;
-}
-
-void text_mark_intern_clear_all(Text *txt) {
- for (MarkIntern mark = 0; mark < LENGTH(txt->marks); mark++)
- text_mark_intern_clear(txt, mark);
-}
-
size_t text_history_get(Text *txt, size_t index) {
for (Action *a = txt->current_action ? txt->current_action : txt->undo; a; a = a->next) {
if (index-- == 0) {
diff --git a/text.h b/text.h
index faa340c..e323cc2 100644
--- a/text.h
+++ b/text.h
@@ -77,12 +77,6 @@ typedef const char* Mark;
Mark text_mark_set(Text*, size_t pos);
size_t text_mark_get(Text*, Mark);
-typedef int MarkIntern;
-void text_mark_intern_set(Text*, MarkIntern, size_t pos);
-size_t text_mark_intern_get(Text*, MarkIntern);
-void text_mark_intern_clear(Text*, MarkIntern);
-void text_mark_intern_clear_all(Text*);
-
/* get position of change denoted by index, where 0 indicates the most recent */
size_t text_history_get(Text*, size_t index);
diff --git a/vis.c b/vis.c
index dc1ac6e..c46ea3c 100644
--- a/vis.c
+++ b/vis.c
@@ -127,7 +127,7 @@ typedef struct { /** collects all information until an operator is e
const Movement *movement;
const TextObject *textobj;
Register *reg;
- MarkIntern mark;
+ int mark;
Key key;
Arg arg;
} Action;
@@ -546,7 +546,7 @@ static bool exec_command(char type, const char *cmdline);
static void op_delete(OperatorContext *c) {
size_t len = c->range.end - c->range.start;
c->reg->linewise = c->linewise;
- register_put(c->reg, vis->win->text, &c->range);
+ register_put(c->reg, vis->win->text->data, &c->range);
editor_delete(vis, c->range.start, len);
window_cursor_to(vis->win->win, c->range.start);
}
@@ -558,11 +558,11 @@ static void op_change(OperatorContext *c) {
static void op_yank(OperatorContext *c) {
c->reg->linewise = c->linewise;
- register_put(c->reg, vis->win->text, &c->range);
+ register_put(c->reg, vis->win->text->data, &c->range);
}
static void op_put(OperatorContext *c) {
- Text *txt = vis->win->text;
+ Text *txt = vis->win->text->data;
size_t pos = window_cursor_get(vis->win->win);
if (c->arg->i > 0) {
if (c->reg->linewise)
@@ -591,7 +591,7 @@ static const char *expand_tab(void) {
}
static void op_shift_right(OperatorContext *c) {
- Text *txt = vis->win->text;
+ Text *txt = vis->win->text->data;
size_t pos = text_line_begin(txt, c->range.end), prev_pos;
const char *tab = expand_tab();
size_t tablen = strlen(tab);
@@ -610,7 +610,7 @@ static void op_shift_right(OperatorContext *c) {
}
static void op_shift_left(OperatorContext *c) {
- Text *txt = vis->win->text;
+ Text *txt = vis->win->text->data;
size_t pos = text_line_begin(txt, c->range.end), prev_pos;
size_t tabwidth = editor_tabwidth_get(vis), tablen;
@@ -642,7 +642,7 @@ static void op_case_change(OperatorContext *c) {
char *buf = malloc(len);
if (!buf)
return;
- len = text_bytes_get(vis->win->text, c->range.start, len, buf);
+ len = text_bytes_get(vis->win->text->data, c->range.start, len, buf);
size_t rem = len;
for (char *cur = buf; rem > 0; cur++, rem--) {
int ch = (unsigned char)*cur;
@@ -656,14 +656,14 @@ static void op_case_change(OperatorContext *c) {
}
}
- text_delete(vis->win->text, c->range.start, len);
- text_insert(vis->win->text, c->range.start, buf, len);
+ text_delete(vis->win->text->data, c->range.start, len);
+ text_insert(vis->win->text->data, c->range.start, buf, len);
editor_draw(vis);
free(buf);
}
static void op_join(OperatorContext *c) {
- Text *txt = vis->win->text;
+ Text *txt = vis->win->text->data;
size_t pos = text_line_begin(txt, c->range.end), prev_pos;
Filerange sel = window_selection_get(vis->win->win);
/* if a selection ends at the begin of a line, skip line break */
@@ -703,7 +703,7 @@ static void op_repeat_replace(OperatorContext *c) {
chars++;
}
- Iterator it = text_iterator_get(vis->win->text, c->pos);
+ Iterator it = text_iterator_get(vis->win->text->data, c->pos);
while (chars-- > 0)
text_iterator_char_next(&it, NULL);
editor_delete(vis, c->pos, it.pos - c->pos);
@@ -713,14 +713,14 @@ static void op_repeat_replace(OperatorContext *c) {
/** movement implementations of type: size_t (*move)(const Arg*) */
static char *get_word_under_cursor() {
- Filerange word = text_object_word(vis->win->text, window_cursor_get(vis->win->win));
+ Filerange word = text_object_word(vis->win->text->data, window_cursor_get(vis->win->win));
if (!text_range_valid(&word))
return NULL;
size_t len = word.end - word.start;
char *buf = malloc(len+1);
if (!buf)
return NULL;
- len = text_bytes_get(vis->win->text, word.start, len, buf);
+ len = text_bytes_get(vis->win->text->data, word.start, len, buf);
buf[len] = '\0';
return buf;
}
@@ -729,7 +729,7 @@ static size_t search_word_forward(const Arg *arg) {
size_t pos = window_cursor_get(vis->win->win);
char *word = get_word_under_cursor();
if (word && !text_regex_compile(vis->search_pattern, word, REG_EXTENDED))
- pos = text_search_forward(vis->win->text, pos, vis->search_pattern);
+ pos = text_search_forward(vis->win->text->data, pos, vis->search_pattern);
free(word);
return pos;
}
@@ -738,58 +738,59 @@ static size_t search_word_backward(const Arg *arg) {
size_t pos = window_cursor_get(vis->win->win);
char *word = get_word_under_cursor();
if (word && !text_regex_compile(vis->search_pattern, word, REG_EXTENDED))
- pos = text_search_backward(vis->win->text, pos, vis->search_pattern);
+ pos = text_search_backward(vis->win->text->data, pos, vis->search_pattern);
free(word);
return pos;
}
static size_t search_forward(const Arg *arg) {
size_t pos = window_cursor_get(vis->win->win);
- return text_search_forward(vis->win->text, pos, vis->search_pattern);
+ return text_search_forward(vis->win->text->data, pos, vis->search_pattern);
}
static size_t search_backward(const Arg *arg) {
size_t pos = window_cursor_get(vis->win->win);
- return text_search_backward(vis->win->text, pos, vis->search_pattern);
+ return text_search_backward(vis->win->text->data, pos, vis->search_pattern);
}
static void mark_set(const Arg *arg) {
- text_mark_intern_set(vis->win->text, arg->i, window_cursor_get(vis->win->win));
+ size_t pos = window_cursor_get(vis->win->win);
+ vis->win->text->marks[arg->i] = text_mark_set(vis->win->text->data, pos);
}
static size_t mark_goto(const Arg *arg) {
- return text_mark_intern_get(vis->win->text, action.mark);
+ return text_mark_get(vis->win->text->data, vis->win->text->marks[action.mark]);
}
static size_t mark_line_goto(const Arg *arg) {
- return text_line_start(vis->win->text, mark_goto(arg));
+ return text_line_start(vis->win->text->data, mark_goto(arg));
}
static size_t to(const Arg *arg) {
- return text_find_char_next(vis->win->text, window_cursor_get(vis->win->win) + 1,
+ return text_find_char_next(vis->win->text->data, window_cursor_get(vis->win->win) + 1,
action.key.str, strlen(action.key.str));
}
static size_t till(const Arg *arg) {
- return text_char_prev(vis->win->text, to(arg));
+ return text_char_prev(vis->win->text->data, to(arg));
}
static size_t to_left(const Arg *arg) {
- return text_find_char_prev(vis->win->text, window_cursor_get(vis->win->win) - 1,
+ return text_find_char_prev(vis->win->text->data, window_cursor_get(vis->win->win) - 1,
action.key.str, strlen(action.key.str));
}
static size_t till_left(const Arg *arg) {
- return text_char_next(vis->win->text, to_left(arg));
+ return text_char_next(vis->win->text->data, to_left(arg));
}
static size_t line(const Arg *arg) {
- return text_pos_by_lineno(vis->win->text, action.count);
+ return text_pos_by_lineno(vis->win->text->data, action.count);
}
static size_t column(const Arg *arg) {
size_t pos = window_cursor_get(vis->win->win);
- return text_line_offset(vis->win->text, pos, action.count);
+ return text_line_offset(vis->win->text->data, pos, action.count);
}
static size_t window_lines_top(const Arg *arg) {
@@ -881,7 +882,7 @@ static void replace(const Arg *arg) {
buffer_put(&buffer_repeat, k.str, strlen(k.str));
editor_delete_key(vis);
editor_insert_key(vis, k.str, strlen(k.str));
- text_snapshot(vis->win->text);
+ text_snapshot(vis->win->text->data);
window_cursor_to(vis->win->win, pos);
}
@@ -969,10 +970,10 @@ static void selection_end(const Arg *arg) {
size_t pos = window_cursor_get(vis->win->win);
Filerange sel = window_selection_get(vis->win->win);
if (pos == sel.start) {
- pos = text_char_prev(vis->win->text, sel.end);
+ pos = text_char_prev(vis->win->text->data, sel.end);
} else {
pos = sel.start;
- sel.start = text_char_prev(vis->win->text, sel.end);
+ sel.start = text_char_prev(vis->win->text->data, sel.end);
sel.end = pos;
}
window_selection_set(vis->win->win, &sel);
@@ -996,7 +997,7 @@ static void mark_line(const Arg *arg) {
}
static void undo(const Arg *arg) {
- size_t pos = text_undo(vis->win->text);
+ size_t pos = text_undo(vis->win->text->data);
if (pos != EPOS) {
window_cursor_to(vis->win->win, pos);
/* redraw all windows in case some display the same file */
@@ -1005,7 +1006,7 @@ static void undo(const Arg *arg) {
}
static void redo(const Arg *arg) {
- size_t pos = text_redo(vis->win->text);
+ size_t pos = text_redo(vis->win->text->data);
if (pos != EPOS) {
window_cursor_to(vis->win->win, pos);
/* redraw all windows in case some display the same file */
@@ -1166,10 +1167,10 @@ static void copy_indent_from_previous_line(Win *win, Text *text) {
static void insert_newline(const Arg *arg) {
insert(&(const Arg){ .s =
- text_newlines_crnl(vis->win->text) ? "\r\n" : "\n" });
+ text_newlines_crnl(vis->win->text->data) ? "\r\n" : "\n" });
if (vis->autoindent)
- copy_indent_from_previous_line(vis->win->win, vis->win->text);
+ copy_indent_from_previous_line(vis->win->win, vis->win->text->data);
}
static void put(const Arg *arg) {
@@ -1202,7 +1203,7 @@ static void switchmode(const Arg *arg) {
/** action processing: execut the operator / movement / text object */
static void action_do(Action *a) {
- Text *txt = vis->win->text;
+ Text *txt = vis->win->text->data;
Win *win = vis->win->win;
size_t pos = window_cursor_get(win);
int count = MAX(1, a->count);
@@ -1507,13 +1508,9 @@ static bool cmd_open(Filerange *range, enum CmdOpt opt, const char *argv[]) {
}
static bool is_window_closeable(EditorWin *win) {
- if (!text_modified(win->text))
+ if (!text_modified(win->text->data))
return true;
- for (EditorWin *w = vis->windows; w; w = w->next) {
- if (w != win && w->text == win->text)
- return true;
- }
- return false;
+ return win->text->refcount > 1;
}
static void info_unsaved_changes(void) {
@@ -1546,7 +1543,7 @@ static bool cmd_quit(Filerange *range, enum CmdOpt opt, const char *argv[]) {
}
static bool cmd_xit(Filerange *range, enum CmdOpt opt, const char *argv[]) {
- if (text_modified(vis->win->text) && !cmd_write(range, opt, argv)) {
+ if (text_modified(vis->win->text->data) && !cmd_write(range, opt, argv)) {
if (!(opt & CMD_OPT_FORCE))
return false;
}
@@ -1554,14 +1551,14 @@ static bool cmd_xit(Filerange *range, enum CmdOpt opt, const char *argv[]) {
}
static bool cmd_bdelete(Filerange *range, enum CmdOpt opt, const char *argv[]) {
- Text *txt = vis->win->text;
+ Text *txt = vis->win->text->data;
if (text_modified(txt) && !(opt & CMD_OPT_FORCE)) {
info_unsaved_changes();
return false;
}
for (EditorWin *next, *win = vis->windows; win; win = next) {
next = win->next;
- if (win->text == txt)
+ if (win->text->data == txt)
editor_window_close(win);
}
if (!vis->windows)
@@ -1572,7 +1569,7 @@ static bool cmd_bdelete(Filerange *range, enum CmdOpt opt, const char *argv[]) {
static bool cmd_qall(Filerange *range, enum CmdOpt opt, const char *argv[]) {
for (EditorWin *next, *win = vis->windows; win; win = next) {
next = win->next;
- if (!text_modified(vis->win->text) || (opt & CMD_OPT_FORCE))
+ if (!text_modified(vis->win->text->data) || (opt & CMD_OPT_FORCE))
editor_window_close(win);
}
if (!vis->windows)
@@ -1599,7 +1596,7 @@ static bool cmd_read(Filerange *range, enum CmdOpt opt, const char *argv[]) {
if (data == MAP_FAILED)
goto err;
- text_insert(vis->win->text, pos, data, info.st_size);
+ text_insert(vis->win->text->data, pos, data, info.st_size);
pos += info.st_size;
err:
if (fd != -1)
@@ -1659,7 +1656,7 @@ static bool cmd_wq(Filerange *range, enum CmdOpt opt, const char *argv[]) {
}
static bool cmd_write(Filerange *range, enum CmdOpt opt, const char *argv[]) {
- Text *text = vis->win->text;
+ Text *text = vis->win->text->data;
if (!argv[1])
argv[1] = text_filename_get(text);
if (!argv[1]) {
@@ -1683,7 +1680,7 @@ static bool cmd_write(Filerange *range, enum CmdOpt opt, const char *argv[]) {
static bool cmd_saveas(Filerange *range, enum CmdOpt opt, const char *argv[]) {
if (cmd_write(range, opt, argv)) {
- text_filename_set(vis->win->text, argv[1]);
+ text_filename_set(vis->win->text->data, argv[1]);
return true;
}
return false;
@@ -1691,8 +1688,9 @@ static bool cmd_saveas(Filerange *range, enum CmdOpt opt, const char *argv[]) {
static Filepos parse_pos(char **cmd) {
size_t pos = EPOS;
- Text *txt = vis->win->text;
Win *win = vis->win->win;
+ Text *txt = vis->win->text->data;
+ Mark *marks = vis->win->text->marks;
switch (**cmd) {
case '.':
pos = text_line_begin(txt, window_cursor_get(win));
@@ -1705,11 +1703,11 @@ static Filepos parse_pos(char **cmd) {
case '\'':
(*cmd)++;
if ('a' <= **cmd && **cmd <= 'z')
- pos = text_mark_intern_get(txt, **cmd - 'a');
+ pos = text_mark_get(txt, marks[**cmd - 'a']);
else if (**cmd == '<')
- pos = text_mark_intern_get(txt, MARK_SELECTION_START);
+ pos = text_mark_get(txt, marks[MARK_SELECTION_START]);
else if (**cmd == '>')
- pos = text_mark_intern_get(txt, MARK_SELECTION_END);
+ pos = text_mark_get(txt, marks[MARK_SELECTION_END]);
(*cmd)++;
break;
case '/':
@@ -1747,8 +1745,9 @@ static Filepos parse_pos(char **cmd) {
}
static Filerange parse_range(char **cmd) {
- Text *txt = vis->win->text;
+ Text *txt = vis->win->text->data;
Filerange r = text_range_empty();
+ Mark *marks = vis->win->text->marks;
switch (**cmd) {
case '%':
r.start = 0;
@@ -1756,8 +1755,8 @@ static Filerange parse_range(char **cmd) {
(*cmd)++;
break;
case '*':
- r.start = text_mark_intern_get(txt, MARK_SELECTION_START);
- r.end = text_mark_intern_get(txt, MARK_SELECTION_END);
+ r.start = text_mark_get(txt, marks[MARK_SELECTION_START]);
+ r.end = text_mark_get(txt, marks[MARK_SELECTION_END]);
(*cmd)++;
break;
default:
@@ -1791,7 +1790,7 @@ static bool exec_cmdline_command(const char *cmdline) {
free(line);
return false;
}
- range = (Filerange){ .start = 0, .end = text_size(vis->win->text) };
+ range = (Filerange){ .start = 0, .end = text_size(vis->win->text->data) };
}
/* skip leading white space */
while (*name == ' ')
diff --git a/window.c b/window.c
index 888389a..10f7819 100644
--- a/window.c
+++ b/window.c
@@ -115,8 +115,9 @@ Filerange window_selection_get(Win *win) {
if (!text_range_valid(&sel))
return text_range_empty();
sel.end = text_char_next(win->text, sel.end);
- text_mark_intern_set(win->text, MARK_SELECTION_START, sel.start);
- text_mark_intern_set(win->text, MARK_SELECTION_END, sel.end);
+ // TODO
+ //text_mark_intern_set(win->text, MARK_SELECTION_START, sel.start);
+ //text_mark_intern_set(win->text, MARK_SELECTION_END, sel.end);
return sel;
}
@@ -439,7 +440,7 @@ void window_draw(Win *win) {
bool window_resize(Win *win, int width, int height) {
size_t lines_size = height*(sizeof(Line) + width*sizeof(Cell));
if (lines_size > win->lines_size) {
- Line *lines = malloc(lines_size);
+ Line *lines = realloc(win->lines, lines_size);
if (!lines)
return false;
win->lines = lines;