post-stream, got miblo incrementors/decrementors started. added settings for code presentation. adding config file for code wrapping

This commit is contained in:
Allen Webster 2016-10-27 19:45:41 -04:00
parent a6a6957ba9
commit 39be882693
18 changed files with 618 additions and 142 deletions

File diff suppressed because one or more lines are too long

View File

@ -511,7 +511,7 @@ get_indent_lines_whole_tokens(Application_Links *app, Buffer_Summary *buffer, Cp
for (;line_start > 0;){
int32_t line_start_pos = 0;
Cpp_Token *token = get_first_token_at_line(app, buffer, tokens, line_start, &line_start_pos);
if (token->start < line_start_pos){
if (token && token->start < line_start_pos){
line_start = buffer_get_line_index(app, buffer, token->start);
}
else{

View File

@ -55,6 +55,7 @@
#define DIRECTORY_GET_HOT_SIG(n) int32_t n(Application_Links *app, char *out, int32_t capacity)
#define GET_FILE_LIST_SIG(n) File_List n(Application_Links *app, char *dir, int32_t len)
#define FREE_FILE_LIST_SIG(n) void n(Application_Links *app, File_List list)
#define SET_GUI_UP_DOWN_KEYS_SIG(n) void n(Application_Links *app, int16_t up_key, int16_t down_key)
#define MEMORY_ALLOCATE_SIG(n) void* n(Application_Links *app, int32_t size)
#define MEMORY_SET_PROTECTION_SIG(n) bool32 n(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags)
#define MEMORY_FREE_SIG(n) void n(Application_Links *app, void *ptr, int32_t size)
@ -122,6 +123,7 @@ typedef GET_THEME_COLORS_SIG(Get_Theme_Colors_Function);
typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot_Function);
typedef GET_FILE_LIST_SIG(Get_File_List_Function);
typedef FREE_FILE_LIST_SIG(Free_File_List_Function);
typedef SET_GUI_UP_DOWN_KEYS_SIG(Set_GUI_Up_Down_Keys_Function);
typedef MEMORY_ALLOCATE_SIG(Memory_Allocate_Function);
typedef MEMORY_SET_PROTECTION_SIG(Memory_Set_Protection_Function);
typedef MEMORY_FREE_SIG(Memory_Free_Function);
@ -191,6 +193,7 @@ Get_Theme_Colors_Function *get_theme_colors;
Directory_Get_Hot_Function *directory_get_hot;
Get_File_List_Function *get_file_list;
Free_File_List_Function *free_file_list;
Set_GUI_Up_Down_Keys_Function *set_gui_up_down_keys;
Memory_Allocate_Function *memory_allocate;
Memory_Set_Protection_Function *memory_set_protection;
Memory_Free_Function *memory_free;
@ -259,6 +262,7 @@ Get_Theme_Colors_Function *get_theme_colors_;
Directory_Get_Hot_Function *directory_get_hot_;
Get_File_List_Function *get_file_list_;
Free_File_List_Function *free_file_list_;
Set_GUI_Up_Down_Keys_Function *set_gui_up_down_keys_;
Memory_Allocate_Function *memory_allocate_;
Memory_Set_Protection_Function *memory_set_protection_;
Memory_Free_Function *memory_free_;
@ -335,6 +339,7 @@ app_links->get_theme_colors_ = Get_Theme_Colors;\
app_links->directory_get_hot_ = Directory_Get_Hot;\
app_links->get_file_list_ = Get_File_List;\
app_links->free_file_list_ = Free_File_List;\
app_links->set_gui_up_down_keys_ = Set_GUI_Up_Down_Keys;\
app_links->memory_allocate_ = Memory_Allocate;\
app_links->memory_set_protection_ = Memory_Set_Protection;\
app_links->memory_free_ = Memory_Free;\
@ -403,6 +408,7 @@ static inline void get_theme_colors(Application_Links *app, Theme_Color *colors,
static inline int32_t directory_get_hot(Application_Links *app, char *out, int32_t capacity){return(app->directory_get_hot(app, out, capacity));}
static inline File_List get_file_list(Application_Links *app, char *dir, int32_t len){return(app->get_file_list(app, dir, len));}
static inline void free_file_list(Application_Links *app, File_List list){(app->free_file_list(app, list));}
static inline void set_gui_up_down_keys(Application_Links *app, int16_t up_key, int16_t down_key){(app->set_gui_up_down_keys(app, up_key, down_key));}
static inline void* memory_allocate(Application_Links *app, int32_t size){return(app->memory_allocate(app, size));}
static inline bool32 memory_set_protection(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags){return(app->memory_set_protection(app, ptr, size, flags));}
static inline void memory_free(Application_Links *app, void *ptr, int32_t size){(app->memory_free(app, ptr, size));}
@ -471,6 +477,7 @@ static inline void get_theme_colors(Application_Links *app, Theme_Color *colors,
static inline int32_t directory_get_hot(Application_Links *app, char *out, int32_t capacity){return(app->directory_get_hot_(app, out, capacity));}
static inline File_List get_file_list(Application_Links *app, char *dir, int32_t len){return(app->get_file_list_(app, dir, len));}
static inline void free_file_list(Application_Links *app, File_List list){(app->free_file_list_(app, list));}
static inline void set_gui_up_down_keys(Application_Links *app, int16_t up_key, int16_t down_key){(app->set_gui_up_down_keys_(app, up_key, down_key));}
static inline void* memory_allocate(Application_Links *app, int32_t size){return(app->memory_allocate_(app, size));}
static inline bool32 memory_set_protection(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags){return(app->memory_set_protection_(app, ptr, size, flags));}
static inline void memory_free(Application_Links *app, void *ptr, int32_t size){(app->memory_free_(app, ptr, size));}

View File

@ -124,9 +124,88 @@ CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line){
exec_command(app, seek_end_of_line);
}
static bool32 enable_code_wrapping = 1;
static int32_t default_wrap_width = 672;
HOOK_SIG(my_start){
init_memory(app);
{
FILE *file = fopen("config.4coder", "rb");
if (file){
Temp_Memory temp = begin_temp_memory(&global_part);
fseek(file, 0, SEEK_END);
int32_t size = ftell(file);
char *mem = (char*)push_block(&global_part, size+1);
fseek(file, 0, SEEK_SET);
fread(mem, 1, size+1, file);
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, HAS_NULL_TERM, &array, NO_OUT_LIMIT);
if (result == LexResult_Finished){
for (int32_t i = 0; i < array.count; ++i){
int32_t read_setting_failed = 1;
Cpp_Token id_token = array.tokens[i];
if (id_token.type == CPP_TOKEN_IDENTIFIER){
++i;
if (i < array.count){
Cpp_Token eq_token = array.tokens[i];
if (eq_token.type == CPP_TOKEN_EQEQ){
++i;
if (i < array.count){
Cpp_Token val_token = array.tokens[i];
{
++i;
if (i < array.count){
Cpp_Token semicolon_token = array.tokens[i];
if (semicolon_token.type == CPP_TOKEN_SEMICOLON){
read_setting_failed = 0;
String id = make_string(mem + id_token.start, id_token.size);
if (match(id, "enable_code_wrapping")){
if (val_token.type == CPP_TOKEN_BOOLEAN_CONSTANT){
String val = make_string(mem + val_token.start, val_token.size);
if (val.str[0] == 't'){
enable_code_wrapping = 1;
}
else{
enable_code_wrapping = 0;
}
}
}
}
}
}
}
}
}
}
if (read_setting_failed){
for (; i < array.count; ++i){
Cpp_Token token = array.tokens[i];
if (token.type == CPP_TOKEN_SEMICOLON){
break;
}
}
}
}
}
end_temp_memory(temp);
}
}
change_theme(app, literal("4coder"));
change_font(app, literal("Liberation Sans"), true);
@ -135,6 +214,12 @@ HOOK_SIG(my_start){
exec_command(app, change_active_panel);
exec_command(app, hide_scrollbar);
{
View_Summary view = get_active_view(app, AccessAll);
int32_t width = view.file_region.x1 - view.file_region.x0;
default_wrap_width = width - 40;
}
// Theme options:
// "4coder"
// "Handmade Hero"
@ -214,8 +299,13 @@ OPEN_FILE_HOOK_SIG(my_file_settings){
buffer_set_setting(app, &buffer, BufferSetting_Lex, treat_as_code);
buffer_set_setting(app, &buffer, BufferSetting_WrapLine, wrap_lines);
buffer_set_setting(app, &buffer, BufferSetting_MapID,
(treat_as_code)?((int32_t)my_code_map):((int32_t)mapid_file));
buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, default_wrap_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 << 20)){
buffer_set_setting(app, &buffer, BufferSetting_WrapLine, 1);
buffer_set_setting(app, &buffer, BufferSetting_VirtualWhitespace, 1);
}
// no meaning for return
return(0);

View File

@ -1354,16 +1354,14 @@ buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int32_
int32_t chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
int32_t no_hard;
int32_t still_looping;
char at_pos;
--pos;
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
// Step 1: Find the first non-whitespace character
// behind the current position.
still_looping = true;
do{
int32_t still_looping = 1;
while (still_looping){
for (; pos >= stream.start; --pos){
at_pos = stream.data[pos];
if (!char_is_whitespace(at_pos)){
@ -1371,7 +1369,7 @@ buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int32_
}
}
still_looping = backward_stream_chunk(&stream);
} while(still_looping);
}
double_break_1:;
// Step 2: Continue scanning backward, at each '\n'
@ -1379,7 +1377,7 @@ buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int32_
// no_hard to true, set it back to false if a
// non-whitespace character is discovered before
// the next '\n'
no_hard = false;
int32_t no_hard = false;
while (still_looping){
for (; pos >= stream.start; --pos){
at_pos = stream.data[pos];
@ -2119,15 +2117,11 @@ CUSTOM_COMMAND_SIG(delete_word){
CUSTOM_COMMAND_SIG(snipe_token_or_word){
uint32_t access = AccessOpen;
View_Summary view;
Buffer_Summary buffer;
int32_t pos1, pos2;
View_Summary view = get_active_view(app, access);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
view = get_active_view(app, access);
buffer = get_buffer(app, view.buffer_id, access);
pos1 = buffer_boundary_seek(app, &buffer, view.cursor.pos, false, BoundaryToken | BoundaryWhitespace);
pos2 = buffer_boundary_seek(app, &buffer, pos1, true, BoundaryToken | BoundaryWhitespace);
int32_t pos1 = buffer_boundary_seek(app, &buffer, view.cursor.pos, false, BoundaryToken | BoundaryWhitespace);
int32_t pos2 = buffer_boundary_seek(app, &buffer, pos1, true, BoundaryToken | BoundaryWhitespace);
Range range = make_range(pos1, pos2);
buffer_replace_range(app, &buffer, range.start, range.end, 0, 0);

View File

@ -123,6 +123,18 @@ ENUM(int32_t, Event_Message_Type_ID){
EventMessage_CloseView
};
/* DOC(A Wrap_Indicator_Mode is used in the buffer setting BufferSetting_WrapIndicator to specify how to indicate that line has been wrapped.) */
ENUM(int32_t, Wrap_Indicator_Mode){
/* DOC(WrapIndicator_Hide tells the buffer rendering system not to put any indicator on wrapped lines.) */
WrapIndicator_Hide,
/* DOC(WrapIndicator_Show_After_Line tells the buffer rendering system to put a backslash indicator on wrapped lines right after the last character of the line.) */
WrapIndicator_Show_After_Line,
/* DOC(WrapIndicator_Show_At_Wrap_Edge tells the buffer rendering system to put a backslash indicator on wrapped lines aligned with the wrap position for that line.) */
WrapIndicator_Show_At_Wrap_Edge,
};
/* DOC(A Buffer_Setting_ID names a setting in a buffer.) */
ENUM(int32_t, Buffer_Setting_ID){
/* DOC(BufferSetting_Null is not a valid setting, it is reserved to detect errors.) */
@ -145,6 +157,12 @@ ENUM(int32_t, Buffer_Setting_ID){
best behavior try to only set this setting once per frame, if possible.) */
BufferSetting_WrapPosition,
/* DOC(The BufferSetting_MinimumBaseWrapPosition setting is used to increase the with in pixels allotted to a line for wrapping, by setting a minimum position away from the base of the line. The base of a line is always 0, or the left hand side of the view, in text files. In code files the base of a line is the amount the line is shifted to the right due to brace nesting. This setting allows for deeply nested code to remain readable by ensuring lines deep in the nesting get some minimum base width which may be more wrapping space than the non base adjusted wrap position would have allowed. In any case where the (default wrapping position) is greater than (the base + minimum base position), the larger ) the default will still be used. */
BufferSetting_MinimumBaseWrapPosition,
/* DOC(The BufferSetting_WrapIndicator setting is used to specify how wrapped lines should be marked so the user can see that they have been wrapped. The value should be one of the values in the Wrap_Indicator_Mode enum.) DOC_SEE(Wrap_Indicator_Mode) */
BufferSetting_WrapIndicator,
/* DOC(The BufferSetting_MapID setting specifies the id of the command map that should be
active when a buffer is active.) */
BufferSetting_MapID,

View File

@ -954,21 +954,15 @@ cpp_lex_nonalloc_no_null_out_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
#define NO_OUT_LIMIT ((int32_t)(-1))
FCPP_LINK Cpp_Lex_Result
cpp_lex_step(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size, int32_t full_size,
Cpp_Token_Array *token_array_out, int32_t max_tokens_out)/*
cpp_lex_step(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size, int32_t full_size, Cpp_Token_Array *token_array_out, int32_t max_tokens_out)/*
DOC_PARAM(S_ptr, The lexer state. Go to the Cpp_Lex_Data section to see how to initialize the state.)
DOC_PARAM(chunk, The first or next chunk of the file being lexed.)
DOC_PARAM(size, The number of bytes in the chunk including the null terminator if the chunk ends in a null terminator.
If the chunk ends in a null terminator the system will interpret it as the end of the file.)
DOC_PARAM(full_size, If the final chunk is not null terminated this parameter should specify the length of the
file in bytes. To rely on an eventual null terminator use HAS_NULL_TERM for this parameter.)
DOC_PARAM(size, The number of bytes in the chunk including the null terminator if the chunk ends in a null terminator. If the chunk ends in a null terminator the system will interpret it as the end of the file.)
DOC_PARAM(full_size, If the final chunk is not null terminated this parameter should specify the length of the file in bytes. To rely on an eventual null terminator use HAS_NULL_TERM for this parameter.)
DOC_PARAM(token_array_out, The token array structure that will receive the tokens output by the lexer.)
DOC_PARAM(max_tokens_out, The maximum number of tokens to be output to the token array. To rely on the
max built into the token array pass NO_OUT_LIMIT here.)
DOC(This call is the primary interface of the lexing system. It is quite general so it can be used in
a lot of different ways. I will explain the general rules first, and then give some examples of common
ways it might be used.
DOC(This call is the primary interface of the lexing system. It is quite general so it can be used in a lot of different ways. I will explain the general rules first, and then give some examples of common ways it might be used.
First a lexing state, Cpp_Lex_Data, must be initialized. The file to lex must be read into N contiguous chunks
of memory. An output Cpp_Token_Array must be allocated and initialized with the appropriate count and max_count

View File

@ -1733,6 +1733,10 @@ App_Init_Sig(app_init){
vars->cli_processes.procs = push_array(partition, CLI_Process, max_children);
vars->cli_processes.max = max_children;
vars->cli_processes.count = 0;
// NOTE(allen): init GUI keys
models->user_up_key = key_up;
models->user_down_key = key_down;
}
internal i32

View File

@ -787,6 +787,24 @@ DOC_SEE(Buffer_Setting_ID)
}
}break;
case BufferSetting_MinimumBaseWrapPosition:
{
i32 new_value = value;
if (new_value < 0){
new_value = 0;
}
if (new_value != file->settings.minimum_base_display_width){
i16 font_id = file->settings.font_id;
Render_Font *font = get_font_info(models->font_set, font_id)->font;
file_set_minimum_base_display_width_and_fix_cursor(system, models, file, new_value, (f32)font->height, font->advance_data);
}
}break;
case BufferSetting_WrapIndicator:
{
file->settings.wrap_indicator = value;
}break;
case BufferSetting_MapID:
{
if (value == mapid_global){
@ -2226,5 +2244,14 @@ DOC(After this call the file list passed in should not be read or written to.)
system->set_file_list(&list, make_string(0, 0));
}
API_EXPORT void
Set_GUI_Up_Down_Keys(Application_Links *app, int16_t up_key, int16_t down_key)
{
Command_Data *cmd = (Command_Data*)app->cmd_context;
Models *models = cmd->models;
models->user_up_key = up_key;
models->user_down_key = down_key;
}
// BOTTOM

View File

@ -89,6 +89,9 @@ struct Models{
b32 keep_playing;
Debug_Data debug;
i16 user_up_key;
i16 user_down_key;
};
// BOTTOM

View File

@ -92,6 +92,7 @@ struct Editing_File_Settings{
i32 base_map_id;
i32 display_width;
i32 minimum_base_display_width;
i32 wrap_indicator;
b32 dos_write_mode;
b32 virtual_white;
i16 font_id;
@ -439,22 +440,21 @@ editing_file_zero(){
internal Editing_File*
working_set_alloc(Working_Set *working_set){
Editing_File *result = 0;
File_Node *node;
Buffer_Slot_ID id;
if (working_set->file_count < working_set->file_max){
node = working_set->free_sentinel.next;
File_Node *node = working_set->free_sentinel.next;
Assert(node != &working_set->free_sentinel);
result = (Editing_File*)node;
dll_remove(node);
id = result->id;
Buffer_Slot_ID id = result->id;
*result = editing_file_zero();
result->id = id;
result->unique_buffer_id = ++working_set->unique_file_counter;
dll_insert(&working_set->used_sentinel, node);
result->settings.display_width = working_set->default_display_width;
result->settings.minimum_base_display_width = working_set->default_minimum_base_display_width;
result->settings.wrap_indicator = WrapIndicator_Show_At_Wrap_Edge;
++working_set->file_count;
}

View File

@ -1861,6 +1861,12 @@ file_set_display_width_and_fix_cursor(System_Functions *system, Models *models,
file_measure_wraps_and_fix_cursor(system, models, file, font_height, adv);
}
internal void
file_set_minimum_base_display_width_and_fix_cursor(System_Functions *system, Models *models, Editing_File *file, i32 minimum_base_display_width, f32 font_height, f32 *adv){
file->settings.minimum_base_display_width = minimum_base_display_width;
file_measure_wraps_and_fix_cursor(system, models, file, font_height, adv);
}
//
//
//
@ -4893,6 +4899,9 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
GUI_id scroll_context = {0};
scroll_context.id[1] = VUI_Interactive + ((u64)view->interaction << 32);
i16 user_up_key = models->user_up_key;
i16 user_down_key = models->user_down_key;
switch (view->interaction){
case IInt_Sys_File_List:
{
@ -4954,9 +4963,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
if (gui_begin_list(target, id, view->list_i, 0,
snap_into_view, &update)){
// TODO(allen): Allow me to handle key consumption correctly here!
gui_standard_list(target, id, &view->gui_scroll,
view->scroll_region,
&keys, &view->list_i, &update);
gui_standard_list(target, id, &view->gui_scroll, view->scroll_region, &keys, &view->list_i, &update, user_up_key, user_down_key);
}
begin_exhaustive_loop(&loop, hdir);
@ -5038,15 +5045,11 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
if (gui_scroll_was_activated(target, scroll_context)){
snap_into_view = 1;
}
gui_begin_scrollable(target, scroll_context, view->gui_scroll,
9 * view->line_height, show_scrollbar);
gui_begin_scrollable(target, scroll_context, view->gui_scroll, 9 * view->line_height, show_scrollbar);
id.id[0] = (u64)(working_set) + 1;
if (gui_begin_list(target, id, view->list_i,
0, snap_into_view, &update)){
gui_standard_list(target, id, &view->gui_scroll,
view->scroll_region,
&keys, &view->list_i, &update);
if (gui_begin_list(target, id, view->list_i, 0, snap_into_view, &update)){
gui_standard_list(target, id, &view->gui_scroll, view->scroll_region, &keys, &view->list_i, &update, user_up_key, user_down_key);
}
{
@ -5940,7 +5943,7 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
params.font_height = (f32)line_height;
params.adv = advance_data;
params.virtual_white = file->settings.virtual_white;
params.wrap_slashes = BRWrapSlash_Show_At_Wrap_Edge;
params.wrap_slashes = file->settings.wrap_indicator;
Buffer_Render_State state = {0};
Buffer_Layout_Stop stop = {0};

View File

@ -1258,7 +1258,7 @@ gui_do_jump(GUI_Target *target, GUI_View_Jump jump, GUI_Scroll_Vars vars){
internal void
gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect scroll_region,
Key_Summary *keys, i32 *list_i, GUI_Item_Update *update,
i16 key_user_up = 0, i16 key_user_down = 0){
i16 user_up_key, i16 user_down_key){
if (update->has_adjustment){
*list_i = update->adjustment_value;
@ -1276,10 +1276,10 @@ gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect
for (i32 j = 0; j < keys->count; ++j){
i16 key = keys->keys[j].keycode;
if (key == key_up || key == key_user_up){
if (key == user_up_key){
--*list_i;
}
else if (key == key_down || key == key_user_down){
else if (key == user_down_key){
++*list_i;
}
else if (key == '\n' || key == '\t'){

View File

@ -90,10 +90,8 @@
;
; [X] query buffer font info
; [X] issues with drive letters
; [] ad hoc call for setting up/down keys for interactive screens
; [] option to not open *messages* every startup
; [] API docs have duplicate ids?
; [] miblo's various number editors
; [X] ad hoc call for setting up/down keys for interactive screens
; [X] miblo's various number editors
; [] decent options for indentation rules for text & presentation
;
@ -194,6 +192,8 @@
; [] support full length unicode file names
; [] user file bar string
; [] option to not open *messages* every startup
; [] API docs have duplicate ids?
; [] API docs as text file
; [] read only files
; [] option to hide hidden files

View File

@ -1188,12 +1188,6 @@ struct Buffer_Render_Params{
i32 wrap_slashes;
};
enum Wrap_Slash_Mode{
BRWrapSlash_Hide,
BRWrapSlash_Show_After_Line,
BRWrapSlash_Show_At_Wrap_Edge,
};
struct Buffer_Render_State{
Buffer_Stream_Type stream;
b32 still_looping;
@ -1295,12 +1289,12 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
if (params.wrapped){
switch (params.wrap_slashes){
case BRWrapSlash_Show_After_Line:
case WrapIndicator_Show_After_Line:
{
S.write = write_render_item(S.write, S.i-1, '\\', BRFlag_Ghost_Character);
}break;
case BRWrapSlash_Show_At_Wrap_Edge:
case WrapIndicator_Show_At_Wrap_Edge:
{
if (S.write.x < shift_x + params.width){
S.write.x = shift_x + params.width;

View File

@ -1,47 +1,3 @@
@echo off
REM pushd W:\4ed\meta
REM cl %OPTS% ..\code\readme_generator.c /Fereadmegen
REM popd
REM pushd W:\4ed\code
REM ..\meta\readmegen
REM call "build_all.bat" /O2 /DFRED_KEEP_ASSERT /Zi
REM del ..\current_dist\4coder\*.html
REM copy ..\build\4ed.exe ..\current_dist\4coder\*
REM copy ..\build\4ed.pdb ..\current_dist\4coder\*
REM copy ..\build\4ed_app.dll ..\current_dist\4coder\*
REM copy ..\build\4ed_app.pdb ..\current_dist\4coder\*
REM copy ..\data\* ..\current_dist\4coder\*
REM copy README.txt ..\current_dist\4coder\*
REM copy TODO.txt ..\current_dist\4coder\*
REM del ..\current_dist\4coder\.4coder_settings
REM call "build_all.bat" /O2 /DFRED_SUPER /DFRED_KEEP_ASSERT /Zi
REM del ..\current_dist\4coder\*.html
REM copy ..\build\4ed.exe ..\current_dist_super\4coder\*
REM copy ..\build\4ed.pdb ..\current_dist_super\4coder\*
REM copy ..\build\4ed_app.dll ..\current_dist_super\4coder\*
REM copy ..\build\4ed_app.pdb ..\current_dist_super\4coder\*
REM copy buildsuper.bat ..\current_dist_super\4coder\*
REM copy ..\data\* ..\current_dist_super\4coder\*
REM del ..\current_dist_super\4coder\basic.cpp
REM copy 4coder_*.h ..\current_dist_super\4coder\*
REM copy 4coder_*.cpp ..\current_dist_super\4coder\*
REM copy README.txt ..\current_dist_super\4coder\*
REM copy TODO.txt ..\current_dist_super\4coder\*
REM copy ..\current_dist\4coder\3rdparty\* ..\current_dist_super\4coder\3rdparty\*
REM del ..\current_dist_super\4coder\*.lib
REM del ..\current_dist_super\4coder\*.obj
REM del ..\current_dist_super\4coder\4coder_custom.dll
REM del ..\current_dist_super\4coder\.4coder_settings
REM copy 4coder_API.html ..\current_dist_super\*
REM del ..\current_dist_power\power\* /F /Q
REM copy power\* ..\current_dist_power\power\*
REM popd
build.bat /DPACKAGE

View File

@ -10,6 +10,8 @@
# define BIND_4CODER_TESTS(context) ((void)context)
#endif
#include "4coder_miblo_numbers.cpp"
#include <string.h>
CUSTOM_COMMAND_SIG(kill_rect){
@ -697,6 +699,13 @@ get_bindings(void *data, int size){
begin_map(context, mapid_file);
bind(context, 'k', MDFR_ALT, kill_rect);
bind(context, ' ', MDFR_ALT, multi_line_edit);
bind(context, key_page_up, MDFR_ALT, miblo_increment_time_stamp);
bind(context, key_page_down, MDFR_ALT, miblo_decrement_time_stamp);
bind(context, key_home, MDFR_ALT, miblo_increment_time_stamp_minute);
bind(context, key_end, MDFR_ALT, miblo_decrement_time_stamp_minute);
end_map(context);
begin_map(context, my_code_map);

View File

@ -0,0 +1,381 @@
#if !defined(MIBLO_NUMBERS_4CODER)
#define MIBLO_NUMBERS_4CODER
// TODO(allen): thevaber number converter idea
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){
int32_t result = 0;
char current = buffer_get_char(app, buffer, start_pos);
if (char_is_numeric(current)){
char chunk[1024];
int32_t chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
int32_t pos = start_pos;
int32_t pos1 = 0;
int32_t pos2 = 0;
if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){
int32_t still_looping = 1;
while (still_looping){
for (; pos >= stream.start; --pos){
char at_pos = stream.data[pos];
if (!char_is_numeric(at_pos)){
++pos;
goto double_break_1;
}
}
still_looping = backward_stream_chunk(&stream);
}
double_break_1:;
pos1 = pos;
if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){
still_looping = 1;
while (still_looping){
for (; pos < stream.end; ++pos){
char at_pos = stream.data[pos];
if (!char_is_numeric(at_pos)){
goto double_break_2;
}
}
still_looping = forward_stream_chunk(&stream);
}
double_break_2:;
pos2 = pos;
result = 1;
*numeric_start = pos1;
*numeric_end = pos2;
}
}
}
return(result);
}
struct Miblo_Number_Info{
int32_t start, end;
int32_t x;
};
static int32_t
get_numeric_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t pos, Miblo_Number_Info *info){
int32_t result = 0;
int32_t numeric_start = 0, numeric_end = 0;
if (get_numeric_string_at_cursor(app, buffer, pos, &numeric_start, &numeric_end)){
char numeric_string[1024];
String str = make_string(numeric_string, numeric_end - numeric_start, sizeof(numeric_string));
if (str.size < str.memory_size){
buffer_read_range(app, buffer, numeric_start, numeric_end, numeric_string);
int32_t x = str_to_int(str);
int_to_str(&str, x+1);
info->start = numeric_start;
info->end = numeric_end;
info->x = x;
result = 1;
}
}
return(result);
}
CUSTOM_COMMAND_SIG(miblo_increment_basic){
View_Summary view = get_active_view(app, AccessOpen);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
Miblo_Number_Info number = {0};
if (get_numeric_at_cursor(app, &buffer, view.cursor.pos, &number)){
char str_space[1024];
String str = make_fixed_width_string(str_space);
int_to_str(&str, number.x + 1);
buffer_replace_range(app, &buffer, number.start, number.end, str.str, str.size);
view_set_cursor(app, &view, seek_pos(number.start + str.size - 1), 1);
}
}
CUSTOM_COMMAND_SIG(miblo_decrement_basic){
View_Summary view = get_active_view(app, AccessOpen);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
Miblo_Number_Info number = {0};
if (get_numeric_at_cursor(app, &buffer, view.cursor.pos, &number)){
char str_space[1024];
String str = make_fixed_width_string(str_space);
int_to_str(&str, number.x - 1);
buffer_replace_range(app, &buffer, number.start, number.end, str.str, str.size);
view_set_cursor(app, &view, seek_pos(number.start + str.size - 1), 1);
}
}
// NOTE(allen): miblo time stamp format
// (h+:)?m?m:ss
static int32_t
get_timestamp_string_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t start_pos, int32_t *timestamp_start, int32_t *timestamp_end){
int32_t result = 0;
char current = buffer_get_char(app, buffer, start_pos);
if (char_is_numeric(current) || current == ':'){
char chunk[1024];
int32_t chunk_size = sizeof(chunk);
Stream_Chunk stream = {0};
int32_t pos = start_pos;
int32_t pos1 = 0;
int32_t pos2 = 0;
if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){
int32_t still_looping = 1;
while (still_looping){
for (; pos >= stream.start; --pos){
char at_pos = stream.data[pos];
if (!(char_is_numeric(at_pos) || at_pos == ':')){
++pos;
goto double_break_1;
}
}
still_looping = backward_stream_chunk(&stream);
}
double_break_1:;
pos1 = pos;
if (init_stream_chunk(&stream, app, buffer, start_pos, chunk, chunk_size)){
still_looping = 1;
while (still_looping){
for (; pos < stream.end; ++pos){
char at_pos = stream.data[pos];
if (!(char_is_numeric(at_pos) || at_pos == ':')){
goto double_break_2;
}
}
still_looping = forward_stream_chunk(&stream);
}
double_break_2:;
pos2 = pos;
result = 1;
*timestamp_start = pos1;
*timestamp_end = pos2;
}
}
}
return(result);
}
struct Miblo_Timestamp{
int32_t hour, minute, second;
};
static Miblo_Timestamp null_miblo_timestamp = {0};
enum{
MIBLO_SECOND,
MIBLO_MINUTE,
MIBLO_HOUR
};
static Miblo_Timestamp
increment_timestamp(Miblo_Timestamp t, int32_t type, int32_t amt){
Miblo_Timestamp r = t;
switch (type){
case MIBLO_SECOND:
r.second += amt;
amt = 0;
// TODO(allen): someday do the math, instead of being lazy.
while (r.second < 0){
--amt;
r.second += 60;
}
while (r.second >= 60){
++amt;
r.second -= 60;
}
case MIBLO_MINUTE:
r.minute += amt;
amt = 0;
// TODO(allen): someday do the math, instead of being lazy.
while (r.minute < 0){
--amt;
r.minute += 60;
}
while (r.minute >= 60){
++amt;
r.minute -= 60;
}
case MIBLO_HOUR:
r.hour += amt;
}
return(r);
}
static void
timestamp_to_str(String *dest, Miblo_Timestamp t){
dest->size = 0;
if (t.hour > 0){
append_int_to_str(dest, t.hour);
append(dest, ":");
}
if (t.minute >= 10){
append_int_to_str(dest, t.minute);
}
else if (t.hour > 0){
append(dest, "0");
append_int_to_str(dest, t.minute);
}
else{
append_int_to_str(dest, t.minute);
}
append(dest, ":");
if (t.second >= 10){
append_int_to_str(dest, t.second);
}
else{
append(dest, "0");
append_int_to_str(dest, t.second);
}
}
struct Miblo_Timestamp_Info{
int32_t start, end;
Miblo_Timestamp time;
};
static int32_t
get_timestamp_at_cursor(Application_Links *app, Buffer_Summary *buffer, int32_t pos, Miblo_Timestamp_Info *info){
int32_t result = 0;
int32_t timestamp_start = 0, timestamp_end = 0;
if (get_timestamp_string_at_cursor(app, buffer, pos, &timestamp_start, &timestamp_end)){
char timestamp_string[1024];
String str = make_string(timestamp_string, timestamp_end - timestamp_start, sizeof(timestamp_string));
if (str.size < str.memory_size){
buffer_read_range(app, buffer, timestamp_start, timestamp_end, timestamp_string);
int32_t count_colons = 0;
for (int32_t i = 0; i < str.size; ++i){
if (str.str[i] == ':'){
++count_colons;
}
}
if (count_colons == 1 || count_colons == 2){
Miblo_Timestamp t = {0};
int32_t success = 0;
int32_t i = 0;
int32_t number_start[3], number_end[3];
for (int32_t k = 0; k < 3; ++k){
number_start[k] = i;
for (; i <= str.size; ++i){
if (i == str.size || str.str[i] == ':'){
number_end[k] = i;
break;
}
}
++i;
if (i >= timestamp_end){
break;
}
}
if (count_colons == 2){
t.hour = str_to_int(make_string(str.str + number_start[0], number_end[0] - number_start[0]));
if (number_end[1] - number_start[1] == 2){
t.minute = str_to_int(make_string(str.str + number_start[1], number_end[1] - number_start[1]));
if (number_end[2] - number_start[2] == 2){
t.second = str_to_int(make_string(str.str + number_start[2], number_end[2] - number_start[2]));
success = 1;
}
}
}
else{
if (number_end[0] - number_start[0] == 2 || number_end[0] - number_start[0] == 1){
t.minute = str_to_int(make_string(str.str + number_start[0], number_end[0] - number_start[0]));
if (number_end[1] - number_start[1] == 2){
t.second = str_to_int(make_string(str.str + number_start[1], number_end[1] - number_start[1]));
success = 1;
}
}
}
if (success){
info->start = timestamp_start;
info->end = timestamp_end;
info->time = t;
result = 1;
}
}
}
}
return(result);
}
static void
miblo_time_stamp_alter(Application_Links *app, int32_t unit_type, int32_t amt){
View_Summary view = get_active_view(app, AccessOpen);
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
Miblo_Timestamp_Info timestamp = {0};
if (get_timestamp_at_cursor(app, &buffer, view.cursor.pos, &timestamp)){
char str_space[1024];
String str = make_fixed_width_string(str_space);
Miblo_Timestamp inc_timestamp = increment_timestamp(timestamp.time, unit_type, amt);
timestamp_to_str(&str, inc_timestamp);
buffer_replace_range(app, &buffer, timestamp.start, timestamp.end, str.str, str.size);
view_set_cursor(app, &view, seek_pos(timestamp.start + str.size - 1), 1);
}
}
CUSTOM_COMMAND_SIG(miblo_increment_time_stamp){
miblo_time_stamp_alter(app, MIBLO_SECOND, 1);
}
CUSTOM_COMMAND_SIG(miblo_decrement_time_stamp){
miblo_time_stamp_alter(app, MIBLO_SECOND, -1);
}
CUSTOM_COMMAND_SIG(miblo_increment_time_stamp_minute){
miblo_time_stamp_alter(app, MIBLO_MINUTE, 1);
}
CUSTOM_COMMAND_SIG(miblo_decrement_time_stamp_minute){
miblo_time_stamp_alter(app, MIBLO_MINUTE, -1);
}
#endif