📄 hooks.c
字号:
/* Ruby scripting hooks *//* $Id: hooks.c,v 1.7.2.1 2005/01/29 02:06:29 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <ruby.h>#include "elinks.h"#include "protocol/uri.h"#include "sched/event.h"#include "sched/session.h"#include "scripting/ruby/core.h"#include "scripting/ruby/hooks.h"#include "util/string.h"/* The events that will trigger the functions below and what they are expected * to do is explained in doc/events.txt *//* We need to catch and handle errors because, otherwise, Ruby will kill us. */struct erb_protect_info { unsigned char *name; int argc; VALUE *args;};static VALUEdo_erb_protected_method_call(VALUE data){ struct erb_protect_info *info = (struct erb_protect_info *) data; ID method_id; assert(info); method_id = rb_intern(info->name); return rb_funcall3(erb_module, method_id, info->argc, info->args);}static VALUEerb_protected_method_call(unsigned char *name, int argc, VALUE *args, int *error){ struct erb_protect_info info = { name, argc, args }; return rb_protect(do_erb_protected_method_call, (VALUE) &info, error);}static enum evhook_statusscript_hook_goto_url(va_list ap, void *data){ unsigned char **url = va_arg(ap, unsigned char **); struct session *ses = va_arg(ap, struct session *); int error; VALUE args[2]; VALUE result; if (*url == NULL) return EVENT_HOOK_STATUS_NEXT; args[0] = rb_str_new2(*url); if (!ses || !have_location(ses)) { args[1] = Qnil; } else { args[1] = rb_str_new2(struri(cur_loc(ses)->vs.uri)); } result = erb_protected_method_call("goto_url_hook", 2, args, &error); if (error) { erb_report_error(ses, error); return EVENT_HOOK_STATUS_NEXT; } switch (rb_type(result)) { case T_STRING: { unsigned char *new_url; new_url = memacpy(RSTRING(result)->ptr, RSTRING(result)->len); if (new_url) { mem_free(*url); *url = new_url; } break; } case T_NIL: break; default: alert_ruby_error(ses, "goto_url_hook must return a string or nil"); } return EVENT_HOOK_STATUS_NEXT;}static enum evhook_statusscript_hook_follow_url(va_list ap, void *data){ unsigned char **url = va_arg(ap, unsigned char **); struct session *ses = va_arg(ap, struct session *); int error; VALUE args[1]; VALUE result; evhook_use_params(url && ses); if (*url == NULL) return EVENT_HOOK_STATUS_NEXT; args[0] = rb_str_new2(*url); result = erb_protected_method_call("follow_url_hook", 1, args, &error); if (error) { erb_report_error(ses, error); return EVENT_HOOK_STATUS_NEXT; } switch (rb_type(result)) { case T_STRING: { unsigned char *new_url; new_url = memacpy(RSTRING(result)->ptr, RSTRING(result)->len); if (new_url) { mem_free(*url); *url = new_url; } break; } case T_NIL: break; default: alert_ruby_error(ses, "follow_url_hook must return a string or nil"); } return EVENT_HOOK_STATUS_NEXT;}static enum evhook_statusscript_hook_pre_format_html(va_list ap, void *data){ unsigned char **html = va_arg(ap, unsigned char **); int *html_len = va_arg(ap, int *); struct session *ses = va_arg(ap, struct session *); unsigned char *url = va_arg(ap, unsigned char *); int error; VALUE args[2]; VALUE result; evhook_use_params(url && ses); if (*html == NULL || *html_len == 0) return EVENT_HOOK_STATUS_NEXT; args[0] = rb_str_new2(url); /* FIXME: Use html_len */ args[1] = rb_str_new2(*html); result = erb_protected_method_call("pre_format_html_hook", 2, args, &error); if (error) { erb_report_error(ses, error); return EVENT_HOOK_STATUS_NEXT; } switch (rb_type(result)) { case T_STRING: { unsigned char *new_html; new_html = memacpy(RSTRING(result)->ptr, RSTRING(result)->len); if (new_html) { *html_len = RSTRING(result)->len; *html = new_html; } break; } case T_NIL: break; default: alert_ruby_error(ses, "pre_format_html_hook must return a string or nil"); } return EVENT_HOOK_STATUS_NEXT;}/* The Ruby function can return: * - "PROXY:PORT" to use the specified proxy * - "" to not use any proxy * - nil to use the default proxies */static enum evhook_statusscript_hook_get_proxy(va_list ap, void *data){ unsigned char **new_proxy_url = va_arg(ap, unsigned char **); unsigned char *url = va_arg(ap, unsigned char *); int error; VALUE args[1]; VALUE result; if (!new_proxy_url || !url) return EVENT_HOOK_STATUS_NEXT; args[0] = rb_str_new2(url); result = erb_protected_method_call("proxy_hook", 1, args, &error); if (error) { erb_report_error(NULL, error); return EVENT_HOOK_STATUS_NEXT; } switch (rb_type(result)) { case T_STRING: { unsigned char *proxy; proxy = memacpy(RSTRING(result)->ptr, RSTRING(result)->len); if (proxy) { *new_proxy_url = proxy; } break; } case T_NIL: break; default: alert_ruby_error(NULL, "proxy_hook must return a string or nil"); } return EVENT_HOOK_STATUS_NEXT;}static enum evhook_statusscript_hook_quit(va_list ap, void *data){ VALUE args[1]; int error; erb_protected_method_call("quit_hook", 0, args, &error); if (error) erb_report_error(NULL, error); return EVENT_HOOK_STATUS_NEXT;}struct event_hook_info ruby_scripting_hooks[] = { { "goto-url", script_hook_goto_url, NULL }, { "follow-url", script_hook_follow_url, NULL }, { "pre-format-html", script_hook_pre_format_html, NULL }, { "get-proxy", script_hook_get_proxy, NULL }, { "quit", script_hook_quit, NULL }, NULL_EVENT_HOOK_INFO,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -