mac layer almost finished
parent
82882f22f5
commit
772adc67a3
|
@ -35,6 +35,7 @@ ENUM(int32_t, Key_Modifier_Index){
|
|||
MDFR_SHIFT_INDEX,
|
||||
MDFR_CONTROL_INDEX,
|
||||
MDFR_ALT_INDEX,
|
||||
MDFR_COMMAND_INDEX,
|
||||
MDFR_CAPS_INDEX,
|
||||
MDFR_HOLD_INDEX,
|
||||
|
||||
|
@ -46,10 +47,11 @@ ENUM(int32_t, Key_Modifier_Index){
|
|||
Flags can be combined with bit or to specify a state with multiple modifiers.) */
|
||||
ENUM(uint32_t, Key_Modifier_Flag){
|
||||
/* DOC(MDFR_NONE specifies that no modifiers are pressed.) */
|
||||
MDFR_NONE = 0x0,
|
||||
MDFR_CTRL = 0x1,
|
||||
MDFR_ALT = 0x2,
|
||||
MDFR_SHIFT = 0x4,
|
||||
MDFR_NONE = 0x0,
|
||||
MDFR_CTRL = 0x1,
|
||||
MDFR_ALT = 0x2,
|
||||
MDFR_COMMAND = 0x4,
|
||||
MDFR_SHIFT = 0x8,
|
||||
};
|
||||
|
||||
/* DOC(A Command_ID is used as a name for commands implemented internally in 4coder.) */
|
||||
|
|
|
@ -163,6 +163,7 @@ default_keys(Bind_Helper *context){
|
|||
bind(context, key_back, MDFR_CTRL, backspace_word);
|
||||
bind(context, key_del, MDFR_CTRL, delete_word);
|
||||
bind(context, key_back, MDFR_ALT, snipe_token_or_word);
|
||||
bind(context, key_del, MDFR_ALT, snipe_token_or_word_right);
|
||||
|
||||
bind(context, ' ', MDFR_CTRL, set_mark);
|
||||
bind(context, 'a', MDFR_CTRL, replace_in_range);
|
||||
|
|
|
@ -130,13 +130,25 @@ CUSTOM_COMMAND_SIG(snipe_token_or_word){
|
|||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t pos1 = buffer_boundary_seek(app, &buffer, view.cursor.pos, 0, BoundaryToken | BoundaryWhitespace);
|
||||
int32_t pos2 = buffer_boundary_seek(app, &buffer, pos1, 1, BoundaryToken | BoundaryWhitespace);
|
||||
int32_t pos1 = buffer_boundary_seek(app, &buffer, view.cursor.pos, false, BoundaryToken | BoundaryWhitespace);
|
||||
int32_t pos2 = buffer_boundary_seek(app, &buffer, pos1, true, BoundaryToken | BoundaryWhitespace);
|
||||
|
||||
Range range = make_range(pos1, pos2);
|
||||
buffer_replace_range(app, &buffer, range.start, range.end, 0, 0);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(snipe_token_or_word_right){
|
||||
uint32_t access = AccessOpen;
|
||||
|
||||
View_Summary view = get_active_view(app, access);
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
|
||||
int32_t pos2 = buffer_boundary_seek(app, &buffer, view.cursor.pos, true, BoundaryToken | BoundaryWhitespace);
|
||||
int32_t pos1 = buffer_boundary_seek(app, &buffer, pos2, false, BoundaryToken | BoundaryWhitespace);
|
||||
|
||||
Range range = make_range(pos1, pos2);
|
||||
buffer_replace_range(app, &buffer, range.start, range.end, 0, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Line Manipulation
|
||||
|
|
|
@ -62,8 +62,8 @@ struct Table{
|
|||
|
||||
static i32_4tech
|
||||
table_required_mem_size(i32_4tech table_size, i32_4tech item_size){
|
||||
i32_4tech hash_size = ((table_size * sizeof(u32_4tech)) + 7) & ~7;
|
||||
i32_4tech mem_size = hash_size + table_size * item_size;
|
||||
i32_4tech hash_size = ((table_size*sizeof(u32_4tech)) + 7) & ~7;
|
||||
i32_4tech mem_size = hash_size + table_size*item_size;
|
||||
return(mem_size);
|
||||
}
|
||||
|
||||
|
|
|
@ -168,27 +168,29 @@ internal Command_Binding
|
|||
map_extract(Command_Map *map, Key_Event_Data key){
|
||||
Command_Binding bind = {0};
|
||||
|
||||
b32 ctrl = key.modifiers[MDFR_CONTROL_INDEX];
|
||||
b32 alt = key.modifiers[MDFR_ALT_INDEX];
|
||||
b32 shift = key.modifiers[MDFR_SHIFT_INDEX];
|
||||
u8 command = MDFR_NONE;
|
||||
b32 ctrl = key.modifiers[MDFR_CONTROL_INDEX];
|
||||
b32 alt = key.modifiers[MDFR_ALT_INDEX];
|
||||
b32 command = key.modifiers[MDFR_COMMAND_INDEX];
|
||||
b32 shift = key.modifiers[MDFR_SHIFT_INDEX];
|
||||
|
||||
if (shift) command |= MDFR_SHIFT;
|
||||
if (ctrl) command |= MDFR_CTRL;
|
||||
if (alt) command |= MDFR_ALT;
|
||||
u8 mod_flags = MDFR_NONE;
|
||||
if (ctrl) mod_flags |= MDFR_CTRL;
|
||||
if (command) mod_flags |= MDFR_COMMAND;
|
||||
if (alt) mod_flags |= MDFR_ALT;
|
||||
if (shift) mod_flags |= MDFR_SHIFT;
|
||||
|
||||
Key_Code code = key.character_no_caps_lock;
|
||||
if (code == 0){
|
||||
code = key.keycode;
|
||||
map_find(map, code, command, &bind);
|
||||
map_find(map, code, mod_flags, &bind);
|
||||
}
|
||||
else{
|
||||
if (code != '\n' && code != '\t' && code != ' '){
|
||||
command &= ~(MDFR_SHIFT);
|
||||
mod_flags &= ~(MDFR_SHIFT);
|
||||
}
|
||||
map_find(map, code, command, &bind);
|
||||
map_find(map, code, mod_flags, &bind);
|
||||
if (bind.function == 0){
|
||||
map_get_vanilla_keyboard_default(map, command, &bind);
|
||||
map_get_vanilla_keyboard_default(map, mod_flags, &bind);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -319,8 +319,9 @@ build(u32 flags, u32 arch, char *code_path, char **code_files, char *out_path, c
|
|||
"-Wno-write-strings -Wno-deprecated-declarations " \
|
||||
"-Wno-comment -Wno-switch -Wno-null-dereference "
|
||||
|
||||
#define GCC_LIBS \
|
||||
#define GCC_LIBS \
|
||||
"-framework Cocoa -framework QuartzCore " \
|
||||
"-framework CoreServices " \
|
||||
"-framework OpenGL -framework IOKit -lfreetype"
|
||||
|
||||
#else
|
||||
|
|
|
@ -490,7 +490,6 @@ private_draw_glyph_mono(System_Functions *system, Render_Target *t, Render_Font
|
|||
|
||||
internal void
|
||||
launch_rendering(System_Functions *system, Render_Target *t){
|
||||
DBG_POINT();
|
||||
char *cursor = t->push_buffer;
|
||||
char *cursor_end = cursor + t->size;
|
||||
|
||||
|
|
|
@ -905,12 +905,7 @@ LinuxKeycodeInit(Display* dpy){
|
|||
|
||||
int key_count = (key_max - key_min) + 1;
|
||||
|
||||
KeySym* syms = XGetKeyboardMapping(
|
||||
dpy,
|
||||
key_min,
|
||||
key_count,
|
||||
&syms_per_code
|
||||
);
|
||||
KeySym* syms = XGetKeyboardMapping(dpy, key_min, key_count, &syms_per_code);
|
||||
|
||||
if (!syms) return;
|
||||
|
||||
|
@ -1824,6 +1819,7 @@ main(int argc, char **argv){
|
|||
linuxvars.input.clipboard = null_string;
|
||||
}
|
||||
|
||||
// HACK(allen): THIS SHIT IS FUCKED (happens on mac too)
|
||||
b32 keep_running = linuxvars.keep_running;
|
||||
|
||||
app.step(&sysfunc, &target, &memory_vars, &linuxvars.input, &result);
|
||||
|
|
|
@ -11,14 +11,6 @@
|
|||
|
||||
#define IS_PLAT_LAYER
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if 0
|
||||
#define DBG_POINT() fprintf(stdout, "%s\n", __FILE__ ":" LINE_STR ":")
|
||||
#else
|
||||
#define DBG_POINT()
|
||||
#endif
|
||||
|
||||
#include "4ed_defines.h"
|
||||
#include "4coder_API/version.h"
|
||||
|
||||
|
@ -87,6 +79,9 @@ struct OSX_Vars{
|
|||
Application_Step_Input input;
|
||||
String clipboard_contents;
|
||||
b32 keep_running;
|
||||
|
||||
b32 has_prev_time;
|
||||
u64 prev_time_u;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
@ -162,7 +157,8 @@ Sys_Is_Fullscreen_Sig(system_is_fullscreen){
|
|||
// HACK(allen): Why does this work differently from the win32 version!?
|
||||
internal
|
||||
Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
|
||||
osx_objc.running = false;
|
||||
DBG_POINT();
|
||||
osxvars.keep_running = false;
|
||||
}
|
||||
|
||||
#include "4ed_coroutine_functions.cpp"
|
||||
|
@ -193,31 +189,108 @@ Sys_Post_Clipboard_Sig(system_post_clipboard){
|
|||
// CLI
|
||||
//
|
||||
|
||||
// HACK(allen): ALMOST an exact duplicate from the Linux version. Just epoll doesn't port. deduplicate.
|
||||
internal
|
||||
Sys_CLI_Call_Sig(system_cli_call){
|
||||
// b32 #(char *path, char *script_name, CLI_Handles *cli_out)
|
||||
NotImplemented;
|
||||
i32 pipe_fds[2];
|
||||
if (pipe(pipe_fds) == -1){
|
||||
DBG_POINT();
|
||||
return 0;
|
||||
}
|
||||
|
||||
i32 child_pid = fork();
|
||||
if (child_pid == -1){
|
||||
DBG_POINT();
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum { PIPE_FD_READ, PIPE_FD_WRITE };
|
||||
|
||||
// child
|
||||
if (child_pid == 0){
|
||||
close(pipe_fds[PIPE_FD_READ]);
|
||||
dup2(pipe_fds[PIPE_FD_WRITE], STDOUT_FILENO);
|
||||
dup2(pipe_fds[PIPE_FD_WRITE], STDERR_FILENO);
|
||||
|
||||
if (chdir(path) == -1){
|
||||
DBG_POINT();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char* argv[] = { "sh", "-c", script_name, NULL };
|
||||
|
||||
if (execv("/bin/sh", argv) == -1){
|
||||
DBG_POINT();
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
else{
|
||||
close(pipe_fds[PIPE_FD_WRITE]);
|
||||
|
||||
*(pid_t*)&cli_out->proc = child_pid;
|
||||
*(int*)&cli_out->out_read = pipe_fds[PIPE_FD_READ];
|
||||
*(int*)&cli_out->out_write = pipe_fds[PIPE_FD_WRITE];
|
||||
|
||||
// TODO(allen): Getting updates when there is new something new on the pipe!?
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_CLI_Begin_Update_Sig(system_cli_begin_update){
|
||||
// void #(CLI_Handles *cli)
|
||||
NotImplemented;
|
||||
// NOTE(inso): I don't think anything needs to be done here.
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_CLI_Update_Step_Sig(system_cli_update_step){
|
||||
// b32 #(CLI_Handles *cli, char *dest, u32 max, u32 *amount)
|
||||
NotImplemented;
|
||||
return(0);
|
||||
i32 pipe_read_fd = *(i32*)&cli->out_read;
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(pipe_read_fd, &fds);
|
||||
|
||||
struct timeval tv = {};
|
||||
|
||||
size_t space_left = max;
|
||||
char* ptr = dest;
|
||||
|
||||
while (space_left > 0 && select(pipe_read_fd + 1, &fds, NULL, NULL, &tv) == 1){
|
||||
ssize_t num = read(pipe_read_fd, ptr, space_left);
|
||||
if (num == -1){
|
||||
DBG_POINT();
|
||||
} else if (num == 0){
|
||||
// NOTE(inso): EOF
|
||||
break;
|
||||
} else {
|
||||
ptr += num;
|
||||
space_left -= num;
|
||||
}
|
||||
}
|
||||
|
||||
*amount = (ptr - dest);
|
||||
return((ptr - dest) > 0);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_CLI_End_Update_Sig(system_cli_end_update){
|
||||
// b32 #(CLI_Handles *cli)
|
||||
NotImplemented;
|
||||
return(false);
|
||||
pid_t pid = *(pid_t*)&cli->proc;
|
||||
b32 close_me = false;
|
||||
|
||||
int status;
|
||||
if (pid && waitpid(pid, &status, WNOHANG) > 0){
|
||||
close_me = true;
|
||||
|
||||
cli->exit = WEXITSTATUS(status);
|
||||
|
||||
//struct epoll_event e = {};
|
||||
//epoll_ctl(linuxvars.epoll, EPOLL_CTL_DEL, *(int*)&cli->out_read, &e);
|
||||
|
||||
close(*(int*)&cli->out_read);
|
||||
close(*(int*)&cli->out_write);
|
||||
}
|
||||
|
||||
return(close_me);
|
||||
}
|
||||
|
||||
#include "4ed_font_data.h"
|
||||
|
@ -230,17 +303,20 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
|
|||
|
||||
external void*
|
||||
osx_allocate(umem size){
|
||||
DBG_POINT();
|
||||
void *result = system_memory_allocate(size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
external void
|
||||
osx_free(void *ptr, umem size){
|
||||
system_memory_free(ptr, size);
|
||||
}
|
||||
|
||||
external void
|
||||
osx_resize(int width, int height){
|
||||
DBG_POINT();
|
||||
osx_objc.width = width;
|
||||
osx_objc.height = height;
|
||||
|
||||
|
||||
if (width > 0 && height > 0){
|
||||
glViewport(0, 0, width, height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
|
@ -260,7 +336,7 @@ osx_push_key(Key_Code code, Key_Code chr, Key_Code chr_nocaps, b8 *mods)
|
|||
|
||||
if (count < KEY_INPUT_BUFFER_SIZE){
|
||||
Key_Event_Data *data = osxvars.input.keys.keys;
|
||||
|
||||
|
||||
data[count].keycode = code;
|
||||
data[count].character = chr;
|
||||
data[count].character_no_caps_lock = chr_nocaps;
|
||||
|
@ -273,7 +349,6 @@ osx_push_key(Key_Code code, Key_Code chr, Key_Code chr_nocaps, b8 *mods)
|
|||
|
||||
external void
|
||||
osx_character_input(u32 code, OSX_Keyboard_Modifiers modifier_flags){
|
||||
DBG_POINT();
|
||||
Key_Code c = 0;
|
||||
switch (code){
|
||||
// TODO(allen): Find the canonical list of these things.
|
||||
|
@ -283,34 +358,36 @@ osx_character_input(u32 code, OSX_Keyboard_Modifiers modifier_flags){
|
|||
case 0xF702: c = key_left; break;
|
||||
case 0xF703: c = key_right; break;
|
||||
case 0x001B: c = key_esc; break;
|
||||
|
||||
|
||||
case 0xF704: c = key_f1; break;
|
||||
case 0xF705: c = key_f2; break;
|
||||
case 0xF706: c = key_f3; break;
|
||||
case 0xF707: c = key_f4; break;
|
||||
|
||||
|
||||
case 0xF708: c = key_f5; break;
|
||||
case 0xF709: c = key_f6; break;
|
||||
case 0xF70A: c = key_f7; break;
|
||||
case 0xF70B: c = key_f8; break;
|
||||
|
||||
|
||||
case 0xF70C: c = key_f9; break;
|
||||
case 0xF70D: c = key_f10; break;
|
||||
case 0xF70E: c = key_f11; break;
|
||||
case 0xF70F: c = key_f12; break;
|
||||
|
||||
|
||||
case 0xF710: c = key_f13; break;
|
||||
case 0xF711: c = key_f14; break;
|
||||
case 0xF712: c = key_f15; break;
|
||||
case 0xF713: c = key_f16; break;
|
||||
}
|
||||
|
||||
fprintf(stdout, "INPUT: %c\n", (char)code);
|
||||
|
||||
b8 mods[MDFR_INDEX_COUNT] = {0};
|
||||
|
||||
if (modifier_flags.shift) mods[MDFR_SHIFT_INDEX] = 1;
|
||||
if (modifier_flags.command) mods[MDFR_CONTROL_INDEX] = 1;
|
||||
if (modifier_flags.caps) mods[MDFR_CAPS_INDEX] = 1;
|
||||
if (modifier_flags.control) mods[MDFR_ALT_INDEX] = 1;
|
||||
if (modifier_flags.shift) mods[MDFR_SHIFT_INDEX] = true;
|
||||
if (modifier_flags.control) mods[MDFR_CONTROL_INDEX] = true;
|
||||
if (modifier_flags.option) mods[MDFR_ALT_INDEX] = true;
|
||||
if (modifier_flags.command) mods[MDFR_COMMAND_INDEX] = true;
|
||||
if (modifier_flags.caps) mods[MDFR_CAPS_INDEX] = true;
|
||||
|
||||
if (c != 0){
|
||||
osx_push_key(c, 0, 0, mods);
|
||||
|
@ -319,16 +396,17 @@ osx_character_input(u32 code, OSX_Keyboard_Modifiers modifier_flags){
|
|||
if (code == '\r'){
|
||||
code = '\n';
|
||||
}
|
||||
Key_Code chr = code;
|
||||
Key_Code nocaps = code;
|
||||
if (modifier_flags.caps){
|
||||
if ('a' <= nocaps && nocaps <= 'z'){
|
||||
nocaps += 'A' - 'a';
|
||||
if ('a' <= chr && chr <= 'z'){
|
||||
chr += 'A' - 'a';
|
||||
}
|
||||
else if ('A' <= nocaps && nocaps <= 'Z'){
|
||||
nocaps += 'a' - 'A';
|
||||
else if ('A' <= chr && chr <= 'Z'){
|
||||
chr += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
osx_push_key(code, code, nocaps, mods);
|
||||
osx_push_key(code, chr, nocaps, mods);
|
||||
}
|
||||
else{
|
||||
osx_push_key(0, 0, 0, mods);
|
||||
|
@ -337,21 +415,20 @@ osx_character_input(u32 code, OSX_Keyboard_Modifiers modifier_flags){
|
|||
|
||||
external void
|
||||
osx_mouse(i32 mx, i32 my, u32 type){
|
||||
DBG_POINT();
|
||||
osxvars.input.mouse.x = mx;
|
||||
osxvars.input.mouse.y = my;
|
||||
osxvars.input.mouse.y = osx_objc.height - my;
|
||||
if (type == MouseType_Press){
|
||||
osxvars.input.mouse.press_l = true;
|
||||
osxvars.input.mouse.l = true;
|
||||
}
|
||||
if (type == MouseType_Release){
|
||||
osxvars.input.mouse.release_l = true;
|
||||
osxvars.input.mouse.l = false;
|
||||
}
|
||||
}
|
||||
|
||||
external void
|
||||
osx_mouse_wheel(float dx, float dy){
|
||||
DBG_POINT();
|
||||
if (dy > 0){
|
||||
osxvars.input.mouse.wheel = 1;
|
||||
}
|
||||
|
@ -361,16 +438,38 @@ osx_mouse_wheel(float dx, float dy){
|
|||
}
|
||||
|
||||
external void
|
||||
osx_step(){
|
||||
osx_try_to_close(void){
|
||||
system_send_exit_signal();
|
||||
}
|
||||
|
||||
external void
|
||||
osx_step(void){
|
||||
Application_Step_Result result = {};
|
||||
result.mouse_cursor_type = APP_MOUSE_CURSOR_DEFAULT;
|
||||
result.trying_to_kill = !osxvars.keep_running;
|
||||
|
||||
osxvars.input.clipboard = null_string;
|
||||
|
||||
app.step(&sysfunc, &target, &memory_vars, &osxvars.input, &result);
|
||||
launch_rendering(&sysfunc, &target);
|
||||
|
||||
if (osx_objc.has_clipboard_item){
|
||||
//void *clipboard_data;
|
||||
//umem clipboard_size, clipboard_max;
|
||||
osxvars.input.clipboard = make_string(osx_objc.clipboard_data, (i32)osx_objc.clipboard_size);
|
||||
}
|
||||
else{
|
||||
osxvars.input.clipboard = null_string;
|
||||
}
|
||||
|
||||
osxvars.input.dt = 1.f/60.f;
|
||||
if (osxvars.has_prev_time){
|
||||
u64 time_u = system_now_time();
|
||||
u64 time_elapsed_u = time_u - osxvars.prev_time_u;
|
||||
osxvars.input.dt = time_elapsed_u/1000000.f;
|
||||
osxvars.prev_time_u = time_u;
|
||||
}
|
||||
else{
|
||||
osxvars.has_prev_time = true;
|
||||
osxvars.prev_time_u = system_now_time();
|
||||
}
|
||||
|
||||
Application_Step_Input frame_input = osxvars.input;
|
||||
osxvars.input.first_step = false;
|
||||
osxvars.input.keys = null_key_input_data;
|
||||
osxvars.input.mouse.press_l = false;
|
||||
|
@ -378,6 +477,20 @@ osx_step(){
|
|||
osxvars.input.mouse.press_r = false;
|
||||
osxvars.input.mouse.release_r = false;
|
||||
osxvars.input.mouse.wheel = 0;
|
||||
|
||||
// HACK(allen): THIS SHIT IS FUCKED (happens on linux too)
|
||||
b32 keep_running = osxvars.keep_running;
|
||||
|
||||
app.step(&sysfunc, &target, &memory_vars, &frame_input, &result);
|
||||
|
||||
if (result.perform_kill){
|
||||
osx_close_app();
|
||||
}
|
||||
else if (!keep_running && !osxvars.keep_running){
|
||||
osxvars.keep_running = true;
|
||||
}
|
||||
|
||||
launch_rendering(&sysfunc, &target);
|
||||
}
|
||||
|
||||
external void
|
||||
|
@ -387,7 +500,7 @@ osx_init(){
|
|||
//
|
||||
// OpenGL Init
|
||||
//
|
||||
|
||||
|
||||
typedef PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackProc;
|
||||
|
||||
GLXLOAD(glDebugMessageCallback);
|
||||
|
@ -403,7 +516,7 @@ osx_init(){
|
|||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
//
|
||||
// System Linkage
|
||||
//
|
||||
|
@ -425,7 +538,7 @@ osx_init(){
|
|||
memset(&custom_api, 0, sizeof(custom_api));
|
||||
|
||||
memory_init();
|
||||
|
||||
|
||||
osxvars.keep_running = true;
|
||||
osxvars.input.first_step = true;
|
||||
|
||||
|
@ -470,7 +583,7 @@ osx_init(){
|
|||
|
||||
DBG_POINT();
|
||||
coroutines_init();
|
||||
|
||||
|
||||
//
|
||||
// Font System Init
|
||||
//
|
||||
|
@ -492,20 +605,19 @@ osx_init(){
|
|||
String curdir = make_string(cwd, size);
|
||||
terminate_with_null(&curdir);
|
||||
replace_char(&curdir, '\\', '/');
|
||||
|
||||
|
||||
DBG_POINT();
|
||||
|
||||
|
||||
String clipboard_string = {0};
|
||||
if (osx_objc.has_clipboard_item){
|
||||
clipboard_string = make_string(osx_objc.clipboard_data, osx_objc.clipboard_size);
|
||||
}
|
||||
|
||||
|
||||
DBG_POINT();
|
||||
fprintf(stdout, "%p\n", app.init);
|
||||
|
||||
|
||||
LOG("Initializing application variables\n");
|
||||
app.init(&sysfunc, &target, &memory_vars, clipboard_string, curdir, custom_api);
|
||||
|
||||
|
||||
DBG_POINT();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#define inline internal
|
||||
#include "4ed_defines.h"
|
||||
#undef inline
|
||||
#include "4coder_API/version.h"
|
||||
#include "4coder_API/keycodes.h"
|
||||
|
||||
|
@ -22,12 +24,20 @@
|
|||
|
||||
#include "osx_objective_c_to_cpp_links.h"
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <CoreVideo/CVDisplayLink.h>
|
||||
#import <IOKit/hid/IOHIDLib.h>
|
||||
#import <OpenGL/OpenGL.h>
|
||||
#import <OpenGL/gl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
osx_post_to_clipboard(char *str){
|
||||
NSPasteboard *board = [NSPasteboard generalPasteboard];
|
||||
|
@ -117,10 +127,16 @@ static DISPLINK_SIG(osx_display_link);
|
|||
osx_mouse_wheel(dx, dy);
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(NSWindow*)sender{
|
||||
osx_try_to_close();
|
||||
return(NO);
|
||||
}
|
||||
|
||||
- (CVReturn)getFrameForTime:(const CVTimeStamp*)time{
|
||||
@autoreleasepool
|
||||
{
|
||||
if (osx_objc.running){
|
||||
osx_objc.has_clipboard_item = false;
|
||||
NSPasteboard *board = [NSPasteboard generalPasteboard];
|
||||
if (board.changeCount != osx_objc.prev_clipboard_change_count){
|
||||
if (!osx_objc.just_posted_to_clipboard){
|
||||
|
@ -169,8 +185,7 @@ static DISPLINK_SIG(osx_display_link);
|
|||
|
||||
- (void)init_gl
|
||||
{
|
||||
if(osx_objc.running)
|
||||
{
|
||||
if(osx_objc.running){
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -190,10 +205,9 @@ static DISPLINK_SIG(osx_display_link);
|
|||
};
|
||||
|
||||
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
|
||||
if(format == nil)
|
||||
{
|
||||
fprintf(stderr, "Error creating OpenGLPixelFormat\n");
|
||||
exit(1);
|
||||
if(format == nil){
|
||||
fprintf(stderr, "Error creating OpenGLPixelFormat\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil];
|
||||
|
@ -286,55 +300,297 @@ DISPLINK_SIG(osx_display_link){
|
|||
}
|
||||
@end
|
||||
|
||||
typedef struct File_Table_Entry{
|
||||
u64 hash;
|
||||
void *name;
|
||||
i32 fd;
|
||||
} File_Table_Entry;
|
||||
|
||||
typedef struct File_Change_Queue{
|
||||
char *buffer;
|
||||
char *read_ptr;
|
||||
char *write_ptr;
|
||||
char *end;
|
||||
i32 kq;
|
||||
|
||||
File_Table_Entry *table;
|
||||
i32 table_count;
|
||||
i32 table_size;
|
||||
} File_Change_Queue;
|
||||
|
||||
static File_Change_Queue file_change_queue = {0};
|
||||
|
||||
void
|
||||
osx_add_file_listener(char *file_name){
|
||||
NotImplemented;
|
||||
void*
|
||||
osx_file_name_prefixed_length(char *name){
|
||||
i32 len = 0;
|
||||
for (; name[len] != 0; ++len);
|
||||
char *name_stored = (char*)malloc(4 + l_round_up_u32(len, 4));
|
||||
*(i32*)name_stored = len;
|
||||
memcpy(name_stored + 4, name, len);
|
||||
return(name_stored);
|
||||
}
|
||||
|
||||
b32
|
||||
osx_name_prefixed_match(void *a, void *b){
|
||||
b32 result = false;
|
||||
i32 *len_a = (i32*)a;
|
||||
i32 *len_b = (i32*)b;
|
||||
if (*len_a == *len_b){
|
||||
char *str_a = (char*)(len_a + 1);
|
||||
char *str_b = (char*)(len_b + 1);
|
||||
if (strncmp(str_a, str_b, *len_a) == 0){
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Table_Entry*
|
||||
osx_file_listener_lookup_and_return_pointer(u64 hash, void *name){
|
||||
File_Table_Entry *result = 0;
|
||||
i32 index = (i32)(hash % file_change_queue.table_size);
|
||||
i32 first_index = index;
|
||||
|
||||
for (;;){
|
||||
File_Table_Entry *entry = &file_change_queue.table[index];
|
||||
if (entry->hash == hash){
|
||||
if (osx_name_prefixed_match(name, entry->name)){
|
||||
result = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entry->name == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
index = (index + 1)%file_change_queue.table_size;
|
||||
if (index == first_index){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
b32
|
||||
osx_file_listener_lookup(u64 hash, void *name, i32 *fd_out){
|
||||
b32 found = false;
|
||||
File_Table_Entry *entry = osx_file_listener_lookup_and_return_pointer(hash, name);
|
||||
if (entry != 0){
|
||||
found = true;
|
||||
if (fd_out != 0){
|
||||
*fd_out = entry->fd;
|
||||
}
|
||||
}
|
||||
return(found);
|
||||
}
|
||||
|
||||
b32
|
||||
osx_file_listener_lookup_and_delete(u64 hash, void *name, i32 *fd_out){
|
||||
b32 found = false;
|
||||
File_Table_Entry *entry = osx_file_listener_lookup_and_return_pointer(hash, name);
|
||||
if (entry != 0){
|
||||
found = true;
|
||||
if (fd_out != 0){
|
||||
*fd_out = entry->fd;
|
||||
}
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
entry->name = (void*)1;
|
||||
}
|
||||
return(found);
|
||||
}
|
||||
|
||||
typedef struct Hash_Result{
|
||||
b32 is_in_table;
|
||||
b32 was_already_in_table;
|
||||
} Hash_Result;
|
||||
|
||||
u64
|
||||
osx_file_hash(void *name){
|
||||
u32 count = *(u32*)(name);
|
||||
char *str = (char*)name + 4;
|
||||
u64 hash = 0;
|
||||
u64 state = count;
|
||||
u64 inc = 1 + 2*count;
|
||||
for (u32 i = 0; i <= count; ++i){
|
||||
u64 old_state = state;
|
||||
state = state*6364136223846783005ULL + inc;
|
||||
u32 xorshifted = ((old_state >> 18u) ^ old_state) >> 27u;
|
||||
u32 rot = old_state >> 59u;
|
||||
hash = (hash << 3) + (hash & 1) + ((xorshifted >> rot) | (xorshifted << ((-rot) & 31)));
|
||||
if (i < count){
|
||||
inc = 1 + 2*(((inc - 1) << 7) | (u8)str[i]);
|
||||
}
|
||||
}
|
||||
return(hash);
|
||||
}
|
||||
|
||||
Hash_Result
|
||||
osx_file_listener_hash(u64 hash, void *name, i32 fd){
|
||||
Hash_Result result = {0};
|
||||
if (osx_file_listener_lookup(hash, name, 0)){
|
||||
result.is_in_table = true;
|
||||
result.was_already_in_table = true;
|
||||
}
|
||||
else if (file_change_queue.table_count * 6 < file_change_queue.table_size * 5){
|
||||
i32 index = (i32)(hash % file_change_queue.table_size);
|
||||
i32 first_index = index;
|
||||
|
||||
for (;;){
|
||||
File_Table_Entry *entry = &file_change_queue.table[index];
|
||||
if (entry->name == 0 || entry->name == (void*)1){
|
||||
entry->hash = hash;
|
||||
entry->name = name;
|
||||
entry->fd = fd;
|
||||
result.is_in_table = true;
|
||||
++file_change_queue.table_count;
|
||||
break;
|
||||
}
|
||||
|
||||
index = (index + 1)%file_change_queue.table_size;
|
||||
if (index == first_index){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.is_in_table){
|
||||
fprintf(stdout, "file change listener table error: could not find a free slot in the table\n");
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
Hash_Result
|
||||
osx_file_listener_hash_bundled(File_Table_Entry entry){
|
||||
Hash_Result result = osx_file_listener_hash(entry.hash, entry.name, entry.fd);
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
osx_remove_file_listener(char *file_name){
|
||||
NotImplemented;
|
||||
osx_file_listener_grow_table(i32 table_size){
|
||||
if (file_change_queue.table_size < table_size){
|
||||
File_Table_Entry *old_table = file_change_queue.table;
|
||||
i32 old_size = file_change_queue.table_size;
|
||||
|
||||
file_change_queue.table = (File_Table_Entry*)osx_allocate(table_size*sizeof(File_Table_Entry));
|
||||
memset(file_change_queue.table, 0, table_size*sizeof(File_Table_Entry));
|
||||
file_change_queue.table_size = table_size;
|
||||
|
||||
for (i32 i = 0; i < old_size; ++i){
|
||||
void *name = file_change_queue.table[i].name;
|
||||
if (name != 0 && name != (void*)1){
|
||||
osx_file_listener_hash_bundled(file_change_queue.table[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (old_table != 0){
|
||||
osx_free(old_table, old_size*sizeof(File_Table_Entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
block_split_copy(void *dst, void *src1, i32 size1, void *src2, i32 size2){
|
||||
memcpy(dst, src1, size1);
|
||||
memcpy((u8*)dst + size1, src2, size2);
|
||||
osx_file_listener_double_table(){
|
||||
osx_file_listener_grow_table(file_change_queue.table_size*2);
|
||||
}
|
||||
|
||||
b32
|
||||
osx_file_listener_hash_always(u64 hash, void *name, i32 fd){
|
||||
b32 was_already_in_table = false;
|
||||
Hash_Result result = osx_file_listener_hash(hash, name, fd);
|
||||
if (result.was_already_in_table){
|
||||
was_already_in_table = true;
|
||||
}
|
||||
else if (!result.is_in_table){
|
||||
osx_file_listener_double_table();
|
||||
osx_file_listener_hash(hash, name, fd);
|
||||
}
|
||||
return(was_already_in_table);
|
||||
}
|
||||
|
||||
void
|
||||
osx_file_listener_init(void){
|
||||
memset(&file_change_queue, 0, sizeof(file_change_queue));
|
||||
file_change_queue.kq = kqueue();
|
||||
osx_file_listener_grow_table(1024);
|
||||
}
|
||||
|
||||
void
|
||||
osx_add_file_listener(char *dir_name){
|
||||
DBG_POINT();
|
||||
if (file_change_queue.kq < 0){
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stdout, "ADD_FILE_LISTENER: %s\n", dir_name);
|
||||
|
||||
i32 fd = open(dir_name, O_EVTONLY);
|
||||
if (fd <= 0){
|
||||
fprintf(stdout, "could not open fd for %s\n", dir_name);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(allen): Decide what to do about these darn string mallocs.
|
||||
void *name_stored = osx_file_name_prefixed_length(dir_name);
|
||||
|
||||
struct kevent new_kevent;
|
||||
EV_SET(&new_kevent, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_DELETE|NOTE_WRITE, 0, name_stored);
|
||||
|
||||
struct timespec t = {0};
|
||||
kevent(file_change_queue.kq, &new_kevent, 1, 0, 0, &t);
|
||||
|
||||
b32 was_already_in_table = osx_file_listener_hash_always(osx_file_hash(name_stored), name_stored, fd);
|
||||
if (was_already_in_table){
|
||||
free(name_stored);
|
||||
}
|
||||
|
||||
DBG_POINT();
|
||||
}
|
||||
|
||||
void
|
||||
osx_remove_file_listener(char *dir_name){
|
||||
void *name = osx_file_name_prefixed_length(dir_name);
|
||||
i32 fd;
|
||||
if (osx_file_listener_lookup_and_delete(osx_file_hash(name), name, &fd)){
|
||||
close(fd);
|
||||
}
|
||||
free(name);
|
||||
}
|
||||
|
||||
i32
|
||||
osx_get_file_change_event(char *buffer, i32 max, i32 *size){
|
||||
i32 result = 0;
|
||||
if (file_change_queue.read_ptr != file_change_queue.write_ptr){
|
||||
i32 change_size = *(i32*)file_change_queue.read_ptr;
|
||||
if (max <= change_size){
|
||||
char *b1 = file_change_queue.read_ptr + 4;
|
||||
char *b2 = file_change_queue.buffer;
|
||||
i32 b1_size = Min(change_size, (i32)(file_change_queue.end - b1));
|
||||
i32 b2_size = change_size - b1_size;
|
||||
block_split_copy(buffer, b1, b1_size, b2, b2_size);
|
||||
if (b1 < file_change_queue.end){
|
||||
file_change_queue.read_ptr = b1 + change_size;
|
||||
}
|
||||
else{
|
||||
file_change_queue.read_ptr = b2 + b2_size;
|
||||
}
|
||||
result = 1;
|
||||
}
|
||||
else{
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
if (file_change_queue.kq < 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
i32 result = 0;
|
||||
struct timespec t = {0};
|
||||
struct kevent event_out;
|
||||
i32 count = kevent(file_change_queue.kq, 0, 0, &event_out, 1, &t);
|
||||
if (count < 0 || (count > 0 && event_out.flags == EV_ERROR)){
|
||||
fprintf(stdout, "count: %4d error: %s\n", count, strerror(errno));
|
||||
}
|
||||
else if (count > 0){
|
||||
if (event_out.udata != 0){
|
||||
i32 len = *(i32*)event_out.udata;
|
||||
char *str = (char*)((i32*)event_out.udata + 1);
|
||||
fprintf(stdout, "got an event for file: %.*s\n", len, str);
|
||||
if (len <= max){
|
||||
*size = len;
|
||||
memcpy(buffer, str, len);
|
||||
result = 1;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): Cache this miss for retrieval???
|
||||
// TODO(allen): Better yet, always cache every event on every platform and therefore make two calls per event, but always with enough memory!??
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
osx_close_app(void){
|
||||
[NSApp terminate: nil];
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -347,6 +603,8 @@ main(int argc, char **argv){
|
|||
osx_objc.argc = argc;
|
||||
osx_objc.argv = argv;
|
||||
|
||||
osx_file_listener_init();
|
||||
|
||||
@autoreleasepool{
|
||||
NSApplication *app = [NSApplication sharedApplication];
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
|
|
@ -19,14 +19,29 @@ init_track_system(File_Track_System *system, Partition *scratch, void *table_mem
|
|||
File_Track_Result
|
||||
add_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
#if 1
|
||||
#if 0
|
||||
// HACK(allen) HACK(allen) HACK(allen)
|
||||
char strspace[1024];
|
||||
String str = make_fixed_width_string(strspace);
|
||||
copy(&str, (char*)filename);
|
||||
remove_last_folder(&str);
|
||||
--str.size;
|
||||
terminate_with_null(&str);
|
||||
osx_add_file_listener(str.str);
|
||||
#else
|
||||
osx_add_file_listener((char*)filename);
|
||||
#endif
|
||||
#endif
|
||||
return(result);
|
||||
}
|
||||
|
||||
File_Track_Result
|
||||
remove_listener(File_Track_System *system, Partition *scratch, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
#if 1
|
||||
osx_remove_file_listener((char*)filename);
|
||||
#endif
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,14 @@
|
|||
#if !defined(OSX_OBJECTIVE_C_TO_CPP_LINKS_H)
|
||||
#define OSX_OBJECTIVE_C_TO_CPP_LINKS_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if 0
|
||||
#define DBG_POINT() fprintf(stdout, "%s\n", __FILE__ ":" LINE_STR ":")
|
||||
#else
|
||||
#define DBG_POINT()
|
||||
#endif
|
||||
|
||||
typedef enum OSX_Mouse_Event_Type{
|
||||
MouseType_Move,
|
||||
MouseType_Press,
|
||||
|
@ -37,13 +45,13 @@ typedef struct OSX_Objective_C_Vars{
|
|||
void *clipboard_data;
|
||||
umem clipboard_size, clipboard_max;
|
||||
b32 just_posted_to_clipboard;
|
||||
|
||||
|
||||
char *clipboard_space;
|
||||
umem clipboard_space_max;
|
||||
|
||||
|
||||
b32 full_screen;
|
||||
b32 do_toggle;
|
||||
|
||||
|
||||
i32 argc;
|
||||
char **argv;
|
||||
} OSX_Objective_C_Vars;
|
||||
|
@ -54,6 +62,9 @@ extern OSX_Objective_C_Vars osx_objc;
|
|||
external void*
|
||||
osx_allocate(umem size);
|
||||
|
||||
external void
|
||||
osx_free(void *ptr, umem size);
|
||||
|
||||
external void
|
||||
osx_resize(int width, int height);
|
||||
|
||||
|
@ -66,6 +77,9 @@ osx_mouse(i32 mx, i32 my, u32 type);
|
|||
external void
|
||||
osx_mouse_wheel(float dx, float dy);
|
||||
|
||||
external void
|
||||
osx_try_to_close(void);
|
||||
|
||||
external void
|
||||
osx_step();
|
||||
|
||||
|
@ -88,6 +102,9 @@ osx_remove_file_listener(char *file_name);
|
|||
external i32
|
||||
osx_get_file_change_event(char *buffer, i32 max, i32 *size);
|
||||
|
||||
external void
|
||||
osx_close_app(void);
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -940,7 +940,7 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
|
|||
case WM_DESTROY:
|
||||
{
|
||||
win32vars.got_useful_event = true;
|
||||
win32vars.input_chunk.trans.trying_to_kill = 1;
|
||||
win32vars.input_chunk.trans.trying_to_kill = true;
|
||||
}break;
|
||||
|
||||
case WM_4coder_ANIMATE:
|
||||
|
|
|
@ -14,3 +14,10 @@ fkey_command_linux[2] = {"build_site.sh" , "*site*" , fals
|
|||
fkey_command_linux[3] = {"build_string.sh" , "*compilation*" , true , true };
|
||||
fkey_command_linux[4] = {"echo build: x86 & ./build.sh -DDEV_BUILD_X86" , "*compilation*", true, true };
|
||||
fkey_command_linux[12] = {"./package.sh" , "*package*" , false, true };
|
||||
|
||||
fkey_command_mac[1] = {"echo build: x64 & ./build.sh", "*compilation*" , true , true };
|
||||
fkey_command_mac[2] = {"build_site.sh" , "*site*" , false, true };
|
||||
fkey_command_mac[3] = {"build_string.sh" , "*compilation*" , true , true };
|
||||
fkey_command_mac[4] = {"echo build: x86 & ./build.sh -DDEV_BUILD_X86" , "*compilation*", true, true };
|
||||
fkey_command_mac[12] = {"./package.sh" , "*package*" , false, true };
|
||||
|
||||
|
|
Loading…
Reference in New Issue