├── files.xml
├── README.md
├── tinyfiledialogs.h
└── tinyfiledialogs.c
/files.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Official version hosted at https://sourceforge.net/projects/tinyfiledialogs/
2 |
3 | This version is _not_ official and is currently updated as required by https://github.com/haxelime/lime only
4 |
5 | # tinyfiledialogs
6 |
7 |
8 | _________
9 | / \ tiny file dialogs ( cross-platform C C++ )
10 | |tiny file| v2.9.3 [July 12, 2017] zlib licence
11 | | dialogs | InputBox PasswordBox MessageBox ColorPicker
12 | \____ ___/ OpenFileDialog SaveFileDialog SelectFolderDialog
13 | \| ASCII UTF-8 (and also MBCS UTF-16 for windows)
14 | Native dialog library for WINDOWS MAC OSX GTK+ QT CONSOLE
15 |
16 | SSH supported via automatic switch to console mode or X11 forwarding
17 |
18 | tested with C & C++ compilers on
19 | Visual Studio MinGW OSX LINUX FREEBSD OPENBSD ILLUMOS SOLARIS MINIX RASPBIAN
20 | using
21 | Gnome Kde Mate Cinnamon Unity Lxde Lxqt Xfce Enlightenment
22 | WindowMaker IceWm Cde Jds OpenBox Awesome Jwm
23 |
24 | bindings for LUA and C# dll
25 | included in LWJGL(java), rust, Allegrobasic
26 |
27 | http://tinyfiledialogs.sourceforge.net
28 | git://git.code.sf.net/p/tinyfiledialogs/code
29 | _________________________________________________________________________
30 | | |
31 | | CONTACT me directly via the email address at the top of the header file |
32 | |_________________________________________________________________________|
33 |
34 | if you absolutely want them, the windows only wchar_t prototypes are in the header file
35 |
36 | int tinyfd_messageBox (
37 | char const * const aTitle , // ""
38 | char const * const aMessage , // "" may contain \n \t
39 | char const * const aDialogType , // "ok" "okcancel" "yesno" "yesnocancel"
40 | char const * const aIconType , // "info" "warning" "error" "question"
41 | int const aDefaultButton ) ;
42 | // 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel
43 |
44 | char const * tinyfd_inputBox (
45 | char const * const aTitle , // ""
46 | char const * const aMessage , // "" may NOT contain \n \t on windows
47 | char const * const aDefaultInput ) ; // "" , if NULL it's a passwordBox
48 | // returns NULL on cancel
49 |
50 | char const * tinyfd_saveFileDialog (
51 | char const * const aTitle , // ""
52 | char const * const aDefaultPathAndFile , // ""
53 | int const aNumOfFilterPatterns , // 0
54 | char const * const * const aFilterPatterns , // NULL | {"*.txt"}
55 | char const * const aSingleFilterDescription ) ; // NULL | "text files"
56 | // returns NULL on cancel
57 |
58 | char const * tinyfd_openFileDialog (
59 | char const * const aTitle , // ""
60 | char const * const aDefaultPathAndFile , // ""
61 | int const aNumOfFilterPatterns , // 0
62 | char const * const * const aFilterPatterns , // NULL {"*.jpg","*.png"}
63 | char const * const aSingleFilterDescription , // NULL | "image files"
64 | int const aAllowMultipleSelects ) ; // 0
65 | // in case of multiple files, the separator is |
66 | // returns NULL on cancel
67 |
68 | char const * tinyfd_selectFolderDialog (
69 | char const * const aTitle , // ""
70 | char const * const aDefaultPath ) ; // ""
71 | // returns NULL on cancel
72 |
73 | char const * tinyfd_colorChooser(
74 | char const * const aTitle , // ""
75 | char const * const aDefaultHexRGB , // NULL or "#FF0000”
76 | unsigned char const aDefaultRGB[3] , // { 0 , 255 , 255 }
77 | unsigned char aoResultRGB[3] ) ; // { 0 , 0 , 0 }
78 | // returns the hexcolor as a string "#FF0000"
79 | // aoResultRGB also contains the result
80 | // aDefaultRGB is used only if aDefaultHexRGB is NULL
81 | // aDefaultRGB and aoResultRGB can be the same array
82 | // returns NULL on cancel
83 |
84 | - This is not for android nor ios.
85 | - The code is pure C, perfectly compatible with C++.
86 | - the windows only wchar_t (utf-16) prototypes are in the header file
87 | - windows is fully supported from XP to 10 (maybe even older versions)
88 | - C# & LUA via dll, see files in the folder EXTRAS
89 | - OSX supported from 10.4 to 10.12 (maybe even older versions)
90 | - Avoid using " and ' in titles and messages.
91 | - There's one file filter only, it may contain several patterns.
92 | - If no filter description is provided,
93 | the list of patterns will become the description.
94 | - char const * filterPatterns[3] = { "*.obj" , "*.stl" , "*.dxf" } ;
95 | - On windows link against Comdlg32.lib and Ole32.lib
96 | (on windows the no linking claim is a lie)
97 | This linking is not compulsary for console mode (see header file).
98 | - On unix: it tries command line calls, so no such need (NO LINKING).
99 | - On unix you need applescript, zenity, matedialog, qarma, kdialog, Xdialog,
100 | python2/tkinter or dialog (will open a terminal if running without console).
101 | - One of those is already included on most (if not all) desktops.
102 | - In the absence of those it will use gdialog, gxmessage or whiptail
103 | with a textinputbox.
104 | - If nothing is found, it switches to basic console input,
105 | it opens a console if needed (requires xterm + bash).
106 | - Use windows separators on windows and unix separators on unix.
107 | - String memory is preallocated statically for all the returned values.
108 | - File and path names are tested before return, they are valid.
109 | - If you pass only a path instead of path + filename,
110 | make sure it ends with a separator.
111 | - tinyfd_forceConsole=1; at run time, forces dialogs into console mode.
112 | - On windows, console mode only make sense for console applications.
113 | - Mutiple selects are not allowed in console mode.
114 | - The package dialog must be installed to run in enhanced console mode.
115 | It is already installed on most unix systems.
116 | - On osx, the package dialog can be installed via http://macports.org
117 | - On windows, for enhanced console mode,
118 | dialog.exe should be copied somewhere on your executable path.
119 | It can be found at the bottom of the following page:
120 | http://andrear.altervista.org/home/cdialog.php
121 | - If dialog is missing, it will switch to basic console input.
122 | - You can query the type of dialog that will be use.
123 | - MinGW needs gcc >= v4.9 otherwise some headers are incomplete.
124 |
125 | - Here is the Hello World:
126 | if a console is missing, it will use graphic dialogs
127 | if a graphical display is absent, it will use console dialogs
128 |
129 |
130 | hello.c
131 | #include
132 | #include
133 | #include "tinyfiledialogs.h"
134 | int main()
135 | {
136 | char const * lTmp;
137 | char const * lTheSaveFileName;
138 | char const * lTheOpenFileName;
139 | char const * lTheSelectFolderName;
140 | char const * lTheHexColor;
141 | char const * lWillBeGraphicMode;
142 | unsigned char lRgbColor[3];
143 | FILE * lIn;
144 | char lBuffer[1024];
145 | char lThePassword[1024];
146 | char const * lFilterPatterns[2] = { "*.txt", "*.text" };
147 |
148 | lWillBeGraphicMode = tinyfd_inputBox("tinyfd_query", NULL, NULL);
149 |
150 | if (lWillBeGraphicMode)
151 | {
152 | strcpy(lBuffer, "graphic mode: ");
153 | }
154 | else
155 | {
156 | strcpy(lBuffer, "console mode: ");
157 | }
158 |
159 | strcat(lBuffer, tinyfd_response);
160 | strcpy(lThePassword, "tinyfiledialogs v");
161 | strcat(lThePassword, tinyfd_version);
162 | tinyfd_messageBox(lThePassword, lBuffer, "ok", "info", 0);
163 |
164 | if ( lWillBeGraphicMode && ! tinyfd_forceConsole )
165 | {
166 | tinyfd_forceConsole = ! tinyfd_messageBox("Hello World",
167 | "graphic dialogs [yes] / console mode [no]?",
168 | "yesno", "question", 1);
169 | }
170 |
171 | lTmp = tinyfd_inputBox(
172 | "a password box", "your password will be revealed", NULL);
173 |
174 | if (!lTmp) return 1 ;
175 |
176 | /* copy lTmp because saveDialog would overwrites
177 | inputBox static buffer in basicinput mode */
178 |
179 | strcpy(lThePassword, lTmp);
180 |
181 | lTheSaveFileName = tinyfd_saveFileDialog(
182 | "let us save this password",
183 | "passwordFile.txt",
184 | 2,
185 | lFilterPatterns,
186 | NULL);
187 |
188 | if (! lTheSaveFileName)
189 | {
190 | tinyfd_messageBox(
191 | "Error",
192 | "Save file name is NULL",
193 | "ok",
194 | "error",
195 | 1);
196 | return 1 ;
197 | }
198 |
199 | lIn = fopen(lTheSaveFileName, "w");
200 | if (!lIn)
201 | {
202 | tinyfd_messageBox(
203 | "Error",
204 | "Can not open this file in write mode",
205 | "ok",
206 | "error",
207 | 1);
208 | return 1 ;
209 | }
210 | fputs(lThePassword, lIn);
211 | fclose(lIn);
212 |
213 | lTheOpenFileName = tinyfd_openFileDialog(
214 | "let us read the password back",
215 | "",
216 | 2,
217 | lFilterPatterns,
218 | NULL,
219 | 0);
220 |
221 | if (! lTheOpenFileName)
222 | {
223 | tinyfd_messageBox(
224 | "Error",
225 | "Open file name is NULL",
226 | "ok",
227 | "error",
228 | 1);
229 | return 1 ;
230 | }
231 |
232 | lIn = fopen(lTheOpenFileName, "r");
233 |
234 | if (!lIn)
235 | {
236 | tinyfd_messageBox(
237 | "Error",
238 | "Can not open this file in read mode",
239 | "ok",
240 | "error",
241 | 1);
242 | return(1);
243 | }
244 | lBuffer[0] = '\0';
245 | fgets(lBuffer, sizeof(lBuffer), lIn);
246 | fclose(lIn);
247 |
248 | tinyfd_messageBox("your password is",
249 | lBuffer, "ok", "info", 1);
250 |
251 | lTheSelectFolderName = tinyfd_selectFolderDialog(
252 | "let us just select a directory", NULL);
253 |
254 | if (!lTheSelectFolderName)
255 | {
256 | tinyfd_messageBox(
257 | "Error",
258 | "Select folder name is NULL",
259 | "ok",
260 | "error",
261 | 1);
262 | return 1;
263 | }
264 |
265 | tinyfd_messageBox("The selected folder is",
266 | lTheSelectFolderName, "ok", "info", 1);
267 |
268 | lTheHexColor = tinyfd_colorChooser(
269 | "choose a nice color",
270 | "#FF0077",
271 | lRgbColor,
272 | lRgbColor);
273 |
274 | if (!lTheHexColor)
275 | {
276 | tinyfd_messageBox(
277 | "Error",
278 | "hexcolor is NULL",
279 | "ok",
280 | "error",
281 | 1);
282 | return 1;
283 | }
284 |
285 | tinyfd_messageBox("The selected hexcolor is",
286 | lTheHexColor, "ok", "info", 1);
287 |
288 | return 0;
289 | }
290 |
291 |
292 | OSX :
293 | $ gcc -o hello.app hello.c tinyfiledialogs.c
294 |
295 | UNIX :
296 | $ gcc -o hello hello.c tinyfiledialogs.c
297 | ( or clang tcc cc CC )
298 |
299 | MinGW (needs gcc >= v4.9 otherwise some headers are incomplete):
300 | > gcc -o hello.exe hello.c tinyfiledialogs.c -LC:/mingw/lib -lcomdlg32 -lole32
301 | (unfortunately some headers are missing with tcc)
302 |
303 | VisualStudio :
304 | Create a console application project,
305 | it links against Comdlg32.lib & Ole32.lib.
306 |
307 |
308 |
--------------------------------------------------------------------------------
/tinyfiledialogs.h:
--------------------------------------------------------------------------------
1 | /*_________
2 | / \ tinyfiledialogs.h v2.9.3 [July 12, 2017] zlib licence
3 | |tiny file| Unique header file created [November 9, 2014]
4 | | dialogs | Copyright (c) 2014 - 2017 Guillaume Vareille http://ysengrin.com
5 | \____ ___/ http://tinyfiledialogs.sourceforge.net
6 | \|
7 | git://git.code.sf.net/p/tinyfiledialogs/code
8 | ______________________________________________
9 | | |
10 | | email: tinyfiledialogs@ysengrin.com |
11 | |______________________________________________|
12 |
13 | A big thank you to Don Heyse http://ldglite.sf.net for
14 | his code contributions, bug corrections & thorough testing!
15 |
16 | git://git.code.sf.net/p/tinyfiledialogs/code
17 |
18 | Please
19 | 1) let me know
20 | - if you are including tiny file dialogs,
21 | I'll be happy to add your link to the list of projects using it.
22 | - If you are using it on different hardware / OS / compiler.
23 | 2) leave a review on Sourceforge. Thanks.
24 |
25 | tiny file dialogs (cross-platform C C++)
26 | InputBox PasswordBox MessageBox ColorPicker
27 | OpenFileDialog SaveFileDialog SelectFolderDialog
28 | Native dialog library for WINDOWS MAC OSX GTK+ QT CONSOLE & more
29 | SSH supported via automatic switch to console mode or X11 forwarding
30 |
31 | One C file (add it to your C or C++ project) with 6 functions:
32 | - message & question
33 | - input & password
34 | - save file
35 | - open file(s)
36 | - select folder
37 | - color picker
38 |
39 | Complements OpenGL GLFW GLUT GLUI VTK SFML TGUI SDL Ogre Unity3d ION OpenCV
40 | CEGUI MathGL GLM CPW GLOW IMGUI MyGUI GLT NGL STB & GUI less programs
41 |
42 | NO INIT
43 | NO MAIN LOOP
44 | NO LINKING
45 | NO INCLUDE
46 |
47 | The dialogs can be forced into console mode
48 |
49 | Windows (XP to 10) ASCII MBCS UTF-8 UTF-16
50 | - native code & vbs create the graphic dialogs
51 | - enhanced console mode can use dialog.exe from
52 | http://andrear.altervista.org/home/cdialog.php
53 | - basic console input
54 |
55 | Unix (command line calls) ASCII UTF-8
56 | - applescript
57 | - zenity / matedialog / qarma (zenity for qt)
58 | - kdialog
59 | - Xdialog
60 | - python2 tkinter
61 | - dialog (opens a console if needed)
62 | - basic console input
63 | The same executable can run across desktops & distributions
64 |
65 | tested with C & C++ compilers
66 | on VisualStudio MinGW Mac Linux Bsd Solaris Minix Raspbian
67 | using Gnome Kde Enlightenment Mate Cinnamon Unity
68 | Lxde Lxqt Xfce WindowMaker IceWm Cde Jds OpenBox Awesome Jwm
69 |
70 | bindings for LUA and C# dll
71 | included in LWJGL(java), rust, Allegrobasic
72 |
73 | - License -
74 |
75 | This software is provided 'as-is', without any express or implied
76 | warranty. In no event will the authors be held liable for any damages
77 | arising from the use of this software.
78 |
79 | Permission is granted to anyone to use this software for any purpose,
80 | including commercial applications, and to alter it and redistribute it
81 | freely, subject to the following restrictions:
82 |
83 | 1. The origin of this software must not be misrepresented; you must not
84 | claim that you wrote the original software. If you use this software
85 | in a product, an acknowledgment in the product documentation would be
86 | appreciated but is not required.
87 | 2. Altered source versions must be plainly marked as such, and must not be
88 | misrepresented as being the original software.
89 | 3. This notice may not be removed or altered from any source distribution.
90 | */
91 |
92 | #ifndef TINYFILEDIALOGS_H
93 | #define TINYFILEDIALOGS_H
94 |
95 | /* #define TINYFD_NOLIB */
96 | /* On windows, define TINYFD_NOLIB here
97 | if you don't want to include the code creating the graphic dialogs.
98 | Then you won't need to link against Comdlg32.lib and Ole32.lib */
99 |
100 | /* if tinydialogs.c is compiled with a C++ compiler rather than with a C compiler
101 | (ie. you change the extension from .c to .cpp), you need to comment out:
102 | extern "C" {
103 | and the corresponding closing bracket near the end of this file:
104 | }
105 | */
106 | #ifdef __cplusplus
107 | extern "C" {
108 | #endif
109 |
110 | extern char tinyfd_version[8]; /* contains tinyfd current version number */
111 |
112 | #ifdef _WIN32
113 | /* for UTF-16 use the functions at the end of this files */
114 | extern int tinyfd_winUtf8; /* 0 (default) or 1 */
115 | /* on windows string char can be 0:MBSC or 1:UTF-8
116 | unless your code is really prepared for UTF-8 on windows, leave this on MBSC.
117 | Or you can use the UTF-16 (wchar) prototypes at the end of ths file.*/
118 | #endif
119 |
120 | extern int tinyfd_forceConsole ; /* 0 (default) or 1 */
121 | /* for unix & windows: 0 (graphic mode) or 1 (console mode).
122 | 0: try to use a graphic solution, if it fails then it uses console mode.
123 | 1: forces all dialogs into console mode even when an X server is present,
124 | if the package dialog (and a console is present) or dialog.exe is installed.
125 | on windows it only make sense for console applications */
126 |
127 | extern char tinyfd_response[1024];
128 | /* if you pass "tinyfd_query" as aTitle,
129 | the functions will not display the dialogs
130 | but will return 0 for console mode, 1 for graphic mode.
131 | tinyfd_response is then filled with the retain solution.
132 | possible values for tinyfd_response are (all lowercase)
133 | for the graphic mode:
134 | windows applescript zenity zenity3 matedialog qarma kdialog
135 | xdialog tkinter gdialog gxmessage xmessage
136 | for the console mode:
137 | dialog whiptail basicinput */
138 |
139 | int tinyfd_messageBox (
140 | char const * const aTitle , /* "" */
141 | char const * const aMessage , /* "" may contain \n \t */
142 | char const * const aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
143 | char const * const aIconType , /* "info" "warning" "error" "question" */
144 | int const aDefaultButton ) ;
145 | /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
146 |
147 | char const * tinyfd_inputBox (
148 | char const * const aTitle , /* "" */
149 | char const * const aMessage , /* "" may NOT contain \n \t on windows */
150 | char const * const aDefaultInput ) ; /* "" , if NULL it's a passwordBox */
151 | /* returns NULL on cancel */
152 |
153 | char const * tinyfd_saveFileDialog (
154 | char const * const aTitle , /* "" */
155 | char const * const aDefaultPathAndFile , /* "" */
156 | int const aNumOfFilterPatterns , /* 0 */
157 | char const * const * const aFilterPatterns , /* NULL | {"*.jpg","*.png"} */
158 | char const * const aSingleFilterDescription ) ; /* NULL | "text files" */
159 | /* returns NULL on cancel */
160 |
161 | char const * tinyfd_openFileDialog (
162 | char const * const aTitle , /* "" */
163 | char const * const aDefaultPathAndFile , /* "" */
164 | int const aNumOfFilterPatterns , /* 0 */
165 | char const * const * const aFilterPatterns , /* NULL {"*.jpg","*.png"} */
166 | char const * const aSingleFilterDescription , /* NULL | "image files" */
167 | int const aAllowMultipleSelects ) ; /* 0 or 1 */
168 | /* in case of multiple files, the separator is | */
169 | /* returns NULL on cancel */
170 |
171 | char const * tinyfd_selectFolderDialog (
172 | char const * const aTitle , /* "" */
173 | char const * const aDefaultPath ) ; /* "" */
174 | /* returns NULL on cancel */
175 |
176 | char const * tinyfd_colorChooser(
177 | char const * const aTitle , /* "" */
178 | char const * const aDefaultHexRGB , /* NULL or "#FF0000" */
179 | unsigned char const aDefaultRGB[3] , /* { 0 , 255 , 255 } */
180 | unsigned char aoResultRGB[3] ) ; /* { 0 , 0 , 0 } */
181 | /* returns the hexcolor as a string "#FF0000" */
182 | /* aoResultRGB also contains the result */
183 | /* aDefaultRGB is used only if aDefaultHexRGB is NULL */
184 | /* aDefaultRGB and aoResultRGB can be the same array */
185 | /* returns NULL on cancel */
186 |
187 |
188 | /************ NOT CROSS PLATFORM SECTION STARTS HERE ************************/
189 | #ifdef _WIN32
190 | #ifndef TINYFD_NOLIB
191 |
192 | /* windows only - utf-16 version */
193 | int tinyfd_messageBoxW(
194 | wchar_t const * const aTitle ,
195 | wchar_t const * const aMessage, /* "" may contain \n \t */
196 | wchar_t const * const aDialogType, /* "ok" "okcancel" "yesno" */
197 | wchar_t const * const aIconType, /* "info" "warning" "error" "question" */
198 | int const aDefaultButton ); /* 0 for cancel/no , 1 for ok/yes */
199 | /* returns 0 for cancel/no , 1 for ok/yes */
200 |
201 | /* windows only - utf-16 version */
202 | wchar_t const * tinyfd_saveFileDialogW(
203 | wchar_t const * const aTitle, /* NULL or "" */
204 | wchar_t const * const aDefaultPathAndFile, /* NULL or "" */
205 | int const aNumOfFilterPatterns, /* 0 */
206 | wchar_t const * const * const aFilterPatterns, /* NULL or {"*.jpg","*.png"} */
207 | wchar_t const * const aSingleFilterDescription); /* NULL or "image files" */
208 | /* returns NULL on cancel */
209 |
210 | /* windows only - utf-16 version */
211 | wchar_t const * tinyfd_openFileDialogW(
212 | wchar_t const * const aTitle, /* "" */
213 | wchar_t const * const aDefaultPathAndFile, /* "" */
214 | int const aNumOfFilterPatterns , /* 0 */
215 | wchar_t const * const * const aFilterPatterns, /* NULL {"*.jpg","*.png"} */
216 | wchar_t const * const aSingleFilterDescription, /* NULL | "image files" */
217 | int const aAllowMultipleSelects ) ; /* 0 or 1 */
218 | /* in case of multiple files, the separator is | */
219 | /* returns NULL on cancel */
220 |
221 | /* windows only - utf-16 version */
222 | wchar_t const * tinyfd_selectFolderDialogW(
223 | wchar_t const * const aTitle, /* "" */
224 | wchar_t const * const aDefaultPath); /* "" */
225 | /* returns NULL on cancel */
226 |
227 | /* windows only - utf-16 version */
228 | wchar_t const * tinyfd_colorChooserW(
229 | wchar_t const * const aTitle, /* "" */
230 | wchar_t const * const aDefaultHexRGB, /* NULL or "#FF0000" */
231 | unsigned char const aDefaultRGB[3] , /* { 0 , 255 , 255 } */
232 | unsigned char aoResultRGB[3] ) ; /* { 0 , 0 , 0 } */
233 | /* returns the hexcolor as a string "#FF0000" */
234 | /* aoResultRGB also contains the result */
235 | /* aDefaultRGB is used only if aDefaultHexRGB is NULL */
236 | /* aDefaultRGB and aoResultRGB can be the same array */
237 | /* returns NULL on cancel */
238 |
239 |
240 | #endif /*TINYFD_NOLIB*/
241 | #else /*_WIN32*/
242 |
243 | /* unix zenity only */
244 | char const * tinyfd_arrayDialog(
245 | char const * const aTitle , /* "" */
246 | int const aNumOfColumns , /* 2 */
247 | char const * const * const aColumns, /* {"Column 1","Column 2"} */
248 | int const aNumOfRows, /* 2*/
249 | char const * const * const aCells);
250 | /* {"Row1 Col1","Row1 Col2","Row2 Col1","Row2 Col2"} */
251 |
252 | #endif /*_WIN32 */
253 |
254 | #ifdef __cplusplus
255 | }
256 | #endif
257 |
258 | #endif /* TINYFILEDIALOGS_H */
259 |
260 | /*
261 | - This is not for android nor ios.
262 | - The code is pure C, perfectly compatible with C++.
263 | - the windows only wchar_t (utf-16) prototypes are in the header file
264 | - windows is fully supported from XP to 10 (maybe even older versions)
265 | - C# & LUA via dll, see example files
266 | - OSX supported from 10.4 to 10.11 (maybe even older versions)
267 | - Avoid using " and ' in titles and messages.
268 | - There's one file filter only, it may contain several patterns.
269 | - If no filter description is provided,
270 | the list of patterns will become the description.
271 | - char const * filterPatterns[3] = { "*.obj" , "*.stl" , "*.dxf" } ;
272 | - On windows link against Comdlg32.lib and Ole32.lib
273 | This linking is not compulsary for console mode (see above).
274 | - On unix: it tries command line calls, so no such need.
275 | - On unix you need applescript, zenity, matedialog, qarma, kdialog, Xdialog,
276 | python2/tkinter or dialog (will open a terminal if running without console).
277 | - One of those is already included on most (if not all) desktops.
278 | - In the absence of those it will use gdialog, gxmessage or whiptail
279 | with a textinputbox.
280 | - If nothing is found, it switches to basic console input,
281 | it opens a console if needed (requires xterm + bash).
282 | - Use windows separators on windows and unix separators on unix.
283 | - String memory is preallocated statically for all the returned values.
284 | - File and path names are tested before return, they are valid.
285 | - If you pass only a path instead of path + filename,
286 | make sure it ends with a separator.
287 | - tinyfd_forceConsole=1; at run time, forces dialogs into console mode.
288 | - On windows, console mode only make sense for console applications.
289 | - Mutiple selects are not allowed in console mode.
290 | - The package dialog must be installed to run in enhanced console mode.
291 | It is already installed on most unix systems.
292 | - On osx, the package dialog can be installed via http://macports.org
293 | - On windows, for enhanced console mode,
294 | dialog.exe should be copied somewhere on your executable path.
295 | It can be found at the bottom of the following page:
296 | http://andrear.altervista.org/home/cdialog.php
297 | - If dialog is missing, it will switch to basic console input.
298 | - You can query the type of dialog that will be use.
299 | - MinGW needs gcc >= v4.9 otherwise some headers are incomplete.
300 | - The Hello World (and a bit more) is on the sourceforge site:
301 | */
302 |
--------------------------------------------------------------------------------
/tinyfiledialogs.c:
--------------------------------------------------------------------------------
1 | /*_________
2 | / \ tinyfiledialogs.c v2.9.3 [July 12, 2017] zlib licence
3 | |tiny file| Unique code file created [November 9, 2014]
4 | | dialogs | Copyright (c) 2014 - 2017 Guillaume Vareille http://ysengrin.com
5 | \____ ___/ http://tinyfiledialogs.sourceforge.net
6 | \|
7 | git://git.code.sf.net/p/tinyfiledialogs/code
8 | ______________________________________________
9 | | |
10 | | email: tinyfiledialogs@ysengrin.com |
11 | |______________________________________________|
12 |
13 | A big thank you to Don Heyse http://ldglite.sf.net for
14 | his code contributions, bug corrections & thorough testing!
15 |
16 | Please
17 | 1) let me know
18 | - if you are including tiny file dialogs,
19 | I'll be happy to add your link to the list of projects using it.
20 | - If you are using it on different hardware / OS / compiler.
21 | 2) leave a review on Sourceforge. Thanks.
22 |
23 | tiny file dialogs (cross-platform C C++)
24 | InputBox PasswordBox MessageBox ColorPicker
25 | OpenFileDialog SaveFileDialog SelectFolderDialog
26 | Native dialog library for WINDOWS MAC OSX GTK+ QT CONSOLE & more
27 | SSH supported via automatic switch to console mode or X11 forwarding
28 |
29 | One C file (add it to your C or C++ project) with 6 functions:
30 | - message & question
31 | - input & password
32 | - save file
33 | - open file(s)
34 | - select folder
35 | - color picker
36 |
37 | Complements OpenGL GLFW GLUT GLUI VTK SFML TGUI SDL Ogre Unity3d ION OpenCV
38 | CEGUI MathGL GLM CPW GLOW IMGUI MyGUI GLT NGL STB & GUI less programs
39 |
40 | NO INIT
41 | NO MAIN LOOP
42 | NO LINKING
43 | NO INCLUDE
44 |
45 | The dialogs can be forced into console mode
46 |
47 | Windows (XP to 10) ASCII MBCS UTF-8 UTF-16
48 | - native code & vbs create the graphic dialogs
49 | - enhanced console mode can use dialog.exe from
50 | http://andrear.altervista.org/home/cdialog.php
51 | - basic console input
52 |
53 | Unix (command line calls) ASCII UTF-8
54 | - applescript
55 | - zenity / matedialog / qarma (zenity for qt)
56 | - kdialog
57 | - Xdialog
58 | - python2 tkinter
59 | - dialog (opens a console if needed)
60 | - basic console input
61 | The same executable can run across desktops & distributions
62 |
63 | tested with C & C++ compilers
64 | on VisualStudio MinGW Mac Linux Bsd Solaris Minix Raspbian
65 | using Gnome Kde Enlightenment Mate Cinnamon Unity
66 | Lxde Lxqt Xfce WindowMaker IceWm Cde Jds OpenBox Awesome Jwm
67 |
68 | bindings for LUA and C# dll
69 | included in LWJGL(java), rust, Allegrobasic
70 |
71 | - License -
72 |
73 | This software is provided 'as-is', without any express or implied
74 | warranty. In no event will the authors be held liable for any damages
75 | arising from the use of this software.
76 |
77 | Permission is granted to anyone to use this software for any purpose,
78 | including commercial applications, and to alter it and redistribute it
79 | freely, subject to the following restrictions:
80 |
81 | 1. The origin of this software must not be misrepresented; you must not
82 | claim that you wrote the original software. If you use this software
83 | in a product, an acknowledgment in the product documentation would be
84 | appreciated but is not required.
85 | 2. Altered source versions must be plainly marked as such, and must not be
86 | misrepresented as being the original software.
87 | 3. This notice may not be removed or altered from any source distribution.
88 | */
89 |
90 | #include
91 | #include
92 | #include
93 | #include
94 | #include
95 |
96 | #include "tinyfiledialogs.h"
97 | /* #define TINYFD_NOLIB */
98 |
99 | #ifdef _WIN32
100 | #ifndef _WIN32_WINNT
101 | #define _WIN32_WINNT 0x0500
102 | #endif
103 | #ifndef TINYFD_NOLIB
104 | #include
105 | /*#define TINYFD_NOSELECTFOLDERWIN*/
106 | #ifndef TINYFD_NOSELECTFOLDERWIN
107 | #include
108 | #endif /*TINYFD_NOSELECTFOLDERWIN*/
109 | #endif
110 | #include
111 | /*#include */
112 | #define SLASH "\\"
113 | int tinyfd_winUtf8 = 0 ; /* on windows string char can be 0:MBSC or 1:UTF-8 */
114 | #else
115 | #include
116 | #include
117 | #include /* on old systems try instead */
118 | #include
119 | #include
120 | #define SLASH "/"
121 | #endif /* _WIN32 */
122 |
123 | #define MAX_PATH_OR_CMD 1024 /* _MAX_PATH or MAX_PATH */
124 | #define MAX_MULTIPLE_FILES 32
125 |
126 | char tinyfd_version [8] = "2.9.3";
127 |
128 | static int tinyfd_verbose = 0 ; /* print on unix the command line calls */
129 |
130 | #if defined(TINYFD_NOLIB) && defined(_WIN32)
131 | int tinyfd_forceConsole = 1 ;
132 | #else
133 | int tinyfd_forceConsole = 0 ; /* 0 (default) or 1 */
134 | #endif
135 | /* for unix & windows: 0 (graphic mode) or 1 (console mode).
136 | 0: try to use a graphic solution, if it fails then it uses console mode.
137 | 1: forces all dialogs into console mode even when the X server is present,
138 | if the package dialog (and a console is present) or dialog.exe is installed.
139 | on windows it only make sense for console applications */
140 |
141 | char tinyfd_response[1024];
142 | /* if you pass "tinyfd_query" as aTitle,
143 | the functions will not display the dialogs
144 | but and return 0 for console mode, 1 for graphic mode.
145 | tinyfd_response is then filled with the retain solution.
146 | possible values for tinyfd_response are (all lowercase)
147 | for the graphic mode:
148 | windows applescript zenity zenity3 matedialog qarma kdialog
149 | tkinter gxmessage gmessage xmessage xdialog gdialog
150 | for the console mode:
151 | dialog whiptail basicinput */
152 |
153 | #if defined(TINYFD_NOLIB) && defined(_WIN32)
154 | static int gWarningDisplayed = 1 ;
155 | #else
156 | static int gWarningDisplayed = 0 ;
157 | #endif
158 |
159 | static char gTitle[]="missing software! (we will try basic console input)";
160 |
161 | #ifdef _WIN32
162 | static char gMessageWin[] = "\
163 | ___________\n\
164 | / \\ \n\
165 | | tiny file |\n\
166 | | dialogs |\n\
167 | \\_____ ____/\n\
168 | \\|\
169 | tiny file dialogs on Windows needs:\
170 | \n\ta graphic display\
171 | \nor\tdialog.exe (enhanced console mode)\
172 | \nor\ta console for basic input";
173 | #else
174 | static char gMessageUnix[] = "\
175 | ___________\n\
176 | / \\ \n\
177 | | tiny file |\n\
178 | | dialogs |\n\
179 | \\_____ ____/\n\
180 | \\|\
181 | \ntiny file dialogs on UNIX needs:\n\tapplescript\
182 | \nor\tzenity / matedialog\
183 | \nor\tqarma (zenity for qt)\
184 | \nor\tkdialog\
185 | \nor\tXdialog\
186 | \nor\tpython 2 + tkinter\
187 | \nor\tdialog (opens a console xterm if needed)\
188 | \nor\txterm + bash (opens a console for basic input)\
189 | \nor\tit will use the existing console for basic input";
190 | #endif
191 |
192 | #ifdef _MSC_VER
193 | #pragma warning(disable:4996) /* allows usage of strncpy, strcpy, strcat, sprintf, fopen */
194 | #pragma warning(disable:4100) /* allows usage of strncpy, strcpy, strcat, sprintf, fopen */
195 | #pragma warning(disable:4706) /* allows usage of strncpy, strcpy, strcat, sprintf, fopen */
196 | #endif
197 |
198 | static char * getPathWithoutFinalSlash(
199 | char * const aoDestination, /* make sure it is allocated, use _MAX_PATH */
200 | char const * const aSource) /* aoDestination and aSource can be the same */
201 | {
202 | char const * lTmp ;
203 | if ( aSource )
204 | {
205 | lTmp = strrchr(aSource, '/');
206 | if (!lTmp)
207 | {
208 | lTmp = strrchr(aSource, '\\');
209 | }
210 | if (lTmp)
211 | {
212 | strncpy(aoDestination, aSource, lTmp - aSource );
213 | aoDestination[lTmp - aSource] = '\0';
214 | }
215 | else
216 | {
217 | * aoDestination = '\0';
218 | }
219 | }
220 | else
221 | {
222 | * aoDestination = '\0';
223 | }
224 | return aoDestination;
225 | }
226 |
227 |
228 | static char * getLastName(
229 | char * const aoDestination, /* make sure it is allocated */
230 | char const * const aSource)
231 | {
232 | /* copy the last name after '/' or '\' */
233 | char const * lTmp ;
234 | if ( aSource )
235 | {
236 | lTmp = strrchr(aSource, '/');
237 | if (!lTmp)
238 | {
239 | lTmp = strrchr(aSource, '\\');
240 | }
241 | if (lTmp)
242 | {
243 | strcpy(aoDestination, lTmp + 1);
244 | }
245 | else
246 | {
247 | strcpy(aoDestination, aSource);
248 | }
249 | }
250 | else
251 | {
252 | * aoDestination = '\0';
253 | }
254 | return aoDestination;
255 | }
256 |
257 |
258 | static void ensureFinalSlash ( char * const aioString )
259 | {
260 | if ( aioString && strlen ( aioString ) )
261 | {
262 | char * lastcar = aioString + strlen ( aioString ) - 1 ;
263 | if ( strncmp ( lastcar , SLASH , 1 ) )
264 | {
265 | strcat ( lastcar , SLASH ) ;
266 | }
267 | }
268 | }
269 |
270 |
271 | static void Hex2RGB( char const aHexRGB [8] ,
272 | unsigned char aoResultRGB [3] )
273 | {
274 | char lColorChannel [8] ;
275 | if ( aoResultRGB )
276 | {
277 | if ( aHexRGB )
278 | {
279 | strcpy(lColorChannel, aHexRGB ) ;
280 | aoResultRGB[2] = (unsigned char)strtoul(lColorChannel+5,NULL,16);
281 | lColorChannel[5] = '\0';
282 | aoResultRGB[1] = (unsigned char)strtoul(lColorChannel+3,NULL,16);
283 | lColorChannel[3] = '\0';
284 | aoResultRGB[0] = (unsigned char)strtoul(lColorChannel+1,NULL,16);
285 | /* printf("%d %d %d\n", aoResultRGB[0], aoResultRGB[1], aoResultRGB[2]); */
286 | }
287 | else
288 | {
289 | aoResultRGB[0]=0;
290 | aoResultRGB[1]=0;
291 | aoResultRGB[2]=0;
292 | }
293 | }
294 | }
295 |
296 | static void RGB2Hex( unsigned char const aRGB [3] ,
297 | char aoResultHexRGB [8] )
298 | {
299 | if ( aoResultHexRGB )
300 | {
301 | if ( aRGB )
302 | {
303 | #if defined(__GNUC__) && defined(_WIN32)
304 | sprintf(aoResultHexRGB, "#%02hx%02hx%02hx",
305 | #else
306 | sprintf(aoResultHexRGB, "#%02hhx%02hhx%02hhx",
307 | #endif
308 | aRGB[0], aRGB[1], aRGB[2]);
309 | /* printf("aoResultHexRGB %s\n", aoResultHexRGB); */
310 | }
311 | else
312 | {
313 | aoResultHexRGB[0]=0;
314 | aoResultHexRGB[1]=0;
315 | aoResultHexRGB[2]=0;
316 | }
317 | }
318 | }
319 |
320 |
321 | static void replaceSubStr ( char const * const aSource ,
322 | char const * const aOldSubStr ,
323 | char const * const aNewSubStr ,
324 | char * const aoDestination )
325 | {
326 | char const * pOccurence ;
327 | char const * p ;
328 | char const * lNewSubStr = "" ;
329 | int lOldSubLen = strlen ( aOldSubStr ) ;
330 |
331 | if ( ! aSource )
332 | {
333 | * aoDestination = '\0' ;
334 | return ;
335 | }
336 | if ( ! aOldSubStr )
337 | {
338 | strcpy ( aoDestination , aSource ) ;
339 | return ;
340 | }
341 | if ( aNewSubStr )
342 | {
343 | lNewSubStr = aNewSubStr ;
344 | }
345 | p = aSource ;
346 | * aoDestination = '\0' ;
347 | while ( ( pOccurence = strstr ( p , aOldSubStr ) ) != NULL )
348 | {
349 | strncat ( aoDestination , p , pOccurence - p ) ;
350 | strcat ( aoDestination , lNewSubStr ) ;
351 | p = pOccurence + lOldSubLen ;
352 | }
353 | strcat ( aoDestination , p ) ;
354 | }
355 |
356 |
357 | static int filenameValid( char const * const aFileNameWithoutPath )
358 | {
359 | if ( ! aFileNameWithoutPath
360 | || ! strlen(aFileNameWithoutPath)
361 | || strpbrk(aFileNameWithoutPath , "\\/:*?\"<>|") )
362 | {
363 | return 0 ;
364 | }
365 | return 1 ;
366 | }
367 |
368 |
369 | static int fileExists( char const * const aFilePathAndName )
370 | {
371 | FILE * lIn ;
372 | if ( ! aFilePathAndName || ! strlen(aFilePathAndName) )
373 | {
374 | return 0 ;
375 | }
376 | lIn = fopen( aFilePathAndName , "r" ) ;
377 | if ( ! lIn )
378 | {
379 | return 0 ;
380 | }
381 | fclose ( lIn ) ;
382 | return 1 ;
383 | }
384 |
385 |
386 | /* source and destination can be the same or ovelap*/
387 | static char const * ensureFilesExist( char * const aDestination ,
388 | char const * const aSourcePathsAndNames)
389 | {
390 | char * lDestination = aDestination ;
391 | char const * p ;
392 | char const * p2 ;
393 | int lLen ;
394 |
395 | if ( ! aSourcePathsAndNames )
396 | {
397 | return NULL ;
398 | }
399 | lLen = strlen( aSourcePathsAndNames ) ;
400 | if ( ! lLen )
401 | {
402 | return NULL ;
403 | }
404 |
405 | p = aSourcePathsAndNames ;
406 | while ( (p2 = strchr(p, '|')) != NULL )
407 | {
408 | lLen = p2-p ;
409 | memmove(lDestination,p,lLen);
410 | lDestination[lLen] = '\0';
411 | if ( fileExists ( lDestination ) )
412 | {
413 | lDestination += lLen ;
414 | * lDestination = '|';
415 | lDestination ++ ;
416 | }
417 | p = p2 + 1 ;
418 | }
419 | if ( fileExists ( p ) )
420 | {
421 | lLen = strlen(p) ;
422 | memmove(lDestination,p,lLen);
423 | lDestination[lLen] = '\0';
424 | }
425 | else
426 | {
427 | * (lDestination-1) = '\0';
428 | }
429 | return aDestination ;
430 | }
431 |
432 |
433 | static void wipefile(char const * const aFilename)
434 | {
435 | int i;
436 | struct stat st;
437 | FILE * lIn;
438 |
439 | if (stat(aFilename, &st) == 0)
440 | {
441 | if ((lIn = fopen(aFilename, "w")))
442 | {
443 | for (i = 0; i < st.st_size; i++)
444 | {
445 | fputc('A', lIn);
446 | }
447 | }
448 | fclose(lIn);
449 | }
450 | }
451 |
452 | #ifdef _WIN32
453 |
454 | static int replaceChr ( char * const aString ,
455 | char const aOldChr ,
456 | char const aNewChr )
457 | {
458 | char * p ;
459 | int lRes = 0 ;
460 |
461 | if ( ! aString )
462 | {
463 | return 0 ;
464 | }
465 |
466 | if ( aOldChr == aNewChr )
467 | {
468 | return 0 ;
469 | }
470 |
471 | p = aString ;
472 | while ( (p = strchr ( p , aOldChr )) )
473 | {
474 | * p = aNewChr ;
475 | p ++ ;
476 | lRes = 1 ;
477 | }
478 | return lRes ;
479 | }
480 |
481 |
482 | static int dirExists ( char const * const aDirPath )
483 | {
484 | struct stat lInfo;
485 | if ( ! aDirPath || ! strlen ( aDirPath ) )
486 | return 0 ;
487 | if ( stat ( aDirPath , & lInfo ) != 0 )
488 | return 0 ;
489 | else if ( lInfo.st_mode & S_IFDIR )
490 | return 1 ;
491 | else
492 | return 0 ;
493 | }
494 |
495 | #ifndef TINYFD_NOLIB
496 |
497 | static wchar_t * getPathWithoutFinalSlashW(
498 | wchar_t * const aoDestination, /* make sure it is allocated, use _MAX_PATH */
499 | wchar_t const * const aSource) /* aoDestination and aSource can be the same */
500 | {
501 | wchar_t const * lTmp;
502 | if (aSource)
503 | {
504 | lTmp = wcsrchr(aSource, L'/');
505 | if (!lTmp)
506 | {
507 | lTmp = wcsrchr(aSource, L'\\');
508 | }
509 | if (lTmp)
510 | {
511 | wcsncpy(aoDestination, aSource, lTmp - aSource);
512 | aoDestination[lTmp - aSource] = L'\0';
513 | }
514 | else
515 | {
516 | *aoDestination = L'\0';
517 | }
518 | }
519 | else
520 | {
521 | *aoDestination = L'\0';
522 | }
523 | return aoDestination;
524 | }
525 |
526 |
527 | static wchar_t * getLastNameW(
528 | wchar_t * const aoDestination, /* make sure it is allocated */
529 | wchar_t const * const aSource)
530 | {
531 | /* copy the last name after '/' or '\' */
532 | wchar_t const * lTmp;
533 | if (aSource)
534 | {
535 | lTmp = wcsrchr(aSource, L'/');
536 | if (!lTmp)
537 | {
538 | lTmp = wcsrchr(aSource, L'\\');
539 | }
540 | if (lTmp)
541 | {
542 | wcscpy(aoDestination, lTmp + 1);
543 | }
544 | else
545 | {
546 | wcscpy(aoDestination, aSource);
547 | }
548 | }
549 | else
550 | {
551 | *aoDestination = L'\0';
552 | }
553 | return aoDestination;
554 | }
555 |
556 |
557 | static void Hex2RGBW(wchar_t const aHexRGB[8],
558 | unsigned char aoResultRGB[3])
559 | {
560 | wchar_t lColorChannel[8];
561 | if (aoResultRGB)
562 | {
563 | if (aHexRGB)
564 | {
565 | wcscpy(lColorChannel, aHexRGB);
566 | aoResultRGB[2] = (unsigned char)wcstoul(lColorChannel + 5, NULL, 16);
567 | lColorChannel[5] = '\0';
568 | aoResultRGB[1] = (unsigned char)wcstoul(lColorChannel + 3, NULL, 16);
569 | lColorChannel[3] = '\0';
570 | aoResultRGB[0] = (unsigned char)wcstoul(lColorChannel + 1, NULL, 16);
571 | /* printf("%d %d %d\n", aoResultRGB[0], aoResultRGB[1], aoResultRGB[2]); */
572 | }
573 | else
574 | {
575 | aoResultRGB[0] = 0;
576 | aoResultRGB[1] = 0;
577 | aoResultRGB[2] = 0;
578 | }
579 | }
580 | }
581 |
582 |
583 | static void RGB2HexW(
584 | unsigned char const aRGB[3],
585 | wchar_t aoResultHexRGB[8])
586 | {
587 | if (aoResultHexRGB)
588 | {
589 | if (aRGB)
590 | {
591 | #if defined(__GNUC__) && __GNUC__ < 5
592 | swprintf(aoResultHexRGB, L"#%02hhx%02hhx%02hhx", aRGB[0], aRGB[1], aRGB[2]);
593 | #else
594 | swprintf(aoResultHexRGB, 8, L"#%02hhx%02hhx%02hhx", aRGB[0], aRGB[1], aRGB[2]);
595 | #endif
596 | /* wprintf(L"aoResultHexRGB %s\n", aoResultHexRGB); */
597 | }
598 | else
599 | {
600 | aoResultHexRGB[0] = 0;
601 | aoResultHexRGB[1] = 0;
602 | aoResultHexRGB[2] = 0;
603 | }
604 | }
605 | }
606 |
607 |
608 | #if !defined(WC_ERR_INVALID_CHARS)
609 | /* undefined prior to Vista, so not yet in MINGW header file */
610 | #define WC_ERR_INVALID_CHARS 0x00000080
611 | #endif
612 |
613 |
614 | static int sizeUtf16(char const * const aUtf8string)
615 | {
616 | return MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
617 | aUtf8string, -1, NULL, 0);
618 | }
619 |
620 |
621 | static int sizeUtf8(wchar_t const * const aUtf16string)
622 | {
623 | return WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
624 | aUtf16string, -1, NULL, 0, NULL, NULL);
625 | }
626 |
627 |
628 | static wchar_t * utf8to16(char const * const aUtf8string)
629 | {
630 | wchar_t * lUtf16string ;
631 | int lSize = sizeUtf16(aUtf8string);
632 | lUtf16string = (wchar_t *) malloc( lSize * sizeof(wchar_t) );
633 | lSize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
634 | aUtf8string, -1, lUtf16string, lSize);
635 | if (lSize == 0)
636 | {
637 | free(lUtf16string);
638 | return NULL;
639 | }
640 | return lUtf16string;
641 | }
642 |
643 |
644 | static char * utf16to8(wchar_t const * const aUtf16string)
645 | {
646 | char * lUtf8string ;
647 | int lSize = sizeUtf8(aUtf16string);
648 | lUtf8string = (char *) malloc( lSize );
649 | lSize = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
650 | aUtf16string, -1, lUtf8string, lSize, NULL, NULL);
651 | if (lSize == 0)
652 | {
653 | free(lUtf8string);
654 | return NULL;
655 | }
656 | return lUtf8string;
657 | }
658 |
659 |
660 | static void runSilentA(char const * const aString)
661 | {
662 | STARTUPINFOA StartupInfo;
663 | PROCESS_INFORMATION ProcessInfo;
664 | char * lArgs;
665 | char * pEnvCMD = NULL;
666 | char * pDefaultCMD = "CMD.EXE";
667 | ULONG rc;
668 | int lStringLen = 0;
669 |
670 | memset(&StartupInfo, 0, sizeof(StartupInfo));
671 | StartupInfo.cb = sizeof(STARTUPINFOA);
672 | StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
673 | StartupInfo.wShowWindow = SW_HIDE;
674 |
675 | if ( aString )
676 | {
677 | lStringLen = strlen(aString);
678 | }
679 | lArgs = (char *) malloc( MAX_PATH_OR_CMD + lStringLen );
680 |
681 | pEnvCMD = getenv("COMSPEC");
682 |
683 | if (pEnvCMD){
684 |
685 | strcpy(lArgs, pEnvCMD);
686 | }
687 | else{
688 | strcpy(lArgs, pDefaultCMD);
689 | }
690 |
691 | /* c to execute then terminate the command window */
692 | strcat(lArgs, " /c ");
693 |
694 | /* application and parameters to run from the command window */
695 | strcat(lArgs, aString);
696 |
697 | if (!CreateProcessA(NULL, lArgs, NULL, NULL, FALSE,
698 | CREATE_NEW_CONSOLE, NULL, NULL,
699 | &StartupInfo, &ProcessInfo))
700 | {
701 | free(lArgs);
702 | return; /* GetLastError(); */
703 | }
704 |
705 | WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
706 | if (!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
707 | rc = 0;
708 |
709 | CloseHandle(ProcessInfo.hThread);
710 | CloseHandle(ProcessInfo.hProcess);
711 |
712 | free(lArgs);
713 | return; /* rc */
714 | }
715 |
716 |
717 | static void runSilentW(wchar_t const * const aString)
718 | {
719 | STARTUPINFOW StartupInfo;
720 | PROCESS_INFORMATION ProcessInfo;
721 | ULONG rc;
722 | wchar_t * lArgs;
723 | wchar_t * pEnvCMD;
724 | wchar_t * pDefaultCMD = L"CMD.EXE";
725 | int lStringLen = 0;
726 |
727 | memset(&StartupInfo, 0, sizeof(StartupInfo));
728 | StartupInfo.cb = sizeof(STARTUPINFOW);
729 | StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
730 | StartupInfo.wShowWindow = SW_HIDE;
731 |
732 | if ( aString )
733 | {
734 | lStringLen = wcslen(aString);
735 | }
736 | lArgs = (wchar_t *) malloc( (MAX_PATH_OR_CMD + lStringLen) * sizeof(wchar_t) );
737 |
738 | pEnvCMD = utf8to16( getenv("COMSPEC") );
739 | if (pEnvCMD)
740 | {
741 | wcscpy(lArgs, pEnvCMD);
742 | free(pEnvCMD);
743 | }
744 | else
745 | {
746 | wcscpy(lArgs, pDefaultCMD);
747 | }
748 |
749 | /* c to execute then terminate the command window */
750 | wcscat(lArgs, L" /c ");
751 |
752 | /* application and parameters to run from the command window */
753 | wcscat(lArgs, aString);
754 |
755 | if (!CreateProcessW(NULL, lArgs, NULL, NULL, FALSE,
756 | CREATE_NEW_CONSOLE, NULL, NULL,
757 | &StartupInfo, &ProcessInfo))
758 | {
759 | free(lArgs);
760 | return; /* GetLastError(); */
761 | }
762 |
763 | WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
764 | if (!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
765 | {
766 | rc = 0;
767 | }
768 |
769 | CloseHandle(ProcessInfo.hThread);
770 | CloseHandle(ProcessInfo.hProcess);
771 |
772 | free(lArgs);
773 | return; /* rc */
774 | }
775 |
776 |
777 | int tinyfd_messageBoxW(
778 | wchar_t const * const aTitle, /* NULL or "" */
779 | wchar_t const * const aMessage, /* NULL or "" may contain \n and \t */
780 | wchar_t const * const aDialogType, /* "ok" "okcancel" "yesno" "yesnocancel" */
781 | wchar_t const * const aIconType, /* "info" "warning" "error" "question" */
782 | int const aDefaultButton) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
783 | {
784 | int lBoxReturnValue;
785 | UINT aCode;
786 |
787 | if (aIconType && !wcscmp(L"warning", aIconType))
788 | {
789 | aCode = MB_ICONWARNING;
790 | }
791 | else if (aIconType && !wcscmp(L"error", aIconType))
792 | {
793 | aCode = MB_ICONERROR;
794 | }
795 | else if (aIconType && !wcscmp(L"question", aIconType))
796 | {
797 | aCode = MB_ICONQUESTION;
798 | }
799 | else
800 | {
801 | aCode = MB_ICONINFORMATION;
802 | }
803 |
804 | if (aDialogType && !wcscmp(L"okcancel", aDialogType))
805 | {
806 | aCode += MB_OKCANCEL;
807 | if (!aDefaultButton)
808 | {
809 | aCode += MB_DEFBUTTON2;
810 | }
811 | }
812 | else if (aDialogType && !wcscmp(L"yesno", aDialogType))
813 | {
814 | aCode += MB_YESNO;
815 | if (!aDefaultButton)
816 | {
817 | aCode += MB_DEFBUTTON2;
818 | }
819 | }
820 | else
821 | {
822 | aCode += MB_OK;
823 | }
824 |
825 | lBoxReturnValue = MessageBoxW(NULL, aMessage, aTitle, aCode);
826 | if (((aDialogType
827 | && wcscmp(L"okcancel", aDialogType)
828 | && wcscmp(L"yesno", aDialogType)))
829 | || (lBoxReturnValue == IDOK)
830 | || (lBoxReturnValue == IDYES))
831 | {
832 | return 1;
833 | }
834 | else
835 | {
836 | return 0;
837 | }
838 | }
839 |
840 |
841 | static int messageBoxWinGui8(
842 | char const * const aTitle, /* NULL or "" */
843 | char const * const aMessage, /* NULL or "" may contain \n and \t */
844 | char const * const aDialogType, /* "ok" "okcancel" "yesno" "yesnocancel" */
845 | char const * const aIconType, /* "info" "warning" "error" "question" */
846 | int const aDefaultButton) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
847 | {
848 | int lIntRetVal;
849 | wchar_t * lTitle;
850 | wchar_t * lMessage;
851 | wchar_t * lDialogType;
852 | wchar_t * lIconType;
853 |
854 | lTitle = utf8to16(aTitle);
855 | lMessage = utf8to16(aMessage);
856 | lDialogType = utf8to16(aDialogType);
857 | lIconType = utf8to16(aIconType);
858 |
859 | lIntRetVal = tinyfd_messageBoxW(lTitle, lMessage,
860 | lDialogType, lIconType, aDefaultButton );
861 |
862 | free(lTitle);
863 | free(lMessage);
864 | free(lDialogType);
865 | free(lIconType);
866 |
867 | return lIntRetVal ;
868 | }
869 |
870 |
871 | static char const * inputBoxWinGui(
872 | char * const aoBuff ,
873 | char const * const aTitle , /* NULL or "" */
874 | char const * const aMessage , /* NULL or "" may NOT contain \n nor \t */
875 | char const * const aDefaultInput ) /* "" , if NULL it's a passwordBox */
876 | {
877 | char * lDialogString;
878 | FILE * lIn;
879 | int lResult;
880 | int lTitleLen;
881 | int lMessageLen;
882 | wchar_t * lDialogStringW;
883 |
884 | lTitleLen = aTitle ? strlen(aTitle) : 0 ;
885 | lMessageLen = aMessage ? strlen(aMessage) : 0 ;
886 | lDialogString = (char *)malloc(3 * MAX_PATH_OR_CMD + lTitleLen + lMessageLen);
887 |
888 | if (aDefaultInput)
889 | {
890 | sprintf(lDialogString, "%s\\AppData\\Local\\Temp\\tinyfd.vbs",
891 | getenv("USERPROFILE"));
892 | }
893 | else
894 | {
895 | sprintf(lDialogString, "%s\\AppData\\Local\\Temp\\tinyfd.hta",
896 | getenv("USERPROFILE"));
897 | }
898 | lIn = fopen(lDialogString, "w");
899 | if (!lIn)
900 | {
901 | free(lDialogString);
902 | return NULL;
903 | }
904 |
905 | if ( aDefaultInput )
906 | {
907 | strcpy(lDialogString, "Dim result:result=InputBox(\"");
908 | if (aMessage && strlen(aMessage))
909 | {
910 | strcat(lDialogString, aMessage);
911 | }
912 | strcat(lDialogString, "\",\"");
913 | if (aTitle && strlen(aTitle))
914 | {
915 | strcat(lDialogString, aTitle);
916 | }
917 | strcat(lDialogString, "\",\"");
918 | if (aDefaultInput && strlen(aDefaultInput))
919 | {
920 | strcat(lDialogString, aDefaultInput);
921 | }
922 | strcat(lDialogString, "\"):If IsEmpty(result) then:WScript.Echo 0");
923 | strcat(lDialogString, ":Else: WScript.Echo \"1\" & result : End If");
924 | }
925 | else
926 | {
927 | sprintf(lDialogString, "\n\
928 | \n\
929 | \n\
930 | %s\n\
931 | \n\
940 | \n\
941 | \n\
984 | \n\
985 | \n\
986 | \n\
987 | \n\
988 | | \n\
989 | %s\n\
990 | | \n\
991 | \n\
992 | \n\
998 | | \n\
999 |
\n\
1000 |
\n\
1001 | \n\
1009 | \n\
1010 | \n\
1011 | " , aTitle ? aTitle : "", aMessage ? aMessage : "") ;
1012 | }
1013 | fputs(lDialogString, lIn);
1014 | fclose(lIn);
1015 |
1016 | strcpy(lDialogString, "");
1017 |
1018 | if (aDefaultInput)
1019 | {
1020 | strcat(lDialogString, "cscript.exe ");
1021 | strcat(lDialogString, "//Nologo ");
1022 | strcat(lDialogString,"%USERPROFILE%\\AppData\\Local\\Temp\\tinyfd.vbs");
1023 | strcat(lDialogString, " > %USERPROFILE%\\AppData\\Local\\Temp\\tinyfd.txt");
1024 | }
1025 | else
1026 | {
1027 | strcat(lDialogString,
1028 | "mshta.exe %USERPROFILE%\\AppData\\Local\\Temp\\tinyfd.hta");
1029 | }
1030 |
1031 | /* printf ( "lDialogString: %s\n" , lDialogString ) ; */
1032 |
1033 | if (tinyfd_winUtf8)
1034 | {
1035 | lDialogStringW = utf8to16(lDialogString);
1036 | runSilentW(lDialogStringW);
1037 | free(lDialogStringW);
1038 | }
1039 | else
1040 | {
1041 | runSilentA(lDialogString);
1042 | }
1043 |
1044 | /*
1045 | if (!(lIn = _popen(lDialogString, "r")))
1046 | {
1047 | free(lDialogString);
1048 | return NULL;
1049 | }
1050 | while (fgets(aoBuff, MAX_PATH_OR_CMD, lIn) != NULL)
1051 | {
1052 | }
1053 | _pclose(lIn);
1054 | if (aoBuff[strlen(aoBuff) - 1] == '\n')
1055 | {
1056 | aoBuff[strlen(aoBuff) - 1] = '\0';
1057 | }
1058 | */
1059 |
1060 | if (aDefaultInput)
1061 | {
1062 | sprintf(lDialogString, "%s\\AppData\\Local\\Temp\\tinyfd.txt",
1063 | getenv("USERPROFILE"));
1064 | if (!(lIn = fopen(lDialogString, "r")))
1065 | {
1066 | remove(lDialogString);
1067 | free(lDialogString);
1068 | return NULL;
1069 | }
1070 | while (fgets(aoBuff, MAX_PATH_OR_CMD, lIn) != NULL)
1071 | {}
1072 | fclose(lIn);
1073 | remove(lDialogString);
1074 |
1075 | sprintf(lDialogString, "%s\\AppData\\Local\\Temp\\tinyfd.vbs",
1076 | getenv("USERPROFILE"));
1077 | }
1078 | else
1079 | {
1080 | sprintf(lDialogString, "%s\\AppData\\Local\\Temp\\tinyfd.txt",
1081 | getenv("USERPROFILE"));
1082 | if (!(lIn = fopen(lDialogString, "r")))
1083 | {
1084 | remove(lDialogString);
1085 | free(lDialogString);
1086 | return NULL;
1087 | }
1088 | while (fgets(aoBuff, MAX_PATH_OR_CMD, lIn) != NULL)
1089 | {}
1090 | fclose(lIn);
1091 |
1092 | wipefile(lDialogString);
1093 | remove(lDialogString);
1094 | sprintf(lDialogString, "%s\\AppData\\Local\\Temp\\tinyfd.hta",
1095 | getenv("USERPROFILE"));
1096 | }
1097 | remove(lDialogString);
1098 | free(lDialogString);
1099 | /* printf ( "aoBuff: %s\n" , aoBuff ) ; */
1100 | lResult = strncmp(aoBuff, "1", 1) ? 0 : 1;
1101 | /* printf ( "lResult: %d \n" , lResult ) ; */
1102 | if (!lResult)
1103 | {
1104 | return NULL ;
1105 | }
1106 |
1107 | if (aoBuff[strlen(aoBuff) - 1] == '\n')
1108 | {
1109 | aoBuff[strlen(aoBuff) - 1] = '\0';
1110 | }
1111 |
1112 | /* printf ( "aoBuff+1: %s\n" , aoBuff+1 ) ; */
1113 | return aoBuff + 1;
1114 | }
1115 |
1116 |
1117 | wchar_t const * tinyfd_saveFileDialogW(
1118 | wchar_t const * const aTitle, /* NULL or "" */
1119 | wchar_t const * const aDefaultPathAndFile, /* NULL or "" */
1120 | int const aNumOfFilterPatterns, /* 0 */
1121 | wchar_t const * const * const aFilterPatterns, /* NULL or {"*.jpg","*.png"} */
1122 | wchar_t const * const aSingleFilterDescription) /* NULL or "image files" */
1123 | {
1124 | static wchar_t lBuff[MAX_PATH_OR_CMD];
1125 | wchar_t lDirname[MAX_PATH_OR_CMD];
1126 | wchar_t lDialogString[MAX_PATH_OR_CMD];
1127 | wchar_t lFilterPatterns[MAX_PATH_OR_CMD] = L"";
1128 | wchar_t * p;
1129 | wchar_t * lRetval;
1130 | int i;
1131 | HRESULT lHResult;
1132 | OPENFILENAMEW ofn = {0};
1133 |
1134 | lHResult = CoInitializeEx(NULL, 0);
1135 |
1136 | getPathWithoutFinalSlashW(lDirname, aDefaultPathAndFile);
1137 | getLastNameW(lBuff, aDefaultPathAndFile);
1138 |
1139 | if (aNumOfFilterPatterns > 0)
1140 | {
1141 | if (aSingleFilterDescription && wcslen(aSingleFilterDescription))
1142 | {
1143 | wcscpy(lFilterPatterns, aSingleFilterDescription);
1144 | wcscat(lFilterPatterns, L"\n");
1145 | }
1146 | wcscat(lFilterPatterns, aFilterPatterns[0]);
1147 | for (i = 1; i < aNumOfFilterPatterns; i++)
1148 | {
1149 | wcscat(lFilterPatterns, L";");
1150 | wcscat(lFilterPatterns, aFilterPatterns[i]);
1151 | }
1152 | wcscat(lFilterPatterns, L"\n");
1153 | if (!(aSingleFilterDescription && wcslen(aSingleFilterDescription)))
1154 | {
1155 | wcscpy(lDialogString, lFilterPatterns);
1156 | wcscat(lFilterPatterns, lDialogString);
1157 | }
1158 | wcscat(lFilterPatterns, L"All Files\n*.*\n");
1159 | p = lFilterPatterns;
1160 | while ((p = wcschr(p, L'\n')) != NULL)
1161 | {
1162 | *p = L'\0';
1163 | p++;
1164 | }
1165 | }
1166 |
1167 | ofn.lStructSize = sizeof(OPENFILENAMEW);
1168 | ofn.hwndOwner = 0;
1169 | ofn.hInstance = 0;
1170 | ofn.lpstrFilter = lFilterPatterns && wcslen(lFilterPatterns) ? lFilterPatterns : NULL;
1171 | ofn.lpstrCustomFilter = NULL;
1172 | ofn.nMaxCustFilter = 0;
1173 | ofn.nFilterIndex = 1;
1174 | ofn.lpstrFile = lBuff;
1175 |
1176 | ofn.nMaxFile = MAX_PATH_OR_CMD;
1177 | ofn.lpstrFileTitle = NULL;
1178 | ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT;
1179 | ofn.lpstrInitialDir = lDirname && wcslen(lDirname) ? lDirname : NULL;
1180 | ofn.lpstrTitle = aTitle && wcslen(aTitle) ? aTitle : NULL;
1181 | ofn.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
1182 | ofn.nFileOffset = 0;
1183 | ofn.nFileExtension = 0;
1184 | ofn.lpstrDefExt = NULL;
1185 | ofn.lCustData = 0L;
1186 | ofn.lpfnHook = NULL;
1187 | ofn.lpTemplateName = NULL;
1188 |
1189 | if (GetSaveFileNameW(&ofn) == 0)
1190 | {
1191 | lRetval = NULL;
1192 | }
1193 | else
1194 | {
1195 | lRetval = lBuff;
1196 | }
1197 |
1198 | if (lHResult == S_OK || lHResult == S_FALSE)
1199 | {
1200 | CoUninitialize();
1201 | }
1202 | return lRetval;
1203 | }
1204 |
1205 |
1206 | static char const * saveFileDialogWinGui8(
1207 | char * const aoBuff,
1208 | char const * const aTitle, /* NULL or "" */
1209 | char const * const aDefaultPathAndFile, /* NULL or "" */
1210 | int const aNumOfFilterPatterns, /* 0 */
1211 | char const * const * const aFilterPatterns, /* NULL or {"*.jpg","*.png"} */
1212 | char const * const aSingleFilterDescription) /* NULL or "image files" */
1213 | {
1214 | wchar_t * lTitle;
1215 | wchar_t * lDefaultPathAndFile;
1216 | wchar_t * lSingleFilterDescription;
1217 | wchar_t * * lFilterPatterns;
1218 | wchar_t const * lTmpWChar;
1219 | char * lTmpChar;
1220 | int i ;
1221 |
1222 | lFilterPatterns = (wchar_t **) malloc(aNumOfFilterPatterns*sizeof(wchar_t *));
1223 | for (i = 0; i < aNumOfFilterPatterns; i++)
1224 | {
1225 | lFilterPatterns[i] = utf8to16(aFilterPatterns[i]);
1226 | }
1227 |
1228 | lTitle = utf8to16(aTitle);
1229 | lDefaultPathAndFile = utf8to16(aDefaultPathAndFile);
1230 | lSingleFilterDescription = utf8to16(aSingleFilterDescription);
1231 |
1232 | lTmpWChar = tinyfd_saveFileDialogW(
1233 | lTitle,
1234 | lDefaultPathAndFile,
1235 | aNumOfFilterPatterns,
1236 | (wchar_t const** ) /*stupid cast for gcc*/
1237 | lFilterPatterns,
1238 | lSingleFilterDescription);
1239 |
1240 | free(lTitle);
1241 | free(lDefaultPathAndFile);
1242 | free(lSingleFilterDescription);
1243 | for (i = 0; i < aNumOfFilterPatterns; i++)
1244 | {
1245 | free(lFilterPatterns[i]);
1246 | }
1247 | free(lFilterPatterns);
1248 |
1249 | if (!lTmpWChar)
1250 | {
1251 | return NULL;
1252 | }
1253 |
1254 | lTmpChar = utf16to8(lTmpWChar);
1255 | strcpy(aoBuff, lTmpChar);
1256 | free(lTmpChar);
1257 |
1258 | return aoBuff;
1259 | }
1260 |
1261 |
1262 | wchar_t const * tinyfd_openFileDialogW(
1263 | wchar_t const * const aTitle, /* NULL or "" */
1264 | wchar_t const * const aDefaultPathAndFile, /* NULL or "" */
1265 | int const aNumOfFilterPatterns, /* 0 */
1266 | wchar_t const * const * const aFilterPatterns, /* NULL or {"*.jpg","*.png"} */
1267 | wchar_t const * const aSingleFilterDescription, /* NULL or "image files" */
1268 | int const aAllowMultipleSelects) /* 0 or 1 */
1269 | {
1270 | static wchar_t lBuff[MAX_MULTIPLE_FILES*MAX_PATH_OR_CMD];
1271 |
1272 | size_t lLengths[MAX_MULTIPLE_FILES];
1273 | wchar_t lDirname[MAX_PATH_OR_CMD];
1274 | wchar_t lFilterPatterns[MAX_PATH_OR_CMD] = L"";
1275 | wchar_t lDialogString[MAX_PATH_OR_CMD];
1276 | wchar_t * lPointers[MAX_MULTIPLE_FILES];
1277 | wchar_t * lRetval, * p;
1278 | int i, j;
1279 | size_t lBuffLen;
1280 | HRESULT lHResult;
1281 | OPENFILENAMEW ofn = { 0 };
1282 |
1283 | lHResult = CoInitializeEx(NULL, 0);
1284 |
1285 | getPathWithoutFinalSlashW(lDirname, aDefaultPathAndFile);
1286 | getLastNameW(lBuff, aDefaultPathAndFile);
1287 |
1288 | if (aNumOfFilterPatterns > 0)
1289 | {
1290 | if (aSingleFilterDescription && wcslen(aSingleFilterDescription))
1291 | {
1292 | wcscpy(lFilterPatterns, aSingleFilterDescription);
1293 | wcscat(lFilterPatterns, L"\n");
1294 | }
1295 | wcscat(lFilterPatterns, aFilterPatterns[0]);
1296 | for (i = 1; i < aNumOfFilterPatterns; i++)
1297 | {
1298 | wcscat(lFilterPatterns, L";");
1299 | wcscat(lFilterPatterns, aFilterPatterns[i]);
1300 | }
1301 | wcscat(lFilterPatterns, L"\n");
1302 | if (!(aSingleFilterDescription && wcslen(aSingleFilterDescription)))
1303 | {
1304 | wcscpy(lDialogString, lFilterPatterns);
1305 | wcscat(lFilterPatterns, lDialogString);
1306 | }
1307 | wcscat(lFilterPatterns, L"All Files\n*.*\n");
1308 | p = lFilterPatterns;
1309 | while ((p = wcschr(p, L'\n')) != NULL)
1310 | {
1311 | *p = L'\0';
1312 | p++;
1313 | }
1314 | }
1315 |
1316 | ofn.lStructSize = sizeof(OPENFILENAME);
1317 | ofn.hwndOwner = 0;
1318 | ofn.hInstance = 0;
1319 | ofn.lpstrFilter = lFilterPatterns && wcslen(lFilterPatterns) ? lFilterPatterns : NULL;
1320 | ofn.lpstrCustomFilter = NULL;
1321 | ofn.nMaxCustFilter = 0;
1322 | ofn.nFilterIndex = 1;
1323 | ofn.lpstrFile = lBuff;
1324 | ofn.nMaxFile = MAX_PATH_OR_CMD;
1325 | ofn.lpstrFileTitle = NULL;
1326 | ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT;
1327 | ofn.lpstrInitialDir = lDirname && wcslen(lDirname) ? lDirname : NULL;
1328 | ofn.lpstrTitle = aTitle && wcslen(aTitle) ? aTitle : NULL;
1329 | ofn.Flags = OFN_EXPLORER | OFN_NOCHANGEDIR;
1330 | ofn.nFileOffset = 0;
1331 | ofn.nFileExtension = 0;
1332 | ofn.lpstrDefExt = NULL;
1333 | ofn.lCustData = 0L;
1334 | ofn.lpfnHook = NULL;
1335 | ofn.lpTemplateName = NULL;
1336 |
1337 | if (aAllowMultipleSelects)
1338 | {
1339 | ofn.Flags |= OFN_ALLOWMULTISELECT;
1340 | }
1341 |
1342 | if (GetOpenFileNameW(&ofn) == 0)
1343 | {
1344 | lRetval = NULL;
1345 | }
1346 | else
1347 | {
1348 | lBuffLen = wcslen(lBuff);
1349 | lPointers[0] = lBuff + lBuffLen + 1;
1350 | if (!aAllowMultipleSelects || (lPointers[0][0] == L'\0'))
1351 | {
1352 | lRetval = lBuff;
1353 | }
1354 | else
1355 | {
1356 | i = 0;
1357 | do
1358 | {
1359 | lLengths[i] = wcslen(lPointers[i]);
1360 | lPointers[i + 1] = lPointers[i] + lLengths[i] + 1;
1361 | i++;
1362 | } while (lPointers[i][0] != L'\0');
1363 | i--;
1364 | p = lBuff + MAX_MULTIPLE_FILES*MAX_PATH_OR_CMD - 1;
1365 | *p = L'\0';
1366 | for (j = i; j >= 0; j--)
1367 | {
1368 | p -= lLengths[j];
1369 | memmove(p, lPointers[j], lLengths[j]*sizeof(wchar_t));
1370 | p--;
1371 | *p = L'\\';
1372 | p -= lBuffLen;
1373 | memmove(p, lBuff, lBuffLen*sizeof(wchar_t));
1374 | p--;
1375 | *p = L'|';
1376 | }
1377 | p++;
1378 | lRetval = p;
1379 | }
1380 | }
1381 |
1382 | if (lHResult == S_OK || lHResult == S_FALSE)
1383 | {
1384 | CoUninitialize();
1385 | }
1386 | return lRetval;
1387 | }
1388 |
1389 |
1390 | static char const * openFileDialogWinGui8(
1391 | char * const aoBuff,
1392 | char const * const aTitle, /* NULL or "" */
1393 | char const * const aDefaultPathAndFile, /* NULL or "" */
1394 | int const aNumOfFilterPatterns, /* 0 */
1395 | char const * const * const aFilterPatterns, /* NULL or {"*.jpg","*.png"} */
1396 | char const * const aSingleFilterDescription, /* NULL or "image files" */
1397 | int const aAllowMultipleSelects) /* 0 or 1 */
1398 | {
1399 | wchar_t * lTitle;
1400 | wchar_t * lDefaultPathAndFile;
1401 | wchar_t * lSingleFilterDescription;
1402 | wchar_t * * lFilterPatterns;
1403 | wchar_t const * lTmpWChar;
1404 | char * lTmpChar;
1405 | int i;
1406 |
1407 | lFilterPatterns = (wchar_t * *) malloc(aNumOfFilterPatterns*sizeof(wchar_t *));
1408 | for (i = 0; i < aNumOfFilterPatterns; i++)
1409 | {
1410 | lFilterPatterns[i] = utf8to16(aFilterPatterns[i]);
1411 | }
1412 |
1413 | lTitle = utf8to16(aTitle);
1414 | lDefaultPathAndFile = utf8to16(aDefaultPathAndFile);
1415 | lSingleFilterDescription = utf8to16(aSingleFilterDescription);
1416 |
1417 | lTmpWChar = tinyfd_openFileDialogW(
1418 | lTitle,
1419 | lDefaultPathAndFile,
1420 | aNumOfFilterPatterns,
1421 | (wchar_t const**) /*stupid cast for gcc*/
1422 | lFilterPatterns,
1423 | lSingleFilterDescription,
1424 | aAllowMultipleSelects);
1425 |
1426 | free(lTitle);
1427 | free(lDefaultPathAndFile);
1428 | free(lSingleFilterDescription);
1429 | for (i = 0; i < aNumOfFilterPatterns; i++)
1430 | {
1431 | free(lFilterPatterns[i]);
1432 | }
1433 | free(lFilterPatterns);
1434 |
1435 | if (!lTmpWChar)
1436 | {
1437 | return NULL;
1438 | }
1439 |
1440 | lTmpChar = utf16to8(lTmpWChar);
1441 | strcpy(aoBuff, lTmpChar);
1442 | free(lTmpChar);
1443 |
1444 | return aoBuff;
1445 | }
1446 |
1447 | #ifndef TINYFD_NOSELECTFOLDERWIN
1448 | static int __stdcall BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
1449 | {
1450 | if (uMsg == BFFM_INITIALIZED)
1451 | {
1452 | SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
1453 | }
1454 | return 0;
1455 | }
1456 |
1457 | static int __stdcall BrowseCallbackProcW(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
1458 | {
1459 | if (uMsg == BFFM_INITIALIZED)
1460 | {
1461 | SendMessage(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM)pData);
1462 | }
1463 | return 0;
1464 | }
1465 |
1466 | wchar_t const * tinyfd_selectFolderDialogW(
1467 | wchar_t const * const aTitle, /* NULL or "" */
1468 | wchar_t const * const aDefaultPath) /* NULL or "" */
1469 | {
1470 | static wchar_t lBuff[MAX_PATH_OR_CMD];
1471 |
1472 | BROWSEINFOW bInfo;
1473 | LPITEMIDLIST lpItem;
1474 | HRESULT lHResult;
1475 |
1476 | lHResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1477 |
1478 | bInfo.hwndOwner = 0;
1479 | bInfo.pidlRoot = NULL;
1480 | bInfo.pszDisplayName = lBuff;
1481 | bInfo.lpszTitle = aTitle && wcslen(aTitle) ? aTitle : NULL;
1482 | if (lHResult == S_OK || lHResult == S_FALSE)
1483 | {
1484 | bInfo.ulFlags = BIF_USENEWUI;
1485 | }
1486 | bInfo.lpfn = BrowseCallbackProcW;
1487 | bInfo.lParam = (LPARAM)aDefaultPath;
1488 | bInfo.iImage = -1;
1489 |
1490 | lpItem = SHBrowseForFolderW(&bInfo);
1491 | if (lpItem)
1492 | {
1493 | SHGetPathFromIDListW(lpItem, lBuff);
1494 | }
1495 |
1496 | if (lHResult == S_OK || lHResult == S_FALSE)
1497 | {
1498 | CoUninitialize();
1499 | }
1500 |
1501 | if (lpItem)
1502 | {
1503 | return lBuff;
1504 | }
1505 | else
1506 | {
1507 | return NULL;
1508 | }
1509 | }
1510 |
1511 |
1512 | static char const * selectFolderDialogWinGui8 (
1513 | char * const aoBuff ,
1514 | char const * const aTitle , /* NULL or "" */
1515 | char const * const aDefaultPath ) /* NULL or "" */
1516 | {
1517 | wchar_t * lTitle;
1518 | wchar_t * lDefaultPath;
1519 | wchar_t const * lTmpWChar;
1520 | char * lTmpChar;
1521 |
1522 | lTitle = utf8to16(aTitle);
1523 | lDefaultPath = utf8to16(aDefaultPath);
1524 |
1525 | lTmpWChar = tinyfd_selectFolderDialogW(
1526 | lTitle,
1527 | lDefaultPath);
1528 |
1529 | free(lTitle);
1530 | free(lDefaultPath);
1531 | if (!lTmpWChar)
1532 | {
1533 | return NULL;
1534 | }
1535 |
1536 | lTmpChar = utf16to8(lTmpWChar);
1537 | strcpy(aoBuff, lTmpChar);
1538 | free(lTmpChar);
1539 |
1540 | return aoBuff;
1541 | }
1542 | #endif /*TINYFD_NOSELECTFOLDERWIN*/
1543 |
1544 |
1545 | wchar_t const * tinyfd_colorChooserW(
1546 | wchar_t const * const aTitle, /* NULL or "" */
1547 | wchar_t const * const aDefaultHexRGB, /* NULL or "#FF0000"*/
1548 | unsigned char const aDefaultRGB[3], /* { 0 , 255 , 255 } */
1549 | unsigned char aoResultRGB[3]) /* { 0 , 0 , 0 } */
1550 | {
1551 | static wchar_t lResultHexRGB[8];
1552 | CHOOSECOLORW cc;
1553 | COLORREF crCustColors[16];
1554 | unsigned char lDefaultRGB[3];
1555 | int lRet;
1556 |
1557 | HRESULT lHResult;
1558 | lHResult = CoInitializeEx(NULL, 0);
1559 |
1560 | if (aDefaultHexRGB)
1561 | {
1562 | Hex2RGBW(aDefaultHexRGB, lDefaultRGB);
1563 | }
1564 | else
1565 | {
1566 | lDefaultRGB[0] = aDefaultRGB[0];
1567 | lDefaultRGB[1] = aDefaultRGB[1];
1568 | lDefaultRGB[2] = aDefaultRGB[2];
1569 | }
1570 |
1571 | /* we can't use aTitle */
1572 | cc.lStructSize = sizeof(CHOOSECOLOR);
1573 | cc.hwndOwner = NULL;
1574 | cc.hInstance = NULL;
1575 | cc.rgbResult = RGB(lDefaultRGB[0], lDefaultRGB[1], lDefaultRGB[2]);
1576 | cc.lpCustColors = crCustColors;
1577 | cc.Flags = CC_RGBINIT | CC_FULLOPEN;
1578 | cc.lCustData = 0;
1579 | cc.lpfnHook = NULL;
1580 | cc.lpTemplateName = NULL;
1581 |
1582 | lRet = ChooseColorW(&cc);
1583 |
1584 | if (!lRet)
1585 | {
1586 | return NULL;
1587 | }
1588 |
1589 | aoResultRGB[0] = GetRValue(cc.rgbResult);
1590 | aoResultRGB[1] = GetGValue(cc.rgbResult);
1591 | aoResultRGB[2] = GetBValue(cc.rgbResult);
1592 |
1593 | RGB2HexW(aoResultRGB, lResultHexRGB);
1594 |
1595 | if (lHResult == S_OK || lHResult == S_FALSE)
1596 | {
1597 | CoUninitialize();
1598 | }
1599 |
1600 | return lResultHexRGB;
1601 | }
1602 |
1603 |
1604 | static char const * colorChooserWinGui8(
1605 | char const * const aTitle, /* NULL or "" */
1606 | char const * const aDefaultHexRGB, /* NULL or "#FF0000"*/
1607 | unsigned char const aDefaultRGB[3], /* { 0 , 255 , 255 } */
1608 | unsigned char aoResultRGB[3]) /* { 0 , 0 , 0 } */
1609 | {
1610 | static char lResultHexRGB[8];
1611 |
1612 | wchar_t * lTitle;
1613 | wchar_t * lDefaultHexRGB;
1614 | wchar_t const * lTmpWChar;
1615 | char * lTmpChar;
1616 |
1617 | lTitle = utf8to16(aTitle);
1618 | lDefaultHexRGB = utf8to16(aDefaultHexRGB);
1619 |
1620 | lTmpWChar = tinyfd_colorChooserW(
1621 | lTitle,
1622 | lDefaultHexRGB,
1623 | aDefaultRGB,
1624 | aoResultRGB );
1625 |
1626 | free(lTitle);
1627 | free(lDefaultHexRGB);
1628 | if (!lTmpWChar)
1629 | {
1630 | return NULL;
1631 | }
1632 |
1633 | lTmpChar = utf16to8(lTmpWChar);
1634 | strcpy(lResultHexRGB, lTmpChar);
1635 | free(lTmpChar);
1636 |
1637 | return lResultHexRGB;
1638 | }
1639 |
1640 |
1641 | static int messageBoxWinGuiA (
1642 | char const * const aTitle , /* NULL or "" */
1643 | char const * const aMessage , /* NULL or "" may contain \n and \t */
1644 | char const * const aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
1645 | char const * const aIconType , /* "info" "warning" "error" "question" */
1646 | int const aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
1647 | {
1648 | int lBoxReturnValue;
1649 | UINT aCode ;
1650 |
1651 | if ( aIconType && ! strcmp( "warning" , aIconType ) )
1652 | {
1653 | aCode = MB_ICONWARNING ;
1654 | }
1655 | else if ( aIconType && ! strcmp("error", aIconType))
1656 | {
1657 | aCode = MB_ICONERROR ;
1658 | }
1659 | else if ( aIconType && ! strcmp("question", aIconType))
1660 | {
1661 | aCode = MB_ICONQUESTION ;
1662 | }
1663 | else
1664 | {
1665 | aCode = MB_ICONINFORMATION ;
1666 | }
1667 |
1668 | if ( aDialogType && ! strcmp( "okcancel" , aDialogType ) )
1669 | {
1670 | aCode += MB_OKCANCEL ;
1671 | if ( ! aDefaultButton )
1672 | {
1673 | aCode += MB_DEFBUTTON2 ;
1674 | }
1675 | }
1676 | else if ( aDialogType && ! strcmp( "yesno" , aDialogType ) )
1677 | {
1678 | aCode += MB_YESNO ;
1679 | if ( ! aDefaultButton )
1680 | {
1681 | aCode += MB_DEFBUTTON2 ;
1682 | }
1683 | }
1684 | else if (aDialogType && !strcmp("yesnocancel", aDialogType))
1685 | {
1686 | aCode += MB_YESNOCANCEL;
1687 | if (!aDefaultButton)
1688 | {
1689 | aCode += MB_DEFBUTTON3;
1690 | }
1691 | else if (aDefaultButton == 2)
1692 | {
1693 | aCode += MB_DEFBUTTON2;
1694 | }
1695 | }
1696 | else
1697 | {
1698 | aCode += MB_OK ;
1699 | }
1700 |
1701 | lBoxReturnValue = MessageBoxA(NULL, aMessage, aTitle, aCode);
1702 |
1703 | if (((aDialogType && !strcmp("yesnocancel", aDialogType))
1704 | && (lBoxReturnValue == IDNO)))
1705 | {
1706 | return 2;
1707 | }
1708 |
1709 | if ( ( ( aDialogType
1710 | && strcmp("yesnocancel", aDialogType)
1711 | && strcmp("okcancel", aDialogType)
1712 | && strcmp("yesno", aDialogType)))
1713 | || (lBoxReturnValue == IDOK)
1714 | || (lBoxReturnValue == IDYES) )
1715 | {
1716 | return 1 ;
1717 | }
1718 | else
1719 | {
1720 | return 0 ;
1721 | }
1722 | }
1723 |
1724 |
1725 | static char const * saveFileDialogWinGuiA (
1726 | char * const aoBuff ,
1727 | char const * const aTitle , /* NULL or "" */
1728 | char const * const aDefaultPathAndFile , /* NULL or "" */
1729 | int const aNumOfFilterPatterns , /* 0 */
1730 | char const * const * const aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
1731 | char const * const aSingleFilterDescription ) /* NULL or "image files" */
1732 | {
1733 | char lDirname [MAX_PATH_OR_CMD] ;
1734 | char lDialogString[MAX_PATH_OR_CMD];
1735 | char lFilterPatterns[MAX_PATH_OR_CMD] = "";
1736 | int i ;
1737 | char * p;
1738 | char * lRetval;
1739 | HRESULT lHResult;
1740 | OPENFILENAMEA ofn = { 0 };
1741 |
1742 | lHResult = CoInitializeEx(NULL,0);
1743 |
1744 | getPathWithoutFinalSlash(lDirname, aDefaultPathAndFile);
1745 | getLastName(aoBuff, aDefaultPathAndFile);
1746 |
1747 | if (aNumOfFilterPatterns > 0)
1748 | {
1749 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
1750 | {
1751 | strcpy(lFilterPatterns, aSingleFilterDescription);
1752 | strcat(lFilterPatterns, "\n");
1753 | }
1754 | strcat(lFilterPatterns, aFilterPatterns[0]);
1755 | for (i = 1; i < aNumOfFilterPatterns; i++)
1756 | {
1757 | strcat(lFilterPatterns, ";");
1758 | strcat(lFilterPatterns, aFilterPatterns[i]);
1759 | }
1760 | strcat(lFilterPatterns, "\n");
1761 | if ( ! (aSingleFilterDescription && strlen(aSingleFilterDescription) ) )
1762 | {
1763 | strcpy(lDialogString, lFilterPatterns);
1764 | strcat(lFilterPatterns, lDialogString);
1765 | }
1766 | strcat(lFilterPatterns, "All Files\n*.*\n");
1767 | p = lFilterPatterns;
1768 | while ((p = strchr(p, '\n')) != NULL)
1769 | {
1770 | *p = '\0';
1771 | p ++ ;
1772 | }
1773 | }
1774 |
1775 | ofn.lStructSize = sizeof(OPENFILENAME) ;
1776 | ofn.hwndOwner = 0 ;
1777 | ofn.hInstance = 0 ;
1778 | ofn.lpstrFilter = lFilterPatterns && strlen(lFilterPatterns) ? lFilterPatterns : NULL;
1779 | ofn.lpstrCustomFilter = NULL ;
1780 | ofn.nMaxCustFilter = 0 ;
1781 | ofn.nFilterIndex = 1 ;
1782 | ofn.lpstrFile = aoBuff;
1783 |
1784 | ofn.nMaxFile = MAX_PATH_OR_CMD ;
1785 | ofn.lpstrFileTitle = NULL ;
1786 | ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT ;
1787 | ofn.lpstrInitialDir = lDirname && strlen(lDirname) ? lDirname : NULL;
1788 | ofn.lpstrTitle = aTitle && strlen(aTitle) ? aTitle : NULL;
1789 | ofn.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR ;
1790 | ofn.nFileOffset = 0 ;
1791 | ofn.nFileExtension = 0 ;
1792 | ofn.lpstrDefExt = NULL ;
1793 | ofn.lCustData = 0L ;
1794 | ofn.lpfnHook = NULL ;
1795 | ofn.lpTemplateName = NULL ;
1796 |
1797 | if ( GetSaveFileNameA ( & ofn ) == 0 )
1798 | {
1799 | lRetval = NULL ;
1800 | }
1801 | else
1802 | {
1803 | lRetval = aoBuff ;
1804 | }
1805 |
1806 | if (lHResult==S_OK || lHResult==S_FALSE)
1807 | {
1808 | CoUninitialize();
1809 | }
1810 | return lRetval ;
1811 | }
1812 |
1813 |
1814 | static char const * openFileDialogWinGuiA (
1815 | char * const aoBuff ,
1816 | char const * const aTitle , /* NULL or "" */
1817 | char const * const aDefaultPathAndFile , /* NULL or "" */
1818 | int const aNumOfFilterPatterns , /* 0 */
1819 | char const * const * const aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
1820 | char const * const aSingleFilterDescription , /* NULL or "image files" */
1821 | int const aAllowMultipleSelects ) /* 0 or 1 */
1822 | {
1823 | char lDirname [MAX_PATH_OR_CMD] ;
1824 | char lFilterPatterns[MAX_PATH_OR_CMD] = "";
1825 | char lDialogString[MAX_PATH_OR_CMD] ;
1826 | char * lPointers[MAX_MULTIPLE_FILES];
1827 | size_t lLengths[MAX_MULTIPLE_FILES];
1828 | int i , j ;
1829 | char * p;
1830 | size_t lBuffLen ;
1831 | char * lRetval;
1832 | HRESULT lHResult;
1833 | OPENFILENAMEA ofn = {0};
1834 |
1835 | lHResult = CoInitializeEx(NULL,0);
1836 |
1837 | getPathWithoutFinalSlash(lDirname, aDefaultPathAndFile);
1838 | getLastName(aoBuff, aDefaultPathAndFile);
1839 |
1840 | if (aNumOfFilterPatterns > 0)
1841 | {
1842 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
1843 | {
1844 | strcpy(lFilterPatterns, aSingleFilterDescription);
1845 | strcat(lFilterPatterns, "\n");
1846 | }
1847 | strcat(lFilterPatterns, aFilterPatterns[0]);
1848 | for (i = 1; i < aNumOfFilterPatterns; i++)
1849 | {
1850 | strcat(lFilterPatterns, ";");
1851 | strcat(lFilterPatterns, aFilterPatterns[i]);
1852 | }
1853 | strcat(lFilterPatterns, "\n");
1854 | if ( ! (aSingleFilterDescription && strlen(aSingleFilterDescription) ) )
1855 | {
1856 | strcpy(lDialogString, lFilterPatterns);
1857 | strcat(lFilterPatterns, lDialogString);
1858 | }
1859 | strcat(lFilterPatterns, "All Files\n*.*\n");
1860 | p = lFilterPatterns;
1861 | while ((p = strchr(p, '\n')) != NULL)
1862 | {
1863 | *p = '\0';
1864 | p ++ ;
1865 | }
1866 | }
1867 |
1868 | ofn.lStructSize = sizeof ( OPENFILENAME ) ;
1869 | ofn.hwndOwner = 0 ;
1870 | ofn.hInstance = 0 ;
1871 | ofn.lpstrFilter = lFilterPatterns && strlen(lFilterPatterns) ? lFilterPatterns : NULL;
1872 | ofn.lpstrCustomFilter = NULL ;
1873 | ofn.nMaxCustFilter = 0 ;
1874 | ofn.nFilterIndex = 1 ;
1875 | ofn.lpstrFile = aoBuff ;
1876 | ofn.nMaxFile = MAX_PATH_OR_CMD ;
1877 | ofn.lpstrFileTitle = NULL ;
1878 | ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT ;
1879 | ofn.lpstrInitialDir = lDirname && strlen(lDirname) ? lDirname : NULL;
1880 | ofn.lpstrTitle = aTitle && strlen(aTitle) ? aTitle : NULL;
1881 | ofn.Flags = OFN_EXPLORER | OFN_NOCHANGEDIR ;
1882 | ofn.nFileOffset = 0 ;
1883 | ofn.nFileExtension = 0 ;
1884 | ofn.lpstrDefExt = NULL ;
1885 | ofn.lCustData = 0L ;
1886 | ofn.lpfnHook = NULL ;
1887 | ofn.lpTemplateName = NULL ;
1888 |
1889 | if ( aAllowMultipleSelects )
1890 | {
1891 | ofn.Flags |= OFN_ALLOWMULTISELECT;
1892 | }
1893 |
1894 | if ( GetOpenFileNameA ( & ofn ) == 0 )
1895 | {
1896 | lRetval = NULL ;
1897 | }
1898 | else
1899 | {
1900 | lBuffLen = strlen(aoBuff) ;
1901 | lPointers[0] = aoBuff + lBuffLen + 1 ;
1902 | if ( !aAllowMultipleSelects || (lPointers[0][0] == '\0') )
1903 | {
1904 | lRetval = aoBuff ;
1905 | }
1906 | else
1907 | {
1908 | i = 0 ;
1909 | do
1910 | {
1911 | lLengths[i] = strlen(lPointers[i]);
1912 | lPointers[i+1] = lPointers[i] + lLengths[i] + 1 ;
1913 | i ++ ;
1914 | }
1915 | while ( lPointers[i][0] != '\0' );
1916 | i--;
1917 | p = aoBuff + MAX_MULTIPLE_FILES*MAX_PATH_OR_CMD - 1 ;
1918 | * p = '\0';
1919 | for ( j = i ; j >=0 ; j-- )
1920 | {
1921 | p -= lLengths[j];
1922 | memmove(p, lPointers[j], lLengths[j]);
1923 | p--;
1924 | *p = '\\';
1925 | p -= lBuffLen ;
1926 | memmove(p, aoBuff, lBuffLen);
1927 | p--;
1928 | *p = '|';
1929 | }
1930 | p++;
1931 | lRetval = p ;
1932 | }
1933 | }
1934 |
1935 | if (lHResult==S_OK || lHResult==S_FALSE)
1936 | {
1937 | CoUninitialize();
1938 | }
1939 | return lRetval;
1940 | }
1941 |
1942 | #ifndef TINYFD_NOSELECTFOLDERWIN
1943 | static char const * selectFolderDialogWinGuiA (
1944 | char * const aoBuff ,
1945 | char const * const aTitle , /* NULL or "" */
1946 | char const * const aDefaultPath ) /* NULL or "" */
1947 | {
1948 | BROWSEINFOA bInfo ;
1949 | LPITEMIDLIST lpItem ;
1950 | HRESULT lHResult;
1951 |
1952 | lHResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1953 |
1954 | /* we can't use aDefaultPath */
1955 | bInfo.hwndOwner = 0 ;
1956 | bInfo.pidlRoot = NULL ;
1957 | bInfo.pszDisplayName = aoBuff ;
1958 | bInfo.lpszTitle = aTitle && strlen(aTitle) ? aTitle : NULL;
1959 | if (lHResult == S_OK || lHResult == S_FALSE)
1960 | {
1961 | bInfo.ulFlags = BIF_USENEWUI;
1962 | }
1963 | bInfo.lpfn = BrowseCallbackProc;
1964 | bInfo.lParam = (LPARAM)aDefaultPath;
1965 | bInfo.iImage = -1 ;
1966 |
1967 | lpItem = SHBrowseForFolderA ( & bInfo ) ;
1968 | if ( lpItem )
1969 | {
1970 | SHGetPathFromIDListA ( lpItem , aoBuff ) ;
1971 | }
1972 |
1973 | if (lHResult==S_OK || lHResult==S_FALSE)
1974 | {
1975 | CoUninitialize();
1976 | }
1977 | return aoBuff ;
1978 | }
1979 | #endif /*TINYFD_NOSELECTFOLDERWIN*/
1980 |
1981 |
1982 | static char const * colorChooserWinGuiA(
1983 | char const * const aTitle, /* NULL or "" */
1984 | char const * const aDefaultHexRGB, /* NULL or "#FF0000"*/
1985 | unsigned char const aDefaultRGB[3], /* { 0 , 255 , 255 } */
1986 | unsigned char aoResultRGB[3]) /* { 0 , 0 , 0 } */
1987 | {
1988 | static char lResultHexRGB[8];
1989 |
1990 | CHOOSECOLORA cc;
1991 | COLORREF crCustColors[16];
1992 | unsigned char lDefaultRGB[3];
1993 | int lRet;
1994 |
1995 | if ( aDefaultHexRGB )
1996 | {
1997 | Hex2RGB(aDefaultHexRGB, lDefaultRGB);
1998 | }
1999 | else
2000 | {
2001 | lDefaultRGB[0]=aDefaultRGB[0];
2002 | lDefaultRGB[1]=aDefaultRGB[1];
2003 | lDefaultRGB[2]=aDefaultRGB[2];
2004 | }
2005 |
2006 | /* we can't use aTitle */
2007 | cc.lStructSize = sizeof ( CHOOSECOLOR ) ;
2008 | cc.hwndOwner = NULL ;
2009 | cc.hInstance = NULL ;
2010 | cc.rgbResult = RGB(lDefaultRGB[0], lDefaultRGB[1], lDefaultRGB[2]);
2011 | cc.lpCustColors = crCustColors;
2012 | cc.Flags = CC_RGBINIT | CC_FULLOPEN;
2013 | cc.lCustData = 0;
2014 | cc.lpfnHook = NULL;
2015 | cc.lpTemplateName = NULL;
2016 |
2017 | lRet = ChooseColorA(&cc);
2018 |
2019 | if ( ! lRet )
2020 | {
2021 | return NULL;
2022 | }
2023 |
2024 | aoResultRGB[0] = GetRValue(cc.rgbResult);
2025 | aoResultRGB[1] = GetGValue(cc.rgbResult);
2026 | aoResultRGB[2] = GetBValue(cc.rgbResult);
2027 |
2028 | RGB2Hex(aoResultRGB, lResultHexRGB);
2029 |
2030 | return lResultHexRGB;
2031 | }
2032 |
2033 | #endif /* TINYFD_NOLIB */
2034 |
2035 | static int dialogPresent ( )
2036 | {
2037 | static int lDialogPresent = -1 ;
2038 | char lBuff [MAX_PATH_OR_CMD] ;
2039 | FILE * lIn ;
2040 | char const * lString = "dialog.exe";
2041 | if ( lDialogPresent < 0 )
2042 | {
2043 | if (!(lIn = _popen("where dialog.exe","r")))
2044 | {
2045 | lDialogPresent = 0 ;
2046 | return 0 ;
2047 | }
2048 | while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
2049 | {}
2050 | _pclose ( lIn ) ;
2051 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
2052 | {
2053 | lBuff[strlen ( lBuff ) -1] = '\0' ;
2054 | }
2055 | if ( strcmp(lBuff+strlen(lBuff)-strlen(lString),lString) )
2056 | {
2057 | lDialogPresent = 0 ;
2058 | }
2059 | else
2060 | {
2061 | lDialogPresent = 1 ;
2062 | }
2063 | }
2064 | return lDialogPresent;
2065 | }
2066 |
2067 |
2068 | static int messageBoxWinConsole (
2069 | char const * const aTitle , /* NULL or "" */
2070 | char const * const aMessage , /* NULL or "" may contain \n and \t */
2071 | char const * const aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
2072 | char const * const aIconType , /* "info" "warning" "error" "question" */
2073 | int const aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
2074 | {
2075 | char lDialogString[MAX_PATH_OR_CMD];
2076 | char lDialogFile[MAX_PATH_OR_CMD];
2077 | FILE * lIn;
2078 | char lBuff [MAX_PATH_OR_CMD] = "";
2079 |
2080 | strcpy ( lDialogString , "dialog " ) ;
2081 | if ( aTitle && strlen(aTitle) )
2082 | {
2083 | strcat(lDialogString, "--title \"") ;
2084 | strcat(lDialogString, aTitle) ;
2085 | strcat(lDialogString, "\" ") ;
2086 | }
2087 |
2088 | if ( aDialogType && ( !strcmp( "okcancel" , aDialogType )
2089 | || !strcmp("yesno", aDialogType) || !strcmp("yesnocancel", aDialogType) ) )
2090 | {
2091 | strcat(lDialogString, "--backtitle \"") ;
2092 | strcat(lDialogString, "tab: move focus") ;
2093 | strcat(lDialogString, "\" ") ;
2094 | }
2095 |
2096 | if ( aDialogType && ! strcmp( "okcancel" , aDialogType ) )
2097 | {
2098 | if ( ! aDefaultButton )
2099 | {
2100 | strcat ( lDialogString , "--defaultno " ) ;
2101 | }
2102 | strcat ( lDialogString ,
2103 | "--yes-label \"Ok\" --no-label \"Cancel\" --yesno " ) ;
2104 | }
2105 | else if ( aDialogType && ! strcmp( "yesno" , aDialogType ) )
2106 | {
2107 | if ( ! aDefaultButton )
2108 | {
2109 | strcat ( lDialogString , "--defaultno " ) ;
2110 | }
2111 | strcat ( lDialogString , "--yesno " ) ;
2112 | }
2113 | else if (aDialogType && !strcmp("yesnocancel", aDialogType))
2114 | {
2115 | if (!aDefaultButton)
2116 | {
2117 | strcat(lDialogString, "--defaultno ");
2118 | }
2119 | strcat(lDialogString, "--menu ");
2120 | }
2121 | else
2122 | {
2123 | strcat ( lDialogString , "--msgbox " ) ;
2124 | }
2125 |
2126 | strcat ( lDialogString , "\"" ) ;
2127 | if ( aMessage && strlen(aMessage) )
2128 | {
2129 | replaceSubStr ( aMessage , "\n" , "\\n" , lBuff ) ;
2130 | strcat(lDialogString, lBuff) ;
2131 | lBuff[0]='\0';
2132 | }
2133 | strcat(lDialogString, "\" ");
2134 |
2135 | if (aDialogType && !strcmp("yesnocancel", aDialogType))
2136 | {
2137 | strcat(lDialogString, "0 60 0 Yes \"\" No \"\"");
2138 | strcat(lDialogString, "2>>");
2139 | }
2140 | else
2141 | {
2142 | strcat(lDialogString, "10 60");
2143 | strcat(lDialogString, " && echo 1 > ");
2144 | }
2145 |
2146 | strcpy(lDialogFile, getenv("USERPROFILE"));
2147 | strcat(lDialogFile, "\\AppData\\Local\\Temp\\tinyfd.txt");
2148 | strcat(lDialogString, lDialogFile);
2149 |
2150 | /*if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;*/
2151 | system ( lDialogString ) ;
2152 |
2153 | if (!(lIn = fopen(lDialogFile, "r")))
2154 | {
2155 | remove(lDialogFile);
2156 | return 0 ;
2157 | }
2158 | while (fgets(lBuff, sizeof(lBuff), lIn) != NULL)
2159 | {}
2160 | fclose(lIn);
2161 | remove(lDialogFile);
2162 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
2163 | {
2164 | lBuff[strlen ( lBuff ) -1] = '\0' ;
2165 | }
2166 |
2167 | /* if (tinyfd_verbose) printf("lBuff: %s\n", lBuff); */
2168 | if ( ! strlen(lBuff) )
2169 | {
2170 | return 0;
2171 | }
2172 |
2173 | if (aDialogType && !strcmp("yesnocancel", aDialogType))
2174 | {
2175 | if (lBuff[0] == 'Y') return 1;
2176 | else return 2;
2177 | }
2178 |
2179 | return 1;
2180 | }
2181 |
2182 |
2183 | static char const * inputBoxWinConsole(
2184 | char * const aoBuff ,
2185 | char const * const aTitle , /* NULL or "" */
2186 | char const * const aMessage , /* NULL or "" may NOT contain \n nor \t */
2187 | char const * const aDefaultInput ) /* "" , if NULL it's a passwordBox */
2188 | {
2189 | char lDialogString[MAX_PATH_OR_CMD];
2190 | char lDialogFile[MAX_PATH_OR_CMD];
2191 | FILE * lIn;
2192 | int lResult;
2193 |
2194 | strcpy(lDialogFile, getenv("USERPROFILE"));
2195 | strcat(lDialogFile, "\\AppData\\Local\\Temp\\tinyfd.txt");
2196 | strcpy(lDialogString , "echo|set /p=1 >" ) ;
2197 | strcat(lDialogString, lDialogFile);
2198 | strcat( lDialogString , " & " ) ;
2199 |
2200 | strcat ( lDialogString , "dialog " ) ;
2201 | if ( aTitle && strlen(aTitle) )
2202 | {
2203 | strcat(lDialogString, "--title \"") ;
2204 | strcat(lDialogString, aTitle) ;
2205 | strcat(lDialogString, "\" ") ;
2206 | }
2207 |
2208 | strcat(lDialogString, "--backtitle \"") ;
2209 | strcat(lDialogString, "tab: move focus") ;
2210 | if ( ! aDefaultInput )
2211 | {
2212 | strcat(lDialogString, " (sometimes nothing, no blink nor star, is shown in text field)") ;
2213 | }
2214 |
2215 | strcat(lDialogString, "\" ") ;
2216 |
2217 | if ( ! aDefaultInput )
2218 | {
2219 | strcat ( lDialogString , "--insecure --passwordbox" ) ;
2220 | }
2221 | else
2222 | {
2223 | strcat ( lDialogString , "--inputbox" ) ;
2224 | }
2225 | strcat ( lDialogString , " \"" ) ;
2226 | if ( aMessage && strlen(aMessage) )
2227 | {
2228 | strcat(lDialogString, aMessage) ;
2229 | }
2230 | strcat(lDialogString,"\" 10 60 ") ;
2231 | if ( aDefaultInput && strlen(aDefaultInput) )
2232 | {
2233 | strcat(lDialogString, "\"") ;
2234 | strcat(lDialogString, aDefaultInput) ;
2235 | strcat(lDialogString, "\" ") ;
2236 | }
2237 |
2238 | strcat(lDialogString, "2>>");
2239 | strcpy(lDialogFile, getenv("USERPROFILE"));
2240 | strcat(lDialogFile, "\\AppData\\Local\\Temp\\tinyfd.txt");
2241 | strcat(lDialogString, lDialogFile);
2242 | strcat(lDialogString, " || echo 0 > ");
2243 | strcat(lDialogString, lDialogFile);
2244 |
2245 | /* printf ( "lDialogString: %s\n" , lDialogString ) ; */
2246 | system ( lDialogString ) ;
2247 |
2248 | if (!(lIn = fopen(lDialogFile, "r")))
2249 | {
2250 | remove(lDialogFile);
2251 | return 0 ;
2252 | }
2253 | while (fgets(aoBuff, MAX_PATH_OR_CMD, lIn) != NULL)
2254 | {}
2255 | fclose(lIn);
2256 |
2257 | wipefile(lDialogFile);
2258 | remove(lDialogFile);
2259 | if ( aoBuff[strlen ( aoBuff ) -1] == '\n' )
2260 | {
2261 | aoBuff[strlen ( aoBuff ) -1] = '\0' ;
2262 | }
2263 | /* printf ( "aoBuff: %s\n" , aoBuff ) ; */
2264 |
2265 | /* printf ( "aoBuff: %s len: %lu \n" , aoBuff , strlen(aoBuff) ) ; */
2266 | lResult = strncmp ( aoBuff , "1" , 1) ? 0 : 1 ;
2267 | /* printf ( "lResult: %d \n" , lResult ) ; */
2268 | if ( ! lResult )
2269 | {
2270 | return NULL ;
2271 | }
2272 | /* printf ( "aoBuff+1: %s\n" , aoBuff+1 ) ; */
2273 | return aoBuff+3 ;
2274 | }
2275 |
2276 |
2277 | static char const * saveFileDialogWinConsole (
2278 | char * const aoBuff ,
2279 | char const * const aTitle , /* NULL or "" */
2280 | char const * const aDefaultPathAndFile ) /* NULL or "" */
2281 | {
2282 | char lDialogString[MAX_PATH_OR_CMD];
2283 | char lPathAndFile[MAX_PATH_OR_CMD] = "";
2284 | FILE * lIn;
2285 |
2286 | strcpy ( lDialogString , "dialog " ) ;
2287 | if ( aTitle && strlen(aTitle) )
2288 | {
2289 | strcat(lDialogString, "--title \"") ;
2290 | strcat(lDialogString, aTitle) ;
2291 | strcat(lDialogString, "\" ") ;
2292 | }
2293 |
2294 | strcat(lDialogString, "--backtitle \"") ;
2295 | strcat(lDialogString,
2296 | "tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY") ;
2297 | strcat(lDialogString, "\" ") ;
2298 |
2299 | strcat ( lDialogString , "--fselect \"" ) ;
2300 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
2301 | {
2302 | /* dialog.exe uses unix separators even on windows */
2303 | strcpy(lPathAndFile, aDefaultPathAndFile);
2304 | replaceChr ( lPathAndFile , '\\' , '/' ) ;
2305 | }
2306 |
2307 | /* dialog.exe needs at least one separator */
2308 | if ( ! strchr(lPathAndFile, '/') )
2309 | {
2310 | strcat(lDialogString, "./") ;
2311 | }
2312 | strcat(lDialogString, lPathAndFile) ;
2313 | strcat(lDialogString, "\" 0 60 2>");
2314 | strcpy(lPathAndFile, getenv("USERPROFILE"));
2315 | strcat(lPathAndFile, "\\AppData\\Local\\Temp\\tinyfd.txt");
2316 | strcat(lDialogString, lPathAndFile);
2317 |
2318 | /* printf ( "lDialogString: %s\n" , lDialogString ) ; */
2319 | system ( lDialogString ) ;
2320 |
2321 | if (!(lIn = fopen(lPathAndFile, "r")))
2322 | {
2323 | remove(lPathAndFile);
2324 | return NULL;
2325 | }
2326 | while (fgets(aoBuff, MAX_PATH_OR_CMD, lIn) != NULL)
2327 | {}
2328 | fclose(lIn);
2329 | remove(lPathAndFile);
2330 | replaceChr ( aoBuff , '/' , '\\' ) ;
2331 | /* printf ( "aoBuff: %s\n" , aoBuff ) ; */
2332 | getLastName(lDialogString,aoBuff);
2333 | if ( ! strlen(lDialogString) )
2334 | {
2335 | return NULL;
2336 | }
2337 | return aoBuff;
2338 | }
2339 |
2340 |
2341 | static char const * openFileDialogWinConsole (
2342 | char * const aoBuff ,
2343 | char const * const aTitle , /* NULL or "" */
2344 | char const * const aDefaultPathAndFile , /* NULL or "" */
2345 | int const aAllowMultipleSelects ) /* 0 or 1 */
2346 | {
2347 | char lFilterPatterns[MAX_PATH_OR_CMD] = "";
2348 | char lDialogString[MAX_PATH_OR_CMD] ;
2349 | FILE * lIn;
2350 |
2351 | strcpy ( lDialogString , "dialog " ) ;
2352 | if ( aTitle && strlen(aTitle) )
2353 | {
2354 | strcat(lDialogString, "--title \"") ;
2355 | strcat(lDialogString, aTitle) ;
2356 | strcat(lDialogString, "\" ") ;
2357 | }
2358 |
2359 | strcat(lDialogString, "--backtitle \"") ;
2360 | strcat(lDialogString,
2361 | "tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY") ;
2362 | strcat(lDialogString, "\" ") ;
2363 |
2364 | strcat ( lDialogString , "--fselect \"" ) ;
2365 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
2366 | {
2367 | /* dialog.exe uses unix separators even on windows */
2368 | strcpy(lFilterPatterns, aDefaultPathAndFile);
2369 | replaceChr ( lFilterPatterns , '\\' , '/' ) ;
2370 | }
2371 |
2372 | /* dialog.exe needs at least one separator */
2373 | if ( ! strchr(lFilterPatterns, '/') )
2374 | {
2375 | strcat(lDialogString, "./") ;
2376 | }
2377 | strcat(lDialogString, lFilterPatterns) ;
2378 | strcat(lDialogString, "\" 0 60 2>");
2379 | strcpy(lFilterPatterns, getenv("USERPROFILE"));
2380 | strcat(lFilterPatterns, "\\AppData\\Local\\Temp\\tinyfd.txt");
2381 | strcat(lDialogString, lFilterPatterns);
2382 |
2383 | /* printf ( "lDialogString: %s\n" , lDialogString ) ; */
2384 | system ( lDialogString ) ;
2385 |
2386 | if (!(lIn = fopen(lFilterPatterns, "r")))
2387 | {
2388 | remove(lFilterPatterns);
2389 | return NULL;
2390 | }
2391 | while (fgets(aoBuff, MAX_PATH_OR_CMD, lIn) != NULL)
2392 | {}
2393 | fclose(lIn);
2394 | remove(lFilterPatterns);
2395 | replaceChr ( aoBuff , '/' , '\\' ) ;
2396 | /* printf ( "aoBuff: %s\n" , aoBuff ) ; */
2397 | return aoBuff;
2398 | }
2399 |
2400 |
2401 | static char const * selectFolderDialogWinConsole (
2402 | char * const aoBuff ,
2403 | char const * const aTitle , /* NULL or "" */
2404 | char const * const aDefaultPath ) /* NULL or "" */
2405 | {
2406 | char lDialogString [MAX_PATH_OR_CMD] ;
2407 | char lString [MAX_PATH_OR_CMD] ;
2408 | FILE * lIn ;
2409 |
2410 | strcpy ( lDialogString , "dialog " ) ;
2411 | if ( aTitle && strlen(aTitle) )
2412 | {
2413 | strcat(lDialogString, "--title \"") ;
2414 | strcat(lDialogString, aTitle) ;
2415 | strcat(lDialogString, "\" ") ;
2416 | }
2417 |
2418 | strcat(lDialogString, "--backtitle \"") ;
2419 | strcat(lDialogString,
2420 | "tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY") ;
2421 | strcat(lDialogString, "\" ") ;
2422 |
2423 | strcat ( lDialogString , "--dselect \"" ) ;
2424 | if ( aDefaultPath && strlen(aDefaultPath) )
2425 | {
2426 | /* dialog.exe uses unix separators even on windows */
2427 | strcpy(lString, aDefaultPath) ;
2428 | ensureFinalSlash(lString);
2429 | replaceChr ( lString , '\\' , '/' ) ;
2430 | strcat(lDialogString, lString) ;
2431 | }
2432 | else
2433 | {
2434 | /* dialog.exe needs at least one separator */
2435 | strcat(lDialogString, "./") ;
2436 | }
2437 | strcat(lDialogString, "\" 0 60 2>");
2438 | strcpy(lString, getenv("USERPROFILE"));
2439 | strcat(lString, "\\AppData\\Local\\Temp\\tinyfd.txt");
2440 | strcat(lDialogString, lString);
2441 |
2442 | /* printf ( "lDialogString: %s\n" , lDialogString ) ; */
2443 | system ( lDialogString ) ;
2444 |
2445 | if (!(lIn = fopen(lString, "r")))
2446 | {
2447 | remove(lString);
2448 | return NULL;
2449 | }
2450 | while (fgets(aoBuff, MAX_PATH_OR_CMD, lIn) != NULL)
2451 | {}
2452 | fclose(lIn);
2453 | remove(lString);
2454 | replaceChr ( aoBuff , '/' , '\\' ) ;
2455 | /* printf ( "aoBuff: %s\n" , aoBuff ) ; */
2456 | return aoBuff;
2457 | }
2458 |
2459 |
2460 | int tinyfd_messageBox (
2461 | char const * const aTitle , /* NULL or "" */
2462 | char const * const aMessage , /* NULL or "" may contain \n and \t */
2463 | char const * const aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
2464 | char const * const aIconType , /* "info" "warning" "error" "question" */
2465 | int const aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
2466 | {
2467 | char lChar ;
2468 |
2469 | #ifndef TINYFD_NOLIB
2470 | if ((!tinyfd_forceConsole || !(GetConsoleWindow() || dialogPresent()))
2471 | && (!getenv("SSH_CLIENT") || getenv("DISPLAY")))
2472 | {
2473 | if (aTitle&&!strcmp(aTitle, "tinyfd_query")){ strcpy(tinyfd_response, "windows"); return 1; }
2474 | if (tinyfd_winUtf8)
2475 | {
2476 | return messageBoxWinGui8(
2477 | aTitle, aMessage, aDialogType, aIconType, aDefaultButton);
2478 | }
2479 | else
2480 | {
2481 | return messageBoxWinGuiA(
2482 | aTitle, aMessage, aDialogType, aIconType, aDefaultButton);
2483 | }
2484 | }
2485 | else
2486 | #endif /* TINYFD_NOLIB */
2487 | if ( dialogPresent() )
2488 | {
2489 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return 0;}
2490 | return messageBoxWinConsole(
2491 | aTitle,aMessage,aDialogType,aIconType,aDefaultButton);
2492 | }
2493 | else
2494 | {
2495 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return 0;}
2496 | if (!gWarningDisplayed && !tinyfd_forceConsole )
2497 | {
2498 | gWarningDisplayed = 1;
2499 | printf("\n\n%s\n", gTitle);
2500 | printf("%s\n\n", gMessageWin);
2501 | }
2502 | if ( aTitle && strlen(aTitle) )
2503 | {
2504 | printf ("\n%s\n\n", aTitle);
2505 | }
2506 | if ( aDialogType && !strcmp("yesno",aDialogType) )
2507 | {
2508 | do
2509 | {
2510 | if ( aMessage && strlen(aMessage) )
2511 | {
2512 | printf("%s\n",aMessage);
2513 | }
2514 | printf("y/n: ");
2515 | lChar = (char) tolower ( _getch() ) ;
2516 | printf("\n\n");
2517 | }
2518 | while ( lChar != 'y' && lChar != 'n' ) ;
2519 | return lChar == 'y' ? 1 : 0 ;
2520 | }
2521 | else if ( aDialogType && !strcmp("okcancel",aDialogType) )
2522 | {
2523 | do
2524 | {
2525 | if ( aMessage && strlen(aMessage) )
2526 | {
2527 | printf("%s\n",aMessage);
2528 | }
2529 | printf("[O]kay/[C]ancel: ");
2530 | lChar = (char) tolower ( _getch() ) ;
2531 | printf("\n\n");
2532 | }
2533 | while ( lChar != 'o' && lChar != 'c' ) ;
2534 | return lChar == 'o' ? 1 : 0 ;
2535 | }
2536 | else if (aDialogType && !strcmp("yesnocancel", aDialogType))
2537 | {
2538 | do
2539 | {
2540 | if (aMessage && strlen(aMessage))
2541 | {
2542 | printf("%s\n", aMessage);
2543 | }
2544 | printf("[Y]es/[N]o/[C]ancel: ");
2545 | lChar = (char)tolower(_getch());
2546 | printf("\n\n");
2547 | } while (lChar != 'y' && lChar != 'n' && lChar != 'c');
2548 | return (lChar == 'y') ? 1 : (lChar == 'n') ? 2 : 0 ;
2549 | }
2550 | else
2551 | {
2552 | if ( aMessage && strlen(aMessage) )
2553 | {
2554 | printf("%s\n\n",aMessage);
2555 | }
2556 | printf("press enter to continue ");
2557 | lChar = (char) _getch() ;
2558 | printf("\n\n");
2559 | return 1 ;
2560 | }
2561 | }
2562 | }
2563 |
2564 |
2565 | /* returns NULL on cancel */
2566 | char const * tinyfd_inputBox(
2567 | char const * const aTitle , /* NULL or "" */
2568 | char const * const aMessage , /* NULL or "" may NOT contain \n nor \t */
2569 | char const * const aDefaultInput ) /* "" , if NULL it's a passwordBox */
2570 | {
2571 | static char lBuff [MAX_PATH_OR_CMD] ;
2572 | char * lEOF;
2573 |
2574 | #ifndef TINYFD_NOLIB
2575 | DWORD mode = 0;
2576 | HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
2577 |
2578 | if ((!tinyfd_forceConsole || !(
2579 | GetConsoleWindow() ||
2580 | dialogPresent()))
2581 | && ( !getenv("SSH_CLIENT") || getenv("DISPLAY") ) )
2582 | {
2583 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"windows");return (char const *)1;}
2584 | lBuff[0]='\0';
2585 | return inputBoxWinGui(lBuff,aTitle,aMessage,aDefaultInput);
2586 | }
2587 | else
2588 | #endif /* TINYFD_NOLIB */
2589 | if ( dialogPresent() )
2590 | {
2591 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
2592 | lBuff[0]='\0';
2593 | return inputBoxWinConsole(lBuff,aTitle,aMessage,aDefaultInput);
2594 | }
2595 | else
2596 | {
2597 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return (char const *)0;}
2598 | lBuff[0]='\0';
2599 | if (!gWarningDisplayed && !tinyfd_forceConsole)
2600 | {
2601 | gWarningDisplayed = 1 ;
2602 | printf("\n\n%s\n", gTitle);
2603 | printf("%s\n\n", gMessageWin);
2604 | }
2605 | if ( aTitle && strlen(aTitle) )
2606 | {
2607 | printf ("\n%s\n\n", aTitle);
2608 | }
2609 | if ( aMessage && strlen(aMessage) )
2610 | {
2611 | printf("%s\n",aMessage);
2612 | }
2613 | printf("(ctrl-Z + enter to cancel): ");
2614 | #ifndef TINYFD_NOLIB
2615 | if ( ! aDefaultInput )
2616 | {
2617 | GetConsoleMode(hStdin,&mode);
2618 | SetConsoleMode(hStdin,mode & (~ENABLE_ECHO_INPUT) );
2619 | }
2620 | #endif /* TINYFD_NOLIB */
2621 | lEOF = fgets(lBuff, MAX_PATH_OR_CMD, stdin);
2622 | if ( ! lEOF )
2623 | {
2624 | return NULL;
2625 | }
2626 | #ifndef TINYFD_NOLIB
2627 | if ( ! aDefaultInput )
2628 | {
2629 | SetConsoleMode(hStdin,mode);
2630 | printf ("\n");
2631 | }
2632 | #endif /* TINYFD_NOLIB */
2633 | printf ("\n");
2634 | if ( strchr(lBuff,27) )
2635 | {
2636 | return NULL ;
2637 | }
2638 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
2639 | {
2640 | lBuff[strlen ( lBuff ) -1] = '\0' ;
2641 | }
2642 | return lBuff ;
2643 | }
2644 | }
2645 |
2646 |
2647 | char const * tinyfd_saveFileDialog (
2648 | char const * const aTitle , /* NULL or "" */
2649 | char const * const aDefaultPathAndFile , /* NULL or "" */
2650 | int const aNumOfFilterPatterns , /* 0 */
2651 | char const * const * const aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
2652 | char const * const aSingleFilterDescription ) /* NULL or "image files" */
2653 | {
2654 | static char lBuff [MAX_PATH_OR_CMD] ;
2655 | char lString[MAX_PATH_OR_CMD] ;
2656 | char const * p ;
2657 | lBuff[0]='\0';
2658 | #ifndef TINYFD_NOLIB
2659 | if ( ( !tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent() ) )
2660 | && ( !getenv("SSH_CLIENT") || getenv("DISPLAY") ) )
2661 | {
2662 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"windows");return (char const *)1;}
2663 | if (tinyfd_winUtf8)
2664 | {
2665 | p = saveFileDialogWinGui8(lBuff,
2666 | aTitle, aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription);
2667 | }
2668 | else
2669 | {
2670 | p = saveFileDialogWinGuiA(lBuff,
2671 | aTitle, aDefaultPathAndFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription);
2672 | }
2673 | }
2674 | else
2675 | #endif /* TINYFD_NOLIB */
2676 | if ( dialogPresent() )
2677 | {
2678 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
2679 | p = saveFileDialogWinConsole(lBuff,aTitle,aDefaultPathAndFile);
2680 | }
2681 | else
2682 | {
2683 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return (char const *)0;}
2684 | p = tinyfd_inputBox(aTitle, "Save file","");
2685 | }
2686 |
2687 | if ( ! p || ! strlen ( p ) )
2688 | {
2689 | return NULL;
2690 | }
2691 | getPathWithoutFinalSlash ( lString , p ) ;
2692 | if ( strlen ( lString ) && ! dirExists ( lString ) )
2693 | {
2694 | return NULL ;
2695 | }
2696 | getLastName(lString,p);
2697 | if ( ! filenameValid(lString) )
2698 | {
2699 | return NULL;
2700 | }
2701 | return p ;
2702 | }
2703 |
2704 |
2705 | /* in case of multiple files, the separator is | */
2706 | char const * tinyfd_openFileDialog (
2707 | char const * const aTitle , /* NULL or "" */
2708 | char const * const aDefaultPathAndFile , /* NULL or "" */
2709 | int const aNumOfFilterPatterns , /* 0 */
2710 | char const * const * const aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
2711 | char const * const aSingleFilterDescription , /* NULL or "image files" */
2712 | int const aAllowMultipleSelects ) /* 0 or 1 */
2713 | {
2714 | static char lBuff[MAX_MULTIPLE_FILES*MAX_PATH_OR_CMD];
2715 | char const * p ;
2716 | #ifndef TINYFD_NOLIB
2717 | if ( ( !tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent() ) )
2718 | && ( !getenv("SSH_CLIENT") || getenv("DISPLAY") ) )
2719 | {
2720 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"windows");return (char const *)1;}
2721 | if (tinyfd_winUtf8)
2722 | {
2723 | p = openFileDialogWinGui8(lBuff,
2724 | aTitle, aDefaultPathAndFile, aNumOfFilterPatterns,
2725 | aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects);
2726 | }
2727 | else
2728 | {
2729 | p = openFileDialogWinGuiA(lBuff,
2730 | aTitle, aDefaultPathAndFile, aNumOfFilterPatterns,
2731 | aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects);
2732 | }
2733 | }
2734 | else
2735 | #endif /* TINYFD_NOLIB */
2736 | if ( dialogPresent() )
2737 | {
2738 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
2739 | p = openFileDialogWinConsole(lBuff,
2740 | aTitle,aDefaultPathAndFile,aAllowMultipleSelects);
2741 | }
2742 | else
2743 | {
2744 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return (char const *)0;}
2745 | p = tinyfd_inputBox(aTitle, "Open file","");
2746 | }
2747 |
2748 | if ( ! p || ! strlen ( p ) )
2749 | {
2750 | return NULL;
2751 | }
2752 | if ( aAllowMultipleSelects && strchr(p, '|') )
2753 | {
2754 | p = ensureFilesExist( lBuff , p ) ;
2755 | }
2756 | else if ( ! fileExists (p) )
2757 | {
2758 | return NULL ;
2759 | }
2760 | /* printf ( "lBuff3: %s\n" , p ) ; */
2761 | return p ;
2762 | }
2763 |
2764 |
2765 | char const * tinyfd_selectFolderDialog (
2766 | char const * const aTitle , /* NULL or "" */
2767 | char const * const aDefaultPath ) /* NULL or "" */
2768 | {
2769 | static char lBuff [MAX_PATH_OR_CMD] ;
2770 | char const * p ;
2771 | #ifndef TINYFD_NOLIB
2772 | if ( ( !tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent() ) )
2773 | && ( !getenv("SSH_CLIENT") || getenv("DISPLAY") ) )
2774 | {
2775 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"windows");return (char const *)1;}
2776 | if (tinyfd_winUtf8)
2777 | {
2778 | #ifndef TINYFD_NOSELECTFOLDERWIN
2779 | p = selectFolderDialogWinGui8(lBuff, aTitle, aDefaultPath);
2780 | }
2781 | else
2782 | {
2783 | p = selectFolderDialogWinGuiA(lBuff, aTitle, aDefaultPath);
2784 | #endif /*TINYFD_NOSELECTFOLDERWIN*/
2785 | }
2786 | }
2787 | else
2788 | #endif /* TINYFD_NOLIB */
2789 | if ( dialogPresent() )
2790 | {
2791 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
2792 | p = selectFolderDialogWinConsole(lBuff,aTitle,aDefaultPath);
2793 | }
2794 | else
2795 | {
2796 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return (char const *)0;}
2797 | p = tinyfd_inputBox(aTitle, "Select folder","");
2798 | }
2799 |
2800 | if ( ! p || ! strlen ( p ) || ! dirExists ( p ) )
2801 | {
2802 | return NULL ;
2803 | }
2804 | return p ;
2805 | }
2806 |
2807 |
2808 | /* returns the hexcolor as a string "#FF0000" */
2809 | /* aoResultRGB also contains the result */
2810 | /* aDefaultRGB is used only if aDefaultHexRGB is NULL */
2811 | /* aDefaultRGB and aoResultRGB can be the same array */
2812 | char const * tinyfd_colorChooser(
2813 | char const * const aTitle, /* NULL or "" */
2814 | char const * const aDefaultHexRGB, /* NULL or "#FF0000"*/
2815 | unsigned char const aDefaultRGB[3], /* { 0 , 255 , 255 } */
2816 | unsigned char aoResultRGB[3]) /* { 0 , 0 , 0 } */
2817 | {
2818 | char lDefaultHexRGB[8];
2819 | char * lpDefaultHexRGB;
2820 | int i;
2821 | char const * p ;
2822 |
2823 | #ifndef TINYFD_NOLIB
2824 | if ( (!tinyfd_forceConsole || !( GetConsoleWindow() || dialogPresent()) )
2825 | && (!getenv("SSH_CLIENT") || getenv("DISPLAY")) )
2826 | {
2827 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"windows");return (char const *)1;}
2828 | if (tinyfd_winUtf8)
2829 | {
2830 | return colorChooserWinGui8(
2831 | aTitle, aDefaultHexRGB, aDefaultRGB, aoResultRGB);
2832 | }
2833 | else
2834 | {
2835 | return colorChooserWinGuiA(
2836 | aTitle, aDefaultHexRGB, aDefaultRGB, aoResultRGB);
2837 | }
2838 | }
2839 | else
2840 | #endif /* TINYFD_NOLIB */
2841 | if ( aDefaultHexRGB )
2842 | {
2843 | lpDefaultHexRGB = (char *) aDefaultHexRGB ;
2844 | }
2845 | else
2846 | {
2847 | RGB2Hex( aDefaultRGB , lDefaultHexRGB ) ;
2848 | lpDefaultHexRGB = (char *) lDefaultHexRGB ;
2849 | }
2850 | p = tinyfd_inputBox(aTitle,
2851 | "Enter hex rgb color (i.e. #f5ca20)",lpDefaultHexRGB);
2852 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")) return p;
2853 |
2854 | if ( !p || (strlen(p) != 7) || (p[0] != '#') )
2855 | {
2856 | return NULL ;
2857 | }
2858 | for ( i = 1 ; i < 7 ; i ++ )
2859 | {
2860 | if ( ! isxdigit( p[i] ) )
2861 | {
2862 | return NULL ;
2863 | }
2864 | }
2865 | Hex2RGB(p,aoResultRGB);
2866 | return p ;
2867 | }
2868 |
2869 | #else /* unix */
2870 |
2871 | static char gPython2Name[16];
2872 |
2873 | static int isDarwin ( )
2874 | {
2875 | static int lsIsDarwin = -1 ;
2876 | struct utsname lUtsname ;
2877 | if ( lsIsDarwin < 0 )
2878 | {
2879 | lsIsDarwin = !uname(&lUtsname) && !strcmp(lUtsname.sysname,"Darwin") ;
2880 | }
2881 | return lsIsDarwin ;
2882 | }
2883 |
2884 |
2885 | static int dirExists ( char const * const aDirPath )
2886 | {
2887 | DIR * lDir ;
2888 | if ( ! aDirPath || ! strlen ( aDirPath ) )
2889 | return 0 ;
2890 | lDir = opendir ( aDirPath ) ;
2891 | if ( ! lDir )
2892 | {
2893 | return 0 ;
2894 | }
2895 | closedir ( lDir ) ;
2896 | return 1 ;
2897 | }
2898 |
2899 |
2900 | static int detectPresence ( char const * const aExecutable )
2901 | {
2902 | char lBuff [MAX_PATH_OR_CMD] ;
2903 | char lTestedString [MAX_PATH_OR_CMD] = "which " ;
2904 | FILE * lIn ;
2905 |
2906 | strcat ( lTestedString , aExecutable ) ;
2907 | strcat( lTestedString, " 2>/dev/null ");
2908 | lIn = popen ( lTestedString , "r" ) ;
2909 | if ( ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
2910 | && ( ! strchr ( lBuff , ':' ) )
2911 | && ( strncmp(lBuff, "no ", 3) ) )
2912 | { /* present */
2913 | pclose ( lIn ) ;
2914 | if (tinyfd_verbose) printf("detectPresence %s %d\n", aExecutable, 1);
2915 | return 1 ;
2916 | }
2917 | else
2918 | {
2919 | pclose ( lIn ) ;
2920 | if (tinyfd_verbose) printf("detectPresence %s %d\n", aExecutable, 0);
2921 | return 0 ;
2922 | }
2923 | }
2924 |
2925 |
2926 | static char const * getVersion ( char const * const aExecutable ) /*version # must follow :*/
2927 | {
2928 | static char lBuff [MAX_PATH_OR_CMD] ;
2929 | char lTestedString [MAX_PATH_OR_CMD] ;
2930 | FILE * lIn ;
2931 | char * lTmp ;
2932 |
2933 | strcpy ( lTestedString , aExecutable ) ;
2934 | strcat ( lTestedString , " --version" ) ;
2935 |
2936 | lIn = popen ( lTestedString , "r" ) ;
2937 | lTmp = fgets ( lBuff , sizeof ( lBuff ) , lIn ) ;
2938 | pclose ( lIn ) ;
2939 | if ( ! lTmp || !(lTmp = strchr ( lBuff , ':' )) ) return 0 ;
2940 | lTmp ++ ;
2941 | /* printf("lTmp %s\n", lTmp); */
2942 | return lTmp ;
2943 | }
2944 |
2945 |
2946 | static int tryCommand ( char const * const aCommand )
2947 | {
2948 | char lBuff [MAX_PATH_OR_CMD] ;
2949 | FILE * lIn ;
2950 |
2951 | lIn = popen ( aCommand , "r" ) ;
2952 | if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) == NULL )
2953 | { /* present */
2954 | pclose ( lIn ) ;
2955 | return 1 ;
2956 | }
2957 | else
2958 | {
2959 | pclose ( lIn ) ;
2960 | return 0 ;
2961 | }
2962 |
2963 | }
2964 |
2965 |
2966 | static int isTerminalRunning()
2967 | {
2968 | return isatty(1);
2969 | }
2970 |
2971 |
2972 | static char const * dialogNameOnly ( )
2973 | {
2974 | static char lDialogName[128] = "*" ;
2975 | if ( lDialogName[0] == '*' )
2976 | {
2977 | if ( isDarwin() && strcpy(lDialogName , "/opt/local/bin/dialog" )
2978 | && detectPresence ( lDialogName ) )
2979 | {}
2980 | else if ( strcpy(lDialogName , "dialog" )
2981 | && detectPresence ( lDialogName ) )
2982 | {}
2983 | else
2984 | {
2985 | strcpy(lDialogName , "" ) ;
2986 | }
2987 | }
2988 | return lDialogName ;
2989 | }
2990 |
2991 |
2992 | int isDialogVersionBetter09b ( )
2993 | {
2994 | char const * lDialogName ;
2995 | char * lVersion ;
2996 | int lMajor ;
2997 | int lMinor ;
2998 | int lDate ;
2999 | int lResult ;
3000 | char * lMinorP ;
3001 | char * lLetter ;
3002 | char lBuff[128] ;
3003 |
3004 | /*char lTest[128] = " 0.9b-20031126" ;*/
3005 |
3006 | lDialogName = dialogNameOnly ( ) ;
3007 | if ( ! lDialogName || !(lVersion = (char *) getVersion(lDialogName)) ) return 0 ;
3008 | /*lVersion = lTest ;*/
3009 | /*printf("lVersion %s\n", lVersion);*/
3010 | strcpy(lBuff,lVersion);
3011 | lMajor = atoi ( strtok(lVersion," ,.-") ) ;
3012 | /*printf("lMajor %d\n", lMajor);*/
3013 | lMinorP = strtok(0," ,.-abcdefghijklmnopqrstuvxyz");
3014 | lMinor = atoi ( lMinorP ) ;
3015 | /*printf("lMinor %d\n", lMinor );*/
3016 | lDate = atoi ( strtok(0," ,.-") ) ;
3017 | if (lDate<0) lDate = - lDate;
3018 | /*printf("lDate %d\n", lDate);*/
3019 | lLetter = lMinorP + strlen(lMinorP) ;
3020 | strcpy(lVersion,lBuff);
3021 | strtok(lLetter," ,.-");
3022 | /*printf("lLetter %s\n", lLetter);*/
3023 | lResult = (lMajor > 0) || ( ( lMinor == 9 ) && (*lLetter == 'b') && (lDate >= 20031126) );
3024 | /*printf("lResult %d\n", lResult);*/
3025 | return lResult;
3026 | }
3027 |
3028 |
3029 | static int whiptailPresentOnly ( )
3030 | {
3031 | static int lWhiptailPresent = -1 ;
3032 | if ( lWhiptailPresent < 0 )
3033 | {
3034 | lWhiptailPresent = detectPresence ( "whiptail" ) ;
3035 | }
3036 | return lWhiptailPresent ;
3037 | }
3038 |
3039 |
3040 | static char const * terminalName ( )
3041 | {
3042 | static char lTerminalName[128] = "*" ;
3043 | char lShellName[64] = "*" ;
3044 |
3045 | if ( lTerminalName[0] == '*' )
3046 | {
3047 | if ( detectPresence ( "bash" ) )
3048 | {
3049 | strcpy(lShellName , "bash -c " ) ; /*good for basic input*/
3050 | }
3051 | else if ( dialogNameOnly() || whiptailPresentOnly() )
3052 | {
3053 | strcpy(lShellName , "sh -c " ) ; /*good enough for dialog & whiptail*/
3054 | }
3055 | else
3056 | {
3057 | return NULL ;
3058 | }
3059 |
3060 | if ( isDarwin() )
3061 | {
3062 | if ( strcpy(lTerminalName , "/opt/X11/bin/xterm" )
3063 | && detectPresence ( lTerminalName ) )
3064 | {
3065 | strcat(lTerminalName , " -fa 'DejaVu Sans Mono' -fs 10 -title tinyfiledialogs -e " ) ;
3066 | strcat(lTerminalName , lShellName ) ;
3067 | }
3068 | else
3069 | {
3070 | strcpy(lTerminalName , "" ) ;
3071 | }
3072 | }
3073 | else if ( strcpy(lTerminalName,"xterm") /*good (small without parameters)*/
3074 | && detectPresence(lTerminalName) )
3075 | {
3076 | strcat(lTerminalName , " -fa 'DejaVu Sans Mono' -fs 10 -title tinyfiledialogs -e " ) ;
3077 | strcat(lTerminalName , lShellName ) ;
3078 | }
3079 | else if ( strcpy(lTerminalName,"terminator") /*good*/
3080 | && detectPresence(lTerminalName) )
3081 | {
3082 | strcat(lTerminalName , " -x " ) ;
3083 | strcat(lTerminalName , lShellName ) ;
3084 | }
3085 | else if ( strcpy(lTerminalName,"lxterminal") /*good*/
3086 | && detectPresence(lTerminalName) )
3087 | {
3088 | strcat(lTerminalName , " -e " ) ;
3089 | strcat(lTerminalName , lShellName ) ;
3090 | }
3091 | else if ( strcpy(lTerminalName,"konsole") /*good*/
3092 | && detectPresence(lTerminalName) )
3093 | {
3094 | strcat(lTerminalName , " -e " ) ;
3095 | strcat(lTerminalName , lShellName ) ;
3096 | }
3097 | else if ( strcpy(lTerminalName,"kterm") /*good*/
3098 | && detectPresence(lTerminalName) )
3099 | {
3100 | strcat(lTerminalName , " -e " ) ;
3101 | strcat(lTerminalName , lShellName ) ;
3102 | }
3103 | else if ( strcpy(lTerminalName,"xfce4-terminal") /*good*/
3104 | && detectPresence(lTerminalName) )
3105 | {
3106 | strcat(lTerminalName , " -x " ) ;
3107 | strcat(lTerminalName , lShellName ) ;
3108 | }
3109 | else if ( strcpy(lTerminalName,"mate-terminal") /*good*/
3110 | && detectPresence(lTerminalName) )
3111 | {
3112 | strcat(lTerminalName , " -x " ) ;
3113 | strcat(lTerminalName , lShellName ) ;
3114 | }
3115 | else if ( strcpy(lTerminalName,"Eterm") /*good*/
3116 | && detectPresence(lTerminalName) )
3117 | {
3118 | strcat(lTerminalName , " -e " ) ;
3119 | strcat(lTerminalName , lShellName ) ;
3120 | }
3121 | else if ( strcpy(lTerminalName,"evilvte") /*good*/
3122 | && detectPresence(lTerminalName) )
3123 | {
3124 | strcat(lTerminalName , " -e " ) ;
3125 | strcat(lTerminalName , lShellName ) ;
3126 | }
3127 | else if ( strcpy(lTerminalName,"pterm") /*good (only letters)*/
3128 | && detectPresence(lTerminalName) )
3129 | {
3130 | strcat(lTerminalName , " -e " ) ;
3131 | strcat(lTerminalName , lShellName ) ;
3132 | }
3133 | else
3134 | {
3135 | strcpy(lTerminalName , "" ) ;
3136 | }
3137 | /*else if ( strcpy(lTerminalName,"gnome-terminal") //bad (good if version < 3)
3138 | && detectPresence(lTerminalName) )
3139 | {
3140 | strcat(lTerminalName , " --disable-factory -x " ) ;
3141 | strcat(lTerminalName , lShellName ) ;
3142 | }*/
3143 | /* bad: koi rxterm guake tilda vala-terminal qterminal
3144 | aterm Terminal terminology sakura lilyterm weston-terminal
3145 | roxterm termit xvt rxvt mrxvt urxvt */
3146 | }
3147 | if ( strlen(lTerminalName) )
3148 | {
3149 | return lTerminalName ;
3150 | }
3151 | else
3152 | {
3153 | return NULL ;
3154 | }
3155 | }
3156 |
3157 |
3158 | static char const * dialogName ( )
3159 | {
3160 | char const * lDialogName ;
3161 | lDialogName = dialogNameOnly ( ) ;
3162 | if ( strlen(lDialogName) && ( isTerminalRunning() || terminalName() ) )
3163 | {
3164 | return lDialogName ;
3165 | }
3166 | else
3167 | {
3168 | return NULL ;
3169 | }
3170 | }
3171 |
3172 |
3173 | static int whiptailPresent ( )
3174 | {
3175 | int lWhiptailPresent ;
3176 | lWhiptailPresent = whiptailPresentOnly ( ) ;
3177 | if ( lWhiptailPresent && ( isTerminalRunning() || terminalName() ) )
3178 | {
3179 | return lWhiptailPresent ;
3180 | }
3181 | else
3182 | {
3183 | return 0 ;
3184 | }
3185 | }
3186 |
3187 |
3188 |
3189 | static int graphicMode()
3190 | {
3191 | return !( tinyfd_forceConsole && (isTerminalRunning() || terminalName()) )
3192 | && ( getenv("DISPLAY")
3193 | || (isDarwin() && (!getenv("SSH_TTY") || getenv("DISPLAY") ) ) ) ;
3194 | }
3195 |
3196 |
3197 | static int xmessagePresent ( )
3198 | {
3199 | static int lXmessagePresent = -1 ;
3200 | if ( lXmessagePresent < 0 )
3201 | {
3202 | lXmessagePresent = detectPresence("xmessage");/*if not tty,not on osxpath*/
3203 | }
3204 | return lXmessagePresent && graphicMode ( ) ;
3205 | }
3206 |
3207 |
3208 | static int gxmessagePresent ( )
3209 | {
3210 | static int lGxmessagePresent = -1 ;
3211 | if ( lGxmessagePresent < 0 )
3212 | {
3213 | lGxmessagePresent = detectPresence("gxmessage") ;
3214 | }
3215 | return lGxmessagePresent && graphicMode ( ) ;
3216 | }
3217 |
3218 |
3219 | static int gmessagePresent ( )
3220 | {
3221 | static int lGmessagePresent = -1 ;
3222 | if ( lGmessagePresent < 0 )
3223 | {
3224 | lGmessagePresent = detectPresence("gmessage") ;
3225 | }
3226 | return lGmessagePresent && graphicMode ( ) ;
3227 | }
3228 |
3229 |
3230 | static int notifysendPresent ( )
3231 | {
3232 | static int lNotifysendPresent = -1 ;
3233 | if ( lNotifysendPresent < 0 )
3234 | {
3235 | lNotifysendPresent = detectPresence("notify-send") ;
3236 | }
3237 | return lNotifysendPresent && graphicMode ( ) ;
3238 | }
3239 |
3240 |
3241 | static int xdialogPresent ( )
3242 | {
3243 | static int lXdialogPresent = -1 ;
3244 | if ( lXdialogPresent < 0 )
3245 | {
3246 | lXdialogPresent = detectPresence("Xdialog") ;
3247 | }
3248 | return lXdialogPresent && graphicMode ( ) ;
3249 | }
3250 |
3251 |
3252 | static int gdialogPresent ( )
3253 | {
3254 | static int lGdialoglPresent = -1 ;
3255 | if ( lGdialoglPresent < 0 )
3256 | {
3257 | lGdialoglPresent = detectPresence ( "gdialog" ) ;
3258 | }
3259 | return lGdialoglPresent && graphicMode ( ) ;
3260 | }
3261 |
3262 |
3263 | static int osascriptPresent ( )
3264 | {
3265 | static int lOsascriptPresent = -1 ;
3266 | if ( lOsascriptPresent < 0 )
3267 | {
3268 | gWarningDisplayed |= !!getenv("SSH_TTY");
3269 | lOsascriptPresent = detectPresence ( "osascript" ) ;
3270 | }
3271 | return lOsascriptPresent && graphicMode() && !getenv("SSH_TTY") ;
3272 | }
3273 |
3274 |
3275 | static int kdialogPresent ( )
3276 | {
3277 | static int lKdialogPresent = -1 ;
3278 | if ( lKdialogPresent < 0 )
3279 | {
3280 | lKdialogPresent = detectPresence("kdialog") ;
3281 | }
3282 | return lKdialogPresent && graphicMode ( ) ;
3283 | }
3284 |
3285 |
3286 | static int qarmaPresent ( )
3287 | {
3288 | static int lQarmaPresent = -1 ;
3289 | if ( lQarmaPresent < 0 )
3290 | {
3291 | lQarmaPresent = detectPresence("qarma") ;
3292 | }
3293 | return lQarmaPresent && graphicMode ( ) ;
3294 | }
3295 |
3296 |
3297 | static int matedialogPresent ( )
3298 | {
3299 | static int lMatedialogPresent = -1 ;
3300 | if ( lMatedialogPresent < 0 )
3301 | {
3302 | lMatedialogPresent = detectPresence("matedialog") ;
3303 | }
3304 | return lMatedialogPresent && graphicMode ( ) ;
3305 | }
3306 |
3307 |
3308 | static int zenityPresent ( )
3309 | {
3310 | static int lZenityPresent = -1 ;
3311 | if ( lZenityPresent < 0 )
3312 | {
3313 | lZenityPresent = detectPresence("zenity") ;
3314 | }
3315 | return lZenityPresent && graphicMode ( ) ;
3316 | }
3317 |
3318 |
3319 | static int osx9orBetter ( )
3320 | {
3321 | static int lOsx9orBetter = -1 ;
3322 | char lBuff [MAX_PATH_OR_CMD] ;
3323 | FILE * lIn ;
3324 | int V,v;
3325 |
3326 | if ( lOsx9orBetter < 0 )
3327 | {
3328 | lOsx9orBetter = 0 ;
3329 | lIn = popen ( "osascript -e 'set osver to system version of (system info)'" , "r" ) ;
3330 | if ( ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
3331 | && ( 2 == sscanf(lBuff, "%d.%d", &V, &v) ) )
3332 | {
3333 | V = V * 100 + v;
3334 | if ( V >= 1009 )
3335 | {
3336 | lOsx9orBetter = 1 ;
3337 | }
3338 | }
3339 | pclose ( lIn ) ;
3340 | /* printf ("Osx10 = %d, %d = <%s>\n", lOsx9orBetter, V, lBuff) ; */
3341 | }
3342 | return lOsx9orBetter ;
3343 | }
3344 |
3345 |
3346 | static int zenity3Present ( )
3347 | {
3348 | static int lZenity3Present = -1 ;
3349 | char lBuff [MAX_PATH_OR_CMD] ;
3350 | FILE * lIn ;
3351 |
3352 | if ( lZenity3Present < 0 )
3353 | {
3354 | lZenity3Present = 0 ;
3355 | if ( zenityPresent() )
3356 | {
3357 | lIn = popen ( "zenity --version" , "r" ) ;
3358 | if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
3359 | {
3360 | if ( atoi(lBuff) >= 3 )
3361 | {
3362 | lZenity3Present = 3 ;
3363 | }
3364 | else if ( ( atoi(lBuff) == 2 ) && ( atoi(strtok(lBuff,".")+2 ) >= 32 ) )
3365 | {
3366 | lZenity3Present = 2 ;
3367 | }
3368 | }
3369 | pclose ( lIn ) ;
3370 | }
3371 | }
3372 | return lZenity3Present && graphicMode ( ) ;
3373 | }
3374 |
3375 |
3376 | static int tkinter2Present ( )
3377 | {
3378 | static int lTkinter2Present = -1 ;
3379 | char lPythonCommand[256];
3380 | char lPythonParams[256] =
3381 | "-c \"try:\n\timport Tkinter;\nexcept:\n\tprint(0);\"";
3382 | int i;
3383 |
3384 | if ( lTkinter2Present < 0 )
3385 | {
3386 | lTkinter2Present = 0 ;
3387 | strcpy(gPython2Name , "python" ) ;
3388 | sprintf ( lPythonCommand , "%s %s" , gPython2Name , lPythonParams ) ;
3389 | if ( ! detectPresence(gPython2Name)
3390 | || ! (lTkinter2Present = tryCommand(lPythonCommand)) )
3391 | {
3392 | strcpy(gPython2Name , "python2" ) ;
3393 | if ( detectPresence(gPython2Name) )
3394 | {
3395 | sprintf ( lPythonCommand , "%s %s" , gPython2Name , lPythonParams ) ;
3396 | lTkinter2Present = tryCommand(lPythonCommand);
3397 | }
3398 | else
3399 | {
3400 | for ( i = 9 ; i >= 0 ; i -- )
3401 | {
3402 | sprintf ( gPython2Name , "python2.%d" , i ) ;
3403 | if ( detectPresence(gPython2Name) )
3404 | {
3405 | sprintf ( lPythonCommand , "%s %s" , gPython2Name , lPythonParams ) ;
3406 | lTkinter2Present = tryCommand(lPythonCommand);
3407 | break ;
3408 | }
3409 | }
3410 | }
3411 | }
3412 | }
3413 | /* printf ("lTkinter2Present %d\n", lTkinter2Present) ; */
3414 | /* printf ("gPython2Name %s\n", gPython2Name) ; */
3415 | return lTkinter2Present && graphicMode() && !(isDarwin() && getenv("SSH_TTY") );
3416 | }
3417 |
3418 |
3419 | int tinyfd_messageBox (
3420 | char const * const aTitle , /* NULL or "" */
3421 | char const * const aMessage , /* NULL or "" may contain \n and \t */
3422 | char const * const aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
3423 | char const * const aIconType , /* "info" "warning" "error" "question" */
3424 | int const aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
3425 | {
3426 | char lBuff [MAX_PATH_OR_CMD] ;
3427 | char * lDialogString = NULL ;
3428 | char * lpDialogString;
3429 | FILE * lIn ;
3430 | int lWasGraphicDialog = 0 ;
3431 | int lWasXterm = 0 ;
3432 | int lResult ;
3433 | char lChar ;
3434 | struct termios infoOri;
3435 | struct termios info;
3436 | int lTitleLen ;
3437 | int lMessageLen ;
3438 |
3439 | lBuff[0]='\0';
3440 |
3441 | lTitleLen = aTitle ? strlen(aTitle) : 0 ;
3442 | lMessageLen = aMessage ? strlen(aMessage) : 0 ;
3443 | if ( !aTitle || strcmp(aTitle,"tinyfd_query") )
3444 | {
3445 | lDialogString = (char *) malloc( MAX_PATH_OR_CMD + lTitleLen + lMessageLen );
3446 | }
3447 |
3448 | if ( osascriptPresent ( ) )
3449 | {
3450 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"applescript");return 1;}
3451 |
3452 | strcpy ( lDialogString , "osascript ");
3453 | if ( ! osx9orBetter() ) strcat ( lDialogString , " -e 'tell application \"System Events\"' -e 'Activate'");
3454 | strcat ( lDialogString , " -e 'try' -e 'set {vButton} to {button returned} of ( display dialog \"") ;
3455 | if ( aMessage && strlen(aMessage) )
3456 | {
3457 | strcat(lDialogString, aMessage) ;
3458 | }
3459 | strcat(lDialogString, "\" ") ;
3460 | if ( aTitle && strlen(aTitle) )
3461 | {
3462 | strcat(lDialogString, "with title \"") ;
3463 | strcat(lDialogString, aTitle) ;
3464 | strcat(lDialogString, "\" ") ;
3465 | }
3466 | strcat(lDialogString, "with icon ") ;
3467 | if ( aIconType && ! strcmp( "error" , aIconType ) )
3468 | {
3469 | strcat(lDialogString, "stop " ) ;
3470 | }
3471 | else if ( aIconType && ! strcmp( "warning" , aIconType ) )
3472 | {
3473 | strcat(lDialogString, "caution " ) ;
3474 | }
3475 | else /* question or info */
3476 | {
3477 | strcat(lDialogString, "note " ) ;
3478 | }
3479 | if ( aDialogType && ! strcmp( "okcancel" , aDialogType ) )
3480 | {
3481 | if ( ! aDefaultButton )
3482 | {
3483 | strcat ( lDialogString ,"default button \"Cancel\" " ) ;
3484 | }
3485 | }
3486 | else if ( aDialogType && ! strcmp( "yesno" , aDialogType ) )
3487 | {
3488 | strcat ( lDialogString ,"buttons {\"No\", \"Yes\"} " ) ;
3489 | if (aDefaultButton)
3490 | {
3491 | strcat ( lDialogString ,"default button \"Yes\" " ) ;
3492 | }
3493 | else
3494 | {
3495 | strcat ( lDialogString ,"default button \"No\" " ) ;
3496 | }
3497 | strcat ( lDialogString ,"cancel button \"No\"" ) ;
3498 | }
3499 | else if ( aDialogType && ! strcmp( "yesnocancel" , aDialogType ) )
3500 | {
3501 | strcat ( lDialogString ,"buttons {\"No\", \"Yes\", \"Cancel\"} " ) ;
3502 | switch (aDefaultButton)
3503 | {
3504 | case 1: strcat ( lDialogString ,"default button \"Yes\" " ) ; break;
3505 | case 2: strcat ( lDialogString ,"default button \"No\" " ) ; break;
3506 | case 0: strcat ( lDialogString ,"default button \"Cancel\" " ) ; break;
3507 | }
3508 | strcat ( lDialogString ,"cancel button \"Cancel\"" ) ;
3509 | }
3510 | else
3511 | {
3512 | strcat ( lDialogString ,"buttons {\"OK\"} " ) ;
3513 | strcat ( lDialogString ,"default button \"OK\" " ) ;
3514 | }
3515 | strcat ( lDialogString, ")' ") ;
3516 |
3517 | strcat ( lDialogString,
3518 | "-e 'if vButton is \"Yes\" then' -e 'return 1' -e 'else if vButton is \"No\" then' -e 'return 2' -e 'else' -e 'return 0' -e 'end if' " );
3519 |
3520 | strcat ( lDialogString, "-e 'on error number -128' " ) ;
3521 | strcat ( lDialogString, "-e '0' " );
3522 |
3523 | strcat ( lDialogString, "-e 'end try'") ;
3524 | if ( ! osx9orBetter() ) strcat ( lDialogString, " -e 'end tell'") ;
3525 | }
3526 | else if ( zenityPresent() || matedialogPresent() || qarmaPresent() )
3527 | {
3528 | if ( zenityPresent() )
3529 | {
3530 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity");return 1;}
3531 | strcpy ( lDialogString , "szAnswer=$(zenity --" ) ;
3532 | }
3533 | else if ( matedialogPresent() )
3534 | {
3535 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"matedialog");return 1;}
3536 | strcpy ( lDialogString , "szAnswer=$(matedialog --" ) ;
3537 | }
3538 | else
3539 | {
3540 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"qarma");return 1;}
3541 | strcpy ( lDialogString , "szAnswer=$(qarma --" ) ;
3542 | }
3543 |
3544 | if ( aDialogType && ! strcmp( "okcancel" , aDialogType ) )
3545 | {
3546 | strcat ( lDialogString ,
3547 | "question --ok-label=Ok --cancel-label=Cancel" ) ;
3548 | }
3549 | else if ( aDialogType && ! strcmp( "yesno" , aDialogType ) )
3550 | {
3551 | strcat ( lDialogString , "question" ) ;
3552 | }
3553 | else if ( aDialogType && ! strcmp( "yesnocancel" , aDialogType ) )
3554 | {
3555 | strcat ( lDialogString , "list --column \"\" --hide-header \"Yes\" \"No\"" ) ;
3556 | }
3557 | else if ( aIconType && ! strcmp( "error" , aIconType ) )
3558 | {
3559 | strcat ( lDialogString , "error" ) ;
3560 | }
3561 | else if ( aIconType && ! strcmp( "warning" , aIconType ) )
3562 | {
3563 | strcat ( lDialogString , "warning" ) ;
3564 | }
3565 | else
3566 | {
3567 | strcat ( lDialogString , "info" ) ;
3568 | }
3569 | if ( aTitle && strlen(aTitle) )
3570 | {
3571 | strcat(lDialogString, " --title=\"") ;
3572 | strcat(lDialogString, aTitle) ;
3573 | strcat(lDialogString, "\"") ;
3574 | }
3575 | if ( aMessage && strlen(aMessage) )
3576 | {
3577 | strcat(lDialogString, " --text=\"") ;
3578 | strcat(lDialogString, aMessage) ;
3579 | strcat(lDialogString, "\"") ;
3580 | }
3581 | if ( zenity3Present ( ) >= 3 )
3582 | {
3583 | strcat ( lDialogString , " --icon-name=dialog-" ) ;
3584 | if ( aIconType && (! strcmp( "question" , aIconType )
3585 | || ! strcmp( "error" , aIconType )
3586 | || ! strcmp( "warning" , aIconType ) ) )
3587 | {
3588 | strcat ( lDialogString , aIconType ) ;
3589 | }
3590 | else
3591 | {
3592 | strcat ( lDialogString , "information" ) ;
3593 | }
3594 | }
3595 |
3596 | if ( ! strcmp( "yesnocancel" , aDialogType ) )
3597 | {
3598 | strcat ( lDialogString ,
3599 | ");if [ $? = 1 ];then echo 0;elif [ $szAnswer = \"No\" ];then echo 2;else echo 1;fi");
3600 | }
3601 | else
3602 | {
3603 | strcat ( lDialogString , ");if [ $? = 0 ];then echo 1;else echo 0;fi");
3604 | }
3605 | }
3606 | else if ( kdialogPresent() )
3607 | {
3608 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"kdialog");return 1;}
3609 |
3610 | strcpy ( lDialogString , "kdialog --" ) ;
3611 | if ( aDialogType && ( ! strcmp( "okcancel" , aDialogType )
3612 | || ! strcmp( "yesno" , aDialogType ) || ! strcmp( "yesnocancel" , aDialogType ) ) )
3613 | {
3614 | if ( aIconType && ( ! strcmp( "warning" , aIconType )
3615 | || ! strcmp( "error" , aIconType ) ) )
3616 | {
3617 | strcat ( lDialogString , "warning" ) ;
3618 | }
3619 | if ( ! strcmp( "yesnocancel" , aDialogType ) )
3620 | {
3621 | strcat ( lDialogString , "yesnocancel" ) ;
3622 | }
3623 | else
3624 | {
3625 | strcat ( lDialogString , "yesno" ) ;
3626 | }
3627 | }
3628 | else if ( aIconType && ! strcmp( "error" , aIconType ) )
3629 | {
3630 | strcat ( lDialogString , "error" ) ;
3631 | }
3632 | else if ( aIconType && ! strcmp( "warning" , aIconType ) )
3633 | {
3634 | strcat ( lDialogString , "sorry" ) ;
3635 | }
3636 | else
3637 | {
3638 | strcat ( lDialogString , "msgbox" ) ;
3639 | }
3640 | strcat ( lDialogString , " \"" ) ;
3641 | if ( aMessage )
3642 | {
3643 | strcat ( lDialogString , aMessage ) ;
3644 | }
3645 | strcat ( lDialogString , "\"" ) ;
3646 | if ( aDialogType && ! strcmp( "okcancel" , aDialogType ) )
3647 | {
3648 | strcat ( lDialogString ,
3649 | " --yes-label Ok --no-label Cancel" ) ;
3650 | }
3651 | if ( aTitle && strlen(aTitle) )
3652 | {
3653 | strcat(lDialogString, " --title \"") ;
3654 | strcat(lDialogString, aTitle) ;
3655 | strcat(lDialogString, "\"") ;
3656 | }
3657 |
3658 | if ( ! strcmp( "yesnocancel" , aDialogType ) )
3659 | {
3660 | strcat ( lDialogString , "; x=$? ;if [ $x = 0 ] ;then echo 1;elif [ $x = 1 ] ;then echo 2;else echo 0;fi");
3661 | }
3662 | else
3663 | {
3664 | strcat ( lDialogString , ";if [ $? = 0 ];then echo 1;else echo 0;fi");
3665 | }
3666 | }
3667 | else if ( !gxmessagePresent() && !gmessagePresent() && !gdialogPresent() && !xdialogPresent() && tkinter2Present ( ) )
3668 | {
3669 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"tkinter");return 1;}
3670 |
3671 | strcpy ( lDialogString , gPython2Name ) ;
3672 | if ( ! isTerminalRunning ( ) && isDarwin ( ) )
3673 | {
3674 | strcat ( lDialogString , " -i" ) ; /* for osx without console */
3675 | }
3676 |
3677 | strcat ( lDialogString ,
3678 | " -c \"import Tkinter,tkMessageBox;root=Tkinter.Tk();root.withdraw();");
3679 |
3680 | if ( isDarwin ( ) )
3681 | {
3682 | strcat ( lDialogString ,
3683 | "import os;os.system('''/usr/bin/osascript -e 'tell app \\\"Finder\\\" to set \
3684 | frontmost of process \\\"Python\\\" to true' ''');");
3685 | }
3686 |
3687 | strcat ( lDialogString ,"res=tkMessageBox." ) ;
3688 | if ( aDialogType && ! strcmp( "okcancel" , aDialogType ) )
3689 | {
3690 | strcat ( lDialogString , "askokcancel(" ) ;
3691 | if ( aDefaultButton )
3692 | {
3693 | strcat ( lDialogString , "default=tkMessageBox.OK," ) ;
3694 | }
3695 | else
3696 | {
3697 | strcat ( lDialogString , "default=tkMessageBox.CANCEL," ) ;
3698 | }
3699 | }
3700 | else if ( aDialogType && ! strcmp( "yesno" , aDialogType ) )
3701 | {
3702 | strcat ( lDialogString , "askyesno(" ) ;
3703 | if ( aDefaultButton )
3704 | {
3705 | strcat ( lDialogString , "default=tkMessageBox.YES," ) ;
3706 | }
3707 | else
3708 | {
3709 | strcat ( lDialogString , "default=tkMessageBox.NO," ) ;
3710 | }
3711 | }
3712 | else if ( aDialogType && ! strcmp( "yesnocancel" , aDialogType ) )
3713 | {
3714 | strcat ( lDialogString , "askyesnocancel(" ) ;
3715 | switch ( aDefaultButton )
3716 | {
3717 | case 1: strcat ( lDialogString , "default=tkMessageBox.YES," ); break;
3718 | case 2: strcat ( lDialogString , "default=tkMessageBox.NO," ); break;
3719 | case 0: strcat ( lDialogString , "default=tkMessageBox.CANCEL," ); break;
3720 | }
3721 | }
3722 | else
3723 | {
3724 | strcat ( lDialogString , "showinfo(" ) ;
3725 | }
3726 |
3727 | strcat ( lDialogString , "icon='" ) ;
3728 | if ( aIconType && (! strcmp( "question" , aIconType )
3729 | || ! strcmp( "error" , aIconType )
3730 | || ! strcmp( "warning" , aIconType ) ) )
3731 | {
3732 | strcat ( lDialogString , aIconType ) ;
3733 | }
3734 | else
3735 | {
3736 | strcat ( lDialogString , "info" ) ;
3737 | }
3738 |
3739 | strcat(lDialogString, "',") ;
3740 | if ( aTitle && strlen(aTitle) )
3741 | {
3742 | strcat(lDialogString, "title='") ;
3743 | strcat(lDialogString, aTitle) ;
3744 | strcat(lDialogString, "',") ;
3745 | }
3746 | if ( aMessage && strlen(aMessage) )
3747 | {
3748 | strcat(lDialogString, "message='") ;
3749 | lpDialogString = lDialogString + strlen(lDialogString);
3750 | replaceSubStr ( aMessage , "\n" , "\\n" , lpDialogString ) ;
3751 | strcat(lDialogString, "'") ;
3752 | }
3753 |
3754 | if ( aDialogType && ! strcmp( "yesnocancel" , aDialogType ) )
3755 | {
3756 | strcat(lDialogString, ");\n\
3757 | if res is None :\n\tprint 0\n\
3758 | elif res is False :\n\tprint 2\n\
3759 | else :\n\tprint 1\n\"" ) ;
3760 | }
3761 | else
3762 | {
3763 | strcat(lDialogString, ");\n\
3764 | if res is False :\n\tprint 0\n\
3765 | else :\n\tprint 1\n\"" ) ;
3766 | }
3767 | }
3768 | else if ( gxmessagePresent() || gmessagePresent() || (!gdialogPresent() && !xdialogPresent() && xmessagePresent()) )
3769 | {
3770 | if ( gxmessagePresent() )
3771 | {
3772 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"gxmessage");return 1;}
3773 | strcpy ( lDialogString , "gxmessage");
3774 | }
3775 | else if ( gmessagePresent() )
3776 | {
3777 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"gmessage");return 1;}
3778 | strcpy ( lDialogString , "gmessage");
3779 | }
3780 | else
3781 | {
3782 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"xmessage");return 1;}
3783 | strcpy ( lDialogString , "xmessage");
3784 | }
3785 |
3786 | if ( aDialogType && ! strcmp("okcancel" , aDialogType) )
3787 | {
3788 | strcat ( lDialogString , " -buttons Ok:1,Cancel:0");
3789 | switch ( aDefaultButton )
3790 | {
3791 | case 1: strcat ( lDialogString , " -default Ok"); break;
3792 | case 0: strcat ( lDialogString , " -default Cancel"); break;
3793 | }
3794 | }
3795 | else if ( aDialogType && ! strcmp("yesno" , aDialogType) )
3796 | {
3797 | strcat ( lDialogString , " -buttons Yes:1,No:0");
3798 | switch ( aDefaultButton )
3799 | {
3800 | case 1: strcat ( lDialogString , " -default Yes"); break;
3801 | case 0: strcat ( lDialogString , " -default No"); break;
3802 | }
3803 | }
3804 | else if ( aDialogType && ! strcmp("yesnocancel" , aDialogType) )
3805 | {
3806 | strcat ( lDialogString , " -buttons Yes:1,No:2,Cancel:0");
3807 | switch ( aDefaultButton )
3808 | {
3809 | case 1: strcat ( lDialogString , " -default Yes"); break;
3810 | case 2: strcat ( lDialogString , " -default No"); break;
3811 | case 0: strcat ( lDialogString , " -default Cancel"); break;
3812 | }
3813 | }
3814 | else
3815 | {
3816 | strcat ( lDialogString , " -buttons Ok:1");
3817 | strcat ( lDialogString , " -default Ok");
3818 | }
3819 |
3820 | strcat ( lDialogString , " -center \"");
3821 | if ( aMessage && strlen(aMessage) )
3822 | {
3823 | strcat ( lDialogString , aMessage ) ;
3824 | }
3825 | strcat(lDialogString, "\"" ) ;
3826 | if ( aTitle && strlen(aTitle) )
3827 | {
3828 | strcat ( lDialogString , " -title \"");
3829 | strcat ( lDialogString , aTitle ) ;
3830 | strcat ( lDialogString, "\"" ) ;
3831 | }
3832 | strcat ( lDialogString , " ; echo $? ");
3833 | }
3834 | else if ( xdialogPresent() || gdialogPresent() || dialogName() || whiptailPresent() )
3835 | {
3836 | if ( gdialogPresent ( ) )
3837 | {
3838 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"gdialog");return 1;}
3839 | lWasGraphicDialog = 1 ;
3840 | strcpy ( lDialogString , "(gdialog " ) ;
3841 | }
3842 | else if ( xdialogPresent ( ) )
3843 | {
3844 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"xdialog");return 1;}
3845 | lWasGraphicDialog = 1 ;
3846 | strcpy ( lDialogString , "(Xdialog " ) ;
3847 | }
3848 | else if ( dialogName ( ) )
3849 | {
3850 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return 0;}
3851 | if ( isTerminalRunning ( ) )
3852 | {
3853 | strcpy ( lDialogString , "(dialog " ) ;
3854 | }
3855 | else
3856 | {
3857 | lWasXterm = 1 ;
3858 | strcpy ( lDialogString , terminalName() ) ;
3859 | strcat ( lDialogString , "'(" ) ;
3860 | strcat ( lDialogString , dialogName() ) ;
3861 | strcat ( lDialogString , " " ) ;
3862 | }
3863 | }
3864 | else if ( isTerminalRunning ( ) )
3865 | {
3866 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"whiptail");return 0;}
3867 | strcpy ( lDialogString , "(whiptail " ) ;
3868 | }
3869 | else
3870 | {
3871 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"whiptail");return 0;}
3872 | lWasXterm = 1 ;
3873 | strcpy ( lDialogString , terminalName() ) ;
3874 | strcat ( lDialogString , "'(whiptail " ) ;
3875 | }
3876 |
3877 | if ( aTitle && strlen(aTitle) )
3878 | {
3879 | strcat(lDialogString, "--title \"") ;
3880 | strcat(lDialogString, aTitle) ;
3881 | strcat(lDialogString, "\" ") ;
3882 | }
3883 |
3884 | if ( !xdialogPresent() && !gdialogPresent() )
3885 | {
3886 | if ( aDialogType && ( !strcmp( "okcancel" , aDialogType ) || !strcmp( "yesno" , aDialogType )
3887 | || !strcmp( "yesnocancel" , aDialogType ) ) )
3888 | {
3889 | strcat(lDialogString, "--backtitle \"") ;
3890 | strcat(lDialogString, "tab: move focus") ;
3891 | strcat(lDialogString, "\" ") ;
3892 | }
3893 | }
3894 |
3895 | if ( aDialogType && ! strcmp( "okcancel" , aDialogType ) )
3896 | {
3897 | if ( ! aDefaultButton )
3898 | {
3899 | strcat ( lDialogString , "--defaultno " ) ;
3900 | }
3901 | strcat ( lDialogString ,
3902 | "--yes-label \"Ok\" --no-label \"Cancel\" --yesno " ) ;
3903 | }
3904 | else if ( aDialogType && ! strcmp( "yesno" , aDialogType ) )
3905 | {
3906 | if ( ! aDefaultButton )
3907 | {
3908 | strcat ( lDialogString , "--defaultno " ) ;
3909 | }
3910 | strcat ( lDialogString , "--yesno " ) ;
3911 | }
3912 | else if (aDialogType && !strcmp("yesnocancel", aDialogType))
3913 | {
3914 | if (!aDefaultButton)
3915 | {
3916 | strcat(lDialogString, "--defaultno ");
3917 | }
3918 | strcat(lDialogString, "--menu ");
3919 | }
3920 | else
3921 | {
3922 | strcat ( lDialogString , "--msgbox " ) ;
3923 |
3924 | }
3925 | strcat ( lDialogString , "\"" ) ;
3926 | if ( aMessage && strlen(aMessage) )
3927 | {
3928 | strcat(lDialogString, aMessage) ;
3929 | }
3930 | strcat(lDialogString, "\" ");
3931 |
3932 | if ( lWasGraphicDialog )
3933 | {
3934 | if (aDialogType && !strcmp("yesnocancel", aDialogType))
3935 | {
3936 | strcat(lDialogString,"0 60 0 Yes \"\" No \"\") 2>/tmp/tinyfd.txt;\
3937 | if [ $? = 0 ];then tinyfdBool=1;else tinyfdBool=0;fi;\
3938 | tinyfdRes=$(cat /tmp/tinyfd.txt);echo $tinyfdBool$tinyfdRes") ;
3939 | }
3940 | else
3941 | {
3942 | strcat(lDialogString,
3943 | "10 60 ) 2>&1;if [ $? = 0 ];then echo 1;else echo 0;fi");
3944 | }
3945 | }
3946 | else
3947 | {
3948 | if (aDialogType && !strcmp("yesnocancel", aDialogType))
3949 | {
3950 | strcat(lDialogString,"0 60 0 Yes \"\" No \"\" >/dev/tty ) 2>/tmp/tinyfd.txt;\
3951 | if [ $? = 0 ];then tinyfdBool=1;else tinyfdBool=0;fi;\
3952 | tinyfdRes=$(cat /tmp/tinyfd.txt);echo $tinyfdBool$tinyfdRes") ;
3953 |
3954 | if ( lWasXterm )
3955 | {
3956 | strcat(lDialogString," >/tmp/tinyfd0.txt';cat /tmp/tinyfd0.txt");
3957 | }
3958 | else
3959 | {
3960 | strcat(lDialogString, "; clear >/dev/tty") ;
3961 | }
3962 | }
3963 | else
3964 | {
3965 | strcat(lDialogString, "10 60 >/dev/tty) 2>&1;if [ $? = 0 ];");
3966 | if ( lWasXterm )
3967 | {
3968 | strcat ( lDialogString ,
3969 | "then\n\techo 1\nelse\n\techo 0\nfi >/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt");
3970 | }
3971 | else
3972 | {
3973 | strcat(lDialogString,
3974 | "then echo 1;else echo 0;fi;clear >/dev/tty");
3975 | }
3976 | }
3977 | }
3978 | }
3979 | else if ( ! isTerminalRunning ( ) && terminalName() )
3980 | {
3981 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return 0;}
3982 | strcpy ( lDialogString , terminalName() ) ;
3983 | strcat ( lDialogString , "'" ) ;
3984 | if ( !gWarningDisplayed && !tinyfd_forceConsole)
3985 | {
3986 | gWarningDisplayed = 1 ;
3987 | strcat ( lDialogString , "echo \"" ) ;
3988 | strcat ( lDialogString, gTitle) ;
3989 | strcat ( lDialogString , "\";" ) ;
3990 | strcat ( lDialogString , "echo \"" ) ;
3991 | strcat ( lDialogString, gMessageUnix) ;
3992 | strcat ( lDialogString , "\";echo;echo;" ) ;
3993 | }
3994 | if ( aTitle && strlen(aTitle) )
3995 | {
3996 | strcat ( lDialogString , "echo \"" ) ;
3997 | strcat ( lDialogString, aTitle) ;
3998 | strcat ( lDialogString , "\";echo;" ) ;
3999 | }
4000 | if ( aMessage && strlen(aMessage) )
4001 | {
4002 | strcat ( lDialogString , "echo \"" ) ;
4003 | strcat ( lDialogString, aMessage) ;
4004 | strcat ( lDialogString , "\"; " ) ;
4005 | }
4006 | if ( aDialogType && !strcmp("yesno",aDialogType) )
4007 | {
4008 | strcat ( lDialogString , "echo -n \"y/n: \"; " ) ;
4009 | strcat ( lDialogString , "stty sane -echo;" ) ;
4010 | strcat ( lDialogString ,
4011 | "answer=$( while ! head -c 1 | grep -i [ny];do true ;done);");
4012 | strcat ( lDialogString ,
4013 | "if echo \"$answer\" | grep -iq \"^y\";then\n");
4014 | strcat ( lDialogString , "\techo 1\nelse\n\techo 0\nfi" ) ;
4015 | }
4016 | else if ( aDialogType && !strcmp("okcancel",aDialogType) )
4017 | {
4018 | strcat ( lDialogString , "echo -n \"[O]kay/[C]ancel: \"; " ) ;
4019 | strcat ( lDialogString , "stty sane -echo;" ) ;
4020 | strcat ( lDialogString ,
4021 | "answer=$( while ! head -c 1 | grep -i [oc];do true ;done);");
4022 | strcat ( lDialogString ,
4023 | "if echo \"$answer\" | grep -iq \"^o\";then\n");
4024 | strcat ( lDialogString , "\techo 1\nelse\n\techo 0\nfi" ) ;
4025 | }
4026 | else if ( aDialogType && !strcmp("yesnocancel",aDialogType) )
4027 | {
4028 | strcat ( lDialogString , "echo -n \"[Y]es/[N]o/[C]ancel: \"; " ) ;
4029 | strcat ( lDialogString , "stty sane -echo;" ) ;
4030 | strcat ( lDialogString ,
4031 | "answer=$( while ! head -c 1 | grep -i [nyc];do true ;done);");
4032 | strcat ( lDialogString ,
4033 | "if echo \"$answer\" | grep -iq \"^y\";then\n\techo 1\n");
4034 | strcat ( lDialogString , "elif echo \"$answer\" | grep -iq \"^n\";then\n\techo 2\n" ) ;
4035 | strcat ( lDialogString , "else\n\techo 0\nfi" ) ;
4036 | }
4037 | else
4038 | {
4039 | strcat(lDialogString , "echo -n \"press enter to continue \"; ");
4040 | strcat ( lDialogString , "stty sane -echo;" ) ;
4041 | strcat ( lDialogString ,
4042 | "answer=$( while ! head -c 1;do true ;done);echo 1");
4043 | }
4044 | strcat ( lDialogString ,
4045 | " >/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt");
4046 | }
4047 | else if ( !isTerminalRunning() && notifysendPresent() && !strcmp("ok" , aDialogType) )
4048 | {
4049 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"notify");return 1;}
4050 |
4051 | strcpy ( lDialogString , "notify-send \"" ) ;
4052 | if ( aTitle && strlen(aTitle) )
4053 | {
4054 | strcat(lDialogString, aTitle) ;
4055 | strcat ( lDialogString , " | " ) ;
4056 | }
4057 | if ( aMessage && strlen(aMessage) )
4058 | {
4059 | strcat(lDialogString, aMessage) ;
4060 | }
4061 | strcat ( lDialogString , "\"" ) ;
4062 | }
4063 | else
4064 | {
4065 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return 0;}
4066 | if ( !gWarningDisplayed && !tinyfd_forceConsole)
4067 | {
4068 | gWarningDisplayed = 1 ;
4069 | printf ("\n\n%s\n", gTitle);
4070 | printf ("%s\n\n", gMessageUnix);
4071 | }
4072 | if ( aTitle && strlen(aTitle) )
4073 | {
4074 | printf ("\n%s\n", aTitle);
4075 | }
4076 |
4077 | tcgetattr(0, &infoOri);
4078 | tcgetattr(0, &info);
4079 | info.c_lflag &= ~ICANON;
4080 | info.c_cc[VMIN] = 1;
4081 | info.c_cc[VTIME] = 0;
4082 | tcsetattr(0, TCSANOW, &info);
4083 | if ( aDialogType && !strcmp("yesno",aDialogType) )
4084 | {
4085 | do
4086 | {
4087 | if ( aMessage && strlen(aMessage) )
4088 | {
4089 | printf("\n%s\n",aMessage);
4090 | }
4091 | printf("y/n: "); fflush(stdout);
4092 | lChar = tolower ( getchar() ) ;
4093 | printf("\n\n");
4094 | }
4095 | while ( lChar != 'y' && lChar != 'n' );
4096 | lResult = lChar == 'y' ? 1 : 0 ;
4097 | }
4098 | else if ( aDialogType && !strcmp("okcancel",aDialogType) )
4099 | {
4100 | do
4101 | {
4102 | if ( aMessage && strlen(aMessage) )
4103 | {
4104 | printf("\n%s\n",aMessage);
4105 | }
4106 | printf("[O]kay/[C]ancel: "); fflush(stdout);
4107 | lChar = tolower ( getchar() ) ;
4108 | printf("\n\n");
4109 | }
4110 | while ( lChar != 'o' && lChar != 'c' );
4111 | lResult = lChar == 'o' ? 1 : 0 ;
4112 | }
4113 | else if ( aDialogType && !strcmp("yesnocancel",aDialogType) )
4114 | {
4115 | do
4116 | {
4117 | if ( aMessage && strlen(aMessage) )
4118 | {
4119 | printf("\n%s\n",aMessage);
4120 | }
4121 | printf("[Y]es/[N]o/[C]ancel: "); fflush(stdout);
4122 | lChar = tolower ( getchar() ) ;
4123 | printf("\n\n");
4124 | }
4125 | while ( lChar != 'y' && lChar != 'n' && lChar != 'c' );
4126 | lResult = (lChar == 'y') ? 1 : (lChar == 'n') ? 2 : 0 ;
4127 | }
4128 | else
4129 | {
4130 | if ( aMessage && strlen(aMessage) )
4131 | {
4132 | printf("\n%s\n\n",aMessage);
4133 | }
4134 | printf("press enter to continue "); fflush(stdout);
4135 | getchar() ;
4136 | printf("\n\n");
4137 | lResult = 1 ;
4138 | }
4139 | tcsetattr(0, TCSANOW, &infoOri);
4140 | free(lDialogString);
4141 | return lResult ;
4142 | }
4143 |
4144 | if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;
4145 |
4146 | if ( ! ( lIn = popen ( lDialogString , "r" ) ) )
4147 | {
4148 | free(lDialogString);
4149 | return 0 ;
4150 | }
4151 | while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
4152 | {}
4153 |
4154 | pclose ( lIn ) ;
4155 |
4156 | /* printf ( "lBuff: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
4157 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
4158 | {
4159 | lBuff[strlen ( lBuff ) -1] = '\0' ;
4160 | }
4161 | /* printf ( "lBuff1: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
4162 |
4163 | if (aDialogType && !strcmp("yesnocancel", aDialogType))
4164 | {
4165 | if ( lBuff[0]=='1' )
4166 | {
4167 | if ( !strcmp ( lBuff+1 , "Yes" )) strcpy(lBuff,"1");
4168 | else if ( !strcmp ( lBuff+1 , "No" )) strcpy(lBuff,"2");
4169 | }
4170 | }
4171 | /* printf ( "lBuff2: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
4172 |
4173 | lResult = !strcmp ( lBuff , "2" ) ? 2 : !strcmp ( lBuff , "1" ) ? 1 : 0;
4174 |
4175 | /* printf ( "lResult: %d\n" , lResult ) ; */
4176 | free(lDialogString);
4177 | return lResult ;
4178 | }
4179 |
4180 |
4181 | /* returns NULL on cancel */
4182 | char const * tinyfd_inputBox(
4183 | char const * const aTitle , /* NULL or "" */
4184 | char const * const aMessage , /* NULL or "" may NOT contain \n nor \t */
4185 | char const * const aDefaultInput ) /* "" , if NULL it's a passwordBox */
4186 | {
4187 | static char lBuff[MAX_PATH_OR_CMD];
4188 | char * lDialogString = NULL;
4189 | char * lpDialogString;
4190 | FILE * lIn ;
4191 | int lResult ;
4192 | int lWasGdialog = 0 ;
4193 | int lWasGraphicDialog = 0 ;
4194 | int lWasXterm = 0 ;
4195 | int lWasBasicXterm = 0 ;
4196 | struct termios oldt ;
4197 | struct termios newt ;
4198 | char * lEOF;
4199 | int lTitleLen ;
4200 | int lMessageLen ;
4201 |
4202 | lBuff[0]='\0';
4203 |
4204 | lTitleLen = aTitle ? strlen(aTitle) : 0 ;
4205 | lMessageLen = aMessage ? strlen(aMessage) : 0 ;
4206 | if ( !aTitle || strcmp(aTitle,"tinyfd_query") )
4207 | {
4208 | lDialogString = (char *) malloc( MAX_PATH_OR_CMD + lTitleLen + lMessageLen );
4209 | }
4210 |
4211 | if ( osascriptPresent ( ) )
4212 | {
4213 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"applescript");return (char const *)1;}
4214 | strcpy ( lDialogString , "osascript ");
4215 | if ( ! osx9orBetter() ) strcat ( lDialogString , " -e 'tell application \"System Events\"' -e 'Activate'");
4216 | strcat ( lDialogString , " -e 'try' -e 'display dialog \"") ;
4217 | if ( aMessage && strlen(aMessage) )
4218 | {
4219 | strcat(lDialogString, aMessage) ;
4220 | }
4221 | strcat(lDialogString, "\" ") ;
4222 | strcat(lDialogString, "default answer \"") ;
4223 | if ( aDefaultInput && strlen(aDefaultInput) )
4224 | {
4225 | strcat(lDialogString, aDefaultInput) ;
4226 | }
4227 | strcat(lDialogString, "\" ") ;
4228 | if ( ! aDefaultInput )
4229 | {
4230 | strcat(lDialogString, "hidden answer true ") ;
4231 | }
4232 | if ( aTitle && strlen(aTitle) )
4233 | {
4234 | strcat(lDialogString, "with title \"") ;
4235 | strcat(lDialogString, aTitle) ;
4236 | strcat(lDialogString, "\" ") ;
4237 | }
4238 | strcat(lDialogString, "with icon note' ") ;
4239 | strcat(lDialogString, "-e '\"1\" & text returned of result' " );
4240 | strcat(lDialogString, "-e 'on error number -128' " ) ;
4241 | strcat(lDialogString, "-e '0' " );
4242 | strcat(lDialogString, "-e 'end try'") ;
4243 | if ( ! osx9orBetter() ) strcat(lDialogString, " -e 'end tell'") ;
4244 | }
4245 | else if ( zenityPresent() || matedialogPresent() || qarmaPresent() )
4246 | {
4247 | if ( zenityPresent() )
4248 | {
4249 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity");return (char const *)1;}
4250 | strcpy ( lDialogString , "szAnswer=$(zenity --entry" ) ;
4251 | }
4252 | else if ( matedialogPresent() )
4253 | {
4254 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"matedialog");return (char const *)1;}
4255 | strcpy ( lDialogString , "szAnswer=$(matedialog --entry" ) ;
4256 | }
4257 | else
4258 | {
4259 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"qarma");return (char const *)1;}
4260 | strcpy ( lDialogString , "szAnswer=$(qarma --entry" ) ;
4261 | }
4262 |
4263 | if ( aTitle && strlen(aTitle) )
4264 | {
4265 | strcat(lDialogString, " --title=\"") ;
4266 | strcat(lDialogString, aTitle) ;
4267 | strcat(lDialogString, "\"") ;
4268 | }
4269 | if ( aMessage && strlen(aMessage) )
4270 | {
4271 | strcat(lDialogString, " --text=\"") ;
4272 | strcat(lDialogString, aMessage) ;
4273 | strcat(lDialogString, "\"") ;
4274 | }
4275 | if ( aDefaultInput && strlen(aDefaultInput) )
4276 | {
4277 | strcat(lDialogString, " --entry-text=\"") ;
4278 | strcat(lDialogString, aDefaultInput) ;
4279 | strcat(lDialogString, "\"") ;
4280 | }
4281 | else
4282 | {
4283 | strcat(lDialogString, " --hide-text") ;
4284 | }
4285 | strcat ( lDialogString ,
4286 | ");if [ $? = 0 ];then echo 1$szAnswer;else echo 0$szAnswer;fi");
4287 | }
4288 | else if ( kdialogPresent() )
4289 | {
4290 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"kdialog");return (char const *)1;}
4291 | strcpy ( lDialogString , "szAnswer=$(kdialog" ) ;
4292 | if ( ! aDefaultInput )
4293 | {
4294 | strcat(lDialogString, " --password ") ;
4295 | }
4296 | else
4297 | {
4298 | strcat(lDialogString, " --inputbox ") ;
4299 |
4300 | }
4301 | strcat(lDialogString, "\"") ;
4302 | if ( aMessage && strlen(aMessage) )
4303 | {
4304 | strcat(lDialogString, aMessage ) ;
4305 | }
4306 | strcat(lDialogString , "\" \"" ) ;
4307 | if ( aDefaultInput && strlen(aDefaultInput) )
4308 | {
4309 | strcat(lDialogString, aDefaultInput ) ;
4310 | }
4311 | strcat(lDialogString , "\"" ) ;
4312 | if ( aTitle && strlen(aTitle) )
4313 | {
4314 | strcat(lDialogString, " --title \"") ;
4315 | strcat(lDialogString, aTitle) ;
4316 | strcat(lDialogString, "\"") ;
4317 | }
4318 | strcat ( lDialogString ,
4319 | ");if [ $? = 0 ];then echo 1$szAnswer;else echo 0$szAnswer;fi");
4320 | }
4321 | else if ( gxmessagePresent() || gmessagePresent() )
4322 | {
4323 | if ( gxmessagePresent() ) {
4324 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"gxmessage");return (char const *)1;}
4325 | strcpy ( lDialogString , "szAnswer=$(gxmessage -buttons Ok:1,Cancel:0 -center \"");
4326 | }
4327 | else
4328 | {
4329 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"gmessage");return (char const *)1;}
4330 | strcpy ( lDialogString , "szAnswer=$(gmessage -buttons Ok:1,Cancel:0 -center \"");
4331 | }
4332 |
4333 | if ( aMessage && strlen(aMessage) )
4334 | {
4335 | strcat ( lDialogString , aMessage ) ;
4336 | }
4337 | strcat(lDialogString, "\"" ) ;
4338 | if ( aTitle && strlen(aTitle) )
4339 | {
4340 | strcat ( lDialogString , " -title \"");
4341 | strcat ( lDialogString , aTitle ) ;
4342 | strcat(lDialogString, "\" " ) ;
4343 | }
4344 | strcat(lDialogString, " -entrytext \"" ) ;
4345 | if ( aDefaultInput && strlen(aDefaultInput) )
4346 | {
4347 | strcat ( lDialogString , aDefaultInput ) ;
4348 | }
4349 | strcat(lDialogString, "\"" ) ;
4350 | strcat ( lDialogString , ");echo $?$szAnswer");
4351 | }
4352 | else if ( !gdialogPresent() && tkinter2Present ( ) )
4353 | {
4354 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"tkinter");return (char const *)1;}
4355 | strcpy ( lDialogString , gPython2Name ) ;
4356 | if ( ! isTerminalRunning ( ) && isDarwin ( ) )
4357 | {
4358 | strcat ( lDialogString , " -i" ) ; /* for osx without console */
4359 | }
4360 |
4361 | strcat ( lDialogString ,
4362 | " -c \"import Tkinter,tkSimpleDialog;root=Tkinter.Tk();root.withdraw();");
4363 |
4364 | if ( isDarwin ( ) )
4365 | {
4366 | strcat ( lDialogString ,
4367 | "import os;os.system('''/usr/bin/osascript -e 'tell app \\\"Finder\\\" to set \
4368 | frontmost of process \\\"Python\\\" to true' ''');");
4369 | }
4370 |
4371 | strcat ( lDialogString ,"res=tkSimpleDialog.askstring(" ) ;
4372 | if ( aTitle && strlen(aTitle) )
4373 | {
4374 | strcat(lDialogString, "title='") ;
4375 | strcat(lDialogString, aTitle) ;
4376 | strcat(lDialogString, "',") ;
4377 | }
4378 | if ( aMessage && strlen(aMessage) )
4379 | {
4380 |
4381 | strcat(lDialogString, "prompt='") ;
4382 | lpDialogString = lDialogString + strlen(lDialogString);
4383 | replaceSubStr ( aMessage , "\n" , "\\n" , lpDialogString ) ;
4384 | strcat(lDialogString, "',") ;
4385 | }
4386 | if ( aDefaultInput )
4387 | {
4388 | if ( strlen(aDefaultInput) )
4389 | {
4390 | strcat(lDialogString, "initialvalue='") ;
4391 | strcat(lDialogString, aDefaultInput) ;
4392 | strcat(lDialogString, "',") ;
4393 | }
4394 | }
4395 | else
4396 | {
4397 | strcat(lDialogString, "show='*'") ;
4398 | }
4399 | strcat(lDialogString, ");\nif res is None :\n\tprint 0");
4400 | strcat(lDialogString, "\nelse :\n\tprint '1'+res\n\"" ) ;
4401 | }
4402 | else if ( gdialogPresent() || xdialogPresent()
4403 | || dialogName() || whiptailPresent() )
4404 | {
4405 | if ( gdialogPresent ( ) )
4406 | {
4407 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"gdialog");return (char const *)1;}
4408 | lWasGraphicDialog = 1 ;
4409 | lWasGdialog = 1 ;
4410 | strcpy ( lDialogString , "(gdialog " ) ;
4411 | }
4412 | else if ( xdialogPresent ( ) )
4413 | {
4414 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"xdialog");return (char const *)1;}
4415 | lWasGraphicDialog = 1 ;
4416 | strcpy ( lDialogString , "(Xdialog " ) ;
4417 | }
4418 | else if ( dialogName ( ) )
4419 | {
4420 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
4421 | if ( isTerminalRunning ( ) )
4422 | {
4423 | strcpy ( lDialogString , "(dialog " ) ;
4424 | }
4425 | else
4426 | {
4427 | lWasXterm = 1 ;
4428 | strcpy ( lDialogString , terminalName() ) ;
4429 | strcat ( lDialogString , "'(" ) ;
4430 | strcat ( lDialogString , dialogName() ) ;
4431 | strcat ( lDialogString , " " ) ;
4432 | }
4433 | }
4434 | else if ( isTerminalRunning ( ) )
4435 | {
4436 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"whiptail");return (char const *)0;}
4437 | strcpy ( lDialogString , "(whiptail " ) ;
4438 | }
4439 | else
4440 | {
4441 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"whiptail");return (char const *)0;}
4442 | lWasXterm = 1 ;
4443 | strcpy ( lDialogString , terminalName() ) ;
4444 | strcat ( lDialogString , "'(whiptail " ) ;
4445 | }
4446 |
4447 | if ( aTitle && strlen(aTitle) )
4448 | {
4449 | strcat(lDialogString, "--title \"") ;
4450 | strcat(lDialogString, aTitle) ;
4451 | strcat(lDialogString, "\" ") ;
4452 | }
4453 |
4454 | if ( !xdialogPresent() && !gdialogPresent() )
4455 | {
4456 | strcat(lDialogString, "--backtitle \"") ;
4457 | strcat(lDialogString, "tab: move focus") ;
4458 | if ( ! aDefaultInput && !lWasGdialog )
4459 | {
4460 | strcat(lDialogString, " (sometimes nothing, no blink nor star, is shown in text field)") ;
4461 | }
4462 | strcat(lDialogString, "\" ") ;
4463 | }
4464 |
4465 | if ( aDefaultInput || lWasGdialog )
4466 | {
4467 | strcat ( lDialogString , "--inputbox" ) ;
4468 | }
4469 | else
4470 | {
4471 | if ( !lWasGraphicDialog && dialogName() && isDialogVersionBetter09b() )
4472 | {
4473 | strcat ( lDialogString , "--insecure " ) ;
4474 | }
4475 | strcat ( lDialogString , "--passwordbox" ) ;
4476 | }
4477 | strcat ( lDialogString , " \"" ) ;
4478 | if ( aMessage && strlen(aMessage) )
4479 | {
4480 | strcat(lDialogString, aMessage) ;
4481 | }
4482 | strcat(lDialogString,"\" 10 60 ") ;
4483 | if ( aDefaultInput && strlen(aDefaultInput) )
4484 | {
4485 | strcat(lDialogString, "\"") ;
4486 | strcat(lDialogString, aDefaultInput) ;
4487 | strcat(lDialogString, "\" ") ;
4488 | }
4489 | if ( lWasGraphicDialog )
4490 | {
4491 | strcat(lDialogString,") 2>/tmp/tinyfd.txt;\
4492 | if [ $? = 0 ];then tinyfdBool=1;else tinyfdBool=0;fi;\
4493 | tinyfdRes=$(cat /tmp/tinyfd.txt);echo $tinyfdBool$tinyfdRes") ;
4494 | }
4495 | else
4496 | {
4497 | strcat(lDialogString,">/dev/tty ) 2>/tmp/tinyfd.txt;\
4498 | if [ $? = 0 ];then tinyfdBool=1;else tinyfdBool=0;fi;\
4499 | tinyfdRes=$(cat /tmp/tinyfd.txt);echo $tinyfdBool$tinyfdRes") ;
4500 |
4501 | if ( lWasXterm )
4502 | {
4503 | strcat(lDialogString," >/tmp/tinyfd0.txt';cat /tmp/tinyfd0.txt");
4504 | }
4505 | else
4506 | {
4507 | strcat(lDialogString, "; clear >/dev/tty") ;
4508 | }
4509 | }
4510 | }
4511 | else if ( ! isTerminalRunning ( ) && terminalName() )
4512 | {
4513 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return (char const *)0;}
4514 | lWasBasicXterm = 1 ;
4515 | strcpy ( lDialogString , terminalName() ) ;
4516 | strcat ( lDialogString , "'" ) ;
4517 | if ( !gWarningDisplayed && !tinyfd_forceConsole)
4518 | {
4519 | tinyfd_messageBox(gTitle,gMessageUnix,"ok","warning",0);
4520 | gWarningDisplayed = 1 ;
4521 | }
4522 | if ( aTitle && strlen(aTitle) && !tinyfd_forceConsole)
4523 | {
4524 | strcat ( lDialogString , "echo \"" ) ;
4525 | strcat ( lDialogString, aTitle) ;
4526 | strcat ( lDialogString , "\";echo;" ) ;
4527 | }
4528 |
4529 | strcat ( lDialogString , "echo \"" ) ;
4530 | if ( aMessage && strlen(aMessage) )
4531 | {
4532 | strcat ( lDialogString, aMessage) ;
4533 | }
4534 | strcat ( lDialogString , "\";read " ) ;
4535 | if ( ! aDefaultInput )
4536 | {
4537 | strcat ( lDialogString , "-s " ) ;
4538 | }
4539 | strcat ( lDialogString , "-p \"" ) ;
4540 | strcat ( lDialogString , "(esc+enter to cancel): \" ANSWER " ) ;
4541 | strcat ( lDialogString , ";echo 1$ANSWER >/tmp/tinyfd.txt';" ) ;
4542 | strcat ( lDialogString , "cat -v /tmp/tinyfd.txt");
4543 | }
4544 | else
4545 | {
4546 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"basicinput");return (char const *)0;}
4547 | if ( !gWarningDisplayed && !tinyfd_forceConsole)
4548 | {
4549 | tinyfd_messageBox(gTitle,gMessageUnix,"ok","warning",0);
4550 | gWarningDisplayed = 1 ;
4551 | }
4552 | if ( aTitle && strlen(aTitle) )
4553 | {
4554 | printf ("\n%s\n", aTitle);
4555 | }
4556 | if ( aMessage && strlen(aMessage) )
4557 | {
4558 | printf("\n%s\n",aMessage);
4559 | }
4560 | printf("(esc+enter to cancel): "); fflush(stdout);
4561 | if ( ! aDefaultInput )
4562 | {
4563 | tcgetattr(STDIN_FILENO, & oldt) ;
4564 | newt = oldt ;
4565 | newt.c_lflag &= ~ECHO ;
4566 | tcsetattr(STDIN_FILENO, TCSANOW, & newt);
4567 | }
4568 |
4569 | lEOF = fgets(lBuff, MAX_PATH_OR_CMD, stdin);
4570 | /* printf("lbuff<%c><%d>\n",lBuff[0],lBuff[0]); */
4571 | if ( ! lEOF || (lBuff[0] == '\0') )
4572 | {
4573 | free(lDialogString);
4574 | return NULL;
4575 | }
4576 |
4577 | if ( lBuff[0] == '\n' )
4578 | {
4579 | lEOF = fgets(lBuff, MAX_PATH_OR_CMD, stdin);
4580 | /* printf("lbuff<%c><%d>\n",lBuff[0],lBuff[0]); */
4581 | if ( ! lEOF || (lBuff[0] == '\0') )
4582 | {
4583 | free(lDialogString);
4584 | return NULL;
4585 | }
4586 | }
4587 |
4588 | if ( ! aDefaultInput )
4589 | {
4590 | tcsetattr(STDIN_FILENO, TCSANOW, & oldt);
4591 | printf ("\n");
4592 | }
4593 | printf ("\n");
4594 | if ( strchr(lBuff,27) )
4595 | {
4596 | free(lDialogString);
4597 | return NULL ;
4598 | }
4599 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
4600 | {
4601 | lBuff[strlen ( lBuff ) -1] = '\0' ;
4602 | }
4603 | free(lDialogString);
4604 | return lBuff ;
4605 | }
4606 |
4607 | if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;
4608 | lIn = popen ( lDialogString , "r" );
4609 | if ( ! lIn )
4610 | {
4611 | if ( fileExists("/tmp/tinyfd.txt") )
4612 | {
4613 | wipefile("/tmp/tinyfd.txt");
4614 | remove("/tmp/tinyfd.txt");
4615 | }
4616 | if ( fileExists("/tmp/tinyfd0.txt") )
4617 | {
4618 | wipefile("/tmp/tinyfd0.txt");
4619 | remove("/tmp/tinyfd0.txt");
4620 | }
4621 | free(lDialogString);
4622 | return NULL ;
4623 | }
4624 | while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
4625 | {}
4626 |
4627 | pclose ( lIn ) ;
4628 |
4629 | if ( fileExists("/tmp/tinyfd.txt") )
4630 | {
4631 | wipefile("/tmp/tinyfd.txt");
4632 | remove("/tmp/tinyfd.txt");
4633 | }
4634 | if ( fileExists("/tmp/tinyfd0.txt") )
4635 | {
4636 | wipefile("/tmp/tinyfd0.txt");
4637 | remove("/tmp/tinyfd0.txt");
4638 | }
4639 |
4640 | /* printf ( "len Buff: %lu\n" , strlen(lBuff) ) ; */
4641 | /* printf ( "lBuff0: %s\n" , lBuff ) ; */
4642 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
4643 | {
4644 | lBuff[strlen ( lBuff ) -1] = '\0' ;
4645 | }
4646 | /* printf ( "lBuff1: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
4647 | if ( lWasBasicXterm )
4648 | {
4649 | if ( strstr(lBuff,"^[") ) /* esc was pressed */
4650 | {
4651 | free(lDialogString);
4652 | return NULL ;
4653 | }
4654 | }
4655 |
4656 | lResult = strncmp ( lBuff , "1" , 1) ? 0 : 1 ;
4657 | /* printf ( "lResult: %d \n" , lResult ) ; */
4658 | if ( ! lResult )
4659 | {
4660 | free(lDialogString);
4661 | return NULL ;
4662 | }
4663 | /* printf ( "lBuff+1: %s\n" , lBuff+1 ) ; */
4664 | free(lDialogString);
4665 |
4666 | return lBuff+1 ;
4667 | }
4668 |
4669 |
4670 | char const * tinyfd_saveFileDialog (
4671 | char const * const aTitle , /* NULL or "" */
4672 | char const * const aDefaultPathAndFile , /* NULL or "" */
4673 | int const aNumOfFilterPatterns , /* 0 */
4674 | char const * const * const aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
4675 | char const * const aSingleFilterDescription ) /* NULL or "image files" */
4676 | {
4677 |
4678 | static char lBuff [MAX_PATH_OR_CMD] ;
4679 | char lDialogString [MAX_PATH_OR_CMD] ;
4680 | char lString [MAX_PATH_OR_CMD] ;
4681 | int i ;
4682 | int lWasGraphicDialog = 0 ;
4683 | int lWasXterm = 0 ;
4684 | char const * p ;
4685 | FILE * lIn ;
4686 | lBuff[0]='\0';
4687 |
4688 | if ( osascriptPresent ( ) )
4689 | {
4690 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"applescript");return (char const *)1;}
4691 | strcpy ( lDialogString , "osascript ");
4692 | if ( ! osx9orBetter() ) strcat ( lDialogString , " -e 'tell application \"Finder\"' -e 'Activate'");
4693 | strcat ( lDialogString , " -e 'try' -e 'POSIX path of ( choose file name " );
4694 | if ( aTitle && strlen(aTitle) )
4695 | {
4696 | strcat(lDialogString, "with prompt \"") ;
4697 | strcat(lDialogString, aTitle) ;
4698 | strcat(lDialogString, "\" ") ;
4699 | }
4700 | getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
4701 | if ( strlen(lString) )
4702 | {
4703 | strcat(lDialogString, "default location \"") ;
4704 | strcat(lDialogString, lString ) ;
4705 | strcat(lDialogString , "\" " ) ;
4706 | }
4707 | getLastName ( lString , aDefaultPathAndFile ) ;
4708 | if ( strlen(lString) )
4709 | {
4710 | strcat(lDialogString, "default name \"") ;
4711 | strcat(lDialogString, lString ) ;
4712 | strcat(lDialogString , "\" " ) ;
4713 | }
4714 | strcat ( lDialogString , ")' " ) ;
4715 | strcat(lDialogString, "-e 'on error number -128' " ) ;
4716 | strcat(lDialogString, "-e 'end try'") ;
4717 | if ( ! osx9orBetter() ) strcat ( lDialogString, " -e 'end tell'") ;
4718 | }
4719 | else if ( zenityPresent() || matedialogPresent() || qarmaPresent() )
4720 | {
4721 | if ( zenityPresent() )
4722 | {
4723 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity");return (char const *)1;}
4724 | strcpy ( lDialogString , "zenity" ) ;
4725 | }
4726 | else if ( matedialogPresent() )
4727 | {
4728 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"matedialog");return (char const *)1;}
4729 | strcpy ( lDialogString , "matedialog" ) ;
4730 |
4731 | }
4732 | else
4733 | {
4734 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"qarma");return (char const *)1;}
4735 | strcpy ( lDialogString , "qarma" ) ;
4736 |
4737 | }
4738 | strcat(lDialogString, " --file-selection --save --confirm-overwrite" ) ;
4739 |
4740 | if ( aTitle && strlen(aTitle) )
4741 | {
4742 | strcat(lDialogString, " --title=\"") ;
4743 | strcat(lDialogString, aTitle) ;
4744 | strcat(lDialogString, "\"") ;
4745 | }
4746 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
4747 | {
4748 | strcat(lDialogString, " --filename=\"") ;
4749 | strcat(lDialogString, aDefaultPathAndFile) ;
4750 | strcat(lDialogString, "\"") ;
4751 | }
4752 | if ( aNumOfFilterPatterns > 0 )
4753 | {
4754 | strcat ( lDialogString , " --file-filter='" ) ;
4755 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
4756 | {
4757 | strcat ( lDialogString , aSingleFilterDescription ) ;
4758 | strcat ( lDialogString , " | " ) ;
4759 | }
4760 | for ( i = 0 ; i < aNumOfFilterPatterns ; i ++ )
4761 | {
4762 | strcat ( lDialogString , aFilterPatterns [i] ) ;
4763 | strcat ( lDialogString , " " ) ;
4764 | }
4765 | strcat ( lDialogString , "' --file-filter='All files | *'" ) ;
4766 | }
4767 | }
4768 | else if ( kdialogPresent() )
4769 | {
4770 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"kdialog");return (char const *)1;}
4771 | strcpy ( lDialogString , "kdialog --getsavefilename" ) ;
4772 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
4773 | {
4774 | strcat(lDialogString, " \"") ;
4775 | strcat(lDialogString, aDefaultPathAndFile ) ;
4776 | strcat(lDialogString , "\"" ) ;
4777 | }
4778 | else
4779 | {
4780 | strcat(lDialogString, " :" ) ;
4781 | }
4782 | if ( aNumOfFilterPatterns > 0 )
4783 | {
4784 | strcat(lDialogString , " \"" ) ;
4785 | for ( i = 0 ; i < aNumOfFilterPatterns ; i ++ )
4786 | {
4787 | strcat ( lDialogString , aFilterPatterns [i] ) ;
4788 | strcat ( lDialogString , " " ) ;
4789 | }
4790 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
4791 | {
4792 | strcat ( lDialogString , " | " ) ;
4793 | strcat ( lDialogString , aSingleFilterDescription ) ;
4794 | }
4795 | strcat ( lDialogString , "\"" ) ;
4796 | }
4797 | if ( aTitle && strlen(aTitle) )
4798 | {
4799 | strcat(lDialogString, " --title \"") ;
4800 | strcat(lDialogString, aTitle) ;
4801 | strcat(lDialogString, "\"") ;
4802 | }
4803 | }
4804 | else if ( ! xdialogPresent() && tkinter2Present ( ) )
4805 | {
4806 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"tkinter");return (char const *)1;}
4807 | strcpy ( lDialogString , gPython2Name ) ;
4808 | if ( ! isTerminalRunning ( ) && isDarwin ( ))
4809 | {
4810 | strcat ( lDialogString , " -i" ) ; /* for osx without console */
4811 | }
4812 | strcat ( lDialogString ,
4813 | " -c \"import Tkinter,tkFileDialog;root=Tkinter.Tk();root.withdraw();");
4814 |
4815 | if ( isDarwin ( ) )
4816 | {
4817 | strcat ( lDialogString ,
4818 | "import os;os.system('''/usr/bin/osascript -e 'tell app \\\"Finder\\\" to set\
4819 | frontmost of process \\\"Python\\\" to true' ''');");
4820 | }
4821 |
4822 | strcat ( lDialogString , "print tkFileDialog.asksaveasfilename(");
4823 | if ( aTitle && strlen(aTitle) )
4824 | {
4825 | strcat(lDialogString, "title='") ;
4826 | strcat(lDialogString, aTitle) ;
4827 | strcat(lDialogString, "',") ;
4828 | }
4829 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
4830 | {
4831 | getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
4832 | if ( strlen(lString) )
4833 | {
4834 | strcat(lDialogString, "initialdir='") ;
4835 | strcat(lDialogString, lString ) ;
4836 | strcat(lDialogString , "'," ) ;
4837 | }
4838 | getLastName ( lString , aDefaultPathAndFile ) ;
4839 | if ( strlen(lString) )
4840 | {
4841 | strcat(lDialogString, "initialfile='") ;
4842 | strcat(lDialogString, lString ) ;
4843 | strcat(lDialogString , "'," ) ;
4844 | }
4845 | }
4846 | if ( ( aNumOfFilterPatterns > 1 )
4847 | || ( (aNumOfFilterPatterns == 1) /* test because poor osx behaviour */
4848 | && ( aFilterPatterns[0][strlen(aFilterPatterns[0])-1] != '*' ) ) )
4849 | {
4850 | strcat(lDialogString , "filetypes=(" ) ;
4851 | strcat ( lDialogString , "('" ) ;
4852 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
4853 | {
4854 | strcat ( lDialogString , aSingleFilterDescription ) ;
4855 | }
4856 | strcat ( lDialogString , "',(" ) ;
4857 | for ( i = 0 ; i < aNumOfFilterPatterns ; i ++ )
4858 | {
4859 | strcat ( lDialogString , "'" ) ;
4860 | strcat ( lDialogString , aFilterPatterns [i] ) ;
4861 | strcat ( lDialogString , "'," ) ;
4862 | }
4863 | strcat ( lDialogString , "))," ) ;
4864 | strcat ( lDialogString , "('All files','*'))" ) ;
4865 | }
4866 | strcat ( lDialogString , ")\"" ) ;
4867 | }
4868 | else if ( xdialogPresent() || dialogName() )
4869 | {
4870 | if ( xdialogPresent ( ) )
4871 | {
4872 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"xdialog");return (char const *)1;}
4873 | lWasGraphicDialog = 1 ;
4874 | strcpy ( lDialogString , "(Xdialog " ) ;
4875 | }
4876 | else if ( isTerminalRunning ( ) )
4877 | {
4878 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
4879 | strcpy ( lDialogString , "(dialog " ) ;
4880 | }
4881 | else
4882 | {
4883 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
4884 | lWasXterm = 1 ;
4885 | strcpy ( lDialogString , terminalName() ) ;
4886 | strcat ( lDialogString , "'(" ) ;
4887 | strcat ( lDialogString , dialogName() ) ;
4888 | strcat ( lDialogString , " " ) ;
4889 | }
4890 |
4891 | if ( aTitle && strlen(aTitle) )
4892 | {
4893 | strcat(lDialogString, "--title \"") ;
4894 | strcat(lDialogString, aTitle) ;
4895 | strcat(lDialogString, "\" ") ;
4896 | }
4897 |
4898 | if ( !xdialogPresent() && !gdialogPresent() )
4899 | {
4900 | strcat(lDialogString, "--backtitle \"") ;
4901 | strcat(lDialogString,
4902 | "tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY") ;
4903 | strcat(lDialogString, "\" ") ;
4904 | }
4905 |
4906 | strcat ( lDialogString , "--fselect \"" ) ;
4907 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
4908 | {
4909 | if ( ! strchr(aDefaultPathAndFile, '/') )
4910 | {
4911 | strcat(lDialogString, "./") ;
4912 | }
4913 | strcat(lDialogString, aDefaultPathAndFile) ;
4914 | }
4915 | else if ( ! isTerminalRunning ( ) && !lWasGraphicDialog )
4916 | {
4917 | strcat(lDialogString, getenv("HOME")) ;
4918 | strcat(lDialogString, "/") ;
4919 | }
4920 | else
4921 | {
4922 | strcat(lDialogString, "./") ;
4923 | }
4924 |
4925 | if ( lWasGraphicDialog )
4926 | {
4927 | strcat(lDialogString, "\" 0 60 ) 2>&1 ") ;
4928 | }
4929 | else
4930 | {
4931 | strcat(lDialogString, "\" 0 60 >/dev/tty) ") ;
4932 | if ( lWasXterm )
4933 | {
4934 | strcat ( lDialogString ,
4935 | "2>/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt");
4936 | }
4937 | else
4938 | {
4939 | strcat(lDialogString, "2>&1 ; clear >/dev/tty") ;
4940 | }
4941 | }
4942 | }
4943 | else
4944 | {
4945 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){return tinyfd_inputBox (aTitle,NULL,NULL);}
4946 | p = tinyfd_inputBox ( aTitle , "Save file" , "" ) ;
4947 | getPathWithoutFinalSlash ( lString , p ) ;
4948 | if ( strlen ( lString ) && ! dirExists ( lString ) )
4949 | {
4950 | return NULL ;
4951 | }
4952 | getLastName(lString,p);
4953 | if ( ! strlen(lString) )
4954 | {
4955 | return NULL;
4956 | }
4957 | return p ;
4958 | }
4959 |
4960 | if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;
4961 | if ( ! ( lIn = popen ( lDialogString , "r" ) ) )
4962 | {
4963 | return NULL ;
4964 | }
4965 | while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
4966 | {}
4967 | pclose ( lIn ) ;
4968 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
4969 | {
4970 | lBuff[strlen ( lBuff ) -1] = '\0' ;
4971 | }
4972 | /* printf ( "lBuff: %s\n" , lBuff ) ; */
4973 | if ( ! strlen(lBuff) )
4974 | {
4975 | return NULL;
4976 | }
4977 | getPathWithoutFinalSlash ( lString , lBuff ) ;
4978 | if ( strlen ( lString ) && ! dirExists ( lString ) )
4979 | {
4980 | return NULL ;
4981 | }
4982 | getLastName(lString,lBuff);
4983 | if ( ! filenameValid(lString) )
4984 | {
4985 | return NULL;
4986 | }
4987 | return lBuff ;
4988 | }
4989 |
4990 |
4991 | /* in case of multiple files, the separator is | */
4992 | char const * tinyfd_openFileDialog (
4993 | char const * const aTitle , /* NULL or "" */
4994 | char const * const aDefaultPathAndFile , /* NULL or "" */
4995 | int const aNumOfFilterPatterns , /* 0 */
4996 | char const * const * const aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
4997 | char const * const aSingleFilterDescription , /* NULL or "image files" */
4998 | int const aAllowMultipleSelects ) /* 0 or 1 */
4999 | {
5000 | static char lBuff [MAX_MULTIPLE_FILES*MAX_PATH_OR_CMD] ;
5001 | char lDialogString [MAX_PATH_OR_CMD] ;
5002 | char lString [MAX_PATH_OR_CMD] ;
5003 | int i ;
5004 | FILE * lIn ;
5005 | char * p ;
5006 | char const * p2 ;
5007 | int lWasKdialog = 0 ;
5008 | int lWasGraphicDialog = 0 ;
5009 | int lWasXterm = 0 ;
5010 | lBuff[0]='\0';
5011 |
5012 | if ( osascriptPresent ( ) )
5013 | {
5014 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"applescript");return (char const *)1;}
5015 | strcpy ( lDialogString , "osascript ");
5016 | if ( ! osx9orBetter() ) strcat ( lDialogString , " -e 'tell application \"System Events\"' -e 'Activate'");
5017 | strcat ( lDialogString , " -e 'try' -e '" );
5018 | if ( ! aAllowMultipleSelects )
5019 | {
5020 |
5021 |
5022 | strcat ( lDialogString , "POSIX path of ( " );
5023 | }
5024 | else
5025 | {
5026 | strcat ( lDialogString , "set mylist to " );
5027 | }
5028 | strcat ( lDialogString , "choose file " );
5029 | if ( aTitle && strlen(aTitle) )
5030 | {
5031 | strcat(lDialogString, "with prompt \"") ;
5032 | strcat(lDialogString, aTitle) ;
5033 | strcat(lDialogString, "\" ") ;
5034 | }
5035 | getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
5036 | if ( strlen(lString) )
5037 | {
5038 | strcat(lDialogString, "default location \"") ;
5039 | strcat(lDialogString, lString ) ;
5040 | strcat(lDialogString , "\" " ) ;
5041 | }
5042 | if ( aNumOfFilterPatterns > 0 )
5043 | {
5044 | strcat(lDialogString , "of type {\"" );
5045 | strcat ( lDialogString , aFilterPatterns [0] + 2 ) ;
5046 | strcat ( lDialogString , "\"" ) ;
5047 | for ( i = 1 ; i < aNumOfFilterPatterns ; i ++ )
5048 | {
5049 | strcat ( lDialogString , ",\"" ) ;
5050 | strcat ( lDialogString , aFilterPatterns [i] + 2) ;
5051 | strcat ( lDialogString , "\"" ) ;
5052 | }
5053 | strcat ( lDialogString , "} " ) ;
5054 | }
5055 | if ( aAllowMultipleSelects )
5056 | {
5057 | strcat ( lDialogString , "multiple selections allowed true ' " ) ;
5058 | strcat ( lDialogString ,
5059 | "-e 'set mystring to POSIX path of item 1 of mylist' " );
5060 | strcat ( lDialogString ,
5061 | "-e 'repeat with i from 2 to the count of mylist' " );
5062 | strcat ( lDialogString , "-e 'set mystring to mystring & \"|\"' " );
5063 | strcat ( lDialogString ,
5064 | "-e 'set mystring to mystring & POSIX path of item i of mylist' " );
5065 | strcat ( lDialogString , "-e 'end repeat' " );
5066 | strcat ( lDialogString , "-e 'mystring' " );
5067 | }
5068 | else
5069 | {
5070 | strcat ( lDialogString , ")' " ) ;
5071 | }
5072 | strcat(lDialogString, "-e 'on error number -128' " ) ;
5073 | strcat(lDialogString, "-e 'end try'") ;
5074 | if ( ! osx9orBetter() ) strcat ( lDialogString, " -e 'end tell'") ;
5075 | }
5076 | else if ( zenityPresent() || matedialogPresent() || qarmaPresent() )
5077 | {
5078 | if ( zenityPresent() )
5079 | {
5080 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity");return (char const *)1;}
5081 | strcpy ( lDialogString , "zenity --file-selection" ) ;
5082 | }
5083 | else if ( matedialogPresent() )
5084 | {
5085 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"matedialog");return (char const *)1;}
5086 | strcpy ( lDialogString , "matedialog --file-selection" ) ;
5087 | }
5088 | else
5089 | {
5090 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"qarma");return (char const *)1;}
5091 | strcpy ( lDialogString , "qarma --file-selection" ) ;
5092 | }
5093 |
5094 | if ( aAllowMultipleSelects )
5095 | {
5096 | strcat ( lDialogString , " --multiple" ) ;
5097 | }
5098 | if ( aTitle && strlen(aTitle) )
5099 | {
5100 | strcat(lDialogString, " --title=\"") ;
5101 | strcat(lDialogString, aTitle) ;
5102 | strcat(lDialogString, "\"") ;
5103 | }
5104 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
5105 | {
5106 | strcat(lDialogString, " --filename=\"") ;
5107 | strcat(lDialogString, aDefaultPathAndFile) ;
5108 | strcat(lDialogString, "\"") ;
5109 | }
5110 | if ( aNumOfFilterPatterns > 0 )
5111 | {
5112 | strcat ( lDialogString , " --file-filter='" ) ;
5113 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
5114 | {
5115 | strcat ( lDialogString , aSingleFilterDescription ) ;
5116 | strcat ( lDialogString , " | " ) ;
5117 | }
5118 | for ( i = 0 ; i < aNumOfFilterPatterns ; i ++ )
5119 | {
5120 | strcat ( lDialogString , aFilterPatterns [i] ) ;
5121 | strcat ( lDialogString , " " ) ;
5122 | }
5123 | strcat ( lDialogString , "' --file-filter='All files | *'" ) ;
5124 | }
5125 | }
5126 | else if ( kdialogPresent() )
5127 | {
5128 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"kdialog");return (char const *)1;}
5129 | lWasKdialog = 1 ;
5130 | strcpy ( lDialogString , "kdialog --getopenfilename" ) ;
5131 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
5132 | {
5133 | strcat(lDialogString, " \"") ;
5134 | strcat(lDialogString, aDefaultPathAndFile ) ;
5135 |
5136 | strcat(lDialogString , "\"" ) ;
5137 | }
5138 | else
5139 | {
5140 | strcat(lDialogString, " :" ) ;
5141 | }
5142 | if ( aNumOfFilterPatterns > 0 )
5143 | {
5144 | strcat(lDialogString , " \"" ) ;
5145 | for ( i = 0 ; i < aNumOfFilterPatterns ; i ++ )
5146 | {
5147 | strcat ( lDialogString , aFilterPatterns [i] ) ;
5148 | strcat ( lDialogString , " " ) ;
5149 | }
5150 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
5151 | {
5152 | strcat ( lDialogString , " | " ) ;
5153 | strcat ( lDialogString , aSingleFilterDescription ) ;
5154 | }
5155 | strcat ( lDialogString , "\"" ) ;
5156 | }
5157 | if ( aAllowMultipleSelects )
5158 | {
5159 | strcat ( lDialogString , " --multiple --separate-output" ) ;
5160 | }
5161 | if ( aTitle && strlen(aTitle) )
5162 | {
5163 | strcat(lDialogString, " --title \"") ;
5164 | strcat(lDialogString, aTitle) ;
5165 | strcat(lDialogString, "\"") ;
5166 | }
5167 | }
5168 | else if ( ! xdialogPresent() && tkinter2Present ( ) )
5169 | {
5170 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"tkinter");return (char const *)1;}
5171 | strcpy ( lDialogString , gPython2Name ) ;
5172 | if ( ! isTerminalRunning ( ) && isDarwin ( ) )
5173 | {
5174 | strcat ( lDialogString , " -i" ) ; /* for osx without console */
5175 | }
5176 | strcat ( lDialogString ,
5177 | " -c \"import Tkinter,tkFileDialog;root=Tkinter.Tk();root.withdraw();");
5178 |
5179 | if ( isDarwin ( ) )
5180 | {
5181 | strcat ( lDialogString ,
5182 | "import os;os.system('''/usr/bin/osascript -e 'tell app \\\"Finder\\\" to set \
5183 | frontmost of process \\\"Python\\\" to true' ''');");
5184 | }
5185 | strcat ( lDialogString , "lFiles=tkFileDialog.askopenfilename(");
5186 | if ( aAllowMultipleSelects )
5187 | {
5188 | strcat ( lDialogString , "multiple=1," ) ;
5189 | }
5190 | if ( aTitle && strlen(aTitle) )
5191 | {
5192 | strcat(lDialogString, "title='") ;
5193 | strcat(lDialogString, aTitle) ;
5194 | strcat(lDialogString, "',") ;
5195 | }
5196 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
5197 | {
5198 | getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
5199 | if ( strlen(lString) )
5200 | {
5201 | strcat(lDialogString, "initialdir='") ;
5202 | strcat(lDialogString, lString ) ;
5203 | strcat(lDialogString , "'," ) ;
5204 | }
5205 | getLastName ( lString , aDefaultPathAndFile ) ;
5206 | if ( strlen(lString) )
5207 | {
5208 | strcat(lDialogString, "initialfile='") ;
5209 | strcat(lDialogString, lString ) ;
5210 | strcat(lDialogString , "'," ) ;
5211 | }
5212 | }
5213 | if ( ( aNumOfFilterPatterns > 1 )
5214 | || ( ( aNumOfFilterPatterns == 1 ) /*test because poor osx behaviour*/
5215 | && ( aFilterPatterns[0][strlen(aFilterPatterns[0])-1] != '*' ) ) )
5216 | {
5217 | strcat(lDialogString , "filetypes=(" ) ;
5218 | strcat ( lDialogString , "('" ) ;
5219 | if ( aSingleFilterDescription && strlen(aSingleFilterDescription) )
5220 | {
5221 | strcat ( lDialogString , aSingleFilterDescription ) ;
5222 | }
5223 | strcat ( lDialogString , "',(" ) ;
5224 | for ( i = 0 ; i < aNumOfFilterPatterns ; i ++ )
5225 | {
5226 | strcat ( lDialogString , "'" ) ;
5227 | strcat ( lDialogString , aFilterPatterns [i] ) ;
5228 | strcat ( lDialogString , "'," ) ;
5229 | }
5230 | strcat ( lDialogString , "))," ) ;
5231 | strcat ( lDialogString , "('All files','*'))" ) ;
5232 | }
5233 | strcat ( lDialogString , ");\
5234 | \nif not isinstance(lFiles, tuple):\n\tprint lFiles\nelse:\
5235 | \n\tlFilesString=''\n\tfor lFile in lFiles:\n\t\tlFilesString+=str(lFile)+'|'\
5236 | \n\tprint lFilesString[:-1]\n\"" ) ;
5237 | }
5238 | else if ( xdialogPresent() || dialogName() )
5239 | {
5240 | if ( xdialogPresent ( ) )
5241 | {
5242 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"xdialog");return (char const *)1;}
5243 | lWasGraphicDialog = 1 ;
5244 | strcpy ( lDialogString , "(Xdialog " ) ;
5245 | }
5246 | else if ( isTerminalRunning ( ) )
5247 | {
5248 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
5249 | strcpy ( lDialogString , "(dialog " ) ;
5250 | }
5251 | else
5252 | {
5253 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
5254 | lWasXterm = 1 ;
5255 | strcpy ( lDialogString , terminalName() ) ;
5256 | strcat ( lDialogString , "'(" ) ;
5257 | strcat ( lDialogString , dialogName() ) ;
5258 | strcat ( lDialogString , " " ) ;
5259 | }
5260 |
5261 | if ( aTitle && strlen(aTitle) )
5262 | {
5263 | strcat(lDialogString, "--title \"") ;
5264 | strcat(lDialogString, aTitle) ;
5265 | strcat(lDialogString, "\" ") ;
5266 | }
5267 |
5268 | if ( !xdialogPresent() && !gdialogPresent() )
5269 | {
5270 | strcat(lDialogString, "--backtitle \"") ;
5271 | strcat(lDialogString,
5272 | "tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY") ;
5273 | strcat(lDialogString, "\" ") ;
5274 | }
5275 |
5276 | strcat ( lDialogString , "--fselect \"" ) ;
5277 | if ( aDefaultPathAndFile && strlen(aDefaultPathAndFile) )
5278 | {
5279 | if ( ! strchr(aDefaultPathAndFile, '/') )
5280 | {
5281 | strcat(lDialogString, "./") ;
5282 | }
5283 | strcat(lDialogString, aDefaultPathAndFile) ;
5284 | }
5285 | else if ( ! isTerminalRunning ( ) && !lWasGraphicDialog )
5286 | {
5287 | strcat(lDialogString, getenv("HOME")) ;
5288 | strcat(lDialogString, "/");
5289 | }
5290 | else
5291 | {
5292 | strcat(lDialogString, "./") ;
5293 | }
5294 |
5295 | if ( lWasGraphicDialog )
5296 | {
5297 | strcat(lDialogString, "\" 0 60 ) 2>&1 ") ;
5298 | }
5299 | else
5300 | {
5301 | strcat(lDialogString, "\" 0 60 >/dev/tty) ") ;
5302 | if ( lWasXterm )
5303 | {
5304 | strcat ( lDialogString ,
5305 | "2>/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt");
5306 | }
5307 | else
5308 | {
5309 | strcat(lDialogString, "2>&1 ; clear >/dev/tty") ;
5310 | }
5311 | }
5312 | }
5313 | else
5314 | {
5315 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){return tinyfd_inputBox (aTitle,NULL,NULL);}
5316 | p2 = tinyfd_inputBox(aTitle, "Open file","");
5317 | if ( ! fileExists (p2) )
5318 | {
5319 | return NULL ;
5320 | }
5321 | return p2 ;
5322 | }
5323 |
5324 | if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;
5325 | if ( ! ( lIn = popen ( lDialogString , "r" ) ) )
5326 | {
5327 | return NULL ;
5328 | }
5329 | lBuff[0]='\0';
5330 | p=lBuff;
5331 | while ( fgets ( p , sizeof ( lBuff ) , lIn ) != NULL )
5332 | {
5333 | p += strlen ( p );
5334 | }
5335 | pclose ( lIn ) ;
5336 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
5337 | {
5338 | lBuff[strlen ( lBuff ) -1] = '\0' ;
5339 | }
5340 | /* printf ( "lBuff: %s\n" , lBuff ) ; */
5341 | if ( lWasKdialog && aAllowMultipleSelects )
5342 | {
5343 | p = lBuff ;
5344 | while ( ( p = strchr ( p , '\n' ) ) )
5345 | * p = '|' ;
5346 | }
5347 | /* printf ( "lBuff2: %s\n" , lBuff ) ; */
5348 | if ( ! strlen ( lBuff ) )
5349 | {
5350 | return NULL;
5351 | }
5352 | if ( aAllowMultipleSelects && strchr(lBuff, '|') )
5353 | {
5354 | p2 = ensureFilesExist( lBuff , lBuff ) ;
5355 | }
5356 | else if ( fileExists (lBuff) )
5357 | {
5358 | p2 = lBuff ;
5359 | }
5360 | else
5361 | {
5362 | return NULL ;
5363 | }
5364 | /* printf ( "lBuff3: %s\n" , p2 ) ; */
5365 |
5366 | return p2 ;
5367 | }
5368 |
5369 |
5370 | char const * tinyfd_selectFolderDialog (
5371 | char const * const aTitle , /* "" */
5372 | char const * const aDefaultPath ) /* "" */
5373 | {
5374 | static char lBuff [MAX_PATH_OR_CMD] ;
5375 | char lDialogString [MAX_PATH_OR_CMD] ;
5376 | FILE * lIn ;
5377 | char const * p ;
5378 | int lWasGraphicDialog = 0 ;
5379 | int lWasXterm = 0 ;
5380 | lBuff[0]='\0';
5381 |
5382 | if ( osascriptPresent ( ))
5383 | {
5384 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"applescript");return (char const *)1;}
5385 | strcpy ( lDialogString , "osascript ");
5386 | if ( ! osx9orBetter() ) strcat ( lDialogString , " -e 'tell application \"System Events\"' -e 'Activate'");
5387 | strcat ( lDialogString , " -e 'try' -e 'POSIX path of ( choose folder ");
5388 | if ( aTitle && strlen(aTitle) )
5389 | {
5390 | strcat(lDialogString, "with prompt \"") ;
5391 | strcat(lDialogString, aTitle) ;
5392 | strcat(lDialogString, "\" ") ;
5393 | }
5394 | if ( aDefaultPath && strlen(aDefaultPath) )
5395 | {
5396 | strcat(lDialogString, "default location \"") ;
5397 | strcat(lDialogString, aDefaultPath ) ;
5398 | strcat(lDialogString , "\" " ) ;
5399 | }
5400 | strcat ( lDialogString , ")' " ) ;
5401 | strcat(lDialogString, "-e 'on error number -128' " ) ;
5402 | strcat(lDialogString, "-e 'end try'") ;
5403 | if ( ! osx9orBetter() ) strcat ( lDialogString, " -e 'end tell'") ;
5404 | }
5405 | else if ( zenityPresent() || matedialogPresent() || qarmaPresent() )
5406 | {
5407 | if ( zenityPresent() )
5408 | {
5409 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity");return (char const *)1;}
5410 | strcpy ( lDialogString , "zenity --file-selection --directory" ) ;
5411 | }
5412 | else if ( matedialogPresent() )
5413 | {
5414 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"matedialog");return (char const *)1;}
5415 | strcpy ( lDialogString , "matedialog --file-selection --directory" ) ;
5416 | }
5417 | else
5418 | {
5419 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"qarma");return (char const *)1;}
5420 | strcpy ( lDialogString , "qarma --file-selection --directory" ) ;
5421 | }
5422 |
5423 | if ( aTitle && strlen(aTitle) )
5424 | {
5425 | strcat(lDialogString, " --title=\"") ;
5426 | strcat(lDialogString, aTitle) ;
5427 | strcat(lDialogString, "\"") ;
5428 | }
5429 | if ( aDefaultPath && strlen(aDefaultPath) )
5430 | {
5431 | strcat(lDialogString, " --filename=\"") ;
5432 | strcat(lDialogString, aDefaultPath) ;
5433 | strcat(lDialogString, "\"") ;
5434 | }
5435 | }
5436 | else if ( kdialogPresent() )
5437 | {
5438 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"kdialog");return (char const *)1;}
5439 | strcpy ( lDialogString , "kdialog --getexistingdirectory" ) ;
5440 | if ( aDefaultPath && strlen(aDefaultPath) )
5441 | {
5442 | strcat(lDialogString, " \"") ;
5443 | strcat(lDialogString, aDefaultPath ) ;
5444 | strcat(lDialogString , "\"" ) ;
5445 | }
5446 | else
5447 | {
5448 | strcat(lDialogString, " :" ) ;
5449 | }
5450 | if ( aTitle && strlen(aTitle) )
5451 | {
5452 | strcat(lDialogString, " --title \"") ;
5453 | strcat(lDialogString, aTitle) ;
5454 | strcat(lDialogString, "\"") ;
5455 | }
5456 | }
5457 | else if ( ! xdialogPresent() && tkinter2Present ( ) )
5458 | {
5459 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"tkinter");return (char const *)1;}
5460 | strcpy ( lDialogString , gPython2Name ) ;
5461 | if ( ! isTerminalRunning ( ) && isDarwin ( ) )
5462 | {
5463 | strcat ( lDialogString , " -i" ) ; /* for osx without console */
5464 | }
5465 | strcat ( lDialogString ,
5466 | " -c \"import Tkinter,tkFileDialog;root=Tkinter.Tk();root.withdraw();");
5467 |
5468 | if ( isDarwin ( ) )
5469 | {
5470 | strcat ( lDialogString ,
5471 | "import os;os.system('''/usr/bin/osascript -e 'tell app \\\"Finder\\\" to set \
5472 | frontmost of process \\\"Python\\\" to true' ''');");
5473 | }
5474 |
5475 | strcat ( lDialogString , "print tkFileDialog.askdirectory(");
5476 | if ( aTitle && strlen(aTitle) )
5477 | {
5478 | strcat(lDialogString, "title='") ;
5479 | strcat(lDialogString, aTitle) ;
5480 | strcat(lDialogString, "',") ;
5481 | }
5482 | if ( aDefaultPath && strlen(aDefaultPath) )
5483 | {
5484 | strcat(lDialogString, "initialdir='") ;
5485 | strcat(lDialogString, aDefaultPath ) ;
5486 | strcat(lDialogString , "'" ) ;
5487 | }
5488 | strcat ( lDialogString , ")\"" ) ;
5489 | }
5490 | else if ( xdialogPresent() || dialogName() )
5491 | {
5492 | if ( xdialogPresent ( ) )
5493 | {
5494 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"xdialog");return (char const *)1;}
5495 | lWasGraphicDialog = 1 ;
5496 | strcpy ( lDialogString , "(Xdialog " ) ;
5497 | }
5498 | else if ( isTerminalRunning ( ) )
5499 | {
5500 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
5501 | strcpy ( lDialogString , "(dialog " ) ;
5502 | }
5503 | else
5504 | {
5505 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dialog");return (char const *)0;}
5506 | lWasXterm = 1 ;
5507 | strcpy ( lDialogString , terminalName() ) ;
5508 | strcat ( lDialogString , "'(" ) ;
5509 | strcat ( lDialogString , dialogName() ) ;
5510 | strcat ( lDialogString , " " ) ;
5511 | }
5512 |
5513 | if ( aTitle && strlen(aTitle) )
5514 | {
5515 | strcat(lDialogString, "--title \"") ;
5516 | strcat(lDialogString, aTitle) ;
5517 | strcat(lDialogString, "\" ") ;
5518 | }
5519 |
5520 | if ( !xdialogPresent() && !gdialogPresent() )
5521 | {
5522 | strcat(lDialogString, "--backtitle \"") ;
5523 | strcat(lDialogString,
5524 | "tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY") ;
5525 | strcat(lDialogString, "\" ") ;
5526 | }
5527 |
5528 | strcat ( lDialogString , "--dselect \"" ) ;
5529 | if ( aDefaultPath && strlen(aDefaultPath) )
5530 | {
5531 | strcat(lDialogString, aDefaultPath) ;
5532 | ensureFinalSlash(lDialogString);
5533 | }
5534 | else if ( ! isTerminalRunning ( ) && !lWasGraphicDialog )
5535 | {
5536 | strcat(lDialogString, getenv("HOME")) ;
5537 | strcat(lDialogString, "/");
5538 | }
5539 | else
5540 | {
5541 | strcat(lDialogString, "./") ;
5542 | }
5543 |
5544 | if ( lWasGraphicDialog )
5545 | {
5546 | strcat(lDialogString, "\" 0 60 ) 2>&1 ") ;
5547 | }
5548 | else
5549 | {
5550 | strcat(lDialogString, "\" 0 60 >/dev/tty) ") ;
5551 | if ( lWasXterm )
5552 | {
5553 | strcat ( lDialogString ,
5554 | "2>/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt");
5555 | }
5556 | else
5557 | {
5558 | strcat(lDialogString, "2>&1 ; clear >/dev/tty") ;
5559 | }
5560 | }
5561 | }
5562 | else
5563 | {
5564 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){return tinyfd_inputBox (aTitle,NULL,NULL);}
5565 | p = tinyfd_inputBox(aTitle, "Select folder","");
5566 | if ( !p || ! strlen ( p ) || ! dirExists ( p ) )
5567 | {
5568 | return NULL ;
5569 | }
5570 | return p ;
5571 | }
5572 | if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;
5573 | if ( ! ( lIn = popen ( lDialogString , "r" ) ) )
5574 | {
5575 | return NULL ;
5576 | }
5577 | while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
5578 | {}
5579 | pclose ( lIn ) ;
5580 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
5581 | {
5582 | lBuff[strlen ( lBuff ) -1] = '\0' ;
5583 | }
5584 | /* printf ( "lBuff: %s\n" , lBuff ) ; */
5585 | if ( ! strlen ( lBuff ) || ! dirExists ( lBuff ) )
5586 | {
5587 | return NULL ;
5588 | }
5589 | return lBuff ;
5590 | }
5591 |
5592 |
5593 | /* returns the hexcolor as a string "#FF0000" */
5594 | /* aoResultRGB also contains the result */
5595 | /* aDefaultRGB is used only if aDefaultHexRGB is NULL */
5596 | /* aDefaultRGB and aoResultRGB can be the same array */
5597 | char const * tinyfd_colorChooser(
5598 | char const * const aTitle , /* NULL or "" */
5599 | char const * const aDefaultHexRGB , /* NULL or "#FF0000"*/
5600 | unsigned char const aDefaultRGB[3] , /* { 0 , 255 , 255 } */
5601 | unsigned char aoResultRGB[3] ) /* { 0 , 0 , 0 } */
5602 | {
5603 | static char lBuff [128] ;
5604 | char lTmp [128] ;
5605 | char lDialogString [MAX_PATH_OR_CMD] ;
5606 | char lDefaultHexRGB[8];
5607 | char * lpDefaultHexRGB;
5608 | unsigned char lDefaultRGB[3];
5609 | char const * p;
5610 | FILE * lIn ;
5611 | int i ;
5612 | int lWasZenity3 = 0 ;
5613 | int lWasOsascript = 0 ;
5614 | int lWasXdialog = 0 ;
5615 | lBuff[0]='\0';
5616 |
5617 | if ( aDefaultHexRGB )
5618 | {
5619 | Hex2RGB ( aDefaultHexRGB , lDefaultRGB ) ;
5620 | lpDefaultHexRGB = (char *) aDefaultHexRGB ;
5621 | }
5622 | else
5623 | {
5624 | lDefaultRGB[0]=aDefaultRGB[0];
5625 | lDefaultRGB[1]=aDefaultRGB[1];
5626 | lDefaultRGB[2]=aDefaultRGB[2];
5627 | RGB2Hex( aDefaultRGB , lDefaultHexRGB ) ;
5628 | lpDefaultHexRGB = (char *) lDefaultHexRGB ;
5629 | }
5630 |
5631 | if ( osascriptPresent ( ) )
5632 | {
5633 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"applescript");return (char const *)1;}
5634 | lWasOsascript = 1 ;
5635 | strcpy ( lDialogString , "osascript");
5636 |
5637 | if ( ! osx9orBetter() )
5638 | {
5639 | strcat ( lDialogString , " -e 'tell application \"System Events\"' -e 'Activate'");
5640 | strcat ( lDialogString , " -e 'try' -e 'set mycolor to choose color default color {");
5641 | }
5642 | else
5643 | {
5644 | strcat ( lDialogString ,
5645 | " -e 'try' -e 'tell app (path to frontmost application as Unicode text) \
5646 | to set mycolor to choose color default color {");
5647 | }
5648 |
5649 | sprintf(lTmp, "%d", 256 * lDefaultRGB[0] ) ;
5650 | strcat(lDialogString, lTmp ) ;
5651 | strcat(lDialogString, "," ) ;
5652 | sprintf(lTmp, "%d", 256 * lDefaultRGB[1] ) ;
5653 | strcat(lDialogString, lTmp ) ;
5654 | strcat(lDialogString, "," ) ;
5655 | sprintf(lTmp, "%d", 256 * lDefaultRGB[2] ) ;
5656 | strcat(lDialogString, lTmp ) ;
5657 | strcat(lDialogString, "}' " ) ;
5658 | strcat ( lDialogString ,
5659 | "-e 'set mystring to ((item 1 of mycolor) div 256 as integer) as string' " );
5660 | strcat ( lDialogString ,
5661 | "-e 'repeat with i from 2 to the count of mycolor' " );
5662 | strcat ( lDialogString ,
5663 | "-e 'set mystring to mystring & \" \" & ((item i of mycolor) div 256 as integer) as string' " );
5664 | strcat ( lDialogString , "-e 'end repeat' " );
5665 | strcat ( lDialogString , "-e 'mystring' ");
5666 | strcat(lDialogString, "-e 'on error number -128' " ) ;
5667 | strcat(lDialogString, "-e 'end try'") ;
5668 | if ( ! osx9orBetter() ) strcat ( lDialogString, " -e 'end tell'") ;
5669 | }
5670 | else if ( zenity3Present() || matedialogPresent() || qarmaPresent() )
5671 | {
5672 | lWasZenity3 = 1 ;
5673 | if ( zenity3Present() )
5674 | {
5675 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity3");return (char const *)1;}
5676 | sprintf ( lDialogString ,
5677 | "zenity --color-selection --show-palette --color=%s" , lpDefaultHexRGB ) ;
5678 | }
5679 | else if ( matedialogPresent() )
5680 | {
5681 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"matedialog");return (char const *)1;}
5682 | sprintf ( lDialogString ,
5683 | "matedialog --color-selection --show-palette --color=%s" , lpDefaultHexRGB ) ;
5684 | }
5685 | else
5686 | {
5687 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"qarma");return (char const *)1;}
5688 | sprintf ( lDialogString ,
5689 | "qarma --color-selection --show-palette --color=%s" , lpDefaultHexRGB ) ;
5690 | }
5691 |
5692 | if ( aTitle && strlen(aTitle) )
5693 | {
5694 | strcat(lDialogString, " --title=\"") ;
5695 | strcat(lDialogString, aTitle) ;
5696 | strcat(lDialogString, "\"") ;
5697 | }
5698 | }
5699 | else if ( kdialogPresent() )
5700 | {
5701 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"kdialog");return (char const *)1;}
5702 | sprintf ( lDialogString ,
5703 | "kdialog --getcolor --default '%s'" , lpDefaultHexRGB ) ;
5704 | if ( aTitle && strlen(aTitle) )
5705 | {
5706 | strcat(lDialogString, " --title \"") ;
5707 | strcat(lDialogString, aTitle) ;
5708 | strcat(lDialogString, "\"") ;
5709 | }
5710 | }
5711 | else if ( xdialogPresent() )
5712 | {
5713 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"xdialog");return (char const *)1;}
5714 | lWasXdialog = 1 ;
5715 | strcpy ( lDialogString , "Xdialog --colorsel \"" ) ;
5716 | if ( aTitle && strlen(aTitle) )
5717 | {
5718 | strcat(lDialogString, aTitle) ;
5719 | }
5720 | strcat(lDialogString, "\" 0 60 ") ;
5721 | sprintf(lTmp,"%hhu %hhu %hhu",lDefaultRGB[0],
5722 | lDefaultRGB[1],lDefaultRGB[2]);
5723 | strcat(lDialogString, lTmp) ;
5724 | strcat(lDialogString, " 2>&1");
5725 | }
5726 | else if ( tkinter2Present ( ) )
5727 | {
5728 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"tkinter");return (char const *)1;}
5729 | strcpy ( lDialogString , gPython2Name ) ;
5730 | if ( ! isTerminalRunning ( ) && isDarwin ( ) )
5731 | {
5732 | strcat ( lDialogString , " -i" ) ; /* for osx without console */
5733 | }
5734 |
5735 | strcat ( lDialogString ,
5736 | " -c \"import Tkinter,tkColorChooser;root=Tkinter.Tk();root.withdraw();");
5737 |
5738 | if ( isDarwin ( ) )
5739 | {
5740 | strcat ( lDialogString ,
5741 | "import os;os.system('''osascript -e 'tell app \\\"Finder\\\" to set \
5742 | frontmost of process \\\"Python\\\" to true' ''');");
5743 | }
5744 |
5745 | strcat ( lDialogString , "res=tkColorChooser.askcolor(color='" ) ;
5746 | strcat(lDialogString, lpDefaultHexRGB ) ;
5747 | strcat(lDialogString, "'") ;
5748 |
5749 |
5750 | if ( aTitle && strlen(aTitle) )
5751 | {
5752 | strcat(lDialogString, ",title='") ;
5753 | strcat(lDialogString, aTitle) ;
5754 | strcat(lDialogString, "'") ;
5755 | }
5756 | strcat ( lDialogString , ");\
5757 | \nif res[1] is not None:\n\tprint res[1]\"" ) ;
5758 | }
5759 | else
5760 | {
5761 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){return tinyfd_inputBox (aTitle,NULL,NULL);}
5762 | p = tinyfd_inputBox(aTitle,
5763 | "Enter hex rgb color (i.e. #f5ca20)",lpDefaultHexRGB);
5764 | if ( !p || (strlen(p) != 7) || (p[0] != '#') )
5765 | {
5766 | return NULL ;
5767 | }
5768 | for ( i = 1 ; i < 7 ; i ++ )
5769 | {
5770 | if ( ! isxdigit( p[i] ) )
5771 | {
5772 | return NULL ;
5773 | }
5774 | }
5775 | Hex2RGB(p,aoResultRGB);
5776 | return p ;
5777 | }
5778 |
5779 | if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;
5780 | if ( ! ( lIn = popen ( lDialogString , "r" ) ) )
5781 | {
5782 | return NULL ;
5783 | }
5784 | while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
5785 | {
5786 | }
5787 | pclose ( lIn ) ;
5788 | if ( ! strlen ( lBuff ) )
5789 | {
5790 | return NULL ;
5791 | }
5792 | /* printf ( "len Buff: %lu\n" , strlen(lBuff) ) ; */
5793 | /* printf ( "lBuff0: %s\n" , lBuff ) ; */
5794 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
5795 | {
5796 | lBuff[strlen ( lBuff ) -1] = '\0' ;
5797 | }
5798 | if ( lWasZenity3 )
5799 | {
5800 | if ( lBuff[0] == '#' ) {
5801 | lBuff[3]=lBuff[5];
5802 | lBuff[4]=lBuff[6];
5803 | lBuff[5]=lBuff[9];
5804 | lBuff[6]=lBuff[10];
5805 | lBuff[7]='\0';
5806 | Hex2RGB(lBuff,aoResultRGB);
5807 | }
5808 | else if ( lBuff[3] == '(' ) {
5809 | sscanf(lBuff,"rgb(%hhu,%hhu,%hhu",
5810 | & aoResultRGB[0], & aoResultRGB[1],& aoResultRGB[2]);
5811 | RGB2Hex(aoResultRGB,lBuff);
5812 | }
5813 | else if ( lBuff[4] == '(' ) {
5814 | sscanf(lBuff,"rgba(%hhu,%hhu,%hhu",
5815 | & aoResultRGB[0], & aoResultRGB[1],& aoResultRGB[2]);
5816 | RGB2Hex(aoResultRGB,lBuff);
5817 | }
5818 | }
5819 | else if ( lWasOsascript || lWasXdialog )
5820 | {
5821 | /* printf ( "lBuff: %s\n" , lBuff ) ; */
5822 | sscanf(lBuff,"%hhu %hhu %hhu",
5823 | & aoResultRGB[0], & aoResultRGB[1],& aoResultRGB[2]);
5824 | RGB2Hex(aoResultRGB,lBuff);
5825 | }
5826 | else
5827 | {
5828 | Hex2RGB(lBuff,aoResultRGB);
5829 | }
5830 | /* printf("%d %d %d\n", aoResultRGB[0],aoResultRGB[1],aoResultRGB[2]); */
5831 | /* printf ( "lBuff: %s\n" , lBuff ) ; */
5832 | return lBuff ;
5833 | }
5834 |
5835 |
5836 | /* not cross platform - zenity only */
5837 | /* contributed by Attila Dusnoki */
5838 | char const * tinyfd_arrayDialog (
5839 | char const * const aTitle , /* "" */
5840 | int const aNumOfColumns , /* 2 */
5841 | char const * const * const aColumns , /* {"Column 1","Column 2"} */
5842 | int const aNumOfRows , /* 2 */
5843 | char const * const * const aCells )
5844 | /* {"Row1 Col1","Row1 Col2","Row2 Col1","Row2 Col2"} */
5845 | {
5846 | static char lBuff [MAX_PATH_OR_CMD] ;
5847 | char lDialogString [MAX_PATH_OR_CMD] ;
5848 | FILE * lIn ;
5849 | lBuff[0]='\0';
5850 | int i ;
5851 |
5852 | if ( zenityPresent() )
5853 | {
5854 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity");return (char const *)1;}
5855 | strcpy ( lDialogString , "zenity --list --print-column=ALL" ) ;
5856 | if ( aTitle && strlen(aTitle) )
5857 | {
5858 | strcat(lDialogString, " --title=\"") ;
5859 | strcat(lDialogString, aTitle) ;
5860 | strcat(lDialogString, "\"") ;
5861 | }
5862 |
5863 | if ( aColumns && (aNumOfColumns > 0) )
5864 | {
5865 | for ( i = 0 ; i < aNumOfColumns ; i ++ )
5866 | {
5867 | strcat ( lDialogString , " --column=\"" ) ;
5868 | strcat ( lDialogString , aColumns [i] ) ;
5869 | strcat ( lDialogString , "\"" ) ;
5870 | }
5871 | }
5872 |
5873 | if ( aCells && (aNumOfRows > 0) )
5874 | {
5875 | strcat ( lDialogString , " " ) ;
5876 | for ( i = 0 ; i < aNumOfRows*aNumOfColumns ; i ++ )
5877 | {
5878 | strcat ( lDialogString , "\"" ) ;
5879 | strcat ( lDialogString , aCells [i] ) ;
5880 | strcat ( lDialogString , "\" " ) ;
5881 | }
5882 | }
5883 | }
5884 | else
5885 | {
5886 | if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"");return (char const *)0;}
5887 | return NULL ;
5888 | }
5889 |
5890 | if (tinyfd_verbose) printf ( "lDialogString: %s\n" , lDialogString ) ;
5891 | if ( ! ( lIn = popen ( lDialogString , "r" ) ) )
5892 | {
5893 | return NULL ;
5894 | }
5895 | while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) != NULL )
5896 | {}
5897 | pclose ( lIn ) ;
5898 | if ( lBuff[strlen ( lBuff ) -1] == '\n' )
5899 | {
5900 | lBuff[strlen ( lBuff ) -1] = '\0' ;
5901 | }
5902 | /* printf ( "lBuff: %s\n" , lBuff ) ; */
5903 | if ( ! strlen ( lBuff ) )
5904 | {
5905 | return NULL ;
5906 | }
5907 | return lBuff ;
5908 | }
5909 | #endif /* _WIN32 */
5910 |
5911 |
5912 | /*
5913 | int main(void)
5914 | {
5915 | char const * lTmp;
5916 | char const * lTheSaveFileName;
5917 | char const * lTheOpenFileName;
5918 | char const * lTheSelectFolderName;
5919 | char const * lTheHexColor;
5920 | char const * lWillBeGraphicMode;
5921 | unsigned char lRgbColor[3];
5922 | FILE * lIn;
5923 | char lBuffer[1024];
5924 | char lThePassword[1024];
5925 | char const * lFilterPatterns[2] = { "*.txt", "*.text" };
5926 |
5927 | lWillBeGraphicMode = tinyfd_inputBox("tinyfd_query", NULL, NULL);
5928 |
5929 | if (lWillBeGraphicMode)
5930 | {
5931 | strcpy(lBuffer, "graphic mode: ");
5932 | }
5933 | else
5934 | {
5935 | strcpy(lBuffer, "console mode: ");
5936 | }
5937 |
5938 | strcat(lBuffer, tinyfd_response);
5939 | strcpy(lThePassword, "tinyfiledialogs v");
5940 | strcat(lThePassword, tinyfd_version);
5941 | tinyfd_messageBox(lThePassword, lBuffer, "ok", "info", 0);
5942 |
5943 | if (lWillBeGraphicMode && !tinyfd_forceConsole)
5944 | {
5945 | tinyfd_forceConsole = ! tinyfd_messageBox("Hello World",
5946 | "graphic dialogs [yes] / console mode [no]?",
5947 | "yesno", "question", 1);
5948 | }
5949 |
5950 | lTmp = tinyfd_inputBox(
5951 | "a password box", "your password will be revealed", NULL);
5952 |
5953 | if (!lTmp) return 1;
5954 |
5955 | strcpy(lThePassword, lTmp);
5956 |
5957 | lTheSaveFileName = tinyfd_saveFileDialog(
5958 | "let us save this password",
5959 | "passwordFile.txt",
5960 | 2,
5961 | lFilterPatterns,
5962 | NULL);
5963 |
5964 | if (!lTheSaveFileName)
5965 | {
5966 | tinyfd_messageBox(
5967 | "Error",
5968 | "Save file name is NULL",
5969 | "ok",
5970 | "error",
5971 | 1);
5972 | return 1;
5973 | }
5974 |
5975 | lIn = fopen(lTheSaveFileName, "w");
5976 | if (!lIn)
5977 | {
5978 | tinyfd_messageBox(
5979 | "Error",
5980 | "Can not open this file in write mode",
5981 | "ok",
5982 | "error",
5983 | 1);
5984 | return 1;
5985 | }
5986 | fputs(lThePassword, lIn);
5987 | fclose(lIn);
5988 |
5989 | lTheOpenFileName = tinyfd_openFileDialog(
5990 | "let us read the password back",
5991 | "",
5992 | 2,
5993 | lFilterPatterns,
5994 | NULL,
5995 | 0);
5996 |
5997 | if (!lTheOpenFileName)
5998 | {
5999 | tinyfd_messageBox(
6000 | "Error",
6001 | "Open file name is NULL",
6002 | "ok",
6003 | "error",
6004 | 1);
6005 | return 1;
6006 | }
6007 |
6008 | lIn = fopen(lTheOpenFileName, "r");
6009 |
6010 | if (!lIn)
6011 | {
6012 | tinyfd_messageBox(
6013 | "Error",
6014 | "Can not open this file in read mode",
6015 | "ok",
6016 | "error",
6017 | 1);
6018 | return(1);
6019 | }
6020 | lBuffer[0] = '\0';
6021 | fgets(lBuffer, sizeof(lBuffer), lIn);
6022 | fclose(lIn);
6023 |
6024 | tinyfd_messageBox("your password is",
6025 | lBuffer, "ok", "info", 1);
6026 |
6027 | lTheSelectFolderName = tinyfd_selectFolderDialog(
6028 | "let us just select a directory", NULL);
6029 |
6030 | if (!lTheSelectFolderName)
6031 | {
6032 | tinyfd_messageBox(
6033 | "Error",
6034 | "Select folder name is NULL",
6035 | "ok",
6036 | "error",
6037 | 1);
6038 | return 1;
6039 | }
6040 |
6041 | tinyfd_messageBox("The selected folder is",
6042 | lTheSelectFolderName, "ok", "info", 1);
6043 |
6044 | lTheHexColor = tinyfd_colorChooser(
6045 | "choose a nice color",
6046 | "#FF0077",
6047 | lRgbColor,
6048 | lRgbColor);
6049 |
6050 | if (!lTheHexColor)
6051 | {
6052 | tinyfd_messageBox(
6053 | "Error",
6054 | "hexcolor is NULL",
6055 | "ok",
6056 | "error",
6057 | 1);
6058 | return 1;
6059 | }
6060 |
6061 | tinyfd_messageBox("The selected hexcolor is",
6062 | lTheHexColor, "ok", "info", 1);
6063 |
6064 | return 0;
6065 | }
6066 | */
6067 |
6068 | #ifdef _MSC_VER
6069 | #pragma warning(default:4996)
6070 | #pragma warning(default:4100)
6071 | #pragma warning(default:4706)
6072 | #endif
6073 |
--------------------------------------------------------------------------------