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

📄 textarea.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Textarea form item handlers *//* $Id: textarea.c,v 1.143.2.2 2005/05/01 22:03:23 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifndef _GNU_SOURCE#define _GNU_SOURCE /* XXX: we want memrchr() ! */#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "elinks.h"#include "bfu/dialog.h"#include "document/document.h"#include "document/forms.h"#include "document/html/parser.h"#include "document/html/renderer.h"#include "document/view.h"#include "intl/gettext/libintl.h"#include "sched/session.h"#include "terminal/draw.h"#include "terminal/window.h"#include "util/error.h"#include "util/file.h"#include "util/memory.h"#include "util/string.h"#include "viewer/text/form.h"#include "viewer/text/textarea.h"#include "viewer/text/view.h"struct line_info {	int start;	int end;};/* We add two extra entries to the table so the ending info can be added * without reallocating. */#define realloc_line_info(info, size) \	mem_align_alloc(info, size, (size) + 3, struct line_info, 0xFF)/* Allocates a line_info table describing the layout of the textarea buffer. * * @width	is max width and the offset at which text will be wrapped * @wrap	controls how the wrapping of text is performed * @format	is non zero the @text will be modified to make it suitable for *		encoding it for form posting */static struct line_info *format_text(unsigned char *text, int width, enum form_wrap wrap, int format){	struct line_info *line = NULL;	int line_number = 0;	int begin = 0;	int pos = 0;	int skip;	assert(text);	if_assert_failed return NULL;	/* Allocate the ending entries */	if (!realloc_line_info(&line, 0))		return NULL;	while (text[pos]) {		if (text[pos] == '\n') {			skip = 1;		} else if (wrap == FORM_WRAP_NONE || pos - begin < width) {			pos++;			continue;		} else {			unsigned char *wrappos;			/* Find a place to wrap the text */			wrappos = memrchr(&text[begin], ' ', pos - begin);			if (wrappos) {				/* When formatting text for form submitting we				 * have to apply the wrapping mode. */				if (wrap == FORM_WRAP_HARD && format)					*wrappos = '\n';				pos = wrappos - text;			}			skip = !!wrappos;		}		if (!realloc_line_info(&line, line_number)) {			mem_free_if(line);			return NULL;		}		line[line_number].start = begin;		line[line_number++].end = pos;		begin = pos += skip;	}	/* Flush the last text before the loop ended */	line[line_number].start = begin;	line[line_number++].end = pos;	/* Add end marker */	line[line_number].start = line[line_number].end = -1;	return line;}/* Searches for @cursor_position (aka. position in the fs->value string) for * the corresponding entry in the @line info. Returns the index or -1 if * position is not found. */static intget_textarea_line_number(struct line_info *line, int cursor_position){	int idx;	for (idx = 0; line[idx].start != -1; idx++) {		int wrap;		if (cursor_position < line[idx].start) continue;		wrap = (line[idx + 1].start == line[idx].end);		if (cursor_position >= line[idx].end + !wrap) continue;		return idx;	}	return -1;}/* Fixes up the vpos and vypos members of the form_state. Returns the * logical position in the textarea view. */intarea_cursor(struct form_control *fc, struct form_state *fs){	struct line_info *line;	int x, y;	assert(fc && fs);	if_assert_failed return 0;	line = format_text(fs->value, fc->cols, fc->wrap, 0);	if (!line) return 0;	y = get_textarea_line_number(line, fs->state);	if (y == -1) {		mem_free(line);		return 0;	}	x = fs->state - line[y].start;	mem_free(line);	if (fc->wrap && x == fc->cols) x--;	int_bounds(&fs->vpos, x - fc->cols + 1, x);	int_bounds(&fs->vypos, y - fc->rows + 1, y);	x -= fs->vpos;	y -= fs->vypos;	return y * fc->cols + x;}voiddraw_textarea(struct terminal *term, struct form_state *fs,	      struct document_view *doc_view, struct link *link){	struct line_info *line, *linex;	struct form_control *fc;	struct box *box;	int vx, vy;	int sl, ye;	int x, y;	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;	box = &doc_view->box;	vx = doc_view->vs->x;	vy = doc_view->vs->y;	if (!link->npoints) return;	area_cursor(fc, fs);	linex = format_text(fs->value, fc->cols, fc->wrap, 0);	if (!linex) return;	line = linex;	sl = fs->vypos;	while (line->start != -1 && sl) sl--, line++;	x = link->points[0].x + box->x - vx;	y = link->points[0].y + box->y - vy;	ye = y + fc->rows;	for (; line->start != -1 && y < ye; line++, y++) {		int i;		if (!row_is_in_box(box, y)) continue;		for (i = 0; i < fc->cols; i++) {			unsigned char data;			int xi = x + i;			if (!col_is_in_box(box, xi))				continue;			if (i >= -fs->vpos			    && i + fs->vpos < line->end - line->start)				data = fs->value[line->start + i + fs->vpos];			else				data = '_';			draw_char_data(term, xi, y, data);		}	}	for (; y < ye; y++) {		int i;		if (!row_is_in_box(box, y)) continue;		for (i = 0; i < fc->cols; i++) {			int xi = x + i;			if (col_is_in_box(box, xi))				draw_char_data(term, xi, y, '_');		}	}	mem_free(linex);}unsigned char *encode_textarea(struct submitted_value *sv){	struct form_control *fc;	struct string newtext;	void *blabla;	int i;	assert(sv && sv->value);	if_assert_failed return NULL;	fc = sv->form_control;	/* We need to reformat text now if it has to be wrapped hard, just	 * before encoding it. */	blabla = format_text(sv->value, fc->cols, fc->wrap, 1);	mem_free_if(blabla);	if (!init_string(&newtext)) return NULL;	for (i = 0; sv->value[i]; i++) {		if (sv->value[i] != '\n')			add_char_to_string(&newtext, sv->value[i]);		else			add_crlf_to_string(&newtext);	}	return newtext.source;}/* We use some evil hacking in order to make external textarea editor working. * We need to have some way how to be notified that the editor finished and we * should reload content of the textarea.  So we use global variable * textarea_editor as a flag whether we have one running, and if we have, we * just call textarea_edit(1, ...).  Then we recover our state from static * variables, reload content of textarea back from file and clean up. * * Unfortunately, we can't support calling of editor from non-master links * session, as it would be extremely ugly to hack (you would have to transfer * the content of it back to master somehow, add special flags for not deleting * of 'delete' etc) and I'm not going to do that now. Inter-links communication * *NEEDS* rewrite, as it looks just like quick messy hack now. --pasky */int textarea_editor = 0;static unsigned char *save_textarea_file(unsigned char *value){	unsigned char *filename;	FILE *file = NULL;	int h;	filename = get_tempdir_filename("elinks-area-XXXXXX");	if (!filename) return NULL;	h = safe_mkstemp(filename);	if (h >= 0) file = fdopen(h, "w");	if (file) {		fwrite(value, strlen(value), 1, file);		fclose(file);	} else {		mem_free(filename);	}	return filename;}static unsigned char *load_textarea_file(unsigned char *filename, int maxlength){	unsigned char *value = NULL;	FILE *file = fopen(filename, "rb+");	int filelen = -1;	if (!file) return NULL;	if (!fseek(file, 0, SEEK_END)) {		filelen = ftell(file);		if (filelen != -1 && fseek(file, 0, SEEK_SET))			filelen = -1;	}	if (filelen >= 0 && filelen <= maxlength) {		int bread;		value = mem_alloc(filelen + 1);		if (value) {			bread = fread(value, 1, filelen, file);			value[bread] = 0;		}	}	fclose(file);

⌨️ 快捷键说明

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