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;
|
||||
}
|
||||
|
||||
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){
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
||||
i32 pos = seek_whitespace_right(
|
||||
(u8*)file->buffer.data, file->buffer.size, view->cursor.pos);
|
||||
i32 pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos);
|
||||
|
||||
view_cursor_move(view, pos);
|
||||
}
|
||||
|
@ -253,14 +228,13 @@ COMMAND_DECL(seek_whitespace_left){
|
|||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
||||
i32 pos = seek_whitespace_left(
|
||||
(u8*)file->buffer.data, view->cursor.pos);
|
||||
i32 pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos);
|
||||
|
||||
view_cursor_move(view, pos);
|
||||
}
|
||||
|
||||
// TODO(allen): see if this becomes better by using buffer procudures directly
|
||||
COMMAND_DECL(seek_whitespace_up){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -286,9 +260,11 @@ COMMAND_DECL(seek_whitespace_up){
|
|||
if (pos != 0) ++pos;
|
||||
|
||||
view_cursor_move(view, pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(seek_whitespace_down){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -320,6 +296,7 @@ COMMAND_DECL(seek_whitespace_down){
|
|||
else pos = prev_endline+1;
|
||||
|
||||
view_cursor_move(view, pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal i32
|
||||
|
@ -374,6 +351,7 @@ COMMAND_DECL(seek_token_right){
|
|||
}
|
||||
|
||||
COMMAND_DECL(seek_white_or_token_right){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -383,11 +361,13 @@ COMMAND_DECL(seek_white_or_token_right){
|
|||
if (file->tokens_complete){
|
||||
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));
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(seek_white_or_token_left){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -397,8 +377,9 @@ COMMAND_DECL(seek_white_or_token_left){
|
|||
if (file->tokens_complete){
|
||||
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));
|
||||
#endif
|
||||
}
|
||||
|
||||
internal i32
|
||||
|
@ -426,6 +407,7 @@ seek_alphanumeric_left(u8 *data, i32 pos){
|
|||
}
|
||||
|
||||
COMMAND_DECL(seek_alphanumeric_right){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -433,6 +415,7 @@ COMMAND_DECL(seek_alphanumeric_right){
|
|||
i32 pos = seek_alphanumeric_right(
|
||||
(u8*)file->buffer.data, file->buffer.size, view->cursor.pos);
|
||||
view_cursor_move(view, pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(seek_alphanumeric_left){
|
||||
|
@ -446,6 +429,7 @@ COMMAND_DECL(seek_alphanumeric_left){
|
|||
}
|
||||
|
||||
COMMAND_DECL(seek_alphanumeric_or_camel_right){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -467,6 +451,7 @@ COMMAND_DECL(seek_alphanumeric_or_camel_right){
|
|||
}
|
||||
|
||||
view_cursor_move(view, camel_pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(seek_alphanumeric_or_camel_left){
|
||||
|
@ -552,6 +537,7 @@ COMMAND_DECL(copy){
|
|||
}
|
||||
|
||||
COMMAND_DECL(cut){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -571,6 +557,7 @@ COMMAND_DECL(cut){
|
|||
view_measure_wraps(&mem->general, view);
|
||||
view_cursor_move(view, next_cursor_pos);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(paste){
|
||||
|
@ -647,6 +634,7 @@ COMMAND_DECL(paste_next){
|
|||
}
|
||||
|
||||
COMMAND_DECL(delete_chunk){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -661,6 +649,7 @@ COMMAND_DECL(delete_chunk){
|
|||
view_cursor_move(view, next_cursor_pos);
|
||||
view->mark = range.start;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(timeline_scrub){
|
||||
|
@ -811,9 +800,11 @@ app_open_file(App_Vars *vars, General_Memory *general, Panel *panel,
|
|||
command_data->view = old_view;
|
||||
|
||||
new_view->map = app_get_map(vars, target_file->base_map_id);
|
||||
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
if (created_file && target_file->tokens_exist)
|
||||
file_first_lex_parallel(general, target_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -886,8 +877,10 @@ COMMAND_DECL(reopen){
|
|||
*file = temp_file;
|
||||
file->source_path.str = file->source_path_;
|
||||
file->live_name.str = file->live_name_;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
if (file->tokens_exist)
|
||||
file_first_lex_parallel(&mem->general, file);
|
||||
#endif
|
||||
|
||||
Partition old_part = command->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);
|
||||
}
|
||||
|
||||
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){
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
|
@ -1049,6 +1031,7 @@ COMMAND_DECL(toggle_show_whitespace){
|
|||
}
|
||||
|
||||
COMMAND_DECL(toggle_tokens){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -1060,6 +1043,7 @@ COMMAND_DECL(toggle_tokens){
|
|||
else{
|
||||
file_first_lex_parallel(&mem->general, file);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -1084,9 +1068,11 @@ case_change_range(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
data[i] += char_delta;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
if (file->token_stack.tokens)
|
||||
file_relex_parallel(mem, file, range.start, range.end, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1280,9 +1266,7 @@ COMMAND_DECL(move_left){
|
|||
REQ_FILE(file, view);
|
||||
|
||||
i32 pos = view->cursor.pos;
|
||||
if (pos > 0){
|
||||
--pos;
|
||||
}
|
||||
if (pos > 0) --pos;
|
||||
|
||||
view_cursor_move(view, pos);
|
||||
}
|
||||
|
@ -1292,16 +1276,15 @@ COMMAND_DECL(move_right){
|
|||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
||||
i32 size = file->buffer.size;
|
||||
i32 size = buffer_size(&file->buffer);
|
||||
i32 pos = view->cursor.pos;
|
||||
if (pos < size){
|
||||
++pos;
|
||||
}
|
||||
if (pos < size) ++pos;
|
||||
|
||||
view_cursor_move(view, pos);
|
||||
}
|
||||
|
||||
COMMAND_DECL(delete){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -1322,9 +1305,11 @@ COMMAND_DECL(delete){
|
|||
view_cursor_move(view, next_cursor_pos);
|
||||
if (view->mark >= end) view->mark -= shift;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(backspace){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -1346,6 +1331,7 @@ COMMAND_DECL(backspace){
|
|||
view_cursor_move(view, next_cursor_pos);
|
||||
if (view->mark >= end) view->mark -= shift;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(move_up){
|
||||
|
@ -1536,6 +1522,7 @@ COMMAND_DECL(set_settings){
|
|||
REQ_FILE(file, view);
|
||||
USE_VARS(vars);
|
||||
USE_MEM(mem);
|
||||
AllowLocal(mem);
|
||||
|
||||
Command_Parameter *end = param_stack_end(&command->part);
|
||||
Command_Parameter *param = param_stack_first(&command->part, end);
|
||||
|
@ -1544,6 +1531,7 @@ COMMAND_DECL(set_settings){
|
|||
switch (p){
|
||||
case par_lex_as_cpp_file:
|
||||
{
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
int v = dynamic_to_bool(¶m->param.value);
|
||||
if (file->tokens_exist){
|
||||
if (!v) file_kill_tokens(&mem->general, file);
|
||||
|
@ -1551,6 +1539,7 @@ COMMAND_DECL(set_settings){
|
|||
else{
|
||||
if (v) file_first_lex_parallel(&mem->general, file);
|
||||
}
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case par_wrap_lines:
|
||||
|
@ -1658,6 +1647,7 @@ extern "C"{
|
|||
if (view){
|
||||
Editing_File *file = view->file;
|
||||
if (file && !file->is_dummy){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
Working_Set *working_set = cmd->working_set;
|
||||
buffer.file_id = (int)(file - working_set->files);
|
||||
buffer.size = file->buffer.size;
|
||||
|
@ -1669,6 +1659,7 @@ extern "C"{
|
|||
buffer.file_cursor_pos = file->cursor_pos;
|
||||
buffer.is_lexed = file->tokens_exist;
|
||||
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_down, MDFR_NONE, command_page_down);
|
||||
|
||||
map_add(commands, codes->right, MDFR_CTRL, command_seek_white_or_token_right);
|
||||
map_add(commands, codes->left, MDFR_CTRL, command_seek_white_or_token_left);
|
||||
map_add(commands, codes->right, MDFR_CTRL, command_seek_whitespace_right);
|
||||
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->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, 'd', MDFR_CTRL, command_delete_chunk);
|
||||
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_tokens);
|
||||
map_add(commands, 'u', MDFR_CTRL, command_to_uppercase);
|
||||
|
@ -1850,7 +1840,6 @@ setup_command_table(){
|
|||
SET(interactive_kill_buffer);
|
||||
SET(kill_buffer);
|
||||
SET(toggle_line_wrap);
|
||||
SET(toggle_endline_mode);
|
||||
SET(to_uppercase);
|
||||
SET(to_lowercase);
|
||||
SET(toggle_show_whitespace);
|
||||
|
@ -2603,7 +2592,9 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
if (!view_->is_active) continue;
|
||||
File_View *view = view_to_file_view(view_);
|
||||
if (!view) continue;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
view_measure_wraps(&vars->mem.general, view);
|
||||
#endif
|
||||
view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos);
|
||||
}
|
||||
app_result.redraw = 1;
|
||||
|
@ -3020,7 +3011,9 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
view_set_file(file_view, file.file, style,
|
||||
vars->hooks[hook_open_file], &command_data, app_links);
|
||||
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);
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case DACT_SWITCH:
|
||||
|
@ -3131,12 +3124,14 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
if (vars->style.font_changed){
|
||||
vars->style.font_changed = 0;
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
Editing_File *file = vars->working_set.files;
|
||||
for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){
|
||||
if (file->buffer.data && !file->is_dummy){
|
||||
file_measure_widths(&vars->mem.general, file, vars->style.font);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Panel *panel = panels;
|
||||
for (i32 panel_i = vars->layout.panel_count; panel_i > 0; --panel_i, ++panel){
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
// 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{
|
||||
i32 start, end;
|
||||
|
@ -70,7 +72,7 @@ struct Undo_Data{
|
|||
};
|
||||
|
||||
struct Editing_File{
|
||||
Buffer buffer;
|
||||
Gap_Buffer buffer;
|
||||
|
||||
Undo_Data undo;
|
||||
|
||||
|
@ -1008,7 +1010,7 @@ struct File_View_Widget{
|
|||
|
||||
struct File_View{
|
||||
View view_base;
|
||||
|
||||
|
||||
Delay *delay;
|
||||
Editing_Layout *layout;
|
||||
|
||||
|
@ -1108,19 +1110,17 @@ internal bool32
|
|||
file_save(Partition *part, Editing_File *file, u8 *filename){
|
||||
bool32 result = 0;
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
Buffer temp_buffer;
|
||||
temp_buffer.max = partition_remaining(part);
|
||||
temp_buffer.size = 0;
|
||||
temp_buffer.data = push_array(part, char, temp_buffer.max);
|
||||
// TODO(allen): What about using this stringify loop to convert out?
|
||||
for (Buffer_Stringify_Loop loop = buffer_stringify_loop(&file->buffer, 0, file->buffer.size, file->buffer.size);
|
||||
i32 max = partition_remaining(part);
|
||||
i32 size = 0;
|
||||
char *data = push_array(part, char, max);
|
||||
i32 data_size = buffer_size(&file->buffer);
|
||||
for (Gap_Buffer_Stringify_Loop loop = buffer_stringify_loop(&file->buffer, 0, data_size, data_size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
memcpy(temp_buffer.data, loop.data, loop.size);
|
||||
temp_buffer.size += loop.size;
|
||||
buffer_eol_convert_out(&temp_buffer);
|
||||
result = system_save_file(filename, temp_buffer.data, temp_buffer.size);
|
||||
memcpy(data + size, loop.data, loop.size);
|
||||
size += loop.size;
|
||||
}
|
||||
result = system_save_file(filename, data, size);
|
||||
end_temp_memory(temp);
|
||||
file_synchronize_times(file, filename);
|
||||
return result;
|
||||
|
@ -1322,18 +1322,11 @@ view_measure_wraps(General_Memory *general, File_View *view){
|
|||
general_memory_allocate(general, sizeof(real32)*max, BUBBLE_WRAPS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Font *font = view->style->font;
|
||||
real32 line_height = (real32)font->height;
|
||||
real32 max_width = view_compute_width(view);
|
||||
real32 *line_widths = file->buffer.line_widths;
|
||||
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;
|
||||
}
|
||||
buffer_measure_wrap_y(&file->buffer, view->line_wrap_y, line_height, max_width);
|
||||
|
||||
view->line_count = line_count;
|
||||
}
|
||||
|
@ -1351,22 +1344,15 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam
|
|||
|
||||
*file = {};
|
||||
file->buffer.data = (char*)data;
|
||||
file->buffer.size = val.size;
|
||||
file->buffer.max = request_size;
|
||||
|
||||
if (val.size > 0){
|
||||
memcpy(data, val.str, val.size);
|
||||
buffer_eol_convert_in(&file->buffer);
|
||||
}
|
||||
|
||||
data[val.size] = 0;
|
||||
gap_buffer_initialize(&file->buffer, val.str, val.size);
|
||||
|
||||
file_synchronize_times(file, filename);
|
||||
file_init_strings(file);
|
||||
file_set_name(file, filename);
|
||||
|
||||
file->base_map_id = mapid_file;
|
||||
|
||||
|
||||
file_measure_starts(general, file);
|
||||
file_measure_widths(general, file, font);
|
||||
file->font = font;
|
||||
|
@ -1471,7 +1457,7 @@ file_close(General_Memory *general, Editing_File *file){
|
|||
internal void
|
||||
file_get_dummy(Editing_File *file){
|
||||
*file = {};
|
||||
file->buffer.data = (char*)&file->buffer.size;
|
||||
file->buffer.data = (char*)&file->buffer.size1;
|
||||
file->is_dummy = 1;
|
||||
}
|
||||
|
||||
|
@ -1479,6 +1465,7 @@ struct Shift_Information{
|
|||
i32 start, end, amount;
|
||||
};
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
internal
|
||||
JOB_CALLBACK(job_full_lex){
|
||||
Editing_File *file = (Editing_File*)data[0];
|
||||
|
@ -1541,6 +1528,7 @@ JOB_CALLBACK(job_full_lex){
|
|||
file->tokens_complete = 1;
|
||||
file->still_lexing = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
internal void
|
||||
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 = {};
|
||||
}
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
internal void
|
||||
file_first_lex_parallel(General_Memory *general, Editing_File *file){
|
||||
#if 1
|
||||
Assert(file->token_stack.tokens == 0);
|
||||
|
||||
file->tokens_complete = 0;
|
||||
|
@ -1570,9 +1558,6 @@ file_first_lex_parallel(General_Memory *general, Editing_File *file){
|
|||
job.data[1] = general;
|
||||
job.memory_request = Kbytes(64);
|
||||
file->lex_job = system_post_job(BACKGROUND_THREADS, job);
|
||||
#else
|
||||
file_kill_tokens(general, file);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -1659,17 +1644,18 @@ file_relex_parallel(Mem_Options *mem, Editing_File *file,
|
|||
file->lex_job = system_post_job(BACKGROUND_THREADS, job);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal bool32
|
||||
file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_size){
|
||||
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){
|
||||
i32 request_size = LargeRoundUp(target_size*2, Kbytes(256));
|
||||
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){
|
||||
new_data[file->buffer.size] = 0;
|
||||
file->buffer.data = new_data;
|
||||
file->buffer.max = request_size;
|
||||
}
|
||||
|
@ -1754,6 +1740,7 @@ struct Edit_Spec{
|
|||
Edit_Step step;
|
||||
};
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
internal Edit_Step*
|
||||
file_post_undo(General_Memory *general, Editing_File *file,
|
||||
Edit_Step step, bool32 do_merge, bool32 can_merge){
|
||||
|
@ -1957,6 +1944,7 @@ file_post_history(General_Memory *general, Editing_File *file,
|
|||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline Full_Cursor
|
||||
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;
|
||||
|
||||
General_Memory *general = &view->view_base.mem->general;
|
||||
AllowLocal(general);
|
||||
Font *font = style->font;
|
||||
view->style = style;
|
||||
view->font_advance = font->advance;
|
||||
view->font_height = font->height;
|
||||
|
||||
|
||||
view_measure_wraps(general, view);
|
||||
|
||||
view->cursor = {};
|
||||
|
@ -2219,6 +2208,7 @@ enum History_Mode{
|
|||
internal void
|
||||
view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str,
|
||||
History_Mode history_mode, i32 next_cursor){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
General_Memory *general = &mem->general;
|
||||
|
||||
#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;
|
||||
#endif
|
||||
}
|
||||
|
||||
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 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);
|
||||
|
||||
// NOTE(allen): fixing stuff afterwards
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
if (file->tokens_exist)
|
||||
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_end = buffer_get_line_index(&file->buffer, end, 0, file->buffer.line_count);
|
||||
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 line_shift = new_line_count - replaced_line_count;
|
||||
|
||||
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);
|
||||
|
||||
Temp_Memory cursor_temp = begin_temp_memory(&mem->part);
|
||||
|
||||
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;
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal void
|
||||
view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||
Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
Assert(file);
|
||||
ProfileMomentFunction();
|
||||
|
||||
|
@ -2586,6 +2587,7 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
}
|
||||
end_temp_memory(cursor_temp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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?
|
||||
internal i32
|
||||
view_find_end_of_line(File_View *view, i32 pos){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
Editing_File *file = view->file;
|
||||
char *data = file->buffer.data;
|
||||
while (pos < file->buffer.size && data[pos] != '\n') ++pos;
|
||||
if (pos > file->buffer.size) pos = file->buffer.size;
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
|
||||
internal i32
|
||||
view_find_beginning_of_line(File_View *view, i32 pos){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
Editing_File *file = view->file;
|
||||
char *data = file->buffer.data;
|
||||
if (pos > 0){
|
||||
|
@ -2725,11 +2730,13 @@ view_find_beginning_of_line(File_View *view, i32 pos){
|
|||
while (pos > 0 && data[pos] != '\n') --pos;
|
||||
if (pos != 0) ++pos;
|
||||
}
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
|
||||
internal i32
|
||||
view_find_beginning_of_next_line(File_View *view, i32 pos){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
Editing_File *file = view->file;
|
||||
char *data = file->buffer.data;
|
||||
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){
|
||||
++pos;
|
||||
}
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
@ -2847,6 +2855,7 @@ enum Endline_Convert_Type{
|
|||
|
||||
internal void
|
||||
view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
Editing_File *file = view->file;
|
||||
Assert(file && !file->is_dummy);
|
||||
Partition *part = &mem->part;
|
||||
|
@ -2917,6 +2926,7 @@ view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout)
|
|||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal u32*
|
||||
|
@ -3469,14 +3479,14 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
|
|||
#if 1
|
||||
Partition *part = &view_->mem->part;
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
|
||||
partition_align(part, 4);
|
||||
i32 max = partition_remaining(part) / sizeof(Buffer_Render_Item);
|
||||
Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, max);
|
||||
|
||||
|
||||
i32 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);
|
||||
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;
|
||||
at_cursor_color = style->main.at_cursor_color;
|
||||
}
|
||||
|
||||
|
||||
i32 token_i = 0;
|
||||
u32 main_color = style->main.default_color;
|
||||
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]);
|
||||
token_i = result.token_index + 1;
|
||||
}
|
||||
|
||||
|
||||
u32 mark_color = style->main.mark_color;
|
||||
Buffer_Render_Item *item = items;
|
||||
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 &&
|
||||
i >= current_token.start && i <= current_token.start + current_token.size){
|
||||
highlight_color = style->main.highlight_junk_color;
|
||||
|
@ -3863,6 +3873,7 @@ internal
|
|||
HANDLE_COMMAND_SIG(handle_command_file_view){
|
||||
File_View *file_view = (File_View*)(view);
|
||||
Editing_File *file = file_view->file;
|
||||
AllowLocal(file);
|
||||
|
||||
switch (file_view->widget.type){
|
||||
case FWIDG_NONE:
|
||||
|
@ -3878,6 +3889,7 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
|
|||
|
||||
case FWIDG_SEARCH:
|
||||
{
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
String *string = &file_view->isearch.str;
|
||||
Single_Line_Input_Step result =
|
||||
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;
|
||||
view_set_widget(file_view, FWIDG_NONE);
|
||||
}
|
||||
#endif
|
||||
}break;
|
||||
|
||||
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
|
||||
|
||||
#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{
|
||||
char *data;
|
||||
int size, max;
|
||||
|
||||
float *line_widths;
|
||||
int *line_starts;
|
||||
float *line_widths;
|
||||
int line_count;
|
||||
int line_max;
|
||||
int widths_max;
|
||||
} Buffer;
|
||||
|
||||
inline_4tech int
|
||||
buffer_size(Buffer *buffer){
|
||||
return buffer->size;
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
Buffer *buffer;
|
||||
char *data, *end;
|
||||
int absolute_pos;
|
||||
int size;
|
||||
int page_size;
|
||||
} Buffer_Stringify_Loop;
|
||||
|
@ -47,6 +42,7 @@ buffer_stringify_loop(Buffer *buffer, int start, int end, int page_size){
|
|||
Buffer_Stringify_Loop result;
|
||||
if (0 <= start && start < end && end <= buffer->size){
|
||||
result.buffer = buffer;
|
||||
result.absolute_pos = start;
|
||||
result.data = buffer->data + start;
|
||||
result.size = end - start;
|
||||
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;
|
||||
else{
|
||||
loop->data += loop->page_size;
|
||||
loop->absolute_pos += loop->page_size;
|
||||
loop->size = (int)(loop->end - loop->data);
|
||||
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
|
||||
buffer_stringify(Buffer *buffer, int start, int end, char *out){
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
internal_4tech void
|
||||
buffer_remeasure_starts(Buffer *buffer, int line_start, int line_end, int line_shift, int text_shift){
|
||||
int *starts;
|
||||
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;
|
||||
buffer_measure_wrap_y(Buffer *buffer, float *wraps,
|
||||
float font_height, float max_width){
|
||||
float *widths;
|
||||
int line_count;
|
||||
char *data;
|
||||
int i, j;
|
||||
float width;
|
||||
char ch;
|
||||
|
||||
starts = buffer->line_starts;
|
||||
widths = buffer->line_widths;
|
||||
float y_pos;
|
||||
int i, line_count;
|
||||
|
||||
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);
|
||||
widths = buffer->line_widths;
|
||||
y_pos = 0;
|
||||
|
||||
++line_end;
|
||||
if (line_shift != 0){
|
||||
memmove_4tech(widths + line_end + line_shift, widths + line_end,
|
||||
sizeof(float)*(line_count - line_end));
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
internal_4tech int
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, float max_width, float font_height,
|
||||
void *advance_data, int stride, Full_Cursor cursor){
|
||||
Full_Cursor prev_cursor;
|
||||
char *data, *advances;
|
||||
char *data;
|
||||
int size;
|
||||
char ch;
|
||||
float ch_width;
|
||||
|
||||
int get_out;
|
||||
Seek_State state;
|
||||
char *advances;
|
||||
char ch;
|
||||
int xy_seek;
|
||||
float x, y, px;
|
||||
int result;
|
||||
|
||||
data = buffer->data;
|
||||
size = buffer->size;
|
||||
|
@ -484,182 +265,18 @@ buffer_cursor_seek(Buffer *buffer, Buffer_Seek seek, float max_width, float font
|
|||
data[size] = 0;
|
||||
|
||||
advances = (char*)advance_data;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
px = 0;
|
||||
xy_seek = (seek.type == buffer_seek_wrapped_xy || seek.type == buffer_seek_unwrapped_xy);
|
||||
state.cursor = cursor;
|
||||
|
||||
for (;;){
|
||||
prev_cursor = cursor;
|
||||
ch = data[cursor.pos];
|
||||
|
||||
switch (ch){
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
do{
|
||||
ch = data[state.cursor.pos];
|
||||
result = cursor_seek_step(&state, seek, xy_seek, max_width, font_height,
|
||||
advances, stride, size, ch);
|
||||
}while(result);
|
||||
|
||||
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
|
||||
buffer_invert_edit_shift(Buffer *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings, int *str_pos, int max, int shift_amount){
|
||||
int pos;
|
||||
|
@ -916,166 +533,5 @@ buffer_eol_convert_out(Buffer *buffer){
|
|||
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
|
||||
|
||||
|
|
|
@ -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 FRAME_TIME (1000000 / FPS)
|
||||
|
||||
#define BUFFER_EXPERIMENT_SCALPEL 0
|
||||
|
||||
#include "4ed_meta.h"
|
||||
|
||||
#define FCPP_FORBID_MALLOC
|
||||
|
@ -91,7 +93,11 @@ struct Sys_Bubble : public Bubble{
|
|||
#include "4ed_command.cpp"
|
||||
#include "4ed_layout.cpp"
|
||||
#include "4ed_style.cpp"
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
#include "4ed_file_view_golden_array.cpp"
|
||||
#else
|
||||
#include "4ed_file_view.cpp"
|
||||
#endif
|
||||
#include "4ed_color_view.cpp"
|
||||
#include "4ed_interactive_view.cpp"
|
||||
#include "4ed_menu_view.cpp"
|
||||
|
|
Loading…
Reference in New Issue