Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 98 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,102 @@
# Modern Delphi 12.3 .gitignore
#
#-------------------------------------------------------------------------------
# Delphi / C++Builder Compiled Output & Binaries
#-------------------------------------------------------------------------------
*.exe
*.dll
*.so
*.a
*.lib
*.bpl
*.dcp
*.dcu
*.bkm
*.obj
*.o

# Compiled resource files
*.res

#-------------------------------------------------------------------------------
# IDE Generated, User-Specific & Intermediate Files
#-------------------------------------------------------------------------------
*.~*
*.bak
*.old

# Delphi 7 and Delphi 6 Diagram Portfolio
*.ddp

# Delphi 7 (and older) Project Configuration filed automatically created by command line compiler
*.cfg

# General temporary files
*.tmp

# General temporary files
*.temp

*.local
*.dsk
*.cfg
*.map
*.tds
*.drc
*.zip
dcu
*.rsm
*.log
*.pch
*.ipch
*.stat
*.identcache
*.dproj.local
*.dproj.user
*.groupproj.local
*.groupproj.user

# Delphi IDE bookmarks
*.bkm

# TestInsight configuration files
*.tvsconfig

# Files with .history extension
*.history

# Legacy project files
*.dof
*.kof

#-------------------------------------------------------------------------------
# IDE History, Recovery & Autosave
#-------------------------------------------------------------------------------
**/__history/
**/__recovery/
*.autosave

#-------------------------------------------------------------------------------
# Output Directories (using **/ to match at any depth)
#-------------------------------------------------------------------------------
**/Win32/
**/Win64/
**/Debug/
**/Release/

# Cross-platform output folders
**/Linux64/
**/OSX64/
**/OSXARM64/
**/Android/
**/Android64/
**/iOSDevice32/
**/iOSDevice64/
**/iOSSimulator/

#-------------------------------------------------------------------------------
# Common Temporary / Local / Sensitive Files (General)
#-------------------------------------------------------------------------------
# General compressed archives (often backups or downloads)
*.zip

# Environment variable files (CRITICAL for sensitive data)
*.env

131 changes: 94 additions & 37 deletions Main.pas
Original file line number Diff line number Diff line change
Expand Up @@ -210,46 +210,103 @@ procedure TfrmUI.FormCreate(Sender: TObject);
End;
end;

// Place this function in a common unit or in the same unit as your form.
// By Gemini 2.5 Pro
function WidePosEx(const SubStr: WideString; const S: WideString; StartPos: Integer = 1): Integer;
var
I, J: Integer;
Found: Boolean;
begin
Result := 0;
if (Length(SubStr) = 0) then
begin
if (StartPos > Length(S) + 1) or (StartPos < 1) then
Exit;
Result := StartPos;
Exit;
end;

if (StartPos < 1) or (StartPos > Length(S) - Length(SubStr) + 1) then
Exit;

for I := StartPos to Length(S) - Length(SubStr) + 1 do
begin
Found := True;
for J := 1 to Length(SubStr) do
begin
if S[I + J - 1] <> SubStr[J] then
begin
Found := False;
Break;
end;
end;
if Found then
begin
Result := I;
Exit;
end;
end;
end;

// By Gemini 2.5 Pro
Procedure TfrmUI.SaveSettings;
var
reg: TTntRegistry;
diskSize: Int64;
i:Integer;
s:WideString;
Begin
reg:=TTntRegistry.Create(KEY_WRITE);
Try
reg.RootKey:=HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\'+serviceName, True) then
begin
diskSize:=StrToInt64(vdSize.Text);
If radioMB.Checked then diskSize:=diskSize Shl 20 Else diskSize:=diskSize shl 30;
i:=0;
while i<memoIgnore.Lines.Count Do
Begin
s:=Trim(memoIgnore.Lines[i]);
If s[2]=':' then s:=Copy(s,4,MaxInt);
If (s='')or(WidePosEx('\',s)>0)or(WidePosEx('/',s)>0) then memoIgnore.Lines.Delete(i)
else
Begin
memoIgnore.Lines[i]:=s;
Inc(i);
end;
end;
reg.WriteString('DiskSize',IntToStr(diskSize));
reg.WriteString('DriveLetter',comboLetter.Text);
reg.WriteString('LoadContent',editFolder.Text);
reg.WriteString('ExcludeFolders',memoIgnore.Lines.Text);
reg.WriteBool('UseTempFolder',chkTemp.Checked);
reg.WriteBool('SyncContent',chkSync.Checked);
reg.WriteBool('DeleteOld',chkDelete.Checked);
Reg.CloseKey;
end;
Finally
reg.Free;
End;
var
reg: TTntRegistry;
diskSize: Int64;
i: Integer;
s: WideString;
Begin
reg := TTntRegistry.Create(KEY_WRITE);
Try
reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\' + serviceName, True) then
begin
diskSize := StrToInt64(vdSize.Text);
If radioMB.Checked then
diskSize := diskSize shl 20
Else
diskSize := diskSize shl 30;

// Corrected loop logic to handle deletions without skipping items
i := 0;
while i < memoIgnore.Lines.Count do
begin
s := Trim(memoIgnore.Lines[i]);

// This is a check for a drive letter and colon, e.g., "C:"
if (Length(s) >= 2) and (s[2] = ':') then
s := Copy(s, 4, MaxInt); // Correctly gets the rest of the path

// Check for empty string, backslash, or forward slash
// We use the custom WidePosEx function to find the characters
if (s = '') or (WidePosEx('\', s) > 0) or (WidePosEx('/', s) > 0) then
begin
memoIgnore.Lines.Delete(i);
// Do NOT increment i, because the next item is now at the same index
end
else
begin
memoIgnore.Lines[i] := s;
Inc(i); // ONLY increment if a line was NOT deleted
end;
end;

// The rest of your code remains the same
reg.WriteString('DiskSize', IntToStr(diskSize));
reg.WriteString('DriveLetter', comboLetter.Text);
reg.WriteString('LoadContent', editFolder.Text);
reg.WriteString('ExcludeFolders', memoIgnore.Lines.Text);
reg.WriteBool('UseTempFolder', chkTemp.Checked);
reg.WriteBool('SyncContent', chkSync.Checked);
reg.WriteBool('DeleteOld', chkDelete.Checked);
Reg.CloseKey;
end;
Finally
reg.Free;
End;
end;


procedure TfrmUI.UpdateLetters;
var
freeLetters: TAssignedDrives;
Expand Down
80 changes: 80 additions & 0 deletions RamSync.pas
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ procedure TreeDelete(const src,dest:WideString;excluded:TTntStringList);
WideFindClose(SR);
end;

(*

// old split path
Procedure SplitPath(const path:WideString;var list:TStrArray);
var
oldPos,newPos,k:Integer;
Expand All @@ -315,6 +318,83 @@ procedure TreeDelete(const src,dest:WideString;excluded:TTntStringList);
SetLength(list,k);
end;

*)

// Make sure to place WidePosExChar above SplitPath or in an interface section
// New WidePosExChar by Gemini 2.5 Pro
function WidePosExChar(const SearchChar: WideChar; const S: WideString; StartPos: Integer = 1): Integer;
var
I: Integer;
begin
Result := 0; // Not found by default
for I := StartPos to Length(S) do
begin
if S[I] = SearchChar then
begin
Result := I;
Exit;
end;
end;
end;

// Assuming TStrArray is defined as array of WideString, e.g.:
// type
// TStrArray = array of WideString;

// new SplitPath by Gemini 2.5 Pro
Procedure SplitPath(const path:WideString;var list:TStrArray);
var
oldPos, newPos, k: Integer;
Begin
// Initialize list with a reasonable capacity. Length(path) is an overestimate,
// but ensures enough initial space. It will be trimmed later.
SetLength(List, Length(path) div 2 + 1); // More realistic initial size for paths
if Length(path) = 0 then // Handle empty path case
begin
SetLength(list, 0);
Exit;
end;

k := 0;
oldPos := 1;
Repeat
// Use your WidePosExChar function here
newPos := WidePosExChar('\', path, oldPos);

if newPos = 0 then // No more delimiters found, this is the last segment
Begin
list[k] := Copy(path, oldPos, MaxInt); // Copy to the end of the string
Inc(k);
Break; // Exit the loop as we've processed the last segment
End
Else // Delimiter found
Begin
// Copy the segment from oldPos up to (but not including) the delimiter
list[k] := Copy(path, oldPos, newPos - oldPos);
Inc(k);
// Move oldPos to the character *after* the delimiter
oldPos := newPos + 1;
End;

// Check if oldPos has gone beyond the string length,
// which can happen if the path ends with a delimiter.
// If it does, and there's an empty segment at the end, add it.
if (oldPos > Length(path)) and (newPos <> 0) then // newPos=0 indicates last segment was handled
begin
// Add an empty string if the path ended with a backslash and we're at the end
if (path[Length(path)] = '\') then // Only if the original string ended with '\'
begin
list[k] := '';
Inc(k);
end;
Break;
end;

Until False; // Use Break to exit the loop once last segment is processed

SetLength(list, k); // Trim the list to the actual number of segments
end;

Procedure SaveRamDisk(Var existing:TRamDisk);
var
list:TTntStringList;
Expand Down
Loading