tImplement middle-click pasting - 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 <[email protected]> | |
Date: Sun, 26 Dec 2021 15:37:23 +0100 | |
Implement middle-click pasting | |
Diffstat: | |
M keys_basic.c | 5 ++--- | |
M ledit.1 | 7 +++++++ | |
M view.c | 47 ++++++++++++++++++++---------… | |
M view.h | 3 ++- | |
M window.c | 17 +++++++++++++---- | |
5 files changed, 54 insertions(+), 25 deletions(-) | |
--- | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -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 | |
t@@ -809,6 +809,8 @@ selects text, which is always copied into the X11 primary … | |
.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 | |
t@@ -868,6 +870,11 @@ The configuration options are described in the file itsel… | |
.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 | |
t@@ -131,6 +131,7 @@ view_create(ledit_buffer *buffer, ledit_theme *theme, ledi… | |
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; | |
t@@ -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 m… | |
+ 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 | |
t@@ -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 … | |
+ char button2_pressed; /* whether button 2 (middle button) is press… | |
char sel_valid; /* whether there is currently a valid select… | |
char redraw; /* whether something has changed so the view… | |
}; | |
diff --git a/window.c b/window.c | |
t@@ -1031,16 +1031,16 @@ window_register_motion(ledit_window *window, XEvent *e… | |
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; | |
t@@ -1055,6 +1055,10 @@ window_button_press(ledit_window *window, XEvent *event… | |
window->redraw = 1; | |
} | |
break; | |
+ case Button2: | |
+ if (x < window->text_w && y < window->text_h && window… | |
+ window->button_callback(window->button_cb_data… | |
+ break; | |
case Button4: | |
case Button5: | |
window->scroll_offset += scroll_num * window->theme->s… | |
t@@ -1071,11 +1075,16 @@ window_button_press(ledit_window *window, XEvent *even… | |
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->butt… | |
+ window->button_callback(window->button_cb_data, event); | |
} | |
} | |