- - Kopieren von Dateien und Ordnern (wahlweise mit Unterordnern)
- Fortschrittsanzeige mit kalkulierter Restzeit
- Direktes "Streamen" von Daten (gleichzeitiges Lesen & Schreiben, wie beim Disc-Brennen)
- Vorgefertigte Callbacks oder eigene nutzbar
- Anzeige der zu kopierenden Größe
- Wahlweise Übernahme von Dateidatum usw -attribute
- Fehlerausgabe
- Einstellbare Puffergröße
- Einstellbare Vergleichsroutine von Quell- und Zieldaten
- Problemlos als DLL oder PB-Include nutzbar
Verbesserungsvorschläge sind natürlich wie immer gerne gesehen.
Code: Alles auswählen
;----------------------------------------
; PureCopy 1.5 (c) Daniel Obermeier
;----------------------------------------
EnableExplicit
Enumeration 0 ; Error Messages
#PURECOPY_OK
#PURECOPY_USERCANCELED
#PURECOPY_ERROR_NOTFOUND
#PURECOPY_ERROR_NOREADFILE
#PURECOPY_ERROR_NOWRITEFILE
#PURECOPY_ERROR_READDENIED
#PURECOPY_ERROR_WRITEDENIED
#PURECOPY_ERROR_DIRECTORYDENIED
#PURECOPY_ERROR_DIRECTORIESMATCH
EndEnumeration
Enumeration 0 ; Compare routines
#PURECOPY_COMPARE_NONE
#PURECOPY_COMPARE_DATE ; Simple filedate compare, recommend, fastest
#PURECOPY_COMPARE_CRC ; Memory based CRC32 checksum compare
#PURECOPY_COMPARE_SIZE ; Check the file sizes
#PURECOPY_COMPARE_EXISTS ; Continue, if destination file already exists
#PURECOPY_COMPARE_ASKCALLBACK ; Ask the Compare Callback for overwriting
; If compare routine not specified, files will always be overwritten
EndEnumeration
; Set Data Modes
#PURECOPY_PROPERTY_CREATED = 1
#PURECOPY_PROPERTY_ACCESSED = 2
#PURECOPY_PROPERTY_MODIFIED = 4
#PURECOPY_PROPERTY_ATTRIBUTES = 8
#PURECOPY_INTERNAL_COUNTSIZE = -1
#PURECOPY_EXPECTEDSLASH = "\"
#PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK = #True
#PURECOPY_COMPILE_WITH_INCLUDE_EXECUTABLE = #True
Structure PURECOPY_INFORMATION
Root.s
BytesProcessed.q
BytesTotal.q
FileBytesProcessed.q
FileBytesTotal.q
SubDirectories.l
SetFileProperties.l
CompareRoutine.l
WaitOnAllErrors.l
SimultaneousTransfer.l
TransferBufferSize.l
SimultaneousBufferSize.l
SharedRead.l
SharedWrite.l
SimultaneousError.l
SimultaneousCanceled.l
SimultaneousPaused.l
SkipFile.l
FileIDRead.l
FileIDWrite.l
*ThreadRead
*ThreadWrite
*TransferBuffer
*ProgressCallBack
*ErrorCallBack
*CompareCallBack
*ReadOnlyCallBack
EndStructure
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
#PURECOPY_CHR10 = Chr(10)
#PURECOPY_CHR34 = Chr(34)
Structure PURECOPY_DEFAULTPROGRESSWINDOW
InitStatus.l
ProgressWindow.l
Font.l
Text_Input.l
Text_Output.l
Text_Status.l
LabelRemain.l
Text_RemainingTime.l
LabelBuffer.l
ProgressBuffer.l
Text1Buffer.l
Text2Buffer.l
LabelFile.l
ProgressFile.l
TextFile.l
ProgressTotal.l
Pause.l
Cancel.l
SkipFile.l
ErrorFrame.l
ErrorList.l
ErrorContinue.l
ErrorContinueAlways.l
ErrorsDisplayed.l
CompareWindow.l
CompareYes.l
CompareNo.l
CompareRemember.l
CompareRememberedChoice.l
ReadOnlyWindow.l
ReadOnlyYes.l
ReadOnlyNo.l
ReadOnlyRemember.l
ReadOnlyRememberedChoice.l
LastSecond.l
LastUpdate.l
LastBytesProcessed.l
RemainingSeconds.l
CurrentSpeed.l
EndStructure
Procedure.l PureCopy_DefaultCallback_CreateProgressWindow(*PureCopy_Information.PURECOPY_INFORMATION, *PureCopy_DefaultProgressWindow.PURECOPY_DEFAULTPROGRESSWINDOW)
*PureCopy_DefaultProgressWindow\Font = LoadFont(#PB_Any, "Tahoma", 8)
*PureCopy_DefaultProgressWindow\ProgressWindow = OpenWindow(#PB_Any, 0, 0, 400, 210, "PureCopy", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
If IsFont(*PureCopy_DefaultProgressWindow\Font)
SetGadgetFont(#PB_Default, FontID(*PureCopy_DefaultProgressWindow\Font))
EndIf
If *PureCopy_DefaultProgressWindow\ProgressWindow
;If CreateGadgetList(WindowID(*PureCopy_DefaultProgressWindow\ProgressWindow))
TextGadget(#PB_Any, 10, 10, 40, 20, "From:")
TextGadget(#PB_Any, 10, 30, 40, 20, "To:")
*PureCopy_DefaultProgressWindow\Text_Input = TextGadget(#PB_Any, 50, 10, 340, 15, "")
*PureCopy_DefaultProgressWindow\Text_Output = TextGadget(#PB_Any, 50, 30, 340, 15, "")
Frame3DGadget(#PB_Any, 10, 55, 380, 115, "Progress")
TextGadget(#PB_Any, 20, 75, 50, 15, "Status:")
*PureCopy_DefaultProgressWindow\Text_Status = TextGadget(#PB_Any, 70, 75, 310, 15, "")
*PureCopy_DefaultProgressWindow\LabelRemain = TextGadget(#PB_Any, 20, 95, 50, 15, "Remain:")
*PureCopy_DefaultProgressWindow\Text_RemainingTime = TextGadget(#PB_Any, 70, 95, 310, 15, "")
If *PureCopy_Information\SimultaneousTransfer
*PureCopy_DefaultProgressWindow\LabelBuffer = TextGadget(#PB_Any, 20, 115, 50, 15, "Buffer:")
*PureCopy_DefaultProgressWindow\ProgressBuffer = ProgressBarGadget(#PB_Any, 70, 115, 190, 10, 1, 100)
*PureCopy_DefaultProgressWindow\Text1Buffer = TextGadget(#PB_Any, 270, 115, 60, 15, "", #PB_Text_Right)
*PureCopy_DefaultProgressWindow\Text2Buffer = TextGadget(#PB_Any, 330, 115, 50, 15, "", #PB_Text_Right)
EndIf
*PureCopy_DefaultProgressWindow\LabelFile = TextGadget(#PB_Any, 20, 130, 50, 15, "File:")
*PureCopy_DefaultProgressWindow\ProgressFile = ProgressBarGadget(#PB_Any, 70, 130, 190, 10, 1, 100)
*PureCopy_DefaultProgressWindow\TextFile = TextGadget(#PB_Any, 270, 130, 110, 15, "", #PB_Text_Right)
TextGadget(#PB_Any, 20, 145, 50, 15, "Total:")
*PureCopy_DefaultProgressWindow\ProgressTotal = ProgressBarGadget(#PB_Any, 70, 145, 310, 15, 1, 100)
*PureCopy_DefaultProgressWindow\SkipFile = ButtonGadget(#PB_Any, 70, 178, 100, 24, "Skip file")
*PureCopy_DefaultProgressWindow\Pause = ButtonGadget(#PB_Any, 180, 178, 100, 24, "Pause", #PB_Button_Toggle)
*PureCopy_DefaultProgressWindow\Cancel = ButtonGadget(#PB_Any, 290, 178, 100, 24, "Cancel")
*PureCopy_DefaultProgressWindow\ErrorFrame = Frame3DGadget(#PB_Any, 10, 205, 380, 200, "Errors")
HideGadget(*PureCopy_DefaultProgressWindow\ErrorFrame, 1)
*PureCopy_DefaultProgressWindow\ErrorList = ListIconGadget(#PB_Any, 20, 225, 360, 140, "Error code", 70)
AddGadgetColumn(*PureCopy_DefaultProgressWindow\ErrorList, 1, "Description", 120)
AddGadgetColumn(*PureCopy_DefaultProgressWindow\ErrorList, 2, "Path", 140)
HideGadget(*PureCopy_DefaultProgressWindow\ErrorList, 1)
*PureCopy_DefaultProgressWindow\ErrorContinue = ButtonGadget(#PB_Any, 280, 372, 100, 24, "Continue")
HideGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 1)
*PureCopy_DefaultProgressWindow\ErrorContinueAlways = CheckBoxGadget(#PB_Any, 170, 377, 100, 16, "Continue always")
If *PureCopy_Information\WaitOnAllErrors
SetGadgetState(*PureCopy_DefaultProgressWindow\ErrorContinueAlways, 0)
Else
SetGadgetState(*PureCopy_DefaultProgressWindow\ErrorContinueAlways, 1)
EndIf
HideGadget(*PureCopy_DefaultProgressWindow\ErrorContinueAlways, 1)
*PureCopy_DefaultProgressWindow\ErrorsDisplayed = 0
;EndIf
EndIf
ProcedureReturn #PURECOPY_OK
EndProcedure
Procedure.s PureCopy_DefaultCallback_ReturnBestTime(Size.l)
If Size < 60
ProcedureReturn Str(Size) + " seconds"
ElseIf Size < 3600
If Size / 60 = 1
ProcedureReturn Str(Size / 60) + " minute"
Else
ProcedureReturn Str(Size / 60) + " minutes"
EndIf
Else
If Size / 3600 = 1
ProcedureReturn Str(Size / 3600) + " hour, " + Str(Size / 60 - Int(Size / 3600) * 60) + " minutes"
Else
ProcedureReturn Str(Size / 3600) + " hours, " + Str(Size / 60 - Int(Size / 3600) * 60) + " minutes"
EndIf
EndIf
EndProcedure
Procedure.s PureCopy_DefaultCallback_ReturnBestSize(Size.q)
If Size >= 1073741824
ProcedureReturn StrD(Size / 1073741824, 2) + " GB"
ElseIf Size >= 1048576
ProcedureReturn StrD(Size / 1048576, 1) + " MB"
ElseIf Size >= 1024
ProcedureReturn StrD(Size / 1024, 1) + " KB"
Else
;ProcedureReturn StrQ(Size) + " Byte"
ProcedureReturn Str(Size) + " Byte"
EndIf
EndProcedure
Procedure.s PureCopy_DefaultCallback_ShortenPath(Path.s, Pixel.l, *PureCopy_DefaultProgressWindow.PURECOPY_DEFAULTPROGRESSWINDOW)
Protected LastSlash.l
Protected NewPath.s
Protected a.l
Protected TempString.s
Protected Size.SIZE
Protected *hDC
If IsFont(*PureCopy_DefaultProgressWindow\Font)
*hDC = GetDC_(WindowID(*PureCopy_DefaultProgressWindow\ProgressWindow))
If *hDC
SelectObject_(*hDC, FontID(*PureCopy_DefaultProgressWindow\Font))
For a = 0 To Len(Path) - 3
If Mid(Path, Len(Path) - a, 1) = #PURECOPY_EXPECTEDSLASH
TempString.s = Left(Path, 3) + Right(Path, a)
GetTextExtentPoint32_(*hDC, TempString, Len(TempString), Size)
If Size\cx > Pixel
Break
Else
LastSlash = a
EndIf
EndIf
Next
If a <> Len(Path) - 2
NewPath = Left(Path, 3) + "..." + #PURECOPY_EXPECTEDSLASH + Right(Path, LastSlash)
Else
NewPath = Path
EndIf
ReleaseDC_(WindowID(*PureCopy_DefaultProgressWindow\ProgressWindow), *hDC)
ProcedureReturn NewPath
Else
ProcedureReturn Path
EndIf
Else
ProcedureReturn Path
EndIf
EndProcedure
Procedure.l PureCopy_DefaultCallback_ProgressCallback(InputPath.s, OutputPath.s, *PureCopy_Information.PURECOPY_INFORMATION, *PureCopy_DefaultProgressWindow.PURECOPY_DEFAULTPROGRESSWINDOW)
Protected RemainingBytes.q
Protected BytesPerSecond.l
Protected TimeDifference.l
Protected FreeBytes.q
Protected EventID.l
Protected BufferFilled.l
If Date() <> *PureCopy_DefaultProgressWindow\LastSecond
*PureCopy_DefaultProgressWindow\RemainingSeconds - 1
*PureCopy_DefaultProgressWindow\LastSecond = Date()
EndIf
InputPath.s = PureCopy_DefaultCallback_ShortenPath(InputPath, 330, *PureCopy_DefaultProgressWindow)
OutputPath.s = PureCopy_DefaultCallback_ShortenPath(OutputPath, 330, *PureCopy_DefaultProgressWindow)
If *PureCopy_Information\BytesProcessed = #PURECOPY_INTERNAL_COUNTSIZE
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_Input, InputPath)
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_Status, PureCopy_DefaultCallback_ReturnBestSize(*PureCopy_Information\BytesTotal))
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_RemainingTime, "Counting files ...")
Else
TimeDifference = Abs(ElapsedMilliseconds() - *PureCopy_DefaultProgressWindow\LastUpdate)
If TimeDifference >= 10000
RemainingBytes = *PureCopy_Information\BytesTotal - *PureCopy_Information\BytesProcessed
BytesPerSecond.l = IntQ(*PureCopy_Information\BytesProcessed - *PureCopy_DefaultProgressWindow\LastBytesProcessed)
BytesPerSecond / (TimeDifference / 1000)
If BytesPerSecond
*PureCopy_DefaultProgressWindow\RemainingSeconds = (RemainingBytes / BytesPerSecond)
*PureCopy_DefaultProgressWindow\CurrentSpeed = BytesPerSecond
EndIf
*PureCopy_DefaultProgressWindow\LastBytesProcessed = *PureCopy_Information\BytesProcessed
*PureCopy_DefaultProgressWindow\LastUpdate = ElapsedMilliseconds()
EndIf
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_Input, InputPath)
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_Output, OutputPath)
GetDiskFreeSpaceEx_(*PureCopy_Information\Root, @FreeBytes, 0, 0)
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_Status, "Copied " + PureCopy_DefaultCallback_ReturnBestSize(*PureCopy_Information\BytesProcessed) + " of " + PureCopy_DefaultCallback_ReturnBestSize(*PureCopy_Information\BytesTotal) + " (remaining space: " + PureCopy_DefaultCallback_ReturnBestSize(FreeBytes) + ")")
If *PureCopy_DefaultProgressWindow\RemainingSeconds > 0
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_RemainingTime, PureCopy_DefaultCallback_ReturnBestTime(*PureCopy_DefaultProgressWindow\RemainingSeconds) + " (" + PureCopy_DefaultCallback_ReturnBestSize(*PureCopy_DefaultProgressWindow\CurrentSpeed) + "/s)")
Else
SetGadgetText(*PureCopy_DefaultProgressWindow\Text_RemainingTime, "")
EndIf
If *PureCopy_Information\SimultaneousTransfer
BufferFilled = *PureCopy_Information\SharedRead - *PureCopy_Information\SharedWrite
If BufferFilled < 0
BufferFilled + *PureCopy_Information\SimultaneousBufferSize
EndIf
SetGadgetState(*PureCopy_DefaultProgressWindow\ProgressBuffer, Round(BufferFilled / *PureCopy_Information\SimultaneousBufferSize * 100, #PB_Round_Nearest))
SetGadgetText(*PureCopy_DefaultProgressWindow\Text1Buffer, StrF(BufferFilled / 1000 / 1000, 1) + " MB")
SetGadgetText(*PureCopy_DefaultProgressWindow\Text2Buffer, "(" + Str(Round(BufferFilled / *PureCopy_Information\SimultaneousBufferSize * 100, #PB_Round_Nearest)) + "%)")
EndIf
SetGadgetState(*PureCopy_DefaultProgressWindow\ProgressFile, Int(*PureCopy_Information\FileBytesProcessed / *PureCopy_Information\FileBytesTotal * 100))
SetGadgetText(*PureCopy_DefaultProgressWindow\TextFile, PureCopy_DefaultCallback_ReturnBestSize(*PureCopy_Information\FileBytesProcessed) + " / " + PureCopy_DefaultCallback_ReturnBestSize(*PureCopy_Information\FileBytesTotal))
SetGadgetState(*PureCopy_DefaultProgressWindow\ProgressTotal, Int(*PureCopy_Information\BytesProcessed / *PureCopy_Information\BytesTotal * 100))
EndIf
Repeat
EventID = WindowEvent()
Select EventID
Case #PB_Event_Gadget
Select EventGadget()
Case *PureCopy_DefaultProgressWindow\SkipFile
*PureCopy_Information\SkipFile = #True
Case *PureCopy_DefaultProgressWindow\Pause
*PureCopy_Information\SimultaneousPaused = #True - *PureCopy_Information\SimultaneousPaused
Case *PureCopy_DefaultProgressWindow\Cancel
DisableGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 1)
ProcedureReturn #False
EndSelect
Case #PB_Event_CloseWindow
ProcedureReturn #False
Case 0
If GetGadgetState(*PureCopy_DefaultProgressWindow\Pause) = #False
ProcedureReturn #True
EndIf
EndSelect
ForEver
EndProcedure
Procedure PureCopy_DefaultCallback_ErrorCallback(ErrorCode.l, Path.s, *PureCopy_Information.PURECOPY_INFORMATION, *PureCopy_DefaultProgressWindow.PURECOPY_DEFAULTPROGRESSWINDOW)
Protected Message.s
Protected EventID.l
Select ErrorCode
Case #PURECOPY_USERCANCELED
Message = "PureCopy canceled by the user"
Case #PURECOPY_ERROR_NOTFOUND
Message = "Source file doesn't exist"
Case #PURECOPY_ERROR_NOREADFILE
Message = "Source file can't be opened"
Case #PURECOPY_ERROR_NOWRITEFILE
Message = "Destination file can't be created"
Case #PURECOPY_ERROR_READDENIED
Message = "Source file can't be read"
Case #PURECOPY_ERROR_WRITEDENIED
Message = "Destination file can't be written"
Case #PURECOPY_ERROR_DIRECTORYDENIED
Message = "Directory can't be examined"
Case #PURECOPY_ERROR_DIRECTORIESMATCH
Message = "Directory file names are equal"
Default
Message = "Unknown error code"
EndSelect
AddGadgetItem(*PureCopy_DefaultProgressWindow\ErrorList, -1, "0x" + Hex(ErrorCode) + #PURECOPY_CHR10 + Message + #PURECOPY_CHR10 + Path)
If *PureCopy_DefaultProgressWindow\ErrorsDisplayed = 0
ResizeWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, #PB_Ignore, #PB_Ignore, #PB_Ignore, 415)
HideGadget(*PureCopy_DefaultProgressWindow\ErrorFrame, 0)
HideGadget(*PureCopy_DefaultProgressWindow\ErrorList, 0)
HideGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 0)
HideGadget(*PureCopy_DefaultProgressWindow\ErrorContinueAlways, 0)
EndIf
DisableGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 0)
*PureCopy_DefaultProgressWindow\ErrorsDisplayed = #True
*PureCopy_Information\WaitOnAllErrors = 1 - GetGadgetState(*PureCopy_DefaultProgressWindow\ErrorContinueAlways)
Repeat
EventID = WindowEvent()
Select EventID
Case #PB_Event_Gadget
Select EventGadget()
Case *PureCopy_DefaultProgressWindow\ErrorContinue
*PureCopy_Information\WaitOnAllErrors = 1 - GetGadgetState(*PureCopy_DefaultProgressWindow\ErrorContinueAlways)
DisableGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 1)
ProcedureReturn #True
Case *PureCopy_DefaultProgressWindow\Cancel
DisableGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 1)
CallDebugger
ProcedureReturn #False
EndSelect
Case #PB_Event_CloseWindow
DisableGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 1)
ProcedureReturn #False
Case 0
If *PureCopy_Information\WaitOnAllErrors = 0
If GetGadgetState(*PureCopy_DefaultProgressWindow\Pause) = 0
DisableGadget(*PureCopy_DefaultProgressWindow\ErrorContinue, 1)
ProcedureReturn #True
EndIf
EndIf
EndSelect
ForEver
EndProcedure
Procedure PureCopy_DefaultCallback_CompareCallback(DestinationFile.s, *PureCopy_DefaultProgressWindow.PURECOPY_DEFAULTPROGRESSWINDOW)
Protected EventID.l
If *PureCopy_DefaultProgressWindow\CompareRememberedChoice <> -1
ProcedureReturn *PureCopy_DefaultProgressWindow\CompareRememberedChoice
EndIf
*PureCopy_DefaultProgressWindow\CompareWindow = OpenWindow(#PB_Any, 0, 0, 360, 100, "PureCopy", #PB_Window_TitleBar | #PB_Window_ScreenCentered, WindowID(*PureCopy_DefaultProgressWindow\ProgressWindow))
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 1)
EndIf
If *PureCopy_DefaultProgressWindow\CompareWindow; And CreateGadgetList(WindowID(*PureCopy_DefaultProgressWindow\CompareWindow))
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 1)
EndIf
MessageBeep_(48)
TextGadget(#PB_Any, 10, 10, 340, 50, "The file " + #PURECOPY_CHR34 + DestinationFile + #PURECOPY_CHR34 + " already exists.")
TextGadget(#PB_Any, 10, 65, 70, 20, "Overwrite?")
*PureCopy_DefaultProgressWindow\CompareYes = ButtonGadget(#PB_Any, 80, 60, 60, 25, "Yes")
*PureCopy_DefaultProgressWindow\CompareNo = ButtonGadget(#PB_Any, 160, 60, 60, 25, "No")
*PureCopy_DefaultProgressWindow\CompareRemember = CheckBoxGadget(#PB_Any, 240, 60, 100, 25, "Remember choice")
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_Gadget
Select EventGadget()
Case *PureCopy_DefaultProgressWindow\CompareYes
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 0)
EndIf
If GetGadgetState(*PureCopy_DefaultProgressWindow\CompareRemember)
*PureCopy_DefaultProgressWindow\CompareRememberedChoice = #True
EndIf
CloseWindow(*PureCopy_DefaultProgressWindow\CompareWindow)
ProcedureReturn #True
Case *PureCopy_DefaultProgressWindow\CompareNo
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 0)
EndIf
If GetGadgetState(*PureCopy_DefaultProgressWindow\CompareRemember)
*PureCopy_DefaultProgressWindow\CompareRememberedChoice = #False
EndIf
CloseWindow(*PureCopy_DefaultProgressWindow\CompareWindow)
ProcedureReturn #False
EndSelect
EndSelect
ForEver
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 0)
EndIf
CloseWindow(*PureCopy_DefaultProgressWindow\CompareWindow)
Else
ProcedureReturn #True
EndIf
EndProcedure
Procedure PureCopy_DefaultCallback_ReadOnlyCallback(DestinationFile.s, *PureCopy_DefaultProgressWindow.PURECOPY_DEFAULTPROGRESSWINDOW)
Protected EventID.l
If *PureCopy_DefaultProgressWindow\ReadOnlyRememberedChoice <> -1
ProcedureReturn *PureCopy_DefaultProgressWindow\ReadOnlyRememberedChoice
EndIf
*PureCopy_DefaultProgressWindow\ReadOnlyWindow = OpenWindow(#PB_Any, 0, 0, 360, 100, "PureCopy", #PB_Window_TitleBar | #PB_Window_ScreenCentered, WindowID(*PureCopy_DefaultProgressWindow\ProgressWindow))
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 1)
EndIf
If *PureCopy_DefaultProgressWindow\ReadOnlyWindow; And CreateGadgetList(WindowID(*PureCopy_DefaultProgressWindow\ReadOnlyWindow))
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 1)
EndIf
MessageBeep_(48)
TextGadget(#PB_Any, 10, 10, 340, 50, "The file " + #PURECOPY_CHR34 + DestinationFile + #PURECOPY_CHR34 + " is read-only.")
TextGadget(#PB_Any, 10, 65, 70, 20, "Overwrite?")
*PureCopy_DefaultProgressWindow\ReadOnlyYes = ButtonGadget(#PB_Any, 80, 60, 60, 25, "Yes")
*PureCopy_DefaultProgressWindow\ReadOnlyNo = ButtonGadget(#PB_Any, 160, 60, 60, 25, "No")
*PureCopy_DefaultProgressWindow\ReadOnlyRemember = CheckBoxGadget(#PB_Any, 240, 60, 100, 25, "Remember choice")
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_Gadget
Select EventGadget()
Case *PureCopy_DefaultProgressWindow\ReadOnlyYes
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 0)
EndIf
If GetGadgetState(*PureCopy_DefaultProgressWindow\ReadOnlyRemember)
*PureCopy_DefaultProgressWindow\ReadOnlyRememberedChoice = #True
EndIf
CloseWindow(*PureCopy_DefaultProgressWindow\ReadOnlyWindow)
ProcedureReturn #True
Case *PureCopy_DefaultProgressWindow\ReadOnlyNo
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 0)
EndIf
If GetGadgetState(*PureCopy_DefaultProgressWindow\ReadOnlyRemember)
*PureCopy_DefaultProgressWindow\ReadOnlyRememberedChoice = #False
EndIf
CloseWindow(*PureCopy_DefaultProgressWindow\ReadOnlyWindow)
ProcedureReturn #False
EndSelect
EndSelect
ForEver
If IsWindow(*PureCopy_DefaultProgressWindow\ProgressWindow)
DisableWindow(*PureCopy_DefaultProgressWindow\ProgressWindow, 0)
EndIf
CloseWindow(*PureCopy_DefaultProgressWindow\ReadOnlyWindow)
Else
ProcedureReturn #True
EndIf
EndProcedure
CompilerEndIf
Procedure PureCopy_Internal_SharedRead(*PureCopy_Information.PURECOPY_INFORMATION)
Protected BufferFilled.l, BufferEmpty.l, ReadSize.l
While Eof(*PureCopy_Information\FileIDRead) = 0 And *PureCopy_Information\SimultaneousCanceled = #False
BufferFilled = *PureCopy_Information\SharedRead - *PureCopy_Information\SharedWrite
If BufferFilled < 0
BufferFilled + *PureCopy_Information\SimultaneousBufferSize
EndIf
BufferEmpty = *PureCopy_Information\SimultaneousBufferSize - BufferFilled
If BufferEmpty <> *PureCopy_Information\TransferBufferSize
ReadSize = ReadData(*PureCopy_Information\FileIDRead, *PureCopy_Information\TransferBuffer + *PureCopy_Information\SharedRead, *PureCopy_Information\TransferBufferSize)
*PureCopy_Information\SharedRead + ReadSize
If ReadSize
If *PureCopy_Information\SharedRead = *PureCopy_Information\SimultaneousBufferSize
*PureCopy_Information\SharedRead = 0
EndIf
Else
*PureCopy_Information\SimultaneousError = #PURECOPY_ERROR_READDENIED
ProcedureReturn
EndIf
EndIf
While *PureCopy_Information\SimultaneousPaused And *PureCopy_Information\SimultaneousCanceled = #False
Delay(100)
Wend
Wend
EndProcedure
Procedure PureCopy_Internal_SharedWrite(*PureCopy_Information.PURECOPY_INFORMATION)
Protected BufferFilled.l, BufferWrite.l
Repeat
BufferFilled = *PureCopy_Information\SharedRead - *PureCopy_Information\SharedWrite
If BufferFilled < 0
BufferFilled + *PureCopy_Information\SimultaneousBufferSize
EndIf
If (BufferFilled <> *PureCopy_Information\TransferBufferSize Or Eof(*PureCopy_Information\FileIDRead)) And BufferFilled <> 0
BufferWrite = BufferFilled
If BufferWrite > *PureCopy_Information\TransferBufferSize
BufferWrite = *PureCopy_Information\TransferBufferSize
EndIf
If WriteData(*PureCopy_Information\FileIDWrite, *PureCopy_Information\TransferBuffer + *PureCopy_Information\SharedWrite, BufferWrite)
*PureCopy_Information\SharedWrite + BufferWrite
*PureCopy_Information\BytesProcessed + BufferWrite
*PureCopy_Information\FileBytesProcessed + BufferWrite
If *PureCopy_Information\SharedWrite = *PureCopy_Information\SimultaneousBufferSize
*PureCopy_Information\SharedWrite = 0
EndIf
Else
*PureCopy_Information\SimultaneousError = #PURECOPY_ERROR_WRITEDENIED
ProcedureReturn
EndIf
EndIf
While *PureCopy_Information\SimultaneousPaused And *PureCopy_Information\SimultaneousCanceled = #False
Delay(100)
Wend
Until (BufferFilled <> 0 And BufferFilled < *PureCopy_Information\TransferBufferSize) Or (BufferFilled = 0 And Eof(*PureCopy_Information\FileIDRead)) Or *PureCopy_Information\SimultaneousCanceled = #True
EndProcedure
Procedure.l PureCopy_Internal_DoFile(InputPath.s, OutputPath.s, *PureCopy_Information.PURECOPY_INFORMATION, *UserInformation)
Protected ReallyReadSize.l
Protected TimeCounter.l
Protected CRCFirstValue.l
Protected CRCInitValue.l
Protected ContentDifferent.l
Protected Attributes.l
CRCInitValue = 0
ContentDifferent = 0
If FileSize(OutputPath) >= 0 And FileSize(InputPath) = FileSize(OutputPath)
If *PureCopy_Information\ProgressCallBack
If CallFunctionFast(*PureCopy_Information\ProgressCallBack, @InputPath, @OutputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
Select *PureCopy_Information\CompareRoutine
Case #PURECOPY_COMPARE_DATE
If GetFileDate(InputPath, #PB_Date_Modified) = GetFileDate(OutputPath, #PB_Date_Modified)
*PureCopy_Information\BytesProcessed + FileSize(InputPath)
ProcedureReturn #PURECOPY_OK
EndIf
Case #PURECOPY_COMPARE_CRC
*PureCopy_Information\FileIDRead = ReadFile(#PB_Any, InputPath)
If *PureCopy_Information\FileIDRead
*PureCopy_Information\FileIDWrite = ReadFile(#PB_Any, OutputPath)
If *PureCopy_Information\FileIDWrite
While Eof(*PureCopy_Information\FileIDRead) = #False
ReallyReadSize = ReadData(*PureCopy_Information\FileIDRead, *PureCopy_Information\TransferBuffer, *PureCopy_Information\TransferBufferSize)
CRCFirstValue = CRC32Fingerprint(*PureCopy_Information\TransferBuffer, ReallyReadSize, CRCInitValue)
ReallyReadSize = ReadData(*PureCopy_Information\FileIDWrite, *PureCopy_Information\TransferBuffer, *PureCopy_Information\TransferBufferSize)
If CRC32Fingerprint(*PureCopy_Information\TransferBuffer, ReallyReadSize, CRCInitValue) <> CRCFirstValue
ContentDifferent = 1
Break
EndIf
CRCInitValue = CRCFirstValue
Wend
CloseFile(*PureCopy_Information\FileIDWrite)
EndIf
CloseFile(*PureCopy_Information\FileIDRead)
EndIf
If ContentDifferent = 0
*PureCopy_Information\BytesProcessed + FileSize(InputPath)
ProcedureReturn #PURECOPY_OK
EndIf
Case #PURECOPY_COMPARE_SIZE
*PureCopy_Information\BytesProcessed + FileSize(InputPath)
ProcedureReturn #PURECOPY_OK
Case #PURECOPY_COMPARE_EXISTS
If FileSize(OutputPath) >= 0
*PureCopy_Information\BytesProcessed + FileSize(InputPath)
ProcedureReturn #PURECOPY_OK
EndIf
Case #PURECOPY_COMPARE_ASKCALLBACK
If *PureCopy_Information\CompareCallBack
If CallFunctionFast(*PureCopy_Information\CompareCallBack, @OutputPath, *UserInformation) = #False
*PureCopy_Information\BytesProcessed + FileSize(InputPath)
ProcedureReturn #PURECOPY_OK
EndIf
EndIf
EndSelect
EndIf
Attributes = GetFileAttributes_(OutputPath)
If Attributes <> -1 And Attributes & #FILE_ATTRIBUTE_READONLY
If CallFunctionFast(*PureCopy_Information\ReadOnlyCallBack, @OutputPath, *UserInformation) = #False
*PureCopy_Information\BytesProcessed + FileSize(InputPath)
ProcedureReturn #PURECOPY_OK
Else
SetFileAttributes_(OutputPath, Attributes &~ #FILE_ATTRIBUTE_READONLY)
EndIf
EndIf
If *PureCopy_Information\ProgressCallBack
If CallFunctionFast(*PureCopy_Information\ProgressCallBack, @InputPath, @OutputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
TimeCounter = ElapsedMilliseconds()
*PureCopy_Information\FileIDRead = ReadFile(#PB_Any, InputPath)
If *PureCopy_Information\FileIDRead
FileBuffersSize(*PureCopy_Information\FileIDRead, 0)
*PureCopy_Information\FileIDWrite = CreateFile(#PB_Any, OutputPath)
If *PureCopy_Information\FileIDWrite
FileBuffersSize(*PureCopy_Information\FileIDWrite, 0)
*PureCopy_Information\FileBytesProcessed = 0
*PureCopy_Information\FileBytesTotal = Lof(*PureCopy_Information\FileIDRead)
If *PureCopy_Information\ProgressCallBack
If CallFunctionFast(*PureCopy_Information\ProgressCallBack, @InputPath, @OutputPath, *PureCopy_Information, *UserInformation) = #False
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
If FileSize(InputPath) <> 0
*PureCopy_Information\SkipFile = #False
If *PureCopy_Information\SimultaneousTransfer
*PureCopy_Information\SharedRead = 0
*PureCopy_Information\SharedWrite = 0
*PureCopy_Information\SimultaneousCanceled = #False
*PureCopy_Information\SimultaneousError = #PURECOPY_OK
*PureCopy_Information\ThreadRead = CreateThread(@PureCopy_Internal_SharedRead(), *PureCopy_Information)
*PureCopy_Information\ThreadWrite = CreateThread(@PureCopy_Internal_SharedWrite(), *PureCopy_Information)
Repeat
If *PureCopy_Information\ProgressCallBack
If CallFunctionFast(*PureCopy_Information\ProgressCallBack, @InputPath, @OutputPath, *PureCopy_Information, *UserInformation) = #False
*PureCopy_Information\SimultaneousCanceled = #True
WaitThread(*PureCopy_Information\ThreadWrite, 10000)
WaitThread(*PureCopy_Information\ThreadRead, 10000)
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
TimeCounter = ElapsedMilliseconds()
EndIf
Until WaitThread(*PureCopy_Information\ThreadWrite, 100) Or *PureCopy_Information\SkipFile
If *PureCopy_Information\SkipFile
*PureCopy_Information\SimultaneousCanceled = #True
*PureCopy_Information\BytesProcessed + (*PureCopy_Information\FileBytesTotal - *PureCopy_Information\FileBytesProcessed)
WaitThread(*PureCopy_Information\ThreadWrite, 10000)
WaitThread(*PureCopy_Information\ThreadRead, 10000)
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
ProcedureReturn #PURECOPY_OK
ElseIf *PureCopy_Information\SimultaneousError <> #PURECOPY_OK
*PureCopy_Information\SimultaneousCanceled = #True
*PureCopy_Information\BytesProcessed + (*PureCopy_Information\FileBytesTotal - *PureCopy_Information\FileBytesProcessed)
WaitThread(*PureCopy_Information\ThreadWrite, 10000)
WaitThread(*PureCopy_Information\ThreadRead, 10000)
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
If *PureCopy_Information\ErrorCallBack
Select *PureCopy_Information\SimultaneousError
Case #PURECOPY_ERROR_READDENIED
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, *PureCopy_Information\SimultaneousError, @InputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
Case #PURECOPY_ERROR_WRITEDENIED
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, *PureCopy_Information\SimultaneousError, @OutputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndSelect
EndIf
ProcedureReturn *PureCopy_Information\SimultaneousError
Else
WaitThread(*PureCopy_Information\ThreadRead, 10000)
EndIf
Else
While Eof(*PureCopy_Information\FileIDRead) = #False And *PureCopy_Information\SkipFile = #False
ReallyReadSize = ReadData(*PureCopy_Information\FileIDRead, *PureCopy_Information\TransferBuffer, *PureCopy_Information\TransferBufferSize)
If ReallyReadSize
If WriteData(*PureCopy_Information\FileIDWrite, *PureCopy_Information\TransferBuffer, ReallyReadSize)
*PureCopy_Information\BytesProcessed + ReallyReadSize
*PureCopy_Information\FileBytesProcessed + ReallyReadSize
Else
*PureCopy_Information\BytesProcessed + (*PureCopy_Information\FileBytesTotal - *PureCopy_Information\FileBytesProcessed)
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
If *PureCopy_Information\ErrorCallBack
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_WRITEDENIED, @OutputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
ProcedureReturn #PURECOPY_ERROR_WRITEDENIED
EndIf
Else
*PureCopy_Information\BytesProcessed + (*PureCopy_Information\FileBytesTotal - *PureCopy_Information\FileBytesProcessed)
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
If *PureCopy_Information\ErrorCallBack
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_READDENIED, @InputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
ProcedureReturn #PURECOPY_ERROR_READDENIED
EndIf
If Abs(ElapsedMilliseconds() - TimeCounter) > 100 And *PureCopy_Information\ProgressCallBack
If CallFunctionFast(*PureCopy_Information\ProgressCallBack, @InputPath, @OutputPath, *PureCopy_Information, *UserInformation) = #False
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
TimeCounter = ElapsedMilliseconds()
EndIf
Wend
If *PureCopy_Information\SkipFile
*PureCopy_Information\BytesProcessed + (*PureCopy_Information\FileBytesTotal - *PureCopy_Information\FileBytesProcessed)
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
DeleteFile(OutputPath)
ProcedureReturn #PURECOPY_OK
EndIf
EndIf
EndIf
CloseFile(*PureCopy_Information\FileIDRead)
CloseFile(*PureCopy_Information\FileIDWrite)
Else
CloseFile(*PureCopy_Information\FileIDRead)
If *PureCopy_Information\ErrorCallBack
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_NOWRITEFILE, @OutputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
ProcedureReturn #PURECOPY_ERROR_NOWRITEFILE
EndIf
Else
If *PureCopy_Information\ErrorCallBack
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_NOREADFILE, @InputPath, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
ProcedureReturn #PURECOPY_ERROR_NOREADFILE
EndIf
If *PureCopy_Information\SetFileProperties & #PURECOPY_PROPERTY_CREATED
SetFileDate(OutputPath, #PB_Date_Created, GetFileDate(InputPath, #PB_Date_Created))
EndIf
If *PureCopy_Information\SetFileProperties & #PURECOPY_PROPERTY_ACCESSED
SetFileDate(OutputPath, #PB_Date_Accessed, GetFileDate(InputPath, #PB_Date_Accessed))
EndIf
If *PureCopy_Information\SetFileProperties & #PURECOPY_PROPERTY_MODIFIED
SetFileDate(OutputPath, #PB_Date_Modified, GetFileDate(InputPath, #PB_Date_Modified))
EndIf
If *PureCopy_Information\SetFileProperties & #PURECOPY_PROPERTY_ATTRIBUTES
SetFileAttributes_(OutputPath, GetFileAttributes_(InputPath)) ; Has to be replaced by another Procedure on Non-Windows OS!
EndIf
ProcedureReturn #PURECOPY_OK
EndProcedure
Procedure.l PureCopy_Internal_DoDirectory(InputDirectory.s, OutputDirectory.s, *PureCopy_Information.PURECOPY_INFORMATION, *UserInformation)
Protected Result.l
Protected Directory.l
Protected DirectoryName.s
InputDirectory + #PURECOPY_EXPECTEDSLASH
OutputDirectory + #PURECOPY_EXPECTEDSLASH
MakeSureDirectoryPathExists_(OutputDirectory) ; Has to be replaced by another Procedure on Non-Windows OS!
Directory = ExamineDirectory(#PB_Any, InputDirectory, "*.*")
If Directory
While NextDirectoryEntry(Directory)
DirectoryName = DirectoryEntryName(Directory)
If DirectoryName = "." Or DirectoryName = ".."
Continue
EndIf
Select DirectoryEntryType(Directory)
Case #PB_DirectoryEntry_File
Result = PureCopy_Internal_DoFile(InputDirectory + DirectoryName, OutputDirectory + DirectoryName, *PureCopy_Information, *UserInformation)
If Result = #PURECOPY_USERCANCELED
FinishDirectory(Directory)
ProcedureReturn Result
EndIf
Case #PB_DirectoryEntry_Directory
If *PureCopy_Information\SubDirectories
Result = PureCopy_Internal_DoDirectory(InputDirectory + DirectoryName, OutputDirectory + DirectoryName, *PureCopy_Information, *UserInformation)
If Result = #PURECOPY_USERCANCELED
FinishDirectory(Directory)
ProcedureReturn Result
EndIf
EndIf
EndSelect
Wend
Else
If *PureCopy_Information\ErrorCallBack
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_DIRECTORYDENIED, @InputDirectory, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
ProcedureReturn #PURECOPY_ERROR_DIRECTORYDENIED
EndIf
FinishDirectory(Directory)
InputDirectory = Left(InputDirectory, Len(InputDirectory) - 1)
OutputDirectory = Left(OutputDirectory, Len(OutputDirectory) - 1)
If *PureCopy_Information\SetFileProperties & #PURECOPY_PROPERTY_ATTRIBUTES
SetFileAttributes_(OutputDirectory, GetFileAttributes_(InputDirectory)) ; Has to be replaced by another Procedure on Non-Windows OS!
EndIf
ProcedureReturn #PURECOPY_OK
EndProcedure
Procedure.l PureCopy_Internal_CountSize(InputDirectory.s, *PureCopy_Information.PURECOPY_INFORMATION, *UserInformation)
Protected Result.l
Protected Directory.l
Protected DirectoryName.s
InputDirectory + #PURECOPY_EXPECTEDSLASH
If *PureCopy_Information\ProgressCallBack
If CallFunctionFast(*PureCopy_Information\ProgressCallBack, @InputDirectory, @"", *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
Directory = ExamineDirectory(#PB_Any, InputDirectory, "*.*")
If Directory
While NextDirectoryEntry(Directory)
DirectoryName = DirectoryEntryName(Directory)
If DirectoryName = "." Or DirectoryName = ".."
Continue
EndIf
Select DirectoryEntryType(Directory)
Case #PB_DirectoryEntry_File
*PureCopy_Information\BytesTotal + DirectoryEntrySize(Directory)
Case #PB_DirectoryEntry_Directory
If *PureCopy_Information\SubDirectories
Result = PureCopy_Internal_CountSize(InputDirectory + DirectoryName, *PureCopy_Information, *UserInformation)
If Result <> #PURECOPY_OK And Result <> #PURECOPY_ERROR_DIRECTORYDENIED
FinishDirectory(Directory)
ProcedureReturn Result
EndIf
EndIf
EndSelect
Wend
Else
If *PureCopy_Information\ErrorCallBack
If CallFunctionFast(*PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_DIRECTORYDENIED, @InputDirectory, *PureCopy_Information, *UserInformation) = #False
ProcedureReturn #PURECOPY_USERCANCELED
EndIf
EndIf
ProcedureReturn #PURECOPY_ERROR_DIRECTORYDENIED
EndIf
FinishDirectory(Directory)
ProcedureReturn #PURECOPY_OK
EndProcedure
Procedure.l PureCopy(SourcePathComplete.s, DestinationDirectory.s, *UserInformation, SubDirectories.l = #PB_Ignore, SetFileProperties.l = #PB_Ignore, CompareRoutine.l = #PB_Ignore, TransferBufferSize.l = #PB_Ignore, SimultaneousBufferCount.l = #PB_Ignore, WaitOnError.l = #PB_Ignore, SimultaneousTransfer.l = #PB_Ignore, *ProgressCallback.l = #PB_Ignore, *ErrorCallback.l = #PB_Ignore, *CompareCallback.l = #PB_Ignore, *ReadOnlyCallback.l = #PB_Ignore)
Protected Result.l
Protected EventID.l
Protected PureCopy_Information.PURECOPY_INFORMATION
Protected SourcePath.s
Protected FilesCount.l
Protected FileIndex.l
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
Protected PureCopy_DefaultProgressWindow.PURECOPY_DEFAULTPROGRESSWINDOW
PureCopy_DefaultProgressWindow\CompareRememberedChoice = -1
PureCopy_DefaultProgressWindow\ReadOnlyRememberedChoice = -1
CompilerEndIf
If Left(DestinationDirectory, 2) = "\\"
PureCopy_Information\Root.s = Left(DestinationDirectory, FindString(DestinationDirectory, #PURECOPY_EXPECTEDSLASH, 3))
Else
PureCopy_Information\Root = Left(DestinationDirectory, 3)
EndIf
If SubDirectories = #PB_Ignore
PureCopy_Information\SubDirectories = 1
Else
PureCopy_Information\SubDirectories = SubDirectories
EndIf
If SetFileProperties = #PB_Ignore
PureCopy_Information\SetFileProperties = #PURECOPY_PROPERTY_CREATED | #PURECOPY_PROPERTY_ACCESSED | #PURECOPY_PROPERTY_MODIFIED | #PURECOPY_PROPERTY_ATTRIBUTES
Else
PureCopy_Information\SetFileProperties = SetFileProperties
EndIf
If CompareRoutine = #PB_Ignore
PureCopy_Information\CompareRoutine = 0
Else
PureCopy_Information\CompareRoutine = CompareRoutine
EndIf
If WaitOnError = #PB_Ignore Or WaitOnError = 0
PureCopy_Information\WaitOnAllErrors = #False
Else
PureCopy_Information\WaitOnAllErrors = #True
EndIf
If SimultaneousTransfer = #PB_Ignore Or SimultaneousTransfer = 0
PureCopy_Information\SimultaneousTransfer = #False
Else
PureCopy_Information\SimultaneousTransfer = #True
EndIf
If *ProgressCallback = #PB_Ignore
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
PureCopy_Information\ProgressCallBack = @PureCopy_DefaultCallback_ProgressCallback()
PureCopy_DefaultProgressWindow\InitStatus = PureCopy_DefaultCallback_CreateProgressWindow(PureCopy_Information, PureCopy_DefaultProgressWindow)
CompilerElse
PureCopy_Information\ProgressCallBack = 0
CompilerEndIf
Else
PureCopy_Information\ProgressCallBack = *ProgressCallback
EndIf
If *ErrorCallback = #PB_Ignore
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If PureCopy_DefaultProgressWindow\InitStatus = #PURECOPY_OK
PureCopy_Information\ErrorCallBack = @PureCopy_DefaultCallback_ErrorCallback()
Else
PureCopy_Information\ErrorCallBack = 0
EndIf
CompilerElse
PureCopy_Information\ErrorCallBack = 0
CompilerEndIf
Else
PureCopy_Information\ErrorCallBack = *ErrorCallback
EndIf
If *CompareCallback = #PB_Ignore
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If PureCopy_DefaultProgressWindow\InitStatus = #PURECOPY_OK
PureCopy_Information\CompareCallBack = @PureCopy_DefaultCallback_CompareCallback()
Else
PureCopy_Information\CompareCallBack = 0
EndIf
CompilerElse
PureCopy_Information\CompareCallBack = 0
CompilerEndIf
Else
PureCopy_Information\CompareCallBack = *CompareCallback
EndIf
If *ReadOnlyCallback = #PB_Ignore
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If PureCopy_DefaultProgressWindow\InitStatus = #PURECOPY_OK
PureCopy_Information\ReadOnlyCallBack = @PureCopy_DefaultCallback_ReadOnlyCallback()
Else
PureCopy_Information\ReadOnlyCallBack = 0
EndIf
CompilerElse
PureCopy_Information\ReadOnlyCallBack = 0
CompilerEndIf
Else
PureCopy_Information\ReadOnlyCallBack = *ReadOnlyCallback
EndIf
If TransferBufferSize = #PB_Ignore
TransferBufferSize = 4096 * 64
EndIf
If SimultaneousBufferCount = #PB_Ignore
SimultaneousBufferCount = 32
EndIf
If PureCopy_Information\SimultaneousTransfer = #True
PureCopy_Information\TransferBuffer = AllocateMemory(TransferBufferSize * SimultaneousBufferCount)
Else
PureCopy_Information\TransferBuffer = AllocateMemory(TransferBufferSize)
EndIf
PureCopy_Information\TransferBufferSize = TransferBufferSize
PureCopy_Information\SimultaneousBufferSize = TransferBufferSize * SimultaneousBufferCount
PureCopy_Information\BytesProcessed = #PURECOPY_INTERNAL_COUNTSIZE
PureCopy_Information\BytesTotal = 0
FilesCount = CountString(SourcePathComplete, #LF$) + 1
For FileIndex = 1 To FilesCount
SourcePath = StringField(SourcePathComplete, FileIndex, #LF$)
Select FileSize(SourcePath)
Case -2
If Right(SourcePath, 1) = #PURECOPY_EXPECTEDSLASH
SourcePath = Left(SourcePath, Len(SourcePath) - 1)
EndIf
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
Result = PureCopy_Internal_CountSize(SourcePath, PureCopy_Information, PureCopy_DefaultProgressWindow)
CompilerElse
Result = PureCopy_Internal_CountSize(SourcePath, PureCopy_Information, *UserInformation)
CompilerEndIf
Default
PureCopy_Information\BytesTotal + FileSize(SourcePath)
EndSelect
Next
If Result <> #PURECOPY_USERCANCELED
PureCopy_Information\BytesProcessed = 0
MakeSureDirectoryPathExists_(GetPathPart(DestinationDirectory)) ; Has to be replaced by another Procedure on Non-Windows OS!
If Right(DestinationDirectory, 1) = #PURECOPY_EXPECTEDSLASH
DestinationDirectory = Left(DestinationDirectory, Len(DestinationDirectory) - 1)
EndIf
For FileIndex = 1 To FilesCount
SourcePath = StringField(SourcePathComplete, FileIndex, #LF$)
Select FileSize(SourcePath)
Case -1
Result = #PURECOPY_ERROR_NOTFOUND
If PureCopy_Information\ErrorCallBack
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If CallFunctionFast(PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_NOTFOUND, @SourcePath, PureCopy_Information, PureCopy_DefaultProgressWindow) = #False
CompilerElse
If CallFunctionFast(PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_NOTFOUND, @SourcePath, PureCopy_Information, *UserInformation) = #False
CompilerEndIf
Result = #PURECOPY_USERCANCELED
EndIf
EndIf
Case -2
If Right(SourcePath, 1) = #PURECOPY_EXPECTEDSLASH
SourcePath = Left(SourcePath, Len(SourcePath) - 1)
EndIf
If FindString(LCase(DestinationDirectory), LCase(SourcePath), 1)
Result = #PURECOPY_ERROR_DIRECTORIESMATCH
If PureCopy_Information\ErrorCallBack
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If CallFunctionFast(PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_DIRECTORIESMATCH, @SourcePath, PureCopy_Information, PureCopy_DefaultProgressWindow) = #False
CompilerElse
If CallFunctionFast(PureCopy_Information\ErrorCallBack, #PURECOPY_ERROR_DIRECTORIESMATCH, @SourcePath, PureCopy_Information, *UserInformation) = #False
CompilerEndIf
Result = #PURECOPY_USERCANCELED
EndIf
EndIf
Else
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If GetPathPart(SourcePath) = DestinationDirectory + #PURECOPY_EXPECTEDSLASH
Result = PureCopy_Internal_DoDirectory(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + "Copy of " + RemoveString(GetFilePart(SourcePath), ":"), PureCopy_Information, PureCopy_DefaultProgressWindow)
Else
Result = PureCopy_Internal_DoDirectory(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + RemoveString(GetFilePart(SourcePath), ":"), PureCopy_Information, PureCopy_DefaultProgressWindow)
EndIf
CompilerElse
If SourcePath = DestinationDirectory
Result = PureCopy_Internal_DoDirectory(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + "Copy of " + RemoveString(GetFilePart(SourcePath), ":"), PureCopy_Information, *UserInformation)
Else
Result = PureCopy_Internal_DoDirectory(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + RemoveString(GetFilePart(SourcePath), ":"), PureCopy_Information, *UserInformation)
EndIf
CompilerEndIf
EndIf
Default
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If SourcePath = DestinationDirectory + #PURECOPY_EXPECTEDSLASH + GetFilePart(SourcePath)
Result = PureCopy_Internal_DoFile(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + "Copy of " + GetFilePart(SourcePath), PureCopy_Information, PureCopy_DefaultProgressWindow)
Else
Result = PureCopy_Internal_DoFile(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + GetFilePart(SourcePath), PureCopy_Information, PureCopy_DefaultProgressWindow)
EndIf
CompilerElse
If SourcePath = DestinationDirectory + #PURECOPY_EXPECTEDSLASH + GetFilePart(SourcePath)
Result = PureCopy_Internal_DoFile(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + "Copy of " + GetFilePart(SourcePath), PureCopy_Information, *UserInformation)
Else
Result = PureCopy_Internal_DoFile(SourcePath, DestinationDirectory + #PURECOPY_EXPECTEDSLASH + GetFilePart(SourcePath), PureCopy_Information, *UserInformation)
EndIf
CompilerEndIf
EndSelect
If Result = #PURECOPY_USERCANCELED
Break
EndIf
Next
FreeMemory(PureCopy_Information\TransferBuffer)
EndIf
CompilerIf #PURECOPY_COMPILE_WITH_DEFAULT_CALLBACK
If *ProgressCallback = #PB_Ignore
If PureCopy_DefaultProgressWindow\InitStatus = #PURECOPY_OK
If CountGadgetItems(PureCopy_DefaultProgressWindow\ErrorList) = 0
CloseWindow(PureCopy_DefaultProgressWindow\ProgressWindow)
Else
SetGadgetText(PureCopy_DefaultProgressWindow\Cancel, "Close")
HideGadget(PureCopy_DefaultProgressWindow\SkipFile, 1)
HideGadget(PureCopy_DefaultProgressWindow\Pause, 1)
HideGadget(PureCopy_DefaultProgressWindow\ErrorContinue, 1)
HideGadget(PureCopy_DefaultProgressWindow\ErrorContinueAlways, 1)
ResizeGadget(PureCopy_DefaultProgressWindow\ErrorList, #PB_Ignore, #PB_Ignore, #PB_Ignore, 170)
SetGadgetText(PureCopy_DefaultProgressWindow\Text_Input, SourcePath)
SetGadgetText(PureCopy_DefaultProgressWindow\Text_Output, DestinationDirectory)
SetGadgetText(PureCopy_DefaultProgressWindow\Text_Status, "Finished")
HideGadget(PureCopy_DefaultProgressWindow\LabelRemain, 1)
HideGadget(PureCopy_DefaultProgressWindow\Text_RemainingTime, 1)
HideGadget(PureCopy_DefaultProgressWindow\LabelFile, 1)
HideGadget(PureCopy_DefaultProgressWindow\ProgressFile, 1)
SetGadgetState(PureCopy_DefaultProgressWindow\ProgressTotal, 100)
SetGadgetState(PureCopy_DefaultProgressWindow\ProgressFile, 100)
SetGadgetText(PureCopy_DefaultProgressWindow\TextFile, "Total: " + PureCopy_DefaultCallback_ReturnBestSize(PureCopy_Information\BytesTotal))
If PureCopy_Information\SimultaneousTransfer
HideGadget(PureCopy_DefaultProgressWindow\LabelBuffer, 1)
HideGadget(PureCopy_DefaultProgressWindow\ProgressBuffer, 1)
HideGadget(PureCopy_DefaultProgressWindow\Text1Buffer, 1)
HideGadget(PureCopy_DefaultProgressWindow\Text2Buffer, 1)
EndIf
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case PureCopy_DefaultProgressWindow\Cancel
Break
EndSelect
EndSelect
ForEver
CloseWindow(PureCopy_DefaultProgressWindow\ProgressWindow)
EndIf
EndIf
EndIf
CompilerEndIf
ProcedureReturn Result
EndProcedure
Procedure OnErrorProcedure()
MessageRequester("Error", ErrorMessage() + "(" + GetFilePart(ErrorFile()) + " line " + Str(ErrorLine()) + ")")
EndProcedure
OnErrorCall(@OnErrorProcedure())
CompilerIf #PURECOPY_COMPILE_WITH_INCLUDE_EXECUTABLE
Define Parameter.s = ""
Define a.l
For a = 1 To CountProgramParameters()
Parameter + ProgramParameter(a - 1) + " "
Next
Parameter = Trim(Parameter)
Define InputFiles.s = StringField(Parameter, 1, Chr(1))
Define OutputFilepath.s = StringField(Parameter, 2, Chr(1))
Define SubDirectories.l = Val(StringField(Parameter, 3, Chr(1)))
Define SetFileProperties.l = Val(StringField(Parameter, 4, Chr(1)))
Define CompareRoutines.l = Val(StringField(Parameter, 5, Chr(1)))
Define WaitOnError.l = Val(StringField(Parameter, 6, Chr(1)))
Define SimultaneousTransfer.l = Val(StringField(Parameter, 7, Chr(1)))
PureCopy(InputFiles, OutputFilepath, 0, SubDirectories, SetFileProperties, CompareRoutines, #PB_Ignore, #PB_Ignore, WaitOnError, SimultaneousTransfer)
CompilerEndIf