#include-once
#include <File.au3>
#include <Array.au3>

; =========================================================================================================
;  _SaveFileCopy($Parm_Src, $Parm_Dest, $Parm_Flag=0)
;
; Funktion:		Kopiert eine oder mehrere Datei(en).
;
; $Parm_Src:	Die Quelldatei(en) - Wildcards werden unterstützt.
;
; $Parm_Dest:	Das Zielverzeichnis der zu kopierenden Datei(en).
;
; $Parm_Flag [optional]:	Dieses Flag bestimmt, ob Dateien überschrieben werden, falls sie schon bestehen.
; 				 	$Parm_Flag kann eine Kombination der folgenden sein:
;   				  0 = (Standard) bestehende Dateien nicht überschreiben
; 					  1 = Überschreiben bestehender Dateien
; 					  8 = Erstellt die Zielverzeichnisstruktur, falls diese nicht besteht.
;
; Bemerkung:	Wenn Flag eine gerade Zahl ist und die Zieldatei schon existiert, wird der Zielname um ein
; 					' (n)' vor der Dateierweiterung ergänzt (n = Zahl ab 2, wobei Zielname noch nicht existiert)
; 					analog zum Verhalten des Windows Explorers mit der Option beide Dateien behalten.
;
; Rückgabe:		Erfolg - Gibt 1 zurück.
;					Fehlerfall - Gibt 0 zurück.
;
; Beispiel: 	Der kombinierte Flagwert '9' (1 + 8) überschreibt das Zielverzeichnis und prüft vorher, ob
;           	die Zielverzeichnisstruktur besteht und erstellt sie gegebenenfalls automatisch.
; =========================================================================================================
Func _SaveFileCopy($Parm_Src, $Parm_Dest, $Parm_Flag=0)
	Local $Loc_Searchhandle, $Loc_SrcFilename
	Local $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt
	Local $Loc_RV=1  ; Standardrückgabe = ok, ein einzelner Fehler setzt Rückgabe auf 0

	If BitAND($Parm_Flag, 1) = 1 then	; Zieldateien überschrieben?
		; Wenn ja, dann Standard FileCopy() Funktion verwenden
		FileCopy($Parm_Src, $Parm_Dest, $Parm_Flag)
	Else	; Zieldateien nicht überschrieben
		If ((StringInStr($Parm_Src,"*")>0) Or (StringInStr($Parm_Src,"?")>0)) Then
			; Wildcard benutzt
			; Dann alle möglichen Quelldateien bestimmen
			$Loc_Searchhandle = FileFindFirstFile($Parm_Src)

			; Prüfen, ob die Suche erfolgreich war
			If ($Loc_Searchhandle = -1) Then	; Keine Datei entspricht Suchmuster in $Parm_Src
				Return 0
			else								; Mindestens eine Quelldatei entspricht Suchmuster in $Parm_Src
				While 1								; Endlosschleife
					;                          		 ; Suche Namen einer passenden Quelldatei
					$Loc_SrcFilename = FileFindNextFile($Loc_Searchhandle)
					If @error Then 					; bis alle Quelldateien überprüft
						ExitLoop
					else							; ansonsten kopiere Quelldatei
														; FileFindNextFile findet nur den Dateinamen ohne Pfad
														; deshalb ergänzen um Quelllaufwerk und Quellpfad
						_PathSplit(_CompletePath($Parm_Src), $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt)
						If (_SaveCopySingleFile($Loc_SrcDrive&$Loc_SrcDir&$Loc_SrcFilename, $Parm_Dest, $Parm_Flag)=0) then
							$Loc_RV=0					; und setzte Rückgabewert auf 0 ( = Fehler)
														; wenn mindestens ein Fehler aufgetreten
						EndIf
					EndIf
				WEnd								; Ende Schleife
				FileClose($Loc_Searchhandle)		; Am Ende Handle für Suche wieder schliessen
				Return ($Loc_RV)
			EndIf
		Else	; Keine Wildcards
			Return (_SaveCopySingleFile($Parm_Src, $Parm_Dest, $Parm_Flag))
		EndIf
	EndIf	; Ende Zieldateien nicht überschrieben

EndFunc


; =========================================================================================================
;  _SaveCopySingleFile($Parm_Src, $Parm_Dest, $Parm_Flag=0)
;
; Funktion:		Kopiert eine einzelne Datei.
;
; $Parm_Src:	Die Quelldatei (relativ oder vollem Pfad) - Wildcards werden nicht unterstützt.
;
; $Parm_Dest:	Das Zielverzeichnis (mit abschliessenden Backslash) oder die Zieldatei.
;
; $Parm_Flag [optional]:	Dieses Flag bestimmt, ob die Zieldatei überschrieben wird, falls sie schon besteht.
; 					$Parm_Flag kann eine Kombination der folgenden sein:
;   				  0 = (Standard) bestehende Dateie nicht überschreiben
; 					  1 = Überschreiben der bestehenden Datei
; 					  8 = Erstellt die Zielverzeichnisstruktur, falls diese nicht besteht.
;
; Bemerkung:	Wenn Flag eine gerade Zahl ist und die Zieldatei schon existiert, wird der Zielname um ein
; 					' (n)' vor der Dateierweiterung ergänzt (n = Zahl ab 2, wobei Zielname noch nicht existiert)
; 					analog zum Verhalten des Windows Explorers mit der Option 'beide Dateien behalten'.
;
; Rückgabe:		Erfolg - Gibt 1 zurück.
;					Fehlerfall - Gibt 0 zurück.
;
; Beispiel: 	Der kombinierte Flagwert '9' (1 + 8) überschreibt das Zielverzeichnis und prüft vorher, ob
;    		      die Zielverzeichnisstruktur besteht und erstellt sie gegebenenfalls automatisch.
; =========================================================================================================
Func _SaveCopySingleFile($Parm_Src, $Parm_Dest, $Parm_Flag=0)
	Local $Loc_FullDestFileName, $Loc_Count, $Loc_NewDest, $Loc_DestArray, $Loc_SrcArray
	Local $Loc_DestDrive, $Loc_DestDir, $Loc_DestName, $Loc_DestExt
	Local $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt

	If BitAND($Parm_Flag, 1) = 1 then	; Zieldateien überschrieben?
		; Wenn ja, dann Standard FileCopy() Funktion verwenden
		FileCopy($Parm_Src, $Parm_Dest, $Parm_Flag)
	Else								; Zieldatei nicht überschreiben
		If Not ((StringInStr($Parm_Src,"*")>0) Or (StringInStr($Parm_Src,"?")>0)) Then
			; No Wildcards
			If StringRight(StringStripWS($Parm_Dest,2),1)="\" Then	; Ziel ist ein Verzeichnis
				; dann Dateiname und Dateiextension für Zieldatei aus Quelle bestimmen
				_PathSplit(_CompletePath($Parm_Dest), $Loc_DestDrive, $Loc_DestDir, $Loc_DestName, $Loc_DestExt)
				_PathSplit($Parm_Src, $Loc_SrcDrive, $Loc_SrcDir, $Loc_SrcName, $Loc_SrcExt)
				; Absoluter Zieldateiname ohne Extenstion = Ziellaufwerk + Zielverzeichnis + Quelldateiname
				$Loc_FullDestFileName = $Loc_DestDrive & $Loc_DestDir & $Loc_SrcName
				; Zieldateiextension = Quellextension
				$Loc_DestExt=$Loc_SrcExt
			Else													; Ziel ist eine Datei
				; dann Dateiname und Dateiextension für Zieldatei aus Ziel bestimmen
				$Loc_DestArray = _PathSplit(_CompletePath($Parm_Dest), $Loc_DestDrive, $Loc_DestDir, $Loc_DestName, $Loc_DestExt)
				; Absoluter Zieldateiname ohne Extenstion = Ziellaufwerk + Zielverzeichnis + Zieldateiname
				$Loc_FullDestFileName=$Loc_DestDrive & $Loc_DestDir & $Loc_DestName
			EndIf													; Ende Ziel ist eine Datei

			$Loc_Count=1											; Analog zu Windows beim 1. Versuch 'Dateiname',
			$Loc_NewDest=$Loc_FullDestFileName						; dann 'Dateiname (2)', ... usw. in $Loc_NewDest

			While FileExists($Loc_NewDest&$Loc_DestExt)				; Durchlaufe Schleife bis Dateiname nicht existiert
				$Loc_Count+=1											; Zähler um 1 erhöhen
				$Loc_NewDest = $Loc_FullDestFileName & " ("&$Loc_Count&")"
			WEnd													; Ende Schleife
			Return (FileCopy ($Parm_Src, $Loc_NewDest&$Loc_DestExt, $Parm_Flag))
		Else													; Wildcards sind nicht erlaubt - also Rückgabewert 0
			Return 0
		EndIf													; Ende Wildcards
	EndIf								; Ende Zieldatei nicht überschreiben
EndFunc

; =========================================================================================================
; Func _CompletePath($Parm_Path)
;
; Funktion:		Ergänzt - falls notwendig - den angegebenen relativen Pfad zu einem absoluten Pfad
;
; $Parm_Path:	Übergebener absoluter oder relativer Pfad
;
; Rückgabe:		Zugehöriger absoluter Pfad
;
; =========================================================================================================
Func _CompletePath($Parm_Path)

	If (StringLeft($Parm_Path,1)=".") Then 			; Bei relativen Pfaden mit die mit '.'
													; oder '..' beginnen
		$Parm_Path=_PathFull($Parm_Path)				; Absoluter Pfad relativ zu Arbeitsverzeichnis
														; berechnen
	ElseIf not (StringInStr($Parm_Path,":")>0) then	; Bei Pfaden etwas ohne Laufwerkbuchstaben
		if Not (StringLeft($Parm_Path,1)="\") then		; Pfade ohne beginnendes Backslash
			$Parm_Path=_PathFull($Parm_Path)				; Absoluter Pfad relativ zu Arbeitsverzeichnis
															; berechnen
		Elseif Not (StringLeft($Parm_Path,2)="\\") then	; oder Pfade die EINEM Backslash beginnen
														; (also keine UNC-Pfade)
			$Parm_Path=StringLeft(@WorkingDir,2)&$Parm_Path	; Pfad um Laufwerk des Arbeitsverzeichnisses
															; ergänzen
		EndIf
	EndIf 												; Ende Pfad ohne Laufwerkbuchstaben
	; (Bei UNC- oder absoluten Pfaden mit Laufwerksbuchstaben - Eingabe unverändert zurückgeben)
	Return $Parm_Path
EndFunc

