Multicursor clipboard
This commit is contained in:
62
src/text_editor/clipboard.cpp
Normal file
62
src/text_editor/clipboard.cpp
Normal 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);
|
||||
}
|
||||
@@ -379,12 +379,16 @@ void BeforeEdit(Window *window) {
|
||||
window->history.debug_edit_phase += 1;
|
||||
Assert(window->cursors.len);
|
||||
SaveHistoryBeforeMergeCursor(window, &window->history.undo_stack);
|
||||
|
||||
// Clear redo stack
|
||||
{
|
||||
For(window->history.redo_stack) {
|
||||
it.cursors.dealloc();
|
||||
ForItem(edit, it.edits) Dealloc(it.edits.allocator, &edit.string.data);
|
||||
it.edits.dealloc();
|
||||
}
|
||||
window->history.redo_stack.dealloc();
|
||||
}
|
||||
MergeCursors(window);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
#include "raylib.h"
|
||||
#include "raymath.h"
|
||||
|
||||
// @todo: add history (undo, redo)
|
||||
// @todo: add clipboard history?
|
||||
// @todo: mouse double click
|
||||
// @todo: context menu
|
||||
// @todo: toy around with acme ideas
|
||||
#include "rect2.cpp"
|
||||
#include "buffer.cpp"
|
||||
#include "layout.cpp"
|
||||
#include "clipboard.cpp"
|
||||
#include "utils.cpp"
|
||||
#include "event_recording.cpp"
|
||||
|
||||
@@ -85,6 +87,7 @@ int main() {
|
||||
int64_t frame = -1;
|
||||
InitEventRecording();
|
||||
while (!WindowShouldClose()) {
|
||||
Clear(&FrameArena);
|
||||
For(windows) {
|
||||
Assert(it.cursors.len);
|
||||
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)) {
|
||||
Array<String> strings = {FrameArena};
|
||||
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);
|
||||
CopyToClipboard(focused_window);
|
||||
}
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_V) || IsKeyPressedRepeat(KEY_V))) {
|
||||
BeforeEdit(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);
|
||||
PasteFromClipboard(focused_window);
|
||||
}
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_X) || IsKeyPressedRepeat(KEY_X))) {
|
||||
// First, if there is no selection - select the entire line
|
||||
For(focused_window->cursors) {
|
||||
if (GetRangeSize(it.range) == 0) {
|
||||
Line line = FindLine(focused_window->buffer, it.range.min);
|
||||
it.range = line.range;
|
||||
}
|
||||
}
|
||||
CopyToClipboard(focused_window);
|
||||
|
||||
BeforeEdit(focused_window);
|
||||
Array<Edit> edits = {FrameArena};
|
||||
Array<String> strings = {FrameArena};
|
||||
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);
|
||||
For(focused_window->cursors) AddEdit(&edits, it.range, "");
|
||||
ApplyEdits(focused_window, edits);
|
||||
AfterEdit(focused_window, edits);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user