streaming
This commit is contained in:
parent
083b4409c5
commit
d3d02da40e
105
4ed.cpp
105
4ed.cpp
|
@ -213,37 +213,12 @@ COMMAND_DECL(write_character){
|
||||||
view->file->cursor_pos = view->cursor.pos;
|
view->file->cursor_pos = view->cursor.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal i32
|
|
||||||
seek_whitespace_right(u8 *data, i32 size, i32 pos){
|
|
||||||
while (pos < size && char_is_whitespace(data[pos])){
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
while (pos < size && !char_is_whitespace(data[pos])){
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal i32
|
|
||||||
seek_whitespace_left(u8 *data, i32 pos){
|
|
||||||
--pos;
|
|
||||||
while (pos > 0 && char_is_whitespace(data[pos])){
|
|
||||||
--pos;
|
|
||||||
}
|
|
||||||
while (pos >= 0 && !char_is_whitespace(data[pos])){
|
|
||||||
--pos;
|
|
||||||
}
|
|
||||||
++pos;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_DECL(seek_whitespace_right){
|
COMMAND_DECL(seek_whitespace_right){
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
|
||||||
i32 pos = seek_whitespace_right(
|
i32 pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos);
|
||||||
(u8*)file->buffer.data, file->buffer.size, view->cursor.pos);
|
|
||||||
|
|
||||||
view_cursor_move(view, pos);
|
view_cursor_move(view, pos);
|
||||||
}
|
}
|
||||||
|
@ -253,14 +228,13 @@ COMMAND_DECL(seek_whitespace_left){
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
|
||||||
i32 pos = seek_whitespace_left(
|
i32 pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos);
|
||||||
(u8*)file->buffer.data, view->cursor.pos);
|
|
||||||
|
|
||||||
view_cursor_move(view, pos);
|
view_cursor_move(view, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(allen): see if this becomes better by using buffer procudures directly
|
|
||||||
COMMAND_DECL(seek_whitespace_up){
|
COMMAND_DECL(seek_whitespace_up){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -286,9 +260,11 @@ COMMAND_DECL(seek_whitespace_up){
|
||||||
if (pos != 0) ++pos;
|
if (pos != 0) ++pos;
|
||||||
|
|
||||||
view_cursor_move(view, pos);
|
view_cursor_move(view, pos);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(seek_whitespace_down){
|
COMMAND_DECL(seek_whitespace_down){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -320,6 +296,7 @@ COMMAND_DECL(seek_whitespace_down){
|
||||||
else pos = prev_endline+1;
|
else pos = prev_endline+1;
|
||||||
|
|
||||||
view_cursor_move(view, pos);
|
view_cursor_move(view, pos);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal i32
|
internal i32
|
||||||
|
@ -374,6 +351,7 @@ COMMAND_DECL(seek_token_right){
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(seek_white_or_token_right){
|
COMMAND_DECL(seek_white_or_token_right){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -383,11 +361,13 @@ COMMAND_DECL(seek_white_or_token_right){
|
||||||
if (file->tokens_complete){
|
if (file->tokens_complete){
|
||||||
token_pos = seek_token_right(&file->token_stack, view->cursor.pos);
|
token_pos = seek_token_right(&file->token_stack, view->cursor.pos);
|
||||||
}
|
}
|
||||||
white_pos = seek_whitespace_right((u8*)file->buffer.data, file->buffer.size, view->cursor.pos);
|
white_pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos);
|
||||||
view_cursor_move(view, Min(token_pos, white_pos));
|
view_cursor_move(view, Min(token_pos, white_pos));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(seek_white_or_token_left){
|
COMMAND_DECL(seek_white_or_token_left){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -397,8 +377,9 @@ COMMAND_DECL(seek_white_or_token_left){
|
||||||
if (file->tokens_complete){
|
if (file->tokens_complete){
|
||||||
token_pos = seek_token_left(&file->token_stack, view->cursor.pos);
|
token_pos = seek_token_left(&file->token_stack, view->cursor.pos);
|
||||||
}
|
}
|
||||||
white_pos = seek_whitespace_left((u8*)file->buffer.data, view->cursor.pos);
|
white_pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos);
|
||||||
view_cursor_move(view, Max(token_pos, white_pos));
|
view_cursor_move(view, Max(token_pos, white_pos));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal i32
|
internal i32
|
||||||
|
@ -426,6 +407,7 @@ seek_alphanumeric_left(u8 *data, i32 pos){
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(seek_alphanumeric_right){
|
COMMAND_DECL(seek_alphanumeric_right){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -433,6 +415,7 @@ COMMAND_DECL(seek_alphanumeric_right){
|
||||||
i32 pos = seek_alphanumeric_right(
|
i32 pos = seek_alphanumeric_right(
|
||||||
(u8*)file->buffer.data, file->buffer.size, view->cursor.pos);
|
(u8*)file->buffer.data, file->buffer.size, view->cursor.pos);
|
||||||
view_cursor_move(view, pos);
|
view_cursor_move(view, pos);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(seek_alphanumeric_left){
|
COMMAND_DECL(seek_alphanumeric_left){
|
||||||
|
@ -446,6 +429,7 @@ COMMAND_DECL(seek_alphanumeric_left){
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(seek_alphanumeric_or_camel_right){
|
COMMAND_DECL(seek_alphanumeric_or_camel_right){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -467,6 +451,7 @@ COMMAND_DECL(seek_alphanumeric_or_camel_right){
|
||||||
}
|
}
|
||||||
|
|
||||||
view_cursor_move(view, camel_pos);
|
view_cursor_move(view, camel_pos);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(seek_alphanumeric_or_camel_left){
|
COMMAND_DECL(seek_alphanumeric_or_camel_left){
|
||||||
|
@ -552,6 +537,7 @@ COMMAND_DECL(copy){
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(cut){
|
COMMAND_DECL(cut){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -571,6 +557,7 @@ COMMAND_DECL(cut){
|
||||||
view_measure_wraps(&mem->general, view);
|
view_measure_wraps(&mem->general, view);
|
||||||
view_cursor_move(view, next_cursor_pos);
|
view_cursor_move(view, next_cursor_pos);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(paste){
|
COMMAND_DECL(paste){
|
||||||
|
@ -647,6 +634,7 @@ COMMAND_DECL(paste_next){
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(delete_chunk){
|
COMMAND_DECL(delete_chunk){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -661,6 +649,7 @@ COMMAND_DECL(delete_chunk){
|
||||||
view_cursor_move(view, next_cursor_pos);
|
view_cursor_move(view, next_cursor_pos);
|
||||||
view->mark = range.start;
|
view->mark = range.start;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(timeline_scrub){
|
COMMAND_DECL(timeline_scrub){
|
||||||
|
@ -811,9 +800,11 @@ app_open_file(App_Vars *vars, General_Memory *general, Panel *panel,
|
||||||
command_data->view = old_view;
|
command_data->view = old_view;
|
||||||
|
|
||||||
new_view->map = app_get_map(vars, target_file->base_map_id);
|
new_view->map = app_get_map(vars, target_file->base_map_id);
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
if (created_file && target_file->tokens_exist)
|
if (created_file && target_file->tokens_exist)
|
||||||
file_first_lex_parallel(general, target_file);
|
file_first_lex_parallel(general, target_file);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -886,8 +877,10 @@ COMMAND_DECL(reopen){
|
||||||
*file = temp_file;
|
*file = temp_file;
|
||||||
file->source_path.str = file->source_path_;
|
file->source_path.str = file->source_path_;
|
||||||
file->live_name.str = file->live_name_;
|
file->live_name.str = file->live_name_;
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
if (file->tokens_exist)
|
if (file->tokens_exist)
|
||||||
file_first_lex_parallel(&mem->general, file);
|
file_first_lex_parallel(&mem->general, file);
|
||||||
|
#endif
|
||||||
|
|
||||||
Partition old_part = command->part;
|
Partition old_part = command->part;
|
||||||
Temp_Memory temp = begin_temp_memory(&vars->mem.part);
|
Temp_Memory temp = begin_temp_memory(&vars->mem.part);
|
||||||
|
@ -1031,17 +1024,6 @@ COMMAND_DECL(toggle_line_wrap){
|
||||||
view_set_relative_scrolling(view, scrolling);
|
view_set_relative_scrolling(view, scrolling);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(toggle_endline_mode){
|
|
||||||
ProfileMomentFunction();
|
|
||||||
REQ_FILE_VIEW(view);
|
|
||||||
REQ_FILE(file, view);
|
|
||||||
USE_MEM(mem);
|
|
||||||
|
|
||||||
file_measure_starts(&mem->general, view->file);
|
|
||||||
view->cursor =
|
|
||||||
view_compute_cursor_from_pos(view, view->cursor.pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND_DECL(toggle_show_whitespace){
|
COMMAND_DECL(toggle_show_whitespace){
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
|
@ -1049,6 +1031,7 @@ COMMAND_DECL(toggle_show_whitespace){
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(toggle_tokens){
|
COMMAND_DECL(toggle_tokens){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -1060,6 +1043,7 @@ COMMAND_DECL(toggle_tokens){
|
||||||
else{
|
else{
|
||||||
file_first_lex_parallel(&mem->general, file);
|
file_first_lex_parallel(&mem->general, file);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
@ -1084,9 +1068,11 @@ case_change_range(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||||
data[i] += char_delta;
|
data[i] += char_delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
if (file->token_stack.tokens)
|
if (file->token_stack.tokens)
|
||||||
file_relex_parallel(mem, file, range.start, range.end, 0);
|
file_relex_parallel(mem, file, range.start, range.end, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1280,9 +1266,7 @@ COMMAND_DECL(move_left){
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
|
||||||
i32 pos = view->cursor.pos;
|
i32 pos = view->cursor.pos;
|
||||||
if (pos > 0){
|
if (pos > 0) --pos;
|
||||||
--pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
view_cursor_move(view, pos);
|
view_cursor_move(view, pos);
|
||||||
}
|
}
|
||||||
|
@ -1292,16 +1276,15 @@ COMMAND_DECL(move_right){
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
|
||||||
i32 size = file->buffer.size;
|
i32 size = buffer_size(&file->buffer);
|
||||||
i32 pos = view->cursor.pos;
|
i32 pos = view->cursor.pos;
|
||||||
if (pos < size){
|
if (pos < size) ++pos;
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
view_cursor_move(view, pos);
|
view_cursor_move(view, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(delete){
|
COMMAND_DECL(delete){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -1322,9 +1305,11 @@ COMMAND_DECL(delete){
|
||||||
view_cursor_move(view, next_cursor_pos);
|
view_cursor_move(view, next_cursor_pos);
|
||||||
if (view->mark >= end) view->mark -= shift;
|
if (view->mark >= end) view->mark -= shift;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(backspace){
|
COMMAND_DECL(backspace){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
REQ_FILE_VIEW(view);
|
REQ_FILE_VIEW(view);
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
|
@ -1346,6 +1331,7 @@ COMMAND_DECL(backspace){
|
||||||
view_cursor_move(view, next_cursor_pos);
|
view_cursor_move(view, next_cursor_pos);
|
||||||
if (view->mark >= end) view->mark -= shift;
|
if (view->mark >= end) view->mark -= shift;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_DECL(move_up){
|
COMMAND_DECL(move_up){
|
||||||
|
@ -1536,6 +1522,7 @@ COMMAND_DECL(set_settings){
|
||||||
REQ_FILE(file, view);
|
REQ_FILE(file, view);
|
||||||
USE_VARS(vars);
|
USE_VARS(vars);
|
||||||
USE_MEM(mem);
|
USE_MEM(mem);
|
||||||
|
AllowLocal(mem);
|
||||||
|
|
||||||
Command_Parameter *end = param_stack_end(&command->part);
|
Command_Parameter *end = param_stack_end(&command->part);
|
||||||
Command_Parameter *param = param_stack_first(&command->part, end);
|
Command_Parameter *param = param_stack_first(&command->part, end);
|
||||||
|
@ -1544,6 +1531,7 @@ COMMAND_DECL(set_settings){
|
||||||
switch (p){
|
switch (p){
|
||||||
case par_lex_as_cpp_file:
|
case par_lex_as_cpp_file:
|
||||||
{
|
{
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
int v = dynamic_to_bool(¶m->param.value);
|
int v = dynamic_to_bool(¶m->param.value);
|
||||||
if (file->tokens_exist){
|
if (file->tokens_exist){
|
||||||
if (!v) file_kill_tokens(&mem->general, file);
|
if (!v) file_kill_tokens(&mem->general, file);
|
||||||
|
@ -1551,6 +1539,7 @@ COMMAND_DECL(set_settings){
|
||||||
else{
|
else{
|
||||||
if (v) file_first_lex_parallel(&mem->general, file);
|
if (v) file_first_lex_parallel(&mem->general, file);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case par_wrap_lines:
|
case par_wrap_lines:
|
||||||
|
@ -1658,6 +1647,7 @@ extern "C"{
|
||||||
if (view){
|
if (view){
|
||||||
Editing_File *file = view->file;
|
Editing_File *file = view->file;
|
||||||
if (file && !file->is_dummy){
|
if (file && !file->is_dummy){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
Working_Set *working_set = cmd->working_set;
|
Working_Set *working_set = cmd->working_set;
|
||||||
buffer.file_id = (int)(file - working_set->files);
|
buffer.file_id = (int)(file - working_set->files);
|
||||||
buffer.size = file->buffer.size;
|
buffer.size = file->buffer.size;
|
||||||
|
@ -1669,6 +1659,7 @@ extern "C"{
|
||||||
buffer.file_cursor_pos = file->cursor_pos;
|
buffer.file_cursor_pos = file->cursor_pos;
|
||||||
buffer.is_lexed = file->tokens_exist;
|
buffer.is_lexed = file->tokens_exist;
|
||||||
buffer.map_id = file->base_map_id;
|
buffer.map_id = file->base_map_id;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1727,8 +1718,8 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co
|
||||||
map_add(commands, codes->page_up, MDFR_NONE, command_page_up);
|
map_add(commands, codes->page_up, MDFR_NONE, command_page_up);
|
||||||
map_add(commands, codes->page_down, MDFR_NONE, command_page_down);
|
map_add(commands, codes->page_down, MDFR_NONE, command_page_down);
|
||||||
|
|
||||||
map_add(commands, codes->right, MDFR_CTRL, command_seek_white_or_token_right);
|
map_add(commands, codes->right, MDFR_CTRL, command_seek_whitespace_right);
|
||||||
map_add(commands, codes->left, MDFR_CTRL, command_seek_white_or_token_left);
|
map_add(commands, codes->left, MDFR_CTRL, command_seek_whitespace_left);
|
||||||
map_add(commands, codes->up, MDFR_CTRL, command_seek_whitespace_up);
|
map_add(commands, codes->up, MDFR_CTRL, command_seek_whitespace_up);
|
||||||
map_add(commands, codes->down, MDFR_CTRL, command_seek_whitespace_down);
|
map_add(commands, codes->down, MDFR_CTRL, command_seek_whitespace_down);
|
||||||
|
|
||||||
|
@ -1748,7 +1739,6 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co
|
||||||
map_add(commands, 'H', MDFR_CTRL, command_history_forward);
|
map_add(commands, 'H', MDFR_CTRL, command_history_forward);
|
||||||
map_add(commands, 'd', MDFR_CTRL, command_delete_chunk);
|
map_add(commands, 'd', MDFR_CTRL, command_delete_chunk);
|
||||||
map_add(commands, 'l', MDFR_CTRL, command_toggle_line_wrap);
|
map_add(commands, 'l', MDFR_CTRL, command_toggle_line_wrap);
|
||||||
map_add(commands, 'L', MDFR_CTRL, command_toggle_endline_mode);
|
|
||||||
map_add(commands, '?', MDFR_CTRL, command_toggle_show_whitespace);
|
map_add(commands, '?', MDFR_CTRL, command_toggle_show_whitespace);
|
||||||
map_add(commands, '|', MDFR_CTRL, command_toggle_tokens);
|
map_add(commands, '|', MDFR_CTRL, command_toggle_tokens);
|
||||||
map_add(commands, 'u', MDFR_CTRL, command_to_uppercase);
|
map_add(commands, 'u', MDFR_CTRL, command_to_uppercase);
|
||||||
|
@ -1850,7 +1840,6 @@ setup_command_table(){
|
||||||
SET(interactive_kill_buffer);
|
SET(interactive_kill_buffer);
|
||||||
SET(kill_buffer);
|
SET(kill_buffer);
|
||||||
SET(toggle_line_wrap);
|
SET(toggle_line_wrap);
|
||||||
SET(toggle_endline_mode);
|
|
||||||
SET(to_uppercase);
|
SET(to_uppercase);
|
||||||
SET(to_lowercase);
|
SET(to_lowercase);
|
||||||
SET(toggle_show_whitespace);
|
SET(toggle_show_whitespace);
|
||||||
|
@ -2603,7 +2592,9 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
||||||
if (!view_->is_active) continue;
|
if (!view_->is_active) continue;
|
||||||
File_View *view = view_to_file_view(view_);
|
File_View *view = view_to_file_view(view_);
|
||||||
if (!view) continue;
|
if (!view) continue;
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
view_measure_wraps(&vars->mem.general, view);
|
view_measure_wraps(&vars->mem.general, view);
|
||||||
|
#endif
|
||||||
view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos);
|
view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos);
|
||||||
}
|
}
|
||||||
app_result.redraw = 1;
|
app_result.redraw = 1;
|
||||||
|
@ -3020,7 +3011,9 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
||||||
view_set_file(file_view, file.file, style,
|
view_set_file(file_view, file.file, style,
|
||||||
vars->hooks[hook_open_file], &command_data, app_links);
|
vars->hooks[hook_open_file], &command_data, app_links);
|
||||||
new_view->map = app_get_map(vars, file.file->base_map_id);
|
new_view->map = app_get_map(vars, file.file->base_map_id);
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
if (file.file->tokens_exist) file_first_lex_parallel(general, file.file);
|
if (file.file->tokens_exist) file_first_lex_parallel(general, file.file);
|
||||||
|
#endif
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case DACT_SWITCH:
|
case DACT_SWITCH:
|
||||||
|
@ -3131,12 +3124,14 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
||||||
if (vars->style.font_changed){
|
if (vars->style.font_changed){
|
||||||
vars->style.font_changed = 0;
|
vars->style.font_changed = 0;
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
Editing_File *file = vars->working_set.files;
|
Editing_File *file = vars->working_set.files;
|
||||||
for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){
|
for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){
|
||||||
if (file->buffer.data && !file->is_dummy){
|
if (file->buffer.data && !file->is_dummy){
|
||||||
file_measure_widths(&vars->mem.general, file, vars->style.font);
|
file_measure_widths(&vars->mem.general, file, vars->style.font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Panel *panel = panels;
|
Panel *panel = panels;
|
||||||
for (i32 panel_i = vars->layout.panel_count; panel_i > 0; --panel_i, ++panel){
|
for (i32 panel_i = vars->layout.panel_count; panel_i > 0; --panel_i, ++panel){
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
#include "buffer/4coder_golden_array.cpp"
|
#include "buffer/4coder_shared.cpp"
|
||||||
|
#include "buffer/4coder_gap_buffer.cpp"
|
||||||
|
#include "buffer/4coder_buffer_abstract.cpp"
|
||||||
|
|
||||||
struct Range{
|
struct Range{
|
||||||
i32 start, end;
|
i32 start, end;
|
||||||
|
@ -70,7 +72,7 @@ struct Undo_Data{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Editing_File{
|
struct Editing_File{
|
||||||
Buffer buffer;
|
Gap_Buffer buffer;
|
||||||
|
|
||||||
Undo_Data undo;
|
Undo_Data undo;
|
||||||
|
|
||||||
|
@ -1008,7 +1010,7 @@ struct File_View_Widget{
|
||||||
|
|
||||||
struct File_View{
|
struct File_View{
|
||||||
View view_base;
|
View view_base;
|
||||||
|
|
||||||
Delay *delay;
|
Delay *delay;
|
||||||
Editing_Layout *layout;
|
Editing_Layout *layout;
|
||||||
|
|
||||||
|
@ -1108,19 +1110,17 @@ internal bool32
|
||||||
file_save(Partition *part, Editing_File *file, u8 *filename){
|
file_save(Partition *part, Editing_File *file, u8 *filename){
|
||||||
bool32 result = 0;
|
bool32 result = 0;
|
||||||
Temp_Memory temp = begin_temp_memory(part);
|
Temp_Memory temp = begin_temp_memory(part);
|
||||||
Buffer temp_buffer;
|
i32 max = partition_remaining(part);
|
||||||
temp_buffer.max = partition_remaining(part);
|
i32 size = 0;
|
||||||
temp_buffer.size = 0;
|
char *data = push_array(part, char, max);
|
||||||
temp_buffer.data = push_array(part, char, temp_buffer.max);
|
i32 data_size = buffer_size(&file->buffer);
|
||||||
// TODO(allen): What about using this stringify loop to convert out?
|
for (Gap_Buffer_Stringify_Loop loop = buffer_stringify_loop(&file->buffer, 0, data_size, data_size);
|
||||||
for (Buffer_Stringify_Loop loop = buffer_stringify_loop(&file->buffer, 0, file->buffer.size, file->buffer.size);
|
|
||||||
buffer_stringify_good(&loop);
|
buffer_stringify_good(&loop);
|
||||||
buffer_stringify_next(&loop)){
|
buffer_stringify_next(&loop)){
|
||||||
memcpy(temp_buffer.data, loop.data, loop.size);
|
memcpy(data + size, loop.data, loop.size);
|
||||||
temp_buffer.size += loop.size;
|
size += loop.size;
|
||||||
buffer_eol_convert_out(&temp_buffer);
|
|
||||||
result = system_save_file(filename, temp_buffer.data, temp_buffer.size);
|
|
||||||
}
|
}
|
||||||
|
result = system_save_file(filename, data, size);
|
||||||
end_temp_memory(temp);
|
end_temp_memory(temp);
|
||||||
file_synchronize_times(file, filename);
|
file_synchronize_times(file, filename);
|
||||||
return result;
|
return result;
|
||||||
|
@ -1322,18 +1322,11 @@ view_measure_wraps(General_Memory *general, File_View *view){
|
||||||
general_memory_allocate(general, sizeof(real32)*max, BUBBLE_WRAPS);
|
general_memory_allocate(general, sizeof(real32)*max, BUBBLE_WRAPS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Font *font = view->style->font;
|
Font *font = view->style->font;
|
||||||
real32 line_height = (real32)font->height;
|
real32 line_height = (real32)font->height;
|
||||||
real32 max_width = view_compute_width(view);
|
real32 max_width = view_compute_width(view);
|
||||||
real32 *line_widths = file->buffer.line_widths;
|
buffer_measure_wrap_y(&file->buffer, view->line_wrap_y, line_height, max_width);
|
||||||
real32 *line_wraps = view->line_wrap_y;
|
|
||||||
i32 y_pos = 0;
|
|
||||||
for (i32 i = 0; i < line_count; ++i){
|
|
||||||
line_wraps[i] = y_pos*line_height;
|
|
||||||
i32 line_span = view_wrapped_line_span(line_widths[i], max_width);
|
|
||||||
y_pos += line_span;
|
|
||||||
}
|
|
||||||
|
|
||||||
view->line_count = line_count;
|
view->line_count = line_count;
|
||||||
}
|
}
|
||||||
|
@ -1351,22 +1344,15 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam
|
||||||
|
|
||||||
*file = {};
|
*file = {};
|
||||||
file->buffer.data = (char*)data;
|
file->buffer.data = (char*)data;
|
||||||
file->buffer.size = val.size;
|
|
||||||
file->buffer.max = request_size;
|
file->buffer.max = request_size;
|
||||||
|
gap_buffer_initialize(&file->buffer, val.str, val.size);
|
||||||
if (val.size > 0){
|
|
||||||
memcpy(data, val.str, val.size);
|
|
||||||
buffer_eol_convert_in(&file->buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
data[val.size] = 0;
|
|
||||||
|
|
||||||
file_synchronize_times(file, filename);
|
file_synchronize_times(file, filename);
|
||||||
file_init_strings(file);
|
file_init_strings(file);
|
||||||
file_set_name(file, filename);
|
file_set_name(file, filename);
|
||||||
|
|
||||||
file->base_map_id = mapid_file;
|
file->base_map_id = mapid_file;
|
||||||
|
|
||||||
file_measure_starts(general, file);
|
file_measure_starts(general, file);
|
||||||
file_measure_widths(general, file, font);
|
file_measure_widths(general, file, font);
|
||||||
file->font = font;
|
file->font = font;
|
||||||
|
@ -1471,7 +1457,7 @@ file_close(General_Memory *general, Editing_File *file){
|
||||||
internal void
|
internal void
|
||||||
file_get_dummy(Editing_File *file){
|
file_get_dummy(Editing_File *file){
|
||||||
*file = {};
|
*file = {};
|
||||||
file->buffer.data = (char*)&file->buffer.size;
|
file->buffer.data = (char*)&file->buffer.size1;
|
||||||
file->is_dummy = 1;
|
file->is_dummy = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1479,6 +1465,7 @@ struct Shift_Information{
|
||||||
i32 start, end, amount;
|
i32 start, end, amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
internal
|
internal
|
||||||
JOB_CALLBACK(job_full_lex){
|
JOB_CALLBACK(job_full_lex){
|
||||||
Editing_File *file = (Editing_File*)data[0];
|
Editing_File *file = (Editing_File*)data[0];
|
||||||
|
@ -1541,6 +1528,7 @@ JOB_CALLBACK(job_full_lex){
|
||||||
file->tokens_complete = 1;
|
file->tokens_complete = 1;
|
||||||
file->still_lexing = 0;
|
file->still_lexing = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
file_kill_tokens(General_Memory *general, Editing_File *file){
|
file_kill_tokens(General_Memory *general, Editing_File *file){
|
||||||
|
@ -1555,9 +1543,9 @@ file_kill_tokens(General_Memory *general, Editing_File *file){
|
||||||
file->token_stack = {};
|
file->token_stack = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
internal void
|
internal void
|
||||||
file_first_lex_parallel(General_Memory *general, Editing_File *file){
|
file_first_lex_parallel(General_Memory *general, Editing_File *file){
|
||||||
#if 1
|
|
||||||
Assert(file->token_stack.tokens == 0);
|
Assert(file->token_stack.tokens == 0);
|
||||||
|
|
||||||
file->tokens_complete = 0;
|
file->tokens_complete = 0;
|
||||||
|
@ -1570,9 +1558,6 @@ file_first_lex_parallel(General_Memory *general, Editing_File *file){
|
||||||
job.data[1] = general;
|
job.data[1] = general;
|
||||||
job.memory_request = Kbytes(64);
|
job.memory_request = Kbytes(64);
|
||||||
file->lex_job = system_post_job(BACKGROUND_THREADS, job);
|
file->lex_job = system_post_job(BACKGROUND_THREADS, job);
|
||||||
#else
|
|
||||||
file_kill_tokens(general, file);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
@ -1659,17 +1644,18 @@ file_relex_parallel(Mem_Options *mem, Editing_File *file,
|
||||||
file->lex_job = system_post_job(BACKGROUND_THREADS, job);
|
file->lex_job = system_post_job(BACKGROUND_THREADS, job);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
internal bool32
|
internal bool32
|
||||||
file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_size){
|
file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_size){
|
||||||
bool32 result = 1;
|
bool32 result = 1;
|
||||||
i32 target_size = file->buffer.size + additional_size + 1;
|
i32 size = buffer_size(&file->buffer);
|
||||||
|
i32 target_size = size + additional_size + 1;
|
||||||
if (target_size >= file->buffer.max){
|
if (target_size >= file->buffer.max){
|
||||||
i32 request_size = LargeRoundUp(target_size*2, Kbytes(256));
|
i32 request_size = LargeRoundUp(target_size*2, Kbytes(256));
|
||||||
char *new_data = (char*)
|
char *new_data = (char*)
|
||||||
general_memory_reallocate(general, file->buffer.data, file->buffer.size, request_size, BUBBLE_BUFFER);
|
general_memory_reallocate(general, file->buffer.data, size, request_size, BUBBLE_BUFFER);
|
||||||
if (new_data){
|
if (new_data){
|
||||||
new_data[file->buffer.size] = 0;
|
|
||||||
file->buffer.data = new_data;
|
file->buffer.data = new_data;
|
||||||
file->buffer.max = request_size;
|
file->buffer.max = request_size;
|
||||||
}
|
}
|
||||||
|
@ -1754,6 +1740,7 @@ struct Edit_Spec{
|
||||||
Edit_Step step;
|
Edit_Step step;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
internal Edit_Step*
|
internal Edit_Step*
|
||||||
file_post_undo(General_Memory *general, Editing_File *file,
|
file_post_undo(General_Memory *general, Editing_File *file,
|
||||||
Edit_Step step, bool32 do_merge, bool32 can_merge){
|
Edit_Step step, bool32 do_merge, bool32 can_merge){
|
||||||
|
@ -1957,6 +1944,7 @@ file_post_history(General_Memory *general, Editing_File *file,
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline Full_Cursor
|
inline Full_Cursor
|
||||||
view_compute_cursor_from_pos(File_View *view, i32 pos){
|
view_compute_cursor_from_pos(File_View *view, i32 pos){
|
||||||
|
@ -2066,11 +2054,12 @@ view_set_file(File_View *view, Editing_File *file, Style *style,
|
||||||
view->file = file;
|
view->file = file;
|
||||||
|
|
||||||
General_Memory *general = &view->view_base.mem->general;
|
General_Memory *general = &view->view_base.mem->general;
|
||||||
|
AllowLocal(general);
|
||||||
Font *font = style->font;
|
Font *font = style->font;
|
||||||
view->style = style;
|
view->style = style;
|
||||||
view->font_advance = font->advance;
|
view->font_advance = font->advance;
|
||||||
view->font_height = font->height;
|
view->font_height = font->height;
|
||||||
|
|
||||||
view_measure_wraps(general, view);
|
view_measure_wraps(general, view);
|
||||||
|
|
||||||
view->cursor = {};
|
view->cursor = {};
|
||||||
|
@ -2219,6 +2208,7 @@ enum History_Mode{
|
||||||
internal void
|
internal void
|
||||||
view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str,
|
view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str,
|
||||||
History_Mode history_mode, i32 next_cursor){
|
History_Mode history_mode, i32 next_cursor){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
General_Memory *general = &mem->general;
|
General_Memory *general = &mem->general;
|
||||||
|
|
||||||
#if FRED_SLOW
|
#if FRED_SLOW
|
||||||
|
@ -2387,6 +2377,7 @@ view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step
|
||||||
}
|
}
|
||||||
|
|
||||||
if (history_mode == hist_normal) file->undo.edit_history_cursor = file->undo.history.edit_count;
|
if (history_mode == hist_normal) file->undo.edit_history_cursor = file->undo.history.edit_count;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline b32
|
inline b32
|
||||||
|
@ -2431,28 +2422,36 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||||
i32 str_len = spec.step.edit.len;
|
i32 str_len = spec.step.edit.len;
|
||||||
|
|
||||||
i32 shift_amount;
|
i32 shift_amount;
|
||||||
while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount))
|
while (gap_buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount))
|
||||||
file_grow_as_needed(general, file, shift_amount);
|
file_grow_as_needed(general, file, shift_amount);
|
||||||
|
|
||||||
// NOTE(allen): fixing stuff afterwards
|
// NOTE(allen): fixing stuff afterwards
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
if (file->tokens_exist)
|
if (file->tokens_exist)
|
||||||
file_relex_parallel(mem, file, start, end, shift_amount);
|
file_relex_parallel(mem, file, start, end, shift_amount);
|
||||||
|
#endif
|
||||||
|
|
||||||
i32 line_start = buffer_get_line_index(&file->buffer, start, 0, file->buffer.line_count);
|
i32 line_start = buffer_get_line_index(&file->buffer, start, 0, file->buffer.line_count);
|
||||||
i32 line_end = buffer_get_line_index(&file->buffer, end, 0, file->buffer.line_count);
|
i32 line_end = buffer_get_line_index(&file->buffer, end, 0, file->buffer.line_count);
|
||||||
i32 replaced_line_count = line_end - line_start;
|
i32 replaced_line_count = line_end - line_start;
|
||||||
|
|
||||||
// TODO(allen): check this
|
|
||||||
i32 new_line_count = file_count_newlines(file, start, start+str_len);
|
i32 new_line_count = file_count_newlines(file, start, start+str_len);
|
||||||
|
|
||||||
|
|
||||||
i32 line_shift = new_line_count - replaced_line_count;
|
i32 line_shift = new_line_count - replaced_line_count;
|
||||||
|
|
||||||
file_remeasure_starts(general, file, line_start, line_end, line_shift, shift_amount);
|
file_remeasure_starts(general, file, line_start, line_end, line_shift, shift_amount);
|
||||||
file_remeasure_widths(general, file, file->font, line_start, line_end, line_shift);
|
file_remeasure_widths(general, file, file->font, line_start, line_end, line_shift);
|
||||||
|
|
||||||
Temp_Memory cursor_temp = begin_temp_memory(&mem->part);
|
|
||||||
i32 panel_count = layout->panel_count;
|
i32 panel_count = layout->panel_count;
|
||||||
|
Panel *current_panel = layout->panels;
|
||||||
|
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
|
||||||
|
File_View *current_view = view_to_file_view(current_panel->view);
|
||||||
|
if (current_view && current_view->file == file){
|
||||||
|
view_measure_wraps(general, current_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
|
i32 cursor_count = 0;
|
||||||
|
Temp_Memory cursor_temp = begin_temp_memory(&mem->part);
|
||||||
i32 cursor_max = layout->panel_max_count * 2;
|
i32 cursor_max = layout->panel_max_count * 2;
|
||||||
Cursor_With_Index *cursors = push_array(&mem->part, Cursor_With_Index, cursor_max);
|
Cursor_With_Index *cursors = push_array(&mem->part, Cursor_With_Index, cursor_max);
|
||||||
|
|
||||||
|
@ -2490,11 +2489,13 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
end_temp_memory(cursor_temp);
|
end_temp_memory(cursor_temp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||||
Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){
|
Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
Assert(file);
|
Assert(file);
|
||||||
ProfileMomentFunction();
|
ProfileMomentFunction();
|
||||||
|
|
||||||
|
@ -2586,6 +2587,7 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||||
}
|
}
|
||||||
end_temp_memory(cursor_temp);
|
end_temp_memory(cursor_temp);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -2709,15 +2711,18 @@ view_history_step(Mem_Options *mem, Editing_Layout *layout, File_View *view, His
|
||||||
// TODO(allen): should these still be view operations?
|
// TODO(allen): should these still be view operations?
|
||||||
internal i32
|
internal i32
|
||||||
view_find_end_of_line(File_View *view, i32 pos){
|
view_find_end_of_line(File_View *view, i32 pos){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
Editing_File *file = view->file;
|
Editing_File *file = view->file;
|
||||||
char *data = file->buffer.data;
|
char *data = file->buffer.data;
|
||||||
while (pos < file->buffer.size && data[pos] != '\n') ++pos;
|
while (pos < file->buffer.size && data[pos] != '\n') ++pos;
|
||||||
if (pos > file->buffer.size) pos = file->buffer.size;
|
if (pos > file->buffer.size) pos = file->buffer.size;
|
||||||
|
#endif
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal i32
|
internal i32
|
||||||
view_find_beginning_of_line(File_View *view, i32 pos){
|
view_find_beginning_of_line(File_View *view, i32 pos){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
Editing_File *file = view->file;
|
Editing_File *file = view->file;
|
||||||
char *data = file->buffer.data;
|
char *data = file->buffer.data;
|
||||||
if (pos > 0){
|
if (pos > 0){
|
||||||
|
@ -2725,11 +2730,13 @@ view_find_beginning_of_line(File_View *view, i32 pos){
|
||||||
while (pos > 0 && data[pos] != '\n') --pos;
|
while (pos > 0 && data[pos] != '\n') --pos;
|
||||||
if (pos != 0) ++pos;
|
if (pos != 0) ++pos;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal i32
|
internal i32
|
||||||
view_find_beginning_of_next_line(File_View *view, i32 pos){
|
view_find_beginning_of_next_line(File_View *view, i32 pos){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
Editing_File *file = view->file;
|
Editing_File *file = view->file;
|
||||||
char *data = file->buffer.data;
|
char *data = file->buffer.data;
|
||||||
while (pos < file->buffer.size &&
|
while (pos < file->buffer.size &&
|
||||||
|
@ -2739,6 +2746,7 @@ view_find_beginning_of_next_line(File_View *view, i32 pos){
|
||||||
if (pos < file->buffer.size){
|
if (pos < file->buffer.size){
|
||||||
++pos;
|
++pos;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2847,6 +2855,7 @@ enum Endline_Convert_Type{
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout){
|
view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout){
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
Editing_File *file = view->file;
|
Editing_File *file = view->file;
|
||||||
Assert(file && !file->is_dummy);
|
Assert(file && !file->is_dummy);
|
||||||
Partition *part = &mem->part;
|
Partition *part = &mem->part;
|
||||||
|
@ -2917,6 +2926,7 @@ view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
end_temp_memory(temp);
|
end_temp_memory(temp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal u32*
|
internal u32*
|
||||||
|
@ -3469,14 +3479,14 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
|
||||||
#if 1
|
#if 1
|
||||||
Partition *part = &view_->mem->part;
|
Partition *part = &view_->mem->part;
|
||||||
Temp_Memory temp = begin_temp_memory(part);
|
Temp_Memory temp = begin_temp_memory(part);
|
||||||
|
|
||||||
partition_align(part, 4);
|
partition_align(part, 4);
|
||||||
i32 max = partition_remaining(part) / sizeof(Buffer_Render_Item);
|
i32 max = partition_remaining(part) / sizeof(Buffer_Render_Item);
|
||||||
Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max);
|
Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max);
|
||||||
|
|
||||||
i32 count;
|
i32 count;
|
||||||
buffer_get_render_data(&file->buffer, view->line_wrap_y, items, max, &count,
|
buffer_get_render_data(&file->buffer, view->line_wrap_y, items, max, &count,
|
||||||
(real32)rect.x0, (real32)rect.y0, view->scroll_x, view->scroll_y, view->unwrapped_lines,
|
(real32)rect.x0, (real32)rect.y0, view->scroll_x, view->scroll_y, !view->unwrapped_lines,
|
||||||
(real32)max_x, (real32)max_y, opad.data, opad.stride, (real32)font->height);
|
(real32)max_x, (real32)max_y, opad.data, opad.stride, (real32)font->height);
|
||||||
Assert(count > 0);
|
Assert(count > 0);
|
||||||
|
|
||||||
|
@ -3494,7 +3504,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
|
||||||
cursor_color = style->main.cursor_color;
|
cursor_color = style->main.cursor_color;
|
||||||
at_cursor_color = style->main.at_cursor_color;
|
at_cursor_color = style->main.at_cursor_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 token_i = 0;
|
i32 token_i = 0;
|
||||||
u32 main_color = style->main.default_color;
|
u32 main_color = style->main.default_color;
|
||||||
if (tokens_use){
|
if (tokens_use){
|
||||||
|
@ -3502,7 +3512,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
|
||||||
main_color = *style_get_color(style, token_stack.tokens[result.token_index]);
|
main_color = *style_get_color(style, token_stack.tokens[result.token_index]);
|
||||||
token_i = result.token_index + 1;
|
token_i = result.token_index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 mark_color = style->main.mark_color;
|
u32 mark_color = style->main.mark_color;
|
||||||
Buffer_Render_Item *item = items;
|
Buffer_Render_Item *item = items;
|
||||||
i32 prev_ind = -1;
|
i32 prev_ind = -1;
|
||||||
|
@ -3523,7 +3533,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
if (current_token.type == CPP_TOKEN_JUNK &&
|
if (current_token.type == CPP_TOKEN_JUNK &&
|
||||||
i >= current_token.start && i <= current_token.start + current_token.size){
|
i >= current_token.start && i <= current_token.start + current_token.size){
|
||||||
highlight_color = style->main.highlight_junk_color;
|
highlight_color = style->main.highlight_junk_color;
|
||||||
|
@ -3863,6 +3873,7 @@ internal
|
||||||
HANDLE_COMMAND_SIG(handle_command_file_view){
|
HANDLE_COMMAND_SIG(handle_command_file_view){
|
||||||
File_View *file_view = (File_View*)(view);
|
File_View *file_view = (File_View*)(view);
|
||||||
Editing_File *file = file_view->file;
|
Editing_File *file = file_view->file;
|
||||||
|
AllowLocal(file);
|
||||||
|
|
||||||
switch (file_view->widget.type){
|
switch (file_view->widget.type){
|
||||||
case FWIDG_NONE:
|
case FWIDG_NONE:
|
||||||
|
@ -3878,6 +3889,7 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
|
||||||
|
|
||||||
case FWIDG_SEARCH:
|
case FWIDG_SEARCH:
|
||||||
{
|
{
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
String *string = &file_view->isearch.str;
|
String *string = &file_view->isearch.str;
|
||||||
Single_Line_Input_Step result =
|
Single_Line_Input_Step result =
|
||||||
app_single_line_input_step(codes, key, string);
|
app_single_line_input_step(codes, key, string);
|
||||||
|
@ -3965,6 +3977,7 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
|
||||||
file_view->show_temp_highlight = 0;
|
file_view->show_temp_highlight = 0;
|
||||||
view_set_widget(file_view, FWIDG_NONE);
|
view_set_widget(file_view, FWIDG_NONE);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case FWIDG_GOTO_LINE:
|
case FWIDG_GOTO_LINE:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,541 @@
|
||||||
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
|
* Four Tech
|
||||||
|
*
|
||||||
|
* public domain -- no warranty is offered or implied; use this code at your own risk
|
||||||
|
*
|
||||||
|
* 16.10.2015
|
||||||
|
*
|
||||||
|
* Buffer data object
|
||||||
|
* type - Golden Array
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
|
#define Buffer_Type Buffer
|
||||||
|
#else
|
||||||
|
#define Buffer_Type Gap_Buffer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CAT_(a,b) a##b
|
||||||
|
#define CAT(a,b) CAT_(a,b)
|
||||||
|
|
||||||
|
#define Buffer_Stringify_Type CAT(Buffer_Type, _Stringify_Loop)
|
||||||
|
#define Buffer_Backify_Type CAT(Buffer_Type, _Backify_Loop)
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
buffer_count_newlines(Buffer_Type *buffer, int start, int end){
|
||||||
|
Buffer_Stringify_Type loop;
|
||||||
|
int i;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
assert_4tech(0 <= start);
|
||||||
|
assert_4tech(start <= end);
|
||||||
|
assert_4tech(end < buffer_size(buffer));
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
for (loop = buffer_stringify_loop(buffer, start, end, end - start);
|
||||||
|
buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
for (i = 0; i < loop.size; ++i){
|
||||||
|
count += (loop.data[i] == '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
buffer_seek_whitespace_right(Buffer_Type *buffer, int pos){
|
||||||
|
Buffer_Stringify_Type loop;
|
||||||
|
char *data;
|
||||||
|
int end;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = buffer_size(buffer);
|
||||||
|
loop = buffer_stringify_loop(buffer, pos, size, size);
|
||||||
|
|
||||||
|
for (;buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
end = loop.size + loop.absolute_pos;
|
||||||
|
data = loop.data - loop.absolute_pos;
|
||||||
|
for (; pos < end && is_whitespace(data[pos]); ++pos);
|
||||||
|
if (!is_whitespace(data[pos])) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
end = loop.size + loop.absolute_pos;
|
||||||
|
data = loop.data - loop.absolute_pos;
|
||||||
|
for (; pos < end && !is_whitespace(data[pos]); ++pos);
|
||||||
|
if (is_whitespace(data[pos])) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
buffer_seek_whitespace_left(Buffer_Type *buffer, int pos){
|
||||||
|
Buffer_Backify_Type loop;
|
||||||
|
char *data;
|
||||||
|
int end;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = buffer_size(buffer);
|
||||||
|
loop = buffer_backify_loop(buffer, pos, 0, size);
|
||||||
|
|
||||||
|
for (;buffer_backify_good(&loop);
|
||||||
|
buffer_backify_next(&loop)){
|
||||||
|
end = loop.absolute_pos;
|
||||||
|
data = loop.data - end;
|
||||||
|
for (; pos > end && is_whitespace(data[pos]); --pos);
|
||||||
|
if (!is_whitespace(data[pos])) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;buffer_backify_good(&loop);
|
||||||
|
buffer_backify_next(&loop)){
|
||||||
|
end = loop.absolute_pos;
|
||||||
|
data = loop.data - end;
|
||||||
|
for (; pos > end && !is_whitespace(data[pos]); --pos);
|
||||||
|
if (is_whitespace(data[pos])) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int i;
|
||||||
|
int count;
|
||||||
|
int start;
|
||||||
|
} Buffer_Measure_Starts;
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
buffer_measure_starts(Buffer_Measure_Starts *state, Buffer_Type *buffer){
|
||||||
|
Buffer_Stringify_Type loop;
|
||||||
|
int *starts;
|
||||||
|
int max;
|
||||||
|
char *data;
|
||||||
|
int size, end;
|
||||||
|
int start, count, i;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
size = buffer_size(buffer);
|
||||||
|
starts = buffer->line_starts;
|
||||||
|
max = buffer->line_max;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
i = state->i;
|
||||||
|
count = state->count;
|
||||||
|
start = state->start;
|
||||||
|
|
||||||
|
for (loop = buffer_stringify_loop(buffer, i, size, size);
|
||||||
|
buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
end = loop.size + loop.absolute_pos;
|
||||||
|
data = loop.data - loop.absolute_pos;
|
||||||
|
for (; i < end; ++i){
|
||||||
|
if (data[i] == '\n'){
|
||||||
|
if (count == max){
|
||||||
|
result = 1;
|
||||||
|
goto buffer_measure_starts_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
starts[count++] = start;
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == size){
|
||||||
|
starts[count++] = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_measure_starts_end:
|
||||||
|
state->i = i;
|
||||||
|
state->count = count;
|
||||||
|
state->start = start;
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech void
|
||||||
|
buffer_remeasure_starts(Buffer_Type *buffer, int line_start, int line_end, int line_shift, int text_shift){
|
||||||
|
Buffer_Stringify_Type loop;
|
||||||
|
int *starts;
|
||||||
|
int line_count;
|
||||||
|
char *data;
|
||||||
|
int size, end;
|
||||||
|
int line_i, char_i, start;
|
||||||
|
|
||||||
|
starts = buffer->line_starts;
|
||||||
|
line_count = buffer->line_count;
|
||||||
|
|
||||||
|
assert_4tech(0 <= line_start);
|
||||||
|
assert_4tech(line_start <= line_end);
|
||||||
|
assert_4tech(line_end < line_count);
|
||||||
|
assert_4tech(line_count + line_shift <= buffer->line_max);
|
||||||
|
|
||||||
|
++line_end;
|
||||||
|
if (text_shift != 0){
|
||||||
|
line_i = line_end;
|
||||||
|
starts += line_i;
|
||||||
|
for (; line_i < line_count; ++line_i, ++starts){
|
||||||
|
*starts += text_shift;
|
||||||
|
}
|
||||||
|
starts = buffer->line_starts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_shift != 0){
|
||||||
|
memmove_4tech(starts + line_end + line_shift, starts + line_end,
|
||||||
|
sizeof(int)*(line_count - line_end));
|
||||||
|
line_count += line_shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_end += line_shift;
|
||||||
|
size = buffer_size(buffer);
|
||||||
|
char_i = starts[line_start];
|
||||||
|
line_i = line_start;
|
||||||
|
start = char_i;
|
||||||
|
|
||||||
|
for (loop = buffer_stringify_loop(buffer, char_i, size, size);
|
||||||
|
buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
end = loop.size + loop.absolute_pos;
|
||||||
|
data = loop.data - loop.absolute_pos;
|
||||||
|
for (; char_i < end; ++char_i){
|
||||||
|
if (data[char_i] == '\n'){
|
||||||
|
starts[line_i++] = start;
|
||||||
|
start = char_i + 1;
|
||||||
|
if (line_i >= line_end && start == starts[line_i]) goto buffer_remeasure_starts_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (char_i == size){
|
||||||
|
starts[line_i++] = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_remeasure_starts_end:
|
||||||
|
assert_4tech(line_count >= 1);
|
||||||
|
buffer->line_count = line_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech void
|
||||||
|
buffer_remeasure_widths(Buffer_Type *buffer, void *advance_data, int stride,
|
||||||
|
int line_start, int line_end, int line_shift){
|
||||||
|
Buffer_Stringify_Type loop;
|
||||||
|
int *starts;
|
||||||
|
float *widths;
|
||||||
|
int line_count;
|
||||||
|
char *data;
|
||||||
|
int size, end;
|
||||||
|
int i, j;
|
||||||
|
float width;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
starts = buffer->line_starts;
|
||||||
|
widths = buffer->line_widths;
|
||||||
|
line_count = buffer->line_count;
|
||||||
|
|
||||||
|
assert_4tech(0 <= line_start);
|
||||||
|
assert_4tech(line_start <= line_end);
|
||||||
|
assert_4tech(line_end < line_count);
|
||||||
|
assert_4tech(line_count <= buffer->widths_max);
|
||||||
|
|
||||||
|
++line_end;
|
||||||
|
if (line_shift != 0){
|
||||||
|
memmove_4tech(widths + line_end + line_shift, widths + line_end,
|
||||||
|
sizeof(float)*(line_count - line_end));
|
||||||
|
}
|
||||||
|
|
||||||
|
line_end += line_shift;
|
||||||
|
i = line_start;
|
||||||
|
j = starts[i];
|
||||||
|
|
||||||
|
if (line_end == line_count) size = buffer_size(buffer);
|
||||||
|
else size = starts[line_end];
|
||||||
|
|
||||||
|
width = 0;
|
||||||
|
|
||||||
|
for (loop = buffer_stringify_loop(buffer, j, size, size);
|
||||||
|
buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
end = loop.size + loop.absolute_pos;
|
||||||
|
data = loop.data - loop.absolute_pos;
|
||||||
|
|
||||||
|
for (; j < end; ++j){
|
||||||
|
ch = data[j];
|
||||||
|
if (ch == '\n'){
|
||||||
|
widths[i] = width;
|
||||||
|
++i;
|
||||||
|
assert_4tech(j + 1 == starts[i]);
|
||||||
|
width = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
width += measure_character(advance_data, stride, ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
buffer_measure_widths(Buffer_Type *buffer, void *advance_data, int stride){
|
||||||
|
assert_4tech(buffer->line_count >= 1);
|
||||||
|
buffer_remeasure_widths(buffer, advance_data, stride, 0, buffer->line_count-1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech void
|
||||||
|
buffer_measure_wrap_y(Buffer_Type *buffer, float *wraps,
|
||||||
|
float font_height, float max_width){
|
||||||
|
float *widths;
|
||||||
|
float y_pos;
|
||||||
|
int i, line_count;
|
||||||
|
|
||||||
|
line_count = buffer->line_count;
|
||||||
|
widths = buffer->line_widths;
|
||||||
|
y_pos = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < line_count; ++i){
|
||||||
|
wraps[i] = y_pos;
|
||||||
|
if (widths[i] == 0) y_pos += font_height;
|
||||||
|
else y_pos += font_height*ceil_4tech(widths[i]/max_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
buffer_get_line_index(Buffer_Type *buffer, int pos, int l_bound, int u_bound){
|
||||||
|
int *lines;
|
||||||
|
int start, end;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert_4tech(0 <= l_bound);
|
||||||
|
assert_4tech(l_bound <= u_bound);
|
||||||
|
assert_4tech(u_bound <= buffer->line_count);
|
||||||
|
|
||||||
|
lines = buffer->line_starts;
|
||||||
|
|
||||||
|
start = l_bound;
|
||||||
|
end = u_bound;
|
||||||
|
for (;;){
|
||||||
|
i = (start + end) >> 1;
|
||||||
|
if (lines[i] < pos) start = i;
|
||||||
|
else if (lines[i] > pos) end = i;
|
||||||
|
else{
|
||||||
|
start = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert_4tech(start < end);
|
||||||
|
if (start == end - 1) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
buffer_get_line_index_from_wrapped_y(float *wraps, float y, float font_height, int l_bound, int u_bound){
|
||||||
|
int start, end, i, result;
|
||||||
|
start = l_bound;
|
||||||
|
end = u_bound;
|
||||||
|
for (;;){
|
||||||
|
i = (start + end) / 2;
|
||||||
|
if (wraps[i]+font_height <= y) start = i;
|
||||||
|
else if (wraps[i] > y) end = i;
|
||||||
|
else{
|
||||||
|
result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (start >= end - 1){
|
||||||
|
result = start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech Full_Cursor
|
||||||
|
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
|
||||||
|
Full_Cursor hint;
|
||||||
|
hint.pos = starts[line_index];
|
||||||
|
hint.line = line_index + 1;
|
||||||
|
hint.character = 1;
|
||||||
|
hint.unwrapped_y = (f32)(line_index * font_height);
|
||||||
|
hint.unwrapped_x = 0;
|
||||||
|
hint.wrapped_y = wrap_ys[line_index];
|
||||||
|
hint.wrapped_x = 0;
|
||||||
|
return(hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech Full_Cursor
|
||||||
|
buffer_cursor_from_pos(Buffer_Type *buffer, int pos, float *wraps,
|
||||||
|
float max_width, float font_height, void *advance_data, int stride){
|
||||||
|
Full_Cursor result;
|
||||||
|
int line_index;
|
||||||
|
|
||||||
|
line_index = buffer_get_line_index(buffer, pos, 0, buffer->line_count);
|
||||||
|
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
||||||
|
result = buffer_cursor_seek(buffer, seek_pos(pos), max_width, font_height,
|
||||||
|
advance_data, stride, result);
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech Full_Cursor
|
||||||
|
buffer_cursor_from_unwrapped_xy(Buffer_Type *buffer, float x, float y, int round_down, float *wraps,
|
||||||
|
float max_width, float font_height, void *advance_data, int stride){
|
||||||
|
Full_Cursor result;
|
||||||
|
int line_index;
|
||||||
|
|
||||||
|
line_index = (int)(y / font_height);
|
||||||
|
if (line_index >= buffer->line_count) line_index = buffer->line_count - 1;
|
||||||
|
if (line_index < 0) line_index = 0;
|
||||||
|
|
||||||
|
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
||||||
|
result = buffer_cursor_seek(buffer, seek_unwrapped_xy(x, y, round_down), max_width, font_height,
|
||||||
|
advance_data, stride, result);
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech Full_Cursor
|
||||||
|
buffer_cursor_from_wrapped_xy(Buffer_Type *buffer, float x, float y, int round_down, float *wraps,
|
||||||
|
float max_width, float font_height, void *advance_data, int stride){
|
||||||
|
Full_Cursor result;
|
||||||
|
int line_index;
|
||||||
|
|
||||||
|
line_index = buffer_get_line_index_from_wrapped_y(wraps, y, font_height, 0, buffer->line_count);
|
||||||
|
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
||||||
|
result = buffer_cursor_seek(buffer, seek_wrapped_xy(x, y, round_down), max_width, font_height,
|
||||||
|
advance_data, stride, result);
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech void
|
||||||
|
buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *items, int max, int *count,
|
||||||
|
float port_x, float port_y, float scroll_x, float scroll_y, Full_Cursor start_cursor, int wrapped,
|
||||||
|
float width, float height, void *advance_data, int stride, float font_height){
|
||||||
|
Buffer_Stringify_Type loop;
|
||||||
|
Buffer_Render_Item *item;
|
||||||
|
char *data;
|
||||||
|
int size, end;
|
||||||
|
float shift_x, shift_y;
|
||||||
|
float x, y;
|
||||||
|
int i, item_i;
|
||||||
|
float ch_width, ch_width_sub;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
size = buffer_size(buffer);
|
||||||
|
|
||||||
|
shift_x = port_x - scroll_x;
|
||||||
|
shift_y = port_y - scroll_y;
|
||||||
|
if (wrapped) shift_y += start_cursor.wrapped_y;
|
||||||
|
else shift_y += start_cursor.unwrapped_y;
|
||||||
|
|
||||||
|
x = shift_x;
|
||||||
|
y = shift_y;
|
||||||
|
item_i = 0;
|
||||||
|
item = items + item_i;
|
||||||
|
|
||||||
|
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size, size);
|
||||||
|
buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
|
||||||
|
end = loop.size + loop.absolute_pos;
|
||||||
|
data = loop.data - loop.absolute_pos;
|
||||||
|
|
||||||
|
for (i = loop.absolute_pos; i < end; ++i){
|
||||||
|
ch = data[i];
|
||||||
|
ch_width = measure_character(advance_data, stride, ch);
|
||||||
|
|
||||||
|
if (ch_width + x > width + shift_x && wrapped){
|
||||||
|
x = shift_x;
|
||||||
|
y += font_height;
|
||||||
|
}
|
||||||
|
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||||
|
|
||||||
|
switch (ch){
|
||||||
|
case '\n':
|
||||||
|
write_render_item_inline(item, i, ' ', x, y, advance_data, stride, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
|
||||||
|
x = shift_x;
|
||||||
|
y += font_height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
x += ch_width;
|
||||||
|
|
||||||
|
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, stride, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
x += ch_width;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
x += ch_width;
|
||||||
|
|
||||||
|
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, stride, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
x += ch_width;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\t':
|
||||||
|
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
|
||||||
|
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, stride, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
x += ch_width;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
||||||
|
++item_i;
|
||||||
|
++item;
|
||||||
|
x += ch_width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_get_render_data_end:
|
||||||
|
// TODO(allen): handle this with a control state
|
||||||
|
assert_4tech(item_i <= max);
|
||||||
|
*count = item_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech void
|
||||||
|
buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *items, int max, int *count,
|
||||||
|
float port_x, float port_y, float scroll_x, float scroll_y, int wrapped,
|
||||||
|
float width, float height, void *advance_data, int stride, float font_height){
|
||||||
|
Full_Cursor start_cursor;
|
||||||
|
if (wrapped){
|
||||||
|
start_cursor = buffer_cursor_from_wrapped_xy(buffer, 0, scroll_y, 0, wraps,
|
||||||
|
width, font_height, advance_data, stride);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
start_cursor = buffer_cursor_from_unwrapped_xy(buffer, 0, scroll_y, 0, wraps,
|
||||||
|
width, font_height, advance_data, stride);
|
||||||
|
}
|
||||||
|
buffer_get_render_data(buffer, wraps, items, max, count,
|
||||||
|
port_x, port_y, scroll_x, scroll_y, start_cursor, wrapped,
|
||||||
|
width, height, advance_data, stride, font_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
|
|
@ -0,0 +1,302 @@
|
||||||
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
|
* Four Tech
|
||||||
|
*
|
||||||
|
* public domain -- no warranty is offered or implied; use this code at your own risk
|
||||||
|
*
|
||||||
|
* 23.10.2015
|
||||||
|
*
|
||||||
|
* Buffer data object
|
||||||
|
* type - Gap Buffer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
char *data;
|
||||||
|
int size1, gap_size, size2, max;
|
||||||
|
|
||||||
|
float *line_widths;
|
||||||
|
int *line_starts;
|
||||||
|
int line_count;
|
||||||
|
int line_max;
|
||||||
|
int widths_max;
|
||||||
|
} Gap_Buffer;
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
gap_buffer_initialize(Gap_Buffer *buffer, char *data, int size){
|
||||||
|
int size1, size2, gap_size;
|
||||||
|
|
||||||
|
assert_4tech(buffer->max >= size);
|
||||||
|
|
||||||
|
size1 = size >> 1;
|
||||||
|
size2 = size - size1;
|
||||||
|
gap_size = buffer->max - size1 - size2;
|
||||||
|
buffer->size1 = size1;
|
||||||
|
buffer->size2 = size2;
|
||||||
|
buffer->gap_size = gap_size;
|
||||||
|
|
||||||
|
if (buffer->size1 > 0){
|
||||||
|
memcpy_4tech(buffer->data, data, size1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->size2 > 0){
|
||||||
|
memcpy_4tech(buffer->data + size1 + gap_size, data + size1, size2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
buffer_size(Gap_Buffer *buffer){
|
||||||
|
int size;
|
||||||
|
size = buffer->size1 + buffer->size2;
|
||||||
|
return(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
Gap_Buffer *buffer;
|
||||||
|
char *data, *base;
|
||||||
|
int absolute_pos;
|
||||||
|
int pos, end;
|
||||||
|
int size;
|
||||||
|
int page_size;
|
||||||
|
int separated;
|
||||||
|
} Gap_Buffer_Stringify_Loop;
|
||||||
|
|
||||||
|
inline_4tech Gap_Buffer_Stringify_Loop
|
||||||
|
buffer_stringify_loop(Gap_Buffer *buffer, int start, int end, int page_size){
|
||||||
|
Gap_Buffer_Stringify_Loop result;
|
||||||
|
if (0 <= start && start < end && end <= buffer->size1 + buffer->size2){
|
||||||
|
result.buffer = buffer;
|
||||||
|
result.base = buffer->data;
|
||||||
|
result.page_size = page_size;
|
||||||
|
result.absolute_pos = start;
|
||||||
|
|
||||||
|
if (end <= buffer->size1) result.end = end;
|
||||||
|
else result.end = end + buffer->gap_size;
|
||||||
|
|
||||||
|
if (start < buffer->size1){
|
||||||
|
if (end <= buffer->size1) result.separated = 0;
|
||||||
|
else result.separated = 1;
|
||||||
|
result.pos = start;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result.separated = 0;
|
||||||
|
result.pos = start + buffer->gap_size;
|
||||||
|
}
|
||||||
|
if (result.separated) result.size = buffer->size1 - start;
|
||||||
|
else result.size = end - start;
|
||||||
|
if (result.size > page_size) result.size = page_size;
|
||||||
|
result.data = buffer->data + result.pos;
|
||||||
|
}
|
||||||
|
else result.buffer = 0;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
buffer_stringify_good(Gap_Buffer_Stringify_Loop *loop){
|
||||||
|
int result;
|
||||||
|
result = (loop->buffer != 0);
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
buffer_stringify_next(Gap_Buffer_Stringify_Loop *loop){
|
||||||
|
int size1, temp_end;
|
||||||
|
if (loop->separated){
|
||||||
|
size1 = loop->buffer->size1;
|
||||||
|
if (loop->pos + loop->size == size1){
|
||||||
|
loop->separated = 0;
|
||||||
|
loop->pos = loop->buffer->gap_size + size1;
|
||||||
|
loop->absolute_pos = size1;
|
||||||
|
temp_end = loop->end;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
loop->pos += loop->page_size;
|
||||||
|
loop->absolute_pos += loop->page_size;
|
||||||
|
temp_end = size1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (loop->pos + loop->size == loop->end){
|
||||||
|
loop->buffer = 0;
|
||||||
|
temp_end = loop->pos;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
loop->pos += loop->page_size;
|
||||||
|
loop->absolute_pos += loop->page_size;
|
||||||
|
temp_end = loop->end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop->size = temp_end - loop->pos;
|
||||||
|
if (loop->size > loop->page_size) loop->size = loop->page_size;
|
||||||
|
loop->data = loop->base + loop->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
Gap_Buffer *buffer;
|
||||||
|
char *data, *base;
|
||||||
|
int pos, end;
|
||||||
|
int size;
|
||||||
|
int absolute_pos;
|
||||||
|
int page_size;
|
||||||
|
int separated;
|
||||||
|
} Gap_Buffer_Backify_Loop;
|
||||||
|
|
||||||
|
inline_4tech Gap_Buffer_Backify_Loop
|
||||||
|
buffer_backify_loop(Gap_Buffer *buffer, int start, int end, int page_size){
|
||||||
|
Gap_Buffer_Backify_Loop result;
|
||||||
|
int chunk2_start;
|
||||||
|
|
||||||
|
if (0 <= end && end < start && start <= buffer->size1 + buffer->size2){
|
||||||
|
chunk2_start = buffer->size1 + buffer->gap_size;
|
||||||
|
|
||||||
|
result.buffer = buffer;
|
||||||
|
result.base = buffer->data;
|
||||||
|
result.page_size = page_size;
|
||||||
|
|
||||||
|
if (end < buffer->size1) result.end = end;
|
||||||
|
else result.end = end + buffer->gap_size;
|
||||||
|
|
||||||
|
if (start <= buffer->size1){
|
||||||
|
result.separated = 0;
|
||||||
|
result.pos = start - page_size;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (end < buffer->size1) result.separated = 1;
|
||||||
|
else result.separated = 0;
|
||||||
|
result.pos = start - page_size + buffer->gap_size;
|
||||||
|
}
|
||||||
|
if (result.separated){
|
||||||
|
if (result.pos < chunk2_start) result.pos = chunk2_start;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (result.pos < result.end) result.pos = result.end;
|
||||||
|
}
|
||||||
|
result.size = start - result.pos;
|
||||||
|
result.absolute_pos = result.pos;
|
||||||
|
if (result.absolute_pos > buffer->size1) result.absolute_pos -= buffer->gap_size;
|
||||||
|
result.data = result.base + result.pos;
|
||||||
|
}
|
||||||
|
else result.buffer = 0;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
buffer_backify_good(Gap_Buffer_Backify_Loop *loop){
|
||||||
|
int result;
|
||||||
|
result = (loop->buffer != 0);
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
buffer_backify_next(Gap_Buffer_Backify_Loop *loop){
|
||||||
|
Gap_Buffer *buffer;
|
||||||
|
int temp_end;
|
||||||
|
int chunk2_start;
|
||||||
|
buffer = loop->buffer;
|
||||||
|
chunk2_start = buffer->size1 + buffer->gap_size;
|
||||||
|
if (loop->separated){
|
||||||
|
if (loop->pos == chunk2_start){
|
||||||
|
loop->separated = 0;
|
||||||
|
temp_end = buffer->size1;
|
||||||
|
loop->pos = temp_end - loop->page_size;
|
||||||
|
loop->absolute_pos = loop->pos;
|
||||||
|
if (loop->pos < loop->end){
|
||||||
|
loop->absolute_pos += (loop->end - loop->pos);
|
||||||
|
loop->pos = loop->end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
temp_end = loop->pos;
|
||||||
|
loop->pos -= loop->page_size;
|
||||||
|
loop->absolute_pos -= loop->page_size;
|
||||||
|
if (loop->pos < chunk2_start){
|
||||||
|
loop->pos = chunk2_start;
|
||||||
|
loop->absolute_pos = buffer->size1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (loop->pos == loop->end){
|
||||||
|
temp_end = 0;
|
||||||
|
loop->buffer = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
temp_end = loop->pos;
|
||||||
|
loop->pos -= loop->page_size;
|
||||||
|
loop->absolute_pos -= loop->page_size;
|
||||||
|
if (loop->pos < loop->end){
|
||||||
|
loop->absolute_pos += (loop->end - loop->pos);
|
||||||
|
loop->pos = loop->end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop->size = temp_end - loop->pos;
|
||||||
|
loop->data = loop->base + loop->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
buffer_stringify(Gap_Buffer *buffer, int start, int end, char *out){
|
||||||
|
for (Gap_Buffer_Stringify_Loop loop = buffer_stringify_loop(buffer, start, end, end - start);
|
||||||
|
buffer_stringify_good(&loop);
|
||||||
|
buffer_stringify_next(&loop)){
|
||||||
|
memcpy_4tech(out, loop.data, loop.size);
|
||||||
|
out += loop.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_4tech Full_Cursor
|
||||||
|
buffer_cursor_seek(Gap_Buffer *buffer, Buffer_Seek seek, float max_width, float font_height,
|
||||||
|
void *advance_data, int stride, Full_Cursor cursor){
|
||||||
|
char *data;
|
||||||
|
int size1, size2, gap_size;
|
||||||
|
int total_size, end, i;
|
||||||
|
int step;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
Seek_State state;
|
||||||
|
char *advances;
|
||||||
|
int xy_seek;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
data = buffer->data;
|
||||||
|
size1 = buffer->size1;
|
||||||
|
gap_size = buffer->gap_size;
|
||||||
|
size2 = buffer->size2;
|
||||||
|
total_size = size1 + gap_size + size2;
|
||||||
|
|
||||||
|
advances = (char*)advance_data;
|
||||||
|
xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy);
|
||||||
|
state.cursor = cursor;
|
||||||
|
|
||||||
|
result = 1;
|
||||||
|
i = cursor.pos;
|
||||||
|
end = size1;
|
||||||
|
for (step = 0; step < 2; ++step){
|
||||||
|
for (; i < end && result; ++i){
|
||||||
|
ch = data[i];
|
||||||
|
result = cursor_seek_step(&state, seek, xy_seek, max_width, font_height,
|
||||||
|
advances, stride, size1 + size2, ch);
|
||||||
|
}
|
||||||
|
end = total_size;
|
||||||
|
i += gap_size;
|
||||||
|
}
|
||||||
|
if (result){
|
||||||
|
result = cursor_seek_step(&state, seek, xy_seek, max_width, font_height,
|
||||||
|
advances, stride, size1 + size2, 0);
|
||||||
|
assert_4tech(result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(state.cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(allen): unfinished below here
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
gap_buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
|
|
@ -13,31 +13,26 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
#ifndef defines_4tech
|
|
||||||
#define inline_4tech inline
|
|
||||||
#define internal_4tech static
|
|
||||||
#define memset_4tech memset
|
|
||||||
#define memcpy_4tech memcpy
|
|
||||||
#define memmove_4tech memmove
|
|
||||||
#define defines_4tech 1
|
|
||||||
#define debug_4tech(x) x
|
|
||||||
#define assert_4tech assert
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
char *data;
|
char *data;
|
||||||
int size, max;
|
int size, max;
|
||||||
|
|
||||||
float *line_widths;
|
|
||||||
int *line_starts;
|
int *line_starts;
|
||||||
|
float *line_widths;
|
||||||
int line_count;
|
int line_count;
|
||||||
int line_max;
|
int line_max;
|
||||||
int widths_max;
|
int widths_max;
|
||||||
} Buffer;
|
} Buffer;
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
buffer_size(Buffer *buffer){
|
||||||
|
return buffer->size;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
Buffer *buffer;
|
Buffer *buffer;
|
||||||
char *data, *end;
|
char *data, *end;
|
||||||
|
int absolute_pos;
|
||||||
int size;
|
int size;
|
||||||
int page_size;
|
int page_size;
|
||||||
} Buffer_Stringify_Loop;
|
} Buffer_Stringify_Loop;
|
||||||
|
@ -47,6 +42,7 @@ buffer_stringify_loop(Buffer *buffer, int start, int end, int page_size){
|
||||||
Buffer_Stringify_Loop result;
|
Buffer_Stringify_Loop result;
|
||||||
if (0 <= start && start < end && end <= buffer->size){
|
if (0 <= start && start < end && end <= buffer->size){
|
||||||
result.buffer = buffer;
|
result.buffer = buffer;
|
||||||
|
result.absolute_pos = start;
|
||||||
result.data = buffer->data + start;
|
result.data = buffer->data + start;
|
||||||
result.size = end - start;
|
result.size = end - start;
|
||||||
result.end = buffer->data + end;
|
result.end = buffer->data + end;
|
||||||
|
@ -69,11 +65,59 @@ buffer_stringify_next(Buffer_Stringify_Loop *loop){
|
||||||
if (loop->data + loop->size == loop->end) loop->buffer = 0;
|
if (loop->data + loop->size == loop->end) loop->buffer = 0;
|
||||||
else{
|
else{
|
||||||
loop->data += loop->page_size;
|
loop->data += loop->page_size;
|
||||||
|
loop->absolute_pos += loop->page_size;
|
||||||
loop->size = (int)(loop->end - loop->data);
|
loop->size = (int)(loop->end - loop->data);
|
||||||
if (loop->size > loop->page_size) loop->size = loop->page_size;
|
if (loop->size > loop->page_size) loop->size = loop->page_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
Buffer *buffer;
|
||||||
|
char *data, *end;
|
||||||
|
int absolute_pos;
|
||||||
|
int size;
|
||||||
|
int page_size;
|
||||||
|
} Buffer_Backify_Loop;
|
||||||
|
|
||||||
|
inline_4tech Buffer_Backify_Loop
|
||||||
|
buffer_backify_loop(Buffer *buffer, int start, int end, int page_size){
|
||||||
|
Buffer_Backify_Loop result;
|
||||||
|
if (0 <= end && end < start && start <= buffer->size){
|
||||||
|
result.buffer = buffer;
|
||||||
|
result.end = buffer->data + end;
|
||||||
|
result.page_size = page_size;
|
||||||
|
result.size = start - end;
|
||||||
|
if (result.size > page_size) result.size = page_size;
|
||||||
|
result.absolute_pos = start - result.size;
|
||||||
|
result.data = buffer->data + result.absolute_pos;
|
||||||
|
}
|
||||||
|
else result.buffer = 0;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
buffer_backify_good(Buffer_Backify_Loop *loop){
|
||||||
|
int result;
|
||||||
|
result = (loop->buffer != 0);
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
buffer_backify_next(Buffer_Backify_Loop *loop){
|
||||||
|
char *old_data;
|
||||||
|
if (loop->data == loop->end) loop->buffer = 0;
|
||||||
|
else{
|
||||||
|
old_data = loop->data;
|
||||||
|
loop->data -= loop->page_size;
|
||||||
|
loop->absolute_pos -= loop->page_size;
|
||||||
|
if (loop->data < loop->end){
|
||||||
|
loop->size = (int)(old_data - loop->end);
|
||||||
|
loop->data = loop->end;
|
||||||
|
loop->absolute_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline_4tech void
|
inline_4tech void
|
||||||
buffer_stringify(Buffer *buffer, int start, int end, char *out){
|
buffer_stringify(Buffer *buffer, int start, int end, char *out){
|
||||||
for (Buffer_Stringify_Loop loop = buffer_stringify_loop(buffer, start, end, end - start);
|
for (Buffer_Stringify_Loop loop = buffer_stringify_loop(buffer, start, end, end - start);
|
||||||
|
@ -84,227 +128,25 @@ buffer_stringify(Buffer *buffer, int start, int end, char *out){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_4tech int
|
#if 0
|
||||||
buffer_count_newlines(Buffer *buffer, int start, int end){
|
|
||||||
char *data;
|
|
||||||
int i;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
assert_4tech(0 <= start);
|
|
||||||
assert_4tech(start <= end);
|
|
||||||
assert_4tech(end < buffer->size);
|
|
||||||
|
|
||||||
data = buffer->data;
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
for (i = start; i < end; ++i){
|
|
||||||
count += (data[i] == '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
return(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
int i;
|
|
||||||
int count;
|
|
||||||
int start;
|
|
||||||
} Buffer_Measure_Starts;
|
|
||||||
|
|
||||||
internal_4tech int
|
|
||||||
buffer_measure_starts(Buffer_Measure_Starts *state, Buffer *buffer){
|
|
||||||
int *starts;
|
|
||||||
int max;
|
|
||||||
char *data;
|
|
||||||
int size;
|
|
||||||
int start, count, i;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
starts = buffer->line_starts;
|
|
||||||
max = buffer->line_max;
|
|
||||||
|
|
||||||
data = buffer->data;
|
|
||||||
size = buffer->size;
|
|
||||||
|
|
||||||
assert_4tech(size < buffer->max);
|
|
||||||
data[size] = '\n';
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
|
|
||||||
i = state->i;
|
|
||||||
count = state->count;
|
|
||||||
start = state->start;
|
|
||||||
|
|
||||||
for (; i <= size; ++i){
|
|
||||||
if (data[i] == '\n'){
|
|
||||||
if (count == max){
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
starts[count++] = start;
|
|
||||||
start = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state->i = i;
|
|
||||||
state->count = count;
|
|
||||||
state->start = start;
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech void
|
internal_4tech void
|
||||||
buffer_remeasure_starts(Buffer *buffer, int line_start, int line_end, int line_shift, int text_shift){
|
buffer_measure_wrap_y(Buffer *buffer, float *wraps,
|
||||||
int *starts;
|
float font_height, float max_width){
|
||||||
int line_count;
|
|
||||||
char *data;
|
|
||||||
int size;
|
|
||||||
int line_i, char_i, start;
|
|
||||||
|
|
||||||
starts = buffer->line_starts;
|
|
||||||
line_count = buffer->line_count;
|
|
||||||
|
|
||||||
assert_4tech(0 <= line_start);
|
|
||||||
assert_4tech(line_start <= line_end);
|
|
||||||
assert_4tech(line_end < line_count);
|
|
||||||
assert_4tech(line_count + line_shift <= buffer->line_max);
|
|
||||||
|
|
||||||
++line_end;
|
|
||||||
if (text_shift != 0){
|
|
||||||
line_i = line_end;
|
|
||||||
starts += line_i;
|
|
||||||
for (; line_i < line_count; ++line_i, ++starts){
|
|
||||||
*starts += text_shift;
|
|
||||||
}
|
|
||||||
starts = buffer->line_starts;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line_shift != 0){
|
|
||||||
memmove_4tech(starts + line_end + line_shift, starts + line_end,
|
|
||||||
sizeof(int)*(line_count - line_end));
|
|
||||||
line_count += line_shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = buffer->size;
|
|
||||||
data = buffer->data;
|
|
||||||
char_i = starts[line_start];
|
|
||||||
line_i = line_start;
|
|
||||||
|
|
||||||
assert_4tech(size < buffer->max);
|
|
||||||
data[size] = '\n';
|
|
||||||
|
|
||||||
start = char_i;
|
|
||||||
line_end += line_shift;
|
|
||||||
for (; char_i <= size; ++char_i){
|
|
||||||
if (data[char_i] == '\n'){
|
|
||||||
starts[line_i++] = start;
|
|
||||||
start = char_i + 1;
|
|
||||||
if (line_i >= line_end && start == starts[line_i]) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_4tech(line_count >= 1);
|
|
||||||
buffer->line_count = line_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline_4tech float
|
|
||||||
measure_character(void *advance_data, int stride, char character){
|
|
||||||
char *advances;
|
|
||||||
float width;
|
|
||||||
|
|
||||||
advances = (char*)advance_data;
|
|
||||||
switch (character){
|
|
||||||
case 0: width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '0'); break;
|
|
||||||
case '\n': width = 0; break;
|
|
||||||
case '\r': width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '\r'); break;
|
|
||||||
default: width = *(float*)(advances + stride * character);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(width);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech void
|
|
||||||
buffer_remeasure_widths(Buffer *buffer, void *advance_data, int stride,
|
|
||||||
int line_start, int line_end, int line_shift){
|
|
||||||
int *starts;
|
|
||||||
float *widths;
|
float *widths;
|
||||||
int line_count;
|
float y_pos;
|
||||||
char *data;
|
int i, line_count;
|
||||||
int i, j;
|
|
||||||
float width;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
starts = buffer->line_starts;
|
|
||||||
widths = buffer->line_widths;
|
|
||||||
line_count = buffer->line_count;
|
line_count = buffer->line_count;
|
||||||
|
widths = buffer->line_widths;
|
||||||
assert_4tech(0 <= line_start);
|
y_pos = 0;
|
||||||
assert_4tech(line_start <= line_end);
|
|
||||||
assert_4tech(line_end < line_count);
|
|
||||||
assert_4tech(line_count <= buffer->widths_max);
|
|
||||||
|
|
||||||
++line_end;
|
for (i = 0; i < line_count; ++i){
|
||||||
if (line_shift != 0){
|
wraps[i] = y_pos;
|
||||||
memmove_4tech(widths + line_end + line_shift, widths + line_end,
|
if (widths[i] == 0) y_pos += font_height;
|
||||||
sizeof(float)*(line_count - line_end));
|
else y_pos += font_height*ceil_4tech(widths[i]/max_width);
|
||||||
line_count += line_shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = buffer->data;
|
|
||||||
|
|
||||||
assert_4tech(buffer->size < buffer->max);
|
|
||||||
data[buffer->size] = '\n';
|
|
||||||
|
|
||||||
i = line_start;
|
|
||||||
j = starts[i];
|
|
||||||
|
|
||||||
line_end += line_shift;
|
|
||||||
for (; i < line_end; ++i){
|
|
||||||
assert_4tech(j == starts[i]);
|
|
||||||
width = 0;
|
|
||||||
|
|
||||||
for (ch = data[j]; ch != '\n'; ch = data[++j]){
|
|
||||||
width += measure_character(advance_data, stride, ch);
|
|
||||||
}
|
|
||||||
++j;
|
|
||||||
|
|
||||||
widths[i] = width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
inline_4tech void
|
|
||||||
buffer_measure_widths(Buffer *buffer, void *advance_data, int stride){
|
|
||||||
assert_4tech(buffer->line_count >= 1);
|
|
||||||
buffer_remeasure_widths(buffer, advance_data, stride, 0, buffer->line_count-1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech int
|
|
||||||
buffer_get_line_index(Buffer *buffer, int pos, int l_bound, int u_bound){
|
|
||||||
int *lines;
|
|
||||||
int start, end;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
assert_4tech(0 <= l_bound);
|
|
||||||
assert_4tech(l_bound <= u_bound);
|
|
||||||
assert_4tech(u_bound <= buffer->line_count);
|
|
||||||
|
|
||||||
start = l_bound;
|
|
||||||
end = u_bound;
|
|
||||||
lines = buffer->line_starts;
|
|
||||||
for (;;){
|
|
||||||
i = (start + end) >> 1;
|
|
||||||
if (lines[i] < pos) start = i;
|
|
||||||
else if (lines[i] > pos) end = i;
|
|
||||||
else{
|
|
||||||
start = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert_4tech(start < end);
|
|
||||||
if (start == end - 1) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(start);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){
|
buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){
|
||||||
|
@ -405,78 +247,17 @@ buffer_update_cursors(Cursor_With_Index *sorted_positions, int count, int start,
|
||||||
for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start;
|
for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum{
|
|
||||||
buffer_seek_pos,
|
|
||||||
buffer_seek_wrapped_xy,
|
|
||||||
buffer_seek_unwrapped_xy,
|
|
||||||
buffer_seek_line_char
|
|
||||||
} Buffer_Seek_Type;
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
Buffer_Seek_Type type;
|
|
||||||
union{
|
|
||||||
struct { int pos; };
|
|
||||||
struct { int round_down; float x, y; };
|
|
||||||
struct { int line, character; };
|
|
||||||
};
|
|
||||||
} Buffer_Seek;
|
|
||||||
|
|
||||||
inline_4tech Buffer_Seek
|
|
||||||
seek_pos(int pos){
|
|
||||||
Buffer_Seek result;
|
|
||||||
result.type = buffer_seek_pos;
|
|
||||||
result.pos = pos;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline_4tech Buffer_Seek
|
|
||||||
seek_wrapped_xy(float x, float y, int round_down){
|
|
||||||
Buffer_Seek result;
|
|
||||||
result.type = buffer_seek_wrapped_xy;
|
|
||||||
result.x = x;
|
|
||||||
result.y = y;
|
|
||||||
result.round_down = round_down;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline_4tech Buffer_Seek
|
|
||||||
seek_unwrapped_xy(float x, float y, int round_down){
|
|
||||||
Buffer_Seek result;
|
|
||||||
result.type = buffer_seek_unwrapped_xy;
|
|
||||||
result.x = x;
|
|
||||||
result.y = y;
|
|
||||||
result.round_down = round_down;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline_4tech Buffer_Seek
|
|
||||||
seek_line_char(int line, int character){
|
|
||||||
Buffer_Seek result;
|
|
||||||
result.type = buffer_seek_line_char;
|
|
||||||
result.line = line;
|
|
||||||
result.character = character;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
int pos;
|
|
||||||
int line, character;
|
|
||||||
float unwrapped_x, unwrapped_y;
|
|
||||||
float wrapped_x, wrapped_y;
|
|
||||||
} Full_Cursor;
|
|
||||||
|
|
||||||
internal_4tech Full_Cursor
|
internal_4tech Full_Cursor
|
||||||
buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, float max_width, float font_height,
|
buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, float max_width, float font_height,
|
||||||
void *advance_data, int stride, Full_Cursor cursor){
|
void *advance_data, int stride, Full_Cursor cursor){
|
||||||
Full_Cursor prev_cursor;
|
char *data;
|
||||||
char *data, *advances;
|
|
||||||
int size;
|
int size;
|
||||||
char ch;
|
|
||||||
float ch_width;
|
|
||||||
|
|
||||||
int get_out;
|
Seek_State state;
|
||||||
|
char *advances;
|
||||||
|
char ch;
|
||||||
int xy_seek;
|
int xy_seek;
|
||||||
float x, y, px;
|
int result;
|
||||||
|
|
||||||
data = buffer->data;
|
data = buffer->data;
|
||||||
size = buffer->size;
|
size = buffer->size;
|
||||||
|
@ -484,182 +265,18 @@ buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, float max_width, float font
|
||||||
data[size] = 0;
|
data[size] = 0;
|
||||||
|
|
||||||
advances = (char*)advance_data;
|
advances = (char*)advance_data;
|
||||||
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
px = 0;
|
|
||||||
xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy);
|
xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy);
|
||||||
|
state.cursor = cursor;
|
||||||
|
|
||||||
for (;;){
|
do{
|
||||||
prev_cursor = cursor;
|
ch = data[state.cursor.pos];
|
||||||
ch = data[cursor.pos];
|
result = cursor_seek_step(&state, seek, xy_seek, max_width, font_height,
|
||||||
|
advances, stride, size, ch);
|
||||||
switch (ch){
|
}while(result);
|
||||||
case '\n':
|
|
||||||
++cursor.line;
|
|
||||||
cursor.unwrapped_y += font_height;
|
|
||||||
cursor.wrapped_y += font_height;
|
|
||||||
cursor.character = 0;
|
|
||||||
cursor.unwrapped_x = 0;
|
|
||||||
cursor.wrapped_x = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
++cursor.character;
|
|
||||||
if (ch == '\r') ch_width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * 'r');
|
|
||||||
else ch_width = *(float*)(advances + stride * ch);
|
|
||||||
|
|
||||||
if (cursor.wrapped_x + ch_width >= max_width){
|
|
||||||
cursor.wrapped_y += font_height;
|
|
||||||
cursor.wrapped_x = 0;
|
|
||||||
prev_cursor = cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor.unwrapped_x += ch_width;
|
|
||||||
cursor.wrapped_x += ch_width;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++cursor.pos;
|
|
||||||
|
|
||||||
if (cursor.pos > size){
|
|
||||||
cursor = prev_cursor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_out = 0;
|
|
||||||
|
|
||||||
switch (seek.type){
|
|
||||||
case buffer_seek_pos:
|
|
||||||
if (cursor.pos > seek.pos){
|
|
||||||
cursor = prev_cursor;
|
|
||||||
get_out = 1;
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case buffer_seek_wrapped_xy:
|
|
||||||
x = cursor.wrapped_x; px = prev_cursor.wrapped_x;
|
|
||||||
y = cursor.wrapped_y; break;
|
|
||||||
|
|
||||||
case buffer_seek_unwrapped_xy:
|
|
||||||
x = cursor.unwrapped_x; px = prev_cursor.unwrapped_x;
|
|
||||||
y = cursor.unwrapped_y; break;
|
|
||||||
|
|
||||||
case buffer_seek_line_char:
|
|
||||||
if (cursor.line == seek.line && cursor.character >= seek.character){
|
|
||||||
get_out = 1;
|
|
||||||
}
|
|
||||||
else if (cursor.line > seek.line){
|
|
||||||
cursor = prev_cursor;
|
|
||||||
get_out = 1;
|
|
||||||
}break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_out) break;
|
|
||||||
if (xy_seek){
|
|
||||||
if (y > seek.y){
|
|
||||||
cursor = prev_cursor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y > seek.y - font_height && x >= seek.x){
|
|
||||||
if (!seek.round_down){
|
|
||||||
if ((seek.x - px) < (x - seek.x)) cursor = prev_cursor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x > seek.x){
|
|
||||||
cursor = prev_cursor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(cursor);
|
return(state.cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline_4tech Full_Cursor
|
|
||||||
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
|
|
||||||
Full_Cursor hint;
|
|
||||||
hint.pos = starts[line_index];
|
|
||||||
hint.line = line_index + 1;
|
|
||||||
hint.character = 1;
|
|
||||||
hint.unwrapped_y = (f32)(line_index * font_height);
|
|
||||||
hint.unwrapped_x = 0;
|
|
||||||
hint.wrapped_y = wrap_ys[line_index];
|
|
||||||
hint.wrapped_x = 0;
|
|
||||||
return(hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech Full_Cursor
|
|
||||||
buffer_cursor_from_pos(Buffer *buffer, int pos, float *wraps,
|
|
||||||
float max_width, float font_height, void *advance_data, int stride){
|
|
||||||
Full_Cursor result;
|
|
||||||
int line_index;
|
|
||||||
|
|
||||||
line_index = buffer_get_line_index(buffer, pos, 0, buffer->line_count);
|
|
||||||
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
|
||||||
result = buffer_cursor_seek(buffer, seek_pos(pos), max_width, font_height,
|
|
||||||
advance_data, stride, result);
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech Full_Cursor
|
|
||||||
buffer_cursor_from_unwrapped_xy(Buffer *buffer, float x, float y, int round_down, float *wraps,
|
|
||||||
float max_width, float font_height, void *advance_data, int stride){
|
|
||||||
Full_Cursor result;
|
|
||||||
int line_index;
|
|
||||||
|
|
||||||
line_index = (int)(y / font_height);
|
|
||||||
if (line_index >= buffer->line_count) line_index = buffer->line_count - 1;
|
|
||||||
if (line_index < 0) line_index = 0;
|
|
||||||
|
|
||||||
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
|
||||||
result = buffer_cursor_seek(buffer, seek_unwrapped_xy(x, y, round_down), max_width, font_height,
|
|
||||||
advance_data, stride, result);
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech Full_Cursor
|
|
||||||
buffer_cursor_from_wrapped_xy(Buffer *buffer, float x, float y, int round_down, float *wraps,
|
|
||||||
float max_width, float font_height, void *advance_data, int stride){
|
|
||||||
Full_Cursor result;
|
|
||||||
int line_index;
|
|
||||||
int start, end, i;
|
|
||||||
|
|
||||||
// NOTE(allen): binary search lines on wrapped y position
|
|
||||||
// TODO(allen): pull this out once other wrap handling code is ready
|
|
||||||
start = 0;
|
|
||||||
end = buffer->line_count;
|
|
||||||
for (;;){
|
|
||||||
i = (start + end) / 2;
|
|
||||||
if (wraps[i]+font_height <= y) start = i;
|
|
||||||
else if (wraps[i] > y) end = i;
|
|
||||||
else{
|
|
||||||
line_index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (start >= end - 1){
|
|
||||||
line_index = start;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = make_cursor_hint(line_index, buffer->line_starts, wraps, font_height);
|
|
||||||
result = buffer_cursor_seek(buffer, seek_wrapped_xy(x, y, round_down), max_width, font_height,
|
|
||||||
advance_data, stride, result);
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
int str_start, len;
|
|
||||||
int start, end;
|
|
||||||
} Buffer_Edit;
|
|
||||||
|
|
||||||
internal_4tech void
|
internal_4tech void
|
||||||
buffer_invert_edit_shift(Buffer *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings, int *str_pos, int max, int shift_amount){
|
buffer_invert_edit_shift(Buffer *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings, int *str_pos, int max, int shift_amount){
|
||||||
int pos;
|
int pos;
|
||||||
|
@ -916,166 +533,5 @@ buffer_eol_convert_out(Buffer *buffer){
|
||||||
buffer->size = size;
|
buffer->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
int index;
|
|
||||||
int glyphid;
|
|
||||||
float x0, y0;
|
|
||||||
float x1, y1;
|
|
||||||
} Buffer_Render_Item;
|
|
||||||
|
|
||||||
internal_4tech void
|
|
||||||
buffer_get_render_data(Buffer *buffer, float *wraps, Buffer_Render_Item *items, int max, int *count,
|
|
||||||
float port_x, float port_y, float scroll_x, float scroll_y, int wrapped,
|
|
||||||
float width, float height, void *advance_data, int stride, float font_height){
|
|
||||||
Full_Cursor start_cursor;
|
|
||||||
Buffer_Render_Item *item;
|
|
||||||
char *data;
|
|
||||||
int size;
|
|
||||||
float shift_x, shift_y;
|
|
||||||
float x, y;
|
|
||||||
int i, item_i;
|
|
||||||
float ch_width;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
data = buffer->data;
|
|
||||||
size = buffer->size;
|
|
||||||
assert_4tech(size < buffer->max);
|
|
||||||
data[size] = 0;
|
|
||||||
|
|
||||||
shift_x = port_x - scroll_x;
|
|
||||||
shift_y = port_y - scroll_y;
|
|
||||||
if (wrapped){
|
|
||||||
start_cursor = buffer_cursor_from_wrapped_xy(buffer, 0, scroll_y, 0, wraps,
|
|
||||||
width, font_height, advance_data, stride);
|
|
||||||
shift_y += start_cursor.wrapped_y;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
start_cursor = buffer_cursor_from_unwrapped_xy(buffer, 0, scroll_y, 0, wraps,
|
|
||||||
width, font_height, advance_data, stride);
|
|
||||||
shift_y += start_cursor.unwrapped_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = start_cursor.pos;
|
|
||||||
|
|
||||||
x = shift_x;
|
|
||||||
y = shift_y;
|
|
||||||
item_i = 0;
|
|
||||||
item = items + item_i;
|
|
||||||
|
|
||||||
for (; i <= size; ++i){
|
|
||||||
ch = data[i];
|
|
||||||
ch_width = measure_character(advance_data, stride, ch);
|
|
||||||
|
|
||||||
if (ch_width + x > width + shift_x && wrapped){
|
|
||||||
x = shift_x;
|
|
||||||
y += font_height;
|
|
||||||
}
|
|
||||||
if (y > height + shift_y) break;
|
|
||||||
|
|
||||||
switch (ch){
|
|
||||||
case '\n':
|
|
||||||
ch_width = measure_character(advance_data, stride, ' ');
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = ' ';
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + ch_width;
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
|
|
||||||
x = shift_x;
|
|
||||||
y += font_height;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
ch_width = measure_character(advance_data, stride, '\\');
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = '\\';
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + ch_width;
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
x += ch_width;
|
|
||||||
|
|
||||||
ch_width = measure_character(advance_data, stride, '0');
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = '0';
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + ch_width;
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
x += ch_width;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\r':
|
|
||||||
ch_width = measure_character(advance_data, stride, '\\');
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = '\\';
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + ch_width;
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
x += ch_width;
|
|
||||||
|
|
||||||
ch_width = measure_character(advance_data, stride, 'r');
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = 'r';
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + ch_width;
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
x += ch_width;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\t':
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = '\\';
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + measure_character(advance_data, stride, '\\');
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = 't';
|
|
||||||
item->x0 = (item-1)->x1;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = item->x0 + measure_character(advance_data, stride, 't');
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
x += ch_width;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
item->index = i;
|
|
||||||
item->glyphid = ch;
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + ch_width;
|
|
||||||
item->y1 = y + font_height;
|
|
||||||
++item_i;
|
|
||||||
++item;
|
|
||||||
x += ch_width;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (y > height + shift_y) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(allen): handle this with a control state
|
|
||||||
assert_4tech(item_i <= max);
|
|
||||||
*count = item_i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,256 @@
|
||||||
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
|
* Four Tech
|
||||||
|
*
|
||||||
|
* public domain -- no warranty is offered or implied; use this code at your own risk
|
||||||
|
*
|
||||||
|
* 23.10.2015
|
||||||
|
*
|
||||||
|
* Items shared by gap buffer types
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
#ifndef defines_4tech
|
||||||
|
#define inline_4tech inline
|
||||||
|
#define internal_4tech static
|
||||||
|
#define memset_4tech memset
|
||||||
|
#define memcpy_4tech memcpy
|
||||||
|
#define memmove_4tech memmove
|
||||||
|
#define defines_4tech 1
|
||||||
|
#define debug_4tech(x) x
|
||||||
|
#define assert_4tech assert
|
||||||
|
|
||||||
|
#define ceil_4tech CEIL32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline_4tech float
|
||||||
|
measure_character(void *advance_data, int stride, char character){
|
||||||
|
char *advances;
|
||||||
|
float width;
|
||||||
|
|
||||||
|
advances = (char*)advance_data;
|
||||||
|
switch (character){
|
||||||
|
case 0: width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '0'); break;
|
||||||
|
case '\n': width = 0; break;
|
||||||
|
case '\r': width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * '\r'); break;
|
||||||
|
default: width = *(float*)(advances + stride * character);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int str_start, len;
|
||||||
|
int start, end;
|
||||||
|
} Buffer_Edit;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
buffer_seek_pos,
|
||||||
|
buffer_seek_wrapped_xy,
|
||||||
|
buffer_seek_unwrapped_xy,
|
||||||
|
buffer_seek_line_char
|
||||||
|
} Buffer_Seek_Type;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
Buffer_Seek_Type type;
|
||||||
|
union{
|
||||||
|
struct { int pos; };
|
||||||
|
struct { int round_down; float x, y; };
|
||||||
|
struct { int line, character; };
|
||||||
|
};
|
||||||
|
} Buffer_Seek;
|
||||||
|
|
||||||
|
inline_4tech Buffer_Seek
|
||||||
|
seek_pos(int pos){
|
||||||
|
Buffer_Seek result;
|
||||||
|
result.type = buffer_seek_pos;
|
||||||
|
result.pos = pos;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech Buffer_Seek
|
||||||
|
seek_wrapped_xy(float x, float y, int round_down){
|
||||||
|
Buffer_Seek result;
|
||||||
|
result.type = buffer_seek_wrapped_xy;
|
||||||
|
result.x = x;
|
||||||
|
result.y = y;
|
||||||
|
result.round_down = round_down;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech Buffer_Seek
|
||||||
|
seek_unwrapped_xy(float x, float y, int round_down){
|
||||||
|
Buffer_Seek result;
|
||||||
|
result.type = buffer_seek_unwrapped_xy;
|
||||||
|
result.x = x;
|
||||||
|
result.y = y;
|
||||||
|
result.round_down = round_down;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech Buffer_Seek
|
||||||
|
seek_line_char(int line, int character){
|
||||||
|
Buffer_Seek result;
|
||||||
|
result.type = buffer_seek_line_char;
|
||||||
|
result.line = line;
|
||||||
|
result.character = character;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int pos;
|
||||||
|
int line, character;
|
||||||
|
float unwrapped_x, unwrapped_y;
|
||||||
|
float wrapped_x, wrapped_y;
|
||||||
|
} Full_Cursor;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int index;
|
||||||
|
int glyphid;
|
||||||
|
float x0, y0;
|
||||||
|
float x1, y1;
|
||||||
|
} Buffer_Render_Item;
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
write_render_item(Buffer_Render_Item *item, int index, int glyphid,
|
||||||
|
float x, float y, float w, float h){
|
||||||
|
item->index = index;
|
||||||
|
item->glyphid = glyphid;
|
||||||
|
item->x0 = x;
|
||||||
|
item->y0 = y;
|
||||||
|
item->x1 = x + w;
|
||||||
|
item->y1 = y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech float
|
||||||
|
write_render_item_inline(Buffer_Render_Item *item, int index, int glyphid,
|
||||||
|
float x, float y, void *advance_data, int stride, float h){
|
||||||
|
float ch_width;
|
||||||
|
ch_width = measure_character(advance_data, stride, (char)glyphid);
|
||||||
|
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||||
|
return(ch_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
Full_Cursor cursor, prev_cursor;
|
||||||
|
} Seek_State;
|
||||||
|
|
||||||
|
internal_4tech int
|
||||||
|
cursor_seek_step(Seek_State *state, Buffer_Seek seek, int xy_seek, float max_width, float font_height,
|
||||||
|
char *advances, int stride, int size, char ch){
|
||||||
|
Full_Cursor cursor, prev_cursor;
|
||||||
|
float ch_width;
|
||||||
|
int result;
|
||||||
|
float x, px, y;
|
||||||
|
|
||||||
|
cursor = state->cursor;
|
||||||
|
prev_cursor = state->prev_cursor;
|
||||||
|
|
||||||
|
result = 1;
|
||||||
|
prev_cursor = cursor;
|
||||||
|
switch (ch){
|
||||||
|
case '\n':
|
||||||
|
++cursor.line;
|
||||||
|
cursor.unwrapped_y += font_height;
|
||||||
|
cursor.wrapped_y += font_height;
|
||||||
|
cursor.character = 1;
|
||||||
|
cursor.unwrapped_x = 0;
|
||||||
|
cursor.wrapped_x = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++cursor.character;
|
||||||
|
if (ch == '\r') ch_width = *(float*)(advances + stride * '\\') + *(float*)(advances + stride * 'r');
|
||||||
|
else ch_width = *(float*)(advances + stride * ch);
|
||||||
|
|
||||||
|
if (cursor.wrapped_x + ch_width >= max_width){
|
||||||
|
cursor.wrapped_y += font_height;
|
||||||
|
cursor.wrapped_x = 0;
|
||||||
|
prev_cursor = cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.unwrapped_x += ch_width;
|
||||||
|
cursor.wrapped_x += ch_width;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++cursor.pos;
|
||||||
|
|
||||||
|
if (cursor.pos > size){
|
||||||
|
cursor = prev_cursor;
|
||||||
|
result = 0;
|
||||||
|
goto cursor_seek_step_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = y = px = 0;
|
||||||
|
|
||||||
|
switch (seek.type){
|
||||||
|
case buffer_seek_pos:
|
||||||
|
if (cursor.pos > seek.pos){
|
||||||
|
cursor = prev_cursor;
|
||||||
|
result = 0;
|
||||||
|
goto cursor_seek_step_end;
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case buffer_seek_wrapped_xy:
|
||||||
|
x = cursor.wrapped_x; px = prev_cursor.wrapped_x;
|
||||||
|
y = cursor.wrapped_y; break;
|
||||||
|
|
||||||
|
case buffer_seek_unwrapped_xy:
|
||||||
|
x = cursor.unwrapped_x; px = prev_cursor.unwrapped_x;
|
||||||
|
y = cursor.unwrapped_y; break;
|
||||||
|
|
||||||
|
case buffer_seek_line_char:
|
||||||
|
if (cursor.line == seek.line && cursor.character >= seek.character){
|
||||||
|
result = 0;
|
||||||
|
goto cursor_seek_step_end;
|
||||||
|
}
|
||||||
|
else if (cursor.line > seek.line){
|
||||||
|
cursor = prev_cursor;
|
||||||
|
result = 0;
|
||||||
|
goto cursor_seek_step_end;
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xy_seek){
|
||||||
|
if (y > seek.y){
|
||||||
|
cursor = prev_cursor;
|
||||||
|
result = 0;
|
||||||
|
goto cursor_seek_step_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y > seek.y - font_height && x >= seek.x){
|
||||||
|
if (!seek.round_down){
|
||||||
|
if (ch != '\n' && (seek.x - px) < (x - seek.x)) cursor = prev_cursor;
|
||||||
|
result = 0;
|
||||||
|
goto cursor_seek_step_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x > seek.x){
|
||||||
|
cursor = prev_cursor;
|
||||||
|
result = 0;
|
||||||
|
goto cursor_seek_step_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor_seek_step_end:
|
||||||
|
state->cursor = cursor;
|
||||||
|
state->prev_cursor = prev_cursor;
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech int
|
||||||
|
is_whitespace(char c){
|
||||||
|
int result;
|
||||||
|
result = (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v');
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
|
|
@ -54,6 +54,8 @@
|
||||||
#define FPS 30
|
#define FPS 30
|
||||||
#define FRAME_TIME (1000000 / FPS)
|
#define FRAME_TIME (1000000 / FPS)
|
||||||
|
|
||||||
|
#define BUFFER_EXPERIMENT_SCALPEL 0
|
||||||
|
|
||||||
#include "4ed_meta.h"
|
#include "4ed_meta.h"
|
||||||
|
|
||||||
#define FCPP_FORBID_MALLOC
|
#define FCPP_FORBID_MALLOC
|
||||||
|
@ -91,7 +93,11 @@ struct Sys_Bubble : public Bubble{
|
||||||
#include "4ed_command.cpp"
|
#include "4ed_command.cpp"
|
||||||
#include "4ed_layout.cpp"
|
#include "4ed_layout.cpp"
|
||||||
#include "4ed_style.cpp"
|
#include "4ed_style.cpp"
|
||||||
|
#if BUFFER_EXPERIMENT_SCALPEL
|
||||||
|
#include "4ed_file_view_golden_array.cpp"
|
||||||
|
#else
|
||||||
#include "4ed_file_view.cpp"
|
#include "4ed_file_view.cpp"
|
||||||
|
#endif
|
||||||
#include "4ed_color_view.cpp"
|
#include "4ed_color_view.cpp"
|
||||||
#include "4ed_interactive_view.cpp"
|
#include "4ed_interactive_view.cpp"
|
||||||
#include "4ed_menu_view.cpp"
|
#include "4ed_menu_view.cpp"
|
||||||
|
|
Loading…
Reference in New Issue