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 + -
显示快捷键?