diff --git a/src/utils/dlist.c b/src/utils/dlist.c index bfd64db..c63bca5 100644 --- a/src/utils/dlist.c +++ b/src/utils/dlist.c @@ -33,7 +33,7 @@ void _dlist_insert(dlist_t *dlist, dlist_node_t *new_el, prev_node->next = new_el; if (new_el->next == NULL) { dlist->current = new_el; - dlist->pointer = new_el; + dlist->work_pointer = new_el; } } else { new_el->next = dlist->start; @@ -49,7 +49,7 @@ void _dlist_insert_end(dlist_t *dlist, dlist_node_t *new_node) { new_node->previous = dlist->current; new_node->next = NULL; dlist->current = new_node; - dlist->pointer = new_node; + dlist->work_pointer = new_node; dlist->len++; } @@ -66,7 +66,7 @@ void _dlist_add_sort(dlist_t *dlist, void *el_ptr, int el_siz, dlist->current = node; node->next = NULL; node->previous = NULL; - dlist->pointer = node; + dlist->work_pointer = node; dlist->len++; return; } @@ -97,7 +97,7 @@ void _dlist_add(dlist_t *dlist, void *el_ptr, int el_siz, node->next = NULL; dlist->start = node; dlist->current = node; - dlist->pointer = node; + dlist->work_pointer = node; } else if (prepend) { node->previous = NULL; node->next = dlist->start; @@ -108,7 +108,7 @@ void _dlist_add(dlist_t *dlist, void *el_ptr, int el_siz, node->next = NULL; dlist->current->next = node; dlist->current = node; - dlist->pointer = node; + dlist->work_pointer = node; } dlist->len++; } @@ -154,7 +154,7 @@ int dlist_clear_list(dlist_t *dlist, dblist_rm_cb_t cb) { dlist->len = 0; dlist->current = NULL; dlist->start = NULL; - dlist->pointer = NULL; + dlist->work_pointer = NULL; return 1; } @@ -162,17 +162,37 @@ int dlist_clear_list(dlist_t *dlist, dblist_rm_cb_t cb) { /* Iterators */ void *dlist_it_prev(dlist_t *dlist) { - dlist_node_t *cur_ptr = dlist->pointer; - if (dlist->pointer->previous != NULL) { - dlist->pointer = dlist->pointer->previous; + dlist_node_t *cur_ptr = dlist->work_pointer; + if (dlist->work_pointer->previous != NULL) { + dlist->work_pointer = dlist->work_pointer->previous; } return cur_ptr->el_ptr; } void *dlist_it_next(dlist_t *dlist) { - dlist_node_t *cur_ptr = dlist->pointer; - if (dlist->pointer->next != NULL) { - dlist->pointer = dlist->pointer->next; + dlist_node_t *cur_ptr = dlist->work_pointer; + if (dlist->work_pointer->next != NULL) { + dlist->work_pointer = dlist->work_pointer->next; } return cur_ptr->el_ptr; +} + +dlist_node_t *dlist_wind_fwd(dlist_t *dlist, int count) { + dlist_node_t *cur_ptr = dlist->work_pointer; + + for (int i = 0; i < count && cur_ptr != NULL; i++) { + cur_ptr = cur_ptr->next; + } + dlist->work_pointer = cur_ptr; + return cur_ptr; +} + +dlist_node_t *dlist_wind_bwd(dlist_t *dlist, int count) { + dlist_node_t *cur_ptr = dlist->work_pointer; + + for (int i = 0; i < count && cur_ptr != NULL; i++) { + cur_ptr = cur_ptr->previous; + } + dlist->work_pointer = cur_ptr; + return cur_ptr; } \ No newline at end of file diff --git a/src/utils/dlist.h b/src/utils/dlist.h index a515464..f0fda6c 100644 --- a/src/utils/dlist.h +++ b/src/utils/dlist.h @@ -13,7 +13,7 @@ typedef struct dlist_node_t { typedef struct dlist_t { dlist_node_t *start; dlist_node_t *current; - dlist_node_t *pointer; + dlist_node_t *work_pointer; size_t len; } dlist_t; @@ -33,13 +33,19 @@ void _dlist_add_sort(dlist_t *dlist, void *el_ptr, int el_siz, dblist_sort_cb_t cb, dblist_add_cb_t add_cb); int dlist_remove_by_ptr(dlist_t *dlist, void *el_ptr, dblist_rm_cb_t cb); int dlist_clear_list(dlist_t *dlist, dblist_rm_cb_t cb); +dlist_node_t *dlist_wind_fwd(dlist_t *dlist, int count); +dlist_node_t *dlist_wind_bwd(dlist_t *dlist, int count); #define dlist_init(el_ptr, el_def, add_cb) \ _dlist_init(el_ptr, sizeof(el_def), add_cb) #define dlist_add(dlist, el_ptr, el_def, add_cb, prepend) \ _dlist_add(dlist, el_ptr, sizeof(el_def), add_cb, prepend) #define dlist_get_current(dlist) dlist->current->el_ptr +#define dlist_get_working_point(dlist) dlist->current->el_ptr #define dlist_add_sort(dlist, el_ptr, el_typ, sort_cb, add_cb) \ _dlist_add_sort(dlist, el_ptr, sizeof(el_typ), sort_cb, add_cb) +#define dlist_reset_wp_to_st(dlist, st_ptr) dlist->work_pointer = st_ptr +#define dlist_get_ptr(node_ptr) node_ptr->el_ptr +#define dlist_set_wp(dlist, node_ptr) dlist->work_pointer = node_ptr #endif \ No newline at end of file diff --git a/src/windows/fs_file_list.c b/src/windows/fs_file_list.c index f44dd12..fbf5dca 100644 --- a/src/windows/fs_file_list.c +++ b/src/windows/fs_file_list.c @@ -15,16 +15,23 @@ #include #include +#include #include #include #include -#include #include "alert.h" +#include "dlist.h" #include "fs_file_list.h" #include "main_window.h" #include "widget_core.h" +#define fl_add(dlist, el_ptr, prepend) \ + dlist_add_sort(dlist, el_ptr, w_lfl_item_t, fl_add_cb, prepend) +#define fl_add_sort(dlist, el_ptr) \ + dlist_add_sort(dlist, el_ptr, w_lfl_item_t, fl_add_sort_cb, fl_add_cb) +#define fl_clear(f_list) dlist_clear_list(f_list, fl_clear_cb) + // void w_fl_reset(w_lfl_ui_t *fl_ui); static size_t get_file_size(char *path) { @@ -46,27 +53,34 @@ struct fl_args { u_char d_type; }; -static void fl_add(w_lfl_item_t **f_start, w_lfl_item_t **f_current, - struct fl_args *fargs) { - w_lfl_item_t *c_item = malloc(sizeof(w_lfl_item_t)); - c_item->name = malloc(strlen(fargs->name) + 1); - strcpy(c_item->name, fargs->name); - c_item->size = fargs->size; - c_item->next = NULL; - c_item->d_type = fargs->d_type; - if (fargs->path != NULL) { - c_item->path = malloc(strlen(fargs->path) + 1); - strcpy(c_item->path, fargs->path); - } - if (*f_start == NULL) { - c_item->prev = NULL; - *f_start = c_item; - *f_current = c_item; +static bool fl_add_cb(void *_dst, void *_src) { + w_lfl_item_t *dst = _dst; + w_lfl_item_t *src = src; + memcpy(dst, src, sizeof(w_lfl_item_t)); + dst->name = malloc(strlen(src->name) + 1); + strcpy(src->name, dst->name); + if (src->path != NULL) { + dst->path = malloc(strlen(src->path) + 1); + strcpy(dst->path, src->path); } else { - c_item->prev = *f_current; - (*f_current)->next = c_item; - *f_current = c_item; + dst->path = NULL; } + return 1; +} + +static bool fl_add_sort_cb(void *_a, void *_b) { + w_lfl_item_t *a = _a; + w_lfl_item_t *b = _b; + /* TODO: do real comparison */ + return true; +} + +static bool fl_clear_cb(void *el_ptr) { + w_lfl_item_t *el = el_ptr; + free(el->path); + free(el->name); + free(el); + return 1; } static void lfl_clear(w_lfl_item_t **start, w_lfl_item_t **arg_current) { @@ -90,75 +104,68 @@ static int get_files_from_fs(w_lfl_ui_t *fui, char *path) { char name[257]; char d_name[257]; char l_path[INBUFSIZE]; - struct fl_args f_args; + w_lfl_item_t f_args; ssize_t r = 0; fui->files_num = 0; - w_lfl_item_t *d_start = NULL, *d_current = NULL; /* directories */ - w_lfl_item_t *f_start = NULL, *f_current = NULL; /* files */ - dir = opendir(path); if (!dir) return 1; if (fui->d_path != NULL) { free(fui->d_path); - lfl_clear(&(fui->start), &(fui->current)); + fl_clear(fui->f_list); } fui->d_path = malloc(strlen(path) + 1); strcpy(fui->d_path, path); while ((dent = readdir(dir)) != NULL) { f_args.path = NULL; if ((f_args.d_type = dent->d_type) == DT_DIR) { + /* -> DIRECTORIES */ if (!strcmp(dent->d_name, "..")) { w_lfl_item_t *t_st = NULL, *t_cur = NULL; sprintf(name, "/%s", dent->d_name); f_args.name = name; f_args.size = 0; - fl_add(&t_st, &t_cur, &f_args); + f_args.d_type = dent->d_type; + fl_add(fui->f_list, &f_args, true); fui->files_num++; - /* Always put .. at the beginning */ - t_st->next = d_start; - d_start = t_st; - if (d_current == NULL) - d_current = t_cur; - continue; } /* Hide directories with dot-beginnings */ if (!strncmp(dent->d_name, ".", 1)) continue; sprintf(name, "/%s", dent->d_name); f_args.name = name; - fl_add(&d_start, &d_current, &f_args); f_args.size = 0; + f_args.d_type = dent->d_type; + fl_add_sort(fui->f_list, &f_args); fui->files_num++; + /* <- DIRECTORIES */ } else if (f_args.d_type == DT_LNK) { + /* -> LINKS */ sprintf(name, "%s/%s", fui->d_path, dent->d_name); r = readlink(name, l_path, INBUFSIZE); sprintf(name, "->/%s", dent->d_name); f_args.name = name; f_args.path = l_path; f_args.size = 0; - fl_add(&d_start, &d_current, &f_args); + f_args.d_type = dent->d_type; + fl_add_sort(fui->f_list, &f_args); fui->files_num++; + /* <- LINKS */ } else { + /* -> FILES */ /* Hide files with dot-beginnings */ if (!strncmp(dent->d_name, ".", 1)) continue; f_args.name = dent->d_name; f_args.size = get_file_size(dent->d_name); - fl_add(&f_start, &f_current, &f_args); + f_args.d_type = dent->d_type; + fl_add_sort(fui->f_list, &f_args); fui->files_num++; - sprintf(name, "%s", dent->d_name); + /* <- FILES */ } } - if (d_current != NULL) - d_current->next = f_start; - if (f_start != NULL) - f_start->prev = d_current; - fui->start = d_start; - fui->page_start = d_start; - fui->current = d_start; fui->cur_page = 1; fui->pages_num = fui->files_num / fui->max_lines; if (fui->files_num % fui->max_lines) { @@ -172,8 +179,9 @@ static void open_selected_item(w_lfl_ui_t *fui, w_cbrp_data *resp_data) { char *selection = NULL; size_t dp_current; char n_path[INBUFSIZE]; - if (fui->current->d_type == DT_DIR) { - if (!strcmp("/..", fui->current->name)) { + w_lfl_item_t *current_item = dlist_get_current(fui->f_list); + if (current_item->d_type == DT_DIR) { + if (!strcmp("/..", current_item->name)) { strcpy(n_path, fui->d_path); bash_case = strrchr(n_path, '/'); if (bash_case != NULL) { @@ -185,60 +193,44 @@ static void open_selected_item(w_lfl_ui_t *fui, w_cbrp_data *resp_data) { } } else { dp_current = strlen(fui->d_path); - selection = fui->current->name + 1; + selection = current_item->name + 1; sprintf(n_path, "%s/%s", fui->d_path, selection); if (get_files_from_fs(fui, n_path)) { w_alert("Can't open the folder!"); return; } } - fui->current = fui->start; fui->current_idx = 0; resp_data->code = cbrc_none; w_lfl_draw(fui); - } else if (fui->current->d_type == DT_REG) { + } else if (current_item->d_type == DT_REG) { resp_data->code = cbrp_val; resp_data->val.type = val_num; resp_data->val.val.num = 1; - } else if (fui->current->d_type == DT_LNK) { - strcpy(n_path, fui->current->path); + } else if (current_item->d_type == DT_LNK) { + strcpy(n_path, current_item->path); if (get_files_from_fs(fui, n_path)) { w_alert("Can't open the link!"); return; } - fui->current = fui->start; fui->current_idx = 0; resp_data->code = cbrc_none; w_lfl_draw(fui); } } -/* next page */ static void page_next(w_lfl_ui_t *fui) { - int count = fui->max_lines; - w_lfl_item_t *n_page_item = fui->page_start; if (fui->cur_page < fui->pages_num) { - for (; count >= 0; count--) { - n_page_item = n_page_item->next; - } + dlist_node_t *n_page_item = dlist_wind_fwd(fui->f_list, fui->max_lines); fui->cur_page++; fui->page_start = n_page_item; fui->current_idx = 0; - fui->current = n_page_item; } } - -/* previous page */ static void page_previous(w_lfl_ui_t *fui) { - int count = fui->max_lines; - w_lfl_item_t *n_page_item = fui->page_start; if (fui->cur_page > 1) { - for (; count >= 0; count--) { - n_page_item = n_page_item->prev; - } + dlist_node_t *n_page_item = dlist_wind_bwd(fui->f_list, fui->max_lines); fui->cur_page--; - fui->current = - fui->page_start->prev; /* the last element of the previous page */ fui->page_start = n_page_item; fui->current_idx = fui->max_lines; } @@ -249,32 +241,24 @@ static void w_lfl_cb(w_cb_args_t *args) { int32_t key = *((int32_t *)args->data); bool is_cur_p = 0; /* current page */ app_t *app = (app_t *)args->app; + dlist_node_t *flwp = fui->f_list->work_pointer; + dlist_set_wp(fui->f_list, fui->fl_selected); switch (key) { case KEY_DOWN: is_cur_p = (fui->current_idx % fui->max_lines || fui->current_idx == 0); - if (fui->current->next != NULL) { - if (is_cur_p) { - if (fui->current_idx < fui->max_lines) { - fui->current = fui->current->next; - fui->current_idx++; - } - } else { /* is_cur_p */ - page_next(fui); - } - } else - break; /* fui->current->next != NULL */ + if (is_cur_p) { + dlist_wind_fwd(fui->f_list, fui->max_lines); + } else { /* is_cur_p */ + page_next(fui); + } w_lfl_draw(fui); break; case KEY_UP: - if (fui->current->prev != NULL) { - if (fui->current_idx > 0) { - fui->current = fui->current->prev; - fui->current_idx--; - } else { - page_previous(fui); - } - } else - break; + if (fui->current_idx > 0) { + dlist_wind_bwd(fui->f_list, fui->max_lines); + } else { + page_next(fui); + } w_lfl_draw(fui); break; case KEY_NPAGE: @@ -287,24 +271,25 @@ static void w_lfl_cb(w_cb_args_t *args) { open_selected_item(fui, &(args->resp_data)); break; } + dlist_reset_wp_to_st(fui->f_list, flwp); } w_lfl_ui_t *w_lfl_init(WINDOW **win, w_t *w_parent) { - w_lfl_ui_t *fl_ui = malloc(sizeof(w_lfl_ui_t)); + w_lfl_ui_t *fui = malloc(sizeof(w_lfl_ui_t)); WINDOW *win_par = *(w_parent->w_parent->parent_win); - w_init(&(fl_ui->w), w_parent, win, ""); - fl_ui->current_idx = 0; - fl_ui->win_info = NULL; - fl_ui->d_path = NULL; + w_init(&(fui->w), w_parent, win, ""); + fui->current_idx = 0; + fui->win_info = NULL; + fui->d_path = NULL; char *path = get_current_dir_name(); - get_files_from_fs(fl_ui, path); - fl_ui->current = fl_ui->start; - fl_ui->w.callback = w_lfl_cb; - fl_ui->w.sz.x = getmaxx(win_par) / 10 * 8; - fl_ui->w.sz.y = getmaxy(win_par) / 10 * 8; - fl_ui->max_lines = 0; /* detects on the first draw */ - fl_ui->cur_page = 1; - return fl_ui; + get_files_from_fs(fui, path); + fui->f_list = dlist_init(NULL, w_lfl_item_t, NULL); + fui->w.callback = w_lfl_cb; + fui->w.sz.x = getmaxx(win_par) / 10 * 8; + fui->w.sz.y = getmaxy(win_par) / 10 * 8; + fui->max_lines = 0; /* detects on the first draw */ + fui->cur_page = 1; + return fui; } static void w_lfl_cb_refresh(void *data) { @@ -349,7 +334,8 @@ static int32_t process_user_input(app_t *app, w_cb_args_t *d_args) { if (d_args->resp_data.code == cbrp_val && d_args->resp_data.val.type == val_num && d_args->resp_data.val.val.num == 1) { - file_upload_open(fui->d_path, fui->current->name, app->query_args); + file_upload_open(fui->d_path, fui->f_list->work_pointer->el_ptr, + app->query_args); app->query_args->state = S_UPLOAD_PARAMS; } return OK; @@ -366,7 +352,7 @@ w_lfl_ui_t *w_lfl_init_win(app_t *app) { app->main_ui.b_keys_len = 2; app->main_ui.cb_b_press = (w_cb_press_t)process_user_input; app->main_ui.reset = w_lfl_reset_app; - app->main_ui.draw = (draw_f_t *) w_lfl_draw; + app->main_ui.draw = (draw_f_t *)w_lfl_draw; app->active_callback = w_lfl_cb; fui->w.callback = w_lfl_cb; w_init(&(fui->w), NULL, &(app->win), ""); @@ -377,6 +363,7 @@ w_lfl_ui_t *w_lfl_init_win(app_t *app) { fui->w.sz.y = getmaxy(app->win); fui->cur_page = 1; fui->w.parent_win = &(app->win); + fui->f_list = dlist_init(NULL, w_lfl_item_t, NULL); /* * INIT UI * */ /* define the width for each sub window */ @@ -394,18 +381,17 @@ w_lfl_ui_t *w_lfl_init_win(app_t *app) { /* get files */ char *path = get_current_dir_name(); get_files_from_fs(fui, path); - fui->current = fui->start; return fui; } -void w_lfl_reset(w_lfl_ui_t *fl_ui) { - fl_ui->current_idx = 0; - lfl_clear(&(fl_ui->start), &(fl_ui->current)); +void w_lfl_reset(w_lfl_ui_t *fui) { + fui->current_idx = 0; + fl_clear(fui->f_list); } void w_lfl_reset_app(void *app) { app_t *_app = app; - w_lfl_ui_t *fl_ui = (w_lfl_ui_t *) _app->main_ui.ui; + w_lfl_ui_t *fl_ui = (w_lfl_ui_t *)_app->main_ui.ui; w_lfl_reset(fl_ui); } @@ -419,8 +405,9 @@ void w_lfl_draw(w_lfl_ui_t *fui) { p_y = 1; p_x = 1; - w_lfl_item_t *el = fui->page_start; - w_lfl_item_t *active_el = fui->page_start; + dlist_reset_wp_to_st(fui->f_list, fui->page_start); + w_lfl_item_t *el = dlist_get_ptr(fui->page_start); + w_lfl_item_t *active_el = dlist_get_ptr(fui->fl_selected); box(fui->win_list, 0, 0); box(fui->win_info, 0, 0); @@ -430,7 +417,7 @@ void w_lfl_draw(w_lfl_ui_t *fui) { p_y++; continue; } - if (el == fui->current) { + if (el == fui->fl_selected->el_ptr) { wattrset(win, A_BOLD | A_REVERSE); active_el = el; } @@ -440,11 +427,11 @@ void w_lfl_draw(w_lfl_ui_t *fui) { if (pad >= 0) { mvwprintw(win, p_y, p_x, "%*s", pad, ""); } - if (el == fui->current) { + if (el == fui->fl_selected->el_ptr) { wattroff(win, A_BOLD | A_REVERSE); } p_y++; - } while ((el = el->next) != NULL && p_y < sz_y_f); + } while ((el = dlist_it_next(fui->f_list)) != NULL && p_y < sz_y_f); p_x = 1; @@ -484,7 +471,7 @@ void w_lfl_draw(w_lfl_ui_t *fui) { void w_lfl_destroy(w_lfl_ui_t **fui) { w_lfl_ui_t *f = *fui; - lfl_clear(&(f->start), &(f->current)); + fl_clear(f->f_list); free(*fui); *fui = NULL; } \ No newline at end of file diff --git a/src/windows/fs_file_list.h b/src/windows/fs_file_list.h index cc326ff..f790d40 100644 --- a/src/windows/fs_file_list.h +++ b/src/windows/fs_file_list.h @@ -4,6 +4,7 @@ #ifndef W_LFL_H /* LOCAL FILE LIST */ #define W_LFL_H +#include "dlist.h" #include #include #include @@ -22,9 +23,6 @@ typedef struct fs_fl_item { typedef struct { w_t w; - w_lfl_item_t *current; - w_lfl_item_t *start; - w_lfl_item_t *page_start; int32_t current_idx; int32_t max_lines; int32_t cur_page; @@ -33,6 +31,9 @@ typedef struct { WINDOW *win_info; WINDOW *win_list; char *d_path; + dlist_t *f_list; + dlist_node_t *page_start; + dlist_node_t *fl_selected; } w_lfl_ui_t; void w_lfl_draw(w_lfl_ui_t *fl_ui);