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 <lua.h>
19 #include <lualib.h>
20 #include <lauxlib.h>
21
22 #include "termit.h"
23 #include "termit_core_api.h"
24 #include "keybindings.h"
25 #include "configs.h"
26 #include "callbacks.h"
27 #include "lua_api.h"
28
29 extern lua_State* L;
30
termit_lua_load_table(lua_State * ls,TermitLuaTableLoaderFunc func,const int tableIndex,void * data)31 TermitLuaTableLoaderResult termit_lua_load_table(lua_State* ls, TermitLuaTableLoaderFunc func,
32 const int tableIndex, void* data)
33 {
34 if (!lua_istable(ls, tableIndex)) {
35 ERROR("not a table");
36 return TERMIT_LUA_TABLE_LOADER_FAILED;
37 }
38
39 lua_pushnil(ls);
40 while (lua_next(ls, tableIndex) != 0) {
41 if (lua_isnumber(ls, tableIndex + 1)) {
42 func("0", ls, tableIndex + 2, data);
43 } else if (lua_isstring(ls, tableIndex + 1)) {
44 const char* name = lua_tostring(ls, tableIndex + 1);
45 func(name, ls, tableIndex + 2, data);
46 } else {
47 ERROR("neither number nor string value found - skipping");
48 lua_pop(ls, 1);
49 }
50 lua_pop(ls, 1);
51 }
52 return TERMIT_LUA_TABLE_LOADER_OK;
53 }
54
55
termit_lua_execute(const gchar * cmd)56 void termit_lua_execute(const gchar* cmd)
57 {
58 TRACE("executing script: %s", cmd);
59 int s = luaL_dostring(L, cmd);
60 termit_lua_report_error(__FILE__, __LINE__, s);
61 }
62
termit_lua_report_error(const char * file,int line,int status)63 void termit_lua_report_error(const char* file, int line, int status)
64 {
65 if (status == 0) {
66 return;
67 }
68 g_fprintf(stderr, "%s:%d %s\n", file, line, lua_tostring(L, -1));
69 lua_pop(L, 1);
70 }
71
termit_lua_setOptions(lua_State * ls)72 static int termit_lua_setOptions(lua_State* ls)
73 {
74 termit_lua_load_table(ls, termit_lua_options_loader, 1, &configs);
75 if (configs.default_tabs) {
76 guint i = 0;
77 for (; i < configs.default_tabs->len; ++i) {
78 struct TabInfo* ti = &g_array_index(configs.default_tabs, struct TabInfo, i);
79 termit_append_tab_with_details(ti);
80 g_free(ti->name);
81 g_strfreev(ti->argv);
82 g_free(ti->encoding);
83 g_free(ti->working_dir);
84 }
85 g_array_free(configs.default_tabs, TRUE);
86 configs.default_tabs = NULL;
87 }
88 return 0;
89 }
90
termit_lua_dofunction(int f)91 int termit_lua_dofunction(int f)
92 {
93 lua_State* ls = L;
94 if(f != LUA_REFNIL) {
95 lua_rawgeti(ls, LUA_REGISTRYINDEX, f);
96 if (lua_pcall(ls, 0, 0, 0)) {
97 TRACE("error running function (%d): %s", f, lua_tostring(ls, -1));
98 lua_pop(ls, 1);
99 return 0;
100 }
101 return 1;
102 }
103 return 0;
104 }
105
termit_lua_dofunction2(int f,const char * arg1)106 int termit_lua_dofunction2(int f, const char* arg1)
107 {
108 lua_State* ls = L;
109 if(f != LUA_REFNIL) {
110 lua_rawgeti(ls, LUA_REGISTRYINDEX, f);
111 lua_pushstring(ls, arg1);
112 if (lua_pcall(ls, 1, 0, 0)) {
113 TRACE("error running function (%d): %s", f, lua_tostring(ls, -1));
114 lua_pop(ls, 1);
115 return 0;
116 }
117 return 1;
118 }
119 return 0;
120 }
121
termit_lua_domatch(int f,const gchar * matchedText)122 int termit_lua_domatch(int f, const gchar* matchedText)
123 {
124 lua_State* ls = L;
125 if(f != LUA_REFNIL) {
126 lua_rawgeti(ls, LUA_REGISTRYINDEX, f);
127 lua_pushstring(ls, matchedText);
128 if (lua_pcall(ls, 1, 0, 0)) {
129 TRACE("error running function (%d: %s): %s", f, matchedText, lua_tostring(ls, -1));
130 lua_pop(ls, 1);
131 return 0;
132 }
133 return 1;
134 }
135 return 0;
136 }
137
termit_lua_unref(int * lua_callback)138 void termit_lua_unref(int* lua_callback)
139 {
140 if (*lua_callback) {
141 luaL_unref(L, LUA_REGISTRYINDEX, *lua_callback);
142 *lua_callback = 0;
143 }
144 }
145
termit_lua_getStatusbarCallback(int f,guint page)146 gchar* termit_lua_getStatusbarCallback(int f, guint page)
147 {
148 lua_State* ls = L;
149 if(f != LUA_REFNIL) {
150 lua_rawgeti(ls, LUA_REGISTRYINDEX, f);
151 lua_pushnumber(ls, page);
152 if (lua_pcall(ls, 1, 1, 0)) {
153 TRACE("error running function: %s", lua_tostring(ls, -1));
154 lua_pop(ls, 1);
155 return NULL;
156 }
157 if (lua_isstring(ls, -1)) {
158 return g_strdup(lua_tostring(ls, -1));
159 }
160 }
161 return NULL;
162 }
163
termit_lua_getTitleCallback(int f,const gchar * title)164 gchar* termit_lua_getTitleCallback(int f, const gchar* title)
165 {
166 lua_State* ls = L;
167 if(f != LUA_REFNIL) {
168 lua_rawgeti(ls, LUA_REGISTRYINDEX, f);
169 lua_pushstring(ls, title);
170 if (lua_pcall(ls, 1, 1, 0)) {
171 TRACE("error running function: %s", lua_tostring(ls, -1));
172 lua_pop(ls, 1);
173 return NULL;
174 }
175 if (lua_isstring(ls, -1)) {
176 return g_strdup(lua_tostring(ls, -1));
177 }
178 }
179 return NULL;
180 }
181
termit_lua_bindKey(lua_State * ls)182 static int termit_lua_bindKey(lua_State* ls)
183 {
184 TRACE_MSG(__FUNCTION__);
185 if (lua_isnil(ls, 1)) {
186 TRACE_MSG("nil args: skipping");
187 } else if (!lua_isstring(ls, 1)) {
188 TRACE_MSG("bad args: skipping");
189 } else if (lua_isnil(ls, 2)) {
190 const char* keybinding = lua_tostring(ls, 1);
191 termit_keys_unbind(keybinding);
192 TRACE("unbindKey: %s", keybinding);
193 } else if (lua_isfunction(ls, 2)) {
194 const char* keybinding = lua_tostring(ls, 1);
195 int func = luaL_ref(ls, LUA_REGISTRYINDEX);
196 termit_keys_bind(keybinding, func);
197 TRACE("bindKey: %s - %d", keybinding, func);
198 }
199 return 0;
200 }
201
termit_lua_bindMouse(lua_State * ls)202 static int termit_lua_bindMouse(lua_State* ls)
203 {
204 if (lua_isnil(ls, 1)) {
205 TRACE_MSG("nil args: skipping");
206 } else if (!lua_isstring(ls, 1)) {
207 TRACE_MSG("bad args: skipping");
208 } else if (lua_isnil(ls, 2)) {
209 const char* mousebinding = lua_tostring(ls, 1);
210 termit_mouse_unbind(mousebinding);
211 TRACE("unbindMouse: %s", mousebinding);
212 } else if (lua_isfunction(ls, 2)) {
213 const char* mousebinding = lua_tostring(ls, 1);
214 int func = luaL_ref(ls, LUA_REGISTRYINDEX);
215 termit_mouse_bind(mousebinding, func);
216 TRACE("bindMouse: %s - %d", mousebinding, func);
217 }
218 return 0;
219 }
220
termit_lua_toggleMenubar(lua_State * ls)221 static int termit_lua_toggleMenubar(lua_State* ls)
222 {
223 termit_toggle_menubar();
224 return 0;
225 }
226
termit_lua_toggleTabbar(lua_State * ls)227 static int termit_lua_toggleTabbar(lua_State* ls)
228 {
229 termit_toggle_tabbar();
230 return 0;
231 }
232
termit_lua_tab_loader(const gchar * name,lua_State * ls,int index,void * data)233 void termit_lua_tab_loader(const gchar* name, lua_State* ls, int index, void* data)
234 {
235 struct TabInfo* ti = (struct TabInfo*)data;
236 if (strcmp(name, "title") == 0) {
237 termit_config_get_string(&ti->name, ls, index);
238 } else if (strcmp(name, "command") == 0) {
239 if (ti->argv == NULL) {
240 ti->argv = (gchar**)g_new0(gchar*, 2);
241 }
242 termit_config_get_string(&ti->argv[0], ls, index);
243 } else if (strcmp(name, "encoding") == 0) {
244 termit_config_get_string(&ti->encoding, ls, index);
245 } else if (strcmp(name, "backspaceBinding") == 0) {
246 termit_config_get_erase_binding(&ti->bksp_binding, ls, index);
247 } else if (strcmp(name, "deleteBinding") == 0) {
248 termit_config_get_erase_binding(&ti->delete_binding, ls, index);
249 } else if (strcmp(name, "cursorBlinkMode") == 0) {
250 termit_config_get_cursor_blink_mode(&ti->cursor_blink_mode, ls, index);
251 } else if (strcmp(name, "cursorShape") == 0) {
252 termit_config_get_cursor_shape(&ti->cursor_shape, ls, index);
253 } else if (strcmp(name, "workingDir") == 0) {
254 termit_config_get_string(&ti->working_dir, ls, index);
255 }
256 }
257
termit_lua_nextTab(lua_State * ls)258 static int termit_lua_nextTab(lua_State* ls)
259 {
260 TRACE_MSG(__FUNCTION__);
261 termit_next_tab();
262 return 0;
263 }
264
termit_lua_prevTab(lua_State * ls)265 static int termit_lua_prevTab(lua_State* ls)
266 {
267 TRACE_MSG(__FUNCTION__);
268 termit_prev_tab();
269 return 0;
270 }
271
termit_lua_copy(lua_State * ls)272 static int termit_lua_copy(lua_State* ls)
273 {
274 TRACE_MSG(__FUNCTION__);
275 termit_copy();
276 return 0;
277 }
278
termit_lua_paste(lua_State * ls)279 static int termit_lua_paste(lua_State* ls)
280 {
281 TRACE_MSG(__FUNCTION__);
282 termit_paste();
283 return 0;
284 }
285
termit_lua_openTab(lua_State * ls)286 static int termit_lua_openTab(lua_State* ls)
287 {
288 TRACE_MSG(__FUNCTION__);
289 if (lua_istable(ls, 1)) {
290 struct TabInfo ti = {};
291 if (termit_lua_load_table(ls, termit_lua_tab_loader, 1, &ti)
292 != TERMIT_LUA_TABLE_LOADER_OK) {
293 ERROR("openTab failed");
294 return 0;
295 }
296 termit_append_tab_with_details(&ti);
297 g_free(ti.name);
298 g_strfreev(ti.argv);
299 g_free(ti.encoding);
300 g_free(ti.working_dir);
301 } else {
302 termit_append_tab();
303 }
304 return 0;
305 }
306
termit_lua_closeTab(lua_State * ls)307 static int termit_lua_closeTab(lua_State* ls)
308 {
309 TRACE_FUNC;
310 termit_close_tab();
311 return 0;
312 }
313
termit_lua_setKbPolicy(lua_State * ls)314 static int termit_lua_setKbPolicy(lua_State* ls)
315 {
316 if (lua_isnil(ls, 1)) {
317 TRACE_MSG("no kbPolicy defined: skipping");
318 return 0;
319 } else if (!lua_isstring(ls, 1)) {
320 TRACE_MSG("kbPolicy is not string: skipping");
321 return 0;
322 }
323 const gchar* val = lua_tostring(ls, 1);
324 TRACE("setKbPolicy: %s", val);
325 if (!strcmp(val, "keycode")) {
326 termit_set_kb_policy(TermitKbUseKeycode);
327 } else if (!strcmp(val, "keysym")) {
328 termit_set_kb_policy(TermitKbUseKeysym);
329 } else {
330 ERROR("unknown kbPolicy: %s", val);
331 }
332 return 0;
333 }
334
menuItemLoader(const gchar * name,lua_State * ls,int index,void * data)335 static void menuItemLoader(const gchar* name, lua_State* ls, int index, void* data)
336 {
337 struct UserMenuItem* umi = (struct UserMenuItem*)data;
338 if (!strcmp(name, "name") && lua_isstring(ls, index)) {
339 const gchar* value = lua_tostring(ls, index);
340 umi->name = g_strdup(value);
341 } else if (!strcmp(name, "action") && lua_isfunction(ls, index)) {
342 umi->lua_callback = luaL_ref(ls, LUA_REGISTRYINDEX);
343 lua_pushnil(ls); // luaL_ref pops value so we restore stack size
344 } else if (!strcmp(name, "accel") && lua_isstring(ls, index)) {
345 const gchar* value = lua_tostring(ls, index);
346 umi->accel = g_strdup(value);
347 }
348 }
349
menuLoader(const gchar * name,lua_State * ls,int index,void * data)350 static void menuLoader(const gchar* name, lua_State* ls, int index, void* data)
351 {
352 struct UserMenu* um = (struct UserMenu*)data;
353 if (lua_istable(ls, index)) {
354 struct UserMenuItem umi = {};
355 if (termit_lua_load_table(ls, menuItemLoader, index, &umi) == TERMIT_LUA_TABLE_LOADER_OK) {
356 g_array_append_val(um->items, umi);
357 } else {
358 ERROR("failed to load item: %s.%s", name, lua_tostring(ls, 3));
359 }
360 } else {
361 ERROR("unknown type instead if menu table: skipping");
362 lua_pop(ls, 1);
363 }
364 }
365
loadMenu(lua_State * ls,GArray * menus)366 static int loadMenu(lua_State* ls, GArray* menus)
367 {
368 if (lua_isnil(ls, 1) || lua_isnil(ls, 2)) {
369 TRACE_MSG("menu not defined: skipping");
370 return -1;
371 } else if (!lua_istable(ls, 1) || !lua_isstring(ls, 2)) {
372 TRACE_MSG("menu is not table: skipping");
373 return -1;
374 }
375 struct UserMenu um = {};
376 um.name = g_strdup(lua_tostring(ls, 2));
377 lua_pop(ls, 1);
378 um.items = g_array_new(FALSE, TRUE, sizeof(struct UserMenuItem));
379 if (termit_lua_load_table(ls, menuLoader, 1, &um) != TERMIT_LUA_TABLE_LOADER_OK) {
380 ERROR("addMenu failed");
381 }
382 if (um.items->len > 0) {
383 g_array_append_val(menus, um);
384 } else {
385 g_free(um.name);
386 g_array_free(um.items, TRUE);
387 }
388 return 0;
389 }
390
termit_lua_addMenu(lua_State * ls)391 static int termit_lua_addMenu(lua_State* ls)
392 {
393 if (loadMenu(ls, configs.user_menus) < 0) {
394 ERROR("addMenu failed");
395 }
396 return 0;
397 }
398
termit_lua_addPopupMenu(lua_State * ls)399 static int termit_lua_addPopupMenu(lua_State* ls)
400 {
401 if (loadMenu(ls, configs.user_popup_menus) < 0) {
402 ERROR("addMenu failed");
403 }
404 return 0;
405 }
406
termit_lua_setColormap(lua_State * ls)407 static int termit_lua_setColormap(lua_State* ls)
408 {
409 const gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook));
410 TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0);
411 termit_lua_load_colormap(ls, 1, &pTab->style.colors, &pTab->style.colors_size);
412 termit_tab_apply_colors(pTab);
413 return 0;
414 }
415
termit_lua_setEncoding(lua_State * ls)416 static int termit_lua_setEncoding(lua_State* ls)
417 {
418 if (lua_isnil(ls, 1)) {
419 TRACE_MSG("no encoding defined: skipping");
420 return 0;
421 } else if (!lua_isstring(ls, 1)) {
422 TRACE_MSG("encoding is not string: skipping");
423 return 0;
424 }
425 const gchar* val = lua_tostring(ls, 1);
426 termit_set_encoding(val);
427 return 0;
428 }
429
termit_lua_activateTab(lua_State * ls)430 static int termit_lua_activateTab(lua_State* ls)
431 {
432 if (lua_isnil(ls, 1)) {
433 TRACE_MSG("no tabNum defined: skipping");
434 return 0;
435 } else if (!lua_isnumber(ls, 1)) {
436 TRACE_MSG("tabNum is not number: skipping");
437 return 0;
438 }
439 int tab_index = lua_tointeger(ls, 1);
440 termit_activate_tab(tab_index - 1);
441 return 0;
442 }
443
termit_lua_currentTab(lua_State * ls)444 static int termit_lua_currentTab(lua_State* ls)
445 {
446 return termit_lua_fill_tab(termit_get_current_tab_index(), ls);
447 }
448
termit_lua_currentTabIndex(lua_State * ls)449 static int termit_lua_currentTabIndex(lua_State* ls)
450 {
451 lua_pushinteger(ls, termit_get_current_tab_index() + 1);
452 return 1;
453 }
454
termit_lua_loadSessionDialog(lua_State * ls)455 static int termit_lua_loadSessionDialog(lua_State* ls)
456 {
457 termit_on_load_session();
458 return 0;
459 }
460
termit_lua_saveSessionDialog(lua_State * ls)461 static int termit_lua_saveSessionDialog(lua_State* ls)
462 {
463 termit_on_save_session();
464 return 0;
465 }
466
termit_lua_preferencesDialog(lua_State * ls)467 static int termit_lua_preferencesDialog(lua_State* ls)
468 {
469 termit_on_edit_preferences();
470 return 0;
471 }
472
termit_lua_setTabTitleDialog(lua_State * ls)473 static int termit_lua_setTabTitleDialog(lua_State* ls)
474 {
475 termit_on_set_tab_name();
476 return 0;
477 }
478
termit_lua_setTabPos(lua_State * ls)479 static int termit_lua_setTabPos(lua_State* ls)
480 {
481 if (lua_isnil(ls, 1)) {
482 TRACE_MSG("no tabNum defined: skipping");
483 return 0;
484 } else if (!lua_isnumber(ls, 1)) {
485 TRACE_MSG("tabNum is not number: skipping");
486 return 0;
487 }
488 int tab_index = lua_tointeger(ls, 1);
489 gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook));
490 TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0);
491 termit_tab_set_pos(pTab, tab_index - 1);
492 return 0;
493 }
494
termit_lua_setTabTitle(lua_State * ls)495 static int termit_lua_setTabTitle(lua_State* ls)
496 {
497 if (lua_isnil(ls, 1)) {
498 TRACE_MSG("no tabName defined: skipping");
499 return 0;
500 } else if (!lua_isstring(ls, 1)) {
501 TRACE_MSG("tabName is not string: skipping");
502 return 0;
503 }
504 const gchar* val = lua_tostring(ls, 1);
505 gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook));
506 TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0);
507 termit_tab_set_title(pTab, val);
508 pTab->custom_tab_name = TRUE;
509 return 0;
510 }
511
termit_lua_setWindowTitle(lua_State * ls)512 static int termit_lua_setWindowTitle(lua_State* ls)
513 {
514 if (lua_isnil(ls, 1)) {
515 TRACE_MSG("no title defined: skipping");
516 return 0;
517 } else if (!lua_isstring(ls, 1)) {
518 TRACE_MSG("title is not string: skipping");
519 return 0;
520 }
521 const gchar* val = lua_tostring(ls, 1);
522 termit_set_window_title(val);
523 return 0;
524 }
525
termit_lua_setTabColor__(lua_State * ls,void (* callback)(gint,const GdkRGBA *))526 static int termit_lua_setTabColor__(lua_State* ls, void (*callback)(gint, const GdkRGBA*))
527 {
528 if (lua_isnil(ls, 1)) {
529 TRACE_MSG("no color defined: skipping");
530 return 0;
531 } else if (!lua_isstring(ls, 1)) {
532 TRACE_MSG("color is not string: skipping");
533 return 0;
534 }
535 const gchar* val = lua_tostring(ls, 1);
536 GdkRGBA color;
537 if (gdk_rgba_parse(&color, val) == TRUE) {
538 callback(-1, &color);
539 }
540 return 0;
541 }
542
termit_lua_setTabForegroundColor(lua_State * ls)543 static int termit_lua_setTabForegroundColor(lua_State* ls)
544 {
545 return termit_lua_setTabColor__(ls, &termit_tab_set_color_foreground_by_index);
546 }
547
termit_lua_setTabBackgroundColor(lua_State * ls)548 static int termit_lua_setTabBackgroundColor(lua_State* ls)
549 {
550 return termit_lua_setTabColor__(ls, &termit_tab_set_color_background_by_index);
551 }
552
termit_lua_setTabFont(lua_State * ls)553 static int termit_lua_setTabFont(lua_State* ls)
554 {
555 if (lua_isnil(ls, 1)) {
556 TRACE_MSG("no font defined: skipping");
557 return 0;
558 } else if (!lua_isstring(ls, 1)) {
559 TRACE_MSG("font is not string: skipping");
560 return 0;
561 }
562 const gchar* val = lua_tostring(ls, 1);
563 termit_tab_set_font_by_index(-1, val);
564 return 0;
565 }
566
termit_lua_spawn(lua_State * ls)567 static int termit_lua_spawn(lua_State* ls)
568 {
569 if (lua_isnil(ls, 1)) {
570 TRACE_MSG("no command defined: skipping");
571 return 0;
572 } else if (!lua_isstring(ls, 1)) {
573 TRACE_MSG("command is not string: skipping");
574 return 0;
575 }
576 GError *err = NULL;
577 const gchar* val = lua_tostring(ls, 1);
578 g_spawn_command_line_async(val, &err);
579 return 0;
580 }
581
termit_lua_forEachRow(lua_State * ls)582 static int termit_lua_forEachRow(lua_State* ls)
583 {
584 if (lua_isnil(ls, 1)) {
585 TRACE_MSG("no function defined: skipping");
586 return 0;
587 } else if (!lua_isfunction(ls, 1)) {
588 TRACE_MSG("1 arg is not function: skipping");
589 return 0;
590 }
591 int func = luaL_ref(ls, LUA_REGISTRYINDEX);
592 termit_for_each_row(func);
593 termit_lua_unref(&func);
594 return 0;
595 }
596
termit_lua_forEachVisibleRow(lua_State * ls)597 static int termit_lua_forEachVisibleRow(lua_State* ls)
598 {
599 if (lua_isnil(ls, 1)) {
600 TRACE_MSG("no function defined: skipping");
601 return 0;
602 } else if (!lua_isfunction(ls, 1)) {
603 TRACE_MSG("1 arg is not function: skipping");
604 return 0;
605 }
606 int func = luaL_ref(ls, LUA_REGISTRYINDEX);
607 termit_for_each_visible_row(func);
608 termit_lua_unref(&func);
609 return 0;
610 }
611
termit_lua_feed(lua_State * ls)612 static int termit_lua_feed(lua_State* ls)
613 {
614 if (lua_isnil(ls, 1)) {
615 TRACE_MSG("no data defined: skipping");
616 return 0;
617 } else if (!lua_isstring(ls, 1)) {
618 TRACE_MSG("data is not string: skipping");
619 return 0;
620 }
621 const gchar* val = lua_tostring(ls, 1);
622 gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook));
623 TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0);
624 termit_tab_feed(pTab, val);
625 return 0;
626 }
627
termit_lua_feedChild(lua_State * ls)628 static int termit_lua_feedChild(lua_State* ls)
629 {
630 if (lua_isnil(ls, 1)) {
631 TRACE_MSG("no data defined: skipping");
632 return 0;
633 } else if (!lua_isstring(ls, 1)) {
634 TRACE_MSG("data is not string: skipping");
635 return 0;
636 }
637 const gchar* val = lua_tostring(ls, 1);
638 gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(termit.notebook));
639 TERMIT_GET_TAB_BY_INDEX(pTab, page, return 0);
640 termit_tab_feed_child(pTab, val);
641 return 0;
642 }
643
termit_lua_findNext(lua_State * ls)644 static int termit_lua_findNext(lua_State* ls)
645 {
646 termit_search_find_next();
647 return 0;
648 }
649
termit_lua_findPrev(lua_State * ls)650 static int termit_lua_findPrev(lua_State* ls)
651 {
652 termit_search_find_prev();
653 return 0;
654 }
655
termit_lua_findDlg(lua_State * ls)656 static int termit_lua_findDlg(lua_State* ls)
657 {
658 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(termit.b_toggle_search), TRUE);
659 return 0;
660 }
661
termit_lua_selection(lua_State * ls)662 static int termit_lua_selection(lua_State* ls)
663 {
664 gchar* buff = termit_get_selection();
665 if (!buff) {
666 return 0;
667 }
668 lua_pushstring(ls, buff);
669 g_free(buff);
670 return 1;
671 }
672
termit_lua_reconfigure(lua_State * ls)673 static int termit_lua_reconfigure(lua_State* ls)
674 {
675 termit_reconfigure();
676 termit_config_trace();
677 return 0;
678 }
679
termit_lua_quit(lua_State * ls)680 static int termit_lua_quit(lua_State* ls)
681 {
682 termit_on_exit();
683 return 0;
684 }
685
686 struct TermitLuaFunction
687 {
688 const char* lua_func_name;
689 lua_CFunction c_func;
690 int lua_func;
691 } functions[] = {
692 {"activateTab", termit_lua_activateTab, 0},
693 {"addMenu", termit_lua_addMenu, 0},
694 {"addPopupMenu", termit_lua_addPopupMenu, 0},
695 {"bindKey", termit_lua_bindKey, 0},
696 {"bindMouse", termit_lua_bindMouse, 0},
697 {"closeTab", termit_lua_closeTab, 0},
698 {"copy", termit_lua_copy, 0},
699 {"currentTab", termit_lua_currentTab, 0},
700 {"currentTabIndex", termit_lua_currentTabIndex, 0},
701 {"feed", termit_lua_feed, 0},
702 {"feedChild", termit_lua_feedChild, 0},
703 {"findDlg", termit_lua_findDlg, 0},
704 {"findNext", termit_lua_findNext, 0},
705 {"findPrev", termit_lua_findPrev, 0},
706 {"forEachRow", termit_lua_forEachRow, 0},
707 {"forEachVisibleRow", termit_lua_forEachVisibleRow, 0},
708 {"loadSessionDlg", termit_lua_loadSessionDialog, 0},
709 {"nextTab", termit_lua_nextTab, 0},
710 {"openTab", termit_lua_openTab, 0},
711 {"paste", termit_lua_paste, 0},
712 {"preferencesDlg", termit_lua_preferencesDialog, 0},
713 {"prevTab", termit_lua_prevTab, 0},
714 {"quit", termit_lua_quit, 0},
715 {"reconfigure", termit_lua_reconfigure, 0},
716 {"saveSessionDlg", termit_lua_saveSessionDialog, 0},
717 {"selection", termit_lua_selection, 0},
718 {"setColormap", termit_lua_setColormap, 0},
719 {"setEncoding", termit_lua_setEncoding, 0},
720 {"setKbPolicy", termit_lua_setKbPolicy, 0},
721 {"setOptions", termit_lua_setOptions, 0},
722 {"setTabBackgroundColor", termit_lua_setTabBackgroundColor, 0},
723 {"setTabFont", termit_lua_setTabFont, 0},
724 {"setTabForegroundColor", termit_lua_setTabForegroundColor, 0},
725 {"setTabPos", termit_lua_setTabPos, 0},
726 {"setTabTitle", termit_lua_setTabTitle, 0},
727 {"setTabTitleDlg", termit_lua_setTabTitleDialog, 0},
728 {"setWindowTitle", termit_lua_setWindowTitle, 0},
729 {"spawn", termit_lua_spawn, 0},
730 {"toggleMenubar", termit_lua_toggleMenubar, 0},
731 {"toggleTabbar", termit_lua_toggleTabbar, 0}
732 };
733
termit_get_lua_func(const char * name)734 int termit_get_lua_func(const char* name)
735 {
736 unsigned short i = 0;
737 for (; i < sizeof(functions)/sizeof(functions[0]); ++i) {
738 if (strcmp(name, functions[i].lua_func_name) == 0) {
739 return functions[i].lua_func;
740 }
741 }
742 ERROR("not found lua function by name [%s]", name);
743 return 0;
744 }
745
746
termit_lua_init_api()747 void termit_lua_init_api()
748 {
749 unsigned short i = 0;
750 for (; i < sizeof(functions)/sizeof(functions[0]); ++i) {
751 lua_pushcfunction(L, functions[i].c_func);
752 functions[i].lua_func = luaL_ref(L, LUA_REGISTRYINDEX);
753 lua_rawgeti(L, LUA_REGISTRYINDEX, functions[i].lua_func);
754 lua_setglobal(L, functions[i].lua_func_name);
755 TRACE("%s [%d]", functions[i].lua_func_name, functions[i].lua_func);
756 }
757 }
758