From 2e83baea8e8867c94ee6d96447d8e278fbccaf47 Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Sat, 13 Jun 2026 09:29:01 +0200 Subject: [PATCH] Added tinyfilediaglogs external dependancy --- external/tinyfiledialogs/build.bat | 6 + external/tinyfiledialogs/build.sh | 21 + .../tinyfiledialogs/linux/tinyfiledialogs.a | Bin 0 -> 185232 bytes .../tinyfiledialogs/linux/tinyfiledialogs.so | Bin 0 -> 147784 bytes .../macos-arm64/tinyfiledialogs.a | Bin 0 -> 169800 bytes .../macos-arm64/tinyfiledialogs.dylib | Bin 0 -> 141352 bytes external/tinyfiledialogs/macos/.gitkeep | 0 external/tinyfiledialogs/tinyfiledialogs.c | 8171 +++++++++++++++++ external/tinyfiledialogs/tinyfiledialogs.h | 314 + external/tinyfiledialogs/tinyfiledialogs.odin | 62 + .../tinyfiledialogs_windows.odin | 28 + .../windows/tinyfiledialogs.lib | Bin 0 -> 93536 bytes 12 files changed, 8602 insertions(+) create mode 100644 external/tinyfiledialogs/build.bat create mode 100755 external/tinyfiledialogs/build.sh create mode 100644 external/tinyfiledialogs/linux/tinyfiledialogs.a create mode 100755 external/tinyfiledialogs/linux/tinyfiledialogs.so create mode 100644 external/tinyfiledialogs/macos-arm64/tinyfiledialogs.a create mode 100755 external/tinyfiledialogs/macos-arm64/tinyfiledialogs.dylib create mode 100644 external/tinyfiledialogs/macos/.gitkeep create mode 100644 external/tinyfiledialogs/tinyfiledialogs.c create mode 100644 external/tinyfiledialogs/tinyfiledialogs.h create mode 100644 external/tinyfiledialogs/tinyfiledialogs.odin create mode 100644 external/tinyfiledialogs/tinyfiledialogs_windows.odin create mode 100644 external/tinyfiledialogs/windows/tinyfiledialogs.lib diff --git a/external/tinyfiledialogs/build.bat b/external/tinyfiledialogs/build.bat new file mode 100644 index 0000000..c126215 --- /dev/null +++ b/external/tinyfiledialogs/build.bat @@ -0,0 +1,6 @@ +@echo off + +cl /c tinyfiledialogs.c /Fo:tinyfiledialogs.obj +lib /OUT:tinyfiledialogs.lib tinyfiledialogs.obj +move tinyfiledialogs.lib \windows\ +del tinyfiledialogs.obj diff --git a/external/tinyfiledialogs/build.sh b/external/tinyfiledialogs/build.sh new file mode 100755 index 0000000..3e1a1a0 --- /dev/null +++ b/external/tinyfiledialogs/build.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +case $(uname) in +"Darwin") + case $(uname -m) in + "arm64") lib_path="macos-arm64" ;; + *) lib_path="macos" ;; + esac + + # Static + clang -c -o tinyfiledialogs.o tinyfiledialogs.c -fPIC + ar r tinyfiledialogs.a tinyfiledialogs.o + mv tinyfiledialogs.a $lib_path/tinyfiledialogs.a + rm tinyfiledialogs.o + ;; +*) + gcc -c tinyfiledialogs.c -o linux/tinyfiledialogs.o + ar rcs linux/tinyfiledialogs.a linux/tinyfiledialogs.o + rm linux/tinyfiledialogs.o + ;; +esac diff --git a/external/tinyfiledialogs/linux/tinyfiledialogs.a b/external/tinyfiledialogs/linux/tinyfiledialogs.a new file mode 100644 index 0000000000000000000000000000000000000000..047a6acf80d524a8565086b370bbd444d1fda455 GIT binary patch literal 185232 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 literal 0 HcmV?d00001 diff --git a/external/tinyfiledialogs/macos-arm64/tinyfiledialogs.dylib b/external/tinyfiledialogs/macos-arm64/tinyfiledialogs.dylib new file mode 100755 index 0000000000000000000000000000000000000000..7a02b458994ed6ea0724f78122143f608f506d19 GIT binary patch literal 141352 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ā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 nyY=_LC;f0Qhh6OCHq3^yWT`w@cug+ zuaSqzt6q5JtIp%Xbw7k|T<1f1dV#EW=i@AJ;3nt8w+q;}wNcb}Jq;Myg5cZ-ZM8u> ztZyF!jN+Jnx$+_QZTzv|`;ufRl^E9guDOo4mUzsCETtwNuC}h(_jvYkm+*Yz&Gdej z&dYaNuuAn6@tQ5Xw7zSm43oo`Pb`sLH~NuF*Q-{jR1=Y z4ErnCOCRBqoW9?uiQlI>-f4g*r$YZ}qCfVY#{p(NNATr28F1gv%B$smN<1p{UB>~R z>$^;x;~Z8~w^aamYMjWLt-sWF9T}8E>bvqRIk>*d$`cXww>38B17GumZ)>zuT^7}3 zZNzta>ACi~$X8_;v-HhPdcF%g$D^^+xb`7gj9S1WAonEH0icb(@wxj;jE!O$8&gpG zfp(&)wO%gK-5Byx8)^M(_IXme1_g{_iPju%qaWFo_LGQz2=r0wRYkR4^>dPXMS7VaPsExiiO8nx$ zPfaZJ=oxk%v)1$7hb9&w9W~C$i=9 zc3;UI)W)_PZse*XI>W8?iqwZyS~@WPP=o&)!XGO5Qg1{urzWMxoaRb9Z;^>+1dt=9^aauEgtdGpsmFp%ZM<`UM>OzFLKC~thkWr4 z`f=<+?ud-lN?m6{#sj1`eG?M2sV1@k*Gcf8I=&xKU%;r2PwV#x=aGM;?^A1JED{dk z5+3Pu0DtSaU^w|0aJD1(Qf?$!U!&Rs@T{_Eri3QJw~F3D*^0Bs#_>clbZ|b=Ie_e2 z13MC5Q(JiErsm>M%d?Iu`n(*&zDguSI^b+P_$Kkb<2CGayylIeI@Iyjl_91ILSrY; zUfD^{rELJe@x6M(KEw=YP|X6 zhH0mO%kg22d+HCp8fo964EBJ3gZBhgv~R&U@-4g&@c5npvYpEN?ww4#)E9Z(oHaA` z+#$r6>Xw)S1ZN$}uwKA8dk=71)|jpfA?sO2#=u^DCzrlY$TalapWWF1 z108=)4t?X+HS2@5>28rB1^cRPe13op%f;^n;it7gJ8}L$(cg*n;0qW7==+p)t^76% zKhim|onsm2h01w6+fW})eYSzdcJ^x(oyYS~5QZ9)Ujp`TJu^69W7wf8Dm5mnh2Qnq zTfY4d>6j>!@6FkE*15oriGAqbYD`Ft$xXo1n4oV9_`a6*rD(r`_y=lBzOySWlN~3l zgFL6aRCMs;WPq{PMS$CWtJK;O*nS(@AUDTJz2+*wBcW`yCGf=-ekY+ZI#Aw8c+&CC z1P%Je6TQ<5d1~oAo=KK0iOn1XReT=LM!7F|40Yzz?=ke-Y~tWMxNg{poG7r9aBXT! zz;{D{?>fgjp8Bst{|#xrQNR#G`L@6OI7Mu)K)dSe`;lVo0g+K_A=WzH5k!A2=sy7Y z(6@_q&34Cg)(*n&ee6q)P#+=AVzOSib*K1^<`BtU>n&JH=CK=}Py1Kjb?>M2kca$Q z2*{!1&zB!C=*+pP$mo|lH%YC--@B&cu(utD(!K}n6N!JI7J_pwY9T&BJKGU@)relV zt6q?|MT|->B(f9Rg-3=6+ra+mG5Z2EO>OFyY~c*xT44c;@BoGR`2qn&CYzKIN2 zm*gDl92aty%t}j!{}mbR_8Za8dogYJ^u<>AvEQZE;c|=LuWX&A{bIDM|46o=|N2?} zXyHG}G3THk`Op4wj$X~l|*w`@g{T_lME<2@2@kw5o%mS_C$fsf8B1?gC; zjW!v7yp49-?siT*)$nM!R;ZAisL$>mYTv(9iY2P~IgccBe3we;&k@vA-`T7dWeiS`2UTWI_`&AMhgPffS=S_e|Zl1X0U(#8JtgF13Xvkj5RiC89Orru`|u_c7aZE z8hkm^#Lf=un(c?!*(NgN$_f2)@tYcmohi6~C;C&sZ>ou%hplVohuB#s{Cu08H;Hxr z1>iSe5B6C--x9Htk~P>N6FaPPYM{vlPbwa*X>@&zya!)p+6FNAh}U2V@Mtxj$-r6gNkl4nNW177oosC|GO zK7V;;G!1RRbxMF&obHPs%EGG(G5;PzNUzBDxsSl66k>8vq9_u)h%G2GbxCG<}WFZ2fBJ!|mK z|J2f_UT9&@zYgPo*CsK64TP-pEa(9G`~Dm%{v3?@AHb7?!E31Kg?q)P05i{mcz>fx zpH2N1aMF!_KCf)|7V<3UA>f;5K|)8K1w9Bj-dQuUX6rA{g6;{*A#P>kFh)2^;yu6cg%j()1YO>$5=jtA9k*aRvQ1|EI02O(3y&FASL@t zoEH>&R{&-||LIAz_F}JcZ#pMwK5GDsd`fHNABYaL&Mu-n<)HQxF-y;X9HQ|CXuOf8 zp>j6>rZN(p^FW8*D=h&H+Mi?JWZ|6vtburAZ*!9Hrau3#y>Ee!s<`)`O@fAC6$Bsk z#UX-8B-uQ82!seB2_zMgNKl}FVY4|&)@*jyJ-d(yR%}u6*`%cwt5vi`QLA#*DZP}8!AJdne>1YU)qnpb#OlAe^TH5nKqVPBJ5DSmyN;>?YlRl!<=i&E7uW!qwU*G_VQ(+ ze2Bk8!0uDd?T4PpFGG0xJ_5;~>QxA4-NzVPMxgPdB1^d_5sfZ)(+wz%cyq_L>$M|kL*=gW^aX;}W zJsnS$ap#ntS2^Bq5U&^Uv>dgrrnI(@3{Hc5(4O0LKZN_9jRSg~%YY6Cy;$mWyel{j z{U70JKeiV`qk)9ZCT*?3fKS=!riR$QG$9EEUlJ_T9bfHH%g-3yuT_8+C}<_FaCh^Hc4Tz@+N zY4+-JBOJXmPv*bWfs+!24++Z(GU zW*W#p-LpCCvVo_{_k^Tp-J9z{JM^C@-#JI$#MyJSXLH(Moaww8?=ZzW&%Zmp=Z)*I zr*jl!|6S7G;OU1vetuuM>+^CWXkGYTde5HA(Z&$IH@$rGo}kt?5-`-L+ z(V72?oVHHqWx|)E{d^yBehB;jq0-vgH?6IXw4Mak=}7)QNbh;v>6Vevv(f36JD}$w zr`rbudhSnk>mD&|Y!7Uq_B^n*9^3O1n;Yc6pY{W8bGl(a;AXge^dk2=)IIuy8lNF& z8ISh^zKd|c!zy4)xpHf=pJwXw#%Q02o4N+Dwb|DZU+R`awOO|JcOsl_vv>yt=5dk_ zd|Pj{9JeFzHz|L|et`GqHlCbiU|ZcqTn5>Omf^i@z`e_$S3Kf6YLC#x-I<;Na_pnF zNcv8;!G%Zn)KFMk8FTgC65JkuAIg?mc50_fc^<26=oZEYgw>8HdP zNY-y*O?{g#7v!e()FV$M>uVL4b%)KZm&euhk0)i4d%CJusRN*USLt*y1|@9iw(|9- zcS5S1DYiGQcSca(+pgwTM7?+il^u>$Tw*lyCfD%7^;cF@kO7&m$jQzH{v5WB*^lpKR%0g@+Rk z&%=KGT;T&Y9!^a1knq0?{&J1_1!X>naEI-eY%9mN0}^HaSlW8HU$XzT@E4E~)gSRD z`vcmnuD|KF`hcED)iK;ZmmnUsd;2B(D(ruK^)jKpW@qOr1_=!!zTFYey#fy^;zPH=KkM+Kk=H-QT&`?CETmgANse4 zv)tGoK9SRS7i<4-+hnvVOUcO2o1;%|AREIqibrRk+`%>moZVONe#}NV-Da=l`lGX` zkSo6Hk}1pcb%dd_sF&hS@8Z-lMOpUuqZhmVJ2HFHDJ*1yI+gm*t{2tG-Y5?K9doOM{S)c^&4wXk`TW~o;70O3QrYh1@bs<70eXys{(!wywm&=H3I32b z@{qDEQT!iDwpa(LcSJsme6(!GK(?S~_hMd4?Lx|Tn0hb!lL%+e)85ujx5=uP^|!sP zJ;-H|{b2#uTN}UceJ=L@;r|}ySnpzf^A6@EYJPQ$oL}{(54tyZ0M@fK-x?^?e5--# z0An2HS{UQH{i_D{bR&&Duvuzb?e~B+Ez9xrz#hyaSDy=czG!<74eZ=UB+ow~F51JP z<;l;sEk!sj&)1QcEHmt?<XN=WB2qtNW5ozt?Y0&NUqReTRO2=pT5`c}kgYJx0px0Nke@BEFQ(HuZkS zzu4l_H$|o2^5c};$Ef$H?}dGE_c_|8GoS}HH@sg$xgl>^&%5AusCuS)feic3p}k zAy>q~+*F>UzTl5)Eqns%k=*n-=sI$L5Pkl^Wcmrc0ypYYG=|-(`9qqrd>aPSx0?4) zLmxSp(s&qYJe*8pyB@pYwjXizT3Pd^!s4vV4Qjt|m9_~zD-OPg@=D!U=h;j$>8*ne z@^pmTn4H^E{I~0_*eviJ%5{`J>kE52e?;6we0m=V(tDrI@*(aX*a`OH9O@p>YHq65 z=}kzhKUv7LHY5wo_2;uJs(HNY1<&|?sLYGxY0&}7bWJ9}}(mNRG!umIGe+u`Zb0@5S3HLK`f8)dnTmN?A1d=z^C#BJW zIxPlX|1k2nLyaM;IFEM`rWaQho$JIs6Yrm*@ozM23wXZ&AdPvlJj1yUPae`!0-p8^ zM?XOL+mZIyDeb5J8)=`)X|Ed6b1J2Ms!AL3m;GP2oowXOJA-8hIrVZK_Ey;B`DM#> zlFoZz&!>3L`ySXusayf%P3Kaz3{SK1qWi|~q2k~jkT2P?Zbn?PlTy1UetVwJYsW7dJa1`)#qNMqr&pov~x($EX8Ze zcu09sUDNp2gEIxN8<9Ruyfc;3pzn!a%YL$LrzhJTWUc0})SeJ-5Bz96ctyQad6<(2 z^7|e9C>^^E{77U%GW8%2+9Lo@n@KkNkZ(EOt4MtJ_QMy&vGesH^QGNK(EJgyA->ip z__EcNtsl~RY^jaiiT?Kn`rkg(*`Fb6lA-2}`k&+tZG9j3>;;bl!0V=Wz$4d*Zl79q znwLE!Yw&T^VR*be!K1Ao^i%)D6Xi|v8vDVa^QJITKAd+e=dIoC@>!h7+xDI0e)2{i z?#{e&WY0j))ULf_FrJ($x-!X*Un(X_zaHiH#+mRN%6_B8L_5!0=$Y(8)T!o8x3x(Q zp3%1U>pC6NAJ5-OzALwybn9nRH={0OzsSS7?jF3KH<#Nr<{SO)J44Iov%Rp_Ohq!V?8yP_OZH?;})LFK!2gJ z4)Nu4ZpTtNNmro_;!HNZV|n&2jI)_EN3)IZwAThX)4FSRZ;seZ<1)E@g0P#Vm~hp4w%TyI#EGH2>(gdGO!kLW-0tX| z)kAc9o1c_TX0o4b5c@{-eDdh$Kdh#9J>OPNgin2MwXMI{^(%DiTIlN@q(O5WdVUH# zcaL~Hw`ULf$U`Ux(q2t^689bSToU@ij=b^{dfrCc66X)tENC5vHgz|`m2p^lR*L2! z)Mj!Ah|O3VtR9a`xbHdipD-kcX8TL zJ^N>Dy{CxU(y@s!Cm+PR7Gsw{yE^$J&?hiW&-CKk3etT)XxJ+xO*ViFnSKW}>?_j! zEzp-UP4D@kjS5P059qZ_{|WR4rt!}8lYY+hPSDRW{R-$mF#RIvH<^AO^xv3%4)o_t z{~9#L2btG1pigJ|DbV>$Zv#D<=_f#+$Mj>M7c#vObUV|JfWDOJe*=9D(+_~Ynd$pL zuV;Ea=tr4e2l|&x-w7J?Tglt)px6M^6n7#t^WlVny^bJfe1AQygouKbyIu3dZ(^1gBWjYM{b*6)$ z{}Z%`1wvgd&5cXUs1*o@Gz^($v!y}Qv?Ae*k862q8#II38-|NCC@;n!e_)EODtB3dFiZm#>*g zqo6=b$*Y}WT@lk5)tn{fRnBN^sA_1asjF?QtZF!KPF=k?ud+%6J1>cecIK|3p}KL- zocS6fL0>H9^S2o#=blw8E(o=U!b?NiSNl=woB$$3AhEy_GZK!(BPtsE6(}bP9cv54 zJIY4pMtuHQ&^Cd=6KLF)UCh@giNC)YF-jIL;kL^v15z!O0A%2Mhx$mQWYy6 zvd0@KlN7!dsvo1Uq05Sy9fdOkO;KO8tFVFOXBE~5Lakn3pru8GEuZC&1|l(|z%+7V zW-w^@B9UOg?~9?08QChnQMCl^#>zHgVWSC|=ZIXxikQB3Gg=TcEkuqPlGB0~11uWn z8imc~lEPT5%g8&+hyFL2Wbq0v0XD3zP^=B|P%I#p^t7m`jaHx|0%;b;t!Sau z=8Kwz(%mYAOwDG~YLA5@g%DBH3>P+`^xkl*Pego5cwZ_K$;E4SnoT3-#c(+b6Mp;>+ruM?}nKhNhoSHc^tBkodbE=K=FQ}VS)sXO+h4xxL zBh`=90a`}1OHiemswQo9DvqdDb7ZJ;e=M*B-7|+HMZ1){WyXwUOQywRv2f@zY5>cc zB#q7&i$_Cd^JPZ3#mF_NR;bCT4rFADY(p#!pkiWy7-}F}fq);aN|@1TI4Ug29$|dZ z5F{b|sA6hz)Xz;rgxmeTklzdn=o4Q&7&AE6>d^N*B?i4HAG&HA*ka8S_~Gk z0ktLzVZ_?Zkg5VDX`@&nGiaHHBLXG%Wx`Xz`-Cq^rk|286f*H>hMJKrGmMIom1sbJ zHJMSPptxiLdm*?i6NQhV6{+?l5jq$_)|b$Gau7HI^=~XU{Bd;t7NaDO5)f86idNrY zwKj!21vNHuMT;m1`p}Jyx^}=&n31Xy3ZdI#snJsi6f9Uy2U@EQVmCXWz%c>{TbM(7sIeM~#gaX;pdj3?Bv~fqsv11Iuxxc;5e(39 zP~Z;-;~f}3vO%{6n$3bX4Ap2Ss%cYS6@gGoI8i5MvI0?KOEJNau4ZRUIg-jK2>Ck9 zGNoDyWK7H^h&h3gRgN{GIK~u_XR8TRnyn^^5*4Z?fXX61QbO5lwwP+xo*OIxDh4h;o6?~iK4fa(p;^K z!+Phm=jKTlFX{T`sBbB-z%;Zh8N(}lR=d{cxmq>b1Js?D-=A|ud2L12%zTQDt{n>Z z8+U$HL%)%0>yi;wi_H~QTNu;T79>QCsw_w3rSsx#oM(mAT8^JDF^R0U4c705n^s6ejuuvHqi zyq26p=H}$&$Z1qlAXM1@w9#0YJv|UYH(w}ciZpXTTMETG!q5qrBw)tx2O9`hFI%Dt z7K_Hs90RFy!?E+~O*D%XS9^O&@z5=XCk<$($#Q#BT1tu!wUt9xw^4MM+BQlYm0f)J zs+Nh_YTBUit)1NZM5`teE(U7~3xnFE;(S{_*E6HKc2v6t${!AT-XaxBzSJYhP;j)x zsUQ#us?2z0xghG7_$-E%pkk2oyMfZ z+(1v{;3jnphgQ)rXvWDw%`*&9WQ;GuOaaoPk*zk2zj-tO#X2H|YC7(Xb;fLCP-4hX zzSF|tU>Oe_HW!*hlqx(Mnsa0>R$qoAQLV+3(MBd>h+@eYv2s>%f4L{7G-!CqSxY~q zG1Oox7jFF&Y#@GWR+KW;N%C~4!coKoyI-Mz;43NPA`)^=sY6K8Rg@b3py`Vy%fYfq zl&fDMVI6LUvIZ(K$^OisC<`l6d*1zKEh|0R;jA*5YH~Vhmwl;|%O;-{@CQPXcuYtx zFrzKSf1=eN4RFW$iKeJn`DS+&h9(*0Vo{Y@J`7R?GLG=+X{LdWg!R`5gJxhf+!tdq z-5P}j0W0kVp{_-x&0);bw7g{`8IzrAA4kyqM z^Q~f(WFdxS+8SU|pb<P;7m&a`JNu z5g^4@lNvy$+of`>p;4*D=Qnd@Zuwu3d?L2WwhL37{GxoC70L^@ocwV`MMZhpB4S2^ zs=P$edN@0d4qa=;CQYhD2}?V=jD;g%N#zn_agp#VIG5d3Ajz68VuKl767ZV{ZjW7X zF3HGJeqSV{ynd3clj4=B_LrSXU)RAG$oL4PC<|}TsHVAe;mA~nzRV~l3(l>jI`7K0 z+5#=He4{Ae$QgyIPx-rGQNFS4vV52s@=9SgktugsuqiNEAZgNQurDk(1fJu^%@DW& zWRZ~#SC){JRGM%Vee{#)S7FFlS+M8z-}wYhriuk7Q6-`|9sOJm0D@(Zhs@`{S8+BwF;PE3meC^<$L zFF5G0tUSxh))RU|=_}+4^FTAqE{x?!WV025cdQPiK`Fa9+c?XRylUGcttwD0un!`P zUf5%Pq0RV^21#vcINEGT(a;EsMQp02ATdi*igBb)$iBi)I>IV|WTAv%P0<9b;M!av ztsMmI{HTgjadhfnGcoT^PQOzo`L>C+Jr=JKzBm%9g4pEh)lU^6ezj=ZIBxQm2&S%aew#~Fw(>7(H_gr|KS#k4(<%*j+o1}!X0KTfci7g zuG?Vt&Ie&M1p}dW5K+T|jV_<;4J3#V`jl$!EdevwoF~w=x&2DgGX3!=Oy$WoPR7t| zL#+lxe=C!(JbnM~Ox_c7Z{z&vlC)Zbpw z^qQG-s%F#HX2tB9`Z?IpmMZrBN*1(k_jgnoVtAhW=xiEiAjm5Gz!U;ASMSvOg3qA zsi1(u;D)JlOCZ`&0Egzq`sWKO~#Pg3T5?K*ajdsYbvRsi%v)^2i zmzNJRQAW&$&(6uqV>=nt7t|Du`P5Z%p)K=`SR8whc?mP<7ir|_$nwkT<7Axv%BQsQ z7qcdfy3ohcXe8}LsKCNW2JOoSv2g-qVQ<}R@(Po*k+b7G)$T%@(j_(cGSnLaVXmYnR;MxbJ`IasCiRm z(%6AEZJ&w>XTK9hF)=))InTPof-L7fXAdO4I%IATJTXr%+Ugq)yk%!n_F z22~J_$H=q;UkaL3NaUi!+w_MBPDe1Si~=hKK+WBrQ*NR<%8Iq^+R^Y;8hyH@a#mXu z=&K5<(+FibIavd7_Q#Np)Pj^Rf~ABTT?R?#O253(Im;1AZHw5`S}>`gcoEIWlq2R+ zR3z2k`xd6(o~vRy3&1?dDd0bse@rlO_LrD$o=u)X|DA&+EC>*5CPHrJM zw}Oq-5KQ4w3`5~)m-I+&2xtchZ(Bo1ai%G0YKurjp&2#y^ssA}DrH*$7%`AXLP<5q zF%i~s$*C%vbNyFcHLr2@jA{1i!x7C561zhVX{pYLtzk4VGGD1-UtvAQE40iJQy)w+ za8innl!R>?OZM|hKFhcugcWl$R;gHm`pZK}4K(LAD+D&mCf%Iz?^O{RE=ytUdP<%WM}8O#i8tRrLw%?TPyi8!%CA`LBU zEEq#gR{AG(6kKREf`v4u2x_7vLzIoOxTQ)+F=ERU7^e{N`peRPQwZ)CZ zAKJ#pxjM({Ev9xa``wV1d8!r^J<`>vJr3z0iF4&&Oo8(CPHMl z*k*Pb(bgu6)zrIl176c>oY^wY?<*nh`i$tK=m?9JF@0_LWe5N{2n;5Ds z14r3f+vr4OYseRrDX8O^LYsJe?uLGck45mYAxQv6!kt(KOEl%7tZB$)zgR~}HFMMD5GhS^pg zH7L<3+QMcDPO&7BV!)bXMmqwiw%PFz9ZQr!0CfQ?GtWILT#Tr68@Cl-kv zXrwJZBd5~5*mq&vXn;Y}m=z9%v21Ly$SA{G<5Oge9#u;n`5Q(5{OkoC9!)9yVGaOb7X3f5|1XpMs@wk#8R1;#mlTo* zHF_E@dOT|+*Dl=&x5@89@L%pFzzo2vGWz-dE{duDnAvT;PH6T(ol~lH^(D(6?i;ryoyI= z#l5)_a3$bMz?Fb20apU91Y8NY5^yEpO2CzXD*;ymt^`~OxDs$B;7Y)ifGYu40XBw}hO>XM9)5(@|5q?LQe91UXC>A-KX+PJb0NI-q$K~ z({JxgWaJ3srMmk32!0&_d>jOC6tluDF?{sY9AV@xHSxw*lgj=LbyX9)P zkS$i{M%X zJDUToffzZgCx;GSFc_BkZjjLI@JD3uO$;ql2Hr-H_~n9bCmczXbcckxJUb&lVy9vkq zs6JmzMd(#7kf?UqFI~dH@KV{}qX!7bL%t4@1N}UW;-;f;PZz7liwv>t^9=lb`r`~Z zJUv#3G_I#;nw=7X_=vzm|$9# zuhpb@Wf@}aXO!BebMa?Ap0P>uMLT>tWLrEOGb_!Q=|>u(BVFvzL9(kpm0bKoaxnwU z`IeZ|13|M=<|0;m%pf964+qhW+3iQ3HZvGBJCMCE+NG0U>q!@nS0m#cGx6u;S@`qZ zd0=6T4)Cr=Q~Nz)kRO7IRImf1C03@Vi(BU*+RERNm<}K^>ZAaF_T!xoX%*C$f0bT?dU!59 zL+sd^2A}IMM#$CQq0DyNoQ6<%BZVd2O%KNcEnW5DNIW9`ion}nN=JwlcT%|RHxm8G zT3HFj#Gg~TGM8R8h9xHi4XG$Z2C^pvXDl8$#<_{|FSMh)>~I@-L-S-g-g--tm?ZFhP{vfaIz z9uj{~cU0C58EBvpq+*KiXISFJj3uaNw6(OB=0wFmsJ(gJ;u} zot|wTquaB>v#X{%eSQ9V&+6Qtrfu@nKkZrL`Kf35Bc6qydLH+D>RB#cMn60jFJm!I zr%o-zKF0ITPE{2B`3pvladt;~ny?AwrzWcq9$B_~kI(z<46#6=)drt7g0p z?}VY>LdN-H6mDl6W8BI3amLp&o(i2qzndA84x-;ZjMpqtcq8NdPKAHXcmv}pOWarL(pp33++#xogLUatHXG2Xs}vSNJx@^*>hlLB`#;Df|Ru@r=U1X1s>+OWOY}<^Mk8os2)$;d_<; z0CYzx|0c$R8CSop{D(9CDFwo>nDN516s}-=a;d^I8Bd<9@CA%xQx$Gzyn}I!@pI+M ze+A=J(-iJzys|>!b&N%&!kY;X6k^4b3U6mz^pwJT7>{M_$yDJdFdof#GUEk|r!rp7 zxRUX0jH?+x#&{;4*ZaW3P>8Rs+J$+(E|r;NukK4TEe zpYasNlNmQMp33+N#+8ikU|h}kDaJDyzrnbk@xWtP{)|U6p2zrn#tRvDFy6)Z`;2!p zzMt_v#xF7MW&9!I_ZScP8uABE;uTe2g^V*8moXm3_&mlV8DGRWmvKAe35>t3@gG$B zw`=^G!jCha%J?;n_b7kQv5LQX#zQs!v-0;cUdXsgF*yZp?HCDCddCX<4WfDGsaJI{wE7T=;h$&!l_#q3R87QR2MO1iv=+ul|*U;&R4g2P^*{ zF@E}F<^LdIL&uQ^SvN;L#2|-hnF} zc(w!k95~{@OB{HG1Fv%6ZU_FM1K;Mr>m2w#2Y$qXA9vuV9r(8n{E7p=?!a$3@P9h+ z-yIk$iIn=wbl~G0_#_859QbSpE^**V4m{0)s~x!Bf#*4}&w&FD9ChGj4!qKVuXo_p z4*X*WUhlvUJMiNU{FDRVh(7aOT(sz4jq3-vZo>6LTx)QVzWfocTX5Zqi>944)g*PX z7S|oP?!@&ITtCIN4%c0{?#8tq*FCuI#YKAdXSnXi^#HC1ac#i$Z@3=9^)RkSaQ!>3 zM{#Y$wF%c|T#w<}g6nZyPv9aQy%pCsTs^qHhwJ;ep2YS4dwC22Lz-IV_gP{##;^)a zS^r9x#5z|YZI6-2VW*I8$(LPf%Y$-Gu8}2nERm&~d=X|!tV>etG%`@C)k8X2sdgIW z*4I{}-21cFNS_qbiFC19Pb5|bl!Ot-=9XkyE#}E2=rF1@(hEi*VPAi?740dl5E?k@ zLPbxpNa&CWyM#2t^l>FSiFUMAr%KRfywG9f3r`ah$< zzsk{GHsekr8D+=O5attU!m(j#%Ykj)Zc!&wz0H=MV!4-A^b{9m%a=~ljIStZ#Fu2k z&d!MK<_aZj>l$ibX-`jD(zOj;ThG~U&K7gFl`AWG!agnu7{=*N7V(5BoCvakuDkjskyu-*W z?_`W7f~?SVm*!_8q}`c_L>$mE2$`74BNm2j*=AG*sjbP4F*YN!{kYG5N@KG$&(^}Y zTo($W(2x@=H__NEZM>>``c3#Lo93)=GeE@Wj|CH57l!$2U#K|<+gxMV@>%|9AQDUX z`dY{cnt)cs^tGGOm}w=0w4??}2~WTZ$3qEoEHY0CKt12=G!q$wtmy=@M>Ps*eBbhtVQF} zHV6p2QHcbQyo^p&0qJ(d+QOmArnr>|5HX|4&`PhsaG#V(b39~8%P<@C8>K@cdJEJ* zRcFA$PE+I3K*S_0tGgciEpr3NE*_gs{5J%B*qWk-FwSvbE*9Er;I@(nc z?&v_<(tb&qJ7kz>z_WZ8hoiFsp>Pys^P?<{vfZPBRNrB(Psn8dp{n)rezx z)s@s)sY(?s+|jrkO4b{k+@#=XHB zr&Axzj-oh)(T{5K2In45=Y!e9j{ut4Lk$Y>KkNwM4c5xZ=-~zp^r^#*BJ7@DQR<38T5bD219bEad>d+HzwC8wBOG2YK^-hYXQ{AL^ z_NQf10@&9LD6V?jKL#o}XeB2{njyG2MjPmkXcRlXYWSs{S~VW)81_+FyCsHKZ;*#s zESD3%kN{8hQSTivy9(~G#Cxi@K1;ku6elVccw@?bE=UhV9`E;pQktx zPRbp_y6T#i7XxRYNj!L6+Y5huzy0BhpZV?;H-7u5*KRxUnjz~xdB6LPY4?3_?wH}z z7evS0G~?pE*LJ;M{1JINB{8R6N~-%_wT;z!Lr)-p8nm3 zKl|RcpKKd-?2rF_(_g>+>W9xRxutXJZEI$)4?n;2sPaG5-;?u;frG|M%H}&56sd)3naU=h0(5?fG4SS;> zy|L>4cfWCZ{BQd|j=uf%@a6L!yx@WLwOc;u8B?+0<6#*$Og;W*p9CiDyYu{J@#qgm z?HYgJXGP~+{o&60E_&&w&#asMm#oD*N+Qdn2O>}1c-=$K%zg9bUr#?!^Vv-|{@}Xv zo~+(^_vdYkFS+{tE9%$Pjk@jbm64Mc|DxoRv%}xJs-bG)-Ffk~AD{E|QMbOgZsm_Q zK6%Rh6-QrGWlm2&Bki%*if_%xd~@TYUE3$ehu$>0f7>K}~zud{~bAMN`_^sb(=$A?|q@k!|SSGG-B{>W9`Q%>j} zKItEiwx0gXHQN`p|L3!>y?tMx{qA3So7bK*yXCH??VlWb%}2w6Z_RsR#WH{SS=YVr z{-TxNeXQl$e?NWy*Pi)9R`-*~@0j8Bu81x?=V!A%`6T_7s%vj)t^2RDBiUCMee%24 zN9T_pk#*Cuop-*zfPzBuBl z*qZjSdCxWMdiJM(xhk{fFX7!=U%C36zx>CRmeO6{C~XxA>pWX1}(Z?US|MH(bG%x(j+b!ENUVY((_O!Zr13q8=$ns0C{NoeX zRbP{T_y4s2?~fW3dadfw;>-7Z|BSO=+kep=<-2}z*QyhKKH%h!&VFddN5#MS&fHl0 zx|=_4y*+mIq?I>3HRze0Pd<3t^zmisPu46L_WtnyE`R6LXMX$no4@YevhBy-a>dqr wHoyAtjc2^}eD@UN^on@-jf?O8d-1p0k9+lkeXrbA^UJ&9n+80)nzhgW1G94s&j0`b literal 0 HcmV?d00001 diff --git a/external/tinyfiledialogs/macos/.gitkeep b/external/tinyfiledialogs/macos/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/external/tinyfiledialogs/tinyfiledialogs.c b/external/tinyfiledialogs/tinyfiledialogs.c new file mode 100644 index 0000000..5614241 --- /dev/null +++ b/external/tinyfiledialogs/tinyfiledialogs.c @@ -0,0 +1,8171 @@ +/* SPDX-License-Identifier: Zlib +Copyright (c) 2014 - 2024 Guillaume Vareille http://ysengrin.com + ________________________________________________________________ + | | + | 100% compatible C C++ -> You can rename this .c file as .cpp | + |________________________________________________________________| + +********* TINY FILE DIALOGS OFFICIAL WEBSITE IS ON SOURCEFORGE ********* + _________ + / \ tinyfiledialogs.c v3.18.2 [Jun 8, 2024] zlib licence + |tiny file| Unique code file created [November 9, 2014] + | dialogs | + \____ ___/ 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. + + __________________________________________ + | ______________________________________ | + | | | | + | | DO NOT USE USER INPUT IN THE DIALOGS | | + | |______________________________________| | + |__________________________________________| +*/ + + +#if defined(__GNUC__) || defined(__clang__) +#ifndef _GNU_SOURCE + #define _GNU_SOURCE /* used only to resolve symbolic links. Can be commented out */ + #ifndef _POSIX_C_SOURCE + #ifdef __FreeBSD__ + #define _POSIX_C_SOURCE 199506L /* 199506L is enough for freebsd for realpath() */ + #elif defined(__illumos__) || defined(__solaris__) + #define _POSIX_C_SOURCE 200112L /* illumos/solaris needs 200112L for realpath() */ + #else + #define _POSIX_C_SOURCE 2 /* to accept POSIX 2 in old ANSI C standards */ + #endif + #endif +#endif +#endif + +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #ifdef __BORLANDC__ + #define _getch getch + #endif + #ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0500 + #endif + #include + #include + #include + #include + #include + #define TINYFD_NOCCSUNICODE + #define TINYFD_SLASH "\\" +#else + #include + #include + #include /* on old systems try instead */ + #include + #include + #include /* on old systems try instead */ + #define TINYFD_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.18.2"; + +/******************************************************************************************************/ +/**************************************** 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 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 yad matedialog + shellementary qarma python2-tkinter python3-tkinter python-dbus + perl-dbus gxmessage gmessage xmessage xdialog gdialog dunst +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 ** Disabled by default **)\ +\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) ** Disabled by default **\ +\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 , TINYFD_SLASH , 1 ) ) + { + strcat( lastcar , TINYFD_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; + if ( strchr(p, '\'')) + { + return 1; + } + + if ( strchr(p, '\"')) + { + return 1; + } + + if ( strchr(p, '`')) + { + return 1; + } + + p = aString; + while ((p = strchr(p, '$'))) + { + p ++ ; + if ( ( * p == '(' ) || ( * p == '_' ) || isalpha( * 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(MB_OK); +} + + +static void wipefileW(wchar_t const * aFilename) +{ + int i; + FILE * lIn; +#if (defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64__) && (__MINGW32_MAJOR_VERSION <= 3)) || defined(__BORLANDC__) || defined(__WATCOMC__) + 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)) || defined(__BORLANDC__) || defined(__WATCOMC__) + 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)) || defined(__BORLANDC__) || defined(__WATCOMC__) + 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)) || defined(__BORLANDC__) || defined(__WATCOMC__) + 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)) || defined(__BORLANDC__) || defined(__WATCOMC__) + 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)) || defined(__BORLANDC__) || defined(__WATCOMC__) + 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]; + wchar_t const* lDialogTitle = (wchar_t const *) lParam; + + GetWindowTextW(hwnd, lTitleName, MAX_PATH); + /* wprintf(L"lTitleName %ls \n", lTitleName); */ + + if (wcscmp(lDialogTitle, 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)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 if (aDialogType && !wcscmp(L"yesnocancel", aDialogType)) + { + aCode += MB_YESNOCANCEL; + if (aDefaultButton == 1) + { + aCode += MB_DEFBUTTON1; + } + else if (aDefaultButton == 2) + { + aCode += MB_DEFBUTTON2; + } + else + { + aCode += MB_DEFBUTTON3; + } + } + else + { + aCode += MB_OK; + } + + aCode += MB_TOPMOST; + + lBoxReturnValue = MessageBoxW(GetForegroundWindow(), aMessage, aTitle, aCode); + + if ( (lBoxReturnValue == IDNO) && (aDialogType && !wcscmp(L"yesnocancel", aDialogType)) ) + { + return 2; + } + else if ( (lBoxReturnValue == IDOK) || (lBoxReturnValue == IDYES) ) + { + return 1; + } + else + { + return 0; + } +} + + +/* int tinyfd_notifyPopupW_ORIGINAL( + wchar_t const * aTitle, + wchar_t const * aMessage, + wchar_t const * aIconType) +{ + 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 -executionpolicy bypass -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"\""); + + hiddenConsoleW(lDialogString, aTitle, 0); + free(lDialogString); + return 1; +}*/ + + +/* 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; + + FILE* lIn; + + 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; + + 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 0; + } + + wcscpy(lDialogString, L"\n\ +\n\ +\n\ +"); + if ( aTitle && wcslen(aTitle) ) wcscat(lDialogString, aTitle); + wcscat(lDialogString, L"\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +
\n"); + + wcscat(lDialogString, aMessage ? aMessage : L""); + + wcscat(lDialogString, L"\n\ +\n\ +\n\ +"); + + fputws(lDialogString, lIn); + fclose(lIn); + + 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 ) ; */ + wcscpy(lDialogString, + L"cmd.exe /c mshta.exe \"%TEMP%\\tinyfd.hta\""); + + 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: use the GRAVE ACCENT \\x60 instead."); + + 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"\",\""); + if (aTitle) wcscat(lDialogString, aTitle); + wcscat(lDialogString, L"\",\""); + + 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\ +\n\ +\n\ +"); + if (aTitle) wcscat(lDialogString, aTitle); + wcscat(lDialogString, L"\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +\n\ +
\n"); + + wcscat(lDialogString, aMessage ? aMessage : L""); + + wcscat(lDialogString, L"\n\ +\n\ +\n\ +\n\ +
\n\ +

