'Main Dlg
#Define IDD_MainDlg             1000
#define IDC_TRVTop              1001
#define IDC_TRVBottom           1002
#define IDC_STCTop              1003
#define IDC_STCBottom           1004
'report type
#define IDC_LSVTop              1005
#Define IDC_LSVBottom           1006
#Define IDC_STCFTPLog           1007
'these are NOT visible
'Large Icon
#Define IDC_LSVTopLgIcon        1008
#Define IDC_LSVBotLgIcon        1009
'Zip file (report view)
#Define IDC_LSVTopZip           1010
#Define IDC_LSVBotZip           1011
'Small Icon
#Define IDC_LSVTopSmIcon        1012
#Define IDC_LSVBotSmIcon        1013

'Exist dlg
#define IDD_DLGFExist           1100
#define IDC_RBNSkip             1101
#define IDC_RBNOverW            1102
#define IDC_RBNRenameInput      1103
#define IDC_EDTInput            1104
#define IDC_BTNConfirm          1105

'File dele confirm dlg
#define IDD_DLGFileDelConfirm   1200
#define IDC_CHKNoMore           1201
#define IDC_STCFileName         1202
#define IDC_BTNDel              1203
#define IDC_BTNSkip             1204

'Trash bin dlg
#Define IDD_DLG_Recycle         1300
#define IDC_LSV_TrashFiles      1301

'FTP Cconnection dlg
#Define IDD_DLGFTP              1400
#define IDC_LSTConnections      1401
'#define IDC_STCHost             1402
'#define IDC_STCUser             1403
'#define IDC_STCPass             1404
'#define IDC_STCBaseDir          1405
#define IDC_EDTHost             1406
#define IDC_EDTUser             1407
#define IDC_EDTPassw            1408
#define IDC_EDTRemDir           1409
#define IDC_BTNConnect          1410
#define IDC_EDTConnection       1411
'#define IDC_STCConName          1412
#define IDC_EDTLDir             1413
'#define IDC_STCLDir             1414

'compare dlg
#Define IDD_DLGCompare          1500
#define IDC_LSTTopNew           1501
#define IDC_LSTTopNF            1502
#define IDC_LSTBotNew           1503
#define IDC_LSTBotNF            1504
#define IDC_BTNRefresh          1505
#define IDC_LSTTopOldSame       1506
#Define IDC_LSTBotOldSame       1507
#define IDC_BTNTopNew           1508
#define IDC_BTNTopOld           1509
#define IDC_BTNTopNF            1510
#define IDC_BTNBotNF            1511
#define IDC_BTNBotOld           1512
#define IDC_BTNBotNew           1513
#define IDC_STCCompTop          1514
#define IDC_STCCompBot          1515

'File properties dlg
#Define IDD_DLGFileProp         1600
'#define IDC_STCPropName         1601
#define IDC_EDTPropName         1602
'#define IDC_STCPropLoc          1603
'#define IDC_STCPropSize         1604
'#define IDC_STCPropDiskSize     1605
'#define IDC_STCPropMod          1606
'#define IDC_STCPropAcc          1607
'#define IDC_STCPropCreate       1608
#define IDC_STCPropCreateV      1609
#define IDC_STCPropAccV         1610
#define IDC_STCPropModV         1611
#define IDC_STCPropDiskSizeV    1612
#define IDC_STCPropSizeV        1613
#define IDC_STCPropLocV         1614
'#define IDC_STCPropAtt          1615
#define IDC_CHKPropRO           1616
#define IDC_CHKPropH            1617
#define IDC_CHKPropZip          1618
#define IDC_CHKPropS            1619
#define IDC_BTNPropDismiss      1620
#define IDC_BTNPropApply        1621

'One folder Sel prop dlg
#Define IDD_DLG1DirProp         1700
#define IDC_BTN1DirApply        1701
#define IDC_BTN1DirDismiss      1702
#define IDC_CHK1DirS            1703
#define IDC_CHK1DirZip          1704
#define IDC_CHK1DirH            1705
#define IDC_CHK1DirRO           1706
'#define IDC_STC1DirAtt          1707
#define IDC_STC1DirLocV         1708
#define IDC_STC1DirSizeV        1709
#define IDC_STC1DirDiskSizeV    1710
#define IDC_STC1DirContV        1712
#define IDC_STC1DirCreateV      1713
'#define IDC_STC1DirCreate       1714
'#define IDC_STC1DirCont         1715
'#define IDC_STC1DirDiskSize     1717
'#define IDC_STC1DirSize         1718
'#define IDC_STC1DirLoc          1719
#define IDC_EDT1DirName         1720
'#define IDC_STC1DirName         1721

'Properties Mixed selections
#Define IDD_DLGMixProp          1800
'#define IDC_STCMixL             1801
'#define IDC_STCMixSize          1802
'#define IDC_STCMixDiskS         1803
'#define IDC_STCMixCont          1804
#define IDC_STCMixContV         1807
#define IDC_STCMixDiskSizeV     1808
#define IDC_STCMixSizeV         1809
#define IDC_STCMixLocV          1810
'#define IDC_STCMixAttr          1811
#define IDC_CHKMixRO            1812
#define IDC_CHKMixH             1813
#define IDC_CHKMixZip           1814
#define IDC_CHKMixS             1815
#define IDC_BTNMixDismiss       1816
#define IDC_BTNMixApply         1817


'Main menu
#Define IDR_MENUMain            10000
'File
#Define IDM_NewT                10023 'will be modified for pop up menu
#define IDM_NewB                10024 'will be modified for pop up menu
#define IDM_OpenT               10016
#define IDM_OpenB               10017
#define IDM_CTB                 10006
#define IDM_CBT                 10007
#define IDM_MTB                 10008
#define IDM_MBT                 10009
#define IDM_DT                  10010
#define IDM_DB                  10011
#define IDM_TrashT              10018
#define IDM_TrashB              10019
#define IDM_SAT                 10004
#define IDM_SAB                 10005
#define IDM_IST                 10012
#define IDM_ISB                 10013
#define IDM_Compare             10021
#define IDM_Exit                10002
'Options
#define IDM_SaveExit            10003
#define IDM_SaveNow             10014
#Define IDM_DirTop              10001
#Define IDM_GrpF                10020
'Options - Views
#define IDM_ViewTopReport       10025 'start/default
#define IDM_ViewTopLargeIcons   10026
#define IDM_ViewTopSmallIcons   10027
'#define IDM_ViewTopList         10029
#define IDM_TopRevSort          10028
#define IDM_ViewBotReport       10030 'start/default
#define IDM_ViewBotLargeIcons   10031
#define IDM_ViewBotSmallIcons   10032
'#define IDM_ViewBotList         10033
#define IDM_BottomRevSort       10034
'FTP
#Define IDM_FTPConnect          10015
#Define IDM_KeepLog             10022

'Trash dlg menu
#define IDR_MENUTrash           11000
#define IDM_RestAll             11001
#define IDM_RestSel             11002
#define IDM_RmvAll              11003
#define IDM_RmvSel              11004

'number of milliseconds to delay main timer
#Define TimerDelay 7000

Dim Shared hInstance As HMODULE
Dim Shared As LongInt TZ 'minutes between UTC and local
Dim Shared As HWND DTop,DBottom,PDispTop,PDispBottom,FTPStats
Dim Shared As String wtTop,wtBottom,strShare,MyRecycle,FTPTemp
Dim Shared As Integer LastSortColTop,LastSortColBottom
Dim Shared As BOOL LastSortAccendTop,LastSortAccendBottom,Connected,KeepDirTop,GroupDir
'0 = report (that is what it starts with)
'1 = Large Icon
'2 = Small Icon
'3 = Zip file (report view)
Dim Shared As HWND FTop(3),FBottom(3)
Dim Shared As Integer TopLVType,BotLVType
'
Dim Shared As HIMAGELIST icons,smicons
'There has to be a better way than this. Only use it in ONE sub.
ReDim Shared As String FileIcons(1),NoIcons(0)
'0 is "unknown" or no file extention
FileIcons(1) = "File Folder"

