blob: 62b4f25519eaa59089aa8fd3a86c73c1e3c55e05 [file] [log] [blame]
/*
* Copyright (c) 2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This file is part of the Contiki desktop environment
*
* $Id: directory.c,v 1.3 2006/05/24 19:34:39 oliverschmidt Exp $
*
*/
#include <stdlib.h>
#include <string.h>
#include "ctk.h"
#include "ctk-draw.h"
#include "ek.h"
#include "loader.h"
#include "cfs.h"
#include "program-handler.h"
#define FILENAMELEN 24
#define MAX_NUMFILES 40
#define WIDTH 36
#define HEIGHT 22
static char (filenames[FILENAMELEN + 1])[MAX_NUMFILES];
static struct dsc *dscs[MAX_NUMFILES];
static unsigned char numfiles, morestart, filenameptr;
static struct ctk_window window;
static struct ctk_label description =
{CTK_LABEL(0, HEIGHT - 1, WIDTH, 1, "")};
static char autoexit = 1;
static struct ctk_button autoexitbutton =
{CTK_BUTTON(WIDTH/2 - 9, 20, 9, "Auto-exit")};
static char autoexiton[] = "is On ";
static char autoexitoff[] = "is Off";
static struct ctk_label autoexitlabel =
{CTK_LABEL(WIDTH/2 - 9 + 12, 20, 6, 1, autoexiton)};
static struct ctk_button morebutton =
{CTK_BUTTON(0, 20, 4, "More")};
static struct ctk_button backbutton =
{CTK_BUTTON(0, 20, 4, "Back")};
static struct ctk_button reloadbutton =
{CTK_BUTTON(30, 20, 6, "Reload")};
EK_EVENTHANDLER(directory_eventhandler, ev, data);
EK_PROCESS(p, "Directory browser", EK_PRIO_NORMAL,
directory_eventhandler, NULL, NULL);
static ek_id_t id = EK_ID_NONE;
static unsigned char width, height;
#define LOADING_DIR 1
#define LOADING_DSC 2
static char loading = 0;
static struct cfs_dir dir;
/*-----------------------------------------------------------------------------------*/
static void
show_statustext(char *text)
{
ctk_label_set_text(&description, text);
CTK_WIDGET_REDRAW(&description);
}
/*-----------------------------------------------------------------------------------*/
static void
startloading(void)
{
if(cfs_opendir(&dir, "/") != 0) {
show_statustext("Cannot open directory");
loading = 0;
} else {
loading = LOADING_DIR;
ek_post(id, EK_EVENT_CONTINUE, NULL);
numfiles = 0;
}
}
/*-----------------------------------------------------------------------------------*/
static void
makewindow(unsigned char i)
{
unsigned char x, y;
ctk_window_clear(&window);
CTK_WIDGET_SET_YPOS(&description, height - 3);
CTK_WIDGET_SET_WIDTH(&description, width);
CTK_WIDGET_ADD(&window, &description);
morestart = i;
x = 0; y = 1;
for(; dscs[i] != NULL; ++i) {
if(x + strlen(dscs[i]->icon->title) >= width) {
y += 5;
x = 0;
if(y >= height - 2 - 4) {
morestart = i;
break;
}
}
CTK_WIDGET_SET_XPOS(dscs[i]->icon, x);
CTK_WIDGET_SET_YPOS(dscs[i]->icon, y);
CTK_WIDGET_ADD(&window, dscs[i]->icon);
x += strlen(dscs[i]->icon->title) + 2;
}
CTK_WIDGET_SET_YPOS(&autoexitbutton, height - 2);
CTK_WIDGET_ADD(&window, &autoexitbutton);
CTK_WIDGET_SET_YPOS(&autoexitlabel, height - 2);
CTK_WIDGET_ADD(&window, &autoexitlabel);
CTK_WIDGET_FOCUS(&window, &autoexitbutton);
if(i != morestart) {
CTK_WIDGET_SET_YPOS(&backbutton, height - 1);
CTK_WIDGET_ADD(&window, &backbutton);
} else {
CTK_WIDGET_SET_YPOS(&morebutton, height - 1);
CTK_WIDGET_ADD(&window, &morebutton);
}
CTK_WIDGET_SET_XPOS(&reloadbutton, width - 8);
CTK_WIDGET_SET_YPOS(&reloadbutton, height - 1);
CTK_WIDGET_ADD(&window, &reloadbutton);
}
/*-----------------------------------------------------------------------------------*/
LOADER_INIT_FUNC(directory_init, arg)
{
arg_free(arg);
if(id == EK_ID_NONE) {
id = ek_start(&p);
width = ctk_draw_width() - 2;
height = ctk_draw_height() - 3;
}
}
/*-----------------------------------------------------------------------------------*/
static void
quit(void)
{
unsigned char i;
if(loading == LOADING_DIR) {
cfs_closedir(&dir);
}
ctk_window_close(&window);
for(i = 0; dscs[i] != NULL; ++i) {
LOADER_UNLOAD_DSC(dscs[i]);
}
ek_exit();
id = EK_ID_NONE;
LOADER_UNLOAD();
}
/*-----------------------------------------------------------------------------------*/
static void
read_dirent(void)
{
static struct cfs_dirent dirent;
static char message[40];
if(loading == LOADING_DIR) {
if(cfs_readdir(&dir, &dirent)) {
cfs_closedir(&dir);
loading = LOADING_DSC;
filenameptr = 0;
} else if(strcasecmp(&dirent.name[strlen(dirent.name) - 4], ".dsc") == 0) {
strncpy(filenames[numfiles], dirent.name, FILENAMELEN);
++numfiles;
if(numfiles == MAX_NUMFILES) {
cfs_closedir(&dir);
loading = LOADING_DSC;
filenameptr = 0;
return;
}
strcpy(message, "Found \"");
strcpy(message + 7, dirent.name);
strcpy(message + 7 + strlen(dirent.name), "\"...");
show_statustext(message);
}
}
}
/*-----------------------------------------------------------------------------------*/
static void
load_dirent(void)
{
static char message[40];
char *name;
if(loading == LOADING_DSC) {
name = filenames[filenameptr];
dscs[filenameptr] = LOADER_LOAD_DSC(name);
if(dscs[filenameptr] == NULL || filenameptr + 1 >= numfiles) {
loading = 0;
makewindow(0);
show_statustext("Directory loaded");
ctk_window_redraw(&window);
return;
}
++filenameptr;
strcpy(message, "Loading \"");
strcpy(message + 9, name);
strcpy(message + 9 + strlen(name), "\"...");
show_statustext(message);
}
}
/*-----------------------------------------------------------------------------------*/
EK_EVENTHANDLER(directory_eventhandler, ev, data)
{
unsigned char i;
EK_EVENTHANDLER_ARGS(ev, data);
if(ev == EK_EVENT_INIT) {
ctk_window_new(&window, width, height, "Directory");
/* loaddirectory();*/
makewindow(0);
show_statustext("Loading directory...");
startloading();
ctk_window_open(&window);
} else if(ev == EK_EVENT_CONTINUE) {
read_dirent();
load_dirent();
if(loading != 0) {
ek_post(id, EK_EVENT_CONTINUE, NULL);
}
} else if(ev == ctk_signal_widget_activate) {
if(data == (ek_data_t)&reloadbutton) {
for(i = 0; dscs[i] != NULL; ++i) {
LOADER_UNLOAD_DSC(dscs[i]);
dscs[i] = NULL;
}
/* loaddirectory();*/
startloading();
makewindow(0);
ctk_window_open(&window);
} else if(data == (ek_data_t)&morebutton) {
makewindow(morestart);
ctk_window_open(&window);
} else if(data == (ek_data_t)&backbutton) {
makewindow(0);
ctk_window_open(&window);
} else if(data == (ek_data_t)&autoexitbutton) {
autoexit = 1 - autoexit;
if(autoexit == 1) {
ctk_label_set_text(&autoexitlabel, autoexiton);
} else {
ctk_label_set_text(&autoexitlabel, autoexitoff);
}
CTK_WIDGET_REDRAW(&autoexitlabel);
} else {
for(i = 0; dscs[i] != NULL; ++i) {
if(data == (ek_data_t)(dscs[i]->icon)) {
program_handler_load(dscs[i]->prgname, NULL);
if(autoexit) {
ctk_window_close(&window);
quit();
}
break;
}
}
}
} else if(ev == ctk_signal_widget_select) {
if(data == (ek_data_t)&reloadbutton) {
show_statustext("Reload directory");
} else if(data == (ek_data_t)&morebutton) {
show_statustext("Show more files");
} else if(data == (ek_data_t)&backbutton) {
show_statustext("Show first files");
} else if(data == (ek_data_t)&autoexitbutton) {
show_statustext("Exit when loading program");
} else {
for(i = 0; dscs[i] != NULL; ++i) {
if(data == (ek_data_t)(dscs[i]->icon)) {
show_statustext(dscs[i]->description);
break;
}
}
}
} else if(ev == ctk_signal_window_close &&
data == (ek_data_t)&window) {
quit();
} else if(ev == EK_EVENT_REQUEST_EXIT) {
ctk_window_close(&window);
quit();
}
}
/*-----------------------------------------------------------------------------------*/