4.0.15 various bug fixes, feature polish, added experimental scope command

master
Allen Webster 2017-01-28 19:03:23 -05:00
parent e410404208
commit 0417cab3d0
40 changed files with 3601 additions and 2822 deletions

View File

@ -306,6 +306,16 @@ CUSTOM_COMMAND_SIG(seek_end_of_line){
view_set_cursor(app, &view, seek_xy(100000.f, y, 1, view.unwrapped_lines), 1); view_set_cursor(app, &view, seek_xy(100000.f, y, 1, view.unwrapped_lines), 1);
} }
CUSTOM_COMMAND_SIG(seek_whitespace_up_end_line){
exec_command(app, seek_whitespace_up);
exec_command(app, seek_end_of_line);
}
CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line){
exec_command(app, seek_whitespace_down);
exec_command(app, seek_end_of_line);
}
// //
// Fancy Editing // Fancy Editing

234
4coder_build_commands.cpp Normal file
View File

@ -0,0 +1,234 @@
/*
4coder_build_commands.cpp - Commands for building.
TYPE: 'drop-in-command-pack'
*/
// TOP
#if !defined(FCODER_BUILD_COMMANDS_CPP)
#define FCODER_BUILD_COMMANDS_CPP
#include "4coder_helper/4coder_helper.h"
#include "4coder_default_framework.h"
// NOTE(allen|a4.0.9): This is provided to establish a default method of getting
// a "build directory". This function tries to setup the build directory in the
// directory of the given buffer, if it cannot get that information it get's the
// 4coder hot directory.
//
// There is no requirement that a custom build system in 4coder actually use the
// directory given by this function.
enum Get_Build_Directory_Result{
BuildDir_None,
BuildDir_AtFile,
BuildDir_AtHot
};
static int32_t
get_build_directory(Application_Links *app, Buffer_Summary *buffer, String *dir_out){
int32_t result = BuildDir_None;
if (buffer && buffer->file_name){
if (!match_cc(buffer->file_name, buffer->buffer_name)){
String dir = make_string_cap(buffer->file_name,
buffer->file_name_len,
buffer->file_name_len+1);
remove_last_folder(&dir);
append_ss(dir_out, dir);
result = BuildDir_AtFile;
}
}
if (!result){
int32_t len = directory_get_hot(app, dir_out->str,
dir_out->memory_size - dir_out->size);
if (len + dir_out->size < dir_out->memory_size){
dir_out->size += len;
result = BuildDir_AtHot;
}
}
return(result);
}
// TODO(allen): Better names for the "standard build search" family.
static int32_t
standard_build_search(Application_Links *app, View_Summary *view, Buffer_Summary *active_buffer, String *dir, String *command, int32_t perform_backup, int32_t use_path_in_command, String filename, String commandname){
int32_t result = false;
for(;;){
int32_t old_size = dir->size;
append_ss(dir, filename);
if (file_exists(app, dir->str, dir->size)){
dir->size = old_size;
if (use_path_in_command){
append_s_char(command, '"');
append_ss(command, *dir);
append_ss(command, commandname);
append_s_char(command, '"');
}
else{
append_ss(command, commandname);
}
char space[512];
String message = make_fixed_width_string(space);
append_ss(&message, make_lit_string("Building with: "));
append_ss(&message, *command);
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);
result = true;
break;
}
dir->size = old_size;
if (directory_cd(app, dir->str, &dir->size, dir->memory_size, literal("..")) == 0){
if (perform_backup){
dir->size = directory_get_hot(app, dir->str, dir->memory_size);
char backup_space[256];
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);
}
break;
}
}
return(result);
}
#if defined(_WIN32)
// NOTE(allen): Build search rule for windows.
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"));
return(result);
}
#elif defined(__linux__)
// 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);
int32_t result = standard_build_search(app, view, active_buffer, dir, command, 0, 1, make_lit_string("build.sh"), make_lit_string("build.sh"));
if (!result){
result = standard_build_search(app, view, active_buffer, &dir_copy, command, perform_backup, 0, make_lit_string("Makefile"), make_lit_string("make"));
}
return(result);
}
#else
# error No build search rule for this platform.
#endif
// 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){
char dir_space[512];
String dir = make_fixed_width_string(dir_space);
char command_str_space[512];
String command = make_fixed_width_string(command_str_space);
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)){
dir.size = 0;
command.size = 0;
build_dir_type = get_build_directory(app, 0, &dir);
}
}
if (build_dir_type == BuildDir_AtHot){
execute_standard_build_search(app, view, active_buffer, &dir, &command, true);
}
}
CUSTOM_COMMAND_SIG(build_search){
uint32_t access = AccessAll;
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
execute_standard_build(app, &view, &buffer);
prev_location = null_location;
lock_jump_buffer(literal("*compilation*"));
}
#define GET_COMP_BUFFER(app) get_buffer_by_name(app, literal("*compilation*"), AccessAll)
static View_Summary
get_or_open_build_panel(Application_Links *app){
View_Summary view = {0};
Buffer_Summary buffer = GET_COMP_BUFFER(app);
if (buffer.exists){
view = get_first_view_with_buffer(app, buffer.buffer_id);
}
if (!view.exists){
view = open_special_note_view(app);
}
return(view);
}
static void
set_fancy_compilation_buffer_font(Application_Links *app){
Buffer_Summary comp_buffer = get_buffer_by_name(app, literal("*compilation*"), AccessAll);
buffer_set_font(app, &comp_buffer, literal("Inconsolata"));
}
CUSTOM_COMMAND_SIG(build_in_build_panel){
uint32_t access = AccessAll;
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
View_Summary build_view = get_or_open_build_panel(app);
execute_standard_build(app, &build_view, &buffer);
set_fancy_compilation_buffer_font(app);
prev_location = null_location;
lock_jump_buffer(literal("*compilation*"));
}
CUSTOM_COMMAND_SIG(close_build_panel){
close_special_note_view(app);
}
CUSTOM_COMMAND_SIG(change_to_build_panel){
View_Summary view = open_special_note_view(app, false);
if (!view.exists){
Buffer_Summary buffer = GET_COMP_BUFFER(app);
if (buffer.exists){
view = open_special_note_view(app);
view_set_buffer(app, &view, buffer.buffer_id, 0);
}
}
if (view.exists){
set_active_view(app, &view);
}
}
#endif
// BOTTOM

147
4coder_clipboard.cpp Normal file
View File

@ -0,0 +1,147 @@
/*
4coder_clipboard.cpp - Copy paste commands and clipboard related setup.
TYPE: 'drop-in-command-pack'
*/
// TOP
#if !defined(FCODER_CLIPBOARD_CPP)
#define FCODER_CLIPBOARD_CPP
#include "4coder_default_framework.h"
#include "4coder_helper/4coder_helper.h"
static bool32
clipboard_copy(Application_Links *app, int32_t start, int32_t end, Buffer_Summary *buffer_out, uint32_t access){
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
bool32 result = 0;
if (buffer.exists){
if (0 <= start && start <= end && end <= buffer.size){
int32_t size = (end - start);
char *str = (char*)app->memory;
if (size <= app->memory_size){
buffer_read_range(app, &buffer, start, end, str);
clipboard_post(app, 0, str, size);
if (buffer_out){*buffer_out = buffer;}
result = 1;
}
}
}
return(result);
}
static int32_t
clipboard_cut(Application_Links *app, int32_t start, int32_t end, Buffer_Summary *buffer_out, uint32_t access){
Buffer_Summary buffer = {0};
int32_t result = false;
if (clipboard_copy(app, start, end, &buffer, access)){
buffer_replace_range(app, &buffer, start, end, 0, 0);
if (buffer_out){*buffer_out = buffer;}
}
return(result);
}
CUSTOM_COMMAND_SIG(copy){
uint32_t access = AccessProtected;
View_Summary view = get_active_view(app, access);
Range range = get_range(&view);
clipboard_copy(app, range.min, range.max, 0, access);
}
CUSTOM_COMMAND_SIG(cut){
uint32_t access = AccessOpen;
View_Summary view = get_active_view(app, access);
Range range = get_range(&view);
clipboard_cut(app, range.min, range.max, 0, access);
}
CUSTOM_COMMAND_SIG(paste){
uint32_t access = AccessOpen;
int32_t count = clipboard_count(app, 0);
if (count > 0){
View_Summary view = get_active_view(app, access);
view_paste_index[view.view_id].next_rewrite = RewritePaste;
int32_t paste_index = 0;
view_paste_index[view.view_id].index = paste_index;
int32_t len = clipboard_index(app, 0, paste_index, 0, 0);
char *str = 0;
if (len <= app->memory_size){
str = (char*)app->memory;
}
if (str){
clipboard_index(app, 0, paste_index, str, len);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
int32_t pos = view.cursor.pos;
buffer_replace_range(app, &buffer, pos, pos, str, len);
view_set_mark(app, &view, seek_pos(pos));
view_set_cursor(app, &view, seek_pos(pos + len), true);
// TODO(allen): Send this to all views.
Theme_Color paste;
paste.tag = Stag_Paste;
get_theme_colors(app, &paste, 1);
view_post_fade(app, &view, 0.667f, pos, pos + len, paste.color);
}
}
}
CUSTOM_COMMAND_SIG(paste_next){
uint32_t access = AccessOpen;
int32_t count = clipboard_count(app, 0);
if (count > 0){
View_Summary view = get_active_view(app, access);
if (view_paste_index[view.view_id].rewrite == RewritePaste){
view_paste_index[view.view_id].next_rewrite = RewritePaste;
int32_t paste_index = view_paste_index[view.view_id].index + 1;
view_paste_index[view.view_id].index = paste_index;
int32_t len = clipboard_index(app, 0, paste_index, 0, 0);
char *str = 0;
if (len <= app->memory_size){
str = (char*)app->memory;
}
if (str){
clipboard_index(app, 0, paste_index, str, len);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
Range range = get_range(&view);
int32_t pos = range.min;
buffer_replace_range(app, &buffer, range.min, range.max, str, len);
view_set_cursor(app, &view, seek_pos(pos + len), true);
// TODO(allen): Send this to all views.
Theme_Color paste;
paste.tag = Stag_Paste;
get_theme_colors(app, &paste, 1);
view_post_fade(app, &view, 0.667f, pos, pos + len, paste.color);
}
}
else{
exec_command(app, paste);
}
}
}
#endif
// BOTTOM

View File

