OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [MW_0_8_9PRE7/] [mw/] [src/] [demos/] [nanox/] [world.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 673 markom
/*
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
5
 *
6
 * ported to 16 bit systems by Greg Haerr
7
 */
8
#include <stdio.h>
9
#include <string.h>
10
#define MWINCLUDECOLORS
11
#include "nano-X.h"
12
 
13
#if defined(MSDOS) || defined(__ECOS)
14
#include <fcntl.h>
15
#endif
16
 
17
#if LINUX | DOS_DJGPP
18
#include <sys/types.h>
19
#include <sys/stat.h>
20
#include <fcntl.h>
21
#include <unistd.h>
22
#endif
23
 
24
#ifndef O_BINARY
25
#define O_BINARY        0
26
#endif
27
 
28
#if defined(DOS_DJGPP) || defined(__ECOS)
29
#define MAPFILE "/world.map"
30
#else
31
#define MAPFILE "demos/nanox/world.map"         /* was /usr/lib*/
32
#endif
33
 
34
#define SELECTBUTTON    GR_BUTTON_L
35
#define COORDBUTTON     GR_BUTTON_R
36
 
37
 
38
/*
39
 * Definitions to use fixed point in place of true floating point.
40
 */
41
typedef long    FLOAT;
42
 
43
#define SCALE   100             /* fixed point scaling factor */
44
 
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)
51
 
52
 
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) */
56
 
57
#define ABS(n)  (((n) < 0) ? -(n) : (n))
58
 
59
 
60
/*
61
 * Structure of a point in the database file.
62
 */
63
typedef struct {
64
        short   Code;           /* type of point (see code_colors below) */
65
        short   Lat;            /* latitude in minutes */
66
        short   Lon;            /* longitude in minutes */
67
} MWPACKED DBPOINT;
68
 
69
#if BIGENDIAN
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))
72
#else
73
#define DBPOINT_CONVERT(p)      ((void)p)
74
#endif
75
 
76
#define POINTSize       sizeof(DBPOINT)
77
#define PCount          128             /* number of points to read at once */
78
 
79
 
80
/*
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!
86
 */
87
static  FLOAT           X_Scale;
88
static  FLOAT           Y_Scale;
89
 
90
/*
91
 * Other variables.
92
 */
93
static  FLOAT           Latitude, Longitude;    /* current center of view */
94
static  FLOAT           zoom;           /* current zoom scaling factor */
95
 
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 */
100
 
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 */
122
 
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;
128
 
129
 
130
/*
131
 * Current selection mode
132
 */
133
#define SELECT_NONE     0
134
#define SELECT_SCALE    1
135
#define SELECT_MOVE     2
136
 
137
/*
138
 * Order of color table (indexed by type of point):
139
 *      unused
140
 *      continents
141
 *      countries
142
 *      unused
143
 *      USA states
144
 *      islands
145
 *      lakes
146
 *      rivers
147
 */
148
static  GR_COLOR        code_colors[] = {
149
        BLACK, GREEN, RED, BLACK, BROWN, GREEN, BLUE, BLUE
150
};
151
 
152
 
153
static  void    load();
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();
164
 
165
 
166
int
167
main(int argc, char **argv)
168
{
169
        GR_SCREEN_INFO  si;
170
        GR_WM_PROPERTIES props;
171
 
172
        if (GrOpen() < 0) {
173
                fprintf(stderr, "Cannot open graphics\n");
174
                exit(1);
175
        }
176
 
177
        GrReqShmCmds(65536); /* Test by Morten Rolland for shm support */
178
 
179
        GrGetScreenInfo(&si);
180
#ifdef __ECOS
181
/* 240x320 screen*/
182
COLS = si.cols - 10;
183
ROWS = si.rows - 40;
184
#else
185
COLS = si.cols - 40;
186
ROWS = si.rows - 80;
187
#endif
188
 
189
        mainwid = GrNewWindow(GR_ROOT_WINDOW_ID, 0, 0, COLS, ROWS,
190
                0, BLACK, BLACK);
191
 
192
        /* set title */
193
        props.flags = GR_WM_FLAGS_TITLE | GR_WM_FLAGS_PROPS;
194
        props.props = GR_WM_PROPS_BORDER | GR_WM_PROPS_CAPTION;
195
        props.title = "NanoX World Map";
196
        GrSetWMProperties(mainwid, &props);
197
 
198
        mapwidth = COLS - 2;
199
        mapheight = ROWS - 2;
200
        mapxorig = mapwidth / 2;
201
        mapyorig = mapheight / 2;
202
        selectxscale = 4;
203
        selectyscale = 3;
204
        coordx = 0;
205
        coordy = ROWS - 1;
206
        mapwid = GrNewWindow(mainwid, 1, 1, mapwidth, mapheight,
207
#if 0
208
                1, BLACK, WHITE);
209
#else
210
                1, LTGRAY, BLACK);
211
#endif
212
        GrSelectEvents(mainwid, GR_EVENT_MASK_CLOSE_REQ);
213
        GrSelectEvents(mapwid, GR_EVENT_MASK_EXPOSURE |
214
                GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP |
215
                GR_EVENT_MASK_MOUSE_POSITION | GR_EVENT_MASK_KEY_DOWN);
216
 
217
        GrMapWindow(mainwid);
218
        GrMapWindow(mapwid);
219
 
220
        mapgc = GrNewGC();
221
        xorgc = GrNewGC();
222
        GrSetGCMode(xorgc, GR_MODE_XOR);
223
 
224
        Longitude = ITOF(0);
225
        Latitude = ITOF(0);
226
        setzoom(ITOF(1));
227
 
228
        while (1)
229
                checkevent();
230
}
231
 
232
 
233
static void
234
checkevent()
235
{
236
        GR_EVENT        event;
237
 
238
        GrGetNextEvent(&event);
239
        switch (event.type) {
240
                case GR_EVENT_TYPE_EXPOSURE:
241
                        doexposure(&event.exposure);
242
                        break;
243
                case GR_EVENT_TYPE_BUTTON_DOWN:
244
                        dobuttondown(&event.button);
245
                        break;
246
                case GR_EVENT_TYPE_BUTTON_UP:
247
                        dobuttonup(&event.button);
248
                        break;
249
                case GR_EVENT_TYPE_MOUSE_POSITION:
250
                        doposition(&event.mouse);
251
                        break;
252
                case GR_EVENT_TYPE_KEY_DOWN:
253
                        dokeydown(&event.keystroke);
254
                        break;
255
                case GR_EVENT_TYPE_CLOSE_REQ:
256
                        GrClose();
257
                        exit(0);
258
        }
259
}
260
 
261
 
262
static void
263
doexposure(ep)
264
        GR_EVENT_EXPOSURE       *ep;
265
{
266
        if (ep->wid != mapwid)
267
                return;
268
 
269
        /* removed: helps with blink with nanowm*/
270
        /*GrClearWindow(mapwid, GR_FALSE);*/
271
        selectvisible = GR_FALSE;
272
        coordvisible = GR_FALSE;
273
        load(MAPFILE);
274
        showselection(GR_TRUE);
275
        showcoords(GR_TRUE);
276
}
277
 
278
 
279
static void
280
dobuttondown(bp)
281
        GR_EVENT_BUTTON *bp;
282
{
283
        if (bp->wid != mapwid)
284
                return;
285
 
286
        if (bp->changebuttons & SELECTBUTTON) {
287
                showselection(GR_FALSE);
288
                selectx = bp->x;
289
                selecty = bp->y;
290
                selectptrx = bp->x;
291
                selectptry = bp->y;
292
                selectwidth = 0;
293
                selectheight = 0;
294
                selectmode = SELECT_SCALE;
295
                showselection(GR_TRUE);
296
        }
297
 
298
        if (bp->changebuttons & COORDBUTTON) {
299
                showcoords(GR_FALSE);
300
                ptrx = bp->x;
301
                ptry = bp->y;
302
                coordenabled = GR_TRUE;
303
                showcoords(GR_TRUE);
304
        }
305
}
306
 
307
 
308
static void
309
dobuttonup(bp)
310
        GR_EVENT_BUTTON *bp;
311
{
312
        if (bp->wid != mapwid)
313
                return;
314
 
315
        if (bp->changebuttons & COORDBUTTON) {
316
                showcoords(GR_FALSE);
317
                coordenabled = GR_FALSE;
318
        }
319
 
320
        if (bp->changebuttons & SELECTBUTTON) {
321
                showselection(GR_FALSE);
322
                if (selectmode == SELECT_NONE)
323
                        return;
324
                selectmode = SELECT_NONE;
325
                if (selectwidth <= 0)
326
                        return;
327
                Longitude +=
328
                        FIDIV(FIMUL(viewlong, selectx - mapxorig), mapwidth);
329
                Latitude -=
330
                        FIDIV(FIMUL(viewlat, selecty - mapyorig), mapheight);
331
                setzoom(FIDIV(FIMUL(zoom, mapwidth), selectwidth));
332
                GrClearWindow(mapwid, GR_TRUE);
333
        }
334
}
335
 
336
 
337
static void
338
doposition(mp)
339
        GR_EVENT_MOUSE  *mp;
340
{
341
        GR_SIZE temp;
342
 
343
        if (mp->wid != mapwid)
344
                return;
345
 
346
        if (coordenabled) {
347
                showcoords(GR_FALSE);
348
                ptrx = mp->x;
349
                ptry = mp->y;
350
                showcoords(GR_TRUE);
351
        }
352
 
353
        showselection(GR_FALSE);
354
        switch (selectmode) {
355
                case SELECT_SCALE:
356
                        selectwidth = ABS(mp->x - selectx) * 2 + 1;
357
                        selectheight = ABS(mp->y - selecty) * 2 + 1;
358
                        temp = ((long) selectwidth) * selectyscale
359
                                / selectxscale;
360
                        if (selectheight < temp)
361
                                selectheight = temp;
362
                        temp = ((long) selectheight) * selectxscale
363
                                / selectyscale;
364
                        if (selectwidth < temp)
365
                                selectwidth = temp;
366
                        break;
367
 
368
                case SELECT_MOVE:
369
                        selectx += (mp->x - selectptrx);
370
                        selecty += (mp->y - selectptry);
371
                        break;
372
        }
373
 
374
        selectptrx = mp->x;
375
        selectptry = mp->y;
376
        showselection(GR_TRUE);
377
}
378
 
379
 
380
static void
381
dokeydown(kp)
382
        GR_EVENT_KEYSTROKE      *kp;
383
{
384
        if (kp->wid != mapwid)
385
                return;
386
 
387
        if (selectmode != SELECT_NONE) {
388
                switch (kp->ch) {
389
                        case 's':       /* scale selection */
390
                                selectmode = SELECT_SCALE;
391
                                break;
392
 
393
                        case 'm':       /* move selection */
394
                                selectmode = SELECT_MOVE;
395
                                break;
396
 
397
                        case '\033':    /* cancel selection */
398
                                showselection(GR_FALSE);
399
                                selectmode = SELECT_NONE;
400
                                break;
401
                }
402
                return;
403
        }
404
 
405
        switch (kp->ch) {
406
                case 'q':               /* quit */
407
                case 'Q':
408
                        GrClose();
409
                        exit(0);
410
 
411
                case 't':               /* redraw total map */
412
                        Longitude = ITOF(0);
413
                        Latitude = ITOF(0);
414
                        setzoom(ITOF(1));
415
                        GrClearWindow(mapwid, GR_TRUE);
416
        }
417
}
418
 
419
 
420
/*
421
 * Draw or erase the current selection if any is defined.
422
 * The selection is a rectangle centered on a specified point, and with a
423
 * specified width and height.  Drawing and erasing the selection are the
424
 * same drawing operation because of the XOR operation.
425
 */
426
static void
427
showselection(show)
428
        GR_BOOL show;           /* TRUE if show the selection */
429
{
430
        if ((show == 0) == (selectvisible == 0))
431
                return;
432
        if (selectmode == SELECT_NONE)
433
                return;
434
        GrRect(mapwid, xorgc, selectx - selectwidth / 2,
435
                selecty - selectheight / 2, selectwidth, selectheight);
436
        selectvisible = show;
437
}
438
 
439
 
440
/*
441
 * Draw or erase the coordinate string of the current pointer position.
442
 * Both of these are the same operation because of the XOR operation.
443
 */
444
static void
445
showcoords(show)
446
        GR_BOOL show;           /* TRUE if show the coordinates */
447
{
448
        long    curlong;
449
        long    curlat;
450
        FLOAT   ptrlat;
451
        FLOAT   ptrlong;
452
 
453
        if (((show == 0) == (coordvisible == 0)) || !coordenabled)
454
                return;
455
 
456
        if (show) {
457
                ptrlat = FIDIV(FIMUL(viewlat, ptry), mapheight - 1);
458
                ptrlong = FIDIV(FIMUL(viewlong, ptrx), mapwidth - 1);
459
 
460
                curlat = FTOI(Latitude + latradius - ptrlat);
461
                curlong = FTOI(Longitude - longradius + ptrlong);
462
 
463
                if (curlong > 180*60)
464
                        curlong -= 360*60;
465
                if (curlong < -180*60)
466
                        curlong += 360*60;
467
 
468
                mintostr(coordstring, curlong);
469
                strcat(coordstring, "  ");
470
                mintostr(coordstring + strlen(coordstring), curlat);
471
        }
472
 
473
        GrText(mapwid, xorgc, coordx, coordy, coordstring, -1, GR_TFBOTTOM);
474
        coordvisible = show;
475
}
476
 
477
 
478
/*
479
 * Convert minutes to a string of the form "ddd'mm" and store it
480
 * into the indicated buffer.
481
 */
482
static void
483
mintostr(buf, minutes)
484
        char    *buf;
485
        long    minutes;
486
{
487
        if (minutes < 0) {
488
                minutes = -minutes;
489
                *buf++ = '-';
490
        }
491
        sprintf(buf, "%ld'%02ld", (long)(minutes / 60), (long)(minutes % 60));
492
}
493
 
494
 
495
#if 0
496
/*
497
 * Convert "ddd'mm" to mins
498
 */
499
static long
500
degtomin(s)
501
        char    *s;
502
{
503
        int     deg, minutes;
504
        char    str[10],*strchr(),*cp;
505
 
506
        strcpy(str,s);
507
        if (cp = strchr(str,'\047')) {
508
                *cp = '\0';
509
                minutes = atoi(++cp);
510
        } else
511
                minutes = 0;
512
        if ((deg = atoi(str)) < 0)
513
                minutes = -minutes;
514
        return(deg * 60 + minutes);
515
}
516
#endif
517
 
518
 
519
/*
520
 * Set the scale factors for the given zoom factor.
521
 * The factors 3 and 4 are here to compensate for the screen aspect ratio.
522
 */
523
static void
524
setzoom(newzoom)
525
        FLOAT   newzoom;
526
{
527
        zoom = newzoom;
528
 
529
        Y_Scale = FIDIV(FIMUL(zoom, mapheight * 3), 180 * 4);
530
        X_Scale = FIDIV(FIMUL(zoom, mapwidth), 360);
531
 
532
        viewlong = FFDIV(WSPAN, zoom);
533
        viewlat = FFDIV(HSPAN * 4 / 3, zoom);
534
        longradius = FIDIV(viewlong, 2);
535
        latradius = FIDIV(viewlat, 2);
536
}
537
 
538
 
539
/*
540
 * Read the database file and draw the world.
541
 */
542
static void
543
load(fn)
544
        char    *fn;
