#include #include #include #include #include #include #include #include "defines.h" #include "backend.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_mutex_t mutex_wait; pthread_cond_t cond_wait; int wait_count; /* this is used to determine how many threads are waiting for cont_wait */ 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; file *file_current; char *top_buffer; /* current path */ unsigned long rgt_file_count; unsigned long mid_file_count; unsigned long lft_file_count; unsigned long top_width; unsigned long selected_file_current=0; unsigned long selected_file_last=0; unsigned int status_mid; extern unsigned int status; extern unsigned int terminal_width; void *thread_mid(void *data){ pthread_mutex_lock(&mutex_mid); char *path; if((path=getcwd(NULL, 0)) == NULL) { mid_content = malloc(sizeof(file)); mid_content->file_name_width = sizeof("cannot open directory"); mid_content->file_name = "cannot open directory"; mid_file_count = 1; } else { if (status & STATUS_RELOAD_DIRECTORY) { free(mid_content); mid_file_count = (unsigned long)get_dir_size(path); if (mid_file_count > 0) { mid_content = malloc(mid_file_count * sizeof(file)); memset(mid_content, ' ', mid_file_count * sizeof(file)); get_dir_content(path, &mid_file_count, mid_content); } else { mid_content = malloc(sizeof(file)); mid_content->status = FILE_STATUS_DIR_EMPTY; mid_content->file_type = 0; mid_content->file_size = 0; mid_content->permissions = 0; mid_content->color_pair = 0; mid_content->file_name_width = sizeof("empty dir"); mid_content->file_name = "empty dir"; file_current->file_name = mid_content->file_name; file_current->file_name_width = mid_content->file_name_width; file_current->file_size = mid_content->file_size; file_current->file_type = mid_content->file_type; file_current->color_pair = mid_content->color_pair; file_current->permissions = mid_content->permissions; file_current->status = mid_content->status; mid_file_count = 0; while(wait_count < 2){ /*wait for thread_rgt and thread_btm to lock*/ } pthread_mutex_lock(&mutex_wait); pthread_cond_broadcast(&cond_wait); pthread_mutex_unlock(&mutex_wait); free(path); pthread_mutex_unlock(&mutex_mid); pthread_exit(0); } } pthread_mutex_lock(&mutex_selection); while(1) { /* this useless while loop exists for the singular purpose of making valgrind happy */ if (selected_file_current >= mid_file_count) { selected_file_current = mid_file_count-1; } else { mid_content[selected_file_current].status |= FILE_STATUS_HOVER; if (selected_file_current != selected_file_last) { mid_content[selected_file_last].status &= ~FILE_STATUS_HOVER; } selected_file_last = selected_file_current; file_current->file_name = mid_content[selected_file_current].file_name; file_current->file_name_width = mid_content[selected_file_current].file_name_width; file_current->file_size = mid_content[selected_file_current].file_size; file_current->file_type = mid_content[selected_file_current].file_type; file_current->color_pair = mid_content[selected_file_current].color_pair; file_current->permissions = mid_content[selected_file_current].permissions; file_current->status = mid_content[selected_file_current].status; while(wait_count < 2){ /*wait for thread_rgt and thread_btm to lock*/ } pthread_mutex_lock(&mutex_wait); pthread_cond_broadcast(&cond_wait); pthread_mutex_unlock(&mutex_wait); break; } } pthread_mutex_unlock(&mutex_selection); } free(path); pthread_mutex_unlock(&mutex_mid); pthread_exit(0); } void *thread_lft(void *data){ pthread_mutex_lock(&mutex_lft); char *path; if((path=getcwd(NULL, 0)) == NULL) { lft_content = malloc(sizeof(file)); lft_content[0].file_name_width = sizeof("cannot open directory"); lft_content[0].file_name = "cannot open directory"; lft_file_count = 1; } else { path[strrchr(path, '/')-path] = '\0'; path[0] = '/'; if (status & STATUS_RELOAD_DIRECTORY) { free(lft_content); lft_file_count = (unsigned long)get_dir_size(path); lft_content = malloc(lft_file_count * sizeof(file)); memset(lft_content, ' ', 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(void *data){ pthread_mutex_lock(&mutex_rgt); pthread_mutex_lock(&mutex_wait); wait_count++; pthread_cond_wait(&cond_wait, &mutex_wait); wait_count--; pthread_mutex_unlock(&mutex_wait); pthread_mutex_lock(&mutex_mid); free(rgt_content); rgt_content = malloc(sizeof(file)); rgt_content->file_name = malloc(file_current->file_name_width + 1); strcpy(rgt_content->file_name, file_current->file_name); rgt_content->file_name_width = file_current->file_name_width; rgt_content->file_size = file_current->file_size; rgt_content->file_type = file_current->file_type; rgt_content->status = file_current->status; pthread_mutex_unlock(&mutex_mid); if (rgt_content->file_type == FILE_TYPE_DIR || rgt_content->file_type == FILE_TYPE_SYMLINK) { char *path = malloc(rgt_content[0].file_name_width + 1); strcpy(path, rgt_content[0].file_name); free(rgt_content); rgt_file_count = get_dir_size(path); rgt_content = malloc(rgt_file_count * sizeof(file)); memset(rgt_content, ' ', rgt_file_count * sizeof(file)); get_dir_content(path, &rgt_file_count, rgt_content); rgt_content[0].status &= ~FILE_STATUS_FILE_OPEN; free(path); free(rgt_buffer); rgt_buffer = malloc(sizeof(char)); memset(rgt_buffer, ' ', sizeof(char)); } else { rgt_file_count = 0; free(rgt_buffer); if (rgt_content->status & FILE_STATUS_DIR_EMPTY) { rgt_buffer = "empty dir"; } else { rgt_content->file_type = FILE_TYPE_OPEN_FILE; rgt_content->status = FILE_STATUS_HOVER; rgt_buffer = preview_file(rgt_content); } } pthread_mutex_unlock(&mutex_rgt); pthread_exit(0); } void *thread_top(void *data){ pthread_mutex_lock(&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 = getcwd(NULL, 0); top_width = strlen(top_buffer); } free(path); pthread_mutex_unlock(&mutex_top); pthread_exit(0); } void *thread_btm(void *data){ pthread_mutex_lock(&mutex_btm); pthread_mutex_lock(&mutex_wait); wait_count++; pthread_cond_wait(&cond_wait, &mutex_wait); wait_count--; pthread_mutex_unlock(&mutex_wait); free(btm_buffer); int buffer_width = terminal_width; btm_buffer = malloc(buffer_width); memset(btm_buffer, 0, buffer_width); btm_buffer[0] = (S_ISDIR(file_current->permissions)) ? 'd' : '-'; btm_buffer[1] = (file_current->permissions & S_IRUSR) ? 'r' : '-'; btm_buffer[2] = (file_current->permissions & S_IWUSR) ? 'w' : '-'; btm_buffer[3] = (file_current->permissions & S_IXUSR) ? 'x' : '-'; btm_buffer[4] = (file_current->permissions & S_IRGRP) ? 'r' : '-'; btm_buffer[5] = (file_current->permissions & S_IWGRP) ? 'w' : '-'; btm_buffer[6] = (file_current->permissions & S_IXGRP) ? 'x' : '-'; btm_buffer[7] = (file_current->permissions & S_IROTH) ? 'r' : '-'; btm_buffer[8] = (file_current->permissions & S_IWOTH) ? 'w' : '-'; btm_buffer[9] = (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, ' ', sizeof(char)); memset(rgt_buffer, ' ', sizeof(char)); memset(btm_buffer, ' ', sizeof(char)); rgt_content[0].file_type = 0; rgt_content[0].file_size = 1; rgt_content[0].file_name_width = 1; rgt_content[0].file_name = malloc(sizeof("a")); strcpy(rgt_content[0].file_name, "a"); file_current = malloc(sizeof(file)); file_current->file_type = 0; file_current->file_size = 1; file_current->file_name_width = 1; file_current->file_name = malloc(sizeof("a")); strcpy(file_current->file_name, "a"); pthread_mutex_init(&mutex_top, NULL); pthread_mutex_init(&mutex_mid, NULL); pthread_mutex_init(&mutex_lft, NULL); pthread_mutex_init(&mutex_selection, NULL); pthread_mutex_init(&mutex_wait, NULL); pthread_cond_init(&cond_wait, NULL); 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); }