summaryrefslogtreecommitdiff
path: root/src/Fl_Native_File_Chooser_MAC.mm
diff options
context:
space:
mode:
authormaxim nikonov <maxim.nikonov@hqo.co>2026-02-05 15:21:34 +0500
committermaxim nikonov <maxim.nikonov@hqo.co>2026-02-05 15:21:34 +0500
commitdb214d1145e46d527a46d1fc2519548d2c4d23f1 (patch)
treecf0fd9922e4d54f6beb63888f9b28c8e2a787bdf /src/Fl_Native_File_Chooser_MAC.mm
parent75fc94d6c71fe686f6dde5b41ad91cba2f6bdd6f (diff)
wip: fork
Diffstat (limited to 'src/Fl_Native_File_Chooser_MAC.mm')
-rw-r--r--src/Fl_Native_File_Chooser_MAC.mm825
1 files changed, 0 insertions, 825 deletions
diff --git a/src/Fl_Native_File_Chooser_MAC.mm b/src/Fl_Native_File_Chooser_MAC.mm
deleted file mode 100644
index b3dd9ae8f..000000000
--- a/src/Fl_Native_File_Chooser_MAC.mm
+++ /dev/null
@@ -1,825 +0,0 @@
-//
-// FLTK native OS file chooser widget for macOS
-//
-// Copyright 2004 Greg Ercolano.
-// Copyright 1998-2024 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-// TODO:
-// o When doing 'open file', only dir is preset, not filename.
-// Possibly 'preset_file' could be used to select the filename.
-//
-
-#include <FL/Fl.H>
-#include <FL/platform.H> // for fl_mac_os_version
-#include <FL/Fl_Native_File_Chooser.H>
-#include <FL/Fl_File_Chooser.H>
-#include <FL/filename.H>
-#include <FL/fl_string_functions.h>
-#define MAXFILTERS 80
-#import <Cocoa/Cocoa.h>
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0
-# import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
-#endif
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9
-const NSInteger NSModalResponseOK = NSFileHandlingPanelOKButton;
-#endif
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-const NSUInteger NSControlSizeRegular = NSRegularControlSize;
-#endif
-
-class Fl_Quartz_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_Driver {
-private:
- int _btype; // kind-of browser to show()
- int _options; // general options
- NSSavePanel *_panel;
- char **_pathnames; // array of pathnames
- int _tpathnames; // total pathnames
- char *_directory; // default pathname to use
- char *_title; // title for window
- char *_preset_file; // the 'save as' filename
-
- char *_filter; // user-side search filter, eg:
- // C Files\t*.[ch]\nText Files\t*.txt"
-
- char *_filt_names; // filter names (tab delimited)
- // eg. "C Files\tText Files"
-
- char *_filt_patt[MAXFILTERS];
- // array of filter patterns, eg:
- // _filt_patt[0]="*.{cxx,h}"
- // _filt_patt[1]="*.txt"
-
- int _filt_total; // parse_filter() # of filters loaded
- int _filt_value; // index of the selected filter
- char *_errmsg; // error message
-
- // Private methods
- void errmsg(const char *msg);
- void clear_pathnames();
- void set_single_pathname(const char *s);
- int get_saveas_basename(void);
- void clear_filters();
- void parse_filter(const char *from);
- int post();
- int runmodal();
-public:
- Fl_Quartz_Native_File_Chooser_Driver(int val);
- ~Fl_Quartz_Native_File_Chooser_Driver();
- void type(int t) FL_OVERRIDE;
- int type() const FL_OVERRIDE;
- void options(int o) FL_OVERRIDE;
- int options() const FL_OVERRIDE;
- int count() const FL_OVERRIDE;
- const char *filename() const FL_OVERRIDE;
- const char *filename(int i) const FL_OVERRIDE;
- void directory(const char *val) FL_OVERRIDE;
- const char *directory() const FL_OVERRIDE;
- void title(const char *t) FL_OVERRIDE;
- const char* title() const FL_OVERRIDE;
- const char *filter() const FL_OVERRIDE;
- void filter(const char *f) FL_OVERRIDE;
- int filters() const FL_OVERRIDE;
- void filter_value(int i) FL_OVERRIDE;
- int filter_value() const FL_OVERRIDE;
- void preset_file(const char*f) FL_OVERRIDE;
- const char* preset_file() const FL_OVERRIDE;
- const char *errmsg() const FL_OVERRIDE;
- int show() FL_OVERRIDE;
-};
-
-Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) {
- platform_fnfc = new Fl_Quartz_Native_File_Chooser_Driver(val);
-}
-
-// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS
-void Fl_Quartz_Native_File_Chooser_Driver::clear_pathnames() {
- if ( _pathnames ) {
- while ( --_tpathnames >= 0 ) {
- _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]);
- }
- delete [] _pathnames;
- _pathnames = NULL;
- }
- _tpathnames = 0;
-}
-
-// SET A SINGLE PATHNAME
-void Fl_Quartz_Native_File_Chooser_Driver::set_single_pathname(const char *s) {
- clear_pathnames();
- _pathnames = new char*[1];
- _pathnames[0] = strnew(s);
- _tpathnames = 1;
-}
-
-// CONSTRUCTOR
-Fl_Quartz_Native_File_Chooser_Driver::Fl_Quartz_Native_File_Chooser_Driver(int val) :
- Fl_Native_File_Chooser_Driver(val) {
- _btype = val;
- _panel = NULL;
- _options = Fl_Native_File_Chooser::NO_OPTIONS;
- _pathnames = NULL;
- _tpathnames = 0;
- _title = NULL;
- _filter = NULL;
- _filt_names = NULL;
- memset(_filt_patt, 0, sizeof(char*) * MAXFILTERS);
- _filt_total = 0;
- _filt_value = 0;
- _directory = NULL;
- _preset_file = NULL;
- _errmsg = NULL;
-}
-
-// DESTRUCTOR
-Fl_Quartz_Native_File_Chooser_Driver::~Fl_Quartz_Native_File_Chooser_Driver() {
- // _opts // nothing to manage
- // _options // nothing to manage
- // _keepstate // nothing to manage
- // _tempitem // nothing to manage
- clear_pathnames();
- _directory = strfree(_directory);
- _title = strfree(_title);
- _preset_file = strfree(_preset_file);
- _filter = strfree(_filter);
- //_filt_names // managed by clear_filters()
- //_filt_patt[i] // managed by clear_filters()
- //_filt_total // managed by clear_filters()
- clear_filters();
- //_filt_value // nothing to manage
- _errmsg = strfree(_errmsg);
-}
-
-// GET TYPE OF BROWSER
-int Fl_Quartz_Native_File_Chooser_Driver::type() const {
- return(_btype);
-}
-
-// SET OPTIONS
-void Fl_Quartz_Native_File_Chooser_Driver::options(int val) {
- _options = val;
-}
-
-// GET OPTIONS
-int Fl_Quartz_Native_File_Chooser_Driver::options() const {
- return(_options);
-}
-
-// SHOW THE BROWSER WINDOW
-// Returns:
-// 0 - user picked a file
-// 1 - user cancelled
-// -1 - failed; errmsg() has reason
-//
-int Fl_Quartz_Native_File_Chooser_Driver::show() {
-
- // Make sure fltk interface updates before posting our dialog
- Fl::flush();
-
- // POST BROWSER
- int err = post();
-
- return(err);
-}
-
-// SET ERROR MESSAGE
-// Internal use only.
-//
-void Fl_Quartz_Native_File_Chooser_Driver::errmsg(const char *msg) {
- _errmsg = strfree(_errmsg);
- _errmsg = strnew(msg);
-}
-
-// RETURN ERROR MESSAGE
-const char *Fl_Quartz_Native_File_Chooser_Driver::errmsg() const {
- return(_errmsg ? _errmsg : "No error");
-}
-
-// GET FILENAME
-const char* Fl_Quartz_Native_File_Chooser_Driver::filename() const {
- if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]);
- return("");
-}
-
-// GET FILENAME FROM LIST OF FILENAMES
-const char* Fl_Quartz_Native_File_Chooser_Driver::filename(int i) const {
- if ( _pathnames && i < _tpathnames ) return(_pathnames[i]);
- return("");
-}
-
-// GET TOTAL FILENAMES CHOSEN
-int Fl_Quartz_Native_File_Chooser_Driver::count() const {
- return(_tpathnames);
-}
-
-// PRESET PATHNAME
-// Value can be NULL for none.
-//
-void Fl_Quartz_Native_File_Chooser_Driver::directory(const char *val) {
- _directory = strfree(_directory);
- _directory = strnew(val);
-}
-
-// GET PRESET PATHNAME
-// Returned value can be NULL if none set.
-//
-const char* Fl_Quartz_Native_File_Chooser_Driver::directory() const {
- return(_directory);
-}
-
-// SET TITLE
-// Value can be NULL if no title desired.
-//
-void Fl_Quartz_Native_File_Chooser_Driver::title(const char *val) {
- _title = strfree(_title);
- _title = strnew(val);
-}
-
-// GET TITLE
-// Returned value can be NULL if none set.
-//
-const char *Fl_Quartz_Native_File_Chooser_Driver::title() const {
- return(_title);
-}
-
-// SET FILTER
-// Can be NULL if no filter needed
-//
-void Fl_Quartz_Native_File_Chooser_Driver::filter(const char *val) {
- _filter = strfree(_filter);
- _filter = strnew(val);
-
- // Parse filter user specified
- // IN: _filter = "C Files\t*.{cxx,h}\nText Files\t*.txt"
- // OUT: _filt_names = "C Files\tText Files"
- // _filt_patt[0] = "*.{cxx,h}"
- // _filt_patt[1] = "*.txt"
- // _filt_total = 2
- //
- parse_filter(_filter);
-}
-
-// GET FILTER
-// Returned value can be NULL if none set.
-//
-const char *Fl_Quartz_Native_File_Chooser_Driver::filter() const {
- return(_filter);
-}
-
-// CLEAR ALL FILTERS
-// Internal use only.
-//
-void Fl_Quartz_Native_File_Chooser_Driver::clear_filters() {
- _filt_names = strfree(_filt_names);
- for (int i=0; i<_filt_total; i++) {
- _filt_patt[i] = strfree(_filt_patt[i]);
- }
- _filt_total = 0;
-}
-
-// PARSE USER'S FILTER SPEC
-// Parses user specified filter ('in'),
-// breaks out into _filt_patt[], _filt_names, and _filt_total.
-//
-// Handles:
-// IN: OUT:_filt_names OUT: _filt_patt
-// ------------------------------------ ------------------ ---------------
-// "*.{ma,mb}" "*.{ma,mb} Files" "*.{ma,mb}"
-// "*.[abc]" "*.[abc] Files" "*.[abc]"
-// "*.txt" "*.txt Files" "*.c"
-// "C Files\t*.[ch]" "C Files" "*.[ch]"
-// "C Files\t*.[ch]\nText Files\t*.cxx" "C Files" "*.[ch]"
-//
-// Parsing Mode:
-// IN:"C Files\t*.{cxx,h}"
-// ||||||| |||||||||
-// mode: nnnnnnn wwwwwwwww
-// \_____/ \_______/
-// Name Wildcard
-//
-void Fl_Quartz_Native_File_Chooser_Driver::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=title, w=wildcard
- char wildcard[1024] = ""; // parsed wildcard
- char name[1024] = "";
-
- // Parse filter user specified
- for ( ; 1; in++ ) {
-
- //// DEBUG
- //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n",
- //// *in, mode, name, wildcard);
-
- switch (*in) {
- // FINISHED PARSING NAME?
- case '\t':
- if ( mode != 'n' ) goto regchar;
- mode = 'w';
- break;
-
- // ESCAPE NEXT CHAR
- case '\\':
- ++in;
- goto regchar;
-
- // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
- case '\r':
- case '\n':
- case '\0':
- // TITLE
- // If user didn't specify a name, make one
- //
- if ( name[0] == '\0' ) {
- snprintf(name, sizeof(name), "%.*s Files", (int)sizeof(name)-10, wildcard);
- }
- // APPEND NEW FILTER TO LIST
- if ( wildcard[0] ) {
- // Add to filtername list
- // Tab delimit if more than one. We later break
- // tab delimited string into CFArray with
- // CFStringCreateArrayBySeparatingStrings()
- //
- if ( _filt_total ) {
- _filt_names = strapp(_filt_names, "\t");
- }
- _filt_names = strapp(_filt_names, name);
-
- // Add filter to the pattern array
- _filt_patt[_filt_total++] = strnew(wildcard);
- }
- // RESET
- wildcard[0] = name[0] = '\0';
- mode = strchr(in, '\t') ? 'n' : 'w';
- // DONE?
- if ( *in == '\0' ) return; // done
- else continue; // not done yet, more filters
-
- // Parse all other chars
- default: // handle all non-special chars
- regchar: // handle regular char
- switch ( mode ) {
- case 'n': chrcat(name, *in); continue;
- case 'w': chrcat(wildcard, *in); continue;
- }
- break;
- }
- }
- //NOTREACHED
-}
-
-// SET PRESET FILE
-// Value can be NULL for none.
-//
-void Fl_Quartz_Native_File_Chooser_Driver::preset_file(const char* val) {
- _preset_file = strfree(_preset_file);
- _preset_file = strnew(val);
-}
-
-// PRESET FILE
-// Returned value can be NULL if none set.
-//
-const char* Fl_Quartz_Native_File_Chooser_Driver::preset_file() const {
- return(_preset_file);
-}
-
-void Fl_Quartz_Native_File_Chooser_Driver::filter_value(int val) {
- _filt_value = val;
-}
-
-int Fl_Quartz_Native_File_Chooser_Driver::filter_value() const {
- return(_filt_value);
-}
-
-int Fl_Quartz_Native_File_Chooser_Driver::filters() const {
- return(_filt_total);
-}
-
-#define UNLIKELYPREFIX "___fl_very_unlikely_prefix_"
-
-int Fl_Quartz_Native_File_Chooser_Driver::get_saveas_basename(void) {
- char *q = fl_strdup( [[[_panel URL] path] UTF8String] );
- if ( !(_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM) ) {
- const char *d = [[[[_panel URL] path] stringByDeletingLastPathComponent] UTF8String];
- int l = (int)strlen(d) + 1;
- if (strcmp(d, "/") == 0) l = 1;
- int lu = (int)strlen(UNLIKELYPREFIX);
- int ln = (int)strlen(q+l);
- if (ln >= lu) {
- // Remove UNLIKELYPREFIX between directory and filename parts
- if (memcmp(q+l, UNLIKELYPREFIX, lu) == 0) memmove(q + l, q + l + lu, strlen(q + l + lu) + 1);
- }
- }
- set_single_pathname( q );
- free(q);
- return 0;
-}
-
-// SET THE TYPE OF BROWSER
-void Fl_Quartz_Native_File_Chooser_Driver::type(int val) {
- _btype = val;
-}
-
-/* Input
- filter= "C files\t*.{c,h}\nText files\t*.txt\n"
- patterns[0] = "*.{c,h}"
- patterns[1] = "*.txt"
- count = 2
- Return:
- "C files (*.{c,h})\nText files (*.txt)\n"
- */
-static char *prepareMacFilter(int count, const char *filter, char **patterns) {
- int rank = 0, l = 0;
- for (int i = 0; i < count; i++) {
- l += strlen(patterns[i]) + 3;
- }
- const char *p = filter;
- const int t_size = (int)strlen(p) + l + 1;
- char *q; q = new char[t_size];
- const char *r, *s;
- char *t;
- t = q;
- do { // copy to t what is in filter removing what is between \t and \n, if any
- r = strchr(p, '\n');
- if (!r) r = p + strlen(p);
- s = strchr(p, '\t');
- if (s && s < r) {
- memcpy(q, p, s - p);
- q += s - p;
- if (rank < count) {
- snprintf(q, t_size-(q-t), " (%s)", patterns[rank]); q += strlen(q);
- }
- }
- else {
- memcpy(q, p, r - p);
- q += r - p;
- }
- rank++;
- *(q++) = '\n';
- if (*r) p = r + 1; else p = r;
- } while(*p);
- *q = 0;
- return t;
-}
-
-@interface FLopenDelegate : NSObject <NSOpenSavePanelDelegate>
-{
- NSPopUpButton *nspopup;
- char **filter_pattern;
-}
-- (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern;
-- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
-- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url;
-@end
-@implementation FLopenDelegate
-- (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern
-{
- nspopup = popup;
- filter_pattern = pattern;
- return self;
-}
-- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
-{
- if ( [nspopup indexOfSelectedItem] == [nspopup numberOfItems] - 1) return YES;
- BOOL isdir = NO;
- [[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isdir];
- if (isdir) return YES;
- if ( fl_filename_match([filename fileSystemRepresentation], filter_pattern[([nspopup indexOfSelectedItem])]) ) return YES;
- return NO;
-}
-- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url
-{
- return [self panel:sender shouldShowFilename:[url path]];
-}
-@end
-
-@interface FLsaveDelegate : NSObject <NSOpenSavePanelDelegate>
-{
- NSSavePanel *dialog;
- BOOL saveas_confirm;
-}
-- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag;
-- (void)control_allowed_types:(const char *)p;
-- (void)changedPopup:(id)sender;
-- (void)panel:(NSSavePanel*)p;
-- (void)option:(BOOL)o;
-@end
-@implementation FLsaveDelegate
-- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
-{
- if ( !okFlag || saveas_confirm ) return filename;
- // User has clicked save, and no overwrite confirmation should occur.
- // To get the latter, we need to change the name we return (hence the prefix):
- return [@ UNLIKELYPREFIX stringByAppendingString:filename];
-}
-- (void)control_allowed_types:(const char *)p
-{
- NSString *ext = [NSString stringWithUTF8String:p];
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0
- if (@available(macOS 11.0, *)) {
- UTType *type = [UTType typeWithFilenameExtension:ext]; // 11.0 + framework UniformTypeIdentifiers
- [dialog setAllowedContentTypes:[NSArray arrayWithObject:type]]; // 11.0
- }
- else
-#endif
- if (fl_mac_os_version >= 100900) {
- [dialog performSelector:@selector(setAllowedFileTypes:)
- withObject:[NSArray arrayWithObject:ext]];
- }
-}
-- (void)changedPopup:(id)sender
-// runs when the save panel popup menu changes output file type
-// correspondingly changes the extension of the output file name
-{
- char *s = fl_strdup([[(NSPopUpButton*)sender titleOfSelectedItem] UTF8String]);
- if (!s) return;
- char *p = strchr(s, '(');
- if (!p) p = s;
- p = strchr(p, '.');
- if (!p) {free(s); return;}
- p++;
- while (*p == ' ') p++;
- if (!p || *p == '{') {free(s); return;}
- char *q = p+1;
- while (*q != ' ' && *q != ')' && *q != 0) q++;
- *q = 0;
- NSString *ns = [NSString stringWithFormat:@"%@.%@",
- [[dialog performSelector:@selector(nameFieldStringValue)] stringByDeletingPathExtension],
- [NSString stringWithUTF8String:p]];
- [self control_allowed_types:p];
- free(s);
- [dialog performSelector:@selector(setNameFieldStringValue:) withObject:ns];
-}
-- (void)panel:(NSSavePanel*)p
-{
- dialog = p;
-}
-- (void) option:(BOOL)o
-{
- saveas_confirm = o;
-}
-@end
-
-
-@interface FLHiddenFilesAction : NSObject
-{
-@public
- NSSavePanel *panel;
- NSButton *button;
-}
-- (void)action;
-@end
-@implementation FLHiddenFilesAction
-- (void)action {
- [panel setShowsHiddenFiles:[button intValue]]; // 10.6
-}
-@end
-
-
-static NSPopUpButton *createPopupAccessory(NSSavePanel *panel, const char *filter, const char *title, int rank)
-{
- NSPopUpButton *popup = nil;
- NSRect rectview = NSMakeRect(5, 5, 350, filter ? 60 : 30);
- NSView *view = [[[NSView alloc] initWithFrame:rectview] autorelease];
- NSRect rectbox = NSMakeRect(0, 3, 140, 20 );
- // the "Show hidden files" button
- NSRect hidden_files_rect = {{150, 0}, {80, 30}};
- if (filter) hidden_files_rect.origin.y = 35;
- NSButton *hidden_files = [[[NSButton alloc] initWithFrame:hidden_files_rect] autorelease];
- [hidden_files setButtonType:
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
- NSButtonTypeSwitch
-#else
- NSSwitchButton
-#endif
- ];
- [hidden_files setTitle:[NSString stringWithUTF8String:Fl_File_Chooser::hidden_label]];
- [hidden_files sizeToFit];
- [hidden_files setIntValue:0];
- [view addSubview:hidden_files];
- static FLHiddenFilesAction *target = [[FLHiddenFilesAction alloc] init]; // never released
- target->panel = panel;
- target->button = hidden_files;
- [hidden_files setAction:@selector(action)];
- [hidden_files setTarget:target];
- if (filter) {
- NSBox *box = [[[NSBox alloc] initWithFrame:rectbox] autorelease];
- NSRect rectpop = NSMakeRect(105, 0, 246, 30 );
- popup = [[[NSPopUpButton alloc ] initWithFrame:rectpop pullsDown:NO] autorelease];
- [view addSubview:box];
- [view addSubview:popup];
- NSString *nstitle = [[NSString alloc] initWithUTF8String:title];
- [box setTitle:nstitle];
- [box setTitlePosition:NSBelowTop];
- [nstitle release];
- NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
- [box setTitleFont:font];
- [box sizeToFit];
- // horizontally move box to fit the locale-dependent width of its title
- NSRect r=[box frame];
- r.origin.x = rectpop.origin.x - r.size.width;
- r.origin.y = rectpop.origin.y + (rectpop.size.height - r.size.height) / 2;
- [box setFrame:r];
- CFStringRef tab = CFSTR("\n");
- CFStringRef tmp_cfs;
- tmp_cfs = CFStringCreateWithCString(NULL, filter, kCFStringEncodingUTF8);
- CFArrayRef array = CFStringCreateArrayBySeparatingStrings(NULL, tmp_cfs, tab);
- CFRelease(tmp_cfs);
- CFRelease(tab);
- [popup addItemsWithTitles:(NSArray*)array];
- NSMenuItem *item = [popup itemWithTitle:@""];
- if (item) [popup removeItemWithTitle:@""];
- CFRelease(array);
- [popup selectItemAtIndex:rank];
- }
- [panel setAccessoryView:view];
- return popup;
-}
-
-int Fl_Quartz_Native_File_Chooser_Driver::runmodal()
-{
- NSString *dir = nil;
- NSString *fname = nil;
- NSString *preset = nil;
- NSInteger retval;
- if (_preset_file) {
- preset = [[NSString alloc] initWithUTF8String:_preset_file];
- if (strchr(_preset_file, '/') != NULL) {
- dir = [[NSString alloc] initWithString:[preset stringByDeletingLastPathComponent]];
- }
- fname = [preset lastPathComponent];
- }
- if (_directory && !dir) dir = [[NSString alloc] initWithUTF8String:_directory];
-#if defined(__BLOCKS__)
- {
- bool usepath = false;
- NSString *path = nil;
- if (dir && fname && [_panel isKindOfClass:[NSOpenPanel class]]) {
- // STR #3406: If both dir + fname specified, combine and pass to setDirectoryURL
- path = [[NSString alloc] initWithFormat:@"%@/%@", dir, fname]; // dir+fname -> path
- // See if full path to file exists
- // If dir exists but fname doesn't, avoid using setDirectoryURL,
- // otherwise NSSavePanel falls back to showing user's Documents dir.
- //
- if ( [[NSFileManager defaultManager] fileExistsAtPath:path] ) usepath = true;
- }
- if (usepath) {
- // Set only if full path exists
- [_panel setDirectoryURL:[NSURL fileURLWithPath:path]]; // 10.6
- } else { // didn't setDirectoryURL to full path? Set dir + fname separately..
- if (dir) [_panel setDirectoryURL:[NSURL fileURLWithPath:dir]]; // 10.6
- if (fname) [_panel setNameFieldStringValue:fname]; // 10.6
- }
- [path release];
- if ([NSApp mainWindow]) {
- __block NSInteger complete = -1;
- [_panel beginSheetModalForWindow:[NSApp mainWindow] completionHandler:^(NSInteger returnCode) {
- complete = returnCode; // this block runs after OK or Cancel was triggered in file dialog
- }]; // 10.6 this message returns immediately and begins the file dialog as a sheet
- while (complete == -1) Fl::wait(100); // loop until end of file dialog
- retval = complete;
- } else {
- retval = [_panel runModal];
- }
- }
-#else // !__BLOCKS__
- // the deprecation warning runs only without blocks
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- retval = [_panel runModalForDirectory:dir file:fname]; // deprecated in 10.6
-#pragma clang diagnostic pop
-#endif // __BLOCKS__
- [dir release];
- [preset release];
- return (retval == NSModalResponseOK ? 1 : 0);
-}
-
-// POST BROWSER
-// Internal use only.
-// Assumes '_opts' has been initialized.
-//
-// Returns:
-// 0 - user picked a file
-// 1 - user cancelled
-// -1 - failed; errmsg() has reason
-//
-int Fl_Quartz_Native_File_Chooser_Driver::post() {
- // INITIALIZE BROWSER
- if ( _filt_total == 0 ) { // Make sure they match
- _filt_value = 0; // TBD: move to someplace more logical?
- }
- fl_open_display();
- NSAutoreleasePool *localPool;
- localPool = [[NSAutoreleasePool alloc] init];
- switch (_btype) {
- case Fl_Native_File_Chooser::BROWSE_FILE:
- case Fl_Native_File_Chooser::BROWSE_MULTI_FILE:
- case Fl_Native_File_Chooser::BROWSE_DIRECTORY:
- case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY:
- _panel = [NSOpenPanel openPanel];
- break;
- case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY:
- case Fl_Native_File_Chooser::BROWSE_SAVE_FILE:
- _panel = [NSSavePanel savePanel];
- break;
- }
- BOOL is_open_panel = [_panel isKindOfClass:[NSOpenPanel class]];
- if (_title) {
- SEL title_or_message = (is_open_panel && fl_mac_os_version >= 101200) ?
- @selector(setMessage:) : @selector(setTitle:);
- [_panel performSelector:title_or_message withObject:[NSString stringWithUTF8String:_title]];
- }
- switch (_btype) {
- case Fl_Native_File_Chooser::BROWSE_MULTI_FILE:
- [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES];
- break;
- case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY:
- [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES];
- /* FALLTHROUGH */
- case Fl_Native_File_Chooser::BROWSE_DIRECTORY:
- [(NSOpenPanel*)_panel setCanChooseDirectories:YES];
- break;
- case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY:
- [_panel setCanCreateDirectories:YES];
- break;
- }
-
- // SHOW THE DIALOG
- NSWindow *key = [NSApp keyWindow];
- NSPopUpButton *popup = nil;
- if ( is_open_panel ) {
- if (_filt_total) {
- char *t = prepareMacFilter(_filt_total, _filter, _filt_patt);
- popup = createPopupAccessory(_panel, t, Fl_File_Chooser::show_label, 0);
- delete[] t;
- [[popup menu] addItem:[NSMenuItem separatorItem]];
- [popup addItemWithTitle:[NSString stringWithUTF8String:Fl_File_Chooser::all_files_label]];
- [popup setAction:@selector(validateVisibleColumns)];
- [popup setTarget:(NSObject*)_panel];
- FLopenDelegate *openDelegate = [[[FLopenDelegate alloc] init] autorelease];
- [openDelegate setPopup:popup filter_pattern:_filt_patt];
- [_panel setDelegate:openDelegate];
- } else createPopupAccessory(_panel, NULL, Fl_File_Chooser::show_label, 0);
- }
- else {
- FLsaveDelegate *saveDelegate = [[[FLsaveDelegate alloc] init] autorelease];
- [_panel setAllowsOtherFileTypes:YES];
- [_panel setDelegate:saveDelegate];
- [saveDelegate option:(_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM)];
- if (_filt_total) {
- if (_filt_value >= _filt_total) _filt_value = _filt_total - 1;
- char *t = prepareMacFilter(_filt_total, _filter, _filt_patt);
- popup = createPopupAccessory(_panel, t, [[_panel nameFieldLabel] UTF8String], _filt_value);
- delete[] t;
- if (_options & Fl_Native_File_Chooser::USE_FILTER_EXT) {
- [popup setAction:@selector(changedPopup:)];
- [popup setTarget:saveDelegate];
- [saveDelegate panel:(NSSavePanel*)_panel];
- if (fl_mac_os_version >= 100900) {
- char *p = _filt_patt[_filt_value];
- char *q = strchr(p, '.'); if(!q) q = p-1;
- do q++; while (*q==' ' || *q=='{');
- p = fl_strdup(q);
- q = strchr(p, ','); if (q) *q = 0;
- [saveDelegate control_allowed_types:p];
- free(p);
- }
- }
- [_panel setCanSelectHiddenExtension:YES];
- [_panel setExtensionHidden:NO];
- } else createPopupAccessory(_panel, NULL, Fl_File_Chooser::show_label, 0);
- }
- int retval = runmodal();
- if (_filt_total) {
- _filt_value = (int)[popup indexOfSelectedItem];
- }
- if ( retval == 1 ) {
- if (is_open_panel) {
- clear_pathnames();
- NSArray *array = [(NSOpenPanel*)_panel URLs];
- _tpathnames = (int)[array count];
- _pathnames = new char*[_tpathnames];
- for(int i = 0; i < _tpathnames; i++) {
- _pathnames[i] = strnew([[(NSURL*)[array objectAtIndex:i] path] UTF8String]);
- }
- }
- else get_saveas_basename();
- }
- [key makeKeyWindow];
- [localPool release];
- return (retval == 1 ? 0 : 1);
-}