From 803f48697326b2f29740aae1d97f4b91854de0b5 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Sun, 18 Sep 2016 22:49:25 -0400 Subject: [PATCH] passing the command line parameters to the application --- 4coder_API.html | 8 +- 4coder_types.h | 2 +- 4cpp_lexer.h | 4 +- 4ed.cpp | 257 +++++++------ 4ed.h | 13 +- 4ed_api_implementation.cpp | 1 + 4ed_app_models.h | 3 + 4ed_metagen.cpp | 4 +- TODO.txt | 7 +- buffer/4coder_gap_buffer.cpp | 696 ++++++++++++++++++----------------- win32_4ed.cpp | 3 +- 11 files changed, 528 insertions(+), 470 deletions(-) diff --git a/4coder_API.html b/4coder_API.html index 52ceab08..37aeb711 100644 --- a/4coder_API.html +++ b/4coder_API.html @@ -1,5 +1,5 @@ 4coder API Docs -

4cpp Lexing Library

Table of Contents

+

4coder API

Table of Contents

§1 Introduction

This is the documentation for alpha 4.0.12 The documentation is still under construction so some of the links are linking to sections that have not been written yet. What is here should be correct and I suspect useful even without some of the other sections.

If you have questions or discover errors please contact editor@4coder.net or to get help from community members you can post on the 4coder forums hosted on handmade.network at 4coder.handmade.network

§2 4coder Systems

Coming Soon

§3 Types and Functions

§3.1 Function List

§3.2 Type List

§3.3 Function Descriptions

§3.3.1: exec_command

bool32 exec_command(
Application_Links *app,
Command_ID command_id
)
Parameters
command_id
The command_id parameter specifies which internal command to execute.
Return
This call returns non-zero if command_id named a valid internal command.
Description
A call to exec_command executes an internal command. @@ -31,7 +31,7 @@ range is not within the bounds of the buffer.

Description
Computes a Partial_Cursor for the given seek position with no side effects. The seek position must be one of the types supported by Partial_Cursor. Those -types are absolute position and line,column position.

See Also

§3.3.14: buffer_batch_edit

bool32 buffer_batch_edit(
Application_Links *app,
Buffer_Summary *buffer,
char *str,
int32_t str_len,
Buffer_Edit *edits,
int32_t edit_count,
Buffer_Batch_Edit_Type type
)
Parameters
str
This parameter provides all of the source string for the edits in the batch.
str_len
This parameter specifies the length of the str string.
edits
This parameter provides about the source string and destination range of each edit as an array.
edit_count
This parameter specifies the number of Buffer_Edit structs in edits.
type
This prameter specifies what type of batch edit to execute.
Return
This call returns non-zero if the batch edit succeeds. This call can fail if the provided +types are absolute position and line,column position.

See Also

§3.3.14: buffer_batch_edit

bool32 buffer_batch_edit(
Application_Links *app,
Buffer_Summary *buffer,
char *str,
int32_t str_len,
Buffer_Edit *edits,
int32_t edit_count,
Buffer_Batch_Edit_Type type
)
Parameters
buffer
The buffer on which to apply the batch of edits.
str
This parameter provides all of the source string for the edits in the batch.
str_len
This parameter specifies the length of the str string.
edits
This parameter provides about the source string and destination range of each edit as an array.
edit_count
This parameter specifies the number of Buffer_Edit structs in edits.
type
This prameter specifies what type of batch edit to execute.
Return
This call returns non-zero if the batch edit succeeds. This call can fail if the provided buffer summary does not refer to an actual buffer in 4coder.
Description
TODO

See Also

§3.3.15: buffer_set_setting

bool32 buffer_set_setting(
Application_Links *app,
Buffer_Summary *buffer,
Buffer_Setting_ID setting,
int32_t value
)
Parameters
buffer
The buffer parameter specifies the buffer on which to set a setting.
setting
The setting parameter identifies the setting that shall be changed.
value
The value parameter specifies the value to which the setting shall be changed.
See Also

§3.3.16: buffer_token_count

int32_t buffer_token_count(
Application_Links *app,
Buffer_Summary *buffer
)
Parameters
buffer
Specifies the buffer from which to read the token count.
Return
If tokens are available for the buffer, the number of tokens on the buffer is returned. If the buffer does not exist or if it is not a lexed buffer, the return is zero.

§3.3.17: buffer_read_tokens

