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;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user