API started

This commit is contained in:
Allen Webster 2015-10-12 12:15:11 -04:00
parent 852a7fd71c
commit c38d6ce47b
13 changed files with 2751 additions and 1616 deletions

View File

@ -2,113 +2,14 @@
* Example use of customization API
*/
// NOTE(allen): NEW THINGS TO LOOK FOR:
// MAPID_USER_CUSTOM - define maps other than the built in GLOBAL/FILE maps
// inherit_map
//
// get_settings
#include "4coder_custom.h"
// NOTE(allen): All this helper stuff is here to make the new API
// work a lot like the old API
struct Bind_Helper{
Binding_Unit *cursor, *start, *end;
Binding_Unit *header, *map;
int write_total;
int error;
};
#define BH_ERR_NONE 0
#define BH_ERR_MISSING_END_MAP 1
#define BH_ERR_MISSING_BEGIN_MAP 2
inline Binding_Unit*
write_unit(Bind_Helper *helper, Binding_Unit unit){
Binding_Unit *p = 0;
helper->write_total += sizeof(Binding_Unit);
if (helper->error == 0 && helper->cursor != helper->end){
p = helper->cursor++;
*p = unit;
}
return p;
}
inline Bind_Helper
begin_bind_helper(void *data, int size){
Bind_Helper result;
result.header = 0;
result.map = 0;
result.write_total = 0;
result.error = 0;
result.cursor = (Binding_Unit*)data;
result.start = result.cursor;
result.end = result.start + size / sizeof(Binding_Unit);
Binding_Unit unit;
unit.type = UNIT_HEADER;
unit.header.total_size = sizeof(Binding_Unit);
result.header = write_unit(&result, unit);
return result;
}
inline void
begin_map(Bind_Helper *helper, int mapid){
if (helper->map != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END_MAP;
Binding_Unit unit;
unit.type = UNIT_MAP_BEGIN;
unit.map_begin.mapid = mapid;
helper->map = write_unit(helper, unit);
}
inline void
end_map(Bind_Helper *helper){
if (helper->map == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN_MAP;
helper->map = 0;
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
if (helper->map == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN_MAP;
Binding_Unit unit;
unit.type = UNIT_BINDING;
unit.binding.command_id = cmdid;
unit.binding.code = code;
unit.binding.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind_me(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
if (helper->map == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN_MAP;
Binding_Unit unit;
unit.type = UNIT_CALLBACK;
unit.callback.func = func;
unit.callback.code = code;
unit.callback.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, int cmdid){
bind(helper, 0, 0, cmdid);
}
inline void
bind_me_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){
bind_me(helper, 0, 0, func);
}
inline void
end_bind_helper(Bind_Helper *helper){
if (helper->header){
helper->header->header.total_size = (int)(helper->cursor - helper->start);
helper->header->header.error = helper->error;
}
}
#include "4coder_helper.h"
#define exec_command app.exec_command
#define fulfill_interaction app.fulfill_interaction
@ -123,37 +24,81 @@ CUSTOM_COMMAND_SIG(open_in_other){
exec_command(cmd_context, cmdid_interactive_open);
}
extern "C" GET_BINDING_DATA(get_bindings){
extern "C" GET_BINDING_DATA(get_binding){
Bind_Helper context_actual = begin_bind_helper(data, size);
Bind_Helper *context = &context_actual;
begin_settings_group(context);
use_when(context, when_default, 1);
set(context, set_lex_as_cpp_file, 0);
set(context, set_wrap_lines, 1);
set(context, set_key_mapid, MAPID_FILE);
// NOTE(allen): options include EOL_USE_CRLF, EOL_USE_CR_USE_LF, EOL_SHOW_CR_USE_LF
// EOL_USE_CRLF - treats a crlf and lf as newline markers, renders lone cr as special character "\r"
// EOL_USE_CR_USE_LF - treats both as separate newline markers
// EOL_SHOW_CR_USE_LF - treats lf as newline marker, renders cr as special character "\r"
set(context, set_end_line_mode, EOL_USE_CRLF);
end_group(context);
begin_settings_group(context);
use_when(context, when_extension, "cpp");
use_when(context, when_extension, "hpp");
use_when(context, when_extension, "c");
use_when(context, when_extension, "h");
set(context, set_lex_as_cpp_file, 1);
set(context, set_key_mapid, MAPID_USER_CUSTOM + 0);
begin_map(context, MAPID_GLOBAL);
// NOTE(allen): Here put the contents of your set_global_bindings
bind(context, 'p', MDFR_CTRL, cmdid_open_panel_vsplit);
bind(context, '-', MDFR_CTRL, cmdid_open_panel_hsplit);
bind(context, 'P', MDFR_CTRL, cmdid_close_panel);
bind(context, 'n', MDFR_CTRL, cmdid_interactive_new);
bind(context, 'o', MDFR_CTRL, cmdid_interactive_open);
bind(context, ',', MDFR_CTRL, cmdid_change_active_panel);
bind(context, 'k', MDFR_CTRL, cmdid_interactive_kill_file);
bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_file);
bind(context, 'k', MDFR_CTRL, cmdid_interactive_kill_buffer);
bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_buffer);
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
bind(context, 'x', MDFR_ALT, cmdid_open_menu);
bind_me(context, 'o', MDFR_ALT, open_in_other);
end_map(context);
begin_map(context, MAPID_USER_CUSTOM + 0);
// NOTE(allen): Set this map (MAPID_USER_CUSTOM + 0) to
// 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.
//
// If this is not set, it defaults to MAPID_GLOBAL.
inherit_map(context, MAPID_FILE);
bind(context, codes->right, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_right);
bind(context, codes->left, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_left);
// NOTE(allen): Not currently functional
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab);
end_map(context);
begin_map(context, MAPID_FILE);
// NOTE(allen): This is a new concept in the API. Binding this can be thought of as binding
// all combos which have an ascii code (shifted or not) and unmodified by CTRL or ALT.
// As of now, if this is used it cannot be overriden for particular combos; this overrides
// normal bindings.
// NOTE(allen): Binding this essentially binds all key combos that
// would normally insert a character into a buffer.
// Or apply this rule (which always works): if the code for the key
// is not in the codes struct, it is a vanilla key.
// It is possible to override this binding for individual keys.
bind_vanilla_keys(context, cmdid_write_character);
// NOTE(allen): Here put the contents of your set_file_bindings
bind(context, codes->left, MDFR_NONE, cmdid_move_left);
bind(context, codes->right, MDFR_NONE, cmdid_move_right);
bind(context, codes->del, MDFR_NONE, cmdid_delete);
@ -165,8 +110,8 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, codes->page_up, MDFR_NONE, cmdid_page_up);
bind(context, codes->page_down, MDFR_NONE, cmdid_page_down);
bind(context, codes->right, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_right);
bind(context, codes->left, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_left);
bind(context, codes->right, MDFR_CTRL, cmdid_seek_whitespace_right);
bind(context, codes->left, MDFR_CTRL, cmdid_seek_whitespace_left);
bind(context, codes->up, MDFR_CTRL, cmdid_seek_whitespace_up);
bind(context, codes->down, MDFR_CTRL, cmdid_seek_whitespace_down);
@ -176,23 +121,26 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, 'x', MDFR_CTRL, cmdid_cut);
bind(context, 'v', MDFR_CTRL, cmdid_paste);
bind(context, 'V', MDFR_CTRL, cmdid_paste_next);
bind(context, 'z', MDFR_CTRL, cmdid_undo);
bind(context, 'y', MDFR_CTRL, cmdid_redo);
bind(context, 'd', MDFR_CTRL, cmdid_delete_chunk);
bind(context, 'l', MDFR_CTRL, cmdid_toggle_line_wrap);
bind(context, 'L', MDFR_CTRL, cmdid_toggle_endline_mode);
bind(context, 'u', MDFR_CTRL, cmdid_to_uppercase);
bind(context, 'j', MDFR_CTRL, cmdid_to_lowercase);
bind(context, '?', MDFR_CTRL, cmdid_toggle_show_whitespace);
// NOTE(allen): These whitespace manipulators are not currently functional
bind(context, '`', MDFR_CTRL, cmdid_clean_line);
bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines);
bind(context, '1', MDFR_CTRL, cmdid_eol_dosify);
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
bind(context, 'f', MDFR_CTRL, cmdid_search);
bind(context, 'r', MDFR_CTRL, cmdid_rsearch);
bind(context, 'g', MDFR_CTRL, cmdid_goto_line);
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab);
bind(context, 'K', MDFR_CTRL, cmdid_kill_file);
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
bind(context, 'O', MDFR_CTRL, cmdid_reopen);
bind(context, 'w', MDFR_CTRL, cmdid_interactive_save_as);
bind(context, 's', MDFR_CTRL, cmdid_save);

View File

@ -70,15 +70,17 @@ enum Command_ID{
cmdid_paste,
cmdid_paste_next,
cmdid_delete_chunk,
cmdid_undo,
cmdid_redo,
cmdid_interactive_new,
cmdid_interactive_open,
cmdid_reopen,
cmdid_save,
cmdid_interactive_save_as,
cmdid_change_active_panel,
cmdid_interactive_switch_file,
cmdid_interactive_kill_file,
cmdid_kill_file,
cmdid_interactive_switch_buffer,
cmdid_interactive_kill_buffer,
cmdid_kill_buffer,
cmdid_toggle_line_wrap,
cmdid_toggle_endline_mode,
cmdid_to_uppercase,
@ -141,36 +143,72 @@ struct Application_Links{
Fulfill_Interaction_Function *fulfill_interaction;
};
enum Settings_Unit_Type{
SUNIT_HEADER,
SUNIT_GROUP,
SUNIT_USE_CLAUSE,
SUNIT_USE_CLAUSE_STRING,
SUNIT_SETTING
};
enum Setting_ID{
set_lex_as_cpp_file,
set_wrap_lines,
set_key_mapid,
set_end_line_mode
};
enum Setting_When_Type{
when_default,
when_extension
};
enum End_Of_Line_Options{
EOL_USE_CRLF,
EOL_USE_CR_USE_LF,
EOL_SHOW_CR_USE_LF
};
enum Binding_Unit_Type{
UNIT_HEADER,
UNIT_MAP_BEGIN,
UNIT_BINDING,
UNIT_CALLBACK
UNIT_CALLBACK,
UNIT_INHERIT,
UNIT_SETTINGS_BEGIN,
UNIT_USE_CLAUSE,
UNIT_USE_CLAUSE_STRING,
UNIT_SETTING
};
enum Map_ID{
MAPID_GLOBAL,
MAPID_FILE
MAPID_FILE,
MAPID_USER_CUSTOM
};
struct Binding_Unit{
Binding_Unit_Type type;
union{
struct{ int total_size; int error; } header;
struct{ int mapid; } map_begin;
struct{ int total_size; int map_count; int group_count; int error; } header;
struct{ int mapid; int bind_count; } map_begin;
struct{ int mapid; } map_inherit;
struct{
int command_id;
short code;
unsigned char modifiers;
} binding;
struct{
Custom_Command_Function *func;
short code;
unsigned char modifiers;
} callback;
struct{ int clause_type; int value; } use_clause;
struct{ int clause_type; int len; char *value; } use_clause_string;
struct{ int setting_id; int value; } setting;
};
};

135
4coder_custom_vim.cpp Normal file
View File

@ -0,0 +1,135 @@
/*
* This is an example of how vim-keys might start
* to work in 4coder, through the customization API.
*/
#include "4coder_custom.h"
#include "4coder_helper.h"
#define exec_command app.exec_command
#define fulfill_interaction app.fulfill_interaction
extern "C" START_HOOK_SIG(start_hook){
exec_command(cmd_context, cmdid_open_panel_vsplit);
exec_command(cmd_context, cmdid_change_active_panel);
}
extern "C" GET_BINDING_DATA(get_binding){
Bind_Helper context_actual = begin_bind_helper(data, size);
Bind_Helper *context = &context_actual;
begin_settings_group(context);
use_when(context, when_default, 1);
set(context, set_lex_as_cpp_file, 0);
set(context, set_wrap_lines, 1);
set(context, set_key_mapid, MAPID_FILE);
// NOTE(allen): options include EOL_USE_CRLF, EOL_USE_CR_USE_LF, EOL_SHOW_CR_USE_LF
// EOL_USE_CRLF - treats a crlf and lf as newline markers, renders lone cr as special character "\r"
// EOL_USE_CR_USE_LF - treats both as separate newline markers
// EOL_SHOW_CR_USE_LF - treats lf as newline marker, renders cr as special character "\r"
set(context, set_end_line_mode, EOL_USE_CRLF);
end_group(context);
begin_settings_group(context);
use_when(context, when_extension, "cpp");
use_when(context, when_extension, "hpp");
use_when(context, when_extension, "c");
use_when(context, when_extension, "h");
set(context, set_lex_as_cpp_file, 1);
set(context, set_key_mapid, MAPID_USER_CUSTOM + 0);
begin_map(context, MAPID_GLOBAL);
bind(context, 'p', MDFR_CTRL, cmdid_open_panel_vsplit);
bind(context, '-', MDFR_CTRL, cmdid_open_panel_hsplit);
bind(context, 'P', MDFR_CTRL, cmdid_close_panel);
bind(context, 'n', MDFR_CTRL, cmdid_interactive_new);
bind(context, 'o', MDFR_CTRL, cmdid_interactive_open);
bind(context, ',', MDFR_CTRL, cmdid_change_active_panel);
bind(context, 'k', MDFR_CTRL, cmdid_interactive_kill_buffer);
bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_buffer);
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
bind(context, 'x', MDFR_ALT, cmdid_open_menu);
bind_me(context, 'o', MDFR_ALT, open_in_other);
end_map(context);
begin_map(context, MAPID_USER_CUSTOM + 0);
inherit_map(context, MAPID_FILE);
end_map(context);
int sub_id;
begin_map(context, MAPID_FILE);
sub_id = begin_sub_map(context);
{
bind_vanilla_keys(context, cmdid_write_character);
bind(context, codes->left, MDFR_NONE, cmdid_move_left);
bind(context, codes->right, MDFR_NONE, cmdid_move_right);
bind(context, codes->del, MDFR_NONE, cmdid_delete);
bind(context, codes->back, MDFR_NONE, cmdid_backspace);
bind(context, codes->up, MDFR_NONE, cmdid_move_up);
bind(context, codes->down, MDFR_NONE, cmdid_move_down);
bind(context, codes->end, MDFR_NONE, cmdid_seek_end_of_line);
bind(context, codes->home, MDFR_NONE, cmdid_seek_beginning_of_line);
bind(context, codes->page_up, MDFR_NONE, cmdid_page_up);
bind(context, codes->page_down, MDFR_NONE, cmdid_page_down);
}
end_sub_map(context);
bind_params(context, 'i', MDFR_NONE, cmdid_use_sub_map);
fill_param(context, "sub_id", sub_id);
end_params(context);
bind_multi(context, 'a', MDFR_NONE);
{
bind(context, 'a', MDFR_NONE, cmdid_move_left);
bind_params(context, 'a', MDFR_NONE, cmdid_use_sub_map);
fill_param(context, "sub_id", sub_id);
end_params(context);
}
end_multi(context);
bind(context, 'b', cmdid_seek_alphanumeric_left);
bind(context, 'w', cmdid_seek_alphanumeric_right);
bind(context, 'e', cmdid_seek_white_or_token_right);
// ???? this seems a bit off
bind_compound(context, 'g');
{
bind(context, 'e', cmdid_seek_white_or_token_left);
}
end_compound(context);
end_map(context);
end_bind_helper(context);
return context->write_total;
}
inline void
strset_(char *dst, char *src){
do{
*dst++ = *src++;
}while (*src);
}
#define strset(d,s) if (sizeof(s) <= sizeof(d)) strset_(d,s)
extern "C" SET_EXTRA_FONT_SIG(set_extra_font){
strset(font_out->file_name, "liberation-mono.ttf");
strset(font_out->font_name, "BIG");
font_out->size = 25;
}

228
4coder_helper.h Normal file
View File

@ -0,0 +1,228 @@
/*
* Bind helper struct and functions
*/
struct Bind_Helper{
Binding_Unit *cursor, *start, *end;
Binding_Unit *header, *group;
int write_total;
int error;
};
#define BH_ERR_NONE 0
#define BH_ERR_MISSING_END 1
#define BH_ERR_MISSING_BEGIN 2
#define BH_ERR_OUT_OF_MEMORY 3
inline int
seek_null(char *str){
char *start = str;
while (*str) ++str;
return (int)(str - start);
}
inline void
copy(char *dest, char *src, int len){
for (int i = 0; i < len; ++i){
*dest++ = *src++;
}
}
inline Binding_Unit*
write_unit(Bind_Helper *helper, Binding_Unit unit){
Binding_Unit *p = 0;
helper->write_total += sizeof(*p);
if (helper->error == 0 && helper->cursor != helper->end){
p = helper->cursor++;
*p = unit;
}
return p;
}
inline char*
write_inline_string(Bind_Helper *helper, char *value, int len){
char *dest = 0;
helper->write_total += len;
if (helper->error == 0){
dest = (char*)helper->cursor;
int cursor_advance = len + sizeof(*helper->cursor) - 1;
cursor_advance /= sizeof(*helper->cursor);
cursor_advance *= sizeof(*helper->cursor);
helper->cursor += cursor_advance;
if (helper->cursor < helper->end){
copy(dest, value, len);
}
else{
helper->error = BH_ERR_OUT_OF_MEMORY;
}
}
return dest;
}
inline Bind_Helper
begin_bind_helper(void *data, int size){
Bind_Helper result;
result.header = 0;
result.group = 0;
result.write_total = 0;
result.error = 0;
result.cursor = (Binding_Unit*)data;
result.start = result.cursor;
result.end = result.start + size / sizeof(*result.cursor);
Binding_Unit unit;
unit.type = UNIT_HEADER;
unit.header.total_size = sizeof(*result.header);
result.header = write_unit(&result, unit);
result.header->header.map_count = 0;
result.header->header.group_count = 0;
return result;
}
inline void
begin_map(Bind_Helper *helper, int mapid){
if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END;
if (!helper->error) ++helper->header->header.map_count;
Binding_Unit unit;
unit.type = UNIT_MAP_BEGIN;
unit.map_begin.mapid = mapid;
helper->group = write_unit(helper, unit);
helper->group->map_begin.bind_count = 0;
}
inline void
end_map(Bind_Helper *helper){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
helper->group = 0;
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = UNIT_BINDING;
unit.binding.command_id = cmdid;
unit.binding.code = code;
unit.binding.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind_me(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = UNIT_CALLBACK;
unit.callback.func = func;
unit.callback.code = code;
unit.callback.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, int cmdid){
bind(helper, 0, 0, cmdid);
}
inline void
bind_me_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){
bind_me(helper, 0, 0, func);
}
inline void
inherit_map(Bind_Helper *helper, int mapid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
Binding_Unit unit;
unit.type = UNIT_INHERIT;
unit.map_inherit.mapid = mapid;
write_unit(helper, unit);
}
inline void
end_bind_helper(Bind_Helper *helper){
if (helper->header){
helper->header->header.total_size = (int)(helper->cursor - helper->start);
helper->header->header.error = helper->error;
}
}
inline void
begin_settings_group(Bind_Helper *helper){
if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END;
if (!helper->error) ++helper->header->header.group_count;
Binding_Unit unit;
unit.type = UNIT_SETTINGS_BEGIN;
helper->group = write_unit(helper, unit);
}
inline void
end_group(Bind_Helper *helper){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
helper->group = 0;
}
inline void
use_when(Bind_Helper *helper, int clause_type, int value){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
Binding_Unit unit;
unit.type = UNIT_USE_CLAUSE;
unit.use_clause.clause_type = clause_type;
unit.use_clause.value = value;
write_unit(helper, unit);
}
inline void
use_when(Bind_Helper *helper, int clause_type, char *value){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
Binding_Unit unit;
unit.type = UNIT_USE_CLAUSE;
unit.use_clause_string.clause_type = clause_type;
unit.use_clause_string.len = seek_null(value);
Binding_Unit *u = write_unit(helper, unit);
u->use_clause_string.value = write_inline_string(helper, value, unit.use_clause_string.len);
}
inline void
use_when(Bind_Helper *helper, int clause_type, char *value, int len){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
Binding_Unit unit;
unit.type = UNIT_USE_CLAUSE;
unit.use_clause_string.clause_type = clause_type;
unit.use_clause_string.len = len;
unit.use_clause_string.value = value;
write_unit(helper, unit);
}
inline void
set(Bind_Helper *helper, int setting_id, int value){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
Binding_Unit unit;
unit.type = UNIT_SETTING;
unit.setting.setting_id = setting_id;
unit.setting.value = value;
write_unit(helper, unit);
}
inline void
end_settings_helper(Bind_Helper *helper){
if (helper->header){
helper->header->header.error = helper->error;
}
}

