icons and fix goto trash dir and fix preview

This commit is contained in:
Night Kaly 2024-03-29 22:34:26 +00:00
parent eab8013601
commit b470b7b286
No known key found for this signature in database
GPG key ID: 8E829D3381CFEBBE
7 changed files with 275 additions and 84 deletions

View file

@ -13,6 +13,7 @@ Consider this project incomplete and WIP!
| Standard movement | X | | | Standard movement | X | |
| Advanced movement (jumps) | X | | | Advanced movement (jumps) | X | |
| File details | X | | | File details | X | |
| File icons! | X | |
| Searching for files | | | | Searching for files | | |
| Sorting | | | | Sorting | | |
| Marking and marking operations | | | | Marking and marking operations | | |
@ -32,9 +33,10 @@ Consider this project incomplete and WIP!
### Dependencies ### Dependencies
- gcc - gcc
- ncurses - ncursesw
- make - make
- pkg-config - pkg-config
- Any [Nerd Font](https://www.nerdfonts.com/) for file icons (optional, but turned on by default)
### Building ### Building

129
ccc.c
View file

@ -10,6 +10,8 @@
#include <ftw.h> #include <ftw.h>
#include <time.h> #include <time.h>
#include <ncurses.h> #include <ncurses.h>
#include <locale.h>
#include <wchar.h>
#include "file.h" #include "file.h"
#include "util.h" #include "util.h"
@ -18,8 +20,9 @@
/* functions' definitions */ /* functions' definitions */
void show_help(); void show_help();
void start_ccc(); void start_ccc();
char *check_trash_dir();
void change_dir(const char *buf, int selection, int ftype); 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); void populate_files(const char *path, int ftype);
int get_directory_size(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); 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 *filepath, int ftype);
@ -41,6 +44,7 @@ bool show_hidden = SHOW_HIDDEN;
bool file_details = SHOW_DETAILS; bool file_details = SHOW_DETAILS;
char *cwd; char *cwd;
char *p_cwd; /* previous cwd */ char *p_cwd; /* previous cwd */
char *trash_dir;
int half_width; int half_width;
ArrayList *files; ArrayList *files;
ArrayList *marked; ArrayList *marked;
@ -71,6 +75,7 @@ int main(int argc, char** argv)
/* initialize screen, don't print special chars, /* initialize screen, don't print special chars,
* make ctrl + c work, don't show cursor * make ctrl + c work, don't show cursor
* enable arrow keys */ * enable arrow keys */
setlocale(LC_ALL, "");
initscr(); initscr();
noecho(); noecho();
cbreak(); cbreak();
@ -234,26 +239,10 @@ int main(int argc, char** argv)
/* go to the trash dir */ /* go to the trash dir */
case 't':; case 't':;
#ifdef TRASH_DIR char *trash_dir = check_trash_dir();
char *trash_dir = TRASH_DIR; if (trash_dir != NULL)
#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");
}
}
}
change_dir(trash_dir, 0, 0); change_dir(trash_dir, 0, 0);
} break;
break;
/* show directories' sizes */ /* show directories' sizes */
case 'A': case 'A':
@ -302,7 +291,11 @@ int main(int argc, char** argv)
/* delete */ /* delete */
case 'd':; case 'd':;
if (marked->length) { if (marked->length) {
; char *trash_dir = check_trash_dir();
if (trash_dir != NULL) {
;
/* do your magic here */
}
} }
break; break;
@ -374,6 +367,44 @@ void start_ccc()
init_windows(); 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 * 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 * Recursively create directory by creating each subdirectory
* like mkdir -p * like mkdir -p
*/ */
int mkdir_p(const char *destdir) void mkdir_p(const char *destdir)
{ {
char *path = memalloc(PATH_MAX * sizeof(char)); char *path = memalloc(PATH_MAX * sizeof(char));
char dir_path[PATH_MAX] = ""; char dir_path[PATH_MAX] = "";
@ -408,7 +439,7 @@ int mkdir_p(const char *destdir)
char *home = getenv("HOME"); char *home = getenv("HOME");
if (home == NULL) { if (home == NULL) {
wpprintw("$HOME is not defined"); wpprintw("$HOME is not defined");
return -1; return;
} }
/* replace ~ with home */ /* replace ~ with home */
snprintf(path, PATH_MAX, "%s%s", home, destdir + 1); snprintf(path, PATH_MAX, "%s%s", home, destdir + 1);
@ -433,15 +464,15 @@ int mkdir_p(const char *destdir)
continue; continue;
} }
perror("ccc"); wpprintw("mkdir failed: %s\n", strerror(errno));
free(path); free(path);
return -1; return;
} }
token = strtok(NULL, "/"); token = strtok(NULL, "/");
} }
free(path); 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 * Get file's last modified time, size, type
* Add that file into list * 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) 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) { if (stat(filepath, &file_stat) == -1) {
/* can't be triggered? */ /* can't be triggered? */
if (errno == EACCES) 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)); char *type = memalloc(4 * sizeof(char));
wchar_t *icon = memalloc(2 * sizeof(wchar_t));
wcsncpy(icon, L"", 2);
int color; int color;
if (S_ISDIR(file_stat.st_mode)) { if (S_ISDIR(file_stat.st_mode)) {
strcpy(type, "DIR"); /* directory type */ strncpy(type, "DIR", 4); /* directory type */
color = 5; /* blue color */ color = 5; /* blue color */
} else if (S_ISREG(file_stat.st_mode)) { } else if (S_ISREG(file_stat.st_mode)) {
strcpy(type, "REG"); /* regular file */ strncpy(type, "REG", 4); /* regular file */
color = 8; /* white color */ color = 8; /* white color */
} else if (S_ISLNK(file_stat.st_mode)) { } else if (S_ISLNK(file_stat.st_mode)) {
strcpy(type, "LNK"); /* symbolic link */ strncpy(type, "LNK", 4); /* symbolic link */
color = 3; /* green color */ color = 3; /* green color */
} else if (S_ISCHR(file_stat.st_mode)) { } else if (S_ISCHR(file_stat.st_mode)) {
strcpy(type, "CHR"); /* character device */ strncpy(type, "CHR", 4); /* character device */
color = 8; /* white color */ color = 8; /* white color */
} else if (S_ISSOCK(file_stat.st_mode)) { } else if (S_ISSOCK(file_stat.st_mode)) {
strcpy(type, "SOC"); /* socket */ strncpy(type, "SOC", 4); /* socket */
color = 8; /* white color */ color = 8; /* white color */
} else if (S_ISBLK(file_stat.st_mode)) { } else if (S_ISBLK(file_stat.st_mode)) {
strcpy(type, "BLK"); /* block device */ strncpy(type, "BLK", 4); /* block device */
color = 4; /* yellow color */ color = 4; /* yellow color */
} else if (S_ISFIFO(file_stat.st_mode)) { } else if (S_ISFIFO(file_stat.st_mode)) {
strcpy(type, "FIF"); /* FIFO */ strncpy(type, "FIF", 4); /* FIFO */
color = 8; /* white color */ color = 8; /* white color */
} else { } else {
color = 8; /* white color */ color = 8; /* white color */
@ -536,16 +570,16 @@ void add_file_stat(char *filepath, int ftype)
if (ftype == 1 || ftype == 2) { if (ftype == 1 || ftype == 2) {
/* force if user is marking all files */ /* force if user is marking all files */
bool force = ftype == 2 ? true : false; 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 and return without allocating more stuff */
free(type); free(type);
return; return;
} }
/* get last modified time */ /* get last modified time */
char *time = memalloc(20 * sizeof(char)); char *time = memalloc(17 * sizeof(char));
/* format last modified time to a string */ /* 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 */ /* get file size */
double bytes = file_stat.st_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 */ /* 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; int unit = 0;
const char* units[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; const char* units[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
while (bytes > 1024) { while (bytes > 1024) {
@ -573,17 +607,18 @@ void add_file_stat(char *filepath, int ftype)
/* get file mode string */ /* get file mode string */
char *mode_str = get_file_mode(file_stat.st_mode); char *mode_str = get_file_mode(file_stat.st_mode);
char *total_stat = memalloc(56 * sizeof(char)); /* 11 + 17 + 8 + 1 for null */
snprintf(total_stat, 56, "%s %s %-8s", mode_str, time, size); char *total_stat = memalloc(37 * sizeof(char));
total_stat[strlen(total_stat)] = '\0'; 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(time);
free(size); free(size);
free(total_stat); free(total_stat);
free(type); free(type);
free(mode_str); 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 *get_file_mode(mode_t mode)
{ {
char *mode_str = memalloc(sizeof(char) * 11); 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[1] = (mode & S_IRUSR) ? 'r' : '-';
mode_str[2] = (mode & S_IWUSR) ? 'w' : '-'; mode_str[2] = (mode & S_IWUSR) ? 'w' : '-';
mode_str[3] = (mode & S_IXUSR) ? 'x' : '-'; 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[7] = (mode & S_IROTH) ? 'r' : '-';
mode_str[8] = (mode & S_IWOTH) ? 'w' : '-'; mode_str[8] = (mode & S_IWOTH) ? 'w' : '-';
mode_str[9] = (mode & S_IXOTH) ? 'x' : '-'; mode_str[9] = (mode & S_IXOTH) ? 'x' : '-';
mode_str[10] = '\0'; // Null terminator mode_str[10] = '\0';
return mode_str; return mode_str;
} }
@ -694,10 +729,10 @@ void highlight_current_line()
#if DRAW_PREVIEW #if DRAW_PREVIEW
show_file_content(); show_file_content();
#endif #endif
wrefresh(preview_content);
#if DRAW_BORDERS #if DRAW_BORDERS
draw_border_title(preview_border, true); draw_border_title(preview_border, true);
#endif #endif
wrefresh(preview_content);
} }
/* /*

View file

@ -9,7 +9,8 @@
#define DRAW_BORDERS true /* Draw borders around windows? */ #define DRAW_BORDERS true /* Draw borders around windows? */
#define DRAW_PREVIEW true /* Draw file preview? */ #define DRAW_PREVIEW true /* Draw file preview? */
#define SHOW_HIDDEN true /* show hidden files/dotfiles in 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: /* set width offset for windows:
+-------------%-------------+ +-------------%-------------+
@ -31,6 +32,9 @@ In COLS:
/* File location to write last directory */ /* File location to write last directory */
#define LAST_D "~/.cache/ccc/.ccc_d" #define LAST_D "~/.cache/ccc/.ccc_d"
/* will create this directory if doesn't exist! */
#define TRASH_DIR "~/.cache/ccc/trash/"
/* Keybindings */ /* Keybindings */
#define CTRLD 0x04 #define CTRLD 0x04
#define ENTER 0xA #define ENTER 0xA

