new memory interface
parent
e88b9ea324
commit
a89b46fda7
|
@ -128,8 +128,18 @@ FCPP_LINK bool append_partial(String *dest, String src);
|
|||
FCPP_LINK bool append(String *dest, char c);
|
||||
inline bool append(String *dest, String src) { return append_partial(dest, src); }
|
||||
inline bool append(String *dest, char *src) { return append_partial(dest, src); }
|
||||
inline void terminate_with_null(String *str)
|
||||
{ if (str->size < str->memory_size) str->str[str->size] = 0; else str->str[str->size-1] = 0; }
|
||||
inline bool terminate_with_null(String *str){
|
||||
bool result;
|
||||
if (str->size < str->memory_size){
|
||||
str->str[str->size] = 0;
|
||||
result = 1;
|
||||
}
|
||||
else{
|
||||
str->str[str->size-1] = 0;
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FCPP_LINK int compare(char *a, char *b);
|
||||
FCPP_LINK int compare(String a, char *b);
|
||||
|
|
149
4ed.cpp
149
4ed.cpp
|
@ -23,6 +23,16 @@ struct App_State_Resizing{
|
|||
i32 min, max;
|
||||
};
|
||||
|
||||
struct CLI_Process{
|
||||
CLI_Handles cli;
|
||||
Editing_File *out_file;
|
||||
};
|
||||
|
||||
struct CLI_List{
|
||||
CLI_Process *procs;
|
||||
i32 count, max;
|
||||
};
|
||||
|
||||
struct App_Vars{
|
||||
Mem_Options mem;
|
||||
Command_Map map_top;
|
||||
|
@ -51,6 +61,8 @@ struct App_Vars{
|
|||
char hot_dir_base_[256];
|
||||
String hot_dir_base;
|
||||
Hot_Directory hot_directory;
|
||||
|
||||
CLI_List cli_processes;
|
||||
|
||||
char query_[256];
|
||||
char dest_[256];
|
||||
|
@ -480,7 +492,7 @@ COMMAND_DECL(paste){
|
|||
|
||||
String *src = working_set_clipboard_head(working_set);
|
||||
i32 pos_left = view->cursor.pos;
|
||||
|
||||
|
||||
i32 next_cursor_pos = pos_left+src->size;
|
||||
view_replace_range(mem, view, layout, pos_left, pos_left, (u8*)src->str, src->size, next_cursor_pos);
|
||||
|
||||
|
@ -966,7 +978,7 @@ case_change_range(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
if (file->still_lexing)
|
||||
system_cancel_job(BACKGROUND_THREADS, file->lex_job);
|
||||
|
||||
view_update_history_before_edit(mem, file, step, 0, hist_normal);
|
||||
file_update_history_before_edit(mem, file, step, 0, hist_normal);
|
||||
|
||||
u8 *data = (u8*)file->buffer.data;
|
||||
for (i32 i = range.start; i < range.end; ++i){
|
||||
|
@ -1518,9 +1530,71 @@ COMMAND_DECL(set_settings){
|
|||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(build){
|
||||
ProfileMomentFunction();
|
||||
USE_VARS(vars);
|
||||
USE_MEM(mem);
|
||||
USE_WORKING_SET(working_set);
|
||||
USE_STYLE(style);
|
||||
USE_LIVE_SET(live_set);
|
||||
USE_PANEL(panel);
|
||||
|
||||
if (vars->cli_processes.count < vars->cli_processes.max){
|
||||
Get_File_Result file = working_set_get_available_file(working_set);
|
||||
if (file.file){
|
||||
file_create_empty(&mem->general, file.file, (u8*)"*cli process*", style->font);
|
||||
table_add(&working_set->table, file.file->source_path, file.index);
|
||||
|
||||
View *new_view = live_set_alloc_view(live_set, mem);
|
||||
view_replace_major(new_view, panel, live_set);
|
||||
|
||||
File_View *file_view = file_view_init(new_view, &vars->delay, &vars->layout);
|
||||
view_set_file(file_view, file.file, style,
|
||||
vars->hooks[hook_open_file], command, app_links);
|
||||
file.file->tokens_exist = 0;
|
||||
new_view->map = app_get_map(vars, file.file->base_map_id);
|
||||
|
||||
i32 i = vars->cli_processes.count++;
|
||||
CLI_Process *proc = vars->cli_processes.procs + i;
|
||||
if (!system_cli_call("..\\misc", "build_all_test", &proc->cli)){
|
||||
--vars->cli_processes.count;
|
||||
}
|
||||
proc->out_file = file.file;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): feedback message - no available file
|
||||
}
|
||||
}
|
||||
else{
|
||||
// TODO(allen): feedback message - no available process slot
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
update_command_data(App_Vars *vars, Command_Data *cmd){
|
||||
Command_Data command_data;
|
||||
command_data.vars = vars;
|
||||
command_data.mem = &vars->mem;
|
||||
command_data.working_set = &vars->working_set;
|
||||
command_data.layout = &vars->layout;
|
||||
command_data.panel = command_data.layout->panels + command_data.layout->active_panel;
|
||||
command_data.view = command_data.panel->view;
|
||||
command_data.live_set = &vars->live_set;
|
||||
command_data.style = &vars->style;
|
||||
command_data.delay = &vars->delay;
|
||||
command_data.screen_width = cmd->screen_width;
|
||||
command_data.screen_height = cmd->screen_height;
|
||||
command_data.key = cmd->key;
|
||||
command_data.part = cmd->part;
|
||||
|
||||
*cmd = command_data;
|
||||
}
|
||||
|
||||
COMPOSE_DECL(compose_write_auto_tab_line){
|
||||
command_write_character(command, binding);
|
||||
update_command_data(command->vars, command);
|
||||
command_auto_tab_line_at_cursor(command, binding);
|
||||
update_command_data(command->vars, command);
|
||||
}
|
||||
|
||||
globalvar Command_Function command_table[cmdid_count];
|
||||
|
@ -1532,7 +1606,9 @@ extern "C"{
|
|||
Command_Binding binding;
|
||||
binding.function = function;
|
||||
if (function) function(cmd, binding);
|
||||
|
||||
|
||||
update_command_data(cmd->vars, cmd);
|
||||
#if 0
|
||||
App_Vars *vars = cmd->vars;
|
||||
Command_Data command_data;
|
||||
command_data.vars = vars;
|
||||
|
@ -1550,6 +1626,7 @@ extern "C"{
|
|||
command_data.part = cmd->part;
|
||||
|
||||
*cmd = command_data;
|
||||
#endif
|
||||
}
|
||||
|
||||
PUSH_PARAMETER_SIG(external_push_parameter){
|
||||
|
@ -1724,24 +1801,9 @@ setup_top_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Com
|
|||
map_add(commands, 'i', MDFR_CTRL, command_interactive_switch_buffer);
|
||||
map_add(commands, 'c', MDFR_ALT, command_open_color_tweaker);
|
||||
map_add(commands, 'x', MDFR_ALT, command_open_menu);
|
||||
map_add(commands, 'm', MDFR_ALT, command_build);
|
||||
}
|
||||
|
||||
#if 0 // TODO(allen): Here's an idea
|
||||
internal void
|
||||
setup_command_table(){
|
||||
BEGIN_META_CODE{
|
||||
int count;
|
||||
char **command_names = get_all_commands(&count);
|
||||
for (int i = 0; i < count; ++i){
|
||||
char *name_ = command_names[i];
|
||||
String name = make_string_slowly(name_);
|
||||
|
||||
outcode("command_table[cmdid_", out_str(name), "] = command_", out_str(name), "\n");
|
||||
}
|
||||
}END_META_CODE
|
||||
}
|
||||
#endif
|
||||
|
||||
internal void
|
||||
setup_command_table(){
|
||||
#define SET(n) command_table[cmdid_##n] = command_##n
|
||||
|
@ -2475,6 +2537,13 @@ app_init(Thread_Context *thread, Application_Memory *memory,
|
|||
|
||||
vars->mini_str = make_string((char*)vars->mini_buffer, 0, 512);
|
||||
|
||||
// NOTE(allen): child proc list setup
|
||||
i32 max_children = 16;
|
||||
partition_align(partition, 8);
|
||||
vars->cli_processes.procs = push_array(partition, CLI_Process, max_children);
|
||||
vars->cli_processes.max = max_children;
|
||||
vars->cli_processes.count = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2522,6 +2591,48 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): update child processes
|
||||
{
|
||||
Temp_Memory temp = begin_temp_memory(&vars->mem.part);
|
||||
u32 max = Kbytes(32);
|
||||
char *dest = push_array(&vars->mem.part, char, max);
|
||||
u32 amount;
|
||||
|
||||
i32 count = vars->cli_processes.count;
|
||||
for (i32 i = 0; i < count; ++i){
|
||||
CLI_Process *proc = vars->cli_processes.procs + i;
|
||||
Editing_File *out_file = proc->out_file;
|
||||
|
||||
i32 new_cursor = out_file->cursor_pos;
|
||||
for (system_cli_begin_update(&proc->cli);
|
||||
system_cli_update_step(&proc->cli, dest, max, &amount);){
|
||||
if (out_file){
|
||||
amount = eol_in_place_convert_in(dest, amount);
|
||||
Edit_Spec spec = {};
|
||||
spec.step.type = ED_NORMAL;
|
||||
spec.step.edit.start = buffer_size(&out_file->buffer);
|
||||
spec.step.edit.end = spec.step.edit.start;
|
||||
spec.step.edit.len = amount;
|
||||
spec.step.pre_pos = new_cursor;
|
||||
spec.step.post_pos = spec.step.edit.start + amount;
|
||||
spec.str = (u8*)dest;
|
||||
file_do_single_edit(&vars->mem, out_file,
|
||||
&vars->layout, spec, hist_normal);
|
||||
app_result.redraw = 1;
|
||||
new_cursor = spec.step.post_pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (system_cli_end_update(&proc->cli)){
|
||||
*proc = vars->cli_processes.procs[--count];
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
vars->cli_processes.count = count;
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
// NOTE(allen): reorganizing panels on screen
|
||||
i32 prev_width = vars->layout.full_width;
|
||||
i32 prev_height = vars->layout.full_height;
|
||||
|
|
26
4ed.h
26
4ed.h
|
@ -112,6 +112,27 @@ general_memory_open(General_Memory *general, void *memory, i32 size){
|
|||
insert_bubble(&general->sentinel, first);
|
||||
}
|
||||
|
||||
internal void
|
||||
general_memory_check(General_Memory *general){
|
||||
Bubble *sentinel = &general->sentinel;
|
||||
for (Bubble *bubble = sentinel->next;
|
||||
bubble != sentinel;
|
||||
bubble = bubble->next){
|
||||
Assert(bubble);
|
||||
|
||||
Bubble *next = bubble->next;
|
||||
Assert(bubble == next->prev);
|
||||
if (next != sentinel){
|
||||
Assert(bubble->next > bubble);
|
||||
Assert(bubble > bubble->prev);
|
||||
|
||||
char *end_ptr = (char*)(bubble + 1) + bubble->size;
|
||||
char *next_ptr = (char*)next;
|
||||
Assert(end_ptr == next_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BUBBLE_MIN_SIZE 1024
|
||||
|
||||
internal void
|
||||
|
@ -129,9 +150,6 @@ general_memory_attempt_split(Bubble *bubble, i32 wanted_size){
|
|||
internal void*
|
||||
general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){
|
||||
void *result = 0;
|
||||
if (size < Kbytes(1)){
|
||||
int x = 1; AllowLocal(x);
|
||||
}
|
||||
for (Bubble *bubble = general->sentinel.next;
|
||||
bubble != &general->sentinel;
|
||||
bubble = bubble->next){
|
||||
|
@ -150,6 +168,8 @@ general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){
|
|||
|
||||
inline void
|
||||
general_memory_do_merge(Bubble *left, Bubble *right){
|
||||
Assert(left->next == right);
|
||||
Assert(right->prev == left);
|
||||
left->size += sizeof(Bubble) + right->size;
|
||||
remove_bubble(right);
|
||||
}
|
||||
|
|
|
@ -1187,8 +1187,8 @@ file_grow_starts_as_needed(General_Memory *general, Editing_File *file, i32 addi
|
|||
i32 max = file->buffer.line_max;
|
||||
i32 count = file->buffer.line_count;
|
||||
i32 target_lines = count + additional_lines;
|
||||
if (target_lines > max){
|
||||
max <<= 1;
|
||||
if (target_lines > max || max == 0){
|
||||
max = LargeRoundUp(target_lines + max, Kbytes(1));
|
||||
i32 *new_lines = (i32*)
|
||||
general_memory_reallocate(general, file->buffer.line_starts,
|
||||
sizeof(i32)*count, sizeof(i32)*max, BUBBLE_STARTS);
|
||||
|
@ -1267,15 +1267,17 @@ internal void
|
|||
file_grow_widths_as_needed(General_Memory *general, Editing_File *file){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
i32 line_count = file->buffer.line_count;
|
||||
if (line_count > file->buffer.widths_max){
|
||||
if (line_count > file->buffer.widths_max || file->buffer.widths_max == 0){
|
||||
i32 new_max = LargeRoundUp(line_count, Kbytes(1));
|
||||
if (new_max < Kbytes(1)) new_max = Kbytes(1);
|
||||
if (file->buffer.line_widths){
|
||||
file->buffer.line_widths = (real32*)
|
||||
general_memory_reallocate_nocopy(general, file->buffer.line_widths, sizeof(real32)*new_max, BUBBLE_WIDTHS);
|
||||
file->buffer.line_widths = (f32*)
|
||||
general_memory_reallocate(general, file->buffer.line_widths,
|
||||
sizeof(f32)*file->buffer.widths_count, sizeof(f32)*new_max, BUBBLE_WIDTHS);
|
||||
}
|
||||
else{
|
||||
file->buffer.line_widths = (real32*)
|
||||
general_memory_allocate(general, sizeof(real32)*new_max, BUBBLE_WIDTHS);
|
||||
file->buffer.line_widths = (f32*)
|
||||
general_memory_allocate(general, sizeof(f32)*new_max, BUBBLE_WIDTHS);
|
||||
}
|
||||
file->buffer.widths_max = new_max;
|
||||
}
|
||||
|
@ -1379,11 +1381,11 @@ internal void
|
|||
file_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val){
|
||||
*file = {};
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 2
|
||||
|
||||
Buffer_Init_Type init = buffer_begin_init(&file->buffer, val.str, val.size);
|
||||
for (; buffer_init_need_more(&init); ){
|
||||
i32 page_size = buffer_init_page_size(&init);
|
||||
page_size = LargeRoundUp(page_size, Kbytes(4));
|
||||
if (page_size < Kbytes(4)) page_size = Kbytes(4);
|
||||
void *data = general_memory_allocate(general, page_size, BUBBLE_BUFFER);
|
||||
buffer_init_provide_page(&init, data, page_size);
|
||||
}
|
||||
|
@ -1396,7 +1398,7 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam
|
|||
file_set_name(file, filename);
|
||||
|
||||
file->base_map_id = mapid_file;
|
||||
|
||||
|
||||
file_measure_starts(general, file);
|
||||
file_measure_widths(general, file, font);
|
||||
file->font = font;
|
||||
|
@ -1695,21 +1697,7 @@ file_relex_parallel(Mem_Options *mem, Editing_File *file,
|
|||
#endif
|
||||
|
||||
internal bool32
|
||||
file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_size){
|
||||
bool32 result = 1;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
i32 size = buffer_size(&file->buffer);
|
||||
i32 target_size = size + additional_size + 1;
|
||||
if (target_size >= file->buffer.max){
|
||||
i32 request_size = LargeRoundUp(target_size*2, Kbytes(256));
|
||||
char *new_data = (char*)
|
||||
general_memory_allocate(general, request_size, BUBBLE_BUFFER);
|
||||
TentativeAssert(new_data);
|
||||
void *old_data = buffer_relocate(&file->buffer, new_data, request_size);
|
||||
general_memory_free(general, old_data);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
file_grow_as_needed_(General_Memory *general, Editing_File *file, i32 new_size){
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -2267,7 +2255,7 @@ enum History_Mode{
|
|||
};
|
||||
|
||||
internal void
|
||||
view_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str,
|
||||
file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str,
|
||||
History_Mode history_mode){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
General_Memory *general = &mem->general;
|
||||
|
@ -2460,13 +2448,13 @@ file_pre_edit_maintenance(Editing_File *file){
|
|||
}
|
||||
|
||||
internal void
|
||||
view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
||||
file_do_single_edit(Mem_Options *mem, Editing_File *file,
|
||||
Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){
|
||||
Assert(file);
|
||||
ProfileMomentFunction();
|
||||
|
||||
// NOTE(allen): fixing stuff beforewards????
|
||||
view_update_history_before_edit(mem, file, spec.step, spec.str, history_mode);
|
||||
file_update_history_before_edit(mem, file, spec.step, spec.str, history_mode);
|
||||
file_pre_edit_maintenance(file);
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 1
|
||||
|
@ -2479,8 +2467,15 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
i32 str_len = spec.step.edit.len;
|
||||
|
||||
i32 shift_amount = 0;
|
||||
while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount))
|
||||
file_grow_as_needed(general, file, shift_amount);
|
||||
i32 request_amount = 0;
|
||||
while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount, &request_amount)){
|
||||
void *new_data = 0;
|
||||
if (request_amount > 0){
|
||||
new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER);
|
||||
}
|
||||
void *old_data = buffer_edit_provide_memory(&file->buffer, new_data, request_amount);
|
||||
if (old_data) general_memory_free(general, old_data);
|
||||
}
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL <= 0
|
||||
// NOTE(allen): fixing stuff afterwards
|
||||
|
@ -2516,10 +2511,8 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
File_View *current_view = view_to_file_view(current_panel->view);
|
||||
if (current_view && current_view->file == file){
|
||||
view_measure_wraps(general, current_view);
|
||||
if (current_view != view){
|
||||
write_cursor_with_index(cursors, &cursor_count, current_view->cursor.pos);
|
||||
write_cursor_with_index(cursors, &cursor_count, current_view->mark);
|
||||
}
|
||||
write_cursor_with_index(cursors, &cursor_count, current_view->cursor.pos);
|
||||
write_cursor_with_index(cursors, &cursor_count, current_view->mark);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2535,11 +2528,9 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
|
||||
File_View *current_view = view_to_file_view(current_panel->view);
|
||||
if (current_view && current_view->file == file){
|
||||
if (current_view != view){
|
||||
view_cursor_move(current_view, cursors[cursor_count++].pos);
|
||||
current_view->mark = cursors[cursor_count++].pos;
|
||||
current_view->preferred_x = view_get_cursor_x(current_view);
|
||||
}
|
||||
view_cursor_move(current_view, cursors[cursor_count++].pos);
|
||||
current_view->mark = cursors[cursor_count++].pos;
|
||||
current_view->preferred_x = view_get_cursor_x(current_view);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2556,7 +2547,7 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
|
||||
// NOTE(allen): fixing stuff beforewards????
|
||||
Assert(spec.str == 0);
|
||||
view_update_history_before_edit(mem, file, spec.step, 0, history_mode);
|
||||
file_update_history_before_edit(mem, file, spec.step, 0, history_mode);
|
||||
file_pre_edit_maintenance(file);
|
||||
|
||||
// NOTE(allen): actual text replacement
|
||||
|
@ -2569,11 +2560,18 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
|
||||
Assert(spec.step.first_child < file->undo.children.edit_count);
|
||||
Assert(batch_size >= 0);
|
||||
|
||||
i32 shift_amount = buffer_batch_edit_max_shift(batch, batch_size);
|
||||
file_grow_as_needed(general, file, shift_amount);
|
||||
|
||||
buffer_batch_edit(&file->buffer, batch, (char*)str_base, batch_size);
|
||||
|
||||
Buffer_Batch_State state = {};
|
||||
i32 request_amount;
|
||||
while (buffer_batch_edit_step(&state, &file->buffer,
|
||||
batch, (char*)str_base, batch_size, &request_amount)){
|
||||
void *new_data = 0;
|
||||
if (request_amount > 0){
|
||||
new_data = general_memory_allocate(general, request_amount, BUBBLE_BUFFER);
|
||||
}
|
||||
void *old_data = buffer_edit_provide_memory(&file->buffer, new_data, request_amount);
|
||||
if (old_data) general_memory_free(general, old_data);
|
||||
}
|
||||
|
||||
// NOTE(allen): token fixing
|
||||
if (file->tokens_complete){
|
||||
|
@ -2585,12 +2583,18 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
Buffer_Edit *end_edit = batch + batch_size;
|
||||
|
||||
i32 shift_amount = 0;
|
||||
i32 local_shift = 0;
|
||||
|
||||
for (; token < end_token && edit < end_edit; ++edit){
|
||||
local_shift = (edit->len - (edit->end - edit->start));
|
||||
for (; token->start < edit->start && edit->start < token->start + token->size &&
|
||||
token < end_token; ++token){
|
||||
token->size += local_shift;
|
||||
}
|
||||
for (; token->start < edit->start && token < end_token; ++token){
|
||||
token->start += shift_amount;
|
||||
}
|
||||
shift_amount += (edit->len - (edit->end - edit->start));
|
||||
shift_amount += local_shift;
|
||||
}
|
||||
for (; token < end_token; ++token){
|
||||
token->start += shift_amount;
|
||||
|
@ -2656,7 +2660,7 @@ view_replace_range(Mem_Options *mem, File_View *view, Editing_Layout *layout,
|
|||
spec.step.pre_pos = view->cursor.pos;
|
||||
spec.step.post_pos = next_cursor;
|
||||
spec.str = str;
|
||||
view_do_single_edit(mem, view, view->file, layout, spec, hist_normal);
|
||||
file_do_single_edit(mem, view->file, layout, spec, hist_normal);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -2683,7 +2687,7 @@ view_undo_redo(Mem_Options *mem, Editing_Layout *layout, File_View *view, Editin
|
|||
spec.step.edit.str_start = 0;
|
||||
spec.str = stack->strings + step.edit.str_start;
|
||||
|
||||
view_do_single_edit(mem, view, file, layout, spec, hist_normal);
|
||||
file_do_single_edit(mem, file, layout, spec, hist_normal);
|
||||
|
||||
if (expected_type == ED_UNDO) view_cursor_move(view, step.pre_pos);
|
||||
else view_cursor_move(view, step.post_pos);
|
||||
|
@ -2742,7 +2746,7 @@ view_history_step(Mem_Options *mem, Editing_Layout *layout, File_View *view, His
|
|||
spec.step.edit.str_start = 0;
|
||||
spec.str = file->undo.history.strings + step.edit.str_start;
|
||||
|
||||
view_do_single_edit(mem, view, file, layout, spec, history_mode);
|
||||
file_do_single_edit(mem, file, layout, spec, history_mode);
|
||||
|
||||
switch (spec.step.type){
|
||||
case ED_NORMAL:
|
||||
|
@ -2906,7 +2910,7 @@ clipboard_copy(General_Memory *general, Working_Set *working, Range range, Editi
|
|||
}
|
||||
|
||||
internal Edit_Spec
|
||||
view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file,
|
||||
file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_pos,
|
||||
Buffer_Edit *edits, char *str_base, i32 str_size,
|
||||
Buffer_Edit *inverse_array, char *inv_str, i32 inv_max,
|
||||
i32 edit_count){
|
||||
|
@ -2933,6 +2937,8 @@ view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file,
|
|||
spec.step.special_type = 1;
|
||||
spec.step.child_count = edit_count;
|
||||
spec.step.inverse_child_count = edit_count;
|
||||
spec.step.pre_pos = cursor_pos;
|
||||
spec.step.post_pos = cursor_pos;
|
||||
#else
|
||||
Edit_Spec spec = {};
|
||||
#endif
|
||||
|
@ -2989,7 +2995,7 @@ view_clean_whitespace(Mem_Options *mem, File_View *view, Editing_Layout *layout)
|
|||
|
||||
char *inv_str = (char*)part->base + part->pos;
|
||||
Edit_Spec spec =
|
||||
view_compute_whitespace_edit(mem, file, edits, str_base, str_size,
|
||||
file_compute_whitespace_edit(mem, file, view->cursor.pos, edits, str_base, str_size,
|
||||
inverse_array, inv_str, part->max - part->pos, edit_count);
|
||||
|
||||
view_do_white_batch_edit(mem, view, file, layout, spec, hist_normal);
|
||||
|
@ -3178,7 +3184,7 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout,
|
|||
|
||||
char *inv_str = (char*)part->base + part->pos;
|
||||
Edit_Spec spec =
|
||||
view_compute_whitespace_edit(mem, file, edits, str_base, str_size,
|
||||
file_compute_whitespace_edit(mem, file, view->cursor.pos, edits, str_base, str_size,
|
||||
inverse_array, inv_str, part->max - part->pos, edit_count);
|
||||
|
||||
view_do_white_batch_edit(mem, view, file, layout, spec, hist_normal);
|
||||
|
@ -3537,8 +3543,12 @@ step_file_view(Thread_Context *thread, View *view_, i32_Rect rect,
|
|||
result = 1;
|
||||
}
|
||||
|
||||
while (cursor_y > target_y + max_y) target_y += delta_y;
|
||||
while (cursor_y < target_y + taken_top_space) target_y -= delta_y;
|
||||
if (cursor_y > target_y + max_y){
|
||||
target_y = cursor_y - max_y + delta_y;
|
||||
}
|
||||
if (cursor_y < target_y + taken_top_space){
|
||||
target_y = cursor_y - delta_y - taken_top_space;
|
||||
}
|
||||
|
||||
if (target_y > max_target_y) target_y = max_target_y;
|
||||
if (target_y < -extra_top) target_y = -extra_top;
|
||||
|
|
|
@ -31,7 +31,7 @@ struct Debug_Event{
|
|||
|
||||
struct Debug_Event_Array{
|
||||
volatile u32 count;
|
||||
Debug_Event e[512];
|
||||
Debug_Event e[4096];
|
||||
};
|
||||
|
||||
struct Profile_Frame{
|
||||
|
|
21
4ed_system.h
21
4ed_system.h
|
@ -7,6 +7,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
struct Plat_Handle{ u64 d[2]; };
|
||||
|
||||
// TODO(allen): This should either be a String or it should be improved
|
||||
// to handle 64-bit sized files. Staying in this state, however, is unacceptable.
|
||||
struct File_Data{
|
||||
|
@ -76,6 +78,25 @@ system_post_clipboard(String str);
|
|||
internal i64
|
||||
system_time();
|
||||
|
||||
struct CLI_Handles{
|
||||
Plat_Handle proc;
|
||||
Plat_Handle out_read;
|
||||
Plat_Handle out_write;
|
||||
u32 scratch_space[4];
|
||||
};
|
||||
|
||||
internal b32
|
||||
system_cli_call(char *path, char *script_name, CLI_Handles *cli_out);
|
||||
|
||||
internal void
|
||||
system_cli_begin_update(CLI_Handles *cli);
|
||||
|
||||
internal b32
|
||||
system_cli_update_step(CLI_Handles *cli, char *dest, u32 max, u32 *amount);
|
||||
|
||||
internal b32
|
||||
system_cli_end_update(CLI_Handles *cli);
|
||||
|
||||
struct Thread_Context;
|
||||
|
||||
struct Thread_Memory{
|
||||
|
|
|
@ -597,6 +597,7 @@ buffer_remeasure_widths(Buffer_Type *buffer, void *advance_data, int stride,
|
|||
int *starts;
|
||||
float *widths;
|
||||
int line_count;
|
||||
int widths_count;
|
||||
char *data;
|
||||
int size, end;
|
||||
int i, j;
|
||||
|
@ -606,17 +607,17 @@ buffer_remeasure_widths(Buffer_Type *buffer, void *advance_data, int stride,
|
|||
starts = buffer->line_starts;
|
||||
widths = buffer->line_widths;
|
||||
line_count = buffer->line_count;
|
||||
widths_count = buffer->widths_count;
|
||||
|
||||
assert_4tech(0 <= line_start);
|
||||
assert_4tech(line_start <= line_end);
|
||||
assert_4tech(line_end < line_count);
|
||||
assert_4tech(line_count <= buffer->widths_max);
|
||||
|
||||
++line_end;
|
||||
|
||||
if (line_shift != 0){
|
||||
memmove_4tech(widths + line_end + line_shift, widths + line_end,
|
||||
sizeof(float)*(line_count - line_end));
|
||||
sizeof(float)*(widths_count - line_end));
|
||||
}
|
||||
buffer->widths_count = line_count;
|
||||
|
||||
line_end += line_shift;
|
||||
i = line_start;
|
||||
|
@ -733,7 +734,6 @@ buffer_get_line_index_from_wrapped_y(float *wraps, float y, float font_height, i
|
|||
#endif
|
||||
|
||||
#ifndef NON_ABSTRACT_4TECH
|
||||
|
||||
typedef struct{
|
||||
Full_Cursor cursor, prev_cursor;
|
||||
} Seek_State;
|
||||
|
@ -1000,13 +1000,15 @@ buffer_invert_batch(Buffer_Invert_Batch *state, Buffer_Type *buffer, Buffer_Edit
|
|||
internal_4tech void
|
||||
buffer_batch_edit(Buffer_Type *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count){
|
||||
Buffer_Batch_State state;
|
||||
int r;
|
||||
|
||||
debug_4tech(int result);
|
||||
|
||||
state.i = 0;
|
||||
state.shift_total = 0;
|
||||
|
||||
debug_4tech(result =)
|
||||
buffer_batch_edit_step(&state, buffer, sorted_edits, strings, edit_count);
|
||||
buffer_batch_edit_step(&state, buffer, sorted_edits, strings, edit_count, &r);
|
||||
assert_4tech(result == 0);
|
||||
}
|
||||
#endif
|
||||
|
@ -1121,7 +1123,6 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
|
|||
}
|
||||
|
||||
buffer_get_render_data_end:
|
||||
|
||||
if (y <= height + shift_y || item == items){
|
||||
ch = 0;
|
||||
ch_width = measure_character(advance_data, stride, ' ');
|
||||
|
|
|
@ -20,6 +20,7 @@ typedef struct{
|
|||
float *line_widths;
|
||||
int *line_starts;
|
||||
int line_count;
|
||||
int widths_count;
|
||||
int line_max;
|
||||
int widths_max;
|
||||
} Gap_Buffer;
|
||||
|
@ -110,7 +111,7 @@ buffer_end_init(Gap_Buffer_Init *init){
|
|||
}
|
||||
|
||||
internal_4tech void*
|
||||
buffer_relocate(Gap_Buffer *buffer, char *new_data, int new_max){
|
||||
buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){
|
||||
void *result;
|
||||
int new_gap_size;
|
||||
|
||||
|
@ -119,9 +120,9 @@ buffer_relocate(Gap_Buffer *buffer, char *new_data, int new_max){
|
|||
result = buffer->data;
|
||||
new_gap_size = new_max - buffer_size(buffer);
|
||||
memcpy_4tech(new_data, buffer->data, buffer->size1);
|
||||
memcpy_4tech(new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2);
|
||||
memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2);
|
||||
|
||||
buffer->data = new_data;
|
||||
buffer->data = (char*)new_data;
|
||||
buffer->gap_size = new_gap_size;
|
||||
buffer->max = new_max;
|
||||
|
||||
|
@ -263,7 +264,7 @@ buffer_backify_next(Gap_Buffer_Backify_Loop *loop){
|
|||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){
|
||||
buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, int *request_amount){
|
||||
char *data;
|
||||
int result;
|
||||
int size;
|
||||
|
@ -301,7 +302,8 @@ buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len,
|
|||
result = 0;
|
||||
}
|
||||
else{
|
||||
result = *shift_amount + size;
|
||||
*request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
@ -309,7 +311,7 @@ buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len,
|
|||
|
||||
// NOTE(allen): This could should be optimized for Gap_Buffer
|
||||
internal_4tech int
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count){
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count, int *request_amount){
|
||||
Buffer_Edit *edit;
|
||||
int i, result;
|
||||
int shift_total, shift_amount;
|
||||
|
@ -321,7 +323,7 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edi
|
|||
edit = sorted_edits + i;
|
||||
for (; i < edit_count; ++i, ++edit){
|
||||
result = buffer_replace_range(buffer, edit->start + shift_total, edit->end + shift_total,
|
||||
strings + edit->str_start, edit->len, &shift_amount);
|
||||
strings + edit->str_start, edit->len, &shift_amount, request_amount);
|
||||
if (result) break;
|
||||
shift_total += shift_amount;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ typedef struct{
|
|||
int *line_starts;
|
||||
float *line_widths;
|
||||
int line_count;
|
||||
int widths_count;
|
||||
int line_max;
|
||||
int widths_max;
|
||||
} Buffer;
|
||||
|
@ -92,14 +93,14 @@ buffer_end_init(Buffer_Init *init){
|
|||
}
|
||||
|
||||
internal_4tech void*
|
||||
buffer_relocate(Buffer *buffer, char *new_data, int new_max){
|
||||
buffer_edit_provide_memory(Buffer *buffer, void *new_data, int new_max){
|
||||
void *result;
|
||||
|
||||
assert_4tech(new_max >= buffer->size);
|
||||
|
||||
result = buffer->data;
|
||||
memcpy_4tech(new_data, buffer->data, buffer->size);
|
||||
buffer->data = new_data;
|
||||
buffer->data = (char*)new_data;
|
||||
buffer->max = new_max;
|
||||
|
||||
return(result);
|
||||
|
@ -174,7 +175,7 @@ buffer_backify_next(Buffer_Backify_Loop *loop){
|
|||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){
|
||||
buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount, int *request_amount){
|
||||
char *data;
|
||||
int result;
|
||||
int size;
|
||||
|
@ -189,20 +190,20 @@ buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int
|
|||
data = (char*)buffer->data;
|
||||
memmove_4tech(data + end + *shift_amount, data + end, buffer->size - end);
|
||||
buffer->size += *shift_amount;
|
||||
data[buffer->size] = 0;
|
||||
if (len != 0) memcpy_4tech(data + start, str, len);
|
||||
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
result = *shift_amount + size;
|
||||
*request_amount = round_up_4tech(2*(*shift_amount + size), 4 << 10);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count){
|
||||
buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *sorted_edits, char *strings, int edit_count, int *request_amount){
|
||||
Buffer_Edit *edit;
|
||||
int i, result;
|
||||
int shift_total, shift_amount;
|
||||
|
@ -214,7 +215,7 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *s
|
|||
edit = sorted_edits + i;
|
||||
for (; i < edit_count; ++i, ++edit){
|
||||
result = buffer_replace_range(buffer, edit->start + shift_total, edit->end + shift_total,
|
||||
strings + edit->str_start, edit->len, &shift_amount);
|
||||
strings + edit->str_start, edit->len, &shift_amount, request_amount);
|
||||
if (result) break;
|
||||
shift_total += shift_amount;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct{
|
|||
float *line_widths;
|
||||
int *line_starts;
|
||||
int line_count;
|
||||
int widths_count;
|
||||
int line_max;
|
||||
int widths_max;
|
||||
} Multi_Gap_Buffer;
|
||||
|
@ -170,21 +171,27 @@ internal_4tech int
|
|||
buffer_find_chunk(Multi_Gap_Buffer *buffer, int pos){
|
||||
Fixed_Width_Gap_Buffer *gaps;
|
||||
int start, end, m, this_pos;
|
||||
|
||||
gaps = buffer->gaps;
|
||||
start = 0;
|
||||
end = buffer->chunk_count;
|
||||
for(;;){
|
||||
m = (start + end) / 2;
|
||||
this_pos = gaps[m].start_pos;
|
||||
if (this_pos < pos) start = m;
|
||||
else if (this_pos > pos) end = m;
|
||||
else break;
|
||||
if (start+1 == end){
|
||||
m = start; break;
|
||||
}
|
||||
assert_4tech(start < end);
|
||||
|
||||
if (pos == buffer_size(buffer)){
|
||||
m = buffer->chunk_count;
|
||||
}
|
||||
else{
|
||||
gaps = buffer->gaps;
|
||||
start = 0;
|
||||
end = buffer->chunk_count;
|
||||
for(;;){
|
||||
m = (start + end) / 2;
|
||||
this_pos = gaps[m].start_pos;
|
||||
if (this_pos < pos) start = m;
|
||||
else if (this_pos > pos) end = m;
|
||||
else break;
|
||||
if (start+1 == end){
|
||||
m = start; break;
|
||||
}
|
||||
assert_4tech(start < end);
|
||||
}
|
||||
}
|
||||
|
||||
return(m);
|
||||
}
|
||||
|
||||
|
@ -360,6 +367,84 @@ buffer_backify_next(Multi_Gap_Buffer_Backify_Loop *loop){
|
|||
}
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount_out, int *request_amount){
|
||||
Fixed_Width_Gap_Buffer *gaps, *gap;
|
||||
int gap_start, gap_end;
|
||||
int result;
|
||||
int size;
|
||||
int local_end;
|
||||
int shift_amount;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
assert_4tech(0 <= start);
|
||||
assert_4tech(start <= end);
|
||||
assert_4tech(end <= size);
|
||||
|
||||
*shift_amount_out = (len - (end - start));
|
||||
|
||||
gaps = buffer->gaps;
|
||||
gap_start = buffer_find_chunk(buffer, start);
|
||||
gap_end = buffer_find_chunk(buffer, end);
|
||||
|
||||
gap = gaps + gap_start;
|
||||
if (gap_start < gap_end){
|
||||
memmove_4tech(gap + 1, gaps + gap_end, sizeof(*gaps)*(buffer->chunk_count - gap_end));
|
||||
buffer->chunk_count -= (gap_end - gap_start + 1);
|
||||
++gap;
|
||||
|
||||
local_end = end - gap->start_pos;
|
||||
|
||||
if (gap->size1 >= local_end){
|
||||
gap->size2 -= (local_end - gap->size1);
|
||||
gap->size1 = 0;
|
||||
}
|
||||
else{
|
||||
memmove_4tech(gap->data, gap->data + local_end, gap->size1 - local_end);
|
||||
gap->size1 -= local_end;
|
||||
}
|
||||
|
||||
--gap;
|
||||
}
|
||||
if (end > gap->size1 + gap->size2) end = gap->size1 + gap->size2;
|
||||
|
||||
shift_amount = (len - (end - start));
|
||||
|
||||
if (shift_amount + gap->size1 + gap->size2 <= fixed_width_buffer_size){
|
||||
start -= gap->start_pos;
|
||||
end -= gap->start_pos;
|
||||
|
||||
data = gap->data;
|
||||
if (end < gap->size1){
|
||||
move_size = gap->size1 - end;
|
||||
memmove_4tech(data + gap->size1 + gap->gap_size - move_size, data + end, move_size);
|
||||
gap->size1 -= move_size;
|
||||
gap->size2 += move_size;
|
||||
}
|
||||
if (start > gap->size1){
|
||||
move_size = start - gap->size1;
|
||||
memmove_4tech(data + gap->size1, data + gap->size1 + gap->gap_size, move_size);
|
||||
gap->size1 += move_size;
|
||||
gap->size2 -= move_size;
|
||||
}
|
||||
|
||||
memcpy_4tech(data + start, str, len);
|
||||
gap->size2 = size - end;
|
||||
gap->size1 = start + len;
|
||||
gap->gap_size -= shift_amount;
|
||||
|
||||
assert_4tech(gap->size1 + gap->size2 == size + shift_amount);
|
||||
assert_4tech(gap->size1 + gap->gap_size + gap->size2 == gap->max);
|
||||
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
div_ceil_4tech(shift_amount, fixed_width_buffer_half_size);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -53,6 +53,19 @@
|
|||
#define cat_4tech(a,b) cat_4tech_(a,b)
|
||||
#endif
|
||||
|
||||
#ifndef round_up_4tech
|
||||
internal_4tech int
|
||||
lroundup_(int x, int granularity){
|
||||
int original_x;
|
||||
original_x = x;
|
||||
x /= granularity;
|
||||
x *= granularity;
|
||||
if (x < original_x) x += granularity;
|
||||
return x;
|
||||
}
|
||||
#define round_up_4tech(x,g) lroundup_(x,g)
|
||||
#endif
|
||||
|
||||
inline_4tech float
|
||||
measure_character(void *advance_data, int stride, char character){
|
||||
char *advances;
|
||||
|
|
144
win32_4ed.cpp
144
win32_4ed.cpp
|
@ -58,7 +58,7 @@
|
|||
#define FPS 30
|
||||
#define FRAME_TIME (1000000 / FPS)
|
||||
|
||||
#define BUFFER_EXPERIMENT_SCALPEL 2
|
||||
#define BUFFER_EXPERIMENT_SCALPEL 0
|
||||
|
||||
#include "4ed_meta.h"
|
||||
|
||||
|
@ -545,11 +545,18 @@ Win32Callback(HWND hwnd, UINT uMsg,
|
|||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
{
|
||||
bool8 previous_state, current_state;
|
||||
previous_state = ((lParam & Bit_30)?(1):(0));
|
||||
current_state = ((lParam & Bit_31)?(0):(1));
|
||||
Win32KeyboardHandle(current_state, previous_state, wParam);
|
||||
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
switch (wParam){
|
||||
case VK_CONTROL:case VK_LCONTROL:case VK_RCONTROL:
|
||||
case VK_MENU:case VK_LMENU:case VK_RMENU:
|
||||
case VK_SHIFT:case VK_LSHIFT:case VK_RSHIFT: break;
|
||||
|
||||
default:
|
||||
bool8 previous_state, current_state;
|
||||
previous_state = ((lParam & Bit_30)?(1):(0));
|
||||
current_state = ((lParam & Bit_31)?(0):(1));
|
||||
Win32KeyboardHandle(current_state, previous_state, wParam);
|
||||
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
|
@ -880,6 +887,131 @@ INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){
|
|||
}
|
||||
#endif
|
||||
|
||||
internal b32
|
||||
system_cli_call(char *path, char *script_name, CLI_Handles *cli_out){
|
||||
char cmd[] = "c:\\windows\\system32\\cmd.exe";
|
||||
char *env_variables = 0;
|
||||
char command_line[2048];
|
||||
|
||||
b32 success = 1;
|
||||
String s = make_fixed_width_string(command_line);
|
||||
copy(&s, make_lit_string("/C "));
|
||||
append_partial(&s, script_name);
|
||||
append_partial(&s, make_lit_string(".bat "));
|
||||
success = terminate_with_null(&s);
|
||||
|
||||
if (success){
|
||||
success = 0;
|
||||
|
||||
SECURITY_ATTRIBUTES sec_attributes;
|
||||
HANDLE out_read;
|
||||
HANDLE out_write;
|
||||
|
||||
sec_attributes = {};
|
||||
sec_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sec_attributes.bInheritHandle = TRUE;
|
||||
|
||||
if (CreatePipe(&out_read, &out_write, &sec_attributes, 0)){
|
||||
if (SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)){
|
||||
STARTUPINFO startup = {};
|
||||
startup.cb = sizeof(STARTUPINFO);
|
||||
startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||
startup.hStdError = out_write;
|
||||
startup.hStdOutput = out_write;
|
||||
startup.wShowWindow = SW_HIDE;
|
||||
|
||||
PROCESS_INFORMATION info = {};
|
||||
|
||||
Assert(sizeof(Plat_Handle) >= sizeof(HANDLE));
|
||||
if (CreateProcess(cmd, command_line,
|
||||
0, 0, TRUE, 0,
|
||||
env_variables, path,
|
||||
&startup, &info)){
|
||||
success = 1;
|
||||
CloseHandle(info.hThread);
|
||||
*(HANDLE*)&cli_out->proc = info.hProcess;
|
||||
*(HANDLE*)&cli_out->out_read = out_read;
|
||||
*(HANDLE*)&cli_out->out_write = out_write;
|
||||
}
|
||||
else{
|
||||
CloseHandle(out_read);
|
||||
CloseHandle(out_write);
|
||||
*(HANDLE*)&cli_out->proc = INVALID_HANDLE_VALUE;
|
||||
*(HANDLE*)&cli_out->out_read = INVALID_HANDLE_VALUE;
|
||||
*(HANDLE*)&cli_out->out_write = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
else{
|
||||
// TODO(allen): failed SetHandleInformation
|
||||
}
|
||||
}
|
||||
else{
|
||||
// TODO(allen): failed CreatePipe
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
struct CLI_Loop_Control{
|
||||
u32 remaining_amount;
|
||||
};
|
||||
|
||||
internal void
|
||||
system_cli_begin_update(CLI_Handles *cli){
|
||||
Assert(sizeof(cli->scratch_space) >= sizeof(CLI_Loop_Control));
|
||||
CLI_Loop_Control *loop = (CLI_Loop_Control*)cli->scratch_space;
|
||||
loop->remaining_amount = 0;
|
||||
}
|
||||
|
||||
internal b32
|
||||
system_cli_update_step(CLI_Handles *cli, char *dest, u32 max, u32 *amount){
|
||||
HANDLE handle = *(HANDLE*)&cli->out_read;
|
||||
CLI_Loop_Control *loop = (CLI_Loop_Control*)cli->scratch_space;
|
||||
b32 has_more = 0;
|
||||
DWORD remaining = loop->remaining_amount;
|
||||
u32 pos = 0;
|
||||
DWORD read_amount = 0;
|
||||
|
||||
for (;;){
|
||||
if (remaining == 0){
|
||||
if (!PeekNamedPipe(handle, 0, 0, 0, &remaining, 0)) break;
|
||||
if (remaining == 0) break;
|
||||
}
|
||||
|
||||
if (remaining + pos < max){
|
||||
has_more = 1;
|
||||
ReadFile(handle, dest + pos, remaining, &read_amount, 0);
|
||||
TentativeAssert(remaining == read_amount);
|
||||
pos += remaining;
|
||||
remaining = 0;
|
||||
}
|
||||
else{
|
||||
has_more = 1;
|
||||
ReadFile(handle, dest + pos, max - pos, &read_amount, 0);
|
||||
TentativeAssert(max - pos == read_amount);
|
||||
loop->remaining_amount = remaining - (max - pos);
|
||||
pos = max;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*amount = pos;
|
||||
|
||||
return has_more;
|
||||
}
|
||||
|
||||
internal b32
|
||||
system_cli_end_update(CLI_Handles *cli){
|
||||
b32 close_me = 0;
|
||||
if (WaitForSingleObject(*(HANDLE*)&cli->proc, 0) == WAIT_OBJECT_0){
|
||||
close_me = 1;
|
||||
CloseHandle(*(HANDLE*)&cli->proc);
|
||||
CloseHandle(*(HANDLE*)&cli->out_read);
|
||||
CloseHandle(*(HANDLE*)&cli->out_write);
|
||||
}
|
||||
return close_me;
|
||||
}
|
||||
|
||||
int
|
||||
WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
|
|
Loading…
Reference in New Issue