'arrays for file data
Type FileStats
	'used in display
	FName As String
	Ext As String
	Att As Integer
	DT As Double
	FSize As ULongInt
	'WIN32_FIND_DATA
	'FName As String
	FName83 As String 'old dos format
	'Att As Integer
	'Modify As Double 'same as DT above?
	LastAccess As Double
	Create As Double
End Type
'v0.1 started as a FTP prg
ReDim Shared As FileStats FTPL(0),FTPR(0) 'L-ocal R-emote/Top Bottom

'create new file popup menu
Type MyMenuType
	As String Ext 'type txt,doc,jpg .....
	As String MenuDisp 'what to show on menu
	As String BlankFile 'Windows/ShellNew file to copy
End Type
ReDim Shared NewFMenu(1 To 1) As MyMenuType

'New type of return code:
Type ExtendedIntRet
	As Integer ToDo 'how many commands could/should be done
	As Integer Done 'how many commands done
	As String FaultStr 'why something wasn't done???? (debug?)
End Type

'Treeview subs
Declare Sub UpdateTrees
Declare Function PutTree(As String,As HTREEITEM,As Integer) As HTREEITEM
Declare Function ResolveTree(TheTree As HWND, Sel As HTREEITEM) As String
Declare Sub TV_NameIt(As HWND,As HTREEITEM,As String)
Declare Sub Check4Children(TheTree As HWND, Sel As HTREEITEM,SubCall As BOOL)
Declare Sub FindPathInTree(TV As HWND)
Declare Function FolderExistInTree(Tv As HWND,Check As String) As HTREEITEM
Declare Function TreeView_GetItemText(TV As HWND, Item As HTREEITEM) As String
Declare Sub ZipInTree(TheTree As HWND, Sel As HTREEITEM, ZFile As String)
Declare Sub RemoveChild(TheTree As HWND, TVSel As HTREEITEM, RemoveItem As String)
Declare Function TV_InsertHere(TheTree As HWND, Parent As HTREEITEM, AfterChild As HTREEITEM, AddThis As String) As HTREEITEM

'from strwrap.bi
Declare Function str_numparse(ByRef source as string,ByRef delimiter as string) As Long
Declare Function str_parse(ByRef source As String,Byref delimiter As String,ByVal idx As Long) As String
Declare Function Str_replaceany(ByRef match As String,Byref sreplace As String,Byref source As String) As String
Declare Function str_ReplaceAnyAll(ByRef match As String,ByRef sreplace As String,ByRef source As String) As String

'Listview subs
Declare Sub LV_SetSelState(H As HWND,R As Integer,MakeSel As BOOL)
Declare Sub LVAddItem(hList As HWND, Rec As String,InZip As Integer=0)
Declare Sub IconicLVAddItem(LV As HWND, Stats As FileStats)
Declare Function LVGetValue(ByVal rr As HWND, ByVal item As Long, ByVal column As Long=0) As String
Declare Function lvFindItem(hList As HWND, Value As String) As Integer
Declare Sub LVSetMaxCols(ByVal rr As HWND,ByVal cols As Long)
Declare Sub LVSetHeader(lvHdl As HWND, ColNum As Long, txtItem As String, ColW As Long)
Declare Function AddFileStats(Info As FileStats) As String
Declare Sub SelAll(LV As HWND)
Declare Sub InvSel(L As HWND)
Declare Sub ViewOpenFile(L As HWND)
Declare Sub RClick(TheWin As HWND, TheLV As HWND, PopX As Integer, PopY As Integer)
Declare Sub HandlePopUpMenu(WhichLV As HWND,Selection As Integer)
Declare Sub GetFileListTop
Declare Sub RefreshTopLV
Declare Sub GetFileListBottom
Declare Sub RefreshBottomLV
Declare Function MyDir(pathspec As String="") As FileStats
Declare Function SelFileInfo(Lv As HWND,Sel As Integer) As FileStats
'Declare Function LV2ArrayInx(LV As HWND,Sel As Integer) As Integer

'sorts
'callback functions for the ListView_SortItems()
Declare Function SortFuncBoth(E1 As FileStats, E2 As FileStats, ByVal Col As Integer, Direction As Integer) As Integer
Declare Function SortFuncTop(I1 As LPARAM, I2 As LPARAM, ByVal C As LPARAM) As Integer
Declare Function SortFuncBottom(I1 As LPARAM, I2 As LPARAM, ByVal C As LPARAM) As Integer
'sorts for zip files display
Declare Function SortFuncTopZip(I1 As LPARAM, I2 As LPARAM, ByVal C As LPARAM) As Integer
Declare Function SortFuncBottomZip(I1 As LPARAM, I2 As LPARAM, ByVal C As LPARAM) As Integer

'file/folder subs
Declare Function hStripFileExt( ByVal filename As ZString Ptr ) As String
Declare Function hFilePath( ByVal filename As ZString Ptr ) As String
Declare Function hStripFilePath( ByVal filename As ZString Ptr ) As String
Declare Function My_Kill(FPath As String, FName As String, Confirm As BOOL, SkipIt As BOOL) As Integer
Declare Function MyMakeDir(Create As String) As String
Declare Function DoFCopy(F As String, T As String, FName As String) As Integer 'ExtendedIntRet
Declare Sub DoFileComm(FromLV As HWND, ToLV As HWND, Comm As String) 'change to function? ExtendedIntRet
Declare Function DoDirComm(F As String,T As String,D As String,C As String) As Integer 'ExtendedIntRet

'My Recycle bin
Declare Sub Recycle(LV As HWND)
Declare Sub DispRecycle(LV As HWND)
Declare Sub EmptyRecycle
Declare Function RestoreRecycle(LV As HWND,Rest As BOOL,SelAll As BOOL) As Integer
Declare Sub RecycleStatus

'Zip file
Declare Sub OpenZipFile(ZipName As String, TopV As BOOL)
Declare Sub CloseZip(TopV As BOOL)
Declare Sub RefreshTopZip
Declare Sub RefreshTopZipLV
Declare Sub RefreshBottomZip
Declare Sub RefreshBottomZipLV
Declare Sub DoZipFileComm(FromLV As HWND, ToLV As HWND, Comm As String)
Declare Function DeleteZDirTop(FoldSel As String) As Integer
Declare Function DeleteZDirBottom(FoldSel As String) As Integer
Declare Function ExtractZDirTop(FoldSel As String, ExtractPath As String) As Integer
Declare Function ExtractZDirBottom(FoldSel As String, ExtractPath As String) As Integer
Declare Sub create_parent_dirs(ByVal file As ZString Ptr)
Declare Sub ClearExtractFolder
Declare Sub FindZipInTree(UseTop As BOOL)
Declare Sub CreateNewZip(FromLV As HWND, MoveFlag As BOOL)

'FTP Declares in FTP_Control.bi (see note there)

'misc
Declare Sub SaveIni(As BOOL,As BOOL)
Declare Function LastErrorStr() As String
Declare Sub LogFTP(Ev As String)
Declare Sub ScrollFTP(D As Integer)
Declare Sub InitPopUpMenu
Declare Function SetIcon(CPath As String,FName As String,InZip As Integer) As Integer
Declare Function ToKB(ByVal NumBytes As ULongInt) As String
Declare Function GetTimeZone() As LongInt

'xterm's Directory walker
ReDim Shared As String DW_Files(0),DW_Folders(0)
Dim Shared As String Path_Delim 'assigned in UpdateTrees
'Path_Delim = Mid(ExePath,3,1) 'root of drive????? stored on flash drive???

Function DW_Dir(Fold As String) As Integer
	Dim As Integer RAtt,Ub
	Dim As String FName
	'
	FName = Dir(Fold+"*",55,@RAtt)
	While FName <> ""
		If (FName <> ".") And (FName <> "..") Then
			If RAtt And 16 Then
				'add to folder array
				Ub = UBound(DW_Folders)+1
				ReDim Preserve DW_Folders(Ub)
				DW_Folders(Ub) = Fold+FName+Path_Delim
			Else
				'add to file array
				Ub = UBound(DW_Files)+1
				ReDim Preserve DW_Files(Ub)
				DW_Files(Ub) = Fold+FName
			EndIf
		EndIf
		FName = Dir(@RAtt)
	Wend
	Return 0
End Function

Function DW_AllDir(RootP As String,Fold As String) As Integer
	Dim As String NextF
	Dim As Integer C
	'clear out any prior run
	ReDim As String DW_Files(0),DW_Folders(0)
	'save init folder
	DW_Folders(0) = RootP+Fold+Path_Delim
	'
	Do
		NextF = DW_Folders(C)
		DW_Dir(NextF)
		C += 1
	Loop Until C > UBound(DW_Folders)
	Return C
End Function

'bring in all the Contollers
#Include "DriveList.bi"
Dim Shared MyDrives As AllDrivesInfo

#Include Once "registry.bi"
#Include "Zip_Control.bi"
#Include "FTP_Control.bi"
#Include "LV_Control.bi"
#Include "Recycle_Control.bi"
#Include "TV_Control.bi"

Function DoFCopy(F As String, T As String, FName As String) As Integer
	Dim As String CheckF,CheckE,SugName
	Dim As Integer x
	'
	If FileExists(T+FName) Then
		'option to rename?
		CheckF = FName
		x = InStrRev(FName,".")
		If x Then
			'has extention
			CheckE = Mid(FName,x) ' holds the .txt
			CheckF = Left(FName,x-1)
		EndIf
		BadUserEntry:
		x = 1
		While FileExists(T+CheckF+" ["+Str(x)+"]"+CheckE)
			x+=1
		Wend
		strShare = CheckF+" ["+Str(x)+"]" 'pass to dlg
		SugName = strShare 'check for change
		'suggest one...ask for user to input
		DialogBoxParam(hInstance, Cast(ZString Ptr,IDD_DLGFExist), NULL, @FileDupDlgP, NULL)
		If strShare = "piks" Then
			'skip
			Return 1 'filecopy error
		EndIf
		If strShare = "revo" Then
			'overwrite
			Return FileCopy(F+FName,T+FName)
		EndIf
		If strShare <> SugName Then
			'user entered a new filename
			'check if this one exists
			If FileExists(T+strShare+CheckE) Then
				MessageBox(0,"The filename you entered is already in use","Confilct",MB_OK)
				GoTo BadUserEntry
			Else
				Return FileCopy(F+FName,T+strShare+CheckE)
			EndIf
		Else
			Return FileCopy(F+FName,T+SugName+CheckE)
		EndIf
		'
		Return 1 'Failed
	EndIf
	Return FileCopy(F+FName,T+FName)
End Function

Sub DoFileComm(FromLV As HWND, ToLV As HWND, Comm As String)
	Dim As String F,FromPath,ToPath
	Dim As Integer Sel,Proc,Ign 'counters
	Dim As Integer CopyFail,L
	Dim As HTREEITEM TVSel
	Dim As FileStats FStats
	'
	Dim As String ftpfile
	Dim As Double ftptime
	'
	'get count of selected files in FromLV
	Sel = SendMessage(FromLV,LVM_GETSELECTEDCOUNT,0,0)
	If Sel = 0 Then
		MessageBox(0,"No files selected!","Minor problem",MB_OK)
		Exit Sub
	EndIf
	'determine paths
	If FromLV = FTop(TopLVType) Then
		FromPath = wtTop
		ToPath = wtBottom
		If Connected Then ToPath = "FTP"
	Else
		FromPath = wtBottom
		If Connected Then FromPath = "FTP"
		ToPath = wtTop
	EndIf
	If FromLV = FTop(3) Then FromPath = TempExtractPath
	If ToLV = FTop(3) Then ToPath = TempExtractPath
	If FromLV = FBottom(3) Then FromPath = TempExtractPath
	If ToLV = FBottom(3) Then ToPath = TempExtractPath
	'
	F = "Moving" 'Comm = "moved"
	If Comm = "copied" Then F = "Copying"
	If Comm = "deleted" Then F = "Deleting"
	Dim As Integer WaitDlg = UnknownWait.StartIt(F+" files","Working","......")
	'
	'loop thru selections
	L = ListView_GetNextItem(FromLV, -1, LVNI_SELECTED)
	While L > -1
		FStats = SelFileInfo(FromLV,L)
		F = FStats.FName
		If (FStats.Att And 16) = 16 Then
			'folder
			If Comm = "deleted" And (FromLV = FTop(3) Or FromLV = FBottom(3)) Then
				'delete folder from zip
				If FromLV = FTop(3) Then
					CopyFail = DeleteZDirTop(F)
					If CopyFail = 0 Then
						'delete folder from tree(s)
						RemoveChild DTop, TreeView_GetSelection(DTop), F
						TopZip.Reload = TRUE
						'temp use this string
						ftpfile = TopZip.ZipFile + Path_Delim
						If Path_Delim <> "/" Then
							ftpfile += Str_replaceany("/",Path_Delim,TopZip.SubF)
						Else
							ftpfile += TopZip.SubF
						EndIf
						TVSel = FolderExistInTree(DBottom,ftpfile)
						If TVSel Then RemoveChild DBottom, TVSel, F
					EndIf
				Else
					CopyFail = DeleteZDirBottom(F)
					If CopyFail = 0 Then
						'delete folder from tree(s)
						RemoveChild DBottom, TreeView_GetSelection(DBottom), F
						BottomZip.Reload = TRUE
						'temp use this string
						ftpfile = BottomZip.ZipFile + Path_Delim
						If Path_Delim <> "/" Then
							ftpfile += Str_replaceany("/",Path_Delim,BottomZip.SubF)
						Else
							ftpfile += BottomZip.SubF
						EndIf
						TVSel = FolderExistInTree(DTop,ftpfile)
						If TVSel Then RemoveChild DTop, TVSel, F
					EndIf
				EndIf
			Else
				If FromLV = FBottom(3) Then
					If ToLV = FTop(3) Then
						'MessageBox(0,"copy folder from bottom to top","Zip to Zip",MB_OK)
						CopyFail = Zip2Zip_FolderBT(F)
						If CopyFail = 0 Then TopZip.Reload = TRUE
					Else
						'bottom zip extract to local
						CopyFail = ExtractZDirBottom(F,ToPath)
					EndIf
					'add folder to top tree
					If CopyFail = 0 Then
						TVSel = TreeView_GetSelection(DTop)
						TVSel = PutTree(F,TVSel,0)
						'add to bottom if needed
						TVSel = FolderExistInTree(DBottom,ToPath)
						If TVSel Then PutTree(F,TVSel,1)
					EndIf
				Else
					If ToPath = "FTP" Or FromPath = "FTP" Then
						CopyFail = 0
						'extract from zip then upload folder to FTP?
						If FromLV = FTop(3) Then CopyFail = ExtractZDirTop(F,FromPath) 'ToPath = "FTP"
						'do upload or download
						If CopyFail = 0 Then CopyFail = FTPDirComm(FromPath,ToPath,F,Comm)
						If CopyFail = 0 Then ftp.LastFTP = Timer
						'downloading folder to zip?
						If ToLV = FTop(3) And CopyFail = 0 Then
							CopyFail = AddDirZip(TopZip,F,ToPath) 'FromPath = "FTP"
							'add folder to top tree
							If CopyFail > 0 Then
								TVSel = TreeView_GetSelection(DTop)
								TVSel = PutTree(F,TVSel,0)
								'Check4Children(DTop,TVSel,FALSE)
								TopZip.Reload = TRUE
								CopyFail = 0
								'even though connected still want to update bottom tree
								'temp use this string
								ftpfile = TopZip.ZipFile + Path_Delim
								If Path_Delim <> "/" Then
									ftpfile += Str_replaceany("/",Path_Delim,TopZip.SubF)
								Else
									ftpfile += TopZip.SubF
								EndIf
								TVSel = FolderExistInTree(DBottom,ftpfile)
								If TVSel Then PutTree(F,TVSel,1)
							EndIf
						EndIf
					Else
						If FromLV = FTop(3) Then
							If ToLV = FBottom(3) Then
								'MessageBox(0,"copy folder from top to bottom","Zip to Zip",MB_OK)
								CopyFail = Zip2Zip_FolderTB(F)
								If CopyFail = 0 Then BottomZip.Reload = TRUE
							Else
								'top zip extract to local
								CopyFail = ExtractZDirTop(F,ToPath)
							EndIf
							'add folder to bottom tree
							If CopyFail = 0 Then
								TVSel = TreeView_GetSelection(DBottom)
								TVSel = PutTree(F,TVSel,1)
								TVSel = FolderExistInTree(DTop,ToPath)
								If TVSel Then PutTree(F,TVSel,0)
							EndIf
						Else
							If ToLV = FTop(3) Then
								'local to top zip
								CopyFail = AddDirZip(TopZip,F,FromPath)
								'add folder to top tree
								If CopyFail > 0 Then
									TVSel = TreeView_GetSelection(DTop)
									TVSel = PutTree(F,TVSel,0)
									'Check4Children(DTop,TVSel,FALSE)
									TopZip.Reload = TRUE
									CopyFail = 0
									'move to zip (delete source)
									If Comm = "moved" Then
										'finalize before deletion of file
										ReLoadZip TopZip
										TopZip.Reload = FALSE
										CopyFail = DoDirComm(FromPath,FromPath,F,"deleted")
									EndIf
								EndIf
							ElseIf ToLV = FBottom(3) Then
								'local to bottom zip
								CopyFail = AddDirZip(BottomZip,F,FromPath)
								'add folder to bottom tree
								If CopyFail > 0 Then
									TVSel = TreeView_GetSelection(DBottom)
									TVSel = PutTree(F,TVSel,1)
									'Check4Children(DBottom,TVSel,FALSE)
									BottomZip.Reload = TRUE
									CopyFail = 0
									'move to zip (delete source)
									If Comm = "moved" Then
										'finalize before deletion of file
										ReLoadZip BottomZip
										BottomZip.Reload = FALSE
										CopyFail = DoDirComm(FromPath,FromPath,F,"deleted")
									EndIf
								EndIf
							Else
								'normal folder handling
								CopyFail = DoDirComm(FromPath,ToPath,F,Comm)
							EndIf
						EndIf
					EndIf
				EndIf
			EndIf
			If CopyFail Then
				Ign += 1
			Else
				Proc += 1
			EndIf
		Else
			'a file
			Select Case Comm
				Case "copied"
					'copy the file
					If ToPath = "FTP" Then
						CopyFail = 0
						If FromLV = FTop(3) Then CopyFail = ExtractZFile(TopZip,F,FromPath,FALSE)
						'If FromLV = FBottom(3) Then CopyFail = ExtractZFile(BottomZip,F,FromPath,FALSE) 'should not happen
						If CopyFail = 0 Then CopyFail = Not(ftp_putfile(@ftp,FromPath+F,F)) 'ftp_putfile returns 0 if Error
						If CopyFail Then
							LogFTP FromPath+F+" upload fail."
							LogFTP LastErrorStr()
						Else
							LogFTP F+" upload success."
							ftp.LastFTP = Timer
						EndIf
					Else
						If FromPath = "FTP" Then
							CopyFail = ftp_getfile(@ftp,F,ToPath+F) 'returns 0 if Error
							If CopyFail Then
								CopyFail = 0
								LogFTP F+" download success."
								ftp.LastFTP = Timer
								If ToLV = FTop(3) Then
									'download file straight to zip file
									CopyFail = AddFileZip(TopZip,F,ToPath)
									'If CopyFail = 0 Then TopZip.Reload = TRUE
									If CopyFail = 0 Then
										CopyFail = 1
									ElseIf CopyFail = 2 Then
										'user choose not to replace
										CopyFail = 0
									Else
										'added or replaced
										CopyFail = 0
										TopZip.Reload = TRUE
									EndIf
								ElseIf UCase(Right(F,4)) = ".ZIP" Then
									'downloaded a zip file
									TVSel = TreeView_GetSelection(DTop)
									TVSel = PutTree(F,TVSel,0)
									'add to bottom if needed
									TVSel = FolderExistInTree(DBottom,ToPath)
									If TVSel Then PutTree(F,TVSel,1)
								EndIf
							Else
								CopyFail = 1
								LogFTP F+" download fail."
								LogFTP LastErrorStr()
							EndIf
						Else
							If ToLV = FTop(3) Then
								If FromLV = FBottom(3) Then
									'MessageBox(0,"Copy file from bottom to top","Zip to Zip",MB_OK)
									CopyFail = Zip2Zip(BottomZip,TopZip,F)
									If CopyFail = 0 Then TopZip.Reload = TRUE
								Else
									CopyFail = AddFileZip(TopZip,F,FromPath)
									If CopyFail = 0 Then
										CopyFail = 1
									ElseIf CopyFail = 2 Then
										'user choose not to replace
										CopyFail = 0
									Else
										'added or replaced
										CopyFail = 0
										TopZip.Reload = TRUE
									EndIf
								EndIf
							ElseIf ToLV = FBottom(3) Then
								If FromLV = FTop(3) Then
									'MessageBox(0,"Copy file from top to bottom","Zip to Zip",MB_OK)
									CopyFail = Zip2Zip(TopZip,BottomZip,F)
									If CopyFail = 0 Then BottomZip.Reload = TRUE
								Else
									CopyFail = AddFileZip(BottomZip,F,FromPath)
									If CopyFail = 0 Then
										CopyFail = 1
									ElseIf CopyFail = 2 Then
										'user choose not to replace
										CopyFail = 0
									Else
										'added or replaced
										CopyFail = 0
										BottomZip.Reload = TRUE
									EndIf
								EndIf
							Else
								CopyFail = DoFCopy(FromPath,ToPath,F) 'returns 1 if error
							EndIf
						EndIf
					EndIf
					If CopyFail Then
						Ign += 1
					Else
						Proc += 1
						'copy of zip file?
					EndIf
					'
				Case "moved"
					'copy the file
					'no move to/from zip
					If ToPath = "FTP" Then
						CopyFail = ftp_putfile(@ftp,FromPath+F,F) 'returns 0 if Error
						If CopyFail Then
							CopyFail = 0
							LogFTP F+" upload success."
							ftp.LastFTP = Timer
						Else
							CopyFail = 1
							LogFTP FromPath+F+" upload fail."
							LogFTP LastErrorStr()
						EndIf
					Else
						If FromPath = "FTP" Then
							CopyFail = ftp_getfile(@ftp,F,ToPath+F) 'returns 0 if Error
							If CopyFail Then
								CopyFail = 0
								LogFTP F+" download success."
								ftp.LastFTP = Timer
								If ToLV = FTop(3) Then
									CopyFail = AddFileZip(TopZip,F,ToPath)
									If CopyFail = 0 Then
										CopyFail = 1
									ElseIf CopyFail = 2 Then
										'user choose not to replace
										CopyFail = 0
									Else
										'added or replaced
										CopyFail = 0
										'TopZip.Reload = TRUE
										'finalize before deletion of file
										ReLoadZip TopZip
										TopZip.Reload = FALSE
									EndIf
								EndIf
							Else
								CopyFail = 1
								LogFTP F+" download fail."
								LogFTP LastErrorStr()
							EndIf
						Else
							If ToLV = FTop(3) Then
								'missed a check somewhere?
								CopyFail = 1
								'If FromLV = FBottom(3) Then
								'	'MessageBox(0,"Move file from bottom to top","Zip to Zip",MB_OK)
								'	'CopyFail = Zip2Zip(BottomZip,TopZip,F) 
								'	CopyFail = 1
								'Else
								'	CopyFail = AddFileZip(TopZip,F,FromPath)
								'	If CopyFail = 0 Then
								'		CopyFail = 1
								'	ElseIf CopyFail = 2 Then
								'		'user choose not to replace
								'		CopyFail = 0
								'	Else
								'		'added or replaced
								'		CopyFail = 0
								'		'TopZip.Reload = TRUE
								'		'finalize before deletion of file
								'		ReLoadZip TopZip
								'		TopZip.Reload = FALSE
								'	EndIf
								'EndIf
							ElseIf ToLV = FBottom(3) Then
								'missed a check somewhere?
								CopyFail = 1
								'If FromLV = FTop(3) Then
								'	'MessageBox(0,"Move file from top to bottom","Zip to Zip",MB_OK)
								'	'missed a check somewhere?
								'	'CopyFail = Zip2Zip(TopZip,BottomZip,F)
								'	CopyFail = 1
								'Else
								'	CopyFail = AddFileZip(BottomZip,F,FromPath)
								'	If CopyFail = 0 Then
								'		CopyFail = 1
								'	ElseIf CopyFail = 2 Then
								'		'user choose not to replace
								'		CopyFail = 0
								'	Else
								'		'added or replaced
								'		CopyFail = 0
								'		BottomZip.Reload = TRUE
								'	EndIf
								'EndIf
							Else
								CopyFail = DoFCopy(FromPath,ToPath,F) 'returns 1 if error
							EndIf
						EndIf
					EndIf
					'delete
					If CopyFail Then
						Ign += 1
					Else
						If FromPath <> "FTP" Then
							CopyFail = My_Kill(FromPath,F,FALSE,FALSE)
							'moved a "whole" zip file
							If LCase(Right(F,4)) = ".zip" And CopyFail < 4 Then
								'remove from tree
								RemoveChild DTop, TreeView_GetSelection(DTop), F
							EndIf
						Else
							'delete ftpfile
							CopyFail = ftp_deletefile(@ftp,F)
							If CopyFail = 0 Then
								CopyFail = 4 'failed
								LogFTP F+" delete fail."
								LogFTP LastErrorStr()
							Else
								CopyFail = 0 'success
								LogFTP F+" delete success."
								ftp.LastFTP = Timer
							EndIf
						EndIf
						If CopyFail < 4 Then
							Proc += 1
						Else
							Ign += 1
						EndIf
					EndIf
					'
				Case "deleted"
					'delete
					If FromPath <> "FTP" Then
						If FromLV = FTop(3) Then
							CopyFail = DeleteZFile(TopZip,F)
							If CopyFail = 0 Then TopZip.Reload = TRUE
						ElseIf FromLV = FBottom(3) Then
							CopyFail = DeleteZFile(BottomZip,F)
							If CopyFail = 0 Then BottomZip.Reload = TRUE
						Else
							'local delete file
							CopyFail = My_Kill(FromPath,F,FALSE,FALSE)
							If CopyFail < 4 Then
								CopyFail = 0
							EndIf
						EndIf
					Else
						'delete ftpfile
						CopyFail = ftp_deletefile(@ftp,F)
						If CopyFail = 0 Then
							CopyFail = 4 'failed
							LogFTP F+" delete fail."
							LogFTP LastErrorStr()
						Else
							CopyFail = 0 'success
							LogFTP F+" delete success."
							ftp.LastFTP = Timer
						EndIf
					EndIf
					If CopyFail < 4 Then
						Proc += 1
					Else
						Ign += 1
					EndIf
					'
			End Select
		EndIf
		L = ListView_GetNextItem(FromLV, L, LVNI_SELECTED)
		If TopZip.ZipPtr <> NULL Or BottomZip.ZipPtr <> NULL Then ClearExtractFolder
	Wend
	If WaitDlg Then UnknownWait.KillIt
	'refresh listviews
	'file delete only?
	If Comm <> "copied" Then
		'deleted or moved from
		Select Case FromPath
			Case "FTP"
				RefreshFTPFiles @ftp
			Case wtTop
				GetFileListTop
			Case wtBottom
				GetFileListBottom
			Case Else
				'zip file delete only
				If FromLV = FTop(3) Then
					ReLoadZip TopZip
					TopZip.Reload = FALSE
					RefreshTopZip
				Else
					ReLoadZip BottomZip
					BottomZip.Reload = FALSE
					RefreshBottomZip
				EndIf
		End Select
	EndIf
	'both windows involved?
	If Comm <> "deleted" Then
		'copy or moved to
		Select Case ToPath
			Case "FTP"
				RefreshFTPFiles @ftp
			Case wtTop
				GetFileListTop
			Case wtBottom
				GetFileListBottom
			Case Else
				'zip file
				If ToLV = FTop(3) Then
					If TopZip.Reload Then ReLoadZip TopZip
					TopZip.Reload = FALSE
					RefreshTopZip
				Else
					If TopZip.Reload Then ReLoadZip BottomZip
					BottomZip.Reload = FALSE
					RefreshBottomZip
				EndIf
		End Select
	EndIf
	If Proc = Sel Then
		F = Str(Proc)+" item(s) "+Comm+"."
	Else
		F = "Of the "+Str(Sel)+" item(s) selected,"+Chr(13)
		F+= Str(Ign)+" were skipped,"+Chr(13)
		F+= Str(Proc)+" "+Comm+"."
	EndIf
	MessageBox(0,F,"Results",MB_OK)
End Sub

Function DoDirComm(F As String,T As String,D As String,C As String) As Integer
	Dim As Integer LL,ErrorCode
	Dim As String W,PassFrom,PassTo,PassFile
	Dim As HTREEITEM Sel', SelHold
	Dim As HWND TreeF, TreeT, NotAssigned
	'
	W = "Moving"
	If C = "copied" Then W = "Copying"
	If C = "deleted" Then W = "Deleting"
	'Dim As UnknownWaitDlg JustWaitDir = UnknownWaitDlg(W+" directories","Working","......")
	Dim As Integer WaitDlg = UnknownWait.StartIt(W+" directories","Working","......")
	'
	'get all folders and files
	LL = DW_AllDir(F,D)
	'
	If F = wtTop Then TreeF = DTop
	If F = wtBottom Then TreeF = DBottom
	If T = wtTop Then TreeT = DTop
	If T = wtBottom Then TreeT = DBottom
	'
	If C = "copied" Or C = "moved" Then
		'create needed folders
		For LL = 0 To UBound(DW_Folders)
			W = Mid(DW_Folders(LL),Len(F)+1)
			W = Left(W,Len(W)-1)
			MkDir T+W
			'normal copy/move -- add to tree
			If TreeT <> NotAssigned And TreeF <> NotAssigned Then
				Sel = TreeView_GetSelection(TreeT)
				While InStr(W,Path_Delim)
					Sel = TreeView_GetChild(TreeT,Sel)
					While TreeView_GetItemText(TreeT, Sel) <> Left(W,InStr(W,Path_Delim)-1)
						Sel = TreeView_GetNextSibling(TreeT,Sel)
					Wend
					W = Mid(W,InStr(W,Path_Delim)+1)
				Wend
				'add here
				If TreeT = DBottom Then
					Sel = PutTree(W,Sel,1)
				Else
					Sel = PutTree(W,Sel,0)
				EndIf
			EndIf
			'moving from trash, the from or to dir may not be available
			If TreeF = NotAssigned Then
				'check both trees to see if can add
				W = T+W
				ErrorCode = InStrRev(W,Path_Delim,Len(W)-2)
				PassTo = Left(W,ErrorCode)
				PassFile = Mid(W,ErrorCode+1)
				Sel = FolderExistInTree(DBottom,PassTo)
				If Sel Then PutTree(PassFile,Sel,1)
				Sel = FolderExistInTree(DTop,PassTo)
				If Sel Then PutTree(PassFile,Sel,0)
			EndIf
		Next
		'copy files
		For LL = 1 To UBound(DW_Files)
			ErrorCode = InStrRev(DW_Files(LL),Path_Delim)
			PassFile = Mid(DW_Files(LL),ErrorCode+1)
			PassFrom = Left(DW_Files(LL),ErrorCode)
			W = T+Mid(DW_Files(LL),Len(F)+1)
			PassTo = Left(W,InStrRev(W,Path_Delim))
			ErrorCode = DoFCopy(PassFrom,PassTo,PassFile)
			If ErrorCode Then
				'DebugMe "Copy Error of file in DoDirComm"
				'DebugMe PassFrom
				'DebugMe PassTo
				'DebugMe PassFile
				Return 1
			EndIf
		Next
	EndIf
	If C = "moved" Or C = "deleted" Then
		'delete files first
		Dim As BOOL Ask = TRUE
		Dim As BOOL Skip = FALSE
		If C = "moved" Then Ask = FALSE
		'
		For LL = 1 To UBound(DW_Files)
			ErrorCode = InStrRev(DW_Files(LL),Path_Delim)
			PassFile = Mid(DW_Files(LL),ErrorCode+1)
			PassFrom = Left(DW_Files(LL),ErrorCode)
			'ErrorCode = Kill(DW_Files(LL))
			ErrorCode = My_Kill(PassFrom,PassFile,Ask,Skip)
			'0 - deleted -- no attr
			'1 - deleted -- Ask = false
			'2 - deleted -- checked
			'3 - deleted -- unchecked
			'4 - Skipped -- checked or Ask=false
			'5 - skipped -- unchecked
			If ErrorCode = 2 Or ErrorCode = 4 Then Ask = FALSE
			If ErrorCode > 3 Then Skip = TRUE
		Next
		'Remove in REVERSE order
		For LL = UBound(DW_Folders) To 0 Step -1
			'count entries
			ErrorCode = 0
			W = Dir(DW_Folders(LL)+"*.*",fbDirectory And fbArchive)
			While Len(W)
				ErrorCode += 1
				W = Dir()
			Wend
			If ErrorCode < 3 Then
				RmDir Left(DW_Folders(LL),Len(DW_Folders(LL))-1)
				'normal move/delete or sending to trash -- remove from tree
				If TreeF <> NotAssigned Then
					W = Mid(DW_Folders(LL),Len(F)+1)
					W = Left(W,Len(W)-1)
					'
					Sel = TreeView_GetSelection(TreeF)
					While InStr(W,Path_Delim)
						Sel = TreeView_GetChild(TreeF,Sel)
						While TreeView_GetItemText(TreeF, Sel) <> Left(W,InStr(W,Path_Delim)-1)
							Sel = TreeView_GetNextSibling(TreeF,Sel)
						Wend
						W = Mid(W,InStr(W,Path_Delim)+1)
					Wend
					'found parent of the one to delete
					Sel = TreeView_GetChild(TreeF,Sel)
					While TreeView_GetItemText(TreeF, Sel) <> W
						Sel = TreeView_GetNextSibling(TreeF,Sel)
					Wend
					'delete this one
					TreeView_DeleteItem(TreeF,Sel)
				EndIf
				'If TreeF = NotAssigned Then 'moving from trash -- no need to remove from trees
				If TreeT = NotAssigned Then
					'sending dir to trash -- TreeF IS VALID
					'check other to see if can remove
					If TreeF = DTop Then
						Sel = FolderExistInTree(DBottom,DW_Folders(LL))
						If Sel Then TreeView_DeleteItem(DBottom,Sel)
					Else
						Sel = FolderExistInTree(DTop,DW_Folders(LL))
						If Sel Then TreeView_DeleteItem(DTop,Sel)
					EndIf
				EndIf
				Sleep 10
			EndIf
		Next
	EndIf
	'
	If WaitDlg Then UnknownWait.KillIt
	ReDim DW_Folders(0),DW_Files(0)
	Return 0
End Function

Sub SaveIni(SOX As BOOL,KeepFTP As BOOL)
	Dim As Integer a = FreeFile
	Open "DDir.ini" For Output As #a
	Print #a, wtTop
	Print #a, wtBottom
	Print #a, SOX 'save on exit flag
	Print #a, KeepDirTop
	Print #a, GroupDir
	Print #a, KeepFTP
	Close #a
End Sub

Function MyMakeDir(Create As String) As String
	'this is only used in "RestoreRecycle" function
	Dim As Integer L=1
	Dim As String f,there
	'may need this string in main prg, and make path delimiters /
	Dim As String Make = str_ReplaceAnyAll("\","/",Create)
	'
	If InStr(Make,"/") = 0 Then
		'just a simple MkDir
		MkDir(Make)
		Function = Make
	Else
		'find out where to start
		Do
			f = str_parse(Make,"/",L)
			there = Dir(f,16)
			If there = "" Then Exit Do
			ChDir(there)
			L += 1
		Loop
		'L is now position to start creating and f holds folder to create
		Function = f 'send back the name of first folder created
		While f <> ""
			MkDir(f)
			ChDir(f)
			L += 1
			f = str_parse(Make,"/",L)
		Wend
		'ChDir(CD)
	EndIf
End Function

Function My_Kill(FPath As String, FName As String, Confirm As BOOL,SkipIt As BOOL) As Integer
	Dim As Integer FAtt,DlgRet
	Dim As String MsgText = FPath+FName
	'
	FAtt = GetFileAttributes(StrPtr(MsgText))
	'
	If (FAtt And 7) Then
		'double check if want to delete
		If Confirm Then
			'ask
			strShare = FName + Chr(13,10) + "has the following attribute(s):"
			If FAtt And fbHidden Then
				strShare += Chr(13,10) + "Hidden"
			EndIf
			If FAtt And fbSystem Then
				strShare += Chr(13,10) + "System"
			EndIf
			If FAtt And fbReadOnly Then
				strShare += Chr(13,10) + "Read Only"
			EndIf
			DlgRet = DialogBoxParam(hInstance, Cast(ZString Ptr,IDD_DLGFileDelConfirm), NULL, @ConfDelDlg, NULL)
			If DlgRet < 4 Then
				'pressed Del button
				SetFileAttributes(FPath+FName,FILE_ATTRIBUTE_ARCHIVE)
				Kill FPath+FName
			EndIf
			'MessageBox(0,Str(DlgRet),"Return Code",MB_OK)
			Return DlgRet
		Else
			If SkipIt Then
				Return 4
			EndIf
			'set and del
			SetFileAttributes(FPath+FName,FILE_ATTRIBUTE_ARCHIVE)
			Kill FPath+FName
			Return 1 'deleted because prior confirmation
		EndIf
	Else
		'del -- no special attributes for this file
		Kill FPath+FName
		Return 0 'normal delete
	EndIf
End Function

Function LastErrorStr() As String
	Dim As String * 1024 buffer
	Dim As Integer p
	'
	FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,_
	0,_
	GetLastError(),_
	0,_
	StrPtr( buffer ),_
	1024,_
	0 )
	'
	buffer = RTrim( buffer )
	p = InStr( buffer, Chr(13) )
	If p Then buffer = Left( buffer, p - 1 )
	'
	Return buffer
End Function

Sub LogFTP(Ev As String)
	'DebugFile "FTP",Ev
	'
	Dim As Integer x
	Static As Integer TotEvents
	' add to session log file
	x = FreeFile
	Open ExePath + Path_Delim + "FTPSession.txt" For Append As #x
	Print #x, Time+" "+Ev
	Close #x
	'
	'keep count of events here
	If Left(Ev,7) = "Connect" Then
		TotEvents = 1
	Else
		TotEvents += 1
	EndIf
	ScrollFTP TotEvents 'force last event to show
End Sub

Sub ScrollFTP(D As Integer)
	'Hoping later to make a scrollable area to display
	Dim As Integer x,h
	Dim As String R,B
	' open session log file
	h = FreeFile
	Open ExePath + Path_Delim + "FTPSession.txt" For Input As #h
	For x = 1 To D
		Line Input #h, R
		'display last 7 entries
		If x + 7 > D Then
			B += R + Chr(13)
		EndIf
	Next
	Close #h
	SetWindowText(FTPStats,B)
End Sub

'create sub menu for "New"
Sub InitPopUpMenu
	Dim As ZString * MAX_PATH WDir
	Dim As String FF
	Dim As Integer x
	'reading registry
	Dim As DWORD dwIdx
	Dim As FILETIME fTime
	Dim As HKEY hKeyMain
	'
	NewFMenu(1).MenuDisp = "Folder"
	'Look for blank files to copy, THESE DO NOT HAVE "ShellNew" IN REGISTRY!
	GetWindowsDirectory(@WDir,MAX_PATH)
	WDir += Path_Delim + "ShellNew" + Path_Delim
	FF = Dir(WDir + "*",32)
	While FF <> ""
		x = UBound(NewFMenu)+1
		ReDim Preserve NewFMenu(1 To x)
		NewFMenu(x).BlankFile = WDir + FF
		dwIdx = InStrRev(FF,".")
		NewFMenu(x).Ext = Mid(FF,dwIdx)
		FF = Dir() 'I always forget to put this in!!!!
	Wend
	'
	dwIdx=0
	If RegOpenKeyEx(HKEY_CLASSES_ROOT, "", 0, KEY_ENUMERATE_SUB_KEYS, @hKeyMain) = ERROR_SUCCESS Then
		Do
			Dim As Zstring*MAX_PATH szKeyName
			Dim As DWORD dwKeySize=MAX_PATH
			If RegEnumKeyEx(hKeyMain, dwIdx, szKeyName, @dwKeySize, NULL, NULL, NULL, @fTime) <> ERROR_SUCCESS Then Exit Do
			Dim As HKEY hSubKey
			If RegOpenKeyEx(hKeyMain, szKeyName, 0, KEY_READ, @hSubKey) = ERROR_SUCCESS Then
				If Left(szKeyName,1) = "." Then
					Dim As HKEY hShellNewTest
					If RegOpenKeyEx(hSubKey, StrPtr("ShellNew"), 0, KEY_READ, @hShellNewTest) = ERROR_SUCCESS Then
						RegCloseKey(hShellNewTest)
						'Registered in MS Explorer
						'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\
						FF = "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" + szKeyName
						If RegOpenKeyEx(HKEY_CURRENT_USER, FF, 0, KEY_READ, @hShellNewTest) = ERROR_SUCCESS Then
							RegCloseKey(hShellNewTest)
							'get default value, if any
							x = 1024
							Dim As ZString * 1024 KValue
							If RegQueryValueEx(hSubKey, StrPtr(""), NULL, NULL, @KValue, @x) = ERROR_SUCCESS Then
								x = UBound(NewFMenu)+1
								ReDim Preserve NewFMenu(1 To x)
								NewFMenu(x).Ext = szKeyName 'extention
								NewFMenu(x).MenuDisp = KValue 'RegKey for "descriptive" txt
							EndIf
						EndIf
					Else
						'did we already "find" it?
						For x = 2 To UBound(NewFMenu)
							If LCase(NewFMenu(x).Ext) = LCase(szKeyName) Then
								'get default value, if any
								Dim As Integer y = 1024
								Dim As ZString * 1024 KValue
								If RegQueryValueEx(hSubKey, StrPtr(""), NULL, NULL, @KValue, @y) = ERROR_SUCCESS Then NewFMenu(x).MenuDisp = KValue 'RegKey for "descriptive" txt
							EndIf
						Next
					EndIf
				Else
					'see if this is a "Description" that I want
					x = 1024
					Dim As ZString * 1024 KValue
					If RegQueryValueEx(hSubKey, StrPtr(""), NULL, NULL, @KValue, @x) = ERROR_SUCCESS Then
						For x = 2 To UBound(NewFMenu)
							If NewFMenu(x).MenuDisp = szKeyName Then
								NewFMenu(x).MenuDisp = KValue '"descriptive" txt
							EndIf
						Next
					EndIf
					'
				EndIf
				RegCloseKey(hSubKey)
			EndIf
			dwIdx += 1
		Loop
		RegCloseKey(hKeyMain)
	EndIf
End Sub

'return path of file -- no ending slash returned
Function hFilePath( ByVal filename As ZString Ptr ) As String
	Dim As Integer lp, p
	''
	lp = 0
	Do
		p = InStr( lp+1, *filename, Any "\/" )
		If p=0 Then
			Exit Do
		End If
		lp = p
	Loop
	''
	If( lp > 0 ) Then
		Function = Left( *filename, lp-1 )
	Else
		Function = *filename
	End If
End Function

'returns xxxx.xx from full path spec
Function hStripFilePath( ByVal filename As ZString Ptr ) As String
	Dim As Integer lp, p
	''
	lp = 0
	Do
		p = InStr( lp+1, *filename, Any "\/" )
		If p=0 Then
			Exit Do
		End If
		lp = p
	Loop
	''
	If( lp > 0 ) Then
		Function = Mid( *filename, lp+1 )
	Else
		Function = *filename
	End If
End Function

'returns file name only
Function hStripFileExt( ByVal filename As ZString Ptr ) As String
	Dim p As Integer, lp As Integer
	''
	lp = 0
	Do
		p = InStr( lp+1, *filename, "." )
		If( p = 0 ) Then
			Exit Do
		End If
		lp = p
	Loop
	''
	If( lp > 0 ) Then
		Function = Left( *filename, lp-1 )
	Else
		Function = *filename
	End If
End Function

