esc

Externally Scriptable Editor

git clone git://mccd.space/esc

commit c15b85a79ab0b8082f821448aac1dbfddf93a9c8
parent 78e6111b107e649a141e18a93994c22961b5cf8a
Author: Marc Coquand <marc@coquand.email>
Date:   Tue, 24 Feb 2026 16:10:08 +0100

Add clipboard support

Diffstat:
Mmain.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+), 0 deletions(-)
diff --git a/main.c b/main.c
@@ -7,6 +7,7 @@
 #include <SDL3/SDL_keycode.h>
 #include <SDL3/SDL_log.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_clipboard.h>
 #include <SDL3/SDL_mouse.h>
 #include <SDL3_ttf/SDL_ttf.h>
 #include <stdbool.h>
@@ -97,6 +98,40 @@ void handle_events(Editor *ed, SDL_Renderer *renderer, float *scroll_x,
 						break;
 					editor_select_all(ed);
 					break;
+				case SDLK_C:
+					if (!(event.key.mod & SDL_KMOD_ALT))
+						break;
+					{
+						char *sel = editor_get_selection(ed);
+						if (sel) {
+							SDL_SetClipboardText(sel);
+							free(sel);
+						}
+					}
+					break;
+				case SDLK_X:
+					if (!(event.key.mod & SDL_KMOD_ALT))
+						break;
+					{
+						char *sel = editor_get_selection(ed);
+						if (sel) {
+							SDL_SetClipboardText(sel);
+							free(sel);
+							editor_insert_text(ed, "", true);
+						}
+					}
+					break;
+				case SDLK_V:
+					if (!(event.key.mod & SDL_KMOD_ALT))
+						break;
+					if (SDL_HasClipboardText()) {
+						char *text = SDL_GetClipboardText();
+						if (text && *text) {
+							editor_insert_text(ed, text, true);
+						}
+						SDL_free(text);
+					}
+					break;
 				case SDLK_B:
 					if (!(event.key.mod & SDL_KMOD_ALT) &&
 					    !event.key.repeat)
@@ -190,6 +225,24 @@ void handle_events(Editor *ed, SDL_Renderer *renderer, float *scroll_x,
 							    sys_cmd, NULL);
 							free(selection);
 						}
+					} else {
+						/* paste from primary selection */
+						if (SDL_HasPrimarySelectionText()) {
+							char *text = SDL_GetPrimarySelectionText();
+							if (text && *text) {
+								float mx, my;
+								SDL_RenderCoordinatesFromWindow(
+								    renderer,
+								    event.button.x,
+								    event.button.y, &mx, &my);
+								editor_set_cursor_from_coords(
+								    ed, mx, my,
+								    *scroll_x, *scroll_y);
+								ed->selection_anchor = ed->cursor_idx;
+								editor_insert_text(ed, text, false);
+							}
+							SDL_free(text);
+						}
 					}
 				}
 				break;
@@ -217,6 +270,15 @@ void handle_events(Editor *ed, SDL_Renderer *renderer, float *scroll_x,
 				break;
 			}
 		} while (SDL_PollEvent(&event));
+
+		/* Auto-sync primary selection for Wayland */
+		if (editor_has_selection(ed)) {
+			char *sel = editor_get_selection(ed);
+			if (sel) {
+				SDL_SetPrimarySelectionText(sel);
+				free(sel);
+			}
+		}
 	}
 }