#include #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; file *rgt_content; file *mid_content; file *lft_content; 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 rgt_file_count = 0; unsigned long mid_file_count = 0; unsigned long lft_file_count; unsigned long top_width; volatile unsigned long selected_file_current = 0; volatile unsigned long selected_file_last = 0; extern unsigned int terminal_width; extern unsigned int status; unsigned int btm_status; void *thread_mid(){ while(!(status & STATUS_QUIT_PROGRAM)){ pthread_mutex_lock(&mutex_mid); pthread_cond_wait(&cond_mid, &mutex_mid); unsigned int local_status = status; char *path; if((path=getcwd(NULL, 0)) == NULL) { mid_content = malloc(sizeof(file)); mid_content->file_name = "cannot open directory"; mid_file_count = 1; } else { if (local_status & STATUS_RELOAD_DIRECTORY) { unsigned long i = 0; for (i = 0; i < mid_file_count; i++) { free(mid_content[i].file_name); } free(mid_content); mid_file_count = get_dir_size(path); if (mid_file_count != 0) { mid_content = malloc(mid_file_count * sizeof(file)); memset(mid_content, '\0', mid_file_count * sizeof(file)); get_dir_content(path, &mid_file_count, mid_content); } else { selected_file_current = 0; mid_content = malloc(sizeof(file)); mid_content->file_type = 0; mid_content->file_size = 0; mid_content->permissions = 0; mid_content->color_pair = 0; mid_content->file_name = malloc(sizeof(char)); mid_content->file_name[0] = '\0'; mid_file_count = 0; } pthread_mutex_lock(&mutex_selection); update_selected_file(); pthread_mutex_unlock(&mutex_selection); } btm_status = local_status; pthread_cond_signal(&cond_rgt); pthread_cond_signal(&cond_btm); } free(path); pthread_mutex_unlock(&mutex_mid); } 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; char *path; if((path=getcwd(NULL, 0)) == NULL) { lft_content = malloc(sizeof(file)); lft_content[0].file_name = "cannot open directory"; lft_file_count = 1; } else { path[strrchr(path, '/')-path] = '\0'; path[0] = '/'; if (local_status & STATUS_RELOAD_DIRECTORY) { lft_file_count = get_dir_size(path); free(lft_content); lft_content = malloc(lft_file_count * sizeof(file)); memset(lft_content, '\0', lft_file_count * sizeof(file)); get_dir_content(path, &lft_file_count, lft_content); } } free(path); pthread_mutex_unlock(&mutex_lft); } pthread_exit(0); } void *thread_rgt(){ file file_current; while(!(status & STATUS_QUIT_PROGRAM)){ pthread_mutex_lock(&mutex_rgt); pthread_cond_wait(&cond_rgt, &mutex_rgt); pthread_mutex_lock(&mutex_mid); char *path; if (mid_file_count != 0) { path = malloc(strlen(mid_content[selected_file_current].file_name) + 1); strcpy(path, mid_content[selected_file_current].file_name); } else { path = malloc(sizeof(char)); path[0] = '\0'; } file_current.file_type = mid_content[selected_file_current].file_type; file_current.file_size = mid_content[selected_file_current].file_size; file_current.status = mid_content[selected_file_current].status; pthread_mutex_unlock(&mutex_mid); if (mid_content[selected_file_current].permissions & S_IRUSR) { if (file_current.file_type &= FILE_TYPE_DIR) { #if SETTINGS_UEBERZUG_IMAGE_PREVIEW != 0 images_clear(); #endif unsigned long i = 0; for (i = 0; i < rgt_file_count; i++) { if (rgt_content[i].file_name) { free(rgt_content[i].file_name); } } free(rgt_content); rgt_file_count = get_dir_size(path); rgt_content = malloc(rgt_file_count * sizeof(file)); memset(rgt_content, '\0', rgt_file_count * sizeof(file)); get_dir_content(path, &rgt_file_count, rgt_content); rgt_content[0].status &= ~FILE_STATUS_FILE_OPEN; free(rgt_buffer); rgt_buffer = malloc(sizeof(char)); rgt_buffer[0] = '\0'; } else if ((status & STATUS_DELTA_TIME) != STATUS_DELTA_TIME) { unsigned long i = 0; for (i = 0; i < rgt_file_count; i++) { if (rgt_content[i].file_name) { free(rgt_content[i].file_name); } } free(rgt_content); rgt_file_count = 0; rgt_content = malloc(sizeof(file)); free(rgt_buffer); rgt_content->file_type = FILE_TYPE_OPEN_FILE; rgt_content->status = FILE_STATUS_HOVER; rgt_buffer = preview_file(path, file_current.file_size); } } else { unsigned long i = 0; for (i = 0; i < rgt_file_count; i++) { if (rgt_content[i].file_name) { free(rgt_content[i].file_name); } } free(rgt_content); rgt_file_count = 0; rgt_content = malloc(sizeof(file)); free(rgt_buffer); rgt_buffer = malloc(sizeof(char)); rgt_buffer[0] = '\0'; } free(path); pthread_mutex_unlock(&mutex_rgt); } 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); char *path; if((path=getcwd(NULL, 0)) == NULL) { top_buffer = malloc(sizeof("cannot open directory")); top_width = sizeof("cannot open directory"); top_buffer = "cannot open directory"; } else { top_buffer = malloc(strlen(path)+1); memcpy(top_buffer, path, strlen(path)+1); top_width = strlen(top_buffer); } free(path); 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_file_count; i++) { if ((mid_content[i].file_type & (FILE_TYPE_DIR)) != FILE_TYPE_DIR) { total_dir_size += mid_content[i].file_size; } } pthread_mutex_unlock(&mutex_mid); if (path != NULL) { /* sometimes NULL remains, need to do deeper analysis soon */ free(path); path = NULL; } else { volatile static int debug_thread_btm; debug_thread_btm++; } free(ui_btm_right_block); 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); memset(btm_buffer, ' ', buffer_width/2); } memset(btm_buffer + (buffer_width/2), ' ', buffer_width/2); 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_ISDIR(mid_content[selected_file_current].permissions)) ? 'd' : '-'; btm_buffer[1] = (mid_content[selected_file_current].permissions & S_IRUSR) ? 'r' : '-'; btm_buffer[2] = (mid_content[selected_file_current].permissions & S_IWUSR) ? 'w' : '-'; btm_buffer[3] = (mid_content[selected_file_current].permissions & S_IXUSR) ? 'x' : '-'; btm_buffer[4] = (mid_content[selected_file_current].permissions & S_IRGRP) ? 'r' : '-'; btm_buffer[5] = (mid_content[selected_file_current].permissions & S_IWGRP) ? 'w' : '-'; btm_buffer[6] = (mid_content[selected_file_current].permissions & S_IXGRP) ? 'x' : '-'; btm_buffer[7] = (mid_content[selected_file_current].permissions & S_IROTH) ? 'r' : '-'; btm_buffer[8] = (mid_content[selected_file_current].permissions & S_IWOTH) ? 'w' : '-'; btm_buffer[9] = (mid_content[selected_file_current].permissions & S_IXOTH) ? 'x' : '-'; pthread_mutex_unlock(&mutex_btm); } pthread_exit(0); } void threading_init(){ rgt_content = malloc(sizeof(file)); mid_content = malloc(sizeof(file)); lft_content = malloc(sizeof(file)); 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)); mid_content->file_type = 0; mid_content->file_size = 0; mid_content->file_name = malloc(sizeof(char)); mid_content->file_name[0] = '\0'; rgt_content->file_type = 0; rgt_content->file_size = 0; rgt_content->file_name = malloc(sizeof(char)); rgt_content->file_name[0] = '\0'; volatile char vol; /* needed to make sure higher optimization steps dont move these around */ vol = pthread_mutex_init(&mutex_top, NULL); vol = pthread_mutex_init(&mutex_mid, NULL); vol = pthread_mutex_init(&mutex_lft, NULL); vol = pthread_mutex_init(&mutex_btm, NULL); vol = pthread_mutex_init(&mutex_rgt, NULL); vol = pthread_mutex_init(&mutex_selection, NULL); vol = pthread_cond_init(&cond_rgt, NULL); vol = pthread_cond_init(&cond_lft, NULL); vol = pthread_cond_init(&cond_mid, NULL); vol = pthread_cond_init(&cond_top, NULL); vol = pthread_cond_init(&cond_btm, NULL); vol; selected_file_current = 0; selected_file_last = 0; } void threading_free(){ free(rgt_content); free(mid_content); free(lft_content); free(top_buffer); pthread_mutex_destroy(&mutex_top); pthread_mutex_destroy(&mutex_mid); pthread_mutex_destroy(&mutex_lft); }