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

📄 inphist.c

📁 一个很有名的浏览器
💻 C
字号:
/* Input history for input fields. *//* $Id: inphist.c,v 1.91.4.2 2005/05/01 22:03:22 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#include "elinks.h"#include "bfu/dialog.h"#include "bfu/inphist.h"#include "bfu/menu.h"#include "config/options.h"#include "lowlevel/home.h"#include "terminal/terminal.h"#include "util/conv.h"#include "util/file.h"#include "util/lists.h"#include "util/memory.h"#include "util/secsave.h"static voidtab_compl_n(struct dialog_data *dlg_data, unsigned char *item, int len){	struct widget_data *widget_data = selected_widget(dlg_data);	assert(widget_is_textfield(widget_data));	int_upper_bound(&len, widget_data->widget->datalen - 1);	memcpy(widget_data->cdata, item, len);	widget_data->cdata[len] = 0;	widget_data->info.field.cpos = len;	widget_data->info.field.vpos = 0;	redraw_dialog(dlg_data, 1);}static voidtab_compl(struct dialog_data *dlg_data, unsigned char *item){	tab_compl_n(dlg_data, item, strlen(item));}/* menu_func */static voidmenu_tab_compl(struct terminal *term, void *item_, void *dlg_data_){	unsigned char *item = item_;	struct dialog_data *dlg_data = dlg_data_;	tab_compl_n(dlg_data, item, strlen(item));}/* Complete to last unambiguous character, and display menu for all possible * further completions. */voiddo_tab_compl(struct dialog_data *dlg_data, struct list_head *history){	struct terminal *term = dlg_data->win->term;	struct widget_data *widget_data = selected_widget(dlg_data);	int cdata_len = strlen(widget_data->cdata);	int n = 0;	struct input_history_entry *entry;	struct menu_item *items = new_menu(FREE_LIST | NO_INTL);	if (!items) return;	foreach (entry, *history) {		if (strncmp(widget_data->cdata, entry->data, cdata_len))			continue;		add_to_menu(&items, entry->data, NULL, ACT_MAIN_NONE,			    menu_tab_compl, entry->data, 0);		n++;	}	if (n > 1) {		do_menu_selected(term, items, dlg_data, n - 1, 0);	} else {		if (n == 1) tab_compl(dlg_data, items->data);		mem_free(items);	}}/* Complete to the last unambiguous character. Eg., I've been to google.com, * google.com/search?q=foo, and google.com/search?q=bar.  This function then * completes `go' to `google.com' and `google.com/' to `google.com/search?q='. */voiddo_tab_compl_unambiguous(struct dialog_data *dlg_data, struct list_head *history){	struct widget_data *widget_data = selected_widget(dlg_data);	int base_len = strlen(widget_data->cdata);	/* Maximum number of characters in a match. Characters after this	 * position are varying in other matches. Zero means that no max has	 * been set yet. */	int longest_common_match = 0;	unsigned char *match = NULL;	struct input_history_entry *entry;	foreach (entry, *history) {		unsigned char *cur = entry->data;		unsigned char *matchpos = match ? match : widget_data->cdata;		int cur_len = 0;		for (; *cur && *cur == *matchpos; ++cur, ++matchpos) {			++cur_len;			/* XXX: I think that unifying the two cases of this			 * test could seriously hurt readability. --pasky */			if (longest_common_match			    && cur_len >= longest_common_match)				break;		}		if (cur_len < base_len)			continue;		if (!match) cur_len = strlen(entry->data);		/* By now, @cur_len oscillates between @base_len and		 * @longest_common_match. */		if (longest_common_match		    && cur_len >= longest_common_match)			continue;		/* We found the next shortest common match. */		longest_common_match = cur_len;		match = entry->data;	}	if (!match) return;	tab_compl_n(dlg_data, match, longest_common_match);}/* Search for duplicate entries in history list, save first one and remove * older ones. */static struct input_history_entry *check_duplicate_entries(struct input_history *history, unsigned char *data){	struct input_history_entry *entry, *first_duplicate = NULL;	if (!history || !data || !*data) return NULL;	foreach (entry, history->entries) {		struct input_history_entry *duplicate;		if (strcmp(entry->data, data)) continue;		/* Found a duplicate -> remove it from history list */		duplicate = entry;		entry = entry->prev;		del_from_history_list(history, duplicate);		/* Save the first duplicate entry */		if (!first_duplicate) {			first_duplicate = duplicate;		} else {			mem_free(duplicate);		}	}	return first_duplicate;}/* Add a new entry in inputbox history list, take care of duplicate if * check_duplicate and respect history size limit. */voidadd_to_input_history(struct input_history *history, unsigned char *data,		     int check_duplicate){	struct input_history_entry *entry;	int length;	if (!history || !data || !*data)		return;	/* Strip spaces at the margins */	trim_chars(data, ' ', &length);	if (!length) return;	if (check_duplicate) {		entry = check_duplicate_entries(history, data);		if (entry) {			add_to_history_list(history, entry);			return;		}	}	/* Copy it all etc. */	/* One byte is already reserved for url in struct input_history_item. */	entry = mem_alloc(sizeof(*entry) + length);	if (!entry) return;	memcpy(entry->data, data, length + 1);	add_to_history_list(history, entry);	/* Limit size of history to MAX_INPUT_HISTORY_ENTRIES, removing first	 * entries if needed. */	while (history->size > MAX_INPUT_HISTORY_ENTRIES) {		if (list_empty(history->entries)) {			INTERNAL("history is empty");			history->size = 0;			return;		}		entry = history->entries.prev;		del_from_history_list(history, entry);		mem_free(entry);	}}/* Load history file */intload_input_history(struct input_history *history, unsigned char *filename){	unsigned char *history_file = filename;	unsigned char line[MAX_STR_LEN];	FILE *file;	if (get_cmd_opt_bool("anonymous")) return 0;	if (elinks_home) {		history_file = straconcat(elinks_home, filename, NULL);		if (!history_file) return 0;	}	file = fopen(history_file, "rb");	if (elinks_home) mem_free(history_file);	if (!file) return 0;	history->nosave = 1;	while (fgets(line, MAX_STR_LEN, file)) {		/* Drop '\n'. */		if (*line) line[strlen(line) - 1] = 0;		add_to_input_history(history, line, 0);	}	history->nosave = 0;	fclose(file);	return 0;}/* Write history list to file. It returns a value different from 0 in case of * failure, 0 on success. */intsave_input_history(struct input_history *history, unsigned char *filename){	struct input_history_entry *entry;	struct secure_save_info *ssi;	unsigned char *history_file;	int i = 0;	if (!history->dirty	    || !elinks_home	    || get_cmd_opt_bool("anonymous"))		return 0;	history_file = straconcat(elinks_home, filename, NULL);	if (!history_file) return -1;	ssi = secure_open(history_file, 0177);	mem_free(history_file);	if (!ssi) return -1;	foreachback (entry, history->entries) {		if (i++ > MAX_INPUT_HISTORY_ENTRIES) break;		secure_fputs(ssi, entry->data);		secure_fputc(ssi, '\n');		if (ssi->err) break;	}	if (!ssi->err) history->dirty = 0;	return secure_close(ssi);}voiddlg_set_history(struct widget_data *widget_data){	assert(widget_has_history(widget_data));	assert(widget_data->widget->datalen > 0);	if ((void *) widget_data->info.field.cur_hist != &widget_data->info.field.history) {		unsigned char *s = widget_data->info.field.cur_hist->data;		widget_data->info.field.cpos = int_min(strlen(s), widget_data->widget->datalen - 1);		if (widget_data->info.field.cpos)			memcpy(widget_data->cdata, s, widget_data->info.field.cpos);	} else {		widget_data->info.field.cpos = 0;	}	widget_data->cdata[widget_data->info.field.cpos] = 0;	widget_data->info.field.vpos = int_max(0, widget_data->info.field.cpos - widget_data->box.width);}

⌨️ 快捷键说明

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