finished up the dangling todo items: fixed the click position bug, setup auto-indent-on-save, and finished the project fkey system

This commit is contained in:
Allen Webster 2016-12-26 17:49:01 -05:00
parent cd6bed08e5
commit 9f8a00169c
13 changed files with 689 additions and 332 deletions

View File

@ -46,6 +46,7 @@ enum Special_Hook_ID{
_hook_scroll_rule = hook_type_count,
_hook_new_file,
_hook_open_file,
_hook_save_file,
_hook_command_caller,
_hook_input_filter,
};

View File

@ -12,7 +12,7 @@
#define BUFFER_REPLACE_RANGE_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, char *str, int32_t len)
#define BUFFER_COMPUTE_CURSOR_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Seek seek, Partial_Cursor *cursor_out)
#define BUFFER_BATCH_EDIT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type)
#define BUFFER_GET_SETTING_SIG(n) int32_t n(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t *value_out)
#define BUFFER_GET_SETTING_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t *value_out)
#define BUFFER_SET_SETTING_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t value)
#define BUFFER_TOKEN_COUNT_SIG(n) int32_t n(Application_Links *app, Buffer_Summary *buffer)
#define BUFFER_READ_TOKENS_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start_token, int32_t end_token, Cpp_Token *tokens_out)
@ -360,7 +360,7 @@ static inline bool32 buffer_read_range(Application_Links *app, Buffer_Summary *b
static inline bool32 buffer_replace_range(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, char *str, int32_t len){return(app->buffer_replace_range(app, buffer, start, end, str, len));}
static inline bool32 buffer_compute_cursor(Application_Links *app, Buffer_Summary *buffer, Buffer_Seek seek, Partial_Cursor *cursor_out){return(app->buffer_compute_cursor(app, buffer, seek, cursor_out));}
static inline bool32 buffer_batch_edit(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type){return(app->buffer_batch_edit(app, buffer, str, str_len, edits, edit_count, type));}
static inline int32_t buffer_get_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t *value_out){return(app->buffer_get_setting(app, buffer, setting, value_out));}
static inline bool32 buffer_get_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t *value_out){return(app->buffer_get_setting(app, buffer, setting, value_out));}
static inline bool32 buffer_set_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t value){return(app->buffer_set_setting(app, buffer, setting, value));}
static inline int32_t buffer_token_count(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_token_count(app, buffer));}
static inline bool32 buffer_read_tokens(Application_Links *app, Buffer_Summary *buffer, int32_t start_token, int32_t end_token, Cpp_Token *tokens_out){return(app->buffer_read_tokens(app, buffer, start_token, end_token, tokens_out));}
@ -428,7 +428,7 @@ static inline bool32 buffer_read_range(Application_Links *app, Buffer_Summary *b
static inline bool32 buffer_replace_range(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, char *str, int32_t len){return(app->buffer_replace_range_(app, buffer, start, end, str, len));}
static inline bool32 buffer_compute_cursor(Application_Links *app, Buffer_Summary *buffer, Buffer_Seek seek, Partial_Cursor *cursor_out){return(app->buffer_compute_cursor_(app, buffer, seek, cursor_out));}
static inline bool32 buffer_batch_edit(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type){return(app->buffer_batch_edit_(app, buffer, str, str_len, edits, edit_count, type));}
static inline int32_t buffer_get_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t *value_out){return(app->buffer_get_setting_(app, buffer, setting, value_out));}
static inline bool32 buffer_get_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t *value_out){return(app->buffer_get_setting_(app, buffer, setting, value_out));}
static inline bool32 buffer_set_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t value){return(app->buffer_set_setting_(app, buffer, setting, value));}
static inline int32_t buffer_token_count(Application_Links *app, Buffer_Summary *buffer){return(app->buffer_token_count_(app, buffer));}
static inline bool32 buffer_read_tokens(Application_Links *app, Buffer_Summary *buffer, int32_t start_token, int32_t end_token, Cpp_Token *tokens_out){return(app->buffer_read_tokens_(app, buffer, start_token, end_token, tokens_out));}

View File

@ -160,7 +160,7 @@ HOOK_SIG(my_view_adjust){
for (View_Summary view = get_view_first(app, AccessAll);
view.exists;
get_view_next(app, &view, AccessAll)){
new_wrap_width += view.file_region.x1 - view.file_region.x0;
new_wrap_width += view.view_region.x1 - view.view_region.x0;
++count;
}
@ -237,7 +237,7 @@ OPEN_FILE_HOOK_SIG(my_file_settings){
if (treat_as_code && enable_code_wrapping && buffer.size < (1 << 18)){
// NOTE(allen|a4.0.12): There is a little bit of grossness going on here.
// If we set BufferSetting_Lex to true, it will launch a lexing job.
// If a lexing job is active when we set BufferSetting_VirtualWhitespace on that call can fail.
// If a lexing job is active when we set BufferSetting_VirtualWhitespace, the call can fail.
// Unfortunantely without tokens virtual whitespace doesn't really make sense.
// So for now I have it automatically turning on lexing when virtual whitespace is turned on.
// Cleaning some of that up is a goal for future versions.
@ -253,6 +253,22 @@ OPEN_FILE_HOOK_SIG(my_file_settings){
return(0);
}
OPEN_FILE_HOOK_SIG(my_file_save){
uint32_t access = AccessAll;
Buffer_Summary buffer = get_buffer(app, buffer_id, access);
assert(buffer.exists);
int32_t is_virtual = 0;
if (automatically_indent_text_on_save && buffer_get_setting(app, &buffer, BufferSetting_VirtualWhitespace, &is_virtual)){
if (is_virtual){
auto_tab_whole_file_by_summary(app, &buffer);
}
}
// no meaning for return
return(0);
}
// NOTE(allen|a4.0.9): The input filter allows you to modify the input
// to a frame before 4coder starts processing it at all.
//
@ -292,6 +308,47 @@ CUSTOM_COMMAND_SIG(toggle_mouse){
set_mouse_suppression(app, !suppressing_mouse);
}
CUSTOM_COMMAND_SIG(execute_arbitrary_command){
// NOTE(allen): This isn't a super powerful version of this command, I will expand
// upon it so that it has all the cmdid_* commands by default. However, with this
// as an example you have everything you need to make it work already. You could
// even use app->memory to create a hash table in the start hook.
Query_Bar bar;
char space[1024];
bar.prompt = make_lit_string("Command: ");
bar.string = make_fixed_width_string(space);
if (!query_user_string(app, &bar)) return;
// NOTE(allen): Here I chose to end this query bar because when I call another
// command it might ALSO have query bars and I don't want this one hanging
// around at that point. Since the bar exists on my stack the result of the query
// is still available in bar.string though.
end_query_bar(app, &bar, 0);
if (match_ss(bar.string, make_lit_string("load project"))){
exec_command(app, load_project);
}
else if (match_ss(bar.string, make_lit_string("open all code"))){
exec_command(app, open_all_code);
}
else if(match_ss(bar.string, make_lit_string("close all code"))){
exec_command(app, close_all_code);
}
else if (match_ss(bar.string, make_lit_string("open menu"))){
exec_command(app, cmdid_open_menu);
}
else if (match_ss(bar.string, make_lit_string("dos lines"))){
exec_command(app, eol_dosify);
}
else if (match_ss(bar.string, make_lit_string("nix lines"))){
exec_command(app, eol_nixify);
}
else{
print_message(app, literal("unrecognized command\n"));
}
}
void
default_keys(Bind_Helper *context){
begin_map(context, mapid_global);
@ -326,10 +383,30 @@ default_keys(Bind_Helper *context){
bind(context, 's', MDFR_ALT, show_scrollbar);
bind(context, 'w', MDFR_ALT, hide_scrollbar);
bind(context, key_f2, MDFR_NONE, toggle_mouse);
bind(context, key_f2, MDFR_CTRL, toggle_mouse);
bind(context, key_page_up, MDFR_CTRL, toggle_fullscreen);
bind(context, 'E', MDFR_ALT, exit_4coder);
bind(context, key_f1, MDFR_NONE, project_fkey_command);
bind(context, key_f2, MDFR_NONE, project_fkey_command);
bind(context, key_f3, MDFR_NONE, project_fkey_command);
bind(context, key_f4, MDFR_NONE, project_fkey_command);
bind(context, key_f5, MDFR_NONE, project_fkey_command);
bind(context, key_f6, MDFR_NONE, project_fkey_command);
bind(context, key_f7, MDFR_NONE, project_fkey_command);
bind(context, key_f8, MDFR_NONE, project_fkey_command);
bind(context, key_f9, MDFR_NONE, project_fkey_command);
bind(context, key_f10, MDFR_NONE, project_fkey_command);
bind(context, key_f11, MDFR_NONE, project_fkey_command);
bind(context, key_f12, MDFR_NONE, project_fkey_command);
bind(context, key_f13, MDFR_NONE, project_fkey_command);
bind(context, key_f14, MDFR_NONE, project_fkey_command);
bind(context, key_f15, MDFR_NONE, project_fkey_command);
bind(context, key_f16, MDFR_NONE, project_fkey_command);
end_map(context);
begin_map(context, my_code_map);
@ -481,6 +558,7 @@ get_bindings(void *data, int32_t size){
set_hook(context, hook_view_size_change, my_view_adjust);
set_open_file_hook(context, my_file_settings);
set_save_file_hook(context, my_file_save);
set_command_caller(context, default_command_caller);
set_input_filter(context, my_suppress_mouse_filter);
set_scroll_rule(context, smooth_scroll_rule);

View File

@ -1036,15 +1036,17 @@ CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){
move_past_lead_whitespace(app, &view, &buffer);
}
static void
auto_tab_whole_file_by_summary(Application_Links *app, Buffer_Summary *buffer){
buffer_auto_indent(app, buffer, 0, buffer->size, DEF_TAB_WIDTH, DEFAULT_INDENT_FLAGS | AutoIndent_FullTokens);
}
CUSTOM_COMMAND_SIG(auto_tab_whole_file){
uint32_t access = AccessOpen;
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
buffer_auto_indent(app, &buffer,
0, buffer.size,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS | AutoIndent_FullTokens);
auto_tab_whole_file_by_summary(app, &buffer);
}
CUSTOM_COMMAND_SIG(auto_tab_range){
@ -2501,77 +2503,9 @@ CUSTOM_COMMAND_SIG(query_replace){
// Fast Buffer Management
//
CUSTOM_COMMAND_SIG(close_all_code){
String extension;
Buffer_Summary buffer;
// TODO(allen): Get better memory constructs to the custom layer
// so that it doesn't have to rely on arbitrary limits like this one.
int32_t buffers_to_close[2048];
int32_t buffers_to_close_count = 0;
uint32_t access = AccessAll;
for (buffer = get_buffer_first(app, access);
buffer.exists;
get_buffer_next(app, &buffer, access)){
extension = file_extension(make_string(buffer.file_name, buffer.file_name_len));
if (match_ss(extension, make_lit_string("cpp")) ||
match_ss(extension, make_lit_string("hpp")) ||
match_ss(extension, make_lit_string("c")) ||
match_ss(extension, make_lit_string("h")) ||
match_ss(extension, make_lit_string("cc"))){
buffers_to_close[buffers_to_close_count++] = buffer.buffer_id;
}
}
for (int32_t i = 0; i < buffers_to_close_count; ++i){
kill_buffer(app, buffer_identifier(buffers_to_close[i]), true, 0);
}
}
CUSTOM_COMMAND_SIG(open_all_code){
// NOTE(allen|a3.4.4): This method of getting the hot directory works
// because this custom.cpp gives no special meaning to app->memory
// and doesn't set up a persistent allocation system within app->memory.
// push_directory isn't a very good option since it's tied to the parameter
// stack, so I am phasing that idea out now.
String dir = make_string_cap(app->memory, 0, app->memory_size);
dir.size = directory_get_hot(app, dir.str, dir.memory_size);
int32_t dir_size = dir.size;
// NOTE(allen|a3.4.4): Here we get the list of files in this directory.
// Notice that we free_file_list at the end.
File_List list = get_file_list(app, dir.str, dir.size);
for (int32_t i = 0; i < list.count; ++i){
File_Info *info = list.infos + i;
if (!info->folder){
String extension = make_string_cap(info->filename, info->filename_len, info->filename_len+1);
extension = file_extension(extension);
if (match_ss(extension, make_lit_string("cpp")) ||
match_ss(extension, make_lit_string("hpp")) ||
match_ss(extension, make_lit_string("c")) ||
match_ss(extension, make_lit_string("h")) ||
match_ss(extension, make_lit_string("cc"))){
// NOTE(allen): There's no way in the 4coder API to use relative
// paths at the moment, so everything should be full paths. Which is
// managable. Here simply set the dir string size back to where it
// was originally, so that new appends overwrite old ones.
dir.size = dir_size;
append_sc(&dir, info->filename);
create_buffer(app, dir.str, dir.size, 0);
}
}
}
free_file_list(app, list);
}
char out_buffer_space[1024];
char command_space[1024];
char hot_directory_space[1024];
static char out_buffer_space[1024];
static char command_space[1024];
static char hot_directory_space[1024];
CUSTOM_COMMAND_SIG(execute_any_cli){
Query_Bar bar_out = {0};
@ -2591,11 +2525,7 @@ CUSTOM_COMMAND_SIG(execute_any_cli){
uint32_t access = AccessAll;
View_Summary view = get_active_view(app, access);
exec_system_command(app, &view,
buffer_identifier(bar_out.string.str, bar_out.string.size),
hot_directory.str, hot_directory.size,
bar_cmd.string.str, bar_cmd.string.size,
CLI_OverlapWithConflict | CLI_CursorAtEnd);
exec_system_command(app, &view, buffer_identifier(bar_out.string.str, bar_out.string.size), hot_directory.str, hot_directory.size, bar_cmd.string.str, bar_cmd.string.size, CLI_OverlapWithConflict | CLI_CursorAtEnd);
}
CUSTOM_COMMAND_SIG(execute_previous_cli){
@ -2607,11 +2537,7 @@ CUSTOM_COMMAND_SIG(execute_previous_cli){
uint32_t access = AccessAll;
View_Summary view = get_active_view(app, access);
exec_system_command(app, &view,
buffer_identifier(out_buffer.str, out_buffer.size),
hot_directory.str, hot_directory.size,
cmd.str, cmd.size,
CLI_OverlapWithConflict | CLI_CursorAtEnd);
exec_system_command(app, &view, buffer_identifier(out_buffer.str, out_buffer.size), hot_directory.str, hot_directory.size, cmd.str, cmd.size, CLI_OverlapWithConflict | CLI_CursorAtEnd);
}
}
@ -2698,8 +2624,7 @@ get_search_all_string(Application_Links *app, Query_Bar *bar){
}
static void
generic_search_all_buffers(Application_Links *app, General_Memory *general, Partition *part,
String string, uint32_t match_flags){
generic_search_all_buffers(Application_Links *app, General_Memory *general, Partition *part, String string, uint32_t match_flags){
Search_Set set = {0};
Search_Iter iter = {0};
@ -2828,32 +2753,28 @@ CUSTOM_COMMAND_SIG(list_all_locations){
Query_Bar bar;
get_search_all_string(app, &bar);
if (bar.string.size == 0) return;
generic_search_all_buffers(app, &global_general, &global_part,
bar.string, SearchFlag_MatchWholeWord);
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_MatchWholeWord);
}
CUSTOM_COMMAND_SIG(list_all_substring_locations){
Query_Bar bar;
get_search_all_string(app, &bar);
if (bar.string.size == 0) return;
generic_search_all_buffers(app, &global_general, &global_part,
bar.string, SearchFlag_MatchSubstring);
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_MatchSubstring);
}
CUSTOM_COMMAND_SIG(list_all_locations_case_insensitive){
Query_Bar bar;
get_search_all_string(app, &bar);
if (bar.string.size == 0) return;
generic_search_all_buffers(app, &global_general, &global_part,
bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchWholeWord);
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchWholeWord);
}
CUSTOM_COMMAND_SIG(list_all_substring_locations_case_insensitive){
Query_Bar bar;
get_search_all_string(app, &bar);
if (bar.string.size == 0) return;
generic_search_all_buffers(app, &global_general, &global_part,
bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchSubstring);
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchSubstring);
}
CUSTOM_COMMAND_SIG(list_all_locations_of_identifier){
@ -3132,12 +3053,7 @@ standard_build_search(Application_Links *app, View_Summary *view, Buffer_Summary
append_s_char(&message, '\n');
print_message(app, message.str, message.size);
exec_system_command(app, view,
buffer_identifier(literal("*compilation*")),
dir->str, dir->size,
command->str, command->size,
CLI_OverlapWithConflict);
exec_system_command(app, view, buffer_identifier(literal("*compilation*")), dir->str, dir->size, command->str, command->size, CLI_OverlapWithConflict);
result = true;
break;
}
@ -3150,11 +3066,7 @@ standard_build_search(Application_Links *app, View_Summary *view, Buffer_Summary
String backup_command = make_fixed_width_string(backup_space);
append_ss(&backup_command, make_lit_string("echo could not find "));
append_ss(&backup_command, filename);
exec_system_command(app, view,
buffer_identifier(literal("*compilation*")),
dir->str, dir->size,
backup_command.str, backup_command.size,
CLI_OverlapWithConflict);
exec_system_command(app, view, buffer_identifier(literal("*compilation*")), dir->str, dir->size, backup_command.str, backup_command.size, CLI_OverlapWithConflict);
}
break;
}
@ -3170,11 +3082,7 @@ static int32_t
execute_standard_build_search(Application_Links *app, View_Summary *view,
Buffer_Summary *active_buffer,
String *dir, String *command, int32_t perform_backup){
int32_t result = standard_build_search(app, view,
active_buffer,
dir, command, perform_backup, true,
make_lit_string("build.bat"),
make_lit_string("build"));
int32_t result = standard_build_search(app, view, active_buffer, dir, command, perform_backup, true, make_lit_string("build.bat"), make_lit_string("build"));
return(result);
}
@ -3183,7 +3091,6 @@ execute_standard_build_search(Application_Links *app, View_Summary *view,
// NOTE(allen): Build search rule for linux.
static int32_t
execute_standard_build_search(Application_Links *app, View_Summary *view, Buffer_Summary *active_buffer, String *dir, String *command, bool32 perform_backup){
char dir_space[512];
String dir_copy = make_fixed_width_string(dir_space);
copy(&dir_copy, *dir);
@ -3205,8 +3112,7 @@ execute_standard_build_search(Application_Links *app, View_Summary *view, Buffer
// NOTE(allen): This searches first using the active file's directory,
// then if no build script is found, it searches from 4coders hot directory.
static void
execute_standard_build(Application_Links *app, View_Summary *view,
Buffer_Summary *active_buffer){
execute_standard_build(Application_Links *app, View_Summary *view, Buffer_Summary *active_buffer){
char dir_space[512];
String dir = make_fixed_width_string(dir_space);
@ -3216,8 +3122,7 @@ execute_standard_build(Application_Links *app, View_Summary *view,
int32_t build_dir_type = get_build_directory(app, active_buffer, &dir);
if (build_dir_type == BuildDir_AtFile){
if (!execute_standard_build_search(app, view, active_buffer,
&dir, &command, false)){
if (!execute_standard_build_search(app, view, active_buffer, &dir, &command, false)){
dir.size = 0;
command.size = 0;
build_dir_type = get_build_directory(app, 0, &dir);
@ -3225,8 +3130,7 @@ execute_standard_build(Application_Links *app, View_Summary *view,
}
if (build_dir_type == BuildDir_AtHot){
execute_standard_build_search(app, view, active_buffer,
&dir, &command, true);
execute_standard_build_search(app, view, active_buffer, &dir, &command, true);
}
}
@ -3296,48 +3200,6 @@ CUSTOM_COMMAND_SIG(change_to_build_panel){
}
}
//
// Other
//
CUSTOM_COMMAND_SIG(execute_arbitrary_command){
// NOTE(allen): This isn't a super powerful version of this command, I will expand
// upon it so that it has all the cmdid_* commands by default. However, with this
// as an example you have everything you need to make it work already. You could
// even use app->memory to create a hash table in the start hook.
Query_Bar bar;
char space[1024];
bar.prompt = make_lit_string("Command: ");
bar.string = make_fixed_width_string(space);
if (!query_user_string(app, &bar)) return;
// NOTE(allen): Here I chose to end this query bar because when I call another
// command it might ALSO have query bars and I don't want this one hanging
// around at that point. Since the bar exists on my stack the result of the query
// is still available in bar.string though.
end_query_bar(app, &bar, 0);
if (match_ss(bar.string, make_lit_string("open all code"))){
exec_command(app, open_all_code);
}
else if(match_ss(bar.string, make_lit_string("close all code"))){
exec_command(app, close_all_code);
}
else if (match_ss(bar.string, make_lit_string("open menu"))){
exec_command(app, cmdid_open_menu);
}
else if (match_ss(bar.string, make_lit_string("dos lines"))){
exec_command(app, eol_dosify);
}
else if (match_ss(bar.string, make_lit_string("nix lines"))){
exec_command(app, eol_nixify);
}
else{
print_message(app, literal("unrecognized command\n"));
}
}
// NOTE(allen|a4): scroll rule information
//
// The parameters:
@ -3454,6 +3316,7 @@ struct Config_Line{
struct Config_Item{
Config_Line line;
Cpp_Token_Array array;
char *mem;
String id;
int32_t subscript_index;
@ -3461,6 +3324,7 @@ struct Config_Item{
};
struct Config_Array_Reader{
Cpp_Token_Array array;
char *mem;
int32_t i;
int32_t val_array_end;
@ -3484,7 +3348,7 @@ read_config_token(Cpp_Token_Array array, int32_t *i_ptr){
token = array.tokens[i];
}
i = *i_ptr;
*i_ptr = i;
return(token);
}
@ -3502,7 +3366,7 @@ read_config_line(Cpp_Token_Array array, int32_t *i_ptr){
Cpp_Token token = read_config_token(array, &i);
bool32 subscript_success = 1;
if (token.type == CPP_TOKEN_BRACE_OPEN){
if (token.type == CPP_TOKEN_BRACKET_OPEN){
subscript_success = 0;
++i;
if (i < array.count){
@ -3511,7 +3375,7 @@ read_config_line(Cpp_Token_Array array, int32_t *i_ptr){
++i;
if (i < array.count){
token = read_config_token(array, &i);
if (token.type == CPP_TOKEN_BRACE_CLOSE){
if (token.type == CPP_TOKEN_BRACKET_CLOSE){
++i;
if (i < array.count){
token = read_config_token(array, &i);
@ -3540,7 +3404,10 @@ read_config_line(Cpp_Token_Array array, int32_t *i_ptr){
bool32 expecting_array_item = 1;
for (; i < array.count; ++i){
Cpp_Token array_token = read_config_token(array, &i);
if (array_token.type != CPP_TOKEN_BRACE_CLOSE){
if (array_token.size == 0){
break;
}
if (array_token.type == CPP_TOKEN_BRACE_CLOSE){
config_line.val_array_end = i;
array_success = 1;
break;
@ -3596,11 +3463,14 @@ read_config_line(Cpp_Token_Array array, int32_t *i_ptr){
}
static Config_Item
get_config_item(Config_Line line, char *mem){
get_config_item(Config_Line line, char *mem, Cpp_Token_Array array){
Config_Item item = {0};
item.line = line;
item.array = array;
item.mem = mem;
item.id = make_string(mem + line.id_token.start,line.id_token.size);
if (line.id_token.size != 0){
item.id = make_string(mem + line.id_token.start, line.id_token.size);
}
if (line.subscript_token.size != 0){
String subscript_str = make_string(mem + line.subscript_token.start,line.subscript_token.size);
@ -3625,6 +3495,7 @@ config_var(Config_Item item, char *var_name, int32_t *subscript, uint32_t token_
subscript_succes = 0;
}
}
if (subscript_succes){
if (var_out){
switch (token_type){
@ -3647,6 +3518,7 @@ config_var(Config_Item item, char *var_name, int32_t *subscript, uint32_t token_
case CPP_TOKEN_BRACE_OPEN:
{
Config_Array_Reader *array_reader = (Config_Array_Reader*)var_out;
array_reader->array = item.array;
array_reader->mem = item.mem;
array_reader->i = item.line.val_array_start;
array_reader->val_array_end = item.line.val_array_end;
@ -3687,9 +3559,37 @@ config_array_var(Config_Item item, char *var_name, int32_t *subscript, Config_Ar
static bool32
config_array_next_item(Config_Array_Reader *array_reader, Config_Item *item){
bool32 result = 0;
for (;array_reader->i < array_reader->val_array_end;
++array_reader->i){
Cpp_Token array_token = read_config_token(array_reader->array, &array_reader->i);
if (array_token.size == 0 || array_reader->i >= array_reader->val_array_end){
break;
}
if (array_token.type == CPP_TOKEN_BRACE_CLOSE){
break;
}
switch (array_token.type){
case CPP_TOKEN_BOOLEAN_CONSTANT:
case CPP_TOKEN_INTEGER_CONSTANT:
case CPP_TOKEN_STRING_CONSTANT:
{
Config_Line line = {0};
line.val_token = array_token;
line.read_success = 1;
*item = get_config_item(line, array_reader->mem, array_reader->array);
result = 1;
++array_reader->i;
goto doublebreak;
}break;
}
}
doublebreak:;
bool32 result = (array_reader->good);
array_reader->good = result;
return(result);
}
@ -3705,6 +3605,8 @@ static bool32 enable_code_wrapping = 1;
static bool32 automatically_adjust_wrapping = 1;
static int32_t default_wrap_width = 672;
static int32_t default_min_base_width = 550;
static bool32 automatically_indent_text_on_save = 1;
static String default_theme_name = make_lit_string("4coder");
static String default_font_name = make_lit_string("Liberation Sans");
@ -3782,10 +3684,11 @@ process_config_file(Application_Links *app){
Config_Line config_line = read_config_line(array, &i);
if (config_line.read_success){
Config_Item item = get_config_item(config_line, mem);
Config_Item item = get_config_item(config_line, mem, array);
config_bool_var(item, "enable_code_wrapping", 0, &enable_code_wrapping);
config_bool_var(item, "automatically_adjust_wrapping", 0, &automatically_adjust_wrapping);
config_bool_var(item, "automatically_indent_text_on_save", 0, &automatically_indent_text_on_save);
config_int_var(item, "default_wrap_width", 0, &new_wrap_width);
config_int_var(item, "default_min_base_width", 0, &new_min_base_width);
@ -3807,7 +3710,223 @@ process_config_file(Application_Links *app){
// NOTE(allen): Project system setup
static char *loaded_project = 0;
static char *default_extensions[] = {
"cpp",
"hpp",
"c",
"h",
"cc"
};
struct Fkey_Command{
char command[128];
char out[128];
bool32 use_build_panel;
};
struct Project{
char dir_space[256];
char *dir;
int32_t dir_len;
char extension_space[256];
char *extensions[94];
int32_t extension_count;
Fkey_Command fkey_commands[16];
bool32 close_all_code_when_this_project_closes;
bool32 close_all_files_when_project_opens;
};
static Project null_project = {};
static Project current_project = {};
static void
set_project_extensions(Project *project, String src){
int32_t mode = 0;
int32_t j = 0, k = 0;
for (int32_t i = 0; i < src.size; ++i){
switch (mode){
case 0:
{
if (src.str[i] == '.'){
mode = 1;
project->extensions[k++] = &project->extension_space[j];
}
}break;
case 1:
{
if (src.str[i] == '.'){
project->extension_space[j++] = 0;
project->extensions[k++] = &project->extension_space[j];
}
else{
project->extension_space[j++] = src.str[i];
}
}break;
}
}
project->extension_space[j++] = 0;
project->extension_count = k;
}
// TODO(allen): make this a string operation or a lexer operation or something
static void
interpret_escaped_string(char *dst, String src){
int32_t mode = 0;
int32_t j = 0;
for (int32_t i = 0; i < src.size; ++i){
switch (mode){
case 0:
{
if (src.str[i] == '\\'){
mode = 1;
}
else{
dst[j++] = src.str[i];
}
}break;
case 1:
{
switch (src.str[i]){
case '\\':{dst[j++] = '\\'; mode = 0;}break;
case 'n': {dst[j++] = '\n'; mode = 0;}break;
case 't': {dst[j++] = '\t'; mode = 0;}break;
case '"': {dst[j++] = '"'; mode = 0;}break;
case '0': {dst[j++] = '\0'; mode = 0;}break;
}
}break;
}
}
dst[j] = 0;
}
static void
close_all_files_with_extension(Application_Links *app, Partition *scratch_part, char **extension_list, int32_t extension_count){
Temp_Memory temp = begin_temp_memory(scratch_part);
int32_t buffers_to_close_max = partition_remaining(scratch_part)/sizeof(int32_t);
int32_t *buffers_to_close = push_array(scratch_part, int32_t, buffers_to_close_max);
int32_t buffers_to_close_count = 0;
bool32 do_repeat = 0;
do{
buffers_to_close_count = 0;
do_repeat = 0;
uint32_t access = AccessAll;
Buffer_Summary buffer = {0};
for (buffer = get_buffer_first(app, access);
buffer.exists;
get_buffer_next(app, &buffer, access)){
bool32 is_match = 1;
if (extension_count > 0){
String extension = file_extension(make_string(buffer.file_name, buffer.file_name_len));
is_match = 0;
for (int32_t i = 0; i < extension_count; ++i){
if (match(extension, extension_list[i])){
is_match = 1;
break;
}
}
}
if (is_match){
if (buffers_to_close_count >= buffers_to_close_max){
do_repeat = 1;
break;
}
buffers_to_close[buffers_to_close_count++] = buffer.buffer_id;
}
}
for (int32_t i = 0; i < buffers_to_close_count; ++i){
kill_buffer(app, buffer_identifier(buffers_to_close[i]), true, 0);
}
}
while(do_repeat);
end_temp_memory(temp);
}
static void
open_all_files_with_extension(Application_Links *app, Partition *scratch_part, char **extension_list, int32_t extension_count){
Temp_Memory temp = begin_temp_memory(scratch_part);
int32_t max_size = partition_remaining(scratch_part);
char *memory = push_array(scratch_part, char, max_size);
String dir = make_string_cap(memory, 0, max_size);
dir.size = directory_get_hot(app, dir.str, dir.memory_size);
int32_t dir_size = dir.size;
// NOTE(allen|a3.4.4): Here we get the list of files in this directory.
// Notice that we free_file_list at the end.
File_List list = get_file_list(app, dir.str, dir.size);
for (int32_t i = 0; i < list.count; ++i){
File_Info *info = list.infos + i;
if (!info->folder){
bool32 is_match = 1;
if (extension_count > 0){
is_match = 0;
String extension = make_string_cap(info->filename, info->filename_len, info->filename_len+1);
extension = file_extension(extension);
for (int32_t j = 0; j < extension_count; ++j){
if (match(extension, extension_list[j])){
is_match = 1;
break;
}
}
if (is_match){
// NOTE(allen): There's no way in the 4coder API to use relative
// paths at the moment, so everything should be full paths. Which is
// managable. Here simply set the dir string size back to where it
// was originally, so that new appends overwrite old ones.
dir.size = dir_size;
append_sc(&dir, info->filename);
create_buffer(app, dir.str, dir.size, 0);
}
}
}
}
free_file_list(app, list);
end_temp_memory(temp);
}
static char**
get_standard_code_extensions(int32_t *extension_count_out){
char **extension_list = default_extensions;
int32_t extension_count = ArrayCount(default_extensions);
if (current_project.dir != 0){
extension_list = current_project.extensions;
extension_count = current_project.extension_count;
}
*extension_count_out = extension_count;
return(extension_list);
}
// NOTE(allen|a4.0.14): open_all_code and close_all_code now use the extensions set in the loaded project. If there is no project loaded the extensions ".cpp.hpp.c.h.cc" are used.
CUSTOM_COMMAND_SIG(open_all_code){
int32_t extension_count = 0;
char **extension_list = get_standard_code_extensions(&extension_count);
open_all_files_with_extension(app, &global_part, extension_list, extension_count);
}
CUSTOM_COMMAND_SIG(close_all_code){
int32_t extension_count = 0;
char **extension_list = get_standard_code_extensions(&extension_count);
close_all_files_with_extension(app, &global_part, extension_list, extension_count);
}
CUSTOM_COMMAND_SIG(load_project){
Partition *part = &global_part;
@ -3820,114 +3939,255 @@ CUSTOM_COMMAND_SIG(load_project){
}
if (project_name.size != 0){
append_sc(&project_name, "/project.4coder");
terminate_with_null(&project_name);
FILE *file = fopen(project_name.str, "rb");
if (file){
Temp_Memory temp = begin_temp_memory(part);
int32_t original_size = project_name.size;
append_sc(&project_name, "project.4coder");
terminate_with_null(&project_name);
char *mem = 0;
int32_t size = 0;
bool32 file_read_success = file_handle_dump(part, file, &mem, &size);
if (file_read_success){
fclose(file);
// TODO(allen): make sure we do nothing when this project is already open
FILE *file = fopen(project_name.str, "rb");
if (file){
project_name.size = original_size;
terminate_with_null(&project_name);
Cpp_Token_Array array;
array.count = 0;
array.max_count = (1 << 20)/sizeof(Cpp_Token);
array.tokens = push_array(&global_part, Cpp_Token, array.max_count);
Cpp_Lex_Data S = cpp_lex_data_init();
Cpp_Lex_Result result = cpp_lex_step(&S, mem, size+1, HAS_NULL_TERM, &array, NO_OUT_LIMIT);
if (result == LexResult_Finished){
for (int32_t i = 0; i < array.count; ++i){
Config_Line config_line = read_config_line(array, &i);
if (config_line.read_success){
Config_Item item = get_config_item(config_line, mem);
{
String str = {0};
if (config_string_var(item, "extensions", 0, &str)){
// TODO(allen)
}
}
Temp_Memory temp = begin_temp_memory(part);
char *mem = 0;
int32_t size = 0;
bool32 file_read_success = file_handle_dump(part, file, &mem, &size);
if (file_read_success){
fclose(file);
{
#if WIN
#define FKEY_COMMAND "fkey_command_wnd"
#else
#define FKEY_COMMAND "fkey_command_linux"
#endif
Cpp_Token_Array array;
array.count = 0;
array.max_count = (1 << 20)/sizeof(Cpp_Token);
array.tokens = push_array(&global_part, Cpp_Token, array.max_count);
Cpp_Lex_Data S = cpp_lex_data_init();
Cpp_Lex_Result result = cpp_lex_step(&S, mem, size+1, HAS_NULL_TERM, &array, NO_OUT_LIMIT);
if (result == LexResult_Finished){
// Clear out current project
if (current_project.close_all_code_when_this_project_closes){
exec_command(app, close_all_code);
}
current_project = null_project;
int32_t index = 0;
Config_Array_Reader array_reader = {0};
if (config_array_var(item, FKEY_COMMAND, &index, &array_reader)){
if (index >= 1 && index <= 16){
Config_Item array_item = {0};
int32_t item_index = 0;
for (config_array_next_item(&array_reader, &array_item);
config_array_good(&array_reader);
config_array_next_item(&array_reader, &array_item)){
if (item_index >= 2){
break;
// Set new project directory
{
current_project.dir = current_project.dir_space;
String str = make_fixed_width_string(current_project.dir_space);
copy(&str, project_name);
terminate_with_null(&str);
current_project.dir_len = str.size;
}
// Read the settings from project.4coder
for (int32_t i = 0; i < array.count; ++i){
Config_Line config_line = read_config_line(array, &i);
if (config_line.read_success){
Config_Item item = get_config_item(config_line, mem, array);
{
String str = {0};
if (config_string_var(item, "extensions", 0, &str)){
if (str.size < sizeof(current_project.extension_space)){
set_project_extensions(&current_project, str);
print_message(app, str.str, str.size);
print_message(app, "\n", 1);
}
else{
print_message(app, literal("STRING TOO LONG!\n"));
}
}
}
switch (item_index){
case 0:
{
if (config_int_var(array_item, 0, 0, 0)){
// TODO(allen)
}
String str = {0};
if (config_string_var(array_item, 0, 0, &str)){
// TODO(allen)
}
}break;
{
#if defined(_WIN32)
#define FKEY_COMMAND "fkey_command_win"
#elif defined(__linux__)
#define FKEY_COMMAND "fkey_command_linux"
#else
#error no project configuration names for this platform
#endif
case 1:
{
if (config_int_var(array_item, 0, 0, 0)){
// TODO(allen)
int32_t index = 0;
Config_Array_Reader array_reader = {0};
if (config_array_var(item, FKEY_COMMAND, &index, &array_reader)){
if (index >= 1 && index <= 16){
Config_Item array_item = {0};
int32_t item_index = 0;
char space[256];
String msg = make_fixed_width_string(space);
append(&msg, FKEY_COMMAND"[");
append_int_to_str(&msg, index);
append(&msg, "] = {");
for (config_array_next_item(&array_reader, &array_item);
config_array_good(&array_reader);
config_array_next_item(&array_reader, &array_item)){
if (item_index >= 3){
break;
}
append(&msg, "[");
append_int_to_str(&msg, item_index);
append(&msg, "] = ");
bool32 read_string = 0;
bool32 read_bool = 0;
char *dest_str = 0;
int32_t dest_str_size = 0;
bool32 *dest_bool = 0;
switch (item_index){
case 0:
{
dest_str = current_project.fkey_commands[index-1].command;
dest_str_size = sizeof(current_project.fkey_commands[index-1].command);
read_string = 1;
}break;
case 1:
{
dest_str = current_project.fkey_commands[index-1].out;
dest_str_size = sizeof(current_project.fkey_commands[index-1].out);
read_string = 1;
}break;
case 2:
{
dest_bool = &current_project.fkey_commands[index-1].use_build_panel;
read_bool = 1;
}break;
}
if (read_string){
if (config_int_var(array_item, 0, 0, 0)){
append(&msg, "NULL, ");
dest_str[0] = 0;
}
String str = {0};
if (config_string_var(array_item, 0, 0, &str)){
if (str.size < dest_str_size){
interpret_escaped_string(dest_str, str);
append(&msg, dest_str);
append(&msg, ", ");
}
else{
append(&msg, "STRING TOO LONG!, ");
}
}
}
String str = {0};
if (config_string_var(array_item, 0, 0, &str)){
// TODO(allen)
if (read_bool){
if (config_bool_var(array_item, 0, 0, dest_bool)){
if (dest_bool){
append(&msg, "true, ");
}
else{
append(&msg, "false, ");
}
}
}
}break;
item_index++;
}
append(&msg, "}\n");
print_message(app, msg.str, msg.size);
}
}
}
item_index++;
}
}
if (current_project.close_all_files_when_project_opens){
close_all_files_with_extension(app, &global_part, 0, 0);
}
// Open all project files
exec_command(app, open_all_code);
}
}
end_temp_memory(temp);
}
else{
char message_space[512];
String message = make_fixed_width_string(message_space);
append_sc(&message, "Did not find project.4coder. ");
if (current_project.dir != 0){
append_sc(&message, "Continuing with: ");
append_sc(&message, current_project.dir);
}
else{
append_sc(&message, "Continuing without a project");
}
print_message(app, message.str, message.size);
}
}
else{
print_message(app, literal("Failed trying to get project file name"));
}
}
CUSTOM_COMMAND_SIG(project_fkey_command){
User_Input input = get_command_input(app);
if (input.type == UserInputKey){
if (input.key.keycode >= key_f1 && input.key.keycode <= key_f16){
int32_t ind = (input.key.keycode - key_f1);
char *command = current_project.fkey_commands[ind].command;
char *out = current_project.fkey_commands[ind].out;
bool32 use_build_panel = current_project.fkey_commands[ind].use_build_panel;
if (command[0] != 0){
int32_t command_len = str_size(command);
View_Summary view_ = {0};
View_Summary *view = 0;
Buffer_Identifier buffer_id = {0};
uint32_t flags = 0;
bool32 set_fancy_font = 0;
if (out[0] != 0){
int32_t out_len = str_size(out);
buffer_id = buffer_identifier(out, out_len);
view = &view_;
if (use_build_panel){
view_ = get_or_open_build_panel(app);
if (match(out, "*compilation*")){
set_fancy_font = 1;
}
}
else{
view_ = get_active_view(app, AccessAll);
}
prev_location = null_location;
lock_jump_buffer(out, out_len);
}
else{
// TODO(allen): fix the exec_system_command call so it can take a null buffer_id.
buffer_id = buffer_identifier(literal("*dump*"));
}
exec_system_command(app, view, buffer_id, current_project.dir, current_project.dir_len, command, command_len, flags);
if (set_fancy_font){
set_fancy_compilation_buffer_font(app);
}
}
}
}
end_temp_memory(temp);
}
else{
char message_space[512];
String message = make_fixed_width_string(message_space);
append_sc(&message, "Did not find project.4coder. ");
if (loaded_project != 0){
append_sc(&message, "Continuing with: ");
append_sc(&message, loaded_project);
}
else{
append_sc(&message, "Continuing without a project");
}
print_message(app, message.str, message.size);
}
}
else{
print_message(app, literal("Failed trying to get project file name"));
}
}
#endif

View File

@ -179,6 +179,16 @@ set_open_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
write_unit(helper, unit);
}
inline void
set_save_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
Binding_Unit unit;
unit.type = unit_hook;
unit.hook.hook_id = _hook_save_file;
unit.hook.func = (void*) func;
write_unit(helper, unit);
}
inline void
set_command_caller(Bind_Helper *helper, Command_Caller_Hook_Function *func){
Binding_Unit unit;

View File

@ -668,7 +668,11 @@ STRUCT View_Summary{
bool32 show_whitespace;
/*
DOC(If this is not a null summary, this describes the screen position in which this view's buffer is displayed.)
DOC(If this is not a null summary, this describes the screen position in which this view's is displayed.)
*/
i32_Rect view_region;
/*
DOC(If this is not a null summary, this describes the screen position in which this view's buffer is displayed. This is different from view_region, because it does not include any fixed height GUI at the top of the view.)
*/
i32_Rect file_region;
/* DOC(If this is not a null summary, this describes the scrolling position inside the view.) */

13
4ed.cpp
View File

@ -414,7 +414,7 @@ COMMAND_DECL(save){
REQ_FILE(file, view);
if (!file->is_dummy && file_is_ready(file) && buffer_can_save(file)){
save_file(system, &models->mem, file);
save_file(system, models, file);
}
}
@ -422,9 +422,7 @@ COMMAND_DECL(save_as){
USE_VIEW(view);
REQ_FILE(file, view);
view_show_interactive(system, view,
IAct_Save_As, IInt_Sys_File_List,
make_lit_string("Save As: "));
view_show_interactive(system, view, IAct_Save_As, IInt_Sys_File_List, make_lit_string("Save As: "));
}
COMMAND_DECL(change_active_panel){
@ -1439,6 +1437,7 @@ App_Init_Sig(app_init){
models->scroll_rule = fallback_scroll_rule;
models->hook_open_file = 0;
models->hook_new_file = 0;
models->hook_save_file = 0;
setup_command_table();
@ -1578,6 +1577,10 @@ App_Init_Sig(app_init){
models->hook_new_file = (Open_File_Hook_Function*)unit->hook.func;
break;
case _hook_save_file:
models->hook_save_file = (Open_File_Hook_Function*)unit->hook.func;
break;
case _hook_command_caller:
models->command_caller = (Command_Caller_Hook_Function*)unit->hook.func;
break;
@ -2564,6 +2567,8 @@ App_Step_Sig(app_step){
"-The 'config.4coder' file can now be placed with the 4ed executable file\n"
"-New options in 'config.4coder' to specify the font and color theme\n"
"-New built in project configuration system\n"
"-New on-save hooks allows custom behavior in the custom layer whenever a file is saved\n"
"-When using code wrapping, any saved file is automatically indented in the text format, this option can be turned off in config.4coder\n"
"\n"
"New in alpha 4.0.12 and 4.0.13:\n"
"-Text files wrap lines at whitespace when possible\n"

View File

@ -87,7 +87,8 @@ fill_view_summary(View_Summary *view, View *vptr, Live_Views *live_set, Working_
view->cursor = vptr->edit_pos->cursor;
view->preferred_x = vptr->edit_pos->preferred_x;
view->file_region = vptr->panel->inner;
view->view_region = vptr->panel->inner;
view->file_region = vptr->file_region;
view->scroll_vars = vptr->edit_pos->scroll;
}
}
@ -118,7 +119,7 @@ imp_get_file(Command_Data *cmd, Buffer_Summary *buffer){
Editing_File *file = 0;
Working_Set *working_set = &cmd->models->working_set;;
if (buffer->exists){
if (buffer && buffer->exists){
file = working_set_get_active_file(working_set, buffer->buffer_id);
if (file != 0 && !file_is_ready(file)){
file = 0;
@ -148,7 +149,7 @@ internal View*
imp_get_view(Command_Data *cmd, View_Summary *view){
View *vptr = 0;
if (view->exists){
if (view && view->exists){
vptr = imp_get_view(cmd, view->view_id);
}
@ -185,28 +186,24 @@ DOC_SEE(Command_ID)
API_EXPORT bool32
Exec_System_Command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags)
/*
DOC_PARAM(view, If the view parameter is non-null it specifies a view to display the command's output buffer.)
DOC_PARAM(view, If the view parameter is non-null it specifies a view to display the command's output buffer, otherwise the command will still work but if there is a buffer capturing the output it will not automatically be displayed.)
DOC_PARAM(buffer, The buffer the command will output to is specified by the buffer parameter.
See Buffer_Identifier for information on how this type specifies a buffer.)
See Buffer_Identifier for information on how this type specifies a buffer. The command will cause a crash if no file is specified.)
DOC_PARAM(path, The path parameter specifies the path in which the command shall be executed. The string need not be null terminated.)
DOC_PARAM(path_len, The parameter path_len specifies the length of the path string.)
DOC_PARAM(command, The command parameter specifies the command that shall be executed. The string need not be null terminated.)
DOC_PARAM(command_len, The parameter command_len specifies the length of the command string.)
DOC_PARAM(flags, Flags for the behavior of the call are specified in the flags parameter.)
DOC_RETURN(This call returns non-zero on success.)
DOC
(
A call to exec_system_command executes a command as if called from the command line, and sends the output to
a buffer. The buffer identifier can either name a new buffer that does not exist, name a buffer that does
exist, or provide the id of a buffer that does exist.
DOC(
A call to exec_system_command executes a command as if called from the command line, and sends the output to a buffer. The buffer identifier can name a new buffer that does not exist, name a buffer that does exist, or provide the id of a buffer that does exist.
If the buffer is not already in an open view and the view parameter is not NULL,
then the provided view will display the output buffer.
If the view parameter is NULL, no view will switch to the output.
)
If the view parameter is NULL, no view will switch to the output.)
DOC_SEE(Buffer_Identifier)
DOC_SEE(Command_Line_Input_Flag)
DOC_SEE(Command_Line_Interface_Flag)
*/{
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
@ -231,6 +228,7 @@ DOC_SEE(Command_Line_Input_Flag)
if (vars->cli_processes.count < vars->cli_processes.max){
file = get_file_from_identifier(system, working_set, buffer);
if (file){
if (file->settings.read_only == 0){
append_ss(&feedback_str, make_lit_string("ERROR: "));
@ -252,13 +250,11 @@ DOC_SEE(Command_Line_Input_Flag)
else if (buffer.name){
file = working_set_alloc_always(system, working_set, general);
if (file == 0){
append_ss(&feedback_str,
make_lit_string("ERROR: unable to allocate a new buffer\n"));
append_ss(&feedback_str, make_lit_string("ERROR: unable to allocate a new buffer\n"));
do_feedback_message(system, models, feedback_str);
result = false;
goto done;
}
String name = make_string_terminated(part, buffer.name, buffer.name_len);
buffer_bind_name(system, general, working_set, file, name);
init_read_only_file(system, models, file);
@ -707,7 +703,7 @@ DOC_SEE(Buffer_Batch_Edit_Type)
return(result);
}
API_EXPORT int32_t
API_EXPORT bool32
Buffer_Get_Setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t *value_out)
/*
DOC_PARAM(buffer, the buffer from which to read a setting)
@ -717,7 +713,7 @@ DOC_RETURN(returns non-zero on success)
*/{
Command_Data *cmd = (Command_Data*)app->cmd_context;
Editing_File *file = imp_get_file(cmd, buffer);
int32_t result = 0;
bool32 result = 0;
if (file){
result = 1;
@ -1141,17 +1137,17 @@ DOC_RETURN(This call returns non-zero on success.)
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
bool32 result = false;
bool32 result = 0;
Editing_File *file = imp_get_file(cmd, buffer);
if (file){
if (file_get_sync(file) != DirtyState_UpToDate){
result = true;
result = 1;
Partition *part = &models->mem.part;
Temp_Memory temp = begin_temp_memory(part);
String name = make_string_terminated(part, filename, filename_len);
save_file_to_name(system, &models->mem, file, name.str);
save_file_to_name(system, models, file, name.str);
end_temp_memory(temp);
}
}

View File

@ -65,6 +65,7 @@ struct Models{
Open_File_Hook_Function *hook_open_file;
Open_File_Hook_Function *hook_new_file;
Open_File_Hook_Function *hook_save_file;
Command_Caller_Hook_Function *command_caller;
Input_Filter_Function *input_filter;
Scroll_Rule_Function *scroll_rule;

View File

@ -744,7 +744,7 @@ file_synchronize_times(System_Functions *system, Editing_File *file){
}
internal b32
save_file_to_name(System_Functions *system, Mem_Options *mem, Editing_File *file, char *filename){
save_file_to_name(System_Functions *system, Models *models, Editing_File *file, char *filename){
b32 result = 0;
b32 using_actual_filename = 0;
@ -755,6 +755,11 @@ save_file_to_name(System_Functions *system, Mem_Options *mem, Editing_File *file
}
if (filename){
Mem_Options *mem = &models->mem;
if (models->hook_save_file){
models->hook_save_file(&models->app_links, file->id.id);
}
i32 max = 0, size = 0;
b32 dos_write_mode = file->settings.dos_write_mode;
char *data = 0;
@ -810,8 +815,8 @@ save_file_to_name(System_Functions *system, Mem_Options *mem, Editing_File *file
}
inline b32
save_file(System_Functions *system, Mem_Options *mem, Editing_File *file){
b32 result = save_file_to_name(system, mem, file, 0);
save_file(System_Functions *system, Models *models, Editing_File *file){
b32 result = save_file_to_name(system, models, file, 0);
return(result);
}
@ -835,12 +840,10 @@ buffer_link_to_new_file(System_Functions *system, General_Memory *general, Worki
}
inline b32
file_save_and_set_names(System_Functions *system, Mem_Options *mem,
Working_Set *working_set, Editing_File *file,
String filename){
b32 result = buffer_link_to_new_file(system, &mem->general, working_set, file, filename);
file_save_and_set_names(System_Functions *system, Models *models, Editing_File *file, String filename){
b32 result = buffer_link_to_new_file(system, &models->mem.general, &models->working_set, file, filename);
if (result){
result = save_file(system, mem, file);
result = save_file(system, models, file);
}
return(result);
}
@ -1960,9 +1963,8 @@ file_create_from_string(System_Functions *system, Models *models,
file->state.undo.current_block_normal = 1;
}
Open_File_Hook_Function *open_hook = models->hook_open_file;
if (open_hook){
open_hook(&models->app_links, file->id.id);
if (models->hook_open_file){
models->hook_open_file(&models->app_links, file->id.id);
}
file->settings.is_initialized = 1;
}
@ -3833,7 +3835,7 @@ view_open_file(System_Functions *system, Models *models, View *view, String file
internal void
view_interactive_save_as(System_Functions *system, Models *models, Editing_File *file, String filename){
if (terminate_with_null(&filename)){
file_save_and_set_names(system, &models->mem, &models->working_set, file, filename);
file_save_and_set_names(system, models, file, filename);
}
}
@ -3913,7 +3915,7 @@ internal void
save_file_by_name(System_Functions *system, Models *models, String name){
Editing_File *file = working_set_name_contains(&models->working_set, name);
if (file){
save_file(system, &models->mem, file);
save_file(system, models, file);
}
}

View File

@ -81,8 +81,6 @@
;
; [] indication on failure to save
; [] history is broken, revist the entire system
; [] 8.0\Include\um\dsound.h (not reproduced, get more info)
; [] paste external text from bug report (in email) (not reproduced, get more info)
;
; [] view fails to follow cursor when the view is shrunk
; [] view fails to follow cursor after deleting long line
@ -91,10 +89,6 @@
; BEFORE I SHIP
;
; [] decent options for indentation rules for text & presentation
; [] code file outlining
; [] alternate code completion plan
;
; TODOS
; [X] success message when compiler works
@ -181,12 +175,16 @@
; [X] handle comments
; [X] additional width for nesting?
; [X] fix issues when relexing happens in parallel
; [X] improve code display mode so that it can auto-indent the text on save
; [] command for setting wrap positions in views directly
; [] ability to see the wrap position as a number/line and adjust graphically
; [] code level wrapping level 2
; [] comment lead whitespace problem
; [] remeasure version of measure_wraps
; [] code file outlining
; [] alternate code completion plan
; Buffer behavior cleanup
; [X] show all characters as \# if they can't be rendered
; [X] get the navigation working correctly around multi-glyph characters

View File

@ -620,6 +620,7 @@ get_bindings(void *data, int size){
set_hook(context, hook_view_size_change, my_view_adjust);
set_open_file_hook(context, my_file_settings);
set_save_file_hook(context, my_file_save);
set_input_filter(context, my_suppress_mouse_filter);
set_command_caller(context, default_command_caller);

View File

@ -1,34 +1,35 @@
extensions=".c.cpp.h.hpp";
extensions=".c.cpp.h.hpp.bat.sh";
fkey_command_wnd[1] = {"build.bat", "*compilation*"};
fkey_command_wnd[2] = {"..\\misc\\run.bat", 0};
fkey_command_wnd[3] = {"site\\build.bat", "*compilation*"};
fkey_command_wnd[4] = {0, 0};
fkey_command_wnd[5] = {0, 0};
fkey_command_wnd[6] = {0, 0};
fkey_command_wnd[7] = {0, 0};
fkey_command_wnd[8] = {0, 0};
fkey_command_wnd[9] = {0, 0};
fkey_command_wnd[10] = {0, 0};
fkey_command_wnd[11] = {0, 0};
fkey_command_wnd[12] = {"package.bat", "*compilation*"};
fkey_command_wnd[13] = {0, 0};
fkey_command_wnd[14] = {0, 0};
fkey_command_wnd[15] = {0, 0};
fkey_command_wnd[16] = {0, 0};
// NOTE(allen): There is some kind of bug where hitting f12 causes a crash. It looks like there is a special meaning placed on some fkeys by windows, which I have not found how to disable yet.
fkey_command_win[1] = {"build.bat", "*compilation*", true};
fkey_command_win[2] = {"..\\misc\\run.bat", "*run*"};
fkey_command_win[3] = {"site\\build.bat", "*compilation*", true};
fkey_command_win[4] = {0, 0};
fkey_command_win[5] = {0, 0};
fkey_command_win[6] = {0, 0};
fkey_command_win[7] = {0, 0};
fkey_command_win[8] = {"package.bat", "*compilation*", true};
fkey_command_win[9] = {0, 0};
fkey_command_win[10] = {0, 0};
fkey_command_win[11] = {0, 0};
fkey_command_win[12] = {0, 0};
fkey_command_win[13] = {0, 0};
fkey_command_win[14] = {0, 0};
fkey_command_win[15] = {0, 0};
fkey_command_win[16] = {0, 0};
fkey_command_linux[1] = {"make", "*compilation*"};
fkey_command_linux[2] = {"../build/4ed", 0};
fkey_command_linux[3] = {"site/build.sh", "*compilation*"};
fkey_command_linux[1] = {"make", "*compilation*", true};
fkey_command_linux[2] = {"../build/4ed", "*run*"};
fkey_command_linux[3] = {"site/build.sh", "*compilation*", true};
fkey_command_linux[4] = {0, 0};
fkey_command_linux[5] = {0, 0};
fkey_command_linux[6] = {0, 0};
fkey_command_linux[7] = {0, 0};
fkey_command_linux[8] = {0, 0};
fkey_command_linux[8] = {"package.sh", "*compilation*", true};
fkey_command_linux[9] = {0, 0};
fkey_command_linux[10] = {0, 0};
fkey_command_linux[11] = {0, 0};
fkey_command_linux[12] = {"package.sh", "*compilation*"};
fkey_command_linux[12] = {0, 0};
fkey_command_linux[13] = {0, 0};
fkey_command_linux[14] = {0, 0};
fkey_command_linux[15] = {0, 0};