ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit bfdeaca153c57726fa2bb87a0612fe7e930e67cc
parent dd363e6519647cb4f88d1cb289647a0d7f5f80c3
Author: lumidify <nobody@lumidify.org>
Date:   Sun, 26 Dec 2021 15:37:23 +0100

Implement middle-click pasting

Diffstat:
Mkeys_basic.c | 5++---
Mledit.1 | 7+++++++
Mview.c | 47++++++++++++++++++++++++++++++-----------------
Mview.h | 3++-
Mwindow.c | 17+++++++++++++----
5 files changed, 54 insertions(+), 25 deletions(-)

diff --git a/keys_basic.c b/keys_basic.c @@ -1642,11 +1642,10 @@ enter_insert(ledit_view *view, char *text, size_t len) { (void)text; (void)len; CHECK_VIEW_LOCKED(view); - if (view->mode == NORMAL) { - view_wipe_line_cursor_attrs(view, view->cur_line); - } else if (view->mode == VISUAL) { + if (view->mode == VISUAL) { view_wipe_selection(view); } + view_wipe_line_cursor_attrs(view, view->cur_line); view_set_mode(view, INSERT); clear_key_stack(); return (struct action){ACTION_NONE, NULL}; diff --git a/ledit.1 b/ledit.1 @@ -809,6 +809,8 @@ selects text, which is always copied into the X11 primary selection. .Pp Note that text selection currently does not work in the line editor because the author is too lazy to implement that. +.Pp +Middle click in insert mode pastes the current X11 primary clipboard. .Sh CONFIGURATION .Nm currently has to be configured entirely by changing header files and @@ -868,6 +870,11 @@ The configuration options are described in the file itself. .Pp This short explanation of the configuration is not very good currently. That will hopefully be changed in the future. +.Pp +Note that there are a few actions that are currently hard-coded and cannot +be configured. +This includes all mouse actions and using escape to cancel a multi-key +command. .Sh MISCELLANEOUS .Nm includes a fair number of sanity checks (asserts) to make sure some illegal diff --git a/view.c b/view.c @@ -131,6 +131,7 @@ view_create(ledit_buffer *buffer, ledit_theme *theme, ledit_mode mode, size_t li view->display_offset = 0; view->sel.line1 = view->sel.byte1 = 0; view->sel.line2 = view->sel.byte2 = 0; + view->button2_pressed = 0; view->selecting = 0; view->sel_valid = 0; view->redraw = 1; @@ -1765,25 +1766,37 @@ view_button_handler(void *data, XEvent *event) { int snap; switch (event->type) { case ButtonPress: - x = event->xbutton.x; - y = event->xbutton.y; - snap = view->mode == NORMAL ? 0 : 1; - view_xy_to_line_byte(view, x, y, snap, &l, &b); - view->selecting = 1; - view_wipe_line_cursor_attrs(view, view->cur_line); - view->cur_line = l; - view->cur_index = b; - /* don't set selection yet because the mouse may not be - dragged, so we don't want to switch to visual (this - allows setting just the cursor position in normal mode - without always switching to visual) */ - if (view->mode == NORMAL) - view_set_line_cursor_attrs(view, l, b); - else if (view->mode == VISUAL) - view_set_selection(view, l, b, l, b); + if (event->xbutton.button == Button1) { + x = event->xbutton.x; + y = event->xbutton.y; + snap = view->mode == NORMAL ? 0 : 1; + view_xy_to_line_byte(view, x, y, snap, &l, &b); + view->selecting = 1; + view_wipe_line_cursor_attrs(view, view->cur_line); + view->cur_line = l; + view->cur_index = b; + /* don't set selection yet because the mouse may not be + dragged, so we don't want to switch to visual (this + allows setting just the cursor position in normal mode + without always switching to visual) */ + if (view->mode == NORMAL) + view_set_line_cursor_attrs(view, l, b); + else if (view->mode == VISUAL) + view_set_selection(view, l, b, l, b); + } else if (event->xbutton.button == Button2) { + view->button2_pressed = 1; + } break; case ButtonRelease: - view->selecting = 0; + /* FIXME: view->button2_pressed should be set to 0 even when + the event does not occur inside the text area */ + if (event->xbutton.button == Button1) { + view->selecting = 0; + } else if (event->xbutton.button == Button2) { + if (view->button2_pressed && view->mode == INSERT) + view_paste_primary(view); + view->button2_pressed = 0; + } break; case MotionNotify: x = event->xmotion.x; diff --git a/view.h b/view.h @@ -76,8 +76,9 @@ struct ledit_view { long total_height; /* total pixel height of all lines */ long display_offset; /* current pixel offset of viewport */ ledit_range sel; /* current selection */ - ledit_mode mode; /* current mode of this view */ + ledit_mode mode; /* current mode of this view */ char selecting; /* whether user is currently selecting text with mouse */ + char button2_pressed; /* whether button 2 (middle button) is pressed */ char sel_valid; /* whether there is currently a valid selection */ char redraw; /* whether something has changed so the view needs to be redrawn */ }; diff --git a/window.c b/window.c @@ -1031,16 +1031,16 @@ window_register_motion(ledit_window *window, XEvent *event) { window->last_motion_valid = 1; } +/* FIXME: make button handling more consistent */ /* FIXME: improve set_scroll_pos; make it a bit clearer */ void window_button_press(ledit_window *window, XEvent *event, int scroll_num) { - int x, y; + int x = event->xbutton.x; + int y = event->xbutton.y; double scroll_h, scroll_y; switch (event->xbutton.button) { case Button1: get_scroll_pos_height(window, &scroll_y, &scroll_h); - x = event->xbutton.x; - y = event->xbutton.y; if (x >= window->text_w) { window->scroll_dragging = 1; window->scroll_grab_handle = y; @@ -1055,6 +1055,10 @@ window_button_press(ledit_window *window, XEvent *event, int scroll_num) { window->redraw = 1; } break; + case Button2: + if (x < window->text_w && y < window->text_h && window->button_callback) + window->button_callback(window->button_cb_data, event); + break; case Button4: case Button5: window->scroll_offset += scroll_num * window->theme->scrollbar_step; @@ -1071,11 +1075,16 @@ window_button_press(ledit_window *window, XEvent *event, int scroll_num) { void window_button_release(ledit_window *window, XEvent *event) { + int x = event->xbutton.x; + int y = event->xbutton.y; + int in_text = x < window->text_w && y < window->text_h; if (event->xbutton.button == Button1) { window->scroll_dragging = 0; - if (window->button_callback) + if (in_text && window->button_callback) window->button_callback(window->button_cb_data, event); window->redraw = 1; + } else if (event->xbutton.button == Button2 && in_text && window->button_callback) { + window->button_callback(window->button_cb_data, event); } }