rewrite: update default dumb and smart prefixes
[elinks/elinks-j605.git] / src / terminal / window.c
blobf7b1452d31bd59bf584ebf47a1cc7bd4df83aef6
1 /** Terminal windows stuff.
2 * @file */
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
8 #include "elinks.h"
10 #include "bfu/dialog.h"
11 #include "bfu/menu.h"
12 #include "terminal/event.h"
13 #include "terminal/tab.h"
14 #include "terminal/terminal.h"
15 #include "terminal/window.h"
16 #include "util/error.h"
17 #include "util/memory.h"
20 void
21 redraw_windows(enum windows_to_redraw which, struct window *win)
23 struct terminal *term = win->term;
24 struct term_event ev;
25 struct window *end;
26 enum term_redrawing_state saved_redraw_state = term->redrawing;
28 switch (which) {
29 case REDRAW_IN_FRONT_OF_WINDOW:
30 win = win->prev;
31 /* fall through */
32 case REDRAW_WINDOW_AND_FRONT:
33 end = (struct window *) &term->windows;
34 if (term->redrawing != TREDRAW_READY) return;
35 term->redrawing = TREDRAW_BUSY;
36 break;
37 case REDRAW_BEHIND_WINDOW:
38 end = win;
39 win = (struct window *) term->windows.prev;
40 if (term->redrawing == TREDRAW_DELAYED) return;
41 term->redrawing = TREDRAW_DELAYED;
42 break;
43 default:
44 ERROR("invalid enum windows_to_redraw: which==%d", (int) which);
45 return;
48 set_redraw_term_event(&ev, term->width, term->height);
49 for (; win != end; win = win->prev) {
50 if (!inactive_tab(win))
51 win->handler(win, &ev);
53 term->redrawing = saved_redraw_state;
56 void
57 add_window(struct terminal *term, window_handler_T handler, void *data)
59 struct term_event ev;
60 struct window *win = mem_calloc(1, sizeof(*win));
62 if (!win) {
63 mem_free_if(data);
64 return;
67 win->handler = handler;
68 win->data = data; /* freed later in delete_window() */
69 win->term = term;
70 win->type = WINDOW_NORMAL;
71 add_at_pos((struct window *) &term->windows, win);
72 set_init_term_event(&ev, term->width, term->height);
73 win->handler(win, &ev);
76 void
77 delete_window(struct window *win)
79 struct term_event ev;
81 /* Updating the status when destroying tabs needs this before the win
82 * handler call. */
83 del_from_list(win);
84 set_abort_term_event(&ev);
85 win->handler(win, &ev);
86 mem_free_if(win->data);
87 redraw_terminal(win->term);
88 mem_free(win);
91 void
92 delete_window_ev(struct window *win, struct term_event *ev)
94 struct window *w;
96 w = list_has_next(win->term->windows, win) ? win->next : NULL;
98 delete_window(win);
100 if (!ev || !w) return;
102 /* If next is a tab send it to the current tab */
103 if (w->type == WINDOW_TAB) {
104 w = get_current_tab(w->term);
107 if (w) w->handler(w, ev);
110 void
111 get_parent_ptr(struct window *win, int *x, int *y)
113 struct window *parent = win->next;
115 if (parent->type == WINDOW_TAB)
116 parent = get_tab_by_number(win->term, win->term->current_tab);
118 if (parent) {
119 *x = parent->x;
120 *y = parent->y;
121 } else {
122 *x = 0;
123 *y = 0;
128 struct ewd {
129 void (*fn)(void *);
130 void *data;
131 unsigned int called_once:1;
134 static void
135 empty_window_handler(struct window *win, struct term_event *ev)
137 struct terminal *term = win->term;
138 struct ewd *ewd = win->data;
139 void (*fn)(void *) = ewd->fn;
140 void *data = ewd->data;
142 if (ewd->called_once) return;
144 switch (ev->ev) {
145 case EVENT_INIT:
146 case EVENT_RESIZE:
147 case EVENT_REDRAW:
148 get_parent_ptr(win, &win->x, &win->y);
149 return;
150 case EVENT_ABORT:
151 fn(data);
152 return;
153 case EVENT_KBD:
154 case EVENT_MOUSE:
155 /* Silence compiler warnings */
156 break;
159 ewd->called_once = 1;
160 delete_window(win);
161 fn(data);
162 term_send_event(term, ev);
165 void
166 add_empty_window(struct terminal *term, void (*fn)(void *), void *data)
168 struct ewd *ewd = mem_alloc(sizeof(*ewd));
170 if (!ewd) return;
171 ewd->fn = fn;
172 ewd->data = data;
173 ewd->called_once = 0;
174 add_window(term, empty_window_handler, ewd);
177 #if CONFIG_DEBUG
178 /** Check that terminal.windows are in the documented order. */
179 void
180 assert_window_stacking(struct terminal *term)
182 enum { WANT_ANY, WANT_TAB, WANT_NONE } want = WANT_ANY;
183 const struct window *win;
184 const struct window *main_menu_win;
186 /* The main menu can be either above or below the tabs. */
187 main_menu_win = term->main_menu ? term->main_menu->win : NULL;
189 foreach (win, term->windows) {
190 switch (want) {
191 case WANT_ANY:
192 if (win->type == WINDOW_TAB)
193 want = WANT_TAB;
194 break;
195 case WANT_TAB:
196 if (win == main_menu_win)
197 want = WANT_NONE;
198 else
199 assert(win->type == WINDOW_TAB);
200 break;
201 case WANT_NONE:
202 assert(0);
203 break;
207 #endif /* CONFIG_DEBUG */
209 void
210 set_dlg_window_ptr(struct dialog_data *dlg_data, struct window *window, int x, int y)
212 struct box *box = &dlg_data->real_box;
214 if (box->height) {
215 int y_max = box->y + box->height;
217 y -= dlg_data->y;
218 if (y < box->y || y >= y_max) return;
220 set_window_ptr(window, x, y);
223 #if CONFIG_SCRIPTING_SPIDERMONKEY
224 /** Check whether keypress events would be directed to @a win. */
226 would_window_receive_keypresses(const struct window *win)
228 struct terminal *const term = win->term;
229 const struct window *selected;
231 /* At least @win must be in the list. */
232 assert(!list_empty(term->windows));
233 if_assert_failed return 0;
235 selected = term->windows.next;
236 if (selected->type != WINDOW_TAB) return 0;
238 selected = get_current_tab(term);
239 if (selected != win) return 0;
241 return 1;
243 #endif /* CONFIG_SCRIPTING_SPIDERMONKEY */