Merge branch 'master' of https://bitbucket.org/4coder/4coder
commit
9b4f29d4a7
|
@ -172,55 +172,57 @@ typedef struct File_List{
|
|||
|
||||
enum Command_ID{
|
||||
cmdid_null,
|
||||
cmdid_write_character,
|
||||
|
||||
cmdid_seek_left,
|
||||
cmdid_seek_right,
|
||||
cmdid_seek_whitespace_up,
|
||||
cmdid_seek_whitespace_down,
|
||||
|
||||
cmdid_center_view,
|
||||
|
||||
cmdid_word_complete,
|
||||
cmdid_set_mark,
|
||||
|
||||
cmdid_copy,
|
||||
cmdid_cut,
|
||||
cmdid_paste,
|
||||
cmdid_paste_next,
|
||||
cmdid_delete_range,
|
||||
|
||||
cmdid_undo,
|
||||
cmdid_redo,
|
||||
cmdid_history_backward,
|
||||
cmdid_history_forward,
|
||||
|
||||
cmdid_interactive_new,
|
||||
cmdid_interactive_open,
|
||||
cmdid_reopen,
|
||||
cmdid_save,
|
||||
cmdid_change_active_panel,
|
||||
cmdid_interactive_switch_buffer,
|
||||
cmdid_interactive_kill_buffer,
|
||||
cmdid_kill_buffer,
|
||||
cmdid_toggle_line_wrap,
|
||||
cmdid_toggle_endline_mode,
|
||||
|
||||
cmdid_change_active_panel,
|
||||
|
||||
cmdid_to_uppercase,
|
||||
cmdid_to_lowercase,
|
||||
|
||||
cmdid_toggle_line_wrap,
|
||||
cmdid_toggle_show_whitespace,
|
||||
cmdid_clean_all_lines,
|
||||
|
||||
cmdid_eol_dosify,
|
||||
cmdid_eol_nixify,
|
||||
|
||||
cmdid_clean_all_lines,
|
||||
cmdid_auto_tab_range,
|
||||
|
||||
cmdid_open_panel_vsplit,
|
||||
cmdid_open_panel_hsplit,
|
||||
cmdid_close_panel,
|
||||
cmdid_move_left,
|
||||
cmdid_move_right,
|
||||
cmdid_delete,
|
||||
cmdid_backspace,
|
||||
cmdid_move_up,
|
||||
cmdid_move_down,
|
||||
|
||||
cmdid_seek_end_of_line,
|
||||
cmdid_seek_beginning_of_line,
|
||||
cmdid_page_up,
|
||||
cmdid_page_down,
|
||||
cmdid_open_color_tweaker,
|
||||
cmdid_cursor_mark_swap,
|
||||
|
||||
cmdid_open_color_tweaker,
|
||||
cmdid_open_menu,
|
||||
cmdid_hide_scrollbar,
|
||||
cmdid_show_scrollbar,
|
||||
|
@ -240,6 +242,7 @@ enum Param_ID{
|
|||
par_lex_as_cpp_file,
|
||||
par_wrap_lines,
|
||||
par_key_mapid,
|
||||
par_show_whitespace,
|
||||
par_cli_path,
|
||||
par_cli_command,
|
||||
par_clear_blank_lines,
|
||||
|
@ -270,9 +273,9 @@ enum Special_Hook_ID{
|
|||
_hook_scroll_rule = hook_type_count,
|
||||
};
|
||||
|
||||
// NOTE(allen): None of the members of *_Summary structs nor any of the
|
||||
// data pointed to by the members should be modified, I would have made
|
||||
// them all const... but that causes a lot problems for C++ reasons.
|
||||
// None of the members of *_Summary structs nor any of the data pointed
|
||||
// to by the members should be modified, I would have made them all
|
||||
// const... but that causes a lot problems for C++ reasons.
|
||||
struct Buffer_Summary{
|
||||
int exists;
|
||||
int ready;
|
||||
|
@ -305,8 +308,9 @@ struct View_Summary{
|
|||
Full_Cursor cursor;
|
||||
Full_Cursor mark;
|
||||
float preferred_x;
|
||||
int line_height;
|
||||
float line_height;
|
||||
int unwrapped_lines;
|
||||
int show_whitespace;
|
||||
};
|
||||
inline View_Summary
|
||||
view_summary_zero(){
|
||||
|
|
|
@ -11,12 +11,8 @@
|
|||
#define GET_BUFFER_FIRST_SIG(n) Buffer_Summary n(Application_Links *app)
|
||||
#define GET_BUFFER_NEXT_SIG(n) void n(Application_Links *app, Buffer_Summary *buffer)
|
||||
#define GET_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int index)
|
||||
#define GET_ACTIVE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app)
|
||||
#define GET_PARAMETER_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int param_index)
|
||||
#define GET_BUFFER_BY_NAME_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int len)
|
||||
#define BUFFER_SEEK_DELIMITER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
|
||||
#define BUFFER_SEEK_STRING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||
#define BUFFER_SEEK_STRING_INSENSITIVE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||
#define REFRESH_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer)
|
||||
#define BUFFER_READ_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out)
|
||||
#define BUFFER_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len)
|
||||
|
@ -56,12 +52,8 @@ extern "C"{
|
|||
typedef GET_BUFFER_FIRST_SIG(Get_Buffer_First_Function);
|
||||
typedef GET_BUFFER_NEXT_SIG(Get_Buffer_Next_Function);
|
||||
typedef GET_BUFFER_SIG(Get_Buffer_Function);
|
||||
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
|
||||
typedef GET_PARAMETER_BUFFER_SIG(Get_Parameter_Buffer_Function);
|
||||
typedef GET_BUFFER_BY_NAME_SIG(Get_Buffer_By_Name_Function);
|
||||
typedef BUFFER_SEEK_DELIMITER_SIG(Buffer_Seek_Delimiter_Function);
|
||||
typedef BUFFER_SEEK_STRING_SIG(Buffer_Seek_String_Function);
|
||||
typedef BUFFER_SEEK_STRING_INSENSITIVE_SIG(Buffer_Seek_String_Insensitive_Function);
|
||||
typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function);
|
||||
typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function);
|
||||
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
|
||||
|
@ -104,12 +96,8 @@ struct Application_Links{
|
|||
Get_Buffer_First_Function *get_buffer_first;
|
||||
Get_Buffer_Next_Function *get_buffer_next;
|
||||
Get_Buffer_Function *get_buffer;
|
||||
Get_Active_Buffer_Function *get_active_buffer;
|
||||
Get_Parameter_Buffer_Function *get_parameter_buffer;
|
||||
Get_Buffer_By_Name_Function *get_buffer_by_name;
|
||||
Buffer_Seek_Delimiter_Function *buffer_seek_delimiter;
|
||||
Buffer_Seek_String_Function *buffer_seek_string;
|
||||
Buffer_Seek_String_Insensitive_Function *buffer_seek_string_insensitive;
|
||||
Refresh_Buffer_Function *refresh_buffer;
|
||||
Buffer_Read_Range_Function *buffer_read_range;
|
||||
Buffer_Replace_Range_Function *buffer_replace_range;
|
||||
|
|
|
@ -49,44 +49,6 @@ CUSTOM_COMMAND_SIG(switch_to_compilation){
|
|||
app->view_set_buffer(app, &view, buffer.buffer_id);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_up_10){
|
||||
View_Summary view;
|
||||
float x, y;
|
||||
|
||||
view = app->get_active_view(app);
|
||||
x = view.preferred_x;
|
||||
|
||||
if (view.unwrapped_lines){
|
||||
y = view.cursor.unwrapped_y;
|
||||
}
|
||||
else{
|
||||
y = view.cursor.wrapped_y;
|
||||
}
|
||||
|
||||
y -= 10*view.line_height;
|
||||
|
||||
app->view_set_cursor(app, &view, seek_xy(x, y, 0, view.unwrapped_lines), 0);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_down_10){
|
||||
View_Summary view;
|
||||
float x, y;
|
||||
|
||||
view = app->get_active_view(app);
|
||||
x = view.preferred_x;
|
||||
|
||||
if (view.unwrapped_lines){
|
||||
y = view.cursor.unwrapped_y;
|
||||
}
|
||||
else{
|
||||
y = view.cursor.wrapped_y;
|
||||
}
|
||||
|
||||
y += 10*view.line_height;
|
||||
|
||||
app->view_set_cursor(app, &view, seek_xy(x, y, 0, view.unwrapped_lines), 0);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
|
||||
View_Summary view;
|
||||
Buffer_Summary buffer;
|
||||
|
@ -141,22 +103,24 @@ CUSTOM_COMMAND_SIG(open_my_files){
|
|||
// any circumstance.
|
||||
push_parameter(app, par_name, literal("w:/4ed/data/test/basic.cpp"));
|
||||
exec_command(app, cmdid_interactive_open);
|
||||
|
||||
|
||||
#if 0
|
||||
exec_command(app, cmdid_change_active_panel);
|
||||
|
||||
|
||||
char my_file[256];
|
||||
int my_file_len;
|
||||
|
||||
|
||||
my_file_len = sizeof("w:/4ed/data/test/basic.txt") - 1;
|
||||
for (int i = 0; i < my_file_len; ++i){
|
||||
my_file[i] = ("w:/4ed/data/test/basic.txt")[i];
|
||||
}
|
||||
|
||||
|
||||
// NOTE(allen|a3.1): null terminators are not needed for strings.
|
||||
push_parameter(app, par_name, my_file, my_file_len);
|
||||
exec_command(app, cmdid_interactive_open);
|
||||
|
||||
|
||||
exec_command(app, cmdid_change_active_panel);
|
||||
#endif
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(build_at_launch_location){
|
||||
|
@ -262,7 +226,7 @@ HOOK_SIG(my_file_settings){
|
|||
push_parameter(app, par_wrap_lines, wrap_lines);
|
||||
push_parameter(app, par_key_mapid, (treat_as_code)?((int)my_code_map):((int)mapid_file));
|
||||
exec_command(app, cmdid_set_settings);
|
||||
|
||||
|
||||
// no meaning for return
|
||||
return(0);
|
||||
}
|
||||
|
@ -270,7 +234,7 @@ HOOK_SIG(my_file_settings){
|
|||
void
|
||||
default_keys(Bind_Helper *context){
|
||||
begin_map(context, mapid_global);
|
||||
|
||||
|
||||
bind(context, 'p', MDFR_CTRL, cmdid_open_panel_vsplit);
|
||||
bind(context, '_', MDFR_CTRL, cmdid_open_panel_hsplit);
|
||||
bind(context, 'P', MDFR_CTRL, cmdid_close_panel);
|
||||
|
@ -282,40 +246,40 @@ default_keys(Bind_Helper *context){
|
|||
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
|
||||
bind(context, 'o', MDFR_ALT, open_in_other);
|
||||
bind(context, 'w', MDFR_CTRL, save_as);
|
||||
|
||||
|
||||
bind(context, 'm', MDFR_ALT, build_search);
|
||||
bind(context, 'x', MDFR_ALT, execute_arbitrary_command);
|
||||
bind(context, 'z', MDFR_ALT, execute_any_cli);
|
||||
bind(context, 'Z', MDFR_ALT, execute_previous_cli);
|
||||
|
||||
|
||||
// NOTE(allen): These callbacks may not actually be useful to you, but
|
||||
// go look at them and see what they do.
|
||||
bind(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files);
|
||||
bind(context, 'M', MDFR_ALT, build_at_launch_location);
|
||||
|
||||
|
||||
end_map(context);
|
||||
|
||||
begin_map(context, my_empty_map1);
|
||||
inherit_map(context, mapid_nomap);
|
||||
end_map(context);
|
||||
|
||||
|
||||
begin_map(context, my_empty_map2);
|
||||
inherit_map(context, mapid_nomap);
|
||||
end_map(context);
|
||||
|
||||
|
||||
begin_map(context, my_code_map);
|
||||
|
||||
|
||||
// NOTE(allen|a3.1): Set this map (my_code_map == mapid_user_custom) to
|
||||
// inherit from mapid_file. When searching if a key is bound
|
||||
// in this map, if it is not found here it will then search mapid_file.
|
||||
//
|
||||
// If this is not set, it defaults to mapid_global.
|
||||
inherit_map(context, mapid_file);
|
||||
|
||||
|
||||
// NOTE(allen|a3.1): Children can override parent's bindings.
|
||||
bind(context, key_right, MDFR_CTRL, seek_alphanumeric_or_camel_right);
|
||||
bind(context, key_left, MDFR_CTRL, seek_alphanumeric_or_camel_left);
|
||||
|
||||
|
||||
// NOTE(allen|a3.2): Specific keys can override vanilla keys,
|
||||
// and write character writes whichever character corresponds
|
||||
// to the key that triggered the command.
|
||||
|
@ -325,11 +289,11 @@ default_keys(Bind_Helper *context){
|
|||
bind(context, ']', MDFR_NONE, write_and_auto_tab);
|
||||
bind(context, ';', MDFR_NONE, write_and_auto_tab);
|
||||
bind(context, '#', MDFR_NONE, write_and_auto_tab);
|
||||
|
||||
|
||||
bind(context, '\t', MDFR_NONE, cmdid_word_complete);
|
||||
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab_range);
|
||||
bind(context, '\t', MDFR_SHIFT, auto_tab_line_at_cursor);
|
||||
|
||||
|
||||
bind(context, '=', MDFR_CTRL, write_increment);
|
||||
bind(context, 't', MDFR_ALT, write_allen_todo);
|
||||
bind(context, 'n', MDFR_ALT, write_allen_note);
|
||||
|
@ -339,54 +303,53 @@ default_keys(Bind_Helper *context){
|
|||
bind(context, 'i', MDFR_ALT, if0_off);
|
||||
bind(context, '1', MDFR_ALT, open_file_in_quotes);
|
||||
bind(context, '0', MDFR_CTRL, write_zero_struct);
|
||||
|
||||
|
||||
end_map(context);
|
||||
|
||||
|
||||
|
||||
|
||||
begin_map(context, mapid_file);
|
||||
|
||||
|
||||
// NOTE(allen|a3.4.4): Binding this essentially binds
|
||||
// all key combos that would normally insert a character
|
||||
// into a buffer. If the code for the key is not an enum
|
||||
// value such as key_left or key_back then it is a vanilla key.
|
||||
// It is possible to override this binding for individual keys.
|
||||
bind_vanilla_keys(context, cmdid_write_character);
|
||||
|
||||
bind(context, key_left, MDFR_NONE, cmdid_move_left);
|
||||
bind(context, key_right, MDFR_NONE, cmdid_move_right);
|
||||
bind(context, key_del, MDFR_NONE, cmdid_delete);
|
||||
bind(context, key_back, MDFR_NONE, cmdid_backspace);
|
||||
bind(context, key_up, MDFR_NONE, cmdid_move_up);
|
||||
bind(context, key_down, MDFR_NONE, cmdid_move_down);
|
||||
bind_vanilla_keys(context, write_character);
|
||||
|
||||
bind(context, key_left, MDFR_NONE, move_left);
|
||||
bind(context, key_right, MDFR_NONE, move_right);
|
||||
bind(context, key_del, MDFR_NONE, delete_char);
|
||||
bind(context, key_back, MDFR_NONE, backspace_char);
|
||||
bind(context, key_up, MDFR_NONE, move_up);
|
||||
bind(context, key_down, MDFR_NONE, move_down);
|
||||
bind(context, key_end, MDFR_NONE, cmdid_seek_end_of_line);
|
||||
bind(context, key_home, MDFR_NONE, cmdid_seek_beginning_of_line);
|
||||
bind(context, key_page_up, MDFR_NONE, cmdid_page_up);
|
||||
bind(context, key_page_down, MDFR_NONE, cmdid_page_down);
|
||||
|
||||
|
||||
bind(context, key_right, MDFR_CTRL, seek_whitespace_right);
|
||||
bind(context, key_left, MDFR_CTRL, seek_whitespace_left);
|
||||
bind(context, key_up, MDFR_CTRL, cmdid_seek_whitespace_up);
|
||||
bind(context, key_down, MDFR_CTRL, cmdid_seek_whitespace_down);
|
||||
|
||||
bind(context, key_up, MDFR_CTRL, seek_whitespace_up);
|
||||
bind(context, key_down, MDFR_CTRL, seek_whitespace_down);
|
||||
|
||||
bind(context, key_up, MDFR_ALT, move_up_10);
|
||||
bind(context, key_down, MDFR_ALT, move_down_10);
|
||||
|
||||
|
||||
bind(context, key_back, MDFR_CTRL, backspace_word);
|
||||
bind(context, key_back, MDFR_ALT, snipe_token_or_word);
|
||||
|
||||
bind(context, ' ', MDFR_CTRL, cmdid_set_mark);
|
||||
|
||||
bind(context, ' ', MDFR_CTRL, set_mark);
|
||||
bind(context, 'a', MDFR_CTRL, replace_in_range);
|
||||
bind(context, 'c', MDFR_CTRL, cmdid_copy);
|
||||
bind(context, 'd', MDFR_CTRL, cmdid_delete_range);
|
||||
bind(context, 'd', MDFR_CTRL, delete_range);
|
||||
bind(context, 'e', MDFR_CTRL, cmdid_center_view);
|
||||
bind(context, 'f', MDFR_CTRL, search);
|
||||
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, 'l', MDFR_CTRL, cmdid_toggle_line_wrap);
|
||||
bind(context, 'j', MDFR_CTRL, cmdid_to_lowercase);
|
||||
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
|
||||
bind(context, 'L', MDFR_CTRL, cmdid_toggle_endline_mode);
|
||||
bind(context, 'l', MDFR_CTRL, cmdid_toggle_line_wrap);
|
||||
bind(context, 'm', MDFR_CTRL, cmdid_cursor_mark_swap);
|
||||
bind(context, 'O', MDFR_CTRL, cmdid_reopen);
|
||||
bind(context, 'q', MDFR_CTRL, query_replace);
|
||||
|
@ -409,7 +372,7 @@ default_keys(Bind_Helper *context){
|
|||
bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines);
|
||||
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
|
||||
bind(context, '\n', MDFR_SHIFT, write_and_auto_tab);
|
||||
bind(context, ' ', MDFR_SHIFT, cmdid_write_character);
|
||||
bind(context, ' ', MDFR_SHIFT, write_character);
|
||||
|
||||
end_map(context);
|
||||
}
|
||||
|
@ -425,7 +388,7 @@ get_bindings(void *data, int size){
|
|||
// and once set they always apply, regardless of what map is active.
|
||||
set_hook(context, hook_start, my_start);
|
||||
set_hook(context, hook_open_file, my_file_settings);
|
||||
|
||||
|
||||
set_scroll_rule(context, smooth_scroll_rule);
|
||||
|
||||
default_keys(context);
|
||||
|
@ -434,94 +397,6 @@ get_bindings(void *data, int size){
|
|||
return(result);
|
||||
}
|
||||
|
||||
struct Custom_Vars{
|
||||
int initialized;
|
||||
Partition part;
|
||||
};
|
||||
|
||||
enum View_Mode{
|
||||
ViewMode_File,
|
||||
};
|
||||
|
||||
struct View_Vars{
|
||||
int id;
|
||||
View_Mode mode;
|
||||
|
||||
GUI_Scroll_Vars scroll;
|
||||
i32_Rect scroll_region;
|
||||
|
||||
int buffer_id;
|
||||
};
|
||||
inline View_Vars
|
||||
view_vars_zero(){
|
||||
View_Vars vars = {0};
|
||||
return(vars);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
view_routine(Application_Links *app, int view_id){
|
||||
Custom_Vars *vars = (Custom_Vars*)app->memory;
|
||||
View_Vars view = {0};
|
||||
view.id = view_id;
|
||||
|
||||
int 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -4,19 +4,293 @@
|
|||
#define FCPP_STRING_IMPLEMENTATION
|
||||
#include "4coder_string.h"
|
||||
|
||||
#define UseInterfacesThatArePhasingOut 0
|
||||
#include "4coder_helper.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static void
|
||||
write_string(Application_Links *app, String string){
|
||||
Buffer_Summary buffer = app->get_active_buffer(app);
|
||||
app->buffer_replace_range(app, &buffer, buffer.buffer_cursor_pos, buffer.buffer_cursor_pos, string.str, string.size);
|
||||
inline float
|
||||
get_view_y(View_Summary view){
|
||||
float y;
|
||||
if (view.unwrapped_lines){
|
||||
y = view.cursor.unwrapped_y;
|
||||
}
|
||||
else{
|
||||
y = view.cursor.wrapped_y;
|
||||
}
|
||||
return(y);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_increment){
|
||||
write_string(app, make_lit_string("++"));
|
||||
inline float
|
||||
get_view_x(View_Summary view){
|
||||
float x;
|
||||
if (view.unwrapped_lines){
|
||||
x = view.cursor.unwrapped_x;
|
||||
}
|
||||
else{
|
||||
x = view.cursor.wrapped_x;
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
|
||||
//
|
||||
// Fundamental Editing
|
||||
//
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_character){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
|
||||
User_Input in = app->get_command_input(app);
|
||||
char character = 0;
|
||||
|
||||
if (in.type == UserInputKey){
|
||||
character = in.key.character;
|
||||
}
|
||||
|
||||
if (character != 0){
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||
int pos = view.cursor.pos;
|
||||
int next_pos = pos + 1;
|
||||
app->buffer_replace_range(app, &buffer,
|
||||
pos, pos, &character, 1);
|
||||
app->view_set_cursor(app, &view, seek_pos(next_pos), true);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(delete_char){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||
|
||||
int pos = view.cursor.pos;
|
||||
if (0 < buffer.size && pos < buffer.size){
|
||||
app->buffer_replace_range(app, &buffer,
|
||||
pos, pos+1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(backspace_char){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||
|
||||
int pos = view.cursor.pos;
|
||||
if (0 < pos && pos <= buffer.size){
|
||||
app->buffer_replace_range(app, &buffer,
|
||||
pos-1, pos, 0, 0);
|
||||
|
||||
app->view_set_cursor(app, &view, seek_pos(pos-1), true);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(set_mark){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
|
||||
app->view_set_mark(app, &view, seek_pos(view.cursor.pos));
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(delete_range){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||
|
||||
Range range = get_range(&view);
|
||||
|
||||
app->buffer_replace_range(app, &buffer,
|
||||
range.min, range.max,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Basic Navigation
|
||||
//
|
||||
|
||||
inline void
|
||||
move_vertical(Application_Links *app, float line_multiplier){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
|
||||
float new_y = get_view_y(view) + line_multiplier*view.line_height;
|
||||
float x = view.preferred_x;
|
||||
|
||||
app->view_set_cursor(app, &view,
|
||||
seek_xy(x, new_y, false, view.unwrapped_lines),
|
||||
false);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_left){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
int new_pos = view.cursor.pos - 1;
|
||||
app->view_set_cursor(app, &view,
|
||||
seek_pos(new_pos),
|
||||
true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(move_right){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
int new_pos = view.cursor.pos + 1;
|
||||
app->view_set_cursor(app, &view,
|
||||
seek_pos(new_pos),
|
||||
true);
|
||||
}
|
||||
|
||||
//
|
||||
// Various Forms of Seek
|
||||
//
|
||||
|
||||
static int
|
||||
buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int pos){
|
||||
char chunk[1024];
|
||||
int chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
int no_hard;
|
||||
int still_looping;
|
||||
char at_pos;
|
||||
|
||||
--pos;
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
// Step 1: Find the first non-whitespace character
|
||||
// behind the current position.
|
||||
still_looping = true;
|
||||
do{
|
||||
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);
|
||||
} while(still_looping);
|
||||
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'
|
||||
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 int
|
||||
buffer_seek_whitespace_down(Application_Links *app, Buffer_Summary *buffer, int pos){
|
||||
char chunk[1024];
|
||||
int chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
int no_hard;
|
||||
int prev_endline;
|
||||
int 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);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_whitespace_up){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id);
|
||||
|
||||
int new_pos = buffer_seek_whitespace_up(app, &buffer, view.cursor.pos);
|
||||
app->view_set_cursor(app, &view,
|
||||
seek_pos(new_pos),
|
||||
true);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(seek_whitespace_down){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id);
|
||||
|
||||
int new_pos = buffer_seek_whitespace_down(app, &buffer, view.cursor.pos);
|
||||
app->view_set_cursor(app, &view,
|
||||
seek_pos(new_pos),
|
||||
true);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -39,6 +313,23 @@ SEEK_COMMAND(alphanumeric, left, BoundryAlphanumeric)
|
|||
SEEK_COMMAND(alphanumeric_or_camel, right, BoundryAlphanumeric | BoundryCamelCase)
|
||||
SEEK_COMMAND(alphanumeric_or_camel, left, BoundryAlphanumeric | BoundryCamelCase)
|
||||
|
||||
|
||||
//
|
||||
// Special string writing commands
|
||||
//
|
||||
|
||||
static void
|
||||
write_string(Application_Links *app, String string){
|
||||
Buffer_Summary buffer = get_active_buffer(app);
|
||||
app->buffer_replace_range(app, &buffer,
|
||||
buffer.buffer_cursor_pos, buffer.buffer_cursor_pos,
|
||||
string.str, string.size);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_increment){
|
||||
write_string(app, make_lit_string("++"));
|
||||
}
|
||||
|
||||
static void
|
||||
long_braces(Application_Links *app, char *text, int size){
|
||||
View_Summary view;
|
||||
|
@ -92,7 +383,7 @@ CUSTOM_COMMAND_SIG(if0_off){
|
|||
int pos;
|
||||
|
||||
view = app->get_active_view(app);
|
||||
buffer = app->get_active_buffer(app);
|
||||
buffer = app->get_buffer(app, view.buffer_id);
|
||||
|
||||
range = get_range(&view);
|
||||
pos = range.min;
|
||||
|
@ -161,8 +452,8 @@ CUSTOM_COMMAND_SIG(open_file_in_quotes){
|
|||
view = app->get_active_view(app);
|
||||
buffer = app->get_buffer(app, view.buffer_id);
|
||||
pos = view.cursor.pos;
|
||||
app->buffer_seek_delimiter(app, &buffer, pos, '"', 1, &end);
|
||||
app->buffer_seek_delimiter(app, &buffer, pos, '"', 0, &start);
|
||||
buffer_seek_delimiter_forward(app, &buffer, pos, '"', &end);
|
||||
buffer_seek_delimiter_backward(app, &buffer, pos, '"', &start);
|
||||
|
||||
++start;
|
||||
size = end - start;
|
||||
|
@ -213,39 +504,39 @@ isearch(Application_Links *app, int start_reversed){
|
|||
Buffer_Summary buffer;
|
||||
User_Input in;
|
||||
Query_Bar bar;
|
||||
|
||||
|
||||
view = app->get_active_view(app);
|
||||
buffer = app->get_buffer(app, view.locked_buffer_id);
|
||||
|
||||
if (!buffer.exists) return;
|
||||
|
||||
if (app->start_query_bar(app, &bar, 0) == 0) return;
|
||||
|
||||
|
||||
Range match;
|
||||
int reverse = start_reversed;
|
||||
int pos;
|
||||
|
||||
pos = view.cursor.pos;
|
||||
match = make_range(pos, pos);
|
||||
|
||||
|
||||
char bar_string_space[256];
|
||||
bar.string = make_fixed_width_string(bar_string_space);
|
||||
|
||||
|
||||
String isearch = make_lit_string("I-Search: ");
|
||||
String rsearch = make_lit_string("Reverse-I-Search: ");
|
||||
|
||||
|
||||
while (1){
|
||||
// NOTE(allen): Change the bar's prompt to match the current direction.
|
||||
if (reverse) bar.prompt = rsearch;
|
||||
else bar.prompt = isearch;
|
||||
|
||||
|
||||
in = app->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);
|
||||
|
||||
|
||||
int made_change = 0;
|
||||
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
|
||||
break;
|
||||
|
@ -260,15 +551,15 @@ isearch(Application_Links *app, int start_reversed){
|
|||
made_change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int step_forward = 0;
|
||||
int step_backward = 0;
|
||||
|
||||
|
||||
if (CommandEqual(in.command, search) ||
|
||||
in.key.keycode == key_page_down || in.key.keycode == key_down) step_forward = 1;
|
||||
in.key.keycode == key_page_down || in.key.keycode == key_down) step_forward = 1;
|
||||
if (CommandEqual(in.command, reverse_search) ||
|
||||
in.key.keycode == key_page_up || in.key.keycode == key_up) step_backward = 1;
|
||||
|
||||
in.key.keycode == key_page_up || in.key.keycode == key_up) step_backward = 1;
|
||||
|
||||
int start_pos = pos;
|
||||
if (step_forward && reverse){
|
||||
start_pos = match.start + 1;
|
||||
|
@ -282,17 +573,18 @@ isearch(Application_Links *app, int start_reversed){
|
|||
reverse = 1;
|
||||
step_backward = 0;
|
||||
}
|
||||
|
||||
|
||||
if (in.key.keycode != key_back){
|
||||
int new_pos;
|
||||
if (reverse){
|
||||
// TODO(allen): Need a good way to allow users to implement seeks for themselves.
|
||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos - 1, bar.string.str, bar.string.size, 0, &new_pos);
|
||||
buffer_seek_string_insensitive_backward(app, &buffer, start_pos - 1,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos >= 0){
|
||||
if (step_backward){
|
||||
pos = new_pos;
|
||||
start_pos = new_pos;
|
||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos - 1, bar.string.str, bar.string.size, 0, &new_pos);
|
||||
buffer_seek_string_insensitive_backward(app, &buffer, start_pos - 1,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos < 0) new_pos = start_pos;
|
||||
}
|
||||
match.start = new_pos;
|
||||
|
@ -300,12 +592,14 @@ isearch(Application_Links *app, int start_reversed){
|
|||
}
|
||||
}
|
||||
else{
|
||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos + 1, bar.string.str, bar.string.size, 1, &new_pos);
|
||||
buffer_seek_string_insensitive_forward(app, &buffer, start_pos + 1,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos < buffer.size){
|
||||
if (step_forward){
|
||||
pos = new_pos;
|
||||
start_pos = new_pos;
|
||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos + 1, bar.string.str, bar.string.size, 1, &new_pos);
|
||||
buffer_seek_string_insensitive_forward(app, &buffer, start_pos + 1,
|
||||
bar.string.str, bar.string.size, &new_pos);
|
||||
if (new_pos >= buffer.size) new_pos = start_pos;
|
||||
}
|
||||
match.start = new_pos;
|
||||
|
@ -318,12 +612,12 @@ isearch(Application_Links *app, int start_reversed){
|
|||
match.end = match.start + bar.string.size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
app->view_set_highlight(app, &view, match.start, match.end, 1);
|
||||
}
|
||||
app->view_set_highlight(app, &view, 0, 0, 0);
|
||||
if (in.abort) return;
|
||||
|
||||
|
||||
app->view_set_cursor(app, &view, seek_pos(match.min), 1);
|
||||
}
|
||||
|
||||
|
@ -365,14 +659,14 @@ CUSTOM_COMMAND_SIG(replace_in_range){
|
|||
|
||||
int pos, new_pos;
|
||||
pos = range.min;
|
||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
||||
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||
|
||||
while (new_pos + r.size <= range.end){
|
||||
app->buffer_replace_range(app, &buffer, new_pos, new_pos + r.size, w.str, w.size);
|
||||
app->refresh_view(app, &view);
|
||||
range = get_range(&view);
|
||||
pos = new_pos + w.size;
|
||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
||||
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,7 +704,7 @@ CUSTOM_COMMAND_SIG(query_replace){
|
|||
buffer = app->get_buffer(app, view.buffer_id);
|
||||
|
||||
pos = view.cursor.pos;
|
||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
||||
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||
|
||||
User_Input in = {0};
|
||||
while (new_pos < buffer.size){
|
||||
|
@ -428,7 +722,7 @@ CUSTOM_COMMAND_SIG(query_replace){
|
|||
pos = match.max;
|
||||
}
|
||||
|
||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
||||
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||
}
|
||||
|
||||
app->view_set_highlight(app, &view, 0, 0, 0);
|
||||
|
@ -663,14 +957,14 @@ CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){
|
|||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(auto_tab_whole_file){
|
||||
Buffer_Summary buffer = app->get_active_buffer(app);
|
||||
Buffer_Summary buffer = get_active_buffer(app);
|
||||
push_parameter(app, par_range_start, 0);
|
||||
push_parameter(app, par_range_end, buffer.size);
|
||||
exec_command(app, cmdid_auto_tab_range);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_and_auto_tab){
|
||||
exec_command(app, cmdid_write_character);
|
||||
exec_command(app, write_character);
|
||||
exec_command(app, auto_tab_line_at_cursor);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ struct GUI_Scroll_Vars{
|
|||
float scroll_y;
|
||||
float target_y;
|
||||
float prev_target_y;
|
||||
float min_y, max_y;
|
||||
float max_y;
|
||||
|
||||
float scroll_x;
|
||||
float target_x;
|
||||
|
|
358
4coder_helper.h
358
4coder_helper.h
|
@ -386,3 +386,361 @@ query_user_number(Application_Links *app, Query_Bar *bar){
|
|||
}
|
||||
|
||||
inline String empty_string() {String Result = {}; return(Result);}
|
||||
|
||||
inline Buffer_Summary
|
||||
get_active_buffer(Application_Links *app){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
|
||||
struct Stream_Chunk{
|
||||
Application_Links *app;
|
||||
Buffer_Summary *buffer;
|
||||
|
||||
char *base_data;
|
||||
int start, end;
|
||||
int data_size;
|
||||
|
||||
char *data;
|
||||
};
|
||||
|
||||
int
|
||||
round_down(int x, int b){
|
||||
int r = 0;
|
||||
if (x >= 0){
|
||||
r = x - (x % b);
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
int
|
||||
round_up(int x, int b){
|
||||
int r = 0;
|
||||
if (x >= 0){
|
||||
r = x - (x % b) + b;
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
int
|
||||
init_stream_chunk(Stream_Chunk *chunk,
|
||||
Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char *data, int size){
|
||||
int result = 0;
|
||||
|
||||
app->refresh_buffer(app, buffer);
|
||||
if (pos >= 0 && pos < buffer->size && size > 0){
|
||||
result = 1;
|
||||
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->end > buffer->size){
|
||||
chunk->end = buffer->size;
|
||||
}
|
||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
int
|
||||
forward_stream_chunk(Stream_Chunk *chunk){
|
||||
Application_Links *app = chunk->app;
|
||||
Buffer_Summary *buffer = chunk->buffer;
|
||||
int result = 0;
|
||||
|
||||
app->refresh_buffer(app, buffer);
|
||||
if (chunk->end < buffer->size){
|
||||
result = 1;
|
||||
chunk->start = chunk->end;
|
||||
chunk->end += chunk->data_size;
|
||||
if (chunk->end > buffer->size){
|
||||
chunk->end = buffer->size;
|
||||
}
|
||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
int
|
||||
backward_stream_chunk(Stream_Chunk *chunk){
|
||||
Application_Links *app = chunk->app;
|
||||
Buffer_Summary *buffer = chunk->buffer;
|
||||
int result = 0;
|
||||
|
||||
app->refresh_buffer(app, buffer);
|
||||
if (chunk->start > 0){
|
||||
result = 1;
|
||||
chunk->end = chunk->start;
|
||||
chunk->start -= chunk->data_size;
|
||||
if (chunk->start < 0){
|
||||
chunk->start = 0;
|
||||
}
|
||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
buffer_seek_delimiter_forward(Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char delim, int *result){
|
||||
if (buffer->exists){
|
||||
char chunk[1024];
|
||||
int size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
|
||||
int 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:;
|
||||
}
|
||||
|
||||
void
|
||||
buffer_seek_delimiter_backward(Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char delim, int *result){
|
||||
if (buffer->exists){
|
||||
char chunk[1024];
|
||||
int size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
|
||||
int 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:;
|
||||
}
|
||||
|
||||
// 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.
|
||||
void
|
||||
buffer_seek_string_forward(Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char *str, int size, int *result){
|
||||
char read_buffer[512];
|
||||
char chunk[1024];
|
||||
int chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (size <= 0){
|
||||
*result = pos;
|
||||
}
|
||||
else if (size > sizeof(read_buffer)){
|
||||
*result = pos;
|
||||
}
|
||||
else{
|
||||
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;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
int still_looping = 1;
|
||||
do{
|
||||
for(; pos < stream.end; ++pos){
|
||||
char at_pos = stream.data[pos];
|
||||
if (at_pos == first_char){
|
||||
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
*result = buffer->size;
|
||||
|
||||
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.
|
||||
void
|
||||
buffer_seek_string_backward(Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char *str, int size, int *result){
|
||||
char read_buffer[512];
|
||||
char chunk[1024];
|
||||
int chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (size <= 0){
|
||||
*result = 0;
|
||||
}
|
||||
else if (size > sizeof(read_buffer)){
|
||||
*result = 0;
|
||||
}
|
||||
else{
|
||||
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;
|
||||
|
||||
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||
int still_looping = 1;
|
||||
do{
|
||||
for(; pos >= stream.start; --pos){
|
||||
char at_pos = stream.data[pos];
|
||||
if (at_pos == first_char){
|
||||
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
*result = 0;
|
||||
|
||||
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.
|
||||
void
|
||||
buffer_seek_string_insensitive_forward(Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char *str, int size, int *result){
|
||||
char read_buffer[512];
|
||||
char chunk[1024];
|
||||
int chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (size <= 0){
|
||||
*result = pos;
|
||||
}
|
||||
else if (size > sizeof(read_buffer)){
|
||||
*result = pos;
|
||||
}
|
||||
else{
|
||||
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)){
|
||||
int still_looping = 1;
|
||||
do{
|
||||
for(; pos < stream.end; ++pos){
|
||||
char at_pos = char_to_upper(stream.data[pos]);
|
||||
if (at_pos == first_char){
|
||||
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match_insensitive(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = forward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
*result = buffer->size;
|
||||
|
||||
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.
|
||||
void
|
||||
buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char *str, int size, int *result){
|
||||
char read_buffer[512];
|
||||
char chunk[1024];
|
||||
int chunk_size = sizeof(chunk);
|
||||
Stream_Chunk stream = {0};
|
||||
|
||||
if (size <= 0){
|
||||
*result = -1;
|
||||
}
|
||||
else if (size > sizeof(read_buffer)){
|
||||
*result = -1;
|
||||
}
|
||||
else{
|
||||
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)){
|
||||
int still_looping = 1;
|
||||
do{
|
||||
for(; pos >= stream.start; --pos){
|
||||
char at_pos = char_to_upper(stream.data[pos]);
|
||||
if (at_pos == first_char){
|
||||
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||
if (match_insensitive(needle_str, read_str)){
|
||||
*result = pos;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = backward_stream_chunk(&stream);
|
||||
}while (still_looping);
|
||||
}
|
||||
}
|
||||
|
||||
*result = -1;
|
||||
|
||||
finished:;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -102,17 +102,17 @@ FSTRING_INLINE bool match_part(String a, char *b) { int x; return match_part
|
|||
FSTRING_LINK bool match_part(char *a, String b);
|
||||
FSTRING_LINK bool match_part(String a, String b);
|
||||
|
||||
FSTRING_LINK bool match_unsensitive(char *a, char *b);
|
||||
FSTRING_LINK bool match_unsensitive(String a, char *b);
|
||||
FSTRING_INLINE bool match_unsensitive(char *a, String b) { return match_unsensitive(b,a); }
|
||||
FSTRING_LINK bool match_unsensitive(String a, String b);
|
||||
FSTRING_LINK bool match_insensitive(char *a, char *b);
|
||||
FSTRING_LINK bool match_insensitive(String a, char *b);
|
||||
FSTRING_INLINE bool match_insensitive(char *a, String b) { return match_insensitive(b,a); }
|
||||
FSTRING_LINK bool match_insensitive(String a, String b);
|
||||
|
||||
FSTRING_LINK bool match_part_unsensitive(char *a, char *b, int *len);
|
||||
FSTRING_LINK bool match_part_unsensitive(String a, char *b, int *len);
|
||||
FSTRING_INLINE bool match_part_unsensitive(char *a, char *b) { int x; return match_part(a,b,&x); }
|
||||
FSTRING_INLINE bool match_part_unsensitive(String a, char *b) { int x; return match_part(a,b,&x); }
|
||||
FSTRING_LINK bool match_part_unsensitive(char *a, String b);
|
||||
FSTRING_LINK bool match_part_unsensitive(String a, String b);
|
||||
FSTRING_LINK bool match_part_insensitive(char *a, char *b, int *len);
|
||||
FSTRING_LINK bool match_part_insensitive(String a, char *b, int *len);
|
||||
FSTRING_INLINE bool match_part_insensitive(char *a, char *b) { int x; return match_part(a,b,&x); }
|
||||
FSTRING_INLINE bool match_part_insensitive(String a, char *b) { int x; return match_part(a,b,&x); }
|
||||
FSTRING_LINK bool match_part_insensitive(char *a, String b);
|
||||
FSTRING_LINK bool match_part_insensitive(String a, String b);
|
||||
|
||||
FSTRING_LINK int find(char *s, int start, char c);
|
||||
FSTRING_LINK int find(String s, int start, char c);
|
||||
|
@ -123,14 +123,14 @@ FSTRING_LINK int find_substr(char *s, int start, String seek);
|
|||
FSTRING_LINK int find_substr(String s, int start, String seek);
|
||||
FSTRING_LINK int rfind_substr(String s, int start, String seek);
|
||||
|
||||
FSTRING_LINK int find_substr_unsensitive(char *s, int start, String seek);
|
||||
FSTRING_LINK int find_substr_unsensitive(String s, int start, String seek);
|
||||
FSTRING_LINK int find_substr_insensitive(char *s, int start, String seek);
|
||||
FSTRING_LINK int find_substr_insensitive(String s, int start, String seek);
|
||||
|
||||
FSTRING_INLINE bool has_substr(char *s, String seek) { return (s[find_substr(s, 0, seek)] != 0); }
|
||||
FSTRING_INLINE bool has_substr(String s, String seek) { return (find_substr(s, 0, seek) < s.size); }
|
||||
|
||||
FSTRING_INLINE bool has_substr_unsensitive(char *s, String seek) { return (s[find_substr_unsensitive(s, 0, seek)] != 0); }
|
||||
FSTRING_INLINE bool has_substr_unsensitive(String s, String seek) { return (find_substr_unsensitive(s, 0, seek) < s.size); }
|
||||
FSTRING_INLINE bool has_substr_insensitive(char *s, String seek) { return (s[find_substr_insensitive(s, 0, seek)] != 0); }
|
||||
FSTRING_INLINE bool has_substr_insensitive(String s, String seek) { return (find_substr_insensitive(s, 0, seek) < s.size); }
|
||||
|
||||
FSTRING_LINK int int_to_str_size(int x);
|
||||
FSTRING_LINK int int_to_str(int x, char *s_out);
|
||||
|
@ -391,7 +391,7 @@ match_part(String a, String b){
|
|||
}
|
||||
|
||||
FSTRING_LINK bool
|
||||
match_unsensitive(char *a, char *b){
|
||||
match_insensitive(char *a, char *b){
|
||||
for (int i = 0;; ++i){
|
||||
if (char_to_upper(a[i]) !=
|
||||
char_to_upper(b[i])){
|
||||
|
@ -404,7 +404,7 @@ match_unsensitive(char *a, char *b){
|
|||
}
|
||||
|
||||
FSTRING_LINK bool
|
||||
match_unsensitive(String a, char *b){
|
||||
match_insensitive(String a, char *b){
|
||||
int i = 0;
|
||||
for (; i < a.size; ++i){
|
||||
if (char_to_upper(a.str[i]) !=
|
||||
|
@ -419,7 +419,7 @@ match_unsensitive(String a, char *b){
|
|||
}
|
||||
|
||||
FSTRING_LINK bool
|
||||
match_unsensitive(String a, String b){
|
||||
match_insensitive(String a, String b){
|
||||
if (a.size != b.size){
|
||||
return 0;
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ match_unsensitive(String a, String b){
|
|||
}
|
||||
|
||||
FSTRING_LINK bool
|
||||
match_part_unsensitive(char *a, char *b, int *len){
|
||||
match_part_insensitive(char *a, char *b, int *len){
|
||||
int i;
|
||||
for (i = 0; b[i] != 0; ++i){
|
||||
if (char_to_upper(a[i]) != char_to_upper(b[i])){
|
||||
|
@ -445,7 +445,7 @@ match_part_unsensitive(char *a, char *b, int *len){
|
|||
}
|
||||
|
||||
FSTRING_LINK bool
|
||||
match_part_unsensitive(String a, char *b, int *len){
|
||||
match_part_insensitive(String a, char *b, int *len){
|
||||
int i;
|
||||
for (i = 0; b[i] != 0; ++i){
|
||||
if (char_to_upper(a.str[i]) != char_to_upper(b[i]) ||
|
||||
|
@ -458,7 +458,7 @@ match_part_unsensitive(String a, char *b, int *len){
|
|||
}
|
||||
|
||||
FSTRING_LINK bool
|
||||
match_part_unsensitive(char *a, String b){
|
||||
match_part_insensitive(char *a, String b){
|
||||
for (int i = 0; i != b.size; ++i){
|
||||
if (char_to_upper(a[i]) != char_to_upper(b.str[i])){
|
||||
return 0;
|
||||
|
@ -468,7 +468,7 @@ match_part_unsensitive(char *a, String b){
|
|||
}
|
||||
|
||||
FSTRING_LINK bool
|
||||
match_part_unsensitive(String a, String b){
|
||||
match_part_insensitive(String a, String b){
|
||||
if (a.size < b.size){
|
||||
return 0;
|
||||
}
|
||||
|
@ -602,7 +602,7 @@ rfind_substr(String str, int start, String seek){
|
|||
}
|
||||
|
||||
FSTRING_LINK int
|
||||
find_substr_unsensitive(char *str, int start, String seek){
|
||||
find_substr_insensitive(char *str, int start, String seek){
|
||||
int i, j, k;
|
||||
bool hit;
|
||||
char a_upper, b_upper;
|
||||
|
@ -630,7 +630,7 @@ find_substr_unsensitive(char *str, int start, String seek){
|
|||
}
|
||||
|
||||
FSTRING_LINK int
|
||||
find_substr_unsensitive(String str, int start, String seek){
|
||||
find_substr_insensitive(String str, int start, String seek){
|
||||
int i, j, k;
|
||||
int stop_at;
|
||||
bool hit;
|
||||
|
@ -1217,8 +1217,8 @@ wildcard_match(Absolutes *absolutes, char *x, int case_sensitive){
|
|||
match_part_func = match_part;
|
||||
}
|
||||
else{
|
||||
match_func = match_unsensitive;
|
||||
match_part_func = match_part_unsensitive;
|
||||
match_func = match_insensitive;
|
||||
match_part_func = match_part_insensitive;
|
||||
}
|
||||
|
||||
if (absolutes->count == 1){
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#define MAJOR 4
|
||||
#define MINOR 0
|
||||
#define PATCH 6
|
||||
#define PATCH 7
|
||||
|
||||
#define VN__(a,b,c) #a"."#b"."#c
|
||||
#define VN_(a,b,c) VN__(a,b,c)
|
||||
|
|
18
4cpp_lexer.h
18
4cpp_lexer.h
|
@ -65,6 +65,19 @@ NOTES ON USE:
|
|||
|
||||
#include "4cpp_lexer_types.h"
|
||||
|
||||
struct Cpp_Lex_Data{
|
||||
Cpp_Preprocessor_State pp_state;
|
||||
int pos;
|
||||
int complete;
|
||||
};
|
||||
|
||||
struct Cpp_Read_Result{
|
||||
Cpp_Token token;
|
||||
int pos;
|
||||
char newline;
|
||||
char has_result;
|
||||
};
|
||||
|
||||
Cpp_File
|
||||
data_as_cpp_file(Data data){
|
||||
Cpp_File result;
|
||||
|
@ -140,7 +153,6 @@ FCPP_LINK bool cpp_push_token_no_merge(Cpp_Token_Stack *stack, Cpp_Token token);
|
|||
FCPP_LINK bool cpp_push_token_nonalloc(Cpp_Token_Stack *stack, Cpp_Token token);
|
||||
|
||||
inline Cpp_Lex_Data cpp_lex_data_zero() { Cpp_Lex_Data data = {(Cpp_Preprocessor_State)0}; return(data); }
|
||||
inline Cpp_Token_Stack cpp_token_stack_zero() { Cpp_Token_Stack stack={0}; return(stack); }
|
||||
|
||||
FCPP_LINK Cpp_Read_Result cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex);
|
||||
|
||||
|
@ -1266,10 +1278,10 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result.token.state_flags = state_flags;
|
||||
result.has_result = has_result;
|
||||
|
||||
|
||||
*lex_data = lex;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -209,23 +209,15 @@ enum Cpp_Preprocessor_State{
|
|||
CPP_LEX_PP_COUNT
|
||||
};
|
||||
|
||||
struct Cpp_Lex_Data{
|
||||
Cpp_Preprocessor_State pp_state;
|
||||
int pos;
|
||||
int complete;
|
||||
};
|
||||
|
||||
struct Cpp_Read_Result{
|
||||
Cpp_Token token;
|
||||
int pos;
|
||||
char newline;
|
||||
char has_result;
|
||||
};
|
||||
|
||||
struct Cpp_Token_Stack{
|
||||
Cpp_Token *tokens;
|
||||
int count, max_count;
|
||||
};
|
||||
inline Cpp_Token_Stack
|
||||
cpp_token_stack_zero(){
|
||||
Cpp_Token_Stack stack={0};
|
||||
return(stack);
|
||||
}
|
||||
|
||||
struct Cpp_Token_Merge{
|
||||
Cpp_Token new_token;
|
||||
|
|
28
4ed.h
28
4ed.h
|
@ -81,17 +81,18 @@ struct Plat_Settings{
|
|||
|
||||
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
|
||||
|
||||
|
||||
#define App_Init_Sig(name) void \
|
||||
name(System_Functions *system, \
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
Exchange *exchange, \
|
||||
String clipboard, \
|
||||
String current_directory, \
|
||||
Custom_API api)
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
String clipboard, \
|
||||
String current_directory, \
|
||||
Custom_API api)
|
||||
|
||||
typedef App_Init_Sig(App_Init);
|
||||
|
||||
|
||||
enum Application_Mouse_Cursor{
|
||||
APP_MOUSE_CURSOR_DEFAULT,
|
||||
APP_MOUSE_CURSOR_ARROW,
|
||||
|
@ -110,19 +111,24 @@ struct Application_Step_Result{
|
|||
b32 animating;
|
||||
};
|
||||
|
||||
struct Application_Step_Input{
|
||||
b32 first_step;
|
||||
f32 dt;
|
||||
Key_Input_Data keys;
|
||||
Mouse_State mouse;
|
||||
String clipboard;
|
||||
};
|
||||
|
||||
#define App_Step_Sig(name) void \
|
||||
name(System_Functions *system, \
|
||||
Key_Input_Data *input, \
|
||||
Mouse_State *mouse, \
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
Exchange *exchange, \
|
||||
String clipboard, \
|
||||
f32 dt, b32 first_step, \
|
||||
Application_Step_Input *input, \
|
||||
Application_Step_Result *result)
|
||||
|
||||
typedef App_Step_Sig(App_Step);
|
||||
|
||||
|
||||
struct App_Functions{
|
||||
App_Read_Command_Line *read_command_line;
|
||||
App_Init *init;
|
||||
|
|
|
@ -58,16 +58,12 @@ struct Models{
|
|||
char hot_dir_base_[256];
|
||||
Hot_Directory hot_directory;
|
||||
|
||||
Delay delay1, delay2;
|
||||
|
||||
Panel *prev_mouse_panel;
|
||||
|
||||
Custom_API config_api;
|
||||
Scroll_Rule_Function *scroll_rule;
|
||||
|
||||
#if 0
|
||||
File_Exchange files;
|
||||
#endif
|
||||
b32 keep_playing;
|
||||
};
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -39,12 +39,10 @@
|
|||
|
||||
#include "4ed_style.h"
|
||||
#include "4ed_style.cpp"
|
||||
#include "4ed_exchange.cpp"
|
||||
#include "4ed_command.cpp"
|
||||
#include "4ed_file.cpp"
|
||||
#include "4ed_gui.cpp"
|
||||
#include "4ed_layout.cpp"
|
||||
#include "4ed_delay.cpp"
|
||||
#include "4ed_app_models.h"
|
||||
#include "4ed_file_view.cpp"
|
||||
#include "4ed.cpp"
|
||||
|
|
140
4ed_delay.cpp
140
4ed_delay.cpp
|
@ -1,140 +0,0 @@
|
|||
enum Action_Type{
|
||||
DACT_OPEN,
|
||||
DACT_OPEN_BACKGROUND,
|
||||
DACT_SET_LINE,
|
||||
DACT_SAVE_AS,
|
||||
DACT_SAVE,
|
||||
DACT_NEW,
|
||||
DACT_SWITCH,
|
||||
DACT_TRY_KILL,
|
||||
DACT_KILL,
|
||||
DACT_TOUCH_FILE,
|
||||
DACT_CLOSE,
|
||||
};
|
||||
|
||||
struct Delayed_Action{
|
||||
Action_Type type;
|
||||
String string;
|
||||
Panel* panel;
|
||||
Editing_File* file;
|
||||
i32 integer;
|
||||
};
|
||||
|
||||
struct Delay{
|
||||
General_Memory* general;
|
||||
Delayed_Action* acts;
|
||||
i32 count;
|
||||
i32 max;
|
||||
};
|
||||
|
||||
internal String
|
||||
str_alloc_copy(General_Memory *general, String str){
|
||||
String result;
|
||||
result.memory_size = str.memory_size + 1;
|
||||
result.size = str.size;
|
||||
result.str = (char*)general_memory_allocate(general, result.memory_size, 0);
|
||||
memcpy(result.str, str.str, str.size);
|
||||
result.str[result.size] = 0;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action
|
||||
delayed_action_zero(){
|
||||
Delayed_Action result = {(Action_Type)0};
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type){
|
||||
Delayed_Action *result;
|
||||
if (delay->count == delay->max){
|
||||
delay->max *= 2;
|
||||
delay->acts = (Delayed_Action*)general_memory_reallocate(delay->general, delay->acts, delay->count*sizeof(Delayed_Action), delay->max*sizeof(Delayed_Action), 0);
|
||||
}
|
||||
result = delay->acts + delay->count++;
|
||||
*result = delayed_action_zero();
|
||||
result->type = type;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type, String string){
|
||||
Delayed_Action *result;
|
||||
result = delayed_action_(delay, type);
|
||||
result->string = str_alloc_copy(delay->general, string);
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type, Panel* panel){
|
||||
Delayed_Action *result;
|
||||
result = delayed_action_(delay, type);
|
||||
result->panel = panel;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type, Editing_File* file){
|
||||
Delayed_Action *result;
|
||||
result = delayed_action_(delay, type);
|
||||
result->file = file;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type, Editing_File* file, Panel* panel){
|
||||
Delayed_Action *result;
|
||||
result = delayed_action_(delay, type);
|
||||
result->file = file;
|
||||
result->panel = panel;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type, String string, Panel* panel){
|
||||
Delayed_Action *result;
|
||||
result = delayed_action_(delay, type);
|
||||
result->string = str_alloc_copy(delay->general, string);
|
||||
result->panel = panel;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type, String string, Editing_File* file){
|
||||
Delayed_Action *result;
|
||||
result = delayed_action_(delay, type);
|
||||
result->string = str_alloc_copy(delay->general, string);
|
||||
result->file = file;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_(Delay *delay, Action_Type type, Panel* panel, i32 integer){
|
||||
Delayed_Action *result;
|
||||
result = delayed_action_(delay, type);
|
||||
result->panel = panel;
|
||||
result->integer = integer;
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Delayed_Action*
|
||||
delayed_action_repush(Delay *delay, Delayed_Action *act){
|
||||
Delayed_Action *new_act = delayed_action_(delay, (Action_Type)0);
|
||||
*new_act = *act;
|
||||
if (act->string.str){
|
||||
new_act->string = str_alloc_copy(delay->general, act->string);
|
||||
}
|
||||
return(new_act);
|
||||
}
|
||||
|
||||
#define delayed_open(delay, ...) delayed_action_(delay, DACT_OPEN, ##__VA_ARGS__)
|
||||
#define delayed_open_background(delay, ...) delayed_action_(delay, DACT_OPEN_BACKGROUND, ##__VA_ARGS__)
|
||||
#define delayed_set_line(delay, ...) delayed_action_(delay, DACT_SET_LINE, ##__VA_ARGS__)
|
||||
#define delayed_save_as(delay, ...) delayed_action_(delay, DACT_SAVE_AS, ##__VA_ARGS__)
|
||||
#define delayed_save(delay, ...) delayed_action_(delay, DACT_SAVE, ##__VA_ARGS__)
|
||||
#define delayed_new(delay, ...) delayed_action_(delay, DACT_NEW, ##__VA_ARGS__)
|
||||
#define delayed_switch(delay, ...) delayed_action_(delay, DACT_SWITCH, ##__VA_ARGS__)
|
||||
#define delayed_try_kill(delay, ...) delayed_action_(delay, DACT_TRY_KILL, ##__VA_ARGS__)
|
||||
#define delayed_kill(delay, ...) delayed_action_(delay, DACT_KILL, ##__VA_ARGS__)
|
||||
#define delayed_touch_file(delay, ...) delayed_action_(delay, DACT_TOUCH_FILE, ##__VA_ARGS__)
|
||||
#define delayed_close(delay, ...) delayed_action_(delay, DACT_CLOSE, ##__VA_ARGS__)
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 9.12.2015
|
||||
*
|
||||
* Exchange stuff
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
// NOTE(allen): Uhhh.... is it just me or did it get awkward
|
||||
// in here when I deleted all the file exchange stuff?
|
||||
|
||||
internal b32
|
||||
queue_job_is_pending(Work_Queue *queue, u32 job_id){
|
||||
b32 result;
|
||||
u32 job_index;
|
||||
Full_Job_Data *full_job;
|
||||
|
||||
job_index = job_id % QUEUE_WRAP;
|
||||
full_job = queue->jobs + job_index;
|
||||
|
||||
Assert(full_job->id == job_id);
|
||||
|
||||
result = 0;
|
||||
if (full_job->running_thread != 0){
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
34
4ed_file.cpp
34
4ed_file.cpp
|
@ -111,9 +111,6 @@ struct Editing_File_Settings{
|
|||
// NOTE(allen): This part of the Editing_File is cleared whenever
|
||||
// the contents of the file is set.
|
||||
struct Editing_File_State{
|
||||
b32 is_dummy;
|
||||
b32 is_loading;
|
||||
|
||||
i16 font_id;
|
||||
Buffer_Type buffer;
|
||||
|
||||
|
@ -135,10 +132,6 @@ struct Editing_File_State{
|
|||
u64 last_sys_write_time;
|
||||
};
|
||||
|
||||
struct Editing_File_Preload{
|
||||
i32 start_line;
|
||||
};
|
||||
|
||||
struct Editing_File_Name{
|
||||
char live_name_[256];
|
||||
char source_path_[256];
|
||||
|
@ -168,9 +161,10 @@ struct Editing_File{
|
|||
// NOTE(allen): node must be the first member of Editing_File!
|
||||
File_Node node;
|
||||
Editing_File_Settings settings;
|
||||
union{
|
||||
struct{
|
||||
b32 is_loading;
|
||||
b32 is_dummy;
|
||||
Editing_File_State state;
|
||||
Editing_File_Preload preload;
|
||||
};
|
||||
Editing_File_Name name;
|
||||
Buffer_Slot_ID id;
|
||||
|
@ -317,7 +311,7 @@ working_set_alloc_always(Working_Set *working_set, General_Memory *general){
|
|||
|
||||
inline void
|
||||
working_set_free_file(Working_Set *working_set, Editing_File *file){
|
||||
file->state.is_dummy = 1;
|
||||
file->is_dummy = 1;
|
||||
dll_remove(&file->node);
|
||||
dll_insert(&working_set->free_sentinel, &file->node);
|
||||
--working_set->file_count;
|
||||
|
@ -349,7 +343,7 @@ inline Editing_File*
|
|||
working_set_get_active_file(Working_Set *working_set, Buffer_Slot_ID id){
|
||||
Editing_File *result = 0;
|
||||
result = working_set_index(working_set, id);
|
||||
if (result && result->state.is_dummy){
|
||||
if (result && result->is_dummy){
|
||||
result = 0;
|
||||
}
|
||||
return(result);
|
||||
|
@ -383,7 +377,7 @@ working_set_init(Working_Set *working_set, Partition *partition, General_Memory
|
|||
|
||||
null_file = working_set_index(working_set, 0);
|
||||
dll_remove(&null_file->node);
|
||||
null_file->state.is_dummy = 1;
|
||||
null_file->is_dummy = 1;
|
||||
++working_set->file_count;
|
||||
|
||||
table_size = working_set->file_max;
|
||||
|
@ -488,9 +482,11 @@ working_set_lookup_file(Working_Set *working_set, String string){
|
|||
|
||||
internal void
|
||||
touch_file(Working_Set *working_set, Editing_File *file){
|
||||
Assert(!file->state.is_dummy);
|
||||
dll_remove(&file->node);
|
||||
dll_insert(&working_set->used_sentinel, &file->node);
|
||||
if (file){
|
||||
Assert(!file->is_dummy);
|
||||
dll_remove(&file->node);
|
||||
dll_insert(&working_set->used_sentinel, &file->node);
|
||||
}
|
||||
}
|
||||
|
||||
// Hot Directory
|
||||
|
@ -586,6 +582,7 @@ filename_match(String query, Absolutes *absolutes, String filename, b32 case_sen
|
|||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
internal Hot_Directory_Match
|
||||
hot_directory_first_match(Hot_Directory *hot_directory,
|
||||
String str,
|
||||
|
@ -609,7 +606,7 @@ hot_directory_first_match(Hot_Directory *hot_directory,
|
|||
if (match(filename, str)) is_match = 1;
|
||||
}
|
||||
else{
|
||||
if (match_unsensitive(filename, str)) is_match = 1;
|
||||
if (match_insensitive(filename, str)) is_match = 1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
@ -625,6 +622,7 @@ hot_directory_first_match(Hot_Directory *hot_directory,
|
|||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline File_Sync_State
|
||||
buffer_get_sync(Editing_File *file){
|
||||
|
@ -648,7 +646,7 @@ buffer_needs_save(Editing_File *file){
|
|||
inline b32
|
||||
file_is_ready(Editing_File *file){
|
||||
b32 result = 0;
|
||||
if (file && file->state.is_loading == 0){
|
||||
if (file && file->is_loading == 0){
|
||||
result = 1;
|
||||
}
|
||||
return(result);
|
||||
|
@ -670,7 +668,7 @@ inline void
|
|||
file_set_to_loading(Editing_File *file){
|
||||
file->state = editing_file_state_zero();
|
||||
file->settings = editing_file_settings_zero();
|
||||
file->state.is_loading = 1;
|
||||
file->is_loading = 1;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
1837
4ed_file_view.cpp
1837
4ed_file_view.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 18.12.2015
|
||||
*
|
||||
* Font set for 4coder
|
||||
*
|
||||
*/
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 18.12.2015
|
||||
*
|
||||
* Font set for 4coder
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
|
@ -40,9 +40,9 @@ font__remove(Font_Slot *slot){
|
|||
n->prev = p;
|
||||
}
|
||||
|
||||
internal Font_Slot
|
||||
inline Font_Slot
|
||||
font_slot_zero(){
|
||||
Font_Slot slot = {};
|
||||
Font_Slot slot = {0};
|
||||
return(slot);
|
||||
}
|
||||
|
||||
|
@ -57,10 +57,10 @@ font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){
|
|||
|
||||
partition_align(partition, 8);
|
||||
set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot)));
|
||||
|
||||
|
||||
set->free_slots = font_slot_zero();
|
||||
set->used_slots = font_slot_zero();
|
||||
|
||||
|
||||
dll_init_sentinel(&set->free_slots);
|
||||
dll_init_sentinel(&set->used_slots);
|
||||
|
||||
|
@ -69,7 +69,7 @@ font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){
|
|||
dll_insert(&set->free_slots, (Font_Slot*)ptr);
|
||||
ptr += sizeof(Font_Slot) + sizeof(Render_Font);
|
||||
}
|
||||
|
||||
|
||||
set->font_used_flags = push_array(partition, b8, max);
|
||||
set->live_max = live_max;
|
||||
}
|
||||
|
@ -87,12 +87,12 @@ font_set_add_hash(Font_Set *set, String name, i16 font_id){
|
|||
entry.hash = font_hash(name);
|
||||
entry.name = name;
|
||||
entry.font_id = font_id;
|
||||
|
||||
|
||||
u32 i, j;
|
||||
i = entry.hash % set->max;
|
||||
j = i - 1;
|
||||
if (i <= 1) j += set->max;
|
||||
|
||||
|
||||
for (; i != j; ++i){
|
||||
if (i == set->max) i = 0;
|
||||
if (set->entries[i].font_id == 0){
|
||||
|
@ -100,7 +100,7 @@ font_set_add_hash(Font_Set *set, String name, i16 font_id){
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Assert(i != j);
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ font_set_load(Partition *partition, Font_Set *set, i16 font_id){
|
|||
font__insert(&set->used_slots, slot);
|
||||
|
||||
Render_Font *font = (Render_Font*)(slot + 1);
|
||||
set->font_load(font, info->filename.str, info->pt_size, 4);
|
||||
set->font_load(font, info->filename.str, info->pt_size, 4, 1);
|
||||
info->font = font;
|
||||
slot->font_id = font_id;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ internal void
|
|||
font_set_use(Partition *partition, Font_Set *set, i16 font_id){
|
||||
b8 already_used;
|
||||
already_used = set->font_used_flags[font_id-1];
|
||||
|
||||
|
||||
if (!already_used){
|
||||
if (set->used_this_frame < set->live_max){
|
||||
++set->used_this_frame;
|
||||
|
@ -153,7 +153,7 @@ font_set_use(Partition *partition, Font_Set *set, i16 font_id){
|
|||
already_used = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (already_used){
|
||||
// TODO(allen): optimize if you don't mind!!!!
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
|
@ -165,7 +165,7 @@ font_set_use(Partition *partition, Font_Set *set, i16 font_id){
|
|||
font_set_load(partition, set, font_id);
|
||||
}
|
||||
slot = ((Font_Slot*)info->font) - 1;
|
||||
|
||||
|
||||
font__remove(slot);
|
||||
font__insert(&set->used_slots, slot);
|
||||
}
|
||||
|
@ -176,12 +176,16 @@ font_set_add(Partition *partition, Font_Set *set,
|
|||
String filename, String name, i32 pt_size){
|
||||
b32 result = 0;
|
||||
if (font_set_can_add(set)){
|
||||
Render_Font dummy_font = {0};
|
||||
i16 font_id = (i16)(++set->count);
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
info->filename = filename;
|
||||
info->name = name;
|
||||
info->pt_size = pt_size;
|
||||
set->font_info_load(partition, filename.str, pt_size, &info->height, &info->advance);
|
||||
set->font_load(&dummy_font, info->filename.str, info->pt_size, 4, 0);
|
||||
info->height = dummy_font.height;
|
||||
info->advance = dummy_font.advance;
|
||||
|
||||
font_set_add_hash(set, name, font_id);
|
||||
|
||||
if (font_set_can_load(set)){
|
||||
|
@ -201,7 +205,7 @@ font_set_find_pos(Font_Set *set, String name, u32 *position){
|
|||
i = hash % set->max;
|
||||
j = i - 1;
|
||||
if (j <= 1) j += set->max;
|
||||
|
||||
|
||||
result = 0;
|
||||
Font_Table_Entry *entry;
|
||||
for (; i != j; ++i){
|
||||
|
@ -215,7 +219,7 @@ font_set_find_pos(Font_Set *set, String name, u32 *position){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
@ -228,7 +232,7 @@ font_set_extract(Font_Set *set, String name, i16 *font_id){
|
|||
if (result){
|
||||
*font_id = set->entries[position].font_id;
|
||||
}
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
77
4ed_gui.cpp
77
4ed_gui.cpp
|
@ -171,8 +171,6 @@ struct GUI_Edit{
|
|||
|
||||
enum GUI_Command_Type{
|
||||
guicom_null,
|
||||
guicom_begin_overlap,
|
||||
guicom_end_overlap,
|
||||
guicom_begin_serial,
|
||||
guicom_end_serial,
|
||||
guicom_top_bar,
|
||||
|
@ -371,16 +369,6 @@ gui_push_string(GUI_Target *target, GUI_Header *h, String s){
|
|||
gui_push_string(target, h, s, 0);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_begin_overlap(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_begin_overlap);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_end_overlap(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_end_overlap);
|
||||
}
|
||||
|
||||
internal void
|
||||
gui_begin_serial_section(GUI_Target *target){
|
||||
gui_push_simple_command(target, guicom_begin_serial);
|
||||
|
@ -661,17 +649,13 @@ gui_get_scroll_vars(GUI_Target *target, GUI_id scroll_context_id, GUI_Scroll_Var
|
|||
*vars_out = target->scroll_updated;
|
||||
*region_out = target->region_updated;
|
||||
|
||||
if (vars_out->target_y < vars_out->min_y) vars_out->target_y = vars_out->min_y;
|
||||
if (vars_out->target_y > vars_out->max_y) vars_out->target_y = vars_out->max_y;
|
||||
|
||||
if (vars_out->scroll_y < vars_out->min_y) vars_out->scroll_y = vars_out->min_y;
|
||||
if (vars_out->scroll_y > vars_out->max_y) vars_out->scroll_y = vars_out->max_y;
|
||||
vars_out->target_y = clamp(0.f, vars_out->target_y, vars_out->max_y);
|
||||
|
||||
if (gui_id_eq(target->active, gui_id_scrollbar())){
|
||||
result = 1;
|
||||
target->animating = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
@ -724,7 +708,6 @@ gui_activate_scrolling(GUI_Target *target){
|
|||
}
|
||||
|
||||
struct GUI_Section{
|
||||
b32 overlapped;
|
||||
i32 max_v, v, top_v;
|
||||
};
|
||||
|
||||
|
@ -739,7 +722,6 @@ struct GUI_Session{
|
|||
i32_Rect full_rect;
|
||||
i32_Rect rect;
|
||||
|
||||
f32 suggested_min_y;
|
||||
f32 suggested_max_y;
|
||||
i32 clip_y;
|
||||
|
||||
|
@ -759,17 +741,11 @@ struct GUI_Session{
|
|||
|
||||
#define GUIScrollbarWidth 16
|
||||
|
||||
// TODO(allen): We can probably totally get rid of this now.
|
||||
internal i32
|
||||
gui_session_get_eclipsed_y(GUI_Session *session){
|
||||
GUI_Section *section = session->sections;
|
||||
i32 count = session->t + 1, i;
|
||||
i32 max_v = 0;
|
||||
for (i = 0; i < count; ++i, ++section){
|
||||
if (section->overlapped){
|
||||
max_v = Max(max_v, section->max_v);
|
||||
}
|
||||
}
|
||||
max_v = Max(max_v, session->sections[count-1].top_v);
|
||||
i32 count = session->t + 1;
|
||||
i32 max_v = session->sections[count-1].top_v;
|
||||
return(max_v);
|
||||
}
|
||||
|
||||
|
@ -804,9 +780,7 @@ gui_session_init(GUI_Session *session, GUI_Target *target,
|
|||
|
||||
internal void
|
||||
gui_section_end_item(GUI_Section *section, i32 v){
|
||||
if (!section->overlapped){
|
||||
section->v = v;
|
||||
}
|
||||
section->v = v;
|
||||
if (section->max_v < v){
|
||||
section->max_v = v;
|
||||
}
|
||||
|
@ -978,29 +952,10 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
switch (h->type){
|
||||
case guicom_null: Assert(0); break;
|
||||
|
||||
case guicom_begin_overlap:
|
||||
++session->t;
|
||||
Assert(session->t < ArrayCount(session->sections));
|
||||
new_section = &session->sections[session->t];
|
||||
new_section->overlapped = 1;
|
||||
new_section->v = y;
|
||||
new_section->max_v = y;
|
||||
new_section->top_v = y;
|
||||
break;
|
||||
|
||||
case guicom_end_overlap:
|
||||
Assert(session->t > 0);
|
||||
Assert(section->overlapped);
|
||||
prev_section = &session->sections[--session->t];
|
||||
end_v = section->max_v;
|
||||
end_section = prev_section;
|
||||
break;
|
||||
|
||||
case guicom_begin_serial:
|
||||
++session->t;
|
||||
Assert(session->t < ArrayCount(session->sections));
|
||||
new_section = &session->sections[session->t];
|
||||
new_section->overlapped = 0;
|
||||
new_section->v = y;
|
||||
new_section->max_v = y;
|
||||
new_section->top_v = y;
|
||||
|
@ -1008,7 +963,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
|
||||
case guicom_end_serial:
|
||||
Assert(session->t > 0);
|
||||
Assert(!section->overlapped);
|
||||
prev_section = &session->sections[--session->t];
|
||||
end_v = section->max_v;
|
||||
end_section = prev_section;
|
||||
|
@ -1110,7 +1064,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
|
||||
case guicom_scrollable:
|
||||
Assert(session->is_scrollable == 0);
|
||||
Assert(!section->overlapped);
|
||||
session->is_scrollable = 1;
|
||||
always_give_to_user = 1;
|
||||
|
||||
|
@ -1128,7 +1081,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
|
||||
case guicom_scrollable_bar:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
rect.x1 = session->full_rect.x1;
|
||||
rect.x0 = rect.x1 - GUIScrollbarWidth;
|
||||
|
@ -1151,7 +1103,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
|
||||
case guicom_scrollable_top:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
gui_scrollbar_top(session->scroll_rect, &rect);
|
||||
scroll_v = 0;
|
||||
|
@ -1159,29 +1110,26 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
|
||||
case guicom_scrollable_slider:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
|
||||
lerp_space_scroll_v =
|
||||
unlerp((f32)target->scroll_original.min_y,
|
||||
unlerp(0,
|
||||
(f32)target->scroll_original.target_y,
|
||||
(f32)target->scroll_original.max_y);
|
||||
|
||||
gui_scrollbar_slider(session->scroll_rect, &rect, lerp_space_scroll_v,
|
||||
&session->scroll_top, &session->scroll_bottom,
|
||||
target->scroll_original.min_y, target->scroll_original.max_y);
|
||||
0, target->scroll_original.max_y);
|
||||
scroll_v = 0;
|
||||
break;
|
||||
|
||||
case guicom_scrollable_invisible:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
always_give_to_user = 1;
|
||||
break;
|
||||
|
||||
case guicom_scrollable_bottom:
|
||||
Assert(session->is_scrollable);
|
||||
Assert(!section->overlapped);
|
||||
give_to_user = 1;
|
||||
gui_scrollbar_bottom(session->scroll_rect, &rect);
|
||||
scroll_v = 0;
|
||||
|
@ -1196,9 +1144,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
|||
|
||||
case guicom_end_scrollable_section:
|
||||
always_give_to_user = 1;
|
||||
session->suggested_min_y =
|
||||
-(f32)(gui_session_get_eclipsed_y(session) -
|
||||
gui_session_get_current_top(session));
|
||||
session->suggested_max_y =
|
||||
(f32)(session->scrollable_items_bottom -
|
||||
session->full_rect.y1 * .5f);
|
||||
|
@ -1268,7 +1213,7 @@ internal GUI_View_Jump
|
|||
gui_compute_view_jump(i32_Rect scroll_region, i32_Rect position){
|
||||
GUI_View_Jump jump = {0};
|
||||
i32 region_h = scroll_region.y1 - scroll_region.y0;
|
||||
jump.view_min = (f32)position.y1 - region_h - scroll_region.y0;
|
||||
jump.view_min = (f32)position.y1 - scroll_region.y0 - region_h;
|
||||
jump.view_max = (f32)position.y0 - scroll_region.y0;
|
||||
return(jump);
|
||||
}
|
||||
|
@ -1295,8 +1240,8 @@ gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect
|
|||
if (update->has_index_position){
|
||||
GUI_View_Jump jump =
|
||||
gui_compute_view_jump(scroll_region, update->index_position);
|
||||
jump.view_min += 45.f;
|
||||
jump.view_max -= 45.f;
|
||||
jump.view_min = jump.view_min + 45.f;
|
||||
jump.view_max = jump.view_max - 45.f;
|
||||
*vars = gui_do_jump(target, jump, *vars);
|
||||
}
|
||||
|
||||
|
|
16
4ed_math.cpp
16
4ed_math.cpp
|
@ -464,9 +464,23 @@ unlerp(f32 a, f32 x, f32 b){
|
|||
return(r);
|
||||
}
|
||||
|
||||
inline f32
|
||||
clamp_bottom(f32 a, f32 n){
|
||||
if (n < a) n = a;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline f32
|
||||
clamp_top(f32 n, f32 z){
|
||||
if (n > z) n = z;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline f32
|
||||
clamp(f32 a, f32 n, f32 z){
|
||||
return (n<a)?(a):((n>z)?(z):n);
|
||||
if (n < a) n = a;
|
||||
else if (n > z) n = z;
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -143,7 +143,9 @@ general_memory_attempt_merge(Bubble *left, Bubble *right){
|
|||
internal void
|
||||
general_memory_free(General_Memory *general, void *memory){
|
||||
Bubble *bubble = ((Bubble*)memory) - 1;
|
||||
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
||||
#if FRED_INTERNAL
|
||||
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
||||
#endif
|
||||
bubble->flags &= ~MEM_BUBBLE_USED;
|
||||
bubble->type = 0;
|
||||
Bubble *prev, *next;
|
||||
|
@ -158,7 +160,9 @@ general_memory_reallocate(General_Memory *general, void *old, i32 old_size, i32
|
|||
void *result = old;
|
||||
Bubble *bubble = ((Bubble*)old) - 1;
|
||||
bubble->type = type;
|
||||
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
||||
#if FRED_INTERNAL
|
||||
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
||||
#endif
|
||||
i32 additional_space = size - bubble->size;
|
||||
if (additional_space > 0){
|
||||
Bubble *next = bubble->next;
|
||||
|
|
200
4ed_metagen.cpp
200
4ed_metagen.cpp
|
@ -143,184 +143,6 @@ char* generate_keycode_enum(){
|
|||
return(filename);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
char daction_enum_name[] = "Action_Type";
|
||||
char *daction_enum[] = {
|
||||
"OPEN",
|
||||
"OPEN_BACKGROUND",
|
||||
"SET_LINE",
|
||||
"SAVE_AS",
|
||||
"SAVE",
|
||||
"NEW",
|
||||
"SWITCH",
|
||||
"TRY_KILL",
|
||||
"KILL",
|
||||
"TOUCH_FILE",
|
||||
"CLOSE",
|
||||
};
|
||||
|
||||
char str_alloc_copy[] =
|
||||
"internal String\n"
|
||||
"str_alloc_copy(General_Memory *general, String str){\n"
|
||||
" String result;\n"
|
||||
" result.memory_size = str.memory_size + 1;\n"
|
||||
" result.size = str.size;\n"
|
||||
" result.str = (char*)general_memory_allocate(general, result.memory_size, 0);\n"
|
||||
" memcpy(result.str, str.str, str.size);\n"
|
||||
" result.str[result.size] = 0;\n"
|
||||
" return(result);\n"
|
||||
"}\n\n";
|
||||
|
||||
char delayed_action_zero[] =
|
||||
"inline Delayed_Action\n"
|
||||
"delayed_action_zero(){\n"
|
||||
" Delayed_Action result = {(Action_Type)0};\n"
|
||||
" return(result);\n"
|
||||
"}\n\n"
|
||||
;
|
||||
|
||||
char daction_name[] = "Delayed_Action";
|
||||
Struct_Field daction_fields[] = {
|
||||
{"Action_Type", "type"},
|
||||
};
|
||||
Struct_Field daction_fields_primary[] = {
|
||||
{"String", "string"},
|
||||
{"Panel*", "panel"},
|
||||
{"Editing_File*", "file"},
|
||||
{"i32", "integer"},
|
||||
};
|
||||
enum Daction_Field_Handle{
|
||||
dfph_null,
|
||||
dfph_string,
|
||||
dfph_panel,
|
||||
dfph_file,
|
||||
dfph_integer,
|
||||
};
|
||||
Daction_Field_Handle dact_param_sets[] = {
|
||||
dfph_string, dfph_null,
|
||||
dfph_panel, dfph_null,
|
||||
dfph_file, dfph_null,
|
||||
dfph_file, dfph_panel, dfph_null,
|
||||
dfph_string, dfph_panel, dfph_null,
|
||||
dfph_string, dfph_file, dfph_null,
|
||||
dfph_panel, dfph_integer, dfph_null,
|
||||
};
|
||||
|
||||
char delay_name[] = "Delay";
|
||||
Struct_Field delay_fields[] = {
|
||||
{"General_Memory*", "general"},
|
||||
{"Delayed_Action*", "acts"},
|
||||
{"i32", "count"},
|
||||
{"i32", "max"},
|
||||
};
|
||||
|
||||
char delayed_action_function_top[] =
|
||||
"inline Delayed_Action*\n"
|
||||
"delayed_action_(Delay *delay, Action_Type type";
|
||||
|
||||
char delayed_action_function_bottom[] =
|
||||
"){\n"
|
||||
" Delayed_Action *result;\n"
|
||||
" if (delay->count == delay->max){\n"
|
||||
" delay->max *= 2;\n"
|
||||
" delay->acts = (Delayed_Action*)general_memory_reallocate("
|
||||
"delay->general, delay->acts, delay->count*sizeof(Delayed_Action), delay->max*sizeof(Delayed_Action), 0);\n"
|
||||
" }\n"
|
||||
" result = delay->acts + delay->count++;\n"
|
||||
" *result = delayed_action_zero();\n"
|
||||
" result->type = type;\n"
|
||||
" return(result);\n"
|
||||
"}\n\n";
|
||||
|
||||
char delayed_action_special_param[] = ", %s %s";
|
||||
|
||||
char delayed_action_specialized_middle[] =
|
||||
"){\n"
|
||||
" Delayed_Action *result;\n"
|
||||
" result = delayed_action_(delay, type);\n";
|
||||
|
||||
char delayed_action_special_line[] =
|
||||
" result->%s = %s;\n";
|
||||
|
||||
char delayed_action_special_string_line[] =
|
||||
" result->%s = str_alloc_copy(delay->general, %s);\n";
|
||||
|
||||
char delayed_action_specialized_bottom[] =
|
||||
" return(result);\n"
|
||||
"}\n\n";
|
||||
|
||||
char delayed_action_macro[] =
|
||||
"#define delayed_%s(delay, ...) delayed_action_(delay, DACT_%s, ##__VA_ARGS__)\n";
|
||||
|
||||
char delayed_action_repush_function[] =
|
||||
"inline Delayed_Action*\n"
|
||||
"delayed_action_repush(Delay *delay, Delayed_Action *act){\n"
|
||||
" Delayed_Action *new_act = delayed_action_(delay, (Action_Type)0);\n"
|
||||
" *new_act = *act;\n"
|
||||
" if (act->string.str){\n"
|
||||
" new_act->string = str_alloc_copy(delay->general, act->string);\n"
|
||||
" }\n"
|
||||
" return(new_act);\n"
|
||||
"}\n\n";
|
||||
|
||||
char* generate_delayed_action(){
|
||||
FILE *file;
|
||||
char *filename = "4ed_delay.cpp";
|
||||
char scratch[256];
|
||||
int i,j;
|
||||
|
||||
file = fopen(filename, "wb");
|
||||
|
||||
fprintf(file, "enum %s{\n", daction_enum_name);
|
||||
for (i = 0; i < ArrayCount(daction_enum); ++i){
|
||||
fprintf(file, " DACT_%s,\n", daction_enum[i]);
|
||||
}
|
||||
fprintf(file, "};\n\n");
|
||||
|
||||
struct_begin(file, daction_name);
|
||||
struct_fields(file, daction_fields, ArrayCount(daction_fields));
|
||||
struct_fields(file, daction_fields_primary, ArrayCount(daction_fields_primary));
|
||||
struct_end(file);
|
||||
|
||||
struct_begin(file, delay_name);
|
||||
struct_fields(file, delay_fields, ArrayCount(delay_fields));
|
||||
struct_end(file);
|
||||
|
||||
fprintf(file, "%s", str_alloc_copy);
|
||||
fprintf(file, "%s", delayed_action_zero);
|
||||
fprintf(file, "%s%s", delayed_action_function_top, delayed_action_function_bottom);
|
||||
|
||||
for (i = 0; i < ArrayCount(dact_param_sets); ++i){
|
||||
j = i;
|
||||
fprintf(file, "%s", delayed_action_function_top);
|
||||
for (; dact_param_sets[i] != dfph_null; ++i){
|
||||
Struct_Field field = daction_fields_primary[dact_param_sets[i] - 1];
|
||||
fprintf(file, delayed_action_special_param, field.type, field.name);
|
||||
}
|
||||
fprintf(file, "%s", delayed_action_specialized_middle);
|
||||
for (; dact_param_sets[j] != dfph_null; ++j){
|
||||
int handle = (int)(dact_param_sets[j]);
|
||||
Struct_Field field = daction_fields_primary[handle - 1];
|
||||
if (handle == dfph_string){
|
||||
fprintf(file, delayed_action_special_string_line, field.name, field.name);
|
||||
}
|
||||
else{
|
||||
fprintf(file, delayed_action_special_line, field.name, field.name);
|
||||
}
|
||||
}
|
||||
fprintf(file, "%s", delayed_action_specialized_bottom);
|
||||
}
|
||||
|
||||
fprintf(file, "%s", delayed_action_repush_function);
|
||||
|
||||
for (i = 0; i < ArrayCount(daction_enum); ++i){
|
||||
to_lower(daction_enum[i], scratch);
|
||||
fprintf(file, delayed_action_macro, scratch, daction_enum[i]);
|
||||
}
|
||||
|
||||
return(filename);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
char* bar_style_fields[] = {
|
||||
"bar",
|
||||
|
@ -456,6 +278,7 @@ char* generate_style(){
|
|||
return(filename);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
struct Function_Signature{
|
||||
String name;
|
||||
String ret;
|
||||
|
@ -653,6 +476,24 @@ generate_custom_headers(){
|
|||
);
|
||||
fprintf(file, "};\n");
|
||||
|
||||
// TODO(allen): Generate app->function(app, ...) to function(app, ...) wrappers.
|
||||
// Need to parse parameter names to do this.
|
||||
#if 0
|
||||
for (int i = 0; i < sig_count; ++i){
|
||||
Function_Signature *sig = sigs + i;
|
||||
|
||||
copy_fast_unsafe(name_buffer, sig->name);
|
||||
name_buffer[sig->name.size] = 0;
|
||||
to_lower(name_buffer, name_buffer);
|
||||
|
||||
fprintf(file,
|
||||
"inline %.*s\n"
|
||||
"%s%.*s{ app->%s(",
|
||||
sig->name.size, sig->name.str,
|
||||
name_buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
fclose(file);
|
||||
|
||||
return(filename);
|
||||
|
@ -664,9 +505,6 @@ int main(){
|
|||
filename = generate_keycode_enum();
|
||||
printf("gen success: %s\n", filename);
|
||||
|
||||
filename = generate_delayed_action();
|
||||
printf("gen success: %s\n", filename);
|
||||
|
||||
filename = generate_style();
|
||||
printf("gen success: %s\n", filename);
|
||||
|
||||
|
|
|
@ -34,28 +34,36 @@ draw_set_color(Render_Target *target, u32 color){
|
|||
}
|
||||
}
|
||||
|
||||
#define PutStruct(s,x) *(s*)(target->push_buffer + target->size) = x; target->size += sizeof(s)
|
||||
inline void
|
||||
draw_safe_push(Render_Target *target, i32 size, void *x){
|
||||
if (size + target->size <= target->max){
|
||||
memcpy(target->push_buffer + target->size, x, size);
|
||||
target->size += size;
|
||||
}
|
||||
}
|
||||
|
||||
#define PutStruct(s,x) draw_safe_push(target, sizeof(s), &x)
|
||||
|
||||
internal void
|
||||
draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
|
||||
PutStruct(Render_Piece_Header, piece.header);
|
||||
|
||||
switch (piece.header.type){
|
||||
case piece_type_rectangle:
|
||||
case piece_type_outline:
|
||||
case piece_type_rectangle:
|
||||
case piece_type_outline:
|
||||
PutStruct(Render_Piece_Rectangle, piece.rectangle);
|
||||
break;
|
||||
|
||||
case piece_type_gradient:
|
||||
case piece_type_gradient:
|
||||
PutStruct(Render_Piece_Gradient, piece.gradient);
|
||||
break;
|
||||
|
||||
case piece_type_glyph:
|
||||
case piece_type_mono_glyph:
|
||||
case piece_type_glyph:
|
||||
case piece_type_mono_glyph:
|
||||
PutStruct(Render_Piece_Glyph, piece.glyph);
|
||||
break;
|
||||
|
||||
case piece_type_mono_glyph_advance:
|
||||
case piece_type_mono_glyph_advance:
|
||||
PutStruct(Render_Piece_Glyph_Advance, piece.glyph_advance);
|
||||
break;
|
||||
}
|
||||
|
@ -297,101 +305,17 @@ launch_rendering(Render_Target *target){
|
|||
|
||||
#undef ExtractStruct
|
||||
|
||||
internal i32
|
||||
draw_font_info_load(Partition *partition,
|
||||
char *filename_untranslated,
|
||||
i32 pt_size, i32 *height, i32 *advance){
|
||||
|
||||
char space_[1024];
|
||||
String filename = make_fixed_width_string(space_);
|
||||
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
|
||||
if (!translate_success) return 0;
|
||||
|
||||
i32 result = 1;
|
||||
File_Data file;
|
||||
file = sysshared_load_file(filename.str);
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(partition);
|
||||
stbtt_packedchar *chardata = push_array(partition, stbtt_packedchar, 256);
|
||||
|
||||
i32 oversample = 2;
|
||||
|
||||
i32 tex_width, tex_height;
|
||||
tex_width = pt_size*128*oversample;
|
||||
tex_height = pt_size*2*oversample;
|
||||
void *block = push_block(partition, tex_width * tex_height);
|
||||
|
||||
if (!file.data.data){
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
stbtt_fontinfo font;
|
||||
if (!stbtt_InitFont(&font, (u8*)file.data.data, 0)){
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
i32 ascent, descent, line_gap;
|
||||
f32 scale;
|
||||
|
||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
||||
|
||||
f32 scaled_ascent, scaled_descent, scaled_line_gap;
|
||||
|
||||
scaled_ascent = scale*ascent;
|
||||
scaled_descent = scale*descent;
|
||||
scaled_line_gap = scale*line_gap;
|
||||
|
||||
i32 font_height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
|
||||
|
||||
stbtt_pack_context spc;
|
||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){
|
||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||
if (stbtt_PackFontRange(&spc, (u8*)file.data.data, 0,
|
||||
STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
|
||||
// do nothing
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
stbtt_PackEnd(&spc);
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if (result){
|
||||
i32 max_advance = 0;
|
||||
for (u8 code_point = 0; code_point < 128; ++code_point){
|
||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
||||
i32 adv = CEIL32(chardata[code_point].xadvance);
|
||||
if (max_advance < adv){
|
||||
max_advance = adv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*height = font_height;
|
||||
*advance = max_advance - 1;
|
||||
}
|
||||
}
|
||||
|
||||
system_free_memory(file.data.data);
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// TODO(allen): Put the burden of translation outside
|
||||
// of this function (and other functions implementing
|
||||
// the same interface).
|
||||
internal i32
|
||||
draw_font_load(Partition *part,
|
||||
Render_Font *font_out,
|
||||
char *filename_untranslated,
|
||||
i32 pt_size,
|
||||
i32 tab_width,
|
||||
i32 oversample){
|
||||
i32 oversample,
|
||||
b32 store_texture){
|
||||
|
||||
char space_[1024];
|
||||
String filename = make_fixed_width_string(space_);
|
||||
|
@ -402,12 +326,6 @@ draw_font_load(Partition *part,
|
|||
|
||||
stbtt_packedchar *chardata = font_out->chardata;
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
i32 tex_width = pt_size*16*oversample;
|
||||
i32 tex_height = pt_size*16*oversample;
|
||||
void *block = sysshared_push_block(part, tex_width * tex_height);
|
||||
|
||||
File_Data file = sysshared_load_file(filename.str);
|
||||
|
||||
if (!file.data.data){
|
||||
|
@ -420,85 +338,89 @@ draw_font_load(Partition *part,
|
|||
result = 0;
|
||||
}
|
||||
else{
|
||||
memset(font_out, 0, sizeof(*font_out));
|
||||
|
||||
i32 ascent, descent, line_gap;
|
||||
f32 scale;
|
||||
|
||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
||||
|
||||
f32 scaled_ascent, scaled_descent, scaled_line_gap;
|
||||
f32 scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
||||
|
||||
scaled_ascent = scale*ascent;
|
||||
scaled_descent = scale*descent;
|
||||
scaled_line_gap = scale*line_gap;
|
||||
f32 scaled_ascent = scale*ascent;
|
||||
f32 scaled_descent = scale*descent;
|
||||
f32 scaled_line_gap = scale*line_gap;
|
||||
|
||||
font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
|
||||
font_out->ascent = (i32)(scaled_ascent);
|
||||
font_out->descent = (i32)(scaled_descent);
|
||||
font_out->line_skip = (i32)(scaled_line_gap);
|
||||
|
||||
font_out->tex_width = tex_width;
|
||||
font_out->tex_height = tex_height;
|
||||
|
||||
stbtt_pack_context spc;
|
||||
|
||||
// TODO(allen): If this fails we can just expand the partition here now
|
||||
// rather than forcing the user to do it.
|
||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
|
||||
tex_width, 1, part)){
|
||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||
if (!stbtt_PackFontRange(&spc, (u8*)file.data.data, 0,
|
||||
STBTT_POINT_SIZE((f32)pt_size),
|
||||
0, 128, chardata)){
|
||||
if (store_texture){
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
i32 tex_width = pt_size*16*oversample;
|
||||
i32 tex_height = pt_size*16*oversample;
|
||||
void *block = sysshared_push_block(part, tex_width * tex_height);
|
||||
|
||||
font_out->tex_width = tex_width;
|
||||
font_out->tex_height = tex_height;
|
||||
|
||||
stbtt_pack_context spc;
|
||||
|
||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
|
||||
tex_width, 1, part)){
|
||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||
if (!stbtt_PackFontRange(&spc, (u8*)file.data.data, 0,
|
||||
STBTT_POINT_SIZE((f32)pt_size),
|
||||
0, 128, chardata)){
|
||||
result = 0;
|
||||
}
|
||||
|
||||
stbtt_PackEnd(&spc);
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
stbtt_PackEnd(&spc);
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if (result){
|
||||
GLuint font_tex;
|
||||
glGenTextures(1, &font_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, font_tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block);
|
||||
|
||||
font_out->tex = font_tex;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
font_out->chardata['\r'] = font_out->chardata[' '];
|
||||
font_out->chardata['\n'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'].xadvance *= tab_width;
|
||||
|
||||
i32 max_advance = 0;
|
||||
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(font_out->chardata[code_point].xadvance);
|
||||
if (max_advance < advance) max_advance = advance;
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
}
|
||||
else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
if (result){
|
||||
GLuint font_tex;
|
||||
glGenTextures(1, &font_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, font_tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block);
|
||||
|
||||
font_out->tex = font_tex;
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
font_out->chardata['\r'] = font_out->chardata[' '];
|
||||
font_out->chardata['\n'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'] = font_out->chardata[' '];
|
||||
font_out->chardata['\t'].xadvance *= tab_width;
|
||||
|
||||
i32 max_advance = 0;
|
||||
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(font_out->chardata[code_point].xadvance);
|
||||
if (max_advance < advance) max_advance = advance;
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
}
|
||||
else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){
|
||||
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
|
||||
}
|
||||
}
|
||||
font_out->advance = max_advance - 1;
|
||||
}
|
||||
font_out->advance = max_advance - 1;
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
}
|
||||
system_free_memory(file.data.data);
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,16 +115,11 @@ typedef Draw_Push_Piece_Sig(Draw_Push_Piece);
|
|||
Render_Font *font_out, \
|
||||
char *filename, \
|
||||
i32 pt_size, \
|
||||
i32 tab_width)
|
||||
i32 tab_width, \
|
||||
b32 store_texture)
|
||||
typedef Font_Load_Sig(Font_Load);
|
||||
|
||||
#define Font_Info_Load_Sig(name) i32 name( \
|
||||
Partition *partition, \
|
||||
char *filename, \
|
||||
i32 pt_size, \
|
||||
i32 *height, \
|
||||
i32 *advance)
|
||||
typedef Font_Info_Load_Sig(Font_Info_Load);
|
||||
|
||||
|
||||
#define Release_Font_Sig(name) void name(Render_Font *font)
|
||||
typedef Release_Font_Sig(Release_Font);
|
||||
|
@ -158,7 +153,7 @@ struct Font_Set{
|
|||
Font_Slot free_slots;
|
||||
Font_Slot used_slots;
|
||||
|
||||
Font_Info_Load *font_info_load;
|
||||
//Font_Info_Load *font_info_load;
|
||||
Font_Load *font_load;
|
||||
Release_Font *release_font;
|
||||
|
||||
|
|
50
4ed_system.h
50
4ed_system.h
|
@ -35,9 +35,16 @@ uhash_equal(Unique_Hash a, Unique_Hash b){
|
|||
return(result);
|
||||
}
|
||||
|
||||
// NOTE(allen): These two time functions should return values
|
||||
// in the same time space. There is no requirement about
|
||||
// resolution but the higher the better. These functions
|
||||
// should not be used for profiling purposes.
|
||||
#define Sys_File_Time_Stamp_Sig(name) u64 name(char *filename)
|
||||
typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp);
|
||||
|
||||
#define Sys_Now_Time_Stamp_Sig(name) u64 name()
|
||||
typedef Sys_Now_Time_Stamp_Sig(System_Now_Time_Stamp);
|
||||
|
||||
// TODO(allen): make directory a char* to signal that it must be null terminated
|
||||
#define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory)
|
||||
typedef Sys_Set_File_List_Sig(System_Set_File_List);
|
||||
|
@ -66,13 +73,9 @@ typedef Sys_File_Load_End_Sig(System_File_Load_End);
|
|||
#define Sys_File_Save_Sig(name) b32 name(char *filename, char *buffer, i32 size)
|
||||
typedef Sys_File_Save_Sig(System_File_Save);
|
||||
|
||||
|
||||
#define Sys_Post_Clipboard_Sig(name) void name(String str)
|
||||
typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard);
|
||||
|
||||
#define Sys_Time_Sig(name) u64 name()
|
||||
typedef Sys_Time_Sig(System_Time);
|
||||
|
||||
// cli
|
||||
struct CLI_Handles{
|
||||
Plat_Handle proc;
|
||||
|
@ -154,15 +157,17 @@ thread_memory_zero(){
|
|||
struct Thread_Exchange;
|
||||
struct System_Functions;
|
||||
|
||||
#define Job_Callback_Sig(name) void name( \
|
||||
System_Functions *system, Thread_Context *thread, Thread_Memory *memory, \
|
||||
Thread_Exchange *exchange, void *data[2])
|
||||
#define Job_Callback_Sig(name) void name( \
|
||||
System_Functions *system, \
|
||||
Thread_Context *thread, \
|
||||
Thread_Memory *memory, \
|
||||
void *data[2])
|
||||
typedef Job_Callback_Sig(Job_Callback);
|
||||
|
||||
struct Job_Data{
|
||||
Job_Callback *callback;
|
||||
void *data[2];
|
||||
i32 memory_request;
|
||||
//i32 memory_request;
|
||||
};
|
||||
|
||||
struct Full_Job_Data{
|
||||
|
@ -186,17 +191,15 @@ struct Work_Queue{
|
|||
#define JOB_ID_WRAP (ArrayCount(queue->jobs) * 4)
|
||||
#define QUEUE_WRAP (ArrayCount(queue->jobs))
|
||||
|
||||
struct Thread_Exchange{
|
||||
Work_Queue queues[THREAD_GROUP_COUNT];
|
||||
volatile u32 force_redraw;
|
||||
};
|
||||
|
||||
#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID group_id, Job_Data job)
|
||||
typedef Sys_Post_Job_Sig(System_Post_Job);
|
||||
|
||||
#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID group_id, u32 job_id)
|
||||
typedef Sys_Cancel_Job_Sig(System_Cancel_Job);
|
||||
|
||||
#define Sys_Check_Cancel_Sig(name) b32 name(Thread_Context *thread)
|
||||
typedef Sys_Check_Cancel_Sig(System_Check_Cancel);
|
||||
|
||||
#define Sys_Grow_Thread_Memory_Sig(name) void name(Thread_Memory *memory)
|
||||
typedef Sys_Grow_Thread_Memory_Sig(System_Grow_Thread_Memory);
|
||||
|
||||
|
@ -217,8 +220,9 @@ typedef INTERNAL_Sys_Get_Thread_States_Sig(INTERNAL_System_Get_Thread_States);
|
|||
typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message);
|
||||
|
||||
struct System_Functions{
|
||||
// files: 6
|
||||
// files: 7
|
||||
System_File_Time_Stamp *file_time_stamp;
|
||||
System_Now_Time_Stamp *now_time_stamp;
|
||||
System_Set_File_List *set_file_list;
|
||||
System_File_Unique_Hash *file_unique_hash;
|
||||
System_File_Track *file_track;
|
||||
|
@ -226,17 +230,14 @@ struct System_Functions{
|
|||
System_File_Load_Begin *file_load_begin;
|
||||
System_File_Load_End *file_load_end;
|
||||
System_File_Save *file_save;
|
||||
|
||||
|
||||
// file system navigation (4coder_custom.h): 3
|
||||
File_Exists_Function *file_exists;
|
||||
Directory_CD_Function *directory_cd;
|
||||
Get_4ed_Path_Function *get_4ed_path;
|
||||
|
||||
|
||||
// clipboard: 1
|
||||
System_Post_Clipboard *post_clipboard;
|
||||
|
||||
// time: 1
|
||||
System_Time *time;
|
||||
|
||||
// coroutine: 4
|
||||
System_Create_Coroutine *create_coroutine;
|
||||
|
@ -249,14 +250,15 @@ struct System_Functions{
|
|||
System_CLI_Begin_Update *cli_begin_update;
|
||||
System_CLI_Update_Step *cli_update_step;
|
||||
System_CLI_End_Update *cli_end_update;
|
||||
|
||||
// threads: 5
|
||||
|
||||
// threads: 7
|
||||
System_Post_Job *post_job;
|
||||
System_Cancel_Job *cancel_job;
|
||||
System_Check_Cancel *check_cancel;
|
||||
System_Grow_Thread_Memory *grow_thread_memory;
|
||||
System_Acquire_Lock *acquire_lock;
|
||||
System_Release_Lock *release_lock;
|
||||
|
||||
|
||||
// debug: 3
|
||||
INTERNAL_System_Sentinel *internal_sentinel;
|
||||
INTERNAL_System_Get_Thread_States *internal_get_thread_states;
|
||||
|
@ -266,9 +268,5 @@ struct System_Functions{
|
|||
char slash;
|
||||
};
|
||||
|
||||
struct Exchange{
|
||||
Thread_Exchange thread;
|
||||
};
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// NOTE(allen): This is an experiment, BUT remember a lot of people shit on templates.
|
||||
// So if you start getting a wiff of stupidity from this back out immediately!
|
||||
//
|
||||
// experience 1: no badness, haven't seen any anoying template errors
|
||||
// experience 1: no badness, haven't seen any annoying template errors
|
||||
// ...
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -57,12 +57,13 @@ table_at_capacity(Table *table){
|
|||
internal b32
|
||||
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
u32 hash, *inspect;
|
||||
i32 i;
|
||||
i32 i, start;
|
||||
|
||||
Assert(table->count * 8 < table->max * 7);
|
||||
|
||||
|
||||
hash = (hash_func(item, arg) | TableHashMin);
|
||||
i = hash % table->max;
|
||||
start = i;
|
||||
inspect = table->hash_array + i;
|
||||
|
||||
while (*inspect >= TableHashMin){
|
||||
|
@ -77,6 +78,7 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
|
|||
i = 0;
|
||||
inspect = table->hash_array;
|
||||
}
|
||||
Assert(i != start);
|
||||
}
|
||||
*inspect = hash;
|
||||
memcpy(table->data_array + i*table->item_size, item, table->item_size);
|
||||
|
@ -88,12 +90,13 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
|
|||
internal b32
|
||||
table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||
u32 hash, *inspect;
|
||||
i32 i;
|
||||
i32 i, start;
|
||||
|
||||
Assert((table->count - 1) * 8 < table->max * 7);
|
||||
|
||||
hash = (hash_func(search_key, arg) | TableHashMin);
|
||||
i = hash % table->max;
|
||||
start = i;
|
||||
inspect = table->hash_array + i;
|
||||
|
||||
while (*inspect != TableHashEmpty){
|
||||
|
@ -110,6 +113,7 @@ table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index,
|
|||
i = 0;
|
||||
inspect = table->hash_array;
|
||||
}
|
||||
if (i == start) break;
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Distribution Date: 24.5.2016 (dd.mm.yyyy)
|
||||
Distribution Date: 31.5.2016 (dd.mm.yyyy)
|
||||
|
||||
Thank you for contributing to the 4coder project!
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Distribution Date: 24.5.2016 (dd.mm.yyyy)
|
||||
Distribution Date: 31.5.2016 (dd.mm.yyyy)
|
||||
|
||||
Thank you for contributing to the 4coder project!
|
||||
|
||||
|
|
37
TODO.txt
37
TODO.txt
|
@ -1,7 +1,3 @@
|
|||
|
||||
; before shipping:
|
||||
; [] make sure 4coder_handmade_hero.cpp works
|
||||
|
||||
; Started this list on: (18.01.2016)(dd.mm.yyyy)
|
||||
; This list is an informal todo list, it may very well miss items
|
||||
; checked or unchecked, that I inted to do some day. It is included
|
||||
|
@ -67,11 +63,15 @@
|
|||
; [X] chronal's map setting issue
|
||||
; [X] linux save jankieness
|
||||
; [X] bouncing when scrolling down
|
||||
; [X] sometimes the main cursor is not the same width as the mark cursor in the same spot
|
||||
; [X] tab character wrong width
|
||||
; [X] miblo's off screen cursor thing
|
||||
; [X] new file is messed up for code files, it never finishes parsing!
|
||||
; [X] key presses that should be consumed in the GUI are now passed to the file!
|
||||
; [X] paste snaps the cursor back into view!
|
||||
;
|
||||
; [] indication on failure to save
|
||||
; [] clean whitespace doesn't appear to be cleaning trailing whitespace anymore???
|
||||
; [] sometimes the main cursor is not the same width as the mark cursor in the same spot
|
||||
; [] tab character wrong width
|
||||
; [] miblo's off screen cursor thing
|
||||
;
|
||||
;
|
||||
|
||||
|
@ -99,6 +99,9 @@
|
|||
; [X] feedback messages
|
||||
; [X] feedback message API
|
||||
; [X] kill rect
|
||||
; [X] add high DPI support
|
||||
;
|
||||
; [] OS font rendering
|
||||
;
|
||||
; [] file status in custom API
|
||||
; [] user file bar string
|
||||
|
@ -117,14 +120,13 @@
|
|||
; [X] rewrite GUI
|
||||
; [X] arrow navigation of GUIs
|
||||
; [] GUI API
|
||||
; [] text links -> arbitrary commands / callbacks?
|
||||
;
|
||||
; search related tech
|
||||
; [X] replace word (incremental and/or in range)
|
||||
; [X] caps insensitivety
|
||||
; [] optimize search
|
||||
; [] allow search wrap around beginning/end
|
||||
; [] improved custom API for text "streams"
|
||||
; [] caps insensitivety
|
||||
;
|
||||
; theme related business
|
||||
; [] fix the versioning system for themes
|
||||
|
@ -173,12 +175,11 @@
|
|||
|
||||
; INTERNAL TODOS
|
||||
; [X] switch building non-extensible version by statically linking to custom.cpp
|
||||
; [X] pack fonts more squarely
|
||||
; [] general parameter handling
|
||||
; [] hashed string pool for clipboard/filenames/etc
|
||||
; [] ask for clipboards to update by request, not on loop
|
||||
; [] pack fonts more squarely
|
||||
; [] setup tests through special tool
|
||||
; [] new profiling/debugging system
|
||||
; [] change job canceling to a polling based thing
|
||||
;
|
||||
|
||||
; EASY TODOS
|
||||
|
@ -192,7 +193,6 @@
|
|||
|
||||
; HARD BUGS
|
||||
; [X] reduce cpu consumption
|
||||
; [?] minimize and reopen problem (reported by two users now, still not reproduced here)
|
||||
; [X] repainting too slow for resize looks really dumb
|
||||
; [] fyoucon's segfaults with malloc on win10
|
||||
; [] handling cursor in non-client part of window so it doesn't spaz
|
||||
|
@ -200,6 +200,17 @@
|
|||
; [] how to get fast repaint (do I really need double buffering?)
|
||||
; [] history breaks when heavily used (disk swaping?)
|
||||
;
|
||||
; [] minimize and reopen problem (reported by two users now, still not reproduced here)
|
||||
;
|
||||
|
||||
; FANCY PANTS IDEAS
|
||||
; [] pass messages to 'jobs' to try to avoid cancelling them
|
||||
; if the job still thinks it should be cancelled it will say so
|
||||
; but otherwise the job can try to incorporate the new info
|
||||
; without throwing away the progress it has made so far.
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
; PORTING TODOS
|
||||
; [X] command line parameters
|
||||
|
|
|
@ -128,98 +128,6 @@ buffer_reverse_seek_delimiter(Buffer_Type *buffer, int pos, char delim){
|
|||
return(pos);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_seek_whitespace_down(Buffer_Type *buffer, int pos){
|
||||
Buffer_Stringify_Type loop;
|
||||
char *data;
|
||||
int end;
|
||||
int size;
|
||||
int no_hard;
|
||||
int prev_endline;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
loop = buffer_stringify_loop(buffer, pos, size);
|
||||
|
||||
for (;buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (;pos < end; ++pos){
|
||||
if (!is_whitespace(data[pos])) goto buffer_seek_whitespace_down_mid;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_seek_whitespace_down_mid:
|
||||
no_hard = 0;
|
||||
prev_endline = -1;
|
||||
for (;buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; pos < end; ++pos){
|
||||
if (data[pos] == '\n'){
|
||||
if (no_hard) goto buffer_seek_whitespace_down_end;
|
||||
else{
|
||||
no_hard = 1;
|
||||
prev_endline = pos;
|
||||
}
|
||||
}
|
||||
else if (!is_whitespace(data[pos])){
|
||||
no_hard = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer_seek_whitespace_down_end:
|
||||
if (prev_endline == -1 || prev_endline+1 >= size) pos = size;
|
||||
else pos = prev_endline+1;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_seek_whitespace_up(Buffer_Type *buffer, int pos){
|
||||
Buffer_Backify_Type loop;
|
||||
char *data;
|
||||
int end;
|
||||
int size;
|
||||
int no_hard;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
loop = buffer_backify_loop(buffer, pos-1, 1);
|
||||
|
||||
for (;buffer_backify_good(&loop);
|
||||
buffer_backify_next(&loop)){
|
||||
end = loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (;pos >= end; --pos){
|
||||
if (!is_whitespace(data[pos])) goto buffer_seek_whitespace_up_mid;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_seek_whitespace_up_mid:
|
||||
no_hard = 0;
|
||||
for (;buffer_backify_good(&loop);
|
||||
buffer_backify_next(&loop)){
|
||||
end = loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; pos >= end; --pos){
|
||||
if (data[pos] == '\n'){
|
||||
if (no_hard) goto buffer_seek_whitespace_up_end;
|
||||
else no_hard = 1;
|
||||
}
|
||||
else if (!is_whitespace(data[pos])){
|
||||
no_hard = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer_seek_whitespace_up_end:
|
||||
if (pos != 0) ++pos;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_seek_whitespace_right(Buffer_Type *buffer, int pos){
|
||||
Buffer_Stringify_Type loop;
|
||||
|
@ -945,6 +853,8 @@ buffer_get_line_index_range(Buffer_Type *buffer, int pos, int l_bound, int u_bou
|
|||
|
||||
lines = buffer->line_starts;
|
||||
|
||||
assert_4tech(lines != 0);
|
||||
|
||||
start = l_bound;
|
||||
end = u_bound;
|
||||
for (;;){
|
||||
|
@ -964,8 +874,7 @@ buffer_get_line_index_range(Buffer_Type *buffer, int pos, int l_bound, int u_bou
|
|||
|
||||
inline_4tech int
|
||||
buffer_get_line_index(Buffer_Type *buffer, int pos){
|
||||
int result;
|
||||
result = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count);
|
||||
int result = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
@ -1313,6 +1222,42 @@ buffer_get_start_cursor(Buffer_Type *buffer, float *wraps, float scroll_y,
|
|||
return(result);
|
||||
}
|
||||
|
||||
#define BRFlag_Special_Character (1 << 0)
|
||||
|
||||
typedef struct Buffer_Render_Item{
|
||||
int index;
|
||||
unsigned short glyphid;
|
||||
unsigned short flags;
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
} Buffer_Render_Item;
|
||||
|
||||
inline_4tech void
|
||||
write_render_item(Buffer_Render_Item *item,
|
||||
int index,
|
||||
unsigned short glyphid,
|
||||
float x, float y,
|
||||
float w, float h){
|
||||
item->index = index;
|
||||
item->glyphid = glyphid;
|
||||
item->x0 = x;
|
||||
item->y0 = y;
|
||||
item->x1 = x + w;
|
||||
item->y1 = y + h;
|
||||
}
|
||||
|
||||
inline_4tech float
|
||||
write_render_item_inline(Buffer_Render_Item *item,
|
||||
int index,
|
||||
unsigned short glyphid,
|
||||
float x, float y,
|
||||
float *advance_data, float h){
|
||||
float ch_width;
|
||||
ch_width = measure_character(advance_data, (char)glyphid);
|
||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||
return(ch_width);
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max, int *count,
|
||||
float port_x, float port_y,
|
||||
|
@ -1324,6 +1269,7 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
|||
|
||||
Buffer_Stringify_Type loop;
|
||||
Buffer_Render_Item *item;
|
||||
Buffer_Render_Item *item_end;
|
||||
char *data;
|
||||
int size, end;
|
||||
float shift_x, shift_y;
|
||||
|
@ -1343,116 +1289,141 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
|||
y = shift_y;
|
||||
item_i = 0;
|
||||
item = items + item_i;
|
||||
item_end = items + max;
|
||||
|
||||
// TODO(allen): What's the plan for when there is not enough space to store
|
||||
// more render items? It seems like we should be able to use the view_x
|
||||
// to skip items that are not in view right? That way I think it would
|
||||
// just always fit in the buffer.
|
||||
if (advance_data){
|
||||
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_good(&loop) && item < item_end;
|
||||
buffer_stringify_next(&loop)){
|
||||
|
||||
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
|
||||
|
||||
for (i = loop.absolute_pos; i < end; ++i){
|
||||
ch = data[i];
|
||||
ch_width = measure_character(advance_data, ch);
|
||||
|
||||
|
||||
if (ch_width + x > width + shift_x && wrapped && ch != '\n'){
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
}
|
||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||
|
||||
switch (ch){
|
||||
case '\n':
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
if (opts.show_slash_t){
|
||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
}
|
||||
else{
|
||||
switch (ch){
|
||||
case '\n':
|
||||
if (item < item_end){
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
++item;
|
||||
|
||||
x = shift_x;
|
||||
y += font_height;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
if (item < item_end){
|
||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
if (opts.show_slash_t){
|
||||
if (item < item_end){
|
||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
if (item < item_end){
|
||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
||||
item->flags = BRFlag_Special_Character;
|
||||
++item_i;
|
||||
++item;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (item < item_end){
|
||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
++item;
|
||||
}
|
||||
}
|
||||
x += ch_width;
|
||||
break;
|
||||
|
||||
default:
|
||||
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
|
||||
|
||||
default:
|
||||
if (item < item_end){
|
||||
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
||||
item->flags = 0;
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_get_render_data_end:
|
||||
|
||||
buffer_get_render_data_end:
|
||||
if (y <= height + shift_y || item == items){
|
||||
if (item < item_end){
|
||||
ch = 0;
|
||||
ch_width = measure_character(advance_data, ' ');
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (item < item_end){
|
||||
ch = 0;
|
||||
ch_width = measure_character(advance_data, ' ');
|
||||
ch_width = 0;
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
}
|
||||
else{
|
||||
ch = 0;
|
||||
ch_width = 0;
|
||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||
++item_i;
|
||||
++item;
|
||||
x += ch_width;
|
||||
}
|
||||
|
||||
// TODO(allen): handle this with a control state
|
||||
assert_4tech(item_i <= max);
|
||||
|
|
|
@ -88,36 +88,6 @@ typedef struct Buffer_Batch_State{
|
|||
int shift_total;
|
||||
} Buffer_Batch_State;
|
||||
|
||||
#define BRFlag_Special_Character (1 << 0)
|
||||
|
||||
typedef struct Buffer_Render_Item{
|
||||
int index;
|
||||
unsigned short glyphid;
|
||||
unsigned short flags;
|
||||
float x0, y0;
|
||||
float x1, y1;
|
||||
} Buffer_Render_Item;
|
||||
|
||||
inline_4tech void
|
||||
write_render_item(Buffer_Render_Item *item, int index, unsigned short glyphid,
|
||||
float x, float y, float w, float h){
|
||||
item->index = index;
|
||||
item->glyphid = glyphid;
|
||||
item->x0 = x;
|
||||
item->y0 = y;
|
||||
item->x1 = x + w;
|
||||
item->y1 = y + h;
|
||||
}
|
||||
|
||||
inline_4tech float
|
||||
write_render_item_inline(Buffer_Render_Item *item, int index, unsigned short glyphid,
|
||||
float x, float y, float *advance_data, float h){
|
||||
float ch_width;
|
||||
ch_width = measure_character(advance_data, (char)glyphid);
|
||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||
return(ch_width);
|
||||
}
|
||||
|
||||
inline_4tech Full_Cursor
|
||||
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
|
||||
Full_Cursor hint;
|
||||
|
|
|
@ -21,8 +21,8 @@ if %ERRORLEVEL% neq 0 (set FirstError=1)
|
|||
popd
|
||||
|
||||
pushd ..\build
|
||||
call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp
|
||||
REM call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp
|
||||
REM call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp
|
||||
call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp
|
||||
REM call "..\code\buildsuper.bat" ..\code\power\4coder_casey.cpp
|
||||
if %ERRORLEVEL% neq 0 (set FirstError=1)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ SET OPTS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd
|
|||
SET OPTS=%OPTS% /GR- /nologo
|
||||
SET DEBUG=/Zi
|
||||
set BUILD_DLL=/LD /link /INCREMENTAL:NO /OPT:REF
|
||||
SET EXPORTS=/EXPORT:view_routine /EXPORT:get_bindings /EXPORT:get_alpha_4coder_version
|
||||
SET EXPORTS=/EXPORT:get_bindings /EXPORT:get_alpha_4coder_version
|
||||
|
||||
REM SET LINKS=user32.lib gdi32.lib
|
||||
SET LINKS=
|
||||
|
|
|
@ -18,14 +18,12 @@ Buffer_Summary Get_Buffer_First(Application_Links *app)
|
|||
void Get_Buffer_Next(Application_Links *app, Buffer_Summary *buffer)
|
||||
|
||||
Buffer_Summary Get_Buffer(Application_Links *app, int index)
|
||||
Buffer_Summary Get_Active_Buffer(Application_Links *app)
|
||||
Buffer_Summary Get_Parameter_Buffer(Application_Links *app, int param_index)
|
||||
Buffer_Summary Get_Buffer_By_Name(Application_Links *app, char *filename, int len)
|
||||
|
||||
// TODO(allen): Need more flexible seek system somehow. Regex? Just expose the text stream to the user?
|
||||
int Buffer_Seek_Delimiter(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
|
||||
int Buffer_Seek_String(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||
int Buffer_Seek_String_Insensitive(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||
//int Buffer_Seek_Delimiter(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
|
||||
//int Buffer_Seek_String(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||
//int Buffer_Seek_String_Insensitive(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||
|
||||
int Refresh_Buffer(Application_Links *app, Buffer_Summary *buffer)
|
||||
int Buffer_Read_Range(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out)
|
||||
|
|
1232
linux_4ed.cpp
1232
linux_4ed.cpp
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,89 @@
|
|||
|
||||
struct Custom_Vars{
|
||||
int initialized;
|
||||
Partition part;
|
||||
};
|
||||
|
||||
enum View_Mode{
|
||||
ViewMode_File,
|
||||
};
|
||||
|
||||
struct View_Vars{
|
||||
int id;
|
||||
View_Mode mode;
|
||||
|
||||
GUI_Scroll_Vars scroll;
|
||||
i32_Rect scroll_region;
|
||||
|
||||
int buffer_id;
|
||||
};
|
||||
inline View_Vars
|
||||
view_vars_zero(){
|
||||
View_Vars vars = {0};
|
||||
return(vars);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
view_routine(Application_Links *app, int view_id){
|
||||
Custom_Vars *vars = (Custom_Vars*)app->memory;
|
||||
View_Vars view = {0};
|
||||
view.id = view_id;
|
||||
|
||||
int 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -104,13 +104,11 @@
|
|||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../4coder_default_include.cpp"
|
||||
|
||||
enum maps{
|
||||
my_code_map
|
||||
};
|
||||
|
||||
#ifndef Assert
|
||||
#define internal static
|
||||
#define Assert assert
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#define NO_BINDING
|
||||
#include "../4coder_default_bindings.cpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
CUSTOM_COMMAND_SIG(kill_rect){
|
||||
View_Summary view = app->get_active_view(app);
|
||||
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||
|
@ -25,102 +27,6 @@ CUSTOM_COMMAND_SIG(kill_rect){
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): This stream stuff will be moved to helper if it looks
|
||||
// like it will be helpful. So if you want to use it to build your own
|
||||
// commands I suggest you move it there first.
|
||||
struct Stream_Chunk{
|
||||
Application_Links *app;
|
||||
Buffer_Summary *buffer;
|
||||
|
||||
char *base_data;
|
||||
int start, end;
|
||||
int data_size;
|
||||
|
||||
char *data;
|
||||
};
|
||||
|
||||
int
|
||||
round_down(int x, int b){
|
||||
int r = 0;
|
||||
if (x >= 0){
|
||||
r = x - (x % b);
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
int
|
||||
round_up(int x, int b){
|
||||
int r = 0;
|
||||
if (x >= 0){
|
||||
r = x - (x % b) + b;
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
int
|
||||
init_stream_chunk(Stream_Chunk *chunk,
|
||||
Application_Links *app, Buffer_Summary *buffer,
|
||||
int pos, char *data, int size){
|
||||
int result = 0;
|
||||
|
||||
app->refresh_buffer(app, buffer);
|
||||
if (pos >= 0 && pos < buffer->size && size > 0){
|
||||
result = 1;
|
||||
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->end > buffer->size){
|
||||
chunk->end = buffer->size;
|
||||
}
|
||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
int
|
||||
forward_stream_chunk(Stream_Chunk *chunk){
|
||||
Application_Links *app = chunk->app;
|
||||
Buffer_Summary *buffer = chunk->buffer;
|
||||
int result = 0;
|
||||
|
||||
app->refresh_buffer(app, buffer);
|
||||
if (chunk->end < buffer->size){
|
||||
result = 1;
|
||||
chunk->start = chunk->end;
|
||||
chunk->end += chunk->data_size;
|
||||
if (chunk->end > buffer->size){
|
||||
chunk->end = buffer->size;
|
||||
}
|
||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
int
|
||||
backward_stream_chunk(Stream_Chunk *chunk){
|
||||
Application_Links *app = chunk->app;
|
||||
Buffer_Summary *buffer = chunk->buffer;
|
||||
int result = 0;
|
||||
|
||||
app->refresh_buffer(app, buffer);
|
||||
if (chunk->start > 0){
|
||||
result = 1;
|
||||
chunk->end = chunk->start;
|
||||
chunk->start -= chunk->data_size;
|
||||
if (chunk->start < 0){
|
||||
chunk->start = 0;
|
||||
}
|
||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||
chunk->data = chunk->base_data - chunk->start;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// TODO(allen): Both of these brace related commands would work better
|
||||
// if the API exposed access to the tokens in a code file.
|
||||
CUSTOM_COMMAND_SIG(mark_matching_brace){
|
||||
|
@ -144,7 +50,8 @@ CUSTOM_COMMAND_SIG(mark_matching_brace){
|
|||
int nesting_counter = 0;
|
||||
char at_cursor = 0;
|
||||
|
||||
if (init_stream_chunk(&chunk, app, &buffer, i, chunk_space, sizeof(chunk_space))){
|
||||
if (init_stream_chunk(&chunk, app, &buffer, i,
|
||||
chunk_space, sizeof(chunk_space))){
|
||||
|
||||
// NOTE(allen): This is important! The data array is a pointer that is adjusted
|
||||
// so that indexing it with "i" will put it with the chunk that is actually loaded.
|
||||
|
@ -377,10 +284,5 @@ get_bindings(void *data, int size){
|
|||
return(result);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
view_routine(Application_Links *app, int view_id){
|
||||
app->get_user_input(app, 0, 0);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@
|
|||
#ifndef FCPP_NEW_LEXER_INC
|
||||
#define FCPP_NEW_LEXER_INC
|
||||
|
||||
#include "..\4cpp_lexer_types.h"
|
||||
#include "4cpp_lexer_fsms.h"
|
||||
#include "4cpp_lexer_tables.c"
|
||||
|
||||
|
@ -286,22 +287,35 @@ cpp_attempt_token_merge(Cpp_Token prev_token, Cpp_Token next_token){
|
|||
return result;
|
||||
}
|
||||
|
||||
lexer_link void
|
||||
cpp_push_token_nonalloc(Cpp_Token *out_tokens, int *token_i, Cpp_Token token){
|
||||
lexer_link int
|
||||
cpp_place_token_nonalloc(Cpp_Token *out_tokens, int token_i, Cpp_Token token){
|
||||
Cpp_Token_Merge merge = {(Cpp_Token_Type)0};
|
||||
Cpp_Token prev_token = {(Cpp_Token_Type)0};
|
||||
|
||||
if (*token_i > 0){
|
||||
prev_token = out_tokens[*token_i - 1];
|
||||
if (token_i > 0){
|
||||
prev_token = out_tokens[token_i - 1];
|
||||
merge = new_lex::cpp_attempt_token_merge(prev_token, token);
|
||||
if (merge.did_merge){
|
||||
out_tokens[*token_i - 1] = merge.new_token;
|
||||
out_tokens[token_i - 1] = merge.new_token;
|
||||
}
|
||||
}
|
||||
|
||||
if (!merge.did_merge){
|
||||
out_tokens[(*token_i)++] = token;
|
||||
out_tokens[token_i++] = token;
|
||||
}
|
||||
|
||||
return(token_i);
|
||||
}
|
||||
|
||||
lexer_link bool
|
||||
cpp_push_token_nonalloc(Cpp_Token_Stack *out_tokens, Cpp_Token token){
|
||||
bool result = 0;
|
||||
if (out_tokens->count == out_tokens->max_count){
|
||||
out_tokens->count =
|
||||
cpp_place_token_nonalloc(out_tokens->tokens, out_tokens->count, token);
|
||||
result = 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
struct Lex_Data{
|
||||
|
@ -311,15 +325,13 @@ struct Lex_Data{
|
|||
|
||||
int pos;
|
||||
int pos_overide;
|
||||
int chunk_pos;
|
||||
|
||||
Lex_FSM fsm;
|
||||
Whitespace_FSM wfsm;
|
||||
unsigned char pp_state;
|
||||
unsigned char completed;
|
||||
|
||||
unsigned short *key_eq_classes;
|
||||
unsigned char *key_table;
|
||||
|
||||
Cpp_Token token;
|
||||
|
||||
int __pc__;
|
||||
|
@ -335,20 +347,27 @@ struct Lex_Data{
|
|||
token_stack_out->count = token_i;\
|
||||
*S_ptr = S; S_ptr->__pc__ = -1; return(n); }
|
||||
|
||||
enum Lex_Result{
|
||||
LexFinished,
|
||||
LexNeedChunk,
|
||||
LexNeedTokenMemory,
|
||||
LexHitTokenLimit
|
||||
};
|
||||
|
||||
lexer_link int
|
||||
cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_stack_out){
|
||||
Lex_Data S = *S_ptr;
|
||||
|
||||
|
||||
Cpp_Token *out_tokens = token_stack_out->tokens;
|
||||
int token_i = token_stack_out->count;
|
||||
int max_token_i = token_stack_out->max_count;
|
||||
|
||||
|
||||
Pos_Update_Rule pos_update_rule = PUR_none;
|
||||
|
||||
|
||||
char c = 0;
|
||||
|
||||
int end_pos = size + S.pos;
|
||||
chunk -= S.pos;
|
||||
|
||||
int end_pos = size + S.chunk_pos;
|
||||
chunk -= S.chunk_pos;
|
||||
|
||||
switch (S.__pc__){
|
||||
DrCase(1);
|
||||
|
@ -357,7 +376,6 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
DrCase(4);
|
||||
DrCase(5);
|
||||
DrCase(6);
|
||||
DrCase(7);
|
||||
}
|
||||
|
||||
for (;;){
|
||||
|
@ -372,7 +390,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.wfsm.white_done = (S.wfsm.pp_state >= LSPP_count);
|
||||
|
||||
if (S.wfsm.white_done == 0){
|
||||
DrYield(4, 1);
|
||||
S.chunk_pos += size;
|
||||
DrYield(4, LexNeedChunk);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
@ -380,7 +399,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.pp_state = S.wfsm.pp_state;
|
||||
if (S.pp_state >= LSPP_count){
|
||||
S.pp_state -= LSPP_count;
|
||||
}
|
||||
}
|
||||
|
||||
S.token_start = S.pos;
|
||||
S.tb_pos = 0;
|
||||
|
@ -388,19 +407,20 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
for(;;){
|
||||
unsigned short *eq_classes = get_eq_classes[S.pp_state];
|
||||
unsigned char *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++] = c;
|
||||
|
||||
|
||||
int i = S.fsm.state + eq_classes[c];
|
||||
S.fsm.state = fsm_table[i];
|
||||
S.fsm.multi_line |= multiline_state_table[S.fsm.state];
|
||||
}
|
||||
S.fsm.emit_token = (S.fsm.state >= LS_count);
|
||||
|
||||
|
||||
if (S.fsm.emit_token == 0){
|
||||
DrYield(3, 1);
|
||||
S.chunk_pos += size;
|
||||
DrYield(3, LexNeedChunk);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
@ -413,13 +433,13 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
if (S.pp_state == LSPP_include){
|
||||
switch (S.fsm.state){
|
||||
case LSINC_default:break;
|
||||
|
||||
|
||||
case LSINC_quotes:
|
||||
case LSINC_pointy:
|
||||
S.token.type = CPP_TOKEN_INCLUDE_FILE;
|
||||
S.token.flags = 0;
|
||||
break;
|
||||
|
||||
|
||||
case LSINC_junk:
|
||||
S.token.type = CPP_TOKEN_JUNK;
|
||||
S.token.flags = 0;
|
||||
|
@ -433,22 +453,22 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
#define OperCase(op,t) case op: S.token.type = t; break;
|
||||
OperCase('{', CPP_TOKEN_BRACE_OPEN);
|
||||
OperCase('}', CPP_TOKEN_BRACE_CLOSE);
|
||||
|
||||
|
||||
OperCase('[', CPP_TOKEN_BRACKET_OPEN);
|
||||
OperCase(']', CPP_TOKEN_BRACKET_CLOSE);
|
||||
|
||||
|
||||
OperCase('(', CPP_TOKEN_PARENTHESE_OPEN);
|
||||
OperCase(')', CPP_TOKEN_PARENTHESE_CLOSE);
|
||||
|
||||
|
||||
OperCase('~', CPP_TOKEN_TILDE);
|
||||
OperCase(',', CPP_TOKEN_COMMA);
|
||||
OperCase(';', CPP_TOKEN_SEMICOLON);
|
||||
OperCase('?', CPP_TOKEN_TERNARY_QMARK);
|
||||
|
||||
|
||||
OperCase('@', CPP_TOKEN_JUNK);
|
||||
OperCase('$', CPP_TOKEN_JUNK);
|
||||
#undef OperCase
|
||||
|
||||
|
||||
case '\\':
|
||||
if (S.pp_state == LSPP_default){
|
||||
S.token.type = CPP_TOKEN_JUNK;
|
||||
|
@ -461,13 +481,14 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
c = chunk[S.pos++];
|
||||
if (!(c == ' ' || c == '\t' || c == '\r' || c == '\v' || c == '\f')) S.wfsm.white_done = 1;
|
||||
}
|
||||
|
||||
|
||||
if (S.wfsm.white_done == 0){
|
||||
DrYield(1, 1);
|
||||
S.chunk_pos += size;
|
||||
DrYield(1, LexNeedChunk);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
|
||||
if (c == '\n'){
|
||||
S.fsm.emit_token = 0;
|
||||
S.pos_overide = 0;
|
||||
|
@ -485,46 +506,10 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
|
||||
case LS_identifier:
|
||||
{
|
||||
S.fsm.state = 0;
|
||||
S.fsm.emit_token = 0;
|
||||
S.fsm.sub_machine = 0;
|
||||
--S.pos;
|
||||
for (;;){
|
||||
// TODO(allen): Need to drop down to the instructions to optimize
|
||||
// this correctly I think. This looks like it will have more branches
|
||||
// than it needs unless I am very careful.
|
||||
for (; S.fsm.state < LSKEY_totally_finished && S.pos < end_pos;){
|
||||
// TODO(allen): Rebase these super tables so that we don't have
|
||||
// to do a subtract on the state.
|
||||
S.key_table = key_tables[S.fsm.sub_machine];
|
||||
S.key_eq_classes = key_eq_class_tables[S.fsm.sub_machine];
|
||||
for (; S.fsm.state < LSKEY_table_transition && S.pos < end_pos;){
|
||||
c = chunk[S.pos++];
|
||||
S.fsm.state = S.key_table[S.fsm.state + S.key_eq_classes[c]];
|
||||
}
|
||||
if (S.fsm.state >= LSKEY_table_transition && S.fsm.state < LSKEY_totally_finished){
|
||||
S.fsm.sub_machine = S.fsm.state - LSKEY_table_transition;
|
||||
S.fsm.state = 0;
|
||||
}
|
||||
}
|
||||
S.fsm.emit_token = (S.fsm.int_state >= LSKEY_totally_finished);
|
||||
|
||||
if (S.fsm.emit_token == 0){
|
||||
DrYield(7, 1);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
--S.pos;
|
||||
|
||||
// TODO(allen): do stuff regarding the actual type of the token
|
||||
S.token.type = CPP_TOKEN_INTEGER_CONSTANT;
|
||||
S.token.flags = 0;
|
||||
|
||||
#if 0
|
||||
--S.pos;
|
||||
|
||||
int word_size = S.pos - S.token_start;
|
||||
|
||||
|
||||
if (S.pp_state == LSPP_body_if){
|
||||
if (match(make_string(S.tb, word_size), make_lit_string("defined"))){
|
||||
S.token.type = CPP_TOKEN_DEFINED;
|
||||
|
@ -532,17 +517,17 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Sub_Match_List_Result sub_match;
|
||||
sub_match = sub_match_list(S.tb, S.tb_pos, 0, bool_lits, word_size);
|
||||
|
||||
|
||||
if (sub_match.index != -1){
|
||||
S.token.type = CPP_TOKEN_BOOLEAN_CONSTANT;
|
||||
S.token.flags = CPP_TFLAG_IS_KEYWORD;
|
||||
}
|
||||
else{
|
||||
sub_match = sub_match_list(S.tb, S.tb_pos, 0, keywords, word_size);
|
||||
|
||||
|
||||
if (sub_match.index != -1){
|
||||
String_And_Flag data = keywords.data[sub_match.index];
|
||||
S.token.type = (Cpp_Token_Type)data.flags;
|
||||
|
@ -553,10 +538,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.token.flags = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}break;
|
||||
|
||||
|
||||
case LS_pound:
|
||||
S.token.flags = 0;
|
||||
switch (c){
|
||||
|
@ -567,7 +550,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_pp:
|
||||
{
|
||||
S.fsm.directive_state = LSDIR_default;
|
||||
|
@ -578,9 +561,10 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.fsm.directive_state = pp_directive_table[S.fsm.directive_state + pp_directive_eq_classes[c]];
|
||||
}
|
||||
S.fsm.emit_token = (S.fsm.int_state >= LSDIR_count);
|
||||
|
||||
|
||||
if (S.fsm.emit_token == 0){
|
||||
DrYield(6, 1);
|
||||
S.chunk_pos += size;
|
||||
DrYield(6, LexNeedChunk);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
@ -590,13 +574,13 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.token.type = type;
|
||||
if (type == CPP_TOKEN_JUNK){
|
||||
S.token.flags = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
S.token.flags = CPP_TFLAG_PP_DIRECTIVE;
|
||||
S.pp_state = (unsigned char)cpp_pp_directive_to_state(S.token.type);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
|
||||
case LS_number:
|
||||
case LS_number0:
|
||||
case LS_hex:
|
||||
|
@ -609,18 +593,19 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.fsm.int_state = int_fsm_table[S.fsm.int_state + int_fsm_eq_classes[c]];
|
||||
}
|
||||
S.fsm.emit_token = (S.fsm.int_state >= LSINT_count);
|
||||
|
||||
|
||||
if (S.fsm.emit_token == 0){
|
||||
DrYield(5, 1);
|
||||
S.chunk_pos += size;
|
||||
DrYield(5, LexNeedChunk);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
--S.pos;
|
||||
|
||||
|
||||
S.token.type = CPP_TOKEN_INTEGER_CONSTANT;
|
||||
S.token.flags = 0;
|
||||
break;
|
||||
|
||||
|
||||
case LS_float:
|
||||
case LS_crazy_float0:
|
||||
case LS_crazy_float1:
|
||||
|
@ -634,27 +619,27 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_char:
|
||||
S.token.type = CPP_TOKEN_CHARACTER_CONSTANT;
|
||||
S.token.flags = 0;
|
||||
break;
|
||||
|
||||
|
||||
case LS_char_multiline:
|
||||
S.token.type = CPP_TOKEN_CHARACTER_CONSTANT;
|
||||
S.token.flags = CPP_TFLAG_MULTILINE;
|
||||
break;
|
||||
|
||||
|
||||
case LS_string:
|
||||
S.token.type = CPP_TOKEN_STRING_CONSTANT;
|
||||
S.token.flags = 0;
|
||||
break;
|
||||
|
||||
|
||||
case LS_string_multiline:
|
||||
S.token.type = CPP_TOKEN_STRING_CONSTANT;
|
||||
S.token.flags = CPP_TFLAG_MULTILINE;
|
||||
break;
|
||||
|
||||
|
||||
case LS_comment_pre:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -665,19 +650,19 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_comment: case LS_comment_block_ending:
|
||||
S.token.type = CPP_TOKEN_COMMENT;
|
||||
S.token.flags = 0;
|
||||
pos_update_rule = PUR_unget_whitespace;
|
||||
break;
|
||||
|
||||
|
||||
case LS_error_message:
|
||||
S.token.type = CPP_TOKEN_ERROR_MESSAGE;
|
||||
S.token.flags = 0;
|
||||
pos_update_rule = PUR_unget_whitespace;
|
||||
break;
|
||||
|
||||
|
||||
case LS_dot:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -688,21 +673,21 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_ellipsis:
|
||||
switch (c){
|
||||
case '.':
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
S.token.type = CPP_TOKEN_ELLIPSIS;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
S.token.type = CPP_TOKEN_JUNK;
|
||||
pos_update_rule = PUR_back_one;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_less:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -713,7 +698,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_less_less:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -724,7 +709,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_more:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -735,7 +720,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_more_more:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -746,7 +731,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_minus:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -758,7 +743,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_arrow:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -769,7 +754,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_and:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -781,7 +766,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_or:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -793,7 +778,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_plus:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -805,7 +790,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_colon:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -816,7 +801,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_star:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -827,7 +812,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_modulo:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -838,7 +823,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_caret:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -849,7 +834,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_eq:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -860,7 +845,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LS_bang:
|
||||
S.token.flags = CPP_TFLAG_IS_OPERATOR;
|
||||
switch (c){
|
||||
|
@ -872,12 +857,12 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch (pos_update_rule){
|
||||
case PUR_back_one:
|
||||
--S.pos;
|
||||
break;
|
||||
|
||||
|
||||
case PUR_unget_whitespace:
|
||||
c = chunk[--S.pos];
|
||||
while (c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\v' || c == '\f'){
|
||||
|
@ -886,7 +871,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
++S.pos;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ((S.token.flags & CPP_TFLAG_PP_DIRECTIVE) == 0){
|
||||
switch (S.pp_state){
|
||||
case LSPP_include:
|
||||
|
@ -895,7 +880,7 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
}
|
||||
S.pp_state = LSPP_junk;
|
||||
break;
|
||||
|
||||
|
||||
case LSPP_macro_identifier:
|
||||
if (S.fsm.state != LS_identifier){
|
||||
S.token.type = CPP_TOKEN_JUNK;
|
||||
|
@ -905,14 +890,14 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.pp_state = LSPP_body;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LSPP_identifier:
|
||||
if (S.fsm.state != LS_identifier){
|
||||
S.token.type = CPP_TOKEN_JUNK;
|
||||
}
|
||||
S.pp_state = LSPP_junk;
|
||||
break;
|
||||
|
||||
|
||||
case LSPP_number:
|
||||
if (S.token.type != CPP_TOKEN_INTEGER_CONSTANT){
|
||||
S.token.type = CPP_TOKEN_JUNK;
|
||||
|
@ -922,14 +907,14 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
S.pp_state = LSPP_include;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LSPP_junk:
|
||||
S.token.type = CPP_TOKEN_JUNK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (S.fsm.emit_token){
|
||||
S.token.start = S.token_start;
|
||||
if (S.pos_overide){
|
||||
|
@ -944,9 +929,9 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
}
|
||||
S.token.state_flags = S.pp_state;
|
||||
|
||||
cpp_push_token_nonalloc(out_tokens, &token_i, S.token);
|
||||
token_i = cpp_place_token_nonalloc(out_tokens, token_i, S.token);
|
||||
if (token_i == max_token_i){
|
||||
DrYield(2, 2);
|
||||
DrYield(2, LexNeedTokenMemory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -957,13 +942,199 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
|||
}
|
||||
}
|
||||
|
||||
DrReturn(0);
|
||||
DrReturn(LexFinished);
|
||||
}
|
||||
|
||||
#undef DrYield
|
||||
#undef DrReturn
|
||||
#undef DrCase
|
||||
|
||||
lexer_link int
|
||||
cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size,
|
||||
Cpp_Token_Stack *token_stack_out, int max_tokens){
|
||||
Cpp_Token_Stack temp_stack = *token_stack_out;
|
||||
if (temp_stack.max_count > temp_stack.count + max_tokens){
|
||||
temp_stack.max_count = temp_stack.count + max_tokens;
|
||||
}
|
||||
|
||||
int result = cpp_lex_nonalloc(S_ptr, chunk, size, &temp_stack);
|
||||
|
||||
token_stack_out->count = temp_stack.count;
|
||||
|
||||
if (result == LexNeedTokenMemory){
|
||||
if (token_stack_out->count < token_stack_out->max_count){
|
||||
result = LexHitTokenLimit;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
lexer_link int
|
||||
cpp_lex_size_nonalloc(Lex_Data *S_ptr, char *chunk, int size, int full_size,
|
||||
Cpp_Token_Stack *token_stack_out){
|
||||
int result = 0;
|
||||
if (S_ptr->pos >= full_size){
|
||||
char end_null = 0;
|
||||
result = cpp_lex_nonalloc(S_ptr, &end_null, 1, token_stack_out);
|
||||
}
|
||||
else{
|
||||
result = cpp_lex_nonalloc(S_ptr, chunk, size, token_stack_out);
|
||||
if (result == LexNeedChunk){
|
||||
if (S_ptr->pos >= full_size){
|
||||
char end_null = 0;
|
||||
result = cpp_lex_nonalloc(S_ptr, &end_null, 1, token_stack_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
lexer_link int
|
||||
cpp_lex_size_nonalloc(Lex_Data *S_ptr, char *chunk, int size, int full_size,
|
||||
Cpp_Token_Stack *token_stack_out, int max_tokens){
|
||||
Cpp_Token_Stack temp_stack = *token_stack_out;
|
||||
if (temp_stack.max_count > temp_stack.count + max_tokens){
|
||||
temp_stack.max_count = temp_stack.count + max_tokens;
|
||||
}
|
||||
|
||||
int result = cpp_lex_size_nonalloc(S_ptr, chunk, size, full_size,
|
||||
&temp_stack);
|
||||
|
||||
token_stack_out->count = temp_stack.count;
|
||||
|
||||
if (result == LexNeedTokenMemory){
|
||||
if (token_stack_out->count < token_stack_out->max_count){
|
||||
result = LexHitTokenLimit;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
#if 0
|
||||
lexer_link Cpp_Relex_State
|
||||
cpp_relex_nonalloc_start(Cpp_File file, Cpp_Token_Stack *stack,
|
||||
int start, int end, int amount, int tolerance){
|
||||
Cpp_Relex_State state;
|
||||
state.file = file;
|
||||
state.stack = stack;
|
||||
state.start = start;
|
||||
state.end = end;
|
||||
state.amount = amount;
|
||||
state.tolerance = tolerance;
|
||||
|
||||
Cpp_Get_Token_Result result = new_lex::cpp_get_token(stack, start);
|
||||
if (result.token_index <= 0){
|
||||
state.start_token_i = 0;
|
||||
}
|
||||
else{
|
||||
state.start_token_i = result.token_index-1;
|
||||
}
|
||||
|
||||
result = new_lex::cpp_get_token(stack, end);
|
||||
if (result.token_index < 0) result.token_index = 0;
|
||||
else if (end > stack->tokens[result.token_index].start) ++result.token_index;
|
||||
state.end_token_i = result.token_index;
|
||||
|
||||
state.relex_start = stack->tokens[state.start_token_i].start;
|
||||
if (start < state.relex_start) state.relex_start = start;
|
||||
|
||||
state.space_request = state.end_token_i - state.start_token_i + tolerance + 1;
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
// TODO(allen): Eliminate this once we actually store the EOF token
|
||||
// in the token stack.
|
||||
inline Cpp_Token
|
||||
cpp__get_token(Cpp_Token_Stack *stack, Cpp_Token *tokens, int size, int index){
|
||||
Cpp_Token result;
|
||||
if (index < stack->count){
|
||||
result = tokens[index];
|
||||
}
|
||||
else{
|
||||
result.start = size;
|
||||
result.size = 0;
|
||||
result.type = CPP_TOKEN_EOF;
|
||||
result.flags = 0;
|
||||
result.state_flags = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FCPP_LINK bool
|
||||
cpp_relex_nonalloc_main(Cpp_Relex_State *state, Cpp_Token_Stack *relex_stack, int *relex_end){
|
||||
Cpp_Token_Stack *stack = state->stack;
|
||||
Cpp_Token *tokens = stack->tokens;
|
||||
|
||||
new_lex::cpp_shift_token_starts(stack, state->end_token_i, state->amount);
|
||||
|
||||
Lex_Data lex = {};
|
||||
lex.pp_state = cpp_token_get_pp_state(tokens[state->start_token_i].state_flags);
|
||||
lex.pos = state->relex_start;
|
||||
|
||||
int relex_end_i = state->end_token_i;
|
||||
Cpp_Token match_token = cpp__get_token(stack, tokens, state->file.size, relex_end_i);
|
||||
Cpp_Token end_token = match_token;
|
||||
bool went_too_far = 0;
|
||||
|
||||
for (;;){
|
||||
Cpp_Read_Result read = cpp_lex_step(state->file, &lex);
|
||||
if (read.has_result){
|
||||
if (read.token.start == end_token.start &&
|
||||
read.token.size == end_token.size &&
|
||||
read.token.flags == end_token.flags &&
|
||||
read.token.state_flags == end_token.state_flags){
|
||||
break;
|
||||
}
|
||||
cpp_push_token_nonalloc(relex_stack, read.token);
|
||||
|
||||
while (lex.pos > end_token.start && relex_end_i < stack->count){
|
||||
++relex_end_i;
|
||||
end_token = cpp__get_token(stack, tokens, state->file.size, relex_end_i);
|
||||
}
|
||||
if (relex_stack->count == relex_stack->max_count){
|
||||
went_too_far = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lex.pos >= state->file.size) break;
|
||||
}
|
||||
|
||||
if (!went_too_far){
|
||||
if (relex_stack->count > 0){
|
||||
if (state->start_token_i > 0){
|
||||
Cpp_Token_Merge merge =
|
||||
cpp_attempt_token_merge(tokens[state->start_token_i - 1],
|
||||
relex_stack->tokens[0]);
|
||||
if (merge.did_merge){
|
||||
--state->start_token_i;
|
||||
relex_stack->tokens[0] = merge.new_token;
|
||||
}
|
||||
}
|
||||
|
||||
if (relex_end_i < state->stack->count){
|
||||
Cpp_Token_Merge merge =
|
||||
cpp_attempt_token_merge(relex_stack->tokens[relex_stack->count-1],
|
||||
tokens[relex_end_i]);
|
||||
if (merge.did_merge){
|
||||
++relex_end_i;
|
||||
relex_stack->tokens[relex_stack->count-1] = merge.new_token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*relex_end = relex_end_i;
|
||||
}
|
||||
else{
|
||||
cpp_shift_token_starts(stack, state->end_token_i, -state->amount);
|
||||
}
|
||||
|
||||
return went_too_far;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// TODO(allen): In what corner cases, such as invalid files
|
||||
// does the new lexer suffer???
|
||||
|
||||
// TOP
|
||||
|
||||
#include "../4ed_meta.h"
|
||||
|
@ -204,104 +207,166 @@ end_t(Times *t){
|
|||
}
|
||||
|
||||
static void
|
||||
run_experiment(Experiment *exp, char *filename, int verbose, int chunks){
|
||||
run_experiment(Experiment *exp, char *filename, int verbose,
|
||||
int chunks, int max_tokens){
|
||||
String extension = {};
|
||||
Data file_data;
|
||||
Cpp_File file_cpp;
|
||||
new_lex::Lex_Data ld = {0};
|
||||
int pass;
|
||||
int k, chunk_size, is_last;
|
||||
|
||||
|
||||
extension = file_extension(make_string_slowly(filename));
|
||||
|
||||
|
||||
if (match(extension, "cpp") || match(extension, "h")){
|
||||
file_data = dump_file(filename);
|
||||
if (file_data.size < (100 << 10)){
|
||||
pass = 1;
|
||||
if (verbose >= 0) printf("testing on file: %s\n", filename);
|
||||
exp->test_total++;
|
||||
|
||||
|
||||
exp->correct_stack.count = 0;
|
||||
exp->testing_stack.count = 0;
|
||||
|
||||
memset(exp->correct_stack.tokens, TOKEN_ARRAY_SIZE, 0);
|
||||
memset(exp->testing_stack.tokens, TOKEN_ARRAY_SIZE, 0);
|
||||
|
||||
|
||||
memset(exp->correct_stack.tokens, 0, TOKEN_ARRAY_SIZE);
|
||||
memset(exp->testing_stack.tokens, 0, TOKEN_ARRAY_SIZE);
|
||||
|
||||
file_cpp.data = (char*)file_data.data;
|
||||
file_cpp.size = file_data.size;
|
||||
|
||||
|
||||
ld.tb = (char*)malloc(file_data.size + 1);
|
||||
|
||||
|
||||
{
|
||||
i64 start;
|
||||
|
||||
|
||||
start = __rdtsc();
|
||||
cpp_lex_file_nonalloc(file_cpp, &exp->correct_stack, lex_data);
|
||||
time.handcoded += (__rdtsc() - start);
|
||||
|
||||
start = __rdtsc();
|
||||
if (chunks){
|
||||
int relevant_size = file_data.size + 1;
|
||||
is_last = 0;
|
||||
for (k = 0; k < relevant_size; k += chunks){
|
||||
chunk_size = chunks;
|
||||
if (chunk_size + k >= relevant_size){
|
||||
chunk_size = relevant_size - k;
|
||||
is_last = 1;
|
||||
|
||||
if (max_tokens == 0){
|
||||
if (chunks){
|
||||
start = __rdtsc();
|
||||
int relevant_size = file_data.size + 1;
|
||||
is_last = 0;
|
||||
for (k = 0; k < relevant_size; k += chunks){
|
||||
chunk_size = chunks;
|
||||
if (chunk_size + k >= relevant_size){
|
||||
chunk_size = relevant_size - k;
|
||||
is_last = 1;
|
||||
}
|
||||
|
||||
int result =
|
||||
new_lex::cpp_lex_nonalloc(&ld,
|
||||
(char*)file_data.data + k, chunk_size,
|
||||
&exp->testing_stack);
|
||||
|
||||
if (result == new_lex::LexFinished ||
|
||||
result == new_lex::LexNeedTokenMemory) break;
|
||||
}
|
||||
|
||||
int result = new_lex::cpp_lex_nonalloc(&ld, (char*)file_data.data + k, chunk_size, &exp->testing_stack);
|
||||
if (result == 0 || result == 2) break;
|
||||
time.fsm += (__rdtsc() - start);
|
||||
}
|
||||
else{
|
||||
start = __rdtsc();
|
||||
new_lex::cpp_lex_nonalloc(&ld,
|
||||
(char*)file_data.data, file_data.size,
|
||||
&exp->testing_stack);
|
||||
time.fsm += (__rdtsc() - start);
|
||||
}
|
||||
}
|
||||
else{
|
||||
new_lex::cpp_lex_nonalloc(&ld, (char*)file_data.data, file_data.size, &exp->testing_stack);
|
||||
if (chunks){
|
||||
start = __rdtsc();
|
||||
int relevant_size = file_data.size + 1;
|
||||
is_last = 0;
|
||||
for (k = 0; k < relevant_size; k += chunks){
|
||||
chunk_size = chunks;
|
||||
if (chunk_size + k >= relevant_size){
|
||||
chunk_size = relevant_size - k;
|
||||
is_last = 1;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
int still_lexing = 1;
|
||||
do{
|
||||
result =
|
||||
new_lex::cpp_lex_size_nonalloc(&ld,
|
||||
(char*)file_data.data + k, chunk_size, file_data.size,
|
||||
&exp->testing_stack,
|
||||
max_tokens);
|
||||
if (result == new_lex::LexFinished ||
|
||||
result == new_lex::LexNeedTokenMemory ||
|
||||
result == new_lex::LexNeedChunk){
|
||||
still_lexing = 0;
|
||||
}
|
||||
} while(still_lexing);
|
||||
|
||||
|
||||
if (result == new_lex::LexFinished ||
|
||||
result == new_lex::LexNeedTokenMemory) break;
|
||||
}
|
||||
time.fsm += (__rdtsc() - start);
|
||||
}
|
||||
else{
|
||||
start = __rdtsc();
|
||||
int still_lexing = 1;
|
||||
do{
|
||||
int result =
|
||||
new_lex::cpp_lex_size_nonalloc(&ld,
|
||||
(char*)file_data.data, file_data.size, file_data.size,
|
||||
&exp->testing_stack,
|
||||
max_tokens);
|
||||
if (result == new_lex::LexFinished ||
|
||||
result == new_lex::LexNeedTokenMemory){
|
||||
still_lexing = 0;
|
||||
}
|
||||
} while(still_lexing);
|
||||
time.fsm += (__rdtsc() - start);
|
||||
}
|
||||
}
|
||||
time.fsm += (__rdtsc() - start);
|
||||
}
|
||||
|
||||
|
||||
free(ld.tb);
|
||||
|
||||
|
||||
if (exp->correct_stack.count != exp->testing_stack.count){
|
||||
pass = 0;
|
||||
if (verbose >= 0){
|
||||
printf("error: stack size mismatch %d original and %d testing\n",
|
||||
exp->correct_stack.count, exp->testing_stack.count);
|
||||
exp->correct_stack.count, exp->testing_stack.count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int min_count = exp->correct_stack.count;
|
||||
if (min_count > exp->testing_stack.count) min_count = exp->testing_stack.count;
|
||||
|
||||
|
||||
for (int j = 0; j < min_count; ++j){
|
||||
Cpp_Token *correct, *testing;
|
||||
correct = exp->correct_stack.tokens + j;
|
||||
testing = exp->testing_stack.tokens + j;
|
||||
|
||||
|
||||
if (correct->type != testing->type){
|
||||
pass = 0;
|
||||
if (verbose >= 1) printf("type mismatch at token %d\n", j);
|
||||
}
|
||||
|
||||
|
||||
if (correct->start != testing->start || correct->size != testing->size){
|
||||
pass = 0;
|
||||
if (verbose >= 1){
|
||||
printf("token range mismatch at token %d\n"
|
||||
" %d:%d original %d:%d testing\n"
|
||||
" %.*s original %.*s testing\n",
|
||||
j,
|
||||
correct->start, correct->size, testing->start, testing->size,
|
||||
correct->size, file_cpp.data + correct->start,
|
||||
testing->size, file_cpp.data + testing->start);
|
||||
" %d:%d original %d:%d testing\n"
|
||||
" %.*s original %.*s testing\n",
|
||||
j,
|
||||
correct->start, correct->size, testing->start, testing->size,
|
||||
correct->size, file_cpp.data + correct->start,
|
||||
testing->size, file_cpp.data + testing->start);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (correct->flags != testing->flags){
|
||||
pass = 0;
|
||||
if (verbose >= 1) printf("token flag mismatch at token %d\n", j);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pass){
|
||||
exp->passed_total++;
|
||||
if (verbose >= 0) printf("test passed!\n\n");
|
||||
|
@ -310,7 +375,7 @@ run_experiment(Experiment *exp, char *filename, int verbose, int chunks){
|
|||
if (verbose >= 0) printf("test failed, you failed, fix it now!\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(file_data.data);
|
||||
}
|
||||
}
|
||||
|
@ -338,12 +403,13 @@ show_time(Times t, int repeats, char *type){
|
|||
|
||||
int main(){
|
||||
int repeats = 1;
|
||||
int verbose_level = 1;
|
||||
int chunk_start = 0;
|
||||
int chunk_end = 0;
|
||||
int verbose_level = 0;
|
||||
int chunk_start = 32;
|
||||
int chunk_end = 64;
|
||||
#define TEST_FILE "parser_test1.cpp"
|
||||
#define SINGLE_ITEM 1
|
||||
|
||||
#define SINGLE_ITEM 0
|
||||
int token_limit = 2;
|
||||
|
||||
int chunks = (chunk_start > 0 && chunk_start <= chunk_end);
|
||||
int c = 0;
|
||||
|
||||
|
@ -371,14 +437,14 @@ int main(){
|
|||
begin_t(&chunk_exp_t);
|
||||
printf("With chunks of %d\n", chunks);
|
||||
for (c = chunk_start; c <= chunk_end; ++c){
|
||||
run_experiment(&chunk_exp, BASE_DIR TEST_FILE, 1, c);
|
||||
run_experiment(&chunk_exp, BASE_DIR TEST_FILE, 1, c, token_limit);
|
||||
}
|
||||
end_t(&chunk_exp_t);
|
||||
}
|
||||
|
||||
begin_t(&exp_t);
|
||||
printf("Unchunked\n");
|
||||
run_experiment(&exp, BASE_DIR TEST_FILE, 1, 0);
|
||||
run_experiment(&exp, BASE_DIR TEST_FILE, 1, 0, token_limit);
|
||||
end_t(&exp_t);
|
||||
|
||||
#else
|
||||
|
@ -391,19 +457,19 @@ int main(){
|
|||
if (chunks){
|
||||
begin_t(&chunk_exp_t);
|
||||
for (c = chunk_start; c <= chunk_end; ++c){
|
||||
run_experiment(&chunk_exp, all_files.infos[i].filename.str, verbose_level, c);
|
||||
run_experiment(&chunk_exp, all_files.infos[i].filename.str, verbose_level, c, token_limit);
|
||||
}
|
||||
end_t(&chunk_exp_t);
|
||||
}
|
||||
|
||||
|
||||
begin_t(&exp_t);
|
||||
if (verbose_level == -1 && chunks){
|
||||
for (c = chunk_start; c <= chunk_end; ++c){
|
||||
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0);
|
||||
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0, token_limit);
|
||||
}
|
||||
}
|
||||
else{
|
||||
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0);
|
||||
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0, token_limit);
|
||||
}
|
||||
end_t(&exp_t);
|
||||
}
|
||||
|
|
|
@ -576,97 +576,6 @@ process_match_node(String_And_Flag *input, Match_Node *node, Match_Tree *tree, F
|
|||
}
|
||||
}
|
||||
|
||||
FSM_Stack
|
||||
generate_keyword_fsms(){
|
||||
Terminal_Lookup_Table terminal_table;
|
||||
Cpp_Token_Type type;
|
||||
|
||||
Future_FSM_Stack unfinished_futures;
|
||||
Match_Tree_Stack tree_stack;
|
||||
FSM_Stack fsm_stack;
|
||||
Match_Tree *tree;
|
||||
FSM *fsm;
|
||||
Future_FSM *future;
|
||||
Match_Node *root_node;
|
||||
FSM_State *root_state;
|
||||
int i, j;
|
||||
|
||||
memset(terminal_table.type_to_state, 0, sizeof(terminal_table.type_to_state));
|
||||
memset(terminal_table.state_to_type, 0, sizeof(terminal_table.state_to_type));
|
||||
|
||||
for (i = 0; i < ArrayCount(keyword_strings); ++i){
|
||||
type = (Cpp_Token_Type)keyword_strings[i].flags;
|
||||
if (terminal_table.type_to_state[type] == 0){
|
||||
terminal_table.type_to_state[type] = terminal_table.state_count;
|
||||
terminal_table.state_to_type[terminal_table.state_count] = type;
|
||||
++terminal_table.state_count;
|
||||
}
|
||||
}
|
||||
|
||||
fsm_stack.max = 255;
|
||||
fsm_stack.count = 0;
|
||||
fsm_stack.fsms = (FSM*)malloc(sizeof(FSM)*fsm_stack.max);
|
||||
fsm_stack.table_transition_state = 26;
|
||||
|
||||
tree_stack.max = 255;
|
||||
tree_stack.count = 0;
|
||||
tree_stack.trees = (Match_Tree*)malloc(sizeof(Match_Tree)*tree_stack.max);
|
||||
|
||||
unfinished_futures.max = 255;
|
||||
unfinished_futures.count = 0;
|
||||
unfinished_futures.futures = (Future_FSM*)malloc(sizeof(Future_FSM)*unfinished_futures.max);
|
||||
|
||||
fsm = get_fsm(&fsm_stack);
|
||||
tree = get_tree(&tree_stack);
|
||||
|
||||
*fsm = fsm_init(200, fsm_stack.table_transition_state);
|
||||
*tree = tree_init(200);
|
||||
|
||||
root_state = fsm_get_state(fsm, RealTerminateBase);
|
||||
root_node = match_get_node(tree);
|
||||
match_init_node(root_node, ArrayCount(keyword_strings));
|
||||
for (i = 0; i < ArrayCount(keyword_strings); ++i){
|
||||
root_node->words[i] = i;
|
||||
}
|
||||
|
||||
root_node->count = ArrayCount(keyword_strings);
|
||||
root_node->state = root_state;
|
||||
root_node->index = -1;
|
||||
|
||||
push_future_fsm(&unfinished_futures, root_node);
|
||||
process_match_node(keyword_strings, root_node, tree, fsm, &terminal_table, 2, &unfinished_futures);
|
||||
|
||||
for (i = 1; i < unfinished_futures.count; ++i){
|
||||
future = unfinished_futures.futures + i;
|
||||
|
||||
fsm = get_fsm(&fsm_stack);
|
||||
tree = get_tree(&tree_stack);
|
||||
|
||||
assert((int)(fsm - fsm_stack.fsms) == i);
|
||||
|
||||
*fsm = fsm_init(200, fsm_stack.table_transition_state);
|
||||
*tree = tree_init(200);
|
||||
|
||||
root_state = fsm_get_state(fsm, RealTerminateBase);
|
||||
root_node = match_get_node(tree);
|
||||
match_copy_init_node(root_node, future->source);
|
||||
root_node->state = root_state;
|
||||
|
||||
for (j = 0; j < root_node->count; ++j){
|
||||
char space[1024];
|
||||
sprintf(space, "%s\n", keyword_strings[root_node->words[j]].str);
|
||||
fsm_add_comment(fsm, space);
|
||||
}
|
||||
|
||||
process_match_node(keyword_strings, root_node, tree, fsm, &terminal_table, 12, &unfinished_futures);
|
||||
}
|
||||
|
||||
assert(fsm_stack.count < 255);
|
||||
fsm_stack.final_state = fsm_stack.table_transition_state + (unsigned char)fsm_stack.count;
|
||||
|
||||
return(fsm_stack);
|
||||
}
|
||||
|
||||
Whitespace_FSM
|
||||
whitespace_skip_fsm(Whitespace_FSM wfsm, char c){
|
||||
if (wfsm.pp_state != LSPP_default){
|
||||
|
@ -781,7 +690,6 @@ main_fsm(Lex_FSM fsm, unsigned char pp_state, unsigned char c){
|
|||
case LS_default:
|
||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'){
|
||||
fsm.state = LS_identifier;
|
||||
fsm.emit_token = 1;
|
||||
}
|
||||
else if (c >= '1' && c <= '9'){
|
||||
fsm.state = LS_number;
|
||||
|
@ -849,13 +757,11 @@ main_fsm(Lex_FSM fsm, unsigned char pp_state, unsigned char c){
|
|||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case LS_identifier:
|
||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')){
|
||||
fsm.emit_token = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LS_pound:
|
||||
switch (c){
|
||||
|
@ -1405,39 +1311,6 @@ main(){
|
|||
render_variable(file, "unsigned char", "LSDIR_count", pp_directive_fsm.count);
|
||||
render_variable(file, "unsigned char", "pp_directive_terminal_base", pp_directive_fsm.terminal_base);
|
||||
|
||||
FSM_Stack keyword_fsms = generate_keyword_fsms();
|
||||
|
||||
char name[1024];
|
||||
for (int i = 0; i < keyword_fsms.count; ++i){
|
||||
FSM_Tables partial_keywords_table =
|
||||
generate_table_from_abstract_fsm(keyword_fsms.fsms[i], keyword_fsms.final_state);
|
||||
if (keyword_fsms.fsms[i].comment){
|
||||
render_comment(file, keyword_fsms.fsms[i].comment);
|
||||
}
|
||||
|
||||
sprintf(name, "keyword_part_%d_table", i);
|
||||
render_fsm_table(file, partial_keywords_table, name);
|
||||
}
|
||||
|
||||
begin_ptr_table(file, "short", "key_eq_class_tables");
|
||||
for (int i = 0; i < keyword_fsms.count; ++i){
|
||||
sprintf(name, "keyword_part_%d_table_eq_classes", i);
|
||||
do_table_item_direct(file, name, "");
|
||||
end_row(file);
|
||||
}
|
||||
end_table(file);
|
||||
|
||||
begin_ptr_table(file, "char", "key_tables");
|
||||
for (int i = 0; i < keyword_fsms.count; ++i){
|
||||
sprintf(name, "keyword_part_%d_table_table", i);
|
||||
do_table_item_direct(file, name, "");
|
||||
end_row(file);
|
||||
}
|
||||
end_table(file);
|
||||
|
||||
fprintf(file, "#define LSKEY_table_transition %d\n", (int)(keyword_fsms.table_transition_state));
|
||||
fprintf(file, "#define LSKEY_totally_finished %d\n", (int)(keyword_fsms.final_state));
|
||||
|
||||
fclose(file);
|
||||
return(0);
|
||||
}
|
||||
|
|
1693
win32_4ed.cpp
1693
win32_4ed.cpp
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 12.12.2014
|
||||
*
|
||||
* Win32 font rendering for nicer fonts
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
internal i32
|
||||
win32_draw_font_load(Partition *part,
|
||||
Render_Font *font_out,
|
||||
char *filename_untranslated,
|
||||
i32 pt_size,
|
||||
i32 tab_width,
|
||||
i32 oversample,
|
||||
b32 store_texture){
|
||||
|
||||
char space_[1024];
|
||||
String filename = make_fixed_width_string(space_);
|
||||
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
|
||||
if (!translate_success) return 0;
|
||||
|
||||
i32 result = 0;
|
||||
|
||||
AddFontResourceEx(filename.str, FR_PRIVATE, 0);
|
||||
|
||||
HFONT font_handle =
|
||||
CreateFontA(pt_size, 0, 0, 0,
|
||||
FW_NORMAL, // WEIGHT
|
||||
FALSE, // ITALICS
|
||||
FALSE, // UNDERLINE
|
||||
FALSE, // STRIKE-OUT
|
||||
ANSI_CHARSET,
|
||||
OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS,
|
||||
ANTIALIASED_QUALITY,
|
||||
DEFAULT_PITCH|FF_DONTCARE,
|
||||
filename.str);
|
||||
|
||||
if (font_handle){
|
||||
HDC dc = CreateCompatibleDC(0);
|
||||
|
||||
if (dc){
|
||||
// TODO(allen): Have to get metrics
|
||||
|
||||
result = 1;
|
||||
|
||||
if (store_texture){
|
||||
i32 tex_width = pt_size*16*oversample;
|
||||
i32 tex_height = pt_size*16*oversample;
|
||||
|
||||
HBITAMP bitmap = CreateCompatibleBitmap(dc, tex_width, tex_height);
|
||||
|
||||
// TODO(allen): pack each glyph into a texture
|
||||
// and generate the equivalent data output by stb
|
||||
// in the stbtt_packedchar array.
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DeleteObject(font_handle);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
Loading…
Reference in New Issue