1 /*************************************************************************
2 * Copyright (C) 2024 Francesco Palumbo <phranz.dev@gmail.com>, Naples (Italy)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 *************************************************************************/
26 #include "evaluator.h"
27 #include "sourcedriver.h"
28 #include "tokenizer.h"
34 #define AUTHOR "Francesco Palumbo <phranz.dev@gmail.com>"
35 #define LICENSE "GPL-3.0-or-later"
36 #define VERSION "2.6.11"
39 unsigned long options
;
48 // widgets never created or not
63 map_widwidget_t
* widgets
;
67 static int x11_initialized
;
69 if (x11_initialized
|| display
)
71 if (!getenv("DISPLAY"))
73 display
= XOpenDisplay(NULL
);
76 dfd
= ConnectionNumber(display
);
77 screen
= DefaultScreen(display
);
78 root
= DefaultRootWindow(display
);
80 delatom
= XInternAtom(display
, "WM_DELETE_WINDOW", False
);
81 colors
= alloc(map_strcol_t
);
84 colors
->insert(colors
, salloc("black"), calloc(1, sizeof(XColor
)));
85 colors
->insert(colors
, salloc("white"), calloc(1, sizeof(XColor
)));
86 colors
->insert(colors
, salloc("gray"), calloc(1, sizeof(XColor
)));
87 colors
->insert(colors
, salloc("lightgray"), calloc(1, sizeof(XColor
)));
88 colors
->insert(colors
, salloc("red"), calloc(1, sizeof(XColor
)));
89 colors
->insert(colors
, salloc("green"), calloc(1, sizeof(XColor
)));
90 colors
->insert(colors
, salloc("blue"), calloc(1, sizeof(XColor
)));
91 colors
->insert(colors
, salloc("yellow"), calloc(1, sizeof(XColor
)));
92 colors
->insert(colors
, salloc("cyan"), calloc(1, sizeof(XColor
)));
93 colors
->insert(colors
, salloc("magenta"), calloc(1, sizeof(XColor
)));
96 colors
->get(colors
, "black", &c
);
97 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "black", c
, &null
);
98 colors
->get(colors
, "white", &c
);
99 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "white", c
, &null
);
100 colors
->get(colors
, "gray", &c
);
101 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "gray", c
, &null
);
102 colors
->get(colors
, "lightgray", &c
);
103 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "lightgray", c
, &null
);
104 colors
->get(colors
, "red", &c
);
105 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "red", c
, &null
);
106 colors
->get(colors
, "green", &c
);
107 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "green", c
, &null
);
108 colors
->get(colors
, "blue", &c
);
109 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "blue", c
, &null
);
110 colors
->get(colors
, "yellow", &c
);
111 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "yellow", c
, &null
);
112 colors
->get(colors
, "cyan", &c
);
113 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "cyan", c
, &null
);
114 colors
->get(colors
, "magenta", &c
);
115 XAllocNamedColor(display
, DefaultColormap(display
, screen
), "magenta", c
, &null
);
117 widgets
= alloc(map_widwidget_t
);
118 exts
= alloc(map_pidwid_t
);
122 static void x11_clean() {
126 eachitem(colors
, strcol_t
, c
,
132 XFreeGC(display
, gc
);
134 XCloseDisplay(display
);
138 static int last_closed() {
139 if (!widgets
|| (!widgets
->count
&& !dirty
))
144 eachitem(widgets
, widwidget_t
, w
,
145 if (w
->val
->flags
& F_CLOSED
)
148 return closed
== widgets
->count
;
151 static void manage_exts() {
155 eachitem(exts
, pidwid_t
, p
,
156 if (kill(p
->key
, 0) < 0 && errno
== ESRCH
) {
160 exts
->remove(exts
, p
->key
);
163 if (waitpid(p
->key
, &stat
, WNOHANG
) > 0 && !stat
) {
167 exts
->remove(exts
, p
->key
);
173 void process_events() {
177 while (XPending(display
)) {
178 XNextEvent(display
, &e
);
179 if (widgets
->get(widgets
, e
.xany
.window
, &w
) && w
)
184 void poll_and_process_events(int us
) {
193 r
= select(dfd
+1, &ins
, NULL
, NULL
, &tv
);
198 static void showfonts() {
202 display
= XOpenDisplay(NULL
);
204 fprintf(stderr
, "Error, unable to open display!\n");
207 f
= XListFonts(display
, "*", 2000, &r
);
208 for (size_t i
=0; i
<(size_t)r
; ++i
)
209 printf("%s\n", f
[i
]);
211 XCloseDisplay(display
);
219 extern map_sigtoken_t actions
;
220 extern map_int_timetoken_t
* schedules
;
221 extern map_int_timetoken_t
* onetimes
;
223 extern sig_atomic_t sq
;
224 extern unsigned long flags
;
225 extern sourcedata_t
* current
;
227 static void help(int fd
, char** argv
) {
229 "Usage: %s [-c <code>][-s][-q][-k][-t][-f][-v][-b][-h][<file>][<arguments>]\n"
231 " -c <code> read and execute commands from command line.\n"
232 " -s display elements when created.\n"
233 " -q quit when closing last element/window.\n"
234 " -k terminate all external programs when quitting.\n"
235 " -t fallback on tty after reading data from other inputs.\n"
236 " -f show available X11 fonts.\n"
237 " -v show version.\n"
238 " -b show build (compiled in) options.\n"
242 argv
[0], AUTHOR
, LICENSE
);
245 static void build_info() {
246 printf("%s" "\n%s" "\n%s" "\n%s\n",
248 "X11 support (Xlib): yes"
250 "X11 support (Xlib): no"
253 #ifdef ENABLE_CONTROL
254 "Control support (Xtst): yes"
256 "Control support (Xtst): no"
260 "Images support (Imlib2): yes"
262 "Images support (Imlib2): no"
266 "Debug activated: yes"
268 "Debug activated: no"
273 static void interpret(vec_token_t
* args
) {
275 vec_token_t
* objs
= NULL
;
276 while (!(flags
& EV_QUITCALLED
) && !sq
) {
280 objs
= parse_phrase(p
, cs
);
284 while (!sq
&& objs
&& eval_expressions(objs
, args
) && !sq
&& eval_statements(objs
, args
) &&
285 !(flags
& EV_QUITCALLED
) && !sq
&& exec(objs
));
286 release_phrase(objs
);
289 release_phrase(objs
);
292 int loop(int s
, char* data
, vec_token_t
* args
) {
293 debug("initial source %d\n", s
);
295 new_source(S_STDIN
, NULL
);
301 while (!sq
&& !(flags
& EV_QUITCALLED
) && !(options
& QUIT_ON_LAST_CLOSED
&& last_closed())) {
304 if (!valid_source()) {
305 if ((!widgets
|| !widgets
->count
) &&
306 (!onetimes
|| !onetimes
->count
) &&
307 (!schedules
|| !schedules
->count
))
309 poll_and_process_events(100000);
314 if (sq
|| flags
& EV_QUITCALLED
)
316 if (source_exahusted())
319 if (current
&& current
->nb
)
320 poll_and_process_events(100000);
326 while (!sq
&& !(flags
& EV_QUITCALLED
) && valid_source()) {
329 if (sq
|| flags
& EV_QUITCALLED
)
331 if (source_exahusted())
333 if (!current
|| current
->nb
)
338 trigger(0, SIG_TERM
);
340 trigger(0, SIG_EXIT
);
344 int main(int argc
, char **argv
) {
346 int initial_source
= S_NOSRC
;
347 char* source_data
= NULL
;
349 while ((opt
= getopt(argc
, argv
, "c:sqktfvbh")) > 0) {
352 initial_source
= S_CMDLINE
;
353 source_data
= salloc(optarg
);
356 options
|= SHOW_ON_CREATE
;
359 options
|= QUIT_ON_LAST_CLOSED
;
362 options
|= KILL_EXTS_ON_QUIT
;
365 options
|= FALLBACK_ON_TTY
;
371 printf("%s\n", VERSION
);
384 debug("optind: %d argc: %d\n", optind
, argc
);
385 if (optind
< argc
&& !source_data
) {
386 initial_source
= S_SOURCE
;
387 source_data
= salloc(argv
[optind
++]);
392 vec_token_t
* args
= NULL
;
393 while (optind
< argc
) {
395 args
= alloc(vec_token_t
);
396 token_t
* arg
= alloc(token_t
);
398 arg
->data
= salloc(argv
[optind
++]);
399 args
->push(args
, arg
);
401 int ret
= loop(initial_source
, source_data
, args
);
402 release_phrase(args
);