mac layer almost finished

master
Allen Webster 2017-11-07 16:35:26 -05:00
parent 82882f22f5
commit 772adc67a3
14 changed files with 550 additions and 128 deletions

View File

@ -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.) */

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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();
}

View File

@ -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];

View File

@ -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);
}

View File

@ -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

View File

@ -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:

View File

@ -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 };