#include #include #include #include #include #include #include #include #include "config.h" #include "dir.h" #include "file_previews.h" pthread_mutex_t mutex_top; pthread_mutex_t mutex_btm; pthread_mutex_t mutex_lft; pthread_mutex_t mutex_mid; pthread_mutex_t mutex_rgt; pthread_mutex_t mutex_render; pthread_cond_t cond_mid; pthread_cond_t cond_rgt; pthread_cond_t cond_lft; pthread_cond_t cond_top; pthread_cond_t cond_btm; dir rgt_dir; dir mid_dir; dir lft_dir; char *rgt_buffer; /* used for file previews, unlike rgt_content, which is used for directory previews */ char *btm_buffer; char *top_buffer; /* current path */ extern WINDOW *win_t; extern WINDOW *win_b; extern WINDOW *win_l; extern WINDOW *win_m; extern WINDOW *win_r; unsigned long top_width; extern unsigned int terminal_width; extern unsigned int status; extern char *global_path; unsigned int btm_status; void *thread_mid(){ dir tmp; tmp.current_file = NULL; tmp.file_list = NULL; tmp.file_count = 0; while(!(status & STATUS_QUIT_PROGRAM)){ pthread_mutex_lock(&mutex_mid); pthread_cond_wait(&cond_mid, &mutex_mid); if (global_path == NULL) { mid_dir.current_file = NULL; mid_dir.file_count = 0; pthread_mutex_unlock(&mutex_mid); continue; } char *path = malloc(strlen(global_path)+1); memcpy(path, global_path, strlen(global_path)+1); if (status & STATUS_RELOAD_DIRECTORY) { long index = mid_dir.current_file - mid_dir.file_list; tmp = mid_dir; mid_dir.file_count = get_dir_size(path); mid_dir.file_list = malloc(mid_dir.file_count * sizeof(file)); if (mid_dir.file_count) { /* fails if dir empty */ get_dir_content(path, &mid_dir); mid_dir.current_file = &mid_dir.file_list[index]; } else { /* the hovered dir is empty */ mid_dir.current_file = NULL; } unsigned long i; for(i = 0; i < mid_dir.file_count && i < tmp.file_count; i++) { mid_dir.file_list[i].status = tmp.file_list[i].status; } } if (mid_dir.current_file > mid_dir.file_list + mid_dir.file_count - 1) { mid_dir.current_file = mid_dir.file_list + mid_dir.file_count - 1; } if (mid_dir.current_file < mid_dir.file_list) { mid_dir.current_file = mid_dir.file_list; } pthread_mutex_unlock(&mutex_mid); pthread_cond_signal(&cond_top); pthread_cond_signal(&cond_btm); pthread_cond_signal(&cond_rgt); /* rendering */ pthread_mutex_lock(&mutex_render); werase(win_m); if (mid_dir.file_count == 0) { mvwaddstr(win_m, 0, 0, "empty"); } else { print_dir(win_m, 1, &mid_dir); } wnoutrefresh(win_m); pthread_mutex_unlock(&mutex_render); unsigned long i; for (i = 0; i < tmp.file_count; i++) { free(tmp.file_list[i].file_name); } free(tmp.file_list); tmp.current_file = NULL; tmp.file_list = NULL; tmp.file_count = 0; } pthread_exit(0); } void *thread_lft(){ while(!(status & STATUS_QUIT_PROGRAM)){ pthread_mutex_lock(&mutex_lft); pthread_cond_wait(&cond_lft, &mutex_lft); if (global_path == NULL) { lft_dir.current_file = NULL; lft_dir.file_count = 0; pthread_mutex_unlock(&mutex_lft); continue; } char *path = malloc(strlen(global_path)+1); memcpy(path, global_path, strlen(global_path)+1); if (strcmp(path, "/") != 0) { path[strrchr(path, '/')-path+1] = '\0'; path[strrchr(path, '/')-path] = '\0'; path[0] = '/'; if (status & STATUS_RELOAD_DIRECTORY) { unsigned long i = 0; for (i = 0; i < lft_dir.file_count; i++) { free(lft_dir.file_list[i].file_name); } free(lft_dir.file_list); lft_dir.file_count = get_dir_size(path); if (lft_dir.file_count != 0) { lft_dir.file_list = malloc(lft_dir.file_count * sizeof(file)); get_dir_content(path, &lft_dir); } else { lft_dir.current_file = NULL; lft_dir.file_count = 0; } } } else { lft_dir.file_count = 0; } /* rendering */ pthread_mutex_lock(&mutex_render); werase(win_l); print_dir(win_l, 0, &lft_dir); wnoutrefresh(win_l); pthread_mutex_unlock(&mutex_render); pthread_mutex_unlock(&mutex_lft); free(path); } pthread_exit(0); } void *thread_rgt(){ dir tmp; tmp.current_file = NULL; tmp.file_list = NULL; tmp.file_count = 0; while(!(status & STATUS_QUIT_PROGRAM)){ pthread_mutex_lock(&mutex_rgt); pthread_cond_wait(&cond_rgt, &mutex_rgt); pthread_mutex_lock(&mutex_mid); char *file_name = malloc(strlen(mid_dir.current_file->file_name)+1); file_name = memcpy(file_name, mid_dir.current_file->file_name, strlen(mid_dir.current_file->file_name)+1); rgt_dir.file_list = malloc(sizeof(file)); memcpy(rgt_dir.file_list, mid_dir.current_file, sizeof(file)); rgt_dir.file_list->file_name = file_name; rgt_dir.current_file = rgt_dir.file_list; rgt_dir.file_count = 1; pthread_mutex_unlock(&mutex_mid); if (rgt_dir.current_file->permissions & S_IRUSR) { if (rgt_dir.current_file->file_type &= FILE_TYPE_DIR) { #if SETTINGS_UEBERZUG_IMAGE_PREVIEW != 0 images_clear(); #endif tmp = rgt_dir; rgt_dir.file_count = get_dir_size(rgt_dir.current_file->file_name); rgt_dir.file_list = malloc(rgt_dir.file_count * sizeof(file)); if (rgt_dir.file_count) { /* fails if dir empty */ get_dir_content(tmp.current_file->file_name, &rgt_dir); } else { /* the hovered dir is empty */ rgt_dir.current_file = NULL; } pthread_mutex_lock(&mutex_render); werase(win_r); print_dir(win_r, 0, &rgt_dir); wnoutrefresh(win_r); pthread_mutex_unlock(&mutex_render); } else if ((status & STATUS_DELTA_TIME) != STATUS_DELTA_TIME && rgt_dir.file_count > 0) { free(rgt_buffer); rgt_buffer = preview_file(rgt_dir.current_file); rgt_dir.current_file->file_type |= FILE_TYPE_OPEN_FILE; pthread_mutex_lock(&mutex_render); werase(win_r); if (rgt_dir.current_file->file_type == FILE_TYPE_OPEN_FILE) { mvwaddnstr(win_r, 0, 0, rgt_buffer, (terminal_width/2) * terminal_width); } else if ((rgt_dir.current_file->permissions & S_IRUSR) == 0) { mvwaddstr(win_r, 0, 0, "not accessible"); } wnoutrefresh(win_r); pthread_mutex_unlock(&mutex_render); } } pthread_mutex_unlock(&mutex_rgt); unsigned long i; for (i = 0; i < tmp.file_count; i++) { free(tmp.file_list[i].file_name); } free(tmp.file_list); tmp.current_file = NULL; tmp.file_list = NULL; tmp.file_count = 0; } pthread_exit(0); } void *thread_top(){ while(!(status & STATUS_QUIT_PROGRAM)){ pthread_mutex_lock(&mutex_top); pthread_cond_wait(&cond_top, &mutex_top); free(top_buffer); if(global_path == NULL) { top_buffer = malloc(sizeof("cannot open directory")); top_width = sizeof("cannot open directory"); top_buffer = "cannot open directory"; pthread_mutex_unlock(&mutex_top); continue; } pthread_mutex_lock(&mutex_mid); top_buffer = malloc(strlen(global_path)+1 + strlen(mid_dir.current_file->file_name)+1); memcpy(top_buffer, global_path, strlen(global_path)); memcpy(top_buffer + strlen(global_path) + 1, mid_dir.current_file->file_name, strlen(mid_dir.current_file->file_name)+1); pthread_mutex_unlock(&mutex_mid); top_buffer[strlen(global_path)] = '/'; top_width = strlen(top_buffer); /* rendering */ pthread_mutex_lock(&mutex_render); werase(win_t); wattron(win_t, COLOR_PAIR(COLOR_PATH)); mvwaddnstr(win_t, 0, 0, top_buffer, strlen(global_path)+1); wattroff(win_t, COLOR_PAIR(COLOR_PATH)); mvwaddstr(win_t, 0, strlen(global_path)+1, top_buffer+strlen(global_path)+1); wnoutrefresh(win_t); pthread_mutex_unlock(&mutex_render); pthread_mutex_unlock(&mutex_top); } pthread_exit(0); } void *thread_btm(){ char *path = NULL; char *ui_btm_right_block = malloc(sizeof(char)); unsigned int ui_btm_right_block_size = 0; unsigned int buffer_width = 0; while(!(status & STATUS_QUIT_PROGRAM)){ pthread_mutex_lock(&mutex_btm); pthread_cond_wait(&cond_btm, &mutex_btm); if (status & (STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY)) { /*{{{ parse storage info; the fold of shame*/ pthread_mutex_lock(&mutex_mid); unsigned long i; float total_dir_size = 0; for(i = 0; i < mid_dir.file_count; i++) { if ((mid_dir.file_list[i].file_type & (FILE_TYPE_DIR)) != FILE_TYPE_DIR) { total_dir_size += mid_dir.file_list[i].file_size; } } pthread_mutex_unlock(&mutex_mid); free(ui_btm_right_block); if(path) { free(path); } path = getcwd(NULL, 0); struct statvfs fs; statvfs(path, &fs); float disk_size_free = fs.f_bsize * fs.f_bavail; float parsed_number[2] = { 0 }; char size_index[2] = { 0 }; if (total_dir_size > 1) { size_index[0] = -1; while (total_dir_size > 1 && size_index[0] < size_unit_count) { parsed_number[0]=total_dir_size; size_index[0]++; total_dir_size /= 1024; } } else { size_index[0] = 0; parsed_number[0] = 0; } if (disk_size_free > 1) { size_index[1] = -1; while (disk_size_free > 1 && size_index[1] < size_unit_count) { parsed_number[1]=disk_size_free; size_index[1]++; disk_size_free /= 1024; } } else { size_index[1] = 0; } if (size_index[0] > 0 && size_index[1] > 0) { ui_btm_right_block_size = snprintf(NULL, 0, "%0.2lf%c %s %0.2lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left)+1; ui_btm_right_block = malloc(ui_btm_right_block_size); sprintf(ui_btm_right_block, "%0.2lf%c %s %0.2lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left); } else if (size_index[0] <= 0 && size_index[1] > 0) { ui_btm_right_block_size = snprintf(NULL, 0, "%0.0lf%c %s %0.2lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left)+1; ui_btm_right_block = malloc(ui_btm_right_block_size); sprintf(ui_btm_right_block, "%0.0lf%c %s %0.2lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left); } else if (size_index[0] > 0 && size_index[1] <= 0) { ui_btm_right_block_size = snprintf(NULL, 0, "%0.2lf%c %s %0.0lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left)+1; ui_btm_right_block = malloc(ui_btm_right_block_size); sprintf(ui_btm_right_block, "%0.2lf%c %s %0.0lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left); } else { ui_btm_right_block_size = snprintf(NULL, 0, "%0.0lf%c %s %0.0lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left)+1; ui_btm_right_block = malloc(ui_btm_right_block_size); sprintf(ui_btm_right_block, "%0.0lf%c %s %0.0lf%c %s", parsed_number[0], size_unit[(unsigned)size_index[0]], ui_btm_current_dir_size, parsed_number[1], size_unit[(unsigned)size_index[1]], ui_btm_text_storage_left); } /*}}}*/ } if (buffer_width != terminal_width) { buffer_width = terminal_width; free(btm_buffer); btm_buffer = malloc(buffer_width+1); } memset(btm_buffer, ' ', buffer_width); btm_buffer[buffer_width] = '\0'; memcpy(btm_buffer + buffer_width - ui_btm_right_block_size, ui_btm_right_block, ui_btm_right_block_size); btm_buffer[0] = (S_ISLNK(mid_dir.current_file->permissions)) ? 'l': (S_ISDIR(mid_dir.current_file->permissions) ? 'd': '-'); btm_buffer[1] = (mid_dir.current_file->permissions & S_IRUSR) ? 'r' : '-'; btm_buffer[2] = (mid_dir.current_file->permissions & S_IWUSR) ? 'w' : '-'; btm_buffer[3] = (mid_dir.current_file->permissions & S_IXUSR) ? 'x' : '-'; btm_buffer[4] = (mid_dir.current_file->permissions & S_IRGRP) ? 'r' : '-'; btm_buffer[5] = (mid_dir.current_file->permissions & S_IWGRP) ? 'w' : '-'; btm_buffer[6] = (mid_dir.current_file->permissions & S_IXGRP) ? 'x' : '-'; btm_buffer[7] = (mid_dir.current_file->permissions & S_IROTH) ? 'r' : '-'; btm_buffer[8] = (mid_dir.current_file->permissions & S_IWOTH) ? 'w' : '-'; btm_buffer[9] = (mid_dir.current_file->permissions & S_IXOTH) ? 'x' : '-'; /* rendering */ pthread_mutex_lock(&mutex_render); werase(win_b); if (*top_buffer != ' ') { /*printing ' ' (standard initialized value, see threading_init) makes valgrind throw a fuss*/ mvwprintw(win_b, 0, 0, "%s", btm_buffer); } wnoutrefresh(win_b); pthread_mutex_unlock(&mutex_render); pthread_mutex_unlock(&mutex_btm); /*the printing of all possible inputs are done in user_interactions */ pthread_mutex_unlock(&mutex_btm); } pthread_exit(0); } void threading_init(){ top_buffer = malloc(sizeof(char)); rgt_buffer = malloc(sizeof(char)); btm_buffer = malloc(sizeof(char)); memset(top_buffer, '\0', sizeof(char)); memset(rgt_buffer, '\0', sizeof(char)); memset(btm_buffer, '\0', sizeof(char)); pthread_mutex_init(&mutex_top, NULL); pthread_mutex_init(&mutex_mid, NULL); pthread_mutex_init(&mutex_lft, NULL); pthread_mutex_init(&mutex_btm, NULL); pthread_mutex_init(&mutex_rgt, NULL); pthread_mutex_init(&mutex_render, NULL); pthread_cond_init(&cond_rgt, NULL); pthread_cond_init(&cond_lft, NULL); pthread_cond_init(&cond_mid, NULL); pthread_cond_init(&cond_top, NULL); pthread_cond_init(&cond_btm, NULL); } void threading_free(){ free(top_buffer); pthread_mutex_destroy(&mutex_top); pthread_mutex_destroy(&mutex_mid); pthread_mutex_destroy(&mutex_lft); }