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

Subversion Repositories or1k

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

powered by: WebSVN 2.1.0

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