all repos — mgba @ 5966f46355d18ba472404a7f7ed3cbeebf846635

mGBA Game Boy Advance Emulator

src/util/gui/file-select.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "file-select.h"
  7
  8#include "util/gui/font.h"
  9#include "util/vector.h"
 10#include "util/vfs.h"
 11
 12DECLARE_VECTOR(FileList, char*);
 13DEFINE_VECTOR(FileList, char*);
 14
 15void _cleanFiles(struct FileList* currentFiles) {
 16	size_t size = FileListSize(currentFiles);
 17	size_t i;
 18	for (i = 0; i < size; ++i) {
 19		free(*FileListGetPointer(currentFiles, i));
 20	}
 21	FileListClear(currentFiles);
 22}
 23
 24void _upDirectory(char* currentPath) {
 25	char* end = strrchr(currentPath, '/');
 26	if (!end) {
 27		return;
 28	}
 29	end[0] = '\0';
 30	if (end[1]) {
 31		return;
 32	}
 33	// TODO: What if there was a trailing slash?
 34}
 35
 36bool _refreshDirectory(const char* currentPath, struct FileList* currentFiles) {
 37	_cleanFiles(currentFiles);
 38
 39	struct VDir* dir = VDirOpen(currentPath);
 40	if (!dir) {
 41		return false;
 42	}
 43	struct VDirEntry* de;
 44	while ((de = dir->listNext(dir))) {
 45		if (de->name(de)[0] == '.') {
 46			continue;
 47		}
 48		*FileListAppend(currentFiles) = strdup(de->name(de));
 49	}
 50	dir->close(dir);
 51	return true;
 52}
 53
 54bool selectFile(const struct GUIParams* params, const char* basePath, char* outPath, size_t outLen, const char* suffix) {
 55	char currentPath[256];
 56	strncpy(currentPath, basePath, sizeof(currentPath));
 57	int oldInput = -1;
 58	size_t fileIndex = 0;
 59
 60	struct FileList currentFiles;
 61	FileListInit(&currentFiles, 0);
 62	_refreshDirectory(currentPath, &currentFiles);
 63
 64	while (true) {
 65		int input = params->pollInput();
 66		int newInput = input & (oldInput ^ input);
 67		oldInput = input;
 68
 69		if (newInput & (1 << GUI_INPUT_UP) && fileIndex > 0) {
 70			--fileIndex;
 71		}
 72		if (newInput & (1 << GUI_INPUT_DOWN) && fileIndex < FileListSize(&currentFiles) - 1) {
 73			++fileIndex;
 74		}
 75		if (newInput & (1 << GUI_INPUT_CANCEL)) {
 76			_cleanFiles(&currentFiles);
 77			FileListDeinit(&currentFiles);
 78			return false;
 79		}
 80		if (newInput & (1 << GUI_INPUT_SELECT)) {
 81			snprintf(currentPath, sizeof(currentPath), "%s%c%s", currentPath, '/', *FileListGetPointer(&currentFiles, fileIndex));
 82			if (!_refreshDirectory(currentPath, &currentFiles)) {
 83				strncpy(outPath, currentPath, outLen);
 84				return true;
 85			}
 86			fileIndex = 0;
 87		}
 88		if (newInput & (1 << GUI_INPUT_BACK)) {
 89			if (strncmp(currentPath, basePath, sizeof(currentPath)) == 0) {
 90				_cleanFiles(&currentFiles);
 91				FileListDeinit(&currentFiles);
 92				return false;
 93			}
 94			_upDirectory(currentPath);
 95			_refreshDirectory(currentPath, &currentFiles);
 96			fileIndex = 0;
 97		}
 98
 99		params->drawStart();
100		int y = GUIFontHeight(params->font);
101		GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, "Current directory: %s", currentPath);
102		y += 2 * GUIFontHeight(params->font);
103		size_t i;
104		for (i = 0; i < FileListSize(&currentFiles); ++i) {
105			int color = 0xE0A0A0A0;
106			char bullet = ' ';
107			if (i == fileIndex) {
108				color = 0xFFFFFFFF;
109				bullet = '>';
110			}
111			GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, *FileListGetPointer(&currentFiles, i));
112			y += GUIFontHeight(params->font);
113			if (y + GUIFontHeight(params->font) > params->height) {
114				break;
115			}
116		}
117		y += GUIFontHeight(params->font) * 2;
118
119		params->drawEnd();
120	}
121}