Clipboard
This commit is contained in:
@@ -104,7 +104,7 @@ void AfterEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets) {
|
||||
buffer->debug_edit_phase -= 2;
|
||||
HistoryEntry *entry = GetLast(buffer->undo_stack);
|
||||
|
||||
#if 1
|
||||
#if BUFFER_DEBUG
|
||||
Assert(entry->carets.len);
|
||||
Assert(entry->edits.len);
|
||||
for (Int i = 0; i < edits->len - 1; i += 1) {
|
||||
@@ -133,8 +133,4 @@ void AfterEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets) {
|
||||
}
|
||||
}
|
||||
for (Int i = 0; i < carets->len; i += 1) carets->data[i] = new_carets[i];
|
||||
|
||||
// Make sure all carets are in range
|
||||
// @todo: remove?
|
||||
For(*carets) it.range = Clamp(*buffer, it.range);
|
||||
}
|
||||
|
||||
@@ -49,3 +49,28 @@ bool AreEqual(String16 a, String16 b, unsigned ignore_case = false) {
|
||||
}
|
||||
inline bool operator==(String16 a, String16 b) { return AreEqual(a, b); }
|
||||
inline bool operator!=(String16 a, String16 b) { return !AreEqual(a, b); }
|
||||
|
||||
String16 Merge(Allocator allocator, Array<String16> list, String16 separator = " ") {
|
||||
int64_t char_count = 0;
|
||||
For(list) char_count += it.len;
|
||||
if (char_count == 0) return {};
|
||||
int64_t node_count = list.len;
|
||||
|
||||
int64_t base_size = (char_count + 1);
|
||||
int64_t sep_size = (node_count - 1) * separator.len;
|
||||
int64_t size = base_size + sep_size;
|
||||
wchar_t *buff = (wchar_t *)AllocSize(allocator, sizeof(wchar_t) * (size + 1));
|
||||
String16 string = {buff, 0};
|
||||
For(list) {
|
||||
Assert(string.len + it.len <= size);
|
||||
memcpy(string.data + string.len, it.data, it.len * sizeof(wchar_t));
|
||||
string.len += it.len;
|
||||
if (!IsLast(list, it)) {
|
||||
memcpy(string.data + string.len, separator.data, separator.len * sizeof(wchar_t));
|
||||
string.len += separator.len;
|
||||
}
|
||||
}
|
||||
Assert(string.len == size - 1);
|
||||
string.data[size] = 0;
|
||||
return string;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,12 @@
|
||||
#include "colors.cpp"
|
||||
|
||||
#include "view.h"
|
||||
#include "view_commands_clipboard.cpp"
|
||||
#include "view_commands.cpp"
|
||||
#include "view_draw.cpp"
|
||||
|
||||
/*
|
||||
- Ctrl + Z, Ctrl + C - Undo redo history
|
||||
- Ctrl + D - create new cursor at next occurence of word
|
||||
- Ctrl + X, Ctrl + C, Ctrl + V - Copy paste
|
||||
- Scrollbars
|
||||
- Line numbers
|
||||
- file info bar at bottom (line, column, line endings)
|
||||
|
||||
@@ -222,6 +222,15 @@ void HandleKeybindings(View *_view) {
|
||||
UndoEdit(&buf, &view.carets);
|
||||
}
|
||||
|
||||
if (CtrlPress(KEY_C)) {
|
||||
Command_Copy(&view);
|
||||
} else if (CtrlPress(KEY_V)) {
|
||||
Command_Paste(&view);
|
||||
} else if (CtrlPress(KEY_X)) {
|
||||
Command_Copy(&view);
|
||||
Command_Replace(&view, L"");
|
||||
}
|
||||
|
||||
if (ShiftPress(KEY_PAGE_UP)) {
|
||||
Command_MoveCursorsByPageSize(&view, DIR_UP, SHIFT_PRESSED);
|
||||
} else if (Press(KEY_PAGE_UP)) {
|
||||
|
||||
67
src/text_editor/view_commands_clipboard.cpp
Normal file
67
src/text_editor/view_commands_clipboard.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
String16 SavedClipboardString;
|
||||
Array<String16> SavedClipboardCursors;
|
||||
|
||||
void Command_Copy(View *view) {
|
||||
Allocator sys_allocator = GetSystemAllocator();
|
||||
|
||||
SavedClipboardCursors.allocator = sys_allocator;
|
||||
if (SavedClipboardCursors.data) {
|
||||
For(SavedClipboardCursors) Dealloc(sys_allocator, &it.data);
|
||||
SavedClipboardCursors.len = 0;
|
||||
}
|
||||
|
||||
if (SavedClipboardString.data) {
|
||||
Dealloc(sys_allocator, &SavedClipboardString.data);
|
||||
SavedClipboardString = {};
|
||||
}
|
||||
|
||||
// First, if there is no selection - select the entire line
|
||||
For(view->carets) {
|
||||
if (GetSize(it.range) == 0) {
|
||||
Int line = PosToLine(*view->buffer, it.range.min);
|
||||
Range line_range = GetLineRange(*view->buffer, line);
|
||||
it.range = line_range;
|
||||
}
|
||||
}
|
||||
|
||||
For(view->carets) {
|
||||
String16 string = GetString(*view->buffer, it.range);
|
||||
String16 copy = Copy(sys_allocator, string);
|
||||
Add(&SavedClipboardCursors, copy);
|
||||
}
|
||||
|
||||
// @todo: maybe only add new line if there is no new line at the end, experiment with it
|
||||
SavedClipboardString = Merge(sys_allocator, SavedClipboardCursors, L"\n");
|
||||
Scratch scratch;
|
||||
SetClipboardText(ToString(scratch, SavedClipboardString).data);
|
||||
}
|
||||
|
||||
void Command_Paste(View *view) {
|
||||
Scratch scratch;
|
||||
const char *text = GetClipboardText();
|
||||
String string_ = text;
|
||||
String16 string = ToString16(scratch, string_);
|
||||
|
||||
// Regular paste
|
||||
if (string != SavedClipboardString || SavedClipboardCursors.len != view->carets.len) {
|
||||
BeforeEdit(view->buffer, view->carets);
|
||||
MergeCarets(&view->carets);
|
||||
Array<Edit> edits = {scratch};
|
||||
For(view->carets) AddEdit(&edits, it.range, string);
|
||||
ApplyEdits(view->buffer, edits);
|
||||
AfterEdit(view->buffer, &edits, &view->carets);
|
||||
return;
|
||||
}
|
||||
|
||||
// Multicursor paste
|
||||
BeforeEdit(view->buffer, view->carets);
|
||||
MergeCarets(&view->carets);
|
||||
Array<Edit> edits = {scratch};
|
||||
for (int64_t i = 0; i < view->carets.len; i += 1) {
|
||||
String16 string = SavedClipboardCursors[i];
|
||||
Caret &it = view->carets[i];
|
||||
AddEdit(&edits, it.range, string);
|
||||
}
|
||||
ApplyEdits(view->buffer, edits);
|
||||
AfterEdit(view->buffer, &edits, &view->carets);
|
||||
}
|
||||
Reference in New Issue
Block a user