summaryrefslogtreecommitdiff
path: root/source/gui.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/gui.c')
-rw-r--r--source/gui.c428
1 files changed, 427 insertions, 1 deletions
diff --git a/source/gui.c b/source/gui.c
index 713ad02..7e55b97 100644
--- a/source/gui.c
+++ b/source/gui.c
@@ -20,10 +20,160 @@
$Id$
*/
-#include <nds.h>
+#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
+#include <nds.h>
+
+#include <sys/dir.h>
#include "framebuffer.h"
+#include "config.h"
+
+
+/* ---------------------------------------- PRIVATE INTERFACES - PATH HANDLING
+*/
+#define FSEL_FILENAME_LEN 20
+#define FSEL_LINES 15
+#define FSEL_MAX_FILES 512
+
+#define FSEL_LIST_Y 12
+#define FSEL_LIST_H FSEL_LINES*8
+
+typedef struct
+{
+ char name[FSEL_FILENAME_LEN+1];
+ int is_dir;
+ int size;
+} FSEL_File;
+
+static FSEL_File fsel[FSEL_MAX_FILES];
+
+
+static void CheckPath(char *path)
+{
+ size_t l;
+
+ l = strlen(path);
+
+ if (l == 1)
+ {
+ path[0] = '/';
+ }
+ else
+ {
+ if (path[l-1] != '/')
+ {
+ path[l] = '/';
+ path[l+1] = 0;
+ }
+ }
+}
+
+
+static void AddPath(char *path, const char *dir)
+{
+ if (strcmp(dir,"..") == 0)
+ {
+ char *p;
+
+ p = strrchr(path,'/');
+
+ if (p && p!=path)
+ {
+ *p = 0;
+ }
+ }
+ else
+ {
+ strcat(path,dir);
+ strcat(path,"/");
+ }
+}
+
+
+
+
+static int SortFiles(const void *a, const void *b)
+{
+ const FSEL_File *f1;
+ const FSEL_File *f2;
+
+ f1 = (const FSEL_File *)a;
+ f2 = (const FSEL_File *)b;
+
+ if (f1->is_dir == f1->is_dir)
+ {
+ return strcmp(f1->name, f2->name);
+ }
+ else if (f1->is_dir)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+
+static int ValidFilename(const char *name, int is_dir, const char *filter)
+{
+ size_t l;
+ size_t f;
+
+ l = strlen(name);
+
+ if (l > FSEL_FILENAME_LEN)
+ return 0;
+
+ if (strcmp(name,".") == 0)
+ return 0;
+
+ if (is_dir || !filter)
+ return 1;
+
+ f = strlen(filter);
+
+ if (l > f)
+ {
+ if (strcmp(name+l-f,filter) == 0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int LoadDir(const char *path, const char *filter)
+{
+ DIR_ITER *dir;
+ struct stat st;
+ char name[FILENAME_MAX];
+ int no = 0;
+
+ if ((dir = diropen(path)))
+ {
+ while(no < FSEL_MAX_FILES && dirnext(dir,name,&st) == 0)
+ {
+ if (ValidFilename(name, (st.st_mode & S_IFDIR), filter))
+ {
+ strcpy(fsel[no].name,name);
+ fsel[no].is_dir = (st.st_mode & S_IFDIR);
+ fsel[no].size = (int)st.st_size;
+ no++;
+ }
+ }
+
+ dirclose(dir);
+
+ qsort(fsel,no,sizeof fsel[0],SortFiles);
+ }
+
+ return no;
+}
/* ---------------------------------------- PUBLIC INTERFACES
@@ -189,3 +339,279 @@ void GUI_Alert(int fatal, const char *text)
}
}
}
+
+
+void GUI_Config(void)
+{
+ int sel;
+ DS81_ConfigItem f;
+ bool done;
+ bool save;
+
+ sel = 0;
+ done = false;
+ save = false;
+
+ FB_Clear();
+
+ FB_Centre("Up/Down to select",140,FB_RGB(31,31,0),-1);
+ FB_Centre("A to toggle",150,FB_RGB(31,31,0),-1);
+ FB_Centre("Or use touchscreen",160,FB_RGB(31,31,0),-1);
+ FB_Centre("START to finish",170,FB_RGB(31,31,0),-1);
+
+#ifndef DS81_DISABLE_FAT
+ FB_Centre("SELECT to save to \\DS81.CFG",180,FB_RGB(31,31,0),-1);
+#endif
+
+ for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++)
+ {
+ FB_Print(ConfigDesc(f),14,20+f*14,FB_RGB(31,31,31),-1);
+ }
+
+ while(!done)
+ {
+ uint32 key=0;
+
+ for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++)
+ {
+ FB_FillBox(2,20+f*14-1,10,10,
+ DS81_Config[f] ? FB_RGB(31,31,31):FB_RGB(0,0,0));
+
+ FB_Box(2,20+f*14-1,10,10,FB_RGB(18,18,18));
+ }
+
+ FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(18,18,31));
+
+ do
+ {
+ swiWaitForVBlank();
+ } while(!(key=keysDownRepeat()));
+
+ FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(0,0,0));
+
+ if (key & KEY_START)
+ {
+ done=true;
+ }
+#ifndef DS81_DISABLE_FAT
+ else if (key & KEY_SELECT)
+ {
+ done=true;
+ save=true;
+ }
+#endif
+ else if (key & KEY_A)
+ {
+ DS81_Config[sel] = !DS81_Config[sel];
+ }
+ else if ((key & KEY_UP) && sel)
+ {
+ sel--;
+ }
+ else if ((key & KEY_DOWN) && sel<DS81_NUM_CONFIG_ITEMS-1)
+ {
+ sel++;
+ }
+ else if (key & KEY_TOUCH)
+ {
+ touchPosition tp = touchReadXY();
+ int nsel;
+
+ nsel = (tp.py-18)/14;
+
+ if (nsel>=0 && nsel<DS81_NUM_CONFIG_ITEMS)
+ {
+ sel = nsel;
+ DS81_Config[sel] = !DS81_Config[sel];
+ }
+ }
+ }
+
+ if (save)
+ {
+ SaveConfig();
+ }
+}
+
+
+bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter)
+{
+ int no;
+ int sel;
+ int top;
+ int bar_size;
+ double bar_step;
+ bool done;
+ bool ret;
+ int pen;
+ int paper;
+ int off;
+ int f;
+
+ CheckPath(pwd);
+
+ FB_Clear();
+
+ FB_printf(0,0,FB_RGB(0,0,0),FB_RGB(22,22,22),"%-31.31s",pwd);
+
+ no = LoadDir(pwd,filter);
+
+ sel = 0;
+ top = 0;
+ done = false;
+ ret = false;
+
+ if (no<=FSEL_LINES)
+ {
+ bar_step = 0;
+ bar_size = FSEL_LIST_H;
+ }
+ else
+ {
+ bar_step = FSEL_LIST_H/(double)no;
+ bar_size = bar_step*FSEL_LINES;
+ }
+
+ while(!done)
+ {
+ uint32 key=0;
+
+ for (f=0;f<FSEL_LINES;f++)
+ {
+ off = f + top;
+
+ if (off<no)
+ {
+ if (off == sel)
+ {
+ pen = FB_RGB(0,0,0);
+ paper = FB_RGB(31,31,31);
+ }
+ else
+ {
+ pen = FB_RGB(31,31,31);
+ paper = FB_RGB(0,0,0);
+ }
+
+ FB_printf(8,FSEL_LIST_Y+f*8,pen,paper,
+ "%-*s %s",
+ FSEL_FILENAME_LEN,
+ fsel[off].name,
+ fsel[off].is_dir ? "DIR" : " ");
+ }
+ else
+ {
+ FB_printf(8,FSEL_LIST_Y+f*8,FB_RGB(31,31,31),FB_RGB(0,0,0),
+ "%-*s %s",
+ FSEL_FILENAME_LEN,
+ off==0 ? "No Files!" : "",
+ "");
+ }
+ }
+
+ FB_FillBox(240,FSEL_LIST_Y,16,FSEL_LIST_H,FB_RGB(10,10,10));
+ FB_FillBox(240,FSEL_LIST_Y+top*bar_step,16,bar_size,FB_RGB(31,31,31));
+
+ do
+ {
+ swiWaitForVBlank();
+ } while(!(key=keysDownRepeat()));
+
+ if (key & KEY_UP)
+ {
+ if (sel)
+ {
+ sel--;
+
+ if (sel<top)
+ {
+ top--;
+ }
+ }
+ }
+ else if (key & KEY_DOWN)
+ {
+ if (sel < (no-1))
+ {
+ sel++;
+
+ if (sel >= (top+FSEL_LINES))
+ {
+ top++;
+ }
+ }
+ }
+ else if (key & KEY_L)
+ {
+ if (sel)
+ {
+ sel-=FSEL_LINES;
+
+ if (sel < 0)
+ {
+ sel = 0;
+ }
+
+ top = sel;
+ }
+ }
+ else if (key & KEY_R)
+ {
+ if (sel < (no-1))
+ {
+ sel+=FSEL_LINES;
+
+ if (sel > (no-1))
+ {
+ sel = no-1;
+ }
+
+ top = sel - FSEL_LINES + 1;
+
+ if (top < 0)
+ {
+ top = 0;
+ }
+ }
+ }
+ else if (key & KEY_A)
+ {
+ if (fsel[sel].is_dir)
+ {
+ AddPath(pwd,fsel[sel].name);
+
+ no = LoadDir(pwd,filter);
+
+ sel = 0;
+ top = 0;
+
+ if (no<=FSEL_LINES)
+ {
+ bar_step = 0;
+ bar_size = FSEL_LIST_H;
+ }
+ else
+ {
+ bar_step = FSEL_LIST_H/(double)no;
+ bar_size = bar_step*FSEL_LINES;
+ }
+ }
+ else
+ {
+ done = true;
+ ret = true;
+
+ strcpy(selected_file,pwd);
+ strcat(selected_file,fsel[sel].name);
+ }
+ }
+ else if (key & KEY_START)
+ {
+ done=true;
+ }
+ }
+
+ while (keysHeld());
+
+ return ret;
+}