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

📄 gview.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
#include	<u.h>#include	<libc.h>#include	<ctype.h>#include	<draw.h>#include	<event.h>#include	<cursor.h>#include	<stdio.h>#define Never	0xffffffff	/* Maximum ulong */#define LOG2  0.301029995664#define Button_bit(b)	(1 << ((b)-1))enum {	But1	= Button_bit(1),/* mouse buttons for events */	But2	= Button_bit(2),	But3	= Button_bit(3),};int cantmv = 1;			/* disallow rotate and move? 0..1 */int plotdots;			/* plot dots instead of lines */int top_border, bot_border, lft_border, rt_border;int lft_border0;		/* lft_border for y-axis labels >0 */int top_left, top_right;	/* edges of top line free space */int Mv_delay = 400;		/* msec for button click vs. button hold down */int Dotrad = 2;			/* dot radius in pixels */int framewd=1;			/* line thickness for frame (pixels) */int framesep=1;			/* distance between frame and surrounding text */int outersep=1;			/* distance: surrounding text to screen edge */Point sdigit;			/* size of a digit in the font */Point smaxch;			/* assume any character in font fits in this */double underscan = .05;		/* fraction of frame initially unused per side */double fuzz = 6;		/* selection tolerance in pixels */int tick_len = 15;		/* length of axis label tick mark in pixels */FILE* logfil = 0;		/* dump selected points here if nonzero */#define labdigs  3		/* allow this many sig digits in axis labels */#define digs10pow 1000		/* pow(10,labdigs) */#define axis_color  clr_im(DLtblue)/********************************* Utilities  *********************************//* Prepend string s to null-terminated string in n-byte buffer buf[], truncating if   necessary and using a space to separate s from the rest of buf[].*/char* str_insert(char* buf, char* s, int n){	int blen, slen = strlen(s) + 1;	if (slen >= n)		{strncpy(buf,s,n); buf[n-1]='\0'; return buf;}	blen = strlen(buf);	if (blen >= n-slen)		buf[blen=n-slen-1] = '\0';	memmove(buf+slen, buf, slen+blen+1);	memcpy(buf, s, slen-1);	buf[slen-1] = ' ';	return buf;}/* Alter string smain (without lengthening it) so as to remove the first occurrence of   ssub, assuming ssub is ASCII.  Return nonzero (true) if string smain had to be changed.   In spite of the ASCII-centric appearance, I think this can handle UTF in smain.*/int remove_substr(char* smain, char* ssub){	char *ss, *s = strstr(smain, ssub);	int n = strlen(ssub);	if (s==0)		return 0;	if (islower(s[n]))		s[0] ^= 32;			/* probably tolower(s[0]) or toupper(s[0]) */	else {		for (ss=s+n; *ss!=0; s++, ss++)			*s = *ss;		*s = '\0';	}	return 1;}void adjust_border(Font* f){	int sep = framesep + outersep;	sdigit = stringsize(f, "8");	smaxch = stringsize(f, "MMMg");	smaxch.x = (smaxch.x + 3)/4;	lft_border0 = (1+labdigs)*sdigit.x + framewd + sep;	rt_border = (lft_border0 - sep)/2 + outersep;	bot_border = sdigit.y + framewd + sep;	top_border = smaxch.y + framewd + sep;	lft_border = lft_border0;		/* this gets reset later */}int is_off_screen(Point p){	const Rectangle* r = &(screen->r);	return p.x-r->min.x<lft_border || r->max.x-p.x<rt_border		|| p.y-r->min.y<=top_border || r->max.y-p.y<=bot_border;}Cursor	bullseye ={	{-7, -7},	{		0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,	 	0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,	 	0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,	 	0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,	},	{		0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,		0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,		0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,		0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,	}};int get_1click(int but, Mouse* m, Cursor* curs){	if (curs)		esetcursor(curs);	while (m->buttons==0)		*m = emouse();	if (curs)		esetcursor(0);	return (m->buttons==Button_bit(but));}/* Wait until but goes up or until a mouse event's msec passes tlimit.   Return a boolean result that tells whether the button went up.*/int lift_button(int but, Mouse* m, int tlimit){	do {	*m = emouse();		if (m->msec >= tlimit)			return 0;	} while (m->buttons & Button_bit(but));	return 1;}/* Set *m to the last pending mouse event, or the first one where but is up.   If no mouse events are pending, wait for the next one.*/void latest_mouse(int but, Mouse* m){	int bbit = Button_bit(but);	do {	*m = emouse();	} while ((m->buttons & bbit) && ecanmouse());}/*********************************** Colors ***********************************/enum {	DOrange=0xffaa00FF, Dgray=0xbbbbbbFF, DDkgreen=0x009900FF,	DDkred=0xcc0000FF, DViolet=0x990099FF, DDkyellow=0xaaaa00FF,	DLtblue=0xaaaaffFF, DPink=0xffaaaaFF,	/* ndraw.h sets DBlack, DBlue, DRed, DYellow, DGreen,		DCyan, DMagenta, DWhite */};typedef struct color_ref {	ulong c;			/* RGBA pixel color */	char* nam;			/* ASCII name (matched to input, used in output)*/	Image* im;			/* replicated solid-color image */} color_ref;color_ref clrtab[] = {	DRed,		"Red",		0,	DPink,		"Pink",		0,	DDkred,		"Dkred",	0,	DOrange,	"Orange",	0,	DYellow,	"Yellow",	0,	DDkyellow,	"Dkyellow",	0,	DGreen,		"Green",	0,	DDkgreen,	"Dkgreen",	0,	DCyan,		"Cyan",		0,	DBlue,		"Blue",		0,	DLtblue,	"Ltblue",	0,	DMagenta,	"Magenta",	0,	DViolet,	"Violet",	0,	Dgray,		"Gray",		0,	DBlack,		"Black",	0,	DWhite,		"White",	0,	DNofill,	0,		0	/* DNofill means "end of data" */};void  init_clrtab(void){	int i;	Rectangle r = Rect(0,0,1,1);	for (i=0; clrtab[i].c!=DNofill; i++)		clrtab[i].im = allocimage(display, r, CMAP8, 1, clrtab[i].c);		/* should check for 0 result? */}int clrim_id(Image* clr){	int i;	for (i=0; clrtab[i].im!=clr; i++)		if (clrtab[i].c==DNofill)			exits("bad image color");	return i;}int clr_id(int clr){	int i;	for (i=0; clrtab[i].c!=clr; i++)		if (clrtab[i].c==DNofill)			exits("bad color");	return i;}#define clr_im(clr)	clrtab[clr_id(clr)].im/* This decides what color to use for a polyline based on the label it has in the   input file.  Whichever color name comes first is the winner, otherwise return black.*/Image* nam2clr(const char* nam, int *idxdest){	char *c, *cbest=nam;	int i, ibest=-1;	if (*nam!=0)		for (i=0; clrtab[i].nam!=0; i++) {			c = strstr(nam,clrtab[i].nam);			if (c!=0 && (ibest<0 || c<cbest))				{ibest=i; cbest=c;}		}	if (idxdest!=0)		*idxdest = (ibest<0) ? clr_id(DBlack) : ibest;	return (ibest<0) ? clr_im(DBlack) : clrtab[ibest].im;}/* A polyline is initial drawn in thick mode iff its label in the file contains "Thick" */int nam2thick(const char* nam){	return strstr(nam,"Thick")==0 ? 0 : 1;}/* Alter string nam so that nam2thick() and nam2clr() agree with th and clr, using   buf[] (a buffer of length bufn) to store the result if it differs from nam.   We go to great pains to perform this alteration in a manner that will seem natural   to the user, i.e., we try removing a suitably isolated color name before inserting   a new one.*/char* nam_with_thclr(char* nam, int th, Image* clr, char* buf, int bufn){	int clr0i, th0=nam2thick(nam);	Image* clr0 = nam2clr(nam, &clr0i);	char *clr0s;	if (th0==th && clr0==clr)		return nam;	clr0s = clrtab[clr0i].nam;	if (strlen(nam)<bufn) strcpy(buf,nam);	else {strncpy(buf,nam,bufn); buf[bufn-1]='\0';}	if (clr0 != clr)		remove_substr(buf, clr0s);	if (th0 > th)		while (remove_substr(buf, "Thick"))			/* do nothing */;	if (nam2clr(buf,0) != clr)		str_insert(buf, clrtab[clrim_id(clr)].nam, bufn);	if (th0 < th)		str_insert(buf, "Thick", bufn);	return buf;}/****************************** Data structures  ******************************/Image* mv_bkgd;				/* Background image (usually 0) */typedef struct fpoint {	double x, y;} fpoint;typedef struct frectangle {	fpoint min, max;} frectangle;frectangle empty_frect = {1e30, 1e30, -1e30, -1e30};/* When *r2 is transformed by y=y-x*slant, might it intersect *r1 ?*/int fintersects(const frectangle* r1, const frectangle* r2, double slant){	double x2min=r2->min.x, x2max=r2->max.x;	if (r1->max.x <= x2min || x2max <= r1->min.x)		return 0;	if (slant >=0)		{x2min*=slant; x2max*=slant;}	else	{double t=x2min*slant; x2min=x2max*slant; x2max=t;}	return r1->max.y > r2->min.y-x2max && r2->max.y-x2min > r1->min.y;}int fcontains(const frectangle* r, fpoint p){	return r->min.x <=p.x && p.x<= r->max.x && r->min.y <=p.y && p.y<= r->max.y;}void grow_bb(frectangle* dest, const frectangle* r){	if (r->min.x < dest->min.x) dest->min.x=r->min.x;	if (r->min.y < dest->min.y) dest->min.y=r->min.y;	if (r->max.x > dest->max.x) dest->max.x=r->max.x;	if (r->max.y > dest->max.y) dest->max.y=r->max.y;}void slant_frect(frectangle *r, double sl){	r->min.y += sl*r->min.x;	r->max.y += sl*r->max.x;}fpoint fcenter(const frectangle* r){	fpoint c;	c.x = .5*(r->max.x + r->min.x);	c.y = .5*(r->max.y + r->min.y);	return c;}typedef struct fpolygon {	fpoint* p;			/* a malloc'ed array */	int n;				/* p[] has n elements: p[0..n] */	frectangle bb;			/* bounding box */	char* nam;			/* name of this polygon (malloc'ed) */	int thick;			/* use 1+2*thick pixel wide lines */	Image* clr;			/* Color to use when drawing this */	struct fpolygon* link;} fpolygon;typedef struct fpolygons {	fpolygon* p;			/* the head of a linked list */	frectangle bb;			/* overall bounding box */	frectangle disp;		/* part being mapped onto screen->r */	double slant_ht;		/* controls how disp is slanted */} fpolygons;fpolygons univ = {			/* everything there is to display */	0,	1e30, 1e30, -1e30, -1e30,	0, 0, 0, 0,	2*1e30};void set_default_clrs(fpolygons* fps, fpolygon* fpstop){	fpolygon* fp;	for (fp=fps->p; fp!=0 && fp!=fpstop; fp=fp->link) {		fp->clr = nam2clr(fp->nam,0);		fp->thick = nam2thick(fp->nam);	}}void fps_invert(fpolygons* fps){	fpolygon *p, *r=0;	for (p=fps->p; p!=0;) {		fpolygon* q = p;		p = p->link;		q->link = r;		r = q;	}	fps->p = r;}void fp_remove(fpolygons* fps, fpolygon* fp){	fpolygon *q, **p = &fps->p;	while (*p!=fp)		if (*p==0)			return;		else	p = &(*p)->link;	*p = fp->link;	fps->bb = empty_frect;	for (q=fps->p; q!=0; q=q->link)		grow_bb(&fps->bb, &q->bb);}/* The transform maps abstract fpoint coordinates (the ones used in the input)   to the current screen coordinates.  The do_untransform() macros reverses this.   If univ.slant_ht is not the height of univ.disp, the actual region in the   abstract coordinates is a parallelogram inscribed in univ.disp with two   vertical edges and two slanted slanted edges: slant_ht>0 means that the   vertical edges have height slant_ht and the parallelogram touches the lower   left and upper right corners of univ.disp; slant_ht<0 refers to a parallelogram   of height -slant_ht that touches the other two corners of univ.disp.   NOTE: the ytransform macro assumes that tr->sl times the x coordinate has   already been subtracted from yy.*/typedef struct transform {	double sl;	fpoint o, sc;		/* (x,y):->(o.x+sc.x*x, o.y+sc.y*y+sl*x) */} transform;#define do_transform(d,tr,s)	((d)->x = (tr)->o.x + (tr)->sc.x*(s)->x,  \				(d)->y = (tr)->o.y + (tr)->sc.y*(s)->y    \					+ (tr)->sl*(s)->x)#define do_untransform(d,tr,s)	((d)->x = (.5+(s)->x-(tr)->o.x)/(tr)->sc.x,    \				(d)->y = (.5+(s)->y-(tr)->sl*(d)->x-(tr)->o.y) \					/(tr)->sc.y)#define xtransform(tr,xx)	((tr)->o.x + (tr)->sc.x*(xx))#define ytransform(tr,yy)	((tr)->o.y + (tr)->sc.y*(yy))#define dxuntransform(tr,xx)	((xx)/(tr)->sc.x)#define dyuntransform(tr,yy)	((yy)/(tr)->sc.y)transform cur_trans(void){	transform t;	Rectangle d = screen->r;	const frectangle* s = &univ.disp;	double sh = univ.slant_ht;	d.min.x += lft_border;	d.min.y += top_border;	d.max.x -= rt_border;	d.max.y -= bot_border;	t.sc.x = (d.max.x - d.min.x)/(s->max.x - s->min.x);	t.sc.y = -(d.max.y - d.min.y)/fabs(sh);	if (sh > 0) {		t.sl = -t.sc.y*(s->max.y-s->min.y-sh)/(s->max.x - s->min.x);		t.o.y = d.min.y - t.sc.y*s->max.y - t.sl*s->max.x;	} else {		t.sl = t.sc.y*(s->max.y-s->min.y+sh)/(s->max.x - s->min.x);		t.o.y = d.min.y - t.sc.y*s->max.y - t.sl*s->min.x;	}	t.o.x = d.min.x - t.sc.x*s->min.x;	return t;}double u_slant_amt(fpolygons *u){	double sh=u->slant_ht, dy=u->disp.max.y - u->disp.min.y;	double dx = u->disp.max.x - u->disp.min.x;	return (sh>0) ? (dy-sh)/dx : -(dy+sh)/dx;}/* Set *y0 and *y1 to the lower and upper bounds of the set of y-sl*x values that   *u says to display, where sl is the amount of slant.*/double set_unslanted_y(fpolygons *u, double *y0, double *y1){	double yy1, sl=u_slant_amt(u);	if (u->slant_ht > 0) {		*y0 = u->disp.min.y - sl*u->disp.min.x;		yy1 = *y0 + u->slant_ht;	} else {		yy1 = u->disp.max.y - sl*u->disp.min.x;		*y0 = yy1 + u->slant_ht;	}	if (y1 != 0)		*y1 = yy1;	return sl;}/*************************** The region to display ****************************/void nontrivial_interval(double *lo, double *hi){	if (*lo >= *hi) {		double mid = .5*(*lo + *hi);		double tweak = 1e-6 + 1e-6*fabs(mid);		*lo = mid - tweak;		*hi = mid + tweak;	}}void init_disp(void){	double dw = (univ.bb.max.x - univ.bb.min.x)*underscan;	double dh = (univ.bb.max.y - univ.bb.min.y)*underscan;	univ.disp.min.x = univ.bb.min.x - dw;	univ.disp.min.y = univ.bb.min.y - dh;	univ.disp.max.x = univ.bb.max.x + dw;	univ.disp.max.y = univ.bb.max.y + dh;	nontrivial_interval(&univ.disp.min.x, &univ.disp.max.x);	nontrivial_interval(&univ.disp.min.y, &univ.disp.max.y);	univ.slant_ht = univ.disp.max.y - univ.disp.min.y;	/* means no slant */}

⌨️ 快捷键说明

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