#include #include #include #include #include #include #include #include #include #include "defines.h" #include "config.h" extern unsigned long selected_file_current; extern unsigned long selected_file_last; extern unsigned int file_modifiers; extern pthread_mutex_t mutex_selection; extern pthread_mutex_t mutex_rgt; extern pthread_mutex_t mutex_mid; extern file *mid_content; extern file *lft_content; extern file *rgt_content; extern file *file_current; extern unsigned int terminal_height; extern unsigned int terminal_width; extern WINDOW *win_b; extern char *rgt_buffer; extern char *btm_buffer; extern unsigned long mid_file_count; extern unsigned int status; unsigned int timeout_time = 0; extern char *input; unsigned int input_pass; int parsed_input_number; extern char *terminal_width_empty_line; extern char *start_path; int read_string(WINDOW *win, int y, int x, char *str); int strcmp_offset(char *in0, char *in1, char offset); extern void render_pass(); 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() { char ch; unsigned long i; unsigned long binding_matches = 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); ch = getch(); if(ch != ERR) { timeout(1); /* blocking timeout of getch() */ input[input_pass] = ch; mvaddstr(terminal_height-1, (terminal_width/3)*2, input); input_pass++; if (ch == 27) { /* esc key */ memset(input, 0, 255); input_pass = 0; timeout(100); /* blocking timeout of getch() */ status |= STATUS_UPDATE_SCREEN_0; } binding_pass = 0; status |= STATUS_UPDATE_SCREEN_0; } void (*func_ptr)(int, int); int number_length = 0; if (!binding_pass) { parsed_input_number = 0; while((*input >= '0') && (*input <= '9')) { parsed_input_number = (parsed_input_number * 10) + (*input - '0'); input++; number_length++; mvaddch(terminal_height-5, 5, number_length+48); } input -= number_length; binding_pass = 1; char cmp_len = strlen(input); if(strlen(input) < 1) { cmp_len++; } for (i = 0; i < binding_count; i++) { if (strcmp(input + number_length, key_binding[i].key) == 0) { func_ptr = key_binding[i].func; func_ptr(parsed_input_number, i); memset(input, 0, 255); input_pass = 0; binding_pass = 0; number_length = 0; timeout(100); /* blocking timeout of getch() */ } else if (strncmp(input+number_length, key_binding[i].key, cmp_len) == 0) { binding_matches++; 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, sizeof("input"), "\t\t\t"); mvaddstr(terminal_height-binding_matches-2, sizeof("input") + sizeof("\t\t\t"), "command"); 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, sizeof(key_binding[i].key), "\t"); mvaddstr(terminal_height-binding_matches-1, sizeof(key_binding[i].key) + sizeof("\t"), key_binding[i].comment); } } } } int read_string(WINDOW *win, int y, int x, char *str){ curs_set(1); timeout(-1); /* negative numbers block until enter is pressed */ unsigned int pass = 0; char ch; char err = 0; wmove(win, y, x); while(1) { /*ch = mvwgetch(win, y, x + pass);*/ ch = wgetch(win); if (ch == '\n') { err = 0; break; } else if (ch == 27) { /* esc key */ err = 1; break; } else if (ch == 127) { /* backspace */ if (pass > 0) { pass--; mvwdelch(win, y, pass); } } else { mvwaddch(win, y, x +pass, ch); str[pass] = ch; pass++; } } str[pass] = '\0'; timeout(10); curs_set(0); return err; } int strcmp_offset(char *in0, char *in1, char offset){ int i = 0; while (in0[i] != '\0' && in1[i] != '\0') { if (in0[i+offset] != in1[i]) { return 1; } i++; in1++; } return 0; } void quit_program(){ status = STATUS_QUIT_PROGRAM; } void toggle_selection(){ pthread_mutex_lock(&mutex_selection); pthread_mutex_lock(&mutex_mid); mid_content[selected_file_current].status ^= FILE_STATUS_SELECTED; file_current->status ^= FILE_STATUS_SELECTED; status |= (STATUS_UPDATE_SCREEN_MASK); pthread_mutex_unlock(&mutex_mid); pthread_mutex_unlock(&mutex_selection); } void move_down(int passes){ pthread_mutex_lock(&mutex_selection); if (passes == 0) { passes++; } /*capping the maximum file is done inside thread_mid */ selected_file_current += passes; status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK); pthread_mutex_unlock(&mutex_selection); } void move_up(int passes){ pthread_mutex_lock(&mutex_selection); if (passes == 0) { passes++; } int i; for (i = 0; i < passes; i++) { if (selected_file_current != 0) { selected_file_current--; } } status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK); pthread_mutex_unlock(&mutex_selection); } void move_left(int passes){ if (passes == 0) { passes++; } int i; for (i = 0; i < passes; i++) { 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); } void move_right(){ if (file_current->file_type == FILE_TYPE_DIR || file_current->file_type == FILE_TYPE_SYMLINK) { if (chdir(file_current->file_name) != 0) { FAIL("move_right", "unhandled error of chdir"); } } else { unsigned long i = 0; char *mime = get_mimetype(file_current->file_name); for (i = 0; i < mimetype_default_count; i++) { if (strstr(mime, mimetype_default_cmd[i].mimetype)) { char *cmd = concat(mimetype_default_cmd[i].command, " ./\""); cmd = concat(cmd, file_current->file_name); cmd = concat(cmd, "\""); btm_buffer = malloc(strlen(cmd)); strcpy(btm_buffer, cmd); if (system(cmd) == -1) { /*do nothing*/ } status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); break; } } free(mime); } status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); } void toggle_hidden_files(){ file_modifiers ^= FILE_MODIFIERS_HIDDEN_FILES; status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); } void jump_bottom(){ pthread_mutex_lock(&mutex_selection); selected_file_current = 0 - 1; status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK); pthread_mutex_unlock(&mutex_selection); } void jump_top(){ pthread_mutex_lock(&mutex_selection); selected_file_current = 0; status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK); pthread_mutex_unlock(&mutex_selection); } void open_with(){ btm_buffer = concat("open \"", file_current->file_name); btm_buffer = concat(btm_buffer, "\" with:"); status = STATUS_UPDATE_SCREEN_0; werase(win_b); mvwin(win_b, terminal_height-6, 0); wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ render_pass(); unsigned long local_height; local_height = getmaxy(win_b); /* TODO(2025-06-22T01:24:36) fix fixed buffer size */ char *str = malloc(255); memset(str, ' ', 255); int err = read_string(win_b, local_height - 1, 0 , str); if (!err) { char *cmd = concat(str, " ./\""); cmd = concat(cmd, file_current->file_name); cmd = concat(cmd, "\""); if (system(cmd) == -1) { FAIL("open_with", "creating subcommand failed unhandled"); } free(btm_buffer); btm_buffer = cmd; } status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); free(str); } void rename_hovered(){ btm_buffer = concat("rename \"", file_current->file_name); btm_buffer = concat(btm_buffer, "\" to:"); status = STATUS_UPDATE_SCREEN_0; werase(win_b); mvwin(win_b, terminal_height-6, 0); wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ render_pass(); unsigned long local_height; local_height = getmaxy(win_b); /* TODO(2025-06-22T01:24:30) fix fixed buffer size */ char *str = malloc(255); memset(str, ' ', 255); int err = read_string(win_b, local_height - 1, 0, str); if (!err) { char *cmd = concat("mv ./\"", file_current->file_name); cmd = concat(cmd, "\" ./\""); cmd = concat(cmd, str); cmd = concat(cmd, "\""); if (system(cmd) == -1) { FAIL("rename_hovered", "mv or creating subcommand failed"); }; btm_buffer = cmd; } status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); free(str); } void delete(){ unsigned int i = 0; unsigned int hits = 0; char *file_str = " "; for (i = 0; i < mid_file_count; i++) { if (mid_content[i].status & FILE_STATUS_SELECTED) { file_str = concat(file_str, "\""); file_str = concat(file_str, mid_content[i].file_name); file_str = concat(file_str, "\" "); hits++; } } if (hits) { btm_buffer = concat("delete:", file_str); } else { btm_buffer = concat("delete: \"", file_current->file_name); btm_buffer = concat(btm_buffer, "\""); } btm_buffer = concat(btm_buffer, "?"); btm_buffer = concat(btm_buffer, "\n\n"); btm_buffer = concat(btm_buffer, "(y/N)"); status = STATUS_UPDATE_SCREEN_0; werase(win_b); mvwin(win_b, terminal_height-6, 0); wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ render_pass(); timeout(-1); /* negative numbers block until enter is pressed */ /* TODO(2025-06-22T01:24:30) fix fixed buffer size */ char ch = wgetch(win_b); if (ch == 'y' || ch == 'Y') { char *cmd = malloc(sizeof(char)); /* TODO(2025-06-30T02:27:06) IMPORTANT: this really fucks up when the file has a quotation mark in its name */ if (hits) { /* the second loop is used to add "./", wich is not being printed" */ for (i = 0; i < mid_file_count; i++) { if (mid_content[i].status & FILE_STATUS_SELECTED) { free(cmd); cmd = concat("rm -rf ./\"", mid_content[i].file_name); cmd = concat(cmd, "\""); if (system(cmd) == -1) { FAIL("delete", "rm -rf or creating subcommand failed"); } } } free(btm_buffer); btm_buffer = concat("deleted: ", file_str); } else { free(btm_buffer); btm_buffer = concat("deleted: \"", file_current->file_name); btm_buffer = concat(btm_buffer, "\""); free(cmd); cmd = concat("rm -rf ./\"", file_current->file_name); cmd = concat(cmd, "\""); if (system(cmd) == -1) { FAIL("delete", "rm -rf or creating subcommand failed"); } } /*system(cmd);*/ free(cmd); } else { free(btm_buffer); btm_buffer = "cancled deletion"; } timeout(10); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); if (hits) { free(file_str); } } void makedir(){ btm_buffer = "create dir: "; status = STATUS_UPDATE_SCREEN_0; werase(win_b); mvwin(win_b, terminal_height-6, 0); wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ render_pass(); unsigned long local_height; local_height = getmaxy(win_b); /* TODO(2025-07-03T01:19:55) fix fixed buffer size */ char *str = malloc(255); memset(str, ' ', 255); int err = read_string(win_b, local_height - 1, 0, str); if (!err) { btm_buffer = concat(btm_buffer, str); mkdir(str, 755); /*magic number from default permissions as created by mkdir*/ } free(str); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); } void makefile(){ btm_buffer = "create file: "; status = STATUS_UPDATE_SCREEN_0; werase(win_b); mvwin(win_b, terminal_height-6, 0); wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ render_pass(); unsigned long local_height; local_height = getmaxy(win_b); /* TODO(2025-07-03T01:19:49) fix fixed buffer size */ char *str = malloc(255); memset(str, ' ', 255); int err = read_string(win_b, local_height - 1, 0, str); if (!err) { btm_buffer = concat(btm_buffer, str); FILE *fp; fp = fopen(str, "w"); fclose(fp); } free(str); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); } void update(){ status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); } void not_implemented(int passes, int index){ mvaddstr(terminal_height-1, 0, key_binding[index].comment); mvaddstr(terminal_height-1, strlen(key_binding[index].comment), "\t"); mvaddstr(terminal_height-1, strlen(key_binding[index].comment) + strlen("\t"), "is not yet implemented"); } void jump_to_dir(int passes, int index){ if ((char*)key_binding[index].black_magic) { if (chdir(getenv((char*)key_binding[index].black_magic+1)) != 0) { FAIL("jump_to_dir", "jumping to black_magic in config.h failed"); } } status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); } void order_by(int passes, int index){ order_func = key_binding[index].black_magic; status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY); } void cmd_on_selected(int passes, int index){ unsigned int i = 0; unsigned int hits = 0; char *file_str = " "; for (i = 0; i < mid_file_count; i++) { if (mid_content[i].status & FILE_STATUS_SELECTED) { file_str = concat(file_str, "\""); file_str = concat(file_str, mid_content[i].file_name); file_str = concat(file_str, "\" "); hits++; } } if (hits) { btm_buffer = concat(key_binding[index].black_magic, file_str); } else { btm_buffer = concat(key_binding[index].black_magic, "\""); btm_buffer = concat(btm_buffer, file_current->file_name); btm_buffer = concat(btm_buffer, "\""); } btm_buffer = concat(btm_buffer, "?"); btm_buffer = concat(btm_buffer, "\n\n"); btm_buffer = concat(btm_buffer, "(y/N)"); status = STATUS_UPDATE_SCREEN_0; werase(win_b); mvwin(win_b, terminal_height-6, 0); wresize(win_b, 5, terminal_width/3); /*the div3 just looks cool*/ render_pass(); timeout(-1); /* negative numbers block until enter is pressed */ /* TODO(2025-07-06T07:22:49) fix fixed buffer size */ char ch = wgetch(win_b); if (ch == 'y' || ch == 'Y') { /* the second loop is used to add "./", wich is not being printed" */ 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 */ if (hits) { for (i = 0; i < mid_file_count; i++) { if (mid_content[i].status & FILE_STATUS_SELECTED) { free(cmd); cmd = concat((char*)key_binding[index].black_magic, " \""); cmd = concat(cmd, mid_content[i].file_name); cmd = concat(cmd, "\""); if (system(cmd) != 0) { /*do nothing*/ } } } free(btm_buffer); btm_buffer = concat("completed: ", key_binding[index].black_magic); } else { free(btm_buffer); free(cmd); cmd = concat((char*)key_binding[index].black_magic, " \""); cmd = concat(cmd, file_current->file_name); cmd = concat(cmd, "\""); if (system(cmd) != 0) { /*do nothing*/ } mvaddstr(10,10, cmd); } /*system(cmd);*/ free(cmd); } else { free(btm_buffer); btm_buffer = "cancled deletion"; } timeout(10); status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_MASK | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_RELOAD_FULL); if (hits) { free(file_str); } }