From 30a2a95b690a58ab3e2f590f22190d4b47c7fcbe Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Tue, 13 Sep 2016 15:56:14 -0400 Subject: [PATCH] fixed up file track issue --- 4ed.cpp | 21 ++-- 4ed_file.cpp | 6 +- 4ed_file_view.cpp | 12 +-- TODO.txt | 13 +-- build.c | 1 - filetrack/4tech_file_track_win32.c | 164 +++++++++++++++++------------ 6 files changed, 120 insertions(+), 97 deletions(-) diff --git a/4ed.cpp b/4ed.cpp index 64c5cfff..580d82aa 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -353,13 +353,17 @@ COMMAND_DECL(reopen){ General_Memory *general = &models->mem.general; File_Edit_Positions edit_poss[16]; + int32_t line_number[16]; + int32_t column_number[16]; View *vptrs[16]; i32 vptr_count = 0; for (View_Iter iter = file_view_iter_init(&models->layout, file, 0); file_view_iter_good(iter); iter = file_view_iter_next(iter)){ vptrs[vptr_count] = iter.view; - edit_poss[vptr_count] = *iter.view->edit_pos; + edit_poss[vptr_count] = iter.view->edit_pos[0]; + line_number[vptr_count] = iter.view->edit_pos[0].cursor.line; + column_number[vptr_count] = iter.view->edit_pos[0].cursor.character; iter.view->edit_pos = 0; ++vptr_count; } @@ -367,13 +371,18 @@ COMMAND_DECL(reopen){ file_close(system, general, file); init_normal_file(system, models, file, buffer, size); - for (i32 i = 0; - i < vptr_count; - ++i){ + for (i32 i = 0; i < vptr_count; ++i){ view_set_file(vptrs[i], file, models); + + int32_t line = line_number[i]; + int32_t column = column_number[i]; + *vptrs[i]->edit_pos = edit_poss[i]; - view_set_cursor(vptrs[i], edit_poss[i].cursor, - true, view->file_data.unwrapped_lines); + Full_Cursor cursor = + view_compute_cursor_from_line_pos(vptrs[i], line, column); + + view_set_cursor(vptrs[i], cursor, true, + view->file_data.unwrapped_lines); } } } diff --git a/4ed_file.cpp b/4ed_file.cpp index 6ac5fd8c..71a93f69 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -41,11 +41,7 @@ struct File_Edit_Positions{ i32 last_set_type; b32 in_view; }; -inline File_Edit_Positions -file_edit_positions_zero(){ - File_Edit_Positions data = {0}; - return(data); -} +static File_Edit_Positions null_edit_pos = {0}; enum Edit_Type{ ED_NORMAL, diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 58d8661d..6292fbba 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -505,14 +505,14 @@ view_compute_cursor_from_xy(View *view, f32 seek_x, f32 seek_y){ Full_Cursor result; if (view->file_data.unwrapped_lines) result = view_compute_cursor_from_unwrapped_xy(view, seek_x, seek_y); else result = view_compute_cursor_from_wrapped_xy(view, seek_x, seek_y); - return result; + return(result); } inline i32 view_wrapped_line_span(f32 line_width, f32 max_width){ i32 line_count = CEIL32(line_width / max_width); if (line_count == 0) line_count = 1; - return line_count; + return(line_count); } internal i32 @@ -535,7 +535,7 @@ view_compute_lowest_line(View *view){ lowest_line += line_span - 1; } } - return lowest_line; + return(lowest_line); } inline i32 @@ -646,10 +646,8 @@ view_move_cursor_to_view(View *view, GUI_Scroll_Vars scroll, } internal void -view_set_cursor(View *view, - Full_Cursor cursor, - b32 set_preferred_x, - b32 unwrapped_lines){ +view_set_cursor(View *view, Full_Cursor cursor, + b32 set_preferred_x, b32 unwrapped_lines){ if (edit_pos_move_to_front(view->file_data.file, view->edit_pos)){ edit_pos_set_cursor_(view->edit_pos, cursor, set_preferred_x, unwrapped_lines); diff --git a/TODO.txt b/TODO.txt index 349af51c..9be1606a 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,10 +1,11 @@ + ; Started this list on: (18.01.2016)(dd.mm.yyyy) ; This list is an informal todo list, it may very well miss items ; checked or unchecked, that I inted to do some day. It is included ; in the distribution so that you may take a look and see if your ; requested feature is there, and if not, so that you may remind me. ; Cheers everyone! -; + ; BUGS ; [X] '\t' thing ; [X] smoothness in smoothscrolling isn't very smooth @@ -74,6 +75,7 @@ ; [X] paths with parens in them ; [X] killing compilation panel changes active panel ; [X] make panel resizing not whacky with child panels +; [X] visual studio file saves aren't picked up by the file track system ; ; [] indication on failure to save ; [] history is broken, revist the entire system @@ -83,12 +85,6 @@ ; [] view fails to follow cursor when the view is shrunk ; [] view fails to follow cursor after deleting long line ; -; - -; BEFORE I SHIP -; -; [] occasionally missing the (!) mark on files on windows -; ; TODOS ; [X] success message when compiler works @@ -144,7 +140,7 @@ ; [] switch to line classification system ; [] more built in options for auto indenting ; -; + ; [] binary buffers ; [] commands for resizing panels ; [] user file bar string @@ -273,6 +269,7 @@ ; [] a triangle rendered for a few frames? color of the dirty markers (not reproduced by me yet) ; [] minimize and reopen problem (not reproduced by me yet) ; +; ; FANCY-PANTS IDEAS ; [] pass messages to 'jobs' to try to avoid cancelling them diff --git a/build.c b/build.c index eac2a18f..52eac7a3 100644 --- a/build.c +++ b/build.c @@ -867,4 +867,3 @@ int main(int argc, char **argv){ #endif // BOTTOM - diff --git a/filetrack/4tech_file_track_win32.c b/filetrack/4tech_file_track_win32.c index 5f3db59c..43323c8e 100644 --- a/filetrack/4tech_file_track_win32.c +++ b/filetrack/4tech_file_track_win32.c @@ -116,6 +116,17 @@ internal_get_file_index(BY_HANDLE_FILE_INFORMATION info){ return(hash); } +#define FLAGS ( \ +FILE_NOTIFY_CHANGE_FILE_NAME | \ +FILE_NOTIFY_CHANGE_DIR_NAME | \ +FILE_NOTIFY_CHANGE_ATTRIBUTES | \ +FILE_NOTIFY_CHANGE_SIZE | \ +FILE_NOTIFY_CHANGE_LAST_WRITE | \ +FILE_NOTIFY_CHANGE_LAST_ACCESS| \ +FILE_NOTIFY_CHANGE_SECURITY | \ +FILE_NOTIFY_CHANGE_CREATION | \ +0) + FILE_TRACK_LINK File_Track_Result add_listener(File_Track_System *system, char *filename){ File_Track_Result result = FileTrack_Good; @@ -157,8 +168,8 @@ add_listener(File_Track_System *system, char *filename){ if (ReadDirectoryChangesW(dir, node->listener.result, sizeof(node->listener.result), - 0, - FILE_NOTIFY_CHANGE_LAST_WRITE, + 1, + FLAGS, 0, &node->listener.overlapped, 0)){ @@ -250,6 +261,7 @@ remove_listener(File_Track_System *system, char *filename){ if (node->listener.user_count == 0){ insert_node(&vars->free_sentinel, &node->node); + CancelIo(win32_dir->dir); CloseHandle(win32_dir->dir); internal_free_slot(tables, dir_lookup); } @@ -316,6 +328,10 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t * File_Track_Result result = FileTrack_NoMoreEvents; Win32_File_Track_Vars *vars = to_vars(system); + static int32_t has_buffered_event = 0; + static DWORD offset = 0; + static Win32_Directory_Listener listener; + EnterCriticalSection(&vars->table_lock); { @@ -323,78 +339,83 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t * DWORD length = 0; ULONG_PTR key = 0; - if (GetQueuedCompletionStatus(vars->iocp, - &length, - &key, - &overlapped, - 0)){ - - Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped; - - // NOTE(allen): Get a copy of the state of this node so we can set the node - // to work listening for changes again right away. - Win32_Directory_Listener listener = *listener_ptr; - - ZeroStruct(listener_ptr->overlapped); - ReadDirectoryChangesW(listener_ptr->dir, - listener_ptr->result, - sizeof(listener_ptr->result), - 0, - FILE_NOTIFY_CHANGE_LAST_WRITE, - 0, - &listener_ptr->overlapped, - 0); - - char *listener_buffer = listener.result; - DWORD offset = 0; - FILE_NOTIFY_INFORMATION *info = 0; - - for (;;){ - info = (FILE_NOTIFY_INFORMATION*)(listener_buffer + offset); + int32_t has_result = 0; + + if (has_buffered_event){ + has_buffered_event = 0; + has_result = 1; + } + else{ + if (GetQueuedCompletionStatus(vars->iocp, + &length, + &key, + &overlapped, + 0)){ + Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped; - int32_t len = info->FileNameLength / 2; - int32_t dir_len = GetFinalPathNameByHandle(listener.dir, 0, 0, - FILE_NAME_NORMALIZED); - int32_t req_size = dir_len + 1 + len; - *size = req_size; - if (req_size < max){ - int32_t pos = 0; - - pos = GetFinalPathNameByHandle(listener.dir, buffer, max, - FILE_NAME_NORMALIZED); - buffer[pos++] = '\\'; - - for (int32_t i = 0; i < len; ++i, ++pos){ - buffer[pos] = (char)info->FileName[i]; - } - - if (buffer[0] == '\\'){ - for (int32_t i = 0; i+4 < pos; ++i){ - buffer[i] = buffer[i+4]; - } - *size -= 4; - } - - result = FileTrack_Good; - } - else{ - // TODO(allen): Need some way to stash this result so that if the - // user comes back with more memory we can give them the change - // notification they missed. - result = FileTrack_MemoryTooSmall; + // NOTE(allen): Get a copy of the state of this node so we can set the node + // to work listening for changes again right away. + listener = *listener_ptr; + + ZeroStruct(listener_ptr->overlapped); + ReadDirectoryChangesW(listener_ptr->dir, + listener_ptr->result, + sizeof(listener_ptr->result), + 1, + FLAGS, + 0, + &listener_ptr->overlapped, + 0); + + offset = 0; + has_result = 1; + } + } + + if (has_result){ + + FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*)(listener.result + offset); + + int32_t len = info->FileNameLength / 2; + int32_t dir_len = GetFinalPathNameByHandle(listener.dir, 0, 0, + FILE_NAME_NORMALIZED); + + int32_t req_size = dir_len + 1 + len; + *size = req_size; + if (req_size < max){ + int32_t pos = 0; + + pos = GetFinalPathNameByHandle(listener.dir, buffer, max, + FILE_NAME_NORMALIZED); + buffer[pos++] = '\\'; + + for (int32_t i = 0; i < len; ++i, ++pos){ + buffer[pos] = (char)info->FileName[i]; } - if (info->NextEntryOffset != 0){ - // TODO(allen): We're not ready to handle this yet. - // For now I am breaking. In the future, if there - // are more results we should stash them and return - // them in future calls. - offset += info->NextEntryOffset; - break; - } - else{ - break; + if (buffer[0] == '\\'){ + for (int32_t i = 0; i+4 < pos; ++i){ + buffer[i] = buffer[i+4]; + } + *size -= 4; } + + result = FileTrack_Good; + } + else{ + // TODO(allen): Need some way to stash this result so that if the + // user comes back with more memory we can give them the change + // notification they missed. + result = FileTrack_MemoryTooSmall; + } + + if (info->NextEntryOffset != 0){ + // TODO(allen): We're not ready to handle this yet. + // For now I am breaking. In the future, if there + // are more results we should stash them and return + // them in future calls. + offset += info->NextEntryOffset; + has_buffered_event = 1; } } } @@ -424,6 +445,9 @@ shut_down_track_system(File_Track_System *system){ if (!entry_is_available(entry)){ Win32_File_Track_Entry *win32_entry = (Win32_File_Track_Entry*)entry; + if (!CancelIo(win32_entry->dir)){ + win32_result = 1; + } if (!CloseHandle(win32_entry->dir)){ win32_result = 1; }