1 /* rxvt.c - terminal emulator widget top-level functions
2    Copyright (C) 1996-2017 Paul Sheer
3 
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 2 of the License, or
7    (at your option) any later version.
8 
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.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307, USA.
18  */
19 
20 #include "rxvt/rxvtlib.h"
21 #include "mad.h"
22 #include "coolwidget.h"
23 #include "font.h"
24 
25 struct rxvts {
26     rxvtlib *rxvt;
27     struct rxvts *next;
28     int killed;
29 } *rxvt_list = 0;
30 
31 extern void rxvt_fd_write_watch (int fd, fd_set * reading, fd_set * writing, fd_set * error,
32 				 void *data);
33 extern void rxvt_fd_read_watch (int fd, fd_set * reading, fd_set * writing, fd_set * error,
34 				void *data);
35 
rxvt_event(XEvent * xevent)36 int rxvt_event (XEvent * xevent)
37 {
38     Window win;
39     struct rxvts *l, *prev = 0;
40     if (!rxvt_list)
41 	return 0;
42     win = xevent->xany.window;
43     for (l = rxvt_list->next, prev = rxvt_list; l; l = l->next) {
44 	l->killed |= CChildExitted (l->rxvt->cmd_pid, 0);
45 	if (l->killed || l->rxvt->killed) {
46 	    struct rxvts *next;
47 	    next = l->next;
48 	    CRemoveWatch (l->rxvt->cmd_fd, rxvt_fd_read_watch, 1);
49 	    CRemoveWatch (l->rxvt->cmd_fd, rxvt_fd_write_watch, 2);
50 	    close (l->rxvt->cmd_fd);
51 	    if (l->killed) {
52 		XDestroyWindow (l->rxvt->Xdisplay,
53 				l->rxvt->TermWin.parent[0]);
54 		XDestroyWindow (l->rxvt->Xdisplay, l->rxvt->TermWin.vt);
55 		XDestroyWindow (l->rxvt->Xdisplay, l->rxvt->scrollBar.win);
56 	    }
57 	    prev->next = next;
58 	    rxvtlib_shut (l->rxvt);
59 	    free (l->rxvt);
60 	    memset (l, 0, sizeof (*l));
61 	    free (l);
62 	    l = prev;
63 	} else if (win && (l->rxvt->TermWin.parent[0] == win
64 			   || l->rxvt->TermWin.parent[1] == win
65 			   || l->rxvt->TermWin.parent[2] == win
66 			   || l->rxvt->TermWin.parent[3] == win
67 			   || l->rxvt->TermWin.parent[4] == win
68 			   || l->rxvt->scrollBar.win == win
69 			   || l->rxvt->menuBar.win == win)) {
70 	    l->rxvt->x_events_pending = 1;
71 	    memcpy (&l->rxvt->xevent, xevent, sizeof (*xevent));
72 	    l->rxvt->fds_available++;
73 	    if (XFilterEvent(xevent, 0)) {
74 		xevent->type = 0;
75 		xevent->xany.window = 0;
76 		return 1;
77 	    }
78 	    rxvt_process_x_event (l->rxvt);
79 	    if (l->rxvt->killed) {
80 		CRemoveWatch (l->rxvt->cmd_fd, 0, 3);
81 		CRemoveWatch (l->rxvt->cmd_fd, 0, 3);
82 		return 1;
83 	    }
84 	    rxvtlib_update_screen (l->rxvt);
85 	    if (win != DefaultRootWindow (l->rxvt->Xdisplay)
86 		&& xevent->type != ClientMessage
87 		&& xevent->type != SelectionNotify
88 		&& xevent->type != SelectionRequest
89 		&& xevent->type != SelectionClear) {
90 		xevent->type = 0;
91 		xevent->xany.window = 0;
92 		return 1;
93 	    }
94 	    return 0;
95 	}
96 	prev = l;
97     }
98     return 0;
99 }
100 
rxvt_have_pid(pid_t pid)101 int rxvt_have_pid (pid_t pid)
102 {
103     struct rxvts *l;
104     if (!rxvt_list)
105 	return 0;
106     for (l = rxvt_list->next; l; l = l->next)
107 	if (l->rxvt->cmd_pid == pid)
108 	    return 1;
109     return 0;
110 }
111 
112 /* rxvt's need to interoperate */
rxvt_selection_clear(void)113 void rxvt_selection_clear (void)
114 {
115     struct rxvts *l;
116     if (!rxvt_list)
117 	return;
118     for (l = rxvt_list->next; l; l = l->next) {
119 	rxvtlib *o;
120 	o = l->rxvt;
121 	if (o->selection.text)
122 	    FREE (o->selection.text);
123 	o->selection.text = NULL;
124 	o->selection.len = 0;
125     }
126     return;
127 }
128 
129 #if 0
130 int rxvt_alive (pid_t p)
131 {
132     struct rxvts *l;
133     if (!rxvt_list)
134 	return 0;
135     for (l = rxvt_list->next; l; l = l->next)
136 	if (l->rxvt->cmd_pid == p && !l->killed && !l->rxvt->killed)
137 	    return 1;
138     return 0;
139 }
140 #endif
141 
142 extern void (*user_selection_clear) (void);
143 
rxvt_allocate(Window win,int c,char ** a,int do_sleep)144 rxvtlib *rxvt_allocate (Window win, int c, char **a, int do_sleep)
145 {
146     rxvtlib *rxvt;
147     struct rxvts *l;
148     rxvt = (rxvtlib *) malloc (sizeof (rxvtlib));
149     rxvtlib_init (rxvt);
150     user_selection_clear = (void (*)(void)) rxvt_selection_clear;
151     rxvt->parent_window = win;
152     rxvtlib_main (rxvt, c, (const char *const *) a, do_sleep);
153     if (rxvt->killed) {
154 	free (rxvt);
155 	return 0;
156     }
157     if (!rxvt_list) {
158 	rxvt_list = l = malloc (sizeof (struct rxvts));
159 	rxvt_list->next = 0;
160 	rxvt_list->rxvt = 0;
161 	rxvt_list->killed = 0;
162     }
163     for (l = rxvt_list; l->next; l = l->next);
164     l = (l->next = malloc (sizeof (struct rxvts)));
165     l->next = 0;
166     l->killed = 0;
167     l->rxvt = rxvt;
168     return rxvt;
169 }
170 
171 extern char *init_font;
172 
rxvt_args(char ** argv)173 char **rxvt_args (char **argv)
174 {
175     char **a;
176     char *b[] =
177 	{ "rxvt", "-fg", "white", "-bg", "black", "-font", "8x13bold", "-sl", "5000", "-si", "+sk", "-e", 0 };
178     int i = 0, j, k;
179     if (argv)
180 	for (i = 0; argv[i]; i++);
181     CPushFont ("editor", 0);
182     if (CIsFixedFont () && init_font) {
183 	for (k = 0; b[k] && strcmp (b[k], "-font"); k++);
184 	if (k != i)
185 	    b[k + 1] = init_font;
186     }
187     CPopFont ();
188     for (j = 0; b[j]; j++);
189     a = malloc ((i + j + 1) * sizeof (char *));
190     memcpy (a, b, j * sizeof (char *));
191     if (argv)
192 	memcpy (a + j, argv, (i + 1) * sizeof (char *));
193     if (!i)
194 	a[--j] = 0;		/* shell */
195     return a;
196 }
197 
198 #if 0
199 void rxvt_resize_window (rxvtlib * rxvt, int w, int h)
200 {
201     XResizeWindow (rxvt->Xdisplay, rxvt->TermWin.parent[0], w, h);
202     rxvtlib_resize_window (rxvt, w, h);
203 }
204 #endif
205 
rxvtlib_shutall(void)206 void rxvtlib_shutall (void)
207 {
208     struct rxvts *l;
209     if (!rxvt_list)
210 	return;
211     l = rxvt_list->next;
212     free (rxvt_list);
213     rxvt_list = 0;
214     while (l) {
215 	struct rxvts *next;
216 	next = l->next;
217 	CRemoveWatch (l->rxvt->cmd_fd, 0, 3);
218 	CRemoveWatch (l->rxvt->cmd_fd, 0, 3);
219 	if (!l->killed)
220 	    close (l->rxvt->cmd_fd);
221 	XDestroyWindow (l->rxvt->Xdisplay, l->rxvt->TermWin.parent[0]);
222 	XDestroyWindow (l->rxvt->Xdisplay, l->rxvt->TermWin.vt);
223 	XDestroyWindow (l->rxvt->Xdisplay, l->rxvt->scrollBar.win);
224 	rxvtlib_shut (l->rxvt);
225 	free (l->rxvt);
226 	memset (l, 0, sizeof (*l));
227 	free (l);
228 	l = next;
229     }
230 }
231 
rxvt_start(Window win,char ** argv,int do_sleep)232 rxvtlib *rxvt_start (Window win, char **argv, int do_sleep)
233 {
234     int a = 0;
235     rxvtlib *rxvt;
236     char **b;
237     b = rxvt_args (argv);
238     while (b[a])
239 	a++;
240     rxvt = rxvt_allocate (win, a, b, do_sleep);
241     if (rxvt) {
242 	rxvtlib_main_loop (rxvt);
243 	rxvtlib_update_screen (rxvt);
244     }
245     free (b);
246     return rxvt;
247 }
248 
rxvt_get_tty_name(rxvtlib * rxvt,char * p)249 void rxvt_get_tty_name (rxvtlib * rxvt, char *p)
250 {
251     strcpy (p, rxvt->ttydev);
252 }
253 
rxvt_get_pid(rxvtlib * rxvt)254 pid_t rxvt_get_pid (rxvtlib * rxvt)
255 {
256     return rxvt->cmd_pid;
257 }
258 
259 #if 0
260 Window rxvt_get_main_window (rxvtlib *rxvt)
261 {
262     return rxvt->TermWin.parent[0];
263 }
264 #endif
265 
266