diff --git a/Makefile b/Makefile index cb042f2..809ef7f 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,30 @@ .POSIX: .SUFFIXES: +CC = cc +VERSION = 1.0 TARGET = ccc MANPAGE = ccc.1 -SRC = ccc.c util.c file.c config.h +CONF = config.h +PREFIX ?= /usr/local +BINDIR = $(PREFIX)/bin +MANDIR = $(PREFIX)/share/man/man1 # Flags LDFLAGS = $(shell pkg-config --libs ncurses) CFLAGS = -march=native -mtune=native -O3 -pipe -s -std=c99 -pedantic $(shell pkg-config --cflags ncurses) -Wall # -Wextra -Werror -CC=cc -PREFIX ?= /usr/local -CONF = config.h -BINDIR = $(PREFIX)/bin -MANDIR = $(PREFIX)/share/man/man1 - -.PHONY: all install uninstall clean +SRC = ccc.c util.c file.c $(CONF) $(TARGET): $(SRC) $(CC) $(CFLAGS) $(LDFLAGS) $(SRC) -o $@ -all: $(TARGET) +dist: + mkdir -p $(TARGET)-$(VERSION) + cp -R README.md $(MANPAGE) $(TARGET) $(TARGET)-$(VERSION) + tar -cf $(TARGET)-$(VERSION).tar $(TARGET)-$(VERSION) + gzip $(TARGET)-$(VERSION).tar + rm -rf $(TARGET)-$(VERSION) install: $(TARGET) mkdir -p $(DESTDIR)$(BINDIR) @@ -36,3 +40,7 @@ uninstall: clean: $(RM) $(TARGET) + +all: $(TARGET) + +.PHONY: all dist install uninstall clean diff --git a/ccc.c b/ccc.c index 417724b..c70da4f 100644 --- a/ccc.c +++ b/ccc.c @@ -39,6 +39,7 @@ void draw_border_title(WINDOW *window, bool active); /* global variables */ unsigned int focus = 0; long current_selection = 0; +bool dir_mode = BLOCK_SIZE; char *cwd; int half_width; WIN_STRUCT windows[5]; @@ -84,7 +85,7 @@ int main(int argc, char** argv) init_pair(4, COLOR_YELLOW, -1); /* BLK */ init_pair(5, COLOR_BLUE, -1); /* DIR */ init_pair(6, COLOR_MAGENTA, -1); /* */ - init_pair(7, COLOR_CYAN, -1); /* */ + init_pair(7, COLOR_CYAN, -1); /* MARKED FILES */ init_pair(8, COLOR_WHITE, -1); /* REG */ half_width = COLS / 2; @@ -238,8 +239,16 @@ int main(int argc, char** argv) } break; + /* a to toggle between DISK_USAGE and BLOCK SIZE */ + case 'a': + dir_mode = !dir_mode; + clear_files(); + populate_files(cwd); + highlight_current_line(); + break; + /* mark files by space */ - case SPACE: + case SPACE:; add_file_stat(get_filepath(current_selection), 1); highlight_current_line(); break; @@ -392,11 +401,15 @@ long add_file_stat(char *filepath, int ftype) /* get file size */ double bytes = file_stat.st_size; - if (S_ISDIR(file_stat.st_mode)) { - /* at most 15 fd opened */ - total_dir_size = 0; - nftw(filepath, &get_directory_size, 15, FTW_PHYS); - bytes = total_dir_size; + + if (!dir_mode) { + /* dir_mode is 0, so disk usage mode, calculate disk usage */ + if (S_ISDIR(file_stat.st_mode)) { + /* at most 15 fd opened */ + total_dir_size = 0; + nftw(filepath, &get_directory_size, 15, FTW_PHYS); + bytes = total_dir_size; + } } /* max 25 chars due to long, space, suffix and null */ char *size = memalloc(25 * sizeof(char)); @@ -443,7 +456,14 @@ long add_file_stat(char *filepath, int ftype) free(type); free(size); free(time); - return index; + if (index != -1) { + /* just marked */ + return index; + } + /* already marked */ + return -1; + /* -1 does nothing, just function required to return something */ + } char *total_stat = memalloc(45 * sizeof(char)); snprintf(total_stat, 45, "%-18s %-10s", time, size); @@ -495,6 +515,15 @@ void highlight_current_line() /* update the panel */ wclear(panel); + + /* showing dir_mode requires 26 characters */ + char *dir_mode_line = memalloc(27 * sizeof(char)); + if (dir_mode) + strncpy(dir_mode_line, "Directory Mode: Block Size", 27); + else + strncpy(dir_mode_line, "Directory Mode: Disk Usage", 27); + + /* check for marked files */ long num_marked = marked_len(); if (num_marked > 0) { /* Determine length of formatted string */ @@ -502,24 +531,36 @@ void highlight_current_line() char *selected = memalloc((m_len + 1) * sizeof(char)); snprintf(selected, m_len + 1, "(%ld selected)", num_marked); - wprintw(panel, "(%ld/%ld) %s %s", current_selection + 1, files_len(), selected, cwd); + wprintw(panel, "(%ld/%ld) %s %s %s", current_selection + 1, files_len(), selected, cwd, dir_mode_line); } else { - wprintw(panel, "(%ld/%ld) %s", current_selection + 1, files_len(), cwd); + wprintw(panel, "(%ld/%ld) %s %s", current_selection + 1, files_len(), cwd, dir_mode_line); } } /* print the actual filename and stats */ char *line = get_line(i); int color = get_color(i); - - /* print the whole directory with colors */ - wattron(directory_content, COLOR_PAIR(color)); + /* check is file marked for action */ + bool marked = in_marked(get_filepath(i)); + if (marked) { + /* show file is selected */ + wattron(directory_content, COLOR_PAIR(7)); + } else { + /* print the whole directory with default colors */ + wattron(directory_content, COLOR_PAIR(color)); + } + if (overflow > 0) mvwprintw(directory_content, line_count, 0, "%s", line); else mvwprintw(directory_content, i, 0, "%s", line); + if (marked) { + wattroff(directory_content, COLOR_PAIR(7)); + } else { + wattroff(directory_content, COLOR_PAIR(color)); + } + wattroff(directory_content, A_REVERSE); - wattroff(directory_content, COLOR_PAIR(color)); free(line); line_count++; } @@ -539,23 +580,36 @@ void show_file_content() wclear(preview_content); file *current_file = get_file((long) current_selection); if (strncmp(current_file->type, "DIR", 3) == 0) return; - FILE *file = fopen(current_file->path, "rb"); - if (file) { - draw_border_title(preview_border, true); - fseek(file, 0, SEEK_END); - long length = ftell(file); - /* check if file isn't empty */ - if (length != 0 && length < 4096) { - fseek(file, 0, SEEK_SET); /* set cursor back to start of file */ - char *buffer = memalloc(length * sizeof(char)); - fread(buffer, 1, length, file); - mvwprintw(preview_content, 0, 0, "%s", buffer); - free(buffer); - } else { - wclear(preview_content); - } - fclose(file); + FILE *file = fopen(current_file->path, "r"); + if (file == NULL) { + mvwprintw(preview_content, 0, 0, "Unable to read %s", current_file->path); + return; } + draw_border_title(preview_border, true); + + int c; + /* check binary */ + while ((c=fgetc(file)) != EOF) { + if (c == '\0') { + mvwprintw(preview_content, 0, 0, "binary"); + return; + } + } + + fseek(file, 0, SEEK_END); + long length = ftell(file); + /* check if file isn't empty */ + if (length != 0) { + fseek(file, 0, SEEK_SET); /* set cursor back to start of file */ + int max_length = (LINES - 3) * (COLS / 2 - 2); + char *buffer = memalloc(max_length * sizeof(char)); + fread(buffer, 1, max_length, file); + mvwprintw(preview_content, 0, 0, "%s", buffer); + free(buffer); + } else { + wclear(preview_content); + } + fclose(file); } /* @@ -611,7 +665,7 @@ void init_windows() /* draw border around windows */ draw_border_title(directory_border, true); - draw_border_title(preview_border, false); + draw_border_title(preview_border, true); scrollok(directory_content, true); /* window location y, x */ diff --git a/config.h b/config.h index 404c50e..325b31d 100644 --- a/config.h +++ b/config.h @@ -1,7 +1,7 @@ #define CTRLD 0x04 -#define ENTER 0xA +#define ENTER 0xA #define CTRLU 0x15 -#define ESC 0x1B /* \e or \033 */ +#define ESC 0x1B #define SPACE 0x20 #define TILDE 0x7E #define DOWN 0x102 @@ -11,3 +11,7 @@ #define BACKSPACE 0x107 #define PH 1 /* panel height */ #define JUMP_NUM 14 /* how long ctrl + u/d jump are */ +#define BLOCK_SIZE true +#define DISK_USAGE false + +static const char *editor = "nvim"; /* default text editor */ diff --git a/file.c b/file.c index e51d204..cfb4976 100644 --- a/file.c +++ b/file.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "util.h" @@ -45,13 +46,24 @@ long marked_len() } +void free_file(file *toremove) +{ + if (toremove->type != NULL) + free(toremove->type); + if (toremove->path != NULL) + free(toremove->path); + if (toremove->stats != NULL) + free(toremove->stats); + free(toremove); +} + void clear_files() { file *tmp; while (files != NULL) { tmp = files; files = files->next; - free(tmp); + free_file(tmp); } } @@ -61,7 +73,7 @@ void clear_marked() while (marked != NULL) { tmp = marked; files = marked->next; - free(tmp); + free_file(tmp); } } @@ -96,6 +108,29 @@ long add_file(char *filepath, char *stats, char *type, int color) return index; } +void remove_marked(file *marked_file) +{ + /* If the head node itself is marked for removal */ + if (marked == marked_file) { + marked = marked->next; + free_file(marked_file); + return; + } + + + /* Search for the marked file node in the list */ + file* temp = marked; + while (temp != NULL && temp->next != marked_file) { + temp = temp->next; + } + + /* If the marked file node is found, remove it from the list */ + if (temp != NULL) { + temp->next = marked_file->next; + free_file(marked_file); + } +} + long add_marked(char *filepath, char *type) { file *current = marked; @@ -107,20 +142,63 @@ long add_marked(char *filepath, char *type) } new_file->path = buf; new_file->type = buf2; + new_file->stats = NULL; + new_file->color = 0; new_file->next = NULL; if (current == NULL) { marked = new_file; return 0; } + long index = 1; while (current->next != NULL) { + if (strcmp(current->path, new_file->path) == 0) { + remove_marked(current); + free_file(new_file); + return -1; + } current = current->next; index++; } + if (strcmp(current->path, new_file->path) == 0){ + remove_marked(current); + free_file(new_file); + return -1; + } current->next = new_file; return index; } +file *get_marked(long index) +{ + file *current = marked; + if (index == 0) { + return current; + } + if (index > files_len()) { + return NULL; + } + for (long i = 0; i < index; i++) { + current = current->next; + } + return current; +} + +bool in_marked(char *path) +{ + file *tmp = marked; + if (tmp == NULL) + return false; + + while (tmp != NULL) { + if (strcmp(path, tmp->path) == 0) { + return true; + } + tmp = tmp->next; + } + return false; +} + file *get_file(long index) { file *current = files; @@ -160,7 +238,7 @@ int get_color(long index) } return color; } else { - return 8; /* white */ + return 8; /* white */ } } diff --git a/file.h b/file.h index d881227..b2890cb 100644 --- a/file.h +++ b/file.h @@ -11,10 +11,14 @@ typedef struct file { long files_len(); long marked_len(); +void free_file(file *toremove); void clear_files(); void clear_marked(); long add_file(char *filepath, char *stats, char *type, int color); +void remove_marked(file *marked_file); long add_marked(char *filepath, char *type); +file *get_marked(long index); +bool in_marked(char *path); file *get_file(long index); char *get_filepath(long index); int get_color(long index);