bool32 buffer_read_tokens(
Application_Links *app,
Buffer_Summary *buffer,
int32_t start_token,
int32_t end_token,
Cpp_Token *tokens_out
)
Parameters
buffer
Specifies the buffer from which to read tokens.
first_token
Specifies the index of the first token to read.
end_token
Specifies the token to stop reading at.
tokens_out
The memory that will store the tokens read from the buffer.
Return
Returns non-zero on success. This call can fail if the buffer doesn't exist or doesn't have tokens ready, or if either the first or last index is out of bounds.
Description
Puts the data for the tokens with the indices [first_token,last_token


§3.3.18: buffer_get_token_index

bool32 buffer_get_token_index(
Application_Links *app,
Buffer_Summary *buffer,
int32_t pos,
Cpp_Get_Token_Result *get_result
)
Parameters
buffer
The buffer from which to get a token.
pos
The position in the buffer in absolute coordinates.
get_result
The output struct specifying which token contains pos.
Return
Returns non-zero on success. This call can fail if the buffer doesn't exist, @@ -103,7 +103,7 @@ a color value, colors are specified as 24 bit integers in 3 channels: 0xRRGGBB.< to textual input that takes modifiers into account.


§3.4.4: Buffer_ID

typedef int32_t Buffer_ID;
Description
Buffer_ID is used to name a 4coder buffer. Each buffer has a unique id but when a buffer is closed it's id may be recycled by future, different buffers.


§3.4.5: View_ID

typedef int32_t View_ID;
Description
View_ID is used to name a 4coder view. Each view has a unique id in the interval [1,16].


§3.4.6: Key_Modifier

enum Key_Modifier;
Description
A Key_Modifier acts as an index for specifying modifiers in arrays.

Values
MDFR_SHIFT_INDEX
MDFR_CONTROL_INDEX
MDFR_ALT_INDEX
MDFR_CAPS_INDEX
MDFR_HOLD_INDEX
MDFR_INDEX_COUNT
MDFR_INDEX_COUNT is used to specify the number of modifiers supported.


§3.4.7: Key_Modifier_Flag

enum Key_Modifier_Flag;
Description
A Key_Modifier_Flag field is used to specify a specific state of modifiers. -Flags can be combined with bit or to specify a state with multiple modifiers.

Values
MDFR_NONE = 0x0
MDFR_NONE specifies that no modifiers are pressed.

MDFR_CTRL = 0x1
MDFR_ALT = 0x2
MDFR_SHIFT = 0x4

§3.4.8: Command_ID

enum Command_ID;
Description
A Command_ID is used as a name for commands implemented internally in 4coder.

Values
cmdid_null
cmdid_null is set aside to always be zero and is not associated with any command.

cmdid_undo
cmdid_undo performs a standard undo behavior.

cmdid_redo
cmdid_redo reperforms an edit that was undone.

cmdid_history_backward
cmdid_history_backward performs a step backwards through the file history, which includes previously lost redo branches.

cmdid_history_forward
cmdid_history_forward unperforms the previous cmdid_history_backward step if possib.e

cmdid_interactive_new
cmdid_interactive_new begins an interactive dialogue to create a new buffer.

cmdid_interactive_open
cmdid_interactive_open begins an interactive dialogue to open a file into a buffer.

cmdid_save_as
cmdid_save_as does not currently work and is likely to be removed rather that fixed.

cmdid_interactive_switch_buffer
cmdid_interactive_switch_buffer begins an interactive dialogue to choose an open buffer to swap into the active view.

cmdid_interactive_kill_buffer
cmdid_interactive_kill_buffer begins an interactive dialogue to choose an open buffer to kill.

cmdid_reopen
cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.

cmdid_save
cmdid_save saves the buffer's contents into the associated file.

cmdid_kill_buffer
cmdid_kill_buffer tries to kill the active buffer.

cmdid_open_color_tweaker
cmdid_open_color_tweaker opens the theme editing GUI.

cmdid_open_config
cmdid_open_config opens the configuration menu.

cmdid_open_menu
cmdid_open_menu opens the top level menu.

cmdid_open_debug
cmdid_open_debug opens the debug information viewer mode.

cmdid_count

§3.4.9: Memory_Protect_Flags

enum Memory_Protect_Flags;
Description
TODO

Values
MemProtect_Read = 0x1
TODO

MemProtect_Write = 0x2
TODO

MemProtect_Execute = 0x4
TODO


§3.4.10: User_Input_Type_ID

enum User_Input_Type_ID;
Description
User_Input_Type_ID specifies a type of user input event.

Values
UserInputNone
UserInputNone indicates that no event has occurred.

UserInputKey
UserInputKey indicates an event which can be described by a Key_Event_Data struct.

UserInputMouse
UserInputMouse indicates an event which can be described by a Mouse_State struct.


§3.4.11: Event_Message_Type_ID

enum Event_Message_Type_ID;
Description
Event_Message_Type_ID is a part of an unfinished feature.

Values
EventMessage_NoMessage
TODO.

EventMessage_OpenView
TODO.

EventMessage_Frame
TODO.

EventMessage_CloseView
TODO.


§3.4.12: Buffer_Setting_ID

enum Buffer_Setting_ID;
Description
A Buffer_Setting_ID names a setting in a buffer.

Values
BufferSetting_Null
BufferSetting_Null is not a valid setting, it is reserved to detect errors.

BufferSetting_Lex
The BufferSetting_Lex setting is used to determine whether to store C++ tokens +Flags can be combined with bit or to specify a state with multiple modifiers.

Values
MDFR_NONE = 0x0
MDFR_NONE specifies that no modifiers are pressed.

MDFR_CTRL = 0x1
MDFR_ALT = 0x2
MDFR_SHIFT = 0x4

§3.4.8: Command_ID

enum Command_ID;
Description
A Command_ID is used as a name for commands implemented internally in 4coder.

Values
cmdid_null
cmdid_null is set aside to always be zero and is not associated with any command.

cmdid_undo
cmdid_undo performs a standard undo behavior.

cmdid_redo
cmdid_redo reperforms an edit that was undone.

cmdid_history_backward
cmdid_history_backward performs a step backwards through the file history, which includes previously lost redo branches.

cmdid_history_forward
cmdid_history_forward unperforms the previous cmdid_history_backward step if possible.

cmdid_interactive_new
cmdid_interactive_new begins an interactive dialogue to create a new buffer.

cmdid_interactive_open
cmdid_interactive_open begins an interactive dialogue to open a file into a buffer.

cmdid_save_as
cmdid_save_as does not currently work and is likely to be removed rather that fixed.

cmdid_interactive_switch_buffer
cmdid_interactive_switch_buffer begins an interactive dialogue to choose an open buffer to swap into the active view.

cmdid_interactive_kill_buffer
cmdid_interactive_kill_buffer begins an interactive dialogue to choose an open buffer to kill.

cmdid_reopen
cmdid_reopen reloads the active buffer's associated file and discards the old buffer contents for the reloaded file.

cmdid_save
cmdid_save saves the buffer's contents into the associated file.

cmdid_kill_buffer
cmdid_kill_buffer tries to kill the active buffer.

cmdid_open_color_tweaker
cmdid_open_color_tweaker opens the theme editing GUI.

cmdid_open_config
cmdid_open_config opens the configuration menu.

cmdid_open_menu
cmdid_open_menu opens the top level menu.

cmdid_open_debug
cmdid_open_debug opens the debug information viewer mode.

cmdid_count

§3.4.9: Memory_Protect_Flags

enum Memory_Protect_Flags;
Description
TODO

Values
MemProtect_Read = 0x1
TODO

MemProtect_Write = 0x2
TODO

MemProtect_Execute = 0x4
TODO


§3.4.10: User_Input_Type_ID

enum User_Input_Type_ID;
Description
User_Input_Type_ID specifies a type of user input event.

Values
UserInputNone
UserInputNone indicates that no event has occurred.

UserInputKey
UserInputKey indicates an event which can be described by a Key_Event_Data struct.

UserInputMouse
UserInputMouse indicates an event which can be described by a Mouse_State struct.


§3.4.11: Event_Message_Type_ID

enum Event_Message_Type_ID;
Description
Event_Message_Type_ID is a part of an unfinished feature.

Values
EventMessage_NoMessage
TODO.

EventMessage_OpenView
TODO.

EventMessage_Frame
TODO.

EventMessage_CloseView
TODO.


§3.4.12: Buffer_Setting_ID

enum Buffer_Setting_ID;
Description
A Buffer_Setting_ID names a setting in a buffer.

Values
BufferSetting_Null
BufferSetting_Null is not a valid setting, it is reserved to detect errors.

BufferSetting_Lex
The BufferSetting_Lex setting is used to determine whether to store C++ tokens from with the buffer.

BufferSetting_WrapLine
The BufferSetting_WrapLine setting is used to determine whether a buffer prefers to be viewed with wrapped lines, individual views can be set to override this value after being tied to the buffer.

BufferSetting_MapID
The BufferSetting_MapID setting specifies the id of the command map that should be @@ -328,7 +328,7 @@ system says it needs a chunk. You may switch to or modify the output array in b The most basic use of this system is to get it all done in one big chunk and try to allocate a nearly "infinite" output array so that it will not run out of memory. This way you can get the entire job done in one call and then just assert to make sure it returns LexResult_Finished to you:

-

Cpp_Token_Array lex_file(char *file_name){
    File_Data file = read_whole_file(file_name);
    
    char *temp = (char*)malloc(4096); // hopefully big enough
    Cpp_Lex_Data lex_state = cpp_lex_data_init(temp);
    
    Cpp_Token_Array array = {0};
    array.tokens = (Cpp_Token*)malloc(1 << 20); // hopefully big enough
    array.max_count = (1 << 20)/sizeof(Cpp_Token);
    
    Cpp_Lex_Result result =
        cpp_lex_step(&lex_state, file.data, file.size, file.size,
                     &array, NO_OUT_LIMIT);
    Assert(result == LexResult_Finished);
    
    free(temp);
    
    return(array);
}
See Also

§5.4.3: cpp_lex_data_init

Cpp_Lex_Data cpp_lex_data_init(
char *mem_buffer
)
Parameters
tb
The memory to use for initializing the lex state's temp memory buffer.
Return
A brand new lex state ready to begin lexing a file from the beginning.
Description
Creates a new lex state in the form of a Cpp_Lex_Data struct and returns the struct. +

Cpp_Token_Array lex_file(char *file_name){
    File_Data file = read_whole_file(file_name);
    
    char *temp = (char*)malloc(4096); // hopefully big enough
    Cpp_Lex_Data lex_state = cpp_lex_data_init(temp);
    
    Cpp_Token_Array array = {0};
    array.tokens = (Cpp_Token*)malloc(1 << 20); // hopefully big enough
    array.max_count = (1 << 20)/sizeof(Cpp_Token);
    
    Cpp_Lex_Result result =
        cpp_lex_step(&lex_state, file.data, file.size, file.size,
                     &array, NO_OUT_LIMIT);
    Assert(result == LexResult_Finished);
    
    free(temp);
    
    return(array);
}
See Also

§5.4.3: cpp_lex_data_init

Cpp_Lex_Data cpp_lex_data_init(
char *mem_buffer
)
Parameters
mem_buffer
The memory to use for initializing the lex state's temp memory buffer.
Return
A brand new lex state ready to begin lexing a file from the beginning.
Description
Creates a new lex state in the form of a Cpp_Lex_Data struct and returns the struct. The system needs a temporary buffer that is as long as the longest token. 4096 is usually enough but the buffer is not checked, so to be 100% bullet proof it has to be the same length as the file being lexed.


§5.4.4: cpp_lex_data_temp_size

int32_t cpp_lex_data_temp_size(
Cpp_Lex_Data *lex_data
)
Parameters
lex_data
The lex state from which to get the temporary buffer size.
Description
This call gets the current size of the temporary buffer in the lexer state so diff --git a/4coder_types.h b/4coder_types.h index 17c839a8..91bd99df 100644 --- a/4coder_types.h +++ b/4coder_types.h @@ -57,7 +57,7 @@ ENUM(uint64_t, Command_ID){ cmdid_redo, /* DOC(cmdid_history_backward performs a step backwards through the file history, which includes previously lost redo branches.) */ cmdid_history_backward, - /* DOC(cmdid_history_forward unperforms the previous cmdid_history_backward step if possib.e) */ + /* DOC(cmdid_history_forward unperforms the previous cmdid_history_backward step if possible.) */ cmdid_history_forward, /* DOC(cmdid_interactive_new begins an interactive dialogue to create a new buffer.) */ diff --git a/4cpp_lexer.h b/4cpp_lexer.h index ca863081..a13f8774 100644 --- a/4cpp_lexer.h +++ b/4cpp_lexer.h @@ -1034,7 +1034,7 @@ DOC_SEE(Cpp_Lex_Data) FCPP_LINK Cpp_Lex_Data cpp_lex_data_init(char *mem_buffer)/* -DOC_PARAM(tb, The memory to use for initializing the lex state's temp memory buffer.) +DOC_PARAM(mem_buffer, The memory to use for initializing the lex state's temp memory buffer.) DOC_RETURN(A brand new lex state ready to begin lexing a file from the beginning.) DOC(Creates a new lex state in the form of a Cpp_Lex_Data struct and returns the struct. @@ -1081,6 +1081,7 @@ FCPP_LINK void cpp_lex_data_new_temp(Cpp_Lex_Data *lex_data, char *new_buffer)/* DOC_PARAM(lex_data, The lex state that will receive the new temporary buffer.) DOC_PARAM(new_buffer, The new temporary buffer that has the same contents as the old temporary buffer.) + DOC(This call can be used to set a new temporary buffer for the lex state. In cases where you want to discontinue lexing, store the state, and resume later. In such a situation it may be necessary for you to free the temp buffer that was originally used to make the lex state. This call allows you to supply @@ -1089,6 +1090,7 @@ a new temp buffer when you are ready to resume lexing. However the new buffer needs to have the same contents the old buffer had. To ensure this you have to use cpp_lex_data_temp_size and cpp_lex_data_temp_read to get the relevant contents of the temp buffer before you free it.) + DOC_SEE(cpp_lex_data_temp_size) DOC_SEE(cpp_lex_data_temp_read) */{ diff --git a/4ed.cpp b/4ed.cpp index 50ae88ee..8cc60fd5 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -1125,134 +1125,165 @@ enum Command_Line_Action{ CLAct_Count }; +enum Command_Line_Mode{ + CLMode_App, + CLMode_Custom +}; + void init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, Command_Line_Parameters clparams){ - char *arg; + char *arg = 0; + Command_Line_Mode mode = CLMode_App; Command_Line_Action action = CLAct_Nothing; - i32 i,index; + i32 i = 0, index = 0; b32 strict = 0; settings->init_files_max = ArrayCount(settings->init_files); for (i = 1; i <= clparams.argc; ++i){ - if (i == clparams.argc) arg = ""; - else arg = clparams.argv[i]; - switch (action){ - case CLAct_Nothing: + if (i == clparams.argc){ + arg = ""; + } + else{ + arg = clparams.argv[i]; + } + + if (arg[0] == '-' && arg[1] == '-'){ + char *long_arg_name = arg+2; + if (match_cc(long_arg_name, "custom")){ + mode = CLMode_Custom; + settings->custom_arg_start = i+1; + settings->custom_arg_end = i+1; + continue; + } + } + + switch (mode){ + case CLMode_App: { - if (arg[0] == '-'){ - action = CLAct_Ignore; - switch (arg[1]){ - case 'u': action = CLAct_UserFile; strict = false; break; - case 'U': action = CLAct_UserFile; strict = true; break; - - case 'd': action = CLAct_CustomDLL; strict = false; break; - case 'D': action = CLAct_CustomDLL; strict = true; break; - - case 'i': action = CLAct_InitialFilePosition; break; - - case 'w': action = CLAct_WindowSize; break; - case 'W': action = CLAct_WindowMaximize; break; - case 'p': action = CLAct_WindowPosition; break; - case 'F': action = CLAct_WindowFullscreen; break; - case 'S': action = CLAct_WindowStreamMode; break; - - case 'f': action = CLAct_FontSize; break; - case 'h': action = CLAct_FontStopHinting; --i; break; - } - } - else if (arg[0] != 0){ - if (settings->init_files_count < settings->init_files_max){ - index = settings->init_files_count++; - settings->init_files[index] = arg; - } - } - }break; - - case CLAct_UserFile: - { - settings->user_file_is_strict = strict; - if (i < clparams.argc){ - settings->user_file = clparams.argv[i]; - } - action = CLAct_Nothing; - }break; - - case CLAct_CustomDLL: - { - plat_settings->custom_dll_is_strict = strict; - if (i < clparams.argc){ - plat_settings->custom_dll = clparams.argv[i]; - } - action = CLAct_Nothing; - }break; - - case CLAct_InitialFilePosition: - { - if (i < clparams.argc){ - settings->initial_line = str_to_int_c(clparams.argv[i]); - } - action = CLAct_Nothing; - }break; - - case CLAct_WindowSize: - { - if (i + 1 < clparams.argc){ - plat_settings->set_window_size = true; - plat_settings->window_w = str_to_int_c(clparams.argv[i]); - plat_settings->window_h = str_to_int_c(clparams.argv[i+1]); + switch (action){ + case CLAct_Nothing: + { + if (arg[0] == '-'){ + action = CLAct_Ignore; + switch (arg[1]){ + case 'u': action = CLAct_UserFile; strict = false; break; + case 'U': action = CLAct_UserFile; strict = true; break; + + case 'd': action = CLAct_CustomDLL; strict = false; break; + case 'D': action = CLAct_CustomDLL; strict = true; break; + + case 'i': action = CLAct_InitialFilePosition; break; + + case 'w': action = CLAct_WindowSize; break; + case 'W': action = CLAct_WindowMaximize; break; + case 'p': action = CLAct_WindowPosition; break; + case 'F': action = CLAct_WindowFullscreen; break; + case 'S': action = CLAct_WindowStreamMode; break; + + case 'f': action = CLAct_FontSize; break; + case 'h': action = CLAct_FontStopHinting; --i; break; + } + } + else if (arg[0] != 0){ + if (settings->init_files_count < settings->init_files_max){ + index = settings->init_files_count++; + settings->init_files[index] = arg; + } + } + }break; - ++i; - } - action = CLAct_Nothing; - }break; - - case CLAct_WindowMaximize: - { - --i; - plat_settings->maximize_window = true; - action = CLAct_Nothing; - }break; - - case CLAct_WindowPosition: - { - if (i + 1 < clparams.argc){ - plat_settings->set_window_pos = true; - plat_settings->window_x = str_to_int_c(clparams.argv[i]); - plat_settings->window_y = str_to_int_c(clparams.argv[i+1]); + case CLAct_UserFile: + { + settings->user_file_is_strict = strict; + if (i < clparams.argc){ + settings->user_file = clparams.argv[i]; + } + action = CLAct_Nothing; + }break; - ++i; + case CLAct_CustomDLL: + { + plat_settings->custom_dll_is_strict = strict; + if (i < clparams.argc){ + plat_settings->custom_dll = clparams.argv[i]; + } + action = CLAct_Nothing; + }break; + + case CLAct_InitialFilePosition: + { + if (i < clparams.argc){ + settings->initial_line = str_to_int_c(clparams.argv[i]); + } + action = CLAct_Nothing; + }break; + + case CLAct_WindowSize: + { + if (i + 1 < clparams.argc){ + plat_settings->set_window_size = true; + plat_settings->window_w = str_to_int_c(clparams.argv[i]); + plat_settings->window_h = str_to_int_c(clparams.argv[i+1]); + + ++i; + } + action = CLAct_Nothing; + }break; + + case CLAct_WindowMaximize: + { + --i; + plat_settings->maximize_window = true; + action = CLAct_Nothing; + }break; + + case CLAct_WindowPosition: + { + if (i + 1 < clparams.argc){ + plat_settings->set_window_pos = true; + plat_settings->window_x = str_to_int_c(clparams.argv[i]); + plat_settings->window_y = str_to_int_c(clparams.argv[i+1]); + + ++i; + } + action = CLAct_Nothing; + }break; + + case CLAct_WindowFullscreen: + { + --i; + plat_settings->fullscreen_window = true; + plat_settings->stream_mode = true; + action = CLAct_Nothing; + }break; + + case CLAct_WindowStreamMode: + { + --i; + plat_settings->stream_mode = true; + action = CLAct_Nothing; + }break; + + case CLAct_FontSize: + { + if (i < clparams.argc){ + settings->font_size = str_to_int_c(clparams.argv[i]); + } + action = CLAct_Nothing; + }break; + + case CLAct_FontStopHinting: + { + plat_settings->use_hinting = true; + action = CLAct_Nothing; + }break; } - action = CLAct_Nothing; }break; - case CLAct_WindowFullscreen: + case CLMode_Custom: { - --i; - plat_settings->fullscreen_window = true; - plat_settings->stream_mode = true; - action = CLAct_Nothing; - }break; - - case CLAct_WindowStreamMode: - { - --i; - plat_settings->stream_mode = true; - action = CLAct_Nothing; - }break; - - case CLAct_FontSize: - { - if (i < clparams.argc){ - settings->font_size = str_to_int_c(clparams.argv[i]); - } - action = CLAct_Nothing; - }break; - - case CLAct_FontStopHinting: - { - plat_settings->use_hinting = true; - action = CLAct_Nothing; + settings->custom_arg_end = i+1; }break; } } diff --git a/4ed.h b/4ed.h index c7c0ed1a..2100d1a5 100644 --- a/4ed.h +++ b/4ed.h @@ -121,12 +121,13 @@ struct Application_Step_Input{ String clipboard; }; -#define App_Step_Sig(name) void \ -name(System_Functions *system, \ - Render_Target *target, \ - Application_Memory *memory, \ - Application_Step_Input *input, \ - Application_Step_Result *result) +#define App_Step_Sig(name) void \ +name(System_Functions *system, \ + Render_Target *target, \ + Application_Memory *memory, \ + Application_Step_Input *input, \ + Application_Step_Result *result, \ + Command_Line_Parameters params) typedef App_Step_Sig(App_Step); diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 8112a5c4..9aa01d8f 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -657,6 +657,7 @@ DOC_SEE(Partial_Cursor) API_EXPORT bool32 Buffer_Batch_Edit(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type)/* +DOC_PARAM(buffer, The buffer on which to apply the batch of edits.) DOC_PARAM(str, This parameter provides all of the source string for the edits in the batch.) DOC_PARAM(str_len, This parameter specifies the length of the str string.) DOC_PARAM(edits, This parameter provides about the source string and destination range of each edit as an array.) diff --git a/4ed_app_models.h b/4ed_app_models.h index 2624ff3d..59f61ad2 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -21,6 +21,9 @@ struct App_Settings{ b32 lctrl_lalt_is_altgr; i32 font_size; + + i32 custom_arg_start; + i32 custom_arg_end; }; struct Debug_Input_Event{ diff --git a/4ed_metagen.cpp b/4ed_metagen.cpp index cdb26f85..bc4834e6 100644 --- a/4ed_metagen.cpp +++ b/4ed_metagen.cpp @@ -2970,9 +2970,9 @@ generate_custom_headers(){ "" "
" - "

4cpp Lexing Library

"); +// "

4cpp Lexing Library

"); -// "

4coder API

"); + "

4coder API

"); struct Section{ char *id_string; diff --git a/TODO.txt b/TODO.txt index 0508e6f1..18e21850 100644 --- a/TODO.txt +++ b/TODO.txt @@ -163,7 +163,12 @@ ; [] the "main_4coder" experiment ; [] multi-line editing ; [] multi-cursor editing -; + +; [] API docs have duplicate ids? +; [] introduce custom command line arguments +; [] control the file opening/start hook relationship better +; [] flag for hiding the *messages* buffer. +; [] get keyboard state on launch ; buffer behavior cleanup ; [] show all characters as \# if they can't be rendered diff --git a/buffer/4coder_gap_buffer.cpp b/buffer/4coder_gap_buffer.cpp index 1154a569..09860aea 100644 --- a/buffer/4coder_gap_buffer.cpp +++ b/buffer/4coder_gap_buffer.cpp @@ -1,341 +1,355 @@ -/* - * Mr. 4th Dimention - Allen Webster - * Four Tech - * - * public domain -- no warranty is offered or implied; use this code at your own risk - * - * 23.10.2015 - * - * Buffer data object - * type - Gap Buffer - * - */ - -// TOP - -typedef struct Gap_Buffer{ - char *data; - int size1, gap_size, size2, max; - - float *line_widths; - int *line_starts; - int line_count; - int widths_count; - int line_max; - int widths_max; -} Gap_Buffer; - -inline_4tech int -buffer_good(Gap_Buffer *buffer){ - int good; - good = (buffer->data != 0); - return(good); -} - -inline_4tech int -buffer_size(Gap_Buffer *buffer){ - int size; - size = buffer->size1 + buffer->size2; - return(size); -} - -typedef struct Gap_Buffer_Init{ - Gap_Buffer *buffer; - char *data; - int size; -} Gap_Buffer_Init; - -internal_4tech Gap_Buffer_Init -buffer_begin_init(Gap_Buffer *buffer, char *data, int size){ - Gap_Buffer_Init init; - init.buffer = buffer; - init.data = data; - init.size = size; - return(init); -} - -internal_4tech int -buffer_init_need_more(Gap_Buffer_Init *init){ - int result; - result = 1; - if (init->buffer->data) result = 0; - return(result); -} - -internal_4tech int -buffer_init_page_size(Gap_Buffer_Init *init){ - int result; - result = init->size * 2; - return(result); -} - -internal_4tech void -buffer_init_provide_page(Gap_Buffer_Init *init, void *page, int page_size){ - Gap_Buffer *buffer; - buffer = init->buffer; - buffer->data = (char*)page; - buffer->max = page_size; -} - -internal_4tech int -buffer_end_init(Gap_Buffer_Init *init, void *scratch, int scratch_size){ - Gap_Buffer *buffer; - int osize1, size1, size2, size; - int result; - - result = 0; - buffer = init->buffer; - size = init->size; - if (buffer->data){ - if (buffer->max >= init->size){ - size2 = size >> 1; - size1 = osize1 = size - size2; - - if (size1 > 0){ - size1 = eol_convert_in(buffer->data, init->data, size1); - if (size2 > 0){ - size2 = eol_convert_in(buffer->data + size1, init->data + osize1, size2); - } - } - - buffer->size1 = size1; - buffer->size2 = size2; - buffer->gap_size = buffer->max - size1 - size2; - memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2); - - result = 1; - } - } - - return(result); -} - -typedef struct Gap_Buffer_Stringify_Loop{ - Gap_Buffer *buffer; - char *data, *base; - int absolute_pos; - int pos, end; - int size; - int separated; -} Gap_Buffer_Stringify_Loop; - -internal_4tech Gap_Buffer_Stringify_Loop -buffer_stringify_loop(Gap_Buffer *buffer, int start, int end){ - Gap_Buffer_Stringify_Loop result; - if (0 <= start && start < end && end <= buffer->size1 + buffer->size2){ - result.buffer = buffer; - result.base = buffer->data; - result.absolute_pos = start; - - if (end <= buffer->size1) result.end = end; - else result.end = end + buffer->gap_size; - - if (start < buffer->size1){ - if (end <= buffer->size1) result.separated = 0; - else result.separated = 1; - result.pos = start; - } - else{ - result.separated = 0; - result.pos = start + buffer->gap_size; - } - if (result.separated) result.size = buffer->size1 - start; - else result.size = end - start; - result.data = buffer->data + result.pos; - } - else result.buffer = 0; - return(result); -} - -inline_4tech int -buffer_stringify_good(Gap_Buffer_Stringify_Loop *loop){ - int result; - result = (loop->buffer != 0); - return(result); -} - -internal_4tech void -buffer_stringify_next(Gap_Buffer_Stringify_Loop *loop){ - int size1, temp_end; - if (loop->separated){ - loop->separated = 0; - size1 = loop->buffer->size1; - loop->pos = loop->buffer->gap_size + size1; - loop->absolute_pos = size1; - temp_end = loop->end; - } - else{ - loop->buffer = 0; - temp_end = loop->pos; - } - loop->size = temp_end - loop->pos; - loop->data = loop->base + loop->pos; -} - -typedef struct Gap_Buffer_Backify_Loop{ - Gap_Buffer *buffer; - char *data, *base; - int pos, end; - int size; - int absolute_pos; - int separated; -} Gap_Buffer_Backify_Loop; - -internal_4tech Gap_Buffer_Backify_Loop -buffer_backify_loop(Gap_Buffer *buffer, int start, int end){ - Gap_Buffer_Backify_Loop result; - - ++start; - if (0 <= end && end < start && start <= buffer->size1 + buffer->size2){ - result.buffer = buffer; - result.base = buffer->data; - - if (end < buffer->size1) result.end = end; - else result.end = end + buffer->gap_size; - - if (start <= buffer->size1){ - result.separated = 0; - result.pos = 0; - } - else{ - if (end < buffer->size1) result.separated = 1; - else result.separated = 0; - result.pos = buffer->size1 + buffer->gap_size; - } - if (!result.separated && result.pos < result.end) result.pos = result.end; - result.size = start - result.pos; - result.absolute_pos = result.pos; - if (result.absolute_pos > buffer->size1) result.absolute_pos -= buffer->gap_size; - result.data = result.base + result.pos; - } - else result.buffer = 0; - return(result); -} - -inline_4tech int -buffer_backify_good(Gap_Buffer_Backify_Loop *loop){ - int result; - result = (loop->buffer != 0); - return(result); -} - -internal_4tech void -buffer_backify_next(Gap_Buffer_Backify_Loop *loop){ - Gap_Buffer *buffer; - int temp_end; - int chunk2_start; - buffer = loop->buffer; - chunk2_start = buffer->size1 + buffer->gap_size; - if (loop->separated){ - loop->separated = 0; - temp_end = buffer->size1; - loop->pos = 0; - loop->absolute_pos = 0; - if (loop->pos < loop->end){ - loop->absolute_pos = loop->end; - loop->pos = loop->end; - } - } - else{ - temp_end = 0; - loop->buffer = 0; - } - loop->size = temp_end - loop->pos; - loop->data = loop->base + loop->pos; -} - -internal_4tech int -buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, - void *scratch, int scratch_memory, int *request_amount){ - char *data; - int result; - int size; - int move_size; - - size = buffer_size(buffer); - assert_4tech(0 <= start); - assert_4tech(start <= end); - assert_4tech(end <= size); - - *shift_amount = (len - (end - start)); - if (*shift_amount + size <= buffer->max){ - data = buffer->data; - if (end < buffer->size1){ - move_size = buffer->size1 - end; - memmove_4tech(data + buffer->size1 + buffer->gap_size - move_size, data + end, move_size); - buffer->size1 -= move_size; - buffer->size2 += move_size; - } - if (start > buffer->size1){ - move_size = start - buffer->size1; - memmove_4tech(data + buffer->size1, data + buffer->size1 + buffer->gap_size, move_size); - buffer->size1 += move_size; - buffer->size2 -= move_size; - } - - memcpy_4tech(data + start, str, len); - buffer->size2 = size - end; - buffer->size1 = start + len; - buffer->gap_size -= *shift_amount; - - assert_4tech(buffer->size1 + buffer->size2 == size + *shift_amount); - assert_4tech(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max); - - result = 0; - } - else{ - *request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10); - result = 1; - } - - return(result); -} - -// NOTE(allen): This could should be optimized for Gap_Buffer -internal_4tech int -buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits, - char *strings, int edit_count, void *scratch, int scratch_size, int *request_amount){ - Buffer_Edit *edit; - int i, result; - int shift_total, shift_amount; - - result = 0; - shift_total = state->shift_total; - i = state->i; - - edit = sorted_edits + i; - for (; i < edit_count; ++i, ++edit){ - result = buffer_replace_range(buffer, edit->start + shift_total, edit->end + shift_total, - strings + edit->str_start, edit->len, &shift_amount, - scratch, scratch_size, request_amount); - if (result) break; - shift_total += shift_amount; - } - - state->shift_total = shift_total; - state->i = i; - - return(result); -} - -internal_4tech void* -buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){ - void *result; - int new_gap_size; - - assert_4tech(new_max >= buffer_size(buffer)); - - result = buffer->data; - new_gap_size = new_max - buffer_size(buffer); - memcpy_4tech(new_data, buffer->data, buffer->size1); - memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); - - buffer->data = (char*)new_data; - buffer->gap_size = new_gap_size; - buffer->max = new_max; - - return(result); -} - -// BOTTOM - +/* + * Mr. 4th Dimention - Allen Webster + * Four Tech + * + * public domain -- no warranty is offered or implied; use this code at your own risk + * + * 23.10.2015 + * + * Buffer data object + * type - Gap Buffer + * + */ + +// TOP + +typedef struct Gap_Buffer{ + char *data; + int size1; + int gap_size; + int size2; + int max; + + float *line_widths; + int *line_starts; + int line_count; + int widths_count; + int line_max; + int widths_max; +} Gap_Buffer; + +inline_4tech int +buffer_good(Gap_Buffer *buffer){ + int good = (buffer->data != 0); + return(good); +} + +inline_4tech int +buffer_size(Gap_Buffer *buffer){ + int size = buffer->size1 + buffer->size2; + return(size); +} + +typedef struct Gap_Buffer_Init{ + Gap_Buffer *buffer; + char *data; + int size; +} Gap_Buffer_Init; + +internal_4tech Gap_Buffer_Init +buffer_begin_init(Gap_Buffer *buffer, char *data, int size){ + Gap_Buffer_Init init; + init.buffer = buffer; + init.data = data; + init.size = size; + return(init); +} + +internal_4tech int +buffer_init_need_more(Gap_Buffer_Init *init){ + int result = 1; + if (init->buffer->data) result = 0; + return(result); +} + +internal_4tech int +buffer_init_page_size(Gap_Buffer_Init *init){ + int result = init->size * 2; + return(result); +} + +internal_4tech void +buffer_init_provide_page(Gap_Buffer_Init *init, void *page, int page_size){ + Gap_Buffer *buffer = init->buffer; + buffer->data = (char*)page; + buffer->max = page_size; +} + +internal_4tech int +buffer_end_init(Gap_Buffer_Init *init, void *scratch, int scratch_size){ + Gap_Buffer *buffer = init->buffer; + int osize1 = 0, size1 = 0, size2 = 0, size = init->size; + int result = 0; + + if (buffer->data){ + if (buffer->max >= init->size){ + size2 = size >> 1; + size1 = osize1 = size - size2; + + if (size1 > 0){ + size1 = eol_convert_in(buffer->data, init->data, size1); + if (size2 > 0){ + size2 = eol_convert_in(buffer->data + size1, init->data + osize1, size2); + } + } + + buffer->size1 = size1; + buffer->size2 = size2; + buffer->gap_size = buffer->max - size1 - size2; + memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2); + + result = 1; + } + } + + return(result); +} + +typedef struct Gap_Buffer_Stringify_Loop{ + Gap_Buffer *buffer; + char *data, *base; + int absolute_pos; + int pos, end; + int size; + int separated; +} Gap_Buffer_Stringify_Loop; + +internal_4tech Gap_Buffer_Stringify_Loop +buffer_stringify_loop(Gap_Buffer *buffer, int start, int end){ + Gap_Buffer_Stringify_Loop result = {0}; + + if (0 <= start && start < end && end <= buffer->size1 + buffer->size2){ + result.buffer = buffer; + result.base = buffer->data; + result.absolute_pos = start; + + if (end <= buffer->size1){ + result.end = end; + } + else{ + result.end = end + buffer->gap_size; + } + + if (start < buffer->size1){ + if (end <= buffer->size1){ + result.separated = 0; + } + else{ + result.separated = 1; + } + result.pos = start; + } + else{ + result.separated = 0; + result.pos = start + buffer->gap_size; + } + + if (result.separated){ + result.size = buffer->size1 - start; + } + else{ + result.size = end - start; + } + + result.data = buffer->data + result.pos; + } + + return(result); +} + +inline_4tech int +buffer_stringify_good(Gap_Buffer_Stringify_Loop *loop){ + int result = (loop->buffer != 0); + return(result); +} + +internal_4tech void +buffer_stringify_next(Gap_Buffer_Stringify_Loop *loop){ + int size1 = 0, temp_end = 0; + if (loop->separated){ + loop->separated = 0; + size1 = loop->buffer->size1; + loop->pos = loop->buffer->gap_size + size1; + loop->absolute_pos = size1; + temp_end = loop->end; + } + else{ + loop->buffer = 0; + temp_end = loop->pos; + } + loop->size = temp_end - loop->pos; + loop->data = loop->base + loop->pos; +} + +typedef struct Gap_Buffer_Backify_Loop{ + Gap_Buffer *buffer; + char *data, *base; + int pos, end; + int size; + int absolute_pos; + int separated; +} Gap_Buffer_Backify_Loop; + +internal_4tech Gap_Buffer_Backify_Loop +buffer_backify_loop(Gap_Buffer *buffer, int start, int end){ + Gap_Buffer_Backify_Loop result = {0}; + + ++start; + if (0 <= end && end < start && start <= buffer->size1 + buffer->size2){ + result.buffer = buffer; + result.base = buffer->data; + + if (end < buffer->size1){ + result.end = end; + } + else{ + result.end = end + buffer->gap_size; + } + + if (start <= buffer->size1){ + result.separated = 0; + result.pos = 0; + } + else{ + if (end < buffer->size1){ + result.separated = 1; + } + else{ + result.separated = 0; + } + result.pos = buffer->size1 + buffer->gap_size; + } + + if (!result.separated && result.pos < result.end){ + result.pos = result.end; + } + + result.size = start - result.pos; + result.absolute_pos = result.pos; + if (result.absolute_pos > buffer->size1){ + result.absolute_pos -= buffer->gap_size; + } + result.data = result.base + result.pos; + } + + return(result); +} + +inline_4tech int +buffer_backify_good(Gap_Buffer_Backify_Loop *loop){ + int result = (loop->buffer != 0); + return(result); +} + +internal_4tech void +buffer_backify_next(Gap_Buffer_Backify_Loop *loop){ + Gap_Buffer *buffer = loop->buffer; + int temp_end = 0; + + if (loop->separated){ + loop->separated = 0; + temp_end = buffer->size1; + loop->pos = 0; + loop->absolute_pos = 0; + if (loop->pos < loop->end){ + loop->absolute_pos = loop->end; + loop->pos = loop->end; + } + } + else{ + temp_end = 0; + loop->buffer = 0; + } + + loop->size = temp_end - loop->pos; + loop->data = loop->base + loop->pos; +} + +internal_4tech int +buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, + void *scratch, int scratch_memory, int *request_amount){ + char *data = buffer->data; + int size = buffer_size(buffer); + int result = 0; + int move_size = 0; + + assert_4tech(0 <= start); + assert_4tech(start <= end); + assert_4tech(end <= size); + + *shift_amount = (len - (end - start)); + if (*shift_amount + size <= buffer->max){ + if (end < buffer->size1){ + move_size = buffer->size1 - end; + memmove_4tech(data + buffer->size1 + buffer->gap_size - move_size, data + end, move_size); + buffer->size1 -= move_size; + buffer->size2 += move_size; + } + if (start > buffer->size1){ + move_size = start - buffer->size1; + memmove_4tech(data + buffer->size1, data + buffer->size1 + buffer->gap_size, move_size); + buffer->size1 += move_size; + buffer->size2 -= move_size; + } + + memcpy_4tech(data + start, str, len); + buffer->size2 = size - end; + buffer->size1 = start + len; + buffer->gap_size -= *shift_amount; + + assert_4tech(buffer->size1 + buffer->size2 == size + *shift_amount); + assert_4tech(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max); + } + else{ + *request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10); + result = 1; + } + + return(result); +} + +// NOTE(allen): This could should be optimized for Gap_Buffer +internal_4tech int +buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits, + char *strings, int edit_count, void *scratch, int scratch_size, int *request_amount){ + Buffer_Edit *edit = 0; + int i = state->i; + int shift_total = state->shift_total; + int shift_amount = 0; + int result = 0; + + edit = sorted_edits + i; + for (; i < edit_count; ++i, ++edit){ + result = buffer_replace_range(buffer, edit->start + shift_total, edit->end + shift_total, + strings + edit->str_start, edit->len, &shift_amount, + scratch, scratch_size, request_amount); + if (result) break; + shift_total += shift_amount; + } + + state->shift_total = shift_total; + state->i = i; + + return(result); +} + +internal_4tech void* +buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){ + void *result = buffer->data; + int size = buffer_size(buffer); + int new_gap_size = new_max - size; + + assert_4tech(new_max >= size); + + memcpy_4tech(new_data, buffer->data, buffer->size1); + memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); + + buffer->data = (char*)new_data; + buffer->gap_size = new_gap_size; + buffer->max = new_max; + + return(result); +} + +// BOTTOM + diff --git a/win32_4ed.cpp b/win32_4ed.cpp index e4a84323..f6a9e19e 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -2438,7 +2438,8 @@ WinMain(HINSTANCE hInstance, &win32vars.target, &memory_vars, &input, - &result); + &result, + clparams); if (result.perform_kill){ keep_playing = 0;