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