\n\ +\n\ +
\n\ +
\n"); + + wcscat(lDialogString, L"\n\ +\n\ +\n\ +\n\ +
\n\ +
\n\ +
\n\ +\n\ +\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 * aDefaultPathAndOrFile, /* 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", aDefaultPathAndOrFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); + if (quoteDetectedW(aDefaultPathAndOrFile)) return tinyfd_saveFileDialogW(aTitle, L"INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); + if (quoteDetectedW(aSingleFilterDescription)) return tinyfd_saveFileDialogW(aTitle, aDefaultPathAndOrFile, 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: use the GRAVE ACCENT \\x60 instead.", aDefaultPathAndOrFile, 0, NULL, NULL); + }*/ + + lHResult = CoInitializeEx(NULL, 0); + + getPathWithoutFinalSlashW(lDirname, aDefaultPathAndOrFile); + getLastNameW(lBuff, aDefaultPathAndOrFile); + + 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 * aDefaultPathAndOrFile, /* 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", aDefaultPathAndOrFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); + if (quoteDetectedW(aDefaultPathAndOrFile)) return tinyfd_openFileDialogW(aTitle, L"INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); + if (quoteDetectedW(aSingleFilterDescription)) return tinyfd_openFileDialogW(aTitle, aDefaultPathAndOrFile, 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: use the GRAVE ACCENT \\x60 instead.", aDefaultPathAndOrFile, 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, aDefaultPathAndOrFile); + getLastNameW(lBuff, aDefaultPathAndOrFile); + + 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]; + (void)lParam; + 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) +{ + (void)lp; + 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: use the GRAVE ACCENT \\x60 instead.", aDefaultRGB, aoResultRGB);*/ + + lHResult = CoInitializeEx(NULL, 0); + + if ( aDefaultHexRGB && wcslen(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 * aDefaultPathAndOrFile, /* 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 (aDefaultPathAndOrFile) + { + if (tinyfd_winUtf8) lTmpWChar = tinyfd_utf8to16(aDefaultPathAndOrFile); + else lTmpWChar = tinyfd_mbcsTo16(aDefaultPathAndOrFile); + 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 * aDefaultPathAndOrFile, /* 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 (aDefaultPathAndOrFile) + { + if (tinyfd_winUtf8) lTmpWChar = tinyfd_utf8to16(aDefaultPathAndOrFile); + else lTmpWChar = tinyfd_mbcsTo16(aDefaultPathAndOrFile); + 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 * lTmpWChar; + char * lTmpChar; + wchar_t lDefaultHexRGB[16] = L""; + + 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) + { + lIn = _popen("where dialog.exe", "r"); + if ( ! lIn ) + { + 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] = ""; + (void)aIconType; + + 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 * aDefaultPathAndOrFile ) /* 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + /* dialog.exe uses unix separators even on windows */ + strcpy(lPathAndFile, aDefaultPathAndOrFile); + 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 * aDefaultPathAndOrFile ) /* 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + /* dialog.exe uses unix separators even on windows */ + strcpy(lFilterPatterns, aDefaultPathAndOrFile); + 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 "); fflush(stdout); + 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: use the GRAVE ACCENT \\x60 instead."); + + 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): "); fflush(stdout); + 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 * aDefaultPathAndOrFile , /* 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 ( ! aFilterPatterns ) aNumOfFilterPatterns = 0 ; + if (tfd_quoteDetected(aTitle)) return tinyfd_saveFileDialog("INVALID TITLE WITH QUOTES", aDefaultPathAndOrFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); + if (tfd_quoteDetected(aDefaultPathAndOrFile)) return tinyfd_saveFileDialog(aTitle, "INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); + if (tfd_quoteDetected(aSingleFilterDescription)) return tinyfd_saveFileDialog(aTitle, aDefaultPathAndOrFile, 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: use the GRAVE ACCENT \\x60 instead.", aDefaultPathAndOrFile, 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, aDefaultPathAndOrFile, 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, aDefaultPathAndOrFile); + } + 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 * aDefaultPathAndOrFile, /* 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 */ +{ + static char lBuff[MAX_PATH_OR_CMD]; + char lString[MAX_PATH_OR_CMD]; + char * p; + char * lPointerInputBox; + int i; + + if ( ! aFilterPatterns ) aNumOfFilterPatterns = 0 ; + if (tfd_quoteDetected(aTitle)) return tinyfd_openFileDialog("INVALID TITLE WITH QUOTES", aDefaultPathAndOrFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); + if (tfd_quoteDetected(aDefaultPathAndOrFile)) return tinyfd_openFileDialog(aTitle, "INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); + if (tfd_quoteDetected(aSingleFilterDescription)) return tinyfd_openFileDialog(aTitle, aDefaultPathAndOrFile, 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: use the GRAVE ACCENT \\x60 instead.", aDefaultPathAndOrFile, 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, aDefaultPathAndOrFile, 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, aDefaultPathAndOrFile); + } + 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 ; +} + + +/* aDefaultRGB is used only if aDefaultHexRGB is absent */ +/* aDefaultRGB and aoResultRGB can be the same array */ +/* returns NULL on cancel */ +/* returns the hexcolor as a string "#FF0000" */ +/* aoResultRGB also contains the result */ +char * tinyfd_colorChooser( + char const * aTitle, /* NULL or "" */ + char const * aDefaultHexRGB, /* NULL or "" 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: use the GRAVE ACCENT \\x60 instead.", 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 && (strlen(aDefaultHexRGB)==7) ) + { + 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] = "command -v " ; + 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 kgx + 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 ffplayPresent(void) +{ + static int lFFplayPresent = -1; + if (lFFplayPresent < 0) + { + lFFplayPresent = detectPresence("ffplay"); + } + return lFFplayPresent; +} + + +static int pactlPresent( void ) +{ + static int lPactlPresent = -1 ; + char lBuff [256] ; + FILE * lIn ; + + if ( lPactlPresent < 0 ) + { + lPactlPresent = detectPresence("pactl") ; + if ( lPactlPresent ) + { + lIn = popen( "pactl info | grep -iF pulseaudio" , "r" ) ; + if ( ! (fgets( lBuff , sizeof( lBuff ) , lIn ) && ! strstr(lBuff, "PipeWire") ) ) + { + lPactlPresent = 0 ; + } + pclose( lIn ) ; + if (tinyfd_verbose) printf("is pactl valid ? %d\n", lPactlPresent); + } + } + return lPactlPresent ; +} + + +static int speakertestPresent(void) +{ + static int lSpeakertestPresent = -1 ; + if ( lSpeakertestPresent < 0 ) + { + lSpeakertestPresent = detectPresence("speaker-test") ; + } + return lSpeakertestPresent ; +} + + +static int playPresent(void) /* play is part of sox */ +{ + static int lPlayPresent = -1; + if (lPlayPresent < 0) + { + lPlayPresent = detectPresence("sox"); /*if sox is present, play is ready*/ + } + return lPlayPresent; +} + + +static int beepexePresent(void) +{ + 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 playsoundPresent(void) /* playsound is part of pipewire */ +{ + static int lPlaysoundPresent = -1 ; + if (lPlaysoundPresent < 0) + { + lPlaysoundPresent = detectPresence("playsound_simple"); + if ( lPlaysoundPresent && ! fileExists("/usr/share/sounds/freedesktop/stereo/bell.oga") ) + { + lPlaysoundPresent = 0 ; + } + } + return lPlaysoundPresent; +} + + +static int paplayPresent(void) /* playsound is part of pipewire */ +{ + static int lPaplayPresent = -1 ; + if (lPaplayPresent < 0) + { + lPaplayPresent = detectPresence("paplay"); + if ( lPaplayPresent && ! fileExists("/usr/share/sounds/freedesktop/stereo/bell.oga") ) + { + lPaplayPresent = 0 ; + } + } + return lPaplayPresent; +} + + +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") ; +} + + +static int dunstifyPresent(void) +{ + static int lDunstifyPresent = -1 ; + static char lBuff[MAX_PATH_OR_CMD] ; + FILE * lIn ; + char * lTmp ; + + if ( lDunstifyPresent < 0 ) + { + lDunstifyPresent = detectPresence( "dunstify" ) ; + if ( lDunstifyPresent ) + { + lIn = popen( "dunstify -s" , "r" ) ; + lTmp = fgets( lBuff , sizeof( lBuff ) , lIn ) ; + pclose( lIn ) ; + /* printf("lTmp:%s\n", lTmp); */ + lDunstifyPresent = strstr(lTmp,"name:dunst\n") ? 1 : 0 ; + if (tinyfd_verbose) printf("lDunstifyPresent %d\n", lDunstifyPresent); + } + } + return lDunstifyPresent && graphicMode( ) ; +} + + +static int dunstPresent(void) +{ + static int lDunstPresent = -1 ; + static char lBuff[MAX_PATH_OR_CMD] ; + FILE * lIn ; + char * lTmp ; + + if ( lDunstPresent < 0 ) + { + lDunstPresent = detectPresence( "dunst" ) ; + if ( lDunstPresent ) + { + lIn = popen( "ps -e | grep dunst | grep -v grep" , "r" ) ; /* add "| wc -l" to receive the number of lines */ + lTmp = fgets( lBuff , sizeof( lBuff ) , lIn ) ; + pclose( lIn ) ; + /* if ( lTmp ) printf("lTmp:%s\n", lTmp); */ + if ( lTmp ) lDunstPresent = 1 ; + else lDunstPresent = 0 ; + if (tinyfd_verbose) printf("lDunstPresent %d\n", lDunstPresent); + } + } + return lDunstPresent && graphicMode( ) ; +} + + +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 lXpropReady = 0 ; + static int lXpropDetected = -1 ; + char lBuff[MAX_PATH_OR_CMD] ; + FILE * lIn ; + + if ( lXpropDetected < 0 ) + { + lXpropDetected = detectPresence("xprop") ; + } + + if ( !lXpropReady && lXpropDetected ) + { /* xwayland Debian issue reported by Kay F. Jahnke and solved with his help */ + lIn = popen( "xprop -root 32x ' $0' _NET_ACTIVE_WINDOW" , "r" ) ; + if ( fgets( lBuff , sizeof( lBuff ) , lIn ) != NULL ) + { + if ( ! strstr( lBuff , "not found" ) ) + { + if (tinyfd_verbose) printf("xprop is ready\n"); + lXpropReady = 1 ; + } + } + pclose( lIn ) ; + } + return graphicMode() ? lXpropReady : 0 ; +} + + +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 ) + { + lDesktop = getenv("XDG_SESSION_DESKTOP"); + if ( !lDesktop || ( strcmp(lDesktop, "KDE") && strcmp(lDesktop, "lxqt") ) ) + { + if ( tfd_zenityPresent() ) + { + 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" ) ; + V = 0 ; + 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 ; + + if ( lPython3Present < 0 ) + { + lPython3Present = 0 ; + strcpy(gPython3Name , "python3" ) ; + if ( detectPresence(gPython3Name) ) lPython3Present = 1; + 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 ; + + if ( lPython2Present < 0 ) + { + lPython2Present = 0 ; + strcpy(gPython2Name , "python2" ) ; + if ( detectPresence(gPython2Name) ) lPython2Present = 1; + 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\timport tkinter;\nexcept:\n\tprint(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\timport Tkinter;\nexcept:\n\tprint 0;\""; + + if ( lTkinter2Present < 0 ) + { + lTkinter2Present = 0 ; + if ( python2Present() ) + { + sprintf( lPythonCommand , "%s %s" , gPython2Name , lPythonParams ) ; + lTkinter2Present = tryCommand(lPythonCommand) ; + } + if (tinyfd_verbose) printf("lTkinter2Present %d graphicMode %d \n", lTkinter2Present, graphicMode() ) ; + } + 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\timport 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 ( pactlPresent() ) + { + signal(SIGINT, sigHandler); + strcpy( lDialogString , + "thnum=$(pactl load-module module-sine frequency=440);sleep .3;pactl unload-module $thnum" ) ; + } + else 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 ( 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 .5; kill -9 $pid" ) ; /*.3 was too short for mac g3*/ + } + else if ( ffplayPresent() ) + { + strcpy(lDialogString, "ffplay -f lavfi -i sine=f=440:d=0.15 -autoexit -nodisp" ); + } + else if (playPresent()) /* play is part of sox */ + { + strcpy(lDialogString, "play -q -n synth .3 sine 440"); + } + else if ( playsoundPresent() ) + { + strcpy( lDialogString , "playsound_simple /usr/share/sounds/freedesktop/stereo/bell.oga") ; + } + else if ( paplayPresent() ) + { + strcpy( lDialogString , "paplay /usr/share/sounds/freedesktop/stereo/bell.oga") ; + } + else if (beepexePresent()) + { + strcpy(lDialogString, "beep.exe 440 300"); + } + /*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" ) ; + } + + strcat(lDialogString, " --title=\""); + if ( aTitle && strlen(aTitle) ) strcat(lDialogString, aTitle) ; + strcat(lDialogString, "\""); + + if (strcmp("yesnocancel", aDialogType)) strcat(lDialogString, " --no-wrap"); + + strcat(lDialogString, " --text=\"") ; + if (aMessage && strlen(aMessage)) 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, " --image=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\techo 1\nelse\n\techo 0\nfi >/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 , "\techo 1\nelse\n\techo 0\nfi" ) ; + } + 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 , "\techo 1\nelse\n\techo 0\nfi" ) ; + } + 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\techo 1\n"); + strcat( lDialogString , "elif echo \"$answer\" | grep -iq \"^n\";then\n\techo 2\n" ) ; + strcat( lDialogString , "else\n\techo 0\nfi" ) ; + } + 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 = (char) 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 = (char) 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 = (char) 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 ( strlen( lBuff ) && 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") && !dunstifyPresent() && !dunstPresent() ) + { + 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 ( getenv("SSH_TTY") ) + { + if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"dunst");return 1;} + strcpy( lDialogString , "notify-send \"" ) ; + if ( aTitle && strlen(aTitle) ) + { + strcat( lDialogString , aTitle ) ; + strcat( lDialogString , "\" \"" ) ; + } + if ( aMessage && strlen(aMessage) ) + { + strcat(lDialogString, aMessage) ; + } + strcat( lDialogString , "\"" ) ; + } + else 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_yadPresent() ) + { + if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"yad");return 1;} + strcpy( lDialogString , "yad --notification"); + + if ( aIconType && strlen( aIconType ) ) + { + strcat( lDialogString , " --image=\""); + 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 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 */ + /* zenity 3.44 doesn't have the notification (3.42 has it) */ + if (aTitle&&!strcmp(aTitle,"tinyfd_query")){strcpy(tinyfd_response,"zenity");return 1;} + strcpy( lDialogString , "zenity --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 (lDialogString) free(lDialogString); + 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: use the GRAVE ACCENT \\x60 instead."); + + 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" ) ; + + strcat(lDialogString, " --title=\"") ; + if (aTitle && strlen(aTitle)) strcat(lDialogString, aTitle) ; + strcat(lDialogString, "\"") ; + + strcat(lDialogString, " --text=\"") ; + if (aMessage && strlen(aMessage)) strcat(lDialogString, aMessage) ; + strcat(lDialogString, "\"") ; + + if ( 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, ");\nif res is None :\n\tprint(0)"); + strcat(lDialogString, "\nelse :\n\tprint('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, ");\nif res is None :\n\tprint 0"); + strcat(lDialogString, "\nelse :\n\tprint '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 ( strlen( lBuff ) && 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 * aDefaultPathAndOrFile , /* NULL or "" , ends with / to set only a directory */ + int aNumOfFilterPatterns , /* 0 */ + char const * const * aFilterPatterns , /* NULL or {"*.txt","*.doc"} */ + char const * aSingleFilterDescription ) /* NULL or "text files" */ +{ + static char lBuff[MAX_PATH_OR_CMD] ; + static char lLastDirectory[MAX_PATH_OR_CMD] = "$PWD" ; + + 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 ( ! aFilterPatterns ) aNumOfFilterPatterns = 0 ; + if (tfd_quoteDetected(aTitle)) return tinyfd_saveFileDialog("INVALID TITLE WITH QUOTES", aDefaultPathAndOrFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); + if (tfd_quoteDetected(aDefaultPathAndOrFile)) return tinyfd_saveFileDialog(aTitle, "INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription); + if (tfd_quoteDetected(aSingleFilterDescription)) return tinyfd_saveFileDialog(aTitle, aDefaultPathAndOrFile, 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: use the GRAVE ACCENT \\x60 instead.", aDefaultPathAndOrFile, 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 , aDefaultPathAndOrFile ) ; + if ( strlen(lString) ) + { + strcat(lDialogString, "default location \"") ; + strcat(lDialogString, lString ) ; + strcat(lDialogString , "\" " ) ; + } + getLastName( lString , aDefaultPathAndOrFile ) ; + 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + if ( aDefaultPathAndOrFile[0] != '/' ) + { + strcat(lDialogString, lLastDirectory) ; + strcat(lDialogString , "/" ) ; + } + strcat(lDialogString, "\"") ; + strcat(lDialogString, aDefaultPathAndOrFile ) ; + strcat(lDialogString , "\"" ) ; + } + else + { + strcat(lDialogString, lLastDirectory) ; + strcat(lDialogString , "/" ) ; + } + + 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" ) ; + + strcat(lDialogString, " --title=\"") ; + if (aTitle && strlen(aTitle)) strcat(lDialogString, aTitle) ; + strcat(lDialogString, "\"") ; + + if ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + strcat(lDialogString, " --filename=\"") ; + strcat(lDialogString, aDefaultPathAndOrFile) ; + 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 --save --confirm-overwrite"); + if (aTitle && strlen(aTitle)) + { + strcat(lDialogString, " --title=\""); + strcat(lDialogString, aTitle); + strcat(lDialogString, "\""); + } + if (aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile)) + { + strcat(lDialogString, " --filename=\""); + strcat(lDialogString, aDefaultPathAndOrFile); + 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + getPathWithoutFinalSlash( lString , aDefaultPathAndOrFile ) ; + if ( strlen(lString) ) + { + strcat(lDialogString, "initialdir='") ; + strcat(lDialogString, lString ) ; + strcat(lDialogString , "'," ) ; + } + getLastName( lString , aDefaultPathAndOrFile ) ; + 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(res, tuple):\n\tprint(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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + getPathWithoutFinalSlash( lString , aDefaultPathAndOrFile ) ; + if ( strlen(lString) ) + { + strcat(lDialogString, "initialdir='") ; + strcat(lDialogString, lString ) ; + strcat(lDialogString , "'," ) ; + } + getLastName( lString , aDefaultPathAndOrFile ) ; + 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(res, tuple):\n\tprint 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + if ( ! strchr(aDefaultPathAndOrFile, '/') ) + { + strcat(lDialogString, "./") ; + } + strcat(lDialogString, aDefaultPathAndOrFile) ; + } + 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 ( strlen(lBuff) && 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 ; + } + strcpy(lLastDirectory, lString) ; + + 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 * aDefaultPathAndOrFile , /* NULL or "" , ends with / to set only a directory */ + int aNumOfFilterPatterns , /* 0 */ + char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */ + char const * aSingleFilterDescription , /* NULL or "image files" */ + int aAllowMultipleSelects ) /* 0 or 1 */ +{ + static char * lBuff = NULL; + static char lLastDirectory[MAX_PATH_OR_CMD] = "$PWD" ; + + char lDialogString[MAX_PATH_OR_CMD] ; + char lString[MAX_PATH_OR_CMD] ; + int i ; + FILE * lIn ; + char * p ; + char * lPointerInputBox ; + size_t lFullBuffLen ; + int lWasKdialog = 0 ; + int lWasGraphicDialog = 0 ; + int lWasXterm = 0 ; + + if ( ! aFilterPatterns ) aNumOfFilterPatterns = 0 ; + if (tfd_quoteDetected(aTitle)) return tinyfd_openFileDialog("INVALID TITLE WITH QUOTES", aDefaultPathAndOrFile, aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); + if (tfd_quoteDetected(aDefaultPathAndOrFile)) return tinyfd_openFileDialog(aTitle, "INVALID DEFAULT_PATH WITH QUOTES", aNumOfFilterPatterns, aFilterPatterns, aSingleFilterDescription, aAllowMultipleSelects); + if (tfd_quoteDetected(aSingleFilterDescription)) return tinyfd_openFileDialog(aTitle, aDefaultPathAndOrFile, 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: use the GRAVE ACCENT \\x60 instead.", aDefaultPathAndOrFile, 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 , aDefaultPathAndOrFile ) ; + 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + if ( aDefaultPathAndOrFile[0] != '/' ) + { + strcat(lDialogString, lLastDirectory) ; + strcat(lDialogString , "/" ) ; + } + strcat(lDialogString, "\"") ; + strcat(lDialogString, aDefaultPathAndOrFile ) ; + strcat(lDialogString , "\"" ) ; + } + else + { + strcat(lDialogString, lLastDirectory) ; + strcat(lDialogString , "/" ) ; + } + + 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" ) ; + } + + strcat(lDialogString, " --title=\"") ; + if (aTitle && strlen(aTitle)) strcat(lDialogString, aTitle) ; + strcat(lDialogString, "\"") ; + + if ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + strcat(lDialogString, " --filename=\"") ; + strcat(lDialogString, aDefaultPathAndOrFile) ; + 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"); + if (aAllowMultipleSelects) + { + strcat(lDialogString, " --multiple"); + } + if (aTitle && strlen(aTitle)) + { + strcat(lDialogString, " --title=\""); + strcat(lDialogString, aTitle); + strcat(lDialogString, "\""); + } + if (aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile)) + { + strcat(lDialogString, " --filename=\""); + strcat(lDialogString, aDefaultPathAndOrFile); + 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + getPathWithoutFinalSlash( lString , aDefaultPathAndOrFile ) ; + if ( strlen(lString) ) + { + strcat(lDialogString, "initialdir='") ; + strcat(lDialogString, lString ) ; + strcat(lDialogString , "'," ) ; + } + getLastName( lString , aDefaultPathAndOrFile ) ; + 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + getPathWithoutFinalSlash( lString , aDefaultPathAndOrFile ) ; + if ( strlen(lString) ) + { + strcat(lDialogString, "initialdir='") ; + strcat(lDialogString, lString ) ; + strcat(lDialogString , "'," ) ; + } + getLastName( lString , aDefaultPathAndOrFile ) ; + 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 ( aDefaultPathAndOrFile && strlen(aDefaultPathAndOrFile) ) + { + if ( ! strchr(aDefaultPathAndOrFile, '/') ) + { + strcat(lDialogString, "./") ; + } + strcat(lDialogString, aDefaultPathAndOrFile) ; + } + 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 ( strlen( lBuff ) && lBuff[strlen( lBuff ) -1] == '\n' ) + { + lBuff[strlen( lBuff ) -1] = '\0' ; + } + /* printf( "strlen lBuff: %d\n" , strlen( 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; + } + + p = strrchr(lBuff, '|'); + if ( !p ) p = lBuff ; + else p ++ ; + getPathWithoutFinalSlash( lString , p ) ; + /* printf( "lString [%lu]: %s\n" , strlen(lString) , lString ) ; */ + if ( strlen( lString ) && ! dirExists( lString ) ) + { + return NULL ; + } + strcpy(lLastDirectory, lString) ; + + lBuff = (char *)( realloc( lBuff, (strlen(lBuff)+1) * sizeof(char))); + + /*printf( "lBuff3 [%lu]: %s\n" , strlen(lBuff) , lBuff ) ; */ + return lBuff ; +} + + +char * tinyfd_selectFolderDialog( + char const * aTitle , /* "" */ + char const * aDefaultPath ) /* "" */ +{ + static char lBuff[MAX_PATH_OR_CMD] ; + static char lLastDirectory[MAX_PATH_OR_CMD] = "$PWD" ; + + 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, lLastDirectory) ; + strcat(lDialogString , "/" ) ; + } + strcat(lDialogString, "\"") ; + strcat(lDialogString, aDefaultPath ) ; + strcat(lDialogString , "\"" ) ; + } + else + { + strcat(lDialogString, lLastDirectory) ; + 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 --directory" ) ; + + strcat(lDialogString, " --title=\"") ; + if (aTitle && strlen(aTitle)) 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 --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, ");\nif not isinstance(res, tuple):\n\tprint(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 ( strlen( lBuff ) && lBuff[strlen( lBuff ) -1] == '\n' ) + { + lBuff[strlen( lBuff ) -1] = '\0' ; + } + /* printf( "lBuff: %s\n" , lBuff ) ; */ + if ( ! strlen( lBuff ) || ! dirExists( lBuff ) ) + { + return NULL ; + } + + getPathWithoutFinalSlash( lLastDirectory , lBuff ) ; + + return lBuff ; +} + + +/* aDefaultRGB is used only if aDefaultHexRGB is absent */ +/* aDefaultRGB and aoResultRGB can be the same array */ +/* returns NULL on cancel */ +/* returns the hexcolor as a string "#FF0000" */ +/* aoResultRGB also contains the result */ +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: use the GRAVE ACCENT \\x60 instead.", aDefaultRGB, aoResultRGB); + + if (aDefaultHexRGB && (strlen(aDefaultHexRGB)==7) ) + { + 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 ) ; + + strcat(lDialogString, " --title=\"") ; + if (aTitle && strlen(aTitle)) 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] = (unsigned char) strtol(lBuff+4, & lTmp2, 10 ); + aoResultRGB[1] = (unsigned char) strtol(lTmp2+1, & lTmp2, 10 ); + aoResultRGB[2] = (unsigned char) 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] = (unsigned char) strtol(lBuff+5, & lTmp2, 10 ); + aoResultRGB[1] = (unsigned char) strtol(lTmp2+1, & lTmp2, 10 ); + aoResultRGB[2] = (unsigned char) 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] = (unsigned char) strtol(lBuff, & lTmp2, 10 ); + aoResultRGB[1] = (unsigned char) strtol(lTmp2+1, & lTmp2, 10 ); + aoResultRGB[2] = (unsigned char) 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 */ + + +/* Modified prototypes for R */ + +void tfd_messageBox( + char const * aTitle , + char const * aMessage , + char const * aDialogType , + char const * aIconType , + int * aiDefaultButton ) +{ + * aiDefaultButton = tinyfd_messageBox( aTitle , aMessage , aDialogType , aIconType , * aiDefaultButton ) ; +} + + +void tfd_inputBox( + char const * aTitle , + char const * aMessage , + char * * aiDefaultInput ) +{ + char * lReturnedInput ; + if ( ! strcmp( * aiDefaultInput , "NULL") ) lReturnedInput = tinyfd_inputBox( aTitle , aMessage , NULL ) ; + else lReturnedInput = tinyfd_inputBox( aTitle , aMessage , * aiDefaultInput ) ; + + if ( lReturnedInput ) strcpy ( * aiDefaultInput , lReturnedInput ) ; + else strcpy ( * aiDefaultInput , "NULL" ) ; +} + + +void tfd_saveFileDialog( + char const * aTitle , + char * * aiDefaultPathAndFile , + int const * aNumOfFilterPatterns , + char const * const * aFilterPatterns , + char const * aSingleFilterDescription ) +{ + char * lSavefile ; + + /* printf( "aFilterPatterns %s\n" , aFilterPatterns [0]); */ + + lSavefile = tinyfd_saveFileDialog( aTitle , * aiDefaultPathAndFile , * aNumOfFilterPatterns , + aFilterPatterns, aSingleFilterDescription ) ; + if ( lSavefile ) strcpy ( * aiDefaultPathAndFile , lSavefile ) ; + else strcpy ( * aiDefaultPathAndFile , "NULL" ) ; +} + + +void tfd_openFileDialog( + char const * aTitle , + char * * aiDefaultPathAndFile , + int const * aNumOfFilterPatterns , + char const * const * aFilterPatterns , + char const * aSingleFilterDescription , + int const * aAllowMultipleSelects ) +{ + char * lOpenfile ; + + /* printf( "aFilterPatterns %s\n" , aFilterPatterns [0]); */ + + lOpenfile = tinyfd_openFileDialog( aTitle , * aiDefaultPathAndFile , * aNumOfFilterPatterns , + aFilterPatterns , aSingleFilterDescription , * aAllowMultipleSelects ) ; + + if ( lOpenfile ) strcpy ( * aiDefaultPathAndFile , lOpenfile ) ; + else strcpy ( * aiDefaultPathAndFile , "NULL" ) ; +} + + +void tfd_selectFolderDialog( + char const * aTitle , + char * * aiDefaultPath ) +{ + char * lSelectedfolder ; + lSelectedfolder = tinyfd_selectFolderDialog( aTitle, * aiDefaultPath ) ; + if ( lSelectedfolder ) strcpy ( * aiDefaultPath , lSelectedfolder ) ; + else strcpy ( * aiDefaultPath , "NULL" ) ; +} + + +void tfd_colorChooser( + char const * aTitle , + char * * aiDefaultHexRGB ) +{ + unsigned char const aDefaultRGB [ 3 ] = {128,128,128} ; + unsigned char aoResultRGB [ 3 ] = {128,128,128} ; + char * lChosenColor ; + lChosenColor = tinyfd_colorChooser( aTitle, * aiDefaultHexRGB, aDefaultRGB, aoResultRGB ) ; + if ( lChosenColor ) strcpy ( * aiDefaultHexRGB , lChosenColor ) ; + else strcpy ( * aiDefaultHexRGB , "NULL" ) ; +} + +/* end of Modified prototypes for R */ + + + +/* +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, "\ngraphic mode: "); +} +else +{ + strcat(lBuffer, "\nconsole 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\tfrom 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 diff --git a/external/tinyfiledialogs/tinyfiledialogs.h b/external/tinyfiledialogs/tinyfiledialogs.h new file mode 100644 index 0000000..c195d9b --- /dev/null +++ b/external/tinyfiledialogs/tinyfiledialogs.h @@ -0,0 +1,314 @@ +/* SPDX-License-Identifier: Zlib +Copyright (c) 2014 - 2024 Guillaume Vareille http://ysengrin.com + ____________________________________________________________________ + | | + | 100% compatible C C++ -> You can rename tinfiledialogs.c as .cpp | + |____________________________________________________________________| + +********* TINY FILE DIALOGS OFFICIAL WEBSITE IS ON SOURCEFORGE ********* + _________ + / \ tinyfiledialogs.h v3.18.2 [Jun 8, 2024] + |tiny file| Unique header file created [November 9, 2014] + | dialogs | + \____ ___/ http://tinyfiledialogs.sourceforge.net + \| git clone http://git.code.sf.net/p/tinyfiledialogs/code tinyfd + ____________________________________________ +| | +| email: tinyfiledialogs at ysengrin.com | +|____________________________________________| + ________________________________________________________________________________ +| ____________________________________________________________________________ | +| | | | +| | - in tinyfiledialogs, char is UTF-8 by default (since v3.6) | | +| | | | +| | on windows: | | +| | - for UTF-16, use the wchar_t functions at the bottom of the header file | | +| | | | +| | - _wfopen() requires wchar_t | | +| | - fopen() uses char but expects ASCII or 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. + + __________________________________________ + | ______________________________________ | + | | | | + | | DO NOT USE USER INPUT IN THE DIALOGS | | + | |______________________________________| | + |__________________________________________| +*/ + +#ifndef TINYFILEDIALOGS_H +#define TINYFILEDIALOGS_H + +#ifdef __cplusplus +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 and counter-intuitive. +On windows they are only ascii and still uses the unix backslash ! **/ +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. + if enabled, 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 yad matedialog + shellementary qarma python2-tkinter python3-tkinter python-dbus + perl-dbus gxmessage gmessage xmessage xdialog gdialog dunst +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 * aDefaultPathAndOrFile , /* NULL or "" , ends with / to set only a directory */ + 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 * aDefaultPathAndOrFile, /* NULL or "" , ends with / to set only a directory */ + 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 "" or "#FF0000" */ + unsigned char const aDefaultRGB[3] , /* unsigned char lDefaultRGB[3] = { 0 , 128 , 255 }; */ + unsigned char aoResultRGB[3] ) ; /* unsigned char lResultRGB[3]; */ + /* aDefaultRGB is used only if aDefaultHexRGB is absent */ + /* aDefaultRGB and aoResultRGB can be the same array */ + /* returns NULL on cancel */ + /* returns the hexcolor as a string "#FF0000" */ + /* aoResultRGB also contains the result */ + + +/************ 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 * aDefaultPathAndOrFile, /* NULL or L"" , ends with / to set only a directory */ + 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 * aDefaultPathAndOrFile, /* NULL or L"" , ends with / to set only a directory */ + 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 +*/ diff --git a/external/tinyfiledialogs/tinyfiledialogs.odin b/external/tinyfiledialogs/tinyfiledialogs.odin new file mode 100644 index 0000000..e6119ac --- /dev/null +++ b/external/tinyfiledialogs/tinyfiledialogs.odin @@ -0,0 +1,62 @@ +package tinyfiledialogs + +import "base:builtin" +import "core:c" + +when ODIN_OS == .Darwin { + foreign import lib "./macos-arm64/tinyfiledialogs.a" +} else when ODIN_OS == .Linux { + // TODO: this is completely untested. + foreign import lib "./linux/tinyfiledialogs.a" +} else when ODIN_OS == .Windows { + foreign import lib {"./windows/tinyfiledialogs.lib", "system:User32.lib", "system:Shell32.lib", "system:Comdlg32.lib", "system:Ole32.lib"} +} + + +@(default_calling_convention = "c") +@(link_prefix = "tinyfd_") +foreign lib { + // contains tinyfd current version number + version: [8]c.char + // info about requirements + needs: []c.char + // 0 (default) or 1 : on unix, prints the command line calls + verbose: c.int + // 1 (default) or 0 : on unix, hide errors and warnings from called dialogs + silent: c.int + // Curses dialogs are difficult to use and counter-intuitive. + // On windows they are only ascii and still uses the unix backslash ! + // 0 (default) or 1 + allowCursesDialogs: c.int + // 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. + // if enabled, it can use the package Dialog or dialog.exe. + // on windows it only make sense for console applications + // 0 (default) or 1 + forceConsole: c.int + // 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 + assumeGraphicDisplay: c.int + // 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 yad matedialog + // shellementary qarma python2-tkinter python3-tkinter python-dbus + // perl-dbus gxmessage gmessage xmessage xdialog gdialog dunst + // for console mode: + // dialog whiptail basicinput no_solution + response: [1024]c.char + + beep :: proc() --- + notifyPopup :: proc(aTitle: cstring, aMessage: cstring, aIconType: cstring) -> c.int --- + messageBox :: proc(aTitle: cstring, aMessage: cstring, aDialogType: cstring, aIconType: cstring, aDefaultButton: c.int) -> c.int --- + inputBox :: proc(aTitle: cstring, aMessage: cstring, aDefaultInput: cstring) -> cstring --- + saveFileDialog :: proc(aTitle: cstring, aDefaultPathAndOrFile: cstring, aNumOfFilterPatterns: c.int, aFilterPatterns: [^]cstring, aSingleFilterDescription: cstring) -> cstring --- + openFileDialog :: proc(aTitle: cstring, aDefaultPathAndOrFile: cstring, aNumOfFilterPatterns: c.int, aFilterPatterns: [^]cstring, aSingleFilterDescription: cstring, aAllowMultipleSelects: c.int) -> cstring --- + selectFolderDialog :: proc(aTitle: cstring, aDefaultPath: cstring) -> cstring --- + colorChooser :: proc(aTitle: cstring, aDefaultHexRGB: cstring, aDefaultRGB: [^]c.uchar, aoResultRGB: [^]c.uchar) -> cstring --- +} diff --git a/external/tinyfiledialogs/tinyfiledialogs_windows.odin b/external/tinyfiledialogs/tinyfiledialogs_windows.odin new file mode 100644 index 0000000..278ef0e --- /dev/null +++ b/external/tinyfiledialogs/tinyfiledialogs_windows.odin @@ -0,0 +1,28 @@ +package tinyfiledialogs + +import "base:builtin" +import "core:c" +import win32 "core:sys/windows" + +foreign import lib {"./windows/tinyfiledialogs.lib", "system:User32.lib", "system:Shell32.lib", "system:Comdlg32.lib", "system:Ole32.lib"} + +@(default_calling_convention = "c") +@(link_prefix = "tinyfd_") +foreign lib { + winUtf8: c.int + + utf8toMbcs :: proc(aUtf8string: cstring) -> cstring --- + utf16toMbcs :: proc(aUtf16string: [^]win32.wchar_t) -> cstring --- + mbcsTo16 :: proc(aMbcsString: cstring) -> [^]win32.wchar_t --- + mbcsTo8 :: proc(aMbcsString: cstring) -> cstring --- + utf8to16 :: proc(aUtf8string: cstring) -> [^]win32.wchar_t --- + utf16to8 :: proc(aUtf16string: [^]win32.wchar_t) -> cstring --- + // Windows only utf-16 versions + notifyPopupW :: proc(aTitle: [^]win32.wchar_t, aMessage: [^]win32.wchar_t, aIconType: [^]win32.wchar_t) -> c.int --- + messageBoxW :: proc(aTitle: [^]win32.wchar_t, aMessage: [^]win32.wchar_t, aDialogType: [^]win32.wchar_t, aIconType: [^]win32.wchar_t, aDefaultButton: c.int) -> c.int --- + inputBoxW :: proc(aTitle: [^]win32.wchar_t, aMessage: [^]win32.wchar_t, aDefaultInput: [^]win32.wchar_t) -> [^]win32.wchar_t --- + saveFileDialogW :: proc(aTitle: [^]win32.wchar_t, aDefaultPathAndOrFile: [^]win32.wchar_t, aNumOfFilterPatterns: c.int, aFilterPatterns: [^]win32.wstring, aSingleFilterDescription: [^]win32.wchar_t) -> [^]win32.wchar_t --- + openFileDialogW :: proc(aTitle: [^]win32.wchar_t, aDefaultPathAndOrFile: [^]win32.wchar_t, aNumOfFilterPatterns: c.int, aFilterPatterns: [^]win32.wstring, aSingleFilterDescription: [^]win32.wchar_t, aAllowMultipleSelects: c.int) -> [^]win32.wchar_t --- + selectFolderDialogW :: proc(aTitle: [^]win32.wchar_t, aDefaultPath: [^]win32.wchar_t) -> [^]win32.wchar_t --- + colorChooserW :: proc(aTitle: [^]win32.wchar_t, aDefaultHexRGB: [^]win32.wchar_t, aDefaultRGB: [^]c.uchar, aoResultRGB: [^]c.uchar) -> win32.wchar_t --- +} diff --git a/external/tinyfiledialogs/windows/tinyfiledialogs.lib b/external/tinyfiledialogs/windows/tinyfiledialogs.lib new file mode 100644 index 0000000000000000000000000000000000000000..e1284c0a99dd6f07bdac6ebfc2f5d37c4c7ac077 GIT binary patch literal 93536 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 literal 0 HcmV?d00001