Function SetIcon(CPath As String,FName As String,InZip As Integer) As Integer
	'InZip started as BOOL, but needed to specify if checking for file or folder
	If InZip = 2 Then Return 1 'folder in a zip file
	'
	Dim As ICONINFO iconData
	Dim As HICON hIcon,hIconSm
	Dim As String iconPath
	Dim As Integer x
	'
	If CPath = "INIT" Then
		'no extention
		iconPath = ReadRegistry(HKEY_CLASSES_ROOT, "\Unknown\DefaultIcon", "")
		x = Val(Mid(iconPath, InStrRev(iconPath, ",")+1))
		iconPath = Trim(Left(iconPath, InStrRev(iconPath, ",")-1), Any """")
		If ExtractIconEx(iconPath, x, @hIcon, 0, 1) <> 1 Then ExtractIconEx("C:\WINDOWS\System32\shell32.dll", 0, @hIcon, 0, 1)
		GetIconInfo(hIcon, @iconData)
		ImageList_Add(icons, iconData.hbmColor, iconData.hbmMask)
		DestroyIcon(hIcon)
		hIcon = NULL
		'
		If ExtractIconEx(iconPath, x, 0, @hIconSm, 1) <> 1 Then ExtractIconEx("C:\WINDOWS\System32\shell32.dll", 0, 0, @hIconSm, 1)
		GetIconInfo(hIconSm, @iconData)
		ImageList_Add(smicons, iconData.hbmColor, iconData.hbmMask)
		DestroyIcon(hIconSm)
		hIconSm = NULL
		'folder
		iconPath = ReadRegistry(HKEY_CLASSES_ROOT, "\Folder\DefaultIcon", "")
		x = Val(Mid(iconPath, InStrRev(iconPath, ",")+1))
		iconPath = Trim(Left(iconPath, InStrRev(iconPath, ",")-1), Any """")
		If ExtractIconEx(iconPath, x, @hIcon, 0, 1) <> 1 Then ExtractIconEx("C:\WINDOWS\System32\shell32.dll", 0, @hIcon, 0, 1)
		GetIconInfo(hIcon, @iconData)
		ImageList_Add(icons, iconData.hbmColor, iconData.hbmMask)
		DestroyIcon(hIcon)
		hIcon = NULL
		'
		If ExtractIconEx(iconPath, x, 0, @hIconSm, 1) <> 1 Then ExtractIconEx("C:\WINDOWS\System32\shell32.dll", 0, 0, @hIconSm, 1)
		GetIconInfo(hIconSm, @iconData)
		ImageList_Add(smicons, iconData.hbmColor, iconData.hbmMask)
		DestroyIcon(hIconSm)
		hIconSm = NULL
		'
		SendMessage(FTop(0), LVM_SETIMAGELIST, LVSIL_SMALL, Cast(LPARAM, smicons))
		SendMessage(FTop(1), LVM_SETIMAGELIST, LVSIL_NORMAL, Cast(LPARAM, icons))
		SendMessage(FTop(2), LVM_SETIMAGELIST, LVSIL_SMALL, Cast(LPARAM, smicons))
		SendMessage(FTop(3), LVM_SETIMAGELIST, LVSIL_SMALL, Cast(LPARAM, smicons))
		'
		SendMessage(FBottom(0), LVM_SETIMAGELIST, LVSIL_SMALL, Cast(LPARAM, smicons))
		SendMessage(FBottom(1), LVM_SETIMAGELIST, LVSIL_NORMAL, Cast(LPARAM, icons))
		SendMessage(FBottom(2), LVM_SETIMAGELIST, LVSIL_SMALL, Cast(LPARAM, smicons))
		SendMessage(FBottom(3), LVM_SETIMAGELIST, LVSIL_SMALL, Cast(LPARAM, smicons))
		Return 0
	EndIf
	'
	Dim As String Ext
	x = InStrRev(FName,".")
	If x Then
		Ext = Mid(FName,x) 'need the "."
	Else
		'pull a quick "dir" to see if it is a folder
		Ext = Dir(CPath+FName,16,@x)
		If Len(Ext) = 0 Or (x And 16) = 0 Then Return 0
		'is a folder
		Return 1
	EndIf
	'check to see if already have an icon
	For x = 0 To UBound(FileIcons)
		If FileIcons(x) = Ext Then Return x
		If FileIcons(x) = CPath+FName Then Return x
	Next
	'check if we "KNOW" there is no icon
	For x = 0 To UBound(NoIcons)
		If NoIcons(x) = Ext Then Return 0
		If NoIcons(x) = CPath+FName Then Return 0
	Next
	'
	'Assume that if it has a large, will have small?
	If LCase(Ext) = ".exe" Then
		'extract from prg?
		If InZip Then Return 0 'the file does not actually exist
		Ext = CPath+FName
		ExtractIconEx(Ext, 0, @hIcon, 0, 1)
		ExtractIconEx(Ext, 0, 0, @hIconSm, 1)
		'ElseIf LCase(Ext) = ".ico" Then
		'Ext = CPath+FName
		'
	Else
		'registry can be very fickle!!! Ext may be .bas, but registry has .Bas
		iconPath = ReadRegistry(HKEY_CLASSES_ROOT, "\" & ReadRegistry(HKEY_CLASSES_ROOT, Ext, "") & "\DefaultIcon", "")
		'Print "Extention: ";Ext
		x = Val(Mid(iconPath, InStrRev(iconPath, ",")+1))
		iconPath = Trim(Left(iconPath, InStrRev(iconPath, ",")-1), Any """")
		If iconPath = "" Then
			If InZip Then Return 0 'the file does not actually exist
			'do it the "hard way"
			Dim As String AsscPrg = Space(MAX_PATH + 1)
			Dim As HINSTANCE Ret = FindExecutable(StrPtr(FName),StrPtr(CPath),StrPtr(AsscPrg))
			Select Case CInt(Ret)
				Case 0
					MessageBox(0,"The system is out of memory or resources.","Error - Find associated Program",MB_OK Or MB_ICONERROR)
					Return 0
				Case ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND
					'ECheck = "Programming error"
					'If Connected = TRUE And LV = FBottom Then ECheck = "File not downloaded."
					'MessageBox(0,ECheck,"Error",MB_OK Or MB_ICONERROR)
					MessageBox(0,"Can not find file "+CPath+FName,"Error - Find associated Program",MB_OK Or MB_ICONERROR)
					'Return 0
				Case 31
					'MessageBox(0,"No associated program for file type '"+Ext+"'.","Error",MB_OK)
					'Return 0
				Case Is > 32
					'has extra spaces at end
					AsscPrg = Trim(AsscPrg)
					'Print "Check: ";AsscPrg
					ExtractIconEx(AsscPrg, 0, @hIcon, 0, 1)
					ExtractIconEx(AsscPrg, 0, 0, @hIconSm, 1)
					'Return 0
				Case Else
					MessageBox(0,"Unknown Error","Error - Find associated Program",MB_OK Or MB_ICONERROR)
					Return 0
			End Select
		Else
			ExtractIconEx(iconPath, x, @hIcon, 0, 1)
			ExtractIconEx(iconPath, x, 0, @hIconSm, 1)
		EndIf
	EndIf
	'Print "Storing icons..."
	If hIcon = NULL Or hIconSm = NULL Then
		hIcon = NULL
		hIconSm = NULL
		'
		If NoIcons(0) = "" Then
			NoIcons(0) = Ext
		Else
			x = UBound(NoIcons)+1
			ReDim Preserve NoIcons(x)
			NoIcons(x) = Ext
		EndIf
		Return 0
	EndIf
	'got both icons
	GetIconInfo(hIcon, @iconData)
	ImageList_Add(icons, iconData.hbmColor, iconData.hbmMask)
	DestroyIcon(hIcon)
	hIcon = NULL
	'
	GetIconInfo(hIconSm, @iconData)
	ImageList_Add(smicons, iconData.hbmColor, iconData.hbmMask)
	DestroyIcon(hIconSm)
	hIconSm = NULL
	'
	x = UBound(FileIcons) + 1
	ReDim Preserve FileIcons(x)
	FileIcons(x) = Ext
	Return x
End Function

Function SelFileInfo(Lv As HWND,Sel As Integer) As FileStats
	Dim lvi As LV_ITEM
	lvi.mask = LVIF_PARAM
	lvi.iSubItem = 0
	lvi.iItem = Sel
	SendMessage(LV,LVM_GETITEM,0,@lvi)
	'Return lvi.lParam' = x 'array index
	'
	If Lv = FTop(TopLVType) Then
		If TopLVType = 3 Then
			Return Zip2FileStats(TopZip,lvi.lParam)
		Else
			Return FTPL(lvi.lParam)
		EndIf
	Else
		If BotLVType = 3 Then
			Return Zip2FileStats(BottomZip,lvi.lParam)
		Else
			Return FTPR(lvi.lParam)
		EndIf
	EndIf
End Function

Function ToKB(ByVal NumBytes As ULongInt) As String
	Dim As String T
	Dim As Integer BFactor
	Dim As Double Calc = NumBytes
	'
	While Calc > 1024
		Calc /= 1024
		BFactor += 1
	Wend
	If BFactor = 0 Then ' < 1K
		T = Format(Calc,"#,##0")
	Else
		T = Format(Calc,"#,##0.00")
	EndIf
	T += " " + Mid("B KBMBGBTB",BFactor*2+1,2)
	Return T
End Function

Function GetTimeZone() As LongInt
	Dim As TIME_ZONE_INFORMATION tzi
	Dim As Integer R
	Dim As LongInt TZOffset '
	'
	R = GetTimeZoneInformation(@tzi)
	'720 is international date
	If tzi.Bias > 720 Then
		TZOffset = tzi.Bias - 720 '+ GMT
	Else
		TZOffset = -tzi.Bias
	EndIf
	TZOffset *= 60 'return number of seconds
	'Print "Time Zone:";tzi.StandardName
	'
	Return TZOffset
End Function

/'
• "Programming is like sex: one mistake and you have to support it for the rest of your life." 
• "A program is a spell cast over a computer, turning input into error messages." 
• "WARNING: Keyboard Not Attached. Press F10 to Continue."
• "Why doesn't DOS ever say 'EXCELLENT command or filename!'" '/