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

📄 form.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Forms viewing/manipulation handling *//* $Id: form.c,v 1.264.2.5 2005/04/06 08:59:39 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifndef _GNU_SOURCE#define _GNU_SOURCE /* XXX: we want memrchr() ! */#endif#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h> /* OS/2 needs this after sys/types.h */#endif#include "elinks.h"#include "bfu/listmenu.h"#include "bfu/dialog.h"#include "config/kbdbind.h"#include "dialogs/menu.h"#include "document/document.h"#include "document/forms.h"#include "document/html/parser.h"#include "document/view.h"#include "intl/gettext/libintl.h"#include "formhist/formhist.h"#include "mime/mime.h"#include "osdep/ascii.h"#include "osdep/osdep.h"#include "protocol/uri.h"#include "sched/action.h"#include "sched/session.h"#include "terminal/terminal.h"#include "terminal/window.h"#include "util/conv.h"#include "util/error.h"#include "util/file.h"#include "util/memory.h"#include "util/string.h"#include "viewer/text/draw.h"#include "viewer/text/form.h"#include "viewer/text/link.h"#include "viewer/text/textarea.h"#include "viewer/text/view.h"#include "viewer/text/vs.h"/* TODO: Some of these (particulary those encoding routines) would feel better * in viewer/common/. --pasky */struct submitted_value *init_submitted_value(unsigned char *name, unsigned char *value, enum form_type type,		     struct form_control *fc, int position){	struct submitted_value *sv;	sv = mem_alloc(sizeof(*sv));	if (!sv) return NULL;	sv->value = stracpy(value);	if (!sv->value) { mem_free(sv); return NULL; }	sv->name = stracpy(name);	if (!sv->name) { mem_free(sv->value); mem_free(sv); return NULL; }	sv->type = type;	sv->form_control = fc;	sv->position = position;	return sv;}voiddone_submitted_value(struct submitted_value *sv){	if (!sv) return;	mem_free_if(sv->value);	mem_free_if(sv->name);	mem_free(sv);}static voidfixup_select_state(struct form_control *fc, struct form_state *fs){	int i;	assert(fc && fs);	if_assert_failed return;	if (fs->state >= 0	    && fs->state < fc->nvalues	    && !strcmp(fc->values[fs->state], fs->value))		return;	for (i = 0; i < fc->nvalues; i++)		if (!strcmp(fc->values[i], fs->value)) {			fs->state = i;			return;		}	fs->state = 0;	mem_free_set(&fs->value, stracpy(fc->nvalues					 ? fc->values[0]					 : (unsigned char *) ""));}/* menu_func */voidselected_item(struct terminal *term, void *item_, void *ses_){	struct session *ses = ses_;	int item = (long) item_;	struct document_view *doc_view;	struct link *link;	struct form_state *fs;	struct form_control *fc;	assert(term && ses);	if_assert_failed return;	doc_view = current_frame(ses);	assert(doc_view && doc_view->vs && doc_view->document);	if_assert_failed return;	link = get_current_link(doc_view);	if (!link || link->type != LINK_SELECT) return;	fc = get_link_form_control(link);	fs = find_form_state(doc_view, fc);	if (fs) {		if (item >= 0 && item < fc->nvalues) {			fs->state = item;			mem_free_set(&fs->value, stracpy(fc->values[item]));		}		fixup_select_state(fc, fs);	}	refresh_view(ses, doc_view, 0);}static voidinit_form_state(struct form_control *fc, struct form_state *fs){	assert(fc && fs);	if_assert_failed return;	mem_free_set(&fs->value, NULL);	switch (fc->type) {		case FC_TEXT:		case FC_PASSWORD:		case FC_TEXTAREA:			fs->value = stracpy(fc->default_value);			fs->state = strlen(fc->default_value);			fs->vpos = 0;			break;		case FC_FILE:			fs->value = stracpy("");			fs->state = 0;			fs->vpos = 0;			break;		case FC_SELECT:			fs->value = stracpy(fc->default_value);			fs->state = fc->default_state;			fixup_select_state(fc, fs);			break;		case FC_CHECKBOX:		case FC_RADIO:			fs->state = fc->default_state;			/* Fall-through */		case FC_SUBMIT:		case FC_IMAGE:		case FC_RESET:		case FC_BUTTON:		case FC_HIDDEN:			fs->value = stracpy(fc->default_value);			break;	}}struct form_state *find_form_state(struct document_view *doc_view, struct form_control *fc){	struct view_state *vs;	struct form_state *fs;	int n;	assert(doc_view && doc_view->vs && fc);	if_assert_failed return NULL;	vs = doc_view->vs;	n = fc->g_ctrl_num;	if (n >= vs->form_info_len) {		int nn = n + 1;		fs = mem_realloc(vs->form_info, nn * sizeof(*fs));		if (!fs) return NULL;		memset(fs + vs->form_info_len, 0,		       (nn - vs->form_info_len) * sizeof(*fs));		vs->form_info = fs;		vs->form_info_len = nn;	}	fs = &vs->form_info[n];	if (fs->form_view && fs->form_view->form_num == fc->form->form_num	    && fs->g_ctrl_num == fc->g_ctrl_num	    && fs->position == fc->position	    && fs->type == fc->type)		return fs;	mem_free_if(fs->value);	memset(fs, 0, sizeof(*fs));	fs->form_view = find_form_view(doc_view, fc->form);	fs->g_ctrl_num = fc->g_ctrl_num;	fs->position = fc->position;	fs->type = fc->type;	init_form_state(fc, fs);	return fs;}struct form_control *find_form_control(struct document *document, struct form_state *fs){	struct form *form = find_form_by_form_view(document, fs->form_view);	struct form_control *fc;	foreach (fc, form->items) {		if (fs->g_ctrl_num == fc->g_ctrl_num		    && fs->position == fc->position		    && fs->type == fc->type)			return fc;	}	return NULL;}struct form_view *find_form_view_in_vs(struct view_state *vs, int form_num){	struct form_view *fv;	assert(vs);	foreach (fv, vs->forms)		if (fv->form_num == form_num)			return fv;	fv = mem_calloc(1, sizeof(*fv));	fv->form_num = form_num;	add_to_list(vs->forms, fv);	return fv;}struct form_view *find_form_view(struct document_view *doc_view, struct form *form){	return find_form_view_in_vs(doc_view->vs, form->form_num);}struct form *find_form_by_form_view(struct document *document, struct form_view *fv){	struct form *form;	foreach (form, document->forms) {		if (form->form_num == fv->form_num)			return form;	}	return NULL;}intget_current_state(struct session *ses){	struct document_view *doc_view;	struct link *link;	struct form_state *fs;	assert(ses);	if_assert_failed return -1;	doc_view = current_frame(ses);	assert(doc_view && doc_view->vs && doc_view->document);	if_assert_failed return -1;	link = get_current_link(doc_view);	if (!link || link->type != LINK_SELECT) return -1;	fs = find_form_state(doc_view, get_link_form_control(link));	if (fs) return fs->state;	return -1;}voiddraw_form_entry(struct terminal *term, struct document_view *doc_view,		struct link *link){	struct form_state *fs;	struct form_control *fc;	struct view_state *vs;	struct box *box;	int dx, dy;	assert(term && doc_view && doc_view->document && doc_view->vs && link);	if_assert_failed return;	fc = get_link_form_control(link);	assertm(fc, "link %d has no form control", (int) (link - doc_view->document->links));	if_assert_failed return;	fs = find_form_state(doc_view, fc);	if (!fs) return;	box = &doc_view->box;	vs = doc_view->vs;	dx = box->x - vs->x;	dy = box->y - vs->y;	switch (fc->type) {		unsigned char *s;		int len;		int i, x, y;		case FC_TEXT:		case FC_PASSWORD:		case FC_FILE:			int_bounds(&fs->vpos, fs->state - fc->size + 1, fs->state);			if (!link->npoints) break;			y = link->points[0].y + dy;			if (!row_is_in_box(box, y))				break;			len = strlen(fs->value) - fs->vpos;			x = link->points[0].x + dx;			for (i = 0; i < fc->size; i++, x++) {				unsigned char data;				if (!col_is_in_box(box, x)) continue;				if (fs->value && i >= -fs->vpos && i < len)					data = fc->type != FC_PASSWORD					     ? fs->value[i + fs->vpos] : '*';				else					data = '_';				draw_char_data(term, x, y, data);			}			break;		case FC_TEXTAREA:			draw_textarea(term, fs, doc_view, link);			break;		case FC_CHECKBOX:		case FC_RADIO:			if (link->npoints < 2) break;			x = link->points[1].x + dx;			y = link->points[1].y + dy;			if (is_in_box(box, x, y))				draw_char_data(term, x, y, fs->state ? 'X' : ' ');			break;		case FC_SELECT:			fixup_select_state(fc, fs);			if (fs->state < fc->nvalues)				s = fc->labels[fs->state];			else				/* XXX: when can this happen? --pasky */				s = "";			len = s ? strlen(s) : 0;			for (i = 0; i < link->npoints; i++) {				x = link->points[i].x + dx;				y = link->points[i].y + dy;				if (is_in_box(box, x, y))					draw_char_data(term, x, y, i < len ? s[i] : '_');			}			break;		case FC_SUBMIT:		case FC_IMAGE:		case FC_RESET:		case FC_BUTTON:		case FC_HIDDEN:			break;	}}voiddraw_forms(struct terminal *term, struct document_view *doc_view){	struct link *l1, *l2;	assert(term && doc_view);	if_assert_failed return;	l1 = get_first_link(doc_view);	l2 = get_last_link(doc_view);	if (!l1 || !l2) {		assertm(!l1 && !l2, "get_first_link == %p, get_last_link == %p", l1, l2);		/* Return path :-). */		return;	}	do {		struct form_control *fc = get_link_form_control(l1);		if (!fc) continue;#ifdef CONFIG_FORMHIST		if (fc->type == FC_TEXT || fc->type == FC_PASSWORD) {			unsigned char *value;			assert(fc->form);			value = get_form_history_value(fc->form->action, fc->name);			if (value)				mem_free_set(&fc->default_value,					     stracpy(value));		}#endif /* CONFIG_FORMHIST */		draw_form_entry(term, doc_view, l1);	} while (l1++ < l2);}voiddone_submitted_value_list(struct list_head *list){	struct submitted_value *sv, *svtmp;	assert(list);	if_assert_failed return;	foreach (sv, *list) {		svtmp = sv;		sv = sv->prev;		del_from_list(svtmp);		done_submitted_value(svtmp);	}}static voidadd_submitted_value_to_list(struct form_control *fc,		            struct form_state *fs,		            struct list_head *list){	struct submitted_value *sub;	unsigned char *name;	enum form_type type;	int position;	assert(fc && fs && list);	name = fc->name;	position = fc->position;	type = fc->type;	switch (fc->type) {	case FC_TEXT:	case FC_PASSWORD:	case FC_FILE:	case FC_TEXTAREA:		sub = init_submitted_value(name, fs->value, type, fc, position);		if (sub) add_to_list(*list, sub);		break;	case FC_CHECKBOX:	case FC_RADIO:		if (!fs->state) break;		/* fall through */	case FC_SUBMIT:	case FC_HIDDEN:	case FC_RESET:	case FC_BUTTON:		sub = init_submitted_value(name, fs->value, type, fc,					   position);		if (sub) add_to_list(*list, sub);		break;	case FC_SELECT:		if (!fc->nvalues) break;		fixup_select_state(fc, fs);		sub = init_submitted_value(name, fs->value, type, fc, position);		if (sub) add_to_list(*list, sub);		break;	case FC_IMAGE:	        name = straconcat(fc->name, ".x", NULL);		if (!name) break;		sub = init_submitted_value(name, "0", type, fc, position);		mem_free(name);		if (sub) add_to_list(*list, sub);		name = straconcat(fc->name, ".y", NULL);		if (!name) break;		sub = init_submitted_value(name, "0", type, fc, position);		mem_free(name);		if (sub) add_to_list(*list, sub);		break;	}}static voidsort_submitted_values(struct list_head *list){	int changed;	do {		struct submitted_value *sub, *next;		changed = 0;		foreach (sub, *list) if (list_has_next(*list, sub))			if (sub->next->position < sub->position) {				next = sub->next;				del_from_list(sub);				add_at_pos(next, sub);				sub = next;				changed = 1;			}

⌨️ 快捷键说明

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