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

📄 file.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "sam.h"/* * Structure of Undo list: * 	The Undo structure follows any associated data, so the list *	can be read backwards: read the structure, then read whatever *	data is associated (insert string, file name) and precedes it. *	The structure includes the previous value of the modify bit *	and a sequence number; successive Undo structures with the *	same sequence number represent simultaneous changes. */typedef struct Undo Undo;typedef struct Merge Merge;struct Undo{	short	type;		/* Delete, Insert, Filename, Dot, Mark */	short	mod;		/* modify bit */	uint	seq;		/* sequence number */	uint	p0;		/* location of change (unused in f) */	uint	n;		/* # runes in string or file name */};struct Merge{	File	*f;	uint	seq;		/* of logged change */	uint	p0;		/* location of change (unused in f) */	uint	n;		/* # runes to delete */	uint	nbuf;		/* # runes to insert */	Rune	buf[RBUFSIZE];};enum{	Maxmerge = 50,	Undosize = sizeof(Undo)/sizeof(Rune),};static Merge	merge;File*fileopen(void){	File *f;	f = emalloc(sizeof(File));	f->dot.f = f;	f->ndot.f = f;	f->seq = 0;	f->mod = FALSE;	f->unread = TRUE;	Strinit0(&f->name);	return f;}intfileisdirty(File *f){	return f->seq != f->cleanseq;}static voidwrinsert(Buffer *delta, int seq, int mod, uint p0, Rune *s, uint ns){	Undo u;	u.type = Insert;	u.mod = mod;	u.seq = seq;	u.p0 = p0;	u.n = ns;	bufinsert(delta, delta->nc, s, ns);	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);}static voidwrdelete(Buffer *delta, int seq, int mod, uint p0, uint p1){	Undo u;	u.type = Delete;	u.mod = mod;	u.seq = seq;	u.p0 = p0;	u.n = p1 - p0;	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);}voidflushmerge(void){	File *f;	f = merge.f;	if(f == nil)		return;	if(merge.seq != f->seq)		panic("flushmerge seq mismatch");	if(merge.n != 0)		wrdelete(&f->epsilon, f->seq, TRUE, merge.p0, merge.p0+merge.n);	if(merge.nbuf != 0)		wrinsert(&f->epsilon, f->seq, TRUE, merge.p0+merge.n, merge.buf, merge.nbuf);	merge.f = nil;	merge.n = 0;	merge.nbuf = 0;}voidmergeextend(File *f, uint p0){	uint mp0n;	mp0n = merge.p0+merge.n;	if(mp0n != p0){		bufread(f, mp0n, merge.buf+merge.nbuf, p0-mp0n);		merge.nbuf += p0-mp0n;		merge.n = p0-merge.p0;	}}/* * like fileundelete, but get the data from arguments */voidloginsert(File *f, uint p0, Rune *s, uint ns){	if(f->rescuing)		return;	if(ns == 0)		return;	if(ns<0 || ns>STRSIZE)		panic("loginsert");	if(f->seq < seq)		filemark(f);	if(p0 < f->hiposn)		error(Esequence);	if(merge.f != f	|| p0-(merge.p0+merge.n)>Maxmerge			/* too far */	|| merge.nbuf+((p0+ns)-(merge.p0+merge.n))>RBUFSIZE)	/* too long */		flushmerge();	if(ns>=RBUFSIZE){		if(!(merge.n == 0 && merge.nbuf == 0 && merge.f == nil))			panic("loginsert bad merge state");		wrinsert(&f->epsilon, f->seq, TRUE, p0, s, ns);	}else{		if(merge.f != f){			merge.f = f;			merge.p0 = p0;			merge.seq = f->seq;		}		mergeextend(f, p0);		/* append string to merge */		runemove(merge.buf+merge.nbuf, s, ns);		merge.nbuf += ns;	}	f->hiposn = p0;	if(!f->unread && !f->mod)		state(f, Dirty);}voidlogdelete(File *f, uint p0, uint p1){	if(f->rescuing)		return;	if(p0 == p1)		return;	if(f->seq < seq)		filemark(f);	if(p0 < f->hiposn)		error(Esequence);	if(merge.f != f	|| p0-(merge.p0+merge.n)>Maxmerge			/* too far */	|| merge.nbuf+(p0-(merge.p0+merge.n))>RBUFSIZE){	/* too long */		flushmerge();		merge.f = f;		merge.p0 = p0;		merge.seq = f->seq;	}	mergeextend(f, p0);	/* add to deletion */	merge.n = p1-merge.p0;	f->hiposn = p1;	if(!f->unread && !f->mod)		state(f, Dirty);}/* * like fileunsetname, but get the data from arguments */voidlogsetname(File *f, String *s){	Undo u;	Buffer *delta;	if(f->rescuing)		return;	if(f->unread){	/* This is setting initial file name */		filesetname(f, s);		return;	}	if(f->seq < seq)		filemark(f);	/* undo a file name change by restoring old name */	delta = &f->epsilon;	u.type = Filename;	u.mod = TRUE;	u.seq = f->seq;	u.p0 = 0;	/* unused */	u.n = s->n;	if(s->n)		bufinsert(delta, delta->nc, s->s, s->n);	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);	if(!f->unread && !f->mod)		state(f, Dirty);}#ifdef NOTEXTFile*fileaddtext(File *f, Text *t){	if(f == nil){		f = emalloc(sizeof(File));		f->unread = TRUE;	}	f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*));	f->text[f->ntext++] = t;	f->curtext = t;	return f;}voidfiledeltext(File *f, Text *t){	int i;	for(i=0; i<f->ntext; i++)		if(f->text[i] == t)			goto Found;	panic("can't find text in filedeltext");    Found:	f->ntext--;	if(f->ntext == 0){		fileclose(f);		return;	}	memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*));	if(f->curtext == t)		f->curtext = f->text[0];}#endifvoidfileinsert(File *f, uint p0, Rune *s, uint ns){	if(p0 > f->nc)		panic("internal error: fileinsert");	if(f->seq > 0)		fileuninsert(f, &f->delta, p0, ns);	bufinsert(f, p0, s, ns);	if(ns)		f->mod = TRUE;}voidfileuninsert(File *f, Buffer *delta, uint p0, uint ns){	Undo u;	/* undo an insertion by deleting */	u.type = Delete;	u.mod = f->mod;	u.seq = f->seq;	u.p0 = p0;	u.n = ns;	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);}voidfiledelete(File *f, uint p0, uint p1){	if(!(p0<=p1 && p0<=f->nc && p1<=f->nc))		panic("internal error: filedelete");	if(f->seq > 0)		fileundelete(f, &f->delta, p0, p1);	bufdelete(f, p0, p1);	if(p1 > p0)		f->mod = TRUE;}voidfileundelete(File *f, Buffer *delta, uint p0, uint p1){	Undo u;	Rune *buf;	uint i, n;	/* undo a deletion by inserting */	u.type = Insert;	u.mod = f->mod;	u.seq = f->seq;	u.p0 = p0;	u.n = p1-p0;	buf = fbufalloc();	for(i=p0; i<p1; i+=n){		n = p1 - i;		if(n > RBUFSIZE)			n = RBUFSIZE;		bufread(f, i, buf, n);		bufinsert(delta, delta->nc, buf, n);	}	fbuffree(buf);	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);}intfilereadc(File *f, uint q){	Rune r;	if(q >= f->nc)		return -1;	bufread(f, q, &r, 1);	return r;}voidfilesetname(File *f, String *s){	if(!f->unread)	/* This is setting initial file name */		fileunsetname(f, &f->delta);	Strduplstr(&f->name, s);	sortname(f);	f->unread = TRUE;}voidfileunsetname(File *f, Buffer *delta){	String s;	Undo u;	/* undo a file name change by restoring old name */	u.type = Filename;	u.mod = f->mod;	u.seq = f->seq;	u.p0 = 0;	/* unused */	Strinit(&s);	Strduplstr(&s, &f->name);	fullname(&s);	u.n = s.n;	if(s.n)		bufinsert(delta, delta->nc, s.s, s.n);	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);	Strclose(&s);}voidfileunsetdot(File *f, Buffer *delta, Range dot){	Undo u;	u.type = Dot;	u.mod = f->mod;	u.seq = f->seq;	u.p0 = dot.p1;	u.n = dot.p2 - dot.p1;	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);}voidfileunsetmark(File *f, Buffer *delta, Range mark){	Undo u;	u.type = Mark;	u.mod = f->mod;	u.seq = f->seq;	u.p0 = mark.p1;	u.n = mark.p2 - mark.p1;	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);}uintfileload(File *f, uint p0, int fd, int *nulls){	if(f->seq > 0)		panic("undo in file.load unimplemented");	return bufload(f, p0, fd, nulls);}intfileupdate(File *f, int notrans, int toterm){	uint p1, p2;	int mod;	if(f->rescuing)		return FALSE;	flushmerge();	/*	 * fix the modification bit	 * subtle point: don't save it away in the log.	 *	 * if another change is made, the correct f->mod	 * state is saved  in the undo log by filemark	 * when setting the dot and mark.	 *	 * if the change is undone, the correct state is	 * saved from f in the fileun... routines.	 */	mod = f->mod;	f->mod = f->prevmod;	if(f == cmd)		notrans = TRUE;	else{		fileunsetdot(f, &f->delta, f->prevdot);		fileunsetmark(f, &f->delta, f->prevmark);	}	f->dot = f->ndot;	fileundo(f, FALSE, !notrans, &p1, &p2, toterm);	f->mod = mod;	if(f->delta.nc == 0)		f->seq = 0;	if(f == cmd)		return FALSE;	if(f->mod){		f->closeok = 0;		quitok = 0;	}else		f->closeok = 1;	return TRUE;}longprevseq(Buffer *b){	Undo u;	uint up;	up = b->nc;	if(up == 0)		return 0;	up -= Undosize;	bufread(b, up, (Rune*)&u, Undosize);	return u.seq;}longundoseq(File *f, int isundo){	if(isundo)		return f->seq;	return prevseq(&f->epsilon);}voidfileundo(File *f, int isundo, int canredo, uint *q0p, uint *q1p, int flag){	Undo u;	Rune *buf;	uint i, n, up;	uint stop;	Buffer *delta, *epsilon;	if(isundo){		/* undo; reverse delta onto epsilon, seq decreases */		delta = &f->delta;		epsilon = &f->epsilon;		stop = f->seq;	}else{		/* redo; reverse epsilon onto delta, seq increases */		delta = &f->epsilon;		epsilon = &f->delta;		stop = 0;	/* don't know yet */	}	raspstart(f);	while(delta->nc > 0){		up = delta->nc-Undosize;		bufread(delta, up, (Rune*)&u, Undosize);		if(isundo){			if(u.seq < stop){				f->seq = u.seq;				raspdone(f, flag);				return;			}		}else{			if(stop == 0)				stop = u.seq;			if(u.seq > stop){				raspdone(f, flag);				return;			}		}		switch(u.type){		default:			panic("undo unknown u.type");			break;		case Delete:			f->seq = u.seq;			if(canredo)				fileundelete(f, epsilon, u.p0, u.p0+u.n);			f->mod = u.mod;			bufdelete(f, u.p0, u.p0+u.n);			raspdelete(f, u.p0, u.p0+u.n, flag);			*q0p = u.p0;			*q1p = u.p0;			break;		case Insert:			f->seq = u.seq;			if(canredo)				fileuninsert(f, epsilon, u.p0, u.n);			f->mod = u.mod;			up -= u.n;			buf = fbufalloc();			for(i=0; i<u.n; i+=n){				n = u.n - i;				if(n > RBUFSIZE)					n = RBUFSIZE;				bufread(delta, up+i, buf, n);				bufinsert(f, u.p0+i, buf, n);				raspinsert(f, u.p0+i, buf, n, flag);			}			fbuffree(buf);			*q0p = u.p0;			*q1p = u.p0+u.n;			break;		case Filename:			f->seq = u.seq;			if(canredo)				fileunsetname(f, epsilon);			f->mod = u.mod;			up -= u.n;			Strinsure(&f->name, u.n+1);			bufread(delta, up, f->name.s, u.n);			f->name.s[u.n] = 0;			f->name.n = u.n;			fixname(&f->name);			sortname(f);			break;		case Dot:			f->seq = u.seq;			if(canredo)				fileunsetdot(f, epsilon, f->dot.r);			f->mod = u.mod;			f->dot.r.p1 = u.p0;			f->dot.r.p2 = u.p0 + u.n;			break;		case Mark:			f->seq = u.seq;			if(canredo)				fileunsetmark(f, epsilon, f->mark);			f->mod = u.mod;			f->mark.p1 = u.p0;			f->mark.p2 = u.p0 + u.n;			break;		}		bufdelete(delta, up, delta->nc);	}	if(isundo)		f->seq = 0;	raspdone(f, flag);}voidfilereset(File *f){	bufreset(&f->delta);	bufreset(&f->epsilon);	f->seq = 0;}voidfileclose(File *f){	Strclose(&f->name);	bufclose(f);	bufclose(&f->delta);	bufclose(&f->epsilon);	if(f->rasp)		listfree(f->rasp);	free(f);}voidfilemark(File *f){	if(f->unread)		return;	if(f->epsilon.nc)		bufdelete(&f->epsilon, 0, f->epsilon.nc);	if(f != cmd){		f->prevdot = f->dot.r;		f->prevmark = f->mark;		f->prevseq = f->seq;		f->prevmod = f->mod;	}	f->ndot = f->dot;	f->seq = seq;	f->hiposn = 0;}

⌨️ 快捷键说明

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