@ -1,314 +1,23 @@
/*
4coder_default_bidings.cpp - Supplies the default bindings used for default 4coder behavior.
TYPE: 'build-target'
*/
// TOP // TOP
#ifndef FCODER_DEFAULT_BINDINGS #if !defined(FCODER_DEFAULT_BINDINGS)
#define FCODER_DEFAULT_BINDINGS #define FCODER_DEFAULT_BINDINGS
#include "4coder_default_include.cpp" #include "4coder_default_include.cpp"
// NOTE(allen|a3.3): All of your custom ids should be enumerated
// as shown here, they may start at 0, and you can only have
// 2^24 of them so don't be wasteful!
enum My_Maps{
my_code_map,
my_maps_count
};
CUSTOM_COMMAND_SIG(write_allen_todo){
write_string(app, make_lit_string("// TODO(allen): "));
}
CUSTOM_COMMAND_SIG(write_allen_note){
write_string(app, make_lit_string("// NOTE(allen): "));
}
CUSTOM_COMMAND_SIG(write_allen_doc){
write_string(app, make_lit_string("/* DOC() */"));
}
CUSTOM_COMMAND_SIG(write_zero_struct){
write_string(app, make_lit_string(" = {0};"));
}
CUSTOM_COMMAND_SIG(switch_to_compilation){
char name[] = "*compilation*";
int32_t name_size = sizeof(name)-1;
uint32_t access = AccessOpen;
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer_by_name(app, name, name_size, access);
view_set_buffer(app, &view, buffer.buffer_id, 0);
}
CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
uint32_t access = AccessOpen;
View_Summary view = get_active_view(app, access);
Full_Cursor cursor = view.cursor;
// TODO(allen): This can be rewritten now without moving the
// cursor around, instead just calling the boundary seek.
Range range = {0};
exec_command(app, seek_token_left);
refresh_view(app, &view);
range.min = view.cursor.pos;
exec_command(app, seek_token_right);
refresh_view(app, &view);
range.max = view.cursor.pos;
String string = {0};
string.str = (char*)app->memory;
string.size = range.max - range.min;
assert(string.size < app->memory_size);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
buffer_read_range(app, &buffer, range.min, range.max, string.str);
int32_t is_first = true;
for (int32_t i = 0; i < string.size; ++i){
if (char_is_alpha_true(string.str[i])){
if (is_first){
is_first = false;
}
else{
string.str[i] = char_to_lower(string.str[i]);
}
}
else{
is_first = true;
}
}
buffer_replace_range(app, &buffer, range.min, range.max, string.str, string.size);
view_set_cursor(app, &view, seek_line_char(cursor.line+1, cursor.character), true);
}
CUSTOM_COMMAND_SIG(open_my_files){
uint32_t access = AccessAll;
View_Summary view = get_active_view(app, access);
view_open_file(app, &view, literal("w:/4ed/data/test/basic.cpp"), true);
}
CUSTOM_COMMAND_SIG(build_at_launch_location){
uint32_t access = AccessAll;
View_Summary view = get_active_view(app, access);
exec_system_command(app, &view, buffer_identifier(literal("*compilation*")),literal("."), literal("build"), CLI_OverlapWithConflict);
}
CUSTOM_COMMAND_SIG(seek_whitespace_up_end_line){
exec_command(app, seek_whitespace_up);
exec_command(app, seek_end_of_line);
}
CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line){
exec_command(app, seek_whitespace_down);
exec_command(app, seek_end_of_line);
}
HOOK_SIG(my_start){
default_4coder_initialize(app);
default_4coder_side_by_side_panels(app);
// no meaning for return
return(0);
}
HOOK_SIG(my_exit){
// if this returns zero it cancels the exit.
return(1);
}
HOOK_SIG(my_view_adjust){
int32_t count = 0;
int32_t new_wrap_width = 0;
for (View_Summary view = get_view_first(app, AccessAll);
view.exists;
get_view_next(app, &view, AccessAll)){
new_wrap_width += view.view_region.x1 - view.view_region.x0;
++count;
}
new_wrap_width /= count;
new_wrap_width = (int32_t)(new_wrap_width * .9f);
int32_t new_min_base_width = (int32_t)(new_wrap_width * .77f);
if (automatically_adjust_wrapping){
adjust_all_buffer_wrap_widths(app, new_wrap_width, new_min_base_width);
}
// no meaning for return
return(0);
}
CUSTOM_COMMAND_SIG(newline_or_goto_position){
View_Summary view = get_active_view(app, AccessProtected);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
if (buffer.lock_flags & AccessProtected){
exec_command(app, goto_jump_at_cursor);
lock_jump_buffer(buffer);
}
else{
exec_command(app, write_character);
}
}
// TODO(allen): Eliminate this hook if you can.
OPEN_FILE_HOOK_SIG(my_file_settings){
// NOTE(allen|a4.0.8): The get_parameter_buffer was eliminated
// and instead the buffer is passed as an explicit parameter through
// the function call. That is where buffer_id comes from here.
uint32_t access = AccessAll;
Buffer_Summary buffer = get_buffer(app, buffer_id, access);
assert(buffer.exists);
int32_t treat_as_code = 0;
int32_t wrap_lines = 1;
if (buffer.file_name && buffer.size < (16 << 20)){
String ext = file_extension(make_string(buffer.file_name, buffer.file_name_len));
if (match_ss(ext, make_lit_string("cpp"))) treat_as_code = 1;
else if (match_ss(ext, make_lit_string("h"))) treat_as_code = 1;
else if (match_ss(ext, make_lit_string("c"))) treat_as_code = 1;
else if (match_ss(ext, make_lit_string("hpp"))) treat_as_code = 1;
}
if (treat_as_code){
wrap_lines = 0;
}
if (buffer.file_name[0] == '*'){
wrap_lines = 0;
}
buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, default_wrap_width);
buffer_set_setting(app, &buffer, BufferSetting_MinimumBaseWrapPosition, default_min_base_width);
buffer_set_setting(app, &buffer, BufferSetting_MapID, (treat_as_code)?((int32_t)my_code_map):((int32_t)mapid_file));
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, 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.
buffer_set_setting(app, &buffer, BufferSetting_WrapLine, 1);
buffer_set_setting(app, &buffer, BufferSetting_VirtualWhitespace, 1);
}
else{
buffer_set_setting(app, &buffer, BufferSetting_WrapLine, wrap_lines);
buffer_set_setting(app, &buffer, BufferSetting_Lex, treat_as_code);
}
// no meaning for return
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.
//
// Right now it only has access to the mouse state, but it will be
// extended to have access to the key presses soon.
static bool32 suppressing_mouse = false;
INPUT_FILTER_SIG(my_suppress_mouse_filter){
if (suppressing_mouse){
*mouse = null_mouse_state;
mouse->x = -100;
mouse->y = -100;
}
}
static void
set_mouse_suppression(Application_Links *app, int32_t suppress){
if (suppress){
suppressing_mouse = 1;
show_mouse_cursor(app, MouseCursorShow_Never);
}
else{
suppressing_mouse = 0;
show_mouse_cursor(app, MouseCursorShow_Always);
}
}
CUSTOM_COMMAND_SIG(suppress_mouse){
set_mouse_suppression(app, true);
}
CUSTOM_COMMAND_SIG(allow_mouse){
set_mouse_suppression(app, false);
}
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 void
default_keys(Bind_Helper *context){ default_keys(Bind_Helper *context){
begin_map(context, mapid_global); begin_map(context, mapid_global);
bind(context, 'p', MDFR_CTRL, open_panel_vsplit); //bind(context, 'p', MDFR_CTRL, open_panel_vsplit);
bind(context, '_', MDFR_CTRL, open_panel_hsplit); //bind(context, '_', MDFR_CTRL, open_panel_hsplit);
bind(context, 'P', MDFR_CTRL, close_panel); //bind(context, 'P', MDFR_CTRL, close_panel);
bind(context, ',', MDFR_CTRL, change_active_panel); bind(context, ',', MDFR_CTRL, change_active_panel);
bind(context, 'n', MDFR_CTRL, interactive_new); bind(context, 'n', MDFR_CTRL, interactive_new);
@ -318,8 +27,8 @@ default_keys(Bind_Helper *context){
bind(context, 'i', MDFR_CTRL, interactive_switch_buffer); bind(context, 'i', MDFR_CTRL, interactive_switch_buffer);
bind(context, 'w', MDFR_CTRL, save_as); bind(context, 'w', MDFR_CTRL, save_as);
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker); bind(context, 'c', MDFR_ALT, open_color_tweaker);
bind(context, 'd', MDFR_ALT, cmdid_open_debug); bind(context, 'd', MDFR_ALT, open_debug);
bind(context, '.', MDFR_ALT, change_to_build_panel); bind(context, '.', MDFR_ALT, change_to_build_panel);
bind(context, ',', MDFR_ALT, close_build_panel); bind(context, ',', MDFR_ALT, close_build_panel);
@ -336,7 +45,7 @@ default_keys(Bind_Helper *context){
bind(context, 's', MDFR_ALT, show_scrollbar); bind(context, 's', MDFR_ALT, show_scrollbar);
bind(context, 'w', MDFR_ALT, hide_scrollbar); bind(context, 'w', MDFR_ALT, hide_scrollbar);
// TODO(allen): This is apparently not working on Linux. Need to try it on windows still. // TODO(allen): This is apparently not working on Linux, must investigate.
bind(context, key_f2, MDFR_CTRL, toggle_mouse); bind(context, key_f2, MDFR_CTRL, toggle_mouse);
bind(context, key_page_up, MDFR_CTRL, toggle_fullscreen); bind(context, key_page_up, MDFR_CTRL, toggle_fullscreen);
bind(context, 'E', MDFR_ALT, exit_4coder); bind(context, 'E', MDFR_ALT, exit_4coder);
@ -363,9 +72,9 @@ default_keys(Bind_Helper *context){
end_map(context); end_map(context);
begin_map(context, my_code_map); begin_map(context, default_code_map);
// NOTE(allen|a3.1): Set this map (my_code_map == mapid_user_custom) to // NOTE(allen|a3.1): Set this map (default_code_map == mapid_user_custom) to
// inherit from mapid_file. When searching if a key is bound // inherit from mapid_file. When searching if a key is bound
// in this map, if it is not found here it will then search mapid_file. // in this map, if it is not found here it will then search mapid_file.
// //
@ -391,15 +100,16 @@ default_keys(Bind_Helper *context){
bind(context, '\t', MDFR_CTRL, auto_tab_range); bind(context, '\t', MDFR_CTRL, auto_tab_range);
bind(context, '\t', MDFR_SHIFT, auto_tab_line_at_cursor); bind(context, '\t', MDFR_SHIFT, auto_tab_line_at_cursor);
bind(context, 't', MDFR_ALT, write_allen_todo); bind(context, 't', MDFR_ALT, write_todo);
bind(context, 'y', MDFR_ALT, write_allen_note); bind(context, 'y', MDFR_ALT, write_note);
bind(context, 'r', MDFR_ALT, write_allen_doc); bind(context, 'r', MDFR_ALT, write_block);
bind(context, '[', MDFR_CTRL, open_long_braces); bind(context, '[', MDFR_CTRL, open_long_braces);
bind(context, '{', MDFR_CTRL, open_long_braces_semicolon); bind(context, '{', MDFR_CTRL, open_long_braces_semicolon);
bind(context, '}', MDFR_CTRL, open_long_braces_break); bind(context, '}', MDFR_CTRL, open_long_braces_break);
bind(context, 'i', MDFR_ALT, if0_off); bind(context, 'i', MDFR_ALT, if0_off);
bind(context, '1', MDFR_ALT, open_file_in_quotes); bind(context, '1', MDFR_ALT, open_file_in_quotes);
bind(context, '0', MDFR_CTRL, write_zero_struct); bind(context, '0', MDFR_CTRL, write_zero_struct);
bind(context, 'I', MDFR_CTRL, list_all_functions_current_buffer);
end_map(context); end_map(context);
@ -460,25 +170,21 @@ default_keys(Bind_Helper *context){
bind(context, 'F', MDFR_ALT, list_all_substring_locations_case_insensitive); bind(context, 'F', MDFR_ALT, list_all_substring_locations_case_insensitive);
bind(context, 'g', MDFR_CTRL, goto_line); bind(context, 'g', MDFR_CTRL, goto_line);
bind(context, 'j', MDFR_CTRL, to_lowercase); bind(context, 'j', MDFR_CTRL, to_lowercase);
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer); bind(context, 'K', MDFR_CTRL, kill_buffer);
bind(context, 'l', MDFR_CTRL, toggle_line_wrap); bind(context, 'l', MDFR_CTRL, toggle_line_wrap);
bind(context, 'm', MDFR_CTRL, cursor_mark_swap); bind(context, 'm', MDFR_CTRL, cursor_mark_swap);
bind(context, 'O', MDFR_CTRL, cmdid_reopen); bind(context, 'O', MDFR_CTRL, reopen);
bind(context, 'q', MDFR_CTRL, query_replace); bind(context, 'q', MDFR_CTRL, query_replace);
bind(context, 'r', MDFR_CTRL, reverse_search); bind(context, 'r', MDFR_CTRL, reverse_search);
bind(context, 's', MDFR_CTRL, cmdid_save); bind(context, 's', MDFR_CTRL, save);
bind(context, 'T', MDFR_CTRL, list_all_locations_of_identifier); bind(context, 'T', MDFR_CTRL, list_all_locations_of_identifier);
bind(context, 'u', MDFR_CTRL, to_uppercase); bind(context, 'u', MDFR_CTRL, to_uppercase);
bind(context, 'U', MDFR_CTRL, rewrite_as_single_caps);
bind(context, 'v', MDFR_CTRL, paste_and_indent); bind(context, 'v', MDFR_CTRL, paste_and_indent);
bind(context, 'v', MDFR_ALT, toggle_virtual_whitespace); bind(context, 'v', MDFR_ALT, toggle_virtual_whitespace);
bind(context, 'V', MDFR_CTRL, paste_next_and_indent); bind(context, 'V', MDFR_CTRL, paste_next_and_indent);
bind(context, 'x', MDFR_CTRL, cut); bind(context, 'x', MDFR_CTRL, cut);
bind(context, 'y', MDFR_CTRL, cmdid_redo); bind(context, 'y', MDFR_CTRL, redo);
bind(context, 'z', MDFR_CTRL, cmdid_undo); bind(context, 'z', MDFR_CTRL, undo);
bind(context, '1', MDFR_CTRL, eol_dosify);
bind(context, '!', MDFR_CTRL, eol_nixify);
bind(context, '2', MDFR_CTRL, decrease_line_wrap); bind(context, '2', MDFR_CTRL, decrease_line_wrap);
bind(context, '3', MDFR_CTRL, increase_line_wrap); bind(context, '3', MDFR_CTRL, increase_line_wrap);
@ -492,8 +198,6 @@ default_keys(Bind_Helper *context){
end_map(context); end_map(context);
} }
#ifndef NO_BINDING #ifndef NO_BINDING
extern "C" int32_t extern "C" int32_t
@ -501,18 +205,7 @@ get_bindings(void *data, int32_t size){
Bind_Helper context_ = begin_bind_helper(data, size); Bind_Helper context_ = begin_bind_helper(data, size);
Bind_Helper *context = &context_; Bind_Helper *context = &context_;
// NOTE(allen|a3.1): Hooks have no loyalties to maps. All hooks are global set_all_default_hooks(context);
// and once set they always apply, regardless of what map is active.
set_hook(context, hook_start, my_start);
set_hook(context, hook_exit, my_exit);
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);
default_keys(context); default_keys(context);
int32_t result = end_bind_helper(context); int32_t result = end_bind_helper(context);
@ -524,3 +217,4 @@ get_bindings(void *data, int32_t size){
#endif //FCODER_DEFAULT_BINDINGS #endif //FCODER_DEFAULT_BINDINGS
// BOTTOM // BOTTOM

View File

@ -10,8 +10,20 @@ TYPE: 'internal-for-default-system'
#if !defined(FCODER_DEFAULT_FRAMEWORK_H) #if !defined(FCODER_DEFAULT_FRAMEWORK_H)
#define FCODER_DEFAULT_FRAMEWORK_H #define FCODER_DEFAULT_FRAMEWORK_H
#include "4coder_base_commands.cpp"
#include "4coder_helper/4coder_helper.h" #include "4coder_helper/4coder_helper.h"
#include "4coder_lib/4coder_mem.h" #include "4coder_lib/4coder_mem.h"
#include "4cpp/4cpp_lexer.h"
//
// Command Maps
//
enum Default_Maps{
default_code_map,
default_maps_count
};
// //
// Global Memory // Global Memory
@ -34,12 +46,14 @@ unlock_jump_buffer(){
static void static void
lock_jump_buffer(char *name, int32_t size){ lock_jump_buffer(char *name, int32_t size){
if (size <= locked_buffer.memory_size){
copy(&locked_buffer, make_string(name, size)); copy(&locked_buffer, make_string(name, size));
} }
}
static void static void
lock_jump_buffer(Buffer_Summary buffer){ lock_jump_buffer(Buffer_Summary buffer){
copy(&locked_buffer, make_string(buffer.buffer_name, buffer.buffer_name_len)); lock_jump_buffer(buffer.buffer_name, buffer.buffer_name_len);
} }
static View_Summary static View_Summary
@ -125,6 +139,601 @@ struct View_Paste_Index{
View_Paste_Index view_paste_index_[16]; View_Paste_Index view_paste_index_[16];
View_Paste_Index *view_paste_index = view_paste_index_ - 1; View_Paste_Index *view_paste_index = view_paste_index_ - 1;
//
// System Buffer Names
//
static char out_buffer_space[1024];
static char command_space[1024];
static char hot_directory_space[1024];
//
// Mouse Suppression
//
static bool32 suppressing_mouse = false;
static void
set_mouse_suppression(Application_Links *app, int32_t suppress){
if (suppress){
suppressing_mouse = 1;
show_mouse_cursor(app, MouseCursorShow_Never);
}
else{
suppressing_mouse = 0;
show_mouse_cursor(app, MouseCursorShow_Always);
}
}
CUSTOM_COMMAND_SIG(suppress_mouse){
set_mouse_suppression(app, true);
}
CUSTOM_COMMAND_SIG(allow_mouse){
set_mouse_suppression(app, false);
}
CUSTOM_COMMAND_SIG(toggle_mouse){
set_mouse_suppression(app, !suppressing_mouse);
}
//
// Projects
//
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;
}
static char**
get_current_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);
}
//
// Location Jumping State
//
typedef struct ID_Based_Jump_Location{
int32_t buffer_id;
int32_t line;
int32_t column;
} ID_Based_Jump_Location;
static ID_Based_Jump_Location null_location = {0};
static ID_Based_Jump_Location prev_location = {0};
//
// Config File Parsing
//
struct Config_Line{
Cpp_Token id_token;
Cpp_Token subscript_token;
Cpp_Token eq_token;
Cpp_Token val_token;
int32_t val_array_start;
int32_t val_array_end;
int32_t val_array_count;
bool32 read_success;
};
struct Config_Item{
Config_Line line;
Cpp_Token_Array array;
char *mem;
String id;
int32_t subscript_index;
bool32 has_subscript;
};
struct Config_Array_Reader{
Cpp_Token_Array array;
char *mem;
int32_t i;
int32_t val_array_end;
bool32 good;
};
static Cpp_Token
read_config_token(Cpp_Token_Array array, int32_t *i_ptr){
Cpp_Token token = {0};
int32_t i = *i_ptr;
for (; i < array.count; ++i){
Cpp_Token comment_token = array.tokens[i];
if (comment_token.type != CPP_TOKEN_COMMENT){
break;
}
}
if (i < array.count){
token = array.tokens[i];
}
*i_ptr = i;
return(token);
}
static Config_Line
read_config_line(Cpp_Token_Array array, int32_t *i_ptr){
Config_Line config_line = {0};
int32_t i = *i_ptr;
config_line.id_token = read_config_token(array, &i);
if (config_line.id_token.type == CPP_TOKEN_IDENTIFIER){
++i;
if (i < array.count){
Cpp_Token token = read_config_token(array, &i);
bool32 subscript_success = 1;
if (token.type == CPP_TOKEN_BRACKET_OPEN){
subscript_success = 0;
++i;
if (i < array.count){
config_line.subscript_token = read_config_token(array, &i);
if (config_line.subscript_token.type == CPP_TOKEN_INTEGER_CONSTANT){
++i;
if (i < array.count){
token = read_config_token(array, &i);
if (token.type == CPP_TOKEN_BRACKET_CLOSE){
++i;
if (i < array.count){
token = read_config_token(array, &i);
subscript_success = 1;
}
}
}
}
}
}
if (subscript_success){
if (token.type == CPP_TOKEN_EQ){
config_line.eq_token = read_config_token(array, &i);
++i;
if (i < array.count){
Cpp_Token val_token = read_config_token(array, &i);
bool32 array_success = 1;
if (val_token.type == CPP_TOKEN_BRACE_OPEN){
array_success = 0;
++i;
if (i < array.count){
config_line.val_array_start = i;
bool32 expecting_array_item = 1;
for (; i < array.count; ++i){
Cpp_Token array_token = read_config_token(array, &i);
if (array_token.size == 0){
break;
}
if (array_token.type == CPP_TOKEN_BRACE_CLOSE){
config_line.val_array_end = i;
array_success = 1;
break;
}
else{
if (array_token.type == CPP_TOKEN_COMMA){
if (!expecting_array_item){
expecting_array_item = 1;
}
else{
break;
}
}
else{
if (expecting_array_item){
expecting_array_item = 0;
++config_line.val_array_count;
}
}
}
}
}
}
if (array_success){
config_line.val_token = val_token;
++i;
if (i < array.count){
Cpp_Token semicolon_token = read_config_token(array, &i);
if (semicolon_token.type == CPP_TOKEN_SEMICOLON){
config_line.read_success = 1;
}
}
}
}
}
}
}
}
if (!config_line.read_success){
for (; i < array.count; ++i){
Cpp_Token token = read_config_token(array, &i);
if (token.type == CPP_TOKEN_SEMICOLON){
break;
}
}
}
*i_ptr = i;
return(config_line);
}
static Config_Item
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;
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);
item.subscript_index = str_to_int_s(subscript_str);
item.has_subscript = 1;
}
return(item);
}
static bool32
config_var(Config_Item item, char *var_name, int32_t *subscript, uint32_t token_type, void *var_out){
bool32 result = 0;
bool32 subscript_succes = 1;
if (item.line.val_token.type == token_type){
if ((var_name == 0 && item.id.size == 0) || match(item.id, var_name)){
if (subscript){
if (item.has_subscript){
*subscript = item.subscript_index;
}
else{
subscript_succes = 0;
}
}
if (subscript_succes){
if (var_out){
switch (token_type){
case CPP_TOKEN_BOOLEAN_CONSTANT:
{
*(bool32*)var_out = (item.mem[item.line.val_token.start] == 't');
}break;
case CPP_TOKEN_INTEGER_CONSTANT:
{
String val = make_string(item.mem + item.line.val_token.start, item.line.val_token.size);
*(int32_t*)var_out = str_to_int(val);
}break;
case CPP_TOKEN_STRING_CONSTANT:
{
*(String*)var_out = make_string(item.mem + item.line.val_token.start + 1,item.line.val_token.size - 2);
}break;
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;
array_reader->good = 1;
}break;
}
}
result = 1;
}
}
}
return(result);
}
static bool32
config_bool_var(Config_Item item, char *var_name, int32_t *subscript, bool32 *var_out){
bool32 result = config_var(item, var_name, subscript, CPP_TOKEN_BOOLEAN_CONSTANT, var_out);
return(result);
}
static bool32
config_int_var(Config_Item item, char *var_name, int32_t *subscript, int32_t *var_out){
bool32 result = config_var(item, var_name, subscript, CPP_TOKEN_INTEGER_CONSTANT, var_out);
return(result);
}
static bool32
config_string_var(Config_Item item, char *var_name, int32_t *subscript, String *var_out){
bool32 result = config_var(item, var_name, subscript, CPP_TOKEN_STRING_CONSTANT, var_out);
return(result);
}
static bool32
config_array_var(Config_Item item, char *var_name, int32_t *subscript, Config_Array_Reader *array_reader){
bool32 result = config_var(item, var_name, subscript, CPP_TOKEN_BRACE_OPEN, array_reader);
return(result);
}
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:;
array_reader->good = result;
return(result);
}
static bool32
config_array_good(Config_Array_Reader *array_reader){
bool32 result = (array_reader->good);
return(result);
}
//
// Configuration
//
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");
static String user_name = {0};
static bool32
get_current_name(char **name_out, int32_t *len_out){
bool32 result = false;
*name_out = 0;
if (user_name.str != 0){
*name_out = user_name.str;
*len_out = user_name.size;
result = true;
}
return(result);
}
// TODO(allen): Stop handling files this way! My own API should be able to do this!!?!?!?!!?!?!!!!?
#include <stdio.h>
static bool32
file_handle_dump(Partition *part, FILE *file, char **mem_ptr, int32_t *size_ptr){
bool32 success = 0;
fseek(file, 0, SEEK_END);
int32_t size = ftell(file);
char *mem = (char*)push_block(part, size+1);
fseek(file, 0, SEEK_SET);
int32_t check_size = (int32_t)fread(mem, 1, size, file);
if (check_size == size){
mem[size] = 0;
success = 1;
}
*mem_ptr = mem;
*size_ptr = size;
return(success);
}
static void
process_config_file(Application_Links *app){
Partition *part = &global_part;
FILE *file = fopen("config.4coder", "rb");
if (!file){
char space[256];
int32_t size = get_4ed_path(app, space, sizeof(space));
String str = make_string_cap(space, size, sizeof(space));
append_sc(&str, "/config.4coder");
terminate_with_null(&str);
file = fopen(str.str, "rb");
}
if (file){
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);
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){
int32_t new_wrap_width = default_wrap_width;
int32_t new_min_base_width = default_min_base_width;
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);
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);
config_string_var(item, "default_theme_name", 0, &default_theme_name);
config_string_var(item, "default_font_name", 0, &default_font_name);
config_string_var(item, "user_name", 0, &user_name);
}
}
adjust_all_buffer_wrap_widths(app, new_wrap_width, new_min_base_width);
default_wrap_width = new_wrap_width;
default_min_base_width = new_min_base_width;
}
}
end_temp_memory(temp);
}
else{
print_message(app, literal("Did not find config.4coder, using default settings\n"));
}
}
//
// Framework Init Functions
//
void
init_memory(Application_Links *app){
int32_t part_size = (32 << 20);
int32_t general_size = (4 << 20);
void *part_mem = memory_allocate(app, part_size);
global_part = make_part(part_mem, part_size);
void *general_mem = memory_allocate(app, general_size);
general_memory_open(&global_general, general_mem, general_size);
}
static void
default_4coder_initialize(Application_Links *app){
init_memory(app);
process_config_file(app);
change_theme(app, default_theme_name.str, default_theme_name.size);
change_font(app, default_font_name.str, default_font_name.size, 1);
}
static void
default_4coder_side_by_side_panels(Application_Links *app){
exec_command(app, open_panel_vsplit);
exec_command(app, hide_scrollbar);
exec_command(app, change_active_panel);
exec_command(app, hide_scrollbar);
}
static void
default_4coder_one_panel(Application_Links *app){
exec_command(app, hide_scrollbar);
}
static void
default_4coder_full_width_bottom_side_by_side_panels(Application_Links){
// TODO(allen):
}
#endif #endif
// BOTTOM // BOTTOM

255
4coder_default_hooks.cpp Normal file
View File

@ -0,0 +1,255 @@
/*
4coder_default_hooks.cpp - Sets up the hooks for the default framework.
TYPE: 'internal-for-default-system'
*/
// TOP
#if !defined(FCODER_DEFAULT_HOOKS_CPP)
#define FCODER_DEFAULT_HOOKS_CPP
#include "4coder_default_framework.h"
#include "4coder_helper/4coder_bind_helper.h"
HOOK_SIG(default_start){
default_4coder_initialize(app);
default_4coder_side_by_side_panels(app);
// no meaning for return
return(0);
}
// NOTE(allen|a4.0.9): All command calls can now go through this hook
// If this hook is not implemented a default behavior of calling the
// command is used. It is important to note that paste_next does not
// work without this hook.
// NOTE(allen|a4.0.10): As of this version the word_complete command
// also relies on this particular command caller hook.
COMMAND_CALLER_HOOK(default_command_caller){
View_Summary view = get_active_view(app, AccessAll);
view_paste_index[view.view_id].next_rewrite = 0;
exec_command(app, cmd);
view_paste_index[view.view_id].rewrite = view_paste_index[view.view_id].next_rewrite;
return(0);
}
HOOK_SIG(default_exit){
// if this returns zero it cancels the exit.
return(1);
}
HOOK_SIG(default_view_adjust){
int32_t count = 0;
int32_t new_wrap_width = 0;
for (View_Summary view = get_view_first(app, AccessAll);
view.exists;
get_view_next(app, &view, AccessAll)){
new_wrap_width += view.view_region.x1 - view.view_region.x0;
++count;
}
new_wrap_width /= count;
new_wrap_width = (int32_t)(new_wrap_width * .9f);
int32_t new_min_base_width = (int32_t)(new_wrap_width * .77f);
if (automatically_adjust_wrapping){
adjust_all_buffer_wrap_widths(app, new_wrap_width, new_min_base_width);
default_wrap_width = new_wrap_width;
default_min_base_width = new_min_base_width;
}
// no meaning for return
return(0);
}
// TODO(allen): Eliminate this hook if you can.
OPEN_FILE_HOOK_SIG(default_file_settings){
// NOTE(allen|a4.0.8): The get_parameter_buffer was eliminated
// and instead the buffer is passed as an explicit parameter through
// the function call. That is where buffer_id comes from here.
uint32_t access = AccessAll;
Buffer_Summary buffer = get_buffer(app, buffer_id, access);
Assert(buffer.exists);
int32_t treat_as_code = 0;
int32_t wrap_lines = 1;
if (buffer.file_name && buffer.size < (16 << 20)){
String ext = file_extension(make_string(buffer.file_name, buffer.file_name_len));
if (match_ss(ext, make_lit_string("cpp")) ||
match_ss(ext, make_lit_string("h")) ||
match_ss(ext, make_lit_string("c")) ||
match_ss(ext, make_lit_string("hpp"))){
treat_as_code = 1;
}
}
if (treat_as_code){
wrap_lines = 0;
}
if (buffer.file_name[0] == '*'){
wrap_lines = 0;
}
buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, default_wrap_width);
buffer_set_setting(app, &buffer, BufferSetting_MinimumBaseWrapPosition, default_min_base_width);
buffer_set_setting(app, &buffer, BufferSetting_MapID, (treat_as_code)?((int32_t)default_code_map):((int32_t)mapid_file));
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, 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.
buffer_set_setting(app, &buffer, BufferSetting_WrapLine, 1);
buffer_set_setting(app, &buffer, BufferSetting_VirtualWhitespace, 1);
}
else{
buffer_set_setting(app, &buffer, BufferSetting_WrapLine, wrap_lines);
buffer_set_setting(app, &buffer, BufferSetting_Lex, treat_as_code);
}
// no meaning for return
return(0);
}
OPEN_FILE_HOOK_SIG(default_file_save){
uint32_t access = AccessAll;
Buffer_Summary buffer = get_buffer(app, buffer_id, access);
Assert(buffer.exists);
#if defined(FCODER_AUTO_INDENT_CPP)
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);
}
}
#endif
// 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.
//
// Right now it only has access to the mouse state, but it will be
// extended to have access to the key presses soon.
INPUT_FILTER_SIG(default_suppress_mouse_filter){
if (suppressing_mouse){
*mouse = null_mouse_state;
mouse->x = -100;
mouse->y = -100;
}
}
// NOTE(allen|a4): scroll rule information
//
// The parameters:
// target_x, target_y
// This is where the view would like to be for the purpose of
// following the cursor, doing mouse wheel work, etc.
//
// scroll_x, scroll_y
// These are pointers to where the scrolling actually is. If you bind
// the scroll rule it is you have to update these in some way to move
// the actual location of the scrolling.
//
// view_id
// This corresponds to which view is computing it's new scrolling position.
// This id DOES correspond to the views that View_Summary contains.
// This will always be between 1 and 16 (0 is a null id).
// See below for an example of having state that carries across scroll udpates.
//
// is_new_target
// If the target of the view is different from the last target in either x or y
// this is true, otherwise it is false.
//
// The return:
// Should be true if and only if scroll_x or scroll_y are changed.
//
// Don't try to use the app pointer in a scroll rule, you're asking for trouble.
//
// If you don't bind scroll_rule, nothing bad will happen, yo will get default
// 4coder scrolling behavior.
//
struct Scroll_Velocity{
float x, y;
};
Scroll_Velocity scroll_velocity_[16] = {0};
Scroll_Velocity *scroll_velocity = scroll_velocity_ - 1;
static int32_t
smooth_camera_step(float target, float *current, float *vel, float S, float T){
int32_t result = 0;
float curr = *current;
float v = *vel;
if (curr != target){
if (curr > target - .1f && curr < target + .1f){
curr = target;
v = 1.f;
}
else{
float L = curr + T*(target - curr);
int32_t sign = (target > curr) - (target < curr);
float V = curr + sign*v;
if (sign > 0) curr = (L<V)?(L):(V);
else curr = (L>V)?(L):(V);
if (curr == V){
v *= S;
}
}
*current = curr;
*vel = v;
result = 1;
}
return(result);
}
SCROLL_RULE_SIG(smooth_scroll_rule){
Scroll_Velocity *velocity = scroll_velocity + view_id;
int32_t result = 0;
if (velocity->x == 0.f){
velocity->x = 1.f;
velocity->y = 1.f;
}
if (smooth_camera_step(target_y, scroll_y, &velocity->y, 80.f, 1.f/2.f)){
result = 1;
}
if (smooth_camera_step(target_x, scroll_x, &velocity->x, 80.f, 1.f/2.f)){
result = 1;
}
return(result);
}
static void
set_all_default_hooks(Bind_Helper *context){
set_hook(context, hook_start, default_start);
set_hook(context, hook_exit, default_exit);
set_hook(context, hook_view_size_change, default_view_adjust);
set_open_file_hook(context, default_file_settings);
set_save_file_hook(context, default_file_save);
set_command_caller(context, default_command_caller);
set_input_filter(context, default_suppress_mouse_filter);
set_scroll_rule(context, smooth_scroll_rule);
}
#endif
// BOTTOM

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,23 @@
/*
4coder_function_list.cpp - Command for listing all functions in a C/C++ file in a jump list.
TYPE: 'drop-in-command-pack'
*/
// TOP // TOP
#if !defined(FCODER_FUNCTION_LIST_CPP)
#define FCODER_FUNCTION_LIST_CPP
#include "4coder_API/custom.h"
#include "4coder_default_framework.h"
#include "4coder_helper/4coder_helper.h"
#include "4coder_helper/4coder_streaming.h"
#include "4coder_lib/4coder_mem.h"
// NOTE(allen|a4.0.14): This turned out to be a nasty little routine. There might // NOTE(allen|a4.0.14): This turned out to be a nasty little routine. There might
// be a better way to do it with just tokens that I didn't see the first time // be a better way to do it with just tokens that I didn't see the first time
// through. Once I build a real parser this should become almost just as easy as // through. Once I build a real parser this should become almost just as easy as
@ -10,7 +27,6 @@
// will then provide the "list_all_functions_current_buffer" command. // will then provide the "list_all_functions_current_buffer" command.
// //
// //
// Declaration list // Declaration list
// //
@ -278,5 +294,7 @@ CUSTOM_COMMAND_SIG(list_all_functions_current_buffer){
list_all_functions(app, &global_part, &buffer); list_all_functions(app, &global_part, &buffer);
} }
#endif
// BOTTOM // BOTTOM

View File

