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

📄 edit.c

📁 具有IDE功能的编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* editor low level data handling and cursor fundamentals.   Copyright (C) 1996-2000 the Free Software Foundation      Authors: 1996, 1997 Paul Sheer   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307, USA.*/#define _EDIT_C THIS_IS#include <config.h>#if defined(NEEDS_IO_H)#    include <io.h>#    include <fcntl.h>#    define CR_LF_TRANSLATION#endif#include "edit.h"#ifdef SCO_FLAVOR#	include <sys/timeb.h>#endif /* SCO_FLAVOR */#include <time.h>	/* for ctime() */#if defined (HAVE_MAD) && ! defined (MIDNIGHT) && ! defined (GTK)#include "mad.h"#endif/* * * here's a quick sketch of the layout: (don't run this through indent.) *  * (b1 is buffers1 and b2 is buffers2) *  *                                       | * \0\0\0\0\0m e _ f i l e . \nf i n . \n|T h i s _ i s _ s o\0\0\0\0\0\0\0\0\0 * ______________________________________|______________________________________ *                                       | * ...  |  b2[2]   |  b2[1]   |  b2[0]   |  b1[0]   |  b1[1]   |  b1[2]   | ... *      |->        |->        |->        |->        |->        |->        | *                                       | *           _<------------------------->|<----------------->_ *                   WEdit->curs2        |   WEdit->curs1 *           ^                           |                   ^ *           |                          ^|^                  | *         cursor                       |||                cursor *                                      ||| *                              file end|||file beginning *                                       | *                                       | *  *           _ * This_is_some_file * fin. * * *//*   returns a byte from any location in the file.   Returns '\n' if out of bounds. */static int push_action_disabled = 0;#ifdef NO_INLINE_GETBYTEint edit_get_byte (WEdit * edit, long byte_index){    unsigned long p;    if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0)	return '\n';    if (byte_index >= edit->curs1) {	p = edit->curs1 + edit->curs2 - byte_index - 1;	return edit->buffers2[p >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1];    } else {	return edit->buffers1[byte_index >> S_EDIT_BUF_SIZE][byte_index & M_EDIT_BUF_SIZE];    }}#endifchar *edit_get_buffer_as_text (WEdit * e){    int l, i;    char *t;    l = e->curs1 + e->curs2;    t = CMalloc (l + 1);    for (i = 0; i < l; i++)	t[i] = edit_get_byte (e, i);    t[l] = 0;    return t;}/* Note on CRLF->LF translation: */#if MY_O_TEXT#error MY_O_TEXT is depreciated. CR_LF_TRANSLATION must be defined which does CR-LF translation internally. See note in source.#endif/*    The edit_open_file (previously edit_load_file) function uses   init_dynamic_edit_buffers to load a file. This is unnecessary   since you can just as well fopen the file and insert the   characters one by one. The real reason for   init_dynamic_edit_buffers (besides allocating the buffers) is   as an optimisation - it uses raw block reads and inserts large   chunks at a time. It is hence extremely fast at loading files.   Where we might not want to use it is if we were doing   CRLF->LF translation or if we were reading from a pipe. *//* Initialisation routines *//* returns 1 on error *//* loads file OR text into buffers. Only one must be none-NULL. *//* cursor set to start of file *//* FIXME: implement proper error handling on failed reads */int init_dynamic_edit_buffers (WEdit * edit, const char *filename, const char *text){    long buf;    int j, file = -1, buf2;    for (j = 0; j <= MAXBUFF; j++) {	edit->buffers1[j] = NULL;	edit->buffers2[j] = NULL;    }    if (filename)	if ((file = open ((char *) filename, O_RDONLY)) == -1) {/* The file-name is printed after the ':' */	    edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open file for reading: "), filename, " ", 0)));	    return 1;	}    edit->curs2 = edit->last_byte;    buf2 = edit->curs2 >> S_EDIT_BUF_SIZE;    edit->buffers2[buf2] = CMalloc (EDIT_BUF_SIZE);    if (filename) {	readall (file, (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE), edit->curs2 & M_EDIT_BUF_SIZE);    } else {	memcpy (edit->buffers2[buf2] + EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE), text, edit->curs2 & M_EDIT_BUF_SIZE);	text += edit->curs2 & M_EDIT_BUF_SIZE;    }    for (buf = buf2 - 1; buf >= 0; buf--) {	edit->buffers2[buf] = CMalloc (EDIT_BUF_SIZE);	if (filename) {	    readall (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE);	} else {	    memcpy (edit->buffers2[buf], text, EDIT_BUF_SIZE);	    text += EDIT_BUF_SIZE;	}    }    edit->curs1 = 0;    if (file != -1)	close (file);    return 0;}/* detecting an error on save is easy: just check if every byte has been written. *//* detecting an error on read, is not so easy 'cos there is not way to tell   whether you read everything or not. *//* FIXME: add proper `triple_pipe_open' to read, write and check errors. */static struct edit_filters {    char *read, *write, *extension;} all_filters[] = {    {	"bzip2 -cd %s", "bzip2 > %s", ".bz2"    },    {	"gzip -cd %s", "gzip > %s", ".gz"    },    {	"compress -cd %s", "compress > %s", ".Z"    }};static int edit_find_filter (const char *filename){    int i, l;    if (!filename)	return -1;    l = strlen (filename);    for (i = 0; i < sizeof (all_filters) / sizeof (struct edit_filters); i++) {	int e;	e = strlen (all_filters[i].extension);	if (l > e)	    if (!strcmp (all_filters[i].extension, filename + l - e))		return i;    }    return -1;}char *edit_get_filter (const char *filename){    int i, l;    char *p;    i = edit_find_filter (filename);    if (i < 0)	return 0;    l = strlen (filename);    p = malloc (strlen (all_filters[i].read) + l + 2);    sprintf (p, all_filters[i].read, filename);    return p;}char *edit_get_write_filter (char *writename, char *filename){    int i, l;    char *p;    i = edit_find_filter (filename);    if (i < 0)	return 0;    l = strlen (writename);    p = malloc (strlen (all_filters[i].write) + l + 2);    sprintf (p, all_filters[i].write, writename);    return p;}#ifdef CR_LF_TRANSLATION/* reads into buffer, replace \r\n with \n */long edit_insert_stream (WEdit * edit, FILE * f){    int a = -1, b;    long i;    while ((b = fgetc (f)) >= 0) {	if (a == '\r' && b == '\n') {	    edit_insert (edit, '\n');	    i++;	    a = -1;	    continue;	} else if (a >= 0) {	    edit_insert (edit, a);	    i++;	}	a = b;    }    if (a >= 0)	edit_insert (edit, a);    return i;}/* writes buffer, replaces, replace \n with \r\n */long edit_write_stream (WEdit * edit, FILE * f){    long i;    int c;    for (i = 0; i < edit->last_byte; i++) {	c = edit_get_byte (edit, i);	if (c == '\n') {	    if (fputc ('\r', f) < 0)		break;	    if (fputc ('\n', f) < 0)		break;	} else {	    if (fputc (c, f) < 0)		break;	}    }    return i;}#elselong edit_insert_stream (WEdit * edit, int fd){    int len;    long total = 0;    for (;;) {	char *p, *q;	len = 8192;	q = p = read_pipe (fd, &len);	if (!len) {	    free (p);	    return total;	}	total += len;	while (len--)	    edit_insert (edit, *p++);	free (q);    }    return total;}long edit_write_stream (WEdit * edit, FILE * f){    long i;    for (i = 0; i < edit->last_byte; i++) {	int r;	while ((r = fputc (edit_get_byte (edit, i), f)) == -1 && errno == EINTR);	if (r < 0)	    break;    }    return i;}#endif#define TEMP_BUF_LEN 1024/* inserts a file at the cursor, returns 1 on success */int edit_insert_file (WEdit * edit, const char *filename){    char *p;    if ((p = edit_get_filter (filename))) {	long current = edit->curs1;	int f, g;	char *a[8];	a[0] = "/bin/sh";	a[1] = "-c";	a[2] = p;	a[3] = 0;	if (triple_pipe_open (0, &f, &g, 0, "sh", a) > 0) {	    edit_insert_stream (edit, f);	    edit_cursor_move (edit, current - edit->curs1);	    free (p);	    p = read_pipe (g, 0);	    if (strlen (p)) {		edit_error_dialog (_ (" Error "), catstrs (_ (" Error reading from pipe: "), p, " ", 0));		free (p);		close (f);		close (g);		return 0;	    }	    close (f);	    close (g);	} else {	    edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open pipe for reading: "), p, " ", 0)));	    free (p);	    return 0;	}	free (p);#ifdef CR_LF_TRANSLATION    } else {	FILE *f;	long current = edit->curs1;	f = fopen (filename, "r");	if (f) {	    edit_insert_stream (edit, f);	    edit_cursor_move (edit, current - edit->curs1);	    if (fclose (f)) {		edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Error reading file: "), filename, " ", 0)));		return 0;	    }	} else {	    edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open file for reading: "), filename, " ", 0)));	    return 0;	}#else    } else {	int i, file, blocklen;	long current = edit->curs1;	unsigned char *buf;	if ((file = open ((char *) filename, O_RDONLY)) == -1)	    return 0;	buf = malloc (TEMP_BUF_LEN);	while ((blocklen = read (file, (char *) buf, TEMP_BUF_LEN)) > 0) {	    for (i = 0; i < blocklen; i++)		edit_insert (edit, buf[i]);	}	edit_cursor_move (edit, current - edit->curs1);	free (buf);	close (file);	if (blocklen)	    return 0;#endif    }    return 1;}static int check_file_access (WEdit *edit, const char *filename, struct stat *st){    int file;#if defined(MIDNIGHT) || defined(GTK)    if ((file = open ((char *) filename, O_RDONLY)) < 0) {	close (creat ((char *) filename, 0666));	if ((file = open ((char *) filename, O_RDONLY)) < 0) {	    edit_error_dialog (_ (" Error "), get_sys_error (catstrs (" Fail trying to open the file, ", filename, ", for reading ", 0)));	    return 2;	}    }#else    if ((file = open ((char *) filename, O_RDONLY)) < 0) {	edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open file for reading: "), filename, " ", 0)));	return 1;    }#endif    if (stat ((char *) filename, st) < 0) {	close (file);/* The file-name is printed after the ':' */	edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Cannot get size/permissions info on file: "), filename, " ", 0)));	return 1;    }    if (S_ISDIR (st->st_mode) || S_ISSOCK (st->st_mode)	|| S_ISFIFO (st->st_mode)) {	close (file);/* The file-name is printed after the ':' */	edit_error_dialog (_ (" Error "), catstrs (_ (" Not an ordinary file: "), filename, " ", 0));	return 1;    }    if (st->st_size >= SIZE_LIMIT) {	close (file);/* The file-name is printed after the ':' */	edit_error_dialog (_ (" Error "), catstrs (_ (" File is too large: "), \						   filename, _ (" \n Increase edit.h:MAXBUF and recompile the editor. "), 0));	return 1;    }    close (file);    return 0;}/* returns 1 on error */int edit_open_file (WEdit * edit, const char *filename, const char *text, unsigned long text_size){    struct stat st;    if (text) {	edit->last_byte = text_size;	filename = 0;    } else {	int r;	r = check_file_access (edit, filename, &st);#if defined(MIDNIGHT) || defined(GTK)	if (r == 2)	    return edit->delete_file = 1;#endif	if (r)	    return 1;	edit->stat = st;#ifndef CR_LF_TRANSLATION	edit->last_byte = st.st_size;#else/* going to read the file into the buffer later byte by byte */	edit->last_byte = 0;	filename = 0;	text = "";#endif    }    return init_dynamic_edit_buffers (edit, filename, text);}#ifdef MIDNIGHT#define space_width 1#elseint space_width;extern int option_long_whitespace;void edit_set_space_width (int s){    space_width = s;}#endifint (*edit_file_is_open) (char *) = 0;/* fills in the edit struct. returns 0 on fail. Pass edit as NULL for this */WEdit *edit_init (WEdit * edit, int lines, int columns, const char *filename, const char *text, const char *dir, unsigned long text_size){    char *f;    int to_free = 0;    int use_filter = 0;#ifndef MIDNIGHT    if (option_long_whitespace)	edit_set_space_width (FONT_PER_CHAR(' ') * 2);    else	edit_set_space_width (FONT_PER_CHAR(' '));#endif    if (!edit) {	edit = malloc (sizeof (WEdit));	memset (edit, 0, sizeof (WEdit));	to_free = 1;    }    memset (&(edit->from_here), 0, (unsigned long) &(edit->to_here) - (unsigned long) &(edit->from_here));#ifndef MIDNIGHT    edit->max_column = columns * FONT_MEAN_WIDTH;#endif    edit->num_widget_lines = lines;    edit->num_widget_columns = columns;

⌨️ 快捷键说明

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