From 9979966610bb3afea12f6363475c2c78fab139a8 Mon Sep 17 00:00:00 2001 From: Piotr Marendowski Date: Fri, 29 Mar 2024 22:43:28 +0100 Subject: [PATCH 01/15] Lay the groundwork for deleting files --- ccc.c | 73 ++++++++++++++++++++++++++++++++++++++++---------------- config.h | 6 ++++- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/ccc.c b/ccc.c index 09b746a..a50c190 100644 --- a/ccc.c +++ b/ccc.c @@ -18,6 +18,7 @@ /* functions' definitions */ void show_help(); void start_ccc(); +char *check_trash_dir(); void change_dir(const char *buf, int selection, int ftype); int mkdir_p(const char *destdir); void populate_files(const char *path, int ftype); @@ -39,8 +40,9 @@ long current_selection = 0; bool dirs_size = DIRS_SIZE; bool show_hidden = SHOW_HIDDEN; bool file_details = SHOW_DETAILS; +char *trash_dir; char *cwd; -char *p_cwd; /* previous cwd */ +char *p_cwd; /* previous cwd */ int half_width; ArrayList *files; ArrayList *marked; @@ -234,25 +236,9 @@ int main(int argc, char** argv) /* go to the trash dir */ case 't':; - #ifdef TRASH_DIR - char *trash_dir = TRASH_DIR; - #else - char *trash_dir = getenv("CCC_TRASH"); - #endif - if (trash_dir == NULL) { - wpprintw("$CCC_TRASH is not defined"); - } else { - if (access(trash_dir, F_OK) != 0) { - /* create the directory with 755 perm if it doesn't exit */ - if (mkdir_p(trash_dir) == -1) { - switch (errno) { - case EACCES: - wpprintw("Parent directory does not allow write permission or one of directories does not allow search access"); - } - } - } + char *trash_dir = check_trash_dir(); + if (trash_dir != NULL) change_dir(trash_dir, 0, 0); - } break; /* show directories' sizes */ @@ -302,7 +288,10 @@ int main(int argc, char** argv) /* delete */ case 'd':; if (marked->length) { - ; + char *trash_dir = check_trash_dir(); + if (trash_dir != NULL) + /* do your magic here */ + change_dir(trash_dir, 0, 0); } break; @@ -374,6 +363,50 @@ void start_ccc() init_windows(); } +/* Checks if trash directory is set and returns it */ +char *check_trash_dir() +{ + char *path = memalloc(PATH_MAX * sizeof(char)); + + #ifdef TRASH_DIR + trash_dir = TRASH_DIR; + #endif + + /* check if there is trash_dir */ + if (trash_dir == NULL) { + wpprintw("No trash directory defined"); + return NULL; + } else { + /* if trash_dir has ~ then make it $HOME */ + /* use path as trash_dir */ + if (trash_dir[0] == '~') { + char *home = getenv("HOME"); + if (home == NULL) { + wpprintw("$HOME is not defined, can't read the trash directory"); + return NULL; + } + /* replace ~ with home */ + snprintf(path, PATH_MAX, "%s%s", home, trash_dir + 1); + } + else { + strcpy(path, trash_dir); + } + + /* if has access to trash_dir */ + if (access(path, F_OK) != 0) { + /* create the directory with 755 perm if it doesn't exit */ + if (mkdir_p(path) == -1) { + switch (errno) { + case EACCES: + wpprintw("Parent directory does not allow write permission or one of directories does not allow search access"); + return NULL; + } + } + } + } + return path; +} + /* * Change directory in window with selection */ diff --git a/config.h b/config.h index f8abf36..d8ca159 100644 --- a/config.h +++ b/config.h @@ -8,8 +8,12 @@ #define DRAW_BORDERS true /* Draw borders around windows? */ #define DRAW_PREVIEW true /* Draw file preview? */ + #define SHOW_HIDDEN true /* show hidden files/dotfiles in preview */ -#define SHOW_DETAILS true /* show file details */ +#define SHOW_DETAILS true /* show file details */ + +/* will create this directory if doesn't exist! */ +#define TRASH_DIR "~/.local/ccc/trash/" /* set width offset for windows: +-------------%-------------+ From b470b7b2861016e2bd16e542c2845bbc8257082a Mon Sep 17 00:00:00 2001 From: night0721 Date: Fri, 29 Mar 2024 22:34:26 +0000 Subject: [PATCH 02/15] icons and fix goto trash dir and fix preview --- README.md | 4 +- ccc.c | 129 +++++++++++++++++++++++++++++++++-------------------- config.h | 6 ++- file.c | 69 +++++++++++++++-------------- file.h | 3 +- icons.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ icons.h | 18 ++++++++ 7 files changed, 275 insertions(+), 84 deletions(-) create mode 100644 icons.c create mode 100644 icons.h diff --git a/README.md b/README.md index 4093a20..e3a6f6b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Consider this project incomplete and WIP! | Standard movement | X | | | Advanced movement (jumps) | X | | | File details | X | | +| File icons! | X | | | Searching for files | | | | Sorting | | | | Marking and marking operations | | | @@ -32,9 +33,10 @@ Consider this project incomplete and WIP! ### Dependencies - gcc -- ncurses +- ncursesw - make - pkg-config +- Any [Nerd Font](https://www.nerdfonts.com/) for file icons (optional, but turned on by default) ### Building diff --git a/ccc.c b/ccc.c index 09b746a..85f4b8c 100644 --- a/ccc.c +++ b/ccc.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "file.h" #include "util.h" @@ -18,8 +20,9 @@ /* functions' definitions */ void show_help(); void start_ccc(); +char *check_trash_dir(); void change_dir(const char *buf, int selection, int ftype); -int mkdir_p(const char *destdir); +void mkdir_p(const char *destdir); void populate_files(const char *path, int ftype); int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); void add_file_stat(char *filepath, int ftype); @@ -41,6 +44,7 @@ bool show_hidden = SHOW_HIDDEN; bool file_details = SHOW_DETAILS; char *cwd; char *p_cwd; /* previous cwd */ +char *trash_dir; int half_width; ArrayList *files; ArrayList *marked; @@ -71,6 +75,7 @@ int main(int argc, char** argv) /* initialize screen, don't print special chars, * make ctrl + c work, don't show cursor * enable arrow keys */ + setlocale(LC_ALL, ""); initscr(); noecho(); cbreak(); @@ -234,26 +239,10 @@ int main(int argc, char** argv) /* go to the trash dir */ case 't':; - #ifdef TRASH_DIR - char *trash_dir = TRASH_DIR; - #else - char *trash_dir = getenv("CCC_TRASH"); - #endif - if (trash_dir == NULL) { - wpprintw("$CCC_TRASH is not defined"); - } else { - if (access(trash_dir, F_OK) != 0) { - /* create the directory with 755 perm if it doesn't exit */ - if (mkdir_p(trash_dir) == -1) { - switch (errno) { - case EACCES: - wpprintw("Parent directory does not allow write permission or one of directories does not allow search access"); - } - } - } + char *trash_dir = check_trash_dir(); + if (trash_dir != NULL) change_dir(trash_dir, 0, 0); - } - break; + break; /* show directories' sizes */ case 'A': @@ -302,7 +291,11 @@ int main(int argc, char** argv) /* delete */ case 'd':; if (marked->length) { - ; + char *trash_dir = check_trash_dir(); + if (trash_dir != NULL) { + ; + /* do your magic here */ + } } break; @@ -374,6 +367,44 @@ void start_ccc() init_windows(); } +/* Checks if trash directory is set and returns it */ +char *check_trash_dir() +{ + char *path = memalloc(PATH_MAX * sizeof(char)); + + #ifdef TRASH_DIR + trash_dir = TRASH_DIR; + #endif + + /* check if there is trash_dir */ + if (trash_dir == NULL) { + wpprintw("No trash directory defined"); + return NULL; + } else { + /* if trash_dir has ~ then make it $HOME */ + /* use path as trash_dir */ + if (trash_dir[0] == '~') { + char *home = getenv("HOME"); + if (home == NULL) { + wpprintw("$HOME is not defined, can't read the trash directory"); + return NULL; + } + /* replace ~ with home */ + snprintf(path, PATH_MAX, "%s%s", home, trash_dir + 1); + } + else { + strcpy(path, trash_dir); + } + + /* if has access to trash_dir */ + if (access(path, F_OK) != 0) { + /* create the directory with 755 perm if it doesn't exit */ + mkdir_p(path); + } + } + return path; +} + /* * Change directory in window with selection */ @@ -399,7 +430,7 @@ void change_dir(const char *buf, int selection, int ftype) * Recursively create directory by creating each subdirectory * like mkdir -p */ -int mkdir_p(const char *destdir) +void mkdir_p(const char *destdir) { char *path = memalloc(PATH_MAX * sizeof(char)); char dir_path[PATH_MAX] = ""; @@ -408,7 +439,7 @@ int mkdir_p(const char *destdir) char *home = getenv("HOME"); if (home == NULL) { wpprintw("$HOME is not defined"); - return -1; + return; } /* replace ~ with home */ snprintf(path, PATH_MAX, "%s%s", home, destdir + 1); @@ -433,15 +464,15 @@ int mkdir_p(const char *destdir) continue; } - perror("ccc"); + wpprintw("mkdir failed: %s\n", strerror(errno)); free(path); - return -1; + return; } token = strtok(NULL, "/"); } free(path); - return 0; + return; } /* @@ -493,7 +524,7 @@ int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, s /* * Get file's last modified time, size, type * Add that file into list - * ftype: normal file = 0, normal marked = 1, marking ALL = 2 + * ftype: normal file = 0, normal marked = 1, marked ALL = 2 */ void add_file_stat(char *filepath, int ftype) { @@ -501,32 +532,35 @@ void add_file_stat(char *filepath, int ftype) if (stat(filepath, &file_stat) == -1) { /* can't be triggered? */ if (errno == EACCES) - arraylist_add(files, filepath, "", "", 8, false, false); + arraylist_add(files, filepath, "", "", "", 8, false, false); } - /* get file type and color, 4 chars for the type */ + /* get file type and color, 4 chars for the type and icon */ char *type = memalloc(4 * sizeof(char)); + wchar_t *icon = memalloc(2 * sizeof(wchar_t)); + wcsncpy(icon, L"", 2); int color; + if (S_ISDIR(file_stat.st_mode)) { - strcpy(type, "DIR"); /* directory type */ + strncpy(type, "DIR", 4); /* directory type */ color = 5; /* blue color */ } else if (S_ISREG(file_stat.st_mode)) { - strcpy(type, "REG"); /* regular file */ + strncpy(type, "REG", 4); /* regular file */ color = 8; /* white color */ } else if (S_ISLNK(file_stat.st_mode)) { - strcpy(type, "LNK"); /* symbolic link */ + strncpy(type, "LNK", 4); /* symbolic link */ color = 3; /* green color */ } else if (S_ISCHR(file_stat.st_mode)) { - strcpy(type, "CHR"); /* character device */ + strncpy(type, "CHR", 4); /* character device */ color = 8; /* white color */ } else if (S_ISSOCK(file_stat.st_mode)) { - strcpy(type, "SOC"); /* socket */ + strncpy(type, "SOC", 4); /* socket */ color = 8; /* white color */ } else if (S_ISBLK(file_stat.st_mode)) { - strcpy(type, "BLK"); /* block device */ + strncpy(type, "BLK", 4); /* block device */ color = 4; /* yellow color */ } else if (S_ISFIFO(file_stat.st_mode)) { - strcpy(type, "FIF"); /* FIFO */ + strncpy(type, "FIF", 4); /* FIFO */ color = 8; /* white color */ } else { color = 8; /* white color */ @@ -536,16 +570,16 @@ void add_file_stat(char *filepath, int ftype) if (ftype == 1 || ftype == 2) { /* force if user is marking all files */ bool force = ftype == 2 ? true : false; - arraylist_add(marked, filepath, NULL, type, 8, true, force); + arraylist_add(marked, filepath, NULL, type, icon, 8, true, force); /* free type and return without allocating more stuff */ free(type); return; } /* get last modified time */ - char *time = memalloc(20 * sizeof(char)); + char *time = memalloc(17 * sizeof(char)); /* format last modified time to a string */ - strftime(time, 20, "%Y-%m-%d %H:%M", localtime(&file_stat.st_mtime)); + strftime(time, 17, "%Y-%m-%d %H:%M", localtime(&file_stat.st_mtime)); /* get file size */ double bytes = file_stat.st_size; @@ -560,7 +594,7 @@ void add_file_stat(char *filepath, int ftype) } } /* max 25 chars due to long, space, suffix and null */ - char *size = memalloc(25 * sizeof(char)); + char *size = memalloc(8 * sizeof(char)); int unit = 0; const char* units[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; while (bytes > 1024) { @@ -573,17 +607,18 @@ void add_file_stat(char *filepath, int ftype) /* get file mode string */ char *mode_str = get_file_mode(file_stat.st_mode); - char *total_stat = memalloc(56 * sizeof(char)); - snprintf(total_stat, 56, "%s %s %-8s", mode_str, time, size); - total_stat[strlen(total_stat)] = '\0'; + /* 11 + 17 + 8 + 1 for null */ + char *total_stat = memalloc(37 * sizeof(char)); + snprintf(total_stat, 37, "%s %s %-8s", mode_str, time, size); - arraylist_add(files, filepath, total_stat, type, color, false, false); + arraylist_add(files, filepath, total_stat, type, icon, color, false, false); free(time); free(size); free(total_stat); free(type); free(mode_str); + free(icon); } /* @@ -593,7 +628,7 @@ void add_file_stat(char *filepath, int ftype) char *get_file_mode(mode_t mode) { char *mode_str = memalloc(sizeof(char) * 11); - mode_str[0] = S_ISDIR(mode) ? 'd' : '-'; // Check if it's a directory + mode_str[0] = S_ISDIR(mode) ? 'd' : '-'; /* Check if it's a directory */ mode_str[1] = (mode & S_IRUSR) ? 'r' : '-'; mode_str[2] = (mode & S_IWUSR) ? 'w' : '-'; mode_str[3] = (mode & S_IXUSR) ? 'x' : '-'; @@ -603,7 +638,7 @@ char *get_file_mode(mode_t mode) mode_str[7] = (mode & S_IROTH) ? 'r' : '-'; mode_str[8] = (mode & S_IWOTH) ? 'w' : '-'; mode_str[9] = (mode & S_IXOTH) ? 'x' : '-'; - mode_str[10] = '\0'; // Null terminator + mode_str[10] = '\0'; return mode_str; } @@ -694,10 +729,10 @@ void highlight_current_line() #if DRAW_PREVIEW show_file_content(); #endif - wrefresh(preview_content); #if DRAW_BORDERS draw_border_title(preview_border, true); #endif + wrefresh(preview_content); } /* diff --git a/config.h b/config.h index f8abf36..e9b48ac 100644 --- a/config.h +++ b/config.h @@ -9,7 +9,8 @@ #define DRAW_BORDERS true /* Draw borders around windows? */ #define DRAW_PREVIEW true /* Draw file preview? */ #define SHOW_HIDDEN true /* show hidden files/dotfiles in preview */ -#define SHOW_DETAILS true /* show file details */ +#define SHOW_DETAILS true /* show file details */ +#define SHOW_ICONS true /* show file icons */ /* set width offset for windows: +-------------%-------------+ @@ -31,6 +32,9 @@ In COLS: /* File location to write last directory */ #define LAST_D "~/.cache/ccc/.ccc_d" +/* will create this directory if doesn't exist! */ +#define TRASH_DIR "~/.cache/ccc/trash/" + /* Keybindings */ #define CTRLD 0x04 #define ENTER 0xA diff --git a/file.c b/file.c index 6430419..1ab9b61 100644 --- a/file.c +++ b/file.c @@ -2,21 +2,10 @@ #include #include #include +#include #include "util.h" - -typedef struct file { - char *path; - char *stats; - char *type; - int color; -} file; - -typedef struct ArrayList { - size_t length; - size_t capacity; - file *items; -} ArrayList; +#include "file.h" ArrayList *arraylist_init(size_t capacity) { @@ -24,6 +13,7 @@ ArrayList *arraylist_init(size_t capacity) list->length = 0; list->capacity = capacity; list->items = memalloc(capacity * sizeof(file)); + return list; } @@ -36,7 +26,10 @@ void arraylist_free(ArrayList *list) free(list->items[i].path); if (list->items[i].stats != NULL) free(list->items[i].stats); + /*if (list->items[i].icon != NULL) + free(list->items[i].icon);*/ } + free(list->items); list->length = 0; } @@ -48,63 +41,66 @@ bool arraylist_includes(ArrayList *list, char *path) return true; } } + return false; } void arraylist_remove(ArrayList *list, long index) { - if (index >= list->length) { + if (index >= list->length) return; - } free(list->items[index].path); free(list->items[index].stats); free(list->items[index].type); + free(list->items[index].icon); - for (long i = index; i < list->length - 1; i++) { + for (long i = index; i < list->length - 1; i++) list->items[i] = list->items[i + 1]; - } list->length--; } /* - * force will not remove duplicate marked files, instead it just skip adding + * Force will not remove duplicate marked files, instead it just skip adding */ -void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, int color, bool marked, bool force) +void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force) { char *filepath_cp = NULL; char *stats_cp = NULL; char *type_cp = NULL; + wchar_t *icon_cp = NULL; + if (filepath != NULL) { filepath_cp = strdup(filepath); - if (filepath_cp == NULL) { + if (filepath_cp == NULL) perror("ccc"); - } } if (stats != NULL) { stats_cp = strdup(stats); - if (stats_cp == NULL) { + if (stats_cp == NULL) perror("ccc"); - } } if (type != NULL) { - type_cp = strdup(type); - if (type_cp == NULL) { + type_cp = strdup(type); + if (type_cp == NULL) + perror("ccc"); + } + if (icon != NULL) { + icon_cp = wcsdup(icon); + if (icon_cp == NULL) perror("ccc"); - } } - /* path, stats, type, color */ - file new_file = { filepath_cp, stats_cp, type_cp, color }; + /* path, stats, type, icon, color */ + file new_file = { filepath_cp, stats_cp, type_cp, icon_cp, color }; if (list->capacity != list->length) { if (marked) { for (int i = 0; i < list->length; i++) { if (strcmp(list->items[i].path, new_file.path) == 0) { - if (!force) { + if (!force) arraylist_remove(list, i); - } return; } } @@ -116,9 +112,10 @@ void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, int file *old_items = list->items; list->capacity = new_cap; list->items = new_items; - for (int i = 0; i < list->length; i++) { + + for (int i = 0; i < list->length; i++) new_items[i] = old_items[i]; - } + free(old_items); list->items[list->length] = new_file; } @@ -132,6 +129,7 @@ char *get_line(ArrayList *list, long index, bool detail) { file file = list->items[index]; char *name = strdup(file.path); + wchar_t *icon = wcsdup(file.icon); char *stats = NULL; size_t length; if (detail) { @@ -148,10 +146,13 @@ char *get_line(ArrayList *list, long index, bool detail) name = basename(name); if (name == NULL) perror("ccc"); + + /*printf("%ls", icon);*/ + if (detail) { - snprintf(line, length, "%s %s", stats, name); + snprintf(line, length, "%s %ls %s", stats, icon, name); } else { - snprintf(line, length, "%s", name); + snprintf(line, length, "%ls %s", icon, name); } return line; diff --git a/file.h b/file.h index e7a0434..49f72fc 100644 --- a/file.h +++ b/file.h @@ -7,6 +7,7 @@ typedef struct file { char *path; char *stats; char *type; + wchar_t *icon; int color; } file; @@ -20,7 +21,7 @@ ArrayList *arraylist_init(size_t capacity); void arraylist_free(ArrayList *list); bool arraylist_includes(ArrayList *list, char *path); void arraylist_remove(ArrayList *list, long index); -void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, int color, bool marked, bool force); +void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force); char *get_line(ArrayList *list, long index, bool detail); #endif diff --git a/icons.c b/icons.c new file mode 100644 index 0000000..4b995ed --- /dev/null +++ b/icons.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include + +#define MAX_NAME 30 +#define TABLE_SIZE 20 + +typedef struct { + char name[MAX_NAME]; + char *icon; +} icon; + +icon *hash_table[TABLE_SIZE]; + +/* Hashes every name with: name and TABLE_SIZE */ +unsigned int hash(char *name) +{ + int length = strnlen(name, MAX_NAME), i = 0; + unsigned int hash_value = 0; + + for (; i < length; i++) { + hash_value += name[i]; + hash_value = (hash_value * name[i]) % TABLE_SIZE; + } + + return hash_value; +} + +void init_hash_table() +{ + int i = 0; + + for (; i < TABLE_SIZE; i++) + hash_table[i] = NULL; +} + +void print_table() +{ + int i = 0; + + for (; i < TABLE_SIZE; i++) { + if (hash_table[i] == NULL) { + printf("%i. ---\n", i); + } else { + printf("%i. %s %s\n", i, hash_table[i]->name, hash_table[i]->icon); + } + } +} + +/* Gets hashed name and tries to store the icon struct in that place */ +bool add_icon(icon *p) +{ + if (p == NULL) return false; + + int index = hash(p->name); + int i = 0, try; + + try = (i + index) % TABLE_SIZE; + if (hash_table[try] == NULL) { + hash_table[try] = p; + return true; + } + + return false; +} + +/* Rehashes the name and then looks in this spot, if found returns icon */ +icon *icon_search(char *name) +{ + int index = hash(name), i = 0; + + // this handles icons with the same hash values + // or use linked lists in structs + // for (; i < TABLE_SIZE; i++) { + // int try = (index + i) % TABLE_SIZE; + // + // for (; i < TABLE_SIZE; i++) { + // try = (i + index) % TABLE_SIZE; + // + // if (hash_table[try] == NULL) + // return false; + // + // if (strncmp(hash_table[try]->name, name, TABLE_SIZE) == 0) + // return hash_table[try]; + // } + // + // return false; + // } + // + // return NULL; + + if (hash_table[index] == NULL) + return false; + + if (strncmp(hash_table[index]->name, name, MAX_NAME) == 0) + return hash_table[index]; + + return NULL; +} + +int main(void) +{ + init_hash_table(); + + /* name reference name icon */ + icon c = { .name="c", .icon="" }; + icon h = { .name="h", .icon="" }; + icon cpp = { .name="cpp", .icon="" }; + icon hpp = { .name="hpp", .icon="󰰀" }; + icon md = { .name="md", .icon="" }; + + add_icon(&c); + add_icon(&h); + add_icon(&cpp); + add_icon(&hpp); + add_icon(&md); + + print_table(); + + icon *tmp = icon_search("hpp"); + + if (tmp == NULL) + printf("null\n"); + + printf("%s", tmp->icon); + + return 0; +} + diff --git a/icons.h b/icons.h new file mode 100644 index 0000000..2de349f --- /dev/null +++ b/icons.h @@ -0,0 +1,18 @@ +#ifndef FILE_H_ +#define FILE_H_ + +#define MAX_NAME 30 +#define TABLE_SIZE 20 + +typedef struct { + char name[MAX_NAME]; + char icon[4]; +} icon; + +unsigned int hash(char *name); +void init_hash_table(); +void print_table(); +bool add_icon(icon *p); +icon *icon_search(char *name); + +#endif From 575d873efeaac8e1cc9069c6ff05519dcfaf71ab Mon Sep 17 00:00:00 2001 From: night0721 Date: Sat, 30 Mar 2024 03:39:02 +0000 Subject: [PATCH 03/15] make icons show in dir content via hash table dynamically --- Makefile | 2 +- ccc.c | 43 +++++++++++++---- config.h | 2 + file.c | 4 +- icons.c | 137 +++++++++++++++++++++++-------------------------------- icons.h | 19 ++++---- 6 files changed, 108 insertions(+), 99 deletions(-) diff --git a/Makefile b/Makefile index 8686316..4eeec43 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ MANDIR = $(PREFIX)/share/man/man1 LDFLAGS = $(shell pkg-config --libs ncursesw) CFLAGS = -O3 -march=native -mtune=native -pipe -s -std=c99 -pedantic -Wall -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 $(shell pkg-config --cflags ncursesw) -SRC = ccc.c util.c file.c +SRC = ccc.c util.c file.c icons.c $(TARGET): $(SRC) $(CC) $(SRC) -o $@ $(CFLAGS) $(LDFLAGS) diff --git a/ccc.c b/ccc.c index 2905eeb..5a7a898 100644 --- a/ccc.c +++ b/ccc.c @@ -13,9 +13,10 @@ #include #include -#include "file.h" -#include "util.h" #include "config.h" +#include "file.h" +#include "icons.h" +#include "util.h" /* functions' definitions */ void show_help(); @@ -105,6 +106,7 @@ int main(int argc, char** argv) /* init files and marked arrays */ files = arraylist_init(100); marked = arraylist_init(100); + hashtable_init(); cwd = memalloc(PATH_MAX * sizeof(char)); if (argc == 2) { @@ -533,13 +535,38 @@ void add_file_stat(char *filepath, int ftype) if (stat(filepath, &file_stat) == -1) { /* can't be triggered? */ if (errno == EACCES) - arraylist_add(files, filepath, "", "", "", 8, false, false); + arraylist_add(files, filepath, NULL, NULL, NULL, 8, false, false); } /* get file type and color, 4 chars for the type and icon */ char *type = memalloc(4 * sizeof(char)); - wchar_t *icon = memalloc(2 * sizeof(wchar_t)); - wcsncpy(icon, L"", 2); + wchar_t *icon_str = memalloc(2 * sizeof(wchar_t)); + + filepath[strlen(filepath)] = '\0'; + /* find last / in path */ + char *f_bname = strrchr(filepath, '/'); + char *ext = NULL; + if (f_bname != NULL) { + /* shift 1 to get basename */ + f_bname += 1; + /* handle file without extension */ + ext = strrchr(f_bname, '.'); + if (ext != NULL) { + ext += 1; + } else { + ext = f_bname; + } + } + if (ext != NULL) { + icon *ext_icon = hashtable_search(ext); + if (ext_icon == NULL) + wcsncpy(icon_str, L"", 2); + else + wcsncpy(icon_str, ext_icon->icon, 2); + } else { + wcsncpy(icon_str, L"0", 2); + } + int color; if (S_ISDIR(file_stat.st_mode)) { @@ -571,7 +598,7 @@ void add_file_stat(char *filepath, int ftype) if (ftype == 1 || ftype == 2) { /* force if user is marking all files */ bool force = ftype == 2 ? true : false; - arraylist_add(marked, filepath, NULL, type, icon, 8, true, force); + arraylist_add(marked, filepath, NULL, type, icon_str, 8, true, force); /* free type and return without allocating more stuff */ free(type); return; @@ -612,14 +639,14 @@ void add_file_stat(char *filepath, int ftype) char *total_stat = memalloc(37 * sizeof(char)); snprintf(total_stat, 37, "%s %s %-8s", mode_str, time, size); - arraylist_add(files, filepath, total_stat, type, icon, color, false, false); + arraylist_add(files, filepath, total_stat, type, icon_str, color, false, false); free(time); free(size); free(total_stat); free(type); free(mode_str); - free(icon); + free(icon_str); } /* diff --git a/config.h b/config.h index 9f9dd7d..52032bc 100644 --- a/config.h +++ b/config.h @@ -1,3 +1,5 @@ +#include "icons.h" + /* Settings */ #define PH 1 /* panel height */ #define JUMP_NUM 14 /* how long ctrl + u/d jump are */ diff --git a/file.c b/file.c index 1ab9b61..50afab1 100644 --- a/file.c +++ b/file.c @@ -26,8 +26,8 @@ void arraylist_free(ArrayList *list) free(list->items[i].path); if (list->items[i].stats != NULL) free(list->items[i].stats); - /*if (list->items[i].icon != NULL) - free(list->items[i].icon);*/ + if (list->items[i].icon != NULL) + free(list->items[i].icon); } free(list->items); diff --git a/icons.c b/icons.c index 4b995ed..59f0638 100644 --- a/icons.c +++ b/icons.c @@ -2,14 +2,10 @@ #include #include #include +#include -#define MAX_NAME 30 -#define TABLE_SIZE 20 - -typedef struct { - char name[MAX_NAME]; - char *icon; -} icon; +#include "icons.h" +#include "util.h" icon *hash_table[TABLE_SIZE]; @@ -24,18 +20,43 @@ unsigned int hash(char *name) hash_value = (hash_value * name[i]) % TABLE_SIZE; } + printf("Name: %s | Hash Value: %d\n", name, hash_value); return hash_value; } -void init_hash_table() +void hashtable_init() { - int i = 0; - - for (; i < TABLE_SIZE; i++) + for (int i = 0; i < TABLE_SIZE; i++) hash_table[i] = NULL; + + icon *c = memalloc(sizeof(icon)); + strcpy(c->name, "c"); + c->icon = L""; + + icon *h = memalloc(sizeof(icon)); + strcpy(h->name, "h"); + h->icon = L""; + + icon *cpp = memalloc(sizeof(icon)); + strcpy(cpp->name, "cpp"); + cpp->icon = L""; + + icon *hpp = memalloc(sizeof(icon)); + strcpy(hpp->name, "hpp"); + hpp->icon = L"󰰀"; + + icon *md = memalloc(sizeof(icon)); + strcpy(md->name, "md"); + md->icon = L""; + + hashtable_add(c); + hashtable_add(h); + hashtable_add(cpp); + hashtable_add(hpp); + hashtable_add(md); } -void print_table() +void hashtable_print() { int i = 0; @@ -43,88 +64,44 @@ void print_table() if (hash_table[i] == NULL) { printf("%i. ---\n", i); } else { - printf("%i. %s %s\n", i, hash_table[i]->name, hash_table[i]->icon); + printf("%i. | Name %s | Icon %ls\n", i, hash_table[i]->name, hash_table[i]->icon); } } } /* Gets hashed name and tries to store the icon struct in that place */ -bool add_icon(icon *p) +bool hashtable_add(icon *p) { if (p == NULL) return false; int index = hash(p->name); - int i = 0, try; - - try = (i + index) % TABLE_SIZE; - if (hash_table[try] == NULL) { - hash_table[try] = p; - return true; + int initial_index = index; + /* linear probing until an empty slot is found */ + while (hash_table[index] != NULL) { + index = (index + 1) % TABLE_SIZE; /* move to next item */ + /* the hash table is full as no available index back to initial index, cannot fit new item */ + if (index == initial_index) return false; } - return false; + hash_table[index] = p; + return true; } /* Rehashes the name and then looks in this spot, if found returns icon */ -icon *icon_search(char *name) +icon *hashtable_search(char *name) { - int index = hash(name), i = 0; - - // this handles icons with the same hash values - // or use linked lists in structs - // for (; i < TABLE_SIZE; i++) { - // int try = (index + i) % TABLE_SIZE; - // - // for (; i < TABLE_SIZE; i++) { - // try = (i + index) % TABLE_SIZE; - // - // if (hash_table[try] == NULL) - // return false; - // - // if (strncmp(hash_table[try]->name, name, TABLE_SIZE) == 0) - // return hash_table[try]; - // } - // - // return false; - // } - // - // return NULL; - - if (hash_table[index] == NULL) - return false; - - if (strncmp(hash_table[index]->name, name, MAX_NAME) == 0) - return hash_table[index]; - + int index = hash(name); + int initial_index = index; + + /* Linear probing until an empty slot or the desired item is found */ + while (hash_table[index] != NULL) { + if (strncmp(hash_table[index]->name, name, MAX_NAME) == 0) + return hash_table[index]; + + index = (index + 1) % TABLE_SIZE; /* Move to the next slot */ + /* back to same item */ + if (index == initial_index) break; + } + return NULL; } - -int main(void) -{ - init_hash_table(); - - /* name reference name icon */ - icon c = { .name="c", .icon="" }; - icon h = { .name="h", .icon="" }; - icon cpp = { .name="cpp", .icon="" }; - icon hpp = { .name="hpp", .icon="󰰀" }; - icon md = { .name="md", .icon="" }; - - add_icon(&c); - add_icon(&h); - add_icon(&cpp); - add_icon(&hpp); - add_icon(&md); - - print_table(); - - icon *tmp = icon_search("hpp"); - - if (tmp == NULL) - printf("null\n"); - - printf("%s", tmp->icon); - - return 0; -} - diff --git a/icons.h b/icons.h index 2de349f..db87223 100644 --- a/icons.h +++ b/icons.h @@ -1,18 +1,21 @@ -#ifndef FILE_H_ -#define FILE_H_ +#ifndef ICONS_H_ +#define ICONS_H_ + +#include +#include #define MAX_NAME 30 -#define TABLE_SIZE 20 +#define TABLE_SIZE 50 typedef struct { char name[MAX_NAME]; - char icon[4]; + wchar_t *icon; } icon; unsigned int hash(char *name); -void init_hash_table(); -void print_table(); -bool add_icon(icon *p); -icon *icon_search(char *name); +void hashtable_init(); +void hashtable_print(); +bool hashtable_add(icon *p); +icon *hashtable_search(char *name); #endif From 652473a0ecb9cfb46ab0cce6ec5ff732bb8c06ee Mon Sep 17 00:00:00 2001 From: Piotr Marendowski Date: Sat, 30 Mar 2024 11:06:38 +0100 Subject: [PATCH 04/15] Add a bunch of icons --- file.c | 2 -- icons.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/file.c b/file.c index 50afab1..1f14be0 100644 --- a/file.c +++ b/file.c @@ -147,8 +147,6 @@ char *get_line(ArrayList *list, long index, bool detail) if (name == NULL) perror("ccc"); - /*printf("%ls", icon);*/ - if (detail) { snprintf(line, length, "%s %ls %s", stats, icon, name); } else { diff --git a/icons.c b/icons.c index 59f0638..9e8b47a 100644 --- a/icons.c +++ b/icons.c @@ -49,11 +49,85 @@ void hashtable_init() strcpy(md->name, "md"); md->icon = L""; + icon *py = memalloc(sizeof(icon)); + strcpy(md->name, "py"); + md->icon = L""; + + icon *java = memalloc(sizeof(icon)); + strcpy(md->name, "java"); + md->icon = L""; + + icon *json = memalloc(sizeof(icon)); + strcpy(md->name, "json"); + md->icon = L""; + + icon *js = memalloc(sizeof(icon)); + strcpy(md->name, "js"); + md->icon = L""; + + icon *html = memalloc(sizeof(icon)); + strcpy(md->name, "html"); + md->icon = L""; + + icon *rs = memalloc(sizeof(icon)); + strcpy(md->name, "rs"); + md->icon = L""; + + icon *sh = memalloc(sizeof(icon)); + strcpy(md->name, "sh"); + md->icon = L""; + + icon *go = memalloc(sizeof(icon)); + strcpy(md->name, "go"); + md->icon = L""; + + icon *r = memalloc(sizeof(icon)); + strcpy(md->name, "r"); + md->icon = L""; + + icon *diff = memalloc(sizeof(icon)); + strcpy(md->name, "diff"); + md->icon = L""; + + icon *hs = memalloc(sizeof(icon)); + strcpy(md->name, "hs"); + md->icon = L""; + + icon *log = memalloc(sizeof(icon)); + strcpy(md->name, "log"); + md->icon = L"󱀂"; + + icon *rb = memalloc(sizeof(icon)); + strcpy(md->name, "rb"); + md->icon = L""; + + icon *iso = memalloc(sizeof(icon)); + strcpy(md->name, "iso"); + md->icon = L"󰻂"; + + icon *lua = memalloc(sizeof(icon)); + strcpy(md->name, "lua"); + md->icon = L""; + hashtable_add(c); hashtable_add(h); hashtable_add(cpp); hashtable_add(hpp); - hashtable_add(md); + hashtable_add(py); + hashtable_add(java); + hashtable_add(json); + hashtable_add(js); + hashtable_add(html); + hashtable_add(rs); + hashtable_add(sh); + hashtable_add(go); + hashtable_add(r); + hashtable_add(diff); + hashtable_add(hs); + hashtable_add(log); + hashtable_add(rb); + hashtable_add(iso); + hashtable_add(lua); } void hashtable_print() From 1f0f19174ad4caeb03c48e351ada6d9b3a7f2bdc Mon Sep 17 00:00:00 2001 From: night0721 Date: Sat, 30 Mar 2024 13:00:16 +0000 Subject: [PATCH 05/15] fix icons not showing and segfault when size not properly formatted --- ccc.c | 7 ++++++- icons.c | 62 ++++++++++++++++++++++++++++----------------------------- icons.h | 2 +- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/ccc.c b/ccc.c index 5a7a898..5cfa39d 100644 --- a/ccc.c +++ b/ccc.c @@ -630,7 +630,12 @@ void add_file_stat(char *filepath, int ftype) unit++; } /* display sizes */ - sprintf(size, "%.3g%s", bytes, units[unit]); + /* Check if there are decimal places */ + if (bytes == (unsigned int) bytes) { + sprintf(size, "%d%s", (unsigned int) bytes, units[unit]); + } else { + sprintf(size, "%.2f%s", bytes, units[unit]); + } /* get file mode string */ char *mode_str = get_file_mode(file_stat.st_mode); diff --git a/icons.c b/icons.c index 9e8b47a..135955b 100644 --- a/icons.c +++ b/icons.c @@ -20,7 +20,6 @@ unsigned int hash(char *name) hash_value = (hash_value * name[i]) % TABLE_SIZE; } - printf("Name: %s | Hash Value: %d\n", name, hash_value); return hash_value; } @@ -50,69 +49,70 @@ void hashtable_init() md->icon = L""; icon *py = memalloc(sizeof(icon)); - strcpy(md->name, "py"); - md->icon = L""; + strcpy(py->name, "py"); + py->icon = L""; icon *java = memalloc(sizeof(icon)); - strcpy(md->name, "java"); - md->icon = L""; + strcpy(java->name, "java"); + java->icon = L""; icon *json = memalloc(sizeof(icon)); - strcpy(md->name, "json"); - md->icon = L""; + strcpy(json->name, "json"); + json->icon = L""; icon *js = memalloc(sizeof(icon)); - strcpy(md->name, "js"); - md->icon = L""; + strcpy(js->name, "js"); + js->icon = L""; icon *html = memalloc(sizeof(icon)); - strcpy(md->name, "html"); - md->icon = L""; + strcpy(html->name, "html"); + html->icon = L""; icon *rs = memalloc(sizeof(icon)); - strcpy(md->name, "rs"); - md->icon = L""; + strcpy(rs->name, "rs"); + rs->icon = L""; icon *sh = memalloc(sizeof(icon)); - strcpy(md->name, "sh"); - md->icon = L""; + strcpy(sh->name, "sh"); + sh->icon = L""; icon *go = memalloc(sizeof(icon)); - strcpy(md->name, "go"); - md->icon = L""; + strcpy(go->name, "go"); + go->icon = L""; icon *r = memalloc(sizeof(icon)); - strcpy(md->name, "r"); - md->icon = L""; + strcpy(r->name, "r"); + r->icon = L""; icon *diff = memalloc(sizeof(icon)); - strcpy(md->name, "diff"); - md->icon = L""; + strcpy(diff->name, "diff"); + diff->icon = L""; icon *hs = memalloc(sizeof(icon)); - strcpy(md->name, "hs"); - md->icon = L""; + strcpy(hs->name, "hs"); + hs->icon = L""; icon *log = memalloc(sizeof(icon)); - strcpy(md->name, "log"); - md->icon = L"󱀂"; + strcpy(log->name, "log"); + log->icon = L"󱀂"; icon *rb = memalloc(sizeof(icon)); - strcpy(md->name, "rb"); - md->icon = L""; + strcpy(rb->name, "rb"); + rb->icon = L""; icon *iso = memalloc(sizeof(icon)); - strcpy(md->name, "iso"); - md->icon = L"󰻂"; + strcpy(iso->name, "iso"); + iso->icon = L"󰻂"; icon *lua = memalloc(sizeof(icon)); - strcpy(md->name, "lua"); - md->icon = L""; + strcpy(lua->name, "lua"); + lua->icon = L""; hashtable_add(c); hashtable_add(h); hashtable_add(cpp); hashtable_add(hpp); + hashtable_add(md); hashtable_add(py); hashtable_add(java); hashtable_add(json); diff --git a/icons.h b/icons.h index db87223..1aadd49 100644 --- a/icons.h +++ b/icons.h @@ -5,7 +5,7 @@ #include #define MAX_NAME 30 -#define TABLE_SIZE 50 +#define TABLE_SIZE 100 typedef struct { char name[MAX_NAME]; From 721cbfff35ba41da7a2c9e6e25a70e636095702a Mon Sep 17 00:00:00 2001 From: Piotr Marendowski Date: Sat, 30 Mar 2024 22:00:57 +0100 Subject: [PATCH 06/15] Add decimal places macro and fuck around config.h --- Makefile | 2 +- ccc.c | 19 +++++++++---------- config.h | 34 ++++++++++++++++++++-------------- icons.c | 1 + 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 4eeec43..ce65e35 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ CFLAGS = -O3 -march=native -mtune=native -pipe -s -std=c99 -pedantic -Wall -D_DE SRC = ccc.c util.c file.c icons.c -$(TARGET): $(SRC) +$(TARGET): $(SRC) $(CONF) $(CC) $(SRC) -o $@ $(CFLAGS) $(LDFLAGS) dist: diff --git a/ccc.c b/ccc.c index 5cfa39d..e506152 100644 --- a/ccc.c +++ b/ccc.c @@ -621,28 +621,27 @@ void add_file_stat(char *filepath, int ftype) bytes = total_dir_size; } } - /* max 25 chars due to long, space, suffix and null */ - char *size = memalloc(8 * sizeof(char)); + /* 3 before decimal + 1 decimal + SIZE_OFFSET (after decimal) + 1 space + 1 null */ + int size_size = 3 + 1 + DECIMAL_PLACES + 1 + 1; + char *size = memalloc(size_size * sizeof(char)); int unit = 0; - const char* units[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; while (bytes > 1024) { bytes /= 1024; unit++; } - /* display sizes */ - /* Check if there are decimal places */ + /* display sizes and check if there are decimal places */ if (bytes == (unsigned int) bytes) { sprintf(size, "%d%s", (unsigned int) bytes, units[unit]); } else { - sprintf(size, "%.2f%s", bytes, units[unit]); + sprintf(size, "%.*f%s", DECIMAL_PLACES, bytes, units[unit]); } - /* get file mode string */ char *mode_str = get_file_mode(file_stat.st_mode); - /* 11 + 17 + 8 + 1 for null */ - char *total_stat = memalloc(37 * sizeof(char)); - snprintf(total_stat, 37, "%s %s %-8s", mode_str, time, size); + /* 11 + 17 + size_size + 1 space + 1 null */ + int stat_size = 11 + 17 + size_size + 1 + 1; + char *total_stat = memalloc(stat_size * sizeof(char)); + snprintf(total_stat, stat_size, "%s %s %-*s ", mode_str, time, size_size, size); arraylist_add(files, filepath, total_stat, type, icon_str, color, false, false); diff --git a/config.h b/config.h index 52032bc..7c2202c 100644 --- a/config.h +++ b/config.h @@ -1,21 +1,15 @@ #include "icons.h" /* Settings */ -#define PH 1 /* panel height */ -#define JUMP_NUM 14 /* how long ctrl + u/d jump are */ -#define PATH_MAX 4096 +#define PH 1 /* panel height */ +#define JUMP_NUM 14 /* how long ctrl + u/d jump are */ +#define PATH_MAX 4096 /* max length of the path */ +#define DECIMAL_PLACES 1 /* how many decimal places show size with */ -/* Calculate directories' sizes RECURSIVELY upon entering? */ -#define DIRS_SIZE false +/* Size units */ +const char* units[] = {"B", "K", "M", "G", "T", "P"}; -#define DRAW_BORDERS true /* Draw borders around windows? */ -#define DRAW_PREVIEW true /* Draw file preview? */ - -#define SHOW_HIDDEN true /* show hidden files/dotfiles in preview */ -#define SHOW_DETAILS true /* show file details */ -#define SHOW_ICONS true /* show file icons */ - -/* set width offset for windows: +/* Set width offset for windows: +-------------%-------------+ | % | | files % preview | @@ -29,13 +23,25 @@ In COLS: -15 will make preview bigger */ #define WINDOW_OFFSET 0 +/* Options */ +#define DRAW_BORDERS true /* draw borders around windows */ +#define DRAW_PREVIEW true /* draw file preview */ + +#define SHOW_HIDDEN true /* show hidden files/dotfiles at startup */ +#define SHOW_DETAILS true /* show file details at startup */ +#define SHOW_ICONS true /* show file icons at startup */ + +/* Calculate directories' sizes RECURSIVELY upon entering + `A` keybind at the startup */ +#define DIRS_SIZE false + /* Default text editor */ #define EDITOR "nvim" /* File location to write last directory */ #define LAST_D "~/.cache/ccc/.ccc_d" -/* will create this directory if doesn't exist! */ +/* Will create this directory if doesn't exist! */ #define TRASH_DIR "~/.cache/ccc/trash/" /* Keybindings */ diff --git a/icons.c b/icons.c index 135955b..1c20868 100644 --- a/icons.c +++ b/icons.c @@ -44,6 +44,7 @@ void hashtable_init() strcpy(hpp->name, "hpp"); hpp->icon = L"󰰀"; + icon *md = memalloc(sizeof(icon)); strcpy(md->name, "md"); md->icon = L""; From 53dd0e16c53b24ce9999747e6542601c47881cb1 Mon Sep 17 00:00:00 2001 From: night0721 Date: Sat, 30 Mar 2024 23:13:14 +0000 Subject: [PATCH 07/15] Reduce magic numbers, calculating size_size correctly, adding commtents at config.h, add more icons --- ccc.c | 30 +++++++++++++++++------------- config.h | 5 ++--- icons.c | 11 ++++++++++- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/ccc.c b/ccc.c index e506152..8e2c875 100644 --- a/ccc.c +++ b/ccc.c @@ -539,11 +539,14 @@ void add_file_stat(char *filepath, int ftype) } /* get file type and color, 4 chars for the type and icon */ - char *type = memalloc(4 * sizeof(char)); - wchar_t *icon_str = memalloc(2 * sizeof(wchar_t)); + size_t type_size = 4 * sizeof(char); + size_t icon_size = 2 * sizeof(wchar_t); + + char *type = memalloc(type_size); + wchar_t *icon_str = memalloc(icon_size); filepath[strlen(filepath)] = '\0'; - /* find last / in path */ + /* find last / in path by finding basename */ char *f_bname = strrchr(filepath, '/'); char *ext = NULL; if (f_bname != NULL) { @@ -564,7 +567,7 @@ void add_file_stat(char *filepath, int ftype) else wcsncpy(icon_str, ext_icon->icon, 2); } else { - wcsncpy(icon_str, L"0", 2); + wcsncpy(icon_str, L"", 2); } int color; @@ -605,9 +608,10 @@ void add_file_stat(char *filepath, int ftype) } /* get last modified time */ - char *time = memalloc(17 * sizeof(char)); + size_t time_size = 17 * sizeof(char); + char *time = memalloc(time_size); /* format last modified time to a string */ - strftime(time, 17, "%Y-%m-%d %H:%M", localtime(&file_stat.st_mtime)); + strftime(time, time_size, "%Y-%m-%d %H:%M", localtime(&file_stat.st_mtime)); /* get file size */ double bytes = file_stat.st_size; @@ -621,8 +625,8 @@ void add_file_stat(char *filepath, int ftype) bytes = total_dir_size; } } - /* 3 before decimal + 1 decimal + SIZE_OFFSET (after decimal) + 1 space + 1 null */ - int size_size = 3 + 1 + DECIMAL_PLACES + 1 + 1; + /* 4 before decimal + 1 dot + DECIMAL_PLACES (after decimal) + unit length(1 for K, 3 for KiB, taking units[1] as B never changes)+ 1 space + 1 null */ + int size_size = 4 + 1 + DECIMAL_PLACES + strlen(units[1]) + 1 + 1; char *size = memalloc(size_size * sizeof(char)); int unit = 0; while (bytes > 1024) { @@ -638,10 +642,10 @@ void add_file_stat(char *filepath, int ftype) /* get file mode string */ char *mode_str = get_file_mode(file_stat.st_mode); - /* 11 + 17 + size_size + 1 space + 1 null */ - int stat_size = 11 + 17 + size_size + 1 + 1; - char *total_stat = memalloc(stat_size * sizeof(char)); - snprintf(total_stat, stat_size, "%s %s %-*s ", mode_str, time, size_size, size); + /* mode_str(11) + time(17) + size_size + 2 spaces + 1 null */ + size_t stat_size = 11 * sizeof(char) + time_size + size_size + 3 * sizeof(char); + char *total_stat = memalloc(stat_size); + snprintf(total_stat, stat_size, "%s %s %-*s", mode_str, time, size_size, size); arraylist_add(files, filepath, total_stat, type, icon_str, color, false, false); @@ -659,7 +663,7 @@ void add_file_stat(char *filepath, int ftype) */ char *get_file_mode(mode_t mode) { - char *mode_str = memalloc(sizeof(char) * 11); + char *mode_str = memalloc(11 * sizeof(char)); mode_str[0] = S_ISDIR(mode) ? 'd' : '-'; /* Check if it's a directory */ mode_str[1] = (mode & S_IRUSR) ? 'r' : '-'; mode_str[2] = (mode & S_IWUSR) ? 'w' : '-'; diff --git a/config.h b/config.h index 7c2202c..949b0b7 100644 --- a/config.h +++ b/config.h @@ -1,5 +1,3 @@ -#include "icons.h" - /* Settings */ #define PH 1 /* panel height */ #define JUMP_NUM 14 /* how long ctrl + u/d jump are */ @@ -32,7 +30,8 @@ In COLS: #define SHOW_ICONS true /* show file icons at startup */ /* Calculate directories' sizes RECURSIVELY upon entering - `A` keybind at the startup */ + `A` keybind at the startup + **VERY EXPENSIVE**, **CAN TAKE UP TO A MINUTE IN ROOT** */ #define DIRS_SIZE false /* Default text editor */ diff --git a/icons.c b/icons.c index 1c20868..5722b6c 100644 --- a/icons.c +++ b/icons.c @@ -44,7 +44,6 @@ void hashtable_init() strcpy(hpp->name, "hpp"); hpp->icon = L"󰰀"; - icon *md = memalloc(sizeof(icon)); strcpy(md->name, "md"); md->icon = L""; @@ -108,6 +107,14 @@ void hashtable_init() icon *lua = memalloc(sizeof(icon)); strcpy(lua->name, "lua"); lua->icon = L""; + + icon *license = memalloc(sizeof(icon)); + strcpy(license->name, "LICENSE"); + license->icon = L""; + + icon *gitignore = memalloc(sizeof(icon)); + strcpy(gitignore->name, "gitignore"); + gitignore->icon = L""; hashtable_add(c); hashtable_add(h); @@ -129,6 +136,8 @@ void hashtable_init() hashtable_add(rb); hashtable_add(iso); hashtable_add(lua); + hashtable_add(license); + hashtable_add(gitignore); } void hashtable_print() From 1e0ce67a7f29c35ed0af174f5648cfe8466578bf Mon Sep 17 00:00:00 2001 From: night0721 Date: Sat, 30 Mar 2024 23:47:51 +0000 Subject: [PATCH 08/15] fix filename partial shown --- file.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/file.c b/file.c index 1f14be0..2c7487a 100644 --- a/file.c +++ b/file.c @@ -129,23 +129,26 @@ char *get_line(ArrayList *list, long index, bool detail) { file file = list->items[index]; char *name = strdup(file.path); + name = basename(name); + if (name == NULL) + perror("ccc"); + wchar_t *icon = wcsdup(file.icon); + char *stats = NULL; size_t length; if (detail) { stats = strdup(file.stats); - length = strlen(name) + strlen(stats) + 2; /* one for space and one for null */ + length = strlen(name) + strlen(stats) + 7; /* 4 for icon, 2 for space and 1 for null */ if (stats == NULL) { perror("ccc"); } } else { - length = strlen(name) + 2; /* one for space and one for null */ + length = strlen(name) + 6; /* 4 for icon, 1 for space and 1 for null */ } char *line = memalloc(length * sizeof(char)); - name = basename(name); - if (name == NULL) - perror("ccc"); + if (detail) { snprintf(line, length, "%s %ls %s", stats, icon, name); From 93c1e5f8c2e0a431894274640b54ac3bea72e205 Mon Sep 17 00:00:00 2001 From: night0721 Date: Sun, 31 Mar 2024 00:01:29 +0000 Subject: [PATCH 09/15] fix change directory from argument --- ccc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ccc.c b/ccc.c index 8e2c875..d062dbb 100644 --- a/ccc.c +++ b/ccc.c @@ -64,10 +64,15 @@ int main(int argc, char** argv) die("Usage: ccc filename"); if (argc == 2) { struct stat st; - if (lstat(argv[1], &st) != 0) { + if (lstat(argv[1], &st)) { perror("ccc"); die("Error from lstat"); } + /* chdir to directory from argument */ + if(S_ISDIR(st.st_mode) && chdir(argv[1])) { + perror("ccc"); + die("Error from chdir"); + } } /* check if it is interactive shell */ @@ -109,11 +114,7 @@ int main(int argc, char** argv) hashtable_init(); cwd = memalloc(PATH_MAX * sizeof(char)); - if (argc == 2) { - strcpy(cwd, argv[1]); - } else { - getcwd(cwd, PATH_MAX); - } + getcwd(cwd, PATH_MAX); p_cwd = memalloc(PATH_MAX * sizeof(char)); start_ccc(); populate_files(cwd, 0); From da2e1ee1440c1e358aba4e15833bb10128742ab0 Mon Sep 17 00:00:00 2001 From: night0721 Date: Sun, 31 Mar 2024 00:20:29 +0000 Subject: [PATCH 10/15] open file with argument --- ccc.c | 13 +++++++++++-- file.c | 16 +++++++++++----- file.h | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/ccc.c b/ccc.c index d062dbb..a0625eb 100644 --- a/ccc.c +++ b/ccc.c @@ -40,6 +40,7 @@ void draw_border_title(WINDOW *window, bool active); /* global variables */ unsigned int focus = 0; long current_selection = 0; +bool to_open_file = false; bool dirs_size = DIRS_SIZE; bool show_hidden = SHOW_HIDDEN; bool file_details = SHOW_DETAILS; @@ -69,10 +70,13 @@ int main(int argc, char** argv) die("Error from lstat"); } /* chdir to directory from argument */ - if(S_ISDIR(st.st_mode) && chdir(argv[1])) { + if (S_ISDIR(st.st_mode) && chdir(argv[1])) { perror("ccc"); die("Error from chdir"); } + if (S_ISREG(st.st_mode)) { + to_open_file = true; + } } /* check if it is interactive shell */ @@ -117,7 +121,12 @@ int main(int argc, char** argv) getcwd(cwd, PATH_MAX); p_cwd = memalloc(PATH_MAX * sizeof(char)); start_ccc(); + populate_files(cwd, 0); + if (to_open_file) { + current_selection = arraylist_search(files, argv[1], true); + highlight_current_line(); + } int ch, ch2; while (1) { @@ -735,7 +744,7 @@ void highlight_current_line() char *line = get_line(files, i, file_details); int color = files->items[i].color; /* check is file marked for action */ - bool is_marked = arraylist_includes(marked, files->items[i].path); + bool is_marked = arraylist_search(marked, files->items[i].path, false) != -1; if (is_marked) { /* show file is selected */ wattron(directory_content, COLOR_PAIR(7)); diff --git a/file.c b/file.c index 2c7487a..0727af1 100644 --- a/file.c +++ b/file.c @@ -34,15 +34,21 @@ void arraylist_free(ArrayList *list) list->length = 0; } -bool arraylist_includes(ArrayList *list, char *path) +long arraylist_search(ArrayList *list, char *path, bool bname) { - for (int i = 0; i < list->length; i++) { - if (strcmp(list->items[i].path, path) == 0) { - return true; + for (long i = 0; i < list->length; i++) { + if (!bname && strcmp(list->items[i].path, path) == 0) { + return i; + } + if (bname) { + char *fbname = basename(list->items[i].path); + if (fbname != NULL && strcmp(fbname, path) == 0) { + return i; + } } } - return false; + return -1; } void arraylist_remove(ArrayList *list, long index) diff --git a/file.h b/file.h index 49f72fc..b803d70 100644 --- a/file.h +++ b/file.h @@ -19,7 +19,7 @@ typedef struct ArrayList { ArrayList *arraylist_init(size_t capacity); void arraylist_free(ArrayList *list); -bool arraylist_includes(ArrayList *list, char *path); +long arraylist_search(ArrayList *list, char *path, bool bname); void arraylist_remove(ArrayList *list, long index); void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force); char *get_line(ArrayList *list, long index, bool detail); From 56ac48e5967efb8bc55d715a9b7037366263ee8e Mon Sep 17 00:00:00 2001 From: Piotr Marendowski Date: Sun, 31 Mar 2024 22:44:05 +0200 Subject: [PATCH 11/15] Separate filename and path into two parts, changes all over --- Makefile | 2 +- ccc.c | 84 ++++++++++++++++++++++++++++++++++---------------------- config.h | 2 +- file.c | 50 +++++++++++++++++++++------------ file.h | 5 ++-- 5 files changed, 88 insertions(+), 55 deletions(-) diff --git a/Makefile b/Makefile index ce65e35..74cae7e 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ MANDIR = $(PREFIX)/share/man/man1 # Flags LDFLAGS = $(shell pkg-config --libs ncursesw) -CFLAGS = -O3 -march=native -mtune=native -pipe -s -std=c99 -pedantic -Wall -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 $(shell pkg-config --cflags ncursesw) +CFLAGS = -O3 -march=native -mtune=native -pipe -s -g -std=c99 -pedantic -Wall -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 $(shell pkg-config --cflags ncursesw) SRC = ccc.c util.c file.c icons.c diff --git a/ccc.c b/ccc.c index 8e2c875..c4e1e8f 100644 --- a/ccc.c +++ b/ccc.c @@ -26,7 +26,7 @@ void change_dir(const char *buf, int selection, int ftype); void mkdir_p(const char *destdir); void populate_files(const char *path, int ftype); int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); -void add_file_stat(char *filepath, int ftype); +void add_file_stat(char *filename, char *path, int ftype); char *get_file_mode(mode_t mode); void highlight_current_line(); void show_file_content(); @@ -125,7 +125,6 @@ int main(int argc, char** argv) die("ccc: Terminal size needs to be at least 80x24\n"); } ch = getch(); - /* printf("%d ",ch); */ switch (ch) { /* quit */ case 'q': @@ -281,7 +280,7 @@ int main(int argc, char** argv) /* mark one file */ case SPACE: - add_file_stat(files->items[current_selection].path, 1); + add_file_stat(files->items[current_selection].filename, files->items[current_selection].path, 1); highlight_current_line(); break; @@ -292,39 +291,49 @@ int main(int argc, char** argv) /* mark actions: */ /* delete */ - case 'd':; + case 'd': if (marked->length) { char *trash_dir = check_trash_dir(); if (trash_dir != NULL) { - ; - /* do your magic here */ + int i = 0; + while (i < marked->length) { + printf("%s", marked->items->path); + if (rename(marked->items->path, trash_dir) == 0) { + printf("file deleted"); + } else { + perror("error moving file"); + } + i++; + } + } else { + wpprintw("implement hard delete"); } } break; /* move */ - case 'm':; + case 'm': if (marked->length) { ; } break; /* copy */ - case 'c':; + case 'c': if (marked->length) { ; } break; /* symbolic link */ - case 's':; + case 's': if (marked->length) { ; } break; /* bulk rename */ - case 'b':; + case 'b': if (marked->length) { ; } @@ -370,7 +379,9 @@ void start_ccc() init_windows(); } -/* Checks if trash directory is set and returns it */ +/* + * Checks if the trash directory is set and returns it + */ char *check_trash_dir() { char *path = memalloc(PATH_MAX * sizeof(char)); @@ -401,7 +412,7 @@ char *check_trash_dir() /* if has access to trash_dir */ if (access(path, F_OK) != 0) { - /* create the directory with 755 perm if it doesn't exit */ + /* create the directory with 755 permissions if it doesn't exist */ mkdir_p(path); } } @@ -481,7 +492,6 @@ void mkdir_p(const char *destdir) /* * Read the provided directory and add all files in directory to linked list * ftype: normal files = 0, marked = 1, marking ALL = 2 - * ep->d_name -> filename */ void populate_files(const char *path, int ftype) { @@ -493,22 +503,24 @@ void populate_files(const char *path, int ftype) wclear(directory_content); while ((ep = readdir(dp)) != NULL) { - char *filename = memalloc(PATH_MAX * sizeof(char)); - /* make filename be basename of selected item just to pass check */ + char *path = memalloc(PATH_MAX * sizeof(char)); + char *filename = memalloc(FILENAME_MAX * sizeof(char)); + /* copy filename */ filename[0] = '\0'; strcat(filename, ep->d_name); /* use strncmp to filter out dotfiles */ if ((!show_hidden && strncmp(filename, ".", 1) && strncmp(filename, "..", 2)) || (show_hidden && strcmp(filename, ".") && strcmp(filename, ".."))) { /* construct full file path */ - filename[0] = '\0'; - strcat(filename, cwd); - strcat(filename, "/"); - strcat(filename, ep->d_name); /* add filename */ + path[0] = '\0'; + strcat(path, cwd); + strcat(path, "/"); + strcat(path, filename); /* add filename */ - add_file_stat(filename, ftype); + add_file_stat(path, filename, ftype); } free(filename); + free(path); } closedir(dp); wrefresh(directory_content); @@ -529,13 +541,14 @@ int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, s * Add that file into list * ftype: normal file = 0, normal marked = 1, marked ALL = 2 */ -void add_file_stat(char *filepath, int ftype) +void add_file_stat(char *filename, char *path, int ftype) { struct stat file_stat; - if (stat(filepath, &file_stat) == -1) { + char *filename_and_path = strcat(path, filename); + if (stat(filename_and_path, &file_stat) == -1) { /* can't be triggered? */ if (errno == EACCES) - arraylist_add(files, filepath, NULL, NULL, NULL, 8, false, false); + arraylist_add(files, filename, path, NULL, NULL, NULL, 8, false, false); } /* get file type and color, 4 chars for the type and icon */ @@ -545,9 +558,9 @@ void add_file_stat(char *filepath, int ftype) char *type = memalloc(type_size); wchar_t *icon_str = memalloc(icon_size); - filepath[strlen(filepath)] = '\0'; + filename[strlen(filename)] = '\0'; /* find last / in path by finding basename */ - char *f_bname = strrchr(filepath, '/'); + char *f_bname = filename; char *ext = NULL; if (f_bname != NULL) { /* shift 1 to get basename */ @@ -560,6 +573,7 @@ void add_file_stat(char *filepath, int ftype) ext = f_bname; } } + /* add file extension */ if (ext != NULL) { icon *ext_icon = hashtable_search(ext); if (ext_icon == NULL) @@ -575,6 +589,7 @@ void add_file_stat(char *filepath, int ftype) if (S_ISDIR(file_stat.st_mode)) { strncpy(type, "DIR", 4); /* directory type */ color = 5; /* blue color */ + wcsncpy(icon_str, L"󰉋", 2); } else if (S_ISREG(file_stat.st_mode)) { strncpy(type, "REG", 4); /* regular file */ color = 8; /* white color */ @@ -601,7 +616,7 @@ void add_file_stat(char *filepath, int ftype) if (ftype == 1 || ftype == 2) { /* force if user is marking all files */ bool force = ftype == 2 ? true : false; - arraylist_add(marked, filepath, NULL, type, icon_str, 8, true, force); + arraylist_add(marked, filename, path, NULL, type, icon_str, 8, true, force); /* free type and return without allocating more stuff */ free(type); return; @@ -621,11 +636,12 @@ void add_file_stat(char *filepath, int ftype) if (S_ISDIR(file_stat.st_mode)) { /* at most 15 fd opened */ total_dir_size = 0; - nftw(filepath, &get_directory_size, 15, FTW_PHYS); + nftw(filename_and_path, &get_directory_size, 15, FTW_PHYS); bytes = total_dir_size; } } - /* 4 before decimal + 1 dot + DECIMAL_PLACES (after decimal) + unit length(1 for K, 3 for KiB, taking units[1] as B never changes)+ 1 space + 1 null */ + /* 4 before decimal + 1 dot + DECIMAL_PLACES (after decimal) + + unit length (1 for K, 3 for KiB, taking units[1] as B never changes) + 1 space + 1 null */ int size_size = 4 + 1 + DECIMAL_PLACES + strlen(units[1]) + 1 + 1; char *size = memalloc(size_size * sizeof(char)); int unit = 0; @@ -647,7 +663,7 @@ void add_file_stat(char *filepath, int ftype) char *total_stat = memalloc(stat_size); snprintf(total_stat, stat_size, "%s %s %-*s", mode_str, time, size_size, size); - arraylist_add(files, filepath, total_stat, type, icon_str, color, false, false); + arraylist_add(files, filename, path, total_stat, type, icon_str, color, false, false); free(time); free(size); @@ -734,7 +750,7 @@ void highlight_current_line() char *line = get_line(files, i, file_details); int color = files->items[i].color; /* check is file marked for action */ - bool is_marked = arraylist_includes(marked, files->items[i].path); + bool is_marked = arraylist_includes(marked, files->items[i].filename, files->items[i].path); if (is_marked) { /* show file is selected */ wattron(directory_content, COLOR_PAIR(7)); @@ -776,15 +792,17 @@ void highlight_current_line() */ void show_file_content() { - wclear(preview_content); file current_file = files->items[current_selection]; + char *filename_and_path = strcat(current_file.path, current_file.filename); if (strncmp(current_file.type, "DIR", 3) == 0) return; - FILE *file = fopen(current_file.path, "r"); + wclear(preview_content); + + FILE *file = fopen(filename_and_path, "r"); if (file == NULL) { - mvwprintw(preview_content, 0, 0, "Unable to read %s", current_file.path); + mvwprintw(preview_content, 0, 0, "Unable to read %s", filename_and_path); return; } diff --git a/config.h b/config.h index 949b0b7..1c45bb7 100644 --- a/config.h +++ b/config.h @@ -5,7 +5,7 @@ #define DECIMAL_PLACES 1 /* how many decimal places show size with */ /* Size units */ -const char* units[] = {"B", "K", "M", "G", "T", "P"}; +static const char* units[] = {"B", "K", "M", "G", "T", "P"}; /* Set width offset for windows: +-------------%-------------+ diff --git a/file.c b/file.c index 2c7487a..f497af1 100644 --- a/file.c +++ b/file.c @@ -20,10 +20,12 @@ ArrayList *arraylist_init(size_t capacity) void arraylist_free(ArrayList *list) { for (size_t i = 0; i < list->length; i++) { - if (list->items[i].type != NULL) - free(list->items[i].type); + if (list->items[i].path != NULL) + free(list->items[i].filename); if (list->items[i].path != NULL) free(list->items[i].path); + if (list->items[i].type != NULL) + free(list->items[i].type); if (list->items[i].stats != NULL) free(list->items[i].stats); if (list->items[i].icon != NULL) @@ -34,10 +36,15 @@ void arraylist_free(ArrayList *list) list->length = 0; } -bool arraylist_includes(ArrayList *list, char *path) +/* + * Check if the file is in the arraylist + */ +bool arraylist_includes(ArrayList *list, char* filename, char *path) { + char *current_whole_path = strcat(path, filename); for (int i = 0; i < list->length; i++) { - if (strcmp(list->items[i].path, path) == 0) { + char *list_whole_path = strcat(list->items[i].path, list->items[i].filename); + if (strcmp(list_whole_path, current_whole_path) == 0) { return true; } } @@ -50,6 +57,7 @@ void arraylist_remove(ArrayList *list, long index) if (index >= list->length) return; + free(list->items[index].filename); free(list->items[index].path); free(list->items[index].stats); free(list->items[index].type); @@ -64,41 +72,49 @@ void arraylist_remove(ArrayList *list, long index) /* * Force will not remove duplicate marked files, instead it just skip adding */ -void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force) +void arraylist_add(ArrayList *list, char *filename, char *path, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force) { - char *filepath_cp = NULL; + char *filename_cp = NULL; + char *path_cp = NULL; char *stats_cp = NULL; char *type_cp = NULL; wchar_t *icon_cp = NULL; - if (filepath != NULL) { - filepath_cp = strdup(filepath); - if (filepath_cp == NULL) - perror("ccc"); + if (filename_cp != NULL) { + filename_cp = strdup(filename_cp); + if (filename_cp == NULL) + perror("can't add filename to arraylist"); + } + if (path_cp != NULL) { + path_cp = strdup(path_cp); + if (path_cp == NULL) + perror("can't add path to arraylist"); } if (stats != NULL) { stats_cp = strdup(stats); if (stats_cp == NULL) - perror("ccc"); + perror("can't add stats to arraylist"); } if (type != NULL) { type_cp = strdup(type); if (type_cp == NULL) - perror("ccc"); + perror("can't add type to arraylist"); } if (icon != NULL) { icon_cp = wcsdup(icon); if (icon_cp == NULL) - perror("ccc"); + perror("can't add icon to arraylist"); } - /* path, stats, type, icon, color */ - file new_file = { filepath_cp, stats_cp, type_cp, icon_cp, color }; + /* filename, path, stats, type, icon, color */ + file new_file = { filename_cp, path_cp, stats_cp, type_cp, icon_cp, color }; if (list->capacity != list->length) { if (marked) { for (int i = 0; i < list->length; i++) { - if (strcmp(list->items[i].path, new_file.path) == 0) { + char *list_whole_path = strcat(list->items[i].path, list->items[i].filename); + char *current_whole_path = strcat(new_file.path, new_file.filename); + if (strcmp(list_whole_path, current_whole_path) == 0) { if (!force) arraylist_remove(list, i); return; @@ -147,9 +163,7 @@ char *get_line(ArrayList *list, long index, bool detail) length = strlen(name) + 6; /* 4 for icon, 1 for space and 1 for null */ } char *line = memalloc(length * sizeof(char)); - - if (detail) { snprintf(line, length, "%s %ls %s", stats, icon, name); } else { diff --git a/file.h b/file.h index 49f72fc..4ec33dd 100644 --- a/file.h +++ b/file.h @@ -5,6 +5,7 @@ typedef struct file { char *path; + char *filename; char *stats; char *type; wchar_t *icon; @@ -19,9 +20,9 @@ typedef struct ArrayList { ArrayList *arraylist_init(size_t capacity); void arraylist_free(ArrayList *list); -bool arraylist_includes(ArrayList *list, char *path); +bool arraylist_includes(ArrayList *list, char* filename, char *path); void arraylist_remove(ArrayList *list, long index); -void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force); +void arraylist_add(ArrayList *list, char *filename, char *path, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force); char *get_line(ArrayList *list, long index, bool detail); #endif From 4fdeb8c56b89ab2bae7ecd2479375261807c4861 Mon Sep 17 00:00:00 2001 From: night0721 Date: Mon, 1 Apr 2024 21:23:10 +0000 Subject: [PATCH 12/15] add common alloc functions and handle cli argument --- ccc.c | 22 ++++++++++++++-------- file.c | 45 +++++++++++++-------------------------------- util.c | 25 +++++++++++++++++++++++-- util.h | 2 ++ 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/ccc.c b/ccc.c index 4c711b8..28171ef 100644 --- a/ccc.c +++ b/ccc.c @@ -44,6 +44,7 @@ bool to_open_file = false; bool dirs_size = DIRS_SIZE; bool show_hidden = SHOW_HIDDEN; bool file_details = SHOW_DETAILS; +char *argv_cp; char *trash_dir; char *cwd; char *p_cwd; /* previous cwd */ @@ -73,9 +74,14 @@ int main(int argc, char** argv) if (S_ISDIR(st.st_mode) && chdir(argv[1])) { perror("ccc"); die("Error from chdir"); - } - if (S_ISREG(st.st_mode)) { -// char *rm_f_name = strrchr(argv[1], '/'); + } else if (S_ISREG(st.st_mode)) { + argv_cp = estrdup(argv[1]); + char *last_slash = strrchr(argv_cp, '/'); + *last_slash = '\0'; + if (chdir(argv[1])) { + perror("ccc"); + die("Error from chdir"); + } to_open_file = true; } } @@ -125,7 +131,7 @@ int main(int argc, char** argv) populate_files(cwd, 0); if (to_open_file) { - current_selection = arraylist_search(files, argv[1], true); + current_selection = arraylist_search(files, argv_cp, true); highlight_current_line(); } @@ -439,10 +445,7 @@ void change_dir(const char *buf, int selection, int ftype) { char *buf_dup; if (buf == p_cwd) { - buf_dup = strdup(p_cwd); - if (buf_dup == NULL) { - return; - } + buf_dup = estrdup(p_cwd); } else { buf_dup = (char *) buf; } @@ -656,6 +659,9 @@ void add_file_stat(char *filename, char *path, int ftype) } /* get file mode string */ char *mode_str = get_file_mode(file_stat.st_mode); + if (mode_str[0] == '-' && (mode_str[3] == 'x' || mode_str[6] == 'x' || mode_str[9] == 'x')) { + + } /* mode_str(11) + time(17) + size_size + 2 spaces + 1 null */ size_t stat_size = 11 * sizeof(char) + time_size + size_size + 3 * sizeof(char); diff --git a/file.c b/file.c index ae0f023..bc31852 100644 --- a/file.c +++ b/file.c @@ -83,31 +83,16 @@ void arraylist_add(ArrayList *list, char *name, char *path, char *stats, char *t char *stats_cp = NULL; wchar_t *icon_cp = NULL; - if (name != NULL) { - name_cp = strdup(name); - if (name_cp == NULL) - perror("can't add name to arraylist"); - } - if (path != NULL) { - path_cp = strdup(path); - if (path_cp == NULL) - perror("can't add path to arraylist"); - } - if (type != NULL) { - type_cp = strdup(type); - if (type_cp == NULL) - perror("can't add type to arraylist"); - } - if (stats != NULL) { - stats_cp = strdup(stats); - if (stats_cp == NULL) - perror("can't add stats to arraylist"); - } - if (icon != NULL) { - icon_cp = wcsdup(icon); - if (icon_cp == NULL) - perror("can't add icon to arraylist"); - } + if (name != NULL) + name_cp = estrdup(name); + if (path != NULL) + path_cp = estrdup(path); + if (type != NULL) + type_cp = estrdup(type); + if (stats != NULL) + stats_cp = estrdup(stats); + if (icon != NULL) + icon_cp = ewcsdup(icon); /* name, path, stats, type, icon, color */ file new_file = { name_cp, path_cp, type_cp, stats_cp, icon_cp, color }; @@ -145,18 +130,14 @@ void arraylist_add(ArrayList *list, char *name, char *path, char *stats, char *t char *get_line(ArrayList *list, long index, bool detail) { file file = list->items[index]; - char *name = strdup(file.name); - wchar_t *icon = wcsdup(file.icon); - if (name == NULL || icon == NULL) - perror("ccc"); + char *name = estrdup(file.name); + wchar_t *icon = ewcsdup(file.icon); size_t name_len = strlen(name); char *stats = NULL; size_t length; if (detail) { - stats = strdup(file.stats); - if (stats == NULL) - perror("ccc"); + stats = estrdup(file.stats); length = name_len + strlen(stats) + 7; /* 4 for icon, 2 for space and 1 for null */ } else { length = name_len + 6; /* 4 for icon, 1 for space and 1 for null */ diff --git a/util.c b/util.c index 9315542..e2a030a 100644 --- a/util.c +++ b/util.c @@ -1,5 +1,7 @@ #include #include +#include +#include void die(char *reason) { @@ -11,18 +13,37 @@ void *memalloc(size_t size) { void *ptr = malloc(size); if (!ptr) { - fprintf(stderr, "ccc: Error allocating memory\n"); + perror("ccc"); exit(EXIT_FAILURE); } return ptr; } +void *estrdup(void *ptr) +{ + void *duped = strdup(ptr); + if (!duped) { + perror("ccc"); + exit(EXIT_FAILURE); + } + return duped; +} + +void *ewcsdup(void *ptr) +{ + void *duped = wcsdup(ptr); + if (!duped) { + perror("ccc"); + exit(EXIT_FAILURE); + } + return duped; +} + void *rememalloc(void *ptr, size_t size) { ptr = realloc(ptr, size); if (!ptr) { perror("ccc"); - fprintf(stderr, "ccc: Error allocating memory\n"); exit(EXIT_FAILURE); } return ptr; diff --git a/util.h b/util.h index e9aab90..9608b5d 100644 --- a/util.h +++ b/util.h @@ -5,6 +5,8 @@ void die(char *reason); void *memalloc(size_t size); +void *estrdup(void *ptr); +void *ewcsdup(void *ptr); void *rememalloc(void *ptr, size_t size); #endif From 60d9928459810fcc45626a3afedf2183db95d82c Mon Sep 17 00:00:00 2001 From: night0721 Date: Tue, 2 Apr 2024 00:18:34 +0000 Subject: [PATCH 13/15] toggle file icons --- ccc.c | 9 ++++++++- file.c | 18 +++++++++++++----- file.h | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ccc.c b/ccc.c index 28171ef..0550362 100644 --- a/ccc.c +++ b/ccc.c @@ -44,6 +44,7 @@ bool to_open_file = false; bool dirs_size = DIRS_SIZE; bool show_hidden = SHOW_HIDDEN; bool file_details = SHOW_DETAILS; +bool show_icons = SHOW_ICONS; char *argv_cp; char *trash_dir; char *cwd; @@ -291,6 +292,11 @@ int main(int argc, char** argv) change_dir(cwd, 0, 0); break; + case 'w': + show_icons = !show_icons; + change_dir(cwd, 0, 0); + break; + case 'X': toggle_executable(); break; @@ -376,6 +382,7 @@ int main(int argc, char** argv) break; } } + free(argv_cp); arraylist_free(files); arraylist_free(marked); endwin(); @@ -752,7 +759,7 @@ void highlight_current_line() } } /* print the actual filename and stats */ - char *line = get_line(files, i, file_details); + char *line = get_line(files, i, file_details, show_icons); int color = files->items[i].color; /* check is file marked for action */ bool is_marked = arraylist_search(marked, files->items[i].path, false) != -1; diff --git a/file.c b/file.c index bc31852..2039d82 100644 --- a/file.c +++ b/file.c @@ -127,7 +127,7 @@ void arraylist_add(ArrayList *list, char *name, char *path, char *stats, char *t /* * Construct a formatted line for display */ -char *get_line(ArrayList *list, long index, bool detail) +char *get_line(ArrayList *list, long index, bool detail, bool icons) { file file = list->items[index]; char *name = estrdup(file.name); @@ -144,11 +144,19 @@ char *get_line(ArrayList *list, long index, bool detail) } char *line = memalloc(length * sizeof(char)); + line[0] = '\0'; if (detail) { - snprintf(line, length, "%s %ls %s", stats, icon, name); - } else { - snprintf(line, length, "%ls %s", icon, name); + strcat(line, stats); + strcat(line, " "); } - + if (icons) { + char *tmp = memalloc(8 * sizeof(char)); + snprintf(tmp, 8, "%ls", icon); + strcat(line, tmp); + strcat(line, " "); + free(tmp); + } + strcat(line, name); + return line; } diff --git a/file.h b/file.h index 5ab34b0..b90a925 100644 --- a/file.h +++ b/file.h @@ -23,6 +23,6 @@ void arraylist_free(ArrayList *list); long arraylist_search(ArrayList *list, char *filepath, bool bname); void arraylist_remove(ArrayList *list, long index); void arraylist_add(ArrayList *list, char *filename, char *path, char *stats, char *type, wchar_t *icon, int color, bool marked, bool force); -char *get_line(ArrayList *list, long index, bool detail); +char *get_line(ArrayList *list, long index, bool detail, bool icons); #endif From a1bc4b80a77e058cb14afbd53563e8ad7ad8e77f Mon Sep 17 00:00:00 2001 From: night0721 Date: Tue, 2 Apr 2024 00:26:52 +0000 Subject: [PATCH 14/15] fix mark all resulting empty directory --- ccc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ccc.c b/ccc.c index 0550362..ca8ab0e 100644 --- a/ccc.c +++ b/ccc.c @@ -457,8 +457,10 @@ void change_dir(const char *buf, int selection, int ftype) buf_dup = (char *) buf; } strcpy(cwd, buf_dup); - arraylist_free(files); - files = arraylist_init(100); + if (ftype != 2) { + arraylist_free(files); + files = arraylist_init(100); + } current_selection = selection; populate_files(cwd, ftype); } From 0c9429ca5336a32be0e59c3d597f3ecc25ed2a9d Mon Sep 17 00:00:00 2001 From: night0721 Date: Tue, 2 Apr 2024 01:30:28 +0000 Subject: [PATCH 15/15] f to create file and d to delete file --- ccc.c | 65 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/ccc.c b/ccc.c index ca8ab0e..325eb5a 100644 --- a/ccc.c +++ b/ccc.c @@ -33,6 +33,8 @@ void show_file_content(); void edit_file(); void toggle_executable(); int write_last_d(); +void create_file(); +void delete_files(); void wpprintw(const char *fmt, ...); void init_windows(); void draw_border_title(WINDOW *window, bool active); @@ -46,10 +48,8 @@ bool show_hidden = SHOW_HIDDEN; bool file_details = SHOW_DETAILS; bool show_icons = SHOW_ICONS; char *argv_cp; -char *trash_dir; char *cwd; char *p_cwd; /* previous cwd */ -char *trash_dir; int half_width; ArrayList *files; ArrayList *marked; @@ -297,6 +297,10 @@ int main(int argc, char** argv) change_dir(cwd, 0, 0); break; + case 'f': + create_file(); + break; + case 'X': toggle_executable(); break; @@ -315,25 +319,7 @@ int main(int argc, char** argv) /* mark actions: */ /* delete */ case 'd': - if (marked->length) { - char *trash_dir = check_trash_dir(); - if (trash_dir != NULL) { - // int i = 0; - /* - while (i < marked->length) { - printf("deleted %s ", marked->items->path); - if (rename(marked->items->path, trash_dir) == 0) { - printf("file deleted"); - } else { - perror("error moving file"); - } - i++; - } - */ - } else { - wpprintw("implement hard delete"); - } - } + delete_files(); break; /* move */ @@ -412,6 +398,7 @@ char *check_trash_dir() { char *path = memalloc(PATH_MAX * sizeof(char)); + char *trash_dir; #ifdef TRASH_DIR trash_dir = TRASH_DIR; #endif @@ -927,6 +914,42 @@ int write_last_d() return 0; } +void create_file() +{ + echo(); + wpprintw("New file: "); + char input[PATH_MAX]; + /* get string at y=0, x=10 */ + mvwgetstr(panel, 0, 10, input); + FILE *f = fopen(input, "w+"); + fclose(f); + wpprintw("Created %s", input); + change_dir(cwd, 0, 0); + noecho(); +} + +void delete_files() +{ + if (marked->length) { + char *trash_dir = check_trash_dir(); + if (trash_dir != NULL) { + for (int i = 0; i < marked->length; i++) { + char *new_path = memalloc(PATH_MAX * sizeof(char)); + strcpy(new_path, trash_dir); + strcat(new_path, "/"); + strcat(new_path, marked->items[i].name); + if (rename(marked->items[i].path, new_path)) { + wpprintw("delete failed: %s\n", strerror(errno)); + } else { + change_dir(cwd, 0, 0); + } + } + } else { + wpprintw("TODO: implement hard delete"); + } + } +} + /* * Print line to the panel */