@ -182,6 +182,16 @@ make_range(int32_t p1, int32_t p2){
return(range); return(range);
} }
static void
adjust_all_buffer_wrap_widths(Application_Links *app, int32_t wrap_width, int32_t min_base_width){
for (Buffer_Summary buffer = get_buffer_first(app, AccessAll);
buffer.exists;
get_buffer_next(app, &buffer, AccessAll)){
buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, wrap_width);
buffer_set_setting(app, &buffer, BufferSetting_MinimumBaseWrapPosition, min_base_width);
}
}
struct Buffer_Rect{ struct Buffer_Rect{
int32_t char0, line0; int32_t char0, line0;
int32_t char1, line1; int32_t char1, line1;

View File

@ -884,7 +884,7 @@ read_line(Application_Links *app, Partition *part, Buffer_Summary *buffer, int32
int32_t success = 0; int32_t success = 0;
if (buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &begin)){ if (buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &begin)){
if (buffer_compute_cursor(app, buffer, seek_line_char(line, 65536), &end)){ if (buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &end)){
if (begin.line == line){ if (begin.line == line){
if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer->size){ if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer->size){
int32_t size = (end.pos - begin.pos); int32_t size = (end.pos - begin.pos);
@ -919,7 +919,7 @@ buffer_get_line_end(Application_Links *app, Buffer_Summary *buffer, int32_t line
Partial_Cursor partial_cursor; Partial_Cursor partial_cursor;
int32_t result = buffer->size; int32_t result = buffer->size;
if (line <= buffer->line_count){ if (line <= buffer->line_count){
buffer_compute_cursor(app, buffer, seek_line_char(line, 65536), &partial_cursor); buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &partial_cursor);
result = partial_cursor.pos; result = partial_cursor.pos;
} }
return(result); return(result);
@ -931,7 +931,7 @@ buffer_line_is_blank(Application_Links *app, Buffer_Summary *buffer, int32_t lin
bool32 result = 0; bool32 result = 0;
if (line <= buffer->line_count){ if (line <= buffer->line_count){
buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &start); buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &start);
buffer_compute_cursor(app, buffer, seek_line_char(line, 65536), &end); buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &end);
static const int32_t chunk_size = 1024; static const int32_t chunk_size = 1024;
char chunk[chunk_size]; char chunk[chunk_size];

View File

@ -22,13 +22,6 @@ typedef struct Name_Based_Jump_Location{
int32_t column; int32_t column;
} Name_Based_Jump_Location; } Name_Based_Jump_Location;
typedef struct ID_Based_Jump_Location{
int32_t buffer_id;
int32_t line;
int32_t column;
} ID_Based_Jump_Location;
static ID_Based_Jump_Location null_location = {0};
static void static void
jump_to_location(Application_Links *app, View_Summary *view, Name_Based_Jump_Location *l){ jump_to_location(Application_Links *app, View_Summary *view, Name_Based_Jump_Location *l){
if (view_open_file(app, view, l->file.str, l->file.size, true)){ if (view_open_file(app, view, l->file.str, l->file.size, true)){
@ -55,8 +48,9 @@ static int32_t
parse_jump_location(String line, Name_Based_Jump_Location *location, int32_t skip_sub_errors, int32_t *colon_char){ parse_jump_location(String line, Name_Based_Jump_Location *location, int32_t skip_sub_errors, int32_t *colon_char){
int32_t result = false; int32_t result = false;
int32_t whitespace_length = 0;
String original_line = line; String original_line = line;
line = skip_chop_whitespace(line); line = skip_chop_whitespace(line, &whitespace_length);
int32_t colon_pos = 0; int32_t colon_pos = 0;
int32_t is_ms_style = 0; int32_t is_ms_style = 0;
@ -102,7 +96,7 @@ parse_jump_location(String line, Name_Based_Jump_Location *location, int32_t ski
location->column = 1; location->column = 1;
} }
*colon_char = colon_pos; *colon_char = colon_pos + whitespace_length;
result = true; result = true;
} }
} }
@ -137,7 +131,7 @@ parse_jump_location(String line, Name_Based_Jump_Location *location, int32_t ski
location->file = filename; location->file = filename;
location->line = str_to_int_s(line_number); location->line = str_to_int_s(line_number);
location->column = str_to_int_s(column_number); location->column = str_to_int_s(column_number);
*colon_char = colon_pos3; *colon_char = colon_pos3 + whitespace_length;
result = true; result = true;
} }
} }
@ -151,7 +145,7 @@ parse_jump_location(String line, Name_Based_Jump_Location *location, int32_t ski
location->file = filename; location->file = filename;
location->line = str_to_int_s(line_number); location->line = str_to_int_s(line_number);
location->column = 0; location->column = 0;
*colon_char = colon_pos2; *colon_char = colon_pos2 + whitespace_length;
result = true; result = true;
} }
} }
@ -253,9 +247,7 @@ seek_next_jump_in_view(Application_Links *app, Partition *part, View_Summary *vi
Name_Based_Jump_Location location = {0}; Name_Based_Jump_Location location = {0};
int32_t line = view->cursor.line; int32_t line = view->cursor.line;
int32_t colon_index = 0; int32_t colon_index = 0;
if (seek_next_jump_in_buffer(app, part, view->buffer_id, if (seek_next_jump_in_buffer(app, part, view->buffer_id, line+direction, skip_sub_errors, direction, &line, &colon_index, &location)){
line+direction, skip_sub_errors, direction,
&line, &colon_index, &location)){
result = true; result = true;
*line_out = line; *line_out = line;
*colon_index_out = colon_index; *colon_index_out = colon_index;
@ -277,8 +269,6 @@ skip_this_jump(ID_Based_Jump_Location prev, ID_Based_Jump_Location jump){
return(result); return(result);
} }
static ID_Based_Jump_Location prev_location = {0};
static int32_t static int32_t
advance_cursor_in_jump_view(Application_Links *app, Partition *part, View_Summary *view, int32_t skip_repeats, int32_t skip_sub_error, int32_t direction, Name_Based_Jump_Location *location_out){ advance_cursor_in_jump_view(Application_Links *app, Partition *part, View_Summary *view, int32_t skip_repeats, int32_t skip_sub_error, int32_t direction, Name_Based_Jump_Location *location_out){
int32_t result = true; int32_t result = true;
@ -289,10 +279,9 @@ advance_cursor_in_jump_view(Application_Links *app, Partition *part, View_Summar
do{ do{
Temp_Memory temp = begin_temp_memory(part); Temp_Memory temp = begin_temp_memory(part);
if (seek_next_jump_in_view(app, part, view, if (seek_next_jump_in_view(app, part, view, skip_sub_error, direction, &line, &colon_index, &location)){
skip_sub_error, direction,
&line, &colon_index, &location)){
jump = convert_name_based_to_id_based(app, location); jump = convert_name_based_to_id_based(app, location);
view_set_cursor(app, view, seek_line_char(line, colon_index+1), true);
result = true; result = true;
} }
else{ else{
@ -313,16 +302,14 @@ advance_cursor_in_jump_view(Application_Links *app, Partition *part, View_Summar
} }
static int32_t static int32_t
seek_error(Application_Links *app, Partition *part, int32_t skip_repeats, int32_t skip_sub_errors, int32_t direction){ seek_jump(Application_Links *app, Partition *part, int32_t skip_repeats, int32_t skip_sub_errors, int32_t direction){
int32_t result = 0; int32_t result = 0;
View_Summary view = get_view_for_locked_jump_buffer(app); View_Summary view = get_view_for_locked_jump_buffer(app);
if (view.exists){ if (view.exists){
Name_Based_Jump_Location location = {0}; Name_Based_Jump_Location location = {0};
if (advance_cursor_in_jump_view(app, &global_part, &view, if (advance_cursor_in_jump_view(app, &global_part, &view, skip_repeats, skip_sub_errors, direction, &location)){
skip_repeats, skip_sub_errors, direction,
&location)){
View_Summary active_view = get_active_view(app, AccessAll); View_Summary active_view = get_active_view(app, AccessAll);
if (active_view.view_id == view.view_id){ if (active_view.view_id == view.view_id){
exec_command(app, change_active_panel); exec_command(app, change_active_panel);
@ -342,28 +329,28 @@ CUSTOM_COMMAND_SIG(goto_next_jump){
int32_t skip_repeats = true; int32_t skip_repeats = true;
int32_t skip_sub_errors = true; int32_t skip_sub_errors = true;
int32_t dir = 1; int32_t dir = 1;
seek_error(app, &global_part, skip_repeats, skip_sub_errors, dir); seek_jump(app, &global_part, skip_repeats, skip_sub_errors, dir);
} }
CUSTOM_COMMAND_SIG(goto_prev_jump){ CUSTOM_COMMAND_SIG(goto_prev_jump){
int32_t skip_repeats = true; int32_t skip_repeats = true;
int32_t skip_sub_errors = true; int32_t skip_sub_errors = true;
int32_t dir = -1; int32_t dir = -1;
seek_error(app, &global_part, skip_repeats, skip_sub_errors, dir); seek_jump(app, &global_part, skip_repeats, skip_sub_errors, dir);
} }
CUSTOM_COMMAND_SIG(goto_next_jump_no_skips){ CUSTOM_COMMAND_SIG(goto_next_jump_no_skips){
int32_t skip_repeats = false; int32_t skip_repeats = false;
int32_t skip_sub_errors = true; int32_t skip_sub_errors = true;
int32_t dir = 1; int32_t dir = 1;
seek_error(app, &global_part, skip_repeats, skip_sub_errors, dir); seek_jump(app, &global_part, skip_repeats, skip_sub_errors, dir);
} }
CUSTOM_COMMAND_SIG(goto_prev_jump_no_skips){ CUSTOM_COMMAND_SIG(goto_prev_jump_no_skips){
int32_t skip_repeats = false; int32_t skip_repeats = false;
int32_t skip_sub_errors = true; int32_t skip_sub_errors = true;
int32_t dir = -1; int32_t dir = -1;
seek_error(app, &global_part, skip_repeats, skip_sub_errors, dir); seek_jump(app, &global_part, skip_repeats, skip_sub_errors, dir);
} }
CUSTOM_COMMAND_SIG(goto_first_jump){ CUSTOM_COMMAND_SIG(goto_first_jump){
@ -374,11 +361,29 @@ CUSTOM_COMMAND_SIG(goto_first_jump){
view_set_cursor(app, &view, seek_pos(0), true); view_set_cursor(app, &view, seek_pos(0), true);
prev_location = null_location; prev_location = null_location;
seek_error(app, &global_part, false, true, 1); seek_jump(app, &global_part, false, true, 1);
} }
end_temp_memory(temp); end_temp_memory(temp);
} }
//
// Insert Newline - or Tigger Jump on Read Only Buffer
//
CUSTOM_COMMAND_SIG(newline_or_goto_position){
View_Summary view = get_active_view(app, AccessProtected);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
if (buffer.lock_flags & AccessProtected){
exec_command(app, goto_jump_at_cursor);
lock_jump_buffer(buffer);
}
else{
exec_command(app, write_character);
}
}
#define seek_error seek_jump
#define goto_next_error goto_next_jump #define goto_next_error goto_next_jump
#define goto_prev_error goto_prev_jump #define goto_prev_error goto_prev_jump
#define goto_next_error_no_skips goto_next_jump_no_skips #define goto_next_error_no_skips goto_next_jump_no_skips

View File

@ -1,5 +1,5 @@
/* /*
4coder_string.h - Version 1.0.14 4coder_string.h - Version 1.0.59
no warranty implied; use at your own risk no warranty implied; use at your own risk
This software is in the public domain. Where that dedication is not This software is in the public domain. Where that dedication is not
@ -94,8 +94,10 @@ FSTRING_INLINE String make_string_slowly(void *str);
FSTRING_INLINE String substr_tail(String str, i32_4tech start); FSTRING_INLINE String substr_tail(String str, i32_4tech start);
FSTRING_INLINE String substr(String str, i32_4tech start, i32_4tech size); FSTRING_INLINE String substr(String str, i32_4tech start, i32_4tech size);
FSTRING_LINK String skip_whitespace(String str); FSTRING_LINK String skip_whitespace(String str);
FSTRING_LINK String skip_whitespace_measure(String str, i32_4tech *skip_length);
FSTRING_LINK String chop_whitespace(String str); FSTRING_LINK String chop_whitespace(String str);
FSTRING_LINK String skip_chop_whitespace(String str); FSTRING_LINK String skip_chop_whitespace(String str);
FSTRING_LINK String skip_chop_whitespace_measure(String str, i32_4tech *skip_length);
FSTRING_INLINE String tailstr(String str); FSTRING_INLINE String tailstr(String str);
FSTRING_LINK b32_4tech match_cc(char *a, char *b); FSTRING_LINK b32_4tech match_cc(char *a, char *b);
FSTRING_LINK b32_4tech match_sc(String a, char *b); FSTRING_LINK b32_4tech match_sc(String a, char *b);
@ -199,6 +201,8 @@ FSTRING_LINK String get_first_word(String source);
FSTRING_INLINE String make_string(void *str, i32_4tech size, i32_4tech mem_size){return(make_string_cap(str,size,mem_size));} FSTRING_INLINE String make_string(void *str, i32_4tech size, i32_4tech mem_size){return(make_string_cap(str,size,mem_size));}
FSTRING_INLINE String substr(String str, i32_4tech start){return(substr_tail(str,start));} FSTRING_INLINE String substr(String str, i32_4tech start){return(substr_tail(str,start));}
FSTRING_LINK String skip_whitespace(String str, i32_4tech *skip_length){return(skip_whitespace_measure(str,skip_length));}
FSTRING_LINK String skip_chop_whitespace(String str, i32_4tech *skip_length){return(skip_chop_whitespace_measure(str,skip_length));}
FSTRING_LINK b32_4tech match(char *a, char *b){return(match_cc(a,b));} FSTRING_LINK b32_4tech match(char *a, char *b){return(match_cc(a,b));}
FSTRING_LINK b32_4tech match(String a, char *b){return(match_sc(a,b));} FSTRING_LINK b32_4tech match(String a, char *b){return(match_sc(a,b));}
FSTRING_INLINE b32_4tech match(char *a, String b){return(match_cs(a,b));} FSTRING_INLINE b32_4tech match(char *a, String b){return(match_cs(a,b));}
@ -460,6 +464,20 @@ skip_whitespace(String str)
} }
#endif #endif
#if defined(FSTRING_IMPLEMENTATION)
FSTRING_LINK String
skip_whitespace_measure(String str, i32_4tech *skip_length)
{
String result = {0};
i32_4tech i = 0;
for (; i < str.size && char_is_whitespace(str.str[i]); ++i);
result = substr(str, i, str.size - i);
*skip_length = i;
return(result);
}
#endif
#if defined(FSTRING_IMPLEMENTATION) #if defined(FSTRING_IMPLEMENTATION)
FSTRING_LINK String FSTRING_LINK String
chop_whitespace(String str) chop_whitespace(String str)
@ -482,6 +500,17 @@ skip_chop_whitespace(String str)
} }
#endif #endif
#if defined(FSTRING_IMPLEMENTATION)
FSTRING_LINK String
skip_chop_whitespace_measure(String str, i32_4tech *skip_length)
{
str = skip_whitespace_measure(str, skip_length);
str = chop_whitespace(str);
return(str);
}
#endif
#if !defined(FSTRING_GUARD) #if !defined(FSTRING_GUARD)
FSTRING_INLINE String FSTRING_INLINE String
tailstr(String str) tailstr(String str)
@ -2031,7 +2060,7 @@ static void
get_absolutes(String name, Absolutes *absolutes, b32_4tech implicit_first, b32_4tech implicit_last){ get_absolutes(String name, Absolutes *absolutes, b32_4tech implicit_first, b32_4tech implicit_last){
if (name.size != 0){ if (name.size != 0){
i32_4tech count = 0; i32_4tech count = 0;
i32_4tech max = sizeof(absolutes->a)/sizeof(absolutes->a[0]) - 1; i32_4tech max = (sizeof(absolutes->a)/sizeof(*absolutes->a)) - 1;
if (implicit_last) --max; if (implicit_last) --max;
String str; String str;

428
4coder_project_commands.cpp Normal file
View File

@ -0,0 +1,428 @@
/*
4coder_project_commands.cpp - Commands for loading and using a project.
TYPE: 'drop-in-command-pack'
*/
// TOP
#if !defined(FCODER_PROJECT_COMMANDS_CPP)
#define FCODER_PROJECT_COMMANDS_CPP
#include "4coder_default_framework.h"
#include "4coder_lib/4coder_mem.h"
#include "4coder_build_commands.cpp"
// 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);
}
// 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_current_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_current_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;
char project_file_space[512];
String project_name = make_fixed_width_string(project_file_space);
project_name.size = directory_get_hot(app, project_name.str, project_name.memory_size);
if (project_name.size >= project_name.memory_size){
project_name.size = 0;
}
if (project_name.size != 0){
int32_t original_size = project_name.size;
append_sc(&project_name, "project.4coder");
terminate_with_null(&project_name);
FILE *file = fopen(project_name.str, "rb");
if (file){
project_name.size = original_size;
terminate_with_null(&project_name);
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);
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;
// 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"));
}
}
}
{
#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
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!, ");
}
}
}
if (read_bool){
if (config_bool_var(array_item, 0, 0, dest_bool)){
if (dest_bool){
append(&msg, "true, ");
}
else{
append(&msg, "false, ");
}
}
}
item_index++;
}
append(&msg, "}\n");
print_message(app, msg.str, msg.size);
}
}
}
}
}
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"));
}
}
static void
exec_project_fkey_command(Application_Links *app, int32_t command_ind){
char *command = current_project.fkey_commands[command_ind].command;
char *out = current_project.fkey_commands[command_ind].out;
bool32 use_build_panel = current_project.fkey_commands[command_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);
}
}
}
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);
exec_project_fkey_command(app, ind);
}
}
}
#endif
// BOTTOM

53
4coder_system_command.cpp Normal file
View File

@ -0,0 +1,53 @@
/*
4coder_system_command.cpp - Commands for executing arbitrary system command line instructions.
TYPE: 'drop-in-command-pack'
*/
// TOP
#if !defined(FCODER_SYSTEM_COMMAND_CPP)
#define FCODER_SYSTEM_COMMAND_CPP
#include "4coder_default_framework.h"
CUSTOM_COMMAND_SIG(execute_any_cli){
Query_Bar bar_out = {0};
Query_Bar bar_cmd = {0};
bar_out.prompt = make_lit_string("Output Buffer: ");
bar_out.string = make_fixed_width_string(out_buffer_space);
if (!query_user_string(app, &bar_out)) return;
bar_cmd.prompt = make_lit_string("Command: ");
bar_cmd.string = make_fixed_width_string(command_space);
if (!query_user_string(app, &bar_cmd)) return;
String hot_directory = make_fixed_width_string(hot_directory_space);
hot_directory.size = directory_get_hot(app, hot_directory.str, hot_directory.memory_size);
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);
lock_jump_buffer(bar_out.string.str, bar_out.string.size);
}
CUSTOM_COMMAND_SIG(execute_previous_cli){
String out_buffer = make_string_slowly(out_buffer_space);
String cmd = make_string_slowly(command_space);
String hot_directory = make_string_slowly(hot_directory_space);
if (out_buffer.size > 0 && cmd.size > 0 && hot_directory.size > 0){
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);
lock_jump_buffer(out_buffer.str, out_buffer.size);
}
}
#endif
// BOTTOM

60
4ed.cpp
View File

