Correct Makefile
[clav.git] / file-selection.c
blob67a386263fb15bccd7ed408cb01ed6450c4aced6
1 /*
2 * Copyright (c) 2016, S. Gilles <sgilles@math.umd.edu>
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
7 * in all copies.
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.
18 #include <errno.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
25 #include "macros.h"
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[] = {
39 /* */
40 [ACT_SAVE] = "kdialog --getsavefilename :clav 2>/dev/null", /* */
41 [ACT_LOAD] = "kdialog --getopenfilename :clav 2>/dev/null", /* */
43 static char *cmd_qarma[] = {
44 /* */
45 [ACT_SAVE] = "qarma --title 'Save As' --file-selection --save 2>/dev/null", /* */
46 [ACT_LOAD] = "qarma --title 'Load' --file-selection 2>/dev/null", /* */
48 static char *cmd_yad[] = {
49 /* */
50 [ACT_SAVE] =
51 "yad --title 'Save As' --width=640 --height=480 --file-selection --save 2>/dev/null", /* */
52 [ACT_LOAD] =
53 "yad --title 'Load' --width=640 --height=480 --file-selection 2>/dev/null", /* */
55 static char *cmd_zenity[] = {
56 /* */
57 [ACT_SAVE] = "zenity --title 'Save As' --file-selection --save 2>/dev/null", /* */
58 [ACT_LOAD] = "zenity --title 'Load' --file-selection 2>/dev/null", /* */
60 static char *cmd_xdialog[] = {
61 /* */
62 [ACT_SAVE] =
63 "Xdialog --stdout --title 'Save As' --fselect '' 0 0 2>/dev/null", /* */
64 [ACT_LOAD] =
65 "Xdialog --stdout --title 'Load' --fselect '' 0 0 2>/dev/null", /* */
68 /* Naively slurp stream in completly, truncate last `\n'. */
69 static int slurp(FILE *f, char **out)
71 static size_t read_size = 1 << 7;
72 int ret = 0;
73 int pret = 0;
74 size_t len = 0;
75 size_t sz = read_size - 1;
76 char *buf = 0;
78 if (!(buf = malloc(sz + 1))) {
79 ret = errno;
80 perror(L("malloc"));
81 goto done;
84 char *p = buf;
86 *p = '\0';
88 do {
89 if (!fgets(buf + len, read_size, f)) {
90 break;
93 p = strchr(buf + len, '\0');
94 len = p - buf;
95 sz += read_size;
96 void *newmem = 0;
98 if (!(newmem = realloc(buf, sz + 1))) {
99 ret = errno;
100 perror(L("realloc"));
101 goto done;
104 buf = newmem;
105 } while (1);
107 if ((p = strrchr(buf + len - 1, '\n'))) {
108 *p = '\0';
111 ret = 0;
112 done:
113 pret = pclose(f);
115 if (!ret &&
116 WIFEXITED(pret) &&
117 WEXITSTATUS(pret) != 127) {
118 *out = buf;
119 } else {
120 ret = 1;
121 free(buf);
122 buf = 0;
123 *out = 0;
126 return ret;
129 static int choose_file(char **out_filename, enum action act)
131 int ret = ENOPKG;
132 char *filename = 0;
133 FILE *f = 0;
135 fflush(0);
137 if (try_kdialog) {
138 if ((f = popen(cmd_kdialog[act], "r"))) {
139 if (!(ret = slurp(f, &filename))) {
140 goto done;
144 free(filename);
145 filename = 0;
146 try_kdialog = 0;
149 if (try_qarma) {
150 if ((f = popen(cmd_qarma[act], "r"))) {
151 if (!(ret = slurp(f, &filename))) {
152 goto done;
156 free(filename);
157 filename = 0;
158 try_qarma = 0;
161 if (try_yad) {
162 if ((f = popen(cmd_yad[act], "r"))) {
163 if (!(ret = slurp(f, &filename))) {
164 goto done;
168 free(filename);
169 filename = 0;
170 try_yad = 0;
173 if (try_zenity) {
174 if ((f = popen(cmd_zenity[act], "r"))) {
175 if (!(ret = slurp(f, &filename))) {
176 goto done;
180 free(filename);
181 filename = 0;
182 try_zenity = 0;
185 if (try_xdialog) {
186 if ((f = popen(cmd_xdialog[act], "r"))) {
187 if (!(ret = slurp(f, &filename))) {
188 goto done;
192 free(filename);
193 filename = 0;
194 try_xdialog = 0;
197 ret = ENOPKG;
198 done:
200 if (!ret) {
201 *out_filename = filename;
202 } else {
203 free(filename);
206 return ret;
209 int choose_save_file(char **out_filename)
211 return choose_file(out_filename, ACT_SAVE);
214 int choose_load_file(char **out_filename)
216 return choose_file(out_filename, ACT_LOAD);