#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include "defines.h" #include "sorting.h" extern unsigned int settings; extern unsigned int file_modifiers; extern unsigned int color_count; extern unsigned int terminal_height; extern color *colors; unsigned long file_offset; int (*order_func)() = sort_natural; char* concat(const char *s1, const char *s2){ const size_t len1 = strlen(s1); const size_t len2 = strlen(s2); char *result = malloc(len1 + len2 + 1); memcpy(result, s1, len1); memcpy(result + len1, s2, len2 + 1); return result; } unsigned long get_dir_size(char *path){ DIR *dir = opendir(path); unsigned long entry_count = 0; if (dir) { struct dirent *entry; while ((entry=readdir(dir))) { if (entry->d_name[0] != '.' || (file_modifiers & FILE_MODIFIERS_HIDDEN_FILES)) { entry_count++; } } } closedir(dir); if (file_modifiers & FILE_MODIFIERS_HIDDEN_FILES) { /* removes files "." and ".." */ entry_count -= 2; } return entry_count; } void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_content){ struct dirent **entry; if (file_modifiers & FILE_MODIFIERS_HIDDEN_FILES) { /* print hidden files */ scandir(path, &entry, skip_dot, alphasort); } else { scandir(path, &entry, skip_hidden_files, alphasort); } unsigned long i = 0; for (i = 0; i < *dir_file_count; i++ ) { if (entry[i]->d_name[0] == '.' && !(file_modifiers & FILE_MODIFIERS_HIDDEN_FILES)) { } else { dir_content[i].file_name_width = strlen(entry[i]->d_name); dir_content[i].file_name = malloc(dir_content[i].file_name_width + 1); strcpy(dir_content[i].file_name, entry[i]->d_name); struct stat *file; file = malloc(sizeof(struct stat)); memset(file, ' ', sizeof(struct stat)); /* using the full path allows using the same function for all windows */ unsigned long path_len = strlen(path); char *full_path = malloc(strlen(path) + strlen(entry[i]->d_name) + 1 + sizeof("/")); memcpy(full_path, path, strlen(path)); memcpy(full_path + path_len, "/", sizeof("/")); memcpy(full_path + path_len + sizeof("/") - 1, entry[i]->d_name, strlen(entry[i]->d_name) + 1); lstat(full_path, file); dir_content[i].file_size = file->st_size; dir_content[i].permissions = 1; dir_content[i].permissions = file->st_mode; if (S_ISDIR(file->st_mode)) { dir_content[i].file_type = FILE_TYPE_DIR; dir_content[i].color_pair = COLOR_DIR; dir_content[i].file_size = get_dir_size(full_path); } else if (S_ISLNK(file->st_mode)) { dir_content[i].file_type = FILE_TYPE_SYMLINK; dir_content[i].color_pair = COLOR_SYMLINK; dir_content[i].file_size = get_dir_size(full_path); } else if (file->st_mode & S_IXUSR) { dir_content[i].file_type = FILE_TYPE_EXEC; dir_content[i].color_pair = COLOR_EXEC; } else if (S_ISBLK(file->st_mode)) { dir_content[i].file_type = FILE_TYPE_BLOCK; dir_content[i].color_pair = COLOR_BLOCK; } else if (S_ISCHR(file->st_mode)) { dir_content[i].file_type = COLOR_CHARDEV; } else if (S_ISFIFO(file->st_mode)) { dir_content[i].file_type = FILE_TYPE_FIFO; dir_content[i].color_pair = COLOR_FIFO; } else if (S_ISSOCK(file->st_mode)) { dir_content[i].file_type = FILE_TYPE_SOCK; dir_content[i].color_pair = COLOR_SOCK; } else if (S_ISREG(file->st_mode)) { dir_content[i].file_type = FILE_TYPE_REGULAR; dir_content[i].color_pair = COLOR_REGULAR; unsigned long j = 0; char *extension = strrchr(entry[i]->d_name, '.'); if (extension) { for (j = 0; j < color_count; j++) { if (!strcmp(colors[j].file_extension, extension)) { dir_content[i].color_pair = colors[j].color_pair; } } } else { } } else { dir_content[i].file_type = COLOR_REGULAR; dir_content[i].color_pair = COLOR_REGULAR; unsigned long j = 0; char *extension = strrchr(entry[i]->d_name, '.'); if (extension) { for (j = 0; j < color_count; j++) { if (!strcmp(colors[j].file_extension, extension)) { dir_content[i].color_pair = colors[j].color_pair; } } } else { } } free(full_path); free(file); } } qsort(dir_content, *dir_file_count, sizeof(file), order_func); for (i = 0; i < *dir_file_count; i++) { free(entry[i]); } free(entry); } void print_dir(WINDOW *win, unsigned long *line_width, unsigned long *dir_file_count, file *dir_content){ /* i am not proud of this function */ char *hover_bg = malloc(*line_width+1); memset(hover_bg, ' ', *line_width); hover_bg[*line_width] = '\0'; unsigned long i = 0; unsigned long j = 0; float file_size = 0; float printed_size = 0; char size_char = ' '; char is_selected = 0; static const char sizes[6] = { 'B', 'K', 'M', 'G', 'T', 'P' }; unsigned long offset_front = 2; if (*dir_file_count > 9) { offset_front = (snprintf(NULL, 0, "%ld", *dir_file_count)) + 1; } for (i = file_offset; i < *dir_file_count && i < terminal_height; i++) { unsigned long offset_back; if (dir_content[i].file_type == FILE_TYPE_DIR || dir_content[i].file_type == FILE_TYPE_SYMLINK) { offset_back = *line_width - (snprintf(NULL,0,"%ld",dir_content[i].file_size) + 1); } else { file_size = dir_content[i].file_size; long passes = 0; while (file_size > 1 || passes > sizeof(sizes)) { printed_size = file_size; file_size /= 1024; passes++; } if (passes) { size_char = sizes[passes-1]; } else { size_char = sizes[0]; } if (size_char == 'B') { offset_back = *line_width - (snprintf(NULL,0,"%0.0lf %c", printed_size, size_char) + 1); } else { offset_back = *line_width - (snprintf(NULL,0,"%0.2lf %c", printed_size, size_char) + 1); } } if (dir_content[i].status & FILE_STATUS_SELECTED) { is_selected = 1; wattron(win, COLOR_PAIR(8)); } else { is_selected = 0; wattron(win, COLOR_PAIR(dir_content[i].color_pair)); } if (dir_content[i].status & FILE_STATUS_HOVER) { wattron(win, A_REVERSE); mvwprintw(win, i, 0, "%s", hover_bg); mvwprintw(win, i, 0, "%ld", i); for (j = 0; j < dir_content[i].file_name_width ;j++) { if (j >= offset_back-1) { mvwaddch(win, i, j, '~'); break; } mvwaddch(win, i, offset_front+j+is_selected, dir_content[i].file_name[j]); } if (dir_content[i].file_type == FILE_TYPE_DIR || dir_content[i].file_type == FILE_TYPE_SYMLINK) { mvwprintw(win, i, offset_back, "%ld", dir_content[i].file_size); } else { if (size_char == 'B') { mvwprintw(win, i, offset_back, "%0.0lf %c", printed_size, size_char); } else { mvwprintw(win, i, offset_back, "%0.2lf %c", printed_size, size_char); } } wattroff(win, A_REVERSE); } else { mvwprintw(win, i, 0, "%ld", i); for (j = 0; j < dir_content[i].file_name_width ;j++) { if (j >= offset_back-1) { mvwaddch(win, i, j, '~'); break; } mvwaddch(win, i, offset_front+j+is_selected, dir_content[i].file_name[j]); } if (dir_content[i].file_type == FILE_TYPE_DIR || dir_content[i].file_type == FILE_TYPE_SYMLINK) { mvwprintw(win, i, offset_back, "%ld", dir_content[i].file_size); } else { if (size_char == 'B') { mvwprintw(win, i, offset_back, "%0.0lf %c", printed_size, size_char); } else { mvwprintw(win, i, offset_back, "%0.2lf %c", printed_size, size_char); } } } if (dir_content[i].status & FILE_STATUS_SELECTED) { wattroff(win, COLOR_PAIR(8)); } else { wattroff(win, COLOR_PAIR(dir_content[i].color_pair)); } } free(hover_bg); }