diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-05-08 16:22:08 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-05-13 09:33:40 -0300 |
commit | 9f25a4153ca17fb5bbba47688817fef984c64b14 (patch) | |
tree | 5b3fd70ae6520f7b4e93806b782a4f5b7308cb33 /src/api/buffer.c | |
parent | 7b04674174c00b85fb75579bbc49524f7ba74afa (diff) | |
download | rneovim-9f25a4153ca17fb5bbba47688817fef984c64b14.tar.gz rneovim-9f25a4153ca17fb5bbba47688817fef984c64b14.tar.bz2 rneovim-9f25a4153ca17fb5bbba47688817fef984c64b14.zip |
API: Implement buffer_{get,set}_line
Diffstat (limited to 'src/api/buffer.c')
-rw-r--r-- | src/api/buffer.c | 210 |
1 files changed, 200 insertions, 10 deletions
diff --git a/src/api/buffer.c b/src/api/buffer.c index 743d8c4729..554272955e 100644 --- a/src/api/buffer.c +++ b/src/api/buffer.c @@ -2,7 +2,40 @@ #include <stdlib.h> #include "api/buffer.h" +#include "api/helpers.h" #include "api/defs.h" +#include "../vim.h" +#include "../buffer.h" +#include "memline.h" +#include "memory.h" +#include "misc1.h" +#include "misc2.h" +#include "move.h" +#include "../window.h" +#include "undo.h" + +static buf_T *find_buffer(Buffer buffer, Error *err); + +// Find a window that contains "buf" and switch to it. +// If there is no such window, use the current window and change "curbuf". +// Caller must initialize save_curbuf to NULL. +// restore_win_for_buf() MUST be called later! +static void switch_to_win_for_buf(buf_T *buf, + win_T **save_curwinp, + tabpage_T **save_curtabp, + buf_T **save_curbufp); + +static void restore_win_for_buf(win_T *save_curwin, + tabpage_T *save_curtab, + buf_T *save_curbuf); + +// Check if deleting lines made the cursor position invalid. +// Changed the lines from "lo" to "hi" and added "extra" lines (negative if +// deleted). +static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra); + +// Normalizes 0-based indexes to buffer line numbers +static int64_t normalize_index(buf_T *buf, int64_t index); int64_t buffer_get_length(Buffer buffer, Error *err) { @@ -11,27 +44,116 @@ int64_t buffer_get_length(Buffer buffer, Error *err) String buffer_get_line(Buffer buffer, int64_t index, Error *err) { - abort(); + String rv; + buf_T *buf = find_buffer(buffer, err); + + if (!buf) { + return rv; + } + + index = normalize_index(buf, index); + char *line = (char *)ml_get_buf(buf, index, false); + rv.size = strlen(line); + rv.data = xmalloc(rv.size); + memcpy(rv.data, line, rv.size); + return rv; } -void buffer_set_line(Buffer buffer, int64_t index, String line, Error *err) +void buffer_set_line(Buffer buffer, int64_t index, Object line, Error *err) { - abort(); + buf_T *buf = find_buffer(buffer, err); + + if (!buf) { + return; + } + + if (line.type != kObjectTypeNil && line.type != kObjectTypeString) { + char msg[] = "Invalid line"; + strncpy(err->msg, msg, sizeof(err->msg)); + err->set = true; + return; + } + + index = normalize_index(buf, index); + buf_T *save_curbuf = NULL; + win_T *save_curwin = NULL; + tabpage_T *save_curtab = NULL; + try_start(); + switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); + + if (line.type == kObjectTypeNil) { + // Delete the line + + if (u_savedel(index, 1L) == FAIL) { + // Failed to save undo + char msg[] = "Cannot save undo information"; + strncpy(err->msg, msg, sizeof(err->msg)); + err->set = true; + } else if (ml_delete(index, FALSE) == FAIL) { + // Failed to delete + char msg[] = "Cannot delete the line"; + strncpy(err->msg, msg, sizeof(err->msg)); + err->set = true; + } else { + restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + // Success + if (buf == curbuf) { + // fix the cursor if it's the current buffer + fix_cursor(index, index + 1, -1); + } + + if (save_curbuf == NULL) { + // Only adjust marks if we managed to switch to a window that + // holds the buffer, otherwise line numbers will be invalid. + deleted_lines_mark(index, 1L); + } + } + + } else if (line.type == kObjectTypeString) { + // Replace line + char *string = xmalloc(line.data.string.size + 1); + memcpy(string, line.data.string.data, line.data.string.size); + string[line.data.string.size] = NUL; + + if (u_savesub(index) == FAIL) { + // Failed to save undo + char msg[] = "Cannot save undo information"; + strncpy(err->msg, msg, sizeof(err->msg)); + err->set = true; + } else if (ml_replace(index, (char_u *)string, FALSE) == FAIL) { + // Failed to replace + char msg[] = "Cannot replace line"; + strncpy(err->msg, msg, sizeof(err->msg)); + err->set = true; + free(string); + } else { + // Success + changed_bytes(index, 0); + restore_win_for_buf(save_curwin, save_curtab, save_curbuf); + + // Check that the cursor is not beyond the end of the line now. + if (buf == curbuf) { + check_cursor_col(); + } + } + } + + try_end(err); } StringArray buffer_get_slice(Buffer buffer, - int64_t start, - int64_t end, - Error *err) + int64_t start, + int64_t end, + Error *err) { abort(); } void buffer_set_slice(Buffer buffer, - int64_t start, - int64_t end, - StringArray lines, - Error *err) + int64_t start, + int64_t end, + StringArray lines, + Error *err) { abort(); } @@ -85,3 +207,71 @@ Position buffer_mark(Buffer buffer, String name, Error *err) { abort(); } + +static buf_T *find_buffer(Buffer buffer, Error *err) +{ + buf_T *buf = buflist_findnr(buffer); + + if (buf == NULL) { + char msg[] = "Invalid buffer id"; + strncpy(err->msg, msg, sizeof(err->msg)); + err->set = true; + } + + return buf; +} + +static void switch_to_win_for_buf(buf_T *buf, + win_T **save_curwinp, + tabpage_T **save_curtabp, + buf_T **save_curbufp) +{ + win_T *wp; + tabpage_T *tp; + + if (find_win_for_buf(buf, &wp, &tp) == FAIL + || switch_win(save_curwinp, save_curtabp, wp, tp, TRUE) == FAIL) + switch_buffer(save_curbufp, buf); +} + +static void restore_win_for_buf(win_T *save_curwin, + tabpage_T *save_curtab, + buf_T *save_curbuf) +{ + if (save_curbuf == NULL) { + restore_win(save_curwin, save_curtab, TRUE); + } else { + restore_buffer(save_curbuf); + } +} + +static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra) +{ + if (curwin->w_cursor.lnum >= lo) { + // Adjust the cursor position if it's in/after the changed + // lines. + if (curwin->w_cursor.lnum >= hi) { + curwin->w_cursor.lnum += extra; + check_cursor_col(); + } + else if (extra < 0) { + curwin->w_cursor.lnum = lo; + check_cursor(); + } else { + check_cursor_col(); + } + changed_cline_bef_curs(); + } + invalidate_botline(); +} + +static int64_t normalize_index(buf_T *buf, int64_t index) +{ + // Fix if < 0 + index = index < 0 ? buf->b_ml.ml_line_count + index : index; + // Convert the index to a vim line number + index++; + // Fix if > line_count + index = index > buf->b_ml.ml_line_count ? buf->b_ml.ml_line_count : index; + return index; +} |