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

📄 gview.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
	q.x = xtransform(tr, p.x) - .5;	qrt.x = q.x + tick_len;	qlft.x = q.x - (framewd + framesep);	seps0 = ceil(y0/iv.sep);	for (seps=0, nseps=floor(y1/iv.sep)-seps0; seps<=nseps; seps+=1) {		char* num = abbrev_num((p.y=iv.sep*(seps0+seps)), &iv);		Point qq = stringsize(f, num);		q.y = qrt.y = qlft.y = ytransform(tr, p.y);		line(screen, qrt, q, Enddisc, Enddisc, 0, axis_color, q);		qq.x = qlft.x - qq.x;		qq.y = qlft.y - qq.y/2;		string(screen, qq, display->black, qq, f, num);	}	return iv;}void lab_iv_info(const lab_interval *iv, double slant, char* buf, int *n){	if (iv->off > 0)		(*n) += sprintf(buf+*n,"-%.12g",iv->off);	else if (iv->off < 0)		(*n) += sprintf(buf+*n,"+%.12g",-iv->off);	if (slant>0)		(*n) += sprintf(buf+*n,"-%.6gx", slant);	else if (slant<0)		(*n) += sprintf(buf+*n,"+%.6gx", -slant);	if (abs(iv->logunit) >= Nthous)		(*n) += sprintf(buf+*n," in 1e%d units", 3*iv->logunit);	else if (iv->logunit > 0)		(*n) += sprintf(buf+*n," in %ss", thous_nam[iv->logunit]);	else if (iv->logunit < 0)		(*n) += sprintf(buf+*n," in %sths", thous_nam[-iv->logunit]);}void draw_xy_ranges(const lab_interval *xiv, const lab_interval *yiv){	Point p;	char buf[2*(19+Len_thous+8)+50];	int bufn = 0;	buf[bufn++] = 'x';	lab_iv_info(xiv, 0, buf, &bufn);	bufn += sprintf(buf+bufn, "; y");	lab_iv_info(yiv, u_slant_amt(&univ), buf, &bufn);	buf[bufn] = '\0';	p = stringsize(display->defaultfont, buf);	top_left = screen->r.min.x + lft_border;	p.x = top_right = screen->r.max.x - rt_border - p.x;	p.y = screen->r.min.y + outersep;	string(screen, p, display->black, p, display->defaultfont, buf);}transform draw_frame(void){	lab_interval x_iv, y_iv;	transform tr;	Rectangle r = screen->r;	lft_border = (univ.disp.min.y<0) ? lft_border0+sdigit.x : lft_border0;	tr = cur_trans();	r.min.x += lft_border;	r.min.y += top_border;	r.max.x -= rt_border;	r.max.y -= bot_border;	border(screen, r, -framewd, axis_color, r.min);	x_iv = mark_x_axis(&tr);	y_iv = mark_y_axis(&tr);	draw_xy_ranges(&x_iv, &y_iv);	return tr;}/*************************** Finding the selection  ***************************/typedef struct pt_on_fpoly {	fpoint p;			/* the point */	fpolygon* fp;			/* the fpolygon it lies on */	double t;			/* how many knots from the beginning */} pt_on_fpoly;static double myx, myy;#define mydist(p,o,sl,xwt,ywt)	(myx=(p).x-(o).x, myy=(p).y-sl*(p).x-(o).y,	\					xwt*myx*myx + ywt*myy*myy)/* At what fraction of the way from p0[0] to p0[1] is mydist(p,ctr,slant,xwt,ywt)   minimized?*/double closest_time(const fpoint* p0, const fpoint* ctr, double slant,		double xwt, double ywt){	double p00y=p0[0].y-slant*p0[0].x, p01y=p0[1].y-slant*p0[1].x;	double dx=p0[1].x-p0[0].x, dy=p01y-p00y;	double x0=p0[0].x-ctr->x, y0=p00y-ctr->y;	double bot = xwt*dx*dx + ywt*dy*dy;	if (bot==0)		return 0;	return -(xwt*x0*dx + ywt*y0*dy)/bot;}/* Scan the polygonal path of length len knots starting at p0, and find the   point that the transformation y=y-x*slant makes closest to the center of *r,   where *r itself defines the distance metric.  Knots get higher priority than   points between knots.  If psel->t is negative, always update *psel; otherwise   update *psel only if the scan can improve it.  Return a boolean that says   whether *psel was updated.     Note that *r is a very tiny rectangle (tiny when converted screen pixels)   such that anything in *r is considered close enough to match the mouse click.   The purpose of this routine is to be careful in case there is a lot of hidden   detail in the tiny rectangle *r.*/int improve_pt(fpoint* p0, double len, const frectangle* r, double slant,		pt_on_fpoly* psel){	fpoint ctr = fcenter(r);	double x_wt=2/(r->max.x-r->min.x), y_wt=2/(r->max.y-r->min.y);	double xwt=x_wt*x_wt, ywt=y_wt*y_wt;	double d, dbest = (psel->t <0) ? 1e30 : mydist(psel->p,ctr,slant,xwt,ywt);	double tt, dbest0 = dbest;	fpoint pp;	int ilen = (int) len;	if (len==0 || ilen>0) {		int i;		for (i=(len==0 ? 0 : 1); i<=ilen; i++) {			d = mydist(p0[i], ctr, slant, xwt, ywt);			if (d < dbest)				{psel->p=p0[i]; psel->t=i; dbest=d;}		}		return (dbest < dbest0);	}	tt = closest_time(p0, &ctr, slant, xwt, ywt);	if (tt > len)		tt = len;	pp.x = p0[0].x + tt*(p0[1].x - p0[0].x);	pp.y = p0[0].y + tt*(p0[1].y - p0[0].y);	if (mydist(pp, ctr, slant, xwt, ywt) < dbest) {		psel->p = pp;		psel->t = tt;		return 1;	}	return 0;}/* Test *fp against *r after transforming by y=y-x*slope, and set *psel accordingly.*/void select_in_fpoly(fpolygon* fp, const frectangle* r, double slant,		pt_on_fpoly* psel){	fpoint *p0=fp->p, *pn=fp->p+fp->n;	double l1, l2;	if (p0==pn)		{improve_pt(p0, 0, r, slant, psel); psel->fp=fp; return;}	while ((l1=out_length(p0,pn,*r,slant)) < pn-p0) {		fpoint p0sav;		int i1 = (int) l1;		p0+=i1; l1-=i1;		p0sav = *p0;		p0[0].x += l1*(p0[1].x - p0[0].x);		p0[0].y += l1*(p0[1].y - p0[0].y);		l2 = in_length(p0, pn, *r, slant);		if (improve_pt(p0, l2, r, slant, psel)) {			if (l1==0 && psel->t!=((int) psel->t)) {				psel->t = 0;				psel->p = *p0;			} else if (psel->t < 1)				psel->t += l1*(1 - psel->t);			psel->t += p0 - fp->p;			psel->fp = fp;		}		*p0 = p0sav;		p0 += (l2>0) ? ((int) ceil(l2)) : 1;	}}/* Test all the fpolygons against *r after transforming by y=y-x*slope, and return   the resulting selection, if any.*/pt_on_fpoly* select_in_univ(const frectangle* r, double slant){	static pt_on_fpoly answ;	fpolygon* fp;	answ.t = -1;	for (fp=univ.p; fp!=0; fp=fp->link)		if (fintersects(r, &fp->bb, slant))			select_in_fpoly(fp, r, slant, &answ);	if (answ.t < 0)		return 0;	return &answ;}/**************************** Using the selection  ****************************/pt_on_fpoly cur_sel;			/* current selection if cur_sel.t>=0 */pt_on_fpoly prev_sel;			/* previous selection if prev_sel.t>=0 (for slant) */Image* sel_bkg = 0;			/* what's behind the red dot */void clear_txt(void){	Rectangle r;	r.min = screen->r.min;	r.min.x += lft_border;	r.min.y += outersep;	r.max.x = top_left;	r.max.y = r.min.y + smaxch.y;	draw(screen, r, display->white, display->opaque, r.min);	top_left = r.min.x;}Rectangle sel_dot_box(const transform* tr){	Point ctr;	Rectangle r;	if (tr==0)		ctr.x = ctr.y = Dotrad;	else	do_transform(&ctr, tr, &cur_sel.p);	r.min.x=ctr.x-Dotrad;  r.max.x=ctr.x+Dotrad+1;	r.min.y=ctr.y-Dotrad;  r.max.y=ctr.y+Dotrad+1;	return r;}void unselect(const transform* tr){	transform tra;	if (sel_bkg==0)		sel_bkg = allocimage(display, sel_dot_box(0), CMAP8, 0, DWhite);	clear_txt();	if (cur_sel.t < 0)		return;	prev_sel = cur_sel;	if (tr==0)		{tra=cur_trans(); tr=&tra;}	draw(screen, sel_dot_box(tr), sel_bkg, display->opaque, ZP);	cur_sel.t = -1;}/* Text at top right is written first and this low-level routine clobbers it if   the new top-left text would overwrite it.  However, users of this routine should   try to keep the new text short enough to avoid this.*/void show_mytext(char* msg){	Point tmp, pt = screen->r.min;	int siz;	tmp = stringsize(display->defaultfont, msg);	siz = tmp.x;	pt.x=top_left;  pt.y+=outersep;	if (top_left+siz > top_right) {		Rectangle r;		r.min.y = pt.y;		r.min.x = top_right;		r.max.y = r.min.y + smaxch.y;		r.max.x = top_left+siz;		draw(screen, r, display->white, display->opaque, r.min);		top_right = top_left+siz;	}	string(screen, pt, display->black, ZP, display->defaultfont, msg);	top_left += siz;}double rnd(double x, double tol)	/* round to enough digits for accuracy tol */{	double t = pow(10, floor(log10(tol)));	return t * floor(x/t + .5);}double t_tol(double xtol, double ytol){	int t = (int) floor(cur_sel.t);	fpoint* p = cur_sel.fp->p;	double dx, dy;	if (t==cur_sel.t)		return 1;	dx = fabs(p[t+1].x - p[t].x);	dy = fabs(p[t+1].y - p[t].y);	xtol /= (xtol>dx) ? xtol : dx;	ytol /= (ytol>dy) ? ytol : dy;	return (xtol<ytol) ? xtol : ytol;}void say_where(const transform* tr){	double xtol=dxuntransform(tr,1), ytol=dyuntransform(tr,-1);	char buf[100];	int n, nmax = (top_right - top_left)/smaxch.x;	if (nmax >= 100)		nmax = 100-1;	n = sprintf(buf,"(%.14g,%.14g) at t=%.14g",			rnd(cur_sel.p.x,xtol), rnd(cur_sel.p.y,ytol),			rnd(cur_sel.t, t_tol(xtol,ytol)));	if (cur_sel.fp->nam[0] != 0)		sprintf(buf+n," %.*s", nmax-n-1, cur_sel.fp->nam);	show_mytext(buf);}void reselect(const transform* tr)	/* uselect(); set cur_sel; call this */{	Point pt2, pt3;	fpoint p2;	transform tra;	if (cur_sel.t < 0)		return;	if (tr==0)		{tra=cur_trans(); tr=&tra;}	do_transform(&p2, tr, &cur_sel.p);	if (fabs(p2.x)+fabs(p2.y)>1e8 || (pt2.x=p2.x, pt2.y=p2.y, is_off_screen(pt2)))		{cur_sel.t= -1; return;}	pt3.x=pt2.x-Dotrad;  pt3.y=pt2.y-Dotrad;	draw(sel_bkg, sel_dot_box(0), screen, display->opaque, pt3);	fillellipse(screen, pt2, Dotrad, Dotrad, clr_im(DRed), pt2);	say_where(tr);}void do_select(Point pt){	transform tr = cur_trans();	fpoint pt1, pt2, ctr;	frectangle r;	double slant;	pt_on_fpoly* psel;	unselect(&tr);	do_untransform(&ctr, &tr, &pt);	pt1.x=pt.x-fuzz;  pt1.y=pt.y+fuzz;	pt2.x=pt.x+fuzz;  pt2.y=pt.y-fuzz;	do_untransform(&r.min, &tr, &pt1);	do_untransform(&r.max, &tr, &pt2);	slant = u_slant_amt(&univ);	slant_frect(&r, -slant);	psel = select_in_univ(&r, slant);	if (psel==0)		return;	if (logfil!=0) {		fprintf(logfil,"%.14g\t%.14g\n", psel->p.x, psel->p.y);		fflush(logfil);	}	cur_sel = *psel;	reselect(&tr);}/***************************** Prompting for text *****************************/void unshow_mytext(char* msg){	Rectangle r;	Point siz = stringsize(display->defaultfont, msg);	top_left -= siz.x;	r.min.y = screen->r.min.y + outersep;	r.min.x = top_left;	r.max.y = r.min.y + siz.y;	r.max.x = r.min.x + siz.x;	draw(screen, r, display->white, display->opaque, r.min);}/* Show the given prompt and read a line of user input.  The text appears at the   top left.  If it runs into the top right text, we stop echoing but let the user   continue typing blind if he wants to.*/char* prompt_text(char* prompt){	static char buf[200];	int n0, n=0, nshown=0;	Rune c;	unselect(0);	show_mytext(prompt);	while (n<200-1-UTFmax && (c=ekbd())!='\n') {		if (c=='\b') {			buf[n] = 0;			if (n > 0)				do n--;				while (n>0 && (buf[n-1]&0xc0)==0x80);			if (n < nshown)				{unshow_mytext(buf+n); nshown=n;}		} else {			n0 = n;			n += runetochar(buf+n, &c);			buf[n] = 0;			if (nshown==n0 && top_right-top_left >= smaxch.x)				{show_mytext(buf+n0); nshown=n;}		}	}	buf[n] = 0;	while (ecanmouse())		emouse();	return buf;}/**************************** Redrawing the screen ****************************//* Let p0 and its successors define a piecewise-linear function of a paramter t,   and draw the 0<=t<=n1 portion using transform *tr.*/void draw_fpts(const fpoint* p0, double n1, const transform* tr, int thick,		Image* clr){	int n = (int) n1;	const fpoint* p = p0 + n;	fpoint pp;	Point qq, q;	if (n1 > n) {		pp.x = p[0].x + (n1-n)*(p[1].x - p[0].x);		pp.y = p[0].y + (n1-n)*(p[1].y - p[0].y);	} else	pp = *p--;	do_transform(&qq, tr, &pp);	if (n1==0)		fillellipse(screen, qq, 1+thick, 1+thick, clr, qq);	for (; p>=p0; p--) {		do_transform(&q, tr, p);		if(plotdots)			fillellipse(screen, q, Dotrad, Dotrad, clr, q);		else			line(screen, qq, q, Enddisc, Enddisc, thick, clr, qq);		qq = q;	}}void draw_1fpoly(const fpolygon* fp, const transform* tr, Image* clr,		const frectangle *udisp, double slant){	fpoint *p0=fp->p, *pn=fp->p+fp->n;	double l1, l2;	if (p0==pn && fcontains(udisp,*p0))		{draw_fpts(p0, 0, tr, fp->thick, clr); return;}	while ((l1=out_length(p0,pn,*udisp,slant)) < pn-p0) {		fpoint p0sav;		int i1 = (int) l1;		p0+=i1; l1-=i1;		p0sav = *p0;		p0[0].x += l1*(p0[1].x - p0[0].x);		p0[0].y += l1*(p0[1].y - p0[0].y);		l2 = in_length(p0, pn, *udisp, slant);		draw_fpts(p0, l2, tr, fp->thick, clr);		*p0 = p0sav;		p0 += (l2>0) ? ((int) ceil(l2)) : 1;	}}double get_clip_data(const fpolygons *u, frectangle *r){	double slant = set_unslanted_y(u, &r->min.y, &r->max.y);	r->min.x = u->disp.min.x;	r->max.x = u->disp.max.x;	return slant;}void draw_fpoly(const fpolygon* fp, const transform* tr, Image* clr){	frectangle r;	double slant = get_clip_data(&univ, &r);	draw_1fpoly(fp, tr, clr, &r, slant);}void eresized(int new){	transform tr;	fpolygon* fp;	frectangle clipr;	double slant;	if(new && getwindow(display, Refmesg) < 0) {		fprintf(stderr,"can't reattach to window\n");		exits("reshap");	}	draw(screen, screen->r, display->white, display->opaque, screen->r.min);	tr = draw_frame();	slant = get_clip_data(&univ, &clipr);	for (fp=univ.p; fp!=0; fp=fp->link)		if (fintersects(&clipr, &fp->bb, slant))			draw_1fpoly(fp, &tr, fp->clr, &clipr, slant);	reselect(0);	if (mv_bkgd!=0 && mv_bkgd->repl==0) {		freeimage(mv_bkgd);		mv_bkgd = display->white;	}	flushimage(display, 1);}/********************************* Recoloring *********************************/int draw_palette(int n)		/* n is number of colors; returns patch dy */{	int y0 = screen->r.min.y + top_border;	int dy = (screen->r.max.y - bot_border - y0)/n;	Rectangle r;	int i;	r.min.y = y0;

⌨️ 快捷键说明

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