improvements to custom.cpp
This commit is contained in:
parent
7b6306683a
commit
18eda91724
|
@ -639,7 +639,7 @@ CUSTOM_COMMAND_SIG(execute_any_cli){
|
|||
hot_directory = make_fixed_width_string(even_more_space);
|
||||
hot_directory.size = app->directory_get_hot(app, hot_directory.str, hot_directory.memory_size);
|
||||
|
||||
push_parameter(app, par_cli_overlap_with_conflict, 1);
|
||||
push_parameter(app, par_cli_flags, CLI_OverlapWithConflict);
|
||||
push_parameter(app, par_name, bar_out.string.str, bar_out.string.size);
|
||||
push_parameter(app, par_cli_path, hot_directory.str, hot_directory.size);
|
||||
push_parameter(app, par_cli_command, bar_cmd.string.str, bar_cmd.string.size);
|
||||
|
@ -726,7 +726,7 @@ CUSTOM_COMMAND_SIG(build_at_launch_location){
|
|||
// An example of calling build by setting all
|
||||
// parameters directly. This only works if build.bat can be called
|
||||
// from the directory the application is launched at.
|
||||
push_parameter(app, par_cli_overlap_with_conflict, 1);
|
||||
push_parameter(app, par_cli_flags, CLI_OverlapWithConflict);
|
||||
push_parameter(app, par_name, literal("*compilation*"));
|
||||
push_parameter(app, par_cli_path, literal("."));
|
||||
push_parameter(app, par_cli_command, literal("build"));
|
||||
|
@ -743,21 +743,24 @@ CUSTOM_COMMAND_SIG(build_search){
|
|||
//
|
||||
// Step 2: app->file_exists queries the file system to see if "<somedir>/build.bat" exists.
|
||||
// If it does exist several parameters are pushed and cmdid_command_line is executed:
|
||||
// - par_cli_overlap_with_conflict: whether to launch this process if an existing process
|
||||
// is already being used for output on the same buffer
|
||||
// - par_cli_flags: flags for specifiying behaviors
|
||||
// CLI_OverlapWithConflict - (on by default) if another CLI is still using the output buffer
|
||||
// that process is detached from the buffer and this process executes outputing to the buffer
|
||||
// CLI_AlwaysBindToView - if set, the current view always switches to the output buffer
|
||||
// even if the output buffer is open in another view
|
||||
//
|
||||
// - par_name: the name of the buffer to fill with the output from the process
|
||||
// - par_buffer_id: the buffer_id of the buffer to to fill with output
|
||||
// If both are set buffer_id is used and the name is ignored.
|
||||
// If neither is set the command runs without storing output anywhere.
|
||||
//
|
||||
// - par_cli_path: sets the path from which the command is executed
|
||||
// If this parameter is unset the command runs from the hot directory.
|
||||
//
|
||||
// - par_cli_command: sets the actual command to be executed, this can be almost any command
|
||||
// that you could execute through a command line interface
|
||||
//
|
||||
//
|
||||
// To set par_cli_path: push_parameter makes a copy of the dir string on the stack
|
||||
// because the string allocated by push_directory is going to change again
|
||||
// To set par_cli_command: app->push_parameter does not make a copy of the dir because
|
||||
// dir isn't going to change again.
|
||||
// - par_cli_command: sets the actual command to be executed, this can be almost any
|
||||
// command that you could execute through a command line interface.
|
||||
// If this parameter is unset the command get's it's command from the range between
|
||||
// the mark and cursor.
|
||||
//
|
||||
// Step 3: If the batch file did not exist change the dir string to the parent directory using
|
||||
// app->directory_cd. The cd function can also be used to navigate to subdirectories.
|
||||
|
@ -778,7 +781,7 @@ CUSTOM_COMMAND_SIG(build_search){
|
|||
if (app->file_exists(app, dir.str, dir.size)){
|
||||
dir.size = old_size;
|
||||
|
||||
push_parameter(app, par_cli_overlap_with_conflict, 0);
|
||||
push_parameter(app, par_cli_flags, 0);
|
||||
push_parameter(app, par_name, literal("*compilation*"));
|
||||
push_parameter(app, par_cli_path, dir.str, dir.size);
|
||||
|
||||
|
@ -807,11 +810,43 @@ CUSTOM_COMMAND_SIG(write_and_auto_tab){
|
|||
exec_command(app, cmdid_auto_tab_line_at_cursor);
|
||||
}
|
||||
|
||||
// NOTE(allen|a4.0.0): scroll rule information
|
||||
//
|
||||
// The parameters:
|
||||
// target_x, target_y
|
||||
// This is where the view would like to be for the purpose of
|
||||
// following the cursor, doing mouse wheel work, etc.
|
||||
//
|
||||
// scroll_x, scroll_y
|
||||
// These are pointers to where the scrolling actually is. If you bind
|
||||
// the scroll rule it is you have to update these in some way to move
|
||||
// the actual location of the scrolling.
|
||||
//
|
||||
// view_id
|
||||
// This corresponds to which view is computing it's new scrolling position.
|
||||
// This id DOES correspond to the views that View_Summary contains.
|
||||
// This will always be between 1 and 16 (0 is a null id).
|
||||
// See below for an example of having state that carries across scroll udpates.
|
||||
//
|
||||
// is_new_target
|
||||
// If the target of the view is different from the last target in either x or y
|
||||
// this is true, otherwise it is false.
|
||||
//
|
||||
// The return:
|
||||
// Should be true if and only if scroll_x or scroll_y are changed.
|
||||
//
|
||||
// Don't try to use the app pointer in a scroll rule, you're asking for trouble.
|
||||
//
|
||||
// If you don't bind scroll_rule, nothing bad will happen, yo will get default
|
||||
// 4coder scrolling behavior.
|
||||
//
|
||||
|
||||
struct Scroll_Velocity{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
Scroll_Velocity scroll_velocity[16] = {0};
|
||||
Scroll_Velocity scroll_velocity_[16] = {0};
|
||||
Scroll_Velocity *scroll_velocity = scroll_velocity_;
|
||||
|
||||
static int
|
||||
smooth_camera_step(float target, float *current, float *vel, float S, float T){
|
||||
|
@ -844,7 +879,7 @@ smooth_camera_step(float target, float *current, float *vel, float S, float T){
|
|||
return result;
|
||||
}
|
||||
|
||||
extern "C" SCROLL_RULE_SIG(scroll_rule){
|
||||
SCROLL_RULE_SIG(smooth_scroll_rule){
|
||||
Scroll_Velocity *velocity = scroll_velocity + view_id;
|
||||
int result = 0;
|
||||
if (velocity->x == 0.f){
|
||||
|
@ -870,6 +905,7 @@ extern "C" GET_BINDING_DATA(get_bindings){
|
|||
// global 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);
|
||||
|
||||
begin_map(context, mapid_global);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include "4coder_version.h"
|
||||
#include "4coder_keycodes.h"
|
||||
#include "4coder_buffer_types.h"
|
||||
|
||||
|
@ -218,7 +219,6 @@ enum Command_ID{
|
|||
cmdid_page_up,
|
||||
cmdid_page_down,
|
||||
cmdid_open_color_tweaker,
|
||||
cmdid_close_minor_view,
|
||||
cmdid_cursor_mark_swap,
|
||||
cmdid_open_menu,
|
||||
cmdid_set_settings,
|
||||
|
@ -238,13 +238,17 @@ enum Param_ID{
|
|||
par_key_mapid,
|
||||
par_cli_path,
|
||||
par_cli_command,
|
||||
par_cli_overlap_with_conflict,
|
||||
par_cli_always_bind_to_view,
|
||||
par_cli_flags,
|
||||
par_clear_blank_lines,
|
||||
// never below this
|
||||
par_type_count
|
||||
};
|
||||
|
||||
#define CLI_OverlapWithConflict 0x1
|
||||
#define CLI_AlwaysBindToView 0x2
|
||||
|
||||
// These are regular hooks, any of them can be set to any function
|
||||
// that matches the HOOK_SIG pattern.
|
||||
enum Hook_ID{
|
||||
hook_start,
|
||||
hook_open_file,
|
||||
|
@ -252,6 +256,12 @@ enum Hook_ID{
|
|||
hook_type_count
|
||||
};
|
||||
|
||||
// These are for special hooks, each must bind to specialized signatures
|
||||
// that do not necessarily have access to the app pointer.
|
||||
enum Special_Hook_ID{
|
||||
_hook_scroll_rule = hook_type_count,
|
||||
};
|
||||
|
||||
// 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.
|
||||
|
@ -474,7 +484,6 @@ struct Application_Links{
|
|||
|
||||
struct Custom_API{
|
||||
Get_Binding_Data_Function *get_bindings;
|
||||
Scroll_Rule_Function *scroll_rule;
|
||||
};
|
||||
|
||||
// NOTE(allen): definitions for the buffer that communicates to 4ed.exe
|
||||
|
@ -517,7 +526,7 @@ struct Binding_Unit{
|
|||
} callback;
|
||||
struct{
|
||||
int hook_id;
|
||||
Custom_Command_Function *func;
|
||||
void *func;
|
||||
} hook;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -162,6 +162,16 @@ set_hook(Bind_Helper *helper, int hook_id, Custom_Command_Function *func){
|
|||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
set_scroll_rule(Bind_Helper *helper, Scroll_Rule_Function *func){
|
||||
Binding_Unit unit;
|
||||
unit.type = unit_hook;
|
||||
unit.hook.hook_id = _hook_scroll_rule;
|
||||
unit.hook.func = func;
|
||||
|
||||
write_unit(helper, unit);
|
||||
}
|
||||
|
||||
inline void
|
||||
end_bind_helper(Bind_Helper *helper){
|
||||
if (helper->header){
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#define MAJOR 3
|
||||
#define MINOR 4
|
||||
#define PATCH 5
|
220
4ed.cpp
220
4ed.cpp
|
@ -194,7 +194,7 @@ panel_make_empty(System_Functions *system, Exchange *exchange, App_Vars *vars, P
|
|||
View_And_ID new_view;
|
||||
|
||||
Assert(panel->view == 0);
|
||||
new_view = live_set_alloc_view(&vars->live_set, models->config_api.scroll_rule);
|
||||
new_view = live_set_alloc_view(&vars->live_set);
|
||||
panel->view = new_view.view;
|
||||
panel->view->panel = panel;
|
||||
|
||||
|
@ -539,7 +539,7 @@ COMMAND_DECL(word_complete){
|
|||
|
||||
COMMAND_DECL(set_mark){
|
||||
ProfileMomentFunction();
|
||||
REQ_OPEN_VIEW(view);
|
||||
USE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
||||
view->mark = (i32)view->cursor.pos;
|
||||
|
@ -548,7 +548,7 @@ COMMAND_DECL(set_mark){
|
|||
COMMAND_DECL(copy){
|
||||
ProfileMomentFunction();
|
||||
USE_MODELS(models);
|
||||
REQ_OPEN_VIEW(view);
|
||||
USE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
||||
// TODO(allen): deduplicate
|
||||
|
@ -755,7 +755,7 @@ COMMAND_DECL(history_forward){
|
|||
COMMAND_DECL(interactive_new){
|
||||
ProfileMomentFunction();
|
||||
USE_MODELS(models);
|
||||
REQ_OPEN_VIEW(view);
|
||||
USE_VIEW(view);
|
||||
|
||||
view_show_interactive(system, view, &models->map_ui,
|
||||
IAct_New, IInt_Sys_File_List, make_lit_string("New: "));
|
||||
|
@ -813,7 +813,7 @@ COMMAND_DECL(interactive_open){
|
|||
ProfileMomentFunction();
|
||||
USE_MODELS(models);
|
||||
USE_PANEL(panel);
|
||||
REQ_OPEN_VIEW(view);
|
||||
USE_VIEW(view);
|
||||
|
||||
Delay *delay = &models->delay1;
|
||||
|
||||
|
@ -846,9 +846,6 @@ COMMAND_DECL(interactive_open){
|
|||
}
|
||||
}
|
||||
else{
|
||||
View *view = panel->view;
|
||||
Assert(view);
|
||||
|
||||
view_show_interactive(system, view, &models->map_ui,
|
||||
IAct_Open, IInt_Sys_File_List, make_lit_string("Open: "));
|
||||
}
|
||||
|
@ -1537,7 +1534,7 @@ COMMAND_DECL(close_minor_view){
|
|||
if (view->file){
|
||||
map = app_get_map(models, view->file->settings.base_map_id);
|
||||
}
|
||||
view_show_file(view, map);
|
||||
view_show_file(view, map, view->file);
|
||||
}
|
||||
|
||||
COMMAND_DECL(cursor_mark_swap){
|
||||
|
@ -1625,22 +1622,23 @@ COMMAND_DECL(set_settings){
|
|||
}
|
||||
}
|
||||
|
||||
#define CLI_OverlapWithConflict (1<<0)
|
||||
#define CLI_AlwaysBindToView (2<<0)
|
||||
|
||||
COMMAND_DECL(command_line){
|
||||
ProfileMomentFunction();
|
||||
USE_VARS(vars);
|
||||
USE_MODELS(models);
|
||||
USE_PANEL(panel);
|
||||
USE_VIEW(view);
|
||||
|
||||
Partition *part = &models->mem.part;
|
||||
|
||||
char *buffer_name = 0;
|
||||
char *path = 0;
|
||||
char *script = 0;
|
||||
|
||||
int buffer_name_len = 0;
|
||||
int path_len = 0;
|
||||
int script_len = 0;
|
||||
i32 buffer_id = 0;
|
||||
i32 buffer_name_len = 0;
|
||||
i32 path_len = 0;
|
||||
i32 script_len = 0;
|
||||
u32 flags = CLI_OverlapWithConflict;
|
||||
|
||||
Command_Parameter *end = param_stack_end(&command->part);
|
||||
|
@ -1650,115 +1648,135 @@ COMMAND_DECL(command_line){
|
|||
switch (p){
|
||||
case par_name:
|
||||
{
|
||||
if (buffer_name == 0){
|
||||
char *new_buffer_name = dynamic_to_string(¶m->param.value, &buffer_name_len);
|
||||
if (new_buffer_name){
|
||||
buffer_name = new_buffer_name;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case par_buffer_id:
|
||||
{
|
||||
buffer_id = dynamic_to_int(¶m->param.value);
|
||||
}break;
|
||||
|
||||
case par_cli_path:
|
||||
{
|
||||
if (path == 0){
|
||||
char *new_cli_path = dynamic_to_string(¶m->param.value, &path_len);
|
||||
if (new_cli_path){
|
||||
path = new_cli_path;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case par_cli_command:
|
||||
{
|
||||
if (script == 0){
|
||||
char *new_command = dynamic_to_string(¶m->param.value, &script_len);
|
||||
if (new_command){
|
||||
script = new_command;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case par_cli_overlap_with_conflict:
|
||||
case par_cli_flags:
|
||||
{
|
||||
if (dynamic_to_int(¶m->param.value))
|
||||
flags |= CLI_OverlapWithConflict;
|
||||
else
|
||||
flags &= (~CLI_OverlapWithConflict);
|
||||
}break;
|
||||
|
||||
case par_cli_always_bind_to_view:
|
||||
{
|
||||
if (dynamic_to_int(¶m->param.value))
|
||||
flags |= CLI_OverlapWithConflict;
|
||||
else
|
||||
flags &= (~CLI_OverlapWithConflict);
|
||||
flags = (u32)dynamic_to_int(¶m->param.value);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Working_Set *working_set = &models->working_set;
|
||||
Editing_File *file;
|
||||
i32 index = 0;
|
||||
b32 bind_to_new_view;
|
||||
|
||||
if (buffer_name == 0 || path == 0 || script == 0){
|
||||
return;
|
||||
}
|
||||
CLI_Process *procs = vars->cli_processes.procs, *proc = 0;
|
||||
Get_File_Result file = {};
|
||||
b32 bind_to_new_view = 1;
|
||||
|
||||
if (vars->cli_processes.count < vars->cli_processes.max){
|
||||
file = working_set_contains(working_set, make_string_slowly(buffer_name));
|
||||
bind_to_new_view = 1;
|
||||
|
||||
if (!file){
|
||||
Get_File_Result get_file = working_set_get_available_file(working_set);
|
||||
file = get_file.file;
|
||||
index = get_file.index;
|
||||
if (buffer_id){
|
||||
if (buffer_id > 0 && buffer_id < working_set->file_index_count){
|
||||
file.file = working_set->files + buffer_id;
|
||||
file.index = buffer_id;
|
||||
}
|
||||
}
|
||||
else{
|
||||
file.file = working_set_contains(working_set, make_string(buffer_name, buffer_name_len));
|
||||
file.index = (i32)(file.file - working_set->files);
|
||||
if (file.file == 0)
|
||||
file = working_set_get_available_file(working_set);
|
||||
}
|
||||
|
||||
if (file.file){
|
||||
i32 proc_count = vars->cli_processes.count;
|
||||
for (i32 i = 0; i < proc_count; ++i){
|
||||
if (vars->cli_processes.procs[i].out_file == file){
|
||||
View_Iter iter;
|
||||
i32 i;
|
||||
|
||||
for (i = 0; i < proc_count; ++i){
|
||||
if (procs[i].out_file == file.file){
|
||||
if (flags & CLI_OverlapWithConflict)
|
||||
vars->cli_processes.procs[i].out_file = 0;
|
||||
else file = 0;
|
||||
procs[i].out_file = 0;
|
||||
else
|
||||
file.file = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
index = (i32)(file - models->working_set.files);
|
||||
if (file){
|
||||
|
||||
if (file.file){
|
||||
if (!(flags & CLI_AlwaysBindToView)){
|
||||
View_Iter iter;
|
||||
iter = file_view_iter_init(&models->layout, file, 0);
|
||||
iter = file_view_iter_init(&models->layout, file.file, 0);
|
||||
if (file_view_iter_good(iter)){
|
||||
bind_to_new_view = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file){
|
||||
file_create_super_locked(system, models, file, buffer_name);
|
||||
file->settings.unimportant = 1;
|
||||
table_add(&working_set->table, file->name.source_path, index);
|
||||
|
||||
if (bind_to_new_view){
|
||||
view_file_in_panel(command, panel, file);
|
||||
}
|
||||
|
||||
i32 i = vars->cli_processes.count++;
|
||||
CLI_Process *proc = vars->cli_processes.procs + i;
|
||||
if (!system->cli_call(path, script, &proc->cli)){
|
||||
--vars->cli_processes.count;
|
||||
}
|
||||
proc->out_file = file;
|
||||
file_create_super_locked(system, models, file.file, buffer_name);
|
||||
file.file->settings.unimportant = 1;
|
||||
table_add(&working_set->table, file.file->name.source_path, file.index);
|
||||
}
|
||||
else{
|
||||
// TODO(allen): feedback message - no available file
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!path){
|
||||
path = models->hot_directory.string.str;
|
||||
terminate_with_null(&models->hot_directory.string);
|
||||
}
|
||||
|
||||
{
|
||||
Temp_Memory temp;
|
||||
Range range;
|
||||
Editing_File *view_file;
|
||||
i32 size;
|
||||
|
||||
temp = begin_temp_memory(part);
|
||||
if (!script){
|
||||
view_file = view->file;
|
||||
if (view_file){
|
||||
range = make_range(view->cursor.pos, view->mark);
|
||||
size = range.end - range.start;
|
||||
script = push_array(part, char, size + 1);
|
||||
buffer_stringify(&view_file->state.buffer, range.start, range.end, script);
|
||||
script[size] = 0;
|
||||
}
|
||||
else{
|
||||
script = " echo no script specified";
|
||||
}
|
||||
}
|
||||
|
||||
if (bind_to_new_view){
|
||||
view_file_in_panel(command, panel, file.file);
|
||||
}
|
||||
|
||||
proc = procs + vars->cli_processes.count++;
|
||||
proc->out_file = file.file;
|
||||
|
||||
if (!system->cli_call(path, script, &proc->cli)){
|
||||
--vars->cli_processes.count;
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
}
|
||||
else{
|
||||
// TODO(allen): feedback message - no available process slot
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1793,14 +1811,21 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor
|
|||
internal void
|
||||
fill_view_summary(View_Summary *view, View *file_view, Live_Views *live_set, Working_Set *working_set){
|
||||
view->exists = 1;
|
||||
view->view_id = (int)((char*)file_view - (char*)live_set->views) / live_set->stride;
|
||||
view->view_id = (int)(file_view - live_set->views) + 1;
|
||||
view->line_height = file_view->font_height;
|
||||
view->unwrapped_lines = file_view->unwrapped_lines;
|
||||
|
||||
if (file_view->file){
|
||||
view->buffer_id = (int)(file_view->file - working_set->files);
|
||||
view->mark = view_compute_cursor_from_pos(file_view, file_view->mark);
|
||||
view->cursor = file_view->cursor;
|
||||
view->preferred_x = file_view->preferred_x;
|
||||
view->line_height = file_view->font_height;
|
||||
view->unwrapped_lines = file_view->unwrapped_lines;
|
||||
}
|
||||
else{
|
||||
view->buffer_id = 0;
|
||||
view->mark = {};
|
||||
view->cursor = {};
|
||||
view->preferred_x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2084,7 +2109,7 @@ extern "C"{
|
|||
GET_VIEW_MAX_INDEX_SIG(external_get_view_max_index){
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Live_Views *live_set = cmd->live_set;
|
||||
int max = live_set->max;
|
||||
int max = live_set->max + 1;
|
||||
return(max);
|
||||
}
|
||||
|
||||
|
@ -2095,8 +2120,9 @@ extern "C"{
|
|||
int max = live_set->max;
|
||||
View *vptr;
|
||||
|
||||
index -= 1;
|
||||
if (index >= 0 && index < max){
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride*index);
|
||||
vptr = live_set->views + index;
|
||||
fill_view_summary(&view, vptr, live_set, &cmd->models->working_set);
|
||||
}
|
||||
|
||||
|
@ -2127,7 +2153,7 @@ extern "C"{
|
|||
|
||||
if (view->exists){
|
||||
live_set = cmd->live_set;
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
|
||||
vptr = live_set->views + view->view_id;
|
||||
result = 1;
|
||||
if (seek.type == buffer_seek_line_char && seek.character <= 0){
|
||||
seek.character = 1;
|
||||
|
@ -2151,7 +2177,7 @@ extern "C"{
|
|||
|
||||
if (view->exists){
|
||||
live_set = cmd->live_set;
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
|
||||
vptr = live_set->views + view->view_id;
|
||||
result = 1;
|
||||
if (seek.type == buffer_seek_line_char && seek.character <= 0){
|
||||
seek.character = 1;
|
||||
|
@ -2177,7 +2203,7 @@ extern "C"{
|
|||
|
||||
if (view->exists){
|
||||
live_set = cmd->live_set;
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
|
||||
vptr = live_set->views + view->view_id;
|
||||
result = 1;
|
||||
if (turn_on){
|
||||
view_set_temp_highlight(vptr, start, end);
|
||||
|
@ -2203,7 +2229,7 @@ extern "C"{
|
|||
if (view->exists){
|
||||
models = cmd->models;
|
||||
live_set = cmd->live_set;
|
||||
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
|
||||
vptr = live_set->views + view->view_id;
|
||||
working_set = &models->working_set;
|
||||
max = working_set->file_index_count;
|
||||
if (buffer_id >= 0 && buffer_id < max){
|
||||
|
@ -2346,7 +2372,7 @@ setup_file_commands(Command_Map *commands, Partition *part, Command_Map *parent)
|
|||
|
||||
internal void
|
||||
setup_top_commands(Command_Map *commands, Partition *part, Command_Map *parent){
|
||||
map_init(commands, part, 5, parent);
|
||||
map_init(commands, part, 10, parent);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -2412,7 +2438,6 @@ setup_command_table(){
|
|||
SET(page_up);
|
||||
SET(page_down);
|
||||
SET(open_color_tweaker);
|
||||
SET(close_minor_view);
|
||||
SET(cursor_mark_swap);
|
||||
SET(open_menu);
|
||||
SET(set_settings);
|
||||
|
@ -2877,25 +2902,21 @@ App_Init_Sig(app_init){
|
|||
}
|
||||
|
||||
{
|
||||
char *vptr = 0;
|
||||
View *v = 0;
|
||||
View *vptr = 0;
|
||||
i32 i = 0;
|
||||
i32 max = 0;
|
||||
i32 view_size = sizeof(View);
|
||||
|
||||
vars->live_set.count = 0;
|
||||
vars->live_set.max = panel_max_count;
|
||||
|
||||
vars->live_set.stride = view_size;
|
||||
vars->live_set.views = push_block(partition, view_size*vars->live_set.max);
|
||||
vars->live_set.views = push_array(partition, View, vars->live_set.max);
|
||||
|
||||
dll_init_sentinel(&vars->live_set.free_sentinel);
|
||||
|
||||
max = vars->live_set.max;
|
||||
vptr = (char*)vars->live_set.views;
|
||||
for (i = 0; i < max; ++i, vptr += view_size){
|
||||
v = (View*)(vptr);
|
||||
dll_insert(&vars->live_set.free_sentinel, v);
|
||||
vptr = vars->live_set.views;
|
||||
for (i = 0; i < max; ++i, ++vptr){
|
||||
dll_insert(&vars->live_set.free_sentinel, vptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2905,9 +2926,7 @@ App_Init_Sig(app_init){
|
|||
b32 did_top = 0;
|
||||
b32 did_file = 0;
|
||||
|
||||
if (models->config_api.scroll_rule == 0){
|
||||
models->config_api.scroll_rule = fallback_scroll_rule;
|
||||
}
|
||||
models->scroll_rule = fallback_scroll_rule;
|
||||
|
||||
setup_command_table();
|
||||
|
||||
|
@ -3010,8 +3029,13 @@ App_Init_Sig(app_init){
|
|||
case unit_hook:
|
||||
{
|
||||
int hook_id = unit->hook.hook_id;
|
||||
if (hook_id >= 0 && hook_id < hook_type_count){
|
||||
models->hooks[hook_id] = unit->hook.func;
|
||||
if (hook_id >= 0){
|
||||
if (hook_id < hook_type_count){
|
||||
models->hooks[hook_id] = (Hook_Function*)unit->hook.func;
|
||||
}
|
||||
else{
|
||||
models->scroll_rule = (Scroll_Rule_Function*)unit->hook.func;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ struct App_Models{
|
|||
Panel *prev_mouse_panel;
|
||||
|
||||
Custom_API config_api;
|
||||
Scroll_Rule_Function *scroll_rule;
|
||||
};
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -28,12 +28,6 @@ struct View_Mode{
|
|||
i32 rewrite;
|
||||
};
|
||||
|
||||
struct Incremental_Search{
|
||||
String str;
|
||||
b32 reverse;
|
||||
i32 pos;
|
||||
};
|
||||
|
||||
enum View_Widget_Type{
|
||||
FWIDG_NONE,
|
||||
FWIDG_TIMELINES,
|
||||
|
@ -76,7 +70,6 @@ struct View{
|
|||
|
||||
Panel *panel;
|
||||
Command_Map *map;
|
||||
Scroll_Rule_Function *scroll_rule;
|
||||
i32 id;
|
||||
|
||||
Editing_File *file;
|
||||
|
@ -130,22 +123,13 @@ struct View{
|
|||
i32 scroll_i;
|
||||
f32 scroll_min_limit;
|
||||
|
||||
union{
|
||||
Incremental_Search isearch;
|
||||
struct{
|
||||
String str;
|
||||
} gotoline;
|
||||
};
|
||||
|
||||
Full_Cursor temp_highlight;
|
||||
i32 temp_highlight_end_pos;
|
||||
b32 show_temp_highlight;
|
||||
|
||||
View_Mode mode, next_mode;
|
||||
View_Widget widget;
|
||||
|
||||
Query_Set query_set;
|
||||
|
||||
i32 scrub_max;
|
||||
|
||||
b32 unwrapped_lines;
|
||||
|
@ -594,20 +578,18 @@ file_create_empty(
|
|||
b32 result = 1;
|
||||
String empty_str = {};
|
||||
file_create_from_string(system, mem, working_set, file, filename, set, font_id, empty_str);
|
||||
return result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
file_create_super_locked(
|
||||
System_Functions *system,
|
||||
App_Models *models,
|
||||
Editing_File *file,
|
||||
char *filename){
|
||||
System_Functions *system, App_Models *models,
|
||||
Editing_File *file, char *filename){
|
||||
b32 result = 1;
|
||||
String empty_str = {};
|
||||
file_create_from_string(system, &models->mem, &models->working_set,
|
||||
file, filename, models->font_set, models->global_font.font_id, empty_str, 1);
|
||||
return result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
struct Get_File_Result{
|
||||
|
@ -615,6 +597,7 @@ struct Get_File_Result{
|
|||
i32 index;
|
||||
};
|
||||
|
||||
// TODO(allen): convert buffers to a dll allocation scheme
|
||||
internal Get_File_Result
|
||||
working_set_get_available_file(Working_Set *working_set){
|
||||
Get_File_Result result = {};
|
||||
|
@ -2641,22 +2624,23 @@ view_show_config(View *fview, Command_Map *gui_map){
|
|||
}
|
||||
|
||||
inline void
|
||||
view_show_interactive(System_Functions *system, View *fview, Command_Map *gui_map,
|
||||
view_show_interactive(System_Functions *system, View *view, Command_Map *gui_map,
|
||||
Interactive_Action action, Interactive_Interaction interaction, String query){
|
||||
fview->ui_state = {};
|
||||
fview->map_for_file = fview->map;
|
||||
fview->map = gui_map;
|
||||
fview->locked = 1;
|
||||
fview->showing_ui = VUI_Interactive;
|
||||
fview->action = action;
|
||||
fview->interaction = interaction;
|
||||
fview->finished = 0;
|
||||
view->ui_state = {};
|
||||
view->map_for_file = view->map;
|
||||
view->map = gui_map;
|
||||
view->locked = 1;
|
||||
view->showing_ui = VUI_Interactive;
|
||||
view->action = action;
|
||||
view->interaction = interaction;
|
||||
view->finished = 0;
|
||||
|
||||
copy(&fview->query, query);
|
||||
fview->dest.size = 0;
|
||||
copy(&view->query, query);
|
||||
view->dest.str[0] = 0;
|
||||
view->dest.size = 0;
|
||||
|
||||
hot_directory_clean_end(fview->hot_directory);
|
||||
hot_directory_reload(system, fview->hot_directory, fview->working_set);
|
||||
hot_directory_clean_end(view->hot_directory);
|
||||
hot_directory_reload(system, view->hot_directory, view->working_set);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -2670,21 +2654,23 @@ view_show_theme(View *fview, Command_Map *gui_map){
|
|||
}
|
||||
|
||||
inline void
|
||||
view_show_file(View *fview, Command_Map *file_map){
|
||||
fview->ui_state = {};
|
||||
view_show_file(View *view, Command_Map *file_map, Editing_File *file){
|
||||
view->ui_state = {};
|
||||
if (file_map){
|
||||
fview->map = file_map;
|
||||
view->map = file_map;
|
||||
}
|
||||
else{
|
||||
fview->map = fview->map_for_file;
|
||||
view->map = view->map_for_file;
|
||||
}
|
||||
fview->locked = 0;
|
||||
fview->showing_ui = VUI_None;
|
||||
view->file = file;
|
||||
view->locked = 0;
|
||||
view->showing_ui = VUI_None;
|
||||
}
|
||||
|
||||
internal void
|
||||
interactive_view_complete(View *view){
|
||||
Panel *panel = view->panel;
|
||||
Editing_File *file = 0;
|
||||
switch (view->action){
|
||||
case IAct_Open:
|
||||
delayed_open(view->delay, view->hot_directory->string, panel);
|
||||
|
@ -2692,6 +2678,7 @@ interactive_view_complete(View *view){
|
|||
|
||||
case IAct_Save_As:
|
||||
delayed_save_as(view->delay, view->hot_directory->string, panel);
|
||||
file = view->file;
|
||||
break;
|
||||
|
||||
case IAct_New:
|
||||
|
@ -2704,6 +2691,7 @@ interactive_view_complete(View *view){
|
|||
|
||||
case IAct_Kill:
|
||||
delayed_try_kill(view->delay, view->dest, panel);
|
||||
file = view->file;
|
||||
break;
|
||||
|
||||
case IAct_Sure_To_Kill:
|
||||
|
@ -2723,7 +2711,7 @@ interactive_view_complete(View *view){
|
|||
}
|
||||
break;
|
||||
}
|
||||
view_show_file(view, 0);
|
||||
view_show_file(view, 0, 0);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -3471,7 +3459,7 @@ step_file_view(System_Functions *system, Exchange *exchange, View *view, i32_Rec
|
|||
}
|
||||
|
||||
// TODO(allen): Split this into passive step and step that depends on input
|
||||
if (file && !file->state.is_loading){
|
||||
if (view->showing_ui == VUI_None && file && !file->state.is_loading){
|
||||
f32 line_height = (f32)view->font_height;
|
||||
f32 cursor_y = view_get_cursor_y(view);
|
||||
f32 target_y = view->target_y;
|
||||
|
@ -3531,10 +3519,10 @@ step_file_view(System_Functions *system, Exchange *exchange, View *view, i32_Rec
|
|||
if (view->target_x != view->prev_target_x) is_new_target = 1;
|
||||
if (view->target_y != view->prev_target_y) is_new_target = 1;
|
||||
|
||||
if (view->scroll_rule(
|
||||
if (view->models->scroll_rule(
|
||||
view->target_x, view->target_y,
|
||||
&view->scroll_x, &view->scroll_y,
|
||||
view->id, is_new_target)){
|
||||
view->id + 1, is_new_target)){
|
||||
result = 1;
|
||||
}
|
||||
|
||||
|
@ -4166,20 +4154,18 @@ view_change_size(System_Functions *system, General_Memory *general, View *view){
|
|||
}
|
||||
|
||||
struct Live_Views{
|
||||
void *views;
|
||||
View *views;
|
||||
View free_sentinel;
|
||||
i32 count, max;
|
||||
i32 stride;
|
||||
};
|
||||
|
||||
internal View*
|
||||
inline View*
|
||||
live_set_get_view(Live_Views *live_set, i32 id){
|
||||
void *result = ((char*)live_set->views + id);
|
||||
return (View*)result;
|
||||
return (live_set->views + id);
|
||||
}
|
||||
|
||||
internal View_And_ID
|
||||
live_set_alloc_view(Live_Views *live_set, Scroll_Rule_Function *scroll_rule){
|
||||
live_set_alloc_view(Live_Views *live_set){
|
||||
View_And_ID result = {};
|
||||
|
||||
Assert(live_set->count < live_set->max);
|
||||
|
@ -4190,8 +4176,7 @@ live_set_alloc_view(Live_Views *live_set, Scroll_Rule_Function *scroll_rule){
|
|||
result.view->id = result.id;
|
||||
|
||||
dll_remove(result.view);
|
||||
memset(result.view, 0, live_set->stride);
|
||||
result.view->scroll_rule = scroll_rule;
|
||||
memset(result.view, 0, sizeof(View));
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ char* generate_keycode_enum(){
|
|||
return(filename);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
char daction_enum_name[] = "Action_Type";
|
||||
char *daction_enum[] = {
|
||||
"OPEN",
|
||||
|
@ -272,15 +273,63 @@ char* generate_delayed_action(){
|
|||
return(filename);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define MAJOR 3
|
||||
#define MINOR 4
|
||||
#define PATCH 5
|
||||
|
||||
#define VERS3__(a,b,c) #a"."#b"."#c
|
||||
#define VERS3_(a,b,c) VERS3__(a,b,c)
|
||||
#define VERS3 VERS3_(MAJOR, MINOR, PATCH)
|
||||
|
||||
#define VERSION_STRING VERS3
|
||||
|
||||
char version_header[] =
|
||||
"#define MAJOR %d\n"
|
||||
"#define MINOR %d\n"
|
||||
"#define PATCH %d\n"
|
||||
"#define VERSION_NUMBER \"alpha %s\"\n"
|
||||
"#ifdef FRED_SUPER\n"
|
||||
"#define VERSION_TYPE \" super!\"\n"
|
||||
"#else\n"
|
||||
"#define VERSION_TYPE \"\"\n"
|
||||
"#endif\n"
|
||||
"#define VERSION VERSION_NUMBER VERSION_TYPE\n";
|
||||
|
||||
char version_custom[] =
|
||||
"#define MAJOR %d\n"
|
||||
"#define MINOR %d\n"
|
||||
"#define PATCH %d\n";
|
||||
|
||||
char* generate_version(){
|
||||
char *filename = "4ed_version.h & 4coder_version.h";
|
||||
char filename_header[] = "4ed_version.h";
|
||||
char filename_custom[] = "4coder_version.h";
|
||||
FILE *file;
|
||||
|
||||
file = fopen(filename_header, "wb");
|
||||
fprintf(file, version_header, MAJOR, MINOR, PATCH, VERSION_STRING);
|
||||
fclose(file);
|
||||
|
||||
file = fopen(filename_custom, "wb");
|
||||
fprintf(file, version_custom, MAJOR, MINOR, PATCH);
|
||||
fclose(file);
|
||||
|
||||
return(filename);
|
||||
}
|
||||
|
||||
|
||||
int main(){
|
||||
char *filename;
|
||||
|
||||
|
||||
filename = generate_keycode_enum();
|
||||
printf("gen success: %s\n", filename);
|
||||
|
||||
filename = generate_delayed_action();
|
||||
printf("gen success: %s\n", filename);
|
||||
|
||||
filename = generate_version();
|
||||
printf("gen success: %s\n", filename);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
// 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
|
||||
// ...
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
|
@ -35,6 +38,7 @@ dll_remove(T *v){
|
|||
v->prev->next = v->next;
|
||||
}
|
||||
|
||||
// for(dll_items(iterator, sentinel_ptr)){...}
|
||||
#define dll_items(it, st) ((it) = (st)->next); ((it) != (st)); ((it) = (it)->next)
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -1,19 +1,10 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 01.03.2016
|
||||
*
|
||||
* Shared header for version stuff
|
||||
*
|
||||
*/
|
||||
|
||||
#define VERSION_NUMBER "alpha 3.4.4"
|
||||
|
||||
#define MAJOR 3
|
||||
#define MINOR 4
|
||||
#define PATCH 5
|
||||
#define VERSION_NUMBER "alpha 3.4.5"
|
||||
#ifdef FRED_SUPER
|
||||
#define VERSION_TYPE " super!"
|
||||
#else
|
||||
#define VERSION_TYPE ""
|
||||
#endif
|
||||
|
||||
#define VERSION VERSION_NUMBER VERSION_TYPE
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ SET clset=64
|
|||
SET WARNINGS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /WX
|
||||
SET STUFF=/GR- /nologo
|
||||
SET DEBUG=/Zi
|
||||
SET EXPORTS=/EXPORT:get_bindings /EXPORT:scroll_rule
|
||||
SET EXPORTS=/EXPORT:get_bindings
|
||||
SET SRC=4coder_custom.cpp
|
||||
|
||||
cl %WARNINGS% %STUFF% %DEBUG% %SRC% /Fe4coder_custom /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS%
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "4ed_config.h"
|
||||
|
||||
|
||||
#include "4ed_meta.h"
|
||||
|
||||
#define FCPP_FORBID_MALLOC
|
||||
|
|
|
@ -1743,9 +1743,6 @@ main(int argc, char **argv){
|
|||
if (win32vars.custom){
|
||||
win32vars.custom_api.get_bindings = (Get_Binding_Data_Function*)
|
||||
GetProcAddress(win32vars.custom, "get_bindings");
|
||||
|
||||
win32vars.custom_api.scroll_rule = (Scroll_Rule_Function*)
|
||||
GetProcAddress(win32vars.custom, "scroll_rule");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue