2 * Copyright (c) 2016-2019, 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
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 static char *cmd_kdialog
= "kdialog --getcolor 2>/dev/null";
38 static char *cmd_qarma
= "qarma --color-selection 2>/dev/null";
39 static char *cmd_yad
= "yad --color 2>/dev/null";
40 static char *cmd_zenity
= "zenity --color-selection 2>/dev/null";
41 static char *cmd_xdialog
= "Xdialog --stdout --colorsel '' 0 0 2>/dev/null";
43 /* Convert result of fgetc into [0,16), with special case for EOF */
45 atoh(int c
, uint_fast8_t *early_eof
)
49 } else if ('0' <= c
&&
52 } else if ('a' <= c
&&
55 } else if ('A' <= c
&&
63 /* Read in #rrggbb, returned by most of these programs */
65 read_hex(FILE *f
, uint32_t *out_argb
, uint_fast8_t *out_affirmed
)
70 uint_fast8_t early_eof
= 0;
74 /* ignore leading '#', if there are any */
87 argb
|= atoh(c
, &early_eof
) << 20;
88 argb
|= atoh(fgetc(f
), &early_eof
) << 16;
91 argb
|= atoh(fgetc(f
), &early_eof
) << 12;
92 argb
|= atoh(fgetc(f
), &early_eof
) << 8;
95 argb
|= atoh(fgetc(f
), &early_eof
) << 4;
96 argb
|= atoh(fgetc(f
), &early_eof
) << 0;
99 /* Sometimes, zenity returns #rrrrggggbbbb */
104 if (fgetc(f
) == EOF
) {
108 if (fgetc(f
) == EOF
) {
112 /* We are certainly in #rrrrggggbbbb */
113 argb
= (argb
& 0xff0000) | ((argb
& 0xff) << 8);
114 argb
|= atoh(fgetc(f
), &early_eof
) << 4;
115 argb
|= atoh(fgetc(f
), &early_eof
) << 0;
121 WEXITSTATUS(pret
) != 127) {
123 *out_affirmed
= !early_eof
;
133 /* Read in rrr ggg bbb, returned by xdialog */
135 read_spaced(FILE *f
, uint32_t *out_argb
, uint_fast8_t *out_affirmed
)
161 } else if ('0' <= c
&&
163 r
= 10 * r
+ (c
- '0');
183 } else if ('0' <= c
&&
185 g
= 10 * g
+ (c
- '0');
207 } else if ('0' <= c
&&
209 b
= 10 * b
+ (c
- '0');
220 WEXITSTATUS(pret
) != 127) {
221 *out_argb
= (r
<< 16) | (g
<< 8) | (b
<< 0);
230 /* read in EITHER rgb(rrr,ggg,bbb) or #rrggbb */
232 read_zenity(FILE *f
, uint32_t *out_argb
, uint_fast8_t *out_affirmed
)
237 /* Probably zenity's rgb(rrr,ggg,bbb,aaa) thing */
242 return read_spaced(f
, out_argb
, out_affirmed
);
243 } else if (c
== '#') {
244 return read_hex(f
, out_argb
, out_affirmed
);
247 /* This also covers the EOF case */
254 choose_color(uint32_t *out_color
, uint_fast8_t *out_affirmed
)
257 uint_fast8_t affirmed
= 0;
264 if ((f
= popen(cmd_kdialog
, "r"))) {
265 if (!(ret
= read_hex(f
, &argb
, &affirmed
))) {
274 if ((f
= popen(cmd_qarma
, "r"))) {
275 if (!(ret
= read_hex(f
, &argb
, &affirmed
))) {
284 if ((f
= popen(cmd_yad
, "r"))) {
285 if (!(ret
= read_hex(f
, &argb
, &affirmed
))) {
294 if ((f
= popen(cmd_zenity
, "r"))) {
295 if (!(ret
= read_zenity(f
, &argb
, &affirmed
))) {
304 if ((f
= popen(cmd_xdialog
, "r"))) {
305 if (!(ret
= read_spaced(f
, &argb
, &affirmed
))) {
318 *out_affirmed
= affirmed
;