2017-01-23 06:19:43 +00:00
|
|
|
/*
|
2018-05-10 08:12:47 +00:00
|
|
|
4coder_seek.cpp - Procedures and commands for jumping through code to useful stop boundaries.
|
|
|
|
*/
|
2017-01-23 06:19:43 +00:00
|
|
|
|
|
|
|
// TOP
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
seek_line_end(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
|
|
|
i32 buffer_size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &buffer_size);
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
char chunk[1024];
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 chunk_size = sizeof(chunk);
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, chunk_size)){
|
|
|
|
b32 still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos < stream.end; ++pos){
|
2019-04-01 02:41:39 +00:00
|
|
|
char at_pos = stream.data[pos];
|
2017-01-23 06:19:43 +00:00
|
|
|
if (at_pos == '\n'){
|
|
|
|
goto double_break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break:;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (pos > buffer_size){
|
|
|
|
pos = buffer_size;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
seek_line_beginning(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char chunk[1024];
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 chunk_size = sizeof(chunk);
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-01-23 06:19:43 +00:00
|
|
|
--pos;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, chunk_size)){
|
|
|
|
b32 still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos >= stream.start; --pos){
|
2019-04-01 02:41:39 +00:00
|
|
|
char at_pos = stream.data[pos];
|
2017-01-23 06:19:43 +00:00
|
|
|
if (at_pos == '\n'){
|
|
|
|
goto double_break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break:;
|
|
|
|
if (pos != 0){
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
if (pos < 0){
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-04-06 21:13:49 +00:00
|
|
|
move_past_lead_whitespace(Application_Links *app, View_ID view, Buffer_ID buffer_id){
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2019-04-06 21:13:49 +00:00
|
|
|
i32 new_pos = seek_line_beginning(app, buffer_id, pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
char space[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk chunk = {};
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 still_looping = false;
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 i = new_pos;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&chunk, app, buffer_id, i, space, sizeof(space))){
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; i < chunk.end; ++i){
|
2017-01-23 06:19:43 +00:00
|
|
|
char at_pos = chunk.data[i];
|
2019-06-01 23:58:28 +00:00
|
|
|
if (at_pos == '\n' || !character_is_whitespace(at_pos)){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto break2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&chunk);
|
|
|
|
}while(still_looping);
|
|
|
|
break2:;
|
|
|
|
|
2019-04-06 21:13:49 +00:00
|
|
|
if (i > pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
view_set_cursor(app, view, seek_pos(i), true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_whitespace_up(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char chunk[1024];
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 chunk_size = sizeof(chunk);
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2017-03-23 19:15:33 +00:00
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
--pos;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, chunk_size)){
|
2017-01-23 06:19:43 +00:00
|
|
|
// Step 1: Find the first non-whitespace character
|
|
|
|
// behind the current position.
|
2019-04-01 02:41:39 +00:00
|
|
|
b32 still_looping = true;
|
|
|
|
for (;still_looping;){
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos >= stream.start; --pos){
|
2019-04-01 02:41:39 +00:00
|
|
|
char at_pos = stream.data[pos];
|
2019-06-01 23:58:28 +00:00
|
|
|
if (!character_is_whitespace(at_pos)){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto double_break_1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}
|
|
|
|
double_break_1:;
|
|
|
|
|
|
|
|
// Step 2: Continue scanning backward, at each '\n'
|
|
|
|
// mark the beginning of another line by setting
|
|
|
|
// no_hard to true, set it back to false if a
|
|
|
|
// non-whitespace character is discovered before
|
|
|
|
// the next '\n'
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 no_hard = false;
|
2019-04-01 02:41:39 +00:00
|
|
|
for (;still_looping;){
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos >= stream.start; --pos){
|
2019-04-01 02:41:39 +00:00
|
|
|
char at_pos = stream.data[pos];
|
2017-01-23 06:19:43 +00:00
|
|
|
if (at_pos == '\n'){
|
|
|
|
if (no_hard){
|
|
|
|
goto double_break_2;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
no_hard = true;
|
|
|
|
}
|
|
|
|
}
|
2019-06-01 23:58:28 +00:00
|
|
|
else if (!character_is_whitespace(at_pos)){
|
2017-01-23 06:19:43 +00:00
|
|
|
no_hard = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}
|
|
|
|
double_break_2:;
|
|
|
|
|
|
|
|
if (pos != 0){
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_whitespace_down(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
|
|
|
i32 buffer_size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &buffer_size);
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
char chunk[1024];
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 chunk_size = sizeof(chunk);
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, chunk_size)){
|
2017-01-23 06:19:43 +00:00
|
|
|
// step 1: find the first non-whitespace character
|
|
|
|
// ahead of the current position.
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos < stream.end; ++pos){
|
2017-03-29 16:32:06 +00:00
|
|
|
char at_pos = stream.data[pos];
|
2019-06-01 23:58:28 +00:00
|
|
|
if (!character_is_whitespace(at_pos)){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto double_break_1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
} while(still_looping);
|
|
|
|
double_break_1:;
|
|
|
|
|
|
|
|
// step 2: continue scanning forward, at each '\n'
|
|
|
|
// mark it as the beginning of a new line by updating
|
|
|
|
// the prev_endline value. if another '\n' is found
|
|
|
|
// with non-whitespace then the previous line was
|
|
|
|
// all whitespace.
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 no_hard = false;
|
|
|
|
i32 prev_endline = -1;
|
2017-01-23 06:19:43 +00:00
|
|
|
while(still_looping){
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos < stream.end; ++pos){
|
2017-03-29 16:32:06 +00:00
|
|
|
char at_pos = stream.data[pos];
|
2017-01-23 06:19:43 +00:00
|
|
|
if (at_pos == '\n'){
|
|
|
|
if (no_hard){
|
|
|
|
goto double_break_2;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
no_hard = true;
|
|
|
|
prev_endline = pos;
|
|
|
|
}
|
|
|
|
}
|
2019-06-01 23:58:28 +00:00
|
|
|
else if (!character_is_whitespace(at_pos)){
|
2017-01-23 06:19:43 +00:00
|
|
|
no_hard = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}
|
|
|
|
double_break_2:;
|
|
|
|
|
2019-04-01 02:41:39 +00:00
|
|
|
if (prev_endline == -1 || prev_endline + 1 >= buffer_size){
|
|
|
|
pos = buffer_size;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-04-01 02:41:39 +00:00
|
|
|
pos = prev_endline + 1;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(pos);
|
|
|
|
}
|
2018-05-10 08:12:47 +00:00
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_whitespace_right(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
|
|
|
i32 buffer_size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &buffer_size);
|
|
|
|
i32 result = buffer_size + 1;
|
2019-02-21 06:58:34 +00:00
|
|
|
if (pos < 0){
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
pos += 1;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (pos < buffer_size){
|
2019-02-21 06:58:34 +00:00
|
|
|
char data_chunk[1024];
|
|
|
|
Stream_Chunk stream = {};
|
|
|
|
stream.add_null = true;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = true;
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_whitespace_1 = character_is_whitespace(buffer_get_char(app, buffer_id, pos - 1));
|
2019-02-21 06:58:34 +00:00
|
|
|
do{
|
|
|
|
for (; pos < stream.end; ++pos){
|
|
|
|
char c2 = stream.data[pos];
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 is_whitespace_2 = true;
|
2019-02-21 06:58:34 +00:00
|
|
|
if (c2 != 0){
|
2019-06-01 23:58:28 +00:00
|
|
|
is_whitespace_2 = character_is_whitespace(c2);
|
2019-02-21 06:58:34 +00:00
|
|
|
}
|
|
|
|
if (!is_whitespace_1 && is_whitespace_2){
|
|
|
|
result = pos;
|
|
|
|
goto double_break;
|
|
|
|
}
|
|
|
|
is_whitespace_1 = is_whitespace_2;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
2019-02-21 06:58:34 +00:00
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break:;
|
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
2019-02-21 06:58:34 +00:00
|
|
|
return(result);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_whitespace_left(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
|
|
|
i32 buffer_size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &buffer_size);
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 result = -1;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (pos > buffer_size){
|
|
|
|
pos = buffer_size;
|
2019-02-21 06:58:34 +00:00
|
|
|
}
|
|
|
|
pos -= 2;
|
|
|
|
if (pos >= 0){
|
|
|
|
char data_chunk[1024];
|
|
|
|
Stream_Chunk stream = {};
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = true;
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_whitespace_2 = character_is_whitespace(buffer_get_char(app, buffer_id, pos + 1));
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos >= stream.start; --pos){
|
2019-02-21 06:58:34 +00:00
|
|
|
char c1 = stream.data[pos];
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 is_whitespace_1 = character_is_whitespace(c1);
|
2019-02-21 06:58:34 +00:00
|
|
|
if (is_whitespace_1 && !is_whitespace_2){
|
|
|
|
result = pos + 1;
|
|
|
|
goto double_break;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
2019-02-21 06:58:34 +00:00
|
|
|
is_whitespace_2 = is_whitespace_1;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
2019-02-21 06:58:34 +00:00
|
|
|
double_break:;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
2019-02-21 06:58:34 +00:00
|
|
|
if (pos == -1){
|
2019-06-01 23:58:28 +00:00
|
|
|
if (!character_is_whitespace(buffer_get_char(app, buffer_id, 0))){
|
2019-02-21 06:58:34 +00:00
|
|
|
result = 0;
|
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
2019-02-21 06:58:34 +00:00
|
|
|
return(result);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_alphanumeric_right(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char data_chunk[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos < stream.end; ++pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (c != '_' && character_is_alpha_numeric_unicode(c)){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto double_break1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break1:;
|
2017-03-29 16:32:06 +00:00
|
|
|
still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos < stream.end; ++pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (!(c != '_' && character_is_alpha_numeric_unicode(c))){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto double_break2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break2:;
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_alphanumeric_left(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char data_chunk[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-01-23 06:19:43 +00:00
|
|
|
--pos;
|
|
|
|
if (pos > 0){
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos >= stream.start; --pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (c != '_' && character_is_alpha_numeric_unicode(c)){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto double_break1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break1:;
|
2017-03-29 16:32:06 +00:00
|
|
|
still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos >= stream.start; --pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (!(c != '_' && character_is_alpha_numeric_unicode(c))){
|
2017-01-23 06:19:43 +00:00
|
|
|
++pos;
|
|
|
|
goto double_break2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break2:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_alphanumeric_or_underscore_right(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
2017-03-29 16:32:06 +00:00
|
|
|
char data_chunk[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = true;
|
2017-03-29 16:32:06 +00:00
|
|
|
do{
|
|
|
|
for (; pos < stream.end; ++pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (character_is_alpha_numeric_unicode(c)){
|
2017-03-29 16:32:06 +00:00
|
|
|
goto double_break1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break1:;
|
|
|
|
still_looping = true;
|
|
|
|
do{
|
|
|
|
for (; pos < stream.end; ++pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (!character_is_alpha_numeric_unicode(c)){
|
2017-03-29 16:32:06 +00:00
|
|
|
goto double_break2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break2:;
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_alphanumeric_or_underscore_left(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
2017-03-29 16:32:06 +00:00
|
|
|
char data_chunk[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-03-29 16:32:06 +00:00
|
|
|
--pos;
|
|
|
|
if (pos > 0){
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = true;
|
2017-03-29 16:32:06 +00:00
|
|
|
do{
|
|
|
|
for (; pos >= stream.start; --pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (character_is_alpha_numeric_unicode(c)){
|
2017-03-29 16:32:06 +00:00
|
|
|
goto double_break1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break1:;
|
|
|
|
still_looping = true;
|
|
|
|
do{
|
|
|
|
for (; pos >= stream.start; --pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = stream.data[pos];
|
|
|
|
if (!character_is_alpha_numeric_unicode(c)){
|
2017-03-29 16:32:06 +00:00
|
|
|
++pos;
|
|
|
|
goto double_break2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break2:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_range_camel_right(Application_Links *app, Buffer_ID buffer_id, i32 pos, i32 an_pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char data_chunk[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-01-23 06:19:43 +00:00
|
|
|
++pos;
|
|
|
|
if (pos < an_pos){
|
|
|
|
stream.max_end = an_pos;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = 0;
|
|
|
|
u8 pc = stream.data[pos];
|
2017-01-23 06:19:43 +00:00
|
|
|
++pos;
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = false;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos < stream.end; ++pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
c = stream.data[pos];
|
2019-06-01 23:58:28 +00:00
|
|
|
if (character_is_upper(c) && character_is_lower_unicode(pc)){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto double_break1;
|
|
|
|
}
|
2017-03-30 15:18:16 +00:00
|
|
|
pc = c;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break1:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
pos = an_pos;
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_range_camel_left(Application_Links *app, Buffer_ID buffer_id, i32 pos, i32 an_pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char data_chunk[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-01-23 06:19:43 +00:00
|
|
|
--pos;
|
|
|
|
if (pos > 0){
|
|
|
|
stream.min_start = an_pos+1;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, data_chunk, sizeof(data_chunk))){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 c = 0;
|
|
|
|
u8 pc = stream.data[pos];
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = false;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (; pos >= stream.start; --pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
c = stream.data[pos];
|
2019-06-01 23:58:28 +00:00
|
|
|
if (character_is_upper(c) && character_is_lower_unicode(pc)){
|
2017-01-23 06:19:43 +00:00
|
|
|
goto double_break1;
|
|
|
|
}
|
2017-03-30 15:18:16 +00:00
|
|
|
pc = c;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
double_break1:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
return(pos);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_alphanumeric_or_camel_right(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
|
|
|
i32 an_pos = buffer_seek_alphanumeric_right(app, buffer_id, pos);
|
|
|
|
i32 result = buffer_seek_range_camel_right(app, buffer_id, pos, an_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_alphanumeric_or_camel_left(Application_Links *app, Buffer_ID buffer_id, i32 pos){
|
|
|
|
i32 an_pos = buffer_seek_alphanumeric_left(app, buffer_id, pos);
|
|
|
|
i32 result = buffer_seek_range_camel_left(app, buffer_id, pos, an_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
|
|
|
seek_token_left(Cpp_Token_Array *tokens, i32 pos){
|
|
|
|
i32 result = -1;
|
|
|
|
i32 token_get_pos = pos - 1;
|
2019-02-21 04:43:25 +00:00
|
|
|
Cpp_Get_Token_Result get = cpp_get_token(*tokens, token_get_pos);
|
|
|
|
if (get.token_index >= 0){
|
|
|
|
result = get.token_start;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
2019-02-21 04:43:25 +00:00
|
|
|
return(result);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
|
|
|
seek_token_right(Cpp_Token_Array *tokens, i32 pos, i32 buffer_end){
|
|
|
|
i32 result = buffer_end + 1;
|
2017-01-23 06:19:43 +00:00
|
|
|
Cpp_Get_Token_Result get = cpp_get_token(*tokens, pos);
|
2019-02-21 06:58:34 +00:00
|
|
|
if (get.in_whitespace_after_token){
|
2019-02-21 04:43:25 +00:00
|
|
|
get.token_index += 1;
|
|
|
|
if (get.token_index < tokens->count){
|
|
|
|
Cpp_Token *token = tokens->tokens + get.token_index;
|
|
|
|
result = token->start + token->size;
|
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
2019-02-21 04:43:25 +00:00
|
|
|
else{
|
2019-02-21 06:58:34 +00:00
|
|
|
result = get.token_one_past_last;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
2019-02-21 04:43:25 +00:00
|
|
|
return(result);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Cpp_Token_Array
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_get_all_tokens(Application_Links *app, Arena *arena, Buffer_ID buffer_id){
|
2018-11-20 08:18:54 +00:00
|
|
|
Cpp_Token_Array array = {};
|
2019-04-01 02:41:39 +00:00
|
|
|
if (buffer_exists(app, buffer_id)){
|
|
|
|
b32 is_lexed = false;
|
2019-06-01 23:58:28 +00:00
|
|
|
if (buffer_get_setting(app, buffer_id, BufferSetting_Lex, &is_lexed)){
|
|
|
|
if (is_lexed){
|
|
|
|
buffer_token_count(app, buffer_id, &array.count);
|
|
|
|
array.max_count = array.count;
|
|
|
|
array.tokens = push_array(arena, Cpp_Token, array.count);
|
|
|
|
buffer_read_tokens(app, buffer_id, 0, array.count, array.tokens);
|
|
|
|
}
|
2019-04-01 02:41:39 +00:00
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
return(array);
|
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_boundary_seek(Application_Links *app, Buffer_ID buffer_id, Arena *scratch, i32 start_pos, b32 seek_forward, Seek_Boundary_Flag flags){
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 result = 0;
|
2017-01-23 06:19:43 +00:00
|
|
|
|
|
|
|
// TODO(allen): reduce duplication?
|
2019-06-01 23:58:28 +00:00
|
|
|
Temp_Memory temp = begin_temp(scratch);
|
2019-04-01 02:41:39 +00:00
|
|
|
if (buffer_exists(app, buffer_id)){
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 pos[4];
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 size = 0;
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 new_pos = 0;
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_get_size(app, buffer_id, &size);
|
2017-01-23 06:19:43 +00:00
|
|
|
|
|
|
|
if (start_pos < 0){
|
|
|
|
start_pos = 0;
|
|
|
|
}
|
|
|
|
else if (start_pos > size){
|
|
|
|
start_pos = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seek_forward){
|
2019-02-26 23:08:42 +00:00
|
|
|
for (i32 i = 0; i < ArrayCount(pos); ++i){
|
2019-02-21 06:58:34 +00:00
|
|
|
pos[i] = size + 1;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & BoundaryWhitespace){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[0] = buffer_seek_whitespace_right(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & BoundaryToken){
|
2019-04-01 02:41:39 +00:00
|
|
|
if (buffer_tokens_are_ready(app, buffer_id)){
|
2019-06-01 23:58:28 +00:00
|
|
|
Cpp_Token_Array array = buffer_get_all_tokens(app, scratch, buffer_id);
|
2019-02-21 04:43:25 +00:00
|
|
|
pos[1] = seek_token_right(&array, start_pos, size);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[1] = buffer_seek_whitespace_right(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & BoundaryAlphanumeric){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[2] = buffer_seek_alphanumeric_right(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
if (flags & BoundaryCamelCase){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[3] = buffer_seek_range_camel_right(app, buffer_id, start_pos, pos[2]);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if (flags & BoundaryCamelCase){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[3] = buffer_seek_alphanumeric_or_camel_right(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-21 06:58:34 +00:00
|
|
|
new_pos = size + 1;
|
2019-02-26 23:08:42 +00:00
|
|
|
for (i32 i = 0; i < ArrayCount(pos); ++i){
|
2019-02-21 06:58:34 +00:00
|
|
|
if (new_pos > pos[i]){
|
2017-01-23 06:19:43 +00:00
|
|
|
new_pos = pos[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
2019-02-26 23:08:42 +00:00
|
|
|
for (i32 i = 0; i < ArrayCount(pos); ++i){
|
2019-02-21 06:58:34 +00:00
|
|
|
pos[i] = -1;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & BoundaryWhitespace){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[0] = buffer_seek_whitespace_left(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & BoundaryToken){
|
2019-04-01 02:41:39 +00:00
|
|
|
if (buffer_tokens_are_ready(app, buffer_id)){
|
2019-06-01 23:58:28 +00:00
|
|
|
Cpp_Token_Array array = buffer_get_all_tokens(app, scratch, buffer_id);
|
2017-01-23 06:19:43 +00:00
|
|
|
pos[1] = seek_token_left(&array, start_pos);
|
|
|
|
}
|
|
|
|
else{
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[1] = buffer_seek_whitespace_left(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & BoundaryAlphanumeric){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[2] = buffer_seek_alphanumeric_left(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
if (flags & BoundaryCamelCase){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[3] = buffer_seek_range_camel_left(app, buffer_id, start_pos, pos[2]);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if (flags & BoundaryCamelCase){
|
2019-04-01 02:41:39 +00:00
|
|
|
pos[3] = buffer_seek_alphanumeric_or_camel_left(app, buffer_id, start_pos);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-21 06:58:34 +00:00
|
|
|
new_pos = -1;
|
2019-02-26 23:08:42 +00:00
|
|
|
for (i32 i = 0; i < ArrayCount(pos); ++i){
|
2019-02-21 06:58:34 +00:00
|
|
|
if (new_pos < pos[i]){
|
2017-01-23 06:19:43 +00:00
|
|
|
new_pos = pos[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result = new_pos;
|
|
|
|
}
|
2019-06-01 23:58:28 +00:00
|
|
|
end_temp(temp);
|
2017-01-23 06:19:43 +00:00
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2018-05-10 08:12:47 +00:00
|
|
|
////////////////////////////////
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2017-03-23 19:15:33 +00:00
|
|
|
void
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_delimiter_forward(Application_Links *app, Buffer_ID buffer_id, i32 pos, char delim, i32 *result){
|
|
|
|
if (buffer_exists(app, buffer_id)){
|
2017-01-23 06:19:43 +00:00
|
|
|
char chunk[1024];
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 size = sizeof(chunk);
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, size)){
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 still_looping = 1;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for(; pos < stream.end; ++pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char at_pos = stream.data[pos];
|
|
|
|
if (at_pos == delim){
|
|
|
|
*result = pos;
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while (still_looping);
|
|
|
|
}
|
|
|
|
}
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_get_size(app, buffer_id, result);
|
2017-01-23 06:19:43 +00:00
|
|
|
finished:;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_seek_delimiter_backward(Application_Links *app, Buffer_ID buffer_id, i32 pos, char delim, i32 *result){
|
|
|
|
if (buffer_exists(app, buffer_id)){
|
2017-01-23 06:19:43 +00:00
|
|
|
char chunk[1024];
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 size = sizeof(chunk);
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, size)){
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 still_looping = 1;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for(; pos >= stream.start; --pos){
|
2017-01-23 06:19:43 +00:00
|
|
|
char at_pos = stream.data[pos];
|
|
|
|
if (at_pos == delim){
|
|
|
|
*result = pos;
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while (still_looping);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*result = 0;
|
|
|
|
finished:;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_forward(Application_Links *app, Buffer_ID buffer_id, i32 pos, i32 end, String_Const_u8 needle_string, i32 *result){
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 buffer_size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &buffer_size);
|
|
|
|
if (buffer_size > end){
|
|
|
|
*result = buffer_size;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
*result = end;
|
|
|
|
}
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
Scratch_Block scratch(app);
|
|
|
|
if (0 < needle_string.size){
|
2019-04-01 02:41:39 +00:00
|
|
|
if (buffer_exists(app, buffer_id)){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 first_char = string_get_character(needle_string, 0);
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 *read_buffer = push_array(scratch, u8, needle_string.size);
|
|
|
|
String_Const_u8 read_str = SCu8(read_buffer, needle_string.size);
|
2017-01-23 06:19:43 +00:00
|
|
|
|
|
|
|
char chunk[1024];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2017-01-23 06:19:43 +00:00
|
|
|
stream.max_end = end;
|
|
|
|
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, sizeof(chunk))){
|
|
|
|
b32 still_looping = true;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for(; pos < stream.end; ++pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 at_pos = stream.data[pos];
|
2017-01-23 06:19:43 +00:00
|
|
|
if (at_pos == first_char){
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_read_range(app, buffer_id, pos, (i32)(pos + needle_string.size), (char*)read_buffer);
|
|
|
|
if (string_match(needle_string, read_str)){
|
2017-01-23 06:19:43 +00:00
|
|
|
*result = pos;
|
|
|
|
goto finished;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while (still_looping);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (end == 0){
|
2019-04-01 02:41:39 +00:00
|
|
|
*result = buffer_size;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
*result = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
finished:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_backward(Application_Links *app, Buffer_ID buffer_id, i32 pos, i32 min, String_Const_u8 needle_string, i32 *result){
|
|
|
|
Scratch_Block scratch(app);
|
2019-04-01 02:41:39 +00:00
|
|
|
*result = min - 1;
|
2019-06-01 23:58:28 +00:00
|
|
|
if (0 < needle_string.size && buffer_exists(app, buffer_id)){
|
|
|
|
u8 first_char = string_get_character(needle_string, 0);
|
|
|
|
|
|
|
|
u8 *read_buffer = push_array(scratch, u8, needle_string.size);
|
|
|
|
String_Const_u8 read_str = SCu8(read_buffer, needle_string.size);
|
|
|
|
|
2019-04-01 02:41:39 +00:00
|
|
|
char chunk[1024];
|
|
|
|
Stream_Chunk stream = {};
|
|
|
|
stream.min_start = min;
|
2019-06-01 23:58:28 +00:00
|
|
|
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, sizeof(chunk))){
|
2019-06-01 23:58:28 +00:00
|
|
|
b32 still_looping = true;
|
2019-04-01 02:41:39 +00:00
|
|
|
do{
|
|
|
|
for(; pos >= stream.start; --pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 at_pos = stream.data[pos];
|
2019-04-01 02:41:39 +00:00
|
|
|
if (at_pos == first_char){
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_read_range(app, buffer_id, pos, (i32)(pos + needle_string.size), (char*)read_buffer);
|
|
|
|
if (string_match(needle_string, read_str)){
|
2019-04-01 02:41:39 +00:00
|
|
|
*result = pos;
|
|
|
|
goto finished;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-01 02:41:39 +00:00
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while (still_looping);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
finished:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_insensitive_forward(Application_Links *app, Buffer_ID buffer_id, i32 pos, i32 end, String_Const_u8 needle_string, i32 *result){
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 buffer_size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &buffer_size);
|
|
|
|
if (buffer_size > end){
|
|
|
|
*result = buffer_size;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
*result = end;
|
|
|
|
}
|
2019-06-01 23:58:28 +00:00
|
|
|
|
|
|
|
Scratch_Block scratch(app);
|
|
|
|
if (0 < needle_string.size && buffer_exists(app, buffer_id)){
|
|
|
|
u8 first_char = character_to_upper(string_get_character(needle_string, 0));
|
|
|
|
|
|
|
|
u8 *read_buffer = push_array(scratch, u8, needle_string.size);
|
|
|
|
String_Const_u8 read_str = SCu8(read_buffer, needle_string.size);
|
|
|
|
|
|
|
|
char chunk[1024];
|
|
|
|
Stream_Chunk stream = {};
|
|
|
|
stream.max_end = end;
|
|
|
|
|
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, sizeof(chunk))){
|
|
|
|
b32 still_looping = true;
|
2019-04-01 02:41:39 +00:00
|
|
|
do{
|
|
|
|
for(; pos < stream.end; ++pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 at_pos = character_to_upper(stream.data[pos]);
|
2019-04-01 02:41:39 +00:00
|
|
|
if (at_pos == first_char){
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_read_range(app, buffer_id, pos, (i32)(pos + needle_string.size), (char*)read_buffer);
|
|
|
|
if (string_match_insensitive(needle_string, read_str)){
|
2019-04-01 02:41:39 +00:00
|
|
|
*result = pos;
|
|
|
|
goto finished;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-01 02:41:39 +00:00
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while (still_looping);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
finished:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_ID buffer_id, i32 pos, i32 min, String_Const_u8 needle_string, i32 *result){
|
|
|
|
Scratch_Block scratch(app);
|
2019-04-01 02:41:39 +00:00
|
|
|
*result = min - 1;
|
2019-06-01 23:58:28 +00:00
|
|
|
if (0 < needle_string.size && buffer_exists(app, buffer_id)){
|
|
|
|
u8 first_char = character_to_upper(string_get_character(needle_string, 0));
|
|
|
|
|
|
|
|
u8 *read_buffer = push_array(scratch, u8, needle_string.size);
|
|
|
|
String_Const_u8 read_str = SCu8(read_buffer, needle_string.size);
|
|
|
|
|
|
|
|
char chunk[1024];
|
|
|
|
Stream_Chunk stream = {};
|
|
|
|
stream.min_start = min;
|
|
|
|
|
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, pos, chunk, sizeof(chunk))){
|
|
|
|
b32 still_looping = true;
|
2019-04-01 02:41:39 +00:00
|
|
|
do{
|
|
|
|
for(; pos >= stream.start; --pos){
|
2019-06-01 23:58:28 +00:00
|
|
|
u8 at_pos = character_to_upper(stream.data[pos]);
|
2019-04-01 02:41:39 +00:00
|
|
|
if (at_pos == first_char){
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_read_range(app, buffer_id, pos, (i32)(pos + needle_string.size), (char*)read_buffer);
|
|
|
|
if (string_match_insensitive(needle_string, read_str)){
|
2019-04-01 02:41:39 +00:00
|
|
|
*result = pos;
|
|
|
|
goto finished;
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-01 02:41:39 +00:00
|
|
|
}
|
|
|
|
still_looping = backward_stream_chunk(&stream);
|
|
|
|
}while (still_looping);
|
2017-01-23 06:19:43 +00:00
|
|
|
}
|
|
|
|
finished:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-10 08:12:47 +00:00
|
|
|
////////////////////////////////
|
2017-11-29 23:00:14 +00:00
|
|
|
|
|
|
|
static void
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string(Application_Links *app, Buffer_ID buffer_id, i32 pos, i32 end, i32 min, String_Const_u8 str, i32 *result, Buffer_Seek_String_Flags flags){
|
2017-11-29 23:00:14 +00:00
|
|
|
switch (flags & 3){
|
|
|
|
case 0:
|
|
|
|
{
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_forward(app, buffer_id, pos, end, str, result);
|
2017-11-29 23:00:14 +00:00
|
|
|
}break;
|
|
|
|
|
|
|
|
case BufferSeekString_Backward:
|
|
|
|
{
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_backward(app, buffer_id, pos, min, str, result);
|
2017-11-29 23:00:14 +00:00
|
|
|
}break;
|
|
|
|
|
|
|
|
case BufferSeekString_CaseInsensitive:
|
|
|
|
{
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_insensitive_forward(app, buffer_id, pos, end, str, result);
|
2017-11-29 23:00:14 +00:00
|
|
|
}break;
|
|
|
|
|
|
|
|
case BufferSeekString_Backward|BufferSeekString_CaseInsensitive:
|
|
|
|
{
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_seek_string_insensitive_backward(app, buffer_id, pos, min, str, result);
|
2017-11-29 23:00:14 +00:00
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2018-05-10 08:12:47 +00:00
|
|
|
////////////////////////////////
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static b32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_line_is_blank(Application_Links *app, Buffer_ID buffer_id, i32 line){
|
2018-11-20 08:18:54 +00:00
|
|
|
Partial_Cursor start = {};
|
|
|
|
Partial_Cursor end = {};
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 result = false;
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 line_count = 0;
|
|
|
|
buffer_get_line_count(app, buffer_id, &line_count);
|
|
|
|
if (line <= line_count){
|
|
|
|
buffer_compute_cursor(app, buffer_id, seek_line_char(line, 1), &start);
|
|
|
|
buffer_compute_cursor(app, buffer_id, seek_line_char(line, -1), &end);
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static const i32 chunk_size = 1024;
|
2017-01-23 06:19:43 +00:00
|
|
|
char chunk[chunk_size];
|
2018-11-20 08:18:54 +00:00
|
|
|
Stream_Chunk stream = {};
|
2019-02-26 23:08:42 +00:00
|
|
|
i32 i = start.pos;
|
2017-01-23 06:19:43 +00:00
|
|
|
stream.max_end = end.pos;
|
|
|
|
|
|
|
|
result = true;
|
2019-04-01 02:41:39 +00:00
|
|
|
if (init_stream_chunk(&stream, app, buffer_id, i, chunk, chunk_size)){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 still_looping = false;
|
2017-01-23 06:19:43 +00:00
|
|
|
do{
|
2017-03-23 19:15:33 +00:00
|
|
|
for (;i < stream.end; ++i){
|
2017-01-23 06:19:43 +00:00
|
|
|
char c = stream.data[i];
|
2019-06-01 23:58:28 +00:00
|
|
|
if (!character_is_whitespace(c)){
|
2017-01-23 06:19:43 +00:00
|
|
|
result = false;
|
|
|
|
goto double_break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
still_looping = forward_stream_chunk(&stream);
|
|
|
|
}while(still_looping);
|
|
|
|
}
|
|
|
|
double_break:;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
static String_Const_u8
|
|
|
|
read_identifier_at_pos(Application_Links *app, Arena *arena, Buffer_ID buffer_id, i32 pos, Range *range_out){
|
|
|
|
String_Const_u8 result = {};
|
2017-03-29 16:32:06 +00:00
|
|
|
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 start = buffer_seek_alphanumeric_or_underscore_left(app, buffer_id, pos);
|
|
|
|
i32 end = buffer_seek_alphanumeric_or_underscore_right(app, buffer_id, start);
|
2017-03-29 16:32:06 +00:00
|
|
|
|
|
|
|
if (!(start <= pos && pos < end)){
|
2019-04-01 02:41:39 +00:00
|
|
|
end = buffer_seek_alphanumeric_or_underscore_right(app, buffer_id, pos);
|
|
|
|
start = buffer_seek_alphanumeric_or_underscore_left(app, buffer_id, end);
|
2017-03-29 16:32:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (start <= pos && pos < end){
|
2019-06-01 23:58:28 +00:00
|
|
|
if (range_out != 0){
|
|
|
|
*range_out = make_range(start, end);
|
2017-03-29 16:32:06 +00:00
|
|
|
}
|
2019-06-01 23:58:28 +00:00
|
|
|
result = scratch_read(app, arena, buffer_id, start, end);
|
2017-03-29 16:32:06 +00:00
|
|
|
}
|
|
|
|
|
2019-06-01 23:58:28 +00:00
|
|
|
return(result);
|
2017-03-29 16:32:06 +00:00
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2018-05-10 08:12:47 +00:00
|
|
|
////////////////////////////////
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
|
|
|
flip_dir(i32 dir){
|
2018-05-10 08:12:47 +00:00
|
|
|
if (dir == DirLeft){
|
2019-02-21 06:58:34 +00:00
|
|
|
dir = DirRight;
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-02-21 06:58:34 +00:00
|
|
|
dir = DirLeft;
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
2019-02-21 06:58:34 +00:00
|
|
|
return(dir);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 23:08:42 +00:00
|
|
|
static i32
|
2019-04-01 02:41:39 +00:00
|
|
|
buffer_boundary_seek(Application_Links *app, Buffer_ID buffer_id, i32 start_pos, i32 dir, Seek_Boundary_Flag flags){
|
2019-02-26 23:08:42 +00:00
|
|
|
b32 forward = (dir != DirLeft);
|
2019-06-01 23:58:28 +00:00
|
|
|
Arena *scratch = context_get_arena(app);
|
|
|
|
return(buffer_boundary_seek(app, buffer_id, scratch, start_pos, forward, flags));
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-04-06 21:13:49 +00:00
|
|
|
view_buffer_boundary_seek_set_pos(Application_Links *app, View_ID view, Buffer_ID buffer_id, i32 dir, u32 flags){
|
|
|
|
i32 cursor_pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &cursor_pos);
|
2019-06-01 23:58:28 +00:00
|
|
|
Arena *scratch = context_get_arena(app);
|
|
|
|
i32 pos = buffer_boundary_seek(app, buffer_id, scratch, cursor_pos, dir, flags);
|
2018-05-10 08:12:47 +00:00
|
|
|
view_set_cursor(app, view, seek_pos(pos), true);
|
2019-04-06 21:13:49 +00:00
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-04-06 21:13:49 +00:00
|
|
|
view_boundary_seek_set_pos(Application_Links *app, View_ID view, i32 dir, u32 flags){
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
2019-04-01 02:41:39 +00:00
|
|
|
view_buffer_boundary_seek_set_pos(app, view, buffer_id, dir, flags);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-02-26 23:08:42 +00:00
|
|
|
current_view_boundary_seek_set_pos(Application_Links *app, i32 dir, u32 flags){
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
|
|
|
view_boundary_seek_set_pos(app, view, dir, flags);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Range
|
2019-04-06 21:13:49 +00:00
|
|
|
view_buffer_boundary_range(Application_Links *app, View_ID view, Buffer_ID buffer_id, i32 dir, u32 flags){
|
|
|
|
i32 pos1 = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos1);
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 pos2 = buffer_boundary_seek(app, buffer_id, pos1, dir, flags);
|
2018-05-10 08:12:47 +00:00
|
|
|
return(make_range(pos1, pos2));
|
|
|
|
}
|
|
|
|
|
|
|
|
static Range
|
2019-04-06 21:13:49 +00:00
|
|
|
view_buffer_snipe_range(Application_Links *app, View_ID view, Buffer_ID buffer_id, i32 dir, u32 flags){
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 buffer_size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &buffer_size);
|
2019-02-21 06:58:34 +00:00
|
|
|
Range result = {};
|
2019-04-06 21:13:49 +00:00
|
|
|
i32 pos0 = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos0);
|
2019-04-01 02:41:39 +00:00
|
|
|
i32 pos1 = buffer_boundary_seek(app, buffer_id, pos0, dir, flags);
|
|
|
|
if (0 <= pos1 && pos1 <= buffer_size){
|
|
|
|
i32 pos2 = buffer_boundary_seek(app, buffer_id, pos1, flip_dir(dir), flags);
|
|
|
|
if (0 <= pos2 && pos2 <= buffer_size){
|
2019-02-21 06:58:34 +00:00
|
|
|
if (dir == DirLeft){
|
2019-06-01 23:58:28 +00:00
|
|
|
pos2 = clamp_bot(pos2, pos0);
|
2019-02-21 06:58:34 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-04-06 21:13:49 +00:00
|
|
|
pos2 = clamp_top(pos2, pos0);
|
2019-02-21 06:58:34 +00:00
|
|
|
}
|
|
|
|
result = make_range(pos1, pos2);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
}
|
2019-02-21 06:58:34 +00:00
|
|
|
return(result);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-02-26 23:08:42 +00:00
|
|
|
current_view_boundary_delete(Application_Links *app, i32 dir, u32 flags){
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessOpen, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessOpen, &buffer_id);
|
|
|
|
Range range = view_buffer_boundary_range(app, view, buffer_id, dir, flags);
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_replace_range(app, buffer_id, range, string_u8_litexpr(""));
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-02-26 23:08:42 +00:00
|
|
|
current_view_snipe_delete(Application_Links *app, i32 dir, u32 flags){
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessOpen, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessOpen, &buffer_id);
|
|
|
|
Range range = view_buffer_snipe_range(app, view, buffer_id, dir, flags);
|
2019-06-01 23:58:28 +00:00
|
|
|
buffer_replace_range(app, buffer_id, range, string_u8_litexpr(""));
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_whitespace_up)
|
|
|
|
CUSTOM_DOC("Seeks the cursor up to the next blank line.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
i32 new_pos = buffer_seek_whitespace_up(app, buffer_id, pos);
|
|
|
|
view_set_cursor(app, view, seek_pos(new_pos), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_whitespace_down)
|
|
|
|
CUSTOM_DOC("Seeks the cursor down to the next blank line.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
i32 new_pos = buffer_seek_whitespace_down(app, buffer_id, pos);
|
|
|
|
view_set_cursor(app, view, seek_pos(new_pos), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_beginning_of_textual_line)
|
|
|
|
CUSTOM_DOC("Seeks the cursor to the beginning of the line across all text.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
i32 new_pos = seek_line_beginning(app, buffer_id, pos);
|
|
|
|
view_set_cursor(app, view, seek_pos(new_pos), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_end_of_textual_line)
|
|
|
|
CUSTOM_DOC("Seeks the cursor to the end of the line across all text.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
i32 new_pos = seek_line_end(app, buffer_id, pos);
|
|
|
|
view_set_cursor(app, view, seek_pos(new_pos), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_beginning_of_line)
|
|
|
|
CUSTOM_DOC("Seeks the cursor to the beginning of the visual line.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
Full_Cursor cursor = {};
|
|
|
|
view_compute_cursor(app, view, seek_pos(pos), &cursor);
|
|
|
|
f32 y = cursor.wrapped_y;
|
|
|
|
view_set_cursor(app, view, seek_wrapped_xy(0.f, y, true), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_end_of_line)
|
|
|
|
CUSTOM_DOC("Seeks the cursor to the end of the visual line.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
Full_Cursor cursor = {};
|
|
|
|
view_compute_cursor(app, view, seek_pos(pos), &cursor);
|
|
|
|
f32 y = cursor.wrapped_y;
|
|
|
|
view_set_cursor(app, view, seek_wrapped_xy(max_f32, y, true), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_whitespace_up_end_line)
|
|
|
|
CUSTOM_DOC("Seeks the cursor up to the next blank line and places it at the end of the line.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
i32 new_pos = buffer_seek_whitespace_up(app, buffer_id, pos);
|
2019-04-01 02:41:39 +00:00
|
|
|
new_pos = seek_line_end(app, buffer_id, new_pos);
|
2019-04-06 21:13:49 +00:00
|
|
|
view_set_cursor(app, view, seek_pos(new_pos), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line)
|
|
|
|
CUSTOM_DOC("Seeks the cursor down to the next blank line and places it at the end of the line.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
2019-04-01 02:41:39 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
|
|
|
i32 pos = 0;
|
|
|
|
view_get_cursor_pos(app, view, &pos);
|
|
|
|
i32 new_pos = buffer_seek_whitespace_down(app, buffer_id, pos);
|
2019-04-01 02:41:39 +00:00
|
|
|
new_pos = seek_line_end(app, buffer_id, new_pos);
|
2019-04-06 21:13:49 +00:00
|
|
|
view_set_cursor(app, view, seek_pos(new_pos), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(goto_beginning_of_file)
|
|
|
|
CUSTOM_DOC("Sets the cursor to the beginning of the file.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
|
|
|
view_set_cursor(app, view, seek_pos(0), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(goto_end_of_file)
|
|
|
|
CUSTOM_DOC("Sets the cursor to the end of the file.")
|
|
|
|
{
|
2019-04-06 21:13:49 +00:00
|
|
|
View_ID view = 0;
|
|
|
|
get_active_view(app, AccessProtected, &view);
|
2019-04-02 20:06:49 +00:00
|
|
|
Buffer_ID buffer_id = 0;
|
2019-04-06 21:13:49 +00:00
|
|
|
view_get_buffer(app, view, AccessProtected, &buffer_id);
|
2019-04-02 20:06:49 +00:00
|
|
|
i32 size = 0;
|
|
|
|
buffer_get_size(app, buffer_id, &size);
|
2019-04-06 21:13:49 +00:00
|
|
|
view_set_cursor(app, view, seek_pos(size), true);
|
|
|
|
no_mark_snap_to_cursor_if_shift(app, view);
|
2018-05-10 08:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_whitespace_right)
|
|
|
|
CUSTOM_DOC("Seek right for the next boundary between whitespace and non-whitespace.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirRight, BoundaryWhitespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_whitespace_left)
|
|
|
|
CUSTOM_DOC("Seek left for the next boundary between whitespace and non-whitespace.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirLeft, BoundaryWhitespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_token_right)
|
|
|
|
CUSTOM_DOC("Seek right for the next end of a token.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirRight, BoundaryToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_token_left)
|
|
|
|
CUSTOM_DOC("Seek left for the next beginning of a token.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirLeft, BoundaryToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_white_or_token_right)
|
|
|
|
CUSTOM_DOC("Seek right for the next end of a token or boundary between whitespace and non-whitespace.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirRight, BoundaryToken|BoundaryWhitespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_white_or_token_left)
|
|
|
|
CUSTOM_DOC("Seek left for the next end of a token or boundary between whitespace and non-whitespace.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirLeft, BoundaryToken|BoundaryWhitespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_alphanumeric_right)
|
|
|
|
CUSTOM_DOC("Seek right for boundary between alphanumeric characters and non-alphanumeric characters.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirRight, BoundaryAlphanumeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_alphanumeric_left)
|
|
|
|
CUSTOM_DOC("Seek left for boundary between alphanumeric characters and non-alphanumeric characters.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirLeft, BoundaryAlphanumeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_alphanumeric_or_camel_right)
|
|
|
|
CUSTOM_DOC("Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirRight, BoundaryAlphanumeric|BoundaryCamelCase);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(seek_alphanumeric_or_camel_left)
|
|
|
|
CUSTOM_DOC("Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.")
|
|
|
|
{
|
|
|
|
current_view_boundary_seek_set_pos(app, DirLeft, BoundaryAlphanumeric|BoundaryCamelCase);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(backspace_word)
|
|
|
|
CUSTOM_DOC("Delete characters between the cursor position and the first alphanumeric boundary to the left.")
|
|
|
|
{
|
|
|
|
current_view_boundary_delete(app, DirLeft, BoundaryAlphanumeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(delete_word)
|
|
|
|
CUSTOM_DOC("Delete characters between the cursor position and the first alphanumeric boundary to the right.")
|
|
|
|
{
|
|
|
|
current_view_boundary_delete(app, DirRight, BoundaryAlphanumeric);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(snipe_token_or_word)
|
|
|
|
CUSTOM_DOC("Delete a single, whole token on or to the left of the cursor and post it to the clipboard.")
|
|
|
|
{
|
|
|
|
current_view_snipe_delete(app, DirLeft, BoundaryToken|BoundaryWhitespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
CUSTOM_COMMAND_SIG(snipe_token_or_word_right)
|
|
|
|
CUSTOM_DOC("Delete a single, whole token on or to the right of the cursor and post it to the clipboard.")
|
|
|
|
{
|
|
|
|
current_view_snipe_delete(app, DirRight, BoundaryToken|BoundaryWhitespace);
|
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
|
2019-02-21 04:43:25 +00:00
|
|
|
// BOTTOM
|
|
|
|
|
|
|
|
|