Contiki 3.x
directory.c
1 /*
2  * Copyright (c) 2003, Adam Dunkels.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided
13  * with the distribution.
14  * 3. The name of the author may not be used to endorse or promote
15  * products derived from this software without specific prior
16  * written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * This file is part of the Contiki desktop environment
31  *
32  *
33  */
34 
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "contiki.h"
39 #include "cfs/cfs.h"
40 #include "ctk/ctk.h"
41 #include "ctk/ctk-draw.h"
42 
43 #include "program-handler.h"
44 
45 #define FILENAMELEN 24
46 #define MAX_NUMFILES 40
47 #define WIDTH 36
48 #define HEIGHT 22
49 
50 static char (filenames[FILENAMELEN + 1])[MAX_NUMFILES];
51 static struct dsc *dscs[MAX_NUMFILES];
52 static unsigned char numfiles, morestart, filenameptr;
53 
54 static struct ctk_window window;
55 
56 static struct ctk_label description =
57  {CTK_LABEL(0, HEIGHT - 1, WIDTH, 1, "")};
58 
59 static char autoexit = 1;
60 static struct ctk_button autoexitbutton =
61  {CTK_BUTTON(WIDTH/2 - 9, 20, 9, "Auto-exit")};
62 static char autoexiton[] = "is On ";
63 static char autoexitoff[] = "is Off";
64 static struct ctk_label autoexitlabel =
65  {CTK_LABEL(WIDTH/2 - 9 + 12, 20, 6, 1, autoexiton)};
66 
67 static struct ctk_button morebutton =
68  {CTK_BUTTON(0, 20, 4, "More")};
69 
70 static struct ctk_button backbutton =
71  {CTK_BUTTON(0, 20, 4, "Back")};
72 
73 static struct ctk_button reloadbutton =
74  {CTK_BUTTON(30, 20, 6, "Reload")};
75 
76 PROCESS(directory_process, "Directory browser");
77 
78 AUTOSTART_PROCESSES(&directory_process);
79 
80 static unsigned char width, height;
81 
82 #define LOADING_DIR 1
83 #define LOADING_DSC 2
84 static char loading = 0;
85 static struct cfs_dir dir;
86 /*-----------------------------------------------------------------------------------*/
87 static void
88 show_statustext(char *text)
89 {
90  ctk_label_set_text(&description, text);
91  CTK_WIDGET_REDRAW(&description);
92 }
93 /*-----------------------------------------------------------------------------------*/
94 static void
95 startloading(void)
96 {
97  if(cfs_opendir(&dir, "/") != 0) {
98  show_statustext("Cannot open directory");
99  loading = 0;
100  } else {
101  loading = LOADING_DIR;
102  process_post(&directory_process, PROCESS_EVENT_CONTINUE, NULL);
103  numfiles = 0;
104  }
105 }
106 /*-----------------------------------------------------------------------------------*/
107 static void
108 makewindow(unsigned char i)
109 {
110  unsigned char x, y;
111 
112  ctk_window_clear(&window);
113  CTK_WIDGET_SET_YPOS(&description, height - 3);
114  CTK_WIDGET_SET_WIDTH(&description, width);
115  CTK_WIDGET_ADD(&window, &description);
116 
117  morestart = i;
118 
119  x = 0; y = 1;
120  for(; dscs[i] != NULL; ++i) {
121 
122  if(x + strlen(dscs[i]->icon->title) >= width) {
123  y += 5;
124  x = 0;
125  if(y >= height - 2 - 4) {
126  morestart = i;
127  break;
128  }
129  }
130  CTK_WIDGET_SET_XPOS(dscs[i]->icon, x);
131  CTK_WIDGET_SET_YPOS(dscs[i]->icon, y);
132  CTK_WIDGET_ADD(&window, dscs[i]->icon);
133 
134  x += (unsigned char)strlen(dscs[i]->icon->title) + 2;
135  }
136  CTK_WIDGET_SET_YPOS(&autoexitbutton, height - 2);
137  CTK_WIDGET_ADD(&window, &autoexitbutton);
138  CTK_WIDGET_SET_YPOS(&autoexitlabel, height - 2);
139  CTK_WIDGET_ADD(&window, &autoexitlabel);
140  CTK_WIDGET_FOCUS(&window, &autoexitbutton);
141 
142  if(i != morestart) {
143  CTK_WIDGET_SET_YPOS(&backbutton, height - 1);
144  CTK_WIDGET_ADD(&window, &backbutton);
145  } else {
146  CTK_WIDGET_SET_YPOS(&morebutton, height - 1);
147  CTK_WIDGET_ADD(&window, &morebutton);
148  }
149  CTK_WIDGET_SET_XPOS(&reloadbutton, width - 8);
150  CTK_WIDGET_SET_YPOS(&reloadbutton, height - 1);
151  CTK_WIDGET_ADD(&window, &reloadbutton);
152 }
153 /*-----------------------------------------------------------------------------------*/
154 static void
155 quit(void)
156 {
157  unsigned char i;
158 
159  if(loading == LOADING_DIR) {
160  cfs_closedir(&dir);
161  }
162  ctk_window_close(&window);
163  for(i = 0; dscs[i] != NULL; ++i) {
164  LOADER_UNLOAD_DSC(dscs[i]);
165  }
166  process_exit(&directory_process);
167  LOADER_UNLOAD();
168 }
169 /*-----------------------------------------------------------------------------------*/
170 static void
171 read_dirent(void)
172 {
173  static struct cfs_dirent dirent;
174  static char message[40];
175 
176  if(loading == LOADING_DIR) {
177  if(cfs_readdir(&dir, &dirent)) {
178  cfs_closedir(&dir);
179  loading = LOADING_DSC;
180  filenameptr = 0;
181  } else if(strcasecmp(&dirent.name[strlen(dirent.name) - 4], ".dsc") == 0) {
182  strncpy(filenames[numfiles], dirent.name, FILENAMELEN);
183  ++numfiles;
184  if(numfiles == MAX_NUMFILES) {
185  cfs_closedir(&dir);
186  loading = LOADING_DSC;
187  filenameptr = 0;
188  return;
189  }
190  strcpy(message, "Found \"");
191  strcpy(message + 7, dirent.name);
192  strcpy(message + 7 + strlen(dirent.name), "\"...");
193  show_statustext(message);
194  }
195  }
196 }
197 /*-----------------------------------------------------------------------------------*/
198 static void
199 load_dirent(void)
200 {
201  static char message[40];
202  char *name;
203 
204  if(loading == LOADING_DSC) {
205 
206  name = filenames[filenameptr];
207  dscs[filenameptr] = LOADER_LOAD_DSC(name);
208  if(dscs[filenameptr] == NULL || filenameptr + 1 >= numfiles) {
209  loading = 0;
210  makewindow(0);
211  show_statustext("Directory loaded");
212  ctk_window_redraw(&window);
213  return;
214  }
215  ++filenameptr;
216  strcpy(message, "Loading \"");
217  strcpy(message + 9, name);
218  strcpy(message + 9 + strlen(name), "\"...");
219  show_statustext(message);
220  }
221 }
222 /*-----------------------------------------------------------------------------------*/
223 PROCESS_THREAD(directory_process, ev, data)
224 {
225  unsigned char i;
226 
227  PROCESS_BEGIN();
228 
229  width = ctk_draw_width() - 2;
230  height = ctk_draw_height() - 2 - CTK_CONF_MENUS;
231 
232  ctk_window_new(&window, width, height, "Directory");
233 
234  /* loaddirectory();*/
235  makewindow(0);
236  show_statustext("Loading directory...");
237  startloading();
238 
239  ctk_window_open(&window);
240 
241  while(1) {
243  if(ev == PROCESS_EVENT_CONTINUE) {
244  read_dirent();
245  load_dirent();
246  if(loading != 0) {
247  process_post(&directory_process, PROCESS_EVENT_CONTINUE, NULL);
248  }
249  } else if(ev == ctk_signal_widget_activate) {
250  if(data == (process_data_t)&reloadbutton) {
251  for(i = 0; dscs[i] != NULL; ++i) {
252  LOADER_UNLOAD_DSC(dscs[i]);
253  dscs[i] = NULL;
254  }
255  /* loaddirectory();*/
256  startloading();
257  makewindow(0);
258  ctk_window_open(&window);
259  } else if(data == (process_data_t)&morebutton) {
260  makewindow(morestart);
261  ctk_window_open(&window);
262  } else if(data == (process_data_t)&backbutton) {
263  makewindow(0);
264  ctk_window_open(&window);
265  } else if(data == (process_data_t)&autoexitbutton) {
266  autoexit = 1 - autoexit;
267  if(autoexit == 1) {
268  ctk_label_set_text(&autoexitlabel, autoexiton);
269  } else {
270  ctk_label_set_text(&autoexitlabel, autoexitoff);
271  }
272  CTK_WIDGET_REDRAW(&autoexitlabel);
273  } else {
274  for(i = 0; dscs[i] != NULL; ++i) {
275  if(data == (process_data_t)(dscs[i]->icon)) {
276  program_handler_load(dscs[i]->prgname, NULL);
277  if(autoexit) {
278  ctk_window_close(&window);
279  quit();
280  }
281  break;
282  }
283  }
284  }
285  } else if(ev == ctk_signal_widget_select) {
286  if(data == (process_data_t)&reloadbutton) {
287  show_statustext("Reload directory");
288  } else if(data == (process_data_t)&morebutton) {
289  show_statustext("Show more files");
290  } else if(data == (process_data_t)&backbutton) {
291  show_statustext("Show first files");
292  } else if(data == (process_data_t)&autoexitbutton) {
293  show_statustext("Exit when loading program");
294  } else {
295  for(i = 0; dscs[i] != NULL; ++i) {
296  if(data == (process_data_t)(dscs[i]->icon)) {
297  show_statustext(dscs[i]->description);
298  break;
299  }
300  }
301  }
302  } else if(ev == ctk_signal_window_close &&
303  data == (process_data_t)&window) {
304  quit();
305  } else if(ev == PROCESS_EVENT_EXIT) {
306  ctk_window_close(&window);
307  quit();
308  }
309  }
310  PROCESS_END();
311 }
312 /*-----------------------------------------------------------------------------------*/
#define CTK_WIDGET_ADD(win, widg)
Add a widget to a window.
Definition: ctk.h:752
process_event_t ctk_signal_window_close
Emitted when a window is closed.
Definition: ctk.c:155
void ctk_window_open(CC_REGISTER_ARG struct ctk_window *w)
Open a window, or bring window to front if already open.
Definition: ctk.c:347
#define CTK_WIDGET_FOCUS(win, widg)
Set focus to a widget.
Definition: ctk.h:763
void ctk_window_close(struct ctk_window *w)
Close a window if it is open.
Definition: ctk.c:400
process_event_t ctk_signal_widget_select
Emitted when a widget is selected.
Definition: ctk.c:126
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define LOADER_LOAD_DSC(name)
Load a DSC (program description).
Definition: loader.h:116
#define ctk_label_set_text(l, t)
Set the text of a label.
Definition: ctk.h:849
#define NULL
The null pointer.
void ctk_window_redraw(struct ctk_window *w)
Redraw a window.
Definition: ctk.c:652
#define CTK_WIDGET_SET_WIDTH(widget, width)
Sets the width of a widget.
Definition: ctk.h:789
int cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record)
Read a directory entry.
Definition: cfs-coffee.c:1264
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
#define CTK_LABEL(x, y, w, h, text)
Instantiating macro for the ctk_label widget.
Definition: ctk.h:171
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
The DSC program description structure.
Definition: dsc.h:75
void ctk_window_new(struct ctk_window *window, unsigned char w, unsigned char h, char *title)
Create a new window.
Definition: ctk.c:732
#define CTK_WIDGET_SET_XPOS(w, xpos)
Sets the x position of a widget, relative to the window in which the widget is contained.
Definition: ctk.h:808
#define LOADER_UNLOAD()
Unload a program from memory.
Definition: loader.h:104
void cfs_closedir(struct cfs_dir *dir)
Close a directory opened with cfs_opendir().
Definition: cfs-coffee.c:1290
void ctk_window_clear(struct ctk_window *w)
Remove all widgets from a window.
Definition: ctk.c:485
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition: process.h:141
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
process_event_t ctk_signal_widget_activate
Emitted when a widget is activated (pressed).
Definition: ctk.c:126
int cfs_opendir(struct cfs_dir *dir, const char *name)
Open a directory for reading directory entries.
Definition: cfs-coffee.c:1253
CTK screen drawing module interface, ctk-draw.
#define CTK_BUTTON(x, y, w, text)
Instantiating macro for the ctk_button widget.
Definition: ctk.h:140
Representation of a CTK window.
Definition: ctk.h:506
#define CTK_WIDGET_SET_YPOS(w, ypos)
Sets the y position of a widget, relative to the window in which the widget is contained.
Definition: ctk.h:826
#define CTK_WIDGET_REDRAW(widg)
Add a widget to the redraw queue.
Definition: ctk.h:771
#define LOADER_UNLOAD_DSC(dsc)
Unload a DSC (program description).
Definition: loader.h:126
void program_handler_load(char *name, char *arg)
Loads a program and displays a dialog telling the user about it.
CTK header file.
void process_exit(struct process *p)
Cause a process to exit.
Definition: process.c:202
CFS header file.