Allen Webster 2016-06-03 20:28:03 -04:00
commit 9b4f29d4a7
46 changed files with 5178 additions and 5968 deletions

View File

@ -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(){

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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:;
}
}

View File

@ -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){

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

1580
4ed.cpp

File diff suppressed because it is too large Load Diff

28
4ed.h
View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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__)

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}
/*

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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>

View File

@ -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);

View File

@ -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!

View File

@ -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!

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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=

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

72
win32_font.cpp Normal file
View File

@ -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