Compare commits

...

20 Commits

Author SHA1 Message Date
nova
47357e039d stability improvenments 2025-07-26 16:46:38 +02:00
nova
ecce6031a4 scrolling limit 2025-07-26 14:12:28 +02:00
nova
e5a2e429f0 added directory scrolling via offset_vertical 2025-07-25 18:04:26 +02:00
nova
1a67c5b4d0 removal of file_size_width 2025-07-25 17:10:44 +02:00
nova
af5a451ec2 size improvements of file struct 2025-07-23 19:49:57 +02:00
nova
a99a519834 general stability improvements 2025-07-23 19:47:37 +02:00
nova
6daeaebb5a added file extension commands 2025-07-18 23:01:49 +02:00
nova
d9ae5c79af improvenments to the rendered output, trunking of longer file names, no more dir sizes and indexes in lft and rgt 2025-07-15 02:45:45 +02:00
nova
2105bb4fe5 improvenments to delete function; need to handle filled dir still 2025-07-14 01:04:36 +02:00
nova
b9c254a0fe now runs with -O2 2025-07-13 21:53:59 +02:00
nova
4092446825 actual decent makefile whoa 2025-07-13 21:50:20 +02:00
nova
bd31ffd17d fixed segfault when quitting 2025-07-13 19:47:01 +02:00
nova
c9c00f4930 added unicode support 2025-07-12 15:00:34 +02:00
nova
d96046ac44 -O2 related refactoring 2025-07-09 01:09:45 +02:00
nova
b6f9633677 handling of empty dirs & refactoring 2025-07-08 20:51:25 +02:00
nova
7fcd148dfe fixed symlink handling 2025-07-08 01:57:58 +02:00
nova
4c958dc10a now parsing file sizes 2025-07-08 01:49:02 +02:00
nova
bc6fb162c5 accounting for files "." and ".." 2025-07-08 00:43:19 +02:00
nova
b77c9a2a29 made configs constant 2025-07-08 00:20:14 +02:00
nova
3f8fdc9e17 improvenments to file previews 2025-07-07 19:28:34 +02:00
15 changed files with 531 additions and 306 deletions

View File

@@ -1,12 +1,24 @@
CC := gcc
CFLAGS := -Wall -Wextra -O2 -flto=auto
CURSES := -lncursesw -ltinfow #utf8 support
#CURSES := -lncurses -tinfo #no utf8
CFLAGS_DEBUG := $(CFLAGS) -g
GDB := gdb --tui ./th
VALGRIND := valgrind --leak-check=full --track-origins=yes --show-leak-kinds=all --log-fd=9 9>>valgrind.log ./th
HELGRIND := valgrind --tool=helgrind --log-fd=9 9>>helgrind.log ./th
all: all:
gcc ./main.c -std=c89 -o th -lncurses -ltinfo -Wall $(CC) ./main.c -o th -std=c89 $(CFLAGS) $(CURSES)
d: d:
gcc -g -std=c89 ./main.c -o th -lncurses -ltinfo -Wall && gdb --tui ./th $(CC) ./main.c -o th -std=c89 $(CFLAGS_DEBUG) $(CURSES)
$(GDB)
v: v:
gcc -g -std=c89 ./main.c -o th -lncurses -ltinfo && valgrind --leak-check=full --log-fd=9 9>>valgrind.log ./th $(CC) ./main.c -o th -std=c89 $(CFLAGS_DEBUG) $(CURSES)
$(VALGRIND)
rel:
gcc ./main.c -std=c89 -o th -lncurses -ltinfo -Wall -O2 -flto
h:
$(CC) ./main.c -o th -std=c89 $(CFLAGS_DEBUG) $(CURSES)
$(HELGRIND)

161
backend.c
View File

@@ -12,8 +12,9 @@
extern unsigned int settings; extern unsigned int settings;
extern unsigned int file_modifiers; extern unsigned int file_modifiers;
extern unsigned int color_count; extern unsigned int color_count;
extern unsigned int terminal_height;
extern volatile unsigned long selected_file_current;
extern color *colors; extern color *colors;
unsigned long file_offset;
int (*order_func)() = sort_natural; int (*order_func)() = sort_natural;
@@ -26,6 +27,7 @@ char* concat(const char *s1, const char *s2){
return result; return result;
} }
unsigned long get_dir_size(char *path){ unsigned long get_dir_size(char *path){
DIR *dir = opendir(path); DIR *dir = opendir(path);
unsigned long entry_count = 0; unsigned long entry_count = 0;
@@ -38,6 +40,10 @@ unsigned long get_dir_size(char *path){
} }
} }
closedir(dir); closedir(dir);
if (file_modifiers & FILE_MODIFIERS_HIDDEN_FILES) {
/* removes files "." and ".." */
entry_count -= 2;
}
return entry_count; return entry_count;
} }
@@ -45,20 +51,19 @@ unsigned long get_dir_size(char *path){
void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_content){ void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_content){
struct dirent **entry; struct dirent **entry;
if (file_modifiers & FILE_MODIFIERS_HIDDEN_FILES) { /* print hidden files */ if (file_modifiers & FILE_MODIFIERS_HIDDEN_FILES) { /* print hidden files */
scandir(path, &entry, NULL, alphasort); scandir(path, &entry, skip_dot, alphasort);
} else { } else {
scandir(path, &entry, skip_hidden_files, alphasort); scandir(path, &entry, skip_hidden_files, alphasort);
} }
unsigned long i = 0; unsigned long i = 0;
for (i = 0; i < *dir_file_count; i++ ) { for (i = 0; i < *dir_file_count; i++ ) {
if (entry[i]->d_name[0] == '.' && !(file_modifiers & FILE_MODIFIERS_HIDDEN_FILES)) { if (entry[i]->d_name[0] == '.' && !(file_modifiers & FILE_MODIFIERS_HIDDEN_FILES)) {
} else { } else {
dir_content[i].file_name_width = strlen(entry[i]->d_name); dir_content[i].file_name = malloc(strlen(entry[i]->d_name)+1);
dir_content[i].file_name = malloc(dir_content[i].file_name_width + 1);
strcpy(dir_content[i].file_name, entry[i]->d_name); strcpy(dir_content[i].file_name, entry[i]->d_name);
dir_content[i].file_name[strlen(entry[i]->d_name)] = '\0';
struct stat *file; struct stat *file;
file = malloc(sizeof(struct stat)); file = malloc(sizeof(struct stat));
@@ -81,6 +86,10 @@ void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_conten
dir_content[i].file_type = FILE_TYPE_DIR; dir_content[i].file_type = FILE_TYPE_DIR;
dir_content[i].color_pair = COLOR_DIR; dir_content[i].color_pair = COLOR_DIR;
dir_content[i].file_size = get_dir_size(full_path); 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) { } else if (file->st_mode & S_IXUSR) {
dir_content[i].file_type = FILE_TYPE_EXEC; dir_content[i].file_type = FILE_TYPE_EXEC;
dir_content[i].color_pair = COLOR_EXEC; dir_content[i].color_pair = COLOR_EXEC;
@@ -89,10 +98,6 @@ void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_conten
dir_content[i].color_pair = COLOR_BLOCK; dir_content[i].color_pair = COLOR_BLOCK;
} else if (S_ISCHR(file->st_mode)) { } else if (S_ISCHR(file->st_mode)) {
dir_content[i].file_type = COLOR_CHARDEV; dir_content[i].file_type = COLOR_CHARDEV;
} 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 (S_ISFIFO(file->st_mode)) { } else if (S_ISFIFO(file->st_mode)) {
dir_content[i].file_type = FILE_TYPE_FIFO; dir_content[i].file_type = FILE_TYPE_FIFO;
dir_content[i].color_pair = COLOR_FIFO; dir_content[i].color_pair = COLOR_FIFO;
@@ -140,63 +145,135 @@ void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_conten
} }
void print_dir(WINDOW *win, unsigned long *line_width, unsigned long *dir_file_count, file *dir_content){ void print_dir(WINDOW *win, char print_info, unsigned long *dir_file_count, file *dir_content){
/* i am not proud of this function */
unsigned long line_width = getmaxx(win);
char *hover_bg = malloc(*line_width+1); char *bg = malloc(line_width+1);
memset(hover_bg, ' ', *line_width); memset(bg, ' ', line_width);
hover_bg[*line_width] = '\0'; bg[line_width] = '\0';
unsigned long i = 0; unsigned long i = 0;
unsigned long j = 0; float file_size;
float printed_size = 0;
char size_char = ' ';
char is_selected = 0; char is_selected = 0;
static const char sizes[6] = { 'B', 'K', 'M', 'G', 'T', 'P' };
unsigned long offset_vertical = 0;
unsigned long offset_back = 0;
unsigned long offset_front = 2; unsigned long offset_front = 2;
if (print_info) {
if (*dir_file_count > 9) { if (*dir_file_count > 9) {
offset_front = (snprintf(NULL, 0, "%ld", *dir_file_count)) + 1; offset_front = (snprintf(NULL, 0, "%ld", *dir_file_count)) + 1;
} }
for (i = file_offset; i < *dir_file_count; i++) { if (selected_file_current > (terminal_height/3)*2) {
if (selected_file_current + (terminal_height/3) >= *dir_file_count) {
unsigned long offset_back = *line_width - (snprintf(NULL,0,"%ld",dir_content[i].file_size) + 1); offset_vertical = *dir_file_count - terminal_height+2;
} else {
offset_vertical = selected_file_current - (terminal_height/3)*2;
}
}
}
for (i = offset_vertical; i < *dir_file_count && i < (terminal_height + offset_vertical); i++) {
if (print_info) {
file_size = dir_content[i].file_size;
char size_index = 0;
while (file_size > 1) {
printed_size=file_size;
file_size /= 1024;
size_index++;
if (size_index >= 6) {
break;
}
}
size_char = sizes[size_index-1];
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 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) { if (dir_content[i].status & FILE_STATUS_SELECTED) {
is_selected = 1; is_selected = 1;
wattron(win, COLOR_PAIR(8));
} else { } else {
is_selected = 0; is_selected = 0;
}
if (dir_content[i].status & FILE_STATUS_SELECTED) {
wattron(win, COLOR_PAIR(8));
} else {
wattron(win, COLOR_PAIR(dir_content[i].color_pair)); wattron(win, COLOR_PAIR(dir_content[i].color_pair));
} }
if (dir_content[i].status & FILE_STATUS_HOVER) {
wattron(win, A_REVERSE);
}
/* shortens the printed file name if it is too long
* example input: aaaaaaaa.txt
* example output: aaa~.txt
* if no extension is found, the name will truncate */
char *file_name;
unsigned long file_name_width = strlen(dir_content[i].file_name);
if ((file_name_width + offset_front + is_selected) > offset_back - 1) {
char *extension = strrchr(dir_content[i].file_name, '.');
if (extension) {
int char_offset = (file_name_width + offset_front + is_selected) - (offset_back - 1) ;
if ((file_name_width - char_offset - strlen(extension) - 1) > 1) {
file_name = malloc(file_name_width - char_offset + 1);
memcpy(file_name, dir_content[i].file_name, file_name_width - char_offset);
memcpy(file_name + (file_name_width - char_offset - strlen(extension)), extension, strlen(extension));
file_name[file_name_width - char_offset - strlen(extension) - 1] = '~';
file_name[file_name_width - char_offset] = '\0';
} else {
file_name = malloc(strlen(extension)+1);
file_name[0] = '~';
memcpy(file_name+1, extension, strlen(extension));
file_name[strlen(extension)] = '\0';
}
} else {
file_name = malloc(file_name_width+1);
memcpy(file_name, dir_content[i].file_name, file_name_width);
file_name[file_name_width] = '\0';
}
} else {
file_name = malloc(file_name_width+1);
memcpy(file_name, dir_content[i].file_name, file_name_width);
file_name[file_name_width] = '\0';
}
mvwaddstr(win, i-offset_vertical, 0, bg);
mvwaddnstr(win, i-offset_vertical, offset_front+is_selected, file_name, line_width-offset_front-is_selected-2);
if(print_info) {
mvwprintw(win, i-offset_vertical, 0, "%ld", i);
free(file_name);
if (dir_content[i].file_type == FILE_TYPE_DIR || dir_content[i].file_type == FILE_TYPE_SYMLINK) {
mvwprintw(win, i-offset_vertical, offset_back, "%ld", dir_content[i].file_size);
}else if (size_char =='B') {
mvwprintw(win, i-offset_vertical, offset_back, "%0.0lf %c", printed_size, size_char);
} else {
mvwprintw(win, i-offset_vertical, offset_back, "%0.2lf %c", printed_size, size_char);
}
} else {
mvwaddnstr(win, i-offset_vertical, 0, file_name, line_width);
free(file_name);
}
if (dir_content[i].status & FILE_STATUS_HOVER) { 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]);
}
mvwprintw(win, i, offset_back, "%ld", dir_content[i].file_size);
wattroff(win, A_REVERSE); 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]);
}
mvwprintw(win, i, offset_back, "%ld", dir_content[i].file_size);
} }
if (dir_content[i].status & FILE_STATUS_SELECTED) { if (dir_content[i].status & FILE_STATUS_SELECTED) {
wattroff(win, COLOR_PAIR(8)); wattroff(win, COLOR_PAIR(8));
} else { } else {
wattroff(win, COLOR_PAIR(dir_content[i].color_pair)); wattroff(win, COLOR_PAIR(dir_content[i].color_pair));
} }
} }
free(hover_bg); free(bg);
} }

View File

@@ -4,4 +4,4 @@
unsigned long get_dir_size(char *path); unsigned long get_dir_size(char *path);
void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_content); void get_dir_content(char *path, unsigned long *dir_file_count, file *dir_content);
void print_dir(WINDOW *win, unsigned long *line_width, unsigned long *dir_file_count, file *dir_content); void print_dir(WINDOW *win, char print_info, unsigned long *dir_file_count, file *dir_content);

View File

@@ -50,15 +50,14 @@ void colors_init() {
FILE *dircolors = fopen("/etc/DIR_COLORS", "r"); FILE *dircolors = fopen("/etc/DIR_COLORS", "r");
if (dircolors) { if (dircolors) {
char *line; char *line = NULL;
char *token; char *token;
char *extension; char *extension;
int tmp = 0;
size_t size = 0; size_t size = 0;
short fg; short fg;
short bg; short bg;
while ((tmp = getline(&line, &size, dircolors)) != -1) { while (getline(&line, &size, dircolors) != -1) {
fg = 7; fg = 7;
bg = 0; bg = 0;
token = strtok(line, " "); token = strtok(line, " ");
@@ -68,15 +67,15 @@ void colors_init() {
} else if (!strcmp(token, "DIR")) { } else if (!strcmp(token, "DIR")) {
parse_colors(line, &fg, &bg); parse_colors(line, &fg, &bg);
init_pair(1, fg, bg); /* directory */ init_pair(1, fg, bg); /* directory */
} else if (!strcmp(token, "EXEC")){
parse_colors(line, &fg, &bg);
init_pair(2, fg, bg); /* exec */
} else if (!strcmp(token, "RESET")){
parse_colors(line, &fg, &bg);
init_pair(3, fg, bg); /* regular file */
} else if (!strcmp(token, "LINK")){ } else if (!strcmp(token, "LINK")){
parse_colors(line, &fg, &bg); parse_colors(line, &fg, &bg);
init_pair(4, fg, bg); /* symlink */ init_pair(2, fg, bg); /* symlink */
} else if (!strcmp(token, "EXEC")){
parse_colors(line, &fg, &bg);
init_pair(3, fg, bg); /* exec */
} else if (!strcmp(token, "RESET")){
parse_colors(line, &fg, &bg);
init_pair(4, fg, bg); /* regular file */
} else if (!strcmp(token, "BLK")){ } else if (!strcmp(token, "BLK")){
parse_colors(line, &fg, &bg); parse_colors(line, &fg, &bg);
init_pair(5, fg, bg); /* block device */ init_pair(5, fg, bg); /* block device */
@@ -98,10 +97,12 @@ void colors_init() {
rewind(dircolors); rewind(dircolors);
/*is it a leak when its intentional?*/
colors = malloc(sizeof(color) * color_count); colors = malloc(sizeof(color) * color_count);
unsigned int i = 0; unsigned int i = 0;
/* proper pass, reads all defined extensions within /etc/DIR_COLORS */ /* proper pass, reads all defined extensions within /etc/DIR_COLORS */
while ((tmp = getline(&line, &size, dircolors)) != -1) { while (getline(&line, &size, dircolors) != -1) {
fg = 7; fg = 7;
bg = 0; bg = 0;
if (line[0] == '.') { if (line[0] == '.') {

View File

@@ -2,7 +2,8 @@
#include "interactions.h" #include "interactions.h"
#include "sorting.h" #include "sorting.h"
static mimetype mimetype_default_cmd[] = {
static const mimetype mimetype_default_cmd[] = {
/* mimetype shell command /* mimetype shell command
* ^ substring of "file --mime-type -b ./hovered" * ^ substring of "file --mime-type -b ./hovered"
* this does mean that this list is checked for completely linear. * this does mean that this list is checked for completely linear.
@@ -16,8 +17,13 @@ static mimetype mimetype_default_cmd[] = {
{ "video", "mpv" }, { "video", "mpv" },
{ "audio", "mpv" } { "audio", "mpv" }
}; };
static const extension file_extension_default_cmd[] = {
static binding key_binding[] = { /* extension shell command
* similar to mimetype_default_cmd, however it searches for exact string matches
* and is checked before mimetype_default_cmd */
{ ".exe", "wine"},
};
static const binding key_binding[] = {
/*key action blackmagic comment*/ /*key action blackmagic comment*/
/*you cannot add bindings that include other bindings in its entirety /*you cannot add bindings that include other bindings in its entirety
* possible: mk, mf * possible: mk, mf
@@ -29,10 +35,10 @@ static binding key_binding[] = {
{ "e", update, NULL, "rerun all backend" }, /* executes the entire backend and redrawing of the screen */ { "e", update, NULL, "rerun all backend" }, /* executes the entire backend and redrawing of the screen */
{ "/", not_implemented, NULL, "search" }, { "/", not_implemented, NULL, "search" },
{ "h", move_right, NULL, "move right" }, /* moves one dir up */ { "h", move_left, NULL, "move left" }, /* moves one dir up */
{ "t", move_down, NULL, "move down" }, { "t", move_down, NULL, "move down" },
{ "n", move_up, NULL, "move up" }, { "n", move_up, NULL, "move up" },
{ "s", move_left, NULL, "move left" }, /* if a dir is hovered, cd into it, if a file is selected, see mimetype_default_cmd */ { "s", move_right, NULL, "move right" }, /* if a dir is hovered, cd into it, if a file is selected, see mimetype_default_cmd */
{ "\n", open_with, NULL, "open \"open with\" dialog" }, /* opens the hovered file with an arbitrary command */ { "\n", open_with, NULL, "open \"open with\" dialog" }, /* opens the hovered file with an arbitrary command */
{ "r", rename_hovered, NULL, "rename hovered file" }, /* renames currently hovered file/directory */ { "r", rename_hovered, NULL, "rename hovered file" }, /* renames currently hovered file/directory */
@@ -40,7 +46,7 @@ static binding key_binding[] = {
* this means that it does not delete the hovered files if files are already selected */ * this means that it does not delete the hovered files if files are already selected */
{ "G", jump_bottom, NULL, "jump to last file in dir" }, { "G", jump_bottom, NULL, "jump to last file in dir" },
{ "gg", jump_top, NULL, "jump to file 0" }, { "gg", jump_top, NULL, "jump to first file in dir" },
{ "gh", jump_to_dir, "$HOME", "jump to $HOME" }, { "gh", jump_to_dir, "$HOME", "jump to $HOME" },
{ "gs", jump_to_dir, "$START_PATH", "jump to $START_PATH" }, { "gs", jump_to_dir, "$START_PATH", "jump to $START_PATH" },
{ "gd", jump_to_dir, "/dev", "jump to /dev" }, { "gd", jump_to_dir, "/dev", "jump to /dev" },
@@ -70,5 +76,6 @@ static binding key_binding[] = {
{ "a", toggle_hidden_files, NULL, "toggle hidden files" }, { "a", toggle_hidden_files, NULL, "toggle hidden files" },
}; };
static unsigned long binding_count = sizeof(key_binding) / sizeof(binding); static const unsigned long binding_count = sizeof(key_binding) / sizeof(binding);
static unsigned long mimetype_default_count = sizeof(mimetype_default_cmd) / sizeof(mimetype); static const unsigned long mimetype_default_count = sizeof(mimetype_default_cmd) / sizeof(mimetype);
static const unsigned long file_extension_default_count = sizeof(file_extension_default_cmd) / sizeof(extension);

View File

@@ -24,13 +24,14 @@
#define FILE_STATUS_HOVER 1 #define FILE_STATUS_HOVER 1
#define FILE_STATUS_SELECTED 2 #define FILE_STATUS_SELECTED 2
#define FILE_STATUS_IS_REGULAR_FILE 4 #define FILE_STATUS_IS_REGULAR_FILE 4
#define FILE_STATUS_DIR_EMPTY 64 /* if a directory is empty */
#define FILE_STATUS_FILE_OPEN 128 /* only used for file previews */ #define FILE_STATUS_FILE_OPEN 128 /* only used for file previews */
#define COLOR_UNKNOWN 0 #define COLOR_UNKNOWN 0
#define COLOR_DIR 1 #define COLOR_DIR 1
#define COLOR_EXEC 2 /* not really a filetype, moreso if it is executable */ #define COLOR_SYMLINK 2
#define COLOR_REGULAR 3 #define COLOR_EXEC 3 /* not really a filetype, moreso if it is executable */
#define COLOR_SYMLINK 4 #define COLOR_REGULAR 4
#define COLOR_BLOCK 5 #define COLOR_BLOCK 5
#define COLOR_CHARDEV 6 #define COLOR_CHARDEV 6
#define COLOR_SOCK 7 #define COLOR_SOCK 7
@@ -55,12 +56,11 @@
/* complex types are good actually */ /* complex types are good actually */
typedef struct File { typedef struct File {
char status; char status;
char *file_name;
unsigned char file_type; unsigned char file_type;
unsigned short color_pair; unsigned short color_pair;
unsigned int permissions; unsigned short permissions;
unsigned long file_name_width;
unsigned long file_size; /*if its a file, its in bytes, if its a dir, its the count of files within that dir */ unsigned long file_size; /*if its a file, its in bytes, if its a dir, its the count of files within that dir */
char *file_name;
} file; } file;
typedef struct Color { typedef struct Color {
char *file_extension; char *file_extension;
@@ -70,6 +70,10 @@ typedef struct Mimetype {
char *mimetype; char *mimetype;
char *command; char *command;
} mimetype; } mimetype;
typedef struct Extension {
char *file_extension;
char *command;
} extension;
typedef struct Binding { typedef struct Binding {
char* key; char* key;
void (*func)(); void (*func)();

View File

@@ -3,7 +3,9 @@
#include <string.h> #include <string.h>
#include "defines.h" #include "defines.h"
char* text(char *path, unsigned long *file_size); char* text(char *path, unsigned long *file_size);
char* generic(char *path);
char* get_mimetype(char *path){ char* get_mimetype(char *path){
static char *cmd_str = "file --mime-type -b ./\""; static char *cmd_str = "file --mime-type -b ./\"";
@@ -20,42 +22,54 @@ char* get_mimetype(char *path){
FILE *cmd_open = popen(cmd, "r"); FILE *cmd_open = popen(cmd, "r");
char *line; char *line;
size_t size = 0; size_t size = 0;
getline(&line, &size, cmd_open); if (getline(&line, &size, cmd_open) != -1){
pclose(cmd_open); pclose(cmd_open);
return line; return line;
} else {
pclose(cmd_open);
return "unknown";
}
} }
char* preview_file(char *path, unsigned long file_size){ char* preview_file(file *file_current){
/* this calls "file" on path */ /* this calls "file" on path */
char *file_buffer; char *file_buffer;
char *mime = get_mimetype(path); char *mime = get_mimetype(file_current->file_name);
unsigned int mime_len = strlen(mime);
if (strstr(mime, "text")) { if (strstr(mime, "text")) {
file_buffer = text(path, &file_size); file_buffer = text(file_current->file_name, &file_current->file_size);
} else { } else {
file_buffer = generic(file_current->file_name);
file_buffer = malloc(mime_len + 1);
memset(file_buffer, ' ', mime_len);
memcpy(file_buffer, mime, mime_len);
file_buffer[mime_len] = '\0';
} }
free(mime); free(mime);
return file_buffer; return file_buffer;
} }
char* text(char *path, unsigned long *file_size){ char* text(char *path, unsigned long *file_size){
char *file_buffer = malloc(*file_size + 1); char *file_buffer = malloc(*file_size + 1);
FILE *fp = fopen(path, "r"); FILE *fp = fopen(path, "r");
fread(file_buffer, *file_size, 1, fp); if (fread(file_buffer, *file_size, 1, fp) != 0) {
file_buffer[*file_size] = '\0'; file_buffer[*file_size] = '\0';
return file_buffer; return file_buffer;
} else {
return "failed reading file";
}
}
char* generic(char *path){
char *cmd = concat("file ./\"", path);
cmd = concat(cmd, "\"");
FILE *cmd_open = popen(cmd, "r");
char *line;
size_t size = 0;
if (getline(&line, &size, cmd_open) != -1) {
pclose(cmd_open);
return line;
} else {
pclose(cmd_open);
return "failed executing shell command \"file\"";
}
} }

View File

@@ -1,4 +1,5 @@
#include "file_previews.c" #include "file_previews.c"
#include "defines.h"
char* preview_file(char *path, unsigned long file_size); char* preview_file(file *file_current);
char* get_mimetype(char *path); char* get_mimetype(char *path);

View File

@@ -1,8 +1,10 @@
#include <curses.h> #include <curses.h>
#include <pthread.h> #include <pthread.h>
#include <dirent.h> #include <dirent.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <strings.h> #include <strings.h>
#include <signal.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@@ -10,8 +12,8 @@
#include "config.h" #include "config.h"
extern unsigned long selected_file_current; extern volatile unsigned long selected_file_current;
extern unsigned long selected_file_last; extern volatile unsigned long selected_file_last;
extern unsigned int file_modifiers; extern unsigned int file_modifiers;
extern pthread_mutex_t mutex_selection; extern pthread_mutex_t mutex_selection;
@@ -20,7 +22,7 @@ extern pthread_mutex_t mutex_mid;
extern file *mid_content; extern file *mid_content;
extern file *lft_content; extern file *lft_content;
extern file *rgt_content; extern file *rgt_content;
extern file *file_current; extern volatile file *file_current;
extern unsigned int terminal_height; extern unsigned int terminal_height;
extern unsigned int terminal_width; extern unsigned int terminal_width;
@@ -37,7 +39,6 @@ unsigned int timeout_time = 0;
extern char *input; extern char *input;
unsigned int input_pass; unsigned int input_pass;
int parsed_input_number; int parsed_input_number;
extern char *terminal_width_empty_line;
extern char *start_path; extern char *start_path;
int read_string(WINDOW *win, int y, int x, char *str); int read_string(WINDOW *win, int y, int x, char *str);
@@ -47,6 +48,14 @@ extern int (*order_func)();
void FAIL(char *function, char *str){
noraw();
endwin();
curs_set(1);
echo();
printf("ERROR in function %s: %s", function, str);
kill(getpid(),9);
}
void user_interactions() { void user_interactions() {
@@ -55,11 +64,7 @@ void user_interactions() {
unsigned long binding_matches = 0; unsigned long binding_matches = 0;
static char binding_pass = 0; static char binding_pass = 0;
free(terminal_width_empty_line);
terminal_width_empty_line = malloc(terminal_width);
memset(terminal_width_empty_line, ' ', terminal_width);
move(terminal_height, terminal_width);
ch = getch(); ch = getch();
if(ch != ERR) { if(ch != ERR) {
timeout(1); /* blocking timeout of getch() */ timeout(1); /* blocking timeout of getch() */
@@ -109,12 +114,10 @@ void user_interactions() {
} else if (strncmp(input+number_length, key_binding[i].key, cmp_len) == 0) { } else if (strncmp(input+number_length, key_binding[i].key, cmp_len) == 0) {
binding_matches++; binding_matches++;
attron(A_UNDERLINE); attron(A_UNDERLINE);
mvaddstr(terminal_height-binding_matches-2, 0, terminal_width_empty_line);
mvaddstr(terminal_height-binding_matches-2, 0, "input"); mvaddstr(terminal_height-binding_matches-2, 0, "input");
mvaddstr(terminal_height-binding_matches-2, sizeof("input"), "\t\t\t"); mvaddstr(terminal_height-binding_matches-2, sizeof("input"), "\t\t\t");
mvaddstr(terminal_height-binding_matches-2, sizeof("input") + sizeof("\t\t\t"), "command"); mvaddstr(terminal_height-binding_matches-2, sizeof("input") + sizeof("\t\t\t"), "command");
attroff(A_UNDERLINE); attroff(A_UNDERLINE);
mvaddstr(terminal_height-binding_matches-1, 0, terminal_width_empty_line);
mvaddstr(terminal_height-binding_matches-1, 0, key_binding[i].key); mvaddstr(terminal_height-binding_matches-1, 0, key_binding[i].key);
mvaddstr(terminal_height-binding_matches-1, 0, key_binding[i].key); mvaddstr(terminal_height-binding_matches-1, 0, key_binding[i].key);
mvaddstr(terminal_height-binding_matches-1, sizeof(key_binding[i].key), "\t"); mvaddstr(terminal_height-binding_matches-1, sizeof(key_binding[i].key), "\t");
@@ -209,22 +212,45 @@ void move_up(int passes){
status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK);
pthread_mutex_unlock(&mutex_selection); pthread_mutex_unlock(&mutex_selection);
} }
void move_right(int passes){ void move_left(int passes){
if (passes == 0) { if (passes == 0) {
passes++; passes++;
} }
int i; int i;
for (i = 0; i < passes; i++) { for (i = 0; i < passes; i++) {
chdir(".."); if (chdir("..") != 0) {
/* TODO(2025-07-09T00:30:05) fix */
FAIL("move_left", "unhandled error of chdir");
}
} }
status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY);
} }
void move_left(){ void move_right(){
if (file_current->file_type == FILE_TYPE_DIR || file_current->file_type == FILE_TYPE_SYMLINK) { if (file_current->file_type == FILE_TYPE_DIR || file_current->file_type == FILE_TYPE_SYMLINK) {
chdir(file_current->file_name); if (chdir(file_current->file_name) != 0) {
FAIL("move_right", "unhandled error of chdir");
}
} else { } else {
unsigned long i = 0; unsigned long i = 0;
char match = 0;
char *mime = get_mimetype(file_current->file_name); char *mime = get_mimetype(file_current->file_name);
char *extension = strrchr(file_current->file_name, '.');
for (i = 0; i < file_extension_default_count; i++) {
if (strstr(extension, file_extension_default_cmd[i].file_extension)) {
char *cmd = concat(file_extension_default_cmd[i].command, " ./\"");
cmd = concat(cmd, file_current->file_name);
cmd = concat(cmd, "\"");
if (system(cmd) == -1) {
/*do nothing*/
}
match = 1;
status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL);
break;
}
}
if (match == 0) {
for (i = 0; i < mimetype_default_count; i++) { for (i = 0; i < mimetype_default_count; i++) {
if (strstr(mime, mimetype_default_cmd[i].mimetype)) { if (strstr(mime, mimetype_default_cmd[i].mimetype)) {
@@ -233,15 +259,18 @@ void move_left(){
cmd = concat(cmd, "\""); cmd = concat(cmd, "\"");
btm_buffer = malloc(strlen(cmd)); btm_buffer = malloc(strlen(cmd));
strcpy(btm_buffer, cmd); strcpy(btm_buffer, cmd-1);
system(cmd); if (system(cmd) == -1) {
/*do nothing*/
}
status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL);
break; break;
} }
} }
}
free(mime); free(mime);
} }
status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY);
@@ -267,7 +296,7 @@ void open_with(){
btm_buffer = concat("open \"", file_current->file_name); btm_buffer = concat("open \"", file_current->file_name);
btm_buffer = concat(btm_buffer, "\" with:"); btm_buffer = concat(btm_buffer, "\" with:");
status = STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
werase(win_b); werase(win_b);
mvwin(win_b, terminal_height-6, 0); mvwin(win_b, terminal_height-6, 0);
wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/
@@ -288,7 +317,9 @@ void open_with(){
cmd = concat(cmd, file_current->file_name); cmd = concat(cmd, file_current->file_name);
cmd = concat(cmd, "\""); cmd = concat(cmd, "\"");
system(cmd); if (system(cmd) == -1) {
FAIL("open_with", "creating subcommand failed unhandled");
}
free(btm_buffer); free(btm_buffer);
btm_buffer = cmd; btm_buffer = cmd;
@@ -305,7 +336,7 @@ void rename_hovered(){
btm_buffer = concat("rename \"", file_current->file_name); btm_buffer = concat("rename \"", file_current->file_name);
btm_buffer = concat(btm_buffer, "\" to:"); btm_buffer = concat(btm_buffer, "\" to:");
status = STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
werase(win_b); werase(win_b);
mvwin(win_b, terminal_height-6, 0); mvwin(win_b, terminal_height-6, 0);
wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/
@@ -327,7 +358,9 @@ void rename_hovered(){
cmd = concat(cmd, str); cmd = concat(cmd, str);
cmd = concat(cmd, "\""); cmd = concat(cmd, "\"");
system(cmd); if (system(cmd) == -1) {
FAIL("rename_hovered", "mv or creating subcommand failed");
};
btm_buffer = cmd; btm_buffer = cmd;
} }
@@ -362,7 +395,7 @@ void delete(){
btm_buffer = concat(btm_buffer, "\n\n"); btm_buffer = concat(btm_buffer, "\n\n");
btm_buffer = concat(btm_buffer, "(y/N)"); btm_buffer = concat(btm_buffer, "(y/N)");
status = STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
werase(win_b); werase(win_b);
mvwin(win_b, terminal_height-6, 0); mvwin(win_b, terminal_height-6, 0);
wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/
@@ -375,30 +408,36 @@ void delete(){
char ch = wgetch(win_b); char ch = wgetch(win_b);
if (ch == 'y' || ch == 'Y') { if (ch == 'y' || ch == 'Y') {
/* the second loop is used to add "./", wich is not being printed" */
char *cmd;
/* TODO(2025-06-30T02:27:06) IMPORTANT: this really fucks up when the file has a quotation mark in its name */ /* TODO(2025-06-30T02:27:06) IMPORTANT: this really fucks up when the file has a quotation mark in its name */
int error;
if (hits) { if (hits) {
int j = 2;
for (i = 0; i < mid_file_count; i++) { for (i = 0; i < mid_file_count; i++) {
if (mid_content[i].status & FILE_STATUS_SELECTED) { if (mid_content[i].status & FILE_STATUS_SELECTED) {
cmd = concat("rm -rf ./\"", mid_content[i].file_name); error = remove(mid_content[i].file_name);
cmd = concat(cmd, "\""); if (error != 0) {
system(cmd); mvaddstr(terminal_height-j, 0, "could not delete: " );
mvaddstr(terminal_height-j, strlen("could not delete: "), mid_content[i].file_name);
j++;
}
} }
} }
free(btm_buffer); free(btm_buffer);
btm_buffer = concat("deleted: ", file_str); btm_buffer = concat("deleted: ", file_str);
} else { } else {
free(btm_buffer); free(btm_buffer);
error = remove(file_current->file_name);
if (error != 0) {
mvaddstr(terminal_height-2, 0, "could not delete: " );
mvaddstr(terminal_height-2, strlen("could not delete: "), mid_content[i].file_name);
btm_buffer = " ";
} else {
btm_buffer = concat("deleted: \"", file_current->file_name); btm_buffer = concat("deleted: \"", file_current->file_name);
btm_buffer = concat(btm_buffer, "\""); btm_buffer = concat(btm_buffer, "\"");
cmd = concat("rm -rf ./\"", file_current->file_name); }
cmd = concat(cmd, "\"");
system(cmd);
} }
/*system(cmd);*/ /*system(cmd);*/
free(cmd);
} else { } else {
free(btm_buffer); free(btm_buffer);
@@ -415,7 +454,7 @@ void delete(){
void makedir(){ void makedir(){
btm_buffer = "create dir: "; btm_buffer = "create dir: ";
status = STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
werase(win_b); werase(win_b);
mvwin(win_b, terminal_height-6, 0); mvwin(win_b, terminal_height-6, 0);
wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/
@@ -437,7 +476,7 @@ void makedir(){
} }
void makefile(){ void makefile(){
btm_buffer = "create file: "; btm_buffer = "create file: ";
status = STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
werase(win_b); werase(win_b);
mvwin(win_b, terminal_height-6, 0); mvwin(win_b, terminal_height-6, 0);
wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/
@@ -470,11 +509,10 @@ void not_implemented(int passes, int index){
} }
void jump_to_dir(int passes, int index){ void jump_to_dir(int passes, int index){
if ((char*)key_binding[index].black_magic) { if ((char*)key_binding[index].black_magic) {
chdir(getenv((char*)key_binding[index].black_magic+1)); if (chdir(getenv((char*)key_binding[index].black_magic+1)) != 0) {
} else { FAIL("jump_to_dir", "jumping to black_magic in config.h failed");
chdir((char*)key_binding[index].black_magic); }
} }
status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY);
} }
void order_by(int passes, int index){ void order_by(int passes, int index){
@@ -507,7 +545,7 @@ void cmd_on_selected(int passes, int index){
btm_buffer = concat(btm_buffer, "\n\n"); btm_buffer = concat(btm_buffer, "\n\n");
btm_buffer = concat(btm_buffer, "(y/N)"); btm_buffer = concat(btm_buffer, "(y/N)");
status = STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
werase(win_b); werase(win_b);
mvwin(win_b, terminal_height-6, 0); mvwin(win_b, terminal_height-6, 0);
wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/
@@ -521,26 +559,31 @@ void cmd_on_selected(int passes, int index){
if (ch == 'y' || ch == 'Y') { if (ch == 'y' || ch == 'Y') {
/* the second loop is used to add "./", wich is not being printed" */ /* the second loop is used to add "./", wich is not being printed" */
char *cmd; char *cmd = malloc(sizeof(char));
/* TODO(2025-07-06T07:23:05) IMPORTANT: this really fucks up when the file has a quotation mark in its name */ /* TODO(2025-07-06T07:23:05) IMPORTANT: this really fucks up when the file has a quotation mark in its name */
if (hits) { if (hits) {
for (i = 0; i < mid_file_count; i++) { for (i = 0; i < mid_file_count; i++) {
if (mid_content[i].status & FILE_STATUS_SELECTED) { if (mid_content[i].status & FILE_STATUS_SELECTED) {
free(cmd);
cmd = concat((char*)key_binding[index].black_magic, " \""); cmd = concat((char*)key_binding[index].black_magic, " \"");
cmd = concat(cmd, mid_content[i].file_name); cmd = concat(cmd, mid_content[i].file_name);
cmd = concat(cmd, "\""); cmd = concat(cmd, "\"");
system(cmd); if (system(cmd) != 0) {
free(cmd); /*do nothing*/
}
} }
} }
free(btm_buffer); free(btm_buffer);
btm_buffer = concat("completed: ", key_binding[index].black_magic); btm_buffer = concat("completed: ", key_binding[index].black_magic);
} else { } else {
free(btm_buffer); free(btm_buffer);
free(cmd);
cmd = concat((char*)key_binding[index].black_magic, " \""); cmd = concat((char*)key_binding[index].black_magic, " \"");
cmd = concat(cmd, file_current->file_name); cmd = concat(cmd, file_current->file_name);
cmd = concat(cmd, "\""); cmd = concat(cmd, "\"");
system(cmd); if (system(cmd) != 0) {
/*do nothing*/
}
mvaddstr(10,10, cmd); mvaddstr(10,10, cmd);
} }

View File

@@ -9,10 +9,10 @@
void user_interactions(); void user_interactions();
void quit_program(); void quit_program();
void toggle_selection(); void toggle_selection();
void move_right(int pssses); void move_right();
void move_up(int passes); void move_up(int passes);
void move_down(int passes); void move_down(int passes);
void move_left(); void move_left(int passes);
void jump_bottom(); void jump_bottom();
void jump_top(); void jump_top();
void toggle_hidden_files(); void toggle_hidden_files();

59
main.c
View File

@@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#include <locale.h>
#include "threading.h" #include "threading.h"
#include "window.h" #include "window.h"
#include "defines.h" #include "defines.h"
@@ -16,7 +17,7 @@ unsigned int temp_heigth = 0; /*used for screen refresh*/
unsigned int temp_width = 0; unsigned int temp_width = 0;
unsigned int settings; unsigned int settings;
unsigned int file_modifiers; unsigned int file_modifiers;
unsigned int status; unsigned int status = (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY);
char *start_path; char *start_path;
WINDOW *win_t; WINDOW *win_t;
@@ -66,28 +67,31 @@ int main(){
temp_width = terminal_width; temp_width = terminal_width;
temp_heigth = terminal_height; temp_heigth = terminal_height;
} }
if (status & STATUS_RUN_BACKEND) { if (status & STATUS_RUN_BACKEND && threading) {
if (threading) {
pthread_cancel(thread_t);
pthread_cancel(thread_l);
pthread_cancel(thread_m);
pthread_cancel(thread_r);
pthread_cancel(thread_b); pthread_cancel(thread_b);
pthread_cancel(thread_r);
pthread_cancel(thread_m);
pthread_cancel(thread_l);
pthread_cancel(thread_t);
}
if (threading) {
status &= ~(STATUS_RELOAD_DIRECTORY);
pthread_join(thread_t, NULL);
pthread_join(thread_l, NULL);
pthread_join(thread_m, NULL);
pthread_join(thread_b, NULL); pthread_join(thread_b, NULL);
pthread_join(thread_r, NULL); pthread_join(thread_r, NULL);
pthread_join(thread_m, NULL);
pthread_join(thread_l, NULL);
pthread_join(thread_t, NULL);
threading = 0; threading = 0;
} }
pthread_create(&thread_t, NULL, thread_top, win_t); /*top bar*/ if (status & STATUS_RUN_BACKEND) {
pthread_create(&thread_l, NULL, thread_lft, win_l); /*current_content slash win_m*/ pthread_create(&thread_t, NULL, thread_top, &status); /*top bar*/
pthread_create(&thread_m, NULL, thread_mid, win_m); /*parent_content slash win_l*/ pthread_create(&thread_l, NULL, thread_lft, &status); /*parent_content slash win_l*/
pthread_create(&thread_r, NULL, thread_rgt, win_r); /*child_content slash win_r*/ pthread_create(&thread_m, NULL, thread_mid, &status); /*current_content slash win_m*/
pthread_create(&thread_b, NULL, thread_btm, win_b); /*bottom bar*/ pthread_create(&thread_b, NULL, thread_btm, &status); /*bottom bar*/
threading = 1; pthread_create(&thread_r, NULL, thread_rgt, &status); /*child_content slash win_r*/
status &= ~(STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY); status &= ~(STATUS_RUN_BACKEND);
status |= STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
threading = 1;
} }
user_interactions(); user_interactions();
@@ -98,11 +102,13 @@ int main(){
threading_free(); threading_free();
free(start_path); free(start_path);
if (threading) {
pthread_join(thread_l, NULL); pthread_join(thread_l, NULL);
pthread_join(thread_r, NULL); pthread_join(thread_r, NULL);
pthread_join(thread_m, NULL); pthread_join(thread_m, NULL);
pthread_join(thread_t, NULL); pthread_join(thread_t, NULL);
pthread_join(thread_b, NULL); pthread_join(thread_b, NULL);
}
delwin(win_l); delwin(win_l);
delwin(win_m); delwin(win_m);
@@ -127,11 +133,11 @@ void render_pass(){
/*TODO: check if deallocation of window and reallocation is faster than this or not */ /*TODO: check if deallocation of window and reallocation is faster than this or not */
werase(win_t); wclear(win_t);
werase(win_b); wclear(win_b);
werase(win_l); wclear(win_l);
werase(win_m); wclear(win_m);
werase(win_r); wclear(win_r);
wresize(win_t, 1, terminal_width); wresize(win_t, 1, terminal_width);
wresize(win_l, terminal_height-2, terminal_width/8); wresize(win_l, terminal_height-2, terminal_width/8);
@@ -167,10 +173,10 @@ void render_pass(){
/*this function exists for things done at startup (initialization, reading config, etc)*/ /*this function exists for things done at startup (initialization, reading config, etc)*/
void init() { void init() {
setlocale(LC_ALL, "");
initscr(); /* start ncurses */ initscr(); /* start ncurses */
noecho(); /* hide keyboard input */ noecho(); /* hide keyboard input */
timeout(0); /* blocking timeout of getch() */ timeout(0); /* blocking timeout of getch() */
keypad(stdscr, TRUE);
curs_set(0); curs_set(0);
/*file_modifiers = (FILE_MODIFIERS_HIDDEN_FILES | FILE_MODIFIERS_SORT_BITMASK);*/ /*file_modifiers = (FILE_MODIFIERS_HIDDEN_FILES | FILE_MODIFIERS_SORT_BITMASK);*/
@@ -178,13 +184,14 @@ void init() {
memset(input, 0, 255); memset(input, 0, 255);
status = (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); status = (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY);
if (getuid() == 0) { if (getuid() == 0) {
status += STATUS_USER_ROOT; status |= STATUS_USER_ROOT;
} }
threading_init(); /* found in threading.c */ threading_init(); /* found in threading.c */
colors_init(); colors_init();
ESCDELAY = 10; ESCDELAY = 10;
char *start_path = getcwd(NULL, 0);
setenv("START_PATH", getcwd(NULL, 0), 0); setenv("START_PATH", start_path, 0);
free(start_path);
} }

View File

@@ -2,6 +2,7 @@
#include <dirent.h> #include <dirent.h>
#include <strings.h> #include <strings.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "defines.h" #include "defines.h"
extern unsigned int settings; extern unsigned int settings;
@@ -13,6 +14,12 @@ int skip_hidden_files(const struct dirent *entry){
} }
return 1; return 1;
} }
int skip_dot(const struct dirent *entry){
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
return 0;
}
return 1;
}
int sort_natural(const void *file0, const void *file1){ int sort_natural(const void *file0, const void *file1){
unsigned char file_type0 = ((file*)file0)->file_type; unsigned char file_type0 = ((file*)file0)->file_type;
@@ -49,8 +56,6 @@ int sort_alpha(const void *file0, const void *file1){
int sort_random(const void *file0, const void *file1){ int sort_random(const void *file0, const void *file1){
unsigned char file_type0 = ((file*)file0)->file_type; unsigned char file_type0 = ((file*)file0)->file_type;
unsigned char file_type1 = ((file*)file1)->file_type; unsigned char file_type1 = ((file*)file1)->file_type;
char *file_name0 = ((file*)file0)->file_name;
char *file_name1 = ((file*)file1)->file_name;
static int seed = 0; static int seed = 0;
static int random = 0; static int random = 0;
@@ -60,9 +65,6 @@ int sort_random(const void *file0, const void *file1){
if (random == 0) { if (random == 0) {
random = seed; random = seed;
} }
if (strcmp(file_name0, ".") == 0 || strcmp(file_name0, "..") == 0) {
return -1;
}
char weight = 0; char weight = 0;
if (file_type0 == FILE_TYPE_DIR || file_type0 == FILE_TYPE_SYMLINK) { if (file_type0 == FILE_TYPE_DIR || file_type0 == FILE_TYPE_SYMLINK) {
weight |= 1; weight |= 1;
@@ -129,9 +131,6 @@ int sort_size(const void *file0, const void *file1){
unsigned long file_size1 = ((file*)file1)->file_size; unsigned long file_size1 = ((file*)file1)->file_size;
char *file_name0 = ((file*)file0)->file_name; char *file_name0 = ((file*)file0)->file_name;
char *file_name1 = ((file*)file1)->file_name; char *file_name1 = ((file*)file1)->file_name;
if (strcmp(file_name0, ".") == 0 || strcmp(file_name0, "..") == 0) {
return -1;
}
if (file_type0 == file_type1) { if (file_type0 == file_type1) {
if (file_size0 > file_size1) { if (file_size0 > file_size1) {
return -1; return -1;

View File

@@ -6,6 +6,8 @@
#include "sorting.c" #include "sorting.c"
#endif #endif
int skip_hidden_files(const struct dirent *entry);
int skip_dot(const struct dirent *entry);
void sort_dir(unsigned long *dir_length_width, char *dir_content); void sort_dir(unsigned long *dir_length_width, char *dir_content);
void sort_dir(unsigned long *dir_length_width, char *dir_content); void sort_dir(unsigned long *dir_length_width, char *dir_content);
int sort_natural(const void *file0, const void *file1); int sort_natural(const void *file0, const void *file1);

View File

@@ -18,17 +18,17 @@ pthread_mutex_t mutex_rgt;
pthread_mutex_t mutex_selection; pthread_mutex_t mutex_selection;
pthread_mutex_t mutex_wait; pthread_mutex_t mutex_wait;
pthread_cond_t cond_wait; pthread_cond_t cond_wait;
int wait_count; /* this is used to determine how many threads are waiting for cont_wait */ volatile char wait_count; /* this is used to determine how many threads are waiting for cont_wait */
file *rgt_content; file *rgt_content;
file *mid_content; file *mid_content;
file *lft_content; file *lft_content;
char *rgt_buffer; /* used for file previews, unlike rgt_content, which is used for directory previews */ char *rgt_buffer; /* used for file previews, unlike rgt_content, which is used for directory previews */
char *btm_buffer; char *btm_buffer;
char *top_buffer; /* current path */
file *file_current; volatile file *file_current;
char *top_content; /* current path */
unsigned long rgt_file_count; unsigned long rgt_file_count;
unsigned long mid_file_count; unsigned long mid_file_count;
@@ -37,51 +37,48 @@ unsigned long top_width;
unsigned long selected_file_current=0; volatile unsigned long selected_file_current = 0;
unsigned long selected_file_last=0; volatile unsigned long selected_file_last = 0;
unsigned int status_mid;
extern unsigned int status;
extern unsigned int terminal_width; extern unsigned int terminal_width;
void *thread_mid(void *data){ void *thread_mid(void *data){
unsigned int status = *(unsigned int*)data;
pthread_mutex_lock(&mutex_mid); pthread_mutex_lock(&mutex_mid);
char *path; char *path;
if((path=getcwd(NULL, 0)) == NULL) { if((path=getcwd(NULL, 0)) == NULL) {
mid_content = malloc(sizeof(file)); mid_content = malloc(sizeof(file));
mid_content[0].file_name_width = sizeof("cannot open directory"); mid_content->file_name = "cannot open directory";
mid_content[0].file_name = "cannot open directory";
mid_file_count = 1; mid_file_count = 1;
} else { } else {
if (status & STATUS_RELOAD_DIRECTORY) { if (status & STATUS_RELOAD_DIRECTORY) {
free(mid_content); free(mid_content);
mid_file_count = (unsigned long)get_dir_size(path); mid_file_count = get_dir_size(path);
if (mid_file_count > 0) {
mid_content = malloc(mid_file_count * sizeof(file)); mid_content = malloc(mid_file_count * sizeof(file));
memset(mid_content, ' ', mid_file_count * sizeof(file)); memset(mid_content, '\0', mid_file_count * sizeof(file));
get_dir_content(path, &mid_file_count, mid_content); get_dir_content(path, &mid_file_count, mid_content);
}
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 { } else {
mid_content[selected_file_current].status |= FILE_STATUS_HOVER; selected_file_current = 0;
if (selected_file_current != selected_file_last) { mid_content = malloc(sizeof(file));
mid_content[selected_file_last].status &= ~FILE_STATUS_HOVER; mid_content->status = FILE_STATUS_DIR_EMPTY;
} mid_content->file_type = 0;
selected_file_last = selected_file_current; mid_content->file_size = 0;
mid_content->permissions = 0;
mid_content->color_pair = 0;
mid_content->file_name = "empty dir";
file_current->file_name = mid_content[selected_file_current].file_name; file_current->file_name = mid_content->file_name;
file_current->file_name_width = mid_content[selected_file_current].file_name_width; file_current->file_size = mid_content->file_size;
file_current->file_size = mid_content[selected_file_current].file_size; file_current->file_type = mid_content->file_type;
file_current->file_type = mid_content[selected_file_current].file_type; file_current->color_pair = mid_content->color_pair;
file_current->permissions = mid_content[selected_file_current].permissions; file_current->permissions = mid_content->permissions;
file_current->status = mid_content->status;
mid_file_count = 0;
while(wait_count < 2){ while(wait_count < 2){
/*wait for thread_rgt and thread_btm to lock*/ /*wait for thread_rgt and thread_btm to lock*/
@@ -89,23 +86,54 @@ void *thread_mid(void *data){
pthread_mutex_lock(&mutex_wait); pthread_mutex_lock(&mutex_wait);
pthread_cond_broadcast(&cond_wait); pthread_cond_broadcast(&cond_wait);
pthread_mutex_unlock(&mutex_wait); pthread_mutex_unlock(&mutex_wait);
break;
free(path);
pthread_mutex_unlock(&mutex_mid);
pthread_exit(0);
} }
} }
pthread_mutex_lock(&mutex_selection);
if (selected_file_current >= mid_file_count) {
selected_file_current = mid_file_count-1;
selected_file_current = mid_file_count-1;
}
if (selected_file_current != selected_file_last) {
mid_content[selected_file_last].status &= ~FILE_STATUS_HOVER;
}
selected_file_last = selected_file_current;
free(file_current->file_name);
file_current->file_name = malloc(strlen(mid_content[selected_file_current].file_name));
strcpy(file_current->file_name, mid_content[selected_file_current].file_name);
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;
mid_content[selected_file_current].status |= FILE_STATUS_HOVER;
file_current->status = mid_content[selected_file_current].status;
pthread_mutex_unlock(&mutex_selection); pthread_mutex_unlock(&mutex_selection);
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); free(path);
pthread_mutex_unlock(&mutex_mid); pthread_mutex_unlock(&mutex_mid);
pthread_exit(NULL); pthread_exit(0);
} }
void *thread_lft(void *data){ void *thread_lft(void *data){
unsigned int status = *(unsigned int*)data;
pthread_mutex_lock(&mutex_lft); pthread_mutex_lock(&mutex_lft);
char *path; char *path;
if((path=getcwd(NULL, 0)) == NULL) { if((path=getcwd(NULL, 0)) == NULL) {
lft_content = malloc(sizeof(file)); lft_content = malloc(sizeof(file));
lft_content[0].file_name_width = sizeof("cannot open directory");
lft_content[0].file_name = "cannot open directory"; lft_content[0].file_name = "cannot open directory";
lft_file_count = 1; lft_file_count = 1;
} else { } else {
@@ -114,41 +142,42 @@ void *thread_lft(void *data){
path[0] = '/'; path[0] = '/';
if (status & STATUS_RELOAD_DIRECTORY) { if (status & STATUS_RELOAD_DIRECTORY) {
lft_file_count = get_dir_size(path);
free(lft_content); free(lft_content);
lft_file_count = (unsigned long)get_dir_size(path);
lft_content = malloc(lft_file_count * sizeof(file)); lft_content = malloc(lft_file_count * sizeof(file));
memset(lft_content, ' ', lft_file_count * sizeof(file)); memset(lft_content, '\0', lft_file_count * sizeof(file));
get_dir_content(path, &lft_file_count, lft_content); get_dir_content(path, &lft_file_count, lft_content);
} }
} }
free(path); free(path);
pthread_mutex_unlock(&mutex_lft); pthread_mutex_unlock(&mutex_lft);
pthread_exit(NULL); pthread_exit(0);
} }
void *thread_rgt(void *data){ void *thread_rgt(void *data){
unsigned int status = *(unsigned int*)data;
pthread_mutex_lock(&mutex_rgt);
pthread_mutex_lock(&mutex_wait); pthread_mutex_lock(&mutex_wait);
wait_count++; wait_count++;
pthread_cond_wait(&cond_wait, &mutex_wait); pthread_cond_wait(&cond_wait, &mutex_wait);
wait_count--; wait_count--;
pthread_mutex_unlock(&mutex_wait); pthread_mutex_unlock(&mutex_wait);
pthread_mutex_lock(&mutex_rgt);
pthread_mutex_lock(&mutex_selection);
free(rgt_content); free(rgt_content);
rgt_content = malloc(sizeof(file)); rgt_content = malloc(sizeof(file));
rgt_content[0].file_name = malloc(file_current->file_name_width + 1); rgt_content->file_name = malloc(strlen(file_current->file_name));
strcpy(rgt_content[0].file_name, file_current->file_name); strcpy(rgt_content->file_name, file_current->file_name);
rgt_content[0].file_name_width = file_current->file_name_width; rgt_content->file_size = file_current->file_size;
rgt_content[0].file_size = file_current->file_size; rgt_content->file_type = file_current->file_type;
rgt_content[0].file_type = file_current->file_type; rgt_content->status = file_current->status;
pthread_mutex_unlock(&mutex_selection);
pthread_mutex_unlock(&mutex_mid); if (rgt_content->file_type == FILE_TYPE_DIR || rgt_content->file_type == FILE_TYPE_SYMLINK) {
char *path = malloc(strlen(rgt_content[0].file_name) + 1);
if (rgt_content[0].file_type == FILE_TYPE_DIR || rgt_content[0].file_type == FILE_TYPE_SYMLINK) {
char *path = malloc(rgt_content[0].file_name_width + 1);
strcpy(path, rgt_content[0].file_name); strcpy(path, rgt_content[0].file_name);
free(rgt_content); free(rgt_content);
rgt_file_count = get_dir_size(path); rgt_file_count = get_dir_size(path);
@@ -157,45 +186,54 @@ void *thread_rgt(void *data){
get_dir_content(path, &rgt_file_count, rgt_content); get_dir_content(path, &rgt_file_count, rgt_content);
rgt_content[0].status &= ~FILE_STATUS_FILE_OPEN; rgt_content[0].status &= ~FILE_STATUS_FILE_OPEN;
free(path); free(path);
free(rgt_buffer);
rgt_buffer = malloc(sizeof(char));
rgt_buffer[0] = '\0';
} else { } else {
rgt_file_count = 1; rgt_file_count = 0;
rgt_content[0].file_type = FILE_TYPE_OPEN_FILE;
rgt_content[0].status = FILE_STATUS_HOVER;
free(rgt_buffer); free(rgt_buffer);
rgt_buffer = preview_file(rgt_content[0].file_name, rgt_content[0].file_size); 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_mutex_unlock(&mutex_rgt);
pthread_exit(NULL); pthread_exit(0);
} }
void *thread_top(void *data){ void *thread_top(void *data){
unsigned int status = *(unsigned int*)data;
pthread_mutex_lock(&mutex_top); pthread_mutex_lock(&mutex_top);
free(top_content); free(top_buffer);
char *path; char *path;
if((path=getcwd(NULL, 0)) == NULL) { if((path=getcwd(NULL, 0)) == NULL) {
top_content = malloc(sizeof("cannot open directory")); top_buffer = malloc(sizeof("cannot open directory"));
top_width = sizeof("cannot open directory"); top_width = sizeof("cannot open directory");
top_content = "cannot open directory"; top_buffer = "cannot open directory";
} else { } else {
top_content = getcwd(NULL, 0); top_buffer = getcwd(NULL, 0);
top_width = strlen(top_content); top_width = strlen(top_buffer);
} }
free(path); free(path);
pthread_mutex_unlock(&mutex_top); pthread_mutex_unlock(&mutex_top);
pthread_exit(NULL); pthread_exit(0);
} }
void *thread_btm(void *data){ void *thread_btm(void *data){
unsigned int status = *(unsigned int*)data;
pthread_mutex_lock(&mutex_btm);
pthread_mutex_lock(&mutex_wait); pthread_mutex_lock(&mutex_wait);
wait_count++; wait_count++;
pthread_cond_wait(&cond_wait, &mutex_wait); pthread_cond_wait(&cond_wait, &mutex_wait);
wait_count--; wait_count--;
pthread_mutex_unlock(&mutex_wait); pthread_mutex_unlock(&mutex_wait);
pthread_mutex_lock(&mutex_btm);
free(btm_buffer); free(btm_buffer);
int buffer_width = terminal_width; int buffer_width = terminal_width;
@@ -214,7 +252,7 @@ void *thread_btm(void *data){
pthread_mutex_unlock(&mutex_btm); pthread_mutex_unlock(&mutex_btm);
pthread_exit(NULL); pthread_exit(0);
} }
void threading_init(){ void threading_init(){
@@ -222,23 +260,39 @@ void threading_init(){
mid_content = malloc(sizeof(file)); mid_content = malloc(sizeof(file));
lft_content = malloc(sizeof(file)); lft_content = malloc(sizeof(file));
top_content = malloc(sizeof(char)); top_buffer = malloc(sizeof(char));
rgt_buffer = malloc(sizeof(char)); rgt_buffer = malloc(sizeof(char));
btm_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';
file_current = malloc(sizeof(file)); file_current = malloc(sizeof(file));
file_current->file_type = 0; file_current->file_type = 0;
file_current->file_size = 1; file_current->file_size = 0;
file_current->file_name_width = 1; file_current->file_name = malloc(sizeof(char));
file_current->file_name = malloc(sizeof("a")); file_current->file_name[0] = '\0';
strcpy(file_current->file_name, "a");
pthread_mutex_init(&mutex_top, NULL); volatile char vol; /* needed to make sure higher optimization steps dont move these around */
pthread_mutex_init(&mutex_mid, NULL); vol = pthread_mutex_init(&mutex_top, NULL);
pthread_mutex_init(&mutex_lft, NULL); vol = pthread_mutex_init(&mutex_mid, NULL);
pthread_mutex_init(&mutex_selection, NULL); vol = pthread_mutex_init(&mutex_lft, NULL);
pthread_mutex_init(&mutex_wait, NULL); vol = pthread_mutex_init(&mutex_btm, NULL);
pthread_cond_init(&cond_wait, NULL); vol = pthread_mutex_init(&mutex_rgt, NULL);
vol = pthread_mutex_init(&mutex_selection, NULL);
vol = pthread_mutex_init(&mutex_wait, NULL);
vol = pthread_cond_init(&cond_wait, NULL);
vol;
selected_file_current = 0; selected_file_current = 0;
selected_file_last = 0; selected_file_last = 0;
} }
@@ -246,7 +300,7 @@ void threading_free(){
free(rgt_content); free(rgt_content);
free(mid_content); free(mid_content);
free(lft_content); free(lft_content);
free(top_content); free(top_buffer);
pthread_mutex_destroy(&mutex_top); pthread_mutex_destroy(&mutex_top);
pthread_mutex_destroy(&mutex_mid); pthread_mutex_destroy(&mutex_mid);

View File

@@ -13,7 +13,7 @@ extern color *colors;
extern file *mid_content; extern file *mid_content;
extern file *lft_content; extern file *lft_content;
extern file *rgt_content; extern file *rgt_content;
extern char *top_content; extern char *top_buffer;
extern char *rgt_buffer; extern char *rgt_buffer;
extern char *btm_buffer; extern char *btm_buffer;
@@ -30,19 +30,18 @@ extern pthread_mutex_t mutex_mid;
extern pthread_mutex_t mutex_rgt; extern pthread_mutex_t mutex_rgt;
void window_top(WINDOW *win){ void window_top(WINDOW *win){
unsigned long i = 0;
werase(win); werase(win);
if (pthread_mutex_trylock(&mutex_top)) { if (pthread_mutex_trylock(&mutex_top) == 0) {
wprintw(win,"loading");
status |= STATUS_UPDATE_SCREEN_0;
pthread_mutex_unlock(&mutex_rgt);
} else {
wattron(win, COLOR_PAIR(COLOR_PATH)); wattron(win, COLOR_PAIR(COLOR_PATH));
mvwprintw(win, i, 0, "%s", top_content); if (*top_buffer != ' ') { /*printing ' ' (standard initialized value, see threading_init) makes valgrind throw a fuss*/
mvwaddstr(win, 0, 0, top_buffer);
}
wattroff(win, COLOR_PAIR(COLOR_PATH)); wattroff(win, COLOR_PAIR(COLOR_PATH));
pthread_mutex_unlock(&mutex_top); pthread_mutex_unlock(&mutex_top);
} else {
wprintw(win,"loading");
status |= STATUS_UPDATE_SCREEN_0;
} }
} }
void window_btm(WINDOW *win){ void window_btm(WINDOW *win){
@@ -50,17 +49,17 @@ void window_btm(WINDOW *win){
unsigned long local_width; unsigned long local_width;
unsigned long local_height; unsigned long local_height;
getmaxyx(win, local_height, local_width); getmaxyx(win, local_height, local_width);
if (pthread_mutex_trylock(&mutex_btm)) { if (pthread_mutex_trylock(&mutex_btm) == 0) {
mvwprintw(win, local_height/2, local_width/2, "LOADING"); if (*top_buffer != ' ') { /*printing ' ' (standard initialized value, see threading_init) makes valgrind throw a fuss*/
status |= STATUS_UPDATE_SCREEN_0;
pthread_mutex_unlock(&mutex_rgt);
} else {
mvwprintw(win, 0, 0, "%s", btm_buffer); mvwprintw(win, 0, 0, "%s", btm_buffer);
}
pthread_mutex_unlock(&mutex_btm); pthread_mutex_unlock(&mutex_btm);
/*the printing of the input char is done in user_interactions*/ /*the printing of the input char is done in user_interactions*/
/*the printing of all possible inputs are done in user_interactions */ /*the printing of all possible inputs are done in user_interactions */
} else {
mvwprintw(win, local_height/2, local_width/2, "LOADING");
status |= STATUS_UPDATE_SCREEN_0;
} }
} }
void window_lft(WINDOW *win){ void window_lft(WINDOW *win){
werase(win); werase(win);
@@ -69,14 +68,13 @@ void window_lft(WINDOW *win){
unsigned long local_width; unsigned long local_width;
unsigned long local_height; unsigned long local_height;
getmaxyx(win, local_height, local_width); getmaxyx(win, local_height, local_width);
if (pthread_mutex_trylock(&mutex_lft)) { if (pthread_mutex_trylock(&mutex_lft) == 0) {
mvwprintw(win, local_height/2, local_width/2, "LOADING"); print_dir(win, 0, &lft_file_count, lft_content);
status |= STATUS_UPDATE_SCREEN_0; pthread_mutex_unlock(&mutex_lft);
pthread_mutex_unlock(&mutex_rgt);
} else { } else {
print_dir(win, &local_width, &lft_file_count, lft_content); mvwprintw(win, local_height/2, local_width/2, "LOADING");
pthread_mutex_unlock(&mutex_lft); status |= STATUS_UPDATE_SCREEN_0;
} }
} }
void window_mid(WINDOW *win){ void window_mid(WINDOW *win){
@@ -86,14 +84,16 @@ void window_mid(WINDOW *win){
unsigned long local_width; unsigned long local_width;
unsigned long local_height; unsigned long local_height;
getmaxyx(win, local_height, local_width); getmaxyx(win, local_height, local_width);
if (pthread_mutex_trylock(&mutex_mid)) { if (pthread_mutex_trylock(&mutex_mid) == 0) {
if (mid_file_count == 0) {
mvwprintw(win, 0, 0, "empty");
} else {
print_dir(win, 1, &mid_file_count, mid_content);
}
pthread_mutex_unlock(&mutex_mid);
} else {
mvwprintw(win, local_height/2, local_width/2, "LOADING"); mvwprintw(win, local_height/2, local_width/2, "LOADING");
status |= STATUS_UPDATE_SCREEN_0; status |= STATUS_UPDATE_SCREEN_0;
pthread_mutex_unlock(&mutex_rgt);
} else {
print_dir(win, &local_width, &mid_file_count, mid_content);
pthread_mutex_unlock(&mutex_mid);
} }
} }
void window_rgt(WINDOW *win){ void window_rgt(WINDOW *win){
@@ -103,17 +103,21 @@ void window_rgt(WINDOW *win){
unsigned long local_width; unsigned long local_width;
unsigned long local_height; unsigned long local_height;
getmaxyx(win, local_height, local_width); getmaxyx(win, local_height, local_width);
if (pthread_mutex_trylock(&mutex_rgt)) { if (pthread_mutex_trylock(&mutex_rgt) == 0) {
/* TODO(2025-06-13T00:49:26) fix race condition and use trylock */ if (rgt_file_count == 0) {
mvwprintw(win, local_height/2, local_width/2, "LOADING");
status |= STATUS_UPDATE_SCREEN_0;
pthread_mutex_unlock(&mutex_rgt);
} else {
if (rgt_content[0].file_type == FILE_TYPE_OPEN_FILE) { if (rgt_content[0].file_type == FILE_TYPE_OPEN_FILE) {
mvwprintw(win, 0, 0, "%s", rgt_buffer); mvwprintw(win, 0, 0, "%s", rgt_buffer);
} else { } else {
print_dir(win, &local_width, &rgt_file_count, rgt_content); mvwprintw(win, 0, 0, "empty");
}
} else {
print_dir(win, 0, &rgt_file_count, rgt_content);
} }
pthread_mutex_unlock(&mutex_rgt); pthread_mutex_unlock(&mutex_rgt);
} else {
mvwprintw(win, local_height/2, local_width/2, "LOADING");
status |= STATUS_UPDATE_SCREEN_0;
} }
} }