Multicursor clipboard

This commit is contained in:
Krzosa Karol
2024-07-01 15:13:23 +02:00
parent 1a420e2f22
commit ce13f83d46
3 changed files with 80 additions and 39 deletions

View File

@@ -0,0 +1,62 @@
String SavedClipboardString;
Array<String> SavedClipboardCursors;
void CopyToClipboard(Window *window) {
Allocator sys_allocator = GetSystemAllocator();
SavedClipboardCursors.allocator = sys_allocator;
if (SavedClipboardCursors.data) {
For(SavedClipboardCursors) Dealloc(sys_allocator, &it.data);
SavedClipboardCursors.clear();
}
if (SavedClipboardString.data) {
Dealloc(sys_allocator, &SavedClipboardString.data);
SavedClipboardString = {};
}
// First, if there is no selection - select the entire line
For(window->cursors) {
if (GetRangeSize(it.range) == 0) {
Line line = FindLine(window->buffer, it.range.min);
it.range = line.range;
}
}
For(window->cursors) {
String string = GetString(window->buffer, it.range);
String copy = Copy(sys_allocator, string);
SavedClipboardCursors.add(copy);
}
// @todo: maybe only add new line if there is no new line at the end, experiment with it
SavedClipboardString = Merge(sys_allocator, SavedClipboardCursors, "\n");
SetClipboardText(SavedClipboardString.data);
}
void PasteFromClipboard(Window *window) {
Scratch scratch;
const char *text = GetClipboardText();
String string = text;
// Regular paste
if (string != SavedClipboardString || SavedClipboardCursors.len != window->cursors.len) {
BeforeEdit(window);
Array<Edit> edits = {scratch};
For(window->cursors) AddEdit(&edits, it.range, string);
ApplyEdits(window, edits);
AfterEdit(window, edits);
return;
}
// Multicursor paste
BeforeEdit(window);
Array<Edit> edits = {scratch};
for (int64_t i = 0; i < window->cursors.len; i += 1) {
String string = SavedClipboardCursors[i];
Cursor &it = window->cursors[i];
AddEdit(&edits, it.range, string);
}
ApplyEdits(window, edits);
AfterEdit(window, edits);
}

View File

@@ -379,12 +379,16 @@ void BeforeEdit(Window *window) {
window->history.debug_edit_phase += 1; window->history.debug_edit_phase += 1;
Assert(window->cursors.len); Assert(window->cursors.len);
SaveHistoryBeforeMergeCursor(window, &window->history.undo_stack); SaveHistoryBeforeMergeCursor(window, &window->history.undo_stack);
// Clear redo stack
{
For(window->history.redo_stack) { For(window->history.redo_stack) {
it.cursors.dealloc(); it.cursors.dealloc();
ForItem(edit, it.edits) Dealloc(it.edits.allocator, &edit.string.data); ForItem(edit, it.edits) Dealloc(it.edits.allocator, &edit.string.data);
it.edits.dealloc(); it.edits.dealloc();
} }
window->history.redo_stack.dealloc(); window->history.redo_stack.dealloc();
}
MergeCursors(window); MergeCursors(window);
} }

View File

@@ -3,12 +3,14 @@
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
// @todo: add history (undo, redo)
// @todo: add clipboard history? // @todo: add clipboard history?
// @todo: mouse double click // @todo: mouse double click
// @todo: context menu
// @todo: toy around with acme ideas
#include "rect2.cpp" #include "rect2.cpp"
#include "buffer.cpp" #include "buffer.cpp"
#include "layout.cpp" #include "layout.cpp"
#include "clipboard.cpp"
#include "utils.cpp" #include "utils.cpp"
#include "event_recording.cpp" #include "event_recording.cpp"
@@ -85,6 +87,7 @@ int main() {
int64_t frame = -1; int64_t frame = -1;
InitEventRecording(); InitEventRecording();
while (!WindowShouldClose()) { while (!WindowShouldClose()) {
Clear(&FrameArena);
For(windows) { For(windows) {
Assert(it.cursors.len); Assert(it.cursors.len);
it.main_cursor_begin_frame = it.cursors[0]; it.main_cursor_begin_frame = it.cursors[0];
@@ -272,46 +275,18 @@ int main() {
} }
} }
// @todo: improve behaviour of all copy pasting
if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) { if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) {
Array<String> strings = {FrameArena}; CopyToClipboard(focused_window);
For(focused_window->cursors) {
String string = GetString(focused_window->buffer, it.range);
strings.add(string);
}
String to_save = Merge(FrameArena, strings, "\n");
SetClipboardText(to_save.data);
} }
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_V) || IsKeyPressedRepeat(KEY_V))) { if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_V) || IsKeyPressedRepeat(KEY_V))) {
BeforeEdit(focused_window); PasteFromClipboard(focused_window);
Array<Edit> edits = {FrameArena};
const char *text = GetClipboardText();
String string = text;
For(focused_window->cursors) {
AddEdit(&edits, it.range, string);
}
ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits);
} }
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_X) || IsKeyPressedRepeat(KEY_X))) { if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_X) || IsKeyPressedRepeat(KEY_X))) {
// First, if there is no selection - select the entire line CopyToClipboard(focused_window);
For(focused_window->cursors) {
if (GetRangeSize(it.range) == 0) {
Line line = FindLine(focused_window->buffer, it.range.min);
it.range = line.range;
}
}
BeforeEdit(focused_window); BeforeEdit(focused_window);
Array<Edit> edits = {FrameArena}; Array<Edit> edits = {FrameArena};
Array<String> strings = {FrameArena}; For(focused_window->cursors) AddEdit(&edits, it.range, "");
For(focused_window->cursors) {
AddEdit(&edits, it.range, "");
String string = GetString(focused_window->buffer, it.range);
strings.add(string);
}
String to_save = Merge(FrameArena, strings, "\n");
SetClipboardText(to_save.data);
ApplyEdits(focused_window, edits); ApplyEdits(focused_window, edits);
AfterEdit(focused_window, edits); AfterEdit(focused_window, edits);
} }