summaryrefslogtreecommitdiff
path: root/examples/dte/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/dte/window.c')
-rw-r--r--examples/dte/window.c507
1 files changed, 0 insertions, 507 deletions
diff --git a/examples/dte/window.c b/examples/dte/window.c
deleted file mode 100644
index 6b0c5cb..0000000
--- a/examples/dte/window.c
+++ /dev/null
@@ -1,507 +0,0 @@
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "window.h"
-#include "editor.h"
-#include "error.h"
-#include "file-history.h"
-#include "load-save.h"
-#include "lock.h"
-#include "move.h"
-#include "util/path.h"
-#include "util/str-util.h"
-#include "util/strtonum.h"
-#include "util/xmalloc.h"
-
-Window *new_window(EditorState *e)
-{
- Window *window = xnew0(Window, 1);
- window->editor = e;
- return window;
-}
-
-View *window_add_buffer(Window *window, Buffer *buffer)
-{
- // We rely on this being 0, for implicit initialization of
- // View::selection and View::select_mode
- static_assert(SELECT_NONE == 0);
-
- View *view = xnew(View, 1);
- *view = (View) {
- .buffer = buffer,
- .window = window,
- .cursor = {
- .blk = BLOCK(buffer->blocks.next),
- .head = &buffer->blocks,
- }
- };
-
- ptr_array_append(&buffer->views, view);
- ptr_array_append(&window->views, view);
- window->update_tabbar = true;
- return view;
-}
-
-View *window_open_empty_buffer(Window *window)
-{
- EditorState *e = window->editor;
- return window_add_buffer(window, open_empty_buffer(&e->buffers, &e->options));
-}
-
-View *window_open_buffer (
- Window *window,
- const char *filename,
- bool must_exist,
- const Encoding *encoding
-) {
- if (unlikely(filename[0] == '\0')) {
- error_msg("Empty filename not allowed");
- return NULL;
- }
-
- EditorState *e = window->editor;
- bool dir_missing = false;
- char *absolute = path_absolute(filename);
- if (absolute) {
- // Already open?
- Buffer *buffer = find_buffer(&e->buffers, absolute);
- if (buffer) {
- if (!streq(absolute, buffer->abs_filename)) {
- const char *bufname = buffer_filename(buffer);
- char *s = short_filename(absolute, &e->home_dir);
- info_msg("%s and %s are the same file", s, bufname);
- free(s);
- }
- free(absolute);
- return window_get_view(window, buffer);
- }
- } else {
- // Let load_buffer() create error message
- dir_missing = (errno == ENOENT);
- }
-
- /*
- /proc/$PID/fd/ contains symbolic links to files that have been opened
- by process $PID. Some of the files may have been deleted but can still
- be opened using the symbolic link but not by using the absolute path.
-
- # create file
- mkdir /tmp/x
- echo foo > /tmp/x/file
-
- # in another shell: keep the file open
- tail -f /tmp/x/file
-
- # make the absolute path unavailable
- rm /tmp/x/file
- rmdir /tmp/x
-
- # this should still succeed
- dte /proc/$(pidof tail)/fd/3
- */
-
- Buffer *buffer = buffer_new(&e->buffers, &e->options, encoding);
- if (!load_buffer(buffer, filename, &e->options, must_exist)) {
- remove_and_free_buffer(&e->buffers, buffer);
- free(absolute);
- return NULL;
- }
- if (unlikely(buffer->file.mode == 0 && dir_missing)) {
- // New file in non-existing directory; this is usually a mistake
- error_msg("Error opening %s: Directory does not exist", filename);
- remove_and_free_buffer(&e->buffers, buffer);
- free(absolute);
- return NULL;
- }
-
- if (absolute) {
- buffer->abs_filename = absolute;
- } else {
- // FIXME: obviously wrong
- buffer->abs_filename = xstrdup(filename);
- }
- update_short_filename(buffer, &e->home_dir);
-
- if (e->options.lock_files) {
- if (!lock_file(buffer->abs_filename)) {
- buffer->readonly = true;
- } else {
- buffer->locked = true;
- }
- }
-
- if (buffer->file.mode != 0 && !buffer->readonly && access(filename, W_OK)) {
- error_msg("No write permission to %s, marking read-only", filename);
- buffer->readonly = true;
- }
-
- return window_add_buffer(window, buffer);
-}
-
-View *window_get_view(Window *window, Buffer *buffer)
-{
- View *view = window_find_view(window, buffer);
- if (!view) {
- // Open the buffer in other window to this window
- view = window_add_buffer(window, buffer);
- view->cursor = ((View*)buffer->views.ptrs[0])->cursor;
- }
- return view;
-}
-
-View *window_find_view(Window *window, Buffer *buffer)
-{
- for (size_t i = 0, n = buffer->views.count; i < n; i++) {
- View *view = buffer->views.ptrs[i];
- if (view->window == window) {
- return view;
- }
- }
- // Buffer isn't open in this window
- return NULL;
-}
-
-View *window_find_unclosable_view(Window *window)
-{
- // Check active view first
- if (window->view && !view_can_close(window->view)) {
- return window->view;
- }
- for (size_t i = 0, n = window->views.count; i < n; i++) {
- View *view = window->views.ptrs[i];
- if (!view_can_close(view)) {
- return view;
- }
- }
- return NULL;
-}
-
-static void window_remove_views(Window *window)
-{
- while (window->views.count > 0) {
- View *view = window->views.ptrs[window->views.count - 1];
- remove_view(view);
- }
-}
-
-// NOTE: window->frame isn't removed
-void window_free(Window *window)
-{
- window_remove_views(window);
- free(window->views.ptrs);
- window->frame = NULL;
- free(window);
-}
-
-// Remove view from view->window and view->buffer->views and free it
-size_t remove_view(View *view)
-{
- Window *window = view->window;
- EditorState *e = window->editor;
- if (view == window->prev_view) {
- window->prev_view = NULL;
- }
- if (view == e->view) {
- e->view = NULL;
- e->buffer = NULL;
- }
-
- size_t idx = ptr_array_idx(&window->views, view);
- BUG_ON(idx >= window->views.count);
- ptr_array_remove_idx(&window->views, idx);
- window->update_tabbar = true;
-
- Buffer *buffer = view->buffer;
- ptr_array_remove(&buffer->views, view);
- if (buffer->views.count == 0) {
- if (buffer->options.file_history && buffer->abs_filename) {
- FileHistory *hist = &e->file_history;
- file_history_add(hist, view->cy + 1, view->cx_char + 1, buffer->abs_filename);
- }
- remove_and_free_buffer(&e->buffers, buffer);
- }
-
- free(view);
- return idx;
-}
-
-void window_close_current_view(Window *window)
-{
- size_t idx = remove_view(window->view);
- if (window->prev_view) {
- window->view = window->prev_view;
- window->prev_view = NULL;
- return;
- }
- if (window->views.count == 0) {
- window_open_empty_buffer(window);
- }
- if (window->views.count == idx) {
- idx--;
- }
- window->view = window->views.ptrs[idx];
-}
-
-static void restore_cursor_from_history(const FileHistory *hist, View *view)
-{
- unsigned long row, col;
- if (file_history_find(hist, view->buffer->abs_filename, &row, &col)) {
- move_to_filepos(view, row, col);
- }
-}
-
-void set_view(View *view)
-{
- EditorState *e = view->window->editor;
- if (e->view == view) {
- return;
- }
-
- // Forget previous view when changing view using any other command but open
- if (e->window) {
- e->window->prev_view = NULL;
- }
-
- e->view = view;
- e->buffer = view->buffer;
- e->window = view->window;
- e->window->view = view;
-
- if (!view->buffer->setup) {
- buffer_setup(e, view->buffer);
- if (view->buffer->options.file_history && view->buffer->abs_filename) {
- restore_cursor_from_history(&e->file_history, view);
- }
- }
-
- // view.cursor can be invalid if same buffer was modified from another view
- if (view->restore_cursor) {
- view->cursor.blk = BLOCK(view->buffer->blocks.next);
- block_iter_goto_offset(&view->cursor, view->saved_cursor_offset);
- view->restore_cursor = false;
- view->saved_cursor_offset = 0;
- }
-
- // Save cursor states of views sharing same buffer
- for (size_t i = 0, n = view->buffer->views.count; i < n; i++) {
- View *other = view->buffer->views.ptrs[i];
- if (other != view) {
- other->saved_cursor_offset = block_iter_get_offset(&other->cursor);
- other->restore_cursor = true;
- }
- }
-}
-
-View *window_open_new_file(Window *window)
-{
- View *prev = window->view;
- View *view = window_open_empty_buffer(window);
- set_view(view);
- window->prev_view = prev;
- return view;
-}
-
-static bool buffer_is_empty_and_untouched(const Buffer *b)
-{
- return !b->abs_filename && b->change_head.nr_prev == 0 && !b->display_filename;
-}
-
-// If window contains only one untouched buffer it'll be closed after
-// opening another file. This is done because closing the last buffer
-// causes an empty buffer to be opened (windows must contain at least
-// one buffer).
-static bool is_useless_empty_view(const View *v)
-{
- return v && v->window->views.count == 1 && buffer_is_empty_and_untouched(v->buffer);
-}
-
-View *window_open_file(Window *window, const char *filename, const Encoding *encoding)
-{
- View *prev = window->view;
- bool useless = is_useless_empty_view(prev);
- View *view = window_open_buffer(window, filename, false, encoding);
- if (view) {
- set_view(view);
- if (useless) {
- remove_view(prev);
- } else {
- window->prev_view = prev;
- }
- }
- return view;
-}
-
-// Open multiple files in window and return the first opened View
-View *window_open_files(Window *window, char **filenames, const Encoding *encoding)
-{
- View *empty = window->view;
- bool useless = is_useless_empty_view(empty);
- View *first = NULL;
-
- for (size_t i = 0; filenames[i]; i++) {
- View *view = window_open_buffer(window, filenames[i], false, encoding);
- if (view && !first) {
- set_view(view);
- first = view;
- }
- }
-
- if (useless && window->view != empty) {
- remove_view(empty);
- }
-
- return first;
-}
-
-void mark_buffer_tabbars_changed(Buffer *buffer)
-{
- for (size_t i = 0, n = buffer->views.count; i < n; i++) {
- View *view = buffer->views.ptrs[i];
- view->window->update_tabbar = true;
- }
-}
-
-static int line_numbers_width(const Window *window, const GlobalOptions *options)
-{
- if (!options->show_line_numbers || !window->view) {
- return 0;
- }
- size_t width = size_str_width(window->view->buffer->nl) + 1;
- return MAX(width, LINE_NUMBERS_MIN_WIDTH);
-}
-
-static int edit_x_offset(const Window *window, const GlobalOptions *options)
-{
- return line_numbers_width(window, options);
-}
-
-static int edit_y_offset(const GlobalOptions *options)
-{
- return options->tab_bar ? 1 : 0;
-}
-
-static void set_edit_size(Window *window, const GlobalOptions *options)
-{
- int xo = edit_x_offset(window, options);
- int yo = edit_y_offset(options);
-
- window->edit_w = window->w - xo;
- window->edit_h = window->h - yo - 1; // statusline
- window->edit_x = window->x + xo;
-}
-
-void calculate_line_numbers(Window *window)
-{
- const GlobalOptions *options = &window->editor->options;
- int w = line_numbers_width(window, options);
- if (w != window->line_numbers.width) {
- window->line_numbers.width = w;
- window->line_numbers.first = 0;
- window->line_numbers.last = 0;
- mark_all_lines_changed(window->view->buffer);
- }
- set_edit_size(window, options);
-}
-
-void set_window_coordinates(Window *window, int x, int y)
-{
- const GlobalOptions *options = &window->editor->options;
- window->x = x;
- window->y = y;
- window->edit_x = x + edit_x_offset(window, options);
- window->edit_y = y + edit_y_offset(options);
-}
-
-void set_window_size(Window *window, int w, int h)
-{
- window->w = w;
- window->h = h;
- calculate_line_numbers(window);
-}
-
-int window_get_scroll_margin(const Window *window, unsigned int scroll_margin)
-{
- int max = (window->edit_h - 1) / 2;
- BUG_ON(max < 0);
- return MIN(max, scroll_margin);
-}
-
-void frame_for_each_window(const Frame *frame, void (*func)(Window*, void*), void *data)
-{
- if (frame->window) {
- func(frame->window, data);
- return;
- }
- for (size_t i = 0, n = frame->frames.count; i < n; i++) {
- frame_for_each_window(frame->frames.ptrs[i], func, data);
- }
-}
-
-typedef struct {
- const Window *const target; // Window to search for (set at init.)
- Window *first; // Window passed in first callback invocation
- Window *last; // Window passed in last callback invocation
- Window *prev; // Window immediately before target (if any)
- Window *next; // Window immediately after target (if any)
- bool found; // Set to true when target is found
-} WindowCallbackData;
-
-static void find_prev_and_next(Window *window, void *ud)
-{
- WindowCallbackData *data = ud;
- data->last = window;
- if (data->found) {
- if (!data->next) {
- data->next = window;
- }
- return;
- }
- if (!data->first) {
- data->first = window;
- }
- if (window == data->target) {
- data->found = true;
- return;
- }
- data->prev = window;
-}
-
-Window *prev_window(Window *window)
-{
- WindowCallbackData data = {.target = window};
- frame_for_each_window(window->editor->root_frame, find_prev_and_next, &data);
- BUG_ON(!data.found);
- return data.prev ? data.prev : data.last;
-}
-
-Window *next_window(Window *window)
-{
- WindowCallbackData data = {.target = window};
- frame_for_each_window(window->editor->root_frame, find_prev_and_next, &data);
- BUG_ON(!data.found);
- return data.next ? data.next : data.first;
-}
-
-void window_close(Window *window)
-{
- EditorState *e = window->editor;
- if (!window->frame->parent) {
- // Don't close last window
- window_remove_views(window);
- set_view(window_open_empty_buffer(window));
- return;
- }
-
- WindowCallbackData data = {.target = window};
- frame_for_each_window(e->root_frame, find_prev_and_next, &data);
- BUG_ON(!data.found);
- Window *next_or_prev = data.next ? data.next : data.prev;
- BUG_ON(!next_or_prev);
-
- remove_frame(e, window->frame);
- e->window = NULL;
- set_view(next_or_prev->view);
-
- mark_everything_changed(e);
- debug_frame(e->root_frame);
-}