2 * Copyright (c) 2016-2021, S. Gilles <sgilles@sgilles.net>
4 * Permission to use, copy, modify, and/or distribute this software
5 * for any purpose with or without fee is hereby granted, provided
6 * that the above copyright notice and this permission notice appear
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
13 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 * I am fully aware of how ugly this file is, which is why it's specially
29 * split out, so that it can be completely redone one day, when some
30 * kind of better solution exists.
32 static uint_fast8_t try_kdialog
= 1;
33 static uint_fast8_t try_qarma
= 1;
34 static uint_fast8_t try_yad
= 1;
35 static uint_fast8_t try_zenity
= 1;
36 static uint_fast8_t try_xdialog
= 1;
37 enum action
{ ACT_SAVE
, ACT_LOAD
};
38 static char *cmd_kdialog
[] = {
40 [ACT_SAVE
] = "kdialog --getsavefilename :clav 2>/dev/null", /* */
41 [ACT_LOAD
] = "kdialog --getopenfilename :clav 2>/dev/null", /* */
43 static char *cmd_qarma
[] = {
46 "qarma --title 'Save As' --file-selection --save 2>/dev/null", /* */
47 [ACT_LOAD
] = "qarma --title 'Load' --file-selection 2>/dev/null", /* */
49 static char *cmd_yad
[] = {
52 "yad --title 'Save As' --width=640 --height=480 --file-selection --save 2>/dev/null", /* */
54 "yad --title 'Load' --width=640 --height=480 --file-selection 2>/dev/null", /* */
56 static char *cmd_zenity
[] = {
59 "zenity --title 'Save As' --file-selection --save 2>/dev/null", /* */
60 [ACT_LOAD
] = "zenity --title 'Load' --file-selection 2>/dev/null", /* */
62 static char *cmd_xdialog
[] = {
65 "Xdialog --stdout --title 'Save As' --fselect '' 0 0 2>/dev/null", /* */
67 "Xdialog --stdout --title 'Load' --fselect '' 0 0 2>/dev/null", /* */
70 /* Naively slurp stream in completly, truncate last `\n'. */
72 slurp(FILE *f
, char **out
)
74 static size_t read_size
= 1 << 7;
78 size_t sz
= read_size
- 1;
81 /* No need to check for overflow; sz + 1 == 1 << 7 */
82 if (!(buf
= malloc(sz
+ 1))) {
93 if (!fgets(buf
+ len
, read_size
, f
)) {
97 p
= strchr(buf
+ len
, '\0');
103 ret
= errno
= EOVERFLOW
;
108 if (!(newmem
= realloc(buf
, sz
+ 1))) {
110 perror(L("realloc"));
118 if ((p
= strrchr(buf
+ len
- 1, '\n'))) {
129 WEXITSTATUS(pret
) != 127) {
142 choose_file(char **out_filename
, enum action act
)
151 if ((f
= popen(cmd_kdialog
[act
], "r"))) {
152 if (!(ret
= slurp(f
, &filename
))) {
163 if ((f
= popen(cmd_qarma
[act
], "r"))) {
164 if (!(ret
= slurp(f
, &filename
))) {
175 if ((f
= popen(cmd_yad
[act
], "r"))) {
176 if (!(ret
= slurp(f
, &filename
))) {
187 if ((f
= popen(cmd_zenity
[act
], "r"))) {
188 if (!(ret
= slurp(f
, &filename
))) {
199 if ((f
= popen(cmd_xdialog
[act
], "r"))) {
200 if (!(ret
= slurp(f
, &filename
))) {
214 *out_filename
= filename
;
223 choose_save_file(char **out_filename
)
225 return choose_file(out_filename
, ACT_SAVE
);
229 choose_load_file(char **out_filename
)
231 return choose_file(out_filename
, ACT_LOAD
);