?? link.c
字號(hào):
assert(doc_view && doc_view->vs); if_assert_failed return 0; link = get_current_link(doc_view); return (link && link_in_view(doc_view, link));}/* Look for the first and the last link currently visible in our * viewport. */static voidget_visible_links_range(struct document_view *doc_view, int *first, int *last){ struct document *document = doc_view->document; int height = int_min(doc_view->vs->y + doc_view->box.height, document->height); int y; *first = document->nlinks - 1; *last = 0; for (y = int_max(0, doc_view->vs->y); y < height; y++) { if (document->lines1[y]) int_upper_bound(first, document->lines1[y] - document->links); if (document->lines2[y]) int_lower_bound(last, document->lines2[y] - document->links); }}intnext_link_in_view(struct document_view *doc_view, int current, int direction, int (*fn)(struct document_view *, struct link *), void (*cntr)(struct document_view *, struct link *)){ struct document *document; struct view_state *vs; int start, end; assert(doc_view && doc_view->document && doc_view->vs && fn); if_assert_failed return 0; document = doc_view->document; vs = doc_view->vs; get_visible_links_range(doc_view, &start, &end); current_link_blur(doc_view); /* Go from the @current link in @direction until either * fn() is happy or we would leave the current viewport. */ while (current >= start && current <= end) { if (fn(doc_view, &document->links[current])) { vs->current_link = current; if (cntr) cntr(doc_view, &document->links[current]); current_link_hover(doc_view); return 1; } current += direction; } vs->current_link = -1; return 0;}/* Get the bounding columns of @link at line @y (or all lines if @y == -1). */static voidget_link_x_bounds(struct link *link, int y, int *min_x, int *max_x){ int point; if (min_x) *min_x = INT_MAX; if (max_x) *max_x = 0; for (point = 0; point < link->npoints; point++) { if (y >= 0 && link->points[point].y != y) continue; if (min_x) int_upper_bound(min_x, link->points[point].x); if (max_x) int_lower_bound(max_x, link->points[point].x); }}/* Check whether there is any point between @min_x and @max_x at the line @y * in link @link. */static intget_link_x_intersect(struct link *link, int y, int min_x, int max_x){ int point; for (point = 0; point < link->npoints; point++) { if (link->points[point].y != y) continue; if (link->points[point].x >= min_x && link->points[point].x <= max_x) return link->points[point].x + 1; } return 0;}/* Check whether there is any point between @min_y and @max_y in the column @x * in link @link. */static intget_link_y_intersect(struct link *link, int x, int min_y, int max_y){ int point; for (point = 0; point < link->npoints; point++) { if (link->points[point].x != x) continue; if (link->points[point].y >= min_y && link->points[point].y <= max_y) return link->points[point].y + 1; } return 0;}intnext_link_in_dir(struct document_view *doc_view, int dir_x, int dir_y){ struct document *document; struct view_state *vs; struct link *link; int min_x = INT_MAX, max_x = 0; int min_y, max_y; assert(doc_view && doc_view->document && doc_view->vs); if_assert_failed return 0; assert(dir_x || dir_y); if_assert_failed return 0; document = doc_view->document; vs = doc_view->vs; link = get_current_link(doc_view); if (!link) return 0; /* Find the link's "bounding box" coordinates. */ get_link_x_bounds(link, -1, &min_x, &max_x); min_y = link->points[0].y; max_y = link->points[link->npoints - 1].y; /* Now go from the bounding box edge in the appropriate * direction and find the nearest link. */ if (dir_y) { /* Vertical movement */ /* The current line number */ int y = (dir_y > 0 ? max_y : min_y) + dir_y; /* The bounding line numbers */ int top = int_max(0, doc_view->vs->y); int bottom = int_min(doc_view->vs->y + doc_view->box.height, document->height); for (; dir_y > 0 ? y < bottom : y >= top; y += dir_y) { /* @backup points to the nearest link from the left * to the desired position. */ struct link *backup = NULL; link = document->lines1[y]; if (!link) continue; /* Go through all the links on line. */ for (; link <= document->lines2[y]; link++) { int l_min_x, l_max_x; /* Some links can be totally out of order here, * ie. in tables or when using tabindex. */ if (y < link->points[0].y || y > link->points[link->npoints - 1].y) continue; get_link_x_bounds(link, y, &l_min_x, &l_max_x); if (l_min_x > max_x) { /* This link is too at the right. */ if (!backup) backup = link; continue; } if (l_max_x < min_x) { /* This link is too at the left. */ backup = link; continue; } /* This link is aligned with the current one. */ goto chose_link; } if (backup) { link = backup; goto chose_link; } } if (!y || y == document->height) { /* We just stay at the same place, do not invalidate * the link number. */ return 0; } } else { /* Horizontal movement */ /* The current column number */ int x = (dir_x > 0 ? max_x : min_x) + dir_x; /* How many lines are already past their last link */ int last = 0; while ((last < max_y - min_y + 1) && (x += dir_x) >= 0) { int y; last = 0; /* Go through all the lines */ for (y = min_y; y <= max_y; y++) { link = document->lines1[y]; if (!link) continue; /* Go through all the links on line. */ while (link <= document->lines2[y]) { if (get_link_y_intersect(link, x, min_y, max_y)) goto chose_link; link++; } /* Check if we already aren't past the last * link on this line. */ if (!get_link_x_intersect(document->lines2[y], y, x, INT_MAX)) last++; } } /* We just stay */ return 0; } current_link_blur(doc_view); vs->current_link = -1; return 0;chose_link: /* The link is in bounds, take it. */ current_link_blur(doc_view); vs->current_link = get_link_index(document, link); set_pos_x(doc_view, link); current_link_hover(doc_view); return 1;}voidset_pos_x(struct document_view *doc_view, struct link *link){ int xm = 0; int xl = INT_MAX; int i; assert(doc_view && link); if_assert_failed return; for (i = 0; i < link->npoints; i++) { int y = link->points[i].y - doc_view->vs->y; if (y >= 0 && y < doc_view->box.height) { int_lower_bound(&xm, link->points[i].x + 1); int_upper_bound(&xl, link->points[i].x); } } if (xl != INT_MAX) int_bounds(&doc_view->vs->x, xm - doc_view->box.width, xl);}voidset_pos_y(struct document_view *doc_view, struct link *link){ int ym = 0; int height; int i; assert(doc_view && doc_view->document && doc_view->vs && link); if_assert_failed return; height = doc_view->document->height; for (i = 0; i < link->npoints; i++) { int_lower_bound(&ym, link->points[i].y + 1); int_upper_bound(&height, link->points[i].y); } doc_view->vs->y = (ym + height - doc_view->box.height) / 2; int_bounds(&doc_view->vs->y, 0, doc_view->document->height - doc_view->box.height);}/* direction == 1 -> DOWN * direction == -1 -> UP */static voidfind_link(struct document_view *doc_view, int direction, int page_mode){ struct link **line; struct link *link = NULL; int link_pos; int y, ymin, ymax; assert(doc_view && doc_view->document && doc_view->vs); if_assert_failed return; if (direction == -1) { /* UP */ line = doc_view->document->lines2; if (!line) goto nolink; y = doc_view->vs->y + doc_view->box.height - 1; int_upper_bound(&y, doc_view->document->height - 1); if (y < 0) goto nolink; } else { /* DOWN */ line = doc_view->document->lines1; if (!line) goto nolink; y = doc_view->vs->y; int_lower_bound(&y, 0); if (y >= doc_view->document->height) goto nolink; } ymin = int_max(0, doc_view->vs->y); ymax = int_min(doc_view->document->height, doc_view->vs->y + doc_view->box.height); if (direction == -1) { /* UP */ do { struct link *cur = line[y--]; if (cur && (!link || cur > link)) link = cur; } while (y >= ymin && y < ymax); } else { /* DOWN */ do { struct link *cur = line[y++]; if (cur && (!link || cur < link)) link = cur; } while (y >= ymin && y < ymax); } if (!link) goto nolink; link_pos = link - doc_view->document->links; if (page_mode) { /* PAGE */ next_link_in_view(doc_view, link_pos, direction, link_in_view, NULL); return; } current_link_blur(doc_view); doc_view->vs->current_link = link_pos; set_pos_x(doc_view, link); current_link_hover(doc_view); return;nolink: current_link_blur(doc_view); doc_view->vs->current_link = -1;}voidfind_link_up(struct document_view *doc_view){ find_link(doc_view, -1, 0);}voidfind_link_page_up(struct document_view *doc_view){ find_link(doc_view, -1, 1);}voidfind_link_down(struct document_view *doc_view){ find_link(doc_view, 1, 0);}voidfind_link_page_down(struct document_view *doc_view){ find_link(doc_view, 1, 1);}struct uri *get_link_uri(struct session *ses, struct document_view *doc_view, struct link *link){ assert(ses && doc_view && link); if_assert_failed return NULL; switch (link->type) { case LINK_HYPERTEXT: case LINK_MAP: if (link->where) return get_uri(link->where, 0); return get_uri(link->where_img, 0); case LINK_BUTTON: case LINK_FIELD: return get_form_uri(ses, doc_view, get_link_form_control(link)); default: return NULL; }}struct link *goto_current_link(struct session *ses, struct document_view *doc_view, int do_reload){ struct link *link; struct uri *uri; assert(doc_view && ses); if_assert_failed return NULL; link = get_current_link(doc_view); if (!link) return NULL; if (link_is_form(link)) uri = get_form_uri(ses, doc_view, get_link_form_control(link)); else
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -