From 56f5d78fa2fb423b98cd5e86e088367d7b0409e9 Mon Sep 17 00:00:00 2001 From: Alex Baines Date: Tue, 4 Feb 2020 21:38:37 +0000 Subject: [PATCH] runs but quite broken --- platform_linux/linux_4ed.cpp | 164 +++++++++++++++++++++---- platform_linux/linux_4ed_functions.cpp | 69 ++++++----- 2 files changed, 178 insertions(+), 55 deletions(-) diff --git a/platform_linux/linux_4ed.cpp b/platform_linux/linux_4ed.cpp index 4e52618a..cd3dce61 100644 --- a/platform_linux/linux_4ed.cpp +++ b/platform_linux/linux_4ed.cpp @@ -15,11 +15,6 @@ #define SLASH '/' #define DLL "so" -#define container_of(ptr, type, member) ({ \ - const typeof(((type*)0)->member)* __mptr = (ptr); \ - (type*)((char*)__mptr - offsetof(type, member)); \ -}) - #include "4coder_base_types.h" #include "4coder_version.h" #include "4coder_events.h" @@ -95,6 +90,10 @@ #define function static #undef Cursor +#undef internal +#include +#define internal static + #include #include @@ -149,6 +148,7 @@ struct Linux_Vars { int xfixes_selection_event; XIM xim; XIC xic; + FcConfig* fontconfig; Linux_Input_Chunk input; @@ -291,6 +291,20 @@ linux_free_object(Linux_Object *object){ //////////////////////////// +internal int +linux_compare_file_infos(File_Info** a, File_Info** b) { + b32 a_hidden = (*a)->file_name.str[0] == '.'; + b32 b_hidden = (*b)->file_name.str[0] == '.'; + + // hidden files lower in list + if(a_hidden != b_hidden) { + return a_hidden - b_hidden; + } + + // push_stringf seems to null terminate + return strcoll((char*)(*a)->file_name.str, (char*)(*b)->file_name.str); +} + internal int linux_system_get_file_list_filter(const struct dirent *dirent) { String_Const_u8 file_name = SCu8((u8*)dirent->d_name); @@ -316,11 +330,11 @@ linux_convert_file_attribute_flags(int mode) { } internal File_Attributes -linux_file_attributes_from_struct_stat(struct stat file_stat) { +linux_file_attributes_from_struct_stat(struct stat* file_stat) { File_Attributes result = {}; - result.size = file_stat.st_size; - result.last_write_time = linux_u64_from_timespec(file_stat.st_mtim); - result.flags = linux_convert_file_attribute_flags(file_stat.st_mode); + result.size = file_stat->st_size; + result.last_write_time = linux_u64_from_timespec(file_stat->st_mtim); + result.flags = linux_convert_file_attribute_flags(file_stat->st_mode); return result; } @@ -501,8 +515,74 @@ graphics_fill_texture_sig(){ //////////////////////////// +internal Face_Description +linux_find_font(Face_Description* desc) { + Face_Description result = *desc; + + char* name = strndupa((char*)desc->font.file_name.str, desc->font.file_name.size); + + double size; + const char* style; + { + Face_Load_Parameters* p = &desc->parameters; + size = p->pt_size; + + if(p->bold && p->italic) { + style = "Bold Italic"; + } else if(p->bold) { + style = "Bold"; + } else if(p->italic) { + style = "Italic"; + } else { + style = "Regular"; + } + } + + FcPattern *pattern = FcPatternBuild( + 0, + FC_POSTSCRIPT_NAME, FcTypeString, name, + FC_SIZE, FcTypeDouble, size, + FC_FONTFORMAT, FcTypeString, "TrueType", + FC_STYLE, FcTypeString, (FcChar8*)style, + NULL); + + if(!pattern) { + return result; + } + + if (FcConfigSubstitute(linuxvars.fontconfig, pattern, FcMatchPattern)){ + FcDefaultSubstitute(pattern); + + FcResult res; + FcPattern *font = FcFontMatch(linuxvars.fontconfig, pattern, &res); + if (!font){ + return result; + } + + FcChar8 *filename = 0; + FcPatternGetString(font, FC_FILE, 0, &filename); + if(filename) { + printf("FONTCONFIG FILENAME = %s\n", filename); + result.font.file_name = push_u8_stringf(linuxvars.frame_arena, "%s", filename); + } + + FcPatternDestroy(font); + } + + FcPatternDestroy(pattern); + + return result; +} + internal font_make_face_sig() { + + // FIXME + if(description->font.file_name.str[0] != '/') { + Face_Description desc2 = linux_find_font(description); + description = &desc2; + } + Face* result = ft__font_make_face(arena, description, scale_factor); if(!result) { @@ -690,7 +770,7 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { render_target.height = h; XSetWindowAttributes swa = {}; - swa.backing_store = WhenMapped; + swa.backing_store = NotUseful; swa.event_mask = StructureNotifyMask; swa.bit_gravity = NorthWestGravity; swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi.screen), vi.visual, AllocNone); @@ -892,7 +972,6 @@ linux_keycode_init(Display* dpy){ *p++ = { XK_equal, KeyCode_Equal }; *p++ = { XK_bracketleft, KeyCode_LeftBracket }; *p++ = { XK_bracketright, KeyCode_RightBracket }; - *p++ = { XK_bracketright, KeyCode_RightBracket }; *p++ = { XK_semicolon, KeyCode_Semicolon }; *p++ = { XK_apostrophe, KeyCode_Quote }; *p++ = { XK_comma, KeyCode_Comma }; @@ -957,7 +1036,7 @@ linux_keycode_init(Display* dpy){ XFree(syms); } -internal b32 +internal void linux_handle_x11_events() { static XEvent prev_event = {}; b32 should_step = false; @@ -993,9 +1072,9 @@ linux_handle_x11_events() { Status status; KeySym keysym = NoSymbol; - u8 buff[32] = {}; + u8 buff[256] = {}; - Xutf8LookupString(linuxvars.xic, &event.xkey, (char*)buff, sizeof(buff) - 1, &keysym, &status); + int len = Xutf8LookupString(linuxvars.xic, &event.xkey, (char*)buff, sizeof(buff) - 1, &keysym, &status); if (status == XBufferOverflow){ //TODO(inso): handle properly @@ -1003,17 +1082,27 @@ linux_handle_x11_events() { XSetICFocus(linuxvars.xic); } - // don't push modifiers - if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R){ - break; - } - if (keysym == XK_ISO_Left_Tab){ //text = '\t'; add_modifier(mods, KeyCode_Shift); } - // TODO: use keycode_lookup_table, push the key and text. + Key_Code key = keycode_lookup_table[(u8)event.xkey.keycode]; + printf("key [%d] = %s\n", event.xkey.keycode, key_code_name[key]); + + if(key) { + Input_Event *ev = push_input_event(linuxvars.frame_arena, &linuxvars.input.trans.event_list); + ev->kind = InputEventKind_KeyStroke; + ev->key.code = key; + ev->key.modifiers = copy_modifier_set(linuxvars.frame_arena, mods); + } + + if(status == XLookupChars || status == XLookupBoth) { + u8* ptr = push_array_write(linuxvars.frame_arena, u8, len, buff); + Input_Event* ev = push_input_event(linuxvars.frame_arena, &linuxvars.input.trans.event_list); + ev->kind = InputEventKind_TextInsert; + ev->text.string = SCu8(ptr, len); + } } break; @@ -1023,8 +1112,23 @@ linux_handle_x11_events() { linux_keycode_init(linuxvars.dpy); } } break; + + case ConfigureNotify: { + should_step = true; + i32 w = event.xconfigure.width; + i32 h = event.xconfigure.height; + + if (w != render_target.width || h != render_target.height){ + render_target.width = w; + render_target.height = h; + } + } break; } } + + if(should_step) { + linux_schedule_step(); + } } internal b32 @@ -1058,7 +1162,7 @@ linux_epoll_process(struct epoll_event* events, int num_events) { } break; case EPOLL_USER_TIMER: { - Linux_Object* obj = container_of(tag, Linux_Object, timer.epoll_tag); + Linux_Object* obj = CastFromMember(Linux_Object, timer.epoll_tag, tag); close(obj->timer.fd); obj->timer.fd = -1; do_step = true; @@ -1092,6 +1196,8 @@ main(int argc, char **argv){ // TODO(allen): *arena; render_target.arena = make_arena_system(KB(256)); + linuxvars.fontconfig = FcInitLoadConfigAndFonts(); + linuxvars.cursor_show = MouseCursorShow_Always; linuxvars.prev_cursor_show = MouseCursorShow_Always; @@ -1262,6 +1368,7 @@ main(int argc, char **argv){ linux_schedule_step(); + b32 first_step = true; b32 keep_running = true; for (;keep_running;){ @@ -1288,7 +1395,6 @@ main(int argc, char **argv){ continue; } - b32 first_step = true; linuxvars.last_step_time = system_now_time(); // NOTE(allen): Frame Clipboard Input @@ -1297,21 +1403,24 @@ main(int argc, char **argv){ XConvertSelection(linuxvars.dpy, linuxvars.atom_CLIPBOARD, linuxvars.atom_UTF8_STRING, linuxvars.atom_CLIPBOARD, linuxvars.win, CurrentTime); } - Application_Step_Input frame_input = {}; + Application_Step_Input input = {}; if (linuxvars.received_new_clipboard){ - frame_input.clipboard = linuxvars.clipboard_contents; + input.clipboard = linuxvars.clipboard_contents; linuxvars.received_new_clipboard = false; } // TODO: fill the rest of it - frame_input.trying_to_kill = !keep_running; + input.trying_to_kill = !keep_running; + input.dt = frame_useconds/1000000.f; + input.events = linuxvars.input.trans.event_list; + input.first_step = first_step; // NOTE(allen): Application Core Update // render_target.buffer.pos = 0; Application_Step_Result result = {}; if (app.step != 0){ - result = app.step(&linuxvars.tctx, &render_target, base_ptr, &frame_input); + result = app.step(&linuxvars.tctx, &render_target, base_ptr, &input); } else{ //LOG("app.step == 0 -- skipping\n"); @@ -1346,6 +1455,9 @@ main(int argc, char **argv){ glXSwapBuffers(linuxvars.dpy, linuxvars.win); first_step = false; + + linalloc_clear(linuxvars.frame_arena); + block_zero_struct(&linuxvars.input.trans); } return 0; diff --git a/platform_linux/linux_4ed_functions.cpp b/platform_linux/linux_4ed_functions.cpp index b75a794b..e66ee31d 100644 --- a/platform_linux/linux_4ed_functions.cpp +++ b/platform_linux/linux_4ed_functions.cpp @@ -64,41 +64,52 @@ internal File_List system_get_file_list(Arena* arena, String_Const_u8 directory){ LINUX_FN_DEBUG("%.*s", (int)directory.size, directory.str); File_List result = {}; - String_Const_u8 search_pattern = {}; - if (character_is_slash(string_get_character(directory, directory.size - 1))){ - search_pattern = push_u8_stringf(arena, "%.*s*", string_expand(directory)); - } - else{ - search_pattern = push_u8_stringf(arena, "%.*s/*", string_expand(directory)); + char* path = strndupa((char*)directory.str, directory.size); + int fd = open(path, O_RDONLY | O_DIRECTORY); + if(fd == -1) { + perror("open"); + return result; } - struct dirent** dir_ents = NULL; - int num_ents = scandir( - (const char*)search_pattern.str, &dir_ents, linux_system_get_file_list_filter, alphasort); + DIR* dir = fdopendir(fd); + struct dirent* d; - File_Info *first = 0; - File_Info *last = 0; - for (int i = 0; i < num_ents; ++i) { - struct dirent* dirent = dir_ents[i]; - File_Info *info = push_array(arena, File_Info, 1); - sll_queue_push(first, last, info); + File_Info* head = NULL; + File_Info** fip = &head; - info->file_name = SCu8((u8*)dirent->d_name); + while((d = readdir(dir))) { + const char* name = d->d_name; - struct stat file_stat; - stat((const char*)dirent->d_name, &file_stat); - info->attributes = linux_file_attributes_from_struct_stat(file_stat); + // ignore . and .. + if(*name == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) { + continue; + } + + *fip = push_array(arena, File_Info, 1); + (*fip)->file_name = push_u8_stringf(arena, "%.*s", d->d_reclen, name); + + struct stat st; + if(fstatat(fd, name, &st, 0) == -1){ + perror("fstatat"); + } + + (*fip)->attributes = linux_file_attributes_from_struct_stat(&st); + fip = &(*fip)->next; + result.count++; + } + closedir(dir); + + result.infos = fip = push_array(arena, File_Info*, result.count); + + for(File_Info* f = head; f; f = f->next) { + *fip++ = f; } - result.infos = push_array(arena, File_Info*, num_ents); - result.count = num_ents; + qsort(result.infos, result.count, sizeof(File_Info*), (__compar_fn_t)&linux_compare_file_infos); - i32 info_index = 0; - for (File_Info* node = first; node != NULL; node = node->next) { - result.infos[info_index] = node; - info_index += 1; - } + + // TODO: relink in new order? return result; } @@ -108,7 +119,7 @@ system_quick_file_attributes(Arena* scratch, String_Const_u8 file_name){ LINUX_FN_DEBUG("%.*s", (int)file_name.size, file_name.str); struct stat file_stat; stat((const char*)file_name.str, &file_stat); - return linux_file_attributes_from_struct_stat(file_stat); + return linux_file_attributes_from_struct_stat(&file_stat); } internal b32 @@ -127,7 +138,7 @@ system_load_attributes(Plat_Handle handle){ LINUX_FN_DEBUG(); struct stat file_stat; fstat(*(int*)&handle, &file_stat); - return linux_file_attributes_from_struct_stat(file_stat); + return linux_file_attributes_from_struct_stat(&file_stat); } internal b32 @@ -158,7 +169,7 @@ system_save_file(Arena* scratch, char* file_name, String_Const_u8 data){ if (bytes_written != -1) { struct stat file_stat; fstat(fd, &file_stat); - return linux_file_attributes_from_struct_stat(file_stat); + return linux_file_attributes_from_struct_stat(&file_stat); } } return result;