view api working, some examples in custom.cpp
This commit is contained in:
parent
eeb7c7c6df
commit
29a405e8df
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 23.02.2016
|
||||
*
|
||||
* Types shared by custom and application
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#ifndef FRED_BUFFER_TYPES_H
|
||||
#define FRED_BUFFER_TYPES_H
|
||||
|
||||
typedef struct Full_Cursor{
|
||||
int pos;
|
||||
int line, character;
|
||||
float unwrapped_x, unwrapped_y;
|
||||
float wrapped_x, wrapped_y;
|
||||
} Full_Cursor;
|
||||
|
||||
typedef enum{
|
||||
buffer_seek_pos,
|
||||
buffer_seek_wrapped_xy,
|
||||
buffer_seek_unwrapped_xy,
|
||||
buffer_seek_line_char
|
||||
} Buffer_Seek_Type;
|
||||
|
||||
typedef struct Buffer_Seek{
|
||||
Buffer_Seek_Type type;
|
||||
union{
|
||||
struct { int pos; };
|
||||
struct { int round_down; float x, y; };
|
||||
struct { int line, character; };
|
||||
};
|
||||
} Buffer_Seek;
|
||||
|
||||
static Buffer_Seek
|
||||
seek_pos(int pos){
|
||||
Buffer_Seek result;
|
||||
result.type = buffer_seek_pos;
|
||||
result.pos = pos;
|
||||
return(result);
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -89,8 +89,87 @@ CUSTOM_COMMAND_SIG(write_increment){
|
|||
// is usually ready, but when a buffer has just been opened it is possible that the contents
|
||||
// haven't been filled yet. If the buffer is not ready trying to read or write it is invalid.
|
||||
// (See my_file_settings for comments on the exists field).
|
||||
char text[] = "++";
|
||||
int size = sizeof(text) - 1;
|
||||
if (buffer.exists && buffer.ready){
|
||||
app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, "++", 2);
|
||||
app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, text, size);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_decrement){
|
||||
Buffer_Summary buffer = app->get_active_buffer(cmd_context);
|
||||
char text[] = "--";
|
||||
int size = sizeof(text) - 1;
|
||||
if (buffer.exists && buffer.ready){
|
||||
app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, text, size);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_long_braces){
|
||||
File_View_Summary view;
|
||||
Buffer_Summary buffer;
|
||||
|
||||
view = app->get_active_view(cmd_context);
|
||||
if (view.exists){
|
||||
buffer = app->get_active_buffer(cmd_context);
|
||||
|
||||
char text[] = "{\n\n}";
|
||||
int size = sizeof(text) - 1;
|
||||
int pos;
|
||||
|
||||
if (buffer.exists && buffer.ready){
|
||||
pos = view.cursor.pos;
|
||||
app->buffer_replace_range(cmd_context, &buffer, pos, pos, text, size);
|
||||
app->view_set_cursor(cmd_context, &view, seek_pos(pos + 2), 1);
|
||||
|
||||
push_parameter(app, cmd_context, par_range_start, pos);
|
||||
push_parameter(app, cmd_context, par_range_end, pos + size);
|
||||
push_parameter(app, cmd_context, par_clear_blank_lines, 0);
|
||||
exec_command(cmd_context, cmdid_auto_tab_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(ifdef_off){
|
||||
File_View_Summary view;
|
||||
Buffer_Summary buffer;
|
||||
|
||||
view = app->get_active_view(cmd_context);
|
||||
if (view.exists){
|
||||
buffer = app->get_active_buffer(cmd_context);
|
||||
|
||||
char text1[] = "#if 0\n";
|
||||
int size1 = sizeof(text1) - 1;
|
||||
|
||||
char text2[] = "#endif\n";
|
||||
int size2 = sizeof(text2) - 1;
|
||||
|
||||
int pos, c, m;
|
||||
|
||||
if (buffer.exists && buffer.ready){
|
||||
c = view.cursor.pos;
|
||||
m = view.mark.pos;
|
||||
pos = (c<m)?(c):(m);
|
||||
|
||||
app->buffer_replace_range(cmd_context, &buffer, pos, pos, text1, size1);
|
||||
|
||||
push_parameter(app, cmd_context, par_range_start, pos);
|
||||
push_parameter(app, cmd_context, par_range_end, pos);
|
||||
exec_command(cmd_context, cmdid_auto_tab_range);
|
||||
|
||||
|
||||
app->refresh_view(cmd_context, &view);
|
||||
c = view.cursor.pos;
|
||||
m = view.mark.pos;
|
||||
pos = (c>m)?(c):(m);
|
||||
|
||||
|
||||
app->buffer_replace_range(cmd_context, &buffer, pos, pos, text2, size2);
|
||||
|
||||
push_parameter(app, cmd_context, par_range_start, pos);
|
||||
push_parameter(app, cmd_context, par_range_end, pos);
|
||||
exec_command(cmd_context, cmdid_auto_tab_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,6 +357,9 @@ extern "C" GET_BINDING_DATA(get_bindings){
|
|||
bind(context, ' ', MDFR_SHIFT, cmdid_write_character);
|
||||
|
||||
bind(context, '=', MDFR_CTRL, write_increment);
|
||||
bind(context, '-', MDFR_CTRL, write_decrement);
|
||||
bind(context, '[', MDFR_CTRL, open_long_braces);
|
||||
bind(context, 'i', MDFR_ALT, ifdef_off);
|
||||
|
||||
end_map(context);
|
||||
|
||||
|
@ -333,7 +415,7 @@ extern "C" GET_BINDING_DATA(get_bindings){
|
|||
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
|
||||
|
||||
bind(context, 'f', MDFR_CTRL, cmdid_search);
|
||||
bind(context, 'r', MDFR_CTRL, cmdid_rsearch);
|
||||
bind(context, 'r', MDFR_CTRL, cmdid_reverse_search);
|
||||
bind(context, 'g', MDFR_CTRL, cmdid_goto_line);
|
||||
|
||||
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#include "4coder_buffer_types.h"
|
||||
|
||||
#define MDFR_NONE 0
|
||||
#define MDFR_CTRL 1
|
||||
#define MDFR_ALT 2
|
||||
|
@ -63,7 +65,7 @@ enum Command_ID{
|
|||
cmdid_seek_alphanumeric_or_camel_left,
|
||||
cmdid_seek_alphanumeric_or_camel_right,
|
||||
cmdid_search,
|
||||
cmdid_rsearch,
|
||||
cmdid_reverse_search,
|
||||
cmdid_word_complete,
|
||||
cmdid_goto_line,
|
||||
cmdid_set_mark,
|
||||
|
@ -124,6 +126,8 @@ enum Command_ID{
|
|||
};
|
||||
|
||||
enum Param_ID{
|
||||
par_range_start,
|
||||
par_range_end,
|
||||
par_name,
|
||||
par_lex_as_cpp_file,
|
||||
par_wrap_lines,
|
||||
|
@ -133,6 +137,7 @@ enum Param_ID{
|
|||
par_cli_command,
|
||||
par_cli_overlap_with_conflict,
|
||||
par_cli_always_bind_to_view,
|
||||
par_clear_blank_lines,
|
||||
// never below this
|
||||
par_type_count
|
||||
};
|
||||
|
@ -216,10 +221,10 @@ struct Extra_Font{
|
|||
int size;
|
||||
};
|
||||
|
||||
// NOTE(allen): None of the members of *_Summary structs nor any of the
|
||||
// data pointed to by the members should be modified, I would have made
|
||||
// them all const... but that causes a lot problems for C++ reasons.
|
||||
struct Buffer_Summary{
|
||||
// NOTE(allen): None of these members nor any of the data pointed to
|
||||
// by these members should be modified, I would have made them const...
|
||||
// but that causes a lot problems for C++ reasons.
|
||||
int exists;
|
||||
int ready;
|
||||
int file_id;
|
||||
|
@ -236,6 +241,15 @@ struct Buffer_Summary{
|
|||
int map_id;
|
||||
};
|
||||
|
||||
struct File_View_Summary{
|
||||
int exists;
|
||||
int view_id;
|
||||
int file_id;
|
||||
|
||||
Full_Cursor cursor;
|
||||
Full_Cursor mark;
|
||||
};
|
||||
|
||||
#ifndef FRED_STRING_STRUCT
|
||||
#define FRED_STRING_STRUCT
|
||||
struct String{
|
||||
|
@ -274,10 +288,21 @@ extern "C"{
|
|||
#define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(void *cmd_context)
|
||||
#define GET_BUFFER_BY_NAME(name) Buffer_Summary name(void *cmd_context, String filename)
|
||||
|
||||
#define REFRESH_BUFFER_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer)
|
||||
#define BUFFER_SEEK_DELIMITER_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, char delim, int *out)
|
||||
#define BUFFER_READ_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *out)
|
||||
#define BUFFER_REPLACE_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *str, int len)
|
||||
|
||||
// File view manipulation
|
||||
#define GET_VIEW_MAX_INDEX_SIG(name) int name(void *cmd_context)
|
||||
#define GET_VIEW_SIG(name) File_View_Summary name(void *cmd_context, int index)
|
||||
#define GET_ACTIVE_VIEW_SIG(name) File_View_Summary name(void *cmd_context)
|
||||
|
||||
#define REFRESH_VIEW_SIG(name) int name(void *cmd_context, File_View_Summary *view)
|
||||
#define VIEW_SET_CURSOR_SIG(name) int name(void *cmd_context, File_View_Summary *view, Buffer_Seek seek, int set_preferred_x)
|
||||
#define VIEW_SET_MARK_SIG(name) int name(void *cmd_context, File_View_Summary *view, Buffer_Seek seek)
|
||||
#define VIEW_SET_FILE_SIG(name) int name(void *cmd_context, File_View_Summary *view, int file_id)
|
||||
|
||||
extern "C"{
|
||||
// Command exectuion
|
||||
typedef EXECUTE_COMMAND_SIG(Exec_Command_Function);
|
||||
|
@ -296,9 +321,20 @@ extern "C"{
|
|||
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
|
||||
typedef GET_BUFFER_BY_NAME(Get_Buffer_By_Name_Function);
|
||||
|
||||
typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function);
|
||||
typedef BUFFER_SEEK_DELIMITER_SIG(Buffer_Seek_Delimiter_Function);
|
||||
typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function);
|
||||
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
|
||||
|
||||
// View manipulation
|
||||
typedef GET_VIEW_MAX_INDEX_SIG(Get_View_Max_Index_Function);
|
||||
typedef GET_VIEW_SIG(Get_View_Function);
|
||||
typedef GET_ACTIVE_VIEW_SIG(Get_Active_View_Function);
|
||||
|
||||
typedef REFRESH_VIEW_SIG(Refresh_View_Function);
|
||||
typedef VIEW_SET_CURSOR_SIG(View_Set_Cursor_Function);
|
||||
typedef VIEW_SET_MARK_SIG(View_Set_Mark_Function);
|
||||
typedef VIEW_SET_FILE_SIG(View_Set_File_Function);
|
||||
}
|
||||
|
||||
struct Application_Links{
|
||||
|
@ -319,9 +355,20 @@ struct Application_Links{
|
|||
Get_Active_Buffer_Function *get_active_buffer;
|
||||
Get_Buffer_By_Name_Function *get_buffer_by_name;
|
||||
|
||||
Refresh_Buffer_Function *refresh_buffer;
|
||||
Buffer_Seek_Delimiter_Function *buffer_seek_delimiter;
|
||||
Buffer_Read_Range_Function *buffer_read_range;
|
||||
Buffer_Replace_Range_Function *buffer_replace_range;
|
||||
|
||||
// View manipulation
|
||||
Get_View_Max_Index_Function *get_view_max_index;
|
||||
Get_View_Function *get_view;
|
||||
Get_Active_View_Function *get_active_view;
|
||||
|
||||
Refresh_View_Function *refresh_view;
|
||||
View_Set_Cursor_Function *view_set_cursor;
|
||||
View_Set_Mark_Function *view_set_mark;
|
||||
View_Set_File_Function *view_set_file;
|
||||
};
|
||||
|
||||
struct Custom_API{
|
||||
|
|
|
@ -92,61 +92,34 @@ end_map(Bind_Helper *helper){
|
|||
helper->group = 0;
|
||||
}
|
||||
|
||||
struct Bind_Target{
|
||||
short code;
|
||||
unsigned char modifiers;
|
||||
};
|
||||
|
||||
inline Bind_Target
|
||||
tkey(short code, unsigned char modifiers){
|
||||
Bind_Target target;
|
||||
target.code = code;
|
||||
target.modifiers = modifiers;
|
||||
return target;
|
||||
}
|
||||
|
||||
inline void
|
||||
bind(Bind_Helper *helper, Bind_Target target, int cmdid){
|
||||
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
|
||||
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
|
||||
if (!helper->error) ++helper->group->map_begin.bind_count;
|
||||
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_binding;
|
||||
unit.binding.command_id = cmdid;
|
||||
unit.binding.code = target.code;
|
||||
unit.binding.modifiers = target.modifiers;
|
||||
unit.binding.code = code;
|
||||
unit.binding.modifiers = modifiers;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind(Bind_Helper *helper, Bind_Target target, Custom_Command_Function *func){
|
||||
bind(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
|
||||
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
|
||||
if (!helper->error) ++helper->group->map_begin.bind_count;
|
||||
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_callback;
|
||||
unit.callback.func = func;
|
||||
unit.callback.code = target.code;
|
||||
unit.callback.modifiers = target.modifiers;
|
||||
unit.callback.code = code;
|
||||
unit.callback.modifiers = modifiers;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
|
||||
Bind_Target target;
|
||||
target = tkey(code, modifiers);
|
||||
bind(helper, target, cmdid);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
|
||||
Bind_Target target;
|
||||
target = tkey(code, modifiers);
|
||||
bind(helper, target, func);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_vanilla_keys(Bind_Helper *helper, int cmdid){
|
||||
bind(helper, 0, 0, cmdid);
|
||||
|
|
235
4ed.cpp
235
4ed.cpp
|
@ -434,7 +434,7 @@ COMMAND_DECL(search){
|
|||
view->isearch.pos = view->cursor.pos - 1;
|
||||
}
|
||||
|
||||
COMMAND_DECL(rsearch){
|
||||
COMMAND_DECL(reverse_search){
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(fixed, view);
|
||||
|
@ -1268,10 +1268,37 @@ COMMAND_DECL(auto_tab_range){
|
|||
REQ_FILE(file, view);
|
||||
USE_LAYOUT(layout);
|
||||
USE_MEM(mem);
|
||||
|
||||
|
||||
int r_start = 0, r_end = 0;
|
||||
int start_set = 0, end_set = 0;
|
||||
int clear_blank_lines = 1;
|
||||
|
||||
Command_Parameter *end = param_stack_end(&command->part);
|
||||
Command_Parameter *param = param_stack_first(&command->part, end);
|
||||
for (; param < end; param = param_next(param, end)){
|
||||
int p = dynamic_to_int(¶m->param.param);
|
||||
switch (p){
|
||||
case par_range_start:
|
||||
start_set = 1;
|
||||
r_start = dynamic_to_int(¶m->param.value);
|
||||
break;
|
||||
|
||||
case par_range_end:
|
||||
end_set = 1;
|
||||
r_end = dynamic_to_int(¶m->param.value);
|
||||
break;
|
||||
|
||||
case par_clear_blank_lines:
|
||||
clear_blank_lines = dynamic_to_bool(¶m->param.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (file->state.token_stack.tokens && file->state.tokens_complete){
|
||||
Range range = get_range(view->cursor.pos, view->mark);
|
||||
view_auto_tab_tokens(system, mem, view, layout, range.start, range.end, 1);
|
||||
if (start_set) range.start = r_start;
|
||||
if (end_set) range.end = r_end;
|
||||
view_auto_tab_tokens(system, mem, view, layout, range.start, range.end, clear_blank_lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1282,9 +1309,22 @@ COMMAND_DECL(auto_tab_line_at_cursor){
|
|||
USE_LAYOUT(layout);
|
||||
USE_MEM(mem);
|
||||
|
||||
int clear_blank_lines = 0;
|
||||
|
||||
Command_Parameter *end = param_stack_end(&command->part);
|
||||
Command_Parameter *param = param_stack_first(&command->part, end);
|
||||
for (; param < end; param = param_next(param, end)){
|
||||
int p = dynamic_to_int(¶m->param.param);
|
||||
switch (p){
|
||||
case par_clear_blank_lines:
|
||||
clear_blank_lines = dynamic_to_bool(¶m->param.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (file->state.token_stack.tokens && file->state.tokens_complete){
|
||||
i32 pos = view->cursor.pos;
|
||||
view_auto_tab_tokens(system, mem, view, layout, pos, pos, 0);
|
||||
view_auto_tab_tokens(system, mem, view, layout, pos, pos, clear_blank_lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1695,7 +1735,6 @@ COMMAND_DECL(set_settings){
|
|||
REQ_FILE_LOADING(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);
|
||||
|
@ -2026,6 +2065,17 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor
|
|||
buffer->map_id = file->settings.base_map_id;
|
||||
}
|
||||
|
||||
internal void
|
||||
fill_view_summary(File_View_Summary *view, File_View *file_view, Live_Views *live_set, Working_Set *working_set){
|
||||
view->exists = 1;
|
||||
view->view_id = (int)((char*)file_view - (char*)live_set->views) / live_set->stride;
|
||||
if (file_view->file){
|
||||
view->file_id = (int)(file_view->file - working_set->files);
|
||||
view->mark = view_compute_cursor_from_pos(file_view, file_view->mark);
|
||||
view->cursor = file_view->cursor;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"{
|
||||
EXECUTE_COMMAND_SIG(external_exec_command_keep_stack){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
|
@ -2079,29 +2129,22 @@ extern "C"{
|
|||
|
||||
GET_BUFFER_MAX_INDEX_SIG(external_get_buffer_max_index){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Working_Set *working_set;
|
||||
int max;
|
||||
working_set = cmd->working_set;
|
||||
max = working_set->file_index_count;
|
||||
Working_Set *working_set = cmd->working_set;
|
||||
int max = working_set->file_index_count;
|
||||
return(max);
|
||||
}
|
||||
|
||||
GET_BUFFER_SIG(external_get_buffer){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Editing_File *file;
|
||||
Working_Set *working_set;
|
||||
int max;
|
||||
Working_Set *working_set = cmd->working_set;
|
||||
int max = working_set->file_index_count;
|
||||
Buffer_Summary buffer = {};
|
||||
|
||||
working_set = cmd->working_set;
|
||||
max = working_set->file_index_count;
|
||||
|
||||
if (index >= 0 && index < max){
|
||||
file = working_set->files + index;
|
||||
if (!file->state.is_dummy){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 0
|
||||
fill_buffer_summary(&buffer, file, working_set);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2121,9 +2164,7 @@ extern "C"{
|
|||
working_set = cmd->working_set;
|
||||
|
||||
if (file && !file->state.is_dummy){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 0
|
||||
fill_buffer_summary(&buffer, file, working_set);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2141,15 +2182,20 @@ extern "C"{
|
|||
if (table_find(&working_set->table, filename, &index)){
|
||||
file = working_set->files + index;
|
||||
if (!file->state.is_dummy && file_is_ready(file)){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 0
|
||||
fill_buffer_summary(&buffer, file, working_set);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
REFRESH_BUFFER_SIG(external_refresh_buffer){
|
||||
int result;
|
||||
*buffer = external_get_buffer(cmd_context, buffer->file_id);
|
||||
result = buffer->exists;
|
||||
return(result);
|
||||
}
|
||||
|
||||
BUFFER_SEEK_DELIMITER_SIG(external_buffer_seek_delimiter){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Editing_File *file;
|
||||
|
@ -2237,6 +2283,135 @@ extern "C"{
|
|||
|
||||
return(result);
|
||||
}
|
||||
|
||||
GET_VIEW_MAX_INDEX_SIG(external_get_view_max_index){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Live_Views *live_set = cmd->live_set;
|
||||
int max = live_set->max;
|
||||
return(max);
|
||||
}
|
||||
|
||||
GET_VIEW_SIG(external_get_view){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Live_Views *live_set = cmd->live_set;
|
||||
int max = live_set->max;
|
||||
View *vptr;
|
||||
File_View *file_view;
|
||||
File_View_Summary view = {};
|
||||
|
||||
if (index >= 0 && index < max){
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride*index);
|
||||
file_view = view_to_file_view(vptr);
|
||||
if (file_view){
|
||||
fill_view_summary(&view, file_view, cmd->live_set, cmd->working_set);
|
||||
}
|
||||
}
|
||||
|
||||
return(view);
|
||||
}
|
||||
|
||||
GET_ACTIVE_VIEW_SIG(external_get_active_view){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
File_View_Summary view = {};
|
||||
File_View *file_view;
|
||||
|
||||
file_view = view_to_file_view(cmd->view);
|
||||
if (file_view){
|
||||
fill_view_summary(&view, file_view, cmd->live_set, cmd->working_set);
|
||||
}
|
||||
|
||||
return(view);
|
||||
}
|
||||
|
||||
REFRESH_VIEW_SIG(external_refresh_view){
|
||||
int result;
|
||||
*view = external_get_view(cmd_context, view->view_id);
|
||||
result = view->exists;
|
||||
return(result);
|
||||
}
|
||||
|
||||
VIEW_SET_CURSOR_SIG(external_view_set_cursor){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Live_Views *live_set;
|
||||
View *vptr;
|
||||
File_View *file_view;
|
||||
int result = 0;
|
||||
|
||||
if (view->exists){
|
||||
live_set = cmd->live_set;
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
|
||||
file_view = view_to_file_view(vptr);
|
||||
if (file_view){
|
||||
result = 1;
|
||||
file_view->cursor = view_compute_cursor(file_view, seek);
|
||||
if (set_preferred_x){
|
||||
file_view->preferred_x = view_get_cursor_x(file_view);
|
||||
}
|
||||
fill_view_summary(view, file_view, cmd->live_set, cmd->working_set);
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
VIEW_SET_MARK_SIG(external_view_set_mark){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Live_Views *live_set;
|
||||
View *vptr;
|
||||
File_View *file_view;
|
||||
Full_Cursor cursor;
|
||||
int result = 0;
|
||||
|
||||
if (view->exists){
|
||||
live_set = cmd->live_set;
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
|
||||
file_view = view_to_file_view(vptr);
|
||||
if (file_view){
|
||||
result = 1;
|
||||
if (seek.type != buffer_seek_pos){
|
||||
cursor = view_compute_cursor(file_view, seek);
|
||||
file_view->mark = cursor.pos;
|
||||
}
|
||||
else{
|
||||
file_view->mark = seek.pos;
|
||||
}
|
||||
fill_view_summary(view, file_view, cmd->live_set, cmd->working_set);
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
VIEW_SET_FILE_SIG(external_view_set_file){
|
||||
Command_Data *cmd = (Command_Data*)cmd_context;
|
||||
Live_Views *live_set;
|
||||
View *vptr;
|
||||
File_View *file_view;
|
||||
Editing_File *file;
|
||||
Working_Set *working_set;
|
||||
int max, result = 0;
|
||||
|
||||
if (view->exists){
|
||||
live_set = cmd->live_set;
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
|
||||
file_view = view_to_file_view(vptr);
|
||||
if (file_view){
|
||||
working_set = cmd->working_set;
|
||||
max = working_set->file_index_count;
|
||||
if (file_id >= 0 && file_id < max){
|
||||
file = working_set->files + file_id;
|
||||
if (!file->state.is_dummy){
|
||||
view_set_file(cmd->system, file_view, file, cmd->vars->font_set, cmd->style,
|
||||
cmd->vars->hooks[hook_open_file], cmd, &app_links);
|
||||
}
|
||||
}
|
||||
|
||||
fill_view_summary(view, file_view, cmd->live_set, cmd->working_set);
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -2250,18 +2425,24 @@ app_links_init(System_Functions *system){
|
|||
app_links.directory_has_file = system->directory_has_file;
|
||||
app_links.directory_cd = system->directory_cd;
|
||||
|
||||
app_links.get_buffer_max_index = external_get_buffer_max_index;
|
||||
app_links.get_buffer = external_get_buffer;
|
||||
app_links.get_buffer_by_name = external_get_buffer_by_name;
|
||||
|
||||
app_links.get_buffer_max_index = external_get_buffer_max_index;
|
||||
app_links.get_buffer = external_get_buffer;
|
||||
app_links.get_active_buffer = external_get_active_buffer;
|
||||
app_links.get_buffer_by_name = external_get_buffer_by_name;
|
||||
|
||||
app_links.refresh_buffer = external_refresh_buffer;
|
||||
app_links.buffer_seek_delimiter = external_buffer_seek_delimiter;
|
||||
app_links.buffer_read_range = external_buffer_read_range;
|
||||
app_links.buffer_replace_range = external_buffer_replace_range;
|
||||
|
||||
app_links.get_view_max_index = external_get_view_max_index;
|
||||
app_links.get_view = external_get_view;
|
||||
app_links.get_active_view = external_get_active_view;
|
||||
|
||||
app_links.refresh_view = external_refresh_view;
|
||||
app_links.view_set_cursor = external_view_set_cursor;
|
||||
app_links.view_set_mark = external_view_set_mark;
|
||||
app_links.view_set_file = external_view_set_file;
|
||||
}
|
||||
|
||||
#if FRED_INTERNAL
|
||||
|
@ -2338,9 +2519,9 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co
|
|||
map_add(commands, 'u', MDFR_CTRL, command_to_uppercase);
|
||||
map_add(commands, 'j', MDFR_CTRL, command_to_lowercase);
|
||||
map_add(commands, '~', MDFR_CTRL, command_clean_all_lines);
|
||||
map_add(commands, 'f', MDFR_CTRL, command_search);
|
||||
|
||||
map_add(commands, 'r', MDFR_CTRL, command_rsearch);
|
||||
map_add(commands, 'f', MDFR_CTRL, command_search);
|
||||
map_add(commands, 'r', MDFR_CTRL, command_reverse_search);
|
||||
map_add(commands, 'g', MDFR_CTRL, command_goto_line);
|
||||
|
||||
map_add(commands, '\n', MDFR_NONE, compose_write_auto_tab_line);
|
||||
|
@ -2404,7 +2585,7 @@ setup_command_table(){
|
|||
SET(seek_alphanumeric_or_camel_right);
|
||||
SET(seek_alphanumeric_or_camel_left);
|
||||
SET(search);
|
||||
SET(rsearch);
|
||||
SET(reverse_search);
|
||||
SET(word_complete);
|
||||
SET(goto_line);
|
||||
SET(set_mark);
|
||||
|
|
|
@ -1207,7 +1207,6 @@ file_post_history(General_Memory *general, Editing_File *file,
|
|||
|
||||
inline Full_Cursor
|
||||
view_compute_cursor_from_pos(File_View *view, i32 pos){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
||||
Editing_File *file = view->file;
|
||||
Style *style = view->style;
|
||||
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
|
||||
|
@ -1219,16 +1218,11 @@ view_compute_cursor_from_pos(File_View *view, i32 pos){
|
|||
max_width, (f32)view->font_height, font->advance_data);
|
||||
}
|
||||
return result;
|
||||
|
||||
#else
|
||||
return view->cursor;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Full_Cursor
|
||||
view_compute_cursor_from_unwrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
|
||||
b32 round_down = 0){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
||||
Editing_File *file = view->file;
|
||||
Style *style = view->style;
|
||||
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
|
||||
|
@ -1242,16 +1236,11 @@ view_compute_cursor_from_unwrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
|
|||
}
|
||||
|
||||
return result;
|
||||
|
||||
#else
|
||||
return view->cursor;
|
||||
#endif
|
||||
}
|
||||
|
||||
internal Full_Cursor
|
||||
view_compute_cursor_from_wrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
|
||||
b32 round_down = 0){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
||||
Editing_File *file = view->file;
|
||||
Style *style = view->style;
|
||||
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
|
||||
|
@ -1265,15 +1254,10 @@ view_compute_cursor_from_wrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
|
|||
}
|
||||
|
||||
return result;
|
||||
|
||||
#else
|
||||
return view->cursor;
|
||||
#endif
|
||||
}
|
||||
|
||||
internal Full_Cursor
|
||||
view_compute_cursor_from_line_pos(File_View *view, i32 line, i32 pos){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 3
|
||||
Editing_File *file = view->file;
|
||||
Style *style = view->style;
|
||||
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
|
||||
|
@ -1286,10 +1270,31 @@ view_compute_cursor_from_line_pos(File_View *view, i32 line, i32 pos){
|
|||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Full_Cursor
|
||||
view_compute_cursor(File_View *view, Buffer_Seek seek){
|
||||
Full_Cursor result = {};
|
||||
|
||||
#else
|
||||
return view->cursor;
|
||||
#endif
|
||||
switch(seek.type){
|
||||
case buffer_seek_pos:
|
||||
result = view_compute_cursor_from_pos(view, seek.pos);
|
||||
break;
|
||||
|
||||
case buffer_seek_wrapped_xy:
|
||||
result = view_compute_cursor_from_wrapped_xy(view, seek.x, seek.y);
|
||||
break;
|
||||
|
||||
case buffer_seek_unwrapped_xy:
|
||||
result = view_compute_cursor_from_unwrapped_xy(view, seek.x, seek.y);
|
||||
break;
|
||||
|
||||
case buffer_seek_line_char:
|
||||
result = view_compute_cursor_from_line_pos(view, seek.line, seek.character);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline Full_Cursor
|
||||
|
@ -2383,8 +2388,8 @@ view_clean_whitespace(System_Functions *system, Mem_Options *mem, File_View *vie
|
|||
for (i32 line_i = 0; line_i < line_count; ++line_i){
|
||||
i32 start = file->state.buffer.line_starts[line_i];
|
||||
i32 preferred_indentation;
|
||||
bool32 all_whitespace = 0;
|
||||
bool32 all_space = 0;
|
||||
b32 all_whitespace = 0;
|
||||
b32 all_space = 0;
|
||||
i32 hard_start =
|
||||
buffer_find_hard_start(&file->state.buffer, start, &all_whitespace, &all_space,
|
||||
&preferred_indentation, 4);
|
||||
|
@ -3389,14 +3394,14 @@ kill_file(System_Functions *system, Exchange *exchange,
|
|||
internal void
|
||||
command_search(System_Functions*,Command_Data*,Command_Binding);
|
||||
internal void
|
||||
command_rsearch(System_Functions*,Command_Data*,Command_Binding);
|
||||
command_reverse_search(System_Functions*,Command_Data*,Command_Binding);
|
||||
|
||||
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:
|
||||
case FWIDG_TIMELINES:
|
||||
|
@ -3418,12 +3423,12 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
|
|||
|
||||
if (result.made_a_change ||
|
||||
binding.function == command_search ||
|
||||
binding.function == command_rsearch){
|
||||
bool32 step_forward = 0;
|
||||
bool32 step_backward = 0;
|
||||
binding.function == command_reverse_search){
|
||||
b32 step_forward = 0;
|
||||
b32 step_backward = 0;
|
||||
|
||||
if (binding.function == command_search) step_forward = 1;
|
||||
if (binding.function == command_rsearch) step_backward = 1;
|
||||
if (binding.function == command_reverse_search) step_backward = 1;
|
||||
|
||||
i32 start_pos = file_view->isearch.pos;
|
||||
if (step_forward){
|
||||
|
|
|
@ -1,481 +1,423 @@
|
|||
/*
|
||||
* 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 inline_4tech
|
||||
#define inline_4tech inline
|
||||
#endif
|
||||
|
||||
#ifndef internal_4tech
|
||||
#define internal_4tech static
|
||||
#endif
|
||||
|
||||
#ifndef memset_4tech
|
||||
#define memset_4tech memset
|
||||
#endif
|
||||
|
||||
#ifndef memzero_4tech
|
||||
#define memzero_4tech(x) ((x) = {})
|
||||
#endif
|
||||
|
||||
#ifndef memcpy_4tech
|
||||
#define memcpy_4tech memcpy
|
||||
#endif
|
||||
|
||||
#ifndef memmove_4tech
|
||||
#define memmove_4tech memmove
|
||||
#endif
|
||||
|
||||
#ifndef debug_4tech
|
||||
#define debug_4tech(x) x
|
||||
#endif
|
||||
|
||||
#ifndef assert_4tech
|
||||
#define assert_4tech assert
|
||||
#endif
|
||||
|
||||
#ifndef ceil_4tech
|
||||
#define ceil_4tech CEIL32
|
||||
#endif
|
||||
|
||||
#ifndef div_ceil_4tech
|
||||
#define div_ceil_4tech DIVCEIL32
|
||||
#endif
|
||||
|
||||
#ifndef cat_4tech
|
||||
#define cat_4tech_(a,b) a##b
|
||||
#define cat_4tech(a,b) cat_4tech_(a,b)
|
||||
#endif
|
||||
|
||||
#ifndef round_up_4tech
|
||||
internal_4tech int
|
||||
lroundup_(int x, int granularity){
|
||||
int original_x;
|
||||
original_x = x;
|
||||
x /= granularity;
|
||||
x *= granularity;
|
||||
if (x < original_x) x += granularity;
|
||||
return x;
|
||||
}
|
||||
#define round_up_4tech(x,g) lroundup_(x,g)
|
||||
#endif
|
||||
|
||||
#ifndef round_pot_4tech
|
||||
#define round_pot_4tech ROUNDPOT32
|
||||
#endif
|
||||
|
||||
#define measure_character(a,c) ((a)[c])
|
||||
|
||||
typedef struct Buffer_Edit{
|
||||
int str_start, len;
|
||||
int start, end;
|
||||
} Buffer_Edit;
|
||||
|
||||
typedef struct Buffer_Batch_State{
|
||||
int i;
|
||||
int shift_total;
|
||||
} Buffer_Batch_State;
|
||||
|
||||
typedef enum{
|
||||
buffer_seek_pos,
|
||||
buffer_seek_wrapped_xy,
|
||||
buffer_seek_unwrapped_xy,
|
||||
buffer_seek_line_char
|
||||
} Buffer_Seek_Type;
|
||||
|
||||
typedef struct Buffer_Seek{
|
||||
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 Full_Cursor{
|
||||
int pos;
|
||||
int line, character;
|
||||
float unwrapped_x, unwrapped_y;
|
||||
float wrapped_x, wrapped_y;
|
||||
} Full_Cursor;
|
||||
|
||||
#define BRFlag_Special_Character (1 << 0)
|
||||
|
||||
typedef struct Buffer_Render_Item{
|
||||
int index;
|
||||
unsigned short glyphid;
|
||||
unsigned short flags;
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
} Buffer_Render_Item;
|
||||
|
||||
inline_4tech void
|
||||
write_render_item(Buffer_Render_Item *item, int index, unsigned short 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, unsigned short glyphid,
|
||||
float x, float y, float *advance_data, float h){
|
||||
float ch_width;
|
||||
ch_width = measure_character(advance_data, (char)glyphid);
|
||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||
return(ch_width);
|
||||
}
|
||||
|
||||
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 = (float)(line_index * font_height);
|
||||
hint.unwrapped_x = 0;
|
||||
hint.wrapped_y = wrap_ys[line_index];
|
||||
hint.wrapped_x = 0;
|
||||
return(hint);
|
||||
}
|
||||
|
||||
typedef struct Cursor_With_Index{
|
||||
int pos, index;
|
||||
} Cursor_With_Index;
|
||||
|
||||
inline_4tech void
|
||||
write_cursor_with_index(Cursor_With_Index *positions, int *count, int pos){
|
||||
positions[*count].index = *count;
|
||||
positions[*count].pos = pos;
|
||||
++*count;
|
||||
}
|
||||
|
||||
#define CursorSwap__(a,b) { Cursor_With_Index t = a; a = b; b = t; }
|
||||
|
||||
internal_4tech void
|
||||
buffer_quick_sort_cursors(Cursor_With_Index *positions, int start, int pivot){
|
||||
int i, mid;
|
||||
int pivot_pos;
|
||||
|
||||
mid = start;
|
||||
pivot_pos = positions[pivot].pos;
|
||||
for (i = mid; i < pivot; ++i){
|
||||
if (positions[i].pos < pivot_pos){
|
||||
CursorSwap__(positions[mid], positions[i]);
|
||||
++mid;
|
||||
}
|
||||
}
|
||||
CursorSwap__(positions[mid], positions[pivot]);
|
||||
|
||||
if (start < mid - 1) buffer_quick_sort_cursors(positions, start, mid - 1);
|
||||
if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_quick_unsort_cursors(Cursor_With_Index *positions, int start, int pivot){
|
||||
int i, mid;
|
||||
int pivot_index;
|
||||
|
||||
mid = start;
|
||||
pivot_index = positions[pivot].index;
|
||||
for (i = mid; i < pivot; ++i){
|
||||
if (positions[i].index < pivot_index){
|
||||
CursorSwap__(positions[mid], positions[i]);
|
||||
++mid;
|
||||
}
|
||||
}
|
||||
CursorSwap__(positions[mid], positions[pivot]);
|
||||
|
||||
if (start < mid - 1) buffer_quick_unsort_cursors(positions, start, mid - 1);
|
||||
if (mid + 1 < pivot) buffer_quick_unsort_cursors(positions, mid + 1, pivot);
|
||||
}
|
||||
|
||||
#undef CursorSwap__
|
||||
|
||||
inline_4tech void
|
||||
buffer_sort_cursors(Cursor_With_Index *positions, int count){
|
||||
assert_4tech(count > 0);
|
||||
buffer_quick_sort_cursors(positions, 0, count-1);
|
||||
}
|
||||
|
||||
inline_4tech void
|
||||
buffer_unsort_cursors(Cursor_With_Index *positions, int count){
|
||||
assert_4tech(count > 0);
|
||||
buffer_quick_unsort_cursors(positions, 0, count-1);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_update_cursors(Cursor_With_Index *sorted_positions, int count, int start, int end, int len){
|
||||
Cursor_With_Index *position;
|
||||
int shift_amount;
|
||||
|
||||
shift_amount = (len - (end - start));
|
||||
|
||||
position = sorted_positions + count - 1;
|
||||
for (; position >= sorted_positions && position->pos >= end; --position) position->pos += shift_amount;
|
||||
for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start;
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, int edit_count){
|
||||
Buffer_Edit *edit;
|
||||
int i, result, start_point;
|
||||
|
||||
result = 1;
|
||||
start_point = 0;
|
||||
|
||||
edit = sorted_edits;
|
||||
for (i = 0; i < edit_count; ++i, ++edit){
|
||||
if (start_point > edit->start){
|
||||
result = 0; break;
|
||||
}
|
||||
start_point = (edit->end < edit->start + 1)?edit->start + 1:edit->end;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_batch_edit_max_shift(Buffer_Edit *sorted_edits, int edit_count){
|
||||
Buffer_Edit *edit;
|
||||
int i, result;
|
||||
int shift_total, shift_max;
|
||||
|
||||
result = 0;
|
||||
shift_total = 0;
|
||||
shift_max = 0;
|
||||
|
||||
edit = sorted_edits;
|
||||
for (i = 0; i < edit_count; ++i, ++edit){
|
||||
shift_total += (edit->len - (edit->end - edit->start));
|
||||
if (shift_total > shift_max) shift_max = shift_total;
|
||||
}
|
||||
|
||||
return(shift_max);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, int count, Buffer_Edit *sorted_edits, int edit_count){
|
||||
Cursor_With_Index *position, *end_position;
|
||||
Buffer_Edit *edit, *end_edit;
|
||||
int start, end;
|
||||
int shift_amount;
|
||||
|
||||
position = sorted_positions;
|
||||
end_position = sorted_positions + count;
|
||||
|
||||
edit = sorted_edits;
|
||||
end_edit = sorted_edits + edit_count;
|
||||
|
||||
shift_amount = 0;
|
||||
|
||||
for (; edit < end_edit && position < end_position; ++edit){
|
||||
start = edit->start;
|
||||
end = edit->end;
|
||||
|
||||
for (; position->pos < start && position < end_position; ++position){
|
||||
position->pos += shift_amount;
|
||||
}
|
||||
|
||||
for (; position->pos < end && position < end_position; ++position){
|
||||
position->pos = start + shift_amount;
|
||||
}
|
||||
|
||||
shift_amount += (edit->len - (end - start));
|
||||
}
|
||||
|
||||
for (; position < end_position; ++position){
|
||||
position->pos += shift_amount;
|
||||
}
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_convert_in(char *dest, char *src, int size){
|
||||
int i, j, k;
|
||||
|
||||
i = 0;
|
||||
k = 0;
|
||||
j = 0;
|
||||
|
||||
for (; j < size && src[j] != '\r'; ++j);
|
||||
memcpy_4tech(dest, src, j);
|
||||
|
||||
if (j < size){
|
||||
k = 1;
|
||||
++j;
|
||||
for (i = j; i < size; ++i){
|
||||
if (src[i] == '\r'){
|
||||
memcpy_4tech(dest + j - k, src + j, i - j);
|
||||
++k;
|
||||
j = i+1;
|
||||
}
|
||||
}
|
||||
memcpy_4tech(dest + j - k, src + j, i - j);
|
||||
j = i - k;
|
||||
}
|
||||
|
||||
return(j);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_in_place_convert_in(char *data, int size){
|
||||
int i, j, k;
|
||||
|
||||
i = 0;
|
||||
k = 0;
|
||||
j = 0;
|
||||
|
||||
for (; j < size && data[j] != '\r'; ++j);
|
||||
|
||||
if (j < size){
|
||||
k = 1;
|
||||
++j;
|
||||
for (i = j; i < size; ++i){
|
||||
if (data[i] == '\r'){
|
||||
memmove_4tech(data + j - k, data + j, i - j);
|
||||
++k;
|
||||
j = i+1;
|
||||
}
|
||||
}
|
||||
memmove_4tech(data + j - k, data + j, i - j);
|
||||
j = i - k;
|
||||
}
|
||||
|
||||
return(j);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_convert_out(char *dest, int max, char *src, int size, int *size_out){
|
||||
int result;
|
||||
int i, j;
|
||||
|
||||
// TODO(allen): iterative memory check?
|
||||
result = 1;
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
for (; i < size; ++i, ++j){
|
||||
if (src[i] == '\n'){
|
||||
dest[j] = '\r';
|
||||
++j;
|
||||
dest[j] = '\n';
|
||||
}
|
||||
else dest[j] = src[i];
|
||||
}
|
||||
|
||||
*size_out = j;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_in_place_convert_out(char *data, int size, int max, int *size_out){
|
||||
int result;
|
||||
int i;
|
||||
|
||||
// TODO(allen): iterative memory check?
|
||||
result = 1;
|
||||
i = 0;
|
||||
|
||||
for (; i < size; ++i){
|
||||
if (data[i] == '\n'){
|
||||
memmove_4tech(data + i + 1, data + i, size - i);
|
||||
data[i] = '\r';
|
||||
++i;
|
||||
++size;
|
||||
}
|
||||
}
|
||||
|
||||
*size_out = size;
|
||||
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);
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_alphanumeric_true(char c){
|
||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_alphanumeric(char c){
|
||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_upper(char c){
|
||||
return (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_lower(char c){
|
||||
return (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
is_match(char *a, char *b, int len){
|
||||
int result;
|
||||
|
||||
result = 1;
|
||||
for (;len > 0; --len, ++a, ++b)
|
||||
if (*a != *b) { result = 0; break; }
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include "../4coder_buffer_types.h"
|
||||
|
||||
#ifndef inline_4tech
|
||||
#define inline_4tech inline
|
||||
#endif
|
||||
|
||||
#ifndef internal_4tech
|
||||
#define internal_4tech static
|
||||
#endif
|
||||
|
||||
#ifndef memset_4tech
|
||||
#define memset_4tech memset
|
||||
#endif
|
||||
|
||||
#ifndef memzero_4tech
|
||||
#define memzero_4tech(x) ((x) = {})
|
||||
#endif
|
||||
|
||||
#ifndef memcpy_4tech
|
||||
#define memcpy_4tech memcpy
|
||||
#endif
|
||||
|
||||
#ifndef memmove_4tech
|
||||
#define memmove_4tech memmove
|
||||
#endif
|
||||
|
||||
#ifndef debug_4tech
|
||||
#define debug_4tech(x) x
|
||||
#endif
|
||||
|
||||
#ifndef assert_4tech
|
||||
#define assert_4tech assert
|
||||
#endif
|
||||
|
||||
#ifndef ceil_4tech
|
||||
#define ceil_4tech CEIL32
|
||||
#endif
|
||||
|
||||
#ifndef div_ceil_4tech
|
||||
#define div_ceil_4tech DIVCEIL32
|
||||
#endif
|
||||
|
||||
#ifndef cat_4tech
|
||||
#define cat_4tech_(a,b) a##b
|
||||
#define cat_4tech(a,b) cat_4tech_(a,b)
|
||||
#endif
|
||||
|
||||
#ifndef round_up_4tech
|
||||
internal_4tech int
|
||||
lroundup_(int x, int granularity){
|
||||
int original_x;
|
||||
original_x = x;
|
||||
x /= granularity;
|
||||
x *= granularity;
|
||||
if (x < original_x) x += granularity;
|
||||
return x;
|
||||
}
|
||||
#define round_up_4tech(x,g) lroundup_(x,g)
|
||||
#endif
|
||||
|
||||
#ifndef round_pot_4tech
|
||||
#define round_pot_4tech ROUNDPOT32
|
||||
#endif
|
||||
|
||||
#define measure_character(a,c) ((a)[c])
|
||||
|
||||
typedef struct Buffer_Edit{
|
||||
int str_start, len;
|
||||
int start, end;
|
||||
} Buffer_Edit;
|
||||
|
||||
typedef struct Buffer_Batch_State{
|
||||
int i;
|
||||
int shift_total;
|
||||
} Buffer_Batch_State;
|
||||
|
||||
#define BRFlag_Special_Character (1 << 0)
|
||||
|
||||
typedef struct Buffer_Render_Item{
|
||||
int index;
|
||||
unsigned short glyphid;
|
||||
unsigned short flags;
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
} Buffer_Render_Item;
|
||||
|
||||
inline_4tech void
|
||||
write_render_item(Buffer_Render_Item *item, int index, unsigned short 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, unsigned short glyphid,
|
||||
float x, float y, float *advance_data, float h){
|
||||
float ch_width;
|
||||
ch_width = measure_character(advance_data, (char)glyphid);
|
||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||
return(ch_width);
|
||||
}
|
||||
|
||||
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 = (float)(line_index * font_height);
|
||||
hint.unwrapped_x = 0;
|
||||
hint.wrapped_y = wrap_ys[line_index];
|
||||
hint.wrapped_x = 0;
|
||||
return(hint);
|
||||
}
|
||||
|
||||
typedef struct Cursor_With_Index{
|
||||
int pos, index;
|
||||
} Cursor_With_Index;
|
||||
|
||||
inline_4tech void
|
||||
write_cursor_with_index(Cursor_With_Index *positions, int *count, int pos){
|
||||
positions[*count].index = *count;
|
||||
positions[*count].pos = pos;
|
||||
++*count;
|
||||
}
|
||||
|
||||
#define CursorSwap__(a,b) { Cursor_With_Index t = a; a = b; b = t; }
|
||||
|
||||
internal_4tech void
|
||||
buffer_quick_sort_cursors(Cursor_With_Index *positions, int start, int pivot){
|
||||
int i, mid;
|
||||
int pivot_pos;
|
||||
|
||||
mid = start;
|
||||
pivot_pos = positions[pivot].pos;
|
||||
for (i = mid; i < pivot; ++i){
|
||||
if (positions[i].pos < pivot_pos){
|
||||
CursorSwap__(positions[mid], positions[i]);
|
||||
++mid;
|
||||
}
|
||||
}
|
||||
CursorSwap__(positions[mid], positions[pivot]);
|
||||
|
||||
if (start < mid - 1) buffer_quick_sort_cursors(positions, start, mid - 1);
|
||||
if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_quick_unsort_cursors(Cursor_With_Index *positions, int start, int pivot){
|
||||
int i, mid;
|
||||
int pivot_index;
|
||||
|
||||
mid = start;
|
||||
pivot_index = positions[pivot].index;
|
||||
for (i = mid; i < pivot; ++i){
|
||||
if (positions[i].index < pivot_index){
|
||||
CursorSwap__(positions[mid], positions[i]);
|
||||
++mid;
|
||||
}
|
||||
}
|
||||
CursorSwap__(positions[mid], positions[pivot]);
|
||||
|
||||
if (start < mid - 1) buffer_quick_unsort_cursors(positions, start, mid - 1);
|
||||
if (mid + 1 < pivot) buffer_quick_unsort_cursors(positions, mid + 1, pivot);
|
||||
}
|
||||
|
||||
#undef CursorSwap__
|
||||
|
||||
inline_4tech void
|
||||
buffer_sort_cursors(Cursor_With_Index *positions, int count){
|
||||
assert_4tech(count > 0);
|
||||
buffer_quick_sort_cursors(positions, 0, count-1);
|
||||
}
|
||||
|
||||
inline_4tech void
|
||||
buffer_unsort_cursors(Cursor_With_Index *positions, int count){
|
||||
assert_4tech(count > 0);
|
||||
buffer_quick_unsort_cursors(positions, 0, count-1);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_update_cursors(Cursor_With_Index *sorted_positions, int count, int start, int end, int len){
|
||||
Cursor_With_Index *position;
|
||||
int shift_amount;
|
||||
|
||||
shift_amount = (len - (end - start));
|
||||
|
||||
position = sorted_positions + count - 1;
|
||||
for (; position >= sorted_positions && position->pos >= end; --position) position->pos += shift_amount;
|
||||
for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start;
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, int edit_count){
|
||||
Buffer_Edit *edit;
|
||||
int i, result, start_point;
|
||||
|
||||
result = 1;
|
||||
start_point = 0;
|
||||
|
||||
edit = sorted_edits;
|
||||
for (i = 0; i < edit_count; ++i, ++edit){
|
||||
if (start_point > edit->start){
|
||||
result = 0; break;
|
||||
}
|
||||
start_point = (edit->end < edit->start + 1)?edit->start + 1:edit->end;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_batch_edit_max_shift(Buffer_Edit *sorted_edits, int edit_count){
|
||||
Buffer_Edit *edit;
|
||||
int i, result;
|
||||
int shift_total, shift_max;
|
||||
|
||||
result = 0;
|
||||
shift_total = 0;
|
||||
shift_max = 0;
|
||||
|
||||
edit = sorted_edits;
|
||||
for (i = 0; i < edit_count; ++i, ++edit){
|
||||
shift_total += (edit->len - (edit->end - edit->start));
|
||||
if (shift_total > shift_max) shift_max = shift_total;
|
||||
}
|
||||
|
||||
return(shift_max);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, int count, Buffer_Edit *sorted_edits, int edit_count){
|
||||
Cursor_With_Index *position, *end_position;
|
||||
Buffer_Edit *edit, *end_edit;
|
||||
int start, end;
|
||||
int shift_amount;
|
||||
|
||||
position = sorted_positions;
|
||||
end_position = sorted_positions + count;
|
||||
|
||||
edit = sorted_edits;
|
||||
end_edit = sorted_edits + edit_count;
|
||||
|
||||
shift_amount = 0;
|
||||
|
||||
for (; edit < end_edit && position < end_position; ++edit){
|
||||
start = edit->start;
|
||||
end = edit->end;
|
||||
|
||||
for (; position->pos < start && position < end_position; ++position){
|
||||
position->pos += shift_amount;
|
||||
}
|
||||
|
||||
for (; position->pos < end && position < end_position; ++position){
|
||||
position->pos = start + shift_amount;
|
||||
}
|
||||
|
||||
shift_amount += (edit->len - (end - start));
|
||||
}
|
||||
|
||||
for (; position < end_position; ++position){
|
||||
position->pos += shift_amount;
|
||||
}
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_convert_in(char *dest, char *src, int size){
|
||||
int i, j, k;
|
||||
|
||||
i = 0;
|
||||
k = 0;
|
||||
j = 0;
|
||||
|
||||
for (; j < size && src[j] != '\r'; ++j);
|
||||
memcpy_4tech(dest, src, j);
|
||||
|
||||
if (j < size){
|
||||
k = 1;
|
||||
++j;
|
||||
for (i = j; i < size; ++i){
|
||||
if (src[i] == '\r'){
|
||||
memcpy_4tech(dest + j - k, src + j, i - j);
|
||||
++k;
|
||||
j = i+1;
|
||||
}
|
||||
}
|
||||
memcpy_4tech(dest + j - k, src + j, i - j);
|
||||
j = i - k;
|
||||
}
|
||||
|
||||
return(j);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_in_place_convert_in(char *data, int size){
|
||||
int i, j, k;
|
||||
|
||||
i = 0;
|
||||
k = 0;
|
||||
j = 0;
|
||||
|
||||
for (; j < size && data[j] != '\r'; ++j);
|
||||
|
||||
if (j < size){
|
||||
k = 1;
|
||||
++j;
|
||||
for (i = j; i < size; ++i){
|
||||
if (data[i] == '\r'){
|
||||
memmove_4tech(data + j - k, data + j, i - j);
|
||||
++k;
|
||||
j = i+1;
|
||||
}
|
||||
}
|
||||
memmove_4tech(data + j - k, data + j, i - j);
|
||||
j = i - k;
|
||||
}
|
||||
|
||||
return(j);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_convert_out(char *dest, int max, char *src, int size, int *size_out){
|
||||
int result;
|
||||
int i, j;
|
||||
|
||||
// TODO(allen): iterative memory check?
|
||||
result = 1;
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
for (; i < size; ++i, ++j){
|
||||
if (src[i] == '\n'){
|
||||
dest[j] = '\r';
|
||||
++j;
|
||||
dest[j] = '\n';
|
||||
}
|
||||
else dest[j] = src[i];
|
||||
}
|
||||
|
||||
*size_out = j;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
eol_in_place_convert_out(char *data, int size, int max, int *size_out){
|
||||
int result;
|
||||
int i;
|
||||
|
||||
// TODO(allen): iterative memory check?
|
||||
result = 1;
|
||||
i = 0;
|
||||
|
||||
for (; i < size; ++i){
|
||||
if (data[i] == '\n'){
|
||||
memmove_4tech(data + i + 1, data + i, size - i);
|
||||
data[i] = '\r';
|
||||
++i;
|
||||
++size;
|
||||
}
|
||||
}
|
||||
|
||||
*size_out = size;
|
||||
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);
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_alphanumeric_true(char c){
|
||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_alphanumeric(char c){
|
||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_upper(char c){
|
||||
return (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_lower(char c){
|
||||
return (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
is_match(char *a, char *b, int len){
|
||||
int result;
|
||||
|
||||
result = 1;
|
||||
for (;len > 0; --len, ++a, ++b)
|
||||
if (*a != *b) { result = 0; break; }
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
Loading…
Reference in New Issue