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

📄 ticks.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include "grap.h"#include "y.tab.h"#define	MAXTICK	200int	ntick	= 0;double	tickval[MAXTICK];	/* tick values (one axis at a time */char	*tickstr[MAXTICK];	/* and labels */int	tside	= 0;int	tlist	= 0;		/* 1 => explicit values given */int	toffside = 0;		/* no ticks on these sides */int	goffside = 0;		/* no ticks on grid on these sides */int	tick_dir = OUT;double	ticklen	= TICKLEN;	/* default tick length */int	autoticks = LEFT|BOT;int	autodir = 0;		/* set LEFT, etc. if automatic ticks go in */void savetick(double f, char *s)	/* remember tick location and label */{	if (ntick >= MAXTICK)		ERROR "too many ticks (%d)", MAXTICK FATAL;	tickval[ntick] = f;	tickstr[ntick] = s;	ntick++;}void dflt_tick(double f){	if (f >= 0.0)		savetick(f, tostring("%g"));	else		savetick(f, tostring("\\%g"));}void tickside(int n)	/* remember which side these ticks/gridlines go on */{	tside |= n;}void tickoff(int side)	/* remember explicit sides */{	toffside |= side;}void gridtickoff(void)	/* turn grid ticks off on the side previously specified (ugh) */{	goffside = tside;}void setlist(void)	/* remember that there was an explicit list */{	tlist = 1;}void tickdir(int dir, double val, int explicit)	/* remember in/out [expr] */{	tick_dir = dir;	if (explicit)		ticklen = val;}void ticks(void)		/* set autoticks after ticks statement */{	/* was there an explicit "ticks [side] off"? */	if (toffside)		autoticks &= ~toffside;	/* was there an explicit list? (eg "ticks at ..." or "ticks from ...") */	if (tlist) {		if (tside & (BOT|TOP))			autoticks &= ~(BOT|TOP);		if (tside & (LEFT|RIGHT))			autoticks &= ~(LEFT|RIGHT);	}	/* was there a side without a list? (eg "ticks left in") */	if (tside && !tlist) {		if (tick_dir == IN)			autodir |= tside;		if (tside & (BOT|TOP))			autoticks = (autoticks & ~(BOT|TOP)) | (tside & (BOT|TOP));		if (tside & (LEFT|RIGHT))			autoticks = (autoticks & ~(LEFT|RIGHT)) | (tside & (LEFT|RIGHT));	}	tlist = tside = toffside = goffside = 0;	tick_dir = OUT;}double modfloor(double f, double t){	t = fabs(t);	return floor(f/t) * t;}double modceil(double f, double t){	t = fabs(t);	return ceil(f/t) * t;}double	xtmin, xtmax;	/* range of ticks */double	ytmin, ytmax;double	xquant, xmult;	/* quantization & scale for auto x ticks */double	yquant, ymult;double	lograt = 5;void do_autoticks(Obj *p)	/* make set of ticks for default coord only */{	double x, xl, xu, q;	if (p == NULL)		return;	fprintf(tfd, "Autoticks:\t# x %g..%g, y %g..%g",		p->pt.x, p->pt1.x, p->pt.y, p->pt1.y);	fprintf(tfd, ";   xt %g,%g, yt %g,%g, xq,xm = %g,%g, yq,ym = %g,%g\n",		xtmin, xtmax, ytmin, ytmax, xquant, xmult, yquant, ymult);	if ((autoticks & (BOT|TOP)) && p->pt1.x >= p->pt.x) {	/* make x ticks */		q = xquant;		xl = p->pt.x;		xu = p->pt1.x;		if (xl >= xu)			dflt_tick(xl);		else if ((p->log & XFLAG) && xu/xl >= lograt) {			for (x = q; x < xu; x *= 10) {				logtick(x, xl, xu);				if (xu/xl <= 100) {					logtick(2*x, xl, xu);					logtick(5*x, xl, xu);				}			}		} else {			xl = modceil(xtmin - q/100, q);			xu = modfloor(xtmax + q/100, q) + q/2;			for (x = xl; x <= xu; x += q)				dflt_tick(x);		}		tside = autoticks & (BOT|TOP);		ticklist(p, 0);	}	if ((autoticks & (LEFT|RIGHT)) && p->pt1.y >= p->pt.y) {	/* make y ticks */		q = yquant;		xl = p->pt.y;		xu = p->pt1.y;		if (xl >= xu)			dflt_tick(xl);		else if ((p->log & YFLAG) && xu/xl >= lograt) {			for (x = q; x < xu; x *= 10) {				logtick(x, xl, xu);				if (xu/xl <= 100) {					logtick(2*x, xl, xu);					logtick(5*x, xl, xu);				}			}		} else {			xl = modceil(ytmin - q/100, q);			xu = modfloor(ytmax + q/100, q) + q/2;			for (x = xl; x <= xu; x += q)				dflt_tick(x);		}		tside = autoticks & (LEFT|RIGHT);		ticklist(p, 0);	}}void logtick(double v, double lb, double ub){	float slop = 1.0;	/* was 1.001 */	if (slop * lb <= v && ub >= slop * v)		dflt_tick(v);}Obj *setauto(void)	/* compute new min,max, and quant & mult */{	Obj *p, *q;	if ((q = lookup("lograt",0)) != NULL)		lograt = q->fval;	for (p = objlist; p; p = p->next)		if (p->type == NAME && strcmp(p->name,dflt_coord) == 0)			break;	if (p) {		if ((p->log & XFLAG) && p->pt1.x/p->pt.x >= lograt)			autolog(p, 'x');		else			autoside(p, 'x');		if ((p->log & YFLAG) && p->pt1.y/p->pt.y >= lograt)			autolog(p, 'y');		else			autoside(p, 'y');	}	return p;}void autoside(Obj *p, int side){	double r, s, d, ub, lb;	if (side == 'x') {		xtmin = lb = p->pt.x;		xtmax = ub = p->pt1.x;	} else {		ytmin = lb = p->pt.y;		ytmax = ub = p->pt1.y;	}	if (ub <= lb)		return;	/* cop out on little ranges */	d = ub - lb;	r = s = 1;	while (d * s < 10)		s *= 10;	d *= s;	while (10 * r < d)		r *= 10;	if (r > d/3)		r /= 2;	else if (r <= d/6)		r *= 2;	if (side == 'x') {		xquant = r / s;	} else {		yquant = r / s;	}}void autolog(Obj *p, int side){	double r, s, t, ub, lb;	int flg;	if (side == 'x') {		xtmin = lb = p->pt.x;		xtmax = ub = p->pt1.x;		flg = p->coord & XFLAG;	} else {		ytmin = lb = p->pt.y;		ytmax = ub = p->pt1.y;		flg = p->coord & YFLAG;	}	for (s = 1; lb * s < 1; s *= 10)		;	lb *= s;	ub *= s;	for (r = 1; 10 * r < lb; r *= 10)		;	for (t = 1; t < ub; t *= 10)		;	if (side == 'x')		xquant = r / s;	else		yquant = r / s;	if (flg)		return;	if (ub / lb < 100) {		if (lb >= 5 * r)			r *= 5;		else if (lb >= 2 * r)			r *= 2;		if (ub * 5 <= t)			t /= 5;		else if (ub * 2 <= t)			t /= 2;		if (side == 'x') {			xtmin = r / s;			xtmax = t / s;		} else {			ytmin = r / s;			ytmax = t / s;		}	}}void iterator(double from, double to, int op, double by, char *fmt)	/* create an iterator */{	double x;	/* should validate limits, etc. */	/* punt for now */	dprintf("iterate from %g to %g by %g, op = %c, fmt=%s\n",		from, to, by, op, fmt ? fmt : "");	switch (op) {	case '+':	case ' ':		for (x = from; x <= to + (SLOP-1) * by; x += by)			if (fmt)				savetick(x, tostring(fmt));			else				dflt_tick(x);		break;	case '-':		for (x = from; x >= to; x -= by)			if (fmt)				savetick(x, tostring(fmt));			else				dflt_tick(x);		break;	case '*':		for (x = from; x <= SLOP * to; x *= by)			if (fmt)				savetick(x, tostring(fmt));			else				dflt_tick(x);		break;	case '/':		for (x = from; x >= to; x /= by)			if (fmt)				savetick(x, tostring(fmt));			else				dflt_tick(x);		break;	}	if (fmt)		free(fmt);}void ticklist(Obj *p, int explicit)	/* fire out the accumulated ticks */					/* 1 => list, 0 => auto */{	if (p == NULL)		return;	fprintf(tfd, "Ticks_%s:\n\tticklen = %g\n", p->name, ticklen);	print_ticks(TICKS, explicit, p, "ticklen", "");}void print_ticks(int type, int explicit, Obj *p, char *lenstr, char *descstr){	int i, logflag, inside;	char buf[100];	double tv;	for (i = 0; i < ntick; i++)	/* any ticks given explicitly? */		if (tickstr[i] != NULL)			break;	if (i >= ntick && type == TICKS)	/* no, so use values */		for (i = 0; i < ntick; i++) {			if (tickval[i] >= 0.0)				sprintf(buf, "%g", tickval[i]);			else				sprintf(buf, "\\-%g", -tickval[i]);			tickstr[i] = tostring(buf);		}	else		for (i = 0; i < ntick; i++) {			if (tickstr[i] != NULL) {				sprintf(buf, tickstr[i], tickval[i]);				free(tickstr[i]);				tickstr[i] = tostring(buf);			}		}	logflag = sidelog(p->log, tside);	for (i = 0; i < ntick; i++) {		tv = tickval[i];		halfrange(p, tside, tv);		if (logflag) {			if (tv <= 0.0)				ERROR "can't take log of tick value %g", tv FATAL;			logit(tv);		}		if (type == GRID)			inside = LEFT|RIGHT|TOP|BOT;		else if (explicit)			inside = (tick_dir == IN) ? tside : 0;		else			inside = autodir;		if (tside & BOT)			maketick(type, p->name, BOT, inside, tv, tickstr[i], lenstr, descstr);		if (tside & TOP)			maketick(type, p->name, TOP, inside, tv, tickstr[i], lenstr, descstr);		if (tside & LEFT)			maketick(type, p->name, LEFT, inside, tv, tickstr[i], lenstr, descstr);		if (tside & RIGHT)			maketick(type, p->name, RIGHT, inside, tv, tickstr[i], lenstr, descstr);		if (tickstr[i]) {			free(tickstr[i]);			tickstr[i] = NULL;		}	}	ntick = 0;}void maketick(int type, char *name, int side, int inflag, double val, char *lab, char *lenstr, char *descstr){	char *sidestr, *td;	fprintf(tfd, "\tline %s ", descstr);	inflag &= side;	switch (side) {	case BOT:	case 0:		td = inflag ? "up" : "down";		fprintf(tfd, "%s %s from (x_%s(%g),0)", td, lenstr, name, val);		break;	case TOP:		td = inflag ? "down" : "up";		fprintf(tfd, "%s %s from (x_%s(%g),frameht)", td, lenstr, name, val);		break;	case LEFT:		td = inflag ? "right" : "left";		fprintf(tfd, "%s %s from (0,y_%s(%g))", td, lenstr, name, val);		break;	case RIGHT:		td = inflag ? "left" : "right";		fprintf(tfd, "%s %s from (framewid,y_%s(%g))", td, lenstr, name, val);		break;	}	fprintf(tfd, "\n");	if (type == GRID && (side & goffside))	/* wanted no ticks on grid */		return;	sidestr = tick_dir == IN ? "start" : "end";	if (lab != NULL) {		/* BUG: should fix size of lab here */		double wid = strlen(lab)/7.5 + (tick_dir == IN ? 0 : 0.1);	/* estimate width at 15 chars/inch */		switch (side) {		case BOT: case 0:			/* can drop "box invis" with new pic */			fprintf(tfd, "\tbox invis \"%s\" ht .25 wid 0 with .n at last line.%s",				lab, sidestr);			break;		case TOP:			fprintf(tfd, "\tbox invis \"%s\" ht .2 wid 0 with .s at last line.%s",				lab, sidestr);			break;		case LEFT:			fprintf(tfd, "\t\"%s \" wid %.2f rjust at last line.%s",				lab, wid, sidestr);			break;		case RIGHT:			fprintf(tfd, "\t\" %s\" wid %.2f ljust at last line.%s",				lab, wid, sidestr);			break;		}		/* BUG: works only if "down x" comes before "at wherever" */		lab_adjust();		fprintf(tfd, "\n");	}}Attr	*grid_desc	= 0;void griddesc(Attr *a){	grid_desc = a;}void gridlist(Obj *p){	char *framestr;	if ((tside & (BOT|TOP)) || tside == 0)		framestr = "frameht";	else		framestr = "framewid";	fprintf(tfd, "Grid_%s:\n", p->name);	tick_dir = IN;	print_ticks(GRID, 0, p, framestr, desc_str(grid_desc));	if (grid_desc) {		freeattr(grid_desc);		grid_desc = 0;	}}char *desc_str(Attr *a)	/* convert DOT to "dotted", etc. */{	static char buf[50], *p;	if (a == NULL)		return p = "";	switch (a->type) {	case DOT:	p = "dotted"; break;	case DASH:	p = "dashed"; break;	case INVIS:	p = "invis"; break;	default:	p = "";	}	if (a->fval != 0.0) {		sprintf(buf, "%s %g", p, a->fval);		return buf;	} else		return p;}sidelog(int logflag, int side)	/* figure out whether to scale a side */{	if ((logflag & XFLAG) && ((side & (BOT|TOP)) || side == 0))		return 1;	else if ((logflag & YFLAG) && (side & (LEFT|RIGHT)))		return 1;	else		return 0;}

⌨️ 快捷键说明

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