got new organization system working on linux
This commit is contained in:
parent
f6a1c50d14
commit
63f695d074
|
@ -1,3 +1,4 @@
|
|||
struct Application_Links;
|
||||
#define EXEC_COMMAND_SIG(n) bool32 n(Application_Links *app, Command_ID command_id)
|
||||
#define EXEC_SYSTEM_COMMAND_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_Identifier buffer, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags)
|
||||
#define CLIPBOARD_POST_SIG(n) void n(Application_Links *app, int32_t clipboard_id, char *str, int32_t len)
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
#ifndef FCODER_CUSTOM_H
|
||||
#define FCODER_CUSTOM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "keycodes.h"
|
||||
#include "style.h"
|
||||
// TODO(allen): I don't like having to pull in the types from my standalone libraries to define the API.
|
||||
// What to do??? Hmmm....
|
||||
#include "4coder_lib/4coder_string.h"
|
||||
#include "4cpp/4cpp_lexer_types.h"
|
||||
#include "types.h"
|
||||
#include "app_functions.h"
|
||||
|
||||
extern "C" _GET_VERSION_SIG(get_alpha_4coder_version){
|
||||
int32_t result = (maj == MAJOR && min == MINOR && patch == PATCH);
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,40 +1,34 @@
|
|||
|
||||
|
||||
#ifndef ENUM
|
||||
#if !defined(FCODER_TYPES_H)
|
||||
#define FCODER_TYPES_H
|
||||
|
||||
#if !defined(FCODER_META_TAGS)
|
||||
#define FCODER_META_TAGS
|
||||
|
||||
# define ENUM(type,name) typedef type name; enum name##_
|
||||
#endif
|
||||
|
||||
#ifndef TYPEDEF
|
||||
# define TYPEDEF typedef
|
||||
#endif
|
||||
|
||||
#ifndef STRUCT
|
||||
# define TYPEDEF_FUNC typedef
|
||||
# define STRUCT struct
|
||||
#endif
|
||||
|
||||
#ifndef UNION
|
||||
# define UNION union
|
||||
# define GLOBAL_VAR static
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* DOC(bool32 is an alias name to signal that an integer parameter or field is for
|
||||
true/false values.) */
|
||||
/* DOC(bool32 is an alias name to signal that an integer parameter or field is for true/false values.) */
|
||||
TYPEDEF int32_t bool32;
|
||||
|
||||
/* DOC(int_color is an alias name to signal that an integer parameter or field is for
|
||||
a color value, colors are specified as 24 bit integers in 3 channels: 0xRRGGBB.) */
|
||||
/* DOC(int_color is an alias name to signal that an integer parameter or field is for a color value, colors are specified as 24 bit integers in 3 channels: 0xRRGGBB.) */
|
||||
TYPEDEF uint32_t int_color;
|
||||
|
||||
/* DOC(Key_Code is the alias for key codes including raw codes and codes translated
|
||||
to textual input that takes modifiers into account.) */
|
||||
/* DOC(Key_Code is the alias for key codes including raw codes and codes translated to textual input that takes modifiers into account.) */
|
||||
TYPEDEF unsigned char Key_Code;
|
||||
|
||||
/* DOC(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.) */
|
||||
/* DOC(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.) */
|
||||
TYPEDEF int32_t Buffer_ID;
|
||||
|
||||
/* DOC(View_ID is used to name a 4coder view. Each view has a unique id in
|
||||
the interval [1,16].) */
|
||||
/* DOC(View_ID is used to name a 4coder view. Each view has a unique id in the interval [1,16].) */
|
||||
TYPEDEF int32_t View_ID;
|
||||
|
||||
/* DOC(A Key_Modifier acts as an index for specifying modifiers in arrays.) */
|
||||
|
@ -68,10 +62,6 @@ ENUM(uint64_t, Command_ID){
|
|||
cmdid_undo,
|
||||
/* DOC(cmdid_redo reperforms an edit that was undone.) */
|
||||
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 possible.) */
|
||||
cmdid_history_forward,
|
||||
|
||||
/* DOC(cmdid_interactive_new begins an interactive dialogue to create a new buffer.) */
|
||||
cmdid_interactive_new,
|
||||
|
@ -358,15 +348,6 @@ ENUM(int32_t, View_Split_Position){
|
|||
ViewSplit_Right
|
||||
};
|
||||
|
||||
/* DOC(Generic_Command acts as a name for a command, and can name an internal command or a custom command.) */
|
||||
UNION Generic_Command{
|
||||
/*DOC(If this Generic_Command represents an internal command the cmdid field will have a value less than cmdid_count, and this field is the command id for the command.)*/
|
||||
Command_ID cmdid;
|
||||
/*DOC(If this Generic_Command does not represent an internal command the command
|
||||
field is the pointer to the custom command..)*/
|
||||
Custom_Command_Function *command;
|
||||
};
|
||||
|
||||
/* DOC(Key_Event_Data describes a key event, including the translation to a character, the translation to a character ignoring the state of caps lock, and an array of all the modifiers that were pressed at the time of the event.) */
|
||||
STRUCT Key_Event_Data{
|
||||
/* DOC(This field is the raw keycode which is always non-zero in valid key events.) */
|
||||
|
@ -385,6 +366,9 @@ STRUCT Key_Event_Data{
|
|||
char modifiers[MDFR_INDEX_COUNT];
|
||||
};
|
||||
|
||||
// TODO(allen): GLOBAL_VAR meta parsing
|
||||
GLOBAL_VAR Key_Event_Data null_key_event_data = {0};
|
||||
|
||||
/* DOC(Mouse_State describes an entire mouse state complete with the position, left and right button states, the wheel state, and whether or not the mouse if in the window.) */
|
||||
STRUCT Mouse_State{
|
||||
/* DOC(This field indicates that the left button is held.) */
|
||||
|
@ -411,6 +395,8 @@ STRUCT Mouse_State{
|
|||
int32_t y;
|
||||
};
|
||||
|
||||
GLOBAL_VAR Mouse_State null_mouse_state = {0};
|
||||
|
||||
/* DOC(
|
||||
Range describes an integer range typically used for ranges within a buffer. Ranges tend are usually not passed as a Range struct into the API, but this struct is used to return ranges.
|
||||
|
||||
|
@ -625,6 +611,26 @@ STRUCT Buffer_Summary{
|
|||
bool32 unwrapped_lines;
|
||||
};
|
||||
|
||||
GLOBAL_VAR Buffer_Summary null_buffer_summary = {0};
|
||||
|
||||
STRUCT i32_Rect{
|
||||
int32_t x0;
|
||||
int32_t y0;
|
||||
int32_t x1;
|
||||
int32_t y1;
|
||||
};
|
||||
|
||||
GLOBAL_VAR i32_Rect null_i32_rect = {0};
|
||||
|
||||
STRUCT f32_Rect{
|
||||
float x0;
|
||||
float y0;
|
||||
float x1;
|
||||
float y1;
|
||||
};
|
||||
|
||||
GLOBAL_VAR f32_Rect null_f32_rect = {0};
|
||||
|
||||
/* DOC(View_Summary acts as a handle to a view and describes the state of the view.)
|
||||
DOC_SEE(Access_Flag)
|
||||
DOC_SEE(Full_Cursor) */
|
||||
|
@ -659,31 +665,14 @@ STRUCT View_Summary{
|
|||
GUI_Scroll_Vars scroll_vars;
|
||||
};
|
||||
|
||||
/*
|
||||
DOC(User_Input describes a user input event which can be either a key press or mouse event.)
|
||||
DOC_SEE(User_Input_Type_ID)
|
||||
DOC_SEE(Generic_Command)
|
||||
*/
|
||||
STRUCT User_Input{
|
||||
/* DOC(This field specifies whether the event was a key press or mouse event.) */
|
||||
User_Input_Type_ID type;
|
||||
/* DOC(This field indicates that an abort event has occurred and the command needs to shut down.) */
|
||||
bool32 abort;
|
||||
UNION{
|
||||
/* DOC(This field describes a key press event.) */
|
||||
Key_Event_Data key;
|
||||
/* DOC(This field describes a mouse input event.) */
|
||||
Mouse_State mouse;
|
||||
};
|
||||
/* DOC(If this event would trigger a command, this field specifies what the command would be.) */
|
||||
Generic_Command command;
|
||||
};
|
||||
GLOBAL_VAR View_Summary null_view_summary = {0};
|
||||
|
||||
/* DOC(Query_Bar is a struct used to store information in the user's control
|
||||
that will be displayed as a drop down bar durring an interactive command.) */
|
||||
STRUCT Query_Bar{
|
||||
/* DOC(This specifies the prompt portion of the drop down bar.) */
|
||||
String prompt;
|
||||
|
||||
/* DOC(This specifies the main string portion of the drop down bar.) */
|
||||
String string;
|
||||
};
|
||||
|
@ -710,14 +699,12 @@ STRUCT Theme_Color{
|
|||
ENUM(int32_t, Buffer_Batch_Edit_Type){
|
||||
/* DOC(The BatchEdit_Normal operation is always correct but does the most work if there are tokens to correct.) */
|
||||
BatchEdit_Normal,
|
||||
/* DOC(The BatchEdit_PreserveTokens operation is one in which none of the edits add, delete, or change any tokens.
|
||||
This usually applies when whitespace is being replaced with whitespace.) */
|
||||
/* DOC(The BatchEdit_PreserveTokens operation is one in which none of the edits add, delete, or change any tokens. This usually applies when whitespace is being replaced with whitespace.) */
|
||||
BatchEdit_PreserveTokens
|
||||
};
|
||||
|
||||
/*
|
||||
DOC(This struct is used to bundle the parameters of the buffer_batch_edit function. It is convenient
|
||||
for a few functions that return a batch edit to the user.)
|
||||
DOC(This struct is used to bundle the parameters of the buffer_batch_edit function. It is convenient for a few functions that return a batch edit to the user.)
|
||||
DOC_SEE(buffer_batch_edit)
|
||||
*/
|
||||
STRUCT Buffer_Batch_Edit{
|
||||
|
@ -733,3 +720,138 @@ STRUCT Buffer_Batch_Edit{
|
|||
};
|
||||
|
||||
|
||||
/* DOC(Custom_Command_Function is a function type which matches the signature used for commands. To declare a command use CUSTOM_COMMAND_SIG.) DOC_SEE(CUSTOM_COMMAND_SIG) */
|
||||
TYPEDEF void Custom_Command_Function(struct Application_Links *app);
|
||||
|
||||
// TODO(allen): Improve meta system so that the system for picking up macros is universal.
|
||||
#define CUSTOM_COMMAND_SIG(name) void name(struct Application_Links *app)
|
||||
|
||||
|
||||
/* DOC(Generic_Command acts as a name for a command, and can name an internal command or a custom command.) */
|
||||
UNION Generic_Command{
|
||||
/*DOC(If this Generic_Command represents an internal command the cmdid field will have a value less than cmdid_count, and this field is the command id for the command.)*/
|
||||
Command_ID cmdid;
|
||||
/*DOC(If this Generic_Command does not represent an internal command the command
|
||||
field is the pointer to the custom command..)*/
|
||||
Custom_Command_Function *command;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
DOC(User_Input describes a user input event which can be either a key press or mouse event.)
|
||||
DOC_SEE(User_Input_Type_ID)
|
||||
DOC_SEE(Generic_Command)
|
||||
*/
|
||||
STRUCT User_Input{
|
||||
/* DOC(This field specifies whether the event was a key press or mouse event.) */
|
||||
User_Input_Type_ID type;
|
||||
/* DOC(This field indicates that an abort event has occurred and the command needs to shut down.) */
|
||||
bool32 abort;
|
||||
UNION{
|
||||
/* DOC(This field describes a key press event.) */
|
||||
Key_Event_Data key;
|
||||
/* DOC(This field describes a mouse input event.) */
|
||||
Mouse_State mouse;
|
||||
};
|
||||
/* DOC(If this event would trigger a command, this field specifies what the command would be.) */
|
||||
Generic_Command command;
|
||||
};
|
||||
|
||||
|
||||
/* DOC(Hook_IDs name the various hooks into 4coder, these hooks use the Hook_Function signature.)
|
||||
DOC_SEE(Hook_Function) */
|
||||
ENUM(int32_t, Hook_ID){
|
||||
/* DOC(TODO) */
|
||||
hook_start,
|
||||
/* DOC(TODO) */
|
||||
hook_file_out_of_sync,
|
||||
/* DOC(TODO) */
|
||||
hook_exit,
|
||||
/* DOC(TODO) */
|
||||
hook_view_size_change,
|
||||
// never below this
|
||||
hook_type_count
|
||||
};
|
||||
|
||||
/* DOC(Special_Hook_IDs name special hooks that use specialized signatures.) */
|
||||
ENUM(int32_t, Special_Hook_ID){
|
||||
/* DOC(TODO) */
|
||||
special_hook_scroll_rule = hook_type_count,
|
||||
/* DOC(TODO) */
|
||||
special_hook_new_file,
|
||||
/* DOC(TODO) */
|
||||
special_hook_open_file,
|
||||
/* DOC(TODO) */
|
||||
special_hook_save_file,
|
||||
/* DOC(TODO) */
|
||||
special_hook_command_caller,
|
||||
/* DOC(TODO) */
|
||||
special_hook_input_filter,
|
||||
};
|
||||
|
||||
TYPEDEF_FUNC int32_t Command_Caller_Hook_Function(struct Application_Links *app, Generic_Command cmd);
|
||||
#define COMMAND_CALLER_HOOK(name) int32_t name(struct Application_Links *app, Generic_Command cmd)
|
||||
|
||||
TYPEDEF_FUNC int32_t Hook_Function(struct Application_Links *app);
|
||||
#define HOOK_SIG(name) int32_t name(struct Application_Links *app)
|
||||
|
||||
TYPEDEF_FUNC int32_t Open_File_Hook_Function(struct Application_Links *app, int32_t buffer_id);
|
||||
#define OPEN_FILE_HOOK_SIG(name) int32_t name(struct Application_Links *app, int32_t buffer_id)
|
||||
|
||||
TYPEDEF_FUNC void Input_Filter_Function(Mouse_State *mouse);
|
||||
#define INPUT_FILTER_SIG(name) void name(Mouse_State *mouse)
|
||||
|
||||
TYPEDEF_FUNC int32_t Scroll_Rule_Function(float target_x, float target_y, float *scroll_x, float *scroll_y, int32_t view_id, int32_t is_new_target, float dt);
|
||||
#define SCROLL_RULE_SIG(name) \
|
||||
int32_t name(float target_x, float target_y, float *scroll_x, float *scroll_y, int32_t view_id, int32_t is_new_target, float dt)
|
||||
|
||||
TYPEDEF_FUNC int32_t Get_Binding_Data_Function(void *data, int32_t size);
|
||||
#define GET_BINDING_DATA(name) int32_t name(void *data, int32_t size)
|
||||
|
||||
// NOTE(allen): Definitions for the format that Get_Binding_Data uses to launch 4coder.
|
||||
// TODO(allen): Find a way to transition to a more dynamic Command_Map system.
|
||||
|
||||
ENUM(int32_t, Binding_Unit_Type){
|
||||
unit_header,
|
||||
unit_map_begin,
|
||||
unit_binding,
|
||||
unit_callback,
|
||||
unit_inherit,
|
||||
unit_hook
|
||||
};
|
||||
|
||||
ENUM(int32_t, Map_ID){
|
||||
mapid_global = (1 << 24),
|
||||
mapid_file,
|
||||
mapid_nomap
|
||||
};
|
||||
|
||||
STRUCT Binding_Unit{
|
||||
Binding_Unit_Type type;
|
||||
UNION{
|
||||
STRUCT{ int32_t total_size; int32_t user_map_count; int32_t error; } header;
|
||||
|
||||
STRUCT{ int32_t mapid; int32_t replace; int32_t bind_count; } map_begin;
|
||||
STRUCT{ int32_t mapid; } map_inherit;
|
||||
STRUCT{
|
||||
int16_t code;
|
||||
uint8_t modifiers;
|
||||
int32_t command_id;
|
||||
} binding;
|
||||
STRUCT{
|
||||
int16_t code;
|
||||
uint8_t modifiers;
|
||||
Custom_Command_Function *func;
|
||||
} callback;
|
||||
STRUCT{
|
||||
int32_t hook_id;
|
||||
void *func;
|
||||
} hook;
|
||||
};
|
||||
};
|
||||
|
||||
typedef int32_t _Get_Version_Function(int32_t maj, int32_t min, int32_t patch);
|
||||
#define _GET_VERSION_SIG(n) int32_t n(int32_t maj, int32_t min, int32_t patch)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +1,27 @@
|
|||
/*
|
||||
4coder_auto_indent.cpp - Commands for auto-indentation of C++ code.
|
||||
|
||||
#ifndef FCODER_AUTO_INDENT_INC
|
||||
#define FCODER_AUTO_INDENT_INC
|
||||
TYPE: 'drop-in-command-pack'
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_AUTO_INDENT_CPP)
|
||||
#define FCODER_AUTO_INDENT_CPP
|
||||
|
||||
#include "4coder_base_commands.cpp"
|
||||
#include "4coder_helper/4coder_streaming.h"
|
||||
#include "4coder_helper/4coder_long_seek.h"
|
||||
#include "4coder_lib/4coder_mem.h"
|
||||
#include "4coder_default_framework.h"
|
||||
|
||||
#if !defined(DEFAULT_INDENT_FLAGS)
|
||||
# define DEFAULT_INDENT_FLAGS 0
|
||||
#endif
|
||||
|
||||
#if !defined(DEF_TAB_WIDTH)
|
||||
# define DEF_TAB_WIDTH 4
|
||||
#endif
|
||||
|
||||
//
|
||||
// Generic Line Indenter
|
||||
|
@ -67,9 +88,7 @@ struct Indent_Options{
|
|||
};
|
||||
|
||||
static Buffer_Batch_Edit
|
||||
make_batch_from_indent_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
int32_t line_start, int32_t line_end, int32_t *indent_marks,
|
||||
Indent_Options opts){
|
||||
make_batch_from_indent_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer, int32_t line_start, int32_t line_end, int32_t *indent_marks, Indent_Options opts){
|
||||
|
||||
Buffer_Batch_Edit result = {0};
|
||||
|
||||
|
@ -140,20 +159,18 @@ make_batch_from_indent_marks(Application_Links *app, Partition *part, Buffer_Sum
|
|||
}
|
||||
|
||||
static void
|
||||
set_line_indents(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
int32_t line_start, int32_t line_end, int32_t *indent_marks, Indent_Options opts){
|
||||
set_line_indents(Application_Links *app, Partition *part, Buffer_Summary *buffer, int32_t line_start, int32_t line_end, int32_t *indent_marks, Indent_Options opts){
|
||||
Buffer_Batch_Edit batch =
|
||||
make_batch_from_indent_marks(app, part, buffer, line_start, line_end, indent_marks, opts);
|
||||
|
||||
if (batch.edit_count > 0){
|
||||
buffer_batch_edit(app, buffer, batch.str, batch.str_len,
|
||||
batch.edits, batch.edit_count, BatchEdit_PreserveTokens);
|
||||
batch.edits, batch.edit_count, BatchEdit_PreserveTokens);
|
||||
}
|
||||
}
|
||||
|
||||
static Cpp_Token*
|
||||
seek_matching_token_backwards(Cpp_Token_Array tokens, Cpp_Token *token,
|
||||
Cpp_Token_Type open_type, Cpp_Token_Type close_type){
|
||||
seek_matching_token_backwards(Cpp_Token_Array tokens, Cpp_Token *token, Cpp_Token_Type open_type, Cpp_Token_Type close_type){
|
||||
int32_t nesting_level = 0;
|
||||
if (token <= tokens.tokens){
|
||||
token = tokens.tokens;
|
||||
|
@ -179,8 +196,7 @@ seek_matching_token_backwards(Cpp_Token_Array tokens, Cpp_Token *token,
|
|||
}
|
||||
|
||||
static Cpp_Token*
|
||||
find_anchor_token(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens,
|
||||
int32_t line_start, int32_t tab_width, int32_t *current_indent_out){
|
||||
find_anchor_token(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line_start, int32_t tab_width, int32_t *current_indent_out){
|
||||
Cpp_Token *token = get_first_token_at_line(app, buffer, tokens, line_start);
|
||||
|
||||
if (token == 0 && tokens.count == 0){
|
||||
|
@ -282,9 +298,7 @@ struct Indent_Parse_State{
|
|||
};
|
||||
|
||||
static int32_t*
|
||||
get_indentation_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
Cpp_Token_Array tokens, int32_t line_start, int32_t line_end,
|
||||
bool32 exact_align, int32_t tab_width){
|
||||
get_indentation_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line_start, int32_t line_end, bool32 exact_align, int32_t tab_width){
|
||||
|
||||
int32_t indent_mark_count = line_end - line_start;
|
||||
int32_t *indent_marks = push_array(part, int32_t, indent_mark_count);
|
||||
|
@ -595,5 +609,56 @@ buffer_auto_indent(Application_Links *app, Buffer_Summary *buffer, int32_t start
|
|||
return(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Commands
|
||||
//
|
||||
|
||||
static void
|
||||
auto_tab_whole_file_by_summary(Application_Links *app, Buffer_Summary *buffer){
|
||||
buffer_auto_indent(app, buffer, 0, buffer->size, DEF_TAB_WIDTH, DEFAULT_INDENT_FLAGS | AutoIndent_FullTokens);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(auto_tab_whole_file){
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
auto_tab_whole_file_by_summary(app, &buffer);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
buffer_auto_indent(app, &buffer, view.cursor.pos, view.cursor.pos, DEF_TAB_WIDTH, DEFAULT_INDENT_FLAGS | AutoIndent_FullTokens);
|
||||
move_past_lead_whitespace(app, &view, &buffer);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(auto_tab_range){
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
Range range = get_range(&view);
|
||||
|
||||
buffer_auto_indent(app, &buffer, range.min, range.max, DEF_TAB_WIDTH, DEFAULT_INDENT_FLAGS | AutoIndent_FullTokens);
|
||||
move_past_lead_whitespace(app, &view, &buffer);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_and_auto_tab){
|
||||
exec_command(app, write_character);
|
||||
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
buffer_auto_indent(app, &buffer, view.cursor.pos, view.cursor.pos, DEF_TAB_WIDTH, DEFAULT_INDENT_FLAGS | AutoIndent_ExactAlignBlock);
|
||||
move_past_lead_whitespace(app, &view, &buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -0,0 +1,841 @@
|
|||
/*
|
||||
4coder_base_commands.cpp - Base commands such as inserting characters, and
|
||||
moving the cursor, which work even without the default 4coder framework.
|
||||
|
||||
TYPE: 'drop-in-command-pack'
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_BASE_COMMANDS_CPP)
|
||||
#define FCODER_BASE_COMMANDS_CPP
|
||||
|
||||
#include "4coder_helper/4coder_helper.h"
|
||||
#include "4coder_helper/4coder_long_seek.h"
|
||||
|
||||
//
|
||||
// Fundamental Editing Commands
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_character){
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
|
||||
User_Input in = get_command_input(app);
|
||||
char character = 0;
|
||||
|
||||
if (in.type == UserInputKey){
|
||||
character = in.key.character;
|
||||
}
|
||||
|
||||
if (character != 0){
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t pos = view.cursor.pos;
|
||||
buffer_replace_range(app, &buffer, pos, pos, &character, 1);
|
||||
view_set_cursor(app, &view, seek_pos(view.cursor.pos + 1), true);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(delete_char){
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t start = view.cursor.pos;
|
||||
|
||||
Full_Cursor cursor;
|
||||
view_compute_cursor(app, &view, seek_character_pos(view.cursor.character_pos+1), &cursor);
|
||||
int32_t end = cursor.pos;
|
||||
|
||||
if (0 <= start && start < buffer.size){
|
||||
buffer_replace_range(app, &buffer, start, end, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(backspace_char){
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t end = view.cursor.pos;
|
||||
|
||||
Full_Cursor cursor;
|
||||
view_compute_cursor(app, &view, seek_character_pos(view.cursor.character_pos-1), &cursor);
|
||||
int32_t start = cursor.pos;
|
||||
|
||||
if (0 < end && end <= buffer.size){
|
||||
buffer_replace_range(app, &buffer, start, end, 0, 0);
|
||||
view_set_cursor(app, &view, seek_character_pos(view.cursor.character_pos-1), true);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(set_mark){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
|
||||
view_set_mark(app, &view, seek_pos(view.cursor.pos));
|
||||
view_set_cursor(app, &view, seek_pos(view.cursor.pos), 1);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(cursor_mark_swap){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
|
||||
int32_t cursor = view.cursor.pos;
|
||||
int32_t mark = view.mark.pos;
|
||||
|
||||
view_set_cursor(app, &view, seek_pos(mark), true);
|
||||
view_set_mark(app, &view, seek_pos(cursor));
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(delete_range){
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
Range range = get_range(&view);
|
||||
buffer_replace_range(app, &buffer, range.min, range.max, 0, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Basic Navigation Commands
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(center_view){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
|
||||
i32_Rect region = view.file_region;
|
||||
GUI_Scroll_Vars scroll = view.scroll_vars;
|
||||
|
||||
float h = (float)(region.y1 - region.y0);
|
||||
float y = get_view_y(&view);
|
||||
y = y - h*.5f;
|
||||
scroll.target_y = (int32_t)(y + .5f);
|
||||
view_set_scroll(app, &view, scroll);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(left_adjust_view){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
|
||||
GUI_Scroll_Vars scroll = view.scroll_vars;
|
||||
|
||||
float x = get_view_x(&view) - 30.f;
|
||||
if (x < 0){
|
||||
x = 0.f;
|
||||
}
|
||||
|
||||
scroll.target_x = (int32_t)(x + .5f);
|
||||
view_set_scroll(app, &view, scroll);
|
||||
}
|
||||
|
||||
bool32
|
||||
global_point_to_view_point(View_Summary *view, int32_t x, int32_t y, float *x_out, float *y_out){
|
||||
bool32 result = false;
|
||||
|
||||
i32_Rect region = view->file_region;
|
||||
|
||||
int32_t max_x = (region.x1 - region.x0);
|
||||
int32_t max_y = (region.y1 - region.y0);
|
||||
GUI_Scroll_Vars scroll_vars = view->scroll_vars;
|
||||
|
||||
int32_t rx = x - region.x0;
|
||||
int32_t ry = y - region.y0;
|
||||
|
||||
if (ry >= 0 && rx >= 0 && rx < max_x && ry < max_y){
|
||||
result = 1;
|
||||
}
|
||||
|
||||
*x_out = (float)rx + scroll_vars.scroll_x;
|
||||
*y_out = (float)ry + scroll_vars.scroll_y;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(click_set_cursor){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
|
||||
Mouse_State mouse = get_mouse_state(app);
|
||||
float rx = 0, ry = 0;
|
||||
if (global_point_to_view_point(&view, mouse.x, mouse.y, &rx, &ry)){
|
||||
view_set_cursor(app, &view, seek_xy(rx, ry, 1, view.unwrapped_lines), 1);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(click_set_mark){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
|
||||
Mouse_State mouse = get_mouse_state(app);
|
||||
float rx = 0, ry = 0;
|
||||
if (global_point_to_view_point(&view, mouse.x, mouse.y, &rx, &ry)){
|
||||
view_set_mark(app, &view, seek_xy(rx, ry, 1, view.unwrapped_lines));
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
move_vertical(Application_Links *app, float line_multiplier){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
|
||||
float new_y = get_view_y(&view) + line_multiplier*view.line_height;
|
||||
float x = view.preferred_x;
|
||||
|
||||
view_set_cursor(app, &view, seek_xy(x, new_y, 0, view.unwrapped_lines), 0);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_up){
|
||||
move_vertical(app, -1.f);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_down){
|
||||
move_vertical(app, 1.f);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_up_10){
|
||||
move_vertical(app, -10.f);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_down_10){
|
||||
move_vertical(app, 10.f);
|
||||
}
|
||||
|
||||
static float
|
||||
get_page_jump(View_Summary *view){
|
||||
i32_Rect region = view->file_region;
|
||||
float page_jump = 1;
|
||||
|
||||
if (view->line_height > 0){
|
||||
page_jump = (float)(region.y1 - region.y0) / view->line_height;
|
||||
page_jump -= 3.f;
|
||||
if (page_jump <= 0){
|
||||
page_jump = 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
return(page_jump);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(page_up){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
float page_jump = get_page_jump(&view);
|
||||
move_vertical(app, -page_jump);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(page_down){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
float page_jump = get_page_jump(&view);
|
||||
move_vertical(app, page_jump);
|
||||
}
|
||||
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_left){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
int32_t new_pos = view.cursor.character_pos - 1;
|
||||
view_set_cursor(app, &view, seek_character_pos(new_pos), 1);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_right){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
int32_t new_pos = view.cursor.character_pos + 1;
|
||||
view_set_cursor(app, &view, seek_character_pos(new_pos), 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Long Seeks
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_whitespace_up){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t new_pos = buffer_seek_whitespace_up(app, &buffer, view.cursor.pos);
|
||||
view_set_cursor(app, &view, seek_pos(new_pos), true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_whitespace_down){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t new_pos = buffer_seek_whitespace_down(app, &buffer, view.cursor.pos);
|
||||
view_set_cursor(app, &view, seek_pos(new_pos), true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_end_of_textual_line){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t new_pos = seek_line_end(app, &buffer, view.cursor.pos);
|
||||
view_set_cursor(app, &view, seek_pos(new_pos), true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_beginning_of_textual_line){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t new_pos = seek_line_beginning(app, &buffer, view.cursor.pos);
|
||||
view_set_cursor(app, &view, seek_pos(new_pos), true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_beginning_of_line){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
|
||||
float y = view.cursor.wrapped_y;
|
||||
if (view.unwrapped_lines){
|
||||
y = view.cursor.unwrapped_y;
|
||||
}
|
||||
|
||||
view_set_cursor(app, &view, seek_xy(0, y, 1, view.unwrapped_lines), 1);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_end_of_line){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
|
||||
float y = view.cursor.wrapped_y;
|
||||
if (view.unwrapped_lines){
|
||||
y = view.cursor.unwrapped_y;
|
||||
}
|
||||
|
||||
view_set_cursor(app, &view, seek_xy(100000.f, y, 1, view.unwrapped_lines), 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Fancy Editing
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(to_uppercase){
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
|
||||
Range range = get_range(&view);
|
||||
int32_t size = range.max - range.min;
|
||||
if (size <= app->memory_size){
|
||||
char *mem = (char*)app->memory;
|
||||
|
||||
buffer_read_range(app, &buffer, range.min, range.max, mem);
|
||||
for (int32_t i = 0; i < size; ++i){
|
||||
mem[i] = char_to_upper(mem[i]);
|
||||
}
|
||||
buffer_replace_range(app, &buffer, range.min, range.max, mem, size);
|
||||
view_set_cursor(app, &view, seek_pos(range.max), true);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(to_lowercase){
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
|
||||
Range range = get_range(&view);
|
||||
int32_t size = range.max - range.min;
|
||||
if (size <= app->memory_size){
|
||||
char *mem = (char*)app->memory;
|
||||
|
||||
buffer_read_range(app, &buffer, range.min, range.max, mem);
|
||||
for (int32_t i = 0; i < size; ++i){
|
||||
mem[i] = char_to_lower(mem[i]);
|
||||
}
|
||||
buffer_replace_range(app, &buffer, range.min, range.max, mem, size);
|
||||
view_set_cursor(app, &view, seek_pos(range.max), true);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(clean_all_lines){
|
||||
// TODO(allen): This command always iterates accross the entire
|
||||
// buffer, so streaming it is actually the wrong call. Rewrite this
|
||||
// to minimize calls to buffer_read_range.
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
|
||||
int32_t line_count = buffer.line_count;
|
||||
int32_t edit_max = line_count;
|
||||
|
||||
if (edit_max*sizeof(Buffer_Edit) < app->memory_size){
|
||||
Buffer_Edit *edits = (Buffer_Edit*)app->memory;
|
||||
|
||||
char data[1024];
|
||||
Stream_Chunk chunk = {0};
|
||||
|
||||
int32_t i = 0;
|
||||
if (init_stream_chunk(&chunk, app, &buffer, i, data, sizeof(data))){
|
||||
Buffer_Edit *edit = edits;
|
||||
|
||||
int32_t buffer_size = buffer.size;
|
||||
int32_t still_looping = true;
|
||||
int32_t last_hard = buffer_size;
|
||||
do{
|
||||
for (; i < chunk.end; ++i){
|
||||
char at_pos = chunk.data[i];
|
||||
if (at_pos == '\n'){
|
||||
if (last_hard+1 < i){
|
||||
edit->str_start = 0;
|
||||
edit->len = 0;
|
||||
edit->start = last_hard+1;
|
||||
edit->end = i;
|
||||
++edit;
|
||||
}
|
||||
last_hard = buffer_size;
|
||||
}
|
||||
else if (char_is_whitespace(at_pos)){
|
||||
// NOTE(allen): do nothing
|
||||
}
|
||||
else{
|
||||
last_hard = i;
|
||||
}
|
||||
}
|
||||
|
||||
still_looping = forward_stream_chunk(&chunk);
|
||||
}while(still_looping);
|
||||
|
||||
if (last_hard+1 < buffer_size){
|
||||
edit->str_start = 0;
|
||||
edit->len = 0;
|
||||
edit->start = last_hard+1;
|
||||
edit->end = buffer_size;
|
||||
++edit;
|
||||
}
|
||||
|
||||
int32_t edit_count = (int32_t)(edit - edits);
|
||||
buffer_batch_edit(app, &buffer, 0, 0, edits, edit_count, BatchEdit_PreserveTokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Scroll Bar Controlling
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(show_scrollbar){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
view_set_setting(app, &view, ViewSetting_ShowScrollbar, true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(hide_scrollbar){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
view_set_setting(app, &view, ViewSetting_ShowScrollbar, false);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Basic Panel Management
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(basic_change_active_panel){
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
get_view_next_looped(app, &view, AccessAll);
|
||||
set_active_view(app, &view);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(close_panel){
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
close_view(app, &view);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_panel_vsplit){
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
View_Summary new_view = open_view(app, &view, ViewSplit_Right);
|
||||
view_set_setting(app, &new_view, ViewSetting_ShowScrollbar, false);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_panel_hsplit){
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
View_Summary new_view = open_view(app, &view, ViewSplit_Bottom);
|
||||
view_set_setting(app, &new_view, ViewSetting_ShowScrollbar, false);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Common Settings Commands
|
||||
//
|
||||
|
||||
//toggle_fullscreen can be used as a command
|
||||
|
||||
CUSTOM_COMMAND_SIG(toggle_line_wrap){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
|
||||
|
||||
bool32 unwrapped = view.unwrapped_lines;
|
||||
buffer_set_setting(app, &buffer, BufferSetting_WrapLine, unwrapped);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(increase_line_wrap){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
|
||||
|
||||
int32_t wrap = 0;
|
||||
buffer_get_setting(app, &buffer, BufferSetting_WrapPosition, &wrap);
|
||||
buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, wrap + 10);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(decrease_line_wrap){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
|
||||
|
||||
int32_t wrap = 0;
|
||||
buffer_get_setting(app, &buffer, BufferSetting_WrapPosition, &wrap);
|
||||
buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, wrap - 10);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(toggle_virtual_whitespace){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
|
||||
|
||||
int32_t vwhite = 0;
|
||||
buffer_get_setting(app, &buffer, BufferSetting_VirtualWhitespace, &vwhite);
|
||||
buffer_set_setting(app, &buffer, BufferSetting_VirtualWhitespace, !vwhite);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(toggle_show_whitespace){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
view_set_setting(app, &view, ViewSetting_ShowWhitespace, !view.show_whitespace);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(eol_dosify){
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
buffer_set_setting(app, &buffer, BufferSetting_Eol, 1);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(eol_nixify){
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
buffer_set_setting(app, &buffer, BufferSetting_Eol, 0);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(exit_4coder){
|
||||
send_exit_signal(app);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Interactive Commands
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(goto_line){
|
||||
uint32_t access = AccessProtected;
|
||||
|
||||
Query_Bar bar = {0};
|
||||
char string_space[256];
|
||||
|
||||
bar.prompt = make_lit_string("Goto Line: ");
|
||||
bar.string = make_fixed_width_string(string_space);
|
||||
|
||||
if (query_user_number(app, &bar)){
|
||||
int32_t line_number = str_to_int_s(bar.string);
|
||||
|
||||
View_Summary view = get_active_view(app, access);
|
||||
view_set_cursor(app, &view, seek_line_char(line_number, 0), true);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(search);
|
||||
CUSTOM_COMMAND_SIG(reverse_search);
|
||||
|
||||
static void
|
||||
isearch(Application_Links *app, int32_t start_reversed){
|
||||
uint32_t access = AccessProtected;
|
||||
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
if (!buffer.exists) return;
|
||||
|
||||
Query_Bar bar = {0};
|
||||
if (start_query_bar(app, &bar, 0) == 0) return;
|
||||
|
||||
int32_t reverse = start_reversed;
|
||||
int32_t pos = view.cursor.pos;
|
||||
int32_t start_pos = pos;
|
||||
int32_t first_pos = pos;
|
||||
Range match = make_range(pos, pos);
|
||||
|
||||
char bar_string_space[256];
|
||||
bar.string = make_fixed_width_string(bar_string_space);
|
||||
|
||||
String isearch_str = make_lit_string("I-Search: ");
|
||||
String rsearch_str = make_lit_string("Reverse-I-Search: ");
|
||||
|
||||
User_Input in = {0};
|
||||
for (;;){
|
||||
view_set_highlight(app, &view, match.start, match.end, true);
|
||||
|
||||
// NOTE(allen): Change the bar's prompt to match the current direction.
|
||||
if (reverse) bar.prompt = rsearch_str;
|
||||
else bar.prompt = isearch_str;
|
||||
|
||||
in = get_user_input(app, EventOnAnyKey, EventOnEsc | EventOnButton);
|
||||
if (in.abort) break;
|
||||
|
||||
// NOTE(allen): If we're getting mouse events here it's a 4coder bug, because we
|
||||
// only asked to intercept key events.
|
||||
Assert(in.type == UserInputKey);
|
||||
|
||||
int32_t made_change = 0;
|
||||
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
|
||||
break;
|
||||
}
|
||||
else if (in.key.character && key_is_unmodified(&in.key)){
|
||||
append_s_char(&bar.string, in.key.character);
|
||||
made_change = 1;
|
||||
}
|
||||
else if (in.key.keycode == key_back){
|
||||
if (bar.string.size > 0){
|
||||
--bar.string.size;
|
||||
made_change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t step_forward = 0;
|
||||
int32_t step_backward = 0;
|
||||
|
||||
if ((in.command.command == search) ||
|
||||
in.key.keycode == key_page_down || in.key.keycode == key_down) step_forward = 1;
|
||||
if ((in.command.command == reverse_search) ||
|
||||
in.key.keycode == key_page_up || in.key.keycode == key_up) step_backward = 1;
|
||||
|
||||
start_pos = pos;
|
||||
if (step_forward && reverse){
|
||||
start_pos = match.start + 1;
|
||||
pos = start_pos;
|
||||
reverse = 0;
|
||||
step_forward = 0;
|
||||
}
|
||||
if (step_backward && !reverse){
|
||||
start_pos = match.start - 1;
|
||||
pos = start_pos;
|
||||
reverse = 1;
|
||||
step_backward = 0;
|
||||
}
|
||||
|
||||
if (in.key.keycode != key_back){
|
||||
int32_t new_pos;
|
||||
if (reverse){
|
||||
buffer_seek_string_insensitive_backward(app, &buffer, start_pos - 1, 0,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos >= 0){
|
||||
if (step_backward){
|
||||
pos = new_pos;
|
||||
start_pos = new_pos;
|
||||
buffer_seek_string_insensitive_backward(app, &buffer, start_pos - 1, 0,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos < 0) new_pos = start_pos;
|
||||
}
|
||||
match.start = new_pos;
|
||||
match.end = match.start + bar.string.size;
|
||||
}
|
||||
}
|
||||
else{
|
||||
buffer_seek_string_insensitive_forward(app, &buffer, start_pos + 1, 0,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos < buffer.size){
|
||||
if (step_forward){
|
||||
pos = new_pos;
|
||||
start_pos = new_pos;
|
||||
buffer_seek_string_insensitive_forward(app, &buffer, start_pos + 1, 0,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos >= buffer.size) new_pos = start_pos;
|
||||
}
|
||||
match.start = new_pos;
|
||||
match.end = match.start + bar.string.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (match.end > match.start + bar.string.size){
|
||||
match.end = match.start + bar.string.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
view_set_highlight(app, &view, 0, 0, false);
|
||||
if (in.abort){
|
||||
view_set_cursor(app, &view, seek_pos(first_pos), true);
|
||||
return;
|
||||
}
|
||||
|
||||
view_set_cursor(app, &view, seek_pos(match.min), true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(search){
|
||||
isearch(app, false);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(reverse_search){
|
||||
isearch(app, true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(replace_in_range){
|
||||
Query_Bar replace;
|
||||
char replace_space[1024];
|
||||
replace.prompt = make_lit_string("Replace: ");
|
||||
replace.string = make_fixed_width_string(replace_space);
|
||||
|
||||
Query_Bar with;
|
||||
char with_space[1024];
|
||||
with.prompt = make_lit_string("With: ");
|
||||
with.string = make_fixed_width_string(with_space);
|
||||
|
||||
if (!query_user_string(app, &replace)) return;
|
||||
if (replace.string.size == 0) return;
|
||||
|
||||
if (!query_user_string(app, &with)) return;
|
||||
|
||||
String r = replace.string, w = with.string;
|
||||
|
||||
uint32_t access = AccessOpen;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
Range range = get_range(&view);
|
||||
|
||||
int32_t pos, new_pos;
|
||||
pos = range.min;
|
||||
|
||||
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
|
||||
|
||||
while (new_pos + r.size <= range.end){
|
||||
buffer_replace_range(app, &buffer, new_pos, new_pos + r.size, w.str, w.size);
|
||||
refresh_view(app, &view);
|
||||
range = get_range(&view);
|
||||
pos = new_pos + w.size;
|
||||
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(query_replace){
|
||||
Query_Bar replace;
|
||||
char replace_space[1024];
|
||||
replace.prompt = make_lit_string("Replace: ");
|
||||
replace.string = make_fixed_width_string(replace_space);
|
||||
|
||||
Query_Bar with;
|
||||
char with_space[1024];
|
||||
with.prompt = make_lit_string("With: ");
|
||||
with.string = make_fixed_width_string(with_space);
|
||||
|
||||
if (!query_user_string(app, &replace)) return;
|
||||
if (replace.string.size == 0) return;
|
||||
|
||||
if (!query_user_string(app, &with)) return;
|
||||
|
||||
String r, w;
|
||||
r = replace.string;
|
||||
w = with.string;
|
||||
|
||||
Query_Bar bar;
|
||||
Buffer_Summary buffer;
|
||||
View_Summary view;
|
||||
int32_t pos, new_pos;
|
||||
|
||||
bar.prompt = make_lit_string("Replace? (y)es, (n)ext, (esc)\n");
|
||||
bar.string = null_string;
|
||||
|
||||
start_query_bar(app, &bar, 0);
|
||||
|
||||
uint32_t access = AccessOpen;
|
||||
view = get_active_view(app, access);
|
||||
buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
pos = view.cursor.pos;
|
||||
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
|
||||
|
||||
User_Input in = {0};
|
||||
while (new_pos < buffer.size){
|
||||
Range match = make_range(new_pos, new_pos + r.size);
|
||||
view_set_highlight(app, &view, match.min, match.max, 1);
|
||||
|
||||
in = get_user_input(app, EventOnAnyKey, EventOnButton);
|
||||
if (in.abort || in.key.keycode == key_esc || !key_is_unmodified(&in.key)) break;
|
||||
|
||||
if (in.key.character == 'y' ||
|
||||
in.key.character == 'Y' ||
|
||||
in.key.character == '\n' ||
|
||||
in.key.character == '\t'){
|
||||
buffer_replace_range(app, &buffer, match.min, match.max, w.str, w.size);
|
||||
pos = match.start + w.size;
|
||||
}
|
||||
else{
|
||||
pos = match.max;
|
||||
}
|
||||
|
||||
buffer_seek_string_forward(app, &buffer, pos, 0, r.str, r.size, &new_pos);
|
||||
}
|
||||
|
||||
view_set_highlight(app, &view, 0, 0, 0);
|
||||
if (in.abort) return;
|
||||
|
||||
view_set_cursor(app, &view, seek_pos(pos), 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// cmdid wrappers
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(undo){
|
||||
exec_command(app, cmdid_undo);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(redo){
|
||||
exec_command(app, cmdid_redo);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(interactive_new){
|
||||
exec_command(app, cmdid_interactive_new);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(interactive_open){
|
||||
exec_command(app, cmdid_interactive_open);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(save_as){
|
||||
exec_command(app, cmdid_save_as);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(interactive_switch_buffer){
|
||||
exec_command(app, cmdid_interactive_switch_buffer);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(interactive_kill_buffer){
|
||||
exec_command(app, cmdid_interactive_kill_buffer);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(reopen){
|
||||
exec_command(app, cmdid_reopen);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(save){
|
||||
exec_command(app, cmdid_save);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(kill_buffer){
|
||||
exec_command(app, cmdid_kill_buffer);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_color_tweaker){
|
||||
exec_command(app, cmdid_open_color_tweaker);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_config){
|
||||
exec_command(app, cmdid_open_config);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_menu){
|
||||
exec_command(app, cmdid_open_menu);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_debug){
|
||||
exec_command(app, cmdid_open_debug);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
165
4coder_custom.h
165
4coder_custom.h
|
@ -1,165 +0,0 @@
|
|||
|
||||
#ifndef FCODER_CUSTOM_H
|
||||
#define FCODER_CUSTOM_H
|
||||
|
||||
#include <stdint.h>
|
||||
// TODO(allen): We need to eliminate our dependence on this soon.
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "common/4coder_version.h"
|
||||
#include "4coder_keycodes.h"
|
||||
#include "4coder_style.h"
|
||||
#include "4coder_rect.h"
|
||||
#include "4coder_mem.h"
|
||||
#include "4cpp_lexer_types.h"
|
||||
|
||||
// TODO(allen): We need to eliminate this soon.
|
||||
#ifndef FSTRING_STRUCT
|
||||
#define FSTRING_STRUCT
|
||||
typedef struct String{
|
||||
char *str;
|
||||
int32_t size;
|
||||
int32_t memory_size;
|
||||
} String;
|
||||
|
||||
typedef struct Offset_String{
|
||||
int32_t offset;
|
||||
int32_t size;
|
||||
} Offset_String;
|
||||
#endif
|
||||
|
||||
// These are regular hooks, any of them can be set to any function
|
||||
// that matches the HOOK_SIG pattern.
|
||||
enum Hook_ID{
|
||||
hook_start,
|
||||
hook_file_out_of_sync,
|
||||
hook_exit,
|
||||
hook_view_size_change,
|
||||
// never below this
|
||||
hook_type_count
|
||||
};
|
||||
|
||||
// These are for special hooks, each must bind to specialized signatures
|
||||
// that do not necessarily have access to the app pointer.
|
||||
enum Special_Hook_ID{
|
||||
_hook_scroll_rule = hook_type_count,
|
||||
_hook_new_file,
|
||||
_hook_open_file,
|
||||
_hook_save_file,
|
||||
_hook_command_caller,
|
||||
_hook_input_filter,
|
||||
};
|
||||
|
||||
#define CUSTOM_COMMAND_SIG(name) void name(struct Application_Links *app)
|
||||
typedef CUSTOM_COMMAND_SIG(Custom_Command_Function);
|
||||
|
||||
#include "4coder_types.h"
|
||||
#include "4coder_seek_types.h"
|
||||
#include "4coder_gui.h"
|
||||
|
||||
#define COMMAND_CALLER_HOOK(name) int32_t name(struct Application_Links *app, Generic_Command cmd)
|
||||
typedef COMMAND_CALLER_HOOK(Command_Caller_Hook_Function);
|
||||
|
||||
static Key_Event_Data null_key_event_data = {0};
|
||||
static Mouse_State null_mouse_state = {0};
|
||||
static Buffer_Summary null_buffer_summary = {0};
|
||||
static View_Summary null_view_summary = {0};
|
||||
|
||||
inline Range
|
||||
make_range(int32_t p1, int32_t p2){
|
||||
Range range;
|
||||
if (p1 < p2){
|
||||
range.min = p1;
|
||||
range.max = p2;
|
||||
}
|
||||
else{
|
||||
range.min = p2;
|
||||
range.max = p1;
|
||||
}
|
||||
return(range);
|
||||
}
|
||||
|
||||
#define HOOK_SIG(name) int32_t name(struct Application_Links *app)
|
||||
#define SCROLL_RULE_SIG(name) int32_t name(float target_x, float target_y, float *scroll_x, float *scroll_y, int32_t view_id, int32_t is_new_target, float dt)
|
||||
#define OPEN_FILE_HOOK_SIG(name) int32_t name(struct Application_Links *app, int32_t buffer_id)
|
||||
#define INPUT_FILTER_SIG(name) void name(Mouse_State *mouse)
|
||||
|
||||
typedef OPEN_FILE_HOOK_SIG(Open_File_Hook_Function);
|
||||
typedef HOOK_SIG(Hook_Function);
|
||||
typedef SCROLL_RULE_SIG(Scroll_Rule_Function);
|
||||
typedef INPUT_FILTER_SIG(Input_Filter_Function);
|
||||
|
||||
|
||||
|
||||
|
||||
struct Application_Links;
|
||||
#include "4coder_custom_api.h"
|
||||
|
||||
|
||||
|
||||
#define VIEW_ROUTINE_SIG(name) void name(struct Application_Links *app, int32_t view_id)
|
||||
#define GET_BINDING_DATA(name) int32_t name(void *data, int32_t size)
|
||||
#define _GET_VERSION_SIG(n) int32_t n(int32_t maj, int32_t min, int32_t patch)
|
||||
|
||||
typedef VIEW_ROUTINE_SIG(View_Routine_Function);
|
||||
typedef GET_BINDING_DATA(Get_Binding_Data_Function);
|
||||
typedef _GET_VERSION_SIG(_Get_Version_Function);
|
||||
|
||||
struct Custom_API{
|
||||
View_Routine_Function *view_routine;
|
||||
Get_Binding_Data_Function *get_bindings;
|
||||
_Get_Version_Function *get_alpha_4coder_version;
|
||||
};
|
||||
|
||||
extern "C" _GET_VERSION_SIG(get_alpha_4coder_version){
|
||||
int32_t result = (maj == MAJOR && min == MINOR && patch == PATCH);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// NOTE(allen): definitions for the buffer that communicates to 4ed.exe
|
||||
|
||||
enum Binding_Unit_Type{
|
||||
unit_header,
|
||||
unit_map_begin,
|
||||
unit_binding,
|
||||
unit_callback,
|
||||
unit_inherit,
|
||||
unit_hook
|
||||
};
|
||||
|
||||
enum Map_ID{
|
||||
mapid_global = (1 << 24),
|
||||
mapid_file,
|
||||
|
||||
// NOTE(allen): mapid_nomap will remain empty even if you attempt to fill it
|
||||
// it is for setting a map's parent to nothing, in cases where you don't want
|
||||
// to inherit from global (which is the default).
|
||||
mapid_nomap
|
||||
};
|
||||
|
||||
struct Binding_Unit{
|
||||
Binding_Unit_Type type;
|
||||
union{
|
||||
struct{ int32_t total_size; int32_t user_map_count; int32_t error; } header;
|
||||
|
||||
struct{ int32_t mapid; int32_t replace; int32_t bind_count; } map_begin;
|
||||
struct{ int32_t mapid; } map_inherit;
|
||||
struct{
|
||||
int16_t code;
|
||||
uint8_t modifiers;
|
||||
int32_t command_id;
|
||||
} binding;
|
||||
struct{
|
||||
int16_t code;
|
||||
uint8_t modifiers;
|
||||
Custom_Command_Function *func;
|
||||
} callback;
|
||||
struct{
|
||||
int32_t hook_id;
|
||||
void *func;
|
||||
} hook;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -11,7 +11,6 @@
|
|||
// 2^24 of them so don't be wasteful!
|
||||
enum My_Maps{
|
||||
my_code_map,
|
||||
|
||||
my_maps_count
|
||||
};
|
||||
|
||||
|
@ -31,15 +30,6 @@ CUSTOM_COMMAND_SIG(write_zero_struct){
|
|||
write_string(app, make_lit_string(" = {0};"));
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_capital){
|
||||
User_Input command_in = get_command_input(app);
|
||||
char c = command_in.key.character_no_caps_lock;
|
||||
if (c != 0){
|
||||
c = char_to_upper(c);
|
||||
write_string(app, make_string(&c, 1));
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(switch_to_compilation){
|
||||
|
||||
char name[] = "*compilation*";
|
||||
|
@ -119,31 +109,8 @@ CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line){
|
|||
}
|
||||
|
||||
HOOK_SIG(my_start){
|
||||
init_memory(app);
|
||||
|
||||
process_config_file(app);
|
||||
|
||||
change_theme(app, default_theme_name.str, default_theme_name.size);
|
||||
change_font(app, default_font_name.str, default_font_name.size, 1);
|
||||
|
||||
exec_command(app, open_panel_vsplit);
|
||||
exec_command(app, hide_scrollbar);
|
||||
exec_command(app, change_active_panel);
|
||||
exec_command(app, hide_scrollbar);
|
||||
|
||||
// Theme options:
|
||||
// "4coder"
|
||||
// "Handmade Hero"
|
||||
// "Twilight"
|
||||
// "Woverine"
|
||||
// "stb"
|
||||
|
||||
// Font options:
|
||||
// "Liberation Sans"
|
||||
// "Liberation Mono"
|
||||
// "Hack"
|
||||
// "Cutive Mono"
|
||||
// "Inconsolata"
|
||||
default_4coder_initialize(app);
|
||||
default_4coder_side_by_side_panels(app);
|
||||
|
||||
// no meaning for return
|
||||
return(0);
|
||||
|
@ -344,11 +311,11 @@ default_keys(Bind_Helper *context){
|
|||
bind(context, 'P', MDFR_CTRL, close_panel);
|
||||
bind(context, ',', MDFR_CTRL, change_active_panel);
|
||||
|
||||
bind(context, 'n', MDFR_CTRL, cmdid_interactive_new);
|
||||
bind(context, 'o', MDFR_CTRL, cmdid_interactive_open);
|
||||
bind(context, 'n', MDFR_CTRL, interactive_new);
|
||||
bind(context, 'o', MDFR_CTRL, interactive_open);
|
||||
bind(context, 'o', MDFR_ALT, open_in_other);
|
||||
bind(context, 'k', MDFR_CTRL, cmdid_interactive_kill_buffer);
|
||||
bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_buffer);
|
||||
bind(context, 'k', MDFR_CTRL, interactive_kill_buffer);
|
||||
bind(context, 'i', MDFR_CTRL, interactive_switch_buffer);
|
||||
bind(context, 'w', MDFR_CTRL, save_as);
|
||||
|
||||
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
|
||||
|
@ -492,8 +459,6 @@ default_keys(Bind_Helper *context){
|
|||
bind(context, 'F', MDFR_CTRL, list_all_locations);
|
||||
bind(context, 'F', MDFR_ALT, list_all_substring_locations_case_insensitive);
|
||||
bind(context, 'g', MDFR_CTRL, goto_line);
|
||||
bind(context, 'h', MDFR_CTRL, cmdid_history_backward);
|
||||
bind(context, 'H', MDFR_CTRL, cmdid_history_forward);
|
||||
bind(context, 'j', MDFR_CTRL, to_lowercase);
|
||||
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
|
||||
bind(context, 'l', MDFR_CTRL, toggle_line_wrap);
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
4coder_default_framework.cpp - Sets up the basics of the framework that is used
|
||||
for default 4coder behaviour.
|
||||
|
||||
TYPE: 'internal-for-default-system'
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_DEFAULT_FRAMEWORK_H)
|
||||
#define FCODER_DEFAULT_FRAMEWORK_H
|
||||
|
||||
#include "4coder_helper/4coder_helper.h"
|
||||
#include "4coder_lib/4coder_mem.h"
|
||||
|
||||
//
|
||||
// Global Memory
|
||||
//
|
||||
|
||||
static Partition global_part;
|
||||
static General_Memory global_general;
|
||||
|
||||
//
|
||||
// Jump Buffer Locking
|
||||
//
|
||||
|
||||
static char locked_buffer_space[256];
|
||||
static String locked_buffer = make_fixed_width_string(locked_buffer_space);
|
||||
|
||||
static void
|
||||
unlock_jump_buffer(){
|
||||
locked_buffer.size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lock_jump_buffer(char *name, int32_t size){
|
||||
copy(&locked_buffer, make_string(name, size));
|
||||
}
|
||||
|
||||
static void
|
||||
lock_jump_buffer(Buffer_Summary buffer){
|
||||
copy(&locked_buffer, make_string(buffer.buffer_name, buffer.buffer_name_len));
|
||||
}
|
||||
|
||||
static View_Summary
|
||||
get_view_for_locked_jump_buffer(Application_Links *app){
|
||||
View_Summary view = {0};
|
||||
|
||||
if (locked_buffer.size > 0){
|
||||
Buffer_Summary buffer = get_buffer_by_name(app, locked_buffer.str, locked_buffer.size, AccessAll);
|
||||
if (buffer.exists){
|
||||
view = get_first_view_with_buffer(app, buffer.buffer_id);
|
||||
}
|
||||
else{
|
||||
unlock_jump_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
return(view);
|
||||
}
|
||||
|
||||
//
|
||||
// Panel Management
|
||||
//
|
||||
|
||||
static View_ID special_note_view_id = 0;
|
||||
|
||||
static void
|
||||
close_special_note_view(Application_Links *app){
|
||||
View_Summary special_view = get_view(app, special_note_view_id, AccessAll);
|
||||
if (special_view.exists){
|
||||
close_view(app, &special_view);
|
||||
}
|
||||
special_note_view_id = 0;
|
||||
}
|
||||
|
||||
static View_Summary
|
||||
open_special_note_view(Application_Links *app, bool32 create_if_not_exist = true){
|
||||
View_Summary special_view = get_view(app, special_note_view_id, AccessAll);
|
||||
|
||||
if (create_if_not_exist && !special_view.exists){
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
special_view = open_view(app, &view, ViewSplit_Bottom);
|
||||
view_set_setting(app, &special_view, ViewSetting_ShowScrollbar, false);
|
||||
view_set_split_proportion(app, &special_view, .2f);
|
||||
set_active_view(app, &view);
|
||||
special_note_view_id = special_view.view_id;
|
||||
}
|
||||
|
||||
return(special_view);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(change_active_panel){
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
View_ID original_view_id = view.view_id;
|
||||
|
||||
do{
|
||||
get_view_next_looped(app, &view, AccessAll);
|
||||
if (view.view_id != special_note_view_id){
|
||||
break;
|
||||
}
|
||||
}while(view.view_id != original_view_id);
|
||||
|
||||
if (view.exists){
|
||||
set_active_view(app, &view);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// View Variabls
|
||||
//
|
||||
|
||||
enum Rewrite_Type{
|
||||
RewriteNone,
|
||||
RewritePaste,
|
||||
RewriteWordComplete
|
||||
};
|
||||
|
||||
struct View_Paste_Index{
|
||||
int32_t rewrite;
|
||||
int32_t next_rewrite;
|
||||
int32_t index;
|
||||
};
|
||||
|
||||
View_Paste_Index view_paste_index_[16];
|
||||
View_Paste_Index *view_paste_index = view_paste_index_ - 1;
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
File diff suppressed because it is too large
Load Diff
463
4coder_helper.h
463
4coder_helper.h
|
@ -1,463 +0,0 @@
|
|||
/*
|
||||
* Bind helper struct and functions
|
||||
*/
|
||||
|
||||
#ifndef FCODER_HELPER_H
|
||||
#define FCODER_HELPER_H
|
||||
|
||||
struct Bind_Helper{
|
||||
Binding_Unit *cursor, *start, *end;
|
||||
Binding_Unit *header, *group;
|
||||
int32_t write_total;
|
||||
int32_t 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 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 Bind_Helper
|
||||
begin_bind_helper(void *data, int32_t 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.user_map_count = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void
|
||||
begin_map_(Bind_Helper *helper, int32_t mapid, int32_t replace){
|
||||
if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END;
|
||||
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
|
||||
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_map_begin;
|
||||
unit.map_begin.mapid = mapid;
|
||||
unit.map_begin.replace = replace;
|
||||
helper->group = write_unit(helper, unit);
|
||||
helper->group->map_begin.bind_count = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
begin_map(Bind_Helper *helper, int32_t mapid){
|
||||
begin_map_(helper, mapid, 0);
|
||||
}
|
||||
|
||||
inline void
|
||||
restart_map(Bind_Helper *helper, int32_t mapid){
|
||||
begin_map_(helper, mapid, 1);
|
||||
}
|
||||
|
||||
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, int32_t 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(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, int32_t cmdid){
|
||||
bind(helper, 0, 0, cmdid);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){
|
||||
bind(helper, 0, 0, func);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, int32_t cmdid){
|
||||
bind(helper, 0, modifiers, cmdid);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, Custom_Command_Function *func){
|
||||
bind(helper, 0, modifiers, func);
|
||||
}
|
||||
|
||||
inline void
|
||||
inherit_map(Bind_Helper *helper, int32_t mapid){
|
||||
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
|
||||
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
|
||||
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_inherit;
|
||||
unit.map_inherit.mapid = mapid;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_hook(Bind_Helper *helper, int32_t hook_id, Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = hook_id;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_scroll_rule(Bind_Helper *helper, Scroll_Rule_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = _hook_scroll_rule;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_new_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = _hook_new_file;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_open_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = _hook_open_file;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_save_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = _hook_save_file;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_command_caller(Bind_Helper *helper, Command_Caller_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = _hook_command_caller;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_input_filter(Bind_Helper *helper, Input_Filter_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = _hook_input_filter;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
end_bind_helper(Bind_Helper *helper){
|
||||
int32_t result;
|
||||
if (helper->header){
|
||||
helper->header->header.total_size = (int32_t)(helper->cursor - helper->start);
|
||||
helper->header->header.error = helper->error;
|
||||
}
|
||||
result = helper->write_total;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Range
|
||||
get_range(View_Summary *view){
|
||||
Range range = make_range(view->cursor.pos, view->mark.pos);
|
||||
return(range);
|
||||
}
|
||||
|
||||
struct Buffer_Rect{
|
||||
int32_t char0,line0;
|
||||
int32_t char1,line1;
|
||||
};
|
||||
|
||||
#ifndef Swap
|
||||
#define Swap(T,a,b) do{ T t = a; a = b; b = t; } while(0)
|
||||
#endif
|
||||
|
||||
inline Buffer_Rect
|
||||
get_rect(View_Summary *view){
|
||||
Buffer_Rect rect = {0};
|
||||
|
||||
rect.char0 = view->mark.character;
|
||||
rect.line0 = view->mark.line;
|
||||
|
||||
rect.char1 = view->cursor.character;
|
||||
rect.line1 = view->cursor.line;
|
||||
|
||||
if (rect.line0 > rect.line1){
|
||||
Swap(int32_t, rect.line0, rect.line1);
|
||||
}
|
||||
if (rect.char0 > rect.char1){
|
||||
Swap(int32_t, rect.char0, rect.char1);
|
||||
}
|
||||
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
get_line_x_rect(View_Summary *view){
|
||||
i32_Rect rect = {0};
|
||||
|
||||
if (view->unwrapped_lines){
|
||||
rect.x0 = (int32_t)view->mark.unwrapped_x;
|
||||
rect.x1 = (int32_t)view->cursor.unwrapped_x;
|
||||
}
|
||||
else{
|
||||
rect.x0 = (int32_t)view->mark.wrapped_x;
|
||||
rect.x1 = (int32_t)view->cursor.wrapped_x;
|
||||
}
|
||||
rect.y0 = view->mark.line;
|
||||
rect.y1 = view->cursor.line;
|
||||
|
||||
if (rect.y0 > rect.y1){
|
||||
Swap(int32_t, rect.y0, rect.y1);
|
||||
}
|
||||
if (rect.x0 > rect.x1){
|
||||
Swap(int32_t, rect.x0, rect.x1);
|
||||
}
|
||||
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline void
|
||||
exec_command(Application_Links *app, Custom_Command_Function *func){
|
||||
func(app);
|
||||
}
|
||||
|
||||
inline void
|
||||
exec_command(Application_Links *app, Generic_Command cmd){
|
||||
if (cmd.cmdid < cmdid_count){
|
||||
exec_command(app, cmd.cmdid);
|
||||
}
|
||||
else{
|
||||
exec_command(app, cmd.command);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
active_view_to_line(Application_Links *app, uint32_t access, int32_t line_number){
|
||||
View_Summary view;
|
||||
view = get_active_view(app, access);
|
||||
|
||||
// NOTE(allen|a3.4.4): We don't have to worry about whether this is a valid line number.
|
||||
// When it's not possible to place a cursor at the position for whatever reason it will set the
|
||||
// cursor to a nearby valid position.
|
||||
view_set_cursor(app, &view, seek_line_char(line_number, 0), 1);
|
||||
}
|
||||
|
||||
inline View_Summary
|
||||
get_first_view_with_buffer(Application_Links *app, int32_t buffer_id){
|
||||
View_Summary result = {};
|
||||
View_Summary test = {};
|
||||
|
||||
if (buffer_id != 0){
|
||||
uint32_t access = AccessAll;
|
||||
for(test = get_view_first(app, access);
|
||||
test.exists;
|
||||
get_view_next(app, &test, access)){
|
||||
|
||||
Buffer_Summary buffer = get_buffer(app, test.buffer_id, access);
|
||||
|
||||
if(buffer.buffer_id == buffer_id){
|
||||
result = test;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
key_is_unmodified(Key_Event_Data *key){
|
||||
char *mods = key->modifiers;
|
||||
int32_t unmodified = !mods[MDFR_CONTROL_INDEX] && !mods[MDFR_ALT_INDEX];
|
||||
return(unmodified);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
query_user_general(Application_Links *app, Query_Bar *bar, int32_t force_number){
|
||||
User_Input in;
|
||||
int32_t success = 1;
|
||||
int32_t good_character = 0;
|
||||
|
||||
// NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to.
|
||||
// start a query bar, but it will be unusual behavior from the point of view of the
|
||||
// user, if this command starts intercepting input even though no prompt is shown.
|
||||
// This will only happen if you have a lot of bars open already or if the current view
|
||||
// doesn't support query bars.
|
||||
if (start_query_bar(app, bar, 0) == 0) return 0;
|
||||
|
||||
while (1){
|
||||
// NOTE(allen|a3.4.4): This call will block until the user does one of the input
|
||||
// types specified in the flags. The first set of flags are inputs you'd like to intercept
|
||||
// that you don't want to abort on. The second set are inputs that you'd like to cause
|
||||
// the command to abort. If an event satisfies both flags, it is treated as an abort.
|
||||
in = get_user_input(app, EventOnAnyKey, EventOnEsc | EventOnButton);
|
||||
|
||||
// NOTE(allen|a3.4.4): The responsible thing to do on abort is to end the command
|
||||
// without waiting on get_user_input again.
|
||||
if (in.abort){
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
good_character = 0;
|
||||
if (key_is_unmodified(&in.key)){
|
||||
if (force_number){
|
||||
if (in.key.character >= '0' && in.key.character <= '9'){
|
||||
good_character = 1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (in.key.character != 0){
|
||||
good_character = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen|a3.4.4): All we have to do to update the query bar is edit our
|
||||
// local Query_Bar struct! This is handy because it means our Query_Bar
|
||||
// is always correct for typical use without extra work updating the bar.
|
||||
if (in.type == UserInputKey){
|
||||
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
|
||||
break;
|
||||
}
|
||||
else if (in.key.keycode == key_back){
|
||||
if (bar->string.size > 0){
|
||||
--bar->string.size;
|
||||
}
|
||||
}
|
||||
else if (good_character){
|
||||
append_s_char(&bar->string, in.key.character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
terminate_with_null(&bar->string);
|
||||
|
||||
return(success);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
query_user_string(Application_Links *app, Query_Bar *bar){
|
||||
int32_t success = query_user_general(app, bar, 0);
|
||||
return(success);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
query_user_number(Application_Links *app, Query_Bar *bar){
|
||||
int32_t success = query_user_general(app, bar, 1);
|
||||
return(success);
|
||||
}
|
||||
|
||||
inline Buffer_Summary
|
||||
get_active_buffer(Application_Links *app, uint32_t access){
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
inline char
|
||||
buffer_get_char(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char result = ' ';
|
||||
*buffer = get_buffer(app, buffer->buffer_id, AccessAll);
|
||||
if (pos >= 0 && pos < buffer->size){
|
||||
buffer_read_range(app, buffer, pos, pos+1, &result);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Buffer_Identifier
|
||||
buffer_identifier(char *str, int32_t len){
|
||||
Buffer_Identifier identifier;
|
||||
identifier.name = str;
|
||||
identifier.name_len = len;
|
||||
identifier.id = 0;
|
||||
return(identifier);
|
||||
}
|
||||
|
||||
inline Buffer_Identifier
|
||||
buffer_identifier(int32_t id){
|
||||
Buffer_Identifier identifier;
|
||||
identifier.name = 0;
|
||||
identifier.name_len = 0;
|
||||
identifier.id = id;
|
||||
return(identifier);
|
||||
}
|
||||
|
||||
static Buffer_Summary
|
||||
create_buffer(Application_Links *app, char *filename, int32_t filename_len, Buffer_Create_Flag flags){
|
||||
|
||||
Buffer_Summary buffer = {0};
|
||||
|
||||
Buffer_Creation_Data data = {0};
|
||||
begin_buffer_creation(app, &data, flags);
|
||||
buffer_creation_name(app, &data, filename, filename_len, 0);
|
||||
buffer = end_buffer_creation(app, &data);
|
||||
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Helpers for setting bindings.
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_BIND_HELPER_H)
|
||||
#define FCODER_BIND_HELPER_H
|
||||
|
||||
//
|
||||
// Binding Helper
|
||||
//
|
||||
|
||||
struct Bind_Helper{
|
||||
Binding_Unit *cursor, *start, *end;
|
||||
Binding_Unit *header, *group;
|
||||
int32_t write_total;
|
||||
int32_t 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 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 Bind_Helper
|
||||
begin_bind_helper(void *data, int32_t 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.user_map_count = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void
|
||||
begin_map_(Bind_Helper *helper, int32_t mapid, int32_t replace){
|
||||
if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END;
|
||||
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
|
||||
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_map_begin;
|
||||
unit.map_begin.mapid = mapid;
|
||||
unit.map_begin.replace = replace;
|
||||
helper->group = write_unit(helper, unit);
|
||||
helper->group->map_begin.bind_count = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
begin_map(Bind_Helper *helper, int32_t mapid){
|
||||
begin_map_(helper, mapid, 0);
|
||||
}
|
||||
|
||||
inline void
|
||||
restart_map(Bind_Helper *helper, int32_t mapid){
|
||||
begin_map_(helper, mapid, 1);
|
||||
}
|
||||
|
||||
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, int32_t 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(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, int32_t cmdid){
|
||||
bind(helper, 0, 0, cmdid);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){
|
||||
bind(helper, 0, 0, func);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, int32_t cmdid){
|
||||
bind(helper, 0, modifiers, cmdid);
|
||||
}
|
||||
|
||||
inline void
|
||||
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, Custom_Command_Function *func){
|
||||
bind(helper, 0, modifiers, func);
|
||||
}
|
||||
|
||||
inline void
|
||||
inherit_map(Bind_Helper *helper, int32_t mapid){
|
||||
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
|
||||
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
|
||||
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_inherit;
|
||||
unit.map_inherit.mapid = mapid;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_hook(Bind_Helper *helper, int32_t hook_id, Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = hook_id;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_scroll_rule(Bind_Helper *helper, Scroll_Rule_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = special_hook_scroll_rule;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_new_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = special_hook_new_file;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_open_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = special_hook_open_file;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_save_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = special_hook_save_file;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_command_caller(Bind_Helper *helper, Command_Caller_Hook_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = special_hook_command_caller;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_input_filter(Bind_Helper *helper, Input_Filter_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = special_hook_input_filter;
|
||||
unit.hook.func = (void*) func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
end_bind_helper(Bind_Helper *helper){
|
||||
int32_t result;
|
||||
if (helper->header){
|
||||
helper->header->header.total_size = (int32_t)(helper->cursor - helper->start);
|
||||
helper->header->header.error = helper->error;
|
||||
}
|
||||
result = helper->write_total;
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* Miscellaneous helpers for common operations.
|
||||
*/
|
||||
|
||||
#if !defined(FCODER_HELPER_H)
|
||||
#define FCODER_HELPER_H
|
||||
|
||||
#include "4coder_seek_types.h"
|
||||
|
||||
inline void
|
||||
exec_command(Application_Links *app, Custom_Command_Function *func){
|
||||
func(app);
|
||||
}
|
||||
|
||||
inline void
|
||||
exec_command(Application_Links *app, Generic_Command cmd){
|
||||
if (cmd.cmdid < cmdid_count){
|
||||
exec_command(app, cmd.cmdid);
|
||||
}
|
||||
else{
|
||||
exec_command(app, cmd.command);
|
||||
}
|
||||
}
|
||||
|
||||
inline View_Summary
|
||||
get_first_view_with_buffer(Application_Links *app, int32_t buffer_id){
|
||||
View_Summary result = {};
|
||||
View_Summary test = {};
|
||||
|
||||
if (buffer_id != 0){
|
||||
uint32_t access = AccessAll;
|
||||
for(test = get_view_first(app, access);
|
||||
test.exists;
|
||||
get_view_next(app, &test, access)){
|
||||
|
||||
Buffer_Summary buffer = get_buffer(app, test.buffer_id, access);
|
||||
|
||||
if(buffer.buffer_id == buffer_id){
|
||||
result = test;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
key_is_unmodified(Key_Event_Data *key){
|
||||
char *mods = key->modifiers;
|
||||
int32_t unmodified = !mods[MDFR_CONTROL_INDEX] && !mods[MDFR_ALT_INDEX];
|
||||
return(unmodified);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
query_user_general(Application_Links *app, Query_Bar *bar, bool32 force_number){
|
||||
User_Input in;
|
||||
int32_t success = 1;
|
||||
int32_t good_character = 0;
|
||||
|
||||
// NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to.
|
||||
// start a query bar, but it will be unusual behavior from the point of view of the
|
||||
// user, if this command starts intercepting input even though no prompt is shown.
|
||||
// This will only happen if you have a lot of bars open already or if the current view
|
||||
// doesn't support query bars.
|
||||
if (start_query_bar(app, bar, 0) == 0) return 0;
|
||||
|
||||
for (;;){
|
||||
// NOTE(allen|a3.4.4): This call will block until the user does one of the input
|
||||
// types specified in the flags. The first set of flags are inputs you'd like to intercept
|
||||
// that you don't want to abort on. The second set are inputs that you'd like to cause
|
||||
// the command to abort. If an event satisfies both flags, it is treated as an abort.
|
||||
in = get_user_input(app, EventOnAnyKey, EventOnEsc | EventOnButton);
|
||||
|
||||
// NOTE(allen|a3.4.4): The responsible thing to do on abort is to end the command
|
||||
// without waiting on get_user_input again.
|
||||
if (in.abort){
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
good_character = 0;
|
||||
if (key_is_unmodified(&in.key)){
|
||||
if (force_number){
|
||||
if (in.key.character >= '0' && in.key.character <= '9'){
|
||||
good_character = 1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (in.key.character != 0){
|
||||
good_character = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen|a3.4.4): All we have to do to update the query bar is edit our
|
||||
// local Query_Bar struct! This is handy because it means our Query_Bar
|
||||
// is always correct for typical use without extra work updating the bar.
|
||||
if (in.type == UserInputKey){
|
||||
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
|
||||
break;
|
||||
}
|
||||
else if (in.key.keycode == key_back){
|
||||
if (bar->string.size > 0){
|
||||
--bar->string.size;
|
||||
}
|
||||
}
|
||||
else if (good_character){
|
||||
append_s_char(&bar->string, in.key.character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
terminate_with_null(&bar->string);
|
||||
|
||||
return(success);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
query_user_string(Application_Links *app, Query_Bar *bar){
|
||||
int32_t success = query_user_general(app, bar, false);
|
||||
return(success);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
query_user_number(Application_Links *app, Query_Bar *bar){
|
||||
int32_t success = query_user_general(app, bar, true);
|
||||
return(success);
|
||||
}
|
||||
|
||||
inline char
|
||||
buffer_get_char(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char result = ' ';
|
||||
*buffer = get_buffer(app, buffer->buffer_id, AccessAll);
|
||||
if (pos >= 0 && pos < buffer->size){
|
||||
buffer_read_range(app, buffer, pos, pos+1, &result);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Buffer_Identifier
|
||||
buffer_identifier(char *str, int32_t len){
|
||||
Buffer_Identifier identifier;
|
||||
identifier.name = str;
|
||||
identifier.name_len = len;
|
||||
identifier.id = 0;
|
||||
return(identifier);
|
||||
}
|
||||
|
||||
inline Buffer_Identifier
|
||||
buffer_identifier(int32_t id){
|
||||
Buffer_Identifier identifier;
|
||||
identifier.name = 0;
|
||||
identifier.name_len = 0;
|
||||
identifier.id = id;
|
||||
return(identifier);
|
||||
}
|
||||
|
||||
static Buffer_Summary
|
||||
create_buffer(Application_Links *app, char *filename, int32_t filename_len, Buffer_Create_Flag flags){
|
||||
Buffer_Summary buffer = {0};
|
||||
|
||||
Buffer_Creation_Data data = {0};
|
||||
begin_buffer_creation(app, &data, flags);
|
||||
buffer_creation_name(app, &data, filename, filename_len, 0);
|
||||
buffer = end_buffer_creation(app, &data);
|
||||
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
inline Range
|
||||
make_range(int32_t p1, int32_t p2){
|
||||
Range range;
|
||||
if (p1 < p2){
|
||||
range.min = p1;
|
||||
range.max = p2;
|
||||
}
|
||||
else{
|
||||
range.min = p2;
|
||||
range.max = p1;
|
||||
}
|
||||
return(range);
|
||||
}
|
||||
|
||||
struct Buffer_Rect{
|
||||
int32_t char0, line0;
|
||||
int32_t char1, line1;
|
||||
};
|
||||
|
||||
#ifndef Swap
|
||||
#define Swap(T,a,b) do{ T t = a; a = b; b = t; } while(0)
|
||||
#endif
|
||||
|
||||
inline Buffer_Rect
|
||||
get_rect(View_Summary *view){
|
||||
Buffer_Rect rect = {0};
|
||||
|
||||
rect.char0 = view->mark.character;
|
||||
rect.line0 = view->mark.line;
|
||||
|
||||
rect.char1 = view->cursor.character;
|
||||
rect.line1 = view->cursor.line;
|
||||
|
||||
if (rect.line0 > rect.line1){
|
||||
Swap(int32_t, rect.line0, rect.line1);
|
||||
}
|
||||
if (rect.char0 > rect.char1){
|
||||
Swap(int32_t, rect.char0, rect.char1);
|
||||
}
|
||||
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
get_line_x_rect(View_Summary *view){
|
||||
i32_Rect rect = {0};
|
||||
|
||||
if (view->unwrapped_lines){
|
||||
rect.x0 = (int32_t)view->mark.unwrapped_x;
|
||||
rect.x1 = (int32_t)view->cursor.unwrapped_x;
|
||||
}
|
||||
else{
|
||||
rect.x0 = (int32_t)view->mark.wrapped_x;
|
||||
rect.x1 = (int32_t)view->cursor.wrapped_x;
|
||||
}
|
||||
rect.y0 = view->mark.line;
|
||||
rect.y1 = view->cursor.line;
|
||||
|
||||
if (rect.y0 > rect.y1){
|
||||
Swap(int32_t, rect.y0, rect.y1);
|
||||
}
|
||||
if (rect.x0 > rect.x1){
|
||||
Swap(int32_t, rect.x0, rect.x1);
|
||||
}
|
||||
|
||||
return(rect);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
open_file(Application_Links *app, Buffer_Summary *buffer_out, char *filename, int32_t filename_len, int32_t background, int32_t never_new){
|
||||
int32_t result = false;
|
||||
Buffer_Summary buffer = get_buffer_by_name(app, filename, filename_len, AccessProtected|AccessHidden);
|
||||
|
||||
if (buffer.exists){
|
||||
if (buffer_out) *buffer_out = buffer;
|
||||
result = true;
|
||||
}
|
||||
else{
|
||||
Buffer_Create_Flag flags = 0;
|
||||
if (background){
|
||||
flags |= BufferCreate_Background;
|
||||
}
|
||||
if (never_new){
|
||||
flags |= BufferCreate_NeverNew;
|
||||
}
|
||||
buffer = create_buffer(app, filename, filename_len, flags);
|
||||
if (buffer.exists){
|
||||
if (buffer_out) *buffer_out = buffer;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
view_open_file(Application_Links *app, View_Summary *view, char *filename, int32_t filename_len, int32_t never_new){
|
||||
int32_t result = 0;
|
||||
|
||||
if (view){
|
||||
Buffer_Summary buffer = {0};
|
||||
if (open_file(app, &buffer, filename, filename_len, false, never_new)){
|
||||
view_set_buffer(app, view, buffer.buffer_id, 0);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
get_view_next_looped(Application_Links *app, View_Summary *view, uint32_t access){
|
||||
get_view_next(app, view, access);
|
||||
if (!view->exists){
|
||||
*view = get_view_first(app, access);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_buffer(Application_Links *app, Buffer_Summary *buffer){
|
||||
*buffer = get_buffer(app, buffer->buffer_id, AccessAll);
|
||||
}
|
||||
|
||||
static void
|
||||
refresh_view(Application_Links *app, View_Summary *view){
|
||||
*view = get_view(app, view->view_id, AccessAll);
|
||||
}
|
||||
|
||||
inline float
|
||||
get_view_y(View_Summary *view){
|
||||
float y = view->cursor.wrapped_y;
|
||||
if (view->unwrapped_lines){
|
||||
y = view->cursor.unwrapped_y;
|
||||
}
|
||||
return(y);
|
||||
}
|
||||
|
||||
inline float
|
||||
get_view_x(View_Summary *view){
|
||||
float x = view->cursor.wrapped_x;
|
||||
if (view->unwrapped_lines){
|
||||
x = view->cursor.unwrapped_x;
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
|
||||
inline Range
|
||||
get_range(View_Summary *view){
|
||||
Range range = make_range(view->cursor.pos, view->mark.pos);
|
||||
return(range);
|
||||
}
|
||||
|
||||
#if !defined(ArrayCount)
|
||||
# define ArrayCount(a) (sizeof(a)/sizeof(a[0]))
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,993 @@
|
|||
/*
|
||||
* Helpers for doing long range seeks.
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_LONG_SEEK_H)
|
||||
#define FCODER_LONG_SEEK_H
|
||||
|
||||
#include "4coder_helper/4coder_streaming.h"
|
||||
#include "4coder_lib/4coder_mem.h"
|
||||
#include "4cpp/4cpp_lexer.h"
|
||||
|
||||
//
|
||||
// Whitespace Based Seeks
|
||||
//
|
||||
|
||||
static int32_t
|
||||
seek_line_end(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char chunk[1024];
|
||||
int32_t chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
int32_t still_looping;
|
||||
char at_pos;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
still_looping = 1;
|
||||
do{
|
||||
for (; pos < stream.end; ++pos){
|
||||
at_pos = stream.data[pos];
|
||||
if (at_pos == '\n'){
|
||||
goto double_break;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break:;
|
||||
|
||||
if (pos > buffer->size){
|
||||
pos = buffer->size;
|
||||
}
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
seek_line_beginning(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char chunk[1024];
|
||||
int32_t chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
int32_t still_looping;
|
||||
char at_pos;
|
||||
|
||||
--pos;
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
still_looping = 1;
|
||||
do{
|
||||
for (; pos >= stream.start; --pos){
|
||||
at_pos = stream.data[pos];
|
||||
if (at_pos == '\n'){
|
||||
goto double_break;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break:;
|
||||
|
||||
if (pos != 0){
|
||||
++pos;
|
||||
}
|
||||
if (pos < 0){
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static void
|
||||
move_past_lead_whitespace(Application_Links *app, View_Summary *view, Buffer_Summary *buffer){
|
||||
refresh_view(app, view);
|
||||
|
||||
int32_t new_pos = seek_line_beginning(app, buffer, view->cursor.pos);
|
||||
char space[1024];
|
||||
Stream_Chunk chunk = {0};
|
||||
int32_t still_looping = false;
|
||||
|
||||
int32_t i = new_pos;
|
||||
if (init_stream_chunk(&chunk, app, buffer, i, space, sizeof(space))){
|
||||
do{
|
||||
for (; i < chunk.end; ++i){
|
||||
char at_pos = chunk.data[i];
|
||||
if (at_pos == '\n' || !char_is_whitespace(at_pos)){
|
||||
goto break2;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&chunk);
|
||||
}while(still_looping);
|
||||
break2:;
|
||||
|
||||
if (i > view->cursor.pos){
|
||||
view_set_cursor(app, view, seek_pos(i), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char chunk[1024];
|
||||
int32_t chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
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.
|
||||
int32_t still_looping = 1;
|
||||
while (still_looping){
|
||||
for (; pos >= stream.start; --pos){
|
||||
at_pos = stream.data[pos];
|
||||
if (!char_is_whitespace(at_pos)){
|
||||
goto double_break_1;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}
|
||||
double_break_1:;
|
||||
|
||||
// Step 2: Continue scanning backward, at each '\n'
|
||||
// mark the beginning of another line by setting
|
||||
// no_hard to true, set it back to false if a
|
||||
// non-whitespace character is discovered before
|
||||
// the next '\n'
|
||||
int32_t no_hard = false;
|
||||
while (still_looping){
|
||||
for (; pos >= stream.start; --pos){
|
||||
at_pos = stream.data[pos];
|
||||
if (at_pos == '\n'){
|
||||
if (no_hard){
|
||||
goto double_break_2;
|
||||
}
|
||||
else{
|
||||
no_hard = true;
|
||||
}
|
||||
}
|
||||
else if (!char_is_whitespace(at_pos)){
|
||||
no_hard = false;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}
|
||||
double_break_2:;
|
||||
|
||||
if (pos != 0){
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_whitespace_down(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char chunk[1024];
|
||||
int32_t chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
int32_t no_hard;
|
||||
int32_t prev_endline;
|
||||
int32_t still_looping;
|
||||
char at_pos;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
// step 1: find the first non-whitespace character
|
||||
// ahead of the current position.
|
||||
still_looping = true;
|
||||
do{
|
||||
for (; pos < stream.end; ++pos){
|
||||
at_pos = stream.data[pos];
|
||||
if (!char_is_whitespace(at_pos)){
|
||||
goto double_break_1;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
} while(still_looping);
|
||||
double_break_1:;
|
||||
|
||||
// step 2: continue scanning forward, at each '\n'
|
||||
// mark it as the beginning of a new line by updating
|
||||
// the prev_endline value. if another '\n' is found
|
||||
// with non-whitespace then the previous line was
|
||||
// all whitespace.
|
||||
no_hard = false;
|
||||
prev_endline = -1;
|
||||
while(still_looping){
|
||||
for (; pos < stream.end; ++pos){
|
||||
at_pos = stream.data[pos];
|
||||
if (at_pos == '\n'){
|
||||
if (no_hard){
|
||||
goto double_break_2;
|
||||
}
|
||||
else{
|
||||
no_hard = true;
|
||||
prev_endline = pos;
|
||||
}
|
||||
}
|
||||
else if (!char_is_whitespace(at_pos)){
|
||||
no_hard = false;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}
|
||||
double_break_2:;
|
||||
|
||||
if (prev_endline == -1 || prev_endline+1 >= buffer->size){
|
||||
pos = buffer->size;
|
||||
}
|
||||
else{
|
||||
pos = prev_endline+1;
|
||||
}
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
static int32_t
|
||||
buffer_seek_whitespace_right(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char data_chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer,
|
||||
pos, data_chunk, sizeof(data_chunk))){
|
||||
|
||||
bool32 still_looping = 1;
|
||||
do{
|
||||
for (; pos < stream.end; ++pos){
|
||||
if (!char_is_whitespace(stream.data[pos])){
|
||||
goto double_break1;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break1:;
|
||||
|
||||
still_looping = 1;
|
||||
do{
|
||||
for (; pos < stream.end; ++pos){
|
||||
if (char_is_whitespace(stream.data[pos])){
|
||||
goto double_break2;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break2:;
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_whitespace_left(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char data_chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
--pos;
|
||||
if (pos > 0){
|
||||
if (init_stream_chunk(&stream, app, buffer,
|
||||
pos, data_chunk, sizeof(data_chunk))){
|
||||
|
||||
bool32 still_looping = 1;
|
||||
do{
|
||||
for (; pos >= stream.start; --pos){
|
||||
if (!char_is_whitespace(stream.data[pos])){
|
||||
goto double_break1;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break1:;
|
||||
|
||||
still_looping = 1;
|
||||
do{
|
||||
for (; pos >= stream.start; --pos){
|
||||
if (char_is_whitespace(stream.data[pos])){
|
||||
++pos;
|
||||
goto double_break2;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break2:;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
//
|
||||
// Boundary Type Seeks
|
||||
//
|
||||
|
||||
static int32_t
|
||||
buffer_seek_alphanumeric_right(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char data_chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer,
|
||||
pos, data_chunk, sizeof(data_chunk))){
|
||||
|
||||
bool32 still_looping = 1;
|
||||
do{
|
||||
for (; pos < stream.end; ++pos){
|
||||
if (char_is_alpha_numeric_true(stream.data[pos])){
|
||||
goto double_break1;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break1:;
|
||||
|
||||
still_looping = 1;
|
||||
do{
|
||||
for (; pos < stream.end; ++pos){
|
||||
if (!char_is_alpha_numeric_true(stream.data[pos])){
|
||||
goto double_break2;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break2:;
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_alphanumeric_left(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char data_chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
--pos;
|
||||
if (pos > 0){
|
||||
if (init_stream_chunk(&stream, app, buffer,
|
||||
pos, data_chunk, sizeof(data_chunk))){
|
||||
|
||||
bool32 still_looping = 1;
|
||||
do{
|
||||
for (; pos >= stream.start; --pos){
|
||||
if (char_is_alpha_numeric_true(stream.data[pos])){
|
||||
goto double_break1;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break1:;
|
||||
|
||||
still_looping = 1;
|
||||
do{
|
||||
for (; pos >= stream.start; --pos){
|
||||
if (!char_is_alpha_numeric_true(stream.data[pos])){
|
||||
++pos;
|
||||
goto double_break2;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break2:;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_range_camel_right(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t an_pos){
|
||||
char data_chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
++pos;
|
||||
if (pos < an_pos){
|
||||
stream.max_end = an_pos;
|
||||
if (init_stream_chunk(&stream, app, buffer,
|
||||
pos, data_chunk, sizeof(data_chunk))){
|
||||
|
||||
char c = 0, pc = stream.data[pos];
|
||||
++pos;
|
||||
|
||||
bool32 still_looping = 1;
|
||||
do{
|
||||
for (; pos < stream.end; ++pos){
|
||||
c = stream.data[pos];
|
||||
if (char_is_upper(c) && char_is_lower(pc)){
|
||||
goto double_break1;
|
||||
}
|
||||
pc = c;
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break1:;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pos = an_pos;
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_range_camel_left(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t an_pos){
|
||||
char data_chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
--pos;
|
||||
if (pos > 0){
|
||||
stream.min_start = an_pos+1;
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, data_chunk, sizeof(data_chunk))){
|
||||
|
||||
char c = 0, pc = stream.data[pos];
|
||||
|
||||
bool32 still_looping = 1;
|
||||
do{
|
||||
for (; pos >= stream.start; --pos){
|
||||
c = stream.data[pos];
|
||||
if (char_is_upper(c) && char_is_lower(pc)){
|
||||
goto double_break1;
|
||||
}
|
||||
pc = c;
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
double_break1:;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
return(pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_alphanumeric_or_camel_right(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
int32_t an_pos = buffer_seek_alphanumeric_right(app, buffer, pos);
|
||||
int32_t result = buffer_seek_range_camel_right(app, buffer, pos, an_pos);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_seek_alphanumeric_or_camel_left(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
int32_t an_pos = buffer_seek_alphanumeric_left(app, buffer, pos);
|
||||
int32_t result = buffer_seek_range_camel_left(app, buffer, pos, an_pos);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
seek_token_left(Cpp_Token_Array *tokens, int32_t pos){
|
||||
Cpp_Get_Token_Result get = cpp_get_token(*tokens, pos);
|
||||
if (get.token_index == -1){
|
||||
get.token_index = 0;
|
||||
}
|
||||
|
||||
Cpp_Token *token = tokens->tokens + get.token_index;
|
||||
if (token->start == pos && get.token_index > 0){
|
||||
--token;
|
||||
}
|
||||
|
||||
return(token->start);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
seek_token_right(Cpp_Token_Array *tokens, int32_t pos){
|
||||
Cpp_Get_Token_Result get = cpp_get_token(*tokens, pos);
|
||||
if (get.in_whitespace){
|
||||
++get.token_index;
|
||||
}
|
||||
if (get.token_index >= tokens->count){
|
||||
get.token_index = tokens->count-1;
|
||||
}
|
||||
|
||||
Cpp_Token *token = tokens->tokens + get.token_index;
|
||||
return(token->start + token->size);
|
||||
}
|
||||
|
||||
static Cpp_Token_Array
|
||||
buffer_get_all_tokens(Application_Links *app, Partition *part, Buffer_Summary *buffer){
|
||||
Cpp_Token_Array array = {0};
|
||||
|
||||
if (buffer->exists && buffer->is_lexed){
|
||||
array.count = buffer_token_count(app, buffer);
|
||||
array.max_count = array.count;
|
||||
array.tokens = push_array(part, Cpp_Token, array.count);
|
||||
buffer_read_tokens(app, buffer, 0, array.count, array.tokens);
|
||||
}
|
||||
|
||||
return(array);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_boundary_seek(Application_Links *app, Buffer_Summary *buffer, Partition *part, int32_t start_pos, bool32 seek_forward, Seek_Boundary_Flag flags)/*
|
||||
DOC_PARAM(buffer, The buffer parameter specifies the buffer through which to seek.)
|
||||
DOC_PARAM(start_pos, The beginning position of the seek is specified by start_pos measured in absolute position.)
|
||||
DOC_PARAM(seek_forward, If this parameter is non-zero it indicates that the seek should move foward through the buffer.)
|
||||
DOC_PARAM(flags, This field specifies the types of boundaries at which the seek should stop.)
|
||||
|
||||
DOC_RETURN(This call returns the absolute position where the seek stopped.
|
||||
If the seek goes below 0 the returned value is -1.
|
||||
If the seek goes past the end the returned value is the size of the buffer.)
|
||||
|
||||
DOC_SEE(Seek_Boundary_Flag)
|
||||
DOC_SEE(4coder_Buffer_Positioning_System)
|
||||
*/{
|
||||
int32_t result = 0;
|
||||
|
||||
// TODO(allen): reduce duplication?
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
if (buffer->exists){
|
||||
int32_t pos[4];
|
||||
int32_t size = buffer->size;
|
||||
int32_t new_pos = 0;
|
||||
|
||||
if (start_pos < 0){
|
||||
start_pos = 0;
|
||||
}
|
||||
else if (start_pos > size){
|
||||
start_pos = size;
|
||||
}
|
||||
|
||||
if (seek_forward){
|
||||
for (int32_t i = 0; i < ArrayCount(pos); ++i){
|
||||
pos[i] = size;
|
||||
}
|
||||
|
||||
if (flags & BoundaryWhitespace){
|
||||
pos[0] = buffer_seek_whitespace_right(app, buffer, start_pos);
|
||||
}
|
||||
|
||||
if (flags & BoundaryToken){
|
||||
if (buffer->tokens_are_ready){
|
||||
Cpp_Token_Array array = buffer_get_all_tokens(app, part, buffer);
|
||||
pos[1] = seek_token_right(&array, start_pos);
|
||||
}
|
||||
else{
|
||||
pos[1] = buffer_seek_whitespace_right(app, buffer, start_pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & BoundaryAlphanumeric){
|
||||
pos[2] = buffer_seek_alphanumeric_right(app, buffer, start_pos);
|
||||
if (flags & BoundaryCamelCase){
|
||||
pos[3] = buffer_seek_range_camel_right(app, buffer, start_pos, pos[2]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (flags & BoundaryCamelCase){
|
||||
pos[3] = buffer_seek_alphanumeric_or_camel_right(app, buffer, start_pos);
|
||||
}
|
||||
}
|
||||
|
||||
new_pos = size;
|
||||
for (int32_t i = 0; i < ArrayCount(pos); ++i){
|
||||
if (pos[i] < new_pos){
|
||||
new_pos = pos[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
for (int32_t i = 0; i < ArrayCount(pos); ++i){
|
||||
pos[i] = 0;
|
||||
}
|
||||
|
||||
if (flags & BoundaryWhitespace){
|
||||
pos[0] = buffer_seek_whitespace_left(app, buffer, start_pos);
|
||||
}
|
||||
|
||||
if (flags & BoundaryToken){
|
||||
if (buffer->tokens_are_ready){
|
||||
Cpp_Token_Array array = buffer_get_all_tokens(app, part, buffer);
|
||||
pos[1] = seek_token_left(&array, start_pos);
|
||||
}
|
||||
else{
|
||||
pos[1] = buffer_seek_whitespace_left(app, buffer, start_pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & BoundaryAlphanumeric){
|
||||
pos[2] = buffer_seek_alphanumeric_left(app, buffer, start_pos);
|
||||
if (flags & BoundaryCamelCase){
|
||||
pos[3] = buffer_seek_range_camel_left(app, buffer, start_pos, pos[2]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (flags & BoundaryCamelCase){
|
||||
pos[3] = buffer_seek_alphanumeric_or_camel_left(app, buffer, start_pos);
|
||||
}
|
||||
}
|
||||
|
||||
new_pos = 0;
|
||||
for (int32_t i = 0; i < ArrayCount(pos); ++i){
|
||||
if (pos[i] > new_pos){
|
||||
new_pos = pos[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
result = new_pos;
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Character Seeks
|
||||
//
|
||||
|
||||
void
|
||||
buffer_seek_delimiter_forward(Application_Links *app, Buffer_Summary *buffer, int32_t pos, char delim, int32_t *result){
|
||||
if (buffer->exists){
|
||||
char chunk[1024];
|
||||
int32_t size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
|
||||
int32_t still_looping = 1;
|
||||
do{
|
||||
for(; pos < stream.end; ++pos){
|
||||
char at_pos = stream.data[pos];
|
||||
if (at_pos == delim){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
*result = buffer->size;
|
||||
|
||||
finished:;
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_seek_delimiter_backward(Application_Links *app, Buffer_Summary *buffer, int32_t pos, char delim, int32_t *result){
|
||||
if (buffer->exists){
|
||||
char chunk[1024];
|
||||
int32_t size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
|
||||
int32_t still_looping = 1;
|
||||
do{
|
||||
for(; pos >= stream.start; --pos){
|
||||
char at_pos = stream.data[pos];
|
||||
if (at_pos == delim){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
*result = 0;
|
||||
|
||||
finished:;
|
||||
}
|
||||
|
||||
//
|
||||
// Buffer Substring Seeks
|
||||
//
|
||||
|
||||
// TODO(allen): This duplication is driving me crazy... I've gotta
|
||||
// upgrade the meta programming system another level.
|
||||
|
||||
// NOTE(allen): This is limitted to a string size of 512.
|
||||
// You can push it up or do something more clever by just
|
||||
// replacing char read_buffer[512]; with more memory.
|
||||
static void
|
||||
buffer_seek_string_forward(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t end, char *str, int32_t size, int32_t *result){
|
||||
char read_buffer[512];
|
||||
|
||||
if (buffer->size > end){
|
||||
*result = buffer->size;
|
||||
}
|
||||
else{
|
||||
*result = end;
|
||||
}
|
||||
|
||||
if (size > 0 && size <= sizeof(read_buffer)){
|
||||
if (buffer->exists){
|
||||
String read_str = make_fixed_width_string(read_buffer);
|
||||
String needle_str = make_string(str, size);
|
||||
char first_char = str[0];
|
||||
|
||||
read_str.size = size;
|
||||
|
||||
char chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
stream.max_end = end;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, sizeof(chunk))){
|
||||
int32_t still_looping = 1;
|
||||
do{
|
||||
for(; pos < stream.end; ++pos){
|
||||
char at_pos = stream.data[pos];
|
||||
if (at_pos == first_char){
|
||||
buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match_ss(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
if (end == 0){
|
||||
*result = buffer->size;
|
||||
}
|
||||
else{
|
||||
*result = end;
|
||||
}
|
||||
|
||||
finished:;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): This is limitted to a string size of 512.
|
||||
// You can push it up or do something more clever by just
|
||||
// replacing char read_buffer[512]; with more memory.
|
||||
static void
|
||||
buffer_seek_string_backward(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t min, char *str, int32_t size, int32_t *result){
|
||||
char read_buffer[512];
|
||||
|
||||
*result = min-1;
|
||||
if (size > 0 && size <= sizeof(read_buffer)){
|
||||
if (buffer->exists){
|
||||
String read_str = make_fixed_width_string(read_buffer);
|
||||
String needle_str = make_string(str, size);
|
||||
char first_char = str[0];
|
||||
|
||||
read_str.size = size;
|
||||
|
||||
char chunk[1024];
|
||||
Stream_Chunk stream = {0};
|
||||
stream.min_start = min;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, sizeof(chunk))){
|
||||
int32_t still_looping = 1;
|
||||
do{
|
||||
for(; pos >= stream.start; --pos){
|
||||
char at_pos = stream.data[pos];
|
||||
if (at_pos == first_char){
|
||||
buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match_ss(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
finished:;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): This is limitted to a string size of 512.
|
||||
// You can push it up or do something more clever by just
|
||||
// replacing char read_buffer[512]; with more memory.
|
||||
static void
|
||||
buffer_seek_string_insensitive_forward(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t end, char *str, int32_t size, int32_t *result){
|
||||
char read_buffer[512];
|
||||
char chunk[1024];
|
||||
int32_t chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
stream.max_end = end;
|
||||
|
||||
if (buffer->size > end){
|
||||
*result = buffer->size;
|
||||
}
|
||||
else{
|
||||
*result = end;
|
||||
}
|
||||
|
||||
if (size > 0 && size <= sizeof(read_buffer)){
|
||||
if (buffer->exists){
|
||||
String read_str = make_fixed_width_string(read_buffer);
|
||||
String needle_str = make_string(str, size);
|
||||
char first_char = char_to_upper(str[0]);
|
||||
|
||||
read_str.size = size;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
int32_t still_looping = 1;
|
||||
do{
|
||||
for(; pos < stream.end; ++pos){
|
||||
char at_pos = char_to_upper(stream.data[pos]);
|
||||
if (at_pos == first_char){
|
||||
buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match_insensitive_ss(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
finished:;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): This is limitted to a string size of 512.
|
||||
// You can push it up or do something more clever by just
|
||||
// replacing char read_buffer[512]; with more memory.
|
||||
static void
|
||||
buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t min, char *str, int32_t size, int32_t *result){
|
||||
char read_buffer[512];
|
||||
char chunk[1024];
|
||||
int32_t chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
stream.min_start = min;
|
||||
|
||||
*result = min-1;
|
||||
if (size > 0 && size <= sizeof(read_buffer)){
|
||||
if (buffer->exists){
|
||||
String read_str = make_fixed_width_string(read_buffer);
|
||||
String needle_str = make_string(str, size);
|
||||
char first_char = char_to_upper(str[0]);
|
||||
|
||||
read_str.size = size;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
int32_t still_looping = 1;
|
||||
do{
|
||||
for(; pos >= stream.start; --pos){
|
||||
char at_pos = char_to_upper(stream.data[pos]);
|
||||
if (at_pos == first_char){
|
||||
buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match_insensitive_ss(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
finished:;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Buffer Line Positioning
|
||||
//
|
||||
|
||||
static int32_t
|
||||
read_line(Application_Links *app, Partition *part, Buffer_Summary *buffer, int32_t line, String *str){
|
||||
Partial_Cursor begin = {0};
|
||||
Partial_Cursor end = {0};
|
||||
|
||||
int32_t success = 0;
|
||||
|
||||
if (buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &begin)){
|
||||
if (buffer_compute_cursor(app, buffer, seek_line_char(line, 65536), &end)){
|
||||
if (begin.line == line){
|
||||
if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer->size){
|
||||
int32_t size = (end.pos - begin.pos);
|
||||
*str = make_string(push_array(part, char, size+1), size+1);
|
||||
if (str->str){
|
||||
success = 1;
|
||||
buffer_read_range(app, buffer, begin.pos, end.pos, str->str);
|
||||
str->size = size;
|
||||
terminate_with_null(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(success);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_get_line_start(Application_Links *app, Buffer_Summary *buffer, int32_t line){
|
||||
Partial_Cursor partial_cursor;
|
||||
int32_t result = buffer->size;
|
||||
if (line <= buffer->line_count){
|
||||
buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &partial_cursor);
|
||||
result = partial_cursor.pos;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_get_line_end(Application_Links *app, Buffer_Summary *buffer, int32_t line){
|
||||
Partial_Cursor partial_cursor;
|
||||
int32_t result = buffer->size;
|
||||
if (line <= buffer->line_count){
|
||||
buffer_compute_cursor(app, buffer, seek_line_char(line, 65536), &partial_cursor);
|
||||
result = partial_cursor.pos;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool32
|
||||
buffer_line_is_blank(Application_Links *app, Buffer_Summary *buffer, int32_t line){
|
||||
Partial_Cursor start, end;
|
||||
bool32 result = 0;
|
||||
if (line <= buffer->line_count){
|
||||
buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &start);
|
||||
buffer_compute_cursor(app, buffer, seek_line_char(line, 65536), &end);
|
||||
|
||||
static const int32_t chunk_size = 1024;
|
||||
char chunk[chunk_size];
|
||||
Stream_Chunk stream = {0};
|
||||
int32_t i = start.pos;
|
||||
stream.max_end = end.pos;
|
||||
|
||||
result = true;
|
||||
if (init_stream_chunk(&stream, app, buffer, i, chunk, chunk_size)){
|
||||
bool32 still_looping = false;
|
||||
do{
|
||||
for (;i < stream.end; ++i){
|
||||
char c = stream.data[i];
|
||||
if (!(c == ' ' || c == '\t' || c == '\r' || c == '\v' || c == '\n')){
|
||||
result = false;
|
||||
goto double_break;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while(still_looping);
|
||||
}
|
||||
double_break:;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_get_line_index(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
Partial_Cursor partial_cursor;
|
||||
buffer_compute_cursor(app, buffer, seek_pos(pos), &partial_cursor);
|
||||
return(partial_cursor.line);
|
||||
}
|
||||
|
||||
static Cpp_Token*
|
||||
get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line, int32_t *line_start_out = 0){
|
||||
int32_t line_start = buffer_get_line_start(app, buffer, line);
|
||||
Cpp_Get_Token_Result get_token = cpp_get_token(tokens, line_start);
|
||||
|
||||
if (get_token.in_whitespace){
|
||||
get_token.token_index += 1;
|
||||
}
|
||||
|
||||
if (line_start_out){
|
||||
*line_start_out = line_start;
|
||||
}
|
||||
|
||||
Cpp_Token *result = 0;
|
||||
if (get_token.token_index < tokens.count){
|
||||
result = tokens.tokens + get_token.token_index;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#ifndef FRED_BUFFER_TYPES_H
|
||||
#if !defined(FRED_BUFFER_TYPES_H)
|
||||
#define FRED_BUFFER_TYPES_H
|
||||
|
||||
static Buffer_Seek
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Helpers for streaming over buffer data to avoid having to read it all at once.
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_STREAMING_H)
|
||||
#define FCODER_STREAMING_H
|
||||
|
||||
#include "4coder_helper/4coder_helper.h"
|
||||
|
||||
struct Stream_Chunk{
|
||||
Application_Links *app;
|
||||
Buffer_Summary *buffer;
|
||||
|
||||
char *base_data;
|
||||
int32_t start, end;
|
||||
int32_t min_start, max_end;
|
||||
bool32 add_null;
|
||||
int32_t data_size;
|
||||
|
||||
char *data;
|
||||
};
|
||||
|
||||
static int32_t
|
||||
round_down(int32_t x, int32_t b){
|
||||
int32_t r = 0;
|
||||
if (x >= 0){
|
||||
r = x - (x % b);
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
round_up(int32_t x, int32_t b){
|
||||
int32_t r = 0;
|
||||
if (x >= 0){
|
||||
r = x - (x % b) + b;
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
static bool32
|
||||
init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_Summary *buffer,
|
||||
int32_t pos, char *data, int32_t size){
|
||||
bool32 result = 0;
|
||||
|
||||
refresh_buffer(app, buffer);
|
||||
if (pos >= 0 && pos < buffer->size && size > 0){
|
||||
chunk->app = app;
|
||||
chunk->buffer = buffer;
|
||||
chunk->base_data = data;
|
||||
chunk->data_size = size;
|
||||
chunk->start = round_down(pos, size);
|
||||
chunk->end = round_up(pos, size);
|
||||
|
||||
if (chunk->max_end > buffer->size || chunk->max_end == 0){
|
||||
chunk->max_end = buffer->size;
|
||||
}
|
||||
|
||||
if (chunk->max_end && chunk->max_end < chunk->end){
|
||||
chunk->end = chunk->max_end;
|
||||
}
|
||||
if (chunk->min_start && chunk->min_start > chunk->start){
|
||||
chunk->start = chunk->min_start;
|
||||
}
|
||||
|
||||
if (chunk->start < chunk->end){
|
||||
buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool32
|
||||
forward_stream_chunk(Stream_Chunk *chunk){
|
||||
Application_Links *app = chunk->app;
|
||||
Buffer_Summary *buffer = chunk->buffer;
|
||||
bool32 result = 0;
|
||||
|
||||
refresh_buffer(app, buffer);
|
||||
if (chunk->end < buffer->size){
|
||||
chunk->start = chunk->end;
|
||||
chunk->end += chunk->data_size;
|
||||
|
||||
if (chunk->max_end && chunk->max_end < chunk->end){
|
||||
chunk->end = chunk->max_end;
|
||||
}
|
||||
if (chunk->min_start && chunk->min_start > chunk->start){
|
||||
chunk->start = chunk->min_start;
|
||||
}
|
||||
|
||||
if (chunk->start < chunk->end){
|
||||
buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
else if (chunk->add_null && chunk->end + 1 < buffer->size){
|
||||
chunk->start = buffer->size;
|
||||
chunk->end = buffer->size + 1;
|
||||
chunk->base_data[0] = 0;
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool32
|
||||
backward_stream_chunk(Stream_Chunk *chunk){
|
||||
Application_Links *app = chunk->app;
|
||||
Buffer_Summary *buffer = chunk->buffer;
|
||||
bool32 result = 0;
|
||||
|
||||
refresh_buffer(app, buffer);
|
||||
if (chunk->start > 0){
|
||||
chunk->end = chunk->start;
|
||||
chunk->start -= chunk->data_size;
|
||||
|
||||
if (chunk->max_end && chunk->max_end < chunk->end){
|
||||
chunk->end = chunk->max_end;
|
||||
}
|
||||
if (chunk->min_start && chunk->min_start > chunk->start){
|
||||
chunk->start = chunk->min_start;
|
||||
}
|
||||
|
||||
if (chunk->start < chunk->end){
|
||||
buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
else if (chunk->add_null && chunk->start > -1){
|
||||
chunk->start = -1;
|
||||
chunk->end = 0;
|
||||
chunk->base_data[0] = 0;
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
struct Stream_Tokens{
|
||||
Application_Links *app;
|
||||
Buffer_Summary *buffer;
|
||||
|
||||
Cpp_Token *base_tokens;
|
||||
Cpp_Token *tokens;
|
||||
int32_t start, end;
|
||||
int32_t count, token_count;
|
||||
};
|
||||
|
||||
static bool32
|
||||
init_stream_tokens(Stream_Tokens *stream, Application_Links *app, Buffer_Summary *buffer, int32_t pos, Cpp_Token *data, int32_t count){
|
||||
bool32 result = 0;
|
||||
|
||||
refresh_buffer(app, buffer);
|
||||
|
||||
int32_t token_count = buffer_token_count(app, buffer);
|
||||
if (buffer->tokens_are_ready && pos >= 0 && pos < token_count && count > 0){
|
||||
stream->app = app;
|
||||
stream->buffer = buffer;
|
||||
stream->base_tokens = data;
|
||||
stream->count = count;
|
||||
stream->start = round_down(pos, count);
|
||||
stream->end = round_up(pos, count);
|
||||
stream->token_count = token_count;
|
||||
|
||||
if (stream->start < 0){
|
||||
stream->start = 0;
|
||||
}
|
||||
if (stream->end > stream->token_count){
|
||||
stream->end = stream->token_count;
|
||||
}
|
||||
|
||||
buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens);
|
||||
stream->tokens = stream->base_tokens - stream->start;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static Stream_Tokens
|
||||
begin_temp_stream_token(Stream_Tokens *stream){
|
||||
return(*stream);
|
||||
}
|
||||
|
||||
static void
|
||||
end_temp_stream_token(Stream_Tokens *stream, Stream_Tokens temp){
|
||||
if (stream->start != temp.start || stream->end != temp.end){
|
||||
Application_Links *app = stream->app;
|
||||
buffer_read_tokens(app, temp.buffer, temp.start, temp.end, temp.base_tokens);
|
||||
stream->tokens = stream->base_tokens - temp.start;
|
||||
stream->start = temp.start;
|
||||
stream->end = temp.end;
|
||||
}
|
||||
}
|
||||
|
||||
static bool32
|
||||
forward_stream_tokens(Stream_Tokens *stream){
|
||||
Application_Links *app = stream->app;
|
||||
Buffer_Summary *buffer = stream->buffer;
|
||||
bool32 result = 0;
|
||||
|
||||
refresh_buffer(app, buffer);
|
||||
if (stream->end < stream->token_count){
|
||||
stream->start = stream->end;
|
||||
stream->end += stream->count;
|
||||
|
||||
if (stream->end > stream->token_count){
|
||||
stream->end = stream->token_count;
|
||||
}
|
||||
|
||||
if (stream->start < stream->end){
|
||||
buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens);
|
||||
stream->tokens = stream->base_tokens - stream->start;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool32
|
||||
backward_stream_tokens(Stream_Tokens *stream){
|
||||
Application_Links *app = stream->app;
|
||||
Buffer_Summary *buffer = stream->buffer;
|
||||
bool32 result = 0;
|
||||
|
||||
refresh_buffer(app, buffer);
|
||||
if (stream->start > 0){
|
||||
stream->end = stream->start;
|
||||
stream->start -= stream->count;
|
||||
|
||||
if (0 > stream->start){
|
||||
stream->start = 0;
|
||||
}
|
||||
|
||||
if (stream->start < stream->end){
|
||||
buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens);
|
||||
stream->tokens = stream->base_tokens - stream->start;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
|
@ -1,7 +1,21 @@
|
|||
/*
|
||||
4coder_jump_parsing.cpp - Commands and helpers for parsing jump locations from
|
||||
compiler errors and jumping to them in the corresponding buffer.
|
||||
|
||||
#ifndef FCODER_JUMP_PARSING
|
||||
TYPE: 'drop-in-command-pack'
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_JUMP_PARSING)
|
||||
#define FCODER_JUMP_PARSING
|
||||
|
||||
#include "4coder_default_framework.h"
|
||||
#include "4coder_helper/4coder_long_seek.h"
|
||||
#include "4coder_helper/4coder_helper.h"
|
||||
|
||||
#include "4coder_lib/4coder_mem.h"
|
||||
|
||||
typedef struct Name_Based_Jump_Location{
|
||||
String file;
|
||||
int32_t line;
|
||||
|
@ -38,8 +52,7 @@ ms_style_verify(String line, int32_t paren_pos){
|
|||
}
|
||||
|
||||
static int32_t
|
||||
parse_jump_location(String line, Name_Based_Jump_Location *location,
|
||||
int32_t skip_sub_errors, int32_t *colon_char){
|
||||
parse_jump_location(String line, Name_Based_Jump_Location *location, int32_t skip_sub_errors, int32_t *colon_char){
|
||||
int32_t result = false;
|
||||
|
||||
String original_line = line;
|
||||
|
@ -150,12 +163,7 @@ parse_jump_location(String line, Name_Based_Jump_Location *location,
|
|||
}
|
||||
|
||||
static int32_t
|
||||
parse_jump_from_buffer_line(Application_Links *app,
|
||||
Partition *part,
|
||||
int32_t buffer_id,
|
||||
int32_t line,
|
||||
int32_t skip_sub_errors,
|
||||
Name_Based_Jump_Location *location){
|
||||
parse_jump_from_buffer_line(Application_Links *app, Partition *part, int32_t buffer_id, int32_t line, int32_t skip_sub_errors, Name_Based_Jump_Location *location){
|
||||
|
||||
int32_t result = false;
|
||||
String line_str = {0};
|
||||
|
@ -193,15 +201,7 @@ CUSTOM_COMMAND_SIG(goto_jump_at_cursor){
|
|||
//
|
||||
|
||||
static int32_t
|
||||
seek_next_jump_in_buffer(Application_Links *app,
|
||||
Partition *part,
|
||||
int32_t buffer_id,
|
||||
int32_t first_line,
|
||||
bool32 skip_sub_errors,
|
||||
int32_t direction,
|
||||
int32_t *line_out,
|
||||
int32_t *colon_index_out,
|
||||
Name_Based_Jump_Location *location_out){
|
||||
seek_next_jump_in_buffer(Application_Links *app, Partition *part, int32_t buffer_id, int32_t first_line, bool32 skip_sub_errors, int32_t direction, int32_t *line_out, int32_t *colon_index_out, Name_Based_Jump_Location *location_out){
|
||||
|
||||
Assert(direction == 1 || direction == -1);
|
||||
|
||||
|
@ -247,14 +247,7 @@ convert_name_based_to_id_based(Application_Links *app, Name_Based_Jump_Location
|
|||
}
|
||||
|
||||
static int32_t
|
||||
seek_next_jump_in_view(Application_Links *app,
|
||||
Partition *part,
|
||||
View_Summary *view,
|
||||
int32_t skip_sub_errors,
|
||||
int32_t direction,
|
||||
int32_t *line_out,
|
||||
int32_t *colon_index_out,
|
||||
Name_Based_Jump_Location *location_out){
|
||||
seek_next_jump_in_view(Application_Links *app, Partition *part, View_Summary *view, int32_t skip_sub_errors, int32_t direction, int32_t *line_out, int32_t *colon_index_out, Name_Based_Jump_Location *location_out){
|
||||
int32_t result = false;
|
||||
|
||||
Name_Based_Jump_Location location = {0};
|
||||
|
@ -287,13 +280,7 @@ skip_this_jump(ID_Based_Jump_Location prev, ID_Based_Jump_Location jump){
|
|||
static ID_Based_Jump_Location prev_location = {0};
|
||||
|
||||
static int32_t
|
||||
advance_cursor_in_jump_view(Application_Links *app,
|
||||
Partition *part,
|
||||
View_Summary *view,
|
||||
int32_t skip_repeats,
|
||||
int32_t skip_sub_error,
|
||||
int32_t direction,
|
||||
Name_Based_Jump_Location *location_out){
|
||||
advance_cursor_in_jump_view(Application_Links *app, Partition *part, View_Summary *view, int32_t skip_repeats, int32_t skip_sub_error, int32_t direction, Name_Based_Jump_Location *location_out){
|
||||
int32_t result = true;
|
||||
|
||||
Name_Based_Jump_Location location = {0};
|
||||
|
@ -325,47 +312,8 @@ advance_cursor_in_jump_view(Application_Links *app,
|
|||
return(result);
|
||||
}
|
||||
|
||||
static char locked_buffer_space[256];
|
||||
static String locked_buffer = make_fixed_width_string(locked_buffer_space);
|
||||
|
||||
static void
|
||||
unlock_jump_buffer(){
|
||||
locked_buffer.size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lock_jump_buffer(char *name, int32_t size){
|
||||
copy(&locked_buffer, make_string(name, size));
|
||||
}
|
||||
|
||||
static void
|
||||
lock_jump_buffer(Buffer_Summary buffer){
|
||||
copy(&locked_buffer, make_string(buffer.buffer_name, buffer.buffer_name_len));
|
||||
}
|
||||
|
||||
static View_Summary
|
||||
get_view_for_locked_jump_buffer(Application_Links *app){
|
||||
View_Summary view = {0};
|
||||
|
||||
if (locked_buffer.size > 0){
|
||||
Buffer_Summary buffer = get_buffer_by_name(app, locked_buffer.str, locked_buffer.size, AccessAll);
|
||||
if (buffer.exists){
|
||||
view = get_first_view_with_buffer(app, buffer.buffer_id);
|
||||
}
|
||||
else{
|
||||
unlock_jump_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
return(view);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
seek_error(Application_Links *app,
|
||||
Partition *part,
|
||||
int32_t skip_repeats,
|
||||
int32_t skip_sub_errors,
|
||||
int32_t direction){
|
||||
seek_error(Application_Links *app, Partition *part, int32_t skip_repeats, int32_t skip_sub_errors, int32_t direction){
|
||||
int32_t result = 0;
|
||||
|
||||
View_Summary view = get_view_for_locked_jump_buffer(app);
|
||||
|
@ -438,3 +386,5 @@ CUSTOM_COMMAND_SIG(goto_first_jump){
|
|||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -1,30 +1,62 @@
|
|||
/*
|
||||
4coder_mem.h - Preversioning
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
#ifndef FCODER_MEM_H
|
||||
This software is in the public domain. Where that dedication is not
|
||||
recognized, you are granted a perpetual, irrevocable license to copy,
|
||||
distribute, and modify this file as you see fit.
|
||||
*/
|
||||
|
||||
#if !defined(FCODER_MEM_H)
|
||||
#define FCODER_MEM_H
|
||||
|
||||
#ifndef Assert
|
||||
# define Assert(n) do{ if(!(n)){*(int*)0 = 0xA11E;} }while(0)
|
||||
// 4tech_standard_preamble.h
|
||||
#if !defined(FTECH_INTEGERS)
|
||||
#define FTECH_INTEGERS
|
||||
#include <stdint.h>
|
||||
typedef int8_t i8_4tech;
|
||||
typedef int16_t i16_4tech;
|
||||
typedef int32_t i32_4tech;
|
||||
typedef int64_t i64_4tech;
|
||||
|
||||
typedef uint8_t u8_4tech;
|
||||
typedef uint16_t u16_4tech;
|
||||
typedef uint32_t u32_4tech;
|
||||
typedef uint64_t u64_4tech;
|
||||
|
||||
typedef float f32_4tech;
|
||||
typedef double f64_4tech;
|
||||
|
||||
typedef int8_t b8_4tech;
|
||||
typedef int32_t b32_4tech;
|
||||
#endif
|
||||
|
||||
#if !defined(Assert)
|
||||
# define Assert(n) do{ if (!(n)) *(int*)0 = 0xA11E; }while(0)
|
||||
#endif
|
||||
// standard preamble end
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct Partition{
|
||||
char *base;
|
||||
int32_t pos;
|
||||
int32_t max;
|
||||
i32_4tech pos;
|
||||
i32_4tech max;
|
||||
};
|
||||
|
||||
struct Temp_Memory{
|
||||
void *handle;
|
||||
int32_t pos;
|
||||
i32_4tech pos;
|
||||
};
|
||||
|
||||
struct Tail_Temp_Partition{
|
||||
Partition part;
|
||||
void *handle;
|
||||
int32_t old_max;
|
||||
i32_4tech old_max;
|
||||
};
|
||||
|
||||
inline Partition
|
||||
make_part(void *memory, int32_t size){
|
||||
make_part(void *memory, i32_4tech size){
|
||||
Partition partition;
|
||||
partition.base = (char*)memory;
|
||||
partition.pos = 0;
|
||||
|
@ -33,7 +65,7 @@ make_part(void *memory, int32_t size){
|
|||
}
|
||||
|
||||
inline void*
|
||||
partition_allocate(Partition *data, int32_t size){
|
||||
partition_allocate(Partition *data, i32_4tech size){
|
||||
void *ret = 0;
|
||||
if (size > 0 && data->pos + size <= data->max){
|
||||
ret = data->base + data->pos;
|
||||
|
@ -43,7 +75,7 @@ partition_allocate(Partition *data, int32_t size){
|
|||
}
|
||||
|
||||
inline void
|
||||
partition_align(Partition *data, uint32_t boundary){
|
||||
partition_align(Partition *data, u32_4tech boundary){
|
||||
--boundary;
|
||||
data->pos = (data->pos + boundary) & (~boundary);
|
||||
}
|
||||
|
@ -53,13 +85,13 @@ partition_current(Partition *data){
|
|||
return(data->base + data->pos);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
inline i32_4tech
|
||||
partition_remaining(Partition *data){
|
||||
return(data->max - data->pos);
|
||||
}
|
||||
|
||||
inline Partition
|
||||
partition_sub_part(Partition *data, int32_t size){
|
||||
partition_sub_part(Partition *data, i32_4tech size){
|
||||
Partition result = {};
|
||||
void *d = partition_allocate(data, size);
|
||||
if (d){
|
||||
|
@ -86,7 +118,7 @@ end_temp_memory(Temp_Memory temp){
|
|||
}
|
||||
|
||||
inline Tail_Temp_Partition
|
||||
begin_tail_part(Partition *data, int32_t size){
|
||||
begin_tail_part(Partition *data, i32_4tech size){
|
||||
Tail_Temp_Partition result = {0};
|
||||
if (data->pos + size <= data->max){
|
||||
result.handle = data;
|
||||
|
@ -121,9 +153,9 @@ struct Bubble{
|
|||
Bubble *next;
|
||||
Bubble *prev2;
|
||||
Bubble *next2;
|
||||
int32_t size;
|
||||
uint32_t flags;
|
||||
uint32_t _unused_[4];
|
||||
i32_4tech size;
|
||||
u32_4tech flags;
|
||||
u32_4tech _unused_[4];
|
||||
};
|
||||
|
||||
struct General_Memory{
|
||||
|
@ -178,12 +210,12 @@ general_sentinel_init(Bubble *bubble){
|
|||
#define BUBBLE_MIN_SIZE 1024
|
||||
|
||||
static void
|
||||
general_memory_attempt_split(General_Memory *general, Bubble *bubble, int32_t wanted_size){
|
||||
int32_t remaining_size = bubble->size - wanted_size;
|
||||
general_memory_attempt_split(General_Memory *general, Bubble *bubble, i32_4tech wanted_size){
|
||||
i32_4tech remaining_size = bubble->size - wanted_size;
|
||||
if (remaining_size >= BUBBLE_MIN_SIZE){
|
||||
bubble->size = wanted_size;
|
||||
Bubble *new_bubble = (Bubble*)((char*)(bubble + 1) + wanted_size);
|
||||
new_bubble->flags = (uint32_t)MEM_BUBBLE_FLAG_INIT;
|
||||
new_bubble->flags = (u32_4tech)MEM_BUBBLE_FLAG_INIT;
|
||||
new_bubble->size = remaining_size - sizeof(Bubble);
|
||||
insert_bubble(bubble, new_bubble);
|
||||
insert_bubble2(&general->free_sentinel, new_bubble);
|
||||
|
@ -206,20 +238,20 @@ general_memory_attempt_merge(Bubble *left, Bubble *right){
|
|||
|
||||
// NOTE(allen): public procedures
|
||||
static void
|
||||
general_memory_open(General_Memory *general, void *memory, int32_t size){
|
||||
general_memory_open(General_Memory *general, void *memory, i32_4tech size){
|
||||
general_sentinel_init(&general->sentinel);
|
||||
general_sentinel_init(&general->free_sentinel);
|
||||
general_sentinel_init(&general->used_sentinel);
|
||||
|
||||
Bubble *first = (Bubble*)memory;
|
||||
first->flags = (uint32_t)MEM_BUBBLE_FLAG_INIT;
|
||||
first->flags = (u32_4tech)MEM_BUBBLE_FLAG_INIT;
|
||||
first->size = size - sizeof(Bubble);
|
||||
insert_bubble(&general->sentinel, first);
|
||||
insert_bubble2(&general->free_sentinel, first);
|
||||
}
|
||||
|
||||
#if defined(Assert)
|
||||
static int32_t
|
||||
static i32_4tech
|
||||
general_memory_check(General_Memory *general){
|
||||
Bubble *sentinel = &general->sentinel;
|
||||
for (Bubble *bubble = sentinel->next;
|
||||
|
@ -243,12 +275,12 @@ general_memory_check(General_Memory *general){
|
|||
return(1);
|
||||
}
|
||||
#else
|
||||
static int32_t
|
||||
static i32_4tech
|
||||
general_memory_check(General_Memory *general){}
|
||||
#endif
|
||||
|
||||
static void*
|
||||
general_memory_allocate(General_Memory *general, int32_t size){
|
||||
general_memory_allocate(General_Memory *general, i32_4tech size){
|
||||
void *result = 0;
|
||||
if (size < BUBBLE_MIN_SIZE) size = BUBBLE_MIN_SIZE;
|
||||
for (Bubble *bubble = general->free_sentinel.next2;
|
||||
|
@ -284,10 +316,10 @@ general_memory_free(General_Memory *general, void *memory){
|
|||
}
|
||||
|
||||
static void*
|
||||
general_memory_reallocate(General_Memory *general, void *old, int32_t old_size, int32_t size){
|
||||
general_memory_reallocate(General_Memory *general, void *old, i32_4tech old_size, i32_4tech size){
|
||||
void *result = old;
|
||||
Bubble *bubble = ((Bubble*)old) - 1;
|
||||
int32_t additional_space = size - bubble->size;
|
||||
i32_4tech additional_space = size - bubble->size;
|
||||
if (additional_space > 0){
|
||||
Bubble *next = bubble->next;
|
||||
if (!(next->flags & MEM_BUBBLE_USED) &&
|
||||
|
@ -305,7 +337,7 @@ general_memory_reallocate(General_Memory *general, void *old, int32_t old_size,
|
|||
}
|
||||
|
||||
inline void*
|
||||
general_memory_reallocate_nocopy(General_Memory *general, void *old, int32_t size){
|
||||
general_memory_reallocate_nocopy(General_Memory *general, void *old, i32_4tech size){
|
||||
void *result = general_memory_reallocate(general, old, 0, size);
|
||||
return(result);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,45 +1,72 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 14.02.2016
|
||||
*
|
||||
* C style genereic hash table
|
||||
*
|
||||
*/
|
||||
4coder_table.h - Preversioning
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
This software is in the public domain. Where that dedication is not
|
||||
recognized, you are granted a perpetual, irrevocable license to copy,
|
||||
distribute, and modify this file as you see fit.
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_TABLE_H)
|
||||
#define FCODER_TABLE_H
|
||||
|
||||
// 4tech_standard_preamble.h
|
||||
#if !defined(FTECH_INTEGERS)
|
||||
#define FTECH_INTEGERS
|
||||
#include <stdint.h>
|
||||
typedef int8_t i8_4tech;
|
||||
typedef int16_t i16_4tech;
|
||||
typedef int32_t i32_4tech;
|
||||
typedef int64_t i64_4tech;
|
||||
|
||||
typedef uint8_t u8_4tech;
|
||||
typedef uint16_t u16_4tech;
|
||||
typedef uint32_t u32_4tech;
|
||||
typedef uint64_t u64_4tech;
|
||||
|
||||
typedef float f32_4tech;
|
||||
typedef double f64_4tech;
|
||||
|
||||
typedef int8_t b8_4tech;
|
||||
typedef int32_t b32_4tech;
|
||||
#endif
|
||||
|
||||
#if !defined(Assert)
|
||||
# define Assert(n) do{ if (!(n)) *(int*)0 = 0xA11E; }while(0)
|
||||
#endif
|
||||
// standard preamble end
|
||||
|
||||
#define TableHashEmpty 0
|
||||
#define TableHashDeleted 1
|
||||
#define TableHashMin 0x10000000
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef uint32_t Hash_Function(void *item, void *arg);
|
||||
typedef int32_t Compare_Function(void *key, void *item, void *arg);
|
||||
typedef u32_4tech Hash_Function(void *item, void *arg);
|
||||
typedef i32_4tech Compare_Function(void *key, void *item, void *arg);
|
||||
|
||||
struct Table{
|
||||
uint32_t *hash_array;
|
||||
u32_4tech *hash_array;
|
||||
char *data_array;
|
||||
int32_t count, max;
|
||||
int32_t item_size;
|
||||
i32_4tech count, max;
|
||||
i32_4tech item_size;
|
||||
};
|
||||
|
||||
static int32_t
|
||||
table_required_mem_size(int32_t table_size, int32_t item_size){
|
||||
int32_t hash_size = ((table_size * sizeof(uint32_t)) + 7) & ~7;
|
||||
int32_t mem_size = hash_size + table_size * item_size;
|
||||
static i32_4tech
|
||||
table_required_mem_size(i32_4tech table_size, i32_4tech item_size){
|
||||
i32_4tech hash_size = ((table_size * sizeof(u32_4tech)) + 7) & ~7;
|
||||
i32_4tech mem_size = hash_size + table_size * item_size;
|
||||
return(mem_size);
|
||||
}
|
||||
|
||||
static void
|
||||
table_init_memory(Table *table, void *memory, int32_t table_size, int32_t item_size){
|
||||
int32_t hash_size = table_size * sizeof(uint32_t);
|
||||
table_init_memory(Table *table, void *memory, i32_4tech table_size, i32_4tech item_size){
|
||||
i32_4tech hash_size = table_size * sizeof(u32_4tech);
|
||||
hash_size = (hash_size + 7) & ~7;
|
||||
|
||||
table->hash_array = (uint32_t*)memory;
|
||||
table->hash_array = (u32_4tech*)memory;
|
||||
table->data_array = (char*)(table->hash_array) + hash_size;
|
||||
|
||||
table->count = 0;
|
||||
|
@ -47,23 +74,23 @@ table_init_memory(Table *table, void *memory, int32_t table_size, int32_t item_s
|
|||
table->item_size = item_size;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
static i32_4tech
|
||||
table_at_capacity(Table *table){
|
||||
int32_t result = true;
|
||||
i32_4tech result = true;
|
||||
if (table->count * 8 < table->max * 7){
|
||||
result = false;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
static i32_4tech
|
||||
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
assert(table->count * 8 < table->max * 7);
|
||||
Assert(table->count * 8 < table->max * 7);
|
||||
|
||||
uint32_t hash = (hash_func(item, arg) | TableHashMin);
|
||||
int32_t i = hash % table->max;
|
||||
int32_t start = i;
|
||||
uint32_t *inspect = table->hash_array + i;
|
||||
u32_4tech hash = (hash_func(item, arg) | TableHashMin);
|
||||
i32_4tech i = hash % table->max;
|
||||
i32_4tech start = i;
|
||||
u32_4tech *inspect = table->hash_array + i;
|
||||
|
||||
while (*inspect >= TableHashMin){
|
||||
if (*inspect == hash){
|
||||
|
@ -77,7 +104,7 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
|
|||
i = 0;
|
||||
inspect = table->hash_array;
|
||||
}
|
||||
assert(i != start);
|
||||
Assert(i != start);
|
||||
}
|
||||
*inspect = hash;
|
||||
memcpy(table->data_array + i*table->item_size, item, table->item_size);
|
||||
|
@ -86,14 +113,14 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
|
|||
return(0);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
table_find_pos(Table *table, void *search_key, void *arg, int32_t *pos, int32_t *index, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
assert((table->count - 1) * 8 < table->max * 7);
|
||||
static i32_4tech
|
||||
table_find_pos(Table *table, void *search_key, void *arg, i32_4tech *pos, i32_4tech *index, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
Assert((table->count - 1) * 8 < table->max * 7);
|
||||
|
||||
uint32_t hash = (hash_func(search_key, arg) | TableHashMin);
|
||||
int32_t i = hash % table->max;
|
||||
int32_t start = i;
|
||||
uint32_t *inspect = table->hash_array + i;
|
||||
u32_4tech hash = (hash_func(search_key, arg) | TableHashMin);
|
||||
i32_4tech i = hash % table->max;
|
||||
i32_4tech start = i;
|
||||
u32_4tech *inspect = table->hash_array + i;
|
||||
|
||||
while (*inspect != TableHashEmpty){
|
||||
if (*inspect == hash){
|
||||
|
@ -118,7 +145,7 @@ table_find_pos(Table *table, void *search_key, void *arg, int32_t *pos, int32_t
|
|||
inline void*
|
||||
table_find_item(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
void *result = 0;
|
||||
int32_t pos;
|
||||
i32_4tech pos;
|
||||
if (table_find_pos(table, search_key, arg, &pos, 0, hash_func, comp_func)){
|
||||
result = table->data_array + pos;
|
||||
}
|
||||
|
@ -126,15 +153,15 @@ table_find_item(Table *table, void *search_key, void *arg, Hash_Function *hash_f
|
|||
}
|
||||
|
||||
inline void
|
||||
table_remove_index(Table *table, int32_t index){
|
||||
table_remove_index(Table *table, i32_4tech index){
|
||||
table->hash_array[index] = TableHashDeleted;
|
||||
--table->count;
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
inline i32_4tech
|
||||
table_remove_match(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
int32_t result = false;
|
||||
int32_t index;
|
||||
i32_4tech result = false;
|
||||
i32_4tech index;
|
||||
if (table_find_pos(table, search_key, arg, 0, &index, hash_func, comp_func)){
|
||||
table_remove_index(table, index);
|
||||
result = true;
|
||||
|
@ -150,14 +177,14 @@ table_clear(Table *table){
|
|||
|
||||
static void
|
||||
table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
assert((dst->count + src->count - 1) * 7 < dst->max * 8);
|
||||
assert(dst->item_size == src->item_size);
|
||||
Assert((dst->count + src->count - 1) * 7 < dst->max * 8);
|
||||
Assert(dst->item_size == src->item_size);
|
||||
|
||||
int32_t count = src->count;
|
||||
int32_t item_size = src->item_size;
|
||||
uint32_t *hash_item = src->hash_array;
|
||||
i32_4tech count = src->count;
|
||||
i32_4tech item_size = src->item_size;
|
||||
u32_4tech *hash_item = src->hash_array;
|
||||
char *data_item = src->data_array;
|
||||
for (int32_t i = 0, c = 0;
|
||||
for (i32_4tech i = 0, c = 0;
|
||||
c < count;
|
||||
++i, ++hash_item, data_item += item_size){
|
||||
if (*hash_item >= TableHashMin){
|
||||
|
@ -167,67 +194,71 @@ table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compar
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
static u32_4tech
|
||||
tbl_string_hash(void *item, void *arg){
|
||||
String *string = (String*)item;
|
||||
char *str = string->str;
|
||||
int32_t i = 0, len = string->size;
|
||||
uint32_t x = 5381;
|
||||
char c;
|
||||
u32_4tech x = 5381;
|
||||
(void)arg;
|
||||
|
||||
char *str = string->str;
|
||||
i32_4tech len = string->size;
|
||||
i32_4tech i = 0;
|
||||
while (i < len){
|
||||
c = str[i++];
|
||||
char c = str[i++];
|
||||
x = ((x << 5) + x) + c;
|
||||
}
|
||||
|
||||
return(x);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
static i32_4tech
|
||||
tbl_string_compare(void *a, void *b, void *arg){
|
||||
String *stra = (String*)a;
|
||||
String *strb = (String*)b;
|
||||
int32_t result = !match_ss(*stra, *strb);
|
||||
i32_4tech result = !match_ss(*stra, *strb);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
struct Offset_String{
|
||||
i32_4tech offset;
|
||||
i32_4tech size;
|
||||
};
|
||||
|
||||
static u32_4tech
|
||||
tbl_offset_string_hash(void *item, void *arg){
|
||||
Offset_String *string = (Offset_String*)item;
|
||||
char *str;
|
||||
int32_t i,len;
|
||||
uint32_t x = 5381;
|
||||
char c;
|
||||
u32_4tech x = 5381;
|
||||
|
||||
str = ((char*)arg) + string->offset;
|
||||
len = string->size;
|
||||
i = 0;
|
||||
char *str = ((char*)arg) + string->offset;
|
||||
i32_4tech len = string->size;
|
||||
i32_4tech i = 0;
|
||||
while (i < len){
|
||||
c = str[i++];
|
||||
char c = str[i++];
|
||||
x = ((x << 5) + x) + c;
|
||||
}
|
||||
|
||||
return(x);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
static i32_4tech
|
||||
tbl_offset_string_compare(void *a, void *b, void *arg){
|
||||
Offset_String *ostra = (Offset_String*)a;
|
||||
Offset_String *ostrb = (Offset_String*)b;
|
||||
String stra = make_string((char*)arg + ostra->offset, ostra->size);
|
||||
String strb = make_string((char*)arg + ostrb->offset, ostrb->size);
|
||||
int32_t result = !match_ss(stra, strb);
|
||||
i32_4tech result = !match_ss(stra, strb);
|
||||
return(result);
|
||||
}
|
||||
|
||||
struct String_Space{
|
||||
char *space;
|
||||
int32_t pos, new_pos, max;
|
||||
i32_4tech pos;
|
||||
i32_4tech new_pos;
|
||||
i32_4tech max;
|
||||
};
|
||||
|
||||
static Offset_String
|
||||
strspace_append(String_Space *space, char *str, int32_t len){
|
||||
strspace_append(String_Space *space, char *str, i32_4tech len){
|
||||
Offset_String result = {};
|
||||
if (space->new_pos + len <= space->max){
|
||||
result.offset = space->new_pos;
|
||||
|
@ -249,5 +280,7 @@ strspace_discard_prev(String_Space *space){
|
|||
space->new_pos = space->pos;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
146
4coder_rect.h
146
4coder_rect.h
|
@ -1,146 +0,0 @@
|
|||
|
||||
#ifndef FCODER_RECT_H
|
||||
#define FCODER_RECT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct i32_Rect{
|
||||
int32_t x0, y0;
|
||||
int32_t x1, y1;
|
||||
};
|
||||
|
||||
struct f32_Rect{
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
};
|
||||
|
||||
inline i32_Rect
|
||||
i32_rect_zero(){
|
||||
i32_Rect rect={0};
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline f32_Rect
|
||||
f32_rect_zero(){
|
||||
f32_Rect rect={0};
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
i32R(int32_t l, int32_t t, int32_t r, int32_t b){
|
||||
i32_Rect rect;
|
||||
rect.x0 = l; rect.y0 = t;
|
||||
rect.x1 = r; rect.y1 = b;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
i32R(f32_Rect r){
|
||||
i32_Rect rect;
|
||||
rect.x0 = (int32_t)r.x0;
|
||||
rect.y0 = (int32_t)r.y0;
|
||||
rect.x1 = (int32_t)r.x1;
|
||||
rect.y1 = (int32_t)r.y1;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
i32XYWH(int32_t x, int32_t y, int32_t w, int32_t h){
|
||||
i32_Rect rect;
|
||||
rect.x0 = x; rect.y0 = y;
|
||||
rect.x1 = x+w; rect.y1 = y+h;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline f32_Rect
|
||||
f32R(float l, float t, float r, float b){
|
||||
f32_Rect rect;
|
||||
rect.x0 = l; rect.y0 = t;
|
||||
rect.x1 = r; rect.y1 = b;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline f32_Rect
|
||||
f32R(i32_Rect r){
|
||||
f32_Rect rect;
|
||||
rect.x0 = (float)r.x0;
|
||||
rect.y0 = (float)r.y0;
|
||||
rect.x1 = (float)r.x1;
|
||||
rect.y1 = (float)r.y1;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline f32_Rect
|
||||
f32XYWH(float x, float y, float w, float h){
|
||||
f32_Rect rect;
|
||||
rect.x0 = x; rect.y0 = y;
|
||||
rect.x1 = x+w; rect.y1 = y+h;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
rect_equal(i32_Rect r1, i32_Rect r2){
|
||||
int32_t result = (r1.x0 == r2.x0 &&
|
||||
r1.y0 == r2.y0 &&
|
||||
r1.x1 == r2.x1 &&
|
||||
r1.y1 == r2.y1);
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
hit_check(int32_t x, int32_t y, int32_t x0, int32_t y0, int32_t x1, int32_t y1){
|
||||
return (x >= x0 && x < x1 && y >= y0 && y < y1);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
hit_check(int32_t x, int32_t y, i32_Rect rect){
|
||||
return (hit_check(x, y, rect.x0, rect.y0, rect.x1, rect.y1));
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
hit_check(int32_t x, int32_t y, float x0, float y0, float x1, float y1){
|
||||
return (x >= x0 && x < x1 && y >= y0 && y < y1);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
hit_check(int32_t x, int32_t y, f32_Rect rect){
|
||||
return (hit_check(x, y, rect.x0, rect.y0, rect.x1, rect.y1));
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
positive_area(i32_Rect rect){
|
||||
return (rect.x0 < rect.x1 && rect.y0 < rect.y1);
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
get_inner_rect(i32_Rect outer, int32_t margin){
|
||||
i32_Rect r;
|
||||
r.x0 = outer.x0 + margin;
|
||||
r.y0 = outer.y0 + margin;
|
||||
r.x1 = outer.x1 - margin;
|
||||
r.y1 = outer.y1 - margin;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
fits_inside(i32_Rect rect, i32_Rect outer){
|
||||
return (rect.x0 >= outer.x0 && rect.x1 <= outer.x1 &&
|
||||
rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
rect_clamp_to_rect(i32_Rect rect, i32_Rect clamp_box){
|
||||
if (rect.x0 < clamp_box.x0) rect.x0 = clamp_box.x0;
|
||||
if (rect.y0 < clamp_box.y0) rect.y0 = clamp_box.y0;
|
||||
if (rect.x1 > clamp_box.x1) rect.x1 = clamp_box.x1;
|
||||
if (rect.y1 > clamp_box.y1) rect.y1 = clamp_box.y1;
|
||||
return rect;
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
rect_clamp_to_rect(int32_t left, int32_t top, int32_t right, int32_t bottom, i32_Rect clamp_box){
|
||||
return rect_clamp_to_rect(i32R(left, top, right, bottom), clamp_box);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,7 +1,27 @@
|
|||
/*
|
||||
4coder_search.cpp - Commands that search accross buffers including word complete,
|
||||
and list all locations.
|
||||
|
||||
#ifndef FCODER_SEARCH
|
||||
TYPE: 'drop-in-command-pack'
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_SEARCH)
|
||||
#define FCODER_SEARCH
|
||||
|
||||
#include "4coder_lib/4coder_table.h"
|
||||
#include "4coder_lib/4coder_mem.h"
|
||||
|
||||
#include "4coder_helper/4coder_streaming.h"
|
||||
#include "4coder_helper/4coder_long_seek.h"
|
||||
|
||||
#include "4coder_default_framework.h"
|
||||
|
||||
//
|
||||
// Search Iteration Systems
|
||||
//
|
||||
|
||||
enum Search_Range_Type{
|
||||
SearchRange_FrontToBack,
|
||||
SearchRange_BackToFront,
|
||||
|
@ -120,7 +140,7 @@ static int32_t
|
|||
search_hit_add(General_Memory *general, Table *hits, String_Space *space, char *str, int32_t len){
|
||||
int32_t result = false;
|
||||
|
||||
assert(len != 0);
|
||||
Assert(len != 0);
|
||||
|
||||
Offset_String ostring = strspace_append(space, str, len);
|
||||
if (ostring.size == 0){
|
||||
|
@ -133,7 +153,7 @@ search_hit_add(General_Memory *general, Table *hits, String_Space *space, char *
|
|||
ostring = strspace_append(space, str, len);
|
||||
}
|
||||
|
||||
assert(ostring.size != 0);
|
||||
Assert(ostring.size != 0);
|
||||
|
||||
if (table_at_capacity(hits)){
|
||||
Table new_hits = {0};
|
||||
|
@ -479,4 +499,381 @@ search_next_match(Application_Links *app, Search_Set *set, Search_Iter *it_ptr){
|
|||
return(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Generic Search All Buffers
|
||||
//
|
||||
|
||||
static void
|
||||
get_search_all_string(Application_Links *app, Query_Bar *bar){
|
||||
char string_space[1024];
|
||||
bar->prompt = make_lit_string("List Locations For: ");
|
||||
bar->string = make_fixed_width_string(string_space);
|
||||
|
||||
if (!query_user_string(app, bar)){
|
||||
bar->string.size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
generic_search_all_buffers(Application_Links *app, General_Memory *general, Partition *part, String string, uint32_t match_flags){
|
||||
Search_Set set = {0};
|
||||
Search_Iter iter = {0};
|
||||
|
||||
search_iter_init(general, &iter, string.size);
|
||||
copy_ss(&iter.word, string);
|
||||
|
||||
int32_t buffer_count = get_buffer_count(app);
|
||||
search_set_init(general, &set, buffer_count);
|
||||
|
||||
Search_Range *ranges = set.ranges;
|
||||
|
||||
String search_name = make_lit_string("*search*");
|
||||
Buffer_Summary search_buffer = get_buffer_by_name(app, search_name.str, search_name.size, AccessAll);
|
||||
if (!search_buffer.exists){
|
||||
search_buffer = create_buffer(app, search_name.str, search_name.size, BufferCreate_AlwaysNew);
|
||||
buffer_set_setting(app, &search_buffer, BufferSetting_Unimportant, true);
|
||||
buffer_set_setting(app, &search_buffer, BufferSetting_ReadOnly, true);
|
||||
buffer_set_setting(app, &search_buffer, BufferSetting_WrapLine, false);
|
||||
}
|
||||
else{
|
||||
buffer_replace_range(app, &search_buffer, 0, search_buffer.size, 0, 0);
|
||||
}
|
||||
|
||||
{
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
|
||||
|
||||
int32_t j = 0;
|
||||
if (buffer.exists){
|
||||
if (buffer.buffer_id != search_buffer.buffer_id){
|
||||
ranges[0].type = SearchRange_FrontToBack;
|
||||
ranges[0].flags = match_flags;
|
||||
ranges[0].buffer = buffer.buffer_id;
|
||||
ranges[0].start = 0;
|
||||
ranges[0].size = buffer.size;
|
||||
j = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (Buffer_Summary buffer_it = get_buffer_first(app, AccessAll);
|
||||
buffer_it.exists;
|
||||
get_buffer_next(app, &buffer_it, AccessAll)){
|
||||
if (buffer.buffer_id != buffer_it.buffer_id){
|
||||
if (search_buffer.buffer_id != buffer_it.buffer_id){
|
||||
ranges[j].type = SearchRange_FrontToBack;
|
||||
ranges[j].flags = match_flags;
|
||||
ranges[j].buffer = buffer_it.buffer_id;
|
||||
ranges[j].start = 0;
|
||||
ranges[j].size = buffer_it.size;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
set.count = j;
|
||||
}
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
Partition line_part = partition_sub_part(part, (4 << 10));
|
||||
char *str = (char*)partition_current(part);
|
||||
int32_t part_size = 0;
|
||||
int32_t size = 0;
|
||||
for (;;){
|
||||
Search_Match match = search_next_match(app, &set, &iter);
|
||||
if (match.found_match){
|
||||
Partial_Cursor word_pos = {0};
|
||||
if (buffer_compute_cursor(app, &match.buffer, seek_pos(match.start), &word_pos)){
|
||||
int32_t file_len = match.buffer.file_name_len;
|
||||
int32_t line_num_len = int_to_str_size(word_pos.line);
|
||||
int32_t column_num_len = int_to_str_size(word_pos.character);
|
||||
|
||||
Temp_Memory line_temp = begin_temp_memory(&line_part);
|
||||
String line_str = {0};
|
||||
read_line(app, &line_part, &match.buffer, word_pos.line, &line_str);
|
||||
line_str = skip_chop_whitespace(line_str);
|
||||
|
||||
int32_t str_len = file_len + 1 + line_num_len + 1 + column_num_len + 1 + 1 + line_str.size + 1;
|
||||
|
||||
char *spare = push_array(part, char, str_len);
|
||||
|
||||
if (spare == 0){
|
||||
buffer_replace_range(app, &search_buffer, size, size, str, part_size);
|
||||
size += part_size;
|
||||
|
||||
end_temp_memory(temp);
|
||||
temp = begin_temp_memory(part);
|
||||
|
||||
part_size = 0;
|
||||
spare = push_array(part, char, str_len);
|
||||
}
|
||||
|
||||
part_size += str_len;
|
||||
|
||||
String out_line = make_string_cap(spare, 0, str_len);
|
||||
append_ss(&out_line, make_string(match.buffer.file_name, file_len));
|
||||
append_s_char(&out_line, ':');
|
||||
append_int_to_str(&out_line, word_pos.line);
|
||||
append_s_char(&out_line, ':');
|
||||
append_int_to_str(&out_line, word_pos.character);
|
||||
append_s_char(&out_line, ':');
|
||||
append_s_char(&out_line, ' ');
|
||||
append_ss(&out_line, line_str);
|
||||
append_s_char(&out_line, '\n');
|
||||
Assert(out_line.size == str_len);
|
||||
|
||||
end_temp_memory(line_temp);
|
||||
}
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_replace_range(app, &search_buffer, size, size, str, part_size);
|
||||
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
view_set_buffer(app, &view, search_buffer.buffer_id, 0);
|
||||
|
||||
lock_jump_buffer(search_name.str, search_name.size);
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
//
|
||||
// List Commands
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(list_all_locations){
|
||||
Query_Bar bar;
|
||||
get_search_all_string(app, &bar);
|
||||
if (bar.string.size == 0) return;
|
||||
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_MatchWholeWord);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(list_all_substring_locations){
|
||||
Query_Bar bar;
|
||||
get_search_all_string(app, &bar);
|
||||
if (bar.string.size == 0) return;
|
||||
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_MatchSubstring);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(list_all_locations_case_insensitive){
|
||||
Query_Bar bar;
|
||||
get_search_all_string(app, &bar);
|
||||
if (bar.string.size == 0) return;
|
||||
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchWholeWord);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(list_all_substring_locations_case_insensitive){
|
||||
Query_Bar bar;
|
||||
get_search_all_string(app, &bar);
|
||||
if (bar.string.size == 0) return;
|
||||
generic_search_all_buffers(app, &global_general, &global_part, bar.string, SearchFlag_CaseInsensitive | SearchFlag_MatchSubstring);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(list_all_locations_of_identifier){
|
||||
View_Summary view = get_active_view(app, AccessProtected);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected);
|
||||
|
||||
Cpp_Get_Token_Result get_result = {0};
|
||||
bool32 success = buffer_get_token_index(app, &buffer, view.cursor.pos, &get_result);
|
||||
|
||||
if (success && !get_result.in_whitespace){
|
||||
char space[128];
|
||||
int32_t size = get_result.token_end - get_result.token_start;
|
||||
|
||||
if (size > 0 && size <= sizeof(space)){
|
||||
success = buffer_read_range(app, &buffer, get_result.token_start, get_result.token_end, space);
|
||||
if (success){
|
||||
String str = make_string(space, size);
|
||||
exec_command(app, change_active_panel);
|
||||
generic_search_all_buffers(app, &global_general, &global_part, str, SearchFlag_MatchWholeWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Word Complete Command
|
||||
//
|
||||
|
||||
struct Word_Complete_State{
|
||||
Search_Set set;
|
||||
Search_Iter iter;
|
||||
Table hits;
|
||||
String_Space str;
|
||||
int32_t word_start;
|
||||
int32_t word_end;
|
||||
int32_t initialized;
|
||||
};
|
||||
|
||||
static Word_Complete_State complete_state = {0};
|
||||
|
||||
CUSTOM_COMMAND_SIG(word_complete){
|
||||
View_Summary view = get_active_view(app, AccessOpen);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
|
||||
|
||||
// NOTE(allen): I just do this because this command is a lot of work
|
||||
// and there is no point in doing any of it if nothing will happen anyway.
|
||||
if (buffer.exists){
|
||||
int32_t do_init = false;
|
||||
|
||||
if (view_paste_index[view.view_id].rewrite != RewriteWordComplete){
|
||||
do_init = true;
|
||||
}
|
||||
view_paste_index[view.view_id].next_rewrite = RewriteWordComplete;
|
||||
if (!complete_state.initialized){
|
||||
do_init = true;
|
||||
}
|
||||
|
||||
int32_t word_end = 0;
|
||||
int32_t word_start = 0;
|
||||
int32_t cursor_pos = 0;
|
||||
int32_t size = 0;
|
||||
|
||||
if (do_init){
|
||||
// NOTE(allen): Get the range where the
|
||||
// partial word is written.
|
||||
word_end = view.cursor.pos;
|
||||
word_start = word_end;
|
||||
cursor_pos = word_end - 1;
|
||||
|
||||
char space[1024];
|
||||
Stream_Chunk chunk = {0};
|
||||
if (init_stream_chunk(&chunk, app, &buffer, cursor_pos, space, sizeof(space))){
|
||||
int32_t still_looping = true;
|
||||
do{
|
||||
for (; cursor_pos >= chunk.start; --cursor_pos){
|
||||
char c = chunk.data[cursor_pos];
|
||||
if (char_is_alpha(c)){
|
||||
word_start = cursor_pos;
|
||||
}
|
||||
else if (!char_is_numeric(c)){
|
||||
goto double_break;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&chunk);
|
||||
}while(still_looping);
|
||||
}
|
||||
double_break:;
|
||||
|
||||
size = word_end - word_start;
|
||||
|
||||
if (size == 0){
|
||||
complete_state.initialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE(allen): Initialize the search iterator
|
||||
// with the partial word.
|
||||
complete_state.initialized = true;
|
||||
search_iter_init(&global_general, &complete_state.iter, size);
|
||||
buffer_read_range(app, &buffer, word_start, word_end,
|
||||
complete_state.iter.word.str);
|
||||
complete_state.iter.word.size = size;
|
||||
|
||||
// NOTE(allen): Initialize the set of ranges to be searched.
|
||||
int32_t buffer_count = get_buffer_count(app);
|
||||
search_set_init(&global_general, &complete_state.set, buffer_count);
|
||||
|
||||
Search_Range *ranges = complete_state.set.ranges;
|
||||
ranges[0].type = SearchRange_Wave;
|
||||
ranges[0].flags = SearchFlag_MatchWordPrefix;
|
||||
ranges[0].buffer = buffer.buffer_id;
|
||||
ranges[0].start = 0;
|
||||
ranges[0].size = buffer.size;
|
||||
ranges[0].mid_start = word_start;
|
||||
ranges[0].mid_size = size;
|
||||
|
||||
int32_t j = 1;
|
||||
for (Buffer_Summary buffer_it = get_buffer_first(app, AccessAll);
|
||||
buffer_it.exists;
|
||||
get_buffer_next(app, &buffer_it, AccessAll)){
|
||||
if (buffer.buffer_id != buffer_it.buffer_id){
|
||||
ranges[j].type = SearchRange_FrontToBack;
|
||||
ranges[j].flags = SearchFlag_MatchWordPrefix;
|
||||
ranges[j].buffer = buffer_it.buffer_id;
|
||||
ranges[j].start = 0;
|
||||
ranges[j].size = buffer_it.size;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
complete_state.set.count = j;
|
||||
|
||||
// NOTE(allen): Initialize the search hit table.
|
||||
search_hits_init(&global_general, &complete_state.hits, &complete_state.str,
|
||||
100, (4 << 10));
|
||||
search_hit_add(&global_general, &complete_state.hits, &complete_state.str,
|
||||
complete_state.iter.word.str,
|
||||
complete_state.iter.word.size);
|
||||
|
||||
complete_state.word_start = word_start;
|
||||
complete_state.word_end = word_end;
|
||||
}
|
||||
else{
|
||||
word_start = complete_state.word_start;
|
||||
word_end = complete_state.word_end;
|
||||
size = complete_state.iter.word.size;
|
||||
}
|
||||
|
||||
// NOTE(allen): Iterate through matches.
|
||||
if (size > 0){
|
||||
for (;;){
|
||||
int32_t match_size = 0;
|
||||
Search_Match match =
|
||||
search_next_match(app, &complete_state.set,
|
||||
&complete_state.iter);
|
||||
|
||||
if (match.found_match){
|
||||
match_size = match.end - match.start;
|
||||
Temp_Memory temp = begin_temp_memory(&global_part);
|
||||
char *spare = push_array(&global_part, char, match_size);
|
||||
|
||||
buffer_read_range(app, &match.buffer,
|
||||
match.start, match.end, spare);
|
||||
|
||||
if (search_hit_add(&global_general, &complete_state.hits, &complete_state.str,
|
||||
spare, match_size)){
|
||||
buffer_replace_range(app, &buffer, word_start, word_end,
|
||||
spare, match_size);
|
||||
view_set_cursor(app, &view,
|
||||
seek_pos(word_start + match_size),
|
||||
true);
|
||||
|
||||
complete_state.word_end = word_start + match_size;
|
||||
complete_state.set.ranges[0].mid_size = match_size;
|
||||
end_temp_memory(temp);
|
||||
break;
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
else{
|
||||
complete_state.iter.pos = 0;
|
||||
complete_state.iter.i = 0;
|
||||
|
||||
search_hits_init(&global_general, &complete_state.hits, &complete_state.str,
|
||||
100, (4 << 10));
|
||||
search_hit_add(&global_general, &complete_state.hits, &complete_state.str,
|
||||
complete_state.iter.word.str,
|
||||
complete_state.iter.word.size);
|
||||
|
||||
match_size = complete_state.iter.word.size;
|
||||
char *str = complete_state.iter.word.str;
|
||||
buffer_replace_range(app, &buffer, word_start, word_end,
|
||||
str, match_size);
|
||||
view_set_cursor(app, &view,
|
||||
seek_pos(word_start + match_size),
|
||||
true);
|
||||
|
||||
complete_state.word_end = word_start + match_size;
|
||||
complete_state.set.ranges[0].mid_size = match_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -1,163 +1,197 @@
|
|||
/*
|
||||
4cpp_lexer.h - Preversioning
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
This software is in the public domain. Where that dedication is not
|
||||
recognized, you are granted a perpetual, irrevocable license to copy,
|
||||
distribute, and modify this file as you see fit.
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#ifndef FCPP_NEW_LEXER_INC
|
||||
#define FCPP_NEW_LEXER_INC
|
||||
|
||||
#ifndef Assert
|
||||
// 4tech_standard_preamble.h
|
||||
#if !defined(FTECH_INTEGERS)
|
||||
#define FTECH_INTEGERS
|
||||
#include <stdint.h>
|
||||
typedef int8_t i8_4tech;
|
||||
typedef int16_t i16_4tech;
|
||||
typedef int32_t i32_4tech;
|
||||
typedef int64_t i64_4tech;
|
||||
|
||||
typedef uint8_t u8_4tech;
|
||||
typedef uint16_t u16_4tech;
|
||||
typedef uint32_t u32_4tech;
|
||||
typedef uint64_t u64_4tech;
|
||||
|
||||
typedef float f32_4tech;
|
||||
typedef double f64_4tech;
|
||||
|
||||
typedef int8_t b8_4tech;
|
||||
typedef int32_t b32_4tech;
|
||||
#endif
|
||||
|
||||
#if !defined(Assert)
|
||||
# define Assert(n) do{ if (!(n)) *(int*)0 = 0xA11E; }while(0)
|
||||
#endif
|
||||
|
||||
#if !defined(API_EXPORT)
|
||||
# define API_EXPORT
|
||||
#endif
|
||||
// standard preamble end
|
||||
|
||||
// duff-routine defines
|
||||
#define DfrCase(PC) case PC: goto resumespot_##PC
|
||||
#define DfrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
|
||||
#define DfrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); }
|
||||
|
||||
#ifndef FCPP_LINK
|
||||
# define FCPP_LINK static
|
||||
#endif
|
||||
|
||||
#ifndef API_EXPORT
|
||||
#define API_EXPORT
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#if !defined(FSTRING_GUARD)
|
||||
# define FSTRING_IMPLEMENTATION
|
||||
# include "4coder_string.h"
|
||||
#endif
|
||||
#include "4cpp_lexer_types.h"
|
||||
#include "4cpp_lexer_tables.c"
|
||||
|
||||
// TODO(allen): revisit this keyword data declaration system
|
||||
struct String_And_Flag{
|
||||
String str;
|
||||
uint32_t flags;
|
||||
char *str;
|
||||
u32_4tech length;
|
||||
u32_4tech flags;
|
||||
};
|
||||
|
||||
#define make_stafl(s,f) (s), sizeof(s)-1, f
|
||||
|
||||
static String_And_Flag preprops[] = {
|
||||
{make_lit_string("include"), CPP_PP_INCLUDE } ,
|
||||
{make_lit_string("INCLUDE"), CPP_PP_INCLUDE } ,
|
||||
{make_lit_string("ifndef" ), CPP_PP_IFNDEF } ,
|
||||
{make_lit_string("IFNDEF" ), CPP_PP_IFNDEF } ,
|
||||
{make_lit_string("define" ), CPP_PP_DEFINE } ,
|
||||
{make_lit_string("DEFINE" ), CPP_PP_DEFINE } ,
|
||||
{make_lit_string("import" ), CPP_PP_IMPORT } ,
|
||||
{make_lit_string("IMPORT" ), CPP_PP_IMPORT } ,
|
||||
{make_lit_string("pragma" ), CPP_PP_PRAGMA } ,
|
||||
{make_lit_string("PRAGMA" ), CPP_PP_PRAGMA } ,
|
||||
{make_lit_string("undef" ), CPP_PP_UNDEF } ,
|
||||
{make_lit_string("UNDEF" ), CPP_PP_UNDEF } ,
|
||||
{make_lit_string("endif" ), CPP_PP_ENDIF } ,
|
||||
{make_lit_string("ENDIF" ), CPP_PP_ENDIF } ,
|
||||
{make_lit_string("error" ), CPP_PP_ERROR } ,
|
||||
{make_lit_string("ERROR" ), CPP_PP_ERROR } ,
|
||||
{make_lit_string("ifdef" ), CPP_PP_IFDEF } ,
|
||||
{make_lit_string("IFDEF" ), CPP_PP_IFDEF } ,
|
||||
{make_lit_string("using" ), CPP_PP_USING } ,
|
||||
{make_lit_string("USING" ), CPP_PP_USING } ,
|
||||
{make_lit_string("else" ), CPP_PP_ELSE } ,
|
||||
{make_lit_string("ELSE" ), CPP_PP_ELSE } ,
|
||||
{make_lit_string("elif" ), CPP_PP_ELIF } ,
|
||||
{make_lit_string("ELIF" ), CPP_PP_ELIF } ,
|
||||
{make_lit_string("line" ), CPP_PP_LINE } ,
|
||||
{make_lit_string("LINE" ), CPP_PP_LINE } ,
|
||||
{make_lit_string("if" ), CPP_PP_IF } ,
|
||||
{make_lit_string("IF" ), CPP_PP_IF } ,
|
||||
{make_stafl("include" , CPP_PP_INCLUDE )} ,
|
||||
{make_stafl("INCLUDE" , CPP_PP_INCLUDE )} ,
|
||||
{make_stafl("ifndef" , CPP_PP_IFNDEF )} ,
|
||||
{make_stafl("IFNDEF" , CPP_PP_IFNDEF )} ,
|
||||
{make_stafl("define" , CPP_PP_DEFINE )} ,
|
||||
{make_stafl("DEFINE" , CPP_PP_DEFINE )} ,
|
||||
{make_stafl("import" , CPP_PP_IMPORT )} ,
|
||||
{make_stafl("IMPORT" , CPP_PP_IMPORT )} ,
|
||||
{make_stafl("pragma" , CPP_PP_PRAGMA )} ,
|
||||
{make_stafl("PRAGMA" , CPP_PP_PRAGMA )} ,
|
||||
{make_stafl("undef" , CPP_PP_UNDEF )} ,
|
||||
{make_stafl("UNDEF" , CPP_PP_UNDEF )} ,
|
||||
{make_stafl("endif" , CPP_PP_ENDIF )} ,
|
||||
{make_stafl("ENDIF" , CPP_PP_ENDIF )} ,
|
||||
{make_stafl("error" , CPP_PP_ERROR )} ,
|
||||
{make_stafl("ERROR" , CPP_PP_ERROR )} ,
|
||||
{make_stafl("ifdef" , CPP_PP_IFDEF )} ,
|
||||
{make_stafl("IFDEF" , CPP_PP_IFDEF )} ,
|
||||
{make_stafl("using" , CPP_PP_USING )} ,
|
||||
{make_stafl("USING" , CPP_PP_USING )} ,
|
||||
{make_stafl("else" , CPP_PP_ELSE )} ,
|
||||
{make_stafl("ELSE" , CPP_PP_ELSE )} ,
|
||||
{make_stafl("elif" , CPP_PP_ELIF )} ,
|
||||
{make_stafl("ELIF" , CPP_PP_ELIF )} ,
|
||||
{make_stafl("line" , CPP_PP_LINE )} ,
|
||||
{make_stafl("LINE" , CPP_PP_LINE )} ,
|
||||
{make_stafl("if" , CPP_PP_IF )} ,
|
||||
{make_stafl("IF" , CPP_PP_IF )} ,
|
||||
};
|
||||
static i32_4tech preprops_count = sizeof(preprops)/sizeof(preprops[0]);
|
||||
|
||||
static String_And_Flag keywords[] = {
|
||||
{make_lit_string("true") , CPP_TOKEN_BOOLEAN_CONSTANT},
|
||||
{make_lit_string("false") , CPP_TOKEN_BOOLEAN_CONSTANT},
|
||||
{make_stafl("true" , CPP_TOKEN_BOOLEAN_CONSTANT)},
|
||||
{make_stafl("false" , CPP_TOKEN_BOOLEAN_CONSTANT)},
|
||||
|
||||
{make_lit_string("and") , CPP_TOKEN_AND},
|
||||
{make_lit_string("and_eq") , CPP_TOKEN_ANDEQ},
|
||||
{make_lit_string("bitand") , CPP_TOKEN_BIT_AND},
|
||||
{make_lit_string("bitor") , CPP_TOKEN_BIT_OR},
|
||||
{make_lit_string("or") , CPP_TOKEN_OR},
|
||||
{make_lit_string("or_eq") , CPP_TOKEN_OREQ},
|
||||
{make_lit_string("sizeof") , CPP_TOKEN_SIZEOF},
|
||||
{make_lit_string("alignof") , CPP_TOKEN_ALIGNOF},
|
||||
{make_lit_string("decltype") , CPP_TOKEN_DECLTYPE},
|
||||
{make_lit_string("throw") , CPP_TOKEN_THROW},
|
||||
{make_lit_string("new") , CPP_TOKEN_NEW},
|
||||
{make_lit_string("delete") , CPP_TOKEN_DELETE},
|
||||
{make_lit_string("xor") , CPP_TOKEN_BIT_XOR},
|
||||
{make_lit_string("xor_eq") , CPP_TOKEN_XOREQ},
|
||||
{make_lit_string("not") , CPP_TOKEN_NOT},
|
||||
{make_lit_string("not_eq") , CPP_TOKEN_NOTEQ},
|
||||
{make_lit_string("typeid") , CPP_TOKEN_TYPEID},
|
||||
{make_lit_string("compl") , CPP_TOKEN_BIT_NOT},
|
||||
{make_stafl("and" , CPP_TOKEN_AND)},
|
||||
{make_stafl("and_eq" , CPP_TOKEN_ANDEQ)},
|
||||
{make_stafl("bitand" , CPP_TOKEN_BIT_AND)},
|
||||
{make_stafl("bitor" , CPP_TOKEN_BIT_OR)},
|
||||
{make_stafl("or" , CPP_TOKEN_OR)},
|
||||
{make_stafl("or_eq" , CPP_TOKEN_OREQ)},
|
||||
{make_stafl("sizeof" , CPP_TOKEN_SIZEOF)},
|
||||
{make_stafl("alignof" , CPP_TOKEN_ALIGNOF)},
|
||||
{make_stafl("decltype" , CPP_TOKEN_DECLTYPE)},
|
||||
{make_stafl("throw" , CPP_TOKEN_THROW)},
|
||||
{make_stafl("new" , CPP_TOKEN_NEW)},
|
||||
{make_stafl("delete" , CPP_TOKEN_DELETE)},
|
||||
{make_stafl("xor" , CPP_TOKEN_BIT_XOR)},
|
||||
{make_stafl("xor_eq" , CPP_TOKEN_XOREQ)},
|
||||
{make_stafl("not" , CPP_TOKEN_NOT)},
|
||||
{make_stafl("not_eq" , CPP_TOKEN_NOTEQ)},
|
||||
{make_stafl("typeid" , CPP_TOKEN_TYPEID)},
|
||||
{make_stafl("compl" , CPP_TOKEN_BIT_NOT)},
|
||||
|
||||
{make_lit_string("void") , CPP_TOKEN_KEY_TYPE},
|
||||
{make_lit_string("bool") , CPP_TOKEN_KEY_TYPE},
|
||||
{make_lit_string("char") , CPP_TOKEN_KEY_TYPE},
|
||||
{make_lit_string("int") , CPP_TOKEN_KEY_TYPE},
|
||||
{make_lit_string("float") , CPP_TOKEN_KEY_TYPE},
|
||||
{make_lit_string("double") , CPP_TOKEN_KEY_TYPE},
|
||||
{make_stafl("void" , CPP_TOKEN_KEY_TYPE)},
|
||||
{make_stafl("bool" , CPP_TOKEN_KEY_TYPE)},
|
||||
{make_stafl("char" , CPP_TOKEN_KEY_TYPE)},
|
||||
{make_stafl("int" , CPP_TOKEN_KEY_TYPE)},
|
||||
{make_stafl("float" , CPP_TOKEN_KEY_TYPE)},
|
||||
{make_stafl("double" , CPP_TOKEN_KEY_TYPE)},
|
||||
|
||||
{make_lit_string("long") , CPP_TOKEN_KEY_MODIFIER},
|
||||
{make_lit_string("short") , CPP_TOKEN_KEY_MODIFIER},
|
||||
{make_lit_string("unsigned") , CPP_TOKEN_KEY_MODIFIER},
|
||||
{make_stafl("long" , CPP_TOKEN_KEY_MODIFIER)},
|
||||
{make_stafl("short" , CPP_TOKEN_KEY_MODIFIER)},
|
||||
{make_stafl("unsigned" , CPP_TOKEN_KEY_MODIFIER)},
|
||||
|
||||
{make_lit_string("const") , CPP_TOKEN_KEY_QUALIFIER},
|
||||
{make_lit_string("volatile") , CPP_TOKEN_KEY_QUALIFIER},
|
||||
{make_stafl("const" , CPP_TOKEN_KEY_QUALIFIER)},
|
||||
{make_stafl("volatile" , CPP_TOKEN_KEY_QUALIFIER)},
|
||||
|
||||
{make_lit_string("asm") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("break") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("case") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("catch") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("continue") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("default") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("do") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("else") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("for") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("goto") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("if") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("return") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("switch") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("try") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("while") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_lit_string("static_assert") , CPP_TOKEN_KEY_CONTROL_FLOW},
|
||||
{make_stafl("asm" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("break" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("case" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("catch" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("continue" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("default" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("do" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("else" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("for" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("goto" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("if" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("return" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("switch" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("try" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("while" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
{make_stafl("static_assert" , CPP_TOKEN_KEY_CONTROL_FLOW)},
|
||||
|
||||
{make_lit_string("const_cast") , CPP_TOKEN_KEY_CAST},
|
||||
{make_lit_string("dynamic_cast") , CPP_TOKEN_KEY_CAST},
|
||||
{make_lit_string("reinterpret_cast") , CPP_TOKEN_KEY_CAST},
|
||||
{make_lit_string("static_cast") , CPP_TOKEN_KEY_CAST},
|
||||
{make_stafl("const_cast" , CPP_TOKEN_KEY_CAST)},
|
||||
{make_stafl("dynamic_cast" , CPP_TOKEN_KEY_CAST)},
|
||||
{make_stafl("reinterpret_cast" , CPP_TOKEN_KEY_CAST)},
|
||||
{make_stafl("static_cast" , CPP_TOKEN_KEY_CAST)},
|
||||
|
||||
{make_lit_string("class") , CPP_TOKEN_KEY_TYPE_DECLARATION},
|
||||
{make_lit_string("enum") , CPP_TOKEN_KEY_TYPE_DECLARATION},
|
||||
{make_lit_string("struct") , CPP_TOKEN_KEY_TYPE_DECLARATION},
|
||||
{make_lit_string("typedef") , CPP_TOKEN_KEY_TYPE_DECLARATION},
|
||||
{make_lit_string("union") , CPP_TOKEN_KEY_TYPE_DECLARATION},
|
||||
{make_lit_string("template") , CPP_TOKEN_KEY_TYPE_DECLARATION},
|
||||
{make_lit_string("typename") , CPP_TOKEN_KEY_TYPE_DECLARATION},
|
||||
{make_stafl("class" , CPP_TOKEN_KEY_TYPE_DECLARATION)},
|
||||
{make_stafl("enum" , CPP_TOKEN_KEY_TYPE_DECLARATION)},
|
||||
{make_stafl("struct" , CPP_TOKEN_KEY_TYPE_DECLARATION)},
|
||||
{make_stafl("typedef" , CPP_TOKEN_KEY_TYPE_DECLARATION)},
|
||||
{make_stafl("union" , CPP_TOKEN_KEY_TYPE_DECLARATION)},
|
||||
{make_stafl("template" , CPP_TOKEN_KEY_TYPE_DECLARATION)},
|
||||
{make_stafl("typename" , CPP_TOKEN_KEY_TYPE_DECLARATION)},
|
||||
|
||||
{make_lit_string("friend") , CPP_TOKEN_KEY_ACCESS},
|
||||
{make_lit_string("namespace") , CPP_TOKEN_KEY_ACCESS},
|
||||
{make_lit_string("private") , CPP_TOKEN_KEY_ACCESS},
|
||||
{make_lit_string("protected") , CPP_TOKEN_KEY_ACCESS},
|
||||
{make_lit_string("public") , CPP_TOKEN_KEY_ACCESS},
|
||||
{make_lit_string("using") , CPP_TOKEN_KEY_ACCESS},
|
||||
{make_stafl("friend" , CPP_TOKEN_KEY_ACCESS)},
|
||||
{make_stafl("namespace" , CPP_TOKEN_KEY_ACCESS)},
|
||||
{make_stafl("private" , CPP_TOKEN_KEY_ACCESS)},
|
||||
{make_stafl("protected" , CPP_TOKEN_KEY_ACCESS)},
|
||||
{make_stafl("public" , CPP_TOKEN_KEY_ACCESS)},
|
||||
{make_stafl("using" , CPP_TOKEN_KEY_ACCESS)},
|
||||
|
||||
{make_lit_string("extern") , CPP_TOKEN_KEY_LINKAGE},
|
||||
{make_lit_string("export") , CPP_TOKEN_KEY_LINKAGE},
|
||||
{make_lit_string("inline") , CPP_TOKEN_KEY_LINKAGE},
|
||||
{make_lit_string("static") , CPP_TOKEN_KEY_LINKAGE},
|
||||
{make_lit_string("virtual") , CPP_TOKEN_KEY_LINKAGE},
|
||||
{make_stafl("extern" , CPP_TOKEN_KEY_LINKAGE)},
|
||||
{make_stafl("export" , CPP_TOKEN_KEY_LINKAGE)},
|
||||
{make_stafl("inline" , CPP_TOKEN_KEY_LINKAGE)},
|
||||
{make_stafl("static" , CPP_TOKEN_KEY_LINKAGE)},
|
||||
{make_stafl("virtual" , CPP_TOKEN_KEY_LINKAGE)},
|
||||
|
||||
{make_lit_string("alignas") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_lit_string("explicit") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_lit_string("noexcept") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_lit_string("nullptr") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_lit_string("operator") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_lit_string("register") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_lit_string("this") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_lit_string("thread_local") , CPP_TOKEN_KEY_OTHER},
|
||||
{make_stafl("alignas" , CPP_TOKEN_KEY_OTHER)},
|
||||
{make_stafl("explicit" , CPP_TOKEN_KEY_OTHER)},
|
||||
{make_stafl("noexcept" , CPP_TOKEN_KEY_OTHER)},
|
||||
{make_stafl("nullptr" , CPP_TOKEN_KEY_OTHER)},
|
||||
{make_stafl("operator" , CPP_TOKEN_KEY_OTHER)},
|
||||
{make_stafl("register" , CPP_TOKEN_KEY_OTHER)},
|
||||
{make_stafl("this" , CPP_TOKEN_KEY_OTHER)},
|
||||
{make_stafl("thread_local" , CPP_TOKEN_KEY_OTHER)},
|
||||
|
||||
#if defined(FCPP_LEXER_EXTRA_KEYWORDS)
|
||||
FCPP_LEXER_EXTRA_KEYWORDS
|
||||
#endif
|
||||
};
|
||||
|
||||
static i32_4tech keywords_count = sizeof(keywords)/sizeof(keywords[0]);
|
||||
|
||||
API_EXPORT FCPP_LINK Cpp_Get_Token_Result
|
||||
cpp_get_token(Cpp_Token_Array array, int32_t pos)/*
|
||||
cpp_get_token(Cpp_Token_Array array, i32_4tech pos)/*
|
||||
DOC_PARAM(array, The array of tokens from which to get a token.)
|
||||
DOC_PARAM(pos, The position, measured in bytes, to get the token for.)
|
||||
DOC_RETURN(A Cpp_Get_Token_Result struct is returned containing the index of a token and a flag indicating whether the pos is contained in the token or in whitespace after the token.)
|
||||
|
@ -169,10 +203,10 @@ DOC_SEE(Cpp_Get_Token_Result)
|
|||
Cpp_Get_Token_Result result = {};
|
||||
Cpp_Token *token_array = array.tokens;
|
||||
Cpp_Token *token = 0;
|
||||
int32_t first = 0;
|
||||
int32_t count = array.count;
|
||||
int32_t last = count;
|
||||
int32_t this_start = 0, next_start = 0;
|
||||
i32_4tech first = 0;
|
||||
i32_4tech count = array.count;
|
||||
i32_4tech last = count;
|
||||
i32_4tech this_start = 0, next_start = 0;
|
||||
|
||||
if (count > 0){
|
||||
for (;;){
|
||||
|
@ -272,35 +306,57 @@ cpp_pp_directive_to_state(Cpp_Token_Type type){
|
|||
return(result);
|
||||
}
|
||||
|
||||
// duff-routine defines
|
||||
#define DrCase(PC) case PC: goto resumespot_##PC
|
||||
FCPP_LINK b32_4tech
|
||||
cpp__match(char *a, i32_4tech a_len, char *b, i32_4tech b_len){
|
||||
b32_4tech result = false;
|
||||
if (a_len == b_len){
|
||||
char *a_end = a + a_len;
|
||||
result = true;
|
||||
for (; a < a_end; ++a, ++b){
|
||||
if (*a != *b){
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define DrYield(PC, n)\
|
||||
{ token_array_out->count = token_i; *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
|
||||
|
||||
#define DrReturn(n) { token_array_out->count = token_i; *S_ptr = S; S_ptr->__pc__ = -1; return(n); }
|
||||
FCPP_LINK b32_4tech
|
||||
cpp__table_match(String_And_Flag *table, i32_4tech count, char *s, i32_4tech len, i32_4tech *index_out){
|
||||
b32_4tech result = false;
|
||||
String_And_Flag *entry = table;
|
||||
*index_out = -1;
|
||||
for (i32_4tech i = 0; i < count; ++i, ++entry){
|
||||
if (cpp__match(entry->str, entry->length, s, len)){
|
||||
result = true;
|
||||
*index_out = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
FCPP_LINK Cpp_Lex_Result
|
||||
cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size,
|
||||
Cpp_Token_Array *token_array_out){
|
||||
cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, i32_4tech size, Cpp_Token_Array *token_array_out){
|
||||
Cpp_Lex_Data S = *S_ptr;
|
||||
|
||||
Cpp_Token *out_tokens = token_array_out->tokens;
|
||||
int32_t token_i = token_array_out->count;
|
||||
int32_t max_token_i = token_array_out->max_count;
|
||||
i32_4tech token_i = token_array_out->count;
|
||||
i32_4tech max_token_i = token_array_out->max_count;
|
||||
|
||||
uint8_t c = 0;
|
||||
u8_4tech c = 0;
|
||||
|
||||
int32_t end_pos = size + S.chunk_pos;
|
||||
i32_4tech end_pos = size + S.chunk_pos;
|
||||
chunk -= S.chunk_pos;
|
||||
|
||||
switch (S.__pc__){
|
||||
DrCase(1);
|
||||
DrCase(2);
|
||||
DrCase(3);
|
||||
DrCase(4);
|
||||
DrCase(5);
|
||||
DrCase(7);
|
||||
DfrCase(1);
|
||||
DfrCase(2);
|
||||
DfrCase(3);
|
||||
DfrCase(4);
|
||||
DfrCase(5);
|
||||
DfrCase(7);
|
||||
}
|
||||
|
||||
for (;;){
|
||||
|
@ -308,14 +364,15 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
for(;;){
|
||||
for (; S.pp_state < LSPP_count && S.pos < end_pos;){
|
||||
c = chunk[S.pos++];
|
||||
int32_t i = S.pp_state + whitespace_fsm_eq_classes[c];
|
||||
i32_4tech i = S.pp_state + whitespace_fsm_eq_classes[c];
|
||||
S.pp_state = whitespace_fsm_table[i];
|
||||
}
|
||||
S.white_done = (S.pp_state >= LSPP_count);
|
||||
|
||||
if (S.white_done == 0){
|
||||
S.chunk_pos += size;
|
||||
DrYield(4, LexResult_NeedChunk);
|
||||
token_array_out->count = token_i;
|
||||
DfrYield(4, LexResult_NeedChunk);
|
||||
}
|
||||
else{
|
||||
break;
|
||||
|
@ -333,14 +390,14 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
S.fsm = null_lex_fsm;
|
||||
for(;;){
|
||||
{
|
||||
uint16_t *eq_classes = get_eq_classes[S.pp_state];
|
||||
uint8_t *fsm_table = get_table[S.pp_state];
|
||||
u16_4tech *eq_classes = get_eq_classes[S.pp_state];
|
||||
u8_4tech *fsm_table = get_table[S.pp_state];
|
||||
|
||||
for (; S.fsm.state < LS_count && S.pos < end_pos;){
|
||||
c = chunk[S.pos++];
|
||||
S.tb[(S.tb_pos++) & (sizeof(S.tb)-1)] = c;
|
||||
|
||||
int32_t i = S.fsm.state + eq_classes[c];
|
||||
i32_4tech i = S.fsm.state + eq_classes[c];
|
||||
S.fsm.state = fsm_table[i];
|
||||
S.fsm.multi_line |= multiline_state_table[S.fsm.state];
|
||||
}
|
||||
|
@ -349,7 +406,8 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
|
||||
if (S.fsm.emit_token == 0){
|
||||
S.chunk_pos += size;
|
||||
DrYield(3, LexResult_NeedChunk);
|
||||
token_array_out->count = token_i;
|
||||
DfrYield(3, LexResult_NeedChunk);
|
||||
}
|
||||
else{
|
||||
break;
|
||||
|
@ -406,7 +464,8 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
|
||||
if (S.white_done == 0){
|
||||
S.chunk_pos += size;
|
||||
DrYield(1, LexResult_NeedChunk);
|
||||
token_array_out->count = token_i;
|
||||
DfrYield(1, LexResult_NeedChunk);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
@ -431,20 +490,19 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
{
|
||||
--S.pos;
|
||||
|
||||
int32_t word_size = S.pos - S.token_start;
|
||||
i32_4tech word_size = S.pos - S.token_start;
|
||||
|
||||
if (word_size < sizeof(S.tb)){
|
||||
if (S.pp_state == LSPP_body_if){
|
||||
if (match_ss(make_string(S.tb, word_size), make_lit_string("defined"))){
|
||||
if (cpp__match(S.tb, word_size, "defined", sizeof("defined")-1)){
|
||||
S.token.type = CPP_PP_DEFINED;
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR | CPP_TFLAG_IS_KEYWORD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t sub_match = -1;
|
||||
string_set_match_table(keywords, sizeof(*keywords), ArrayCount(keywords),
|
||||
make_string(S.tb, S.tb_pos-1), &sub_match);
|
||||
i32_4tech sub_match = -1;
|
||||
cpp__table_match(keywords, keywords_count, S.tb, S.tb_pos-1, &sub_match);
|
||||
|
||||
if (sub_match != -1){
|
||||
String_And_Flag data = keywords[sub_match];
|
||||
|
@ -481,23 +539,22 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
--S.pos;
|
||||
|
||||
if (S.tb_pos < sizeof(S.tb)){
|
||||
int32_t pos = S.tb_pos-1;
|
||||
int32_t i = 1;
|
||||
i32_4tech pos = S.tb_pos-1;
|
||||
i32_4tech i = 1;
|
||||
for (;i < pos; ++i){
|
||||
if (S.tb[i] != ' '){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t sub_match = -1;
|
||||
string_set_match_table(preprops, sizeof(*preprops), ArrayCount(preprops),
|
||||
make_string(S.tb+i, pos-i), &sub_match);
|
||||
i32_4tech sub_match = -1;
|
||||
cpp__table_match(preprops, preprops_count, S.tb+i, pos-i, &sub_match);
|
||||
|
||||
if (sub_match != -1){
|
||||
String_And_Flag data = preprops[sub_match];
|
||||
S.token.type = (Cpp_Token_Type)data.flags;
|
||||
S.token.flags = CPP_TFLAG_PP_DIRECTIVE;
|
||||
S.pp_state = (uint8_t)cpp_pp_directive_to_state(S.token.type);
|
||||
S.pp_state = (u8_4tech)cpp_pp_directive_to_state(S.token.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +578,8 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
|
||||
if (S.fsm.emit_token == 0){
|
||||
S.chunk_pos += size;
|
||||
DrYield(5, LexResult_NeedChunk);
|
||||
token_array_out->count = token_i;
|
||||
DfrYield(5, LexResult_NeedChunk);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
@ -863,16 +921,20 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
S.token.size = S.pos - S.token_start;
|
||||
}
|
||||
if ((S.token.flags & CPP_TFLAG_PP_DIRECTIVE) == 0){
|
||||
S.token.flags |= (S.pp_state != LSPP_default)?(CPP_TFLAG_PP_BODY):(0);
|
||||
if (S.pp_state != LSPP_default){
|
||||
S.token.flags |= CPP_TFLAG_PP_BODY;
|
||||
}
|
||||
}
|
||||
|
||||
out_tokens[token_i++] = S.token;
|
||||
if (token_i == max_token_i){
|
||||
if (S.pos == end_pos){
|
||||
S.chunk_pos += size;
|
||||
DrYield(7, LexResult_NeedChunk);
|
||||
token_array_out->count = token_i;
|
||||
DfrYield(7, LexResult_NeedChunk);
|
||||
}
|
||||
DrYield(2, LexResult_NeedTokenMemory);
|
||||
token_array_out->count = token_i;
|
||||
DfrYield(2, LexResult_NeedTokenMemory);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -881,16 +943,13 @@ cpp_lex_nonalloc_null_end_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
}
|
||||
}
|
||||
|
||||
DrReturn(LexResult_Finished);
|
||||
token_array_out->count = token_i;
|
||||
DfrReturn(LexResult_Finished);
|
||||
}
|
||||
|
||||
#undef DrYield
|
||||
#undef DrReturn
|
||||
#undef DrCase
|
||||
|
||||
FCPP_LINK Cpp_Lex_Result
|
||||
cpp_lex_nonalloc_null_end_out_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size,
|
||||
Cpp_Token_Array *token_array_out, int32_t max_tokens_out){
|
||||
cpp_lex_nonalloc_null_end_out_limit(Cpp_Lex_Data *S_ptr, char *chunk, i32_4tech size,
|
||||
Cpp_Token_Array *token_array_out, i32_4tech max_tokens_out){
|
||||
Cpp_Token_Array temp_array = *token_array_out;
|
||||
if (temp_array.max_count > temp_array.count + max_tokens_out){
|
||||
temp_array.max_count = temp_array.count + max_tokens_out;
|
||||
|
@ -909,7 +968,7 @@ cpp_lex_nonalloc_null_end_out_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t si
|
|||
}
|
||||
|
||||
FCPP_LINK Cpp_Lex_Result
|
||||
cpp_lex_nonalloc_no_null_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size, int32_t full_size,
|
||||
cpp_lex_nonalloc_no_null_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, i32_4tech size, i32_4tech full_size,
|
||||
Cpp_Token_Array *token_array_out){
|
||||
Cpp_Lex_Result result = 0;
|
||||
if (S_ptr->pos >= full_size){
|
||||
|
@ -929,8 +988,8 @@ cpp_lex_nonalloc_no_null_no_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t size
|
|||
}
|
||||
|
||||
FCPP_LINK Cpp_Lex_Result
|
||||
cpp_lex_nonalloc_no_null_out_limit(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_nonalloc_no_null_out_limit(Cpp_Lex_Data *S_ptr, char *chunk, i32_4tech size, i32_4tech full_size,
|
||||
Cpp_Token_Array *token_array_out, i32_4tech max_tokens_out){
|
||||
Cpp_Token_Array temp_stack = *token_array_out;
|
||||
if (temp_stack.max_count > temp_stack.count + max_tokens_out){
|
||||
temp_stack.max_count = temp_stack.count + max_tokens_out;
|
||||
|
@ -950,11 +1009,11 @@ cpp_lex_nonalloc_no_null_out_limit(Cpp_Lex_Data *S_ptr, char *chunk, int32_t siz
|
|||
return(result);
|
||||
}
|
||||
|
||||
#define HAS_NULL_TERM ((int32_t)(-1))
|
||||
#define NO_OUT_LIMIT ((int32_t)(-1))
|
||||
#define HAS_NULL_TERM ((i32_4tech)(-1))
|
||||
#define NO_OUT_LIMIT ((i32_4tech)(-1))
|
||||
|
||||
API_EXPORT 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, i32_4tech size, i32_4tech full_size, Cpp_Token_Array *token_array_out, i32_4tech 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.)
|
||||
|
@ -1031,7 +1090,7 @@ as the file being lexed.)
|
|||
return(data);
|
||||
}
|
||||
|
||||
API_EXPORT FCPP_LINK int32_t
|
||||
API_EXPORT FCPP_LINK i32_4tech
|
||||
cpp_lex_data_temp_size(Cpp_Lex_Data *lex_data)/*
|
||||
DOC_PARAM(lex_data, The lex state from which to get the temporary buffer size.)
|
||||
DOC(This call gets the current size of the temporary buffer in the lexer state so
|
||||
|
@ -1039,7 +1098,7 @@ that you can move to a new temporary buffer by copying the data over.)
|
|||
DOC_SEE(cpp_lex_data_temp_read)
|
||||
DOC_SEE(cpp_lex_data_new_temp)
|
||||
*/{
|
||||
int32_t result = lex_data->tb_pos;
|
||||
i32_4tech result = lex_data->tb_pos;
|
||||
Assert(lex_data->tb != 0);
|
||||
return(result);
|
||||
}
|
||||
|
@ -1053,7 +1112,7 @@ DOC(This call reads the current contents of the temporary buffer.)
|
|||
DOC_SEE(cpp_lex_data_temp_size)
|
||||
DOC_SEE(cpp_lex_data_new_temp)
|
||||
*/{
|
||||
int32_t size = lex_data->tb_pos;
|
||||
i32_4tech size = lex_data->tb_pos;
|
||||
char *src = lex_data->tb;
|
||||
char *end = src + size;
|
||||
for (; src < end; ++src, ++out_buffer){
|
||||
|
@ -1066,21 +1125,21 @@ cpp_lex_data_new_temp_DEP(Cpp_Lex_Data *lex_data, char *new_buffer)
|
|||
/*DOC(Deprecated in 4cpp Lexer 1.0.1*/{}
|
||||
|
||||
FCPP_LINK char
|
||||
cpp_token_get_pp_state(uint16_t bitfield){
|
||||
cpp_token_get_pp_state(u16_4tech bitfield){
|
||||
return (char)(bitfield);
|
||||
}
|
||||
|
||||
FCPP_LINK void
|
||||
cpp_shift_token_starts(Cpp_Token_Array *array, int32_t from_token_i, int32_t shift_amount){
|
||||
cpp_shift_token_starts(Cpp_Token_Array *array, i32_4tech from_token_i, i32_4tech shift_amount){
|
||||
Cpp_Token *token = array->tokens + from_token_i;
|
||||
int32_t count = array->count, i = 0;
|
||||
i32_4tech count = array->count, i = 0;
|
||||
for (i = from_token_i; i < count; ++i, ++token){
|
||||
token->start += shift_amount;
|
||||
}
|
||||
}
|
||||
|
||||
FCPP_LINK Cpp_Token
|
||||
cpp_index_array(Cpp_Token_Array *array, int32_t file_size, int32_t index){
|
||||
cpp_index_array(Cpp_Token_Array *array, i32_4tech file_size, i32_4tech index){
|
||||
Cpp_Token result;
|
||||
if (index < array->count){
|
||||
result = array->tokens[index];
|
||||
|
@ -1096,7 +1155,7 @@ cpp_index_array(Cpp_Token_Array *array, int32_t file_size, int32_t index){
|
|||
}
|
||||
|
||||
API_EXPORT FCPP_LINK Cpp_Relex_Range
|
||||
cpp_get_relex_range(Cpp_Token_Array *array, int32_t start_pos, int32_t end_pos)
|
||||
cpp_get_relex_range(Cpp_Token_Array *array, i32_4tech start_pos, i32_4tech end_pos)
|
||||
/*
|
||||
DOC_PARAM(array, A pointer to the token array that will be modified by the relex,
|
||||
this array should already contain the tokens for the previous state of the file.)
|
||||
|
@ -1129,7 +1188,7 @@ The start and end points are based on the edited region of the file before the e
|
|||
}
|
||||
|
||||
API_EXPORT FCPP_LINK Cpp_Relex_Data
|
||||
cpp_relex_init(Cpp_Token_Array *array, int32_t start_pos, int32_t end_pos, int32_t character_shift_amount)
|
||||
cpp_relex_init(Cpp_Token_Array *array, i32_4tech start_pos, i32_4tech end_pos, i32_4tech character_shift_amount)
|
||||
/*
|
||||
DOC_PARAM(array, A pointer to the token array that will be modified by the relex,
|
||||
this array should already contain the tokens for the previous state of the file.)
|
||||
|
@ -1172,7 +1231,7 @@ DOC_SEE(cpp_relex_is_start_chunk)
|
|||
return(state);
|
||||
}
|
||||
|
||||
API_EXPORT FCPP_LINK int32_t
|
||||
API_EXPORT FCPP_LINK i32_4tech
|
||||
cpp_relex_start_position(Cpp_Relex_Data *S_ptr)
|
||||
/*
|
||||
DOC_PARAM(S_ptr, A pointer to a state that is done with the first stage of initialization (cpp_relex_init))
|
||||
|
@ -1187,12 +1246,12 @@ DOC_SEE(cpp_relex_init)
|
|||
DOC_SEE(cpp_relex_declare_first_chunk_position)
|
||||
|
||||
*/{
|
||||
int32_t result = S_ptr->relex_start_position;
|
||||
i32_4tech result = S_ptr->relex_start_position;
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT FCPP_LINK void
|
||||
cpp_relex_declare_first_chunk_position(Cpp_Relex_Data *S_ptr, int32_t position)
|
||||
cpp_relex_declare_first_chunk_position(Cpp_Relex_Data *S_ptr, i32_4tech position)
|
||||
/*
|
||||
DOC_PARAM(S_ptr, A pointer to a state that is done with the first stage of initialization (cpp_relex_init))
|
||||
DOC_PARAM(position, The start position of the first chunk that will be fed to the relex process.)
|
||||
|
@ -1210,8 +1269,8 @@ DOC_SEE(cpp_relex_start_position)
|
|||
S_ptr->lex.chunk_pos = position;
|
||||
}
|
||||
|
||||
API_EXPORT FCPP_LINK int32_t
|
||||
cpp_relex_is_start_chunk(Cpp_Relex_Data *S_ptr, char *chunk, int32_t chunk_size)
|
||||
API_EXPORT FCPP_LINK i32_4tech
|
||||
cpp_relex_is_start_chunk(Cpp_Relex_Data *S_ptr, char *chunk, i32_4tech chunk_size)
|
||||
/*
|
||||
DOC_PARAM(S_ptr, A pointer to a state that is done with the first stage of initialization (cpp_relex_init))
|
||||
DOC_PARAM(chunk, The chunk to check.)
|
||||
|
@ -1228,11 +1287,11 @@ in the one and only call to cpp_relex_step.)
|
|||
|
||||
DOC_SEE(cpp_relex_init)
|
||||
*/{
|
||||
int32_t pos = S_ptr->relex_start_position;
|
||||
int32_t start = S_ptr->lex.chunk_pos;
|
||||
int32_t end = start + chunk_size;
|
||||
i32_4tech pos = S_ptr->relex_start_position;
|
||||
i32_4tech start = S_ptr->lex.chunk_pos;
|
||||
i32_4tech end = start + chunk_size;
|
||||
|
||||
int32_t good_chunk = 0;
|
||||
i32_4tech good_chunk = 0;
|
||||
if (start <= pos && pos < end){
|
||||
good_chunk = 1;
|
||||
}
|
||||
|
@ -1249,19 +1308,8 @@ DOC_SEE(cpp_relex_init)
|
|||
return(good_chunk);
|
||||
}
|
||||
|
||||
// duff-routine defines
|
||||
#define DrCase(PC) case PC: goto resumespot_##PC
|
||||
|
||||
#define DrYield(PC, n) { \
|
||||
S_ptr->result_state = n; \
|
||||
*S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
|
||||
|
||||
#define DrReturn(n) { \
|
||||
S_ptr->result_state = n; \
|
||||
*S_ptr = S; S_ptr->__pc__ = -1; return(n); }
|
||||
|
||||
API_EXPORT FCPP_LINK Cpp_Lex_Result
|
||||
cpp_relex_step(Cpp_Relex_Data *S_ptr, char *chunk, int32_t chunk_size, int32_t full_size,
|
||||
cpp_relex_step(Cpp_Relex_Data *S_ptr, char *chunk, i32_4tech chunk_size, i32_4tech full_size,
|
||||
Cpp_Token_Array *array, Cpp_Token_Array *relex_array)
|
||||
/*
|
||||
DOC_PARAM(S_ptr, A pointer to a fully initiazed relex state.)
|
||||
|
@ -1316,8 +1364,8 @@ DOC_SEE(cpp_relex_abort)
|
|||
Cpp_Lex_Result step_result = LexResult_Finished;
|
||||
|
||||
switch (S.__pc__){
|
||||
DrCase(1);
|
||||
DrCase(2);
|
||||
DfrCase(1);
|
||||
DfrCase(2);
|
||||
}
|
||||
|
||||
cpp_shift_token_starts(array, S.end_token_index, S.character_shift_amount);
|
||||
|
@ -1325,9 +1373,7 @@ DOC_SEE(cpp_relex_abort)
|
|||
|
||||
// TODO(allen): This can be better I suspect.
|
||||
for (;;){
|
||||
step_result =
|
||||
cpp_lex_nonalloc_no_null_out_limit(&S.lex, chunk, chunk_size, full_size,
|
||||
relex_array, 1);
|
||||
step_result = cpp_lex_nonalloc_no_null_out_limit(&S.lex, chunk, chunk_size, full_size, relex_array, 1);
|
||||
|
||||
switch (step_result){
|
||||
case LexResult_HitTokenLimit:
|
||||
|
@ -1349,24 +1395,29 @@ DOC_SEE(cpp_relex_abort)
|
|||
}
|
||||
break;
|
||||
|
||||
case LexResult_NeedChunk: DrYield(1, LexResult_NeedChunk); break;
|
||||
case LexResult_NeedChunk:
|
||||
{
|
||||
S_ptr->result_state = LexResult_NeedChunk;
|
||||
DfrYield(1, LexResult_NeedChunk);
|
||||
}break;
|
||||
|
||||
case LexResult_NeedTokenMemory: DrYield(2, LexResult_NeedTokenMemory); break;
|
||||
case LexResult_NeedTokenMemory:
|
||||
{
|
||||
S_ptr->result_state = LexResult_NeedTokenMemory;
|
||||
DfrYield(2, LexResult_NeedTokenMemory);
|
||||
}break;
|
||||
|
||||
case LexResult_Finished: goto double_break;
|
||||
}
|
||||
}
|
||||
|
||||
double_break:;
|
||||
DrReturn(LexResult_Finished);
|
||||
S_ptr->result_state = LexResult_Finished;
|
||||
DfrReturn(LexResult_Finished);
|
||||
}
|
||||
|
||||
#undef DrYield
|
||||
#undef DrReturn
|
||||
#undef DrCase
|
||||
|
||||
API_EXPORT FCPP_LINK int32_t
|
||||
cpp_relex_get_new_count(Cpp_Relex_Data *S_ptr, int32_t current_count, Cpp_Token_Array *relex_array)
|
||||
API_EXPORT FCPP_LINK i32_4tech
|
||||
cpp_relex_get_new_count(Cpp_Relex_Data *S_ptr, i32_4tech current_count, Cpp_Token_Array *relex_array)
|
||||
/*
|
||||
DOC_PARAM(S_ptr, A pointer to a state that has gone through cpp_relex_step with a LexResult_Finished return.)
|
||||
DOC_PARAM(current_count, The count of tokens in the original array before the edit.)
|
||||
|
@ -1376,11 +1427,11 @@ DOC(After getting a LexResult_Finished from cpp_relex_step, this call can be use
|
|||
the size the new array will have. If the original array doesn't have enough capacity to store
|
||||
the new array, it's capacity should be increased before passing to cpp_relex_complete.)
|
||||
*/{
|
||||
int32_t result = -1;
|
||||
i32_4tech result = -1;
|
||||
|
||||
if (S_ptr->result_state == LexResult_Finished){
|
||||
int32_t delete_amount = S_ptr->end_token_index - S_ptr->start_token_index;
|
||||
int32_t shift_amount = relex_array->count - delete_amount;
|
||||
i32_4tech delete_amount = S_ptr->end_token_index - S_ptr->start_token_index;
|
||||
i32_4tech shift_amount = relex_array->count - delete_amount;
|
||||
result = current_count + shift_amount;
|
||||
}
|
||||
|
||||
|
@ -1392,12 +1443,12 @@ the new array, it's capacity should be increased before passing to cpp_relex_com
|
|||
#endif
|
||||
|
||||
FCPP_LINK void
|
||||
cpp__block_move(void *dst, void *src, int32_t size){
|
||||
cpp__block_move(void *dst, void *src, i32_4tech size){
|
||||
#if !defined(FCPP_FORBID_MEMCPY)
|
||||
memmove(dst, src, size);
|
||||
#else
|
||||
// TODO(allen): find a way to write a fast one of these.
|
||||
uint8_t *d = (uint8_t*)dst, *s = (uint8_t*)src;
|
||||
u8_4tech *d = (u8_4tech*)dst, *s = (u8_4tech*)src;
|
||||
if (d < s || d >= s + size){
|
||||
for (; size > 0; --size){
|
||||
*(d++) = *(s++);
|
||||
|
@ -1424,11 +1475,11 @@ DOC(After getting a LexResult_Finished from cpp_relex_step, and ensuring that
|
|||
array has a large enough capacity by calling cpp_relex_get_new_count, this call
|
||||
does the necessary replacement of tokens in the array to make it match the new file.)
|
||||
*/{
|
||||
int32_t delete_amount = S_ptr->end_token_index - S_ptr->start_token_index;
|
||||
int32_t shift_amount = relex_array->count - delete_amount;
|
||||
i32_4tech delete_amount = S_ptr->end_token_index - S_ptr->start_token_index;
|
||||
i32_4tech shift_amount = relex_array->count - delete_amount;
|
||||
|
||||
if (shift_amount != 0){
|
||||
int32_t shift_size = array->count - S_ptr->end_token_index;
|
||||
i32_4tech shift_size = array->count - S_ptr->end_token_index;
|
||||
if (shift_size > 0){
|
||||
Cpp_Token *old_base = array->tokens + S_ptr->end_token_index;
|
||||
cpp__block_move(old_base + shift_amount, old_base, sizeof(Cpp_Token)*shift_size);
|
||||
|
@ -1461,7 +1512,7 @@ is dead.)
|
|||
#include <string.h>
|
||||
|
||||
API_EXPORT FCPP_LINK Cpp_Token_Array
|
||||
cpp_make_token_array(int32_t starting_max)/*
|
||||
cpp_make_token_array(i32_4tech starting_max)/*
|
||||
DOC_PARAM(starting_max, The number of tokens to initialize the array with.)
|
||||
DOC_RETURN(An empty Cpp_Token_Array with memory malloc'd for storing tokens.)
|
||||
DOC(This call allocates a Cpp_Token_Array with malloc for use in other
|
||||
|
@ -1485,7 +1536,7 @@ DOC_SEE(cpp_make_token_array)
|
|||
}
|
||||
|
||||
API_EXPORT FCPP_LINK void
|
||||
cpp_resize_token_array(Cpp_Token_Array *token_array, int32_t new_max)/*
|
||||
cpp_resize_token_array(Cpp_Token_Array *token_array, i32_4tech new_max)/*
|
||||
DOC_PARAM(token_array, An array previously allocated by cpp_make_token_array.)
|
||||
DOC_PARAM(new_max, The new maximum size the array should support. If this is not greater
|
||||
than the current size of the array the operation is ignored.)
|
||||
|
@ -1506,7 +1557,7 @@ DOC_SEE(cpp_make_token_array)
|
|||
}
|
||||
|
||||
API_EXPORT FCPP_LINK void
|
||||
cpp_lex_file(char *data, int32_t size, Cpp_Token_Array *token_array_out)/*
|
||||
cpp_lex_file(char *data, i32_4tech size, Cpp_Token_Array *token_array_out)/*
|
||||
DOC_PARAM(data, The file data to be lexed in a single contiguous block.)
|
||||
DOC_PARAM(size, The number of bytes in data.)
|
||||
DOC_PARAM(token_array_out, The token array where the output tokens will be pushed.
|
||||
|
@ -1531,13 +1582,13 @@ return(array);
|
|||
DOC_SEE(cpp_make_token_array)
|
||||
*/{
|
||||
Cpp_Lex_Data S = cpp_lex_data_init();
|
||||
int32_t quit = 0;
|
||||
i32_4tech quit = 0;
|
||||
|
||||
char empty = 0;
|
||||
|
||||
token_array_out->count = 0;
|
||||
for (;!quit;){
|
||||
int32_t result = cpp_lex_step(&S, data, size, HAS_NULL_TERM, token_array_out, NO_OUT_LIMIT);
|
||||
i32_4tech result = cpp_lex_step(&S, data, size, HAS_NULL_TERM, token_array_out, NO_OUT_LIMIT);
|
||||
switch (result){
|
||||
case LexResult_Finished:
|
||||
{
|
||||
|
@ -1560,7 +1611,7 @@ DOC_SEE(cpp_make_token_array)
|
|||
// NOTE(allen): We told the system to use all of the output memory
|
||||
// but we ran out anyway, so allocate more memory. We hereby assume
|
||||
// the stack was allocated using cpp_make_token_array.
|
||||
int32_t new_max = 2*token_array_out->max_count + 1;
|
||||
i32_4tech new_max = 2*token_array_out->max_count + 1;
|
||||
cpp_resize_token_array(token_array_out, new_max);
|
||||
}break;
|
||||
}
|
||||
|
@ -1569,6 +1620,12 @@ DOC_SEE(cpp_make_token_array)
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
#undef DfrYield
|
||||
#undef DfrReturn
|
||||
#undef DfrCase
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
247
4ed.cpp
247
4ed.cpp
|
@ -304,22 +304,6 @@ COMMAND_DECL(redo){
|
|||
Assert(file->state.undo.undo.size >= 0);
|
||||
}
|
||||
|
||||
COMMAND_DECL(history_backward){
|
||||
USE_MODELS(models);
|
||||
REQ_OPEN_VIEW(view);
|
||||
REQ_FILE_HISTORY(file, view);
|
||||
|
||||
view_history_step(system, models, view, hist_backward);
|
||||
}
|
||||
|
||||
COMMAND_DECL(history_forward){
|
||||
USE_MODELS(models);
|
||||
REQ_OPEN_VIEW(view);
|
||||
REQ_FILE_HISTORY(file, view);
|
||||
|
||||
view_history_step(system, models, view, hist_backward);
|
||||
}
|
||||
|
||||
COMMAND_DECL(interactive_new){
|
||||
USE_VIEW(view);
|
||||
|
||||
|
@ -466,7 +450,6 @@ COMMAND_DECL(toggle_line_wrap){
|
|||
|
||||
Assert(view->edit_pos);
|
||||
|
||||
// TODO(allen): WHAT TO DO HERE???
|
||||
Relative_Scrolling scrolling = view_get_relative_scrolling(view);
|
||||
if (file->settings.unwrapped_lines){
|
||||
file->settings.unwrapped_lines = 0;
|
||||
|
@ -495,7 +478,9 @@ COMMAND_DECL(toggle_tokens){
|
|||
|
||||
internal void
|
||||
case_change_range(System_Functions *system, Mem_Options *mem, View *view, Editing_File *file, u8 a, u8 z, u8 char_delta){
|
||||
Range range = make_range(view->edit_pos->cursor.pos, view->edit_pos->mark);
|
||||
Range range = {0};
|
||||
range.min = Min(view->edit_pos->cursor.pos, view->edit_pos->mark);
|
||||
range.max = Max(view->edit_pos->cursor.pos, view->edit_pos->mark);
|
||||
if (range.start < range.end){
|
||||
Edit_Step step = {};
|
||||
step.type = ED_NORMAL;
|
||||
|
@ -522,175 +507,6 @@ case_change_range(System_Functions *system, Mem_Options *mem, View *view, Editin
|
|||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(open_panel_vsplit){
|
||||
USE_VARS(vars);
|
||||
USE_MODELS(models);
|
||||
USE_PANEL(panel);
|
||||
|
||||
if (models->layout.panel_count < models->layout.panel_max_count){
|
||||
Split_Result split = layout_split_panel(&models->layout, panel, 1);
|
||||
|
||||
Panel *panel1 = panel;
|
||||
Panel *panel2 = split.panel;
|
||||
|
||||
panel2->screen_region = panel1->screen_region;
|
||||
|
||||
i32 x_pos = ROUND32(lerp((f32)panel1->full.x0,
|
||||
split.divider->pos,
|
||||
(f32)panel1->full.x1)
|
||||
);
|
||||
|
||||
panel2->full.x0 = x_pos;
|
||||
panel2->full.x1 = panel1->full.x1;
|
||||
panel1->full.x1 = x_pos;
|
||||
|
||||
panel_fix_internal_area(panel1);
|
||||
panel_fix_internal_area(panel2);
|
||||
panel2->prev_inner = panel2->inner;
|
||||
|
||||
models->layout.active_panel = (i32)(panel2 - models->layout.panels);
|
||||
panel_make_empty(system, vars, panel2);
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(open_panel_hsplit){
|
||||
USE_VARS(vars);
|
||||
USE_MODELS(models);
|
||||
USE_PANEL(panel);
|
||||
|
||||
if (models->layout.panel_count < models->layout.panel_max_count){
|
||||
Split_Result split = layout_split_panel(&models->layout, panel, 0);
|
||||
|
||||
Panel *panel1 = panel;
|
||||
Panel *panel2 = split.panel;
|
||||
|
||||
panel2->screen_region = panel1->screen_region;
|
||||
|
||||
i32 y_pos = ROUND32(lerp((f32)panel1->full.y0,
|
||||
split.divider->pos,
|
||||
(f32)panel1->full.y1)
|
||||
);
|
||||
|
||||
panel2->full.y0 = y_pos;
|
||||
panel2->full.y1 = panel1->full.y1;
|
||||
panel1->full.y1 = y_pos;
|
||||
|
||||
panel_fix_internal_area(panel1);
|
||||
panel_fix_internal_area(panel2);
|
||||
panel2->prev_inner = panel2->inner;
|
||||
|
||||
models->layout.active_panel = (i32)(panel2 - models->layout.panels);
|
||||
panel_make_empty(system, vars, panel2);
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(close_panel){
|
||||
USE_MODELS(models);
|
||||
USE_PANEL(panel);
|
||||
USE_VIEW(view);
|
||||
|
||||
Panel *panel_ptr, *used_panels;
|
||||
Divider_And_ID div, parent_div, child_div;
|
||||
i32 child;
|
||||
i32 parent;
|
||||
i32 which_child;
|
||||
i32 active;
|
||||
|
||||
if (models->layout.panel_count > 1){
|
||||
live_set_free_view(command->live_set, view);
|
||||
panel->view = 0;
|
||||
|
||||
div = layout_get_divider(&models->layout, panel->parent);
|
||||
|
||||
// This divider cannot have two child dividers.
|
||||
Assert(div.divider->child1 == -1 || div.divider->child2 == -1);
|
||||
|
||||
// Get the child who needs to fill in this node's spot
|
||||
child = div.divider->child1;
|
||||
if (child == -1) child = div.divider->child2;
|
||||
|
||||
parent = div.divider->parent;
|
||||
which_child = div.divider->which_child;
|
||||
|
||||
// Fill the child in the slot this node use to hold
|
||||
if (parent == -1){
|
||||
Assert(models->layout.root == div.id);
|
||||
models->layout.root = child;
|
||||
}
|
||||
else{
|
||||
parent_div = layout_get_divider(&models->layout, parent);
|
||||
if (which_child == -1){
|
||||
parent_div.divider->child1 = child;
|
||||
}
|
||||
else{
|
||||
parent_div.divider->child2 = child;
|
||||
}
|
||||
}
|
||||
|
||||
// If there was a child divider, give it information about it's new parent.
|
||||
if (child != -1){
|
||||
child_div = layout_get_divider(&models->layout, child);
|
||||
child_div.divider->parent = parent;
|
||||
child_div.divider->which_child = div.divider->which_child;
|
||||
}
|
||||
|
||||
// What is the new active panel?
|
||||
active = -1;
|
||||
if (child == -1){
|
||||
used_panels = &models->layout.used_sentinel;
|
||||
for (dll_items(panel_ptr, used_panels)){
|
||||
if (panel_ptr != panel && panel_ptr->parent == div.id){
|
||||
panel_ptr->parent = parent;
|
||||
panel_ptr->which_child = which_child;
|
||||
active = (i32)(panel_ptr - models->layout.panels);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
panel_ptr = panel->next;
|
||||
if (panel_ptr == &models->layout.used_sentinel){
|
||||
panel_ptr = panel_ptr->next;
|
||||
}
|
||||
Assert(panel_ptr != panel);
|
||||
active = (i32)(panel_ptr - models->layout.panels);
|
||||
}
|
||||
|
||||
Assert(active != -1 && panel != models->layout.panels + active);
|
||||
models->layout.active_panel = active;
|
||||
|
||||
layout_free_divider(&models->layout, div.divider);
|
||||
layout_free_panel(&models->layout, panel);
|
||||
layout_fix_all_panels(&models->layout);
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(page_down){
|
||||
REQ_READABLE_VIEW(view);
|
||||
|
||||
Assert(view->edit_pos);
|
||||
|
||||
i32 height = CEIL32(view_file_height(view));
|
||||
f32 y = view_get_cursor_y(view);
|
||||
f32 x = view->edit_pos->preferred_x;
|
||||
|
||||
Full_Cursor cursor = view_compute_cursor_from_xy(view, x, y+height);
|
||||
view_set_cursor(view, cursor, false, view->file_data.file->settings.unwrapped_lines);
|
||||
}
|
||||
|
||||
COMMAND_DECL(page_up){
|
||||
REQ_READABLE_VIEW(view);
|
||||
|
||||
Assert(view->edit_pos);
|
||||
|
||||
i32 height = CEIL32(view_file_height(view));
|
||||
f32 y = view_get_cursor_y(view);
|
||||
f32 x = view->edit_pos->preferred_x;
|
||||
|
||||
Full_Cursor cursor = view_compute_cursor_from_xy(view, x, y-height);
|
||||
view_set_cursor(view, cursor, false, view->file_data.file->settings.unwrapped_lines);
|
||||
}
|
||||
|
||||
COMMAND_DECL(open_color_tweaker){
|
||||
USE_VIEW(view);
|
||||
view_show_theme(view);
|
||||
|
@ -717,7 +533,7 @@ COMMAND_DECL(user_callback){
|
|||
if (binding.custom) binding.custom(&models->app_links);
|
||||
}
|
||||
|
||||
globalvar Command_Function command_table[cmdid_count];
|
||||
global Command_Function command_table[cmdid_count];
|
||||
|
||||
#include "4ed_api_implementation.cpp"
|
||||
|
||||
|
@ -749,13 +565,6 @@ command_caller(Coroutine *coroutine){
|
|||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
view_caller(Coroutine *coroutine){
|
||||
View *view = (View*)coroutine->in;
|
||||
View_Persistent *persistent = &view->persistent;
|
||||
persistent->view_routine(&persistent->models->app_links, persistent->id);
|
||||
}
|
||||
|
||||
internal void
|
||||
app_links_init(System_Functions *system, Application_Links *app_links, void *data, i32 size){
|
||||
app_links->memory = data;
|
||||
|
@ -805,8 +614,6 @@ setup_command_table(){
|
|||
|
||||
SET(undo);
|
||||
SET(redo);
|
||||
SET(history_backward);
|
||||
SET(history_forward);
|
||||
|
||||
SET(interactive_new);
|
||||
SET(interactive_open);
|
||||
|
@ -1429,16 +1236,10 @@ App_Init_Sig(app_init){
|
|||
persistent = &view->persistent;
|
||||
persistent->id = i;
|
||||
persistent->models = models;
|
||||
persistent->view_routine = models->config_api.view_routine;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Command_Map *global = 0;
|
||||
i32 wanted_size = 0;
|
||||
b32 did_top = 0;
|
||||
b32 did_file = 0;
|
||||
|
||||
models->scroll_rule = fallback_scroll_rule;
|
||||
models->hook_open_file = 0;
|
||||
models->hook_new_file = 0;
|
||||
|
@ -1446,11 +1247,13 @@ App_Init_Sig(app_init){
|
|||
|
||||
setup_command_table();
|
||||
|
||||
global = &models->map_top;
|
||||
Command_Map *global_map = &models->map_top;
|
||||
Assert(models->config_api.get_bindings != 0);
|
||||
|
||||
wanted_size = models->config_api.get_bindings(models->app_links.memory, models->app_links.memory_size);
|
||||
i32 wanted_size = models->config_api.get_bindings(models->app_links.memory, models->app_links.memory_size);
|
||||
|
||||
b32 did_top = false;
|
||||
b32 did_file = false;
|
||||
if (wanted_size <= models->app_links.memory_size){
|
||||
Command_Map *map_ptr = 0;
|
||||
Binding_Unit *unit, *end;
|
||||
|
@ -1497,21 +1300,23 @@ App_Init_Sig(app_init){
|
|||
i32 table_max = count * 3 / 2;
|
||||
if (mapid == mapid_global){
|
||||
map_ptr = &models->map_top;
|
||||
map_init(map_ptr, &models->mem.part, table_max, global);
|
||||
did_top = 1;
|
||||
map_init(map_ptr, &models->mem.part, table_max, global_map);
|
||||
did_top = true;
|
||||
}
|
||||
else if (mapid == mapid_file){
|
||||
map_ptr = &models->map_file;
|
||||
map_init(map_ptr, &models->mem.part, table_max, global);
|
||||
did_file = 1;
|
||||
map_init(map_ptr, &models->mem.part, table_max, global_map);
|
||||
did_file = true;
|
||||
}
|
||||
else if (mapid < mapid_global){
|
||||
i32 index = get_or_add_map_index(models, mapid);
|
||||
Assert(index < user_map_count);
|
||||
map_ptr = models->user_maps + index;
|
||||
map_init(map_ptr, &models->mem.part, table_max, global);
|
||||
map_init(map_ptr, &models->mem.part, table_max, global_map);
|
||||
}
|
||||
else{
|
||||
map_ptr = 0;
|
||||
}
|
||||
else map_ptr = 0;
|
||||
|
||||
if (map_ptr && unit->map_begin.replace){
|
||||
map_clear(map_ptr);
|
||||
|
@ -1574,27 +1379,27 @@ App_Init_Sig(app_init){
|
|||
}
|
||||
else{
|
||||
switch (hook_id){
|
||||
case _hook_open_file:
|
||||
case special_hook_open_file:
|
||||
models->hook_open_file = (Open_File_Hook_Function*)unit->hook.func;
|
||||
break;
|
||||
|
||||
case _hook_new_file:
|
||||
case special_hook_new_file:
|
||||
models->hook_new_file = (Open_File_Hook_Function*)unit->hook.func;
|
||||
break;
|
||||
|
||||
case _hook_save_file:
|
||||
case special_hook_save_file:
|
||||
models->hook_save_file = (Open_File_Hook_Function*)unit->hook.func;
|
||||
break;
|
||||
|
||||
case _hook_command_caller:
|
||||
case special_hook_command_caller:
|
||||
models->command_caller = (Command_Caller_Hook_Function*)unit->hook.func;
|
||||
break;
|
||||
|
||||
case _hook_scroll_rule:
|
||||
case special_hook_scroll_rule:
|
||||
models->scroll_rule = (Scroll_Rule_Function*)unit->hook.func;
|
||||
break;
|
||||
|
||||
case _hook_input_filter:
|
||||
case special_hook_input_filter:
|
||||
models->input_filter = (Input_Filter_Function*)unit->hook.func;
|
||||
break;
|
||||
}
|
||||
|
@ -1607,10 +1412,10 @@ App_Init_Sig(app_init){
|
|||
}
|
||||
|
||||
memset(models->app_links.memory, 0, wanted_size);
|
||||
if (!did_top) setup_top_commands(&models->map_top, &models->mem.part, global);
|
||||
if (!did_file) setup_file_commands(&models->map_file, &models->mem.part, global);
|
||||
if (!did_top) setup_top_commands(&models->map_top, &models->mem.part, global_map);
|
||||
if (!did_file) setup_file_commands(&models->map_file, &models->mem.part, global_map);
|
||||
|
||||
setup_ui_commands(&models->map_ui, &models->mem.part, global);
|
||||
setup_ui_commands(&models->map_ui, &models->mem.part, global_map);
|
||||
}
|
||||
|
||||
// NOTE(allen): font setup
|
||||
|
@ -2008,7 +1813,7 @@ App_Step_Sig(app_step){
|
|||
// NOTE(allen): update child processes
|
||||
if (input->dt > 0){
|
||||
Temp_Memory temp = begin_temp_memory(&models->mem.part);
|
||||
u32 max = Kbytes(128);
|
||||
u32 max = KB(128);
|
||||
char *dest = push_array(&models->mem.part, char, max);
|
||||
|
||||
i32 count = vars->cli_processes.count;
|
||||
|
|
13
4ed.h
13
4ed.h
|
@ -84,14 +84,13 @@ Command_Line_Parameters clparams)
|
|||
|
||||
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
|
||||
|
||||
struct Custom_API{
|
||||
Get_Binding_Data_Function *get_bindings;
|
||||
_Get_Version_Function *get_alpha_4coder_version;
|
||||
};
|
||||
|
||||
#define App_Init_Sig(name) void \
|
||||
name(System_Functions *system, \
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
String clipboard, \
|
||||
String current_directory, \
|
||||
Custom_API api)
|
||||
#define App_Init_Sig(name) \
|
||||
void name(System_Functions *system, Render_Target *target, Application_Memory *memory, String clipboard, String current_directory, Custom_API api)
|
||||
|
||||
typedef App_Init_Sig(App_Init);
|
||||
|
||||
|
|
|
@ -1367,18 +1367,14 @@ DOC_SEE(View_Split_Position)
|
|||
|
||||
split.panel->screen_region = panel->screen_region;
|
||||
if (vsplit){
|
||||
i32 x_pos = ROUND32(lerp((f32)lsrpanel->full.x0,
|
||||
split.divider->pos,
|
||||
(f32)lsrpanel->full.x1));
|
||||
i32 x_pos = round32(lerp((f32)lsrpanel->full.x0, split.divider->pos, (f32)lsrpanel->full.x1));
|
||||
|
||||
grtpanel->full.x0 = x_pos;
|
||||
grtpanel->full.x1 = lsrpanel->full.x1;
|
||||
lsrpanel->full.x1 = x_pos;
|
||||
}
|
||||
else{
|
||||
i32 y_pos = ROUND32(lerp((f32)lsrpanel->full.y0,
|
||||
split.divider->pos,
|
||||
(f32)lsrpanel->full.y1));
|
||||
i32 y_pos = round32(lerp((f32)lsrpanel->full.y0, split.divider->pos, (f32)lsrpanel->full.y1));
|
||||
|
||||
grtpanel->full.y0 = y_pos;
|
||||
grtpanel->full.y1 = lsrpanel->full.y1;
|
||||
|
@ -2156,20 +2152,6 @@ directories controlled on the custom side.
|
|||
return(hot->string.size);
|
||||
}
|
||||
|
||||
// TODO(allen): Replace this with an autogenerated file
|
||||
#define Memory_Allocate system->memory_allocate
|
||||
#define Memory_Set_Protection system->memory_set_protection
|
||||
#define Memory_Free system->memory_free
|
||||
|
||||
#define Get_4ed_Path system->get_4ed_path
|
||||
#define File_Exists system->file_exists
|
||||
#define Directory_CD system->directory_cd
|
||||
#define Show_Mouse_Cursor system->show_mouse_cursor
|
||||
|
||||
#define Toggle_Fullscreen system->toggle_fullscreen
|
||||
#define Is_Fullscreen system->is_fullscreen
|
||||
#define Send_Exit_Signal system->send_exit_signal
|
||||
|
||||
API_EXPORT File_List
|
||||
Get_File_List(Application_Links *app, char *dir, int32_t len)
|
||||
/*
|
||||
|
@ -2213,5 +2195,149 @@ DOC(This is a temporary ad-hoc solution to allow some customization of the behav
|
|||
models->user_down_key = down_key;
|
||||
}
|
||||
|
||||
API_EXPORT void*
|
||||
Memory_Allocate(Application_Links *app, int32_t size)
|
||||
/*
|
||||
DOC_PARAM(size, The size in bytes of the block that should be returned.)
|
||||
DOC(This calls to a low level OS allocator which means it is best used for infrequent, large allocations. The size of the block must be remembered if it will be freed or if it's mem protection status will be changed.)
|
||||
DOC_SEE(memory_free)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
void *result = system->memory_allocate(size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Memory_Set_Protection(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags)
|
||||
/*
|
||||
DOC_PARAM(ptr, The base of the block on which to set memory protection flags.)
|
||||
DOC_PARAM(size, The size that was originally used to allocate this block.)
|
||||
DOC_PARAM(flags, The new memory protection flags.)
|
||||
DOC(This call sets the memory protection flags of a block of memory that was previously allocate by memory_allocate.)
|
||||
DOC_SEE(memory_allocate)
|
||||
DOC_SEE(Memory_Protect_Flags)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
bool32 result = system->memory_set_protection(ptr, size, flags);
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Memory_Free(Application_Links *app, void *ptr, int32_t size)
|
||||
/*
|
||||
DOC_PARAM(mem, The base of a block to free.)
|
||||
DOC_PARAM(size, The size that was originally used to allocate this block.)
|
||||
DOC(This call frees a block of memory that was previously allocated by memory_allocate.)
|
||||
DOC_SEE(memory_allocate)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
system->memory_free(ptr, size);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
File_Exists(Application_Links *app, char *filename, int32_t len)
|
||||
/*
|
||||
DOC_PARAM(filename, This parameter specifies the full path to a file; it need not be null terminated.)
|
||||
DOC_PARAM(len, This parameter specifies the length of the filename string.)
|
||||
DOC_RETURN(This call returns non-zero if and only if the file exists.)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
bool32 result = system->file_exists(filename, len);
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Directory_CD(Application_Links *app, char *dir, int32_t *len, int32_t capacity, char *rel_path, int32_t rel_len)
|
||||
/*
|
||||
DOC_PARAM(dir, This parameter provides a character buffer that stores a directory; it need not be null terminated.)
|
||||
DOC_PARAM(len, This parameter specifies the length of the dir string.)
|
||||
DOC_PARAM(capacity, This parameter specifies the maximum size of the dir string.)
|
||||
DOC_PARAM(rel_path, This parameter specifies the path to change to, may include '.' or '..'; it need not be null terminated.)
|
||||
DOC_PARAM(rel_len, This parameter specifies the length of the rel_path string.)
|
||||
DOC_RETURN(This call returns non-zero if the call succeeds.)
|
||||
DOC(
|
||||
This call succeeds if the new directory exists and the it fits inside the dir buffer. If the call succeeds the dir buffer is filled with the new directory and len is overwritten with the length of the new string in the buffer.
|
||||
|
||||
For instance if dir contains "C:/Users/MySelf" and rel is "Documents" the buffer will contain "C:/Users/MySelf/Documents" and len will contain the length of that string. This call can also be used with rel set to ".." to traverse to parent folders.
|
||||
)*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
bool32 result = system->directory_cd(dir, len, capacity, rel_path, rel_len);
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT int32_t
|
||||
Get_4ed_Path(Application_Links *app, char *out, int32_t capacity)
|
||||
/*
|
||||
DOC_PARAM(out, This parameter provides a character buffer that receives the path to the 4ed executable file.)
|
||||
DOC_PARAM(capacity, This parameter specifies the maximum capacity of the out buffer.)
|
||||
DOC_RETURN(This call returns non-zero on success.)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
int32_t result = system->get_4ed_path(out, capacity);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// TODO(allen): add a "shown but auto-hides on timer" setting here.
|
||||
API_EXPORT void
|
||||
Show_Mouse_Cursor(Application_Links *app, Mouse_Cursor_Show_Type show)
|
||||
/*
|
||||
DOC_PARAM(show, This parameter specifies the new state of the mouse cursor.)
|
||||
DOC_SEE(Mouse_Cursor_Show_Type)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
system->show_mouse_cursor(show);
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Toggle_Fullscreen(Application_Links *app)
|
||||
/*
|
||||
DOC(This call tells 4coder to switch into or out of full screen mode.
|
||||
The changes of full screen mode do not take effect until the end of the current frame.
|
||||
On Windows this call will not work unless 4coder was started in "stream mode".
|
||||
Stream mode can be enabled with -S or -F flags on the command line to 4ed.)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
if (!system->toggle_fullscreen()){
|
||||
char msg[] =
|
||||
"ERROR: Failed to go fullscreen.\n"
|
||||
"You can try using 'stream mode' by launching with the -S flag.\n";
|
||||
print_message(app, literal(msg));
|
||||
}
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Is_Fullscreen(Application_Links *app)
|
||||
/*
|
||||
DOC(This call returns true if the 4coder is in full screen mode. This call
|
||||
takes toggles that have already occured this frame into account. So it may return
|
||||
true even though the frame has not ended and actually put 4coder into full screen. If
|
||||
it returns true though, 4coder will definitely be full screen by the beginning of the next
|
||||
frame if the state is not changed.)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
bool32 result = system->is_fullscreen();
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Send_Exit_Signal(Application_Links *app)
|
||||
/*
|
||||
DOC(This call sends a signal to 4coder to attempt to exit. If there are unsaved
|
||||
files this triggers a dialogue ensuring you're okay with closing.)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
system->send_exit_signal();
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -9,34 +9,34 @@
|
|||
|
||||
// TOP
|
||||
|
||||
// TODO(allen): can I get away from this one?
|
||||
// TODO(allen): get away from assert.h
|
||||
// TODO(allen): get away from string.h
|
||||
#include <assert.h>
|
||||
#include "common/4coder_defines.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "4tech_defines.h"
|
||||
|
||||
#include "4coder_API/custom.h"
|
||||
|
||||
#include "4ed_math.h"
|
||||
#include "4ed_system.h"
|
||||
|
||||
//#define USE_DEBUG_MEMORY
|
||||
|
||||
#define FSTRING_IMPLEMENTATION
|
||||
#define FSTRING_C
|
||||
#include "4coder_string.h"
|
||||
|
||||
#include "4coder_custom.h"
|
||||
|
||||
#include "4ed_math.h"
|
||||
|
||||
#include "4ed_system.h"
|
||||
#include "4ed_rendering.h"
|
||||
|
||||
#include "4ed.h"
|
||||
|
||||
# include "4coder_mem.h"
|
||||
|
||||
//#define USE_DEBUG_MEMORY
|
||||
#include "4coder_lib/4coder_string.h"
|
||||
#include "4coder_lib/4coder_mem.h"
|
||||
#include "4coder_lib/4coder_table.h"
|
||||
#if defined(USE_DEBUG_MEMORY)
|
||||
# include "4ed_debug_mem.h"
|
||||
#endif
|
||||
|
||||
#define FCPP_FORBID_MALLOC
|
||||
#include "4cpp_lexer.h"
|
||||
#include "4ed_rendering.h"
|
||||
#include "4ed.h"
|
||||
|
||||
#include "4coder_table.cpp"
|
||||
#define FCPP_FORBID_MALLOC
|
||||
#include "4cpp/4cpp_lexer.h"
|
||||
|
||||
#include "4ed_doubly_linked_list.cpp"
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
|||
#include "file/4coder_working_set.cpp"
|
||||
#include "file/4coder_hot_directory.cpp"
|
||||
|
||||
#include "4ed_gui.h"
|
||||
#include "4ed_gui.cpp"
|
||||
#include "4ed_layout.cpp"
|
||||
#include "4ed_app_models.h"
|
||||
|
|
|
@ -175,7 +175,6 @@ context_eq(Scroll_Context a, Scroll_Context b){
|
|||
struct View_Persistent{
|
||||
i32 id;
|
||||
|
||||
View_Routine_Function *view_routine;
|
||||
Coroutine *coroutine;
|
||||
Event_Message message_passing_slot;
|
||||
|
||||
|
@ -477,7 +476,7 @@ inline i32
|
|||
view_compute_max_target_y(i32 lowest_line, i32 line_height, f32 view_height){
|
||||
f32 max_target_y = ((lowest_line+.5f)*line_height) - view_height*.5f;
|
||||
max_target_y = clamp_bottom(0.f, max_target_y);
|
||||
return(CEIL32(max_target_y));
|
||||
return(ceil32(max_target_y));
|
||||
}
|
||||
|
||||
internal i32
|
||||
|
@ -521,28 +520,28 @@ view_move_view_to_cursor(View *view, GUI_Scroll_Vars *scroll, b32 center_view){
|
|||
|
||||
if (cursor_y > target_y + limits.max){
|
||||
if (center_view){
|
||||
target_y = ROUND32(cursor_y - limits.max*.5f);
|
||||
target_y = round32(cursor_y - limits.max*.5f);
|
||||
}
|
||||
else{
|
||||
target_y = CEIL32(cursor_y - limits.max + limits.delta);
|
||||
target_y = ceil32(cursor_y - limits.max + limits.delta);
|
||||
}
|
||||
}
|
||||
if (cursor_y < target_y + limits.min){
|
||||
if (center_view){
|
||||
target_y = ROUND32(cursor_y - limits.max*.5f);
|
||||
target_y = round32(cursor_y - limits.max*.5f);
|
||||
}
|
||||
else{
|
||||
target_y = FLOOR32(cursor_y - limits.delta - limits.min);
|
||||
target_y = floor32(cursor_y - limits.delta - limits.min);
|
||||
}
|
||||
}
|
||||
|
||||
target_y = clamp(0, target_y, max_y);
|
||||
|
||||
if (cursor_x >= target_x + max_x){
|
||||
target_x = CEIL32(cursor_x - max_x/2);
|
||||
target_x = ceil32(cursor_x - max_x/2);
|
||||
}
|
||||
else if (cursor_x < target_x){
|
||||
target_x = FLOOR32(Max(0, cursor_x - max_x/2));
|
||||
target_x = floor32(Max(0, cursor_x - max_x/2));
|
||||
}
|
||||
|
||||
if (target_x != scroll_vars.target_x || target_y != scroll_vars.target_y){
|
||||
|
@ -854,7 +853,7 @@ file_grow_starts_as_needed(General_Memory *general, Gap_Buffer *buffer, i32 addi
|
|||
i32 target_lines = count + additional_lines;
|
||||
|
||||
if (target_lines > max || max == 0){
|
||||
max = l_round_up_i32(target_lines + max, Kbytes(1));
|
||||
max = l_round_up(target_lines + max, KB(1));
|
||||
|
||||
i32 *new_lines = (i32*)general_memory_reallocate(general, buffer->line_starts, sizeof(i32)*count, sizeof(f32)*max);
|
||||
|
||||
|
@ -896,7 +895,7 @@ file_update_cursor_positions(Models *models, Editing_File *file){
|
|||
internal void
|
||||
file_measure_starts(General_Memory *general, Gap_Buffer *buffer){
|
||||
if (!buffer->line_starts){
|
||||
i32 max = buffer->line_max = Kbytes(1);
|
||||
i32 max = buffer->line_max = KB(1);
|
||||
buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32));
|
||||
TentativeAssert(buffer->line_starts);
|
||||
// TODO(allen): when unable to allocate?
|
||||
|
@ -977,7 +976,7 @@ struct Code_Wrap_X{
|
|||
i32 paren_safe_top;
|
||||
i32 paren_top;
|
||||
};
|
||||
globalvar Code_Wrap_X null_wrap_x = {0};
|
||||
global Code_Wrap_X null_wrap_x = {0};
|
||||
|
||||
struct Code_Wrap_State{
|
||||
Cpp_Token_Array token_array;
|
||||
|
@ -1462,7 +1461,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
|
|||
wrap_state_init(&wrap_state, file, adv);
|
||||
use_tokens = 1;
|
||||
|
||||
potential_marks = push_array(part, Potential_Wrap_Indent_Pair, FLOOR32(width));
|
||||
potential_marks = push_array(part, Potential_Wrap_Indent_Pair, floor32(width));
|
||||
|
||||
max_wrap_indent_mark = partition_remaining(part)/sizeof(Wrap_Indent_Pair);
|
||||
wrap_indent_marks = push_array(part, Wrap_Indent_Pair, max_wrap_indent_mark);
|
||||
|
@ -1905,8 +1904,10 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
|
|||
Gap_Buffer_Init init = buffer_begin_init(&file->state.buffer, val.str, val.size);
|
||||
for (; buffer_init_need_more(&init); ){
|
||||
i32 page_size = buffer_init_page_size(&init);
|
||||
page_size = l_round_up_i32(page_size, Kbytes(4));
|
||||
if (page_size < Kbytes(4)) page_size = Kbytes(4);
|
||||
page_size = l_round_up(page_size, KB(4));
|
||||
if (page_size < KB(4)){
|
||||
page_size = KB(4);
|
||||
}
|
||||
void *data = general_memory_allocate(general, page_size);
|
||||
buffer_init_provide_page(&init, data, page_size);
|
||||
}
|
||||
|
@ -1937,7 +1938,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
|
|||
file->settings.read_only = read_only;
|
||||
if (!read_only){
|
||||
// TODO(allen): Redo undo system (if you don't mind the pun)
|
||||
i32 request_size = Kbytes(64);
|
||||
i32 request_size = KB(64);
|
||||
file->state.undo.undo.max = request_size;
|
||||
file->state.undo.undo.strings = (u8*)general_memory_allocate(general, request_size);
|
||||
file->state.undo.undo.edit_max = request_size / sizeof(Edit_Step);
|
||||
|
@ -2079,7 +2080,7 @@ Job_Callback_Sig(job_full_lex){
|
|||
}
|
||||
} while (still_lexing);
|
||||
|
||||
i32 new_max = l_round_up_i32(tokens.count+1, Kbytes(1));
|
||||
i32 new_max = l_round_up(tokens.count+1, KB(1));
|
||||
|
||||
system->acquire_lock(FRAME_LOCK);
|
||||
{
|
||||
|
@ -2206,7 +2207,7 @@ file_first_lex_serial(Mem_Options *mem, Editing_File *file){
|
|||
}
|
||||
} while (still_lexing);
|
||||
|
||||
i32 new_max = l_round_up_i32(tokens.count+1, Kbytes(1));
|
||||
i32 new_max = l_round_up(tokens.count+1, KB(1));
|
||||
|
||||
{
|
||||
Assert(file->state.swap_array.tokens == 0);
|
||||
|
@ -2320,7 +2321,7 @@ file_relex_parallel(System_Functions *system, Mem_Options *mem, Editing_File *fi
|
|||
if (inline_lex){
|
||||
i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array);
|
||||
if (new_count > array->max_count){
|
||||
i32 new_max = l_round_up_i32(new_count, Kbytes(1));
|
||||
i32 new_max = l_round_up(new_count, KB(1));
|
||||
array->tokens = (Cpp_Token*)
|
||||
general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token));
|
||||
array->max_count = new_max;
|
||||
|
@ -2435,9 +2436,8 @@ file_relex_serial(Mem_Options *mem, Editing_File *file, i32 start_i, i32 end_i,
|
|||
|
||||
i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array);
|
||||
if (new_count > array->max_count){
|
||||
i32 new_max = l_round_up_i32(new_count, Kbytes(1));
|
||||
array->tokens = (Cpp_Token*)
|
||||
general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token));
|
||||
i32 new_max = l_round_up(new_count, KB(1));
|
||||
array->tokens = (Cpp_Token*)general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token));
|
||||
array->max_count = new_max;
|
||||
}
|
||||
|
||||
|
@ -2658,7 +2658,7 @@ file_post_history(General_Memory *general, Editing_File *file, Edit_Step step, b
|
|||
Edit_Stack *history = &file->state.undo.history;
|
||||
Edit_Step *result = 0;
|
||||
|
||||
persist Edit_Type reverse_types[4];
|
||||
local_persist Edit_Type reverse_types[4];
|
||||
if (reverse_types[ED_UNDO] == 0){
|
||||
reverse_types[ED_NORMAL] = ED_REVERSE_NORMAL;
|
||||
reverse_types[ED_REVERSE_NORMAL] = ED_NORMAL;
|
||||
|
@ -2816,7 +2816,7 @@ view_set_relative_scrolling(View *view, Relative_Scrolling scrolling){
|
|||
|
||||
if (view->edit_pos){
|
||||
view->edit_pos->scroll.scroll_y = cursor_y - scrolling.scroll_y;
|
||||
view->edit_pos->scroll.target_y = ROUND32(clamp_bottom(0.f, cursor_y - scrolling.target_y));
|
||||
view->edit_pos->scroll.target_y = round32(clamp_bottom(0.f, cursor_y - scrolling.target_y));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3088,8 +3088,7 @@ file_edit_cursor_fix(System_Functions *system, Models *models,
|
|||
}
|
||||
y_position += y_offset;
|
||||
|
||||
scroll.target_y +=
|
||||
ROUND32(y_position - scroll.scroll_y);
|
||||
scroll.target_y += round32(y_position - scroll.scroll_y);
|
||||
scroll.scroll_y = y_position;
|
||||
}
|
||||
|
||||
|
@ -4165,10 +4164,10 @@ view_reinit_scrolling(View *view){
|
|||
h = view_file_height(view);
|
||||
|
||||
if (cursor_x >= target_x + w){
|
||||
target_x = ROUND32(cursor_x - w*.35f);
|
||||
target_x = round32(cursor_x - w*.35f);
|
||||
}
|
||||
|
||||
target_y = clamp_bottom(0, FLOOR32(cursor_y - h*.5f));
|
||||
target_y = clamp_bottom(0, floor32(cursor_y - h*.5f));
|
||||
}
|
||||
|
||||
GUI_Scroll_Vars scroll = {0};
|
||||
|
@ -4254,9 +4253,9 @@ begin_exhaustive_loop(Exhaustive_File_Loop *loop, Hot_Directory *hdir){
|
|||
|
||||
internal Exhaustive_File_Info
|
||||
get_exhaustive_info(System_Functions *system, Working_Set *working_set, Exhaustive_File_Loop *loop, i32 i){
|
||||
persist String message_loaded = make_lit_string(" LOADED");
|
||||
persist String message_unsaved = make_lit_string(" LOADED *");
|
||||
persist String message_unsynced = make_lit_string(" LOADED !");
|
||||
local_persist String message_loaded = make_lit_string(" LOADED");
|
||||
local_persist String message_unsaved = make_lit_string(" LOADED *");
|
||||
local_persist String message_unsynced = make_lit_string(" LOADED !");
|
||||
|
||||
Exhaustive_File_Info result = {0};
|
||||
Editing_File *file = 0;
|
||||
|
@ -5029,8 +5028,8 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su
|
|||
|
||||
case IInt_Live_File_List:
|
||||
{
|
||||
persist String message_unsaved = make_lit_string(" *");
|
||||
persist String message_unsynced = make_lit_string(" !");
|
||||
local_persist String message_unsaved = make_lit_string(" *");
|
||||
local_persist String message_unsynced = make_lit_string(" !");
|
||||
|
||||
String message = {0};
|
||||
switch (view->action){
|
||||
|
@ -5805,7 +5804,7 @@ do_step_file_view(System_Functions *system,
|
|||
v = unlerp(gui_session.scroll_top, (f32)my,
|
||||
gui_session.scroll_bottom);
|
||||
v = clamp(0.f, v, 1.f);
|
||||
result.vars.target_y = ROUND32(lerp(0.f, v, (f32)max_y));
|
||||
result.vars.target_y = round32(lerp(0.f, v, (f32)max_y));
|
||||
|
||||
gui_activate_scrolling(target);
|
||||
result.is_animating = 1;
|
||||
|
@ -6146,7 +6145,7 @@ draw_text_field(Render_Target *target, View *view, i16 font_id,
|
|||
|
||||
if (target){
|
||||
draw_rectangle(target, rect, back_color);
|
||||
x = CEIL32(draw_string(target, font_id, p, x, y, text2_color));
|
||||
x = ceil32(draw_string(target, font_id, p, x, y, text2_color));
|
||||
draw_string(target, font_id, t, x, y, text1_color);
|
||||
}
|
||||
}
|
||||
|
@ -6178,19 +6177,19 @@ draw_text_with_cursor(Render_Target *target, View *view, i16 font_id,
|
|||
part3 = substr(s, pos+1, s.size-pos-1);
|
||||
|
||||
|
||||
x = draw_string(target, font_id, part1, FLOOR32(x), y, text_color);
|
||||
x = draw_string(target, font_id, part1, floor32(x), y, text_color);
|
||||
|
||||
cursor_rect.x0 = FLOOR32(x);
|
||||
cursor_rect.x1 = FLOOR32(x) + CEIL32(font->advance_data[s.str[pos]]);
|
||||
cursor_rect.x0 = floor32(x);
|
||||
cursor_rect.x1 = floor32(x) + ceil32(font->advance_data[s.str[pos]]);
|
||||
cursor_rect.y0 = y;
|
||||
cursor_rect.y1 = y + view->line_height;
|
||||
draw_rectangle(target, cursor_rect, cursor_color);
|
||||
x = draw_string(target, font_id, part2, FLOOR32(x), y, at_cursor_color);
|
||||
x = draw_string(target, font_id, part2, floor32(x), y, at_cursor_color);
|
||||
|
||||
draw_string(target, font_id, part3, FLOOR32(x), y, text_color);
|
||||
draw_string(target, font_id, part3, floor32(x), y, text_color);
|
||||
}
|
||||
else{
|
||||
draw_string(target, font_id, s, FLOOR32(x), y, text_color);
|
||||
draw_string(target, font_id, s, floor32(x), y, text_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6254,13 +6253,13 @@ draw_file_bar(Render_Target *target, View *view, Editing_File *file, i32_Rect re
|
|||
switch (file_get_sync(file)){
|
||||
case DirtyState_UnloadedChanges:
|
||||
{
|
||||
persist String out_of_sync = make_lit_string(" !");
|
||||
local_persist String out_of_sync = make_lit_string(" !");
|
||||
intbar_draw_string(target, &bar, out_of_sync, pop2_color);
|
||||
}break;
|
||||
|
||||
case DirtyState_UnsavedChanges:
|
||||
{
|
||||
persist String out_of_sync = make_lit_string(" *");
|
||||
local_persist String out_of_sync = make_lit_string(" *");
|
||||
intbar_draw_string(target, &bar, out_of_sync, pop2_color);
|
||||
}break;
|
||||
}
|
||||
|
@ -6358,13 +6357,12 @@ draw_fat_option_block(GUI_Target *gui_target, Render_Target *target, View *view,
|
|||
x = checkbox_rect.x1 + 3;
|
||||
}
|
||||
|
||||
x = CEIL32(draw_string(target, font_id, text, x, y, text_color));
|
||||
x = ceil32(draw_string(target, font_id, text, x, y, text_color));
|
||||
draw_string(target, font_id, pop, x, y, pop_color);
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_button(GUI_Target *gui_target, Render_Target *target, View *view,
|
||||
i16 font_id, i32_Rect rect, GUI_id id, String text){
|
||||
draw_button(GUI_Target *gui_target, Render_Target *target, View *view, i16 font_id, i32_Rect rect, GUI_id id, String text){
|
||||
Models *models = view->persistent.models;
|
||||
Style *style = main_style(models);
|
||||
|
||||
|
@ -6410,7 +6408,7 @@ draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view,
|
|||
|
||||
i32 y = inner.y0;
|
||||
i32 x = inner.x0;
|
||||
x = CEIL32(draw_string(target, font_id, style->name.str, x, y, text_color));
|
||||
x = ceil32(draw_string(target, font_id, style->name.str, x, y, text_color));
|
||||
i32 font_x = (i32)(inner.x1 - font_string_width(target, font_id, info->name.str));
|
||||
if (font_x > x + 10){
|
||||
draw_string(target, font_id, info->name.str, font_x, y, text_color);
|
||||
|
@ -6418,13 +6416,13 @@ draw_style_preview(GUI_Target *gui_target, Render_Target *target, View *view,
|
|||
|
||||
x = inner.x0;
|
||||
y += info->height;
|
||||
x = CEIL32(draw_string(target, font_id, "if", x, y, keyword_color));
|
||||
x = CEIL32(draw_string(target, font_id, "(x < ", x, y, text_color));
|
||||
x = CEIL32(draw_string(target, font_id, "0", x, y, int_constant_color));
|
||||
x = CEIL32(draw_string(target, font_id, ") { x = ", x, y, text_color));
|
||||
x = CEIL32(draw_string(target, font_id, "0", x, y, int_constant_color));
|
||||
x = CEIL32(draw_string(target, font_id, "; } ", x, y, text_color));
|
||||
x = CEIL32(draw_string(target, font_id, "// comment", x, y, comment_color));
|
||||
x = ceil32(draw_string(target, font_id, "if", x, y, keyword_color));
|
||||
x = ceil32(draw_string(target, font_id, "(x < ", x, y, text_color));
|
||||
x = ceil32(draw_string(target, font_id, "0", x, y, int_constant_color));
|
||||
x = ceil32(draw_string(target, font_id, ") { x = ", x, y, text_color));
|
||||
x = ceil32(draw_string(target, font_id, "0", x, y, int_constant_color));
|
||||
x = ceil32(draw_string(target, font_id, "; } ", x, y, text_color));
|
||||
x = ceil32(draw_string(target, font_id, "// comment", x, y, comment_color));
|
||||
|
||||
x = inner.x0;
|
||||
y += info->height;
|
||||
|
@ -6680,7 +6678,7 @@ live_set_alloc_view(Live_Views *live_set, Panel *panel, Models *models){
|
|||
init_query_set(&result.view->query_set);
|
||||
|
||||
{
|
||||
i32 gui_mem_size = Kbytes(512);
|
||||
i32 gui_mem_size = KB(512);
|
||||
void *gui_mem = general_memory_allocate(&models->mem.general, gui_mem_size + 8);
|
||||
result.view->gui_mem = gui_mem;
|
||||
gui_mem = advance_to_alignment(gui_mem);
|
||||
|
|
46
4ed_gui.cpp
46
4ed_gui.cpp
|
@ -213,14 +213,14 @@ gui_active_level(GUI_Target *target, GUI_id id){
|
|||
i32 level = 0;
|
||||
if (gui_id_eq(target->active, id)){
|
||||
level = 4;
|
||||
}
|
||||
}
|
||||
else if (gui_id_eq(target->auto_hot, id)){
|
||||
level = 3;
|
||||
}
|
||||
else if (gui_id_eq(target->mouse_hot, id)){
|
||||
if (gui_id_eq(target->hover, id)){
|
||||
level = 3;
|
||||
}
|
||||
}
|
||||
else{
|
||||
level = 2;
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ gui_push_aligned_item(GUI_Target *target, GUI_Header *h, void *item, i32 size){
|
|||
char *ptr = (char*)partition_allocate(&target->push, size);
|
||||
if (ptr && item){
|
||||
memcpy(ptr, item, size);
|
||||
}
|
||||
}
|
||||
gui_align(target, h);
|
||||
return(ptr);
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ gui_push_item(GUI_Target *target, GUI_Header *h, void *item, i32 size){
|
|||
ptr = (char*)partition_allocate(&target->push, size);
|
||||
if (ptr && item){
|
||||
memcpy(ptr, item, size);
|
||||
}
|
||||
}
|
||||
h->size += size;
|
||||
return(ptr);
|
||||
}
|
||||
|
@ -445,7 +445,7 @@ gui_do_color_button(GUI_Target *target, GUI_id id, u32 fore, u32 back, String te
|
|||
if (gui_id_eq(id, target->active)){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -462,7 +462,7 @@ gui_do_font_button(GUI_Target *target, GUI_id id, i16 font_id, String text){
|
|||
if (gui_id_eq(id, target->active)){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -485,7 +485,7 @@ gui_begin_list(GUI_Target *target, GUI_id id, i32 list_i,
|
|||
if (gui_id_eq(id, target->active)){
|
||||
active = 1;
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_into_view){
|
||||
if (target->list_view_min > list_min){
|
||||
|
@ -543,7 +543,7 @@ gui_do_file_option(GUI_Target *target, GUI_id id, String filename,
|
|||
if (gui_id_eq(id, target->active)){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ gui_do_button(GUI_Target *target, GUI_id id, String message){
|
|||
if (gui_id_eq(id, target->active)){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ gui_do_fixed_option(GUI_Target *target, GUI_id id, String message, char key){
|
|||
if (gui_id_eq(id, target->active)){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -594,7 +594,7 @@ gui_do_fixed_option_checkbox(GUI_Target *target, GUI_id id, String message, char
|
|||
if (gui_id_eq(id, target->active)){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -610,7 +610,7 @@ gui_do_style_preview(GUI_Target *target, GUI_id id, i32 style_index){
|
|||
if (gui_id_eq(id, target->active)){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
@ -821,7 +821,7 @@ gui_layout_top_bottom(GUI_Session *session, i32 y0, i32 y1){
|
|||
if (session->is_scrollable){
|
||||
rect.x0 = session->scroll_region.x0;
|
||||
rect.x1 = session->scroll_region.x1;
|
||||
}
|
||||
}
|
||||
|
||||
return(rect);
|
||||
}
|
||||
|
@ -968,10 +968,10 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
y = section->v;
|
||||
|
||||
if (!session->is_scrollable) scroll_v = 0;
|
||||
|
||||
|
||||
switch (h->type){
|
||||
case guicom_null: Assert(0); break;
|
||||
|
||||
|
||||
case guicom_begin_serial:
|
||||
++session->t;
|
||||
Assert(session->t < ArrayCount(session->sections));
|
||||
|
@ -980,21 +980,21 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
new_section->max_v = y;
|
||||
new_section->top_v = y;
|
||||
break;
|
||||
|
||||
|
||||
case guicom_end_serial:
|
||||
Assert(session->t > 0);
|
||||
prev_section = &session->sections[--session->t];
|
||||
end_v = section->max_v;
|
||||
end_section = prev_section;
|
||||
break;
|
||||
|
||||
|
||||
case guicom_top_bar:
|
||||
give_to_user = 1;
|
||||
rect = gui_layout_fixed_h(session, y, session->line_height + 2);
|
||||
end_v = rect.y1;
|
||||
end_section = section;
|
||||
break;
|
||||
|
||||
|
||||
case guicom_file:
|
||||
give_to_user = 1;
|
||||
rect = gui_layout_top_bottom(session, y, session->full_rect.y1);
|
||||
|
@ -1002,7 +1002,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
end_section = section;
|
||||
scroll_v = 0;
|
||||
break;
|
||||
|
||||
|
||||
case guicom_text_with_cursor:
|
||||
case guicom_text_field:
|
||||
give_to_user = 1;
|
||||
|
@ -1010,7 +1010,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
end_v = rect.y1;
|
||||
end_section = section;
|
||||
break;
|
||||
|
||||
|
||||
case guicom_color_button:
|
||||
case guicom_font_button:
|
||||
give_to_user = 1;
|
||||
|
@ -1018,7 +1018,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
end_v = rect.y1;
|
||||
end_section = section;
|
||||
break;
|
||||
|
||||
|
||||
case guicom_begin_list:
|
||||
{
|
||||
GUI_Interactive *b = (GUI_Interactive*)h;
|
||||
|
@ -1164,9 +1164,7 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
|
||||
case guicom_end_scrollable_section:
|
||||
always_give_to_user = 1;
|
||||
session->suggested_max_y =
|
||||
CEIL32(session->scrollable_items_bottom -
|
||||
(session->full_rect.y0 + session->full_rect.y1)*.5f);
|
||||
session->suggested_max_y = ceil32(session->scrollable_items_bottom - (session->full_rect.y0 + session->full_rect.y1)*.5f);
|
||||
if (session->suggested_max_y < 0){
|
||||
session->suggested_max_y = 0;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ panel_init(Panel *panel){
|
|||
panel->view = 0;
|
||||
panel->parent = -1;
|
||||
panel->which_child = 0;
|
||||
panel->screen_region.full = i32_rect_zero();
|
||||
panel->screen_region.inner = i32_rect_zero();
|
||||
panel->screen_region.full = null_i32_rect;
|
||||
panel->screen_region.inner = null_i32_rect;
|
||||
panel->l_margin = 3;
|
||||
panel->r_margin = 3;
|
||||
panel->t_margin = 3;
|
||||
|
@ -233,18 +233,18 @@ layout_get_rect(Editing_Layout *layout, i32 id, i32 which_child){
|
|||
Panel_Divider *div = dividers + divider_chain[i];
|
||||
if (div->v_divider){
|
||||
if (div->child1 == divider_chain[i-1]){
|
||||
r.x1 = ROUND32(lerp((f32)r.x0, div->pos, (f32)r.x1));
|
||||
r.x1 = round32(lerp((f32)r.x0, div->pos, (f32)r.x1));
|
||||
}
|
||||
else{
|
||||
r.x0 = ROUND32(lerp((f32)r.x0, div->pos, (f32)r.x1));
|
||||
r.x0 = round32(lerp((f32)r.x0, div->pos, (f32)r.x1));
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (div->child1 == divider_chain[i-1]){
|
||||
r.y1 = ROUND32(lerp((f32)r.y0, div->pos, (f32)r.y1));
|
||||
r.y1 = round32(lerp((f32)r.y0, div->pos, (f32)r.y1));
|
||||
}
|
||||
else{
|
||||
r.y0 = ROUND32(lerp((f32)r.y0, div->pos, (f32)r.y1));
|
||||
r.y0 = round32(lerp((f32)r.y0, div->pos, (f32)r.y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,20 +253,20 @@ layout_get_rect(Editing_Layout *layout, i32 id, i32 which_child){
|
|||
case 1:
|
||||
{
|
||||
if (original_div->v_divider){
|
||||
r.x0 = ROUND32(lerp((f32)r.x0, original_div->pos, (f32)r.x1));
|
||||
r.x0 = round32(lerp((f32)r.x0, original_div->pos, (f32)r.x1));
|
||||
}
|
||||
else{
|
||||
r.y0 = ROUND32(lerp((f32)r.y0, original_div->pos, (f32)r.y1));
|
||||
r.y0 = round32(lerp((f32)r.y0, original_div->pos, (f32)r.y1));
|
||||
}
|
||||
}break;
|
||||
|
||||
case -1:
|
||||
{
|
||||
if (original_div->v_divider){
|
||||
r.x1 = ROUND32(lerp((f32)r.x0, original_div->pos, (f32)r.x1));
|
||||
r.x1 = round32(lerp((f32)r.x0, original_div->pos, (f32)r.x1));
|
||||
}
|
||||
else{
|
||||
r.y1 = ROUND32(lerp((f32)r.y0, original_div->pos, (f32)r.y1));
|
||||
r.y1 = round32(lerp((f32)r.y0, original_div->pos, (f32)r.y1));
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
|
173
4ed_math.h
173
4ed_math.h
|
@ -60,10 +60,10 @@ COS(f32 x_degrees){
|
|||
struct Vec2{
|
||||
union{
|
||||
struct{
|
||||
real32 x, y;
|
||||
f32 x, y;
|
||||
};
|
||||
struct{
|
||||
real32 v[2];
|
||||
f32 v[2];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -71,21 +71,21 @@ struct Vec2{
|
|||
struct Vec3{
|
||||
union{
|
||||
struct{
|
||||
real32 x, y, z;
|
||||
f32 x, y, z;
|
||||
};
|
||||
struct{
|
||||
real32 r, g, b;
|
||||
f32 r, g, b;
|
||||
};
|
||||
struct{
|
||||
Vec2 xy;
|
||||
real32 _z;
|
||||
f32 _z;
|
||||
};
|
||||
struct{
|
||||
real32 _x;
|
||||
f32 _x;
|
||||
Vec2 yz;
|
||||
};
|
||||
struct{
|
||||
real32 v[3];
|
||||
f32 v[3];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -93,35 +93,35 @@ struct Vec3{
|
|||
struct Vec4{
|
||||
union{
|
||||
struct{
|
||||
real32 r, g, b, a;
|
||||
f32 r, g, b, a;
|
||||
};
|
||||
|
||||
struct{
|
||||
real32 h, s, l, __a;
|
||||
f32 h, s, l, __a;
|
||||
};
|
||||
struct{
|
||||
real32 x, y, z, w;
|
||||
f32 x, y, z, w;
|
||||
};
|
||||
struct{
|
||||
Vec3 rgb;
|
||||
real32 _a;
|
||||
f32 _a;
|
||||
};
|
||||
struct{
|
||||
Vec3 xyz;
|
||||
real32 _w;
|
||||
f32 _w;
|
||||
};
|
||||
struct{
|
||||
real32 _x;
|
||||
f32 _x;
|
||||
Vec3 yzw;
|
||||
};
|
||||
struct{
|
||||
real32 v[4];
|
||||
f32 v[4];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
inline internal Vec2
|
||||
V2(real32 x, real32 y){
|
||||
V2(f32 x, f32 y){
|
||||
Vec2 result;
|
||||
result.x = x;
|
||||
result.y = y;
|
||||
|
@ -129,7 +129,7 @@ V2(real32 x, real32 y){
|
|||
}
|
||||
|
||||
inline internal Vec3
|
||||
V3(real32 x, real32 y, real32 z){
|
||||
V3(f32 x, f32 y, f32 z){
|
||||
Vec3 result;
|
||||
result.x = x;
|
||||
result.y = y;
|
||||
|
@ -138,7 +138,7 @@ V3(real32 x, real32 y, real32 z){
|
|||
}
|
||||
|
||||
inline internal Vec4
|
||||
V4(real32 x, real32 y, real32 z, real32 w){
|
||||
V4(f32 x, f32 y, f32 z, f32 w){
|
||||
Vec4 result;
|
||||
result.x = x;
|
||||
result.y = y;
|
||||
|
@ -202,7 +202,7 @@ operator-(Vec4 a, Vec4 b){
|
|||
}
|
||||
|
||||
inline internal Vec2
|
||||
operator*(Vec2 a, real32 k){
|
||||
operator*(Vec2 a, f32 k){
|
||||
Vec2 result;
|
||||
result.x = a.x * k;
|
||||
result.y = a.y * k;
|
||||
|
@ -210,7 +210,7 @@ operator*(Vec2 a, real32 k){
|
|||
}
|
||||
|
||||
inline internal Vec3
|
||||
operator*(Vec3 a, real32 k){
|
||||
operator*(Vec3 a, f32 k){
|
||||
Vec3 result;
|
||||
result.x = a.x * k;
|
||||
result.y = a.y * k;
|
||||
|
@ -219,7 +219,7 @@ operator*(Vec3 a, real32 k){
|
|||
}
|
||||
|
||||
inline internal Vec4
|
||||
operator*(Vec4 a, real32 k){
|
||||
operator*(Vec4 a, f32 k){
|
||||
Vec4 result;
|
||||
result.x = a.x * k;
|
||||
result.y = a.y * k;
|
||||
|
@ -229,7 +229,7 @@ operator*(Vec4 a, real32 k){
|
|||
}
|
||||
|
||||
inline internal Vec2
|
||||
operator*(real32 k, Vec2 a){
|
||||
operator*(f32 k, Vec2 a){
|
||||
Vec2 result;
|
||||
result.x = a.x * k;
|
||||
result.y = a.y * k;
|
||||
|
@ -237,7 +237,7 @@ operator*(real32 k, Vec2 a){
|
|||
}
|
||||
|
||||
inline internal Vec3
|
||||
operator*(real32 k, Vec3 a){
|
||||
operator*(f32 k, Vec3 a){
|
||||
Vec3 result;
|
||||
result.x = a.x * k;
|
||||
result.y = a.y * k;
|
||||
|
@ -246,7 +246,7 @@ operator*(real32 k, Vec3 a){
|
|||
}
|
||||
|
||||
inline internal Vec4
|
||||
operator*(real32 k, Vec4 a){
|
||||
operator*(f32 k, Vec4 a){
|
||||
Vec4 result;
|
||||
result.x = a.x * k;
|
||||
result.y = a.y * k;
|
||||
|
@ -292,40 +292,40 @@ operator-=(Vec4 &a, Vec4 b){
|
|||
}
|
||||
|
||||
inline internal Vec2&
|
||||
operator*=(Vec2 &a, real32 k){
|
||||
operator*=(Vec2 &a, f32 k){
|
||||
a = (a * k);
|
||||
return a;
|
||||
}
|
||||
|
||||
inline internal Vec3&
|
||||
operator*=(Vec3 &a, real32 k){
|
||||
operator*=(Vec3 &a, f32 k){
|
||||
a = (a * k);
|
||||
return a;
|
||||
}
|
||||
|
||||
inline internal Vec4&
|
||||
operator*=(Vec4 &a, real32 k){
|
||||
operator*=(Vec4 &a, f32 k){
|
||||
a = (a * k);
|
||||
return a;
|
||||
}
|
||||
|
||||
inline internal real32
|
||||
inline internal f32
|
||||
dot(Vec2 a, Vec2 b){
|
||||
real32 result;
|
||||
f32 result;
|
||||
result = a.x*b.x + a.y*b.y;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline internal real32
|
||||
inline internal f32
|
||||
dot(Vec3 a, Vec3 b){
|
||||
real32 result;
|
||||
f32 result;
|
||||
result = a.x*b.x + a.y*b.y + a.z*b.z;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline internal real32
|
||||
inline internal f32
|
||||
dot(Vec4 a, Vec4 b){
|
||||
real32 result;
|
||||
f32 result;
|
||||
result = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
|
||||
return result;
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ perp(Vec2 v){
|
|||
}
|
||||
|
||||
inline Vec2
|
||||
polar_to_cartesian(real32 theta_degrees, real32 length){
|
||||
polar_to_cartesian(f32 theta_degrees, f32 length){
|
||||
Vec2 result;
|
||||
result.x = COS(theta_degrees)*length;
|
||||
result.y = SIN(theta_degrees)*length;
|
||||
|
@ -383,9 +383,9 @@ polar_to_cartesian(real32 theta_degrees, real32 length){
|
|||
}
|
||||
|
||||
inline Vec2
|
||||
rotate(Vec2 v, real32 theta_degrees){
|
||||
rotate(Vec2 v, f32 theta_degrees){
|
||||
Vec2 result;
|
||||
real32 c, s;
|
||||
f32 c, s;
|
||||
c = COS(theta_degrees);
|
||||
s = SIN(theta_degrees);
|
||||
result.x = v.x*c - v.y*s;
|
||||
|
@ -475,7 +475,7 @@ clamp(i32 a, i32 n, i32 z){
|
|||
|
||||
// TODO(allen): Convert colors to Vec4
|
||||
inline u32
|
||||
color_blend(u32 a, real32 t, u32 b){
|
||||
color_blend(u32 a, f32 t, u32 b){
|
||||
union{
|
||||
u8 byte[4];
|
||||
u32 comp;
|
||||
|
@ -524,7 +524,7 @@ pack_color4(Vec4 color){
|
|||
internal Vec4
|
||||
rgba_to_hsla(Vec4 rgba){
|
||||
Vec4 hsla = {};
|
||||
real32 max, min, delta;
|
||||
f32 max, min, delta;
|
||||
i32 maxc;
|
||||
hsla.a = rgba.a;
|
||||
max = rgba.r; min = rgba.r;
|
||||
|
@ -580,43 +580,80 @@ rgba_to_hsla(Vec4 rgba){
|
|||
internal Vec4
|
||||
hsla_to_rgba(Vec4 hsla){
|
||||
if (hsla.h >= 1.f) hsla.h = 0.f;
|
||||
Vec4 rgba = {};
|
||||
real32 C, X, m;
|
||||
i32 H;
|
||||
Vec4 rgba = {0};
|
||||
f32 C = (1.f - ABS(2*hsla.z - 1.f)) * hsla.y;
|
||||
f32 X = C * (1.f-ABS(MOD(hsla.x*6.f, 2)-1.f));
|
||||
f32 m = hsla.z - C*.5f;
|
||||
i32 H = floor32(hsla.x * 6.f);
|
||||
rgba.a = hsla.a;
|
||||
C = (1.f - ABS(2*hsla.z - 1.f)) * hsla.y;
|
||||
X = C * (1.f-ABS(MOD(hsla.x*6.f, 2)-1.f));
|
||||
m = hsla.z - C*.5f;
|
||||
H = FLOOR32(hsla.x * 6.f);
|
||||
switch (H){
|
||||
case 0:
|
||||
rgba.r = C; rgba.g = X; rgba.b = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rgba.r = X; rgba.g = C; rgba.b = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
rgba.r = 0; rgba.g = C; rgba.b = X;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
rgba.r = 0; rgba.g = X; rgba.b = C;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rgba.r = X; rgba.g = 0; rgba.b = C;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
rgba.r = C; rgba.g = 0; rgba.b = X;
|
||||
break;
|
||||
case 0: rgba.r = C; rgba.g = X; rgba.b = 0; break;
|
||||
case 1: rgba.r = X; rgba.g = C; rgba.b = 0; break;
|
||||
case 2: rgba.r = 0; rgba.g = C; rgba.b = X; break;
|
||||
case 3: rgba.r = 0; rgba.g = X; rgba.b = C; break;
|
||||
case 4: rgba.r = X; rgba.g = 0; rgba.b = C; break;
|
||||
case 5: rgba.r = C; rgba.g = 0; rgba.b = X; break;
|
||||
}
|
||||
rgba.r += m;
|
||||
rgba.g += m;
|
||||
rgba.b += m;
|
||||
return rgba;
|
||||
return(rgba);
|
||||
}
|
||||
|
||||
//
|
||||
// Rectangle Operations
|
||||
//
|
||||
|
||||
inline i32_Rect
|
||||
i32R(int32_t l, int32_t t, int32_t r, int32_t b){
|
||||
i32_Rect rect;
|
||||
rect.x0 = l; rect.y0 = t;
|
||||
rect.x1 = r; rect.y1 = b;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline f32_Rect
|
||||
f32R(float l, float t, float r, float b){
|
||||
f32_Rect rect;
|
||||
rect.x0 = l; rect.y0 = t;
|
||||
rect.x1 = r; rect.y1 = b;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline f32_Rect
|
||||
f32R(i32_Rect r){
|
||||
f32_Rect rect;
|
||||
rect.x0 = (float)r.x0;
|
||||
rect.y0 = (float)r.y0;
|
||||
rect.x1 = (float)r.x1;
|
||||
rect.y1 = (float)r.y1;
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
rect_equal(i32_Rect r1, i32_Rect r2){
|
||||
int32_t result = (r1.x0 == r2.x0 && r1.y0 == r2.y0 && r1.x1 == r2.x1 && r1.y1 == r2.y1);
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
hit_check(int32_t x, int32_t y, int32_t x0, int32_t y0, int32_t x1, int32_t y1){
|
||||
return (x >= x0 && x < x1 && y >= y0 && y < y1);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
hit_check(int32_t x, int32_t y, i32_Rect rect){
|
||||
return (hit_check(x, y, rect.x0, rect.y0, rect.x1, rect.y1));
|
||||
}
|
||||
|
||||
inline i32_Rect
|
||||
get_inner_rect(i32_Rect outer, int32_t margin){
|
||||
i32_Rect r;
|
||||
r.x0 = outer.x0 + margin;
|
||||
r.y0 = outer.y0 + margin;
|
||||
r.x1 = outer.x1 - margin;
|
||||
r.y1 = outer.y1 - margin;
|
||||
return r;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -1,20 +1 @@
|
|||
#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)
|
||||
#define FILE_EXISTS_SIG(n) bool32 n(Application_Links *app, char *filename, int32_t len)
|
||||
#define DIRECTORY_CD_SIG(n) bool32 n(Application_Links *app, char *dir, int32_t *len, int32_t capacity, char *rel_path, int32_t rel_len)
|
||||
#define GET_4ED_PATH_SIG(n) int32_t n(Application_Links *app, char *out, int32_t capacity)
|
||||
#define SHOW_MOUSE_CURSOR_SIG(n) void n(Application_Links *app, Mouse_Cursor_Show_Type show)
|
||||
#define TOGGLE_FULLSCREEN_SIG(n) void n(Application_Links *app)
|
||||
#define IS_FULLSCREEN_SIG(n) bool32 n(Application_Links *app)
|
||||
#define SEND_EXIT_SIGNAL_SIG(n) void n(Application_Links *app)
|
||||
typedef MEMORY_ALLOCATE_SIG(Memory_Allocate_Function);
|
||||
typedef MEMORY_SET_PROTECTION_SIG(Memory_Set_Protection_Function);
|
||||
typedef MEMORY_FREE_SIG(Memory_Free_Function);
|
||||
typedef FILE_EXISTS_SIG(File_Exists_Function);
|
||||
typedef DIRECTORY_CD_SIG(Directory_CD_Function);
|
||||
typedef GET_4ED_PATH_SIG(Get_4ed_Path_Function);
|
||||
typedef SHOW_MOUSE_CURSOR_SIG(Show_Mouse_Cursor_Function);
|
||||
typedef TOGGLE_FULLSCREEN_SIG(Toggle_Fullscreen_Function);
|
||||
typedef IS_FULLSCREEN_SIG(Is_Fullscreen_Function);
|
||||
typedef SEND_EXIT_SIGNAL_SIG(Send_Exit_Signal_Function);
|
||||
struct Application_Links;
|
||||
|
|
|
@ -30,9 +30,9 @@ struct Render_Font{
|
|||
// TODO(allen): Have our own type here instead
|
||||
// of stbtt_packedchar, and have both stb fonts
|
||||
// and OS fonts go to our type.
|
||||
Glyph_Data glyphs[256];
|
||||
Glyph_Data glyphs[256];
|
||||
f32 advance_data[256];
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 advance;
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
|
@ -174,7 +174,12 @@ struct Render_Target{
|
|||
|
||||
inline i32_Rect
|
||||
rect_from_target(Render_Target *target){
|
||||
return i32R(0, 0, target->width, target->height);
|
||||
i32_Rect r;
|
||||
r.x0 = 0;
|
||||
r.y0 = 0;
|
||||
r.x1 = target->width;
|
||||
r.y1 = target->height;
|
||||
return(r);
|
||||
}
|
||||
|
||||
inline Font_Info*
|
||||
|
|
|
@ -9,6 +9,20 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#if 0
|
||||
inline i32_Rect
|
||||
i32_rect_zero(){
|
||||
i32_Rect rect={0};
|
||||
return(rect);
|
||||
}
|
||||
|
||||
inline f32_Rect
|
||||
f32_rect_zero(){
|
||||
f32_Rect rect={0};
|
||||
return(rect);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void
|
||||
draw_push_clip(Render_Target *target, i32_Rect clip_box){
|
||||
target->push_clip(target, clip_box);
|
||||
|
|
BIN
4ed_site.ctm
BIN
4ed_site.ctm
Binary file not shown.
58
4ed_system.h
58
4ed_system.h
|
@ -200,12 +200,42 @@ typedef Sys_Acquire_Lock_Sig(System_Acquire_Lock);
|
|||
#define Sys_Release_Lock_Sig(name) void name(i32 id)
|
||||
typedef Sys_Release_Lock_Sig(System_Release_Lock);
|
||||
|
||||
// needed for custom layer
|
||||
#define Sys_Memory_Allocate_Sig(name) void* name(i32 size)
|
||||
typedef Sys_Memory_Allocate_Sig(System_Memory_Allocate);
|
||||
|
||||
#define Sys_Memory_Set_Protection_Sig(name) bool32 name(void *ptr, i32 size, u32 flags)
|
||||
typedef Sys_Memory_Set_Protection_Sig(System_Memory_Set_Protection);
|
||||
|
||||
#define Sys_Memory_Free_Sig(name) void name(void *ptr, i32 size)
|
||||
typedef Sys_Memory_Free_Sig(System_Memory_Free);
|
||||
|
||||
#define Sys_File_Exists_Sig(name) b32 name(char *filename, i32 len)
|
||||
typedef Sys_File_Exists_Sig(System_File_Exists);
|
||||
|
||||
#define Sys_Directory_CD_Sig(name) bool32 name(char *dir, i32 *len, i32 cap, char *rel_path, i32 rel_len)
|
||||
typedef Sys_Directory_CD_Sig(System_Directory_CD);
|
||||
|
||||
#define Sys_Get_4ed_Path_Sig(name) int32_t name(char *out, i32 capacity)
|
||||
typedef Sys_Get_4ed_Path_Sig(System_Get_4ed_Path);
|
||||
|
||||
#define Sys_Show_Mouse_Cursor_Sig(name) void name(i32 show)
|
||||
typedef Sys_Show_Mouse_Cursor_Sig(System_Show_Mouse_Cursor);
|
||||
|
||||
#define Sys_Toggle_Fullscreen_Sig(name) b32 name()
|
||||
typedef Sys_Toggle_Fullscreen_Sig(System_Toggle_Fullscreen);
|
||||
|
||||
#define Sys_Is_Fullscreen_Sig(name) bool32 name()
|
||||
typedef Sys_Is_Fullscreen_Sig(System_Is_Fullscreen);
|
||||
|
||||
#define Sys_Send_Exit_Signal_Sig(name) void name()
|
||||
typedef Sys_Send_Exit_Signal_Sig(System_Send_Exit_Signal);
|
||||
|
||||
// debug
|
||||
#define INTERNAL_Sys_Get_Thread_States_Sig(name) void name(Thread_Group_ID id, b8 *running, i32 *pending)
|
||||
typedef INTERNAL_Sys_Get_Thread_States_Sig(INTERNAL_System_Get_Thread_States);
|
||||
|
||||
struct System_Functions{
|
||||
|
||||
// files (tracked api): 10
|
||||
System_Set_File_List *set_file_list;
|
||||
System_Get_Canonical *get_canonical;
|
||||
|
@ -221,18 +251,6 @@ struct System_Functions{
|
|||
// time: 1
|
||||
System_Now_Time *now_time;
|
||||
|
||||
// 4coder_custom.h: 7
|
||||
Memory_Allocate_Function *memory_allocate;
|
||||
Memory_Set_Protection_Function *memory_set_protection;
|
||||
Memory_Free_Function *memory_free;
|
||||
File_Exists_Function *file_exists;
|
||||
Directory_CD_Function *directory_cd;
|
||||
Get_4ed_Path_Function *get_4ed_path;
|
||||
Show_Mouse_Cursor_Function *show_mouse_cursor;
|
||||
Toggle_Fullscreen_Function *toggle_fullscreen;
|
||||
Is_Fullscreen_Function *is_fullscreen;
|
||||
Send_Exit_Signal_Function *send_exit_signal;
|
||||
|
||||
// clipboard: 1
|
||||
System_Post_Clipboard *post_clipboard;
|
||||
|
||||
|
@ -248,7 +266,7 @@ struct System_Functions{
|
|||
System_CLI_Update_Step *cli_update_step;
|
||||
System_CLI_End_Update *cli_end_update;
|
||||
|
||||
// threads: 7
|
||||
// threads: 6
|
||||
System_Post_Job *post_job;
|
||||
System_Cancel_Job *cancel_job;
|
||||
System_Check_Cancel *check_cancel;
|
||||
|
@ -256,6 +274,18 @@ struct System_Functions{
|
|||
System_Acquire_Lock *acquire_lock;
|
||||
System_Release_Lock *release_lock;
|
||||
|
||||
// custom: 10
|
||||
System_Memory_Allocate *memory_allocate;
|
||||
System_Memory_Set_Protection *memory_set_protection;
|
||||
System_Memory_Free *memory_free;
|
||||
System_File_Exists *file_exists;
|
||||
System_Directory_CD *directory_cd;
|
||||
System_Get_4ed_Path *get_4ed_path;
|
||||
System_Show_Mouse_Cursor *show_mouse_cursor;
|
||||
System_Toggle_Fullscreen *toggle_fullscreen;
|
||||
System_Is_Fullscreen *is_fullscreen;
|
||||
System_Send_Exit_Signal *send_exit_signal;
|
||||
|
||||
// debug: 1
|
||||
INTERNAL_System_Get_Thread_States *internal_get_thread_states;
|
||||
};
|
||||
|
|
|
@ -304,6 +304,12 @@ draw_push_piece_clip(Render_Target *target, i32_Rect clip_box){
|
|||
PutStruct(Render_Piece_Change_Clip, clip);
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
fits_inside(i32_Rect rect, i32_Rect outer){
|
||||
return (rect.x0 >= outer.x0 && rect.x1 <= outer.x1 &&
|
||||
rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
|
||||
}
|
||||
|
||||
internal void
|
||||
draw_push_clip(Render_Target *target, i32_Rect clip_box){
|
||||
Assert(target->clip_top == -1 ||
|
||||
|
@ -472,8 +478,7 @@ private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
|
|||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
|
||||
real32 x, real32 y, u32 color){
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, u32 color){
|
||||
private_draw_glyph_mono(target, font, character, x, y, (f32)font->advance, color);
|
||||
}
|
||||
|
||||
|
@ -656,7 +661,7 @@ stb_font_load(Partition *part,
|
|||
f32 *advance_data = font_out->advance_data;
|
||||
Glyph_Data *glyphs = font_out->glyphs;
|
||||
for (u8 code_point = 0; code_point < 128; ++code_point){
|
||||
advance_data[code_point] = (f32)(CEIL32(chardata[code_point].xadvance));
|
||||
advance_data[code_point] = (f32)(ceil32(chardata[code_point].xadvance));
|
||||
glyphs[code_point].x0 = chardata[code_point].x0;
|
||||
glyphs[code_point].y0 = chardata[code_point].y0;
|
||||
glyphs[code_point].x1 = chardata[code_point].x1;
|
||||
|
@ -680,7 +685,7 @@ stb_font_load(Partition *part,
|
|||
for (u8 code_point = 0; code_point < 128; ++code_point){
|
||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
||||
font_out->glyphs[code_point].exists = 1;
|
||||
i32 advance = CEIL32(advance_data[code_point]);
|
||||
i32 advance = ceil32(advance_data[code_point]);
|
||||
if (max_advance < advance){
|
||||
max_advance = advance;
|
||||
}
|
||||
|
@ -758,10 +763,10 @@ font_load_freetype(Partition *part,
|
|||
FT_Request_Size(face, &size);
|
||||
|
||||
rf->loaded = 1;
|
||||
rf->ascent = CEIL32 (face->size->metrics.ascender / 64.0f);
|
||||
rf->descent = FLOOR32 (face->size->metrics.descender / 64.0f);
|
||||
rf->advance = CEIL32 (face->size->metrics.max_advance / 64.0f);
|
||||
rf->height = CEIL32 (face->size->metrics.height / 64.0f);
|
||||
rf->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
|
||||
rf->descent = floor32 (face->size->metrics.descender / 64.0f);
|
||||
rf->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
|
||||
rf->height = ceil32 (face->size->metrics.height / 64.0f);
|
||||
rf->line_skip = rf->height - (rf->ascent - rf->descent);
|
||||
|
||||
rf->height -= rf->line_skip;
|
||||
|
@ -777,7 +782,7 @@ font_load_freetype(Partition *part,
|
|||
tex_width *= 2;
|
||||
float glyphs_per_row = ceilf(tex_width / (float) max_glyph_w);
|
||||
float rows = ceilf(NUM_GLYPHS / glyphs_per_row);
|
||||
tex_height = CEIL32(rows * (max_glyph_h + 2));
|
||||
tex_height = ceil32(rows * (max_glyph_h + 2));
|
||||
} while(tex_height > tex_width);
|
||||
|
||||
tex_height = next_pow_of_2(tex_height);
|
||||
|
@ -836,7 +841,7 @@ font_load_freetype(Partition *part,
|
|||
|
||||
// TODO(allen): maybe advance data should be integers for a while...
|
||||
// I require the actual values to be integers anyway... hmm...
|
||||
rf->advance_data[i] = (f32)CEIL32(face->glyph->advance.x / 64.0f);
|
||||
rf->advance_data[i] = (f32)ceil32(face->glyph->advance.x / 64.0f);
|
||||
|
||||
rf->glyphs[i].exists = 1;
|
||||
|
||||
|
@ -872,7 +877,7 @@ font_load_freetype(Partition *part,
|
|||
}
|
||||
}
|
||||
|
||||
pen_x = CEIL32(c->x1 + 1);
|
||||
pen_x = ceil32(c->x1 + 1);
|
||||
}
|
||||
|
||||
// TODO(allen): advance data is still too stupid.
|
||||
|
|
|
@ -19,7 +19,7 @@ struct File_Data{
|
|||
u32 size;
|
||||
b32 got_file;
|
||||
};
|
||||
globalvar File_Data null_file_data = {0};
|
||||
global File_Data null_file_data = {0};
|
||||
|
||||
#define Sys_Get_Memory_Sig(name) void* name(i32 size, i32 line_number, char *file_name)
|
||||
#define Sys_Free_Memory_Sig(name) void name(void *block)
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
4tech_defines.h - Standard defines across all 4tech projects.
|
||||
By Allen Webster
|
||||
Created 21.01.2017 (dd.mm.yyyy)
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FTECH_DEFINES)
|
||||
#define FTECH_DEFINES
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef i8 b8;
|
||||
typedef i32 b32;
|
||||
|
||||
// TODO(allen): Find a real way to detect 32 bit ness.
|
||||
#if defined(FTECH_32_BIT)
|
||||
typedef u32 umem;
|
||||
typedef i32 imem;
|
||||
#else
|
||||
typedef u64 umem;
|
||||
typedef i64 imem;
|
||||
#endif
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#define internal static
|
||||
#define local_persist static
|
||||
#define global static
|
||||
#define local_const static const
|
||||
#define global_const static const
|
||||
|
||||
#define ArrayCount(a) ((sizeof(a))/(sizeof(*a)))
|
||||
#define ExpandArray(a) (a), (ArrayCount(a))
|
||||
#define AllowLocal(c) (void)(c)
|
||||
|
||||
#if defined(Assert)
|
||||
# undef Assert
|
||||
#endif
|
||||
|
||||
#define Assert(c) do { if (!(c)) *((i32*)0) = 0xA11E; } while(0)
|
||||
#define TentativeAssert(c) Assert(c)
|
||||
#define InvalidCodePath Assert(!"Invalid Code Path!")
|
||||
#define NotImplemented Assert(!"Not Implemented!")
|
||||
|
||||
#define Swap(t,a,b) do { t x = a; a = b; b = x; } while(0)
|
||||
|
||||
#define Max(a,b) (((a)>(b))?(a):(b))
|
||||
#define Min(a,b) (((a)<(b))?(a):(b))
|
||||
|
||||
#define ceil32(v) (((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) ))
|
||||
|
||||
#define floor32(v) (((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) ))
|
||||
|
||||
#define round32(v) (floor32(v + 0.5f))
|
||||
|
||||
#define trunc32(v) (i32)(v)
|
||||
|
||||
#define div_ceil(n,d) ( ((n) % (d) != 0) + ((n) / (d)) )
|
||||
|
||||
#define l_round_up(x,b) ( ((x)+(b)-1) - (((x)+(b)-1)%(b)) )
|
||||
|
||||
#define STR__(s) #s
|
||||
#define STR_(s) STR__(s)
|
||||
|
||||
#define DrCase(PC) case PC: goto resumespot_##PC
|
||||
#define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; }
|
||||
#define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); }
|
||||
|
||||
#define Bytes(x) ((umem)x)
|
||||
#define KB(x) (((umem)x) << 10)
|
||||
#define MB(x) (((umem)x) << 20)
|
||||
#define GB(x) (((umem)x) << 30)
|
||||
#define TB(x) (((umem)x) << 40)
|
||||
|
||||
#define max_i8 ((i8)0x7F)
|
||||
#define max_i16 ((i16)0x7FFF)
|
||||
#define max_i32 ((i32)0x7FFFFFFF)
|
||||
#define max_i64 ((i64)0x7FFFFFFFFFFFFFFF)
|
||||
|
||||
#define min_i8 ((i8)0x80)
|
||||
#define min_i16 ((i16)0x8000)
|
||||
#define min_i32 ((i32)0x80000000)
|
||||
#define min_i64 ((i64)0x8000000000000000)
|
||||
|
||||
#define max_u8 ((u8)0xFF)
|
||||
#define max_u16 ((u16)0xFFFF)
|
||||
#define max_u32 ((u32)0xFFFFFFFF)
|
||||
#define max_u64 ((u64)0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
#define min_u8 ((u8)0)
|
||||
#define min_u16 ((u16)0)
|
||||
#define min_u32 ((u32)0)
|
||||
#define min_u64 ((u64)0)
|
||||
|
||||
#define Bit_0 (1 << 0)
|
||||
#define Bit_1 (1 << 1)
|
||||
#define Bit_2 (1 << 2)
|
||||
#define Bit_3 (1 << 3)
|
||||
#define Bit_4 (1 << 4)
|
||||
#define Bit_5 (1 << 5)
|
||||
#define Bit_6 (1 << 6)
|
||||
#define Bit_7 (1 << 7)
|
||||
|
||||
#define Bit_8 (1 << 8)
|
||||
#define Bit_9 (1 << 9)
|
||||
#define Bit_10 (1 << 10)
|
||||
#define Bit_11 (1 << 11)
|
||||
#define Bit_12 (1 << 12)
|
||||
#define Bit_13 (1 << 13)
|
||||
#define Bit_14 (1 << 14)
|
||||
#define Bit_15 (1 << 15)
|
||||
|
||||
#define Bit_16 (1 << 16)
|
||||
#define Bit_17 (1 << 17)
|
||||
#define Bit_18 (1 << 18)
|
||||
#define Bit_19 (1 << 19)
|
||||
#define Bit_20 (1 << 20)
|
||||
#define Bit_21 (1 << 21)
|
||||
#define Bit_22 (1 << 22)
|
||||
#define Bit_23 (1 << 23)
|
||||
|
||||
#define Bit_24 (1 << 24)
|
||||
#define Bit_25 (1 << 25)
|
||||
#define Bit_26 (1 << 26)
|
||||
#define Bit_27 (1 << 27)
|
||||
#define Bit_28 (1 << 28)
|
||||
#define Bit_29 (1 << 29)
|
||||
#define Bit_30 (1 << 30)
|
||||
#define Bit_31 (1 << 31)
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
Binary file not shown.
|
@ -25,5 +25,5 @@ call "print_size.bat" 4ed_app.dll
|
|||
call "print_size.bat" 4ed.exe
|
||||
popd
|
||||
|
||||
::END
|
||||
:END
|
||||
call "ctime" -end 4ed_data.ctm %FirstError%
|
||||
|
|
|
@ -17,7 +17,7 @@ REM default files no matter where you store your code.
|
|||
REM And no matter how you call buildsuper.bat.
|
||||
SET CODE_HOME=%~dp0
|
||||
|
||||
cl /I%CODE_HOME% %OPTS% %DEBUG% %SRC% /Fe4coder_custom %BUILD_DLL% %EXPORTS%
|
||||
cl /I%CODE_HOME% %OPTS% %DEBUG% %SRC% /Fecustom_4coder %BUILD_DLL% %EXPORTS%
|
||||
|
||||
REM file spammation preventation
|
||||
del *.exp
|
||||
|
|
|
@ -1,196 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 12.12.2014
|
||||
*
|
||||
* Meta setup for project codename "4ed"
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_DEFINES_H)
|
||||
#define FRED_DEFINES_H
|
||||
|
||||
#if !defined (FRED_TYPES)
|
||||
#include <stdint.h>
|
||||
#define FRED_TYPES
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
typedef i32 bool32;
|
||||
typedef i8 bool8;
|
||||
typedef i32 b32;
|
||||
typedef i16 b16;
|
||||
typedef i8 b8;
|
||||
|
||||
typedef float real32;
|
||||
typedef double real64;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#define internal static
|
||||
#define globalvar static
|
||||
#define persist static
|
||||
|
||||
#define globalconst static const
|
||||
#endif
|
||||
|
||||
#define COMP_ID_(a,b,c,d) (d << 24) | (c << 16) | (b << 8) | a
|
||||
#define COMPOSE_ID(a,b,c,d) (COMP_ID_((a),(b),(c),(d)))
|
||||
|
||||
#define S(X) #X
|
||||
#define S_(X) S(X)
|
||||
#define S__LINE__ S_(__LINE__)
|
||||
|
||||
#if FRED_INTERNAL || FRED_KEEP_ASSERT
|
||||
# define Assert(c) assert(c)
|
||||
#else
|
||||
# define Assert(c)
|
||||
#endif
|
||||
#define TentativeAssert(c) Assert(c)
|
||||
#define NotImplemented Assert(!"This is not implemented yet!")
|
||||
#define InvalidCodePath Assert(!"Invalid code path!")
|
||||
#define InvalidPath InvalidCodePath
|
||||
|
||||
#define AllowLocal(name) (void)name
|
||||
#ifndef ArrayCount
|
||||
# define ArrayCount(array) (sizeof(array)/sizeof(array[0]))
|
||||
#endif
|
||||
|
||||
#define OffsetOfStruct(S,c) ((i64)(& ((S*)0)->c ))
|
||||
|
||||
#define Swap(T,a,b) do{ T t = a; a = b; b = t; } while(0)
|
||||
|
||||
#define Min(a,b) (((a)<(b))?(a):(b))
|
||||
#define Max(a,b) (((a)>(b))?(a):(b))
|
||||
|
||||
#define TMax(t,v) globalconst t max_##t = v
|
||||
TMax(u8, 255);
|
||||
TMax(u16, 65535);
|
||||
TMax(u32, 4294967295);
|
||||
TMax(u64, 18446744073709551615U);
|
||||
|
||||
TMax(i8, 127);
|
||||
TMax(i16, 32767);
|
||||
TMax(i32, 2147483647);
|
||||
TMax(i64, 9223372036854775807);
|
||||
#undef TMax
|
||||
|
||||
#define TMin(t) globalconst t min_##t = 0
|
||||
TMin(u8);
|
||||
TMin(u16);
|
||||
TMin(u32);
|
||||
TMin(u64);
|
||||
#undef TMin
|
||||
|
||||
#define TMin(t,v) globalconst t min_##t = ((t)(v))
|
||||
TMin(i8, -127-1);
|
||||
TMin(i16, -32767-1);
|
||||
TMin(i32, -2147483647-1);
|
||||
TMin(i64, -9223372036854775807-1);
|
||||
#undef TMin
|
||||
|
||||
#define Bit_0 (1 << 0)
|
||||
#define Bit_1 (1 << 1)
|
||||
#define Bit_2 (1 << 2)
|
||||
#define Bit_3 (1 << 3)
|
||||
#define Bit_4 (1 << 4)
|
||||
#define Bit_5 (1 << 5)
|
||||
#define Bit_6 (1 << 6)
|
||||
#define Bit_7 (1 << 7)
|
||||
|
||||
#define Bit_8 (1 << 8)
|
||||
#define Bit_9 (1 << 9)
|
||||
#define Bit_10 (1 << 10)
|
||||
#define Bit_11 (1 << 11)
|
||||
#define Bit_12 (1 << 12)
|
||||
#define Bit_13 (1 << 13)
|
||||
#define Bit_14 (1 << 14)
|
||||
#define Bit_15 (1 << 15)
|
||||
|
||||
#define Bit_16 (1 << 16)
|
||||
#define Bit_17 (1 << 17)
|
||||
#define Bit_18 (1 << 18)
|
||||
#define Bit_19 (1 << 19)
|
||||
#define Bit_20 (1 << 20)
|
||||
#define Bit_21 (1 << 21)
|
||||
#define Bit_22 (1 << 22)
|
||||
#define Bit_23 (1 << 23)
|
||||
|
||||
#define Bit_24 (1 << 24)
|
||||
#define Bit_25 (1 << 25)
|
||||
#define Bit_26 (1 << 26)
|
||||
#define Bit_27 (1 << 27)
|
||||
#define Bit_28 (1 << 28)
|
||||
#define Bit_29 (1 << 29)
|
||||
#define Bit_30 (1 << 30)
|
||||
#define Bit_31 (1 << 31)
|
||||
|
||||
#define bytes(n) (n)
|
||||
#define Kbytes(n) ((n) << 10)
|
||||
#define Mbytes(n) ((n) << 20)
|
||||
#define Gbytes(n) (((u64)n) << 30)
|
||||
#define Tbytes(n) (((u64)n) << 40)
|
||||
|
||||
//
|
||||
// Rounding
|
||||
//
|
||||
|
||||
internal u32
|
||||
l_round_up_u32(u32 x, u32 granularity){
|
||||
u32 new_x = x + granularity - 1;
|
||||
new_x = new_x - (new_x % granularity);
|
||||
return(new_x);
|
||||
}
|
||||
|
||||
internal i32
|
||||
l_round_up_i32(i32 x, i32 granularity){
|
||||
i32 new_x = (i32)l_round_up_u32((u32)x, (u32)granularity);
|
||||
return(new_x);
|
||||
}
|
||||
|
||||
inline i32
|
||||
TRUNC32(real32 x) { return (i32)x; }
|
||||
|
||||
inline i32
|
||||
FLOOR32(real32 x) { return (i32)(x)-((x!=(i32)(x) && x<0)?1:0); }
|
||||
|
||||
inline i32
|
||||
CEIL32(real32 x) { return (i32)(x)+((x!=(i32)(x) && x>0)?1:0); }
|
||||
|
||||
inline i32
|
||||
ROUND32(real32 x) { return FLOOR32(x + .5f); }
|
||||
|
||||
inline i32
|
||||
DIVCEIL32(i32 n, i32 d) {
|
||||
i32 q = (n/d);
|
||||
return q + (q*d < n);
|
||||
}
|
||||
|
||||
inline real32
|
||||
FRACPART32(real32 x) { return x - (i32)x; }
|
||||
|
||||
inline u32
|
||||
ROUNDPOT32(u32 v){
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -13,11 +13,7 @@
|
|||
// Buffer low level operations
|
||||
//
|
||||
|
||||
// TODO(allen): Put 4coder_seek_types into the file directory.
|
||||
// Setup a meta system for putting together a file in the custom
|
||||
// code directory from the export structs and helpers.
|
||||
|
||||
#include "../4coder_seek_types.h"
|
||||
#include "../4coder_helper/4coder_seek_types.h"
|
||||
|
||||
typedef struct Cursor_With_Index{
|
||||
i32 pos;
|
||||
|
@ -506,7 +502,7 @@ buffer_replace_range(Gap_Buffer *buffer, i32 start, i32 end, char *str, i32 len,
|
|||
assert(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max);
|
||||
}
|
||||
else{
|
||||
*request_amount = l_round_up_u32(2*(*shift_amount + size), 4 << 10);
|
||||
*request_amount = l_round_up(2*(*shift_amount + size), 4 << 10);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
|
@ -1201,7 +1197,7 @@ buffer_get_line_index_from_character_pos(i32 *character_starts, i32 pos, i32 l_b
|
|||
|
||||
inline i32
|
||||
buffer_get_line_index_from_wrapped_y(i32 *wrap_line_index, f32 y, f32 line_height, i32 l_bound, i32 u_bound){
|
||||
i32 wrap_index = FLOOR32(y/line_height);
|
||||
i32 wrap_index = floor32(y/line_height);
|
||||
i32 i = binary_search(wrap_line_index, wrap_index, l_bound, u_bound);
|
||||
return(i);
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 03.01.2017
|
||||
*
|
||||
* File layer for 4coder
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "../common/4ed_defines.h"
|
||||
|
||||
#include "4coder_buffer.cpp"
|
||||
#include "4coder_undo.cpp"
|
||||
|
||||
int main(){
|
||||
return(0);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
@echo off
|
||||
|
||||
SET OPTS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /wd4390 /WX
|
||||
SET OPTS=%OPTS% /GR- /EHa- /nologo /FC
|
||||
|
||||
pushd ..\build
|
||||
cl %OPTS% ..\code\file\4coder_file_tests.cpp /Zi /Fefile_test
|
||||
popd
|
||||
|
||||
if %ERRORLEVEL% eq 0 (..\build\file_test)
|
||||
|
115
linux_4ed.cpp
115
linux_4ed.cpp
|
@ -12,50 +12,23 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "common/4coder_defines.h"
|
||||
#include "common/4coder_version.h"
|
||||
#include "4tech_defines.h"
|
||||
#include "4coder_API/version.h"
|
||||
|
||||
#if FRED_SUPER
|
||||
#if defined(FRED_SUPER)
|
||||
# include "4coder_API/keycodes.h"
|
||||
# include "4coder_API/style.h"
|
||||
|
||||
# define FSTRING_IMPLEMENTATION
|
||||
# define FSTRING_C
|
||||
# include "4coder_string.h"
|
||||
# include "4coder_lib/4coder_string.h"
|
||||
# include "4coder_lib/4coder_mem.h"
|
||||
|
||||
# include "4coder_keycodes.h"
|
||||
# include "4coder_style.h"
|
||||
# include "4coder_rect.h"
|
||||
|
||||
# include "4coder_mem.h"
|
||||
|
||||
// TODO(allen): This is duplicated from 4coder_custom.h
|
||||
// I need to work out a way to avoid this.
|
||||
#define VIEW_ROUTINE_SIG(name) void name(struct Application_Links *app, int32_t view_id)
|
||||
#define GET_BINDING_DATA(name) int32_t name(void *data, int32_t size)
|
||||
#define _GET_VERSION_SIG(n) int32_t n(int32_t maj, int32_t min, int32_t patch)
|
||||
|
||||
typedef VIEW_ROUTINE_SIG(View_Routine_Function);
|
||||
typedef GET_BINDING_DATA(Get_Binding_Data_Function);
|
||||
typedef _GET_VERSION_SIG(_Get_Version_Function);
|
||||
|
||||
struct Custom_API{
|
||||
View_Routine_Function *view_routine;
|
||||
Get_Binding_Data_Function *get_bindings;
|
||||
_Get_Version_Function *get_alpha_4coder_version;
|
||||
};
|
||||
|
||||
|
||||
typedef void Custom_Command_Function;
|
||||
#include "4coder_types.h"
|
||||
struct Application_Links;
|
||||
# include "4coder_API/types.h"
|
||||
# include "4ed_os_custom_api.h"
|
||||
|
||||
#else
|
||||
# include "4coder_default_bindings.cpp"
|
||||
|
||||
# define FSTRING_IMPLEMENTATION
|
||||
# define FSTRING_C
|
||||
# include "4coder_string.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include "4ed_math.h"
|
||||
|
@ -252,8 +225,8 @@ struct Linux_Vars{
|
|||
// Linux globals
|
||||
//
|
||||
|
||||
globalvar Linux_Vars linuxvars;
|
||||
globalvar Application_Memory memory_vars;
|
||||
global Linux_Vars linuxvars;
|
||||
global Application_Memory memory_vars;
|
||||
|
||||
//
|
||||
// Linux forward declarations
|
||||
|
@ -601,11 +574,11 @@ Sys_Now_Time_Sig(system_now_time){
|
|||
}
|
||||
|
||||
//
|
||||
// 4coder_custom.h
|
||||
// custom.h
|
||||
//
|
||||
|
||||
internal
|
||||
MEMORY_ALLOCATE_SIG(system_memory_allocate){
|
||||
Sys_Memory_Allocate_Sig(system_memory_allocate){
|
||||
// NOTE(allen): This must return the exact base of the vpage.
|
||||
// We will count on the user to keep track of size themselves.
|
||||
void *result = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
@ -617,7 +590,7 @@ MEMORY_ALLOCATE_SIG(system_memory_allocate){
|
|||
}
|
||||
|
||||
internal
|
||||
MEMORY_SET_PROTECTION_SIG(system_memory_set_protection){
|
||||
Sys_Memory_Set_Protection_Sig(system_memory_set_protection){
|
||||
// NOTE(allen):
|
||||
// There is no such thing as "write only" in windows
|
||||
// so I just made write = write + read in all cases.
|
||||
|
@ -658,13 +631,13 @@ MEMORY_SET_PROTECTION_SIG(system_memory_set_protection){
|
|||
}
|
||||
|
||||
internal
|
||||
MEMORY_FREE_SIG(system_memory_free){
|
||||
Sys_Memory_Free_Sig(system_memory_free){
|
||||
// NOTE(allen): This must take the exact base of the vpage.
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
internal
|
||||
FILE_EXISTS_SIG(system_file_exists){
|
||||
Sys_File_Exists_Sig(system_file_exists){
|
||||
int result = 0;
|
||||
char buff[PATH_MAX] = {};
|
||||
|
||||
|
@ -683,8 +656,8 @@ FILE_EXISTS_SIG(system_file_exists){
|
|||
}
|
||||
|
||||
internal
|
||||
DIRECTORY_CD_SIG(system_directory_cd){
|
||||
String directory = make_string_cap(dir, *len, capacity);
|
||||
Sys_Directory_CD_Sig(system_directory_cd){
|
||||
String directory = make_string_cap(dir, *len, cap);
|
||||
b32 result = 0;
|
||||
i32 old_size;
|
||||
|
||||
|
@ -722,24 +695,26 @@ DIRECTORY_CD_SIG(system_directory_cd){
|
|||
}
|
||||
|
||||
internal
|
||||
GET_4ED_PATH_SIG(system_get_4ed_path){
|
||||
Sys_Get_4ed_Path_Sig(system_get_4ed_path){
|
||||
String str = make_string_cap(out, 0, capacity);
|
||||
return(system_get_binary_path(&str));
|
||||
}
|
||||
|
||||
internal
|
||||
SHOW_MOUSE_CURSOR_SIG(system_show_mouse_cursor){
|
||||
Sys_Show_Mouse_Cursor_Sig(system_show_mouse_cursor){
|
||||
linuxvars.hide_cursor = !show;
|
||||
XDefineCursor(linuxvars.XDisplay, linuxvars.XWindow, show ? None : linuxvars.hidden_cursor);
|
||||
}
|
||||
|
||||
internal
|
||||
TOGGLE_FULLSCREEN_SIG(system_toggle_fullscreen){
|
||||
Sys_Toggle_Fullscreen_Sig(system_toggle_fullscreen){
|
||||
b32 success = true;
|
||||
LinuxToggleFullscreen(linuxvars.XDisplay, linuxvars.XWindow);
|
||||
return(success);
|
||||
}
|
||||
|
||||
internal
|
||||
IS_FULLSCREEN_SIG(system_is_fullscreen){
|
||||
Sys_Is_Fullscreen_Sig(system_is_fullscreen){
|
||||
b32 result = 0;
|
||||
|
||||
Atom type, *prop;
|
||||
|
@ -765,7 +740,7 @@ IS_FULLSCREEN_SIG(system_is_fullscreen){
|
|||
}
|
||||
|
||||
internal
|
||||
SEND_EXIT_SIGNAL_SIG(system_send_exit_signal){
|
||||
Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
|
||||
linuxvars.keep_running = 0;
|
||||
}
|
||||
|
||||
|
@ -1020,7 +995,7 @@ JobThreadProc(void* lpParameter){
|
|||
Thread_Memory *thread_memory = linuxvars.thread_memory + thread_index;
|
||||
|
||||
if (thread_memory->size == 0){
|
||||
i32 new_size = Kbytes(64);
|
||||
i32 new_size = KB(64);
|
||||
thread_memory->data = LinuxGetMemory(new_size);
|
||||
thread_memory->size = new_size;
|
||||
}
|
||||
|
@ -1285,7 +1260,7 @@ Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
|
|||
system_acquire_lock(CANCEL_LOCK0 + memory->id - 1);
|
||||
old_data = memory->data;
|
||||
old_size = memory->size;
|
||||
new_size = LargeRoundUp(memory->size*2, Kbytes(4));
|
||||
new_size = l_round_up(memory->size*2, KB(4));
|
||||
memory->data = system_get_memory(new_size);
|
||||
memory->size = new_size;
|
||||
if (old_data){
|
||||
|
@ -1358,13 +1333,13 @@ Font_Load_Sig(system_draw_font_load){
|
|||
LINUX_FN_DEBUG("%s, %dpt, tab_width: %d", filename, pt_size, tab_width);
|
||||
|
||||
if (linuxvars.font_part.base == 0){
|
||||
linuxvars.font_part = sysshared_scratch_partition(Mbytes(8));
|
||||
linuxvars.font_part = sysshared_scratch_partition(MB(8));
|
||||
}
|
||||
|
||||
i32 oversample = 2;
|
||||
|
||||
#if SUPPORT_DPI
|
||||
pt_size = ROUND32(pt_size * size_change(linuxvars.dpi_x, linuxvars.dpi_y));
|
||||
pt_size = round32(pt_size * size_change(linuxvars.dpi_x, linuxvars.dpi_y));
|
||||
#endif
|
||||
|
||||
for(; attempts < 3; ++attempts){
|
||||
|
@ -1444,7 +1419,7 @@ LinuxLoadSystemCode(){
|
|||
// time
|
||||
linuxvars.system.now_time = system_now_time;
|
||||
|
||||
// 4coder_custom.h
|
||||
// custom.h
|
||||
linuxvars.system.memory_allocate = system_memory_allocate;
|
||||
linuxvars.system.memory_set_protection = system_memory_set_protection;
|
||||
linuxvars.system.memory_free = system_memory_free;
|
||||
|
@ -1911,7 +1886,7 @@ LinuxInputInit(Display *dpy, Window XWindow)
|
|||
// Keyboard handling funcs
|
||||
//
|
||||
|
||||
globalvar u8 keycode_lookup_table[255];
|
||||
global u8 keycode_lookup_table[255];
|
||||
|
||||
internal void
|
||||
LinuxKeycodeInit(Display* dpy){
|
||||
|
@ -2979,14 +2954,14 @@ main(int argc, char **argv)
|
|||
LinuxLoadSystemCode();
|
||||
LinuxLoadRenderCode();
|
||||
|
||||
memory_vars.vars_memory_size = Mbytes(2);
|
||||
memory_vars.vars_memory_size = MB(2);
|
||||
memory_vars.vars_memory = system_get_memory(memory_vars.vars_memory_size);
|
||||
memory_vars.target_memory_size = Mbytes(512);
|
||||
memory_vars.target_memory_size = MB(512);
|
||||
memory_vars.target_memory = system_get_memory(memory_vars.target_memory_size);
|
||||
memory_vars.user_memory_size = Mbytes(2);
|
||||
memory_vars.user_memory_size = MB(2);
|
||||
memory_vars.user_memory = system_get_memory(memory_vars.user_memory_size);
|
||||
|
||||
linuxvars.target.max = Mbytes(1);
|
||||
linuxvars.target.max = MB(1);
|
||||
linuxvars.target.push_buffer = (char*)system_get_memory(linuxvars.target.max);
|
||||
|
||||
if(memory_vars.vars_memory == NULL || memory_vars.target_memory == NULL || memory_vars.user_memory == NULL || linuxvars.target.push_buffer == NULL){
|
||||
|
@ -3043,7 +3018,7 @@ main(int argc, char **argv)
|
|||
|
||||
#ifdef FRED_SUPER
|
||||
|
||||
char *custom_file_default = "4coder_custom.so";
|
||||
char *custom_file_default = "custom_4coder.so";
|
||||
sysshared_to_binary_path(&base_dir, custom_file_default);
|
||||
custom_file_default = base_dir.str;
|
||||
|
||||
|
@ -3067,23 +3042,21 @@ main(int argc, char **argv)
|
|||
|
||||
if (linuxvars.custom_api.get_alpha_4coder_version == 0 ||
|
||||
linuxvars.custom_api.get_alpha_4coder_version(MAJOR, MINOR, PATCH) == 0){
|
||||
LinuxFatalErrorMsg("Failed to load '4coder_custom.so': Version mismatch. Try rebuilding it with 'buildsuper.sh'.");
|
||||
LinuxFatalErrorMsg("Failed to load 'custom_4coder.so': Version mismatch. Try rebuilding it with 'buildsuper.sh'.");
|
||||
exit(1);
|
||||
}
|
||||
else{
|
||||
linuxvars.custom_api.get_bindings = (Get_Binding_Data_Function*)
|
||||
dlsym(linuxvars.custom, "get_bindings");
|
||||
linuxvars.custom_api.view_routine = (View_Routine_Function*)
|
||||
dlsym(linuxvars.custom, "view_routine");
|
||||
|
||||
if (linuxvars.custom_api.get_bindings == 0){
|
||||
LinuxFatalErrorMsg("Failed to load '4coder_custom.so': "
|
||||
LinuxFatalErrorMsg("Failed to load 'custom_4coder.so': "
|
||||
"It does not export the required 'get_bindings' function. "
|
||||
"Try rebuilding it with 'buildsuper.sh'.");
|
||||
exit(1);
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "Successfully loaded 4coder_custom.so\n");
|
||||
fprintf(stderr, "Successfully loaded custom_4coder.so\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -3091,7 +3064,7 @@ main(int argc, char **argv)
|
|||
const char* error = dlerror();
|
||||
snprintf(buf, sizeof(buf), "Error loading custom: %s. "
|
||||
"Make sure this file is in the same directory as the main '4ed' executable.",
|
||||
error ? error : "'4coder_custom.so' missing");
|
||||
error ? error : "'custom_4coder.so' missing");
|
||||
LinuxFatalErrorMsg(buf);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -3099,14 +3072,6 @@ main(int argc, char **argv)
|
|||
linuxvars.custom_api.get_bindings = get_bindings;
|
||||
#endif
|
||||
|
||||
linuxvars.custom_api.view_routine = 0;
|
||||
|
||||
#if 0
|
||||
if (linuxvars.custom_api.view_routine == 0){
|
||||
linuxvars.custom_api.view_routine = view_routine;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Coroutine / Thread / Semaphore / Mutex init
|
||||
//
|
||||
|
@ -3116,7 +3081,7 @@ main(int argc, char **argv)
|
|||
linuxvars.coroutine_data[i].next = linuxvars.coroutine_data + i + 1;
|
||||
}
|
||||
|
||||
const size_t stack_size = Mbytes(2);
|
||||
const size_t stack_size = MB(2);
|
||||
for (i32 i = 0; i < ArrayCount(linuxvars.coroutine_data); ++i){
|
||||
linuxvars.coroutine_data[i].stack.ss_size = stack_size;
|
||||
linuxvars.coroutine_data[i].stack.ss_sp = system_get_memory(stack_size);
|
||||
|
|
|
@ -9,21 +9,24 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#include "../common/4coder_defines.h"
|
||||
#include "../common/4coder_version.h"
|
||||
#define KEYCODES_FILE "4coder_API/keycodes.h"
|
||||
#define STYLE_FILE "4coder_API/style.h"
|
||||
|
||||
#if !defined(FSTRING_GUARD)
|
||||
#include "../internal_4coder_string.cpp"
|
||||
#endif
|
||||
#define API_H "4coder_API/app_functions.h"
|
||||
#define OS_API_H "4ed_os_custom_api.h"
|
||||
|
||||
#include "../4cpp_lexer.h"
|
||||
#include "4tech_meta_defines.h"
|
||||
#include "../4coder_API/version.h"
|
||||
|
||||
#define FSTRING_IMPLEMENTATION
|
||||
#include "../4coder_lib/4coder_string.h"
|
||||
#include "../4coder_lib/4coder_mem.h"
|
||||
|
||||
#include "../4cpp/4cpp_lexer.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../4coder_mem.h"
|
||||
|
||||
#include "meta_parser.cpp"
|
||||
#include "out_context.cpp"
|
||||
|
@ -69,7 +72,7 @@ char *keys_that_need_codes[] = {
|
|||
|
||||
void
|
||||
generate_keycode_enum(){
|
||||
char *filename_keycodes = "4coder_keycodes.h";
|
||||
char *filename_keycodes = KEYCODES_FILE;
|
||||
Out_Context context = {0};
|
||||
int32_t i = 0, count = 0;
|
||||
unsigned char code = 1;
|
||||
|
@ -196,7 +199,7 @@ make_style_tag(char *tag){
|
|||
|
||||
static void
|
||||
generate_style(){
|
||||
char filename_4coder[] = "4coder_style.h";
|
||||
char filename_4coder[] = STYLE_FILE;
|
||||
char filename_4ed[] = "4ed_style.h";
|
||||
char *tag = 0;
|
||||
int32_t count = 0, i = 0;
|
||||
|
@ -377,9 +380,7 @@ allocate_app_api(Partition *part, int32_t count){
|
|||
|
||||
static void
|
||||
generate_custom_headers(){
|
||||
#define API_H "4coder_custom_api.h"
|
||||
#define OS_API_H "4ed_os_custom_api.h"
|
||||
#define STRING_H "4coder_string.h"
|
||||
META_BEGIN();
|
||||
|
||||
int32_t size = (512 << 20);
|
||||
void *mem = malloc(size);
|
||||
|
@ -401,24 +402,12 @@ generate_custom_headers(){
|
|||
|
||||
#define ExpandArray(a) (a), (ArrayCount(a))
|
||||
|
||||
// NOTE(allen): Parse the internal string file.
|
||||
static char *string_files[] = {
|
||||
"internal_4coder_string.cpp",
|
||||
0
|
||||
};
|
||||
|
||||
Meta_Unit string_unit = compile_meta_unit(part, ".", string_files, ExpandArray(meta_keywords));
|
||||
|
||||
|
||||
// NOTE(allen): Parse the customization API files
|
||||
static char *functions_files[] = {
|
||||
"4ed_api_implementation.cpp",
|
||||
"win32_api_impl.cpp",
|
||||
0
|
||||
};
|
||||
|
||||
static char *functions_files[] = { "4ed_api_implementation.cpp", 0 };
|
||||
Meta_Unit unit_custom = compile_meta_unit(part, ".", functions_files, ExpandArray(meta_keywords));
|
||||
|
||||
if (unit_custom.parse == 0){
|
||||
Assert(!"Missing one or more input files!");
|
||||
}
|
||||
|
||||
// NOTE(allen): Compute and store variations of the function names
|
||||
App_API func_4ed_names = allocate_app_api(part, unit_custom.set.count);
|
||||
|
@ -446,6 +435,8 @@ generate_custom_headers(){
|
|||
if (begin_file_out(&context, OS_API_H, &out)){
|
||||
int32_t main_api_count = unit_custom.parse[0].item_count;
|
||||
int32_t os_api_count = unit_custom.parse[1].item_count;
|
||||
append_sc(&out, "struct Application_Links;\n");
|
||||
|
||||
for (int32_t i = main_api_count; i < os_api_count; ++i){
|
||||
append_sc(&out, "#define ");
|
||||
append_ss(&out, func_4ed_names.names[i].macro);
|
||||
|
@ -471,6 +462,8 @@ generate_custom_headers(){
|
|||
}
|
||||
|
||||
if (begin_file_out(&context, API_H, &out)){
|
||||
append_sc(&out, "struct Application_Links;\n");
|
||||
|
||||
for (int32_t i = 0; i < unit_custom.set.count; ++i){
|
||||
append_sc(&out, "#define ");
|
||||
append_ss(&out, func_4ed_names.names[i].macro);
|
||||
|
@ -586,212 +579,7 @@ generate_custom_headers(){
|
|||
// TODO(allen): warning
|
||||
}
|
||||
|
||||
// NOTE(allen): String Library
|
||||
if (begin_file_out(&context, STRING_H, &out)){
|
||||
Cpp_Token *token = 0;
|
||||
int32_t start = 0;
|
||||
|
||||
Parse parse = string_unit.parse[0];
|
||||
Parse_Context pcontext = setup_parse_context(parse);
|
||||
|
||||
for (; (token = get_token(&pcontext)) != 0; get_next_token(&pcontext)){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY) &&
|
||||
token->type == CPP_TOKEN_IDENTIFIER){
|
||||
String lexeme = get_lexeme(*token, pcontext.data);
|
||||
if (match_ss(lexeme, make_lit_string("FSTRING_BEGIN"))){
|
||||
start = token->start + token->size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String pstr = {0};
|
||||
int32_t do_whitespace_print = true;
|
||||
|
||||
for(;(token = get_next_token(&pcontext)) != 0;){
|
||||
if (do_whitespace_print){
|
||||
pstr = str_start_end(pcontext.data, start, token->start);
|
||||
append_ss(&out, pstr);
|
||||
}
|
||||
else{
|
||||
do_whitespace_print = true;
|
||||
}
|
||||
|
||||
String lexeme = get_lexeme(*token, pcontext.data);
|
||||
|
||||
int32_t do_print = true;
|
||||
if (match_ss(lexeme, make_lit_string("FSTRING_DECLS"))){
|
||||
append_sc(&out, "#if !defined(FCODER_STRING_H)\n#define FCODER_STRING_H\n\n");
|
||||
do_print = false;
|
||||
|
||||
static int32_t SIG_PADDING = 35;
|
||||
|
||||
for (int32_t j = 0; j < string_unit.set.count; ++j){
|
||||
char line_[2048];
|
||||
String line = make_fixed_width_string(line_);
|
||||
Item_Node *item = string_unit.set.items + j;
|
||||
|
||||
if (item->t == Item_Function){
|
||||
//append_ss (&line, item->marker);
|
||||
//append_padding (&line, ' ', RETURN_PADDING);
|
||||
append_ss (&line, item->ret);
|
||||
append_padding (&line, ' ', SIG_PADDING);
|
||||
append_ss (&line, item->name);
|
||||
append_ss (&line, item->args);
|
||||
append_sc (&line, ";\n");
|
||||
}
|
||||
else if (item->t == Item_Macro){
|
||||
append_ss (&line, make_lit_string("#ifndef "));
|
||||
append_padding (&line, ' ', 10);
|
||||
append_ss (&line, item->name);
|
||||
append_s_char (&line, '\n');
|
||||
|
||||
append_ss (&line, make_lit_string("# define "));
|
||||
append_padding (&line, ' ', 10);
|
||||
append_ss (&line, item->name);
|
||||
append_ss (&line, item->args);
|
||||
append_s_char (&line, ' ');
|
||||
append_ss (&line, item->body);
|
||||
append_s_char (&line, '\n');
|
||||
|
||||
append_ss (&line, make_lit_string("#endif"));
|
||||
append_s_char (&line, '\n');
|
||||
}
|
||||
else{
|
||||
InvalidPath;
|
||||
}
|
||||
|
||||
append_ss(&out, line);
|
||||
}
|
||||
|
||||
append_sc(&out, "\n#endif\n");
|
||||
|
||||
// NOTE(allen): C++ overload definitions
|
||||
append_sc(&out, "\n#if !defined(FSTRING_C) && !defined(FSTRING_GUARD)\n\n");
|
||||
|
||||
for (int32_t j = 0; j < string_unit.set.count; ++j){
|
||||
char line_space[2048];
|
||||
String line = make_fixed_width_string(line_space);
|
||||
|
||||
Item_Node *item = &string_unit.set.items[j];
|
||||
|
||||
if (item->t == Item_Function){
|
||||
String cpp_name = item->cpp_name;
|
||||
if (cpp_name.str != 0){
|
||||
Argument_Breakdown breakdown = item->breakdown;
|
||||
|
||||
append_ss (&line, item->ret);
|
||||
append_padding(&line, ' ', SIG_PADDING);
|
||||
append_ss (&line, cpp_name);
|
||||
append_ss (&line, item->args);
|
||||
if (match_ss(item->ret, make_lit_string("void"))){
|
||||
append_ss(&line, make_lit_string("{("));
|
||||
}
|
||||
else{
|
||||
append_ss(&line, make_lit_string("{return("));
|
||||
}
|
||||
append_ss (&line, item->name);
|
||||
append_s_char(&line, '(');
|
||||
|
||||
if (breakdown.count > 0){
|
||||
for (int32_t i = 0; i < breakdown.count; ++i){
|
||||
if (i != 0){
|
||||
append_s_char(&line, ',');
|
||||
}
|
||||
append_ss(&line, breakdown.args[i].param_name);
|
||||
}
|
||||
}
|
||||
else{
|
||||
append_ss(&line, make_lit_string("void"));
|
||||
}
|
||||
|
||||
append_ss(&line, make_lit_string("));}\n"));
|
||||
|
||||
append_ss(&out, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
append_sc(&out, "\n#endif\n");
|
||||
}
|
||||
|
||||
else if (match_ss(lexeme, make_lit_string("API_EXPORT_MACRO"))){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_COMMENT){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_PP_DEFINE){
|
||||
for (;(token = get_next_token(&pcontext)) != 0;){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (token != 0){
|
||||
get_prev_token(&pcontext);
|
||||
}
|
||||
do_print = false;
|
||||
do_whitespace_print = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (match_ss(lexeme, make_lit_string("API_EXPORT")) ||
|
||||
match_ss(lexeme, make_lit_string("API_EXPORT_INLINE"))){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
if (match_ss(lexeme, make_lit_string("API_EXPORT_INLINE"))){
|
||||
append_sc(&out, "#if !defined(FSTRING_GUARD)\n");
|
||||
}
|
||||
else{
|
||||
append_sc(&out, "#if defined(FSTRING_IMPLEMENTATION)\n");
|
||||
}
|
||||
print_function_body_code(&out, &pcontext, start);
|
||||
append_sc(&out, "\n#endif");
|
||||
do_print = false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (match_ss(lexeme, make_lit_string("CPP_NAME"))){
|
||||
Cpp_Token *token_start = token;
|
||||
int32_t has_cpp_name = false;
|
||||
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_PARENTHESE_OPEN){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_IDENTIFIER){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_PARENTHESE_CLOSE){
|
||||
has_cpp_name = true;
|
||||
do_print = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_cpp_name){
|
||||
token = set_token(&pcontext, token_start);
|
||||
}
|
||||
}
|
||||
|
||||
else if (token->type == CPP_TOKEN_COMMENT){
|
||||
if (check_and_fix_docs(&lexeme)){
|
||||
do_print = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((token = get_token(&pcontext)) != 0){
|
||||
if (do_print){
|
||||
pstr = get_lexeme(*token, pcontext.data);
|
||||
append_ss(&out, pstr);
|
||||
}
|
||||
start = token->start + token->size;
|
||||
}
|
||||
}
|
||||
pstr = str_start_end(pcontext.data, start, parse.code.size);
|
||||
append_ss(&out, pstr);
|
||||
|
||||
end_file_out(context);
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning
|
||||
}
|
||||
META_FINISH();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
|
|
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
4tech_file_moving.h - Code for moving files around on the file system.
|
||||
By Allen Webster
|
||||
21.01.2017 (dd.mm.yyyy)
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FTECH_FILE_MOVING_H)
|
||||
#define FTECH_FILE_MOVING_H
|
||||
|
||||
#include <stdio.h> // include system for windows
|
||||
#include <stdlib.h> // include system for linux (YAY!)
|
||||
|
||||
// NOTE(allen): Compiler/OS cracking.
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
# define IS_CL
|
||||
# define snprintf _snprintf
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define IS_WINDOWS
|
||||
# pragma comment(lib, "Kernel32.lib")
|
||||
# else
|
||||
# error This compiler/platform combo is not supported yet
|
||||
# endif
|
||||
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
|
||||
# define IS_GCC
|
||||
|
||||
# if defined(__gnu_linux__)
|
||||
# define IS_LINUX
|
||||
# else
|
||||
# error This compiler/platform combo is not supported yet
|
||||
# endif
|
||||
|
||||
#else
|
||||
#error This compiler is not supported yet
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
# define ONLY_WINDOWS(x) x
|
||||
# define ONLY_LINUX(x) (void)0
|
||||
|
||||
#define SLASH "\\"
|
||||
static char platform_correct_slash = '\\';
|
||||
|
||||
#elif defined(IS_LINUX)
|
||||
# define ONLY_WINDOWS(x) (void)0
|
||||
# define ONLY_LINUX(x) x
|
||||
|
||||
#define SLASH "/"
|
||||
static char platform_correct_slash = '/';
|
||||
|
||||
#else
|
||||
# define ONLY_WINDOWS(x) (void)0
|
||||
# define ONLY_LINUX(x) (void)0
|
||||
|
||||
#define SLASH "/"
|
||||
static char platform_correct_slash = '/';
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static char cmd[4096];
|
||||
static i32 error_state = 0;
|
||||
static i32 prev_error = 0;
|
||||
|
||||
#define systemf(...) do{ \
|
||||
int32_t n = snprintf(cmd, sizeof(cmd), __VA_ARGS__); \
|
||||
AllowLocal(n); \
|
||||
Assert(n < sizeof(cmd)); \
|
||||
prev_error = system(cmd); \
|
||||
if (prev_error != 0) error_state = 1; \
|
||||
}while(0)
|
||||
|
||||
static void init_time_system();
|
||||
static u64 get_time();
|
||||
static i32 get_current_directory(char *buffer, i32 max);
|
||||
static void execute_in_dir(char *dir, char *str, char *args);
|
||||
|
||||
static void make_folder_if_missing(char *dir, char *folder);
|
||||
static void clear_folder(char *folder);
|
||||
static void delete_file(char *file);
|
||||
static void copy_file(char *path, char *file, char *folder1, char *folder2, char *newname);
|
||||
static void copy_all(char *source, char *tag, char *folder);
|
||||
static void zip(char *parent, char *folder, char *dest);
|
||||
|
||||
static void slash_fix(char *path);
|
||||
#define DECL_STR(n,s) char n[] = s; slash_fix(n)
|
||||
|
||||
typedef struct Temp_Dir{
|
||||
char dir[512];
|
||||
} Temp_Dir;
|
||||
|
||||
static Temp_Dir pushdir(char *dir);
|
||||
static void popdir(Temp_Dir temp);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(FTECH_FILE_MOVING_IMPLEMENTATION) && !defined(FTECH_FILE_MOVING_IMPL_GUARD)
|
||||
#define FTECH_FILE_MOVING_IMPL_GUARD
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
|
||||
typedef uint32_t DWORD;
|
||||
typedef int32_t LONG;
|
||||
typedef int64_t LONGLONG;
|
||||
typedef char* LPTSTR;
|
||||
typedef char* LPCTSTR;
|
||||
typedef int32_t BOOL;
|
||||
typedef void* LPSECURITY_ATTRIBUTES;
|
||||
typedef union _LARGE_INTEGER {
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
};
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
} u;
|
||||
LONGLONG QuadPart;
|
||||
} LARGE_INTEGER, *PLARGE_INTEGER;
|
||||
|
||||
#define WINAPI
|
||||
|
||||
extern "C"{
|
||||
DWORD WINAPI GetCurrentDirectoryA(_In_ DWORD nBufferLength, _Out_ LPTSTR lpBuffer);
|
||||
BOOL WINAPI SetCurrentDirectoryA(_In_ LPCTSTR lpPathName);
|
||||
|
||||
BOOL WINAPI QueryPerformanceCounter(_Out_ LARGE_INTEGER *lpPerformanceCount);
|
||||
|
||||
BOOL WINAPI QueryPerformanceFrequency(_Out_ LARGE_INTEGER *lpFrequency);
|
||||
|
||||
BOOL WINAPI CreateDirectoryA(_In_ LPCTSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes);
|
||||
|
||||
BOOL WINAPI CopyFileA(_In_ LPCTSTR lpExistingFileName, _In_ LPCTSTR lpNewFileName, _In_ BOOL bFailIfExists);
|
||||
}
|
||||
|
||||
static uint64_t perf_frequency;
|
||||
|
||||
static Temp_Dir
|
||||
pushdir(char *dir){
|
||||
Temp_Dir temp = {0};
|
||||
GetCurrentDirectoryA(sizeof(temp.dir), temp.dir);
|
||||
SetCurrentDirectoryA(dir);
|
||||
return(temp);
|
||||
}
|
||||
|
||||
static void
|
||||
popdir(Temp_Dir temp){
|
||||
SetCurrentDirectoryA(temp.dir);
|
||||
}
|
||||
|
||||
static void
|
||||
init_time_system(){
|
||||
LARGE_INTEGER lint;
|
||||
if (QueryPerformanceFrequency(&lint)){
|
||||
perf_frequency = lint.QuadPart;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
get_time(){
|
||||
uint64_t time = 0;
|
||||
LARGE_INTEGER lint;
|
||||
if (QueryPerformanceCounter(&lint)){
|
||||
time = lint.QuadPart;
|
||||
time = (time * 1000000) / perf_frequency;
|
||||
}
|
||||
return(time);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
get_current_directory(char *buffer, int32_t max){
|
||||
int32_t result = GetCurrentDirectoryA(max, buffer);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
execute_in_dir(char *dir, char *str, char *args){
|
||||
if (dir){
|
||||
Temp_Dir temp = pushdir(dir);
|
||||
if (args){
|
||||
systemf("call \"%s\" %s", str, args);
|
||||
}
|
||||
else{
|
||||
systemf("call \"%s\"", str);
|
||||
}
|
||||
popdir(temp);
|
||||
}
|
||||
else{
|
||||
if (args){
|
||||
systemf("call \"%s\" %s", str, args);
|
||||
}
|
||||
else{
|
||||
systemf("call \"%s\"", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
slash_fix(char *path){
|
||||
if (path){
|
||||
for (int32_t i = 0; path[i]; ++i){
|
||||
if (path[i] == '/') path[i] = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
make_folder_if_missing(char *dir, char *folder){
|
||||
char space[1024];
|
||||
String path = make_fixed_width_string(space);
|
||||
append_sc(&path, dir);
|
||||
if (folder){
|
||||
append_sc(&path, "\\");
|
||||
append_sc(&path, folder);
|
||||
}
|
||||
terminate_with_null(&path);
|
||||
|
||||
char *p = path.str;
|
||||
for (; *p; ++p){
|
||||
if (*p == '\\'){
|
||||
*p = 0;
|
||||
CreateDirectoryA(path.str, 0);
|
||||
*p = '\\';
|
||||
}
|
||||
}
|
||||
CreateDirectoryA(path.str, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_folder(char *folder){
|
||||
systemf("del /S /Q /F %s\\* & rmdir /S /Q %s & mkdir %s",
|
||||
folder, folder, folder);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_file(char *file){
|
||||
systemf("del %s", file);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_file(char *path, char *file, char *folder1, char *folder2, char *newname){
|
||||
char src[256], dst[256];
|
||||
String b = make_fixed_width_string(src);
|
||||
if (path){
|
||||
append_sc(&b, path);
|
||||
append_sc(&b, "\\");
|
||||
}
|
||||
append_sc(&b, file);
|
||||
terminate_with_null(&b);
|
||||
|
||||
b = make_fixed_width_string(dst);
|
||||
append_sc(&b, folder1);
|
||||
append_sc(&b, "\\");
|
||||
if (folder2){
|
||||
append_sc(&b, folder2);
|
||||
append_sc(&b, "\\");
|
||||
}
|
||||
if (newname){
|
||||
append_sc(&b, newname);
|
||||
}
|
||||
else{
|
||||
append_sc(&b, file);
|
||||
}
|
||||
terminate_with_null(&b);
|
||||
|
||||
CopyFileA(src, dst, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_all(char *source, char *tag, char *folder){
|
||||
if (source){
|
||||
systemf("copy %s\\%s %s\\*", source, tag, folder);
|
||||
}
|
||||
else{
|
||||
systemf("copy %s %s\\*", tag, folder);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zip(char *parent, char *folder, char *dest){
|
||||
char cdir[512];
|
||||
get_current_directory(cdir, sizeof(cdir));
|
||||
|
||||
Temp_Dir temp = pushdir(parent);
|
||||
systemf("%s\\zip %s\\4tech_gobble.zip", cdir, cdir);
|
||||
popdir(temp);
|
||||
|
||||
systemf("copy %s\\4tech_gobble.zip %s & del %s\\4tech_gobble.zip", cdir, dest, cdir);
|
||||
}
|
||||
|
||||
#elif defined(IS_LINUX)
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static Temp_Dir
|
||||
pushdir(char *dir){
|
||||
Temp_Dir temp;
|
||||
char *result = getcwd(temp.dir, sizeof(temp.dir));
|
||||
int32_t chresult = chdir(dir);
|
||||
if (result == 0 || chresult != 0){
|
||||
printf("trying pushdir %s\n", dir);
|
||||
assert(result != 0);
|
||||
assert(chresult == 0);
|
||||
}
|
||||
return(temp);
|
||||
}
|
||||
|
||||
static void
|
||||
popdir(Temp_Dir temp){
|
||||
chdir(temp.dir);
|
||||
}
|
||||
|
||||
static void
|
||||
init_time_system(){
|
||||
// NOTE(allen): do nothing
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
get_time(){
|
||||
struct timespec spec;
|
||||
uint64_t result;
|
||||
clock_gettime(CLOCK_MONOTONIC, &spec);
|
||||
result = (spec.tv_sec * (uint64_t)(1000000)) + (spec.tv_nsec / (uint64_t)(1000));
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
get_current_directory(char *buffer, int32_t max){
|
||||
int32_t result = 0;
|
||||
char *d = getcwd(buffer, max);
|
||||
if (d == buffer){
|
||||
result = strlen(buffer);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
execute_in_dir(char *dir, char *str, char *args){
|
||||
if (dir){
|
||||
if (args){
|
||||
Temp_Dir temp = pushdir(dir);
|
||||
systemf("%s %s", str, args);
|
||||
popdir(temp);
|
||||
}
|
||||
else{
|
||||
Temp_Dir temp = pushdir(dir);
|
||||
systemf("%s", str);
|
||||
popdir(temp);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (args){
|
||||
systemf("%s %s", str, args);
|
||||
}
|
||||
else{
|
||||
systemf("%s", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
slash_fix(char *path){}
|
||||
|
||||
static void
|
||||
make_folder_if_missing(char *dir, char *folder){
|
||||
if (folder){
|
||||
systemf("mkdir -p %s/%s", dir, folder);
|
||||
}
|
||||
else{
|
||||
systemf("mkdir -p %s", dir);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_folder(char *folder){
|
||||
systemf("rm -rf %s*", folder);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_file(char *file){
|
||||
systemf("rm %s", file);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_file(char *path, char *file, char *folder1, char *folder2, char *newname){
|
||||
if (!newname){
|
||||
newname = file;
|
||||
}
|
||||
|
||||
if (path){
|
||||
if (folder2){
|
||||
systemf("cp %s/%s %s/%s/%s", path, file, folder1, folder2, newname);
|
||||
}
|
||||
else{
|
||||
systemf("cp %s/%s %s/%s", path, file, folder1, newname);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (folder2){
|
||||
systemf("cp %s %s/%s/%s", file, folder1, folder2, newname);
|
||||
}
|
||||
else{
|
||||
systemf("cp %s %s/%s", file, folder1, newname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_all(char *source, char *tag, char *folder){
|
||||
if (source){
|
||||
systemf("cp -rf %s/%s %s", source, tag, folder);
|
||||
}
|
||||
else{
|
||||
systemf("cp -rf %s %s", tag, folder);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zip(char *parent, char *folder, char *file){
|
||||
Temp_Dir temp = pushdir(parent);
|
||||
systemf("zip -r %s %s", file, folder);
|
||||
popdir(temp);
|
||||
}
|
||||
|
||||
#else
|
||||
#error This OS is not supported yet
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
4tech_meta_defines.h - Header to setup metaprograms.
|
||||
By Allen Webster
|
||||
Created 21.01.2017 (dd.mm.yyyy)
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FTECH_META_DEFINES_H)
|
||||
#define FTECH_META_DEFINES_H
|
||||
|
||||
#include "../4tech_defines.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
|
||||
global jmp_buf META_ASSERT_ENV;
|
||||
global char* META_ASSERT_MSG;
|
||||
|
||||
internal void
|
||||
__meta_finish__(){
|
||||
if (META_ASSERT_MSG != 0){
|
||||
printf("%s\n", META_ASSERT_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
#define META_FINISH() } __META_FINISH__: __meta_finish__()
|
||||
|
||||
#define LINE_STR STR_(__LINE__)
|
||||
|
||||
#if defined(Assert)
|
||||
# undef Assert
|
||||
#endif
|
||||
|
||||
#define Assert(c) do { if (!(c)) { META_ASSERT_MSG = __FILE__":"LINE_STR": "#c; longjmp(META_ASSERT_ENV, 1); } } while(0)
|
||||
|
||||
#define META_BEGIN() META_ASSERT_MSG = 0; if (setjmp(META_ASSERT_ENV) == 1){ goto __META_FINISH__; } {
|
||||
|
||||
char STANDARD_DISCLAIMER[] =
|
||||
"no warranty implied; use at your own risk\n"
|
||||
"\n"
|
||||
"This software is in the public domain. Where that dedication is not\n"
|
||||
"recognized, you are granted a perpetual, irrevocable license to copy,\n"
|
||||
"distribute, and modify this file as you see fit.\n\n";
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
503
meta/build.cpp
503
meta/build.cpp
|
@ -4,16 +4,16 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#include <stdio.h> // include system for windows
|
||||
#include <stdlib.h> // include system for linux (YAY!)
|
||||
#include <stdint.h>
|
||||
#include "../4tech_defines.h"
|
||||
#include "4tech_file_moving.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/4coder_version.h"
|
||||
#include "../4coder_API/version.h"
|
||||
|
||||
#define FSTRING_INLINE static
|
||||
#include "../internal_4coder_string.cpp"
|
||||
#define FSTRING_IMPLEMENTATION
|
||||
#include "../4coder_lib/4coder_string.h"
|
||||
|
||||
//
|
||||
// reusable
|
||||
|
@ -21,397 +21,6 @@
|
|||
|
||||
#define IS_64BIT
|
||||
|
||||
// NOTE(allen): Compiler/OS cracking.
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
# define IS_CL
|
||||
# define snprintf _snprintf
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define IS_WINDOWS
|
||||
# pragma comment(lib, "Kernel32.lib")
|
||||
# else
|
||||
# error This compiler/platform combo is not supported yet
|
||||
# endif
|
||||
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
|
||||
# define IS_GCC
|
||||
|
||||
# if defined(__gnu_linux__)
|
||||
# define IS_LINUX
|
||||
# else
|
||||
# error This compiler/platform combo is not supported yet
|
||||
# endif
|
||||
|
||||
#else
|
||||
#error This compiler is not supported yet
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
# define ONLY_WINDOWS(x) x
|
||||
# define ONLY_LINUX(x) (void)0
|
||||
#elif defined(IS_LINUX)
|
||||
# define ONLY_WINDOWS(x) (void)0
|
||||
# define ONLY_LINUX(x) x
|
||||
#else
|
||||
# define ONLY_WIN(x) (void)0
|
||||
# define ONLY_LINUX(x) (void)0
|
||||
#endif
|
||||
|
||||
|
||||
static char cmd[4096];
|
||||
static int32_t error_state = 0;
|
||||
static int32_t prev_error = 0;
|
||||
|
||||
#define systemf(...) do{ \
|
||||
int32_t n = snprintf(cmd, sizeof(cmd), __VA_ARGS__); \
|
||||
assert(n < sizeof(cmd)); \
|
||||
prev_error = system(cmd); \
|
||||
if (prev_error != 0) error_state = 1; \
|
||||
}while(0)
|
||||
|
||||
static void init_time_system();
|
||||
static uint64_t get_time();
|
||||
static int32_t get_current_directory(char *buffer, int32_t max);
|
||||
static void execute_in_dir(char *dir, char *str, char *args);
|
||||
|
||||
static void make_folder_if_missing(char *dir, char *folder);
|
||||
static void clear_folder(char *folder);
|
||||
static void copy_file(char *path, char *file, char *folder1, char *folder2, char *newname);
|
||||
static void copy_all(char *source, char *tag, char *folder);
|
||||
static void zip(char *parent, char *folder, char *dest);
|
||||
|
||||
typedef struct Temp_Dir{
|
||||
char dir[512];
|
||||
} Temp_Dir;
|
||||
|
||||
static Temp_Dir pushdir(char *dir);
|
||||
static void popdir(Temp_Dir temp);
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
|
||||
typedef uint32_t DWORD;
|
||||
typedef int32_t LONG;
|
||||
typedef int64_t LONGLONG;
|
||||
typedef char* LPTSTR;
|
||||
typedef char* LPCTSTR;
|
||||
typedef int32_t BOOL;
|
||||
typedef void* LPSECURITY_ATTRIBUTES;
|
||||
typedef union _LARGE_INTEGER {
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
};
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
} u;
|
||||
LONGLONG QuadPart;
|
||||
} LARGE_INTEGER, *PLARGE_INTEGER;
|
||||
|
||||
#if defined(IS_64BIT)
|
||||
# define WINAPI
|
||||
#endif
|
||||
|
||||
extern "C"{
|
||||
DWORD WINAPI GetCurrentDirectoryA(_In_ DWORD nBufferLength, _Out_ LPTSTR lpBuffer);
|
||||
BOOL WINAPI SetCurrentDirectoryA(_In_ LPCTSTR lpPathName);
|
||||
|
||||
BOOL WINAPI QueryPerformanceCounter(_Out_ LARGE_INTEGER *lpPerformanceCount);
|
||||
|
||||
BOOL WINAPI QueryPerformanceFrequency(_Out_ LARGE_INTEGER *lpFrequency);
|
||||
|
||||
BOOL WINAPI CreateDirectoryA(_In_ LPCTSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes);
|
||||
|
||||
BOOL WINAPI CopyFileA(_In_ LPCTSTR lpExistingFileName, _In_ LPCTSTR lpNewFileName, _In_ BOOL bFailIfExists);
|
||||
}
|
||||
|
||||
static uint64_t perf_frequency;
|
||||
|
||||
static Temp_Dir
|
||||
pushdir(char *dir){
|
||||
Temp_Dir temp = {0};
|
||||
GetCurrentDirectoryA(sizeof(temp.dir), temp.dir);
|
||||
SetCurrentDirectoryA(dir);
|
||||
return(temp);
|
||||
}
|
||||
|
||||
static void
|
||||
popdir(Temp_Dir temp){
|
||||
SetCurrentDirectoryA(temp.dir);
|
||||
}
|
||||
|
||||
static void
|
||||
init_time_system(){
|
||||
LARGE_INTEGER lint;
|
||||
if (QueryPerformanceFrequency(&lint)){
|
||||
perf_frequency = lint.QuadPart;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
get_time(){
|
||||
uint64_t time = 0;
|
||||
LARGE_INTEGER lint;
|
||||
if (QueryPerformanceCounter(&lint)){
|
||||
time = lint.QuadPart;
|
||||
time = (time * 1000000) / perf_frequency;
|
||||
}
|
||||
return(time);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
get_current_directory(char *buffer, int32_t max){
|
||||
int32_t result = GetCurrentDirectoryA(max, buffer);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
execute_in_dir(char *dir, char *str, char *args){
|
||||
if (dir){
|
||||
Temp_Dir temp = pushdir(dir);
|
||||
if (args){
|
||||
systemf("call \"%s\" %s", str, args);
|
||||
}
|
||||
else{
|
||||
systemf("call \"%s\"", str);
|
||||
}
|
||||
popdir(temp);
|
||||
}
|
||||
else{
|
||||
if (args){
|
||||
systemf("call \"%s\" %s", str, args);
|
||||
}
|
||||
else{
|
||||
systemf("call \"%s\"", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
slash_fix(char *path){
|
||||
if (path){
|
||||
for (int32_t i = 0; path[i]; ++i){
|
||||
if (path[i] == '/') path[i] = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
make_folder_if_missing(char *dir, char *folder){
|
||||
char space[1024];
|
||||
String path = make_fixed_width_string(space);
|
||||
append_sc(&path, dir);
|
||||
if (folder){
|
||||
append_sc(&path, "\\");
|
||||
append_sc(&path, folder);
|
||||
}
|
||||
terminate_with_null(&path);
|
||||
|
||||
char *p = path.str;
|
||||
for (; *p; ++p){
|
||||
if (*p == '\\'){
|
||||
*p = 0;
|
||||
CreateDirectoryA(path.str, 0);
|
||||
*p = '\\';
|
||||
}
|
||||
}
|
||||
CreateDirectoryA(path.str, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_folder(char *folder){
|
||||
systemf("del /S /Q /F %s\\* & rmdir /S /Q %s & mkdir %s",
|
||||
folder, folder, folder);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_file(char *path, char *file, char *folder1, char *folder2, char *newname){
|
||||
char src[256], dst[256];
|
||||
String b = make_fixed_width_string(src);
|
||||
if (path){
|
||||
append_sc(&b, path);
|
||||
append_sc(&b, "\\");
|
||||
}
|
||||
append_sc(&b, file);
|
||||
terminate_with_null(&b);
|
||||
|
||||
b = make_fixed_width_string(dst);
|
||||
append_sc(&b, folder1);
|
||||
append_sc(&b, "\\");
|
||||
if (folder2){
|
||||
append_sc(&b, folder2);
|
||||
append_sc(&b, "\\");
|
||||
}
|
||||
if (newname){
|
||||
append_sc(&b, newname);
|
||||
}
|
||||
else{
|
||||
append_sc(&b, file);
|
||||
}
|
||||
terminate_with_null(&b);
|
||||
|
||||
CopyFileA(src, dst, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_all(char *source, char *tag, char *folder){
|
||||
if (source){
|
||||
systemf("copy %s\\%s %s\\*", source, tag, folder);
|
||||
}
|
||||
else{
|
||||
systemf("copy %s %s\\*", tag, folder);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zip(char *parent, char *folder, char *dest){
|
||||
char cdir[512];
|
||||
get_current_directory(cdir, sizeof(cdir));
|
||||
|
||||
Temp_Dir temp = pushdir(parent);
|
||||
systemf("%s\\zip %s\\4tech_gobble.zip", cdir, cdir);
|
||||
popdir(temp);
|
||||
|
||||
systemf("copy %s\\4tech_gobble.zip %s & del %s\\4tech_gobble.zip", cdir, dest, cdir);
|
||||
}
|
||||
|
||||
#elif defined(IS_LINUX)
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static Temp_Dir
|
||||
pushdir(char *dir){
|
||||
Temp_Dir temp;
|
||||
char *result = getcwd(temp.dir, sizeof(temp.dir));
|
||||
int32_t chresult = chdir(dir);
|
||||
if (result == 0 || chresult != 0){
|
||||
printf("trying pushdir %s\n", dir);
|
||||
assert(result != 0);
|
||||
assert(chresult == 0);
|
||||
}
|
||||
return(temp);
|
||||
}
|
||||
|
||||
static void
|
||||
popdir(Temp_Dir temp){
|
||||
chdir(temp.dir);
|
||||
}
|
||||
|
||||
static void
|
||||
init_time_system(){
|
||||
// NOTE(allen): do nothing
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
get_time(){
|
||||
struct timespec spec;
|
||||
uint64_t result;
|
||||
clock_gettime(CLOCK_MONOTONIC, &spec);
|
||||
result = (spec.tv_sec * (uint64_t)(1000000)) + (spec.tv_nsec / (uint64_t)(1000));
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
get_current_directory(char *buffer, int32_t max){
|
||||
int32_t result = 0;
|
||||
char *d = getcwd(buffer, max);
|
||||
if (d == buffer){
|
||||
result = strlen(buffer);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
execute_in_dir(char *dir, char *str, char *args){
|
||||
if (dir){
|
||||
if (args){
|
||||
Temp_Dir temp = pushdir(dir);
|
||||
systemf("%s %s", str, args);
|
||||
popdir(temp);
|
||||
}
|
||||
else{
|
||||
Temp_Dir temp = pushdir(dir);
|
||||
systemf("%s", str);
|
||||
popdir(temp);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (args){
|
||||
systemf("%s %s", str, args);
|
||||
}
|
||||
else{
|
||||
systemf("%s", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
slash_fix(char *path){}
|
||||
|
||||
static void
|
||||
make_folder_if_missing(char *dir, char *folder){
|
||||
if (folder){
|
||||
systemf("mkdir -p %s/%s", dir, folder);
|
||||
}
|
||||
else{
|
||||
systemf("mkdir -p %s", dir);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_folder(char *folder){
|
||||
systemf("rm -rf %s*", folder);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_file(char *path, char *file, char *folder1, char *folder2, char *newname){
|
||||
if (!newname){
|
||||
newname = file;
|
||||
}
|
||||
|
||||
if (path){
|
||||
if (folder2){
|
||||
systemf("cp %s/%s %s/%s/%s", path, file, folder1, folder2, newname);
|
||||
}
|
||||
else{
|
||||
systemf("cp %s/%s %s/%s", path, file, folder1, newname);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (folder2){
|
||||
systemf("cp %s %s/%s/%s", file, folder1, folder2, newname);
|
||||
}
|
||||
else{
|
||||
systemf("cp %s %s/%s", file, folder1, newname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_all(char *source, char *tag, char *folder){
|
||||
if (source){
|
||||
systemf("cp -rf %s/%s %s", source, tag, folder);
|
||||
}
|
||||
else{
|
||||
systemf("cp -rf %s %s", tag, folder);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zip(char *parent, char *folder, char *file){
|
||||
Temp_Dir temp = pushdir(parent);
|
||||
systemf("zip -r %s %s", file, folder);
|
||||
popdir(temp);
|
||||
}
|
||||
|
||||
#else
|
||||
#error This OS is not supported yet
|
||||
#endif
|
||||
|
||||
#define BEGIN_TIME_SECTION() uint64_t start = get_time()
|
||||
#define END_TIME_SECTION(n) uint64_t total = get_time() - start; printf("%-20s: %.2lu.%.6lu\n", (n), total/1000000, total%1000000);
|
||||
|
||||
|
@ -480,7 +89,7 @@ typedef struct Build_Line{
|
|||
char build_optionsB[BUILD_LINE_MAX];
|
||||
char *build_options;
|
||||
char *build_options_prev;
|
||||
int32_t build_max;
|
||||
i32 build_max;
|
||||
} Build_Line;
|
||||
|
||||
static void
|
||||
|
@ -504,21 +113,18 @@ init_build_line(Build_Line *line){
|
|||
|
||||
#elif defined(IS_GCC)
|
||||
|
||||
#define build_ap(line, str, ...) do{ \
|
||||
snprintf(line.build_options, \
|
||||
line.build_max, "%s "str, \
|
||||
line.build_options_prev, ##__VA_ARGS__);\
|
||||
swap_ptr(&line.build_options, \
|
||||
&line.build_options_prev); \
|
||||
#define build_ap(line, str, ...) do{ \
|
||||
snprintf(line.build_options, line.build_max, "%s "str, \
|
||||
line.build_options_prev, ##__VA_ARGS__); \
|
||||
swap_ptr(&line.build_options, &line.build_options_prev); \
|
||||
}while(0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define CL_OPTS \
|
||||
"/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 " \
|
||||
"/wd4127 /wd4510 /wd4512 /wd4610 /wd4390 /WX " \
|
||||
"/GR- /EHa- /nologo /FC"
|
||||
"-W4 -wd4310 -wd4100 -wd4201 -wd4505 -wd4996 " \
|
||||
"-wd4127 -wd4510 -wd4512 -wd4610 -wd4390 " \
|
||||
"-wd4611 -WX -GR- -EHa- -nologo -FC"
|
||||
|
||||
#define CL_INCLUDES "/I..\\foreign /I..\\foreign\\freetype2"
|
||||
|
||||
|
@ -531,7 +137,7 @@ init_build_line(Build_Line *line){
|
|||
#define CL_ICON "..\\res\\icon.res"
|
||||
|
||||
static void
|
||||
build_cl(uint32_t flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){
|
||||
build_cl(u32 flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){
|
||||
Build_Line line;
|
||||
init_build_line(&line);
|
||||
|
||||
|
@ -609,7 +215,7 @@ build_cl(uint32_t flags, char *code_path, char *code_file, char *out_path, char
|
|||
"-lGL -ldl -lXfixes -lfreetype -lfontconfig"
|
||||
|
||||
static void
|
||||
build_gcc(uint32_t flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){
|
||||
build_gcc(u32 flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){
|
||||
Build_Line line;
|
||||
init_build_line(&line);
|
||||
|
||||
|
@ -620,7 +226,7 @@ build_gcc(uint32_t flags, char *code_path, char *code_file, char *out_path, char
|
|||
if (flags & INCLUDES){
|
||||
// TODO(allen): Abstract this out.
|
||||
#if defined(IS_LINUX)
|
||||
int32_t size = 0;
|
||||
i32 size = 0;
|
||||
char freetype_include[512];
|
||||
FILE *file = popen("pkg-config --cflags freetype2", "r");
|
||||
if (file != 0){
|
||||
|
@ -676,7 +282,7 @@ build_gcc(uint32_t flags, char *code_path, char *code_file, char *out_path, char
|
|||
}
|
||||
|
||||
static void
|
||||
build(uint32_t flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){
|
||||
build(u32 flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){
|
||||
#if defined(IS_CL)
|
||||
build_cl(flags, code_path, code_file, out_path, out_file, exports);
|
||||
#elif defined(IS_GCC)
|
||||
|
@ -728,8 +334,6 @@ buildsuper(char *code_path, char *out_path, char *filename){
|
|||
#error No platform layer defined for this OS.
|
||||
#endif
|
||||
|
||||
#define DECL_STR(n,s) char n[] = s; slash_fix(n)
|
||||
|
||||
static void
|
||||
fsm_generator(char *cdir){
|
||||
{
|
||||
|
@ -777,7 +381,7 @@ enum{
|
|||
};
|
||||
|
||||
static void
|
||||
do_buildsuper(char *cdir, int32_t custom_option){
|
||||
do_buildsuper(char *cdir, i32 custom_option){
|
||||
char space[1024];
|
||||
String str = make_fixed_width_string(space);
|
||||
|
||||
|
@ -818,7 +422,7 @@ do_buildsuper(char *cdir, int32_t custom_option){
|
|||
}
|
||||
|
||||
static void
|
||||
build_main(char *cdir, uint32_t flags){
|
||||
build_main(char *cdir, u32 flags){
|
||||
DECL_STR(dir, BUILD_DIR);
|
||||
{
|
||||
DECL_STR(file, "4ed_app_target.cpp");
|
||||
|
@ -835,7 +439,9 @@ build_main(char *cdir, uint32_t flags){
|
|||
}
|
||||
|
||||
static void
|
||||
standard_build(char *cdir, uint32_t flags){
|
||||
standard_build(char *cdir, u32 flags){
|
||||
//run_update("4coder_string.h");
|
||||
//run_update("4cpp/4cpp_lexer.h 4cpp/4cpp_lexer.h 4cpp/4cpp_lexer.h");
|
||||
fsm_generator(cdir);
|
||||
metagen(cdir);
|
||||
do_buildsuper(cdir, Custom_Experiments);
|
||||
|
@ -844,7 +450,7 @@ standard_build(char *cdir, uint32_t flags){
|
|||
}
|
||||
|
||||
static void
|
||||
site_build(char *cdir, uint32_t flags){
|
||||
site_build(char *cdir, u32 flags){
|
||||
{
|
||||
DECL_STR(file, "site/sitegen.cpp");
|
||||
DECL_STR(dir, BUILD_DIR"/site");
|
||||
|
@ -857,14 +463,14 @@ site_build(char *cdir, uint32_t flags){
|
|||
BEGIN_TIME_SECTION();
|
||||
|
||||
DECL_STR(cmd, "../build/site/sitegen . ../site_resources site/source_material ../site");
|
||||
systemf(cmd);
|
||||
systemf("%s", cmd);
|
||||
|
||||
END_TIME_SECTION("run sitegen");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_4coder_dist_name(String *zip_file, int32_t OS_specific, char *tier, char *ext){
|
||||
get_4coder_dist_name(String *zip_file, i32 OS_specific, char *tier, char *ext){
|
||||
zip_file->size = 0;
|
||||
|
||||
append_sc(zip_file, PACK_DIR"/");
|
||||
|
@ -927,13 +533,13 @@ package(char *cdir){
|
|||
make_folder_if_missing(pack_alpha_dir, "3rdparty");
|
||||
make_folder_if_missing(pack_dir, "alpha");
|
||||
copy_file(build_dir, "4ed"EXE, pack_alpha_dir, 0, 0);
|
||||
ONLY_WINDOWS(copy_file(build_dir, "4ed"PDB, pack_alpha_dir, 0, 0));
|
||||
//ONLY_WINDOWS(copy_file(build_dir, "4ed"PDB, pack_alpha_dir, 0, 0));
|
||||
copy_file(build_dir, "4ed_app"DLL, pack_alpha_dir, 0, 0);
|
||||
ONLY_WINDOWS(copy_file(build_dir, "4ed_app"PDB, pack_alpha_dir, 0, 0));
|
||||
//ONLY_WINDOWS(copy_file(build_dir, "4ed_app"PDB, pack_alpha_dir, 0, 0));
|
||||
copy_all (pack_data_dir, "*", pack_alpha_dir);
|
||||
copy_file(0, "README.txt", pack_alpha_dir, 0, 0);
|
||||
copy_file(0, "TODO.txt", pack_alpha_dir, 0, 0);
|
||||
copy_file(DATA_DIR, "release-config.4coder", pack_alpha_dir, 0, "config.4coder");
|
||||
copy_file(data_dir, "release-config.4coder", pack_alpha_dir, 0, "config.4coder");
|
||||
|
||||
get_4coder_dist_name(&str, 1, "alpha", "zip");
|
||||
zip(pack_alpha_par_dir, "4coder", str.str);
|
||||
|
@ -948,22 +554,47 @@ package(char *cdir){
|
|||
make_folder_if_missing(pack_dir, "super-docs");
|
||||
|
||||
copy_file(build_dir, "4ed"EXE, pack_super_dir, 0, 0);
|
||||
ONLY_WINDOWS(copy_file(build_dir, "4ed"PDB, pack_super_dir, 0, 0));
|
||||
//ONLY_WINDOWS(copy_file(build_dir, "4ed"PDB, pack_super_dir, 0, 0));
|
||||
copy_file(build_dir, "4ed_app"DLL, pack_super_dir, 0, 0);
|
||||
ONLY_WINDOWS(copy_file(build_dir, "4ed_app"PDB, pack_super_dir, 0, 0));
|
||||
copy_file(build_dir, "4coder_custom"DLL, pack_super_dir, 0, 0);
|
||||
//ONLY_WINDOWS(copy_file(build_dir, "4ed_app"PDB, pack_super_dir, 0, 0));
|
||||
copy_file(build_dir, "custom_4coder"DLL, pack_super_dir, 0, 0);
|
||||
|
||||
copy_all (pack_data_dir, "*", pack_super_dir);
|
||||
copy_file(0, "README.txt", pack_super_dir, 0, 0);
|
||||
copy_file(0, "TODO.txt", pack_super_dir, 0, 0);
|
||||
copy_file(data_dir, "release-config.4coder", pack_super_dir, 0, "config.4coder");
|
||||
|
||||
copy_all (0, "4coder_*.h", pack_super_dir);
|
||||
copy_all (0, "4coder_*.cpp", pack_super_dir);
|
||||
copy_all (0, "4cpp_*.h", pack_super_dir);
|
||||
copy_all (0, "4cpp_*.c", pack_super_dir);
|
||||
copy_all(0, "4coder_*", pack_super_dir);
|
||||
|
||||
copy_file(0, "buildsuper"BAT, pack_super_dir, 0, 0);
|
||||
|
||||
DECL_STR(custom_dir, "4coder_API");
|
||||
DECL_STR(custom_helper_dir, "4coder_helper");
|
||||
DECL_STR(custom_lib_dir, "4coder_lib");
|
||||
DECL_STR(fcpp_dir, "4cpp");
|
||||
|
||||
char *dir_array[] = {
|
||||
custom_dir,
|
||||
custom_helper_dir,
|
||||
custom_lib_dir,
|
||||
fcpp_dir,
|
||||
};
|
||||
i32 dir_count = ArrayCount(dir_array);
|
||||
|
||||
for (i32 i = 0; i < dir_count; ++i){
|
||||
char *d = dir_array[i];
|
||||
make_folder_if_missing(pack_super_dir, d);
|
||||
|
||||
char space[256];
|
||||
String str = make_fixed_width_string(space);
|
||||
append_sc(&str, pack_super_dir);
|
||||
append_s_char(&str, platform_correct_slash);
|
||||
append_sc(&str, d);
|
||||
terminate_with_null(&str);
|
||||
|
||||
copy_all(d, "*", str.str);
|
||||
}
|
||||
|
||||
get_4coder_dist_name(&str, 0, "API", "html");
|
||||
str2 = front_of_directory(str);
|
||||
copy_file(site_dir, "custom_docs.html", pack_dir, "super-docs", str2.str);
|
||||
|
@ -989,7 +620,7 @@ int main(int argc, char **argv){
|
|||
char cdir[256];
|
||||
|
||||
BEGIN_TIME_SECTION();
|
||||
int32_t n = get_current_directory(cdir, sizeof(cdir));
|
||||
i32 n = get_current_directory(cdir, sizeof(cdir));
|
||||
assert(n < sizeof(cdir));
|
||||
END_TIME_SECTION("current directory");
|
||||
|
||||
|
@ -1002,12 +633,11 @@ int main(int argc, char **argv){
|
|||
|
||||
int main(int argc, char **argv){
|
||||
init_time_system();
|
||||
init_global_strings();
|
||||
|
||||
char cdir[256];
|
||||
|
||||
BEGIN_TIME_SECTION();
|
||||
int32_t n = get_current_directory(cdir, sizeof(cdir));
|
||||
i32 n = get_current_directory(cdir, sizeof(cdir));
|
||||
assert(n < sizeof(cdir));
|
||||
END_TIME_SECTION("current directory");
|
||||
|
||||
|
@ -1024,7 +654,7 @@ int main(int argc, char **argv){
|
|||
char cdir[256];
|
||||
|
||||
BEGIN_TIME_SECTION();
|
||||
int32_t n = get_current_directory(cdir, sizeof(cdir));
|
||||
i32 n = get_current_directory(cdir, sizeof(cdir));
|
||||
assert(n < sizeof(cdir));
|
||||
END_TIME_SECTION("current directory");
|
||||
|
||||
|
@ -1037,4 +667,9 @@ int main(int argc, char **argv){
|
|||
#error No build type specified
|
||||
#endif
|
||||
|
||||
#define FTECH_FILE_MOVING_IMPLEMENTATION
|
||||
#include "4tech_file_moving.h"
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#define Assert(n) do{ if (!(n)) { *(int*)0 = 0xA11E; } }while(0)
|
||||
#define ArrayCount(a) (sizeof(a)/sizeof(*a))
|
||||
|
||||
#include "../4cpp_lexer_types.h"
|
||||
#define LEXER_TABLE_FILE "4cpp/4cpp_lexer_tables.c"
|
||||
|
||||
#include "../4cpp/4cpp_lexer_types.h"
|
||||
#include "../4ed_mem_ansi.c"
|
||||
|
||||
typedef struct Whitespace_FSM{
|
||||
|
@ -700,7 +702,7 @@ static PP_Names pp_names[] = {
|
|||
int
|
||||
main(){
|
||||
FILE *file;
|
||||
file = fopen("4cpp_lexer_tables.c", "wb");
|
||||
file = fopen(LEXER_TABLE_FILE, "wb");
|
||||
|
||||
FSM_Tables wtables = generate_whitespace_skip_table();
|
||||
render_fsm_table(file, wtables, "whitespace_fsm");
|
||||
|
|
|
@ -9,21 +9,8 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#if !defined(META_PARSER_CPP_4CODER)
|
||||
#define META_PARSER_CPP_4CODER
|
||||
|
||||
#if !defined(FSTRING_GUARD)
|
||||
#include "internal_4coder_string.cpp"
|
||||
#endif
|
||||
|
||||
#include "../4cpp_lexer.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../4coder_mem.h"
|
||||
#if !defined(META_PARSER_CPP)
|
||||
#define META_PARSER_CPP
|
||||
|
||||
typedef struct Parse_Context{
|
||||
Cpp_Token *token_s;
|
||||
|
@ -241,8 +228,10 @@ static Parse
|
|||
meta_lex(char *filename){
|
||||
Parse result = {0};
|
||||
result.code = file_dump(filename);
|
||||
result.tokens = cpp_make_token_array(1024);
|
||||
cpp_lex_file(result.code.str, result.code.size, &result.tokens);
|
||||
if (result.code.str != 0){
|
||||
result.tokens = cpp_make_token_array(1024);
|
||||
cpp_lex_file(result.code.str, result.code.size, &result.tokens);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
@ -261,7 +250,7 @@ get_next_line(String source, String line){
|
|||
int32_t start = 0;
|
||||
|
||||
if (pos < source.size){
|
||||
assert(source.str[pos] == '\n');
|
||||
Assert(source.str[pos] == '\n');
|
||||
start = pos + 1;
|
||||
|
||||
if (start < source.size){
|
||||
|
@ -369,7 +358,7 @@ static String
|
|||
doc_parse_note_string(String source, int32_t *pos){
|
||||
String result = {0};
|
||||
|
||||
assert(source.str[*pos] == '(');
|
||||
Assert(source.str[*pos] == '(');
|
||||
|
||||
int32_t p = *pos + 1;
|
||||
int32_t start = p;
|
||||
|
@ -498,7 +487,7 @@ perform_doc_parse(Partition *part, String doc_string, Documentation *doc){
|
|||
switch (doc_note_type){
|
||||
case DOC_PARAM:
|
||||
{
|
||||
assert(param_index < param_count);
|
||||
Assert(param_index < param_count);
|
||||
int32_t param_pos = 0;
|
||||
String param_name = doc_parse_parameter(doc_note_string, ¶m_pos);
|
||||
String param_docs = doc_parse_last_parameter(doc_note_string, ¶m_pos);
|
||||
|
@ -519,7 +508,7 @@ perform_doc_parse(Partition *part, String doc_string, Documentation *doc){
|
|||
|
||||
case DOC_SEE:
|
||||
{
|
||||
assert(see_index < see_count);
|
||||
Assert(see_index < see_count);
|
||||
doc->see_also[see_index++] = doc_note_string;
|
||||
}break;
|
||||
}
|
||||
|
@ -613,7 +602,7 @@ struct_parse_next_member(Partition *part, Parse_Context *context){
|
|||
break;
|
||||
}
|
||||
else{
|
||||
assert(!"unhandled error");
|
||||
Assert(!"unhandled error");
|
||||
}
|
||||
}
|
||||
else if (match_ss(lexeme, make_lit_string("UNION"))){
|
||||
|
@ -623,7 +612,7 @@ struct_parse_next_member(Partition *part, Parse_Context *context){
|
|||
break;
|
||||
}
|
||||
else{
|
||||
assert(!"unhandled error");
|
||||
Assert(!"unhandled error");
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
@ -633,7 +622,7 @@ struct_parse_next_member(Partition *part, Parse_Context *context){
|
|||
break;
|
||||
}
|
||||
else{
|
||||
assert(!"unhandled error");
|
||||
Assert(!"unhandled error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1210,6 +1199,7 @@ compile_meta_unit(Partition *part, char *code_directory, char **files, Meta_Keyw
|
|||
unit.count = file_count;
|
||||
unit.parse = push_array(part, Parse, file_count);
|
||||
|
||||
b32 all_files_lexed = true;
|
||||
int32_t i = 0;
|
||||
for (char **file_ptr = files; *file_ptr; ++file_ptr, ++i){
|
||||
char str_space[512];
|
||||
|
@ -1224,143 +1214,151 @@ compile_meta_unit(Partition *part, char *code_directory, char **files, Meta_Keyw
|
|||
terminate_with_null(&name);
|
||||
|
||||
unit.parse[i] = meta_lex(name.str);
|
||||
if (unit.parse[i].code.str == 0){
|
||||
all_files_lexed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(allen): This stage counts nested structs
|
||||
// and unions which is not correct. Luckily it only
|
||||
// means we over allocate by a few items, but fixing it
|
||||
// to be exactly correct would be nice.
|
||||
for (int32_t J = 0; J < unit.count; ++J){
|
||||
Cpp_Token *token = 0;
|
||||
Parse_Context context_ = setup_parse_context(unit.parse[J]);
|
||||
Parse_Context *context = &context_;
|
||||
|
||||
for (; (token = get_token(context)) != 0; get_next_token(context)){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
|
||||
String lexeme = get_lexeme(*token, context->data);
|
||||
int32_t match_index = 0;
|
||||
if (string_set_match_table(keywords, sizeof(*keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = keywords[match_index].type;
|
||||
|
||||
if (all_files_lexed){
|
||||
// TODO(allen): This stage counts nested structs and unions which is not correct. Luckily it only means we over allocate by a few items, but fixing it to be exactly correct would be nice.
|
||||
for (int32_t J = 0; J < unit.count; ++J){
|
||||
Cpp_Token *token = 0;
|
||||
Parse_Context context_ = setup_parse_context(unit.parse[J]);
|
||||
Parse_Context *context = &context_;
|
||||
|
||||
for (; (token = get_token(context)) != 0; get_next_token(context)){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
|
||||
if (type > Item_Null && type < Item_Type_Count){
|
||||
++unit.set.count;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): Warning
|
||||
String lexeme = get_lexeme(*token, context->data);
|
||||
int32_t match_index = 0;
|
||||
if (string_set_match_table(keywords, sizeof(*keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = keywords[match_index].type;
|
||||
|
||||
if (type > Item_Null && type < Item_Type_Count){
|
||||
++unit.set.count;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): Warning
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unit.set.count > 0){
|
||||
unit.set = allocate_item_set(part, unit.set.count);
|
||||
}
|
||||
|
||||
int32_t index = 0;
|
||||
|
||||
for (int32_t J = 0; J < unit.count; ++J){
|
||||
Cpp_Token *token = 0;
|
||||
Parse_Context context_ = setup_parse_context(unit.parse[J]);
|
||||
Parse_Context *context = &context_;
|
||||
|
||||
String cpp_name = {0};
|
||||
int32_t has_cpp_name = 0;
|
||||
|
||||
for (; (token = get_token(context)) != 0; get_next_token(context)){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
|
||||
String lexeme = get_lexeme(*token, context->data);
|
||||
int32_t match_index = 0;
|
||||
if (string_set_match_table(keywords, sizeof(*keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = keywords[match_index].type;
|
||||
|
||||
switch (type){
|
||||
case Item_Function:
|
||||
{
|
||||
if (function_parse(part, context, unit.set.items + index, cpp_name)){
|
||||
Assert(unit.set.items[index].t == Item_Function);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "warning: invalid function signature\n");
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_CppName:
|
||||
{
|
||||
if (cpp_name_parse(context, &cpp_name)){
|
||||
has_cpp_name = 1;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Macro:
|
||||
{
|
||||
if (macro_parse(part, context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Macro);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Typedef: //typedef
|
||||
{
|
||||
if (typedef_parse(context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Typedef);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Struct: case Item_Union: //struct/union
|
||||
{
|
||||
if (struct_parse(part, (type == Item_Struct), context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Struct ||
|
||||
unit.set.items[index].t == Item_Union);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Enum: //ENUM
|
||||
{
|
||||
if (enum_parse(part, context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Enum);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_cpp_name){
|
||||
has_cpp_name = 0;
|
||||
}
|
||||
else{
|
||||
cpp_name = null_string;
|
||||
}
|
||||
|
||||
unit.parse[J].item_count = index;
|
||||
if (unit.set.count > 0){
|
||||
unit.set = allocate_item_set(part, unit.set.count);
|
||||
}
|
||||
|
||||
// NOTE(allen): This is necessary for now because
|
||||
// the original count is slightly overestimated thanks
|
||||
// to nested structs and unions.
|
||||
unit.set.count = index;
|
||||
int32_t index = 0;
|
||||
|
||||
for (int32_t J = 0; J < unit.count; ++J){
|
||||
Cpp_Token *token = 0;
|
||||
Parse_Context context_ = setup_parse_context(unit.parse[J]);
|
||||
Parse_Context *context = &context_;
|
||||
|
||||
String cpp_name = {0};
|
||||
int32_t has_cpp_name = 0;
|
||||
|
||||
for (; (token = get_token(context)) != 0; get_next_token(context)){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
|
||||
String lexeme = get_lexeme(*token, context->data);
|
||||
int32_t match_index = 0;
|
||||
if (string_set_match_table(keywords, sizeof(*keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = keywords[match_index].type;
|
||||
|
||||
switch (type){
|
||||
case Item_Function:
|
||||
{
|
||||
if (function_parse(part, context, unit.set.items + index, cpp_name)){
|
||||
Assert(unit.set.items[index].t == Item_Function);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "warning: invalid function signature\n");
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_CppName:
|
||||
{
|
||||
if (cpp_name_parse(context, &cpp_name)){
|
||||
has_cpp_name = 1;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Macro:
|
||||
{
|
||||
if (macro_parse(part, context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Macro);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Typedef: //typedef
|
||||
{
|
||||
if (typedef_parse(context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Typedef);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Struct: case Item_Union: //struct/union
|
||||
{
|
||||
if (struct_parse(part, (type == Item_Struct), context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Struct ||
|
||||
unit.set.items[index].t == Item_Union);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
case Item_Enum: //ENUM
|
||||
{
|
||||
if (enum_parse(part, context, unit.set.items + index)){
|
||||
Assert(unit.set.items[index].t == Item_Enum);
|
||||
++index;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): warning message
|
||||
}
|
||||
}break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_cpp_name){
|
||||
has_cpp_name = 0;
|
||||
}
|
||||
else{
|
||||
cpp_name = null_string;
|
||||
}
|
||||
|
||||
unit.parse[J].item_count = index;
|
||||
}
|
||||
|
||||
// NOTE(allen): This is necessary for now because
|
||||
// the original count is slightly overestimated thanks
|
||||
// to nested structs and unions.
|
||||
unit.set.count = index;
|
||||
}
|
||||
}
|
||||
else{
|
||||
unit.parse = 0;
|
||||
unit.count = 0;
|
||||
}
|
||||
|
||||
return(unit);
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
|
||||
struct Custom_Vars{
|
||||
int32_t initialized;
|
||||
Partition part;
|
||||
};
|
||||
|
||||
enum View_Mode{
|
||||
ViewMode_File,
|
||||
};
|
||||
|
||||
struct View_Vars{
|
||||
int32_t id;
|
||||
View_Mode mode;
|
||||
|
||||
GUI_Scroll_Vars scroll;
|
||||
i32_Rect scroll_region;
|
||||
|
||||
int32_t buffer_id;
|
||||
};
|
||||
inline View_Vars
|
||||
view_vars_zero(){
|
||||
View_Vars vars = {0};
|
||||
return(vars);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
view_routine(Application_Links *app, int32_t view_id){
|
||||
Custom_Vars *vars = (Custom_Vars*)app->memory;
|
||||
View_Vars view = {0};
|
||||
view.id = view_id;
|
||||
|
||||
int32_t show_scrollbar = 1;
|
||||
|
||||
if (!vars->initialized){
|
||||
vars->initialized = 1;
|
||||
vars->part = make_part(app->memory, app->memory_size);
|
||||
push_struct(&vars->part, Custom_Vars);
|
||||
}
|
||||
|
||||
for(;;){
|
||||
Event_Message message = {0};
|
||||
message = app->get_event_message(app);
|
||||
|
||||
switch (message.type){
|
||||
case EM_Open_View:
|
||||
{
|
||||
view = view_vars_zero();
|
||||
view.id = view_id;
|
||||
}break;
|
||||
|
||||
case EM_Frame:
|
||||
{
|
||||
GUI_Functions *guifn = app->get_gui_functions(app);
|
||||
GUI *gui = app->get_gui(app, view_id);
|
||||
|
||||
guifn->begin(gui);
|
||||
guifn->top_bar(gui);
|
||||
|
||||
switch (view.mode){
|
||||
case ViewMode_File:
|
||||
// TODO(allen): Overlapped widget
|
||||
GUI_id scroll_id;
|
||||
scroll_id.id[1] = view.mode;
|
||||
scroll_id.id[0] = view.buffer_id;
|
||||
|
||||
guifn->get_scroll_vars(gui, scroll_id, &view.scroll,
|
||||
&view.scroll_region);
|
||||
guifn->begin_scrollable(gui, scroll_id, view.scroll,
|
||||
144.f, show_scrollbar);
|
||||
guifn->file(gui, view.buffer_id);
|
||||
guifn->end_scrollable(gui);
|
||||
break;
|
||||
}
|
||||
|
||||
guifn->end(gui);
|
||||
|
||||
// TODO(allen): Put this code in charge of dispatching
|
||||
// to the command or command coroutine or whatever.
|
||||
|
||||
// TODO(allen): Put this code in charge of when to process
|
||||
// the GUI with input and retrieve new layout data.
|
||||
}break;
|
||||
|
||||
case EM_Close_View:
|
||||
{}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "4coder_default_include.cpp"
|
||||
|
||||
#include "4coder_function_list.cpp"
|
||||
|
||||
#define NO_BINDING
|
||||
#include "4coder_default_bindings.cpp"
|
||||
|
||||
|
@ -197,273 +199,6 @@ CUSTOM_COMMAND_SIG(multi_line_edit){
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Declaration list
|
||||
//
|
||||
|
||||
static void
|
||||
list_all_functions(Application_Links *app, Partition *part, Buffer_Summary *buffer){
|
||||
String search_name = make_lit_string("*decls*");
|
||||
Buffer_Summary decls_buffer = get_buffer_by_name(app, search_name.str, search_name.size, AccessAll);
|
||||
if (!decls_buffer.exists){
|
||||
decls_buffer = create_buffer(app, search_name.str, search_name.size, BufferCreate_AlwaysNew);
|
||||
buffer_set_setting(app, &decls_buffer, BufferSetting_Unimportant, true);
|
||||
buffer_set_setting(app, &decls_buffer, BufferSetting_ReadOnly, true);
|
||||
buffer_set_setting(app, &decls_buffer, BufferSetting_WrapLine, false);
|
||||
}
|
||||
else{
|
||||
buffer_replace_range(app, &decls_buffer, 0, decls_buffer.size, 0, 0);
|
||||
}
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
struct Function_Positions{
|
||||
int32_t sig_start_index;
|
||||
int32_t sig_end_index;
|
||||
int32_t open_paren_pos;
|
||||
};
|
||||
|
||||
Function_Positions *positions_array = push_array(part, Function_Positions, (4<<10)/sizeof(Function_Positions));
|
||||
int32_t positions_count = 0;
|
||||
|
||||
Partition extra_memory_ = partition_sub_part(part, (4<<10));
|
||||
Partition *extra_memory = &extra_memory_;
|
||||
char *str = (char*)partition_current(part);
|
||||
int32_t part_size = 0;
|
||||
int32_t size = 0;
|
||||
|
||||
static const int32_t token_chunk_size = 512;
|
||||
Cpp_Token token_chunk[token_chunk_size];
|
||||
Stream_Tokens token_stream = {0};
|
||||
|
||||
if (init_stream_tokens(&token_stream, app, buffer, 0, token_chunk, token_chunk_size)){
|
||||
Stream_Tokens start_position_stream_temp = begin_temp_stream_token(&token_stream);
|
||||
|
||||
int32_t token_index = 0;
|
||||
int32_t nest_level = 0;
|
||||
int32_t paren_nest_level = 0;
|
||||
|
||||
int32_t first_paren_index = 0;
|
||||
int32_t first_paren_position = 0;
|
||||
int32_t last_paren_index = 0;
|
||||
|
||||
bool32 still_looping = false;
|
||||
|
||||
// Look for the next token at global scope that might need to be printed.
|
||||
mode1: do{
|
||||
for (; token_index < token_stream.end; ++token_index){
|
||||
Cpp_Token *token = &token_stream.tokens[token_index];
|
||||
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_BRACE_OPEN:
|
||||
{
|
||||
++nest_level;
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
{
|
||||
if (nest_level > 0){
|
||||
--nest_level;
|
||||
}
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
{
|
||||
if (nest_level == 0){
|
||||
first_paren_index = token_index;
|
||||
first_paren_position = token->start;
|
||||
goto paren_mode1;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
goto end;
|
||||
|
||||
// Look for a closing parenthese to mark the end of a function signature.
|
||||
paren_mode1:
|
||||
paren_nest_level = 0;
|
||||
do{
|
||||
for (; token_index < token_stream.end; ++token_index){
|
||||
Cpp_Token *token = &token_stream.tokens[token_index];
|
||||
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
{
|
||||
++paren_nest_level;
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
{
|
||||
--paren_nest_level;
|
||||
if (paren_nest_level == 0){
|
||||
last_paren_index = token_index;
|
||||
goto paren_mode2;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
goto end;
|
||||
|
||||
// Look backwards from an open parenthese to find the start of a function signature.
|
||||
paren_mode2: {
|
||||
Stream_Tokens backward_stream_temp = begin_temp_stream_token(&token_stream);
|
||||
int32_t local_index = first_paren_index;
|
||||
int32_t signature_start_index = 0;
|
||||
|
||||
do{
|
||||
for (; local_index >= token_stream.start; --local_index){
|
||||
Cpp_Token *token = &token_stream.tokens[local_index];
|
||||
if ((token->flags & CPP_TFLAG_PP_BODY) || (token->flags & CPP_TFLAG_PP_DIRECTIVE) || token->type == CPP_TOKEN_BRACE_CLOSE || token->type == CPP_TOKEN_SEMICOLON || token->type == CPP_TOKEN_PARENTHESE_CLOSE){
|
||||
++local_index;
|
||||
signature_start_index = local_index;
|
||||
goto paren_mode2_done;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
// When this loop ends by going all the way back to the beginning set the signature start to 0 and fall through to the printing phase.
|
||||
signature_start_index = 0;
|
||||
|
||||
paren_mode2_done:;
|
||||
{
|
||||
Function_Positions positions;
|
||||
positions.sig_start_index = signature_start_index;
|
||||
positions.sig_end_index = last_paren_index;
|
||||
positions.open_paren_pos = first_paren_position;
|
||||
positions_array[positions_count++] = positions;
|
||||
}
|
||||
|
||||
end_temp_stream_token(&token_stream, backward_stream_temp);
|
||||
goto mode1;
|
||||
}
|
||||
|
||||
end:;
|
||||
end_temp_stream_token(&token_stream, start_position_stream_temp);
|
||||
// Print the results
|
||||
String buffer_name = make_string(buffer->buffer_name, buffer->buffer_name_len);
|
||||
for (int32_t i = 0; i < positions_count; ++i){
|
||||
Function_Positions *positions = &positions_array[i];
|
||||
Temp_Memory extra_temp = begin_temp_memory(extra_memory);
|
||||
|
||||
int32_t local_index = positions->sig_start_index;
|
||||
int32_t end_index = positions->sig_end_index;
|
||||
int32_t open_paren_pos = positions->open_paren_pos;
|
||||
|
||||
do{
|
||||
for (; local_index < token_stream.end; ++local_index){
|
||||
Cpp_Token *token = &token_stream.tokens[local_index];
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
if (token->type != CPP_TOKEN_COMMENT){
|
||||
bool32 delete_space_before = false;
|
||||
bool32 space_after = false;
|
||||
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_COMMA:
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
{
|
||||
delete_space_before = true;
|
||||
}break;
|
||||
}
|
||||
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_IDENTIFIER:
|
||||
case CPP_TOKEN_COMMA:
|
||||
case CPP_TOKEN_STAR:
|
||||
{
|
||||
space_after = true;
|
||||
}break;
|
||||
}
|
||||
if (token->flags & CPP_TFLAG_IS_KEYWORD){
|
||||
space_after = true;
|
||||
}
|
||||
|
||||
if (delete_space_before){
|
||||
int32_t pos = extra_memory->pos - 1;
|
||||
char *base = ((char*)(extra_memory->base));
|
||||
if (pos >= 0 && base[pos] == ' '){
|
||||
extra_memory->pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
char *token_str = push_array(extra_memory, char, token->size + space_after);
|
||||
|
||||
buffer_read_range(app, buffer, token->start, token->start + token->size, token_str);
|
||||
if (space_after){
|
||||
token_str[token->size] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (local_index == end_index){
|
||||
goto finish_print;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
|
||||
finish_print:;
|
||||
{
|
||||
int32_t sig_size = extra_memory->pos;
|
||||
String sig = make_string(extra_memory->base, sig_size);
|
||||
|
||||
int32_t line_number = buffer_get_line_index(app, buffer, open_paren_pos);
|
||||
int32_t line_number_len = int_to_str_size(line_number);
|
||||
|
||||
int32_t append_len = buffer_name.size + 1 + line_number_len + 1 + 1 + sig_size + 1;
|
||||
|
||||
char *out_space = push_array(part, char, append_len);
|
||||
if (out_space == 0){
|
||||
buffer_replace_range(app, &decls_buffer, size, size, str, part_size);
|
||||
size += part_size;
|
||||
|
||||
end_temp_memory(temp);
|
||||
temp = begin_temp_memory(part);
|
||||
|
||||
part_size = 0;
|
||||
out_space = push_array(part, char, append_len);
|
||||
}
|
||||
|
||||
part_size += append_len;
|
||||
String out = make_string(out_space, 0, append_len);
|
||||
append(&out, buffer_name);
|
||||
append(&out, ':');
|
||||
append_int_to_str(&out, line_number);
|
||||
append(&out, ':');
|
||||
append(&out, ' ');
|
||||
append(&out, sig);
|
||||
append(&out, '\n');
|
||||
}
|
||||
|
||||
end_temp_memory(extra_temp);
|
||||
}
|
||||
|
||||
buffer_replace_range(app, &decls_buffer, size, size, str, part_size);
|
||||
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
view_set_buffer(app, &view, decls_buffer.buffer_id, 0);
|
||||
|
||||
lock_jump_buffer(search_name.str, search_name.size);
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(list_all_functions_current_buffer){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
list_all_functions(app, &global_part, &buffer);
|
||||
}
|
||||
|
||||
//
|
||||
// Scope-Smart Editing Basics
|
||||
//
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
|
||||
// TOP
|
||||
|
||||
// NOTE(allen|a4.0.14): This turned out to be a nasty little routine. There might
|
||||
// be a better way to do it with just tokens that I didn't see the first time
|
||||
// through. Once I build a real parser this should become almost just as easy as
|
||||
// iterating tokens is now.
|
||||
//
|
||||
// This version can be dropped anywhere underneath 4coder_default_include.cpp and
|
||||
// will then provide the "list_all_functions_current_buffer" command.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Declaration list
|
||||
//
|
||||
|
||||
static void
|
||||
list_all_functions(Application_Links *app, Partition *part, Buffer_Summary *buffer){
|
||||
String search_name = make_lit_string("*decls*");
|
||||
Buffer_Summary decls_buffer = get_buffer_by_name(app, search_name.str, search_name.size, AccessAll);
|
||||
if (!decls_buffer.exists){
|
||||
decls_buffer = create_buffer(app, search_name.str, search_name.size, BufferCreate_AlwaysNew);
|
||||
buffer_set_setting(app, &decls_buffer, BufferSetting_Unimportant, true);
|
||||
buffer_set_setting(app, &decls_buffer, BufferSetting_ReadOnly, true);
|
||||
buffer_set_setting(app, &decls_buffer, BufferSetting_WrapLine, false);
|
||||
}
|
||||
else{
|
||||
buffer_replace_range(app, &decls_buffer, 0, decls_buffer.size, 0, 0);
|
||||
}
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
struct Function_Positions{
|
||||
int32_t sig_start_index;
|
||||
int32_t sig_end_index;
|
||||
int32_t open_paren_pos;
|
||||
};
|
||||
|
||||
Function_Positions *positions_array = push_array(part, Function_Positions, (4<<10)/sizeof(Function_Positions));
|
||||
int32_t positions_count = 0;
|
||||
|
||||
Partition extra_memory_ = partition_sub_part(part, (4<<10));
|
||||
Partition *extra_memory = &extra_memory_;
|
||||
char *str = (char*)partition_current(part);
|
||||
int32_t part_size = 0;
|
||||
int32_t size = 0;
|
||||
|
||||
static const int32_t token_chunk_size = 512;
|
||||
Cpp_Token token_chunk[token_chunk_size];
|
||||
Stream_Tokens token_stream = {0};
|
||||
|
||||
if (init_stream_tokens(&token_stream, app, buffer, 0, token_chunk, token_chunk_size)){
|
||||
Stream_Tokens start_position_stream_temp = begin_temp_stream_token(&token_stream);
|
||||
|
||||
int32_t token_index = 0;
|
||||
int32_t nest_level = 0;
|
||||
int32_t paren_nest_level = 0;
|
||||
|
||||
int32_t first_paren_index = 0;
|
||||
int32_t first_paren_position = 0;
|
||||
int32_t last_paren_index = 0;
|
||||
|
||||
bool32 still_looping = false;
|
||||
|
||||
// Look for the next token at global scope that might need to be printed.
|
||||
mode1: do{
|
||||
for (; token_index < token_stream.end; ++token_index){
|
||||
Cpp_Token *token = &token_stream.tokens[token_index];
|
||||
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_BRACE_OPEN:
|
||||
{
|
||||
++nest_level;
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
{
|
||||
if (nest_level > 0){
|
||||
--nest_level;
|
||||
}
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
{
|
||||
if (nest_level == 0){
|
||||
first_paren_index = token_index;
|
||||
first_paren_position = token->start;
|
||||
goto paren_mode1;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
goto end;
|
||||
|
||||
// Look for a closing parenthese to mark the end of a function signature.
|
||||
paren_mode1:
|
||||
paren_nest_level = 0;
|
||||
do{
|
||||
for (; token_index < token_stream.end; ++token_index){
|
||||
Cpp_Token *token = &token_stream.tokens[token_index];
|
||||
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
{
|
||||
++paren_nest_level;
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
{
|
||||
--paren_nest_level;
|
||||
if (paren_nest_level == 0){
|
||||
last_paren_index = token_index;
|
||||
goto paren_mode2;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
goto end;
|
||||
|
||||
// Look backwards from an open parenthese to find the start of a function signature.
|
||||
paren_mode2: {
|
||||
Stream_Tokens backward_stream_temp = begin_temp_stream_token(&token_stream);
|
||||
int32_t local_index = first_paren_index;
|
||||
int32_t signature_start_index = 0;
|
||||
|
||||
do{
|
||||
for (; local_index >= token_stream.start; --local_index){
|
||||
Cpp_Token *token = &token_stream.tokens[local_index];
|
||||
if ((token->flags & CPP_TFLAG_PP_BODY) || (token->flags & CPP_TFLAG_PP_DIRECTIVE) || token->type == CPP_TOKEN_BRACE_CLOSE || token->type == CPP_TOKEN_SEMICOLON || token->type == CPP_TOKEN_PARENTHESE_CLOSE){
|
||||
++local_index;
|
||||
signature_start_index = local_index;
|
||||
goto paren_mode2_done;
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
// When this loop ends by going all the way back to the beginning set the signature start to 0 and fall through to the printing phase.
|
||||
signature_start_index = 0;
|
||||
|
||||
paren_mode2_done:;
|
||||
{
|
||||
Function_Positions positions;
|
||||
positions.sig_start_index = signature_start_index;
|
||||
positions.sig_end_index = last_paren_index;
|
||||
positions.open_paren_pos = first_paren_position;
|
||||
positions_array[positions_count++] = positions;
|
||||
}
|
||||
|
||||
end_temp_stream_token(&token_stream, backward_stream_temp);
|
||||
goto mode1;
|
||||
}
|
||||
|
||||
end:;
|
||||
end_temp_stream_token(&token_stream, start_position_stream_temp);
|
||||
// Print the results
|
||||
String buffer_name = make_string(buffer->buffer_name, buffer->buffer_name_len);
|
||||
for (int32_t i = 0; i < positions_count; ++i){
|
||||
Function_Positions *positions = &positions_array[i];
|
||||
Temp_Memory extra_temp = begin_temp_memory(extra_memory);
|
||||
|
||||
int32_t local_index = positions->sig_start_index;
|
||||
int32_t end_index = positions->sig_end_index;
|
||||
int32_t open_paren_pos = positions->open_paren_pos;
|
||||
|
||||
do{
|
||||
for (; local_index < token_stream.end; ++local_index){
|
||||
Cpp_Token *token = &token_stream.tokens[local_index];
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
if (token->type != CPP_TOKEN_COMMENT){
|
||||
bool32 delete_space_before = false;
|
||||
bool32 space_after = false;
|
||||
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_COMMA:
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
{
|
||||
delete_space_before = true;
|
||||
}break;
|
||||
}
|
||||
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_IDENTIFIER:
|
||||
case CPP_TOKEN_COMMA:
|
||||
case CPP_TOKEN_STAR:
|
||||
{
|
||||
space_after = true;
|
||||
}break;
|
||||
}
|
||||
if (token->flags & CPP_TFLAG_IS_KEYWORD){
|
||||
space_after = true;
|
||||
}
|
||||
|
||||
if (delete_space_before){
|
||||
int32_t pos = extra_memory->pos - 1;
|
||||
char *base = ((char*)(extra_memory->base));
|
||||
if (pos >= 0 && base[pos] == ' '){
|
||||
extra_memory->pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
char *token_str = push_array(extra_memory, char, token->size + space_after);
|
||||
|
||||
buffer_read_range(app, buffer, token->start, token->start + token->size, token_str);
|
||||
if (space_after){
|
||||
token_str[token->size] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (local_index == end_index){
|
||||
goto finish_print;
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_tokens(&token_stream);
|
||||
}while(still_looping);
|
||||
|
||||
finish_print:;
|
||||
{
|
||||
int32_t sig_size = extra_memory->pos;
|
||||
String sig = make_string(extra_memory->base, sig_size);
|
||||
|
||||
int32_t line_number = buffer_get_line_index(app, buffer, open_paren_pos);
|
||||
int32_t line_number_len = int_to_str_size(line_number);
|
||||
|
||||
int32_t append_len = buffer_name.size + 1 + line_number_len + 1 + 1 + sig_size + 1;
|
||||
|
||||
char *out_space = push_array(part, char, append_len);
|
||||
if (out_space == 0){
|
||||
buffer_replace_range(app, &decls_buffer, size, size, str, part_size);
|
||||
size += part_size;
|
||||
|
||||
end_temp_memory(temp);
|
||||
temp = begin_temp_memory(part);
|
||||
|
||||
part_size = 0;
|
||||
out_space = push_array(part, char, append_len);
|
||||
}
|
||||
|
||||
part_size += append_len;
|
||||
String out = make_string(out_space, 0, append_len);
|
||||
append(&out, buffer_name);
|
||||
append(&out, ':');
|
||||
append_int_to_str(&out, line_number);
|
||||
append(&out, ':');
|
||||
append(&out, ' ');
|
||||
append(&out, sig);
|
||||
append(&out, '\n');
|
||||
}
|
||||
|
||||
end_temp_memory(extra_temp);
|
||||
}
|
||||
|
||||
buffer_replace_range(app, &decls_buffer, size, size, str, part_size);
|
||||
|
||||
View_Summary view = get_active_view(app, AccessAll);
|
||||
view_set_buffer(app, &view, decls_buffer.buffer_id, 0);
|
||||
|
||||
lock_jump_buffer(search_name.str, search_name.size);
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(list_all_functions_current_buffer){
|
||||
uint32_t access = AccessProtected;
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
list_all_functions(app, &global_part, &buffer);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -2,7 +2,7 @@ extensions=".c.cpp.h.hpp.bat.sh";
|
|||
|
||||
fkey_command_win[1] = {"build.bat", "*compilation*", true};
|
||||
fkey_command_win[2] = {"site\\build.bat", "*compilation*", true};
|
||||
fkey_command_win[3] = {"file\\run_tests.bat", "*tests*", true};
|
||||
fkey_command_win[3] = {"string\\build.bat", "*compilation*", true};
|
||||
fkey_command_win[4] = {0, 0};
|
||||
fkey_command_win[5] = {"..\\misc\\run.bat", "*run*"};
|
||||
fkey_command_win[6] = {0, 0};
|
||||
|
|
|
@ -831,7 +831,7 @@ write_enriched_text_html(String *out, Partition *part, Enriched_Text *text, Docu
|
|||
Abstract_Item *img_lookup = get_item_by_name(doc_system->img_list, img_name);
|
||||
|
||||
if (img_lookup){
|
||||
pixel_height = CEIL32(pixel_width*img_lookup->h_w_ratio);
|
||||
pixel_height = ceil32(pixel_width*img_lookup->h_w_ratio);
|
||||
|
||||
append_sc(out, "<img src='");
|
||||
|
||||
|
|
|
@ -20,13 +20,12 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/4coder_defines.h"
|
||||
#include "../common/4coder_version.h"
|
||||
#include "../4tech_defines.h"
|
||||
#include "../4coder_API/version.h"
|
||||
#define FSTRING_IMPLEMENTATION
|
||||
#include "../4coder_string.h"
|
||||
#include "../4cpp_lexer.h"
|
||||
|
||||
#include "../4coder_mem.h"
|
||||
#include "../4coder_lib/4coder_string.h"
|
||||
#include "../4coder_lib/4coder_mem.h"
|
||||
#include "../4cpp/4cpp_lexer.h"
|
||||
|
||||
#include "../meta/meta_parser.cpp"
|
||||
#include "../meta/out_context.cpp"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
1
|
||||
0
|
||||
59
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 4tech_standard_preamble.h
|
||||
#if !defined(FTECH_INTEGERS)
|
||||
#define FTECH_INTEGERS
|
||||
#include <stdint.h>
|
||||
typedef int8_t i8_4tech;
|
||||
typedef int16_t i16_4tech;
|
||||
typedef int32_t i32_4tech;
|
||||
typedef int64_t i64_4tech;
|
||||
|
||||
typedef uint8_t u8_4tech;
|
||||
typedef uint16_t u16_4tech;
|
||||
typedef uint32_t u32_4tech;
|
||||
typedef uint64_t u64_4tech;
|
||||
|
||||
typedef float f32_4tech;
|
||||
typedef double f64_4tech;
|
||||
|
||||
typedef int8_t b8_4tech;
|
||||
typedef int32_t b32_4tech;
|
||||
#endif
|
||||
|
||||
#if !defined(Assert)
|
||||
# define Assert(n) do{ if (!(n)) *(int*)0 = 0xA11E; }while(0)
|
||||
#endif
|
||||
// standard preamble end
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
@echo off
|
||||
|
||||
call "ctime" -begin string\_4coder_string.ctm
|
||||
|
||||
SET OPTS=-W4 -wd4310 -wd4100 -wd4201 -wd4505 -wd4996 -wd4127 -wd4510 -wd4512 -wd4610 -wd4390 -WX
|
||||
SET OPTS=%OPTS% -wd4611 -GR- -EHa- -nologo -FC
|
||||
|
||||
SET FirstError=0
|
||||
|
||||
pushd ..\build
|
||||
cl %OPTS% ..\code\string\string_builder.cpp /Zi /Festring_builder
|
||||
if %ERRORLEVEL% neq 0 (set FirstError=1)
|
||||
if %ERRORLEVEL% neq 0 (goto END)
|
||||
popd
|
||||
|
||||
pushd string
|
||||
..\..\build\string_builder
|
||||
if %ERRORLEVEL% neq 0 (set FirstError=1)
|
||||
popd
|
||||
|
||||
:END
|
||||
call "ctime" -end string\_4coder_string.ctm %FirstError%
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
Builder for the 4coder_string.h header.
|
||||
By Allen Webster
|
||||
Created 21.01.2017 (dd.mm.yyyy)
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "../4cpp/4cpp_lexer.h"
|
||||
// TODO(allen): Make sure to only publish the 4coder_string.h if it builds and passes a series of tests.
|
||||
#define FSTRING_IMPLEMENTATION
|
||||
#include "../4coder_lib/4coder_string.h"
|
||||
|
||||
#include "../4tech_defines.h"
|
||||
#include "../meta/4tech_meta_defines.h"
|
||||
#include "../meta/4tech_file_moving.h"
|
||||
|
||||
|
||||
#define BUILD_NUMBER_FILE "4coder_string_build_num.txt"
|
||||
|
||||
#define GENERATED_FILE "4coder_string.h"
|
||||
#define INTERNAL_STRING "internal_4coder_string.cpp"
|
||||
|
||||
#define BACKUP_FOLDER ".." SLASH ".." SLASH "string_backup"
|
||||
#define PUBLISH_FOLDER ".." SLASH "4coder_helper"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../4coder_lib/4coder_mem.h"
|
||||
|
||||
#define V_MAJ_NUM 1
|
||||
#define V_MIN_NUM 0
|
||||
|
||||
#define V_MAJ STR_(V_MAJ_NUM)
|
||||
#define V_MIN STR_(V_MIN_NUM)
|
||||
|
||||
#include "../meta/meta_parser.cpp"
|
||||
|
||||
static b32
|
||||
parse_build_number(char *file_name, i32 *major_out, i32 *minor_out, i32 *build_out){
|
||||
b32 result = false;
|
||||
String file = file_dump(file_name);
|
||||
|
||||
if (file.str != 0){
|
||||
char *end_str = file.str + file.size;
|
||||
char *major_str = file.str;
|
||||
char *minor_str = major_str;
|
||||
for (; minor_str < end_str && *minor_str != '\n'; ++minor_str);
|
||||
++minor_str;
|
||||
|
||||
*major_out = 0;
|
||||
*minor_out = 0;
|
||||
*build_out = 0;
|
||||
|
||||
if (major_str < end_str){
|
||||
char *build_str = minor_str;
|
||||
for (; build_str < end_str && *build_str != '\n'; ++build_str);
|
||||
++build_str;
|
||||
|
||||
if (build_str < end_str){
|
||||
char *ender = build_str;
|
||||
for (; ender < end_str && *ender != '\n'; ++ender);
|
||||
|
||||
if (ender < end_str){
|
||||
*ender = 0;
|
||||
}
|
||||
|
||||
minor_str[-1] = 0;
|
||||
build_str[-1] = 0;
|
||||
|
||||
*major_out = str_to_int_c(major_str);
|
||||
*minor_out = str_to_int_c(minor_str);
|
||||
*build_out = str_to_int_c(build_str);
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
free(file.str);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
save_build_number(char *file_name, i32 major, i32 minor, i32 build){
|
||||
FILE *out = fopen(file_name, "wb");
|
||||
fprintf(out, "%d\n", major);
|
||||
fprintf(out, "%d\n", minor);
|
||||
fprintf(out, "%d\n\n\n", build);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
#include "../meta/out_context.cpp"
|
||||
|
||||
//
|
||||
// Meta Parse Rules
|
||||
//
|
||||
|
||||
static void
|
||||
print_function_body_code(String *out, Parse_Context *context, int32_t start){
|
||||
String pstr = {0}, lexeme = {0};
|
||||
Cpp_Token *token = 0;
|
||||
|
||||
int32_t do_print = 0;
|
||||
int32_t nest_level = 0;
|
||||
int32_t finish = false;
|
||||
int32_t do_whitespace_print = false;
|
||||
int32_t is_first = true;
|
||||
|
||||
for (; (token = get_token(context)) != 0; get_next_token(context)){
|
||||
if (do_whitespace_print){
|
||||
pstr = str_start_end(context->data, start, token->start);
|
||||
append_ss(out, pstr);
|
||||
}
|
||||
else{
|
||||
do_whitespace_print = true;
|
||||
}
|
||||
|
||||
do_print = true;
|
||||
if (token->type == CPP_TOKEN_COMMENT){
|
||||
lexeme = get_lexeme(*token, context->data);
|
||||
if (check_and_fix_docs(&lexeme)){
|
||||
do_print = false;
|
||||
}
|
||||
}
|
||||
else if (token->type == CPP_TOKEN_BRACE_OPEN){
|
||||
++nest_level;
|
||||
}
|
||||
else if (token->type == CPP_TOKEN_BRACE_CLOSE){
|
||||
--nest_level;
|
||||
if (nest_level == 0){
|
||||
finish = true;
|
||||
}
|
||||
}
|
||||
if (is_first){
|
||||
do_print = false;
|
||||
is_first = false;
|
||||
}
|
||||
|
||||
if (do_print){
|
||||
pstr = get_lexeme(*token, context->data);
|
||||
append_ss(out, pstr);
|
||||
}
|
||||
|
||||
start = token->start + token->size;
|
||||
|
||||
if (finish){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
file_move(char *path, char *file_name){
|
||||
copy_file(0, file_name, path, 0, file_name);
|
||||
}
|
||||
|
||||
int main(){
|
||||
META_BEGIN();
|
||||
|
||||
i32 size = (512 << 20);
|
||||
void *mem = malloc(size);
|
||||
memset(mem, 0, size);
|
||||
|
||||
Partition part_ = make_part(mem, size);
|
||||
Partition *part = &part_;
|
||||
|
||||
static Meta_Keywords meta_keywords[] = {
|
||||
{make_lit_string("API_EXPORT") , Item_Function } ,
|
||||
{make_lit_string("API_EXPORT_INLINE") , Item_Function } ,
|
||||
{make_lit_string("API_EXPORT_MACRO") , Item_Macro } ,
|
||||
{make_lit_string("CPP_NAME") , Item_CppName } ,
|
||||
{make_lit_string("TYPEDEF") , Item_Typedef } ,
|
||||
{make_lit_string("STRUCT") , Item_Struct } ,
|
||||
{make_lit_string("UNION") , Item_Union } ,
|
||||
{make_lit_string("ENUM") , Item_Enum } ,
|
||||
};
|
||||
|
||||
// NOTE(allen): Parse the internal string file.
|
||||
char *string_files[] = { INTERNAL_STRING, 0 };
|
||||
Meta_Unit string_unit = compile_meta_unit(part, ".", string_files, ExpandArray(meta_keywords));
|
||||
|
||||
if (string_unit.parse == 0){
|
||||
Assert(!"Missing one or more input files!");
|
||||
}
|
||||
|
||||
// NOTE(allen): Parse the version counter file
|
||||
i32 major_number = 0;
|
||||
i32 minor_number = 0;
|
||||
i32 build_number = 0;
|
||||
b32 parsed_version_counter = parse_build_number(BUILD_NUMBER_FILE, &major_number, &minor_number, &build_number);
|
||||
Assert(parsed_version_counter);
|
||||
|
||||
if (V_MAJ_NUM < major_number){
|
||||
Assert(!"major version mismatch");
|
||||
}
|
||||
else if (V_MAJ_NUM > major_number){
|
||||
major_number = V_MAJ_NUM;
|
||||
minor_number = V_MIN_NUM;
|
||||
build_number = 0;
|
||||
}
|
||||
else{
|
||||
if (V_MIN_NUM < minor_number){
|
||||
Assert(!"minor version mismatch");
|
||||
}
|
||||
else if (V_MIN_NUM > minor_number){
|
||||
minor_number = V_MIN_NUM;
|
||||
build_number = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): Output
|
||||
String out = str_alloc(part, 10 << 20);
|
||||
Out_Context context = {0};
|
||||
|
||||
// NOTE(allen): String Library
|
||||
if (begin_file_out(&context, GENERATED_FILE, &out)){
|
||||
Cpp_Token *token = 0;
|
||||
int32_t start = 0;
|
||||
|
||||
Parse parse = string_unit.parse[0];
|
||||
Parse_Context pcontext = setup_parse_context(parse);
|
||||
|
||||
for (; (token = get_token(&pcontext)) != 0; get_next_token(&pcontext)){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY) &&
|
||||
token->type == CPP_TOKEN_IDENTIFIER){
|
||||
String lexeme = get_lexeme(*token, pcontext.data);
|
||||
if (match_ss(lexeme, make_lit_string("FSTRING_BEGIN"))){
|
||||
start = token->start + token->size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
append_sc(&out, "/*\n");
|
||||
|
||||
append_sc(&out, GENERATED_FILE " - Version "V_MAJ"."V_MIN".");
|
||||
append_int_to_str(&out, build_number);
|
||||
append_sc(&out, "\n");
|
||||
|
||||
append_sc(&out, STANDARD_DISCLAIMER);
|
||||
append_sc(&out,
|
||||
"To include implementation: #define FSTRING_IMPLEMENTATION\n"
|
||||
"To use in C mode: #define FSTRING_C\n");
|
||||
|
||||
append_sc(&out, "*/\n");
|
||||
|
||||
String pstr = {0};
|
||||
int32_t do_whitespace_print = true;
|
||||
|
||||
for(;(token = get_next_token(&pcontext)) != 0;){
|
||||
if (do_whitespace_print){
|
||||
pstr = str_start_end(pcontext.data, start, token->start);
|
||||
append_ss(&out, pstr);
|
||||
}
|
||||
else{
|
||||
do_whitespace_print = true;
|
||||
}
|
||||
|
||||
String lexeme = get_lexeme(*token, pcontext.data);
|
||||
|
||||
int32_t do_print = true;
|
||||
if (match_ss(lexeme, make_lit_string("FSTRING_DECLS"))){
|
||||
append_sc(&out, "#if !defined(FCODER_STRING_H)\n#define FCODER_STRING_H\n\n");
|
||||
do_print = false;
|
||||
|
||||
static int32_t RETURN_PADDING = 16;
|
||||
static int32_t SIG_PADDING = 35;
|
||||
|
||||
for (int32_t j = 0; j < string_unit.set.count; ++j){
|
||||
char line_[2048];
|
||||
String line = make_fixed_width_string(line_);
|
||||
Item_Node *item = string_unit.set.items + j;
|
||||
|
||||
if (item->t == Item_Function){
|
||||
//append_ss (&line, item->marker);
|
||||
//append_padding (&line, ' ', RETURN_PADDING);
|
||||
append_ss (&line, item->ret);
|
||||
append_padding (&line, ' ', SIG_PADDING);
|
||||
append_ss (&line, item->name);
|
||||
append_ss (&line, item->args);
|
||||
append_sc (&line, ";\n");
|
||||
}
|
||||
else if (item->t == Item_Macro){
|
||||
append_ss (&line, make_lit_string("#ifndef "));
|
||||
append_padding (&line, ' ', 10);
|
||||
append_ss (&line, item->name);
|
||||
append_s_char (&line, '\n');
|
||||
|
||||
append_ss (&line, make_lit_string("# define "));
|
||||
append_padding (&line, ' ', 10);
|
||||
append_ss (&line, item->name);
|
||||
append_ss (&line, item->args);
|
||||
append_s_char (&line, ' ');
|
||||
append_ss (&line, item->body);
|
||||
append_s_char (&line, '\n');
|
||||
|
||||
append_ss (&line, make_lit_string("#endif"));
|
||||
append_s_char (&line, '\n');
|
||||
}
|
||||
else{
|
||||
InvalidCodePath;
|
||||
}
|
||||
|
||||
append_ss(&out, line);
|
||||
}
|
||||
|
||||
append_sc(&out, "\n#endif\n");
|
||||
|
||||
// NOTE(allen): C++ overload definitions
|
||||
append_sc(&out, "\n#if !defined(FSTRING_C) && !defined(FSTRING_GUARD)\n\n");
|
||||
|
||||
for (int32_t j = 0; j < string_unit.set.count; ++j){
|
||||
char line_space[2048];
|
||||
String line = make_fixed_width_string(line_space);
|
||||
|
||||
Item_Node *item = &string_unit.set.items[j];
|
||||
|
||||
if (item->t == Item_Function){
|
||||
String cpp_name = item->cpp_name;
|
||||
if (cpp_name.str != 0){
|
||||
Argument_Breakdown breakdown = item->breakdown;
|
||||
|
||||
append_ss (&line, item->ret);
|
||||
append_padding(&line, ' ', SIG_PADDING);
|
||||
append_ss (&line, cpp_name);
|
||||
append_ss (&line, item->args);
|
||||
if (match_ss(item->ret, make_lit_string("void"))){
|
||||
append_ss(&line, make_lit_string("{("));
|
||||
}
|
||||
else{
|
||||
append_ss(&line, make_lit_string("{return("));
|
||||
}
|
||||
append_ss (&line, item->name);
|
||||
append_s_char(&line, '(');
|
||||
|
||||
if (breakdown.count > 0){
|
||||
for (int32_t i = 0; i < breakdown.count; ++i){
|
||||
if (i != 0){
|
||||
append_s_char(&line, ',');
|
||||
}
|
||||
append_ss(&line, breakdown.args[i].param_name);
|
||||
}
|
||||
}
|
||||
else{
|
||||
append_ss(&line, make_lit_string("void"));
|
||||
}
|
||||
|
||||
append_ss(&line, make_lit_string("));}\n"));
|
||||
|
||||
append_ss(&out, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
append_sc(&out, "\n#endif\n");
|
||||
}
|
||||
|
||||
else if (match_ss(lexeme, make_lit_string("API_EXPORT_MACRO"))){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_COMMENT){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_PP_DEFINE){
|
||||
for (;(token = get_next_token(&pcontext)) != 0;){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (token != 0){
|
||||
get_prev_token(&pcontext);
|
||||
}
|
||||
do_print = false;
|
||||
do_whitespace_print = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (match_ss(lexeme, make_lit_string("API_EXPORT")) ||
|
||||
match_ss(lexeme, make_lit_string("API_EXPORT_INLINE"))){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
if (match_ss(lexeme, make_lit_string("API_EXPORT_INLINE"))){
|
||||
append_sc(&out, "#if !defined(FSTRING_GUARD)\n");
|
||||
}
|
||||
else{
|
||||
append_sc(&out, "#if defined(FSTRING_IMPLEMENTATION)\n");
|
||||
}
|
||||
print_function_body_code(&out, &pcontext, start);
|
||||
append_sc(&out, "\n#endif");
|
||||
do_print = false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (match_ss(lexeme, make_lit_string("CPP_NAME"))){
|
||||
Cpp_Token *token_start = token;
|
||||
int32_t has_cpp_name = false;
|
||||
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_PARENTHESE_OPEN){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_IDENTIFIER){
|
||||
token = get_next_token(&pcontext);
|
||||
if (token && token->type == CPP_TOKEN_PARENTHESE_CLOSE){
|
||||
has_cpp_name = true;
|
||||
do_print = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_cpp_name){
|
||||
token = set_token(&pcontext, token_start);
|
||||
}
|
||||
}
|
||||
|
||||
else if (token->type == CPP_TOKEN_COMMENT){
|
||||
if (check_and_fix_docs(&lexeme)){
|
||||
do_print = false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (token->type == CPP_PP_INCLUDE){
|
||||
token = get_next_token(&pcontext);
|
||||
|
||||
if (token && token->type == CPP_PP_INCLUDE_FILE){
|
||||
lexeme = get_lexeme(*token, pcontext.data);;
|
||||
lexeme.size -= 2;
|
||||
lexeme.str += 1;
|
||||
|
||||
char space[512];
|
||||
String str = make_fixed_width_string(space);
|
||||
append_ss(&str, lexeme);
|
||||
terminate_with_null(&str);
|
||||
String dump = file_dump(str.str);
|
||||
if (dump.str){
|
||||
append_ss(&out, dump);
|
||||
}
|
||||
else{
|
||||
lexeme.size += 2;
|
||||
lexeme.str -= 1;
|
||||
append_sc(&out, "#error Could not find ");
|
||||
append_ss(&out, lexeme);
|
||||
append_sc(&out, "\n");
|
||||
}
|
||||
free(dump.str);
|
||||
}
|
||||
|
||||
do_print = false;
|
||||
}
|
||||
|
||||
if ((token = get_token(&pcontext)) != 0){
|
||||
if (do_print){
|
||||
pstr = get_lexeme(*token, pcontext.data);
|
||||
append_ss(&out, pstr);
|
||||
}
|
||||
start = token->start + token->size;
|
||||
}
|
||||
}
|
||||
pstr = str_start_end(pcontext.data, start, parse.code.size);
|
||||
append_ss(&out, pstr);
|
||||
|
||||
end_file_out(context);
|
||||
}
|
||||
|
||||
// NOTE(allen): Publish the new file. (Would like to be able to automatically test the result before publishing).
|
||||
{
|
||||
make_folder_if_missing(BACKUP_FOLDER SLASH V_MAJ SLASH V_MIN, 0);
|
||||
file_move(BACKUP_FOLDER SLASH V_MAJ SLASH V_MIN, INTERNAL_STRING);
|
||||
file_move(BACKUP_FOLDER SLASH V_MAJ SLASH V_MIN, GENERATED_FILE);
|
||||
//file_move(PUBLISH_FOLDER, GENERATED_FILE);
|
||||
delete_file(GENERATED_FILE);
|
||||
printf("published "GENERATED_FILE": v%d.%d.%d\n", major_number, minor_number, build_number);
|
||||
save_build_number(BUILD_NUMBER_FILE, major_number, minor_number, build_number + 1);
|
||||
}
|
||||
|
||||
META_FINISH();
|
||||
}
|
||||
|
||||
#define FTECH_FILE_MOVING_IMPLEMENTATION
|
||||
#include "..\meta\4tech_file_moving.h"
|
||||
|
||||
// BOTTOM
|
||||
|
327
win32_4ed.cpp
327
win32_4ed.cpp
|
@ -11,50 +11,23 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "common/4coder_defines.h"
|
||||
#include "common/4coder_version.h"
|
||||
#include "4tech_defines.h"
|
||||
#include "4coder_API/version.h"
|
||||
|
||||
#if defined(FRED_SUPER)
|
||||
# include "4coder_API/keycodes.h"
|
||||
# include "4coder_API/style.h"
|
||||
|
||||
# define FSTRING_IMPLEMENTATION
|
||||
# define FSTRING_C
|
||||
# include "4coder_string.h"
|
||||
# include "4coder_lib/4coder_string.h"
|
||||
# include "4coder_lib/4coder_mem.h"
|
||||
|
||||
# include "4coder_keycodes.h"
|
||||
# include "4coder_style.h"
|
||||
# include "4coder_rect.h"
|
||||
# include "4coder_mem.h"
|
||||
# include "4cpp_lexer.h"
|
||||
|
||||
// TODO(allen): This is duplicated from 4coder_custom.h
|
||||
// I need to work out a way to avoid this.
|
||||
#define VIEW_ROUTINE_SIG(name) void name(struct Application_Links *app, int32_t view_id)
|
||||
#define GET_BINDING_DATA(name) int32_t name(void *data, int32_t size)
|
||||
#define _GET_VERSION_SIG(n) int32_t n(int32_t maj, int32_t min, int32_t patch)
|
||||
|
||||
typedef VIEW_ROUTINE_SIG(View_Routine_Function);
|
||||
typedef GET_BINDING_DATA(Get_Binding_Data_Function);
|
||||
typedef _GET_VERSION_SIG(_Get_Version_Function);
|
||||
|
||||
struct Custom_API{
|
||||
View_Routine_Function *view_routine;
|
||||
Get_Binding_Data_Function *get_bindings;
|
||||
_Get_Version_Function *get_alpha_4coder_version;
|
||||
};
|
||||
|
||||
|
||||
typedef void Custom_Command_Function;
|
||||
#include "4coder_types.h"
|
||||
struct Application_Links;
|
||||
# include "4coder_custom_api.h"
|
||||
# include "4coder_API/types.h"
|
||||
# include "4ed_os_custom_api.h"
|
||||
|
||||
#else
|
||||
# include "4coder_default_bindings.cpp"
|
||||
|
||||
# define FSTRING_IMPLEMENTATION
|
||||
# define FSTRING_C
|
||||
# include "4coder_string.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include "4ed_math.h"
|
||||
|
@ -203,8 +176,8 @@ typedef struct Win32_Vars{
|
|||
|
||||
} Win32_Vars;
|
||||
|
||||
globalvar Win32_Vars win32vars;
|
||||
globalvar Application_Memory memory_vars;
|
||||
global Win32_Vars win32vars;
|
||||
global Application_Memory memory_vars;
|
||||
|
||||
|
||||
//
|
||||
|
@ -245,6 +218,48 @@ Win32Ptr(void *h){
|
|||
// Memory (not exposed to application, but needed in system_shared.cpp)
|
||||
//
|
||||
|
||||
internal
|
||||
Sys_Memory_Allocate_Sig(system_memory_allocate){
|
||||
void *result = VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Memory_Set_Protection_Sig(system_memory_set_protection){
|
||||
bool32 result = false;
|
||||
DWORD old_protect = 0;
|
||||
DWORD protect = 0;
|
||||
|
||||
flags = flags & 0x7;
|
||||
|
||||
switch (flags){
|
||||
case 0: protect = PAGE_NOACCESS; break;
|
||||
|
||||
case MemProtect_Read: protect = PAGE_READONLY; break;
|
||||
|
||||
case MemProtect_Write:
|
||||
case MemProtect_Read|MemProtect_Write:
|
||||
protect = PAGE_READWRITE; break;
|
||||
|
||||
case MemProtect_Execute: protect = PAGE_EXECUTE; break;
|
||||
|
||||
case MemProtect_Execute|MemProtect_Read: protect = PAGE_EXECUTE_READ; break;
|
||||
|
||||
case MemProtect_Execute|MemProtect_Write:
|
||||
case MemProtect_Execute|MemProtect_Write|MemProtect_Read:
|
||||
protect = PAGE_EXECUTE_READWRITE; break;
|
||||
}
|
||||
|
||||
VirtualProtect(ptr, size, protect, &old_protect);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Memory_Free_Sig(system_memory_free){
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
// TODO(allen): delete
|
||||
internal
|
||||
Sys_Get_Memory_Sig(system_get_memory_){
|
||||
void *ptr = 0;
|
||||
|
@ -254,6 +269,7 @@ Sys_Get_Memory_Sig(system_get_memory_){
|
|||
return(ptr);
|
||||
}
|
||||
|
||||
// TODO(allen): delete
|
||||
internal
|
||||
Sys_Free_Memory_Sig(system_free_memory){
|
||||
if (block){
|
||||
|
@ -317,7 +333,7 @@ JobThreadProc(LPVOID lpParameter){
|
|||
Thread_Memory *thread_memory = win32vars.thread_memory + thread_index;
|
||||
|
||||
if (thread_memory->size == 0){
|
||||
i32 new_size = Kbytes(64);
|
||||
i32 new_size = KB(64);
|
||||
thread_memory->data = Win32GetMemory(new_size);
|
||||
thread_memory->size = new_size;
|
||||
}
|
||||
|
@ -575,13 +591,10 @@ Sys_Check_Cancel_Sig(system_check_cancel){
|
|||
|
||||
internal
|
||||
Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
|
||||
void *old_data;
|
||||
i32 old_size, new_size;
|
||||
|
||||
system_acquire_lock(CANCEL_LOCK0 + memory->id - 1);
|
||||
old_data = memory->data;
|
||||
old_size = memory->size;
|
||||
new_size = l_round_up_i32(memory->size*2, Kbytes(4));
|
||||
void *old_data = memory->data;
|
||||
i32 old_size = memory->size;
|
||||
i32 new_size = l_round_up(memory->size*2, KB(4));
|
||||
memory->data = system_get_memory(new_size);
|
||||
memory->size = new_size;
|
||||
if (old_data){
|
||||
|
@ -593,13 +606,15 @@ Sys_Grow_Thread_Memory_Sig(system_grow_thread_memory){
|
|||
|
||||
#if FRED_INTERNAL
|
||||
internal void
|
||||
INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){
|
||||
INTERNAL_get_thread_states(Thread_Group_ID id, b8 *running, i32 *pending){
|
||||
Thread_Group *group = win32vars.groups + id;
|
||||
Unbounded_Work_Queue *source_queue = &group->queue;
|
||||
Work_Queue *queue = win32vars.queues + id;
|
||||
u32 write = queue->write_position;
|
||||
u32 read = queue->read_position;
|
||||
if (write < read) write += QUEUE_WRAP;
|
||||
if (write < read){
|
||||
write += QUEUE_WRAP;
|
||||
}
|
||||
*pending = (i32)(write - read) + source_queue->count - source_queue->skip;
|
||||
|
||||
for (i32 i = 0; i < group->count; ++i){
|
||||
|
@ -996,6 +1011,76 @@ Sys_Get_Binary_Path_Sig(system_get_binary_path){
|
|||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_File_Exists_Sig(system_file_exists){
|
||||
char full_filename_space[1024];
|
||||
String full_filename;
|
||||
HANDLE file;
|
||||
b32 result = 0;
|
||||
|
||||
if (len < sizeof(full_filename_space)){
|
||||
full_filename = make_fixed_width_string(full_filename_space);
|
||||
copy_ss(&full_filename, make_string(filename, len));
|
||||
terminate_with_null(&full_filename);
|
||||
|
||||
file = CreateFile(full_filename.str, GENERIC_READ, 0, 0,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
|
||||
if (file != INVALID_HANDLE_VALUE){
|
||||
CloseHandle(file);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Directory_CD_Sig(system_directory_cd){
|
||||
String directory = make_string_cap(dir, *len, cap);
|
||||
b32 result = 0;
|
||||
i32 old_size;
|
||||
|
||||
char rel_path_space[1024];
|
||||
String rel_path_string = make_fixed_width_string(rel_path_space);
|
||||
copy_ss(&rel_path_string, make_string(rel_path, rel_len));
|
||||
terminate_with_null(&rel_path_string);
|
||||
|
||||
if (rel_path[0] != 0){
|
||||
if (rel_path[0] == '.' && rel_path[1] == 0){
|
||||
result = 1;
|
||||
}
|
||||
else if (rel_path[0] == '.' && rel_path[1] == '.' && rel_path[2] == 0){
|
||||
result = remove_last_folder(&directory);
|
||||
terminate_with_null(&directory);
|
||||
}
|
||||
else{
|
||||
if (directory.size + rel_len + 1 > directory.memory_size){
|
||||
old_size = directory.size;
|
||||
append_partial_sc(&directory, rel_path);
|
||||
append_s_char(&directory, '\\');
|
||||
if (Win32DirectoryExists(directory.str)){
|
||||
result = 1;
|
||||
}
|
||||
else{
|
||||
directory.size = old_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*len = directory.size;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Get_4ed_Path_Sig(system_get_4ed_path){
|
||||
String str = make_string_cap(out, 0, capacity);
|
||||
int32_t size = system_get_binary_path(&str);
|
||||
return(size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
NOTE(casey): This follows Raymond Chen's prescription
|
||||
|
@ -1031,8 +1116,6 @@ Win32ToggleFullscreen(void){
|
|||
}
|
||||
}
|
||||
|
||||
#include "win32_api_impl.cpp"
|
||||
|
||||
//
|
||||
// Clipboard
|
||||
//
|
||||
|
@ -1206,10 +1289,12 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
|
|||
DWORD result = 0;
|
||||
|
||||
if (WaitForSingleObject(proc, 0) == WAIT_OBJECT_0){
|
||||
if (GetExitCodeProcess(proc, &result) == 0)
|
||||
if (GetExitCodeProcess(proc, &result) == 0){
|
||||
cli->exit = -1;
|
||||
else
|
||||
}
|
||||
else{
|
||||
cli->exit = (i32)result;
|
||||
}
|
||||
|
||||
close_me = 1;
|
||||
CloseHandle(*(HANDLE*)&cli->proc);
|
||||
|
@ -1221,6 +1306,59 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
|
|||
return(close_me);
|
||||
}
|
||||
|
||||
//
|
||||
// Appearence Settings
|
||||
//
|
||||
|
||||
// TODO(allen): add a "shown but auto-hides on timer" setting here.
|
||||
internal
|
||||
Sys_Show_Mouse_Cursor_Sig(system_show_mouse_cursor){
|
||||
switch (show){
|
||||
case MouseCursorShow_Never:
|
||||
ShowCursor(false);
|
||||
break;
|
||||
|
||||
case MouseCursorShow_Always:
|
||||
ShowCursor(true);
|
||||
break;
|
||||
|
||||
// TODO(allen): MouseCursor_HideWhenStill
|
||||
}
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Toggle_Fullscreen_Sig(system_toggle_fullscreen){
|
||||
/* NOTE(allen): Don't actually change window size now!
|
||||
Tell the platform layer to do the toggle (or to cancel the toggle)
|
||||
later when the app.step function isn't running. If the size changes
|
||||
mid step, it messes up the rendering rules and stuff. */
|
||||
|
||||
b32 success = false;
|
||||
|
||||
// NOTE(allen): On windows we must be in stream mode to go fullscreen.
|
||||
if (win32vars.settings.stream_mode){
|
||||
win32vars.do_toggle = !win32vars.do_toggle;
|
||||
success = true;
|
||||
}
|
||||
|
||||
return(success);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Is_Fullscreen_Sig(system_is_fullscreen){
|
||||
/* NOTE(allen): This is a fancy way to say 'full_screen XOR do_toggle'
|
||||
This way this function can always report the state the fullscreen
|
||||
will have when the next frame runs, given the number of toggles
|
||||
that have occurred this frame and the original value. */
|
||||
bool32 result = (win32vars.full_screen + win32vars.do_toggle) & 1;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
|
||||
win32vars.send_exit_signal = 1;
|
||||
}
|
||||
|
||||
#include "4ed_system_shared.cpp"
|
||||
|
||||
#if USE_FT_FONTS
|
||||
|
@ -1239,14 +1377,14 @@ size_change(i32 dpi_x, i32 dpi_y){
|
|||
internal
|
||||
Font_Load_Sig(system_draw_font_load){
|
||||
if (win32vars.font_part.base == 0){
|
||||
win32vars.font_part = Win32ScratchPartition(Mbytes(8));
|
||||
win32vars.font_part = Win32ScratchPartition(MB(8));
|
||||
}
|
||||
|
||||
i32 oversample = 2;
|
||||
AllowLocal(oversample);
|
||||
|
||||
#if SUPPORT_DPI
|
||||
pt_size = ROUND32(pt_size * size_change(win32vars.dpi_x, win32vars.dpi_y));
|
||||
pt_size = round32(pt_size * size_change(win32vars.dpi_x, win32vars.dpi_y));
|
||||
#endif
|
||||
|
||||
for (b32 success = 0; success == 0;){
|
||||
|
@ -1331,19 +1469,6 @@ Win32LoadSystemCode(){
|
|||
|
||||
win32vars.system.now_time = system_now_time;
|
||||
|
||||
win32vars.system.memory_allocate = Memory_Allocate;
|
||||
win32vars.system.memory_set_protection = Memory_Set_Protection;
|
||||
win32vars.system.memory_free = Memory_Free;
|
||||
|
||||
win32vars.system.file_exists = File_Exists;
|
||||
win32vars.system.directory_cd = Directory_CD;
|
||||
win32vars.system.get_4ed_path = Get_4ed_Path;
|
||||
win32vars.system.show_mouse_cursor = Show_Mouse_Cursor;
|
||||
|
||||
win32vars.system.toggle_fullscreen = Toggle_Fullscreen;
|
||||
win32vars.system.is_fullscreen = Is_Fullscreen;
|
||||
win32vars.system.send_exit_signal = Send_Exit_Signal;
|
||||
|
||||
win32vars.system.post_clipboard = system_post_clipboard;
|
||||
|
||||
win32vars.system.create_coroutine = system_create_coroutine;
|
||||
|
@ -1363,6 +1488,17 @@ Win32LoadSystemCode(){
|
|||
win32vars.system.acquire_lock = system_acquire_lock;
|
||||
win32vars.system.release_lock = system_release_lock;
|
||||
|
||||
win32vars.system.memory_allocate = system_memory_allocate;
|
||||
win32vars.system.memory_set_protection = system_memory_set_protection;
|
||||
win32vars.system.memory_free = system_memory_free;
|
||||
win32vars.system.file_exists = system_file_exists;
|
||||
win32vars.system.directory_cd = system_directory_cd;
|
||||
win32vars.system.get_4ed_path = system_get_4ed_path;
|
||||
win32vars.system.toggle_fullscreen = system_toggle_fullscreen;
|
||||
win32vars.system.is_fullscreen = system_is_fullscreen;win32vars.system.show_mouse_cursor = system_show_mouse_cursor;
|
||||
win32vars.system.send_exit_signal = system_send_exit_signal;
|
||||
|
||||
|
||||
#if FRED_INTERNAL
|
||||
win32vars.system.internal_get_thread_states = INTERNAL_get_thread_states;
|
||||
#endif
|
||||
|
@ -1382,7 +1518,7 @@ Win32LoadRenderCode(){
|
|||
// Helpers
|
||||
//
|
||||
|
||||
globalvar u8 keycode_lookup_table[255];
|
||||
global u8 keycode_lookup_table[255];
|
||||
|
||||
internal void
|
||||
Win32KeycodeInit(){
|
||||
|
@ -1855,37 +1991,31 @@ WinMain(HINSTANCE hInstance,
|
|||
|
||||
LPVOID base;
|
||||
#if FRED_INTERNAL
|
||||
base = (LPVOID)Tbytes(1);
|
||||
base = (LPVOID)TB(1);
|
||||
#else
|
||||
base = (LPVOID)0;
|
||||
#endif
|
||||
|
||||
memory_vars.vars_memory_size = Mbytes(2);
|
||||
memory_vars.vars_memory = VirtualAlloc(base, memory_vars.vars_memory_size,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_READWRITE);
|
||||
memory_vars.vars_memory_size = MB(2);
|
||||
memory_vars.vars_memory = VirtualAlloc(base, memory_vars.vars_memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
#if FRED_INTERNAL
|
||||
base = (LPVOID)Tbytes(2);
|
||||
base = (LPVOID)TB(2);
|
||||
#else
|
||||
base = (LPVOID)0;
|
||||
#endif
|
||||
memory_vars.target_memory_size = Mbytes(512);
|
||||
memory_vars.target_memory =
|
||||
VirtualAlloc(base, memory_vars.target_memory_size,
|
||||
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
memory_vars.target_memory_size = MB(512);
|
||||
memory_vars.target_memory = VirtualAlloc(base, memory_vars.target_memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
base = (LPVOID)0;
|
||||
memory_vars.user_memory_size = Mbytes(2);
|
||||
memory_vars.user_memory =
|
||||
VirtualAlloc(base, memory_vars.target_memory_size,
|
||||
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
memory_vars.user_memory_size = MB(2);
|
||||
memory_vars.user_memory = VirtualAlloc(base, memory_vars.target_memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
if (!memory_vars.vars_memory){
|
||||
exit(1);
|
||||
}
|
||||
|
||||
win32vars.target.max = Mbytes(1);
|
||||
win32vars.target.max = MB(1);
|
||||
win32vars.target.push_buffer = (char*)system_get_memory(win32vars.target.max);
|
||||
|
||||
|
||||
|
@ -1943,7 +2073,7 @@ WinMain(HINSTANCE hInstance,
|
|||
//
|
||||
|
||||
#if defined(FRED_SUPER)
|
||||
char *custom_file_default = "4coder_custom.dll";
|
||||
char *custom_file_default = "custom_4coder.dll";
|
||||
char *custom_file = 0;
|
||||
if (win32vars.settings.custom_dll) custom_file = win32vars.settings.custom_dll;
|
||||
else custom_file = custom_file_default;
|
||||
|
@ -1966,13 +2096,6 @@ WinMain(HINSTANCE hInstance,
|
|||
}
|
||||
win32vars.custom_api.get_bindings = (Get_Binding_Data_Function*)
|
||||
GetProcAddress(win32vars.custom, "get_bindings");
|
||||
|
||||
// NOTE(allen): I am temporarily taking the view routine
|
||||
// back out, it will be back soon.
|
||||
#if 0
|
||||
win32vars.custom_api.view_routine = (View_Routine_Function*)
|
||||
GetProcAddress(win32vars.custom, "view_routine");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (win32vars.custom_api.get_bindings == 0){
|
||||
|
@ -1984,15 +2107,6 @@ WinMain(HINSTANCE hInstance,
|
|||
win32vars.custom_api.get_bindings = (Get_Binding_Data_Function*)get_bindings;
|
||||
#endif
|
||||
|
||||
win32vars.custom_api.view_routine = (View_Routine_Function*)0;
|
||||
|
||||
#if 0
|
||||
if (win32vars.custom_api.view_routine == 0){
|
||||
win32vars.custom_api.view_routine = (View_Routine_Function*)view_routine;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Window and GL Initialization
|
||||
//
|
||||
|
@ -2232,10 +2346,21 @@ WinMain(HINSTANCE hInstance,
|
|||
if (GetCursorPos(&mouse_point) &&
|
||||
ScreenToClient(win32vars.window_handle, &mouse_point)){
|
||||
|
||||
i32_Rect screen =
|
||||
i32R(0, 0, win32vars.target.width, win32vars.target.height);
|
||||
i32_Rect screen;
|
||||
screen.x0 = 0;
|
||||
screen.y0 = 0;
|
||||
screen.x1 = win32vars.target.width;
|
||||
screen.y1 = win32vars.target.height;
|
||||
|
||||
if (!hit_check(mouse_point.x, mouse_point.y, screen)){
|
||||
i32 mx = mouse_point.x;
|
||||
i32 my = mouse_point.y;
|
||||
|
||||
b32 is_hit = false;
|
||||
if (mx >= screen.x0 && mx < screen.x1 && my >= screen.y0 && my < screen.y1){
|
||||
is_hit = true;
|
||||
}
|
||||
|
||||
if (!is_hit){
|
||||
win32vars.input_chunk.trans.out_of_window = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
/*
|
||||
Implementation of system level functions that get exposed straight
|
||||
into the 4coder custom API. This file need not be split on other platforms,
|
||||
as this is the only one that will be used for generating headers and docs.
|
||||
-Allen
|
||||
|
||||
27.06.2016 (dd.mm.yyyy)
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#define API_EXPORT
|
||||
|
||||
API_EXPORT void*
|
||||
Memory_Allocate(Application_Links *app, int32_t size)
|
||||
/*
|
||||
DOC_PARAM(size, The size in bytes of the block that should be returned.)
|
||||
DOC(This calls to a low level OS allocator which means it is best used
|
||||
for infrequent, large allocations. The size of the block must be remembered
|
||||
if it will be freed or if it's mem protection status will be changed.)
|
||||
DOC_SEE(memory_free)
|
||||
*/{
|
||||
void *result = VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Memory_Set_Protection(Application_Links *app, void *ptr, int32_t size, Memory_Protect_Flags flags)
|
||||
/*
|
||||
DOC_PARAM(ptr, The base of the block on which to set memory protection flags.)
|
||||
DOC_PARAM(size, The size that was originally used to allocate this block.)
|
||||
DOC_PARAM(flags, The new memory protection flags.)
|
||||
DOC(This call sets the memory protection flags of a block of memory that was previously
|
||||
allocate by memory_allocate.)
|
||||
DOC_SEE(memory_allocate)
|
||||
DOC_SEE(Memory_Protect_Flags)
|
||||
*/{
|
||||
bool32 result = false;
|
||||
DWORD old_protect = 0;
|
||||
DWORD protect = 0;
|
||||
|
||||
flags = flags & 0x7;
|
||||
|
||||
switch (flags){
|
||||
case 0: protect = PAGE_NOACCESS; break;
|
||||
|
||||
case MemProtect_Read: protect = PAGE_READONLY; break;
|
||||
|
||||
case MemProtect_Write:
|
||||
case MemProtect_Read|MemProtect_Write:
|
||||
protect = PAGE_READWRITE; break;
|
||||
|
||||
case MemProtect_Execute: protect = PAGE_EXECUTE; break;
|
||||
|
||||
case MemProtect_Execute|MemProtect_Read: protect = PAGE_EXECUTE_READ; break;
|
||||
|
||||
case MemProtect_Execute|MemProtect_Write:
|
||||
case MemProtect_Execute|MemProtect_Write|MemProtect_Read:
|
||||
protect = PAGE_EXECUTE_READWRITE; break;
|
||||
}
|
||||
|
||||
VirtualProtect(ptr, size, protect, &old_protect);
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Memory_Free(Application_Links *app, void *ptr, int32_t size)/*
|
||||
DOC_PARAM(mem, The base of a block to free.)
|
||||
DOC_PARAM(size, The size that was originally used to allocate this block.)
|
||||
DOC(This call frees a block of memory that was previously allocated by
|
||||
memory_allocate.)
|
||||
DOC_SEE(memory_allocate)
|
||||
*/{
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
File_Exists(Application_Links *app, char *filename, int32_t len)/*
|
||||
DOC_PARAM(filename, This parameter specifies the full path to a file; it need not be null terminated.)
|
||||
DOC_PARAM(len, This parameter specifies the length of the filename string.)
|
||||
DOC_RETURN(This call returns non-zero if and only if the file exists.)
|
||||
*/{
|
||||
char full_filename_space[1024];
|
||||
String full_filename;
|
||||
HANDLE file;
|
||||
b32 result = 0;
|
||||
|
||||
if (len < sizeof(full_filename_space)){
|
||||
full_filename = make_fixed_width_string(full_filename_space);
|
||||
copy_ss(&full_filename, make_string(filename, len));
|
||||
terminate_with_null(&full_filename);
|
||||
|
||||
file = CreateFile(full_filename.str, GENERIC_READ, 0, 0,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
|
||||
if (file != INVALID_HANDLE_VALUE){
|
||||
CloseHandle(file);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Directory_CD(Application_Links *app, char *dir, int32_t *len, int32_t capacity, char *rel_path, int32_t rel_len)/*
|
||||
DOC_PARAM(dir, This parameter provides a character buffer that stores a directory; it need not be null terminated.)
|
||||
DOC_PARAM(len, This parameter specifies the length of the dir string.)
|
||||
DOC_PARAM(capacity, This parameter specifies the maximum size of the dir string.)
|
||||
DOC_PARAM(rel_path, This parameter specifies the path to change to, may include '.' or '..'; it need not be null terminated.)
|
||||
DOC_PARAM(rel_len, This parameter specifies the length of the rel_path string.)
|
||||
DOC_RETURN(This call returns non-zero if the call succeeds.)
|
||||
DOC
|
||||
(
|
||||
This call succeeds if the new directory exists and the it fits inside the
|
||||
dir buffer. If the call succeeds the dir buffer is filled with the new
|
||||
directory and len is overwritten with the length of the new string in the buffer.
|
||||
|
||||
For instance if dir contains "C:/Users/MySelf" and rel is "Documents" the buffer
|
||||
will contain "C:/Users/MySelf/Documents" and len will contain the length of that
|
||||
string. This call can also be used with rel set to ".." to traverse to parent
|
||||
folders.
|
||||
)
|
||||
*/{
|
||||
String directory = make_string_cap(dir, *len, capacity);
|
||||
b32 result = 0;
|
||||
i32 old_size;
|
||||
|
||||
char rel_path_space[1024];
|
||||
String rel_path_string = make_fixed_width_string(rel_path_space);
|
||||
copy_ss(&rel_path_string, make_string(rel_path, rel_len));
|
||||
terminate_with_null(&rel_path_string);
|
||||
|
||||
if (rel_path[0] != 0){
|
||||
if (rel_path[0] == '.' && rel_path[1] == 0){
|
||||
result = 1;
|
||||
}
|
||||
else if (rel_path[0] == '.' && rel_path[1] == '.' && rel_path[2] == 0){
|
||||
result = remove_last_folder(&directory);
|
||||
terminate_with_null(&directory);
|
||||
}
|
||||
else{
|
||||
if (directory.size + rel_len + 1 > directory.memory_size){
|
||||
old_size = directory.size;
|
||||
append_partial_sc(&directory, rel_path);
|
||||
append_s_char(&directory, '\\');
|
||||
if (Win32DirectoryExists(directory.str)){
|
||||
result = 1;
|
||||
}
|
||||
else{
|
||||
directory.size = old_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*len = directory.size;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT int32_t
|
||||
Get_4ed_Path(Application_Links *app, char *out, int32_t capacity)
|
||||
/*
|
||||
DOC_PARAM(out, This parameter provides a character buffer that receives the path to the 4ed executable file.)
|
||||
DOC_PARAM(capacity, This parameter specifies the maximum capacity of the out buffer.)
|
||||
DOC_RETURN(This call returns non-zero on success.)
|
||||
*/{
|
||||
String str = make_string_cap(out, 0, capacity);
|
||||
int32_t size = system_get_binary_path(&str);
|
||||
return(size);
|
||||
}
|
||||
|
||||
// TODO(allen): add a "shown but auto-hides on timer" setting here.
|
||||
API_EXPORT void
|
||||
Show_Mouse_Cursor(Application_Links *app, Mouse_Cursor_Show_Type show)
|
||||
/*
|
||||
DOC_PARAM(show, This parameter specifies the new state of the mouse cursor.)
|
||||
DOC_SEE(Mouse_Cursor_Show_Type)
|
||||
*/{
|
||||
switch (show){
|
||||
case MouseCursorShow_Never:
|
||||
ShowCursor(false);
|
||||
break;
|
||||
|
||||
case MouseCursorShow_Always:
|
||||
ShowCursor(true);
|
||||
break;
|
||||
|
||||
// TODO(allen): MouseCursor_HideWhenStill
|
||||
}
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Toggle_Fullscreen(Application_Links *app)
|
||||
/*
|
||||
DOC(This call tells 4coder to switch into or out of full screen mode.
|
||||
The changes of full screen mode do not take effect until the end of the current frame.
|
||||
On Windows this call will not work unless 4coder was started in "stream mode".
|
||||
Stream mode can be enabled with -S or -F flags on the command line to 4ed.)
|
||||
*/{
|
||||
/* NOTE(allen): Don't actually change window size now!
|
||||
Tell the platform layer to do the toggle (or to cancel the toggle)
|
||||
later when the app.step function isn't running. If the size changes
|
||||
mid step, it messes up the rendering rules and stuff. */
|
||||
|
||||
// NOTE(allen): On windows we must be in stream mode to go fullscreen.
|
||||
if (win32vars.settings.stream_mode){
|
||||
win32vars.do_toggle = !win32vars.do_toggle;
|
||||
}
|
||||
else{
|
||||
print_message(app, literal("WARNING: Cannot go full screen unless 4coder is in stream mode\n Use the flag -S to put 4coder in stream mode.\n"));
|
||||
}
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
Is_Fullscreen(Application_Links *app)
|
||||
/*
|
||||
DOC(This call returns true if the 4coder is in full screen mode. This call
|
||||
takes toggles that have already occured this frame into account. So it may return
|
||||
true even though the frame has not ended and actually put 4coder into full screen. If
|
||||
it returns true though, 4coder will definitely be full screen by the beginning of the next
|
||||
frame if the state is not changed.)
|
||||
*/{
|
||||
/* NOTE(allen): This is a fancy way to say 'full_screen XOR do_toggle'
|
||||
This way this function can always report the state the fullscreen
|
||||
will have when the next frame runs, given the number of toggles
|
||||
that have occurred this frame and the original value. */
|
||||
bool32 result = (win32vars.full_screen + win32vars.do_toggle) & 1;
|
||||
return(result);
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
Send_Exit_Signal(Application_Links *app)
|
||||
/*
|
||||
DOC(This call sends a signal to 4coder to attempt to exit. If there are unsaved
|
||||
files this triggers a dialogue ensuring you're okay with closing.)
|
||||
*/{
|
||||
win32vars.send_exit_signal = 1;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
Loading…
Reference in New Issue