diff --git a/main.c b/main.c index b476a56..9e55d3e 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include typedef struct { char *path; @@ -419,7 +419,8 @@ void rzf_sort_files(void) { } void rzf_draw_file_preview(WINDOW *win, const char *filepath) { - if (!win) return; + if (!win) + return; werase(win); box(win, 0, 0); @@ -581,11 +582,17 @@ void *rzf_indexing_worker_func(void *arg) { struct stat statbuf; if (lstat(path, &statbuf) == 0) { int is_dir = S_ISDIR(statbuf.st_mode); + char real[PATH_MAX]; + if (realpath(path, real) == NULL) /* canonical, absolute path */ + continue; local_batch[local_count].path = strdup(path); local_batch[local_count].lower_path = rzf_to_lower(path); - if (!local_batch[local_count].path || !local_batch[local_count].lower_path) { - if (local_batch[local_count].path) free(local_batch[local_count].path); - if (local_batch[local_count].lower_path) free(local_batch[local_count].lower_path); + if (!local_batch[local_count].path || + !local_batch[local_count].lower_path) { + if (local_batch[local_count].path) + free(local_batch[local_count].path); + if (local_batch[local_count].lower_path) + free(local_batch[local_count].lower_path); continue; } local_batch[local_count].size = statbuf.st_size; @@ -714,7 +721,7 @@ int rzf_recursive_delete(const char *path) { struct stat path_stat; if (lstat(path, &path_stat) != 0) return -1; - + if (!S_ISDIR(path_stat.st_mode)) { return remove(path); } @@ -762,7 +769,8 @@ void rzf_draw_help_window(int height, int width) { int start_y = (height - h) / 2; int start_x = (width - w) / 2; WINDOW *win = newwin(h, w, start_y, start_x); - if (!win) return; + if (!win) + return; box(win, 0, 0); wattron(win, A_BOLD); mvwprintw(win, 1, (w - 10) / 2, "Shortcuts"); @@ -795,11 +803,13 @@ void rzf_draw_help_window(int height, int width) { bool rzf_show_confirmation(int height, int width, const char *message) { int h = 3, w = strlen(message) + 8; - if (w > width - 4) w = width - 4; + if (w > width - 4) + w = width - 4; int start_y = (height - h) / 2; int start_x = (width - w) / 2; WINDOW *win = newwin(h, w, start_y, start_x); - if (!win) return false; + if (!win) + return false; box(win, 0, 0); mvwprintw(win, 1, 2, "%.*s (y/n)", w - 8, message); wrefresh(win); @@ -820,11 +830,13 @@ bool rzf_show_confirmation(int height, int width, const char *message) { char *rzf_prompt_for_command(int height, int width) { int h = 3, w = 60; - if (w > width - 4) w = width - 4; + if (w > width - 4) + w = width - 4; int start_y = (height - h) / 2; int start_x = (width - w) / 2; WINDOW *win = newwin(h, w, start_y, start_x); - if (!win) return NULL; + if (!win) + return NULL; box(win, 0, 0); mvwprintw(win, 1, 2, "Command: "); wrefresh(win); @@ -952,12 +964,75 @@ char *rzf_run_interface(char **selected_file_path) { pthread_mutex_lock(&files_mutex); int file_idx = filtered_indices[selected_index]; if (file_idx < file_count) { - *selected_file_path = strdup(files[file_idx].path); - command = strdup(files[file_idx].is_dir ? "xdg-open" : "vim"); + if (files[file_idx].is_dir) { + // Navigate into directory + char *dir_path = strdup(files[file_idx].path); + pthread_mutex_unlock(&files_mutex); + + if (dir_path && chdir(dir_path) == 0) { + // Clear the queue + pthread_mutex_lock(&queue_mutex); + for (int i = 0; i < queue_count; i++) { + int idx = (queue_head + i) % DIR_QUEUE_CAPACITY; + if (dir_queue[idx]) { + free(dir_queue[idx]); + dir_queue[idx] = NULL; + } + } + queue_head = 0; + queue_tail = 0; + queue_count = 0; + pthread_mutex_unlock(&queue_mutex); + + // Clear files + pthread_mutex_lock(&files_mutex); + if (files) { + for (int i = 0; i < file_count; i++) { + free(files[i].path); + free(files[i].lower_path); + } + free(files); + } + files = NULL; + file_count = 0; + file_capacity = 0; + pthread_mutex_unlock(&files_mutex); + + // Cancel and restart indexing + if (indexing_started && !indexing_complete) { + pthread_cancel(indexing_thread); + pthread_join(indexing_thread, NULL); + } + indexing_complete = false; + indexing_started = false; + producer_finished = false; + active_workers = 0; + pthread_create(&indexing_thread, NULL, rzf_indexing_thread_func, NULL); + + search_query[0] = '\0'; + selected_index = 0; + scroll_offset = 0; + } + if (dir_path) free(dir_path); + } else { + // Open file + char abs[PATH_MAX]; + if (realpath(files[file_idx].path, abs)) + *selected_file_path = strdup(abs); /* always absolute */ + else /* fallback (shouldn't)*/ + *selected_file_path = strdup(files[file_idx].path); + + command = strdup("vim"); + pthread_mutex_unlock(&files_mutex); + goto end_loop; + } + } else { + pthread_mutex_unlock(&files_mutex); } - pthread_mutex_unlock(&files_mutex); } - goto end_loop; + break; + + case 27: case 3: goto end_loop; @@ -988,13 +1063,10 @@ char *rzf_run_interface(char **selected_file_path) { if (dot) { snprintf(backup_path, sizeof(backup_path), "%.*s/.%.*s%s%s.bak", - (int)dir_len, path, - (int)(dot - fname), fname, - dt, dot); + (int)dir_len, path, (int)(dot - fname), fname, dt, dot); } else { snprintf(backup_path, sizeof(backup_path), "%.*s/.%s%s.bak", - (int)dir_len, path, - fname, dt); + (int)dir_len, path, fname, dt); } char cmd[PATH_MAX * 2 + 10]; @@ -1090,21 +1162,22 @@ char *rzf_run_interface(char **selected_file_path) { } if (confirmed) { if (selected_count > 0) { - char **paths_to_delete = malloc(selected_count * sizeof(char*)); + char **paths_to_delete = malloc(selected_count * sizeof(char *)); int *is_dir_flags = malloc(selected_count * sizeof(int)); int delete_count = 0; - + pthread_mutex_lock(&files_mutex); for (int i = 0; i < selected_count; i++) { if (selected_indices[i] < file_count) { - paths_to_delete[delete_count] = strdup(files[selected_indices[i]].path); + paths_to_delete[delete_count] = + strdup(files[selected_indices[i]].path); is_dir_flags[delete_count] = files[selected_indices[i]].is_dir; if (paths_to_delete[delete_count]) delete_count++; } } pthread_mutex_unlock(&files_mutex); - + for (int i = 0; i < delete_count; i++) { if (is_dir_flags[i]) rzf_recursive_delete(paths_to_delete[i]); @@ -1129,7 +1202,7 @@ char *rzf_run_interface(char **selected_file_path) { free(p); } } - + pthread_mutex_lock(&queue_mutex); for (int i = 0; i < queue_count; i++) { int idx = (queue_head + i) % DIR_QUEUE_CAPACITY; @@ -1142,7 +1215,7 @@ char *rzf_run_interface(char **selected_file_path) { queue_tail = 0; queue_count = 0; pthread_mutex_unlock(&queue_mutex); - + pthread_mutex_lock(&files_mutex); if (files) { for (int i = 0; i < file_count; i++) { @@ -1155,7 +1228,7 @@ char *rzf_run_interface(char **selected_file_path) { file_count = 0; file_capacity = 0; pthread_mutex_unlock(&files_mutex); - + if (indexing_started && !indexing_complete) { pthread_cancel(indexing_thread); pthread_join(indexing_thread, NULL); @@ -1164,7 +1237,8 @@ char *rzf_run_interface(char **selected_file_path) { indexing_started = false; producer_finished = false; active_workers = 0; - pthread_create(&indexing_thread, NULL, rzf_indexing_thread_func, NULL); + pthread_create(&indexing_thread, NULL, rzf_indexing_thread_func, + NULL); } } break; @@ -1222,7 +1296,7 @@ char *rzf_run_interface(char **selected_file_path) { queue_tail = 0; queue_count = 0; pthread_mutex_unlock(&queue_mutex); - + pthread_mutex_lock(&files_mutex); if (files) { for (int i = 0; i < file_count; i++) { @@ -1235,7 +1309,7 @@ char *rzf_run_interface(char **selected_file_path) { file_count = 0; file_capacity = 0; pthread_mutex_unlock(&files_mutex); - + if (indexing_started && !indexing_complete) { pthread_cancel(indexing_thread); pthread_join(indexing_thread, NULL); @@ -1244,7 +1318,8 @@ char *rzf_run_interface(char **selected_file_path) { indexing_started = false; producer_finished = false; active_workers = 0; - pthread_create(&indexing_thread, NULL, rzf_indexing_thread_func, NULL); + pthread_create(&indexing_thread, NULL, rzf_indexing_thread_func, + NULL); search_query[0] = '\0'; selected_index = 0; scroll_offset = 0; @@ -1280,7 +1355,8 @@ char *rzf_run_interface(char **selected_file_path) { free(fp); } } - if (cmd) free(cmd); + if (cmd) + free(cmd); } break; case 22: @@ -1312,7 +1388,8 @@ char *rzf_run_interface(char **selected_file_path) { current_file_count = file_count; if (current_file_count > filtered_capacity) { filtered_capacity = current_file_count * 2; - int *new_filtered = realloc(filtered_indices, filtered_capacity * sizeof(int)); + int *new_filtered = + realloc(filtered_indices, filtered_capacity * sizeof(int)); if (!new_filtered) { pthread_mutex_unlock(&files_mutex); continue; @@ -1324,7 +1401,8 @@ char *rzf_run_interface(char **selected_file_path) { char search_pattern[256]; if (filter_start) { size_t len = filter_start - search_query; - if (len >= sizeof(search_pattern)) len = sizeof(search_pattern) - 1; + if (len >= sizeof(search_pattern)) + len = sizeof(search_pattern) - 1; strncpy(search_pattern, search_query, len); search_pattern[len] = '\0'; } else { @@ -1379,7 +1457,8 @@ char *rzf_run_interface(char **selected_file_path) { for (int i = 0; i < list_height && (i + scroll_offset) < filtered_count; ++i) { int current_index = i + scroll_offset; - if (current_index >= filtered_count) continue; + if (current_index >= filtered_count) + continue; int file_idx = filtered_indices[current_index]; if (file_idx >= file_count) continue; @@ -1500,7 +1579,7 @@ int main() { signal(SIGINT, rzf_cleanup_terminal); signal(SIGTERM, rzf_cleanup_terminal); signal(SIGHUP, rzf_cleanup_terminal); - + pthread_create(&indexing_thread, NULL, rzf_indexing_thread_func, NULL); char *file_to_open = NULL; char *command = rzf_run_interface(&file_to_open); @@ -1508,7 +1587,7 @@ int main() { pthread_cancel(indexing_thread); } pthread_join(indexing_thread, NULL); - + pthread_mutex_lock(&queue_mutex); for (int i = 0; i < queue_count; i++) { int idx = (queue_head + i) % DIR_QUEUE_CAPACITY; @@ -1518,13 +1597,18 @@ int main() { } } pthread_mutex_unlock(&queue_mutex); - + if (command && file_to_open) { - reset_shell_mode(); - pid_t pid = fork(); + reset_shell_mode(); + pid_t pid = fork(); if (pid == 0) { - execlp(command, command, file_to_open, NULL); - perror("execlp failed"); + char abs_path[PATH_MAX]; + if (realpath(file_to_open, abs_path)) { + execlp("vim", "vim", abs_path, (char *)NULL); + perror("execlp failed"); + } else + perror("realpath"); + exit(EXIT_FAILURE); } else if (pid > 0) { wait(NULL); @@ -1533,8 +1617,9 @@ int main() { } free(file_to_open); } - if (command) free(command); - + if (command) + free(command); + rzf_free_files(); rzf_free_bookmarks(); pthread_mutex_destroy(&files_mutex); diff --git a/main.o b/main.o index 25c6c9e..d6fb005 100644 Binary files a/main.o and b/main.o differ diff --git a/rzf b/rzf index 0f093d4..316f007 100755 Binary files a/rzf and b/rzf differ