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

📄 text.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	case 0x05:	/* ^E: end of line */		typecommit(t);		q0 = t->q0;		while(q0<t->file->nc && textreadc(t, q0)!='\n')			q0++;		textshow(t, q0, q0, TRUE);		return;	}	if(t->what == Body){		seq++;		filemark(t->file);	}	if(t->q1 > t->q0){		if(t->ncache != 0)			error("text.type");		cut(t, t, nil, TRUE, TRUE, nil, 0);		t->eq0 = ~0;	}	textshow(t, t->q0, t->q0, 1);	switch(r){	case 0x06:	case Kins:		rp = textcomplete(t);		if(rp == nil)			return;		nr = runestrlen(rp);		break;	/* fall through to normal insertion case */	case 0x1B:		if(t->eq0 != ~0)			textsetselect(t, t->eq0, t->q0);		if(t->ncache > 0)			typecommit(t);		return;	case 0x08:	/* ^H: erase character */	case 0x15:	/* ^U: erase line */	case 0x17:	/* ^W: erase word */		if(t->q0 == 0)	/* nothing to erase */			return;		nnb = textbswidth(t, r);		q1 = t->q0;		q0 = q1-nnb;		/* if selection is at beginning of window, avoid deleting invisible text */		if(q0 < t->org){			q0 = t->org;			nnb = q1-q0;		}		if(nnb <= 0)			return;		for(i=0; i<t->file->ntext; i++){			u = t->file->text[i];			u->nofill = TRUE;			nb = nnb;			n = u->ncache;			if(n > 0){				if(q1 != u->cq0+n)					error("text.type backspace");				if(n > nb)					n = nb;				u->ncache -= n;				textdelete(u, q1-n, q1, FALSE);				nb -= n;			}			if(u->eq0==q1 || u->eq0==~0)				u->eq0 = q0;			if(nb && u==t)				textdelete(u, q0, q0+nb, TRUE);			if(u != t)				textsetselect(u, u->q0, u->q1);			else				textsetselect(t, q0, q0);			u->nofill = FALSE;		}		for(i=0; i<t->file->ntext; i++)			textfill(t->file->text[i]);		return;	case '\n':		if(t->w->autoindent){			/* find beginning of previous line using backspace code */			nnb = textbswidth(t, 0x15); /* ^U case */			rp = runemalloc(nnb + 1);			nr = 0;			rp[nr++] = r;			for(i=0; i<nnb; i++){				r = textreadc(t, t->q0-nnb+i);				if(r != ' ' && r != '\t')					break;				rp[nr++] = r;			}		}		break; /* fall through to normal code */	}	/* otherwise ordinary character; just insert, typically in caches of all texts */	for(i=0; i<t->file->ntext; i++){		u = t->file->text[i];		if(u->eq0 == ~0)			u->eq0 = t->q0;		if(u->ncache == 0)			u->cq0 = t->q0;		else if(t->q0 != u->cq0+u->ncache)			error("text.type cq1");		textinsert(u, t->q0, rp, nr, FALSE);		if(u != t)			textsetselect(u, u->q0, u->q1);		if(u->ncache+nr > u->ncachealloc){			u->ncachealloc += 10 + nr;			u->cache = runerealloc(u->cache, u->ncachealloc);		}		runemove(u->cache+u->ncache, rp, nr);		u->ncache += nr;	}	if(rp != &r)		free(rp);	textsetselect(t, t->q0+nr, t->q0+nr);	if(r=='\n' && t->w!=nil)		wincommit(t->w, t);}voidtextcommit(Text *t, int tofile){	if(t->ncache == 0)		return;	if(tofile)		fileinsert(t->file, t->cq0, t->cache, t->ncache);	if(t->what == Body){		t->w->dirty = TRUE;		t->w->utflastqid = -1;	}	t->ncache = 0;}static	Text	*clicktext;static	uint	clickmsec;static	Text	*selecttext;static	uint	selectq;/* * called from frame library */voidframescroll(Frame *f, int dl){	if(f != &selecttext->Frame)		error("frameselect not right frame");	textframescroll(selecttext, dl);}voidtextframescroll(Text *t, int dl){	uint q0;	if(dl == 0){		scrsleep(100);		return;	}	if(dl < 0){		q0 = textbacknl(t, t->org, -dl);		if(selectq > t->org+t->p0)			textsetselect(t, t->org+t->p0, selectq);		else			textsetselect(t, selectq, t->org+t->p0);	}else{		if(t->org+t->nchars == t->file->nc)			return;		q0 = t->org+frcharofpt(t, Pt(t->r.min.x, t->r.min.y+dl*t->font->height));		if(selectq > t->org+t->p1)			textsetselect(t, t->org+t->p1, selectq);		else			textsetselect(t, selectq, t->org+t->p1);	}	textsetorigin(t, q0, TRUE);}voidtextselect(Text *t){	uint q0, q1;	int b, x, y;	int state;	selecttext = t;	/*	 * To have double-clicking and chording, we double-click	 * immediately if it might make sense.	 */	b = mouse->buttons;	q0 = t->q0;	q1 = t->q1;	selectq = t->org+frcharofpt(t, mouse->xy);	if(clicktext==t && mouse->msec-clickmsec<500)	if(q0==q1 && selectq==q0){		textdoubleclick(t, &q0, &q1);		textsetselect(t, q0, q1);		flushimage(display, 1);		x = mouse->xy.x;		y = mouse->xy.y;		/* stay here until something interesting happens */		do			readmouse(mousectl);		while(mouse->buttons==b && abs(mouse->xy.x-x)<3 && abs(mouse->xy.y-y)<3);		mouse->xy.x = x;	/* in case we're calling frselect */		mouse->xy.y = y;		q0 = t->q0;	/* may have changed */		q1 = t->q1;		selectq = q0;	}	if(mouse->buttons == b){		t->Frame.scroll = framescroll;		frselect(t, mousectl);		/* horrible botch: while asleep, may have lost selection altogether */		if(selectq > t->file->nc)			selectq = t->org + t->p0;		t->Frame.scroll = nil;		if(selectq < t->org)			q0 = selectq;		else			q0 = t->org + t->p0;		if(selectq > t->org+t->nchars)			q1 = selectq;		else			q1 = t->org+t->p1;	}	if(q0 == q1){		if(q0==t->q0 && clicktext==t && mouse->msec-clickmsec<500){			textdoubleclick(t, &q0, &q1);			clicktext = nil;		}else{			clicktext = t;			clickmsec = mouse->msec;		}	}else		clicktext = nil;	textsetselect(t, q0, q1);	flushimage(display, 1);	state = 0;	/* undo when possible; +1 for cut, -1 for paste */	while(mouse->buttons){		mouse->msec = 0;		b = mouse->buttons;		if((b&1) && (b&6)){			if(state==0 && t->what==Body){				seq++;				filemark(t->w->body.file);			}			if(b & 2){				if(state==-1 && t->what==Body){					winundo(t->w, TRUE);					textsetselect(t, q0, t->q0);					state = 0;				}else if(state != 1){					cut(t, t, nil, TRUE, TRUE, nil, 0);					state = 1;				}			}else{				if(state==1 && t->what==Body){					winundo(t->w, TRUE);					textsetselect(t, q0, t->q1);					state = 0;				}else if(state != -1){					paste(t, t, nil, TRUE, FALSE, nil, 0);					state = -1;				}			}			textscrdraw(t);			clearmouse();		}		flushimage(display, 1);		while(mouse->buttons == b)			readmouse(mousectl);		clicktext = nil;	}}voidtextshow(Text *t, uint q0, uint q1, int doselect){	int qe;	int nl;	uint q;	if(t->what != Body){		if(doselect)			textsetselect(t, q0, q1);		return;	}	if(t->w!=nil && t->maxlines==0)		colgrow(t->col, t->w, 1);	if(doselect)		textsetselect(t, q0, q1);	qe = t->org+t->nchars;	if(t->org<=q0 && (q0<qe || (q0==qe && qe==t->file->nc+t->ncache)))		textscrdraw(t);	else{		if(t->w->nopen[QWevent] > 0)			nl = 3*t->maxlines/4;		else			nl = t->maxlines/4;		q = textbacknl(t, q0, nl);		/* avoid going backwards if trying to go forwards - long lines! */		if(!(q0>t->org && q<t->org))			textsetorigin(t, q, TRUE);		while(q0 > t->org+t->nchars)			textsetorigin(t, t->org+1, FALSE);	}}staticintregion(int a, int b){	if(a < b)		return -1;	if(a == b)		return 0;	return 1;}voidselrestore(Frame *f, Point pt0, uint p0, uint p1){	if(p1<=f->p0 || p0>=f->p1){		/* no overlap */		frdrawsel0(f, pt0, p0, p1, f->cols[BACK], f->cols[TEXT]);		return;	}	if(p0>=f->p0 && p1<=f->p1){		/* entirely inside */		frdrawsel0(f, pt0, p0, p1, f->cols[HIGH], f->cols[HTEXT]);		return;	}	/* they now are known to overlap */	/* before selection */	if(p0 < f->p0){		frdrawsel0(f, pt0, p0, f->p0, f->cols[BACK], f->cols[TEXT]);		p0 = f->p0;		pt0 = frptofchar(f, p0);	}	/* after selection */	if(p1 > f->p1){		frdrawsel0(f, frptofchar(f, f->p1), f->p1, p1, f->cols[BACK], f->cols[TEXT]);		p1 = f->p1;	}	/* inside selection */	frdrawsel0(f, pt0, p0, p1, f->cols[HIGH], f->cols[HTEXT]);}voidtextsetselect(Text *t, uint q0, uint q1){	int p0, p1;	/* t->p0 and t->p1 are always right; t->q0 and t->q1 may be off */	t->q0 = q0;	t->q1 = q1;	/* compute desired p0,p1 from q0,q1 */	p0 = q0-t->org;	p1 = q1-t->org;	if(p0 < 0)		p0 = 0;	if(p1 < 0)		p1 = 0;	if(p0 > t->nchars)		p0 = t->nchars;	if(p1 > t->nchars)		p1 = t->nchars;	if(p0==t->p0 && p1==t->p1)		return;	/* screen disagrees with desired selection */	if(t->p1<=p0 || p1<=t->p0 || p0==p1 || t->p1==t->p0){		/* no overlap or too easy to bother trying */		frdrawsel(t, frptofchar(t, t->p0), t->p0, t->p1, 0);		frdrawsel(t, frptofchar(t, p0), p0, p1, 1);		goto Return;	}	/* overlap; avoid unnecessary painting */	if(p0 < t->p0){		/* extend selection backwards */		frdrawsel(t, frptofchar(t, p0), p0, t->p0, 1);	}else if(p0 > t->p0){		/* trim first part of selection */		frdrawsel(t, frptofchar(t, t->p0), t->p0, p0, 0);	}	if(p1 > t->p1){		/* extend selection forwards */		frdrawsel(t, frptofchar(t, t->p1), t->p1, p1, 1);	}else if(p1 < t->p1){		/* trim last part of selection */		frdrawsel(t, frptofchar(t, p1), p1, t->p1, 0);	}    Return:	t->p0 = p0;	t->p1 = p1;}/* * Release the button in less than DELAY ms and it's considered a null selection * if the mouse hardly moved, regardless of whether it crossed a char boundary. */enum {	DELAY = 2,	MINMOVE = 4,};uintxselect(Frame *f, Mousectl *mc, Image *col, uint *p1p)	/* when called, button is down */{	uint p0, p1, q, tmp;	ulong msec;	Point mp, pt0, pt1, qt;	int reg, b;	mp = mc->xy;	b = mc->buttons;	msec = mc->msec;	/* remove tick */	if(f->p0 == f->p1)		frtick(f, frptofchar(f, f->p0), 0);	p0 = p1 = frcharofpt(f, mp);	pt0 = frptofchar(f, p0);	pt1 = frptofchar(f, p1);	reg = 0;	frtick(f, pt0, 1);	do{		q = frcharofpt(f, mc->xy);		if(p1 != q){			if(p0 == p1)				frtick(f, pt0, 0);			if(reg != region(q, p0)){	/* crossed starting point; reset */				if(reg > 0)					selrestore(f, pt0, p0, p1);				else if(reg < 0)					selrestore(f, pt1, p1, p0);				p1 = p0;				pt1 = pt0;				reg = region(q, p0);				if(reg == 0)					frdrawsel0(f, pt0, p0, p1, col, display->white);			}			qt = frptofchar(f, q);			if(reg > 0){				if(q > p1)					frdrawsel0(f, pt1, p1, q, col, display->white);				else if(q < p1)					selrestore(f, qt, q, p1);			}else if(reg < 0){				if(q > p1)					selrestore(f, pt1, p1, q);				else					frdrawsel0(f, qt, q, p1, col, display->white);			}			p1 = q;			pt1 = qt;		}		if(p0 == p1)			frtick(f, pt0, 1);		flushimage(f->display, 1);		readmouse(mc);	}while(mc->buttons == b);	if(mc->msec-msec < DELAY && p0!=p1	&& abs(mp.x-mc->xy.x)<MINMOVE	&& abs(mp.y-mc->xy.y)<MINMOVE) {		if(reg > 0)			selrestore(f, pt0, p0, p1);		else if(reg < 0)			selrestore(f, pt1, p1, p0);		p1 = p0;	}	if(p1 < p0){		tmp = p0;		p0 = p1;		p1 = tmp;	}	pt0 = frptofchar(f, p0);	if(p0 == p1)		frtick(f, pt0, 0);	selrestore(f, pt0, p0, p1);	/* restore tick */	if(f->p0 == f->p1)		frtick(f, frptofchar(f, f->p0), 1);	flushimage(f->display, 1);	*p1p = p1;	return p0;}inttextselect23(Text *t, uint *q0, uint *q1, Image *high, int mask){	uint p0, p1;	int buts;		p0 = xselect(t, mousectl, high, &p1);	buts = mousectl->buttons;	if((buts & mask) == 0){		*q0 = p0+t->org;		*q1 = p1+t->org;	}	while(mousectl->buttons)		readmouse(mousectl);	return buts;}inttextselect2(Text *t, uint *q0, uint *q1, Text **tp){	int buts;	*tp = nil;	buts = textselect23(t, q0, q1, but2col, 4);	if(buts & 4)		return 0;	if(buts & 1){	/* pick up argument */		*tp = argtext;		return 1;	}	return 1;}inttextselect3(Text *t, uint *q0, uint *q1){	int h;	h = (textselect23(t, q0, q1, but3col, 1|2) == 0);	return h;}static Rune left1[] =  { L'{', L'[', L'(', L'<', L'«', 0 };static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 };static Rune left2[] =  { L'\n', 0 };static Rune left3[] =  { L'\'', L'"', L'`', 0 };staticRune *left[] = {	left1,	left2,	left3,	nil};staticRune *right[] = {	right1,	left2,	left3,	nil};voidtextdoubleclick(Text *t, uint *q0, uint *q1){	int c, i;	Rune *r, *l, *p;	uint q;	for(i=0; left[i]!=nil; i++){		q = *q0;		l = left[i];		r = right[i];		/* try matching character to left, looking right */		if(q == 0)			c = '\n';		else			c = textreadc(t, q-1);		p = runestrchr(l, c);		if(p != nil){			if(textclickmatch(t, c, r[p-l], 1, &q))				*q1 = q-(c!='\n');			return;		}		/* try matching character to right, looking left */		if(q == t->file->nc)			c = '\n';		else			c = textreadc(t, q);		p = runestrchr(r, c);		if(p != nil){			if(textclickmatch(t, c, l[p-r], -1, &q)){				*q1 = *q0+(*q0<t->file->nc && c=='\n');				*q0 = q;				if(c!='\n' || q!=0 || textreadc(t, 0)=='\n')					(*q0)++;			}			return;		}	}	/* try filling out word to right */	while(*q1<t->file->nc && isalnum(textreadc(t, *q1)))		(*q1)++;	/* try filling out word to left */	while(*q0>0 && isalnum(textreadc(t, *q0-1)))		(*q0)--;}inttextclickmatch(Text *t, int cl, int cr, int dir, uint *q){	Rune c;	int nest;	nest = 1;	for(;;){		if(dir > 0){			if(*q == t->file->nc)				break;			c = textreadc(t, *q);			(*q)++;		}else{			if(*q == 0)				break;			(*q)--;			c = textreadc(t, *q);		}		if(c == cr){			if(--nest==0)				return 1;		}else if(c == cl)			nest++;	}	return cl=='\n' && nest==1;}uinttextbacknl(Text *t, uint p, uint n){	int i, j;	/* look for start of this line if n==0 */	if(n==0 && p>0 && textreadc(t, p-1)!='\n')		n = 1;	i = n;	while(i-->0 && p>0){		--p;	/* it's at a newline now; back over it */		if(p == 0)			break;		/* at 128 chars, call it a line anyway */		for(j=128; --j>0 && p>0; p--)			if(textreadc(t, p-1)=='\n')				break;	}	return p;}voidtextsetorigin(Text *t, uint org, int exact){	int i, a, fixup;	Rune *r;	uint n;	if(org>0 && !exact){		/* org is an estimate of the char posn; find a newline */		/* don't try harder than 256 chars */		for(i=0; i<256 && org<t->file->nc; i++){			if(textreadc(t, org) == '\n'){				org++;				break;			}			org++;		}	}	a = org-t->org;	fixup = 0;	if(a>=0 && a<t->nchars){		frdelete(t, 0, a);		fixup = 1;	/* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */	}	else if(a<0 && -a<t->nchars){		n = t->org - org;		r = runemalloc(n);		bufread(t->file, org, r, n);		frinsert(t, r, r+n, 0);		free(r);	}else		frdelete(t, 0, t->nchars);	t->org = org;	textfill(t);	textscrdraw(t);	textsetselect(t, t->q0, t->q1);	if(fixup && t->p1 > t->p0)		frdrawsel(t, frptofchar(t, t->p1-1), t->p1-1, t->p1, 1);}voidtextreset(Text *t){	t->file->seq = 0;	t->eq0 = ~0;	/* do t->delete(0, t->nc, TRUE) without building backup stuff */	textsetselect(t, t->org, t->org);	frdelete(t, 0, t->nchars);	t->org = 0;	t->q0 = 0;	t->q1 = 0;	filereset(t->file);	bufreset(t->file);}

⌨️ 快捷键说明

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