Merge from trunk.
Subversion-branch: /branches/v2-branch Subversion-revision: 2577
This commit is contained in:
commit
47af28e168
8 changed files with 813 additions and 12 deletions
|
|
@ -68,6 +68,8 @@ static int found_iwad_selected;
|
|||
|
||||
static char *iwadfile;
|
||||
|
||||
static char *wad_extensions[] = { "wad", "lmp", "deh", NULL };
|
||||
|
||||
static char *doom_skills[] =
|
||||
{
|
||||
"I'm too young to die.", "Hey, not too rough.", "Hurt me plenty.",
|
||||
|
|
@ -163,7 +165,7 @@ static void AddWADs(execute_context_t *exec)
|
|||
{
|
||||
int have_wads = 0;
|
||||
int i;
|
||||
|
||||
|
||||
for (i=0; i<NUM_WADS; ++i)
|
||||
{
|
||||
if (wads[i] != NULL && strlen(wads[i]) > 0)
|
||||
|
|
@ -277,7 +279,7 @@ static void StartGame(int multiplayer)
|
|||
AddWADs(exec);
|
||||
|
||||
TXT_Shutdown();
|
||||
|
||||
|
||||
M_SaveDefaults();
|
||||
PassThroughArguments(exec);
|
||||
|
||||
|
|
@ -610,7 +612,9 @@ static void OpenWadsWindow(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data))
|
|||
|
||||
for (i=0; i<NUM_WADS; ++i)
|
||||
{
|
||||
TXT_AddWidget(window, TXT_NewInputBox(&wads[i], 60));
|
||||
TXT_AddWidget(window,
|
||||
TXT_NewFileSelector(&wads[i], 60, "Select a WAD file",
|
||||
wad_extensions));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ libtextscreen_a_SOURCES = \
|
|||
txt_checkbox.c txt_checkbox.h \
|
||||
txt_desktop.c txt_desktop.h \
|
||||
txt_dropdown.c txt_dropdown.h \
|
||||
txt_fileselect.c txt_fileselect.h \
|
||||
txt_gui.c txt_gui.h \
|
||||
txt_inputbox.c txt_inputbox.h \
|
||||
txt_io.c txt_io.h \
|
||||
|
|
|
|||
|
|
@ -39,10 +39,13 @@ enum
|
|||
RADIO_VALUE_MUSHROOM,
|
||||
RADIO_VALUE_SNAKE,
|
||||
};
|
||||
char *extensions[] = { "wad", "lmp", "txt", NULL };
|
||||
char *radio_values[] = { "Badger", "Mushroom", "Snake" };
|
||||
char *textbox_value = NULL;
|
||||
int numbox_value = 0;
|
||||
int radiobutton_value;
|
||||
char *file_path = NULL;
|
||||
char *dir_path = NULL;
|
||||
txt_label_t *value_label;
|
||||
txt_window_t *firstwin;
|
||||
int cheesy;
|
||||
|
|
@ -187,12 +190,20 @@ void Window2(void)
|
|||
TXT_AddWidget(window, TXT_NewSeparator("Input boxes"));
|
||||
table = TXT_NewTable(2);
|
||||
TXT_AddWidget(window, table);
|
||||
TXT_AddWidget(table, TXT_NewLabel("String: "));
|
||||
TXT_AddWidget(table, TXT_NewInputBox(&textbox_value, 20));
|
||||
TXT_AddWidget(table, TXT_NewLabel("Int: "));
|
||||
TXT_AddWidget(table, TXT_NewIntInputBox(&numbox_value, 10));
|
||||
TXT_AddWidget(table, TXT_NewLabel("Spin control:"));
|
||||
TXT_AddWidget(table, TXT_NewSpinControl(&numbox_value, 0, 15));
|
||||
TXT_AddWidgets(table,
|
||||
TXT_NewLabel("String: "),
|
||||
TXT_NewInputBox(&textbox_value, 20),
|
||||
TXT_NewLabel("Int: "),
|
||||
TXT_NewIntInputBox(&numbox_value, 10),
|
||||
TXT_NewLabel("Spin control:"),
|
||||
TXT_NewSpinControl(&numbox_value, 0, 15),
|
||||
TXT_NewLabel("File:"),
|
||||
TXT_NewFileSelector(&file_path, 28, "Select file:",
|
||||
extensions),
|
||||
TXT_NewLabel("Directory:"),
|
||||
TXT_NewFileSelector(&dir_path, 28, "Select directory:",
|
||||
TXT_DIRECTORY),
|
||||
NULL);
|
||||
|
||||
TXT_AddWidget(window, TXT_NewSeparator("Scroll pane test"));
|
||||
scrollpane = TXT_NewScrollPane(40, 5, TXT_NewLabel(
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "txt_checkbox.h"
|
||||
#include "txt_desktop.h"
|
||||
#include "txt_dropdown.h"
|
||||
#include "txt_fileselect.h"
|
||||
#include "txt_inputbox.h"
|
||||
#include "txt_label.h"
|
||||
#include "txt_radiobutton.h"
|
||||
|
|
|
|||
676
textscreen/txt_fileselect.c
Normal file
676
textscreen/txt_fileselect.c
Normal file
|
|
@ -0,0 +1,676 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2013 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Routines for selecting files.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomkeys.h"
|
||||
|
||||
#include "txt_fileselect.h"
|
||||
#include "txt_inputbox.h"
|
||||
#include "txt_main.h"
|
||||
#include "txt_widget.h"
|
||||
|
||||
struct txt_fileselect_s {
|
||||
txt_widget_t widget;
|
||||
txt_inputbox_t *inputbox;
|
||||
int size;
|
||||
char *prompt;
|
||||
char **extensions;
|
||||
};
|
||||
|
||||
// Dummy value to select a directory.
|
||||
|
||||
char *TXT_DIRECTORY[] = { "__directory__", NULL };
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static char *ExecReadOutput(char **argv)
|
||||
{
|
||||
char *result;
|
||||
int completed;
|
||||
int pid, status, result_len;
|
||||
int pipefd[2];
|
||||
|
||||
if (pipe(pipefd) != 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
dup2(pipefd[1], fileno(stdout));
|
||||
execv(argv[0], argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
|
||||
|
||||
// Read program output into 'result' string.
|
||||
// Wait until the program has completed and (if it was successful)
|
||||
// a full line has been read.
|
||||
|
||||
result = NULL;
|
||||
result_len = 0;
|
||||
completed = 0;
|
||||
|
||||
while (!completed
|
||||
|| (status == 0 && (result == NULL || strchr(result, '\n') == NULL)))
|
||||
{
|
||||
char buf[64];
|
||||
int bytes;
|
||||
|
||||
if (!completed && waitpid(pid, &status, WNOHANG) != 0)
|
||||
{
|
||||
completed = 1;
|
||||
}
|
||||
|
||||
bytes = read(pipefd[0], buf, sizeof(buf));
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = realloc(result, result_len + bytes + 1);
|
||||
memcpy(result + result_len, buf, bytes);
|
||||
result_len += bytes;
|
||||
result[result_len] = '\0';
|
||||
}
|
||||
|
||||
usleep(100 * 1000);
|
||||
TXT_Sleep(1);
|
||||
TXT_UpdateScreen();
|
||||
}
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
// Must have a success exit code.
|
||||
|
||||
if (WEXITSTATUS(status) != 0)
|
||||
{
|
||||
free(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
// Strip off newline from the end.
|
||||
|
||||
if (result != NULL && result[result_len - 1] == '\n')
|
||||
{
|
||||
result[result_len - 1] = '\0';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
// Windows code. Use comdlg32 to pop up a dialog box.
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
static BOOL WINAPI (*MyGetOpenFileName)(LPOPENFILENAME) = NULL;
|
||||
static LPITEMIDLIST (*MySHBrowseForFolder)(LPBROWSEINFO) = NULL;
|
||||
static BOOL (*MySHGetPathFromIDList)(LPITEMIDLIST, LPTSTR) = NULL;
|
||||
|
||||
// Load library functions from DLL files.
|
||||
|
||||
static int LoadDLLs(void)
|
||||
{
|
||||
HMODULE comdlg32 = LoadLibraryW(L"comdlg32.dll");
|
||||
HMODULE shell32 = LoadLibraryW(L"shell32.dll");
|
||||
|
||||
if (comdlg32 == NULL || shell32 == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
MyGetOpenFileName =
|
||||
(void *) GetProcAddress(comdlg32, "GetOpenFileNameA");
|
||||
MySHBrowseForFolder =
|
||||
(void *) GetProcAddress(shell32, "SHBrowseForFolder");
|
||||
MySHGetPathFromIDList =
|
||||
(void *) GetProcAddress(shell32, "SHGetPathFromIDList");
|
||||
|
||||
return MyGetOpenFileName != NULL
|
||||
&& MySHBrowseForFolder != NULL
|
||||
&& MySHGetPathFromIDList != NULL;
|
||||
}
|
||||
|
||||
static int InitLibraries(void)
|
||||
{
|
||||
static int initted = 0, success = 0;
|
||||
|
||||
if (!initted)
|
||||
{
|
||||
success = LoadDLLs();
|
||||
initted = 1;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Generate the "filter" string from the list of extensions.
|
||||
|
||||
static char *GenerateFilterString(char **extensions)
|
||||
{
|
||||
unsigned int result_len = 1;
|
||||
unsigned int i;
|
||||
char *result, *out;
|
||||
|
||||
if (extensions == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
result_len += 16 + strlen(extensions[i]) * 3;
|
||||
}
|
||||
|
||||
result = malloc(result_len);
|
||||
out = result;
|
||||
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
// .wad files (*.wad)\0
|
||||
out += 1 + sprintf(out, "%s files (*.%s)",
|
||||
extensions[i], extensions[i]);
|
||||
// *.wad\0
|
||||
out += 1 + sprintf(out, "*.%s", extensions[i]);
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int TXT_CanSelectFiles(void)
|
||||
{
|
||||
return InitLibraries();
|
||||
}
|
||||
|
||||
static char *SelectDirectory(char *window_title)
|
||||
{
|
||||
LPITEMIDLIST pidl;
|
||||
BROWSEINFO bi;
|
||||
char selected[MAX_PATH] = "";
|
||||
char *result;
|
||||
|
||||
ZeroMemory(&bi, sizeof(bi));
|
||||
bi.hwndOwner = NULL;
|
||||
bi.lpszTitle = window_title;
|
||||
bi.pszDisplayName = selected;
|
||||
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
|
||||
|
||||
pidl = MySHBrowseForFolder(&bi);
|
||||
|
||||
result = NULL;
|
||||
|
||||
if (pidl != NULL)
|
||||
{
|
||||
if (MySHGetPathFromIDList(pidl, selected))
|
||||
{
|
||||
result = strdup(selected);
|
||||
}
|
||||
|
||||
// TODO: Free pidl
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *TXT_SelectFile(char *window_title, char **extensions)
|
||||
{
|
||||
OPENFILENAME fm;
|
||||
char selected[MAX_PATH] = "";
|
||||
char *filter_string, *result;
|
||||
|
||||
if (!InitLibraries())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (extensions == TXT_DIRECTORY)
|
||||
{
|
||||
return SelectDirectory(window_title);
|
||||
}
|
||||
|
||||
filter_string = GenerateFilterString(extensions);
|
||||
|
||||
ZeroMemory(&fm, sizeof(fm));
|
||||
fm.lStructSize = sizeof(OPENFILENAME);
|
||||
fm.hwndOwner = NULL;
|
||||
fm.lpstrTitle = window_title;
|
||||
fm.lpstrFilter = filter_string;
|
||||
fm.lpstrFile = selected;
|
||||
fm.nMaxFile = MAX_PATH;
|
||||
fm.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
fm.lpstrDefExt = "";
|
||||
|
||||
if (!MyGetOpenFileName(&fm))
|
||||
{
|
||||
result = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = strdup(selected);
|
||||
}
|
||||
|
||||
free(filter_string);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#elif defined(__MACOSX__)
|
||||
|
||||
// Mac OS X code. Popping up a dialog requires Objective C/Cocoa
|
||||
// but we can get away with using AppleScript which avoids adding
|
||||
// an Objective C dependency. This is rather silly.
|
||||
|
||||
// Printf format string for the "wrapper" portion of the AppleScript:
|
||||
|
||||
#define APPLESCRIPT_WRAPPER \
|
||||
"tell application (path to frontmost application as text)\n" \
|
||||
" set theFile to (%s)\n" \
|
||||
" copy POSIX path of theFile to stdout\n" \
|
||||
"end tell\n"
|
||||
|
||||
static char *EscapedString(char *s)
|
||||
{
|
||||
char *result;
|
||||
char *in, *out;
|
||||
|
||||
result = malloc(strlen(s) + 3);
|
||||
out = result;
|
||||
*out++ = '\"';
|
||||
for (in = s; *in != '\0'; ++in)
|
||||
{
|
||||
if (*in == '\"' || *in == '\\')
|
||||
{
|
||||
*out++ = '\\';
|
||||
}
|
||||
*out++ = *in;
|
||||
}
|
||||
*out++ = '\"';
|
||||
*out = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Build list of extensions, like: {"wad","lmp","txt"}
|
||||
|
||||
static char *ExtensionsList(char **extensions)
|
||||
{
|
||||
char *result, *escaped;
|
||||
unsigned int result_len;
|
||||
unsigned int i;
|
||||
|
||||
if (extensions == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result_len = 3;
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
result_len += 5 + strlen(extensions[i]) * 2;
|
||||
}
|
||||
|
||||
result = malloc(result_len);
|
||||
strcpy(result, "{");
|
||||
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
escaped = EscapedString(extensions[i]);
|
||||
strcat(result, escaped);
|
||||
free(escaped);
|
||||
|
||||
if (extensions[i + 1] != NULL)
|
||||
strcat(result, ",");
|
||||
}
|
||||
|
||||
strcat(result, "}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *GenerateSelector(char *window_title, char **extensions)
|
||||
{
|
||||
char *chooser, *ext_list, *result;
|
||||
unsigned int result_len;
|
||||
|
||||
result_len = 64;
|
||||
|
||||
if (extensions == TXT_DIRECTORY)
|
||||
{
|
||||
chooser = "choose folder";
|
||||
ext_list = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
chooser = "choose file";
|
||||
ext_list = ExtensionsList(extensions);
|
||||
}
|
||||
|
||||
// Calculate size.
|
||||
|
||||
if (window_title != NULL)
|
||||
{
|
||||
window_title = EscapedString(window_title);
|
||||
result_len += strlen(window_title);
|
||||
}
|
||||
if (ext_list != NULL)
|
||||
{
|
||||
result_len += strlen(ext_list);
|
||||
}
|
||||
|
||||
result = malloc(result_len);
|
||||
|
||||
strcpy(result, chooser);
|
||||
|
||||
if (window_title != NULL)
|
||||
{
|
||||
strcat(result, " with prompt ");
|
||||
strcat(result, window_title);
|
||||
free(window_title);
|
||||
}
|
||||
|
||||
if (ext_list != NULL)
|
||||
{
|
||||
strcat(result, "of type ");
|
||||
strcat(result, ext_list);
|
||||
free(ext_list);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *GenerateAppleScript(char *window_title, char **extensions)
|
||||
{
|
||||
char *selector, *result;
|
||||
|
||||
selector = GenerateSelector(window_title, extensions);
|
||||
|
||||
result = malloc(strlen(APPLESCRIPT_WRAPPER) + strlen(selector));
|
||||
sprintf(result, APPLESCRIPT_WRAPPER, selector);
|
||||
free(selector);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int TXT_CanSelectFiles(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *TXT_SelectFile(char *window_title, char **extensions)
|
||||
{
|
||||
char *argv[4];
|
||||
char *result, *applescript;
|
||||
|
||||
applescript = GenerateAppleScript(window_title, extensions);
|
||||
|
||||
argv[0] = "/usr/bin/osascript";
|
||||
argv[1] = "-e";
|
||||
argv[2] = applescript;
|
||||
argv[3] = NULL;
|
||||
|
||||
result = ExecReadOutput(argv);
|
||||
|
||||
free(applescript);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Linux version: invoke the Zenity command line program to pop up a
|
||||
// dialog box. This avoids adding Gtk+ as a compile dependency.
|
||||
|
||||
#define ZENITY_BINARY "/usr/bin/zenity"
|
||||
|
||||
static unsigned int NumExtensions(char **extensions)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
|
||||
if (extensions != NULL)
|
||||
{
|
||||
for (result = 0; extensions[result] != NULL; ++result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ZenityAvailable(void)
|
||||
{
|
||||
return system(ZENITY_BINARY " --help >/dev/null 2>&1") == 0;
|
||||
}
|
||||
|
||||
int TXT_CanSelectFiles(void)
|
||||
{
|
||||
return ZenityAvailable();
|
||||
}
|
||||
|
||||
char *TXT_SelectFile(char *window_title, char **extensions)
|
||||
{
|
||||
unsigned int i;
|
||||
char *result;
|
||||
char **argv;
|
||||
int argc;
|
||||
|
||||
if (!ZenityAvailable())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
argv = calloc(4 + NumExtensions(extensions), sizeof(char *));
|
||||
argv[0] = ZENITY_BINARY;
|
||||
argv[1] = "--file-selection";
|
||||
argc = 2;
|
||||
|
||||
if (window_title != NULL)
|
||||
{
|
||||
argv[argc] = malloc(10 + strlen(window_title));
|
||||
sprintf(argv[argc], "--title=%s", window_title);
|
||||
++argc;
|
||||
}
|
||||
|
||||
if (extensions == TXT_DIRECTORY)
|
||||
{
|
||||
argv[argc] = strdup("--directory");
|
||||
++argc;
|
||||
}
|
||||
else if (extensions != NULL)
|
||||
{
|
||||
for (i = 0; extensions[i] != NULL; ++i)
|
||||
{
|
||||
argv[argc] = malloc(30 + strlen(extensions[i]) * 2);
|
||||
sprintf(argv[argc], "--file-filter=.%s | *.%s",
|
||||
extensions[i], extensions[i]);
|
||||
++argc;
|
||||
}
|
||||
}
|
||||
|
||||
argv[argc] = NULL;
|
||||
|
||||
result = ExecReadOutput(argv);
|
||||
|
||||
for (i = 2; i < argc; ++i)
|
||||
{
|
||||
free(argv[i]);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void TXT_FileSelectSizeCalc(TXT_UNCAST_ARG(fileselect))
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
// Calculate widget size, but override the width to always
|
||||
// be the configured size.
|
||||
|
||||
TXT_CalcWidgetSize(fileselect->inputbox);
|
||||
fileselect->widget.w = fileselect->size;
|
||||
fileselect->widget.h = fileselect->inputbox->widget.h;
|
||||
}
|
||||
|
||||
static void TXT_FileSelectDrawer(TXT_UNCAST_ARG(fileselect))
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
// Input box widget inherits all the properties of the
|
||||
// file selector.
|
||||
|
||||
fileselect->inputbox->widget.x = fileselect->widget.x;
|
||||
fileselect->inputbox->widget.y = fileselect->widget.y;
|
||||
fileselect->inputbox->widget.w = fileselect->widget.w;
|
||||
fileselect->inputbox->widget.h = fileselect->widget.h;
|
||||
|
||||
TXT_DrawWidget(fileselect->inputbox);
|
||||
}
|
||||
|
||||
static void TXT_FileSelectDestructor(TXT_UNCAST_ARG(fileselect))
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
TXT_DestroyWidget(fileselect->inputbox);
|
||||
}
|
||||
|
||||
static int DoSelectFile(txt_fileselect_t *fileselect)
|
||||
{
|
||||
char *path;
|
||||
char **var;
|
||||
|
||||
if (TXT_CanSelectFiles())
|
||||
{
|
||||
path = TXT_SelectFile(fileselect->prompt,
|
||||
fileselect->extensions);
|
||||
var = fileselect->inputbox->value;
|
||||
free(*var);
|
||||
*var = path;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int TXT_FileSelectKeyPress(TXT_UNCAST_ARG(fileselect), int key)
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
// When the enter key is pressed, pop up a file selection dialog,
|
||||
// if file selectors work. Allow holding down 'alt' to override
|
||||
// use of the native file selector, so the user can just type a path.
|
||||
|
||||
if (!fileselect->inputbox->editing
|
||||
&& !TXT_GetModifierState(TXT_MOD_ALT)
|
||||
&& key == KEY_ENTER)
|
||||
{
|
||||
if (DoSelectFile(fileselect))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return TXT_WidgetKeyPress(fileselect->inputbox, key);
|
||||
}
|
||||
|
||||
static void TXT_FileSelectMousePress(TXT_UNCAST_ARG(fileselect),
|
||||
int x, int y, int b)
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
if (!fileselect->inputbox->editing
|
||||
&& !TXT_GetModifierState(TXT_MOD_ALT)
|
||||
&& b == TXT_MOUSE_LEFT)
|
||||
{
|
||||
if (DoSelectFile(fileselect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return TXT_WidgetMousePress(fileselect->inputbox, x, y, b);
|
||||
}
|
||||
|
||||
static void TXT_FileSelectFocused(TXT_UNCAST_ARG(fileselect), int focused)
|
||||
{
|
||||
TXT_CAST_ARG(txt_fileselect_t, fileselect);
|
||||
|
||||
TXT_SetWidgetFocus(fileselect->inputbox, focused);
|
||||
}
|
||||
|
||||
txt_widget_class_t txt_fileselect_class =
|
||||
{
|
||||
TXT_AlwaysSelectable,
|
||||
TXT_FileSelectSizeCalc,
|
||||
TXT_FileSelectDrawer,
|
||||
TXT_FileSelectKeyPress,
|
||||
TXT_FileSelectDestructor,
|
||||
TXT_FileSelectMousePress,
|
||||
NULL,
|
||||
TXT_FileSelectFocused,
|
||||
};
|
||||
|
||||
txt_fileselect_t *TXT_NewFileSelector(char **variable, int size,
|
||||
char *prompt, char **extensions)
|
||||
{
|
||||
txt_fileselect_t *fileselect;
|
||||
|
||||
fileselect = malloc(sizeof(txt_fileselect_t));
|
||||
TXT_InitWidget(fileselect, &txt_fileselect_class);
|
||||
fileselect->inputbox = TXT_NewInputBox(variable, 1024);
|
||||
fileselect->inputbox->widget.parent = &fileselect->widget;
|
||||
fileselect->size = size;
|
||||
fileselect->prompt = prompt;
|
||||
fileselect->extensions = extensions;
|
||||
|
||||
return fileselect;
|
||||
}
|
||||
|
||||
88
textscreen/txt_fileselect.h
Normal file
88
textscreen/txt_fileselect.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2013 Simon Howard
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Routines for selecting files, and the txt_fileselect_t widget.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef TXT_FILESELECT_H
|
||||
#define TXT_FILESELECT_H
|
||||
|
||||
/**
|
||||
* @file txt_fileselect.h
|
||||
*
|
||||
* File selection widget.
|
||||
*/
|
||||
|
||||
/**
|
||||
* File selection widget.
|
||||
*
|
||||
* A file selection widget resembles an input box (@ref txt_inputbox_t)
|
||||
* but opens a file selector dialog box when clicked.
|
||||
*/
|
||||
|
||||
typedef struct txt_fileselect_s txt_fileselect_t;
|
||||
|
||||
/**
|
||||
* Returns non-zero if a native file selector is available on this
|
||||
* platform.
|
||||
*/
|
||||
|
||||
int TXT_CanSelectFiles(void);
|
||||
|
||||
/**
|
||||
* Open a native file selector to select a file.
|
||||
*
|
||||
* @param prompt Pointer to a string containing a prompt to display
|
||||
* in the window.
|
||||
* @param extensions NULL-terminated list of filename extensions for
|
||||
* files that can be selected, or @ref TXT_DIRECTORY
|
||||
* to select directories.
|
||||
*/
|
||||
|
||||
char *TXT_SelectFile(char *prompt, char **extensions);
|
||||
|
||||
/**
|
||||
* Create a new txt_fileselect_t widget.
|
||||
*
|
||||
* @param variable Pointer to a char * variable in which the selected
|
||||
* file should be stored.
|
||||
* @param size Width of the file selector widget in characters.
|
||||
* @param prompt Pointer to a string containing a prompt to display
|
||||
* in the file selection window.
|
||||
* @param extensions NULL-terminated list of filename extensions that
|
||||
* can be used for this widget, or @ref TXT_DIRECTORY
|
||||
* to select directories.
|
||||
*/
|
||||
|
||||
txt_fileselect_t *TXT_NewFileSelector(char **variable, int size,
|
||||
char *prompt, char **extensions);
|
||||
|
||||
/**
|
||||
* Special value to use for 'extensions' that selects a directory
|
||||
* instead of a file.
|
||||
*/
|
||||
|
||||
extern char *TXT_DIRECTORY[];
|
||||
|
||||
#endif /* #ifndef TXT_FILESELECT_H */
|
||||
|
||||
|
|
@ -139,9 +139,21 @@ static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox))
|
|||
SetBufferFromValue(inputbox);
|
||||
}
|
||||
|
||||
TXT_DrawUTF8String(inputbox->buffer);
|
||||
// If string size exceeds the widget's width, show only the end.
|
||||
|
||||
chars = TXT_UTF8_Strlen(inputbox->buffer);
|
||||
if (TXT_UTF8_Strlen(inputbox->buffer) > w - 1)
|
||||
{
|
||||
TXT_DrawString("\xae");
|
||||
TXT_DrawUTF8String(
|
||||
TXT_UTF8_SkipChars(inputbox->buffer,
|
||||
TXT_UTF8_Strlen(inputbox->buffer) - w + 2));
|
||||
chars = w - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TXT_DrawUTF8String(inputbox->buffer);
|
||||
chars = TXT_UTF8_Strlen(inputbox->buffer);
|
||||
}
|
||||
|
||||
if (chars < w && inputbox->editing && focused)
|
||||
{
|
||||
|
|
@ -204,6 +216,15 @@ static int TXT_InputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Backspace or delete erases the contents of the box.
|
||||
|
||||
if ((key == KEY_DEL || key == KEY_BACKSPACE)
|
||||
&& inputbox->widget.widget_class == &txt_inputbox_class)
|
||||
{
|
||||
free(*((char **)inputbox->value));
|
||||
*((char **) inputbox->value) = strdup("");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,6 @@ int TXT_HoveringOverWidget(TXT_UNCAST_ARG(widget));
|
|||
* whether it is selected and the mouse is hovering over it.
|
||||
*
|
||||
* @param widget The widget.
|
||||
* @param selected Whether the widget is selected.
|
||||
*/
|
||||
|
||||
void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget));
|
||||
|
|
|
|||
Loading…
Reference in a new issue