dl-fldigi/src/fileselector/Native_File_Chooser_WIN32.cxx

778 wiersze
21 KiB
C++

//
// Fl_Native_File_Chooser_WIN32.cxx -- FLTK native OS file chooser widget
//
// Copyright 2004 by Greg Ercolano.
// API changes + filter improvements by Nathan Vander Wilt 2005
// FLTK2/WIN32 port by Greg Ercolano
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdio.h> // debugging
#include "flnfc_common.cxx" // strnew/strfree/strapp/chrcat
#include "FL/Native_File_Chooser.H"
#define FNFC_CLASS Fl_Native_File_Chooser
#define FNFC_CTOR Fl_Native_File_Chooser
#define LCURLY_CHR '{'
#define RCURLY_CHR '}'
#define LBRACKET_CHR '['
#define RBRACKET_CHR ']'
#define MAXFILTERS 80
#if 0
// STATIC: PRINT WINDOWS 'DOUBLE NULL' STRING (DEBUG)
static void dnullprint(char *wp) {
if ( ! wp ) return;
for ( int t=0; true; t++ ) {
if ( wp[t] == '\0' && wp[t+1] == '\0' ) {
printf("\\0\\0");
fflush(stdout);
return;
} else if ( wp[t] == '\0' ) {
printf("\\0");
} else {
printf("%c",wp[t]);
}
}
}
#endif
// RETURN LENGTH OF DOUBLENULL STRING
// Includes single nulls in count, excludes trailing doublenull.
//
// 1234 567
// |||/\|||
// IN: "one\0two\0\0"
// OUT: 7
//
static int dnulllen(const char *wp) {
int len = 0;
while ( ! ( *(wp+0) == 0 && *(wp+1) == 0 ) )
{ ++wp; ++len; }
return(len);
}
// STATIC: Append a string to another, leaving terminated with DOUBLE NULL.
// Automatically handles extending length of string.
// wp can be NULL (a new wp will be allocated and initialized).
// string must be NULL terminated.
// The pointer wp may be modified on return.
//
static void dnullcat(char*&wp, const char *string, int n = -1 ) {
//DEBUG printf("DEBUG: dnullcat IN: <"); dnullprint(wp); printf(">\n");
int inlen = ( n < 0 ) ? strlen(string) : n;
if ( ! wp ) {
wp = new char[inlen + 4];
*(wp+0) = '\0';
*(wp+1) = '\0';
} else {
int wplen = dnulllen(wp);
// Make copy of wp into larger buffer
char *tmp = new char[wplen + inlen + 4];
memcpy(tmp, wp, wplen+2); // copy of wp plus doublenull
delete [] wp; // delete old wp
wp = tmp; // use new copy
//DEBUG printf("DEBUG: dnullcat COPY: <"); dnullprint(wp); printf("> (wplen=%d)\n", wplen);
}
// Find end of double null string
// *wp2 is left pointing at second null.
//
char *wp2 = wp;
if ( *(wp2+0) != '\0' && *(wp2+1) != '\0' ) {
for ( ; 1; wp2++ )
if ( *(wp2+0) == '\0' && *(wp2+1) == '\0' )
{ wp2++; break; }
}
if ( n == -1 ) n = strlen(string);
strncpy(wp2, string, n);
// Leave string double-null terminated
*(wp2+n+0) = '\0';
*(wp2+n+1) = '\0';
//DEBUG printf("DEBUG: dnullcat OUT: <"); dnullprint(wp); printf(">\n\n");
}
// CTOR
FNFC_CLASS::FNFC_CTOR(int val) {
_btype = val;
_options = NO_OPTIONS;
memset((void*)&_ofn, 0, sizeof(OPENFILENAME));
_ofn.lStructSize = sizeof(OPENFILENAME);
_ofn.hwndOwner = NULL;
memset((void*)&_binf, 0, sizeof(BROWSEINFO));
_pathnames = NULL;
_tpathnames = 0;
_directory = NULL;
_title = NULL;
_filter = NULL;
_parsedfilt = NULL;
_nfilters = 0;
_preset_file = NULL;
_errmsg = NULL;
}
// DTOR
FNFC_CLASS::~FNFC_CTOR() {
//_pathnames // managed by clear_pathnames()
//_tpathnames // managed by clear_pathnames()
_directory = strfree(_directory);
_title = strfree(_title);
_filter = strfree(_filter);
//_parsedfilt // managed by clear_filters()
//_nfilters // managed by clear_filters()
_preset_file = strfree(_preset_file);
_errmsg = strfree(_errmsg);
clear_filters();
clear_pathnames();
ClearOFN();
ClearBINF();
}
// SET TYPE OF BROWSER
void FNFC_CLASS::type(int val) {
_btype = val;
}
// GET TYPE OF BROWSER
int FNFC_CLASS::type() const {
return( _btype );
}
// SET OPTIONS
void FNFC_CLASS::options(int val) {
_options = val;
}
// GET OPTIONS
int FNFC_CLASS::options() const {
return(_options);
}
// PRIVATE: SET ERROR MESSAGE
void FNFC_CLASS::errmsg(const char *val) {
_errmsg = strfree(_errmsg);
_errmsg = strnew(val);
}
// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS
void FNFC_CLASS::clear_pathnames() {
if ( _pathnames ) {
while ( --_tpathnames >= 0 ) {
_pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]);
}
delete [] _pathnames;
_pathnames = NULL;
}
_tpathnames = 0;
}
// SET A SINGLE PATHNAME
void FNFC_CLASS::set_single_pathname(const char *s) {
clear_pathnames();
_pathnames = new char*[1];
_pathnames[0] = strnew(s);
_tpathnames = 1;
}
// ADD PATHNAME TO EXISTING ARRAY
void FNFC_CLASS::add_pathname(const char *s) {
if ( ! _pathnames ) {
// Create first element in array
++_tpathnames;
_pathnames = new char*[_tpathnames];
} else {
// Grow array by 1
char **tmp = new char*[_tpathnames+1]; // create new buffer
memcpy((void*)tmp, (void*)_pathnames,
sizeof(char*)*_tpathnames); // copy old
delete [] _pathnames; // delete old
_pathnames = tmp; // use new
++_tpathnames;
}
_pathnames[_tpathnames-1] = strnew(s);
}
// FREE A PIDL (Pointer to IDentity List)
void FNFC_CLASS::FreePIDL(ITEMIDLIST *pidl) {
IMalloc *imalloc = NULL;
if ( SUCCEEDED(SHGetMalloc(&imalloc)) )
{ imalloc->Free(pidl); imalloc->Release(); imalloc = NULL; }
}
// CLEAR MICROSOFT OFN (OPEN FILE NAME) CLASS
void FNFC_CLASS::ClearOFN() {
// Free any previously allocated lpstrFile before zeroing out _ofn
if ( _ofn.lpstrFile ) {
_ofn.lpstrFile = strfree((char*)_ofn.lpstrFile);
}
if ( _ofn.lpstrInitialDir ) {
_ofn.lpstrInitialDir = (LPCSTR)strfree((char*)_ofn.lpstrInitialDir);
}
_ofn.lpstrFilter = NULL; // (deleted elsewhere)
int temp = _ofn.nFilterIndex; // keep the filter_value
memset((void*)&_ofn, 0, sizeof(_ofn));
_ofn.lStructSize = sizeof(OPENFILENAME);
_ofn.nFilterIndex = temp;
}
// CLEAR MICROSOFT BINF (BROWSER INFO) CLASS
void FNFC_CLASS::ClearBINF() {
if ( _binf.pidlRoot ) {
FreePIDL((ITEMIDLIST*)_binf.pidlRoot);
_binf.pidlRoot = NULL;
}
memset((void*)&_binf, 0, sizeof(_binf));
}
// CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES
void FNFC_CLASS::Win2Unix(char *s) {
for ( ; *s; s++ )
if ( *s == '\\' ) *s = '/';
}
// CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES
void FNFC_CLASS::Unix2Win(char *s) {
for ( ; *s; s++ )
if ( *s == '/' ) *s = '\\';
}
// SHOW FILE BROWSER
int FNFC_CLASS::showfile() {
ClearOFN();
clear_pathnames();
size_t fsize = 2048;
_ofn.Flags |= OFN_NOVALIDATE; // prevent disabling of front slashes
_ofn.Flags |= OFN_HIDEREADONLY; // hide goofy readonly flag
// USE NEW BROWSER
_ofn.Flags |= OFN_EXPLORER; // use newer explorer windows
_ofn.Flags |= OFN_ENABLESIZING; // allow window to be resized (hey, why not?)
// XXX: The docs for OFN_NOCHANGEDIR says the flag is 'ineffective' on XP/2K/NT!
// But let's set it anyway..
//
_ofn.Flags |= OFN_NOCHANGEDIR; // prevent dialog for messing up the cwd
switch ( _btype ) {
case BROWSE_DIRECTORY:
case BROWSE_MULTI_DIRECTORY:
case BROWSE_SAVE_DIRECTORY:
abort(); // never happens: handled by showdir()
case BROWSE_FILE:
fsize = 65536; // XXX: there must be a better way
break;
case BROWSE_MULTI_FILE:
_ofn.Flags |= OFN_ALLOWMULTISELECT;
fsize = 65536; // XXX: there must be a better way
break;
case BROWSE_SAVE_FILE:
if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) {
_ofn.Flags |= OFN_OVERWRITEPROMPT;
}
break;
}
// SPACE FOR RETURNED FILENAME
_ofn.lpstrFile = new char[fsize];
_ofn.nMaxFile = fsize-1;
_ofn.lpstrFile[0] = '\0';
_ofn.lpstrFile[1] = '\0'; // dnull
// PARENT WINDOW
_ofn.hwndOwner = GetForegroundWindow();
// DIALOG TITLE
_ofn.lpstrTitle = _title ? _title : NULL;
// FILTER
_ofn.lpstrFilter = _parsedfilt ? _parsedfilt : NULL;
// PRESET FILE
// If set, supercedes _directory. See KB Q86920 for details
//
if ( _preset_file ) {
size_t len = strlen(_preset_file);
if ( len >= _ofn.nMaxFile ) {
char msg[80];
sprintf(msg, "preset_file() filename is too long: %ld is >=%ld",
(long)len, (long)fsize);
return(-1);
}
strncpy(_ofn.lpstrFile, _preset_file, _ofn.nMaxFile);
Unix2Win(_ofn.lpstrFile);
_ofn.lpstrFile[len+0] = 0; // multiselect needs dnull
_ofn.lpstrFile[len+1] = 0;
}
if ( _directory ) {
// PRESET DIR
// XXX: See KB Q86920 for doc bug:
// http://support.microsoft.com/default.aspx?scid=kb;en-us;86920
//
_ofn.lpstrInitialDir = strnew(_directory);
Unix2Win((char*)_ofn.lpstrInitialDir);
}
// SAVE THE CURRENT DIRECTORY
// XXX: Save the cwd because GetOpenFileName() is probably going to
// change it, in spite of the OFN_NOCHANGEDIR flag, due to its docs
// saying the flag is 'ineffective'. %^(
//
char oldcwd[MAX_PATH];
GetCurrentDirectory(MAX_PATH, oldcwd);
oldcwd[MAX_PATH-1] = '\0';
// OPEN THE DIALOG WINDOW
int err;
if ( _btype == BROWSE_SAVE_FILE ) {
err = GetSaveFileName(&_ofn);
} else {
err = GetOpenFileName(&_ofn);
}
if ( err == 0 ) {
// EXTENDED ERROR CHECK
int err = CommDlgExtendedError();
// CANCEL?
if ( err == 0 )
return(1); // user hit 'cancel'
// AN ERROR OCCURRED
char msg[80];
sprintf(msg, "CommDlgExtendedError() code=%d", err);
errmsg(msg);
// XXX: RESTORE CWD
if ( oldcwd[0] ) SetCurrentDirectory(oldcwd);
return(-1);
}
// XXX: RESTORE CWD
if ( oldcwd[0] ) {
SetCurrentDirectory(oldcwd);
}
// PREPARE PATHNAMES FOR RETURN
switch ( _btype ) {
case BROWSE_FILE:
case BROWSE_SAVE_FILE:
set_single_pathname(_ofn.lpstrFile);
Win2Unix(_pathnames[_tpathnames-1]);
break;
case BROWSE_MULTI_FILE: {
// EXTRACT MULTIPLE FILENAMES
const char *dirname = _ofn.lpstrFile;
int dirlen = strlen(dirname);
if ( dirlen > 0 ) {
// WALK STRING SEARCHING FOR 'DOUBLE-NULL'
// eg. "/dir/name\0foo1\0foo2\0foo3\0\0"
//
char pathname[2048];
for ( const char *s = _ofn.lpstrFile + dirlen + 1;
*s; s+= (strlen(s)+1)) {
strcpy(pathname, dirname);
strcat(pathname, "\\");
strcat(pathname, s);
add_pathname(pathname);
Win2Unix(_pathnames[_tpathnames-1]);
}
}
// XXX
// Work around problem where pasted forward-slash pathname
// into the file browser causes new "Explorer" interface
// not to grok forward slashes, passing back as a 'filename'..!
//
if ( _tpathnames == 0 ) {
add_pathname(dirname);
Win2Unix(_pathnames[_tpathnames-1]);
}
break;
}
case BROWSE_DIRECTORY:
case BROWSE_MULTI_DIRECTORY:
case BROWSE_SAVE_DIRECTORY:
abort(); // never happens: handled by showdir()
}
return(0);
}
// Used by SHBrowseForFolder(), sets initial selected dir.
// Ref: Usenet: microsoft.public.vc.mfc, Dec 8 2000, 1:38p David Lowndes
// Subject: How to specify to select an initial folder .."
//
int CALLBACK FNFC_CLASS::Dir_CB(HWND win, UINT msg,
LPARAM param, LPARAM data) {
switch (msg) {
case BFFM_INITIALIZED:
if (data) ::SendMessage(win, BFFM_SETSELECTION, TRUE, data);
break;
case BFFM_SELCHANGED:
TCHAR path[MAX_PATH];
if ( SHGetPathFromIDList((ITEMIDLIST*)param, path) ) {
::SendMessage(win, BFFM_ENABLEOK, 0, 1);
} else {
//disable ok button if not a path
::SendMessage(win, BFFM_ENABLEOK, 0, 0);
}
break;
case BFFM_VALIDATEFAILED:
// we could pop up an annoying message here.
// also needs set ulFlags |= BIF_VALIDATE
break;
default:
break;
}
return(0);
}
// SHOW DIRECTORY BROWSER
int FNFC_CLASS::showdir() {
OleInitialize(NULL); // init needed by BIF_USENEWUI
ClearBINF();
clear_pathnames();
// PARENT WINDOW
_binf.hwndOwner = GetForegroundWindow();
// DIALOG TITLE
_binf.lpszTitle = _title ? _title : NULL;
// FLAGS
_binf.ulFlags = 0; // initialize
// TBD: make sure matches to runtime system, if need be.
//( what if _WIN32_IE doesn't match system? does the program not run? )
// TBD: match all 3 types of directories
#if defined(BIF_NONEWFOLDERBUTTON) // Version 6.0
if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags |= BIF_NONEWFOLDERBUTTON;
_binf.ulFlags |= BIF_USENEWUI | BIF_SHAREABLE | BIF_RETURNONLYFSDIRS;
#elif defined(BIF_USENEWUI) // Version 5.0
if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags |= BIF_EDITBOX;
else if ( _btype == BROWSE_SAVE_DIRECTORY ) _binf.ulFlags |= BIF_USENEWUI;
_binf.ulFlags |= BIF_SHAREABLE | BIF_RETURNONLYFSDIRS;
#elif defined(BIF_EDITBOX) // Version 4.71
_binf.ulFlags |= BIF_RETURNONLYFSDIRS | BIF_EDITBOX;
#else // Version Old
_binf.ulFlags |= BIF_RETURNONLYFSDIRS;
#endif
// BUFFER
char displayname[MAX_PATH];
_binf.pszDisplayName = displayname;
// PRESET DIR
char presetname[MAX_PATH];
if ( _directory ) {
strcpy(presetname, _directory);
Unix2Win(presetname);
_binf.lParam = (LPARAM)presetname;
}
else _binf.lParam = 0;
_binf.lpfn = Dir_CB;
// OPEN BROWSER
ITEMIDLIST *pidl = SHBrowseForFolder(&_binf);
// CANCEL?
if ( pidl == NULL ) return(1);
// GET THE PATHNAME(S) THE USER SELECTED
// TBD: expand NetHood shortcuts from this PIDL??
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shbrowseforfolder.asp
TCHAR path[MAX_PATH];
if ( SHGetPathFromIDList(pidl, path) ) {
Win2Unix(path);
add_pathname(path);
}
FreePIDL(pidl);
if ( !strlen(path) ) return(1); // don't return empty pathnames
return(0);
}
// RETURNS:
// 0 - user picked a file
// 1 - user cancelled
// -1 - failed; errmsg() has reason
//
int FNFC_CLASS::show() {
if ( _btype == BROWSE_DIRECTORY ||
_btype == BROWSE_MULTI_DIRECTORY ||
_btype == BROWSE_SAVE_DIRECTORY ) {
return(showdir());
} else {
return(showfile());
}
}
// RETURN ERROR MESSAGE
const char *FNFC_CLASS::errmsg() const {
return(_errmsg ? _errmsg : "No error");
}
// GET FILENAME
const char* FNFC_CLASS::filename() const {
if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]);
return("");
}
// GET FILENAME FROM LIST OF FILENAMES
const char* FNFC_CLASS::filename(int i) const {
if ( _pathnames && i < _tpathnames ) return(_pathnames[i]);
return("");
}
// GET TOTAL FILENAMES CHOSEN
int FNFC_CLASS::count() const {
return(_tpathnames);
}
// PRESET PATHNAME
// Can be NULL if no preset is desired.
//
void FNFC_CLASS::directory(const char *val) {
_directory = strfree(_directory);
_directory = strnew(val);
}
// GET PRESET PATHNAME
// Can return NULL if none set.
//
const char *FNFC_CLASS::directory() const {
return(_directory);
}
// SET TITLE
// Can be NULL if no title desired.
//
void FNFC_CLASS::title(const char *val) {
_title = strfree(_title);
_title = strnew(val);
}
// GET TITLE
// Can return NULL if none set.
//
const char *FNFC_CLASS::title() const {
return(_title);
}
// SET FILTER
// Can be NULL if no filter needed
//
void FNFC_CLASS::filter(const char *val) {
_filter = strfree(_filter);
clear_filters();
if ( val ) {
_filter = strnew(val);
parse_filter(_filter);
}
add_filter("All Files", "*.*"); // always include 'all files' option
#ifdef DEBUG
nullprint(_parsedfilt);
#endif /*DEBUG*/
}
// GET FILTER
// Can return NULL if none set.
//
const char *FNFC_CLASS::filter() const {
return(_filter);
}
// CLEAR FILTERS
void FNFC_CLASS::clear_filters() {
_nfilters = 0;
_parsedfilt = strfree(_parsedfilt);
}
// ADD A FILTER
void FNFC_CLASS::add_filter(
const char *name_in, // name of filter (optional: can be null)
const char *winfilter // windows style filter (eg. "*.cxx;*.h")
) {
// No name? Make one..
char name[1024];
if ( !name_in || name_in[0] == '\0' ) {
sprintf(name, "%.*s Files", sizeof(name)-10, winfilter);
} else {
sprintf(name, "%.*s", sizeof(name)-10, name_in);
}
dnullcat(_parsedfilt, name);
dnullcat(_parsedfilt, winfilter);
_nfilters++;
//DEBUG printf("DEBUG: ADD FILTER name=<%s> winfilter=<%s>\n", name, winfilter);
}
// CONVERT FLTK STYLE PATTERN MATCHES TO WINDOWS 'DOUBLENULL' PATTERN
// Handles:
// IN OUT
// ----------- -----------------------------
// *.{ma,mb} "*.{ma,mb} Files\0*.ma;*.mb\0\0"
// *.[abc] "*.[abc] Files\0*.a;*.b;*.c\0\0"
// *.txt "*.txt Files\0*.txt\0\0"
// C Files\t*.[ch] "C Files\0*.c;*.h\0\0"
//
// Example:
// IN: "*.{ma,mb}"
// OUT: "*.ma;*.mb Files\0*.ma;*.mb\0All Files\0*.*\0\0"
// --------------- --------- --------- ---
// | | | |
// Title Wildcards Title Wildcards
//
// Parsing Mode:
// IN:"C Files\t*.{cxx,h}"
// ||||||| |||||||||
// mode: nnnnnnn ww{{{{{{{
// \_____/ \_______/
// Name Wildcard
//
void FNFC_CLASS::parse_filter(const char *in) {
clear_filters();
if ( ! in ) return;
int has_name = strchr(in, '\t') ? 1 : 0;
char mode = has_name ? 'n' : 'w'; // parse mode: n=name, w=wildcard
int nwildcards = 0;
char wildcards[MAXFILTERS][1024]; // parsed wildcards (can be several)
char wildprefix[512] = "";
char name[512] = "";
// Init
int t;
for ( t=0; t<MAXFILTERS; t++ ) {
wildcards[t][0] = '\0';
}
// Parse
for ( ; 1; in++ ) {
//// DEBUG
//// printf("WORKING ON '%c': mode=<%c> name=<%s> wildprefix=<%s> nwildcards=%d wildcards[n]=<%s>\n",
//// *in, mode, name, wildprefix, nwildcards, wildcards[nwildcards]);
switch (*in) {
case ',':
case '|':
if ( mode == LCURLY_CHR ) {
// create new wildcard, copy in prefix
strcat(wildcards[nwildcards++], wildprefix);
continue;
} else {
goto regchar;
}
continue;
// FINISHED PARSING A NAME?
case '\t':
if ( mode != 'n' ) goto regchar;
// finish parsing name? switch to wildcard mode
mode = 'w';
break;
// ESCAPE NEXT CHAR
case '\\':
++in;
goto regchar;
// FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
case '\r':
case '\n':
case '\0':
{
if ( mode == 'w' ) { // finished parsing wildcard?
if ( nwildcards == 0 ) {
strcpy(wildcards[nwildcards++], wildprefix);
}
// Append wildcards in Microsoft's "*.one;*.two" format
char comp[4096] = "";
for ( t=0; t<nwildcards; t++ ) {
if ( t != 0 ) strcat(comp, ";");
strcat(comp, wildcards[t]);
}
// Add if not empty
if ( comp[0] ) {
add_filter(name, comp);
}
}
// RESET
for ( t=0; t<MAXFILTERS; t++ ) {
wildcards[t][0] = '\0';
}
nwildcards = 0;
wildprefix[0] = name[0] = '\0';
mode = strchr(in,'\t') ? 'n' : 'w';
// DONE?
if ( *in == '\0' ) return; // done
continue; // not done yet, more filters
}
// STARTING A WILDCARD?
case LBRACKET_CHR:
case LCURLY_CHR:
mode = *in;
if ( *in == LCURLY_CHR ) {
// create new wildcard
strcat(wildcards[nwildcards++], wildprefix);
}
continue;
// ENDING A WILDCARD?
case RBRACKET_CHR:
case RCURLY_CHR:
mode = 'w'; // back to wildcard mode
continue;
// ALL OTHER NON-SPECIAL CHARACTERS
default:
regchar: // handle regular char
switch ( mode ) {
case LBRACKET_CHR:
// create new wildcard
++nwildcards;
// copy in prefix
strcpy(wildcards[nwildcards-1], wildprefix);
// append search char
chrcat(wildcards[nwildcards-1], *in);
continue;
case LCURLY_CHR:
if ( nwildcards > 0 ) {
chrcat(wildcards[nwildcards-1], *in);
}
continue;
case 'n':
chrcat(name, *in);
continue;
case 'w':
chrcat(wildprefix, *in);
for ( t=0; t<nwildcards; t++ ) {
chrcat(wildcards[t], *in);
}
continue;
}
break;
}
}
}
// SET 'CURRENTLY SELECTED FILTER'
void FNFC_CLASS::filter_value(int i) {
_ofn.nFilterIndex = i + 1;
}
// RETURN VALUE OF 'CURRENTLY SELECTED FILTER'
int FNFC_CLASS::filter_value() const {
return(_ofn.nFilterIndex ? _ofn.nFilterIndex-1 : _nfilters+1);
}
// PRESET FILENAME FOR 'SAVE AS' CHOOSER
void FNFC_CLASS::preset_file(const char* val) {
_preset_file = strfree(_preset_file);
_preset_file = strnew(val);
}
// GET PRESET FILENAME FOR 'SAVE AS' CHOOSER
const char* FNFC_CLASS::preset_file() const {
return(_preset_file);
}