API started
parent
852a7fd71c
commit
c38d6ce47b
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
2520
4ed_file_view.cpp
2520
4ed_file_view.cpp
File diff suppressed because it is too large
Load Diff
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue