📄 view.c
字号:
/* HTML viewer (and much more) *//* $Id: view.c,v 1.665.2.8 2005/05/05 23:48:58 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "elinks.h"#include "bfu/leds.h"#include "bfu/menu.h"#include "bfu/dialog.h"#include "config/kbdbind.h"#include "config/options.h"#include "dialogs/document.h"#include "dialogs/menu.h"#include "dialogs/options.h"#include "dialogs/status.h"#include "document/document.h"#include "document/html/frames.h"#include "document/options.h"#include "document/renderer.h"#include "document/view.h"#include "intl/charsets.h"#include "intl/gettext/libintl.h"#include "osdep/osdep.h"#include "protocol/uri.h"#include "sched/action.h"#include "sched/download.h"#include "sched/event.h"#include "sched/location.h"#include "sched/session.h"#include "sched/task.h"#include "terminal/draw.h"#include "terminal/event.h"#include "terminal/kbd.h"#include "terminal/mouse.h"#include "terminal/tab.h"#include "terminal/terminal.h"#include "terminal/window.h"#include "util/color.h"#include "util/conv.h"#include "util/error.h"#include "util/memory.h"#include "util/snprintf.h"#include "util/string.h"#include "viewer/dump/dump.h"#include "viewer/text/draw.h"#include "viewer/text/form.h"#include "viewer/text/link.h"#include "viewer/text/marks.h"#include "viewer/text/search.h"#include "viewer/text/textarea.h"#include "viewer/text/view.h"#include "viewer/text/vs.h"voiddetach_formatted(struct document_view *doc_view){ assert(doc_view); if_assert_failed return; if (doc_view->document) { release_document(doc_view->document); doc_view->document = NULL; } if (doc_view->vs) { doc_view->vs->doc_view = NULL; doc_view->vs = NULL; } if (doc_view->link_bg) free_link(doc_view); mem_free_set(&doc_view->name, NULL);}/* type == 0 -> PAGE_DOWN * type == 1 -> DOWN */static enum frame_event_statusmove_down(struct session *ses, struct document_view *doc_view, int type){ int newpos; assert(ses && doc_view && doc_view->vs); if_assert_failed return FRAME_EVENT_OK; ses->navigate_mode = NAVIGATE_LINKWISE; /* XXX: why here and not in move_up() ??? */ newpos = doc_view->vs->y + doc_view->box.height; if (newpos < doc_view->document->height) doc_view->vs->y = newpos; if (current_link_is_visible(doc_view)) return FRAME_EVENT_REFRESH; if (type) find_link_down(doc_view); else find_link_page_down(doc_view); return FRAME_EVENT_REFRESH;}enum frame_event_statusmove_page_down(struct session *ses, struct document_view *doc_view){ enum frame_event_status status; int count; count = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; do { status = move_down(ses, doc_view, 0); if (status != FRAME_EVENT_REFRESH) break; } while (--count > 0); return status;}/* type == 0 -> PAGE_UP * type == 1 -> UP */static enum frame_event_statusmove_up(struct session *ses, struct document_view *doc_view, int type){ assert(ses && doc_view && doc_view->vs); if_assert_failed return FRAME_EVENT_OK; if (doc_view->vs->y == 0) return FRAME_EVENT_OK; doc_view->vs->y -= doc_view->box.height; int_lower_bound(&doc_view->vs->y, 0); if (current_link_is_visible(doc_view)) return FRAME_EVENT_REFRESH; if (type) find_link_up(doc_view); else find_link_page_up(doc_view); return FRAME_EVENT_REFRESH;}enum frame_event_statusmove_page_up(struct session *ses, struct document_view *doc_view){ enum frame_event_status status; int count; count = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; do { status = move_up(ses, doc_view, 0); if (status != FRAME_EVENT_REFRESH) break; } while (--count > 0); return status;}enum frame_event_statusmove_link(struct session *ses, struct document_view *doc_view, int direction, int wraparound_bound, int wraparound_link){ int wraparound = 0; int count; assert(ses && doc_view && doc_view->vs && doc_view->document); if_assert_failed return FRAME_EVENT_OK; ses->navigate_mode = NAVIGATE_LINKWISE; if (doc_view->document->nlinks == 0) { /* There are no links, therefore the only sensible value for * wraparound_bound is -1 (no link selected). */ wraparound_bound = -1; } else { /* We only bother this option is there's some links * in document. */ wraparound = get_opt_bool("document.browse.links.wraparound"); } count = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; do { int current_link = doc_view->vs->current_link; if (current_link == wraparound_bound) { if (wraparound) { jump_to_link_number(ses, doc_view, wraparound_link); /* FIXME: This needs further work, we should call * page_down() and set_textarea() under some conditions * as well. --pasky */ continue; } } else { if (next_link_in_view(doc_view, current_link + direction, direction, link_in_view_y, set_pos_x)) continue; } /* This is a work around for the case where the index of * @wraparound_bound is not necessarily the index of the first * or the last link in the view. It means that the link moving * could end up calling next_link_in_view() in the condition * above. This is bad because next_link_in_view() will then * 'reset' doc_view->vs->current_link to -1 and the effect will * be that the current link will 'wrap around'. By restoring * the index of the @current_link nothing will be wrapped * around and move_{up,down} will take care of finding the next * link. */ doc_view->vs->current_link = current_link; if (direction > 0) { move_down(ses, doc_view, 1); } else { move_up(ses, doc_view, 1); } if (current_link != wraparound_bound && current_link != doc_view->vs->current_link) { set_textarea(doc_view, -direction); } } while (--count > 0); return FRAME_EVENT_REFRESH;}enum frame_event_statusmove_link_dir(struct session *ses, struct document_view *doc_view, int dir_x, int dir_y){ int count; assert(ses && doc_view && doc_view->vs && doc_view->document); if_assert_failed return FRAME_EVENT_OK; ses->navigate_mode = NAVIGATE_LINKWISE; count = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; do { int current_link = doc_view->vs->current_link; if (next_link_in_dir(doc_view, dir_x, dir_y)) continue; /* FIXME: This won't preserve the column! */ if (dir_y > 0) move_down(ses, doc_view, 1); else if (dir_y < 0) move_up(ses, doc_view, 1); if (dir_y && current_link != doc_view->vs->current_link) { set_textarea(doc_view, -dir_y); } } while (--count > 0); return FRAME_EVENT_REFRESH;}/* @steps > 0 -> down */static enum frame_event_statusvertical_scroll(struct session *ses, struct document_view *doc_view, int steps){ int y; assert(ses && doc_view && doc_view->vs && doc_view->document); if_assert_failed return FRAME_EVENT_OK; y = doc_view->vs->y + steps; if (steps > 0) { /* DOWN */ int max_height = doc_view->document->height - doc_view->box.height; if (doc_view->vs->y >= max_height) return FRAME_EVENT_OK; int_upper_bound(&y, max_height); } int_lower_bound(&y, 0); if (doc_view->vs->y == y) return FRAME_EVENT_OK; doc_view->vs->y = y; if (current_link_is_visible(doc_view)) return FRAME_EVENT_REFRESH; if (steps > 0) find_link_page_down(doc_view); else find_link_page_up(doc_view); return FRAME_EVENT_REFRESH;}/* @steps > 0 -> right */static enum frame_event_statushorizontal_scroll(struct session *ses, struct document_view *doc_view, int steps){ int x, max; assert(ses && doc_view && doc_view->vs && doc_view->document); if_assert_failed return FRAME_EVENT_OK; x = doc_view->vs->x + steps; if (get_opt_bool("document.browse.scrolling.horizontal_extended")) { max = doc_view->document->width - 1; } else { max = int_max(doc_view->vs->x, doc_view->document->width - doc_view->box.width); } int_bounds(&x, 0, max); if (doc_view->vs->x == x) return FRAME_EVENT_OK; doc_view->vs->x = x; if (current_link_is_visible(doc_view)) return FRAME_EVENT_REFRESH; find_link_page_down(doc_view); return FRAME_EVENT_REFRESH;}enum frame_event_statusscroll_up(struct session *ses, struct document_view *doc_view){ int steps = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; if (!steps) steps = get_opt_int("document.browse.scrolling.vertical_step"); return vertical_scroll(ses, doc_view, -steps);}enum frame_event_statusscroll_down(struct session *ses, struct document_view *doc_view){ int steps = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; if (!steps) steps = get_opt_int("document.browse.scrolling.vertical_step"); return vertical_scroll(ses, doc_view, steps);}enum frame_event_statusscroll_left(struct session *ses, struct document_view *doc_view){ int steps = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; if (!steps) steps = get_opt_int("document.browse.scrolling.horizontal_step"); return horizontal_scroll(ses, doc_view, -steps);}enum frame_event_statusscroll_right(struct session *ses, struct document_view *doc_view){ int steps = ses->kbdprefix.repeat_count; ses->kbdprefix.repeat_count = 0; if (!steps) steps = get_opt_int("document.browse.scrolling.horizontal_step"); return horizontal_scroll(ses, doc_view, steps);}#ifdef CONFIG_MOUSEstatic enum frame_event_statusscroll_mouse_up(struct session *ses, struct document_view *doc_view){ int steps = get_opt_int("document.browse.scrolling.vertical_step"); return vertical_scroll(ses, doc_view, -steps);}static enum frame_event_statusscroll_mouse_down(struct session *ses, struct document_view *doc_view){ int steps = get_opt_int("document.browse.scrolling.vertical_step"); return vertical_scroll(ses, doc_view, steps);}static enum frame_event_statusscroll_mouse_left(struct session *ses, struct document_view *doc_view){ int steps = get_opt_int("document.browse.scrolling.horizontal_step"); return horizontal_scroll(ses, doc_view, -steps);}static enum frame_event_statusscroll_mouse_right(struct session *ses, struct document_view *doc_view){ int steps = get_opt_int("document.browse.scrolling.horizontal_step"); return horizontal_scroll(ses, doc_view, steps);}#endif /* CONFIG_MOUSE */enum frame_event_statusmove_document_start(struct session *ses, struct document_view *doc_view){ assert(ses && doc_view && doc_view->vs); if_assert_failed return FRAME_EVENT_OK; doc_view->vs->y = doc_view->vs->x = 0; if (ses->navigate_mode == NAVIGATE_CURSOR_ROUTING) { /* Move to the first line and the first column. */ move_cursor(ses, doc_view, doc_view->box.x, doc_view->box.y); } else { find_link_page_down(doc_view); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -