commit
1b202d5df1
6 changed files with 233 additions and 311 deletions
2
Makefile
2
Makefile
|
@ -12,7 +12,7 @@ MANDIR = $(PREFIX)/share/man/man1
|
|||
|
||||
# Flags
|
||||
LDFLAGS = $(shell pkg-config --libs ncurses)
|
||||
CFLAGS = -O3 -pipe -s -std=c99 -pedantic -Wall $(shell pkg-config --cflags ncurses)
|
||||
CFLAGS = -O3 -march=native -mtune=native -pipe -s -std=c99 -pedantic -Wall $(shell pkg-config --cflags ncurses)
|
||||
|
||||
SRC = ccc.c util.c file.c
|
||||
|
||||
|
|
19
README.md
19
README.md
|
@ -49,30 +49,37 @@ $ sudo make install
|
|||
## Usage
|
||||
|
||||
```
|
||||
h: go to parent dir
|
||||
j: scroll down
|
||||
k: scroll up
|
||||
h: go to parent dir
|
||||
l: go to child dir
|
||||
|
||||
left: go to parent dir
|
||||
down: scroll down
|
||||
up: scroll up
|
||||
left: go to parent dir
|
||||
right: go to child dir
|
||||
|
||||
enter: go to child dir/open file
|
||||
backspace: go to parent dir
|
||||
|
||||
g: go to top
|
||||
gg: go to top
|
||||
G: go to bottom
|
||||
|
||||
t: go to trash
|
||||
~: go to home
|
||||
ctrl+u: jump up
|
||||
ctrl+d: jump down
|
||||
|
||||
t: go to trash dir
|
||||
~: go to home dir
|
||||
-: go to previous dir
|
||||
z: refresh current dir
|
||||
|
||||
A: show directory disk usage/block size
|
||||
space: mark file
|
||||
a: mark all files in directory
|
||||
|
||||
q: exit
|
||||
?: show help
|
||||
q: exit with last dir written to file
|
||||
ctrl+c exit without writing last dir
|
||||
```
|
||||
|
||||
## License
|
||||
|
|
170
ccc.c
170
ccc.c
|
@ -16,11 +16,13 @@
|
|||
#include "config.h"
|
||||
|
||||
/* functions' definitions */
|
||||
void show_help();
|
||||
void start_ccc();
|
||||
void change_dir(const char *buf, int selection);
|
||||
int 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);
|
||||
long add_file_stat(char *filepath, int ftype);
|
||||
void add_file_stat(char *filepath, int ftype);
|
||||
void highlight_current_line();
|
||||
void show_file_content();
|
||||
void edit_file();
|
||||
|
@ -33,8 +35,13 @@ void draw_border_title(WINDOW *window, bool active);
|
|||
unsigned int focus = 0;
|
||||
long current_selection = 0;
|
||||
bool dirs_size = DIRS_SIZE;
|
||||
bool show_hidden = SHOW_HIDDEN;
|
||||
bool file_details = SHOW_DETAILS;
|
||||
char *cwd;
|
||||
char *p_cwd; /* previous cwd */
|
||||
int half_width;
|
||||
ArrayList *files;
|
||||
ArrayList *marked;
|
||||
WINDOW *directory_border;
|
||||
WINDOW *directory_content;
|
||||
WINDOW *preview_border;
|
||||
|
@ -80,15 +87,14 @@ int main(int argc, char** argv)
|
|||
init_pair(7, COLOR_CYAN, -1); /* MARKED FILES */
|
||||
init_pair(8, COLOR_WHITE, -1); /* REG */
|
||||
|
||||
half_width = COLS / 2;
|
||||
init_windows();
|
||||
refresh();
|
||||
/* init files and marked arrays */
|
||||
files = arraylist_init(100);
|
||||
marked = arraylist_init(100);
|
||||
|
||||
cwd = memalloc(PATH_MAX * sizeof(char));
|
||||
p_cwd = memalloc(PATH_MAX * sizeof(char));
|
||||
getcwd(cwd, PATH_MAX);
|
||||
|
||||
populate_files(cwd, 0);
|
||||
highlight_current_line();
|
||||
start_ccc();
|
||||
|
||||
int ch, ch2;
|
||||
while (1) {
|
||||
|
@ -118,6 +124,7 @@ int main(int argc, char** argv)
|
|||
case LEFT:
|
||||
case 'h':;
|
||||
/* get parent directory */
|
||||
strcpy(p_cwd, cwd);
|
||||
char *last_slash = strrchr(cwd, '/');
|
||||
if (last_slash != NULL) {
|
||||
*last_slash = '\0';
|
||||
|
@ -129,16 +136,15 @@ int main(int argc, char** argv)
|
|||
case ENTER:
|
||||
case RIGHT:
|
||||
case 'l':;
|
||||
file *file = get_file(current_selection);
|
||||
if (file != NULL) {
|
||||
strcpy(p_cwd, cwd);
|
||||
file c_file = files->items[current_selection];
|
||||
/* check if it is directory or a regular file */
|
||||
if (strncmp(file->type, "DIR", 3) == 0) {
|
||||
if (strncmp(c_file.type, "DIR", 3) == 0) {
|
||||
/* change cwd to directory */
|
||||
change_dir(file->path, 0);
|
||||
} else if (strncmp(file->type, "REG", 3) == 0) {
|
||||
change_dir(c_file.path, 0);
|
||||
} else if (strncmp(c_file.type, "REG", 3) == 0) {
|
||||
edit_file();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* jump up (ctrl u) */
|
||||
|
@ -162,10 +168,10 @@ int main(int argc, char** argv)
|
|||
|
||||
/* jump down (ctrl d) */
|
||||
case CTRLD:
|
||||
if ((current_selection + JUMP_NUM) < (files_len() - 1))
|
||||
if ((current_selection + JUMP_NUM) < (files->length - 1))
|
||||
current_selection += JUMP_NUM;
|
||||
else
|
||||
current_selection = (files_len() - 1);
|
||||
current_selection = (files->length - 1);
|
||||
|
||||
highlight_current_line();
|
||||
break;
|
||||
|
@ -173,7 +179,7 @@ int main(int argc, char** argv)
|
|||
/* go down by j or down arrow */
|
||||
case DOWN:
|
||||
case 'j':
|
||||
if (current_selection < (files_len() - 1))
|
||||
if (current_selection < (files->length - 1))
|
||||
current_selection++;
|
||||
|
||||
highlight_current_line();
|
||||
|
@ -181,7 +187,7 @@ int main(int argc, char** argv)
|
|||
|
||||
/* jump to the bottom */
|
||||
case 'G':
|
||||
current_selection = (files_len() - 1);
|
||||
current_selection = (files->length - 1);
|
||||
highlight_current_line();
|
||||
break;
|
||||
|
||||
|
@ -234,14 +240,33 @@ int main(int argc, char** argv)
|
|||
/* show directories' sizes */
|
||||
case 'A':
|
||||
dirs_size = !dirs_size;
|
||||
clear_files();
|
||||
populate_files(cwd, 0);
|
||||
highlight_current_line();
|
||||
change_dir(cwd, 0);
|
||||
break;
|
||||
|
||||
/* go to previous dir */
|
||||
case '-':
|
||||
change_dir(p_cwd, 0);
|
||||
break;
|
||||
|
||||
/* show help */
|
||||
case '?':
|
||||
show_help();
|
||||
break;
|
||||
|
||||
/* toggle hidden files */
|
||||
case '.':
|
||||
show_hidden = !show_hidden;
|
||||
change_dir(cwd, 0);
|
||||
break;
|
||||
|
||||
/* toggle file details */
|
||||
case 'i':
|
||||
file_details = !file_details;
|
||||
change_dir(cwd, 0);
|
||||
|
||||
/* mark one file */
|
||||
case SPACE:
|
||||
add_file_stat(get_filepath(current_selection), 1);
|
||||
add_file_stat(files->items[current_selection].path, 1);
|
||||
highlight_current_line();
|
||||
break;
|
||||
|
||||
|
@ -254,35 +279,35 @@ int main(int argc, char** argv)
|
|||
/* mark actions: */
|
||||
/* delete */
|
||||
case 'd':;
|
||||
if (marked_len()) {
|
||||
if (marked->length) {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
/* move */
|
||||
case 'm':;
|
||||
if (marked_len()) {
|
||||
if (marked->length) {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
/* copy */
|
||||
case 'c':;
|
||||
if (marked_len()) {
|
||||
if (marked->length) {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
/* symbolic link */
|
||||
case 's':;
|
||||
if (marked_len()) {
|
||||
if (marked->length) {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
/* bulk rename */
|
||||
case 'b':;
|
||||
if (marked_len()) {
|
||||
if (marked->length) {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
@ -298,29 +323,54 @@ int main(int argc, char** argv)
|
|||
delwin(preview_content);
|
||||
delwin(panel);
|
||||
endwin();
|
||||
half_width = COLS / 2;
|
||||
init_windows();
|
||||
refresh();
|
||||
populate_files(cwd, 0);
|
||||
highlight_current_line();
|
||||
start_ccc();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
clear_files();
|
||||
clear_marked();
|
||||
arraylist_free(files);
|
||||
arraylist_free(marked);
|
||||
endwin();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void show_help()
|
||||
{
|
||||
wclear(directory_content);
|
||||
wclear(preview_content);
|
||||
wprintw(directory_content,"h: go to parent dir\nj: scroll down\nk: scroll up\nl: go to child dir\n\nleft: go to parent dir\ndown: scroll down\nup: scroll up\nright: go to child dir\n\nenter: go to child dir/open file\nbackspace: go to parent dir\n\ngg: go to top\nG: go to bottom\n\nctrl+u: jump up\nctrl+d: jump down\n\nt: go to trash dir\n~: go to home dir\n-: go to previous dir\nz: refresh current dir\n\nA: show directory disk usage/block size\nspace: mark file\na: mark all files in directory\n\n?: show help\nq: exit with last dir written to file\nctrl+c exit without writing last dir");
|
||||
wpprintw("Visit https://github.com/piotr-marendowski/ccc or use 'man ccc' for help");
|
||||
wrefresh(directory_content);
|
||||
wrefresh(preview_content);
|
||||
}
|
||||
|
||||
void start_ccc()
|
||||
{
|
||||
half_width = COLS / 2;
|
||||
init_windows();
|
||||
refresh();
|
||||
populate_files(cwd, 0);
|
||||
highlight_current_line();
|
||||
}
|
||||
|
||||
/*
|
||||
* Change directory in window with selection
|
||||
*/
|
||||
void change_dir(const char *buf, int selection)
|
||||
{
|
||||
strcpy(cwd, buf);
|
||||
clear_files();
|
||||
char *buf_dup;
|
||||
if (buf == p_cwd) {
|
||||
buf_dup = strdup(p_cwd);
|
||||
if (buf_dup == NULL) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
buf_dup = (char *) buf;
|
||||
}
|
||||
strcpy(cwd, buf_dup);
|
||||
arraylist_free(files);
|
||||
files = arraylist_init(100);
|
||||
populate_files(cwd, 0);
|
||||
current_selection = selection;
|
||||
highlight_current_line();
|
||||
|
@ -398,8 +448,8 @@ void populate_files(const char *path, int ftype)
|
|||
filename[0] = '\0';
|
||||
strcat(filename, ep->d_name);
|
||||
|
||||
/* can't be strncmp as that would filter out the dotfiles */
|
||||
if (strcmp(filename, ".") && strcmp(filename, "..")) {
|
||||
/* 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);
|
||||
|
@ -428,13 +478,13 @@ 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, marking ALL = 2
|
||||
*/
|
||||
long add_file_stat(char *filepath, int ftype)
|
||||
void add_file_stat(char *filepath, int ftype)
|
||||
{
|
||||
struct stat file_stat;
|
||||
if (stat(filepath, &file_stat) == -1) {
|
||||
/* can't be triggered? */
|
||||
if (errno == EACCES)
|
||||
return add_file(filepath, "", "", 8);
|
||||
arraylist_add(files, filepath, "", "", 8, false, false);
|
||||
}
|
||||
|
||||
/* get file type and color, 4 chars for the type */
|
||||
|
@ -469,14 +519,10 @@ long 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;
|
||||
long index = add_marked(filepath, type, force);
|
||||
arraylist_add(marked, filepath, NULL, type, 8, true, force);
|
||||
/* free type and return without allocating more stuff */
|
||||
free(type);
|
||||
if (index != -1) {
|
||||
return index; /* just marked */
|
||||
} else {
|
||||
return -1; /* already marked */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* get last modified time */
|
||||
|
@ -511,13 +557,12 @@ long add_file_stat(char *filepath, int ftype)
|
|||
snprintf(total_stat, 45, "%-18s %-8s", time, size);
|
||||
total_stat[strlen(total_stat)] = '\0';
|
||||
|
||||
long index = add_file(filepath, total_stat, type, color);
|
||||
arraylist_add(files, filepath, total_stat, type, color, false, false);
|
||||
|
||||
free(time);
|
||||
free(size);
|
||||
free(total_stat);
|
||||
free(type);
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
|
@ -533,7 +578,7 @@ void highlight_current_line()
|
|||
}
|
||||
|
||||
/* calculate range of files to show */
|
||||
long range = files_len();
|
||||
long range = files->length;
|
||||
/* not highlight if no files in directory */
|
||||
if (range == 0) {
|
||||
#if DRAW_PREVIEW
|
||||
|
@ -560,24 +605,24 @@ void highlight_current_line()
|
|||
wclear(panel);
|
||||
|
||||
/* check for marked files */
|
||||
long num_marked = marked_len();
|
||||
long num_marked = marked->length;
|
||||
if (num_marked > 0) {
|
||||
/* Determine length of formatted string */
|
||||
int m_len = snprintf(NULL, 0, "[%ld] selected", num_marked);
|
||||
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", current_selection + 1, files->length, selected, cwd);
|
||||
} else {
|
||||
wprintw(panel, "(%ld/%ld) %s", current_selection + 1, files_len(), cwd);
|
||||
wprintw(panel, "(%ld/%ld) %s", current_selection + 1, files->length, cwd);
|
||||
}
|
||||
}
|
||||
/* print the actual filename and stats */
|
||||
char *line = get_line(i);
|
||||
int color = get_color(i);
|
||||
char *line = get_line(files, i, file_details);
|
||||
int color = files->items[i].color;
|
||||
/* check is file marked for action */
|
||||
bool marked = in_marked(get_filepath(i));
|
||||
if (marked) {
|
||||
bool is_marked = arraylist_includes(marked, files->items[i].path);
|
||||
if (is_marked) {
|
||||
/* show file is selected */
|
||||
wattron(directory_content, COLOR_PAIR(7));
|
||||
} else {
|
||||
|
@ -590,7 +635,7 @@ void highlight_current_line()
|
|||
else
|
||||
mvwprintw(directory_content, i, 0, "%s", line);
|
||||
|
||||
if (marked) {
|
||||
if (is_marked) {
|
||||
wattroff(directory_content, COLOR_PAIR(7));
|
||||
} else {
|
||||
wattroff(directory_content, COLOR_PAIR(color));
|
||||
|
@ -616,14 +661,14 @@ void highlight_current_line()
|
|||
void show_file_content()
|
||||
{
|
||||
wclear(preview_content);
|
||||
file *current_file = get_file((long) current_selection);
|
||||
file current_file = files->items[current_selection];
|
||||
|
||||
if (strncmp(current_file->type, "DIR", 3) == 0)
|
||||
if (strncmp(current_file.type, "DIR", 3) == 0)
|
||||
return;
|
||||
|
||||
FILE *file = fopen(current_file->path, "r");
|
||||
FILE *file = fopen(current_file.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", current_file.path);
|
||||
return;
|
||||
}
|
||||
#if DRAW_BORDERS
|
||||
|
@ -673,7 +718,7 @@ void edit_file()
|
|||
def_prog_mode(); /* save the tty modes */
|
||||
endwin(); /* end curses mode temporarily */
|
||||
|
||||
char *filename = get_filepath(current_selection);
|
||||
char *filename = files->items[current_selection].path;
|
||||
int length = strlen(editor) + strlen(filename) + 2; /* one for space one for null */
|
||||
char command[length];
|
||||
|
||||
|
@ -685,7 +730,8 @@ void edit_file()
|
|||
}
|
||||
}
|
||||
|
||||
int write_last_d() {
|
||||
int write_last_d()
|
||||
{
|
||||
#ifdef LAST_D
|
||||
char *last_d = memalloc(PATH_MAX * sizeof(char));
|
||||
strcpy(last_d, LAST_D);
|
||||
|
|
2
config.h
2
config.h
|
@ -8,6 +8,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 */
|
||||
|
||||
/* set width offset for windows:
|
||||
+-------------%-------------+
|
||||
|
|
292
file.c
292
file.c
|
@ -5,263 +5,134 @@
|
|||
|
||||
#include "util.h"
|
||||
|
||||
/* files in a link list data structure */
|
||||
typedef struct file {
|
||||
char *path;
|
||||
char *stats;
|
||||
char *type;
|
||||
int color;
|
||||
struct file *next;
|
||||
} file;
|
||||
|
||||
file *files = NULL;
|
||||
file *marked = NULL;
|
||||
typedef struct ArrayList {
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
file *items;
|
||||
} ArrayList;
|
||||
|
||||
/*
|
||||
* Get length of files linked list
|
||||
*/
|
||||
long files_len()
|
||||
ArrayList *arraylist_init(size_t capacity)
|
||||
{
|
||||
file *current = files;
|
||||
int count = 0;
|
||||
while (current != NULL) {
|
||||
count++;
|
||||
current = current->next;
|
||||
}
|
||||
return count;
|
||||
ArrayList *list = memalloc(sizeof(ArrayList));
|
||||
list->length = 0;
|
||||
list->capacity = capacity;
|
||||
list->items = memalloc(capacity * sizeof(file));
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get length of marked files
|
||||
*/
|
||||
long marked_len()
|
||||
void arraylist_free(ArrayList *list)
|
||||
{
|
||||
file *current = marked;
|
||||
int count = 0;
|
||||
while (current != NULL) {
|
||||
count++;
|
||||
current = current->next;
|
||||
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].path);
|
||||
if (list->items[i].stats != NULL)
|
||||
free(list->items[i].stats);
|
||||
}
|
||||
return count;
|
||||
|
||||
free(list->items);
|
||||
list->length = 0;
|
||||
}
|
||||
|
||||
void free_file(file *toremove)
|
||||
bool arraylist_includes(ArrayList *list, char *path)
|
||||
{
|
||||
if (toremove->type != NULL)
|
||||
free(toremove->type);
|
||||
if (toremove->path != NULL)
|
||||
free(toremove->path);
|
||||
if (toremove->stats != NULL)
|
||||
free(toremove->stats);
|
||||
free(toremove);
|
||||
for (int i = 0; i < list->length; i++) {
|
||||
if (strcmp(list->items[i].path, path) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void clear_files()
|
||||
void arraylist_remove(ArrayList *list, long index)
|
||||
{
|
||||
file *tmp;
|
||||
while (files != NULL) {
|
||||
tmp = files;
|
||||
files = files->next;
|
||||
free_file(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_marked()
|
||||
{
|
||||
file *tmp;
|
||||
while (marked != NULL) {
|
||||
tmp = marked;
|
||||
files = marked->next;
|
||||
free_file(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
long add_file(char *filepath, char *stats, char *type, int color)
|
||||
{
|
||||
file *current = files;
|
||||
file *new_file = memalloc(sizeof(file));
|
||||
char *buf = strdup(filepath);
|
||||
char *buf2 = strdup(stats);
|
||||
char *buf3 = strdup(type);
|
||||
int buf4 = color;
|
||||
|
||||
if (buf == NULL || buf2 == NULL || buf3 == NULL)
|
||||
perror("ccc");
|
||||
|
||||
new_file->path = buf;
|
||||
new_file->stats = buf2;
|
||||
new_file->type = buf3;
|
||||
new_file->color = buf4;
|
||||
new_file->next = NULL;
|
||||
|
||||
if (current == NULL) {
|
||||
files = new_file;
|
||||
return 0;
|
||||
}
|
||||
long index = 1;
|
||||
while (current->next != NULL) {
|
||||
current = current->next;
|
||||
index++;
|
||||
}
|
||||
current->next = new_file;
|
||||
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);
|
||||
if (index >= list->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(list->items[index].path);
|
||||
free(list->items[index].stats);
|
||||
free(list->items[index].type);
|
||||
|
||||
/* Search for the marked file node in the list */
|
||||
file* temp = marked;
|
||||
while (temp != NULL && temp->next != marked_file) {
|
||||
temp = temp->next;
|
||||
for (long i = index; i < list->length - 1; i++) {
|
||||
list->items[i] = list->items[i + 1];
|
||||
}
|
||||
|
||||
/* If the marked file node is found, remove it from the list */
|
||||
if (temp != NULL) {
|
||||
temp->next = marked_file->next;
|
||||
free_file(marked_file);
|
||||
}
|
||||
list->length--;
|
||||
}
|
||||
|
||||
/*
|
||||
* force will not remove duplicate marked files, instead it just skip adding
|
||||
*/
|
||||
long add_marked(char *filepath, char *type, bool force)
|
||||
void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, int color, bool marked, bool force)
|
||||
{
|
||||
file *current = marked;
|
||||
file *new_file = memalloc(sizeof(file));
|
||||
char *buf = strdup(filepath);
|
||||
char *buf2 = strdup(type);
|
||||
if (buf == NULL || buf2 == NULL) {
|
||||
char *filepath_cp = NULL;
|
||||
char *stats_cp = NULL;
|
||||
char *type_cp = NULL;
|
||||
if (filepath != NULL) {
|
||||
filepath_cp = strdup(filepath);
|
||||
if (filepath_cp == NULL) {
|
||||
perror("ccc");
|
||||
}
|
||||
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) {
|
||||
if (force) {
|
||||
return index;
|
||||
} else {
|
||||
remove_marked(current);
|
||||
free_file(new_file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
current = current->next;
|
||||
index++;
|
||||
}
|
||||
if (strcmp(current->path, new_file->path) == 0){
|
||||
if (force) {
|
||||
return 0;
|
||||
} else {
|
||||
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;
|
||||
if (index == 0) {
|
||||
return current;
|
||||
}
|
||||
if (index > files_len()) {
|
||||
return NULL;
|
||||
}
|
||||
for (long i = 0; i < index; i++) {
|
||||
current = current->next;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
char *get_filepath(long index)
|
||||
{
|
||||
file *file = get_file(index);
|
||||
if (file != NULL) {
|
||||
char *name = strdup(file->path);
|
||||
if (!name) {
|
||||
if (stats != NULL) {
|
||||
stats_cp = strdup(stats);
|
||||
if (stats_cp == NULL) {
|
||||
perror("ccc");
|
||||
}
|
||||
return name;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
if (type != NULL) {
|
||||
type_cp = strdup(type);
|
||||
if (type_cp == NULL) {
|
||||
perror("ccc");
|
||||
}
|
||||
}
|
||||
|
||||
int get_color(long index)
|
||||
{
|
||||
file *file = get_file(index);
|
||||
if (file != NULL) {
|
||||
int color = file->color;
|
||||
if (!color) {
|
||||
perror("ccc");
|
||||
/* path, stats, type, color */
|
||||
file new_file = { filepath_cp, stats_cp, type_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) {
|
||||
arraylist_remove(list, i);
|
||||
}
|
||||
return color;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
list->items[list->length] = new_file;
|
||||
} else {
|
||||
return 8; /* white */
|
||||
int new_cap = list->capacity * 2;
|
||||
file *new_items = memalloc(new_cap * sizeof(file));
|
||||
file *old_items = list->items;
|
||||
list->capacity = new_cap;
|
||||
list->items = new_items;
|
||||
for (int i = 0; i < list->length; i++) {
|
||||
new_items[i] = old_items[i];
|
||||
}
|
||||
free(old_items);
|
||||
list->items[list->length] = new_file;
|
||||
}
|
||||
list->length++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a formatted line for display
|
||||
*/
|
||||
char *get_line(long index)
|
||||
char *get_line(ArrayList *list, long index, bool detail)
|
||||
{
|
||||
file *file = get_file(index);
|
||||
if (file != NULL) {
|
||||
char *name = strdup(file->path);
|
||||
char *stats = strdup(file->stats);
|
||||
file file = list->items[index];
|
||||
char *name = strdup(file.path);
|
||||
char *stats = strdup(file.stats);
|
||||
size_t length = strlen(name) + strlen(stats) + 2; /* one for space and one for null */
|
||||
char *line = memalloc(length * sizeof(char));
|
||||
|
||||
|
@ -272,7 +143,4 @@ char *get_line(long index)
|
|||
snprintf(line, length, "%s %s", stats, name);
|
||||
|
||||
return line;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
29
file.h
29
file.h
|
@ -1,27 +1,26 @@
|
|||
#ifndef FILE_H_
|
||||
#define FILE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct file {
|
||||
char *path;
|
||||
char *stats;
|
||||
char *type;
|
||||
int color;
|
||||
struct file *next;
|
||||
} 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, bool force);
|
||||
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);
|
||||
char *get_line(long index);
|
||||
typedef struct ArrayList {
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
file *items;
|
||||
} ArrayList;
|
||||
|
||||
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);
|
||||
char *get_line(ArrayList *list, long index, bool detail);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue