2024-08-12 14:55:46 +00:00
/* If you are using a C++ compiler to compile tinyfiledialogs.c (maybe renamed with an extension ".cpp")
then comment out < < extern " C " > > bellow in this header file ) */
/*_________
/ \ tinyfiledialogs . h v3 .8 .8 [ Apr 22 , 2021 ] zlib licence
| tiny file | Unique header file created [ November 9 , 2014 ]
| dialogs | Copyright ( c ) 2014 - 2021 Guillaume Vareille http : //ysengrin.com
\ ____ ___ / http : //tinyfiledialogs.sourceforge.net
\ | git clone http : //git.code.sf.net/p/tinyfiledialogs/code tinyfd
____________________________________________
| |
| email : tinyfiledialogs at ysengrin . com |
| ____________________________________________ |
________________________________________________________________________________
| ____________________________________________________________________________ |
| | | |
| | on windows : | |
| | - for UTF - 16 , use the wchar_t functions at the bottom of the header file | |
| | - _wfopen ( ) requires wchar_t | |
| | | |
| | - in tinyfiledialogs , char is UTF - 8 by default ( since v3 .6 ) | |
| | - but fopen ( ) expects MBCS ( not UTF - 8 ) | |
| | - if you want char to be MBCS : set tinyfd_winUtf8 to 0 | |
| | | |
| | - alternatively , tinyfiledialogs provides | |
| | functions to convert between UTF - 8 , UTF - 16 and MBCS | |
| | ____________________________________________________________________________ | |
| ________________________________________________________________________________ |
If you like tinyfiledialogs , please upvote my stackoverflow answer
https : //stackoverflow.com/a/47651444
- License -
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
*/
# ifndef TINYFILEDIALOGS_H
# define TINYFILEDIALOGS_H
# ifdef __cplusplus
/* if tinydialogs.c is compiled as C++ code rather than C code, you may need to comment this out
and the corresponding closing bracket near the end of this file . */
extern " C " {
# endif
/******************************************************************************************************/
/**************************************** UTF-8 on Windows ********************************************/
/******************************************************************************************************/
# ifdef _WIN32
/* On windows, if you want to use UTF-8 ( instead of the UTF-16/wchar_t functions at the end of this file )
Make sure your code is really prepared for UTF - 8 ( on windows , functions like fopen ( ) expect MBCS and not UTF - 8 ) */
extern int tinyfd_winUtf8 ; /* on windows char strings can be 1:UTF-8(default) or 0:MBCS */
/* for MBCS change this to 0, in tinyfiledialogs.c or in your code */
/* Here are some functions to help you convert between UTF-16 UTF-8 MBSC */
char * tinyfd_utf8toMbcs ( char const * aUtf8string ) ;
char * tinyfd_utf16toMbcs ( wchar_t const * aUtf16string ) ;
wchar_t * tinyfd_mbcsTo16 ( char const * aMbcsString ) ;
char * tinyfd_mbcsTo8 ( char const * aMbcsString ) ;
wchar_t * tinyfd_utf8to16 ( char const * aUtf8string ) ;
char * tinyfd_utf16to8 ( wchar_t const * aUtf16string ) ;
# endif
/******************************************************************************************************/
/******************************************************************************************************/
/******************************************************************************************************/
/************* 3 funtions for C# (you don't need this in C or C++) : */
char const * tinyfd_getGlobalChar ( char const * aCharVariableName ) ; /* returns NULL on error */
int tinyfd_getGlobalInt ( char const * aIntVariableName ) ; /* returns -1 on error */
int tinyfd_setGlobalInt ( char const * aIntVariableName , int aValue ) ; /* returns -1 on error */
/* aCharVariableName: "tinyfd_version" "tinyfd_needs" "tinyfd_response"
aIntVariableName : " tinyfd_verbose " " tinyfd_silent " " tinyfd_allowCursesDialogs "
" tinyfd_forceConsole " " tinyfd_assumeGraphicDisplay " " tinyfd_winUtf8 "
* * * * * * * * * * * * * */
extern char tinyfd_version [ 8 ] ; /* contains tinyfd current version number */
extern char tinyfd_needs [ ] ; /* info about requirements */
extern int tinyfd_verbose ; /* 0 (default) or 1 : on unix, prints the command line calls */
extern int tinyfd_silent ; /* 1 (default) or 0 : on unix, hide errors and warnings from called dialogs */
/* Curses dialogs are difficult to use, on windows they are only ascii and uses the unix backslah */
extern int tinyfd_allowCursesDialogs ; /* 0 (default) or 1 */
extern int tinyfd_forceConsole ; /* 0 (default) or 1 */
/* for unix & windows: 0 (graphic mode) or 1 (console mode).
0 : try to use a graphic solution , if it fails then it uses console mode .
1 : forces all dialogs into console mode even when an X server is present ,
it can use the package dialog or dialog . exe .
on windows it only make sense for console applications */
extern int tinyfd_assumeGraphicDisplay ; /* 0 (default) or 1 */
/* some systems don't set the environment variable DISPLAY even when a graphic display is present.
set this to 1 to tell tinyfiledialogs to assume the existence of a graphic display */
extern char tinyfd_response [ 1024 ] ;
/* if you pass "tinyfd_query" as aTitle,
the functions will not display the dialogs
but will return 0 for console mode , 1 for graphic mode .
tinyfd_response is then filled with the retain solution .
possible values for tinyfd_response are ( all lowercase )
for graphic mode :
windows_wchar windows applescript kdialog zenity zenity3 matedialog
shellementary qarma yad python2 - tkinter python3 - tkinter python - dbus
perl - dbus gxmessage gmessage xmessage xdialog gdialog
for console mode :
dialog whiptail basicinput no_solution */
void tinyfd_beep ( void ) ;
int tinyfd_notifyPopup (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n \t */
char const * aIconType ) ; /* "info" "warning" "error" */
/* return has only meaning for tinyfd_query */
int tinyfd_messageBox (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n \t */
char const * aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
char const * aIconType , /* "info" "warning" "error" "question" */
int aDefaultButton ) ;
/* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
char * tinyfd_inputBox (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" (\n and \t have no effect) */
char const * aDefaultInput ) ; /* NULL passwordBox, "" inputbox */
/* returns NULL on cancel */
char * tinyfd_saveFileDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 (1 in the following example) */
char const * const * aFilterPatterns , /* NULL or char const * lFilterPatterns[1]={"*.txt"} */
char const * aSingleFilterDescription ) ; /* NULL or "text files" */
/* returns NULL on cancel */
char * tinyfd_openFileDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 (2 in the following example) */
char const * const * aFilterPatterns , /* NULL or char const * lFilterPatterns[2]={"*.png","*.jpg"}; */
char const * aSingleFilterDescription , /* NULL or "image files" */
int aAllowMultipleSelects ) ; /* 0 or 1 */
/* in case of multiple files, the separator is | */
/* returns NULL on cancel */
char * tinyfd_selectFolderDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPath ) ; /* NULL or "" */
/* returns NULL on cancel */
char * tinyfd_colorChooser (
char const * aTitle , /* NULL or "" */
char const * aDefaultHexRGB , /* NULL or "#FF0000" */
unsigned char const aDefaultRGB [ 3 ] , /* unsigned char lDefaultRGB[3] = { 0 , 128 , 255 }; */
unsigned char aoResultRGB [ 3 ] ) ; /* unsigned char lResultRGB[3]; */
/* returns the hexcolor as a string "#FF0000" */
/* aoResultRGB also contains the result */
/* aDefaultRGB is used only if aDefaultHexRGB is NULL */
/* aDefaultRGB and aoResultRGB can be the same array */
/* returns NULL on cancel */
/************ WINDOWS ONLY SECTION ************************/
# ifdef _WIN32
/* windows only - utf-16 version */
int tinyfd_notifyPopupW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aMessage , /* NULL or L"" may contain \n \t */
wchar_t const * aIconType ) ; /* L"info" L"warning" L"error" */
/* windows only - utf-16 version */
int tinyfd_messageBoxW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aMessage , /* NULL or L"" may contain \n \t */
wchar_t const * aDialogType , /* L"ok" L"okcancel" L"yesno" */
wchar_t const * aIconType , /* L"info" L"warning" L"error" L"question" */
int aDefaultButton ) ; /* 0 for cancel/no , 1 for ok/yes */
/* returns 0 for cancel/no , 1 for ok/yes */
/* windows only - utf-16 version */
wchar_t * tinyfd_inputBoxW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aMessage , /* NULL or L"" (\n nor \t not respected) */
wchar_t const * aDefaultInput ) ; /* NULL passwordBox, L"" inputbox */
/* windows only - utf-16 version */
wchar_t * tinyfd_saveFileDialogW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aDefaultPathAndFile , /* NULL or L"" */
int aNumOfFilterPatterns , /* 0 (1 in the following example) */
wchar_t const * const * aFilterPatterns , /* NULL or wchar_t const * lFilterPatterns[1]={L"*.txt"} */
wchar_t const * aSingleFilterDescription ) ; /* NULL or L"text files" */
/* returns NULL on cancel */
/* windows only - utf-16 version */
wchar_t * tinyfd_openFileDialogW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aDefaultPathAndFile , /* NULL or L"" */
int aNumOfFilterPatterns , /* 0 (2 in the following example) */
wchar_t const * const * aFilterPatterns , /* NULL or wchar_t const * lFilterPatterns[2]={L"*.png","*.jpg"} */
wchar_t const * aSingleFilterDescription , /* NULL or L"image files" */
int aAllowMultipleSelects ) ; /* 0 or 1 */
/* in case of multiple files, the separator is | */
/* returns NULL on cancel */
/* windows only - utf-16 version */
wchar_t * tinyfd_selectFolderDialogW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aDefaultPath ) ; /* NULL or L"" */
/* returns NULL on cancel */
/* windows only - utf-16 version */
wchar_t * tinyfd_colorChooserW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aDefaultHexRGB , /* NULL or L"#FF0000" */
unsigned char const aDefaultRGB [ 3 ] , /* unsigned char lDefaultRGB[3] = { 0 , 128 , 255 }; */
unsigned char aoResultRGB [ 3 ] ) ; /* unsigned char lResultRGB[3]; */
/* returns the hexcolor as a string L"#FF0000" */
/* aoResultRGB also contains the result */
/* aDefaultRGB is used only if aDefaultHexRGB is NULL */
/* aDefaultRGB and aoResultRGB can be the same array */
/* returns NULL on cancel */
# endif /*_WIN32 */
# ifdef __cplusplus
} /*extern "C"*/
# endif
# endif /* TINYFILEDIALOGS_H */
/*
________________________________________________________________________________
| ____________________________________________________________________________ |
| | | |
| | on windows : | |
| | - for UTF - 16 , use the wchar_t functions at the bottom of the header file | |
| | - _wfopen ( ) requires wchar_t | |
| | | |
| | - in tinyfiledialogs , char is UTF - 8 by default ( since v3 .6 ) | |
| | - but fopen ( ) expects MBCS ( not UTF - 8 ) | |
| | - if you want char to be MBCS : set tinyfd_winUtf8 to 0 | |
| | | |
| | - alternatively , tinyfiledialogs provides | |
| | functions to convert between UTF - 8 , UTF - 16 and MBCS | |
| | ____________________________________________________________________________ | |
| ________________________________________________________________________________ |
- This is not for ios nor android ( it works in termux though ) .
- The files can be renamed with extension " .cpp " as the code is 100 % compatible C C + +
( just comment out < < extern " C " > > in the header file )
- Windows is fully supported from XP to 10 ( maybe even older versions )
- C # & LUA via dll , see files in the folder EXTRAS
- OSX supported from 10.4 to latest ( maybe even older versions )
- Do not use " and ' as the dialogs will be displayed with a warning
instead of the title , message , etc . . .
- There ' s one file filter only , it may contain several patterns .
- If no filter description is provided ,
the list of patterns will become the description .
- On windows link against Comdlg32 . lib and Ole32 . lib
( on windows the no linking claim is a lie )
- On unix : it tries command line calls , so no such need ( NO LINKING ) .
- On unix you need one of the following :
applescript , kdialog , zenity , matedialog , shellementary , qarma , yad ,
python ( 2 or 3 ) / tkinter / python - dbus ( optional ) , Xdialog
or curses dialogs ( opens terminal if running without console ) .
- One of those is already included on most ( if not all ) desktops .
- In the absence of those it will use gdialog , gxmessage or whiptail
with a textinputbox . If nothing is found , it switches to basic console input ,
it opens a console if needed ( requires xterm + bash ) .
- for curses dialogs you must set tinyfd_allowCursesDialogs = 1
- You can query the type of dialog that will be used ( pass " tinyfd_query " as aTitle )
- String memory is preallocated statically for all the returned values .
- File and path names are tested before return , they should be valid .
- tinyfd_forceConsole = 1 ; at run time , forces dialogs into console mode .
- On windows , console mode only make sense for console applications .
- On windows , console mode is not implemented for wchar_T UTF - 16.
- Mutiple selects are not possible in console mode .
- The package dialog must be installed to run in curses dialogs in console mode .
It is already installed on most unix systems .
- On osx , the package dialog can be installed via
http : //macappstore.org/dialog or http://macports.org
- On windows , for curses dialogs console mode ,
dialog . exe should be copied somewhere on your executable path .
It can be found at the bottom of the following page :
http : //andrear.altervista.org/home/cdialog.php
*/
# ifdef TFD_IMPLEMENTATION
/* this file can be renamed with extension ".cpp" and compiled as C++.
The code is 100 % compatible C C + +
( just comment out < < extern " C " > > in the header file ) */
/*_________
/ \ tinyfiledialogs . c v3 .8 .8 [ Apr 22 , 2021 ] zlib licence
| tiny file | Unique code file created [ November 9 , 2014 ]
| dialogs | Copyright ( c ) 2014 - 2021 Guillaume Vareille http : //ysengrin.com
\ ____ ___ / http : //tinyfiledialogs.sourceforge.net
\ | git clone http : //git.code.sf.net/p/tinyfiledialogs/code tinyfd
____________________________________________
| |
| email : tinyfiledialogs at ysengrin . com |
| ____________________________________________ |
_________________________________________________________________________________
| |
| the windows only wchar_t UTF - 16 prototypes are at the bottom of the header file |
| _________________________________________________________________________________ |
_________________________________________________________
| |
| on windows : - since v3 .6 char is UTF - 8 by default |
| - if you want MBCS set tinyfd_winUtf8 to 0 |
| - functions like fopen expect MBCS |
| _________________________________________________________ |
If you like tinyfiledialogs , please upvote my stackoverflow answer
https : //stackoverflow.com/a/47651444
- License -
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
- - - - - - - - - - -
Thanks for contributions , bug corrections & thorough testing to :
- Don Heyse http : //ldglite.sf.net for bug corrections & thorough testing!
- Paul Rouget
*/
# ifndef __sun
# ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 2 /* to accept POSIX 2 in old ANSI C standards */
# endif
# endif
# if !defined(_WIN32) && ( defined(__GNUC__) || defined(__clang__) )
# if !defined(_GNU_SOURCE)
# define _GNU_SOURCE /* used only to resolve symbolic links. Can be commented out */
# endif
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
# include <sys/stat.h>
# ifdef _WIN32
# ifdef __BORLANDC__
# define _getch getch
# endif
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0500
# endif
# include <windows.h>
# include <commdlg.h>
# include <shlobj.h>
# include <conio.h>
# include <direct.h>
# define TINYFD_NOCCSUNICODE
# define SLASH "\\"
# else
# include <limits.h>
# include <unistd.h>
# include <dirent.h> /* on old systems try <sys/dir.h> instead */
# include <termios.h>
# include <sys/utsname.h>
# include <signal.h> /* on old systems try <sys/signal.h> instead */
# define SLASH " / "
# endif /* _WIN32 */
//#include "tinyfiledialogs.h"
# define MAX_PATH_OR_CMD 1024 /* _MAX_PATH or MAX_PATH */
# ifndef MAX_MULTIPLE_FILES
# define MAX_MULTIPLE_FILES 1024
# endif
# define LOW_MULTIPLE_FILES 32
char tinyfd_version [ 8 ] = " 3.8.8 " ;
/******************************************************************************************************/
/**************************************** UTF-8 on Windows ********************************************/
/******************************************************************************************************/
# ifdef _WIN32
/* if you want to use UTF-8 ( instead of the UTF-16/wchar_t functions at the end of tinyfiledialogs.h )
Make sure your code is really prepared for UTF - 8 ( on windows , functions like fopen ( ) expect MBCS and not UTF - 8 ) */
int tinyfd_winUtf8 = 1 ; /* on windows char strings can be 1:UTF-8(default) or 0:MBCS */
/* for MBCS change this to 0, here or in your code */
# endif
/******************************************************************************************************/
/******************************************************************************************************/
/******************************************************************************************************/
int tinyfd_verbose = 0 ; /* on unix: prints the command line calls */
int tinyfd_silent = 1 ; /* 1 (default) or 0 : on unix, hide errors and warnings from called dialogs */
/* Curses dialogs are difficult to use, on windows they are only ascii and uses the unix backslah */
int tinyfd_allowCursesDialogs = 0 ; /* 0 (default) or 1 */
int tinyfd_forceConsole = 0 ; /* 0 (default) or 1 */
/* for unix & windows: 0 (graphic mode) or 1 (console mode).
0 : try to use a graphic solution , if it fails then it uses console mode .
1 : forces all dialogs into console mode even when the X server is present .
it can use the package dialog or dialog . exe .
on windows it only make sense for console applications */
int tinyfd_assumeGraphicDisplay = 0 ; /* 0 (default) or 1 */
/* some systems don't set the environment variable DISPLAY even when a graphic display is present.
set this to 1 to tell tinyfiledialogs to assume the existence of a graphic display */
char tinyfd_response [ 1024 ] ;
/* if you pass "tinyfd_query" as aTitle,
the functions will not display the dialogs
but and return 0 for console mode , 1 for graphic mode .
tinyfd_response is then filled with the retain solution .
possible values for tinyfd_response are ( all lowercase )
for graphic mode :
windows_wchar windows applescript kdialog zenity zenity3 matedialog
shellementary qarma yad python2 - tkinter python3 - tkinter python - dbus
perl - dbus gxmessage gmessage xmessage xdialog gdialog
for console mode :
dialog whiptail basicinput no_solution */
static int gWarningDisplayed = 0 ;
static char gTitle [ ] = " missing software! (we will try basic console input) " ;
# ifdef _WIN32
char tinyfd_needs [ ] = " \
___________ \ n \
/ \ \ \ n \
| tiny file | \ n \
| dialogs | \ n \
\ \ _____ ____ / \ n \
\ \ | \
\ ntiny file dialogs on Windows needs : \
\ n a graphic display \
\ nor dialog . exe ( curses console mode ) \
\ nor a console for basic input " ;
# else
char tinyfd_needs [ ] = " \
___________ \ n \
/ \ \ \ n \
| tiny file | \ n \
| dialogs | \ n \
\ \ _____ ____ / \ n \
\ \ | \
\ ntiny file dialogs on UNIX needs : \
\ n applescript or kdialog or yad or Xdialog \
\ nor zenity ( or matedialog or shellementary or qarma ) \
\ nor python ( 2 or 3 ) + tkinter + python - dbus ( optional ) \
\ nor dialog ( opens console if needed ) \
\ nor xterm + bash ( opens console for basic input ) \
\ nor existing console for basic input " ;
# endif
# ifdef _MSC_VER
# pragma warning(disable:4996) /* allows usage of strncpy, strcpy, strcat, sprintf, fopen */
# pragma warning(disable:4100) /* allows usage of strncpy, strcpy, strcat, sprintf, fopen */
# pragma warning(disable:4706) /* allows usage of strncpy, strcpy, strcat, sprintf, fopen */
# endif
static int getenvDISPLAY ( void )
{
return tinyfd_assumeGraphicDisplay | | getenv ( " DISPLAY " ) ;
}
static char * getCurDir ( void )
{
static char lCurDir [ MAX_PATH_OR_CMD ] ;
return getcwd ( lCurDir , sizeof ( lCurDir ) ) ;
}
static char * getPathWithoutFinalSlash (
char * aoDestination , /* make sure it is allocated, use _MAX_PATH */
char const * aSource ) /* aoDestination and aSource can be the same */
{
char const * lTmp ;
if ( aSource )
{
lTmp = strrchr ( aSource , ' / ' ) ;
if ( ! lTmp )
{
lTmp = strrchr ( aSource , ' \\ ' ) ;
}
if ( lTmp )
{
strncpy ( aoDestination , aSource , lTmp - aSource ) ;
aoDestination [ lTmp - aSource ] = ' \0 ' ;
}
else
{
* aoDestination = ' \0 ' ;
}
}
else
{
* aoDestination = ' \0 ' ;
}
return aoDestination ;
}
static char * getLastName (
char * aoDestination , /* make sure it is allocated */
char const * aSource )
{
/* copy the last name after '/' or '\' */
char const * lTmp ;
if ( aSource )
{
lTmp = strrchr ( aSource , ' / ' ) ;
if ( ! lTmp )
{
lTmp = strrchr ( aSource , ' \\ ' ) ;
}
if ( lTmp )
{
strcpy ( aoDestination , lTmp + 1 ) ;
}
else
{
strcpy ( aoDestination , aSource ) ;
}
}
else
{
* aoDestination = ' \0 ' ;
}
return aoDestination ;
}
static void ensureFinalSlash ( char * aioString )
{
if ( aioString & & strlen ( aioString ) )
{
char * lastcar = aioString + strlen ( aioString ) - 1 ;
if ( strncmp ( lastcar , SLASH , 1 ) )
{
strcat ( lastcar , SLASH ) ;
}
}
}
static void Hex2RGB ( char const aHexRGB [ 8 ] , unsigned char aoResultRGB [ 3 ] )
{
char lColorChannel [ 8 ] ;
if ( aoResultRGB )
{
if ( aHexRGB )
{
strcpy ( lColorChannel , aHexRGB ) ;
aoResultRGB [ 2 ] = ( unsigned char ) strtoul ( lColorChannel + 5 , NULL , 16 ) ;
lColorChannel [ 5 ] = ' \0 ' ;
aoResultRGB [ 1 ] = ( unsigned char ) strtoul ( lColorChannel + 3 , NULL , 16 ) ;
lColorChannel [ 3 ] = ' \0 ' ;
aoResultRGB [ 0 ] = ( unsigned char ) strtoul ( lColorChannel + 1 , NULL , 16 ) ;
/* printf("%d %d %d\n", aoResultRGB[0], aoResultRGB[1], aoResultRGB[2]); */
}
else
{
aoResultRGB [ 0 ] = 0 ;
aoResultRGB [ 1 ] = 0 ;
aoResultRGB [ 2 ] = 0 ;
}
}
}
static void RGB2Hex ( unsigned char const aRGB [ 3 ] , char aoResultHexRGB [ 8 ] )
{
if ( aoResultHexRGB )
{
if ( aRGB )
{
# if (defined(__cplusplus ) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__clang__)
sprintf ( aoResultHexRGB , " #%02hhx%02hhx%02hhx " , aRGB [ 0 ] , aRGB [ 1 ] , aRGB [ 2 ] ) ;
# else
sprintf ( aoResultHexRGB , " #%02hx%02hx%02hx " , aRGB [ 0 ] , aRGB [ 1 ] , aRGB [ 2 ] ) ;
# endif
/*printf("aoResultHexRGB %s\n", aoResultHexRGB);*/
}
else
{
aoResultHexRGB [ 0 ] = 0 ;
aoResultHexRGB [ 1 ] = 0 ;
aoResultHexRGB [ 2 ] = 0 ;
}
}
}
void tfd_replaceSubStr ( char const * aSource , char const * aOldSubStr ,
char const * aNewSubStr , char * aoDestination )
{
char const * pOccurence ;
char const * p ;
char const * lNewSubStr = " " ;
size_t lOldSubLen = strlen ( aOldSubStr ) ;
if ( ! aSource )
{
* aoDestination = ' \0 ' ;
return ;
}
if ( ! aOldSubStr )
{
strcpy ( aoDestination , aSource ) ;
return ;
}
if ( aNewSubStr )
{
lNewSubStr = aNewSubStr ;
}
p = aSource ;
* aoDestination = ' \0 ' ;
while ( ( pOccurence = strstr ( p , aOldSubStr ) ) ! = NULL )
{
strncat ( aoDestination , p , pOccurence - p ) ;
strcat ( aoDestination , lNewSubStr ) ;
p = pOccurence + lOldSubLen ;
}
strcat ( aoDestination , p ) ;
}
static int filenameValid ( char const * aFileNameWithoutPath )
{
if ( ! aFileNameWithoutPath
| | ! strlen ( aFileNameWithoutPath )
| | strpbrk ( aFileNameWithoutPath , " \\ /:*? \" <>| " ) )
{
return 0 ;
}
return 1 ;
}
# ifndef _WIN32
static int fileExists ( char const * aFilePathAndName )
{
FILE * lIn ;
if ( ! aFilePathAndName | | ! strlen ( aFilePathAndName ) )
{
return 0 ;
}
lIn = fopen ( aFilePathAndName , " r " ) ;
if ( ! lIn )
{
return 0 ;
}
fclose ( lIn ) ;
return 1 ;
}
# endif
static void wipefile ( char const * aFilename )
{
int i ;
struct stat st ;
FILE * lIn ;
if ( stat ( aFilename , & st ) = = 0 )
{
if ( ( lIn = fopen ( aFilename , " w " ) ) )
{
for ( i = 0 ; i < st . st_size ; i + + )
{
fputc ( ' A ' , lIn ) ;
}
fclose ( lIn ) ;
}
}
}
int tfd_quoteDetected ( char const * aString )
{
char const * p ;
if ( ! aString ) return 0 ;
p = aString ;
while ( ( p = strchr ( p , ' \' ' ) ) )
{
return 1 ;
}
p = aString ;
while ( ( p = strchr ( p , ' \" ' ) ) )
{
return 1 ;
}
return 0 ;
}
char const * tinyfd_getGlobalChar ( char const * aCharVariableName ) /* to be called from C# (you don't need this in C or C++) */
{
if ( ! aCharVariableName | | ! strlen ( aCharVariableName ) ) return NULL ;
else if ( ! strcmp ( aCharVariableName , " tinyfd_version " ) ) return tinyfd_version ;
else if ( ! strcmp ( aCharVariableName , " tinyfd_needs " ) ) return tinyfd_needs ;
else if ( ! strcmp ( aCharVariableName , " tinyfd_response " ) ) return tinyfd_response ;
else return NULL ;
}
int tinyfd_getGlobalInt ( char const * aIntVariableName ) /* to be called from C# (you don't need this in C or C++) */
{
if ( ! aIntVariableName | | ! strlen ( aIntVariableName ) ) return - 1 ;
else if ( ! strcmp ( aIntVariableName , " tinyfd_verbose " ) ) return tinyfd_verbose ;
else if ( ! strcmp ( aIntVariableName , " tinyfd_silent " ) ) return tinyfd_silent ;
else if ( ! strcmp ( aIntVariableName , " tinyfd_allowCursesDialogs " ) ) return tinyfd_allowCursesDialogs ;
else if ( ! strcmp ( aIntVariableName , " tinyfd_forceConsole " ) ) return tinyfd_forceConsole ;
else if ( ! strcmp ( aIntVariableName , " tinyfd_assumeGraphicDisplay " ) ) return tinyfd_assumeGraphicDisplay ;
# ifdef _WIN32
else if ( ! strcmp ( aIntVariableName , " tinyfd_winUtf8 " ) ) return tinyfd_winUtf8 ;
# endif
else return - 1 ;
}
int tinyfd_setGlobalInt ( char const * aIntVariableName , int aValue ) /* to be called from C# (you don't need this in C or C++) */
{
if ( ! aIntVariableName | | ! strlen ( aIntVariableName ) ) return - 1 ;
else if ( ! strcmp ( aIntVariableName , " tinyfd_verbose " ) ) { tinyfd_verbose = aValue ; return tinyfd_verbose ; }
else if ( ! strcmp ( aIntVariableName , " tinyfd_silent " ) ) { tinyfd_silent = aValue ; return tinyfd_silent ; }
else if ( ! strcmp ( aIntVariableName , " tinyfd_allowCursesDialogs " ) ) { tinyfd_allowCursesDialogs = aValue ; return tinyfd_allowCursesDialogs ; }
else if ( ! strcmp ( aIntVariableName , " tinyfd_forceConsole " ) ) { tinyfd_forceConsole = aValue ; return tinyfd_forceConsole ; }
else if ( ! strcmp ( aIntVariableName , " tinyfd_assumeGraphicDisplay " ) ) { tinyfd_assumeGraphicDisplay = aValue ; return tinyfd_assumeGraphicDisplay ; }
# ifdef _WIN32
else if ( ! strcmp ( aIntVariableName , " tinyfd_winUtf8 " ) ) { tinyfd_winUtf8 = aValue ; return tinyfd_winUtf8 ; }
# endif
else return - 1 ;
}
# ifdef _WIN32
static int powershellPresent ( void )
{ /*only on vista and above (or installed on xp)*/
static int lPowershellPresent = - 1 ;
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
char const * lString = " powershell.exe " ;
if ( lPowershellPresent < 0 )
{
if ( ! ( lIn = _popen ( " where powershell.exe " , " r " ) ) )
{
lPowershellPresent = 0 ;
return 0 ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{
}
_pclose ( lIn ) ;
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
if ( strcmp ( lBuff + strlen ( lBuff ) - strlen ( lString ) , lString ) )
{
lPowershellPresent = 0 ;
}
else
{
lPowershellPresent = 1 ;
}
}
return lPowershellPresent ;
}
static int windowsVersion ( void )
{
# if !defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)
typedef LONG NTSTATUS ;
typedef NTSTATUS ( WINAPI * RtlGetVersionPtr ) ( PRTL_OSVERSIONINFOW ) ;
HMODULE hMod ;
RtlGetVersionPtr lFxPtr ;
RTL_OSVERSIONINFOW lRovi = { 0 } ;
hMod = GetModuleHandleW ( L " ntdll.dll " ) ;
if ( hMod ) {
lFxPtr = ( RtlGetVersionPtr ) GetProcAddress ( hMod , " RtlGetVersion " ) ;
if ( lFxPtr )
{
lRovi . dwOSVersionInfoSize = sizeof ( lRovi ) ;
if ( ! lFxPtr ( & lRovi ) )
{
return lRovi . dwMajorVersion ;
}
}
}
# endif
if ( powershellPresent ( ) ) return 6 ; /*minimum is vista or installed on xp*/
return 0 ;
}
static void replaceChr ( char * aString , char aOldChr , char aNewChr )
{
char * p ;
if ( ! aString ) return ;
if ( aOldChr = = aNewChr ) return ;
p = aString ;
while ( ( p = strchr ( p , aOldChr ) ) )
{
* p = aNewChr ;
p + + ;
}
return ;
}
# if !defined(WC_ERR_INVALID_CHARS)
/* undefined prior to Vista, so not yet in MINGW header file */
# define WC_ERR_INVALID_CHARS 0x00000000 /* 0x00000080 for MINGW maybe ? */
# endif
static int sizeUtf16From8 ( char const * aUtf8string )
{
return MultiByteToWideChar ( CP_UTF8 , MB_ERR_INVALID_CHARS ,
aUtf8string , - 1 , NULL , 0 ) ;
}
static int sizeUtf16FromMbcs ( char const * aMbcsString )
{
return MultiByteToWideChar ( CP_ACP , MB_ERR_INVALID_CHARS ,
aMbcsString , - 1 , NULL , 0 ) ;
}
static int sizeUtf8 ( wchar_t const * aUtf16string )
{
return WideCharToMultiByte ( CP_UTF8 , WC_ERR_INVALID_CHARS ,
aUtf16string , - 1 , NULL , 0 , NULL , NULL ) ;
}
static int sizeMbcs ( wchar_t const * aMbcsString )
{
int lRes = WideCharToMultiByte ( CP_ACP , 0 ,
aMbcsString , - 1 , NULL , 0 , NULL , NULL ) ;
/* DWORD licic = GetLastError(); */
return lRes ;
}
wchar_t * tinyfd_mbcsTo16 ( char const * aMbcsString )
{
static wchar_t * lMbcsString = NULL ;
int lSize ;
free ( lMbcsString ) ;
if ( ! aMbcsString ) { lMbcsString = NULL ; return NULL ; }
lSize = sizeUtf16FromMbcs ( aMbcsString ) ;
if ( lSize )
{
lMbcsString = ( wchar_t * ) malloc ( lSize * sizeof ( wchar_t ) ) ;
lSize = MultiByteToWideChar ( CP_ACP , 0 , aMbcsString , - 1 , lMbcsString , lSize ) ;
}
else wcscpy ( lMbcsString , L " " ) ;
return lMbcsString ;
}
wchar_t * tinyfd_utf8to16 ( char const * aUtf8string )
{
static wchar_t * lUtf16string = NULL ;
int lSize ;
free ( lUtf16string ) ;
if ( ! aUtf8string ) { lUtf16string = NULL ; return NULL ; }
lSize = sizeUtf16From8 ( aUtf8string ) ;
if ( lSize )
{
lUtf16string = ( wchar_t * ) malloc ( lSize * sizeof ( wchar_t ) ) ;
lSize = MultiByteToWideChar ( CP_UTF8 , MB_ERR_INVALID_CHARS ,
aUtf8string , - 1 , lUtf16string , lSize ) ;
return lUtf16string ;
}
else
{
/* let's try mbcs anyway */
lUtf16string = NULL ;
return tinyfd_mbcsTo16 ( aUtf8string ) ;
}
}
char * tinyfd_utf16toMbcs ( wchar_t const * aUtf16string )
{
static char * lMbcsString = NULL ;
int lSize ;
free ( lMbcsString ) ;
if ( ! aUtf16string ) { lMbcsString = NULL ; return NULL ; }
lSize = sizeMbcs ( aUtf16string ) ;
if ( lSize )
{
lMbcsString = ( char * ) malloc ( lSize ) ;
lSize = WideCharToMultiByte ( CP_ACP , 0 , aUtf16string , - 1 , lMbcsString , lSize , NULL , NULL ) ;
}
else strcpy ( lMbcsString , " " ) ;
return lMbcsString ;
}
char * tinyfd_utf8toMbcs ( char const * aUtf8string )
{
wchar_t const * lUtf16string ;
lUtf16string = tinyfd_utf8to16 ( aUtf8string ) ;
return tinyfd_utf16toMbcs ( lUtf16string ) ;
}
char * tinyfd_utf16to8 ( wchar_t const * aUtf16string )
{
static char * lUtf8string = NULL ;
int lSize ;
free ( lUtf8string ) ;
if ( ! aUtf16string ) { lUtf8string = NULL ; return NULL ; }
lSize = sizeUtf8 ( aUtf16string ) ;
if ( lSize )
{
lUtf8string = ( char * ) malloc ( lSize ) ;
lSize = WideCharToMultiByte ( CP_UTF8 , WC_ERR_INVALID_CHARS , aUtf16string , - 1 , lUtf8string , lSize , NULL , NULL ) ;
}
else strcpy ( lUtf8string , " " ) ;
return lUtf8string ;
}
char * tinyfd_mbcsTo8 ( char const * aMbcsString )
{
wchar_t const * lUtf16string ;
lUtf16string = tinyfd_mbcsTo16 ( aMbcsString ) ;
return tinyfd_utf16to8 ( lUtf16string ) ;
}
void tinyfd_beep ( void )
{
if ( windowsVersion ( ) > 5 ) Beep ( 440 , 300 ) ;
else MessageBeep ( - 1 ) ;
}
static void wipefileW ( wchar_t const * aFilename )
{
int i ;
FILE * lIn ;
# if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3)
struct _stat st ;
if ( _wstat ( aFilename , & st ) = = 0 )
# else
struct __stat64 st ;
if ( _wstat64 ( aFilename , & st ) = = 0 )
# endif
{
if ( ( lIn = _wfopen ( aFilename , L " w " ) ) )
{
for ( i = 0 ; i < st . st_size ; i + + )
{
fputc ( ' A ' , lIn ) ;
}
fclose ( lIn ) ;
}
}
}
static wchar_t * getPathWithoutFinalSlashW (
wchar_t * aoDestination , /* make sure it is allocated, use _MAX_PATH */
wchar_t const * aSource ) /* aoDestination and aSource can be the same */
{
wchar_t const * lTmp ;
if ( aSource )
{
lTmp = wcsrchr ( aSource , L ' / ' ) ;
if ( ! lTmp )
{
lTmp = wcsrchr ( aSource , L ' \\ ' ) ;
}
if ( lTmp )
{
wcsncpy ( aoDestination , aSource , lTmp - aSource ) ;
aoDestination [ lTmp - aSource ] = L ' \0 ' ;
}
else
{
* aoDestination = L ' \0 ' ;
}
}
else
{
* aoDestination = L ' \0 ' ;
}
return aoDestination ;
}
static wchar_t * getLastNameW (
wchar_t * aoDestination , /* make sure it is allocated */
wchar_t const * aSource )
{
/* copy the last name after '/' or '\' */
wchar_t const * lTmp ;
if ( aSource )
{
lTmp = wcsrchr ( aSource , L ' / ' ) ;
if ( ! lTmp )
{
lTmp = wcsrchr ( aSource , L ' \\ ' ) ;
}
if ( lTmp )
{
wcscpy ( aoDestination , lTmp + 1 ) ;
}
else
{
wcscpy ( aoDestination , aSource ) ;
}
}
else
{
* aoDestination = L ' \0 ' ;
}
return aoDestination ;
}
static void Hex2RGBW ( wchar_t const aHexRGB [ 8 ] , unsigned char aoResultRGB [ 3 ] )
{
wchar_t lColorChannel [ 8 ] ;
if ( aoResultRGB )
{
if ( aHexRGB )
{
wcscpy ( lColorChannel , aHexRGB ) ;
aoResultRGB [ 2 ] = ( unsigned char ) wcstoul ( lColorChannel + 5 , NULL , 16 ) ;
lColorChannel [ 5 ] = ' \0 ' ;
aoResultRGB [ 1 ] = ( unsigned char ) wcstoul ( lColorChannel + 3 , NULL , 16 ) ;
lColorChannel [ 3 ] = ' \0 ' ;
aoResultRGB [ 0 ] = ( unsigned char ) wcstoul ( lColorChannel + 1 , NULL , 16 ) ;
/* printf("%d %d %d\n", aoResultRGB[0], aoResultRGB[1], aoResultRGB[2]); */
}
else
{
aoResultRGB [ 0 ] = 0 ;
aoResultRGB [ 1 ] = 0 ;
aoResultRGB [ 2 ] = 0 ;
}
}
}
static void RGB2HexW ( unsigned char const aRGB [ 3 ] , wchar_t aoResultHexRGB [ 8 ] )
{
# if (defined(__cplusplus ) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__clang__)
wchar_t const * const lPrintFormat = L " #%02hhx%02hhx%02hhx " ;
# else
wchar_t const * const lPrintFormat = L " #%02hx%02hx%02hx " ;
# endif
if ( aoResultHexRGB )
{
if ( aRGB )
{
/* wprintf(L"aoResultHexRGB %s\n", aoResultHexRGB); */
# if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
swprintf ( aoResultHexRGB , 8 , lPrintFormat , aRGB [ 0 ] , aRGB [ 1 ] , aRGB [ 2 ] ) ;
# else
swprintf ( aoResultHexRGB , lPrintFormat , aRGB [ 0 ] , aRGB [ 1 ] , aRGB [ 2 ] ) ;
# endif
}
else
{
aoResultHexRGB [ 0 ] = 0 ;
aoResultHexRGB [ 1 ] = 0 ;
aoResultHexRGB [ 2 ] = 0 ;
}
}
}
static int dirExists ( char const * aDirPath )
{
# if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3)
struct _stat lInfo ;
# else
struct __stat64 lInfo ;
# endif
wchar_t * lTmpWChar ;
int lStatRet ;
size_t lDirLen ;
if ( ! aDirPath )
return 0 ;
lDirLen = strlen ( aDirPath ) ;
if ( ! lDirLen )
return 1 ;
if ( ( lDirLen = = 2 ) & & ( aDirPath [ 1 ] = = ' : ' ) )
return 1 ;
if ( tinyfd_winUtf8 )
{
lTmpWChar = tinyfd_utf8to16 ( aDirPath ) ;
# if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3)
lStatRet = _wstat ( lTmpWChar , & lInfo ) ;
# else
lStatRet = _wstat64 ( lTmpWChar , & lInfo ) ;
# endif
if ( lStatRet ! = 0 )
return 0 ;
else if ( lInfo . st_mode & S_IFDIR )
return 1 ;
else
return 0 ;
}
# if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3)
else if ( _stat ( aDirPath , & lInfo ) ! = 0 )
# else
else if ( _stat64 ( aDirPath , & lInfo ) ! = 0 )
# endif
return 0 ;
else if ( lInfo . st_mode & S_IFDIR )
return 1 ;
else
return 0 ;
}
static int fileExists ( char const * aFilePathAndName )
{
# if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3)
struct _stat lInfo ;
# else
struct __stat64 lInfo ;
# endif
wchar_t * lTmpWChar ;
int lStatRet ;
FILE * lIn ;
if ( ! aFilePathAndName | | ! strlen ( aFilePathAndName ) )
{
return 0 ;
}
if ( tinyfd_winUtf8 )
{
lTmpWChar = tinyfd_utf8to16 ( aFilePathAndName ) ;
# if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3)
lStatRet = _wstat ( lTmpWChar , & lInfo ) ;
# else
lStatRet = _wstat64 ( lTmpWChar , & lInfo ) ;
# endif
if ( lStatRet ! = 0 )
return 0 ;
else if ( lInfo . st_mode & _S_IFREG )
return 1 ;
else
return 0 ;
}
else
{
lIn = fopen ( aFilePathAndName , " r " ) ;
if ( ! lIn )
{
return 0 ;
}
fclose ( lIn ) ;
return 1 ;
}
}
static void replaceWchar ( wchar_t * aString ,
wchar_t aOldChr ,
wchar_t aNewChr )
{
wchar_t * p ;
if ( ! aString )
{
return ;
}
if ( aOldChr = = aNewChr )
{
return ;
}
p = aString ;
while ( ( p = wcsrchr ( p , aOldChr ) ) )
{
* p = aNewChr ;
# ifdef TINYFD_NOCCSUNICODE
p + + ;
# endif
p + + ;
}
return ;
}
static int quoteDetectedW ( wchar_t const * aString )
{
wchar_t const * p ;
if ( ! aString ) return 0 ;
p = aString ;
while ( ( p = wcsrchr ( p , L ' \' ' ) ) )
{
return 1 ;
}
p = aString ;
while ( ( p = wcsrchr ( p , L ' \" ' ) ) )
{
return 1 ;
}
return 0 ;
}
# endif /* _WIN32 */
/* source and destination can be the same or ovelap*/
static char * ensureFilesExist ( char * aDestination ,
char const * aSourcePathsAndNames )
{
char * lDestination = aDestination ;
char const * p ;
char const * p2 ;
size_t lLen ;
if ( ! aSourcePathsAndNames )
{
return NULL ;
}
lLen = strlen ( aSourcePathsAndNames ) ;
if ( ! lLen )
{
return NULL ;
}
p = aSourcePathsAndNames ;
while ( ( p2 = strchr ( p , ' | ' ) ) ! = NULL )
{
lLen = p2 - p ;
memmove ( lDestination , p , lLen ) ;
lDestination [ lLen ] = ' \0 ' ;
if ( fileExists ( lDestination ) )
{
lDestination + = lLen ;
* lDestination = ' | ' ;
lDestination + + ;
}
p = p2 + 1 ;
}
if ( fileExists ( p ) )
{
lLen = strlen ( p ) ;
memmove ( lDestination , p , lLen ) ;
lDestination [ lLen ] = ' \0 ' ;
}
else
{
* ( lDestination - 1 ) = ' \0 ' ;
}
return aDestination ;
}
# ifdef _WIN32
static int __stdcall EnumThreadWndProc ( HWND hwnd , LPARAM lParam )
{
wchar_t lTitleName [ MAX_PATH ] ;
GetWindowTextW ( hwnd , lTitleName , MAX_PATH ) ;
/* wprintf(L"lTitleName %ls \n", lTitleName); */
if ( wcscmp ( L " tinyfiledialogsTopWindow " , lTitleName ) = = 0 )
{
SetWindowPos ( hwnd , HWND_TOPMOST , 0 , 0 , 0 , 0 , SWP_NOMOVE | SWP_NOSIZE ) ;
return 0 ;
}
return 1 ;
}
static void hiddenConsoleW ( wchar_t const * aString , wchar_t const * aDialogTitle , int aInFront )
{
STARTUPINFOW StartupInfo ;
PROCESS_INFORMATION ProcessInfo ;
if ( ! aString | | ! wcslen ( aString ) ) return ;
memset ( & StartupInfo , 0 , sizeof ( StartupInfo ) ) ;
StartupInfo . cb = sizeof ( STARTUPINFOW ) ;
StartupInfo . dwFlags = STARTF_USESHOWWINDOW ;
StartupInfo . wShowWindow = SW_HIDE ;
if ( ! CreateProcessW ( NULL , ( LPWSTR ) aString , NULL , NULL , FALSE ,
CREATE_NEW_CONSOLE , NULL , NULL ,
& StartupInfo , & ProcessInfo ) )
{
return ; /* GetLastError(); */
}
WaitForInputIdle ( ProcessInfo . hProcess , INFINITE ) ;
if ( aInFront )
{
while ( EnumWindows ( EnumThreadWndProc , ( LPARAM ) NULL ) ) { }
SetWindowTextW ( GetForegroundWindow ( ) , aDialogTitle ) ;
}
WaitForSingleObject ( ProcessInfo . hProcess , INFINITE ) ;
CloseHandle ( ProcessInfo . hThread ) ;
CloseHandle ( ProcessInfo . hProcess ) ;
}
int tinyfd_messageBoxW (
wchar_t const * aTitle , /* NULL or "" */
wchar_t const * aMessage , /* NULL or "" may contain \n and \t */
wchar_t const * aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
wchar_t const * aIconType , /* "info" "warning" "error" "question" */
int aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
{
int lBoxReturnValue ;
UINT aCode ;
if ( aTitle & & ! wcscmp ( aTitle , L " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows_wchar " ) ; return 1 ; }
if ( quoteDetectedW ( aTitle ) ) return tinyfd_messageBoxW ( L " INVALID TITLE WITH QUOTES " , aMessage , aDialogType , aIconType , aDefaultButton ) ;
if ( quoteDetectedW ( aMessage ) ) return tinyfd_messageBoxW ( aTitle , L " INVALID MESSAGE WITH QUOTES " , aDialogType , aIconType , aDefaultButton ) ;
if ( aIconType & & ! wcscmp ( L " warning " , aIconType ) )
{
aCode = MB_ICONWARNING ;
}
else if ( aIconType & & ! wcscmp ( L " error " , aIconType ) )
{
aCode = MB_ICONERROR ;
}
else if ( aIconType & & ! wcscmp ( L " question " , aIconType ) )
{
aCode = MB_ICONQUESTION ;
}
else
{
aCode = MB_ICONINFORMATION ;
}
if ( aDialogType & & ! wcscmp ( L " okcancel " , aDialogType ) )
{
aCode + = MB_OKCANCEL ;
if ( ! aDefaultButton )
{
aCode + = MB_DEFBUTTON2 ;
}
}
else if ( aDialogType & & ! wcscmp ( L " yesno " , aDialogType ) )
{
aCode + = MB_YESNO ;
if ( ! aDefaultButton )
{
aCode + = MB_DEFBUTTON2 ;
}
}
else
{
aCode + = MB_OK ;
}
aCode + = MB_TOPMOST ;
lBoxReturnValue = MessageBoxW ( GetForegroundWindow ( ) , aMessage , aTitle , aCode ) ;
if ( ( ( aDialogType
& & wcscmp ( L " okcancel " , aDialogType )
& & wcscmp ( L " yesno " , aDialogType ) ) )
| | ( lBoxReturnValue = = IDOK )
| | ( lBoxReturnValue = = IDYES ) )
{
return 1 ;
}
else
{
return 0 ;
}
}
/* return has only meaning for tinyfd_query */
int tinyfd_notifyPopupW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aMessage , /* NULL or L"" may contain \n \t */
wchar_t const * aIconType ) /* L"info" L"warning" L"error" */
{
wchar_t * lDialogString ;
size_t lTitleLen ;
size_t lMessageLen ;
size_t lDialogStringLen ;
if ( aTitle & & ! wcscmp ( aTitle , L " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows_wchar " ) ; return 1 ; }
if ( quoteDetectedW ( aTitle ) ) return tinyfd_notifyPopupW ( L " INVALID TITLE WITH QUOTES " , aMessage , aIconType ) ;
if ( quoteDetectedW ( aMessage ) ) return tinyfd_notifyPopupW ( aTitle , L " INVALID MESSAGE WITH QUOTES " , aIconType ) ;
lTitleLen = aTitle ? wcslen ( aTitle ) : 0 ;
lMessageLen = aMessage ? wcslen ( aMessage ) : 0 ;
lDialogStringLen = 3 * MAX_PATH_OR_CMD + lTitleLen + lMessageLen ;
lDialogString = ( wchar_t * ) malloc ( 2 * lDialogStringLen ) ;
if ( ! lDialogString ) return 0 ;
wcscpy ( lDialogString , L " powershell.exe -command \" \
function Show - BalloonTip { \
[ cmdletbinding ( ) ] \
param ( \
[ string ] $ Title = ' ' , \
[ string ] $ Message = ' ' , \
[ ValidateSet ( ' info ' , ' warning ' , ' error ' ) ] \
[ string ] $ IconType = ' info ' ) ; \
[ system . Reflection . Assembly ] : : LoadWithPartialName ( ' System . Windows . Forms ' ) | Out - Null ; \
$ balloon = New - Object System . Windows . Forms . NotifyIcon ; \
$ path = Get - Process - id $ pid | Select - Object - ExpandProperty Path ; \
$ icon = [ System . Drawing . Icon ] : : ExtractAssociatedIcon ( $ path ) ; " );
wcscat ( lDialogString , L " \
$ balloon . Icon = $ icon ; \
$ balloon . BalloonTipIcon = $ IconType ; \
$ balloon . BalloonTipText = $ Message ; \
$ balloon . BalloonTipTitle = $ Title ; \
$ balloon . Text = ' tinyfiledialogs ' ; \
$ balloon . Visible = $ true ; \
$ balloon . ShowBalloonTip ( 5000 ) } ; \
Show - BalloonTip " );
if ( aTitle & & wcslen ( aTitle ) )
{
wcscat ( lDialogString , L " -Title ' " ) ;
wcscat ( lDialogString , aTitle ) ;
wcscat ( lDialogString , L " ' " ) ;
}
if ( aMessage & & wcslen ( aMessage ) )
{
wcscat ( lDialogString , L " -Message ' " ) ;
wcscat ( lDialogString , aMessage ) ;
wcscat ( lDialogString , L " ' " ) ;
}
if ( aMessage & & wcslen ( aIconType ) )
{
wcscat ( lDialogString , L " -IconType ' " ) ;
wcscat ( lDialogString , aIconType ) ;
wcscat ( lDialogString , L " ' " ) ;
}
wcscat ( lDialogString , L " \" " ) ;
/* wprintf ( L"lDialogString: %ls\n" , lDialogString ) ; */
hiddenConsoleW ( lDialogString , aTitle , 0 ) ;
free ( lDialogString ) ;
return 1 ;
}
wchar_t * tinyfd_inputBoxW (
wchar_t const * aTitle , /* NULL or L"" */
wchar_t const * aMessage , /* NULL or L"" (\n and \t have no effect) */
wchar_t const * aDefaultInput ) /* L"" , if NULL it's a passwordBox */
{
static wchar_t lBuff [ MAX_PATH_OR_CMD ] ;
wchar_t * lDialogString ;
FILE * lIn ;
FILE * lFile ;
int lResult ;
size_t lTitleLen ;
size_t lMessageLen ;
size_t lDialogStringLen ;
if ( aTitle & & ! wcscmp ( aTitle , L " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows_wchar " ) ; return ( wchar_t * ) 1 ; }
if ( quoteDetectedW ( aTitle ) ) return tinyfd_inputBoxW ( L " INVALID TITLE WITH QUOTES " , aMessage , aDefaultInput ) ;
if ( quoteDetectedW ( aMessage ) ) return tinyfd_inputBoxW ( aTitle , L " INVALID MESSAGE WITH QUOTES " , aDefaultInput ) ;
if ( quoteDetectedW ( aDefaultInput ) ) return tinyfd_inputBoxW ( aTitle , aMessage , L " INVALID DEFAULT_INPUT WITH QUOTES " ) ;
lTitleLen = aTitle ? wcslen ( aTitle ) : 0 ;
lMessageLen = aMessage ? wcslen ( aMessage ) : 0 ;
lDialogStringLen = 3 * MAX_PATH_OR_CMD + lTitleLen + lMessageLen ;
lDialogString = ( wchar_t * ) malloc ( 2 * lDialogStringLen ) ;
if ( aDefaultInput )
{
swprintf ( lDialogString ,
# if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
lDialogStringLen ,
# endif
L " %ls \\ tinyfd.vbs " , _wgetenv ( L " TEMP " ) ) ;
}
else
{
swprintf ( lDialogString ,
# if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
lDialogStringLen ,
# endif
L " %ls \\ tinyfd.hta " , _wgetenv ( L " TEMP " ) ) ;
}
lIn = _wfopen ( lDialogString , L " w " ) ;
if ( ! lIn )
{
free ( lDialogString ) ;
return NULL ;
}
if ( aDefaultInput )
{
wcscpy ( lDialogString , L " Dim result:result=InputBox( \" " ) ;
if ( aMessage & & wcslen ( aMessage ) )
{
wcscpy ( lBuff , aMessage ) ;
replaceWchar ( lBuff , L ' \n ' , L ' ' ) ;
wcscat ( lDialogString , lBuff ) ;
}
wcscat ( lDialogString , L " \" , \" tinyfiledialogsTopWindow \" , \" " ) ;
if ( aDefaultInput & & wcslen ( aDefaultInput ) )
{
wcscpy ( lBuff , aDefaultInput ) ;
replaceWchar ( lBuff , L ' \n ' , L ' ' ) ;
wcscat ( lDialogString , lBuff ) ;
}
wcscat ( lDialogString , L " \" ):If IsEmpty(result) then:WScript.Echo 0 " ) ;
wcscat ( lDialogString , L " :Else: WScript.Echo \" 1 \" & result : End If " ) ;
}
else
{
wcscpy ( lDialogString , L " \n \
< html > \ n \
< head > \ n \
< title > " );
wcscat ( lDialogString , L " tinyfiledialogsTopWindow " ) ;
wcscat ( lDialogString , L " </title> \n \
< HTA : APPLICATION \ n \
ID = ' tinyfdHTA ' \ n \
APPLICATIONNAME = ' tinyfd_inputBox ' \ n \
MINIMIZEBUTTON = ' no ' \ n \
MAXIMIZEBUTTON = ' no ' \ n \
BORDER = ' dialog ' \ n \
SCROLL = ' no ' \ n \
SINGLEINSTANCE = ' yes ' \ n \
WINDOWSTATE = ' hidden ' > \ n \
\ n \
< script language = ' VBScript ' > \ n \
\ n \
intWidth = Screen . Width / 4 \ n \
intHeight = Screen . Height / 6 \ n \
ResizeTo intWidth , intHeight \ n \
MoveTo ( ( Screen . Width / 2 ) - ( intWidth / 2 ) ) , ( ( Screen . Height / 2 ) - ( intHeight / 2 ) ) \ n \
result = 0 \ n \
\ n \
Sub Window_onLoad \ n \
txt_input . Focus \ n \
End Sub \ n \
\ n " );
wcscat ( lDialogString , L " \
Sub Window_onUnload \ n \
Set objFSO = CreateObject ( \ " Scripting.FileSystemObject \" ) \n \
Set oShell = CreateObject ( \ " WScript.Shell \" ) \n \
strTempFolder = oShell . ExpandEnvironmentStrings ( \ " %TEMP% \" ) \n \
Set objFile = objFSO . CreateTextFile ( strTempFolder & \ " \\ tinyfd.txt \" ,True,True) \n \
If result = 1 Then \ n \
objFile . Write 1 & txt_input . Value \ n \
Else \ n \
objFile . Write 0 \ n \
End If \ n \
objFile . Close \ n \
End Sub \ n \
\ n \
Sub Run_ProgramOK \ n \
result = 1 \ n \
window . Close \ n \
End Sub \ n \
\ n \
Sub Run_ProgramCancel \ n \
window . Close \ n \
End Sub \ n \
\ n " );
wcscat ( lDialogString , L " Sub Default_Buttons \n \
If Window . Event . KeyCode = 13 Then \ n \
btn_OK . Click \ n \
ElseIf Window . Event . KeyCode = 27 Then \ n \
btn_Cancel . Click \ n \
End If \ n \
End Sub \ n \
\ n \
< / script > \ n \
< / head > \ n \
< body style = ' background - color : # EEEEEE ' onkeypress = ' vbs : Default_Buttons ' align = ' top ' > \ n \
< table width = ' 100 % ' height = ' 80 % ' align = ' center ' border = ' 0 ' > \ n \
< tr border = ' 0 ' > \ n \
< td align = ' left ' valign = ' middle ' style = ' Font - Family : Arial ' > \ n " );
wcscat ( lDialogString , aMessage ? aMessage : L " " ) ;
wcscat ( lDialogString , L " \n \
< / td > \ n \
< td align = ' right ' valign = ' middle ' style = ' margin - top : 0 em ' > \ n \
< table align = ' right ' style = ' margin - right : 0 em ; ' > \ n \
< tr align = ' right ' style = ' margin - top : 5 em ; ' > \ n \
< input type = ' button ' value = ' OK ' name = ' btn_OK ' onClick = ' vbs : Run_ProgramOK ' style = ' width : 5 em ; margin - top : 2 em ; ' > < br > \ n \
< input type = ' button ' value = ' Cancel ' name = ' btn_Cancel ' onClick = ' vbs : Run_ProgramCancel ' style = ' width : 5 em ; ' > < br > < br > \ n \
< / tr > \ n \
< / table > \ n \
< / td > \ n \
< / tr > \ n \
< / table > \ n " );
wcscat ( lDialogString , L " <table width = '100%' height = '100%' align = 'center' border = '0'> \n \
< tr > \ n \
< td align = ' left ' valign = ' top ' > \ n \
< input type = ' password ' id = ' txt_input ' \ n \
name = ' txt_input ' value = ' ' style = ' float : left ; width : 100 % ' > < BR > \ n \
< / td > \ n \
< / tr > \ n \
< / table > \ n \
< / body > \ n \
< / html > \ n \
" ) ;
}
fputws ( lDialogString , lIn ) ;
fclose ( lIn ) ;
if ( aDefaultInput )
{
swprintf ( lDialogString ,
# if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
lDialogStringLen ,
# endif
L " %ls \\ tinyfd.txt " , _wgetenv ( L " TEMP " ) ) ;
# ifdef TINYFD_NOCCSUNICODE
lFile = _wfopen ( lDialogString , L " w " ) ;
fputc ( 0xFF , lFile ) ;
fputc ( 0xFE , lFile ) ;
# else
lFile = _wfopen ( lDialogString , L " wt, ccs=UNICODE " ) ; /*or ccs=UTF-16LE*/
# endif
fclose ( lFile ) ;
wcscpy ( lDialogString , L " cmd.exe /c cscript.exe //U //Nologo " ) ;
wcscat ( lDialogString , L " \" %TEMP% \\ tinyfd.vbs \" " ) ;
wcscat ( lDialogString , L " >> \" %TEMP% \\ tinyfd.txt \" " ) ;
}
else
{
wcscpy ( lDialogString ,
L " cmd.exe /c mshta.exe \" %TEMP% \\ tinyfd.hta \" " ) ;
}
/* wprintf ( "lDialogString: %ls\n" , lDialogString ) ; */
hiddenConsoleW ( lDialogString , aTitle , 1 ) ;
swprintf ( lDialogString ,
# if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
lDialogStringLen ,
# endif
L " %ls \\ tinyfd.txt " , _wgetenv ( L " TEMP " ) ) ;
/* wprintf(L"lDialogString: %ls\n", lDialogString); */
# ifdef TINYFD_NOCCSUNICODE
if ( ! ( lIn = _wfopen ( lDialogString , L " r " ) ) )
# else
if ( ! ( lIn = _wfopen ( lDialogString , L " rt, ccs=UNICODE " ) ) ) /*or ccs=UTF-16LE*/
# endif
{
_wremove ( lDialogString ) ;
free ( lDialogString ) ;
return NULL ;
}
memset ( lBuff , 0 , MAX_PATH_OR_CMD * sizeof ( wchar_t ) ) ;
# ifdef TINYFD_NOCCSUNICODE
fgets ( ( char * ) lBuff , 2 * MAX_PATH_OR_CMD , lIn ) ;
# else
fgetws ( lBuff , MAX_PATH_OR_CMD , lIn ) ;
# endif
fclose ( lIn ) ;
wipefileW ( lDialogString ) ;
_wremove ( lDialogString ) ;
if ( aDefaultInput )
{
swprintf ( lDialogString ,
# if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
lDialogStringLen ,
# endif
L " %ls \\ tinyfd.vbs " , _wgetenv ( L " TEMP " ) ) ;
}
else
{
swprintf ( lDialogString ,
# if !defined(__BORLANDC__) && !defined(__TINYC__) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
lDialogStringLen ,
# endif
L " %ls \\ tinyfd.hta " , _wgetenv ( L " TEMP " ) ) ;
}
_wremove ( lDialogString ) ;
free ( lDialogString ) ;
/* wprintf( L"lBuff: %ls\n" , lBuff ) ; */
# ifdef TINYFD_NOCCSUNICODE
lResult = ! wcsncmp ( lBuff + 1 , L " 1 " , 1 ) ;
# else
lResult = ! wcsncmp ( lBuff , L " 1 " , 1 ) ;
# endif
/* printf( "lResult: %d \n" , lResult ) ; */
if ( ! lResult )
{
return NULL ;
}
/* wprintf( "lBuff+1: %ls\n" , lBuff+1 ) ; */
# ifdef TINYFD_NOCCSUNICODE
if ( aDefaultInput )
{
lDialogStringLen = wcslen ( lBuff ) ;
lBuff [ lDialogStringLen - 1 ] = L ' \0 ' ;
lBuff [ lDialogStringLen - 2 ] = L ' \0 ' ;
}
return lBuff + 2 ;
# else
if ( aDefaultInput ) lBuff [ wcslen ( lBuff ) - 1 ] = L ' \0 ' ;
return lBuff + 1 ;
# endif
}
wchar_t * tinyfd_saveFileDialogW (
wchar_t const * aTitle , /* NULL or "" */
wchar_t const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
wchar_t const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
wchar_t const * aSingleFilterDescription ) /* NULL or "image files" */
{
static wchar_t lBuff [ MAX_PATH_OR_CMD ] ;
wchar_t lDirname [ MAX_PATH_OR_CMD ] ;
wchar_t lDialogString [ MAX_PATH_OR_CMD ] ;
wchar_t lFilterPatterns [ MAX_PATH_OR_CMD ] = L " " ;
wchar_t * p ;
wchar_t * lRetval ;
wchar_t const * ldefExt = NULL ;
int i ;
HRESULT lHResult ;
OPENFILENAMEW ofn = { 0 } ;
if ( aTitle & & ! wcscmp ( aTitle , L " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows_wchar " ) ; return ( wchar_t * ) 1 ; }
if ( quoteDetectedW ( aTitle ) ) return tinyfd_saveFileDialogW ( L " INVALID TITLE WITH QUOTES " , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription ) ;
if ( quoteDetectedW ( aDefaultPathAndFile ) ) return tinyfd_saveFileDialogW ( aTitle , L " INVALID DEFAULT_PATH WITH QUOTES " , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription ) ;
if ( quoteDetectedW ( aSingleFilterDescription ) ) return tinyfd_saveFileDialogW ( aTitle , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , L " INVALID FILTER_DESCRIPTION WITH QUOTES " ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( quoteDetectedW ( aFilterPatterns [ i ] ) ) return tinyfd_saveFileDialogW ( L " INVALID FILTER_PATTERN WITH QUOTES " , aDefaultPathAndFile , 0 , NULL , NULL ) ;
}
lHResult = CoInitializeEx ( NULL , 0 ) ;
getPathWithoutFinalSlashW ( lDirname , aDefaultPathAndFile ) ;
getLastNameW ( lBuff , aDefaultPathAndFile ) ;
if ( aNumOfFilterPatterns > 0 )
{
ldefExt = aFilterPatterns [ 0 ] ;
if ( aSingleFilterDescription & & wcslen ( aSingleFilterDescription ) )
{
wcscpy ( lFilterPatterns , aSingleFilterDescription ) ;
wcscat ( lFilterPatterns , L " \n " ) ;
}
wcscat ( lFilterPatterns , aFilterPatterns [ 0 ] ) ;
for ( i = 1 ; i < aNumOfFilterPatterns ; i + + )
{
wcscat ( lFilterPatterns , L " ; " ) ;
wcscat ( lFilterPatterns , aFilterPatterns [ i ] ) ;
}
wcscat ( lFilterPatterns , L " \n " ) ;
if ( ! ( aSingleFilterDescription & & wcslen ( aSingleFilterDescription ) ) )
{
wcscpy ( lDialogString , lFilterPatterns ) ;
wcscat ( lFilterPatterns , lDialogString ) ;
}
wcscat ( lFilterPatterns , L " All Files \n *.* \n " ) ;
p = lFilterPatterns ;
while ( ( p = wcschr ( p , L ' \n ' ) ) ! = NULL )
{
* p = L ' \0 ' ;
p + + ;
}
}
ofn . lStructSize = sizeof ( OPENFILENAMEW ) ;
ofn . hwndOwner = GetForegroundWindow ( ) ;
ofn . hInstance = 0 ;
ofn . lpstrFilter = wcslen ( lFilterPatterns ) ? lFilterPatterns : NULL ;
ofn . lpstrCustomFilter = NULL ;
ofn . nMaxCustFilter = 0 ;
ofn . nFilterIndex = 1 ;
ofn . lpstrFile = lBuff ;
ofn . nMaxFile = MAX_PATH_OR_CMD ;
ofn . lpstrFileTitle = NULL ;
ofn . nMaxFileTitle = MAX_PATH_OR_CMD / 2 ;
ofn . lpstrInitialDir = wcslen ( lDirname ) ? lDirname : NULL ;
ofn . lpstrTitle = aTitle & & wcslen ( aTitle ) ? aTitle : NULL ;
ofn . Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST ;
ofn . nFileOffset = 0 ;
ofn . nFileExtension = 0 ;
ofn . lpstrDefExt = ldefExt ;
ofn . lCustData = 0L ;
ofn . lpfnHook = NULL ;
ofn . lpTemplateName = NULL ;
if ( GetSaveFileNameW ( & ofn ) = = 0 )
{
lRetval = NULL ;
}
else
{
lRetval = lBuff ;
}
if ( lHResult = = S_OK | | lHResult = = S_FALSE )
{
CoUninitialize ( ) ;
}
return lRetval ;
}
wchar_t * tinyfd_openFileDialogW (
wchar_t const * aTitle , /* NULL or "" */
wchar_t const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
wchar_t const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
wchar_t const * aSingleFilterDescription , /* NULL or "image files" */
int aAllowMultipleSelects ) /* 0 or 1 ; -1 to free allocated memory and return */
{
size_t lLengths [ MAX_MULTIPLE_FILES ] ;
wchar_t lDirname [ MAX_PATH_OR_CMD ] ;
wchar_t lFilterPatterns [ MAX_PATH_OR_CMD ] = L " " ;
wchar_t lDialogString [ MAX_PATH_OR_CMD ] ;
wchar_t * lPointers [ MAX_MULTIPLE_FILES + 1 ] ;
wchar_t * p ;
int i , j ;
size_t lBuffLen ;
DWORD lFullBuffLen ;
HRESULT lHResult ;
OPENFILENAMEW ofn = { 0 } ;
static wchar_t * lBuff = NULL ;
free ( lBuff ) ;
lBuff = NULL ;
if ( aAllowMultipleSelects < 0 ) return ( wchar_t * ) 0 ;
if ( aTitle & & ! wcscmp ( aTitle , L " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows_wchar " ) ; return ( wchar_t * ) 1 ; }
if ( quoteDetectedW ( aTitle ) ) return tinyfd_openFileDialogW ( L " INVALID TITLE WITH QUOTES " , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription , aAllowMultipleSelects ) ;
if ( quoteDetectedW ( aDefaultPathAndFile ) ) return tinyfd_openFileDialogW ( aTitle , L " INVALID DEFAULT_PATH WITH QUOTES " , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription , aAllowMultipleSelects ) ;
if ( quoteDetectedW ( aSingleFilterDescription ) ) return tinyfd_openFileDialogW ( aTitle , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , L " INVALID FILTER_DESCRIPTION WITH QUOTES " , aAllowMultipleSelects ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( quoteDetectedW ( aFilterPatterns [ i ] ) ) return tinyfd_openFileDialogW ( L " INVALID FILTER_PATTERN WITH QUOTES " , aDefaultPathAndFile , 0 , NULL , NULL , aAllowMultipleSelects ) ;
}
if ( aAllowMultipleSelects )
{
lFullBuffLen = MAX_MULTIPLE_FILES * MAX_PATH_OR_CMD + 1 ;
lBuff = ( wchar_t * ) ( malloc ( lFullBuffLen * sizeof ( wchar_t ) ) ) ;
if ( ! lBuff )
{
lFullBuffLen = LOW_MULTIPLE_FILES * MAX_PATH_OR_CMD + 1 ;
lBuff = ( wchar_t * ) ( malloc ( lFullBuffLen * sizeof ( wchar_t ) ) ) ;
}
}
else
{
lFullBuffLen = MAX_PATH_OR_CMD + 1 ;
lBuff = ( wchar_t * ) ( malloc ( lFullBuffLen * sizeof ( wchar_t ) ) ) ;
}
if ( ! lBuff ) return NULL ;
lHResult = CoInitializeEx ( NULL , 0 ) ;
getPathWithoutFinalSlashW ( lDirname , aDefaultPathAndFile ) ;
getLastNameW ( lBuff , aDefaultPathAndFile ) ;
if ( aNumOfFilterPatterns > 0 )
{
if ( aSingleFilterDescription & & wcslen ( aSingleFilterDescription ) )
{
wcscpy ( lFilterPatterns , aSingleFilterDescription ) ;
wcscat ( lFilterPatterns , L " \n " ) ;
}
wcscat ( lFilterPatterns , aFilterPatterns [ 0 ] ) ;
for ( i = 1 ; i < aNumOfFilterPatterns ; i + + )
{
wcscat ( lFilterPatterns , L " ; " ) ;
wcscat ( lFilterPatterns , aFilterPatterns [ i ] ) ;
}
wcscat ( lFilterPatterns , L " \n " ) ;
if ( ! ( aSingleFilterDescription & & wcslen ( aSingleFilterDescription ) ) )
{
wcscpy ( lDialogString , lFilterPatterns ) ;
wcscat ( lFilterPatterns , lDialogString ) ;
}
wcscat ( lFilterPatterns , L " All Files \n *.* \n " ) ;
p = lFilterPatterns ;
while ( ( p = wcschr ( p , L ' \n ' ) ) ! = NULL )
{
* p = L ' \0 ' ;
p + + ;
}
}
ofn . lStructSize = sizeof ( OPENFILENAME ) ;
ofn . hwndOwner = GetForegroundWindow ( ) ;
ofn . hInstance = 0 ;
ofn . lpstrFilter = wcslen ( lFilterPatterns ) ? lFilterPatterns : NULL ;
ofn . lpstrCustomFilter = NULL ;
ofn . nMaxCustFilter = 0 ;
ofn . nFilterIndex = 1 ;
ofn . lpstrFile = lBuff ;
ofn . nMaxFile = lFullBuffLen ;
ofn . lpstrFileTitle = NULL ;
ofn . nMaxFileTitle = MAX_PATH_OR_CMD / 2 ;
ofn . lpstrInitialDir = wcslen ( lDirname ) ? lDirname : NULL ;
ofn . lpstrTitle = aTitle & & wcslen ( aTitle ) ? aTitle : NULL ;
ofn . Flags = OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST ;
ofn . nFileOffset = 0 ;
ofn . nFileExtension = 0 ;
ofn . lpstrDefExt = NULL ;
ofn . lCustData = 0L ;
ofn . lpfnHook = NULL ;
ofn . lpTemplateName = NULL ;
if ( aAllowMultipleSelects )
{
ofn . Flags | = OFN_ALLOWMULTISELECT ;
}
if ( GetOpenFileNameW ( & ofn ) = = 0 )
{
free ( lBuff ) ;
lBuff = NULL ;
}
else
{
lBuffLen = wcslen ( lBuff ) ;
lPointers [ 0 ] = lBuff + lBuffLen + 1 ;
if ( aAllowMultipleSelects & & ( lPointers [ 0 ] [ 0 ] ! = L ' \0 ' ) )
{
i = 0 ;
do
{
lLengths [ i ] = wcslen ( lPointers [ i ] ) ;
lPointers [ i + 1 ] = lPointers [ i ] + lLengths [ i ] + 1 ;
i + + ;
} while ( lPointers [ i ] [ 0 ] ! = L ' \0 ' & & i < MAX_MULTIPLE_FILES ) ;
if ( i > MAX_MULTIPLE_FILES )
{
free ( lBuff ) ;
lBuff = NULL ;
}
else
{
i - - ;
p = lBuff + lFullBuffLen - 1 ;
* p = L ' \0 ' ;
for ( j = i ; j > = 0 ; j - - )
{
p - = lLengths [ j ] ;
memmove ( p , lPointers [ j ] , lLengths [ j ] * sizeof ( wchar_t ) ) ;
p - - ;
* p = L ' \\ ' ;
p - = lBuffLen ;
memmove ( p , lBuff , lBuffLen * sizeof ( wchar_t ) ) ;
p - - ;
* p = L ' | ' ;
}
p + + ;
wcscpy ( lBuff , p ) ;
lBuffLen = wcslen ( lBuff ) ;
}
}
if ( lBuff ) lBuff = ( wchar_t * ) ( realloc ( lBuff , ( lBuffLen + 1 ) * sizeof ( wchar_t ) ) ) ;
}
if ( lHResult = = S_OK | | lHResult = = S_FALSE )
{
CoUninitialize ( ) ;
}
return lBuff ;
}
BOOL CALLBACK BrowseCallbackProcW_enum ( HWND hWndChild , LPARAM lParam )
{
wchar_t buf [ 255 ] ;
GetClassNameW ( hWndChild , buf , sizeof ( buf ) ) ;
if ( wcscmp ( buf , L " SysTreeView32 " ) = = 0 ) {
HTREEITEM hNode = TreeView_GetSelection ( hWndChild ) ;
TreeView_EnsureVisible ( hWndChild , hNode ) ;
return FALSE ;
}
return TRUE ;
}
static int __stdcall BrowseCallbackProcW ( HWND hwnd , UINT uMsg , LPARAM lp , LPARAM pData )
{
switch ( uMsg ) {
case BFFM_INITIALIZED :
SendMessage ( hwnd , BFFM_SETSELECTIONW , TRUE , ( LPARAM ) pData ) ;
break ;
case BFFM_SELCHANGED :
EnumChildWindows ( hwnd , BrowseCallbackProcW_enum , 0 ) ;
}
return 0 ;
}
wchar_t * tinyfd_selectFolderDialogW (
wchar_t const * aTitle , /* NULL or "" */
wchar_t const * aDefaultPath ) /* NULL or "" */
{
static wchar_t lBuff [ MAX_PATH_OR_CMD ] ;
wchar_t * lRetval ;
BROWSEINFOW bInfo ;
LPITEMIDLIST lpItem ;
HRESULT lHResult ;
if ( aTitle & & ! wcscmp ( aTitle , L " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows_wchar " ) ; return ( wchar_t * ) 1 ; }
if ( quoteDetectedW ( aTitle ) ) return tinyfd_selectFolderDialogW ( L " INVALID TITLE WITH QUOTES " , aDefaultPath ) ;
if ( quoteDetectedW ( aDefaultPath ) ) return tinyfd_selectFolderDialogW ( aTitle , L " INVALID DEFAULT_PATH WITH QUOTES " ) ;
lHResult = CoInitializeEx ( NULL , COINIT_APARTMENTTHREADED ) ;
bInfo . hwndOwner = GetForegroundWindow ( ) ;
bInfo . pidlRoot = NULL ;
bInfo . pszDisplayName = lBuff ;
bInfo . lpszTitle = aTitle & & wcslen ( aTitle ) ? aTitle : NULL ;
if ( lHResult = = S_OK | | lHResult = = S_FALSE )
{
bInfo . ulFlags = BIF_USENEWUI ;
}
bInfo . lpfn = BrowseCallbackProcW ;
bInfo . lParam = ( LPARAM ) aDefaultPath ;
bInfo . iImage = - 1 ;
lpItem = SHBrowseForFolderW ( & bInfo ) ;
if ( ! lpItem )
{
lRetval = NULL ;
}
else
{
SHGetPathFromIDListW ( lpItem , lBuff ) ;
lRetval = lBuff ;
}
if ( lHResult = = S_OK | | lHResult = = S_FALSE )
{
CoUninitialize ( ) ;
}
return lRetval ;
}
wchar_t * tinyfd_colorChooserW (
wchar_t const * aTitle , /* NULL or "" */
wchar_t const * aDefaultHexRGB , /* NULL or "#FF0000"*/
unsigned char const aDefaultRGB [ 3 ] , /* { 0 , 255 , 255 } */
unsigned char aoResultRGB [ 3 ] ) /* { 0 , 0 , 0 } */
{
static wchar_t lResultHexRGB [ 8 ] ;
CHOOSECOLORW cc ;
COLORREF crCustColors [ 16 ] ;
unsigned char lDefaultRGB [ 3 ] ;
int lRet ;
HRESULT lHResult ;
if ( aTitle & & ! wcscmp ( aTitle , L " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows_wchar " ) ; return ( wchar_t * ) 1 ; }
if ( quoteDetectedW ( aTitle ) ) return tinyfd_colorChooserW ( L " INVALID TITLE WITH QUOTES " , aDefaultHexRGB , aDefaultRGB , aoResultRGB ) ;
if ( quoteDetectedW ( aDefaultHexRGB ) ) return tinyfd_colorChooserW ( aTitle , L " INVALID DEFAULT_HEX_RGB WITH QUOTES " , aDefaultRGB , aoResultRGB ) ;
lHResult = CoInitializeEx ( NULL , 0 ) ;
if ( aDefaultHexRGB )
{
Hex2RGBW ( aDefaultHexRGB , lDefaultRGB ) ;
}
else
{
lDefaultRGB [ 0 ] = aDefaultRGB [ 0 ] ;
lDefaultRGB [ 1 ] = aDefaultRGB [ 1 ] ;
lDefaultRGB [ 2 ] = aDefaultRGB [ 2 ] ;
}
/* we can't use aTitle */
cc . lStructSize = sizeof ( CHOOSECOLOR ) ;
cc . hwndOwner = GetForegroundWindow ( ) ;
cc . hInstance = NULL ;
cc . rgbResult = RGB ( lDefaultRGB [ 0 ] , lDefaultRGB [ 1 ] , lDefaultRGB [ 2 ] ) ;
cc . lpCustColors = crCustColors ;
cc . Flags = CC_RGBINIT | CC_FULLOPEN | CC_ANYCOLOR ;
cc . lCustData = 0 ;
cc . lpfnHook = NULL ;
cc . lpTemplateName = NULL ;
lRet = ChooseColorW ( & cc ) ;
if ( ! lRet )
{
return NULL ;
}
aoResultRGB [ 0 ] = GetRValue ( cc . rgbResult ) ;
aoResultRGB [ 1 ] = GetGValue ( cc . rgbResult ) ;
aoResultRGB [ 2 ] = GetBValue ( cc . rgbResult ) ;
RGB2HexW ( aoResultRGB , lResultHexRGB ) ;
if ( lHResult = = S_OK | | lHResult = = S_FALSE )
{
CoUninitialize ( ) ;
}
return lResultHexRGB ;
}
static int messageBoxWinGui (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n and \t */
char const * aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
char const * aIconType , /* "info" "warning" "error" "question" */
int aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
{
int lIntRetVal ;
wchar_t lTitle [ 128 ] = L " " ;
wchar_t * lMessage = NULL ;
wchar_t lDialogType [ 16 ] = L " " ;
wchar_t lIconType [ 16 ] = L " " ;
wchar_t * lTmpWChar ;
if ( aTitle )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aTitle ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aTitle ) ;
wcscpy ( lTitle , lTmpWChar ) ;
}
if ( aMessage )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aMessage ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aMessage ) ;
lMessage = ( wchar_t * ) malloc ( ( wcslen ( lTmpWChar ) + 1 ) * sizeof ( wchar_t ) ) ;
if ( lMessage ) wcscpy ( lMessage , lTmpWChar ) ;
}
if ( aDialogType )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aDialogType ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aDialogType ) ;
wcscpy ( lDialogType , lTmpWChar ) ;
}
if ( aIconType )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aIconType ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aIconType ) ;
wcscpy ( lIconType , lTmpWChar ) ;
}
lIntRetVal = tinyfd_messageBoxW ( lTitle , lMessage , lDialogType , lIconType , aDefaultButton ) ;
free ( lMessage ) ;
return lIntRetVal ;
}
static int notifyWinGui (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may NOT contain \n nor \t */
char const * aIconType )
{
wchar_t lTitle [ 128 ] = L " " ;
wchar_t * lMessage = NULL ;
wchar_t lIconType [ 16 ] = L " " ;
wchar_t * lTmpWChar ;
if ( aTitle )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aTitle ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aTitle ) ;
wcscpy ( lTitle , lTmpWChar ) ;
}
if ( aMessage )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aMessage ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aMessage ) ;
lMessage = ( wchar_t * ) malloc ( ( wcslen ( lTmpWChar ) + 1 ) * sizeof ( wchar_t ) ) ;
if ( lMessage ) wcscpy ( lMessage , lTmpWChar ) ;
}
if ( aIconType )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aIconType ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aIconType ) ;
wcscpy ( lIconType , lTmpWChar ) ;
}
tinyfd_notifyPopupW ( lTitle , lMessage , lIconType ) ;
free ( lMessage ) ;
return 1 ;
}
static int inputBoxWinGui (
char * aoBuff ,
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may NOT contain \n nor \t */
char const * aDefaultInput ) /* "" , if NULL it's a passwordBox */
{
wchar_t lTitle [ 128 ] = L " " ;
wchar_t * lMessage = NULL ;
wchar_t lDefaultInput [ MAX_PATH_OR_CMD ] = L " " ;
wchar_t * lTmpWChar ;
char * lTmpChar ;
if ( aTitle )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aTitle ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aTitle ) ;
wcscpy ( lTitle , lTmpWChar ) ;
}
if ( aMessage )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aMessage ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aMessage ) ;
lMessage = ( wchar_t * ) malloc ( ( wcslen ( lTmpWChar ) + 1 ) * sizeof ( wchar_t ) ) ;
if ( lMessage ) wcscpy ( lMessage , lTmpWChar ) ;
}
if ( aDefaultInput )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aDefaultInput ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aDefaultInput ) ;
wcscpy ( lDefaultInput , lTmpWChar ) ;
lTmpWChar = tinyfd_inputBoxW ( lTitle , lMessage , lDefaultInput ) ;
}
else lTmpWChar = tinyfd_inputBoxW ( lTitle , lMessage , NULL ) ;
free ( lMessage ) ;
if ( ! lTmpWChar )
{
aoBuff [ 0 ] = ' \0 ' ;
return 0 ;
}
if ( tinyfd_winUtf8 ) lTmpChar = tinyfd_utf16to8 ( lTmpWChar ) ;
else lTmpChar = tinyfd_utf16toMbcs ( lTmpWChar ) ;
strcpy ( aoBuff , lTmpChar ) ;
return 1 ;
}
static char * saveFileDialogWinGui (
char * aoBuff ,
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
char const * aSingleFilterDescription ) /* NULL or "image files" */
{
wchar_t lTitle [ 128 ] = L " " ;
wchar_t lDefaultPathAndFile [ MAX_PATH_OR_CMD ] = L " " ;
wchar_t lSingleFilterDescription [ 128 ] = L " " ;
wchar_t * * lFilterPatterns ;
wchar_t * lTmpWChar ;
char * lTmpChar ;
int i ;
lFilterPatterns = ( wchar_t * * ) malloc ( aNumOfFilterPatterns * sizeof ( wchar_t * ) ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aFilterPatterns [ i ] ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aFilterPatterns [ i ] ) ;
lFilterPatterns [ i ] = ( wchar_t * ) malloc ( ( wcslen ( lTmpWChar ) + 1 ) * sizeof ( wchar_t * ) ) ;
if ( lFilterPatterns [ i ] ) wcscpy ( lFilterPatterns [ i ] , lTmpWChar ) ;
}
if ( aTitle )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aTitle ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aTitle ) ;
wcscpy ( lTitle , lTmpWChar ) ;
}
if ( aDefaultPathAndFile )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aDefaultPathAndFile ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aDefaultPathAndFile ) ;
wcscpy ( lDefaultPathAndFile , lTmpWChar ) ;
}
if ( aSingleFilterDescription )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aSingleFilterDescription ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aSingleFilterDescription ) ;
wcscpy ( lSingleFilterDescription , lTmpWChar ) ;
}
lTmpWChar = tinyfd_saveFileDialogW (
lTitle ,
lDefaultPathAndFile ,
aNumOfFilterPatterns ,
( wchar_t const * * ) lFilterPatterns , /*stupid cast for gcc*/
lSingleFilterDescription ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
free ( lFilterPatterns [ i ] ) ;
}
free ( lFilterPatterns ) ;
if ( ! lTmpWChar )
{
return NULL ;
}
if ( tinyfd_winUtf8 ) lTmpChar = tinyfd_utf16to8 ( lTmpWChar ) ;
else lTmpChar = tinyfd_utf16toMbcs ( lTmpWChar ) ;
strcpy ( aoBuff , lTmpChar ) ;
if ( tinyfd_winUtf8 ) ( void ) tinyfd_utf16to8 ( NULL ) ;
else ( void ) tinyfd_utf16toMbcs ( NULL ) ;
return aoBuff ;
}
static char * openFileDialogWinGui (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
char const * aSingleFilterDescription , /* NULL or "image files" */
int aAllowMultipleSelects ) /* 0 or 1 */
{
wchar_t lTitle [ 128 ] = L " " ;
wchar_t lDefaultPathAndFile [ MAX_PATH_OR_CMD ] = L " " ;
wchar_t lSingleFilterDescription [ 128 ] = L " " ;
wchar_t * * lFilterPatterns ;
wchar_t * lTmpWChar ;
char * lTmpChar ;
int i ;
lFilterPatterns = ( wchar_t * * ) malloc ( aNumOfFilterPatterns * sizeof ( wchar_t * ) ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aFilterPatterns [ i ] ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aFilterPatterns [ i ] ) ;
lFilterPatterns [ i ] = ( wchar_t * ) malloc ( ( wcslen ( lTmpWChar ) + 1 ) * sizeof ( wchar_t * ) ) ;
if ( lFilterPatterns [ i ] ) wcscpy ( lFilterPatterns [ i ] , lTmpWChar ) ;
}
if ( aTitle )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aTitle ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aTitle ) ;
wcscpy ( lTitle , lTmpWChar ) ;
}
if ( aDefaultPathAndFile )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aDefaultPathAndFile ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aDefaultPathAndFile ) ;
wcscpy ( lDefaultPathAndFile , lTmpWChar ) ;
}
if ( aSingleFilterDescription )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aSingleFilterDescription ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aSingleFilterDescription ) ;
wcscpy ( lSingleFilterDescription , lTmpWChar ) ;
}
lTmpWChar = tinyfd_openFileDialogW (
lTitle ,
lDefaultPathAndFile ,
aNumOfFilterPatterns ,
( wchar_t const * * ) lFilterPatterns , /*stupid cast for gcc*/
lSingleFilterDescription ,
aAllowMultipleSelects ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
free ( lFilterPatterns [ i ] ) ;
}
free ( lFilterPatterns ) ;
if ( ! lTmpWChar ) return NULL ;
if ( tinyfd_winUtf8 ) lTmpChar = tinyfd_utf16to8 ( lTmpWChar ) ;
else lTmpChar = tinyfd_utf16toMbcs ( lTmpWChar ) ;
( void ) tinyfd_openFileDialogW ( NULL , NULL , 0 , NULL , NULL , - 1 ) ;
return lTmpChar ;
}
static char * selectFolderDialogWinGui (
char * aoBuff ,
char const * aTitle , /* NULL or "" */
char const * aDefaultPath ) /* NULL or "" */
{
wchar_t lTitle [ 128 ] = L " " ;
wchar_t lDefaultPath [ MAX_PATH_OR_CMD ] = L " " ;
wchar_t * lTmpWChar ;
char * lTmpChar ;
if ( aTitle )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aTitle ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aTitle ) ;
wcscpy ( lTitle , lTmpWChar ) ;
}
if ( aDefaultPath )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aDefaultPath ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aDefaultPath ) ;
wcscpy ( lDefaultPath , lTmpWChar ) ;
}
lTmpWChar = tinyfd_selectFolderDialogW (
lTitle ,
lDefaultPath ) ;
if ( ! lTmpWChar )
{
return NULL ;
}
if ( tinyfd_winUtf8 ) lTmpChar = tinyfd_utf16to8 ( lTmpWChar ) ;
else lTmpChar = tinyfd_utf16toMbcs ( lTmpWChar ) ;
strcpy ( aoBuff , lTmpChar ) ;
return aoBuff ;
}
static char * colorChooserWinGui (
char const * aTitle , /* NULL or "" */
char const * aDefaultHexRGB , /* NULL or "#FF0000"*/
unsigned char const aDefaultRGB [ 3 ] , /* { 0 , 255 , 255 } */
unsigned char aoResultRGB [ 3 ] ) /* { 0 , 0 , 0 } */
{
static char lResultHexRGB [ 8 ] ;
wchar_t lTitle [ 128 ] ;
wchar_t lDefaultHexRGB [ 16 ] ;
wchar_t * lTmpWChar ;
char * lTmpChar ;
if ( aTitle )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aTitle ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aTitle ) ;
wcscpy ( lTitle , lTmpWChar ) ;
}
if ( aDefaultHexRGB )
{
if ( tinyfd_winUtf8 ) lTmpWChar = tinyfd_utf8to16 ( aDefaultHexRGB ) ;
else lTmpWChar = tinyfd_mbcsTo16 ( aDefaultHexRGB ) ;
wcscpy ( lDefaultHexRGB , lTmpWChar ) ;
}
lTmpWChar = tinyfd_colorChooserW (
lTitle ,
lDefaultHexRGB ,
aDefaultRGB ,
aoResultRGB ) ;
if ( ! lTmpWChar )
{
return NULL ;
}
if ( tinyfd_winUtf8 ) lTmpChar = tinyfd_utf16to8 ( lTmpWChar ) ;
else lTmpChar = tinyfd_utf16toMbcs ( lTmpWChar ) ;
strcpy ( lResultHexRGB , lTmpChar ) ;
return lResultHexRGB ;
}
static int dialogPresent ( void )
{
static int lDialogPresent = - 1 ;
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
char const * lString = " dialog.exe " ;
if ( ! tinyfd_allowCursesDialogs ) return 0 ;
if ( lDialogPresent < 0 )
{
if ( ! ( lIn = _popen ( " where dialog.exe " , " r " ) ) )
{
lDialogPresent = 0 ;
return 0 ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{ }
_pclose ( lIn ) ;
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
if ( strcmp ( lBuff + strlen ( lBuff ) - strlen ( lString ) , lString ) )
{
lDialogPresent = 0 ;
}
else
{
lDialogPresent = 1 ;
}
}
return lDialogPresent ;
}
static int messageBoxWinConsole (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n and \t */
char const * aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
char const * aIconType , /* "info" "warning" "error" "question" */
int aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
{
char lDialogString [ MAX_PATH_OR_CMD ] ;
char lDialogFile [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
char lBuff [ MAX_PATH_OR_CMD ] = " " ;
strcpy ( lDialogString , " dialog " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDialogType & & ( ! strcmp ( " okcancel " , aDialogType )
| | ! strcmp ( " yesno " , aDialogType ) | | ! strcmp ( " yesnocancel " , aDialogType ) ) )
{
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString , " tab: move focus " ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
if ( ! aDefaultButton )
{
strcat ( lDialogString , " --defaultno " ) ;
}
strcat ( lDialogString ,
" --yes-label \" Ok \" --no-label \" Cancel \" --yesno " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
if ( ! aDefaultButton )
{
strcat ( lDialogString , " --defaultno " ) ;
}
strcat ( lDialogString , " --yesno " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
if ( ! aDefaultButton )
{
strcat ( lDialogString , " --defaultno " ) ;
}
strcat ( lDialogString , " --menu " ) ;
}
else
{
strcat ( lDialogString , " --msgbox " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
tfd_replaceSubStr ( aMessage , " \n " , " \\ n " , lBuff ) ;
strcat ( lDialogString , lBuff ) ;
lBuff [ 0 ] = ' \0 ' ;
}
strcat ( lDialogString , " \" " ) ;
if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " 0 60 0 Yes \" \" No \" \" " ) ;
strcat ( lDialogString , " 2>> " ) ;
}
else
{
strcat ( lDialogString , " 10 60 " ) ;
strcat ( lDialogString , " && echo 1 > " ) ;
}
strcpy ( lDialogFile , getenv ( " TEMP " ) ) ;
strcat ( lDialogFile , " \\ tinyfd.txt " ) ;
strcat ( lDialogString , lDialogFile ) ;
/*if (tinyfd_verbose) printf( "lDialogString: %s\n" , lDialogString ) ;*/
system ( lDialogString ) ;
if ( ! ( lIn = fopen ( lDialogFile , " r " ) ) )
{
remove ( lDialogFile ) ;
return 0 ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{ }
fclose ( lIn ) ;
remove ( lDialogFile ) ;
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
/* if (tinyfd_verbose) printf("lBuff: %s\n", lBuff); */
if ( ! strlen ( lBuff ) )
{
return 0 ;
}
if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
if ( lBuff [ 0 ] = = ' Y ' ) return 1 ;
else return 2 ;
}
return 1 ;
}
static int inputBoxWinConsole (
char * aoBuff ,
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may NOT contain \n nor \t */
char const * aDefaultInput ) /* "" , if NULL it's a passwordBox */
{
char lDialogString [ MAX_PATH_OR_CMD ] ;
char lDialogFile [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
int lResult ;
strcpy ( lDialogFile , getenv ( " TEMP " ) ) ;
strcat ( lDialogFile , " \\ tinyfd.txt " ) ;
strcpy ( lDialogString , " echo|set /p=1 > " ) ;
strcat ( lDialogString , lDialogFile ) ;
strcat ( lDialogString , " & " ) ;
strcat ( lDialogString , " dialog " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString , " tab: move focus " ) ;
if ( ! aDefaultInput )
{
strcat ( lDialogString , " (sometimes nothing, no blink nor star, is shown in text field) " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( ! aDefaultInput )
{
strcat ( lDialogString , " --insecure --passwordbox " ) ;
}
else
{
strcat ( lDialogString , " --inputbox " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" 10 60 " ) ;
if ( aDefaultInput & & strlen ( aDefaultInput ) )
{
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , aDefaultInput ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " 2>> " ) ;
strcpy ( lDialogFile , getenv ( " TEMP " ) ) ;
strcat ( lDialogFile , " \\ tinyfd.txt " ) ;
strcat ( lDialogString , lDialogFile ) ;
strcat ( lDialogString , " || echo 0 > " ) ;
strcat ( lDialogString , lDialogFile ) ;
/* printf( "lDialogString: %s\n" , lDialogString ) ; */
system ( lDialogString ) ;
if ( ! ( lIn = fopen ( lDialogFile , " r " ) ) )
{
remove ( lDialogFile ) ;
aoBuff [ 0 ] = ' \0 ' ;
return 0 ;
}
while ( fgets ( aoBuff , MAX_PATH_OR_CMD , lIn ) ! = NULL )
{ }
fclose ( lIn ) ;
wipefile ( lDialogFile ) ;
remove ( lDialogFile ) ;
if ( aoBuff [ strlen ( aoBuff ) - 1 ] = = ' \n ' )
{
aoBuff [ strlen ( aoBuff ) - 1 ] = ' \0 ' ;
}
/* printf( "aoBuff: %s\n" , aoBuff ) ; */
/* printf( "aoBuff: %s len: %lu \n" , aoBuff , strlen(aoBuff) ) ; */
lResult = strncmp ( aoBuff , " 1 " , 1 ) ? 0 : 1 ;
/* printf( "lResult: %d \n" , lResult ) ; */
if ( ! lResult )
{
aoBuff [ 0 ] = ' \0 ' ;
return 0 ;
}
/* printf( "aoBuff+1: %s\n" , aoBuff+1 ) ; */
strcpy ( aoBuff , aoBuff + 3 ) ;
return 1 ;
}
static char * saveFileDialogWinConsole (
char * aoBuff ,
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile ) /* NULL or "" */
{
char lDialogString [ MAX_PATH_OR_CMD ] ;
char lPathAndFile [ MAX_PATH_OR_CMD ] = " " ;
FILE * lIn ;
strcpy ( lDialogString , " dialog " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString ,
" tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY " ) ;
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , " --fselect \" " ) ;
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
/* dialog.exe uses unix separators even on windows */
strcpy ( lPathAndFile , aDefaultPathAndFile ) ;
replaceChr ( lPathAndFile , ' \\ ' , ' / ' ) ;
}
/* dialog.exe needs at least one separator */
if ( ! strchr ( lPathAndFile , ' / ' ) )
{
strcat ( lDialogString , " ./ " ) ;
}
strcat ( lDialogString , lPathAndFile ) ;
strcat ( lDialogString , " \" 0 60 2> " ) ;
strcpy ( lPathAndFile , getenv ( " TEMP " ) ) ;
strcat ( lPathAndFile , " \\ tinyfd.txt " ) ;
strcat ( lDialogString , lPathAndFile ) ;
/* printf( "lDialogString: %s\n" , lDialogString ) ; */
system ( lDialogString ) ;
if ( ! ( lIn = fopen ( lPathAndFile , " r " ) ) )
{
remove ( lPathAndFile ) ;
return NULL ;
}
while ( fgets ( aoBuff , MAX_PATH_OR_CMD , lIn ) ! = NULL )
{ }
fclose ( lIn ) ;
remove ( lPathAndFile ) ;
replaceChr ( aoBuff , ' / ' , ' \\ ' ) ;
/* printf( "aoBuff: %s\n" , aoBuff ) ; */
getLastName ( lDialogString , aoBuff ) ;
if ( ! strlen ( lDialogString ) )
{
return NULL ;
}
return aoBuff ;
}
static char * openFileDialogWinConsole (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile ) /* NULL or "" */
{
char lFilterPatterns [ MAX_PATH_OR_CMD ] = " " ;
char lDialogString [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
static char aoBuff [ MAX_PATH_OR_CMD ] ;
strcpy ( lDialogString , " dialog " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString ,
" tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY " ) ;
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , " --fselect \" " ) ;
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
/* dialog.exe uses unix separators even on windows */
strcpy ( lFilterPatterns , aDefaultPathAndFile ) ;
replaceChr ( lFilterPatterns , ' \\ ' , ' / ' ) ;
}
/* dialog.exe needs at least one separator */
if ( ! strchr ( lFilterPatterns , ' / ' ) )
{
strcat ( lDialogString , " ./ " ) ;
}
strcat ( lDialogString , lFilterPatterns ) ;
strcat ( lDialogString , " \" 0 60 2> " ) ;
strcpy ( lFilterPatterns , getenv ( " TEMP " ) ) ;
strcat ( lFilterPatterns , " \\ tinyfd.txt " ) ;
strcat ( lDialogString , lFilterPatterns ) ;
/* printf( "lDialogString: %s\n" , lDialogString ) ; */
system ( lDialogString ) ;
if ( ! ( lIn = fopen ( lFilterPatterns , " r " ) ) )
{
remove ( lFilterPatterns ) ;
return NULL ;
}
while ( fgets ( aoBuff , MAX_PATH_OR_CMD , lIn ) ! = NULL )
{ }
fclose ( lIn ) ;
remove ( lFilterPatterns ) ;
replaceChr ( aoBuff , ' / ' , ' \\ ' ) ;
/* printf( "aoBuff: %s\n" , aoBuff ) ; */
return aoBuff ;
}
static char * selectFolderDialogWinConsole (
char * aoBuff ,
char const * aTitle , /* NULL or "" */
char const * aDefaultPath ) /* NULL or "" */
{
char lDialogString [ MAX_PATH_OR_CMD ] ;
char lString [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
strcpy ( lDialogString , " dialog " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString ,
" tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY " ) ;
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , " --dselect \" " ) ;
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
/* dialog.exe uses unix separators even on windows */
strcpy ( lString , aDefaultPath ) ;
ensureFinalSlash ( lString ) ;
replaceChr ( lString , ' \\ ' , ' / ' ) ;
strcat ( lDialogString , lString ) ;
}
else
{
/* dialog.exe needs at least one separator */
strcat ( lDialogString , " ./ " ) ;
}
strcat ( lDialogString , " \" 0 60 2> " ) ;
strcpy ( lString , getenv ( " TEMP " ) ) ;
strcat ( lString , " \\ tinyfd.txt " ) ;
strcat ( lDialogString , lString ) ;
/* printf( "lDialogString: %s\n" , lDialogString ) ; */
system ( lDialogString ) ;
if ( ! ( lIn = fopen ( lString , " r " ) ) )
{
remove ( lString ) ;
return NULL ;
}
while ( fgets ( aoBuff , MAX_PATH_OR_CMD , lIn ) ! = NULL )
{ }
fclose ( lIn ) ;
remove ( lString ) ;
replaceChr ( aoBuff , ' / ' , ' \\ ' ) ;
/* printf( "aoBuff: %s\n" , aoBuff ) ; */
return aoBuff ;
}
static void writeUtf8 ( char const * aUtf8String )
{
unsigned long lNum ;
void * lConsoleHandle ;
wchar_t * lTmpWChar ;
lConsoleHandle = GetStdHandle ( STD_OUTPUT_HANDLE ) ;
lTmpWChar = tinyfd_utf8to16 ( aUtf8String ) ;
( void ) WriteConsoleW ( lConsoleHandle , lTmpWChar , ( DWORD ) wcslen ( lTmpWChar ) , & lNum , NULL ) ;
}
int tinyfd_messageBox (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n and \t */
char const * aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
char const * aIconType , /* "info" "warning" "error" "question" */
int aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
{
char lChar ;
UINT lOriginalCP = 0 ;
UINT lOriginalOutputCP = 0 ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_messageBox ( " INVALID TITLE WITH QUOTES " , aMessage , aDialogType , aIconType , aDefaultButton ) ;
if ( tfd_quoteDetected ( aMessage ) ) return tinyfd_messageBox ( aTitle , " INVALID MESSAGE WITH QUOTES " , aDialogType , aIconType , aDefaultButton ) ;
if ( ( ! tinyfd_forceConsole | | ! ( GetConsoleWindow ( ) | | dialogPresent ( ) ) )
& & ( ! getenv ( " SSH_CLIENT " ) | | getenvDISPLAY ( ) ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows " ) ; return 1 ; }
return messageBoxWinGui ( aTitle , aMessage , aDialogType , aIconType , aDefaultButton ) ;
}
else if ( dialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return 0 ; }
return messageBoxWinConsole (
aTitle , aMessage , aDialogType , aIconType , aDefaultButton ) ;
}
else
{
if ( ! tinyfd_winUtf8 )
{
lOriginalCP = GetConsoleCP ( ) ;
lOriginalOutputCP = GetConsoleOutputCP ( ) ;
( void ) SetConsoleCP ( GetACP ( ) ) ;
( void ) SetConsoleOutputCP ( GetACP ( ) ) ;
}
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return 0 ; }
if ( ! gWarningDisplayed & & ! tinyfd_forceConsole )
{
gWarningDisplayed = 1 ;
printf ( " \n \n %s \n " , gTitle ) ;
printf ( " %s \n \n " , tinyfd_needs ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
printf ( " \n " ) ;
if ( tinyfd_winUtf8 ) writeUtf8 ( aTitle ) ;
else printf ( " %s " , aTitle ) ;
printf ( " \n \n " ) ;
}
if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
do
{
if ( aMessage & & strlen ( aMessage ) )
{
if ( tinyfd_winUtf8 ) writeUtf8 ( aMessage ) ;
else printf ( " %s " , aMessage ) ;
printf ( " \n " ) ;
}
printf ( " y/n: " ) ;
lChar = ( char ) tolower ( _getch ( ) ) ;
printf ( " \n \n " ) ;
} while ( lChar ! = ' y ' & & lChar ! = ' n ' ) ;
if ( ! tinyfd_winUtf8 ) { ( void ) SetConsoleCP ( lOriginalCP ) ; ( void ) SetConsoleOutputCP ( lOriginalOutputCP ) ; }
return lChar = = ' y ' ? 1 : 0 ;
}
else if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
do
{
if ( aMessage & & strlen ( aMessage ) )
{
if ( tinyfd_winUtf8 ) writeUtf8 ( aMessage ) ;
else printf ( " %s " , aMessage ) ;
printf ( " \n " ) ;
}
printf ( " [O]kay/[C]ancel: " ) ;
lChar = ( char ) tolower ( _getch ( ) ) ;
printf ( " \n \n " ) ;
} while ( lChar ! = ' o ' & & lChar ! = ' c ' ) ;
if ( ! tinyfd_winUtf8 ) { ( void ) SetConsoleCP ( lOriginalCP ) ; ( void ) SetConsoleOutputCP ( lOriginalOutputCP ) ; }
return lChar = = ' o ' ? 1 : 0 ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
do
{
if ( aMessage & & strlen ( aMessage ) )
{
if ( tinyfd_winUtf8 ) writeUtf8 ( aMessage ) ;
else printf ( " %s " , aMessage ) ;
printf ( " \n " ) ;
}
printf ( " [Y]es/[N]o/[C]ancel: " ) ;
lChar = ( char ) tolower ( _getch ( ) ) ;
printf ( " \n \n " ) ;
} while ( lChar ! = ' y ' & & lChar ! = ' n ' & & lChar ! = ' c ' ) ;
if ( ! tinyfd_winUtf8 ) { ( void ) SetConsoleCP ( lOriginalCP ) ; ( void ) SetConsoleOutputCP ( lOriginalOutputCP ) ; }
return ( lChar = = ' y ' ) ? 1 : ( lChar = = ' n ' ) ? 2 : 0 ;
}
else
{
if ( aMessage & & strlen ( aMessage ) )
{
if ( tinyfd_winUtf8 ) writeUtf8 ( aMessage ) ;
else printf ( " %s " , aMessage ) ;
printf ( " \n \n " ) ;
}
printf ( " press enter to continue " ) ;
lChar = ( char ) _getch ( ) ;
printf ( " \n \n " ) ;
if ( ! tinyfd_winUtf8 ) { ( void ) SetConsoleCP ( lOriginalCP ) ; ( void ) SetConsoleOutputCP ( lOriginalOutputCP ) ; }
return 1 ;
}
}
}
/* return has only meaning for tinyfd_query */
int tinyfd_notifyPopup (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n \t */
char const * aIconType ) /* "info" "warning" "error" */
{
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_notifyPopup ( " INVALID TITLE WITH QUOTES " , aMessage , aIconType ) ;
if ( tfd_quoteDetected ( aMessage ) ) return tinyfd_notifyPopup ( aTitle , " INVALID MESSAGE WITH QUOTES " , aIconType ) ;
if ( powershellPresent ( ) & & ( ! tinyfd_forceConsole | | ! (
GetConsoleWindow ( ) | |
dialogPresent ( ) ) )
& & ( ! getenv ( " SSH_CLIENT " ) | | getenvDISPLAY ( ) ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows " ) ; return 1 ; }
return notifyWinGui ( aTitle , aMessage , aIconType ) ;
}
else
return tinyfd_messageBox ( aTitle , aMessage , " ok " , aIconType , 0 ) ;
}
/* returns NULL on cancel */
char * tinyfd_inputBox (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" (\n and \t have no effect) */
char const * aDefaultInput ) /* "" , if NULL it's a passwordBox */
{
static char lBuff [ MAX_PATH_OR_CMD ] = " " ;
char * lEOF ;
DWORD mode = 0 ;
HANDLE hStdin = GetStdHandle ( STD_INPUT_HANDLE ) ;
unsigned long lNum ;
void * lConsoleHandle ;
char * lTmpChar ;
wchar_t lBuffW [ 1024 ] ;
UINT lOriginalCP = 0 ;
UINT lOriginalOutputCP = 0 ;
if ( ! aTitle & & ! aMessage & & ! aDefaultInput ) return lBuff ; /* now I can fill lBuff from outside */
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_inputBox ( " INVALID TITLE WITH QUOTES " , aMessage , aDefaultInput ) ;
if ( tfd_quoteDetected ( aMessage ) ) return tinyfd_inputBox ( aTitle , " INVALID MESSAGE WITH QUOTES " , aDefaultInput ) ;
if ( tfd_quoteDetected ( aDefaultInput ) ) return tinyfd_inputBox ( aTitle , aMessage , " INVALID DEFAULT_INPUT WITH QUOTES " ) ;
mode = 0 ;
hStdin = GetStdHandle ( STD_INPUT_HANDLE ) ;
if ( ( ! tinyfd_forceConsole | | ! (
GetConsoleWindow ( ) | |
dialogPresent ( ) ) )
& & ( ! getenv ( " SSH_CLIENT " ) | | getenvDISPLAY ( ) ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows " ) ; return ( char * ) 1 ; }
lBuff [ 0 ] = ' \0 ' ;
if ( inputBoxWinGui ( lBuff , aTitle , aMessage , aDefaultInput ) ) return lBuff ;
else return NULL ;
}
else if ( dialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
lBuff [ 0 ] = ' \0 ' ;
if ( inputBoxWinConsole ( lBuff , aTitle , aMessage , aDefaultInput ) ) return lBuff ;
else return NULL ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return ( char * ) 0 ; }
lBuff [ 0 ] = ' \0 ' ;
if ( ! gWarningDisplayed & & ! tinyfd_forceConsole )
{
gWarningDisplayed = 1 ;
printf ( " \n \n %s \n " , gTitle ) ;
printf ( " %s \n \n " , tinyfd_needs ) ;
}
if ( ! tinyfd_winUtf8 )
{
lOriginalCP = GetConsoleCP ( ) ;
lOriginalOutputCP = GetConsoleOutputCP ( ) ;
( void ) SetConsoleCP ( GetACP ( ) ) ;
( void ) SetConsoleOutputCP ( GetACP ( ) ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
printf ( " \n " ) ;
if ( tinyfd_winUtf8 ) writeUtf8 ( aTitle ) ;
else printf ( " %s " , aTitle ) ;
printf ( " \n \n " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
if ( tinyfd_winUtf8 ) writeUtf8 ( aMessage ) ;
else printf ( " %s " , aMessage ) ;
printf ( " \n " ) ;
}
printf ( " (ctrl-Z + enter to cancel): " ) ;
if ( ! aDefaultInput )
{
( void ) GetConsoleMode ( hStdin , & mode ) ;
( void ) SetConsoleMode ( hStdin , mode & ( ~ ENABLE_ECHO_INPUT ) ) ;
}
if ( tinyfd_winUtf8 )
{
lConsoleHandle = GetStdHandle ( STD_INPUT_HANDLE ) ;
( void ) ReadConsoleW ( lConsoleHandle , lBuffW , MAX_PATH_OR_CMD , & lNum , NULL ) ;
if ( ! aDefaultInput )
{
( void ) SetConsoleMode ( hStdin , mode ) ;
printf ( " \n " ) ;
}
lBuffW [ lNum ] = ' \0 ' ;
if ( lBuffW [ wcslen ( lBuffW ) - 1 ] = = ' \n ' ) lBuffW [ wcslen ( lBuffW ) - 1 ] = ' \0 ' ;
if ( lBuffW [ wcslen ( lBuffW ) - 1 ] = = ' \r ' ) lBuffW [ wcslen ( lBuffW ) - 1 ] = ' \0 ' ;
lTmpChar = tinyfd_utf16to8 ( lBuffW ) ;
if ( lTmpChar )
{
strcpy ( lBuff , lTmpChar ) ;
return lBuff ;
}
else
return NULL ;
}
else
{
lEOF = fgets ( lBuff , MAX_PATH_OR_CMD , stdin ) ;
if ( ! aDefaultInput )
{
( void ) SetConsoleMode ( hStdin , mode ) ;
printf ( " \n " ) ;
}
if ( ! tinyfd_winUtf8 )
{
( void ) SetConsoleCP ( lOriginalCP ) ;
( void ) SetConsoleOutputCP ( lOriginalOutputCP ) ;
}
if ( ! lEOF )
{
return NULL ;
}
printf ( " \n " ) ;
if ( strchr ( lBuff , 27 ) )
{
return NULL ;
}
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
return lBuff ;
}
}
}
char * tinyfd_saveFileDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
char const * aSingleFilterDescription ) /* NULL or "image files" */
{
static char lBuff [ MAX_PATH_OR_CMD ] ;
char lString [ MAX_PATH_OR_CMD ] ;
char * p ;
char * lPointerInputBox ;
int i ;
lBuff [ 0 ] = ' \0 ' ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_saveFileDialog ( " INVALID TITLE WITH QUOTES " , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription ) ;
if ( tfd_quoteDetected ( aDefaultPathAndFile ) ) return tinyfd_saveFileDialog ( aTitle , " INVALID DEFAULT_PATH WITH QUOTES " , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription ) ;
if ( tfd_quoteDetected ( aSingleFilterDescription ) ) return tinyfd_saveFileDialog ( aTitle , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , " INVALID FILTER_DESCRIPTION WITH QUOTES " ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( tfd_quoteDetected ( aFilterPatterns [ i ] ) ) return tinyfd_saveFileDialog ( " INVALID FILTER_PATTERN WITH QUOTES " , aDefaultPathAndFile , 0 , NULL , NULL ) ;
}
if ( ( ! tinyfd_forceConsole | | ! ( GetConsoleWindow ( ) | | dialogPresent ( ) ) )
& & ( ! getenv ( " SSH_CLIENT " ) | | getenvDISPLAY ( ) ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows " ) ; return ( char * ) 1 ; }
p = saveFileDialogWinGui ( lBuff ,
aTitle , aDefaultPathAndFile , aNumOfFilterPatterns , ( char const * const * ) aFilterPatterns , aSingleFilterDescription ) ;
}
else if ( dialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
p = saveFileDialogWinConsole ( lBuff , aTitle , aDefaultPathAndFile ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return ( char * ) 0 ; }
strcpy ( lBuff , " Save file in " ) ;
strcat ( lBuff , getCurDir ( ) ) ;
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , lBuff , " " ) ;
if ( p ) strcpy ( lBuff , p ) ; else lBuff [ 0 ] = ' \0 ' ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lString ) ; /* restore its previous content to tinyfd_inputBox */
p = lBuff ;
}
if ( ! p | | ! strlen ( p ) )
{
return NULL ;
}
getPathWithoutFinalSlash ( lString , p ) ;
if ( strlen ( lString ) & & ! dirExists ( lString ) )
{
return NULL ;
}
getLastName ( lString , p ) ;
if ( ! filenameValid ( lString ) )
{
return NULL ;
}
return p ;
}
/* in case of multiple files, the separator is | */
char * tinyfd_openFileDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
char const * aSingleFilterDescription , /* NULL or "image files" */
int aAllowMultipleSelects ) /* 0 or 1 */
{
char lString [ MAX_PATH_OR_CMD ] ;
char lBuff [ MAX_PATH_OR_CMD ] ;
char * p ;
char * lPointerInputBox ;
int i ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_openFileDialog ( " INVALID TITLE WITH QUOTES " , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription , aAllowMultipleSelects ) ;
if ( tfd_quoteDetected ( aDefaultPathAndFile ) ) return tinyfd_openFileDialog ( aTitle , " INVALID DEFAULT_PATH WITH QUOTES " , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription , aAllowMultipleSelects ) ;
if ( tfd_quoteDetected ( aSingleFilterDescription ) ) return tinyfd_openFileDialog ( aTitle , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , " INVALID FILTER_DESCRIPTION WITH QUOTES " , aAllowMultipleSelects ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( tfd_quoteDetected ( aFilterPatterns [ i ] ) ) return tinyfd_openFileDialog ( " INVALID FILTER_PATTERN WITH QUOTES " , aDefaultPathAndFile , 0 , NULL , NULL , aAllowMultipleSelects ) ;
}
if ( ( ! tinyfd_forceConsole | | ! ( GetConsoleWindow ( ) | | dialogPresent ( ) ) )
& & ( ! getenv ( " SSH_CLIENT " ) | | getenvDISPLAY ( ) ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows " ) ; return ( char * ) 1 ; }
p = openFileDialogWinGui ( aTitle , aDefaultPathAndFile , aNumOfFilterPatterns ,
( char const * const * ) aFilterPatterns , aSingleFilterDescription , aAllowMultipleSelects ) ;
}
else if ( dialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
p = openFileDialogWinConsole ( aTitle , aDefaultPathAndFile ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return ( char * ) 0 ; }
strcpy ( lBuff , " Open file from " ) ;
strcat ( lBuff , getCurDir ( ) ) ;
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , lBuff , " " ) ;
if ( p ) strcpy ( lBuff , p ) ; else lBuff [ 0 ] = ' \0 ' ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lString ) ; /* restore its previous content to tinyfd_inputBox */
p = lBuff ;
}
if ( ! p | | ! strlen ( p ) )
{
return NULL ;
}
if ( aAllowMultipleSelects & & strchr ( p , ' | ' ) )
{
p = ensureFilesExist ( ( char * ) p , p ) ;
}
else if ( ! fileExists ( p ) )
{
return NULL ;
}
/* printf( "lBuff3: %s\n" , p ) ; */
return p ;
}
char * tinyfd_selectFolderDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPath ) /* NULL or "" */
{
static char lBuff [ MAX_PATH_OR_CMD ] ;
char * p ;
char * lPointerInputBox ;
char lString [ MAX_PATH_OR_CMD ] ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_selectFolderDialog ( " INVALID TITLE WITH QUOTES " , aDefaultPath ) ;
if ( tfd_quoteDetected ( aDefaultPath ) ) return tinyfd_selectFolderDialog ( aTitle , " INVALID DEFAULT_PATH WITH QUOTES " ) ;
if ( ( ! tinyfd_forceConsole | | ! ( GetConsoleWindow ( ) | | dialogPresent ( ) ) )
& & ( ! getenv ( " SSH_CLIENT " ) | | getenvDISPLAY ( ) ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows " ) ; return ( char * ) 1 ; }
p = selectFolderDialogWinGui ( lBuff , aTitle , aDefaultPath ) ;
}
else
if ( dialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
p = selectFolderDialogWinConsole ( lBuff , aTitle , aDefaultPath ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return ( char * ) 0 ; }
strcpy ( lBuff , " Select folder from " ) ;
strcat ( lBuff , getCurDir ( ) ) ;
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , lBuff , " " ) ;
if ( p ) strcpy ( lBuff , p ) ; else lBuff [ 0 ] = ' \0 ' ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lString ) ; /* restore its previous content to tinyfd_inputBox */
p = lBuff ;
}
if ( ! p | | ! strlen ( p ) | | ! dirExists ( p ) )
{
return NULL ;
}
return p ;
}
/* returns the hexcolor as a string "#FF0000" */
/* aoResultRGB also contains the result */
/* aDefaultRGB is used only if aDefaultHexRGB is NULL */
/* aDefaultRGB and aoResultRGB can be the same array */
char * tinyfd_colorChooser (
char const * aTitle , /* NULL or "" */
char const * aDefaultHexRGB , /* NULL or "#FF0000"*/
unsigned char const aDefaultRGB [ 3 ] , /* { 0 , 255 , 255 } */
unsigned char aoResultRGB [ 3 ] ) /* { 0 , 0 , 0 } */
{
static char lDefaultHexRGB [ 16 ] ;
int i ;
char * p ;
char * lPointerInputBox ;
char lString [ MAX_PATH_OR_CMD ] ;
lDefaultHexRGB [ 0 ] = ' \0 ' ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_colorChooser ( " INVALID TITLE WITH QUOTES " , aDefaultHexRGB , aDefaultRGB , aoResultRGB ) ;
if ( tfd_quoteDetected ( aDefaultHexRGB ) ) return tinyfd_colorChooser ( aTitle , " INVALID DEFAULT_HEX_RGB WITH QUOTES " , aDefaultRGB , aoResultRGB ) ;
if ( ( ! tinyfd_forceConsole | | ! ( GetConsoleWindow ( ) | | dialogPresent ( ) ) )
& & ( ! getenv ( " SSH_CLIENT " ) | | getenvDISPLAY ( ) ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " windows " ) ; return ( char * ) 1 ; }
p = colorChooserWinGui ( aTitle , aDefaultHexRGB , aDefaultRGB , aoResultRGB ) ;
if ( p )
{
strcpy ( lDefaultHexRGB , p ) ;
return lDefaultHexRGB ;
}
return NULL ;
}
else if ( dialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return ( char * ) 0 ; }
}
if ( aDefaultHexRGB )
{
strncpy ( lDefaultHexRGB , aDefaultHexRGB , 7 ) ;
lDefaultHexRGB [ 7 ] = ' \0 ' ;
}
else
{
RGB2Hex ( aDefaultRGB , lDefaultHexRGB ) ;
}
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , " Enter hex rgb color (i.e. #f5ca20) " , lDefaultHexRGB ) ;
if ( ! p | | ( strlen ( p ) ! = 7 ) | | ( p [ 0 ] ! = ' # ' ) )
{
return NULL ;
}
for ( i = 1 ; i < 7 ; i + + )
{
if ( ! isxdigit ( ( int ) p [ i ] ) )
{
return NULL ;
}
}
Hex2RGB ( p , aoResultRGB ) ;
strcpy ( lDefaultHexRGB , p ) ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lString ) ; /* restore its previous content to tinyfd_inputBox */
return lDefaultHexRGB ;
}
# else /* unix */
static char gPython2Name [ 16 ] ;
static char gPython3Name [ 16 ] ;
static char gPythonName [ 16 ] ;
int tfd_isDarwin ( void )
{
static int lsIsDarwin = - 1 ;
struct utsname lUtsname ;
if ( lsIsDarwin < 0 )
{
lsIsDarwin = ! uname ( & lUtsname ) & & ! strcmp ( lUtsname . sysname , " Darwin " ) ;
}
return lsIsDarwin ;
}
static int dirExists ( char const * aDirPath )
{
DIR * lDir ;
if ( ! aDirPath | | ! strlen ( aDirPath ) )
return 0 ;
lDir = opendir ( aDirPath ) ;
if ( ! lDir )
{
return 0 ;
}
closedir ( lDir ) ;
return 1 ;
}
static int detectPresence ( char const * aExecutable )
{
char lBuff [ MAX_PATH_OR_CMD ] ;
char lTestedString [ MAX_PATH_OR_CMD ] = " which " ;
FILE * lIn ;
# ifdef _GNU_SOURCE
char * lAllocatedCharString ;
int lSubstringUndetected ;
# endif
strcat ( lTestedString , aExecutable ) ;
strcat ( lTestedString , " 2>/dev/null " ) ;
lIn = popen ( lTestedString , " r " ) ;
if ( ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
& & ( ! strchr ( lBuff , ' : ' ) ) & & ( strncmp ( lBuff , " no " , 3 ) ) )
{ /* present */
pclose ( lIn ) ;
# ifdef _GNU_SOURCE /*to bypass this, just comment out "#define _GNU_SOURCE" at the top of the file*/
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' ) lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
lAllocatedCharString = realpath ( lBuff , NULL ) ; /*same as canonicalize_file_name*/
lSubstringUndetected = ! strstr ( lAllocatedCharString , aExecutable ) ;
free ( lAllocatedCharString ) ;
if ( lSubstringUndetected )
{
if ( tinyfd_verbose ) printf ( " detectPresence %s %d \n " , aExecutable , 0 ) ;
return 0 ;
}
# endif /*_GNU_SOURCE*/
if ( tinyfd_verbose ) printf ( " detectPresence %s %d \n " , aExecutable , 1 ) ;
return 1 ;
}
else
{
pclose ( lIn ) ;
if ( tinyfd_verbose ) printf ( " detectPresence %s %d \n " , aExecutable , 0 ) ;
return 0 ;
}
}
static char * getVersion ( char const * aExecutable ) /*version must be first numeral*/
{
static char lBuff [ MAX_PATH_OR_CMD ] ;
char lTestedString [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
char * lTmp ;
strcpy ( lTestedString , aExecutable ) ;
strcat ( lTestedString , " --version " ) ;
lIn = popen ( lTestedString , " r " ) ;
lTmp = fgets ( lBuff , sizeof ( lBuff ) , lIn ) ;
pclose ( lIn ) ;
lTmp + = strcspn ( lTmp , " 0123456789 " ) ;
/* printf("lTmp:%s\n", lTmp); */
return lTmp ;
}
static int * getMajorMinorPatch ( char const * aExecutable )
{
static int lArray [ 3 ] ;
char * lTmp ;
lTmp = ( char * ) getVersion ( aExecutable ) ;
lArray [ 0 ] = atoi ( strtok ( lTmp , " ,.- " ) ) ;
/* printf("lArray0 %d\n", lArray[0]); */
lArray [ 1 ] = atoi ( strtok ( 0 , " ,.- " ) ) ;
/* printf("lArray1 %d\n", lArray[1]); */
lArray [ 2 ] = atoi ( strtok ( 0 , " ,.- " ) ) ;
/* printf("lArray2 %d\n", lArray[2]); */
if ( ! lArray [ 0 ] & & ! lArray [ 1 ] & & ! lArray [ 2 ] ) return NULL ;
return lArray ;
}
static int tryCommand ( char const * aCommand )
{
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
lIn = popen ( aCommand , " r " ) ;
if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) = = NULL )
{ /* present */
pclose ( lIn ) ;
return 1 ;
}
else
{
pclose ( lIn ) ;
return 0 ;
}
}
static int isTerminalRunning ( void )
{
static int lIsTerminalRunning = - 1 ;
if ( lIsTerminalRunning < 0 )
{
lIsTerminalRunning = isatty ( 1 ) ;
if ( tinyfd_verbose ) printf ( " isTerminalRunning %d \n " , lIsTerminalRunning ) ;
}
return lIsTerminalRunning ;
}
static char * dialogNameOnly ( void )
{
static char lDialogName [ 128 ] = " * " ;
if ( lDialogName [ 0 ] = = ' * ' )
{
if ( ! tinyfd_allowCursesDialogs )
{
strcpy ( lDialogName , " " ) ;
}
else if ( tfd_isDarwin ( ) & & * strcpy ( lDialogName , " /opt/local/bin/dialog " )
& & detectPresence ( lDialogName ) )
{ }
else if ( * strcpy ( lDialogName , " dialog " )
& & detectPresence ( lDialogName ) )
{ }
else
{
strcpy ( lDialogName , " " ) ;
}
}
return lDialogName ;
}
int isDialogVersionBetter09b ( void )
{
char const * lDialogName ;
char * lVersion ;
int lMajor ;
int lMinor ;
int lDate ;
int lResult ;
char * lMinorP ;
char * lLetter ;
char lBuff [ 128 ] ;
/*char lTest[128] = " 0.9b-20031126" ;*/
lDialogName = dialogNameOnly ( ) ;
if ( ! strlen ( lDialogName ) | | ! ( lVersion = ( char * ) getVersion ( lDialogName ) ) ) return 0 ;
/*lVersion = lTest ;*/
/*printf("lVersion %s\n", lVersion);*/
strcpy ( lBuff , lVersion ) ;
lMajor = atoi ( strtok ( lVersion , " ,.- " ) ) ;
/*printf("lMajor %d\n", lMajor);*/
lMinorP = strtok ( 0 , " ,.-abcdefghijklmnopqrstuvxyz " ) ;
lMinor = atoi ( lMinorP ) ;
/*printf("lMinor %d\n", lMinor );*/
lDate = atoi ( strtok ( 0 , " ,.- " ) ) ;
if ( lDate < 0 ) lDate = - lDate ;
/*printf("lDate %d\n", lDate);*/
lLetter = lMinorP + strlen ( lMinorP ) ;
strcpy ( lVersion , lBuff ) ;
strtok ( lLetter , " ,.- " ) ;
/*printf("lLetter %s\n", lLetter);*/
lResult = ( lMajor > 0 ) | | ( ( lMinor = = 9 ) & & ( * lLetter = = ' b ' ) & & ( lDate > = 20031126 ) ) ;
/*printf("lResult %d\n", lResult);*/
return lResult ;
}
static int whiptailPresentOnly ( void )
{
static int lWhiptailPresent = - 1 ;
if ( ! tinyfd_allowCursesDialogs ) return 0 ;
if ( lWhiptailPresent < 0 )
{
lWhiptailPresent = detectPresence ( " whiptail " ) ;
}
return lWhiptailPresent ;
}
static char * terminalName ( void )
{
static char lTerminalName [ 128 ] = " * " ;
char lShellName [ 64 ] = " * " ;
int * lArray ;
if ( lTerminalName [ 0 ] = = ' * ' )
{
if ( detectPresence ( " bash " ) )
{
strcpy ( lShellName , " bash -c " ) ; /*good for basic input*/
}
else if ( strlen ( dialogNameOnly ( ) ) | | whiptailPresentOnly ( ) )
{
strcpy ( lShellName , " sh -c " ) ; /*good enough for dialog & whiptail*/
}
else
{
strcpy ( lTerminalName , " " ) ;
return NULL ;
}
if ( tfd_isDarwin ( ) )
{
if ( * strcpy ( lTerminalName , " /opt/X11/bin/xterm " )
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -fa 'DejaVu Sans Mono' -fs 10 -title tinyfiledialogs -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else
{
strcpy ( lTerminalName , " " ) ;
}
}
else if ( * strcpy ( lTerminalName , " xterm " ) /*good (small without parameters)*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -fa 'DejaVu Sans Mono' -fs 10 -title tinyfiledialogs -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " terminator " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -x " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " lxterminal " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " konsole " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " kterm " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " tilix " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " xfce4-terminal " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -x " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " mate-terminal " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -x " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " Eterm " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " evilvte " ) /*good*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " pterm " ) /*good (only letters)*/
& & detectPresence ( lTerminalName ) )
{
strcat ( lTerminalName , " -e " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else if ( * strcpy ( lTerminalName , " gnome-terminal " )
& & detectPresence ( lTerminalName ) & & ( lArray = getMajorMinorPatch ( lTerminalName ) )
& & ( ( lArray [ 0 ] < 3 ) | | ( lArray [ 0 ] = = 3 & & lArray [ 1 ] < = 6 ) ) )
{
strcat ( lTerminalName , " --disable-factory -x " ) ;
strcat ( lTerminalName , lShellName ) ;
}
else
{
strcpy ( lTerminalName , " " ) ;
}
/* bad: koi rxterm guake tilda vala-terminal qterminal
aterm Terminal terminology sakura lilyterm weston - terminal
roxterm termit xvt rxvt mrxvt urxvt */
}
if ( strlen ( lTerminalName ) )
{
return lTerminalName ;
}
else
{
return NULL ;
}
}
static char * dialogName ( void )
{
char * lDialogName ;
lDialogName = dialogNameOnly ( ) ;
if ( strlen ( lDialogName ) & & ( isTerminalRunning ( ) | | terminalName ( ) ) )
{
return lDialogName ;
}
else
{
return NULL ;
}
}
static int whiptailPresent ( void )
{
int lWhiptailPresent ;
lWhiptailPresent = whiptailPresentOnly ( ) ;
if ( lWhiptailPresent & & ( isTerminalRunning ( ) | | terminalName ( ) ) )
{
return lWhiptailPresent ;
}
else
{
return 0 ;
}
}
static int graphicMode ( void )
{
return ! ( tinyfd_forceConsole & & ( isTerminalRunning ( ) | | terminalName ( ) ) )
& & ( getenvDISPLAY ( )
| | ( tfd_isDarwin ( ) & & ( ! getenv ( " SSH_TTY " ) | | getenvDISPLAY ( ) ) ) ) ;
}
static int pactlPresent ( void )
{
static int lPactlPresent = - 1 ;
if ( lPactlPresent < 0 )
{
lPactlPresent = detectPresence ( " pactl " ) ;
}
return lPactlPresent ;
}
static int speakertestPresent ( void )
{
static int lSpeakertestPresent = - 1 ;
if ( lSpeakertestPresent < 0 )
{
lSpeakertestPresent = detectPresence ( " speaker-test " ) ;
}
return lSpeakertestPresent ;
}
static int playPresent ( )
{
static int lPlayPresent = - 1 ;
if ( lPlayPresent < 0 )
{
lPlayPresent = detectPresence ( " sox " ) ; /*if sox is present, play is ready*/
}
return lPlayPresent ;
}
static int beepexePresent ( )
{
static int lBeepexePresent = - 1 ;
if ( lBeepexePresent < 0 )
{
lBeepexePresent = detectPresence ( " beep.exe " ) ;
}
return lBeepexePresent ;
}
static int beepPresent ( void )
{
static int lBeepPresent = - 1 ;
if ( lBeepPresent < 0 )
{
lBeepPresent = detectPresence ( " beep " ) ;
}
return lBeepPresent ;
}
static int xmessagePresent ( void )
{
static int lXmessagePresent = - 1 ;
if ( lXmessagePresent < 0 )
{
lXmessagePresent = detectPresence ( " xmessage " ) ; /*if not tty,not on osxpath*/
}
return lXmessagePresent & & graphicMode ( ) ;
}
static int gxmessagePresent ( void )
{
static int lGxmessagePresent = - 1 ;
if ( lGxmessagePresent < 0 )
{
lGxmessagePresent = detectPresence ( " gxmessage " ) ;
}
return lGxmessagePresent & & graphicMode ( ) ;
}
static int gmessagePresent ( void )
{
static int lGmessagePresent = - 1 ;
if ( lGmessagePresent < 0 )
{
lGmessagePresent = detectPresence ( " gmessage " ) ;
}
return lGmessagePresent & & graphicMode ( ) ;
}
static int notifysendPresent ( void )
{
static int lNotifysendPresent = - 1 ;
if ( lNotifysendPresent < 0 )
{
lNotifysendPresent = detectPresence ( " notify-send " ) ;
}
return lNotifysendPresent & & graphicMode ( ) ;
}
static int perlPresent ( void )
{
static int lPerlPresent = - 1 ;
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
if ( lPerlPresent < 0 )
{
lPerlPresent = detectPresence ( " perl " ) ;
if ( lPerlPresent )
{
lIn = popen ( " perl -MNet::DBus -e \" Net::DBus->session->get_service('org.freedesktop.Notifications') \" 2>&1 " , " r " ) ;
if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) = = NULL )
{
lPerlPresent = 2 ;
}
pclose ( lIn ) ;
if ( tinyfd_verbose ) printf ( " perl-dbus %d \n " , lPerlPresent ) ;
}
}
return graphicMode ( ) ? lPerlPresent : 0 ;
}
static int afplayPresent ( void )
{
static int lAfplayPresent = - 1 ;
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
if ( lAfplayPresent < 0 )
{
lAfplayPresent = detectPresence ( " afplay " ) ;
if ( lAfplayPresent )
{
lIn = popen ( " test -e /System/Library/Sounds/Ping.aiff || echo Ping " , " r " ) ;
if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) = = NULL )
{
lAfplayPresent = 2 ;
}
pclose ( lIn ) ;
if ( tinyfd_verbose ) printf ( " afplay %d \n " , lAfplayPresent ) ;
}
}
return graphicMode ( ) ? lAfplayPresent : 0 ;
}
static int xdialogPresent ( void )
{
static int lXdialogPresent = - 1 ;
if ( lXdialogPresent < 0 )
{
lXdialogPresent = detectPresence ( " Xdialog " ) ;
}
return lXdialogPresent & & graphicMode ( ) ;
}
static int gdialogPresent ( void )
{
static int lGdialoglPresent = - 1 ;
if ( lGdialoglPresent < 0 )
{
lGdialoglPresent = detectPresence ( " gdialog " ) ;
}
return lGdialoglPresent & & graphicMode ( ) ;
}
static int osascriptPresent ( void )
{
static int lOsascriptPresent = - 1 ;
if ( lOsascriptPresent < 0 )
{
gWarningDisplayed | = ! ! getenv ( " SSH_TTY " ) ;
lOsascriptPresent = detectPresence ( " osascript " ) ;
}
return lOsascriptPresent & & graphicMode ( ) & & ! getenv ( " SSH_TTY " ) ;
}
int tfd_qarmaPresent ( void )
{
static int lQarmaPresent = - 1 ;
if ( lQarmaPresent < 0 )
{
lQarmaPresent = detectPresence ( " qarma " ) ;
}
return lQarmaPresent & & graphicMode ( ) ;
}
int tfd_matedialogPresent ( void )
{
static int lMatedialogPresent = - 1 ;
if ( lMatedialogPresent < 0 )
{
lMatedialogPresent = detectPresence ( " matedialog " ) ;
}
return lMatedialogPresent & & graphicMode ( ) ;
}
int tfd_shellementaryPresent ( void )
{
static int lShellementaryPresent = - 1 ;
if ( lShellementaryPresent < 0 )
{
lShellementaryPresent = 0 ; /*detectPresence("shellementary"); shellementary is not ready yet */
}
return lShellementaryPresent & & graphicMode ( ) ;
}
int tfd_xpropPresent ( void )
{
static int lXpropPresent = - 1 ;
if ( lXpropPresent < 0 )
{
lXpropPresent = detectPresence ( " xprop " ) ;
}
return lXpropPresent & & graphicMode ( ) ;
}
int tfd_zenityPresent ( void )
{
static int lZenityPresent = - 1 ;
if ( lZenityPresent < 0 )
{
lZenityPresent = detectPresence ( " zenity " ) ;
}
return lZenityPresent & & graphicMode ( ) ;
}
int tfd_yadPresent ( void )
{
static int lYadPresent = - 1 ;
if ( lYadPresent < 0 )
{
lYadPresent = detectPresence ( " yad " ) ;
}
return lYadPresent & & graphicMode ( ) ;
}
int tfd_zenity3Present ( void )
{
static int lZenity3Present = - 1 ;
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
int lIntTmp ;
if ( lZenity3Present < 0 )
{
lZenity3Present = 0 ;
if ( tfd_zenityPresent ( ) )
{
lIn = popen ( " zenity --version " , " r " ) ;
if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{
if ( atoi ( lBuff ) > = 3 )
{
lZenity3Present = 3 ;
lIntTmp = atoi ( strtok ( lBuff , " . " ) + 2 ) ;
if ( lIntTmp > = 18 )
{
lZenity3Present = 5 ;
}
else if ( lIntTmp > = 10 )
{
lZenity3Present = 4 ;
}
}
else if ( ( atoi ( lBuff ) = = 2 ) & & ( atoi ( strtok ( lBuff , " . " ) + 2 ) > = 32 ) )
{
lZenity3Present = 2 ;
}
if ( tinyfd_verbose ) printf ( " zenity type %d \n " , lZenity3Present ) ;
}
pclose ( lIn ) ;
}
}
return graphicMode ( ) ? lZenity3Present : 0 ;
}
int tfd_kdialogPresent ( void )
{
static int lKdialogPresent = - 1 ;
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
char * lDesktop ;
if ( lKdialogPresent < 0 )
{
if ( tfd_zenityPresent ( ) )
{
lDesktop = getenv ( " XDG_SESSION_DESKTOP " ) ;
if ( ! lDesktop | | ( strcmp ( lDesktop , " KDE " ) & & strcmp ( lDesktop , " lxqt " ) ) )
{
lKdialogPresent = 0 ;
return lKdialogPresent ;
}
}
lKdialogPresent = detectPresence ( " kdialog " ) ;
if ( lKdialogPresent & & ! getenv ( " SSH_TTY " ) )
{
lIn = popen ( " kdialog --attach 2>&1 " , " r " ) ;
if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{
if ( ! strstr ( " Unknown " , lBuff ) )
{
lKdialogPresent = 2 ;
if ( tinyfd_verbose ) printf ( " kdialog-attach %d \n " , lKdialogPresent ) ;
}
}
pclose ( lIn ) ;
if ( lKdialogPresent = = 2 )
{
lKdialogPresent = 1 ;
lIn = popen ( " kdialog --passivepopup 2>&1 " , " r " ) ;
if ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{
if ( ! strstr ( " Unknown " , lBuff ) )
{
lKdialogPresent = 2 ;
if ( tinyfd_verbose ) printf ( " kdialog-popup %d \n " , lKdialogPresent ) ;
}
}
pclose ( lIn ) ;
}
}
}
return graphicMode ( ) ? lKdialogPresent : 0 ;
}
static int osx9orBetter ( void )
{
static int lOsx9orBetter = - 1 ;
char lBuff [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
int V , v ;
if ( lOsx9orBetter < 0 )
{
lOsx9orBetter = 0 ;
lIn = popen ( " osascript -e 'set osver to system version of (system info)' " , " r " ) ;
if ( ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
& & ( 2 = = sscanf ( lBuff , " %d.%d " , & V , & v ) ) )
{
V = V * 100 + v ;
if ( V > = 1009 )
{
lOsx9orBetter = 1 ;
}
}
pclose ( lIn ) ;
if ( tinyfd_verbose ) printf ( " Osx10 = %d, %d = %s \n " , lOsx9orBetter , V , lBuff ) ;
}
return lOsx9orBetter ;
}
static int python3Present ( void )
{
static int lPython3Present = - 1 ;
int i ;
if ( lPython3Present < 0 )
{
lPython3Present = 0 ;
strcpy ( gPython3Name , " python3 " ) ;
if ( detectPresence ( gPython3Name ) ) lPython3Present = 1 ;
else
{
for ( i = 9 ; i > = 0 ; i - - )
{
sprintf ( gPython3Name , " python3.%d " , i ) ;
if ( detectPresence ( gPython3Name ) )
{
lPython3Present = 1 ;
break ;
}
}
}
if ( tinyfd_verbose ) printf ( " lPython3Present %d \n " , lPython3Present ) ;
if ( tinyfd_verbose ) printf ( " gPython3Name %s \n " , gPython3Name ) ;
}
return lPython3Present ;
}
static int python2Present ( void )
{
static int lPython2Present = - 1 ;
int i ;
if ( lPython2Present < 0 )
{
lPython2Present = 0 ;
strcpy ( gPython2Name , " python2 " ) ;
if ( detectPresence ( gPython2Name ) ) lPython2Present = 1 ;
else
{
for ( i = 9 ; i > = 0 ; i - - )
{
sprintf ( gPython2Name , " python2.%d " , i ) ;
if ( detectPresence ( gPython2Name ) )
{
lPython2Present = 1 ;
break ;
}
}
}
if ( tinyfd_verbose ) printf ( " lPython2Present %d \n " , lPython2Present ) ;
if ( tinyfd_verbose ) printf ( " gPython2Name %s \n " , gPython2Name ) ;
}
return lPython2Present ;
}
static int tkinter3Present ( void )
{
static int lTkinter3Present = - 1 ;
char lPythonCommand [ 256 ] ;
char lPythonParams [ 128 ] =
" -S -c \" try: \n \t import tkinter; \n except: \n \t print(0); \" " ;
if ( lTkinter3Present < 0 )
{
lTkinter3Present = 0 ;
if ( python3Present ( ) )
{
sprintf ( lPythonCommand , " %s %s " , gPython3Name , lPythonParams ) ;
lTkinter3Present = tryCommand ( lPythonCommand ) ;
}
if ( tinyfd_verbose ) printf ( " lTkinter3Present %d \n " , lTkinter3Present ) ;
}
return lTkinter3Present & & graphicMode ( ) & & ! ( tfd_isDarwin ( ) & & getenv ( " SSH_TTY " ) ) ;
}
static int tkinter2Present ( void )
{
static int lTkinter2Present = - 1 ;
char lPythonCommand [ 256 ] ;
char lPythonParams [ 128 ] =
" -S -c \" try: \n \t import Tkinter; \n except: \n \t print 0; \" " ;
if ( lTkinter2Present < 0 )
{
lTkinter2Present = 0 ;
if ( python2Present ( ) )
{
sprintf ( lPythonCommand , " %s %s " , gPython2Name , lPythonParams ) ;
lTkinter2Present = tryCommand ( lPythonCommand ) ;
}
if ( tinyfd_verbose ) printf ( " lTkinter2Present %d \n " , lTkinter2Present ) ;
}
return lTkinter2Present & & graphicMode ( ) & & ! ( tfd_isDarwin ( ) & & getenv ( " SSH_TTY " ) ) ;
}
static int pythonDbusPresent ( void )
{
static int lPythonDbusPresent = - 1 ;
char lPythonCommand [ 384 ] ;
char lPythonParams [ 256 ] =
" -c \" try: \n \t import dbus;bus=dbus.SessionBus(); \
notif = bus . get_object ( ' org . freedesktop . Notifications ' , ' / org / freedesktop / Notifications ' ) ; \
notify = dbus . Interface ( notif , ' org . freedesktop . Notifications ' ) ; \ nexcept : \ n \ tprint ( 0 ) ; \ " " ;
if ( lPythonDbusPresent < 0 )
{
lPythonDbusPresent = 0 ;
if ( python2Present ( ) )
{
strcpy ( gPythonName , gPython2Name ) ;
sprintf ( lPythonCommand , " %s %s " , gPythonName , lPythonParams ) ;
lPythonDbusPresent = tryCommand ( lPythonCommand ) ;
}
if ( ! lPythonDbusPresent & & python3Present ( ) )
{
strcpy ( gPythonName , gPython3Name ) ;
sprintf ( lPythonCommand , " %s %s " , gPythonName , lPythonParams ) ;
lPythonDbusPresent = tryCommand ( lPythonCommand ) ;
}
if ( tinyfd_verbose ) printf ( " lPythonDbusPresent %d \n " , lPythonDbusPresent ) ;
if ( tinyfd_verbose ) printf ( " gPythonName %s \n " , gPythonName ) ;
}
return lPythonDbusPresent & & graphicMode ( ) & & ! ( tfd_isDarwin ( ) & & getenv ( " SSH_TTY " ) ) ;
}
static void sigHandler ( int signum )
{
FILE * lIn ;
if ( ( lIn = popen ( " pactl unload-module module-sine " , " r " ) ) )
{
pclose ( lIn ) ;
}
if ( tinyfd_verbose ) printf ( " tinyfiledialogs caught signal %d \n " , signum ) ;
}
void tinyfd_beep ( void )
{
char lDialogString [ 256 ] ;
FILE * lIn ;
if ( osascriptPresent ( ) )
{
if ( afplayPresent ( ) > = 2 )
{
strcpy ( lDialogString , " afplay /System/Library/Sounds/Ping.aiff " ) ;
}
else
{
strcpy ( lDialogString , " osascript -e 'tell application \" System Events \" to beep' " ) ;
}
}
else if ( pactlPresent ( ) )
{
signal ( SIGINT , sigHandler ) ;
/*strcpy( lDialogString , "pactl load-module module-sine frequency=440;sleep .3;pactl unload-module module-sine" ) ;*/
strcpy ( lDialogString , " thnum=$(pactl load-module module-sine frequency=440);sleep .3;pactl unload-module $thnum " ) ;
}
else if ( speakertestPresent ( ) )
{
/*strcpy( lDialogString , "timeout -k .3 .3 speaker-test --frequency 440 --test sine > /dev/tty" ) ;*/
strcpy ( lDialogString , " ( speaker-test -t sine -f 440 > /dev/tty )& pid=$!;sleep .4; kill -9 $pid " ) ; /*.3 was too short for mac g3*/
}
else if ( beepexePresent ( ) )
{
strcpy ( lDialogString , " beep.exe 440 300 " ) ;
}
else if ( playPresent ( ) ) /* play is part of sox */
{
strcpy ( lDialogString , " play -q -n synth .3 sine 440 " ) ;
}
else if ( beepPresent ( ) )
{
strcpy ( lDialogString , " beep -f 440 -l 300 " ) ;
}
else
{
strcpy ( lDialogString , " printf ' \a ' > /dev/tty " ) ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
if ( ( lIn = popen ( lDialogString , " r " ) ) )
{
pclose ( lIn ) ;
}
if ( pactlPresent ( ) )
{
signal ( SIGINT , SIG_DFL ) ;
}
}
int tinyfd_messageBox (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n and \t */
char const * aDialogType , /* "ok" "okcancel" "yesno" "yesnocancel" */
char const * aIconType , /* "info" "warning" "error" "question" */
int aDefaultButton ) /* 0 for cancel/no , 1 for ok/yes , 2 for no in yesnocancel */
{
char lBuff [ MAX_PATH_OR_CMD ] ;
char * lDialogString = NULL ;
char * lpDialogString ;
FILE * lIn ;
int lWasGraphicDialog = 0 ;
int lWasXterm = 0 ;
int lResult ;
char lChar ;
struct termios infoOri ;
struct termios info ;
size_t lTitleLen ;
size_t lMessageLen ;
lBuff [ 0 ] = ' \0 ' ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_messageBox ( " INVALID TITLE WITH QUOTES " , aMessage , aDialogType , aIconType , aDefaultButton ) ;
if ( tfd_quoteDetected ( aMessage ) ) return tinyfd_messageBox ( aTitle , " INVALID MESSAGE WITH QUOTES " , aDialogType , aIconType , aDefaultButton ) ;
lTitleLen = aTitle ? strlen ( aTitle ) : 0 ;
lMessageLen = aMessage ? strlen ( aMessage ) : 0 ;
if ( ! aTitle | | strcmp ( aTitle , " tinyfd_query " ) )
{
lDialogString = ( char * ) malloc ( MAX_PATH_OR_CMD + lTitleLen + lMessageLen ) ;
}
if ( osascriptPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " applescript " ) ; return 1 ; }
strcpy ( lDialogString , " osascript " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'tell application \" System Events \" ' -e 'Activate' " ) ;
strcat ( lDialogString , " -e 'try' -e 'set {vButton} to {button returned} of ( display dialog \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " with title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " with icon " ) ;
if ( aIconType & & ! strcmp ( " error " , aIconType ) )
{
strcat ( lDialogString , " stop " ) ;
}
else if ( aIconType & & ! strcmp ( " warning " , aIconType ) )
{
strcat ( lDialogString , " caution " ) ;
}
else /* question or info */
{
strcat ( lDialogString , " note " ) ;
}
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
if ( ! aDefaultButton )
{
strcat ( lDialogString , " default button \" Cancel \" " ) ;
}
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
strcat ( lDialogString , " buttons { \" No \" , \" Yes \" } " ) ;
if ( aDefaultButton )
{
strcat ( lDialogString , " default button \" Yes \" " ) ;
}
else
{
strcat ( lDialogString , " default button \" No \" " ) ;
}
strcat ( lDialogString , " cancel button \" No \" " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " buttons { \" No \" , \" Yes \" , \" Cancel \" } " ) ;
switch ( aDefaultButton )
{
case 1 : strcat ( lDialogString , " default button \" Yes \" " ) ; break ;
case 2 : strcat ( lDialogString , " default button \" No \" " ) ; break ;
case 0 : strcat ( lDialogString , " default button \" Cancel \" " ) ; break ;
}
strcat ( lDialogString , " cancel button \" Cancel \" " ) ;
}
else
{
strcat ( lDialogString , " buttons { \" OK \" } " ) ;
strcat ( lDialogString , " default button \" OK \" " ) ;
}
strcat ( lDialogString , " )' " ) ;
strcat ( lDialogString ,
" -e 'if vButton is \" Yes \" then' -e 'return 1' \
- e ' else if vButton is \ " OK \" then' -e 'return 1' \
- e ' else if vButton is \ " No \" then' -e 'return 2' \
- e ' else ' - e ' return 0 ' - e ' end if ' " );
strcat ( lDialogString , " -e 'on error number -128' " ) ;
strcat ( lDialogString , " -e '0' " ) ;
strcat ( lDialogString , " -e 'end try' " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'end tell' " ) ;
}
else if ( tfd_kdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " kdialog " ) ; return 1 ; }
strcpy ( lDialogString , " kdialog " ) ;
if ( ( tfd_kdialogPresent ( ) = = 2 ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
strcat ( lDialogString , " -- " ) ;
if ( aDialogType & & ( ! strcmp ( " okcancel " , aDialogType )
| | ! strcmp ( " yesno " , aDialogType ) | | ! strcmp ( " yesnocancel " , aDialogType ) ) )
{
if ( aIconType & & ( ! strcmp ( " warning " , aIconType )
| | ! strcmp ( " error " , aIconType ) ) )
{
strcat ( lDialogString , " warning " ) ;
}
if ( ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " yesnocancel " ) ;
}
else
{
strcat ( lDialogString , " yesno " ) ;
}
}
else if ( aIconType & & ! strcmp ( " error " , aIconType ) )
{
strcat ( lDialogString , " error " ) ;
}
else if ( aIconType & & ! strcmp ( " warning " , aIconType ) )
{
strcat ( lDialogString , " sorry " ) ;
}
else
{
strcat ( lDialogString , " msgbox " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aMessage )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
strcat ( lDialogString ,
" --yes-label Ok --no-label Cancel " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " ; x=$? ;if [ $x = 0 ] ;then echo 1;elif [ $x = 1 ] ;then echo 2;else echo 0;fi " ) ;
}
else
{
strcat ( lDialogString , " ;if [ $? = 0 ];then echo 1;else echo 0;fi " ) ;
}
}
else if ( tfd_zenityPresent ( ) | | tfd_matedialogPresent ( ) | | tfd_shellementaryPresent ( ) | | tfd_qarmaPresent ( ) )
{
if ( tfd_zenityPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " zenity " ) ; return 1 ; }
strcpy ( lDialogString , " szAnswer=$(zenity " ) ;
if ( ( tfd_zenity3Present ( ) > = 4 ) & & ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(sleep .01;xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
else if ( tfd_matedialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " matedialog " ) ; return 1 ; }
strcpy ( lDialogString , " szAnswer=$(matedialog " ) ;
}
else if ( tfd_shellementaryPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " shellementary " ) ; return 1 ; }
strcpy ( lDialogString , " szAnswer=$(shellementary " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " qarma " ) ; return 1 ; }
strcpy ( lDialogString , " szAnswer=$(qarma " ) ;
if ( ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
strcat ( lDialogString , " -- " ) ;
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
strcat ( lDialogString ,
" question --ok-label=Ok --cancel-label=Cancel " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
strcat ( lDialogString , " question " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " list --column \" \" --hide-header \" Yes \" \" No \" " ) ;
}
else if ( aIconType & & ! strcmp ( " error " , aIconType ) )
{
strcat ( lDialogString , " error " ) ;
}
else if ( aIconType & & ! strcmp ( " warning " , aIconType ) )
{
strcat ( lDialogString , " warning " ) ;
}
else
{
strcat ( lDialogString , " info " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
if ( strcmp ( " yesnocancel " , aDialogType ) ) strcat ( lDialogString , " --no-wrap " ) ;
strcat ( lDialogString , " --text= \" " ) ;
strcat ( lDialogString , aMessage ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( ( tfd_zenity3Present ( ) > = 3 ) | | ( ! tfd_zenityPresent ( ) & & ( tfd_shellementaryPresent ( ) | | tfd_qarmaPresent ( ) ) ) )
{
strcat ( lDialogString , " --icon-name=dialog- " ) ;
if ( aIconType & & ( ! strcmp ( " question " , aIconType )
| | ! strcmp ( " error " , aIconType )
| | ! strcmp ( " warning " , aIconType ) ) )
{
strcat ( lDialogString , aIconType ) ;
}
else
{
strcat ( lDialogString , " information " ) ;
}
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
if ( ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString ,
" );if [ $? = 1 ];then echo 0;elif [ $szAnswer = \" No \" ];then echo 2;else echo 1;fi " ) ;
}
else
{
strcat ( lDialogString , " );if [ $? = 0 ];then echo 1;else echo 0;fi " ) ;
}
}
else if ( tfd_yadPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " yad " ) ; return 1 ; }
strcpy ( lDialogString , " szAnswer=$(yad -- " ) ;
if ( aDialogType & & ! strcmp ( " ok " , aDialogType ) )
{
strcat ( lDialogString , " button=Ok:1 " ) ;
}
else if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
strcat ( lDialogString , " button=Ok:1 --button=Cancel:0 " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
strcat ( lDialogString , " button=Yes:1 --button=No:0 " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " button=Yes:1 --button=No:2 --button=Cancel:0 " ) ;
}
else if ( aIconType & & ! strcmp ( " error " , aIconType ) )
{
strcat ( lDialogString , " error " ) ;
}
else if ( aIconType & & ! strcmp ( " warning " , aIconType ) )
{
strcat ( lDialogString , " warning " ) ;
}
else
{
strcat ( lDialogString , " info " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " --text= \" " ) ;
strcat ( lDialogString , aMessage ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --icon-name=dialog- " ) ;
if ( aIconType & & ( ! strcmp ( " question " , aIconType )
| | ! strcmp ( " error " , aIconType )
| | ! strcmp ( " warning " , aIconType ) ) )
{
strcat ( lDialogString , aIconType ) ;
}
else
{
strcat ( lDialogString , " information " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
strcat ( lDialogString , " );echo $? " ) ;
}
else if ( ! gxmessagePresent ( ) & & ! gmessagePresent ( ) & & ! gdialogPresent ( ) & & ! xdialogPresent ( ) & & tkinter3Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python3-tkinter " ) ; return 1 ; }
strcpy ( lDialogString , gPython3Name ) ;
strcat ( lDialogString ,
" -S -c \" import tkinter;from tkinter import messagebox;root=tkinter.Tk();root.withdraw(); " ) ;
strcat ( lDialogString , " res=messagebox. " ) ;
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
strcat ( lDialogString , " askokcancel( " ) ;
if ( aDefaultButton )
{
strcat ( lDialogString , " default=messagebox.OK, " ) ;
}
else
{
strcat ( lDialogString , " default=messagebox.CANCEL, " ) ;
}
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
strcat ( lDialogString , " askyesno( " ) ;
if ( aDefaultButton )
{
strcat ( lDialogString , " default=messagebox.YES, " ) ;
}
else
{
strcat ( lDialogString , " default=messagebox.NO, " ) ;
}
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " askyesnocancel( " ) ;
switch ( aDefaultButton )
{
case 1 : strcat ( lDialogString , " default=messagebox.YES, " ) ; break ;
case 2 : strcat ( lDialogString , " default=messagebox.NO, " ) ; break ;
case 0 : strcat ( lDialogString , " default=messagebox.CANCEL, " ) ; break ;
}
}
else
{
strcat ( lDialogString , " showinfo( " ) ;
}
strcat ( lDialogString , " icon=' " ) ;
if ( aIconType & & ( ! strcmp ( " question " , aIconType )
| | ! strcmp ( " error " , aIconType )
| | ! strcmp ( " warning " , aIconType ) ) )
{
strcat ( lDialogString , aIconType ) ;
}
else
{
strcat ( lDialogString , " info " ) ;
}
strcat ( lDialogString , " ', " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " message=' " ) ;
lpDialogString = lDialogString + strlen ( lDialogString ) ;
tfd_replaceSubStr ( aMessage , " \n " , " \\ n " , lpDialogString ) ;
strcat ( lDialogString , " ' " ) ;
}
if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " ); \n \
if res is None : \ n \ tprint ( 0 ) \ n \
elif res is False : \ n \ tprint ( 2 ) \ n \
else : \ n \ tprint ( 1 ) \ n \ " " ) ;
}
else
{
strcat ( lDialogString , " ); \n \
if res is False : \ n \ tprint ( 0 ) \ n \
else : \ n \ tprint ( 1 ) \ n \ " " ) ;
}
}
else if ( ! gxmessagePresent ( ) & & ! gmessagePresent ( ) & & ! gdialogPresent ( ) & & ! xdialogPresent ( ) & & tkinter2Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python2-tkinter " ) ; return 1 ; }
strcpy ( lDialogString , " export PYTHONIOENCODING=utf-8; " ) ;
strcat ( lDialogString , gPython2Name ) ;
if ( ! isTerminalRunning ( ) & & tfd_isDarwin ( ) )
{
strcat ( lDialogString , " -i " ) ; /* for osx without console */
}
strcat ( lDialogString ,
" -S -c \" import Tkinter,tkMessageBox;root=Tkinter.Tk();root.withdraw(); " ) ;
if ( tfd_isDarwin ( ) )
{
strcat ( lDialogString ,
" import os;os.system('''/usr/bin/osascript -e 'tell app \\ \" Finder \\ \" to set \
frontmost of process \ \ \ " Python \\ \" to true' '''); " ) ;
}
strcat ( lDialogString , " res=tkMessageBox. " ) ;
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
strcat ( lDialogString , " askokcancel( " ) ;
if ( aDefaultButton )
{
strcat ( lDialogString , " default=tkMessageBox.OK, " ) ;
}
else
{
strcat ( lDialogString , " default=tkMessageBox.CANCEL, " ) ;
}
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
strcat ( lDialogString , " askyesno( " ) ;
if ( aDefaultButton )
{
strcat ( lDialogString , " default=tkMessageBox.YES, " ) ;
}
else
{
strcat ( lDialogString , " default=tkMessageBox.NO, " ) ;
}
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " askyesnocancel( " ) ;
switch ( aDefaultButton )
{
case 1 : strcat ( lDialogString , " default=tkMessageBox.YES, " ) ; break ;
case 2 : strcat ( lDialogString , " default=tkMessageBox.NO, " ) ; break ;
case 0 : strcat ( lDialogString , " default=tkMessageBox.CANCEL, " ) ; break ;
}
}
else
{
strcat ( lDialogString , " showinfo( " ) ;
}
strcat ( lDialogString , " icon=' " ) ;
if ( aIconType & & ( ! strcmp ( " question " , aIconType )
| | ! strcmp ( " error " , aIconType )
| | ! strcmp ( " warning " , aIconType ) ) )
{
strcat ( lDialogString , aIconType ) ;
}
else
{
strcat ( lDialogString , " info " ) ;
}
strcat ( lDialogString , " ', " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " message=' " ) ;
lpDialogString = lDialogString + strlen ( lDialogString ) ;
tfd_replaceSubStr ( aMessage , " \n " , " \\ n " , lpDialogString ) ;
strcat ( lDialogString , " ' " ) ;
}
if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " ); \n \
if res is None : \ n \ tprint 0 \ n \
elif res is False : \ n \ tprint 2 \ n \
else : \ n \ tprint 1 \ n \ " " ) ;
}
else
{
strcat ( lDialogString , " ); \n \
if res is False : \ n \ tprint 0 \ n \
else : \ n \ tprint 1 \ n \ " " ) ;
}
}
else if ( gxmessagePresent ( ) | | gmessagePresent ( ) | | ( ! gdialogPresent ( ) & & ! xdialogPresent ( ) & & xmessagePresent ( ) ) )
{
if ( gxmessagePresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " gxmessage " ) ; return 1 ; }
strcpy ( lDialogString , " gxmessage " ) ;
}
else if ( gmessagePresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " gmessage " ) ; return 1 ; }
strcpy ( lDialogString , " gmessage " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " xmessage " ) ; return 1 ; }
strcpy ( lDialogString , " xmessage " ) ;
}
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
strcat ( lDialogString , " -buttons Ok:1,Cancel:0 " ) ;
switch ( aDefaultButton )
{
case 1 : strcat ( lDialogString , " -default Ok " ) ; break ;
case 0 : strcat ( lDialogString , " -default Cancel " ) ; break ;
}
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
strcat ( lDialogString , " -buttons Yes:1,No:0 " ) ;
switch ( aDefaultButton )
{
case 1 : strcat ( lDialogString , " -default Yes " ) ; break ;
case 0 : strcat ( lDialogString , " -default No " ) ; break ;
}
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " -buttons Yes:1,No:2,Cancel:0 " ) ;
switch ( aDefaultButton )
{
case 1 : strcat ( lDialogString , " -default Yes " ) ; break ;
case 2 : strcat ( lDialogString , " -default No " ) ; break ;
case 0 : strcat ( lDialogString , " -default Cancel " ) ; break ;
}
}
else
{
strcat ( lDialogString , " -buttons Ok:1 " ) ;
strcat ( lDialogString , " -default Ok " ) ;
}
strcat ( lDialogString , " -center \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " -title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " ; echo $? " ) ;
}
else if ( xdialogPresent ( ) | | gdialogPresent ( ) | | dialogName ( ) | | whiptailPresent ( ) )
{
if ( gdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " gdialog " ) ; return 1 ; }
lWasGraphicDialog = 1 ;
strcpy ( lDialogString , " (gdialog " ) ;
}
else if ( xdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " xdialog " ) ; return 1 ; }
lWasGraphicDialog = 1 ;
strcpy ( lDialogString , " (Xdialog " ) ;
}
else if ( dialogName ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return 0 ; }
if ( isTerminalRunning ( ) )
{
strcpy ( lDialogString , " (dialog " ) ;
}
else
{
lWasXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " '( " ) ;
strcat ( lDialogString , dialogName ( ) ) ;
strcat ( lDialogString , " " ) ;
}
}
else if ( isTerminalRunning ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " whiptail " ) ; return 0 ; }
strcpy ( lDialogString , " (whiptail " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " whiptail " ) ; return 0 ; }
lWasXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " '(whiptail " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( ! xdialogPresent ( ) & & ! gdialogPresent ( ) )
{
if ( aDialogType & & ( ! strcmp ( " okcancel " , aDialogType ) | | ! strcmp ( " yesno " , aDialogType )
| | ! strcmp ( " yesnocancel " , aDialogType ) ) )
{
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString , " tab: move focus " ) ;
strcat ( lDialogString , " \" " ) ;
}
}
if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
if ( ! aDefaultButton )
{
strcat ( lDialogString , " --defaultno " ) ;
}
strcat ( lDialogString ,
" --yes-label \" Ok \" --no-label \" Cancel \" --yesno " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
if ( ! aDefaultButton )
{
strcat ( lDialogString , " --defaultno " ) ;
}
strcat ( lDialogString , " --yesno " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
if ( ! aDefaultButton )
{
strcat ( lDialogString , " --defaultno " ) ;
}
strcat ( lDialogString , " --menu " ) ;
}
else
{
strcat ( lDialogString , " --msgbox " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( lWasGraphicDialog )
{
if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " 0 60 0 Yes \" \" No \" \" ) 2>/tmp/tinyfd.txt; \
if [ $ ? = 0 ] ; then tinyfdBool = 1 ; else tinyfdBool = 0 ; fi ; \
tinyfdRes = $ ( cat / tmp / tinyfd . txt ) ; echo $ tinyfdBool $ tinyfdRes " ) ;
}
else
{
strcat ( lDialogString ,
" 10 60 ) 2>&1;if [ $? = 0 ];then echo 1;else echo 0;fi " ) ;
}
}
else
{
if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " 0 60 0 Yes \" \" No \" \" >/dev/tty ) 2>/tmp/tinyfd.txt; \
if [ $ ? = 0 ] ; then tinyfdBool = 1 ; else tinyfdBool = 0 ; fi ; \
tinyfdRes = $ ( cat / tmp / tinyfd . txt ) ; echo $ tinyfdBool $ tinyfdRes " ) ;
if ( lWasXterm )
{
strcat ( lDialogString , " >/tmp/tinyfd0.txt';cat /tmp/tinyfd0.txt " ) ;
}
else
{
strcat ( lDialogString , " ; clear >/dev/tty " ) ;
}
}
else
{
strcat ( lDialogString , " 10 60 >/dev/tty) 2>&1;if [ $? = 0 ]; " ) ;
if ( lWasXterm )
{
strcat ( lDialogString ,
" then \n \t echo 1 \n else \n \t echo 0 \n fi >/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt " ) ;
}
else
{
strcat ( lDialogString ,
" then echo 1;else echo 0;fi;clear >/dev/tty " ) ;
}
}
}
}
else if ( ! isTerminalRunning ( ) & & terminalName ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return 0 ; }
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " ' " ) ;
if ( ! gWarningDisplayed & & ! tinyfd_forceConsole )
{
gWarningDisplayed = 1 ;
strcat ( lDialogString , " echo \" " ) ;
strcat ( lDialogString , gTitle ) ;
strcat ( lDialogString , " \" ; " ) ;
strcat ( lDialogString , " echo \" " ) ;
strcat ( lDialogString , tinyfd_needs ) ;
strcat ( lDialogString , " \" ;echo;echo; " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " echo \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" ;echo; " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " echo \" " ) ;
strcat ( lDialogString , aMessage ) ;
strcat ( lDialogString , " \" ; " ) ;
}
if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
strcat ( lDialogString , " echo -n \" y/n: \" ; " ) ;
strcat ( lDialogString , " stty sane -echo; " ) ;
strcat ( lDialogString ,
" answer=$( while ! head -c 1 | grep -i [ny];do true ;done); " ) ;
strcat ( lDialogString ,
" if echo \" $answer \" | grep -iq \" ^y \" ;then \n " ) ;
strcat ( lDialogString , " \t echo 1 \n else \n \t echo 0 \n fi " ) ;
}
else if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
strcat ( lDialogString , " echo -n \" [O]kay/[C]ancel: \" ; " ) ;
strcat ( lDialogString , " stty sane -echo; " ) ;
strcat ( lDialogString ,
" answer=$( while ! head -c 1 | grep -i [oc];do true ;done); " ) ;
strcat ( lDialogString ,
" if echo \" $answer \" | grep -iq \" ^o \" ;then \n " ) ;
strcat ( lDialogString , " \t echo 1 \n else \n \t echo 0 \n fi " ) ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
strcat ( lDialogString , " echo -n \" [Y]es/[N]o/[C]ancel: \" ; " ) ;
strcat ( lDialogString , " stty sane -echo; " ) ;
strcat ( lDialogString ,
" answer=$( while ! head -c 1 | grep -i [nyc];do true ;done); " ) ;
strcat ( lDialogString ,
" if echo \" $answer \" | grep -iq \" ^y \" ;then \n \t echo 1 \n " ) ;
strcat ( lDialogString , " elif echo \" $answer \" | grep -iq \" ^n \" ;then \n \t echo 2 \n " ) ;
strcat ( lDialogString , " else \n \t echo 0 \n fi " ) ;
}
else
{
strcat ( lDialogString , " echo -n \" press enter to continue \" ; " ) ;
strcat ( lDialogString , " stty sane -echo; " ) ;
strcat ( lDialogString ,
" answer=$( while ! head -c 1;do true ;done);echo 1 " ) ;
}
strcat ( lDialogString ,
" >/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt " ) ;
}
else if ( ! isTerminalRunning ( ) & & pythonDbusPresent ( ) & & ! strcmp ( " ok " , aDialogType ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python-dbus " ) ; return 1 ; }
strcpy ( lDialogString , gPythonName ) ;
strcat ( lDialogString , " -c \" import dbus;bus=dbus.SessionBus(); " ) ;
strcat ( lDialogString , " notif=bus.get_object('org.freedesktop.Notifications','/org/freedesktop/Notifications'); " ) ;
strcat ( lDialogString , " notify=dbus.Interface(notif,'org.freedesktop.Notifications'); " ) ;
strcat ( lDialogString , " notify.Notify('',0,' " ) ;
if ( aIconType & & strlen ( aIconType ) )
{
strcat ( lDialogString , aIconType ) ;
}
strcat ( lDialogString , " ',' " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , aTitle ) ;
}
strcat ( lDialogString , " ',' " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
lpDialogString = lDialogString + strlen ( lDialogString ) ;
tfd_replaceSubStr ( aMessage , " \n " , " \\ n " , lpDialogString ) ;
}
strcat ( lDialogString , " ','','',5000) \" " ) ;
}
else if ( ! isTerminalRunning ( ) & & ( perlPresent ( ) > = 2 ) & & ! strcmp ( " ok " , aDialogType ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " perl-dbus " ) ; return 1 ; }
strcpy ( lDialogString , " perl -e \" use Net::DBus; \
my \ \ $ sessionBus = Net : : DBus - > session ; \
my \ \ $ notificationsService = \ \ $ sessionBus - > get_service ( ' org . freedesktop . Notifications ' ) ; \
my \ \ $ notificationsObject = \ \ $ notificationsService - > get_object ( ' / org / freedesktop / Notifications ' , \
' org . freedesktop . Notifications ' ) ; " );
sprintf ( lDialogString + strlen ( lDialogString ) ,
" my \\ $notificationId; \\ $notificationId = \\ $notificationsObject->Notify(shift, 0, '%s', '%s', '%s', [], {}, -1); \" " ,
aIconType ? aIconType : " " , aTitle ? aTitle : " " , aMessage ? aMessage : " " ) ;
}
else if ( ! isTerminalRunning ( ) & & notifysendPresent ( ) & & ! strcmp ( " ok " , aDialogType ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " notifysend " ) ; return 1 ; }
strcpy ( lDialogString , " notify-send " ) ;
if ( aIconType & & strlen ( aIconType ) )
{
strcat ( lDialogString , " -i ' " ) ;
strcat ( lDialogString , aIconType ) ;
strcat ( lDialogString , " ' " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " | " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
tfd_replaceSubStr ( aMessage , " \n \t " , " | " , lBuff ) ;
tfd_replaceSubStr ( aMessage , " \n " , " | " , lBuff ) ;
tfd_replaceSubStr ( aMessage , " \t " , " " , lBuff ) ;
strcat ( lDialogString , lBuff ) ;
}
strcat ( lDialogString , " \" " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return 0 ; }
if ( ! gWarningDisplayed & & ! tinyfd_forceConsole )
{
gWarningDisplayed = 1 ;
printf ( " \n \n %s \n " , gTitle ) ;
printf ( " %s \n \n " , tinyfd_needs ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
printf ( " \n %s \n " , aTitle ) ;
}
tcgetattr ( 0 , & infoOri ) ;
tcgetattr ( 0 , & info ) ;
info . c_lflag & = ~ ICANON ;
info . c_cc [ VMIN ] = 1 ;
info . c_cc [ VTIME ] = 0 ;
tcsetattr ( 0 , TCSANOW , & info ) ;
if ( aDialogType & & ! strcmp ( " yesno " , aDialogType ) )
{
do
{
if ( aMessage & & strlen ( aMessage ) )
{
printf ( " \n %s \n " , aMessage ) ;
}
printf ( " y/n: " ) ; fflush ( stdout ) ;
lChar = tolower ( getchar ( ) ) ;
printf ( " \n \n " ) ;
}
while ( lChar ! = ' y ' & & lChar ! = ' n ' ) ;
lResult = lChar = = ' y ' ? 1 : 0 ;
}
else if ( aDialogType & & ! strcmp ( " okcancel " , aDialogType ) )
{
do
{
if ( aMessage & & strlen ( aMessage ) )
{
printf ( " \n %s \n " , aMessage ) ;
}
printf ( " [O]kay/[C]ancel: " ) ; fflush ( stdout ) ;
lChar = tolower ( getchar ( ) ) ;
printf ( " \n \n " ) ;
}
while ( lChar ! = ' o ' & & lChar ! = ' c ' ) ;
lResult = lChar = = ' o ' ? 1 : 0 ;
}
else if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
do
{
if ( aMessage & & strlen ( aMessage ) )
{
printf ( " \n %s \n " , aMessage ) ;
}
printf ( " [Y]es/[N]o/[C]ancel: " ) ; fflush ( stdout ) ;
lChar = tolower ( getchar ( ) ) ;
printf ( " \n \n " ) ;
}
while ( lChar ! = ' y ' & & lChar ! = ' n ' & & lChar ! = ' c ' ) ;
lResult = ( lChar = = ' y ' ) ? 1 : ( lChar = = ' n ' ) ? 2 : 0 ;
}
else
{
if ( aMessage & & strlen ( aMessage ) )
{
printf ( " \n %s \n \n " , aMessage ) ;
}
printf ( " press enter to continue " ) ; fflush ( stdout ) ;
getchar ( ) ;
printf ( " \n \n " ) ;
lResult = 1 ;
}
tcsetattr ( 0 , TCSANOW , & infoOri ) ;
free ( lDialogString ) ;
return lResult ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
if ( ! ( lIn = popen ( lDialogString , " r " ) ) )
{
free ( lDialogString ) ;
return 0 ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{ }
pclose ( lIn ) ;
/* printf( "lBuff: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
/* printf( "lBuff1: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
if ( aDialogType & & ! strcmp ( " yesnocancel " , aDialogType ) )
{
if ( lBuff [ 0 ] = = ' 1 ' )
{
if ( ! strcmp ( lBuff + 1 , " Yes " ) ) strcpy ( lBuff , " 1 " ) ;
else if ( ! strcmp ( lBuff + 1 , " No " ) ) strcpy ( lBuff , " 2 " ) ;
}
}
/* printf( "lBuff2: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
lResult = ! strcmp ( lBuff , " 2 " ) ? 2 : ! strcmp ( lBuff , " 1 " ) ? 1 : 0 ;
/* printf( "lResult: %d\n" , lResult ) ; */
free ( lDialogString ) ;
return lResult ;
}
/* return has only meaning for tinyfd_query */
int tinyfd_notifyPopup (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" may contain \n and \t */
char const * aIconType ) /* "info" "warning" "error" */
{
char lBuff [ MAX_PATH_OR_CMD ] ;
char * lDialogString = NULL ;
char * lpDialogString ;
FILE * lIn ;
size_t lTitleLen ;
size_t lMessageLen ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_notifyPopup ( " INVALID TITLE WITH QUOTES " , aMessage , aIconType ) ;
if ( tfd_quoteDetected ( aMessage ) ) return tinyfd_notifyPopup ( aTitle , " INVALID MESSAGE WITH QUOTES " , aIconType ) ;
if ( getenv ( " SSH_TTY " ) )
{
return tinyfd_messageBox ( aTitle , aMessage , " ok " , aIconType , 0 ) ;
}
lTitleLen = aTitle ? strlen ( aTitle ) : 0 ;
lMessageLen = aMessage ? strlen ( aMessage ) : 0 ;
if ( ! aTitle | | strcmp ( aTitle , " tinyfd_query " ) )
{
lDialogString = ( char * ) malloc ( MAX_PATH_OR_CMD + lTitleLen + lMessageLen ) ;
}
if ( osascriptPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " applescript " ) ; return 1 ; }
strcpy ( lDialogString , " osascript " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'tell application \" System Events \" ' -e 'Activate' " ) ;
strcat ( lDialogString , " -e 'try' -e 'display notification \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " with title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " ' -e 'end try' " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'end tell' " ) ;
}
else if ( tfd_kdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " kdialog " ) ; return 1 ; }
strcpy ( lDialogString , " kdialog " ) ;
if ( aIconType & & strlen ( aIconType ) )
{
strcat ( lDialogString , " --icon ' " ) ;
strcat ( lDialogString , aIconType ) ;
strcat ( lDialogString , " ' " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --passivepopup " ) ;
strcat ( lDialogString , " \" " ) ;
if ( aMessage )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" 5 " ) ;
}
else if ( ( tfd_zenity3Present ( ) > = 5 ) )
{
/* zenity 2.32 & 3.14 has the notification but with a bug: it doesnt return from it */
/* zenity 3.8 show the notification as an alert ok cancel box */
if ( tfd_zenity3Present ( ) > = 5 )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " zenity " ) ; return 1 ; }
strcpy ( lDialogString , " zenity " ) ;
}
strcat ( lDialogString , " --notification " ) ;
if ( aIconType & & strlen ( aIconType ) )
{
strcat ( lDialogString , " --window-icon ' " ) ;
strcat ( lDialogString , aIconType ) ;
strcat ( lDialogString , " ' " ) ;
}
strcat ( lDialogString , " --text \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \n " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
}
else if ( perlPresent ( ) > = 2 )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " perl-dbus " ) ; return 1 ; }
strcpy ( lDialogString , " perl -e \" use Net::DBus; \
my \ \ $ sessionBus = Net : : DBus - > session ; \
my \ \ $ notificationsService = \ \ $ sessionBus - > get_service ( ' org . freedesktop . Notifications ' ) ; \
my \ \ $ notificationsObject = \ \ $ notificationsService - > get_object ( ' / org / freedesktop / Notifications ' , \
' org . freedesktop . Notifications ' ) ; " );
sprintf ( lDialogString + strlen ( lDialogString ) ,
" my \\ $notificationId; \\ $notificationId = \\ $notificationsObject->Notify(shift, 0, '%s', '%s', '%s', [], {}, -1); \" " ,
aIconType ? aIconType : " " , aTitle ? aTitle : " " , aMessage ? aMessage : " " ) ;
}
else if ( pythonDbusPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python-dbus " ) ; return 1 ; }
strcpy ( lDialogString , gPythonName ) ;
strcat ( lDialogString , " -c \" import dbus;bus=dbus.SessionBus(); " ) ;
strcat ( lDialogString , " notif=bus.get_object('org.freedesktop.Notifications','/org/freedesktop/Notifications'); " ) ;
strcat ( lDialogString , " notify=dbus.Interface(notif,'org.freedesktop.Notifications'); " ) ;
strcat ( lDialogString , " notify.Notify('',0,' " ) ;
if ( aIconType & & strlen ( aIconType ) )
{
strcat ( lDialogString , aIconType ) ;
}
strcat ( lDialogString , " ',' " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , aTitle ) ;
}
strcat ( lDialogString , " ',' " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
lpDialogString = lDialogString + strlen ( lDialogString ) ;
tfd_replaceSubStr ( aMessage , " \n " , " \\ n " , lpDialogString ) ;
}
strcat ( lDialogString , " ','','',5000) \" " ) ;
}
else if ( notifysendPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " notifysend " ) ; return 1 ; }
strcpy ( lDialogString , " notify-send " ) ;
if ( aIconType & & strlen ( aIconType ) )
{
strcat ( lDialogString , " -i ' " ) ;
strcat ( lDialogString , aIconType ) ;
strcat ( lDialogString , " ' " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " | " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
tfd_replaceSubStr ( aMessage , " \n \t " , " | " , lBuff ) ;
tfd_replaceSubStr ( aMessage , " \n " , " | " , lBuff ) ;
tfd_replaceSubStr ( aMessage , " \t " , " " , lBuff ) ;
strcat ( lDialogString , lBuff ) ;
}
strcat ( lDialogString , " \" " ) ;
}
else
{
return tinyfd_messageBox ( aTitle , aMessage , " ok " , aIconType , 0 ) ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
if ( ! ( lIn = popen ( lDialogString , " r " ) ) )
{
free ( lDialogString ) ;
return 0 ;
}
pclose ( lIn ) ;
free ( lDialogString ) ;
return 1 ;
}
/* returns NULL on cancel */
char * tinyfd_inputBox (
char const * aTitle , /* NULL or "" */
char const * aMessage , /* NULL or "" (\n and \t have no effect) */
char const * aDefaultInput ) /* "" , if NULL it's a passwordBox */
{
static char lBuff [ MAX_PATH_OR_CMD ] ;
char * lDialogString = NULL ;
char * lpDialogString ;
FILE * lIn ;
int lResult ;
int lWasGdialog = 0 ;
int lWasGraphicDialog = 0 ;
int lWasXterm = 0 ;
int lWasBasicXterm = 0 ;
struct termios oldt ;
struct termios newt ;
char * lEOF ;
size_t lTitleLen ;
size_t lMessageLen ;
if ( ! aTitle & & ! aMessage & & ! aDefaultInput ) return lBuff ; /* now I can fill lBuff from outside */
lBuff [ 0 ] = ' \0 ' ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_inputBox ( " INVALID TITLE WITH QUOTES " , aMessage , aDefaultInput ) ;
if ( tfd_quoteDetected ( aMessage ) ) return tinyfd_inputBox ( aTitle , " INVALID MESSAGE WITH QUOTES " , aDefaultInput ) ;
if ( tfd_quoteDetected ( aDefaultInput ) ) return tinyfd_inputBox ( aTitle , aMessage , " INVALID DEFAULT_INPUT WITH QUOTES " ) ;
lTitleLen = aTitle ? strlen ( aTitle ) : 0 ;
lMessageLen = aMessage ? strlen ( aMessage ) : 0 ;
if ( ! aTitle | | strcmp ( aTitle , " tinyfd_query " ) )
{
lDialogString = ( char * ) malloc ( MAX_PATH_OR_CMD + lTitleLen + lMessageLen ) ;
}
if ( osascriptPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " applescript " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " osascript " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'tell application \" System Events \" ' -e 'Activate' " ) ;
strcat ( lDialogString , " -e 'try' -e 'display dialog \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , " default answer \" " ) ;
if ( aDefaultInput & & strlen ( aDefaultInput ) )
{
strcat ( lDialogString , aDefaultInput ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( ! aDefaultInput )
{
strcat ( lDialogString , " hidden answer true " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " with title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " with icon note' " ) ;
strcat ( lDialogString , " -e ' \" 1 \" & text returned of result' " ) ;
strcat ( lDialogString , " -e 'on error number -128' " ) ;
strcat ( lDialogString , " -e '0' " ) ;
strcat ( lDialogString , " -e 'end try' " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'end tell' " ) ;
}
else if ( tfd_kdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " kdialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(kdialog " ) ;
if ( ( tfd_kdialogPresent ( ) = = 2 ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
if ( ! aDefaultInput )
{
strcat ( lDialogString , " --password " ) ;
}
else
{
strcat ( lDialogString , " --inputbox " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" \" " ) ;
if ( aDefaultInput & & strlen ( aDefaultInput ) )
{
strcat ( lDialogString , aDefaultInput ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString ,
" );if [ $? = 0 ];then echo 1$szAnswer;else echo 0$szAnswer;fi " ) ;
}
else if ( tfd_zenityPresent ( ) | | tfd_matedialogPresent ( ) | | tfd_shellementaryPresent ( ) | | tfd_qarmaPresent ( ) )
{
if ( tfd_zenityPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " zenity " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(zenity " ) ;
if ( ( tfd_zenity3Present ( ) > = 4 ) & & ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(sleep .01;xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
else if ( tfd_matedialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " matedialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(matedialog " ) ;
}
else if ( tfd_shellementaryPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " shellementary " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(shellementary " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " qarma " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(qarma " ) ;
if ( ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
strcat ( lDialogString , " --entry " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " --text= \" " ) ;
strcat ( lDialogString , aMessage ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultInput & & strlen ( aDefaultInput ) )
{
strcat ( lDialogString , " --entry-text= \" " ) ;
strcat ( lDialogString , aDefaultInput ) ;
strcat ( lDialogString , " \" " ) ;
}
else
{
strcat ( lDialogString , " --hide-text " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
strcat ( lDialogString ,
" );if [ $? = 0 ];then echo 1$szAnswer;else echo 0$szAnswer;fi " ) ;
}
else if ( tfd_yadPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " yad " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(yad --entry " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " --text= \" " ) ;
strcat ( lDialogString , aMessage ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultInput & & strlen ( aDefaultInput ) )
{
strcat ( lDialogString , " --entry-text= \" " ) ;
strcat ( lDialogString , aDefaultInput ) ;
strcat ( lDialogString , " \" " ) ;
}
else
{
strcat ( lDialogString , " --hide-text " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
strcat ( lDialogString ,
" );if [ $? = 0 ];then echo 1$szAnswer;else echo 0$szAnswer;fi " ) ;
}
else if ( gxmessagePresent ( ) | | gmessagePresent ( ) )
{
if ( gxmessagePresent ( ) ) {
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " gxmessage " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(gxmessage -buttons Ok:1,Cancel:0 -center \" " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " gmessage " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " szAnswer=$(gmessage -buttons Ok:1,Cancel:0 -center \" " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " -title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " -entrytext \" " ) ;
if ( aDefaultInput & & strlen ( aDefaultInput ) )
{
strcat ( lDialogString , aDefaultInput ) ;
}
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , " );echo $?$szAnswer " ) ;
}
else if ( ! gdialogPresent ( ) & & ! xdialogPresent ( ) & & tkinter3Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python3-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , gPython3Name ) ;
strcat ( lDialogString ,
" -S -c \" import tkinter; from tkinter import simpledialog;root=tkinter.Tk();root.withdraw(); " ) ;
strcat ( lDialogString , " res=simpledialog.askstring( " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " prompt=' " ) ;
lpDialogString = lDialogString + strlen ( lDialogString ) ;
tfd_replaceSubStr ( aMessage , " \n " , " \\ n " , lpDialogString ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultInput )
{
if ( strlen ( aDefaultInput ) )
{
strcat ( lDialogString , " initialvalue=' " ) ;
strcat ( lDialogString , aDefaultInput ) ;
strcat ( lDialogString , " ', " ) ;
}
}
else
{
strcat ( lDialogString , " show='*' " ) ;
}
strcat ( lDialogString , " ); \n if res is None : \n \t print(0) " ) ;
strcat ( lDialogString , " \n else : \n \t print('1'+res) \n \" " ) ;
}
else if ( ! gdialogPresent ( ) & & ! xdialogPresent ( ) & & tkinter2Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python2-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " export PYTHONIOENCODING=utf-8; " ) ;
strcat ( lDialogString , gPython2Name ) ;
if ( ! isTerminalRunning ( ) & & tfd_isDarwin ( ) )
{
strcat ( lDialogString , " -i " ) ; /* for osx without console */
}
strcat ( lDialogString ,
" -S -c \" import Tkinter,tkSimpleDialog;root=Tkinter.Tk();root.withdraw(); " ) ;
if ( tfd_isDarwin ( ) )
{
strcat ( lDialogString ,
" import os;os.system('''/usr/bin/osascript -e 'tell app \\ \" Finder \\ \" to set \
frontmost of process \ \ \ " Python \\ \" to true' '''); " ) ;
}
strcat ( lDialogString , " res=tkSimpleDialog.askstring( " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , " prompt=' " ) ;
lpDialogString = lDialogString + strlen ( lDialogString ) ;
tfd_replaceSubStr ( aMessage , " \n " , " \\ n " , lpDialogString ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultInput )
{
if ( strlen ( aDefaultInput ) )
{
strcat ( lDialogString , " initialvalue=' " ) ;
strcat ( lDialogString , aDefaultInput ) ;
strcat ( lDialogString , " ', " ) ;
}
}
else
{
strcat ( lDialogString , " show='*' " ) ;
}
strcat ( lDialogString , " ); \n if res is None : \n \t print 0 " ) ;
strcat ( lDialogString , " \n else : \n \t print '1'+res \n \" " ) ;
}
else if ( gdialogPresent ( ) | | xdialogPresent ( ) | | dialogName ( ) | | whiptailPresent ( ) )
{
if ( gdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " gdialog " ) ; return ( char * ) 1 ; }
lWasGraphicDialog = 1 ;
lWasGdialog = 1 ;
strcpy ( lDialogString , " (gdialog " ) ;
}
else if ( xdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " xdialog " ) ; return ( char * ) 1 ; }
lWasGraphicDialog = 1 ;
strcpy ( lDialogString , " (Xdialog " ) ;
}
else if ( dialogName ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
if ( isTerminalRunning ( ) )
{
strcpy ( lDialogString , " (dialog " ) ;
}
else
{
lWasXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " '( " ) ;
strcat ( lDialogString , dialogName ( ) ) ;
strcat ( lDialogString , " " ) ;
}
}
else if ( isTerminalRunning ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " whiptail " ) ; return ( char * ) 0 ; }
strcpy ( lDialogString , " (whiptail " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " whiptail " ) ; return ( char * ) 0 ; }
lWasXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " '(whiptail " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( ! xdialogPresent ( ) & & ! gdialogPresent ( ) )
{
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString , " tab: move focus " ) ;
if ( ! aDefaultInput & & ! lWasGdialog )
{
strcat ( lDialogString , " (sometimes nothing, no blink nor star, is shown in text field) " ) ;
}
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultInput | | lWasGdialog )
{
strcat ( lDialogString , " --inputbox " ) ;
}
else
{
if ( ! lWasGraphicDialog & & dialogName ( ) & & isDialogVersionBetter09b ( ) )
{
strcat ( lDialogString , " --insecure " ) ;
}
strcat ( lDialogString , " --passwordbox " ) ;
}
strcat ( lDialogString , " \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" 10 60 " ) ;
if ( aDefaultInput & & strlen ( aDefaultInput ) )
{
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , aDefaultInput ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( lWasGraphicDialog )
{
strcat ( lDialogString , " ) 2>/tmp/tinyfd.txt; \
if [ $ ? = 0 ] ; then tinyfdBool = 1 ; else tinyfdBool = 0 ; fi ; \
tinyfdRes = $ ( cat / tmp / tinyfd . txt ) ; echo $ tinyfdBool $ tinyfdRes " ) ;
}
else
{
strcat ( lDialogString , " >/dev/tty ) 2>/tmp/tinyfd.txt; \
if [ $ ? = 0 ] ; then tinyfdBool = 1 ; else tinyfdBool = 0 ; fi ; \
tinyfdRes = $ ( cat / tmp / tinyfd . txt ) ; echo $ tinyfdBool $ tinyfdRes " ) ;
if ( lWasXterm )
{
strcat ( lDialogString , " >/tmp/tinyfd0.txt';cat /tmp/tinyfd0.txt " ) ;
}
else
{
strcat ( lDialogString , " ; clear >/dev/tty " ) ;
}
}
}
else if ( ! isTerminalRunning ( ) & & terminalName ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return ( char * ) 0 ; }
lWasBasicXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " ' " ) ;
if ( ! gWarningDisplayed & & ! tinyfd_forceConsole )
{
gWarningDisplayed = 1 ;
tinyfd_messageBox ( gTitle , tinyfd_needs , " ok " , " warning " , 0 ) ;
}
if ( aTitle & & strlen ( aTitle ) & & ! tinyfd_forceConsole )
{
strcat ( lDialogString , " echo \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" ;echo; " ) ;
}
strcat ( lDialogString , " echo \" " ) ;
if ( aMessage & & strlen ( aMessage ) )
{
strcat ( lDialogString , aMessage ) ;
}
strcat ( lDialogString , " \" ;read " ) ;
if ( ! aDefaultInput )
{
strcat ( lDialogString , " -s " ) ;
}
strcat ( lDialogString , " -p \" " ) ;
strcat ( lDialogString , " (esc+enter to cancel): \" ANSWER " ) ;
strcat ( lDialogString , " ;echo 1$ANSWER >/tmp/tinyfd.txt'; " ) ;
strcat ( lDialogString , " cat -v /tmp/tinyfd.txt " ) ;
}
else if ( ! gWarningDisplayed & & ! isTerminalRunning ( ) & & ! terminalName ( ) ) {
gWarningDisplayed = 1 ;
tinyfd_messageBox ( gTitle , tinyfd_needs , " ok " , " warning " , 0 ) ;
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " no_solution " ) ; return ( char * ) 0 ; }
free ( lDialogString ) ;
return NULL ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " basicinput " ) ; return ( char * ) 0 ; }
if ( ! gWarningDisplayed & & ! tinyfd_forceConsole )
{
gWarningDisplayed = 1 ;
tinyfd_messageBox ( gTitle , tinyfd_needs , " ok " , " warning " , 0 ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
printf ( " \n %s \n " , aTitle ) ;
}
if ( aMessage & & strlen ( aMessage ) )
{
printf ( " \n %s \n " , aMessage ) ;
}
printf ( " (esc+enter to cancel): " ) ; fflush ( stdout ) ;
if ( ! aDefaultInput )
{
tcgetattr ( STDIN_FILENO , & oldt ) ;
newt = oldt ;
newt . c_lflag & = ~ ECHO ;
tcsetattr ( STDIN_FILENO , TCSANOW , & newt ) ;
}
lEOF = fgets ( lBuff , MAX_PATH_OR_CMD , stdin ) ;
/* printf("lbuff<%c><%d>\n",lBuff[0],lBuff[0]); */
if ( ! lEOF | | ( lBuff [ 0 ] = = ' \0 ' ) )
{
free ( lDialogString ) ;
return NULL ;
}
if ( lBuff [ 0 ] = = ' \n ' )
{
lEOF = fgets ( lBuff , MAX_PATH_OR_CMD , stdin ) ;
/* printf("lbuff<%c><%d>\n",lBuff[0],lBuff[0]); */
if ( ! lEOF | | ( lBuff [ 0 ] = = ' \0 ' ) )
{
free ( lDialogString ) ;
return NULL ;
}
}
if ( ! aDefaultInput )
{
tcsetattr ( STDIN_FILENO , TCSANOW , & oldt ) ;
printf ( " \n " ) ;
}
printf ( " \n " ) ;
if ( strchr ( lBuff , 27 ) )
{
free ( lDialogString ) ;
return NULL ;
}
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
free ( lDialogString ) ;
return lBuff ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
lIn = popen ( lDialogString , " r " ) ;
if ( ! lIn )
{
if ( fileExists ( " /tmp/tinyfd.txt " ) )
{
wipefile ( " /tmp/tinyfd.txt " ) ;
remove ( " /tmp/tinyfd.txt " ) ;
}
if ( fileExists ( " /tmp/tinyfd0.txt " ) )
{
wipefile ( " /tmp/tinyfd0.txt " ) ;
remove ( " /tmp/tinyfd0.txt " ) ;
}
free ( lDialogString ) ;
return NULL ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{ }
pclose ( lIn ) ;
if ( fileExists ( " /tmp/tinyfd.txt " ) )
{
wipefile ( " /tmp/tinyfd.txt " ) ;
remove ( " /tmp/tinyfd.txt " ) ;
}
if ( fileExists ( " /tmp/tinyfd0.txt " ) )
{
wipefile ( " /tmp/tinyfd0.txt " ) ;
remove ( " /tmp/tinyfd0.txt " ) ;
}
/* printf( "len Buff: %lu\n" , strlen(lBuff) ) ; */
/* printf( "lBuff0: %s\n" , lBuff ) ; */
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
/* printf( "lBuff1: %s len: %lu \n" , lBuff , strlen(lBuff) ) ; */
if ( lWasBasicXterm )
{
if ( strstr ( lBuff , " ^[ " ) ) /* esc was pressed */
{
free ( lDialogString ) ;
return NULL ;
}
}
lResult = strncmp ( lBuff , " 1 " , 1 ) ? 0 : 1 ;
/* printf( "lResult: %d \n" , lResult ) ; */
if ( ! lResult )
{
free ( lDialogString ) ;
return NULL ;
}
/* printf( "lBuff+1: %s\n" , lBuff+1 ) ; */
free ( lDialogString ) ;
return lBuff + 1 ;
}
char * tinyfd_saveFileDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
char const * aSingleFilterDescription ) /* NULL or "image files" */
{
static char lBuff [ MAX_PATH_OR_CMD ] ;
char lDialogString [ MAX_PATH_OR_CMD ] ;
char lString [ MAX_PATH_OR_CMD ] ;
int i ;
int lWasGraphicDialog = 0 ;
int lWasXterm = 0 ;
char * p ;
char * lPointerInputBox ;
FILE * lIn ;
lBuff [ 0 ] = ' \0 ' ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_saveFileDialog ( " INVALID TITLE WITH QUOTES " , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription ) ;
if ( tfd_quoteDetected ( aDefaultPathAndFile ) ) return tinyfd_saveFileDialog ( aTitle , " INVALID DEFAULT_PATH WITH QUOTES " , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription ) ;
if ( tfd_quoteDetected ( aSingleFilterDescription ) ) return tinyfd_saveFileDialog ( aTitle , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , " INVALID FILTER_DESCRIPTION WITH QUOTES " ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( tfd_quoteDetected ( aFilterPatterns [ i ] ) ) return tinyfd_saveFileDialog ( " INVALID FILTER_PATTERN WITH QUOTES " , aDefaultPathAndFile , 0 , NULL , NULL ) ;
}
if ( osascriptPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " applescript " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " osascript " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'tell application \" Finder \" ' -e 'Activate' " ) ;
strcat ( lDialogString , " -e 'try' -e 'POSIX path of ( choose file name " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " with prompt \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " default location \" " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " \" " ) ;
}
getLastName ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " default name \" " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " )' " ) ;
strcat ( lDialogString , " -e 'on error number -128' " ) ;
strcat ( lDialogString , " -e 'end try' " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'end tell' " ) ;
}
else if ( tfd_kdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " kdialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " kdialog " ) ;
if ( ( tfd_kdialogPresent ( ) = = 2 ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
strcat ( lDialogString , " --getsavefilename " ) ;
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
if ( aDefaultPathAndFile [ 0 ] ! = ' / ' )
{
strcat ( lDialogString , " $PWD/ " ) ;
}
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , aDefaultPathAndFile ) ;
strcat ( lDialogString , " \" " ) ;
}
else
{
strcat ( lDialogString , " $PWD/ " ) ;
}
if ( aNumOfFilterPatterns > 0 )
{
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , aFilterPatterns [ 0 ] ) ;
for ( i = 1 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
}
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , " | " ) ;
strcat ( lDialogString , aSingleFilterDescription ) ;
}
strcat ( lDialogString , " \" " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
}
else if ( tfd_zenityPresent ( ) | | tfd_matedialogPresent ( ) | | tfd_shellementaryPresent ( ) | | tfd_qarmaPresent ( ) )
{
if ( tfd_zenityPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " zenity " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " zenity " ) ;
if ( ( tfd_zenity3Present ( ) > = 4 ) & & ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(sleep .01;xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
else if ( tfd_matedialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " matedialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " matedialog " ) ;
}
else if ( tfd_shellementaryPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " shellementary " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " shellementary " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " qarma " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " qarma " ) ;
if ( ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
strcat ( lDialogString , " --file-selection --save --confirm-overwrite " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
strcat ( lDialogString , " --filename= \" " ) ;
strcat ( lDialogString , aDefaultPathAndFile ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aNumOfFilterPatterns > 0 )
{
strcat ( lDialogString , " --file-filter=' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
strcat ( lDialogString , " | " ) ;
}
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
}
strcat ( lDialogString , " ' --file-filter='All files | *' " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( tfd_yadPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " yad " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " yad --file-selection --save --confirm-overwrite " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
strcat ( lDialogString , " --filename= \" " ) ;
strcat ( lDialogString , aDefaultPathAndFile ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aNumOfFilterPatterns > 0 )
{
strcat ( lDialogString , " --file-filter=' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
strcat ( lDialogString , " | " ) ;
}
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
}
strcat ( lDialogString , " ' --file-filter='All files | *' " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( ! xdialogPresent ( ) & & tkinter3Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python3-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , gPython3Name ) ;
strcat ( lDialogString ,
" -S -c \" import tkinter;from tkinter import filedialog;root=tkinter.Tk();root.withdraw(); " ) ;
strcat ( lDialogString , " res=filedialog.asksaveasfilename( " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialdir=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
getLastName ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialfile=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
}
if ( ( aNumOfFilterPatterns > 1 )
| | ( ( aNumOfFilterPatterns = = 1 ) /* test because poor osx behaviour */
& & ( aFilterPatterns [ 0 ] [ strlen ( aFilterPatterns [ 0 ] ) - 1 ] ! = ' * ' ) ) )
{
strcat ( lDialogString , " filetypes=( " ) ;
strcat ( lDialogString , " (' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
}
strcat ( lDialogString , " ',( " ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " ' " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
strcat ( lDialogString , " ', " ) ;
}
strcat ( lDialogString , " )), " ) ;
strcat ( lDialogString , " ('All files','*')) " ) ;
}
strcat ( lDialogString , " ); \n if not isinstance(res, tuple): \n \t print(res) \n \" " ) ;
}
else if ( ! xdialogPresent ( ) & & tkinter2Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python2-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " export PYTHONIOENCODING=utf-8; " ) ;
strcat ( lDialogString , gPython2Name ) ;
if ( ! isTerminalRunning ( ) & & tfd_isDarwin ( ) )
{
strcat ( lDialogString , " -i " ) ; /* for osx without console */
}
strcat ( lDialogString ,
" -S -c \" import Tkinter,tkFileDialog;root=Tkinter.Tk();root.withdraw(); " ) ;
if ( tfd_isDarwin ( ) )
{
strcat ( lDialogString ,
" import os;os.system('''/usr/bin/osascript -e 'tell app \\ \" Finder \\ \" to set \
frontmost of process \ \ \ " Python \\ \" to true' '''); " ) ;
}
strcat ( lDialogString , " res=tkFileDialog.asksaveasfilename( " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialdir=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
getLastName ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialfile=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
}
if ( ( aNumOfFilterPatterns > 1 )
| | ( ( aNumOfFilterPatterns = = 1 ) /* test because poor osx behaviour */
& & ( aFilterPatterns [ 0 ] [ strlen ( aFilterPatterns [ 0 ] ) - 1 ] ! = ' * ' ) ) )
{
strcat ( lDialogString , " filetypes=( " ) ;
strcat ( lDialogString , " (' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
}
strcat ( lDialogString , " ',( " ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " ' " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
strcat ( lDialogString , " ', " ) ;
}
strcat ( lDialogString , " )), " ) ;
strcat ( lDialogString , " ('All files','*')) " ) ;
}
strcat ( lDialogString , " ); \n if not isinstance(res, tuple): \n \t print res \n \" " ) ;
}
else if ( xdialogPresent ( ) | | dialogName ( ) )
{
if ( xdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " xdialog " ) ; return ( char * ) 1 ; }
lWasGraphicDialog = 1 ;
strcpy ( lDialogString , " (Xdialog " ) ;
}
else if ( isTerminalRunning ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
strcpy ( lDialogString , " (dialog " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
lWasXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " '( " ) ;
strcat ( lDialogString , dialogName ( ) ) ;
strcat ( lDialogString , " " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( ! xdialogPresent ( ) & & ! gdialogPresent ( ) )
{
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString ,
" tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY " ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --fselect \" " ) ;
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
if ( ! strchr ( aDefaultPathAndFile , ' / ' ) )
{
strcat ( lDialogString , " ./ " ) ;
}
strcat ( lDialogString , aDefaultPathAndFile ) ;
}
else if ( ! isTerminalRunning ( ) & & ! lWasGraphicDialog )
{
strcat ( lDialogString , getenv ( " HOME " ) ) ;
strcat ( lDialogString , " / " ) ;
}
else
{
strcat ( lDialogString , " ./ " ) ;
}
if ( lWasGraphicDialog )
{
strcat ( lDialogString , " \" 0 60 ) 2>&1 " ) ;
}
else
{
strcat ( lDialogString , " \" 0 60 >/dev/tty) " ) ;
if ( lWasXterm )
{
strcat ( lDialogString ,
" 2>/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt " ) ;
}
else
{
strcat ( lDialogString , " 2>&1 ; clear >/dev/tty " ) ;
}
}
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { return tinyfd_inputBox ( aTitle , NULL , NULL ) ; }
strcpy ( lBuff , " Save file in " ) ;
strcat ( lBuff , getCurDir ( ) ) ;
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , lBuff , " " ) ;
if ( p ) strcpy ( lBuff , p ) ; else lBuff [ 0 ] = ' \0 ' ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lString ) ; /* restore its previous content to tinyfd_inputBox */
p = lBuff ;
getPathWithoutFinalSlash ( lString , p ) ;
if ( strlen ( lString ) & & ! dirExists ( lString ) )
{
return NULL ;
}
getLastName ( lString , p ) ;
if ( ! strlen ( lString ) )
{
return NULL ;
}
return p ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
if ( ! ( lIn = popen ( lDialogString , " r " ) ) )
{
return NULL ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{ }
pclose ( lIn ) ;
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
/* printf( "lBuff: %s\n" , lBuff ) ; */
if ( ! strlen ( lBuff ) )
{
return NULL ;
}
getPathWithoutFinalSlash ( lString , lBuff ) ;
if ( strlen ( lString ) & & ! dirExists ( lString ) )
{
return NULL ;
}
getLastName ( lString , lBuff ) ;
if ( ! filenameValid ( lString ) )
{
return NULL ;
}
return lBuff ;
}
/* in case of multiple files, the separator is | */
char * tinyfd_openFileDialog (
char const * aTitle , /* NULL or "" */
char const * aDefaultPathAndFile , /* NULL or "" */
int aNumOfFilterPatterns , /* 0 */
char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
char const * aSingleFilterDescription , /* NULL or "image files" */
int aAllowMultipleSelects ) /* 0 or 1 */
{
char lDialogString [ MAX_PATH_OR_CMD ] ;
char lString [ MAX_PATH_OR_CMD ] ;
int i ;
FILE * lIn ;
char * p ;
char * lPointerInputBox ;
int lWasKdialog = 0 ;
int lWasGraphicDialog = 0 ;
int lWasXterm = 0 ;
size_t lFullBuffLen ;
static char * lBuff = NULL ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_openFileDialog ( " INVALID TITLE WITH QUOTES " , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription , aAllowMultipleSelects ) ;
if ( tfd_quoteDetected ( aDefaultPathAndFile ) ) return tinyfd_openFileDialog ( aTitle , " INVALID DEFAULT_PATH WITH QUOTES " , aNumOfFilterPatterns , aFilterPatterns , aSingleFilterDescription , aAllowMultipleSelects ) ;
if ( tfd_quoteDetected ( aSingleFilterDescription ) ) return tinyfd_openFileDialog ( aTitle , aDefaultPathAndFile , aNumOfFilterPatterns , aFilterPatterns , " INVALID FILTER_DESCRIPTION WITH QUOTES " , aAllowMultipleSelects ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
if ( tfd_quoteDetected ( aFilterPatterns [ i ] ) ) return tinyfd_openFileDialog ( " INVALID FILTER_PATTERN WITH QUOTES " , aDefaultPathAndFile , 0 , NULL , NULL , aAllowMultipleSelects ) ;
}
free ( lBuff ) ;
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) )
{
lBuff = NULL ;
}
else
{
if ( aAllowMultipleSelects )
{
lFullBuffLen = MAX_MULTIPLE_FILES * MAX_PATH_OR_CMD + 1 ;
lBuff = ( char * ) ( malloc ( lFullBuffLen * sizeof ( char ) ) ) ;
if ( ! lBuff )
{
lFullBuffLen = LOW_MULTIPLE_FILES * MAX_PATH_OR_CMD + 1 ;
lBuff = ( char * ) ( malloc ( lFullBuffLen * sizeof ( char ) ) ) ;
}
}
else
{
lFullBuffLen = MAX_PATH_OR_CMD + 1 ;
lBuff = ( char * ) ( malloc ( lFullBuffLen * sizeof ( char ) ) ) ;
}
if ( ! lBuff ) return NULL ;
lBuff [ 0 ] = ' \0 ' ;
}
if ( osascriptPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " applescript " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " osascript " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'tell application \" System Events \" ' -e 'Activate' " ) ;
strcat ( lDialogString , " -e 'try' -e ' " ) ;
if ( ! aAllowMultipleSelects )
{
strcat ( lDialogString , " POSIX path of ( " ) ;
}
else
{
strcat ( lDialogString , " set mylist to " ) ;
}
strcat ( lDialogString , " choose file " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " with prompt \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " default location \" " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aNumOfFilterPatterns > 0 )
{
strcat ( lDialogString , " of type { \" " ) ;
strcat ( lDialogString , aFilterPatterns [ 0 ] + 2 ) ;
strcat ( lDialogString , " \" " ) ;
for ( i = 1 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " , \" " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] + 2 ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " } " ) ;
}
if ( aAllowMultipleSelects )
{
strcat ( lDialogString , " multiple selections allowed true ' " ) ;
strcat ( lDialogString ,
" -e 'set mystring to POSIX path of item 1 of mylist' " ) ;
strcat ( lDialogString ,
" -e 'repeat with i from 2 to the count of mylist' " ) ;
strcat ( lDialogString , " -e 'set mystring to mystring & \" | \" ' " ) ;
strcat ( lDialogString ,
" -e 'set mystring to mystring & POSIX path of item i of mylist' " ) ;
strcat ( lDialogString , " -e 'end repeat' " ) ;
strcat ( lDialogString , " -e 'mystring' " ) ;
}
else
{
strcat ( lDialogString , " )' " ) ;
}
strcat ( lDialogString , " -e 'on error number -128' " ) ;
strcat ( lDialogString , " -e 'end try' " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'end tell' " ) ;
}
else if ( tfd_kdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " kdialog " ) ; return ( char * ) 1 ; }
lWasKdialog = 1 ;
strcpy ( lDialogString , " kdialog " ) ;
if ( ( tfd_kdialogPresent ( ) = = 2 ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
strcat ( lDialogString , " --getopenfilename " ) ;
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
if ( aDefaultPathAndFile [ 0 ] ! = ' / ' )
{
strcat ( lDialogString , " $PWD/ " ) ;
}
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , aDefaultPathAndFile ) ;
strcat ( lDialogString , " \" " ) ;
}
else
{
strcat ( lDialogString , " $PWD/ " ) ;
}
if ( aNumOfFilterPatterns > 0 )
{
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , aFilterPatterns [ 0 ] ) ;
for ( i = 1 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
}
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , " | " ) ;
strcat ( lDialogString , aSingleFilterDescription ) ;
}
strcat ( lDialogString , " \" " ) ;
}
if ( aAllowMultipleSelects )
{
strcat ( lDialogString , " --multiple --separate-output " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
}
else if ( tfd_zenityPresent ( ) | | tfd_matedialogPresent ( ) | | tfd_shellementaryPresent ( ) | | tfd_qarmaPresent ( ) )
{
if ( tfd_zenityPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " zenity " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " zenity " ) ;
if ( ( tfd_zenity3Present ( ) > = 4 ) & & ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(sleep .01;xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
else if ( tfd_matedialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " matedialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " matedialog " ) ;
}
else if ( tfd_shellementaryPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " shellementary " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " shellementary " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " qarma " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " qarma " ) ;
if ( ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
strcat ( lDialogString , " --file-selection " ) ;
if ( aAllowMultipleSelects )
{
strcat ( lDialogString , " --multiple " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
strcat ( lDialogString , " --filename= \" " ) ;
strcat ( lDialogString , aDefaultPathAndFile ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aNumOfFilterPatterns > 0 )
{
strcat ( lDialogString , " --file-filter=' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
strcat ( lDialogString , " | " ) ;
}
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
}
strcat ( lDialogString , " ' --file-filter='All files | *' " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( tfd_yadPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " yad " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " yad --file-selection " ) ;
if ( aAllowMultipleSelects )
{
strcat ( lDialogString , " --multiple " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
strcat ( lDialogString , " --filename= \" " ) ;
strcat ( lDialogString , aDefaultPathAndFile ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aNumOfFilterPatterns > 0 )
{
strcat ( lDialogString , " --file-filter=' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
strcat ( lDialogString , " | " ) ;
}
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
}
strcat ( lDialogString , " ' --file-filter='All files | *' " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( tkinter3Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python3-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , gPython3Name ) ;
strcat ( lDialogString ,
" -S -c \" import tkinter;from tkinter import filedialog;root=tkinter.Tk();root.withdraw(); " ) ;
strcat ( lDialogString , " lFiles=filedialog.askopenfilename( " ) ;
if ( aAllowMultipleSelects )
{
strcat ( lDialogString , " multiple=1, " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialdir=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
getLastName ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialfile=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
}
if ( ( aNumOfFilterPatterns > 1 )
| | ( ( aNumOfFilterPatterns = = 1 ) /*test because poor osx behaviour*/
& & ( aFilterPatterns [ 0 ] [ strlen ( aFilterPatterns [ 0 ] ) - 1 ] ! = ' * ' ) ) )
{
strcat ( lDialogString , " filetypes=( " ) ;
strcat ( lDialogString , " (' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
}
strcat ( lDialogString , " ',( " ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " ' " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
strcat ( lDialogString , " ', " ) ;
}
strcat ( lDialogString , " )), " ) ;
strcat ( lDialogString , " ('All files','*')) " ) ;
}
strcat ( lDialogString , " ); \
\ nif not isinstance ( lFiles , tuple ) : \ n \ tprint ( lFiles ) \ nelse : \
\ n \ tlFilesString = ' ' \ n \ tfor lFile in lFiles : \ n \ t \ tlFilesString + = str ( lFile ) + ' | ' \
\ n \ tprint ( lFilesString [ : - 1 ] ) \ n \ " " ) ;
}
else if ( tkinter2Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python2-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " export PYTHONIOENCODING=utf-8; " ) ;
strcat ( lDialogString , gPython2Name ) ;
if ( ! isTerminalRunning ( ) & & tfd_isDarwin ( ) )
{
strcat ( lDialogString , " -i " ) ; /* for osx without console */
}
strcat ( lDialogString ,
" -S -c \" import Tkinter,tkFileDialog;root=Tkinter.Tk();root.withdraw(); " ) ;
if ( tfd_isDarwin ( ) )
{
strcat ( lDialogString ,
" import os;os.system('''/usr/bin/osascript -e 'tell app \\ \" Finder \\ \" to set \
frontmost of process \ \ \ " Python \\ \" to true' '''); " ) ;
}
strcat ( lDialogString , " lFiles=tkFileDialog.askopenfilename( " ) ;
if ( aAllowMultipleSelects )
{
strcat ( lDialogString , " multiple=1, " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
getPathWithoutFinalSlash ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialdir=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
getLastName ( lString , aDefaultPathAndFile ) ;
if ( strlen ( lString ) )
{
strcat ( lDialogString , " initialfile=' " ) ;
strcat ( lDialogString , lString ) ;
strcat ( lDialogString , " ', " ) ;
}
}
if ( ( aNumOfFilterPatterns > 1 )
| | ( ( aNumOfFilterPatterns = = 1 ) /*test because poor osx behaviour*/
& & ( aFilterPatterns [ 0 ] [ strlen ( aFilterPatterns [ 0 ] ) - 1 ] ! = ' * ' ) ) )
{
strcat ( lDialogString , " filetypes=( " ) ;
strcat ( lDialogString , " (' " ) ;
if ( aSingleFilterDescription & & strlen ( aSingleFilterDescription ) )
{
strcat ( lDialogString , aSingleFilterDescription ) ;
}
strcat ( lDialogString , " ',( " ) ;
for ( i = 0 ; i < aNumOfFilterPatterns ; i + + )
{
strcat ( lDialogString , " ' " ) ;
strcat ( lDialogString , aFilterPatterns [ i ] ) ;
strcat ( lDialogString , " ', " ) ;
}
strcat ( lDialogString , " )), " ) ;
strcat ( lDialogString , " ('All files','*')) " ) ;
}
strcat ( lDialogString , " ); \
\ nif not isinstance ( lFiles , tuple ) : \ n \ tprint lFiles \ nelse : \
\ n \ tlFilesString = ' ' \ n \ tfor lFile in lFiles : \ n \ t \ tlFilesString + = str ( lFile ) + ' | ' \
\ n \ tprint lFilesString [ : - 1 ] \ n \ " " ) ;
}
else if ( xdialogPresent ( ) | | dialogName ( ) )
{
if ( xdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " xdialog " ) ; return ( char * ) 1 ; }
lWasGraphicDialog = 1 ;
strcpy ( lDialogString , " (Xdialog " ) ;
}
else if ( isTerminalRunning ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
strcpy ( lDialogString , " (dialog " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
lWasXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " '( " ) ;
strcat ( lDialogString , dialogName ( ) ) ;
strcat ( lDialogString , " " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( ! xdialogPresent ( ) & & ! gdialogPresent ( ) )
{
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString ,
" tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY " ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --fselect \" " ) ;
if ( aDefaultPathAndFile & & strlen ( aDefaultPathAndFile ) )
{
if ( ! strchr ( aDefaultPathAndFile , ' / ' ) )
{
strcat ( lDialogString , " ./ " ) ;
}
strcat ( lDialogString , aDefaultPathAndFile ) ;
}
else if ( ! isTerminalRunning ( ) & & ! lWasGraphicDialog )
{
strcat ( lDialogString , getenv ( " HOME " ) ) ;
strcat ( lDialogString , " / " ) ;
}
else
{
strcat ( lDialogString , " ./ " ) ;
}
if ( lWasGraphicDialog )
{
strcat ( lDialogString , " \" 0 60 ) 2>&1 " ) ;
}
else
{
strcat ( lDialogString , " \" 0 60 >/dev/tty) " ) ;
if ( lWasXterm )
{
strcat ( lDialogString ,
" 2>/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt " ) ;
}
else
{
strcat ( lDialogString , " 2>&1 ; clear >/dev/tty " ) ;
}
}
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { return tinyfd_inputBox ( aTitle , NULL , NULL ) ; }
strcpy ( lBuff , " Open file from " ) ;
strcat ( lBuff , getCurDir ( ) ) ;
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lDialogString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , lBuff , " " ) ;
if ( p ) strcpy ( lBuff , p ) ; else lBuff [ 0 ] = ' \0 ' ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lDialogString ) ; /* restore its previous content to tinyfd_inputBox */
if ( ! fileExists ( lBuff ) )
{
free ( lBuff ) ;
lBuff = NULL ;
}
else
{
lBuff = ( char * ) ( realloc ( lBuff , ( strlen ( lBuff ) + 1 ) * sizeof ( char ) ) ) ;
}
return lBuff ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
if ( ! ( lIn = popen ( lDialogString , " r " ) ) )
{
free ( lBuff ) ;
lBuff = NULL ;
return NULL ;
}
lBuff [ 0 ] = ' \0 ' ;
p = lBuff ;
while ( fgets ( p , sizeof ( lBuff ) , lIn ) ! = NULL )
{
p + = strlen ( p ) ;
}
pclose ( lIn ) ;
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
/* printf( "lBuff: %s\n" , lBuff ) ; */
if ( lWasKdialog & & aAllowMultipleSelects )
{
p = lBuff ;
while ( ( p = strchr ( p , ' \n ' ) ) )
* p = ' | ' ;
}
/* printf( "lBuff2: %s\n" , lBuff ) ; */
if ( ! strlen ( lBuff ) )
{
free ( lBuff ) ;
lBuff = NULL ;
return NULL ;
}
if ( aAllowMultipleSelects & & strchr ( lBuff , ' | ' ) )
{
if ( ! ensureFilesExist ( lBuff , lBuff ) )
{
free ( lBuff ) ;
lBuff = NULL ;
return NULL ;
}
}
else if ( ! fileExists ( lBuff ) )
{
free ( lBuff ) ;
lBuff = NULL ;
return NULL ;
}
lBuff = ( char * ) ( realloc ( lBuff , ( strlen ( lBuff ) + 1 ) * sizeof ( char ) ) ) ;
/*printf( "lBuff3: %s\n" , lBuff ) ; */
return lBuff ;
}
char * tinyfd_selectFolderDialog (
char const * aTitle , /* "" */
char const * aDefaultPath ) /* "" */
{
static char lBuff [ MAX_PATH_OR_CMD ] ;
char lDialogString [ MAX_PATH_OR_CMD ] ;
FILE * lIn ;
char * p ;
char * lPointerInputBox ;
int lWasGraphicDialog = 0 ;
int lWasXterm = 0 ;
lBuff [ 0 ] = ' \0 ' ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_selectFolderDialog ( " INVALID TITLE WITH QUOTES " , aDefaultPath ) ;
if ( tfd_quoteDetected ( aDefaultPath ) ) return tinyfd_selectFolderDialog ( aTitle , " INVALID DEFAULT_PATH WITH QUOTES " ) ;
if ( osascriptPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " applescript " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " osascript " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'tell application \" System Events \" ' -e 'Activate' " ) ;
strcat ( lDialogString , " -e 'try' -e 'POSIX path of ( choose folder " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " with prompt \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
strcat ( lDialogString , " default location \" " ) ;
strcat ( lDialogString , aDefaultPath ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " )' " ) ;
strcat ( lDialogString , " -e 'on error number -128' " ) ;
strcat ( lDialogString , " -e 'end try' " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'end tell' " ) ;
}
else if ( tfd_kdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " kdialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " kdialog " ) ;
if ( ( tfd_kdialogPresent ( ) = = 2 ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
strcat ( lDialogString , " --getexistingdirectory " ) ;
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
if ( aDefaultPath [ 0 ] ! = ' / ' )
{
strcat ( lDialogString , " $PWD/ " ) ;
}
strcat ( lDialogString , " \" " ) ;
strcat ( lDialogString , aDefaultPath ) ;
strcat ( lDialogString , " \" " ) ;
}
else
{
strcat ( lDialogString , " $PWD/ " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
}
else if ( tfd_zenityPresent ( ) | | tfd_matedialogPresent ( ) | | tfd_shellementaryPresent ( ) | | tfd_qarmaPresent ( ) )
{
if ( tfd_zenityPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " zenity " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " zenity " ) ;
if ( ( tfd_zenity3Present ( ) > = 4 ) & & ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(sleep .01;xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
else if ( tfd_matedialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " matedialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " matedialog " ) ;
}
else if ( tfd_shellementaryPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " shellementary " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " shellementary " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " qarma " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " qarma " ) ;
if ( ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
strcat ( lDialogString , " --file-selection --directory " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
strcat ( lDialogString , " --filename= \" " ) ;
strcat ( lDialogString , aDefaultPath ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( tfd_yadPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " yad " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " yad --file-selection --directory " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
strcat ( lDialogString , " --filename= \" " ) ;
strcat ( lDialogString , aDefaultPath ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( ! xdialogPresent ( ) & & tkinter3Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python3-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , gPython3Name ) ;
strcat ( lDialogString ,
" -S -c \" import tkinter;from tkinter import filedialog;root=tkinter.Tk();root.withdraw(); " ) ;
strcat ( lDialogString , " res=filedialog.askdirectory( " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
strcat ( lDialogString , " initialdir=' " ) ;
strcat ( lDialogString , aDefaultPath ) ;
strcat ( lDialogString , " ' " ) ;
}
strcat ( lDialogString , " ); \n if not isinstance(res, tuple): \n \t print(res) \n \" " ) ;
}
else if ( ! xdialogPresent ( ) & & tkinter2Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python2-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " export PYTHONIOENCODING=utf-8; " ) ;
strcat ( lDialogString , gPython2Name ) ;
if ( ! isTerminalRunning ( ) & & tfd_isDarwin ( ) )
{
strcat ( lDialogString , " -i " ) ; /* for osx without console */
}
strcat ( lDialogString ,
" -S -c \" import Tkinter,tkFileDialog;root=Tkinter.Tk();root.withdraw(); " ) ;
if ( tfd_isDarwin ( ) )
{
strcat ( lDialogString ,
" import os;os.system('''/usr/bin/osascript -e 'tell app \\ \" Finder \\ \" to set \
frontmost of process \ \ \ " Python \\ \" to true' '''); " ) ;
}
strcat ( lDialogString , " print tkFileDialog.askdirectory( " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ', " ) ;
}
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
strcat ( lDialogString , " initialdir=' " ) ;
strcat ( lDialogString , aDefaultPath ) ;
strcat ( lDialogString , " ' " ) ;
}
strcat ( lDialogString , " ) \" " ) ;
}
else if ( xdialogPresent ( ) | | dialogName ( ) )
{
if ( xdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " xdialog " ) ; return ( char * ) 1 ; }
lWasGraphicDialog = 1 ;
strcpy ( lDialogString , " (Xdialog " ) ;
}
else if ( isTerminalRunning ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
strcpy ( lDialogString , " (dialog " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " dialog " ) ; return ( char * ) 0 ; }
lWasXterm = 1 ;
strcpy ( lDialogString , terminalName ( ) ) ;
strcat ( lDialogString , " '( " ) ;
strcat ( lDialogString , dialogName ( ) ) ;
strcat ( lDialogString , " " ) ;
}
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( ! xdialogPresent ( ) & & ! gdialogPresent ( ) )
{
strcat ( lDialogString , " --backtitle \" " ) ;
strcat ( lDialogString ,
" tab: focus | /: populate | spacebar: fill text field | ok: TEXT FIELD ONLY " ) ;
strcat ( lDialogString , " \" " ) ;
}
strcat ( lDialogString , " --dselect \" " ) ;
if ( aDefaultPath & & strlen ( aDefaultPath ) )
{
strcat ( lDialogString , aDefaultPath ) ;
ensureFinalSlash ( lDialogString ) ;
}
else if ( ! isTerminalRunning ( ) & & ! lWasGraphicDialog )
{
strcat ( lDialogString , getenv ( " HOME " ) ) ;
strcat ( lDialogString , " / " ) ;
}
else
{
strcat ( lDialogString , " ./ " ) ;
}
if ( lWasGraphicDialog )
{
strcat ( lDialogString , " \" 0 60 ) 2>&1 " ) ;
}
else
{
strcat ( lDialogString , " \" 0 60 >/dev/tty) " ) ;
if ( lWasXterm )
{
strcat ( lDialogString ,
" 2>/tmp/tinyfd.txt';cat /tmp/tinyfd.txt;rm /tmp/tinyfd.txt " ) ;
}
else
{
strcat ( lDialogString , " 2>&1 ; clear >/dev/tty " ) ;
}
}
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { return tinyfd_inputBox ( aTitle , NULL , NULL ) ; }
strcpy ( lBuff , " Select folder from " ) ;
strcat ( lBuff , getCurDir ( ) ) ;
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lDialogString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , lBuff , " " ) ;
if ( p ) strcpy ( lBuff , p ) ; else lBuff [ 0 ] = ' \0 ' ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lDialogString ) ; /* restore its previous content to tinyfd_inputBox */
p = lBuff ;
if ( ! p | | ! strlen ( p ) | | ! dirExists ( p ) )
{
return NULL ;
}
return p ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
if ( ! ( lIn = popen ( lDialogString , " r " ) ) )
{
return NULL ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{ }
pclose ( lIn ) ;
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
/* printf( "lBuff: %s\n" , lBuff ) ; */
if ( ! strlen ( lBuff ) | | ! dirExists ( lBuff ) )
{
return NULL ;
}
return lBuff ;
}
/* returns the hexcolor as a string "#FF0000" */
/* aoResultRGB also contains the result */
/* aDefaultRGB is used only if aDefaultHexRGB is NULL */
/* aDefaultRGB and aoResultRGB can be the same array */
char * tinyfd_colorChooser (
char const * aTitle , /* NULL or "" */
char const * aDefaultHexRGB , /* NULL or "#FF0000"*/
unsigned char const aDefaultRGB [ 3 ] , /* { 0 , 255 , 255 } */
unsigned char aoResultRGB [ 3 ] ) /* { 0 , 0 , 0 } */
{
static char lDefaultHexRGB [ 16 ] ;
char lBuff [ 128 ] ;
char lTmp [ 128 ] ;
# if !((defined(__cplusplus ) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__clang__))
char * lTmp2 ;
# endif
char lDialogString [ MAX_PATH_OR_CMD ] ;
unsigned char lDefaultRGB [ 3 ] ;
char * p ;
char * lPointerInputBox ;
FILE * lIn ;
int i ;
int lWasZenity3 = 0 ;
int lWasOsascript = 0 ;
int lWasXdialog = 0 ;
lBuff [ 0 ] = ' \0 ' ;
if ( tfd_quoteDetected ( aTitle ) ) return tinyfd_colorChooser ( " INVALID TITLE WITH QUOTES " , aDefaultHexRGB , aDefaultRGB , aoResultRGB ) ;
if ( tfd_quoteDetected ( aDefaultHexRGB ) ) return tinyfd_colorChooser ( aTitle , " INVALID DEFAULT_HEX_RGB WITH QUOTES " , aDefaultRGB , aoResultRGB ) ;
if ( aDefaultHexRGB )
{
Hex2RGB ( aDefaultHexRGB , lDefaultRGB ) ;
strcpy ( lDefaultHexRGB , aDefaultHexRGB ) ;
}
else
{
lDefaultRGB [ 0 ] = aDefaultRGB [ 0 ] ;
lDefaultRGB [ 1 ] = aDefaultRGB [ 1 ] ;
lDefaultRGB [ 2 ] = aDefaultRGB [ 2 ] ;
RGB2Hex ( aDefaultRGB , lDefaultHexRGB ) ;
}
if ( osascriptPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " applescript " ) ; return ( char * ) 1 ; }
lWasOsascript = 1 ;
strcpy ( lDialogString , " osascript " ) ;
if ( ! osx9orBetter ( ) )
{
strcat ( lDialogString , " -e 'tell application \" System Events \" ' -e 'Activate' " ) ;
strcat ( lDialogString , " -e 'try' -e 'set mycolor to choose color default color { " ) ;
}
else
{
strcat ( lDialogString ,
" -e 'try' -e 'tell app (path to frontmost application as Unicode text) \
to set mycolor to choose color default color { " );
}
sprintf ( lTmp , " %d " , 256 * lDefaultRGB [ 0 ] ) ;
strcat ( lDialogString , lTmp ) ;
strcat ( lDialogString , " , " ) ;
sprintf ( lTmp , " %d " , 256 * lDefaultRGB [ 1 ] ) ;
strcat ( lDialogString , lTmp ) ;
strcat ( lDialogString , " , " ) ;
sprintf ( lTmp , " %d " , 256 * lDefaultRGB [ 2 ] ) ;
strcat ( lDialogString , lTmp ) ;
strcat ( lDialogString , " }' " ) ;
strcat ( lDialogString ,
" -e 'set mystring to ((item 1 of mycolor) div 256 as integer) as string' " ) ;
strcat ( lDialogString ,
" -e 'repeat with i from 2 to the count of mycolor' " ) ;
strcat ( lDialogString ,
" -e 'set mystring to mystring & \" \" & ((item i of mycolor) div 256 as integer) as string' " ) ;
strcat ( lDialogString , " -e 'end repeat' " ) ;
strcat ( lDialogString , " -e 'mystring' " ) ;
strcat ( lDialogString , " -e 'on error number -128' " ) ;
strcat ( lDialogString , " -e 'end try' " ) ;
if ( ! osx9orBetter ( ) ) strcat ( lDialogString , " -e 'end tell' " ) ;
}
else if ( tfd_kdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " kdialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " kdialog " ) ;
if ( ( tfd_kdialogPresent ( ) = = 2 ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
sprintf ( lDialogString + strlen ( lDialogString ) , " --getcolor --default '%s' " , lDefaultHexRGB ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
}
else if ( tfd_zenity3Present ( ) | | tfd_matedialogPresent ( ) | | tfd_shellementaryPresent ( ) | | tfd_qarmaPresent ( ) )
{
lWasZenity3 = 1 ;
if ( tfd_zenity3Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " zenity3 " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " zenity " ) ;
if ( ( tfd_zenity3Present ( ) > = 4 ) & & ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(sleep .01;xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
else if ( tfd_matedialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " matedialog " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " matedialog " ) ;
}
else if ( tfd_shellementaryPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " shellementary " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " shellementary " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " qarma " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " qarma " ) ;
if ( ! getenv ( " SSH_TTY " ) & & tfd_xpropPresent ( ) )
{
strcat ( lDialogString , " --attach=$(xprop -root 32x ' \t $0' _NET_ACTIVE_WINDOW | cut -f 2) " ) ; /* contribution: Paul Rouget */
}
}
strcat ( lDialogString , " --color-selection --show-palette " ) ;
sprintf ( lDialogString + strlen ( lDialogString ) , " --color=%s " , lDefaultHexRGB ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( tfd_yadPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " yad " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " yad --color " ) ;
sprintf ( lDialogString + strlen ( lDialogString ) , " --init-color=%s " , lDefaultHexRGB ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " --title= \" " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " \" " ) ;
}
if ( tinyfd_silent ) strcat ( lDialogString , " 2>/dev/null " ) ;
}
else if ( xdialogPresent ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " xdialog " ) ; return ( char * ) 1 ; }
lWasXdialog = 1 ;
strcpy ( lDialogString , " Xdialog --colorsel \" " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , aTitle ) ;
}
strcat ( lDialogString , " \" 0 60 " ) ;
# if (defined(__cplusplus ) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__clang__)
sprintf ( lTmp , " %hhu %hhu %hhu " , lDefaultRGB [ 0 ] , lDefaultRGB [ 1 ] , lDefaultRGB [ 2 ] ) ;
# else
sprintf ( lTmp , " %hu %hu %hu " , lDefaultRGB [ 0 ] , lDefaultRGB [ 1 ] , lDefaultRGB [ 2 ] ) ;
# endif
strcat ( lDialogString , lTmp ) ;
strcat ( lDialogString , " 2>&1 " ) ;
}
else if ( tkinter3Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python3-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , gPython3Name ) ;
strcat ( lDialogString ,
" -S -c \" import tkinter;from tkinter import colorchooser;root=tkinter.Tk();root.withdraw(); " ) ;
strcat ( lDialogString , " res=colorchooser.askcolor(color=' " ) ;
strcat ( lDialogString , lDefaultHexRGB ) ;
strcat ( lDialogString , " ' " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " ,title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ' " ) ;
}
strcat ( lDialogString , " ); \
\ nif res [ 1 ] is not None : \ n \ tprint ( res [ 1 ] ) \ " " ) ;
}
else if ( tkinter2Present ( ) )
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { strcpy ( tinyfd_response , " python2-tkinter " ) ; return ( char * ) 1 ; }
strcpy ( lDialogString , " export PYTHONIOENCODING=utf-8; " ) ;
strcat ( lDialogString , gPython2Name ) ;
if ( ! isTerminalRunning ( ) & & tfd_isDarwin ( ) )
{
strcat ( lDialogString , " -i " ) ; /* for osx without console */
}
strcat ( lDialogString ,
" -S -c \" import Tkinter,tkColorChooser;root=Tkinter.Tk();root.withdraw(); " ) ;
if ( tfd_isDarwin ( ) )
{
strcat ( lDialogString ,
" import os;os.system('''osascript -e 'tell app \\ \" Finder \\ \" to set \
frontmost of process \ \ \ " Python \\ \" to true' '''); " ) ;
}
strcat ( lDialogString , " res=tkColorChooser.askcolor(color=' " ) ;
strcat ( lDialogString , lDefaultHexRGB ) ;
strcat ( lDialogString , " ' " ) ;
if ( aTitle & & strlen ( aTitle ) )
{
strcat ( lDialogString , " ,title=' " ) ;
strcat ( lDialogString , aTitle ) ;
strcat ( lDialogString , " ' " ) ;
}
strcat ( lDialogString , " ); \
\ nif res [ 1 ] is not None : \ n \ tprint res [ 1 ] \ " " ) ;
}
else
{
if ( aTitle & & ! strcmp ( aTitle , " tinyfd_query " ) ) { return tinyfd_inputBox ( aTitle , NULL , NULL ) ; }
lPointerInputBox = tinyfd_inputBox ( NULL , NULL , NULL ) ; /* obtain a pointer on the current content of tinyfd_inputBox */
if ( lPointerInputBox ) strcpy ( lDialogString , lPointerInputBox ) ; /* preserve the current content of tinyfd_inputBox */
p = tinyfd_inputBox ( aTitle , " Enter hex rgb color (i.e. #f5ca20) " , lDefaultHexRGB ) ;
if ( ! p | | ( strlen ( p ) ! = 7 ) | | ( p [ 0 ] ! = ' # ' ) )
{
return NULL ;
}
for ( i = 1 ; i < 7 ; i + + )
{
if ( ! isxdigit ( ( int ) p [ i ] ) )
{
return NULL ;
}
}
Hex2RGB ( p , aoResultRGB ) ;
strcpy ( lDefaultHexRGB , p ) ;
if ( lPointerInputBox ) strcpy ( lPointerInputBox , lDialogString ) ; /* restore its previous content to tinyfd_inputBox */
return lDefaultHexRGB ;
}
if ( tinyfd_verbose ) printf ( " lDialogString: %s \n " , lDialogString ) ;
if ( ! ( lIn = popen ( lDialogString , " r " ) ) )
{
return NULL ;
}
while ( fgets ( lBuff , sizeof ( lBuff ) , lIn ) ! = NULL )
{
}
pclose ( lIn ) ;
if ( ! strlen ( lBuff ) )
{
return NULL ;
}
/* printf( "len Buff: %lu\n" , strlen(lBuff) ) ; */
/* printf( "lBuff0: %s\n" , lBuff ) ; */
if ( lBuff [ strlen ( lBuff ) - 1 ] = = ' \n ' )
{
lBuff [ strlen ( lBuff ) - 1 ] = ' \0 ' ;
}
if ( lWasZenity3 )
{
if ( lBuff [ 0 ] = = ' # ' )
{
if ( strlen ( lBuff ) > 7 )
{
lBuff [ 3 ] = lBuff [ 5 ] ;
lBuff [ 4 ] = lBuff [ 6 ] ;
lBuff [ 5 ] = lBuff [ 9 ] ;
lBuff [ 6 ] = lBuff [ 10 ] ;
lBuff [ 7 ] = ' \0 ' ;
}
Hex2RGB ( lBuff , aoResultRGB ) ;
}
else if ( lBuff [ 3 ] = = ' ( ' ) {
# if (defined(__cplusplus ) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__clang__)
sscanf ( lBuff , " rgb(%hhu,%hhu,%hhu " , & aoResultRGB [ 0 ] , & aoResultRGB [ 1 ] , & aoResultRGB [ 2 ] ) ;
# else
aoResultRGB [ 0 ] = strtol ( lBuff + 4 , & lTmp2 , 10 ) ;
aoResultRGB [ 1 ] = strtol ( lTmp2 + 1 , & lTmp2 , 10 ) ;
aoResultRGB [ 2 ] = strtol ( lTmp2 + 1 , NULL , 10 ) ;
# endif
RGB2Hex ( aoResultRGB , lBuff ) ;
}
else if ( lBuff [ 4 ] = = ' ( ' ) {
# if (defined(__cplusplus ) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__clang__)
sscanf ( lBuff , " rgba(%hhu,%hhu,%hhu " , & aoResultRGB [ 0 ] , & aoResultRGB [ 1 ] , & aoResultRGB [ 2 ] ) ;
# else
aoResultRGB [ 0 ] = strtol ( lBuff + 5 , & lTmp2 , 10 ) ;
aoResultRGB [ 1 ] = strtol ( lTmp2 + 1 , & lTmp2 , 10 ) ;
aoResultRGB [ 2 ] = strtol ( lTmp2 + 1 , NULL , 10 ) ;
# endif
RGB2Hex ( aoResultRGB , lBuff ) ;
}
}
else if ( lWasOsascript | | lWasXdialog )
{
/* printf( "lBuff: %s\n" , lBuff ) ; */
# if (defined(__cplusplus ) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__clang__)
sscanf ( lBuff , " %hhu %hhu %hhu " , & aoResultRGB [ 0 ] , & aoResultRGB [ 1 ] , & aoResultRGB [ 2 ] ) ;
# else
aoResultRGB [ 0 ] = strtol ( lBuff , & lTmp2 , 10 ) ;
aoResultRGB [ 1 ] = strtol ( lTmp2 + 1 , & lTmp2 , 10 ) ;
aoResultRGB [ 2 ] = strtol ( lTmp2 + 1 , NULL , 10 ) ;
# endif
RGB2Hex ( aoResultRGB , lBuff ) ;
}
else
{
Hex2RGB ( lBuff , aoResultRGB ) ;
}
/* printf("%d %d %d\n", aoResultRGB[0],aoResultRGB[1],aoResultRGB[2]); */
/* printf( "lBuff: %s\n" , lBuff ) ; */
strcpy ( lDefaultHexRGB , lBuff ) ;
return lDefaultHexRGB ;
}
# endif /* _WIN32 */
/*
int main ( int argc , char * argv [ ] )
{
char const * lTmp ;
char const * lTheSaveFileName ;
char const * lTheOpenFileName ;
char const * lTheSelectFolderName ;
char const * lTheHexColor ;
char const * lWillBeGraphicMode ;
unsigned char lRgbColor [ 3 ] ;
FILE * lIn ;
char lBuffer [ 1024 ] ;
char lString [ 1024 ] ;
char const * lFilterPatterns [ 2 ] = { " *.txt " , " *.text " } ;
tinyfd_verbose = argc - 1 ;
tinyfd_silent = 1 ;
lWillBeGraphicMode = tinyfd_inputBox ( " tinyfd_query " , NULL , NULL ) ;
strcpy ( lBuffer , " v " ) ;
strcat ( lBuffer , tinyfd_version ) ;
if ( lWillBeGraphicMode )
{
strcat ( lBuffer , " \n graphic mode: " ) ;
}
else
{
strcat ( lBuffer , " \n console mode: " ) ;
}
strcat ( lBuffer , tinyfd_response ) ;
strcat ( lBuffer , " \n " ) ;
strcat ( lBuffer , tinyfd_needs + 78 ) ;
strcpy ( lString , " tinyfiledialogs " ) ;
tinyfd_messageBox ( lString , lBuffer , " ok " , " info " , 0 ) ;
tinyfd_notifyPopup ( " the title " , " the message \n \t from outer-space " , " info " ) ;
if ( lWillBeGraphicMode & & ! tinyfd_forceConsole )
{
tinyfd_forceConsole = ! tinyfd_messageBox ( " Hello World " ,
" graphic dialogs [yes] / console mode [no]? " ,
" yesno " , " question " , 1 ) ;
}
lTmp = tinyfd_inputBox (
" a password box " , " your password will be revealed " , NULL ) ;
if ( ! lTmp ) return 1 ;
strcpy ( lString , lTmp ) ;
lTheSaveFileName = tinyfd_saveFileDialog (
" let us save this password " ,
" passwordFile.txt " ,
2 ,
lFilterPatterns ,
NULL ) ;
if ( ! lTheSaveFileName )
{
tinyfd_messageBox (
" Error " ,
" Save file name is NULL " ,
" ok " ,
" error " ,
1 ) ;
return 1 ;
}
lIn = fopen ( lTheSaveFileName , " w " ) ;
if ( ! lIn )
{
tinyfd_messageBox (
" Error " ,
" Can not open this file in write mode " ,
" ok " ,
" error " ,
1 ) ;
return 1 ;
}
fputs ( lString , lIn ) ;
fclose ( lIn ) ;
lTheOpenFileName = tinyfd_openFileDialog (
" let us read the password back " ,
" " ,
2 ,
lFilterPatterns ,
NULL ,
0 ) ;
if ( ! lTheOpenFileName )
{
tinyfd_messageBox (
" Error " ,
" Open file name is NULL " ,
" ok " ,
" error " ,
1 ) ;
return 1 ;
}
lIn = fopen ( lTheOpenFileName , " r " ) ;
if ( ! lIn )
{
tinyfd_messageBox (
" Error " ,
" Can not open this file in read mode " ,
" ok " ,
" error " ,
1 ) ;
return ( 1 ) ;
}
lBuffer [ 0 ] = ' \0 ' ;
fgets ( lBuffer , sizeof ( lBuffer ) , lIn ) ;
fclose ( lIn ) ;
tinyfd_messageBox ( " your password is " ,
lBuffer , " ok " , " info " , 1 ) ;
lTheSelectFolderName = tinyfd_selectFolderDialog (
" let us just select a directory " , NULL ) ;
if ( ! lTheSelectFolderName )
{
tinyfd_messageBox (
" Error " ,
" Select folder name is NULL " ,
" ok " ,
" error " ,
1 ) ;
return 1 ;
}
tinyfd_messageBox ( " The selected folder is " ,
lTheSelectFolderName , " ok " , " info " , 1 ) ;
lTheHexColor = tinyfd_colorChooser (
" choose a nice color " ,
" #FF0077 " ,
lRgbColor ,
lRgbColor ) ;
if ( ! lTheHexColor )
{
tinyfd_messageBox (
" Error " ,
" hexcolor is NULL " ,
" ok " ,
" error " ,
1 ) ;
return 1 ;
}
tinyfd_messageBox ( " The selected hexcolor is " ,
lTheHexColor , " ok " , " info " , 1 ) ;
tinyfd_beep ( ) ;
return 0 ;
}
*/
# ifdef _MSC_VER
# pragma warning(default:4996)
# pragma warning(default:4100)
# pragma warning(default:4706)
# endif
# endif // TFD_IMPLEMENTATION