 Rem File: IO8.bas - Dndedit.bas
 Rem $Include: 'dndedit.inc'

Function Timeit!
 t1$ = Format$(Now, "hh:mm:ss") ' seconds past midnight
 t1! = CSNG(INT(VAL(MID$(t1$, 1, 2)))) * 3600! + CSNG(INT(VAL(MID$(t1$, 4, 2)))) * 60! + CSNG(INT(VAL(MID$(t1$, 7, 2))))
 Timeit!=t1!
End Function

Function Time.Elapsed(Start.Time!,Wait.Time!)
 Elapsed.Time!=Timeit!-Start.Time!
 If Elapsed.Time!<SFalse Then
    Elapsed.Time!=Elapsed.Time!+86400!
 Endif
 If Elapsed.Time!>=Wait.Time! Then
    Time.Elapsed=True
 Else
    Time.Elapsed=False
 Endif
End Function

Function FClock2$
 FClock2$=Format$(Now,"dd mmm yyyy\, hh:mm:ss")
End Function

Sub Stdin(Var)
 Var=0
 ' check stdin length
 InregsX.AX = &H4202 ' eof
 InregsX.BX = 0 ' stdin
 InregsX.CX = 0
 InregsX.DX = 0
 CALL InterruptX(&H21, InregsX, OutregsX)
 IF OutregsX.AX = 0 THEN ' no input found
     EXIT SUB
 END IF
 Print "Illegal standard input attempted."
 END
End Sub

Sub Read.Keyboard(Var$)
 On Local Error Goto Error.Trap11
 Call Read.Node.Mess(Prompt$)
 Var$=Inkey$
 If Len(Var$) Then
    Exit Sub
 Endif
 If Local.Mode Then
    Call Release.Time(1)
    Exit Sub
 Endif
 Call Check.Carrier
 Call Driver(3)
 If (OutregsX.AX And &H0100)=&H0100 Then
    Call Driver(2)
    Char=(OutregsX.AX And &HFF)
    If Char<>False Then
       Buffer=Buffer+Chr$(Char)
    Endif
 Endif
 Select Case Len(Buffer)
 Case 0
    Eat$ = Nul
 Case 1
    Select Case Buffer
    Case Chr$(22) ' insert ^v
       Var$=Chr$(0)+Chr$(82)
       Buffer=Nul
    Case Chr$(127) ' delete
       Var$=Chr$(0)+Chr$(83)
       Buffer=Nul
    Case Chr$(27)
       Eat$ = Nul
    Case Else
       Var$=Buffer
       Buffer=Nul
    End Select
 Case 2
    Select Case Ucase$(Buffer)
    Case Chr$(27)+"I" ' up
       Var$=Chr$(0)+Chr$(72)
       Buffer=Nul
    Case Chr$(27)+"M" ' down
       Var$=Chr$(0)+Chr$(80)
       Buffer=Nul
    Case Chr$(27)+"K" ' right
       Var$=Chr$(0)+Chr$(77)
       Buffer=Nul
    Case Chr$(27)+"J" ' left
       Var$=Chr$(0)+Chr$(75)
       Buffer=Nul
    Case Chr$(27)+"O" ' home
       Var$=Chr$(0)+Chr$(71)
       Buffer=Nul
    Case Chr$(27)+"L" ' end
       Var$=Chr$(0)+Chr$(79)
       Buffer=Nul
    Case Chr$(27)+"U" ' pageup
       Var$=Chr$(0)+Chr$(73)
       Buffer=Nul
    Case Chr$(27)+"N" ' pagedown
       Var$=Chr$(0)+Chr$(81)
       Buffer=Nul
    Case Chr$(27)+Chr$(27) ' exit
       Var$=Chr$(27)
       Buffer=Nul
    Case Chr$(27)+"["
       Eat$ = Nul
    Case Chr$(27)+Chr$(13) ' ^x override
       Eat$ = Nul
    Case Else
       Buffer=Nul
    End Select
 Case 3
    Select Case Buffer
    Case Chr$(27)+"[A" ' Up ^[[A
       Var$=Chr$(0)+Chr$(72)
       Buffer=Nul
    Case Chr$(27)+"[B" ' Down ^[[B
       Var$=Chr$(0)+Chr$(80)
       Buffer=Nul
    Case Chr$(27)+"[C" ' Right ^[[C
       Var$=Chr$(0)+Chr$(77)
       Buffer=Nul
    Case Chr$(27)+"[D" ' Left ^[[D
       Var$=Chr$(0)+Chr$(75)
       Buffer=Nul
    Case Chr$(27)+"[H" ' Home ^[[H
       Var$=Chr$(0)+Chr$(71)
       Buffer=Nul
    Case Chr$(27)+"[K" ' End ^[[K
       Var$=Chr$(0)+Chr$(79)
       Buffer=Nul
    Case Else
       If Left$(Buffer,2)=Chr$(27)+Chr$(13) Then
          V$=Ucase$(Right$(Buffer,1))
          If V$>="A" And V$<="Z" Then
             Var$=Chr$(Asc(V$)-64) ' ^a - ^z
             Buffer=Nul
             Exit Sub
          Endif
       Endif
       Buffer=Nul
    End Select
 Case Else
    Var$=Nul
    Buffer=Nul
 End Select
Error.Resume11:
 Exit Sub
Error.Trap11:
 Resume Error.Resume11
End Sub

' adds dndpack detection 10/10/2024.
Sub Read.Node.Mess(VarX$)
 On Local Error Goto ErrorTrap13x
    DND.Path=Environ$("DNDBBS")
    If DND.Path<>Nul Then
       If Right$(DND.Path,1)<>"\" Then
          DND.Path=DND.Path+"\"
       Endif
    Endif
    FilenameX$=DND.Path+"NODEEXIT.OUT"
    If Dir$(FilenameX$)<>"" Then
       Color 7, 0
       Locate Max.Row-1,1,1
       Print
       Call Hang.Up
    Endif
ErrorResume13x:
 Exit Sub
ErrorTrap13x:
 Resume ErrorResume13x
End Sub

Sub Release.Time(Var)
 On Local Error Goto Error.Trap12
 If Supported.Call=False Then
    For Var2=1 To Var
       Call Slice.Function
       If (OutregsX.AX And &HFF)=&H80 Then
	  Supported.Call=True
	  Exit For
       Endif
    Next
 Endif
Error.Resume12:
 Exit Sub
Error.Trap12:
 Resume Error.Resume12
End Sub

Sub Check.Carrier
 On Local Error Goto Error.Trap13
 If Lost.Carrier Then
    Exit Sub
 Endif
 Call Driver(3)
 If (OutregsX.AX And &H80)=False Then
    Call Hang.Up
    Exit Sub
 Endif
Error.Resume13:
 Exit Sub
Error.Trap13:
 Resume Error.Resume13
End Sub

Sub Driver(Var)
 On Local Error Goto Error.Trap14
 If Local.Mode Then
    Exit Sub
 Endif
 Select Case Var
 Case 1
    InregsX.AX=InregsX.AX Or &H0100
 Case 2 To 5
    InregsX.AX=&H100*Var
 End Select
 InregsX.DX=Port
 Call InterruptX(&H14,InregsX,OutregsX)
Error.Resume14:
 Exit Sub
Error.Trap14:
 Resume Error.Resume14
End Sub

Sub Hang.Up
 On Local Error Goto Error.Trap15
 Buffer=Nul
 Func.Buffer=Nul
 Out2=Nul
 Strng=Nul
 Time.Left=180!
 Lost.Carrier=True
 Security.Guard=False
Error.Resume15:
 Exit Sub
Error.Trap15:
 Resume Error.Resume15
End Sub

Sub Check.Local.ANSI
 On Local Error Goto Error.Trap43
 Local.Mode=True
 Lost.Carrier=False
 Call Plex.Function(26)
 If (OutregsX.AX And &HFF)=&HFF Then
    Local.ANSI.Color=True
 Else
    Local.ANSI.Color=False
 Endif
 Call VideoInt(15,0)
 Video.Page=OutregsX.BX
Error.Resume43:
 Exit Sub
Error.Trap43:
 Resume Error.Resume43
End Sub

Sub ANSI(VarX,VarY,VarZ)
 On Local Error Goto Error.Trap16
 Var$=Nul
 Select Case VarX
 Case 1
    Var$=Chr$(27)+"[0;"+Mid$(Str$(VarY),2)+";"+Mid$(Str$(VarZ),2)+"m"
 Case 2
    Var$=Chr$(27)+"["+Mid$(Str$(VarY),2)+";"+Mid$(Str$(VarZ),2)+"H"
 Case 3
    Var$=Chr$(27)+"[2J"
 Case 4
    Var$=Chr$(27)+"[1;"+Mid$(Str$(VarY),2)+";"+Mid$(Str$(VarZ),2)+"m"
 Case 5
    TempD$=Chr$(27)+"["+Mid$(Str$(VarY),2)+"m"
 End Select
 Call Modem(Var$)
 If Local.ANSI.Color Then
    Call Scrn(Var$)
    Exit Sub
 Endif
 Select Case VarX
 Case 1
    Call Convert.Color(VarY,VarZ,True)
 Case 2
    Locate VarY,VarZ,1
 Case 3
    Cls
 Case 4
    Call Convert.Color(VarY,VarZ,False)
 Case 5
    Call Convert.Color(VarY,VarZ,False)
 End Select
Error.Resume16:
 Exit Sub
Error.Trap16:
 Resume Error.Resume16
End Sub

Sub Scrn(Var$)
 On Local Error Goto Error.Trap17
 Call Modem(Var$)
 Call MouseDriver(2)
 If Local.ANSI.Color Then
    For VarX=1 To Len(Var$)
       VarY=Asc(Mid$(Var$,VarX,1))
       Call StdinInt(6,VarY)
    Next
 Else
    Print Var$;
 Endif
 Call MouseDriver(1)
Error.Resume17:
 Exit Sub
Error.Trap17:
 Resume Error.Resume17
End Sub

Sub Modem(Var$)
 On Local Error Goto Error.Trap18
 If Lost.Carrier Then
    Exit Sub
 Endif
 If Local.Mode Then
    Exit Sub
 Endif
 For VarX=1 To Len(Var$)
    Var=Asc(Mid$(Var$,VarX,1))
    Do
       Call Driver(3)
       If (OutregsX.AX And &H4000)=&H4000 Then
          InregsX.AX=Var
          Call Driver(1) ' put char w/ wait
          Exit Do
       Endif
    Loop
 Next
 Do
    Call Driver(3) ' get line status
    If (OutregsX.AX And &H4000)=&H4000 Then ' empty buffer
       Exit Do
    Endif
 Loop
Error.Resume18:
 Exit Sub
Error.Trap18:
 Resume Error.Resume18
End Sub

Sub Convert.Color(VarX,VarY,VarZ)
 On Local Error Goto Error.Trap19
 Select Case VarX
 Case 30
    VarF=8
 Case 31
    VarF=12
 Case 32
    VarF=10
 Case 33
    VarF=14
 Case 34
    VarF=9
 Case 35
    VarF=13
 Case 36
    VarF=11
 Case 37
    VarF=15
 End Select
 Select Case VarY
 Case 40
    VarB=8
 Case 41
    VarB=12
 Case 42
    VarB=10
 Case 43
    VarB=14
 Case 44
    VarB=9
 Case 45
    VarB=13
 Case 46
    VarB=11
 Case 47
    VarB=15
 End Select
 If VarZ Then
    VarF=VarF-8
    VarB=VarB-8
 Endif
 Color VarF,VarB
Error.Resume19:
 Exit Sub
Error.Trap19:
 Resume Error.Resume19
End Sub

Sub Valid(Var$,Var)
 On Local Error Goto Error.Trap125
 If Len(Var$)/2<>Len(Var$)\2 Then
    Var$=Var$+" "
 Endif
 If Var/2<>Var\2 Then
    Var=Var+1
 Endif
 Var$=Left$(Var$,Var)
 Var$=Var$+Space$(Var-Len(Var$))
 For Var1=1 To Var
    Var2=Asc(Mid$(Var$,Var1,1))
    If Var2<32 Or Var2>127 Then
       Var$=Nul
       Exit Sub
    Endif
 Next
Error.Resume125:
 Exit Sub
Error.Trap125:
 Resume Error.Resume125
End Sub

Sub DisplayEditScreen(Var1,Var2,Var$)
 On Local Error Goto Error.Trap49
 Select Case Var1
 Case 1
    Restore RoomData
 Case 2
    Restore ObjectData
 Case 3
    Restore TreasureData
 Case 4
    Restore MonsterData
 Case 5
    Restore SpellData
 Case 6
    Restore ActionData
 Case 7
    Restore UserData
 Case 8
    Restore NonplayerData
 Case 9
    Restore MessBaseData
 Case 10
    Restore EmailData
 Case 11
    Restore PlayerData
 End Select
 For Temp2=1 To Var2
    Read Title.Data(Temp2), Array.Data(Temp2,1), Array.Data(Temp2,2)
 Next
 Call DisplayBorder(Var$)
 Call ANSI(4,37,44)
 Call ANSI(2,Array.Data(1,1),Array.Data(1,2))
 Strng=Title.Data(1)
 Call Scrn(Strng)
 Call ANSI(4,33,44)
 If Var1=2 Then
    Var2=15
 Endif
 For Temp2=2 To Var2
    Call ANSI(2,Array.Data(Temp2,1),Array.Data(Temp2,2))
    Strng=Title.Data(Temp2)
    Call Scrn(Strng)
 Next
 Selection=1
 Next.Field=0
Error.Resume49:
 Exit Sub
Error.Trap49:
 Resume Error.Resume49
End Sub

Sub DisplayBorder(Var$)
 On Local Error Goto Error.Trap50
 VarX$=Ucase$(Environ$("BLIND"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Off=True
 Endif
 VarX$=Ucase$(Environ$("BLINDCHAR"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Char=-1
 Endif
 Call ANSI(4,37,44)
 Call ANSI(3,0,0)
 Call ANSI(4,36,44)
 If Local.Mode Then
    Call Shell.ANSI.Program(1)
    If Border.Off=False Then
       Call ANSI(2,1,1)
       If Border.Char=0 Then
          Strng=Chr$(201)+String$(78,205)+Chr$(187)
       Else
          Strng="+"+String$(78,"-")+"+"
       Endif
       Call Scrn(Strng)
    Endif
 Endif
 Call ANSI(4,37,44)
 Var$=" "+Var$+" "
 VarX=Int(40-Len(Var$)/2+1)
 Call ANSI(2,1,VarX)
 Call Scrn(Var$)
 Call ANSI(4,36,44)
 If Local.Mode Then
    If Border.Off=False Then
       For Temp=2 To 24
          Call ANSI(2,Temp,1)
          If Border.Char=0 Then
             Strng=Chr$(186)
          Else
             Strng="|"
          Endif
          Call Scrn(Strng)
          Call ANSI(2,Temp,80)
          If Border.Char=0 Then
             Strng=Chr$(186)
          Else
             Strng="|"
          Endif
          Call Scrn(Strng)
       Next
    Endif
 Endif
 If Local.Mode Then
    If Border.Off=False Then
       Call ANSI(2,25,1)
       If Border.Char=0 Then
          Strng=Chr$(200)+String$(78,205)
       Else
          Strng="+"+String$(78,"-")
       Endif
       Call Scrn(Strng)
       Color 11,1
       Locate 25,80,0
       If Border.Char=0 Then
          Print Chr$(188);
       Else
          Print "+";
       Endif
       Locate 1,1,1
    Endif
 Endif
 Call ANSI(2,1,1)
Error.Resume50:
 Exit Sub
Error.Trap50:
 Resume Error.Resume50
End Sub

RoomData:
 Data "Short Description",3,2,"Long Description (press enter):",6,2
 Data "North",13,2,"East",15,2,"South",17,2,"West",19,2
 Data "Northeast",13,20,"Southeast",15,20,"Southwest",17,20,"Northwest",19,20
 Data "Up",13,40,"Down",15,40,"In",17,40,"Out",19,40
 Data "MonClass",13,60,"Action",15,60
 Data "Custom1",21,2,"Link1",21,23,"Custom2",21,38,"Link2",21,59

ObjectData:
 Data "Object Name",3,2,"Object Identifier",6,2,"Room Link",9,2,"Lighted",11,2
 Data "Light Time",11,12,"Key Number",13,2,"Description",15,2
 Data "Entry Description",18,2,"Hidden",3,50,"Invisible",5,50,"Jail Trap",7,50
 Data "Locked",9,50,"Relocks",11,50,"Permanent",13,50,"Trapped(B/C/D/F/P)",15,50
 Data "Hits For",17,50,"Fatigue/Vitality",18,50

TreasureData:
 Data "Treasure Name",3,2,"Identifier",5,2,"Weight",8,2,"Value",10,2
 Data "Plus",12,2,"Charges",14,2,"Class",15,2,"Treasure Type",16,2
 Data "Vehicle Type",18,2,"Container Max",20,2
 Data "Coins",3,20,"Potion",5,20,"Scroll",7,20,"Invisible",9,20
 Data "Loadable",11,20,"Loads Ammo",13,20,"Ammunition",15,20
 Data "Key Number",17,20,"Magical",19,20,"Container Prefix",20,20
 Data "Spell",3,40,"Ring",5,40, "Ring Protection Type",7,40
 Data "Antispell",9,40,"Light",11,40,"Light Charges",13,40
 Data "Fuel",15,40,"Fuel Charges",17,40,"Edible",19,40,"Rustable",3,62
 Data "Rust Percent",5,62,"Stealable",7,62,"Steal Percent",9,62
 Data "Launchable",11,62,"Launch Loads",13,62,"Launch Ammo",15,62
 Data "Movable",17,62,"Vehicle",19,62,"Type",20,62

MonsterData:
 Data "Monster Name",3,2,"Plural",6,2,"Level",9,2,"Hits",11,2,"Experience",13,2
 Data "Gold",15,2,"Jail",17,2,"Rate",19,2,"Rate Percent",19,13
 Data "Psionic",21,2,"Psi Spell",21,12,"Group Number",3,45
 Data "Poison",5,45,"Percent",5,60,"Level Drain",7,45,"Percent",7,60
 Data "Block",9,45,"Percent",9,60,"Prevent",11,45,"Percent",11,60
 Data "Follow",13,45,"Percent",13,60,"Teleport",12,72,"Cast Spell",15,45
 Data "Percent",15,60,"Spell",17,45,"Magical",19,45,"Permanent",19,55
 Data "Equation",20,45

SpellData:
 Data "Spell Name",3,2,"Teleport Room",6,2,"Level",8,2,"Spell Type",8,14
 Data "Psionic Spell",10,2,"Psionic Mode(A/D)",12,2,"Equation",13,2
 Data "Chant",15,2,"Spell Description",17,2,"Fighter",20,2,"Magic User",20,12
 Data "Thief",20,25,"Cleric",20,33,"Paladin",20,42,"Ranger",20,52
 Data "Druid",20,61,"Lady",20,70,"Spell Ingredients",3,49
 Data "Use Command",10,49,"Scroll",12,49,"Cast Command",14,49

ActionData:
 Data "Monster Number",4,2,"Talk to Monster",6,2,"Teleport to",8,2,"Spell",10,2
 Data "Level Entry",13,2,"Entry max/min",15,2,"N",18,2,"E",18,7,"S",18,12
 Data "W",18,17,"NE",18,22,"SE",18,28,"SW",18,34,"NW",18,40,"Up",18,46
 Data "Down",18,52,"In",18,60,"Out",18,66,"Go",18,73,"Health Rate",4,50
 Data "Encounter Rate",6,50,"Fumble",8,50,"Inventory Damage",10,50
 Data "Hits for(F/V)",12,50,"Fatigue/Vitality",13,50,"Rust Rate",15,50
 Data "Steal Rate",15,65,"Inventory Percent",16,50,"Inv Number",17,50

UserData:
 Data "Username",3,2,"Password",5,2,"Level",7,2,"Room",9,2,"Race",11,2
 Data "Class",12,2,"Alignment",13,2,"Classname",14,2,"Weapon Proficiency",16,2
 Data "Pole",17,2,"Blunt",17,11,"Sharp",17,21,"Thrusting",17,31
 Data "Fatigue",19,2,"Vitality",19,16,"Magic",19,31,"Psionic Points",21,2
 Data "Exp",3,50,"Gold",5,50,"Time Limit",7,50,"Strength",9,50
 Data "Intelligence",11,50,"Wisdom",13,50,"Dexterity",15,50
 Data "Constitution",17,50,"Piety",19,50,"Charisma",21,50

NonplayerData:
 Data "Monster Name",3,2,"Rooms(comma separated)",6,2,"Level",9,2,"Hits",11,2,"Experience",13,2
 Data "Gold",15,2,"Jail",17,2,"Rate",19,2,"Rate Percent",19,13
 Data "Psionic",21,2,"Psi Spell",21,12,"Group Number",3,45
 Data "Poison",5,45,"Percent",5,60,"Level Drain",7,45,"Percent",7,60
 Data "Block",9,45,"Percent",9,60,"Prevent",11,45,"Percent",11,60
 Data "Follow",13,45,"Percent",13,60,"Teleport",12,72,"Cast Spell",15,45
 Data "Percent",15,60,"Spell",17,45,"Magical",19,45,"Permanent",19,55
 Data "Equation",20,45

MessBaseData:
 Data "Messbase Name",3,2
 Data "Deleted",6,2
 Data "Base Type Restrictions",7,2
 Data "Base Filename",17,2

EmailData:
 Data "Text",3,2
 Data "Private",4,2
 Data "Deleted",6,2
 Data "From",8,2
 Data "Subject",10,2
 Data "TO",12,2
 Data "Time",14,2

 Data "Received",4,40
 Data "Times Read",6,40
 Data "Replied to",8,40
 Data "Thread",10,40
 Data "Stat",12,40
 Data "Type",14,40

PlayerData:
 Data "Team Name",4,2
 Data "Password",6,2
 Data "Deleted",8,2
 Data "Member#1",10,2
 Data "Member#2",12,2
 Data "Member#3",14,2
 Data "Member#4",16,2
 Data "Member#5",18,2
 Data "Team Gold",20,2
 Data "Prefix",8,14

Sub MouseDriver(Var1)
 On Local Error Goto Error.Trap5
 Static Mouse.X As Integer, Mouse.Y As Integer
 If Mouse.Present=False Then
    Exit Sub
 Endif
 Select Case Var1
 Case 1 ' show mouse
    Call Mouse.Function(1,0) ' ax, bx
 Case 2 ' hide mouse
    Call Mouse.Function(2,0) ' ax, bx
 Case 3
    Mouse.Button=False
    Call Mouse.Function(5,0)
    If (OutregsX.AX AND 1)=1 Then
       If OutregsX.BX>False Then
          Mouse.Button=True
          Mouse.Row=Int((OutregsX.DX)/8+1)
          Mouse.Column=Int((OutregsX.CX)/8+1)
          Exit Sub
       Endif
    Endif
    Mouse.Button2=False
    Call Mouse.Function(5,1)
    If (OutregsX.AX AND 2)=2 Then
       If OutregsX.BX>False Then
          Mouse.Button2=True
          Exit Sub
       Endif
    Endif
    Mouse.Button3=False
    Call Mouse.Function(5,2)
    If (OutregsX.AX AND 4)=4 Then
       If OutregsX.BX>False Then
          Mouse.Button3=True
          Call Terminate.Program(True)
          Exit Sub
       Endif
    Endif
    Call Mouse.Function(3,0)
    Var2=Int((OutregsX.CX)/8+1)
    Var3=Int((OutregsX.DX)/8+1)
    Mouse.Row=False
    Mouse.Column=False
    If Var2<>Mouse.Y Or Var3<>Mouse.X Then
       Mouse.X=Var3
       Mouse.Y=Var2
       Mouse.Row=Mouse.X
       Mouse.Column=Mouse.Y
    Endif
 End Select
Error.Resume5:
 Exit Sub
Error.Trap5:
 Resume Error.Resume5
End Sub

Sub MouseButton(Var1)
 On Local Error Goto Error.Trap9
 For Var=1 To Var1
    If Mouse.Row=Array.Data(Var,1) Then
       If Mouse.Column>=Array.Data(Var,2) Then
          If Mouse.Column<=Array.Data(Var,2)+Len(Rtrim$(Title.Data(Var)))-1 Then
             If Var=Selection Then
                TempX$=Chr$(13)
             Endif
             Exit Sub
          Endif
       Endif
    Endif
 Next
 Call MouseCheck
Error.Resume9:
 Exit Sub
Error.Trap9:
 Resume Error.Resume9
End Sub

Sub MouseCheck
 On Local Error Goto Error.Trap10
 For Var=22 To 24
    If Mouse.Row=Var Then
       Select Case Var
       Case 22
          TempD$=Lcase$(TempC$)
       Case 23
          TempD$=Lcase$(TempA$)
       Case 24
          TempD$=Lcase$(TempB$)
       End Select
       If Len(TempD$) Then
          Var1=Instr(TempD$,"<esc>")
          If Var1 Then
             If Mouse.Column>=Var1 And Mouse.Column<=Var1+4 Then
                TempX$=Chr$(27)
                Exit Sub
             Endif
          Endif
          Var1=Instr(TempD$,"<esc> exit and save")
          If Var1 Then
             If Mouse.Column>=Var1 And Mouse.Column<=Var1+18 Then
                TempX$=Chr$(27)
                Exit Sub
             Endif
          Endif
          Var1=Instr(TempD$,Chr$(60)+Chr$(217)+" enter choice")
          If Var1 Then
             If Mouse.Column>=Var1 And Mouse.Column<=Var1+14 Then
                TempX$=Chr$(13)
                Exit Sub
             Endif
          Endif
          Var1=Instr(TempD$,Chr$(60)+Chr$(217)+" exit field")
          If Var1 Then
             If Mouse.Column>=Var1 And Mouse.Column<=Var1+14 Then
                TempX$=Chr$(13)
                Exit Sub
             Endif
          Endif
          Var1=Instr(TempD$,Chr$(60)+Chr$(217)+" select")
          If Var1 Then
             If Mouse.Column>=Var1 And Mouse.Column<=Var1+14 Then
                TempX$=Chr$(13)
                Exit Sub
             Endif
          Endif
          For Var1=Mouse.Column To 1 Step -1
             If Mid$(TempD$,Var1,1)="^" Then
                VarX$=Mid$(TempD$,Var1+1,1)
                If VarX$>="a" And VarX$<="z" Then
                   TempX$=Chr$(Asc(VarX$)-96)
                   Exit Sub
                Else
                   If VarX$="?" Then ' added 06/20/2022
                      TempX$=VarX$
                      Exit Sub
                   Endif
                Endif
             Endif
          Next
          If Asc(Mid$(TempD$,2,1))=24 Then
             If Mouse.Column=2 Then
                TempX$=Chr$(0)+Chr$(72)
                Exit Sub
             Endif
          Endif
          If Asc(Mid$(TempD$,3,1))=25 Then
             If Mouse.Column=3 Then
                TempX$=Chr$(0)+Chr$(80)
                Exit Sub
             Endif
          Endif
       Endif
       Exit For
    Endif
 Next
Error.Resume10:
 Exit Sub
Error.Trap10:
 Resume Error.Resume10
End Sub

Sub MouseSelect(Var1)
 On Local Error Goto Error.Trap7
 For Var=1 To Var1
    If Mouse.Row=Array.Data(Var,1) Then
       If Mouse.Column>=Array.Data(Var,2) Then
          Var1=Len(Rtrim$(Title.Data(Var)))
          If Mouse.Column<=Array.Data(Var,2)+Var1-1 Then
             If Var<>Selection Then
                Next.Field=Var
                Call ShowField
             Endif
             Exit For
          Endif
       Endif
    Endif
 Next
Error.Resume7:
 Exit Sub
Error.Trap7:
 Resume Error.Resume7
End Sub

Sub Terminate.Program(Var)
 On Local Error Goto Error.Trap1
 Var$=Strng : Var2$=Strng2
 Call MouseDriver(2)
 Call Clear.Screen
 Erase Array.Data, Edit.Data, Link.Data, Title.Data
 If Chained Then
    Chain DND.Path+"DNDBBS.EXE"
 Endif
 Call MouseDriver(2)
 Call Decrease.PSP
 If Chained=False Then
    Call Save.Screen(True)
 Endif
 Color 15,0
 Print
 If Var>=0 Then
    Print
    Color 15,0
    Print "DndEdit menu error:"
    Color 14,0
    Print
    Print Var$
    If Var=1 Then Print Var2$
    Print
    Print "Check command line and restart Dndedit."
    Color 15,0
    Print
 Endif
 Print "Now exiting Dndedit.."
 Call MouseDriver(2)
 Color 7,0
Error.Resume1:
 End
Error.Trap1:
 Resume Error.Resume1
End Sub

Sub Clear.Screen
 On Local Error Goto Error.Trap2
 Color 7,0
 Call ANSI(1,37,0)
 Cls
 Call ANSI(3,0,0)
 Locate Max.Row-1,1,1
 Call ANSI(2,Max.Row-1,1)
Error.Resume2:
 Exit Sub
Error.Trap2:
 Resume Error.Resume2
End Sub

Sub Clear.Screen2
 ' force screen to blue
 On Local Error Goto Error.Trap2a
 Color 7,1
 Cls
 Locate Max.Row-1,1,1
Error.Resume2a:
 Exit Sub
Error.Trap2a:
 Resume Error.Resume2a
End Sub

Sub Save.Screen(Var)
 On Local Error Goto Error.Trap62
 If Var=False Then
    VarX3=(Max.Row-1)*80+80
    Redim Temp.ArrayY(VarX3) As Long
    Redim Temp.ArrayZ(VarX3) As Double
    For Var1=1 To Max.Row
       For Var2=1 To 80
          TempZ1=Screen(Var1,Var2)
          TempZ2=Screen(Var1,Var2,1)
          VarX2=(Var1-1)*80+Var2
          Temp.ArrayY(VarX2)=TempZ1
          Temp.ArrayZ(VarX2)=TempZ2
       Next
    Next
 Else
    Cls
    For VarX=Max.Row To 1 Step -1
       For VarY=1 To 80
          VarX2=(VarX-1)*80+VarY
          If Temp.ArrayY(VarX2)<>32 Then
             Goto Next.Line
          Endif
       Next
    Next
Next.Line:
    TempX=VarX
    For Var1=1 To VarX ' Max.Row
       For Var2=1 To 80
          VarX2=(Var1-1)*80+Var2
          VarB=Int(Temp.ArrayZ(VarX2)/16)
          VarF=Temp.ArrayZ(VarX2) Mod 16
          TempZ1=Temp.ArrayY(VarX2)
          Locate Var1,Var2,0
          Color VarF,VarB
          Print Chr$(TempZ1);
       Next
    Next
 Endif
Error.Resume62:
 Exit Sub
Error.Trap62:
 Resume Error.Resume62
End Sub

Sub RedisplayField
 On Local Error Goto Error.Trap57
 Call ANSI(4,37,45)
 Call ANSI(2,Array.Data(Selection,1),Array.Data(Selection,2))
 Strng=Title.Data(Selection)
 Call Scrn(Strng)
Error.Resume57:
 Exit Sub
Error.Trap57:
 Resume Error.Resume57
End Sub

Sub ScreenEdit
 On Local Error Goto Error.Trap47
 For Temp2=1 To Max.Lines
    Edit.Data(Temp2)=Rtrim$(Edit.Data(Temp2))
 Next
 Inserting=True
 Call ANSI(4,37,44)
 Call ANSI(2,2,73)
 Strng="Insert "
 Call Scrn(Strng)
 Call ANSI(4,37,40)
 If Max.Lines=1 Then
    Call ANSI(2,Xcoor,Ycoor)
    Locate Xcoor,Ycoor,1
    Call Scrn(Rtrim$(Edit.Data(1)))
    Ycoor=Ycoor+Len(Rtrim$(Edit.Data(1)))
 Endif
 Do While Lost.Carrier=False
    Call ANSI(2,Xcoor,Ycoor)
    IF Inserting = -3 THEN
       Locate Xcoor, Ycoor, 1, 1, 7
    ELSE
       IF Inserting = -1 THEN
          Locate Xcoor,Ycoor,1,3,7
       Else
          Locate Xcoor,Ycoor,1,7,7
       Endif
    Endif
    TempX$=Nul
    Do While TempX$=Nul
       If Lost.Carrier Then
          Exit Do
       Endif
       Call Read.Keyboard(TempX$)
       Call MouseDriver(3)
       If Mouse.Button2 Then
          TempX$=Chr$(27)
       Endif
       If Mouse.Button3 Then
          Call Terminate.Program(True)
          End
       Endif
       If Mouse.Button Then
          If Multiplier Then
             If Mouse.Row=23 Then
                If Mouse.Column=Multiplier+2 Then ' +
                   TempX$="+"
                   Exit Do
                Endif
                If Mouse.Column=Multiplier+4 Then ' -
                   TempX$="-"
                   Exit Do
                Endif
                If Mouse.Column=Multiplier+6 Then ' x
                   TempX$="x"
                   Exit Do
                Endif
             Endif
          Endif
          If Mouse.Row=Row Then
             If Mouse.Column>=Column And Mouse.Column<=Column+Line.Length-1 Then
                If Max.Lines=1 Then
                   If Multiplier=0 Then
                      Select Case Lcase$(Rtrim$(Edit.Data(1)))
                      Case "y"
                         Edit.Data(1)="N"
                         Xcoor=Row
                         Ycoor=Column
                         Call ANSI(2,Xcoor,Ycoor)
                         Locate Xcoor,Ycoor,1
                         Call Scrn("N")
                      Case "n"
                         Edit.Data(1)="Y"
                         Xcoor=Row
                         Ycoor=Column
                         Call ANSI(2,Xcoor,Ycoor)
                         Locate Xcoor,Ycoor,1
                         Call Scrn("Y")
                      End Select
                   Endif
                Endif
             Endif
          Endif
       Endif
       If Mouse.Button Then
          Call MouseCheck
       Endif
    Loop
    If Multiplier Then
       Select Case Lcase$(TempX$)
       Case "+"
          ' maxint single fixed 10/10/2020
          Var!=Int(Val(Edit.Data(1))+.5)+1! ' edit field is 6 char.
          If Var!<999999! Then
             Gosub DisplayField1
          Else
             Var!=999999!
             Gosub DisplayField1
          Endif
          TempX$=Nul
       Case "-"
          Var!=Int(Val(Edit.Data(1))+.5)-1!
          If Var!>0! Then
             Gosub DisplayField1
          Endif
          TempX$=Nul
       Case "x"
          Exit Do
       End Select
    Endif
    Select Case Len(TempX$)
    Case 1
       Select Case TempX$
       Case Chr$(13)
          ' exit
          If Max.Lines=1 Then
             Exit Do
          Endif
          ' nextline
          If Line.Number<Max.Lines Then
             Line.Number=Line.Number+1
             Xcoor=Xcoor+1
             Ycoor=Column
          Endif
       Case Chr$(8) ' backspace
          ' move up 1 line
          If Line.Number > 1 Then
             If Ycoor = Column Then
                Xcoor = Xcoor - 1
                Line.Number = Line.Number - 1
             Endif
          Endif
          ' move left 1 char and display line
          If Ycoor-Column>False Then
             If Inserting=False Then
                Ycoor=Ycoor-1
             Else
                Edit.Data(Line.Number)= _
                Left$(Edit.Data(Line.Number),Ycoor-Column-1)+ _
                Mid$(Edit.Data(Line.Number),Ycoor-Column+1)
                Ycoor=Ycoor-1
                If Hidden=False Then
                   Call ANSI(2,Xcoor,Ycoor)
                   Strng=Mid$(Edit.Data(Line.Number),Ycoor-Column+1)+" "
                   Call Scrn(Strng)
                Else
                   If Hidden=-1 Then
                      Call ANSI(2,Row,Column)
                      VarX$=String$(20,Mask$)
                      Call Scrn(VarX$)
                   Else
                      Call ANSI(2,Row,Column)
                      VarX$=String$(Len(Edit.Data(Line.Number)),Mask$)+" "
                      Call Scrn(VarX$)
                   Endif
                Endif
             Endif
          Endif
       Case Chr$(9) ' tab
          If Ycoor-Column+8<=Len(Edit.Data(Line.Number)) Then
             Ycoor=Ycoor+8
          Else
             Ycoor=Len(Edit.Data(Line.Number))+Column
          Endif
       Case Chr$(27) ' exit
          Inserting=-2
          Exit Do
       Case Else ' insert character
          VarX=0
          If Multiplier Then
             If Asc(TempX$)>=48 And Asc(TempX$)<=57 Then ' 0-9
                VarX=-1
             Endif
          Else
             If Asc(TempX$)>=32 And Asc(TempX$)<=127 Then ' char
                VarX=-1
             Endif
          Endif
          If VarX Then
             If Ycoor-Column+1>Line.Length Then
                If Max.Lines>1 Then
                   If Line.Number<Max.Lines Then
                      Line.Number=Line.Number+1
                      Xcoor=Xcoor+1
                      Ycoor=Column
                   Endif
                Endif
             Else
                If Inserting=False Then
                   If Ycoor-Column+1>Len(Edit.Data(Line.Number)) Then
                      Edit.Data(Line.Number)=Edit.Data(Line.Number)+TempX$
                   Else
                      Mid$(Edit.Data(Line.Number),Ycoor-Column+1,1)=TempX$
                   Endif
                   Strng=TempX$
                   If Hidden=False Then
                      Call ANSI(2,Xcoor,Ycoor)
                      Call Scrn(Strng)
                   Else
                      If Hidden=-1 Then
                         Call ANSI(2,Row,Column)
                         VarX$=String$(20,Mask$)
                         Call Scrn(VarX$)
                      Else
                         Call ANSI(2,Row,Column)
                         VarX$=String$(Len(Edit.Data(Line.Number)),Mask$)
                         Call Scrn(VarX$)
                      Endif
                   Endif
                   Ycoor=Ycoor+1
                Else
                   Edit.Data(Line.Number)= _
                   Left$(Edit.Data(Line.Number),Ycoor-Column)+TempX$+ _
                   Mid$(Edit.Data(Line.Number),Ycoor-Column+1)
                   Edit.Data(Line.Number)= _
                   Left$(Edit.Data(Line.Number),Line.Length)
                   Strng=Mid$(Edit.Data(Line.Number),Ycoor-Column+1)
                   If Hidden=False Then
                      Call ANSI(2,Xcoor,Ycoor)
                      Call Scrn(Strng)
                   Else
                      If Hidden=-1 Then
                         Call ANSI(2,Row,Column)
                         VarX$=String$(20,Mask$)
                         Call Scrn(VarX$)
                      Else
                         Call ANSI(2,Row,Column)
                         VarX$=String$(Len(Edit.Data(Line.Number)),Mask$)
                         Call Scrn(VarX$)
                      Endif
                   Endif
                   Ycoor=Ycoor+1
                Endif
             Endif
          Endif
       End Select
    Case 2
       Temp=Asc(Mid$(TempX$,2,1))
       Select Case Temp
       Case 0 'ctrl-break
          Inserting=-2
          Exit Do
       Case 82 ' insert
          Select Case Inserting
          Case 0
             Inserting=-1
          Case -1
             Inserting=-3
          Case -3
             Inserting=0
          End Select
          Call ANSI(4,37,44)
          Call ANSI(2,2,73)
          If Inserting=False Then
             Strng=Space$(7)
          Else
             If Inserting=-1 Then
                Strng="Insert "
             Else
                Strng="InsertX"
             Endif
          Endif
          Call Scrn(Strng)
          Call ANSI(4,37,40)
       Case 83, 147 ' delete/control-delete
          If Ycoor-Column+1<=Len(Edit.Data(Line.Number)) Then
             Edit.Data(Line.Number)= _
             Left$(Edit.Data(Line.Number),Ycoor-Column)+ _
             Mid$(Edit.Data(Line.Number),Ycoor-Column+2)
             If Hidden=False Then
                Call ANSI(2,Xcoor,Ycoor)
                Strng=Mid$(Edit.Data(Line.Number),Ycoor-Column+1)+" "
                Call Scrn(Strng)
             Else
                If Hidden=-1 Then
                   Call ANSI(2,Row,Column)
                   VarX$=String$(20,Mask$)
                   Call Scrn(VarX$)
                Else
                   Call ANSI(2,Row,Column)
                   VarX$=String$(Len(Edit.Data(Line.Number)),Mask$)+" "
                   Call Scrn(VarX$)
                Endif
             Endif
          Endif
       Case 71 ' home
          Ycoor=Column
       Case 79 ' end
          Ycoor=Len(Edit.Data(Line.Number))+Column
       Case 15 ' shift-tab
          If Ycoor-Column-8>False Then
             Ycoor=Ycoor-8
          Else
             Ycoor=Column
          Endif
       Case 77, 157 ' right/alt-right
          If Ycoor-Column+1<=Len(Edit.Data(Line.Number)) Then
             Ycoor=Ycoor+1
          Endif
       Case 75, 155 ' left/alt-left
          If Ycoor-Column>False Then
             Ycoor=Ycoor-1
          Endif
       Case 72, 141, 152 ' up/ctrl-up/alt-up
          If Line.Number>1 Then
             Xcoor=Xcoor-1
             Line.Number=Line.Number-1
             If Ycoor-Column+1>Len(Edit.Data(Line.Number)) Then
                Ycoor=Len(Edit.Data(Line.Number))+Column
             Endif
          Endif
       Case 80, 145, 160 ' down/ctrl-dn/alt-dn
          If Line.Number<Max.Lines Then
             Xcoor=Xcoor+1
             Line.Number=Line.Number+1
             If Ycoor-Column+1>Len(Edit.Data(Line.Number)) Then
                Ycoor=Len(Edit.Data(Line.Number))+Column
             Endif
          Endif
       Case 73, 132 ' pageup/ctrl-pageup
          If Line.Number>1 Then
             Xcoor=Row
             Line.Number=1
             If Ycoor-Column+1>Len(Edit.Data(Line.Number)) Then
                Ycoor=Len(Edit.Data(Line.Number))+Column
             Endif
          Endif
       Case 81, 118 ' pagedown/ctrl-pagedn
          If Line.Number<Max.Lines Then
             Temp2=Max.Lines
             Do While Lost.Carrier=False
                Xcoor=Row+Temp2-1
                Line.Number=Temp2
                If Line.Number=1 Then
                   Exit Do
                Endif
                If Len(Edit.Data(Line.Number))=False Then
                   Temp2=Temp2-1
                Else
                   Exit Do
                Endif
             Loop
             If Ycoor-Column+1>Len(Edit.Data(Line.Number)) Then
                Ycoor=Len(Edit.Data(Line.Number))+Column
             Endif
          Endif
       Case 119 ' control-home
          Xcoor=Row
          Line.Number=1
          Ycoor=Column
       Case 117 ' control-end
          Temp2=Max.Lines
          Do While Lost.Carrier=False
             Xcoor=Row+Temp2-1
             Line.Number=Temp2
             If Line.Number=1 Then
                Exit Do
             Endif
             If Len(Edit.Data(Line.Number))=False Then
                Temp2=Temp2-1
             Else
                Exit Do
             Endif
          Loop
          Ycoor=Len(Edit.Data(Line.Number))+Column
       Case 116 ' control-right
          Do While Lost.Carrier=False
             For Temp2=Ycoor-Column+1 To Len(Edit.Data(Line.Number))-1
                If Mid$(Edit.Data(Line.Number),Temp2,1)=" " Then
                   If Mid$(Edit.Data(Line.Number),Temp2+1,1)<>" " Then
                      Ycoor=Temp2+Column
                      Exit Do
                   Endif
                Endif
             Next
             If Ycoor-Column+1<=Len(Edit.Data(Line.Number)) Then
                Ycoor=Len(Edit.Data(Line.Number))+Column
             Else
                If Max.Lines>1 And Line.Number<Max.Lines Then
                   Line.Number=Line.Number+1
                   Xcoor=Xcoor+1
                   Ycoor=Column
                Endif
             Endif
             Exit Do
          Loop
       Case 115 ' control-left
          Do While Lost.Carrier=False
             For Temp2=Ycoor-Column-1 To 1 Step -1
                If Mid$(Edit.Data(Line.Number),Temp2,1)=" " Then
                   Ycoor=Temp2+Column
                   Exit Do
                Endif
             Next
             If Ycoor=Column Then
                If Max.Lines>1 And Line.Number>1 Then
                   Line.Number=Line.Number-1
                   Xcoor=Xcoor-1
                   Ycoor=Len(Edit.Data(Line.Number))+Column
                Endif
             Else
                Ycoor=Column
             Endif
             Exit Do
          Loop
       End Select
    End Select
 Loop
 Call ANSI(4,37,44)
 Call ANSI(2,2,73)
 Strng=Space$(7)
 Call Scrn(Strng)
 Locate ,,1,7,7
 Exit Sub
DisplayField1:
 ' cursor position fixed 02/22/2022
 VarX$=Space$(Line.Length)
 Xcoor=Row
 Ycoor=Column
 Call ANSI(2,Xcoor,Ycoor)
 Call Scrn(VarX$)

 VarX$=Ltrim$(Str$(Var!))
 VarX$=Left$(VarX$,Line.Length)
 Edit.Data(1)=VarX$
 Xcoor=Row
 Ycoor=Column
 Call ANSI(2,Xcoor,Ycoor)
 Call Scrn(Edit.Data(1))

 Ycoor=Len(Rtrim$(Edit.Data(1)))+Column ' end
 IF Inserting=-3 THEN
    Locate Xcoor,Ycoor,1,1,7
 Else
    If Inserting=-1 Then
       Locate Xcoor,Ycoor,1,3,7
    Else
       Locate Xcoor,Ycoor,1,7,7
    Endif
 Endif
 Return
Error.Resume47:
 Exit Sub
Error.Trap47:
 Resume Error.Resume47
End Sub

Sub StatusLine
 On Local Error Goto Error.Trap116
 TempA$=Rtrim$(Strng)
 TempB$=Rtrim$(Out2)
 Call ANSI(4,33,44)
 Call ANSI(2,23,2)
 Strng=Space$(78)
 Call Scrn(Strng)
 Call ANSI(2,23,2)
 Call Scrn(TempA$)
 Call ANSI(2,24,2)
 Strng=Space$(78)
 Call Scrn(Strng)
 Call ANSI(2,24,2)
 Call Scrn(TempB$)
 TempA$=" "+TempA$
 TempB$=" "+TempB$
Error.Resume116:
 Exit Sub
Error.Trap116:
 Resume Error.Resume116
End Sub

Sub ShowField
 On Local Error Goto Error.Trap55
 If Next.Field Then
    Call ANSI(4,33,44)
    Call DisplayField
    Selection=Next.Field
    Call ANSI(4,37,45)
    Call DisplayField
 Endif
Error.Resume55:
 Exit Sub
Error.Trap55:
 Resume Error.Resume55
End Sub

Sub DisplayField
 On Local Error Goto Error.Trap56
 Call ANSI(2,Array.Data(Selection,1),Array.Data(Selection,2))
 Strng=Title.Data(Selection)
 Call Scrn(Strng)
Error.Resume56:
 Exit Sub
Error.Trap56:
 Resume Error.Resume56
End Sub

Sub ErrorMessage
 On Local Error Goto Error.Trap51
 TempC$=Strng+" Press <esc>."
 Call ANSI(4,37,44)
 Call ANSI(2,22,2)
 Strng=Space$(78)
 Call Scrn(Strng)
 Call ANSI(2,22,2)
 Call Scrn(TempC$)
 TempC$=" "+TempC$
 TempX$=Nul
 Do While TempX$<>Chr$(27)
    If Lost.Carrier Then
       Exit Do
    Endif
    Call Read.Keyboard(TempX$)
    Call MouseDriver(3)
    If Mouse.Button2 Then
       TempX$=Chr$(27)
    Endif
    If Mouse.Button3 Then
       Call Terminate.Program(True)
       End
    Endif
    If Mouse.Button Then
       Call MouseCheck
    Endif
 Loop
 Call ANSI(2,22,2)
 Strng=Space$(78)
 Call Scrn(Strng)
 Call RedisplayField
Error.Resume51:
 Exit Sub
Error.Trap51:
 Resume Error.Resume51
End Sub

Sub TitleBar(Title$)
 On Local Error Goto ErrorTrp27x2
 VarX$=Ucase$(Environ$("BLIND"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Off=True
 Endif
 VarX$=Ucase$(Environ$("BLINDCHAR"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Char=-1
 Endif
 Strng=Title$
 If Border.Off=False Then
    If Border.Char=0 Then
       Strng=Strng+String$(8,205)
    Else
       Strng=Strng+String$(8,"+")
    Endif
 Else
    Strng=Strng+Space$(8)
 Endif
 Call ANSI(2,6,45)
 Call Scrn(Strng)
ErrorRsm27x2:
 Exit Sub
ErrorTrp27x2:
 Resume ErrorRsm27x2
End Sub

Sub MakeBox(x1,y1,x2,y2)
 On Local Error Goto ErrorTrp27x
 VarX$=Ucase$(Environ$("BLIND"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Off=True
 Endif
 VarX$=Ucase$(Environ$("BLINDCHAR"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Char=-1
 Endif
 '201,205,187
 '186     186
 '200,205,188
 If x2-x1<2 Then
    Exit Sub
 Endif
 If y2-y1<2 Then
    Exit Sub
 Endif
 Call ANSI(4,33,44)
 Call ANSI(2,x1,y1) ' upper-left
 If Border.Off=False Then
    If Border.Char=0 Then
       Strng=Chr$(201)
    Else
       Strng="+"
    Endif
 Else
    Strng=" "
 Endif
 Call Scrn(Strng)
 Call ANSI(2,x2,y2) ' lower-right
 If Border.Off=False Then
    If Border.Char=0 Then
       Strng=Chr$(188)
    Else
       Strng="+"
    Endif
 Else
    Strng=" "
 Endif
 Call Scrn(Strng)
 Call ANSI(2,x1,y2) ' upper-right
 If Border.Off=False Then
    If Border.Char=0 Then
       Strng=Chr$(187)
    Else
       Strng="+"
    Endif
 Else
    Strng=" "
 Endif
 Call Scrn(Strng)
 Call ANSI(2,x2,y1) ' lower-left
 If Border.Off=False Then
    If Border.Char=0 Then
       Strng=Chr$(200)
    Else
       Strng="+"
    Endif
 Else
    Strng=" "
 Endif
 Call Scrn(Strng)
 Call ANSI(2,x1,y1+1) ' top bar
 If Border.Off=False Then
    If Border.Char=0 Then
       Strng=String$(y2-y1-1,205)
    Else
       Strng=String$(y2-y1-1,"-")
    Endif
 Else
    Strng=String$(y2-y1-1,32)
 Endif
 Call Scrn(Strng)
 Call ANSI(2,x2,y1+1) ' lower bar
 If Border.Off=False Then
    If Border.Char=0 Then
       Strng=String$(y2-y1-1,205)
    Else
       Strng=String$(y2-y1-1,"-")
    Endif
 Else
    Strng=String$(y2-y1-1,32)
 Endif
 Call Scrn(Strng)
 For V=x1+1 To x2-1 ' left side
    Call ANSI(2,V,y1)
    If Border.Off=False Then
       If Border.Char=0 Then
          Strng=Chr$(186)
       Else
          Strng="|"
       Endif
    Else
       Strng=" "
    Endif
    Call Scrn(Strng)
 Next
 For V=x1+1 To x2-1 ' right side
    Call ANSI(2,V,y2)
    If Border.Off=False Then
       If Border.Char=0 Then
          Strng=Chr$(186)
       Else
          Strng="|"
       Endif
    Else
       Strng=" "
    Endif
    Call Scrn(Strng)
 Next
 ' fill area of box
 For Var=x1+1 To x2-1
    Call ANSI(2,Var,y1+1)
    Strng=Space$(y2-y1-1)
    Call Scrn(Strng)
 Next
ErrorRsm27x:
 Exit Sub
ErrorTrp27x:
 Resume ErrorRsm27x
End Sub

Sub Help(Var1)
 On Local Error Goto Error.Trap53
 VarX$=Ucase$(Environ$("BLIND"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Off=True
 Endif
 VarX$=Ucase$(Environ$("BLINDCHAR"))
 If VarX$="ON" Or VarX$="-1" Or VarX$="TRUE" Then
    Border.Char=-1
 Endif
 Close #HelpFile4
 FileName2$=Help.FileName4
 Open FileName2$ For Random Shared As #HelpFile4 Len=HelpRecLen4
 Call ANSI(4,37,44)
 Call ANSI(3,0,0)
 Call ANSI(4,36,44)
 Call MouseDriver(2)
 Color 7,1 : Cls
 Call MouseDriver(1)
 If Local.Mode Then
    Call Shell.ANSI.Program(1)
    Call ANSI(4,36,44)
    If Border.Off=False Then
       Call ANSI(2,1,1)
       If Border.Char=0 Then
          Strng=Chr$(201)+String$(78,205)+Chr$(187)
       Else
          Strng="+"+String$(78,"-")+"+"
       Endif
       Call Scrn(Strng)
    For Temp=2 To 24
       Call ANSI(2,Temp,1)
       If Border.Char=0 Then
          Strng=Chr$(186)
       Else
          Strng="|"
       Endif
       Call Scrn(Strng)
       Call ANSI(2,Temp,80)
       If Border.Char=0 Then
          Strng=Chr$(186)
       Else
          Strng="|"
       Endif
       Call Scrn(Strng)
    Next
    Call ANSI(2,25,1)
       If Border.Char=0 Then
          Strng=Chr$(200)+String$(78,205)
       Else
          Strng="+"+String$(78,"-")
       Endif
       Call Scrn(Strng)
       Color 11,1
       Locate 25,80,0
       If Border.Char=0 Then
          Print Chr$(188);
       Else
          Print "+";
       Endif
       Locate 1,1,1
    Endif
 Endif
 Call ANSI(2,25,6)
 Call ANSI(4,37,44)
 Strng=" Next Screen: Cursor Up/Dn "
 Call Scrn(Strng)
 Call ANSI(2,25,35)
 Strng=" Next Topic: Page Up/Dn "
 Call Scrn(Strng)
 Call ANSI(2,25,61)
 Strng=" Quit: Escape "
 Call Scrn(Strng)
 Call ANSI(4,33,44)
 Temp2=1
 Temp1=False
 Gosub Read.Data
 Locate ,,0
 Do While Lost.Carrier=False
    TempX$=Nul
    Do While TempX$=Nul
       If Lost.Carrier Then
          Exit Do
       Endif
       Call Read.Keyboard(TempX$)
       If TempX$=Chr$(21) Then ' ^U = pageup
          TempX$=Chr$(0)+Chr$(73)
       Endif
       If TempX$=Chr$(14) Then ' ^N = pagedown
          TempX$=Chr$(0)+Chr$(81)
       Endif
       Call MouseDriver(3)
       If Mouse.Button2 Then
          TempX$=Chr$(27)
       Endif
       If Mouse.Button3 Then
          Call Terminate.Program(True)
          End
       Endif
       If Mouse.Button Then
          Call HelpMouseButton
          Exit Do
       Endif
    Loop
    If TempX$=Chr$(27) Then
       Exit Sub
    Endif
    If Len(TempX$)=2 Then
       Temp8=Asc(Mid$(TempX$,2,1))
       Select Case Temp8
       Case 71, 119 ' home/ctrl-home
          If Temp1 Then
             Temp2=1
             Temp1=Temp1-1
             Gosub Read.Data
          Endif
       Case 79, 117 ' end/ctrl-end
          Temp1=Temp1+1
          Temp3=Temp2
          Temp2=1
          Gosub Read.Data
          If Temp5<Temp1 Then
             Temp1=Temp5
             Temp2=Temp3
          Endif
       Case 72, 141, 152 ' up/ctrl-up/alt-up
          If Temp2<>1 Then
             Temp2=Temp2-1
             Gosub Read.Data
          Endif
       Case 80, 145, 160 ' down/ctrl-dn/alt-dn
          Temp2=Temp2+1
          Gosub Read.Data
          Temp2=Temp4
       Case 73, 132 ' pageup/ctrl-pageup
          If Temp1 Then
             Temp2=1
             Temp1=Temp1-1
             Gosub Read.Data
          Endif
       Case 81, 118 ' pagedown/ctrl-pagedn
          Temp1=Temp1+1
          Temp3=Temp2
          Temp2=1
          Gosub Read.Data
          If Temp5<Temp1 Then
             Temp1=Temp5
             Temp2=Temp3
          Endif
       End Select
       Locate ,,0
    Endif
 Loop
 Exit Sub

Read.Data:
 Restore HelpData
 Temp5=False
 Temp8=1
 Dat1=False
 Dat2=False
 Dat3=False
 Do While Lost.Carrier=False
    Read Dat1,Dat2,Dat3,VarZ$
    If Dat1=99 And Dat2=99 And Dat3=99 Then
       Exit Do
    Endif
    VarZ$=" "+VarZ$+" "
    If Dat1>False And Dat1>Var1 Then
       Return
    Endif
    If (Dat1=Var1 Or Dat1=False) And Dat2=Temp1 Then
       Temp5=Dat2
       Temp4=1
       Temp7=False
       For Temp9=1 To Dat3
          Call Read.Helpfile(HelpFile4,Temp8+Temp9)
          Temp7=Temp7+1
          If Temp4=Temp2 Then
             Call ANSI(4,HelpRecord3.TextColor,44)
             Call ANSI(2,Temp7+1,2)
             Strng=HelpRecord3.Text
             Call Scrn(Strng)
          Endif
          If Temp4=Temp2 And Temp7=1 Then
             If Local.Mode Then
                If Border.Off=False Then
                   Call ANSI(4,36,44)
                   Call ANSI(2,1,2)
                   If Border.Char=0 Then
                      Strng=String$(78,205)
                   Else
                      Strng=String$(78,"-")
                   Endif
                   Call Scrn(Strng)
                Endif
             Endif
             Call ANSI(4,37,44)
             VarX=Int(40-Len(VarZ$)/2+1)
             Call ANSI(2,1,VarX)
             Strng=VarZ$
             Call Scrn(Strng)
          Endif
          If Temp7=22 Then
             If Temp4=Temp2 Then
                Return
             Else
                Temp4=Temp4+1
                Temp7=False
             Endif
          Endif
       Next
       If Temp7=False Then
          Temp4=Temp4-1
          Return
       Endif
       If Temp2>Temp4 Then
          Return
       Endif
       If Temp7<22 Then
          For Temp9=Temp7+1 To 22
             Call ANSI(2,Temp9+1,2)
             Strng=Space$(78)
             Call Scrn(Strng)
          Next
       Endif 
       Return
    Endif
    Temp8=Temp8+Dat3
    Temp5=Dat2
 Loop
 Return
Error.Resume53:
 Exit Sub
Error.Trap53:
 Resume Error.Resume53
End Sub

Sub HelpMouseButton
 On Local Error Goto Error.Trap54
 If Mouse.Row=25 Then
    Select Case Mouse.Column
    Case 7 To 18 ' Next Screen:
       TempX$=Chr$(0)+Chr$(80) ' down
    Case 37 To 47 ' Next Topic:
       TempX$=Chr$(0)+Chr$(81) ' pgdn
    Case 20 To 28 ' cursor up
       TempX$=Chr$(0)+Chr$(72) ' up
    Case 30, 31 ' down
       TempX$=Chr$(0)+Chr$(80)
    Case 48 To 54 ' page up
       TempX$=Chr$(0)+Chr$(73) ' pgup
    Case 56, 57 ' pgdn
       TempX$=Chr$(0)+Chr$(81)
    Case 62 To 73 ' esc
       TempX$=Chr$(27)
    End Select
 Endif
Error.Resume54:
 Exit Sub
Error.Trap54:
 Resume Error.Resume54
End Sub

HelpData:
 Data 0,0,22,"Dndedit Keys Chart"
 Data 1,1,41,"Dndedit Room Edit Keys Chart"
 Data 1,2,43,"Dndedit Room Fields"
 Data 2,1,19,"Dndedit Object Edit Keys Chart"
 Data 2,2,146,"Dndedit Object Fields"
 Data 3,1,17,"Dndedit Treasure Edit Keys Chart"
 Data 3,2,282,"Dndedit Treasure Fields"
 Data 4,1,28,"Dndedit Monster Edit Keys Chart"
 Data 4,2,216,"Dndedit Monster Fields"
 Data 5,1,19,"Dndedit Spell Edit Keys Chart"
 Data 5,2,127,"Dndedit Spell Fields"
 Data 6,1,13,"Dndedit Action Edit Keys Chart"
 Data 6,2,166,"Dndedit Action Fields"
 Data 7,1,38,"Dndedit User Edit Keys Chart"
 Data 7,2,234,"Dndedit User Fields"
 Data 8,1,17,"Dndedit Monclass Edit Keys Chart"
 Data 8,2,19,"Dndedit Monclass Fields"
 Data 9,1,20,"Dndedit Roomlink Edit Keys Chart"
 Data 9,2,9,"Dndedit Roomlink Fields"
 Data 10,1,28,"Dndedit Nonplayer Edit Keys Chart"
 Data 10,2,194,"Dndedit Nonplayer Fields"
 Data 11,1,21,"Dndedit Messbase Edit Keys Chart"
 Data 11,2,30,"Dndedit Messbase Fields"
 Data 12,1,17,"Dndedit Email Edit Keys Chart"
 Data 12,2,82,"Dndedit Email Fields"
 Data 13,1,22,"Dndedit Player Team Edit Keys Chart"
 Data 13,2,37,"Dndedit Player Team Fields"
 Data 14,1,22,"Dndedit Main Page"
 Data 99,99,99,"EOF"

Sub ErrorStatusLine
 On Local Error Goto Error.Trap52
 Strng=Nul
 Out2=Out2+" Press <esc>."
 Call StatusLine
 TempX$=Nul
 Do While TempX$<>Chr$(27)
    If Lost.Carrier Then
       Exit Do
    Endif
    Call Read.Keyboard(TempX$)
    Call MouseDriver(3)
    If Mouse.Button2 Then
       TempX$=Chr$(27)
    Endif
    If Mouse.Button3 Then
       Call Terminate.Program(True)
       End
    Endif
    If Mouse.Button Then
       Call MouseCheck
    Endif
 Loop
Error.Resume52:
 Exit Sub
Error.Trap52:
 Resume Error.Resume52
End Sub

Sub ErrorStatusLineX
 On Local Error Goto Error.Trap52X
 Strng=Out2+" Press <esc>."
 Call StatusLineX
 TempX$=Nul
 Do While TempX$<>Chr$(27)
    If Lost.Carrier Then
       Exit Do
    Endif
    Call Read.Keyboard(TempX$)
    Call MouseDriver(3)
    If Mouse.Button2 Then
       TempX$=Chr$(27)
    Endif
    If Mouse.Button3 Then
       Call Terminate.Program(True)
       End
    Endif
    If Mouse.Button Then
       Call MouseCheck
    Endif
 Loop
Error.Resume52X:
 Exit Sub
Error.Trap52X:
 Resume Error.Resume52X
End Sub

Sub StatusLineX
 On Local Error Goto Error.Trap116x
 Call ANSI(4,33,44)
 Call ANSI(2,22,5)
 VarX$=Space$(73)
 Call Scrn(VarX$)
 Call ANSI(2,22,5)
 Call Scrn(Strng)
Error.Resume116x:
 Exit Sub
Error.Trap116x:
 Resume Error.Resume116x
End Sub

Sub ClearSubstats
 On Local Error Goto Error.Trap60
 If TempD Then
    TempD=False
    Call ANSI(4,37,44)
    Call ANSI(2,6,34)
    Strng=Space$(46)
    Call Scrn(Strng)
    Call ANSI(4,33,44)
    For Var=7 To 12
       Call ANSI(2,Var,30)
       Strng=Space$(50)
       Call Scrn(Strng)
    Next
 Endif
Error.Resume60:
 Exit Sub
Error.Trap60:
 Resume Error.Resume60
End Sub

Sub Init.Arrays
 On Local Error Goto Error.Trap4a
 Redim Array.Data(1 To 40, 1 To 2) As Integer, _
 Edit.Data(1 To 19) As String, _
 Link.Data(1 To 14, 1 To 2) As Integer, _
 Title.Data(1 To 40) As String
Error.Resume4a:
 Exit Sub
Error.Trap4a:
 Resume Error.Resume4a
End Sub

Sub Init.Mouse
 On Local Error Goto Error.Trap4
 Call Mouse.Function(0,0)
 Mouse.Present=False
 If OutregsX.AX=&HFFFF Then
    Mouse.Present=True
    Call Mouse.Function2(7,0,0,632) ' set column range to 80
    M.Row=Max.Row*8-8
    Select Case Max.Row
    Case 25
       Call Mouse.Function2(8,0,0,192) ' 25 rows
    Case 41
       Call Mouse.Function2(8,0,0,336) ' 43 rows
    Case 48
       Call Mouse.Function2(8,0,0,392) ' 50 rows
    Case Else
       Call Mouse.Function2(8,0,0,192) ' 25 rows
    End Select
    Call Mouse.Function(1,0) ' show mouse
 Endif
Error.Resume4:
 Exit Sub
Error.Trap4:
 Resume Error.Resume4
End Sub

Sub Read.Config(Var)
 On Local Error Goto Error.Trap42
 Call Check.Local.ANSI
 Call Open.Arrays
 Call Get.Config(Var)
 Call Get.Environment
 Call Increase.Files
 Call Open.Files
 Call Detect.Share
Error.Resume42:
 Exit Sub
Error.Trap42:
 Resume Error.Resume42
End Sub

Sub Open.Arrays
 On Local Error Goto Array.Error
Redim Alignment.Name1(1 To 3) As String*7, _
 Alignment.Name2(1 to 3) As String*7,_
 Class.Name(1 To 10) As String*15,_
 Direction(1 To 12) As String*9,_
 High.Class.Name(1 To 10) As String*15,_
 InventoryNames(1 To 10) As String*8,_
 Numeral(1 To 10) As String*5,_
 Race(1 To 8) As String*8,_
 Room.Array(1 To 20) As String*40,_
 Stat(1 To 7) As String*12,_
 Training.Stats(1 To 10,1 To 4) As Integer,_
 Weapon.Type.Name(1 To 4) As String*9
 Exit Sub
Array.Error:
 Data.Error=Err
 ' Out of memory/Subscript out of range/Out of string space.
 If Data.Error=7 Or Data.Error=9 Or Data.Error=14 Then
    Strng="Memory error opening arrays. Free more RAM."
 Else
    Call Error.List(Data.Error)
    Strng="Error '"+Strng+"' opening arrays. Free more RAM."
 Endif
 Call Terminate.Program(False)
End Sub

Sub Get.Config(VarX)
 On Local Error Goto Config.Error
 Data.Error=False
 Close #TempFile1
 Call Get.Filename(VarX)
 Close #TempFile1
 Open FileName For Input Shared As #TempFile1
 Line Input #TempFile1,Var$
 For Temp1=1 To MaxConfigArray1
    Input #TempFile1,Var!
 Next
 For Temp1=1 To MaxConfigArray2
    Input #TempFile1,Var%
    If Temp1=48 Then
       Allow.High.Class=Var%
    Endif
    If Temp1=81 Then
       Allow.Remote.Edit=Var%
    Endif
 Next
 For Temp1=1 To MaxConfigArray3
    Line Input #TempFile1,Var$
    Select Case Temp1
    Case 11
       Data.Path1=Var$
    Case 12
       MonClass.FileName=Var$
    Case 13
       MonTalk.FileName=Var$
    Case 15
       File.Extension1=Var$
    Case 16
       Room.FileName=Var$
    Case 17
       Object.FileName=Var$
    Case 18
       Monster.FileName=Var$
    Case 19
       Treasure.FileName=Var$
    Case 20
       Spell.FileName=Var$
    Case 21
       User.FileName=Var$
    Case 22
       NonPlayer.FileName=Var$
    Case 51
       Usage.Filename=Var$
    Case 53
       Data.Path3=Var$
    Case 54
       Data.Path4=Var$
    Case 57
       Team.FileName=Var$
    Case 58
       Public.FileName=Var$
    Case 59
       Message.Base.FileName=Var$
    Case 60
       Private.FileName=Var$
    Case 68
       MessWork.FileName=Var$
    Case 71
       Action.FileName=Var$
    Case 76
       Help.FileName4=Var$
    Case 80
       Container.FileName=Var$
    Case 86
       UserInv.FileName=Var$
    Case 87
       CtnInv.FileName=Var$
    Case 88
       TeamInv.FileName=Var$
    Case 89
       RoomInv.FileName=Var$
    Case 90
       MonInv.FileName=Var$
    Case 93
       Room.Desc.FileName=Var$
    End Select
 Next
 For Temp1=1 To 10
    For Temp2=1 To 4
       Input #TempFile1,Var%
       Training.Stats(Temp1,Temp2)=Var%
    Next
 Next
 For Temp1=1 To 20
    Line Input #TempFile1,Var$
    Room.Array(Temp1)=Var$
 Next
 For Temp1=1 To 10
    Line Input #TempFile1,Var$
    High.Class.Name(Temp1)=Var$
 Next
 For Temp1=1 To 8
    Line Input #TempFile1,Var$
    Race(Temp1)=Var$
 Next
 For Temp1=1 To 10
    Line Input #TempFile1,Var$
    Class.Name(Temp1)=Var$
 Next
 For Temp1=1 To 7
    Line Input #TempFile1,Var$
    Stat(Temp1)=Var$
 Next
 For Temp1=1 To 12
    Line Input #TempFile1,Var$
    Direction(Temp1)=Var$
 Next
 For Temp1=1 To 10
    Line Input #TempFile1,Var$
    Numeral(Temp1)=Var$
 Next
 For Temp1=1 To 4
    Line Input #TempFile1,Var$
    Weapon.Type.Name(Temp1)=Var$
 Next
 For Temp1=1 To 3
    Line Input #TempFile1,Var$
    Alignment.Name1(Temp1)=Var$
 Next
 For Temp1=1 To 3
    Line Input #TempFile1,Var$
    Alignment.Name2(Temp1)=Var$
 Next
 For Temp1=1 To MaxUserCommands
    Line Input #TempFile1,Var$
    For Temp2=1 To 3
       Line Input #TempFile1,Var$
    Next
    Input #TempFile1,Var$
    For Temp2=1 To 8
       Input #TempFile1,Var
    Next
    For Temp2=1 To 4
       Input #TempFile1,Var
    Next
    Input #TempFile1,Var
    Input #TempFile1,Var
 Next
 For Temp1=1 To MaxDMcommands
    Line Input #TempFile1,Var$
    Input #TempFile1,Var
    For Temp2=1 To 3
       Input #TempFile1,Var
    Next
 Next
 For Temp1=1 To MaxSysopCommands
    Line Input #TempFile1,Var$
    Input #TempFile1,Var
 Next
 For Temp1=1 To MaxNodeCommands
    Line Input #TempFile1,Var$
    For Temp2=1 To 8
       Input #TempFile1,Var
    Next
 Next
 For Temp1=1 To MaxLetters
    Input #TempFile1,Var
 Next
 For Temp1=1 To MaxStrips
    Line Input #TempFile1,Var$
 Next
 For Temp1=1 To 10
    Line Input #TempFile1,Var$
    Input #TempFile1,Var
    Input #TempFile1,Var
 Next
 For Temp1=1 To 10
    Line Input #TempFile1,Var$
    InventoryNames(Temp1)=Var$
 Next
 Close #TempFile1
Config.Resume:
 Exit Sub
Config.Error:
 If VarX Then
    Data.Error=Err
    Out2="Error loading "+Lcase$(FileName)+"."
    Call ErrorStatusLineX
    Resume Config.Resume
 Else
    Call Error.List(Err)
    Strng="Error '"+Strng+"' reading "+Lcase$(FileName)+"."
    Call Terminate.Program(False)
 Endif
End Sub

Sub Error.List(Var2)
 On Local Error Goto Error.Trap10a
 Select Case Var2
 Case 52
    Strng="bad file name or number"
 Case 53
    Strng="file not found"
 Case 55
    Strng="file already open"
 Case 57
    Strng="device i/o error"
 Case 61
    Strng="disk full"
 Case 62
    Strng="input past eof"
 Case 64
    Strng="bad file name"
 Case 67
    Strng="not enough file handles"
 Case 68
    Strng="device unavailable"
 Case 70
    Strng="permission denied"
 Case 71
    Strng="disk not ready"
 Case 75
    Strng="path/file access error"
 CASE 76
    Strng="pathname not found"
 Case Else
    Strng=Ltrim$(Str$(Var2))
 End Select
Error.Resume10a:
 Exit Sub
Error.Trap10a:
 Resume Error.Resume10a
End Sub

Sub Get.Filename(VarX)
 On Local Error Goto Filename.Error
 DND.Path=Environ$("DNDBBS")
 If DND.Path<>Nul Then
    If Right$(DND.Path,1)<>"\" Then
       DND.Path=DND.Path+"\"
    Endif
 Endif
 If VarX=False Then
    Var$=Command$
 Endif
 If VarX Then
    Strng="^ Cursor Edit "+Chr$(60)+Chr$(217)+" Exit Field  "
    Call StatusLineX
    Call ANSI(4,33,44)
    Call ANSI(2,23,5)
    VarX$=Space$(73)
    Call Scrn(VarX$)
    Call ANSI(2,23,5)
    Strng="Enter Node Number(<enter>,0-9,A-Z,10-99): "
    Call Scrn(Strng)
    Call ANSI(4,37,40)
    Call ANSI(2,23,47)
    Strng=Space$(2)
    Call Scrn(Strng)
    Xcoor=23
    Ycoor=47
    Column=47
    Line.Length=2
    Max.Lines=1
    Row=23
    Line.Number=1
    Edit.Data(1)=Nul
    Call ScreenEdit
    If Inserting=-2 Then ' escape
       Out2="Error, node must be <enter>,0-9,A-Z,10-99."
       Call ErrorStatusLineX
       Exit Sub
    Endif
    Var$=Edit.Data(1)
 Endif
 Var$=Ucase$(Var$)
 Select Case Len(Var$)
 Case 0
    FileName=DND.Path+"DND.CFG"
 Case 1
    Select Case Ucase$(Var$)
    Case "0" To "9"
       FileName=DND.Path+"DND"+Var$+".CFG"
    Case "A" To "Z"
       FileName=DND.Path+"DND"+Var$+".CFG"
    Case Else
       If VarX=False Then
          Strng="Error reading command line."
          Call Terminate.Program(False)
       Else
          Out2="Error, node must be <enter>,0-9,A-Z,10-99."
          Call ErrorStatusLineX
       Endif
       FileName=DND.Path+"DND.CFG"
    End Select
 Case 2
    VarZ=Int(Val(Var$)+.5)
    If VarZ>=10 And VarZ<=99 Then
       FileName=DND.Path+"DND"+Mid$(Str$(VarZ),2)+".CFG"
    Else
       If VarX=False Then
          Strng="Error reading command line."
          Call Terminate.Program(False)
       Else
          Out2="Error, node must be <enter>,0-9,A-Z,10-99."
          Call ErrorStatusLineX
          FileName=DND.Path+"DND.CFG"
       Endif
    Endif
 Case Else
    Strng="Error reading command line."
    Call Terminate.Program(False)
 End Select
 Temp.Command=Filename
Filename.Resume:
 Exit Sub
Filename.Error:
 Resume Filename.Resume
End Sub

Sub Get.Environment
 On Local Error Goto Error.Trap44
 Out2=Environ$("DNDDAT")
 If Out2<>Nul Then
    If Right$(Out2,1)<>"\" Then
       Out2=Out2+"\"
    Endif
    Data.Path1=Out2
 Endif
 Out2=Environ$("DNDTEMP")
 If Out2<>Nul Then
    If Right$(Out2,1)<>"\" Then
       Out2=Out2+"\"
    Endif
    Data.Path2=Out2
 Endif
 Out2=Environ$("DNDMESS")
 If Out2<>Nul Then
    If Right$(Out2,1)<>"\" Then
       Out2=Out2+"\"
    Endif
    Data.Path3=Out2
 Endif
Error.Resume44:
 Exit Sub
Error.Trap44:
 Resume Error.Resume44
End Sub

Sub Increase.Files
 On Local Error Goto Error.Trap45
 Close
 Call StdinInt(62,0)
 PSP.Segment=OutregsX.BX
 Def Seg=PSP.Segment
 Command.Line=&H80
 Command.Tail=Command.Line+60
 For Var=1 To 54
    Poke Command.Tail+Var-1,&HFF
 Next
 For Var=1 To 4
    File.Handle=Peek(&H18+Var-1)
    Poke Command.Tail+Var-1,File.Handle
 Next
 Poke &H32,54
 Poke &H34,Command.Tail
 Def Seg
 Close
Error.Resume45:
 Exit Sub
Error.Trap45:
 Resume Error.Resume45
End Sub

Sub Decrease.PSP
 On Local Error Goto Error.Trap3
 Close
 Call StdinInt(62,0)
 PSP.Segment=OutregsX.BX
 Def Seg=PSP.Segment
 Poke &H32,20
 Poke &H34,&H18
 Def Seg
 Close
Error.Resume3:
 Exit Sub
Error.Trap3:
 Resume Error.Resume3
End Sub

Sub Open.Files
 On Local Error Goto Open.Error
 HelpRecLen4=Len(HelpRecord3)
 Help.FileName4=Data.Path1+Help.FileName4+File.Extension1

 UserRecLen=Len(UserRecord)
 FileName2$=Data.Path1+User.FileName+File.Extension1
 Open FileName2$ For Random Shared As #UserFile Len=UserRecLen
 Open FileName2$ For Random Shared As #UserFile2 Len=UserRecLen
 NonPlayerRecLen=Len(MonsterRecord)
 FileName2$=Data.Path1+NonPlayer.FileName+File.Extension1
 Open FileName2$ For Random Shared As #NonPlayerFile Len=NonPlayerRecLen
 RoomRecLen=Len(RoomRecord)
 FileName2$=Data.Path1+Room.FileName+File.Extension1
 Open FileName2$ For Random Shared As #RoomFile Len=RoomRecLen
 ObjectRecLen=Len(ObjectRecord)
 FileName2$=Data.Path1+Object.FileName+File.Extension1
 Open FileName2$ For Random Shared As #ObjectFile Len=ObjectRecLen
 MonsterRecLen=Len(MonsterRecord)
 FileName2$=Data.Path1+Monster.FileName+File.Extension1
 Open FileName2$ For Random Shared As #MonsterFile Len=MonsterRecLen
 TreasureRecLen=Len(TreasureRecord)
 FileName2$=Data.Path1+Treasure.FileName+File.Extension1
 Open FileName2$ For Random Shared As #TreasureFile Len=TreasureRecLen
 MonClassRecLen=Len(MonClassRecord)
 FileName2$=Data.Path1+MonClass.FileName+File.Extension1
 Open FileName2$ For Random Shared As #MonClassFile Len=MonClassRecLen
 SpellRecLen=Len(SpellRecord)
 FileName2$=Data.Path1+Spell.FileName+File.Extension1
 Open FileName2$ For Random Shared As #SpellFile Len=SpellRecLen
 ActionRecLen=Len(ActionRecord)
 FileName2$=Data.Path1+Action.FileName+File.Extension1
 Open FileName2$ For Random Shared As #ActionFile Len=ActionRecLen
 ContainerRecLen=Len(ContainerRecord)
 FileName2$=Data.Path1+Container.FileName+File.Extension1
 Open FileName2$ For Random Shared As #ContainerFile Len=ContainerRecLen
 TeamRecLen=Len(TeamRecord)
 FileName2$=Data.Path1+Team.FileName+File.Extension1
 Open FileName2$ For Random Shared As #TeamFile Len=TeamRecLen
 RoomDescLen=Len(BufferRecord)
 FileName2$=Data.Path1+Room.Desc.FileName+File.Extension1
 Open FileName2$ For Random Shared As #RoomDescFile Len=RoomDescLen
 MessBaseRecLen=Len(MessageBaseRecord)
 FileName2$=Data.Path4+Message.Base.FileName+File.Extension1
 Open FileName2$ For Random Shared As #MessBaseFile Len=MessBaseRecLen
 MessWorkRecLen1=Len(MessWorkRecord1)
 FileName2$=Data.Path3+MessWork.FileName+"1"+File.Extension1
 Open FileName2$ For Random Shared As #MessWorkFile1 Len=MessWorkRecLen1
 MessWorkRecLen6=Len(MessWorkRecord6)
 FileName2$=Data.Path1+TeamInv.FileName+File.Extension1
 Open FileName2$ For Random Shared As #TeamInvFile Len=MessWorkRecLen6
 FileName2$=Data.Path1+UserInv.FileName+File.Extension1
 Open FileName2$ For Random Shared As #UserInvFile Len=MessWorkRecLen6
 FileName2$=Data.Path1+CtnInv.FileName+File.Extension1
 Open FileName2$ For Random Shared As #CtnInvFile Len=MessWorkRecLen6
 FileName2$=Data.Path1+RoomInv.FileName+File.Extension1
 Open FileName2$ For Random Shared As #RoomInvFile Len=MessWorkRecLen6
 FileName2$=Data.Path1+MonInv.FileName+File.Extension1
 Open FileName2$ For Random Shared As #MonInvFile Len=MessWorkRecLen6
 FileName2$=Data.Path3+MessWork.FileName+"6"+File.Extension1
 Open FileName2$ For Random Shared As #MessWorkFile6 Len=MessWorkRecLen6
 MessWorkRecLen7=Len(MessWorkRecord7)
 FileName2$=Data.Path3+MessWork.FileName+"7"+File.Extension1
 Open FileName2$ For Random Shared As #MessWorkFile7 Len=MessWorkRecLen7
 Exit Sub
Open.Error:
 Data.Error=Err
 Call Error.List(Data.Error)
 Strng="Error '"+Strng+"' reading "+Lcase$(FileName2$)+"."
 If Data.Error=67 Then
    Strng2="Increase files= in config.sys or config.nt."
    Call Terminate.Program(1)
 Else
    Call Terminate.Program(0)
 Endif
End Sub

