2 * Draw a crude map of the world using mini-X graphics on MINIX.
3 * Converted from an Amiga program by Mike Groshart and Bob Dufford.
4 * Author: David I. Bell
6 * ported to 16 bit systems by Greg Haerr
10 #define MWINCLUDECOLORS
13 #if defined(MSDOS) || defined(__ECOS)
18 #include <sys/types.h>
28 #if defined(DOS_DJGPP) || defined(__ECOS)
29 #define MAPFILE "world.map"
31 #define MAPFILE "demos/nanox/world.map" /* was /usr/lib*/
34 #define SELECTBUTTON GR_BUTTON_L
35 #define COORDBUTTON GR_BUTTON_R
39 * Definitions to use fixed point in place of true floating point.
43 #define SCALE 100 /* fixed point scaling factor */
45 #define FFMUL(a,b) (((FLOAT)(a) * (b) + (SCALE / 2)) / SCALE)
46 #define FFDIV(a,b) (((FLOAT)(a) * SCALE) / (b))
47 #define FIMUL(a,b) ((FLOAT)(a) * (b))
48 #define FIDIV(a,b) ((FLOAT)(a) / (b))
49 #define ITOF(a) ((FLOAT)(a) * SCALE)
50 #define FTOI(a) (((FLOAT)(a) + (SCALE / 2)) / SCALE)
53 #define QSPAN (90L*60*SCALE) /* equator to pole (90 degrees) */
54 #define HSPAN (QSPAN*2) /* pole to pole (180 degrees) */
55 #define WSPAN (QSPAN*4) /* around equator (360 degrees) */
57 #define ABS(n) (((n) < 0) ? -(n) : (n))
61 * Structure of a point in the database file.
64 short Code; /* type of point (see code_colors below) */
65 short Lat; /* latitude in minutes */
66 short Lon; /* longitude in minutes */
70 #define SHORT_SWAP(p) (p = ((p & 0xff) << 8) | ((p >> 8) & 0xff))
71 #define DBPOINT_CONVERT(p) (SHORT_SWAP(p->Code),SHORT_SWAP(p->Lat),SHORT_SWAP(p->Lon))
73 #define DBPOINT_CONVERT(p) ((void)p)
76 #define POINTSize sizeof(DBPOINT)
77 #define PCount 128 /* number of points to read at once */
81 * The following variables are the scaling factors to be used when drawing
82 * points. However, they are larger than the true value by a factor of 60.
83 * This is done because without real floating point, their true values are
84 * too small to be accurate enough. I cannot just increase the fixed point
85 * precision because that causes overflows. What a pain!
93 static FLOAT Latitude, Longitude; /* current center of view */
94 static FLOAT zoom; /* current zoom scaling factor */
96 static FLOAT latradius; /* half of view of latitide */
97 static FLOAT longradius; /* half of view of longitude */
98 static FLOAT viewlong; /* amount of longitide in view */
99 static FLOAT viewlat; /* amount of latitude in view */
101 static GR_SIZE mapwidth; /* width of map in pixels */
102 static GR_SIZE mapheight; /* height of map in pixels */
103 static GR_COORD mapxorig; /* one half of map width */
104 static GR_COORD mapyorig; /* one half of map height */
105 static GR_COORD selectx; /* x position of current selection */
106 static GR_COORD selecty; /* y position of current selection */
107 static GR_COORD selectptrx; /* x position of pointer in selection */
108 static GR_COORD selectptry; /* y position of pointer in selection */
109 static GR_SIZE selectwidth; /* width of current selection */
110 static GR_SIZE selectheight; /* height of current selection */
111 static int selectmode; /* selection mode */
112 static GR_BOOL selectvisible; /* TRUE if selection is visible on screen */
113 static GR_SIZE selectxscale; /* x scaling factor for selection rectangle */
114 static GR_SIZE selectyscale; /* y scaling factor for selection rectangle */
115 static GR_BOOL coordvisible; /* TRUE if coordinates are visible on screen */
116 static GR_BOOL coordenabled; /* TRUE if coordinate display is enabled */
117 static GR_COORD coordx; /* x position of coordinates */
118 static GR_COORD coordy; /* y position of coordinates */
119 static GR_COORD ptrx; /* latest x position of pointer */
120 static GR_COORD ptry; /* latest y position of pointer */
121 static char coordstring[32]; /* coordinate string */
123 static GR_WINDOW_ID mainwid; /* main window id */
124 static GR_WINDOW_ID mapwid; /* window id for map */
125 static GR_GC_ID mapgc; /* GC used for drawing map */
126 static GR_GC_ID xorgc; /* GC used for rubber banding */
127 static GR_SIZE COLS, ROWS;
131 * Current selection mode
133 #define SELECT_NONE 0
134 #define SELECT_SCALE 1
135 #define SELECT_MOVE 2
138 * Order of color table (indexed by type of point):
148 static GR_COLOR code_colors[] = {
149 BLACK, GREEN, RED, BLACK, BROWN, GREEN, BLUE, BLUE
154 static void setzoom();
155 static void checkevent();
156 static void doexposure();
157 static void dobuttondown();
158 static void dobuttonup();
159 static void doposition();
160 static void dokeydown();
161 static void showselection();
162 static void showcoords();
163 static void mintostr();
168 world_main(int argc, char **argv)
171 main(int argc, char **argv)
175 GR_WM_PROPERTIES props;
178 fprintf(stderr, "Cannot open graphics\n");
182 GrReqShmCmds(65536); /* Test by Morten Rolland for shm support */
184 GrGetScreenInfo(&si);
194 mainwid = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, COLS, ROWS,
198 props.flags = GR_WM_FLAGS_TITLE | GR_WM_FLAGS_PROPS;
199 props.props = GR_WM_PROPS_BORDER | GR_WM_PROPS_CAPTION;
200 props.title = "NanoX World Map";
201 GrSetWMProperties(mainwid, &props);
204 mapheight = ROWS - 2;
205 mapxorig = mapwidth / 2;
206 mapyorig = mapheight / 2;
211 mapwid = GrNewWindow(mainwid, 1, 1, mapwidth, mapheight,
217 GrSelectEvents(mainwid, GR_EVENT_MASK_CLOSE_REQ);
218 GrSelectEvents(mapwid, GR_EVENT_MASK_EXPOSURE |
219 GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP |
220 GR_EVENT_MASK_MOUSE_POSITION | GR_EVENT_MASK_KEY_DOWN);
222 GrMapWindow(mainwid);
227 GrSetGCMode(xorgc, GR_MODE_XOR);
243 GrGetNextEvent(&event);
244 switch (event.type) {
245 case GR_EVENT_TYPE_EXPOSURE:
246 doexposure(&event.exposure);
248 case GR_EVENT_TYPE_BUTTON_DOWN:
249 dobuttondown(&event.button);
251 case GR_EVENT_TYPE_BUTTON_UP:
252 dobuttonup(&event.button);
254 case GR_EVENT_TYPE_MOUSE_POSITION:
255 doposition(&event.mouse);
257 case GR_EVENT_TYPE_KEY_DOWN:
258 dokeydown(&event.keystroke);
260 case GR_EVENT_TYPE_CLOSE_REQ:
269 GR_EVENT_EXPOSURE *ep;
271 if (ep->wid != mapwid)
274 /* removed: helps with blink with nanowm*/
275 /*GrClearWindow(mapwid, GR_FALSE);*/
276 selectvisible = GR_FALSE;
277 coordvisible = GR_FALSE;
279 showselection(GR_TRUE);
288 if (bp->wid != mapwid)
291 if (bp->changebuttons & SELECTBUTTON) {
292 showselection(GR_FALSE);
299 selectmode = SELECT_SCALE;
300 showselection(GR_TRUE);
303 if (bp->changebuttons & COORDBUTTON) {
304 showcoords(GR_FALSE);
307 coordenabled = GR_TRUE;
317 if (bp->wid != mapwid)
320 if (bp->changebuttons & COORDBUTTON) {
321 showcoords(GR_FALSE);
322 coordenabled = GR_FALSE;
325 if (bp->changebuttons & SELECTBUTTON) {
326 showselection(GR_FALSE);
327 if (selectmode == SELECT_NONE)
329 selectmode = SELECT_NONE;
330 if (selectwidth <= 0)
333 FIDIV(FIMUL(viewlong, selectx - mapxorig), mapwidth);
335 FIDIV(FIMUL(viewlat, selecty - mapyorig), mapheight);
336 setzoom(FIDIV(FIMUL(zoom, mapwidth), selectwidth));
337 GrClearWindow(mapwid, GR_TRUE);
348 if (mp->wid != mapwid)
352 showcoords(GR_FALSE);
358 showselection(GR_FALSE);
359 switch (selectmode) {
361 selectwidth = ABS(mp->x - selectx) * 2 + 1;
362 selectheight = ABS(mp->y - selecty) * 2 + 1;
363 temp = ((long) selectwidth) * selectyscale
365 if (selectheight < temp)
367 temp = ((long) selectheight) * selectxscale
369 if (selectwidth < temp)
374 selectx += (mp->x - selectptrx);
375 selecty += (mp->y - selectptry);
381 showselection(GR_TRUE);
387 GR_EVENT_KEYSTROKE *kp;
389 if (kp->wid != mapwid)
392 if (selectmode != SELECT_NONE) {
394 case 's': /* scale selection */
395 selectmode = SELECT_SCALE;
398 case 'm': /* move selection */
399 selectmode = SELECT_MOVE;
402 case '\033': /* cancel selection */
403 showselection(GR_FALSE);
404 selectmode = SELECT_NONE;
416 case 't': /* redraw total map */
420 GrClearWindow(mapwid, GR_TRUE);
426 * Draw or erase the current selection if any is defined.
427 * The selection is a rectangle centered on a specified point, and with a
428 * specified width and height. Drawing and erasing the selection are the
429 * same drawing operation because of the XOR operation.
433 GR_BOOL show; /* TRUE if show the selection */
435 if ((show == 0) == (selectvisible == 0))
437 if (selectmode == SELECT_NONE)
439 GrRect(mapwid, xorgc, selectx - selectwidth / 2,
440 selecty - selectheight / 2, selectwidth, selectheight);
441 selectvisible = show;
446 * Draw or erase the coordinate string of the current pointer position.
447 * Both of these are the same operation because of the XOR operation.
451 GR_BOOL show; /* TRUE if show the coordinates */
458 if (((show == 0) == (coordvisible == 0)) || !coordenabled)
462 ptrlat = FIDIV(FIMUL(viewlat, ptry), mapheight - 1);
463 ptrlong = FIDIV(FIMUL(viewlong, ptrx), mapwidth - 1);
465 curlat = FTOI(Latitude + latradius - ptrlat);
466 curlong = FTOI(Longitude - longradius + ptrlong);
468 if (curlong > 180*60)
470 if (curlong < -180*60)
473 mintostr(coordstring, curlong);
474 strcat(coordstring, " ");
475 mintostr(coordstring + strlen(coordstring), curlat);
478 GrText(mapwid, xorgc, coordx, coordy, coordstring, -1, GR_TFBOTTOM);
484 * Convert minutes to a string of the form "ddd'mm" and store it
485 * into the indicated buffer.
488 mintostr(buf, minutes)
496 sprintf(buf, "%ld'%02ld", (long)(minutes / 60), (long)(minutes % 60));
502 * Convert "ddd'mm" to mins
509 char str[10],*strchr(),*cp;
512 if (cp = strchr(str,'\047')) {
514 minutes = atoi(++cp);
517 if ((deg = atoi(str)) < 0)
519 return(deg * 60 + minutes);
525 * Set the scale factors for the given zoom factor.
526 * The factors 3 and 4 are here to compensate for the screen aspect ratio.
534 Y_Scale = FIDIV(FIMUL(zoom, mapheight * 3), 180 * 4);
535 X_Scale = FIDIV(FIMUL(zoom, mapwidth), 360);
537 viewlong = FFDIV(WSPAN, zoom);
538 viewlat = FFDIV(HSPAN * 4 / 3, zoom);
539 longradius = FIDIV(viewlong, 2);
540 latradius = FIDIV(viewlat, 2);
545 * Read the database file and draw the world.
551 register DBPOINT *pp;
553 FLOAT x, y, LonPrv, LatPrv;
556 GR_COORD xold = 0, yold = 0;
559 GR_BOOL newseg = GR_FALSE;
572 fh = open(fn, O_BINARY | O_RDONLY);
575 fprintf(stderr, "Cannot open %s\n", fn);
579 while ((n = read(fh, p, PCount * POINTSize)) > 0) {
580 for (pp = p,pend = p + n/POINTSize; pp < pend; pp++)
583 /* do displacement */
584 x = ITOF(pp->Lon) - Longitude;
585 y = ITOF(pp->Lat) - Latitude;
587 /* wrap around for East-West */
594 newcolor = code_colors[pp->Code / 1000];
595 if (newcolor != oldcolor) {
597 GrSetGCForeground(mapgc, oldcolor);
602 if (oldcolor == BLACK)
605 /* ignore points outside magnified area */
606 if ((x < -longradius || x > longradius ||
607 y < -latradius || y > latradius))
610 if (was_out) { /* out to out */
617 xold = mapxorig + FTOI(FFMUL(LonPrv, X_Scale)) / 60;
618 yold = mapyorig - FTOI(FFMUL(LatPrv, Y_Scale)) / 60;
619 } else { /* out to in */
623 FTOI(FFMUL(LonPrv, X_Scale)) / 60;
625 FTOI(FFMUL(LatPrv, Y_Scale)) / 60;
632 /* scale points w/in area to interlace screen */
633 xnew = mapxorig + FTOI(FFMUL(x, X_Scale)) / 60;
634 ynew = mapyorig - FTOI(FFMUL(y, Y_Scale)) / 60;
636 /* if new segment, move to place */
637 if (newseg || ABS(oldlong - pp->Lon) > 180*60) {
643 GrLine(mapwid, mapgc, xold, yold, xnew, ynew);