View File

@ -1661,10 +1661,10 @@ cpp_relex_nonalloc_main(Cpp_Relex_State *state, Cpp_Token_Stack *relex_stack, in
for (;;){
Cpp_Read_Result read = cpp_lex_step(state->file, &lex);
if (read.has_result){
if (read.token.start == match_token.start &&
read.token.size == match_token.size &&
read.token.flags == match_token.flags &&
read.token.state_flags == match_token.state_flags){
if (read.token.start == end_token.start &&
read.token.size == end_token.size &&
read.token.flags == end_token.flags &&
read.token.state_flags == end_token.state_flags){
break;
}
cpp_push_token_nonalloc(relex_stack, read.token);

View File

@ -111,13 +111,13 @@ FCPP_LINK int hexchar_to_int(char c);
FCPP_LINK int int_to_hexchar(char c);
FCPP_LINK int hexstr_to_int(String s);
FCPP_LINK void copy_fast_unsafe(char *dest, char *src);
FCPP_LINK int copy_fast_unsafe(char *dest, char *src);
FCPP_LINK void copy_fast_unsafe(char *dest, String src);
FCPP_LINK bool copy_checked(String *dest, String src);
FCPP_LINK bool copy_partial(String *dest, char *src);
FCPP_LINK bool copy_partial(String *dest, String src);
inline void copy(char *dest, char *src) { copy_fast_unsafe(dest, src); }
inline int copy(char *dest, char *src) { return copy_fast_unsafe(dest, src); }
inline void copy(String *dest, String src) { copy_checked(dest, src); }
inline void copy(String *dest, char *src) { copy_partial(dest, src); }
@ -671,14 +671,15 @@ hexstr_to_int(String str){
return x;
}
FCPP_LINK void
FCPP_LINK int
copy_fast_unsafe(char *dest, char *src){
int i = 0;
while (src[i] != 0){
dest[i] = src[i];
++i;
char *start = dest;
while (*src != 0){
*dest = *src;
++dest;
++src;
}
dest[i] = 0;
return (int)(dest - start);
}
FCPP_LINK void
@ -688,7 +689,6 @@ copy_fast_unsafe(char *dest, String src){
dest[i] = src.str[i];
++i;
}
dest[i] = 0;
}
FCPP_LINK bool

651
4ed.cpp

File diff suppressed because it is too large Load Diff

View File

@ -71,66 +71,6 @@ struct Color_Highlight{
i32 ids[4];
};
struct Widget_ID{
i32 id;
i32 sub_id0;
i32 sub_id1;
i32 sub_id2;
};
inline bool32
widget_match(Widget_ID s1, Widget_ID s2){
return (s1.id == s2.id && s1.sub_id0 == s2.sub_id0 &&
s1.sub_id1 == s2.sub_id1 && s1.sub_id2 == s2.sub_id2);
}
struct UI_State{
Render_Target *target;
Style *style;
Font *font;
Mouse_Summary *mouse;
Key_Summary *keys;
Key_Codes *codes;
Working_Set *working_set;
Widget_ID selected, hover, hot;
bool32 activate_me;
bool32 redraw;
bool32 input_stage;
i32 sub_id1_change;
real32 height, view_y;
};
inline bool32
is_selected(UI_State *state, Widget_ID id){
return widget_match(state->selected, id);
}
inline bool32
is_hot(UI_State *state, Widget_ID id){
return widget_match(state->hot, id);
}
inline bool32
is_hover(UI_State *state, Widget_ID id){
return widget_match(state->hover, id);
}
struct UI_Layout{
i32 row_count;
i32 row_item_width;
i32 row_max_item_height;
i32_Rect rect;
i32 x, y;
};
struct UI_Layout_Restore{
UI_Layout layout;
UI_Layout *dest;
};
struct Library_UI{
UI_State state;
UI_Layout layout;
@ -183,58 +123,6 @@ view_to_color_view(View *view){
return (Color_View*)view;
}
inline void
begin_layout(UI_Layout *layout, i32_Rect rect){
layout->rect = rect;
layout->x = rect.x0;
layout->y = rect.y0;
layout->row_count = 0;
layout->row_max_item_height = 0;
}
inline void
begin_row(UI_Layout *layout, i32 count){
layout->row_count = count;
layout->row_item_width = (layout->rect.x1 - layout->x) / count;
}
inline i32_Rect
layout_rect(UI_Layout *layout, i32 height){
i32_Rect rect;
rect.x0 = layout->x;
rect.y0 = layout->y;
rect.x1 = rect.x0;
rect.y1 = rect.y0 + height;
if (layout->row_count > 0){
--layout->row_count;
rect.x1 = rect.x0 + layout->row_item_width;
layout->x += layout->row_item_width;
layout->row_max_item_height = Max(height, layout->row_max_item_height);
}
if (layout->row_count == 0){
rect.x1 = layout->rect.x1;
layout->row_max_item_height = Max(height, layout->row_max_item_height);
layout->y += layout->row_max_item_height;
layout->x = layout->rect.x0;
layout->row_max_item_height = 0;
}
return rect;
}
inline UI_Layout_Restore
begin_sub_layout(UI_Layout *layout, i32_Rect area){
UI_Layout_Restore restore;
restore.layout = *layout;
restore.dest = layout;
begin_layout(layout, area);
return restore;
}
inline void
end_sub_layout(UI_Layout_Restore restore){
*restore.dest = restore.layout;
}
internal real32
font_string_width(Font *font, char *str){
real32 x = 0;
@ -308,203 +196,6 @@ draw_rgb_slider(Render_Target *target, Vec4 base, i32 channel, i32 steps, real32
draw_gradient_slider(target, base, channel, steps, top, slider, 0);
}
inline Widget_ID
make_id(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.id = id;
return r;
}
inline Widget_ID
make_sub0(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.sub_id0 = id;
return r;
}
inline Widget_ID
make_sub1(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.sub_id1 = id;
return r;
}
inline Widget_ID
make_sub2(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.sub_id2 = id;
return r;
}
internal bool32
ui_do_button_input(UI_State *state, i32_Rect rect, Widget_ID id, bool32 activate, bool32 *right = 0){
bool32 result = 0;
Mouse_Summary *mouse = state->mouse;
bool32 hover = hit_check(mouse->mx, mouse->my, rect);
if (hover){
state->hover = id;
if (activate) state->activate_me = 1;
if (mouse->press_l || (mouse->press_r && right)) state->hot = id;
if (mouse->l && mouse->r) state->hot = {};
}
bool32 is_match = widget_match(state->hot, id);
if (mouse->release_l && is_match){
if (hover) result = 1;
state->redraw = 1;
}
if (right && mouse->release_r && is_match){
if (hover) *right = 1;
state->redraw = 1;
}
return result;
}
internal bool32
ui_do_subdivided_button_input(UI_State *state, i32_Rect rect, i32 parts, Widget_ID id, bool32 activate, i32 *indx_out, bool32 *right = 0){
bool32 result = 0;
real32 x0, x1;
i32_Rect sub_rect;
Widget_ID sub_widg = id;
real32 sub_width = (rect.x1 - rect.x0) / (real32)parts;
sub_rect.y0 = rect.y0;
sub_rect.y1 = rect.y1;
x1 = (real32)rect.x0;
for (i32 i = 0; i < parts; ++i){
x0 = x1;
x1 = x1 + sub_width;
sub_rect.x0 = TRUNC32(x0);
sub_rect.x1 = TRUNC32(x1);
sub_widg.sub_id2 = i;
if (ui_do_button_input(state, sub_rect, sub_widg, activate, right)){
*indx_out = i;
break;
}
}
return result;
}
internal real32
ui_do_vscroll_input(UI_State *state, i32_Rect top, i32_Rect bottom, i32_Rect slider,
Widget_ID id, real32 val, real32 step_amount,
real32 smin, real32 smax, real32 vmin, real32 vmax){
Mouse_Summary *mouse = state->mouse;
i32 mx = mouse->mx;
i32 my = mouse->my;
if (hit_check(mx, my, top)){
state->hover = id;
state->hover.sub_id2 = 1;
}
if (hit_check(mx, my, bottom)){
state->hover = id;
state->hover.sub_id2 = 2;
}
if (hit_check(mx, my, slider)){
state->hover = id;
state->hover.sub_id2 = 3;
}
if (mouse->press_l) state->hot = state->hover;
if (id.id == state->hot.id){
if (mouse->release_l){
Widget_ID wid1, wid2;
wid1 = wid2 = id;
wid1.sub_id2 = 1;
wid2.sub_id2 = 2;
if (state->hot.sub_id2 == 1 && is_hover(state, wid1)) val -= step_amount;
if (state->hot.sub_id2 == 2 && is_hover(state, wid2)) val += step_amount;
state->redraw = 1;
}
if (state->hot.sub_id2 == 3){
real32 S, L;
S = (real32)mouse->my - (slider.y1 - slider.y0) / 2;
if (S < smin) S = smin;
if (S > smax) S = smax;
L = unlerp(smin, S, smax);
val = lerp(vmin, L, vmax);
state->redraw = 1;
}
}
return val;
}
internal bool32
ui_do_text_field_input(UI_State *state, String *str){
bool32 result = 0;
Key_Summary *keys = state->keys;
for (i32 key_i = 0; key_i < keys->count; ++key_i){
Key_Single key = get_single_key(keys, key_i);
char c = (char)key.key.character;
if (char_is_basic(c) && str->size < str->memory_size-1){
str->str[str->size++] = c;
str->str[str->size] = 0;
}
else if (c == '\n'){
result = 1;
}
else if (key.key.keycode == state->codes->back && str->size > 0){
str->str[--str->size] = 0;
}
}
return result;
}
internal bool32
ui_do_file_field_input(UI_State *state, Hot_Directory *hot_dir){
bool32 result = 0;
Key_Summary *keys = state->keys;
for (i32 key_i = 0; key_i < keys->count; ++key_i){
Key_Single key = get_single_key(keys, key_i);
String *str = &hot_dir->string;
terminate_with_null(str);
Single_Line_Input_Step step =
app_single_file_input_step(state->codes, state->working_set, key, str, hot_dir, 1);
if (step.hit_newline || step.hit_ctrl_newline) result = 1;
}
return result;
}
internal bool32
ui_do_line_field_input(UI_State *state, String *string){
bool32 result = 0;
Key_Summary *keys = state->keys;
for (i32 key_i = 0; key_i < keys->count; ++key_i){
Key_Single key = get_single_key(keys, key_i);
terminate_with_null(string);
Single_Line_Input_Step step =
app_single_line_input_step(state->codes, key, string);
if (step.hit_newline || step.hit_ctrl_newline) result = 1;
}
return result;
}
internal bool32
ui_do_slider_input(UI_State *state, i32_Rect rect, Widget_ID wid,
real32 min, real32 max, real32 *v){
bool32 result = 0;
ui_do_button_input(state, rect, wid, 0);
Mouse_Summary *mouse = state->mouse;
if (is_hot(state, wid)){
result = 1;
*v = unlerp(min, (real32)mouse->mx, max);
state->redraw = 1;
}
return result;
}
struct UI_Style{
u32 dark, dim, bright;
};
internal UI_Style
get_ui_style(Style *style){
UI_Style ui_style;
ui_style.dark = style->main.back_color;
ui_style.dim = style->main.margin_color;
ui_style.bright = style->main.margin_active_color;
return ui_style;
}
internal void
do_label(UI_State *state, UI_Layout *layout, char *text, real32 height = 2.f){
Style *style = state->style;
@ -522,27 +213,6 @@ do_label(UI_State *state, UI_Layout *layout, char *text, real32 height = 2.f){
}
}
internal void
get_colors(UI_State *state, u32 *back, u32 *fore, Widget_ID wid, UI_Style style){
bool32 hover = is_hover(state, wid);
bool32 hot = is_hot(state, wid);
i32 level = hot + hover;
switch (level){
case 2:
*back = style.bright;
*fore = style.dark;
break;
case 1:
*back = style.dim;
*fore = style.bright;
break;
case 0:
*back = style.dark;
*fore = style.bright;
break;
}
}
internal bool32
do_button(i32 id, UI_State *state, UI_Layout *layout, char *text,
bool32 is_toggle = 0, bool32 on = 0){
@ -550,7 +220,7 @@ do_button(i32 id, UI_State *state, UI_Layout *layout, char *text,
Font *font = state->font;
i32 character_h = font->height;
i32_Rect btn_rect = layout_rect(layout, font->height * 2);
i32_Rect btn_rect = layout_rect(layout, character_h * 2);
btn_rect = get_inner_rect(btn_rect, 2);
Widget_ID wid = make_id(state, id);
@ -1350,75 +1020,6 @@ do_font_switch(Color_UI *ui){
}
}
internal UI_State
ui_state_init(UI_State *state_in, Render_Target *target, Input_Summary *user_input,
Style *style, Working_Set *working_set, bool32 input_stage){
UI_State state;
state.target = target;
state.style = style;
state.font = style->font;
state.working_set = working_set;
state.mouse = &user_input->mouse;
state.keys = &user_input->keys;
state.codes = user_input->codes;
state.selected = state_in->selected;
state.hot = state_in->hot;
if (input_stage) state.hover = {};
else state.hover = state_in->hover;
state.redraw = 0;
state.activate_me = 0;
state.input_stage = input_stage;
state.height = state_in->height;
state.view_y = state_in->view_y;
return state;
}
inline bool32
ui_state_match(UI_State a, UI_State b){
return (widget_match(a.selected, b.selected) &&
widget_match(a.hot, b.hot) &&
widget_match(a.hover, b.hover));
}
internal bool32
ui_finish_frame(UI_State *persist_state, UI_State *state, UI_Layout *layout, i32_Rect rect,
bool32 do_wheel, bool32 *did_activation){
bool32 result = 0;
real32 h = layout->y + persist_state->view_y - rect.y0;
real32 max_y = h - (rect.y1 - rect.y0);
persist_state->height = h;
persist_state->view_y = state->view_y;
if (state->input_stage){
Mouse_Summary *mouse = state->mouse;
if (mouse->wheel_used && do_wheel){
persist_state->view_y += mouse->wheel_amount*state->font->height;
result = 1;
}
if (mouse->release_l && widget_match(state->hot, state->hover)){
if (did_activation) *did_activation = 1;
if (state->activate_me){
state->selected = state->hot;
}
}
if (!mouse->l && !mouse->r){
state->hot = {};
}
if (!ui_state_match(*persist_state, *state) || state->redraw){
result = 1;
}
*persist_state = *state;
}
if (persist_state->view_y >= max_y) persist_state->view_y = max_y;
if (persist_state->view_y < 0) persist_state->view_y = 0;
return result;
}
internal i32
step_draw_adjusting(Color_View *color_view, i32_Rect rect, View_Message message,
Render_Target *target, Input_Summary *user_input){
@ -1860,11 +1461,11 @@ do_file_list_box(UI_State *state, UI_Layout *layout, Hot_Directory *hot_dir, boo
terminate_with_null(&hot_dir->string);
}
else{
String p4c_extension = make_lit_string("p4c");
String message_loaded = make_lit_string(" LOADED");
String message_unsaved = make_lit_string(" LOADED *");
String message_unsynced = make_lit_string(" LOADED BEHIND OS");
String message_nothing = {};
persist String p4c_extension = make_lit_string("p4c");
persist String message_loaded = make_lit_string(" LOADED");
persist String message_unsaved = make_lit_string(" LOADED *");
persist String message_unsynced = make_lit_string(" LOADED BEHIND OS");
persist String message_nothing = {};
char front_name_space[256];
String front_name = make_fixed_width_string(front_name_space);
@ -1896,14 +1497,10 @@ do_file_list_box(UI_State *state, UI_Layout *layout, Hot_Directory *hot_dir, boo
String message = message_nothing;
if (is_loaded){
if (file->last_4ed_write_time != file->last_sys_write_time){
message = message_unsynced;
}
else if (file->last_4ed_edit_time > file->last_sys_write_time){
message = message_unsaved;
}
else{
message = message_loaded;
switch (buffer_get_sync(file)){
case SYNC_GOOD: message = message_loaded; break;
case SYNC_BEHIND_OS: message = message_unsynced; break;
case SYNC_UNSAVED: message = message_unsaved; break;
}
}
@ -1938,6 +1535,10 @@ do_live_file_list_box(UI_State *state, UI_Layout *layout, Working_Set *working_s
terminate_with_null(string);
}
else{
persist String message_unsaved = make_lit_string(" *");
persist String message_unsynced = make_lit_string(" BEHIND OS");
persist String message_nothing = {};
Absolutes absolutes;
get_absolutes(*string, &absolutes, 1, 1);
@ -1947,8 +1548,14 @@ do_live_file_list_box(UI_State *state, UI_Layout *layout, Working_Set *working_s
Editing_File *file = files + i;
if (!file->is_dummy){
String message = message_nothing;
switch (buffer_get_sync(file)){
case SYNC_BEHIND_OS: message = message_unsynced; break;
case SYNC_UNSAVED: message = message_unsaved; break;
}
if (filename_match(*string, &absolutes, file->live_name)){
if (do_file_option(100+i, state, layout, file->live_name, 0, {})){
if (do_file_option(100+i, state, layout, file->live_name, 0, message)){
result = 1;
*selected = 1;
copy(string, file->live_name);

View File

@ -121,11 +121,11 @@ map_extract(Command_Map *map, Key_Single key){
if (alt) command |= MDFR_ALT;
u16 code = key.key.character_no_caps_lock;
if (code != 0) map_get_vanilla_keyboard_default(map, command, &bind);
if (code == 0) code = key.key.keycode;
map_find(map, code, command, &bind);
if (bind.function == 0){
if (code == 0) code = key.key.keycode;
map_find(map, code, command, &bind);
if (bind.function == 0 && key.key.character_no_caps_lock != 0){
map_get_vanilla_keyboard_default(map, command, &bind);
}
return bind;

View File

@ -41,7 +41,7 @@ internal i32
draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32 y){
Font *font = view->font;
i32 y_advance = font->height;
Bubble *sentinel = &view->view_base.general->sentinel;
Bubble *sentinel = &view->view_base.mem->general.sentinel;
for (Bubble *bubble = sentinel->next;
bubble != sentinel;
@ -62,6 +62,8 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32
case BUBBLE_TOKENS: append(&s, "tokens"); break;
case BUBBLE_UNDO_STRING: append(&s, "undo string"); break;
case BUBBLE_UNDO: append(&s, "undo"); break;
case BUBBLE_HISTORY_STRING: append(&s, "history string"); break;
case BUBBLE_HISTORY: append(&s, "history"); break;
default: append(&s, "unknown"); break;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -9,50 +9,19 @@
// TOP
enum Action_Type{
DACT_OPEN,
DACT_SAVE_AS,
DACT_NEW,
DACT_SWITCH,
DACT_KILL,
DACT_CLOSE_MINOR,
DACT_CLOSE_MAJOR,
DACT_THEME_OPTIONS
};
struct Delayed_Action{
Action_Type type;
String string;
Panel *panel;
};
struct Delay{
Delayed_Action acts[8];
i32 count, max;
};
inline void
delayed_action(Delay *delay, Action_Type type,
String string, Panel *panel){
Assert(delay->count < delay->max);
Delayed_Action action;
action.type = type;
action.string = string;
action.panel = panel;
delay->acts[delay->count++] = action;
}
enum Interactive_View_Action{
INTV_OPEN,
INTV_SAVE_AS,
INTV_NEW,
INTV_SWITCH,
INTV_KILL,
INTV_SURE_TO_KILL
};
enum Interactive_View_Interaction{
INTV_SYS_FILE_LIST,
INTV_LIVE_FILE_LIST,
INTV_SURE_TO_KILL_INTER
};
struct Interactive_View{
@ -64,10 +33,12 @@ struct Interactive_View{
UI_State state;
Interactive_View_Interaction interaction;
Interactive_View_Action action;
char query_[256];
String query;
char dest_[256];
String dest;
i32 user_action;
};
inline Interactive_View*
@ -101,8 +72,26 @@ interactive_view_complete(Interactive_View *view){
break;
case INTV_KILL:
delayed_action(view->delay, DACT_KILL, view->dest, panel);
delayed_action(view->delay, DACT_CLOSE_MINOR, {}, panel);
delayed_action(view->delay, DACT_TRY_KILL, view->dest, panel);
break;
case INTV_SURE_TO_KILL:
switch (view->user_action){
case 0:
delayed_action(view->delay, DACT_KILL, view->dest, panel);
delayed_action(view->delay, DACT_CLOSE_MINOR, {}, panel);
break;
case 1:
delayed_action(view->delay, DACT_CLOSE_MINOR, {}, panel);
break;
case 2:
delayed_action(view->delay, DACT_SAVE, view->dest, panel);
delayed_action(view->delay, DACT_KILL, view->dest, panel);
delayed_action(view->delay, DACT_CLOSE_MINOR, {}, panel);
break;
}
break;
}
}
@ -119,7 +108,7 @@ step_draw_int_view(Interactive_View *view, Render_Target *target, i32_Rect rect,
begin_layout(&layout, rect);
bool32 new_dir = 0;
bool32 file_selected = 0;
bool32 complete = 0;
terminate_with_null(&view->query);
do_label(&state, &layout, view->query.str, 1.f);
@ -127,7 +116,7 @@ step_draw_int_view(Interactive_View *view, Render_Target *target, i32_Rect rect,
switch (view->interaction){
case INTV_SYS_FILE_LIST:
if (do_file_list_box(&state, &layout, view->hot_directory, 0,
&new_dir, &file_selected, 0)){
&new_dir, &complete, 0)){
result = 1;
}
if (new_dir){
@ -136,13 +125,55 @@ step_draw_int_view(Interactive_View *view, Render_Target *target, i32_Rect rect,
break;
case INTV_LIVE_FILE_LIST:
if (do_live_file_list_box(&state, &layout, view->working_set, &view->dest, &file_selected)){
if (do_live_file_list_box(&state, &layout, view->working_set, &view->dest, &complete)){
result = 1;
}
break;
case INTV_SURE_TO_KILL_INTER:
{
i32 action = -1;
char s_[256];
String s = make_fixed_width_string(s_);
append(&s, view->dest);
append(&s, " has unsaved changes, kill it?");
do_label(&state, &layout, s.str, 1.f);
i32 id = 0;
if (do_list_option(++id, &state, &layout, make_lit_string("(Y)es"))){
action = 0;
}
if (do_list_option(++id, &state, &layout, make_lit_string("(N)o"))){
action = 1;
}
if (do_list_option(++id, &state, &layout, make_lit_string("(S)ave and kill"))){
action = 2;
}
if (action == -1 && input_stage){
i32 key_count = user_input->keys.count;
for (i32 i = 0; i < key_count; ++i){
Key_Event_Data key = user_input->keys.keys[i];
switch (key.character){
case 'y': case 'Y': action = 0; break;
case 'n': case 'N': action = 1; break;
case 's': case 'S': action = 2; break;
}
if (action == -1 && key.keycode == state.codes->esc) action = 1;
if (action != -1) break;
}
}
if (action != -1){
complete = 1;
view->user_action = action;
}
}break;
}
if (file_selected){
if (complete){
interactive_view_complete(view);
}
@ -156,6 +187,7 @@ step_draw_int_view(Interactive_View *view, Render_Target *target, i32_Rect rect,
DO_VIEW_SIG(do_interactive_view){
i32 result = 0;
view->mouse_cursor_type = APP_MOUSE_CURSOR_ARROW;
Interactive_View *int_view = (Interactive_View*)view;
switch (message){
case VMSG_STEP: case VMSG_DRAW:

View File

@ -69,7 +69,7 @@ struct View{
Command_Map *map;
Do_View_Function *do_view;
Handle_Command_Function *handle_command;
General_Memory *general;
Mem_Options *mem;
i32 type;
i32 block_size;
Application_Mouse_Cursor mouse_cursor_type;
@ -173,7 +173,7 @@ live_set_get_view(Live_Views *live_set, i32 i){
}
internal View*
live_set_alloc_view(Live_Views *live_set, General_Memory *general){
live_set_alloc_view(Live_Views *live_set, Mem_Options *mem){
Assert(live_set->count < live_set->max);
View *result = 0;
result = live_set->free_view;
@ -181,7 +181,7 @@ live_set_alloc_view(Live_Views *live_set, General_Memory *general){
memset(result, 0, live_set->stride);
++live_set->count;
result->is_active = 1;
result->general = general;
result->mem = mem;
return result;
}