Movement with new semantics fully completed
This commit is contained in:
@@ -1,128 +0,0 @@
|
|||||||
const int DIR_RIGHT = 0;
|
|
||||||
const int DIR_LEFT = 1;
|
|
||||||
const int DIR_DOWN = 2;
|
|
||||||
const int DIR_UP = 3;
|
|
||||||
const int DIR_COUNT = 4;
|
|
||||||
|
|
||||||
const bool CTRL_PRESSED = true;
|
|
||||||
|
|
||||||
Int MoveOnWhitespaceBoundary(Buffer &buffer, Int pos, int direction) {
|
|
||||||
Assert(direction == DIR_RIGHT || direction == DIR_LEFT);
|
|
||||||
bool right = direction == DIR_RIGHT;
|
|
||||||
|
|
||||||
pos = Clamp(pos, (Int)0, buffer.len);
|
|
||||||
bool standing_on_whitespace = IsWhitespace(buffer.str[pos]);
|
|
||||||
bool standing_on_symbol = IsSymbol(buffer.str[pos]);
|
|
||||||
bool standing_on_word = !standing_on_whitespace && !standing_on_symbol;
|
|
||||||
bool seek_whitespace = standing_on_whitespace == false;
|
|
||||||
bool seek_word = standing_on_whitespace || standing_on_symbol;
|
|
||||||
bool seek_symbol = standing_on_whitespace || standing_on_word;
|
|
||||||
|
|
||||||
Int result = right ? buffer.len : 0;
|
|
||||||
Int delta = right ? 1 : -1;
|
|
||||||
Int prev_pos = pos;
|
|
||||||
for (Int i = pos; right ? i < buffer.len : i >= 0; i += delta) {
|
|
||||||
bool is_whitespace = IsWhitespace(buffer.str[i]);
|
|
||||||
bool is_symbol = IsSymbol(buffer.str[i]);
|
|
||||||
bool is_word = !is_whitespace && !is_symbol;
|
|
||||||
Int res = right ? i : prev_pos;
|
|
||||||
if (seek_word && is_word) {
|
|
||||||
result = res;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (seek_whitespace && is_whitespace) {
|
|
||||||
result = res;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (seek_symbol && is_symbol) {
|
|
||||||
result = res;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev_pos = i;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Int MoveOnWhitespaceBoundaryVertical(Buffer &buffer, Int pos, int direction) {
|
|
||||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
|
||||||
|
|
||||||
bool up = direction == DIR_UP;
|
|
||||||
Int delta = up ? -1 : 1;
|
|
||||||
|
|
||||||
Int result = pos;
|
|
||||||
Int next_line = PosToLine(buffer, pos) + delta;
|
|
||||||
for (Int line = next_line; up ? line >= 0 : line < buffer.line_starts.len; line += delta) {
|
|
||||||
Range line_range = GetLineRange(buffer, line);
|
|
||||||
result = line_range.min;
|
|
||||||
|
|
||||||
bool whitespace_line = true;
|
|
||||||
for (Int i = line_range.min; i < line_range.max; i += 1) {
|
|
||||||
if (!IsWhitespace(buffer.str[i])) {
|
|
||||||
whitespace_line = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (whitespace_line) break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Int MovePos(Buffer &buffer, Int pos, int direction, bool ctrl_pressed = false) {
|
|
||||||
Assert(direction >= 0 && direction <= 3);
|
|
||||||
if (ctrl_pressed) {
|
|
||||||
switch (direction) {
|
|
||||||
case DIR_RIGHT: return MoveOnWhitespaceBoundary(buffer, pos, direction);
|
|
||||||
case DIR_LEFT: return MoveOnWhitespaceBoundary(buffer, pos - 1, direction);
|
|
||||||
case DIR_DOWN: return MoveOnWhitespaceBoundaryVertical(buffer, pos, direction);
|
|
||||||
case DIR_UP: return MoveOnWhitespaceBoundaryVertical(buffer, pos, direction);
|
|
||||||
default: return pos;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (direction) {
|
|
||||||
case DIR_RIGHT: return Clamp(pos + 1, (Int)0, buffer.len);
|
|
||||||
case DIR_LEFT: return Clamp(pos - 1, (Int)0, buffer.len);
|
|
||||||
case DIR_DOWN: return OffsetByLine(&buffer, pos, 1);
|
|
||||||
case DIR_UP: return OffsetByLine(&buffer, pos, -1);
|
|
||||||
default: return pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Caret FindInBuffer(Buffer *buffer, String16 needle, Caret caret, bool find_next = false) {
|
|
||||||
Int pos = caret.range.min;
|
|
||||||
String16 medium = GetString(*buffer, {pos, INT64_MAX});
|
|
||||||
|
|
||||||
Caret result = {};
|
|
||||||
Int index = 0;
|
|
||||||
if (Seek(medium, needle, &index)) {
|
|
||||||
result = MakeCaret(pos + index + needle.len, pos + index);
|
|
||||||
} else {
|
|
||||||
medium = GetString(*buffer);
|
|
||||||
if (Seek(medium, needle, &index)) {
|
|
||||||
result = MakeCaret(index + needle.len, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (find_next && AreEqual(result, caret)) {
|
|
||||||
caret.range.min = Clamp(*buffer, caret.range.min + 1);
|
|
||||||
caret.range.max = Clamp(*buffer, caret.range.max + 1);
|
|
||||||
result = FindInBuffer(buffer, needle, caret, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<Range> FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needle) {
|
|
||||||
Array<Range> result = {allocator};
|
|
||||||
String16 string_buffer = GetString(*buffer);
|
|
||||||
for (Int pos = 0;;) {
|
|
||||||
Int index = 0;
|
|
||||||
String16 medium = Skip(string_buffer, pos);
|
|
||||||
if (!Seek(medium, needle, &index)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Add(&result, Rng(pos + index, pos + index + needle.len));
|
|
||||||
pos += needle.len;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@@ -39,6 +39,14 @@ struct Event {
|
|||||||
const char *text;
|
const char *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int DIR_RIGHT = 0;
|
||||||
|
const int DIR_LEFT = 1;
|
||||||
|
const int DIR_DOWN = 2;
|
||||||
|
const int DIR_UP = 3;
|
||||||
|
const int DIR_COUNT = 4;
|
||||||
|
const bool CTRL_PRESSED = true;
|
||||||
|
bool SHIFT_PRESSED = true;
|
||||||
|
|
||||||
#define Press(KEY) (event.key == KEY)
|
#define Press(KEY) (event.key == KEY)
|
||||||
#define Ctrl(KEY) (event.key == KEY && event.ctrl)
|
#define Ctrl(KEY) (event.key == KEY && event.ctrl)
|
||||||
#define Shift(KEY) (event.key == KEY && event.shift)
|
#define Shift(KEY) (event.key == KEY && event.shift)
|
||||||
|
|||||||
@@ -1,3 +1,152 @@
|
|||||||
|
|
||||||
|
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
|
||||||
|
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
||||||
|
View &view = *GetActiveView(window);
|
||||||
|
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||||
|
|
||||||
|
Rect2I visible_cells_rect = GetVisibleCells(window);
|
||||||
|
Int y = GetSize(visible_cells_rect).y - 2;
|
||||||
|
if (direction == DIR_UP) y = -y;
|
||||||
|
|
||||||
|
For(view.carets) {
|
||||||
|
XY xy = PosToXY(*buffer, GetFront(it));
|
||||||
|
if (direction == DIR_DOWN && xy.line == buffer->line_starts.len - 1) {
|
||||||
|
Range line_range = GetLineRange(*buffer, xy.line);
|
||||||
|
xy.col = line_range.max - line_range.min;
|
||||||
|
} else if (direction == DIR_UP && xy.line == 0) {
|
||||||
|
xy.col = 0;
|
||||||
|
}
|
||||||
|
xy.line += y;
|
||||||
|
|
||||||
|
Int pos = XYToPos(*buffer, xy);
|
||||||
|
if (shift) {
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else {
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command_MoveCursorsToSide(View *view, int direction, bool shift = false) {
|
||||||
|
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
||||||
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
|
||||||
|
For(view->carets) {
|
||||||
|
Int pos = GetFront(it);
|
||||||
|
if (direction == DIR_RIGHT) {
|
||||||
|
pos = GetLineEnd(buffer, pos);
|
||||||
|
} else {
|
||||||
|
pos = GetLineStart(buffer, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shift) {
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else {
|
||||||
|
it.range.max = it.range.min = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Caret MoveCaret(Buffer *buffer, Caret it, int direction, bool ctrl = false, bool shift = false) {
|
||||||
|
Int front = GetFront(it);
|
||||||
|
Int range_size = GetSize(it.range);
|
||||||
|
switch (direction) {
|
||||||
|
case DIR_UP: {
|
||||||
|
if (ctrl && shift) {
|
||||||
|
Int pos = GetPrevEmptyLineStart(buffer, front);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else if (ctrl) {
|
||||||
|
Int pos = GetPrevEmptyLineStart(buffer, it.range.min);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
} else if (shift) {
|
||||||
|
Int pos = OffsetByLine(buffer, front, -1);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else {
|
||||||
|
if (range_size == 0) {
|
||||||
|
Int pos = OffsetByLine(buffer, it.range.min, -1);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
} else {
|
||||||
|
it = MakeCaret(it.range.min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case DIR_DOWN: {
|
||||||
|
if (ctrl && shift) {
|
||||||
|
Int pos = GetNextEmptyLineStart(buffer, front);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else if (ctrl) {
|
||||||
|
Int pos = GetNextEmptyLineStart(buffer, it.range.max);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
} else if (shift) {
|
||||||
|
Int pos = OffsetByLine(buffer, front, 1);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else {
|
||||||
|
if (range_size == 0) {
|
||||||
|
Int pos = OffsetByLine(buffer, it.range.max, 1);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
} else {
|
||||||
|
it = MakeCaret(it.range.max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case DIR_LEFT: {
|
||||||
|
if (ctrl && shift) {
|
||||||
|
Int pos = GetPrevWordStart(buffer, front);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else if (ctrl) {
|
||||||
|
if (range_size != 0 && front != it.range.min) {
|
||||||
|
it = MakeCaret(it.range.min);
|
||||||
|
} else {
|
||||||
|
Int pos = GetPrevWordStart(buffer, it.range.min);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
}
|
||||||
|
} else if (shift) {
|
||||||
|
Int pos = GetPrevChar(buffer, front);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else {
|
||||||
|
if (range_size == 0) {
|
||||||
|
Int pos = GetPrevChar(buffer, it.range.min);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
} else {
|
||||||
|
it = MakeCaret(it.range.min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case DIR_RIGHT: {
|
||||||
|
if (ctrl && shift) {
|
||||||
|
Int pos = GetNextWordEnd(buffer, front);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else if (ctrl) {
|
||||||
|
if (range_size != 0 && front != it.range.max) {
|
||||||
|
it = MakeCaret(it.range.max);
|
||||||
|
} else {
|
||||||
|
Int pos = GetNextWordEnd(buffer, it.range.max);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
}
|
||||||
|
} else if (shift) {
|
||||||
|
Int pos = GetNextChar(buffer, front);
|
||||||
|
it = ChangeFront(it, pos);
|
||||||
|
} else {
|
||||||
|
if (range_size == 0) {
|
||||||
|
Int pos = GetNextChar(buffer, it.range.max);
|
||||||
|
it = MakeCaret(pos);
|
||||||
|
} else {
|
||||||
|
it = MakeCaret(it.range.max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command_Move(View *view, int direction, bool ctrl = false, bool shift = false) {
|
||||||
|
Assert(direction < DIR_COUNT);
|
||||||
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
|
For(view->carets) {
|
||||||
|
it = MoveCaret(buffer, it, direction, ctrl, shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Command_Replace(View *view, String16 string) {
|
void Command_Replace(View *view, String16 string) {
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -28,7 +177,7 @@ void Command_DuplicateLine(View *view, int direction) {
|
|||||||
ApplyEdits(buffer, edits);
|
ApplyEdits(buffer, edits);
|
||||||
AfterEdit(buffer, &edits, &view->carets);
|
AfterEdit(buffer, &edits, &view->carets);
|
||||||
|
|
||||||
For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, direction, false));
|
Command_Move(view, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
Int FindRangeByPos(Array<Range> &ranges, Int pos) {
|
Int FindRangeByPos(Array<Range> &ranges, Int pos) {
|
||||||
@@ -177,90 +326,6 @@ void Command_KillSelectedLines(View *view) {
|
|||||||
AfterEdit(buffer, &edits, &view->carets, KILL_SELECTION);
|
AfterEdit(buffer, &edits, &view->carets, KILL_SELECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHIFT_PRESSED = true;
|
|
||||||
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
|
|
||||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
|
||||||
View &view = *GetActiveView(window);
|
|
||||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
|
||||||
|
|
||||||
Rect2I visible_cells_rect = GetVisibleCells(window);
|
|
||||||
Int y = GetSize(visible_cells_rect).y - 2;
|
|
||||||
if (direction == DIR_UP) y = -y;
|
|
||||||
|
|
||||||
For(view.carets) {
|
|
||||||
XY xy = PosToXY(*buffer, GetFront(it));
|
|
||||||
if (direction == DIR_DOWN && xy.line == buffer->line_starts.len - 1) {
|
|
||||||
Range line_range = GetLineRange(*buffer, xy.line);
|
|
||||||
xy.col = line_range.max - line_range.min;
|
|
||||||
} else if (direction == DIR_UP && xy.line == 0) {
|
|
||||||
xy.col = 0;
|
|
||||||
}
|
|
||||||
xy.line += y;
|
|
||||||
|
|
||||||
Int pos = XYToPos(*buffer, xy);
|
|
||||||
if (shift) {
|
|
||||||
it = ChangeFront(it, pos);
|
|
||||||
} else {
|
|
||||||
it = MakeCaret(pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Command_MoveCursorsToSide(View *view, int direction, bool shift = false) {
|
|
||||||
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
|
||||||
|
|
||||||
For(view->carets) {
|
|
||||||
Int pos = GetFront(it);
|
|
||||||
if (direction == DIR_RIGHT) {
|
|
||||||
pos = GetLineEnd(buffer, pos);
|
|
||||||
} else {
|
|
||||||
pos = GetLineStart(buffer, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shift) {
|
|
||||||
it = ChangeFront(it, pos);
|
|
||||||
} else {
|
|
||||||
it.range.max = it.range.min = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Command_Move(View *view, int direction, bool ctrl = false, bool shift = false) {
|
|
||||||
Assert(direction < DIR_COUNT);
|
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
|
||||||
For(view->carets) {
|
|
||||||
Int front = GetFront(it);
|
|
||||||
switch (direction) {
|
|
||||||
case DIR_UP: {
|
|
||||||
} break;
|
|
||||||
case DIR_DOWN: {
|
|
||||||
if (ctrl && shift) {
|
|
||||||
Int pos = GetNextEmptyLineStart(buffer, front);
|
|
||||||
it = ChangeFront(it, pos);
|
|
||||||
} else if (ctrl) {
|
|
||||||
Int pos = GetNextEmptyLineStart(buffer, it.range.max);
|
|
||||||
it = MakeCaret(pos);
|
|
||||||
} else if (shift) {
|
|
||||||
Int pos = OffsetByLine(buffer, front, 1);
|
|
||||||
it = ChangeFront(it, pos);
|
|
||||||
} else {
|
|
||||||
if (GetSize(it.range) == 0) {
|
|
||||||
Int pos = OffsetByLine(buffer, it.range.max, 1);
|
|
||||||
it = MakeCaret(pos);
|
|
||||||
} else {
|
|
||||||
it = MakeCaret(it.range.max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case DIR_LEFT: {
|
|
||||||
} break;
|
|
||||||
case DIR_RIGHT: {
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Command_Delete(View *view, int direction, bool ctrl = false) {
|
void Command_Delete(View *view, int direction, bool ctrl = false) {
|
||||||
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
Assert(direction == DIR_LEFT || direction == DIR_RIGHT);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -271,8 +336,7 @@ void Command_Delete(View *view, int direction, bool ctrl = false) {
|
|||||||
// Select things to delete
|
// Select things to delete
|
||||||
For(view->carets) {
|
For(view->carets) {
|
||||||
if (GetSize(it.range)) continue;
|
if (GetSize(it.range)) continue;
|
||||||
Int pos = MovePos(*buffer, it.range.min, direction, ctrl);
|
it = MoveCaret(buffer, it, direction, ctrl, SHIFT_PRESSED);
|
||||||
it = MakeCaret(pos, it.range.min);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeCarets(view);
|
MergeCarets(view);
|
||||||
@@ -306,17 +370,20 @@ void Command_CreateCursorVertical(View *_view, int direction) {
|
|||||||
View &view = *_view;
|
View &view = *_view;
|
||||||
Buffer *buffer = GetBuffer(view.active_buffer);
|
Buffer *buffer = GetBuffer(view.active_buffer);
|
||||||
|
|
||||||
|
Int line_offset = direction == DIR_UP ? -1 : 1;
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Caret> arr = {scratch};
|
Array<Caret> arr = {scratch};
|
||||||
For(view.carets) {
|
For(view.carets) {
|
||||||
if (PosToLine(*buffer, it.range.min) == PosToLine(*buffer, it.range.max)) {
|
if (PosToLine(*buffer, it.range.min) == PosToLine(*buffer, it.range.max)) {
|
||||||
Int f = MovePos(*buffer, GetFront(it), direction);
|
Int f = OffsetByLine(buffer, GetFront(it), line_offset);
|
||||||
Int b = MovePos(*buffer, GetBack(it), direction);
|
Int b = OffsetByLine(buffer, GetBack(it), line_offset);
|
||||||
Add(&arr, MakeCaret(f, b));
|
Add(&arr, MakeCaret(f, b));
|
||||||
} else {
|
} else {
|
||||||
Int pos = direction == DIR_UP ? it.range.min : it.range.max;
|
Int pos = direction == DIR_UP ? it.range.min : it.range.max;
|
||||||
Int min = MovePos(*buffer, pos, direction);
|
Caret caret = MakeCaret(pos);
|
||||||
Add(&arr, MakeCaret(min));
|
caret = MoveCaret(buffer, caret, direction);
|
||||||
|
Add(&arr, caret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
For(arr) Add(&view.carets, it);
|
For(arr) Add(&view.carets, it);
|
||||||
@@ -391,6 +458,45 @@ void MergeCarets(View *view, Range *mouse_selection_anchor) {
|
|||||||
Swap(&view->carets[first_caret_index], &view->carets[0]);
|
Swap(&view->carets[first_caret_index], &view->carets[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Caret FindInBuffer(Buffer *buffer, String16 needle, Caret caret, bool find_next = false) {
|
||||||
|
Int pos = caret.range.min;
|
||||||
|
String16 medium = GetString(*buffer, {pos, INT64_MAX});
|
||||||
|
|
||||||
|
Caret result = {};
|
||||||
|
Int index = 0;
|
||||||
|
if (Seek(medium, needle, &index)) {
|
||||||
|
result = MakeCaret(pos + index + needle.len, pos + index);
|
||||||
|
} else {
|
||||||
|
medium = GetString(*buffer);
|
||||||
|
if (Seek(medium, needle, &index)) {
|
||||||
|
result = MakeCaret(index + needle.len, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (find_next && AreEqual(result, caret)) {
|
||||||
|
caret.range.min = Clamp(*buffer, caret.range.min + 1);
|
||||||
|
caret.range.max = Clamp(*buffer, caret.range.max + 1);
|
||||||
|
result = FindInBuffer(buffer, needle, caret, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<Range> FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needle) {
|
||||||
|
Array<Range> result = {allocator};
|
||||||
|
String16 string_buffer = GetString(*buffer);
|
||||||
|
for (Int pos = 0;;) {
|
||||||
|
Int index = 0;
|
||||||
|
String16 medium = Skip(string_buffer, pos);
|
||||||
|
if (!Seek(medium, needle, &index)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Add(&result, Rng(pos + index, pos + index + needle.len));
|
||||||
|
pos += needle.len;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void WindowCommand(Event event, Window *window, View *view) {
|
void WindowCommand(Event event, Window *window, View *view) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
@@ -409,33 +515,6 @@ void WindowCommand(Event event, Window *window, View *view) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Underline
|
|
||||||
if (event.ctrl) {
|
|
||||||
Caret caret = view->carets[0];
|
|
||||||
if (GetSize(caret.range) == 0) {
|
|
||||||
view->underline_pos[view->underline_count++] = caret.range.min;
|
|
||||||
Assert(view->underline_count <= 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Vec2I mouse = MouseVec2I();
|
|
||||||
Vec2I mworld = mouse - window->document_rect.min + view->scroll;
|
|
||||||
Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing};
|
|
||||||
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
|
||||||
Int p = XYToPosErrorOutOfBounds(*buffer, xy);
|
|
||||||
if (p != -1) {
|
|
||||||
view->underline_pos[view->underline_count++] = p;
|
|
||||||
Assert(view->underline_count <= 2);
|
|
||||||
|
|
||||||
if (Mouse(LEFT)) {
|
|
||||||
Range enclose = EncloseLoadWord(buffer, p);
|
|
||||||
String16 string = GetString(*buffer, enclose);
|
|
||||||
Open(string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlAlt(SDLK_DOWN)) {
|
if (CtrlAlt(SDLK_DOWN)) {
|
||||||
Command_DuplicateLine(view, DIR_DOWN);
|
Command_DuplicateLine(view, DIR_DOWN);
|
||||||
} else if (AltShift(SDLK_DOWN)) {
|
} else if (AltShift(SDLK_DOWN)) {
|
||||||
@@ -455,63 +534,33 @@ void WindowCommand(Event event, Window *window, View *view) {
|
|||||||
} else if (AltShift(SDLK_UP)) {
|
} else if (AltShift(SDLK_UP)) {
|
||||||
Command_CreateCursorVertical(view, DIR_UP);
|
Command_CreateCursorVertical(view, DIR_UP);
|
||||||
} else if (CtrlShift(SDLK_UP)) {
|
} else if (CtrlShift(SDLK_UP)) {
|
||||||
For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP, CTRL_PRESSED));
|
Command_Move(view, DIR_UP, CTRL_PRESSED, SHIFT_PRESSED);
|
||||||
} else if (Ctrl(SDLK_UP)) {
|
} else if (Ctrl(SDLK_UP)) {
|
||||||
For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP, CTRL_PRESSED));
|
Command_Move(view, DIR_UP, CTRL_PRESSED);
|
||||||
} else if (Shift(SDLK_UP)) {
|
} else if (Shift(SDLK_UP)) {
|
||||||
For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_UP));
|
Command_Move(view, DIR_UP, false, SHIFT_PRESSED);
|
||||||
} else if (Press(SDLK_UP)) {
|
} else if (Press(SDLK_UP)) {
|
||||||
For(view->carets) {
|
Command_Move(view, DIR_UP);
|
||||||
if (GetSize(it.range) == 0) {
|
|
||||||
it = MakeCaret(MovePos(*buffer, it.range.min, DIR_UP));
|
|
||||||
} else {
|
|
||||||
it = MakeCaret(it.range.min);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlShift(SDLK_LEFT)) {
|
if (CtrlShift(SDLK_LEFT)) {
|
||||||
For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, true));
|
Command_Move(view, DIR_LEFT, CTRL_PRESSED, SHIFT_PRESSED);
|
||||||
} else if (Ctrl(SDLK_LEFT)) {
|
} else if (Ctrl(SDLK_LEFT)) {
|
||||||
For(view->carets) {
|
Command_Move(view, DIR_LEFT, CTRL_PRESSED);
|
||||||
if (GetSize(it.range) != 0 && GetFront(it) != it.range.min) {
|
|
||||||
it = MakeCaret(it.range.min);
|
|
||||||
} else {
|
|
||||||
it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (Shift(SDLK_LEFT)) {
|
} else if (Shift(SDLK_LEFT)) {
|
||||||
For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_LEFT, false));
|
Command_Move(view, DIR_LEFT, false, SHIFT_PRESSED);
|
||||||
} else if (Press(SDLK_LEFT)) {
|
} else if (Press(SDLK_LEFT)) {
|
||||||
For(view->carets) {
|
Command_Move(view, DIR_LEFT);
|
||||||
if (GetSize(it.range) == 0) {
|
|
||||||
it = MakeCaret(MovePos(*buffer, it.range.min, DIR_LEFT, false));
|
|
||||||
} else {
|
|
||||||
it = MakeCaret(it.range.min);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlShift(SDLK_RIGHT)) {
|
if (CtrlShift(SDLK_RIGHT)) {
|
||||||
For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, true));
|
Command_Move(view, DIR_RIGHT, CTRL_PRESSED, SHIFT_PRESSED);
|
||||||
} else if (Ctrl(SDLK_RIGHT)) {
|
} else if (Ctrl(SDLK_RIGHT)) {
|
||||||
For(view->carets) {
|
Command_Move(view, DIR_RIGHT, CTRL_PRESSED);
|
||||||
if (GetSize(it.range) != 0 && GetFront(it) != it.range.max) {
|
|
||||||
it = MakeCaret(it.range.max);
|
|
||||||
} else {
|
|
||||||
it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (Shift(SDLK_RIGHT)) {
|
} else if (Shift(SDLK_RIGHT)) {
|
||||||
For(view->carets) it = ChangeFront(it, MovePos(*buffer, GetFront(it), DIR_RIGHT, false));
|
Command_Move(view, DIR_RIGHT, false, SHIFT_PRESSED);
|
||||||
} else if (Press(SDLK_RIGHT)) {
|
} else if (Press(SDLK_RIGHT)) {
|
||||||
For(view->carets) {
|
Command_Move(view, DIR_RIGHT);
|
||||||
if (GetSize(it.range) == 0) {
|
|
||||||
it = MakeCaret(MovePos(*buffer, it.range.max, DIR_RIGHT, false));
|
|
||||||
} else {
|
|
||||||
it = MakeCaret(it.range.max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlShift(SDLK_Z)) {
|
if (CtrlShift(SDLK_Z)) {
|
||||||
@@ -718,6 +767,33 @@ void WindowCommand(Event event, Window *window, View *view) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Underline
|
||||||
|
if (event.ctrl) {
|
||||||
|
Caret caret = view->carets[0];
|
||||||
|
if (GetSize(caret.range) == 0) {
|
||||||
|
view->underline_pos[view->underline_count++] = caret.range.min;
|
||||||
|
Assert(view->underline_count <= 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Vec2I mouse = MouseVec2I();
|
||||||
|
Vec2I mworld = mouse - window->document_rect.min + view->scroll;
|
||||||
|
Vec2I pos = mworld / Vec2I{FontCharSpacing, FontLineSpacing};
|
||||||
|
XY xy = {(Int)(pos.x), (Int)(pos.y)};
|
||||||
|
Int p = XYToPosErrorOutOfBounds(*buffer, xy);
|
||||||
|
if (p != -1) {
|
||||||
|
view->underline_pos[view->underline_count++] = p;
|
||||||
|
Assert(view->underline_count <= 2);
|
||||||
|
|
||||||
|
if (Mouse(LEFT)) {
|
||||||
|
Range enclose = EncloseLoadWord(buffer, p);
|
||||||
|
String16 string = GetString(*buffer, enclose);
|
||||||
|
Open(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
Vec2I mouse = MouseVec2I();
|
Vec2I mouse = MouseVec2I();
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ int FullScreenPositionX, FullScreenPositionY;
|
|||||||
#include "buffer_helpers.cpp"
|
#include "buffer_helpers.cpp"
|
||||||
#include "buffer.cpp"
|
#include "buffer.cpp"
|
||||||
#include "buffer_multi_cursor.cpp"
|
#include "buffer_multi_cursor.cpp"
|
||||||
#include "buffer_ops.cpp"
|
|
||||||
#include "buffer_history.cpp"
|
#include "buffer_history.cpp"
|
||||||
#include "buffer_fuzzy_search.cpp"
|
#include "buffer_fuzzy_search.cpp"
|
||||||
#include "buffer_test_load.cpp"
|
#include "buffer_test_load.cpp"
|
||||||
|
|||||||
Reference in New Issue
Block a user