1 /* window.c: Window-management routines for libRUIN
2 * Copyright (C) 2011 Julian Graham
3 *
4 * libRUIN 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.
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, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <glib.h>
19 #ifdef LINUX
20 #include <pty.h>
21 #endif /* LINUX */
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/ioctl.h>
26
27 #include "layout.h"
28 #include "load.h"
29 #include "parse.h"
30 #include "scheme.h"
31 #include "util.h"
32 #include "window.h"
33
34 extern void ruin_box_free (ruin_box_t *);
35 extern ruin_windows_t *_ruin_windows;
36 static pthread_mutex_t ruin_window_signal_handler_SIGWINCH_entry_lock;
37
resize_window(gpointer key,gpointer value,gpointer user_data)38 static void resize_window (gpointer key, gpointer value, gpointer user_data)
39 {
40 ruin_window_t *window = (ruin_window_t *) value;
41 int *newxy = (int *) user_data;
42 int oldx = 0, oldy = 0, newx = 0, newy = 0;
43
44 ruin_box_t *root_box = (ruin_box_t *) g_list_nth_data (window->root_boxes, 0);
45 ruin_node_t *generator = root_box->generator;
46 GList *root_box_ptr = window->root_boxes;
47
48 oldx = window->width;
49 oldy = window->height;
50
51 newx = newxy[0];
52 newy = newxy[1];
53
54 if (oldx != newx || oldy != newy)
55 {
56 window->width = newx;
57 window->height = newy;
58
59 resizeterm (newy, newx);
60 ruin_load_layout_and_render (window, generator);
61
62 while (root_box_ptr != NULL)
63 {
64 ruin_box_t *old_box = (ruin_box_t *) root_box_ptr->data;
65 ruin_box_free (old_box);
66 root_box_ptr = root_box_ptr->next;
67 }
68 }
69 }
70
ruin_window_signal_handler_SIGWINCH(int n,siginfo_t * s,void * u)71 void ruin_window_signal_handler_SIGWINCH (int n, siginfo_t *s, void *u)
72 {
73 static int busy = 0;
74 struct winsize ws;
75 int newxy[2];
76
77 pthread_mutex_lock (&ruin_window_signal_handler_SIGWINCH_entry_lock);
78 if (busy)
79 {
80 pthread_mutex_unlock (&ruin_window_signal_handler_SIGWINCH_entry_lock);
81 return;
82 }
83 pthread_mutex_unlock (&ruin_window_signal_handler_SIGWINCH_entry_lock);
84 busy = TRUE;
85
86 (void) ioctl (0, TIOCGWINSZ, &ws);
87
88 newxy[0] = ws.ws_col;
89 newxy[1] = ws.ws_row;
90
91 g_hash_table_foreach (_ruin_windows->windows, resize_window, newxy);
92
93 busy = FALSE;
94 }
95
ruin_windows_new()96 ruin_windows_t *ruin_windows_new ()
97 {
98 char *xul = NULL;
99 char *xhtml = NULL;
100
101 char *env_val = getenv ("RUIN_CSS_PATH");
102
103 SCM port = SCM_EOL;
104
105 ruin_windows_t *t = calloc (1, sizeof (ruin_windows_t));
106 t->windows = g_hash_table_new (g_str_hash, g_str_equal);
107
108 if (env_val == NULL)
109 env_val = RUIN_CSS_PATH;
110
111 xul = calloc (strlen (env_val) + 16, sizeof(char));
112 xhtml = calloc (strlen (env_val) + 18, sizeof(char));
113 strcat (xul, "file://");
114 strcat (xul, env_val);
115 strcat (xul, "/xul.css");
116 strcat (xhtml, "file://");
117 strcat (xhtml, env_val);
118 strcat (xhtml, "/xhtml.css");
119
120 port = scm_open_file
121 (scm_from_locale_string (xul + 7), scm_from_locale_string ("r"));
122 t->xul_agent_css = ruin_scheme_scss_css_to_scss_port (NULL, port, xul);
123
124 port = scm_open_file
125 (scm_from_locale_string (xhtml + 7), scm_from_locale_string ("r"));
126 t->xhtml_agent_css = ruin_scheme_scss_css_to_scss_port (NULL, port, xhtml);
127
128 free (xul);
129 free (xhtml);
130
131 pthread_mutex_init (&ruin_window_signal_handler_SIGWINCH_entry_lock, NULL);
132
133 return t;
134 }
135
ruin_windows_free(ruin_windows_t * t)136 void ruin_windows_free (ruin_windows_t *t)
137 {
138 free (t->windows);
139 scm_gc_unprotect_object (t->xul_agent_css);
140 scm_gc_unprotect_object (t->xhtml_agent_css);
141 free (t);
142 }
143
ruin_window_new(WINDOW * w,FILE * f)144 ruin_window_t *ruin_window_new (WINDOW *w, FILE *f)
145 {
146 ruin_window_t *t = calloc (1, sizeof (ruin_window_t));
147 char *tmp = NULL, *tmp_ptr = NULL;
148 int tmp_val = 0;
149
150 t->window = w;
151 t->log = f;
152 t->render_state = calloc (1, sizeof (ruin_window_render_state_t));
153
154 t->internal_id = ruin_util_generate_id ();
155 g_hash_table_insert
156 (_ruin_windows->windows, ruin_util_long_to_string (t->internal_id), t);
157
158 t->ids = ruin_util_hash_new ();
159 t->internal_ids = ruin_util_hash_new ();
160
161 if ((tmp = getenv (RUIN_WINDOW_FONT_HEIGHT_ENV)) &&
162 ((tmp_val = strtol (tmp, &tmp_ptr, 10)) > 0) &&
163 (tmp != tmp_ptr))
164 t->font_height = tmp_val;
165 else t->font_height = RUIN_WINDOW_DEFAULT_FONT_HEIGHT;
166
167 if ((tmp = getenv (RUIN_WINDOW_FONT_WIDTH_ENV)) &&
168 ((tmp_val = strtol (tmp, &tmp_ptr, 10)) > 0) &&
169 (tmp != tmp_ptr))
170 t->font_width = tmp_val;
171 else t->font_width = RUIN_WINDOW_DEFAULT_FONT_WIDTH;
172
173 if ((tmp = getenv (RUIN_WINDOW_DPI_ENV)) &&
174 ((tmp_val = strtol (tmp, &tmp_ptr, 10)) > 0) &&
175 (tmp != tmp_ptr))
176 t->dpi = tmp_val;
177 else t->dpi = RUIN_WINDOW_DEFAULT_DPI;
178
179 getmaxyx (w, t->height, t->width);
180
181 if (_ruin_windows->current_window == NULL)
182 _ruin_windows->current_window = t;
183
184 return t;
185 }
186
ruin_window_free(ruin_window_t * t)187 void ruin_window_free (ruin_window_t *t)
188 {
189 g_hash_table_remove
190 (_ruin_windows->windows, ruin_util_long_to_string (t->internal_id));
191
192 ruin_window_clear (t);
193 ruin_util_hash_free (t->ids);
194 ruin_util_hash_free (t->internal_ids);
195
196 free (t->render_state);
197 free (t);
198 return;
199 }
200
ruin_window_clear(ruin_window_t * w)201 void ruin_window_clear (ruin_window_t *w)
202 {
203 ruin_util_hash_clear (w->ids);
204 ruin_util_hash_clear (w->internal_ids);
205 return;
206 }
207
ruin_window_lookup_scm(SCM elt)208 ruin_node_t *ruin_window_lookup_scm (SCM elt)
209 {
210 ruin_window_t *containing_win = ruin_window_lookup_window (elt);
211 if (containing_win != NULL)
212 {
213 SCM res = SCM_EOL;
214 if (scm_eq_p (res, SCM_EOL) == SCM_BOOL_T)
215 ruin_util_log (containing_win, "found containing window but not node");
216 return (ruin_node_t *)
217 ruin_util_string_to_ptr (scm_to_locale_string (res));
218 }
219 return NULL;
220 }
221
ruin_window_lookup_window(SCM elt)222 ruin_window_t *ruin_window_lookup_window (SCM elt)
223 {
224 return NULL;
225 }
226
ruin_get_current_window()227 ruin_window_t *ruin_get_current_window ()
228 {
229 return ruin_window_get_current_window ();
230 }
231
ruin_window_get_current_window()232 ruin_window_t *ruin_window_get_current_window ()
233 {
234 return _ruin_windows->current_window;
235 }
236
ruin_set_current_window(ruin_window_t * w)237 void ruin_set_current_window (ruin_window_t *w)
238 {
239 ruin_window_set_current_window (w);
240 /* TODO: Render it! */
241 }
242
ruin_window_set_current_window(ruin_window_t * w)243 void ruin_window_set_current_window (ruin_window_t *w)
244 {
245 _ruin_windows->current_window = w;
246 }
247