1 /* Copyright © 2007-2016 Evgeny Ratnikov
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <string.h>
18 #include <gdk/gdk.h>
19
20 #include "termit.h"
21 #include "keybindings.h"
22 #include "configs.h"
23 #include "lua_api.h"
24
25 struct Configs configs = {};
26
27 static struct {
28 const char* name;
29 VteEraseBinding val;
30 } erase_bindings[] = {
31 {"Auto", VTE_ERASE_AUTO},
32 {"AsciiBksp", VTE_ERASE_ASCII_BACKSPACE},
33 {"AsciiDel", VTE_ERASE_ASCII_DELETE},
34 {"EraseDel", VTE_ERASE_DELETE_SEQUENCE},
35 {"EraseTty", VTE_ERASE_TTY}
36 };
37 static guint EraseBindingsSz = sizeof(erase_bindings)/sizeof(erase_bindings[0]);
38
termit_erase_binding_to_string(VteEraseBinding val)39 const char* termit_erase_binding_to_string(VteEraseBinding val)
40 {
41 return erase_bindings[val].name;
42 }
43
termit_erase_binding_from_string(const char * str)44 VteEraseBinding termit_erase_binding_from_string(const char* str)
45 {
46 guint i = 0;
47 for (; i < EraseBindingsSz; ++i) {
48 if (strcmp(str, erase_bindings[i].name) == 0) {
49 return erase_bindings[i].val;
50 }
51 }
52 ERROR("unknown erase binding [%s], using Auto", str);
53 return VTE_ERASE_AUTO;
54 }
55
56 static struct {
57 const char* name;
58 VteCursorBlinkMode val;
59 } cursor_blink_modes[] = {
60 {"System", VTE_CURSOR_BLINK_SYSTEM},
61 {"BlinkOn", VTE_CURSOR_BLINK_ON},
62 {"BlinkOff", VTE_CURSOR_BLINK_OFF}
63 };
64 static guint BlinkModesSz = sizeof(cursor_blink_modes)/sizeof(cursor_blink_modes[0]);
65
termit_cursor_blink_mode_to_string(VteCursorBlinkMode val)66 const char* termit_cursor_blink_mode_to_string(VteCursorBlinkMode val)
67 {
68 return cursor_blink_modes[val].name;
69 }
70
termit_cursor_blink_mode_from_string(const char * str)71 VteCursorBlinkMode termit_cursor_blink_mode_from_string(const char* str)
72 {
73 guint i = 0;
74 for (; i < BlinkModesSz; ++i) {
75 if (strcmp(str, cursor_blink_modes[i].name) == 0) {
76 return cursor_blink_modes[i].val;
77 }
78 }
79 ERROR("unknown blink mode [%s], using System", str);
80 return VTE_CURSOR_BLINK_SYSTEM;
81 }
82
83 static struct {
84 const char* name;
85 VteCursorShape val;
86 } cursor_shapes[] = {
87 {"Block", VTE_CURSOR_SHAPE_BLOCK},
88 {"Ibeam", VTE_CURSOR_SHAPE_IBEAM},
89 {"Underline", VTE_CURSOR_SHAPE_UNDERLINE}
90 };
91 static guint ShapesSz = sizeof(cursor_shapes)/sizeof(cursor_shapes[0]);
92
termit_cursor_shape_to_string(VteCursorShape val)93 const char* termit_cursor_shape_to_string(VteCursorShape val)
94 {
95 return cursor_shapes[val].name;
96 }
97
termit_cursor_shape_from_string(const char * str)98 VteCursorShape termit_cursor_shape_from_string(const char* str)
99 {
100 guint i = 0;
101 for (; i < ShapesSz; ++i) {
102 if (strcmp(str, cursor_shapes[i].name) == 0) {
103 return cursor_shapes[i].val;
104 }
105 }
106 ERROR("unknown cursor shape [%s], using Block", str);
107 return VTE_CURSOR_SHAPE_BLOCK;
108 }
109
termit_config_trace()110 void termit_config_trace()
111 {
112 #ifdef DEBUG
113 TRACE(" default_window_title = %s", configs.default_window_title);
114 TRACE(" default_tab_name = %s", configs.default_tab_name);
115 TRACE(" default_encoding = %s", configs.default_encoding);
116 TRACE(" default_word_char_exceptions = %s", configs.default_word_char_exceptions);
117 TRACE(" show_scrollbar = %d", configs.show_scrollbar);
118 TRACE(" hide_menubar = %d", configs.hide_menubar);
119 TRACE(" hide_tabbar = %d", configs.hide_tabbar);
120 TRACE(" fill_tabbar = %d", configs.fill_tabbar);
121 TRACE(" show_border = %d", configs.show_border);
122 TRACE(" hide_single_tab = %d", configs.hide_single_tab);
123 TRACE(" start_maximized = %d", configs.start_maximized);
124 TRACE(" hide_titlebar_when_maximized = %d", configs.hide_titlebar_when_maximized);
125 TRACE(" scrollback_lines = %d", configs.scrollback_lines);
126 TRACE(" cols x rows = %d x %d", configs.cols, configs.rows);
127 TRACE(" backspace = %s", termit_erase_binding_to_string(configs.default_bksp));
128 TRACE(" delete = %s", termit_erase_binding_to_string(configs.default_delete));
129 TRACE(" blink = %s", termit_cursor_blink_mode_to_string(configs.default_blink));
130 TRACE(" shape = %s", termit_cursor_shape_to_string(configs.default_shape));
131 TRACE(" allow_changing_title = %d", configs.allow_changing_title);
132 TRACE(" audible_bell = %d", configs.audible_bell);
133 TRACE(" scroll_on_output = %d", configs.scroll_on_output);
134 TRACE(" scroll_on_keystroke = %d", configs.scroll_on_keystroke);
135 TRACE(" get_window_title_callback = %d", configs.get_window_title_callback);
136 TRACE(" get_tab_title_callback = %d", configs.get_tab_title_callback);
137 TRACE(" get_statusbar_callback = %d", configs.get_statusbar_callback);
138 TRACE(" kb_policy = %d", configs.kb_policy);
139 TRACE(" tab_pos = %d", configs.tab_pos);
140 TRACE(" style:");
141 TRACE(" font_name = %s", configs.style.font_name);
142 if (configs.style.foreground_color) {
143 gchar* tmpStr = gdk_rgba_to_string(configs.style.foreground_color);
144 TRACE(" foreground_color = %s", tmpStr);
145 g_free(tmpStr);
146 }
147 if (configs.style.background_color) {
148 gchar* tmpStr = gdk_rgba_to_string(configs.style.background_color);
149 TRACE(" background_color = %s", tmpStr);
150 g_free(tmpStr);
151 }
152 #endif
153 }
154
termit_configs_set_defaults()155 void termit_configs_set_defaults()
156 {
157 configs.default_window_title = g_strdup("Termit");
158 configs.default_tab_name = g_strdup("Terminal");
159 termit_style_init(&configs.style);
160 configs.default_command = g_strdup(g_getenv("SHELL"));
161 configs.default_encoding = g_strdup("UTF-8");
162 configs.default_word_char_exceptions = g_strdup("-A-Za-z0-9,./?%&#_~");
163 configs.scrollback_lines = 4096;
164 configs.cols = 80;
165 configs.rows = 24;
166 configs.default_bksp = VTE_ERASE_AUTO;
167 configs.default_delete = VTE_ERASE_AUTO;
168 configs.default_blink = VTE_CURSOR_BLINK_SYSTEM;
169 configs.default_shape = VTE_CURSOR_SHAPE_BLOCK;
170
171 configs.user_menus = g_array_new(FALSE, TRUE, sizeof(struct UserMenu));
172 configs.user_popup_menus = g_array_new(FALSE, TRUE, sizeof(struct UserMenu));
173 configs.key_bindings = g_array_new(FALSE, TRUE, sizeof(struct KeyBinding));
174 configs.mouse_bindings = g_array_new(FALSE, TRUE, sizeof(struct MouseBinding));
175 configs.matches = g_array_new(FALSE, TRUE, sizeof(struct Match));
176
177 configs.start_maximized = FALSE;
178 configs.hide_titlebar_when_maximized = FALSE;
179 configs.hide_single_tab = FALSE;
180 configs.show_scrollbar = TRUE;
181 configs.fill_tabbar = FALSE;
182 configs.hide_menubar = FALSE;
183 configs.hide_tabbar = FALSE;
184 configs.show_border = TRUE;
185 configs.allow_changing_title = FALSE;
186 configs.audible_bell = FALSE;
187 configs.urgency_on_bell = FALSE;
188 configs.get_window_title_callback = 0;
189 configs.get_tab_title_callback = 0;
190 configs.get_statusbar_callback = 0;
191 configs.kb_policy = TermitKbUseKeysym;
192 configs.tab_pos = GTK_POS_TOP;
193 configs.scroll_on_output = FALSE;
194 configs.scroll_on_keystroke = TRUE;
195 }
196
free_menu(GArray * menus)197 static void free_menu(GArray* menus)
198 {
199 guint i = 0;
200 for (; i<menus->len; ++i) {
201 struct UserMenu* um = &g_array_index(menus, struct UserMenu, i);
202 guint j = 0;
203 for (; j<um->items->len; ++j) {
204 struct UserMenuItem* umi = &g_array_index(um->items, struct UserMenuItem, j);
205 g_free(umi->name);
206 g_free(umi->accel);
207 termit_lua_unref(&umi->lua_callback);
208 }
209 g_free(um->name);
210 g_array_free(um->items, TRUE);
211 }
212 }
213
termit_config_deinit()214 void termit_config_deinit()
215 {
216 g_free(configs.default_window_title);
217 g_free(configs.default_tab_name);
218 termit_style_free(&configs.style);
219 g_free(configs.default_command);
220 g_free(configs.default_encoding);
221 g_free(configs.default_word_char_exceptions);
222
223 free_menu(configs.user_menus);
224 g_array_free(configs.user_menus, TRUE);
225 free_menu(configs.user_popup_menus);
226 g_array_free(configs.user_popup_menus, TRUE);
227
228 // name and default_binding are static (e.g. can be in readonly mempage)
229 guint i = 0;
230 for (; i<configs.key_bindings->len; ++i) {
231 struct KeyBinding* kb = &g_array_index(configs.key_bindings, struct KeyBinding, i);
232 termit_lua_unref(&kb->lua_callback);
233 }
234 g_array_free(configs.key_bindings, TRUE);
235
236 i = 0;
237 for (; i<configs.mouse_bindings->len; ++i) {
238 struct MouseBinding* mb = &g_array_index(configs.mouse_bindings, struct MouseBinding, i);
239 termit_lua_unref(&mb->lua_callback);
240 }
241 g_array_free(configs.mouse_bindings, TRUE);
242
243 i = 0;
244 for (; i<configs.matches->len; ++i) {
245 struct Match* match = &g_array_index(configs.matches, struct Match, i);
246 vte_regex_unref(match->regex);
247 g_free(match->pattern);
248 }
249 g_array_free(configs.matches, TRUE);
250
251 termit_lua_unref(&configs.get_window_title_callback);
252 termit_lua_unref(&configs.get_tab_title_callback);
253 termit_lua_unref(&configs.get_statusbar_callback);
254 }
255