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

📄 flayer.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include "flayer.h"#include "samterm.h"#define	DELTA	10static Flayer	**llist;	/* front to back */static int	nllist;static int	nlalloc;static Rectangle lDrect;Vis		visibility(Flayer *);void		newvisibilities(int);void		llinsert(Flayer*);void		lldelete(Flayer*);Image	*maincols[NCOL];Image	*cmdcols[NCOL];voidflstart(Rectangle r){	lDrect = r;	/* Main text is yellowish */	maincols[BACK] = allocimagemix(display, DPaleyellow, DWhite);	maincols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkyellow);	maincols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, DYellowgreen);	maincols[TEXT] = display->black;	maincols[HTEXT] = display->black;	/* Command text is blueish */	cmdcols[BACK] = allocimagemix(display, DPalebluegreen, DWhite);	cmdcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen);	cmdcols[BORD] = allocimage(display, Rect(0,0,2,2), screen->chan, 1, DPurpleblue);	cmdcols[TEXT] = display->black;	cmdcols[HTEXT] = display->black;}voidflnew(Flayer *l, Rune *(*fn)(Flayer*, long, ulong*), int u0, void *u1){	if(nllist == nlalloc){		nlalloc += DELTA;		llist = realloc(llist, nlalloc*sizeof(Flayer**));		if(llist == 0)			panic("flnew");	}	l->textfn = fn;	l->user0 = u0;	l->user1 = u1;	l->lastsr = ZR;	llinsert(l);}Rectangleflrect(Flayer *l, Rectangle r){	rectclip(&r, lDrect);	l->entire = r;	l->scroll = insetrect(r, FLMARGIN);	r.min.x =	 l->scroll.max.x = r.min.x+FLMARGIN+FLSCROLLWID+(FLGAP-FLMARGIN);	return r;}voidflinit(Flayer *l, Rectangle r, Font *ft, Image **cols){	lldelete(l);	llinsert(l);	l->visible = All;	l->origin = l->p0 = l->p1 = 0;	frinit(&l->f, insetrect(flrect(l, r), FLMARGIN), ft, screen, cols);	l->f.maxtab = maxtab*stringwidth(ft, "0");	newvisibilities(1);	draw(screen, l->entire, l->f.cols[BACK], nil, ZP);	scrdraw(l, 0L);	flborder(l, 0);}voidflclose(Flayer *l){	if(l->visible == All)		draw(screen, l->entire, display->white, nil, ZP);	else if(l->visible == Some){		if(l->f.b == 0)			l->f.b = allocimage(display, l->entire, screen->chan, 0, DNofill);		if(l->f.b){			draw(l->f.b, l->entire, display->white, nil, ZP);			flrefresh(l, l->entire, 0);		}	}	frclear(&l->f, 1);	lldelete(l);	if(l->f.b && l->visible!=All)		freeimage(l->f.b);	l->textfn = 0;	newvisibilities(1);}voidflborder(Flayer *l, int wide){	if(flprepare(l)){		border(l->f.b, l->entire, FLMARGIN, l->f.cols[BACK], ZP);		border(l->f.b, l->entire, wide? FLMARGIN : 1, l->f.cols[BORD], ZP);		if(l->visible==Some)			flrefresh(l, l->entire, 0);	}}Flayer *flwhich(Point p){	int i;	if(p.x==0 && p.y==0)		return nllist? llist[0] : 0;	for(i=0; i<nllist; i++)		if(ptinrect(p, llist[i]->entire))			return llist[i];	return 0;}voidflupfront(Flayer *l){	int v = l->visible;	lldelete(l);	llinsert(l);	if(v!=All)		newvisibilities(0);}voidnewvisibilities(int redraw)	/* if redraw false, we know it's a flupfront, and needn't	 * redraw anyone becoming partially covered */{	int i;	Vis ov;	Flayer *l;	for(i = 0; i<nllist; i++){		l = llist[i];		l->lastsr = ZR;	/* make sure scroll bar gets redrawn */		ov = l->visible;		l->visible = visibility(l);#define	V(a, b)	(((a)<<2)|((b)))		switch(V(ov, l->visible)){		case V(Some, None):			if(l->f.b)				freeimage(l->f.b);		case V(All, None):		case V(All, Some):			l->f.b = 0;			frclear(&l->f, 0);			break;		case V(Some, Some):			if(l->f.b==0 && redraw)		case V(None, Some):				flprepare(l);			if(l->f.b && redraw){				flrefresh(l, l->entire, 0);				freeimage(l->f.b);				l->f.b = 0;				frclear(&l->f, 0);			}		case V(None, None):		case V(All, All):			break;		case V(Some, All):			if(l->f.b){				draw(screen, l->entire, l->f.b, nil, l->entire.min);				freeimage(l->f.b);				l->f.b = screen;				break;			}		case V(None, All):			flprepare(l);			break;		}		if(ov==None && l->visible!=None)			flnewlyvisible(l);	}}voidllinsert(Flayer *l){	int i;	for(i=nllist; i>0; --i)		llist[i]=llist[i-1];	llist[0]=l;	nllist++;}voidlldelete(Flayer *l){	int i;	for(i=0; i<nllist; i++)		if(llist[i]==l){			--nllist;			for(; i<nllist; i++)				llist[i] = llist[i+1];			return;		}	panic("lldelete");}voidflinsert(Flayer *l, Rune *sp, Rune *ep, long p0){	if(flprepare(l)){		frinsert(&l->f, sp, ep, p0-l->origin);		scrdraw(l, scrtotal(l));		if(l->visible==Some)			flrefresh(l, l->entire, 0);	}}voidfldelete(Flayer *l, long p0, long p1){	if(flprepare(l)){		p0 -= l->origin;		if(p0 < 0)			p0 = 0;		p1 -= l->origin;		if(p1<0)			p1 = 0;		frdelete(&l->f, p0, p1);		scrdraw(l, scrtotal(l));		if(l->visible==Some)			flrefresh(l, l->entire, 0);	}}intflselect(Flayer *l){	int ret;	if(l->visible!=All)		flupfront(l);	frselect(&l->f, mousectl);	ret = 0;	if(l->f.p0==l->f.p1){		if(mousep->msec-l->click<Clicktime && l->f.p0+l->origin==l->p0){			ret = 1;			l->click = 0;		}else			l->click = mousep->msec;	}else		l->click = 0;	l->p0 = l->f.p0+l->origin, l->p1 = l->f.p1+l->origin;	return ret;}voidflsetselect(Flayer *l, long p0, long p1){	ulong fp0, fp1;	l->click = 0;	if(l->visible==None || !flprepare(l)){		l->p0 = p0, l->p1 = p1;		return;	}	l->p0 = p0, l->p1 = p1;	flfp0p1(l, &fp0, &fp1);	if(fp0==l->f.p0 && fp1==l->f.p1)		return;	if(fp1<=l->f.p0 || fp0>=l->f.p1 || l->f.p0==l->f.p1 || fp0==fp1){		/* no overlap or trivial repainting */		frdrawsel(&l->f, frptofchar(&l->f, l->f.p0), l->f.p0, l->f.p1, 0);		frdrawsel(&l->f, frptofchar(&l->f, fp0), fp0, fp1, 1);		goto Refresh;	}	/* the current selection and the desired selection overlap and are both non-empty */	if(fp0 < l->f.p0){		/* extend selection backwards */		frdrawsel(&l->f, frptofchar(&l->f, fp0), fp0, l->f.p0, 1);	}else if(fp0 > l->f.p0){		/* trim first part of selection */		frdrawsel(&l->f, frptofchar(&l->f, l->f.p0), l->f.p0, fp0, 0);	}	if(fp1 > l->f.p1){		/* extend selection forwards */		frdrawsel(&l->f, frptofchar(&l->f, l->f.p1), l->f.p1, fp1, 1);	}else if(fp1 < l->f.p1){		/* trim last part of selection */		frdrawsel(&l->f, frptofchar(&l->f, fp1), fp1, l->f.p1, 0);	}    Refresh:	l->f.p0 = fp0;	l->f.p1 = fp1;	if(l->visible==Some)		flrefresh(l, l->entire, 0);}voidflfp0p1(Flayer *l, ulong *pp0, ulong *pp1){	long p0 = l->p0-l->origin, p1 = l->p1-l->origin;	if(p0 < 0)		p0 = 0;	if(p1 < 0)		p1 = 0;	if(p0 > l->f.nchars)		p0 = l->f.nchars;	if(p1 > l->f.nchars)		p1 = l->f.nchars;	*pp0 = p0;	*pp1 = p1;}Rectanglerscale(Rectangle r, Point old, Point new){	r.min.x = r.min.x*new.x/old.x;	r.min.y = r.min.y*new.y/old.y;	r.max.x = r.max.x*new.x/old.x;	r.max.y = r.max.y*new.y/old.y;	return r;}voidflresize(Rectangle dr){	int i;	Flayer *l;	Frame *f;	Rectangle r, olDrect;	int move;	olDrect = lDrect;	lDrect = dr;	move = 0;	/* no moving on rio; must repaint */	if(0 && Dx(dr)==Dx(olDrect) && Dy(dr)==Dy(olDrect))		move = 1;	else		draw(screen, lDrect, display->white, nil, ZP);	for(i=0; i<nllist; i++){		l = llist[i];		l->lastsr = ZR;		f = &l->f;		if(move)			r = rectaddpt(rectsubpt(l->entire, olDrect.min), dr.min);		else{			r = rectaddpt(rscale(rectsubpt(l->entire, olDrect.min),				subpt(olDrect.max, olDrect.min),				subpt(dr.max, dr.min)), dr.min);			if(l->visible==Some && f->b){				freeimage(f->b);				frclear(f, 0);			}			f->b = 0;			if(l->visible!=None)				frclear(f, 0);		}		if(!rectclip(&r, dr))			panic("flresize");		if(r.max.x-r.min.x<100)			r.min.x = dr.min.x;		if(r.max.x-r.min.x<100)			r.max.x = dr.max.x;		if(r.max.y-r.min.y<2*FLMARGIN+f->font->height)			r.min.y = dr.min.y;		if(r.max.y-r.min.y<2*FLMARGIN+f->font->height)			r.max.y = dr.max.y;		if(!move)			l->visible = None;		frsetrects(f, insetrect(flrect(l, r), FLMARGIN), f->b);		if(!move && f->b)			scrdraw(l, scrtotal(l));	}	newvisibilities(1);}intflprepare(Flayer *l){	Frame *f;	ulong n;	Rune *r;	if(l->visible == None)		return 0;	f = &l->f;	if(f->b == 0){		if(l->visible == All)			f->b = screen;		else if((f->b = allocimage(display, l->entire, screen->chan, 0, 0))==0)			return 0;		draw(f->b, l->entire, f->cols[BACK], nil, ZP);		border(f->b, l->entire, l==llist[0]? FLMARGIN : 1, f->cols[BORD], ZP);		n = f->nchars;		frinit(f, f->entire, f->font, f->b, 0);		f->maxtab = maxtab*stringwidth(f->font, "0");		r = (*l->textfn)(l, n, &n);		frinsert(f, r, r+n, (ulong)0);		frdrawsel(f, frptofchar(f, f->p0), f->p0, f->p1, 0);		flfp0p1(l, &f->p0, &f->p1);		frdrawsel(f, frptofchar(f, f->p0), f->p0, f->p1, 1);		l->lastsr = ZR;		scrdraw(l, scrtotal(l));	}	return 1;}static	int	somevis, someinvis, justvis;Visvisibility(Flayer *l){	somevis = someinvis = 0;	justvis = 1;	flrefresh(l, l->entire, 0);	justvis = 0;	if(somevis==0)		return None;	if(someinvis==0)		return All;	return Some;}voidflrefresh(Flayer *l, Rectangle r, int i){	Flayer *t;	Rectangle s;    Top:	if((t=llist[i++]) == l){		if(!justvis)			draw(screen, r, l->f.b, nil, r.min);		somevis = 1;	}else{		if(!rectXrect(t->entire, r))			goto Top;	/* avoid stacking unnecessarily */		if(t->entire.min.x>r.min.x){			s = r;			s.max.x = t->entire.min.x;			flrefresh(l, s, i);			r.min.x = t->entire.min.x;		}		if(t->entire.min.y>r.min.y){			s = r;			s.max.y = t->entire.min.y;			flrefresh(l, s, i);			r.min.y = t->entire.min.y;		}		if(t->entire.max.x<r.max.x){			s = r;			s.min.x = t->entire.max.x;			flrefresh(l, s, i);			r.max.x = t->entire.max.x;		}		if(t->entire.max.y<r.max.y){			s = r;			s.min.y = t->entire.max.y;			flrefresh(l, s, i);			r.max.y = t->entire.max.y;		}		/* remaining piece of r is blocked by t; forget about it */		someinvis = 1;	}}

⌨️ 快捷键说明

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