#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_selection; 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 */ 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); unsigned int local_status = status; if (global_path == NULL) { mid_dir.current_file = NULL; mid_dir.file_count = 0; continue; } char *path = malloc(strlen(global_path)+1); memcpy(path, global_path, strlen(global_path)+1); if (local_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; } } pthread_cond_signal(&cond_rgt); btm_status = local_status; pthread_cond_signal(&cond_btm); pthread_mutex_unlock(&mutex_mid); 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); unsigned int local_status = status; 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 (local_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; } free(path); pthread_mutex_unlock(&mutex_lft); } 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; } } else if ((status & STATUS_DELTA_TIME) != STATUS_DELTA_TIME && mid_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; } } else { } pthread_mutex_unlock(&mutex_rgt); 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; } top_buffer = malloc(strlen(global_path)+1); memcpy(top_buffer, global_path, strlen(global_path)+1); top_width = strlen(top_buffer); /*printing of mid_dir.current_file->file_name is done directly in window.c window_top()*/ 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); unsigned int local_status = btm_status; if (local_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' : '-'; 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_selection, 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); }