1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2010-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 #  include "config.h"
28 #endif
29 
30 #if defined (HAVE_FLTK)
31 
32 #if defined (WIN32)
33 #  define WIN32_LEAN_AND_MEAN
34 #endif
35 
36 #include <string>
37 
38 #include <FL/Fl.H>
39 #include <FL/Fl_File_Chooser.H>
40 
41 // FLTK headers may include X11/X.h which defines Complex, and that
42 // conflicts with Octave's Complex typedef.  We don't need the X11
43 // Complex definition in this file, so remove it before including Octave
44 // headers which may require Octave's Complex typedef.
45 #undef Complex
46 
47 #endif
48 
49 #include "dMatrix.h"
50 #include "file-ops.h"
51 
52 #include "Cell.h"
53 #include "defun-dld.h"
54 #include "errwarn.h"
55 #include "ov.h"
56 
57 DEFUN_DLD (__fltk_uigetfile__, args, ,
58            doc: /* -*- texinfo -*-
59 @deftypefn {} {} __fltk_uigetfile__ (@dots{})
60 Undocumented internal function.
61 @end deftypefn */)
62 {
63 #if defined (HAVE_FLTK)
64 
65   // Expected argument list:
66   //
67   //   args(0) ... FileFilter in fltk format
68   //   args(1) ... Title
69   //   args(2) ... Default Filename
70   //   args(3) ... PositionValue [x,y]
71   //   args(4) ... SelectValue "on"/"off"/"dir"/"create"
72 
73   octave_value_list retval (3, octave_value (0));
74 
75   std::string file_filter = args(0).string_value ();
76   std::string title = args(1).string_value ();
77   std::string default_name = args(2).string_value ();
78   Matrix pos = args(3).matrix_value ();
79 
80   int multi_type = Fl_File_Chooser::SINGLE;
81   std::string flabel = "Filename:";
82 
83   std::string multi = args(4).string_value ();
84   if (multi == "on")
85     multi_type = Fl_File_Chooser::MULTI;
86   else if (multi == "dir")
87     {
88       multi_type = Fl_File_Chooser::DIRECTORY;
89       flabel = "Directory:";
90     }
91   else if (multi == "create")
92     multi_type = Fl_File_Chooser::CREATE;
93 
94   Fl_File_Chooser::filename_label = flabel.c_str ();
95 
96   Fl_File_Chooser fc (default_name.c_str (), file_filter.c_str (),
97                       multi_type, title.c_str ());
98 
99   fc.preview (0);
100 
101   if (multi_type == Fl_File_Chooser::CREATE)
102     fc.ok_label ("Save");
103 
104   fc.show ();
105 
106   while (fc.shown ())
107     Fl::wait ();
108 
109   if (fc.value ())
110     {
111       int file_count = fc.count ();
112       std::string fname;
113 
114       // FLTK uses forward slash even for Windows
115       std::string sep = "/";
116       std::size_t idx;
117 
118       if (file_count == 1 && multi_type != Fl_File_Chooser::DIRECTORY)
119         {
120           fname = fc.value ();
121           idx = fname.find_last_of (sep);
122           retval(0) = fname.substr (idx + 1);
123         }
124       else
125         {
126           Cell file_cell = Cell (file_count, 1);
127           for (octave_idx_type n = 1; n <= file_count; n++)
128             {
129               fname = fc.value (n);
130               idx = fname.find_last_of (sep);
131               file_cell(n - 1) = fname.substr (idx + 1);
132             }
133           retval(0) = file_cell;
134         }
135 
136       if (multi_type == Fl_File_Chooser::DIRECTORY)
137         retval(0) = octave::sys::file_ops::native_separator_path (std::string (fc.value ()));
138       else
139         {
140           retval(1) = octave::sys::file_ops::native_separator_path (std::string (fc.directory ()) + sep);
141           retval(2) = fc.filter_value () + 1;
142         }
143     }
144 
145   fc.hide ();
146   Fl::flush ();
147 
148   return retval;
149 
150 #else
151 
152   octave_unused_parameter (args);
153 
154   err_disabled_feature ("__fltk_uigetfile__", "OpenGL and FLTK");
155 
156 #endif
157 }
158 
159 /*
160 ## No test needed for internal helper function.
161 %!assert (1)
162 */
163