⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, elinks也是gentoo安装过程中默认使用的浏览器, 这是elinks源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	txt = case_sensitive ? stracpy(*doc_view->search_word)			     : lowered_string(*doc_view->search_word, l);	if (!txt) return;	box = &doc_view->box;	xoffset = box->x - doc_view->vs->x;	yoffset = box->y - doc_view->vs->y;#define maybe_tolower(c) (case_sensitive ? (c) : tolower(c))	for (; s1 <= s2; s1++) {		int i;		if (maybe_tolower(s1[0].c) != txt[0]) {srch_failed:			continue;		}		for (i = 1; i < l; i++)			if (maybe_tolower(s1[i].c) != txt[i])				goto srch_failed;		for (i = 0; i < l; i++) {			int j;			int y = s1[i].y + yoffset;			if (!row_is_in_box(box, y))				continue;			for (j = 0; j < s1[i].n; j++) {				int sx = s1[i].x + j;				int x = sx + xoffset;				if (!col_is_in_box(box, x))					continue;				if (!realloc_points(&points, len))					continue;				points[len].x = sx;				points[len++].y = s1[i].y;			}		}	}#undef maybe_tolower	mem_free(txt);	*pt = points;	*pl = len;}#ifdef HAVE_REGEX_Hstruct get_searched_regex_context {	int xoffset;	int yoffset;	struct box *box;	struct point *points;	int len;};static voidget_searched_regex_match(struct regex_match_context *common_ctx, void *data){	struct get_searched_regex_context *ctx = data;	int i;	for (i = 0; i < common_ctx->textlen; i++) {		int j;		int y = common_ctx->s1[i].y + ctx->yoffset;		if (!row_is_in_box(ctx->box, y))			continue;		for (j = 0; j < common_ctx->s1[i].n; j++) {			int sx = common_ctx->s1[i].x + j;			int x = sx + ctx->xoffset;			if (!col_is_in_box(ctx->box, x))				continue;			if (!realloc_points(&ctx->points, ctx->len))				continue;			ctx->points[ctx->len].x = sx;			ctx->points[ctx->len++].y = common_ctx->s1[i].y;		}	}}static voidget_searched_regex(struct document_view *doc_view, struct point **pt, int *pl,		   int textlen, struct search *s1, struct search *s2){	struct regex_match_context common_ctx;	struct get_searched_regex_context ctx;	ctx.points = NULL;	ctx.len = 0;	ctx.box = &doc_view->box;	ctx.xoffset = ctx.box->x - doc_view->vs->x;	ctx.yoffset = ctx.box->y - doc_view->vs->y;	common_ctx.found = 0;	common_ctx.textlen = textlen;	common_ctx.y1 = doc_view->vs->y - 1;	common_ctx.y2 = doc_view->vs->y + ctx.box->height;	common_ctx.pattern = *doc_view->search_word;	common_ctx.s1 = s1;	common_ctx.s2 = s2;	search_for_pattern(&common_ctx, &ctx, get_searched_regex_match);	*pt = ctx.points;	*pl = ctx.len;}#endif /* HAVE_REGEX_H */static voidget_searched(struct document_view *doc_view, struct point **pt, int *pl){	struct search *s1, *s2;	int l;	assert(doc_view && doc_view->vs && pt && pl);	if_assert_failed return;	if (!has_search_word(doc_view))		return;	get_search_data(doc_view->document);	l = strlen(*doc_view->search_word);	if (get_range(doc_view->document, doc_view->vs->y,		      doc_view->box.height, l, &s1, &s2)) {		*pt = NULL;		*pl = 0;		return;	}#ifdef HAVE_REGEX_H	if (get_opt_int("document.browse.search.regex"))		get_searched_regex(doc_view, pt, pl, l, s1, s2);	else#endif		get_searched_plain(doc_view, pt, pl, l, s1, s2);}/* Highlighting of searched strings. */voiddraw_searched(struct terminal *term, struct document_view *doc_view){	struct point *pt = NULL;	int len = 0;	assert(term && doc_view);	if_assert_failed return;	if (!has_search_word(doc_view))		return;	get_searched(doc_view, &pt, &len);	if (len) {		int i;		struct color_pair *color = get_bfu_color(term, "searched");		int xoffset = doc_view->box.x - doc_view->vs->x;		int yoffset = doc_view->box.y - doc_view->vs->y;		for (i = 0; i < len; i++) {			int x = pt[i].x + xoffset;			int y = pt[i].y + yoffset;			/* TODO: We should take in account original colors and			 * combine them with defined color. */#if 0			/* This piece of code shows the old way of handling			 * colors and screen char attributes. */			unsigned co = get_char(term, x, y);			co = ((co >> 3) & 0x0700) | ((co << 3) & 0x3800);#endif			draw_char_color(term, x, y, color);		}	}	mem_free_if(pt);}enum find_error {	FIND_ERROR_NONE,	FIND_ERROR_NO_PREVIOUS_SEARCH,	FIND_ERROR_HIT_TOP,	FIND_ERROR_HIT_BOTTOM,	FIND_ERROR_NOT_FOUND,	FIND_ERROR_MEMORY,	FIND_ERROR_REGEX,};static enum find_error find_next_do(struct session *ses,				    struct document_view *doc_view,				    int direction);static void print_find_error(struct session *ses, enum find_error find_error);static enum find_errorsearch_for_do(struct session *ses, unsigned char *str, int direction,	      int report_errors){	struct document_view *doc_view;	enum find_error error;	assert(ses && str);	if_assert_failed return FIND_ERROR_NOT_FOUND;	doc_view = current_frame(ses);	assert(doc_view);	if_assert_failed return FIND_ERROR_NOT_FOUND;	mem_free_set(&ses->search_word, NULL);	mem_free_set(&ses->last_search_word, NULL);	if (!*str) return FIND_ERROR_NOT_FOUND;	/* We only set the last search word because we don.t want find_next()	 * to try to find next link in search before the search data has been	 * initialized. find_next() will set ses->search_word for us. */	ses->last_search_word = stracpy(str);	if (!ses->last_search_word) return FIND_ERROR_NOT_FOUND;	ses->search_direction = direction;	error = find_next_do(ses, doc_view, 1);	if (report_errors)		print_find_error(ses, error);	return error;}static voidsearch_for_back(struct session *ses, unsigned char *str){	assert(ses && str);	if_assert_failed return;	search_for_do(ses, str, -1, 1);}static voidsearch_for(struct session *ses, unsigned char *str){	assert(ses && str);	if_assert_failed return;	search_for_do(ses, str, 1, 1);}static inline intpoint_intersect(struct point *p1, int l1, struct point *p2, int l2){#define HASH_SIZE	4096#define HASH(p) ((((p).y << 6) + (p).x) & (HASH_SIZE - 1))	int i;	static char hash[HASH_SIZE];	static int first_time = 1;	assert(p2);	if_assert_failed return 0;	if (first_time) memset(hash, 0, HASH_SIZE), first_time = 0;	for (i = 0; i < l1; i++) hash[HASH(p1[i])] = 1;	for (i = 0; i < l2; i++) {		int j;		if (!hash[HASH(p2[i])]) continue;		for (j = 0; j < l1; j++) {			if (p1[j].x != p2[i].x) continue;			if (p1[j].y != p2[i].y) continue;			for (i = 0; i < l1; i++)				hash[HASH(p1[i])] = 0;			return 1;		}	}	for (i = 0; i < l1; i++) hash[HASH(p1[i])] = 0;	return 0;#undef HASH#undef HASH_SIZE}static intfind_next_link_in_search(struct document_view *doc_view, int direction){	assert(doc_view && doc_view->vs);	if_assert_failed return 0;	if (direction == -2 || direction == 2) {		direction /= 2;		if (direction < 0)			find_link_page_up(doc_view);		else			find_link_page_down(doc_view);		if (doc_view->vs->current_link == -1) return 1;		goto nt;	}	while (doc_view->vs->current_link != -1	       && next_link_in_view(doc_view, doc_view->vs->current_link + direction,	                            direction)) {		struct point *pt = NULL;		struct link *link;		int len;nt:		link = &doc_view->document->links[doc_view->vs->current_link];		get_searched(doc_view, &pt, &len);		if (point_intersect(pt, len, link->points, link->npoints)) {			mem_free(pt);			return 0;		}		mem_free_if(pt);	}	if (direction < 0)		find_link_page_up(doc_view);	else		find_link_page_down(doc_view);	return 1;}static enum find_errorfind_next_do(struct session *ses, struct document_view *doc_view, int direction){	int p, min, max, c = 0;	int step, hit_bottom = 0, hit_top = 0;	int height;	assert(ses && ses->tab && ses->tab->term && doc_view && doc_view->vs	       && direction);	if_assert_failed return FIND_ERROR_NONE;	direction *= ses->search_direction;	p = doc_view->vs->y;	height = doc_view->box.height;	step = direction * height;	if (ses->search_word) {		if (!find_next_link_in_search(doc_view, direction))			return FIND_ERROR_NONE;		p += step;	}	if (!ses->search_word) {		if (!ses->last_search_word) {			return FIND_ERROR_NO_PREVIOUS_SEARCH;		}		ses->search_word = stracpy(ses->last_search_word);		if (!ses->search_word) return FIND_ERROR_NONE;	}	get_search_data(doc_view->document);	do {		int in_range = is_in_range(doc_view->document, p, height,					   ses->search_word, &min, &max);		if (in_range == -1) return FIND_ERROR_MEMORY;		if (in_range == -2) return FIND_ERROR_REGEX;		if (in_range) {			doc_view->vs->y = p;			if (max >= min)				doc_view->vs->x = int_min(int_max(doc_view->vs->x,								  max - doc_view->box.width),								  min);			set_link(doc_view);			find_next_link_in_search(doc_view, direction * 2);			if (hit_top)				return FIND_ERROR_HIT_TOP;			if (hit_bottom)				return FIND_ERROR_HIT_BOTTOM;			return FIND_ERROR_NONE;		}		p += step;		if (p > doc_view->document->height) {			hit_bottom = 1;			p = 0;		}		if (p < 0) {			hit_top = 1;			p = 0;			while (p < doc_view->document->height) p += height;			p -= height;		}		c += height;	} while (c < doc_view->document->height + height);	return FIND_ERROR_NOT_FOUND;}static voidprint_find_error_not_found(struct session *ses, unsigned char *title,			   unsigned char *message, unsigned char *search_string){	switch (get_opt_int("document.browse.search.show_not_found")) {		case 2:			info_box(ses->tab->term, MSGBOX_FREE_TEXT,				 title, ALIGN_CENTER,				 msg_text(ses->tab->term, message,					  search_string));			break;		case 1:			beep_terminal(ses->tab->term);		default:			break;	}}static voidprint_find_error(struct session *ses, enum find_error find_error){	int hit_top = 0;	unsigned char *message = NULL;	switch (find_error) {		case FIND_ERROR_HIT_TOP:			hit_top = 1;		case FIND_ERROR_HIT_BOTTOM:			if (!get_opt_bool("document.browse.search"					  ".show_hit_top_bottom"))				break;			message = hit_top				 ? N_("Search hit top, continuing at bottom.")				 : N_("Search hit bottom, continuing at top.");			break;		case FIND_ERROR_NO_PREVIOUS_SEARCH:			message = N_("No previous search");			break;		case FIND_ERROR_NOT_FOUND:			print_find_error_not_found(ses, N_("Search"),						   N_("Search string"						      " '%s' not found"),						   ses->search_word);			break;		case FIND_ERROR_REGEX:			print_find_error_not_found(ses, N_("Search"),						   N_("Could not compile"						      " regular expression"						      " '%s'"),						   ses->search_word);			break;		case FIND_ERROR_MEMORY:			/* Why bother trying to create a msg_box?			 * We probably don't have the memory... */		case FIND_ERROR_NONE:			break;	}	if (!message) return;	info_box(ses->tab->term, 0, N_("Search"), ALIGN_CENTER, message);}enum frame_event_statusfind_next(struct session *ses, struct document_view *doc_view, int direction){	print_find_error(ses, find_next_do(ses, doc_view, direction));	/* FIXME: Make this more fine-grained */	return FRAME_EVENT_REFRESH;}/* Link typeahead */enum typeahead_code {	TYPEAHEAD_MATCHED,	TYPEAHEAD_ERROR,	TYPEAHEAD_ERROR_NO_FURTHER,	TYPEAHEAD_CANCEL,};static voidtypeahead_error(struct session *ses, unsigned char *typeahead, int no_further){	unsigned char *message;	if (no_further)		message = N_("No further matches for '%s'.");	else		message = N_("Could not find a link with the text '%s'.");	print_find_error_not_found(ses, N_("Typeahead"), message, typeahead);}static inline unsigned char *get_link_typeahead_text(struct link *link){	unsigned char *name = get_link_name(link);	if (name) return name;	if (link->where) return link->where;	if (link->where_img) return link->where_img;	return "";}static intmatch_link_text(struct link *link, unsigned char *text, int textlen,		int case_sensitive){	unsigned char *match = get_link_typeahead_text(link);	unsigned char *matchpos;	if (link_is_form(link) || textlen > strlen(match))		return -1;	matchpos = case_sensitive ? strstr(match, text)				  : strcasestr(match, text);	if (matchpos) {		return matchpos - match;	}	return -1;}/* Searches the @document for a link with the given @text. takes the * current_link in the view, the link to start searching from @i and the * direction to search (1 is forward, -1 is back). */static inline intsearch_link_text(struct document *document, int current_link, int i,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -