REM MAPFIX.bas PROGRAM.  SEE MAPFIX.TXT for HELP info
REM
'****  NEWEST   Yes, 1.4 is latest.  I began renumbering after 6.9
Ver$ = "1.4"  ' Still was an occassional bug in F2 convert
'       1.3     Fixed a bug in F2 CONVERT command and added label markers
'       1.2     Added KILL LABEL command. (long needed!)

MaxNumMAPS = 150' Maximum number of maps allowed in MAPLIST
MaxNumPoints = 3000  'APRS limit. Six times this many are permitted in MAPFIX
MaxNumLABELS = 199 'was 99 prior to 68c
MaxNumLines = 1900
REM $DYNAMIC
   ScrnType$ = "EGA": Ycen = 175: Yfactr = 1: YfacTXT = 350 / 350: SCREEN 9
   COLOR 15, 0
   REM for EGA test, Cfactr = 14: bln = 25
   GBLn = 43: Cfactr = 8: bln = 43
   WIDTH 80, 43

   PALETTE 6, 6
   DIM Crsr(16)
   CIRCLE (4, 3), 4, 14
   GET (0, 0)-(8, 6), Crsr
   REM PSET (40, 50), 10
   REM PUT (40 - 4, 50 - 3), Crsr, XOR
   REM LOCATE 23, 1: INPUT a$
GOTO BEGIN

Info: COLOR 15, 2: CLS
   PRINT "Ver 1.3/4  * Fixed F2 CONVERSION bug and added dots at LABEL locations "
   PRINT "    1.2    * Added a long needed KILL LABEL command"
   PRINT "    1.1    * F3,4,6,7,8,F10,11,12 hot keys Begin new Digitizer lines"
   PRINT "           * Added Clear Single Point command that scans entire map for"
   PRINT "             singlularities and kills them"
   PRINT
   PRINT "Ver 1.0  Added ^OVERLAY command for overlaying a map temporarily"
   PRINT "         F3 sets compressed mode for Map save.  Saves 33% in file"
   PRINT "         loading time.  Requires new MAP limits of X,2048 and Y,1024"
   PRINT "         New ^LOAD command for beginning a new map"
   PRINT
   PRINT "Ver 6.8d Fixed GPS Track History plots for E. and S. Hemispheres"
   PRINT
   PRINT "Ver 6.5d This version ADDED two modes of MOUSE SUPPORT!  "
   PRINT "         * CURSOR: Use F9 to open appropriate MOUSE port (must be MICROSOFT"
   PRINT "           serial mouse).  Left button is ALT-ADD and right is FIND command."
   PRINT
   PRINT "         * POOR-MANS DIGITIZER: Use alt-O to OPEN COMM port & READ MOUSE.txt"
   PRINT
   PRINT
   PRINT
   PRINT "**********  MAPFIX can build and edit APRS maps in a variety of ways:  *****"
   PRINT
   PRINT " FREE-HAND: Good for filling in missing roads, but hard to make roads exact"
   PRINT " CDROM:     Gets points from 2,000,000:1 and 100,000:1 USGS CD ROM. "
   PRINT "            Both generate Mbytes worth of points that take a lot of time to"
   PRINT "            filter down to a useable APRS size!"
   PRINT " TABLET:    Connect a serial data digitizer tablet and draw!     BEST METHOD!"
   PRINT " GPS DATA:  Replay any APRS GPS track history file and DRAW map lines over it"
   PRINT " CONVERSION:Change origin or scale on-line (old function of MAPCNVRT.bas)"
   PRINT " IMPORTING: Import features from other maps with auto-point conversion!"
   PRINT
   PRINT
   PRINT
   PRINT " FOR MORE DETAILS, BE SURE TO READ THE MAPFIX.TXT file!!!"
   PRINT
   PRINT
   Display$ = "UNKnown"
   RETURN

GetChar: a$ = "": DO UNTIL a$ <> "": a$ = INKEY$: LOOP: RETURN

BEGIN: GOSUB Info:
   PRINT " HIT ANY KEY to proceed onto the HELP screen...";
   GOSUB GetChar

   DIM x%(6 * MaxNumPoints), y%(6 * MaxNumPoints)
   DIM LN$(MaxNumLines) ' (no limit in APRS)
   nn = 2 * MaxNumLABELS
   DIM ML$(nn), Mla(nn), Mlo(nn), MLr(nn) 'Map Labels, lengths and coordinates
   nn = 2 * MaxNumMAPS
   DIM MapName$(nn), LatCen(nn), LonCen(nn), MapMax(nn), Comment$(nn)
   i = 1000
   DIM HLAT(i), HLONG(i)'For lat/longs from big GPS history files

INIT: ON ERROR GOTO ErrorTrap
   RdsOn = -1: Labls = -1:  KP = 1: Changed = 0: MapSize = 256
   Redraw = -1: Acenter = 0: nmp = 0: z = 0: nml = 0: LNi = 0
   Path$ = "C:\MAPS\S01_"

SCREEN , , 0, 0: Display$ = "HELP": GOSUB HELP: GOSUB LoadMap
REM ON ERROR GOTO 0

Main: GOSUB DrwMPaCur
  DO
GoAgain: Fault = 0
    IF Digitizer THEN
       IF LOC(1) > 9 THEN
          GOSUB GetXY
          REM Here is where ANY digitizer input ADDS a point EXCEPT if it was
          REM due to a button 3.  If button 3, then just the cursor moves.
          REM To configure MAPFIX to recognize your buttons, see line 1105.
          REM If you have no, or just 1 button, then F1 will simulate a button
          REM 3 so you can use the digitizer to only move the cursor
          IF JustCur OR Btn = 3 THEN
             GOSUB Cursor: GOSUB DrwMpPt' Only move cursor and clear JustCur
          ELSE GOSUB Cursor: GOSUB AddPoint'
          END IF
       END IF
    END IF
    a$ = ""
    IF Mouse THEN
       IF LOC(1) > 2 THEN
       C$ = INPUT$(1, 1)
       IF C$ > CHR$(191) THEN
         a = ASC(C$) - 192
         x = 0: y = 0
         C$ = INPUT$(1, 1): IF C$ > CHR$(127) THEN x = ASC(C$) - 128
         C$ = INPUT$(1, 1): IF C$ > CHR$(127) THEN y = ASC(C$) - 128
         IF x > 31 THEN x = x - 64
         IF y > 31 THEN y = y - 64
         cpx = cpx - x * degpmh
         cpy = cpy - y * degpmv
         GOSUB Cursor
         IF a > 31 THEN a = a - 32: a$ = CHR$(0) + CHR$(30)
         IF a > 15 THEN a = a - 16: a$ = "F"
       END IF
     END IF
    END IF
    IF a$ = "" THEN a$ = INKEY$
    IF a$ <> "" THEN
       IF LEN(a$) = 1 THEN a$ = UCASE$(a$)
       Key$ = a$
       SELECT CASE a$
       CASE "B": GOSUB BoxPPD
       CASE "C": GOSUB Clr1Pts
       CASE "D": GOSUB MapDIR
       CASE "F": LnStrt = 0: StrtSrch = 1: GOSUB FindPoint
       CASE "G": GOSUB CurToPoint: GOSUB CurDrwMap
       CASE "H"
          IF Display$ <> "HELP" THEN
             SCREEN , , 0, 0: COLOR 15, 1: GOSUB HELP
          ELSE GOSUB Info
             LOCATE bln, 1: PRINT " H for HELP or SPACE BAR for map..."; : a$ = ""
          END IF
       CASE "K": GOSUB KillLabel
       CASE "L": Labls = NOT Labls
       CASE "M": GOSUB ListMAPlist
       CASE "N": GOSUB NextLine: GOSUB Cursor
       CASE "O": GOSUB DrwAndShow
       CASE "P": GOSUB Previous: GOSUB Cursor
       CASE "Q": GOSUB QUIT
       CASE "R": z = 2: LnPtr = 1
       CASE "S": GOSUB labels
       CASE "T": GOSUB Scrunch
       CASE "U": GOSUB GetUSGS
       CASE " "
                 Display$ = "MAP": Redraw = -1: USGS = 0:
                 IF Scrn = 0 THEN SCREEN , , 1, 1: COLOR 15, 0
                 IF Scrn = 1 THEN GOSUB DrwMPaCur
                 Scrn = 1
       CASE "+": z = z + 1: GOSUB MapPoint  ' moves to next map point
       CASE "-": z = z - 1: GOSUB MapPoint  ' moves backwards
       CASE CHR$(1): Acenter = NOT Acenter
       CASE CHR$(3): GOSUB ChgColr
       CASE CHR$(6): LnStrt = LnPtr: StrtSrch = z + 1: GOSUB FindPoint
       CASE CHR$(12): GOTO INIT
       CASE CHR$(15): OVERLAY = -1: Redraw = 0: GOSUB Import
       CASE CHR$(18): Redraw = NOT Redraw: GOSUB Redraw
       CASE CHR$(19): GOSUB SaveMap
      
       CASE "7": CDX = LONo: CDY = LATo: GOSUB DrwMPaCur 'ShiftHOME
       CASE "6": cpx = cpx - 20 / (Sfac): GOSUB Cursor 'SHIFT Cursor by 4
       CASE "4": cpx = cpx + 20 / (Sfac): GOSUB Cursor
       CASE "8": cpy = cpy + 20 / (Sfac): GOSUB Cursor
       CASE "2": cpy = cpy - 20 / (Sfac): GOSUB Cursor

       END SELECT
      
       B$ = "": IF LEN(a$) = 2 THEN B$ = RIGHT$(a$, 1): REM process arrow & special keys
       SELECT CASE B$
       REM CASE CHR$(1) TO CHR$(127): PRINT ASC(B$)
       CASE "I": RS = RS * 2: GOSUB CurDrwMap: REM change scale
       CASE "Q": RS = RS / 2: GOSUB CurDrwMap
       CASE CHR$(132): RS = RS * 8: GOSUB CurDrwMap: REM change scale by factor of 4
       CASE CHR$(118): RS = RS / 8: GOSUB CurDrwMap
       CASE "G": GOSUB CurDrwMap 'Home key
       
       CASE "O": CDX = LonCen: CDY = LatCen: Acenter = 0: GOSUB DrwMPaCur'End Key
       CASE "M": cpx = cpx - 4 / (Sfac): GOSUB Cursor
       CASE "K": cpx = cpx + 4 / (Sfac): GOSUB Cursor
       CASE "H": cpy = cpy + 4 / (Sfac): GOSUB Cursor
       CASE "P": cpy = cpy - 4 / (Sfac): GOSUB Cursor
       REM Here are the special MapFIx routines
       CASE CHR$(30)                          'alt-A  (also left mouse button!)
          SELECT CASE MsInit
          CASE 0: GOSUB AddPoint              'alt-ADD point
          CASE 4: LAb = cpy
          CASE 3
                GOSUB BoxLine23: BEEP
                INPUT "Enter total LAT moved in Degrees"; z$
                degpmv = VAL(z$) / (Sfac * (cpy - LAb))
          CASE 2: LOb = cpx
          CASE 1
                GOSUB BoxLine23: BEEP
                INPUT "Enter total LONG moved in Degrees"; z$
                degpmh = VAL(z$) / (Sfac * (cpx - LOb))
          END SELECT
          IF MsInit THEN MsInit = MsInit - 1
       
       CASE CHR$(48): IF Digitizer THEN GOSUB NewFeature'alt-BEGIN
       CASE CHR$(46): GOSUB NewCenter                   'alt-CENTER
       CASE CHR$(32): GOSUB DelPT                       'alt-DELete point
       CASE CHR$(34): GOSUB LoadHst                     'alt-GPS hstry file
       CASE CHR$(23): GOSUB Import                      'alt-IMPORT
       CASE CHR$(36): GOSUB Join                        'alt-JOIN
       CASE CHR$(37): GOSUB KillF                       'alt-KILL Feature
       CASE CHR$(38): GOSUB AddLabel                    'alt-add LABEL
       CASE CHR$(50): GOSUB MakePT: IF Redraw THEN GOSUB DrawMap 'MOVE point to cursor
       CASE CHR$(49): GOSUB NewFeature                  'alt-NEW Feature
       CASE CHR$(24): GOSUB WhichDgtzr                  'alt-OPEN dgtzr COM
       CASE CHR$(19): GOSUB MapRange                    'alt-RANGE
       CASE CHR$(20): GOSUB TRIM                        'alt-TRIM
       CASE CHR$(31): GOSUB Scrunch                     'alt-SCRUNCH
       CASE CHR$(22): GOSUB GetUSGS                     'alt-U
       CASE CHR$(59): JustCur = -1: GOSUB DrwMpPt       'F1
       CASE CHR$(60): GOSUB MapCnvrt                    'F2
       CASE CHR$(61)                                    'F3 for smaller Maps
          IF MpLstLdd THEN
             MapSize = MapSize / 2: IF MapSize < 1 THEN MapSize = 1
             GOSUB ShowMaps
          ELSE SavClr = 3: a$ = "Stream": GOSUB HotKey
          END IF
       CASE CHR$(62)                                    'F4 for larger Maps
          IF MpLstLdd THEN
             MapSize = MapSize * 2: IF MapSize > 1000 THEN MapSize = 1000
             GOSUB DrwAndShow
          ELSE SavClr = 4: GOSUB HotKey
          END IF
       CASE CHR$(63): Slower = NOT Slower                           'F5
       CASE CHR$(64): SavClr = 6: a$ = "Border": GOSUB HotKey       'F6
       CASE CHR$(65): SavClr = 7: a$ = "Minor road": GOSUB HotKey   'F7
       CASE CHR$(66): SavClr = 8: a$ = "Railroad": GOSUB HotKey     'F8
       CASE CHR$(67): GOSUB InitMouse                   'F9
       CASE CHR$(68): SavClr = 10: a$ = "Interstate": GOSUB HotKey  'F10
       CASE CHR$(84): SavClr = 11: a$ = "Water": GOSUB HotKey       'F11
       CASE CHR$(85): SavClr = 12: a$ = "Major Road": GOSUB HotKey  'F12
       CASE CHR$(86): Comp = -1: abort = 0                          'F3 shift
            FOR i = 1 TO nmp
                IF x%(i) < 0 OR x%(i) > 2047 THEN abort = -1
                IF y%(i) < 0 OR y%(i) > 1023 THEN abort = -1
            NEXT i
            IF abort THEN
                LOCATE 20, 10: Comp = 0: abort = 0
                PRINT "POINTS OUT OF RANGE.  CANNOT COMPRESS"
            ELSE Changed = Changed + 1
            END IF
            GOSUB Redraw
       CASE CHR$(87): Comp = 0: GOSUB Redraw                       'F4 shift
       CASE CHR$(91): GOSUB AddMark                                'F8 shift
       END SELECT
          
    END IF
  LOOP
  SYSTEM 'you should never get here

KillLabel: j = 0: k = RS / 2000
           FOR i = 1 TO nml
               IF j THEN
                    ML$(i - 1) = ML$(i): Mla(i - 1) = Mla(i)
                    Mlo(i - 1) = Mlo(i): MLr(i - 1) = MLr(i)
               ELSE
                    IF ABS(cpx - Mlo(i)) < k THEN
                       IF ABS(cpy - Mla(i)) < k THEN j = i
                    END IF
               END IF
           NEXT
           IF j <> 0 THEN nml = nml - 1: GOSUB DrawMap ELSE BEEP
           RETURN

AddMark: a$ = "Ref Point": SavClr = 14
   GOSUB BeginF: GOSUB MakePT
   CUY = CUY - 6: GOSUB AddPoint
   CUX = CUX + 10: GOSUB AddPoint
   CUY = CUY + 6: GOSUB AddPoint
   CUX = CUX - 10: GOSUB AddPoint
   CUY = CUY - 6: GOSUB AddPoint
   CUX = CUX + 5: CUY = CUY + 3: GOSUB Cursor
   RETURN

WhichDgtzr: GOSUB BoxLine23
   INPUT "Select (D)igitizer or (P)oor-Man's-Mouse-Mode"; a$
   a$ = UCASE$(a$): IF a$ = "D" THEN GOSUB DigiInit: GOTO DrawMap
   IF a$ <> "P" THEN RETURN
   IF NOT Mouse THEN GOSUB InitMouse
   CLS : LOCATE 6, 1
   PRINT "POOR-MANS-MOUSE-MODE  (Digitizer)"
   PRINT
   PRINT "We must first calibrate the mouse movement with actual LAT/LONG movements."
   PRINT "Perform the following steps in sequence.  If you mess up, START PROGRAM OVER!"
   PRINT
   PRINT "During this process, ignore the cursor on the screen."
   PRINT
   PRINT "Lift and move mouse to a low LATTITUDE mark.  Hit left button."
   PRINT "     move mouse carefully up to an UPPER LATTITUDE mark.  Hit left button."
   PRINT
   PRINT "Lift and move mouse to a right LONGITUDE mark.  Hit left button."
   PRINT "     move mouse carefully to a LEFT LONGITUDE mark.  Hit left button."
   MsInit = 4
   RETURN



InitMouse: GOSUB BoxLine23
    INPUT "Mouse on COM 1, 2 or None"; a$
    IF a$ = "1" OR a$ = "2" THEN
       OPEN "com" + a$ + ":1200,n,8,1,CS0,DS0,CD0" FOR RANDOM AS #1
       Mouse = -1
       GOSUB BoxLine23
       PRINT "Left button is alt-ADD.  Right button is FIND."; ""
       degpmh = 1 / Sfac: degpmv = 1 / Sfac
    END IF
    RETURN

Redraw: LOCATE 1, 25
    PRINT "LOAD TIME"; LEFT$(STR$(LdTime), 5); "   ";
    IF Comp THEN PRINT "COMPRESSED    ";  ELSE PRINT "              ";
    IF Redraw THEN PRINT "REDRAW ENABLED" ELSE PRINT "NO ReDraw...  "
    RETURN

QUIT: CLS : BEEP: INPUT "Really quit MAPFIX (Y/N) [Y]"; a$
    IF UCASE$(a$) = "N" THEN GOSUB DrawMap: RETURN
    a$ = "Y"
    IF Changed THEN
       GOSUB BoxLine23
       PRINT "**** MAP HAS BEEN MODIFIED"; Changed; "TIMES BUT NOT SAVED!!!  SAVE NOW? (Y)";
       INPUT a$
    IF UCASE$(a$) <> "N" THEN GOSUB SaveMap
    END IF
    SYSTEM

TRIM: GOSUB BoxLine23
    CLS : PRINT "TRIM ALL POINTS AND LABELS OUTSIDE OF MAPRANGE"
    PRINT
    PRINT "This command removes all points and labels outside of the white map border"
    PRINT
    PRINT "map border (located with the alt-CENTER and alt-RANGE command."
    PRINT : PRINT
    PRINT "To avoid errors near the edge, make the CENTER/RANGE box about 10% larger"
    PRINT
    PRINT "You might consider stopping now and doing a SAVE (ctrl-S) before proceeding."
    PRINT
    PRINT "ALSO, THIS DOES NOT WORK FOR POINTS WITH NEGATIVE VALUES!  Be sure  your"
    PRINT "selected area is below and to right of ORIGIN.  If not do an F2 CONVERT."
    PRINT : PRINT
    INPUT "Are you ready to proceed? (Y/N) (N)"; ans$
    CDX = LonCen: CDY = LatCen: GOSUB DrwMPaCur
    IF UCASE$(ans$) <> "Y" THEN RETURN
    C = 0: LOCATE bln - 2, 1: PRINT "Processing...";
    REM dx and dy are num pix of center of map
    REM bx and by are borders of map based on MapRng
    by = ppdv * MapRng / 60
    bx = by / Lfac
    z = 0
    DO
      z = z + 1
      IF x%(z) = 0 THEN z = z + 2
      IF x%(z) > dx + bx OR y%(z) > dy + by THEN bad = 1 ELSE bad = 0
      IF x%(z) < dx - bx OR y%(z) < dy - by THEN bad = 1
      IF bad THEN
         REM IF x%(z - 1) <> 0 AND x%(z + 1) <> 0 THEN
            GOSUB DelPT: z = z - 1
            C = C + 1
         REM END IF
      END IF
      IF z >= nmp - 4 THEN EXIT DO
    LOOP
    LOCATE bln - 2, 1: PRINT "Now removing labels...";
    FOR i = 1 TO nml: REM now eliminate all labels outside
        bad = 0: xm = MapRng / (60 * Lfac): ym = MapRng / 60
        IF Mlo(i) > LonCen + xm OR Mla(i) > LatCen + ym THEN bad = 1
        IF Mlo(i) < LonCen - xm OR Mla(i) < LatCen - ym THEN bad = 1
        IF bad = 1 THEN
           FOR j = i TO nml
               ML$(j) = ML$(j + 1): Mla(j) = Mla(j + 1)
               Mlo(j) = Mlo(j + 1): MLr(j) = MLr(j + 1)
           NEXT j: nml = nml - 1: PRINT ".";
        END IF
    NEXT i
    GOTO DrawMap
   
FindPoint: CurX = INT(.5 + dx + (CUX - 320) / (KP * Hfac))
           CurY = INT(.5 + dy + (CUY - Ycen) / KP)

    GOSUB BoxLine23: PRINT "SEARCHING THROUGH ALL POINTS IN FILE...";
    REM SaveZ = Z: SaveLNptr = LnPtr
Agn: FOR j = 0 TO 30            ' Go through abt 20 times lookin pt.
        IF j > 10 THEN j = j + 1' first with 0 delta, then bigger
        PRINT ".";
        LnCtr = LnStrt
        FOR i = StrtSrch TO nmp
            IF x%(i) = 0 THEN LnCtr = LnCtr + 1
            IF LnCtr >= LNi THEN i = nmp
            IF x%(i) > CurX - j AND x%(i) < CurX + j THEN
               IF y%(i) > CurY - j AND y%(i) < CurY + j THEN
                  z = i: LnPtr = LnCtr: GOSUB CurToPoint
                  j = 99: i = nmp
               END IF
            END IF
        NEXT i:
    NEXT j
    IF j < 99 AND Key$ = CHR$(6) THEN StrtSrch = 2: LnCtr = 1: Key$ = "F": GOTO Agn
    IF j < 99 THEN PRINT "None found!": RETURN
    GOSUB MapPoint: SavClr = 0
    GOSUB Find1st: LineColor = 15: dots = &HCCCC: GOSUB DP
    RETURN
                 
HotKey: IF NOT Digitizer THEN RETURN
        GOSUB BeginF: GOSUB GetXY: GOSUB Cursor: GOSUB MakePT
        RETURN

NewFeature: LOCATE bln - 1, 1: PRINT SPACE$(27); : GOSUB BoxLine23
    INPUT "Enter reference name for new feature"; a$
    IF a$ = "" THEN RETURN
    GOSUB Rainbow: IF abort THEN RETURN
    GOSUB BeginF
    GOSUB BoxLine23
    LOCATE bln, 1: PRINT SPACE$(80); : LOCATE bln, 1
    IF RIGHT$(Key$, 1) = CHR$(48) THEN
       PRINT "NOW USE DIGITIZER TO ADD NEW POINTS TO THIS FEATURE...";
       GOSUB GetXY: GOSUB Cursor
    ELSE
       PRINT "NOW MOVE CURSOR AND USE ALT-A TO ADD POINTS TO THIS NEW FEATURE...";
    END IF
    GOSUB MakePT
    RETURN

Rainbow: LOCATE bln, 1
    FOR i = 0 TO 14
        PRINT RIGHT$(" " + MID$(STR$(i + 1), 2), 2); "   ";
        LINE (16 + i * 40, 335 * YfacTXT)-(40 + i * 40, 349 * YfacTXT), i + 1, BF
    NEXT i
    GOSUB BoxLine23
    INPUT "Select color (4,7,10-Hwys 11-Water 12-Hwy 13-Spcl 14-City)"; B$
    SavClr = VAL(B$): IF SavClr > 15 OR SavClr < 1 THEN abort = -1 ELSE abort = 0
    RETURN

           
BeginF: x%(nmp) = 0: y%(nmp) = SavClr   'Store feature color 0,c
    LN$(LNi + 1) = LN$(LNi): LnPtr = LNi'Bump up present LN$ comment
    LN$(LNi) = a$: LNi = LNi + 1'Store feature name
    nmp = nmp + 1: z = nmp
    nmp = nmp + 1: x%(nmp) = 0: y%(nmp) = 0'nmp points to ending 0,0
    RETURN

CanclF: nmp = nmp - 2: z = Kz
    LNi = LNi - 1: LN$(LNi) = LN$(LNi + 1): RETURN

NewCenter: LatCen = cpy: LonCen = cpx: Changed = Changed + 1: GOTO CurDrwMap

MapRange: GOSUB BoxLine23: INPUT "Enter map range"; a$
    IF VAL(a$) <> 0 THEN MapRng = VAL(a$)
    Changed = Changed + 1: GOTO DrwMPaCur

AddPoint: x% = dx + (CUX - 320) / (KP * Hfac)
    IF x% = 0 THEN BEEP: PRINT "X=0!!!": RETURN
    nmp = nmp + 1: z = z + 1
    FOR i = nmp TO z STEP -1
        x%(i) = x%(i - 1): y%(i) = y%(i - 1)
    NEXT
    GOSUB MakePT
    IF SavClr = 0 AND Redraw THEN GOTO DrawMap
    LineColor = SavClr
    s = z - 1: GOTO DP

MakePT: x%(z) = dx + (CUX - 320) / (KP * Hfac)
    y%(z) = dy + (CUY - Ycen) / KP
    Changed = Changed + 1
    GOTO MapPoint

CurToPoint:
    cpx = CDX - (x%(z) - dx) / ppdv
    cpy = CDY - (y%(z) - dy) / (ppdv * Yfactr)
    GOTO Cursor

Clr1Pts: FOR i = 1 TO nmp
             IF x%(i) = 0 THEN
                IF x%(i + 1) = 0 THEN z = i: GOSUB DelZ:
             END IF
         NEXT i: BEEP
         RETURN

DelPT: GOSUB DelZ
    REM if 1st pt, it stays as 1st pt

    IF x%(z) = 0 THEN z = z - 1: REM if end pt, it stays as end
    IF x%(z + 1) = 0 AND x%(z - 1) = 0 THEN 'It is LAST point
       GOSUB Kline: LnPtr = LnPtr - 1       'So Kill Line
       GOSUB DelZ                           'And Kiil it
       z = z - 1: GOSUB DelZ: z = z - 1     'Kill 0,color
    END IF                                  'and -1 to end point
    IF B$ = CHR$(32) AND Redraw THEN GOSUB DrawMap ELSE GOSUB MapPoint
    RETURN

DelZ: nmp = nmp - 1
      FOR i = z TO nmp
          x%(i) = x%(i + 1): y%(i) = y%(i + 1)
      NEXT: Changed = Changed + 1: RETURN

NextLine: IF z >= nmp - 1 THEN z = nmp - 1: BEEP: RETURN
    DO UNTIL x%(z) = 0: z = z + 1: LOOP
    IF z < nmp - 1 THEN z = z + 1: LnPtr = LnPtr + 1
    SavClr = 0: GOTO MapPoint

Previous: DO UNTIL z = 1 OR x%(z) = 0: z = z - 1: LOOP
    IF z > 3 THEN z = z - 1: LnPtr = LnPtr - 1
    SavClr = 0: GOTO MapPoint

KillF: GOSUB Find1st: REM Stop at Beginning (0) point of the feature to kill
    ni = s' Now scan for next feature
    DO UNTIL x%(ni) = 0: ni = ni + 1: LOOP
    REM now move down rest of array to fill
    DO UNTIL ni = nmp + 1
       x%(s - 1) = x%(ni): y%(s - 1) = y%(ni)
       s = s + 1: ni = ni + 1
    LOOP
    nmp = nmp - (ni - (s - 1)): y%(nmp) = 0
    GOSUB Kline
    GOTO DrawMap
    
Find1st: s = z: DO UNTIL x%(s - 1) = 0: s = s - 1: LOOP
         REM z = Bi + 1
         RETURN

ChgColr: GOSUB Find1st: GOSUB Rainbow: IF abort THEN RETURN
         y%(s - 1) = SavClr: Changed = Changed + 1
         LineColor = SavClr
         GOSUB DP
         RETURN


Kline: FOR i = LnPtr TO LNi
           LN$(i) = LN$(i + 1)
       NEXT i
       LNi = LNi - 1
       RETURN

MapPoint:
     IF z < 2 THEN z = 2: LnPtr = 1: BEEP: SavClr = 0
     IF z > nmp - 1 THEN z = z - 1: BEEP: SavClr = 0
     IF x%(z) = 0 THEN
        IF a$ = "-" THEN
             LnPtr = LnPtr - 1: z = z - 1
        ELSE LnPtr = LnPtr + 1: z = z + 1
        END IF: SavClr = 0
     END IF
     IF LnPtr < 0 THEN LnPtr = 0
     IF Display$ = "MAP" THEN
          LOCATE bln - 3, 1
          PRINT "Fture#"; LnPtr; TAB(12); LEFT$(LN$(LnPtr) + "            ", 12);
     END IF
DrwMpPt: IF Display$ <> "MAP" THEN RETURN
     IF JustCur THEN pc = 12 ELSE pc = 15
     CIRCLE (Xtest, Ytest), 10, 0 'Erase old circle
     Xtest = 320 + KP * (x%(z) - dx) * Hfac
     Ytest = Ycen + KP * (y%(z) - dy) * Yfactr
     IF Acenter AND (Xtest > 600 OR Xtest < 40 OR Ytest > 300 OR Ytest < 40) THEN
        GOSUB CurToPoint: GOSUB CurDrwMap
        Xtest = 320 + KP * (x%(z) - dx) * Hfac
        Ytest = Ycen + KP * (y%(z) - dy) * Yfactr
     END IF
     CIRCLE (Xtest, Ytest), 10, pc
     
     LOCATE bln - 2, 1: PRINT "MapPt#"; z;
     IF z > 999 THEN PRINT TAB(13); "val:";  ELSE PRINT TAB(12); "vals:";
     PRINT TAB(17); x%(z); TAB(23); y%(z)
     RETURN

AddLabel: nml = nml + 1
     Mla(nml) = cpy: Mlo(nml) = cpx
     GOSUB BoxLine23: INPUT "Enter Label Name"; a$: ML$(nml) = a$
     GOSUB BoxLine23: INPUT "Begin displaying label at what range?"; a$
     a = VAL(a$): IF a <> 0 THEN MLr(nml) = a:  ELSE MLr(nml) = 2048
     Changed = Changed + 1: GOTO labels

BoxLine23: LOCATE bln - 2, 1: PRINT SPACE$(80); : LOCATE bln - 2, 1: RETURN

ErrorTrap: Fault = ERR: 'Error handling routine
     IF ERR = 57 THEN PRINT "  I/O-error-User-logoff"; : RESUME
     IF ERR = 69 THEN PRINT "  Comm-buffer-overflow"; : RESUME
     IF ERR = 53 THEN PRINT "  file-"; F$; "-not-found": CLOSE : RESUME NEXT
     IF ERR = 62 THEN RESUME NEXT
     IF ERR = 64 THEN RESUME NEXT
     IF ERR = 52 THEN RESUME NEXT
     IF ERR = 55 THEN RESUME NEXT
     IF ERR = 2 THEN PRINT "SYNTAX-error"
     IF ERR = 70 THEN PRINT " WRITE PROTECTED!...": RESUME NEXT
     IF ERR = 76 THEN PRINT "Wrong Path!": RESUME NEXT
     IF ERR = 71 THEN PRINT "no disk!": RESUME NEXT
     RESET
     PRINT : PRINT "Error beyond repair. Number = "; ERR;
     INPUT "Hit RETURN to return to DOS"; a$
     SYSTEM

MapDIR: CLS : PRINT "MAP FILES DIRECTORY": PRINT
     PRINT "To display MAP files, enter the path to your xxxxxxx.MAP files."
     PRINT "For example, the default '\APRS\MAPS\*.MAP' will show all maps in the APRS"
     PRINT "directory.  Similarly '*.map' will search your present directory."
     PRINT "For any other path, enter the full file specification.": PRINT
     F$ = "\aprs\MAPS\*.map"
     PRINT "Enter Filespec for searching the DIRECTORY ("; F$; ")";
     INPUT a$: IF a$ <> "" THEN F$ = a$
     PRINT : PRINT : FILES F$
     RETURN


LoadMap: 'Maps are drawn to the default EGA resolution of 640 x 400 (350)
Again: GOSUB BoxLine23
      
    INPUT " Enter map FILENAME, or NEW, or ? for a list, or Q to quit)"; a$
    a$ = UCASE$(a$): IF a$ = "" THEN GOTO Again
    IF a$ = "Q" THEN SYSTEM
    IF a$ = "?" THEN GOSUB MapDIR: GOTO Again
    IF a$ = "NEW" THEN Key$ = "NEW": GOSUB NewMap: RETURN
    a = INSTR(3, a$, "."): IF a = 0 THEN a$ = a$ + ".MAP"
    Strtime = TIMER
    MapFile$ = a$: F$ = MapFile$: OPEN F$ FOR INPUT AS #3
    IF Fault = 53 THEN Fault = 0: PRINT : CLOSE #3: GOTO Again
    GOSUB BoxLine23: PRINT " Loading "; F$; "..."
    INPUT #3, LATo: LINE INPUT #3, LATtext$
    INPUT #3, LONo: LINE INPUT #3, LONtext$
    INPUT #3, ppdv: LINE INPUT #3, VS$'Pixels per degree horiz
    INPUT #3, LatCen: LINE INPUT #3, LatCen$
    INPUT #3, LonCen: LINE INPUT #3, LonCen$
    INPUT #3, MapRng: LINE INPUT #3, MapRng$
    INPUT #3, MinRng: LINE INPUT #3, MR$
    LINE INPUT #3, TextLine$ ' Line of comments or instrutcitons
    IF TextLine$ = "Compressed" THEN Comp = -1 ELSE Comp = 0
    IF LEFT$(TextLine$, 14) = "Map generated " THEN Redraw = 0
    RS = 2 ^ INT(LOG(MapRng) / LOG(2))'Rng is intgr of VERTrng
    i = 0: LNi = 0:
    REM ON ERROR GOTO 0
    DO WHILE NOT EOF(3)
       i = i + 1
       IF Comp THEN
            LINE INPUT #3, a$
            IF a$ = " 0,0" THEN
                 x%(i) = 0: y = 0
            ELSEIF a$ = " 0,-1" THEN x%(i) = 0: y = -1
            ELSE 'abc where c = .xxxxyyy
                 '          x = 16*a + xxxx  and  y = 8*b +yyy
                 C$ = RIGHT$(a$, 1): B$ = MID$(a$, 2, 1): a$ = LEFT$(a$, 1)
                 cx% = INT((ASC(C$) - 27) / 8): cy% = (ASC(C$) - 27) - cx% * 8
                 x%(i) = 16 * (ASC(a$) - 27) + cx%
                 y%(i) = 8 * (ASC(B$) - 27) + cy%
            END IF
       ELSE INPUT #3, x%(i), y: y%(i) = y * Yfactr
       END IF
       IF x%(i) = 0 AND NOT EOF(3) THEN ' Get line color & store with x=0
          INPUT #3, y%(i): LNi = LNi + 1: LINE INPUT #3, LN$(LNi)' Save line name
          IF y = -1 THEN GOSUB LoadLabels ' All labels listed at end of file
       END IF
    LOOP: nmp = i  'nmp points to 0,-1 that ends all data (but the value
                   'of X% and y% are 0,0 until file is saved.
    CDY = LatCen: CDX = LonCen'Center display on ORIGIN
    cpx = CDX: cpy = CDY 'Cursor Posn to Center of Display
    z = 2: LnPtr = 1: REM start at first point and first line segment
    CLOSE #3:     REM first X% value is map color.  2nd val is 1st pt
    LdTime = TIMER - Strtime
    RETURN


LoadLabels: k = 0
     DO WHILE NOT EOF(3)
        k = k + 1: INPUT #3, ML$(k), Mla(k), Mlo(k), MLr(k)
     LOOP
     IF Mla(k) = 0 OR Mlo(k) = 0 THEN nml = k - 1 ELSE nml = k
     RETURN
       
SaveMap: GOSUB BoxLine23
   PRINT "Enter file name to save if other than "; MapFile$;
   INPUT a$
   IF a$ <> "" THEN
      IF INSTR(a$, ".") = 0 THEN a$ = a$ + ".map"
      MapFile$ = a$
   END IF
   F$ = MapFile$
   GOSUB BoxLine23: PRINT "Saving map to file named "; F$; " ..."
   OPEN F$ FOR OUTPUT AS #4
   IF Fault = 70 OR Fault = 71 THEN Fault = 0: CLOSE #4: GOTO SaveMap
   PRINT #4, LATo; ","; LATtext$
   PRINT #4, LONo; ","; LONtext$
   PRINT #4, ppdv; ","; VS$
   PRINT #4, LatCen; ","; LatCen$
   PRINT #4, LonCen; ","; LonCen$
   PRINT #4, MapRng; ","; MapRng$
   PRINT #4, MinRng; ","; MR$
   j = 1: abort = 0
   IF Comp THEN
      REM ON ERROR GOTO 0
      PRINT #4, "Compressed"
      'abc where c = .xxxxyyy
      '          x = 16*a + xxxx  and  y = 8*b +yyy
      FOR i = 1 TO nmp
          IF x%(i) <> 0 THEN 'WRITE #4, x%(i), INT((y%(i) / Yfactr) + .5)
             a% = INT(x%(i) / 16): cx% = x%(i) - a% * 16
             B% = INT(y%(i) / 8): cy% = y%(i) - B% * 8
             C% = 8 * cx% + cy%
             PRINT #4, CHR$(a% + 27); CHR$(B% + 27); CHR$(C% + 27)
          END IF
          IF i = nmp THEN PRINT #4, " 0,-1"
          IF x%(i) = 0 AND i <> nmp THEN
             PRINT #4, " 0,0"
             PRINT #4, y%(i); ","; LN$(j): j = j + 1
          END IF
      NEXT i
   ELSE
      IF TextLine$ <> "Compressed" THEN PRINT #4, TextLine$ ELSE PRINT #4, "ASCII"
      FOR i = 1 TO nmp
          IF x%(i) <> 0 THEN WRITE #4, x%(i), INT((y%(i) / Yfactr) + .5)
          IF i = nmp THEN PRINT #4, " 0,-1"  'Used to be AND X%(i)=0
          IF x%(i) = 0 AND i <> nmp THEN
             PRINT #4, "0,0"
             PRINT #4, y%(i); ","; LN$(j): j = j + 1
          END IF
      NEXT i
   END IF
   PRINT #4, "0,"; LN$(LNi)
   x = 4
   IF ppdv > 60 THEN x = 5
   IF ppdv > 240 THEN x = 6
   IF ppdv > 900 THEN x = 7
   IF ppdv > 2400 THEN x = 8
   FOR k = 1 TO nml
       PRINT #4, ML$(k); ",";
       PRINT #4, LEFT$(LTRIM$(STR$(Mla(k))), x); ",";
       PRINT #4, LEFT$(LTRIM$(STR$(Mlo(k))), x + 1); ",";
       PRINT #4, LTRIM$(STR$(MLr(k)))
   NEXT k: CLOSE #4: LOCATE bln - 1, 1:
   Changed = 0
   IF nmp > MaxNumPoints OR nml > MaxNumLABELS THEN
      CLS : LOCATE 9, 29: PRINT "CAUTION!": PRINT : PRINT
      IF nmp > MaxNumPoints THEN
         PRINT "            The number of points,"; nmp; "is greater than"; MaxNumPoints
      END IF
      IF nml > MaxNumLABELS THEN
         PRINT "            The number of LABELS,"; nml; "is greater than"; MaxNumLABELS
      END IF
      LOCATE 18, 12
      PRINT " Therefore this map will not work with APRS (yet) "
      LOCATE bln - 2, 1: INPUT "HIT Enter to continue..."; a$
   END IF
   GOTO DrwMPaCur

CurDrwMap: CDX = cpx: CDY = cpy: GOTO DrawMap: REM Re-center at CURSOR location

DrwMPaCur: cpx = CDX: cpy = CDY: GOSUB DrawMap
           REM After drawing map, Put cursor at center
           RETURN

DrawMap: IF USGS THEN RETURN
    SCREEN , , 1, 1: Scrn = 1: CLS : CUX = 0
    Display$ = "MAP"
    COLOR 15, 0
    WIDTH 80, GBLn: bln = GBLn
   'Draw to range scale RS and center display CDX and CDY
  
   DO WHILE RS < 320 / ppdv: RS = RS * 2: LOOP
   IF RS > 8192 THEN RS = 8192
   KP = 100 * 100 / (RS * ppdv)' this is kinda arbitrary..??
   Sfac = 50 * 200 / RS

   Lfac = COS(CDY / 57.296)
   Hfac = (640 / 350) * (3 / 4) * Lfac
   dx = ppdv * (LONo - CDX)
   dy = ppdv * (LATo - CDY)
        
   LOCATE 1, 2: PRINT "Redrawing Map"
   REM first put ORIGIN and 1024 by 75% of 2048 BOX (and CENTER) on the map
   x0 = 320 - (dx * KP * Hfac): y0 = Ycen - (dy * KP * Yfactr)
   xm = 320 + (1512 - dx) * KP * Hfac: ym = Ycen + (1024 - dy) * KP * Yfactr
   REM 1512 is 3/4ths of 2048
   LINE (x0, y0)-(xm, ym), 14, B
   CMX = 320 + Sfac * (CDX - LonCen) * Hfac'new
   CMY = Ycen + Sfac * (CDY - LatCen) * Yfactr
   LINE (CMX - 27, CMY)-(CMX + 27, CMY), 15
   LINE (CMX, CMY - 20)-(CMX, CMY + 20), 15
   CIRCLE (CMX, CMY), 10, 15
   CIRCLE (320 - dx * KP * Hfac, Ycen - KP * dy), 12, 14
   s = 0: GOSUB MapPoint: REM Redraw MapPoint
   StrtPt = 0
   
DP: 'Speeded this up by 33% but is harder to follow
    HfacK = KP * Hfac
    YfactrK = KP * Yfactr
    FOR i = s TO nmp - 1
       x = 320 + (x%(i) - dx) * HfacK
       y = Ycen + (y%(i) - dy) * YfactrK
       X1 = 320 + (x%(i + 1) - dx) * HfacK
       Y1 = Ycen + (y%(i + 1) - dy) * YfactrK
       IF StrtPt THEN
          'x = 320 + (x%(i) - dx) * HfacK
          'y = Ycen + (y%(i) - dy) * YfactrK
          PSET (x, y), LineColor
          CIRCLE (x, y), 2, 9: StrtPt = 0
          LINE -(X1, Y1), LineColor, , dots
       ELSE
          IF x%(i + 1) <> 0 THEN
             LINE -(X1, Y1), LineColor, , dots
          ELSE
             CIRCLE (x, y), 3, 10: StrtPt = -1
             LineColor = y%(i + 1): i = i + 1
             IF LineColor = 8 THEN dots = &HF0F0 ELSE dots = &HFFFF
             IF LineColor = 0 OR LineColor = 15 THEN dots = &HCCCC: LineColor = 15
             x = 320 + (x%(i + 1) - dx) * HfacK
             y = Ycen + (y%(i + 1) - dy) * YfactrK
             IF Display$ = "SHOW" AND LineColor > 8 THEN LineColor = LineColor - 8
          END IF
       END IF
       IF i = z THEN SavClr = LineColor
   NEXT i
   GOSUB Cursor
   GOSUB Redraw
   GOSUB DrawHist: REM draw GPS history track
   IF Key$ <> CHR$(0) + CHR$(30) THEN GOSUB ShowBox
   IF Display$ = "SHOW" THEN
      GOSUB ShowMaps
   ELSE
      LOCATE bln, 1: PRINT "Use +/- to move MAPpoint.  N/P for Next/Previous Feature.  H for HELP!.";
      LOCATE 1, 71 ' was 61
      PRINT "PTS"; nmp ' ; "= "; INT((nmp / MaxNumPoints) * 100); "%";
      LOCATE 2, 71 ' was 61
      PRINT "LBLS "; nml '; "= "; INT((nml / MaxNumLABELS) * 100); "%";
      LOCATE 3, 71: PRINT "PPD"; ppdv
      LOCATE 4, 71: PRINT "Rng"; LEFT$(STR$(MapRng), 5)
   END IF

labels:
   IF Labls THEN
      FOR i = 1 TO nml ' Now plot labels on map
      IF RS <= MLr(i) OR Key$ = "S" THEN
         LET x = 320 + Sfac * (CDX - Mlo(i)) * Hfac'new
         LET y = Ycen + Sfac * (CDY - Mla(i)) * Yfactr
         CIRCLE (x, y), 1, 14
         IF y > Cfactr * Yfactr AND y < bln * Cfactr * Yfactr AND x > 8 * (LEN(ML$(i)) + 1) AND x < 632 THEN
            LOCATE y / (Cfactr * Yfactr), (x / 8) - LEN(ML$(i)): PRINT ML$(i);
         END IF
      END IF
      NEXT i
   END IF
   GOSUB ShowMap
   RETURN
         
ShowMap: REM this shows the map boarder of the loaded map
    x = 320 + KP * (CDX - LonCen) * ppdv * Hfac'new
    y = Ycen + KP * (CDY - LatCen) * ppdv * Yfactr
      by = MapRng * Sfac * Yfactr / 60
      bx = by * 640 / (400 * Yfactr) * Lfac'old
      C = 15
    LINE (x - bx, y - by)-(x + bx, y + by), C, B
    RETURN

Cursor: JustCur = 0: IF pc = 12 THEN GOSUB DrwMpPt
     REM circle(CUX, CUY), 4, 0
     IF CUX > 4 AND CUY > 3 AND CUX < 635 AND CUY < 343 * Yfactr THEN PUT (CUX - 4, CUY - 3), Crsr, XOR
     CUX = 320 + Sfac * (CDX - cpx) * Hfac'new
     CUY = Ycen + Sfac * (CDY - cpy) * Yfactr
     REM CIRCLE (CUX, CUY), 4, 14
     IF CUX > 4 AND CUY > 3 AND CUX < 635 AND CUY < 343 * Yfactr THEN PUT (CUX - 4, CUY - 3), Crsr, XOR
     IF cpx > 0 THEN
          x = INT(cpx): xm = (cpx - x) * 60
     ELSE x = INT(-cpx): xm = -(cpx + x) * 60
     END IF
     IF cpy > 0 THEN
          y = INT(cpy): ym = (cpy - y) * 60
     ELSE y = INT(-cpy): ym = -(cpy + y) * 60
     END IF
     x$ = RIGHT$(STR$(x), 3) + " "
     LOCATE 1, 2: PRINT "RNG"; RIGHT$("   " + STR$(RS), 4) + " Miles"
     LOCATE 2, 2: PRINT "LAT "; y; MID$(STR$(ym) + "   ", 2, 5)
     LOCATE 3, 2: PRINT "LON "; x$; MID$(STR$(xm) + "   ", 2, 5)
     
     LOCATE bln - 1, 1: PRINT "Cursor coordnts:"; TAB(17);
     PRINT INT(.5 + dx + (CUX - 320) / (KP * Hfac)); TAB(23); INT(.5 + dy + (CUY - Ycen) / KP);
     REM LOCATE BLn-1, 55: PRINT "Degrees: ";
     REM PRINT LEFT$(STR$(CPY) + " ", 7); LEFT$(STR$(CPX) + "   ", 7);
     LOCATE 1, 16: PRINT "Decimal";
     LOCATE 2, 15: PRINT LEFT$(STR$(cpy) + " ", 8);
     LOCATE 3, 15: PRINT LEFT$(STR$(cpx) + "   ", 8);
     LINE (0, 0)-(178, 3 * Cfactr * Yfactr), 12, B'Box around it
     LINE (0, 0)-(116, 3 * Cfactr * Yfactr), 12, B'Box around it
     LET a$ = "": LET B$ = "": RETURN

HELP: SCREEN , , 0, 0: Scrn = 0: CLS
      REM WIDTH 80, 25: BLn = 25
      COLOR 15, 1
      LINE (0, 0)-(639, 18 * Yfactr), 14, BF
      LOCATE 1, 20: PRINT " MAPFIX.bas HELP SCREEN Ver "; Ver$
      LOCATE 3, 1
      PRINT
      PRINT " The ORIGIN, CENTER and BORDER are shown (but only the CENTER and RANGE in "
      PRINT " MAPLIST.apr are actually used by APRS.  Labels are right justified to the point"
      PRINT " just after the last letter.  CALLS & OBJECT names will be left justified."
      PRINT ""
      PRINT
      PRINT " OPERATIONS          MAP FUNCTIONS         POINT FUNCTIONS     LABEL COMMANDS"
      PRINT
      PRINT " H - HELP SCREENS    @C- Change CENTER     @A - ADD point      S - SHOW labels"
      PRINT " D - map DIRECTORY   @R- set map RANGE     @D - DELETE point  @L - add a LABEL"
      PRINT "^S - SAVE MAP!!!     @T- TRIM border Pts   @K - Kill feature   L - LABELS off"
      PRINT "^L - LOAD NEW map    @I- IMPORT from map   @M - MOVE point     K - KILL a Label"
      PRINT "@G - GPS Overlay     ^O- OVERLAY a map     @N - NEW feature"
      PRINT " C = CLEAR Sngle Pts  M- show MAPLIST      ^C - CHANGE Color"; ""
      PRINT " Q - QUIT             O- OTHER map bordrs       "
      PRINT ""
      PRINT
      PRINT " DISPLAY COMMANDS     POINTER MOVEMENTS   USGS CD ROM CMDS  DIGITIZER/MOUSE"
      PRINT
      PRINT " SPACE to draw map    N- Next Feature     B- BOX PPD area   @O- OPEN COMMS"
      PRINT " ARROWS  (shft)       P- Prev Feature     U- USGS overlay   @B- BEGIN new line"
      PRINT " PgUP/DN (ctrl)       G- Go to Pointer    T- Test Scruncher F1- MOVE cursor"
      PRINT " HOME to Cursor       F- Find point      @S- SCRUNCH file        vice ADD pt"
      PRINT " HOME(shft) to Orign ^F- Find another    @U- USGS Load!     F3,4,6,7,8,10,"
      PRINT " END to map center    R- RESET to 1st Pt @J- JOIN lines     F1,2shftd=11,12"
      PRINT "                     ^R- REDRAW on/off                        HOTKYS begin Ln"
      PRINT "                     ^A- AUTOCENTER on/off                  F9- Init Mouse"
      PRINT "                     +/- move Pointer"
      PRINT
      PRINT " F1 Temporarily re-defines Digitizer click to move cursor vice ADD point"
      PRINT " F2 Convert Origin to new point and/or Pix/per/deg"
      PRINT " F3 (SHFT) Save mapfile in COMPRESSED format"
      PRINT " F4 (SHFT) Save mapfile in ASCII format"
      PRINT " F5        Slow GPS overlay so U can see chronologically"
      PRINT " F8 (shft) Adds MARKER to map.  Useful for re-calibrating MOUSE"
      PRINT " F9        Init Mouse (Msoft serial mouse only)"
      PRINT
      PRINT : REM LINE (0, 190 * Yfactr)-(639, 190 * Yfactr), 15
              
      IF Display$ <> "HELP" THEN
       LOCATE bln, 1
       PRINT " HIT H AGAIN FOR MORE HELP SCREENS, OR SPACE BAR FOR MAP...";
      END IF
      Display$ = "HELP"
      LINE (0, 0)-(634, 348 * Yfactr), 15, B
      RETURN

LdMapLst: GOSUB BoxLine23: INPUT "FileSpec for MAPLIST.apr if not \APRS\MAPLIST.APR"; a$
    IF a$ <> "" THEN F$ = a$ ELSE F$ = "\aprs\Maplist.apr"
    OPEN F$ FOR INPUT AS #3: IF Fault <> 0 THEN RETURN
    i = 1: NumGood = 0
    INPUT #3, DfltY: LINE INPUT #3, a$
    INPUT #3, DfltX: LINE INPUT #3, a$
    INPUT #3, BestRng: LINE INPUT #3, a$: DfltR = BestRng
    INPUT #3, GMToffset: LINE INPUT #3, a$
    WHILE a$ <> "* BEGIN *": LINE INPUT #3, a$: WEND ' Skip comment block
    WHILE NOT EOF(3) AND i <= UBOUND(MapName$)
       INPUT #3, MapName$(i), LatCen(i), LonCen(i), MapMax(i)
       LINE INPUT #3, Comment$(i)
       IF LEFT$(MapName$(i), 1) <> "*" THEN NumGood = NumGood + 1
       NumMaps = i: i = i + 1
    WEND: CLOSE #3
    IF NumGood >= MaxNumMAPS - 1 THEN
       CLS : LOCATE 2, 5
       PRINT "WARNING: Too many ACTIVE MAPS (more than"; MaxNumMAPS; ") in MAPLIST.map file for APRS"
       LOCATE 4, 10: PRINT "Use EDITOR to suppress mapnames with an (*) that you don't need."
       PRINT : PRINT : PRINT : MpLstLdd = -1
       INPUT "HIT RETURN to continue"; a$
    END IF
    RETURN

ListMAPlist: IF NOT MpLstLdd THEN GOSUB LdMapLst
   GOSUB ListHeader
   FOR i = 1 TO NumMaps
       IF i / 19 = INT(i / 19) THEN
          LOCATE bln, 1: PRINT "HIT RETURN to continue"; : INPUT a$
          GOSUB ListHeader
       END IF
       PRINT MapName$(i); TAB(14);
       PRINT INT(LatCen(i) * 100) / 100; TAB(21); INT(LonCen(i) * 100) / 100;
       PRINT TAB(29); MapMax(i); TAB(36); LEFT$(LTRIM$(Comment$(i)), 43)
   NEXT i
   
   LOCATE bln, 1: PRINT "LIST COMPLETE. CONTINUE WITH NEXT MAPFIX COMMAND...";
   RETURN

ListHeader: CLS
   PRINT "MAPS in MAPLIST.map (*MAPS are suppressed)     [For now, use EDITOR to modify]"
   PRINT :
   PRINT "MAP NAME      LATcen LONcen  RANGE COmments"
   PRINT "------------  ------ ------- ----- -------------------------------------------"
   RETURN

DrwAndShow: IF NOT MpLstLdd THEN GOSUB LdMapLst
            Display$ = "SHOW": GOSUB DrwMPaCur

ShowMaps: IF MapSize > RS / 2 THEN MapSize = RS / 2
    LOCATE bln, 1: PRINT " Drawing all maps >"; MapSize;
    PRINT "mi.  F3 to see smaller, F4 for bigger, SPACE to cancel.";
    LINE (0, 336 * Yfactr)-(639, 349 * Yfactr), 14, B
    FOR i = 1 TO NumMaps
   
    x = 320 + Sfac * (CDX - LonCen(i)) * Hfac
    y = Ycen + Sfac * (CDY - LatCen(i)) * Yfactr
      dy = MapMax(i) * Sfac * Yfactr / 60
      dx = dy * 640 / (400 * Yfactr) * Lfac
      C = 15
      IF MapMax(i) > 32 THEN C = 14
      IF MapMax(i) > 64 THEN C = 12
      IF MapMax(i) > 128 THEN C = 11
      IF MapMax(i) > 256 THEN C = 13
          
    IF MapMax(i) > MapSize THEN
       LINE (x - dx, y - dy)-(x + dx, y + dy), C, B
       IF y + dy > Cfactr * Yfactr AND y + dy < bln * Cfactr * Yfactr THEN
          IF x + dx > 8 * (LEN(MapName$(i)) + 1) AND x + dx < 632 THEN
             LOCATE (y + dy) / (Cfactr * Yfactr), (x + dx) / 8 - LEN(MapName$(i))
             IF MapMax(i) > RS / 4 THEN PRINT MapName$(i);
          END IF
       END IF
    END IF
    NEXT i: RETURN
        
REM Next routines added by W7KKE for overlyaying GPS track histoiries

Hstdir: CLS : PRINT "HISTORY FILES DIRECTORY": PRINT
    PRINT "To display HST files, enter the path to your xxxxxxx.HST files."
    PRINT "For example, the default '\APRS\*.HST' will show all maps in the APRS"
    PRINT "directory.  Similarly '*.hst' will search your present QBasic directory."
    PRINT "For any other path, enter the full file specification.": PRINT
         
    PRINT "Enter Filespec for searching the DIRECTORY (\aprs\*.hst)";
    INPUT F$: IF F$ = "" THEN F$ = "\aprs\*.hst"
    IF INSTR(F$, ".") = 0 THEN F$ = F$ + ".HST"
    PRINT : PRINT : FILES F$
    RETURN

LoadHst: GOSUB BoxLine23
    INPUT "Which history file to load (ENTER for list, Q to quit)"; F$
    IF UCASE$(F$) = "Q" THEN RETURN
    IF F$ = "" THEN GOSUB Hstdir: GOTO LoadHst
    a = INSTR(3, F$, "."): IF a = 0 THEN F$ = F$ + ".hst"
    Fault = 0: F$ = UCASE$(F$): OPEN F$ FOR INPUT AS #3
   
    IF Fault = 53 OR Fault = 62 THEN Fault = 0: RETURN
    GOSUB BoxLine23: PRINT "Loading track history from "; F$
      
    DO WHILE NOT EOF(3)
       i = i + 1
       INPUT #3, a$
       HLAT(i) = VAL(MID$(a$, 26, 2)) + (VAL(MID$(a$, 28, 5)) / 60)
       HLONG(i) = VAL(MID$(a$, 35, 3)) + (VAL(MID$(a$, 38, 5)) / 60)
       IF MID$(a$, 33, 1) = "S" THEN HLAT(i) = -HLAT(i)
       IF MID$(a$, 43, 1) = "E" THEN HLONG(i) = -HLONG(i)
       maxhist = i
     LOOP
     CLOSE #3: Histloaded = -1
     GOSUB BoxLine23: PRINT "File loading is complete.  GPS data is plotted."
     REM fall through...

DrawHist:  'put history track on map
     IF Histloaded THEN
        size = 3: IF RS < 2 THEN size = size * 2 / RS
        FOR i = 1 TO maxhist
            HMX = 320 + KP * (CDX - HLONG(i)) * ppdv * Hfac'new
            HMY = Ycen + KP * (CDY - HLAT(i)) * ppdv * Yfactr
            CIRCLE (HMX, HMY), size, 13
            IF Slower THEN FOR zz = 1 TO 1500: NEXT zz
        NEXT i
     END IF
     RETURN

NewMap: CLS : PRINT "BEGINNING A NEW MAP FROM SCRATCH...": PRINT
   PRINT "All points in an APRS map are measured to the right and down from an origin."
   PRINT
   PRINT
   INPUT "Enter the LATITUDE  of the ORIGIN in degrees , minutes (DD, mm.xx)"; LATo, LAm
   PRINT
   INPUT "Enter the LONGITUDE of the ORIGIN in degrees , minutes (DDD, mm.xx)"; LONo, LOm
   LATo = LATo + SGN(LATo) * LAm / 60
   LONo = LONo + SGN(LONo) * LOm / 60
   PRINT
   PRINT
   PRINT
   PRINT "Choose the number of pixels per degree to set the map scale:"
   PRINT
   PRINT "Approximate size              Range from center  Resolution Pixels/Deg"
   PRINT "----------------              -----------------  ---------- ----------"
   PRINT "Typical state                        128 mi       400 yds      240"
   PRINT "Several County region                 64 mi       200 yds      450"
   PRINT "Typical VHF range                     32 mi       100 yds      900"
   PRINT "Big metro area     1:100,000 scale    16 mi       160 ft      1800"
   PRINT "Four 7.5 min maps                      8 mi        80 ft      3600"
   PRINT "One 7.5 min map    1: 24,000 scale     4 mi        40 ft      7200"
   PRINT ""
   INPUT "Enter desired Pixels/Deg"; ppdB
   IF ppdB = 0 THEN GOTO NewMap
   REM In following lines, 500 is half of 999 (maximum nominal value for pts)
   LatCen = LATo - (500 * Yfactr / ppdB)
   LonCen = LONo - (756 / ppdB) 'had been 500. Now .75 of 2048 % 2
   GOSUB StartMap: ppdv = ppdB
   CLS : PRINT "YOU ARE NOW READY TO DRAW A NEW MAP...": PRINT : PRINT
   PRINT
   PRINT "The YELLOW box shows the maximum values permitted for this ORIGIN and SCALE."
   PRINT
   PRINT "The PURPLE box shows the same limits, but moves with the current map center."
   PRINT
   PRINT "The WHITE  box shows the current map range to be entered into MAPLIST.xxx."
   PRINT
   PRINT
   PRINT "USING CURSOR WITHOUT DIGITIZER:  Move coursor to starting point for a NEW"
   PRINT "feature and hit ALT-N.  Then enter new feature name (for reference purposes)"
   PRINT "and continue moving cursor to the next point and hit ALT-A to add more points."
   PRINT "Continue in this fashion, using ALT-N whenever you want to begin a NEW feature."
   PRINT
   PRINT
   PRINT "USING A DIGITIZER:  First, use ALT-O once to OPEN the digitizer COM port.  Then"
   PRINT "use ALT-B to BEGIN each new map feature.  Enter the name and color of the new"
   PRINT "feature.  Then use the digitizer mouse to add more points."
   PRINT : PRINT : PRINT
   PRINT "Add LABELS on the map at the current cursor location by using the ALT-L key. "
   PRINT
   PRINT
   PRINT "When you are finished, be sure to SAVE the map using the CTRL-S command..."
   PRINT : PRINT : PRINT
   PRINT "FOR HELP, REMEMBER THE  H  KEY!"
   PRINT : PRINT : PRINT "Hit ENTER to proceed..."; : INPUT a$
   RETURN

StartMap: REM This called by NEW and in middle of USGS build
   LatCen$ = "LAT of CENTER": LonCen$ = "LON of CENTER"
   MapRng = 60 * 500 * Yfactr / ppdB: REM 500 is half of full map size
   MapRng$ = "Map range from center"
   VS$ = "Pixels per degree"
   MinRng = 1: MR$ = "Reserved"
   TextLine$ = "NEW Map generated by MAPFIX.bas routine..."
   IF Key$ = "NEW" THEN RS = 2 ^ INT(LOG(MapRng) / LOG(2))'Rng is intgr of VERTrng
   CDX = LonCen: CDY = LatCen: cpx = CDX: cpy = CDY
   nmp = 1: nml = 0
   LNi = 1: LN$(1) = "Labels begin here"
   RETURN


DigiInit:
   CLS : PRINT : Digitizer = -1: MpLstLdd = 0
   PRINT "DIGITIZER INITIALIZATION:"
   PRINT
   PRINT "This routine will replace many CURSOR functions with the Digitizer's MOUSE."
   PRINT "Assuming your digitizer can output an X,Y,C format."
   PRINT
   PRINT "Only Mercator projection charts will give absolutely accurate results.  Other"
   PRINT "types, Lambert Conformal, Conical, etc will induce distortions."
   PRINT
   PRINT : PRINT
   PRINT "The digitizr should operate at 9600,N,8,1 in POINT mode with 200 LPI resolution."
   PRINT "The FORMAT outputs X,Y,C values separated by commas (C is for button pressed."
   PRINT
   PRINT "Set up the digitizer according to your model's instructions.  For the model"
   PRINT "23360, use the drawing board menu by pressing the mouse button 0 on the SETUP"
   PRINT "label so that the LED is ON.  Then move the mouse to each other label and"
   PRINT "use the 0 button to toggle the value ON or off as follows:"
   PRINT
   PRINT "POINT is ON                             PARITY 7/8 and 1 are ON "
   PRINT "BAUDRATE 3 is ON                        FORMAT is ON ON off ON"
   PRINT "DATA RATE doesn't matter                RESOLUTION off off ON"
   PRINT : PRINT
   INPUT "Is DIGITIZER connected to COM1 or COM2 (1)"; a$
   IF a$ <> "2" THEN a$ = "COM1" ELSE a$ = "COM2"
   INPUT "9600 baud.  Is digitizer set for 7 or 8 bits (8)"; B$
   IF B$ = "7" THEN B$ = "E,7" ELSE B$ = "N,8"
   Port$ = a$ + ":9600," + B$ + ",1,cs0,ds0,cd0"
   OPEN Port$ FOR RANDOM AS #1
   

   CLS : PRINT "FIRST LETS TEST THE DIGITIZER, AND GET THE MAP ON STRAIGHT.": PRINT
   PRINT "Move your mouse (or pen) and hit the 0 button (or touch tablet) to see if the"
   PRINT "digitizer is outputting in the desired format.  While doing this, it is a good"
   PRINT "idea to verify that your map is on straight.  The Y values from the mouse"
   PRINT "should give the same values for the same LATITUDE line on both the right and"
   PRINT "left edges of the map.  If not, move your map to get it horizontal."
   PRINT
   PRINT "OUTPUT FORMAT:"
   PRINT
   PRINT "XXXXX,YYYYY,APn (Only the X and Y values are used (4 or 5 digits is ok)"
   PRINT "                (APn can be anything.  But if you press the 4th key on a 4"
   PRINT "                (button mouse, this will be a 3 and will only move cursor,"
   PRINT "                (and NOT add a point."
   PRINT
   LOCATE bln, 1: PRINT "Hit ENTER and press 0 button on mouse to continue...";
   LOCATE 13, 1
   DO UNTIL INKEY$ <> "": LINE INPUT #1, a$: PRINT a$: LOOP
  
   CLS : PRINT
   PRINT "NEXT YOU MUST ESTABLISH THE SCALE OF YOUR DIGITIZER."
   PRINT
   PRINT "The scale is established by two points, the first near the"
   PRINT "upper left corner, the second near the lower right corner."
   PRINT
   PRINT "To get the best accuracy on maps not exactly MERCATOR, use points within the "
   PRINT "area where you are working, not on the extreme corners.  IE:  choose points"
   PRINT "that are in the center of the upper left quadrant and the lower right quadrant."
   PRINT
   PRINT "To establish the upper left reference point:"
   INPUT "     Enter lat  (deg,min)"; LATref1, M
   LATref1 = LATref1 + SGN(LATref1) * M / 60
   INPUT "     Enter long (deg,min)"; LONref1, M
   LONref1 = LONref1 + SGN(LONref1) * M / 60
   PRINT

   PRINT "Place the mouse on the upper left point and press the 0 button."
   LINE INPUT #1, a$: SOUND 150, 3
        digix1 = 5000 - VAL(LEFT$(a$, 5))
        digiy1 = VAL(MID$(a$, 7, 5))
        PRINT "Digitizer reads "; digix1, digiy1; " for this point.": PRINT

   PRINT "NOW Establish the lower right reference point:"
   INPUT "      Enter lat  (deg,min)"; LATref2, M
   LATref2 = LATref2 + SGN(LATref2) * M / 60
   INPUT "      Enter long (deg,min)"; LONref2, M
   LONref2 = LONref2 + SGN(LONref2) * M / 60
   PRINT
   PRINT "Place digitizer pen on lower right point."
   LINE INPUT #1, a$: SOUND 150, 3
        digix2 = 5000 - VAL(LEFT$(a$, 5))
        digiy2 = VAL(MID$(a$, 7, 5))
        PRINT "Digitizer reads "; digix2, digiy2; " for this point.": PRINT

   REM Find delta lat/long between reference points
   REM Calculate degrees per x/y unit
        degx# = (LONref1 - LONref2) / (digix1 - digix2)
        degy# = (LATref1 - LATref2) / (digiy1 - digiy2)

   CLS : PRINT "YOU ARE NOW READY TO USE THE DIGITIZER TO ENTER POINTS INTO MAPFIX..."
   PRINT
   PRINT "The digitizer works just about like the cursor and arrow keys in MAPFIX.  Any"
   PRINT "point identified by the digitizer will be ADDED just as if you had hit ALT-A."
   PRINT "All points are added to a feature after the current MapPoint identified by the"
   PRINT "white circle. "
   PRINT
   PRINT "With the digitizer, do NOT use the ALT-N NEW command which always begins at the"
   PRINT "current cursor location.  For the digitizer, use ALT-B to BEGIN a new feature."
   PRINT "You will be asked to identify the name and color of the new feature.  From then"
   PRINT "on, just move the digitizer mouse (or pen) to ADD new points.  "
   PRINT
   PRINT "If your digitizer mouse has 4 buttons, use the first (left) button for ADDing "
   PRINT "points, use the 4th (right) button to just move the cursor with no action."
   PRINT "With point-pens or single button mice, press F1 and the next use of the Pen "
   PRINT "will just move the cursor, NOT add a point."
   PRINT : PRINT
   INPUT "Hit ENTER to continue with MAPFIX..."; a$
   RETURN

GetXY: LINE INPUT #1, a$: SOUND 150, 3
   a = INSTR(a$, ","): IF a = 0 THEN RETURN
       x = 5000 - VAL(LEFT$(a$, a - 1))
   B = INSTR(a + 1, a$, ","): IF B = 0 THEN B = LEN(a$)
       y = VAL(MID$(a$, a + 1, B - (a)))
   Btn = VAL(RIGHT$(a$, 1)): REM Here is where I get the BUTTON value
                             REM as the right-most character fm the digitizer
   cpy = ((y - digiy2) * degy#) + LATref2
   cpx = ((x - digix2) * degx#) + LONref2
   IF LOC(1) <> 0 THEN a$ = INPUT$(LOC(1), #1)'Clear input buffer
   RETURN

BoxPPD:  GOSUB BoxLine23: INPUT "Enter the desired PPD (enter 0 to eliminate purple box)"; a$
         IF a$ <> "" THEN ppdB = VAL(a$): gotthem = 0' To force re-evaluation
ShowBox: IF ppdB > 1 THEN
             y = (30000 / ppdB) * Sfac * Yfactr / 60 'had been 30000 thn 36000
             x = y * 820 / (400 * Yfactr) * Lfac 'had been 640 then 560
             LINE (CUX - x, CUY - y)-(CUX + x, CUY + y), 13, B
            GOSUB BoxLine23
            PRINT "Purple box shows the largest APRS map that can be made with that scale.       "
         END IF
         RETURN
        
GetUSGS: REM This used for both U=OVERLAY and by ALT-U = USGS BUILD!
   Redraw = 0: USGS = -1: ni = 0: nt = 0: j = 0: NumLines = 0
   IF Key$ <> "U" THEN
      IF ppdB = 0 THEN GOSUB BoxPPD
      ppdv = ppdB
      IF gotthem = 0 THEN
         LATo = CDY + (500 * Yfactr / ppdv)
         LONo = CDX + (756 / ppdv) 'had been 500 (now .75 of 2048)/2
         LE = 1: OE = 1
         gotthem = 1
      END IF
      GOSUB BoxLine23: PRINT "Round-off LAT ORIGIN of "; LATo; : INPUT a$
            IF a$ <> "" THEN LATo = VAL(a$)
      GOSUB BoxLine23: PRINT "Round-off LON ORIGIN of "; LONo; : INPUT a$
            IF a$ <> "" THEN LONo = VAL(a$)
      GOSUB BoxLine23: INPUT "LATitude extent (100%)"; a$
            IF a$ <> "" THEN LE = VAL(a$) / 100
      GOSUB BoxLine23: INPUT "LONgitude extent (100%)"; a$
            IF a$ <> "" THEN OE = VAL(a$) / 100
      dx = ppdv * (LONo - CDX)
      dy = ppdv * (LATo - CDY)
      KP = 100 * 100 / (RS * ppdv)
      LatCen = CDY: LonCen = CDX: GOSUB StartMap
      LATtext$ = "Decimal LAT  of map ORIGIN"
      LONtext$ = "Decimal LONG of map ORIGIN"
      TextLine$ = "Map generated by MAPFIX from USGS 2,000,000:1 CD ROM (data valid mid-1980's)"
   END IF
   Slope = 1.2: REM IF ppdV < 600 THEN Slope = 1.5 ELSE Slope = 1.2
   SlopeI = 1 / Slope
   IF ppdv < 610 THEN mindel = .004 ELSE mindel = 2.4 / ppdv
   REM this .004 seems to be magic for 2,000,000 source data

   Lmax = 500 + 500 * LE: Lmin = 501 - 500 * LE 'Max=1000 and Min =1
   Omax = 756 + 756 * OE: Omin = 757 - 756 * OE 'Max=1512 and min =1
   IF Lmin < 1 THEN Lmin = 1
   IF Omin < 1 THEN Omin = 1

   GOSUB BoxLine23: PRINT "Which category (AB,CF,PB,RD,RR,ST,WB) ("; Cat$; ")";
   INPUT a$
   IF a$ <> "" THEN
      a = INSTR(a$, "."): IF a = 0 THEN a$ = a$ + ".GRF"
      Cat$ = a$
   END IF
   LOCATE bln - 1, 1: PRINT "MAPFIX will add the CATEGORY (RD,ST,WB,etc).GRF to the PATH\FILENAME above.    ";
   GOSUB BoxLine23: PRINT "Enter DRIVE:PATH\filename up to CATEGORY ("; Path$; ")";
   INPUT a$
   IF a$ <> "" THEN Path$ = a$
  
   USGS$ = Path$ + Cat$
   TY$ = UCASE$(LEFT$(Cat$, 2))
   LowMax = 99: HiMin = 0
   SELECT CASE TY$
      CASE "RD", "PB", "AB", "CF", "RR": MaxRnk = 99: MinRNk = 0
      CASE "WB": MaxRnk = 20: MinRNk = 0: LowMax = 0: HiMin = 5
      CASE "ST": MaxRnk = 50: MinRNk = 5: LowMax = 16: HiMin = 43
               ' Does not include canals
               ' Make minRNK=7 normal, 10 Alaska, 3 alaska for full map
   END SELECT
   OPEN USGS$ FOR INPUT AS #3
   IF Fault <> 0 THEN RETURN
   REM PRINT "raw data format.....", "   LineID", "#-Rnk-Atbts", "  NumPts"
   LOCATE 5, 72: PRINT "RNG"; INT(30000 / ppdv): LOCATE bln - 1, 1
   IF Key$ = "U" THEN
      PRINT "While USGS OVERLAYED, do not redraw map or you will have to do it again...";
   ELSE PRINT "Blue circles start lines, Green Box ends.  Red points discarded, Yellow Kept!";
   END IF
   LOCATE 1, 71: PRINT "PTS     ";
   LOCATE 2, 71: PRINT "USED    ";
   LOCATE 3, 71: PRINT "LINE    ";
   LOCATE 4, 71: PRINT "USED    ";
   LOCATE 6, 72: PRINT "RNK";

 DO UNTIL EOF(3) OR LNi = MaxNumLines - 1
   IF INKEY$ <> "" THEN EXIT DO
   NumLines = NumLines + 1
   LOCATE 1, 75: PRINT nt
   LOCATE 2, 75: PRINT ni
   LOCATE 3, 75: PRINT NumLines
   LOCATE 4, 75: PRINT LNi
   a$ = INPUT$(20, 3): REM PRINT a$;
        LnID$ = LEFT$(a$, 7)
        Rank$ = MID$(a$, 8, 2): Rank = VAL(Rank$): LOCATE 6, 75: PRINT Rank
        Npts$ = MID$(a$, 10, 6): Npts = VAL(Npts$)
        AtCd$ = MID$(a$, 16, 5)
        a$ = LTRIM$(LnID$) + "-" + Rank$ + "-" + AtCd$
        REM PRINT , LnID$, a$, Npts$
   IF Rank < 24 THEN SavClr = 4 ELSE SavClr = 7
   IF Rank < 20 THEN SavClr = 12
   IF Rank < 14 THEN SavClr = 10
   IF TY$ = "WB" THEN SavClr = 11
   IF TY$ = "ST" THEN SavClr = 3
   IF TY$ = "CF" THEN SavClr = 14
   IF TY$ = "RR" THEN SavClr = 8
   IF TY$ = "PB" THEN SavClr = 6
   IF YT$ = "AB" THEN SavClr = 14
   LineOK = 0: IF Key$ <> "U" THEN GOSUB BeginF
   REM IF ppdV < 610 THEN mindel = .004 ELSE mindel = 2.4 / ppdV
   REM this .004 seems to be magic for 2,000,000 source data
   FOR i = 1 TO Npts
    a$ = INPUT$(20, 3)
    IF Rank > MaxRnk OR Rank < MinRNk THEN IF Rank > 2 OR TY$ <> "ST" THEN GOTO Skp
    IF Rank > LowMax AND Rank < HiMin THEN GOTO Skp
    REM IF VAL(Rank$) > 99 THEN GOTO Skp
    LA = VAL(LEFT$(a$, 2)) + VAL(MID$(a$, 3, 2)) / 60 + VAL(MID$(a$, 5, 2)) / 3600
    LO = VAL(MID$(a$, 8, 3)) + VAL(MID$(a$, 11, 2)) / 60 + VAL(MID$(a$, 13, 2)) / 3600
    IF Key$ = "U" THEN
        REM Following lines used to limit points if just doing an OVERLAY only
        IF LA > CDY + RS / 60 OR LA < CDY - RS / 50 THEN GOTO Skp 'off screen
        IF LO > CDX + RS / (35 * Hfac) OR LO < CDX - RS / (35 * Hfac) THEN GOTO Skp
        REM s$ = MID$(a$, 16, 5)
        REM PRINT S$, LA, LO
    END IF 'oops stack problem here if too many times...
    y% = (LATo - LA) * ppdv
    x% = (LONo - LO) * ppdv: IF x% = 0 THEN x% = -1
    IF Key$ <> "U" AND (x% > Omax OR x% < Omin) THEN GOTO Skp'this ignores points off PPD
    IF Key$ <> "U" AND (y% > Lmax OR y% < Lmin) THEN GOTO Skp'scale
    LineOK = -1
       X1 = 320 + KP * (x% - dx) * Hfac
       Y1 = Ycen + KP * (y% - dy) * Yfactr
       IF i > 2 THEN
          REM LINE (x, y)-(X1, Y1), 6
          dd = LO - LOb: IF dd = 0 THEN dd = .0000001
          dn = LA - LAb
          s = dn / dd' Note that 1>s>.01 for Xdelta of 1 to 100
          IF ABS(s) < .1 AND ABS(Lsp) < .1 THEN
             sd = 1
          ELSEIF ABS(s) > 10 AND ABS(Lsp) > 10 THEN sd = 1
          ELSEIF ABS(dd) < mindel AND ABS(dn) < mindel THEN sd = 1
          REM this had been .004 for 2,000,000 CD rom and ppdV 300 to 600
          REM now is 2.4/ppdV for 100,000
          ELSEIF s <> 0 THEN sd = Lsp / s
          ELSE sd = 0
          END IF
          IF sd > Slope OR sd < SlopeI OR i = Npts THEN
             PSET (x, y), 14
             IF Key$ <> "U" THEN GOSUB KeepLine
          ELSE PSET (x, y), 4
          END IF
          Lsp = s: nt = nt + 1
       ELSE Lsp = 0: CIRCLE (X1, Y1), 2, 9
          IF Key$ <> "U" THEN GOSUB KeepLine 'keeps first two lines
       END IF
       LAb = LA: LOb = LO
       x = X1: y = Y1
       
Skp: NEXT i
     IF Key$ <> "U" THEN
        IF LineOK THEN nmp = nmp - 1: z = z - 1: ni = ni + 1 ELSE GOSUB CanclF
     END IF
     LINE (x - 1, y - 1)-(x + 1, y + 1), 10, B ' Last Point
 LOOP
 IF LNi > MaxNumLines - 2 THEN LOCATE 12, 20: PRINT "PROCESSING STOPPED... TOO MANY LLINES!..."
   CLOSE #3
   IF x%(nmp) <> 0 THEN x%(nmp) = 0: y%(nmp) = 0
   GOSUB MakeNoise
   RETURN

KeepLine: x%(z) = x%: y%(z) = y%: nmp = nmp + 1: z = z + 1: ni = ni + 1: RETURN


Scrunch: i = 0: Pt = 0: nt = 0: ni = 0: GOSUB BoxLine23
    INPUT "Enter slope filter ratio 1.1 to 1.5 (typically 1.2)"; a$
    IF a$ = "" THEN Slope = 1.2 ELSE Slope = VAL(a$)
    DO UNTIL i >= nmp - 1
      i = i + 1
      X1 = 320 + KP * (x%(i) - dx) * Hfac
      Y1 = Ycen + KP * (y%(i) - dy) * Yfactr
      IF x%(i) <> 0 THEN
        Pt = Pt + 1
        IF Pt > 2 THEN
          REM LINE (x, y)-(x1, y1), 6
          dd = x - X1
          dn = y - Y1
          IF dd = 0 AND dn = 0 THEN
            sd = Slope: s = Lsp  'Here the points are identical
            CIRCLE (x, y), 9, 13
          ELSE
            IF dd = 0 THEN dd = .01
            dst = ((dd * dd) + (dn * dn)) ^ .5
            s = dn / dd' Note that 1>s>.01 for Xdelta of 1 to 100
            IF s = 0 THEN s = .05
            IF ABS(s) < .2 THEN s = .2 * SGN(s)
            IF ABS(s) > 5 THEN s = 5 * SGN(s)
            IF ABS(s) <= .2 AND ABS(Lsp) <= .2 THEN
               sd = 1
            ELSEIF ABS(s) >= 5 AND ABS(Lsp) >= 5 THEN sd = 1
            ELSE sd = Lsp / s
            END IF
            IF ABS(dd) > 50 * KP OR ABS(dn) > 30 * KP THEN sd = 0
            REM IF ABS(dd) < 5 OR ABS(dn) < 4 THEN sd = 1
          END IF
          IF sd > Slope OR sd < 1 / Slope OR x%(i + 1) = 0 OR NumRej > 4 THEN
            ni = ni + 1: CIRCLE (x, y), 1, 15: NumRej = 0
          ELSE PSET (x, y), 4: NumRej = NumRej + 1: Changed = Changed + 1
            IF Key$ <> "T" THEN
               i = i - 1: nmp = nmp - 1
               FOR ii = i TO nmp
                   x%(ii) = x%(ii + 1): y%(ii) = y%(ii + 1)
               NEXT ii
            END IF
          END IF
          Lsp = s: nt = nt + 1
        ELSE Lsp = 0: nt = nt + 1: ni = ni + 1: CIRCLE (X1, Y1), 4, 9
        END IF
      ELSE Pt = 0: nt = nt + 1: ni = ni + 1
        LOCATE 1, 71: PRINT "PTS "; nt
        LOCATE 2, 71: PRINT "SAVD"; ni
      END IF
      x = X1: y = Y1
    LOOP
    GOTO MakeNoise

Join: REM Search for end=begin point values and CONCATONATE if equal!
   LnPtr = 0: i = 0: k = 0: GOSUB BoxLine23: PRINT "Lines joined: ";
   DO UNTIL i >= nmp
      i = i + 1
       IF x%(i) = x%(i + 2) AND y%(i) = y%(i + 2) AND y%(i + 1) = LColor THEN
          nmp = nmp - 2: LNi = LNi - 1: k = k + 1: LOCATE bln - 2, 15: PRINT k
          FOR j = i + 1 TO nmp: x%(j) = x%(j + 2): y%(j) = y%(j + 2): NEXT j
          FOR j = LnPtr TO LNi: LN$(j) = LN$(j + 1): NEXT j
       ELSEIF x%(i) = 0 THEN LColor = y%(i): LnPtr = LnPtr + 1
       END IF
   LOOP: GOSUB DrawMap
   GOTO MakeNoise

MapCnvrt: CLS
   INPUT "Enter desired SCALE in pixels-per-deg (ENTER to abort)"; a$
   IF a$ = "" THEN RETURN
   PPDD = VAL(a$): Changed = Changed + 1
   INPUT "Enter New Latitude of origin"; a$
   IF a$ = "" THEN Nlat = LATo ELSE Nlat = VAL(a$)
   INPUT "Enter New Longitude of origin"; a$
   IF a$ = "" THEN Nlon = LONo ELSE Nlon = VAL(a$)
     ChgFac = PPDD / ppdv
     LOfset = LONo - Nlon
     LAfset = LATo - Nlat

     PRINT : PRINT "Now processing map points."

     FOR i = 1 TO nmp'DO WHILE NOT EOF(3)
         IF x%(i) <> 0 THEN
            x%(i) = ChgFac * (x%(i) - ppdv * LOfset)
            y%(i) = ChgFac * (y%(i) - ppdv * LAfset)
            IF x%(i) = 0 THEN x%(i) = 1: PRINT "ZERO value of X!  Converted to 1,"; y%
        ELSEIF y%(i) = -1 THEN i = nmp 'shuldnt occur since -1 is NOT in array
        END IF                         'but is only writen at end of file
     NEXT i
     PRINT
     PRINT : PRINT "CONVERSION SUCCESSFUL."
     INPUT "Hit ENTER to continue.."; a$
     LATo = Nlat
     LONo = Nlon
     ppdv = PPDD
     Display$ = "MAP": Redraw = -1: USGS = 0: GOSUB DrwMPaCur
     RETURN

Import: 'Also this does OVERLAY CtrlO
   IF (CDX <> LonCen OR CDY <> LatCen) AND NOT OVERLAY THEN
      CDX = LonCen: CDY = LatCen: GOSUB DrwMPaCur
      'Cuz TRIM calcs are based on range from CDX,CDY vice alt-CENTER
   END IF: IF Import$ = "" THEN Import$ = "    "
   LOCATE 42, 1: PRINT "IMPORT ALL FEATURES (of one color) FROM ANOTHER MAP THAT FIT INSIDE THIS MAP'S";
   LOCATE 43, 1: PRINT "BORDER.  POINTS ARE AUTOMATICALLY CONVERTED TO THE CURRENT SCALE AND ORIGIN.  ";
   LOCATE 41, 1: PRINT "Enter map filename ("; Import$; ")";
   INPUT a$
   IF a$ <> "" THEN
      Import$ = a$
      IF INSTR(a$, ".") = 0 THEN Import$ = Import$ + ".MAP"
   END IF: F$ = Import$
   Fault = 0: OPEN Import$ FOR INPUT AS #2
   IF Fault <> 0 THEN RETURN
   LOCATE bln - 3, 1
   INPUT "Color of feature to import (1 to 15) or ALL"; a$
   IF UCASE$(a$) = "ALL" OR a$ = "" THEN All = -1 ELSE All = 0
   IF a$ <> "" THEN Fcolr = VAL(a$)
   INPUT #2, LATa: LINE INPUT #2, a$:
   INPUT #2, LONa: LINE INPUT #2, a$: IF Nlon = 0 THEN Nlon = LONa
   INPUT #2, OppdV: LINE INPUT #2, a$'Pix-per-deg-Vert
   INPUT #2, oLatCen: LINE INPUT #2, a$
   INPUT #2, oLonCen: LINE INPUT #2, a$
   INPUT #2, oMapRng: LINE INPUT #2, a$
   INPUT #2, oMinRnga: LINE INPUT #2, a$
   LINE INPUT #2, a$
   IF a$ = "Compressed" THEN PRINT "OOPS, Cannot use a map in COMPRESSED format!"
   IF a$ = "Compressed" THEN BEEP: CLOSE #2: RETURN
   i = 0
   REM now make offset and scale calculations
   Nfac = ppdv / OppdV
   LOfset = LONa - LONo
   LAfset = LATa - LATo
    by = ppdv * MapRng / 60 ' These the same as TRIM borders
    bx = by / Lfac
    s = nmp'start for RE-DRAW at end of this routine
    x% = 1: y% = 1' To get around first test
    DO WHILE NOT EOF(2)
      IF x% = 0 AND y% = 0 THEN
         StrtPt = -1
         INPUT #2, LColor: LINE INPUT #2, a$'get color and name
         IF LColor = Fcolr OR All THEN
            IF NOT OVERLAY THEN
               x%(nmp) = 0: y%(nmp) = LColor ' over top of previous 0,0 at nmp
               LNi = LNi + 1: LN$(LNi) = a$
            END IF
            NofPts = 0' helps us not delete pts until line has at least 2 pts
            DO
               INPUT #2, x%, y%
               IF NOT OVERLAY THEN nmp = nmp + 1: Changed = Changed + 1
               IF x% = 0 THEN EXIT DO
               x = Nfac * (x% - OppdV * LOfset)
               y = Nfac * (y% - OppdV * LAfset)
               IF x = 0 THEN
                  x = 1
                  IF NOT OVERLAY THEN PRINT "ZERO value of X!  Converted to 1,"; y%
               END IF
               IF NOT OVERLAY THEN x%(nmp) = x: y%(nmp) = y
               IF x > dx + bx OR y > dy + by THEN bad = 1 ELSE bad = 0
               IF x < dx - bx OR y < dy - by THEN bad = 1
               IF bad AND NofPts > 1 THEN
                  IF NOT OVERLAY THEN nmp = nmp - 1
               ELSE NofPts = NofPts + 1
                    Xc = 320 + (x - dx) * HfacK
                    Yc = Ycen + (y - dy) * YfactrK
                    IF StrtPt THEN
                       PSET (Xc, Yc), LColor
                       CIRCLE (Xc, Yc), 2, 9: StrtPt = 0
                    ELSE
                       LINE -(Xc, Yc), LColor
                    END IF
               END IF
            LOOP
            IF NofPts = 2 AND bad AND NOT OVERLAY THEN LNi = LNi - 1: nmp = nmp - 3
            IF NOT OVERLAY THEN
               x%(nmp) = 0: y%(nmp) = 0
            ELSE CIRCLE (Xc, Yc), 3, 10
            END IF
         END IF
      ELSE INPUT #2, x%, y%
      END IF
      IF x% = 0 AND y% = -1 THEN EXIT DO
   LOOP
   FOR i = 40 TO 43: LOCATE i, 1: PRINT SPACE$(80); : NEXT
   LOCATE 41, 1: PRINT "All map points converted..."
      DO WHILE NOT EOF(2)
      LINE INPUT #2, a$
      LOOP: CLOSE #2
      IF NOT OVERLAY THEN GOSUB DP
      OVERLAY = 0
       
MakeNoise: SOUND 800, 4: SOUND 1500, 3: SOUND 500, 2
   RETURN

END

