1 /* Terminal interface - low-level displaying implementation. */
16 #include "bookmarks/bookmarks.h"
17 #include "config/options.h"
18 #include "intl/gettext/libintl.h"
19 #include "main/main.h"
20 #include "main/object.h"
21 #include "main/select.h"
22 #include "osdep/osdep.h"
23 #include "osdep/signals.h"
24 #include "session/session.h"
25 #include "terminal/draw.h"
26 #include "terminal/event.h"
27 #include "terminal/hardio.h"
28 #include "terminal/kbd.h"
29 #include "terminal/screen.h"
30 #include "terminal/terminal.h"
31 #include "terminal/window.h"
32 #include "util/error.h"
33 #include "util/memory.h"
34 #include "util/string.h"
35 #include "viewer/text/textarea.h"
38 INIT_LIST_HEAD(terminals
);
41 static void check_if_no_terminal(void);
45 redraw_terminal(struct terminal
*term
)
49 set_redraw_term_event(&ev
, term
->width
, term
->height
);
50 term_send_event(term
, &ev
);
54 redraw_terminal_cls(struct terminal
*term
)
58 set_resize_term_event(&ev
, term
->width
, term
->height
);
59 term_send_event(term
, &ev
);
63 cls_redraw_all_terminals(void)
65 struct terminal
*term
;
67 foreach (term
, terminals
)
68 redraw_terminal_cls(term
);
72 init_term(int fdin
, int fdout
)
74 struct terminal
*term
= mem_calloc(1, sizeof(*term
));
77 check_if_no_terminal();
81 term
->screen
= init_screen();
87 init_list(term
->windows
);
91 term
->master
= (term
->fdout
== get_output_handle());
93 term
->spec
= get_opt_rec(config_options
, "terminal._template_");
94 object_lock(term
->spec
);
96 add_to_list(terminals
, term
);
98 set_handlers(fdin
, (select_handler_T
) in_term
, NULL
,
99 (select_handler_T
) destroy_terminal
, term
);
104 redraw_all_terminals(void)
106 struct terminal
*term
;
108 foreach (term
, terminals
)
113 destroy_terminal(struct terminal
*term
)
115 #ifdef CONFIG_BOOKMARKS
116 bookmark_auto_save_tabs(term
);
119 while (!list_empty(term
->windows
))
120 delete_window(term
->windows
.next
);
122 /* mem_free_if(term->cwd); */
123 mem_free_if(term
->title
);
124 if (term
->screen
) done_screen(term
->screen
);
126 clear_handlers(term
->fdin
);
127 mem_free_if(term
->interlink
);
129 if (term
->blocked
!= -1) {
130 close(term
->blocked
);
131 clear_handlers(term
->blocked
);
137 if (term
->fdout
!= 1) {
138 if (term
->fdout
!= term
->fdin
) close(term
->fdout
);
140 unhandle_terminal_signals(term
);
142 #ifndef NO_FORK_ON_EXIT
143 if (!list_empty(terminals
)) {
149 object_unlock(term
->spec
);
151 check_if_no_terminal();
155 destroy_all_terminals(void)
157 while (!list_empty(terminals
))
158 destroy_terminal(terminals
.next
);
162 check_if_no_terminal(void)
164 program
.terminate
= list_empty(terminals
)
165 && !get_opt_bool("ui.sessions.keep_session_active");
169 exec_thread(unsigned char *path
, int p
)
171 int plen
= strlen(path
+ 1) + 2;
173 #if defined(HAVE_SETPGID) && !defined(CONFIG_BEOS) && !defined(HAVE_BEGINTHREAD)
174 if (path
[0] == 2) setpgid(0, 0);
177 if (path
[plen
]) unlink(path
+ plen
);
181 close_handle(void *h
)
184 clear_handlers((long) h
);
188 unblock_terminal(struct terminal
*term
)
190 close_handle((void *) (long) term
->blocked
);
192 set_handlers(term
->fdin
, (select_handler_T
) in_term
, NULL
,
193 (select_handler_T
) destroy_terminal
, term
);
194 unblock_itrm(term
->fdin
);
195 redraw_terminal_cls(term
);
196 if (textarea_editor
) /* XXX */
197 textarea_edit(1, NULL
, NULL
, NULL
, NULL
);
201 exec_on_terminal(struct terminal
*term
, unsigned char *path
,
202 unsigned char *delete, int fg
)
205 int dlen
= strlen(delete);
207 if (path
&& !*path
) return;
219 if (!*path
) dispatch_special(delete);
222 unsigned char *param
;
225 if (is_blocked() && fg
) {
230 param_size
= plen
+ dlen
+ 2 /* 2 null char */ + 1 /* fg */;
231 param
= mem_alloc(param_size
);
235 memcpy(param
+ 1, path
, plen
+ 1);
236 memcpy(param
+ 1 + plen
+ 1, delete, dlen
+ 1);
238 if (fg
== 1) block_itrm(term
->fdin
);
240 blockh
= start_thread((void (*)(void *, int)) exec_thread
,
243 if (fg
== 1) unblock_itrm(term
->fdin
);
250 term
->blocked
= blockh
;
252 (select_handler_T
) unblock_terminal
,
254 (select_handler_T
) unblock_terminal
,
256 set_handlers(term
->fdin
, NULL
, NULL
,
257 (select_handler_T
) destroy_terminal
,
259 /* block_itrm(term->fdin); */
261 set_handlers(blockh
, close_handle
, NULL
,
262 close_handle
, (void *) (long) blockh
);
266 int data_size
= plen
+ dlen
+ 1 /* 0 */ + 1 /* fg */ + 2 /* 2 null char */;
267 unsigned char *data
= mem_alloc(data_size
);
272 memcpy(data
+ 2, path
, plen
+ 1);
273 memcpy(data
+ 2 + plen
+ 1, delete, dlen
+ 1);
274 hard_write(term
->fdout
, data
, data_size
);
279 hard_write(term
->fdout
, &x
, 1);
281 hard_write(term
->fdout
, &x
, 1);
282 hard_write(term
->fdout
, path
, strlen(path
) + 1);
283 hard_write(term
->fdout
, delete, strlen(delete) + 1);
289 exec_shell(struct terminal
*term
)
293 if (!can_open_os_shell(term
->environment
)) return;
297 exec_on_terminal(term
, sh
, "", 1);
302 do_terminal_function(struct terminal
*term
, unsigned char code
,
305 int data_len
= strlen(data
);
306 unsigned char *x_data
= fmem_alloc(data_len
+ 1 /* code */ + 1 /* null char */);
310 memcpy(x_data
+ 1, data
, data_len
+ 1);
311 exec_on_terminal(term
, NULL
, x_data
, 0);
316 set_terminal_title(struct terminal
*term
, unsigned char *title
)
318 if (term
->title
&& !strcmp(title
, term
->title
)) return;
319 mem_free_set(&term
->title
, stracpy(title
));
320 do_terminal_function(term
, TERM_FN_TITLE
, title
);
323 static int terminal_pipe
[2];
326 check_terminal_pipes(void)
328 return c_pipe(terminal_pipe
);
332 close_terminal_pipes(void)
334 close(terminal_pipe
[0]);
335 close(terminal_pipe
[1]);
339 attach_terminal(int in
, int out
, int ctl
, void *info
, int len
)
341 struct terminal
*term
;
343 if (set_nonblocking_fd(terminal_pipe
[0]) < 0) return NULL
;
344 if (set_nonblocking_fd(terminal_pipe
[1]) < 0) return NULL
;
345 handle_trm(in
, out
, out
, terminal_pipe
[1], ctl
, info
, len
, 0);
347 term
= init_term(terminal_pipe
[0], out
);
349 close_terminal_pipes();