core.c
来自「elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, el」· C语言 代码 · 共 893 行 · 第 1/2 页
C
893 行
/* Lua interface (scripting engine) */#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/home.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/charsets.h"#include "intl/gettext/libintl.h"#include "main/event.h"#include "main/module.h"#include "osdep/signals.h"#include "protocol/uri.h"#include "scripting/lua/core.h"#include "session/location.h"#include "session/session.h"#include "session/task.h"#include "terminal/terminal.h"#include "util/color.h"#include "util/conv.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);static void handle_ref(LS, struct session *ses, int func_ref, unsigned char *from, int num_args, int unref);/* * 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) { sanitize_title(clean_title); 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; size_t 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]; size_t 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;}/* * 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; if (func_ref == LUA_NOREF) { alert_lua_error("key bound to nothing (internal error)"); return EVENT_HOOK_STATUS_NEXT; } handle_ref(L, ses, func_ref, "keyboard function", 0, 0); return EVENT_HOOK_STATUS_NEXT;}static intl_bind_key(LS){ int ref; int event_id; unsigned char *err = NULL; struct string event_name = NULL_STRING; 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 = luaL_ref(S, LUA_REGISTRYINDEX); add_format_to_string(&event_name, "lua-run-func %i", ref); event_id = bind_key_to_event_name((unsigned char *) lua_tostring(S, 1), (unsigned char *) lua_tostring(S, 2), event_name.source, &err); done_string(&event_name); if (!err) { event_id = register_event_hook(event_id, run_lua_func, 0, (void *) (long) ref); if (event_id == EVENT_NONE) err = gettext("Error registering event hook"); } if (err) { luaL_unref(S, LUA_REGISTRYINDEX, 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; lua_pushstring(s, data->cat); lua_pushstring(s, data->name); lua_pushstring(s, data->url); handle_ref(s, lua_ses, data->func_ref, "post dialog function", 3, 1);}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 = luaL_ref(S, LUA_REGISTRYINDEX); 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 i; for (i = 0; i < data->nfields; i++) lua_pushstring(s, data->fields[i]); handle_ref(s, lua_ses, data->func_ref, "post xdialog function", data->nfields, 1);}static intl_xdialog(LS){ struct terminal *term; struct dialog *dlg; struct lua_xdialog_data *data; int nargs, nfields, nitems; int i = 0; if (!lua_ses) return 0; term = lua_ses->tab->term; nargs = lua_gettop(S); nfields = nargs - 1; nitems = nfields + 2; if ((nfields < 1) || (nfields > XDIALOG_MAX_FIELDS)) goto lua_error; for (i = 1; i < nargs; i++) if (!lua_isstring(S, i)) goto lua_error; if (!lua_isfunction(S, nargs)) goto lua_error; dlg = calloc_dialog(nitems, sizeof(*data)); if (!dlg) return 0; data = (struct lua_xdialog_data *) get_dialog_offset(dlg, nitems); data->state = S; data->nfields = nfields; for (i = 0; i < nfields; i++) safe_strncpy(data->fields[i], (unsigned char *) lua_tostring(S, i+1), MAX_STR_LEN-1); lua_pushvalue(S, nargs); data->func_ref = luaL_ref(S, LUA_REGISTRYINDEX);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?