'File Manager v0.2052 for PicoMiteVGA by JAVAVI (c)2025
'For start FM from flash memory enter this instructions
'> FLASH SAVE 2
'> Option F9 "FLASH RUN 2"+Chr$(13)
'
' This trial version uses sorted file lists.
' - Sort for name, date and size.
' - DeleteDir included
' - CopyDir   included
' - ListHex   included
' - TxtView   included improved (02032)
' - Merge     included
' - New InputE$() included (+ blinking cursor)
' - Rename + Mkdir revised
' - GetFList revised to speed up
' - Multiselect included
' - Show number and size of selected files
' - Shift-F-Keys (F9,F10) are new
' - F12 = EXIT FM!
' - jmp2Letter moves he file cursor to the corresponding letter
' - (passive) ScrollBars
' - Alt/(BS) F-Keys reenabled
' - overLoad ">" indicator, when more than RMax files in file list
' - PSIDE$="L" deleted
' - Scroll bars included
' Use at your own risk. Pls report errors.
'***************************************************
Option default integer
Option base 0
MODE 1: Font 1: TILE Height 12: Color RGB(WHITE),RGB(BLACK)

Const TRUE=1,FALSE=Not TRUE
Const _ON =TRUE,_OFF=FALSE
Const FW=MM.Info(FONTWIDTH), FH=MM.Info(FONTHEIGHT)
Const CHR=MM.HRES\FW, CVR=MM.VRES\FH
'* User config:
Const SStimeout=300000 'Screen saver timeout
Const RMax=200 'Max files in a folder to read
Const Diskinfo_Path$  ="B:/di.bas" 'Path to diskinfo
Const Snippet_Path$   ="B:/snippet.cut"'a snippet can be any text/.bas file
Const MergedText_Path$="B:/merged.txt" 'result of merge
Const CLEAR_KBBUFFER=TRUE
'multi select keys (german kb) Suggestion: us =[,],',/
Const SKey=Asc("+")  , d_SKey=Asc("-")'select, deselect
Const i_SKey=Asc("#"), s_SKey=Asc("<")'invert selection, sort selection
Const SClr=12        'MapColor = c() for selected files
'***************
Const DV$=MM.Info(device)

Dim string VERSION$="0.2052" LENGTH 7
Dim integer PS=1'PanelSide L=1,R=0
Dim string  BSort$(1)=("Name>","Name>") LENGTH 5
Dim string  BDisk$(1)=("A:","A:")    LENGTH 3 'Left(panel)=1,R=0
Dim string  BDir$(1)=("/","/")    'L=1,R=0

Dim string  LFList$(RMax)  LENGTH 64
Dim string  RFList$(RMax)  LENGTH 64
Dim string  LFSlct$(RMax)  LENGTH 1
Dim string  RFSlct$(RMax)  LENGTH 1
Dim string  overLoad$(1)   LENGTH 1=("","")' files > RMax
Dim integer BSel(1)        'Number of selected files
Dim integer LSindex(RMax)  'sort index left
Dim integer RSindex(RMax)  'sort index right
Dim integer LFLIndx,RFLIndx'
Dim integer LFLS(2),RFLS(2)'File List Struct (RQ,DQ,FQ)
Dim integer LPPos,RPPos,LFLTop,RFLTop,BSSize(1)
Dim integer PgS=33
Dim integer ROffs(1)=(40,0),oldPg(1)=(-1,-1)
Dim integer CKey,Tick1s,inf9_f(1)=(FALSE,FALSE)
Dim integer FC=MM.Info(FCOLOUR), BC=MM.Info(BCOLOUR)
Dim integer c(15)=(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
Colour Map c(),c()
MENU_ITEMS:
Data "01> MEMORY"
Data "02> FLASH LIST"
Data "03> OPTION LIST"
Data "04> LIST PINS"'v60002!
Data "05> COLORTABLE"
Data "06> ASCIITABLE"
Data "07> Print Time$"
Data "08> Print Date$"
Data "09> Print VERSION$"
Data "10> Print MM.INFO(HEAP)"
Data "11> Freespace"
Data ""
'============================
BEGIN:
Timer =0
SetTick 1000,ISR_Tick1s,1
On ERROR SKIP 1
If MM.Info(SDCARD)="Ready" Then BDisk$(0)="B:"
On ERROR CLEAR
PanelsReStart()
'----------------------
F9_CHARS:
Restore F9_CHARS 'keys enabled in F9 menu
Data 9,13,27,128,129,130,131,134,135,136,137,145,156,0
Read tmp
Do While tmp
  Inc F9char$,Chr$(tmp)
  Read tmp
Loop

Do 'main
  If CLEAR_KBBUFFER Then
    Do :Loop Until Inkey$=""
  EndIf
  Do :CKey=Asc(Inkey$)
    If Tick1s Then PrintTime()
  Loop Until (CKey>0 And Not inf9_f(PS)) Or Instr(F9char$,Chr$(CKey)) Or Timer>SStimeout

Select Case CKey
Case 48 To 57,97 To 122'#++
  jmp2Letter CKey
Case 9    'Tab
  SetPControl("TAB")
Case 13   'Enter
  EnterControl()
Case 32   'Space
  SelectControl()
  SetPControl("DWN")
Case 27   'Escape
  PanelsReStart()
Case 42   'PrintScr *
'  Save image "PrScr"
Case SKey,d_SKey,i_SKey'
  SetPControl("DIS")
  MSelect(Chr$(CKey))
  RewritePPanel()
Case s_SKey   '"<"
  If PS Then
    sortSelectFls(LFList$(),LFSlct$(),LSindex(),LFLS())
  Else
    sortSelectFls(RFList$(),RFSlct$(),RSindex(),RFLS())
  EndIf
  BSort$(PS)="Name>"
  RewritePPanel()
Case 4,14,19'CTRL "d"+"n","s"
  chngSort CKey
  ReShowPPanel()
Case 127  'del
  WDisk()
  ReShowPPanel()
Case 128  'Up
  SetPControl("UP")
Case 129  'Dn
  SetPControl("DWN")
Case 130  'Left
  SetPControl("PREV")
Case 131  'Right
  SetPControl("NEXT")
Case 132  'Insert = goto root
  SetPControl("ROOT")
  ReShowPPanel()
Case 134  'Home
  SetPControl("TOP")
Case 135  'End
  SetPControl("BOT")
Case 136  'PgUp
  SetPControl("PREV")
Case 137  'PgDn
  SetPControl("NEXT")
Case 139,8'Alt or BS
  SetAltPControl()
Case 145  'F1-Help
  SetPControl("DIS")
  PrintHelp()
  PanelsReStore()
Case 146  'F2-ReName
  SetPControl("DIS")
  W_F2_ReNAME()
  PanelsReStart()
Case 147  'F3-List
  On ERROR IGNORE
  TxtView(GetCurrFullName$(PS))
  On ERROR CLEAR
  PanelsReStart()
Case 148  'F4-Edit
  W_F4_Edit()
  PanelsReStart()
Case 149  'F5-Copy
  SetPControl("DIS")
  If BSel(PS)>0 Then
    W_F5_MSCopy()
  Else
    W_F5_Copy()
  EndIf
  PanelsReStart()
Case 150  'F6-Move
  SetPControl("DIS")
  W_F6_Move()
  PanelsReStart()
Case 151  'F7-MkDir
  SetPControl("DIS")
  W_F7_MkDIR()
  PanelsReStart()
Case 152  'F8-Delete
  SetPControl("DIS")
  If BSel(PS)>0 Then
    W_F8_MS_DELETE()
  Else
    W_F8_DELETE()
  EndIf
  PanelsReStart()
Case 153  'F9-Menu
  W_F9_MENU()
Case 154  'F10-Diskinfo, (set cursor on a Dir to execute)
  On error ignore
  If Diskinfo_Path$<>"" And MM.Info(exists FILE Diskinfo_Path$) Then
    If MM.Info(EXISTS DIR GetCurrFullName$(PS)) Then
      End "run"+Chr$(34)+Diskinfo_Path$+Chr$(34)+","+Chr$(34)+GetCurrFullName$(PS)+Chr$(34)
    EndIf
  Else
    Error "Diskinfo: "+Diskinfo_Path$+" not found!"
  EndIf
  W_ERROR_MSG()
Case 156  'F12-QUIT
  CLS :End
Case 27,158  'Pause
  Play Stop
Case 179  'Shift F3-ListHEX
  ListHex GetCurrFullName$(PS)
  PanelsReStore()
Case 180  'Shift F4 R.Sort
  BSort$(PS)=SortSwitch$(BSort$(PS))
  ReShowPPanel()
Case 184  'Shift F8-Cutter
  SetPControl("DIS")
  W_altF8_Cutter(GetCurrFullName$(PS))
  PanelsReStart()
Case 185  'Shift F9-Merge
  SetPControl("DIS")
  W_altF9_Merge(GetCurrFullName$(PS))
  PanelsReStart()
Case Else
End Select
'----------------------
If Tick1s Then PrintTime()
If Timer>SStimeout Then SSMatrix()
Timer =0
Loop '******* Main loop **************


Sub jmp2Letter CKey'#j
Local integer i=0,Found=FALSE
If BSort$(PS)<>"Name>" Then BSort$(PS)="Name>":ReShowPPanel()
If PS Then
  For i= LFLS(1)+1 To LFLS(0)
    If Chr$(CKey)=LCase$(Left$(LFList$(LSindex(i)),1)) Then
      Found=TRUE
      Exit For
    EndIf
  Next
  If Not found Then'try to find the next bigger char
    Do While CKey<123
      Inc CKey
      For i= LFLS(1)+1 To LFLS(0)
        If Chr$(CKey)=LCase$(Left$(LFList$(LSindex(i)),1)) Then
          Found=TRUE
          Exit Do
        EndIf
      Next
    Loop
  EndIf
  If Found Then
    LFLIndx=i
    If i< LFLTop Then
      LFLTop=i
      LPPos=0
    ElseIf i>LFLTop+PgS Then
      If LFLS(2)>=PgS Then
        LFLTop=i-PgS+1:LPPos=PgS-1
      Else
        LFLTop=i-LFLS(2):LPPos=LFLS(2)
      EndIf
    Else
      LPPos=i-LFLTop
    EndIf
    FLPrint(LFList$(),LFLTop,1,1,38,PgS,1)
  EndIf
Else
  For i=RFLS(1)+1 To RFLS(0)
    If CKey = Asc(LCase$(Left$(RFList$(RSindex(i)),1))) Then
      Found=TRUE
      Exit For
    EndIf
  Next
  If Not found Then
    Do While CKey<123
      Inc CKey
      For i= RFLS(1)+1 To RFLS(0)
        If Chr$(CKey)=LCase$(Left$(RFList$(RSindex(i)),1)) Then
          Found=TRUE
          Exit Do
        EndIf
      Next
    Loop
  EndIf
  If Found Then
    RFLIndx=i
    If i< RFLTop Then
      RFLTop=i
      RPPos=0
    ElseIf i>RFLTop+PgS Then
      If RFLS(2)>=PgS Then
        RFLTop=i-PgS+1:RPPos=PgS-1
      Else
        RFLTop=i-RFLS(2):RPPos=RFLS(2)
      EndIf
    Else
      RPPos=i-RFLTop
    EndIf
    FLPrint(RFList$(),RFLTop,41,1,38,PgS,0)
  EndIf
EndIf
SetPControl("ENA")
End Sub

Sub chngSort CKey
  Select Case CKey
  Case 19's
    BSort$(PS)="Size>"
  Case 4 'd
    BSort$(PS)="Date<"
  Case 14'n
    BSort$(PS)="Name>"
  End Select
End Sub


'* Multi select ##m
Sub MSelect(Modus$)'Modus$=*+-
Local BFLS(2),side=(PS)'(s=1) = L
Local PATT$,SMode$(1)
Local float regexSize=0
BFLS(0)=Choice(Side,LFLS(0),RFLS(0))'RQt
BFLS(1)=Choice(Side,LFLS(1),RFLS(1))'DQt
If Modus$ = "#" Then
  For i = BFLS(1)+1 To BFLS(0)
    If Side Then
      oLFSlct$=LFSlct$(LSindex(i))
      LFSlct$(LSindex(i))=Choice(LFSlct$(LSindex(i))="1","","1")
      If oLFSlct$<>LFSlct$(LSindex(i)) Then
        Inc BSel(PS),Choice(LFSlct$(LSindex(i))="1",1,-1)
      EndIf
    Else
      oRFSlct$=RFSlct$(RSindex(i))
      RFSlct$(RSindex(i))=Choice(RFSlct$(RSindex(i))="1","","1")
      If oRFSlct$<>RFSlct$(RSindex(i)) Then
        Inc BSel(PS),Choice(RFSlct$(RSindex(i))="1",1,-1)
      EndIf
    EndIf
  Next
Else
Color FC,c(1)
SMode$(0)="Deselect"
SMode$(1)="Select"
OpenWindow(SMode$(Modus$="+")+" files: on drive "+BDisk$(side),2+ROffs(side),14,35,4)
Color FC,BC
Print @(4*FW+ROffs(side)*FW,16*FH);Space$(32)
Print @(4*FW+ROffs(side)*FW,16*FH);
ml=31
PATT$=InputE$("*.*",ml)
If ml =-1 Then Exit Sub
PATT$=DOS2Regex$(PATT$)
For i = BFLS(1)+1 To BFLS(0)
  On error skip
  If Side Then 'L
    If Instr(LCase$(LFList$(LSindex(i))),PATT$,regexSize) > 0 Then
      oLFSlct$=LFSlct$(LSindex(i))
      LFSlct$(LSindex(i))=Choice((Modus$="+"),"1","")
      If oLFSlct$<>LFSlct$(LSindex(i)) Then
        Inc BSel(PS),Choice(LFSlct$(LSindex(i))="1",1,-1)
      EndIf
    EndIf
   Else
    If Instr(LCase$(RFList$(RSindex(i))),PATT$,regexSize) > 0 Then
      oRFSlct$=RFSlct$(RSindex(i))
      RFSlct$(RSindex(i))=Choice((Modus$="+"),"1","")
      If oRFSlct$<>RFSlct$(RSindex(i)) Then
        Inc BSel(PS),Choice(RFSlct$(RSindex(i))="1",1,-1)
      EndIf
    EndIf
  EndIf
Next
W_ERROR_MSG()
EndIf
End Sub

Function DOS2Regex$(dosPattern$)
Local i, ch$, regex$= ""
For i = 1 To Len(dosPattern$)
  ch$ = Mid$(dosPattern$,i,1)
  Select Case ch$
    Case "*"
      Inc regex$, ".*"
    Case "?"
      Inc regex$, "."
    Case Else
      If Instr(".^$+(){}|\",ch$) Then '[]\
        Inc regex$, "\" + ch$
      Else
        Inc regex$, ch$
      End If
  End Select
Next
DOS2Regex$ = "^"+regex$+"$"
End Function

Sub SelectControl()'select one file ##a
If PS Then
 If Not(isDir(LFList$(LSindex(LFLIndx)))) Then
   LFSlct$(LSindex(LFLIndx))=Choice(LFSlct$(LSindex(LFLIndx))="1","","1")
   If LFSlct$(LSindex(LFLIndx))="1" Then
     TILE 1,1+LPPos,c(SClr),FC,38,1
     Inc BSSize(PS), MM.Info(filesize LFList$(LSindex(LFLIndx)))
     Inc BSel(PS)
   Else
     TILE 1,1+LPPos,c(0),FC,38,1
     Inc BSSize(PS), -MM.Info(filesize LFList$(LSindex(LFLIndx)))
     Inc BSel(PS),-1
   EndIf
 EndIf
Else
 If Not(isDir(RFList$(RSindex(RFLIndx)))) Then
   RFSlct$(RSindex(RFLIndx))=Choice(RFSlct$(RSindex(RFLIndx))="1","","1")
   If RFSlct$(RSindex(RFLIndx))="1" Then
     TILE 41,1+RPPos,c(SClr),FC,38,1
     Inc BSSize(PS), MM.Info(filesize RFList$(RSindex(RFLIndx)))
     Inc BSel(PS)
   Else
     TILE 41,1+RPPos,c(0),FC,38,1
     Inc BSSize(PS),-MM.Info(filesize RFList$(RSindex(RFLIndx)))
     Inc BSel(PS),-1
   EndIf
 EndIf
EndIf
showSel(FALSE)
End Sub

Sub CalcFSizes
Local i
  BSSize(PS)=0
  BSel(PS)=0
  If PS Then
    For i = LFLS(1)+1 To LFLS(0)
      If LFSlct$(LSindex(i)) ="1" Then
        Inc BSSize(PS), MM.Info(filesize LFList$(LSindex(i)))
        Inc BSel(PS)
      EndIf
    Next
  Else
    For i = RFLS(1)+1 To RFLS(0)
      If RFSlct$(RSindex(i)) ="1" Then
        Inc BSSize(PS), MM.Info(filesize RFList$(RSindex(i)))
        Inc BSel(PS)
      EndIf
    Next
  EndIf
End Sub

Sub showSel(ReCalc)
Local rl,ll
  If ReCalc Then CalcFSizes()
  ll=Len(Str$(BSel(1)))+Len(Str$(BSSize(1)))
  rl=Len(Str$(BSel(0)))+Len(Str$(BSSize(0)))
  Print @(72+ROffs(1)*FW,34*FH)Chr$(180);
  Print " Selected:" BSel(1);"/";BSSize(1) " ";Chr$(195)String$(12-ll,Chr$(196));
  Print @(72+ROffs(0)*FW,34*FH)Chr$(180);
  Print " Selected:" BSel(0);"/";BSSize(0) " ";Chr$(195)String$(12-rl,Chr$(196));
End Sub

Function isDir(FName$)
  isDir=Left$(FName$,1)="/" Xor Left$(FName$,2)=".."
End Function

'ENTER KEY CONTROL ==========
Sub EnterControl()
Local string TEMP$
If PS Then
 TEMP$=LFList$(LSindex(LFLIndx))
Else
 TEMP$=RFList$(RSindex(RFLIndx))
EndIf
'Action with files
If Instr(LCase$(TEMP$),".bas") Then CLS :Run TEMP$
If Instr(LCase$(TEMP$),".bmp") Then
  If Instr(1,DV$,"2350") Then
    If Instr(1,DV$,"VGA") Or Instr(1,DV$,"HDMI") Then MODE 3
  EndIf
  CLS : Load image TEMP$
  mywait
  MODE 1
  CLS
  PanelsReStart()
  Exit Sub
EndIf
If Instr(LCase$(TEMP$),".mod") Then
  Play modfile TEMP$
  mywait
  Play Stop
  Exit Sub
EndIf
If Instr(LCase$(TEMP$),".mp3") Then
  On ERROR ignore
  Play mp3 TEMP$
  W_ERROR_MSG()
  mywait
  Play Stop
  Exit Sub
EndIf
'Execute Commands from MENU
If Mid$(TEMP$,3,2)="> " Then
  TEMP$=Mid$(TEMP$,5)
  CLS
  If TEMP$ = "Freespace" Then
    freespace()
  Else
    Execute TEMP$
  EndIf
  mywait
  inf9_f(0)=0:inf9_f(1)=0
  PanelsReStart()
  Exit Sub
EndIf 'Programm from MENU
If Mid$(TEMP$,1,2)="* " Then
  CLS
  Run TEMP$=Mid$(TEMP$,3,Len(TEMP$)-2)
EndIf
'Change Directory
PS=PS=1'
oldPg(PS)=-1
If isDir(TEMP$) Then
  BSel(PS)=0
  If PS Then
    Erase LFSlct$():Dim LFSlct$(RMax) LENGTH 1
  Else
    Erase RFSlct$():Dim RFSlct$(RMax) LENGTH 1
  EndIf
  If Left$(TEMP$,2)=".." Then
    inf9_f(PS)=FALSE
    Chdir ".."
  Else
    Chdir Mid$(TEMP$,2,63)
  EndIf
EndIf
TEMP$=Mid$(Cwd$,3,Len(Cwd$)-2)
If Len(TEMP$)>1 Then TEMP$=TEMP$+"/"
BDir$(PS)=TEMP$
If PS Then
  LPanelShow()
Else
  RPanelShow()
EndIf
SetPControl("ENA")
End Sub
'================================
Sub SetPControl(CTRL$)
Local STRING COM$
If PS Then
'---- Left Panel Control --------##b
Select Case CTRL$
Case "TAB"
  SetPControl("DIS")
  PS=0
  SetPControl("ENA")
Case "UP"
  If LFLIndx>0 Then
    fileCursor FALSE
    Inc LFLIndx,-1
    If LPPos>0 Then
      Inc LPPos,-1
    Else
      If LFLTop>0 Then Inc LFLTop,-1
      FLPrint(LFList$(),LFLTop,1,1,38,PgS,1)
    EndIf
    fileCursor TRUE
  EndIf
Case "DWN"
  If LFLIndx<LFLS(0) Then
    fileCursor FALSE
    Inc LFLIndx
    If LPPos<(PgS-1) Then
      Inc LPPos
    Else
      Inc LFLTop
      FLPrint(LFList$(),LFLTop,1,1,38,PgS,1)
    EndIf
    fileCursor TRUE
  EndIf
Case "TOP"
  LFLIndx=0:LFLTop=0:LPPos=0
  FLPrint(LFList$(),LFLTop,1,1,38,PgS,1)
  fileCursor TRUE
Case "BOT"
  LFLIndx=LFLS(0)
  If LFLS(0)>PgS Then
    LPPos=PgS-1:LFLTop=LFLS(0)-(PgS-1)
  Else
    LPPos=LFLS(0)-LFLTop
  EndIf
  FLPrint(LFList$(),LFLTop,1,1,38,PgS,1)
  fileCursor TRUE
Case "PREV"
  fileCursor FALSE
  Inc LFLIndx,-PgS
  LFLTop = LFLIndx -PgS +1
  If LFLTop < 0 Then LFLTop =0
  If LFLTop = 0 Then LFLIndx=0
  LPPos = LFLIndx -LFLTop
  FLPrint(LFList$(),LFLTop,1,1,38,PgS,1)
  fileCursor TRUE
Case "NEXT"
  Inc LFLIndx,PgS
  If LFLIndx>LFLS(0)-1 Then LFLIndx=LFLS(0)
  LFLTop=LFLIndx
  If LFLTop +PgS>LFLS(0) Then LFLTop=LFLS(0)-(PgS-1)': LFLIndx = LFLS(0)
  If LFLTop<0 Then LFLTop=0
  LPPos = LFLIndx -LFLTop
  FLPrint(LFList$(),LFLTop,1,1,38,PgS,1)
  fileCursor TRUE
Case "ROOT"
  BDir$(PS)="/":Chdir BDisk$(PS)+"/"
End Select

If oldPg(1) <>Int((LFLIndx)\PgS) Then
  oldPg(1)=Int((LFLIndx)\PgS)
  ScrollBar(LFLS(0), oldPg(1),1)
EndIf

'---- Right Panel Control -------
Else
Select Case CTRL$
Case "TAB"
  SetPControl("DIS")
  PS=1
  SetPControl("ENA")
Case "UP"
  fileCursor FALSE
  If RFLIndx>0 Then
    Inc RFLIndx,-1
    If RPPos>0 Then
      Inc RPPos,-1
    Else
      If RFLTop>0 Then Inc RFLTop,-1
      FLPrint(RFList$(),RFLTop,41,1,38,PgS,0)
    EndIf
  EndIf
  fileCursor TRUE
Case "DWN"
  fileCursor FALSE
  If RFLIndx<RFLS(0) Then
    Inc RFLIndx
    If RPPos<(PgS-1) Then
      Inc RPPos
    Else
      Inc RFLTop
      FLPrint(RFList$(),RFLTop,41,1,38,PgS,0)
    EndIf
  End If
  fileCursor TRUE
Case "TOP"
  RFLIndx=0:RFLTop=0:RPPos=0
  FLPrint(RFList$(),RFLTop,41,1,38,PgS,0)
  fileCursor TRUE
Case "BOT"
  RFLIndx=RFLS(0)
  If RFLS(0)>PgS Then
    RPPos=PgS-1:RFLTop=RFLS(0)-(PgS-1)
  Else
    RPPos=RFLS(0)-RFLTop
  EndIf
  FLPrint(RFList$(),RFLTop,41,1,38,PgS,0)
  fileCursor TRUE
Case "PREV"
  Inc RFLIndx,-PgS
  RFLTop = RFLIndx -PgS +1
  If RFLTop < 0 Then RFLTop =0
  If RFLTop = 0 Then RFLIndx=0
  RPPos = RFLIndx -RFLTop
  FLPrint(RFList$(),RFLTop,41,1,38,PgS,0)
  fileCursor TRUE
Case "NEXT"
  Inc RFLIndx,PgS
  If RFLIndx>RFLS(0)-1 Then RFLIndx=RFLS(0)
  RFLTop=RFLIndx
  If RFLTop +PgS>RFLS(0) Then RFLTop=RFLS(0)-(PgS-1)': RFLIndx = RFLS(0)
  If RFLTop<0 Then RFLTop=0
  RPPos = RFLIndx -RFLTop
  FLPrint(RFList$(),RFLTop,41,1,38,PgS,0)
  fileCursor TRUE
Case "ROOT"
  BDir$(PS)="/":Chdir BDISK$(PS)+"/"
End Select
  If oldPg(0) <>Int((RFLIndx)\PgS) Then
    oldPg(0)=Int((RFLIndx)\PgS)
    ScrollBar(RFLS(0), oldPg(0),0)
  EndIf
EndIf
'---- Common Actions --------
Select Case CTRL$ '##ena
Case "DIS"
  fileCursor FALSE
Case "ENA"
  Drive BDisk$(PS)
  Chdir BDir$(PS)
  oldPg(PS)=-1
  fileCursor TRUE
  ScrollBar(LFLS(0), Int((LFLIndx)\PgS),1)
  ScrollBar(RFLS(0), Int((RFLIndx)\PgS),0)
End Select
'Print Command Line ---------
COM$=BDisk$(PS)+BDir$(PS)+">"
Print @(0,FH*38);COM$+Space$(80-Len(COM$))
'Print Panels Info ----------#4
If PS Then
  COM$=LFList$(LSindex(LFLIndx))
  If Len(COM$)<39 Then
    COM$=Mid$(COM$,1,38)
    COM$=COM$+Space$(38-Len(COM$))
  Else
    COM$=Mid$(COM$,1,37)+"}"
  EndIf
  Print @(FW,35*FH);COM$;
  Print @(FW,36*FH);Space$(38);
  COM$=LFList$(LSindex(LFLIndx))
  Print @(FW,36*FH);
  If COM$=".." Or Left$(COM$,1)="/" Then
    Print "<DIR>"
  Else
    Print "Size:";MM.Info(FILESIZE COM$)
  EndIf
  Print @(20*FW,36*FH);MM.Info(MODIFIED COM$)
Else
  COM$=RFList$(RSindex(RFLIndx))
  If Len(COM$)<39 Then
    COM$=Mid$(COM$,1,38)
    COM$=COM$+Space$(38-Len(COM$))
  Else
    COM$=Mid$(COM$,1,37)+"}"
  EndIf
  Print @((ROffs(0)+1)*FW,35*FH);COM$;
  COM$=RFList$(RSindex(RFLIndx))
  Print @((ROffs(0)+1)*FW,36*FH);Space$(38)
  Print @((ROffs(0)+1)*FW,36*FH);
  If COM$=".." Or Left$(COM$,1)="/" Then
    Print "<DIR>"
  Else
    Print "Size:";MM.Info(FILESIZE COM$)
  EndIf
  Print @((ROffs(0)+20)*FW,36*FH);MM.Info(MODIFIED COM$)
EndIf
End Sub

Sub fileCursor(on_off)
If PS Then
  If on_off Then
    If LFSlct$(LSindex(LFLIndx))="1" Then
      TILE 1,1+LPPos,c(SClr),FC,38,1
    Else
      TILE 1,1+LPPos,BC,FC,38,1
    EndIf
  Else
    If LFSlct$(LSindex(LFLIndx))="1" Then
      TILE 1,1+LPPos,c(SClr),BC,38,1
    Else
      TILE 1,1+LPPos,FC,BC,38,1
    EndIf
  EndIf
Else
  If on_off Then
    If RFSlct$(RSindex(RFLIndx))="1" Then
      TILE 41,1+RPPos,c(SClr),FC,38,1
    Else
      TILE 41,1+RPPos,BC,FC,38,1
    EndIf
  Else
    If RFSlct$(RSindex(RFLIndx))="1" Then
      TILE 41,1+RPPos,c(SClr),BC,38,1
    Else
      TILE 41,1+RPPos,FC,BC,38,1
    EndIf
  EndIf
EndIf
End Sub

Sub SetAltPControl()'#alt
PrintAltFMenu()
On error abort
CKey=getkey()
Select Case CKey
Case 145  'help
  SetPControl("DIS")
  PrintHelp()
  PanelsReStore()
Case 147,179  'alt/shift F3-ListHEX
  ListHex GetCurrFullName$(PS)
  PanelsReStore()
Case 148,180  'alt/shift F4 R.Sort
  BSort$(PS)=SortSwitch$(BSort$(PS))
  ReShowPPanel()
Case 152,184  'alt/shift F8-Cutter
  SetPControl("DIS")
  W_altF8_Cutter(GetCurrFullName$(PS))
  PanelsReStart()
Case 153,185  'alt/shift F9-Merge
  SetPControl("DIS")
  W_altF9_Merge(GetCurrFullName$(PS))
  PanelsReStart()
End Select
PrintFMenu()
End Sub

Sub WDisk 'Replacement for WDiskSelect()
On ERROR SKIP 1
If MM.Info(SDCARD)="Ready" Then
  On ERROR CLEAR
  If BDISK$(PS)="A:" Then BDISK$(PS)="B:" Else BDISK$(PS)="A:"
  BDir$(PS)="/"
  If PS Then
    Erase LFSlct$():Dim LFSlct$(RMax) LENGTH 1
  Else
    Erase RFSlct$():Dim RFSlct$(RMax) LENGTH 1
  EndIf
EndIf
End Sub

'----------------------
Function SortSwitch$(SS$)
  Select Case SS$
  Case "Name>"
    SortSwitch$="Date>"
  Case "Date>"
    SortSwitch$="Size>"
  Case "Size>"
    SortSwitch$="Name<"
  Case "Name<"
    SortSwitch$="Date<"
  Case "Date<"
    SortSwitch$="Size<"
  Case "Size<"
    SortSwitch$="Name>"
  End Select
End Function
'=======================
Sub W_F2_ReNAME()
Local string oldName$ length 64,newName$ length 64
Local ml=64,is_Dir=0
  oldName$=GetCurrName$(PS)
  newName$=oldName$
  If Left$(oldName$,2)=".." Then End Sub
  is_Dir = isDir(oldName$)
  Color FC,c(1)
  OpenWindow("ReName: "+Choice(is_Dir,"DIR","FILE"),4,14,71,9)
  Chdir GetCurrFullPath$(PS)
  Print @(48,192);GetCurrFullPath$(PS);
  Print @(48,216);"AS";
  Print @(64,228);">";
  Color FC,BC:Print @(72,204);Space$(64);
  Print @(72,204);oldName$
  Color c(14),BC:Print @(72,228);Space$(64);
  Print @(72,228);
  If is_Dir Then
    Print "/";
    newName$=Mid$(newName$,2)
  EndIf
  newName$=InputE$(newName$,ml)'Drives A: and B: behave differently
  If ml=-1 Or newName$="" Or Choice(is_Dir,"/","")+newName$ = oldName$ Then Exit Sub
  If is_Dir And MM.Info(exists dir newName$) Or MM.Info(exists file newName$) Then
    Color FC,c(8)
    cprint(21,"Prohibited! Entry already exists. Hit any key to cancel.")
    Color FC,BC
    mywait
    Exit Sub
  EndIf
  On ERROR ignore
  Rename oldName$ As newName$
  W_ERROR_MSG()
End Sub
'----------------------#f4
Sub W_F4_Edit()
Drive "A:"
Local ml=64,freesp=MM.Info(free space)
Local TEMP$=GetCurrName$(PS)
Drive BDisk(ps)
Color FC,BC
On error ignore
Select Case Mid$(TEMP$,1,1)
Case ".."
  Local string TEMP$
  Color FC,c(1)
  OpenWindow("EDIT New File",4,14,71,6)
  Print @(48,192);GetCurrFullPath$(PS);
  Print @(64,216);">"
  Color c(14),BC:Print @(72,216);Space$(64);
  Print @(72,216);:TEMP$=InputE$("",ml)
  Color FC,BC
  If ml<>-1 Then Edit File TEMP$
Case "/"
  Exit Sub
Case Else
  If freesp>250000 Then 'there must be 250000 bytes free on A:
    Edit File TEMP$
  Else
    Error "Need more than "+Str$(freesp)+" bytes free space on drive A: !"
  EndIf
  W_ERROR_MSG()
End Select
End Sub
'----------------------#f5
Sub W_F5_MSCopy()
Local string TEMP$ length 64
Local done=0,BFLS(2)
Color FC,c(1)
OpenWindow("Multi-Copy selected files:",4,12,71,14)
Print @(48,168);"From: ";GetCurrFullPath$(PS);
Print @(48,192);"Copy ";BSel(PS)  " files to: "
Print @(48,216);GetCurrFullPath$(OpSide());
k=getkey("Press any key to execute, or [ESC] to cancel",25)
If k=27 Then Exit Sub
BFLS(1)=Choice(PS,LFLS(1),RFLS(1))
BFLS(2)=Choice(PS,LFLS(2),RFLS(2))

If PS Then
   For i = BFLS(1)+1 To BFLS(1)+BFLS(2)
    If LFSlct$(LSindex(i))="1" Then
      Color FC,c(1)
      OpenWindow("Multi-Copy selected files:",4,12,71,14)
      Print @(48,168);"From: ";GetCurrFullPath$(PS);
      Print @(48,192);"Copy ";BSel(PS)-done  " files to: ";
      Print @(48,216);GetCurrFullPath$(OpSide());
      TEMP$=LFList$(LSindex(i))
      Print @(48,240);"Copy file: ";
      Print @(48,264) TEMP$;
      TEMP$=GetCurrFullPath$(OpSide())+TEMP$
      If MM.Info(exists file TEMP$) Then
        Color FC,c(8)
   Print @(88,288)"Warning! File already exists. To Overwrite, press [ENTER]"
   Print @(88,300)"  or [ESC] to skip this file, or any other key to cancel "
        Color FC,BC
        Do
          CKey=Asc(Inkey$)
          If CKey=13 Then Exit Do
          If CKey=27 Then Next i
          If CKey>0  Then Exit Sub
        Loop
      EndIf
      Copy LFList$(LSindex(i)) To TEMP$
      Inc done
    EndIf
   Next i
  Else
   For i = BFLS(1)+1 To BFLS(1)+BFLS(2)
    If RFSlct$(RSindex(i))="1" Then
      Color FC,c(1)
      OpenWindow("Multi-Copy selected files:",4,12,71,14)
      Print @(48,216-48);"From: ";GetCurrFullPath$(PS);
      Print @(48,192);"Copy ";BSel(PS)-done  " files to: ";
      Print @(48,216);GetCurrFullPath$(OpSide());
      TEMP$=RFList$(RSindex(i))
      Print @(48,240);"Copy file: ";
      Print @(48,264) TEMP$;
      TEMP$=GetCurrFullPath$(OpSide())+TEMP$
      If MM.Info(exists file TEMP$) Then
        Color FC,c(8)
   Print @(88,288)"Warning! File already exists. To Overwrite, press [ENTER]"
   Print @(88,300)"  or [ESC] to skip this file, or any other key to cancel "
        Color FC,BC
        Do
          CKey=Asc(Inkey$)
          If CKey=13 Then Exit Do
          If CKey=27 Then Next i
          If CKey>0  Then Exit Sub
        Loop
      EndIf
      Copy RFList$(RSindex(i)) To TEMP$
      Inc done
    EndIf
  Next i
EndIf
End Sub '******


Sub W_F5_Copy()
Local string TEMP$ length 64,source$,dest$
Local spos,ml=64,is_Dir=0
  If Left$(GetCurrName$(PS),2)=".." Then End Sub
  is_Dir=(Left$(GetCurrName$(PS),1)="/")
  Color FC,c(1)
  OpenWindow("Copy a "+Choice(is_Dir,"directory:","file:"),4,14,71,10)
  Chdir GetCurrFullPath$(PS)
  Print @(48,192);GetCurrFullPath$(PS);
  Print @(48,216);"to";
  Print @(48,240);GetCurrFullPath$(OpSide());
  Print @(64,252);">";
  Color FC,BC:Print @(72,204);Space$(64);
  Print @(72,204);GetCurrName$(PS);
  Color c(14),BC:Print @(72,252);Space$(64);
  TEMP$=GetCurrName$(PS)
  Print @(72,252);
  If is_Dir Then
    Color FC,c(1)
    Print "/";
    Color FC,BC
    TEMP$=Mid$(GetCurrName$(PS),2)
  EndIf
  TEMP$=InputE$(TEMP$,ml)
  If ml=-1 Or TEMP$="" Then Exit Sub 'ESC
  source$=GetCurrFullPath$(PS)+Mid$(GetCurrName$(PS),2)
  dest$  =GetCurrFullPath$(OpSide())+TEMP$
  spos   =Instr(4,dest$,"/")
  If spos Then dest$=Left$(dest$,spos-1)
  spos   =Instr(4,source$,"/")
  If spos Then source$=Left$(source$,spos-1)
  On ERROR ignore
  If is_Dir Then
    If source$ = dest$ Then
      Color c(12),BC
      OpenWindow("Caution! Please confirm: ",4,14,71,10)
      CPrint(17," You are trying to copy from source to source directory:")
      CPrint(19,Chr$(34)+source$+Chr$(34)+" to "+Chr$(34)+dest$+Chr$(34))
      CPrint(21,"This is not possible. Press any key to cancel")
      Color FC,BC
      mywait
      Exit Sub
    EndIf
    If MM.Info(exists dir(GetCurrFullPath$(OpSide())+TEMP$)) Then
      Color c(12),BC
      OpenWindow("WARNING! Please confirm: ",4,14,71,10)
      CPrint(17," This DIRECTORY exists: ")
      CPrint(19,Chr$(34)+GetCurrFullPath$(OpSide())+TEMP$+Chr$(34))
      CPrint(21,"to OVERWRITE press [INS], or any key to cancel")
      Color FC,BC
      Do
        CKey=Asc(Inkey$)
        If CKey=132 Then Exit Do 'INS-key
        If CKey>0   Then Exit Sub
      Loop
    EndIf
    source$=GetCurrFullPath$(PS)+Mid$(GetCurrName$(PS),2)
    dest$  =GetCurrFullPath$(OpSide())+TEMP$
    For i = 15 To 23
      cPrint(i,Space$(70))
    Next
    copydir source$,dest$
    Pause 2000
  Else
    TEMP$=GetCurrFullPath$(OpSide())+TEMP$
    If MM.Info(exists file TEMP$) Then
      Color FC,c(8)
      Print @(72,276) " Warning!  File already exists. To Overwrite, press [ENTER]"
      Color FC,BC
      Do
        CKey=Asc(Inkey$)
        If CKey=13 Then Exit Do
        If CKey>0  Then Exit Sub
      Loop
    EndIf
    Copy GetCurrFullName$(PS) To TEMP$
  EndIf
  W_ERROR_MSG()
End Sub
'----------------------
Sub W_F6_MOVE()
Local string TEMP$
Local ml=64
  If Left$(GetCurrName$(PS),2)=".." Then End Sub
  Color FC,c(1)
  OpenWindow("Move:",4,14,71,9)
  Print @(48,192);GetCurrFullPath$(PS);
  Print @(48,216);"to";
  Print @(48,240);GetCurrFullPath$(OpSide());
  Print @(64,252);">";
  Color FC,BC:Print @(72,204);Space$(64);
  Print @(72,204);GetCurrName$(PS);
  Color c(14),BC:Print @(72,252);Space$(64);
  Print @(72,252);:TEMP$=InputE$(GetCurrName$(PS),ml)
  If ml=-1 Then Exit Sub 'ESC
  Color FC,BC
  If MM.Info(exists file GetCurrFullPath$(OpSide())+TEMP$) Then
    Color FC,c(8)
    Print @(72,276) " Caution!  File already exists. To Overwrite, press [ENTER]"
    Color FC,BC
    Do
      CKey=Asc(Inkey$)
      If CKey=13 Then Exit Do
      If CKey>0  Then Exit Sub
    Loop
  EndIf
  If TEMP$<>"" Then
    TEMP$=GetCurrFullPath$(OpSide())+TEMP$
    On ERROR ignore
    Copy GetCurrFullName$(PS) To TEMP$
    If Not MM.Errno Then
      Kill GetCurrFullName$(PS)
    EndIf
    W_ERROR_MSG()
  EndIf
End Sub
'----------------------
Sub W_F7_MkDIR()
Local string TEMP$
Local ml=64
  Color FC,c(1)
  OpenWindow("Make a Directory:",4,14,71,6)
  TEMP$=GetCurrFullPath$(PS)
  Chdir TEMP$
  Print @(48,192);TEMP$
  Print @(64,216);">";
  Color c(14),BC:Print Space$(64);
  Print @(72,216);:TEMP$=InputE$("",ml)
  If ml<>-1 And TEMP$<>"" Then
    If MM.Info(exists dir TEMP$) Or MM.Info(exists file TEMP$) Then
      Color FC,c(8)
      cprint(21,"Prohibited! Entry already exists. Hit any key to cancel.")
      Color FC,BC
      mywait
      Exit Sub
    EndIf
    On error skip
    Mkdir TEMP$
    W_ERROR_MSG()
  EndIf
End Sub
'----------------------#f8
Sub W_F8_MS_DELETE()
Local BFSlct$
Local BFLS(2)
Color BC,RGB(GOLD)
OpenWindow("Caution! Multi-Delete "+Str$(BSel(PS))+" selected files on:",4,14,71,7)
Print @(48,192);GetCurrFullPath$(PS);
CKey=getkey(" Hit [ESC] to cancel, [ENTER] to execute delete ",19)
Chdir GetCurrFullPath$(PS)
If CKey=27 Then Exit Sub
If CKey=13 Then

On ERROR ignore
BFLS(0)=Choice(PS,LFLS(0),RFLS(0))
BFLS(1)=Choice(PS,LFLS(1),RFLS(1))
For i = BFLS(1)+1 To BFLS(0)
  TEMP$  =Choice(PS,LFList$(LSindex(i)),RFList$(RSindex(i)))
  BFSlct$=Choice(PS,LFSlct$(LSindex(i)),RFSlct$(RSindex(i)))
  If BFSlct$="1") Then
    Color c(14),BC
    cPrint(19,Space$(64),64)
    cPrint(19,TEMP$,Len(TEMP$))
    If Inkey$=Chr$(27) Then Exit For
    Kill TEMP$
    W_ERROR_MSG()
    Inc BSel(PS),-1
    If PS Then
      LFSlct$(LSindex(i))=""
    Else
      RFSlct$(RSindex(i))=""
    EndIf
    cPrint(17,Str$(BSel(PS)),6)
    If BSel(PS) <= 0 Or MM.Errno Then Exit For
  EndIf
  Color FC,BC
  Next
  W_ERROR_MSG()
EndIf
End Sub '-----------

Sub W_F8_DELETE()
  If Left$(GetCurrName$(PS),2)=".." Then End Sub
  is_Dir=(Left$(GetCurrName$(PS),1)="/")
  Color FC,c(1+is_Dir*9)
  OpenWindow("Delete a "+Choice(is_Dir,"FOLDER: ","file: "),4,14,71,8)
  Chdir GetCurrFullPath$(PS)
  Print @(48,192);GetCurrFullPath$(PS);
  Print @(64,216);">";
  Color c(14),BC:Print @(72,216);Space$(64);
  Print @(72,216);GetCurrName$(PS);
  CKey=getkey("Press [ESC] to cancel")
  If CKey=13 Then
    On ERROR ignore
    If is_Dir Then
      OpenWindow("WARNING! Please confirm: ",4,14,71,8)
      CPrint(16," To DELETE this DIRECTORY: ")
      CPrint(18,Chr$(34)+GetCurrFullPath$(PS)+Mid$(GetCurrName$(PS),2)+Chr$(34))
      CPrint(20,"press [DEL] to execute, or any key to cancel")
      Color FC,BC
      Do
        CKey=Asc(Inkey$)
        If CKey=127 Then Exit Do 'Del-key
        If CKey>0   Then Exit Sub
      Loop
      For i = 16 To 20
        cPrint(i,Space$(70))
      Next
      DeleteDir(GetCurrFullPath$(PS)+Mid$(GetCurrName$(PS),2))
    Else
      Kill GetCurrName$(PS)
    EndIf
    W_ERROR_MSG()
  EndIf
End Sub
'-------------
Sub CPrint(line,msg$,cl)
  Print @((Int(80-cl)/2)*FW,line*FH)Space$(cl);
  Print @((Int(80-Len(msg$))/2)*FW,line*FH)msg$;
End Sub
'----------------------
Sub W_F9_MENU()'#f9
If inf9_f(PS) Then Exit Sub
  inf9_f(PS) = TRUE
  Chdir GetCurrFullPath$(PS)
  BSSize(PS)=0
  If PS Then
    Erase LFSlct$():Dim LFSlct$(RMax) LENGTH 1
    LPPos=0:LFLIndx=0:LFLTop=0:BSel(PS)=0
    GetMenuList(LFList$(),LFLS(),0)
  Else
    Erase RFSlct$():Dim RFSlct$(RMax) LENGTH 1
    RPPos=0:RFLIndx=0:RFLTop=0:BSel(PS)=0
    GetMenuList(RFList$(),RFLS(),1)
  EndIf
  RewritePPanel()
End Sub
'----------------------
Sub GetMenuList(ML$(),LS(),side)
Local n
ML$(0)=".."
Restore MENU_ITEMS
For n=1 To PgS
  Read ML$(n)
  If ML$(n)="" Then Exit For
Next n
If side=0 Then
  Sort ML$(),LSindex(),,,n-1
Else
  Sort ML$(),RSindex(),,,n-1
EndIf
LS(0)=n-1
LS(1)=0:LS(2)=0
End Sub
'Window ERROR MSG -----------
Sub W_ERROR_MSG()
Local integer x,l
If MM.Errno Then
  Color FC,c(8)
  l=Len(MM.ErrMsg$)+4: x=40-(l\2)
  OpenWindow("ERROR:",x,24,l,5)
  Print @((x+2)*FW,26*FH);
  Print MM.ErrMsg$;
  Color FC,BC
  On ERROR CLEAR
  mywait
  PanelsReStore()
EndIf
On ERROR ABORT
End Sub
'============================
Sub GetFList(Disk$,Folder$,SSort$,FList$(),FLS(),Si(),side)'##00
Local string  FName$,LSort$=Left$(SSort$,4)
Local integer RQt=0,DQt=0,FQt=0
Local string   FLtmp$(Rmax) LENGTH 64 'File name temp used for both panels
Local string  FDateT$(RMax) LENGTH 19 'File date temp
Local integer FSizeT(RMax)           'File size temp
Drive Disk$
Chdir Folder$
FList$(0)=".."
FName$=Dir$("*",DIR)
Do While FName$<>""
  Inc RQt: Inc DQt: If RQt=RMax Then Exit Do
  FList$(RQt)="/"+FName$
  FLtmp$(RQt)=FList$(RQt)
  If LSort$="Date" Then FDateT$(RQt)=MM.Info(MODIFIED FName$)
  FSizeT(RQt)=0
  FName$=Dir$()
Loop
overLoad$(side)=""
oldPg(side)=-1
FName$=Dir$("*",FILE)
Do While FName$<>""
  If RQt>=RMax Then
    On error ignore
    Error "To many files (>="+Str$(RQt)+") on drive: "+Disk$+Folder$
    overLoad$(side)=">"
    W_ERROR_MSG()
    Exit Do
  EndIf
  Inc RQt:Inc FQt
  FList$(RQt)=FName$
  FLtmp$(RQt)=FName$
  If LSort$="Date" Then FDateT$(RQt)=MM.Info(MODIFIED FName$)
  If LSort$="Size" Then FSizeT(RQt)=MM.Info(FILESIZE FName$)
  FName$=Dir$()
Loop
FLS(0)=RQt
FLS(1)=DQt
FLS(2)=FQt
If RQt>0 Then
  If SSort$="Name>" Then Sort FLtmp$() ,SI(),6,1,RQt 'Name
  If SSort$="Date>" Then Sort FDateT$(),SI(),4,DQt+1 'Date experimental
  If SSort$="Size>" Then Sort FSizeT() ,SI(), ,1,RQt 'Size
  If SSort$="Name<" Then Sort FLtmp$() ,SI(),3,1,RQt 'Name< =REVERSE
  If SSort$="Date<" Then Sort FDateT$(),SI(),1,DQt+1',FQt 'Date<
  If SSort$="Size<" Then Sort FSizeT() ,SI(),1,1,RQt 'Size<
EndIf
End Sub


Sub sortSelectFls(FList$(),FSlct$(),SI(),FLS())
Local i
Local FSTmp$(RMax) LENGTH 64
  For i = 0 To FLS(0)
    FSTmp$(i)=Choice(FSlct$(i)="1",Chr$(0)+FList$(i),FSlct$(i))+FList$(i)
  Next
  Sort FSTmp$(),SI(),6,FLS(1)+1,FLS(2) 'Sort selection
End Sub

'============================
Function GetCurrFullPath$(Side) As string
  GetCurrFullPath$=BDisk$(SIDE)+BDir$(SIDE)
End Function
'----------------------
Function GetCurrName$(SIDE) As string
If SIDE Then
  GetCurrName$=LFList$(LSindex(LFLIndx))
Else
  GetCurrName$=RFList$(RSindex(RFLIndx))
EndIf
End Function
'----------------------
Function GetCurrFullName$(SIDE) As string
Local string Flist$
Flist$=Choice(SIDE,LFList$(LSindex(LFLIndx)),RFList$(RSindex(RFLIndx)))
If Left$(Flist$,1)="/" Then Flist$=Mid$(Flist$,2)
GetCurrFullName$=GetCurrFullPath$(SIDE)+Flist$
End Function
'----------------------
Function PanelPath$(SIDE) As string
Local TEMP$
TEMP$=BDisk$(SIDE)+BDir$(SIDE)
If Len(TEMP$)<37 Then
  PanelPath$=TEMP$
Else
  PanelPath$=Mid$(TEMP$,1,3)+".."+Mid$(TEMP$,(Len(TEMP$)-31),31)
EndIf
End Function
'----------------------
Function OpSide() As integer
  If PS Then OpSide=0 Else OpSide=1
End Function
'============================
'Panels Interface ReWrite
Sub PanelsReStart()
  PrintFMenu()
  LPanelShow()
  RPanelShow()
  SetPControl("ENA")
  inf9_f(0)=FALSE:inf9_f(1)=FALSE
End Sub
Sub ReShowPPanel()
  BSel(PS)=0
  If PS Then
    Erase LFSlct$():Dim LFSlct$(RMax) LENGTH 1
    LPanelShow()
  Else
    Erase RFSlct$():Dim RFSlct$(RMax) LENGTH 1
    RPanelShow()
  EndIf
  SetPControl("ENA")
End Sub

'Panels Interface Restore
Sub PanelsReStore()
  PrintFMenu()
  LPrintPanel
  RPrintPanel
  SetPControl("ENA")
End Sub
Sub RewritePPanel()
  If PS Then
    LPrintPanel
  Else
    RPrintPanel
  EndIf
  SetPControl("ENA")
End Sub

'----------------------LPanel
Sub LPanelShow()'##++
SetPControl("DIS")
LPPos=0:LFLIndx=0:LFLTop=0
Erase LFList$():Dim LFList$(RMax) LENGTH 64
GetFList(BDisk$(1),BDir$(1),BSort$(PS),LFList$(),LFLS(),LSindex(),1)
LPrintPanel
End Sub
Sub LPrintPanel
OpenWindow(PanelPath$(1),0,0,39,37)
WBar(BSort$(PS),0,34,39)
FLPrint(LFList$(),LFLTop, 1,1,38,PgS,1)
Print @(6*FW,37*FH)" Folders:";LFLS(1);", Files:";overLoad$(1);LFLS(2);" "
End Sub
'----------------------RPanel
Sub RPanelShow()
SetPControl("DIS")
RPPos=0:RFLIndx=0:RFLTop=0
Erase RFList$():Dim RFList$(RMax) LENGTH 64
GetFList(BDisk$(0),BDir$(0),BSort$(PS),RFList$(),RFLS(),RSindex(),0)
RPrintPanel
End Sub
Sub RPrintPanel
OpenWindow(PanelPath$(0),ROffs(0),0,39,37)
WBar(BSort$(PS),ROffs(0),34,39)
FLPrint(RFList$(),RFLTop,ROffs(0)+1,1,38,PgS,0)'#p
Print @((ROffs(0)+6)*FW,37*FH)" Folders:";RFLS(1);", Files:";overLoad$(0);RFLS(2);" "
End Sub
'============================
Sub OpenWindow(Titl$,xc,yc,wc,hc)
Local integer i,x=(xc+1)*8,y=(yc+1)*12
Local string TEMP$=Space$(wc-1)
  For i=0 To hc-2     'Clear space in frame
    Print @(x,y) TEMP$;
    Inc y,12
  Next
  WFrame(xc,yc,wc,hc)
  Print @((xc+2)*8,yc*12)Chr$(181);Titl$;Chr$(198);
End Sub
'----------------------
Sub WFrame(xc,yc,wc,hc)
Local integer x,y
  Print @(xc*8,yc*12)Chr$(201);
  For x=xc+1 To xc+wc-1
    Print Chr$(205);
  Next
  Print @((xc+wc)*8,yc*12)Chr$(187);
  For y=yc+1 To yc+hc-1
    Print @(xc*8,y*12)Chr$(186);
    Print @((xc+wc)*8,y*12)Chr$(186);
  Next
  Print @(xc*8,(yc+hc)*12)Chr$(200);
  For x=xc+1 To xc+wc-1
    Print Chr$(205);
  Next
  Print @((xc+wc)*8,(yc+hc)*12)Chr$(188);
End Sub
'----------------------
Sub WBar(Titl$,xc,yc,wc)
Local integer x=Len(Titl$)
  Print @(xc*8,yc*12)Chr$(199);
  If x>0 Then Inc x,2: Print Chr$(180);Titl$;Chr$(195);
  Color FC,0
  For x=x+xc+1 To xc+wc-1
    Print Chr$(196);
  Next
  showsel(TRUE)
End Sub

'============================
'PRINT File List on Panel
Sub FLPrint(Flist$(),top,xc,yc,wc,hc,side)
Local string FName$
Local integer y,FNum=0,selected
FNum=top
For y=yc To yc+hc-1
 selected=0
 FName$=""
 Print @(xc*FW,y*FH);
 If FNum<=RMax Then
   If side=1 Then
     FName$=FList$(LSindex(FNum))
     selected=LFSlct$(LSindex(FNum))="1"
   Else
     FName$=FList$(RSindex(FNum))
     selected=RFSlct$(RSindex(FNum))="1"
   EndIf
 EndIf
 If FName$<>"" And (FName$<>".." Or FNum< 1) Then
   FName$=Mid$(FName$,1,wc)
   FName$=FName$+Space$(wc-Len(Fname$))
   If selected Then Color c(SClr)
   Print FName$
   Color FC
   Inc FNum
 Else
   Print Space$(wc)
 EndIf
Next
End Sub

'PRINT HELP -----------
Sub PrintHelp()
hp=64
Color FC,c(1)
OpenWindow("Help",6,3,68,32)
Print @(hp,64) "File Manager ";VERSION$;" for PicoMiteVGA/HDMI MMBasic >=V6.00.02"
Print :Print @(hp)"By Jatlov Vadim    javavict@gmail.com (c)2025"
Print :Print @(hp)"[Arrows],[PgUp],[PgDn],[Home],[End] Keys - Navigation"
Print :Print @(hp)"[0-9,a-z] moves the file cursor to the corresponding filename"
Print :Print @(hp)"[Tab] Key - Switches between left & right panels"
Print :Print @(hp)"[F1]...[F9] Keys - Main Control Functions"
Print :Print @(hp)"[Alt] or [BS]+[F1]...[F9] Keys - Alternate control functions"
Print :Print @(hp)"[Shift]+[F3] - Hex List, [Shift]+[F8] Cutter, [Shift]+[F9] Merge"
Print :Print @(hp)"[F10] - DiskInfo (external: 'di.bas')"
Print :Print @(hp)"[F12] Exit to command prompt, [DEL]-Change Drive, [INS] -> Root"
Print :Print @(hp)"[Esc] Key - Escape from popup input"
Print :Print @(hp)"[Enter] Key - Entering a folder, running a file"
Print :Print @(hp)"[SPACE] to select a single file [+,-,#] to multi select (RegEx)"
Print :Print @(hp)"[CTRL]+'n','d' and 's' Sort mode for file list (Name, Date, Size)"
Print :Print @(hp)"[<] Key - to sort selected files"
Color 0,c(14):Print @(520,84);"    ":Color 0,c(7):Print @(520,96);"    "
Color FC,BC
mywait
End Sub
'PRINT FUNCTION KEY MENU
Sub PrintFMenu()
Color FC,BC
Print @(0,480-12);
Print  "F1"; :Color 0,c(7):Print "Help  ";:Color FC,0
Print " F2"; :Color 0,c(7):Print "ReName";:Color FC,0
Print " F3"; :Color 0,c(7):Print "TView ";:Color FC,0
Print " F4"; :Color 0,c(7):Print "Edit  ";:Color FC,0
Print " F5"; :Color 0,c(7):Print "Copy  ";:Color FC,0
Print " F6"; :Color 0,c(7):Print "Move  ";:Color FC,0
Print " F7"; :Color 0,c(7):Print "MkDir ";:Color FC,0
Print " F8"; :Color 0,c(7):Print "Delete";:Color FC,0
Print " F9"; :Color 0,c(7):Print "Menu  ";:Color FC,0
End Sub
'----------------------
Sub PrintAltFMenu()
Color FC,BC
Print @(0,480-12);
Print  "F1"; :Color 0,c(7):Print "      ";:Color FC,0
Print " F2"; :Color 0,c(7):Print "      ";:Color FC,0
Print " F3"; :Color 0,c(7):Print "LstHex";:Color FC,0
Print " F4"; :Color 0,c(7):Print "Sort M";:Color FC,0
Print " F5"; :Color 0,c(7):Print "      ";:Color FC,0
Print " F6"; :Color 0,c(7):Print "      ";:Color FC,0
Print " F7"; :Color 0,c(7):Print "      ";:Color FC,0
Print " F8"; :Color 0,c(7):Print "Cutter";:Color FC,0
Print " F9"; :Color 0,c(7):Print "Merge ";:Color FC,0
End Sub
'PRINT Watch Time -----
Sub PrintTime()
  Tick1s=0
  Color c(14),c(1)
  Print @(600,0);Mid$(Time$,1,5);
  Color FC,BC
End Sub
'INTERRUP ROUTINES
Sub ISR_Tick1s
  Inc Tick1s
End Sub
'============================
'SCREEN SAVER - Matrix
Sub SSMatrix
Local matr(CHR),fade(CHR),clr,x
For x=1 To CHR:matr(x)=CVR*Rnd:fade(x)=&h8F*Rnd:Next
Do
  For x=1 To CHR
    clr=200*fade(x) And &hFF00
    If x=Rnd*CHR/2 Then Next
    Color clr
    Print @(x*FW-FW,matr(x)*FH)Chr$(Rnd*223+32);
    If matr(x)>CVR  Then matr(x)=0 Else Inc matr(x)
    If fade(x)=&hF0 Then fade(x)=0 Else Inc fade(x)
  Next
Loop While Inkey$=""
Color FC
Timer =0
CLS
PanelsReStore()
End Sub


Sub LHHead(FileN$) '* Procedure for ListHex()
  CLS
  Color RGB(BLUE),FC
  Print String$(79," ");@(0)
  Print String$(79," ");@(0);
  Print " File: "FileN$,, "Length: "MM.Info(Filesize FileN$)
  Color RGB(Yellow),RGB(CERULEAN)
  Print "             "Chr$(179)Chr$(179)"00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"Chr$(179);
  Color FC, RGB(MYRTLE)
  Print "                "
  Color FC,RGB(CERULEAN)
  Print "  Pos Offset "Chr$(179)Chr$(179)"01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16"Chr$(179);
  Color FC, RGB(MYRTLE)
  Print "    A S C I I   "
  Color FC, RGB(128,128,128)
  Print String$(13,Chr$(196));Chr$(197);Chr$(197);
  Print String$(47,Chr$(196));Chr$(197);
  Print String$(16,Chr$(196))
  Color FC,BC
End Sub

'***************************
' included by twofingers
'
Sub ListHex filename$

Const TRUE=1, FALSE=TRUE=0
Local string  asciiView$
Local string  buffer$(512) length 1
Local string  key$="",PRESS$,SKey$
Local Integer startOffset=0, newOffset
Local Integer fileSize
Local Integer bytesRead
Local Integer i, j, x, b

Const ESC$=Chr$(27),PGUP$=Chr$(136),PGDN$=Chr$(137)
Const HOME$=Chr$(134),END$=Chr$(135),INS$=Chr$(132)
Const LKey$=ESC$+HOME$+PGUP$+PGDN$+END$+INS$
Const FRSTKey$=ESC$+PGDN$+END$+INS$
Const EOFKey$=ESC$+HOME$+PGUP$+INS$
'Const FH=MM.Info(fontheight),FW=MM.Info(fontwidth)
Const BELL$=Chr$(7)
Const rowsPerPage=32,pageSize=rowsPerPage*16

Const PRESSKM$= "<<< Press "+Chr$(146)+Chr$(147)+" or <HOME> or <END> to continue!(or <ESC> To EXIT) >>>"
Const PRESSKF$= "<<< Press "+Chr$(147)+" or <END> to continue!(Or <ESC> to EXIT) >>>"
Const PRESSKE$= "<<< End of File. Press "+Chr$(146)+" or <HOME> to continue, or <ESC> To EXIT! >>>"
Const PRESSKL$= "<<< End of File. Press <ESC> To EXIT! >>>"

CLS
On ERROR IGNORE

Open fileName$ For Input As #1
fileSize =MM.Info(fileSize fileName$)

If fileSize = 0 Or Not MM.Info(exists file fileName$) Then
  Print "File is empty or cannot be read."
  Close #1
  End Sub
End If
startOffset = 1
Do
  CLS
  Seek #1, startOffset
  For x = 0 To pageSize
    buffer$(x) = Input$(1,#1)
  Next x
  bytesRead=x-1
  LHHead(filename$)
  For i = 0 To bytesRead - 1 Step 16
    If startOffset+i<=fileSize Then
      Print " ";Format$(startOffset+i,"%12g"); '*
    Else
      Print String$(13," ");
    EndIf
    Color FC,RGB(GRAY)
    Print Chr$(179)Chr$(179);
    asciiView$ = ""
    Color FC,RGB(BLUE)
    For j = 0 To 15
      If i + j < bytesRead Then
        b = Asc(buffer$(i + j))
        If startOffset+i + j >fileSize Then
          Color FC,BC
          Print "--";
          b=32 'ascii space
        Else
          Print Hex$(b,2);
        EndIf
        Print Chr$(179);
        If b >= 32 And b <= 255 Then
          asciiView$ = asciiView$ + Chr$(b)
        Else
          asciiView$ = asciiView$ + "."
        End If
      Else
        Print "  ";
        End If
    Next j
    Color FC,BC
    Print asciiView$
 Next i
 Do :Loop While Inkey$<>""
   If pageSize > fileSize Then
     PRESS$=PRESSKL$:SKey$=EOFKey$
   ElseIf startOffset + pageSize > fileSize Then
     PRESS$=PRESSKE$:SKey$=EOFKey$
   ElseIf startOffset - pageSize < 0 Then
     PRESS$=PRESSKF$:SKey$=FRSTKey$
   Else
     PRESS$=PRESSKm$:SKey$=LKey$
   EndIf
   Print
   Print @((80-Len(PRESS$))/2*MM.Info(fontwidth));
   Print PRESS$;
   Print
   Do :Key$=Inkey$:Loop Until Instr(SKey$,Key$)
   Select Case Key$
     Case PGDN$
       If startOffset + pageSize <= fileSize Then
         Inc startOffset, pageSize
       Else
         startOffset = (((fileSize-1) \ pageSize) * pageSize)+1
       End If
     Case PGUP$
       If startOffset - pageSize > 0 Then
         Inc startOffset, -pageSize
       End If
     Case HOME$
       startOffset = 1
     Case END$
       startOffset = (((fileSize-1) \ pageSize) * pageSize)+1
     Case INS$
       Color FC,RGB(RUST)
       Print @(20*FW);" Enter New FileOffs: ";
       Color FC,BC
       Input newOffset
       If newOffset > fileSize Then
         startOffset = (((fileSize-1) \ pageSize) * pageSize)+1
         Print BELL$;
       ElseIf newOffset > 0 Then
         startOffset = (((newOffset-1) \ pageSize) * pageSize)+1
       End If
     Case ESC$
       Color FC, RGB(RED)
       Print @(0,MM.Info(vpos)-FH);String$(79," ");
       Print @((80-27)/2*FW);
       Print ">>> Cancelled by user! <<<"
       Color FC,BC
       Exit Do
     End Select
  Loop
  Close #1

  On ERROR CLEAR
  mywait
End Sub


Sub COLORTABLE
Local integer i,col=0
Local string  cname$
Restore colors

Print "COLOR-TABLE"
Print @(47*FW)"R    G    B"
For i = 15 To 0 Step-1
  Read cname$
  Color BC,c(i)
  If i < 6 Then Color FC,c(i)
  Print Str$(i,3)"   "+cname$+"  ",convertCol$(c(i))
Next

col=RGB(64,32,96):Color FC,col
Print "     "+" *VIOLET* "+"  ",convertCol$(col)
col=RGB(64,64,64):Color FC,col
Print "     "+"*DARKGRAY*"+"  ",convertCol$(col)
For i = 1 To 7
  Read cname$
  Read col
  Color BC,col
  Print "      "+cname$+"  ",convertCol$(col)
Next
Print
Color FC,BC
Print "All colors shown are predefined in MMBasic, except DARKGRAY + VIOLET"
'* for "color map" and "c()" see the main prog!
colors:
Data " WHITE   "," YELLOW  "
Data " LILAC   "," BROWN   "
Data " FUCHSIA "," RUST    "
Data " MAGENTA "," RED     "
Data " CYAN    "," GREEN   "
Data "CERULEAN ","MIDGREEN "
Data " COBALT  "," MYRTLE  "
Data " BLUE    "," BLACK   "
Data " GRAY    ",RGB(GRAY)
Data "LIGHTGRAY",RGB(LIGHTGRAY)
Data " PINK    ",RGB(PINK)
Data " GOLD    ",RGB(GOLD)
Data " ORANGE  ",RGB(ORANGE)
Data " SALMON  ",RGB(SALMON)
Data " BEIGE   ",RGB(BEIGE)
Restore
End Sub

Function convertCol$(col)
mask=&HFF
convertCol$=Left$(Bin$(col,24),8)+" "+Mid$(Bin$(col,24),9,8)+" "+Right$(Bin$(col,24),8)
Inc convertCol$,"  "+Str$(col>>16 And mask,3)+", "
Inc convertCol$,Str$(col>>8 And mask,3)+", "+Str$(col And mask,3)+" "
End Function


Sub ASCIITABLE
Local integer a,i,j
CLS
 If Not FW Then FW=MM.Info(FONTWIDTH) 'if started from command line
 If Not FH Then FH=MM.Info(FONTHEIGHT)
 Print
 Color FC,RGB(MYRTLE)
 Print @(FW*6)"               "
 Print @(FW*6)"    MMBasic    "
 Print @(FW*6)"  ASCII-TABLE  "
 Print @(FW*6)"               "
 Box FW*6-2,FH-2,15*FW+2,4*FH+2,2
 Color FC,BC
 Print
 For j = 4 To 31
  For i = 0 To 7
    a=j*8+i
    If i=0 Then Print "   ";
    Print Format$(a,"%4g");
    Print " ";Chr$(a);" ";
  Next i
  If j < 31 Then Print
  Print @(0,MM.Info(vpos)-FH+2)
 Next j

 For i = 1 To 7
   Line FW*7*i+1+3*FW,6*FH,FW*7*i+1+3*FW,38*FH+FH/2,1
 Next i
 Box FW*3+1,FH*6-FH/2,57*FW-6,33*FH+FH/2,2
End Sub


'********************************
Sub DeleteDir(path$)
Local string file$, subdir$, aStr$
On error ignore
For check_twice = 1 To 3 'why?
 file$ = Dir$(path$ + "/*", FILE)
 Do While file$ <> ""
   cprint(15,"Delete file: ")
   cprint(17,shortStr$(path$ + "/" + file$),70)
   Kill path$ + "/" + file$
   file$ = Dir$()
 Loop
Next
L1_del: '--- do ---
 subdir$ = Dir$(path$ + "/*", DIR)
 If subdir$ = "" GoTo Lend_del
   cprint(19,"Delete dir: ")
   cprint(20,path$ + "/" + subdir$,70)
   DeleteDir(path$ + "/" + subdir$)  ' recursive
   '--- loop ---
   GoTo l1_del'replacement for do/loop
Lend_del:
   Rmdir path$
 Chdir ".."
 W_ERROR_MSG()
End Sub

'***********************
Sub CopyDir(src$, dest$)
Local dcount=0, i=0
Local string file$, aStr$
 Drive Left$(dest$,2)
 If Not MM.Info(exists dir dest$) Then
   On error skip
   Mkdir dest$
 EndIf
 err=MM.Errno
 W_ERROR_MSG()
 If err Then Exit Sub
 Drive Left$(src$,2)
 Chdir src$

'* files
 file$ = Dir$(src$+"/*", FILE)
 Do While file$ <> ""
   cPrint(20," copy file: "+shortStr$(dest$ + "/" + file$),70)
   On error skip
   Copy src$ + "/" + file$ To dest$ + "/" + file$
   err=MM.Errno
   W_ERROR_MSG()
   If err Then Exit Sub
   file$ = Dir$()
 Loop

'* dirs
  Local subDir$ = Dir$("*", DIR)
  Do While subDir$ <> ""
    Inc dcount
    subDir$ = Dir$()
  Loop
  If dcount >= 1 Then
    Local sdirs$(dcount)
    subDir$ = Dir$("*", DIR)
    Do While subDir$ <> ""
      sdirs$(i) = subDir$
      Inc i
      subDir$ = Dir$()
    Loop
    For i = 0 To dcount-1
      Pause 500
      cPrint(17," copy dir: "+shortStr$(src$ + "/" + sdirs$(i)),70)
      CopyDir(src$ + "/" + sdirs$(i), dest$ + "/" + sdirs$(i))
    Next i
  EndIf
End Sub

Function shortStr$(inStr$)
  shortStr$=inStr$
  If Len(shortStr$)>50 Then
    shortStr$=Left$(shortStr$,23)+" .. "+Right$(shortStr$,23)
  EndIf
End Function


'********************************
Sub TxtView(FName$)'for MMBasic >6.0001 or Drive A: only!
Const LinesPP   = 37'lines per page
Const maxPages  = 500
Local pPos(maxPages), cOvr(maxPages), LcOvr(maxPages)
Local string LN$,key$,snipName$,snip$,Prog$(2)=(Chr$(220),Chr$(223))
Local curPage   = 1
Local lastPage  = 1
Local lineCount,p=0,l_ln,help_on=1,oldPage,plines,olc
Local FSize=MM.Info(FILESIZE FName$)
If FSize<1 Then Exit Sub
CLS
On error skip 1
Close #1
On error clear
Open FName$ For INPUT As #1
If MM.Errno<>0 Then W_ERROR_MSG():Exit Sub
cprint(15,"Please wait!")
pPos(curPage)=1
Do
  lineCount = 0
  plines=0
  Do Until Eof(#1)
    If LN$ ="" Then
      Line Input #1,LN$:Inc plines
      If MM.Errno Then W_ERROR_MSG():Exit Sub
    EndIf
    LN$ =Mid$(LN$,75)
    Inc lineCount
  Loop Until lineCount >= LinesPP
  If LN$<>"" Then LcOvr(curPage)=Len(LN$)
  Inc curPage
  If curPage>=maxPages Then
    cprint(16,,80)
    cprint(17,"Sorry. Can't read the whole file. Limit: "+Str$(maxPages)+" pages",80)
    cprint(18,,80)
    Pause 5000
    Exit Sub
  EndIf
  cOvr(curPage)=cOvr(curPage-1)+lineCount-plines
  pPos(curPage)=Loc(#1)-Len(LN$)-Choice(LN$>"",2,0)
  p=p=0:cprint(17,Prog$(p))
Loop While Not Eof(#1)
lastPage=curPage-1+(LN$<>"")
pPos(lastPage +1)=Loc(#1)
curPage=1
oldPag =1
LN$=""

Do
  Print @(0,0);:If oldPage<>curPage Then CLS
  oldPage=curPage
  Seek #1, pPos(curPage)
  lineCount = 0
  plines=0
  Do
    If LN$ ="" Then
      Line Input #1,LN$:Inc plines:olc=0
    Else
      Inc olc
    EndIf
    If olc=0 Then
      lc$=Str$((curPage-1)*37+plines-cOvr(curPage)-(LcOvr(curPage-1)>0),6)
    Else
      lc$="      "
    EndIf
    Color BC,FC:Print lc$;:Color FC,BC
    Print Left$(LN$,74)
    LN$ =Mid$(LN$,75)
    Inc lineCount
  Loop Until lineCount >= LinesPP Or Eof(#1)
  cPrint(37,String$(80,Chr$(220)))
  Color FC,c(3)
  cPrint(38,,80)
  Print @(0,38*FH) "Pg "; Str$(curPage,3);"/";Str$(lastPage,3);
  Print " Offset:";Str$(pPos(curPage)-1,7);"/";FSize;
  If help_on Then
    Print @(36*FW)"|F1| PgUp|PgDn | HOME|END | INS | DEL | ESC ";
  Else
    Seek #1, pPos(curPage):Line Input #1,LN$
    Print @(36*FW)"|F1|";Right$(FName$,38);
  EndIf
  Color FC,BC
  Select Case getkey("-")
    Case 27'ESC
      Exit Sub
    Case 127'DEL
      snipName$=Snippet_Path$
      If Not MM.Info(SDCARD)="READY" Then
        snipName$=Mid$(Snippet_Path$,3)
      EndIf
      If snipName$=FName$ Then Exit Do
      On error skip 1
      Close #1,#2
      Open snipName$ For output As #2
      Open FName$ For INPUT As #1
      Seek #1, pPos(curPage)
      For i = 0 To plines-1
        Input #1,snip$
        Print #2,snip$
      Next
      Close #2
      Print @(40*FW,38*FH);Chr$(34);snipName$;Chr$(34);" created.";
      Pause 2000
      Exit Sub
    Case 132'INS
      Color FC,c(8)
      cprint(38,"   Goto page #:           ")
      cprint(38,"")
      Input gotoPage
      Color FC,BC
      If gotoPage=0 Then
        LN$=""
        Continue do
      EndIf
      If gotoPage < lastPage Then
        curPage=gotoPage
      Else
        curPage=lastPage
      EndIf
      oldPage=0
    Case 134'HOME
      curPage=1
    Case 135'END
      If curPage+1<>lastPage Then LN$=""
      curPage=lastPage
    Case 136'PGUP
      Inc curPage,-1
    Case 137'PGDN
      If curPage<lastPage Then Inc curPage
    Case 145'F1
      help_on=help_on=0
  End Select
  LN$=""
  If curPage<1 Then curPage=1
Loop
On error skip 1
Close #1
End Sub


Function getKey(msg$,ln) As integer
  If msg$="-" Then
    msg$="Press any key!"
  EndIf
  If ln=0 Then ln=39
  cprint(ln,msg$)
'  Do :Loop While Inkey$<>""
  Do :getKey=Asc(Inkey$):Loop While getKey=0
End Function

Sub mywait
  Do :Loop While Inkey$=""
End Sub


'***** Merge, for text files only *****
Sub W_altF9_Merge(FName$)
Local inName$  =Snippet_Path$
Local outName$ =MergedText_Path$
Local string LN$,msg$
Local lineCount
On error skip
Close #1,#2,#3

If MM.Info(exists dir FName$) Then End Sub
Color FC,c(1)
OpenWindow("Merge: ",1,14,77,7)
cprint(16,"Source: "+FName$+"  Dest: "+outName$)
If Not MM.Info(exists file inName$) Then
  cprint(17,inName$+" not found!",74)
  Pause 2000
  End Sub
EndIf
cprint(17,"Enter the line number after which "+Chr$(34)+inName$+Chr$(34)+" should be inserted: ")
cprint(19,"")
TEMP$=InputE$("",6,1,1)
If Val(TEMP$)>0 Then
  insert_pos=Val(TEMP$)
  Open   FName$ For INPUT  As #1
  Open inName$  For INPUT  As #2
  Open outName$ For OUTPUT As #3
  If Lof(#1) Then
    lineCount = 0
    Do
      On error skip
      Line Input #1,LN$
      Print #3,LN$
      Inc lineCount
      If insert_pos=lineCount Or Eof(#1) Then
        Do While Not Eof(#2)
          Line Input #2,LN$
          Print #3,LN$
        Loop
      EndIf
    Loop Until Eof(#1)
  EndIf
  If MM.Errno Then
    W_ERROR_MSG()
  Else
    If Lof(#1)+Lof(#2)=Lof(#3) Then
      msg$="Successfully merged!"
    Else
      Color FC,c(8)
      msg$="Something went wrong!"+Str$(Lof(#3))+" bytes of "+Str$(Lof(#1)+Lof(#2))+" copied."
    EndIf
    cprint(19,msg$,74)
    cprint(20,"Press any key",74)
    mywait
  EndIf
  Color FC,BC
  Close #1,#2,#3
EndIf
End Sub

'***** Cutter, for text files only *****
Sub W_altF8_Cutter(FName$)
Local inName$  =FName$
Local outName$ =Snippet_Path$
Local string LN$,msg$
Local from_pos,end_pos,lnumber
On error skip
Close #1,#2
Color FC,c(1)
OpenWindow("Cutter: (for text files only!)",11,13,57,12)
cprint(15,"Source: "+inName$+"  -->>  Dest: "+outName$)
If MM.Info(exists dir inName$) Then
  Color FC,c(8)
  cprint(17,"Oopps: "+inName$+" is a folder!",40)
  mywait
  End Sub
EndIf
If Not MM.Info(exists file inName$) Then
  Color FC,c(8)
  cprint(17,inName$+" not found!",40)
  mywait
  End Sub
EndIf
cprint(17,"Enter the first line number to start cutting:")
cprint(18,"")
TEMP$=InputE$("0",6,1,1)
from_pos=Val(TEMP$)
cprint(18,TEMP$,20)
cprint(20,"Enter the last line number:")
cprint(21,"")
TEMP$=InputE$(TEMP$,6,1,1)
end_pos=Val(TEMP$)
cprint(21,TEMP$,20)
Color FC,BC
CKey=getkey("Press <Enter> to continue, <ESC> to exit",23)
Do
  If CKey=27 Then Exit Sub
  If CKey=13 Then Exit Do
Loop
If end_pos>from_pos Then
 If Val(TEMP$)>0 Then
  Open inName$  For INPUT  As #1
  Open outName$ For OUTPUT As #2
  lnumber=0
  Do While lnumber<from_pos-1
    On error skip
    Line Input #1,LN$
    Inc lnumber
  Loop
  If Lof(#1) Then
    Do
      On error skip
      Line Input #1,LN$
      Print #2,LN$
      Inc lnumber
    Loop Until end_pos=lnumber Or Eof(#1)
  EndIf
  On error skip
  Close #1,#2
  If MM.Errno Then W_ERROR_MSG() EndIf
  Print @(80,21*FH);
  If lnumber-from_pos<>end_pos-from_pos Then
    nosucc$= "ERROR: only "+Str$(lnumber-from_pos+1)+" lines copied!"
    cprint(21,nosucc$)
    TILE (80-Len(nosucc$)-2)/2)-3,21,FC,c(8),Len(nosucc$)+1
  Else
    succ$=Str$(lnumber-from_pos+1)+" lines copied!"
    cprint(21,succ$)
    TILE (80-Len(succ$)-2)/2)-3,21,FC,c(4),Len(succ$)+1
  EndIf
  cprint(23,"Press a key to leave",42)
  mywait
 EndIf
EndIf
End Sub

Sub Freespace' F9_menu
  Print Str$(MM.Info(free space));" bytes free on drive: "MM.Info(drive)
End Sub

'INPUT+ESCape-- NEW Version v2.0 blink -----
Function InputE$(inString$,maxLen As integer,ovrOn,N_only) As string
Local s$=inString$,k$ length 1
Local gk,delflg,tLen=Len(s$),x=MM.Info(hPos),y=MM.Info(vPos)
Local cPos=tLen,exit_flag=0
Local cSet(1,1)=(32,127,48,58)'ASCII Character set vs Numbers
Local bc=MM.Info(Bcolor), fc=MM.Info(Fcolor),ovr_c=RGB(RUST)
Local blkon=0,BlkPLen=3000'period length

If maxLen=0 Then maxLen=tLen
If maxLen>79 Then maxLen>=79
Do
 Print @(x,y);Left$(s$,cPos);
 Color bc,Choice(ovrOn,ovr_c,fc)
 Inc blkon,3+tlen:If blkon>BlkPLen*2 Then blkon=0
 If blkon>BlkPLen Then Color fc,bc 'disable blink in text here
 Print Mid$(s$,cPos+1,1);
 Color fc,bc
 Print Mid$(s$,cPos+2);
 If cpos>=tLen And Not exit_flag Then
   Color Choice(ovrOn,ovr_c,fc),bc
   If blkon>BlkPLen Then Print Chr$(220); Else Print "_";
 Else
   Print " ";
 EndIf
 Color fc,bc
 If delflg Then Print " ";:delflg=0
 k$=Inkey$
 gk=Asc(k$)
 If exit_flag Then Exit Do
 If gk=13  Then exit_flag=1
 If gk=27  Then exit_flag=2
 If gk=130 And  cPos >0 Then Inc cPos,-1
 If gk=131 And  cPos <tLen Then Inc cPos
 If gk=132 Then ovrOn=ovrOn=0
 If gk=134 Then cPos =0 'HOME
 If gk=135 Then cPos =tLen 'END
 If gk=127 And cPos<tLen Then
   s$=Left$(s$,cPos) +Mid$(s$,cPos+2)
   Inc tLen,-1:delflg=1
 EndIf
 If gk=8 And tLen>0 And cPos>0 Then
   s$=Left$(s$,cPos -1) +Mid$(s$,cPos+1)
   Inc cPos,-1:Inc tLen,-1:delflg=1
 EndIf
 If gk>=cSet(0,N_only) And gk<cSet(1,N_only) Then
   If cPos<tLen And ovrOn Then
     s$=Left$(s$,cPos) +k$ +Mid$(s$,cPos+2)
     Inc cPos
   ElseIf tLen<maxLen Then
     s$=Left$(s$,cPos) +k$ +Mid$(s$,cPos+1)
     Inc cPos:Inc tLen
   EndIf
 EndIf
Loop
Color fc,bc
Print @(x,y);Space$(tLen); 'clear input line
Print @(x,y);
If exit_flag=2 Then
  maxLen=-1
  InputE$=inString$
Else
  InputE$=s$
EndIf
End Function

Sub ScrollBar(numFiles, curPage, Side)
Const pgSize = PgS'33
Const barH   = 25
Const sOffs=(ROffs(Side)+39)*FW
Local allPgs, sldrH=0, sldrPos, i
'  Color RGB(GRAY)
'  Color RGB(CERULEAN)
  If overLoad(Side)<>"" And PS=Side Then
    Color RGB(ORANGE)
  Else
    If PS<>Side Then Color FC Else Color RGB(128,196,255)
  EndIf
  If numFiles <=0 Then numFiles =1
  sldrH  =barH/(Int(numFiles/pgSize)+1)
  allPgs =(numFiles+pgSize) \ pgSize
  sldrPos=0
  If allPgs >1 Then
    sldrPos=Int((curPage/(allPgs -1)) * (barH -sldrH))
  EndIf
  Print @(sOffs,4*FH,2)Chr$(146);
  Print @(sOffs,30*FH,2)Chr$(147);
  For i =0 To barH -1
    If i >=sldrPos And i <sldrPos +sldrH Then
      Print @(sOffs,(i+5)*FH)Chr$(174);
    Else
      Print @(sOffs,(i+5)*FH,2)Chr$(179);
    EndIf
  Next
  Color FC,BC
End Sub      