📄 core.c
字号:
/* Lua interface (scripting engine) *//* $Id: core.c,v 1.173.4.12 2005/05/06 23:40:46 miciah Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <setjmp.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <lua.h>#include <lualib.h>#include "elinks.h"#include "bfu/dialog.h"#include "cache/cache.h"#include "config/kbdbind.h"#include "config/options.h"#include "config/opttypes.h"#include "document/document.h"#include "document/renderer.h"#include "document/view.h"#include "intl/gettext/libintl.h"#include "intl/charsets.h"#include "lowlevel/home.h"#include "lowlevel/signals.h"#include "modules/module.h"#include "protocol/uri.h"#include "sched/event.h"#include "sched/session.h"#include "sched/task.h"#include "scripting/lua/core.h"#include "scripting/lua/hooks.h"#include "scripting/scripting.h"#include "terminal/terminal.h"#include "util/color.h"#include "util/file.h"#include "util/memory.h"#include "util/string.h"#include "viewer/dump/dump.h"#include "viewer/text/view.h"#include "viewer/text/vs.h"#define LUA_HOOKS_FILENAME "hooks.lua"lua_State *lua_state;static struct session *lua_ses;static struct terminal *errterm;static sigjmp_buf errjmp;#define L lua_state#define LS lua_State *Sstatic void handle_standard_lua_returns(unsigned char *from);/* * Functions exported to the lua_State. */static intl_alert(LS){ alert_lua_error((unsigned char *) lua_tostring(S, 1)); return 0;}static intl_current_url(LS){ if (lua_ses && have_location(lua_ses)) { struct view_state *vs = &cur_loc(lua_ses)->vs; unsigned char *url = get_uri_string(vs->uri, URI_ORIGINAL); if (url) { lua_pushstring(S, url); mem_free(url); return 1; } } lua_pushnil(S); return 1;}static intl_current_link(LS){ struct link *link = get_current_session_link(lua_ses); if (link) { lua_pushstring(S, link->where); } else { lua_pushnil(S); } return 1;}static intl_current_title(LS){ struct document_view *doc_view = current_frame(lua_ses); if (doc_view && doc_view->document->title) { unsigned char *clean_title = stracpy(doc_view->document->title); if (clean_title) { int i = 0; while (clean_title[i]) { if (clean_title[i] < ' ' || clean_title[i] == NBSP_CHAR) clean_title[i] = ' '; i++; } lua_pushstring(S, clean_title); mem_free(clean_title); return 1; } } lua_pushnil(S); return 1;}static intl_current_document(LS){ if (lua_ses) { struct cache_entry *cached = find_in_cache(cur_loc(lua_ses)->vs.uri); struct fragment *f = cached ? cached->frag.next : NULL; if (f && f->length) { lua_pushlstring(S, f->data, f->length); return 1; } } lua_pushnil(S); return 1;}/* XXX: This function is mostly copied from `dump_to_file'. */static intl_current_document_formatted(LS){ struct document_view *doc_view; struct string buffer; int width, old_width = 0; if (lua_gettop(S) == 0) width = -1; else if (!lua_isnumber(S, 1)) goto lua_error; else if ((width = lua_tonumber(S, 1)) <= 0) goto lua_error; if (!lua_ses || !(doc_view = current_frame(lua_ses))) goto lua_error; if (width > 0) { old_width = lua_ses->tab->term->width; lua_ses->tab->term->width = width; render_document_frames(lua_ses, 0); } if (init_string(&buffer)) { add_document_to_string(&buffer, doc_view->document); lua_pushlstring(S, buffer.source, buffer.length); done_string(&buffer); } if (width > 0) { lua_ses->tab->term->width = old_width; render_document_frames(lua_ses, 0); } return 1;lua_error: lua_pushnil(S); return 1;}static intl_pipe_read(LS){ FILE *fp; unsigned char *s = NULL; int len = 0; if (!lua_isstring(S, 1)) goto lua_error; fp = popen(lua_tostring(S, 1), "r"); if (!fp) goto lua_error; while (!feof(fp)) { unsigned char buf[1024]; int l = fread(buf, 1, sizeof(buf), fp); if (l > 0) { s = mem_realloc(s, len + l); if (!s) goto lua_error; memcpy(s + len, buf, l); len += l; } else if (l < 0) { goto lua_error; } } pclose(fp); lua_pushlstring(S, s, len); mem_free_if(s); return 1;lua_error: mem_free_if(s); lua_pushnil(S); return 1;}static intl_execute(LS){ if (lua_isstring(S, 1)) { exec_on_terminal(lua_ses->tab->term, (unsigned char *) lua_tostring(S, 1), "", 0); lua_pushnumber(S, 0); return 1; } lua_pushnil(L); return 1;}static intl_tmpname(LS){ unsigned char *fn = tempnam(NULL, "elinks"); if (fn) { lua_pushstring(S, fn); free(fn); return 1; } alert_lua_error("Error generating temporary file name"); lua_pushnil(S); return 1;}static intl_enable_systems_functions(LS){ lua_iolibopen(S); lua_register(S, "pipe_read", l_pipe_read); lua_register(S, "execute", l_execute); lua_register(S, "tmpname", l_tmpname); return 0;}/* * Helper to run Lua functions bound to keystrokes. */static enum evhook_statusrun_lua_func(va_list ap, void *data){ struct session *ses = va_arg(ap, struct session *); int func_ref = (long) data; int err; if (func_ref == LUA_NOREF) { alert_lua_error("key bound to nothing (internal error)"); return EVENT_HOOK_STATUS_NEXT; } lua_getref(L, func_ref); if (prepare_lua(ses)) return EVENT_HOOK_STATUS_NEXT; err = lua_call(L, 0, 2); finish_lua(); if (!err) handle_standard_lua_returns("keyboard function"); return EVENT_HOOK_STATUS_NEXT;}static intl_bind_key(LS){ int ref; unsigned char *err; struct string event_name = NULL_STRING; int event_id; if (!lua_isstring(S, 1) || !lua_isstring(S, 2) || !lua_isfunction(S, 3)) { alert_lua_error("bad arguments to bind_key"); goto lua_error; } if (!init_string(&event_name)) goto lua_error; lua_pushvalue(S, 3); ref = lua_ref(S, 1); add_format_to_string(&event_name, "lua-run-func %i", ref); event_id = register_event(event_name.source); event_id = register_event_hook(event_id, run_lua_func, 0, (void *) (long) ref); done_string(&event_name); if (event_id == EVENT_NONE) goto lua_error; err = bind_scripting_func((unsigned char *) lua_tostring(S, 1), (unsigned char *) lua_tostring(S, 2), event_id); if (err) { lua_unref(S, ref); alert_lua_error2("error in bind_key: ", err); goto lua_error; } lua_pushnumber(S, 1); return 1;lua_error: lua_pushnil(S); return 1;}/* Begin very hackish bit for bookmark editing dialog. *//* XXX: Add history and generalise. */struct lua_dlg_data { lua_State *state; unsigned char cat[MAX_STR_LEN]; unsigned char name[MAX_STR_LEN]; unsigned char url[MAX_STR_LEN]; int func_ref;};static voiddialog_run_lua(void *data_){ struct lua_dlg_data *data = data_; lua_State *s = data->state; int err; lua_getref(s, data->func_ref); lua_pushstring(s, data->cat); lua_pushstring(s, data->name); lua_pushstring(s, data->url); if (prepare_lua(lua_ses)) return; err = lua_call(s, 3, 2); finish_lua(); lua_unref(s, data->func_ref); handle_standard_lua_returns("post dialog function");}static intl_edit_bookmark_dialog(LS){ struct terminal *term = lua_ses->tab->term; struct dialog *dlg; struct lua_dlg_data *data; if (!lua_isstring(S, 1) || !lua_isstring(S, 2) || !lua_isstring(S, 3) || !lua_isfunction(S, 4)) { lua_pushnil(S); return 1; }#define L_EDIT_BMK_WIDGETS_COUNT 5 dlg = calloc_dialog(L_EDIT_BMK_WIDGETS_COUNT, sizeof(*data)); if (!dlg) return 0; data = (struct lua_dlg_data *) get_dialog_offset(dlg, L_EDIT_BMK_WIDGETS_COUNT); data->state = S; safe_strncpy(data->cat, (unsigned char *) lua_tostring(S, 1), MAX_STR_LEN-1); safe_strncpy(data->name, (unsigned char *) lua_tostring(S, 2), MAX_STR_LEN-1); safe_strncpy(data->url, (unsigned char *) lua_tostring(S, 3), MAX_STR_LEN-1); lua_pushvalue(S, 4); data->func_ref = lua_ref(S, 1); dlg->title = _("Edit bookmark", term); dlg->layouter = generic_dialog_layouter; dlg->layout.maximize_width = 1; add_dlg_field(dlg, _("Name", term), 0, 0, NULL, MAX_STR_LEN, data->cat, NULL); add_dlg_field(dlg, _("Name", term), 0, 0, NULL, MAX_STR_LEN, data->name, NULL); add_dlg_field(dlg, _("URL", term), 0, 0, NULL, MAX_STR_LEN, data->url, NULL); add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, dialog_run_lua, data); add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL); add_dlg_end(dlg, L_EDIT_BMK_WIDGETS_COUNT); do_dialog(term, dlg, getml(dlg, NULL)); lua_pushnumber(S, 1); return 1;}/* End very hackish bit. *//* Begin hackish bit for half-generalised dialog. *//* XXX: Add history and custom labels. */#define XDIALOG_MAX_FIELDS 5struct lua_xdialog_data { lua_State *state; int func_ref; int nfields; unsigned char fields[XDIALOG_MAX_FIELDS][MAX_STR_LEN];};static voidxdialog_run_lua(void *data_){ struct lua_xdialog_data *data = data_; lua_State *s = data->state; int err; int i; lua_getref(s, data->func_ref); for (i = 0; i < data->nfields; i++) lua_pushstring(s, data->fields[i]); if (prepare_lua(lua_ses)) return; err = lua_call(s, data->nfields, 2); finish_lua(); lua_unref(s, data->func_ref); handle_standard_lua_returns("post xdialog function");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -