2016-02-01 05:03:42 +00:00
2016-03-04 06:06:11 +00:00
# include "4coder_version.h"
2016-02-25 23:52:11 +00:00
# include "4coder_keycodes.h"
2016-03-04 23:10:00 +00:00
# include "4coder_style.h"
2016-02-24 05:16:08 +00:00
# include "4coder_buffer_types.h"
2016-03-03 19:27:09 +00:00
# ifndef FRED_STRING_STRUCT
# define FRED_STRING_STRUCT
typedef struct String {
char * str ;
int size ;
int memory_size ;
} String ;
typedef struct Offset_String {
int offset ;
int size ;
} Offset_String ;
# endif
typedef unsigned char Code ;
typedef enum {
MDFR_SHIFT_INDEX ,
MDFR_CONTROL_INDEX ,
MDFR_ALT_INDEX ,
MDFR_CAPS_INDEX ,
// always last
MDFR_INDEX_COUNT
} Key_Control ;
typedef struct Key_Event_Data {
Code keycode ;
Code character ;
Code character_no_caps_lock ;
char modifiers [ MDFR_INDEX_COUNT ] ;
} Key_Event_Data ;
typedef struct Mouse_State {
char l , r ;
char press_l , press_r ;
char release_l , release_r ;
char wheel ;
char out_of_window ;
int x , y ;
} Mouse_State ;
typedef union Range {
struct {
int min , max ;
} ;
struct {
int start , end ;
} ;
} Range ;
inline Range
make_range ( int p1 , int p2 ) {
Range range ;
if ( p1 < p2 ) {
range . min = p1 ;
range . max = p2 ;
}
else {
range . min = p2 ;
range . max = p1 ;
}
return ( range ) ;
}
typedef enum Dynamic_Type {
dynamic_type_int ,
dynamic_type_string ,
// never below this
dynamic_type_count
} Dynamic_Type ;
typedef struct Dynamic {
int type ;
union {
struct {
int str_len ;
char * str_value ;
} ;
int int_value ;
} ;
} Dynamic ;
inline Dynamic
dynamic_int ( int x ) {
Dynamic result ;
result . type = dynamic_type_int ;
result . int_value = x ;
return result ;
}
inline Dynamic
dynamic_string ( const char * string , int len ) {
Dynamic result ;
result . type = dynamic_type_string ;
result . str_len = len ;
result . str_value = ( char * ) ( string ) ;
return result ;
}
inline int
dynamic_to_int ( Dynamic * dynamic ) {
int result = 0 ;
if ( dynamic - > type = = dynamic_type_int ) {
result = dynamic - > int_value ;
}
return result ;
}
inline char *
dynamic_to_string ( Dynamic * dynamic , int * len ) {
char * result = 0 ;
if ( dynamic - > type = = dynamic_type_string ) {
result = dynamic - > str_value ;
* len = dynamic - > str_len ;
}
return result ;
}
inline int
dynamic_to_bool ( Dynamic * dynamic ) {
int result = 0 ;
if ( dynamic - > type = = dynamic_type_int ) {
result = ( dynamic - > int_value ! = 0 ) ;
}
else {
result = 1 ;
}
return result ;
}
typedef struct File_Info {
String filename ;
int folder ;
} File_Info ;
typedef struct File_List {
// Ignore this, it's for internal stuff.
void * block ;
// The list of files and folders.
File_Info * infos ;
int count ;
// Ignore this, it's for internal stuff.
int block_size ;
} File_List ;
2016-02-01 05:03:42 +00:00
# define MDFR_NONE 0
# define MDFR_CTRL 1
# define MDFR_ALT 2
# define MDFR_SHIFT 4
enum Command_ID {
cmdid_null ,
cmdid_write_character ,
2016-03-04 23:10:00 +00:00
cmdid_seek_left ,
cmdid_seek_right ,
2016-02-01 05:03:42 +00:00
cmdid_seek_whitespace_right ,
cmdid_seek_whitespace_left ,
cmdid_seek_whitespace_up ,
cmdid_seek_whitespace_down ,
cmdid_seek_token_left ,
cmdid_seek_token_right ,
cmdid_seek_white_or_token_left ,
cmdid_seek_white_or_token_right ,
cmdid_seek_alphanumeric_left ,
cmdid_seek_alphanumeric_right ,
cmdid_seek_alphanumeric_or_camel_left ,
cmdid_seek_alphanumeric_or_camel_right ,
2016-02-20 21:36:16 +00:00
cmdid_word_complete ,
2016-02-01 05:03:42 +00:00
cmdid_set_mark ,
cmdid_copy ,
cmdid_cut ,
cmdid_paste ,
cmdid_paste_next ,
cmdid_delete_range ,
cmdid_timeline_scrub ,
cmdid_undo ,
cmdid_redo ,
cmdid_history_backward ,
cmdid_history_forward ,
cmdid_interactive_new ,
cmdid_interactive_open ,
cmdid_reopen ,
cmdid_save ,
cmdid_interactive_save_as ,
cmdid_change_active_panel ,
cmdid_interactive_switch_buffer ,
cmdid_interactive_kill_buffer ,
cmdid_kill_buffer ,
cmdid_toggle_line_wrap ,
cmdid_toggle_endline_mode ,
cmdid_to_uppercase ,
cmdid_to_lowercase ,
cmdid_toggle_show_whitespace ,
cmdid_clean_all_lines ,
cmdid_eol_dosify ,
cmdid_eol_nixify ,
cmdid_auto_tab_range ,
cmdid_auto_tab_line_at_cursor ,
cmdid_auto_tab_whole_file ,
cmdid_open_panel_vsplit ,
cmdid_open_panel_hsplit ,
cmdid_close_panel ,
cmdid_move_left ,
cmdid_move_right ,
cmdid_delete ,
cmdid_backspace ,
cmdid_move_up ,
cmdid_move_down ,
cmdid_seek_end_of_line ,
cmdid_seek_beginning_of_line ,
cmdid_page_up ,
cmdid_page_down ,
cmdid_open_color_tweaker ,
cmdid_cursor_mark_swap ,
cmdid_open_menu ,
cmdid_set_settings ,
2016-02-28 20:30:51 +00:00
cmdid_command_line ,
2016-02-01 05:03:42 +00:00
//
cmdid_count
} ;
enum Param_ID {
2016-02-24 05:16:08 +00:00
par_range_start ,
par_range_end ,
2016-02-01 05:03:42 +00:00
par_name ,
2016-02-28 20:30:51 +00:00
par_buffer_id ,
par_do_in_background ,
2016-03-04 23:10:00 +00:00
par_flags ,
2016-02-01 05:03:42 +00:00
par_lex_as_cpp_file ,
par_wrap_lines ,
par_key_mapid ,
par_cli_path ,
par_cli_command ,
2016-02-24 05:16:08 +00:00
par_clear_blank_lines ,
2016-02-01 05:03:42 +00:00
// never below this
par_type_count
} ;
2016-03-04 06:06:11 +00:00
# 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.
2016-02-01 05:03:42 +00:00
enum Hook_ID {
hook_start ,
hook_open_file ,
// never below this
hook_type_count
} ;
2016-03-04 06:06:11 +00:00
// 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 ,
} ;
2016-02-24 05:16:08 +00:00
// 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.
2016-02-01 05:03:42 +00:00
struct Buffer_Summary {
2016-02-23 16:04:55 +00:00
int exists ;
int ready ;
2016-02-26 17:40:51 +00:00
int buffer_id ;
2016-02-01 05:03:42 +00:00
int size ;
int file_name_len ;
int buffer_name_len ;
2016-02-25 00:04:08 +00:00
char * file_name ;
char * buffer_name ;
2016-02-01 05:03:42 +00:00
2016-02-26 17:40:51 +00:00
int buffer_cursor_pos ;
2016-02-01 05:03:42 +00:00
int is_lexed ;
int map_id ;
} ;
2016-03-03 04:10:45 +00:00
struct View_Summary {
2016-02-24 05:16:08 +00:00
int exists ;
int view_id ;
2016-02-26 17:40:51 +00:00
int buffer_id ;
2016-03-04 23:10:00 +00:00
int locked_buffer_id ;
int hidden_buffer_id ;
2016-02-24 05:16:08 +00:00
Full_Cursor cursor ;
Full_Cursor mark ;
2016-02-25 00:04:08 +00:00
float preferred_x ;
int line_height ;
int unwrapped_lines ;
2016-02-24 05:16:08 +00:00
} ;
2016-02-27 07:44:17 +00:00
# define UserInputKey 0
# define UserInputMouse 1
2016-02-26 17:40:51 +00:00
struct User_Input {
2016-02-27 07:44:17 +00:00
int type ;
2016-02-27 17:34:13 +00:00
int abort ;
2016-02-27 07:44:17 +00:00
union {
Key_Event_Data key ;
Mouse_State mouse ;
} ;
2016-02-27 17:34:13 +00:00
unsigned long long command ;
2016-02-26 17:40:51 +00:00
} ;
2016-02-27 17:34:13 +00:00
# define CommandEqual(c1,c2) ((unsigned long long)(c1) == (unsigned long long)(c2))
2016-02-27 07:44:17 +00:00
struct Query_Bar {
2016-02-26 17:40:51 +00:00
String prompt ;
String string ;
} ;
2016-02-25 23:52:11 +00:00
# define GET_BINDING_DATA(name) int name(void *data, int size)
2016-02-26 06:26:26 +00:00
# define CUSTOM_COMMAND_SIG(name) void name(struct Application_Links *app)
# define HOOK_SIG(name) void name(struct Application_Links *app)
2016-03-03 00:50:04 +00:00
# define SCROLL_RULE_SIG(name) int name(float target_x, float target_y, float *scroll_x, float *scroll_y, int view_id, int is_new_target)
2016-02-01 05:03:42 +00:00
extern " C " {
typedef CUSTOM_COMMAND_SIG ( Custom_Command_Function ) ;
typedef GET_BINDING_DATA ( Get_Binding_Data_Function ) ;
typedef HOOK_SIG ( Hook_Function ) ;
2016-03-03 00:50:04 +00:00
typedef SCROLL_RULE_SIG ( Scroll_Rule_Function ) ;
2016-02-01 05:03:42 +00:00
}
2016-02-26 06:26:26 +00:00
struct Application_Links ;
2016-02-23 20:06:22 +00:00
// Command exectuion
2016-03-03 19:27:09 +00:00
# define PUSH_PARAMETER_SIG(name) void name(Application_Links *app, Dynamic param, Dynamic value)
# define PUSH_MEMORY_SIG(name) char* name(Application_Links *app, int len)
# define EXECUTE_COMMAND_SIG(name) void name(Application_Links *app, int command_id)
# define CLEAR_PARAMETERS_SIG(name) void name(Application_Links *app)
2016-02-23 20:06:22 +00:00
// File system navigation
2016-03-03 19:27:09 +00:00
# define DIRECTORY_GET_HOT_SIG(name) int name(Application_Links *app, char *out, int capacity)
# define FILE_EXISTS_SIG(name) int name(Application_Links *app, char *filename, int len)
# define DIRECTORY_CD_SIG(name) int name(Application_Links *app, char *dir, int *len, int capacity, char *rel_path, int rel_len)
# define GET_FILE_LIST_SIG(name) File_List name(Application_Links *app, char *dir, int len)
# define FREE_FILE_LIST_SIG(name) void name(Application_Links *app, File_List list)
2016-02-01 05:03:42 +00:00
2016-02-23 20:41:11 +00:00
// Direct buffer manipulation
2016-03-04 21:26:00 +00:00
# define GET_BUFFER_FIRST_SIG(name) Buffer_Summary name(Application_Links *app)
# define GET_BUFFER_NEXT_SIG(name) void name(Application_Links *app, Buffer_Summary *buffer)
2016-03-03 19:27:09 +00:00
# define GET_BUFFER_SIG(name) Buffer_Summary name(Application_Links *app, int index)
# define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(Application_Links *app)
2016-03-04 21:26:00 +00:00
# define GET_PARAMETER_BUFFER_SIG(name) Buffer_Summary name(Application_Links *app, int param_index)
2016-03-03 19:27:09 +00:00
# define GET_BUFFER_BY_NAME(name) Buffer_Summary name(Application_Links *app, char *filename, int len)
# define BUFFER_SEEK_DELIMITER_SIG(name) int name(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
# define BUFFER_SEEK_STRING_SIG(name) int name(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
2016-03-04 23:10:00 +00:00
# define REFRESH_BUFFER_SIG(name) int name(Application_Links *app, Buffer_Summary *buffer)
2016-03-03 19:27:09 +00:00
# define BUFFER_READ_RANGE_SIG(name) int name(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out)
# define BUFFER_REPLACE_RANGE_SIG(name) int name(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len)
# define BUFFER_SET_POS_SIG(name) int name(Application_Links *app, Buffer_Summary *buffer, int pos)
2016-02-23 20:41:11 +00:00
2016-02-24 05:16:08 +00:00
// File view manipulation
2016-03-04 21:26:00 +00:00
# define GET_VIEW_FIRST_SIG(name) View_Summary name(Application_Links *app)
# define GET_VIEW_NEXT_SIG(name) void name(Application_Links *app, View_Summary *view)
2016-03-03 19:27:09 +00:00
# define GET_VIEW_SIG(name) View_Summary name(Application_Links *app, int index)
# define GET_ACTIVE_VIEW_SIG(name) View_Summary name(Application_Links *app)
# define REFRESH_VIEW_SIG(name) int name(Application_Links *app, View_Summary *view)
# define VIEW_SET_CURSOR_SIG(name) int name(Application_Links *app, View_Summary *view, Buffer_Seek seek, int set_preferred_x)
# define VIEW_SET_MARK_SIG(name) int name(Application_Links *app, View_Summary *view, Buffer_Seek seek)
# define VIEW_SET_HIGHLIGHT_SIG(name) int name(Application_Links *app, View_Summary *view, int start, int end, int turn_on)
# define VIEW_SET_BUFFER_SIG(name) int name(Application_Links *app, View_Summary *view, int buffer_id)
2016-02-26 17:40:51 +00:00
// Directly get user input
2016-03-04 23:10:00 +00:00
# define GET_USER_INPUT_SIG(name) User_Input name(Application_Links *context, unsigned int get_type, unsigned int abort_type)
// Queries
# define START_QUERY_BAR_SIG(name) int name(Application_Links *context, Query_Bar *bar, unsigned int flags)
# define END_QUERY_BAR_SIG(name) void name(Application_Links *context, Query_Bar *bar, unsigned int flags)
// Boundry type flags
# define BoundryWhitespace 0x1
# define BoundryToken 0x2
# define BoundryAlphanumeric 0x4
# define BoundryCamelCase 0x8
// Input type flags
2016-02-27 07:44:17 +00:00
# define EventOnAnyKey 0x1
# define EventOnEsc 0x2
# define EventOnLeftButton 0x4
# define EventOnRightButton 0x8
# define EventOnWheel 0x10
# define EventOnButton (EventOnLeftButton | EventOnRightButton | EventOnWheel)
2016-02-29 14:43:34 +00:00
// NOTE(allen): These don't work so much, so let's pretend they're not here for now.
2016-02-27 07:44:17 +00:00
# define EventOnMouseMove 0x20
# define EventOnMouse (EventOnButton | EventOnMouseMove)
2016-02-26 17:40:51 +00:00
2016-02-24 05:16:08 +00:00
2016-02-01 05:03:42 +00:00
extern " C " {
2016-02-23 20:06:22 +00:00
// Command exectuion
2016-02-01 05:03:42 +00:00
typedef EXECUTE_COMMAND_SIG ( Exec_Command_Function ) ;
typedef PUSH_PARAMETER_SIG ( Push_Parameter_Function ) ;
typedef PUSH_MEMORY_SIG ( Push_Memory_Function ) ;
typedef CLEAR_PARAMETERS_SIG ( Clear_Parameters_Function ) ;
2016-02-23 20:06:22 +00:00
// File system navigation
2016-02-28 20:30:51 +00:00
typedef DIRECTORY_GET_HOT_SIG ( Directory_Get_Hot_Function ) ;
typedef FILE_EXISTS_SIG ( File_Exists_Function ) ;
typedef DIRECTORY_CD_SIG ( Directory_CD_Function ) ;
typedef GET_FILE_LIST_SIG ( Get_File_List_Function ) ;
typedef FREE_FILE_LIST_SIG ( Free_File_List_Function ) ;
2016-02-23 15:23:45 +00:00
2016-02-23 20:06:22 +00:00
// Buffer manipulation
2016-03-04 21:26:00 +00:00
typedef GET_BUFFER_FIRST_SIG ( Get_Buffer_First_Function ) ;
typedef GET_BUFFER_NEXT_SIG ( Get_Buffer_Next_Function ) ;
2016-02-23 15:23:45 +00:00
typedef GET_BUFFER_SIG ( Get_Buffer_Function ) ;
typedef GET_ACTIVE_BUFFER_SIG ( Get_Active_Buffer_Function ) ;
2016-03-04 21:26:00 +00:00
typedef GET_PARAMETER_BUFFER_SIG ( Get_Parameter_Buffer_Function ) ;
2016-02-23 15:23:45 +00:00
typedef GET_BUFFER_BY_NAME ( Get_Buffer_By_Name_Function ) ;
2016-02-23 20:06:22 +00:00
typedef BUFFER_SEEK_DELIMITER_SIG ( Buffer_Seek_Delimiter_Function ) ;
2016-02-27 19:33:42 +00:00
typedef BUFFER_SEEK_STRING_SIG ( Buffer_Seek_String_Function ) ;
2016-03-04 23:10:00 +00:00
typedef REFRESH_BUFFER_SIG ( Refresh_Buffer_Function ) ;
2016-02-23 20:06:22 +00:00
typedef BUFFER_READ_RANGE_SIG ( Buffer_Read_Range_Function ) ;
2016-02-23 20:41:11 +00:00
typedef BUFFER_REPLACE_RANGE_SIG ( Buffer_Replace_Range_Function ) ;
2016-03-03 00:50:04 +00:00
typedef BUFFER_SET_POS_SIG ( Buffer_Set_Pos_Function ) ;
2016-02-24 05:16:08 +00:00
// View manipulation
2016-03-04 21:26:00 +00:00
typedef GET_VIEW_FIRST_SIG ( Get_View_First_Function ) ;
typedef GET_VIEW_NEXT_SIG ( Get_View_Next_Function ) ;
2016-03-03 04:10:45 +00:00
typedef GET_VIEW_SIG ( Get_View_Function ) ;
typedef GET_ACTIVE_VIEW_SIG ( Get_Active_View_Function ) ;
2016-02-24 05:16:08 +00:00
2016-03-03 04:10:45 +00:00
typedef REFRESH_VIEW_SIG ( Refresh_View_Function ) ;
2016-02-24 05:16:08 +00:00
typedef VIEW_SET_CURSOR_SIG ( View_Set_Cursor_Function ) ;
typedef VIEW_SET_MARK_SIG ( View_Set_Mark_Function ) ;
2016-02-27 19:33:42 +00:00
typedef VIEW_SET_HIGHLIGHT_SIG ( View_Set_Highlight_Function ) ;
2016-02-26 17:40:51 +00:00
typedef VIEW_SET_BUFFER_SIG ( View_Set_Buffer_Function ) ;
// Directly get user input
typedef GET_USER_INPUT_SIG ( Get_User_Input_Function ) ;
// Queries
2016-02-27 07:44:17 +00:00
typedef START_QUERY_BAR_SIG ( Start_Query_Bar_Function ) ;
typedef END_QUERY_BAR_SIG ( End_Query_Bar_Function ) ;
2016-02-01 05:03:42 +00:00
}
struct Application_Links {
2016-02-28 20:30:51 +00:00
// User data
2016-02-29 03:35:19 +00:00
void * memory ;
int memory_size ;
2016-02-26 17:40:51 +00:00
2016-02-23 15:23:45 +00:00
// Command exectuion
2016-02-01 05:03:42 +00:00
Exec_Command_Function * exec_command_keep_stack ;
Push_Parameter_Function * push_parameter ;
Push_Memory_Function * push_memory ;
Clear_Parameters_Function * clear_parameters ;
2016-02-23 15:23:45 +00:00
// File system navigation
2016-02-28 20:30:51 +00:00
Directory_Get_Hot_Function * directory_get_hot ;
File_Exists_Function * file_exists ;
Directory_CD_Function * directory_cd ;
Get_File_List_Function * get_file_list ;
Free_File_List_Function * free_file_list ;
2016-02-23 15:23:45 +00:00
// Buffer manipulation
2016-03-04 21:26:00 +00:00
Get_Buffer_First_Function * get_buffer_first ;
Get_Buffer_Next_Function * get_buffer_next ;
2016-02-23 15:23:45 +00:00
Get_Buffer_Function * get_buffer ;
Get_Active_Buffer_Function * get_active_buffer ;
2016-03-04 21:26:00 +00:00
Get_Parameter_Buffer_Function * get_parameter_buffer ;
2016-02-23 15:23:45 +00:00
Get_Buffer_By_Name_Function * get_buffer_by_name ;
2016-02-23 20:06:22 +00:00
Buffer_Seek_Delimiter_Function * buffer_seek_delimiter ;
2016-02-27 19:33:42 +00:00
Buffer_Seek_String_Function * buffer_seek_string ;
2016-03-04 23:10:00 +00:00
Refresh_Buffer_Function * refresh_buffer ;
2016-02-23 20:06:22 +00:00
Buffer_Read_Range_Function * buffer_read_range ;
2016-02-23 20:41:11 +00:00
Buffer_Replace_Range_Function * buffer_replace_range ;
2016-03-03 00:50:04 +00:00
Buffer_Set_Pos_Function * buffer_set_pos ;
2016-02-24 05:16:08 +00:00
// View manipulation
2016-03-04 21:26:00 +00:00
Get_View_First_Function * get_view_first ;
Get_View_Next_Function * get_view_next ;
2016-03-03 04:10:45 +00:00
Get_View_Function * get_view ;
Get_Active_View_Function * get_active_view ;
2016-02-24 05:16:08 +00:00
2016-03-03 04:10:45 +00:00
Refresh_View_Function * refresh_view ;
2016-02-24 05:16:08 +00:00
View_Set_Cursor_Function * view_set_cursor ;
View_Set_Mark_Function * view_set_mark ;
2016-02-27 19:33:42 +00:00
View_Set_Highlight_Function * view_set_highlight ;
2016-02-26 17:40:51 +00:00
View_Set_Buffer_Function * view_set_buffer ;
2016-02-26 06:26:26 +00:00
2016-02-26 17:40:51 +00:00
// Directly get user input
2016-02-27 07:44:17 +00:00
Get_User_Input_Function * get_user_input ;
2016-02-26 17:40:51 +00:00
// Queries
2016-02-27 07:44:17 +00:00
Start_Query_Bar_Function * start_query_bar ;
End_Query_Bar_Function * end_query_bar ;
2016-02-28 20:30:51 +00:00
// Internal
void * cmd_context ;
2016-02-01 05:03:42 +00:00
} ;
struct Custom_API {
Get_Binding_Data_Function * get_bindings ;
} ;
// NOTE(allen): definitions for the buffer that communicates to 4ed.exe
enum Binding_Unit_Type {
unit_header ,
unit_map_begin ,
unit_binding ,
unit_callback ,
unit_inherit ,
unit_hook
} ;
enum Map_ID {
mapid_global = ( 1 < < 24 ) ,
mapid_file ,
2016-02-22 02:45:41 +00:00
2016-02-01 05:03:42 +00:00
// NOTE(allen): mapid_nomap will remain empty even if you attempt to fill it
// it is for setting a map's parent to nothing, in cases where you don't want
// to inherit from global (which is the default).
mapid_nomap
} ;
struct Binding_Unit {
Binding_Unit_Type type ;
union {
struct { int total_size ; int user_map_count ; int error ; } header ;
struct { int mapid ; int bind_count ; } map_begin ;
struct { int mapid ; } map_inherit ;
struct {
short code ;
unsigned char modifiers ;
int command_id ;
} binding ;
struct {
short code ;
unsigned char modifiers ;
Custom_Command_Function * func ;
} callback ;
struct {
int hook_id ;
2016-03-04 06:06:11 +00:00
void * func ;
2016-02-01 05:03:42 +00:00
} hook ;
} ;
} ;