pre-insofaras-patch-1

This commit is contained in:
Allen Webster 2016-02-21 12:44:23 -05:00
parent c8db4004a6
commit 762e31bed0
9 changed files with 1242 additions and 1226 deletions

View File

@ -139,7 +139,7 @@ CUSTOM_COMMAND_SIG(build_search){
// Step 3: If the batch file did not exist try to move to the parent directory using
// app->directory_cd. The cd function can also be used to navigate to subdirectories.
// It returns true if it can actually move in the specified direction, and false otherwise.
int keep_going = 1;
String dir = push_directory(app, cmd_context);
while (keep_going){
@ -147,7 +147,7 @@ CUSTOM_COMMAND_SIG(build_search){
push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 0);
push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*"));
push_parameter(app, cmd_context, par_cli_path, dir.str, dir.size);
if (append(&dir, "build")){
app->push_parameter(cmd_context,
dynamic_int(par_cli_command),
@ -157,7 +157,7 @@ CUSTOM_COMMAND_SIG(build_search){
else{
clear_parameters(cmd_context);
}
return;
}

View File

@ -3038,7 +3038,7 @@ App_Step_Sig(app_step){
// NOTE(allen): OS clipboard event handling
if (clipboard.str){
String *dest = working_set_next_clipboard_string(&vars->mem.general, &vars->working_set, clipboard.size);
copy(dest, make_string((char*)clipboard.str, clipboard.size));
dest->size = eol_convert_in(dest->str, clipboard.str, clipboard.size);
}
// TODO(allen): profile this make sure it's not costing me too much power.

10
4ed.h
View File

@ -84,12 +84,6 @@ struct Input_Summary{
Key_Codes *codes;
};
// TODO(allen): This can go, and we can just use a String for it.
struct Clipboard_Contents{
u8 *str;
i32 size;
};
struct Command_Line_Parameters{
char **argv;
int argc;
@ -122,7 +116,7 @@ typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
Application_Memory *memory, \
Exchange *exchange, \
Key_Codes *codes, \
Clipboard_Contents clipboard, \
String clipboard, \
String current_directory, \
Custom_API api)
@ -152,7 +146,7 @@ struct Application_Step_Result{
Render_Target *target, \
Application_Memory *memory, \
Exchange *exchange, \
Clipboard_Contents clipboard, \
String clipboard, \
b32 time_step, b32 first_step, b32 force_redraw, \
Application_Step_Result *result)

View File

@ -40,6 +40,8 @@
#include "4ed_command.cpp"
#include "4ed_layout.cpp"
#include "4ed_style.cpp"
#include "4ed_file.cpp"
#include "4ed_gui.cpp"
#include "4ed_file_view.cpp"
#include "4ed_color_view.cpp"
#include "4ed_interactive_view.cpp"

376
4ed_file.cpp Normal file
View File

@ -0,0 +1,376 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 20.02.2016
*
* File editing view for 4coder
*
*/
// TOP
#include "buffer/4coder_shared.cpp"
#if BUFFER_EXPERIMENT_SCALPEL == 0
#include "buffer/4coder_golden_array.cpp"
#define Buffer_Type Buffer
#elif BUFFER_EXPERIMENT_SCALPEL == 1
#include "buffer/4coder_gap_buffer.cpp"
#define Buffer_Type Gap_Buffer
#elif BUFFER_EXPERIMENT_SCALPEL == 2
#include "buffer/4coder_multi_gap_buffer.cpp"
#define Buffer_Type Multi_Gap_Buffer
#else
#include "buffer/4coder_rope_buffer.cpp"
#define Buffer_Type Rope_Buffer
#endif
#include "buffer/4coder_buffer_abstract.cpp"
enum Edit_Type{
ED_NORMAL,
ED_REVERSE_NORMAL,
ED_UNDO,
ED_REDO,
};
struct Edit_Step{
Edit_Type type;
union{
struct{
b32 can_merge;
Buffer_Edit edit;
i32 pre_pos;
i32 post_pos;
i32 next_block, prev_block;
};
struct{
i32 first_child;
i32 inverse_first_child;
i32 inverse_child_count;
i32 special_type;
};
};
i32 child_count;
};
struct Edit_Stack{
u8 *strings;
i32 size, max;
Edit_Step *edits;
i32 edit_count, edit_max;
};
struct Small_Edit_Stack{
u8 *strings;
i32 size, max;
Buffer_Edit *edits;
i32 edit_count, edit_max;
};
struct Undo_Data{
Edit_Stack undo;
Edit_Stack redo;
Edit_Stack history;
Small_Edit_Stack children;
i32 history_block_count, history_head_block;
i32 edit_history_cursor;
b32 current_block_normal;
};
struct Text_Effect{
i32 start, end;
u32 color;
i32 tick_down, tick_max;
};
// NOTE(allen): The Editing_File struct is now divided into two
// parts. Variables in the Settings part can be set even when the
// file is still streaming in, and all operations except for the
// initial allocation of the file.
struct Editing_File_Settings{
Font_Set *set;
i32 base_map_id;
i32 dos_write_mode;
b32 unwrapped_lines;
b8 tokens_exist;
b8 super_locked;
b8 is_initialized;
b8 unimportant;
};
// 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;
i32 cursor_pos;
Undo_Data undo;
Cpp_Token_Stack token_stack;
Cpp_Token_Stack swap_stack;
u32 lex_job;
b32 tokens_complete;
b32 still_lexing;
Text_Effect paste_effect;
u64 last_4ed_write_time;
u64 last_4ed_edit_time;
u64 last_sys_write_time;
};
struct Editing_File_Preload{
i32 start_line;
};
struct Editing_File_Name{
char live_name_[256];
String live_name;
char source_path_[256];
char extension_[16];
String source_path;
String extension;
};
struct Editing_File{
Editing_File_Settings settings;
union{
Editing_File_State state;
Editing_File_Preload preload;
};
Editing_File_Name name;
};
struct File_Table_Entry{
String name;
u32 hash;
i32 id;
};
struct File_Table{
File_Table_Entry *table;
i32 count, max;
};
internal u32
get_file_hash(String name){
u32 x = 5381;
int i = 0;
char c;
while (i < name.size){
c = name.str[i++];
x = ((x << 5) + x) + c;
}
return x;
}
internal b32
table_add(File_Table *table, String name, i32 id){
Assert(table->count * 3 < table->max * 2);
File_Table_Entry entry, e;
i32 i;
entry.name = name;
entry.id = id;
entry.hash = get_file_hash(name);
i = entry.hash % table->max;
while ((e = table->table[i]).name.str){
if (e.hash == entry.hash && match(e.name, entry.name)){
return 1;
}
i = (i + 1) % table->max;
}
table->table[i] = entry;
++table->count;
return 0;
}
internal bool32
table_find_pos(File_Table *table, String name, i32 *index){
File_Table_Entry e;
i32 i;
u32 hash;
hash = get_file_hash(name);
i = hash % table->max;
while ((e = table->table[i]).name.size){
if (e.name.str && e.hash == hash && match(e.name, name)){
*index = i;
return 1;
}
i = (i + 1) % table->max;
}
return 0;
}
inline b32
table_find(File_Table *table, String name, i32 *id){
i32 pos;
b32 r = table_find_pos(table, name, &pos);
if (r) *id = table->table[pos].id;
return r;
}
inline b32
table_remove(File_Table *table, String name){
i32 pos;
b32 r = table_find_pos(table, name, &pos);
if (r){
table->table[pos].name.str = 0;
--table->count;
}
return r;
}
struct Working_Set{
Editing_File *files;
i32 file_index_count, file_max_count;
File_Table table;
String clipboards[64];
i32 clipboard_size, clipboard_max_size;
i32 clipboard_current, clipboard_rolling;
};
// Hot Directory
struct Hot_Directory{
String string;
File_List file_list;
};
internal void
hot_directory_init(Hot_Directory *hot_directory, String base, String dir){
hot_directory->string = base;
hot_directory->string.str[255] = 0;
hot_directory->string.size = 0;
copy(&hot_directory->string, dir);
append(&hot_directory->string, "\\");
}
internal void
hot_directory_clean_end(Hot_Directory *hot_directory){
String *str = &hot_directory->string;
if (str->size != 0 && str->str[str->size-1] != '\\'){
str->size = reverse_seek_slash(*str) + 1;
str->str[str->size] = 0;
}
}
internal i32
hot_directory_quick_partition(File_Info *infos, i32 start, i32 pivot){
File_Info *p = infos + pivot;
File_Info *a = infos + start;
for (i32 i = start; i < pivot; ++i, ++a){
i32 comp = 0;
comp = p->folder - a->folder;
if (comp == 0) comp = compare(a->filename, p->filename);
if (comp < 0){
Swap(*a, infos[start]);
++start;
}
}
Swap(*p, infos[start]);
return start;
}
internal void
hot_directory_quick_sort(File_Info *infos, i32 start, i32 pivot){
i32 mid = hot_directory_quick_partition(infos, start, pivot);
if (start < mid-1) hot_directory_quick_sort(infos, start, mid-1);
if (mid+1 < pivot) hot_directory_quick_sort(infos, mid+1, pivot);
}
inline void
hot_directory_fixup(Hot_Directory *hot_directory, Working_Set *working_set){
File_List *files = &hot_directory->file_list;
if (files->count >= 2)
hot_directory_quick_sort(files->infos, 0, files->count - 1);
}
inline void
hot_directory_set(System_Functions *system, Hot_Directory *hot_directory,
String str, Working_Set *working_set){
b32 success = copy_checked(&hot_directory->string, str);
terminate_with_null(&hot_directory->string);
if (success){
system->set_file_list(&hot_directory->file_list, str);
}
hot_directory_fixup(hot_directory, working_set);
}
inline void
hot_directory_reload(System_Functions *system, Hot_Directory *hot_directory, Working_Set *working_set){
system->set_file_list(&hot_directory->file_list, hot_directory->string);
hot_directory_fixup(hot_directory, working_set);
}
struct Hot_Directory_Match{
String filename;
b32 is_folder;
};
internal b32
filename_match(String query, Absolutes *absolutes, String filename, b32 case_sensitive){
b32 result;
result = (query.size == 0);
if (!result) result = wildcard_match(absolutes, filename, case_sensitive);
return result;
}
internal Hot_Directory_Match
hot_directory_first_match(Hot_Directory *hot_directory,
String str,
b32 include_files,
b32 exact_match,
b32 case_sensitive){
Hot_Directory_Match result = {};
Absolutes absolutes;
if (!exact_match)
get_absolutes(str, &absolutes, 1, 1);
File_List *files = &hot_directory->file_list;
File_Info *info, *end;
end = files->infos + files->count;
for (info = files->infos; info != end; ++info){
String filename = info->filename;
b32 is_match = 0;
if (exact_match){
if (case_sensitive){
if (match(filename, str)) is_match = 1;
}
else{
if (match_unsensitive(filename, str)) is_match = 1;
}
}
else{
if (filename_match(str, &absolutes, filename, case_sensitive)) is_match = 1;
}
if (is_match){
result.is_folder = info->folder;
result.filename = filename;
break;
}
}
return result;
}
// BOTTOM

File diff suppressed because it is too large Load Diff

854
4ed_gui.cpp Normal file
View File

@ -0,0 +1,854 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 20.02.2016
*
* GUI system for 4coder
*
*/
// TOP
struct Single_Line_Input_Step{
b8 hit_newline;
b8 hit_ctrl_newline;
b8 hit_a_character;
b8 hit_backspace;
b8 hit_esc;
b8 made_a_change;
b8 did_command;
b8 no_file_match;
};
enum Single_Line_Input_Type{
SINGLE_LINE_STRING,
SINGLE_LINE_FILE
};
struct Single_Line_Mode{
Single_Line_Input_Type type;
String *string;
Hot_Directory *hot_directory;
b32 fast_folder_select;
b32 try_to_match;
b32 case_sensitive;
};
internal Single_Line_Input_Step
app_single_line_input_core(System_Functions *system,
Key_Codes *codes, Working_Set *working_set,
Key_Event_Data key, Single_Line_Mode mode){
Single_Line_Input_Step result = {};
if (key.keycode == codes->back){
result.hit_backspace = 1;
if (mode.string->size > 0){
result.made_a_change = 1;
--mode.string->size;
switch (mode.type){
case SINGLE_LINE_STRING:
mode.string->str[mode.string->size] = 0; break;
case SINGLE_LINE_FILE:
{
char end_character = mode.string->str[mode.string->size];
if (char_is_slash(end_character)){
mode.string->size = reverse_seek_slash(*mode.string) + 1;
mode.string->str[mode.string->size] = 0;
hot_directory_set(system, mode.hot_directory, *mode.string, working_set);
}
else{
mode.string->str[mode.string->size] = 0;
}
}break;
}
}
}
else if (key.character == '\n' || key.character == '\t'){
result.made_a_change = 1;
if (key.modifiers[CONTROL_KEY_CONTROL] ||
key.modifiers[CONTROL_KEY_ALT]){
result.hit_ctrl_newline = 1;
}
else{
result.hit_newline = 1;
if (mode.fast_folder_select){
Hot_Directory_Match match;
char front_name_space[256];
String front_name = make_fixed_width_string(front_name_space);
get_front_of_directory(&front_name, *mode.string);
match =
hot_directory_first_match(mode.hot_directory, front_name, 1, 1, mode.case_sensitive);
if (mode.try_to_match && !match.filename.str){
match = hot_directory_first_match(mode.hot_directory, front_name, 1, 0, mode.case_sensitive);
}
if (match.filename.str){
if (match.is_folder){
set_last_folder(mode.string, match.filename);
hot_directory_set(system, mode.hot_directory, *mode.string, working_set);
result.hit_newline = 0;
}
else{
if (mode.try_to_match){
mode.string->size = reverse_seek_slash(*mode.string) + 1;
append(mode.string, match.filename);
}
}
}
else{
if (mode.try_to_match){
result.no_file_match = 1;
}
}
}
}
}
else if (key.keycode == codes->esc){
result.hit_esc = 1;
result.made_a_change = 1;
}
else if (key.character){
result.hit_a_character = 1;
if (!key.modifiers[CONTROL_KEY_CONTROL] &&
!key.modifiers[CONTROL_KEY_ALT]){
if (mode.string->size+1 < mode.string->memory_size){
u8 new_character = (u8)key.character;
mode.string->str[mode.string->size] = new_character;
mode.string->size++;
mode.string->str[mode.string->size] = 0;
if (mode.type == SINGLE_LINE_FILE && char_is_slash(new_character)){
hot_directory_set(system, mode.hot_directory, *mode.string, working_set);
}
result.made_a_change = 1;
}
}
else{
result.did_command = 1;
result.made_a_change = 1;
}
}
return result;
}
inline Single_Line_Input_Step
app_single_line_input_step(System_Functions *system,
Key_Codes *codes, Key_Event_Data key, String *string){
Single_Line_Mode mode = {};
mode.type = SINGLE_LINE_STRING;
mode.string = string;
return app_single_line_input_core(system, codes, 0, key, mode);
}
inline Single_Line_Input_Step
app_single_file_input_step(System_Functions *system, Key_Codes *codes,
Working_Set *working_set, Key_Event_Data key,
String *string, Hot_Directory *hot_directory,
b32 fast_folder_select, b32 try_to_match, b32 case_sensitive){
Single_Line_Mode mode = {};
mode.type = SINGLE_LINE_FILE;
mode.string = string;
mode.hot_directory = hot_directory;
mode.fast_folder_select = fast_folder_select;
mode.try_to_match = try_to_match;
mode.case_sensitive = case_sensitive;
return app_single_line_input_core(system, codes, working_set, key, mode);
}
inline Single_Line_Input_Step
app_single_number_input_step(System_Functions *system, Key_Codes *codes,
Key_Event_Data key, String *string){
Single_Line_Input_Step result = {};
Single_Line_Mode mode = {};
mode.type = SINGLE_LINE_STRING;
mode.string = string;
char c = (char)key.character;
if (c == 0 || c == '\n' || char_is_numeric(c))
result = app_single_line_input_core(system, codes, 0, key, mode);
return result;
}
struct Widget_ID{
i32 id;
i32 sub_id0;
i32 sub_id1;
i32 sub_id2;
};
inline b32
widget_match(Widget_ID s1, Widget_ID s2){
return (s1.id == s2.id && s1.sub_id0 == s2.sub_id0 &&
s1.sub_id1 == s2.sub_id1 && s1.sub_id2 == s2.sub_id2);
}
struct UI_State{
Render_Target *target;
Style *style;
Font_Set *font_set;
Mouse_Summary *mouse;
Key_Summary *keys;
Key_Codes *codes;
Working_Set *working_set;
i16 font_id;
Widget_ID selected, hover, hot;
b32 activate_me;
b32 redraw;
b32 input_stage;
i32 sub_id1_change;
real32 height, view_y;
};
inline Widget_ID
make_id(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.id = id;
return r;
}
inline Widget_ID
make_sub0(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.sub_id0 = id;
return r;
}
inline Widget_ID
make_sub1(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.sub_id1 = id;
return r;
}
inline Widget_ID
make_sub2(UI_State *state, i32 id){
Widget_ID r = state->selected;
r.sub_id2 = id;
return r;
}
inline b32
is_selected(UI_State *state, Widget_ID id){
return widget_match(state->selected, id);
}
inline b32
is_hot(UI_State *state, Widget_ID id){
return widget_match(state->hot, id);
}
inline b32
is_hover(UI_State *state, Widget_ID id){
return widget_match(state->hover, id);
}
struct UI_Layout{
i32 row_count;
i32 row_item_width;
i32 row_max_item_height;
i32_Rect rect;
i32 x, y;
};
struct UI_Layout_Restore{
UI_Layout layout;
UI_Layout *dest;
};
inline void
begin_layout(UI_Layout *layout, i32_Rect rect){
layout->rect = rect;
layout->x = rect.x0;
layout->y = rect.y0;
layout->row_count = 0;
layout->row_max_item_height = 0;
}
inline void
begin_row(UI_Layout *layout, i32 count){
layout->row_count = count;
layout->row_item_width = (layout->rect.x1 - layout->x) / count;
}
inline i32_Rect
layout_rect(UI_Layout *layout, i32 height){
i32_Rect rect;
rect.x0 = layout->x;
rect.y0 = layout->y;
rect.x1 = rect.x0;
rect.y1 = rect.y0 + height;
if (layout->row_count > 0){
--layout->row_count;
rect.x1 = rect.x0 + layout->row_item_width;
layout->x += layout->row_item_width;
layout->row_max_item_height = Max(height, layout->row_max_item_height);
}
if (layout->row_count == 0){
rect.x1 = layout->rect.x1;
layout->row_max_item_height = Max(height, layout->row_max_item_height);
layout->y += layout->row_max_item_height;
layout->x = layout->rect.x0;
layout->row_max_item_height = 0;
}
return rect;
}
inline UI_Layout_Restore
begin_sub_layout(UI_Layout *layout, i32_Rect area){
UI_Layout_Restore restore;
restore.layout = *layout;
restore.dest = layout;
begin_layout(layout, area);
return restore;
}
inline void
end_sub_layout(UI_Layout_Restore restore){
*restore.dest = restore.layout;
}
struct UI_Style{
u32 dark, dim, bright;
u32 base, pop1, pop2;
};
internal UI_Style
get_ui_style(Style *style){
UI_Style ui_style;
ui_style.dark = style->main.back_color;
ui_style.dim = style->main.margin_color;
ui_style.bright = style->main.margin_active_color;
ui_style.base = style->main.default_color;
ui_style.pop1 = style->main.file_info_style.pop1_color;
ui_style.pop2 = style->main.file_info_style.pop2_color;
return ui_style;
}
internal UI_Style
get_ui_style_upper(Style *style){
UI_Style ui_style;
ui_style.dark = style->main.margin_color;
ui_style.dim = style->main.margin_hover_color;
ui_style.bright = style->main.margin_active_color;
ui_style.base = style->main.default_color;
ui_style.pop1 = style->main.file_info_style.pop1_color;
ui_style.pop2 = style->main.file_info_style.pop2_color;
return ui_style;
}
inline void
get_colors(UI_State *state, u32 *back, u32 *fore, Widget_ID wid, UI_Style style){
bool32 hover = is_hover(state, wid);
bool32 hot = is_hot(state, wid);
i32 level = hot + hover;
switch (level){
case 2:
*back = style.bright;
*fore = style.dark;
break;
case 1:
*back = style.dim;
*fore = style.bright;
break;
case 0:
*back = style.dark;
*fore = style.bright;
break;
}
}
inline void
get_pop_color(UI_State *state, u32 *pop, Widget_ID wid, UI_Style style){
bool32 hover = is_hover(state, wid);
bool32 hot = is_hot(state, wid);
i32 level = hot + hover;
switch (level){
case 2:
*pop = style.pop1;
break;
case 1:
*pop = style.pop1;
break;
case 0:
*pop = style.pop1;
break;
}
}
internal UI_State
ui_state_init(UI_State *state_in, Render_Target *target, Input_Summary *user_input,
Style *style, Font_Set *font_set, Working_Set *working_set, b32 input_stage){
UI_State state = {};
state.target = target;
state.style = style;
state.font_set = font_set;
state.font_id = style->font_id;
state.working_set = working_set;
if (user_input){
state.mouse = &user_input->mouse;
state.keys = &user_input->keys;
state.codes = user_input->codes;
}
state.selected = state_in->selected;
state.hot = state_in->hot;
if (input_stage) state.hover = {};
else state.hover = state_in->hover;
state.redraw = 0;
state.activate_me = 0;
state.input_stage = input_stage;
state.height = state_in->height;
state.view_y = state_in->view_y;
return state;
}
inline bool32
ui_state_match(UI_State a, UI_State b){
return (widget_match(a.selected, b.selected) &&
widget_match(a.hot, b.hot) &&
widget_match(a.hover, b.hover));
}
internal b32
ui_finish_frame(UI_State *persist_state, UI_State *state, UI_Layout *layout, i32_Rect rect,
b32 do_wheel, b32 *did_activation){
b32 result = 0;
f32 h = layout->y + persist_state->view_y - rect.y0;
f32 max_y = h - (rect.y1 - rect.y0);
persist_state->height = h;
persist_state->view_y = state->view_y;
if (state->input_stage){
Mouse_Summary *mouse = state->mouse;
Font_Set *font_set = state->font_set;
if (mouse->wheel_used && do_wheel){
i32 height = get_font_info(font_set, state->font_id)->height;
persist_state->view_y += mouse->wheel_amount*height;
result = 1;
}
if (mouse->release_l && widget_match(state->hot, state->hover)){
if (did_activation) *did_activation = 1;
if (state->activate_me){
state->selected = state->hot;
}
}
if (!mouse->l && !mouse->r){
state->hot = {};
}
if (!ui_state_match(*persist_state, *state) || state->redraw){
result = 1;
}
*persist_state = *state;
}
if (persist_state->view_y >= max_y) persist_state->view_y = max_y;
if (persist_state->view_y < 0) persist_state->view_y = 0;
return result;
}
internal bool32
ui_do_button_input(UI_State *state, i32_Rect rect, Widget_ID id, bool32 activate, bool32 *right = 0){
bool32 result = 0;
Mouse_Summary *mouse = state->mouse;
bool32 hover = hit_check(mouse->mx, mouse->my, rect);
if (hover){
state->hover = id;
if (activate) state->activate_me = 1;
if (mouse->press_l || (mouse->press_r && right)) state->hot = id;
if (mouse->l && mouse->r) state->hot = {};
}
bool32 is_match = is_hot(state, id);
if (mouse->release_l && is_match){
if (hover) result = 1;
state->redraw = 1;
}
if (right && mouse->release_r && is_match){
if (hover) *right = 1;
state->redraw = 1;
}
return result;
}
internal bool32
ui_do_subdivided_button_input(UI_State *state, i32_Rect rect, i32 parts, Widget_ID id, bool32 activate, i32 *indx_out, bool32 *right = 0){
bool32 result = 0;
real32 x0, x1;
i32_Rect sub_rect;
Widget_ID sub_widg = id;
real32 sub_width = (rect.x1 - rect.x0) / (real32)parts;
sub_rect.y0 = rect.y0;
sub_rect.y1 = rect.y1;
x1 = (real32)rect.x0;
for (i32 i = 0; i < parts; ++i){
x0 = x1;
x1 = x1 + sub_width;
sub_rect.x0 = TRUNC32(x0);
sub_rect.x1 = TRUNC32(x1);
sub_widg.sub_id2 = i;
if (ui_do_button_input(state, sub_rect, sub_widg, activate, right)){
*indx_out = i;
break;
}
}
return result;
}
internal real32
ui_do_vscroll_input(UI_State *state, i32_Rect top, i32_Rect bottom, i32_Rect slider,
Widget_ID id, real32 val, real32 step_amount,
real32 smin, real32 smax, real32 vmin, real32 vmax){
Mouse_Summary *mouse = state->mouse;
i32 mx = mouse->mx;
i32 my = mouse->my;
if (hit_check(mx, my, top)){
state->hover = id;
state->hover.sub_id2 = 1;
}
if (hit_check(mx, my, bottom)){
state->hover = id;
state->hover.sub_id2 = 2;
}
if (hit_check(mx, my, slider)){
state->hover = id;
state->hover.sub_id2 = 3;
}
if (mouse->press_l) state->hot = state->hover;
if (id.id == state->hot.id){
if (mouse->release_l){
Widget_ID wid1, wid2;
wid1 = wid2 = id;
wid1.sub_id2 = 1;
wid2.sub_id2 = 2;
if (state->hot.sub_id2 == 1 && is_hover(state, wid1)) val -= step_amount;
if (state->hot.sub_id2 == 2 && is_hover(state, wid2)) val += step_amount;
state->redraw = 1;
}
if (state->hot.sub_id2 == 3){
real32 S, L;
S = (real32)mouse->my - (slider.y1 - slider.y0) / 2;
if (S < smin) S = smin;
if (S > smax) S = smax;
L = unlerp(smin, S, smax);
val = lerp(vmin, L, vmax);
state->redraw = 1;
}
}
return val;
}
internal b32
ui_do_text_field_input(UI_State *state, String *str){
b32 result = 0;
Key_Summary *keys = state->keys;
for (i32 key_i = 0; key_i < keys->count; ++key_i){
Key_Event_Data key = get_single_key(keys, key_i);
char c = (char)key.character;
if (char_is_basic(c) && str->size < str->memory_size-1){
str->str[str->size++] = c;
str->str[str->size] = 0;
}
else if (c == '\n'){
result = 1;
}
else if (key.keycode == state->codes->back && str->size > 0){
str->str[--str->size] = 0;
}
}
return result;
}
internal b32
ui_do_file_field_input(System_Functions *system, UI_State *state,
Hot_Directory *hot_dir, b32 try_to_match, b32 case_sensitive){
Key_Event_Data key;
Single_Line_Input_Step step;
String *str = &hot_dir->string;
Key_Summary *keys = state->keys;
i32 key_i;
b32 result = 0;
terminate_with_null(str);
for (key_i = 0; key_i < keys->count; ++key_i){
key = get_single_key(keys, key_i);
step =
app_single_file_input_step(system, state->codes,
state->working_set, key, str,
hot_dir, 1, try_to_match, case_sensitive);
if ((step.hit_newline || step.hit_ctrl_newline) && !step.no_file_match) result = 1;
}
return result;
}
internal b32
ui_do_line_field_input(System_Functions *system,
UI_State *state, String *string){
b32 result = 0;
Key_Summary *keys = state->keys;
for (i32 key_i = 0; key_i < keys->count; ++key_i){
Key_Event_Data key = get_single_key(keys, key_i);
terminate_with_null(string);
Single_Line_Input_Step step =
app_single_line_input_step(system, state->codes, key, string);
if (step.hit_newline || step.hit_ctrl_newline) result = 1;
}
return result;
}
internal bool32
ui_do_slider_input(UI_State *state, i32_Rect rect, Widget_ID wid,
real32 min, real32 max, real32 *v){
bool32 result = 0;
ui_do_button_input(state, rect, wid, 0);
Mouse_Summary *mouse = state->mouse;
if (is_hot(state, wid)){
result = 1;
*v = unlerp(min, (real32)mouse->mx, max);
state->redraw = 1;
}
return result;
}
internal bool32
do_text_field(Widget_ID wid, UI_State *state, UI_Layout *layout,
String prompt, String dest){
b32 result = 0;
i32 character_h = get_font_info(state->font_set, state->font_id)->height;
i32_Rect rect = layout_rect(layout, character_h);
if (state->input_stage){
ui_do_button_input(state, rect, wid, 1);
if (is_selected(state, wid)){
if (ui_do_text_field_input(state, &dest)){
result = 1;
}
}
}
else{
Render_Target *target = state->target;
UI_Style ui_style = get_ui_style_upper(state->style);
u32 back, fore, prompt_pop;
get_colors(state, &back, &fore, wid, ui_style);
get_pop_color(state, &prompt_pop, wid, ui_style);
draw_rectangle(target, rect, back);
i32 x = rect.x0;
x = draw_string(target, state->font_id, prompt, x, rect.y0, prompt_pop);
draw_string(target, state->font_id, dest, x, rect.y0, ui_style.base);
}
return result;
}
internal b32
do_button(i32 id, UI_State *state, UI_Layout *layout, char *text, i32 height_mult,
b32 is_toggle = 0, b32 on = 0){
b32 result = 0;
i16 font_id = state->style->font_id;
i32 character_h = get_font_info(state->font_set, font_id)->height;
i32_Rect btn_rect = layout_rect(layout, character_h * height_mult);
if (height_mult > 1) btn_rect = get_inner_rect(btn_rect, 2);
else{
btn_rect.x0 += 2;
btn_rect.x1 -= 2;
}
Widget_ID wid = make_id(state, id);
if (state->input_stage){
if (ui_do_button_input(state, btn_rect, wid, 0)){
result = 1;
}
}
else{
Render_Target *target = state->target;
UI_Style ui_style = get_ui_style(state->style);
u32 back, fore, outline;
outline = ui_style.bright;
get_colors(state, &back, &fore, wid, ui_style);
draw_rectangle(target, btn_rect, back);
draw_rectangle_outline(target, btn_rect, outline);
real32 text_width = font_string_width(target, font_id, text);
i32 box_width = btn_rect.x1 - btn_rect.x0;
i32 box_height = btn_rect.y1 - btn_rect.y0;
i32 x_pos = TRUNC32(btn_rect.x0 + (box_width - text_width)*.5f);
draw_string(target, font_id, text, x_pos, btn_rect.y0 + (box_height - character_h) / 2, fore);
if (is_toggle){
i32_Rect on_box = get_inner_rect(btn_rect, character_h/2);
on_box.x1 = on_box.x0 + (on_box.y1 - on_box.y0);
if (on) draw_rectangle(target, on_box, fore);
else draw_rectangle(target, on_box, back);
draw_rectangle_outline(target, on_box, fore);
}
}
return result;
}
internal b32
do_undo_slider(Widget_ID wid, UI_State *state, UI_Layout *layout, i32 max, i32 v, Undo_Data *undo, i32 *out){
b32 result = 0;
i16 font_id = state->style->font_id;
i32 character_h = get_font_info(state->font_set, font_id)->height;
i32_Rect containing_rect = layout_rect(layout, character_h);
i32_Rect click_rect;
click_rect.x0 = containing_rect.x0 + character_h - 1;
click_rect.x1 = containing_rect.x1 - character_h + 1;
click_rect.y0 = containing_rect.y0 + 2;
click_rect.y1 = containing_rect.y1 - 2;
if (state->input_stage){
real32 l;
if (ui_do_slider_input(state, click_rect, wid, (real32)click_rect.x0, (real32)click_rect.x1, &l)){
real32 v_new = lerp(0.f, l, (real32)max);
v = ROUND32(v_new);
result = 1;
if (out) *out = v;
}
}
else{
Render_Target *target = state->target;
if (max > 0){
UI_Style ui_style = get_ui_style_upper(state->style);
real32 L = unlerp(0.f, (real32)v, (real32)max);
i32 x = FLOOR32(lerp((real32)click_rect.x0, L, (real32)click_rect.x1));
i32 bar_top = ((click_rect.y0 + click_rect.y1) >> 1) - 1;
i32 bar_bottom = bar_top + 2;
bool32 show_bar = 1;
real32 tick_step = (click_rect.x1 - click_rect.x0) / (real32)max;
bool32 show_ticks = 1;
if (tick_step <= 5.f) show_ticks = 0;
if (undo == 0){
if (show_bar){
i32_Rect slider_rect;
slider_rect.x0 = click_rect.x0;
slider_rect.x1 = x;
slider_rect.y0 = bar_top;
slider_rect.y1 = bar_bottom;
draw_rectangle(target, slider_rect, ui_style.dim);
slider_rect.x0 = x;
slider_rect.x1 = click_rect.x1;
draw_rectangle(target, slider_rect, ui_style.pop1);
}
if (show_ticks){
f32_Rect tick;
tick.x0 = (real32)click_rect.x0 - 1;
tick.x1 = (real32)click_rect.x0 + 1;
tick.y0 = (real32)bar_top - 3;
tick.y1 = (real32)bar_bottom + 3;
for (i32 i = 0; i < v; ++i){
draw_rectangle(target, tick, ui_style.dim);
tick.x0 += tick_step;
tick.x1 += tick_step;
}
for (i32 i = v; i <= max; ++i){
draw_rectangle(target, tick, ui_style.pop1);
tick.x0 += tick_step;
tick.x1 += tick_step;
}
}
}
else{
if (show_bar){
i32_Rect slider_rect;
slider_rect.x0 = click_rect.x0;
slider_rect.y0 = bar_top;
slider_rect.y1 = bar_bottom;
Edit_Step *history = undo->history.edits;
i32 block_count = undo->history_block_count;
Edit_Step *step = history;
for (i32 i = 0; i < block_count; ++i){
u32 color;
if (step->type == ED_REDO ||
step->type == ED_UNDO) color = ui_style.pop1;
else color = ui_style.dim;
real32 L;
if (i + 1 == block_count){
L = 1.f;
}else{
step = history + step->next_block;
L = unlerp(0.f, (real32)(step - history), (real32)max);
}
if (L > 1.f) L = 1.f;
i32 x = FLOOR32(lerp((real32)click_rect.x0, L, (real32)click_rect.x1));
slider_rect.x1 = x;
draw_rectangle(target, slider_rect, color);
slider_rect.x0 = slider_rect.x1;
if (L == 1.f) break;
}
}
if (show_ticks){
f32_Rect tick;
tick.x0 = (real32)click_rect.x0 - 1;
tick.x1 = (real32)click_rect.x0 + 1;
tick.y0 = (real32)bar_top - 3;
tick.y1 = (real32)bar_bottom + 3;
Edit_Step *history = undo->history.edits;
u32 color = ui_style.dim;
for (i32 i = 0; i <= max; ++i){
if (i != max){
if (history[i].type == ED_REDO) color = ui_style.pop1;
else if (history[i].type == ED_UNDO ||
history[i].type == ED_NORMAL) color = ui_style.pop2;
else color = ui_style.dim;
}
draw_rectangle(target, tick, color);
tick.x0 += tick_step;
tick.x1 += tick_step;
}
}
}
i32_Rect slider_handle;
slider_handle.x0 = x - 2;
slider_handle.x1 = x + 2;
slider_handle.y0 = click_rect.y0;
slider_handle.y1 = click_rect.y1;
draw_rectangle(target, slider_handle, ui_style.bright);
}
}
return result;
}
// BOTTOM

BIN
vc120.pdb

Binary file not shown.

View File

@ -111,7 +111,7 @@ struct Win32_Vars{
HCURSOR cursor_leftright;
HCURSOR cursor_updown;
Application_Mouse_Cursor prev_mouse_cursor;
Clipboard_Contents clipboard_contents;
String clipboard_contents;
b32 next_clipboard_is_self;
DWORD clipboard_sequence;
@ -1326,7 +1326,7 @@ UpdateLoop(LPVOID param){
HANDLE clip_data;
clip_data = GetClipboardData(CF_TEXT);
if (clip_data){
win32vars.clipboard_contents.str = (u8*)GlobalLock(clip_data);
win32vars.clipboard_contents.str = (char*)GlobalLock(clip_data);
if (win32vars.clipboard_contents.str){
win32vars.clipboard_contents.size = str_size((char*)win32vars.clipboard_contents.str);
GlobalUnlock(clip_data);
@ -1337,12 +1337,11 @@ UpdateLoop(LPVOID param){
}
}
}
u32 redraw = exchange_vars.thread.force_redraw;
if (redraw) exchange_vars.thread.force_redraw = 0;
redraw = redraw || input_chunk.trans.redraw;
Key_Input_Data input_data;
Mouse_State mouse;
Application_Step_Result result;
@ -1749,7 +1748,7 @@ main(int argc, char **argv){
HANDLE clip_data;
clip_data = GetClipboardData(CF_TEXT);
if (clip_data){
win32vars.clipboard_contents.str = (u8*)GlobalLock(clip_data);
win32vars.clipboard_contents.str = (char*)GlobalLock(clip_data);
if (win32vars.clipboard_contents.str){
win32vars.clipboard_contents.size = str_size((char*)win32vars.clipboard_contents.str);
GlobalUnlock(clip_data);