@ -62,22 +62,22 @@ typedef struct Consumption_Record{
} Consumption_Record; } Consumption_Record;
typedef struct Available_Input{ typedef struct Available_Input{
Key_Summary *keys; Key_Input_Data *keys;
Mouse_State *mouse; Mouse_State *mouse;
Consumption_Record records[Input_Count]; Consumption_Record records[Input_Count];
} Available_Input; } Available_Input;
internal Available_Input internal Available_Input
init_available_input(Key_Summary *keys, Mouse_State *mouse){ init_available_input(Key_Input_Data *keys, Mouse_State *mouse){
Available_Input result = {0}; Available_Input result = {0};
result.keys = keys; result.keys = keys;
result.mouse = mouse; result.mouse = mouse;
return(result); return(result);
} }
internal Key_Summary internal Key_Input_Data
direct_get_key_data(Available_Input *available){ direct_get_key_data(Available_Input *available){
Key_Summary result = *available->keys; Key_Input_Data result = *available->keys;
return(result); return(result);
} }
@ -87,9 +87,9 @@ direct_get_mouse_state(Available_Input *available){
return(result); return(result);
} }
internal Key_Summary internal Key_Input_Data
get_key_data(Available_Input *available){ get_key_data(Available_Input *available){
Key_Summary result = {0}; Key_Input_Data result = {0};
if (!available->records[Input_AnyKey].consumed){ if (!available->records[Input_AnyKey].consumed){
result = *available->keys; result = *available->keys;
@ -1688,46 +1688,32 @@ App_Step_Sig(app_step){
if (prev_width != current_width || prev_height != current_height){ if (prev_width != current_width || prev_height != current_height){
layout_refit(&models->layout, prev_width, prev_height); layout_refit(&models->layout, prev_width, prev_height);
} }
} }
// NOTE(allen): prepare input information // NOTE(allen): prepare input information
Key_Summary key_summary = {0};
{ {
for (i32 i = 0; i < input->keys.press_count; ++i){
key_summary.keys[key_summary.count++] = input->keys.press[i];
}
for (i32 i = 0; i < input->keys.hold_count; ++i){
key_summary.keys[key_summary.count++] = input->keys.hold[i];
}
if (models->input_filter){ if (models->input_filter){
models->input_filter(&input->mouse); models->input_filter(&input->mouse);
} }
Key_Event_Data mouse_event = {0}; Key_Event_Data mouse_event = {0};
memcpy(mouse_event.modifiers, input->keys.modifiers, sizeof(input->keys.modifiers));
if (input->mouse.press_l){ if (input->mouse.press_l){
mouse_event.keycode = key_mouse_left; mouse_event.keycode = key_mouse_left;
key_summary.keys[key_summary.count++] = mouse_event; input->keys.keys[input->keys.count++] = mouse_event;
}
else if (input->mouse.release_l){
mouse_event.keycode = key_mouse_left_release;
input->keys.keys[input->keys.count++] = mouse_event;
} }
if (input->mouse.press_r){ if (input->mouse.press_r){
mouse_event.keycode = key_mouse_right; mouse_event.keycode = key_mouse_right;
key_summary.keys[key_summary.count++] = mouse_event; input->keys.keys[input->keys.count++] = mouse_event;
} }
else if (input->mouse.release_r){
if (input->mouse.release_l){
mouse_event.keycode = key_mouse_left_release;
key_summary.keys[key_summary.count++] = mouse_event;
}
if (input->mouse.release_r){
mouse_event.keycode = key_mouse_right_release; mouse_event.keycode = key_mouse_right_release;
key_summary.keys[key_summary.count++] = mouse_event; input->keys.keys[input->keys.count++] = mouse_event;
} }
input->mouse.wheel = -input->mouse.wheel; input->mouse.wheel = -input->mouse.wheel;
@ -1996,11 +1982,11 @@ App_Step_Sig(app_step){
} }
// NOTE(allen): pass events to debug // NOTE(allen): pass events to debug
vars->available_input = init_available_input(&key_summary, &input->mouse); vars->available_input = init_available_input(&input->keys, &input->mouse);
{ {
Debug_Data *debug = &models->debug; Debug_Data *debug = &models->debug;
Key_Summary key_data = get_key_data(&vars->available_input); Key_Input_Data key_data = get_key_data(&vars->available_input);
Debug_Input_Event *events = debug->input_events; Debug_Input_Event *events = debug->input_events;
@ -2033,7 +2019,7 @@ App_Step_Sig(app_step){
get_flags |= abort_flags; get_flags |= abort_flags;
if ((get_flags & EventOnAnyKey) || (get_flags & EventOnEsc)){ if ((get_flags & EventOnAnyKey) || (get_flags & EventOnEsc)){
Key_Summary key_data = get_key_data(&vars->available_input); Key_Input_Data key_data = get_key_data(&vars->available_input);
for (i32 key_i = 0; key_i < key_data.count; ++key_i){ for (i32 key_i = 0; key_i < key_data.count; ++key_i){
Key_Event_Data key = get_single_key(&key_data, key_i); Key_Event_Data key = get_single_key(&key_data, key_i);
@ -2259,7 +2245,7 @@ App_Step_Sig(app_step){
// NOTE(allen): command execution // NOTE(allen): command execution
{ {
Key_Summary key_data = get_key_data(&vars->available_input); Key_Input_Data key_data = get_key_data(&vars->available_input);
b32 hit_something = 0; b32 hit_something = 0;
b32 hit_esc = 0; b32 hit_esc = 0;
@ -2379,6 +2365,11 @@ App_Step_Sig(app_step){
"If you're new to 4coder there are some tutorials at http://4coder.net/tutorials.html\n" "If you're new to 4coder there are some tutorials at http://4coder.net/tutorials.html\n"
"\n" "\n"
"Newest features:\n" "Newest features:\n"
"-<ctrl I> find all functions in the current buffer and list them in a jump buffer\n"
"-option to set user name in config.4coder\n"
" The user name is used in <alt t> and <alt y> comment writing commands\n"
"\n"
"New in alpha 4.0.14:\n"
"-Option to have wrap widths automatically adjust based on average view width\n" "-Option to have wrap widths automatically adjust based on average view width\n"
"-The 'config.4coder' file can now be placed with the 4ed executable file\n" "-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 options in 'config.4coder' to specify the font and color theme\n"
@ -2389,7 +2380,7 @@ App_Step_Sig(app_step){
"New in alpha 4.0.12 and 4.0.13:\n" "New in alpha 4.0.12 and 4.0.13:\n"
"-Text files wrap lines at whitespace when possible\n" "-Text files wrap lines at whitespace when possible\n"
"-New code wrapping feature is on by default\n" "-New code wrapping feature is on by default\n"
"-Introduced a 'config.4coder' for setting several wrapping options:" "-Introduced a 'config.4coder' for setting several wrapping options:\n"
" enable_code_wrapping: set to false if you want the text like behavior\n" " enable_code_wrapping: set to false if you want the text like behavior\n"
" default_wrap_width: the wrap width to set in new files\n" " default_wrap_width: the wrap width to set in new files\n"
"-<ctrl 2> decrease the current buffer's wrap width\n" "-<ctrl 2> decrease the current buffer's wrap width\n"
@ -2635,8 +2626,7 @@ App_Step_Sig(app_step){
} }
} }
do_render_file_view(system, view, scroll_vars, active_view, do_render_file_view(system, view, scroll_vars, active_view, panel->inner, active, target, &dead_input);
panel->inner, active, target, &dead_input);
draw_pop_clip(target); draw_pop_clip(target);

27
4ed.h
View File

@ -23,35 +23,24 @@ struct Application_Memory{
i32 user_memory_size; i32 user_memory_size;
}; };
#define KEY_INPUT_BUFFER_SIZE 4 #define KEY_INPUT_BUFFER_SIZE 8
#define KEY_INPUT_BUFFER_DSIZE (KEY_INPUT_BUFFER_SIZE << 1) #define KEY_EXTRA_SIZE 2
struct Key_Input_Data{ struct Key_Input_Data{
Key_Event_Data press[KEY_INPUT_BUFFER_SIZE]; Key_Event_Data keys[KEY_INPUT_BUFFER_SIZE + KEY_EXTRA_SIZE];
Key_Event_Data hold[KEY_INPUT_BUFFER_SIZE]; i32 count;
i32 press_count;
i32 hold_count;
// TODO(allen): determine if we still need this.
char modifiers[MDFR_INDEX_COUNT];
}; };
static Key_Input_Data null_key_input_data = {0}; static Key_Input_Data null_key_input_data = {0};
struct Key_Summary{
i32 count;
Key_Event_Data keys[KEY_INPUT_BUFFER_DSIZE + 2];
};
inline Key_Event_Data inline Key_Event_Data
get_single_key(Key_Summary *summary, i32 index){ get_single_key(Key_Input_Data *data, i32 index){
Key_Event_Data key; Key_Event_Data key = data->keys[index];
key = summary->keys[index]; return(key);
return key;
} }
typedef struct Input_Summary{ typedef struct Input_Summary{
Mouse_State mouse; Mouse_State mouse;
Key_Summary keys; Key_Input_Data keys;
f32 dt; f32 dt;
} Input_Summary; } Input_Summary;

View File

@ -187,8 +187,7 @@ 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) 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, otherwise the command will still work but if there is a buffer capturing the output it will not automatically be displayed.) 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. 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. The command will cause a crash if no file is specified.)
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, 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(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, The command parameter specifies the command that shall be executed. The string need not be null terminated.)
@ -1636,9 +1635,6 @@ DOC_SEE(Full_Cursor)
if (vptr){ if (vptr){
file = vptr->file_data.file; file = vptr->file_data.file;
if (file && !file->is_loading){ if (file && !file->is_loading){
if (seek.type == buffer_seek_line_char && seek.character <= 0){
seek.character = 1;
}
result = true; result = true;
*cursor_out = view_compute_cursor(vptr, seek, 0); *cursor_out = view_compute_cursor(vptr, seek, 0);
fill_view_summary(view, vptr, cmd); fill_view_summary(view, vptr, cmd);
@ -1673,9 +1669,6 @@ DOC_SEE(Buffer_Seek)
Assert(file); Assert(file);
if (!file->is_loading){ if (!file->is_loading){
result = true; result = true;
if (seek.type == buffer_seek_line_char && seek.character <= 0){
seek.character = 1;
}
Full_Cursor cursor = view_compute_cursor(vptr, seek, 0); Full_Cursor cursor = view_compute_cursor(vptr, seek, 0);
view_set_cursor(vptr, cursor, set_preferred_x, file->settings.unwrapped_lines); view_set_cursor(vptr, cursor, set_preferred_x, file->settings.unwrapped_lines);
fill_view_summary(view, vptr, cmd); fill_view_summary(view, vptr, cmd);
@ -1726,12 +1719,13 @@ DOC_SEE(Buffer_Seek)
if (vptr){ if (vptr){
file = vptr->file_data.file; file = vptr->file_data.file;
if (file && !file->is_loading){ if (file && !file->is_loading){
result = true;
if (seek.type != buffer_seek_pos){ if (seek.type != buffer_seek_pos){
result = true;
cursor = view_compute_cursor(vptr, seek, 0); cursor = view_compute_cursor(vptr, seek, 0);
vptr->edit_pos->mark = cursor.pos; vptr->edit_pos->mark = cursor.pos;
} }
else{ else{
result = true;
vptr->edit_pos->mark = seek.pos; vptr->edit_pos->mark = seek.pos;
} }
fill_view_summary(view, vptr, cmd); fill_view_summary(view, vptr, cmd);

View File

@ -853,7 +853,7 @@ file_grow_starts_as_needed(General_Memory *general, Gap_Buffer *buffer, i32 addi
i32 target_lines = count + additional_lines; i32 target_lines = count + additional_lines;
if (target_lines > max || max == 0){ if (target_lines > max || max == 0){
max = l_round_up(target_lines + max, KB(1)); max = l_round_up_i32(target_lines + max, KB(1));
i32 *new_lines = (i32*)general_memory_reallocate(general, buffer->line_starts, sizeof(i32)*count, sizeof(f32)*max); i32 *new_lines = (i32*)general_memory_reallocate(general, buffer->line_starts, sizeof(i32)*count, sizeof(f32)*max);
@ -1904,7 +1904,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
Gap_Buffer_Init init = buffer_begin_init(&file->state.buffer, val.str, val.size); Gap_Buffer_Init init = buffer_begin_init(&file->state.buffer, val.str, val.size);
for (; buffer_init_need_more(&init); ){ for (; buffer_init_need_more(&init); ){
i32 page_size = buffer_init_page_size(&init); i32 page_size = buffer_init_page_size(&init);
page_size = l_round_up(page_size, KB(4)); page_size = l_round_up_i32(page_size, KB(4));
if (page_size < KB(4)){ if (page_size < KB(4)){
page_size = KB(4); page_size = KB(4);
} }
@ -2080,7 +2080,7 @@ Job_Callback_Sig(job_full_lex){
} }
} while (still_lexing); } while (still_lexing);
i32 new_max = l_round_up(tokens.count+1, KB(1)); i32 new_max = l_round_up_i32(tokens.count+1, KB(1));
system->acquire_lock(FRAME_LOCK); system->acquire_lock(FRAME_LOCK);
{ {
@ -2207,7 +2207,7 @@ file_first_lex_serial(Mem_Options *mem, Editing_File *file){
} }
} while (still_lexing); } while (still_lexing);
i32 new_max = l_round_up(tokens.count+1, KB(1)); i32 new_max = l_round_up_i32(tokens.count+1, KB(1));
{ {
Assert(file->state.swap_array.tokens == 0); Assert(file->state.swap_array.tokens == 0);
@ -2321,7 +2321,7 @@ file_relex_parallel(System_Functions *system, Mem_Options *mem, Editing_File *fi
if (inline_lex){ if (inline_lex){
i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array); i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array);
if (new_count > array->max_count){ if (new_count > array->max_count){
i32 new_max = l_round_up(new_count, KB(1)); i32 new_max = l_round_up_i32(new_count, KB(1));
array->tokens = (Cpp_Token*) array->tokens = (Cpp_Token*)
general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token)); general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token));
array->max_count = new_max; array->max_count = new_max;
@ -2436,7 +2436,7 @@ file_relex_serial(Mem_Options *mem, Editing_File *file, i32 start_i, i32 end_i,
i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array); i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array);
if (new_count > array->max_count){ if (new_count > array->max_count){
i32 new_max = l_round_up(new_count, KB(1)); i32 new_max = l_round_up_i32(new_count, KB(1));
array->tokens = (Cpp_Token*)general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token)); array->tokens = (Cpp_Token*)general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token));
array->max_count = new_max; array->max_count = new_max;
} }
@ -2766,6 +2766,22 @@ view_cursor_move(View *view, i32 line, i32 character){
view_cursor_move(view, cursor); view_cursor_move(view, cursor);
} }
inline void
view_show_file(View *view){
Editing_File *file = view->file_data.file;
if (file){
view->map = get_map(view->persistent.models, file->settings.base_map_id);
}
else{
view->map = get_map(view->persistent.models, mapid_global);
}
if (view->showing_ui != VUI_None){
view->showing_ui = VUI_None;
view->changed_context_in_step = 1;
}
}
internal void internal void
view_set_file(View *view, Editing_File *file, Models *models){ view_set_file(View *view, Editing_File *file, Models *models){
Assert(file); Assert(file);
@ -2792,6 +2808,10 @@ view_set_file(View *view, Editing_File *file, Models *models){
if (edit_pos->cursor.line == 0){ if (edit_pos->cursor.line == 0){
view_cursor_move(view, 0); view_cursor_move(view, 0);
} }
if (view->showing_ui == VUI_None){
view_show_file(view);
}
} }
struct Relative_Scrolling{ struct Relative_Scrolling{
@ -3714,22 +3734,6 @@ view_show_theme(View *view){
view->changed_context_in_step = 1; view->changed_context_in_step = 1;
} }
inline void
view_show_file(View *view){
Editing_File *file = view->file_data.file;
if (file){
view->map = get_map(view->persistent.models, file->settings.base_map_id);
}
else{
view->map = get_map(view->persistent.models, mapid_global);
}
if (view->showing_ui != VUI_None){
view->showing_ui = VUI_None;
view->changed_context_in_step = 1;
}
}
internal String internal String
make_string_terminated(Partition *part, char *str, i32 len){ make_string_terminated(Partition *part, char *str, i32 len){
char *space = (char*)push_array(part, char, len + 1); char *space = (char*)push_array(part, char, len + 1);
@ -4600,7 +4604,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
View_Step_Result result = {0}; View_Step_Result result = {0};
GUI_Target *target = &view->gui_target; GUI_Target *target = &view->gui_target;
Models *models = view->persistent.models; Models *models = view->persistent.models;
Key_Summary keys = input.keys; Key_Input_Data keys = input.keys;
b32 show_scrollbar = !view->hide_scrollbar; b32 show_scrollbar = !view->hide_scrollbar;
@ -5754,23 +5758,19 @@ do_step_file_view(System_Functions *system,
} }
{ {
Key_Event_Data key; Key_Input_Data *keys = &user_input->keys;
Key_Summary *keys = &user_input->keys;
void *ptr = (b + 1); void *ptr = (b + 1);
String string; String string = gui_read_string(&ptr);
char activation_key; AllowLocal(string);
i32 i, count; char activation_key = *(char*)ptr;
string = gui_read_string(&ptr);
activation_key = *(char*)ptr;
activation_key = char_to_upper(activation_key); activation_key = char_to_upper(activation_key);
if (activation_key != 0){ if (activation_key != 0){
count = keys->count; i32 count = keys->count;
for (i = 0; i < count; ++i){ for (i32 i = 0; i < count; ++i){
key = get_single_key(keys, i); Key_Event_Data key = get_single_key(keys, i);
if (char_to_upper(key.character) == activation_key){ if (char_to_upper(key.character) == activation_key){
target->active = b->id; target->active = b->id;
result.is_animating = 1; result.is_animating = 1;

View File

@ -1254,9 +1254,7 @@ gui_do_jump(GUI_Target *target, GUI_View_Jump jump, GUI_Scroll_Vars vars){
} }
internal void internal void
gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect scroll_region, gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect scroll_region, Key_Input_Data *keys, i32 *list_i, GUI_Item_Update *update, i16 user_up_key, i16 user_down_key){
Key_Summary *keys, i32 *list_i, GUI_Item_Update *update,
i16 user_up_key, i16 user_down_key){
if (update->has_adjustment){ if (update->has_adjustment){
*list_i = update->adjustment_value; *list_i = update->adjustment_value;

View File

@ -277,29 +277,25 @@ layout_get_rect(Editing_Layout *layout, i32 id, i32 which_child){
internal i32_Rect internal i32_Rect
layout_get_panel_rect(Editing_Layout *layout, Panel *panel){ layout_get_panel_rect(Editing_Layout *layout, Panel *panel){
Assert(layout->panel_count > 1); Assert(layout->panel_count > 1);
i32_Rect r = layout_get_rect(layout, panel->parent, panel->which_child); i32_Rect r = layout_get_rect(layout, panel->parent, panel->which_child);
return(r); return(r);
} }
internal void internal void
layout_fix_all_panels(Editing_Layout *layout){ layout_fix_all_panels(Editing_Layout *layout){
Panel *panel;
Panel_Divider *dividers = layout->dividers; AllowLocal(dividers); Panel_Divider *dividers = layout->dividers; AllowLocal(dividers);
i32 panel_count = layout->panel_count; i32 panel_count = layout->panel_count;
if (panel_count > 1){ if (panel_count > 1){
for (panel = layout->used_sentinel.next; for (Panel *panel = layout->used_sentinel.next;
panel != &layout->used_sentinel; panel != &layout->used_sentinel;
panel = panel->next){ panel = panel->next){
panel->full = layout_get_panel_rect(layout, panel); panel->full = layout_get_panel_rect(layout, panel);
panel_fix_internal_area(panel); panel_fix_internal_area(panel);
} }
} }
else{ else{
panel = layout->used_sentinel.next; Panel *panel = layout->used_sentinel.next;
panel->full.x0 = 0; panel->full.x0 = 0;
panel->full.y0 = 0; panel->full.y0 = 0;
panel->full.x1 = layout->full_width; panel->full.x1 = layout->full_width;
@ -316,10 +312,8 @@ layout_refit(Editing_Layout *layout, i32 prev_width, i32 prev_height){
i32 max = layout->panel_max_count - 1; i32 max = layout->panel_max_count - 1;
Panel_Divider *divider = dividers; Panel_Divider *divider = dividers;
if (layout->panel_count > 1){ if (layout->panel_count > 1){
Assert(prev_width != 0 && prev_height != 0); Assert(prev_width != 0 && prev_height != 0);
for (i32 i = 0; i < max; ++i, ++divider){ for (i32 i = 0; i < max; ++i, ++divider){
if (divider->v_divider){ if (divider->v_divider){
divider->pos = divider->pos; divider->pos = divider->pos;
@ -373,8 +367,8 @@ layout_compute_position(Editing_Layout *layout, Panel_Divider *divider, i32 pos)
internal void internal void
layout_compute_abs_step(Editing_Layout *layout, i32 divider_id, i32_Rect rect, i32 *abs_pos){ layout_compute_abs_step(Editing_Layout *layout, i32 divider_id, i32_Rect rect, i32 *abs_pos){
Panel_Divider *div = layout->dividers + divider_id; Panel_Divider *div = layout->dividers + divider_id;
i32 p0 = 0, p1 = 0;
i32 p0 = 0, p1 = 0;
if (div->v_divider){ if (div->v_divider){
p0 = rect.x0; p1 = rect.x1; p0 = rect.x0; p1 = rect.x1;
} }
@ -405,11 +399,7 @@ layout_compute_abs_step(Editing_Layout *layout, i32 divider_id, i32_Rect rect, i
internal void internal void
layout_compute_absolute_positions(Editing_Layout *layout, i32 *abs_pos){ layout_compute_absolute_positions(Editing_Layout *layout, i32 *abs_pos){
i32_Rect r; i32_Rect r = i32R(0, 0, layout->full_width, layout->full_height);
r.x0 = 0;
r.y0 = 0;
r.x1 = layout->full_width;
r.y1 = layout->full_height;
if (layout->panel_count > 1){ if (layout->panel_count > 1){
layout_compute_abs_step(layout, layout->root, r, abs_pos); layout_compute_abs_step(layout, layout->root, r, abs_pos);
} }
@ -434,14 +424,12 @@ layout_get_min_max_step_up(Editing_Layout *layout, b32 v, i32 divider_id, i32 wh
} }
if (divider->parent != -1){ if (divider->parent != -1){
layout_get_min_max_step_up(layout, v, divider->parent, divider->which_child, layout_get_min_max_step_up(layout, v, divider->parent, divider->which_child, abs_pos, min_out, max_out);
abs_pos, min_out, max_out);
} }
} }
internal void internal void
layout_get_min_max_step_down(Editing_Layout *layout, b32 v, i32 divider_id, i32 which_child, layout_get_min_max_step_down(Editing_Layout *layout, b32 v, i32 divider_id, i32 which_child, i32 *abs_pos, i32 *min_out, i32 *max_out){
i32 *abs_pos, i32 *min_out, i32 *max_out){
Panel_Divider *divider = layout->dividers + divider_id; Panel_Divider *divider = layout->dividers + divider_id;
// NOTE(allen): The min/max is switched here, because children on the -1 side // NOTE(allen): The min/max is switched here, because children on the -1 side
@ -504,8 +492,8 @@ layout_get_min_max(Editing_Layout *layout, Panel_Divider *divider, i32 *abs_pos,
internal void internal void
layout_update_pos_step(Editing_Layout *layout, i32 divider_id, i32_Rect rect, i32 *abs_pos){ layout_update_pos_step(Editing_Layout *layout, i32 divider_id, i32_Rect rect, i32 *abs_pos){
Panel_Divider *div = layout->dividers + divider_id; Panel_Divider *div = layout->dividers + divider_id;
i32 p0 = 0, p1 = 0;
i32 p0 = 0, p1 = 0;
if (div->v_divider){ if (div->v_divider){
p0 = rect.x0; p1 = rect.x1; p0 = rect.x0; p1 = rect.x1;
} }
@ -516,6 +504,7 @@ layout_update_pos_step(Editing_Layout *layout, i32 divider_id, i32_Rect rect, i3
i32 pos = abs_pos[divider_id]; i32 pos = abs_pos[divider_id];
i32_Rect r1 = rect, r2 = rect; i32_Rect r1 = rect, r2 = rect;
f32 lpos = unlerp((f32)p0, (f32)pos, (f32)p1); f32 lpos = unlerp((f32)p0, (f32)pos, (f32)p1);
lpos = clamp(0.f, lpos, 1.f);
div->pos = lpos; div->pos = lpos;
@ -539,11 +528,7 @@ layout_update_pos_step(Editing_Layout *layout, i32 divider_id, i32_Rect rect, i3
internal void internal void
layout_update_all_positions(Editing_Layout *layout, i32 *abs_pos){ layout_update_all_positions(Editing_Layout *layout, i32 *abs_pos){
i32_Rect r; i32_Rect r = i32R(0, 0, layout->full_width, layout->full_height);
r.x0 = 0;
r.y0 = 0;
r.x1 = layout->full_width;
r.y1 = layout->full_height;
if (layout->panel_count > 1){ if (layout->panel_count > 1){
layout_update_pos_step(layout, layout->root, r, abs_pos); layout_update_pos_step(layout, layout->root, r, abs_pos);
} }

View File

@ -647,13 +647,28 @@ hit_check(int32_t x, int32_t y, i32_Rect rect){
} }
inline i32_Rect inline i32_Rect
get_inner_rect(i32_Rect outer, int32_t margin){ get_inner_rect(i32_Rect outer, i32 margin){
i32_Rect r; i32_Rect r;
r.x0 = outer.x0 + margin; r.x0 = outer.x0 + margin;
r.y0 = outer.y0 + margin; r.y0 = outer.y0 + margin;
r.x1 = outer.x1 - margin; r.x1 = outer.x1 - margin;
r.y1 = outer.y1 - margin; r.y1 = outer.y1 - margin;
return r; return(r);
}
inline f32_Rect
get_inner_rect(f32_Rect outer, f32 margin){
f32_Rect r;
r.x0 = outer.x0 + margin;
r.y0 = outer.y0 + margin;
r.x1 = outer.x1 - margin;
r.y1 = outer.y1 - margin;
return(r);
}
inline int32_t
fits_inside(i32_Rect rect, i32_Rect outer){
return(rect.x0 >= outer.x0 && rect.x1 <= outer.x1 && rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
} }
// BOTTOM // BOTTOM

View File

@ -151,6 +151,7 @@ struct Render_Target{
void *context; void *context;
i32_Rect clip_boxes[5]; i32_Rect clip_boxes[5];
i32 clip_top; i32 clip_top;
b32 clip_all;
i32 width, height; i32 width, height;
i32 bound_texture; i32 bound_texture;
u32 color; u32 color;
@ -166,8 +167,6 @@ struct Render_Target{
Draw_Push_Clip *push_clip; Draw_Push_Clip *push_clip;
Draw_Pop_Clip *pop_clip; Draw_Pop_Clip *pop_clip;
Draw_Push_Piece *push_piece; Draw_Push_Piece *push_piece;
//i32 dpi;
}; };
#define DpiMultiplier(n,dpi) ((n) * (dpi) / 96) #define DpiMultiplier(n,dpi) ((n) * (dpi) / 96)

View File

@ -9,20 +9,6 @@
// TOP // TOP
#if 0
inline i32_Rect
i32_rect_zero(){
i32_Rect rect={0};
return(rect);
}
inline f32_Rect
f32_rect_zero(){
f32_Rect rect={0};
return(rect);
}
#endif
inline void inline void
draw_push_clip(Render_Target *target, i32_Rect clip_box){ draw_push_clip(Render_Target *target, i32_Rect clip_box){
target->push_clip(target, clip_box); target->push_clip(target, clip_box);

Binary file not shown.

View File

@ -266,6 +266,7 @@ draw_safe_push(Render_Target *target, i32 size, void *x){
internal void internal void
draw_push_piece(Render_Target *target, Render_Piece_Combined piece){ draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
if (!target->clip_all){
PutStruct(Render_Piece_Header, piece.header); PutStruct(Render_Piece_Header, piece.header);
switch (piece.header.type){ switch (piece.header.type){
@ -290,9 +291,11 @@ draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
Assert(target->size <= target->max); Assert(target->size <= target->max);
} }
}
internal void internal void
draw_push_piece_clip(Render_Target *target, i32_Rect clip_box){ draw_push_piece_clip(Render_Target *target, i32_Rect clip_box){
if (!target->clip_all){
// TODO(allen): optimize out if there are two clip box changes in a row // TODO(allen): optimize out if there are two clip box changes in a row
Render_Piece_Change_Clip clip; Render_Piece_Change_Clip clip;
Render_Piece_Header header; Render_Piece_Header header;
@ -303,32 +306,26 @@ draw_push_piece_clip(Render_Target *target, i32_Rect clip_box){
PutStruct(Render_Piece_Header, header); PutStruct(Render_Piece_Header, header);
PutStruct(Render_Piece_Change_Clip, clip); PutStruct(Render_Piece_Change_Clip, clip);
} }
inline int32_t
fits_inside(i32_Rect rect, i32_Rect outer){
return (rect.x0 >= outer.x0 && rect.x1 <= outer.x1 &&
rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
} }
internal void internal void
draw_push_clip(Render_Target *target, i32_Rect clip_box){ draw_push_clip(Render_Target *target, i32_Rect clip_box){
Assert(target->clip_top == -1 || Assert(target->clip_top == -1 || fits_inside(clip_box, target->clip_boxes[target->clip_top]));
fits_inside(clip_box, target->clip_boxes[target->clip_top]));
Assert(target->clip_top+1 < ArrayCount(target->clip_boxes)); Assert(target->clip_top+1 < ArrayCount(target->clip_boxes));
target->clip_boxes[++target->clip_top] = clip_box; target->clip_boxes[++target->clip_top] = clip_box;
target->clip_all = (clip_box.x0 >= clip_box.x1 || clip_box.y0 >= clip_box.y1);
draw_push_piece_clip(target, clip_box); draw_push_piece_clip(target, clip_box);
} }
internal i32_Rect internal i32_Rect
draw_pop_clip(Render_Target *target){ draw_pop_clip(Render_Target *target){
i32_Rect result = {0};
i32_Rect clip_box = {0};
Assert(target->clip_top > 0); Assert(target->clip_top > 0);
result = target->clip_boxes[target->clip_top]; i32_Rect result = target->clip_boxes[target->clip_top];
--target->clip_top; --target->clip_top;
clip_box = target->clip_boxes[target->clip_top]; i32_Rect clip_box = target->clip_boxes[target->clip_top];
target->clip_all = (clip_box.x0 >= clip_box.x1 || clip_box.y0 >= clip_box.y1);
draw_push_piece_clip(target, clip_box); draw_push_piece_clip(target, clip_box);
return(result); return(result);
@ -352,12 +349,7 @@ private_draw_rectangle(Render_Target *target, f32_Rect rect, u32 color){
inline void inline void
private_draw_rectangle_outline(Render_Target *target, f32_Rect rect, u32 color){ private_draw_rectangle_outline(Render_Target *target, f32_Rect rect, u32 color){
f32_Rect r; f32_Rect r = get_inner_rect(rect, .5f);
r.x0 = rect.x0 + .5f;
r.y0 = rect.y0 + .5f;
r.x1 = rect.x1 - .5f;
r.y1 = rect.y1 - .5f;
draw_set_color(target, color); draw_set_color(target, color);
draw_bind_texture(target, 0); draw_bind_texture(target, 0);
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);

View File

@ -59,17 +59,33 @@ typedef double f64;
#define Max(a,b) (((a)>(b))?(a):(b)) #define Max(a,b) (((a)>(b))?(a):(b))
#define Min(a,b) (((a)<(b))?(a):(b)) #define Min(a,b) (((a)<(b))?(a):(b))
#define ceil32(v) (((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) )) inline i32 ceil32(f32 v){
return(((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) ));
}
#define floor32(v) (((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) )) inline i32 floor32(f32 v){
return(((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) ));
}
#define round32(v) (floor32(v + 0.5f)) inline i32 round32(f32 v){
return(floor32(v + 0.5f));
}
#define trunc32(v) (i32)(v) inline i32 trun32(f32 v){
return((i32)(v));
}
#define div_ceil(n,d) ( ((n) % (d) != 0) + ((n) / (d)) ) inline i32 div_ceil(i32 n, i32 d){
return( ((n) % (d) != 0) + ((n) / (d)) );
}
#define l_round_up(x,b) ( ((x)+(b)-1) - (((x)+(b)-1)%(b)) ) inline i32 l_round_up_i32(i32 x, i32 b){
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
}
inline u32 l_round_up_u32(u32 x, u32 b){
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
}
#define STR__(s) #s #define STR__(s) #s
#define STR_(s) STR__(s) #define STR_(s) STR__(s)

BIN
custom_4coder.dll Normal file

Binary file not shown.

BIN
custom_4coder.pdb Normal file

Binary file not shown.

View File

@ -502,7 +502,7 @@ buffer_replace_range(Gap_Buffer *buffer, i32 start, i32 end, char *str, i32 len,
assert(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max); assert(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max);
} }
else{ else{
*request_amount = l_round_up(2*(*shift_amount + size), 4 << 10); *request_amount = l_round_up_i32(2*(*shift_amount + size), 4 << 10);
result = 1; result = 1;
} }
@ -1235,6 +1235,7 @@ buffer_partial_from_line_character(Gap_Buffer *buffer, i32 line, i32 character){
} }
i32 size = buffer_size(buffer); i32 size = buffer_size(buffer);
i32 this_start = buffer->line_starts[line_index]; i32 this_start = buffer->line_starts[line_index];
i32 max_character = (size-this_start) + 1; i32 max_character = (size-this_start) + 1;
if (line_index+1 < buffer->line_count){ if (line_index+1 < buffer->line_count){
@ -1242,14 +1243,28 @@ buffer_partial_from_line_character(Gap_Buffer *buffer, i32 line, i32 character){
max_character = (next_start-this_start); max_character = (next_start-this_start);
} }
if (character <= 0){ i32 adjusted_pos = 0;
character = 1; if (character > 0){
}
if (character > max_character){ if (character > max_character){
character = max_character; adjusted_pos = max_character - 1;
}
else{
adjusted_pos = character - 1;
}
}
else if (character == 0){
adjusted_pos = 0;
}
else{
if (-character > max_character){
adjusted_pos = 0;
}
else{
adjusted_pos = max_character + character;
}
} }
result.pos = this_start + character - 1; result.pos = this_start + adjusted_pos;
result.line = line_index + 1; result.line = line_index + 1;
result.character = character; result.character = character;

View File

@ -285,7 +285,7 @@ file_compute_cursor_from_line_character(Editing_File *file, i32 line, i32 charac
inline b32 inline b32
file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor *cursor){ file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor *cursor){
b32 result = 1; b32 result = true;
switch (seek.type){ switch (seek.type){
case buffer_seek_pos: case buffer_seek_pos:
{ {
@ -299,7 +299,7 @@ file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor
default: default:
{ {
result = 0; result = false;
}break; }break;
} }
return(result); return(result);

View File

@ -445,6 +445,7 @@ standard_build(char *cdir, u32 flags){
fsm_generator(cdir); fsm_generator(cdir);
metagen(cdir); metagen(cdir);
do_buildsuper(cdir, Custom_Experiments); do_buildsuper(cdir, Custom_Experiments);
//do_buildsuper(cdir, Custom_Casey);
//do_buildsuper(cdir, Custom_ChronalVim); //do_buildsuper(cdir, Custom_ChronalVim);
build_main(cdir, flags); build_main(cdir, flags);
} }

View File

@ -657,11 +657,6 @@ CUSTOM_COMMAND_SIG(casey_save_and_make_without_asking)
save_buffer(app, &buffer, buffer.file_name, buffer.file_name_len, 0); save_buffer(app, &buffer, buffer.file_name, buffer.file_name_len, 0);
} }
// NOTE(allen): The parameter pushing made it a little easier
// to deal with this particular pattern where two similar strings
// were both used. Now both strings need to exist at the same
// time on the users side.
int size = app->memory_size/2; int size = app->memory_size/2;
String dir = make_string(app->memory, 0, size); String dir = make_string(app->memory, 0, size);
String command = make_string((char*)app->memory + size, 0, size); String command = make_string((char*)app->memory + size, 0, size);
@ -683,14 +678,17 @@ CUSTOM_COMMAND_SIG(casey_save_and_make_without_asking)
{ {
unsigned int access = AccessAll; unsigned int access = AccessAll;
View_Summary view = get_active_view(app, access); View_Summary view = get_active_view(app, access);
char *BufferName = GlobalCompilationBufferName;
int BufferNameLength = (int)strlen(GlobalCompilationBufferName);
exec_system_command(app, &view, exec_system_command(app, &view,
buffer_identifier(GlobalCompilationBufferName, (int)strlen(GlobalCompilationBufferName)), buffer_identifier(BufferName, BufferNameLength),
dir.str, dir.size, dir.str, dir.size,
command.str, command.size, command.str, command.size,
CLI_OverlapWithConflict); CLI_OverlapWithConflict);
lock_jump_buffer(BufferName, BufferNameLength);
} }
exec_command(app, change_active_panel);
exec_command(app, change_active_panel);
prev_location = null_location; prev_location = null_location;
} }

View File

@ -1,9 +1,16 @@
/*
4coder_experiments.cpp - Supplies extension bindings to the defaults with experimental new features.
TYPE: 'build-target'
*/
// TOP // TOP
#include "4coder_default_include.cpp" #if !defined(FCODER_EXPERIMENTS_CPP)
#define FCODER_EXPERIMENTS_CPP
#include "4coder_function_list.cpp" #include "4coder_default_include.cpp"
#include "4coder_miblo_numbers.cpp"
#define NO_BINDING #define NO_BINDING
#include "4coder_default_bindings.cpp" #include "4coder_default_bindings.cpp"
@ -12,8 +19,6 @@
# define BIND_4CODER_TESTS(context) ((void)context) # define BIND_4CODER_TESTS(context) ((void)context)
#endif #endif
#include "4coder_miblo_numbers.cpp"
#include <string.h> #include <string.h>
static float static float
@ -108,8 +113,8 @@ multi-cursor showing but it is unclear to me how to do that
conveniently. Since this won't exist inside a coroutine conveniently. Since this won't exist inside a coroutine
what does such an API even look like??? It's clear to me now what does such an API even look like??? It's clear to me now
that I may need to start pushing for the view routine before that I may need to start pushing for the view routine before
I am even able to support the GUI. Because that will the I am even able to support the GUI. Because that will set up the
system up to allow me to think about the problem in more ways. system to allow me to think about the problem in more ways.
Finally I have decided not to pursue this direction any more, Finally I have decided not to pursue this direction any more,
it just seems like the wrong way to do it, so I'll stop without it just seems like the wrong way to do it, so I'll stop without
@ -540,7 +545,7 @@ view_set_to_region(Application_Links *app, View_Summary *view, int32_t major_pos
static float scope_center_threshold = 0.75f; static float scope_center_threshold = 0.75f;
CUSTOM_COMMAND_SIG(highlight_surroundng_scope){ CUSTOM_COMMAND_SIG(highlight_surrounding_scope){
uint32_t access = AccessProtected; uint32_t access = AccessProtected;
View_Summary view = get_active_view(app, access); View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access); Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
@ -714,6 +719,334 @@ CUSTOM_COMMAND_SIG(place_in_scope){
} }
} }
CUSTOM_COMMAND_SIG(delete_current_scope){
uint32_t access = AccessOpen;
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
int32_t top = view.cursor.pos;
int32_t bottom = view.mark.pos;
if (top > bottom){
int32_t x = top;
top = bottom;
bottom = x;
}
if (buffer_get_char(app, &buffer, top) == '{' && buffer_get_char(app, &buffer, bottom-1) == '}'){
int32_t top_len = 1;
int32_t bottom_len = 1;
if (buffer_get_char(app, &buffer, top-1) == '\n'){
top_len = 2;
}
if (buffer_get_char(app, &buffer, bottom+1) == '\n'){
bottom_len = 2;
}
Buffer_Edit edits[2];
edits[0].str_start = 0;
edits[0].len = 0;
edits[0].start = top+1 - top_len;
edits[0].end = top+1;
edits[1].str_start = 0;
edits[1].len = 0;
edits[1].start = bottom-1;
edits[1].end = bottom-1 + bottom_len;
buffer_batch_edit(app, &buffer, 0, 0, edits, 2, BatchEdit_Normal);
}
}
struct Statement_Parser{
Stream_Tokens stream;
int32_t token_index;
Buffer_Summary *buffer;
};
static Cpp_Token*
parser_next_token(Statement_Parser *parser){
Cpp_Token *result = 0;
bool32 still_looping = true;
while (parser->token_index >= parser->stream.end && still_looping){
still_looping = forward_stream_tokens(&parser->stream);
}
if (parser->token_index < parser->stream.end){
result = &parser->stream.tokens[parser->token_index];
++parser->token_index;
}
return(result);
}
static bool32 parse_statement_down(Application_Links *app, Statement_Parser *parser, Cpp_Token *token_out);
static bool32
parse_for_down(Application_Links *app, Statement_Parser *parser, Cpp_Token *token_out){
bool32 success = false;
Cpp_Token *token = parser_next_token(parser);
int32_t paren_level = 0;
while (token != 0){
if (!(token->flags & CPP_TFLAG_PP_BODY)){
switch (token->type){
case CPP_TOKEN_PARENTHESE_OPEN:
{
++paren_level;
}break;
case CPP_TOKEN_PARENTHESE_CLOSE:
{
--paren_level;
if (paren_level == 0){
success = parse_statement_down(app, parser, token_out);
goto finished;
}
else if (paren_level < 0){
success = false;
goto finished;
}
}break;
}
}
token = parser_next_token(parser);
}
finished:;
return(success);
}
static bool32
parse_if_down(Application_Links *app, Statement_Parser *parser, Cpp_Token *token_out){
bool32 success = false;
Cpp_Token *token = parser_next_token(parser);
if (token != 0){
success = parse_statement_down(app, parser, token_out);
if (success){
token = parser_next_token(parser);
if (token != 0 && token->type == CPP_TOKEN_KEY_CONTROL_FLOW){
char lexeme[32];
if (sizeof(lexeme)-1 >= token->size){
if (buffer_read_range(app, parser->buffer, token->start, token->start + token->size, lexeme)){
lexeme[token->size] = 0;
if (match(lexeme, "else")){
success = parse_statement_down(app, parser, token_out);
}
}
}
}
}
}
return(success);
}
static bool32
parse_block_down(Application_Links *app, Statement_Parser *parser, Cpp_Token *token_out){
bool32 success = false;
Cpp_Token *token = parser_next_token(parser);
int32_t nest_level = 0;
while (token != 0){
switch (token->type){
case CPP_TOKEN_BRACE_OPEN:
{
++nest_level;
}break;
case CPP_TOKEN_BRACE_CLOSE:
{
if (nest_level == 0){
*token_out = *token;
success = true;
goto finished;
}
--nest_level;
}break;
}
token = parser_next_token(parser);
}
finished:;
return(success);
}
static bool32
parse_statement_down(Application_Links *app, Statement_Parser *parser, Cpp_Token *token_out){
bool32 success = false;
Cpp_Token *token = parser_next_token(parser);
if (token != 0){
bool32 not_getting_block = false;
do{
switch (token->type){
case CPP_TOKEN_BRACE_CLOSE:
{
goto finished;
}break;
case CPP_TOKEN_KEY_CONTROL_FLOW:
{
char lexeme[32];
if (sizeof(lexeme)-1 >= token->size){
if (buffer_read_range(app, parser->buffer, token->start, token->start + token->size, lexeme)){
lexeme[token->size] = 0;
if (match(lexeme, "for")){
success = parse_for_down(app, parser, token_out);
goto finished;
}
else if (match(lexeme, "if")){
success = parse_if_down(app, parser, token_out);
goto finished;
}
else if (match(lexeme, "else")){
success = false;
goto finished;
}
}
}
}break;
case CPP_TOKEN_BRACE_OPEN:
{
if (!not_getting_block){
success = parse_block_down(app, parser, token_out);
goto finished;
}
}break;
case CPP_TOKEN_SEMICOLON:
{
success = true;
*token_out = *token;
goto finished;
}break;
case CPP_TOKEN_EQ:
{
not_getting_block = true;
}break;
}
token = parser_next_token(parser);
}while(token != 0);
}
finished:;
return(success);
}
static bool32
find_whole_statement_down(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t *start_out, int32_t *end_out){
bool32 result = false;
int32_t start = pos;
int32_t end = start;
Cpp_Get_Token_Result get_result = {0};
if (buffer_get_token_index(app, buffer, pos, &get_result)){
Statement_Parser parser = {0};
parser.token_index = get_result.token_index;
if (parser.token_index < 0){
parser.token_index = 0;
}
if (get_result.in_whitespace){
parser.token_index += 1;
}
static const int32_t chunk_cap = 512;
Cpp_Token chunk[chunk_cap];
if (init_stream_tokens(&parser.stream, app, buffer, parser.token_index, chunk, chunk_cap)){
parser.buffer = buffer;
Cpp_Token end_token = {0};
if (parse_statement_down(app, &parser, &end_token)){
end = end_token.start + end_token.size;
result = true;
}
}
}
*start_out = start;
*end_out = end;
return(result);
}
CUSTOM_COMMAND_SIG(scope_absorb_down){
uint32_t access = AccessOpen;
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
int32_t top = view.cursor.pos;
int32_t bottom = view.mark.pos;
if (top > bottom){
int32_t x = top;
top = bottom;
bottom = x;
}
Partition *part = &global_part;
Temp_Memory temp = begin_temp_memory(part);
if (buffer_get_char(app, &buffer, top) == '{' && buffer_get_char(app, &buffer, bottom-1) == '}'){
Range range;
if (find_whole_statement_down(app, &buffer, bottom, &range.start, &range.end)){
char *string_space = push_array(part, char, range.end - range.start);
buffer_read_range(app, &buffer, range.start, range.end, string_space);
String string = make_string(string_space, range.end - range.start);
string = skip_chop_whitespace(string);
int32_t newline_count = 0;
for (char *ptr = string_space; ptr < string.str; ++ptr){
if (*ptr == '\n'){
++newline_count;
}
}
bool32 extra_newline = false;
if (newline_count >= 2){
extra_newline = true;
}
int32_t edit_len = string.size + 1;
if (extra_newline){
edit_len += 1;
}
char *edit_str = push_array(part, char, edit_len);
if (extra_newline){
edit_str[0] = '\n';
copy_fast_unsafe(edit_str+1, string);
edit_str[edit_len-1] = '\n';
}
else{
copy_fast_unsafe(edit_str, string);
edit_str[edit_len-1] = '\n';
}
Buffer_Edit edits[2];
edits[0].str_start = 0;
edits[0].len = edit_len;
edits[0].start = bottom-1;
edits[0].end = bottom-1;
edits[1].str_start = 0;
edits[1].len = 0;
edits[1].start = range.start;
edits[1].end = range.end;
buffer_batch_edit(app, &buffer, edit_str, edit_len, edits, 2, BatchEdit_Normal);
}
}
end_temp_memory(temp);
}
// NOTE(allen): Some basic code manipulation ideas. // NOTE(allen): Some basic code manipulation ideas.
CUSTOM_COMMAND_SIG(rename_parameter){ CUSTOM_COMMAND_SIG(rename_parameter){
@ -890,17 +1223,17 @@ CUSTOM_COMMAND_SIG(write_explicit_enum_values){
++token_index; ++token_index;
int32_t closed_correctly = 0;
int32_t seeker_index = token_index; int32_t seeker_index = token_index;
Stream_Tokens seek_stream = begin_temp_stream_token(&stream); Stream_Tokens seek_stream = begin_temp_stream_token(&stream);
int32_t still_looping = 0; bool32 closed_correctly = false;
bool32 still_looping = false;
do{ do{
for (; seeker_index < stream.end; ++seeker_index){ for (; seeker_index < stream.end; ++seeker_index){
Cpp_Token *token_seeker = stream.tokens + seeker_index; Cpp_Token *token_seeker = stream.tokens + seeker_index;
switch (token_seeker->type){ switch (token_seeker->type){
case CPP_TOKEN_BRACE_CLOSE: case CPP_TOKEN_BRACE_CLOSE:
closed_correctly = 1; closed_correctly = true;
goto finished_seek; goto finished_seek;
case CPP_TOKEN_BRACE_OPEN: case CPP_TOKEN_BRACE_OPEN:
@ -915,15 +1248,15 @@ CUSTOM_COMMAND_SIG(write_explicit_enum_values){
if (closed_correctly){ if (closed_correctly){
int32_t count_estimate = 1 + (seeker_index - token_index)/2; int32_t count_estimate = 1 + (seeker_index - token_index)/2;
Buffer_Edit *edits = push_array(part, Buffer_Edit, count_estimate);
int32_t edit_count = 0; int32_t edit_count = 0;
Buffer_Edit *edits = push_array(part, Buffer_Edit, count_estimate);
char *string_base = (char*)partition_current(part); char *string_base = (char*)partition_current(part);
String string = make_string(string_base, 0, partition_remaining(part)); String string = make_string(string_base, 0, partition_remaining(part));
closed_correctly = false;
still_looping = false;
int32_t value = 0; int32_t value = 0;
closed_correctly = 0;
still_looping = 0;
do{ do{
for (;token_index < stream.end; ++token_index){ for (;token_index < stream.end; ++token_index){
Cpp_Token *token_ptr = stream.tokens + token_index; Cpp_Token *token_ptr = stream.tokens + token_index;
@ -1016,12 +1349,12 @@ get_bindings(void *data, int32_t size){
Bind_Helper context_ = begin_bind_helper(data, size); Bind_Helper context_ = begin_bind_helper(data, size);
Bind_Helper *context = &context_; Bind_Helper *context = &context_;
set_hook(context, hook_start, my_start); set_hook(context, hook_start, default_start);
set_hook(context, hook_view_size_change, my_view_adjust); set_hook(context, hook_view_size_change, default_view_adjust);
set_open_file_hook(context, my_file_settings); set_open_file_hook(context, default_file_settings);
set_save_file_hook(context, my_file_save); set_save_file_hook(context, default_file_save);
set_input_filter(context, my_suppress_mouse_filter); set_input_filter(context, default_suppress_mouse_filter);
set_command_caller(context, default_command_caller); set_command_caller(context, default_command_caller);
set_scroll_rule(context, smooth_scroll_rule); set_scroll_rule(context, smooth_scroll_rule);
@ -1048,14 +1381,17 @@ get_bindings(void *data, int32_t size){
end_map(context); end_map(context);
begin_map(context, my_code_map); begin_map(context, default_code_map);
bind(context, '[', MDFR_ALT, highlight_surroundng_scope); bind(context, '[', MDFR_ALT, highlight_surrounding_scope);
bind(context, ']', MDFR_ALT, highlight_prev_scope_absolute); bind(context, ']', MDFR_ALT, highlight_prev_scope_absolute);
bind(context, '\'', MDFR_ALT, highlight_next_scope_absolute); bind(context, '\'', MDFR_ALT, highlight_next_scope_absolute);
bind(context, '/', MDFR_ALT, place_in_scope);
bind(context, '-', MDFR_ALT, delete_current_scope);
bind(context, 'j', MDFR_ALT, scope_absorb_down);
bind(context, key_insert, MDFR_CTRL, write_explicit_enum_values); bind(context, key_insert, MDFR_CTRL, write_explicit_enum_values);
bind(context, 'p', MDFR_ALT, rename_parameter); bind(context, 'p', MDFR_ALT, rename_parameter);
bind(context, 'I', MDFR_CTRL, list_all_functions_current_buffer);
end_map(context); end_map(context);
BIND_4CODER_TESTS(context); BIND_4CODER_TESTS(context);
@ -1064,5 +1400,7 @@ get_bindings(void *data, int32_t size){
return(result); return(result);
} }
#endif
// BOTTOM // BOTTOM

View File

@ -1,8 +1,18 @@
/*
4coder_miblo_numbers.cpp - Commands for so called "Miblo Number Operations" which involve incrementing
and decrementing various forms of number as numerical objects despite being encoded as text objects.
#if !defined(MIBLO_NUMBERS_4CODER) TYPE: 'drop-in-command-pack'
#define MIBLO_NUMBERS_4CODER */
// TODO(allen): thevaber number converter idea // TOP
#if !defined(FCODER_MIBLO_NUMBERS_CPP)
#define FCODER_MIBLO_NUMBERS_CPP
#include "4coder_API/custom.h"
#include "4coder_helper/4coder_helper.h"
#include "4coder_helper/4coder_streaming.h"
static int32_t static int32_t
get_numeric_string_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, int32_t *numeric_start, int32_t *numeric_end){ get_numeric_string_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, int32_t *numeric_start, int32_t *numeric_end){
@ -378,4 +388,4 @@ CUSTOM_COMMAND_SIG(miblo_decrement_time_stamp_minute){
#endif #endif
// BOTTOM

View File

@ -3,33 +3,14 @@ extensions=".c.cpp.h.hpp.bat.sh";
fkey_command_win[1] = {"build.bat", "*compilation*", true}; fkey_command_win[1] = {"build.bat", "*compilation*", true};
fkey_command_win[2] = {"site\\build.bat", "*compilation*", true}; fkey_command_win[2] = {"site\\build.bat", "*compilation*", true};
fkey_command_win[3] = {"string\\build.bat", "*compilation*", true}; fkey_command_win[3] = {"string\\build.bat", "*compilation*", true};
fkey_command_win[4] = {0, 0};
fkey_command_win[5] = {"..\\misc\\run.bat", "*run*"}; fkey_command_win[5] = {"..\\misc\\run.bat", "*run*"};
fkey_command_win[6] = {0, 0};
fkey_command_win[7] = {0, 0}; fkey_command_win[12] = {"package.bat", "*package*"};
fkey_command_win[8] = {0, 0};
fkey_command_win[9] = {0, 0};
fkey_command_win[10] = {0, 0};
fkey_command_win[11] = {0, 0};
fkey_command_win[8] = {"package.bat", "*package*"};
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] = {"./build.sh", "*compilation*", true}; fkey_command_linux[1] = {"./build.sh", "*compilation*", true};
fkey_command_linux[2] = {"site/build.sh", "*compilation*", true}; fkey_command_linux[2] = {"site/build.sh", "*compilation*", true};
fkey_command_linux[3] = {0, 0};
fkey_command_linux[4] = {0, 0};
fkey_command_linux[5] = {"../build/4ed", "*run*"}; fkey_command_linux[5] = {"../build/4ed", "*run*"};
fkey_command_linux[6] = {0, 0};
fkey_command_linux[7] = {0, 0};
fkey_command_linux[8] = {0, 0};
fkey_command_linux[9] = {0, 0};
fkey_command_linux[10] = {0, 0};
fkey_command_linux[11] = {0, 0};
fkey_command_linux[12] = {"./package.sh", "*package*"}; fkey_command_linux[12] = {"./package.sh", "*package*"};
fkey_command_linux[13] = {0, 0};
fkey_command_linux[14] = {0, 0};
fkey_command_linux[15] = {0, 0};
fkey_command_linux[16] = {0, 0};

View File

@ -1,5 +1,5 @@
1 1
0 0
59 61

Binary file not shown.

View File

@ -230,6 +230,20 @@ considered immutable.) DOC_SEE(substr) */{
return(result); return(result);
} }
CPP_NAME(skip_whitespace)
API_EXPORT FSTRING_LINK String
skip_whitespace_measure(String str, i32_4tech *skip_length)
/* DOC(This call creates a substring that starts with the first non-whitespace character of str.
Like other substr calls, the new string uses the underlying memory and so should usually be
considered immutable.) DOC_SEE(substr) */{
String result = {0};
i32_4tech i = 0;
for (; i < str.size && char_is_whitespace(str.str[i]); ++i);
result = substr(str, i, str.size - i);
*skip_length = i;
return(result);
}
API_EXPORT FSTRING_LINK String API_EXPORT FSTRING_LINK String
chop_whitespace(String str) chop_whitespace(String str)
/* DOC(This call creates a substring that ends with the last non-whitespace character of str. /* DOC(This call creates a substring that ends with the last non-whitespace character of str.
@ -251,6 +265,16 @@ DOC_SEE(skip_whitespace) DOC_SEE(chop_whitespace)*/{
return(str); return(str);
} }
CPP_NAME(skip_chop_whitespace)
API_EXPORT FSTRING_LINK String
skip_chop_whitespace_measure(String str, i32_4tech *skip_length)
/* DOC(This call is equivalent to calling skip_whitespace and chop_whitespace together.)
DOC_SEE(skip_whitespace) DOC_SEE(chop_whitespace)*/{
str = skip_whitespace_measure(str, skip_length);
str = chop_whitespace(str);
return(str);
}
API_EXPORT_INLINE FSTRING_INLINE String API_EXPORT_INLINE FSTRING_INLINE String
tailstr(String str) tailstr(String str)
/* DOC(This call returns an empty String with underlying memory taken from /* DOC(This call returns an empty String with underlying memory taken from
@ -1880,7 +1904,7 @@ static void
get_absolutes(String name, Absolutes *absolutes, b32_4tech implicit_first, b32_4tech implicit_last){ get_absolutes(String name, Absolutes *absolutes, b32_4tech implicit_first, b32_4tech implicit_last){
if (name.size != 0){ if (name.size != 0){
i32_4tech count = 0; i32_4tech count = 0;
i32_4tech max = ArrayCount(absolutes->a) - 1; i32_4tech max = (sizeof(absolutes->a)/sizeof(*absolutes->a)) - 1;
if (implicit_last) --max; if (implicit_last) --max;
String str; String str;

View File

@ -38,6 +38,7 @@
#include <Windows.h> #include <Windows.h>
#include <GL/gl.h> #include <GL/gl.h>
#include "win32_gl.h"
#define GL_TEXTURE_MAX_LEVEL 0x813D #define GL_TEXTURE_MAX_LEVEL 0x813D
@ -594,7 +595,7 @@ Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
system_acquire_lock(CANCEL_LOCK0 + memory->id - 1); system_acquire_lock(CANCEL_LOCK0 + memory->id - 1);
void *old_data = memory->data; void *old_data = memory->data;
i32 old_size = memory->size; i32 old_size = memory->size;
i32 new_size = l_round_up(memory->size*2, KB(4)); i32 new_size = l_round_up_i32(memory->size*2, KB(4));
memory->data = system_get_memory(new_size); memory->data = system_get_memory(new_size);
memory->size = new_size; memory->size = new_size;
if (old_data){ if (old_data){
@ -1575,6 +1576,148 @@ Win32Resize(i32 width, i32 height){
} }
} }
internal void*
win32_load_gl_always(char *name, HMODULE module){
void *p = (void *)wglGetProcAddress(name), *r = 0;
if(p == 0 ||
(p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) ||
(p == (void*)-1) ){
r = (void *)GetProcAddress(module, name);
}
else{
r = p;
}
return(r);
}
internal void
OpenGLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam)
{
OutputDebugStringA(message);
OutputDebugStringA("\n");
}
internal void
Win32InitGL(){
// GL context initialization
{
PIXELFORMATDESCRIPTOR format;
int format_id;
BOOL success;
HDC dc;
format.nSize = sizeof(format);
format.nVersion = 1;
format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
format.iPixelType = PFD_TYPE_RGBA;
format.cColorBits = 32;
format.cRedBits = 0;
format.cRedShift = 0;
format.cGreenBits = 0;
format.cGreenShift = 0;
format.cBlueBits = 0;
format.cBlueShift = 0;
format.cAlphaBits = 0;
format.cAlphaShift = 0;
format.cAccumBits = 0;
format.cAccumRedBits = 0;
format.cAccumGreenBits = 0;
format.cAccumBlueBits = 0;
format.cAccumAlphaBits = 0;
format.cDepthBits = 24;
format.cStencilBits = 8;
format.cAuxBuffers = 0;
format.iLayerType = PFD_MAIN_PLANE;
format.bReserved = 0;
format.dwLayerMask = 0;
format.dwVisibleMask = 0;
format.dwDamageMask = 0;
dc = GetDC(win32vars.window_handle);
Assert(dc);
format_id = ChoosePixelFormat(dc, &format);
Assert(format_id != 0);
success = SetPixelFormat(dc, format_id, &format);
Assert(success == TRUE);
HGLRC glcontext = wglCreateContext(dc);
wglMakeCurrent(dc, glcontext);
{
HMODULE module = LoadLibraryA("opengl32.dll");
wglCreateContextAttribsARB_Function *wglCreateContextAttribsARB = 0;
wglCreateContextAttribsARB = (wglCreateContextAttribsARB_Function*)
win32_load_gl_always("wglCreateContextAttribsARB", module);
wglChoosePixelFormatARB_Function *wglChoosePixelFormatARB = 0;
wglChoosePixelFormatARB = (wglChoosePixelFormatARB_Function*)
win32_load_gl_always("wglChoosePixelFormatARB", module);
if (wglCreateContextAttribsARB != 0 && wglChoosePixelFormatARB != 0){
const int choosePixel_attribList[] =
{
WGL_DRAW_TO_WINDOW_ARB, TRUE,
WGL_SUPPORT_OPENGL_ARB, TRUE,
//WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0,
};
i32 extended_format_id;
UINT num_formats = 0;
BOOL result = 0;
result = wglChoosePixelFormatARB(dc, choosePixel_attribList, 0, 1, &extended_format_id, &num_formats);
if (result != 0 && num_formats > 0){
const int createContext_attribList[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
if (extended_format_id == format_id){
HGLRC extended_context = wglCreateContextAttribsARB(dc, 0, createContext_attribList);
if (extended_context){
wglMakeCurrent(dc, extended_context);
wglDeleteContext(glcontext);
glcontext = extended_context;
}
}
}
}
}
ReleaseDC(win32vars.window_handle, dc);
}
#if FRED_INTERNAL
// NOTE(casey): This slows down GL but puts error messages to
// the debug console immediately whenever you do something wrong
glDebugMessageCallback_type *glDebugMessageCallback =
(glDebugMessageCallback_type *)wglGetProcAddress("glDebugMessageCallback");
glDebugMessageControl_type *glDebugMessageControl =
(glDebugMessageControl_type *)wglGetProcAddress("glDebugMessageControl");
if(glDebugMessageCallback && glDebugMessageControl)
{
glDebugMessageCallback(OpenGLDebugCallback, 0);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
#endif
glEnable(GL_TEXTURE_2D);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
internal void internal void
Win32SetCursorFromUpdate(Application_Mouse_Cursor cursor){ Win32SetCursorFromUpdate(Application_Mouse_Cursor cursor){
switch (cursor){ switch (cursor){
@ -1602,93 +1745,18 @@ Win32HighResolutionTime(){
return(result); return(result);
} }
internal void
Win32Foo(WPARAM wParam, LPARAM lParam){
internal LRESULT
Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
LRESULT result = 0;
switch (uMsg){
case WM_MENUCHAR:
case WM_SYSCHAR:break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
switch (wParam){
case VK_CONTROL:case VK_LCONTROL:case VK_RCONTROL:
case VK_MENU:case VK_LMENU:case VK_RMENU:
case VK_SHIFT:case VK_LSHIFT:case VK_RSHIFT:
{
Control_Keys *controls = &win32vars.input_chunk.pers.controls;
b8 *control_keys = win32vars.input_chunk.pers.control_keys;
b8 down = ((lParam & Bit_31)?(0):(1));
b8 is_right = ((lParam & Bit_24)?(1):(0));
if (wParam != 255){
switch (wParam){
case VK_SHIFT:
{
control_keys[MDFR_SHIFT_INDEX] = down;
}break;
case VK_CONTROL:
{
if (is_right) controls->r_ctrl = down;
else controls->l_ctrl = down;
}break;
case VK_MENU:
{
if (is_right) controls->r_alt = down;
else controls->l_alt = down;
}break;
}
b8 ctrl, alt;
ctrl = (controls->r_ctrl || (controls->l_ctrl && !controls->r_alt));
alt = (controls->l_alt || (controls->r_alt && !controls->l_ctrl));
if (win32vars.lctrl_lalt_is_altgr){
if (controls->l_alt && controls->l_ctrl){
ctrl = 0;
alt = 0;
}
}
control_keys[MDFR_CONTROL_INDEX] = ctrl;
control_keys[MDFR_ALT_INDEX] = alt;
}
}break;
default:
{
b8 previous_state = ((lParam & Bit_30)?(1):(0)); b8 previous_state = ((lParam & Bit_30)?(1):(0));
b8 current_state = ((lParam & Bit_31)?(0):(1)); b8 current_state = ((lParam & Bit_31)?(0):(1));
win32vars.got_useful_event = 1;
if (current_state){ if (current_state){
u8 key = keycode_lookup_table[(u8)wParam]; u8 key = keycode_lookup_table[(u8)wParam];
i32 *count = 0; i32 *count = &win32vars.input_chunk.trans.key_data.count;
Key_Event_Data *data = 0; Key_Event_Data *data = win32vars.input_chunk.trans.key_data.keys;
b8 *control_keys = 0; b8 *control_keys = win32vars.input_chunk.pers.control_keys;
i32 control_keys_size = 0; i32 control_keys_size = sizeof(win32vars.input_chunk.pers.control_keys);
if (!previous_state){
count = &win32vars.input_chunk.trans.key_data.press_count;
data = win32vars.input_chunk.trans.key_data.press;
}
else{
count = &win32vars.input_chunk.trans.key_data.hold_count;
data = win32vars.input_chunk.trans.key_data.hold;
}
control_keys = win32vars.input_chunk.pers.control_keys;
control_keys_size = sizeof(win32vars.input_chunk.pers.control_keys);
if (*count < KEY_INPUT_BUFFER_SIZE){ if (*count < KEY_INPUT_BUFFER_SIZE){
if (!key){ if (!key){
@ -1790,12 +1858,134 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
++(*count); ++(*count);
} }
} }
}
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
internal LRESULT
Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
LRESULT result = 0;
switch (uMsg){
case WM_MENUCHAR:break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
switch (wParam){
case VK_CONTROL:case VK_LCONTROL:case VK_RCONTROL:
case VK_MENU:case VK_LMENU:case VK_RMENU:
case VK_SHIFT:case VK_LSHIFT:case VK_RSHIFT:
{
Control_Keys *controls = &win32vars.input_chunk.pers.controls;
b8 *control_keys = win32vars.input_chunk.pers.control_keys;
b8 down = ((lParam & Bit_31)?(0):(1));
b8 is_right = ((lParam & Bit_24)?(1):(0));
if (wParam != 255){
switch (wParam){
case VK_SHIFT:
{
control_keys[MDFR_SHIFT_INDEX] = down;
}break;
case VK_CONTROL:
{
if (is_right) controls->r_ctrl = down;
else controls->l_ctrl = down;
}break;
case VK_MENU:
{
if (is_right) controls->r_alt = down;
else controls->l_alt = down;
}break;
}
b8 ctrl = (controls->r_ctrl || (controls->l_ctrl && !controls->r_alt));
b8 alt = (controls->l_alt || (controls->r_alt && !controls->l_ctrl));
if (win32vars.lctrl_lalt_is_altgr){
if (controls->l_alt && controls->l_ctrl){
ctrl = 0;
alt = 0;
}
}
control_keys[MDFR_CONTROL_INDEX] = ctrl;
control_keys[MDFR_ALT_INDEX] = alt;
}
}break;
default:
{
b8 current_state = ((lParam & Bit_31)?(0):(1));
if (current_state){
u8 key = keycode_lookup_table[(u8)wParam];
if (key != 0){
i32 *count = &win32vars.input_chunk.trans.key_data.count;
Key_Event_Data *data = win32vars.input_chunk.trans.key_data.keys;
b8 *control_keys = win32vars.input_chunk.pers.control_keys;
i32 control_keys_size = sizeof(win32vars.input_chunk.pers.control_keys);
Assert(*count < KEY_INPUT_BUFFER_SIZE);
data[*count].character = 0;
data[*count].character_no_caps_lock = 0;
data[*count].keycode = key;
memcpy(data[*count].modifiers, control_keys, control_keys_size);
++(*count);
win32vars.got_useful_event = 1;
}
}
}break; }break;
}/* switch */ }/* switch */
}break; }break;
case WM_CHAR: case WM_SYSCHAR: case WM_UNICHAR:
{
u8 character = wParam & 0x7F;
if (character == '\r'){
character = '\n';
}
else if ((character < 32 && character != '\t') || character == 127){
break;
}
u8 character_no_caps_lock = character;
i32 *count = &win32vars.input_chunk.trans.key_data.count;
Key_Event_Data *data = win32vars.input_chunk.trans.key_data.keys;
b8 *control_keys = win32vars.input_chunk.pers.control_keys;
i32 control_keys_size = sizeof(win32vars.input_chunk.pers.control_keys);
BYTE state[256];
GetKeyboardState(state);
if (state[VK_CAPITAL]){
if (character_no_caps_lock >= 'a' && character_no_caps_lock <= 'z'){
character_no_caps_lock += (u8)('A' - 'a');
}
else if (character_no_caps_lock >= 'A' && character_no_caps_lock <= 'Z'){
character_no_caps_lock += (u8)('a' - 'A');
}
}
Assert(*count < KEY_INPUT_BUFFER_SIZE);
data[*count].character = character;
data[*count].character_no_caps_lock = character_no_caps_lock;
data[*count].keycode = character_no_caps_lock;
memcpy(data[*count].modifiers, control_keys, control_keys_size);
++(*count);
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
win32vars.got_useful_event = 1;
}break;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
{ {
i32 new_x = LOWORD(lParam); i32 new_x = LOWORD(lParam);
@ -1865,12 +2055,10 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
case WM_SIZE: case WM_SIZE:
{ {
win32vars.got_useful_event = 1; win32vars.got_useful_event = 1;
if (win32vars.target.handle){
i32 new_width = LOWORD(lParam); i32 new_width = LOWORD(lParam);
i32 new_height = HIWORD(lParam); i32 new_height = HIWORD(lParam);
Win32Resize(new_width, new_height); Win32Resize(new_width, new_height);
}
}break; }break;
case WM_PAINT: case WM_PAINT:
@ -1907,21 +2095,6 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
return(result); return(result);
} }
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
#define GL_DEBUG_OUTPUT 0x92E0
typedef void GLDEBUGPROC_TYPE(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char * message, const GLvoid * userParam);
typedef GLDEBUGPROC_TYPE * GLDEBUGPROC;
typedef void glDebugMessageControl_type(GLenum source, GLenum type, GLenum severity, GLsizei count, GLuint * ids, GLboolean enabled);
typedef void glDebugMessageCallback_type(GLDEBUGPROC callback, void * userParam);
internal void
OpenGLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam)
{
OutputDebugStringA(message);
OutputDebugStringA("\n");
}
int int
WinMain(HINSTANCE hInstance, WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, HINSTANCE hPrevInstance,
@ -2177,65 +2350,9 @@ WinMain(HINSTANCE hInstance,
#endif #endif
GetClientRect(win32vars.window_handle, &window_rect); GetClientRect(win32vars.window_handle, &window_rect);
DWORD pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
// NOTE(allen): This is probably not an issue on linux and
// does not need to be ported.
if (!win32vars.settings.stream_mode){
pfd_flags |= PFD_DOUBLEBUFFER;
}
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
pfd_flags,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0 };
// TODO(allen): get an upgraded context to see if that fixes the nvidia card issues.
{
i32 pixel_format;
pixel_format = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, pixel_format, &pfd);
win32vars.target.handle = hdc;
win32vars.target.context = wglCreateContext(hdc);
wglMakeCurrent(hdc, (HGLRC)win32vars.target.context);
}
ReleaseDC(win32vars.window_handle, hdc); ReleaseDC(win32vars.window_handle, hdc);
#if FRED_INTERNAL Win32InitGL();
// NOTE(casey): This slows down GL but puts error messages to
// the debug console immediately whenever you do something wrong
glDebugMessageCallback_type *glDebugMessageCallback =
(glDebugMessageCallback_type *)wglGetProcAddress("glDebugMessageCallback");
glDebugMessageControl_type *glDebugMessageControl =
(glDebugMessageControl_type *)wglGetProcAddress("glDebugMessageControl");
if(glDebugMessageCallback && glDebugMessageControl)
{
glDebugMessageCallback(OpenGLDebugCallback, 0);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
#endif
glEnable(GL_TEXTURE_2D);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Win32Resize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top); Win32Resize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top);
@ -2316,28 +2433,96 @@ WinMain(HINSTANCE hInstance,
if (!(win32vars.first && win32vars.settings.stream_mode)){ if (!(win32vars.first && win32vars.settings.stream_mode)){
system_release_lock(FRAME_LOCK); system_release_lock(FRAME_LOCK);
if (win32vars.running_cli == 0){ b32 get_more_messages = true;
win32vars.got_useful_event = 0; do{
for (;win32vars.got_useful_event == 0;){ if (win32vars.got_useful_event == 0){
if (GetMessage(&msg, 0, 0, 0)){ get_more_messages = GetMessage(&msg, 0, 0, 0);
}
else{
get_more_messages = PeekMessage(&msg, 0, 0, 0, 1);
}
if (get_more_messages){
if (msg.message == WM_QUIT){ if (msg.message == WM_QUIT){
keep_playing = 0; keep_playing = 0;
}else{ }else{
TranslateMessage(&msg); b32 treat_normally = true;
DispatchMessage(&msg); if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN){
} switch (msg.wParam){
} case VK_CONTROL:case VK_LCONTROL:case VK_RCONTROL:
case VK_MENU:case VK_LMENU:case VK_RMENU:
case VK_SHIFT:case VK_LSHIFT:case VK_RSHIFT:break;
default: treat_normally = false; break;
} }
} }
while (PeekMessage(&msg, 0, 0, 0, 1)){ if (treat_normally){
if (msg.message == WM_QUIT){
keep_playing = 0;
}else{
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} }
else{
Control_Keys *controls = &win32vars.input_chunk.pers.controls;
b8 ctrl = (controls->r_ctrl || (controls->l_ctrl && !controls->r_alt));
b8 alt = (controls->l_alt || (controls->r_alt && !controls->l_ctrl));
if (win32vars.lctrl_lalt_is_altgr){
if (controls->l_alt && controls->l_ctrl){
ctrl = 0;
alt = 0;
} }
}
BYTE ctrl_state = 0, alt_state = 0;
BYTE state[256];
if (ctrl || alt){
GetKeyboardState(state);
if (ctrl){
ctrl_state = state[VK_CONTROL];
state[VK_CONTROL] = 0;
}
if (alt){
alt_state = state[VK_MENU];
state[VK_MENU] = 0;
}
SetKeyboardState(state);
TranslateMessage(&msg);
DispatchMessage(&msg);
if (ctrl){
state[VK_CONTROL] = ctrl_state;
}
if (alt){
state[VK_MENU] = alt_state;
}
SetKeyboardState(state);
}
else{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#if 0
UINT count = 0;
INPUT in[1];
if (ctrl){
in[count].type = INPUT_KEYBOARD;
in[count].ki.wVk = VK_CONTROL;
in[count].ki.wScan = 0;
in[count].ki.dwFlags = KEYEVENTF_KEYUP;
in[count].ki.time = 0;
in[count].ki.dwExtraInfo = GetMessageExtraInfo();
++count;
}
if(count > 0){
SendInput(count, in, sizeof(in));
}
#endif
}
}
}
}while(get_more_messages);
system_acquire_lock(FRAME_LOCK); system_acquire_lock(FRAME_LOCK);
} }
@ -2398,7 +2583,6 @@ WinMain(HINSTANCE hInstance,
input.dt = frame_useconds / 1000000.f; input.dt = frame_useconds / 1000000.f;
input.keys = input_chunk.trans.key_data; input.keys = input_chunk.trans.key_data;
memcpy(input.keys.modifiers, input_chunk.pers.control_keys, sizeof(input_chunk.pers.control_keys));
input.mouse.out_of_window = input_chunk.trans.out_of_window; input.mouse.out_of_window = input_chunk.trans.out_of_window;

83
win32_gl.h Normal file
View File

@ -0,0 +1,83 @@
/*
WGL declarations for 4coder.
By Allen Webster
Created 27.01.2017 (dd.mm.yyyy)
*/
// TOP
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_DRAW_TO_BITMAP_ARB 0x2002
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_NEED_PALETTE_ARB 0x2004
#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
#define WGL_SWAP_METHOD_ARB 0x2007
#define WGL_NUMBER_OVERLAYS_ARB 0x2008
#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
#define WGL_TRANSPARENT_ARB 0x200A
#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
#define WGL_SHARE_DEPTH_ARB 0x200C
#define WGL_SHARE_STENCIL_ARB 0x200D
#define WGL_SHARE_ACCUM_ARB 0x200E
#define WGL_SUPPORT_GDI_ARB 0x200F
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_STEREO_ARB 0x2012
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_RED_BITS_ARB 0x2015
#define WGL_RED_SHIFT_ARB 0x2016
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_GREEN_SHIFT_ARB 0x2018
#define WGL_BLUE_BITS_ARB 0x2019
#define WGL_BLUE_SHIFT_ARB 0x201A
#define WGL_ALPHA_BITS_ARB 0x201B
#define WGL_ALPHA_SHIFT_ARB 0x201C
#define WGL_ACCUM_BITS_ARB 0x201D
#define WGL_ACCUM_RED_BITS_ARB 0x201E
#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_AUX_BUFFERS_ARB 0x2024
#define WGL_NO_ACCELERATION_ARB 0x2025
#define WGL_GENERIC_ACCELERATION_ARB 0x2026
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_SWAP_EXCHANGE_ARB 0x2028
#define WGL_SWAP_COPY_ARB 0x2029
#define WGL_SWAP_UNDEFINED_ARB 0x202A
#define WGL_TYPE_RGBA_ARB 0x202B
#define WGL_TYPE_COLORINDEX_ARB 0x202C
typedef BOOL wglChoosePixelFormatARB_Function(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define ERROR_INVALID_VERSION_ARB 0x2095
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
typedef HGLRC wglCreateContextAttribsARB_Function(HDC hDC, HGLRC hshareContext, const int *attribList);
typedef const char* wglGetExtensionsStringARB_Function(HDC hdc);
typedef void GLDEBUGPROC_TYPE(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char * message, const GLvoid * userParam);
typedef GLDEBUGPROC_TYPE * GLDEBUGPROC;
typedef void glDebugMessageControl_type(GLenum source, GLenum type, GLenum severity, GLsizei count, GLuint * ids, GLboolean enabled);
typedef void glDebugMessageCallback_type(GLDEBUGPROC callback, void * userParam);
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
#define GL_DEBUG_OUTPUT 0x92E0
// BOTTOM