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

📄 world.c

📁 linux的图形界面程序
💻 C
字号:
/* * Draw a crude map of the world using mini-X graphics on MINIX. * Converted from an Amiga program by Mike Groshart and Bob Dufford. * Author: David I. Bell * * ported to 16 bit systems by Greg Haerr */#include <stdio.h>#include <string.h>#include "nano-X.h"#if MSDOS#include <fcntl.h>#endif#ifndef O_BINARY#define O_BINARY 	0#endif#define	MAPFILE	"demos/nanox/world.map"		/* was /usr/lib*/#define	SELECTBUTTON	GR_BUTTON_L#define	COORDBUTTON	GR_BUTTON_R/* * Definitions to use fixed point in place of true floating point. */typedef	long	FLOAT;#define	SCALE	100		/* fixed point scaling factor */#define	FFMUL(a,b)	(((FLOAT)(a) * (b) + (SCALE / 2)) / SCALE)#define	FFDIV(a,b)	(((FLOAT)(a) * SCALE) / (b))#define	FIMUL(a,b)	((FLOAT)(a) * (b))#define	FIDIV(a,b)	((FLOAT)(a) / (b))#define	ITOF(a)		((FLOAT)(a) * SCALE)#define	FTOI(a)		(((FLOAT)(a) + (SCALE / 2)) / SCALE)#define	QSPAN	(90L*60*SCALE)	/* equator to pole (90 degrees) */#define HSPAN	(QSPAN*2)	/* pole to pole (180 degrees) */#define WSPAN	(QSPAN*4)	/* around equator (360 degrees) */#define	ABS(n)	(((n) < 0) ? -(n) : (n))/* * Structure of a point in the database file. */typedef struct {	short	Code;		/* type of point (see code_colors below) */	short	Lat;		/* latitude in minutes */	short	Lon;		/* longitude in minutes */} DBPOINT;#define POINTSize	sizeof(DBPOINT)#define PCount		1024		/* number of points to read at once *//* * The following variables are the scaling factors to be used when drawing * points.  However, they are larger than the true value by a factor of 60. * This is done because without real floating point, their true values are * too small to be accurate enough.  I cannot just increase the fixed point * precision because that causes overflows.  What a pain! */static	FLOAT		X_Scale;static	FLOAT		Y_Scale;/* * Other variables. */static	FLOAT		Latitude, Longitude;	/* current center of view */static	FLOAT		zoom;		/* current zoom scaling factor */static	FLOAT		latradius;	/* half of view of latitide */static	FLOAT		longradius;	/* half of view of longitude */static	FLOAT		viewlong;	/* amount of longitide in view */static	FLOAT		viewlat;	/* amount of latitude in view */static	GR_SIZE		mapwidth;	/* width of map in pixels */static	GR_SIZE		mapheight;	/* height of map in pixels */static	GR_COORD	mapxorig;	/* one half of map width */static	GR_COORD	mapyorig;	/* one half of map height */static	GR_COORD	selectx;	/* x position of current selection */static	GR_COORD	selecty;	/* y position of current selection */static	GR_COORD	selectptrx;	/* x position of pointer in selection */static	GR_COORD	selectptry;	/* y position of pointer in selection */static	GR_SIZE		selectwidth;	/* width of current selection */static	GR_SIZE		selectheight;	/* height of current selection */static	int		selectmode;	/* selection mode */static	GR_BOOL		selectvisible;	/* TRUE if selection is visible on screen */static	GR_SIZE		selectxscale;	/* x scaling factor for selection rectangle */static	GR_SIZE		selectyscale;	/* y scaling factor for selection rectangle */static	GR_BOOL		coordvisible;	/* TRUE if coordinates are visible on screen */static	GR_BOOL		coordenabled;	/* TRUE if coordinate display is enabled */static	GR_COORD	coordx;		/* x position of coordinates */static	GR_COORD	coordy;		/* y position of coordinates */static	GR_COORD	ptrx;		/* latest x position of pointer */static	GR_COORD	ptry;		/* latest y position of pointer */static	char		coordstring[32];	/* coordinate string */static	GR_WINDOW_ID	mainwid;	/* main window id */static	GR_WINDOW_ID	mapwid;		/* window id for map */static	GR_GC_ID	mapgc;		/* GC used for drawing map */static	GR_GC_ID	xorgc;		/* GC used for rubber banding *//* * Current selection mode */#define	SELECT_NONE	0#define	SELECT_SCALE	1#define	SELECT_MOVE	2/* * Order of color table (indexed by type of point): *	unused *	continents *	countries *	unused *	USA states *	islands *	lakes *	rivers */static	GR_COLOR	code_colors[] = {	BLACK, GREEN, RED, BLACK, BROWN, GREEN, BLUE, BLUE};static	void	load();static	void	setzoom();static	void	checkevent();static	void	doexposure();static	void	dobuttondown();static	void	dobuttonup();static	void	doposition();static	void	dokeydown();static	void	showselection();static	void	showcoords();static	void	mintostr();intmain(argc, argv)	char	**argv;{	GR_SCREEN_INFO	si;	if (GrOpen() < 0) {		fprintf(stderr, "Cannot open graphics\n");		exit(1);	}	GrGetScreenInfo(&si);	mainwid = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, si.cols, si.rows,		0, BLACK, BLACK);	mapwidth = si.cols - 2;	mapheight = si.rows - 2;	mapxorig = mapwidth / 2;	mapyorig = mapheight / 2;	selectxscale = 4;	selectyscale = 3;	coordx = 0;	coordy = si.rows - 1;	mapwid = GrNewWindow(mainwid, 1, 1, mapwidth, mapheight,		1, BLACK, WHITE);	GrSelectEvents(mapwid, GR_EVENT_MASK_EXPOSURE |		GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP |		GR_EVENT_MASK_MOUSE_POSITION | GR_EVENT_MASK_KEY_DOWN);	GrMapWindow(mainwid);	GrMapWindow(mapwid);	mapgc = GrNewGC();	xorgc = GrNewGC();	GrSetGCMode(xorgc, GR_MODE_XOR);	Longitude = ITOF(0);	Latitude = ITOF(0);	setzoom(ITOF(1));	while (1)		checkevent();}static voidcheckevent(){	GR_EVENT	event;	GrGetNextEvent(&event);	switch (event.type) {		case GR_EVENT_TYPE_EXPOSURE:			doexposure(&event.exposure);			break;		case GR_EVENT_TYPE_BUTTON_DOWN:			dobuttondown(&event.button);			break;		case GR_EVENT_TYPE_BUTTON_UP:			dobuttonup(&event.button);			break;		case GR_EVENT_TYPE_MOUSE_POSITION:			doposition(&event.mouse);			break;		case GR_EVENT_TYPE_KEY_DOWN:			dokeydown(&event.keystroke);			break;	}}static voiddoexposure(ep)	GR_EVENT_EXPOSURE	*ep;{	if (ep->wid != mapwid)		return;	GrClearWindow(mapwid, GR_FALSE);	selectvisible = GR_FALSE;	coordvisible = GR_FALSE;	load(MAPFILE);	showselection(GR_TRUE);	showcoords(GR_TRUE);}static voiddobuttondown(bp)	GR_EVENT_BUTTON	*bp;{	if (bp->wid != mapwid)		return;	if (bp->changebuttons & SELECTBUTTON) {		showselection(GR_FALSE);		selectx = bp->x;		selecty = bp->y;		selectptrx = bp->x;		selectptry = bp->y;		selectwidth = 0;		selectheight = 0;		selectmode = SELECT_SCALE;		showselection(GR_TRUE);	}	if (bp->changebuttons & COORDBUTTON) {		showcoords(GR_FALSE);		ptrx = bp->x;		ptry = bp->y;		coordenabled = GR_TRUE;		showcoords(GR_TRUE);	}}static voiddobuttonup(bp)	GR_EVENT_BUTTON	*bp;{	if (bp->wid != mapwid)		return;	if (bp->changebuttons & COORDBUTTON) {		showcoords(GR_FALSE);		coordenabled = GR_FALSE;	}	if (bp->changebuttons & SELECTBUTTON) {		showselection(GR_FALSE);		if (selectmode == SELECT_NONE)			return;		selectmode = SELECT_NONE;		if (selectwidth <= 0)			return;		Longitude +=			FIDIV(FIMUL(viewlong, selectx - mapxorig), mapwidth);		Latitude -=			FIDIV(FIMUL(viewlat, selecty - mapyorig), mapheight);		setzoom(FIDIV(FIMUL(zoom, mapwidth), selectwidth));		GrClearWindow(mapwid, GR_TRUE);	}}static voiddoposition(mp)	GR_EVENT_MOUSE	*mp;{	GR_SIZE	temp;	if (mp->wid != mapwid)		return;	if (coordenabled) {		showcoords(GR_FALSE);		ptrx = mp->x;		ptry = mp->y;		showcoords(GR_TRUE);	}	showselection(GR_FALSE);	switch (selectmode) {		case SELECT_SCALE:			selectwidth = ABS(mp->x - selectx) * 2 + 1;			selectheight = ABS(mp->y - selecty) * 2 + 1;			temp = ((long) selectwidth) * selectyscale				/ selectxscale;			if (selectheight < temp)				selectheight = temp;			temp = ((long) selectheight) * selectxscale				/ selectyscale;			if (selectwidth < temp)				selectwidth = temp;			break;		case SELECT_MOVE:			selectx += (mp->x - selectptrx);			selecty += (mp->y - selectptry);			break;	}	selectptrx = mp->x;	selectptry = mp->y;	showselection(GR_TRUE);}static voiddokeydown(kp)	GR_EVENT_KEYSTROKE	*kp;{	if (kp->wid != mapwid)		return;	if (selectmode != SELECT_NONE) {		switch (kp->ch) {			case 's':	/* scale selection */				selectmode = SELECT_SCALE;				break;			case 'm':	/* move selection */				selectmode = SELECT_MOVE;				break;			case '\033':	/* cancel selection */				showselection(GR_FALSE);				selectmode = SELECT_NONE;				break;		}		return;	}	switch (kp->ch) {		case 'q':		/* quit */		case 'Q':			GrClose();			exit(0);		case 't':		/* redraw total map */			Longitude = ITOF(0);			Latitude = ITOF(0);			setzoom(ITOF(1));			GrClearWindow(mapwid, GR_TRUE);	}}/* * Draw or erase the current selection if any is defined. * The selection is a rectangle centered on a specified point, and with a * specified width and height.  Drawing and erasing the selection are the * same drawing operation because of the XOR operation. */static voidshowselection(show)	GR_BOOL	show;		/* TRUE if show the selection */{	if ((show == 0) == (selectvisible == 0))		return;	if (selectmode == SELECT_NONE)		return;	GrRect(mapwid, xorgc, selectx - selectwidth / 2,		selecty - selectheight / 2, selectwidth, selectheight);	selectvisible = show;}/* * Draw or erase the coordinate string of the current pointer position. * Both of these are the same operation because of the XOR operation. */static voidshowcoords(show)	GR_BOOL	show;		/* TRUE if show the coordinates */{	long	curlong;	long	curlat;	FLOAT	ptrlat;	FLOAT	ptrlong;	if (((show == 0) == (coordvisible == 0)) || !coordenabled)		return;	if (show) {		ptrlat = FIDIV(FIMUL(viewlat, ptry), mapheight - 1);		ptrlong = FIDIV(FIMUL(viewlong, ptrx), mapwidth - 1);		curlat = FTOI(Latitude + latradius - ptrlat);		curlong = FTOI(Longitude - longradius + ptrlong);		if (curlong > 180*60)			curlong -= 360*60;		if (curlong < -180*60)			curlong += 360*60;		mintostr(coordstring, curlong);		strcat(coordstring, "  ");		mintostr(coordstring + strlen(coordstring), curlat);	}	GrText(mapwid, xorgc, coordx, coordy, coordstring, strlen(coordstring));	coordvisible = show;}/* * Convert minutes to a string of the form "ddd'mm" and store it * into the indicated buffer. */static voidmintostr(buf, min)	char	*buf;	long	min;{	if (min < 0) {		min = -min;		*buf++ = '-';	}	sprintf(buf, "%d'%02d", min / 60, min % 60);}#if 0/* * Convert "ddd'mm" to mins */static longdegtomin(s)	char	*s;{	int	deg, min;	char	str[10],*strchr(),*cp;	strcpy(str,s);	if (cp = strchr(str,'\047')) {		*cp = '\0';		min = atoi(++cp);	} else		min = 0;	if ((deg = atoi(str)) < 0)		min = -min;	return(deg * 60 + min);}#endif/* * Set the scale factors for the given zoom factor. * The factors 3 and 4 are here to compensate for the screen aspect ratio. */static voidsetzoom(newzoom)	FLOAT	newzoom;{	zoom = newzoom;	Y_Scale = FIDIV(FIMUL(zoom, mapheight * 3), 180 * 4);	X_Scale = FIDIV(FIMUL(zoom, mapwidth), 360);	viewlong = FFDIV(WSPAN, zoom);	viewlat = FFDIV(HSPAN * 4 / 3, zoom);	longradius = FIDIV(viewlong, 2);	latradius = FIDIV(viewlat, 2);}/* * Read the database file and draw the world. */static voidload(fn)	char	*fn;{	register DBPOINT	*pp;	DBPOINT		*pend;	FLOAT		x, y, LonPrv, LatPrv;	long		oldlong;	GR_COORD	xnew, ynew;	GR_COORD	xold, yold;	GR_BOOL		is_out;	GR_BOOL		was_out;	GR_BOOL		newseg;	GR_COLOR	oldcolor;	GR_COLOR	newcolor;	int		n;	int		fh;	DBPOINT		p[PCount];	LonPrv = ITOF(0);	LatPrv = ITOF(0);	oldcolor = -1;	is_out = GR_FALSE;	was_out = GR_FALSE;	fh = open(fn, O_BINARY);	if (fh < 0) {		GrClose();		fprintf(stderr, "Cannot open %s\n", fn);		exit(1);	}	while ((n = read(fh, p, PCount * POINTSize)) > 0) {		for (pp = p,pend = p + n/POINTSize; pp < pend; pp++)		{			/* do displacement */			x = ITOF(pp->Lon) - Longitude;			y = ITOF(pp->Lat) - Latitude;			/* wrap around for East-West */			if (x < -HSPAN)				x += WSPAN;			if (x > HSPAN)				x -= WSPAN;			if (pp->Code > 5) {				newcolor = code_colors[pp->Code / 1000];				if (newcolor != oldcolor) {					oldcolor = newcolor;					GrSetGCForeground(mapgc, oldcolor);				}				newseg = GR_TRUE;			}			if (oldcolor == BLACK)				goto go_on;			/* ignore points outside magnified area */			if ((x < -longradius || x > longradius ||				y < -latradius || y > latradius))			{				is_out = 1;				if (was_out) {		/* out to out */					LonPrv = x;					LatPrv = y;					goto go_on;				}				/* in to out */				xold = mapxorig + FTOI(FFMUL(LonPrv, X_Scale)) / 60;				yold = mapyorig - FTOI(FFMUL(LatPrv, Y_Scale)) / 60;			} else {			/* out to in */				is_out = 0;				if (was_out) {					xold = mapxorig +						FTOI(FFMUL(LonPrv, X_Scale)) / 60;					yold = mapyorig -						FTOI(FFMUL(LatPrv, Y_Scale)) / 60;				}				/* in to in */			}			LonPrv = x;			LatPrv = y;			/* scale points w/in area to interlace screen */			xnew = mapxorig + FTOI(FFMUL(x, X_Scale)) / 60;			ynew = mapyorig - FTOI(FFMUL(y, Y_Scale)) / 60;			/* if new segment, move to place */			if (newseg || ABS(oldlong - pp->Lon) > 180*60) {				xold = xnew;				yold = ynew;			}			oldlong = pp->Lon;			GrLine(mapwid, mapgc, xold, yold, xnew, ynew);			xold = xnew;			yold = ynew;go_on:			was_out = is_out;			newseg = GR_FALSE;		}	}	close(fh);}/* END CODE */

⌨️ 快捷键说明

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