69
file.c
View file

@ -2,21 +2,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <libgen.h> #include <libgen.h>
#include <wchar.h>
#include "util.h" #include "util.h"
#include "file.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;
ArrayList *arraylist_init(size_t capacity) ArrayList *arraylist_init(size_t capacity)
{ {
@ -24,6 +13,7 @@ ArrayList *arraylist_init(size_t capacity)
list->length = 0; list->length = 0;
list->capacity = capacity; list->capacity = capacity;
list->items = memalloc(capacity * sizeof(file)); list->items = memalloc(capacity * sizeof(file));
return list; return list;
} }
@ -36,7 +26,10 @@ void arraylist_free(ArrayList *list)
free(list->items[i].path); free(list->items[i].path);
if (list->items[i].stats != NULL) if (list->items[i].stats != NULL)
free(list->items[i].stats); free(list->items[i].stats);
/*if (list->items[i].icon != NULL)
free(list->items[i].icon);*/
} }
free(list->items); free(list->items);
list->length = 0; list->length = 0;
} }
@ -48,63 +41,66 @@ bool arraylist_includes(ArrayList *list, char *path)
return true; return true;
} }
} }
return false; return false;
} }
void arraylist_remove(ArrayList *list, long index) void arraylist_remove(ArrayList *list, long index)
{ {
if (index >= list->length) { if (index >= list->length)
return; return;
}
free(list->items[index].path); free(list->items[index].path);
free(list->items[index].stats); free(list->items[index].stats);
free(list->items[index].type); 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->items[i] = list->items[i + 1];
}
list->length--; 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 *filepath_cp = NULL;
char *stats_cp = NULL; char *stats_cp = NULL;
char *type_cp = NULL; char *type_cp = NULL;
wchar_t *icon_cp = NULL;
if (filepath != NULL) { if (filepath != NULL) {
filepath_cp = strdup(filepath); filepath_cp = strdup(filepath);
if (filepath_cp == NULL) { if (filepath_cp == NULL)
perror("ccc"); perror("ccc");
}
} }
if (stats != NULL) { if (stats != NULL) {
stats_cp = strdup(stats); stats_cp = strdup(stats);
if (stats_cp == NULL) { if (stats_cp == NULL)
perror("ccc"); perror("ccc");
}
} }
if (type != NULL) { if (type != NULL) {
type_cp = strdup(type); type_cp = strdup(type);
if (type_cp == NULL) { if (type_cp == NULL)
perror("ccc");
}
if (icon != NULL) {
icon_cp = wcsdup(icon);
if (icon_cp == NULL)
perror("ccc"); perror("ccc");
}
} }
/* path, stats, type, color */ /* path, stats, type, icon, color */
file new_file = { filepath_cp, stats_cp, type_cp, color }; file new_file = { filepath_cp, stats_cp, type_cp, icon_cp, color };
if (list->capacity != list->length) { if (list->capacity != list->length) {
if (marked) { if (marked) {
for (int i = 0; i < list->length; i++) { for (int i = 0; i < list->length; i++) {
if (strcmp(list->items[i].path, new_file.path) == 0) { if (strcmp(list->items[i].path, new_file.path) == 0) {
if (!force) { if (!force)
arraylist_remove(list, i); arraylist_remove(list, i);
}
return; return;
} }
} }
@ -116,9 +112,10 @@ void arraylist_add(ArrayList *list, char *filepath, char *stats, char *type, int
file *old_items = list->items; file *old_items = list->items;
list->capacity = new_cap; list->capacity = new_cap;
list->items = new_items; 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]; new_items[i] = old_items[i];
}
free(old_items); free(old_items);
list->items[list->length] = new_file; list->items[list->length] = new_file;
} }
@ -132,6 +129,7 @@ char *get_line(ArrayList *list, long index, bool detail)
{ {
file file = list->items[index]; file file = list->items[index];
char *name = strdup(file.path); char *name = strdup(file.path);
wchar_t *icon = wcsdup(file.icon);
char *stats = NULL; char *stats = NULL;
size_t length; size_t length;
if (detail) { if (detail) {
@ -148,10 +146,13 @@ char *get_line(ArrayList *list, long index, bool detail)
name = basename(name); name = basename(name);
if (name == NULL) if (name == NULL)
perror("ccc"); perror("ccc");
/*printf("%ls", icon);*/
if (detail) { if (detail) {
snprintf(line, length, "%s %s", stats, name); snprintf(line, length, "%s %ls %s", stats, icon, name);
} else { } else {
snprintf(line, length, "%s", name); snprintf(line, length, "%ls %s", icon, name);
} }
return line; return line;

3
file.h
View file

@ -7,6 +7,7 @@ typedef struct file {
char *path; char *path;
char *stats; char *stats;
char *type; char *type;
wchar_t *icon;
int color; int color;
} file; } file;
@ -20,7 +21,7 @@ ArrayList *arraylist_init(size_t capacity);
void arraylist_free(ArrayList *list); void arraylist_free(ArrayList *list);
bool arraylist_includes(ArrayList *list, char *path); bool arraylist_includes(ArrayList *list, char *path);
void arraylist_remove(ArrayList *list, long index); 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); char *get_line(ArrayList *list, long index, bool detail);
#endif #endif

130
icons.c Normal file
View file

@ -0,0 +1,130 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#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;
}

18
icons.h Normal file
View file

@ -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