545
{
546
        register DBPOINT        *pp;
547
        DBPOINT         *pend;
548
        FLOAT           x, y, LonPrv, LatPrv;
549
        long            oldlong = 0L;
550
        GR_COORD        xnew, ynew;
551
        GR_COORD        xold = 0, yold = 0;
552
        GR_BOOL         is_out;
553
        GR_BOOL         was_out;
554
        GR_BOOL         newseg = GR_FALSE;
555
        GR_COLOR        oldcolor;
556
        GR_COLOR        newcolor;
557
        int             n;
558
        int             fh;
559
        DBPOINT         p[PCount];
560
 
561
        LonPrv = ITOF(0);
562
        LatPrv = ITOF(0);
563
        oldcolor = -1;
564
        is_out = GR_FALSE;
565
        was_out = GR_FALSE;
566
 
567
        fh = open(fn, O_BINARY | O_RDONLY);
568
        if (fh < 0) {
569
                GrClose();
570
                fprintf(stderr, "Cannot open %s\n", fn);
571
                exit(1);
572
        }
573
 
574
        while ((n = read(fh, p, PCount * POINTSize)) > 0) {
575
                for (pp = p,pend = p + n/POINTSize; pp < pend; pp++)
576
                {
577
                        DBPOINT_CONVERT(pp);
578
                        /* do displacement */
579
                        x = ITOF(pp->Lon) - Longitude;
580
                        y = ITOF(pp->Lat) - Latitude;
581
 
582
                        /* wrap around for East-West */
583
                        if (x < -HSPAN)
584
                                x += WSPAN;
585
                        if (x > HSPAN)
586
                                x -= WSPAN;
587
 
588
                        if (pp->Code > 5) {
589
                                newcolor = code_colors[pp->Code / 1000];
590
                                if (newcolor != oldcolor) {
591
                                        oldcolor = newcolor;
592
                                        GrSetGCForeground(mapgc, oldcolor);
593
                                }
594
                                newseg = GR_TRUE;
595
                        }
596
 
597
                        if (oldcolor == BLACK)
598
                                goto go_on;
599
 
600
                        /* ignore points outside magnified area */
601
                        if ((x < -longradius || x > longradius ||
602
                                y < -latradius || y > latradius))
603
                        {
604
                                is_out = 1;
605
                                if (was_out) {          /* out to out */
606
                                        LonPrv = x;
607
                                        LatPrv = y;
608
                                        goto go_on;
609
                                }
610
 
611
                                /* in to out */
612
                                xold = mapxorig + FTOI(FFMUL(LonPrv, X_Scale)) / 60;
613
                                yold = mapyorig - FTOI(FFMUL(LatPrv, Y_Scale)) / 60;
614
                        } else {                        /* out to in */
615
                                is_out = 0;
616
                                if (was_out) {
617
                                        xold = mapxorig +
618
                                                FTOI(FFMUL(LonPrv, X_Scale)) / 60;
619
                                        yold = mapyorig -
620
                                                FTOI(FFMUL(LatPrv, Y_Scale)) / 60;
621
                                }
622
                                /* in to in */
623
                        }
624
                        LonPrv = x;
625
                        LatPrv = y;
626
 
627
                        /* scale points w/in area to interlace screen */
628
                        xnew = mapxorig + FTOI(FFMUL(x, X_Scale)) / 60;
629
                        ynew = mapyorig - FTOI(FFMUL(y, Y_Scale)) / 60;
630
 
631
                        /* if new segment, move to place */
632
                        if (newseg || ABS(oldlong - pp->Lon) > 180*60) {
633
                                xold = xnew;
634
                                yold = ynew;
635
                        }
636
                        oldlong = pp->Lon;
637
 
638
                        GrLine(mapwid, mapgc, xold, yold, xnew, ynew);
639
                        xold = xnew;
640
                        yold = ynew;
641
go_on:
642
                        was_out = is_out;
643
                        newseg = GR_FALSE;
644
                }
645
        }
646
        close(fh);
647
}
648
 
649
/* END CODE */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.