HelenOS sources
This source file includes following definitions.
- ui_file_list_create
- ui_file_list_destroy
- ui_file_list_set_cb
- ui_file_list_ctl
- ui_file_list_set_rect
- ui_file_list_is_active
- ui_file_list_activate
- ui_file_list_deactivate
- ui_file_list_entry_attr_init
- ui_file_list_entry_append
- ui_file_list_entry_destroy
- ui_file_list_clear_entries
- ui_file_list_read_dir
- ui_file_list_sort
- ui_file_list_list_compare
- ui_file_list_first
- ui_file_list_last
- ui_file_list_next
- ui_file_list_prev
- ui_file_list_get_cursor
- ui_file_list_open
- ui_file_list_open_dir
- ui_file_list_open_file
- ui_file_list_activate_req
- ui_file_list_selected
- ui_file_list_paint
- ui_file_list_ctl_destroy
- ui_file_list_ctl_paint
- ui_file_list_ctl_kbd_event
- ui_file_list_ctl_pos_event
- ui_file_list_list_activate_req
- ui_file_list_list_selected
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <str.h>
#include <ui/control.h>
#include <ui/filelist.h>
#include <ui/list.h>
#include <ui/resource.h>
#include <vfs/vfs.h>
#include <qsort.h>
#include "../private/filelist.h"
#include "../private/list.h"
#include "../private/resource.h"
static void ui_file_list_ctl_destroy(void *);
static errno_t ui_file_list_ctl_paint(void *);
static ui_evclaim_t ui_file_list_ctl_kbd_event(void *, kbd_event_t *);
static ui_evclaim_t ui_file_list_ctl_pos_event(void *, pos_event_t *);
ui_control_ops_t ui_file_list_ctl_ops = {
.destroy = ui_file_list_ctl_destroy,
.paint = ui_file_list_ctl_paint,
.kbd_event = ui_file_list_ctl_kbd_event,
.pos_event = ui_file_list_ctl_pos_event
};
static void ui_file_list_list_activate_req(ui_list_t *, void *);
static void ui_file_list_list_selected(ui_list_entry_t *, void *);
ui_list_cb_t ui_file_list_list_cb = {
.activate_req = ui_file_list_list_activate_req,
.selected = ui_file_list_list_selected,
.compare = ui_file_list_list_compare,
};
errno_t ui_file_list_create(ui_window_t *window, bool active,
ui_file_list_t **rflist)
{
ui_file_list_t *flist;
errno_t rc;
flist = calloc(1, sizeof(ui_file_list_t));
if (flist == NULL)
return ENOMEM;
rc = ui_control_new(&ui_file_list_ctl_ops, (void *)flist,
&flist->control);
if (rc != EOK)
goto error;
rc = gfx_color_new_ega(0x0f, &flist->dir_color);
if (rc != EOK)
goto error;
rc = gfx_color_new_ega(0x0a, &flist->svc_color);
if (rc != EOK)
goto error;
rc = ui_list_create(window, active, &flist->list);
if (rc != EOK)
goto error;
ui_list_set_cb(flist->list, &ui_file_list_list_cb, (void *)flist);
flist->window = window;
*rflist = flist;
return EOK;
error:
ui_control_delete(flist->control);
if (flist->dir_color != NULL)
gfx_color_delete(flist->dir_color);
if (flist->svc_color != NULL)
gfx_color_delete(flist->svc_color);
free(flist);
return rc;
}
void ui_file_list_destroy(ui_file_list_t *flist)
{
ui_file_list_clear_entries(flist);
ui_list_destroy(flist->list);
ui_control_delete(flist->control);
free(flist);
}
void ui_file_list_set_cb(ui_file_list_t *flist, ui_file_list_cb_t *cb, void *arg)
{
flist->cb = cb;
flist->cb_arg = arg;
}
ui_control_t *ui_file_list_ctl(ui_file_list_t *flist)
{
return flist->control;
}
void ui_file_list_set_rect(ui_file_list_t *flist, gfx_rect_t *rect)
{
ui_list_set_rect(flist->list, rect);
}
bool ui_file_list_is_active(ui_file_list_t *flist)
{
return ui_list_is_active(flist->list);
}
errno_t ui_file_list_activate(ui_file_list_t *flist)
{
errno_t rc;
if (flist->dir != NULL) {
rc = vfs_cwd_set(flist->dir);
if (rc != EOK)
return rc;
}
return ui_list_activate(flist->list);
}
void ui_file_list_deactivate(ui_file_list_t *flist)
{
ui_list_deactivate(flist->list);
}
void ui_file_list_entry_attr_init(ui_file_list_entry_attr_t *attr)
{
memset(attr, 0, sizeof(*attr));
}
errno_t ui_file_list_entry_append(ui_file_list_t *flist, ui_file_list_entry_attr_t *attr)
{
ui_file_list_entry_t *entry;
ui_list_entry_attr_t lattr;
ui_list_entry_t *lentry;
ui_resource_t *res;
char *caption;
errno_t rc;
int rv;
res = ui_window_get_res(flist->window);
entry = calloc(1, sizeof(ui_file_list_entry_t));
if (entry == NULL)
return ENOMEM;
entry->flist = flist;
entry->name = str_dup(attr->name);
if (entry->name == NULL) {
free(entry);
return ENOMEM;
}
entry->size = attr->size;
entry->isdir = attr->isdir;
entry->svc = attr->svc;
if (attr->isdir && !res->textmode) {
rv = asprintf(&caption, "[%s]", attr->name);
if (rv < 0)
caption = NULL;
} else {
caption = str_dup(attr->name);
}
if (caption == NULL) {
free(entry->name);
free(entry);
return ENOMEM;
}
lattr.caption = caption;
lattr.arg = (void *)entry;
lattr.color = NULL;
lattr.bgcolor = NULL;
if (res->textmode) {
if (attr->isdir) {
lattr.color = flist->dir_color;
lattr.bgcolor = flist->dir_color;
} else if (attr->svc != 0) {
lattr.color = flist->svc_color;
lattr.bgcolor = flist->svc_color;
}
}
rc = ui_list_entry_append(flist->list, &lattr, &lentry);
if (rc != EOK) {
free(caption);
free(entry->name);
free(entry);
return rc;
}
free(caption);
entry->entry = lentry;
return EOK;
}
void ui_file_list_entry_destroy(ui_file_list_entry_t *entry)
{
ui_list_entry_destroy(entry->entry);
free(entry->name);
free(entry);
}
void ui_file_list_clear_entries(ui_file_list_t *flist)
{
ui_file_list_entry_t *entry;
entry = ui_file_list_first(flist);
while (entry != NULL) {
ui_file_list_entry_destroy(entry);
entry = ui_file_list_first(flist);
}
}
errno_t ui_file_list_read_dir(ui_file_list_t *flist, const char *dirname)
{
DIR *dir;
struct dirent *dirent;
vfs_stat_t finfo;
char newdir[256];
char *ndir = NULL;
ui_file_list_entry_attr_t attr;
ui_file_list_entry_t *cur;
ui_file_list_entry_t *next;
char *olddn;
errno_t rc;
rc = vfs_cwd_set(dirname);
if (rc != EOK)
return rc;
rc = vfs_cwd_get(newdir, sizeof(newdir));
if (rc != EOK)
return rc;
ndir = str_dup(newdir);
if (ndir == NULL)
return ENOMEM;
dir = opendir(".");
if (dir == NULL) {
rc = errno;
goto error;
}
if (str_cmp(ndir, "/") != 0) {
ui_file_list_entry_attr_init(&attr);
attr.name = "..";
attr.isdir = true;
rc = ui_file_list_entry_append(flist, &attr);
if (rc != EOK)
goto error;
}
dirent = readdir(dir);
while (dirent != NULL) {
rc = vfs_stat_path(dirent->d_name, &finfo);
if (rc != EOK) {
dirent = readdir(dir);
continue;
}
ui_file_list_entry_attr_init(&attr);
attr.name = dirent->d_name;
attr.size = finfo.size;
attr.isdir = finfo.is_directory;
attr.svc = finfo.service;
rc = ui_file_list_entry_append(flist, &attr);
if (rc != EOK)
goto error;
dirent = readdir(dir);
}
closedir(dir);
rc = ui_file_list_sort(flist);
if (rc != EOK)
goto error;
if (str_cmp(dirname, "..") == 0) {
olddn = str_rchr(flist->dir, '/');
if (olddn != NULL && *olddn != '\0') {
++olddn;
cur = ui_file_list_first(flist);
next = ui_file_list_next(cur);
while (next != NULL && str_cmp(next->name, olddn) <= 0 &&
next->isdir) {
cur = next;
next = ui_file_list_next(cur);
}
ui_list_cursor_center(flist->list, cur->entry);
}
}
free(flist->dir);
flist->dir = ndir;
return EOK;
error:
(void) vfs_cwd_set(flist->dir);
if (ndir != NULL)
free(ndir);
if (dir != NULL)
closedir(dir);
return rc;
}
errno_t ui_file_list_sort(ui_file_list_t *flist)
{
return ui_list_sort(flist->list);
}
int ui_file_list_list_compare(ui_list_entry_t *ea, ui_list_entry_t *eb)
{
ui_file_list_entry_t *a;
ui_file_list_entry_t *b;
int dcmp;
a = (ui_file_list_entry_t *)ui_list_entry_get_arg(ea);
b = (ui_file_list_entry_t *)ui_list_entry_get_arg(eb);
dcmp = b->isdir - a->isdir;
if (dcmp != 0)
return dcmp;
return str_cmp(a->name, b->name);
}
ui_file_list_entry_t *ui_file_list_first(ui_file_list_t *flist)
{
ui_list_entry_t *lentry;
lentry = ui_list_first(flist->list);
if (lentry == NULL)
return NULL;
return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
}
ui_file_list_entry_t *ui_file_list_last(ui_file_list_t *flist)
{
ui_list_entry_t *lentry;
lentry = ui_list_last(flist->list);
if (lentry == NULL)
return NULL;
return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
}
ui_file_list_entry_t *ui_file_list_next(ui_file_list_entry_t *cur)
{
ui_list_entry_t *lentry;
lentry = ui_list_next(cur->entry);
if (lentry == NULL)
return NULL;
return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
}
ui_file_list_entry_t *ui_file_list_prev(ui_file_list_entry_t *cur)
{
ui_list_entry_t *lentry;
lentry = ui_list_prev(cur->entry);
if (lentry == NULL)
return NULL;
return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
}
ui_file_list_entry_t *ui_file_list_get_cursor(ui_file_list_t *flist)
{
ui_list_entry_t *entry;
entry = ui_list_get_cursor(flist->list);
if (entry == NULL)
return NULL;
return (ui_file_list_entry_t *)ui_list_entry_get_arg(entry);
}
errno_t ui_file_list_open(ui_file_list_t *flist, ui_file_list_entry_t *entry)
{
if (entry->isdir)
return ui_file_list_open_dir(flist, entry);
else if (entry->svc == 0)
return ui_file_list_open_file(flist, entry);
else
return EOK;
}
errno_t ui_file_list_open_dir(ui_file_list_t *flist,
ui_file_list_entry_t *entry)
{
char *dirname;
errno_t rc;
assert(entry->isdir);
dirname = str_dup(entry->name);
if (dirname == NULL)
return ENOMEM;
ui_file_list_clear_entries(flist);
rc = ui_file_list_read_dir(flist, dirname);
if (rc != EOK) {
free(dirname);
return rc;
}
free(dirname);
rc = ui_file_list_paint(flist);
if (rc != EOK)
return rc;
return EOK;
}
errno_t ui_file_list_open_file(ui_file_list_t *flist,
ui_file_list_entry_t *entry)
{
ui_file_list_selected(flist, entry->name);
return EOK;
}
void ui_file_list_activate_req(ui_file_list_t *flist)
{
if (flist->cb != NULL && flist->cb->activate_req != NULL)
flist->cb->activate_req(flist, flist->cb_arg);
}
void ui_file_list_selected(ui_file_list_t *flist, const char *fname)
{
if (flist->cb != NULL && flist->cb->selected != NULL)
flist->cb->selected(flist, flist->cb_arg, fname);
}
errno_t ui_file_list_paint(ui_file_list_t *flist)
{
return ui_control_paint(ui_list_ctl(flist->list));
}
void ui_file_list_ctl_destroy(void *arg)
{
ui_file_list_t *flist = (ui_file_list_t *) arg;
ui_file_list_destroy(flist);
}
errno_t ui_file_list_ctl_paint(void *arg)
{
ui_file_list_t *flist = (ui_file_list_t *) arg;
return ui_file_list_paint(flist);
}
ui_evclaim_t ui_file_list_ctl_kbd_event(void *arg, kbd_event_t *event)
{
ui_file_list_t *flist = (ui_file_list_t *) arg;
return ui_control_kbd_event(ui_list_ctl(flist->list), event);
}
ui_evclaim_t ui_file_list_ctl_pos_event(void *arg, pos_event_t *event)
{
ui_file_list_t *flist = (ui_file_list_t *) arg;
return ui_control_pos_event(ui_list_ctl(flist->list), event);
}
static void ui_file_list_list_activate_req(ui_list_t *list, void *arg)
{
ui_file_list_t *flist = (ui_file_list_t *)arg;
ui_file_list_activate_req(flist);
}
static void ui_file_list_list_selected(ui_list_entry_t *entry, void *arg)
{
ui_file_list_entry_t *fentry = (void *)arg;
(void) ui_file_list_open(fentry->flist, fentry);
}
HelenOS homepage, sources at GitHub