PureCopy

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Jilocasin
Beiträge: 665
Registriert: 13.05.2006 16:04
Kontaktdaten:

PureCopy

Beitrag von Jilocasin »

Features:
  • - 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
Zuletzt geändert von Jilocasin am 22.04.2010 10:50, insgesamt 3-mal geändert.
Bild
Benutzeravatar
LukasBanana
Beiträge: 150
Registriert: 14.03.2007 19:13
Kontaktdaten:

Beitrag von LukasBanana »

Hey cooler Code, kann man sicher mal gut gebrauchen! :allright:
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Code: Alles auswählen

Enumeration 1 ; Error Messages 
  #PURECOPY_OK 
  
  #PURECOPY_ERROR_NOFILE 
  #PURECOPY_ERROR_NOREADFILE 
  #PURECOPY_ERROR_NOWRITEFILE 
  #PURECOPY_ERROR_READDENIED 
  #PURECOPY_ERROR_WRITEDENIED 
  #PURECOPY_ERROR_DIRECTORYDENIED 
  
  #PURECOPY_ERROR_NODEFAULTPROGRESSWINDOW 
  #PURECOPY_ERROR_NOGADGETLIST 
  
  #PURECOPY_ERROR_USERCANCELED 
EndEnumeration 
Ohne es getestet zu haben, aber warum benutzt du nicht 0 als OK?
So könnte man schneller überprüfen, ob alles kopiert wurde, wenn man den Fehler nicht genauer wissen will/muss:

Code: Alles auswählen

If Not PureCopy()
Wäre sehr praktisch, denn wenn #OK = 0, dann würde das gehen.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Jilocasin
Beiträge: 665
Registriert: 13.05.2006 16:04
Kontaktdaten:

Beitrag von Jilocasin »

Wieso Not?

Das OK = 1 hatte ich dafür gedacht:

Code: Alles auswählen

If PureCopy() = #PURECOPY_OK
  Blaaa.....
Endif
aber auch, damit folgendes machbar ist:

Code: Alles auswählen

If PureCopy()
  Blaaa....
Endif
:)

Aber wer es anders möchte, darf gerne die 1 bei Enumeration wegmachen, dafür hab ich ja den Code gepostet
Bild
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

> aber auch, damit folgendes machbar ist
Du verstehst nicht, worauf ich hinaus wollte.
Wie soll ich denn bei

Code: Alles auswählen

If PureCopy()

EndIf
wissen, ob die Aktion erfolgreich war? Geht nicht, weil #PURECOPY_OK und #PURECOPY_ERROR_* alle ungleich null sind. Sie alle werden also durch gerade genannte If-Abfrage abgefangen.

Möchte man aber, dass eine If-Abfrage nur dann ausgeführt wird, wenn die Aktion erfolgreich oder fehlgeschlagen ist (also nur eines von beidem), dann muss man die Result-Werte logisch wählen.
Also entweder Erfolg<>0 und Fehlschlag=0 oder umgekehrt.

Bei den meisten PB-Befehlen ist die Aktion erfolgreich verlaufen, wenn der Rückgabewert ungleich null ist, d. h.

Code: Alles auswählen

If CreateFile()

EndIf
klappt. Du möchtest mit deinen Konstanten aber beim Rückgabewert ermöglichen, auch gleich noch die Ursache festzustellen, ähnlich, wie der Befehl XMLStatus(). Dieser Befehl hat als Success-Konstante auch null (#PB_XML_OK=0), damit man, wenn die Art des Fehlers unerheblich ist und nur auf Erfolg prüfen will, den Code übersichtlicher und effektiver gestalten kann:

Code: Alles auswählen

If Not XMLStatus()
   ; Erfolg
Else
   ; Irgendein Fehler
EndIf

Nun, verstehe dies bitte nicht als Anschuldigung oder dergleichen. Ich möchte dir und allen anderen Interessenten nur eine, naja ich nenn's mal "intelligente" Möglichkeit aufzeigen, wie man seine Result-Werte logisch wählen kann. Ich hoffe mein Tipp hat dir geholfen. :)
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Jilocasin
Beiträge: 665
Registriert: 13.05.2006 16:04
Kontaktdaten:

Re: PureCopy

Beitrag von Jilocasin »

Nach ziemlich langer Zeit hab ich den Code jetzt nochmal überarbeitet und nutze ihn jetzt zur Erstellung von Backups :mrgreen:

Um den Code im ersten Post mit Oberfläche zu nutzen sollte er als "PureCopy_IncludeExecutable.exe" kompiliert werden:

Code: Alles auswählen

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


Enumeration
  #W_Main
EndEnumeration

Enumeration
  #M_Main
EndEnumeration

Enumeration
  #Event_ImageInput
  #Event_ImageOutput
  
  #Event_Start
  
  #Event_SubDirectories
  #Event_SetFilePropertiesCreated
  #Event_SetFilePropertiesAccessed
  #Event_SetFilePropertiesModified
  #Event_SetFilePropertiesAttributes
  #Event_CompareRoutine
  #Event_WaitOnError
  #Event_SimultaneousTransfer
  
  #Event_Website
  
  #Event_ShowWindow
  #Event_End
EndEnumeration

Enumeration
  #I_Input
  #I_Output
  #I_SystrayMain
EndEnumeration


Enumeration
  #Param_Default
  #Param_Directory
  #Param_Unknown
EndEnumeration



Define InputFilepath.s = ""
Global InputFiles.s = ""
Global OutputFilepath.s = ""
Define OutputFilepathTemp.s = ""

Define FilesCount.l = 0
Define FileIndex.l

Define SystrayMain.l

Procedure DrawFilepathIcon(Image, Filepath.s, Parameter)
  Define shInfo.SHFILEINFO
  
  Select Parameter
  Case #Param_Unknown
    ExtractIconEx_("shell32.dll", 175, @shInfo\hIcon, 0, 1)
    
  Case #Param_Directory
    ExtractIconEx_("shell32.dll", 54, @shInfo\hIcon, 0, 1)
  
  Case #Param_Default
    If FileSize(Filepath) = -2
      ExtractIconEx_("shell32.dll", 3, @shInfo\hIcon, 0, 1)
    Else
      SHGetFileInfo_(Filepath, #FILE_ATTRIBUTE_NORMAL, @shInfo, SizeOf(shInfo), #SHGFI_USEFILEATTRIBUTES | #SHGFI_ICON | #SHGFI_LARGEICON)
      
      If shInfo\hIcon = 0
        ExtractIconEx_(Filepath, 0, @shInfo\hIcon, 0, 1)
      EndIf
      
      If shInfo\hIcon = 0
        ExtractIconEx_("shell32.dll", 0, @shInfo\hIcon, 0, 1)
      EndIf
    EndIf
  EndSelect
  
  CreateImage(Image, 32, 32)
  If StartDrawing(ImageOutput(Image))
    Box(0, 0, 32, 32, GetSysColor_(#COLOR_BTNFACE))
    
    If shInfo\hIcon
      DrawImage(shInfo\hIcon, 0, 0)
    EndIf
    StopDrawing()
  EndIf
  
  
  If shInfo\hIcon
    DestroyIcon_(shInfo\hIcon)
  EndIf
EndProcedure


Procedure.s ShortcutTarget(ShortcutFile.s) 
  Define Result.s = "" 
  
  If Right(LCase(ShortcutFile), 4) <> ".lnk"
    ProcedureReturn ShortcutFile
  EndIf
  
  CoInitialize_(0) 
  
  Define ShellLink.IShellLinkA
  Define LinkFile.IPersistFile
  
  If CoCreateInstance_(?CLSID_ShellLink, 0, 1, ?IID_IShellLink, @ShellLink) = #S_OK
    If ShellLink\QueryInterface(?IID_IPersistFile, @LinkFile) = #S_OK
      Define *buffer = AllocateMemory(1024)
      
      If *buffer
        MultiByteToWideChar_(#CP_ACP, 0, @ShortcutFile, -1, *buffer, 1024)
        
        If LinkFile\Load(*buffer, 0) = #S_OK
          If ShellLink\Resolve(0, 1) = #S_OK
            RtlZeroMemory_(*buffer, 1024)
            ShellLink\GetPath(*buffer, 1024, 0, 0)
            Result = PeekS(*buffer)
          EndIf
        EndIf 
        
        FreeMemory(*buffer)
      EndIf
      
      LinkFile\Release()
    EndIf
    
    ShellLink\Release()
  EndIf
  
  CoUninitialize_()
  
  ProcedureReturn Result
  
  
  DataSection 
  CLSID_ShellLink: 
    Data.l $00021401 
    Data.w $0000,$0000      
    Data.b $C0,$00,$00,$00,$00,$00,$00,$46 
    
  IID_IShellLink: 
    Data.l $000214EE 
    Data.w $0000,$0000 
    Data.b $C0,$00,$00,$00,$00,$00,$00,$46 
    
  IID_IPersistFile: 
    Data.l $0000010b 
    Data.w $0000,$0000 
    Data.b $C0,$00,$00,$00,$00,$00,$00,$46 
  EndDataSection 
EndProcedure



Procedure StartPureCopy()
  Protected File = CreateFile(#PB_Any, GetTemporaryDirectory() + "~purecopy.exe")
  
  If File
    WriteData(File, ?PURECOPY_INCLUDEEXECUTABLE1, ?PURECOPY_INCLUDEEXECUTABLE2 - ?PURECOPY_INCLUDEEXECUTABLE1)
    CloseFile(File)
    
    Protected Parameter.s = ""
    
    Parameter + InputFiles + Chr(1)
    Parameter + OutputFilepath + Chr(1)
    Parameter + Str(GetGadgetState(#Event_SubDirectories)) + Chr(1)
    Parameter + Str(GetGadgetState(#Event_SetFilePropertiesCreated) * #PURECOPY_PROPERTY_CREATED + GetGadgetState(#Event_SetFilePropertiesAccessed) * #PURECOPY_PROPERTY_ACCESSED + GetGadgetState(#Event_SetFilePropertiesModified) * #PURECOPY_PROPERTY_MODIFIED + GetGadgetState(#Event_SetFilePropertiesAttributes) * #PURECOPY_PROPERTY_ATTRIBUTES) + Chr(1)
    Parameter + Str(GetGadgetState(#Event_CompareRoutine)) + Chr(1)
    Parameter + Str(GetGadgetState(#Event_WaitOnError)) + Chr(1)
    Parameter + Str(GetGadgetState(#Event_SimultaneousTransfer))
    
    RunProgram(GetTemporaryDirectory() + "~purecopy.exe", Parameter, GetPathPart(ProgramFilename()))
  EndIf
EndProcedure







DrawFilepathIcon(#I_Input, "", #Param_Unknown)
DrawFilepathIcon(#I_Output, "", #Param_Unknown)



OpenWindow(#W_Main, 0, 0, 250, 210, "PureCopy", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
StickyWindow(#W_Main, 1)

ImageGadget(#Event_ImageInput, 5, 8, 32, 32, ImageID(#I_Input))
  EnableGadgetDrop(#Event_ImageInput, #PB_Drop_Files, #PB_Drag_Copy | #PB_Drag_Move | #PB_Drag_Link)
  
ButtonGadget(#Event_Start, 50, 5, 150, 40, "> > PureCopy > >")
  DisableGadget(#Event_Start, 1)
  
ImageGadget(#Event_ImageOutput, 210, 8, 32, 32, ImageID(#I_Output))
  EnableGadgetDrop(#Event_ImageOutput, #PB_Drop_Files, #PB_Drag_Copy | #PB_Drag_Move | #PB_Drag_Link)


Frame3DGadget(#PB_Any, 10, 50, 110, 90, "Options")
  CheckBoxGadget(#Event_SubDirectories, 20, 70, 90, 20, "Subdirectories")
    SetGadgetState(#Event_SubDirectories, 1)
  CheckBoxGadget(#Event_WaitOnError, 20, 90, 90, 20, "Wait on error")
  CheckBoxGadget(#Event_SimultaneousTransfer, 20, 110, 90, 20, "Simultaneous")
    SetGadgetState(#Event_SimultaneousTransfer, 1)
    
Frame3DGadget(#PB_Any, 10, 150, 110, 50, "Compare routine")
  ComboBoxGadget(#Event_CompareRoutine, 20, 170, 90, 22)
    AddGadgetItem(#Event_CompareRoutine, #PURECOPY_COMPARE_NONE, "None")
    AddGadgetItem(#Event_CompareRoutine, #PURECOPY_COMPARE_DATE, "Date")
    AddGadgetItem(#Event_CompareRoutine, #PURECOPY_COMPARE_CRC, "CRC checksum")
    AddGadgetItem(#Event_CompareRoutine, #PURECOPY_COMPARE_SIZE, "Size")
    AddGadgetItem(#Event_CompareRoutine, #PURECOPY_COMPARE_EXISTS, "Exists")
    AddGadgetItem(#Event_CompareRoutine, #PURECOPY_COMPARE_ASKCALLBACK, "Ask")
    SetGadgetState(#Event_CompareRoutine, #PURECOPY_COMPARE_DATE)
    
Frame3DGadget(#PB_Any, 130, 50, 110, 105, "Set file properties")
  CheckBoxGadget(#Event_SetFilePropertiesCreated, 140, 70, 90, 20, "Created")
    SetGadgetState(#Event_SetFilePropertiesCreated, 1)
  CheckBoxGadget(#Event_SetFilePropertiesAccessed, 140, 90, 90, 20, "Accessed")
    SetGadgetState(#Event_SetFilePropertiesAccessed, 1)
  CheckBoxGadget(#Event_SetFilePropertiesModified, 140, 110, 90, 20, "Modified")
    SetGadgetState(#Event_SetFilePropertiesModified, 1)
  CheckBoxGadget(#Event_SetFilePropertiesAttributes, 140, 130, 90, 20, "File attributes")
    SetGadgetState(#Event_SetFilePropertiesAttributes, 1)



TextGadget(#PB_Any, 130, 165, 110, 18, "Copyright:", #PB_Text_Center)
HyperLinkGadget(#Event_Website, 143, 183, 82, 20, "Daniel Obermeier", $FF0000)




Repeat
  Define EventID = WaitWindowEvent()
  
  Select EventID
  Case #PB_Event_CloseWindow
    End
    
    
  Case #PB_Event_GadgetDrop
    Select EventGadget()
    Case #Event_ImageInput
      InputFilepath = EventDropFiles()
      FilesCount = CountString(InputFilepath, #LF$) + 1
      
      InputFiles = ""
      For FileIndex = 1 To FilesCount
        InputFiles + ShortcutTarget(StringField(InputFilepath, FileIndex, #LF$)) + #LF$
      Next
      InputFiles = Left(InputFiles, Len(InputFiles) - 1)
      
      If FilesCount = 1
        DrawFilepathIcon(#I_Input, InputFiles, #Param_Default)
        SetGadgetState(#Event_ImageInput, ImageID(#I_Input))
      Else
        DrawFilepathIcon(#I_Input, "", #Param_Directory)
        SetGadgetState(#Event_ImageInput, ImageID(#I_Input))
      EndIf
      
      GadgetToolTip(#I_Input, InputFiles)
      
      If OutputFilepath
        DisableGadget(#Event_Start, 0)
      EndIf
      
      
    Case #Event_ImageOutput
      OutputFilepath = EventDropFiles()
      FilesCount = CountString(OutputFilepath, Chr(10)) + 1
      
      GadgetToolTip(#I_Output, OutputFilepath)
      
      If FilesCount = 1
        OutputFilepath = ShortcutTarget(OutputFilepath)
        
        If FileSize(OutputFilepath) <> -2
          OutputFilepath = GetPathPart(OutputFilepath)
        EndIf
        
        DrawFilepathIcon(#I_Output, OutputFilepath, #Param_Default)
        SetGadgetState(#Event_ImageOutput, ImageID(#I_Output))
        
        If InputFiles
          DisableGadget(#Event_Start, 0)
        EndIf
      Else
        DrawFilepathIcon(#I_Output, OutputFilepath, #Param_Unknown)
        SetGadgetState(#Event_ImageOutput, ImageID(#I_Output))
        
        DisableGadget(#Event_Start, 1)
        OutputFilepath = ""
      EndIf
      
      GadgetToolTip(#I_Output, OutputFilepath)
    EndSelect
    
    
  Case #PB_Event_Gadget
    Select EventGadget()
    Case #Event_ImageOutput
      If EventType() = #PB_EventType_LeftClick
        OutputFilepathTemp.s = PathRequester("Choose output directory", OutputFilepath)
        If OutputFilepathTemp
          OutputFilepath = OutputFilepathTemp
          
          DrawFilepathIcon(#I_Output, OutputFilepath, #Param_Default)
          SetGadgetState(#Event_ImageOutput, ImageID(#I_Output))
          
          DisableGadget(#Event_Start, 0)
        EndIf
      EndIf
      
    Case #Event_Website
      RunProgram("http://www.jilocasin.de")
      
    Case #Event_Start
      StartPureCopy()
      
    EndSelect
  EndSelect
  
  
ForEver



DataSection
  PURECOPY_INCLUDEEXECUTABLE1:
    IncludeBinary "PureCopy_IncludeExecutable.exe"
  PURECOPY_INCLUDEEXECUTABLE2:
EndDataSection
Bild
Benutzeravatar
Arrag0n
Beiträge: 32
Registriert: 24.06.2005 20:49
Wohnort: Austria
Kontaktdaten:

Re: PureCopy

Beitrag von Arrag0n »

@Jilocasin
Gute Arbeit und vielen Dank fürs Teilen. :allright:
Soetwas hab ich genau gesucht.

Arrag0n
Aus den Steinen, die einem in den Weg gelegt werden, kann man Schönes bauen.
Antworten