summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Application.cpp2
-rw-r--r--BUILD/Changelog.txt17
-rw-r--r--BUILD/FreeFileSync.chmbin671768 -> 672005 bytes
-rw-r--r--BUILD/Help/html/ComparisonSettings.html10
-rw-r--r--BUILD/Help/html/FreeFileSync.html18
-rw-r--r--BUILD/Help/html/RealtimeSync.html6
-rw-r--r--BUILD/Help/html/RunAsService.html12
-rw-r--r--BUILD/Help/html/ScheduleBatch.html10
-rw-r--r--BUILD/Help/html/ScheduleBatch_html_372f0f3.gifbin20148 -> 0 bytes
-rw-r--r--BUILD/Help/html/ShadowCopy.html2
-rw-r--r--BUILD/Help/html/VariableDrive.html2
-rw-r--r--BUILD/Help/html/scheduleBatch_html_13615436.gifbin27319 -> 0 bytes
-rw-r--r--BUILD/Help/html/scheduleBatch_html_28bb3203.gifbin28325 -> 0 bytes
-rw-r--r--BUILD/Help/html/scheduleBatch_html_m22c860a2.gifbin27294 -> 0 bytes
-rw-r--r--BUILD/Help/img/CmpSettings.png (renamed from BUILD/Help/html/CmpSettings.png)bin28812 -> 28854 bytes
-rw-r--r--BUILD/Help/img/CompareButton.png (renamed from BUILD/Help/html/CompareButton.png)bin4856 -> 4856 bytes
-rw-r--r--BUILD/Help/img/ErrorHandling.png (renamed from BUILD/Help/html/ErrorHandling.png)bin28680 -> 28680 bytes
-rw-r--r--BUILD/Help/img/MainDialog.png (renamed from BUILD/Help/html/MainDialog.png)bin76362 -> 76362 bytes
-rw-r--r--BUILD/Help/img/RealtimeSync.png (renamed from BUILD/Help/html/RealtimeSync.png)bin32699 -> 32699 bytes
-rw-r--r--BUILD/Help/img/RunAsService_html_17e8fbfe.png (renamed from BUILD/Help/html/RunAsService_html_17e8fbfe.png)bin9916 -> 9916 bytes
-rw-r--r--BUILD/Help/img/RunAsService_html_4f230a46.png (renamed from BUILD/Help/html/RunAsService_html_4f230a46.png)bin16072 -> 16072 bytes
-rw-r--r--BUILD/Help/img/RunAsService_html_68e0fe53.png (renamed from BUILD/Help/html/RunAsService_html_68e0fe53.png)bin7391 -> 7391 bytes
-rw-r--r--BUILD/Help/img/RunAsService_html_7aa44556.png (renamed from BUILD/Help/html/RunAsService_html_7aa44556.png)bin101229 -> 101229 bytes
-rw-r--r--BUILD/Help/img/RunAsService_html_bf02de4e.png (renamed from BUILD/Help/html/RunAsService_html_bf02de4e.png)bin13958 -> 13958 bytes
-rw-r--r--BUILD/Help/img/RunAsService_html_m3be0f332.png (renamed from BUILD/Help/html/RunAsService_html_m3be0f332.png)bin16574 -> 16574 bytes
-rw-r--r--BUILD/Help/img/RunAsService_html_m3e56d901.png (renamed from BUILD/Help/html/RunAsService_html_m3e56d901.png)bin72687 -> 72687 bytes
-rw-r--r--BUILD/Help/img/RunMinimized.png (renamed from BUILD/Help/html/RunMinimized.png)bin41946 -> 41946 bytes
-rw-r--r--BUILD/Help/img/ScheduleBatch_html_m10bf0d36.gif (renamed from BUILD/Help/html/ScheduleBatch_html_m10bf0d36.gif)bin21107 -> 21107 bytes
-rw-r--r--BUILD/Help/img/SourceTarget.png (renamed from BUILD/Help/html/SourceTarget.png)bin4857 -> 4857 bytes
-rw-r--r--BUILD/Help/img/SyncConfigButton.png (renamed from BUILD/Help/html/SyncConfigButton.png)bin2813 -> 2813 bytes
-rw-r--r--BUILD/Help/img/SynchronizeButton.png (renamed from BUILD/Help/html/SynchronizeButton.png)bin5109 -> 5109 bytes
-rw-r--r--BUILD/Help/img/VolumeName.png (renamed from BUILD/Help/html/VolumeName.png)bin5553 -> 5553 bytes
-rw-r--r--BUILD/Help/img/WatchUsbInsert.png (renamed from BUILD/Help/html/WatchUsbInsert.png)bin34801 -> 34801 bytes
-rw-r--r--BUILD/Help/img/ffsicon.png (renamed from BUILD/Help/html/ffsicon.png)bin7709 -> 7709 bytes
-rw-r--r--BUILD/Help/img/menuAdv.png (renamed from BUILD/Help/html/menuAdv.png)bin2711 -> 2711 bytes
-rw-r--r--BUILD/Help/img/menuFile.png (renamed from BUILD/Help/html/menuFile.png)bin5574 -> 5574 bytes
-rw-r--r--BUILD/Help/img/menuHelp.png (renamed from BUILD/Help/html/menuHelp.png)bin1823 -> 1823 bytes
-rw-r--r--BUILD/Help/img/rtsicon.png (renamed from BUILD/Help/html/rtsicon.png)bin7462 -> 7462 bytes
-rw-r--r--BUILD/Help/img/ubuntuScheduler.png (renamed from BUILD/Help/html/ubuntuScheduler.png)bin53376 -> 53376 bytes
-rw-r--r--BUILD/Help/img/win7scheduler.png (renamed from BUILD/Help/html/win7scheduler.png)bin29311 -> 29311 bytes
-rw-r--r--BUILD/Languages/chinese_simple.lng426
-rw-r--r--BUILD/Languages/chinese_traditional.lng438
-rw-r--r--BUILD/Languages/croatian.lng1490
-rw-r--r--BUILD/Languages/czech.lng448
-rw-r--r--BUILD/Languages/danish.lng442
-rw-r--r--BUILD/Languages/dutch.lng432
-rw-r--r--BUILD/Languages/english_uk.lng442
-rw-r--r--BUILD/Languages/finnish.lng98
-rw-r--r--BUILD/Languages/french.lng432
-rw-r--r--BUILD/Languages/german.lng76
-rw-r--r--BUILD/Languages/greek.lng78
-rw-r--r--BUILD/Languages/hebrew.lng444
-rw-r--r--BUILD/Languages/hungarian.lng76
-rw-r--r--BUILD/Languages/italian.lng442
-rw-r--r--BUILD/Languages/japanese.lng104
-rw-r--r--BUILD/Languages/korean.lng436
-rw-r--r--BUILD/Languages/polish.lng448
-rw-r--r--BUILD/Languages/portuguese.lng432
-rw-r--r--BUILD/Languages/portuguese_br.lng448
-rw-r--r--BUILD/Languages/romanian.lng464
-rw-r--r--BUILD/Languages/russian.lng438
-rw-r--r--BUILD/Languages/slovenian.lng454
-rw-r--r--BUILD/Languages/spanish.lng444
-rw-r--r--BUILD/Languages/swedish.lng442
-rw-r--r--BUILD/Languages/turkish.lng98
-rw-r--r--BUILD/Languages/ukrainian.lng438
-rw-r--r--BUILD/Resources.zipbin250353 -> 272977 bytes
-rw-r--r--FreeFileSync.cbp6
-rw-r--r--RealtimeSync/RealtimeSync.cbp4
-rw-r--r--RealtimeSync/watcher.cpp13
-rw-r--r--algorithm.cpp185
-rw-r--r--algorithm.h4
-rw-r--r--comparison.cpp127
-rw-r--r--comparison.h2
-rw-r--r--file_hierarchy.cpp227
-rw-r--r--file_hierarchy.h191
-rw-r--r--lib/custom_grid.cpp169
-rw-r--r--lib/db_file.cpp476
-rw-r--r--lib/db_file.h5
-rw-r--r--lib/detect_renaming.cpp285
-rw-r--r--lib/detect_renaming.h26
-rw-r--r--lib/dir_exist_async.h4
-rw-r--r--lib/dir_lock.cpp16
-rw-r--r--lib/dir_name.cpp2
-rw-r--r--lib/localization.cpp1
-rw-r--r--lib/parallel_scan.cpp15
-rw-r--r--lib/status_handler.h18
-rw-r--r--structures.cpp126
-rw-r--r--structures.h56
-rw-r--r--synchronization.cpp1423
-rw-r--r--synchronization.h49
-rw-r--r--ui/batch_status_handler.cpp10
-rw-r--r--ui/batch_status_handler.h10
-rw-r--r--ui/grid_view.cpp4
-rw-r--r--ui/gui_generated.cpp369
-rw-r--r--ui/gui_generated.h99
-rw-r--r--ui/gui_status_handler.cpp20
-rw-r--r--ui/gui_status_handler.h20
-rw-r--r--ui/main_dlg.cpp81
-rw-r--r--ui/progress_indicator.cpp75
-rw-r--r--ui/small_dlgs.cpp16
-rw-r--r--ui/sync_cfg.cpp41
-rw-r--r--ui/wx_form_build_hide_warnings.h6
-rw-r--r--version/version.h2
-rw-r--r--version/version.rc4
-rw-r--r--wx+/format_unit.cpp2
-rw-r--r--wx+/format_unit.h2
-rw-r--r--wx+/serialize.h114
-rw-r--r--zen/FindFilePlus/FindFilePlus.vcxproj (renamed from lib/FindFilePlus/FindFilePlus.vcxproj)0
-rw-r--r--zen/FindFilePlus/dll_main.cpp (renamed from lib/FindFilePlus/dll_main.cpp)0
-rw-r--r--zen/FindFilePlus/find_file_plus.cpp (renamed from lib/FindFilePlus/find_file_plus.cpp)0
-rw-r--r--zen/FindFilePlus/find_file_plus.h (renamed from lib/FindFilePlus/find_file_plus.h)2
-rw-r--r--zen/FindFilePlus/init_dll_binding.h (renamed from lib/FindFilePlus/init_dll_binding.h)0
-rw-r--r--zen/FindFilePlus/load_dll.cpp (renamed from lib/FindFilePlus/load_dll.cpp)0
-rw-r--r--zen/FindFilePlus/load_dll.h (renamed from lib/FindFilePlus/load_dll.h)0
-rw-r--r--zen/dir_watcher.cpp54
-rw-r--r--zen/dir_watcher.h3
-rw-r--r--zen/file_handling.cpp84
-rw-r--r--zen/file_handling.h7
-rw-r--r--zen/file_id.cpp13
-rw-r--r--zen/file_id.h5
-rw-r--r--zen/file_id_def.h65
-rw-r--r--zen/file_id_internal.h48
-rw-r--r--zen/file_traverser.cpp767
-rw-r--r--zen/file_traverser.h7
-rw-r--r--zen/guid.h2
-rw-r--r--zen/int64.h4
-rw-r--r--zen/long_path_prefix.h1
-rw-r--r--zen/notify_removal.cpp41
-rw-r--r--zen/privilege.cpp80
-rw-r--r--zen/privilege.h47
-rw-r--r--zen/process_status.h40
-rw-r--r--zen/stl_tools.h46
-rw-r--r--zen/symlink_target.h2
-rw-r--r--zen/time.h5
135 files changed, 8881 insertions, 7236 deletions
diff --git a/Application.cpp b/Application.cpp
index 24763493..e15b3db0 100644
--- a/Application.cpp
+++ b/Application.cpp
@@ -369,7 +369,7 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet
syncProc.startSynchronizationProcess(syncProcessCfg, folderCmp);
- //play (optional) sound notification after sync has completed
+ //play (optional) sound notification after sync has completed -> don't play in silent mode, consider RealtimeSync!
if (!batchCfg.silent)
{
const wxString soundFile = toWx(getResourceDir()) + wxT("Sync_Complete.wav");
diff --git a/BUILD/Changelog.txt b/BUILD/Changelog.txt
index dbe9bd75..7116b447 100644
--- a/BUILD/Changelog.txt
+++ b/BUILD/Changelog.txt
@@ -2,8 +2,19 @@
|FreeFileSync|
--------------
+Changelog v4.3
+--------------
+Detection of moved and renamed files
+New database format for <Automatic> mode: a full sync is suggested before upgrading
+Fixed overwrite symlink with regular file
+Fixed synchronization result dialog GUI glitch (Windows XP)
+Fixed macro %weekday%
+RealtimeSync: Fixed support for manual volume unmount (Windows)
+Added Croatian language
+
+
Changelog v4.2
----------------
+--------------
Implemented workaround for compiler bug leading to uncaught exceptions (Windows 32 bit)
Shadow Copy Service: Native support for Windows7/Server 2008
Fixed reference by volume name parsing issue
@@ -17,7 +28,7 @@ New option in GlobalSettings.xml: "RunWithBackgroundPriority" (Windows Vista and
Changelog v4.1
----------------
+--------------
Improved synchronization progress dialog
Show all available aliases in directory history list
Show password prompt when connecting to mapped network share
@@ -31,7 +42,7 @@ Allow passing multiple directory names via command line
Changelog v4.0
----------------
+--------------
Thumbnail list view
Option to specify comparison settings at folder pair level
Correctly update parent-child relationship when changing sync directions
diff --git a/BUILD/FreeFileSync.chm b/BUILD/FreeFileSync.chm
index 7a38d187..cc0d3174 100644
--- a/BUILD/FreeFileSync.chm
+++ b/BUILD/FreeFileSync.chm
Binary files differ
diff --git a/BUILD/Help/html/ComparisonSettings.html b/BUILD/Help/html/ComparisonSettings.html
index 069a7fd0..15fffaaf 100644
--- a/BUILD/Help/html/ComparisonSettings.html
+++ b/BUILD/Help/html/ComparisonSettings.html
@@ -5,7 +5,7 @@
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="OpenOffice.org 3.2 (Win32)">
<META NAME="CREATED" CONTENT="20091206;16574000">
- <META NAME="CHANGED" CONTENT="20110910;15564800">
+ <META NAME="CHANGED" CONTENT="20111117;19373200">
<META NAME="Info 1" CONTENT="">
<META NAME="Info 2" CONTENT="">
<META NAME="Info 3" CONTENT="">
@@ -25,7 +25,7 @@
<BODY LANG="en-US" DIR="LTR">
<H3 CLASS="western"><FONT FACE="Tahoma, sans-serif">Comparison
Settings</FONT></H3>
-<P STYLE="margin-bottom: 0cm"><IMG SRC="CmpSettings.png" NAME="Grafik1" ALIGN=BOTTOM BORDER=0></P>
+<P STYLE="margin-bottom: 0cm"><IMG SRC="../img/CmpSettings.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=250 HEIGHT=257 BORDER=0></P>
<H3 CLASS="western" STYLE="page-break-after: avoid"><FONT FACE="Tahoma, sans-serif">I.
Compare by &quot;File time and size&quot;</FONT></H3>
<P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">This
@@ -131,9 +131,9 @@ handling</FONT></H3>
offers three options to configure processing of symbolic links (also
called symlinks or soft links):</FONT></P>
<OL>
- <LI><P STYLE="margin-bottom: 0cm"><SPAN STYLE="text-decoration: none"><FONT FACE="Tahoma, sans-serif"><SPAN STYLE="font-style: normal"><B>Ignore:</B></SPAN></FONT></SPAN>
- <FONT FACE="Tahoma, sans-serif">excludes symbolic links while
- scanning input directories.<BR></FONT>&nbsp;</P>
+ <LI><P STYLE="margin-bottom: 0cm"><SPAN STYLE="text-decoration: none"><FONT FACE="Tahoma, sans-serif"><SPAN STYLE="font-style: normal"><B>Exclude:</B></SPAN></FONT></SPAN>
+ <FONT FACE="Tahoma, sans-serif">skips symbolic links while scanning
+ input directories.<BR></FONT>&nbsp;</P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><B>Direct:</B></FONT>
<FONT FACE="Tahoma, sans-serif">configures synchronization of the
symbolic link object itself and not its target. symbolic links will
diff --git a/BUILD/Help/html/FreeFileSync.html b/BUILD/Help/html/FreeFileSync.html
index 0b81ac64..762445b4 100644
--- a/BUILD/Help/html/FreeFileSync.html
+++ b/BUILD/Help/html/FreeFileSync.html
@@ -24,23 +24,23 @@
</STYLE>
</HEAD>
<BODY LANG="de-DE" DIR="LTR">
-<H3 CLASS="western" ALIGN=CENTER><IMG SRC="ffsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0>
+<H3 CLASS="western" ALIGN=CENTER><IMG SRC="../img/ffsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0>
<FONT SIZE=4 STYLE="font-size: 16pt">FreeFileSync<BR></FONT><FONT SIZE=3><I><SPAN STYLE="font-weight: normal">-
Folder Comparison and Synchronization -</SPAN></I></FONT></H3>
<H3 CLASS="western" ALIGN=LEFT>Usage:</H3>
<OL>
<LI VALUE=1><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Choose
- left and right directories.<BR></FONT><IMG SRC="SourceTarget.png" NAME="Grafik4" ALIGN=TEXTTOP WIDTH=427 HEIGHT=52 BORDER=0></P>
+ left and right directories.<BR></FONT><IMG SRC="../img/SourceTarget.png" NAME="Grafik4" ALIGN=TEXTTOP WIDTH=427 HEIGHT=52 BORDER=0></P>
<P STYLE="margin-bottom: 0cm">&nbsp;</P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">&quot;</FONT><FONT FACE="Tahoma, sans-serif"><I>Compare</I></FONT><FONT FACE="Tahoma, sans-serif">&quot;
- them.<BR></FONT><IMG SRC="CompareButton.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=178 HEIGHT=39 BORDER=0></P>
+ them.<BR></FONT><IMG SRC="../img/CompareButton.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=178 HEIGHT=39 BORDER=0></P>
<P STYLE="margin-bottom: 0cm">&nbsp;</P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Select
- synchronization settings.<BR></FONT><IMG SRC="SyncConfigButton.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=46 HEIGHT=40 BORDER=0></P>
+ synchronization settings.<BR></FONT><IMG SRC="../img/SyncConfigButton.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=46 HEIGHT=40 BORDER=0></P>
<P STYLE="margin-bottom: 0cm">&nbsp;</P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Press
&quot;</FONT><FONT FACE="Tahoma, sans-serif"><I>Synchronize...</I></FONT><FONT FACE="Tahoma, sans-serif">&quot;
- to begin synchronization.<BR></FONT><IMG SRC="SynchronizeButton.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=183 HEIGHT=40 BORDER=0></P>
+ to begin synchronization.<BR></FONT><IMG SRC="../img/SynchronizeButton.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=183 HEIGHT=40 BORDER=0></P>
</OL>
<P STYLE="margin-bottom: 0cm; border-top: none; border-bottom: 1px solid #000000; border-left: none; border-right: none; padding-top: 0cm; padding-bottom: 0.07cm; padding-left: 0cm; padding-right: 0cm">
<BR>
@@ -50,7 +50,7 @@ Folder Comparison and Synchronization -</SPAN></I></FONT></H3>
<H3 CLASS="western" STYLE="page-break-before: always"><FONT FACE="Tahoma, sans-serif">Main
Dialog:</FONT></H3>
<OL>
- <P STYLE="margin-bottom: 0cm"><IMG SRC="MainDialog.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=743 HEIGHT=438 BORDER=0></P>
+ <P STYLE="margin-bottom: 0cm"><IMG SRC="../img/MainDialog.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=743 HEIGHT=438 BORDER=0></P>
</OL>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
@@ -127,7 +127,7 @@ bar:</FONT></H3>
</UL>
</TD>
<TD WIDTH=212>
- <P><IMG SRC="menuFile.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=211 HEIGHT=196 BORDER=0></P>
+ <P><IMG SRC="../img/menuFile.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=211 HEIGHT=196 BORDER=0></P>
</TD>
</TR>
</TABLE>
@@ -158,7 +158,7 @@ bar:</FONT></H3>
</UL>
</TD>
<TD WIDTH=157>
- <P><IMG SRC="menuAdv.png" NAME="Grafik11" ALIGN=MIDDLE WIDTH=159 HEIGHT=112 BORDER=0></P>
+ <P><IMG SRC="../img/menuAdv.png" NAME="Grafik11" ALIGN=MIDDLE WIDTH=159 HEIGHT=112 BORDER=0></P>
</TD>
</TR>
</TABLE>
@@ -181,7 +181,7 @@ bar:</FONT></H3>
</UL>
</TD>
<TD WIDTH=202>
- <P><IMG SRC="menuHelp.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=202 HEIGHT=90 BORDER=0></P>
+ <P><IMG SRC="../img/menuHelp.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=202 HEIGHT=90 BORDER=0></P>
</TD>
</TR>
</TABLE>
diff --git a/BUILD/Help/html/RealtimeSync.html b/BUILD/Help/html/RealtimeSync.html
index fc0a2054..3468bc76 100644
--- a/BUILD/Help/html/RealtimeSync.html
+++ b/BUILD/Help/html/RealtimeSync.html
@@ -23,7 +23,7 @@
</STYLE>
</HEAD>
<BODY LANG="en-US" DIR="LTR">
-<H3 CLASS="western" ALIGN=CENTER><IMG SRC="rtsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0>
+<H3 CLASS="western" ALIGN=CENTER><IMG SRC="../img/rtsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0>
<FONT SIZE=4 STYLE="font-size: 16pt">RealtimeSync<BR></FONT><FONT SIZE=3><I><SPAN STYLE="font-weight: normal">-
Automated Synchronization -</SPAN></I></FONT></H3>
<P ALIGN=LEFT><BR><BR>
@@ -53,7 +53,7 @@ but also sets up the command-line to execute the </FONT><FONT FACE="Courier New,
Now press &quot;</FONT><FONT FACE="Tahoma, sans-serif"><I>Start</I></FONT><FONT FACE="Tahoma, sans-serif">&quot;
to begin monitoring.</FONT></P>
<UL>
- <P STYLE="margin-bottom: 0cm"><IMG SRC="RealtimeSync.png" NAME="Grafik3" ALIGN=MIDDLE WIDTH=420 HEIGHT=480 BORDER=0></P>
+ <P STYLE="margin-bottom: 0cm"><IMG SRC="../img/RealtimeSync.png" NAME="Grafik3" ALIGN=MIDDLE WIDTH=420 HEIGHT=480 BORDER=0></P>
</UL>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
@@ -95,7 +95,7 @@ the relevant configuration on the USB stick's root directory to have
it called when the stick is mounted. Then configure RealtimeSync as
shown in the following:</FONT></P>
<UL>
- <P><IMG SRC="WatchUsbInsert.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=436 HEIGHT=447 BORDER=0></P>
+ <P><IMG SRC="../img/WatchUsbInsert.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=436 HEIGHT=447 BORDER=0></P>
</UL>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
diff --git a/BUILD/Help/html/RunAsService.html b/BUILD/Help/html/RunAsService.html
index c347a4fa..8b5e0d42 100644
--- a/BUILD/Help/html/RunAsService.html
+++ b/BUILD/Help/html/RunAsService.html
@@ -49,7 +49,7 @@ Create and register a new Service via command line:</FONT></P>
<P ALIGN=LEFT STYLE="margin-left: 0.79cm; margin-right: 0.98cm; margin-bottom: 0cm">
<FONT FACE="Courier New, monospace">instsrv &lt;ServiceName&gt;
&lt;PathToResourceKit&gt;\srvany.exe</FONT></P>
- </SPAN><BR CLEAR=LEFT>&nbsp;<BR><IMG SRC="RunAsService_html_4f230a46.png" NAME="Grafik9" ALIGN=BOTTOM WIDTH=430 HEIGHT=107 BORDER=0></P>
+ </SPAN><BR CLEAR=LEFT>&nbsp;<BR><IMG SRC="../img/RunAsService_html_4f230a46.png" NAME="Grafik9" ALIGN=BOTTOM WIDTH=430 HEIGHT=107 BORDER=0></P>
</UL>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
@@ -60,10 +60,10 @@ the new Service with RealtimeSync:</FONT></P>
the Registry editor (Regedit.exe) and navigate to key
&quot;</FONT><FONT FACE="Courier New, monospace">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\&lt;ServiceName&gt;</FONT><FONT FACE="Tahoma, sans-serif">&quot;</FONT></P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Add
- a new key &quot;</FONT><FONT FACE="Courier New, monospace">Parameters</FONT><FONT FACE="Tahoma, sans-serif">&quot;.<BR><IMG SRC="RunAsService_html_bf02de4e.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=249 HEIGHT=101 BORDER=0></FONT></P>
+ a new key &quot;</FONT><FONT FACE="Courier New, monospace">Parameters</FONT><FONT FACE="Tahoma, sans-serif">&quot;.<BR><IMG SRC="../img/RunAsService_html_bf02de4e.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=249 HEIGHT=101 BORDER=0></FONT></P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Add
a new String value named &quot;</FONT><FONT FACE="Courier New, monospace">Application</FONT><FONT FACE="Tahoma, sans-serif">&quot;
- and specify a command line that shall be executed as value.<BR><IMG SRC="RunAsService_html_m3be0f332.png" NAME="Grafik10" ALIGN=BOTTOM WIDTH=620 HEIGHT=58 BORDER=0></FONT></P>
+ and specify a command line that shall be executed as value.<BR><IMG SRC="../img/RunAsService_html_m3be0f332.png" NAME="Grafik10" ALIGN=BOTTOM WIDTH=620 HEIGHT=58 BORDER=0></FONT></P>
</UL>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
@@ -97,7 +97,7 @@ administration:</FONT></P>
<P STYLE="margin-right: 0.98cm"><SPAN ID="Rahmen5" DIR="LTR" STYLE="float: left; width: 80%; height: 0.14cm; border: none; padding: 0cm; background: #e6e6e6">
<P ALIGN=LEFT STYLE="margin-left: 0.79cm; margin-right: 0.98cm; margin-bottom: 0cm">
<FONT FACE="Tahoma, sans-serif">net start &lt;ServiceName&gt;</FONT></P>
- </SPAN><BR CLEAR=LEFT>&nbsp;<BR><IMG SRC="RunAsService_html_17e8fbfe.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=640 HEIGHT=55 BORDER=0><BR>&nbsp;<BR><IMG SRC="RunAsService_html_7aa44556.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=548 HEIGHT=291 BORDER=0></P>
+ </SPAN><BR CLEAR=LEFT>&nbsp;<BR><IMG SRC="../img/RunAsService_html_17e8fbfe.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=640 HEIGHT=55 BORDER=0><BR>&nbsp;<BR><IMG SRC="../img/RunAsService_html_7aa44556.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=548 HEIGHT=291 BORDER=0></P>
</UL>
<P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"><BR>
</P>
@@ -111,7 +111,7 @@ administration:</FONT></P>
Service administration.</FONT></P>
</SPAN><BR CLEAR=LEFT><BR>
</P>
-<P STYLE="margin-left: 1.46cm; margin-bottom: 0cm"><IMG SRC="RunAsService_html_m3e56d901.png" NAME="Grafik6" ALIGN=BOTTOM WIDTH=410 HEIGHT=468 BORDER=0></P>
+<P STYLE="margin-left: 1.46cm; margin-bottom: 0cm"><IMG SRC="../img/RunAsService_html_m3e56d901.png" NAME="Grafik6" ALIGN=BOTTOM WIDTH=410 HEIGHT=468 BORDER=0></P>
<P STYLE="margin-left: 1.46cm; margin-bottom: 0cm"><BR>
</P>
<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
@@ -122,7 +122,7 @@ Service shall be removed from the system, enter via command line:</FONT></P>
<P STYLE="margin-right: 0.98cm"><SPAN ID="Rahmen6" DIR="LTR" STYLE="float: left; width: 80%; height: 0.14cm; border: none; padding: 0cm; background: #e6e6e6">
<P ALIGN=LEFT STYLE="margin-left: 0.79cm; margin-right: 0.98cm; margin-bottom: 0cm">
<FONT FACE="Tahoma, sans-serif">instsrv &lt;ServiceName&gt; remove</FONT></P>
- </SPAN><BR CLEAR=LEFT>&nbsp;<BR><IMG SRC="RunAsService_html_68e0fe53.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=640 HEIGHT=52 BORDER=0></P>
+ </SPAN><BR CLEAR=LEFT>&nbsp;<BR><IMG SRC="../img/RunAsService_html_68e0fe53.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=640 HEIGHT=52 BORDER=0></P>
</UL>
<P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"><BR>
</P>
diff --git a/BUILD/Help/html/ScheduleBatch.html b/BUILD/Help/html/ScheduleBatch.html
index 4bd0c8ad..9594ec3d 100644
--- a/BUILD/Help/html/ScheduleBatch.html
+++ b/BUILD/Help/html/ScheduleBatch.html
@@ -31,12 +31,12 @@ Job</FONT></H3>
for example, as &quot;</FONT><FONT FACE="Courier New, monospace">C:\SyncJob.ffs_batch</FONT><FONT FACE="Tahoma, sans-serif">&quot;.<BR>&nbsp;</FONT></P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Enable
checkbox &quot;<I>Run miminized</I>&quot; to avoid blocking while
- showing a status dialog at the end of the process.<BR><IMG SRC="RunMinimized.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=709 HEIGHT=332 BORDER=0></FONT></P>
+ showing a status dialog at the end of the process.<BR><IMG SRC="../img/RunMinimized.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=709 HEIGHT=332 BORDER=0></FONT></P>
<P STYLE="margin-bottom: 0cm">&nbsp;</P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">In
order to prevent error or warning popup messages from stopping
progress, set &quot;<I>Error handling</I>&quot; to either &quot;<I>Ignore
- errors</I>&quot; or &quot;<I>Exit instantly</I>&quot;.<BR><IMG SRC="ErrorHandling.png" NAME="Grafik4" ALIGN=BOTTOM WIDTH=313 HEIGHT=331 BORDER=0></FONT></P>
+ errors</I>&quot; or &quot;<I>Exit instantly</I>&quot;.<BR><IMG SRC="../img/ErrorHandling.png" NAME="Grafik4" ALIGN=BOTTOM WIDTH=313 HEIGHT=331 BORDER=0></FONT></P>
<P STYLE="margin-bottom: 0cm">&nbsp;</P>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Setup
your operating system's scheduler</FONT></P>
@@ -63,7 +63,7 @@ Job</FONT></H3>
<UL>
<LI><P STYLE="margin-bottom: 0cm; font-weight: normal"><FONT FACE="Tahoma, sans-serif"><FONT COLOR="#000000"><FONT SIZE=3>Use
quotes if any paths contain spaces, e.g.: </FONT></FONT><FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=3>&quot;C:\some
- folder\SyncJob.ffs_batch&quot;</FONT></FONT></FONT><FONT COLOR="#000000"><FONT SIZE=3><BR></FONT></FONT><IMG SRC="win7scheduler.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=708 HEIGHT=321 BORDER=0><BR>&nbsp;</FONT></P>
+ folder\SyncJob.ffs_batch&quot;</FONT></FONT></FONT><FONT COLOR="#000000"><FONT SIZE=3><BR></FONT></FONT><IMG SRC="../img/win7scheduler.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=708 HEIGHT=321 BORDER=0><BR>&nbsp;</FONT></P>
</UL>
</OL>
</OL>
@@ -80,7 +80,7 @@ Job</FONT></H3>
<LI><P STYLE="margin-bottom: 0cm; font-weight: normal"><FONT FACE="Tahoma, sans-serif">Make
sure &quot;Run:&quot; is specified as: <FONT FACE="Courier New, monospace">&lt;FreeFileSync
installation directory&gt;\FreeFileSync.exe &lt;ffs_batch
- file&gt;</FONT><BR><IMG SRC="ScheduleBatch_html_m10bf0d36.gif" NAME="Grafik2" ALIGN=BOTTOM WIDTH=406 HEIGHT=455 BORDER=0><BR>&nbsp;</FONT></P>
+ file&gt;</FONT><BR><IMG SRC="../img/ScheduleBatch_html_m10bf0d36.gif" NAME="Grafik2" ALIGN=BOTTOM WIDTH=406 HEIGHT=455 BORDER=0><BR>&nbsp;</FONT></P>
</UL>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><B>Ubuntu
Linux Gnome-schedule:</B></FONT></P>
@@ -105,7 +105,7 @@ Job</FONT></H3>
<UL>
<LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">Specify
the command as:</SPAN></SPAN></FONT> <FONT FACE="Courier New, monospace"><I><SPAN STYLE="font-weight: normal">&lt;FreeFileSync
- installation directory&gt;\FreeFileSync &lt;ffs_batch file&gt;<BR></SPAN></I></FONT><IMG SRC="ubuntuScheduler.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=629 HEIGHT=560 BORDER=0></P>
+ installation directory&gt;\FreeFileSync &lt;ffs_batch file&gt;<BR></SPAN></I></FONT><IMG SRC="../img/ubuntuScheduler.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=629 HEIGHT=560 BORDER=0></P>
</UL>
</OL>
</OL>
diff --git a/BUILD/Help/html/ScheduleBatch_html_372f0f3.gif b/BUILD/Help/html/ScheduleBatch_html_372f0f3.gif
deleted file mode 100644
index 4cddbc19..00000000
--- a/BUILD/Help/html/ScheduleBatch_html_372f0f3.gif
+++ /dev/null
Binary files differ
diff --git a/BUILD/Help/html/ShadowCopy.html b/BUILD/Help/html/ShadowCopy.html
index d8286285..ce66ccee 100644
--- a/BUILD/Help/html/ShadowCopy.html
+++ b/BUILD/Help/html/ShadowCopy.html
@@ -39,7 +39,7 @@ Copy of the source drive. To enable this feature go to </FONT><FONT FACE="Tahoma
not use Volume Shadow Copy Service when being synchronized.</FONT></P>
<LI><P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"><SPAN STYLE="font-style: normal"><FONT FACE="Tahoma, sans-serif">Creating
Volume Snapshots using VSS requires the application to be started
- with Administrator rights.</FONT></SPAN></P>
+ with administrator rights.</FONT></SPAN></P>
</UL>
</SPAN><BR CLEAR=LEFT><BR>
</P>
diff --git a/BUILD/Help/html/VariableDrive.html b/BUILD/Help/html/VariableDrive.html
index ebf80b8d..3e0ea71e 100644
--- a/BUILD/Help/html/VariableDrive.html
+++ b/BUILD/Help/html/VariableDrive.html
@@ -42,7 +42,7 @@ name&gt;]\&lt;path&gt;</FONT></FONT></P>
</P>
<P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">It is
not required to look up and enter the volume name manually. Just
-select the corresponding entry in the drop down menu.<BR></FONT><IMG SRC="VolumeName.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=279 HEIGHT=103 BORDER=0></P>
+select the corresponding entry in the drop down menu.<BR></FONT><IMG SRC="../img/VolumeName.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=279 HEIGHT=103 BORDER=0></P>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
<P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><B>Option
diff --git a/BUILD/Help/html/scheduleBatch_html_13615436.gif b/BUILD/Help/html/scheduleBatch_html_13615436.gif
deleted file mode 100644
index 23d7bda9..00000000
--- a/BUILD/Help/html/scheduleBatch_html_13615436.gif
+++ /dev/null
Binary files differ
diff --git a/BUILD/Help/html/scheduleBatch_html_28bb3203.gif b/BUILD/Help/html/scheduleBatch_html_28bb3203.gif
deleted file mode 100644
index 45c8b1c2..00000000
--- a/BUILD/Help/html/scheduleBatch_html_28bb3203.gif
+++ /dev/null
Binary files differ
diff --git a/BUILD/Help/html/scheduleBatch_html_m22c860a2.gif b/BUILD/Help/html/scheduleBatch_html_m22c860a2.gif
deleted file mode 100644
index 1f8da914..00000000
--- a/BUILD/Help/html/scheduleBatch_html_m22c860a2.gif
+++ /dev/null
Binary files differ
diff --git a/BUILD/Help/html/CmpSettings.png b/BUILD/Help/img/CmpSettings.png
index eb0c83ab..d2548891 100644
--- a/BUILD/Help/html/CmpSettings.png
+++ b/BUILD/Help/img/CmpSettings.png
Binary files differ
diff --git a/BUILD/Help/html/CompareButton.png b/BUILD/Help/img/CompareButton.png
index bab3780b..bab3780b 100644
--- a/BUILD/Help/html/CompareButton.png
+++ b/BUILD/Help/img/CompareButton.png
Binary files differ
diff --git a/BUILD/Help/html/ErrorHandling.png b/BUILD/Help/img/ErrorHandling.png
index 628fac9c..628fac9c 100644
--- a/BUILD/Help/html/ErrorHandling.png
+++ b/BUILD/Help/img/ErrorHandling.png
Binary files differ
diff --git a/BUILD/Help/html/MainDialog.png b/BUILD/Help/img/MainDialog.png
index ab6a6f7c..ab6a6f7c 100644
--- a/BUILD/Help/html/MainDialog.png
+++ b/BUILD/Help/img/MainDialog.png
Binary files differ
diff --git a/BUILD/Help/html/RealtimeSync.png b/BUILD/Help/img/RealtimeSync.png
index 20d582c6..20d582c6 100644
--- a/BUILD/Help/html/RealtimeSync.png
+++ b/BUILD/Help/img/RealtimeSync.png
Binary files differ
diff --git a/BUILD/Help/html/RunAsService_html_17e8fbfe.png b/BUILD/Help/img/RunAsService_html_17e8fbfe.png
index 23eb6083..23eb6083 100644
--- a/BUILD/Help/html/RunAsService_html_17e8fbfe.png
+++ b/BUILD/Help/img/RunAsService_html_17e8fbfe.png
Binary files differ
diff --git a/BUILD/Help/html/RunAsService_html_4f230a46.png b/BUILD/Help/img/RunAsService_html_4f230a46.png
index a32a442d..a32a442d 100644
--- a/BUILD/Help/html/RunAsService_html_4f230a46.png
+++ b/BUILD/Help/img/RunAsService_html_4f230a46.png
Binary files differ
diff --git a/BUILD/Help/html/RunAsService_html_68e0fe53.png b/BUILD/Help/img/RunAsService_html_68e0fe53.png
index 5639a21c..5639a21c 100644
--- a/BUILD/Help/html/RunAsService_html_68e0fe53.png
+++ b/BUILD/Help/img/RunAsService_html_68e0fe53.png
Binary files differ
diff --git a/BUILD/Help/html/RunAsService_html_7aa44556.png b/BUILD/Help/img/RunAsService_html_7aa44556.png
index b37fe6e4..b37fe6e4 100644
--- a/BUILD/Help/html/RunAsService_html_7aa44556.png
+++ b/BUILD/Help/img/RunAsService_html_7aa44556.png
Binary files differ
diff --git a/BUILD/Help/html/RunAsService_html_bf02de4e.png b/BUILD/Help/img/RunAsService_html_bf02de4e.png
index 2bdac2db..2bdac2db 100644
--- a/BUILD/Help/html/RunAsService_html_bf02de4e.png
+++ b/BUILD/Help/img/RunAsService_html_bf02de4e.png
Binary files differ
diff --git a/BUILD/Help/html/RunAsService_html_m3be0f332.png b/BUILD/Help/img/RunAsService_html_m3be0f332.png
index 5ad45cfa..5ad45cfa 100644
--- a/BUILD/Help/html/RunAsService_html_m3be0f332.png
+++ b/BUILD/Help/img/RunAsService_html_m3be0f332.png
Binary files differ
diff --git a/BUILD/Help/html/RunAsService_html_m3e56d901.png b/BUILD/Help/img/RunAsService_html_m3e56d901.png
index 860d1543..860d1543 100644
--- a/BUILD/Help/html/RunAsService_html_m3e56d901.png
+++ b/BUILD/Help/img/RunAsService_html_m3e56d901.png
Binary files differ
diff --git a/BUILD/Help/html/RunMinimized.png b/BUILD/Help/img/RunMinimized.png
index 145a7568..145a7568 100644
--- a/BUILD/Help/html/RunMinimized.png
+++ b/BUILD/Help/img/RunMinimized.png
Binary files differ
diff --git a/BUILD/Help/html/ScheduleBatch_html_m10bf0d36.gif b/BUILD/Help/img/ScheduleBatch_html_m10bf0d36.gif
index 20d27d6d..20d27d6d 100644
--- a/BUILD/Help/html/ScheduleBatch_html_m10bf0d36.gif
+++ b/BUILD/Help/img/ScheduleBatch_html_m10bf0d36.gif
Binary files differ
diff --git a/BUILD/Help/html/SourceTarget.png b/BUILD/Help/img/SourceTarget.png
index 2a3a834e..2a3a834e 100644
--- a/BUILD/Help/html/SourceTarget.png
+++ b/BUILD/Help/img/SourceTarget.png
Binary files differ
diff --git a/BUILD/Help/html/SyncConfigButton.png b/BUILD/Help/img/SyncConfigButton.png
index 2ac5c94e..2ac5c94e 100644
--- a/BUILD/Help/html/SyncConfigButton.png
+++ b/BUILD/Help/img/SyncConfigButton.png
Binary files differ
diff --git a/BUILD/Help/html/SynchronizeButton.png b/BUILD/Help/img/SynchronizeButton.png
index a8b8002b..a8b8002b 100644
--- a/BUILD/Help/html/SynchronizeButton.png
+++ b/BUILD/Help/img/SynchronizeButton.png
Binary files differ
diff --git a/BUILD/Help/html/VolumeName.png b/BUILD/Help/img/VolumeName.png
index 9d1b9201..9d1b9201 100644
--- a/BUILD/Help/html/VolumeName.png
+++ b/BUILD/Help/img/VolumeName.png
Binary files differ
diff --git a/BUILD/Help/html/WatchUsbInsert.png b/BUILD/Help/img/WatchUsbInsert.png
index 9d106fb8..9d106fb8 100644
--- a/BUILD/Help/html/WatchUsbInsert.png
+++ b/BUILD/Help/img/WatchUsbInsert.png
Binary files differ
diff --git a/BUILD/Help/html/ffsicon.png b/BUILD/Help/img/ffsicon.png
index 7ff53bb6..7ff53bb6 100644
--- a/BUILD/Help/html/ffsicon.png
+++ b/BUILD/Help/img/ffsicon.png
Binary files differ
diff --git a/BUILD/Help/html/menuAdv.png b/BUILD/Help/img/menuAdv.png
index 3626c1f0..3626c1f0 100644
--- a/BUILD/Help/html/menuAdv.png
+++ b/BUILD/Help/img/menuAdv.png
Binary files differ
diff --git a/BUILD/Help/html/menuFile.png b/BUILD/Help/img/menuFile.png
index 7e6844d5..7e6844d5 100644
--- a/BUILD/Help/html/menuFile.png
+++ b/BUILD/Help/img/menuFile.png
Binary files differ
diff --git a/BUILD/Help/html/menuHelp.png b/BUILD/Help/img/menuHelp.png
index db51f82f..db51f82f 100644
--- a/BUILD/Help/html/menuHelp.png
+++ b/BUILD/Help/img/menuHelp.png
Binary files differ
diff --git a/BUILD/Help/html/rtsicon.png b/BUILD/Help/img/rtsicon.png
index dabaa256..dabaa256 100644
--- a/BUILD/Help/html/rtsicon.png
+++ b/BUILD/Help/img/rtsicon.png
Binary files differ
diff --git a/BUILD/Help/html/ubuntuScheduler.png b/BUILD/Help/img/ubuntuScheduler.png
index 82bf329f..82bf329f 100644
--- a/BUILD/Help/html/ubuntuScheduler.png
+++ b/BUILD/Help/img/ubuntuScheduler.png
Binary files differ
diff --git a/BUILD/Help/html/win7scheduler.png b/BUILD/Help/img/win7scheduler.png
index 29fa1f36..29fa1f36 100644
--- a/BUILD/Help/html/win7scheduler.png
+++ b/BUILD/Help/img/win7scheduler.png
Binary files differ
diff --git a/BUILD/Languages/chinese_simple.lng b/BUILD/Languages/chinese_simple.lng
index fc37aac5..65887d4f 100644
--- a/BUILD/Languages/chinese_simple.lng
+++ b/BUILD/Languages/chinese_simple.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>实时同步 - 自动同步</target>
-<source>Browse</source>
-<target>浏览</target>
-
-<source>Windows Error Code %x:</source>
-<target>Windows错误代码 %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Linux错误代码 %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>无效的命令行: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>解决符号链接出错:</target>
-
-<source>Show pop-up</source>
-<target>显示弹出对话框</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>在错误或警告时显示弹出对话框</target>
-
-<source>Ignore errors</source>
-<target>忽略错误</target>
-
-<source>Hide all error and warning messages</source>
-<target>隐藏所有错误与警告信息</target>
-
-<source>Exit instantly</source>
-<target>立即退出</target>
-
-<source>Abort synchronization immediately</source>
-<target>立即中止同步</target>
-
<source>Select alternate comparison settings</source>
<target>选择替换的比较设置</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>选择时间跨度</target>
+<source>Show pop-up</source>
+<target>显示弹出对话框</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>在错误或警告时显示弹出对话框</target>
+
+<source>Ignore errors</source>
+<target>忽略错误</target>
+
+<source>Hide all error and warning messages</source>
+<target>隐藏所有错误与警告信息</target>
+
+<source>Exit instantly</source>
+<target>立即退出</target>
+
+<source>Abort synchronization immediately</source>
+<target>立即中止同步</target>
+
+<source>Browse</source>
+<target>浏览</target>
+
+<source>Error reading from synchronization database:</source>
+<target>从同步数据库中读取时出错:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>向同步数据库中写入时出错:</target>
+
+<source>Invalid command line: %x</source>
+<target>无效的命令行: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows错误代码 %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux错误代码 %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>解决符号链接出错:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -162,17 +168,14 @@
<source>Comparison Result</source>
<target>比较结果</target>
-<source>Incompatible synchronization database format:</source>
-<target>不兼容的同步数据库格式:</target>
-
<source>Initial synchronization:</source>
<target>初始化同步:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>FreeFileSync数据库文件其中一个不存在:</target>
-<source>Error reading from synchronization database:</source>
-<target>从同步数据库中读取时出错:</target>
+<source>Incompatible synchronization database format:</source>
+<target>不兼容的同步数据库格式:</target>
<source>Database files do not share a common synchronization session:</source>
<target>数据库文件没不共享一个公共的同步段</target>
@@ -197,12 +200,18 @@
<pluralform>%x 秒</pluralform>
</target>
+<source>Drag && drop</source>
+<target>拖放</target>
+
<source>Info</source>
<target>信息</target>
<source>Fatal Error</source>
<target>致命错误</target>
+<source>Error reading file:</source>
+<target>读取文件出错:</target>
+
<source>Scanning:</source>
<target>扫描中:</target>
@@ -220,15 +229,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>无效的 FreeFileSync 配置文件!</target>
-<source>File does not exist:</source>
-<target>文件不存在:</target>
-
<source>Error parsing configuration file:</source>
<target>分析配置文件出错:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>移动到回收站出错:</target>
+
+<source>Could not load a required DLL:</source>
+<target>不能加载所需的动态连接库:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>使用卷影复制服务时出错!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>不支持在WOW64上使用卷影复制. 请使用 FreeFileSync 64位版本.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>不能确定此文件的卷名称:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>卷名 %x 并非文件名 %y 的一部分!</target>
+
<source>/sec</source>
<target>/秒</target>
+<source>File does not exist:</source>
+<target>文件不存在:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>不能从如下XML节点读取数值:</target>
+
<source>S&ave configuration...</source>
<target>保存配置(&A)...</target>
@@ -321,138 +351,6 @@ The command line is executed each time:
<source>A directory input field is empty.</source>
<target>有一个目录输入字段是空的.</target>
-<source>Drag && drop</source>
-<target>拖放</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>不能初始化目录监视:</target>
-
-<source>Error when monitoring directories.</source>
-<target>监视目录时出错.</target>
-
-<source>Conversion error:</source>
-<target>转换错误:</target>
-
-<source>Error deleting file:</source>
-<target>删除文件出错:</target>
-
-<source>Error moving file:</source>
-<target>移动文件时出错:</target>
-
-<source>Target file already existing!</source>
-<target>目标文件已经存在!</target>
-
-<source>Error moving directory:</source>
-<target>移动目录时出错:</target>
-
-<source>Target directory already existing!</source>
-<target>目标目录已经存在!</target>
-
-<source>Error deleting directory:</source>
-<target>删除目录出错:</target>
-
-<source>Error changing modification time:</source>
-<target>改变修改时间时出错:</target>
-
-<source>Error loading library function:</source>
-<target>加载库函数出错:</target>
-
-<source>Error reading security context:</source>
-<target>读取安全上下文时出错:</target>
-
-<source>Error writing security context:</source>
-<target>写入安全上下文时出错:</target>
-
-<source>Error copying file permissions:</source>
-<target>复制文件权限时出错:</target>
-
-<source>Error creating directory:</source>
-<target>创建目录出错:</target>
-
-<source>Error copying symbolic link:</source>
-<target>复制符号链接时出错:</target>
-
-<source>Error copying file:</source>
-<target>复制文件出错:</target>
-
-<source>Error opening file:</source>
-<target>打开文件出错:</target>
-
-<source>Error writing file:</source>
-<target>写入文件出错:</target>
-
-<source>Error reading file:</source>
-<target>读取文件出错:</target>
-
-<source>Operation aborted!</source>
-<target>操作已取消!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>遍历目录时出现无限循环:</target>
-
-<source>Error traversing directory:</source>
-<target>遍历目录出错:</target>
-
-<source>Error setting privilege:</source>
-<target>设置权限时出错:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>移动到回收站出错:</target>
-
-<source>Could not load a required DLL:</source>
-<target>不能加载所需的动态连接库:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>向同步数据库中写入时出错:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>使用卷影复制服务时出错!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>不支持在WOW64上使用卷影复制. 请使用 FreeFileSync 64位版本.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>不能确定此文件的卷名称:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>卷名 %x 并非文件名 %y 的一部分!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>%x 分</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>%x 小时</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>%x 天</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>不能从如下XML节点读取数值:</target>
-
<source>Logging</source>
<target>记录</target>
@@ -471,9 +369,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>批处理执行</target>
-<source>Log-messages:</source>
-<target>日志信息:</target>
-
<source>Stop</source>
<target>停止</target>
@@ -600,6 +495,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>将被转移的总数据</target>
+<source>Operation:</source>
+<target>操作:</target>
+
+<source>Items found:</source>
+<target>已找到的元素:</target>
+
+<source>Items remaining:</source>
+<target>剩余的元素:</target>
+
+<source>Speed:</source>
+<target>速度:</target>
+
+<source>Time remaining:</source>
+<target>剩余时间:</target>
+
+<source>Time elapsed:</source>
+<target>已用时间:</target>
+
<source>Batch job</source>
<target>批处理作业</target>
@@ -648,32 +561,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>取消(&C)</target>
-<source>Operation:</source>
-<target>操作:</target>
-
-<source>Items found:</source>
-<target>已找到的元素:</target>
-
-<source>Items remaining:</source>
-<target>剩余的元素:</target>
-
-<source>Speed:</source>
-<target>速度:</target>
-
-<source>Time remaining:</source>
-<target>剩余时间:</target>
-
-<source>Time elapsed:</source>
-<target>已用时间:</target>
-
<source>Select variant:</source>
<target>选择变化的:</target>
<source><Automatic></source>
<target><自动></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>使用数据库来识别和传送两边的改变. 自动检测删除和冲突状态.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target></target>
<source>Mirror ->></source>
<target>镜像 ->></target>
@@ -900,22 +795,14 @@ Exclude: \stuff\temp\*
<source>Copy locked files</source>
<target>复制被锁定的文件</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-通过卷影复制服务复制共享或锁定的文件(需要管理员权限)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>通过卷影复制服务复制共享或锁定的文件(需要管理员权限)</target>
<source>Copy file access permissions</source>
<target>复制文件存取权限</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-转移文件和目录的权限(需要管理员权限)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>转移文件和目录的权限(需要管理员权限)</target>
<source>Hidden dialogs:</source>
<target>隐藏对话框:</target>
@@ -947,6 +834,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>查找下一个(&F)</target>
+<source>Operation aborted!</source>
+<target>操作已取消!</target>
+
<source>Main bar</source>
<target>主工具条</target>
@@ -1124,6 +1014,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>文件清单已经导出!</target>
+<source>Error writing file:</source>
+<target>写入文件出错:</target>
+
<source>Batch file created successfully!</source>
<target>批处理文件创建成功!</target>
@@ -1219,9 +1112,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>过滤器:单一的配对</target>
-<source>Ignore</source>
-<target>忽略</target>
-
<source>Direct</source>
<target>直接</target>
@@ -1283,6 +1173,102 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>移动文件到时间标记子目录</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>%x 分</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>%x 小时</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>%x 天</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>不能初始化目录监视:</target>
+
+<source>Error when monitoring directories.</source>
+<target>监视目录时出错.</target>
+
+<source>Conversion error:</source>
+<target>转换错误:</target>
+
+<source>Error deleting file:</source>
+<target>删除文件出错:</target>
+
+<source>Error moving file:</source>
+<target>移动文件时出错:</target>
+
+<source>Target file already existing!</source>
+<target>目标文件已经存在!</target>
+
+<source>Error moving directory:</source>
+<target>移动目录时出错:</target>
+
+<source>Target directory already existing!</source>
+<target>目标目录已经存在!</target>
+
+<source>Error deleting directory:</source>
+<target>删除目录出错:</target>
+
+<source>Error changing modification time:</source>
+<target>改变修改时间时出错:</target>
+
+<source>Error loading library function:</source>
+<target>加载库函数出错:</target>
+
+<source>Error reading security context:</source>
+<target>读取安全上下文时出错:</target>
+
+<source>Error writing security context:</source>
+<target>写入安全上下文时出错:</target>
+
+<source>Error copying file permissions:</source>
+<target>复制文件权限时出错:</target>
+
+<source>Error creating directory:</source>
+<target>创建目录出错:</target>
+
+<source>Error copying symbolic link:</source>
+<target>复制符号链接时出错:</target>
+
+<source>Error copying file:</source>
+<target>复制文件出错:</target>
+
+<source>Error opening file:</source>
+<target>打开文件出错:</target>
+
+<source>Error traversing directory:</source>
+<target>遍历目录出错:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>遍历目录时出现无限循环:</target>
+
+<source>Error setting privilege:</source>
+<target>设置权限时出错:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>在最后的同步之后两边均已改变!</target>
@@ -1313,9 +1299,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>目录有依赖性!在设立同步规则时请小心:</target>
-<source>Comparing content of files %x</source>
-<target>正在比较文件 %x 的内容</target>
-
<source>Memory allocation failed!</source>
<target>内存分配失败!</target>
@@ -1331,15 +1314,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>符号连接 %x 有相同的日期但目标不同!</target>
+<source>Comparing content of files %x</source>
+<target>正在比较文件 %x 的内容</target>
+
<source>Comparing files by content failed.</source>
<target>按文件内容比较失败.</target>
<source>Generating file list...</source>
<target>生成文件列表...</target>
-<source>Multiple...</source>
-<target>并联...</target>
-
<source>Both sides are equal</source>
<target>两侧相等</target>
@@ -1358,6 +1341,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>删除右侧文件/文件夹</target>
+<source>Move file on left</source>
+<target></target>
+
+<source>Move file on right</source>
+<target></target>
+
<source>Overwrite left file/folder with right one</source>
<target>从右侧覆盖左侧的文件/文件夹</target>
@@ -1373,6 +1362,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>仅复制文件属性到右侧</target>
+<source>Multiple...</source>
+<target>并联...</target>
+
<source>Deleting file %x</source>
<target>正删除文件 %x</target>
diff --git a/BUILD/Languages/chinese_traditional.lng b/BUILD/Languages/chinese_traditional.lng
index f872c6aa..380d2c9b 100644
--- a/BUILD/Languages/chinese_traditional.lng
+++ b/BUILD/Languages/chinese_traditional.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>即時同步 - 自動同步</target>
-<source>Browse</source>
-<target>瀏覽</target>
-
-<source>Windows Error Code %x:</source>
-<target>Windows 錯誤代碼 %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Linux 錯誤代碼 %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>無效的命令列:%x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>解析錯誤的符號連結:</target>
-
-<source>Show pop-up</source>
-<target>顯示彈出視窗</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>在彈出視窗上顯示錯誤或警告訊息</target>
-
-<source>Ignore errors</source>
-<target>忽略錯誤</target>
-
-<source>Hide all error and warning messages</source>
-<target>隱藏所有錯誤和警告訊息</target>
-
-<source>Exit instantly</source>
-<target>立即退出</target>
-
-<source>Abort synchronization immediately</source>
-<target>立即中止同步</target>
-
<source>Select alternate comparison settings</source>
<target>選擇替代的比對設定</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>選擇時間範圍</target>
+<source>Show pop-up</source>
+<target>顯示彈出視窗</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>在彈出視窗上顯示錯誤或警告訊息</target>
+
+<source>Ignore errors</source>
+<target>忽略錯誤</target>
+
+<source>Hide all error and warning messages</source>
+<target>隱藏所有錯誤和警告訊息</target>
+
+<source>Exit instantly</source>
+<target>立即退出</target>
+
+<source>Abort synchronization immediately</source>
+<target>立即中止同步</target>
+
+<source>Browse</source>
+<target>瀏覽</target>
+
+<source>Error reading from synchronization database:</source>
+<target>讀取同步資料庫錯誤:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>寫入同步資料庫錯誤:</target>
+
+<source>Invalid command line: %x</source>
+<target>無效的命令列:%x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows 錯誤代碼 %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux 錯誤代碼 %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>解析錯誤的符號連結:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -162,17 +168,14 @@
<source>Comparison Result</source>
<target>比對結果</target>
-<source>Incompatible synchronization database format:</source>
-<target>同步資料庫格式不相容:</target>
-
<source>Initial synchronization:</source>
<target>初始化同步:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>其中一個 FreeFileSync 資料庫檔案不存在:</target>
-<source>Error reading from synchronization database:</source>
-<target>讀取同步資料庫錯誤:</target>
+<source>Incompatible synchronization database format:</source>
+<target>同步資料庫格式不相容:</target>
<source>Database files do not share a common synchronization session:</source>
<target>資料庫檔案不共享一個共同的同步連線:</target>
@@ -197,12 +200,18 @@
<pluralform>%x 秒</pluralform>
</target>
+<source>Drag && drop</source>
+<target>拖放</target>
+
<source>Info</source>
<target>訊息</target>
<source>Fatal Error</source>
<target>嚴重錯誤</target>
+<source>Error reading file:</source>
+<target>讀取檔案錯誤:</target>
+
<source>Scanning:</source>
<target>正在掃瞄:</target>
@@ -220,15 +229,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>無效的 FreeFileSync 配置檔案!</target>
-<source>File does not exist:</source>
-<target>檔案不存在:</target>
-
<source>Error parsing configuration file:</source>
<target>分析配置檔案錯誤:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>移動到資源回收筒錯誤:</target>
+
+<source>Could not load a required DLL:</source>
+<target>無法載入一個所需的DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>讀取卷影複製服務時錯誤!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>不支援製作 WOW64 上的卷影副本。請使用 FreeFileSync 64位元版本。</target>
+
+<source>Could not determine volume name for file:</source>
+<target>無法判斷此檔案的卷標名稱:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>卷名 %x 並非檔名 %y 的一部份!</target>
+
<source>/sec</source>
<target>/秒</target>
+<source>File does not exist:</source>
+<target>檔案不存在:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>無法讀取 XML 之後節點的值:</target>
+
<source>S&ave configuration...</source>
<target>儲存配置(&A)...</target>
@@ -321,138 +351,6 @@ The command line is executed each time:
<source>A directory input field is empty.</source>
<target>目錄輸入的欄位為空</target>
-<source>Drag && drop</source>
-<target>拖放</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>無法初始化目錄監測:</target>
-
-<source>Error when monitoring directories.</source>
-<target>監測目錄錯誤。</target>
-
-<source>Conversion error:</source>
-<target>轉換錯誤:</target>
-
-<source>Error deleting file:</source>
-<target>刪除檔案錯誤:</target>
-
-<source>Error moving file:</source>
-<target>移動檔案錯誤:</target>
-
-<source>Target file already existing!</source>
-<target>目標檔案已存在!</target>
-
-<source>Error moving directory:</source>
-<target>移動目錄錯誤:</target>
-
-<source>Target directory already existing!</source>
-<target>目標目錄已存在!</target>
-
-<source>Error deleting directory:</source>
-<target>刪除目錄錯誤:</target>
-
-<source>Error changing modification time:</source>
-<target>變更修改時間錯誤:</target>
-
-<source>Error loading library function:</source>
-<target>載入函數庫錯誤:</target>
-
-<source>Error reading security context:</source>
-<target>讀取安全內文錯誤:</target>
-
-<source>Error writing security context:</source>
-<target>寫入安全性內容錯誤:</target>
-
-<source>Error copying file permissions:</source>
-<target>複製檔案權限錯誤:</target>
-
-<source>Error creating directory:</source>
-<target>新建目錄錯誤:</target>
-
-<source>Error copying symbolic link:</source>
-<target>複製符號連結錯誤:</target>
-
-<source>Error copying file:</source>
-<target>複製檔案錯誤:</target>
-
-<source>Error opening file:</source>
-<target>開啟檔案錯誤:</target>
-
-<source>Error writing file:</source>
-<target>寫入檔案錯誤:</target>
-
-<source>Error reading file:</source>
-<target>讀取檔案錯誤:</target>
-
-<source>Operation aborted!</source>
-<target>中止操作!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>當遍歷目錄時無限循環:</target>
-
-<source>Error traversing directory:</source>
-<target>遍歷目錄錯誤:</target>
-
-<source>Error setting privilege:</source>
-<target>設定權限錯誤:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>移動到資源回收筒錯誤:</target>
-
-<source>Could not load a required DLL:</source>
-<target>無法載入一個所需的DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>寫入同步資料庫錯誤:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>讀取卷影複製服務時錯誤!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>不支援製作 WOW64 上的卷影副本。請使用 FreeFileSync 64位元版本。</target>
-
-<source>Could not determine volume name for file:</source>
-<target>無法判斷此檔案的卷標名稱:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>卷名 %x 並非檔名 %y 的一部份!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>%x 分</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>%x 小時</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>%x 天</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>無法讀取 XML 之後節點的值:</target>
-
<source>Logging</source>
<target>日誌記錄</target>
@@ -471,9 +369,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>批次處理執行</target>
-<source>Log-messages:</source>
-<target>日誌訊息:</target>
-
<source>Stop</source>
<target>停止</target>
@@ -600,6 +495,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>將要傳輸的全部資料量</target>
+<source>Operation:</source>
+<target>操作:</target>
+
+<source>Items found:</source>
+<target>尋找要素:</target>
+
+<source>Items remaining:</source>
+<target>剩餘要素:</target>
+
+<source>Speed:</source>
+<target>速度:</target>
+
+<source>Time remaining:</source>
+<target>剩餘時間:</target>
+
+<source>Time elapsed:</source>
+<target>經過時間:</target>
+
<source>Batch job</source>
<target>批次處理作業</target>
@@ -648,31 +561,13 @@ The command line is executed each time:
<source>&Cancel</source>
<target>取消(&C)</target>
-<source>Operation:</source>
-<target>操作:</target>
-
-<source>Items found:</source>
-<target>尋找要素:</target>
-
-<source>Items remaining:</source>
-<target>剩餘要素:</target>
-
-<source>Speed:</source>
-<target>速度:</target>
-
-<source>Time remaining:</source>
-<target>剩餘時間:</target>
-
-<source>Time elapsed:</source>
-<target>經過時間:</target>
-
<source>Select variant:</source>
<target>選擇變數:</target>
<source><Automatic></source>
<target><自動></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
<target>對兩邊使用同一個資料庫的識別和傳送更改。自動檢測刪除和衝突部份。</target>
<source>Mirror ->></source>
@@ -886,27 +781,19 @@ Exclude: \stuff\temp\*
<target>異動檔案副本</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>第一次將檔寫入到一個暫存 (*.ffs_tmp) 順便將它們重新命名。即使在嚴重錯誤的情況下,還可確保一致的狀態。</target>
<source>Copy locked files</source>
<target>複製被鎖定的檔案</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-複製共用或鎖定檔案使用使用卷影複製服務(需要管理員權限)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>複製共用或鎖定檔案使用使用卷影複製服務(需要管理員權限)</target>
<source>Copy file access permissions</source>
<target>複製檔案系統權限</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-傳輸檔案和目錄權限(需要管理員權限)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>傳輸檔案和目錄權限(需要管理員權限)</target>
<source>Hidden dialogs:</source>
<target>隱藏對話框:</target>
@@ -938,6 +825,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>找下一個(&F)</target>
+<source>Operation aborted!</source>
+<target>中止操作!</target>
+
<source>Main bar</source>
<target>主欄位</target>
@@ -978,16 +868,16 @@ Transfer file and directory permissions (Requires Administrator rights)
<target>自動調整欄寬</target>
<source>Icon size:</source>
-<target></target>
+<target>圖示大小:</target>
<source>Small</source>
-<target></target>
+<target>小</target>
<source>Medium</source>
-<target></target>
+<target>中</target>
<source>Large</source>
-<target></target>
+<target>大</target>
<source>Include all rows</source>
<target>包括所有行</target>
@@ -1115,6 +1005,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>檔案清單已匯出!</target>
+<source>Error writing file:</source>
+<target>寫入檔案錯誤:</target>
+
<source>Batch file created successfully!</source>
<target>批次檔新建成功!</target>
@@ -1131,7 +1024,7 @@ Transfer file and directory permissions (Requires Administrator rights)
<pluralform>%x directories</pluralform>
</source>
<target>
-<pluralform>%x 目錄</pluralform>
+<pluralform>%x 個目錄</pluralform>
</target>
<source>
@@ -1139,7 +1032,7 @@ Transfer file and directory permissions (Requires Administrator rights)
<pluralform>%x files</pluralform>
</source>
<target>
-<pluralform>%x 檔案</pluralform>
+<pluralform>%x 個檔案</pluralform>
</target>
<source>
@@ -1210,9 +1103,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>篩選器:單對</target>
-<source>Ignore</source>
-<target>忽略</target>
-
<source>Direct</source>
<target>直接</target>
@@ -1274,6 +1164,102 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>移動檔案到一個時間標記的子目錄</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>%x 分</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>%x 小時</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>%x 天</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>無法初始化目錄監測:</target>
+
+<source>Error when monitoring directories.</source>
+<target>監測目錄錯誤。</target>
+
+<source>Conversion error:</source>
+<target>轉換錯誤:</target>
+
+<source>Error deleting file:</source>
+<target>刪除檔案錯誤:</target>
+
+<source>Error moving file:</source>
+<target>移動檔案錯誤:</target>
+
+<source>Target file already existing!</source>
+<target>目標檔案已存在!</target>
+
+<source>Error moving directory:</source>
+<target>移動目錄錯誤:</target>
+
+<source>Target directory already existing!</source>
+<target>目標目錄已存在!</target>
+
+<source>Error deleting directory:</source>
+<target>刪除目錄錯誤:</target>
+
+<source>Error changing modification time:</source>
+<target>變更修改時間錯誤:</target>
+
+<source>Error loading library function:</source>
+<target>載入函數庫錯誤:</target>
+
+<source>Error reading security context:</source>
+<target>讀取安全內文錯誤:</target>
+
+<source>Error writing security context:</source>
+<target>寫入安全性內容錯誤:</target>
+
+<source>Error copying file permissions:</source>
+<target>複製檔案權限錯誤:</target>
+
+<source>Error creating directory:</source>
+<target>新建目錄錯誤:</target>
+
+<source>Error copying symbolic link:</source>
+<target>複製符號連結錯誤:</target>
+
+<source>Error copying file:</source>
+<target>複製檔案錯誤:</target>
+
+<source>Error opening file:</source>
+<target>開啟檔案錯誤:</target>
+
+<source>Error traversing directory:</source>
+<target>遍歷目錄錯誤:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>當遍歷目錄時無限循環:</target>
+
+<source>Error setting privilege:</source>
+<target>設定權限錯誤:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>自上次同步後,兩邊均已更改過!</target>
@@ -1304,9 +1290,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>目錄有依靠性!請小心設定同步規則:</target>
-<source>Comparing content of files %x</source>
-<target>正在比對檔案内容的百分比 %x</target>
-
<source>Memory allocation failed!</source>
<target>記憶體分配失敗!</target>
@@ -1322,15 +1305,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>符號連結 %x 有相同日期但是不同目標!</target>
+<source>Comparing content of files %x</source>
+<target>正在比對檔案内容的百分比 %x</target>
+
<source>Comparing files by content failed.</source>
<target>比對檔案內容失敗。</target>
<source>Generating file list...</source>
<target>產生檔案清單...</target>
-<source>Multiple...</source>
-<target>多個...</target>
-
<source>Both sides are equal</source>
<target>兩邊都相同</target>
@@ -1349,6 +1332,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>刪除右邊檔案/資料夾</target>
+<source>Move file on left</source>
+<target>移動左邊的檔案</target>
+
+<source>Move file on right</source>
+<target>移動右邊的檔案</target>
+
<source>Overwrite left file/folder with right one</source>
<target>用適合檔案/資料夾覆蓋左邊檔案/資料夾</target>
@@ -1364,6 +1353,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>只複製檔案屬性到右邊</target>
+<source>Multiple...</source>
+<target>多個...</target>
+
<source>Deleting file %x</source>
<target>正在刪除檔案 %x</target>
diff --git a/BUILD/Languages/croatian.lng b/BUILD/Languages/croatian.lng
new file mode 100644
index 00000000..cba3663a
--- /dev/null
+++ b/BUILD/Languages/croatian.lng
@@ -0,0 +1,1490 @@
+<header>
+ <language name>Hrvatski</language name>
+ <translator>Slavko Blažević</translator>
+ <locale>hr_HR</locale>
+ <flag file>croatia.png</flag file>
+ <plural forms>3</plural forms>
+ <plural definition>n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2</plural definition>
+</header>
+
+<source>Searching for directory %x...</source>
+<target>Tražim direktorij %x...</target>
+
+<source>Show in Explorer</source>
+<target>Prikaži u Exploreru</target>
+
+<source>Open with default application</source>
+<target>Otvori s zadanom aplikacijom</target>
+
+<source>Browse directory</source>
+<target>Odaberi direktorij</target>
+
+<source>RealtimeSync - Automated Synchronization</source>
+<target>RealtimeSync - Automatska Sinkronizacija</target>
+
+<source>Select alternate comparison settings</source>
+<target>Izaberite alternativne postavke usporedbe</target>
+
+<source>Select alternate synchronization settings</source>
+<target>Izaberite alternativne postavke sinkronizacije</target>
+
+<source>No filter selected</source>
+<target>Nijedan filter odabran</target>
+
+<source>Filter is active</source>
+<target>Filter je aktivan</target>
+
+<source>Remove alternate settings</source>
+<target>Ukloni alternativne postavke</target>
+
+<source>Clear filter settings</source>
+<target>Počisti postavke filtera</target>
+
+<source>Create a batch job</source>
+<target>Izradi batch zadatak</target>
+
+<source>Synchronization settings</source>
+<target>Postavke sinkronizacije</target>
+
+<source>Comparison settings</source>
+<target>Postavke usporedbe</target>
+
+<source>About</source>
+<target>O programu</target>
+
+<source>Error</source>
+<target>Greška</target>
+
+<source>Warning</source>
+<target>Oprez</target>
+
+<source>Question</source>
+<target>Pitanje</target>
+
+<source>Confirm</source>
+<target>Potvrdi</target>
+
+<source>Configure filter</source>
+<target>Konfiguriraj filter</target>
+
+<source>Customize columns</source>
+<target>Uredi stupce</target>
+
+<source>Global settings</source>
+<target>Globalne postavke</target>
+
+<source>Synchronization Preview</source>
+<target>Pregled sinkronizacije</target>
+
+<source>Find</source>
+<target>Pronađi</target>
+
+<source>Select time span</source>
+<target>Izaberite mjerni raspon</target>
+
+<source>Show pop-up</source>
+<target>Prikaži skočni prozor</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Prikaži skočni prozor pri greškama i upozorenjima</target>
+
+<source>Ignore errors</source>
+<target>Ignoriraj greške</target>
+
+<source>Hide all error and warning messages</source>
+<target>Sakrij sve greške i upozorenja</target>
+
+<source>Exit instantly</source>
+<target>Izađi trenutno</target>
+
+<source>Abort synchronization immediately</source>
+<target>Odmah prekini sinkronizaciju</target>
+
+<source>Browse</source>
+<target>Odaberi</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Greška pri čitanju iz sinkronizacijske baze:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Greška pri pisanju u sinkronizacijsku bazu:</target>
+
+<source>Invalid command line: %x</source>
+<target>Netočna naredba: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows greška %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux greška %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Pogreška pri otvaranju poveznice simbola:</target>
+
+<source>%x MB</source>
+<target>%x MB</target>
+
+<source>%x KB</source>
+<target>%x KB</target>
+
+<source>%x GB</source>
+<target>%x GB</target>
+
+<source>
+<pluralform>1 Byte</pluralform>
+<pluralform>%x Bytes</pluralform>
+</source>
+<target>
+<pluralform>%x Bajt</pluralform>
+<pluralform>%x Bajta</pluralform>
+<pluralform>%x Bajtova</pluralform>
+</target>
+
+<source><Symlink></source>
+<target><Poveznica simbola></target>
+
+<source><Directory></source>
+<target><Direktorij></target>
+
+<source>Size</source>
+<target>Veličina</target>
+
+<source>Date</source>
+<target>Datum</target>
+
+<source>Full path</source>
+<target>Puna putanja</target>
+
+<source>Filename</source>
+<target>Ime datoteke</target>
+
+<source>Relative path</source>
+<target>Relativna Putanja</target>
+
+<source>Directory</source>
+<target>Direktorij</target>
+
+<source>Extension</source>
+<target>Ekstenzija</target>
+
+<source>Comparison Result</source>
+<target>Rezultati usporedbe</target>
+
+<source>Initial synchronization:</source>
+<target>Početna sinkronizacija:</target>
+
+<source>One of the FreeFileSync database files is not yet existing:</source>
+<target>Jedna od FreeFileSync datoteka podatkovne baze još ne postoji:</target>
+
+<source>Incompatible synchronization database format:</source>
+<target>Nekompatibilan format sinkronizacijske podatkovne baze:</target>
+
+<source>Database files do not share a common synchronization session:</source>
+<target>Datoteke podatkovne baze ne dijele zajedničke sinkronizacijske sesije:</target>
+
+<source>An exception occurred!</source>
+<target>Dogodilo se izuzeće!</target>
+
+<source>Error reading file attributes:</source>
+<target>Greška pri čitanju atributa datoteke:</target>
+
+<source>Waiting while directory is locked (%x)...</source>
+<target>Čekam dok se direktorij zaključava (%x)...</target>
+
+<source>Error setting directory lock:</source>
+<target>Greška pri postavljanju zaključenja direktorija:</target>
+
+<source>
+<pluralform>1 sec</pluralform>
+<pluralform>%x sec</pluralform>
+</source>
+<target>
+<pluralform>%x sek</pluralform>
+<pluralform>%x sek</pluralform>
+<pluralform>%x sek</pluralform>
+</target>
+
+<source>Drag && drop</source>
+<target>Povuci && ispusti</target>
+
+<source>Info</source>
+<target>Info</target>
+
+<source>Fatal Error</source>
+<target>Kritična greška</target>
+
+<source>Error reading file:</source>
+<target>Greška pri čitanju datoteke:</target>
+
+<source>Scanning:</source>
+<target>Pretražujem:</target>
+
+<source>Encoding extended time information: %x</source>
+<target>:Spremam informacije o vremenu %x</target>
+
+<source>
+<pluralform>[1 Thread]</pluralform>
+<pluralform>[%x Threads]</pluralform>
+</source>
+<target>
+<pluralform>%x Stavka</pluralform>
+<pluralform>%x Stavke</pluralform>
+<pluralform>% Stavki</pluralform>
+</target>
+
+<source>Invalid FreeFileSync config file!</source>
+<target>Nevaljana FreeFileSync konfiguracijska datoteka!</target>
+
+<source>Error parsing configuration file:</source>
+<target>Greška pri raščlanjivanju datoteke postavki:</target>
+
+<source>Error moving to Recycle Bin:</source>
+<target>Greška pri premještanju u Koš za smeće:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Nemože se pokrenuti potrebni DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Greška pri pristupu servisu particijskog kopiranja!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Stvaranje sjeničnih kopija na WOW63 nije podržano. Molimo koristite 64-bitnu FreeFileSync inačnicu.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Nemože se odrediti naziv particije za datoteku:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Naziv particije %x dio naziva datoteke %y!</target>
+
+<source>/sec</source>
+<target>/sek</target>
+
+<source>File does not exist:</source>
+<target>Datoteka ne postoji:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Nemogu pročitati vrijednosti iz slijedećih XML središta:</target>
+
+<source>S&ave configuration...</source>
+<target>&Spremi postavke...</target>
+
+<source>&Load configuration...</source>
+<target>&Uvezi postavke...</target>
+
+<source>&Quit</source>
+<target>&Izlaz</target>
+
+<source>&File</source>
+<target>&Datoteka</target>
+
+<source>&Content</source>
+<target>&Sadržaj</target>
+
+<source>&About...</source>
+<target>&O programu...</target>
+
+<source>&Help</source>
+<target>&Pomoć</target>
+
+<source>Usage:</source>
+<target>Uporaba:</target>
+
+<source>1. Select directories to monitor.</source>
+<target>1. Izaberite mape za nadziranje</target>
+
+<source>2. Enter a command line.</source>
+<target>2. Unesite naredbu.</target>
+
+<source>3. Press 'Start'.</source>
+<target>3. Pretisnite 'Start'.</target>
+
+<source>
+The command line is executed each time:
+- all directories become available (e.g. USB stick insert)
+- files within these directories or subdirectories are modified
+</source>
+<target>
+Naredba će biti izvršena kada:
+- sve mape postanu dostupne (npr. USB stick je umetnut)
+- datoteke unutar tih mapa ili podmapa budu mijenjane
+</target>
+
+<source>Directories to watch</source>
+<target>Mape za nadziranje</target>
+
+<source>Add folder</source>
+<target>Dodaj mapu</target>
+
+<source>Remove folder</source>
+<target>Ukloni mapu</target>
+
+<source>Select a folder</source>
+<target>Izaberite mapu</target>
+
+<source>Command line</source>
+<target>Naredbena linija</target>
+
+<source>Minimum Idle Time [seconds]</source>
+<target>Minimalno vrijeme pripravnosti [sekunde]</target>
+
+<source>Idle time between detection of last change and execution of command line in seconds</source>
+<target>Vrijeme pripravnosti između pronalaska zadnje promjene i izvršenja naredbe u sekundama</target>
+
+<source>Start</source>
+<target>Start</target>
+
+<source>(Build: %x)</source>
+<target>(Inačnica: %x)</target>
+
+<source>RealtimeSync configuration</source>
+<target>RealtimeSync postavke</target>
+
+<source>File already exists. Overwrite?</source>
+<target>Datoteka već postoji. Prepisati?</target>
+
+<source>&Restore</source>
+<target>&Vrati</target>
+
+<source>&Exit</source>
+<target>&Izlaz</target>
+
+<source>Monitoring active...</source>
+<target>Nadziranje aktivno...</target>
+
+<source>Waiting for missing directories...</source>
+<target>Čekam nedostajuće direktorije...</target>
+
+<source>A directory input field is empty.</source>
+<target>Upisno polje za direktorij je prazno.</target>
+
+<source>Logging</source>
+<target>Zapisivanje</target>
+
+<source>FreeFileSync batch file</source>
+<target>FreeFileSync batch datoteka</target>
+
+<source>FreeFileSync configuration</source>
+<target>FreeFileSync postavke</target>
+
+<source>FreeFileSync Batch Job</source>
+<target>FreeFileSync Batch zadatak</target>
+
+<source>Unable to create logfile!</source>
+<target>Nemogu napraviti zapisnik!</target>
+
+<source>Batch execution</source>
+<target>Batch izvršavanje</target>
+
+<source>Stop</source>
+<target>Zaustavi</target>
+
+<source>Total time:</source>
+<target>Ukupno vrijeme:</target>
+
+<source>Synchronization aborted!</source>
+<target>Sinkronizacija prekinuta!</target>
+
+<source>Synchronization completed with errors!</source>
+<target>Sinkronizacija završena s greškama!</target>
+
+<source>Synchronization completed successfully!</source>
+<target>Sinkronizacija uspješno završena!</target>
+
+<source>Press "Switch" to open FreeFileSync GUI mode.</source>
+<target>Pretisnite "Zamjena", da otvorite FreeFileSync GUI način.</target>
+
+<source>Switching to FreeFileSync GUI mode...</source>
+<target>Prelazim na FreeFileSync GUI način...</target>
+
+<source>Unable to connect to sourceforge.net!</source>
+<target>Ne mogu se povezati na sourceforge.net!</target>
+
+<source>A newer version of FreeFileSync is available:</source>
+<target>Dostupna je nova verzija FreeFileSync:</target>
+
+<source>Download now?</source>
+<target>Preuzeti sada?</target>
+
+<source>Information</source>
+<target>Informacija</target>
+
+<source>FreeFileSync is up to date!</source>
+<target>FreeFileSync je ažuriran!</target>
+
+<source>Do you want FreeFileSync to automatically check for updates every week?</source>
+<target>Dali želite da FreeFileSync automatski traži ažuriranja svaki tjedan?</target>
+
+<source>(Requires an Internet connection!)</source>
+<target>(Zahtjeva vezu na Internet!)</target>
+
+<source>1. &Compare</source>
+<target>1. &Usporedi</target>
+
+<source>2. &Synchronize...</source>
+<target>2. &Sinkroniziraj...</target>
+
+<source>S&witch view</source>
+<target>Pr&omjeni pogled</target>
+
+<source>&New</source>
+<target>&Novo</target>
+
+<source>&Program</source>
+<target>&Program</target>
+
+<source>&Language</source>
+<target>&Jezik</target>
+
+<source>&Global settings...</source>
+<target>&Globalne postavke...</target>
+
+<source>&Create batch job...</source>
+<target>&Izradi batch zadatak...</target>
+
+<source>&Export file list...</source>
+<target>&Izvoz liste datoteka...</target>
+
+<source>&Advanced</source>
+<target>&Napredno</target>
+
+<source>&Check for new version</source>
+<target>&Provjeri za novu verziju</target>
+
+<source>Compare</source>
+<target>Usporedi</target>
+
+<source>Compare both sides</source>
+<target>Usporedi obje strane</target>
+
+<source>&Abort</source>
+<target>&Odustani</target>
+
+<source>Synchronize...</source>
+<target>Sinkroniziraj...</target>
+
+<source>Start synchronization</source>
+<target>Započni sinkronizaciju</target>
+
+<source>Add folder pair</source>
+<target>Dodaj mapu</target>
+
+<source>Remove folder pair</source>
+<target>Odstrani mapu</target>
+
+<source>Swap sides</source>
+<target>Zamjeni strane</target>
+
+<source>Save current configuration to file</source>
+<target>Spremi sadašnje postavke u datoteku</target>
+
+<source>Load configuration from file</source>
+<target>Uvezi postavke iz datoteke</target>
+
+<source>Last used configurations (press DEL to remove from list)</source>
+<target>Zadnje korištene postavke (pretisite DEL za ukloniti s liste)</target>
+
+<source>Hide excluded items</source>
+<target>Sakrij isključene stavke</target>
+
+<source>Hide filtered or temporarily excluded files</source>
+<target>Sakrij filtrirane ili trenutno isključene datoteke</target>
+
+<source>Number of files and directories that will be created</source>
+<target>Broj datoteka i direktorija koji će biti napravljeni</target>
+
+<source>Number of files that will be overwritten</source>
+<target>Broj datoteka koje će biti prepisane</target>
+
+<source>Number of files and directories that will be deleted</source>
+<target>Broj datoteka i direktorija koji će biti izbrisani</target>
+
+<source>Total amount of data that will be transferred</source>
+<target>Ukupna količina podataka koja će biti prebečana</target>
+
+<source>Operation:</source>
+<target>Operacija:</target>
+
+<source>Items found:</source>
+<target>Pronađene stavke:</target>
+
+<source>Items remaining:</source>
+<target>Preostale stavke:</target>
+
+<source>Speed:</source>
+<target>Brzina:</target>
+
+<source>Time remaining:</source>
+<target>Vremena preostalo:</target>
+
+<source>Time elapsed:</source>
+<target>Vremena prošlo:</target>
+
+<source>Batch job</source>
+<target>Batch zadatak</target>
+
+<source>Create a batch file for automated synchronization. To start in batch mode simply double-click the file or execute via command line: FreeFileSync.exe <ffs_batch file>. This can also be scheduled in your operating system's task planner.</source>
+<target>Napravite batch datoteku za automatsku sinkronizaciju. Da bi započeli batch mod dvostruki-klik na fajl ili izvršite pomoću komandne linije: FreeFileSync.exe <ffs_batch datoteka>. Ovo se također može zadati u planeru operacijskog sustava.</target>
+
+<source>Help</source>
+<target>Pomoć</target>
+
+<source>Filter files</source>
+<target>Filtriraj datoteke</target>
+
+<source>Error handling</source>
+<target>Greška pri obradi</target>
+
+<source>Left</source>
+<target>Lijevo</target>
+
+<source>Right</source>
+<target>Desno</target>
+
+<source>Overview</source>
+<target>Pregled</target>
+
+<source>Status feedback</source>
+<target>Status veze</target>
+
+<source>Run minimized</source>
+<target>Pokreni minimizirano</target>
+
+<source>Maximum number of logfiles:</source>
+<target>Maksimalan broj izvješća:</target>
+
+<source>Select logfile directory:</source>
+<target>Odaberite direktorij izvješća:</target>
+
+<source>Batch settings</source>
+<target>Batch postavke</target>
+
+<source>&Save</source>
+<target>&Spremi</target>
+
+<source>&Load</source>
+<target>&Uvezi</target>
+
+<source>&Cancel</source>
+<target>&Odustani</target>
+
+<source>Select variant:</source>
+<target>Izaberite varijantu:</target>
+
+<source><Automatic></source>
+<target><Automatski></target>
+
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identificiraj i izvedi promjene na obje strane koristeći bazu podataka. Brisanja, preimenovanja i sukobi se automatski detektiraju</target>
+
+<source>Mirror ->></source>
+<target>Zrcalno ->></target>
+
+<source>Mirror backup of left folder. Right folder is modified to exactly match left folder after synchronization.</source>
+<target>Zrcalna pričuva lijeve mape. Desna mapa je uređena da bi bila jednaka lijevom folderu nakon sinkronizacije.</target>
+
+<source>Update -></source>
+<target>Ažuriraj -></target>
+
+<source>Copy new or updated files to right folder.</source>
+<target>Kopiraj nove ili ažurirane datoteke u desnu mapu.</target>
+
+<source>Custom</source>
+<target>Uobičajeno</target>
+
+<source>Configure your own synchronization rules.</source>
+<target>Konfigurirajte vaša vlastita sinkronizacijska pravila.</target>
+
+<source>Deletion handling</source>
+<target>Upravljanje pri brisanju</target>
+
+<source>&OK</source>
+<target>&U redu</target>
+
+<source>Configuration</source>
+<target>Postavke</target>
+
+<source>Category</source>
+<target>Kategorija</target>
+
+<source>Action</source>
+<target>Radnja</target>
+
+<source>File/folder exists on left side only</source>
+<target>Datoteka/mapa postoji samo na lijevoj strani</target>
+
+<source>File/folder exists on right side only</source>
+<target>Datoteka/mapa postoji samo na desnoj strani</target>
+
+<source>Left file is newer</source>
+<target>Lijeva datoteka je novija</target>
+
+<source>Right file is newer</source>
+<target>Desna datoteka je novija</target>
+
+<source>Files have different content</source>
+<target>Datoteke imaju različit sadržaj</target>
+
+<source>Conflict/file cannot be categorized</source>
+<target>Konflikt/datoteka ne more biti kategorizirana</target>
+
+<source>Compare by...</source>
+<target>Usporedi prema...</target>
+
+<source>
+Files are found equal if
+ - last write time and date
+ - file size
+are the same
+</source>
+<target>
+Datoteke se smatraju jednake ako su im
+ - vrijeme zadnje promjene i datum
+ - veličina datoteke
+jednaki
+</target>
+
+<source>File time and size</source>
+<target>Vrijeme i veličina datoteke</target>
+
+<source>
+Files are found equal if
+ - file content
+is the same
+</source>
+<target>
+Datoteke se smatraju jednake ako im je
+ - sadržaj datoteke
+jednak
+</target>
+
+<source>File content</source>
+<target>Sadržaj datoteke</target>
+
+<source>Symbolic Link handling</source>
+<target>Upravljanje simboličnim poveznicama</target>
+
+<source>Synchronizing...</source>
+<target>Sinkroniziram...</target>
+
+<source>Items processed:</source>
+<target>Obrađeni elementi:</target>
+
+<source>&Pause</source>
+<target>&Pauziraj</target>
+
+<source>Source code written in C++ utilizing:</source>
+<target>Izvorni kod napisan u C++ uz korištenje:</target>
+
+<source>Big thanks for localizing FreeFileSync goes out to:</source>
+<target>Zahvale za prijevod FreeFileSync idu:</target>
+
+<source>Feedback and suggestions are welcome at:</source>
+<target>Povratne informacije i prijedlozi su dobrodošli na:</target>
+
+<source>FreeFileSync at Sourceforge</source>
+<target>FreeFileSync na Sourceforge</target>
+
+<source>Homepage</source>
+<target>Početna stranica</target>
+
+<source>If you like FFS</source>
+<target>Ako volite FFS</target>
+
+<source>Donate with PayPal</source>
+<target>Doniraj s PayPal</target>
+
+<source>Email</source>
+<target>Email</target>
+
+<source>Report translation error</source>
+<target>Prijavi grešku u prijevodu</target>
+
+<source>Published under the GNU General Public License:</source>
+<target>Objavljeno pod licencom GNU General Public:</target>
+
+<source>Ignore subsequent errors</source>
+<target>Ignoriraj naknadne greške</target>
+
+<source>Hide further error messages during the current process</source>
+<target>Sakrij iduće poruke grešaka tokom slijedećeg procesa</target>
+
+<source>&Ignore</source>
+<target>&Ignoriraj</target>
+
+<source>&Retry</source>
+<target>&Ponovi</target>
+
+<source>Do not show this dialog again</source>
+<target>Ne prikazuj ovaj prozor ponovno</target>
+
+<source>&Switch</source>
+<target>&Zamjeni</target>
+
+<source>&Yes</source>
+<target>&Da</target>
+
+<source>&No</source>
+<target>&Ne</target>
+
+<source>Delete on both sides</source>
+<target>Izbriši na obje strane</target>
+
+<source>Delete on both sides even if the file is selected on one side only</source>
+<target>Izbriši na obje strane iako je označena datoteka samo na jednoj strani</target>
+
+<source>Use Recycle Bin</source>
+<target>Uporabi Koš za smeće</target>
+
+<source>
+Only files/directories that match all filter settings will be selected for synchronization.
+Note: The name filter must be specified relative(!) to main synchronization directories.
+</source>
+<target>
+Samo datoteke/direktorije koji odgovaraju svim filterskim postavkama će biti odabrane za sinkronizaciju.
+Napomena: Ime filtra mora biti određeno relativno(!) prema glavnim sinkronizacijskim direktorijima.
+</target>
+
+<source>Hints:</source>
+<target>Savjeti:</target>
+
+<source>1. Enter relative file or directory names separated by ';' or a new line.</source>
+<target>1. Unesite relativno ime datoteke ili naziva direktorija odvojeno ';' ili novim redom.</target>
+
+<source>2. Use wildcard characters '*' and '?'.</source>
+<target>2. Uporabite znakove poput '*' ili '?'.</target>
+
+<source>3. Exclude files directly on main grid via context menu.</source>
+<target>3. Isključite datoteke neposredno na glavnoj mreži s kontekstnog menija.</target>
+
+<source>Example</source>
+<target>Primjer</target>
+
+<source>
+Include: *.doc;*.zip;*.exe
+Exclude: \stuff\temp\*
+</source>
+<target>
+Uključi: *.doc;*.zip;*.exe
+Isključi: \stuff\temp\*
+</target>
+
+<source>Synchronize all .doc, .zip and .exe files except everything in subfolder "temp".</source>
+<target>Sinkroniziraj sve .doc, .zip i .exe datoteke, izuzev svega iz podmape "temp".</target>
+
+<source>Include</source>
+<target>Uključi</target>
+
+<source>Exclude</source>
+<target>Isključi</target>
+
+<source>Minimum file size</source>
+<target>Minimalna veličina datoteke</target>
+
+<source>Maximum file size</source>
+<target>Maksimalna veličina datoteke</target>
+
+<source>&Default</source>
+<target>&Zadano</target>
+
+<source>Move column up</source>
+<target>Premakni stupac gore</target>
+
+<source>Move column down</source>
+<target>Premakni stupac dolje</target>
+
+<source>Transactional file copy</source>
+<target>Transakcijsko kopiranje datoteke</target>
+
+<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
+<target>Zapiši u privremenu datoteku (*.ffs_tmp) najprije a onda ju preimenuj. Ovo garantira nepromjenjivost čak u slučaju kritične greške.</target>
+
+<source>Copy locked files</source>
+<target>Kopiraj zaključane datoteke</target>
+
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopiraj zajedničke ili zaključane datoteke koristeći Volume Shadow Copy Servis(Zahtjeva Administratorske ovlasti)</target>
+
+<source>Copy file access permissions</source>
+<target>Kopiraj datotečna dopuštenja</target>
+
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Prebaci datotečna dopuštenja (Zahtjeva Administratorske ovlasti)</target>
+
+<source>Hidden dialogs:</source>
+<target>Skriveni prozori:</target>
+
+<source>Reset</source>
+<target>Resetiraj</target>
+
+<source>Show hidden dialogs</source>
+<target>Prikaži skrivene prozore</target>
+
+<source>External applications</source>
+<target>Vanjske aplikacije</target>
+
+<source>Description</source>
+<target>Opis</target>
+
+<source>Variant</source>
+<target>Način</target>
+
+<source>Statistics</source>
+<target>Statistika</target>
+
+<source>Find what:</source>
+<target>Nađi što</target>
+
+<source>Match case</source>
+<target>Poklopi se</target>
+
+<source>&Find next</source>
+<target>&Nađi slijedeće</target>
+
+<source>Operation aborted!</source>
+<target>Operacija otkazana!</target>
+
+<source>Main bar</source>
+<target>Glavna traka</target>
+
+<source>Folder pairs</source>
+<target>Par mape</target>
+
+<source>Select view</source>
+<target>Izaberite pogled</target>
+
+<source>Set direction:</source>
+<target>Odaberi smijer:</target>
+
+<source>Exclude temporarily</source>
+<target>Trenutno izključi</target>
+
+<source>Include temporarily</source>
+<target>Trenutno uključi</target>
+
+<source>Exclude via filter:</source>
+<target>Isključi preko filtra:</target>
+
+<source><multiple selection></source>
+<target><višestruki odabir></target>
+
+<source>D-Click</source>
+<target>D-Klik</target>
+
+<source>Delete</source>
+<target>Izbriši</target>
+
+<source>Customize...</source>
+<target>Prilagodi...</target>
+
+<source>Select time span...</source>
+<target>Izaberite vremenski raspon...</target>
+
+<source>Auto-adjust columns</source>
+<target>Samo-prilagodi stupce</target>
+
+<source>Icon size:</source>
+<target>Veličina Ikone</target>
+
+<source>Small</source>
+<target>Malo</target>
+
+<source>Medium</source>
+<target>Srednje</target>
+
+<source>Large</source>
+<target>Veliko</target>
+
+<source>Include all rows</source>
+<target>Uključi sve redove</target>
+
+<source>Exclude all rows</source>
+<target>Isključi sve redove</target>
+
+<source>Reset view</source>
+<target>Resetiraj pogled</target>
+
+<source>Show "%x"</source>
+<target>Prikaži "%x"</target>
+
+<source><Last session></source>
+<target><Zadnja sesija></target>
+
+<source>Configuration saved!</source>
+<target>Postavke spremljene!</target>
+
+<source>Save changes to current configuration?</source>
+<target>Spremiti promjene na trenutne postavke?</target>
+
+<source>Configuration loaded!</source>
+<target>Postavke učitane!</target>
+
+<source>Folder Comparison and Synchronization</source>
+<target>Usporedba i sinkronizacija mapa</target>
+
+<source>Hide files that exist on left side only</source>
+<target>Sakrij datoteke koje postoje samo na lijevoj strani</target>
+
+<source>Show files that exist on left side only</source>
+<target>Prikaži datoteke koje postoje samo na lijevoj strani</target>
+
+<source>Hide files that exist on right side only</source>
+<target>Sakrij datoteke koje koje postoje samo na desnoj strani</target>
+
+<source>Show files that exist on right side only</source>
+<target>Prikaži datoteke koje postoje samo na desnoj strani</target>
+
+<source>Hide files that are newer on left</source>
+<target>Sakrij datoteke koje su novije lijevo</target>
+
+<source>Show files that are newer on left</source>
+<target>Prikaži datoteke koje su novije lijevo</target>
+
+<source>Hide files that are newer on right</source>
+<target>Skrij datoteke koje su novije desno</target>
+
+<source>Show files that are newer on right</source>
+<target>Prikaži datoteke koje su novije desno</target>
+
+<source>Hide files that are equal</source>
+<target>Skrij jednake datoteke</target>
+
+<source>Show files that are equal</source>
+<target>Prikaži jednake datoteke</target>
+
+<source>Hide files that are different</source>
+<target>Sakrij datoteke koje su različite</target>
+
+<source>Show files that are different</source>
+<target>Prikaži datoteke koje su različite</target>
+
+<source>Hide conflicts</source>
+<target>Sakrij sukobe</target>
+
+<source>Show conflicts</source>
+<target>Prikaži spore</target>
+
+<source>Hide files that will be created on the left side</source>
+<target>Sakrij datoteke koje će biti napravljene na lijevoj strani</target>
+
+<source>Show files that will be created on the left side</source>
+<target>Prikaži datoteke koje će biti napravljene na lijevoj strani</target>
+
+<source>Hide files that will be created on the right side</source>
+<target>Sakrij datoteke koje će biti napravljene na desnoj strani</target>
+
+<source>Show files that will be created on the right side</source>
+<target>Prikaži datoteke koje će biti napravljene na desnoj strani</target>
+
+<source>Hide files that will be deleted on the left side</source>
+<target>Sakrij datoteke koje će biti izbrisane na lijevoj strani</target>
+
+<source>Show files that will be deleted on the left side</source>
+<target>Prikaži datoteke koje će biti izbrisane na lijevoj strani</target>
+
+<source>Hide files that will be deleted on the right side</source>
+<target>Skrij datoteke koje će biti izbrisane na desnoj strani</target>
+
+<source>Show files that will be deleted on the right side</source>
+<target>Prikaži datoteke koje će biti izbrisane na desnoj strani</target>
+
+<source>Hide files that will be overwritten on left side</source>
+<target>Skrij datoteke koje će biti prepisane na lijevoj strani</target>
+
+<source>Show files that will be overwritten on left side</source>
+<target>Prikaži datoteke koje će biti prepisane na lijevoj strani</target>
+
+<source>Hide files that will be overwritten on right side</source>
+<target>Skrij datoteke koje će biti prepisane na desnoj strani</target>
+
+<source>Show files that will be overwritten on right side</source>
+<target>Prikaži datoteke koje će biti prepisane na desnoj strani</target>
+
+<source>Hide files that won't be copied</source>
+<target>Sakrij datoteke koje neće biti kopirane</target>
+
+<source>Show files that won't be copied</source>
+<target>Prikaži datoteke koje neće biti kopirane</target>
+
+<source>All directories in sync!</source>
+<target>Svi direktoriji su sinkronizirani!</target>
+
+<source>Please run a Compare first before synchronizing!</source>
+<target>Molmo pokrenite Usporedbu prije sinkronizacije!</target>
+
+<source>Comma separated list</source>
+<target>Zarezom odvojene liste</target>
+
+<source>Legend</source>
+<target>Legenda</target>
+
+<source>File list exported!</source>
+<target>Datotečna lista izvezena!</target>
+
+<source>Error writing file:</source>
+<target>Napaka pri pisanju datoteke:</target>
+
+<source>Batch file created successfully!</source>
+<target>Batch datoteka uspješno izrađena!</target>
+
+<source>
+<pluralform>Object deleted successfully!</pluralform>
+<pluralform>%x objects deleted successfully!</pluralform>
+</source>
+<target>
+<pluralform>%x Objekt uspješno izbrisan!</pluralform>
+<pluralform>%x objekta uspješno izbrisana!</pluralform>
+<pluralform>%x objekata uspješno izbrisano!</pluralform>
+</target>
+
+<source>
+<pluralform>1 directory</pluralform>
+<pluralform>%x directories</pluralform>
+</source>
+<target>
+<pluralform>%x direktorij</pluralform>
+<pluralform>%x direktorija</pluralform>
+<pluralform>%x direktorija</pluralform>
+</target>
+
+<source>
+<pluralform>1 file</pluralform>
+<pluralform>%x files</pluralform>
+</source>
+<target>
+<pluralform>%x datoteka</pluralform>
+<pluralform>%x datoteke</pluralform>
+<pluralform>%x datoteka</pluralform>
+</target>
+
+<source>
+<pluralform>%x of 1 row in view</pluralform>
+<pluralform>%x of %y rows in view</pluralform>
+</source>
+<target>
+<pluralform>%x od %y red u prikazu</pluralform>
+<pluralform>%x od %y reda u prikazu</pluralform>
+<pluralform>%x od %y redova u prikazu</pluralform>
+</target>
+
+<source>Scanning...</source>
+<target>Pregledajem...</target>
+
+<source>Comparing content...</source>
+<target>Uspoređujem sadržaj...</target>
+
+<source>Paused</source>
+<target>Pauzirano</target>
+
+<source>Aborted</source>
+<target>Prekinuto</target>
+
+<source>Completed</source>
+<target>Završeno</target>
+
+<source>Abort requested: Waiting for current operation to finish...</source>
+<target>Prekid zahtjevan: čekam da se trenutna akcija završi...</target>
+
+<source>Continue</source>
+<target>Nastavi</target>
+
+<source>Pause</source>
+<target>Pauziraj</target>
+
+<source>Cannot find %x</source>
+<target>Nemogu pronać %x</target>
+
+<source>Inactive</source>
+<target>Neaktivno</target>
+
+<source>Last x hours</source>
+<target>Zadnjih x sati</target>
+
+<source>Today</source>
+<target>Danas</target>
+
+<source>This week</source>
+<target>Ovaj tjedan</target>
+
+<source>This month</source>
+<target>Ovaj mjesec</target>
+
+<source>This year</source>
+<target>Ove godine</target>
+
+<source>Byte</source>
+<target>Bajt</target>
+
+<source>KB</source>
+<target>KB</target>
+
+<source>MB</source>
+<target>MB</target>
+
+<source>Filter: All pairs</source>
+<target>Filtriraj: Sve parove</target>
+
+<source>Filter: Single pair</source>
+<target>Filtriraj: Sam par</target>
+
+<source>Direct</source>
+<target>Neposredno</target>
+
+<source>Follow</source>
+<target>Slijedi</target>
+
+<source>Copy NTFS permissions</source>
+<target>Kopiraj NTFS dopuštenja</target>
+
+<source>Integrate external applications into context menu. The following macros are available:</source>
+<target>Integriraj vanjske aplikacije u kontekstni meni. Sljedeći makroi su dostupni:</target>
+
+<source>- full file or directory name</source>
+<target>- puno ime datoteke ili direktorija</target>
+
+<source>- directory part only</source>
+<target>- samo dio direktorija</target>
+
+<source>- Other side's counterpart to %name</source>
+<target>- Duplikat s druge strane k %name</target>
+
+<source>- Other side's counterpart to %dir</source>
+<target>- Duplikat s druge strane k %dir</target>
+
+<source>Restore all hidden dialogs?</source>
+<target>Vrati sve skrivene prozore?</target>
+
+<source>
+<pluralform>Do you really want to move the following object to the Recycle Bin?</pluralform>
+<pluralform>Do you really want to move the following %x objects to the Recycle Bin?</pluralform>
+</source>
+<target>
+<pluralform>Dali zaista želite prebaciti navedeni %x objekt u Koš za smeće?</pluralform>
+<pluralform>Dali zaista želite prebaciti navedena %x objekta u Koš za smeće?</pluralform>
+<pluralform>Dali zaista želite prebaciti navedenih %x objekata u Koš za smeće?</pluralform>
+</target>
+
+<source>
+<pluralform>Do you really want to delete the following object?</pluralform>
+<pluralform>Do you really want to delete the following %x objects?</pluralform>
+</source>
+<target>
+<pluralform>Dali zaista želite izbrisati navedeni %x objekt?</pluralform>
+<pluralform>Dali zaista želite izbrisati navedena %x objekta?</pluralform>
+<pluralform>Dali zaista želite izbrisati navedenih %x objekata?</pluralform>
+</target>
+
+<source>Leave as unresolved conflict</source>
+<target>Ostavi kao neriješeni sukob</target>
+
+<source>Delete permanently</source>
+<target>Trajno izbriši</target>
+
+<source>Delete or overwrite files permanently</source>
+<target>Trajno izbriši ili prepiši datoteke</target>
+
+<source>Use Recycle Bin when deleting or overwriting files</source>
+<target>Koristi Koš za smeće pri brisanju ili prepisivanju datoteka</target>
+
+<source>Versioning</source>
+<target>Verzija</target>
+
+<source>Move files into a time-stamped subdirectory</source>
+<target>Premjesti datoteke u vremenski-označen podfolder</target>
+
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>%x min</pluralform>
+<pluralform>%x min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>%x sat</pluralform>
+<pluralform>%x sata</pluralform>
+<pluralform>%x sati</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>%x dan</pluralform>
+<pluralform>%x dana</pluralform>
+<pluralform>%x dana</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Ne mogu započeti nadziranje direktorija:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Greška pri nadziranju direktorija.</target>
+
+<source>Conversion error:</source>
+<target>Greška pri pretvorbi:</target>
+
+<source>Error deleting file:</source>
+<target>Greška pri brisanju datoteke:</target>
+
+<source>Error moving file:</source>
+<target>Greška pri premještanju datoteke:</target>
+
+<source>Target file already existing!</source>
+<target>Ciljna datoteka već postoji!</target>
+
+<source>Error moving directory:</source>
+<target>Greška pri premještanju direktorija:</target>
+
+<source>Target directory already existing!</source>
+<target>Ciljni direktorij već postoji!</target>
+
+<source>Error deleting directory:</source>
+<target>Greška pri brisanju direktorija:</target>
+
+<source>Error changing modification time:</source>
+<target>Greška pri promjeni vremena izmjene:</target>
+
+<source>Error loading library function:</source>
+<target>Greška pri zadavanju funkcije iz knjižnice:</target>
+
+<source>Error reading security context:</source>
+<target>Greška pri čitanju zaštićenog sadržaja:</target>
+
+<source>Error writing security context:</source>
+<target>Greška pri pisanju zaštićenog sadržaja:</target>
+
+<source>Error copying file permissions:</source>
+<target>Greška pri kopiranju datotečnih dopuštenja:</target>
+
+<source>Error creating directory:</source>
+<target>Greška pri izradi direktorija:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Greška pri kopiranju poveznice simbola:</target>
+
+<source>Error copying file:</source>
+<target>Greška pri kopiranju datoteke:</target>
+
+<source>Error opening file:</source>
+<target>Greška pri otvaranju datoteke:</target>
+
+<source>Error traversing directory:</source>
+<target>Greška pri prelasku direktorija:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Beskonačna petlja pri prelasku direktorija:</target>
+
+<source>Error setting privilege:</source>
+<target>Greška pri postavljanju dopuštenja:</target>
+
+<source>Both sides have changed since last synchronization!</source>
+<target>Obje su strane promjenjene od posljednje sinkronizacije!</target>
+
+<source>Cannot determine sync-direction:</source>
+<target>Ne mogu odrediti smijer sinkronizacije.</target>
+
+<source>No change since last synchronization!</source>
+<target>Nema promjena od zadnje sinkronizacije!</target>
+
+<source>Filter settings have changed!</source>
+<target>Filterske postavke su promjenjene!</target>
+
+<source>The file was not processed by last synchronization!</source>
+<target>Datoteka nije procesirana tokom prošle sinkronizacije !</target>
+
+<source>Setting default synchronization directions: Old files will be overwritten with newer files.</source>
+<target>Postavljam zadani sinkronizacijski smijer: Stare datoteke će biti prepisane novim datotekama.</target>
+
+<source>The file does not contain a valid configuration:</source>
+<target>Datoteka ne sadrži ispravne postavke:</target>
+
+<source>You can ignore this error to consider the directory as empty.</source>
+<target>Možete ignorirati ovu grešku uzimajući datoteku kao praznu .</target>
+
+<source>Directory does not exist:</source>
+<target>Direktorij ne postoji:</target>
+
+<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
+<target>Direktoriji su u ovisnosti! Budite oprezni pri postavljanju sinkronizacijskih pravila:</target>
+
+<source>Memory allocation failed!</source>
+<target>Neuspješno dodjeljivanje memorije!</target>
+
+<source>File %x has an invalid date!</source>
+<target>Datoteka %x ima nevaljan datum!</target>
+
+<source>Conflict detected:</source>
+<target>Sukob pronađen:</target>
+
+<source>Files %x have the same date but a different size!</source>
+<target>Datoteke %x imaju isti datum ali drugačiju veličinu!</target>
+
+<source>Symlinks %x have the same date but a different target!</source>
+<target>Simbolične poveznice %x imaju isti datum ali drugačiji cilj!</target>
+
+<source>Comparing content of files %x</source>
+<target>Uspoređujem sadržaj datoteka %x</target>
+
+<source>Comparing files by content failed.</source>
+<target>Usporedba datoteka prema sadržaju nije uspjela.</target>
+
+<source>Generating file list...</source>
+<target>Generiram listu datoteka...</target>
+
+<source>Both sides are equal</source>
+<target>Obje strane su jednake</target>
+
+<source>Files/folders differ in attributes only</source>
+<target>Datoteke/mape se razlikuju samo u atributima</target>
+
+<source>Copy new file/folder to left</source>
+<target>Kopiraj novu datoteku/mapu na lijevo</target>
+
+<source>Copy new file/folder to right</source>
+<target>Kopiraj novu datoteku/mapu na desno</target>
+
+<source>Delete left file/folder</source>
+<target>Izbriši lijevu datoteku/mapu</target>
+
+<source>Delete right file/folder</source>
+<target>Izbriši desnu datoteku/mapu</target>
+
+<source>Move file on left</source>
+<target>Premjesti datoteku lijevo</target>
+
+<source>Move file on right</source>
+<target>Premjest datoteku desno</target>
+
+<source>Overwrite left file/folder with right one</source>
+<target>Prepiši lijevu datoteku/mapu s onom sa desne strane</target>
+
+<source>Overwrite right file/folder with left one</source>
+<target>Prepiši desnu datoteku/mapu s onom sa lijeve strane</target>
+
+<source>Do nothing</source>
+<target>Ne radi ništa</target>
+
+<source>Copy file attributes only to left</source>
+<target>Kopiraj atribute datoteke samo na levo</target>
+
+<source>Copy file attributes only to right</source>
+<target>Kopiraj atribute datoteke samo na desno</target>
+
+<source>Multiple...</source>
+<target>Mnogostruko...</target>
+
+<source>Deleting file %x</source>
+<target>Brisanje datoteke %x</target>
+
+<source>Deleting folder %x</source>
+<target>Brisanje mape %x</target>
+
+<source>Deleting symbolic link %x</source>
+<target>Brisanje simboličnih poveznica %x</target>
+
+<source>Moving file %x to recycle bin</source>
+<target>Premještam datoteku %x u Koš za smeće</target>
+
+<source>Moving folder %x to recycle bin</source>
+<target>Premještam mapu %x u Koš za smeće</target>
+
+<source>Moving symbolic link %x to recycle bin</source>
+<target>Premještam simboličnu poveznicu %x u Koš za smeće</target>
+
+<source>Moving file %x to %y</source>
+<target>Premještam datoteku %x u %y</target>
+
+<source>Moving folder %x to %y</source>
+<target>Premještam mapu %x u %y</target>
+
+<source>Moving symbolic link %x to %y</source>
+<target>Premještam simboličnu poveznicu %x u %y</target>
+
+<source>Creating file %x</source>
+<target>Izrađujem datoteku %x</target>
+
+<source>Creating symbolic link %x</source>
+<target>Izrađujem simboličnu poveznicu %x</target>
+
+<source>Creating folder %x</source>
+<target>Izrađujem mapu %x</target>
+
+<source>Overwriting file %x</source>
+<target>Prepisujem datoteku %x</target>
+
+<source>Overwriting symbolic link %x</source>
+<target>Prepisujem simboličnu poveznicu %x</target>
+
+<source>Verifying file %x</source>
+<target>Provjeravam datoteku %x</target>
+
+<source>Updating attributes of %x</source>
+<target>Obnavljam atribute od %x</target>
+
+<source>Target directory name must not be empty!</source>
+<target>Ime ciljnog direktorija ne smije biti prazno!</target>
+
+<source>User-defined directory for deletion was not specified!</source>
+<target>Korisnički definiran direktorij za brisanje nije definiran!</target>
+
+<source>Source directory does not exist anymore:</source>
+<target>Izvorni direktorij više ne postoji:</target>
+
+<source>Unresolved conflicts existing!</source>
+<target>Nerješivi sukob postoji!</target>
+
+<source>You can ignore conflicts and continue synchronization.</source>
+<target>Možete ignorirati sukob i nastaviti s sinkronizacijom.</target>
+
+<source>Significant difference detected:</source>
+<target>Značajna razlika opažena:</target>
+
+<source>More than 50% of the total number of files will be copied or deleted!</source>
+<target>Više od 50% od ukupnog broja datoteka će biti kopirano ili izbrisano!</target>
+
+<source>Not enough free disk space available in:</source>
+<target>Nedovoljno prostora na disku:</target>
+
+<source>Free disk space required:</source>
+<target>Potreban prostor na disku:</target>
+
+<source>Free disk space available:</source>
+<target>Prostor na disku dostupan:</target>
+
+<source>Recycle Bin is not available for the following paths! Files will be deleted permanently instead:</source>
+<target>Koš za smeće nije dostupan za navedene putanje! Umjesto toga datoteke će biti trajno izbrisane:</target>
+
+<source>A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!</source>
+<target>Direktorij će biti mjenjan koji je dio više parova mapa! Molimo pogledajte postavke sinkronizacije!</target>
+
+<source>Processing folder pair:</source>
+<target>Obrađujem parove mapa:</target>
+
+<source>Generating database...</source>
+<target>Izrađujem bazu podataka...</target>
+
+<source>Nothing to synchronize according to configuration!</source>
+<target>Po trenutnim postavkama nema ništa za sinkroniziranje!</target>
+
+<source>Error copying locked file %x!</source>
+<target>Greška pri kopiranju zaključane datoteke %x!</target>
+
+<source>Data verification error: Source and target file have different content!</source>
+<target>Greška pri provjeravanju podataka: Izvorna i ciljna datoteka imaju različit sadržaj!</target>
+
diff --git a/BUILD/Languages/czech.lng b/BUILD/Languages/czech.lng
index d3dd805e..fb72c119 100644
--- a/BUILD/Languages/czech.lng
+++ b/BUILD/Languages/czech.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Automatická synchronizace</target>
-<source>Browse</source>
-<target>Procházet</target>
-
-<source>Windows Error Code %x:</source>
-<target>Chybový kód Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Chybový kód Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Neplatný příkaz: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Chyba odkazu zástupce:</target>
-
-<source>Show pop-up</source>
-<target>Zobrazit okno</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Zobrazit hlášení při chybě nebo varování</target>
-
-<source>Ignore errors</source>
-<target>Přeskočit chyby</target>
-
-<source>Hide all error and warning messages</source>
-<target>Skrýt všechny chyby a varování</target>
-
-<source>Exit instantly</source>
-<target>Ukončit ihned</target>
-
-<source>Abort synchronization immediately</source>
-<target>Přerušit synchronizaci ihned</target>
-
<source>Select alternate comparison settings</source>
<target>Změnit nastavení porovnání</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Časové rozmezí</target>
+<source>Show pop-up</source>
+<target>Zobrazit okno</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Zobrazit hlášení při chybě nebo varování</target>
+
+<source>Ignore errors</source>
+<target>Přeskočit chyby</target>
+
+<source>Hide all error and warning messages</source>
+<target>Skrýt všechny chyby a varování</target>
+
+<source>Exit instantly</source>
+<target>Ukončit ihned</target>
+
+<source>Abort synchronization immediately</source>
+<target>Přerušit synchronizaci ihned</target>
+
+<source>Browse</source>
+<target>Procházet</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Chyba čtení synchronizační databáze:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Chyba zápisu synchronizační databáze:</target>
+
+<source>Invalid command line: %x</source>
+<target>Neplatný příkaz: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Chybový kód Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Chybový kód Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Chyba odkazu zástupce:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -164,17 +170,14 @@
<source>Comparison Result</source>
<target>Výsledek porovnání</target>
-<source>Incompatible synchronization database format:</source>
-<target>Chyba formátu synchronizační databáze:</target>
-
<source>Initial synchronization:</source>
<target>Prvotní synchronizace:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Některý z databázových souborů FreeFileSync neexistuje:</target>
-<source>Error reading from synchronization database:</source>
-<target>Chyba čtení synchronizační databáze:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Chyba formátu synchronizační databáze:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Databázové soubory nejsou navzájem komplementární</target>
@@ -201,12 +204,18 @@
<pluralform>%x sekund</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Drag && Drop</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Závažná chyba</target>
+<source>Error reading file:</source>
+<target>Chyba čtení souboru:</target>
+
<source>Scanning:</source>
<target>Zpracováváno:</target>
@@ -226,15 +235,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Chybný konfigurační soubor FreeFileSync!</target>
-<source>File does not exist:</source>
-<target>Soubor neexistuje:</target>
-
<source>Error parsing configuration file:</source>
<target>Chyba zpracování konfigurace:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Chyba přesunu do Koše:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Nelze načíst požadovanou knihovnu DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Chyba přístupu ke službě Volume Shadow Copy Service!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Vytváření stínových kopií na WOW64 není podporováno. Prosím použijte 64 bitovou verzi FreeFileSync.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Není možné zjistit jméno jednotky souboru:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Disk %x není součástí jména souboru %y!</target>
+
<source>/sec</source>
<target>/s</target>
+<source>File does not exist:</source>
+<target>Soubor neexistuje:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Nelze načíst hodnoty následujících XML elementy:</target>
+
<source>S&ave configuration...</source>
<target>&Uložení konfigurace...</target>
@@ -327,144 +357,6 @@ Příkazová řádka je spuštěna pokaždé když:
<source>A directory input field is empty.</source>
<target>Není zadán vstupní adresář.</target>
-<source>Drag && drop</source>
-<target>Drag && Drop</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Nelze nastavit monitorování adresáře:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Chyba při sledování adresářů.</target>
-
-<source>Conversion error:</source>
-<target>Chyba konverze:</target>
-
-<source>Error deleting file:</source>
-<target>Chyba mazání souboru:</target>
-
-<source>Error moving file:</source>
-<target>Chyba přesouvání souboru:</target>
-
-<source>Target file already existing!</source>
-<target>Cílový soubor již existuje!</target>
-
-<source>Error moving directory:</source>
-<target>Chyba přesouvání adresáře:</target>
-
-<source>Target directory already existing!</source>
-<target>Cílový adresář již existuje!</target>
-
-<source>Error deleting directory:</source>
-<target>Chyba mazání adresáře:</target>
-
-<source>Error changing modification time:</source>
-<target>Chyba nastavení času změny:</target>
-
-<source>Error loading library function:</source>
-<target>Chyba načtení knihovny funkcí:</target>
-
-<source>Error reading security context:</source>
-<target>Chyba při čtení přístupových práv:</target>
-
-<source>Error writing security context:</source>
-<target>Chyba při zápisu přístupových práv:</target>
-
-<source>Error copying file permissions:</source>
-<target>Chyba kopírování oprávnění souborů:</target>
-
-<source>Error creating directory:</source>
-<target>Chyba vytvoření adresáře:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Chyba kopírování zástupce:</target>
-
-<source>Error copying file:</source>
-<target>Chyba kopírování souboru:</target>
-
-<source>Error opening file:</source>
-<target>Chyba otevření souboru:</target>
-
-<source>Error writing file:</source>
-<target>Chyba zápisu souboru:</target>
-
-<source>Error reading file:</source>
-<target>Chyba čtení souboru:</target>
-
-<source>Operation aborted!</source>
-<target>Operace zrušena!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Zacyklení při procházení adresáře:</target>
-
-<source>Error traversing directory:</source>
-<target>Chyba procházení adresáře:</target>
-
-<source>Error setting privilege:</source>
-<target>Chyba nastavení práv:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Chyba přesunu do Koše:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Nelze načíst požadovanou knihovnu DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Chyba zápisu synchronizační databáze:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Chyba přístupu ke službě Volume Shadow Copy Service!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Vytváření stínových kopií na WOW64 není podporováno. Prosím použijte 64 bitovou verzi FreeFileSync.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Není možné zjistit jméno jednotky souboru:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Disk %x není součástí jména souboru %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 minuta</pluralform>
-<pluralform>%x minuty</pluralform>
-<pluralform>%x minut</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 hodina</pluralform>
-<pluralform>%x hodiny</pluralform>
-<pluralform>%x hodin</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 den</pluralform>
-<pluralform>%x dny</pluralform>
-<pluralform>%x dnů</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Nelze načíst hodnoty následujících XML elementy:</target>
-
<source>Logging</source>
<target>Zaznamenávání</target>
@@ -483,9 +375,6 @@ Příkazová řádka je spuštěna pokaždé když:
<source>Batch execution</source>
<target>Spuštění dávky</target>
-<source>Log-messages:</source>
-<target>Záznamy:</target>
-
<source>Stop</source>
<target>Stop</target>
@@ -612,6 +501,24 @@ Příkazová řádka je spuštěna pokaždé když:
<source>Total amount of data that will be transferred</source>
<target>Celkový objem dat, který bude přenesen</target>
+<source>Operation:</source>
+<target>Operace:</target>
+
+<source>Items found:</source>
+<target>Nalezeno položek:</target>
+
+<source>Items remaining:</source>
+<target>Zbývá položek:</target>
+
+<source>Speed:</source>
+<target>Rychlost:</target>
+
+<source>Time remaining:</source>
+<target>Zbývající čas:</target>
+
+<source>Time elapsed:</source>
+<target>Uplynulý čas:</target>
+
<source>Batch job</source>
<target>Dávkový soubor</target>
@@ -660,32 +567,14 @@ Příkazová řádka je spuštěna pokaždé když:
<source>&Cancel</source>
<target>&Zrušit</target>
-<source>Operation:</source>
-<target>Operace:</target>
-
-<source>Items found:</source>
-<target>Nalezeno položek:</target>
-
-<source>Items remaining:</source>
-<target>Zbývá položek:</target>
-
-<source>Speed:</source>
-<target>Rychlost:</target>
-
-<source>Time remaining:</source>
-<target>Zbývající čas:</target>
-
-<source>Time elapsed:</source>
-<target>Uplynulý čas:</target>
-
<source>Select variant:</source>
<target>Vyberte variantu:</target>
<source><Automatic></source>
<target><- Automaticky -></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Rozpoznat a provést změny na obou stranách pomocí databáze. Odstraněné soubory a konflikty budou detekovány automaticky.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Rozpoznat a provést změny na obou stranách pomocí databáze. Odstraněné nebo přejmenované soubory a konflikty budou detekovány automaticky.</target>
<source>Mirror ->></source>
<target>Zrcadlení ->></target>
@@ -907,27 +796,19 @@ Vynechat: \někde\něco\*
<target>Bezpečné kopírování souborů</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Kopíruje data nejprve do pomocného souboru (*.ffs_tmp) a poté teprve soubor přejmenuje. Tento postup zajišťuje bezpečné chování i v případě chyby během přenosu</target>
<source>Copy locked files</source>
<target>Kopírovat zamčené soubory</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Kopírovat sdílené nebo zamčené soubory pomocí Volume Shadow Copy Service (Vyžaduje administrátorské oprávnění)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopírovat sdílené nebo zamčené soubory pomocí Volume Shadow Copy Service (Vyžaduje administrátorské oprávnění)</target>
<source>Copy file access permissions</source>
<target>Kopírovat přístupová oprávnění k souborům</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administrátorké oprávnění)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administrátorké oprávnění)</target>
<source>Hidden dialogs:</source>
<target>Skryté dialogy:</target>
@@ -959,6 +840,9 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>&Find next</source>
<target>&Najít další</target>
+<source>Operation aborted!</source>
+<target>Operace zrušena!</target>
+
<source>Main bar</source>
<target>Hlavní lišta</target>
@@ -999,16 +883,16 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<target>Automaticky přizpůsobit šířku</target>
<source>Icon size:</source>
-<target></target>
+<target>Velikost ikon:</target>
<source>Small</source>
-<target></target>
+<target>Malé</target>
<source>Medium</source>
-<target></target>
+<target>Střední</target>
<source>Large</source>
-<target></target>
+<target>Velké</target>
<source>Include all rows</source>
<target>Použít všechny řádky</target>
@@ -1136,6 +1020,9 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>File list exported!</source>
<target>Seznam souborů exportován!</target>
+<source>Error writing file:</source>
+<target>Chyba zápisu souboru:</target>
+
<source>Batch file created successfully!</source>
<target>Dávka úspěšně vytvořena!</target>
@@ -1239,9 +1126,6 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>Filter: Single pair</source>
<target>Filtr: Jeden pár</target>
-<source>Ignore</source>
-<target>Přeskočit</target>
-
<source>Direct</source>
<target>Zachovat</target>
@@ -1307,6 +1191,108 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>Move files into a time-stamped subdirectory</source>
<target>Přesunout soubory do časově označeného podadresáře</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 minuta</pluralform>
+<pluralform>%x minuty</pluralform>
+<pluralform>%x minut</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 hodina</pluralform>
+<pluralform>%x hodiny</pluralform>
+<pluralform>%x hodin</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 den</pluralform>
+<pluralform>%x dny</pluralform>
+<pluralform>%x dnů</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Nelze nastavit monitorování adresáře:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Chyba při sledování adresářů.</target>
+
+<source>Conversion error:</source>
+<target>Chyba konverze:</target>
+
+<source>Error deleting file:</source>
+<target>Chyba mazání souboru:</target>
+
+<source>Error moving file:</source>
+<target>Chyba přesouvání souboru:</target>
+
+<source>Target file already existing!</source>
+<target>Cílový soubor již existuje!</target>
+
+<source>Error moving directory:</source>
+<target>Chyba přesouvání adresáře:</target>
+
+<source>Target directory already existing!</source>
+<target>Cílový adresář již existuje!</target>
+
+<source>Error deleting directory:</source>
+<target>Chyba mazání adresáře:</target>
+
+<source>Error changing modification time:</source>
+<target>Chyba nastavení času změny:</target>
+
+<source>Error loading library function:</source>
+<target>Chyba načtení knihovny funkcí:</target>
+
+<source>Error reading security context:</source>
+<target>Chyba při čtení přístupových práv:</target>
+
+<source>Error writing security context:</source>
+<target>Chyba při zápisu přístupových práv:</target>
+
+<source>Error copying file permissions:</source>
+<target>Chyba kopírování oprávnění souborů:</target>
+
+<source>Error creating directory:</source>
+<target>Chyba vytvoření adresáře:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Chyba kopírování zástupce:</target>
+
+<source>Error copying file:</source>
+<target>Chyba kopírování souboru:</target>
+
+<source>Error opening file:</source>
+<target>Chyba otevření souboru:</target>
+
+<source>Error traversing directory:</source>
+<target>Chyba procházení adresáře:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Zacyklení při procházení adresáře:</target>
+
+<source>Error setting privilege:</source>
+<target>Chyba nastavení práv:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Došlo ke změně obou stran od poslední synchronizace!</target>
@@ -1337,9 +1323,6 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Adresáře jsou závislé! Buďte opatrní s definicí synchronizačních pravidel:</target>
-<source>Comparing content of files %x</source>
-<target>Porovnávání obsahu souborů %x</target>
-
<source>Memory allocation failed!</source>
<target>Chyba přidělení paměti!</target>
@@ -1355,15 +1338,15 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>Symlinks %x have the same date but a different target!</source>
<target>Symbolický odkaz %x má stejné datum ale jiný cíl!</target>
+<source>Comparing content of files %x</source>
+<target>Porovnávání obsahu souborů %x</target>
+
<source>Comparing files by content failed.</source>
<target>Porovnání obsahu souborů se nezdařilo.</target>
<source>Generating file list...</source>
<target>Vytváření seznamu souborů...</target>
-<source>Multiple...</source>
-<target>Různé...</target>
-
<source>Both sides are equal</source>
<target>Obě strany jsou shodné</target>
@@ -1382,6 +1365,12 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>Delete right file/folder</source>
<target>Smazat soubor/adresáře z prava</target>
+<source>Move file on left</source>
+<target>Přesunout soubor nalevo</target>
+
+<source>Move file on right</source>
+<target>Přesunout soubor napravo</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Přepsat levý soubor/adresář tím z prava</target>
@@ -1397,6 +1386,9 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr
<source>Copy file attributes only to right</source>
<target>Kopírovat vlastnosti souboru pouze do prava</target>
+<source>Multiple...</source>
+<target>Různé...</target>
+
<source>Deleting file %x</source>
<target>Mazání souboru %x</target>
diff --git a/BUILD/Languages/danish.lng b/BUILD/Languages/danish.lng
index d13de994..cc3d8536 100644
--- a/BUILD/Languages/danish.lng
+++ b/BUILD/Languages/danish.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSynk - Automatisk Synkronisering</target>
-<source>Browse</source>
-<target>Gennemse</target>
-
-<source>Windows Error Code %x:</source>
-<target>Windows Fejl kode %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Linux Fejl kode %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Ugyldig kommando: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Fejl i at finde link:</target>
-
-<source>Show pop-up</source>
-<target>Vis pop-up</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Vis pop-up ved fejl eller advarsler</target>
-
-<source>Ignore errors</source>
-<target>Ignorer fejl</target>
-
-<source>Hide all error and warning messages</source>
-<target>Skjul beskeder om fejl og advarsler</target>
-
-<source>Exit instantly</source>
-<target>Afslut med det samme</target>
-
-<source>Abort synchronization immediately</source>
-<target>Abort synkronisering med det samme</target>
-
<source>Select alternate comparison settings</source>
<target>Vælg alternative sammenlignings indstillinger</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Vælg tids område</target>
+<source>Show pop-up</source>
+<target>Vis pop-up</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Vis pop-up ved fejl eller advarsler</target>
+
+<source>Ignore errors</source>
+<target>Ignorer fejl</target>
+
+<source>Hide all error and warning messages</source>
+<target>Skjul beskeder om fejl og advarsler</target>
+
+<source>Exit instantly</source>
+<target>Afslut med det samme</target>
+
+<source>Abort synchronization immediately</source>
+<target>Abort synkronisering med det samme</target>
+
+<source>Browse</source>
+<target>Gennemse</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Fejl i læsning fra synkroniserings databasen:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Fejl i skrivning til synkroniserings databasen:</target>
+
+<source>Invalid command line: %x</source>
+<target>Ugyldig kommando: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows Fejl kode %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux Fejl kode %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Fejl i at finde link:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Sammenlignings Resultat</target>
-<source>Incompatible synchronization database format:</source>
-<target>Ukompatibelt synkroniserings database format:</target>
-
<source>Initial synchronization:</source>
<target>Indledende synkronisering:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>En af FreeFileSync database filerne findes ikke endnu:</target>
-<source>Error reading from synchronization database:</source>
-<target>Fejl i læsning fra synkroniserings databasen:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Ukompatibelt synkroniserings database format:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Database filer deler ikke en fælles synkroniserings session</target>
@@ -199,12 +202,18 @@
<pluralform>%x sek</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Træk && slip</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Uoprettelig Fejl</target>
+<source>Error reading file:</source>
+<target>Fejl i læsning af fil:</target>
+
<source>Scanning:</source>
<target>Skanner:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Ugyldig FreeFileSync config fil!</target>
-<source>File does not exist:</source>
-<target>Filen findes ikke:</target>
-
<source>Error parsing configuration file:</source>
<target>Fejl i at lave konfigurations filen:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Fejl i at flytte til skraldespand:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Kunne ikke hente en krævet DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Fejl i adgang til Enhedens Kopi Service</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>At lave spejl kopier af WOW64 er ikke understøttet. Brug venligst FreeFileSync 64-bit version.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Kunne ikke finde drev navn til filen:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Drev navn %x ikke en del af filnavn %y!</target>
+
<source>/sec</source>
<target>/sek</target>
+<source>File does not exist:</source>
+<target>Filen findes ikke:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Kunne ikke læse værdierne for følgende XML punkter:</target>
+
<source>S&ave configuration...</source>
<target>G&em konfiguration...</target>
@@ -324,141 +354,6 @@ Kommando linjen bliver afviklet hver gang:
<source>A directory input field is empty.</source>
<target>Et biblioteks felt er tomt.</target>
-<source>Drag && drop</source>
-<target>Træk && slip</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Kunne ikke initialiserer biblioteks overvågningen:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Fejl i overvågning af biblioteker.</target>
-
-<source>Conversion error:</source>
-<target>Konverterings fejl:</target>
-
-<source>Error deleting file:</source>
-<target>Fejl i sletning af fil:</target>
-
-<source>Error moving file:</source>
-<target>Fejl i flytning af fil:</target>
-
-<source>Target file already existing!</source>
-<target>Filen findes i forvejen!</target>
-
-<source>Error moving directory:</source>
-<target>Fejl i flytning af bibliotek:</target>
-
-<source>Target directory already existing!</source>
-<target>Bibliotek findes i forvejen!</target>
-
-<source>Error deleting directory:</source>
-<target>Fejl i sletning af bibliotek:</target>
-
-<source>Error changing modification time:</source>
-<target>Fejl i ændring af modificerings tiden:</target>
-
-<source>Error loading library function:</source>
-<target>Fejl i biblioteks funktionen:</target>
-
-<source>Error reading security context:</source>
-<target>Fejl i læsning af sikkerhedstilladelser:</target>
-
-<source>Error writing security context:</source>
-<target>Fejl i skrivning af sikkerhedstilladelser:</target>
-
-<source>Error copying file permissions:</source>
-<target>Fejl i kopiering af filtilladelser:</target>
-
-<source>Error creating directory:</source>
-<target>Fejl i oprettelse af bibliotek:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Fejl i kopiering af link:</target>
-
-<source>Error copying file:</source>
-<target>Fejl i kopiering af fil:</target>
-
-<source>Error opening file:</source>
-<target>Fejl i åbning af fil:</target>
-
-<source>Error writing file:</source>
-<target>Fejl i at skrive fil:</target>
-
-<source>Error reading file:</source>
-<target>Fejl i læsning af fil:</target>
-
-<source>Operation aborted!</source>
-<target>Operation afbrudt!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Uendelig løkke ved gennemgang af bibliotek:</target>
-
-<source>Error traversing directory:</source>
-<target>Fejl i gennemgang af bibliotek:</target>
-
-<source>Error setting privilege:</source>
-<target>Fejl i at sætte privilegier:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Fejl i at flytte til skraldespand:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Kunne ikke hente en krævet DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Fejl i skrivning til synkroniserings databasen:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Fejl i adgang til Enhedens Kopi Service</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>At lave spejl kopier af WOW64 er ikke understøttet. Brug venligst FreeFileSync 64-bit version.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Kunne ikke finde drev navn til filen:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Drev navn %x ikke en del af filnavn %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 timer</pluralform>
-<pluralform>%x timer</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 dag</pluralform>
-<pluralform>%x dage</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Kunne ikke læse værdierne for følgende XML punkter:</target>
-
<source>Logging</source>
<target>Logger</target>
@@ -477,9 +372,6 @@ Kommando linjen bliver afviklet hver gang:
<source>Batch execution</source>
<target>Batch afvikling</target>
-<source>Log-messages:</source>
-<target>Log-beskeder:</target>
-
<source>Stop</source>
<target>Stop</target>
@@ -606,6 +498,24 @@ Kommando linjen bliver afviklet hver gang:
<source>Total amount of data that will be transferred</source>
<target>Samlet antal data der vil blive overført</target>
+<source>Operation:</source>
+<target>Igang:</target>
+
+<source>Items found:</source>
+<target>Enheder fundet:</target>
+
+<source>Items remaining:</source>
+<target>Enheder tilbage:</target>
+
+<source>Speed:</source>
+<target>Hastighed:</target>
+
+<source>Time remaining:</source>
+<target>Tid tilbage:</target>
+
+<source>Time elapsed:</source>
+<target>Tid gået:</target>
+
<source>Batch job</source>
<target>Batch job</target>
@@ -654,32 +564,14 @@ Kommando linjen bliver afviklet hver gang:
<source>&Cancel</source>
<target>&Anuller</target>
-<source>Operation:</source>
-<target>Igang:</target>
-
-<source>Items found:</source>
-<target>Enheder fundet:</target>
-
-<source>Items remaining:</source>
-<target>Enheder tilbage:</target>
-
-<source>Speed:</source>
-<target>Hastighed:</target>
-
-<source>Time remaining:</source>
-<target>Tid tilbage:</target>
-
-<source>Time elapsed:</source>
-<target>Tid gået:</target>
-
<source>Select variant:</source>
<target>Vælg variant:</target>
<source><Automatic></source>
<target><Automatisk></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Indentifiser og udbred ændringer på begge sider via. database. Sletninger og konflikter opdages automatisk.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>find ændringer på begge sider via. database. Sletninger, omdøbninger og konflikter bliver automatisk fundet.</target>
<source>Mirror ->></source>
<target>Spejl ->></target>
@@ -901,27 +793,19 @@ Udeluk: \ting\temp\*
<target>Transaktionel fil kopiering</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Skriv til en midlertidig fil (*.ffs_tmp) først så omdøb den. Dette garanterer sikkerheden selv ved en kritisk fejl.</target>
<source>Copy locked files</source>
<target>Kopier låste filer</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Kopier delte eller låste filer ved hjælp af Drev Kopi Servicen (Kræver Administrator rettigheder)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopier delte eller låste filer ved hjælp af Drev Kopi Servicen (Kræver Administrator rettigheder)</target>
<source>Copy file access permissions</source>
<target>Kopier fil adgangs tilladelser</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)</target>
<source>Hidden dialogs:</source>
<target>Skjulte dialoger:</target>
@@ -953,6 +837,9 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>&Find next</source>
<target>&Find næste</target>
+<source>Operation aborted!</source>
+<target>Operation afbrudt!</target>
+
<source>Main bar</source>
<target>Hoved værktøjslinjen</target>
@@ -993,16 +880,16 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<target>Auto-juster kolonner</target>
<source>Icon size:</source>
-<target></target>
+<target>Ikon størrelse:</target>
<source>Small</source>
-<target></target>
+<target>Lille</target>
<source>Medium</source>
-<target></target>
+<target>Mellem</target>
<source>Large</source>
-<target></target>
+<target>Stor</target>
<source>Include all rows</source>
<target>Inkluder alle rækker</target>
@@ -1130,6 +1017,9 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>File list exported!</source>
<target>Fil listen er eksporteret!</target>
+<source>Error writing file:</source>
+<target>Fejl i at skrive fil:</target>
+
<source>Batch file created successfully!</source>
<target>Batch fil oprettet!</target>
@@ -1229,9 +1119,6 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>Filter: Single pair</source>
<target>Filter: Par</target>
-<source>Ignore</source>
-<target>Ignorer</target>
-
<source>Direct</source>
<target>Direkte</target>
@@ -1295,6 +1182,105 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>Move files into a time-stamped subdirectory</source>
<target>Flyt filer til et datomærket underbibliotek</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 timer</pluralform>
+<pluralform>%x timer</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 dag</pluralform>
+<pluralform>%x dage</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Kunne ikke initialiserer biblioteks overvågningen:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Fejl i overvågning af biblioteker.</target>
+
+<source>Conversion error:</source>
+<target>Konverterings fejl:</target>
+
+<source>Error deleting file:</source>
+<target>Fejl i sletning af fil:</target>
+
+<source>Error moving file:</source>
+<target>Fejl i flytning af fil:</target>
+
+<source>Target file already existing!</source>
+<target>Filen findes i forvejen!</target>
+
+<source>Error moving directory:</source>
+<target>Fejl i flytning af bibliotek:</target>
+
+<source>Target directory already existing!</source>
+<target>Bibliotek findes i forvejen!</target>
+
+<source>Error deleting directory:</source>
+<target>Fejl i sletning af bibliotek:</target>
+
+<source>Error changing modification time:</source>
+<target>Fejl i ændring af modificerings tiden:</target>
+
+<source>Error loading library function:</source>
+<target>Fejl i biblioteks funktionen:</target>
+
+<source>Error reading security context:</source>
+<target>Fejl i læsning af sikkerhedstilladelser:</target>
+
+<source>Error writing security context:</source>
+<target>Fejl i skrivning af sikkerhedstilladelser:</target>
+
+<source>Error copying file permissions:</source>
+<target>Fejl i kopiering af filtilladelser:</target>
+
+<source>Error creating directory:</source>
+<target>Fejl i oprettelse af bibliotek:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Fejl i kopiering af link:</target>
+
+<source>Error copying file:</source>
+<target>Fejl i kopiering af fil:</target>
+
+<source>Error opening file:</source>
+<target>Fejl i åbning af fil:</target>
+
+<source>Error traversing directory:</source>
+<target>Fejl i gennemgang af bibliotek:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Uendelig løkke ved gennemgang af bibliotek:</target>
+
+<source>Error setting privilege:</source>
+<target>Fejl i at sætte privilegier:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Begge sider er ændret siden sidste synkronisering!</target>
@@ -1325,9 +1311,6 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Biblioteker er afhængige! Vær forsigtig når du laver synkroniserings reglerne:</target>
-<source>Comparing content of files %x</source>
-<target>Sammenligner indhold af filer %x</target>
-
<source>Memory allocation failed!</source>
<target>Hukommelses fejl!</target>
@@ -1343,15 +1326,15 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>Symlinks %x have the same date but a different target!</source>
<target>Links %x har den samme dato men forskellige destinationerl!</target>
+<source>Comparing content of files %x</source>
+<target>Sammenligner indhold af filer %x</target>
+
<source>Comparing files by content failed.</source>
<target>Fejl i sammenligning af filernes indhold.</target>
<source>Generating file list...</source>
<target>Laver fil liste...</target>
-<source>Multiple...</source>
-<target>Flere...</target>
-
<source>Both sides are equal</source>
<target>Begge sider er ens</target>
@@ -1370,6 +1353,12 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>Delete right file/folder</source>
<target>Slet højre fil/mappe</target>
+<source>Move file on left</source>
+<target>Flyt filen til venstre</target>
+
+<source>Move file on right</source>
+<target>flyt filen til højre</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Overskriv venstre fil/mappe med højre</target>
@@ -1385,6 +1374,9 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)
<source>Copy file attributes only to right</source>
<target>Kopiere fil attributter kun til højre</target>
+<source>Multiple...</source>
+<target>Flere...</target>
+
<source>Deleting file %x</source>
<target>Sletter fil %x</target>
diff --git a/BUILD/Languages/dutch.lng b/BUILD/Languages/dutch.lng
index 17519715..8c9d8a33 100644
--- a/BUILD/Languages/dutch.lng
+++ b/BUILD/Languages/dutch.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Geautomatiseerde Synchronisatie</target>
-<source>Browse</source>
-<target>Verkennen</target>
-
-<source>Windows Error Code %x:</source>
-<target>Windows Fout Code %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Linux Fout Code %x:</target>
-
-<source>Invalid command line: %x</source>
-<target></target>
-
-<source>Error resolving symbolic link:</source>
-<target>Fout tijdens opzoeken van symbolische koppeling:</target>
-
-<source>Show pop-up</source>
-<target></target>
-
-<source>Show pop-up on errors or warnings</source>
-<target></target>
-
-<source>Ignore errors</source>
-<target>Negeer foutmeldingen</target>
-
-<source>Hide all error and warning messages</source>
-<target>Verberg alle fout- en waarschuwingsberichten</target>
-
-<source>Exit instantly</source>
-<target>Sluit meteen af</target>
-
-<source>Abort synchronization immediately</source>
-<target>Stop synchronisatie onmiddelijk</target>
-
<source>Select alternate comparison settings</source>
<target></target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target></target>
+<source>Show pop-up</source>
+<target></target>
+
+<source>Show pop-up on errors or warnings</source>
+<target></target>
+
+<source>Ignore errors</source>
+<target>Negeer foutmeldingen</target>
+
+<source>Hide all error and warning messages</source>
+<target>Verberg alle fout- en waarschuwingsberichten</target>
+
+<source>Exit instantly</source>
+<target>Sluit meteen af</target>
+
+<source>Abort synchronization immediately</source>
+<target>Stop synchronisatie onmiddelijk</target>
+
+<source>Browse</source>
+<target>Verkennen</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Fout tijdens uitlezen van synchronisatie-database:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Fout tijdens schrijven naar synchronisatie-database:</target>
+
+<source>Invalid command line: %x</source>
+<target></target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows Fout Code %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux Fout Code %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Fout tijdens opzoeken van symbolische koppeling:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Resultaat vergelijken</target>
-<source>Incompatible synchronization database format:</source>
-<target>Opmaak van synchronisatie-database komt niet overeen:</target>
-
<source>Initial synchronization:</source>
<target>Initiële synchronisatie:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Eén van de FreeFileSync database bestanden bestaat nog niet:</target>
-<source>Error reading from synchronization database:</source>
-<target>Fout tijdens uitlezen van synchronisatie-database:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Opmaak van synchronisatie-database komt niet overeen:</target>
<source>Database files do not share a common synchronization session:</source>
<target></target>
@@ -199,12 +202,18 @@
<pluralform>%x sec</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Drag en drop</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Fatale fout</target>
+<source>Error reading file:</source>
+<target>Fout tijdens lezen van bestand:</target>
+
<source>Scanning:</source>
<target>Doorzoekt:</target>
@@ -220,15 +229,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Foutief FreeFileSync configuratiebestand!</target>
-<source>File does not exist:</source>
-<target>Bestand bestaat niet:</target>
-
<source>Error parsing configuration file:</source>
<target>Fout tijdens verwerking configuratiebestand:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Fout tijdens verplaatsen naar prullenbak:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Kon een benodigde DLL niet laden:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target></target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Het aanmaken van schaduwkopieën op WOW64 wordt niet ondersteund. Gebruik alstublieft de 64-bit versie van FreeFileSync.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Kon de schijfnaam niet vaststellen van bestand:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Schijfnaam %x maakt geen deel uit van bestandsnaam %y!</target>
+
<source>/sec</source>
<target>/sec</target>
+<source>File does not exist:</source>
+<target>Bestand bestaat niet:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Kon geen waarden inlezen voor de volgende XML punten:</target>
+
<source>S&ave configuration...</source>
<target>Sl&a configuratie op...</target>
@@ -321,141 +351,6 @@ De opdrachtregel wordt telkens uitgevoerd indien:
<source>A directory input field is empty.</source>
<target>Een tekstveld over de map is leeg.</target>
-<source>Drag && drop</source>
-<target>Drag en drop</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Initaliseren van map-observatie niet mogelijk:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Fout tijdens observeren van mappen.</target>
-
-<source>Conversion error:</source>
-<target>Converteer fout:</target>
-
-<source>Error deleting file:</source>
-<target>Fout tijdens verwijderen van bestand:</target>
-
-<source>Error moving file:</source>
-<target>Fout tijdens verplaatsen van bestand:</target>
-
-<source>Target file already existing!</source>
-<target>Doelbestand bestaat al!</target>
-
-<source>Error moving directory:</source>
-<target>Fout tijdens verplaatsen van map:</target>
-
-<source>Target directory already existing!</source>
-<target>Doelmap bestaat al!</target>
-
-<source>Error deleting directory:</source>
-<target>Fout tijdens het verwijderen van map:</target>
-
-<source>Error changing modification time:</source>
-<target>Fout tijdens aanpassing van de wijzigingstijd:</target>
-
-<source>Error loading library function:</source>
-<target>Fout tijdens laden van bibliotheek functie:</target>
-
-<source>Error reading security context:</source>
-<target>Fout tijdens lezen van beveiligingscontext:</target>
-
-<source>Error writing security context:</source>
-<target>Fout tijdens schrijven van beveiligingscontext:</target>
-
-<source>Error copying file permissions:</source>
-<target>Fout tijdens kopiëren van bestandspermissies:</target>
-
-<source>Error creating directory:</source>
-<target>Fout tijdens het aanmaken van map:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Fout tijdens kopiëren van symbolische koppeling:</target>
-
-<source>Error copying file:</source>
-<target>Fout tijdens kopiëren van bestand:</target>
-
-<source>Error opening file:</source>
-<target>Fout tijdens openen van bestand:</target>
-
-<source>Error writing file:</source>
-<target>Fout tijdens schrijven van bestand:</target>
-
-<source>Error reading file:</source>
-<target>Fout tijdens lezen van bestand:</target>
-
-<source>Operation aborted!</source>
-<target>Bewerking afgebroken!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Oneindige lus bij het doorlopen van map:</target>
-
-<source>Error traversing directory:</source>
-<target>Fout tijdens doorzoeken van map:</target>
-
-<source>Error setting privilege:</source>
-<target>Fout tijdens instellen van privileges:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Fout tijdens verplaatsen naar prullenbak:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Kon een benodigde DLL niet laden:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Fout tijdens schrijven naar synchronisatie-database:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target></target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Het aanmaken van schaduwkopieën op WOW64 wordt niet ondersteund. Gebruik alstublieft de 64-bit versie van FreeFileSync.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Kon de schijfnaam niet vaststellen van bestand:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Schijfnaam %x maakt geen deel uit van bestandsnaam %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 uur</pluralform>
-<pluralform>%x uren</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 dag</pluralform>
-<pluralform>%x dagen</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Kon geen waarden inlezen voor de volgende XML punten:</target>
-
<source>Logging</source>
<target>Loggen</target>
@@ -474,9 +369,6 @@ De opdrachtregel wordt telkens uitgevoerd indien:
<source>Batch execution</source>
<target>Taak uitvoeren</target>
-<source>Log-messages:</source>
-<target>Logberichten:</target>
-
<source>Stop</source>
<target>Stop</target>
@@ -603,6 +495,24 @@ De opdrachtregel wordt telkens uitgevoerd indien:
<source>Total amount of data that will be transferred</source>
<target>Totale hoeveelheid data die verplaatst wordt</target>
+<source>Operation:</source>
+<target>Bewerking:</target>
+
+<source>Items found:</source>
+<target>Onderdelen gevonden:</target>
+
+<source>Items remaining:</source>
+<target>Onderdelen te gaan:</target>
+
+<source>Speed:</source>
+<target>Snelheid:</target>
+
+<source>Time remaining:</source>
+<target>Benodigde tijd:</target>
+
+<source>Time elapsed:</source>
+<target>Verstreken tijd:</target>
+
<source>Batch job</source>
<target>Taaklijst</target>
@@ -651,32 +561,14 @@ De opdrachtregel wordt telkens uitgevoerd indien:
<source>&Cancel</source>
<target>&Annuleren</target>
-<source>Operation:</source>
-<target>Bewerking:</target>
-
-<source>Items found:</source>
-<target>Onderdelen gevonden:</target>
-
-<source>Items remaining:</source>
-<target>Onderdelen te gaan:</target>
-
-<source>Speed:</source>
-<target>Snelheid:</target>
-
-<source>Time remaining:</source>
-<target>Benodigde tijd:</target>
-
-<source>Time elapsed:</source>
-<target>Verstreken tijd:</target>
-
<source>Select variant:</source>
<target>Selecteer een variant:</target>
<source><Automatic></source>
<target><Automatisch></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identificeer en verwerk veranderingen aan beide zijdes dmv een database. Verwijderingen en conflicten worden automatisch gedetecteerd.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target></target>
<source>Mirror ->></source>
<target>Spiegelen ->></target>
@@ -898,22 +790,14 @@ Uitsluiten: \stuff\temp\*
<source>Copy locked files</source>
<target>Kopieer vergrendelde bestanden</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Kopieer gedeelde of vergrendelde bestanden met Volume Shadow Copy Service (Vereist Administrator rechten)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopieer gedeelde of vergrendelde bestanden met Volume Shadow Copy Service (Vereist Administrator rechten)</target>
<source>Copy file access permissions</source>
<target></target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Zet bestand en map permissies over (Vereist Administrator rechten)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Zet bestand en map permissies over (Vereist Administrator rechten)</target>
<source>Hidden dialogs:</source>
<target>Verborgen dialogen:</target>
@@ -945,6 +829,9 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>&Find next</source>
<target>&Vind volgende</target>
+<source>Operation aborted!</source>
+<target>Bewerking afgebroken!</target>
+
<source>Main bar</source>
<target>Hoofdbalk</target>
@@ -1122,6 +1009,9 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>File list exported!</source>
<target>Bestandslijst geëxporteerd!</target>
+<source>Error writing file:</source>
+<target>Fout tijdens schrijven van bestand:</target>
+
<source>Batch file created successfully!</source>
<target>Taakbestand is succesvol aangemaakt!</target>
@@ -1221,9 +1111,6 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>Filter: Single pair</source>
<target>Filter: Enkel paar</target>
-<source>Ignore</source>
-<target>Negeer</target>
-
<source>Direct</source>
<target>Direct</target>
@@ -1287,6 +1174,105 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>Move files into a time-stamped subdirectory</source>
<target>Verplaats de bestanden naar een tijd-gemarkeerde submap</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 uur</pluralform>
+<pluralform>%x uren</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 dag</pluralform>
+<pluralform>%x dagen</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Initaliseren van map-observatie niet mogelijk:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Fout tijdens observeren van mappen.</target>
+
+<source>Conversion error:</source>
+<target>Converteer fout:</target>
+
+<source>Error deleting file:</source>
+<target>Fout tijdens verwijderen van bestand:</target>
+
+<source>Error moving file:</source>
+<target>Fout tijdens verplaatsen van bestand:</target>
+
+<source>Target file already existing!</source>
+<target>Doelbestand bestaat al!</target>
+
+<source>Error moving directory:</source>
+<target>Fout tijdens verplaatsen van map:</target>
+
+<source>Target directory already existing!</source>
+<target>Doelmap bestaat al!</target>
+
+<source>Error deleting directory:</source>
+<target>Fout tijdens het verwijderen van map:</target>
+
+<source>Error changing modification time:</source>
+<target>Fout tijdens aanpassing van de wijzigingstijd:</target>
+
+<source>Error loading library function:</source>
+<target>Fout tijdens laden van bibliotheek functie:</target>
+
+<source>Error reading security context:</source>
+<target>Fout tijdens lezen van beveiligingscontext:</target>
+
+<source>Error writing security context:</source>
+<target>Fout tijdens schrijven van beveiligingscontext:</target>
+
+<source>Error copying file permissions:</source>
+<target>Fout tijdens kopiëren van bestandspermissies:</target>
+
+<source>Error creating directory:</source>
+<target>Fout tijdens het aanmaken van map:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Fout tijdens kopiëren van symbolische koppeling:</target>
+
+<source>Error copying file:</source>
+<target>Fout tijdens kopiëren van bestand:</target>
+
+<source>Error opening file:</source>
+<target>Fout tijdens openen van bestand:</target>
+
+<source>Error traversing directory:</source>
+<target>Fout tijdens doorzoeken van map:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Oneindige lus bij het doorlopen van map:</target>
+
+<source>Error setting privilege:</source>
+<target>Fout tijdens instellen van privileges:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Beide zijdes zijn veranderd sinds de laatste synchronisatie!</target>
@@ -1317,9 +1303,6 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Mappen zijn afhankelijk van elkaar! Wees voorzichtig met het maken van synchronisatieregels:</target>
-<source>Comparing content of files %x</source>
-<target>De inhoud van %x bestanden wordt vergeleken</target>
-
<source>Memory allocation failed!</source>
<target>RAM geheugen error!</target>
@@ -1335,15 +1318,15 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>Symlinks %x have the same date but a different target!</source>
<target>Symbolische koppeling %x heeft dezelfde datum maar een ander doel!</target>
+<source>Comparing content of files %x</source>
+<target>De inhoud van %x bestanden wordt vergeleken</target>
+
<source>Comparing files by content failed.</source>
<target>Bestand-inhoudvergelijking mislukt.</target>
<source>Generating file list...</source>
<target>Genereren van bestandslijst...</target>
-<source>Multiple...</source>
-<target>Meerdere...</target>
-
<source>Both sides are equal</source>
<target>Beide kanten zijn gelijk</target>
@@ -1362,6 +1345,12 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>Delete right file/folder</source>
<target>Verwijder rechter bestand/map</target>
+<source>Move file on left</source>
+<target></target>
+
+<source>Move file on right</source>
+<target></target>
+
<source>Overwrite left file/folder with right one</source>
<target>Overschrijf linker bestand/map met de rechter</target>
@@ -1377,6 +1366,9 @@ Zet bestand en map permissies over (Vereist Administrator rechten)
<source>Copy file attributes only to right</source>
<target>Kopieer bestandsattributen allen naar rechts</target>
+<source>Multiple...</source>
+<target>Meerdere...</target>
+
<source>Deleting file %x</source>
<target>Verwijderen van bestand %x</target>
diff --git a/BUILD/Languages/english_uk.lng b/BUILD/Languages/english_uk.lng
index a562a229..bea82597 100644
--- a/BUILD/Languages/english_uk.lng
+++ b/BUILD/Languages/english_uk.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Automated Synchronisation</target>
-<source>Browse</source>
-<target>Browse</target>
-
-<source>Windows Error Code %x:</source>
-<target>Windows Error Code %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Linux Error Code %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Invalid command line: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Error resolving symbolic link:</target>
-
-<source>Show pop-up</source>
-<target>Show pop-up</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Show pop-up on errors or warnings</target>
-
-<source>Ignore errors</source>
-<target>Ignore errors</target>
-
-<source>Hide all error and warning messages</source>
-<target>Hide all error and warning messages</target>
-
-<source>Exit instantly</source>
-<target>Exit instantly</target>
-
-<source>Abort synchronization immediately</source>
-<target>Abort synchronisation immediately</target>
-
<source>Select alternate comparison settings</source>
<target>Select alternate comparison settings</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Select time span</target>
+<source>Show pop-up</source>
+<target>Show pop-up</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Show pop-up on errors or warnings</target>
+
+<source>Ignore errors</source>
+<target>Ignore errors</target>
+
+<source>Hide all error and warning messages</source>
+<target>Hide all error and warning messages</target>
+
+<source>Exit instantly</source>
+<target>Exit instantly</target>
+
+<source>Abort synchronization immediately</source>
+<target>Abort synchronisation immediately</target>
+
+<source>Browse</source>
+<target>Browse</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Error reading from synchronisation database:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Error writing to synchronisation database:</target>
+
+<source>Invalid command line: %x</source>
+<target>Invalid command line: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows Error Code %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux Error Code %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Error resolving symbolic link:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Comparison Result</target>
-<source>Incompatible synchronization database format:</source>
-<target>Incompatible synchronisation database format:</target>
-
<source>Initial synchronization:</source>
<target>Initial synchronisation:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>One of the FreeFileSync database files is not yet existing:</target>
-<source>Error reading from synchronization database:</source>
-<target>Error reading from synchronisation database:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Incompatible synchronisation database format:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Database files do not share a common synchronisation session:</target>
@@ -199,12 +202,18 @@
<pluralform>%x sec</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Drag && drop</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Fatal Error</target>
+<source>Error reading file:</source>
+<target>Error reading file:</target>
+
<source>Scanning:</source>
<target>Scanning:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Invalid FreeFileSync config file!</target>
-<source>File does not exist:</source>
-<target>File does not exist:</target>
-
<source>Error parsing configuration file:</source>
<target>Error parsing configuration file:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Error moving to Recycle Bin:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Could not load a required DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Error accessing Volume Shadow Copy Service!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Could not determine volume name for file:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Volume name %x not part of filename %y!</target>
+
<source>/sec</source>
<target>/sec</target>
+<source>File does not exist:</source>
+<target>File does not exist:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Could not read values for the following XML nodes:</target>
+
<source>S&ave configuration...</source>
<target>S&ave configuration...</target>
@@ -324,141 +354,6 @@ The command line is executed each time:
<source>A directory input field is empty.</source>
<target>A directory input field is empty.</target>
-<source>Drag && drop</source>
-<target>Drag && drop</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Could not initialise directory monitoring:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Error when monitoring directories.</target>
-
-<source>Conversion error:</source>
-<target>Conversion error:</target>
-
-<source>Error deleting file:</source>
-<target>Error deleting file:</target>
-
-<source>Error moving file:</source>
-<target>Error moving file:</target>
-
-<source>Target file already existing!</source>
-<target>Target file already existing!</target>
-
-<source>Error moving directory:</source>
-<target>Error moving directory:</target>
-
-<source>Target directory already existing!</source>
-<target>Target directory already existing!</target>
-
-<source>Error deleting directory:</source>
-<target>Error deleting directory:</target>
-
-<source>Error changing modification time:</source>
-<target>Error changing modification time:</target>
-
-<source>Error loading library function:</source>
-<target>Error loading library function:</target>
-
-<source>Error reading security context:</source>
-<target>Error reading security context:</target>
-
-<source>Error writing security context:</source>
-<target>Error writing security context:</target>
-
-<source>Error copying file permissions:</source>
-<target>Error copying file permissions:</target>
-
-<source>Error creating directory:</source>
-<target>Error creating directory:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Error copying symbolic link:</target>
-
-<source>Error copying file:</source>
-<target>Error copying file:</target>
-
-<source>Error opening file:</source>
-<target>Error opening file:</target>
-
-<source>Error writing file:</source>
-<target>Error writing file:</target>
-
-<source>Error reading file:</source>
-<target>Error reading file:</target>
-
-<source>Operation aborted!</source>
-<target>Operation aborted!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Endless loop when traversing directory:</target>
-
-<source>Error traversing directory:</source>
-<target>Error traversing directory:</target>
-
-<source>Error setting privilege:</source>
-<target>Error setting privilege:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Error moving to Recycle Bin:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Could not load a required DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Error writing to synchronisation database:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Error accessing Volume Shadow Copy Service!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Could not determine volume name for file:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Volume name %x not part of filename %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Could not read values for the following XML nodes:</target>
-
<source>Logging</source>
<target>Logging</target>
@@ -477,9 +372,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>Batch execution</target>
-<source>Log-messages:</source>
-<target>Log-messages:</target>
-
<source>Stop</source>
<target>Stop</target>
@@ -606,6 +498,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>Total amount of data that will be transferred</target>
+<source>Operation:</source>
+<target>Operation:</target>
+
+<source>Items found:</source>
+<target>Elements found:</target>
+
+<source>Items remaining:</source>
+<target>Elements remaining:</target>
+
+<source>Speed:</source>
+<target>Speed:</target>
+
+<source>Time remaining:</source>
+<target>Time remaining:</target>
+
+<source>Time elapsed:</source>
+<target>Time elapsed:</target>
+
<source>Batch job</source>
<target>Batch job</target>
@@ -654,32 +564,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>&Cancel</target>
-<source>Operation:</source>
-<target>Operation:</target>
-
-<source>Items found:</source>
-<target>Elements found:</target>
-
-<source>Items remaining:</source>
-<target>Elements remaining:</target>
-
-<source>Speed:</source>
-<target>Speed:</target>
-
-<source>Time remaining:</source>
-<target>Time remaining:</target>
-
-<source>Time elapsed:</source>
-<target>Time elapsed:</target>
-
<source>Select variant:</source>
<target>Select variant:</target>
<source><Automatic></source>
<target><Automatic></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</target>
<source>Mirror ->></source>
<target>Mirror ->></target>
@@ -901,27 +793,19 @@ Exclude: \stuff\temp\*
<target>Transactional file copy</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</target>
<source>Copy locked files</source>
<target>Copy locked files</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</target>
<source>Copy file access permissions</source>
<target>Copy file access permissions</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Transfer file and directory permissions (Requires Administrator rights)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Transfer file and directory permissions (Requires Administrator rights)</target>
<source>Hidden dialogs:</source>
<target>Hidden dialogues:</target>
@@ -953,6 +837,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>&Find next</target>
+<source>Operation aborted!</source>
+<target>Operation aborted!</target>
+
<source>Main bar</source>
<target>Main bar</target>
@@ -993,16 +880,16 @@ Transfer file and directory permissions (Requires Administrator rights)
<target>Auto-adjust columns</target>
<source>Icon size:</source>
-<target></target>
+<target>Icon size:</target>
<source>Small</source>
-<target></target>
+<target>Small</target>
<source>Medium</source>
-<target></target>
+<target>Medium</target>
<source>Large</source>
-<target></target>
+<target>Large</target>
<source>Include all rows</source>
<target>Include all rows</target>
@@ -1130,6 +1017,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>File list exported!</target>
+<source>Error writing file:</source>
+<target>Error writing file:</target>
+
<source>Batch file created successfully!</source>
<target>Batch file created successfully!</target>
@@ -1229,9 +1119,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>Filter: Single pair</target>
-<source>Ignore</source>
-<target>Ignore</target>
-
<source>Direct</source>
<target>Direct</target>
@@ -1295,6 +1182,105 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>Move files into a time-stamped subdirectory</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Could not initialise directory monitoring:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Error when monitoring directories.</target>
+
+<source>Conversion error:</source>
+<target>Conversion error:</target>
+
+<source>Error deleting file:</source>
+<target>Error deleting file:</target>
+
+<source>Error moving file:</source>
+<target>Error moving file:</target>
+
+<source>Target file already existing!</source>
+<target>Target file already existing!</target>
+
+<source>Error moving directory:</source>
+<target>Error moving directory:</target>
+
+<source>Target directory already existing!</source>
+<target>Target directory already existing!</target>
+
+<source>Error deleting directory:</source>
+<target>Error deleting directory:</target>
+
+<source>Error changing modification time:</source>
+<target>Error changing modification time:</target>
+
+<source>Error loading library function:</source>
+<target>Error loading library function:</target>
+
+<source>Error reading security context:</source>
+<target>Error reading security context:</target>
+
+<source>Error writing security context:</source>
+<target>Error writing security context:</target>
+
+<source>Error copying file permissions:</source>
+<target>Error copying file permissions:</target>
+
+<source>Error creating directory:</source>
+<target>Error creating directory:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Error copying symbolic link:</target>
+
+<source>Error copying file:</source>
+<target>Error copying file:</target>
+
+<source>Error opening file:</source>
+<target>Error opening file:</target>
+
+<source>Error traversing directory:</source>
+<target>Error traversing directory:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Endless loop when traversing directory:</target>
+
+<source>Error setting privilege:</source>
+<target>Error setting privilege:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Both sides have changed since last synchronisation!</target>
@@ -1325,9 +1311,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Directories are dependent! Be careful when setting up synchronisation rules:</target>
-<source>Comparing content of files %x</source>
-<target>Comparing content of files %x</target>
-
<source>Memory allocation failed!</source>
<target>Memory allocation failed!</target>
@@ -1343,15 +1326,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>Symlinks %x have the same date but a different target!</target>
+<source>Comparing content of files %x</source>
+<target>Comparing content of files %x</target>
+
<source>Comparing files by content failed.</source>
<target>Comparing files by content failed.</target>
<source>Generating file list...</source>
<target>Generating file list...</target>
-<source>Multiple...</source>
-<target>Multiple...</target>
-
<source>Both sides are equal</source>
<target>Both sides are equal</target>
@@ -1370,6 +1353,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>Delete right file/folder</target>
+<source>Move file on left</source>
+<target>Move file on left</target>
+
+<source>Move file on right</source>
+<target>Move file on right</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Overwrite left file/folder with right one</target>
@@ -1385,6 +1374,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>Copy file attributes only to right</target>
+<source>Multiple...</source>
+<target>Multiple...</target>
+
<source>Deleting file %x</source>
<target>Deleting file %x</target>
diff --git a/BUILD/Languages/finnish.lng b/BUILD/Languages/finnish.lng
index 8b2012f6..942fbc33 100644
--- a/BUILD/Languages/finnish.lng
+++ b/BUILD/Languages/finnish.lng
@@ -169,15 +169,15 @@
<source>Comparison Result</source>
<target>Vertailun tulos</target>
-<source>Incompatible synchronization database format:</source>
-<target>Täsmäytyksen tietokannan muoto on virheellinen:</target>
-
<source>Initial synchronization:</source>
<target>Ensi täsmäytys:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Jokin FreeFileSynk tietokannan tiedostoista puuttuu vielä:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Täsmäytyksen tietokannan muoto on virheellinen:</target>
+
<source>Database files do not share a common synchronization session:</source>
<target>Kannan tiedostot ovat eri sessioista:</target>
@@ -232,9 +232,6 @@
<source>Invalid FreeFileSync config file!</source>
<target>Virheellinen FreeFileSync asetustiedosto!</target>
-<source>File does not exist:</source>
-<target>Tiedosto puuttuu:</target>
-
<source>Error parsing configuration file:</source>
<target>Virhe jäsentäessä asetustiedostoa:</target>
@@ -259,6 +256,9 @@
<source>/sec</source>
<target>/s</target>
+<source>File does not exist:</source>
+<target>Tiedosto puuttuu:</target>
+
<source>Could not read values for the following XML nodes:</source>
<target>Tietoja lukeminen epäonnistui, XML jäsen:</target>
@@ -372,9 +372,6 @@ Komento suoritetaan kun:
<source>Batch execution</source>
<target>Eräajon suoritus</target>
-<source>Log-messages:</source>
-<target>Lokin viestit:</target>
-
<source>Stop</source>
<target>Seis</target>
@@ -501,6 +498,24 @@ Komento suoritetaan kun:
<source>Total amount of data that will be transferred</source>
<target>Siirrettävän datan määrä</target>
+<source>Operation:</source>
+<target>Toiminto:</target>
+
+<source>Items found:</source>
+<target>Osia löytyi:</target>
+
+<source>Items remaining:</source>
+<target>Osia jäljellä:</target>
+
+<source>Speed:</source>
+<target>Nopeus:</target>
+
+<source>Time remaining:</source>
+<target>Aikaa jäljellä:</target>
+
+<source>Time elapsed:</source>
+<target>Kulunut aika:</target>
+
<source>Batch job</source>
<target>Eräajo</target>
@@ -549,32 +564,14 @@ Komento suoritetaan kun:
<source>&Cancel</source>
<target>&Lopeta</target>
-<source>Operation:</source>
-<target>Toiminto:</target>
-
-<source>Items found:</source>
-<target>Osia löytyi:</target>
-
-<source>Items remaining:</source>
-<target>Osia jäljellä:</target>
-
-<source>Speed:</source>
-<target>Nopeus:</target>
-
-<source>Time remaining:</source>
-<target>Aikaa jäljellä:</target>
-
-<source>Time elapsed:</source>
-<target>Kulunut aika:</target>
-
<source>Select variant:</source>
<target>Valitse vaihtoehto:</target>
<source><Automatic></source>
<target><- Automaattinen -></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Tunnista ja monista muutokset molemmilla puolilla tietokannalla. Poistot ja ristiriidat hoidetaan automaattisesti.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target></target>
<source>Mirror ->></source>
<target>Peilaava ->></target>
@@ -801,22 +798,14 @@ Sulje pois: \stuff\temp\*
<source>Copy locked files</source>
<target>Kopioi lukitut tiedostot</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Kopioi jaetut/lukitut tiedostot Volume Shadow Copy prosessilla (Vaatii Järjestelmävalvojan oikeuksia)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopioi jaetut/lukitut tiedostot Volume Shadow Copy prosessilla (Vaatii Järjestelmävalvojan oikeuksia)</target>
<source>Copy file access permissions</source>
<target>Kopioi tiedoston käyttöoikeuksia</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia)</target>
<source>Hidden dialogs:</source>
<target>Piilotetut ikkunat:</target>
@@ -1130,9 +1119,6 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia
<source>Filter: Single pair</source>
<target>Suodata: Yksi pari</target>
-<source>Ignore</source>
-<target>Sivuta</target>
-
<source>Direct</source>
<target>Suoraan</target>
@@ -1286,12 +1272,12 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia
<source>Error opening file:</source>
<target>Virhe avatessa tiedostoa:</target>
-<source>Endless loop when traversing directory:</source>
-<target>Suorita hakemiston läpikulku jatkuvana:</target>
-
<source>Error traversing directory:</source>
<target>Virhe hakemistoa läpikäydessä:</target>
+<source>Endless loop when traversing directory:</source>
+<target>Suorita hakemiston läpikulku jatkuvana:</target>
+
<source>Error setting privilege:</source>
<target>Virhe, asettaessa oikeuksia:</target>
@@ -1325,9 +1311,6 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Hakemistot riippuvuussuhteessa! Aseta täsmäyssääntöjä varovasti:</target>
-<source>Comparing content of files %x</source>
-<target>Vertaa tiedostojen %x tietosisältöä</target>
-
<source>Memory allocation failed!</source>
<target>Muistin varaus epäonnistui!</target>
@@ -1343,15 +1326,15 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia
<source>Symlinks %x have the same date but a different target!</source>
<target>Pikakuvakkeilla %x on sama päiväys mutta kohde on toinen!</target>
+<source>Comparing content of files %x</source>
+<target>Vertaa tiedostojen %x tietosisältöä</target>
+
<source>Comparing files by content failed.</source>
<target>Tietosisällön vertailu epäonnistui.</target>
<source>Generating file list...</source>
<target>Luodaan tiedostolista...</target>
-<source>Multiple...</source>
-<target>Moninkertainen...</target>
-
<source>Both sides are equal</source>
<target>Puolet ovat denttiset</target>
@@ -1370,6 +1353,12 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia
<source>Delete right file/folder</source>
<target>Poista tiedosto/hakemisto oikealta</target>
+<source>Move file on left</source>
+<target></target>
+
+<source>Move file on right</source>
+<target></target>
+
<source>Overwrite left file/folder with right one</source>
<target>Ylikirjoita oikea tiedosto/hakemista vasemanpuolisella</target>
@@ -1385,6 +1374,9 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia
<source>Copy file attributes only to right</source>
<target>Monista tiedosto-ominaisuudet oikealle</target>
+<source>Multiple...</source>
+<target>Moninkertainen...</target>
+
<source>Deleting file %x</source>
<target>Poista tiedosto %x</target>
diff --git a/BUILD/Languages/french.lng b/BUILD/Languages/french.lng
index 0fc97f8c..c81fa341 100644
--- a/BUILD/Languages/french.lng
+++ b/BUILD/Languages/french.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Synchronisation Automatisée</target>
-<source>Browse</source>
-<target>Parcourir</target>
-
-<source>Windows Error Code %x:</source>
-<target>Code erreur Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Code erreur Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Ligne de commande incorrecte : %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Erreur lors de la résolution du lien symbolique :</target>
-
-<source>Show pop-up</source>
-<target>Montrer les boîtes de dialogue</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Montrer les messages d'avertissement ou d'erreur</target>
-
-<source>Ignore errors</source>
-<target>Ignorer les erreurs</target>
-
-<source>Hide all error and warning messages</source>
-<target>Masquer tous les messages d'erreurs et les avertissements</target>
-
-<source>Exit instantly</source>
-<target>Sortie immédiate</target>
-
-<source>Abort synchronization immediately</source>
-<target>Abandon immédiat de la synchronisation</target>
-
<source>Select alternate comparison settings</source>
<target>Choisir d'autres paramètres de comparaison</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>choisir un intervalle de temps</target>
+<source>Show pop-up</source>
+<target>Montrer les boîtes de dialogue</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Montrer les messages d'avertissement ou d'erreur</target>
+
+<source>Ignore errors</source>
+<target>Ignorer les erreurs</target>
+
+<source>Hide all error and warning messages</source>
+<target>Masquer tous les messages d'erreurs et les avertissements</target>
+
+<source>Exit instantly</source>
+<target>Sortie immédiate</target>
+
+<source>Abort synchronization immediately</source>
+<target>Abandon immédiat de la synchronisation</target>
+
+<source>Browse</source>
+<target>Parcourir</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Erreur lors de la lecture de la base de données de synchro :</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Erreur lors de l'écriture de la base de données de synchro :</target>
+
+<source>Invalid command line: %x</source>
+<target>Ligne de commande incorrecte : %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Code erreur Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Code erreur Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Erreur lors de la résolution du lien symbolique :</target>
+
<source>%x MB</source>
<target>%x Mo</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Résultat de la comparaison</target>
-<source>Incompatible synchronization database format:</source>
-<target>Format de la base de données de synchro incompatible :</target>
-
<source>Initial synchronization:</source>
<target>Première synchronisation :</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>L'un des fichiers de la base de données FreeFileSync n'existe plus :</target>
-<source>Error reading from synchronization database:</source>
-<target>Erreur lors de la lecture de la base de données de synchro :</target>
+<source>Incompatible synchronization database format:</source>
+<target>Format de la base de données de synchro incompatible :</target>
<source>Database files do not share a common synchronization session:</source>
<target>Les fichiers de la base de données ne font pas partie de la même session de synchronisation</target>
@@ -199,12 +202,18 @@
<pluralform>%x sec</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Glisser && Déposer</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Erreur Fatale</target>
+<source>Error reading file:</source>
+<target>Erreur lors de la lecture du fichier :</target>
+
<source>Scanning:</source>
<target>Lecture en cours :</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Fichier de configuration FreeFileSync invalide !</target>
-<source>File does not exist:</source>
-<target>Le fichier n'existe pas :</target>
-
<source>Error parsing configuration file:</source>
<target>Erreur lors de l'analyse du fichier de configuration :</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Erreur lors du déplacement dans la Corbeille :</target>
+
+<source>Could not load a required DLL:</source>
+<target>Impossible de charger une DLL :</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Erreur lors de l'accès au Volume Shadow Copy Service !</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>La copie en tâche de fond sur WOW64 n'est pas possible. Utilisez pour cela la version 64 bits de FreeFileSync.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Impossible de trouver le nom de volume pour le fichier :</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Le nom de volume %x ne fait pas partie du nom de fichier %y !</target>
+
<source>/sec</source>
<target>/sec</target>
+<source>File does not exist:</source>
+<target>Le fichier n'existe pas :</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Impossible de lire les valeurs des noeuds XML suivants :</target>
+
<source>S&ave configuration...</source>
<target>S&auvegarder la configuration...</target>
@@ -324,141 +354,6 @@ La ligne de commande est exécutée chaque fois que :
<source>A directory input field is empty.</source>
<target>Un champ répertoire est vide</target>
-<source>Drag && drop</source>
-<target>Glisser && Déposer</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Impossible d'initialiser la surveillance des dossiers :</target>
-
-<source>Error when monitoring directories.</source>
-<target>Erreur lors de la surveillance des répertoires.</target>
-
-<source>Conversion error:</source>
-<target>Erreur de conversion :</target>
-
-<source>Error deleting file:</source>
-<target>Erreur lors de la suppression d'un fichier :</target>
-
-<source>Error moving file:</source>
-<target>Erreur lors du déplacement du fichier :</target>
-
-<source>Target file already existing!</source>
-<target>Le fichier de destination existe déjà !</target>
-
-<source>Error moving directory:</source>
-<target>Erreur lors du déplacement du répertoire :</target>
-
-<source>Target directory already existing!</source>
-<target>Le répertoire de destination existe déjà !</target>
-
-<source>Error deleting directory:</source>
-<target>Erreur lors de la suppression d'un répertoire :</target>
-
-<source>Error changing modification time:</source>
-<target>Erreur lors du changement de la date de modification :</target>
-
-<source>Error loading library function:</source>
-<target>Erreur lors du chargement de la bibliothèque de fonctions :</target>
-
-<source>Error reading security context:</source>
-<target>Erreur de lecture du contexte de sécurité:</target>
-
-<source>Error writing security context:</source>
-<target>Erreur d'écriture du contexte de sécurité:</target>
-
-<source>Error copying file permissions:</source>
-<target>Erreur lors de la copie des attributs système</target>
-
-<source>Error creating directory:</source>
-<target>Erreur lors de la création d'un répertoire :</target>
-
-<source>Error copying symbolic link:</source>
-<target>Erreur lors de la copie du lien symbolique :</target>
-
-<source>Error copying file:</source>
-<target>Erreur lors de la copie du fichier :</target>
-
-<source>Error opening file:</source>
-<target>Erreur lors de l'ouverture du fichier :</target>
-
-<source>Error writing file:</source>
-<target>Erreur lors de l'écriture du fichier :</target>
-
-<source>Error reading file:</source>
-<target>Erreur lors de la lecture du fichier :</target>
-
-<source>Operation aborted!</source>
-<target>Opération abandonnée !</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Boucle sans fin lors du parcours du répertoire :</target>
-
-<source>Error traversing directory:</source>
-<target>Erreur lors du parcours du répertoire :</target>
-
-<source>Error setting privilege:</source>
-<target>Erreur de paramétrage de privilège</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Erreur lors du déplacement dans la Corbeille :</target>
-
-<source>Could not load a required DLL:</source>
-<target>Impossible de charger une DLL :</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Erreur lors de l'écriture de la base de données de synchro :</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Erreur lors de l'accès au Volume Shadow Copy Service !</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>La copie en tâche de fond sur WOW64 n'est pas possible. Utilisez pour cela la version 64 bits de FreeFileSync.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Impossible de trouver le nom de volume pour le fichier :</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Le nom de volume %x ne fait pas partie du nom de fichier %y !</target>
-
-<source>%x TB</source>
-<target>%x To</target>
-
-<source>%x PB</source>
-<target>%x Po</target>
-
-<source>%x%</source>
-<target>%x %</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>%x min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>%x heure</pluralform>
-<pluralform>%x heures</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>%x jour</pluralform>
-<pluralform>%x jours</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Impossible de lire les valeurs des noeuds XML suivants :</target>
-
<source>Logging</source>
<target>Connexion</target>
@@ -477,9 +372,6 @@ La ligne de commande est exécutée chaque fois que :
<source>Batch execution</source>
<target>Exécution du traitement batch</target>
-<source>Log-messages:</source>
-<target>Messages log :</target>
-
<source>Stop</source>
<target>Arrêt</target>
@@ -606,6 +498,24 @@ La ligne de commande est exécutée chaque fois que :
<source>Total amount of data that will be transferred</source>
<target>Volume de données à transférer</target>
+<source>Operation:</source>
+<target>Opération :</target>
+
+<source>Items found:</source>
+<target>Elements trouvés :</target>
+
+<source>Items remaining:</source>
+<target>Elements restants :</target>
+
+<source>Speed:</source>
+<target>Vitesse :</target>
+
+<source>Time remaining:</source>
+<target>Temps restant :</target>
+
+<source>Time elapsed:</source>
+<target>Temps écoulé :</target>
+
<source>Batch job</source>
<target>Fichier de commandes</target>
@@ -654,32 +564,14 @@ La ligne de commande est exécutée chaque fois que :
<source>&Cancel</source>
<target>&Annuler</target>
-<source>Operation:</source>
-<target>Opération :</target>
-
-<source>Items found:</source>
-<target>Elements trouvés :</target>
-
-<source>Items remaining:</source>
-<target>Elements restants :</target>
-
-<source>Speed:</source>
-<target>Vitesse :</target>
-
-<source>Time remaining:</source>
-<target>Temps restant :</target>
-
-<source>Time elapsed:</source>
-<target>Temps écoulé :</target>
-
<source>Select variant:</source>
<target>Choisissez une variante :</target>
<source><Automatic></source>
<target><Automatique></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identifier et propager les modifications des deux côtés en utilisant une base de données. Les suppressions et les conflits sont détectés automatiquement.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target></target>
<source>Mirror ->></source>
<target>Miroir ->></target>
@@ -906,22 +798,14 @@ Exclude: \stuff\temp\*
<source>Copy locked files</source>
<target>Copier les fichiers verrouillés</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-La copie des fichiers partagés ou verrouillés nécessite le Service Volume Shadow Copy (avec les droits administrateur)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>La copie des fichiers partagés ou verrouillés nécessite le Service Volume Shadow Copy (avec les droits administrateur)</target>
<source>Copy file access permissions</source>
<target>Copie des droits d'accès aux fichiers</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Transfert des attributs système des fichiers et des répertoires (avec les droits administrateur)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Transfert des attributs système des fichiers et des répertoires (avec les droits administrateur)</target>
<source>Hidden dialogs:</source>
<target>Boîtes de dialogue masquées :</target>
@@ -953,6 +837,9 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>&Find next</source>
<target>&Chercher le suivant</target>
+<source>Operation aborted!</source>
+<target>Opération abandonnée !</target>
+
<source>Main bar</source>
<target>Barre principale</target>
@@ -1130,6 +1017,9 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>File list exported!</source>
<target>Liste des fichiers exportée !</target>
+<source>Error writing file:</source>
+<target>Erreur lors de l'écriture du fichier :</target>
+
<source>Batch file created successfully!</source>
<target>Fichier de traitement batch créé avec succès !</target>
@@ -1229,9 +1119,6 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>Filter: Single pair</source>
<target>Filtre : Une seule paire</target>
-<source>Ignore</source>
-<target>Ignorer</target>
-
<source>Direct</source>
<target>Direct</target>
@@ -1295,6 +1182,105 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>Move files into a time-stamped subdirectory</source>
<target>Déplacer les fichiers vers un sous-répertoire daté</target>
+<source>%x TB</source>
+<target>%x To</target>
+
+<source>%x PB</source>
+<target>%x Po</target>
+
+<source>%x%</source>
+<target>%x %</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>%x min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>%x heure</pluralform>
+<pluralform>%x heures</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>%x jour</pluralform>
+<pluralform>%x jours</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Impossible d'initialiser la surveillance des dossiers :</target>
+
+<source>Error when monitoring directories.</source>
+<target>Erreur lors de la surveillance des répertoires.</target>
+
+<source>Conversion error:</source>
+<target>Erreur de conversion :</target>
+
+<source>Error deleting file:</source>
+<target>Erreur lors de la suppression d'un fichier :</target>
+
+<source>Error moving file:</source>
+<target>Erreur lors du déplacement du fichier :</target>
+
+<source>Target file already existing!</source>
+<target>Le fichier de destination existe déjà !</target>
+
+<source>Error moving directory:</source>
+<target>Erreur lors du déplacement du répertoire :</target>
+
+<source>Target directory already existing!</source>
+<target>Le répertoire de destination existe déjà !</target>
+
+<source>Error deleting directory:</source>
+<target>Erreur lors de la suppression d'un répertoire :</target>
+
+<source>Error changing modification time:</source>
+<target>Erreur lors du changement de la date de modification :</target>
+
+<source>Error loading library function:</source>
+<target>Erreur lors du chargement de la bibliothèque de fonctions :</target>
+
+<source>Error reading security context:</source>
+<target>Erreur de lecture du contexte de sécurité:</target>
+
+<source>Error writing security context:</source>
+<target>Erreur d'écriture du contexte de sécurité:</target>
+
+<source>Error copying file permissions:</source>
+<target>Erreur lors de la copie des attributs système</target>
+
+<source>Error creating directory:</source>
+<target>Erreur lors de la création d'un répertoire :</target>
+
+<source>Error copying symbolic link:</source>
+<target>Erreur lors de la copie du lien symbolique :</target>
+
+<source>Error copying file:</source>
+<target>Erreur lors de la copie du fichier :</target>
+
+<source>Error opening file:</source>
+<target>Erreur lors de l'ouverture du fichier :</target>
+
+<source>Error traversing directory:</source>
+<target>Erreur lors du parcours du répertoire :</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Boucle sans fin lors du parcours du répertoire :</target>
+
+<source>Error setting privilege:</source>
+<target>Erreur de paramétrage de privilège</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Les deux côtés ont changé depuis la dernière synchronisation !</target>
@@ -1325,9 +1311,6 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Les répertoires sont imbriqués ! Attention à la mise à jour des règles de synchronisation :</target>
-<source>Comparing content of files %x</source>
-<target>Comparaison du contenu des fichiers %x</target>
-
<source>Memory allocation failed!</source>
<target>Erreur d'allocation de mémoire!</target>
@@ -1343,15 +1326,15 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>Symlinks %x have the same date but a different target!</source>
<target>Le lien symbolique %x a la même date mais une destination différente !</target>
+<source>Comparing content of files %x</source>
+<target>Comparaison du contenu des fichiers %x</target>
+
<source>Comparing files by content failed.</source>
<target>La comparaison des fichiers par leur contenu a échoué.</target>
<source>Generating file list...</source>
<target>Génération de la liste des fichiers...</target>
-<source>Multiple...</source>
-<target>Multiple...</target>
-
<source>Both sides are equal</source>
<target>Les deux cotés sont identiques</target>
@@ -1370,6 +1353,12 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>Delete right file/folder</source>
<target>Supprimer les fichiers/dossiers de droite</target>
+<source>Move file on left</source>
+<target></target>
+
+<source>Move file on right</source>
+<target></target>
+
<source>Overwrite left file/folder with right one</source>
<target>Remplacer le fichier/dossier de gauche avec celui de droite</target>
@@ -1385,6 +1374,9 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi
<source>Copy file attributes only to right</source>
<target>Copier seulement les attributs du fichier à droite</target>
+<source>Multiple...</source>
+<target>Multiple...</target>
+
<source>Deleting file %x</source>
<target>Suppression du fichier %x</target>
diff --git a/BUILD/Languages/german.lng b/BUILD/Languages/german.lng
index 78c9ee8f..3b260354 100644
--- a/BUILD/Languages/german.lng
+++ b/BUILD/Languages/german.lng
@@ -169,15 +169,15 @@
<source>Comparison Result</source>
<target>Ergebnis des Vergleichs</target>
-<source>Incompatible synchronization database format:</source>
-<target>Inkompatibles Datenbankformat:</target>
-
<source>Initial synchronization:</source>
<target>Erstmalige Synchronisation:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Eine der FreeFileSync Datenbankdateien existiert noch nicht:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Inkompatibles Datenbankformat:</target>
+
<source>Database files do not share a common synchronization session:</source>
<target>Die Datenbankdateien enthalten keine gemeinsame Synchronisationssitzung:</target>
@@ -372,9 +372,6 @@ Die Befehlszeile wird ausgeführt wenn:
<source>Batch execution</source>
<target>Batchlauf</target>
-<source>Log-messages:</source>
-<target>Meldungen:</target>
-
<source>Stop</source>
<target>Stop</target>
@@ -501,6 +498,24 @@ Die Befehlszeile wird ausgeführt wenn:
<source>Total amount of data that will be transferred</source>
<target>Gesamtmenge der zu übertragenden Daten</target>
+<source>Operation:</source>
+<target>Vorgang:</target>
+
+<source>Items found:</source>
+<target>Gefundene Elemente:</target>
+
+<source>Items remaining:</source>
+<target>Verbleibende Elemente:</target>
+
+<source>Speed:</source>
+<target>Geschwindigkeit:</target>
+
+<source>Time remaining:</source>
+<target>Verbleibende Zeit:</target>
+
+<source>Time elapsed:</source>
+<target>Vergangene Zeit:</target>
+
<source>Batch job</source>
<target>Batch-Job</target>
@@ -549,32 +564,14 @@ Die Befehlszeile wird ausgeführt wenn:
<source>&Cancel</source>
<target>&Abbrechen</target>
-<source>Operation:</source>
-<target>Vorgang:</target>
-
-<source>Items found:</source>
-<target>Gefundene Elemente:</target>
-
-<source>Items remaining:</source>
-<target>Verbleibende Elemente:</target>
-
-<source>Speed:</source>
-<target>Geschwindigkeit:</target>
-
-<source>Time remaining:</source>
-<target>Verbleibende Zeit:</target>
-
-<source>Time elapsed:</source>
-<target>Vergangene Zeit:</target>
-
<source>Select variant:</source>
<target>Variante auswählen:</target>
<source><Automatic></source>
<target><Automatik></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identifiziere und propagiere Änderungen auf beiden Seiten mit Hilfe einer Datenbank. Löschungen und Konflikte werden automatisch erkannt.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identifiziere und propagiere Änderungen auf beiden Seiten mit Hilfe einer Datenbank. Löschungen, Umbenennungen und Konflikte werden automatisch erkannt.</target>
<source>Mirror ->></source>
<target>Spiegeln ->></target>
@@ -1122,9 +1119,6 @@ Ausschließen: \stuff\temp\*
<source>Filter: Single pair</source>
<target>Filter: Einzelnes Verzeichnispaar</target>
-<source>Ignore</source>
-<target>Ignorieren</target>
-
<source>Direct</source>
<target>Direkt</target>
@@ -1278,12 +1272,12 @@ Ausschließen: \stuff\temp\*
<source>Error opening file:</source>
<target>Fehler beim Öffnen der Datei:</target>
-<source>Endless loop when traversing directory:</source>
-<target>Endlosschleife beim Lesen des Verzeichnisses:</target>
-
<source>Error traversing directory:</source>
<target>Fehler beim Durchsuchen des Verzeichnisses:</target>
+<source>Endless loop when traversing directory:</source>
+<target>Endlosschleife beim Lesen des Verzeichnisses:</target>
+
<source>Error setting privilege:</source>
<target>Fehler beim Setzen des Privilegs:</target>
@@ -1317,9 +1311,6 @@ Ausschließen: \stuff\temp\*
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Die Verzeichnisse sind voneinander abhängig! Achtung beim Festlegen der Synchronisationseinstellungen:</target>
-<source>Comparing content of files %x</source>
-<target>Vergleiche Inhalt der Dateien %x</target>
-
<source>Memory allocation failed!</source>
<target>Speicherallokation fehlgeschlagen!</target>
@@ -1335,15 +1326,15 @@ Ausschließen: \stuff\temp\*
<source>Symlinks %x have the same date but a different target!</source>
<target>Die Symbolischen Links %x haben dasselbe Datum, aber ein unterschiedliches Ziel!</target>
+<source>Comparing content of files %x</source>
+<target>Vergleiche Inhalt der Dateien %x</target>
+
<source>Comparing files by content failed.</source>
<target>Vergleich nach Dateiinhalt ist fehlgeschlagen.</target>
<source>Generating file list...</source>
<target>Erzeuge Dateiliste...</target>
-<source>Multiple...</source>
-<target>Verschiedene...</target>
-
<source>Both sides are equal</source>
<target>Beide Seiten sind gleich</target>
@@ -1362,6 +1353,12 @@ Ausschließen: \stuff\temp\*
<source>Delete right file/folder</source>
<target>Lösche rechte Datei</target>
+<source>Move file on left</source>
+<target>Verschiebe linke Datei</target>
+
+<source>Move file on right</source>
+<target>Verschiebe rechte Datei</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Überschreibe linke Datei mit rechter</target>
@@ -1377,6 +1374,9 @@ Ausschließen: \stuff\temp\*
<source>Copy file attributes only to right</source>
<target>Kopiere nur die Dateiattribute nach rechts</target>
+<source>Multiple...</source>
+<target>Verschiedene...</target>
+
<source>Deleting file %x</source>
<target>Lösche Datei %x</target>
diff --git a/BUILD/Languages/greek.lng b/BUILD/Languages/greek.lng
index c3a9a44a..1b883921 100644
--- a/BUILD/Languages/greek.lng
+++ b/BUILD/Languages/greek.lng
@@ -169,15 +169,15 @@
<source>Comparison Result</source>
<target>Αποτέλεσμα της σύγκρισης</target>
-<source>Incompatible synchronization database format:</source>
-<target>Η μορφή της βάσης δεδομένων συγχρονισμού δεν είναι συμβατή:</target>
-
<source>Initial synchronization:</source>
<target>Αρχικός συγχρονισμός:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Μια από τις βάσεις δεδομένων του FreeFileSync δεν υπάρχει ακόμα:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Η μορφή της βάσης δεδομένων συγχρονισμού δεν είναι συμβατή:</target>
+
<source>Database files do not share a common synchronization session:</source>
<target>Οι βάσεις δεδομένων δεν έχουν δημιουργηθεί από τον ίδιο συγχρονισμό:</target>
@@ -206,7 +206,7 @@
<target>Μεταφορά && Απόθεση</target>
<source>Info</source>
-<target>Πληροφορίες</target>
+<target>Πληροφορία</target>
<source>Fatal Error</source>
<target>Σημαντικό Σφάλμα</target>
@@ -372,9 +372,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>Εκτέλεση δέσμης ενεργειών</target>
-<source>Log-messages:</source>
-<target>Αποθηκευμένα μηνύματα:</target>
-
<source>Stop</source>
<target>Λήξη</target>
@@ -501,6 +498,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>Συνολικός όγκος δεδομένων που θα μεταφερθούν</target>
+<source>Operation:</source>
+<target>Λειτουργία:</target>
+
+<source>Items found:</source>
+<target>Βρέθηκαν στοιχεία:</target>
+
+<source>Items remaining:</source>
+<target>Περισσεύουν στοιχεία:</target>
+
+<source>Speed:</source>
+<target>Ταχύτητα:</target>
+
+<source>Time remaining:</source>
+<target>Απομένει χρόνος:</target>
+
+<source>Time elapsed:</source>
+<target>Πέρασε χρόνος:</target>
+
<source>Batch job</source>
<target>Δέσμη ενεργειών</target>
@@ -549,32 +564,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>&Άκυρο</target>
-<source>Operation:</source>
-<target>Λειτουργία:</target>
-
-<source>Items found:</source>
-<target>Βρέθηκαν στοιχεία:</target>
-
-<source>Items remaining:</source>
-<target>Περισσεύουν στοιχεία:</target>
-
-<source>Speed:</source>
-<target>Ταχύτητα:</target>
-
-<source>Time remaining:</source>
-<target>Απομένει χρόνος:</target>
-
-<source>Time elapsed:</source>
-<target>Πέρασε χρόνος:</target>
-
<source>Select variant:</source>
<target>Επιλέξτε μια μέθοδο:</target>
<source><Automatic></source>
<target><Αυτόματα></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Ανίχνευση και εφαρμογή των αλλαγών και στις δυο πλευρές με τη χρήση βάσης δεδομένων. Διαγραφές και διενέξεις ανιχνεύονται αυτόματα.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Αναγνώριση και αναπαραγωγή των αλλαγών και στις δύο πλευρές με τη χρήση μιας βάσης δεδομένων. Διαγραφές, μετονομασίες και διενέξεις ανιχνεύονται αυτόματα.</target>
<source>Mirror ->></source>
<target>Κατοπτρισμός ->></target>
@@ -1122,9 +1119,6 @@ Exclude: \stuff\temp\*
<source>Filter: Single pair</source>
<target>Φίλτρο: Ένα ζεύγος</target>
-<source>Ignore</source>
-<target>Παράβλεψη</target>
-
<source>Direct</source>
<target>Ως δεσμό</target>
@@ -1278,12 +1272,12 @@ Exclude: \stuff\temp\*
<source>Error opening file:</source>
<target>Σφάλμα κατά το άνοιγμα του αρχείου:</target>
-<source>Endless loop when traversing directory:</source>
-<target>Ατέρμονος βρόχος κατά την την ανάλυση του υποκαταλόγου:</target>
-
<source>Error traversing directory:</source>
<target>Σφάλμα κατά την ανάλυση του υποκαταλόγου:</target>
+<source>Endless loop when traversing directory:</source>
+<target>Ατέρμονος βρόχος κατά την την ανάλυση του υποκαταλόγου:</target>
+
<source>Error setting privilege:</source>
<target>Σφάλμα κατά τον ορισμό δικαιωμάτων:</target>
@@ -1317,9 +1311,6 @@ Exclude: \stuff\temp\*
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Οι υποκατάλογοι είναι εξαρτώμενοι. Προσοχή κατά την εισαγωγή των κανόνων συγχρονισμού:</target>
-<source>Comparing content of files %x</source>
-<target>Σύγκριση του περιεχομένου των αρχείων %x</target>
-
<source>Memory allocation failed!</source>
<target>Η δέσμευση χώρου μνήμης απέτυχε!</target>
@@ -1335,15 +1326,15 @@ Exclude: \stuff\temp\*
<source>Symlinks %x have the same date but a different target!</source>
<target>Οι συμβολικοί δεσμοί %x έχουν την ίδια ημερομηνία αλλά διαφορετικό προορισμό!</target>
+<source>Comparing content of files %x</source>
+<target>Σύγκριση του περιεχομένου των αρχείων %x</target>
+
<source>Comparing files by content failed.</source>
<target>Η σύγκριση του περιεχομένου των αρχείων απέτυχε.</target>
<source>Generating file list...</source>
<target>Δημιουργία καταλόγου αρχείων...</target>
-<source>Multiple...</source>
-<target>Πολλαπλές ρυθμίσεις...</target>
-
<source>Both sides are equal</source>
<target>Οι δυο πλευρές είναι ίδιες</target>
@@ -1362,6 +1353,12 @@ Exclude: \stuff\temp\*
<source>Delete right file/folder</source>
<target>Διαγραφή του αρχείου/υποκαταλόγου στα δεξιά</target>
+<source>Move file on left</source>
+<target>Μεταφορά του αρχείου που βρίσκεται αριστερά</target>
+
+<source>Move file on right</source>
+<target>Μεταφορά του αρχείου που βρίσκεται δεξιά</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Αντικατάσταση του αρχείου/υποκαταλόγου στα αριστερά από το(ν) αντίστοιχο στα δεξιά</target>
@@ -1377,6 +1374,9 @@ Exclude: \stuff\temp\*
<source>Copy file attributes only to right</source>
<target>Αντιγραφή μόνο των χαρακτηριστικών του αρχείου στα δεξιά</target>
+<source>Multiple...</source>
+<target>Πολλαπλές ρυθμίσεις...</target>
+
<source>Deleting file %x</source>
<target>Διαγραφή του αρχείου %x</target>
diff --git a/BUILD/Languages/hebrew.lng b/BUILD/Languages/hebrew.lng
index 40b6721a..b15dfc56 100644
--- a/BUILD/Languages/hebrew.lng
+++ b/BUILD/Languages/hebrew.lng
@@ -2,7 +2,7 @@
<language name>עברית</language name>
<translator>nitnit</translator>
<locale>he_IL</locale>
- <flag file>isreal.png</flag file>
+ <flag file>israel.png</flag file>
<plural forms>2</plural forms>
<plural definition>n == 1 ? 0 : 1</plural definition>
</header>
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - סינכרון אוטומטי</target>
-<source>Browse</source>
-<target>עיין</target>
-
-<source>Windows Error Code %x:</source>
-<target>קוד שגיאת חלונות %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>קוד שגיאת לינוקס %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>שורת פקודה בלתי חוקית: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>שגיאה בפענוח קישור סימבולי (Symbolic Link)</target>
-
-<source>Show pop-up</source>
-<target>הראה חלונות מוקפצים</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>הראה חלונות מוקפצים עבור שגיאות או אזהרות</target>
-
-<source>Ignore errors</source>
-<target>התעלם מטעויות</target>
-
-<source>Hide all error and warning messages</source>
-<target>הסתר את כל הודעות ההזהרה והשגיאה</target>
-
-<source>Exit instantly</source>
-<target>צא מידית</target>
-
-<source>Abort synchronization immediately</source>
-<target>הפסק סנכרון מידית</target>
-
<source>Select alternate comparison settings</source>
<target>בחר הגדרות השוואה חליפיות</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>בחר תחום זמן</target>
+<source>Show pop-up</source>
+<target>הראה חלונות מוקפצים</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>הראה חלונות מוקפצים עבור שגיאות או אזהרות</target>
+
+<source>Ignore errors</source>
+<target>התעלם מטעויות</target>
+
+<source>Hide all error and warning messages</source>
+<target>הסתר את כל הודעות ההזהרה והשגיאה</target>
+
+<source>Exit instantly</source>
+<target>צא מידית</target>
+
+<source>Abort synchronization immediately</source>
+<target>הפסק סנכרון מידית</target>
+
+<source>Browse</source>
+<target>עיין</target>
+
+<source>Error reading from synchronization database:</source>
+<target>שגיאה בקריאה מבסיס הנתונים של הסנכרון:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>שגיאה ברישום לבסיס נתוני סנכרון:</target>
+
+<source>Invalid command line: %x</source>
+<target>שורת פקודה בלתי חוקית: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>קוד שגיאת חלונות %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>קוד שגיאת לינוקס %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>שגיאה בפענוח קישור סימבולי (Symbolic Link)</target>
+
<source>%x MB</source>
<target>%x מגה בייט</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>תוצאות ההשוואה</target>
-<source>Incompatible synchronization database format:</source>
-<target>מסד נתונים של הסנכרון לא תואם:</target>
-
<source>Initial synchronization:</source>
<target>סנכרון ראשוני:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>אחד מקובצי בסיס הנתונים הבא עדיין לא קיים</target>
-<source>Error reading from synchronization database:</source>
-<target>שגיאה בקריאה מבסיס הנתונים של הסנכרון:</target>
+<source>Incompatible synchronization database format:</source>
+<target>מסד נתונים של הסנכרון לא תואם:</target>
<source>Database files do not share a common synchronization session:</source>
<target>קבצי בסיס הנתונים אינם חולקים ארוע סנכרון משותף:</target>
@@ -199,12 +202,18 @@
<pluralform>%x שניות</pluralform>
</target>
+<source>Drag && drop</source>
+<target>גרור והשלך</target>
+
<source>Info</source>
<target>מידע</target>
<source>Fatal Error</source>
<target>שגיאה פטלית</target>
+<source>Error reading file:</source>
+<target>שגיאה בקריאת קובץ:</target>
+
<source>Scanning:</source>
<target>סורק:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>קובץ תצורה בלתי חוקי!</target>
-<source>File does not exist:</source>
-<target>קובץ לא קיים:</target>
-
<source>Error parsing configuration file:</source>
<target>שגיאה בניתוח קובץ תצורה:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>שגיאה בהעברה לסל המיחזור:</target>
+
+<source>Could not load a required DLL:</source>
+<target>:נדרש DLL לא יכל לטעון</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>שגיאה בגישה לשרות Volume Shadow Copy Service</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>לא נתמכת בגרסה זאת אנא התקן גרסה 64 WOW64 העתקת צל ב</target>
+
+<source>Could not determine volume name for file:</source>
+<target>לא יכול לקבוע שם כרך לקובץ:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>כנונן %x לא בנתיב של קובץ %y!</target>
+
<source>/sec</source>
<target>/שנ</target>
+<source>File does not exist:</source>
+<target>קובץ לא קיים:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>XML לא יכול לקרא ערכים מצמתי :</target>
+
<source>S&ave configuration...</source>
<target>&שמור תצורה...</target>
@@ -324,141 +354,6 @@ The command line is executed each time:
<source>A directory input field is empty.</source>
<target>שדה כניסת מחיצה ריק.</target>
-<source>Drag && drop</source>
-<target>גרור והשלך</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>לא יכול לאתחל ניטור מחיצה:</target>
-
-<source>Error when monitoring directories.</source>
-<target>שגיאה בזמן ניטור מחיצות.</target>
-
-<source>Conversion error:</source>
-<target>שגיאה בהסבה:</target>
-
-<source>Error deleting file:</source>
-<target>שגיאה במחיקת קובץ:</target>
-
-<source>Error moving file:</source>
-<target>שגיאה בהעברת קובץ:</target>
-
-<source>Target file already existing!</source>
-<target>קובץ מטרה כבר קיים!</target>
-
-<source>Error moving directory:</source>
-<target>שגיאה בהעברת מחיצה:</target>
-
-<source>Target directory already existing!</source>
-<target>מחיצת מטרה כבר קיימת!</target>
-
-<source>Error deleting directory:</source>
-<target>שגיאה במחיקת מחיצה:</target>
-
-<source>Error changing modification time:</source>
-<target>שגיאה בשינוי זמן:</target>
-
-<source>Error loading library function:</source>
-<target>שגיאה בטעינת ספרית פונקציות:</target>
-
-<source>Error reading security context:</source>
-<target>שגיאה בכתיבת הקשר בטיחות:</target>
-
-<source>Error writing security context:</source>
-<target>שגיאה בכתיבת הקשר בטיחות:</target>
-
-<source>Error copying file permissions:</source>
-<target>שגיאה בהעתקת הרשאות קובץ:</target>
-
-<source>Error creating directory:</source>
-<target>שגיאה ביצירת מחיצה:</target>
-
-<source>Error copying symbolic link:</source>
-<target>שגיאה בהעתקת קישור :</target>
-
-<source>Error copying file:</source>
-<target>שגיאה בהעתקת קובץ:</target>
-
-<source>Error opening file:</source>
-<target>שגיאה בפתיחת קובץ:</target>
-
-<source>Error writing file:</source>
-<target>שגיאה בכתיבת קובץ:</target>
-
-<source>Error reading file:</source>
-<target>שגיאה בקריאת קובץ:</target>
-
-<source>Operation aborted!</source>
-<target>הפעולה בוטלה!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>נוצרת לולאה אינסופית בחצית מחיצות</target>
-
-<source>Error traversing directory:</source>
-<target>שגיאה בהצלבת מחיצות</target>
-
-<source>Error setting privilege:</source>
-<target>שגיאה בהשמת פריווילגיה</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>שגיאה בהעברה לסל המיחזור:</target>
-
-<source>Could not load a required DLL:</source>
-<target>:נדרש DLL לא יכל לטעון</target>
-
-<source>Error writing to synchronization database:</source>
-<target>שגיאה ברישום לבסיס נתוני סנכרון:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>שגיאה בגישה לשרות Volume Shadow Copy Service</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>לא נתמכת בגרסה זאת אנא התקן גרסה 64 WOW64 העתקת צל ב</target>
-
-<source>Could not determine volume name for file:</source>
-<target>לא יכול לקבוע שם כרך לקובץ:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>כנונן %x לא בנתיב של קובץ %y!</target>
-
-<source>%x TB</source>
-<target>%x טרה בייט</target>
-
-<source>%x PB</source>
-<target>%x פטה בייט</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 דקה</pluralform>
-<pluralform>%x דקות</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 שעה</pluralform>
-<pluralform>%x שעות</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 יום</pluralform>
-<pluralform>%x ימים</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>XML לא יכול לקרא ערכים מצמתי :</target>
-
<source>Logging</source>
<target>רישום ביומן</target>
@@ -477,9 +372,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>פעולת אצווה</target>
-<source>Log-messages:</source>
-<target>הודעת יומן:</target>
-
<source>Stop</source>
<target>עצור</target>
@@ -606,6 +498,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>סך הכל נתונים להעברה</target>
+<source>Operation:</source>
+<target>פעולה:</target>
+
+<source>Items found:</source>
+<target>אלמנטים נמצאו:</target>
+
+<source>Items remaining:</source>
+<target>אלמנתים נותרו:</target>
+
+<source>Speed:</source>
+<target>מהירות:</target>
+
+<source>Time remaining:</source>
+<target>זמן נותר:</target>
+
+<source>Time elapsed:</source>
+<target>זמן עבר:</target>
+
<source>Batch job</source>
<target>עבודת אצווה</target>
@@ -654,32 +564,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>&בטל</target>
-<source>Operation:</source>
-<target>פעולה:</target>
-
-<source>Items found:</source>
-<target>אלמנטים נמצאו:</target>
-
-<source>Items remaining:</source>
-<target>אלמנתים נותרו:</target>
-
-<source>Speed:</source>
-<target>מהירות:</target>
-
-<source>Time remaining:</source>
-<target>זמן נותר:</target>
-
-<source>Time elapsed:</source>
-<target>זמן עבר:</target>
-
<source>Select variant:</source>
<target>בחר משתנה:</target>
<source><Automatic></source>
<target><אוטומטי></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>זהה והפץ שינויים בשני הצדדים בעזרת בסיס נתונים. מחיקות וקונפליקטים מזוהים באופן אוטומטי.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>זהה והפץ שינויים בשני הצדדים באמצעות שימוש בבסיס נתונים. מחיקות, שינויי שמות וסתירות מתגלים באופן אוטומטי.</target>
<source>Mirror ->></source>
<target><<- מראה</target>
@@ -901,27 +793,19 @@ Exclude: \stuff\temp\*
<target>העתקת קובץ בעסקה</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>רשום לקובץ זמני (*.ffs_tmp) תחילה ושנה שם. פעולה זו מבטיחה עקביות המצב גם במקרה של שגיאה חמורה.</target>
<source>Copy locked files</source>
<target>העתק קבצים נעולים</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-העתק קבצים בשיתוף או נעולים באמצעות שרות Volume Shadow Copy Service (דורש הרשאות מנהל מערכת)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>העתק קבצים בשיתוף או נעולים באמצעות שרות Volume Shadow Copy Service (דורש הרשאות מנהל מערכת)</target>
<source>Copy file access permissions</source>
<target>העתק הרשאות גישה של הקובץ</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-העבר הרשאות קבצים ומחיצות (דורש הרשאות מנהל מערכת)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>העבר הרשאות קבצים ומחיצות (דורש הרשאות מנהל מערכת)</target>
<source>Hidden dialogs:</source>
<target>דיאלוגים מוסתרים:</target>
@@ -953,6 +837,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>&מצא הבא</target>
+<source>Operation aborted!</source>
+<target>הפעולה בוטלה!</target>
+
<source>Main bar</source>
<target>סרגל ראשי</target>
@@ -993,16 +880,16 @@ Transfer file and directory permissions (Requires Administrator rights)
<target>עימוד אוטומטי</target>
<source>Icon size:</source>
-<target></target>
+<target>גודל סמל:</target>
<source>Small</source>
-<target></target>
+<target>קטן</target>
<source>Medium</source>
-<target></target>
+<target>בינוני</target>
<source>Large</source>
-<target></target>
+<target>גדול</target>
<source>Include all rows</source>
<target>כלול את כל השורות</target>
@@ -1130,6 +1017,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>רשימת קבצים יוצאה!</target>
+<source>Error writing file:</source>
+<target>שגיאה בכתיבת קובץ:</target>
+
<source>Batch file created successfully!</source>
<target>קובץ אצווה נוצר בהצלחה!</target>
@@ -1229,9 +1119,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>זוג אחד :מסונן</target>
-<source>Ignore</source>
-<target>התעלם</target>
-
<source>Direct</source>
<target>כוון</target>
@@ -1295,6 +1182,105 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>העבר קבצים לתוך מחיצות עם שם המכיל טביעת זמן ותאריך</target>
+<source>%x TB</source>
+<target>%x טרה בייט</target>
+
+<source>%x PB</source>
+<target>%x פטה בייט</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 דקה</pluralform>
+<pluralform>%x דקות</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 שעה</pluralform>
+<pluralform>%x שעות</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 יום</pluralform>
+<pluralform>%x ימים</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>לא יכול לאתחל ניטור מחיצה:</target>
+
+<source>Error when monitoring directories.</source>
+<target>שגיאה בזמן ניטור מחיצות.</target>
+
+<source>Conversion error:</source>
+<target>שגיאה בהסבה:</target>
+
+<source>Error deleting file:</source>
+<target>שגיאה במחיקת קובץ:</target>
+
+<source>Error moving file:</source>
+<target>שגיאה בהעברת קובץ:</target>
+
+<source>Target file already existing!</source>
+<target>קובץ מטרה כבר קיים!</target>
+
+<source>Error moving directory:</source>
+<target>שגיאה בהעברת מחיצה:</target>
+
+<source>Target directory already existing!</source>
+<target>מחיצת מטרה כבר קיימת!</target>
+
+<source>Error deleting directory:</source>
+<target>שגיאה במחיקת מחיצה:</target>
+
+<source>Error changing modification time:</source>
+<target>שגיאה בשינוי זמן:</target>
+
+<source>Error loading library function:</source>
+<target>שגיאה בטעינת ספרית פונקציות:</target>
+
+<source>Error reading security context:</source>
+<target>שגיאה בכתיבת הקשר בטיחות:</target>
+
+<source>Error writing security context:</source>
+<target>שגיאה בכתיבת הקשר בטיחות:</target>
+
+<source>Error copying file permissions:</source>
+<target>שגיאה בהעתקת הרשאות קובץ:</target>
+
+<source>Error creating directory:</source>
+<target>שגיאה ביצירת מחיצה:</target>
+
+<source>Error copying symbolic link:</source>
+<target>שגיאה בהעתקת קישור :</target>
+
+<source>Error copying file:</source>
+<target>שגיאה בהעתקת קובץ:</target>
+
+<source>Error opening file:</source>
+<target>שגיאה בפתיחת קובץ:</target>
+
+<source>Error traversing directory:</source>
+<target>שגיאה בהצלבת מחיצות</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>נוצרת לולאה אינסופית בחצית מחיצות</target>
+
+<source>Error setting privilege:</source>
+<target>שגיאה בהשמת פריווילגיה</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>שני הצדדים שונו מאז הסנכרון האחרון!</target>
@@ -1325,9 +1311,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>מחיצות תלויות! זהירות בהגדרת כללי סנכרון:</target>
-<source>Comparing content of files %x</source>
-<target>השווה תכולה של קבצים %x</target>
-
<source>Memory allocation failed!</source>
<target>הקצאת זכרון נכשלה!</target>
@@ -1343,15 +1326,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>קשור סימבולי %x בעל תאריך זהה אך מטרה שונה!</target>
+<source>Comparing content of files %x</source>
+<target>השווה תכולה של קבצים %x</target>
+
<source>Comparing files by content failed.</source>
<target>השוואת קבצים באמצעות תכולה נכשלה.</target>
<source>Generating file list...</source>
<target>מייצר רשימת קבצים...</target>
-<source>Multiple...</source>
-<target>הכפל...</target>
-
<source>Both sides are equal</source>
<target>שני הצדדים שווים</target>
@@ -1370,6 +1353,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>מחק קובץ\מחיצה בצד ימין</target>
+<source>Move file on left</source>
+<target>העבר קובץ בצד שמאל</target>
+
+<source>Move file on right</source>
+<target>העבר קובץ בצד ימין</target>
+
<source>Overwrite left file/folder with right one</source>
<target>העתק ודרוס קובץ\מחיצה מימין לשמאל</target>
@@ -1385,6 +1374,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>העתק תכונות קובץ בלבד משמאל לימין</target>
+<source>Multiple...</source>
+<target>הכפל...</target>
+
<source>Deleting file %x</source>
<target>מוחק קובץ %x</target>
diff --git a/BUILD/Languages/hungarian.lng b/BUILD/Languages/hungarian.lng
index b5a14889..c21d5efd 100644
--- a/BUILD/Languages/hungarian.lng
+++ b/BUILD/Languages/hungarian.lng
@@ -169,15 +169,15 @@
<source>Comparison Result</source>
<target>Az összehasonlítás eredménye</target>
-<source>Incompatible synchronization database format:</source>
-<target>Inkompatibilis szinkronizációs adatbázis formátum:</target>
-
<source>Initial synchronization:</source>
<target>Első szinkronizáció:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>A FreeFileSync egyik adatbázisfájlja nem létezik:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Inkompatibilis szinkronizációs adatbázis formátum:</target>
+
<source>Database files do not share a common synchronization session:</source>
<target>Az adatbázisfájlok nem osztoznak egy közös szinkronizációs munkameneten:</target>
@@ -372,9 +372,6 @@ A parancssor végrehajtódik minden alkalommal, ha:
<source>Batch execution</source>
<target>Kötegelt végrehajtás</target>
-<source>Log-messages:</source>
-<target>Naplóbejegyzések:</target>
-
<source>Stop</source>
<target>Megállítás</target>
@@ -501,6 +498,24 @@ A parancssor végrehajtódik minden alkalommal, ha:
<source>Total amount of data that will be transferred</source>
<target>A mozgatandó adatok összmérete</target>
+<source>Operation:</source>
+<target>Művelet:</target>
+
+<source>Items found:</source>
+<target>Talált elemek száma:</target>
+
+<source>Items remaining:</source>
+<target>Hátralévő elemek száma:</target>
+
+<source>Speed:</source>
+<target>Sebesség:</target>
+
+<source>Time remaining:</source>
+<target>Hátralévő idő:</target>
+
+<source>Time elapsed:</source>
+<target>Eltelt idő:</target>
+
<source>Batch job</source>
<target>Kötegelt feladat</target>
@@ -549,32 +564,14 @@ A parancssor végrehajtódik minden alkalommal, ha:
<source>&Cancel</source>
<target>&Mégsem</target>
-<source>Operation:</source>
-<target>Művelet:</target>
-
-<source>Items found:</source>
-<target>Talált elemek száma:</target>
-
-<source>Items remaining:</source>
-<target>Hátralévő elemek száma:</target>
-
-<source>Speed:</source>
-<target>Sebesség:</target>
-
-<source>Time remaining:</source>
-<target>Hátralévő idő:</target>
-
-<source>Time elapsed:</source>
-<target>Eltelt idő:</target>
-
<source>Select variant:</source>
<target>Változat kiválasztása:</target>
<source><Automatic></source>
<target><Automatikus></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Mindkét oldal változásainak azonosítása és tárolása adatbázis segítségével. A törlések és ütközések automatikusan észlelődnek.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target></target>
<source>Mirror ->></source>
<target>Tükrözés ->></target>
@@ -1123,9 +1120,6 @@ Kizárni: \stuff\temp\*
<source>Filter: Single pair</source>
<target>Szűrő: Egy pár</target>
-<source>Ignore</source>
-<target>Figyelmen kívül hagy</target>
-
<source>Direct</source>
<target>Közvetlen</target>
@@ -1279,12 +1273,12 @@ Kizárni: \stuff\temp\*
<source>Error opening file:</source>
<target>A fájl megnyitása sikertelen:</target>
-<source>Endless loop when traversing directory:</source>
-<target>Végtelen hurok a mappák bejárásakor:</target>
-
<source>Error traversing directory:</source>
<target>A mappa átnézése sikertelen:</target>
+<source>Endless loop when traversing directory:</source>
+<target>Végtelen hurok a mappák bejárásakor:</target>
+
<source>Error setting privilege:</source>
<target>Hiba történt a jogok beállítása közben:</target>
@@ -1318,9 +1312,6 @@ Kizárni: \stuff\temp\*
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>A mappák függenek egymástól! Legyen óvatos, amikor megadja a szinkronizálási szabályokat:</target>
-<source>Comparing content of files %x</source>
-<target>%x fájlok tartalmának összehasonlítása</target>
-
<source>Memory allocation failed!</source>
<target>Sikertelen memóriafoglalás!</target>
@@ -1336,15 +1327,15 @@ Kizárni: \stuff\temp\*
<source>Symlinks %x have the same date but a different target!</source>
<target>A(z) %x symlinknek megegyezik a dátuma, de a célpontja nem!</target>
+<source>Comparing content of files %x</source>
+<target>%x fájlok tartalmának összehasonlítása</target>
+
<source>Comparing files by content failed.</source>
<target>Sikertelen a fájlok összehasonlítása tartalom alapján.</target>
<source>Generating file list...</source>
<target>Fájllista generálása...</target>
-<source>Multiple...</source>
-<target>Sokszorosítás</target>
-
<source>Both sides are equal</source>
<target>Mindkét oldal egyforma</target>
@@ -1363,6 +1354,12 @@ Kizárni: \stuff\temp\*
<source>Delete right file/folder</source>
<target>Jobb oldali fájl/mappa törlése</target>
+<source>Move file on left</source>
+<target></target>
+
+<source>Move file on right</source>
+<target></target>
+
<source>Overwrite left file/folder with right one</source>
<target>Bal oldali fájl/mappa felülírása a jobb oldalival</target>
@@ -1378,6 +1375,9 @@ Kizárni: \stuff\temp\*
<source>Copy file attributes only to right</source>
<target>Fájl attribútumok másolása csak a jobb oldalra</target>
+<source>Multiple...</source>
+<target>Sokszorosítás</target>
+
<source>Deleting file %x</source>
<target>Fájl törlése %x</target>
diff --git a/BUILD/Languages/italian.lng b/BUILD/Languages/italian.lng
index cdf4ef83..97aff271 100644
--- a/BUILD/Languages/italian.lng
+++ b/BUILD/Languages/italian.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Sincronizzazione Automatizzata</target>
-<source>Browse</source>
-<target>Sfoglia</target>
-
-<source>Windows Error Code %x:</source>
-<target>Errore Windows Codice %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Errore Linux Codice %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Linea di comando non valida: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Errore nella risoluzione di collegamento simbolico:</target>
-
-<source>Show pop-up</source>
-<target>Mostra pop-up</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Mostra pop-up di errori o avvisi</target>
-
-<source>Ignore errors</source>
-<target>Ignora gli errori</target>
-
-<source>Hide all error and warning messages</source>
-<target>Nascondi tutti gli errori e i messaggi d'avviso</target>
-
-<source>Exit instantly</source>
-<target>Esci istantaneamente</target>
-
-<source>Abort synchronization immediately</source>
-<target>Interrompi immediatamente la sincronizzazione</target>
-
<source>Select alternate comparison settings</source>
<target>Seleziona impostazioni di comparazione alternative</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Seleziona intervallo di tempo</target>
+<source>Show pop-up</source>
+<target>Mostra pop-up</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Mostra pop-up di errori o avvisi</target>
+
+<source>Ignore errors</source>
+<target>Ignora gli errori</target>
+
+<source>Hide all error and warning messages</source>
+<target>Nascondi tutti gli errori e i messaggi d'avviso</target>
+
+<source>Exit instantly</source>
+<target>Esci istantaneamente</target>
+
+<source>Abort synchronization immediately</source>
+<target>Interrompi immediatamente la sincronizzazione</target>
+
+<source>Browse</source>
+<target>Sfoglia</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Errore in lettura dal database di sincronizzione:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Errore in scrittura sul database di sincronizzazione:</target>
+
+<source>Invalid command line: %x</source>
+<target>Linea di comando non valida: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Errore Windows Codice %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Errore Linux Codice %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Errore nella risoluzione di collegamento simbolico:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Risultato della comparazione</target>
-<source>Incompatible synchronization database format:</source>
-<target>Formato database di sincronizzazione incompatibile:</target>
-
<source>Initial synchronization:</source>
<target>Prima sincronizzazione:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Un file database di FreeFileSync non è ancora stato creato:</target>
-<source>Error reading from synchronization database:</source>
-<target>Errore in lettura dal database di sincronizzione:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Formato database di sincronizzazione incompatibile:</target>
<source>Database files do not share a common synchronization session:</source>
<target>I file database non condividono una comune sessione di sincronizzazione:</target>
@@ -199,12 +202,18 @@
<pluralform>%x sec</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Drag && drop</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Errore Fatale</target>
+<source>Error reading file:</source>
+<target>Errore durante la lettura del file:</target>
+
<source>Scanning:</source>
<target>Analisi in corso:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>File di configurazione FreeFileSync non valido!</target>
-<source>File does not exist:</source>
-<target>Il file non esiste:</target>
-
<source>Error parsing configuration file:</source>
<target>Errore nell'analisi del file di configurazione:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Errore durante lo spostamento nel Cestino:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Impossibile caricare una DLL richiesta:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Errore in accesso al Servizio Volume Shadow Copy</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>La creazione di copie shadow su WOW64 non e' supportata. Utilizzare FreeFileSync in versione 64-bit.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Impossibile determinare il nome volume per il file:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Il nome volume %x non è parte del nome file %y!</target>
+
<source>/sec</source>
<target>/sec</target>
+<source>File does not exist:</source>
+<target>Il file non esiste:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Impossibile leggere i valori per i seguenti nodi XML:</target>
+
<source>S&ave configuration...</source>
<target>S&alva la configurazione...</target>
@@ -324,141 +354,6 @@ La linea di comando è eseguita ogni volta che:
<source>A directory input field is empty.</source>
<target>Un campo directory di input è vuoto.</target>
-<source>Drag && drop</source>
-<target>Drag && drop</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Monitoraggio directory non inizializzabile:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Errore durante il monitoraggio directory.</target>
-
-<source>Conversion error:</source>
-<target>Errore di conversione:</target>
-
-<source>Error deleting file:</source>
-<target>Errore durante l'eliminazione del file:</target>
-
-<source>Error moving file:</source>
-<target>Errore nello spostamento file:</target>
-
-<source>Target file already existing!</source>
-<target>File destinazione già esistente!</target>
-
-<source>Error moving directory:</source>
-<target>Errore nello spostamento directory:</target>
-
-<source>Target directory already existing!</source>
-<target>Directory di destinazione già esistente!</target>
-
-<source>Error deleting directory:</source>
-<target>Errore durante l'eliminazione delle directory:</target>
-
-<source>Error changing modification time:</source>
-<target>Errore durante la modifica della data:</target>
-
-<source>Error loading library function:</source>
-<target>Errore nel caricamento della funzione libreria:</target>
-
-<source>Error reading security context:</source>
-<target>Errore in lettura del contesto di sicurezza:</target>
-
-<source>Error writing security context:</source>
-<target>Errore in scrittura del contesto di sicurezza:</target>
-
-<source>Error copying file permissions:</source>
-<target>Errore durante la copia dei permessi su file:</target>
-
-<source>Error creating directory:</source>
-<target>Errore durante la creazione della directory:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Errore durante la copia del link simbolico:</target>
-
-<source>Error copying file:</source>
-<target>Errore durante la copia del file:</target>
-
-<source>Error opening file:</source>
-<target>Errore in apertura file:</target>
-
-<source>Error writing file:</source>
-<target>Errore durante la scrittura del file:</target>
-
-<source>Error reading file:</source>
-<target>Errore durante la lettura del file:</target>
-
-<source>Operation aborted!</source>
-<target>Operazione abortita!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Loop senza fine attraverso le directory:</target>
-
-<source>Error traversing directory:</source>
-<target>Errore nel percorso della directory:</target>
-
-<source>Error setting privilege:</source>
-<target>Errore nell'impostazione dei privilegi:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Errore durante lo spostamento nel Cestino:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Impossibile caricare una DLL richiesta:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Errore in scrittura sul database di sincronizzazione:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Errore in accesso al Servizio Volume Shadow Copy</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>La creazione di copie shadow su WOW64 non e' supportata. Utilizzare FreeFileSync in versione 64-bit.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Impossibile determinare il nome volume per il file:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Il nome volume %x non è parte del nome file %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 ora</pluralform>
-<pluralform>%x ore</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 giorno</pluralform>
-<pluralform>%x giorni</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Impossibile leggere i valori per i seguenti nodi XML:</target>
-
<source>Logging</source>
<target>Logging</target>
@@ -477,9 +372,6 @@ La linea di comando è eseguita ogni volta che:
<source>Batch execution</source>
<target>Esecuzione in batch</target>
-<source>Log-messages:</source>
-<target>Log-messages:</target>
-
<source>Stop</source>
<target>Stop</target>
@@ -606,6 +498,24 @@ La linea di comando è eseguita ogni volta che:
<source>Total amount of data that will be transferred</source>
<target>Volume dei dati che verranno trasferiti</target>
+<source>Operation:</source>
+<target>Operazione:</target>
+
+<source>Items found:</source>
+<target>Elementi trovati:</target>
+
+<source>Items remaining:</source>
+<target>Elementi rimanenti:</target>
+
+<source>Speed:</source>
+<target>Velocita':</target>
+
+<source>Time remaining:</source>
+<target>Tempo rimanente:</target>
+
+<source>Time elapsed:</source>
+<target>Tempo trascorso:</target>
+
<source>Batch job</source>
<target>Batch job</target>
@@ -654,32 +564,14 @@ La linea di comando è eseguita ogni volta che:
<source>&Cancel</source>
<target>&Annulla</target>
-<source>Operation:</source>
-<target>Operazione:</target>
-
-<source>Items found:</source>
-<target>Elementi trovati:</target>
-
-<source>Items remaining:</source>
-<target>Elementi rimanenti:</target>
-
-<source>Speed:</source>
-<target>Velocita':</target>
-
-<source>Time remaining:</source>
-<target>Tempo rimanente:</target>
-
-<source>Time elapsed:</source>
-<target>Tempo trascorso:</target>
-
<source>Select variant:</source>
<target>Selezionare una variante:</target>
<source><Automatic></source>
<target><Automatico></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identifica e propaga cambiamenti su entrambi i lati usando un database. Cancellazioni e conflitti sono riconosciuti automaticamente.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identifica e propaga modifiche su entrambi i lati usando un database. Cancellazioni, ridenominazioni e conflitti sono rilevati automaticamente.</target>
<source>Mirror ->></source>
<target>Mirror ->></target>
@@ -901,27 +793,19 @@ Escludi: \stuff\temp\*
<target>Copia transazionale file</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Scrivi su un file temporaneo (*.ffs_tmp) prima di rinominarlo. Ciò garantisce uno stato consistente anche in caso di errore fatale.</target>
<source>Copy locked files</source>
<target>Copia file bloccati</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Copia file condivisi o bloccati usando il Servizio Volume Shadow Copy (Richiede diritti di Administrator)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Copia file condivisi o bloccati usando il Servizio Volume Shadow Copy (Richiede diritti di Administrator)</target>
<source>Copy file access permissions</source>
<target>Copia permessi di accesso file</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)</target>
<source>Hidden dialogs:</source>
<target>Messaggi nascosti:</target>
@@ -953,6 +837,9 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>&Find next</source>
<target>&Trova successivo</target>
+<source>Operation aborted!</source>
+<target>Operazione abortita!</target>
+
<source>Main bar</source>
<target>Barra principale</target>
@@ -993,16 +880,16 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<target>Larghezza automatica colonne</target>
<source>Icon size:</source>
-<target></target>
+<target>Dimensione icona:</target>
<source>Small</source>
-<target></target>
+<target>Piccola</target>
<source>Medium</source>
-<target></target>
+<target>Media</target>
<source>Large</source>
-<target></target>
+<target>Grande</target>
<source>Include all rows</source>
<target>Includi tutte le righe</target>
@@ -1130,6 +1017,9 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>File list exported!</source>
<target>Lista dei file esportata!</target>
+<source>Error writing file:</source>
+<target>Errore durante la scrittura del file:</target>
+
<source>Batch file created successfully!</source>
<target>Creazione batch file riuscita!</target>
@@ -1229,9 +1119,6 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>Filter: Single pair</source>
<target>Filtro: Singola coppia</target>
-<source>Ignore</source>
-<target>Ignora</target>
-
<source>Direct</source>
<target>Diretto</target>
@@ -1295,6 +1182,105 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>Move files into a time-stamped subdirectory</source>
<target>Sposta file in una sotto-cartella datata</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 ora</pluralform>
+<pluralform>%x ore</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 giorno</pluralform>
+<pluralform>%x giorni</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Monitoraggio directory non inizializzabile:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Errore durante il monitoraggio directory.</target>
+
+<source>Conversion error:</source>
+<target>Errore di conversione:</target>
+
+<source>Error deleting file:</source>
+<target>Errore durante l'eliminazione del file:</target>
+
+<source>Error moving file:</source>
+<target>Errore nello spostamento file:</target>
+
+<source>Target file already existing!</source>
+<target>File destinazione già esistente!</target>
+
+<source>Error moving directory:</source>
+<target>Errore nello spostamento directory:</target>
+
+<source>Target directory already existing!</source>
+<target>Directory di destinazione già esistente!</target>
+
+<source>Error deleting directory:</source>
+<target>Errore durante l'eliminazione delle directory:</target>
+
+<source>Error changing modification time:</source>
+<target>Errore durante la modifica della data:</target>
+
+<source>Error loading library function:</source>
+<target>Errore nel caricamento della funzione libreria:</target>
+
+<source>Error reading security context:</source>
+<target>Errore in lettura del contesto di sicurezza:</target>
+
+<source>Error writing security context:</source>
+<target>Errore in scrittura del contesto di sicurezza:</target>
+
+<source>Error copying file permissions:</source>
+<target>Errore durante la copia dei permessi su file:</target>
+
+<source>Error creating directory:</source>
+<target>Errore durante la creazione della directory:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Errore durante la copia del link simbolico:</target>
+
+<source>Error copying file:</source>
+<target>Errore durante la copia del file:</target>
+
+<source>Error opening file:</source>
+<target>Errore in apertura file:</target>
+
+<source>Error traversing directory:</source>
+<target>Errore nel percorso della directory:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Loop senza fine attraverso le directory:</target>
+
+<source>Error setting privilege:</source>
+<target>Errore nell'impostazione dei privilegi:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Entrambi i lati sono cambiati dall'ultima sincronizzazione!</target>
@@ -1325,9 +1311,6 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Le directory sono dipendenti! Fai attenzione quando configuri le regole di sincronizzazione:</target>
-<source>Comparing content of files %x</source>
-<target>Comparazione contenuto del file %x</target>
-
<source>Memory allocation failed!</source>
<target>Allocazione di memoria fallita!</target>
@@ -1343,15 +1326,15 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>Symlinks %x have the same date but a different target!</source>
<target>Symlinks %x hanno stessa data ma differente target!</target>
+<source>Comparing content of files %x</source>
+<target>Comparazione contenuto del file %x</target>
+
<source>Comparing files by content failed.</source>
<target>Comparazione file in base al contenuto fallita.</target>
<source>Generating file list...</source>
<target>Generazione lista dei file...</target>
-<source>Multiple...</source>
-<target>Multiplo...</target>
-
<source>Both sides are equal</source>
<target>Entrambi i lati sono uguali</target>
@@ -1370,6 +1353,12 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>Delete right file/folder</source>
<target>Cancella file/cartella di destra</target>
+<source>Move file on left</source>
+<target>Sposta il file a sinistra</target>
+
+<source>Move file on right</source>
+<target>Sposta il file a destra</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Sovrascrivi file/cartella di sinistra con quello di destra</target>
@@ -1385,6 +1374,9 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)
<source>Copy file attributes only to right</source>
<target>Copia i soli attributi file verso destra</target>
+<source>Multiple...</source>
+<target>Multiplo...</target>
+
<source>Deleting file %x</source>
<target>Eliminazione file %x</target>
diff --git a/BUILD/Languages/japanese.lng b/BUILD/Languages/japanese.lng
index fb788c8d..b3f3e1d1 100644
--- a/BUILD/Languages/japanese.lng
+++ b/BUILD/Languages/japanese.lng
@@ -80,7 +80,7 @@
<target>検索</target>
<source>Select time span</source>
-<target></target>
+<target>タイムスパンを選択</target>
<source>Show pop-up</source>
<target>ポップアップ表示</target>
@@ -148,7 +148,7 @@
<target>サイズ</target>
<source>Date</source>
-<target>データ</target>
+<target>日付</target>
<source>Full path</source>
<target>フルパス</target>
@@ -168,15 +168,15 @@
<source>Comparison Result</source>
<target>比較結果</target>
-<source>Incompatible synchronization database format:</source>
-<target>同期データベースの書式に互換性がありません:</target>
-
<source>Initial synchronization:</source>
<target>同期処理の初期化:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>FreeFileSync データベースファイルが存在しません:</target>
+<source>Incompatible synchronization database format:</source>
+<target>同期データベースの書式に互換性がありません:</target>
+
<source>Database files do not share a common synchronization session:</source>
<target>データベースファイルは一般的な同期セッションを共有しません:</target>
@@ -239,7 +239,7 @@
<target>必要なDLLを読み込めません:</target>
<source>Error accessing Volume Shadow Copy Service!</source>
-<target></target>
+<target>ボリュームシャドウ・コピーサービスにアクセス出来ません!</target>
<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
<target>WOW64 では、ボリュームシャドウコピーに対応していません、FreeFileSync 64-bit 版をお試しください。</target>
@@ -369,9 +369,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>一括処理を実行</target>
-<source>Log-messages:</source>
-<target>ログメッセージ:</target>
-
<source>Stop</source>
<target>停止</target>
@@ -498,6 +495,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>転送されたデータの総量</target>
+<source>Operation:</source>
+<target>操作:</target>
+
+<source>Items found:</source>
+<target>見つかった要素:</target>
+
+<source>Items remaining:</source>
+<target>残りの要素:</target>
+
+<source>Speed:</source>
+<target>速度:</target>
+
+<source>Time remaining:</source>
+<target>残り時間:</target>
+
+<source>Time elapsed:</source>
+<target>経過時間:</target>
+
<source>Batch job</source>
<target>一括処理</target>
@@ -546,32 +561,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>キャンセル(&C)</target>
-<source>Operation:</source>
-<target>操作:</target>
-
-<source>Items found:</source>
-<target>見つかった要素:</target>
-
-<source>Items remaining:</source>
-<target>残りの要素:</target>
-
-<source>Speed:</source>
-<target>速度:</target>
-
-<source>Time remaining:</source>
-<target>残り時間:</target>
-
-<source>Time elapsed:</source>
-<target>経過時間:</target>
-
<source>Select variant:</source>
<target>変数を選択:</target>
<source><Automatic></source>
<target><自動></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>データベースを使用して、両側アイテムの変更を特定します。 削除、競合は自動的に検出することができます。</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>両側の識別、プロパティの変更特定にデータベースを使用します。削除、リネーム及び競合などは自動的に検出されます</target>
<source>Mirror ->></source>
<target>ミラー >></target>
@@ -790,30 +787,22 @@ Exclude: \stuff\temp\*
<target>列を下に移動</target>
<source>Transactional file copy</source>
-<target>Transactional ファイルコピー</target>
+<target>トランザクション・コピーを使用</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
<target>最初に一時ファイル(*.ffs_tmp)に書き込み、それをリネームします。これにより、致命的なエラーが起こっても状態は保証されます</target>
<source>Copy locked files</source>
-<target>ロックされたファイルをコピー</target>
+<target>ロックされたファイルをコピーする</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-ボリュームシャドーコピーを使用して共有/ロックされたファイルをコピー(管理者権限が必要)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>ボリュームシャドーコピーを使用して共有/ロックされたファイルをコピー(管理者権限が必要)</target>
<source>Copy file access permissions</source>
-<target>ファイルのアクセスパーミッションをコピー</target>
+<target>ファイルのアクセスパーミッションをコピーする</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-ファイルとディレクトリのパーミッション転送(管理者権限が必要)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>ファイルとディレクトリのパーミッション転送(管理者権限が必要)</target>
<source>Hidden dialogs:</source>
<target>ダイアログを隠す</target>
@@ -1123,9 +1112,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>フィルター:単一ペア</target>
-<source>Ignore</source>
-<target>無視</target>
-
<source>Direct</source>
<target>方向</target>
@@ -1274,12 +1260,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Error opening file:</source>
<target>ファイルのオープンに失敗:</target>
-<source>Endless loop when traversing directory:</source>
-<target>ディレクトリ移動中に無限ループが発生:</target>
-
<source>Error traversing directory:</source>
<target>ディレクトリの移動エラー:</target>
+<source>Endless loop when traversing directory:</source>
+<target>ディレクトリ移動中に無限ループが発生:</target>
+
<source>Error setting privilege:</source>
<target>特権の設定エラー:</target>
@@ -1313,9 +1299,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>ディレクトリが依存関係にあります! 同期規則の設定時には注意してください:</target>
-<source>Comparing content of files %x</source>
-<target>ファイル %x の内容を比較中</target>
-
<source>Memory allocation failed!</source>
<target>メモリ割り当てに失敗!</target>
@@ -1331,15 +1314,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>シンボリックリンク %x の日付は同一ですが、異なる対象があります!</target>
+<source>Comparing content of files %x</source>
+<target>ファイル %x の内容を比較中</target>
+
<source>Comparing files by content failed.</source>
<target>ファイル内容の比較に失敗しました</target>
<source>Generating file list...</source>
<target>ファイル一覧を作成中...</target>
-<source>Multiple...</source>
-<target>複数処理...</target>
-
<source>Both sides are equal</source>
<target>両側とも等しく</target>
@@ -1358,6 +1341,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>右側のファイル/フォルダを削除</target>
+<source>Move file on left</source>
+<target>ファイルを左に移動</target>
+
+<source>Move file on right</source>
+<target>ファイルを右に移動</target>
+
<source>Overwrite left file/folder with right one</source>
<target>右側のものを左側のファイル/フォルダに上書き</target>
@@ -1373,6 +1362,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>ファイル属性のみ右側にコピー</target>
+<source>Multiple...</source>
+<target>複数処理...</target>
+
<source>Deleting file %x</source>
<target>ファイル %x を削除中</target>
diff --git a/BUILD/Languages/korean.lng b/BUILD/Languages/korean.lng
index 561c10cd..653fb7e9 100644
--- a/BUILD/Languages/korean.lng
+++ b/BUILD/Languages/korean.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>실시간 동기화 - 자동 동기화</target>
-<source>Browse</source>
-<target>찾아보기</target>
-
-<source>Windows Error Code %x:</source>
-<target>윈도우 에러 코드 %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>리눅스 에러 코드 %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>잘못된 명령줄 : %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>심볼릭 링크를 해결하던 중 발생한 오류 :</target>
-
-<source>Show pop-up</source>
-<target>팝업 보이기</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>오류 또는 경고에 대한 팝업 보이기</target>
-
-<source>Ignore errors</source>
-<target>오류 무시</target>
-
-<source>Hide all error and warning messages</source>
-<target>모든 오류/경고 메세지 숨기기</target>
-
-<source>Exit instantly</source>
-<target>즉시 종료</target>
-
-<source>Abort synchronization immediately</source>
-<target>동기화 작업 즉시 중단</target>
-
<source>Select alternate comparison settings</source>
<target>대체 비교 설정 선택</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>시간간격(타임스팬) 선택</target>
+<source>Show pop-up</source>
+<target>팝업 보이기</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>오류 또는 경고에 대한 팝업 보이기</target>
+
+<source>Ignore errors</source>
+<target>오류 무시</target>
+
+<source>Hide all error and warning messages</source>
+<target>모든 오류/경고 메세지 숨기기</target>
+
+<source>Exit instantly</source>
+<target>즉시 종료</target>
+
+<source>Abort synchronization immediately</source>
+<target>동기화 작업 즉시 중단</target>
+
+<source>Browse</source>
+<target>찾아보기</target>
+
+<source>Error reading from synchronization database:</source>
+<target>동기화 데이터베이스로부터 읽어 들이던 중 발생한 오류 :</target>
+
+<source>Error writing to synchronization database:</source>
+<target>동기화 데이터베이스에 쓰던 중 발생한 오류 :</target>
+
+<source>Invalid command line: %x</source>
+<target>잘못된 명령줄 : %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>윈도우 에러 코드 %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>리눅스 에러 코드 %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>심볼릭 링크를 해결하던 중 발생한 오류 :</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -162,17 +168,14 @@
<source>Comparison Result</source>
<target>비교 결과</target>
-<source>Incompatible synchronization database format:</source>
-<target>호환되지 않는 동기화 데이터베이스 형식 :</target>
-
<source>Initial synchronization:</source>
<target>초기 동기화 :</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>FreeFileSync 데이터베이스 파일 중 하나가 아직 존재하지 않습니다 :</target>
-<source>Error reading from synchronization database:</source>
-<target>동기화 데이터베이스로부터 읽어 들이던 중 발생한 오류 :</target>
+<source>Incompatible synchronization database format:</source>
+<target>호환되지 않는 동기화 데이터베이스 형식 :</target>
<source>Database files do not share a common synchronization session:</source>
<target>데이터베이스 파일이 공통 동기화 세션을 공유하지 않습니다 :</target>
@@ -197,12 +200,18 @@
<pluralform>%x초</pluralform>
</target>
+<source>Drag && drop</source>
+<target>드래그 && 드랍 (마우스로 파일 끌어다 놓기)</target>
+
<source>Info</source>
<target>정보</target>
<source>Fatal Error</source>
<target>치명적 오류</target>
+<source>Error reading file:</source>
+<target>파일을 읽던 중 발생한 오류 :</target>
+
<source>Scanning:</source>
<target>스캔 :</target>
@@ -220,15 +229,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>잘못된 FreeFileSync 설정 파일!</target>
-<source>File does not exist:</source>
-<target>파일이 존재하지 않습니다 :</target>
-
<source>Error parsing configuration file:</source>
<target>설정파일 분석 중 발생한 오류 :</target>
+<source>Error moving to Recycle Bin:</source>
+<target>휴지통으로 이동 중 발생한 오류 :</target>
+
+<source>Could not load a required DLL:</source>
+<target>필요한 DLL을 로드할 수 없습니다 :</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>볼륨 섀도 복사본 서비스에 액세스하던 중 오류 발생!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>WOW64 에서의 Shadow Copy 는 지원하지 않습니다. FreeFileSync 64-bit 버전을 사용하세요.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>파일 볼륨 이름을 결정할 수 없습니다 :</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>볼륨 이름 %x 이(가) 파일 이름 %y 의 일부가 아닙니다!</target>
+
<source>/sec</source>
<target>/초</target>
+<source>File does not exist:</source>
+<target>파일이 존재하지 않습니다 :</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>다음 XML 노드 값을 읽어 들일 수 없습니다 :</target>
+
<source>S&ave configuration...</source>
<target>설정 저장</target>
@@ -321,138 +351,6 @@ The command line is executed each time:
<source>A directory input field is empty.</source>
<target>디렉토리 입력 필드가 비어 있습니다.</target>
-<source>Drag && drop</source>
-<target>드래그 && 드랍</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>디렉토리 모니터링을 초기화 할 수 없습니다 :</target>
-
-<source>Error when monitoring directories.</source>
-<target>디렉토리 모니터링 중 발생한 오류 :</target>
-
-<source>Conversion error:</source>
-<target>변환 오류 :</target>
-
-<source>Error deleting file:</source>
-<target>파일 삭제 중 발생한 오류 :</target>
-
-<source>Error moving file:</source>
-<target>파일 이동 중 발생한 오류 :</target>
-
-<source>Target file already existing!</source>
-<target>대상 파일이 이미 존재합니다!</target>
-
-<source>Error moving directory:</source>
-<target>디렉토리 이동 중 발생한 오류 :</target>
-
-<source>Target directory already existing!</source>
-<target>대상 디렉토리가 이미 존재합니다!</target>
-
-<source>Error deleting directory:</source>
-<target>디렉토리 삭제 중 발생한 오류 :</target>
-
-<source>Error changing modification time:</source>
-<target>시간 수정 중 발생한 오류 :</target>
-
-<source>Error loading library function:</source>
-<target>라이브러리 기능 로드 중 발생한 오류 :</target>
-
-<source>Error reading security context:</source>
-<target>보안 컨텍스트를 읽던 중 발생한 오류 :</target>
-
-<source>Error writing security context:</source>
-<target>보안 컨텍스트를 쓰던 중 발생한 오류 :</target>
-
-<source>Error copying file permissions:</source>
-<target>파일 권한 복사 중 발생한 오류 :</target>
-
-<source>Error creating directory:</source>
-<target>디렉토리 생성 중 발생한 오류 :</target>
-
-<source>Error copying symbolic link:</source>
-<target>심볼릭 링크 복사 중 발생한 오류 :</target>
-
-<source>Error copying file:</source>
-<target>파일 복사 중 발생한 오류 :</target>
-
-<source>Error opening file:</source>
-<target>파일을 열던 중 발생한 오류 :</target>
-
-<source>Error writing file:</source>
-<target>파일을 쓰던 중 발생한 오류 :</target>
-
-<source>Error reading file:</source>
-<target>파일을 읽던 중 발생한 오류 :</target>
-
-<source>Operation aborted!</source>
-<target>작업 중단!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>디렉토리 이동 중 무한 루프 발생 :</target>
-
-<source>Error traversing directory:</source>
-<target>디렉토리 이동 중 발생한 오류 :</target>
-
-<source>Error setting privilege:</source>
-<target>권한 설정 중 발생한 오류 :</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>휴지통으로 이동 중 발생한 오류 :</target>
-
-<source>Could not load a required DLL:</source>
-<target>필요한 DLL을 로드할 수 없습니다 :</target>
-
-<source>Error writing to synchronization database:</source>
-<target>동기화 데이터베이스에 쓰던 중 발생한 오류 :</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>볼륨 섀도 복사본 서비스에 액세스하던 중 오류 발생!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>WOW64 에서의 Shadow Copy 는 지원하지 않습니다. FreeFileSync 64-bit 버전을 사용하세요.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>파일 볼륨 이름을 결정할 수 없습니다 :</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>볼륨 이름 %x 이(가) 파일 이름 %y 의 일부가 아닙니다!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>%x분</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>%x시간</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>%x일</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>다음 XML 노드 값을 읽어 들일 수 없습니다 :</target>
-
<source>Logging</source>
<target>로그 중</target>
@@ -471,9 +369,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>일괄 실행</target>
-<source>Log-messages:</source>
-<target>로그 메세지 :</target>
-
<source>Stop</source>
<target>정지</target>
@@ -600,6 +495,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>전송하게 될 전체 데이터 용량</target>
+<source>Operation:</source>
+<target>작업 :</target>
+
+<source>Items found:</source>
+<target>발견된 요소 :</target>
+
+<source>Items remaining:</source>
+<target>남은 요소 :</target>
+
+<source>Speed:</source>
+<target>속도 :</target>
+
+<source>Time remaining:</source>
+<target>남은 시간 :</target>
+
+<source>Time elapsed:</source>
+<target>경과 시간 :</target>
+
<source>Batch job</source>
<target>일괄 작업</target>
@@ -648,32 +561,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>취소(&C)</target>
-<source>Operation:</source>
-<target>작업 :</target>
-
-<source>Items found:</source>
-<target>발견된 요소 :</target>
-
-<source>Items remaining:</source>
-<target>남은 요소 :</target>
-
-<source>Speed:</source>
-<target>속도 :</target>
-
-<source>Time remaining:</source>
-<target>남은 시간 :</target>
-
-<source>Time elapsed:</source>
-<target>경과 시간 :</target>
-
<source>Select variant:</source>
<target>옵션 선택 :</target>
<source><Automatic></source>
<target><자동></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>데이터베이스를 사용하여, 양측 변경사항을 확인합니다. 삭제 및 충돌 내역은 자동 감지됩니다.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>데이터베이스를 활용하여 양측의 변경사항을 확인하고 반영합니다. 파일 삭제/명칭 변경/충돌은 자동으로 감지됩니다.</target>
<source>Mirror ->></source>
<target>미러 ->></target>
@@ -895,27 +790,19 @@ Exclude: \stuff\temp\*
<target>트랜잭션 파일 복사</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>임시 파일 (*.ffs_tmp)로 우선 작성 후, 파일명을 변경합니다. 이러면 치명적인 오류가 발생하더라도 일관된 상태를 보장할 수 있습니다.</target>
<source>Copy locked files</source>
<target>락 걸린 파일 복사</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Volume Shadow Copy를 사용하여 공유 또는 락 걸린 파일을 복사 (관리자 권한 필요)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Volume Shadow Copy를 사용하여 공유 또는 락 걸린 파일을 복사 (관리자 권한 필요)</target>
<source>Copy file access permissions</source>
<target>파일 접근 권한 복사</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-파일 및 디렉토리 권한 전송 (관리자 권한이 필요함)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>파일 및 디렉토리 권한 전송 (관리자 권한이 필요함)</target>
<source>Hidden dialogs:</source>
<target>다이얼로그 숨기기</target>
@@ -947,6 +834,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>다음 검색(&F)</target>
+<source>Operation aborted!</source>
+<target>작업 중단!</target>
+
<source>Main bar</source>
<target>메인 바</target>
@@ -987,16 +877,16 @@ Transfer file and directory permissions (Requires Administrator rights)
<target>열 자동정렬</target>
<source>Icon size:</source>
-<target></target>
+<target>아이콘 크기</target>
<source>Small</source>
-<target></target>
+<target>작게</target>
<source>Medium</source>
-<target></target>
+<target>중간</target>
<source>Large</source>
-<target></target>
+<target>크게</target>
<source>Include all rows</source>
<target>모든 행 포함</target>
@@ -1124,6 +1014,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>파일 리스트 내보내기 완료!</target>
+<source>Error writing file:</source>
+<target>파일을 쓰던 중 발생한 오류 :</target>
+
<source>Batch file created successfully!</source>
<target>일괄 파일이 성공적으로 생성 됐습니다!</target>
@@ -1219,9 +1112,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>필터 : 단일 페어(짝)</target>
-<source>Ignore</source>
-<target>무시</target>
-
<source>Direct</source>
<target>다이렉트</target>
@@ -1283,6 +1173,102 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>파일을 타임스탬프 된 서브 폴더로 이동</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>%x분</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>%x시간</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>%x일</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>디렉토리 모니터링을 초기화 할 수 없습니다 :</target>
+
+<source>Error when monitoring directories.</source>
+<target>디렉토리 모니터링 중 발생한 오류 :</target>
+
+<source>Conversion error:</source>
+<target>변환 오류 :</target>
+
+<source>Error deleting file:</source>
+<target>파일 삭제 중 발생한 오류 :</target>
+
+<source>Error moving file:</source>
+<target>파일 이동 중 발생한 오류 :</target>
+
+<source>Target file already existing!</source>
+<target>대상 파일이 이미 존재합니다!</target>
+
+<source>Error moving directory:</source>
+<target>디렉토리 이동 중 발생한 오류 :</target>
+
+<source>Target directory already existing!</source>
+<target>대상 디렉토리가 이미 존재합니다!</target>
+
+<source>Error deleting directory:</source>
+<target>디렉토리 삭제 중 발생한 오류 :</target>
+
+<source>Error changing modification time:</source>
+<target>시간 수정 중 발생한 오류 :</target>
+
+<source>Error loading library function:</source>
+<target>라이브러리 기능 로드 중 발생한 오류 :</target>
+
+<source>Error reading security context:</source>
+<target>보안 컨텍스트를 읽던 중 발생한 오류 :</target>
+
+<source>Error writing security context:</source>
+<target>보안 컨텍스트를 쓰던 중 발생한 오류 :</target>
+
+<source>Error copying file permissions:</source>
+<target>파일 권한 복사 중 발생한 오류 :</target>
+
+<source>Error creating directory:</source>
+<target>디렉토리 생성 중 발생한 오류 :</target>
+
+<source>Error copying symbolic link:</source>
+<target>심볼릭 링크 복사 중 발생한 오류 :</target>
+
+<source>Error copying file:</source>
+<target>파일 복사 중 발생한 오류 :</target>
+
+<source>Error opening file:</source>
+<target>파일을 열던 중 발생한 오류 :</target>
+
+<source>Error traversing directory:</source>
+<target>디렉토리 이동 중 발생한 오류 :</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>디렉토리 이동 중 무한 루프 발생 :</target>
+
+<source>Error setting privilege:</source>
+<target>권한 설정 중 발생한 오류 :</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>마지막 동기화 작업 이후, 양측 모두 변경 되었습니다!</target>
@@ -1313,9 +1299,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>디렉토리가 의존 관계에 있습니다. 동기화 규칙 설정시 주의하십시오.</target>
-<source>Comparing content of files %x</source>
-<target>파일 %x 내용 별 비교 중</target>
-
<source>Memory allocation failed!</source>
<target>메모리 할당 실패!</target>
@@ -1331,15 +1314,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>심링크 %x 의 날짜는 같으나, 대상이 다릅니다!</target>
+<source>Comparing content of files %x</source>
+<target>파일 %x 내용 별 비교 중</target>
+
<source>Comparing files by content failed.</source>
<target>내용 별 파일 비교 실패</target>
<source>Generating file list...</source>
<target>파일 리스트 생성 중...</target>
-<source>Multiple...</source>
-<target>다중처리 (멀티플) 작업...</target>
-
<source>Both sides are equal</source>
<target>양측이 같음</target>
@@ -1358,6 +1341,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>우측 파일/폴더 삭제</target>
+<source>Move file on left</source>
+<target>좌측 파일 이동</target>
+
+<source>Move file on right</source>
+<target>우측 파일 이동</target>
+
<source>Overwrite left file/folder with right one</source>
<target>우측 파일/폴더로 좌측 파일/폴더 덮어쓰기</target>
@@ -1373,6 +1362,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>파일 속성만 우측으로 복사</target>
+<source>Multiple...</source>
+<target>다중처리 (멀티플) 작업...</target>
+
<source>Deleting file %x</source>
<target>파일 %x 삭제 중</target>
diff --git a/BUILD/Languages/polish.lng b/BUILD/Languages/polish.lng
index 6ce2e79b..5c874c53 100644
--- a/BUILD/Languages/polish.lng
+++ b/BUILD/Languages/polish.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Automatyczna Synchronizacja</target>
-<source>Browse</source>
-<target>Przeglądaj</target>
-
-<source>Windows Error Code %x:</source>
-<target>Błąd systemu Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Błąd systemu linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Nieprawidłowa komenda: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Błąd odczytu dowiązania symbolicznego:</target>
-
-<source>Show pop-up</source>
-<target>Pokazuj okna pop-up</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Pokazuj okna pop-up dla błędów i ostrzeżeń</target>
-
-<source>Ignore errors</source>
-<target>Ignoruj błędy</target>
-
-<source>Hide all error and warning messages</source>
-<target>Ukryj wszystkie informacje błędach i ostrzeżeniach</target>
-
-<source>Exit instantly</source>
-<target>Wyjdź natychmiast</target>
-
-<source>Abort synchronization immediately</source>
-<target>Natychmiast zakończ synchronizację</target>
-
<source>Select alternate comparison settings</source>
<target>Określ alternatywne ustawienia porównywania</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Określ przedział czasowy</target>
+<source>Show pop-up</source>
+<target>Pokazuj okna pop-up</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Pokazuj okna pop-up dla błędów i ostrzeżeń</target>
+
+<source>Ignore errors</source>
+<target>Ignoruj błędy</target>
+
+<source>Hide all error and warning messages</source>
+<target>Ukryj wszystkie informacje błędach i ostrzeżeniach</target>
+
+<source>Exit instantly</source>
+<target>Wyjdź natychmiast</target>
+
+<source>Abort synchronization immediately</source>
+<target>Natychmiast zakończ synchronizację</target>
+
+<source>Browse</source>
+<target>Przeglądaj</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Błąd odczytu z bazy danych synchronizacji:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Błąd zapisu do bazy danych synchronizacji:</target>
+
+<source>Invalid command line: %x</source>
+<target>Nieprawidłowa komenda: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Błąd systemu Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Błąd systemu linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Błąd odczytu dowiązania symbolicznego:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -164,17 +170,14 @@
<source>Comparison Result</source>
<target>Rezultat porównywania</target>
-<source>Incompatible synchronization database format:</source>
-<target>Niepoprawny format bazy danych dla synchronizacji:</target>
-
<source>Initial synchronization:</source>
<target>Wstępna synchronizacja:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Jeden z plików bazy danych FreeFileSync nie istnieje:</target>
-<source>Error reading from synchronization database:</source>
-<target>Błąd odczytu z bazy danych synchronizacji:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Niepoprawny format bazy danych dla synchronizacji:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Pliki danych nie współdzielą wspólnej sesji synchronizacji:</target>
@@ -201,12 +204,18 @@
<pluralform>%x sekund</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Drag && Drop</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Błąd krytyczny</target>
+<source>Error reading file:</source>
+<target>Błąd odczytu pliku:</target>
+
<source>Scanning:</source>
<target>Skanowanie:</target>
@@ -226,15 +235,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Nieprawidłowy plik konfiguracyjny!</target>
-<source>File does not exist:</source>
-<target>Plik nie istnieje:</target>
-
<source>Error parsing configuration file:</source>
<target>Błąd parsowania pliku konfiguracyjnego:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Błąd podczas przenoszenia do kosza:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Nie można załadować wymaganej biblioteki DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Błąd podczas dostępdu do usługi Volume Shadow Copy!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Tworzenie Shadow Copies dla WOW64 nie jest obsługiwane. Zainstaluj 64 bitową wersję FreeFileSync.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Nie można określić nazwy dysku dla pliku:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Dysk %x nie jest częścią pliku %y!</target>
+
<source>/sec</source>
<target>/sekundę</target>
+<source>File does not exist:</source>
+<target>Plik nie istnieje:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Nie można odczytać wartości dla danych gałęzi XML:</target>
+
<source>S&ave configuration...</source>
<target>Z&apisz konfigurację...</target>
@@ -327,144 +357,6 @@ Komenda jest wykonwywana za każdym razem gdy:
<source>A directory input field is empty.</source>
<target>Pole ze ścieżką katalogu jest puste.</target>
-<source>Drag && drop</source>
-<target>Drag && Drop</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Nie można uruchomić monitora katalogów:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Błąd podczas monitorowania katalogów.</target>
-
-<source>Conversion error:</source>
-<target>Błąd konwersji:</target>
-
-<source>Error deleting file:</source>
-<target>Błąd podczas usuwania pliku:</target>
-
-<source>Error moving file:</source>
-<target>Błąd podczas przenoszenia pliku:</target>
-
-<source>Target file already existing!</source>
-<target>Plik docelowy już istnieje!</target>
-
-<source>Error moving directory:</source>
-<target>Błąd podczas przenoszenia katalogu:</target>
-
-<source>Target directory already existing!</source>
-<target>Katalog docelowy już istnieje!</target>
-
-<source>Error deleting directory:</source>
-<target>Błąd podczas usuwania katalogu:</target>
-
-<source>Error changing modification time:</source>
-<target>Błąd zmiany godziny modyfikacji:</target>
-
-<source>Error loading library function:</source>
-<target>Błąd wczytywania funkcji:</target>
-
-<source>Error reading security context:</source>
-<target>Błąd odczytu kontekstu bezpieczeństwa:</target>
-
-<source>Error writing security context:</source>
-<target>Błąd zapisu kontekstu bezpieczeństwa:</target>
-
-<source>Error copying file permissions:</source>
-<target>Błąd podczas kopiowania uprawnień pliku:</target>
-
-<source>Error creating directory:</source>
-<target>Błąd podczas tworzenia katalogu:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Błąd podczas kopiowania dowiązania symbolicznego (symlink)</target>
-
-<source>Error copying file:</source>
-<target>Błąd podczas kopiowania pliku:</target>
-
-<source>Error opening file:</source>
-<target>Błąd odczytu pliku:</target>
-
-<source>Error writing file:</source>
-<target>Błąd zapisu pliku:</target>
-
-<source>Error reading file:</source>
-<target>Błąd odczytu pliku:</target>
-
-<source>Operation aborted!</source>
-<target>Operacja przerwana!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Zapętlenie podczas przeglądania katalogu:</target>
-
-<source>Error traversing directory:</source>
-<target>Błąd podczas odczytywania katalogu:</target>
-
-<source>Error setting privilege:</source>
-<target>Błąd ustawiania uprawnień:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Błąd podczas przenoszenia do kosza:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Nie można załadować wymaganej biblioteki DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Błąd zapisu do bazy danych synchronizacji:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Błąd podczas dostępdu do usługi Volume Shadow Copy!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Tworzenie Shadow Copies dla WOW64 nie jest obsługiwane. Zainstaluj 64 bitową wersję FreeFileSync.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Nie można określić nazwy dysku dla pliku:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Dysk %x nie jest częścią pliku %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 minuta</pluralform>
-<pluralform>%x minuty</pluralform>
-<pluralform>%x minut</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 godzina</pluralform>
-<pluralform>%x godziny</pluralform>
-<pluralform>%x godzin</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 dzień</pluralform>
-<pluralform>%x dni</pluralform>
-<pluralform>%x dni</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Nie można odczytać wartości dla danych gałęzi XML:</target>
-
<source>Logging</source>
<target>Tworzenie logów</target>
@@ -483,9 +375,6 @@ Komenda jest wykonwywana za każdym razem gdy:
<source>Batch execution</source>
<target>Uruchomienie pliku wsadowego</target>
-<source>Log-messages:</source>
-<target>Logi:</target>
-
<source>Stop</source>
<target>Zatrzymaj</target>
@@ -612,6 +501,24 @@ Komenda jest wykonwywana za każdym razem gdy:
<source>Total amount of data that will be transferred</source>
<target>Liczba danych do przekopiowania</target>
+<source>Operation:</source>
+<target>Operacja:</target>
+
+<source>Items found:</source>
+<target>Znalezione elementy:</target>
+
+<source>Items remaining:</source>
+<target>Pozostałe elementy:</target>
+
+<source>Speed:</source>
+<target>Prędkość:</target>
+
+<source>Time remaining:</source>
+<target>Pozostały czas:</target>
+
+<source>Time elapsed:</source>
+<target>Czas:</target>
+
<source>Batch job</source>
<target>Plik wsadowy</target>
@@ -660,32 +567,14 @@ Komenda jest wykonwywana za każdym razem gdy:
<source>&Cancel</source>
<target>&Anuluj</target>
-<source>Operation:</source>
-<target>Operacja:</target>
-
-<source>Items found:</source>
-<target>Znalezione elementy:</target>
-
-<source>Items remaining:</source>
-<target>Pozostałe elementy:</target>
-
-<source>Speed:</source>
-<target>Prędkość:</target>
-
-<source>Time remaining:</source>
-<target>Pozostały czas:</target>
-
-<source>Time elapsed:</source>
-<target>Czas:</target>
-
<source>Select variant:</source>
<target>Wybierz wariant:</target>
<source><Automatic></source>
<target><Automatycznie></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Wykryj i zastosuj zmiany po obu stronach używając bazy danych. Usunięcia i konflikty są wykrywane automatycznie.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Znajdź i zastosuj zmiany po obu stronach przy pomocy bazy danych. Usunięnia, zmiany nazwy plików oraz konflikty są usuwane automatycznie.</target>
<source>Mirror ->></source>
<target>Lustrzana ->></target>
@@ -907,27 +796,19 @@ Wyklucz: \moje\temp\*
<target>Transakcyjne kopiowanie pliku</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Stwórz tymczasowy plik (*.ffs_tmp) następnie zamień jego nazwę. Gwarantuje to spójność nawet po wystąpieniu błędu.</target>
<source>Copy locked files</source>
<target>Kopiuj zablokowane pliki</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Kopiuj pliki udostępnione i zablokowane używając usługi Volume Shadow Copy (Wymaga uprawnień administratora)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopiuj pliki udostępnione i zablokowane używając usługi Volume Shadow Copy (Wymaga uprawnień administratora)</target>
<source>Copy file access permissions</source>
<target>Kopiuj uprawnienia plików</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)</target>
<source>Hidden dialogs:</source>
<target>Ukryte dialogi:</target>
@@ -959,6 +840,9 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>&Find next</source>
<target>&Znajdź następny</target>
+<source>Operation aborted!</source>
+<target>Operacja przerwana!</target>
+
<source>Main bar</source>
<target>Główny pasek</target>
@@ -999,16 +883,16 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<target>Autodopasowanie kolumn</target>
<source>Icon size:</source>
-<target></target>
+<target>Rozmiar ikony:</target>
<source>Small</source>
-<target></target>
+<target>Mały</target>
<source>Medium</source>
-<target></target>
+<target>Średni</target>
<source>Large</source>
-<target></target>
+<target>Duży</target>
<source>Include all rows</source>
<target>Dołącz wszystkie rzędy</target>
@@ -1136,6 +1020,9 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>File list exported!</source>
<target>Lista plików wyeksportowana!</target>
+<source>Error writing file:</source>
+<target>Błąd zapisu pliku:</target>
+
<source>Batch file created successfully!</source>
<target>Plik wsadowy utworzony pomyślnie!</target>
@@ -1239,9 +1126,6 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>Filter: Single pair</source>
<target>Filtr: Pojedyńcza para</target>
-<source>Ignore</source>
-<target>Ignoruj</target>
-
<source>Direct</source>
<target>Bezpośrednio</target>
@@ -1307,6 +1191,108 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>Move files into a time-stamped subdirectory</source>
<target>Przenieś pliki do oznaczonego podkatalogu</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 minuta</pluralform>
+<pluralform>%x minuty</pluralform>
+<pluralform>%x minut</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 godzina</pluralform>
+<pluralform>%x godziny</pluralform>
+<pluralform>%x godzin</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 dzień</pluralform>
+<pluralform>%x dni</pluralform>
+<pluralform>%x dni</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Nie można uruchomić monitora katalogów:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Błąd podczas monitorowania katalogów.</target>
+
+<source>Conversion error:</source>
+<target>Błąd konwersji:</target>
+
+<source>Error deleting file:</source>
+<target>Błąd podczas usuwania pliku:</target>
+
+<source>Error moving file:</source>
+<target>Błąd podczas przenoszenia pliku:</target>
+
+<source>Target file already existing!</source>
+<target>Plik docelowy już istnieje!</target>
+
+<source>Error moving directory:</source>
+<target>Błąd podczas przenoszenia katalogu:</target>
+
+<source>Target directory already existing!</source>
+<target>Katalog docelowy już istnieje!</target>
+
+<source>Error deleting directory:</source>
+<target>Błąd podczas usuwania katalogu:</target>
+
+<source>Error changing modification time:</source>
+<target>Błąd zmiany godziny modyfikacji:</target>
+
+<source>Error loading library function:</source>
+<target>Błąd wczytywania funkcji:</target>
+
+<source>Error reading security context:</source>
+<target>Błąd odczytu kontekstu bezpieczeństwa:</target>
+
+<source>Error writing security context:</source>
+<target>Błąd zapisu kontekstu bezpieczeństwa:</target>
+
+<source>Error copying file permissions:</source>
+<target>Błąd podczas kopiowania uprawnień pliku:</target>
+
+<source>Error creating directory:</source>
+<target>Błąd podczas tworzenia katalogu:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Błąd podczas kopiowania dowiązania symbolicznego (symlink)</target>
+
+<source>Error copying file:</source>
+<target>Błąd podczas kopiowania pliku:</target>
+
+<source>Error opening file:</source>
+<target>Błąd odczytu pliku:</target>
+
+<source>Error traversing directory:</source>
+<target>Błąd podczas odczytywania katalogu:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Zapętlenie podczas przeglądania katalogu:</target>
+
+<source>Error setting privilege:</source>
+<target>Błąd ustawiania uprawnień:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Obie strony uległy zmianie od ostatniej synchronizacji!</target>
@@ -1337,9 +1323,6 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Katalogi są zależne! Pamiętaj o tym podczas ustawiania zasad synchronizacji:</target>
-<source>Comparing content of files %x</source>
-<target>Porównywanie zawartości plików %x</target>
-
<source>Memory allocation failed!</source>
<target>Błąd alokacji zasobów!</target>
@@ -1355,15 +1338,15 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>Symlinks %x have the same date but a different target!</source>
<target>Dowiązanie symboliczne %x ma te same dane, ale inny cel!</target>
+<source>Comparing content of files %x</source>
+<target>Porównywanie zawartości plików %x</target>
+
<source>Comparing files by content failed.</source>
<target>Porównywanie przez zawartość zakończone niepowodzeniem.</target>
<source>Generating file list...</source>
<target>Generowanie listy plików...</target>
-<source>Multiple...</source>
-<target>Wiele...</target>
-
<source>Both sides are equal</source>
<target>Obie strony są równe</target>
@@ -1382,6 +1365,12 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>Delete right file/folder</source>
<target>Usuń plik/katalog po prawej stronie</target>
+<source>Move file on left</source>
+<target>Przenieś plik na lewą stronę</target>
+
+<source>Move file on right</source>
+<target>Przenieś plik na prawą stronę</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Nadpisz plik/katalog po lewej stronie tym po prawej</target>
@@ -1397,6 +1386,9 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)
<source>Copy file attributes only to right</source>
<target>Kopiuj atrybuty plików tylko na prawą stronę</target>
+<source>Multiple...</source>
+<target>Wiele...</target>
+
<source>Deleting file %x</source>
<target>Usuwanie pliku %x</target>
diff --git a/BUILD/Languages/portuguese.lng b/BUILD/Languages/portuguese.lng
index 97603be2..a108cdc3 100644
--- a/BUILD/Languages/portuguese.lng
+++ b/BUILD/Languages/portuguese.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Sincronização Automática</target>
-<source>Browse</source>
-<target>Procurar</target>
-
-<source>Windows Error Code %x:</source>
-<target>Código de erro do Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Código de erro do Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Linha de comando inválida: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Erro na resolução do link simbólico:</target>
-
-<source>Show pop-up</source>
-<target>Mostrar popup</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Mostrar popup em caso de erros ou avisos</target>
-
-<source>Ignore errors</source>
-<target>Ignorar erros</target>
-
-<source>Hide all error and warning messages</source>
-<target>Ocultar todas as mensagens de erro/aviso</target>
-
-<source>Exit instantly</source>
-<target>Sair imediatamente</target>
-
-<source>Abort synchronization immediately</source>
-<target>Abortar sincronização imediatamente</target>
-
<source>Select alternate comparison settings</source>
<target>Selecionar opções alternativas de comparação</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Selecionar intervalo de tempo</target>
+<source>Show pop-up</source>
+<target>Mostrar popup</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Mostrar popup em caso de erros ou avisos</target>
+
+<source>Ignore errors</source>
+<target>Ignorar erros</target>
+
+<source>Hide all error and warning messages</source>
+<target>Ocultar todas as mensagens de erro/aviso</target>
+
+<source>Exit instantly</source>
+<target>Sair imediatamente</target>
+
+<source>Abort synchronization immediately</source>
+<target>Abortar sincronização imediatamente</target>
+
+<source>Browse</source>
+<target>Procurar</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Erro ao ler a base de dados de sincronização:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Erro na escrita da base de dados de sincronização:</target>
+
+<source>Invalid command line: %x</source>
+<target>Linha de comando inválida: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Código de erro do Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Código de erro do Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Erro na resolução do link simbólico:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Resultados da comparação</target>
-<source>Incompatible synchronization database format:</source>
-<target>Formato de base de dados de sincronização incompatível:</target>
-
<source>Initial synchronization:</source>
<target>Sincronização inicial:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Um dos ficheiros da base de dados não existe:</target>
-<source>Error reading from synchronization database:</source>
-<target>Erro ao ler a base de dados de sincronização:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Formato de base de dados de sincronização incompatível:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Bases de dados não partilham a mesma sessão de sincronização:</target>
@@ -199,12 +202,18 @@
<pluralform>%x segs</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Arrastar && Largar</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Erro crítico</target>
+<source>Error reading file:</source>
+<target>Erro de leitura de ficheiro:</target>
+
<source>Scanning:</source>
<target>A pesquisar:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Ficheiro de configuração inválido!</target>
-<source>File does not exist:</source>
-<target>O ficheiro não existe:</target>
-
<source>Error parsing configuration file:</source>
<target>Erro de leitura do ficheiro de configuração:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Erro ao mover para a Reciclagem:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Não foi possível carregar a DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Erro no acesso ao serviço Volume Shadow Copy!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Fazer cópias fantasma em WOW64 não é suportado. Por favor usar a versão 64-bit.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Não é possível determinar o nome do volume para o ficheiro:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Nome do volume %x não faz parte do ficheiro %y!</target>
+
<source>/sec</source>
<target>/seg</target>
+<source>File does not exist:</source>
+<target>O ficheiro não existe:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Não foi possível ler os valores dos seguintes nós XML:</target>
+
<source>S&ave configuration...</source>
<target>G&uardar a configuração...</target>
@@ -324,141 +354,6 @@ A linha de comandos é executada cada vez que:
<source>A directory input field is empty.</source>
<target>Um campo de directório está vazio.</target>
-<source>Drag && drop</source>
-<target>Arrastar && Largar</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Não é possível iniciar monitorização do directório:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Erro ao monitorizar os directórios.</target>
-
-<source>Conversion error:</source>
-<target>Erro de conversão:</target>
-
-<source>Error deleting file:</source>
-<target>Erro ao eliminar o ficheiro:</target>
-
-<source>Error moving file:</source>
-<target>Erro ao mover o ficheiro:</target>
-
-<source>Target file already existing!</source>
-<target>Ficheiro de destino já existe!</target>
-
-<source>Error moving directory:</source>
-<target>Erro ao mover o directório:</target>
-
-<source>Target directory already existing!</source>
-<target>Directório de destino já existe!</target>
-
-<source>Error deleting directory:</source>
-<target>Erro ao eliminar a pasta:</target>
-
-<source>Error changing modification time:</source>
-<target>Erro ao mudar a hora de modificação:</target>
-
-<source>Error loading library function:</source>
-<target>Erro ao carregar a livraria:</target>
-
-<source>Error reading security context:</source>
-<target>Erro ao ler contexto de segurança:</target>
-
-<source>Error writing security context:</source>
-<target>Erro de escrita no contexto de segurança:</target>
-
-<source>Error copying file permissions:</source>
-<target>Erro ao copiar permissões dos ficheiros:</target>
-
-<source>Error creating directory:</source>
-<target>Erro ao criar a pasta:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Erro ao copiar o link:</target>
-
-<source>Error copying file:</source>
-<target>Erro ao copiar ficheiro:</target>
-
-<source>Error opening file:</source>
-<target>Erro ao abrir ficheiro:</target>
-
-<source>Error writing file:</source>
-<target>Erro de escrita no ficheiro:</target>
-
-<source>Error reading file:</source>
-<target>Erro de leitura de ficheiro:</target>
-
-<source>Operation aborted!</source>
-<target>Operação abortada!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Loop infinito ao percorrer directório:</target>
-
-<source>Error traversing directory:</source>
-<target>Erro ao percorrer a pasta:</target>
-
-<source>Error setting privilege:</source>
-<target>Erro ao estabelecer privilégios:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Erro ao mover para a Reciclagem:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Não foi possível carregar a DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Erro na escrita da base de dados de sincronização:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Erro no acesso ao serviço Volume Shadow Copy!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Fazer cópias fantasma em WOW64 não é suportado. Por favor usar a versão 64-bit.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Não é possível determinar o nome do volume para o ficheiro:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Nome do volume %x não faz parte do ficheiro %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x mins</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 hora</pluralform>
-<pluralform>%x horas</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 dia</pluralform>
-<pluralform>%x dias</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Não foi possível ler os valores dos seguintes nós XML:</target>
-
<source>Logging</source>
<target>A escrever em log</target>
@@ -477,9 +372,6 @@ A linha de comandos é executada cada vez que:
<source>Batch execution</source>
<target>Execução do batch</target>
-<source>Log-messages:</source>
-<target>Log de mensagens:</target>
-
<source>Stop</source>
<target>Parar</target>
@@ -606,6 +498,24 @@ A linha de comandos é executada cada vez que:
<source>Total amount of data that will be transferred</source>
<target>Volume de dados a ser transferido</target>
+<source>Operation:</source>
+<target>Operação:</target>
+
+<source>Items found:</source>
+<target>Elementos encontrados:</target>
+
+<source>Items remaining:</source>
+<target>Elementos restantes:</target>
+
+<source>Speed:</source>
+<target>Velocidade:</target>
+
+<source>Time remaining:</source>
+<target>Tempo restante:</target>
+
+<source>Time elapsed:</source>
+<target>Tempo passado:</target>
+
<source>Batch job</source>
<target>Ficheiro Batch</target>
@@ -654,32 +564,14 @@ A linha de comandos é executada cada vez que:
<source>&Cancel</source>
<target>&Cancelar</target>
-<source>Operation:</source>
-<target>Operação:</target>
-
-<source>Items found:</source>
-<target>Elementos encontrados:</target>
-
-<source>Items remaining:</source>
-<target>Elementos restantes:</target>
-
-<source>Speed:</source>
-<target>Velocidade:</target>
-
-<source>Time remaining:</source>
-<target>Tempo restante:</target>
-
-<source>Time elapsed:</source>
-<target>Tempo passado:</target>
-
<source>Select variant:</source>
<target>Selecione uma variante:</target>
<source><Automatic></source>
<target><Automático></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identificar e propagar as mudanças usando base de dados. Eliminações e conflitos serão detectados automaticamente.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target></target>
<source>Mirror ->></source>
<target>Espelhar ->></target>
@@ -905,22 +797,14 @@ Excluir: \stuff\temp\*
<source>Copy locked files</source>
<target>Copiar ficheiros bloqueados</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Copiar ficheiros partilhados ou bloqueados usando o serviço Volume Shadow Copy (Requer direitos de administrador)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Copiar ficheiros partilhados ou bloqueados usando o serviço Volume Shadow Copy (Requer direitos de administrador)</target>
<source>Copy file access permissions</source>
<target>Copiar permissões de acesso do ficheiro</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Transferir ficheiro e permissões (Requer direitos de administrador)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Transferir ficheiro e permissões (Requer direitos de administrador)</target>
<source>Hidden dialogs:</source>
<target>Diálogos ocultos:</target>
@@ -952,6 +836,9 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>&Find next</source>
<target>&Procurar seguinte</target>
+<source>Operation aborted!</source>
+<target>Operação abortada!</target>
+
<source>Main bar</source>
<target>Barra principal</target>
@@ -1129,6 +1016,9 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>File list exported!</source>
<target>Lista dos ficheiros exportada!</target>
+<source>Error writing file:</source>
+<target>Erro de escrita no ficheiro:</target>
+
<source>Batch file created successfully!</source>
<target>Ficheiro batch criado com sucesso!</target>
@@ -1228,9 +1118,6 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>Filter: Single pair</source>
<target>Filtro: Par simples</target>
-<source>Ignore</source>
-<target>Ignorar</target>
-
<source>Direct</source>
<target>Direto</target>
@@ -1294,6 +1181,105 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>Move files into a time-stamped subdirectory</source>
<target>Mover ficheiros para uma subpasta datada</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x mins</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 hora</pluralform>
+<pluralform>%x horas</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 dia</pluralform>
+<pluralform>%x dias</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Não é possível iniciar monitorização do directório:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Erro ao monitorizar os directórios.</target>
+
+<source>Conversion error:</source>
+<target>Erro de conversão:</target>
+
+<source>Error deleting file:</source>
+<target>Erro ao eliminar o ficheiro:</target>
+
+<source>Error moving file:</source>
+<target>Erro ao mover o ficheiro:</target>
+
+<source>Target file already existing!</source>
+<target>Ficheiro de destino já existe!</target>
+
+<source>Error moving directory:</source>
+<target>Erro ao mover o directório:</target>
+
+<source>Target directory already existing!</source>
+<target>Directório de destino já existe!</target>
+
+<source>Error deleting directory:</source>
+<target>Erro ao eliminar a pasta:</target>
+
+<source>Error changing modification time:</source>
+<target>Erro ao mudar a hora de modificação:</target>
+
+<source>Error loading library function:</source>
+<target>Erro ao carregar a livraria:</target>
+
+<source>Error reading security context:</source>
+<target>Erro ao ler contexto de segurança:</target>
+
+<source>Error writing security context:</source>
+<target>Erro de escrita no contexto de segurança:</target>
+
+<source>Error copying file permissions:</source>
+<target>Erro ao copiar permissões dos ficheiros:</target>
+
+<source>Error creating directory:</source>
+<target>Erro ao criar a pasta:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Erro ao copiar o link:</target>
+
+<source>Error copying file:</source>
+<target>Erro ao copiar ficheiro:</target>
+
+<source>Error opening file:</source>
+<target>Erro ao abrir ficheiro:</target>
+
+<source>Error traversing directory:</source>
+<target>Erro ao percorrer a pasta:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Loop infinito ao percorrer directório:</target>
+
+<source>Error setting privilege:</source>
+<target>Erro ao estabelecer privilégios:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Ambos os lados tiveram alterações desde a última sincronização!</target>
@@ -1324,9 +1310,6 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Directórios são dependentes! Cuidado ao definir as regras de sincronização:</target>
-<source>Comparing content of files %x</source>
-<target>A comparar o conteúdo do ficheiro %x</target>
-
<source>Memory allocation failed!</source>
<target>Alocação de memória falhou!</target>
@@ -1342,15 +1325,15 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>Symlinks %x have the same date but a different target!</source>
<target>Links simbólicos %x tem a mesma data mas diferente destino!</target>
+<source>Comparing content of files %x</source>
+<target>A comparar o conteúdo do ficheiro %x</target>
+
<source>Comparing files by content failed.</source>
<target>A comparação de ficheiros por conteúdo falhou.</target>
<source>Generating file list...</source>
<target>A gerar lista ficheiros...</target>
-<source>Multiple...</source>
-<target>Multiplo...</target>
-
<source>Both sides are equal</source>
<target>Ambos os lados iguais</target>
@@ -1369,6 +1352,12 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>Delete right file/folder</source>
<target>Eliminar ficheiro/pasta à direita</target>
+<source>Move file on left</source>
+<target></target>
+
+<source>Move file on right</source>
+<target></target>
+
<source>Overwrite left file/folder with right one</source>
<target>Substituir ficheiro/pasta da esquerda (pelo da direita)</target>
@@ -1384,6 +1373,9 @@ Transferir ficheiro e permissões (Requer direitos de administrador)
<source>Copy file attributes only to right</source>
<target>Copiar apenas atributos de ficheiro para a direita</target>
+<source>Multiple...</source>
+<target>Multiplo...</target>
+
<source>Deleting file %x</source>
<target>Apagar ficheiro %x</target>
diff --git a/BUILD/Languages/portuguese_br.lng b/BUILD/Languages/portuguese_br.lng
index 5489adeb..b6ec4d95 100644
--- a/BUILD/Languages/portuguese_br.lng
+++ b/BUILD/Languages/portuguese_br.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Sincronização Automatizada</target>
-<source>Browse</source>
-<target>Procurar</target>
-
-<source>Windows Error Code %x:</source>
-<target>Código de Erro do Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Código de Erro do Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Linha de comando inválida: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Erro na resolução de link simbólico:</target>
-
-<source>Show pop-up</source>
-<target>Mostrar pop-up</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Mostrar pop-up em erros e avisos</target>
-
-<source>Ignore errors</source>
-<target>Ignorar erros</target>
-
-<source>Hide all error and warning messages</source>
-<target>Ocultar todas as mensagens de erro ou aviso</target>
-
-<source>Exit instantly</source>
-<target>Sair instantaneamente</target>
-
-<source>Abort synchronization immediately</source>
-<target>Cancelar a sincronização imediatamente</target>
-
<source>Select alternate comparison settings</source>
<target>Selecionar configuração de comparação alternativa</target>
@@ -89,7 +56,7 @@
<target>Erro</target>
<source>Warning</source>
-<target>Atenção</target>
+<target>Avisos</target>
<source>Question</source>
<target>Questão</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Selecionar período de tempo</target>
+<source>Show pop-up</source>
+<target>Mostrar pop-up</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Mostrar pop-up em erros e avisos</target>
+
+<source>Ignore errors</source>
+<target>Ignorar erros</target>
+
+<source>Hide all error and warning messages</source>
+<target>Ocultar todas as mensagens de erro ou aviso</target>
+
+<source>Exit instantly</source>
+<target>Sair instantaneamente</target>
+
+<source>Abort synchronization immediately</source>
+<target>Cancelar a sincronização imediatamente</target>
+
+<source>Browse</source>
+<target>Procurar</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Erro ao ler do banco de dados de sincronização:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Erro ao escrever no banco de dados de sincronização:</target>
+
+<source>Invalid command line: %x</source>
+<target>Linha de comando inválida: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Código de Erro do Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Código de Erro do Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Erro na resolução de link simbólico:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Resultado da Comparação</target>
-<source>Incompatible synchronization database format:</source>
-<target>Formato de banco de dados de sincronização incompatível:</target>
-
<source>Initial synchronization:</source>
<target>Sincronização inicial:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Um dos arquivos de banco de dados do FreeFileSync ainda não existe:</target>
-<source>Error reading from synchronization database:</source>
-<target>Erro ao ler do banco de dados de sincronização:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Formato de banco de dados de sincronização incompatível:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Arquivos de banco de dados não compartilham uma sessão de sincronização comum:</target>
@@ -199,12 +202,18 @@
<pluralform>%x seg</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Arrastar && Soltar</target>
+
<source>Info</source>
-<target>Info</target>
+<target>Informações</target>
<source>Fatal Error</source>
<target>Erro fatal</target>
+<source>Error reading file:</source>
+<target>Erro ao ler arquivo:</target>
+
<source>Scanning:</source>
<target>Pesquisando:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Arquivo de configuração do FreeFileSync inválido!</target>
-<source>File does not exist:</source>
-<target>O arquivo não existe:</target>
-
<source>Error parsing configuration file:</source>
<target>Erro de leitura do arquivo de configuração:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Erro ao mover para a Lixeira:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Não foi possível carregar uma DLL requerida:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Erro ao acessar o Serviço de Cópia de Sombra de Volume!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Cópias de sombra no WOW64 não são suportadas. Por favor use a versão 64-bits do FreeFileSync.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Não foi possível determinar o nome do volume para o arquivo:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Nome do volume %x não é parte do arquivo %y!</target>
+
<source>/sec</source>
<target>/seg</target>
+<source>File does not exist:</source>
+<target>O arquivo não existe:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Não foi possível ler os valores para os seguintes nós XML:</target>
+
<source>S&ave configuration...</source>
<target>S&alvar configuração...</target>
@@ -324,143 +354,8 @@ A linha de comando é executada cada vez que:
<source>A directory input field is empty.</source>
<target>Um campo de entrada de diretório está vazio.</target>
-<source>Drag && drop</source>
-<target>Arrastar && Soltar</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Não foi possível inicializar o monitoramento de diretórios:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Erro ao monitorar os diretórios.</target>
-
-<source>Conversion error:</source>
-<target>Erro de conversão:</target>
-
-<source>Error deleting file:</source>
-<target>Erro ao apagar arquivo:</target>
-
-<source>Error moving file:</source>
-<target>Erro ao mover arquivo:</target>
-
-<source>Target file already existing!</source>
-<target>Arquivo de destino já existe!</target>
-
-<source>Error moving directory:</source>
-<target>Erro ao mover diretório:</target>
-
-<source>Target directory already existing!</source>
-<target>Diretório de destino já existe!</target>
-
-<source>Error deleting directory:</source>
-<target>Erro ao apagar diretório:</target>
-
-<source>Error changing modification time:</source>
-<target>Erro ao mudar a hora de modificação:</target>
-
-<source>Error loading library function:</source>
-<target>Erro ao carregar a biblioteca de funções:</target>
-
-<source>Error reading security context:</source>
-<target>Erro ao ler contexto de segurança:</target>
-
-<source>Error writing security context:</source>
-<target>Erro ao escrever contexto de segurança:</target>
-
-<source>Error copying file permissions:</source>
-<target>Erro ao copiar permissões do arquivo:</target>
-
-<source>Error creating directory:</source>
-<target>Erro ao criar diretório:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Erro ao copiar links simbólicos:</target>
-
-<source>Error copying file:</source>
-<target>Erro ao copiar arquivo:</target>
-
-<source>Error opening file:</source>
-<target>Erro ao abrir arquivo:</target>
-
-<source>Error writing file:</source>
-<target>Erro ao escrever arquivo:</target>
-
-<source>Error reading file:</source>
-<target>Erro ao ler arquivo:</target>
-
-<source>Operation aborted!</source>
-<target>Operação cancelada!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Loop infinito quando percorrendo diretório:</target>
-
-<source>Error traversing directory:</source>
-<target>Erro ao percorrer diretório:</target>
-
-<source>Error setting privilege:</source>
-<target>Erro ao definir privilégio:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Erro ao mover para a Lixeira:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Não foi possível carregar uma DLL requerida:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Erro ao escrever no banco de dados de sincronização:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Erro ao acessar o Serviço de Cópia de Sombra de Volume!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Cópias de sombra no WOW64 não são suportadas. Por favor use a versão 64-bits do FreeFileSync.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Não foi possível determinar o nome do volume para o arquivo:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Nome do volume %x não é parte do arquivo %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 hora</pluralform>
-<pluralform>%x horas</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 dia</pluralform>
-<pluralform>%x dias</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Não foi possível ler os valores para os seguintes nós XML:</target>
-
<source>Logging</source>
-<target>Gravando log</target>
+<target>Log</target>
<source>FreeFileSync batch file</source>
<target>FreeFileSync arquivo batch</target>
@@ -477,9 +372,6 @@ A linha de comando é executada cada vez que:
<source>Batch execution</source>
<target>Execução do batch</target>
-<source>Log-messages:</source>
-<target>Log de mensagens:</target>
-
<source>Stop</source>
<target>Parar</target>
@@ -606,6 +498,24 @@ A linha de comando é executada cada vez que:
<source>Total amount of data that will be transferred</source>
<target>Volume total de dados que será transferido</target>
+<source>Operation:</source>
+<target>Operação:</target>
+
+<source>Items found:</source>
+<target>Elementos encontrados:</target>
+
+<source>Items remaining:</source>
+<target>Elementos faltantes:</target>
+
+<source>Speed:</source>
+<target>Velocidade:</target>
+
+<source>Time remaining:</source>
+<target>Tempo restante:</target>
+
+<source>Time elapsed:</source>
+<target>Tempo decorrido:</target>
+
<source>Batch job</source>
<target>Arquivo Batch</target>
@@ -654,32 +564,14 @@ A linha de comando é executada cada vez que:
<source>&Cancel</source>
<target>&Cancelar</target>
-<source>Operation:</source>
-<target>Operação:</target>
-
-<source>Items found:</source>
-<target>Elementos encontrados:</target>
-
-<source>Items remaining:</source>
-<target>Elementos faltantes:</target>
-
-<source>Speed:</source>
-<target>Velocidade:</target>
-
-<source>Time remaining:</source>
-<target>Tempo restante:</target>
-
-<source>Time elapsed:</source>
-<target>Tempo passado:</target>
-
<source>Select variant:</source>
<target>Selecione um modo:</target>
<source><Automatic></source>
<target><Automático></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identifica e propaga mudanças em ambos os lados utilizando um banco de dados. Exclusões e conflitos serão detectados automaticamente.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identifica e propaga as mudanças em ambos os lados usando um banco de dados. Arquivos apagados, renomeados e conflitantes são detectados automaticamente.</target>
<source>Mirror ->></source>
<target>Espelhar ->></target>
@@ -901,27 +793,19 @@ Excluir: \stuff\temp\*
<target>Cópia de arquivo transacional</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Escreve para um arquivo temporário primeiro (*.ffs_tmp) e depois o renomeia. Isto garante um estado consistente mesmo em caso de erro fatal.</target>
<source>Copy locked files</source>
<target>Copiar arquivos bloqueados (em uso)</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Copia os arquivos compartilhados ou bloqueados (em uso) usando o Serviço de Cópia de Sombra de Volume (Requer direitos de Administrador)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Copia os arquivos compartilhados ou bloqueados (em uso) usando o Serviço de Cópia de Sombra de Volume (Requer direitos de Administrador)</target>
<source>Copy file access permissions</source>
<target>Copiar permissões de acesso aos arquivos</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Transfere as permissões de arquivos e diretórios (Requer direitos de Administrador)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Transfere as permissões de arquivos e diretórios (Requer direitos de Administrador)</target>
<source>Hidden dialogs:</source>
<target>Diálogos ocultados:</target>
@@ -953,6 +837,9 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>&Find next</source>
<target>&Localizar próxima</target>
+<source>Operation aborted!</source>
+<target>Operação cancelada!</target>
+
<source>Main bar</source>
<target>Barra principal</target>
@@ -993,16 +880,16 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<target>Autoajustar colunas</target>
<source>Icon size:</source>
-<target></target>
+<target>Tamanho do ícone:</target>
<source>Small</source>
-<target></target>
+<target>Pequeno</target>
<source>Medium</source>
-<target></target>
+<target>Médio</target>
<source>Large</source>
-<target></target>
+<target>Grande</target>
<source>Include all rows</source>
<target>Incluir todas as linhas</target>
@@ -1130,6 +1017,9 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>File list exported!</source>
<target>Lista de arquivos exportada!</target>
+<source>Error writing file:</source>
+<target>Erro ao escrever arquivo:</target>
+
<source>Batch file created successfully!</source>
<target>Arquivo batch criado com sucesso!</target>
@@ -1229,9 +1119,6 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>Filter: Single pair</source>
<target>Filtro: Apenas um par</target>
-<source>Ignore</source>
-<target>Ignorar</target>
-
<source>Direct</source>
<target>Direcionar</target>
@@ -1295,6 +1182,105 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>Move files into a time-stamped subdirectory</source>
<target>Mover arquivos para um subdiretório com carimbo de tempo</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 hora</pluralform>
+<pluralform>%x horas</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 dia</pluralform>
+<pluralform>%x dias</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Não foi possível inicializar o monitoramento de diretórios:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Erro ao monitorar os diretórios.</target>
+
+<source>Conversion error:</source>
+<target>Erro de conversão:</target>
+
+<source>Error deleting file:</source>
+<target>Erro ao apagar arquivo:</target>
+
+<source>Error moving file:</source>
+<target>Erro ao mover arquivo:</target>
+
+<source>Target file already existing!</source>
+<target>Arquivo de destino já existe!</target>
+
+<source>Error moving directory:</source>
+<target>Erro ao mover diretório:</target>
+
+<source>Target directory already existing!</source>
+<target>Diretório de destino já existe!</target>
+
+<source>Error deleting directory:</source>
+<target>Erro ao apagar diretório:</target>
+
+<source>Error changing modification time:</source>
+<target>Erro ao mudar a hora de modificação:</target>
+
+<source>Error loading library function:</source>
+<target>Erro ao carregar a biblioteca de funções:</target>
+
+<source>Error reading security context:</source>
+<target>Erro ao ler contexto de segurança:</target>
+
+<source>Error writing security context:</source>
+<target>Erro ao escrever contexto de segurança:</target>
+
+<source>Error copying file permissions:</source>
+<target>Erro ao copiar permissões do arquivo:</target>
+
+<source>Error creating directory:</source>
+<target>Erro ao criar diretório:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Erro ao copiar links simbólicos:</target>
+
+<source>Error copying file:</source>
+<target>Erro ao copiar arquivo:</target>
+
+<source>Error opening file:</source>
+<target>Erro ao abrir arquivo:</target>
+
+<source>Error traversing directory:</source>
+<target>Erro ao percorrer diretório:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Loop infinito quando percorrendo diretório:</target>
+
+<source>Error setting privilege:</source>
+<target>Erro ao definir privilégio:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Ambos os lados foram alterados desde a última sincronização!</target>
@@ -1325,9 +1311,6 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Diretórios são dependentes! Cuidado ao definir as regras de sincronização:</target>
-<source>Comparing content of files %x</source>
-<target>Comparando conteúdo do arquivo %x</target>
-
<source>Memory allocation failed!</source>
<target>Alocação de memória falhou!</target>
@@ -1343,15 +1326,15 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>Symlinks %x have the same date but a different target!</source>
<target>Links Simbólicos %x têm a mesma data mas um destino diferente!</target>
+<source>Comparing content of files %x</source>
+<target>Comparando conteúdo do arquivo %x</target>
+
<source>Comparing files by content failed.</source>
<target>Comparação de arquivos pelo conteúdo falhou.</target>
<source>Generating file list...</source>
<target>Gerando lista de arquivos...</target>
-<source>Multiple...</source>
-<target>Múltiplos...</target>
-
<source>Both sides are equal</source>
<target>Ambos os lados são iguais</target>
@@ -1370,6 +1353,12 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>Delete right file/folder</source>
<target>Apagar arquivos/pastas da direita</target>
+<source>Move file on left</source>
+<target>Mover arquivo da esquerda</target>
+
+<source>Move file on right</source>
+<target>Mover arquivo da direita</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Substituir arquivos/pastas da esquerda pelos da direita</target>
@@ -1385,6 +1374,9 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr
<source>Copy file attributes only to right</source>
<target>Copiar apenas os atributos do arquivo para a direita</target>
+<source>Multiple...</source>
+<target>Múltiplos...</target>
+
<source>Deleting file %x</source>
<target>Apagando arquivo %x</target>
diff --git a/BUILD/Languages/romanian.lng b/BUILD/Languages/romanian.lng
index f9e85c0e..c7b8958c 100644
--- a/BUILD/Languages/romanian.lng
+++ b/BUILD/Languages/romanian.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Sincronizare Inteligentă</target>
-<source>Browse</source>
-<target>Explorează</target>
-
-<source>Windows Error Code %x:</source>
-<target>Codul Erorii Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Codul Erorii Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Linie de comandă nevalidă: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Eroare la rezolvarea legăturii simbolice:</target>
-
-<source>Show pop-up</source>
-<target>Este arătat un popîc</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Se afișează o fereastră popîc [popup] la erori sau avertizări</target>
-
-<source>Ignore errors</source>
-<target>Erorile sînt ignorate</target>
-
-<source>Hide all error and warning messages</source>
-<target>Sînt ascunse toate mesajele de eroare și de avertizare</target>
-
-<source>Exit instantly</source>
-<target>Ieși imediat</target>
-
-<source>Abort synchronization immediately</source>
-<target>Abandonează imediat sincronizarea</target>
-
<source>Select alternate comparison settings</source>
<target>Selectează setările alternative de comparare</target>
@@ -101,7 +68,7 @@
<target>Configurează Filtrul</target>
<source>Customize columns</source>
-<target>Personalizează coloanele</target>
+<target>Bifează coloanele de afișat</target>
<source>Global settings</source>
<target>Setări Globale</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Selectează intervalul de timp</target>
+<source>Show pop-up</source>
+<target>Este arătat un popîc</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Se afișează o fereastră popîc [popup] la erori sau avertizări</target>
+
+<source>Ignore errors</source>
+<target>Erorile sînt ignorate</target>
+
+<source>Hide all error and warning messages</source>
+<target>Sînt ascunse toate mesajele de eroare și de avertizare</target>
+
+<source>Exit instantly</source>
+<target>Ieși imediat</target>
+
+<source>Abort synchronization immediately</source>
+<target>Abandonează imediat sincronizarea</target>
+
+<source>Browse</source>
+<target>Explorează</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Eroare la citirea din baza de date a sincronizării:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Eroare la scrierea în baza de date a sincronizării:</target>
+
+<source>Invalid command line: %x</source>
+<target>Linie de comandă nevalidă: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Codul Erorii Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Codul Erorii Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Eroare la rezolvarea legăturii simbolice:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -147,7 +153,7 @@
<target>Dată</target>
<source>Full path</source>
-<target>Cale completă</target>
+<target>Calea Completă</target>
<source>Filename</source>
<target>Numele Elementului</target>
@@ -164,17 +170,14 @@
<source>Comparison Result</source>
<target>Rezultatul Comparării</target>
-<source>Incompatible synchronization database format:</source>
-<target>Format al bazei de date necompatibil cu versiunea softului:</target>
-
<source>Initial synchronization:</source>
<target>Sincronizare inițială:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Una dintre părți nu are o filă de tip bază de date FreeFileSync:</target>
-<source>Error reading from synchronization database:</source>
-<target>Eroare la citirea din baza de date a sincronizării:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Format al bazei de date necompatibil cu versiunea softului:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Filele bază de date nu partajează o sesiune comună de sincronizare</target>
@@ -201,17 +204,23 @@
<pluralform>%x de sec</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Trage și pune un dosar peste compartimentul de mai jos sau selectează-l cu butonul de explorare</target>
+
<source>Info</source>
<target>Informații</target>
<source>Fatal Error</source>
<target>Eroare Fatală</target>
+<source>Error reading file:</source>
+<target>Eroare la citirea filei:</target>
+
<source>Scanning:</source>
<target>Scanez:</target>
<source>Encoding extended time information: %x</source>
-<target>Codarea informațiilor timpului extins: %x</target>
+<target>Codez informațiile extinse despre timp: %x</target>
<source>
<pluralform>[1 Thread]</pluralform>
@@ -226,15 +235,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Filă de configurare FreeFileSync nevalidă!</target>
-<source>File does not exist:</source>
-<target>Fila nu există:</target>
-
<source>Error parsing configuration file:</source>
<target>Eroare la parsarea filei de configurare:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Eroare la mutarea în Reciclator:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Nu pot încărca o filă DLL necesară:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Eroare la accesarea Serviciului de Conservare a Volumelor [Volume Shadow Copy]!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Realizarea de conservări (copii de rezervă) prin sistemul WOW64 nu este suportată. Folosește versiunea pe 64-biți a FreeFileSync.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Nu pot determina numele volumului pentru fila:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Numele volumului %x nu face parte din numele filei %y !</target>
+
<source>/sec</source>
<target>/sec</target>
+<source>File does not exist:</source>
+<target>Fila nu există:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Nu pot citi valorile pentru următoarele noduri XML:</target>
+
<source>S&ave configuration...</source>
<target>S&alvează Configurația...</target>
@@ -327,146 +357,8 @@ Linia de comandă este executată de fiecare dată cînd:
<source>A directory input field is empty.</source>
<target>Cel puțin unul din dosarele de comparat este nespecificat.</target>
-<source>Drag && drop</source>
-<target>Trage și lasă un dosar peste compartimentul de mai jos sau selectează-l cu butonul de explorare</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Nu pot inițializa monitorizarea dosarelor:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Eroare la monitorizarea dosarelor.</target>
-
-<source>Conversion error:</source>
-<target>Eroare de convertire:</target>
-
-<source>Error deleting file:</source>
-<target>Eroare la ștergerea filei:</target>
-
-<source>Error moving file:</source>
-<target>Eroare la mutarea filei:</target>
-
-<source>Target file already existing!</source>
-<target>Fila țintă există deja!</target>
-
-<source>Error moving directory:</source>
-<target>Eroare la mutarea dosarului:</target>
-
-<source>Target directory already existing!</source>
-<target>Dosarul țintă există deja!</target>
-
-<source>Error deleting directory:</source>
-<target>Eroare la ștergerea dosarului:</target>
-
-<source>Error changing modification time:</source>
-<target>Eroare la schimbarea datei de modificare:</target>
-
-<source>Error loading library function:</source>
-<target>Eroare la încărcarea bibliotecii de funcții:</target>
-
-<source>Error reading security context:</source>
-<target>Eroare la citirea contextului de securitate:</target>
-
-<source>Error writing security context:</source>
-<target>Eroare la scrierea contextului de securitate:</target>
-
-<source>Error copying file permissions:</source>
-<target>Eroare la copierea permisiunilor filei:</target>
-
-<source>Error creating directory:</source>
-<target>Eroare la crearea dosarului:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Eroare la copierea legăturii simbolice:</target>
-
-<source>Error copying file:</source>
-<target>Eroare la copierea filei:</target>
-
-<source>Error opening file:</source>
-<target>Eroare la deschiderea filei:</target>
-
-<source>Error writing file:</source>
-<target>Eroare la scrierea filei:</target>
-
-<source>Error reading file:</source>
-<target>Eroare la citirea filei:</target>
-
-<source>Operation aborted!</source>
-<target>Operație abandonată!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Buclă infinită la parcurgerea dosarului:</target>
-
-<source>Error traversing directory:</source>
-<target>Eroare la parcurgerea dosarului:</target>
-
-<source>Error setting privilege:</source>
-<target>Eroare la setarea privilegiului:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Eroare la mutarea în Reciclator:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Nu pot încărca o filă DLL necesară:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Eroare la scrierea în baza de date a sincronizării:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Eroare la accesarea Serviciului de Conservare a Volumelor [Volume Shadow Copy]!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Realizarea de conservări (copii de rezervă) prin sistemul WOW64 nu este suportată. Folosește versiunea pe 64-biți a FreeFileSync.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Nu pot determina numele volumului pentru fila:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Numele volumului %x nu face parte din numele filei %y !</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-<pluralform>%x de min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 oră</pluralform>
-<pluralform>%x ore</pluralform>
-<pluralform>%x de ore</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 zi</pluralform>
-<pluralform>%x zile</pluralform>
-<pluralform>%x de zile</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Nu pot citi valorile pentru următoarele noduri XML:</target>
-
<source>Logging</source>
-<target>Jurnalizez</target>
+<target>Jurnal</target>
<source>FreeFileSync batch file</source>
<target>Filă cu set de comenzi FreeFileSync</target>
@@ -483,9 +375,6 @@ Linia de comandă este executată de fiecare dată cînd:
<source>Batch execution</source>
<target>Execută Fila Set</target>
-<source>Log-messages:</source>
-<target>Mesaje de jurnalizare:</target>
-
<source>Stop</source>
<target>Oprește</target>
@@ -612,6 +501,24 @@ Linia de comandă este executată de fiecare dată cînd:
<source>Total amount of data that will be transferred</source>
<target>Volumul total de date care va fi transferat</target>
+<source>Operation:</source>
+<target>Operație:</target>
+
+<source>Items found:</source>
+<target>Elemente Găsite:</target>
+
+<source>Items remaining:</source>
+<target>Elemente Rămase:</target>
+
+<source>Speed:</source>
+<target>Viteză:</target>
+
+<source>Time remaining:</source>
+<target>Timp Rămas:</target>
+
+<source>Time elapsed:</source>
+<target>Timp Scurs:</target>
+
<source>Batch job</source>
<target>Sarcină Set</target>
@@ -660,32 +567,14 @@ Linia de comandă este executată de fiecare dată cînd:
<source>&Cancel</source>
<target>&Anulează</target>
-<source>Operation:</source>
-<target>Operație:</target>
-
-<source>Items found:</source>
-<target>Elemente Găsite:</target>
-
-<source>Items remaining:</source>
-<target>Elemente Rămase:</target>
-
-<source>Speed:</source>
-<target>Viteză:</target>
-
-<source>Time remaining:</source>
-<target>Timp Rămas:</target>
-
-<source>Time elapsed:</source>
-<target>Timp Scurs:</target>
-
<source>Select variant:</source>
<target>Selectează Varianta de Sincronizare:</target>
<source><Automatic></source>
<target><Sincronizare Inteligentă></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Modificările din ambele părți sînt identificate și propagate folosind o bază de date. Ștergerile și conflictele sînt detectate automat.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identificare și propagare a modificărilor din ambele părți folosind o bază de date. Ștergerile, renumirile și conflictele sînt detectate automat</target>
<source>Mirror ->></source>
<target>Clonare =>></target>
@@ -697,7 +586,7 @@ Linia de comandă este executată de fiecare dată cînd:
<target>Actualizare =></target>
<source>Copy new or updated files to right folder.</source>
-<target>Copiază în dosarul din dreapta filele actualizate sau noi.</target>
+<target>Copiere în dosarul din dreapta a filelor actualizate sau noi.</target>
<source>Custom</source>
<target>Sincronizare Personalizată</target>
@@ -907,27 +796,19 @@ Excluse: \stuff\temp\*
<target>Copiere tranzacțională a filelor</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Scrierea se face mai întîi într-o filă temporară (*.ffs_tmp), care e apoi renumită. Se garantează astfel consecvența stării filelor chiar și în cazul apariției de erori fatale.</target>
<source>Copy locked files</source>
-<target>Copiere și a filelor zăvorîte [locked]</target>
+<target>Copiere a filelor partajate [shared] sau zăvorîte [locked]</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Copiază filele partajate sau zăvorîte folosind Serviciul de Conservare a Volumelor [Volume Shadow Copy] (Necesită drepturi de Administrator)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Filele partajate sau zăvorîte sînt copiate folosind Serviciul de Conservare a Volumelor din Windows [Volume Shadow Copy] (necesită drepturi de Administrator)</target>
<source>Copy file access permissions</source>
<target>Copiază permisiunile de acces ale filelor</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrator)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Transferă permisiunile filelor și dosarelor (necesită drepturi de Administrator)</target>
<source>Hidden dialogs:</source>
<target>Casete de dialog ascunse:</target>
@@ -948,7 +829,7 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<target>Varianta Sincronizării</target>
<source>Statistics</source>
-<target>Statistici</target>
+<target>Statis.</target>
<source>Find what:</source>
<target>Găsește Asta:</target>
@@ -959,6 +840,9 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>&Find next</source>
<target>&Găsește Următorul</target>
+<source>Operation aborted!</source>
+<target>Operație abandonată!</target>
+
<source>Main bar</source>
<target>Bara Principală</target>
@@ -996,19 +880,19 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<target>Selectează intervalul de timp...</target>
<source>Auto-adjust columns</source>
-<target>Autoajustează Coloanele</target>
+<target>Ajustează Automat Coloanele</target>
<source>Icon size:</source>
-<target></target>
+<target>Mărimea Icoanelor Elementelor:</target>
<source>Small</source>
-<target></target>
+<target>Mică</target>
<source>Medium</source>
-<target></target>
+<target>Medie</target>
<source>Large</source>
-<target></target>
+<target>Mare</target>
<source>Include all rows</source>
<target>Include Toate Rîndurile</target>
@@ -1136,6 +1020,9 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>File list exported!</source>
<target>Lista de file a fost exportată!</target>
+<source>Error writing file:</source>
+<target>Eroare la scrierea filei:</target>
+
<source>Batch file created successfully!</source>
<target>Fila cu setul de comenzi a fost creată cu succces !</target>
@@ -1239,9 +1126,6 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>Filter: Single pair</source>
<target>Filtru: O singură pereche</target>
-<source>Ignore</source>
-<target>Ignoră</target>
-
<source>Direct</source>
<target>Direcționează</target>
@@ -1307,6 +1191,108 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>Move files into a time-stamped subdirectory</source>
<target>Filele sînt mutate într-un subdosar cu marcaj de timp</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+<pluralform>%x de min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 oră</pluralform>
+<pluralform>%x ore</pluralform>
+<pluralform>%x de ore</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 zi</pluralform>
+<pluralform>%x zile</pluralform>
+<pluralform>%x de zile</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Nu pot inițializa monitorizarea dosarelor:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Eroare la monitorizarea dosarelor.</target>
+
+<source>Conversion error:</source>
+<target>Eroare de convertire:</target>
+
+<source>Error deleting file:</source>
+<target>Eroare la ștergerea filei:</target>
+
+<source>Error moving file:</source>
+<target>Eroare la mutarea filei:</target>
+
+<source>Target file already existing!</source>
+<target>Fila țintă există deja!</target>
+
+<source>Error moving directory:</source>
+<target>Eroare la mutarea dosarului:</target>
+
+<source>Target directory already existing!</source>
+<target>Dosarul țintă există deja!</target>
+
+<source>Error deleting directory:</source>
+<target>Eroare la ștergerea dosarului:</target>
+
+<source>Error changing modification time:</source>
+<target>Eroare la schimbarea datei de modificare:</target>
+
+<source>Error loading library function:</source>
+<target>Eroare la încărcarea bibliotecii de funcții:</target>
+
+<source>Error reading security context:</source>
+<target>Eroare la citirea contextului de securitate:</target>
+
+<source>Error writing security context:</source>
+<target>Eroare la scrierea contextului de securitate:</target>
+
+<source>Error copying file permissions:</source>
+<target>Eroare la copierea permisiunilor filei:</target>
+
+<source>Error creating directory:</source>
+<target>Eroare la crearea dosarului:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Eroare la copierea legăturii simbolice:</target>
+
+<source>Error copying file:</source>
+<target>Eroare la copierea filei:</target>
+
+<source>Error opening file:</source>
+<target>Eroare la deschiderea filei:</target>
+
+<source>Error traversing directory:</source>
+<target>Eroare la parcurgerea dosarului:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Buclă infinită la parcurgerea dosarului:</target>
+
+<source>Error setting privilege:</source>
+<target>Eroare la setarea privilegiului:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Ambele părți s-au modificat de la ultima sincronizare!</target>
@@ -1337,9 +1323,6 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Dosarele sînt interdependente! Atenție la setarea regulilor de sincronizare:</target>
-<source>Comparing content of files %x</source>
-<target>Compar conținutul filelor %x</target>
-
<source>Memory allocation failed!</source>
<target>Alocarea memoriei a eșuat!</target>
@@ -1355,15 +1338,15 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>Symlinks %x have the same date but a different target!</source>
<target>Simlegăturile %x au dată identică, dar ținte diferite!</target>
+<source>Comparing content of files %x</source>
+<target>Compar conținutul filelor %x</target>
+
<source>Comparing files by content failed.</source>
<target>Compararea filelor după conținut a eșuat.</target>
<source>Generating file list...</source>
<target>Generez lista de file...</target>
-<source>Multiple...</source>
-<target>Multiplu...</target>
-
<source>Both sides are equal</source>
<target>Ambele părți sînt identice</target>
@@ -1382,6 +1365,12 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>Delete right file/folder</source>
<target>Șterge elementul drept</target>
+<source>Move file on left</source>
+<target>Mută fila în stînga</target>
+
+<source>Move file on right</source>
+<target>Mută fila în dreapta</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Suprascrie elementul stîng (fila/dosarul) cu cel drept</target>
@@ -1397,6 +1386,9 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat
<source>Copy file attributes only to right</source>
<target>Copiază atributele filelor doar înspre dreapta</target>
+<source>Multiple...</source>
+<target>Multiplu...</target>
+
<source>Deleting file %x</source>
<target>Șterg fila %x</target>
diff --git a/BUILD/Languages/russian.lng b/BUILD/Languages/russian.lng
index 1a4965e8..75da2588 100644
--- a/BUILD/Languages/russian.lng
+++ b/BUILD/Languages/russian.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Автоматическая синхронизация</target>
-<source>Browse</source>
-<target>Обзор</target>
-
-<source>Windows Error Code %x:</source>
-<target>Код ошибки Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Код ошибки Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Неверная командная строка: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Ошибка при решении символической ссылки:</target>
-
-<source>Show pop-up</source>
-<target>Показывать всплывающие окна</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Показывать всплывающие окна при ошибках и замечаниях</target>
-
-<source>Ignore errors</source>
-<target>Игнорировать ошибки</target>
-
-<source>Hide all error and warning messages</source>
-<target>Скрывать все ошибки и сообщения с предупреждениями</target>
-
-<source>Exit instantly</source>
-<target>Выйти немедленно</target>
-
-<source>Abort synchronization immediately</source>
-<target>Отменить синхронизацию немедленно</target>
-
<source>Select alternate comparison settings</source>
<target>Выбрать альтернативные настройки сравнения</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Выберите промежуток времени</target>
+<source>Show pop-up</source>
+<target>Показывать всплывающие окна</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Показывать всплывающие окна при ошибках и замечаниях</target>
+
+<source>Ignore errors</source>
+<target>Игнорировать ошибки</target>
+
+<source>Hide all error and warning messages</source>
+<target>Скрывать все ошибки и сообщения с предупреждениями</target>
+
+<source>Exit instantly</source>
+<target>Выйти немедленно</target>
+
+<source>Abort synchronization immediately</source>
+<target>Отменить синхронизацию немедленно</target>
+
+<source>Browse</source>
+<target>Обзор</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Ошибка при чтении из базы данных синхронизации:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Ошибка при записи в базу данных синхронизации:</target>
+
+<source>Invalid command line: %x</source>
+<target>Неверная командная строка: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Код ошибки Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Код ошибки Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Ошибка при решении символической ссылки:</target>
+
<source>%x MB</source>
<target>%x МБ</target>
@@ -164,17 +170,14 @@
<source>Comparison Result</source>
<target>Результаты сравнения</target>
-<source>Incompatible synchronization database format:</source>
-<target>Несовместимый формат базы данных синхронизации:</target>
-
<source>Initial synchronization:</source>
<target>Первоначальная синхронизация:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Одного из файлов баз данных FreeFileSync еще не существует:</target>
-<source>Error reading from synchronization database:</source>
-<target>Ошибка при чтении из базы данных синхронизации:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Несовместимый формат базы данных синхронизации:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Файлы баз данных не имеют общей сессии синхронизации:</target>
@@ -201,12 +204,18 @@
<pluralform>%x секунд</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Drag && drop</target>
+
<source>Info</source>
<target>Информация</target>
<source>Fatal Error</source>
<target>Критическая ошибка</target>
+<source>Error reading file:</source>
+<target>Ошибка при чтении файла:</target>
+
<source>Scanning:</source>
<target>Сканирую:</target>
@@ -226,15 +235,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Неверный файл конфигурации FreeFileSync!</target>
-<source>File does not exist:</source>
-<target>Файл не существует:</target>
-
<source>Error parsing configuration file:</source>
<target>Ошибка при анализе файла настроек синхронизации:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Ошибка при перемещении в "Корзину":</target>
+
+<source>Could not load a required DLL:</source>
+<target>Не удалось загрузить необходимые DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Ошибка доступа к службе Теневого Копирования Тома!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Создание теневых копий на WOW64 не поддерживается. Пожалуйста, используйте FreeFileSync 64-разрядной версии.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Не удалось определить название тома для файла:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Имя тома %x не является частью имени файла %y!</target>
+
<source>/sec</source>
<target>/с</target>
+<source>File does not exist:</source>
+<target>Файл не существует:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Не удалось прочитать значения для следующих XML записей:</target>
+
<source>S&ave configuration...</source>
<target>Сохранить настройки синхронизации...</target>
@@ -327,144 +357,6 @@ The command line is executed each time:
<source>A directory input field is empty.</source>
<target>Поле ввода пути папки пустое.</target>
-<source>Drag && drop</source>
-<target>Drag && drop</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Не удалось инициализировать папку для мониторинга:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Ошибка при мониторинге папок.</target>
-
-<source>Conversion error:</source>
-<target>Ошибка преобразования:</target>
-
-<source>Error deleting file:</source>
-<target>Ошибка при удалении файла:</target>
-
-<source>Error moving file:</source>
-<target>Ошибка перемещения файла:</target>
-
-<source>Target file already existing!</source>
-<target>Конечный файл уже существует!</target>
-
-<source>Error moving directory:</source>
-<target>Ошибка перемещения папки:</target>
-
-<source>Target directory already existing!</source>
-<target>Конечная папка уже существует!</target>
-
-<source>Error deleting directory:</source>
-<target>Ошибка при удалении папки:</target>
-
-<source>Error changing modification time:</source>
-<target>Ошибка при изменении времени модификации файла:</target>
-
-<source>Error loading library function:</source>
-<target>Ошибка при загрузке функции библиотеки:</target>
-
-<source>Error reading security context:</source>
-<target>Ошибка при чтении контекста безобасности:</target>
-
-<source>Error writing security context:</source>
-<target>Ошибка при записи контекста безобасности:</target>
-
-<source>Error copying file permissions:</source>
-<target>Ошибка при копировании прав доступа:</target>
-
-<source>Error creating directory:</source>
-<target>Ошибка при создании папки:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Ошибка при копировании символьной ссылки:</target>
-
-<source>Error copying file:</source>
-<target>Ошибка при копировании файла:</target>
-
-<source>Error opening file:</source>
-<target>Ошибка при открытии файла:</target>
-
-<source>Error writing file:</source>
-<target>Ошибка при записи файла:</target>
-
-<source>Error reading file:</source>
-<target>Ошибка при чтении файла:</target>
-
-<source>Operation aborted!</source>
-<target>Операция отменена!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Зацикливание при встрече пересекающихся путей:</target>
-
-<source>Error traversing directory:</source>
-<target>Ошибка при пересечении папок:</target>
-
-<source>Error setting privilege:</source>
-<target>Ошибка установки привилегий:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Ошибка при перемещении в "Корзину":</target>
-
-<source>Could not load a required DLL:</source>
-<target>Не удалось загрузить необходимые DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Ошибка при записи в базу данных синхронизации:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Ошибка доступа к службе Теневого Копирования Тома!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Создание теневых копий на WOW64 не поддерживается. Пожалуйста, используйте FreeFileSync 64-разрядной версии.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Не удалось определить название тома для файла:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Имя тома %x не является частью имени файла %y!</target>
-
-<source>%x TB</source>
-<target>%x ТБ</target>
-
-<source>%x PB</source>
-<target>%x ПБ</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>%x минута</pluralform>
-<pluralform>%x минуты</pluralform>
-<pluralform>%x минут</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>%x час</pluralform>
-<pluralform>%x часа</pluralform>
-<pluralform>%x часов</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>%x день</pluralform>
-<pluralform>%x дня</pluralform>
-<pluralform>%x дней</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Не удалось прочитать значения для следующих XML записей:</target>
-
<source>Logging</source>
<target>Лог-файлы</target>
@@ -483,9 +375,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>Выполнение пакетного задания</target>
-<source>Log-messages:</source>
-<target>Лог-сообщения:</target>
-
<source>Stop</source>
<target>Стоп</target>
@@ -615,6 +504,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>Общий объем данных, который будет передаваться</target>
+<source>Operation:</source>
+<target>Операция:</target>
+
+<source>Items found:</source>
+<target>Элементов найдено:</target>
+
+<source>Items remaining:</source>
+<target>Элементов осталось:</target>
+
+<source>Speed:</source>
+<target>Скорость:</target>
+
+<source>Time remaining:</source>
+<target>Времени осталось:</target>
+
+<source>Time elapsed:</source>
+<target>Времени прошло:</target>
+
<source>Batch job</source>
<target>Пакетное задание</target>
@@ -663,32 +570,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>&Отмена</target>
-<source>Operation:</source>
-<target>Операция:</target>
-
-<source>Items found:</source>
-<target>Элементов найдено:</target>
-
-<source>Items remaining:</source>
-<target>Элементов осталось:</target>
-
-<source>Speed:</source>
-<target>Скорость:</target>
-
-<source>Time remaining:</source>
-<target>Времени осталось:</target>
-
-<source>Time elapsed:</source>
-<target>Времени прошло:</target>
-
<source>Select variant:</source>
<target>Выберите вариант:</target>
<source><Automatic></source>
<target><Автоматический></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Выявление и распространение изменений на обеих сторонах с использованием базы данных. Удаленные файлы и конфликты определяются автоматически.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Выявление и распространение изменений на обе стороны, используя базу данных. Удаленные, переименованные и конфликтные файлы определяются автоматически.</target>
<source>Mirror ->></source>
<target>Зеркало ->></target>
@@ -910,22 +799,14 @@ Exclude: \stuff\temp\*
<source>Copy locked files</source>
<target>Копирование заблокированных файлов</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Копирование общих или заблокированных файлов с использованием службы Теневого Копирования Тома (требуются права Администратора)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Копирование общих или заблокированных файлов с использованием службы Теневого Копирования Тома (требуются права Администратора)</target>
<source>Copy file access permissions</source>
<target>Копирование прав доступа к файлам</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Передача прав доступа к файлам/папкам (требуются права Администратора)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Передача прав доступа к файлам/папкам (требуются права Администратора)</target>
<source>Hidden dialogs:</source>
<target>Скрытые диалоги</target>
@@ -957,6 +838,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>&Найти далее</target>
+<source>Operation aborted!</source>
+<target>Операция отменена!</target>
+
<source>Main bar</source>
<target>Главная панель</target>
@@ -1134,6 +1018,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>Список файлов экспортирован!</target>
+<source>Error writing file:</source>
+<target>Ошибка при записи файла:</target>
+
<source>Batch file created successfully!</source>
<target>Файл пакетного задания создан успешно!</target>
@@ -1237,9 +1124,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>Фильтр: Одна пара</target>
-<source>Ignore</source>
-<target>Игнорировать</target>
-
<source>Direct</source>
<target>Прямое</target>
@@ -1308,6 +1192,108 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>Перемещать файлы в заданную папку (можно создавать архивные версии удаленных файлов)</target>
+<source>%x TB</source>
+<target>%x ТБ</target>
+
+<source>%x PB</source>
+<target>%x ПБ</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>%x минута</pluralform>
+<pluralform>%x минуты</pluralform>
+<pluralform>%x минут</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>%x час</pluralform>
+<pluralform>%x часа</pluralform>
+<pluralform>%x часов</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>%x день</pluralform>
+<pluralform>%x дня</pluralform>
+<pluralform>%x дней</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Не удалось инициализировать папку для мониторинга:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Ошибка при мониторинге папок.</target>
+
+<source>Conversion error:</source>
+<target>Ошибка преобразования:</target>
+
+<source>Error deleting file:</source>
+<target>Ошибка при удалении файла:</target>
+
+<source>Error moving file:</source>
+<target>Ошибка перемещения файла:</target>
+
+<source>Target file already existing!</source>
+<target>Конечный файл уже существует!</target>
+
+<source>Error moving directory:</source>
+<target>Ошибка перемещения папки:</target>
+
+<source>Target directory already existing!</source>
+<target>Конечная папка уже существует!</target>
+
+<source>Error deleting directory:</source>
+<target>Ошибка при удалении папки:</target>
+
+<source>Error changing modification time:</source>
+<target>Ошибка при изменении времени модификации файла:</target>
+
+<source>Error loading library function:</source>
+<target>Ошибка при загрузке функции библиотеки:</target>
+
+<source>Error reading security context:</source>
+<target>Ошибка при чтении контекста безобасности:</target>
+
+<source>Error writing security context:</source>
+<target>Ошибка при записи контекста безобасности:</target>
+
+<source>Error copying file permissions:</source>
+<target>Ошибка при копировании прав доступа:</target>
+
+<source>Error creating directory:</source>
+<target>Ошибка при создании папки:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Ошибка при копировании символьной ссылки:</target>
+
+<source>Error copying file:</source>
+<target>Ошибка при копировании файла:</target>
+
+<source>Error opening file:</source>
+<target>Ошибка при открытии файла:</target>
+
+<source>Error traversing directory:</source>
+<target>Ошибка при пересечении папок:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Зацикливание при встрече пересекающихся путей:</target>
+
+<source>Error setting privilege:</source>
+<target>Ошибка установки привилегий:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Со времени последней синхронизации с обеих сторон произошли изменения!</target>
@@ -1341,9 +1327,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Зависимые папки! Будьте внимательны при настройке правил синхронизации:</target>
-<source>Comparing content of files %x</source>
-<target>Сравнение содержания файлов %x</target>
-
<source>Memory allocation failed!</source>
<target>Ошибка выделения памяти! (Не хватает памяти)</target>
@@ -1359,15 +1342,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>Символьная ссылка %x имеет ту же дату, но различное содержание!</target>
+<source>Comparing content of files %x</source>
+<target>Сравнение содержания файлов %x</target>
+
<source>Comparing files by content failed.</source>
<target>Сравнение файлов по содержимому провалено.</target>
<source>Generating file list...</source>
<target>Создание списка файлов...</target>
-<source>Multiple...</source>
-<target>Различные варианты синхронизации</target>
-
<source>Both sides are equal</source>
<target>Обе стороны равны</target>
@@ -1386,6 +1369,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>Удалить файл/папку справа</target>
+<source>Move file on left</source>
+<target>Переместить файл налево</target>
+
+<source>Move file on right</source>
+<target>Переместить файл направо</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Перезаписать файл/папку слева на аналогичную из правой части</target>
@@ -1401,6 +1390,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>Скопировать только атрибуты файла направо</target>
+<source>Multiple...</source>
+<target>Различные варианты синхронизации</target>
+
<source>Deleting file %x</source>
<target>Удаление файла %x</target>
diff --git a/BUILD/Languages/slovenian.lng b/BUILD/Languages/slovenian.lng
index bf917426..4e6683db 100644
--- a/BUILD/Languages/slovenian.lng
+++ b/BUILD/Languages/slovenian.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Avtomatizirana sinhronizacija</target>
-<source>Browse</source>
-<target>Brskaj</target>
-
-<source>Windows Error Code %x:</source>
-<target>Windows koda napake %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Linux koda napake %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Napačna ukazna vrstica: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Napaka pri razreševanju simbolične povezave:</target>
-
-<source>Show pop-up</source>
-<target>Prikaži pojavno okno</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Prikaži pojavne napaka ali opozorila</target>
-
-<source>Ignore errors</source>
-<target>Ignoriraj napake</target>
-
-<source>Hide all error and warning messages</source>
-<target>Skrij vsa obvestila o napakah in opozorilih</target>
-
-<source>Exit instantly</source>
-<target>Zapusti v trenutku</target>
-
-<source>Abort synchronization immediately</source>
-<target>Takoj prekini sinhronizacijo</target>
-
<source>Select alternate comparison settings</source>
<target>Izberite alternativne nastavitve primerjanja</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Izberite časovni okvir</target>
+<source>Show pop-up</source>
+<target>Prikaži pojavno okno</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Prikaži pojavne napaka ali opozorila</target>
+
+<source>Ignore errors</source>
+<target>Ignoriraj napake</target>
+
+<source>Hide all error and warning messages</source>
+<target>Skrij vsa obvestila o napakah in opozorilih</target>
+
+<source>Exit instantly</source>
+<target>Zapusti v trenutku</target>
+
+<source>Abort synchronization immediately</source>
+<target>Takoj prekini sinhronizacijo</target>
+
+<source>Browse</source>
+<target>Brskaj</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Napaka pri branju iz sinhronizacijske podatkovne baze:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Napaka pri pisanju v sinhronizacijsko podatkovno bazo:</target>
+
+<source>Invalid command line: %x</source>
+<target>Napačna ukazna vrstica: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows koda napake %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux koda napake %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Napaka pri razreševanju simbolične povezave:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -165,17 +171,14 @@
<source>Comparison Result</source>
<target>Rezultati primerjave</target>
-<source>Incompatible synchronization database format:</source>
-<target>Nekompatibilen format sinhronizacijske podatkovne baze:</target>
-
<source>Initial synchronization:</source>
<target>Začetna sinhronizacija:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Ena od FreeFileSync datotek podatkovne baze še en obstaja:</target>
-<source>Error reading from synchronization database:</source>
-<target>Napaka pri branju iz sinhronizacijske podatkovne baze:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Nekompatibilen format sinhronizacijske podatkovne baze:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Datoteke podatkovne baze si ne delijo skupne sinhronizacijske seje:</target>
@@ -203,12 +206,18 @@
<pluralform>%x sek</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Povleci && spusti</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Usodna napaka</target>
+<source>Error reading file:</source>
+<target>Napaka pri branju datoteke:</target>
+
<source>Scanning:</source>
<target>Pregledujem:</target>
@@ -229,15 +238,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Neveljavna FreeFileSync nastavitvena datoteka!</target>
-<source>File does not exist:</source>
-<target>Datoteka ne obstaja:</target>
-
<source>Error parsing configuration file:</source>
<target>Napaka pri preverjanju konfiguracijske datoteke:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Napaka pri premikanju v Koš:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Ne morem naložiti zahtevano DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Napaka pri dostopu do servisa senčnih kopij!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Ustvarjanje senčnih kopij na WOW63 ni podprto. Prosimo uporabite 64-bitno FreeFileSync različico.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Ne morem določiti imena volumna za datoteko:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Ime volumna %x ni del imena datoteke %y!</target>
+
<source>/sec</source>
<target>/sek</target>
+<source>File does not exist:</source>
+<target>Datoteka ne obstaja:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Ne morem brati vrednosti za naslednja XML vozlišča:</target>
+
<source>S&ave configuration...</source>
<target>Shr&ani konfiguracijo...</target>
@@ -330,147 +360,6 @@ Ukazna vrstica se izvrši vsakič ko:
<source>A directory input field is empty.</source>
<target>Vpisno polje za imenik je prazno.</target>
-<source>Drag && drop</source>
-<target>Povleci && spusti</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Ne morem začeti nadzorovanja imenikov:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Napaka pri nadzorovanju imenikov.</target>
-
-<source>Conversion error:</source>
-<target>Napaka pri pretvorbi:</target>
-
-<source>Error deleting file:</source>
-<target>Napaka pri brisanju datoteke:</target>
-
-<source>Error moving file:</source>
-<target>Napaka pri premikanju datoteke:</target>
-
-<source>Target file already existing!</source>
-<target>Ciljna datoteka že obstaja!</target>
-
-<source>Error moving directory:</source>
-<target>Napaka pri premikanju imenika:</target>
-
-<source>Target directory already existing!</source>
-<target>Ciljni imenik že obstaja!</target>
-
-<source>Error deleting directory:</source>
-<target>Napaka pri brisanju imenika:</target>
-
-<source>Error changing modification time:</source>
-<target>Napaka pri spreminjanju časa modifikacije:</target>
-
-<source>Error loading library function:</source>
-<target>Napaka pri nalaganju funkcije iz knjižnice:</target>
-
-<source>Error reading security context:</source>
-<target>Napaka pri branju varnostne skladnosti:</target>
-
-<source>Error writing security context:</source>
-<target>Napaka pri pisanju varnostne skladnosti:</target>
-
-<source>Error copying file permissions:</source>
-<target>Napaka pri kopiranju datotečnih dovoljenj:</target>
-
-<source>Error creating directory:</source>
-<target>Napaka pri ustvarjanju imenika:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Napaka pri kopiranju simboličnih povezav:</target>
-
-<source>Error copying file:</source>
-<target>Napaka pri kopiranju datoteke:</target>
-
-<source>Error opening file:</source>
-<target>Napaka pri odpiranju datoteke:</target>
-
-<source>Error writing file:</source>
-<target>Napaka pri pisanju datoteke:</target>
-
-<source>Error reading file:</source>
-<target>Napaka pri branju datoteke:</target>
-
-<source>Operation aborted!</source>
-<target>Operacija prekinjena!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Neskončna zanka pri prehodu imenika:</target>
-
-<source>Error traversing directory:</source>
-<target>Napaka pri prehajanju imenika:</target>
-
-<source>Error setting privilege:</source>
-<target>Napaka pri nastavljanju privilegija:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Napaka pri premikanju v Koš:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Ne morem naložiti zahtevano DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Napaka pri pisanju v sinhronizacijsko podatkovno bazo:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Napaka pri dostopu do servisa senčnih kopij!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Ustvarjanje senčnih kopij na WOW63 ni podprto. Prosimo uporabite 64-bitno FreeFileSync različico.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Ne morem določiti imena volumna za datoteko:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Ime volumna %x ni del imena datoteke %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-<pluralform>%x min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 ura</pluralform>
-<pluralform>%x uri</pluralform>
-<pluralform>%x ure</pluralform>
-<pluralform>%x ur</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 dan</pluralform>
-<pluralform>%x dni</pluralform>
-<pluralform>%x dni</pluralform>
-<pluralform>%x dni</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Ne morem brati vrednosti za naslednja XML vozlišča:</target>
-
<source>Logging</source>
<target>Beleženje</target>
@@ -489,9 +378,6 @@ Ukazna vrstica se izvrši vsakič ko:
<source>Batch execution</source>
<target>Paketno izvajanje</target>
-<source>Log-messages:</source>
-<target>Sporočila beleženja:</target>
-
<source>Stop</source>
<target>Ustavi</target>
@@ -618,6 +504,24 @@ Ukazna vrstica se izvrši vsakič ko:
<source>Total amount of data that will be transferred</source>
<target>Količina podatkov, ki bo prenešena</target>
+<source>Operation:</source>
+<target>Operacija:</target>
+
+<source>Items found:</source>
+<target>Najdenih elementov:</target>
+
+<source>Items remaining:</source>
+<target>Preostalih elementov:</target>
+
+<source>Speed:</source>
+<target>Hitrost:</target>
+
+<source>Time remaining:</source>
+<target>Preostali čas:</target>
+
+<source>Time elapsed:</source>
+<target>Pretečen čas:</target>
+
<source>Batch job</source>
<target>Paketno opravilo</target>
@@ -666,32 +570,14 @@ Ukazna vrstica se izvrši vsakič ko:
<source>&Cancel</source>
<target>&Prekliči</target>
-<source>Operation:</source>
-<target>Operacija:</target>
-
-<source>Items found:</source>
-<target>Najdenih elementov:</target>
-
-<source>Items remaining:</source>
-<target>Preostalih elementov:</target>
-
-<source>Speed:</source>
-<target>Hitrost:</target>
-
-<source>Time remaining:</source>
-<target>Preostali čas:</target>
-
-<source>Time elapsed:</source>
-<target>Pretečen čas:</target>
-
<source>Select variant:</source>
<target>Izberite varianto:</target>
<source><Automatic></source>
<target><Samodejno></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Prepoznaj in širi spremembe na obeh straneh z uporabo podatkovne baze. Izbrisi in spori so zaznani samodejno.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identificiraj in promoviraj spremembe na obeh straneh z uporabo podatkovne baze. Izbrisi, preimenovanja in spori so samodejno zaznani.</target>
<source>Mirror ->></source>
<target>Zrcalno ->></target>
@@ -913,27 +799,19 @@ Izključi: \stuff\temp\*
<target>Transakcijsko kopiranje datotek</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Najprej zapisuj v začasno datoteko (*.ffs_tmp) in nato preimenuj. To zagotavlja dosledno stanje celo v primeru usodne napake.</target>
<source>Copy locked files</source>
<target>Kopiraj zaklenjene datoteke</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Kopiraj deljene ali zaklenjene datoteke z uporabo servisa Shadow Copy (Zahteva pravice skrbnika)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopiraj deljene ali zaklenjene datoteke z uporabo servisa Shadow Copy (Zahteva pravice skrbnika)</target>
<source>Copy file access permissions</source>
<target>Kopiraj dovoljenja dostopov datoteke</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)</target>
<source>Hidden dialogs:</source>
<target>Skriti pogovori:</target>
@@ -965,6 +843,9 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>&Find next</source>
<target>&Najdi naslednje</target>
+<source>Operation aborted!</source>
+<target>Operacija prekinjena!</target>
+
<source>Main bar</source>
<target>Glavna vrstica</target>
@@ -1005,16 +886,16 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<target>Samo-prilagodi stolpce</target>
<source>Icon size:</source>
-<target></target>
+<target>Velikost ikone:</target>
<source>Small</source>
-<target></target>
+<target>Majhna</target>
<source>Medium</source>
-<target></target>
+<target>Srednja</target>
<source>Large</source>
-<target></target>
+<target>Velika</target>
<source>Include all rows</source>
<target>Vključi se vrstice</target>
@@ -1142,6 +1023,9 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>File list exported!</source>
<target>Seznam datotek je bil izvožen!</target>
+<source>Error writing file:</source>
+<target>Napaka pri pisanju datoteke:</target>
+
<source>Batch file created successfully!</source>
<target>Paketna datoteka je bila uspešno ustvarjena!</target>
@@ -1249,9 +1133,6 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>Filter: Single pair</source>
<target>Filtriraj: En sam par</target>
-<source>Ignore</source>
-<target>Ignoriraj</target>
-
<source>Direct</source>
<target>Neposredno</target>
@@ -1319,6 +1200,111 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>Move files into a time-stamped subdirectory</source>
<target>Premakni datoteke v časovno-označen podimenik</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+<pluralform>%x min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 ura</pluralform>
+<pluralform>%x uri</pluralform>
+<pluralform>%x ure</pluralform>
+<pluralform>%x ur</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 dan</pluralform>
+<pluralform>%x dni</pluralform>
+<pluralform>%x dni</pluralform>
+<pluralform>%x dni</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Ne morem začeti nadzorovanja imenikov:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Napaka pri nadzorovanju imenikov.</target>
+
+<source>Conversion error:</source>
+<target>Napaka pri pretvorbi:</target>
+
+<source>Error deleting file:</source>
+<target>Napaka pri brisanju datoteke:</target>
+
+<source>Error moving file:</source>
+<target>Napaka pri premikanju datoteke:</target>
+
+<source>Target file already existing!</source>
+<target>Ciljna datoteka že obstaja!</target>
+
+<source>Error moving directory:</source>
+<target>Napaka pri premikanju imenika:</target>
+
+<source>Target directory already existing!</source>
+<target>Ciljni imenik že obstaja!</target>
+
+<source>Error deleting directory:</source>
+<target>Napaka pri brisanju imenika:</target>
+
+<source>Error changing modification time:</source>
+<target>Napaka pri spreminjanju časa modifikacije:</target>
+
+<source>Error loading library function:</source>
+<target>Napaka pri nalaganju funkcije iz knjižnice:</target>
+
+<source>Error reading security context:</source>
+<target>Napaka pri branju varnostne skladnosti:</target>
+
+<source>Error writing security context:</source>
+<target>Napaka pri pisanju varnostne skladnosti:</target>
+
+<source>Error copying file permissions:</source>
+<target>Napaka pri kopiranju datotečnih dovoljenj:</target>
+
+<source>Error creating directory:</source>
+<target>Napaka pri ustvarjanju imenika:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Napaka pri kopiranju simboličnih povezav:</target>
+
+<source>Error copying file:</source>
+<target>Napaka pri kopiranju datoteke:</target>
+
+<source>Error opening file:</source>
+<target>Napaka pri odpiranju datoteke:</target>
+
+<source>Error traversing directory:</source>
+<target>Napaka pri prehajanju imenika:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Neskončna zanka pri prehodu imenika:</target>
+
+<source>Error setting privilege:</source>
+<target>Napaka pri nastavljanju privilegija:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Obe strani sta se spremenili od zadnje sinhronizacije!</target>
@@ -1349,9 +1335,6 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Imeniki so v odvisnosti! Bodite pozorni, ko nastavljate sinhronizacijska pravila:</target>
-<source>Comparing content of files %x</source>
-<target>Primerjam vsebino datotek %x</target>
-
<source>Memory allocation failed!</source>
<target>Neuspešno dodeljevanje pomnilnika!</target>
@@ -1367,15 +1350,15 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>Symlinks %x have the same date but a different target!</source>
<target>Simbolične povezave %x imajo isti datum, vendar različni cilj!</target>
+<source>Comparing content of files %x</source>
+<target>Primerjam vsebino datotek %x</target>
+
<source>Comparing files by content failed.</source>
<target>Primerjava datotek po vsebini ni uspela.</target>
<source>Generating file list...</source>
<target>Ustvarjam seznam datotek...</target>
-<source>Multiple...</source>
-<target>Večkratno...</target>
-
<source>Both sides are equal</source>
<target>Obe strani sta enaki</target>
@@ -1394,6 +1377,12 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>Delete right file/folder</source>
<target>Izbriši desno datoteko/mapo</target>
+<source>Move file on left</source>
+<target>Premakni datoteko na levo</target>
+
+<source>Move file on right</source>
+<target>Premakni datoteko na desno</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Prepiši levo datoteko/mapo s tisto na desni</target>
@@ -1409,6 +1398,9 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)
<source>Copy file attributes only to right</source>
<target>Kopiraj atribute datoteke samo na desno</target>
+<source>Multiple...</source>
+<target>Večkratno...</target>
+
<source>Deleting file %x</source>
<target>Brisanje datoteke %x</target>
diff --git a/BUILD/Languages/spanish.lng b/BUILD/Languages/spanish.lng
index f1072972..574aeca1 100644
--- a/BUILD/Languages/spanish.lng
+++ b/BUILD/Languages/spanish.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Sincronización Automática</target>
-<source>Browse</source>
-<target>Examinar</target>
-
-<source>Windows Error Code %x:</source>
-<target>Código de error de Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Código de error de Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Línea de comandos errónea: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Error al resolver enlace simbólico:</target>
-
-<source>Show pop-up</source>
-<target>Mostrar ventana emergente</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Mostrar ventana emergente de errores o avisos</target>
-
-<source>Ignore errors</source>
-<target>Ignorar errores</target>
-
-<source>Hide all error and warning messages</source>
-<target>Ocultar todos los mensajes de error y aviso</target>
-
-<source>Exit instantly</source>
-<target>Salir inmediatamente</target>
-
-<source>Abort synchronization immediately</source>
-<target>Abortar sincronización inmediatamente</target>
-
<source>Select alternate comparison settings</source>
<target>Seleccionar opciones alternativas de comparación</target>
@@ -113,7 +80,46 @@
<target>Buscar</target>
<source>Select time span</source>
-<target></target>
+<target>Seleccionar duración</target>
+
+<source>Show pop-up</source>
+<target>Mostrar ventana emergente</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Mostrar ventana emergente de errores o avisos</target>
+
+<source>Ignore errors</source>
+<target>Ignorar errores</target>
+
+<source>Hide all error and warning messages</source>
+<target>Ocultar todos los mensajes de error y aviso</target>
+
+<source>Exit instantly</source>
+<target>Salir inmediatamente</target>
+
+<source>Abort synchronization immediately</source>
+<target>Abortar sincronización inmediatamente</target>
+
+<source>Browse</source>
+<target>Examinar</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Error al leer de la base de datos de sincronización:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Error al escribir en la base de datos de sincronización:</target>
+
+<source>Invalid command line: %x</source>
+<target>Línea de comandos errónea: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Código de error de Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Código de error de Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Error al resolver enlace simbólico:</target>
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Resultado de la comparación</target>
-<source>Incompatible synchronization database format:</source>
-<target>Formato de base de datos de sincronización incompatible:</target>
-
<source>Initial synchronization:</source>
<target>Sincronización inicial:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Uno de los archivos de la base de datos de FreeFileSync aún no existe:</target>
-<source>Error reading from synchronization database:</source>
-<target>Error al leer de la base de datos de sincronización:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Formato de base de datos de sincronización incompatible:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Archivos de base de datos no comparten la misma sesión de sincronización:</target>
@@ -199,12 +202,18 @@
<pluralform>%x segundos</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Arrastrar y soltar</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Error fatal</target>
+<source>Error reading file:</source>
+<target>Error al leer archivo:</target>
+
<source>Scanning:</source>
<target>Escanear:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>¡Archivo de configuración de FreeFileSync inválido!</target>
-<source>File does not exist:</source>
-<target>El archivo no existe:</target>
-
<source>Error parsing configuration file:</source>
<target>Error al analizar el archivo de configuración:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Error al mover a la Papelera de Reciclaje:</target>
+
+<source>Could not load a required DLL:</source>
+<target>No se ha podido cargar el DLL solicitado:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>¡Error al acceder al servicio Volume Shadow Copy!</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>La realización de copias shadow en WOW64 no está soportado. Por favor, use la versión 64-bit de FreeFileSync.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>No se ha podido determinar el nombre del volumen para el archivo:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>El nombre del volumen %x no es una parte del nombre de archivo %y</target>
+
<source>/sec</source>
<target>/seg</target>
+<source>File does not exist:</source>
+<target>El archivo no existe:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>No se ha podido leer los valores para los siguientes nodos XML:</target>
+
<source>S&ave configuration...</source>
<target>G&uardar configuración...</target>
@@ -324,141 +354,6 @@ La línea de comandos se ejecuta cada vez:
<source>A directory input field is empty.</source>
<target>Un campo de directorio está vacío.</target>
-<source>Drag && drop</source>
-<target>Arrastrar y soltar</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>No se ha podido inicializar la visualización de directorios:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Error al visualizar los directorios.</target>
-
-<source>Conversion error:</source>
-<target>Error de conversión:</target>
-
-<source>Error deleting file:</source>
-<target>Error al borrar archivo:</target>
-
-<source>Error moving file:</source>
-<target>Error al mover archivo:</target>
-
-<source>Target file already existing!</source>
-<target>¡El archivo de destino ya existe!</target>
-
-<source>Error moving directory:</source>
-<target>Error al mover directorio:</target>
-
-<source>Target directory already existing!</source>
-<target>¡El directorio de destino ya existe!</target>
-
-<source>Error deleting directory:</source>
-<target>Error al borrar directorio:</target>
-
-<source>Error changing modification time:</source>
-<target>Error al cambiar hora de modificación:</target>
-
-<source>Error loading library function:</source>
-<target>Error al cargar la función de biblioteca:</target>
-
-<source>Error reading security context:</source>
-<target>Error al leer en contexto de seguridad:</target>
-
-<source>Error writing security context:</source>
-<target>Error al escribir en contexto de seguridad:</target>
-
-<source>Error copying file permissions:</source>
-<target>Error al copiar permisos del fichero:</target>
-
-<source>Error creating directory:</source>
-<target>Error al crear directorio:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Error al copiar enlace simbólico:</target>
-
-<source>Error copying file:</source>
-<target>Error al copiar archivo:</target>
-
-<source>Error opening file:</source>
-<target>Error al abrir archivo:</target>
-
-<source>Error writing file:</source>
-<target>Error al escribir archivo:</target>
-
-<source>Error reading file:</source>
-<target>Error al leer archivo:</target>
-
-<source>Operation aborted!</source>
-<target>¡Operación abortada!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Bucle infinito al buscar en el directorio:</target>
-
-<source>Error traversing directory:</source>
-<target>Error al buscar en el directorio:</target>
-
-<source>Error setting privilege:</source>
-<target>Error al establecer privilegios:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Error al mover a la Papelera de Reciclaje:</target>
-
-<source>Could not load a required DLL:</source>
-<target>No se ha podido cargar el DLL solicitado:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Error al escribir en la base de datos de sincronización:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>¡Error al acceder al servicio Volume Shadow Copy!</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>La realización de copias shadow en WOW64 no está soportado. Por favor, use la versión 64-bit de FreeFileSync.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>No se ha podido determinar el nombre del volumen para el archivo:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>El nombre del volumen %x no es una parte del nombre de archivo %y</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 minuto</pluralform>
-<pluralform>%x minutos</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 hora</pluralform>
-<pluralform>%x horas</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 día</pluralform>
-<pluralform>%x días</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>No se ha podido leer los valores para los siguientes nodos XML:</target>
-
<source>Logging</source>
<target>Iniciando sesión</target>
@@ -477,9 +372,6 @@ La línea de comandos se ejecuta cada vez:
<source>Batch execution</source>
<target>Ejecución batch</target>
-<source>Log-messages:</source>
-<target>Registro de mensajes:</target>
-
<source>Stop</source>
<target>Detener</target>
@@ -606,6 +498,24 @@ La línea de comandos se ejecuta cada vez:
<source>Total amount of data that will be transferred</source>
<target>Cantidad total de datos que serán transferidos</target>
+<source>Operation:</source>
+<target>Operación:</target>
+
+<source>Items found:</source>
+<target>Elementos encontrados:</target>
+
+<source>Items remaining:</source>
+<target>Elementos restantes:</target>
+
+<source>Speed:</source>
+<target>Velocidad:</target>
+
+<source>Time remaining:</source>
+<target>Tiempo restante:</target>
+
+<source>Time elapsed:</source>
+<target>Tiempo transcurrido:</target>
+
<source>Batch job</source>
<target>Tarea batch</target>
@@ -654,32 +564,14 @@ La línea de comandos se ejecuta cada vez:
<source>&Cancel</source>
<target>&Cancelar</target>
-<source>Operation:</source>
-<target>Operación:</target>
-
-<source>Items found:</source>
-<target>Elementos encontrados:</target>
-
-<source>Items remaining:</source>
-<target>Elementos restantes:</target>
-
-<source>Speed:</source>
-<target>Velocidad:</target>
-
-<source>Time remaining:</source>
-<target>Tiempo restante:</target>
-
-<source>Time elapsed:</source>
-<target>Tiempo transcurrido:</target>
-
<source>Select variant:</source>
<target>Seleccione un tipo:</target>
<source><Automatic></source>
<target><Automático></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identificar y aplicar cambios en ambos lados usando una base de datos. Las eliminaciones y los conflictos se detectan automáticamente.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Identificar y propagar cambios en ambos lados usando una base de datos. Borrados, renombraciones y conflictos son detectados automáticamente.</target>
<source>Mirror ->></source>
<target>Espejo ->></target>
@@ -901,27 +793,19 @@ Excluir: \stuff\temp\*
<target>Copia de archivos transaccionales</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Escribir en archivo temporal (*.ffs_tmp) primero y después renombrarlo. Esto garantiza un estado consistente incluso en caso de error fatal.</target>
<source>Copy locked files</source>
<target>Copiar archivos bloqueados</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Copiar archivos compartidos o bloqueados usando el servicio "Volume Shadow Copy" (Requiere derechos de administrador)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Copiar archivos compartidos o bloqueados usando el servicio "Volume Shadow Copy" (Requiere derechos de administrador)</target>
<source>Copy file access permissions</source>
<target>Copiar permisos de acceso al archivo</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Transferir permisos de archivo y directorio (Requiere derechos de administrador)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Transferir permisos de archivo y directorio (Requiere derechos de administrador)</target>
<source>Hidden dialogs:</source>
<target>Diálogos ocultos:</target>
@@ -953,6 +837,9 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>&Find next</source>
<target>&Buscar siguiente</target>
+<source>Operation aborted!</source>
+<target>¡Operación abortada!</target>
+
<source>Main bar</source>
<target>Barra principal</target>
@@ -993,16 +880,16 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<target>Ajustar automáticamente las columnas</target>
<source>Icon size:</source>
-<target></target>
+<target>Tamaño del icono:</target>
<source>Small</source>
-<target></target>
+<target>Pequeño</target>
<source>Medium</source>
-<target></target>
+<target>Medio</target>
<source>Large</source>
-<target></target>
+<target>Grande</target>
<source>Include all rows</source>
<target>Incluir todas las filas</target>
@@ -1130,6 +1017,9 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>File list exported!</source>
<target>¡Lista de archivos exportada!</target>
+<source>Error writing file:</source>
+<target>Error al escribir archivo:</target>
+
<source>Batch file created successfully!</source>
<target>¡El archivo batch ha sido creado correctamente!</target>
@@ -1229,9 +1119,6 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>Filter: Single pair</source>
<target>Filtro: Sólo un par</target>
-<source>Ignore</source>
-<target>Ignorar</target>
-
<source>Direct</source>
<target>Enviar</target>
@@ -1295,6 +1182,105 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>Move files into a time-stamped subdirectory</source>
<target>Mover archivos a un subdirectorio con marca de tiempo</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 minuto</pluralform>
+<pluralform>%x minutos</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 hora</pluralform>
+<pluralform>%x horas</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 día</pluralform>
+<pluralform>%x días</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>No se ha podido inicializar la visualización de directorios:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Error al visualizar los directorios.</target>
+
+<source>Conversion error:</source>
+<target>Error de conversión:</target>
+
+<source>Error deleting file:</source>
+<target>Error al borrar archivo:</target>
+
+<source>Error moving file:</source>
+<target>Error al mover archivo:</target>
+
+<source>Target file already existing!</source>
+<target>¡El archivo de destino ya existe!</target>
+
+<source>Error moving directory:</source>
+<target>Error al mover directorio:</target>
+
+<source>Target directory already existing!</source>
+<target>¡El directorio de destino ya existe!</target>
+
+<source>Error deleting directory:</source>
+<target>Error al borrar directorio:</target>
+
+<source>Error changing modification time:</source>
+<target>Error al cambiar hora de modificación:</target>
+
+<source>Error loading library function:</source>
+<target>Error al cargar la función de biblioteca:</target>
+
+<source>Error reading security context:</source>
+<target>Error al leer en contexto de seguridad:</target>
+
+<source>Error writing security context:</source>
+<target>Error al escribir en contexto de seguridad:</target>
+
+<source>Error copying file permissions:</source>
+<target>Error al copiar permisos del fichero:</target>
+
+<source>Error creating directory:</source>
+<target>Error al crear directorio:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Error al copiar enlace simbólico:</target>
+
+<source>Error copying file:</source>
+<target>Error al copiar archivo:</target>
+
+<source>Error opening file:</source>
+<target>Error al abrir archivo:</target>
+
+<source>Error traversing directory:</source>
+<target>Error al buscar en el directorio:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Bucle infinito al buscar en el directorio:</target>
+
+<source>Error setting privilege:</source>
+<target>Error al establecer privilegios:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>¡Ambos lados han cambiado desde la última sincronizacion!</target>
@@ -1325,9 +1311,6 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>¡Los directorios son dependientes! Tenga cuidado al establecer las reglas de sincronización:</target>
-<source>Comparing content of files %x</source>
-<target>Comparación del contenido de los archivos %x</target>
-
<source>Memory allocation failed!</source>
<target>¡La asignación de memoria ha fallado!</target>
@@ -1343,15 +1326,15 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>Symlinks %x have the same date but a different target!</source>
<target>¡Los enlaces simbólicos %x tienen la misma fecha pero un destino diferente!</target>
+<source>Comparing content of files %x</source>
+<target>Comparación del contenido de los archivos %x</target>
+
<source>Comparing files by content failed.</source>
<target>La comparación de archivos por el contenido ha fallado.</target>
<source>Generating file list...</source>
<target>Generando lista de archivos...</target>
-<source>Multiple...</source>
-<target>Múltiple...</target>
-
<source>Both sides are equal</source>
<target>Ambos lados son iguales</target>
@@ -1370,6 +1353,12 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>Delete right file/folder</source>
<target>Eliminar archivo/carpeta de la derecha</target>
+<source>Move file on left</source>
+<target>Mover archivo a la izquierda</target>
+
+<source>Move file on right</source>
+<target>Mover archivo a la derecha</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Sobreescribir archivo/carpeta de la izquierda por el de la derecha</target>
@@ -1385,6 +1374,9 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador)
<source>Copy file attributes only to right</source>
<target>Copiar sólo atributos del archivo a la derecha</target>
+<source>Multiple...</source>
+<target>Múltiple...</target>
+
<source>Deleting file %x</source>
<target>Borrar archivo %x</target>
diff --git a/BUILD/Languages/swedish.lng b/BUILD/Languages/swedish.lng
index acd17992..07d20948 100644
--- a/BUILD/Languages/swedish.lng
+++ b/BUILD/Languages/swedish.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Automatiserad synkronisering</target>
-<source>Browse</source>
-<target>Bläddra</target>
-
-<source>Windows Error Code %x:</source>
-<target>Windows Felkod %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Linux Felkod %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Ogiltig kommandorad: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Kan inte tyda symbolisk länk:</target>
-
-<source>Show pop-up</source>
-<target>Visa pop-up</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Visa pop-up vid fel och varningar</target>
-
-<source>Ignore errors</source>
-<target>Ignorera fel</target>
-
-<source>Hide all error and warning messages</source>
-<target>Visa inte fel- och varningsmeddelanden</target>
-
-<source>Exit instantly</source>
-<target>Avsluta omedelbart</target>
-
-<source>Abort synchronization immediately</source>
-<target>Avbryt synkronisering omedelbart</target>
-
<source>Select alternate comparison settings</source>
<target>Välj alternativa jämförelseinställningar</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Välj tidsintervall</target>
+<source>Show pop-up</source>
+<target>Visa pop-up</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Visa pop-up vid fel och varningar</target>
+
+<source>Ignore errors</source>
+<target>Ignorera fel</target>
+
+<source>Hide all error and warning messages</source>
+<target>Visa inte fel- och varningsmeddelanden</target>
+
+<source>Exit instantly</source>
+<target>Avsluta omedelbart</target>
+
+<source>Abort synchronization immediately</source>
+<target>Avbryt synkronisering omedelbart</target>
+
+<source>Browse</source>
+<target>Bläddra</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Kan inte läsa från databasen:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Kan inte skriva till databas:</target>
+
+<source>Invalid command line: %x</source>
+<target>Ogiltig kommandorad: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Windows Felkod %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Linux Felkod %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Kan inte tyda symbolisk länk:</target>
+
<source>%x MB</source>
<target>%x MB</target>
@@ -163,17 +169,14 @@
<source>Comparison Result</source>
<target>Jämförelseresultat</target>
-<source>Incompatible synchronization database format:</source>
-<target>Inkompatibelt databasformat:</target>
-
<source>Initial synchronization:</source>
<target>Initial synkronisering:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>En av FreeFileSyncs databasfiler saknas:</target>
-<source>Error reading from synchronization database:</source>
-<target>Kan inte läsa från databasen:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Inkompatibelt databasformat:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Databasfiler delar inte en gemensam synkroniseringssession:</target>
@@ -199,12 +202,18 @@
<pluralform>%x sek</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Dra && släpp</target>
+
<source>Info</source>
<target>Info</target>
<source>Fatal Error</source>
<target>Allvarligt fel</target>
+<source>Error reading file:</source>
+<target>Kan inte läsa fil:</target>
+
<source>Scanning:</source>
<target>Skannar:</target>
@@ -223,15 +232,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Felaktig FreeFileSync konfigurationsfil!</target>
-<source>File does not exist:</source>
-<target>Filen finns inte:</target>
-
<source>Error parsing configuration file:</source>
<target>Kan inte läsa in konfigurationsfil:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Kan inte flytta till papperskorgen:</target>
+
+<source>Could not load a required DLL:</source>
+<target>Kan inte läsa in nödvändig DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Kunde inte starta tjänsten Volume Shadow Copy (VSS)</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Skuggkopior av wow64 stöds ej. Använd FreeFileSync x64 istället!</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Kan inte bestämma volym för fil:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Volymnamn %x saknas i filnamn %y!</target>
+
<source>/sec</source>
<target>/s</target>
+<source>File does not exist:</source>
+<target>Filen finns inte:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Kan inte läsa värden för följande XML-noder:</target>
+
<source>S&ave configuration...</source>
<target>S&para inställningar...</target>
@@ -324,141 +354,6 @@ Kommandot verkställes när:
<source>A directory input field is empty.</source>
<target>Ett katalogfält är tomt</target>
-<source>Drag && drop</source>
-<target>Dra && släpp</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Kan inte initiera katalogskanner:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Fel vid övervakning av kataloger.</target>
-
-<source>Conversion error:</source>
-<target>Konversionsfel:</target>
-
-<source>Error deleting file:</source>
-<target>Kan inte ta bort fil:</target>
-
-<source>Error moving file:</source>
-<target>Kan inte flytta fil:</target>
-
-<source>Target file already existing!</source>
-<target>Filen finns redan!</target>
-
-<source>Error moving directory:</source>
-<target>Kan inte flytta katalog:</target>
-
-<source>Target directory already existing!</source>
-<target>Målkatalogen finns redan!</target>
-
-<source>Error deleting directory:</source>
-<target>Kan inte ta bort katalog:</target>
-
-<source>Error changing modification time:</source>
-<target>Kan inte modifiera tidsstämpel:</target>
-
-<source>Error loading library function:</source>
-<target>Kan inte starta biblioteksfunktion:</target>
-
-<source>Error reading security context:</source>
-<target>Kan inte läsa säkerhetskontext:</target>
-
-<source>Error writing security context:</source>
-<target>Kan inte skriva säkerhetskontext:</target>
-
-<source>Error copying file permissions:</source>
-<target>Kan inte kopiera filsystembehörighet:</target>
-
-<source>Error creating directory:</source>
-<target>Kan inte skapa katalog:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Kan inte kopiera symbolisk länk:</target>
-
-<source>Error copying file:</source>
-<target>Kan inte kopiera fil:</target>
-
-<source>Error opening file:</source>
-<target>Kan inte öppna fil:</target>
-
-<source>Error writing file:</source>
-<target>Kan inte skriva fil:</target>
-
-<source>Error reading file:</source>
-<target>Kan inte läsa fil:</target>
-
-<source>Operation aborted!</source>
-<target>Processen avbruten!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Oändlig loop vid accessförsök på katalog:</target>
-
-<source>Error traversing directory:</source>
-<target>Accessfel på katalog:</target>
-
-<source>Error setting privilege:</source>
-<target>Kan inte ange privilegie:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Kan inte flytta till papperskorgen:</target>
-
-<source>Could not load a required DLL:</source>
-<target>Kan inte läsa in nödvändig DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Kan inte skriva till databas:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Kunde inte starta tjänsten Volume Shadow Copy (VSS)</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Skuggkopior av wow64 stöds ej. Använd FreeFileSync x64 istället!</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Kan inte bestämma volym för fil:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Volymnamn %x saknas i filnamn %y!</target>
-
-<source>%x TB</source>
-<target>%x TB</target>
-
-<source>%x PB</source>
-<target>%x PB</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>1 timma</pluralform>
-<pluralform>%x timmar</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>1 dag</pluralform>
-<pluralform>%x dagar</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Kan inte läsa värden för följande XML-noder:</target>
-
<source>Logging</source>
<target>Loggar</target>
@@ -477,9 +372,6 @@ Kommandot verkställes när:
<source>Batch execution</source>
<target>Batch-körning</target>
-<source>Log-messages:</source>
-<target>Logg-meddelanden:</target>
-
<source>Stop</source>
<target>Stopp</target>
@@ -606,6 +498,24 @@ Kommandot verkställes när:
<source>Total amount of data that will be transferred</source>
<target>Total mängd data som kommer att överföras</target>
+<source>Operation:</source>
+<target>Arbetsuppgift:</target>
+
+<source>Items found:</source>
+<target>Funna poster:</target>
+
+<source>Items remaining:</source>
+<target>Återstående poster:</target>
+
+<source>Speed:</source>
+<target>Hastighet:</target>
+
+<source>Time remaining:</source>
+<target>Kvarvarande tid:</target>
+
+<source>Time elapsed:</source>
+<target>Förfluten tid:</target>
+
<source>Batch job</source>
<target>Batch-jobb</target>
@@ -654,32 +564,14 @@ Kommandot verkställes när:
<source>&Cancel</source>
<target>&Avbryt</target>
-<source>Operation:</source>
-<target>Arbetsuppgift:</target>
-
-<source>Items found:</source>
-<target>Funna poster:</target>
-
-<source>Items remaining:</source>
-<target>Återstående poster:</target>
-
-<source>Speed:</source>
-<target>Hastighet:</target>
-
-<source>Time remaining:</source>
-<target>Kvarvarande tid:</target>
-
-<source>Time elapsed:</source>
-<target>Förfluten tid:</target>
-
<source>Select variant:</source>
<target>Välj variant:</target>
<source><Automatic></source>
<target><Automatisk></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Identifiera och visa förändringar på båda sidor via databas. Borttagningar och konflikter upptäcks automatiskt.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Använd en databas för att identifiera och sprida ändringar på båda sidor. Borttagning, namnbyte och konflikter upptäcks automatiskt</target>
<source>Mirror ->></source>
<target>Spegla ->></target>
@@ -901,27 +793,19 @@ Undanta: \stuff\temp\*
<target>Transaktionell filkopiering</target>
<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source>
-<target></target>
+<target>Skriv först till en temporär fil (*.ffs_tmp) och byt sedan namn på den. Detta garanterar en konsistent status även vid allvarliga fel</target>
<source>Copy locked files</source>
<target>Kopiera låsta filer</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Kopiera delade eller låsta filer med hjälp av Volume Shadow Copy Service (Kräver administratörsrättighet)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Kopiera delade eller låsta filer med hjälp av Volume Shadow Copy Service (Kräver administratörsrättighet)</target>
<source>Copy file access permissions</source>
<target>Kopiera filåtkomstbehörigheter</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Överför fil- och katalogrättigheter (Kräver administratörsrättigheter)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Överför fil- och katalogrättigheter (Kräver administratörsrättigheter)</target>
<source>Hidden dialogs:</source>
<target>Dolda meddelanden:</target>
@@ -953,6 +837,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>&Sök nästa</target>
+<source>Operation aborted!</source>
+<target>Processen avbruten!</target>
+
<source>Main bar</source>
<target>Huvudfält</target>
@@ -993,16 +880,16 @@ Transfer file and directory permissions (Requires Administrator rights)
<target>Autojustera kollumner</target>
<source>Icon size:</source>
-<target></target>
+<target>Ikonstorlek:</target>
<source>Small</source>
-<target></target>
+<target>Liten</target>
<source>Medium</source>
-<target></target>
+<target>Normal</target>
<source>Large</source>
-<target></target>
+<target>Stor</target>
<source>Include all rows</source>
<target>Inkludera alla rader</target>
@@ -1130,6 +1017,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>Fillista exporterad!</target>
+<source>Error writing file:</source>
+<target>Kan inte skriva fil:</target>
+
<source>Batch file created successfully!</source>
<target>Batch-filen skapades korrekt!</target>
@@ -1229,9 +1119,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>Filter: Enstaka undantag</target>
-<source>Ignore</source>
-<target>Ignorera</target>
-
<source>Direct</source>
<target>Direkt</target>
@@ -1295,6 +1182,105 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>Flytta filer till en tidsstämplad underkatalog</target>
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 timma</pluralform>
+<pluralform>%x timmar</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 dag</pluralform>
+<pluralform>%x dagar</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Kan inte initiera katalogskanner:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Fel vid övervakning av kataloger.</target>
+
+<source>Conversion error:</source>
+<target>Konversionsfel:</target>
+
+<source>Error deleting file:</source>
+<target>Kan inte ta bort fil:</target>
+
+<source>Error moving file:</source>
+<target>Kan inte flytta fil:</target>
+
+<source>Target file already existing!</source>
+<target>Filen finns redan!</target>
+
+<source>Error moving directory:</source>
+<target>Kan inte flytta katalog:</target>
+
+<source>Target directory already existing!</source>
+<target>Målkatalogen finns redan!</target>
+
+<source>Error deleting directory:</source>
+<target>Kan inte ta bort katalog:</target>
+
+<source>Error changing modification time:</source>
+<target>Kan inte modifiera tidsstämpel:</target>
+
+<source>Error loading library function:</source>
+<target>Kan inte starta biblioteksfunktion:</target>
+
+<source>Error reading security context:</source>
+<target>Kan inte läsa säkerhetskontext:</target>
+
+<source>Error writing security context:</source>
+<target>Kan inte skriva säkerhetskontext:</target>
+
+<source>Error copying file permissions:</source>
+<target>Kan inte kopiera filsystembehörighet:</target>
+
+<source>Error creating directory:</source>
+<target>Kan inte skapa katalog:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Kan inte kopiera symbolisk länk:</target>
+
+<source>Error copying file:</source>
+<target>Kan inte kopiera fil:</target>
+
+<source>Error opening file:</source>
+<target>Kan inte öppna fil:</target>
+
+<source>Error traversing directory:</source>
+<target>Accessfel på katalog:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Oändlig loop vid accessförsök på katalog:</target>
+
+<source>Error setting privilege:</source>
+<target>Kan inte ange privilegie:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>Båda sidor har ändrats sedan senaste synkroniseringen!</target>
@@ -1325,9 +1311,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Kataloger är beroende! Var försiktig när du sätter upp synkroniseringsregler:</target>
-<source>Comparing content of files %x</source>
-<target>Jämför filinnehåll för %x</target>
-
<source>Memory allocation failed!</source>
<target>Minnesallokering misslyckades!</target>
@@ -1343,15 +1326,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>Symbolisk länk %x har samma datum, men annat mål!</target>
+<source>Comparing content of files %x</source>
+<target>Jämför filinnehåll för %x</target>
+
<source>Comparing files by content failed.</source>
<target>Kunde inte jämföra filinnehåll.</target>
<source>Generating file list...</source>
<target>Skapar fillista...</target>
-<source>Multiple...</source>
-<target>Multipla...</target>
-
<source>Both sides are equal</source>
<target>Bägge sidor är lika</target>
@@ -1370,6 +1353,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>Ta bort höger fil/katalog</target>
+<source>Move file on left</source>
+<target>Flytta fil på vänster sida</target>
+
+<source>Move file on right</source>
+<target>Flytta fil på höger sida</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Skriv över vänster fil/katalog med den högra</target>
@@ -1385,6 +1374,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>Kopiera endast filattribut åt höger</target>
+<source>Multiple...</source>
+<target>Multipla...</target>
+
<source>Deleting file %x</source>
<target>Tar bort filen %x</target>
diff --git a/BUILD/Languages/turkish.lng b/BUILD/Languages/turkish.lng
index a360bcd1..2e0622d4 100644
--- a/BUILD/Languages/turkish.lng
+++ b/BUILD/Languages/turkish.lng
@@ -169,15 +169,15 @@
<source>Comparison Result</source>
<target>Karşılaştırma sonucu</target>
-<source>Incompatible synchronization database format:</source>
-<target>Uyumsuz eşleştirme veritabanı biçimi:</target>
-
<source>Initial synchronization:</source>
<target>Başlangıç eşleştirmesi:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>FreeFileSync veritabanı dosyalarından biri henüz yok:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Uyumsuz eşleştirme veritabanı biçimi:</target>
+
<source>Database files do not share a common synchronization session:</source>
<target>Veritabanıdosyaları ortak bir eşleştirmeoturumunu paylaşmıyor:</target>
@@ -232,9 +232,6 @@
<source>Invalid FreeFileSync config file!</source>
<target>Geçersiz FreeFileSync yapılandırma dosyası!</target>
-<source>File does not exist:</source>
-<target>Dosya bulunamadı:</target>
-
<source>Error parsing configuration file:</source>
<target>Yapılandırma dosyası çözümlenirken hata:</target>
@@ -259,6 +256,9 @@
<source>/sec</source>
<target>/san</target>
+<source>File does not exist:</source>
+<target>Dosya bulunamadı:</target>
+
<source>Could not read values for the following XML nodes:</source>
<target>Şu XML düğümlerindeki değerler okunamadı:</target>
@@ -372,9 +372,6 @@ Her seferinde çalıştırılacak komut satırı:
<source>Batch execution</source>
<target>Toplu komut yürütme</target>
-<source>Log-messages:</source>
-<target>Günlük iletileri:</target>
-
<source>Stop</source>
<target>Durdur</target>
@@ -501,6 +498,24 @@ Her seferinde çalıştırılacak komut satırı:
<source>Total amount of data that will be transferred</source>
<target>Aktarılacak toplam veri miktarı</target>
+<source>Operation:</source>
+<target>İşlem:</target>
+
+<source>Items found:</source>
+<target>Bulunan bileşenler:</target>
+
+<source>Items remaining:</source>
+<target>Kalan bileşenler:</target>
+
+<source>Speed:</source>
+<target>Hız:</target>
+
+<source>Time remaining:</source>
+<target>Kalan zaman:</target>
+
+<source>Time elapsed:</source>
+<target>Geçen zaman:</target>
+
<source>Batch job</source>
<target>Toplu iş</target>
@@ -549,32 +564,14 @@ Her seferinde çalıştırılacak komut satırı:
<source>&Cancel</source>
<target>İ&ptal</target>
-<source>Operation:</source>
-<target>İşlem:</target>
-
-<source>Items found:</source>
-<target>Bulunan bileşenler:</target>
-
-<source>Items remaining:</source>
-<target>Kalan bileşenler:</target>
-
-<source>Speed:</source>
-<target>Hız:</target>
-
-<source>Time remaining:</source>
-<target>Kalan zaman:</target>
-
-<source>Time elapsed:</source>
-<target>Geçen zaman:</target>
-
<source>Select variant:</source>
<target>Davranışı seçin:</target>
<source><Automatic></source>
<target><Kendiliğinden></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Bir veritabanı kullanarak iki yandaki değişiklikleri belirler ve günceller. Silinme ve tutarsızlıklar kendiliğinden algılanır.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>İki yandaki değişiklikleri bir veritabanı kullanarak belirle ve sakla. Silme, yeniden adlandırma ve çakışma işlemleri kendiliğinden algılanır.</target>
<source>Mirror ->></source>
<target>Yansı ->></target>
@@ -801,22 +798,14 @@ Katma: \stuff\temp\*
<source>Copy locked files</source>
<target>Kilitli dosyaları da kopyala</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Paylaşılan ya da kilitli dosyaları Gölge Kopya Hizmetini kullanarak kopyalar (Yönetici izinlerine gerek duyar)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Paylaşılan ya da kilitli dosyaları Gölge Kopya Hizmetini kullanarak kopyalar (Yönetici izinlerine gerek duyar)</target>
<source>Copy file access permissions</source>
<target>Dosya erişim izinlerini kopyala</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)</target>
<source>Hidden dialogs:</source>
<target>Gizlenmiş iletiler:</target>
@@ -1130,9 +1119,6 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)
<source>Filter: Single pair</source>
<target>Süzgeç: Tek çift</target>
-<source>Ignore</source>
-<target>Yoksay</target>
-
<source>Direct</source>
<target>Doğrudan</target>
@@ -1286,12 +1272,12 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)
<source>Error opening file:</source>
<target>Dosya açılırken hata:</target>
-<source>Endless loop when traversing directory:</source>
-<target>Klasörlerde dolaşırken sonsuz döngü:</target>
-
<source>Error traversing directory:</source>
<target>Klasörde dolaşırken hata:</target>
+<source>Endless loop when traversing directory:</source>
+<target>Klasörlerde dolaşırken sonsuz döngü:</target>
+
<source>Error setting privilege:</source>
<target>İzinler ayarlanırken hata:</target>
@@ -1325,9 +1311,6 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Klasörler bağımlı! Eşleştirme kurallarını koyarken dikkatli olun:</target>
-<source>Comparing content of files %x</source>
-<target>%x dosyalarının içeriği karşılaştırılıyor</target>
-
<source>Memory allocation failed!</source>
<target>Bellek ayrılamadı!</target>
@@ -1343,15 +1326,15 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)
<source>Symlinks %x have the same date but a different target!</source>
<target>Sembolik bağlantılar %x aynı tarihli fakat hedefleri farklı!</target>
+<source>Comparing content of files %x</source>
+<target>%x dosyalarının içeriği karşılaştırılıyor</target>
+
<source>Comparing files by content failed.</source>
<target>Dosyaların içerikleri karşılaştırılamadı.</target>
<source>Generating file list...</source>
<target>Dosya listesi oluşturuluyor...</target>
-<source>Multiple...</source>
-<target>Çoklu...</target>
-
<source>Both sides are equal</source>
<target>İki tarafta aynı</target>
@@ -1370,6 +1353,12 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)
<source>Delete right file/folder</source>
<target>Sağdaki dosya/klasörleri sil</target>
+<source>Move file on left</source>
+<target>Soldaki dosyayı taşı</target>
+
+<source>Move file on right</source>
+<target>Sağdaki dosyayı taşı</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Soldaki dosya/klasörlerin üzerine sağdakileri yaz</target>
@@ -1385,6 +1374,9 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)
<source>Copy file attributes only to right</source>
<target>Dosya özniteliklerini yalnız sağa kopyalaya</target>
+<source>Multiple...</source>
+<target>Çoklu...</target>
+
<source>Deleting file %x</source>
<target>%x dosyası siliniyor</target>
diff --git a/BUILD/Languages/ukrainian.lng b/BUILD/Languages/ukrainian.lng
index 4973cf06..cfe7e92d 100644
--- a/BUILD/Languages/ukrainian.lng
+++ b/BUILD/Languages/ukrainian.lng
@@ -22,39 +22,6 @@
<source>RealtimeSync - Automated Synchronization</source>
<target>RealtimeSync - Автоматична синхронізація</target>
-<source>Browse</source>
-<target>Переглянути</target>
-
-<source>Windows Error Code %x:</source>
-<target>Код помилки Windows %x:</target>
-
-<source>Linux Error Code %x:</source>
-<target>Код помилки Linux %x:</target>
-
-<source>Invalid command line: %x</source>
-<target>Неправильний командний рядок: %x</target>
-
-<source>Error resolving symbolic link:</source>
-<target>Помилка при вирішені символічного посилання:</target>
-
-<source>Show pop-up</source>
-<target>Показувати виринаючі вікна</target>
-
-<source>Show pop-up on errors or warnings</source>
-<target>Показувати виринаючі вікна при помилках та попередженнях</target>
-
-<source>Ignore errors</source>
-<target>Ігнорувати помилки</target>
-
-<source>Hide all error and warning messages</source>
-<target>Приховати всі помилки і повідомлення з попередженнями</target>
-
-<source>Exit instantly</source>
-<target>Вийти негайно</target>
-
-<source>Abort synchronization immediately</source>
-<target>Перервати синхронізацію негайно</target>
-
<source>Select alternate comparison settings</source>
<target>Вибрати альтернативні налаштування порівняння</target>
@@ -115,6 +82,45 @@
<source>Select time span</source>
<target>Виберіть часовий інтервал</target>
+<source>Show pop-up</source>
+<target>Показувати виринаючі вікна</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Показувати виринаючі вікна при помилках та попередженнях</target>
+
+<source>Ignore errors</source>
+<target>Ігнорувати помилки</target>
+
+<source>Hide all error and warning messages</source>
+<target>Приховати всі помилки і повідомлення з попередженнями</target>
+
+<source>Exit instantly</source>
+<target>Вийти негайно</target>
+
+<source>Abort synchronization immediately</source>
+<target>Перервати синхронізацію негайно</target>
+
+<source>Browse</source>
+<target>Переглянути</target>
+
+<source>Error reading from synchronization database:</source>
+<target>Помилка при читанні з бази даних синхронізації:</target>
+
+<source>Error writing to synchronization database:</source>
+<target>Помилка при записі у базу данних синхронізації:</target>
+
+<source>Invalid command line: %x</source>
+<target>Неправильний командний рядок: %x</target>
+
+<source>Windows Error Code %x:</source>
+<target>Код помилки Windows %x:</target>
+
+<source>Linux Error Code %x:</source>
+<target>Код помилки Linux %x:</target>
+
+<source>Error resolving symbolic link:</source>
+<target>Помилка при вирішені символічного посилання:</target>
+
<source>%x MB</source>
<target>%x МБ</target>
@@ -164,17 +170,14 @@
<source>Comparison Result</source>
<target>Результати порівнювання</target>
-<source>Incompatible synchronization database format:</source>
-<target>Несумісний формат бази даних синхронізації:</target>
-
<source>Initial synchronization:</source>
<target>Вступна синхронізація:</target>
<source>One of the FreeFileSync database files is not yet existing:</source>
<target>Файлу бази даних FreeFileSync ще не існує:</target>
-<source>Error reading from synchronization database:</source>
-<target>Помилка при читанні з бази даних синхронізації:</target>
+<source>Incompatible synchronization database format:</source>
+<target>Несумісний формат бази даних синхронізації:</target>
<source>Database files do not share a common synchronization session:</source>
<target>Файли бази даних не мають спільної сесії синхронізації</target>
@@ -201,12 +204,18 @@
<pluralform>%x сек</pluralform>
</target>
+<source>Drag && drop</source>
+<target>Drag && drop</target>
+
<source>Info</source>
<target>Інформація</target>
<source>Fatal Error</source>
<target>Критична помилка</target>
+<source>Error reading file:</source>
+<target>Помилка при читанні файлу:</target>
+
<source>Scanning:</source>
<target>Сканую:</target>
@@ -226,15 +235,36 @@
<source>Invalid FreeFileSync config file!</source>
<target>Неправильний файл конфігурації FreeFileSync!</target>
-<source>File does not exist:</source>
-<target>Файл не існує:</target>
-
<source>Error parsing configuration file:</source>
<target>Помилка при анализі файлу налаштувань синхронізації:</target>
+<source>Error moving to Recycle Bin:</source>
+<target>Помилка переміщення в "Корзину":</target>
+
+<source>Could not load a required DLL:</source>
+<target>Не вдалося завантажити необхідні DLL:</target>
+
+<source>Error accessing Volume Shadow Copy Service!</source>
+<target>Помилка доступу до послуги Тіньового Копіювання Тому</target>
+
+<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
+<target>Створення тіньових копій на WOW64 не підтримується. Будь ласка, використайте FreeFileSync 64-розрядної версії.</target>
+
+<source>Could not determine volume name for file:</source>
+<target>Не вдалося визначити назву тому для файлу:</target>
+
+<source>Volume name %x not part of filename %y!</source>
+<target>Ім’я тому %x не є частиною імені файлу %y!</target>
+
<source>/sec</source>
<target>/сек</target>
+<source>File does not exist:</source>
+<target>Файл не існує:</target>
+
+<source>Could not read values for the following XML nodes:</source>
+<target>Не вдалося прочитати значення таких XML записів:</target>
+
<source>S&ave configuration...</source>
<target>Зберегти налаштування...</target>
@@ -327,144 +357,6 @@ The command line is executed each time:
<source>A directory input field is empty.</source>
<target>Поле введення шляху каталога порожнє.</target>
-<source>Drag && drop</source>
-<target>Drag && drop</target>
-
-<source>Could not initialize directory monitoring:</source>
-<target>Не вдалося ініціювати каталог для моніторингу:</target>
-
-<source>Error when monitoring directories.</source>
-<target>Помилка моніторингу каталогу.</target>
-
-<source>Conversion error:</source>
-<target>Помилка перетворення:</target>
-
-<source>Error deleting file:</source>
-<target>Помилка при вилученні файлу:</target>
-
-<source>Error moving file:</source>
-<target>Помилка переміщення файлу:</target>
-
-<source>Target file already existing!</source>
-<target>Кінцевий файл уже існує!</target>
-
-<source>Error moving directory:</source>
-<target>Помилка переміщення каталогу:</target>
-
-<source>Target directory already existing!</source>
-<target>Кінцевий каталог вже існує!</target>
-
-<source>Error deleting directory:</source>
-<target>Помилка при вилученні каталогу:</target>
-
-<source>Error changing modification time:</source>
-<target>Помилка при зміні часу модификації файлу:</target>
-
-<source>Error loading library function:</source>
-<target>Помилка при завантаженні функції бібліотеки:</target>
-
-<source>Error reading security context:</source>
-<target>Помилка при читанні контексту безпеки:</target>
-
-<source>Error writing security context:</source>
-<target>Помилка при записі контексту безпеки:</target>
-
-<source>Error copying file permissions:</source>
-<target>Помилка при копіюванні прав доступу:</target>
-
-<source>Error creating directory:</source>
-<target>Помилка при створенні каталогу:</target>
-
-<source>Error copying symbolic link:</source>
-<target>Помилка при копіюванні символьного посилання:</target>
-
-<source>Error copying file:</source>
-<target>Помилка при копіюванні файлу:</target>
-
-<source>Error opening file:</source>
-<target>Помилка при відкриванні файлу:</target>
-
-<source>Error writing file:</source>
-<target>Помилка при записі файлу:</target>
-
-<source>Error reading file:</source>
-<target>Помилка при читанні файлу:</target>
-
-<source>Operation aborted!</source>
-<target>Операція відмінена!</target>
-
-<source>Endless loop when traversing directory:</source>
-<target>Зациклюванння при обході каталогу:</target>
-
-<source>Error traversing directory:</source>
-<target>Помилка обходу каталогу:</target>
-
-<source>Error setting privilege:</source>
-<target>Помилка встановлення привилеїв:</target>
-
-<source>Error moving to Recycle Bin:</source>
-<target>Помилка переміщення в "Корзину":</target>
-
-<source>Could not load a required DLL:</source>
-<target>Не вдалося завантажити необхідні DLL:</target>
-
-<source>Error writing to synchronization database:</source>
-<target>Помилка при записі у базу данних синхронізації:</target>
-
-<source>Error accessing Volume Shadow Copy Service!</source>
-<target>Помилка доступу до послуги Тіньового Копіювання Тому</target>
-
-<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source>
-<target>Створення тіньових копій на WOW64 не підтримується. Будь ласка, використайте FreeFileSync 64-розрядної версії.</target>
-
-<source>Could not determine volume name for file:</source>
-<target>Не вдалося визначити назву тому для файлу:</target>
-
-<source>Volume name %x not part of filename %y!</source>
-<target>Ім’я тому %x не є частиною імені файлу %y!</target>
-
-<source>%x TB</source>
-<target>%x ТБ</target>
-
-<source>%x PB</source>
-<target>%x ПБ</target>
-
-<source>%x%</source>
-<target>%x%</target>
-
-<source>
-<pluralform>1 min</pluralform>
-<pluralform>%x min</pluralform>
-</source>
-<target>
-<pluralform>%x хв</pluralform>
-<pluralform>%x хв</pluralform>
-<pluralform>%x хв</pluralform>
-</target>
-
-<source>
-<pluralform>1 hour</pluralform>
-<pluralform>%x hours</pluralform>
-</source>
-<target>
-<pluralform>%x година</pluralform>
-<pluralform>%x години</pluralform>
-<pluralform>%x годин</pluralform>
-</target>
-
-<source>
-<pluralform>1 day</pluralform>
-<pluralform>%x days</pluralform>
-</source>
-<target>
-<pluralform>%x день</pluralform>
-<pluralform>%x дні</pluralform>
-<pluralform>%x днів</pluralform>
-</target>
-
-<source>Could not read values for the following XML nodes:</source>
-<target>Не вдалося прочитати значення таких XML записів:</target>
-
<source>Logging</source>
<target>Лог-файли</target>
@@ -483,9 +375,6 @@ The command line is executed each time:
<source>Batch execution</source>
<target>Виконання пакетного завдання</target>
-<source>Log-messages:</source>
-<target>Лог-повідомлення:</target>
-
<source>Stop</source>
<target>Стоп</target>
@@ -615,6 +504,24 @@ The command line is executed each time:
<source>Total amount of data that will be transferred</source>
<target>Загальний об’єм даних, які будуть передаватися</target>
+<source>Operation:</source>
+<target>Операція:</target>
+
+<source>Items found:</source>
+<target>Елементів знайдено:</target>
+
+<source>Items remaining:</source>
+<target>Елементів залишилось:</target>
+
+<source>Speed:</source>
+<target>Швидкість:</target>
+
+<source>Time remaining:</source>
+<target>Залишилось часу:</target>
+
+<source>Time elapsed:</source>
+<target>Пройшло часу:</target>
+
<source>Batch job</source>
<target>Пакетне завдання</target>
@@ -663,32 +570,14 @@ The command line is executed each time:
<source>&Cancel</source>
<target>&Відмінити</target>
-<source>Operation:</source>
-<target>Операція:</target>
-
-<source>Items found:</source>
-<target>Елементів знайдено:</target>
-
-<source>Items remaining:</source>
-<target>Елементів залишилось:</target>
-
-<source>Speed:</source>
-<target>Швидкість:</target>
-
-<source>Time remaining:</source>
-<target>Залишилось часу:</target>
-
-<source>Time elapsed:</source>
-<target>Пройшло часу:</target>
-
<source>Select variant:</source>
<target>Виберіть варіант:</target>
<source><Automatic></source>
<target><Автоматичний></target>
-<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source>
-<target>Виявлення і поширення змін на обох сторінах з використанням бази даних. Вилучені файли і конфлікти визначаються автоматично.</target>
+<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source>
+<target>Виявити та поширити зміни на обидві сторони використовуючи базу даних. Видалення, перейменування та конфлікти визначаються автоматично.</target>
<source>Mirror ->></source>
<target>Дзеркало ->></target>
@@ -911,22 +800,14 @@ Exclude: \stuff\temp\*
<source>Copy locked files</source>
<target>Копіювати заблоковані файли</target>
-<source>
-Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)
-</source>
-<target>
-Копіювати спільних чи заблокованих файлів з використанням послуги Тіньового Копіювання Тому (потрібні права Адміністратора)
-</target>
+<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source>
+<target>Копіювати спільних чи заблокованих файлів з використанням послуги Тіньового Копіювання Тому (потрібні права Адміністратора)</target>
<source>Copy file access permissions</source>
<target>Копіювати права доступу до файлу</target>
-<source>
-Transfer file and directory permissions (Requires Administrator rights)
-</source>
-<target>
-Передача прав доступу файлу/каталогу (потрібні права Адміністратора)
-</target>
+<source>Transfer file and directory permissions (Requires Administrator rights)</source>
+<target>Передача прав доступу файлу/каталогу (потрібні права Адміністратора)</target>
<source>Hidden dialogs:</source>
<target>Приховані діалоги</target>
@@ -958,6 +839,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>&Find next</source>
<target>&Знайти наступний</target>
+<source>Operation aborted!</source>
+<target>Операція відмінена!</target>
+
<source>Main bar</source>
<target>Головна панель</target>
@@ -1135,6 +1019,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>File list exported!</source>
<target>Список файлів експортовано!</target>
+<source>Error writing file:</source>
+<target>Помилка при записі файлу:</target>
+
<source>Batch file created successfully!</source>
<target>Файл завдання успішно створений!</target>
@@ -1238,9 +1125,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Filter: Single pair</source>
<target>Фільтр: Одна пара</target>
-<source>Ignore</source>
-<target>Ігнорувати</target>
-
<source>Direct</source>
<target>Прямо</target>
@@ -1306,6 +1190,108 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Move files into a time-stamped subdirectory</source>
<target>Переміщати файли в підкатлог з часовою міткою</target>
+<source>%x TB</source>
+<target>%x ТБ</target>
+
+<source>%x PB</source>
+<target>%x ПБ</target>
+
+<source>%x%</source>
+<target>%x%</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>%x хв</pluralform>
+<pluralform>%x хв</pluralform>
+<pluralform>%x хв</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>%x година</pluralform>
+<pluralform>%x години</pluralform>
+<pluralform>%x годин</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>%x день</pluralform>
+<pluralform>%x дні</pluralform>
+<pluralform>%x днів</pluralform>
+</target>
+
+<source>Could not initialize directory monitoring:</source>
+<target>Не вдалося ініціювати каталог для моніторингу:</target>
+
+<source>Error when monitoring directories.</source>
+<target>Помилка моніторингу каталогу.</target>
+
+<source>Conversion error:</source>
+<target>Помилка перетворення:</target>
+
+<source>Error deleting file:</source>
+<target>Помилка при вилученні файлу:</target>
+
+<source>Error moving file:</source>
+<target>Помилка переміщення файлу:</target>
+
+<source>Target file already existing!</source>
+<target>Кінцевий файл уже існує!</target>
+
+<source>Error moving directory:</source>
+<target>Помилка переміщення каталогу:</target>
+
+<source>Target directory already existing!</source>
+<target>Кінцевий каталог вже існує!</target>
+
+<source>Error deleting directory:</source>
+<target>Помилка при вилученні каталогу:</target>
+
+<source>Error changing modification time:</source>
+<target>Помилка при зміні часу модификації файлу:</target>
+
+<source>Error loading library function:</source>
+<target>Помилка при завантаженні функції бібліотеки:</target>
+
+<source>Error reading security context:</source>
+<target>Помилка при читанні контексту безпеки:</target>
+
+<source>Error writing security context:</source>
+<target>Помилка при записі контексту безпеки:</target>
+
+<source>Error copying file permissions:</source>
+<target>Помилка при копіюванні прав доступу:</target>
+
+<source>Error creating directory:</source>
+<target>Помилка при створенні каталогу:</target>
+
+<source>Error copying symbolic link:</source>
+<target>Помилка при копіюванні символьного посилання:</target>
+
+<source>Error copying file:</source>
+<target>Помилка при копіюванні файлу:</target>
+
+<source>Error opening file:</source>
+<target>Помилка при відкриванні файлу:</target>
+
+<source>Error traversing directory:</source>
+<target>Помилка обходу каталогу:</target>
+
+<source>Endless loop when traversing directory:</source>
+<target>Зациклюванння при обході каталогу:</target>
+
+<source>Error setting privilege:</source>
+<target>Помилка встановлення привилеїв:</target>
+
<source>Both sides have changed since last synchronization!</source>
<target>З моменту останньої синхронізації з обох сторін відбулися зміни!</target>
@@ -1339,9 +1325,6 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Directories are dependent! Be careful when setting up synchronization rules:</source>
<target>Залежні каталоги! Будьте уважні при налаштуванні правил синхронізації:</target>
-<source>Comparing content of files %x</source>
-<target>Порівнювання вмісту файлів %x</target>
-
<source>Memory allocation failed!</source>
<target>Помилка виділення пам’яті! (Не хватает памяти)</target>
@@ -1357,15 +1340,15 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Symlinks %x have the same date but a different target!</source>
<target>Символьне посиланння %x має таку ж дату, але різний вміст!</target>
+<source>Comparing content of files %x</source>
+<target>Порівнювання вмісту файлів %x</target>
+
<source>Comparing files by content failed.</source>
<target>Порівнювання файлів за вмістом не вдалося.</target>
<source>Generating file list...</source>
<target>Створення списку файлів...</target>
-<source>Multiple...</source>
-<target>Різні варіанти...</target>
-
<source>Both sides are equal</source>
<target>Сторони ідентичні</target>
@@ -1384,6 +1367,12 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Delete right file/folder</source>
<target>Вилучити файл/папку праворуч</target>
+<source>Move file on left</source>
+<target>Перемістити файли ліворуч</target>
+
+<source>Move file on right</source>
+<target>Перемістити файли праворуч</target>
+
<source>Overwrite left file/folder with right one</source>
<target>Перезаписати файл/папку ліворуч відповідником зправа</target>
@@ -1399,6 +1388,9 @@ Transfer file and directory permissions (Requires Administrator rights)
<source>Copy file attributes only to right</source>
<target>Зкопіювати праворуч лише атрибути файлу</target>
+<source>Multiple...</source>
+<target>Різні варіанти...</target>
+
<source>Deleting file %x</source>
<target>Вилучення файлу %x</target>
diff --git a/BUILD/Resources.zip b/BUILD/Resources.zip
index d1f7ca37..9ad96f71 100644
--- a/BUILD/Resources.zip
+++ b/BUILD/Resources.zip
Binary files differ
diff --git a/FreeFileSync.cbp b/FreeFileSync.cbp
index 14c02576..a81cea63 100644
--- a/FreeFileSync.cbp
+++ b/FreeFileSync.cbp
@@ -23,7 +23,7 @@
<Linker>
<Add option="-s" />
<Add option="-static" />
- <Add library="libboost_thread-mgw46-mt-s-1_47.a" />
+ <Add library="libboost_thread-mgw46-mt-s-1_48.a" />
<Add library="libwxmsw28u_aui.a" />
<Add library="libwxmsw28u_adv.a" />
<Add library="libwxmsw28u_core.a" />
@@ -50,7 +50,7 @@
<Add directory="C:\Programme\C++\wxWidgets\lib\gcc_dll\mswud" />
</Compiler>
<Linker>
- <Add library="libboost_thread-mgw46-mt-sd-1_47.a" />
+ <Add library="libboost_thread-mgw46-mt-sd-1_48.a" />
<Add library="libwxmsw28ud_aui.a" />
<Add library="libwxmsw28ud_adv.a" />
<Add library="libwxmsw28ud_core.a" />
@@ -77,7 +77,7 @@
<Add directory="lib\gtest\include" />
</Compiler>
<Linker>
- <Add library="libboost_thread-mgw46-mt-sd-1_47.a" />
+ <Add library="libboost_thread-mgw46-mt-sd-1_48.a" />
<Add library="libwxmsw28ud_adv.a" />
<Add library="libwxmsw28ud_core.a" />
<Add library="libwxbase28ud.a" />
diff --git a/RealtimeSync/RealtimeSync.cbp b/RealtimeSync/RealtimeSync.cbp
index c842e6bb..1f6c8049 100644
--- a/RealtimeSync/RealtimeSync.cbp
+++ b/RealtimeSync/RealtimeSync.cbp
@@ -27,7 +27,7 @@
<Add library="libwxbase28u.a" />
<Add library="libwxpng.a" />
<Add library="libwxzlib.a" />
- <Add library="libboost_thread-mgw46-mt-s-1_47.a" />
+ <Add library="libboost_thread-mgw46-mt-s-1_48.a" />
<Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" />
</Linker>
</Target>
@@ -51,7 +51,7 @@
<Add library="libwxbase28ud.a" />
<Add library="libwxpngd.a" />
<Add library="libwxzlibd.a" />
- <Add library="libboost_thread-mgw46-mt-sd-1_47.a" />
+ <Add library="libboost_thread-mgw46-mt-sd-1_48.a" />
<Add directory="C:\Program Files\C++\wxWidgets\lib\gcc_dll" />
</Linker>
</Target>
diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp
index 97ad480a..52dead7a 100644
--- a/RealtimeSync/watcher.cpp
+++ b/RealtimeSync/watcher.cpp
@@ -8,6 +8,7 @@
#include <zen/file_handling.h>
#include <zen/stl_tools.h>
#include <set>
+#include <ctime>
#include <wx/timer.h>
#include "../lib/resolve_path.h"
#include <zen/dir_watcher.h>
@@ -22,12 +23,14 @@ using namespace zen;
bool rts::updateUiIsAllowed()
{
- static wxLongLong lastExec;
- const wxLongLong newExec = wxGetLocalTimeMillis();
+ const std::clock_t CLOCK_UPDATE_INTERVAL = UI_UPDATE_INTERVAL * CLOCKS_PER_SEC / 1000;
- if (newExec - lastExec >= rts::UI_UPDATE_INTERVAL) //perform ui updates not more often than necessary
+ static std::clock_t lastExec = 0;
+ const std::clock_t now = std::clock(); //this is quite fast: 2 * 10^-5
+
+ if (now - lastExec >= CLOCK_UPDATE_INTERVAL) //perform ui updates not more often than necessary
{
- lastExec = newExec;
+ lastExec = now;
return true;
}
return false;
@@ -105,7 +108,7 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
try
{
- std::vector<Zstring> changedFiles = watcher.getChanges(); //throw FileError, ErrorNotExisting
+ std::vector<Zstring> changedFiles = watcher.getChanges([&] { statusHandler->requestUiRefresh(); }); //throw FileError, ErrorNotExisting
//remove to be ignored changes
vector_remove_if(changedFiles, [](const Zstring& name)
diff --git a/algorithm.cpp b/algorithm.cpp
index 7c6dc5d9..9a3b46f0 100644
--- a/algorithm.cpp
+++ b/algorithm.cpp
@@ -7,6 +7,7 @@
#include "algorithm.h"
#include <iterator>
#include <stdexcept>
+#include <tuple>
#include "lib/resources.h"
#include <zen/file_handling.h>
#include "lib/recycler.h"
@@ -34,9 +35,15 @@ void zen::swapGrids(const MainConfiguration& config, FolderComparison& folderCmp
class Redetermine
{
public:
+ static void execute(const DirectionSet& dirCfgIn, HierarchyObject& hierObj)
+ {
+ Redetermine(dirCfgIn).recurse(hierObj);
+ }
+
+private:
Redetermine(const DirectionSet& dirCfgIn) : dirCfg(dirCfgIn) {}
- void execute(HierarchyObject& hierObj) const
+ void recurse(HierarchyObject& hierObj) const
{
std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), [&](FileMapping& fileMap) { (*this)(fileMap); });
std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), [&](SymLinkMapping& linkMap) { (*this)(linkMap); });
@@ -136,11 +143,9 @@ public:
break;
}
- //recursion
- execute(dirObj);
+ recurse(dirObj);
}
-private:
const DirectionSet dirCfg;
};
@@ -242,6 +247,8 @@ private:
Zstring shortName; //empty if object not existing
zen::Int64 lastWriteTime;
zen::UInt64 fileSize;
+
+ //note: we do *not* consider FileId here, but are only interested in *visual* changes. Consider user moving data to some other medium, this is not a change!
};
@@ -392,6 +399,12 @@ std::pair<DataSetDir, const DirContainer*> retrieveDataSetDir(const Zstring& obj
class RedetermineAuto
{
public:
+ static void execute(BaseDirMapping& baseDirectory, DeterminationProblem* handler)
+ {
+ RedetermineAuto(baseDirectory, handler);
+ }
+
+private:
RedetermineAuto(BaseDirMapping& baseDirectory,
DeterminationProblem* handler) :
txtBothSidesChanged(_("Both sides have changed since last synchronization!")),
@@ -411,7 +424,7 @@ public:
//set conservative "two-way" directions
DirectionSet twoWayCfg = getTwoWaySet();
- Redetermine(twoWayCfg).execute(baseDirectory);
+ Redetermine::execute(twoWayCfg, baseDirectory);
return;
}
@@ -428,13 +441,20 @@ public:
if (respectFiltering(baseDirectory, dirInfoRight))
dbFilterRight = dirInfoRight.filter.get();
*/
- execute(baseDirectory,
+ recurse(baseDirectory,
&dirInfoLeft.baseDirContainer,
&dirInfoRight.baseDirContainer);
- }
+ //----------- detect renamed files -----------------
+ if (!exLeftOnly.empty() && !exRightOnly.empty())
+ {
+ findEqualDbEntries(dirInfoLeft.baseDirContainer, //fill map "onceEqual"
+ dirInfoRight.baseDirContainer);
+
+ detectRenamedFiles();
+ }
+ }
-private:
/*
static bool respectFiltering(const BaseDirMapping& baseDirectory, const DirInformation& dirInfo)
{
@@ -454,7 +474,7 @@ private:
catch (FileErrorDatabaseNotExisting&) {} //let's ignore these errors for now...
catch (FileError& error) //e.g. incompatible database version
{
- if (handler_) handler_->reportWarning(error.toString() + wxT(" \n\n") +
+ if (handler_) handler_->reportWarning(error.toString() + L" \n\n" +
_("Setting default synchronization directions: Old files will be overwritten with newer files."));
}
return std::pair<DirInfoPtr, DirInfoPtr>(); //NULL
@@ -477,7 +497,7 @@ private:
}
*/
- void execute(HierarchyObject& hierObj,
+ void recurse(HierarchyObject& hierObj,
const DirContainer* dbDirectoryLeft,
const DirContainer* dbDirectoryRight)
{
@@ -499,6 +519,18 @@ private:
if (cat == FILE_EQUAL)
return;
+ //----------------- prepare detection of renamed files -----------------
+ if (cat == FILE_LEFT_SIDE_ONLY)
+ {
+ if (fileObj.getFileId<LEFT_SIDE>() != FileId())
+ exLeftOnly.push_back(&fileObj);
+ }
+ else if (cat == FILE_RIGHT_SIDE_ONLY)
+ {
+ if (fileObj.getFileId<RIGHT_SIDE>() != FileId())
+ exRightOnly.insert(std::make_pair(getAssocKey<RIGHT_SIDE>(fileObj), &fileObj));
+ }
+ //----------------------------------------------------------------------
//##################### schedule potentially existing temporary files for deletion ####################
if (cat == FILE_LEFT_SIDE_ONLY && endsWith(fileObj.getFullName<LEFT_SIDE>(), zen::TEMP_FILE_ENDING))
@@ -530,14 +562,14 @@ private:
const DataSetFile dataDbLeft = retrieveDataSetFile(fileObj.getObjShortName(), dbDirectoryLeft);
const DataSetFile dataDbRight = retrieveDataSetFile(fileObj.getObjShortName(), dbDirectoryRight);
- const DataSetFile dataCurrentLeft( fileObj, Int2Type<LEFT_SIDE>());
+ const DataSetFile dataCurrentLeft (fileObj, Int2Type<LEFT_SIDE >());
const DataSetFile dataCurrentRight(fileObj, Int2Type<RIGHT_SIDE>());
//evaluation
const bool changeOnLeft = dataDbLeft != dataCurrentLeft;
const bool changeOnRight = dataDbRight != dataCurrentRight;
- if (dataDbLeft == dataDbRight) //last sync seems to have been successful
+ if (dataDbLeft == dataDbRight) //we have a "last synchronous state" => last sync seems to have been successful
{
if (changeOnLeft)
{
@@ -651,7 +683,7 @@ private:
;
}
- SetDirChangedFilter().execute(dirObj); //filter issue for this directory => treat subfiles/-dirs the same
+ SetDirChangedFilter().recurse(dirObj); //filter issue for this directory => treat subfiles/-dirs the same
return;
}
*/
@@ -711,18 +743,133 @@ private:
}
}
- execute(dirObj, dataDbLeftStuff.second, dataDbRightStuff.second); //recursion
+ recurse(dirObj, dataDbLeftStuff.second, dataDbRightStuff.second); //recursion
}
+
+ void findEqualDbEntries(const DirContainer& dbDirectoryLeft,
+ const DirContainer& dbDirectoryRight)
+ {
+ //note: we cannot integrate this traversal into "recurse()" since it may take a *slightly* different path: e.g. file renamed on both sides
+
+ std::for_each(dbDirectoryLeft.files.begin(), dbDirectoryLeft.files.end(),
+ [&](const DirContainer::FileList::value_type& entryLeft)
+ {
+ auto iterRight = dbDirectoryRight.files.find(entryLeft.first);
+ if (iterRight != dbDirectoryRight.files.end())
+ {
+ if (entryLeft. second.id != FileId() &&
+ iterRight->second.id != FileId() &&
+ DataSetFile(entryLeft.first, entryLeft.second) == DataSetFile(iterRight->first, iterRight->second))
+ onceEqual.insert(std::make_pair(getAssocKey(entryLeft.second), getAssocKey(iterRight->second)));
+ }
+ });
+
+ std::for_each(dbDirectoryLeft.dirs.begin(), dbDirectoryLeft.dirs.end(),
+ [&](const DirContainer::DirList::value_type& entryLeft)
+ {
+ auto iterRight = dbDirectoryRight.dirs.find(entryLeft.first);
+ if (iterRight != dbDirectoryRight.dirs.end())
+ findEqualDbEntries(entryLeft.second, iterRight->second);
+ });
+ }
+
+ typedef std::tuple<Int64, UInt64, FileId> AssocKey; //(date, size, file ID)
+
+
+ //modification date is *not* considered as part of container key, so check here!
+ template <class Container>
+ static typename Container::const_iterator findValue(const Container& cnt, const AssocKey& key)
+ {
+ auto iterPair = cnt.equal_range(key); //since file id is already unique, we expect a single-element range at most
+ auto iter = std::find_if(iterPair.first, iterPair.second,
+ [&](const typename Container::value_type& item)
+ {
+ return sameFileTime(std::get<0>(item.first), std::get<0>(key), 2); //respect 2 second FAT/FAT32 precision
+ });
+ return iter == iterPair.second ? cnt.end() : iter;
+ }
+
+ void detectRenamedFiles() const
+ {
+ std::for_each(exLeftOnly.begin(), exLeftOnly.end(),
+ [&](FileMapping* fileLeftOnly)
+ {
+ const AssocKey& keyLeft = RedetermineAuto::getAssocKey<LEFT_SIDE>(*fileLeftOnly);
+
+ auto iter = findValue(onceEqual, keyLeft);
+ if (iter != onceEqual.end())
+ {
+ const AssocKey& keyRight = iter->second;
+
+ auto iter2 = findValue(exRightOnly, keyRight);
+ if (iter2 != exRightOnly.end())
+ {
+ FileMapping* fileRightOnly = iter2->second;
+
+ //found a pair, mark it!
+ fileLeftOnly ->setMoveRef(fileRightOnly->getId());
+ fileRightOnly->setMoveRef(fileLeftOnly ->getId());
+ }
+ }
+ });
+ }
+
+
const std::wstring txtBothSidesChanged;
const std::wstring txtNoSideChanged;
const std::wstring txtFilterChanged;
const std::wstring txtLastSyncFail;
- //const HardFilter* dbFilterLeft; //optional
- //const HardFilter* dbFilterRight; //optional
-
DeterminationProblem* const handler_;
+
+ //detection of renamed files
+ template <SelectedSide side>
+ static AssocKey getAssocKey(const FileMapping& fsObj) { return std::make_tuple(fsObj.getLastWriteTime<side>(), fsObj.getFileSize<side>(), fsObj.getFileId<side>()); }
+ static AssocKey getAssocKey(const FileDescriptor& fileDescr) { return std::make_tuple(fileDescr.lastWriteTimeRaw, fileDescr.fileSize, fileDescr.id); }
+
+ struct LessAssocKey
+ {
+ bool operator()(const AssocKey& lhs, const AssocKey& rhs) const
+ {
+ //caveat: *don't* allow 2 sec tolerance as container predicate!!
+ // => no strict weak ordering relation! reason: no transitivity of equivalence!
+
+ //-> bad: if (!sameFileTime(std::get<0>(lhs), std::get<0>(rhs), 2))
+ // return std::get<0>(lhs) < std::get<0>(rhs);
+
+ if (std::get<1>(lhs) != std::get<1>(rhs)) //file size
+ return std::get<1>(lhs) < std::get<1>(rhs);
+
+ return std::get<2>(lhs) < std::get<2>(rhs); //file id
+ }
+ };
+
+ std::vector<FileMapping*> exLeftOnly;
+
+ std::multimap<AssocKey, AssocKey, LessAssocKey> onceEqual; //keys for left and right files which are considered "equal" by database
+
+ std::multimap<AssocKey, FileMapping*, LessAssocKey> exRightOnly;
+
+ /*
+ detect renamed files
+
+ X -> |_| Create right
+ |_| -> Y Delete right
+
+ is detected as:
+
+ Rename Y to X on right
+
+ Algorithm:
+ ----------
+ DB-file left --- name, size, date ---> DB-file right
+ /|\ |
+ | file ID, size, date
+ file ID, size, date |
+ | \|/
+ X Y
+ */
};
@@ -750,11 +897,11 @@ std::vector<DirectionConfig> zen::extractDirectionCfg(const MainConfiguration& m
void zen::redetermineSyncDirection(const DirectionConfig& directConfig, BaseDirMapping& baseDirectory, DeterminationProblem* handler)
{
if (directConfig.var == DirectionConfig::AUTOMATIC)
- RedetermineAuto(baseDirectory, handler);
+ RedetermineAuto::execute(baseDirectory, handler);
else
{
DirectionSet dirCfg = extractDirections(directConfig);
- Redetermine(dirCfg).execute(baseDirectory);
+ Redetermine::execute(dirCfg, baseDirectory);
}
}
diff --git a/algorithm.h b/algorithm.h
index 6eb9f24d..96ff6b1a 100644
--- a/algorithm.h
+++ b/algorithm.h
@@ -17,7 +17,7 @@ void swapGrids(const MainConfiguration& config, FolderComparison& folderCmp);
struct DeterminationProblem //callback
{
virtual ~DeterminationProblem() {}
- virtual void reportWarning(const wxString& text) = 0;
+ virtual void reportWarning(const std::wstring& text) = 0;
};
std::vector<DirectionConfig> extractDirectionCfg(const MainConfiguration& mainCfg);
@@ -56,7 +56,7 @@ public:
IGNORE_ERROR = 10,
RETRY
};
- virtual Response reportError(const wxString& errorMessage) = 0;
+ virtual Response reportError(const std::wstring& errorMessage) = 0;
//virtual void totalFilesToDelete(int objectsTotal) = 0; //informs about the total number of files to be deleted
virtual void notifyDeletion(const Zstring& currentObject) = 0; //called for each file/folder that has been deleted
diff --git a/comparison.cpp b/comparison.cpp
index 79b18ae9..f66c291e 100644
--- a/comparison.cpp
+++ b/comparison.cpp
@@ -5,16 +5,16 @@
// **************************************************************************
#include "comparison.h"
+#include <stdexcept>
+#include <zen/scope_guard.h>
+#include <wx+/string_conv.h>
+#include <wx+/format_unit.h>
#include "lib/parallel_scan.h"
#include "lib/resolve_path.h"
-#include <stdexcept>
#include "lib/dir_exist_async.h"
-#include <wx+/string_conv.h>
-#include <zen/scope_guard.h>
#include "lib/binary.h"
-#include "algorithm.h"
-#include <wx+/format_unit.h>
#include "lib/cmp_filetime.h"
+#include "algorithm.h"
#ifdef FFS_WIN
#include <zen/perf.h>
@@ -120,39 +120,33 @@ void checkDirectoryExistence(const std::set<Zstring, LessFilename>& dirnames,
}
-namespace
-{
-struct EqualDependentDirectory : public std::binary_function<Zstring, Zstring, bool>
-{
- bool operator()(const Zstring& lhs, const Zstring& rhs) const
- {
- return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())),
- Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length())));
- }
-};
-}
-
//check whether one side is subdirectory of other side (folder pair wise!)
//similar check if one directory is read/written by multiple pairs not before beginning of synchronization
-wxString checkFolderDependency(const std::vector<FolderPairCfg>& folderPairsForm) //returns warning message, empty if all ok
+std::wstring checkFolderDependency(const std::vector<FolderPairCfg>& folderPairsForm) //returns warning message, empty if all ok
{
- typedef std::vector<std::pair<wxString, wxString> > DirDirList;
+ typedef std::vector<std::pair<std::wstring, std::wstring> > DirDirList;
DirDirList dependentDirs;
+ auto dependentDir = [](const Zstring& lhs, const Zstring& rhs)
+ {
+ return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), //note: this is NOT an equivalence relation!
+ Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length())));
+ };
+
for (std::vector<FolderPairCfg>::const_iterator i = folderPairsForm.begin(); i != folderPairsForm.end(); ++i)
if (!i->leftDirectoryFmt.empty() && !i->rightDirectoryFmt.empty()) //empty folders names may be accepted by user
{
- if (EqualDependentDirectory()(i->leftDirectoryFmt, i->rightDirectoryFmt)) //test wheter leftDirectory begins with rightDirectory or the other way round
- dependentDirs.push_back(std::make_pair(toWx(i->leftDirectoryFmt), toWx(i->rightDirectoryFmt)));
+ if (dependentDir(i->leftDirectoryFmt, i->rightDirectoryFmt)) //test wheter leftDirectory begins with rightDirectory or the other way round
+ dependentDirs.push_back(std::make_pair(utf8CvrtTo<std::wstring>(i->leftDirectoryFmt), utf8CvrtTo<std::wstring>(i->rightDirectoryFmt)));
}
- wxString warningMsg;
+ std::wstring warningMsg;
if (!dependentDirs.empty())
{
warningMsg = _("Directories are dependent! Be careful when setting up synchronization rules:");
for (auto i = dependentDirs.begin(); i != dependentDirs.end(); ++i)
- warningMsg += wxString(L"\n\n") +
+ warningMsg += std::wstring(L"\n\n") +
L"\"" + i->first + L"\"\n" +
L"\"" + i->second + L"\"";
}
@@ -214,17 +208,17 @@ CompareProcess::CompareProcess(size_t fileTimeTol,
m_warnings(warnings),
allowUserInteraction_(allowUserInteraction),
procCallback(handler)
- {
-if (runWithBackgroundPriority)
-procBackground.reset(new ScheduleForBackgroundProcessing);
- }
+{
+ if (runWithBackgroundPriority)
+ procBackground.reset(new ScheduleForBackgroundProcessing);
+}
void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& cfgList, FolderComparison& output)
{
- //prevent shutdown while (binary) comparison is in progress
- DisableStandby dummy2;
- (void)dummy2;
+ //prevent shutdown while (binary) comparison is in progress
+ PreventStandby dummy2;
+ (void)dummy2;
/*
#ifdef NDEBUG
@@ -257,9 +251,9 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& cfgLi
{
//check if folders have dependencies
- wxString warningMessage = checkFolderDependency(cfgList);
+ std::wstring warningMessage = checkFolderDependency(cfgList);
if (!warningMessage.empty())
- procCallback.reportWarning(warningMessage.c_str(), m_warnings.warningDependentFolders);
+ procCallback.reportWarning(warningMessage, m_warnings.warningDependentFolders);
}
//-------------------end of basic checks------------------------------------------
@@ -364,7 +358,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& cfgLi
warningSyncDatabase_(warningSyncDatabase),
procCallback_(procCallback) {}
- virtual void reportWarning(const wxString& text)
+ virtual void reportWarning(const std::wstring& text)
{
procCallback_.reportWarning(text, warningSyncDatabase_);
}
@@ -404,25 +398,14 @@ std::wstring getConflictInvalidDate(const Zstring& fileNameFull, Int64 utcTime)
namespace
{
-inline
-void makeSameLength(wxString& first, wxString& second)
-{
- const size_t maxPref = std::max(first.length(), second.length());
- first.Pad(maxPref - first.length(), wxT(' '), true);
- second.Pad(maxPref - second.length(), wxT(' '), true);
-}
-
-
//check for changed files with same modification date
std::wstring getConflictSameDateDiffSize(const FileMapping& fileObj)
{
std::wstring msg = _("Files %x have the same date but a different size!");
replace(msg, L"%x", std::wstring(L"\"") + fileObj.getRelativeName<LEFT_SIDE>() + L"\"");
msg += L"\n\n";
- msg += L"<-- \t" + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<LEFT_SIDE>()) +
- L" \t" + _("Size") + L": " + toStringSep(fileObj.getFileSize<LEFT_SIDE>()) + L"\n";
- msg += L"--> \t" + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<RIGHT_SIDE>()) +
- L" \t" + _("Size") + L": " + toStringSep(fileObj.getFileSize<RIGHT_SIDE>());
+ msg += L"<-- " + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<LEFT_SIDE >()) + L" " + _("Size") + L": " + toStringSep(fileObj.getFileSize<LEFT_SIDE>()) + L"\n";
+ msg += L"--> " + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<RIGHT_SIDE>()) + L" " + _("Size") + L": " + toStringSep(fileObj.getFileSize<RIGHT_SIDE>());
return _("Conflict detected:") + L"\n" + msg;
}
}
@@ -625,7 +608,7 @@ void CompareProcess::compareByContent(std::vector<std::pair<FolderPairCfg, BaseD
const CmpFileTime timeCmp(fileTimeTolerance);
-const std::wstring txtComparingContentOfFiles = replaceCpy(_("Comparing content of files %x"), L"%x", L"\n\"%x\"", false);
+ const std::wstring txtComparingContentOfFiles = replaceCpy(_("Comparing content of files %x"), L"%x", L"\n\"%x\"", false);
//compare files (that have same size) bytewise...
std::for_each(filesToCompareBytewise.begin(), filesToCompareBytewise.end(),
@@ -697,36 +680,19 @@ private:
};
-template <>
-void MergeSides::fillOneSide<LEFT_SIDE>(const DirContainer& dirCont, HierarchyObject& output)
-{
- for (DirContainer::FileList::const_iterator i = dirCont.files.begin(); i != dirCont.files.end(); ++i)
- output.addSubFile(i->second, i->first);
-
- for (DirContainer::LinkList::const_iterator i = dirCont.links.begin(); i != dirCont.links.end(); ++i)
- output.addSubLink(i->second, i->first);
-
- for (DirContainer::DirList::const_iterator i = dirCont.dirs.begin(); i != dirCont.dirs.end(); ++i)
- {
- DirMapping& newDirMap = output.addSubDir(i->first, Zstring());
- fillOneSide<LEFT_SIDE>(i->second, newDirMap); //recurse into subdirectories
- }
-}
-
-
-template <>
-void MergeSides::fillOneSide<RIGHT_SIDE>(const DirContainer& dirCont, HierarchyObject& output)
+template <SelectedSide side>
+void MergeSides::fillOneSide(const DirContainer& dirCont, HierarchyObject& output)
{
- for (DirContainer::FileList::const_iterator i = dirCont.files.begin(); i != dirCont.files.end(); ++i)
- output.addSubFile(i->first, i->second);
+ for (auto iter = dirCont.files.cbegin(); iter != dirCont.files.cend(); ++iter)
+ output.addSubFile<side>(iter->first, iter->second);
- for (DirContainer::LinkList::const_iterator i = dirCont.links.begin(); i != dirCont.links.end(); ++i)
- output.addSubLink(i->first, i->second);
+ for (auto iter = dirCont.links.cbegin(); iter != dirCont.links.cend(); ++iter)
+ output.addSubLink<side>(iter->first, iter->second);
- for (DirContainer::DirList::const_iterator i = dirCont.dirs.begin(); i != dirCont.dirs.end(); ++i)
+ for (auto iter = dirCont.dirs.cbegin(); iter != dirCont.dirs.cend(); ++iter)
{
- DirMapping& newDirMap = output.addSubDir(Zstring(), i->first);
- fillOneSide<RIGHT_SIDE>(i->second, newDirMap); //recurse into subdirectories
+ DirMapping& newDirMap = output.addSubDir<side>(iter->first);
+ fillOneSide<side>(iter->second, newDirMap); //recurse
}
}
@@ -777,8 +743,8 @@ void MergeSides::execute(const DirContainer& leftSide, const DirContainer& right
typedef const DirContainer::FileList::value_type FileData;
linearMerge(leftSide.files, rightSide.files,
- [&](const FileData& fileLeft) { output.addSubFile(fileLeft.second, fileLeft.first); }, //left only
- [&](const FileData& fileRight) { output.addSubFile(fileRight.first, fileRight.second); }, //right only
+ [&](const FileData& fileLeft) { output.addSubFile<LEFT_SIDE> (fileLeft.first, fileLeft.second); }, //left only
+ [&](const FileData& fileRight) { output.addSubFile<RIGHT_SIDE>(fileRight.first, fileRight.second); }, //right only
[&](const FileData& fileLeft, const FileData& fileRight) //both sides
{
@@ -794,8 +760,8 @@ void MergeSides::execute(const DirContainer& leftSide, const DirContainer& right
typedef const DirContainer::LinkList::value_type LinkData;
linearMerge(leftSide.links, rightSide.links,
- [&](const LinkData& linkLeft) { output.addSubLink(linkLeft.second, linkLeft.first); }, //left only
- [&](const LinkData& linkRight) { output.addSubLink(linkRight.first, linkRight.second); }, //right only
+ [&](const LinkData& linkLeft) { output.addSubLink<LEFT_SIDE >(linkLeft.first, linkLeft.second); }, //left only
+ [&](const LinkData& linkRight) { output.addSubLink<RIGHT_SIDE>(linkRight.first, linkRight.second); }, //right only
[&](const LinkData& linkLeft, const LinkData& linkRight) //both sides
{
@@ -813,12 +779,12 @@ void MergeSides::execute(const DirContainer& leftSide, const DirContainer& right
linearMerge(leftSide.dirs, rightSide.dirs,
[&](const DirData& dirLeft) //left only
{
- DirMapping& newDirMap = output.addSubDir(dirLeft.first, Zstring());
+ DirMapping& newDirMap = output.addSubDir<LEFT_SIDE>(dirLeft.first);
this->fillOneSide<LEFT_SIDE>(dirLeft.second, newDirMap); //recurse into subdirectories
},
[&](const DirData& dirRight) //right only
{
- DirMapping& newDirMap = output.addSubDir(Zstring(), dirRight.first);
+ DirMapping& newDirMap = output.addSubDir<RIGHT_SIDE>(dirRight.first);
this->fillOneSide<RIGHT_SIDE>(dirRight.second, newDirMap); //recurse into subdirectories
},
@@ -839,7 +805,7 @@ void processFilteredDirs(HierarchyObject& hierObj, const HardFilter& filterProc)
std::for_each(subDirs.begin(), subDirs.end(),
[&](DirMapping& dirObj)
{
- dirObj.setActive(filterProc.passDirFilter(dirObj.getObjRelativeName().c_str(), NULL)); //subObjMightMatch is always true in this context!
+ dirObj.setActive(filterProc.passDirFilter(dirObj.getObjRelativeName(), NULL)); //subObjMightMatch is always true in this context!
processFilteredDirs(dirObj, filterProc);
});
@@ -878,7 +844,6 @@ void CompareProcess::performComparison(const FolderPairCfg& fpCfg,
const DirectoryValue& bufValueRight = getDirValue(fpCfg.rightDirectoryFmt);
procCallback.reportStatus(_("Generating file list..."));
- procCallback.forceUiRefresh(); //keep total number of scanned files up to date
//PERF_START;
MergeSides(undefinedFiles, undefinedLinks).execute(bufValueLeft.dirCont, bufValueRight.dirCont, output);
diff --git a/comparison.h b/comparison.h
index 3928f44e..f3226e90 100644
--- a/comparison.h
+++ b/comparison.h
@@ -7,11 +7,11 @@
#ifndef COMPARISON_H_INCLUDED
#define COMPARISON_H_INCLUDED
+#include <zen/process_status.h>
#include "file_hierarchy.h"
#include "lib/process_xml.h"
#include "lib/status_handler.h"
#include "structures.h"
-#include <zen/process_status.h>
#include "lib/norm_filter.h"
#include "lib/parallel_scan.h"
diff --git a/file_hierarchy.cpp b/file_hierarchy.cpp
index cfe1b6a0..39b789fd 100644
--- a/file_hierarchy.cpp
+++ b/file_hierarchy.cpp
@@ -5,6 +5,8 @@
// **************************************************************************
#include "file_hierarchy.h"
+#include <zen/i18n.h>
+#include <zen/utf8.h>
using namespace zen;
@@ -31,12 +33,12 @@ void HierarchyObject::removeEmptyRec()
std::for_each(refSubDirs().begin(), refSubDirs().end(), std::mem_fun_ref(&HierarchyObject::removeEmptyRec));
}
-
-SyncOperation FileSystemObject::getSyncOperation(
- CompareFilesResult cmpResult,
- bool selectedForSynchronization,
- SyncDirection syncDir,
- const std::wstring& syncDirConflict)
+namespace
+{
+SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
+ bool selectedForSynchronization,
+ SyncDirection syncDir,
+ const std::wstring& syncDirConflict)
{
if (!selectedForSynchronization)
return cmpResult == FILE_EQUAL ?
@@ -105,8 +107,6 @@ SyncOperation FileSystemObject::getSyncOperation(
}
-namespace
-{
template <class Predicate> inline
bool hasDirectChild(const HierarchyObject& hierObj, Predicate p)
{
@@ -117,6 +117,22 @@ bool hasDirectChild(const HierarchyObject& hierObj, Predicate p)
}
+SyncOperation FileSystemObject::testSyncOperation(SyncDirection testSyncDir) const
+{
+ return proposedSyncOperation(getCategory(), selectedForSynchronization, testSyncDir, syncDirConflict);
+}
+
+
+SyncOperation FileSystemObject::getSyncOperation() const
+{
+ return FileSystemObject::testSyncOperation(syncDir);
+ //no *not* make a virtual call to testSyncOperation()! See FileMapping::testSyncOperation()!
+}
+
+
+//SyncOperation DirMapping::testSyncOperation() const -> not required: we do NOT want to consider child elements when testing!
+
+
SyncOperation DirMapping::getSyncOperation() const
{
if (!syncOpUpToDate)
@@ -124,7 +140,7 @@ SyncOperation DirMapping::getSyncOperation() const
syncOpUpToDate = true;
//redetermine...
- //suggested operation for directory only
+ //suggested operation *not* considering child elements
syncOpBuffered = FileSystemObject::getSyncOperation();
//action for child elements may occassionally have to overwrite parent task:
@@ -132,6 +148,10 @@ SyncOperation DirMapping::getSyncOperation() const
{
case SO_OVERWRITE_LEFT:
case SO_OVERWRITE_RIGHT:
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
assert(false);
case SO_CREATE_NEW_LEFT:
case SO_CREATE_NEW_RIGHT:
@@ -149,19 +169,32 @@ SyncOperation DirMapping::getSyncOperation() const
//1. if at least one child-element is to be created, make sure parent folder is created also
//note: this automatically fulfills "create parent folders even if excluded";
//see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080
- if (hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() == SO_CREATE_NEW_LEFT; }))
- syncOpBuffered = SO_CREATE_NEW_LEFT;
+ if (hasDirectChild(*this,
+ [](const FileSystemObject& fsObj) -> bool { const SyncOperation op = fsObj.getSyncOperation(); return op == SO_CREATE_NEW_LEFT || op == SO_MOVE_LEFT_TARGET; }))
+ syncOpBuffered = SO_CREATE_NEW_LEFT;
//2. cancel parent deletion if only a single child is not also scheduled for deletion
else if (syncOpBuffered == SO_DELETE_RIGHT &&
- hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() != SO_DELETE_RIGHT; }))
+ hasDirectChild(*this,
+ [](const FileSystemObject& fsObj) -> bool
+ {
+ if (fsObj.isEmpty()) return false; //fsObj may already be empty because it once contained a "move source"
+ const SyncOperation op = fsObj.getSyncOperation(); return op != SO_DELETE_RIGHT && op != SO_MOVE_RIGHT_SOURCE;
+ }))
syncOpBuffered = SO_DO_NOTHING;
}
else if (isEmpty<RIGHT_SIDE>())
{
- if (hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() == SO_CREATE_NEW_RIGHT; }))
- syncOpBuffered = SO_CREATE_NEW_RIGHT;
+ if (hasDirectChild(*this,
+ [](const FileSystemObject& fsObj) -> bool { const SyncOperation op = fsObj.getSyncOperation(); return op == SO_CREATE_NEW_RIGHT || op == SO_MOVE_RIGHT_TARGET; }))
+ syncOpBuffered = SO_CREATE_NEW_RIGHT;
else if (syncOpBuffered == SO_DELETE_LEFT &&
- hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() != SO_DELETE_LEFT; }))
+ hasDirectChild(*this,
+ [](const FileSystemObject& fsObj) -> bool
+ {
+ if (fsObj.isEmpty()) return false;
+ const SyncOperation op = fsObj.getSyncOperation();
+ return op != SO_DELETE_LEFT && op != SO_MOVE_LEFT_SOURCE;
+ }))
syncOpBuffered = SO_DO_NOTHING;
}
}
@@ -170,3 +203,167 @@ SyncOperation DirMapping::getSyncOperation() const
}
return syncOpBuffered;
}
+
+
+SyncOperation FileMapping::testSyncOperation(SyncDirection testSyncDir) const
+{
+ SyncOperation op = FileSystemObject::testSyncOperation(testSyncDir);
+
+ /*
+ check whether we can optimize "create + delete" via "move":
+ note: as long as we consider "create + delete" cases only, detection of renamed files, should be fine even for "binary" comparison variant!
+ */
+ if (const FileMapping* refFile = dynamic_cast<const FileMapping*>(FileSystemObject::retrieve(moveFileRef)))
+ {
+ SyncOperation opRef = refFile->FileSystemObject::getSyncOperation(); //do *not* make a virtual call!
+
+ if (op == SO_CREATE_NEW_LEFT &&
+ opRef == SO_DELETE_LEFT)
+ op = SO_MOVE_LEFT_TARGET;
+ else if (op == SO_DELETE_LEFT &&
+ opRef == SO_CREATE_NEW_LEFT)
+ op = SO_MOVE_LEFT_SOURCE;
+ else if (op == SO_CREATE_NEW_RIGHT &&
+ opRef == SO_DELETE_RIGHT)
+ op = SO_MOVE_RIGHT_TARGET;
+ else if (op == SO_DELETE_RIGHT &&
+ opRef == SO_CREATE_NEW_RIGHT)
+ op = SO_MOVE_RIGHT_SOURCE;
+ }
+ return op;
+}
+
+
+SyncOperation FileMapping::getSyncOperation() const
+{
+ return FileMapping::testSyncOperation(getSyncDir());
+}
+
+
+std::wstring zen::getCategoryDescription(CompareFilesResult cmpRes)
+{
+ switch (cmpRes)
+ {
+ case FILE_LEFT_SIDE_ONLY:
+ return _("File/folder exists on left side only");
+ case FILE_RIGHT_SIDE_ONLY:
+ return _("File/folder exists on right side only");
+ case FILE_LEFT_NEWER:
+ return _("Left file is newer");
+ case FILE_RIGHT_NEWER:
+ return _("Right file is newer");
+ case FILE_DIFFERENT:
+ return _("Files have different content");
+ case FILE_EQUAL:
+ return _("Both sides are equal");
+ case FILE_DIFFERENT_METADATA:
+ return _("Files/folders differ in attributes only");
+ case FILE_CONFLICT:
+ return _("Conflict/file cannot be categorized");
+ }
+ assert(false);
+ return std::wstring();
+}
+
+
+std::wstring zen::getCategoryDescription(const FileSystemObject& fsObj)
+{
+ const CompareFilesResult cmpRes = fsObj.getCategory();
+ if (cmpRes == FILE_CONFLICT)
+ return fsObj.getCatConflict();
+
+ return getCategoryDescription(cmpRes);
+}
+
+
+std::wstring zen::getSyncOpDescription(SyncOperation op)
+{
+ switch (op)
+ {
+ case SO_CREATE_NEW_LEFT:
+ return _("Copy new file/folder to left");
+ case SO_CREATE_NEW_RIGHT:
+ return _("Copy new file/folder to right");
+ case SO_DELETE_LEFT:
+ return _("Delete left file/folder");
+ case SO_DELETE_RIGHT:
+ return _("Delete right file/folder");
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ return _("Move file on left");
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
+ return _("Move file on right");
+ case SO_OVERWRITE_LEFT:
+ return _("Overwrite left file/folder with right one");
+ case SO_OVERWRITE_RIGHT:
+ return _("Overwrite right file/folder with left one");
+ case SO_DO_NOTHING:
+ return _("Do nothing");
+ case SO_EQUAL:
+ return _("Both sides are equal");
+ case SO_COPY_METADATA_TO_LEFT:
+ return _("Copy file attributes only to left");
+ case SO_COPY_METADATA_TO_RIGHT:
+ return _("Copy file attributes only to right");
+ case SO_UNRESOLVED_CONFLICT: //not used on GUI, but in .csv
+ _("Conflict/file cannot be categorized");
+ }
+ assert(false);
+ return std::wstring();
+}
+
+
+std::wstring zen::getSyncOpDescription(const FileSystemObject& fsObj)
+{
+ const SyncOperation op = fsObj.getSyncOperation();
+ switch (op)
+ {
+ case SO_CREATE_NEW_LEFT:
+ case SO_CREATE_NEW_RIGHT:
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ case SO_OVERWRITE_LEFT:
+ case SO_OVERWRITE_RIGHT:
+ case SO_DO_NOTHING:
+ case SO_EQUAL:
+ case SO_COPY_METADATA_TO_LEFT:
+ case SO_COPY_METADATA_TO_RIGHT:
+ return getSyncOpDescription(op); //use generic description
+
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
+ if (const FileMapping* sourceFile = dynamic_cast<const FileMapping*>(&fsObj))
+ if (const FileMapping* targetFile = dynamic_cast<const FileMapping*>(FileSystemObject::retrieve(sourceFile->getMoveRef())))
+ {
+ const bool onLeft = op == SO_MOVE_LEFT_SOURCE || op == SO_MOVE_LEFT_TARGET;
+ const bool isSource = op == SO_MOVE_LEFT_SOURCE || op == SO_MOVE_RIGHT_SOURCE;
+
+ if (!isSource)
+ std::swap(sourceFile, targetFile);
+
+ auto getRelName = [&](const FileSystemObject& fso, bool leftSide) { return leftSide ? fso.getRelativeName<LEFT_SIDE>() : fso.getRelativeName<RIGHT_SIDE>(); };
+
+ const Zstring relSource = getRelName(*sourceFile, onLeft);
+ const Zstring relTarget = getRelName(*targetFile, !onLeft);
+
+ return getSyncOpDescription(op) + L"\n" +
+ (EqualFilename()(beforeLast(relSource, FILE_NAME_SEPARATOR), beforeLast(relTarget, FILE_NAME_SEPARATOR)) ? //returns empty string if ch not found
+ //detected pure "rename"
+ L"\"" + utf8CvrtTo<std::wstring>(afterLast(relSource, FILE_NAME_SEPARATOR)) + L"\"" + L" ->\n" + //show short name only
+ L"\"" + utf8CvrtTo<std::wstring>(afterLast(relTarget, FILE_NAME_SEPARATOR)) + L"\"" :
+ //"move" or "move + rename"
+ L"\"" + utf8CvrtTo<std::wstring>(relSource) + L"\"" + L" ->\n" +
+ L"\"" + utf8CvrtTo<std::wstring>(relTarget) + L"\"");
+ //attention: ::SetWindowText() doesn't handle tab characters correctly in combination with certain file names, so don't use them
+ }
+ break;
+ case SO_UNRESOLVED_CONFLICT:
+ return fsObj.getSyncOpConflict();
+ }
+
+ assert(false);
+ return std::wstring();
+}
diff --git a/file_hierarchy.h b/file_hierarchy.h
index 6ea9d244..cfa71ab2 100644
--- a/file_hierarchy.h
+++ b/file_hierarchy.h
@@ -15,6 +15,7 @@
#include <zen/fixed_list.h>
#include "structures.h"
#include <zen/int64.h>
+#include <zen/file_id_def.h>
#include "structures.h"
#include "lib/hard_filter.h"
@@ -24,13 +25,16 @@ namespace zen
struct FileDescriptor
{
FileDescriptor() {}
- FileDescriptor(zen::Int64 lastWriteTimeRawIn,
- zen::UInt64 fileSizeIn) :
+ FileDescriptor(Int64 lastWriteTimeRawIn,
+ UInt64 fileSizeIn,
+ const FileId& idIn) :
lastWriteTimeRaw(lastWriteTimeRawIn),
- fileSize(fileSizeIn) {}
+ fileSize(fileSizeIn),
+ id(idIn) {}
- zen::Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long)
- zen::UInt64 fileSize;
+ Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long)
+ UInt64 fileSize;
+ FileId id; //optional! (however, always set on Linux, and *generally* available on Windows)
};
@@ -43,16 +47,16 @@ struct LinkDescriptor
};
LinkDescriptor() : type(TYPE_FILE) {}
- LinkDescriptor(zen::Int64 lastWriteTimeRawIn,
+ LinkDescriptor(Int64 lastWriteTimeRawIn,
const Zstring& targetPathIn,
LinkType lt) :
lastWriteTimeRaw(lastWriteTimeRawIn),
targetPath(targetPathIn),
type(lt) {}
- zen::Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long)
- Zstring targetPath; //symlink "content", may be empty if determination failed
- LinkType type; //type is required for Windows only! On Linux there is no such thing => consider this when comparing Symbolic Links!
+ Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long)
+ Zstring targetPath; //symlink "content", may be empty if determination failed
+ LinkType type; //type is required for Windows only! On Linux there is no such thing => consider this when comparing Symbolic Links!
};
@@ -119,6 +123,9 @@ struct DirContainer
//------------------------------------------------------------------
/* inheritance diagram:
+ ObjectMgr
+ /|\
+ |
FileSystemObject HierarchyObject
/|\ /|\
_______________|______________ ______|______
@@ -133,32 +140,36 @@ class HierarchyObject
friend class FileSystemObject;
typedef zen::FixedList<FileMapping> SubFileVec; //MergeSides::execute() requires a structure that doesn't invalidate pointers after push_back()
- typedef zen::FixedList<SymLinkMapping> SubLinkVec; //Note: deque<> has circular reference in VCPP!
+ typedef zen::FixedList<SymLinkMapping> SubLinkVec; //Note: deque<> has circular dependency in VCPP!
typedef zen::FixedList<DirMapping> SubDirVec;
public:
DirMapping& addSubDir(const Zstring& shortNameLeft,
const Zstring& shortNameRight);
+ template <SelectedSide side>
+ DirMapping& addSubDir(const Zstring& shortName); //dir exists on one side only
+
+
FileMapping& addSubFile(const Zstring& shortNameLeft,
const FileDescriptor& left, //file exists on both sides
CompareFilesResult defaultCmpResult,
const Zstring& shortNameRight,
const FileDescriptor& right);
- void addSubFile(const FileDescriptor& left, //file exists on left side only
- const Zstring& shortNameLeft);
- void addSubFile(const Zstring& shortNameRight, //file exists on right side only
- const FileDescriptor& right);
+
+ template <SelectedSide side>
+ FileMapping& addSubFile(const Zstring& shortNameRight, //file exists on one side only
+ const FileDescriptor& right);
SymLinkMapping& addSubLink(const Zstring& shortNameLeft,
const LinkDescriptor& left, //link exists on both sides
CompareSymlinkResult defaultCmpResult,
const Zstring& shortNameRight,
const LinkDescriptor& right);
- void addSubLink(const LinkDescriptor& left, //link exists on left side only
- const Zstring& shortNameLeft);
- void addSubLink(const Zstring& shortNameRight, //link exists on right side only
- const LinkDescriptor& right);
+
+ template <SelectedSide side>
+ SymLinkMapping& addSubLink(const Zstring& shortName, //link exists on one side only
+ const LinkDescriptor& descr);
const SubFileVec& refSubFiles() const { return subFiles; }
/**/ SubFileVec& refSubFiles() { return subFiles; }
@@ -225,7 +236,7 @@ public:
virtual void flip();
private:
- BaseDirMapping(const BaseDirMapping&); //this class is referenced by HierarchyObject => make it non-copyable/movable!
+ BaseDirMapping(const BaseDirMapping&); //this class is referenced by HierarchyObject => make it non-copyable/movable!
BaseDirMapping& operator=(const BaseDirMapping&); //
//this member is currently not used by the business logic -> may be removed!
@@ -286,7 +297,7 @@ public:
virtual void visit(const DirMapping& dirObj) = 0;
};
-//inherit from this class to allow safe access by id instead of unsafe raw pointer
+//inherit from this class to allow safe random access by id instead of unsafe raw pointer
//allow for similar semantics like std::weak_ptr without having to use std::shared_ptr
template <class T>
class ObjectMgr
@@ -296,9 +307,9 @@ public:
ObjectID getId() { activeObjects().insert(this); return this; }
//unfortunately we need to keep this method non-const to get non-const "this" pointer
- //we could instead put this into the constructor, but temporaries created by STL would lead to some overhead
+ //we could instead put this into the constructor, but temporaries created by STL could lead to some overhead
- static T* retrieve(ObjectID id) //returns NULL if object is not found
+ static T* retrieve(ObjectID id) //returns NULL if object is not valid anymore
{
auto iter = activeObjects().find(const_cast<ObjectMgr*>(id));
return static_cast<T*>(iter == activeObjects().end() ? NULL : *iter); //static down-cast
@@ -337,13 +348,14 @@ public:
virtual CompareFilesResult getCategory() const = 0;
virtual std::wstring getCatConflict() const = 0; //only filled if getCategory() == FILE_CONFLICT
//sync operation
+ virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const;
virtual SyncOperation getSyncOperation() const;
std::wstring getSyncOpConflict() const; //return conflict when determining sync direction or during categorization
- SyncOperation testSyncOperation(SyncDirection syncDir) const; //get syncOp with provided settings
//sync settings
void setSyncDir(SyncDirection newDir);
void setSyncDirConflict(const std::wstring& description); //set syncDir = SYNC_DIR_NONE + fill conflict description
+ SyncDirection getSyncDir() const { return syncDir; }
bool isActive() const;
void setActive(bool active);
@@ -383,11 +395,6 @@ private:
virtual void removeObjectL() = 0;
virtual void removeObjectR() = 0;
- static SyncOperation getSyncOperation(CompareFilesResult cmpResult,
- bool selectedForSynchronization,
- SyncDirection syncDir,
- const std::wstring& syncDirConflict); //evaluate comparison result and sync direction
-
bool selectedForSynchronization;
SyncDirection syncDir;
std::wstring syncDirConflict; //non-empty if we have a conflict setting sync-direction
@@ -461,25 +468,33 @@ class FileMapping : public FileSystemObject
public:
virtual void accept(FSObjectVisitor& visitor) const;
- FileMapping(const Zstring& shortNameLeft, //use empty string if "not existing"
- const FileDescriptor& left,
- CompareFilesResult defaultCmpResult,
- const Zstring& shortNameRight, //
- const FileDescriptor& right,
+ FileMapping(const Zstring& shortNameLeft, //use empty string if "not existing"
+ const FileDescriptor& left,
+ CompareFilesResult defaultCmpResult,
+ const Zstring& shortNameRight, //
+ const FileDescriptor& right,
HierarchyObject& parentObj) :
FileSystemObject(shortNameLeft, shortNameRight, parentObj),
cmpResult(defaultCmpResult),
dataLeft(left),
- dataRight(right) {}
+ dataRight(right),
+ moveFileRef(NULL) {}
template <SelectedSide side> Int64 getLastWriteTime() const;
- template <SelectedSide side> UInt64 getFileSize() const;
+ template <SelectedSide side> UInt64 getFileSize () const;
+ template <SelectedSide side> FileId getFileId () const;
template <SelectedSide side> const Zstring getExtension() const;
+ void setMoveRef(ObjectID refId) { moveFileRef = refId; } //reference to corresponding renamed file
+ ObjectID getMoveRef() const { return moveFileRef; } //may be NULL
+
virtual CompareFilesResult getCategory() const;
virtual std::wstring getCatConflict() const;
- template <SelectedSide side> void copyTo(const FileDescriptor* srcDescr); //copy + update file attributes
+ virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const;
+ virtual SyncOperation getSyncOperation() const;
+
+ template <SelectedSide side> void syncTo(const FileDescriptor& descrTarget, const FileDescriptor* descrSource = NULL); //copy + update file attributes (optional)
private:
template <CompareFilesResult res>
@@ -497,6 +512,8 @@ private:
FileDescriptor dataLeft;
FileDescriptor dataRight;
+
+ ObjectID moveFileRef;
};
//------------------------------------------------------------------
@@ -549,7 +566,15 @@ private:
//------------------------------------------------------------------
+//generic type descriptions (usecase CSV legend, sync config)
+std::wstring getCategoryDescription(CompareFilesResult cmpRes);
+std::wstring getSyncOpDescription (SyncOperation op);
+//item-specific type descriptions
+std::wstring getCategoryDescription(const FileSystemObject& fsObj);
+std::wstring getSyncOpDescription (const FileSystemObject& fsObj);
+
+//------------------------------------------------------------------
@@ -681,20 +706,6 @@ void FileSystemObject::setActive(bool active)
}
-inline
-SyncOperation FileSystemObject::getSyncOperation() const
-{
- return getSyncOperation(getCategory(), selectedForSynchronization, syncDir, syncDirConflict);
-}
-
-
-inline
-SyncOperation FileSystemObject::testSyncOperation(SyncDirection proposedDir) const
-{
- return getSyncOperation(getCategory(), true, proposedDir, std::wstring()); //should be safe by design
-}
-
-
template <> inline
bool FileSystemObject::isEmpty<LEFT_SIDE>() const
{
@@ -839,6 +850,22 @@ DirMapping& HierarchyObject::addSubDir(const Zstring& shortNameLeft,
}
+template <> inline
+DirMapping& HierarchyObject::addSubDir<LEFT_SIDE>(const Zstring& shortName)
+{
+ subDirs.emplace_back(shortName, Zstring(), *this);
+ return subDirs.back();
+}
+
+
+template <> inline
+DirMapping& HierarchyObject::addSubDir<RIGHT_SIDE>(const Zstring& shortName)
+{
+ subDirs.emplace_back(Zstring(), shortName, *this);
+ return subDirs.back();
+}
+
+
inline
FileMapping& HierarchyObject::addSubFile(
const Zstring& shortNameLeft,
@@ -852,19 +879,19 @@ FileMapping& HierarchyObject::addSubFile(
}
-inline
-void HierarchyObject::addSubFile(const FileDescriptor& left, //file exists on left side only
- const Zstring& shortNameLeft)
+template <> inline
+FileMapping& HierarchyObject::addSubFile<LEFT_SIDE>(const Zstring& shortName, const FileDescriptor& descr)
{
- subFiles.emplace_back(shortNameLeft, left, FILE_LEFT_SIDE_ONLY, Zstring(), FileDescriptor(), *this);
+ subFiles.emplace_back(shortName, descr, FILE_LEFT_SIDE_ONLY, Zstring(), FileDescriptor(), *this);
+ return subFiles.back();
}
-inline
-void HierarchyObject::addSubFile(const Zstring& shortNameRight, //file exists on right side only
- const FileDescriptor& right)
+template <> inline
+FileMapping& HierarchyObject::addSubFile<RIGHT_SIDE>(const Zstring& shortName, const FileDescriptor& descr)
{
- subFiles.emplace_back(Zstring(), FileDescriptor(), FILE_RIGHT_SIDE_ONLY, shortNameRight, right, *this);
+ subFiles.emplace_back(Zstring(), FileDescriptor(), FILE_RIGHT_SIDE_ONLY, shortName, descr, *this);
+ return subFiles.back();
}
@@ -881,19 +908,19 @@ SymLinkMapping& HierarchyObject::addSubLink(
}
-inline
-void HierarchyObject::addSubLink(const LinkDescriptor& left, //link exists on left side only
- const Zstring& shortNameLeft)
+template <> inline
+SymLinkMapping& HierarchyObject::addSubLink<LEFT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr)
{
- subLinks.emplace_back(shortNameLeft, left, SYMLINK_LEFT_SIDE_ONLY, Zstring(), LinkDescriptor(), *this);
+ subLinks.emplace_back(shortName, descr, SYMLINK_LEFT_SIDE_ONLY, Zstring(), LinkDescriptor(), *this);
+ return subLinks.back();
}
-inline
-void HierarchyObject::addSubLink(const Zstring& shortNameRight, //link exists on right side only
- const LinkDescriptor& right)
+template <> inline
+SymLinkMapping& HierarchyObject::addSubLink<RIGHT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr)
{
- subLinks.emplace_back(Zstring(), LinkDescriptor(), SYMLINK_RIGHT_SIDE_ONLY, shortNameRight, right, *this);
+ subLinks.emplace_back(Zstring(), LinkDescriptor(), SYMLINK_RIGHT_SIDE_ONLY, shortName, descr, *this);
+ return subLinks.back();
}
@@ -1062,6 +1089,20 @@ zen::UInt64 FileMapping::getFileSize<RIGHT_SIDE>() const
}
+template <> inline
+FileId FileMapping::getFileId<LEFT_SIDE>() const
+{
+ return dataLeft.id;
+}
+
+
+template <> inline
+FileId FileMapping::getFileId<RIGHT_SIDE>() const
+{
+ return dataRight.id;
+}
+
+
template <SelectedSide side> inline
const Zstring FileMapping::getExtension() const
{
@@ -1076,24 +1117,26 @@ const Zstring FileMapping::getExtension() const
template <> inline
-void FileMapping::copyTo<LEFT_SIDE>(const FileDescriptor* srcDescr) //copy + update file attributes
+void FileMapping::syncTo<LEFT_SIDE>(const FileDescriptor& descrTarget, const FileDescriptor* descrSource) //copy + update file attributes
{
- if (srcDescr)
- dataRight = *srcDescr;
- dataLeft = dataRight;
+ dataLeft = descrTarget;
+ if (descrSource)
+ dataRight = *descrSource;
+ moveFileRef = NULL;
cmpResult = FILE_EQUAL;
copyToL(); //copy FileSystemObject specific part
}
template <> inline
-void FileMapping::copyTo<RIGHT_SIDE>(const FileDescriptor* srcDescr) //copy + update file attributes
+void FileMapping::syncTo<RIGHT_SIDE>(const FileDescriptor& descrTarget, const FileDescriptor* descrSource) //copy + update file attributes
{
- if (srcDescr)
- dataLeft = *srcDescr;
- dataRight = dataLeft;
+ dataRight = descrTarget;
+ if (descrSource)
+ dataLeft = *descrSource;
+ moveFileRef = NULL;
cmpResult = FILE_EQUAL;
copyToR(); //copy FileSystemObject specific part
}
diff --git a/lib/custom_grid.cpp b/lib/custom_grid.cpp
index 97db1676..f2892624 100644
--- a/lib/custom_grid.cpp
+++ b/lib/custom_grid.cpp
@@ -557,23 +557,24 @@ private:
case SO_CREATE_NEW_LEFT:
case SO_OVERWRITE_LEFT:
case SO_DELETE_LEFT:
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_COPY_METADATA_TO_LEFT:
result.first = *wxBLACK;
result.second = COLOR_SYNC_BLUE;
break;
- case SO_COPY_METADATA_TO_LEFT:
- result.first = *wxBLACK;
- result.second = COLOR_SYNC_BLUE_LIGHT;
+ // result.second = COLOR_SYNC_BLUE_LIGHT;
break;
case SO_CREATE_NEW_RIGHT:
case SO_OVERWRITE_RIGHT:
case SO_DELETE_RIGHT:
- result.first = *wxBLACK;
- result.second = COLOR_SYNC_GREEN;
- break;
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
case SO_COPY_METADATA_TO_RIGHT:
result.first = *wxBLACK;
- result.second = COLOR_SYNC_GREEN_LIGHT;
+ result.second = COLOR_SYNC_GREEN;
break;
+ // result.second = COLOR_SYNC_GREEN_LIGHT;
case SO_UNRESOLVED_CONFLICT:
result.first = *wxBLACK;
result.second = COLOR_YELLOW;
@@ -2038,70 +2039,77 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos)
if (getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview
{
- const SyncOperation syncOp = fsObj->getSyncOperation();
- switch (syncOp)
+ const wchar_t* imageName = [&]() -> const wchar_t*
{
- case SO_CREATE_NEW_LEFT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("createLeft")));
- break;
- case SO_CREATE_NEW_RIGHT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("createRight")));
- break;
- case SO_DELETE_LEFT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("deleteLeft")));
- break;
- case SO_DELETE_RIGHT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("deleteRight")));
- break;
- case SO_OVERWRITE_LEFT:
- case SO_COPY_METADATA_TO_LEFT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("updateLeft")));
- break;
- case SO_OVERWRITE_RIGHT:
- case SO_COPY_METADATA_TO_RIGHT:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("updateRight")));
- break;
- case SO_DO_NOTHING:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("none")));
- break;
- case SO_EQUAL:
- toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("equal")));
- break;
- case SO_UNRESOLVED_CONFLICT:
- toolTip.show(fsObj->getSyncOpConflict(), pos, &GlobalResources::getImage(wxT("conflict")));
- break;
- };
+ const SyncOperation syncOp = fsObj->getSyncOperation();
+ switch (syncOp)
+ {
+ case SO_CREATE_NEW_LEFT:
+ return L"createLeft";
+ case SO_CREATE_NEW_RIGHT:
+ return L"createRight";
+ case SO_DELETE_LEFT:
+ return L"deleteLeft";
+ case SO_DELETE_RIGHT:
+ return L"deleteRight";
+ case SO_MOVE_LEFT_SOURCE:
+ return L"moveLeftSource";
+ case SO_MOVE_LEFT_TARGET:
+ return L"moveLeftTarget";
+ case SO_MOVE_RIGHT_SOURCE:
+ return L"moveRightSource";
+ case SO_MOVE_RIGHT_TARGET:
+ return L"moveRightTarget";
+ case SO_OVERWRITE_LEFT:
+ return L"updateLeft";
+ case SO_COPY_METADATA_TO_LEFT:
+ return L"moveLeft";
+ case SO_OVERWRITE_RIGHT:
+ return L"updateRight";
+ case SO_COPY_METADATA_TO_RIGHT:
+ return L"moveRight";
+ case SO_DO_NOTHING:
+ return L"none";
+ case SO_EQUAL:
+ return L"equal";
+ case SO_UNRESOLVED_CONFLICT:
+ return L"conflict";
+ };
+ assert(false);
+ return L"";
+ }();
+
+ toolTip.show(getSyncOpDescription(*fsObj), pos, &GlobalResources::getImage(imageName));
}
else
{
- const CompareFilesResult cmpRes = fsObj->getCategory();
- switch (cmpRes)
+ const wchar_t* imageName = [&]() -> const wchar_t*
{
- case FILE_LEFT_SIDE_ONLY:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("leftOnly")));
- break;
- case FILE_RIGHT_SIDE_ONLY:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("rightOnly")));
- break;
- case FILE_LEFT_NEWER:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("leftNewer")));
- break;
- case FILE_RIGHT_NEWER:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("rightNewer")));
- break;
- case FILE_DIFFERENT:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("different")));
- break;
- case FILE_EQUAL:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("equal")));
- break;
- case FILE_DIFFERENT_METADATA:
- toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("conflict")));
- break;
- case FILE_CONFLICT:
- toolTip.show(fsObj->getCatConflict(), pos, &GlobalResources::getImage(wxT("conflict")));
- break;
- }
+ const CompareFilesResult cmpRes = fsObj->getCategory();
+ switch (cmpRes)
+ {
+ case FILE_LEFT_SIDE_ONLY:
+ return L"leftOnly";
+ case FILE_RIGHT_SIDE_ONLY:
+ return L"rightOnly";
+ case FILE_LEFT_NEWER:
+ return L"leftNewer";
+ case FILE_RIGHT_NEWER:
+ return L"rightNewer";
+ case FILE_DIFFERENT:
+ return L"different";
+ case FILE_EQUAL:
+ return L"equal";
+ case FILE_DIFFERENT_METADATA:
+ return L"conflict";
+ case FILE_CONFLICT:
+ return L"conflict";
+ }
+ assert(false);
+ return L"";
+ }();
+
+ toolTip.show(getCategoryDescription(*fsObj), pos, &GlobalResources::getImage(imageName));
}
}
@@ -2284,6 +2292,7 @@ void GridCellRendererMiddle::Draw(wxGrid& grid,
//HIGHLIGHTNING (sync direction):
if (rowIsHighlighted &&
m_gridMiddle.highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files
+
switch (m_gridMiddle.highlightedPos)
{
case CustomGridMiddle::BLOCKPOS_CHECK_BOX:
@@ -2374,25 +2383,35 @@ const wxBitmap& zen::getSyncOpImage(SyncOperation syncOp)
switch (syncOp) //evaluate comparison result and sync direction
{
case SO_CREATE_NEW_LEFT:
- return GlobalResources::getImage(wxT("createLeftSmall"));
+ return GlobalResources::getImage(L"createLeftSmall");
case SO_CREATE_NEW_RIGHT:
- return GlobalResources::getImage(wxT("createRightSmall"));
+ return GlobalResources::getImage(L"createRightSmall");
case SO_DELETE_LEFT:
- return GlobalResources::getImage(wxT("deleteLeftSmall"));
+ return GlobalResources::getImage(L"deleteLeftSmall");
case SO_DELETE_RIGHT:
- return GlobalResources::getImage(wxT("deleteRightSmall"));
+ return GlobalResources::getImage(L"deleteRightSmall");
+ case SO_MOVE_LEFT_SOURCE:
+ return GlobalResources::getImage(L"moveLeftSourceSmall");
+ case SO_MOVE_LEFT_TARGET:
+ return GlobalResources::getImage(L"moveLeftTargetSmall");
+ case SO_MOVE_RIGHT_SOURCE:
+ return GlobalResources::getImage(L"moveRightSourceSmall");
+ case SO_MOVE_RIGHT_TARGET:
+ return GlobalResources::getImage(L"moveRightTargetSmall");
case SO_OVERWRITE_RIGHT:
+ return GlobalResources::getImage(L"updateRightSmall");
case SO_COPY_METADATA_TO_RIGHT:
- return GlobalResources::getImage(wxT("updateRightSmall"));
+ return GlobalResources::getImage(L"moveRightSmall");
case SO_OVERWRITE_LEFT:
+ return GlobalResources::getImage(L"updateLeftSmall");
case SO_COPY_METADATA_TO_LEFT:
- return GlobalResources::getImage(wxT("updateLeftSmall"));
+ return GlobalResources::getImage(L"moveLeftSmall");
case SO_DO_NOTHING:
- return GlobalResources::getImage(wxT("noneSmall"));
+ return GlobalResources::getImage(L"noneSmall");
case SO_EQUAL:
- return GlobalResources::getImage(wxT("equalSmall"));
+ return GlobalResources::getImage(L"equalSmall");
case SO_UNRESOLVED_CONFLICT:
- return GlobalResources::getImage(wxT("conflictSmall"));
+ return GlobalResources::getImage(L"conflictSmall");
}
return wxNullBitmap; //dummy
diff --git a/lib/db_file.cpp b/lib/db_file.cpp
index faee4c8a..60a721b1 100644
--- a/lib/db_file.cpp
+++ b/lib/db_file.cpp
@@ -15,7 +15,7 @@
#include <zen/file_io.h>
#include <zen/scope_guard.h>
#include <zen/guid.h>
-#include <boost/bind.hpp>
+#include <zen/utf8.h>
#ifdef FFS_WIN
#include <zen/win.h> //includes "windows.h"
@@ -29,15 +29,24 @@ namespace
{
//-------------------------------------------------------------------------------------------------------------------------------
const char FILE_FORMAT_DESCR[] = "FreeFileSync";
-const int FILE_FORMAT_VER = 7;
+const int FILE_FORMAT_VER = 8;
//-------------------------------------------------------------------------------------------------------------------------------
+typedef std::string UniqueId;
+typedef Zbase<char> MemoryStream; //ref-counted byte stream representing DirInformation
+typedef std::map<UniqueId, MemoryStream> StreamMapping; //list of streams ordered by session UUID
+
+
+//------------------------------------------------------------------------------------
+//| ensure 32/64 bit portability: used fixed size data types only e.g. std::uint32_t |
+//------------------------------------------------------------------------------------
+
template <SelectedSide side> inline
Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false)
{
- //Linux and Windows builds are binary incompatible: char/wchar_t case, sensitive/insensitive
- //32 and 64 bit db files ARE designed to be binary compatible!
+ //Linux and Windows builds are binary incompatible: different file id?, problem with case sensitivity?
+ //however 32 and 64 bit db files *are* designed to be binary compatible!
//Give db files different names.
//make sure they end with ".ffs_db". These files will not be included into comparison when located in base sync directories
#ifdef FFS_WIN
@@ -51,255 +60,209 @@ Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false)
}
-
-class FileInputStreamDB : public FileInputStream
+StreamMapping loadStreams(const Zstring& filename) //throw FileError
{
-public:
- FileInputStreamDB(const Zstring& filename) : //throw FileError
- FileInputStream(filename)
+ if (!zen::fileExists(filename))
+ throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
+ _("One of the FreeFileSync database files is not yet existing:") + L" \n" +
+ L"\"" + filename + L"\"");
+ try
{
+ //read format description (uncompressed)
+ FileInputStream rawStream(filename); //throw FileError
+
//read FreeFileSync file identifier
char formatDescr[sizeof(FILE_FORMAT_DESCR)] = {};
- Read(formatDescr, sizeof(formatDescr)); //throw FileError
+ rawStream.Read(formatDescr, sizeof(formatDescr)); //throw FileError
if (!std::equal(FILE_FORMAT_DESCR, FILE_FORMAT_DESCR + sizeof(FILE_FORMAT_DESCR), formatDescr))
throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\"");
- }
-private:
-};
+ wxZlibInputStream decompressed(rawStream, wxZLIB_ZLIB);
+ CheckedReader cr(decompressed, filename);
-class FileOutputStreamDB : public FileOutputStream
-{
-public:
- FileOutputStreamDB(const Zstring& filename) : //throw FileError
- FileOutputStream(filename)
+ std::int32_t version = cr.readNumberC<std::int32_t>();
+ if (version != FILE_FORMAT_VER) //read file format version#
+ throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\"");
+
+ //read stream lists
+ StreamMapping output;
+
+ std::uint32_t dbCount = cr.readNumberC<std::uint32_t>(); //number of databases: one for each sync-pair
+ while (dbCount-- != 0)
+ {
+ //DB id of partner databases
+ const std::string sessionID = cr.readStringC<std::string>();
+ const MemoryStream stream = cr.readStringC<MemoryStream>(); //read db-entry stream (containing DirInformation)
+
+ output.insert(std::make_pair(sessionID, stream));
+ }
+ return output;
+ }
+ catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
{
- //write FreeFileSync file identifier
- Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); //throw FileError
+ throw FileError(_("Error reading from synchronization database:") + L" (bad alloc)");
}
-
-private:
-};
}
-//#######################################################################################################################################
-class ReadDirInfo : public zen::ReadInputStream
+class StreamParser : private CheckedReader
{
public:
- ReadDirInfo(wxInputStream& stream, const Zstring& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName)
+ static DirInfoPtr execute(const MemoryStream& stream, const Zstring& fileName) //throw FileError -> return value always bound!
{
- //|-------------------------------------------------------------------------------------
- //| ensure 32/64 bit portability: use fixed size data types only e.g. boost::uint32_t |
- //|-------------------------------------------------------------------------------------
-
- //read filter settings -> currently not required, but persisting it doesn't hurt
- dirInfo.filter = HardFilter::loadFilter(getStream());
- check();
-
- //start recursion
- execute(dirInfo.baseDirContainer);
+ try
+ {
+ //read streams into DirInfo
+ auto dirInfo = std::make_shared<DirInformation>();
+ wxMemoryInputStream buffer(&*stream.begin(), stream.size()); //convert char-array to inputstream: no copying, ownership not transferred
+ StreamParser(buffer, fileName, *dirInfo); //throw FileError
+ return dirInfo;
+ }
+ catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
+ {
+ throw FileError(_("Error reading from synchronization database:") + L" (bad alloc)");
+ }
}
private:
- void execute(DirContainer& dirCont) const
+ StreamParser(wxInputStream& stream, const Zstring& errorObjName, DirInformation& dirInfo) : CheckedReader(stream, errorObjName)
{
- while (readNumberC<bool>())
- readSubFile(dirCont);
-
- while (readNumberC<bool>())
- readSubLink(dirCont);
-
- while (readNumberC<bool>())
- readSubDirectory(dirCont);
+ recurse(dirInfo.baseDirContainer);
}
- void readSubFile(DirContainer& dirCont) const
+ Zstring readStringUtf8() const
{
- //attention: order of function argument evaluation is undefined! So do it one after the other...
- const Zstring shortName = readStringC<Zstring>(); //file name
-
- const std::int64_t modTime = readNumberC<std::int64_t>();
- const std::uint64_t fileSize = readNumberC<std::uint64_t>();
-
- //const util::FileID fileIdentifier(stream_);
- //check();
-
- dirCont.addSubFile(shortName,
- FileDescriptor(modTime, fileSize));
+ return utf8CvrtTo<Zstring>(readStringC<Zbase<char>>());
}
-
- void readSubLink(DirContainer& dirCont) const
+ FileId readFileId() const
{
- //attention: order of function argument evaluation is undefined! So do it one after the other...
- const Zstring shortName = readStringC<Zstring>(); //file name
- const std::int64_t modTime = readNumberC<std::int64_t>();
- const Zstring targetPath = readStringC<Zstring>(); //file name
- const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<std::int32_t>());
-
- dirCont.addSubLink(shortName,
- LinkDescriptor(modTime, targetPath, linkType));
- }
+ assert_static(sizeof(FileId().first ) <= sizeof(std::uint64_t));
+ assert_static(sizeof(FileId().second) <= sizeof(std::uint64_t));
-
- void readSubDirectory(DirContainer& dirCont) const
- {
- const Zstring shortName = readStringC<Zstring>(); //directory name
- DirContainer& subDir = dirCont.addSubDir(shortName);
- execute(subDir); //recurse
+ const auto devId = static_cast<decltype(FileId().first )>(readNumberC<std::uint64_t>()); //
+ const auto fId = static_cast<decltype(FileId().second)>(readNumberC<std::uint64_t>()); //silence "loss of precision" compiler warnings
+ return std::make_pair(devId, fId);
}
-};
-namespace
-{
-typedef std::string UniqueId;
-typedef std::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation
-typedef std::map<UniqueId, MemoryStreamPtr> StreamMapping; //list of streams ordered by session UUID
-}
-
-class ReadFileStream : public zen::ReadInputStream
-{
-public:
- ReadFileStream(wxInputStream& stream, const Zstring& filename, StreamMapping& streamList) : ReadInputStream(stream, filename)
+ void recurse(DirContainer& dirCont) const
{
- //|-------------------------------------------------------------------------------------
- //| ensure 32/64 bit portability: used fixed size data types only e.g. boost::uint32_t |
- //|-------------------------------------------------------------------------------------
-
- std::int32_t version = readNumberC<std::int32_t>();
+ while (readNumberC<bool>()) //files
+ {
+ //attention: order of function argument evaluation is undefined! So do it one after the other...
+ const Zstring shortName = readStringUtf8(); //file name
- if (version != FILE_FORMAT_VER) //read file format version
- throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\"");
+ const std::int64_t modTime = readNumberC<std::int64_t>();
+ const std::uint64_t fileSize = readNumberC<std::uint64_t>();
+ const FileId fileID = readFileId();
- streamList.clear();
+ dirCont.addSubFile(shortName,
+ FileDescriptor(modTime, fileSize, fileID));
+ }
- boost::uint32_t dbCount = readNumberC<boost::uint32_t>(); //number of databases: one for each sync-pair
- while (dbCount-- != 0)
+ while (readNumberC<bool>()) //symlinks
{
- //DB id of partner databases
- const CharArray tmp2 = readArrayC();
- const std::string sessionID(tmp2->begin(), tmp2->end());
-
- CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation)
+ //attention: order of function argument evaluation is undefined! So do it one after the other...
+ const Zstring shortName = readStringUtf8(); //file name
+ const std::int64_t modTime = readNumberC<std::int64_t>();
+ const Zstring targetPath = readStringUtf8(); //file name
+ const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<std::int32_t>());
+
+ dirCont.addSubLink(shortName,
+ LinkDescriptor(modTime, targetPath, linkType));
+ }
- streamList.insert(std::make_pair(sessionID, buffer));
+ while (readNumberC<bool>()) //directories
+ {
+ const Zstring shortName = readStringUtf8(); //directory name
+ DirContainer& subDir = dirCont.addSubDir(shortName);
+ recurse(subDir);
}
}
};
-namespace
-{
-StreamMapping loadStreams(const Zstring& filename) //throw FileError
-{
- if (!zen::fileExists(filename))
- throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
- _("One of the FreeFileSync database files is not yet existing:") + L" \n" +
- L"\"" + filename + L"\"");
-
- try
- {
- //read format description (uncompressed)
- FileInputStreamDB uncompressed(filename); //throw FileError
-
- wxZlibInputStream input(uncompressed, wxZLIB_ZLIB);
- StreamMapping streamList;
- ReadFileStream(input, filename, streamList);
- return streamList;
- }
- catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
+//save/load DirContainer
+void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw FileError
+{
{
- throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)");
- }
-}
+ FileOutputStream rawStream(filename); //throw FileError
+ //write FreeFileSync file identifier
+ rawStream.Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); //throw FileError
-DirInfoPtr parseStream(const std::vector<char>& stream, const Zstring& fileName) //throw FileError -> return value always bound!
-{
- try
- {
- //read streams into DirInfo
- auto dirInfo = std::make_shared<DirInformation>();
- wxMemoryInputStream buffer(&stream[0], stream.size()); //convert char-array to inputstream: no copying, ownership not transferred
- ReadDirInfo(buffer, fileName, *dirInfo); //throw FileError
- return dirInfo;
- }
- catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file
- {
- throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)");
- }
-}
-}
+ wxZlibOutputStream compressed(rawStream, 4, wxZLIB_ZLIB);
+ /* 4 - best compromise between speed and compression: (scanning 200.000 objects)
+ 0 (uncompressed) 8,95 MB - 422 ms
+ 2 2,07 MB - 470 ms
+ 4 1,87 MB - 500 ms
+ 6 1,77 MB - 613 ms
+ 9 (maximal compression) 1,74 MB - 3330 ms */
+ CheckedWriter cw(compressed, filename);
-std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMapping) //throw FileError
-{
- const Zstring fileNameLeft = getDBFilename<LEFT_SIDE>(baseMapping);
- const Zstring fileNameRight = getDBFilename<RIGHT_SIDE>(baseMapping);
+ //save file format version
+ cw.writeNumberC<std::int32_t>(FILE_FORMAT_VER);
- //read file data: list of session ID + DirInfo-stream
- const StreamMapping streamListLeft = ::loadStreams(fileNameLeft); //throw FileError
- const StreamMapping streamListRight = ::loadStreams(fileNameRight); //throw FileError
+ //save stream list
+ cw.writeNumberC<std::uint32_t>(static_cast<std::uint32_t>(streamList.size())); //number of database records: one for each sync-pair
- //find associated session: there can be at most one session within intersection of left and right ids
- StreamMapping::const_iterator streamLeft = streamListLeft .end();
- StreamMapping::const_iterator streamRight = streamListRight.end();
- for (auto iterLeft = streamListLeft.begin(); iterLeft != streamListLeft.end(); ++iterLeft)
- {
- auto iterRight = streamListRight.find(iterLeft->first);
- if (iterRight != streamListRight.end())
+ for (auto iter = streamList.begin(); iter != streamList.end(); ++iter)
{
- streamLeft = iterLeft;
- streamRight = iterRight;
- break;
+ cw.writeStringC<std::string >(iter->first ); //sync session id
+ cw.writeStringC<MemoryStream>(iter->second); //DirInformation stream
}
}
-
- if (streamLeft == streamListLeft .end() ||
- streamRight == streamListRight.end() ||
- !streamLeft ->second.get() ||
- !streamRight->second.get())
- throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
- _("Database files do not share a common synchronization session:") + L" \n" +
- L"\"" + fileNameLeft + L"\"\n" +
- L"\"" + fileNameRight + L"\"");
- //read streams into DirInfo
- DirInfoPtr dirInfoLeft = parseStream(*streamLeft ->second, fileNameLeft); //throw FileError
- DirInfoPtr dirInfoRight = parseStream(*streamRight->second, fileNameRight); //throw FileError
-
- return std::make_pair(dirInfoLeft, dirInfoRight);
+ //(try to) hide database file
+#ifdef FFS_WIN
+ ::SetFileAttributes(zen::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN);
+#endif
}
-//-------------------------------------------------------------------------------------------------------------------------
template <SelectedSide side>
-class SaveDirInfo : public WriteOutputStream
+class StreamGenerator : private CheckedWriter
{
public:
- SaveDirInfo(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName, wxOutputStream& stream) : WriteOutputStream(errorObjName, stream)
+ static MemoryStream execute(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName)
{
- //save filter settings
- baseMapping.getFilter()->saveFilter(getStream());
- check();
+ wxMemoryOutputStream buffer;
+ StreamGenerator(baseMapping, oldDirInfo, errorObjName, buffer);
- //start recursion
- execute(baseMapping, oldDirInfo);
+ MemoryStream output;
+ output.resize(buffer.GetSize());
+ buffer.CopyTo(&*output.begin(), buffer.GetSize());
+ return output;
}
private:
- void execute(const HierarchyObject& hierObj, const DirContainer* oldDirInfo)
+ StreamGenerator(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName, wxOutputStream& stream) : CheckedWriter(stream, errorObjName)
+ {
+ recurse(baseMapping, oldDirInfo);
+ }
+
+ void recurse(const HierarchyObject& hierObj, const DirContainer* oldDirInfo)
{
- std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), boost::bind(&SaveDirInfo::processFile, this, _1, oldDirInfo));
+ // for (const auto& fileMap : hierObj.refSubFiles()) { processFile(fileMap, oldDirInfo); }); !
+
+ std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), [&](const FileMapping& fileMap) { this->processFile(fileMap, oldDirInfo); });
writeNumberC<bool>(false); //mark last entry
- std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), boost::bind(&SaveDirInfo::processLink, this, _1, oldDirInfo));
+ std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), [&](const SymLinkMapping& linkObj) { this->processLink(linkObj, oldDirInfo); });
writeNumberC<bool>(false); //mark last entry
- std::for_each(hierObj.refSubDirs ().begin(), hierObj.refSubDirs ().end(), boost::bind(&SaveDirInfo::processDir, this, _1, oldDirInfo));
+ std::for_each(hierObj.refSubDirs ().begin(), hierObj.refSubDirs ().end(), [&](const DirMapping& dirMap) { this->processDir(dirMap, oldDirInfo); });
writeNumberC<bool>(false); //mark last entry
}
+ void writeStringUtf8(const Zstring& str) { writeStringC(utf8CvrtTo<Zbase<char>>(str)); }
+
+ void writeFileId(const FileId& id)
+ {
+ writeNumberC<std::uint64_t>(id.first ); //device id
+ writeNumberC<std::uint64_t>(id.second); //file id
+ }
+
void processFile(const FileMapping& fileMap, const DirContainer* oldParentDir)
{
if (fileMap.getCategory() == FILE_EQUAL) //data in sync: write current state
@@ -307,9 +270,10 @@ private:
if (!fileMap.isEmpty<side>())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(fileMap.getShortName<side>()); //save respecting case! (Windows)
- writeNumberC<std:: int64_t>(to<std:: int64_t>(fileMap.getLastWriteTime<side>())); //last modification time
- writeNumberC<std::uint64_t>(to<std::uint64_t>(fileMap.getFileSize<side>())); //filesize
+ writeStringUtf8(fileMap.getShortName<side>()); //save respecting case! (Windows)
+ writeNumberC<std:: int64_t>(to<std:: int64_t>(fileMap.getLastWriteTime<side>()));
+ writeNumberC<std::uint64_t>(to<std::uint64_t>(fileMap.getFileSize<side>()));
+ writeFileId(fileMap.getFileId<side>());
}
}
else //not in sync: reuse last synchronous state
@@ -320,9 +284,10 @@ private:
if (iter != oldParentDir->files.end())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(iter->first); //save respecting case! (Windows)
- writeNumberC<std:: int64_t>(to<std:: int64_t>(iter->second.lastWriteTimeRaw)); //last modification time
- writeNumberC<std::uint64_t>(to<std::uint64_t>(iter->second.fileSize)); //filesize
+ writeStringUtf8(iter->first); //save respecting case! (Windows)
+ writeNumberC<std:: int64_t>(to<std:: int64_t>(iter->second.lastWriteTimeRaw));
+ writeNumberC<std::uint64_t>(to<std::uint64_t>(iter->second.fileSize));
+ writeFileId(iter->second.id);
}
}
}
@@ -335,9 +300,9 @@ private:
if (!linkObj.isEmpty<side>())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(linkObj.getShortName<side>()); //save respecting case! (Windows)
- writeNumberC<std::int64_t>(to<std::int64_t>(linkObj.getLastWriteTime<side>())); //last modification time
- writeStringC(linkObj.getTargetPath<side>());
+ writeStringUtf8(linkObj.getShortName<side>()); //save respecting case! (Windows)
+ writeNumberC<std::int64_t>(to<std::int64_t>(linkObj.getLastWriteTime<side>()));
+ writeStringUtf8(linkObj.getTargetPath<side>());
writeNumberC<std::int32_t>(linkObj.getLinkType<side>());
}
}
@@ -349,9 +314,9 @@ private:
if (iter != oldParentDir->links.end())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(iter->first); //save respecting case! (Windows)
- writeNumberC<std::int64_t>(to<std::int64_t>(iter->second.lastWriteTimeRaw)); //last modification time
- writeStringC(iter->second.targetPath);
+ writeStringUtf8(iter->first); //save respecting case! (Windows)
+ writeNumberC<std::int64_t>(to<std::int64_t>(iter->second.lastWriteTimeRaw));
+ writeStringUtf8(iter->second.targetPath);
writeNumberC<std::int32_t>(iter->second.type);
}
}
@@ -379,8 +344,8 @@ private:
if (!dirMap.isEmpty<side>())
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(dirMap.getShortName<side>()); //save respecting case! (Windows)
- execute(dirMap, oldDir); //recurse
+ writeStringUtf8(dirMap.getShortName<side>()); //save respecting case! (Windows)
+ recurse(dirMap, oldDir);
}
}
else //not in sync: reuse last synchronous state
@@ -388,8 +353,8 @@ private:
if (oldDir)
{
writeNumberC<bool>(true); //mark beginning of entry
- writeStringC(*oldDirName); //save respecting case! (Windows)
- execute(dirMap, oldDir); //recurse
+ writeStringUtf8(*oldDirName); //save respecting case! (Windows)
+ recurse(dirMap, oldDir);
return;
}
//no data is also a "synchronous state"!
@@ -408,69 +373,53 @@ private:
break;
case DIR_DIFFERENT_METADATA:
writeNumberC<bool>(true);
- writeStringC(dirMap.getShortName<side>());
+ writeStringUtf8(dirMap.getShortName<side>());
//ATTENTION: strictly this is a violation of the principle of reporting last synchronous state!
//however in this case this will result in "last sync unsuccessful" for this directory within <automatic> algorithm, which is fine
- execute(dirMap, oldDir); //recurse and save sub-items which are in sync
+ recurse(dirMap, oldDir); //recurse and save sub-items which are in sync
break;
}
}
}
};
+}
+//#######################################################################################################################################
-class WriteFileStream : public WriteOutputStream
+std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMapping) //throw FileError
{
-public:
- WriteFileStream(const StreamMapping& streamList, const Zstring& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream)
- {
- //save file format version
- writeNumberC<std::int32_t>(FILE_FORMAT_VER);
+ const Zstring fileNameLeft = getDBFilename<LEFT_SIDE >(baseMapping);
+ const Zstring fileNameRight = getDBFilename<RIGHT_SIDE>(baseMapping);
- writeNumberC<boost::uint32_t>(static_cast<boost::uint32_t>(streamList.size())); //number of database records: one for each sync-pair
+ //read file data: list of session ID + DirInfo-stream
+ const StreamMapping streamListLeft = ::loadStreams(fileNameLeft); //throw FileError
+ const StreamMapping streamListRight = ::loadStreams(fileNameRight); //throw FileError
- for (StreamMapping::const_iterator i = streamList.begin(); i != streamList.end(); ++i)
+ //find associated session: there can be at most one session within intersection of left and right ids
+ StreamMapping::const_iterator streamLeft = streamListLeft .end();
+ StreamMapping::const_iterator streamRight = streamListRight.end();
+ for (auto iterLeft = streamListLeft.begin(); iterLeft != streamListLeft.end(); ++iterLeft)
+ {
+ auto iterRight = streamListRight.find(iterLeft->first);
+ if (iterRight != streamListRight.end())
{
- //sync session id
- writeArrayC(std::vector<char>(i->first.begin(), i->first.end()));
-
- //write DirInformation stream
- writeArrayC(*(i->second));
+ streamLeft = iterLeft;
+ streamRight = iterRight;
+ break;
}
}
-};
+ if (streamLeft == streamListLeft .end() ||
+ streamRight == streamListRight.end())
+ throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" +
+ _("Database files do not share a common synchronization session:") + L" \n" +
+ L"\"" + fileNameLeft + L"\"\n" +
+ L"\"" + fileNameRight + L"\"");
+ //read streams into DirInfo
+ DirInfoPtr dirInfoLeft = StreamParser::execute(streamLeft ->second, fileNameLeft); //throw FileError
+ DirInfoPtr dirInfoRight = StreamParser::execute(streamRight->second, fileNameRight); //throw FileError
-//save/load DirContainer
-void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw FileError
-{
- {
- //write format description (uncompressed)
- FileOutputStreamDB uncompressed(filename); //throw FileError
-
- wxZlibOutputStream output(uncompressed, 4, wxZLIB_ZLIB);
- /* 4 - best compromise between speed and compression: (scanning 200.000 objects)
- 0 (uncompressed) 8,95 MB - 422 ms
- 2 2,07 MB - 470 ms
- 4 1,87 MB - 500 ms
- 6 1,77 MB - 613 ms
- 9 (maximal compression) 1,74 MB - 3330 ms */
-
- WriteFileStream(streamList, filename, output);
- }
- //(try to) hide database file
-#ifdef FFS_WIN
- ::SetFileAttributes(zen::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN);
-#endif
-}
-
-
-bool equalEntry(const MemoryStreamPtr& lhs, const MemoryStreamPtr& rhs)
-{
- if (!lhs.get() || !rhs.get())
- return lhs.get() == rhs.get();
-
- return *lhs == *rhs;
+ return std::make_pair(dirInfoLeft, dirInfoRight);
}
@@ -522,12 +471,10 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError
try
{
if (streamLeft != streamListLeft .end() &&
- streamRight != streamListRight.end() &&
- streamLeft ->second.get() &&
- streamRight->second.get())
+ streamRight != streamListRight.end())
{
- oldDirInfoLeft = parseStream(*streamLeft ->second, dbNameLeft); //throw FileError
- oldDirInfoRight = parseStream(*streamRight->second, dbNameRight); //throw FileError
+ oldDirInfoLeft = StreamParser::execute(streamLeft ->second, dbNameLeft ); //throw FileError
+ oldDirInfoRight = StreamParser::execute(streamRight->second, dbNameRight); //throw FileError
}
}
catch (FileError&)
@@ -538,28 +485,13 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError
}
//create new database entries
- MemoryStreamPtr newStreamLeft = std::make_shared<std::vector<char>>();
- {
- wxMemoryOutputStream buffer;
- const DirContainer* oldDir = oldDirInfoLeft.get() ? &oldDirInfoLeft->baseDirContainer : NULL;
- SaveDirInfo<LEFT_SIDE>(baseMapping, oldDir, dbNameLeft, buffer);
- newStreamLeft->resize(buffer.GetSize()); //convert output stream to char-array
- buffer.CopyTo(&(*newStreamLeft)[0], buffer.GetSize()); //
- }
-
- MemoryStreamPtr newStreamRight = std::make_shared<std::vector<char>>();
- {
- wxMemoryOutputStream buffer;
- const DirContainer* oldDir = oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL;
- SaveDirInfo<RIGHT_SIDE>(baseMapping, oldDir, dbNameRight, buffer);
- newStreamRight->resize(buffer.GetSize()); //convert output stream to char-array
- buffer.CopyTo(&(*newStreamRight)[0], buffer.GetSize()); //
- }
+ MemoryStream newStreamLeft = StreamGenerator<LEFT_SIDE >::execute(baseMapping, oldDirInfoLeft .get() ? &oldDirInfoLeft ->baseDirContainer : NULL, dbNameLeft);
+ MemoryStream newStreamRight = StreamGenerator<RIGHT_SIDE>::execute(baseMapping, oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL, dbNameRight);
//check if there is some work to do at all
{
- const bool updateRequiredLeft = streamLeft == streamListLeft .end() || !equalEntry(newStreamLeft, streamLeft ->second);
- const bool updateRequiredRight = streamRight == streamListRight.end() || !equalEntry(newStreamRight, streamRight->second);
+ const bool updateRequiredLeft = streamLeft == streamListLeft .end() || newStreamLeft != streamLeft ->second;
+ const bool updateRequiredRight = streamRight == streamListRight.end() || newStreamRight != streamRight->second;
//some users monitor the *.ffs_db file with RTS => don't touch the file if it isnt't strictly needed
if (!updateRequiredLeft && !updateRequiredRight)
return;
@@ -579,10 +511,10 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError
streamListRight.insert(std::make_pair(sessionID, newStreamRight));
//write (temp-) files...
- zen::ScopeGuard guardTempFileLeft = zen::makeGuard([&]() {zen::removeFile(dbNameLeftTmp); });
+ zen::ScopeGuard guardTempFileLeft = zen::makeGuard([&] {zen::removeFile(dbNameLeftTmp); });
saveFile(streamListLeft, dbNameLeftTmp); //throw FileError
- zen::ScopeGuard guardTempFileRight = zen::makeGuard([&]() {zen::removeFile(dbNameRightTmp); });
+ zen::ScopeGuard guardTempFileRight = zen::makeGuard([&] {zen::removeFile(dbNameRightTmp); });
saveFile(streamListRight, dbNameRightTmp); //throw FileError
//operation finished: rename temp files -> this should work transactionally:
diff --git a/lib/db_file.h b/lib/db_file.h
index d6d765cc..0413c404 100644
--- a/lib/db_file.h
+++ b/lib/db_file.h
@@ -14,11 +14,8 @@ namespace zen
{
const Zstring SYNC_DB_FILE_ENDING = Zstr(".ffs_db");
-void saveToDisk(const BaseDirMapping& baseMapping); //throw FileError
-
struct DirInformation
{
- HardFilter::FilterRef filter; //filter settings (used when retrieving directory data)
DirContainer baseDirContainer; //hierarchical directory information
};
typedef std::shared_ptr<const DirInformation> DirInfoPtr;
@@ -26,6 +23,8 @@ typedef std::shared_ptr<const DirInformation> DirInfoPtr;
DEFINE_NEW_FILE_ERROR(FileErrorDatabaseNotExisting);
std::pair<DirInfoPtr, DirInfoPtr> loadFromDisk(const BaseDirMapping& baseMapping); //throw FileError, FileErrorDatabaseNotExisting -> return value always bound!
+
+void saveToDisk(const BaseDirMapping& baseMapping); //throw FileError
}
#endif // DBFILE_H_INCLUDED
diff --git a/lib/detect_renaming.cpp b/lib/detect_renaming.cpp
deleted file mode 100644
index 39e7eb4b..00000000
--- a/lib/detect_renaming.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#include "detect_renaming.h"
-#include <map>
-#include <vector>
-#include <boost/bind.hpp>
-
-using namespace FreeFileSync;
-
-/*detect renamed files:
-Example:
- X -> |_| Create right
-|_| -> Y Delete right
-
-is detected as:
-
-Rename Y to X on right
-
-Algorithm:
-----------
-DB-file left ---filename, Metadata(=:MD)---> DB-file right
- /|\ |
- | fileID, MD
- fileID, MD |
- | \|/
- X Y
-
-*/
-
-
-class FindDBAssoc
-{
- /*
- load and associate db-files by filename and metadata(size, date)
- fileID, MD |-> fileID
- */
-public:
- struct AssocKey
- {
- AssocKey(const Utility::FileID& fileId,
- const wxLongLong& lastWriteTimeRaw,
- const wxULongLong& fileSize);
-
- bool operator<(const AssocKey& other) const;
-
- Utility::FileID fileId_;
- wxLongLong lastWriteTimeRaw_;
- wxULongLong fileSize_;
- };
-
- FindDBAssoc(const FreeFileSync::BaseDirMapping& baseMapping,
- std::map<AssocKey, Utility::FileID>& assocDBLeftToRight);
-
-private:
- void recurse(const DirContainer& leftSide, const DirContainer& rightSide);
-
- std::map<AssocKey, Utility::FileID>& assocDBLeftToRight_; //-->
-};
-
-
-inline
-FindDBAssoc::AssocKey::AssocKey(const Utility::FileID& fileId,
- const wxLongLong& lastWriteTimeRaw,
- const wxULongLong& fileSize) :
- fileId_(fileId),
- lastWriteTimeRaw_(lastWriteTimeRaw),
- fileSize_(fileSize) {}
-
-
-inline
-bool FindDBAssoc::AssocKey::operator<(const AssocKey& other) const
-{
- if (fileId_ != other.fileId_)
- return fileId_ < other.fileId_;
-
- if (lastWriteTimeRaw_ != other.lastWriteTimeRaw_)
- return lastWriteTimeRaw_ < other.lastWriteTimeRaw_;
-
- return fileSize_ < other.fileSize_;
-}
-
-
-FindDBAssoc::FindDBAssoc(const FreeFileSync::BaseDirMapping& baseMapping,
- std::map<AssocKey, Utility::FileID>& assocDBLeftToRight) : assocDBLeftToRight_(assocDBLeftToRight)
-{
- try
- {
- std::pair<FreeFileSync::DirInfoPtr, FreeFileSync::DirInfoPtr> dbInfo =
- FreeFileSync::loadFromDisk(baseMapping); //throw (FileError)
-
- recurse(dbInfo.first->baseDirContainer,
- dbInfo.second->baseDirContainer);
- }
- catch (...) {} //swallow...
-}
-
-
-void FindDBAssoc::recurse(const DirContainer& leftSide, const DirContainer& rightSide)
-{
- for (DirContainer::SubFileList::const_iterator i = leftSide.getSubFiles().begin(); i != leftSide.getSubFiles().end(); ++i)
- {
- const FileDescriptor& fileDescrI = i->second.getData();
- if (!fileDescrI.fileIdentifier.isNull()) //fileIdentifier may be NULL
- {
- const DirContainer::SubFileList::const_iterator j = rightSide.getSubFiles().find(i->first);
-
- //find files that exist on left and right
- if (j != rightSide.getSubFiles().end())
- {
- const FileDescriptor& fileDescrJ = j->second.getData();
- if (!fileDescrJ.fileIdentifier.isNull()) //fileIdentifier may be NULL
- {
- if ( fileDescrI.lastWriteTimeRaw == fileDescrJ.lastWriteTimeRaw &&
- fileDescrI.fileSize == fileDescrJ.fileSize)
- {
- assocDBLeftToRight_[AssocKey(fileDescrI.fileIdentifier,
- fileDescrI.lastWriteTimeRaw,
- fileDescrI.fileSize)] = fileDescrJ.fileIdentifier;
- }
- }
- }
- }
- }
-
- //-----------------------------------------------------------------------------------------------
- for (DirContainer::SubDirList::const_iterator i = leftSide.getSubDirs().begin(); i != leftSide.getSubDirs().end(); ++i)
- {
- const DirContainer::SubDirList::const_iterator j = rightSide.getSubDirs().find(i->first);
-
- //directories that exist on both sides
- if (j != rightSide.getSubDirs().end())
- {
- recurse(i->second, j->second); //recurse into subdirectories
- }
- }
-}
-
-
-
-class FindRenameCandidates
-{
-public:
- FindRenameCandidates(FreeFileSync::BaseDirMapping& baseMapping)
- {
- FindDBAssoc(baseMapping,
- assocDBLeftToRight);
-
- if (!assocDBLeftToRight.empty())
- recurse(baseMapping);
- }
-
- void getRenameCandidates(std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnLeft,
- std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnRight);
-
-private:
- void recurse(HierarchyObject& hierObj)
- {
- //files
- std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(),
- boost::bind(&FindRenameCandidates::processFile, this, _1));
-
- //directories
- std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(),
- boost::bind(&FindRenameCandidates::recurse, this, _1));//recursion
- }
-
- void processFile(FileMapping& fileObj)
- {
- switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction
- {
- case SO_CREATE_NEW_LEFT:
- if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL
- createLeft[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(),
- fileObj.getLastWriteTime<RIGHT_SIDE>(),
- fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj;
- break;
-
- case SO_CREATE_NEW_RIGHT:
- if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL
- createRight.push_back(&fileObj);
- break;
-
- case SO_DELETE_LEFT:
- if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL
- deleteLeft.push_back(&fileObj);
- break;
-
- case SO_DELETE_RIGHT:
- if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL
- deleteRight[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(),
- fileObj.getLastWriteTime<RIGHT_SIDE>(),
- fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj;
- break;
-
- case SO_OVERWRITE_RIGHT:
- case SO_OVERWRITE_LEFT:
- case SO_DO_NOTHING:
- case SO_UNRESOLVED_CONFLICT:
- break;
- }
-
- }
-
-
- std::vector<FileMapping*> createRight; //pointer always bound!
- std::vector<FileMapping*> deleteLeft; //
- // |
- // \|/
- std::map<FindDBAssoc::AssocKey, Utility::FileID> assocDBLeftToRight;
- // |
- // \|/
- std::map<FindDBAssoc::AssocKey, FileMapping*> deleteRight; //pointer always bound!
- std::map<FindDBAssoc::AssocKey, FileMapping*> createLeft; //
-
-};
-
-
-
-void FindRenameCandidates::getRenameCandidates(
- std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnLeft,
- std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnRight)
-{
- for (std::vector<FileMapping*>::const_iterator crRightIter = createRight.begin();
- crRightIter != createRight.end();
- ++crRightIter)
- {
- const FindDBAssoc::AssocKey assocDbKey((*crRightIter)->getFileID<LEFT_SIDE>(),
- (*crRightIter)->getLastWriteTime<LEFT_SIDE>(),
- (*crRightIter)->getFileSize<LEFT_SIDE>());
-
- const std::map<FindDBAssoc::AssocKey, Utility::FileID>::const_iterator assocDBIter =
- assocDBLeftToRight.find(assocDbKey);
-
- if (assocDBIter != assocDBLeftToRight.end())
- {
- std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator delRightIter =
- deleteRight.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side
- assocDbKey.lastWriteTimeRaw_,
- assocDbKey.fileSize_));
-
- if (delRightIter != deleteRight.end())
- {
- renameOnRight.push_back(std::make_pair(*crRightIter, delRightIter->second));
- }
- }
- }
- //------------------------------------------------------------------------------------------------
- for (std::vector<FileMapping*>::const_iterator delLeftIter = deleteLeft.begin();
- delLeftIter != deleteLeft.end();
- ++delLeftIter)
- {
- const FindDBAssoc::AssocKey assocDbKey((*delLeftIter)->getFileID<LEFT_SIDE>(),
- (*delLeftIter)->getLastWriteTime<LEFT_SIDE>(),
- (*delLeftIter)->getFileSize<LEFT_SIDE>());
-
- const std::map<FindDBAssoc::AssocKey, Utility::FileID>::const_iterator assocDBIter =
- assocDBLeftToRight.find(assocDbKey);
-
- if (assocDBIter != assocDBLeftToRight.end())
- {
- std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator createLeftIter =
- createLeft.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side
- assocDbKey.lastWriteTimeRaw_,
- assocDbKey.fileSize_));
-
- if (createLeftIter != createLeft.end())
- {
- renameOnLeft.push_back(std::make_pair(createLeftIter->second, *delLeftIter));
- }
- }
- }
-}
-
-
-void FreeFileSync::getRenameCandidates(FreeFileSync::BaseDirMapping& baseMapping, //in
- std::vector<std::pair<CreateOnLeft, DeleteOnLeft> >& renameOnLeft, //out
- std::vector<std::pair<CreateOnRight, DeleteOnRight> >& renameOnRight) //out throw()!
-{
- FindRenameCandidates(baseMapping).getRenameCandidates(renameOnLeft, renameOnRight);
-}
-
diff --git a/lib/detect_renaming.h b/lib/detect_renaming.h
deleted file mode 100644
index e94927c0..00000000
--- a/lib/detect_renaming.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef DETECTRENAMING_H_INCLUDED
-#define DETECTRENAMING_H_INCLUDED
-
-#include "../file_hierarchy.h"
-
-
-//identify a file "create and delete"-operation as a file renaming!
-
-namespace zen
-{
-typedef FileMapping* CreateOnLeft;
-typedef FileMapping* DeleteOnLeft;
-typedef FileMapping* CreateOnRight;
-typedef FileMapping* DeleteOnRight;
-void getRenameCandidates(zen::BaseDirMapping& baseMapping, //in
- std::vector<std::pair<CreateOnLeft, DeleteOnLeft> >& renameOnLeft, //out
- std::vector<std::pair<CreateOnRight, DeleteOnRight> >& renameOnRight); //out throw()!
-}
-
-#endif // DETECTRENAMING_H_INCLUDED
diff --git a/lib/dir_exist_async.h b/lib/dir_exist_async.h
index 72741ee2..f59e9490 100644
--- a/lib/dir_exist_async.h
+++ b/lib/dir_exist_async.h
@@ -20,9 +20,7 @@ bool dirExistsUpdating(const Zstring& dirname, bool allowUserInteraction, Proces
{
using namespace zen;
- std::wstring statusText = _("Searching for directory %x...");
- replace(statusText, L"%x", std::wstring(L"\"") + dirname + L"\"", false);
- procCallback.reportStatus(statusText);
+ procCallback.reportStatus(replaceCpy(_("Searching for directory %x..."), L"%x", std::wstring(L"\"") + dirname + L"\"", false));
auto ft = async([=]() -> bool
{
diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp
index 735fd7b6..ab3c84ea 100644
--- a/lib/dir_lock.cpp
+++ b/lib/dir_lock.cpp
@@ -74,10 +74,10 @@ public:
//ATTENTION: setting file pointer IS required! => use CreateFile/FILE_GENERIC_WRITE + SetFilePointerEx!
//although CreateFile/FILE_APPEND_DATA without SetFilePointerEx works locally, it MAY NOT work on some network shares creating a 4 gig file!!!
- const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_.c_str()).c_str(),
+ const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_).c_str(),
GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp
FILE_SHARE_READ,
- 0,
+ NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
@@ -340,8 +340,8 @@ std::string retrieveLockId(const Zstring& lockfilename) //throw FileError, Error
void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //throw FileError
{
- std::wstring infoMsg = _("Waiting while directory is locked (%x)...");
- replace(infoMsg, L"%x", std::wstring(L"\"") + lockfilename + L"\"");
+ const std::wstring infoMsg = replaceCpy(_("Waiting while directory is locked (%x)..."), L"%x", std::wstring(L"\"") + lockfilename + L"\"");
+
if (callback)
callback->reportInfo(infoMsg);
//---------------------------------------------------------------
@@ -408,8 +408,8 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr
long remainingSeconds = ((DETECT_EXITUS_INTERVAL - (wxGetLocalTimeMillis() - lockSilentStart)) / 1000).ToLong();
remainingSeconds = std::max(0L, remainingSeconds);
- std::wstring remSecMsg = _P("1 sec", "%x sec", remainingSeconds);
- replace(remSecMsg, L"%x", toString<std::wstring>(remainingSeconds));
+ const std::wstring remSecMsg = replaceCpy(_P("1 sec", "%x sec", remainingSeconds), L"%x", toString<std::wstring>(remainingSeconds));
+
callback->reportInfo(infoMsg + L" " + remSecMsg);
}
else
@@ -441,7 +441,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError
const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename).c_str(),
GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0,
+ NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
@@ -472,7 +472,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError
::close(fileHandle);
#endif
- zen::ScopeGuard guardLockFile = zen::makeGuard([&]() { zen::removeFile(lockfilename); });
+ ScopeGuard guardLockFile = zen::makeGuard([&] { zen::removeFile(lockfilename); });
//write UUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks, etc.)
writeLockInfo(lockfilename); //throw FileError
diff --git a/lib/dir_name.cpp b/lib/dir_name.cpp
index 71a3e9ef..55a4185c 100644
--- a/lib/dir_name.cpp
+++ b/lib/dir_name.cpp
@@ -40,7 +40,7 @@ void setDirectoryNameImpl(const wxString& dirname, wxDirPickerCtrl* dirPicker, w
if (dirPicker && !dirFormatted.empty())
{
Zstring dir = toZ(dirFormatted); //convert to Zstring first: we don't want to pass wxString by value and risk MT issues!
- auto ft = async([=]() { return zen::dirExists(dir); });
+ auto ft = async([=] { return zen::dirExists(dir); });
if (ft.timed_wait(boost::posix_time::milliseconds(timeout)) && ft.get()) //potentially slow network access: wait 200ms at most
dirPicker->SetPath(dirFormatted);
diff --git a/lib/localization.cpp b/lib/localization.cpp
index e8ff6040..574910ea 100644
--- a/lib/localization.cpp
+++ b/lib/localization.cpp
@@ -301,6 +301,7 @@ wxLanguage mapLanguageDialect(wxLanguage language)
//case wxLANGUAGE_PORTUGUESE_BRAZILIAN:
//case wxLANGUAGE_KOREAN:
//case wxLANGUAGE_UKRAINIAN:
+ //case wxLANGUAGE_CROATIAN:
//variants of wxLANGUAGE_ARABIC
case wxLANGUAGE_ARABIC_ALGERIA:
diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp
index 96b167b8..1052a408 100644
--- a/lib/parallel_scan.cpp
+++ b/lib/parallel_scan.cpp
@@ -141,7 +141,7 @@ Windows 7: Windows XP:
1 Thread: 41s | 13s 1 Thread: 45s | 13s
2 Threads: 42s | 11s 2 Threads: 38s | 8s
-=> Traversing does not take any advantage of file locality so that even multiple threads operating on the same disk impose no performance overhead!
+=> Traversing does not take any advantage of file locality so that even multiple threads operating on the same disk impose no performance overhead! (even faster on XP)
*/
@@ -196,7 +196,7 @@ public:
errorMsg.clear();
errorResponse.reset();
- //dummy.unlock();
+ dummy.unlock(); //optimization for condition_variable::notify_one()
conditionCanReportError.notify_one();
return rv;
@@ -204,13 +204,13 @@ public:
void processErrors(FillBufferCallback& callback) //context of main thread, call repreatedly
{
- boost::lock_guard<boost::mutex> dummy(lockErrorMsg);
+ boost::unique_lock<boost::mutex> dummy(lockErrorMsg);
if (!errorMsg.empty() && !errorResponse.get())
{
FillBufferCallback::HandleError rv = callback.reportError(copyStringTo<std::wstring>(errorMsg)); //throw!
errorResponse.reset(new FillBufferCallback::HandleError(rv));
- //dummy.unlock();
+ dummy.unlock(); //optimization for condition_variable::notify_one()
conditionGotResponse.notify_one();
}
}
@@ -293,6 +293,7 @@ private:
};
//-------------------------------------------------------------------------------------------------
+
struct TraverserShared
{
public:
@@ -372,7 +373,7 @@ void DirCallback::onFile(const Zchar* shortName, const Zstring& fullName, const
Linux: retrieveFileID takes about 50% longer in VM! (avoidable because of redundant stat() call!)
*/
- output_.addSubFile(fileNameShort, FileDescriptor(details.lastWriteTimeRaw, details.fileSize));
+ output_.addSubFile(fileNameShort, FileDescriptor(details.lastWriteTimeRaw, details.fileSize, details.id));
cfg.acb_.incItemsScanned(); //add 1 element to the progress indicator
}
@@ -547,8 +548,8 @@ void zen::fillBuffer(const std::set<DirectoryKey>& keysToRead, //in
zen::ScopeGuard guardWorker = zen::makeGuard([&]()
{
- std::for_each(worker.begin(), worker.end(), std::mem_fun_ref(&boost::thread::interrupt)); //interrupt all at once, then join
- std::for_each(worker.begin(), worker.end(), std::mem_fun_ref(&boost::thread::join));
+ std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) { wt.interrupt(); }); //interrupt all at once, then join
+ std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) { wt.join(); });
});
std::shared_ptr<AsyncCallback> acb = std::make_shared<AsyncCallback>();
diff --git a/lib/status_handler.h b/lib/status_handler.h
index 390b4f0a..686c1f0e 100644
--- a/lib/status_handler.h
+++ b/lib/status_handler.h
@@ -7,7 +7,6 @@
#ifndef STATUSHANDLER_H_INCLUDED
#define STATUSHANDLER_H_INCLUDED
-#include <wx/string.h>
#include <string>
#include <zen/int64.h>
@@ -45,21 +44,18 @@ struct ProcessCallback
//note: this one must NOT throw in order to properly allow undoing setting of statistics!
//it is in general paired with a call to requestUiRefresh() to compensate!
- virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //throw()
+ virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //throw()!!
//opportunity to abort must be implemented in a frequently executed method like requestUiRefresh()
virtual void requestUiRefresh() = 0; //throw ?
- //this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events
- virtual void forceUiRefresh() = 0;
-
//called periodically after data was processed: expected(!) to request GUI update
- virtual void reportStatus(const wxString& text) = 0; //status info only, should not be logged!
+ virtual void reportStatus(const std::wstring& text) = 0; //status info only, should not be logged!
//called periodically after data was processed: expected(!) to request GUI update
- virtual void reportInfo(const wxString& text) = 0;
+ virtual void reportInfo(const std::wstring& text) = 0;
- virtual void reportWarning(const wxString& warningMessage, bool& warningActive) = 0;
+ virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive) = 0;
//error handling:
enum Response
@@ -67,8 +63,8 @@ struct ProcessCallback
IGNORE_ERROR = 10,
RETRY
};
- virtual Response reportError (const wxString& errorMessage) = 0; //recoverable error situation
- virtual void reportFatalError(const wxString& errorMessage) = 0; //non-recoverable error situation
+ virtual Response reportError (const std::wstring& errorMessage) = 0; //recoverable error situation
+ virtual void reportFatalError(const std::wstring& errorMessage) = 0; //non-recoverable error situation
};
@@ -86,6 +82,8 @@ class StatusHandler : public ProcessCallback, public AbortCallback
public:
StatusHandler() : abortRequested(false) {}
+ virtual void forceUiRefresh() = 0;
+
virtual void requestUiRefresh()
{
if (updateUiIsAllowed()) //test if specific time span between ui updates is over
diff --git a/structures.cpp b/structures.cpp
index 1612445c..c3b20886 100644
--- a/structures.cpp
+++ b/structures.cpp
@@ -13,7 +13,7 @@
using namespace zen;
-wxString zen::getVariantName(CompareVariant var)
+std::wstring zen::getVariantName(CompareVariant var)
{
switch (var)
{
@@ -22,13 +22,12 @@ wxString zen::getVariantName(CompareVariant var)
case CMP_BY_TIME_SIZE:
return _("File time and size");
}
-
assert(false);
- return wxEmptyString;
+ return _("Error");
}
-wxString zen::getVariantName(DirectionConfig::Variant var)
+std::wstring zen::getVariantName(DirectionConfig::Variant var)
{
switch (var)
{
@@ -41,6 +40,7 @@ wxString zen::getVariantName(DirectionConfig::Variant var)
case DirectionConfig::CUSTOM:
return _("Custom");
}
+ assert(false);
return _("Error");
}
@@ -92,7 +92,7 @@ DirectionSet zen::getTwoWaySet()
}
-wxString MainConfiguration::getCompVariantName() const
+std::wstring MainConfiguration::getCompVariantName() const
{
const CompareVariant firstVariant = firstPair.altCmpConfig.get() ?
firstPair.altCmpConfig->compareVar :
@@ -113,7 +113,7 @@ wxString MainConfiguration::getCompVariantName() const
}
-wxString MainConfiguration::getSyncVariantName() const
+std::wstring MainConfiguration::getSyncVariantName() const
{
const DirectionConfig::Variant firstVariant = firstPair.altSyncConfig.get() ?
firstPair.altSyncConfig->directionCfg.var :
@@ -134,120 +134,64 @@ wxString MainConfiguration::getSyncVariantName() const
}
-wxString zen::getDescription(CompareFilesResult cmpRes)
+std::wstring zen::getSymbol(CompareFilesResult cmpRes)
{
switch (cmpRes)
{
case FILE_LEFT_SIDE_ONLY:
- return _("File/folder exists on left side only");
+ return L"only <-";
case FILE_RIGHT_SIDE_ONLY:
- return _("File/folder exists on right side only");
+ return L"only ->";
case FILE_LEFT_NEWER:
- return _("Left file is newer");
+ return L"newer <-";
case FILE_RIGHT_NEWER:
- return _("Right file is newer");
+ return L"newer ->";
case FILE_DIFFERENT:
- return _("Files have different content");
+ return L"!=";
case FILE_EQUAL:
- return _("Both sides are equal");
- case FILE_DIFFERENT_METADATA:
- return _("Files/folders differ in attributes only");
- case FILE_CONFLICT:
- return _("Conflict/file cannot be categorized");
- }
-
- assert(false);
- return wxEmptyString;
-}
-
-
-wxString zen::getSymbol(CompareFilesResult cmpRes)
-{
- switch (cmpRes)
- {
- case FILE_LEFT_SIDE_ONLY:
- return wxT("<|");
- case FILE_RIGHT_SIDE_ONLY:
- return wxT("|>");
- case FILE_LEFT_NEWER:
- return wxT("<<");
- case FILE_RIGHT_NEWER:
- return wxT(">>");
- case FILE_DIFFERENT:
- return wxT("!=");
- case FILE_EQUAL:
- return wxT("'=="); //added quotation mark to avoid error in Excel cell when exporting to *.cvs
+ return L"'=="; //added quotation mark to avoid error in Excel cell when exporting to *.cvs
case FILE_CONFLICT:
case FILE_DIFFERENT_METADATA:
- return wxT("\\/\\->");
+ return L"conflict";
}
-
assert(false);
- return wxEmptyString;
+ return std::wstring();
}
-wxString zen::getDescription(SyncOperation op)
+std::wstring zen::getSymbol(SyncOperation op)
{
switch (op)
{
case SO_CREATE_NEW_LEFT:
- return _("Copy new file/folder to left");
+ return L"create <-";
case SO_CREATE_NEW_RIGHT:
- return _("Copy new file/folder to right");
+ return L"create ->";
case SO_DELETE_LEFT:
- return _("Delete left file/folder");
+ return L"delete <-";
case SO_DELETE_RIGHT:
- return _("Delete right file/folder");
- case SO_OVERWRITE_LEFT:
- return _("Overwrite left file/folder with right one");
- case SO_OVERWRITE_RIGHT:
- return _("Overwrite right file/folder with left one");
- case SO_DO_NOTHING:
- return _("Do nothing");
- case SO_EQUAL:
- return _("Both sides are equal");
- case SO_COPY_METADATA_TO_LEFT:
- return _("Copy file attributes only to left");
- case SO_COPY_METADATA_TO_RIGHT:
- return _("Copy file attributes only to right");
- case SO_UNRESOLVED_CONFLICT: //not used on GUI, but in .csv
- return _("Conflict/file cannot be categorized");
- };
-
- assert(false);
- return wxEmptyString;
-}
-
-
-wxString zen::getSymbol(SyncOperation op)
-{
- switch (op)
- {
- case SO_CREATE_NEW_LEFT:
- return wxT("*-");
- case SO_CREATE_NEW_RIGHT:
- return wxT("-*");
- case SO_DELETE_LEFT:
- return wxT("D-");
- case SO_DELETE_RIGHT:
- return wxT("-D");
+ return L"delete ->";
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ return L"move <-";
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
+ return L"move ->";
case SO_OVERWRITE_LEFT:
case SO_COPY_METADATA_TO_LEFT:
- return wxT("<-");
+ return L"update <-";
case SO_OVERWRITE_RIGHT:
case SO_COPY_METADATA_TO_RIGHT:
- return wxT("->");
+ return L"update ->";
case SO_DO_NOTHING:
- return wxT(" -");
+ return L" -";
case SO_EQUAL:
- return wxT("'=="); //added quotation mark to avoid error in Excel cell when exporting to *.cvs
+ return L"'=="; //added quotation mark to avoid error in Excel cell when exporting to *.cvs
case SO_UNRESOLVED_CONFLICT:
- return wxT("\\/\\->");
+ return L"conflict";
};
-
assert(false);
- return wxEmptyString;
+ return std::wstring();
}
@@ -329,7 +273,7 @@ zen::Int64 resolve(size_t value, UnitTime unit, zen::Int64 defaultVal)
zen::UInt64 resolve(size_t value, UnitSize unit, zen::UInt64 defaultVal)
{
- double out = value;
+ double out = 0;
switch (unit)
{
case USIZE_NONE:
@@ -337,10 +281,10 @@ zen::UInt64 resolve(size_t value, UnitSize unit, zen::UInt64 defaultVal)
case USIZE_BYTE:
return value;
case USIZE_KB:
- out *= 1024;
+ out = 1024.0 * value;
break;
case USIZE_MB:
- out *= 1024 * 1024;
+ out = 1024 * 1024.0 * value;
break;
}
return out >= to<double>(std::numeric_limits<zen::UInt64>::max()) ? //prevent overflow!!!
diff --git a/structures.h b/structures.h
index 47d34d0c..046b719e 100644
--- a/structures.h
+++ b/structures.h
@@ -7,15 +7,13 @@
#ifndef FREEFILESYNC_H_INCLUDED
#define FREEFILESYNC_H_INCLUDED
-#include <wx/string.h>
#include <vector>
+#include <memory>
#include <zen/zstring.h>
#include <zen/assert_static.h>
-#include <memory>
#include <zen/int64.h>
-
namespace zen
{
enum CompareVariant
@@ -24,7 +22,7 @@ enum CompareVariant
CMP_BY_CONTENT
};
-wxString getVariantName(CompareVariant var);
+std::wstring getVariantName(CompareVariant var);
enum SymLinkHandling
{
@@ -89,8 +87,7 @@ CompareFilesResult convertToFilesResult(CompareSymlinkResult value)
}
-wxString getDescription(CompareFilesResult cmpRes);
-wxString getSymbol(CompareFilesResult cmpRes);
+std::wstring getSymbol(CompareFilesResult cmpRes);
enum SyncOperation
@@ -99,17 +96,24 @@ enum SyncOperation
SO_CREATE_NEW_RIGHT,
SO_DELETE_LEFT,
SO_DELETE_RIGHT,
+
+ SO_MOVE_LEFT_SOURCE, //SO_DELETE_LEFT - optimization!
+ SO_MOVE_LEFT_TARGET, //SO_CREATE_NEW_LEFT
+
+ SO_MOVE_RIGHT_SOURCE, //SO_DELETE_RIGHT - optimization!
+ SO_MOVE_RIGHT_TARGET, //SO_CREATE_NEW_RIGHT
+
SO_OVERWRITE_LEFT,
SO_OVERWRITE_RIGHT,
SO_COPY_METADATA_TO_LEFT, //objects are already equal: transfer metadata only
SO_COPY_METADATA_TO_RIGHT, //
+
SO_DO_NOTHING, //= both sides differ, but nothing will be synced
SO_EQUAL, //= both sides are equal, so nothing will be synced
SO_UNRESOLVED_CONFLICT
};
-wxString getDescription(SyncOperation op);
-wxString getSymbol(SyncOperation op);
+std::wstring getSymbol (SyncOperation op); //method used for exporting .csv file only!
struct DirectionSet
@@ -171,7 +175,7 @@ bool operator==(const DirectionConfig& lhs, const DirectionConfig& rhs)
//get sync directions: DON'T call for variant AUTOMATIC!
DirectionSet extractDirections(const DirectionConfig& cfg);
-wxString getVariantName(DirectionConfig::Variant var);
+std::wstring getVariantName(DirectionConfig::Variant var);
@@ -209,8 +213,8 @@ enum DeletionPolicy
struct SyncConfig
{
SyncConfig(const DirectionConfig& directCfg,
- const DeletionPolicy handleDel,
- const wxString& customDelDir) :
+ const DeletionPolicy handleDel,
+ const Zstring& customDelDir) :
directionCfg(directCfg),
handleDeletion(handleDel),
customDeletionDirectory(customDelDir) {}
@@ -223,7 +227,7 @@ struct SyncConfig
//misc options
DeletionPolicy handleDeletion; //use Recycle, delete permanently or move to user-defined location
- wxString customDeletionDirectory;
+ Zstring customDeletionDirectory;
};
inline
@@ -231,7 +235,7 @@ bool operator==(const SyncConfig& lhs, const SyncConfig& rhs)
{
return lhs.directionCfg == rhs.directionCfg &&
lhs.handleDeletion == rhs.handleDeletion &&
- (lhs.handleDeletion != MOVE_TO_CUSTOM_DIRECTORY || //only cmp custom deletion directory if required!
+ (lhs.handleDeletion != MOVE_TO_CUSTOM_DIRECTORY || //only compare deletion directory if required!
lhs.customDeletionDirectory == rhs.customDeletionDirectory);
}
@@ -365,16 +369,14 @@ struct MainConfiguration
MainConfiguration() :
#ifdef FFS_WIN
globalFilter(Zstr("*"),
- Zstr("\
-\\System Volume Information\\\n\
-\\RECYCLED\\\n\
-\\RECYCLER\\\n\
-\\$Recycle.Bin\\")) {}
+ Zstr("\\System Volume Information\\\n")
+ Zstr("\\RECYCLED\\\n")
+ Zstr("\\RECYCLER\\\n")
+ Zstr("\\$Recycle.Bin\\")) {}
#elif defined FFS_LINUX
globalFilter(Zstr("*"),
- Zstr("\
-/.Trash-*/\n\
-/.recycle/")) {}
+ Zstr("/.Trash-*/\n")
+ Zstr("/.recycle/")) {}
#endif
CompConfig cmpConfig; //global compare settings: may be overwritten by folder pair settings
@@ -384,18 +386,18 @@ struct MainConfiguration
FolderPairEnh firstPair; //there needs to be at least one pair!
std::vector<FolderPairEnh> additionalPairs;
- wxString getCompVariantName() const;
- wxString getSyncVariantName() const;
+ std::wstring getCompVariantName() const;
+ std::wstring getSyncVariantName() const;
};
inline
bool operator==(const MainConfiguration& lhs, const MainConfiguration& rhs)
{
- return lhs.cmpConfig == rhs.cmpConfig &&
- lhs.globalFilter == rhs.globalFilter &&
- lhs.syncCfg == rhs.syncCfg &&
- lhs.firstPair == rhs.firstPair &&
+ return lhs.cmpConfig == rhs.cmpConfig &&
+ lhs.globalFilter == rhs.globalFilter &&
+ lhs.syncCfg == rhs.syncCfg &&
+ lhs.firstPair == rhs.firstPair &&
lhs.additionalPairs == rhs.additionalPairs;
}
diff --git a/synchronization.cpp b/synchronization.cpp
index 66c7d262..8a5027be 100644
--- a/synchronization.cpp
+++ b/synchronization.cpp
@@ -8,7 +8,7 @@
#include <memory>
#include <deque>
#include <stdexcept>
-#include <wx/msgdlg.h>
+#include <wx/utils.h>
#include <wx/log.h>
#include <wx/file.h>
#include <wx+/string_conv.h>
@@ -32,36 +32,55 @@
using namespace zen;
+namespace
+{
+inline
+int getCUD(const SyncStatistics& stat)
+{
+ return stat.getCreate() +
+ stat.getUpdate() +
+ stat.getDelete();
+}
+}
+
void SyncStatistics::init()
{
- createLeft = 0;
- createRight = 0;
- overwriteLeft = 0;
- overwriteRight = 0;
- deleteLeft = 0;
- deleteRight = 0;
- conflict = 0;
- rowsTotal = 0;
+ createLeft = 0;
+ createRight = 0;
+ updateLeft = 0;
+ updateRight = 0;
+ deleteLeft = 0;
+ deleteRight = 0;
+ conflict = 0;
+ rowsTotal = 0;
}
SyncStatistics::SyncStatistics(const FolderComparison& folderCmp)
{
init();
- std::for_each(begin(folderCmp), end(folderCmp), [&](const BaseDirMapping& baseMap) { getNumbersRecursively(baseMap); });
+ std::for_each(begin(folderCmp), end(folderCmp), [&](const BaseDirMapping& baseMap) { recurse(baseMap); });
}
SyncStatistics::SyncStatistics(const HierarchyObject& hierObj)
{
init();
- getNumbersRecursively(hierObj);
+ recurse(hierObj);
+}
+
+
+SyncStatistics::SyncStatistics(const FileMapping& fileObj)
+{
+ init();
+ getFileNumbers(fileObj);
+ rowsTotal += 1;
}
inline
-void SyncStatistics::getNumbersRecursively(const HierarchyObject& hierObj)
+void SyncStatistics::recurse(const HierarchyObject& hierObj)
{
std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(),
[&](const DirMapping& dirObj) { getDirNumbers(dirObj); });
@@ -101,13 +120,25 @@ void SyncStatistics::getFileNumbers(const FileMapping& fileObj)
++deleteRight;
break;
+ case SO_MOVE_LEFT_TARGET:
+ ++updateLeft;
+ break;
+
+ case SO_MOVE_RIGHT_TARGET:
+ ++updateRight;
+ break;
+
+ case SO_MOVE_LEFT_SOURCE: //ignore
+ case SO_MOVE_RIGHT_SOURCE: //
+ break;
+
case SO_OVERWRITE_LEFT:
- ++overwriteLeft;
+ ++updateLeft;
dataToProcess += fileObj.getFileSize<RIGHT_SIDE>();
break;
case SO_OVERWRITE_RIGHT:
- ++overwriteRight;
+ ++updateRight;
dataToProcess += fileObj.getFileSize<LEFT_SIDE>();
break;
@@ -118,11 +149,11 @@ void SyncStatistics::getFileNumbers(const FileMapping& fileObj)
break;
case SO_COPY_METADATA_TO_LEFT:
- ++overwriteLeft;
+ ++updateLeft;
break;
case SO_COPY_METADATA_TO_RIGHT:
- ++overwriteRight;
+ ++updateRight;
break;
case SO_DO_NOTHING:
@@ -155,12 +186,12 @@ void SyncStatistics::getLinkNumbers(const SymLinkMapping& linkObj)
case SO_OVERWRITE_LEFT:
case SO_COPY_METADATA_TO_LEFT:
- ++overwriteLeft;
+ ++updateLeft;
break;
case SO_OVERWRITE_RIGHT:
case SO_COPY_METADATA_TO_RIGHT:
- ++overwriteRight;
+ ++updateRight;
break;
case SO_UNRESOLVED_CONFLICT:
@@ -169,6 +200,11 @@ void SyncStatistics::getLinkNumbers(const SymLinkMapping& linkObj)
firstConflicts.push_back(std::make_pair(linkObj.getObjRelativeName(), linkObj.getSyncOpConflict()));
break;
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
+ assert(false);
case SO_DO_NOTHING:
case SO_EQUAL:
break;
@@ -209,20 +245,24 @@ void SyncStatistics::getDirNumbers(const DirMapping& dirObj)
break;
case SO_COPY_METADATA_TO_LEFT:
- ++overwriteLeft;
+ ++updateLeft;
break;
case SO_COPY_METADATA_TO_RIGHT:
- ++overwriteRight;
+ ++updateRight;
break;
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
+ assert(false);
case SO_DO_NOTHING:
case SO_EQUAL:
break;
}
- //recurse into sub-dirs
- getNumbersRecursively(dirObj);
+ recurse(dirObj);
}
@@ -245,7 +285,7 @@ std::vector<zen::FolderPairSyncCfg> zen::extractSyncCfg(const MainConfiguration&
output.push_back(
FolderPairSyncCfg(syncCfg.directionCfg.var == DirectionConfig::AUTOMATIC,
syncCfg.handleDeletion,
- toZ(syncCfg.customDeletionDirectory)));
+ syncCfg.customDeletionDirectory));
}
return output;
@@ -257,7 +297,7 @@ namespace
bool synchronizationNeeded(const SyncStatistics& statisticsTotal)
{
return statisticsTotal.getCreate() +
- statisticsTotal.getOverwrite() +
+ statisticsTotal.getUpdate() +
statisticsTotal.getDelete() +
//conflicts (unless excluded) justify a sync! Also note: if this method returns false, no warning about unresolved conflicts were shown!
statisticsTotal.getConflict() != 0;
@@ -269,18 +309,18 @@ bool synchronizationNeeded(const SyncStatistics& statisticsTotal)
bool significantDifferenceDetected(const SyncStatistics& folderPairStat)
{
//initial file copying shall not be detected as major difference
- if (folderPairStat.getCreate<LEFT_SIDE>() == 0 &&
- folderPairStat.getOverwrite() == 0 &&
- folderPairStat.getDelete() == 0 &&
- folderPairStat.getConflict() == 0) return false;
+ if (folderPairStat.getCreate<LEFT_SIDE>() == 0 &&
+ folderPairStat.getUpdate () == 0 &&
+ folderPairStat.getDelete () == 0 &&
+ folderPairStat.getConflict() == 0) return false;
if (folderPairStat.getCreate<RIGHT_SIDE>() == 0 &&
- folderPairStat.getOverwrite() == 0 &&
- folderPairStat.getDelete() == 0 &&
- folderPairStat.getConflict() == 0) return false;
+ folderPairStat.getUpdate () == 0 &&
+ folderPairStat.getDelete () == 0 &&
+ folderPairStat.getConflict() == 0) return false;
- const int changedRows = folderPairStat.getCreate() +
- folderPairStat.getOverwrite() +
- folderPairStat.getDelete() +
+ const int changedRows = folderPairStat.getCreate () +
+ folderPairStat.getUpdate () +
+ folderPairStat.getDelete () +
folderPairStat.getConflict();
return changedRows >= 10 && changedRows > 0.5 * folderPairStat.getRowCount();
@@ -361,10 +401,10 @@ SyncProcess::SyncProcess(xmlAccess::OptionalDialogs& warnings,
transactionalFileCopy_(transactionalFileCopy),
m_warnings(warnings),
procCallback(handler)
- {
-if (runWithBackgroundPriority)
-procBackground.reset(new ScheduleForBackgroundProcessing);
- }
+{
+ if (runWithBackgroundPriority)
+ procBackground.reset(new ScheduleForBackgroundProcessing);
+}
//--------------------------------------------------------------------------------------------------------------
namespace
@@ -377,7 +417,7 @@ class DeletionHandling //e.g. generate name of alternate deletion directory (uni
public:
DeletionHandling(DeletionPolicy handleDel,
const Zstring& custDelFolder,
- const Zstring& baseDir, //with separator postfix
+ const Zstring& baseDirPf, //with separator postfix
ProcessCallback& procCallback);
~DeletionHandling(); //always (try to) clean up, even if synchronization is aborted!
@@ -387,9 +427,9 @@ public:
void removeFile (const Zstring& relativeName) const; //throw FileError
void removeFolder(const Zstring& relativeName) const; //throw FileError
- const wxString& getTxtRemovingFile () const { return txtRemovingFile; } //
- const wxString& getTxtRemovingSymLink() const { return txtRemovingSymlink; } //status text templates
- const wxString& getTxtRemovingDir () const { return txtRemovingDirectory; } //
+ const std::wstring& getTxtRemovingFile () const { return txtRemovingFile; } //
+ const std::wstring& getTxtRemovingSymLink() const { return txtRemovingSymlink; } //status text templates
+ const std::wstring& getTxtRemovingDir () const { return txtRemovingDirectory; } //
//evaluate whether a deletion will actually free space within a volume
bool deletionFreesSpace() const;
@@ -401,12 +441,12 @@ private:
Zstring sessionDelDir; //target deletion folder for current folder pair (with timestamp, ends with path separator)
- Zstring baseDir_; //with separator postfix
+ Zstring baseDirPf_; //with separator postfix
//preloaded status texts:
- wxString txtRemovingFile;
- wxString txtRemovingSymlink;
- wxString txtRemovingDirectory;
+ std::wstring txtRemovingFile;
+ std::wstring txtRemovingSymlink;
+ std::wstring txtRemovingDirectory;
bool cleanedUp;
};
@@ -414,41 +454,41 @@ private:
DeletionHandling::DeletionHandling(DeletionPolicy handleDel,
const Zstring& custDelFolder,
- const Zstring& baseDir, //with separator postfix
+ const Zstring& baseDirPf, //with separator postfix
ProcessCallback& procCallback) :
deletionType(handleDel),
procCallback_(&procCallback),
- baseDir_(baseDir),
+ baseDirPf_(baseDirPf),
cleanedUp(false)
{
#ifdef FFS_WIN
- if (baseDir.empty() ||
- (deletionType == MOVE_TO_RECYCLE_BIN && recycleBinStatus(baseDir) != STATUS_REC_EXISTS))
+ if (baseDirPf.empty() ||
+ (deletionType == MOVE_TO_RECYCLE_BIN && recycleBinStatus(baseDirPf) != STATUS_REC_EXISTS))
deletionType = DELETE_PERMANENTLY; //Windows' ::SHFileOperation() will do this anyway, but we have a better and faster deletion routine (e.g. on networks)
#endif
switch (deletionType)
{
case DELETE_PERMANENTLY:
- txtRemovingFile = replaceCpy(_("Deleting file %x" ), L"%x", L"\n\"%x\"", false);
- txtRemovingDirectory = replaceCpy(_("Deleting folder %x" ), L"%x", L"\n\"%x\"", false);
- txtRemovingSymlink = replaceCpy(_("Deleting symbolic link %x"), L"%x", L"\n\"%x\"", false);
+ txtRemovingFile = replaceCpy(_("Deleting file %x" ), L"%x", L"\"%x\"", false);
+ txtRemovingDirectory = replaceCpy(_("Deleting folder %x" ), L"%x", L"\"%x\"", false);
+ txtRemovingSymlink = replaceCpy(_("Deleting symbolic link %x"), L"%x", L"\"%x\"", false);
break;
case MOVE_TO_RECYCLE_BIN:
- sessionDelDir = getSessionDeletionDir(baseDir_, Zstr("FFS "));
+ sessionDelDir = getSessionDeletionDir(baseDirPf_, Zstr("FFS "));
- txtRemovingFile = replaceCpy(_("Moving file %x to recycle bin" ), L"%x", L"\n\"%x\"", false);
- txtRemovingDirectory = replaceCpy(_("Moving folder %x to recycle bin" ), L"%x", L"\n\"%x\"", false);
- txtRemovingSymlink = replaceCpy(_("Moving symbolic link %x to recycle bin"), L"%x", L"\n\"%x\"", false);
+ txtRemovingFile = replaceCpy(_("Moving file %x to recycle bin" ), L"%x", L"\"%x\"", false);
+ txtRemovingDirectory = replaceCpy(_("Moving folder %x to recycle bin" ), L"%x", L"\"%x\"", false);
+ txtRemovingSymlink = replaceCpy(_("Moving symbolic link %x to recycle bin"), L"%x", L"\"%x\"", false);
break;
case MOVE_TO_CUSTOM_DIRECTORY:
sessionDelDir = getSessionDeletionDir(custDelFolder);
- txtRemovingFile = replaceCpy(replaceCpy(_("Moving file %x to %y" ), L"%x", L"\n\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<wxString>(custDelFolder) + L"\"", false);
- txtRemovingDirectory = replaceCpy(replaceCpy(_("Moving folder %x to %y" ), L"%x", L"\n\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<wxString>(custDelFolder) + L"\"", false);
- txtRemovingSymlink = replaceCpy(replaceCpy(_("Moving symbolic link %x to %y"), L"%x", L"\n\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<wxString>(custDelFolder) + L"\"", false);
+ txtRemovingFile = replaceCpy(replaceCpy(_("Moving file %x to %y" ), L"%x", L"\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<std::wstring>(custDelFolder) + L"\"", false);
+ txtRemovingDirectory = replaceCpy(replaceCpy(_("Moving folder %x to %y" ), L"%x", L"\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<std::wstring>(custDelFolder) + L"\"", false);
+ txtRemovingSymlink = replaceCpy(replaceCpy(_("Moving symbolic link %x to %y"), L"%x", L"\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<std::wstring>(custDelFolder) + L"\"", false);
break;
}
}
@@ -497,12 +537,12 @@ struct CallbackRemoveDirImpl : public CallbackRemoveDir
virtual void notifyFileDeletion(const Zstring& filename)
{
- delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(filename)));
+ delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingFile(), L"%x", utf8CvrtTo<std::wstring>(filename)));
}
virtual void notifyDirDeletion(const Zstring& dirname)
{
- delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingDir(), L"%x", utf8CvrtTo<wxString>(dirname)));
+ delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingDir(), L"%x", utf8CvrtTo<std::wstring>(dirname)));
}
private:
@@ -513,7 +553,7 @@ private:
void DeletionHandling::removeFile(const Zstring& relativeName) const
{
- const Zstring fullName = baseDir_ + relativeName;
+ const Zstring fullName = baseDirPf_ + relativeName;
switch (deletionType)
{
@@ -562,7 +602,7 @@ void DeletionHandling::removeFile(const Zstring& relativeName) const
void DeletionHandling::removeFolder(const Zstring& relativeName) const
{
- const Zstring fullName = baseDir_ + relativeName;
+ const Zstring fullName = baseDirPf_ + relativeName;
switch (deletionType)
{
@@ -621,7 +661,7 @@ bool DeletionHandling::deletionFreesSpace() const
case MOVE_TO_RECYCLE_BIN:
return false; //in general... (unless Recycle Bin is full)
case MOVE_TO_CUSTOM_DIRECTORY:
- switch (zen::onSameVolume(baseDir_, sessionDelDir))
+ switch (zen::onSameVolume(baseDirPf_, sessionDelDir))
{
case IS_SAME_YES:
return false;
@@ -642,20 +682,21 @@ namespace
class DiskSpaceNeeded
{
public:
- DiskSpaceNeeded(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight) :
- freeSpaceDelLeft_(freeSpaceDelLeft),
- freeSpaceDelRight_(freeSpaceDelRight)
+ static std::pair<Int64, Int64> calculate(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight)
{
- processRecursively(baseObj);
+ DiskSpaceNeeded inst(baseObj, freeSpaceDelLeft, freeSpaceDelRight);
+ return std::make_pair(inst.spaceNeededLeft, inst.spaceNeededRight);
}
- std::pair<zen::Int64, zen::Int64> getSpaceTotal() const
+private:
+ DiskSpaceNeeded(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight) :
+ freeSpaceDelLeft_(freeSpaceDelLeft),
+ freeSpaceDelRight_(freeSpaceDelRight)
{
- return std::make_pair(spaceNeededLeft, spaceNeededRight);
+ recurse(baseObj);
}
-private:
- void processRecursively(const HierarchyObject& hierObj)
+ void recurse(const HierarchyObject& hierObj)
{
//don't process directories
@@ -664,33 +705,33 @@ private:
switch (i->getSyncOperation()) //evaluate comparison result and sync direction
{
case SO_CREATE_NEW_LEFT:
- spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>());
+ spaceNeededLeft += to<Int64>(i->getFileSize<RIGHT_SIDE>());
break;
case SO_CREATE_NEW_RIGHT:
- spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>());
+ spaceNeededRight += to<Int64>(i->getFileSize<LEFT_SIDE>());
break;
case SO_DELETE_LEFT:
if (freeSpaceDelLeft_)
- spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>());
+ spaceNeededLeft -= to<Int64>(i->getFileSize<LEFT_SIDE>());
break;
case SO_DELETE_RIGHT:
if (freeSpaceDelRight_)
- spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>());
+ spaceNeededRight -= to<Int64>(i->getFileSize<RIGHT_SIDE>());
break;
case SO_OVERWRITE_LEFT:
if (freeSpaceDelLeft_)
- spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>());
- spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>());
+ spaceNeededLeft -= to<Int64>(i->getFileSize<LEFT_SIDE>());
+ spaceNeededLeft += to<Int64>(i->getFileSize<RIGHT_SIDE>());
break;
case SO_OVERWRITE_RIGHT:
if (freeSpaceDelRight_)
- spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>());
- spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>());
+ spaceNeededRight -= to<Int64>(i->getFileSize<RIGHT_SIDE>());
+ spaceNeededRight += to<Int64>(i->getFileSize<LEFT_SIDE>());
break;
case SO_DO_NOTHING:
@@ -698,6 +739,10 @@ private:
case SO_UNRESOLVED_CONFLICT:
case SO_COPY_METADATA_TO_LEFT:
case SO_COPY_METADATA_TO_RIGHT:
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
break;
}
@@ -705,78 +750,20 @@ private:
//[...]
//recurse into sub-dirs
- std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), [&](const HierarchyObject& subDir) { this->processRecursively(subDir); });
+ std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), [&](const HierarchyObject& subDir) { this->recurse(subDir); });
//for (auto& subDir : hierObj.refSubDirs())
- // processRecursively(subDir);
+ // recurse(subDir);
}
const bool freeSpaceDelLeft_;
const bool freeSpaceDelRight_;
- zen::Int64 spaceNeededLeft;
- zen::Int64 spaceNeededRight;
+ Int64 spaceNeededLeft;
+ Int64 spaceNeededRight;
};
}
//----------------------------------------------------------------------------------------
-//test if current sync-line will result in deletion of files or
-//big file is overwritten by smaller one -> used to avoid disc space bottlenecks (at least if permanent deletion is active)
-inline
-bool diskSpaceIsReduced(const FileMapping& fileObj)
-{
- switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction
- {
- case SO_DELETE_LEFT:
- case SO_DELETE_RIGHT:
- return true;
-
- case SO_OVERWRITE_LEFT:
- return fileObj.getFileSize<LEFT_SIDE>() > fileObj.getFileSize<RIGHT_SIDE>();
-
- case SO_OVERWRITE_RIGHT:
- return fileObj.getFileSize<LEFT_SIDE>() < fileObj.getFileSize<RIGHT_SIDE>();
-
- case SO_CREATE_NEW_LEFT:
- case SO_CREATE_NEW_RIGHT:
- case SO_DO_NOTHING:
- case SO_EQUAL:
- case SO_UNRESOLVED_CONFLICT:
- case SO_COPY_METADATA_TO_LEFT:
- case SO_COPY_METADATA_TO_RIGHT:
- return false;
- }
- assert(false);
- return false; //dummy
-}
-
-
-inline
-bool diskSpaceIsReduced(const DirMapping& dirObj)
-{
- switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction
- {
- case SO_DELETE_LEFT:
- case SO_DELETE_RIGHT:
- return true;
-
- case SO_OVERWRITE_LEFT:
- case SO_OVERWRITE_RIGHT:
- assert(false);
- case SO_CREATE_NEW_LEFT:
- case SO_CREATE_NEW_RIGHT:
- case SO_DO_NOTHING:
- case SO_EQUAL:
- case SO_UNRESOLVED_CONFLICT:
- case SO_COPY_METADATA_TO_LEFT:
- case SO_COPY_METADATA_TO_RIGHT:
- return false;
- }
- assert(false);
- return false; //dummy
-}
-//---------------------------------------------------------------------------------------------------------------
-
-
class zen::SynchronizeFolderPair
{
public:
@@ -801,36 +788,58 @@ public:
txtOverwritingFile (replaceCpy(_("Overwriting file %x" ), L"%x", L"\"%x\"", false)),
txtOverwritingLink (replaceCpy(_("Overwriting symbolic link %x"), L"%x", L"\"%x\"", false)),
txtVerifying (replaceCpy(_("Verifying file %x" ), L"%x", L"\"%x\"", false)),
- txtWritingAttributes(replaceCpy(_("Updating attributes of %x" ), L"%x", L"\"%x\"", false)) {}
+ txtWritingAttributes(replaceCpy(_("Updating attributes of %x" ), L"%x", L"\"%x\"", false)),
+ txtMovingFile (replaceCpy(replaceCpy(_("Moving file %x to %y"), L"%x", L"\"%x\"", false), L"%y", L"\"%y\"", false)) {}
void startSync(BaseDirMapping& baseMap)
{
- //loop through all files twice; reason: first delete files (or overwrite big ones with smaller ones), then copy rest
- execute<FIRST_PASS >(baseMap);
- execute<SECOND_PASS>(baseMap);
+ runZeroPass(baseMap); //first process file moves
+ runPass<PASS_ONE>(baseMap); //delete files (or overwrite big ones with smaller ones)
+ runPass<PASS_TWO>(baseMap); //copy rest
}
private:
enum PassId
{
- FIRST_PASS, //delete files
- SECOND_PASS //create, modify
+ PASS_ONE, //delete files
+ PASS_TWO, //create, modify
+ PASS_NEVER //skip
};
+ static PassId getPass(const FileMapping& fileObj);
+ static PassId getPass(const SymLinkMapping& linkObj);
+ static PassId getPass(const DirMapping& dirObj);
+
+ template <SelectedSide side>
+ void prepare2StepMove(FileMapping& sourceObj, FileMapping& targetObj); //throw FileError
+ bool createParentDir(FileSystemObject& fsObj); //throw FileError
+ template <SelectedSide side>
+ void manageFileMove(FileMapping& sourceObj, FileMapping& targetObj); //throw FileError
+
+ void runZeroPass(HierarchyObject& hierObj);
template <PassId pass>
- void execute(HierarchyObject& hierObj);
+ void runPass(HierarchyObject& hierObj);
+
+ void synchronizeFile(FileMapping& fileObj) const;
+ template <SelectedSide side> void synchronizeFileInt(FileMapping& fileObj, SyncOperation syncOp) const;
+
+ void synchronizeLink(SymLinkMapping& linkObj) const;
+ template <SelectedSide sideTrg> void synchronizeLinkInt(SymLinkMapping& linkObj, SyncOperation syncOp) const;
+
+ void synchronizeFolder(DirMapping& dirObj) const;
+ template <SelectedSide sideTrg> void synchronizeFolderInt(DirMapping& dirObj, SyncOperation syncOp) const;
- void synchronizeFile (FileMapping& fileObj) const;
- void synchronizeLink (SymLinkMapping& linkObj) const;
- void synchronizeFolder(DirMapping& dirObj) const;
+ void reportInfo (const std::wstring& rawText, const Zstring& objname) const { procCallback_.reportInfo (replaceCpy(rawText, L"%x", utf8CvrtTo<std::wstring>(objname))); };
+ void reportStatus(const std::wstring& rawText, const Zstring& objname) const { procCallback_.reportStatus(replaceCpy(rawText, L"%x", utf8CvrtTo<std::wstring>(objname))); };
//more low level helper
- template <zen::SelectedSide side>
- void deleteSymlink(const SymLinkMapping& linkObj) const;
template <SelectedSide side, class DelTargetCommand>
- void copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileDescriptor& sourceAttr) const;
+ void copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileAttrib& newAttr) const;
void verifyFileCopy(const Zstring& source, const Zstring& target) const;
+ template <SelectedSide side>
+ const DeletionHandling& getDelHandling() const;
+
ProcessCallback& procCallback_;
#ifdef FFS_WIN
shadow::ShadowCopy* shadowCopyHandler_; //optional!
@@ -843,198 +852,556 @@ private:
const bool transactionalFileCopy;
//preload status texts
- const wxString txtCreatingFile;
- const wxString txtCreatingLink;
- const wxString txtCreatingFolder;
- const wxString txtOverwritingFile;
- const wxString txtOverwritingLink;
- const wxString txtVerifying;
- const wxString txtWritingAttributes;
+ const std::wstring txtCreatingFile;
+ const std::wstring txtCreatingLink;
+ const std::wstring txtCreatingFolder;
+ const std::wstring txtOverwritingFile;
+ const std::wstring txtOverwritingLink;
+ const std::wstring txtVerifying;
+ const std::wstring txtWritingAttributes;
+ const std::wstring txtMovingFile;
};
+//---------------------------------------------------------------------------------------------------------------
+namespace zen
+{
+template <> inline
+const DeletionHandling& SynchronizeFolderPair::getDelHandling<LEFT_SIDE>() const { return delHandlingLeft_; }
+
+template <> inline
+const DeletionHandling& SynchronizeFolderPair::getDelHandling<RIGHT_SIDE>() const { return delHandlingRight_; }
+}
+
+
+/*
+__________________________
+|Move algorithm, 0th pass|
+--------------------------
+1. loop over hierarchy and find "move source"
+
+2. check whether parent directory of "move source" is going to be deleted or location of "move source" may lead to name clash with other dir/symlink
+ -> no: delay move until 2nd pass
+
+3. create move target's parent directory recursively + execute move
+ do we have name clash?
+ -> prepare a 2-step move operation: 1. move source to root and update "move target" accordingly 2. delay move until 2nd pass
+
+4. If any of the operations above did not succeed (even after retry), update statistics and revert to "copy + delete"
+ Note: first pass may delete "move source"!!!
+
+__________________
+|killer-scenarios|
+------------------
+propagate the following move sequences:
+I) a -> a/a caveat sync'ing parent directory first leads to circular dependency!
+
+II) a/a -> a caveat: fixing name clash will remove source!
+
+III) c -> d caveat: move-sequence needs to be processed in correct order!
+ b -> c/b
+ a -> b/a
+*/
+
+namespace
+{
+template <class Mapping> inline
+bool haveNameClash(const Zstring& shortname, Mapping& m)
+{
+ return std::find_if(m.begin(), m.end(),
+ [&](const typename Mapping::value_type& obj) { return EqualFilename()(obj.getObjShortName(), shortname); }) != m.end();
+}
+
+
+Zstring findUniqueTempName(const Zstring& filename)
+{
+ Zstring output = filename + zen::TEMP_FILE_ENDING;
+
+ //ensure uniqueness
+ for (int i = 1; somethingExists(output); ++i)
+ output = filename + Zchar('_') + toString<Zstring>(i) + zen::TEMP_FILE_ENDING;
+
+ return output;
+}
+}
+
+
+template <SelectedSide side>
+void SynchronizeFolderPair::prepare2StepMove(FileMapping& sourceObj,
+ FileMapping& targetObj) //throw FileError
+{
+ const Zstring& source = sourceObj.getFullName<side>();
+ const Zstring& tmpTarget = findUniqueTempName(sourceObj.getBaseDirPf<side>() + sourceObj.getShortName<side>());
+ //this could still lead to a name-clash in obscure cases, if some file ex. on the other side with
+ //the very same (.ffs_tmp) name and is copied before the second step of the move is executed
+ //good news: even in this pathologic case, this may only prevent the copy of the other file, but not the move
+
+ reportInfo(replaceCpy(txtMovingFile, L"%y", utf8CvrtTo<std::wstring>(tmpTarget)), source);
+
+ renameFile(source, tmpTarget); //throw FileError;
+
+ //update file hierarchy
+ const FileDescriptor descrSource(sourceObj.getLastWriteTime<side>(),
+ sourceObj.getFileSize <side>(),
+ sourceObj.getFileId <side>());
+
+ sourceObj.removeObject<side>();
+
+ FileMapping& tempFile = sourceObj.root().addSubFile<side>(afterLast(tmpTarget, FILE_NAME_SEPARATOR), descrSource);
+
+ //prepare move in second pass
+ tempFile.setSyncDir(side == LEFT_SIDE ? SYNC_DIR_LEFT : SYNC_DIR_RIGHT);
+
+ targetObj.setMoveRef(tempFile .getId());
+ tempFile .setMoveRef(targetObj.getId());
+
+ //NO statistics update!
+ procCallback_.requestUiRefresh(); //may throw
+}
+
+
+bool SynchronizeFolderPair::createParentDir(FileSystemObject& fsObj) //throw FileError, "false" on name clash
+{
+ if (DirMapping* parentDir = dynamic_cast<DirMapping*>(&fsObj.parent()))
+ {
+ if (!createParentDir(*parentDir))
+ return false;
+
+ //detect (and try to resolve) file type conflicts: 1. symlinks 2. files
+ const Zstring& shortname = parentDir->getObjShortName();
+ if (haveNameClash(shortname, parentDir->parent().refSubLinks()) ||
+ haveNameClash(shortname, parentDir->parent().refSubFiles()))
+ return false;
+
+ //in this context "parentDir" cannot be scheduled for deletion since it contains a "move target"!
+ //note: if parentDir were deleted, we'd end up destroying "fsObj"!
+ assert(parentDir->getSyncOperation() != SO_DELETE_LEFT &&
+ parentDir->getSyncOperation() != SO_DELETE_RIGHT);
+
+ synchronizeFolder(*parentDir); //throw FileError
+ }
+ return true;
+}
+
+
+template <SelectedSide side>
+void SynchronizeFolderPair::manageFileMove(FileMapping& sourceObj,
+ FileMapping& targetObj) //throw FileError
+{
+ assert((sourceObj.getSyncOperation() == SO_MOVE_LEFT_SOURCE && targetObj.getSyncOperation() == SO_MOVE_LEFT_TARGET && side == LEFT_SIDE) ||
+ (sourceObj.getSyncOperation() == SO_MOVE_RIGHT_SOURCE && targetObj.getSyncOperation() == SO_MOVE_RIGHT_TARGET && side == RIGHT_SIDE));
+
+ const bool sourceWillBeDeleted = [&]() -> bool
+ {
+ if (DirMapping* parentDir = dynamic_cast<DirMapping*>(&sourceObj.parent()))
+ {
+ switch (parentDir->getSyncOperation()) //evaluate comparison result and sync direction
+ {
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ return true; //we need to do something about it
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
+ case SO_OVERWRITE_LEFT:
+ case SO_OVERWRITE_RIGHT:
+ case SO_CREATE_NEW_LEFT:
+ case SO_CREATE_NEW_RIGHT:
+ case SO_DO_NOTHING:
+ case SO_EQUAL:
+ case SO_UNRESOLVED_CONFLICT:
+ case SO_COPY_METADATA_TO_LEFT:
+ case SO_COPY_METADATA_TO_RIGHT:
+ break;
+ }
+ }
+ return false;
+ }();
+
+ auto haveNameClash = [](const FileMapping& fileObj)
+ {
+ return ::haveNameClash(fileObj.getObjShortName(), fileObj.parent().refSubLinks()) ||
+ ::haveNameClash(fileObj.getObjShortName(), fileObj.parent().refSubDirs());
+ };
+
+ if (sourceWillBeDeleted || haveNameClash(sourceObj))
+ {
+ //prepare for move now: - revert to 2-step move on name clashes
+ if (haveNameClash(targetObj) ||
+ !createParentDir(targetObj)) //throw FileError
+ return prepare2StepMove<side>(sourceObj, targetObj); //throw FileError
+
+ //finally start move! this should work now:
+ synchronizeFile(sourceObj); //throw FileError
+ }
+ //else: sourceObj will not be deleted, and is not standing in the way => delay to second pass
+ //note: this case may include "move sources" from two-step sub-routine!
+}
+
+
+void SynchronizeFolderPair::runZeroPass(HierarchyObject& hierObj)
+{
+ //search for file move-operations
+
+ for (auto iter = hierObj.refSubFiles().begin(); iter != hierObj.refSubFiles().end(); ++iter) //VS 2010 crashes if we use for_each + lambda here...
+ {
+ FileMapping& fileObj = *iter;
+
+ const SyncOperation syncOp = fileObj.getSyncOperation();
+ switch (syncOp) //evaluate comparison result and sync direction
+ {
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ {
+ FileMapping* sourceObj = &fileObj;
+ if (FileMapping* targetObj = dynamic_cast<FileMapping*>(FileSystemObject::retrieve(fileObj.getMoveRef())))
+ {
+ if (!tryReportingError(procCallback_, [&] { return syncOp == SO_MOVE_LEFT_SOURCE ? this->manageFileMove<LEFT_SIDE>(*sourceObj, *targetObj) : this->manageFileMove<RIGHT_SIDE>(*sourceObj, *targetObj); }))
+ {
+ //move operation has failed! We cannot allow to continue and have move source's parent directory deleted, messing up statistics!
+ // => revert to ordinary "copy + delete"
+
+ auto getStat = [&]() -> std::pair<int, Int64>
+ {
+ SyncStatistics statSrc(*sourceObj);
+ SyncStatistics statTrg(*targetObj);
+
+ return std::make_pair(getCUD(statSrc) + getCUD(statTrg),
+ to<Int64>(statSrc.getDataToProcess() + statTrg.getDataToProcess()));
+ };
+
+ const auto statBefore = getStat();
+ sourceObj->setMoveRef(NULL);
+ targetObj->setMoveRef(NULL);
+ const auto statAfter = getStat();
+ //fix statistics to match "copy + delete"
+ procCallback_.updateProcessedData(statBefore.first - statAfter.first, statBefore.second - statAfter.second);
+ }
+ }
+ }
+ break;
+ case SO_MOVE_LEFT_TARGET: //it's enough to try each move-pair *once*
+ case SO_MOVE_RIGHT_TARGET: //
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ case SO_OVERWRITE_LEFT:
+ case SO_OVERWRITE_RIGHT:
+ case SO_CREATE_NEW_LEFT:
+ case SO_CREATE_NEW_RIGHT:
+ case SO_DO_NOTHING:
+ case SO_EQUAL:
+ case SO_UNRESOLVED_CONFLICT:
+ case SO_COPY_METADATA_TO_LEFT:
+ case SO_COPY_METADATA_TO_RIGHT:
+ break;
+ }
+ }
+
+ std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(),
+ [&](DirMapping& dirObj) { this->runZeroPass(dirObj); /*recurse */ });
+}
+//---------------------------------------------------------------------------------------------------------------
+
+
+//1st, 2nd pass requirements:
+// - avoid disk space shortage: 1. delete files, 2. overwrite big with small files first
+// - support change in type: overwrite file by directory, symlink by file, ect.
+
+inline
+SynchronizeFolderPair::PassId SynchronizeFolderPair::getPass(const FileMapping& fileObj)
+{
+ switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction
+ {
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ return PASS_ONE;
+
+ case SO_OVERWRITE_LEFT:
+ return fileObj.getFileSize<LEFT_SIDE>() > fileObj.getFileSize<RIGHT_SIDE>() ? PASS_ONE : PASS_TWO;
+
+ case SO_OVERWRITE_RIGHT:
+ return fileObj.getFileSize<LEFT_SIDE>() < fileObj.getFileSize<RIGHT_SIDE>() ? PASS_ONE : PASS_TWO;
+
+ case SO_MOVE_LEFT_SOURCE: //
+ case SO_MOVE_RIGHT_SOURCE: // [!]
+ return PASS_NEVER;
+ case SO_MOVE_LEFT_TARGET: //
+ case SO_MOVE_RIGHT_TARGET: //to be processed in second pass, after "move target" parent directory was created!
+ return PASS_TWO;
+
+ case SO_CREATE_NEW_LEFT:
+ case SO_CREATE_NEW_RIGHT:
+ case SO_DO_NOTHING:
+ case SO_EQUAL:
+ case SO_UNRESOLVED_CONFLICT:
+ case SO_COPY_METADATA_TO_LEFT:
+ case SO_COPY_METADATA_TO_RIGHT:
+ return PASS_TWO;
+ }
+ assert(false);
+ return PASS_TWO; //dummy
+}
+
+
+inline
+SynchronizeFolderPair::PassId SynchronizeFolderPair::getPass(const SymLinkMapping& linkObj)
+{
+ switch (linkObj.getSyncOperation()) //evaluate comparison result and sync direction
+ {
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ return PASS_ONE; //make sure to delete symlinks in first pass, and equally named file or dir in second pass: usecase "overwrite symlink with regular file"!
+
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
+ assert(false);
+ case SO_OVERWRITE_LEFT:
+ case SO_OVERWRITE_RIGHT:
+ case SO_CREATE_NEW_LEFT:
+ case SO_CREATE_NEW_RIGHT:
+ case SO_DO_NOTHING:
+ case SO_EQUAL:
+ case SO_UNRESOLVED_CONFLICT:
+ case SO_COPY_METADATA_TO_LEFT:
+ case SO_COPY_METADATA_TO_RIGHT:
+ return PASS_TWO;
+ }
+ assert(false);
+ return PASS_TWO; //dummy
+}
+
+
+inline
+SynchronizeFolderPair::PassId SynchronizeFolderPair::getPass(const DirMapping& dirObj)
+{
+ switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction
+ {
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ return PASS_ONE;
+
+ case SO_OVERWRITE_LEFT:
+ case SO_OVERWRITE_RIGHT:
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
+ assert(false);
+ case SO_CREATE_NEW_LEFT:
+ case SO_CREATE_NEW_RIGHT:
+ case SO_DO_NOTHING:
+ case SO_EQUAL:
+ case SO_UNRESOLVED_CONFLICT:
+ case SO_COPY_METADATA_TO_LEFT:
+ case SO_COPY_METADATA_TO_RIGHT:
+ return PASS_TWO;
+ }
+ assert(false);
+ return PASS_TWO; //dummy
+}
template <SynchronizeFolderPair::PassId pass>
-void SynchronizeFolderPair::execute(HierarchyObject& hierObj)
+void SynchronizeFolderPair::runPass(HierarchyObject& hierObj)
{
//synchronize files:
std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(),
[&](FileMapping& fileObj)
{
- const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(fileObj); //to be deleted files on first pass, rest on second!
- if (letsDoThis)
- tryReportingError(procCallback_, [&]() { synchronizeFile(fileObj); });
+ if (pass == getPass(fileObj))
+ tryReportingError(procCallback_, [&] { synchronizeFile(fileObj); });
});
- //synchronize symbolic links: (process in second step only)
- if (pass == SECOND_PASS)
- std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(),
- [&](SymLinkMapping& linkObj) { tryReportingError(procCallback_, [&]() { synchronizeLink(linkObj); }); });
+ //synchronize symbolic links:
+ std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(),
+ [&](SymLinkMapping& linkObj)
+ {
+ if (pass == getPass(linkObj))
+ tryReportingError(procCallback_, [&] { synchronizeLink(linkObj); });
+ });
//synchronize folders:
std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(),
[&](DirMapping& dirObj)
{
- const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(dirObj); //to be deleted dirs on first pass, rest on second!
- if (letsDoThis) //if we created all folders on first pass it would look strange for initial mirror sync when all folders are created at once
- tryReportingError(procCallback_, [&]() { synchronizeFolder(dirObj); });
+ if (pass == getPass(dirObj))
+ tryReportingError(procCallback_, [&] { synchronizeFolder(dirObj); });
- //recursion!
- this->execute<pass>(dirObj);
+ this->runPass<pass>(dirObj); //recurse
});
}
+//---------------------------------------------------------------------------------------------------------------
-void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
+namespace
{
- wxString logText;
- Zstring target;
-
- switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction
+inline
+bool getTargetDir(SyncOperation syncOp, SelectedSide* side)
+{
+ switch (syncOp)
{
case SO_CREATE_NEW_LEFT:
- target = fileObj.getBaseDirPf<LEFT_SIDE>() + fileObj.getRelativeName<RIGHT_SIDE>(); //can't use "getFullName" as target is not yet existing
+ case SO_DELETE_LEFT:
+ case SO_OVERWRITE_LEFT:
+ case SO_COPY_METADATA_TO_LEFT:
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ *side = LEFT_SIDE;
+ return true;
- logText = txtCreatingFile;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ case SO_CREATE_NEW_RIGHT:
+ case SO_DELETE_RIGHT:
+ case SO_OVERWRITE_RIGHT:
+ case SO_COPY_METADATA_TO_RIGHT:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
+ *side = RIGHT_SIDE;
+ return true;
- try
- {
- FileDescriptor sourceAttr;
- copyFileUpdatingTo<LEFT_SIDE>(fileObj,
- []() {}, //no target to delete
- sourceAttr);
+ case SO_DO_NOTHING:
+ case SO_EQUAL:
+ case SO_UNRESOLVED_CONFLICT:
+ break; //nothing to do
+ }
+ return false;
+}
+}
- fileObj.copyTo<LEFT_SIDE>(&sourceAttr); //update FileMapping
- }
- catch (FileError&)
- {
- if (fileExists(fileObj.getFullName<RIGHT_SIDE>()))
- throw;
- //source deleted meanwhile...
- procCallback_.updateProcessedData(0, to<zen::Int64>(fileObj.getFileSize<RIGHT_SIDE>()));
- fileObj.removeObject<RIGHT_SIDE>();
- }
- break;
+inline
+void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
+{
+ const SyncOperation syncOp = fileObj.getSyncOperation();
+
+ SelectedSide sideTrg = LEFT_SIDE;
+
+ if (getTargetDir(syncOp, &sideTrg))
+ {
+ if (sideTrg == LEFT_SIDE)
+ synchronizeFileInt<LEFT_SIDE>(fileObj, syncOp);
+ else
+ synchronizeFileInt<RIGHT_SIDE>(fileObj, syncOp);
+ }
+}
+
+
+template <SelectedSide sideTrg>
+void SynchronizeFolderPair::synchronizeFileInt(FileMapping& fileObj, SyncOperation syncOp) const
+{
+ static const SelectedSide sideSrc = OtherSide<sideTrg>::result;
+
+ switch (syncOp)
+ {
+ case SO_CREATE_NEW_LEFT:
case SO_CREATE_NEW_RIGHT:
- target = fileObj.getBaseDirPf<RIGHT_SIDE>() + fileObj.getRelativeName<LEFT_SIDE>();
+ {
+ const Zstring& target = fileObj.getBaseDirPf<sideTrg>() + fileObj.getRelativeName<sideSrc>(); //can't use "getFullName" as target is not yet existing
- logText = txtCreatingFile;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ reportInfo(txtCreatingFile, target);
try
{
- FileDescriptor sourceAttr;
- copyFileUpdatingTo<RIGHT_SIDE>(fileObj,
- []() {}, //no target to delete
- sourceAttr);
+ FileAttrib newAttr;
+ copyFileUpdatingTo<sideTrg>(fileObj, [] {}, /*no target to delete*/ newAttr);
- fileObj.copyTo<RIGHT_SIDE>(&sourceAttr); //update FileMapping
+ const FileDescriptor descrSource(newAttr.modificationTime, newAttr.fileSize, newAttr.sourceFileId);
+ const FileDescriptor descrTarget(newAttr.modificationTime, newAttr.fileSize, newAttr.targetFileId);
+ fileObj.syncTo<sideTrg>(descrTarget, &descrSource); //update FileMapping
}
catch (FileError&)
{
- if (fileExists(fileObj.getFullName<LEFT_SIDE>()))
+ if (fileExists(fileObj.getFullName<sideSrc>()))
throw;
//source deleted meanwhile...
- procCallback_.updateProcessedData(0, to<zen::Int64>(fileObj.getFileSize<LEFT_SIDE>()));
- fileObj.removeObject<LEFT_SIDE>();
+ procCallback_.updateProcessedData(0, to<zen::Int64>(fileObj.getFileSize<sideSrc>()));
+ fileObj.removeObject<sideSrc>();
}
- break;
+ }
+ break;
case SO_DELETE_LEFT:
- logText = replaceCpy(delHandlingLeft_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<LEFT_SIDE>()));
- procCallback_.reportInfo(logText);
+ case SO_DELETE_RIGHT:
+ reportInfo(getDelHandling<sideTrg>().getTxtRemovingFile(), fileObj.getFullName<sideTrg>());
- delHandlingLeft_.removeFile(fileObj.getObjRelativeName()); //throw FileError
- fileObj.removeObject<LEFT_SIDE>(); //update FileMapping
+ getDelHandling<sideTrg>().removeFile(fileObj.getObjRelativeName()); //throw FileError
+ fileObj.removeObject<sideTrg>(); //update FileMapping
break;
- case SO_DELETE_RIGHT:
- logText = replaceCpy(delHandlingRight_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<RIGHT_SIDE>()));
- procCallback_.reportInfo(logText);
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_RIGHT_TARGET:
+ if (FileMapping* targetObj = dynamic_cast<FileMapping*>(FileSystemObject::retrieve(fileObj.getMoveRef())))
+ {
+ FileMapping* sourceObj = &fileObj;
- delHandlingRight_.removeFile(fileObj.getObjRelativeName()); //throw FileError
- fileObj.removeObject<RIGHT_SIDE>(); //update FileMapping
- break;
+ if (syncOp != SO_MOVE_LEFT_SOURCE && syncOp != SO_MOVE_RIGHT_SOURCE)
+ std::swap(sourceObj, targetObj);
- case SO_OVERWRITE_LEFT:
- {
- target = fileObj.getBaseDirPf<LEFT_SIDE>() + fileObj.getRelativeName<RIGHT_SIDE>(); //respect differences in case of source object
+ assert((sourceObj->getSyncOperation() == SO_MOVE_LEFT_SOURCE && targetObj->getSyncOperation() == SO_MOVE_LEFT_TARGET && sideTrg == LEFT_SIDE) ||
+ (sourceObj->getSyncOperation() == SO_MOVE_RIGHT_SOURCE && targetObj->getSyncOperation() == SO_MOVE_RIGHT_TARGET && sideTrg == RIGHT_SIDE));
- logText = txtOverwritingFile;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ const Zstring& source = sourceObj->getFullName<sideTrg>();
+ const Zstring& target = targetObj->getBaseDirPf<sideTrg>() + targetObj->getRelativeName<sideSrc>();
- FileDescriptor sourceAttr;
- copyFileUpdatingTo<LEFT_SIDE>(fileObj,
- [&]() //delete target at appropriate time
- {
- procCallback_.reportStatus(replaceCpy(delHandlingLeft_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<LEFT_SIDE>())));
+ reportInfo(replaceCpy(txtMovingFile, L"%y", utf8CvrtTo<std::wstring>(target)), source);
- delHandlingLeft_.removeFile(fileObj.getObjRelativeName()); //throw FileError
- fileObj.removeObject<LEFT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
+ renameFile(source, target); //throw FileError;
- procCallback_.reportStatus(logText); //restore status text copy file
- }, sourceAttr);
+ const FileDescriptor descrTarget(sourceObj->getLastWriteTime<sideTrg>(),
+ sourceObj->getFileSize <sideTrg>(),
+ sourceObj->getFileId <sideTrg>());
- fileObj.copyTo<LEFT_SIDE>(&sourceAttr); //update FileMapping
- }
- break;
+ sourceObj->removeObject<sideTrg>(); //
+ targetObj->syncTo<sideTrg>(descrTarget); //update FileMapping
+ }
+ break;
+ case SO_OVERWRITE_LEFT:
case SO_OVERWRITE_RIGHT:
{
- target = fileObj.getBaseDirPf<RIGHT_SIDE>() + fileObj.getRelativeName<LEFT_SIDE>(); //respect differences in case of source object
+ const Zstring& target = fileObj.getBaseDirPf<sideTrg>() + fileObj.getRelativeName<sideSrc>(); //respect differences in case of source object
- logText = txtOverwritingFile;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ reportInfo(txtOverwritingFile, target);
- FileDescriptor sourceAttr;
- copyFileUpdatingTo<RIGHT_SIDE>(fileObj,
- [&]() //delete target at appropriate time
+ FileAttrib newAttr;
+ copyFileUpdatingTo<sideTrg>(fileObj,
+ [&] //delete target at appropriate time
{
- procCallback_.reportStatus(replaceCpy(delHandlingRight_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<RIGHT_SIDE>())));
+ reportStatus(this->getDelHandling<sideTrg>().getTxtRemovingFile(), fileObj.getFullName<sideTrg>());
- delHandlingRight_.removeFile(fileObj.getObjRelativeName()); //throw FileError
- fileObj.removeObject<RIGHT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
+ this->getDelHandling<sideTrg>().removeFile(fileObj.getObjRelativeName()); //throw FileError
+ fileObj.removeObject<sideTrg>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
- procCallback_.reportStatus(logText); //restore status text copy file
- }, sourceAttr);
+ reportStatus(txtOverwritingFile, target); //restore status text copy file
+ }, newAttr);
- fileObj.copyTo<RIGHT_SIDE>(&sourceAttr); //update FileMapping
+ const FileDescriptor descrSource(newAttr.modificationTime, newAttr.fileSize, newAttr.sourceFileId);
+ const FileDescriptor descrTarget(newAttr.modificationTime, newAttr.fileSize, newAttr.targetFileId);
+ fileObj.syncTo<sideTrg>(descrTarget, &descrSource); //update FileMapping
}
break;
case SO_COPY_METADATA_TO_LEFT:
- logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<LEFT_SIDE>()));
- procCallback_.reportInfo(logText);
-
- if (fileObj.getShortName<LEFT_SIDE>() != fileObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only)
- renameFile(fileObj.getFullName<LEFT_SIDE>(),
- beforeLast(fileObj.getFullName<LEFT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<RIGHT_SIDE>()); //throw FileError;
-
- if (!sameFileTime(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision
- setFileTime(fileObj.getFullName<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), SYMLINK_FOLLOW); //throw FileError
- //do NOT read *current* source file time, but use buffered value which corresponds to time of comparison!
-
- fileObj.copyTo<LEFT_SIDE>(NULL); //-> both sides *should* be completely equal now...
- break;
-
case SO_COPY_METADATA_TO_RIGHT:
- logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<RIGHT_SIDE>()));
- procCallback_.reportInfo(logText);
+ {
+ reportInfo(txtWritingAttributes, fileObj.getFullName<sideTrg>());
- if (fileObj.getShortName<LEFT_SIDE>() != fileObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only)
- renameFile(fileObj.getFullName<RIGHT_SIDE>(),
- beforeLast(fileObj.getFullName<RIGHT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<LEFT_SIDE>()); //throw FileError;
+ if (fileObj.getShortName<sideTrg>() != fileObj.getShortName<sideSrc>()) //adapt difference in case (windows only)
+ renameFile(fileObj.getFullName<sideTrg>(),
+ beforeLast(fileObj.getFullName<sideTrg>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<sideSrc>()); //throw FileError;
- if (!sameFileTime(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision
- setFileTime(fileObj.getFullName<RIGHT_SIDE>(), fileObj.getLastWriteTime<LEFT_SIDE>(), SYMLINK_FOLLOW); //throw FileError
+ if (!sameFileTime(fileObj.getLastWriteTime<sideTrg>(), fileObj.getLastWriteTime<sideSrc>(), 2)) //respect 2 second FAT/FAT32 precision
+ setFileTime(fileObj.getFullName<sideTrg>(), fileObj.getLastWriteTime<sideSrc>(), SYMLINK_FOLLOW); //throw FileError
+ //do NOT read *current* source file time, but use buffered value which corresponds to time of comparison!
- fileObj.copyTo<RIGHT_SIDE>(NULL); //-> both sides *should* be completely equal now...
- break;
+ const FileDescriptor descrTarget(fileObj.getLastWriteTime<sideSrc>(),
+ fileObj.getFileSize <sideTrg >(),
+ fileObj.getFileId <sideTrg >());
+ fileObj.syncTo<sideTrg>(descrTarget); //-> both sides *should* be completely equal now...
+ }
+ break;
case SO_DO_NOTHING:
case SO_EQUAL:
@@ -1049,137 +1416,112 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
}
+inline
void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const
{
- wxString logText;
- Zstring target;
+ const SyncOperation syncOp = linkObj.getSyncOperation();
- switch (linkObj.getSyncOperation()) //evaluate comparison result and sync direction
+ SelectedSide sideTrg = LEFT_SIDE;
+
+ if (getTargetDir(syncOp, &sideTrg))
{
- case SO_CREATE_NEW_LEFT:
- target = linkObj.getBaseDirPf<LEFT_SIDE>() + linkObj.getRelativeName<RIGHT_SIDE>();
+ if (sideTrg == LEFT_SIDE)
+ synchronizeLinkInt<LEFT_SIDE>(linkObj, syncOp);
+ else
+ synchronizeLinkInt<RIGHT_SIDE>(linkObj, syncOp);
+ }
+}
- logText = txtCreatingLink;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
- try
- {
- zen::copySymlink(linkObj.getFullName<RIGHT_SIDE>(), target, copyFilePermissions); //throw FileError
+template <SelectedSide sideTrg>
+void SynchronizeFolderPair::synchronizeLinkInt(SymLinkMapping& linkObj, SyncOperation syncOp) const
+{
+ static const SelectedSide sideSrc = OtherSide<sideTrg>::result;
- linkObj.copyTo<LEFT_SIDE>(); //update SymLinkMapping
- }
- catch (FileError&)
- {
- if (fileExists(linkObj.getFullName<RIGHT_SIDE>()))
- throw;
- //source deleted meanwhile...
- linkObj.removeObject<RIGHT_SIDE>();
- }
- break;
+ auto deleteSymlink = [&]
+ {
+ switch (linkObj.getLinkType<sideTrg>())
+ {
+ case LinkDescriptor::TYPE_DIR:
+ this->getDelHandling<sideTrg>().removeFolder(linkObj.getObjRelativeName()); //throw FileError
+ break;
+
+ case LinkDescriptor::TYPE_FILE: //Windows: true file symlink; Linux: file-link or broken link
+ this->getDelHandling<sideTrg>().removeFile(linkObj.getObjRelativeName()); //throw FileError
+ break;
+ }
+ };
+ switch (syncOp)
+ {
+ case SO_CREATE_NEW_LEFT:
case SO_CREATE_NEW_RIGHT:
- target = linkObj.getBaseDirPf<RIGHT_SIDE>() + linkObj.getRelativeName<LEFT_SIDE>();
+ {
+ const Zstring& target = linkObj.getBaseDirPf<sideTrg>() + linkObj.getRelativeName<sideSrc>();
- logText = txtCreatingLink;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ reportInfo(txtCreatingLink, target);
try
{
- zen::copySymlink(linkObj.getFullName<LEFT_SIDE>(), target, copyFilePermissions); //throw FileError
+ zen::copySymlink(linkObj.getFullName<sideSrc>(), target, copyFilePermissions); //throw FileError
- linkObj.copyTo<RIGHT_SIDE>(); //update SymLinkMapping
+ linkObj.copyTo<sideTrg>(); //update SymLinkMapping
}
catch (FileError&)
{
- if (fileExists(linkObj.getFullName<LEFT_SIDE>()))
+ if (fileExists(linkObj.getFullName<sideSrc>()))
throw;
//source deleted meanwhile...
- linkObj.removeObject<LEFT_SIDE>();
+ linkObj.removeObject<sideSrc>();
}
- break;
+ }
+ break;
case SO_DELETE_LEFT:
- logText = replaceCpy(delHandlingLeft_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<LEFT_SIDE>()));
- procCallback_.reportInfo(logText);
-
- deleteSymlink<LEFT_SIDE>(linkObj); //throw FileError
-
- linkObj.removeObject<LEFT_SIDE>(); //update SymLinkMapping
- break;
-
case SO_DELETE_RIGHT:
- logText = replaceCpy(delHandlingRight_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<RIGHT_SIDE>()));
- procCallback_.reportInfo(logText);
+ reportInfo(getDelHandling<sideTrg>().getTxtRemovingSymLink(), linkObj.getFullName<sideTrg>());
- deleteSymlink<RIGHT_SIDE>(linkObj); //throw FileError
+ deleteSymlink(); //throw FileError
- linkObj.removeObject<RIGHT_SIDE>(); //update SymLinkMapping
+ linkObj.removeObject<sideTrg>(); //update SymLinkMapping
break;
case SO_OVERWRITE_LEFT:
- target = linkObj.getBaseDirPf<LEFT_SIDE>() + linkObj.getRelativeName<RIGHT_SIDE>(); //respect differences in case of source object
-
- logText = txtOverwritingLink;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
-
- procCallback_.reportStatus(replaceCpy(delHandlingLeft_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<LEFT_SIDE>())));
- deleteSymlink<LEFT_SIDE>(linkObj); //throw FileError
- linkObj.removeObject<LEFT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
-
- procCallback_.reportStatus(logText); //restore status text
- zen::copySymlink(linkObj.getFullName<RIGHT_SIDE>(), target, copyFilePermissions); //throw FileError
-
- linkObj.copyTo<LEFT_SIDE>(); //update SymLinkMapping
- break;
-
case SO_OVERWRITE_RIGHT:
- target = linkObj.getBaseDirPf<RIGHT_SIDE>() + linkObj.getRelativeName<LEFT_SIDE>(); //respect differences in case of source object
-
- logText = txtOverwritingLink;
- replace(logText, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ {
+ const Zstring& target = linkObj.getBaseDirPf<sideTrg>() + linkObj.getRelativeName<sideSrc>(); //respect differences in case of source object
- procCallback_.reportStatus(replaceCpy(delHandlingRight_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<RIGHT_SIDE>())));
- deleteSymlink<RIGHT_SIDE>(linkObj); //throw FileError
- linkObj.removeObject<RIGHT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
+ reportInfo(txtOverwritingLink, target);
- procCallback_.reportStatus(logText); //restore status text
- zen::copySymlink(linkObj.getFullName<LEFT_SIDE>(), target, copyFilePermissions); //throw FileError
+ reportStatus(getDelHandling<sideTrg>().getTxtRemovingSymLink(), linkObj.getFullName<sideTrg>());
+ deleteSymlink(); //throw FileError
+ linkObj.removeObject<sideTrg>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
- linkObj.copyTo<RIGHT_SIDE>(); //update SymLinkMapping
- break;
+ reportStatus(txtOverwritingLink, target); //restore status text
+ zen::copySymlink(linkObj.getFullName<sideSrc>(), target, copyFilePermissions); //throw FileError
+ linkObj.copyTo<sideTrg>(); //update SymLinkMapping
+ }
+ break;
case SO_COPY_METADATA_TO_LEFT:
- logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<LEFT_SIDE>()));
- procCallback_.reportInfo(logText);
-
- if (linkObj.getShortName<LEFT_SIDE>() != linkObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only)
- renameFile(linkObj.getFullName<LEFT_SIDE>(),
- beforeLast(linkObj.getFullName<LEFT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<RIGHT_SIDE>()); //throw FileError;
-
- if (!sameFileTime(linkObj.getLastWriteTime<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision
- setFileTime(linkObj.getFullName<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), SYMLINK_DIRECT); //throw FileError
-
- linkObj.copyTo<LEFT_SIDE>(); //-> both sides *should* be completely equal now...
- break;
-
case SO_COPY_METADATA_TO_RIGHT:
- logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<RIGHT_SIDE>()));
- procCallback_.reportInfo(logText);
+ reportInfo(txtWritingAttributes, linkObj.getFullName<sideTrg>());
- if (linkObj.getShortName<LEFT_SIDE>() != linkObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only)
- renameFile(linkObj.getFullName<RIGHT_SIDE>(),
- beforeLast(linkObj.getFullName<RIGHT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<LEFT_SIDE>()); //throw FileError;
+ if (linkObj.getShortName<sideTrg>() != linkObj.getShortName<sideSrc>()) //adapt difference in case (windows only)
+ renameFile(linkObj.getFullName<sideTrg>(),
+ beforeLast(linkObj.getFullName<sideTrg>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<sideSrc>()); //throw FileError;
- if (!sameFileTime(linkObj.getLastWriteTime<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision
- setFileTime(linkObj.getFullName<RIGHT_SIDE>(), linkObj.getLastWriteTime<LEFT_SIDE>(), SYMLINK_DIRECT); //throw FileError
+ if (!sameFileTime(linkObj.getLastWriteTime<sideTrg>(), linkObj.getLastWriteTime<sideSrc>(), 2)) //respect 2 second FAT/FAT32 precision
+ setFileTime(linkObj.getFullName<sideTrg>(), linkObj.getLastWriteTime<sideSrc>(), SYMLINK_DIRECT); //throw FileError
- linkObj.copyTo<RIGHT_SIDE>(); //-> both sides *should* be completely equal now...
+ linkObj.copyTo<sideTrg>(); //-> both sides *should* be completely equal now...
break;
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
+ assert(false);
case SO_DO_NOTHING:
case SO_EQUAL:
case SO_UNRESOLVED_CONFLICT:
@@ -1193,126 +1535,89 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const
}
+inline
void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const
{
- wxString logText;
- Zstring target;
+ const SyncOperation syncOp = dirObj.getSyncOperation();
- //synchronize folders:
- switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction
- {
- case SO_CREATE_NEW_LEFT:
- //some check to catch the error that directory on source has been deleted externally after "compare"...
- if (!dirExists(dirObj.getFullName<RIGHT_SIDE>()))
- {
- // throw FileError(_ ("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<RIGHT_SIDE>() + "\"");
- const SyncStatistics subObjects(dirObj); //DON'T forget to notify about implicitly deleted objects!
- procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess()));
+ SelectedSide sideTrg = LEFT_SIDE;
- dirObj.refSubFiles().clear(); //...then remove sub-objects
- dirObj.refSubLinks().clear(); //
- dirObj.refSubDirs ().clear(); //
- dirObj.removeObject<RIGHT_SIDE>();
- }
- else
- {
- target = dirObj.getBaseDirPf<LEFT_SIDE>() + dirObj.getRelativeName<RIGHT_SIDE>();
+ if (getTargetDir(syncOp, &sideTrg))
+ {
+ if (sideTrg == LEFT_SIDE)
+ synchronizeFolderInt<LEFT_SIDE>(dirObj, syncOp);
+ else
+ synchronizeFolderInt<RIGHT_SIDE>(dirObj, syncOp);
+ }
+}
- logText = replaceCpy(txtCreatingFolder, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
- createDirectory(target, dirObj.getFullName<RIGHT_SIDE>(), copyFilePermissions); //no symlink copying!
- dirObj.copyTo<LEFT_SIDE>(); //update DirMapping
- }
- break;
+template <SelectedSide sideTrg>
+void SynchronizeFolderPair::synchronizeFolderInt(DirMapping& dirObj, SyncOperation syncOp) const
+{
+ static const SelectedSide sideSrc = OtherSide<sideTrg>::result;
+ switch (syncOp)
+ {
+ case SO_CREATE_NEW_LEFT:
case SO_CREATE_NEW_RIGHT:
- //some check to catch the error that directory on source has been deleted externally after "compare"...
- if (!dirExists(dirObj.getFullName<LEFT_SIDE>()))
+ if (dirExists(dirObj.getFullName<sideSrc>()))
{
- //throw FileError(_ ("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<LEFT_SIDE>() + "\"");
- const SyncStatistics subObjects(dirObj); //DON'T forget to notify about implicitly deleted objects!
- procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess()));
+ const Zstring& target = dirObj.getBaseDirPf<sideTrg>() + dirObj.getRelativeName<sideSrc>();
- dirObj.refSubFiles().clear(); //...then remove sub-objects
- dirObj.refSubLinks().clear(); //
- dirObj.refSubDirs ().clear(); //
- dirObj.removeObject<LEFT_SIDE>();
+ reportInfo(txtCreatingFolder, target);
+ createDirectory(target, dirObj.getFullName<sideSrc>(), copyFilePermissions); //no symlink copying!
+ dirObj.copyTo<sideTrg>(); //update DirMapping
}
- else
+ else //source directory has been deleted externally after "compare"...
{
- target = dirObj.getBaseDirPf<RIGHT_SIDE>() + dirObj.getRelativeName<LEFT_SIDE>();
-
- logText = replaceCpy(txtCreatingFolder, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ // throw FileError(_ ("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<sideSrc>() + "\"");
+ const SyncStatistics subStats(dirObj); //DON'T forget to notify about implicitly deleted objects!
+ procCallback_.updateProcessedData(getCUD(subStats), to<zen::Int64>(subStats.getDataToProcess()));
- createDirectory(target, dirObj.getFullName<LEFT_SIDE>(), copyFilePermissions); //no symlink copying!
- dirObj.copyTo<RIGHT_SIDE>(); //update DirMapping
+ dirObj.refSubFiles().clear(); //...then remove sub-objects
+ dirObj.refSubLinks().clear(); //
+ dirObj.refSubDirs ().clear(); //
+ dirObj.removeObject<sideSrc>();
}
break;
case SO_COPY_METADATA_TO_LEFT:
- logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<LEFT_SIDE>()));
- procCallback_.reportInfo(logText);
-
- if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only)
- renameFile(dirObj.getFullName<LEFT_SIDE>(),
- beforeLast(dirObj.getFullName<LEFT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<RIGHT_SIDE>()); //throw FileError;
- //copyFileTimes(dirObj.getFullName<RIGHT_SIDE>(), dirObj.getFullName<LEFT_SIDE>(), true); //throw FileError -> is executed after sub-objects have finished synchronization
-
- dirObj.copyTo<LEFT_SIDE>(); //-> both sides *should* be completely equal now...
- break;
-
case SO_COPY_METADATA_TO_RIGHT:
- logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<RIGHT_SIDE>()));
- procCallback_.reportInfo(logText);
+ reportInfo(txtWritingAttributes, dirObj.getFullName<sideTrg>());
- if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only)
- renameFile(dirObj.getFullName<RIGHT_SIDE>(),
- beforeLast(dirObj.getFullName<RIGHT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<LEFT_SIDE>()); //throw FileError;
- //copyFileTimes(dirObj.getFullName<LEFT_SIDE>(), dirObj.getFullName<RIGHT_SIDE>(), true); //throw FileError -> is executed after sub-objects have finished synchronization
+ if (dirObj.getShortName<sideTrg>() != dirObj.getShortName<sideSrc>()) //adapt difference in case (windows only)
+ renameFile(dirObj.getFullName<sideTrg>(),
+ beforeLast(dirObj.getFullName<sideTrg>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<sideSrc>()); //throw FileError;
+ //copyFileTimes -> useless at this time: modification time changes with each child-object creation/deletion
- dirObj.copyTo<RIGHT_SIDE>(); //-> both sides *should* be completely equal now...
+ dirObj.copyTo<sideTrg>(); //-> both sides *should* be completely equal now...
break;
case SO_DELETE_LEFT:
- //status information
- logText = replaceCpy(delHandlingLeft_.getTxtRemovingDir(), L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<LEFT_SIDE>()));
- procCallback_.reportInfo(logText);
+ case SO_DELETE_RIGHT:
+ {
+ reportInfo(getDelHandling<sideTrg>().getTxtRemovingDir(), dirObj.getFullName<sideTrg>());
- delHandlingLeft_.removeFolder(dirObj.getObjRelativeName()); //throw FileError
- {
- //progress indicator update: DON'T forget to notify about implicitly deleted objects!
- const SyncStatistics subObjects(dirObj);
- //...then remove everything
- dirObj.refSubFiles().clear();
- dirObj.refSubLinks().clear();
- dirObj.refSubDirs ().clear();
- procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess()));
- }
- dirObj.removeObject<LEFT_SIDE>(); //update DirMapping
- break;
+ getDelHandling<sideTrg>().removeFolder(dirObj.getObjRelativeName()); //throw FileError
- case SO_DELETE_RIGHT:
- //status information
- logText = replaceCpy(delHandlingRight_.getTxtRemovingDir(), L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<RIGHT_SIDE>()));
- procCallback_.reportInfo(logText);
+ //progress indicator update: DON'T forget to notify about implicitly deleted objects!
+ const SyncStatistics subStats(dirObj);
+ dirObj.refSubFiles().clear(); //...then remove everything
+ dirObj.refSubLinks().clear();
+ dirObj.refSubDirs ().clear();
+ procCallback_.updateProcessedData(getCUD(subStats), to<zen::Int64>(subStats.getDataToProcess()));
- delHandlingRight_.removeFolder(dirObj.getObjRelativeName()); //throw FileError
- {
- //progress indicator update: DON'T forget to notify about implicitly deleted objects!
- const SyncStatistics subObjects(dirObj);
- //...then remove everything
- dirObj.refSubFiles().clear();
- dirObj.refSubLinks().clear();
- dirObj.refSubDirs ().clear();
- procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess()));
- }
- dirObj.removeObject<RIGHT_SIDE>(); //update DirMapping
- break;
+ dirObj.removeObject<sideTrg>(); //update DirMapping
+ }
+ break;
case SO_OVERWRITE_RIGHT:
case SO_OVERWRITE_LEFT:
+ case SO_MOVE_LEFT_SOURCE:
+ case SO_MOVE_RIGHT_SOURCE:
+ case SO_MOVE_LEFT_TARGET:
+ case SO_MOVE_RIGHT_TARGET:
assert(false);
case SO_UNRESOLVED_CONFLICT:
case SO_DO_NOTHING:
@@ -1336,31 +1641,27 @@ void makeSameLength(std::wstring& first, std::wstring& second)
second.resize(maxPref, L' ');
}
+
+/*
struct LessDependentDirectory : public std::binary_function<Zstring, Zstring, bool>
{
+-> a *very* bad idea: this is NOT a strict weak ordering! No transitivity of equivalence!
+
bool operator()(const Zstring& lhs, const Zstring& rhs) const
{
return LessFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())),
Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length())));
}
};
-
-struct EqualDependentDirectory : public std::binary_function<Zstring, Zstring, bool>
-{
- bool operator()(const Zstring& lhs, const Zstring& rhs) const
- {
- return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())),
- Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length())));
- }
-};
+*/
}
void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCfg>& syncConfig, FolderComparison& folderCmp)
{
- //prevent shutdown while synchronization is in progress
- DisableStandby dummy;
- (void)dummy;
+ //prevent shutdown while synchronization is in progress
+ PreventStandby dummy;
+ (void)dummy;
#ifdef NDEBUG
wxLogNull noWxLogs; //prevent wxWidgets logging
@@ -1371,12 +1672,11 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
if (syncConfig.size() != folderCmp.size())
throw std::logic_error("Programming Error: Contract violation!");
-
//inform about the total amount of data that will be processed from now on
const SyncStatistics statisticsTotal(folderCmp);
//keep at beginning so that all gui elements are initialized properly
- procCallback.initNewProcess(statisticsTotal.getCreate() + statisticsTotal.getOverwrite() + statisticsTotal.getDelete(),
+ procCallback.initNewProcess(getCUD(statisticsTotal),
to<zen::Int64>(statisticsTotal.getDataToProcess()),
ProcessCallback::PROCESS_SYNCHRONIZING);
@@ -1404,12 +1704,34 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
//-------------------some basic checks:------------------------------------------
+ auto dependentDir = [](const Zstring& lhs, const Zstring& rhs) //note: this is NOT an equivalence relation!
+ {
+ return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())),
+ Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length())));
+ };
//aggregate information
- typedef std::set<Zstring, LessDependentDirectory> DirReadSet; //count (at least one) read access
- typedef std::map<Zstring, size_t, LessDependentDirectory> DirWriteMap; //count (read+)write accesses
- DirReadSet dirReadCount;
- DirWriteMap dirWriteCount;
+ std::map<Zstring, std::pair<size_t, size_t>> dirReadWriteCount; //count read/write accesses
+ auto incReadCount = [&](const Zstring& baseDir)
+ {
+ dirReadWriteCount[baseDir]; //create entry
+ for (auto iter = dirReadWriteCount.begin(); iter != dirReadWriteCount.end(); ++iter)
+ {
+ auto& countRef = iter->second;
+ if (dependentDir(baseDir, iter->first))
+ ++countRef.first;
+ }
+ };
+ auto incWriteCount = [&](const Zstring& baseDir)
+ {
+ dirReadWriteCount[baseDir]; //create entry
+ for (auto iter = dirReadWriteCount.begin(); iter != dirReadWriteCount.end(); ++iter)
+ {
+ auto& countRef = iter->second;
+ if (dependentDir(baseDir, iter->first))
+ ++countRef.second;
+ }
+ };
typedef std::vector<std::pair<Zstring, Zstring> > DirPairList;
DirPairList significantDiff;
@@ -1417,8 +1739,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
typedef std::vector<std::pair<Zstring, std::pair<zen::Int64, zen::Int64> > > DirSpaceRequAvailList; //dirname / space required / space available
DirSpaceRequAvailList diskSpaceMissing;
- typedef std::set<Zstring, LessDependentDirectory> DirRecyclerMissing;
- DirRecyclerMissing recyclMissing;
+ std::set<Zstring> recyclMissing;
//start checking folder pairs
for (auto j = begin(folderCmp); j != end(folderCmp); ++j)
@@ -1435,13 +1756,13 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
const SyncStatistics folderPairStat(*j);
//aggregate basic information
- const bool writeLeft = folderPairStat.getCreate <LEFT_SIDE>() +
- folderPairStat.getOverwrite<LEFT_SIDE>() +
- folderPairStat.getDelete <LEFT_SIDE>() > 0;
+ const bool writeLeft = folderPairStat.getCreate<LEFT_SIDE>() +
+ folderPairStat.getUpdate<LEFT_SIDE>() +
+ folderPairStat.getDelete<LEFT_SIDE>() > 0;
- const bool writeRight = folderPairStat.getCreate <RIGHT_SIDE>() +
- folderPairStat.getOverwrite<RIGHT_SIDE>() +
- folderPairStat.getDelete <RIGHT_SIDE>() > 0;
+ const bool writeRight = folderPairStat.getCreate<RIGHT_SIDE>() +
+ folderPairStat.getUpdate<RIGHT_SIDE>() +
+ folderPairStat.getDelete<RIGHT_SIDE>() > 0;
//skip folder pair if there is nothing to do (except for automatic mode, where data base needs to be written even in this case)
if (!writeLeft && !writeRight &&
@@ -1453,7 +1774,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
//check empty input fields: basically this only makes sense if empty field is not target (and not automatic mode: because of db file creation)
- if ((j->getBaseDirPf<LEFT_SIDE>(). empty() && (writeLeft || folderPairCfg.inAutomaticMode)) ||
+ if ((j->getBaseDirPf<LEFT_SIDE >().empty() && (writeLeft || folderPairCfg.inAutomaticMode)) ||
(j->getBaseDirPf<RIGHT_SIDE>().empty() && (writeRight || folderPairCfg.inAutomaticMode)))
{
procCallback.reportFatalError(_("Target directory name must not be empty!"));
@@ -1462,30 +1783,32 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
}
//aggregate information of folders used by multiple pairs in read/write access
- if (!EqualDependentDirectory()(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())) //true in general
+ if (!dependentDir(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())) //true in general
{
- if (writeLeft)
+ if (writeLeft && writeRight)
+ {
+ incWriteCount(j->getBaseDirPf<LEFT_SIDE >());
+ incWriteCount(j->getBaseDirPf<RIGHT_SIDE>());
+ }
+ else if (writeLeft)
{
- ++dirWriteCount[j->getBaseDirPf<LEFT_SIDE>()];
- if (writeRight)
- ++dirWriteCount[j->getBaseDirPf<RIGHT_SIDE>()];
- else
- dirReadCount.insert(j->getBaseDirPf<RIGHT_SIDE>());
+ incWriteCount(j->getBaseDirPf<LEFT_SIDE>());
+ incReadCount (j->getBaseDirPf<RIGHT_SIDE>());
}
else if (writeRight)
{
- dirReadCount.insert(j->getBaseDirPf<LEFT_SIDE>());
- ++dirWriteCount[j->getBaseDirPf<RIGHT_SIDE>()];
+ incReadCount (j->getBaseDirPf<LEFT_SIDE>());
+ incWriteCount(j->getBaseDirPf<RIGHT_SIDE>());
}
}
else //if folder pair contains two dependent folders, a warning was already issued after comparison; in this context treat as one write access at most
{
if (writeLeft || writeRight)
- ++dirWriteCount[j->getBaseDirPf<LEFT_SIDE>()];
+ incWriteCount(j->getBaseDirPf<LEFT_SIDE>());
}
- if (folderPairStat.getOverwrite() + folderPairStat.getDelete() > 0)
+ if (folderPairStat.getUpdate() + folderPairStat.getDelete() > 0)
{
if (folderPairCfg.handleDeletion == zen::MOVE_TO_CUSTOM_DIRECTORY)
{
@@ -1500,7 +1823,9 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
}
//avoid data loss when source directory doesn't (temporarily?) exist anymore AND user chose to ignore errors (else we wouldn't arrive here)
- if (folderPairStat.getCreate() + folderPairStat.getOverwrite() + folderPairStat.getConflict() == 0 &&
+ if (folderPairStat.getCreate() +
+ folderPairStat.getUpdate() +
+ folderPairStat.getConflict() == 0 &&
folderPairStat.getDelete() > 0) //deletions only... (respect filtered items!)
{
Zstring missingSrcDir;
@@ -1522,9 +1847,8 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
significantDiff.push_back(std::make_pair(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>()));
//check for sufficient free diskspace in left directory
- const std::pair<zen::Int64, zen::Int64> spaceNeeded = DiskSpaceNeeded(*j,
- delHandlerFp.first.deletionFreesSpace(),
- delHandlerFp.second.deletionFreesSpace()).getSpaceTotal();
+ const std::pair<Int64, Int64> spaceNeeded = DiskSpaceNeeded::calculate(*j, delHandlerFp.first.deletionFreesSpace(),
+ delHandlerFp.second.deletionFreesSpace());
wxLongLong freeDiskSpaceLeft;
if (wxGetDiskSpace(toWx(j->getBaseDirPf<LEFT_SIDE>()), NULL, &freeDiskSpaceLeft))
{
@@ -1546,14 +1870,14 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
#ifdef FFS_WIN
if (folderPairCfg.handleDeletion == MOVE_TO_RECYCLE_BIN)
{
- if (folderPairStat.getOverwrite<LEFT_SIDE>() +
- folderPairStat.getDelete <LEFT_SIDE>() > 0 &&
+ if (folderPairStat.getUpdate<LEFT_SIDE>() +
+ folderPairStat.getDelete<LEFT_SIDE>() > 0 &&
recycleBinStatus(j->getBaseDirPf<LEFT_SIDE>()) != STATUS_REC_EXISTS)
recyclMissing.insert(j->getBaseDirPf<LEFT_SIDE>());
- if (folderPairStat.getOverwrite<RIGHT_SIDE>() +
- folderPairStat.getDelete <RIGHT_SIDE>() > 0 &&
+ if (folderPairStat.getUpdate<RIGHT_SIDE>() +
+ folderPairStat.getDelete<RIGHT_SIDE>() > 0 &&
recycleBinStatus(j->getBaseDirPf<RIGHT_SIDE>()) != STATUS_REC_EXISTS)
recyclMissing.insert(j->getBaseDirPf<RIGHT_SIDE>());
@@ -1565,20 +1889,20 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
if (statisticsTotal.getConflict() > 0)
{
//show the first few conflicts in warning message also:
- wxString warningMessage = wxString(_("Unresolved conflicts existing!")) +
- wxT(" (") + toStringSep(statisticsTotal.getConflict()) + wxT(")\n\n");
+ std::wstring warningMessage = _("Unresolved conflicts existing!") +
+ L" (" + toStringSep(statisticsTotal.getConflict()) + L")\n\n";
const SyncStatistics::ConflictTexts& firstConflicts = statisticsTotal.getFirstConflicts(); //get first few sync conflicts
for (SyncStatistics::ConflictTexts::const_iterator i = firstConflicts.begin(); i != firstConflicts.end(); ++i)
{
- wxString conflictDescription = i->second;
+ std::wstring conflictDescription = i->second;
//conflictDescription.Replace(wxT("\n"), wxT(" ")); //remove line-breaks
warningMessage += std::wstring(L"\"") + i->first + L"\": " + conflictDescription + L"\n\n";
}
if (statisticsTotal.getConflict() > static_cast<int>(firstConflicts.size()))
- warningMessage += wxT("[...]\n\n");
+ warningMessage += L"[...]\n\n";
warningMessage += _("You can ignore conflicts and continue synchronization.");
@@ -1589,13 +1913,14 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
//check if more than 50% of total number of files/dirs are to be created/overwritten/deleted
if (!significantDiff.empty())
{
- wxString warningMessage = _("Significant difference detected:");
+ std::wstring warningMessage = _("Significant difference detected:");
for (DirPairList::const_iterator i = significantDiff.begin(); i != significantDiff.end(); ++i)
warningMessage += std::wstring(L"\n\n") +
i->first + L" <-> " + L"\n" +
i->second;
- warningMessage += wxString(L"\n\n") + _("More than 50% of the total number of files will be copied or deleted!");
+ warningMessage += L"\n\n";
+ warningMessage += _("More than 50% of the total number of files will be copied or deleted!");
procCallback.reportWarning(warningMessage, m_warnings.warningSignificantDifference);
}
@@ -1604,13 +1929,13 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
//check for sufficient free diskspace
if (!diskSpaceMissing.empty())
{
- wxString warningMessage = _("Not enough free disk space available in:");
+ std::wstring warningMessage = _("Not enough free disk space available in:");
for (auto i = diskSpaceMissing.begin(); i != diskSpaceMissing.end(); ++i)
warningMessage += std::wstring(L"\n\n") +
L"\"" + i->first + L"\"\n" +
- _("Free disk space required:") + wxT(" ") + filesizeToShortString(to<UInt64>(i->second.first)) + L"\n" +
- _("Free disk space available:") + wxT(" ") + filesizeToShortString(to<UInt64>(i->second.second));
+ _("Free disk space required:") + L" " + filesizeToShortString(to<UInt64>(i->second.first)) + L"\n" +
+ _("Free disk space available:") + L" " + filesizeToShortString(to<UInt64>(i->second.second));
procCallback.reportWarning(warningMessage, m_warnings.warningNotEnoughDiskSpace);
}
@@ -1620,11 +1945,11 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
#ifdef FFS_WIN
if (!recyclMissing.empty())
{
- wxString warningMessage = _("Recycle Bin is not available for the following paths! Files will be deleted permanently instead:");
+ std::wstring warningMessage = _("Recycle Bin is not available for the following paths! Files will be deleted permanently instead:");
warningMessage += L"\n";
std::for_each(recyclMissing.begin(), recyclMissing.end(),
- [&](const Zstring& path) { warningMessage += L"\n" + toWx(path); });
+ [&](const Zstring& path) { warningMessage += L"\n" + utf8CvrtTo<std::wstring>(path); });
procCallback.reportWarning(warningMessage, m_warnings.warningRecyclerMissing);
}
@@ -1632,15 +1957,18 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
//check if folders are used by multiple pairs in read/write access
std::vector<Zstring> conflictDirs;
- for (DirWriteMap::const_iterator i = dirWriteCount.begin(); i != dirWriteCount.end(); ++i)
- if (i->second >= 2 || //multiple write accesses
- (i->second == 1 && dirReadCount.find(i->first) != dirReadCount.end())) //read/write access
- conflictDirs.push_back(i->first);
+ for (auto iter = dirReadWriteCount.cbegin(); iter != dirReadWriteCount.cend(); ++iter)
+ {
+ const auto& countRef = iter->second;
+ if (countRef.second >= 2 || //multiple write accesses
+ (countRef.second == 1 && countRef.first >= 1)) //read/write access
+ conflictDirs.push_back(iter->first);
+ }
if (!conflictDirs.empty())
{
- wxString warningMessage = wxString(_("A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!")) + wxT("\n");
- for (std::vector<Zstring>::const_iterator i = conflictDirs.begin(); i != conflictDirs.end(); ++i)
+ std::wstring warningMessage = _("A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!") + L"\n";
+ for (auto i = conflictDirs.begin(); i != conflictDirs.end(); ++i)
warningMessage += std::wstring(L"\n") +
L"\"" + *i + L"\"";
procCallback.reportWarning(warningMessage, m_warnings.warningMultiFolderWriteAccess);
@@ -1677,8 +2005,8 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
makeSameLength(left, right);
const std::wstring statusTxt = _("Processing folder pair:") + L" \n" +
- L"\t" + left + L"\"" + j->getBaseDirPf<LEFT_SIDE>() + L"\"" + L" \n" +
- L"\t" + right + L"\"" + j->getBaseDirPf<RIGHT_SIDE>() + L"\"";
+ L" " + left + L"\"" + j->getBaseDirPf<LEFT_SIDE>() + L"\"" + L" \n" +
+ L" " + right + L"\"" + j->getBaseDirPf<RIGHT_SIDE>() + L"\"";
procCallback.reportInfo(statusTxt);
//------------------------------------------------------------------------------------------
@@ -1725,7 +2053,6 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
if (folderPairCfg.inAutomaticMode)
{
procCallback.reportStatus(_("Generating database..."));
- procCallback.forceUiRefresh();
tryReportingError(procCallback, [&]() { zen::saveToDisk(*j); }); //throw FileError
guardUpdateDb.dismiss();
@@ -1737,7 +2064,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
}
catch (const std::exception& e)
{
- procCallback.reportFatalError(wxString::FromUTF8(e.what()));
+ procCallback.reportFatalError(utf8CvrtTo<std::wstring>(e.what()));
}
}
@@ -1768,7 +2095,7 @@ public:
}
private:
- UInt64& bytesReported_;
+ UInt64& bytesReported_;
ProcessCallback& statusHandler_;
DelTargetCommand cmd_;
};
@@ -1776,13 +2103,13 @@ private:
//copy file while refreshing UI
template <SelectedSide side, class DelTargetCommand>
-void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileDescriptor& sourceAttr) const
+void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileAttrib& newAttr) const
{
const UInt64 totalBytesToCpy = fileObj.getFileSize<OtherSide<side>::result>();
Zstring source = fileObj.getFullName<OtherSide<side>::result>();
const Zstring& target = fileObj.getBaseDirPf<side>() + fileObj.getRelativeName<OtherSide<side>::result>();
- auto copyOperation = [&]()
+ auto copyOperation = [&]
{
//start of (possibly) long-running copy process: ensure status updates are performed regularly
UInt64 bytesReported;
@@ -1790,16 +2117,13 @@ void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const
zen::ScopeGuard guardStatistics = zen::makeGuard([&]() { procCallback_.updateProcessedData(0, -1 * to<Int64>(bytesReported)); });
WhileCopying<DelTargetCommand> callback(bytesReported, procCallback_, cmd);
- FileAttrib fileAttr;
zen::copyFile(source, //type File implicitly means symlinks need to be dereferenced!
- target,
- copyFilePermissions,
- transactionalFileCopy,
- &callback,
- &fileAttr); //throw FileError, ErrorFileLocked
-
- sourceAttr = FileDescriptor(fileAttr.modificationTime, fileAttr.fileSize);
+ target,
+ copyFilePermissions,
+ transactionalFileCopy,
+ &callback,
+ &newAttr); //throw FileError, ErrorFileLocked
//inform about the (remaining) processed amount of data
procCallback_.updateProcessedData(0, to<Int64>(totalBytesToCpy) - to<Int64>(bytesReported));
@@ -1851,24 +2175,6 @@ void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const
}
-template <zen::SelectedSide side>
-void SynchronizeFolderPair::deleteSymlink(const SymLinkMapping& linkObj) const
-{
- const DeletionHandling& delHandling = side == LEFT_SIDE ? delHandlingLeft_ : delHandlingRight_;
-
- switch (linkObj.getLinkType<side>())
- {
- case LinkDescriptor::TYPE_DIR:
- delHandling.removeFolder(linkObj.getObjRelativeName()); //throw FileError
- break;
-
- case LinkDescriptor::TYPE_FILE: //Windows: true file symlink; Linux: file-link or broken link
- delHandling.removeFile(linkObj.getObjRelativeName()); //throw FileError
- break;
- }
-}
-
-
//--------------------- data verification -------------------------
//callback functionality for status updates while verifying
@@ -1936,8 +2242,7 @@ private:
void SynchronizeFolderPair::verifyFileCopy(const Zstring& source, const Zstring& target) const
{
- wxString logText = replaceCpy(txtVerifying, L"%x", utf8CvrtTo<wxString>(target));
- procCallback_.reportInfo(logText);
+ procCallback_.reportInfo(replaceCpy(txtVerifying, L"%x", utf8CvrtTo<std::wstring>(target)));
VerifyStatusUpdater callback(procCallback_);
diff --git a/synchronization.h b/synchronization.h
index 4e11d5a9..6cf32de5 100644
--- a/synchronization.h
+++ b/synchronization.h
@@ -21,19 +21,20 @@ class SyncStatistics
public:
SyncStatistics(const HierarchyObject& hierObj);
SyncStatistics(const FolderComparison& folderCmp);
+ SyncStatistics(const FileMapping& fileObj);
int getCreate() const;
template <SelectedSide side> int getCreate() const;
- int getOverwrite() const;
- template <SelectedSide side> int getOverwrite() const;
+ int getUpdate() const;
+ template <SelectedSide side> int getUpdate() const;
int getDelete() const;
template <SelectedSide side> int getDelete() const;
int getConflict() const { return conflict; }
- typedef std::vector<std::pair<Zstring, wxString> > ConflictTexts; // Pair(filename/conflict text)
+ typedef std::vector<std::pair<Zstring, std::wstring> > ConflictTexts; // Pair(filename/conflict text)
const ConflictTexts& getFirstConflicts() const { return firstConflicts; }
zen::UInt64 getDataToProcess() const { return dataToProcess; }
@@ -42,15 +43,15 @@ public:
private:
void init();
- void getNumbersRecursively(const HierarchyObject& hierObj);
+ void recurse(const HierarchyObject& hierObj);
void getFileNumbers(const FileMapping& fileObj);
void getLinkNumbers(const SymLinkMapping& linkObj);
void getDirNumbers(const DirMapping& dirObj);
- int createLeft, createRight;
- int overwriteLeft, overwriteRight;
- int deleteLeft, deleteRight;
+ int createLeft, createRight;
+ int updateLeft, updateRight;
+ int deleteLeft, deleteRight;
int conflict;
ConflictTexts firstConflicts; //save the first few conflict texts to display as a warning message
zen::UInt64 dataToProcess;
@@ -103,7 +104,7 @@ private:
xmlAccess::OptionalDialogs& m_warnings;
ProcessCallback& procCallback;
-std::unique_ptr<ScheduleForBackgroundProcessing> procBackground;
+ std::unique_ptr<ScheduleForBackgroundProcessing> procBackground;
};
@@ -131,16 +132,14 @@ std::unique_ptr<ScheduleForBackgroundProcessing> procBackground;
-// inline implementation
-template <>
-inline
+// ----------- implementation ----------------
+template <> inline
int SyncStatistics::getCreate<LEFT_SIDE>() const
{
return createLeft;
}
-template <>
-inline
+template <> inline
int SyncStatistics::getCreate<RIGHT_SIDE>() const
{
return createRight;
@@ -152,36 +151,32 @@ int SyncStatistics::getCreate() const
return getCreate<LEFT_SIDE>() + getCreate<RIGHT_SIDE>();
}
-template <>
-inline
-int SyncStatistics::getOverwrite<LEFT_SIDE>() const
+template <> inline
+int SyncStatistics::getUpdate<LEFT_SIDE>() const
{
- return overwriteLeft;
+ return updateLeft;
}
-template <>
-inline
-int SyncStatistics::getOverwrite<RIGHT_SIDE>() const
+template <> inline
+int SyncStatistics::getUpdate<RIGHT_SIDE>() const
{
- return overwriteRight;
+ return updateRight;
}
inline
-int SyncStatistics::getOverwrite() const
+int SyncStatistics::getUpdate() const
{
- return getOverwrite<LEFT_SIDE>() + getOverwrite<RIGHT_SIDE>();
+ return getUpdate<LEFT_SIDE>() + getUpdate<RIGHT_SIDE>();
}
-template <>
-inline
+template <> inline
int SyncStatistics::getDelete<LEFT_SIDE>() const
{
return deleteLeft;
}
-template <>
-inline
+template <> inline
int SyncStatistics::getDelete<RIGHT_SIDE>() const
{
return deleteRight;
diff --git a/ui/batch_status_handler.cpp b/ui/batch_status_handler.cpp
index 93237c70..1a710eee 100644
--- a/ui/batch_status_handler.cpp
+++ b/ui/batch_status_handler.cpp
@@ -278,14 +278,14 @@ void BatchStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 da
}
-void BatchStatusHandler::reportStatus(const wxString& text)
+void BatchStatusHandler::reportStatus(const std::wstring& text)
{
syncStatusFrame.setStatusText_NoUpdate(text);
requestUiRefresh(); //throw AbortThisProcess
}
-void BatchStatusHandler::reportInfo(const wxString& text)
+void BatchStatusHandler::reportInfo(const std::wstring& text)
{
errorLog.logMsg(text, TYPE_INFO);
@@ -294,7 +294,7 @@ void BatchStatusHandler::reportInfo(const wxString& text)
}
-void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& warningActive)
+void BatchStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive)
{
errorLog.logMsg(warningMessage, TYPE_WARNING);
@@ -339,7 +339,7 @@ void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& war
}
-ProcessCallback::Response BatchStatusHandler::reportError(const wxString& errorMessage)
+ProcessCallback::Response BatchStatusHandler::reportError(const std::wstring& errorMessage)
{
switch (handleError_)
{
@@ -384,7 +384,7 @@ ProcessCallback::Response BatchStatusHandler::reportError(const wxString& errorM
}
-void BatchStatusHandler::reportFatalError(const wxString& errorMessage)
+void BatchStatusHandler::reportFatalError(const std::wstring& errorMessage)
{
if (handleError_ == xmlAccess::ON_ERROR_POPUP)
exitWhenFinished = false; //log fatal error and show it on status dialog
diff --git a/ui/batch_status_handler.h b/ui/batch_status_handler.h
index 548447f6..998f2bc8 100644
--- a/ui/batch_status_handler.h
+++ b/ui/batch_status_handler.h
@@ -34,13 +34,13 @@ public:
virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID);
virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed);
- virtual void reportStatus(const wxString& text);
- virtual void reportInfo(const wxString& text);
+ virtual void reportStatus(const std::wstring& text);
+ virtual void reportInfo(const std::wstring& text);
virtual void forceUiRefresh();
- virtual void reportWarning(const wxString& warningMessage, bool& warningActive);
- virtual Response reportError(const wxString& errorMessage);
- virtual void reportFatalError(const wxString& errorMessage);
+ virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive);
+ virtual Response reportError(const std::wstring& errorMessage);
+ virtual void reportFatalError(const std::wstring& errorMessage);
private:
virtual void abortThisProcess();
diff --git a/ui/grid_view.cpp b/ui/grid_view.cpp
index bd2bf4f4..0120764f 100644
--- a/ui/grid_view.cpp
+++ b/ui/grid_view.cpp
@@ -181,18 +181,22 @@ GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //map
switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction
{
case SO_CREATE_NEW_LEFT:
+ case SO_MOVE_LEFT_TARGET:
output.existsSyncCreateLeft = true;
if (!syncCreateLeftActive) continue;
break;
case SO_CREATE_NEW_RIGHT:
+ case SO_MOVE_RIGHT_TARGET:
output.existsSyncCreateRight = true;
if (!syncCreateRightActive) continue;
break;
case SO_DELETE_LEFT:
+ case SO_MOVE_LEFT_SOURCE:
output.existsSyncDeleteLeft = true;
if (!syncDeleteLeftActive) continue;
break;
case SO_DELETE_RIGHT:
+ case SO_MOVE_RIGHT_SOURCE:
output.existsSyncDeleteRight = true;
if (!syncDeleteRightActive) continue;
break;
diff --git a/ui/gui_generated.cpp b/ui/gui_generated.cpp
index 3704d666..2b3761c5 100644
--- a/ui/gui_generated.cpp
+++ b/ui/gui_generated.cpp
@@ -942,6 +942,167 @@ FolderPairGenerated::~FolderPairGenerated()
{
}
+CompareStatusGenerated::CompareStatusGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
+{
+ wxBoxSizer* bSizer40;
+ bSizer40 = new wxBoxSizer( wxVERTICAL );
+
+
+ bSizer40->Add( 0, 0, 1, wxEXPAND, 5 );
+
+ wxBoxSizer* bSizer48;
+ bSizer48 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_staticText30 = new wxStaticText( this, wxID_ANY, _("Operation:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText30->Wrap( -1 );
+ m_staticText30->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
+
+ bSizer48->Add( m_staticText30, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_textCtrlStatus = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
+ m_textCtrlStatus->SetBackgroundColour( wxColour( 208, 208, 208 ) );
+
+ bSizer48->Add( m_textCtrlStatus, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer40->Add( bSizer48, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+
+ m_gauge2 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL|wxGA_SMOOTH );
+ bSizer40->Add( m_gauge2, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
+
+ bSizer42 = new wxBoxSizer( wxHORIZONTAL );
+
+ wxBoxSizer* bSizer157;
+ bSizer157 = new wxBoxSizer( wxVERTICAL );
+
+ bSizerFilesFound = new wxBoxSizer( wxHORIZONTAL );
+
+ m_staticText321 = new wxStaticText( this, wxID_ANY, _("Items found:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText321->Wrap( -1 );
+ m_staticText321->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+
+ bSizerFilesFound->Add( m_staticText321, 0, wxALIGN_BOTTOM, 5 );
+
+ m_staticTextScanned = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextScanned->Wrap( -1 );
+ m_staticTextScanned->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
+
+ bSizerFilesFound->Add( m_staticTextScanned, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
+
+ bSizer157->Add( bSizerFilesFound, 0, 0, 5 );
+
+ bSizerFilesRemaining = new wxBoxSizer( wxHORIZONTAL );
+
+ m_staticText46 = new wxStaticText( this, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText46->Wrap( -1 );
+ m_staticText46->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+
+ bSizerFilesRemaining->Add( m_staticText46, 0, wxALIGN_BOTTOM, 5 );
+
+ wxBoxSizer* bSizer154;
+ bSizer154 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_staticTextFilesRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextFilesRemaining->Wrap( -1 );
+ m_staticTextFilesRemaining->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
+
+ bSizer154->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 );
+
+ m_staticText117 = new wxStaticText( this, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText117->Wrap( -1 );
+ m_staticText117->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) );
+
+ bSizer154->Add( m_staticText117, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
+
+ m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextDataRemaining->Wrap( -1 );
+ m_staticTextDataRemaining->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) );
+
+ bSizer154->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 );
+
+ m_staticText118 = new wxStaticText( this, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText118->Wrap( -1 );
+ m_staticText118->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) );
+
+ bSizer154->Add( m_staticText118, 0, wxALIGN_BOTTOM, 5 );
+
+ bSizerFilesRemaining->Add( bSizer154, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
+
+ bSizer157->Add( bSizerFilesRemaining, 0, 0, 5 );
+
+ bSizer42->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
+
+ sSizerSpeed = new wxBoxSizer( wxHORIZONTAL );
+
+ m_staticText104 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText104->Wrap( -1 );
+ m_staticText104->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+
+ sSizerSpeed->Add( m_staticText104, 0, wxALIGN_BOTTOM, 5 );
+
+ m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextSpeed->Wrap( -1 );
+ m_staticTextSpeed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
+
+ sSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
+
+ bSizer42->Add( sSizerSpeed, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer42->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ sSizerTimeRemaining = new wxBoxSizer( wxHORIZONTAL );
+
+ m_staticTextTimeRemFixed = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextTimeRemFixed->Wrap( -1 );
+ m_staticTextTimeRemFixed->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+
+ sSizerTimeRemaining->Add( m_staticTextTimeRemFixed, 0, wxALIGN_BOTTOM, 5 );
+
+ m_staticTextRemTime = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextRemTime->Wrap( -1 );
+ m_staticTextRemTime->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
+
+ sSizerTimeRemaining->Add( m_staticTextRemTime, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
+
+ bSizer42->Add( sSizerTimeRemaining, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
+
+ sSizerTimeElapsed = new wxBoxSizer( wxHORIZONTAL );
+
+ wxStaticText* m_staticText37;
+ m_staticText37 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText37->Wrap( -1 );
+ m_staticText37->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
+
+ sSizerTimeElapsed->Add( m_staticText37, 0, wxALIGN_BOTTOM, 5 );
+
+ m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextTimeElapsed->Wrap( -1 );
+ m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
+
+ sSizerTimeElapsed->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
+
+ bSizer42->Add( sSizerTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
+
+
+ bSizer40->Add( 0, 0, 1, wxEXPAND, 5 );
+
+ this->SetSizer( bSizer40 );
+ this->Layout();
+ bSizer40->Fit( this );
+}
+
+CompareStatusGenerated::~CompareStatusGenerated()
+{
+}
+
BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxSize( 560,320 ), wxDefaultSize );
@@ -1464,167 +1625,6 @@ BatchFolderPairGenerated::~BatchFolderPairGenerated()
{
}
-CompareStatusGenerated::CompareStatusGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
-{
- wxBoxSizer* bSizer40;
- bSizer40 = new wxBoxSizer( wxVERTICAL );
-
-
- bSizer40->Add( 0, 0, 1, wxEXPAND, 5 );
-
- wxBoxSizer* bSizer48;
- bSizer48 = new wxBoxSizer( wxHORIZONTAL );
-
- m_staticText30 = new wxStaticText( this, wxID_ANY, _("Operation:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText30->Wrap( -1 );
- m_staticText30->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
-
- bSizer48->Add( m_staticText30, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_textCtrlStatus = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
- m_textCtrlStatus->SetBackgroundColour( wxColour( 208, 208, 208 ) );
-
- bSizer48->Add( m_textCtrlStatus, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- bSizer40->Add( bSizer48, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
-
- m_gauge2 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL|wxGA_SMOOTH );
- bSizer40->Add( m_gauge2, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
-
- bSizer42 = new wxBoxSizer( wxHORIZONTAL );
-
- wxBoxSizer* bSizer157;
- bSizer157 = new wxBoxSizer( wxVERTICAL );
-
- bSizerFilesFound = new wxBoxSizer( wxHORIZONTAL );
-
- m_staticText321 = new wxStaticText( this, wxID_ANY, _("Items found:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText321->Wrap( -1 );
- m_staticText321->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
-
- bSizerFilesFound->Add( m_staticText321, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticTextScanned = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextScanned->Wrap( -1 );
- m_staticTextScanned->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
-
- bSizerFilesFound->Add( m_staticTextScanned, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
-
- bSizer157->Add( bSizerFilesFound, 0, 0, 5 );
-
- bSizerFilesRemaining = new wxBoxSizer( wxHORIZONTAL );
-
- m_staticText46 = new wxStaticText( this, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText46->Wrap( -1 );
- m_staticText46->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
-
- bSizerFilesRemaining->Add( m_staticText46, 0, wxALIGN_BOTTOM, 5 );
-
- wxBoxSizer* bSizer154;
- bSizer154 = new wxBoxSizer( wxHORIZONTAL );
-
- m_staticTextFilesRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextFilesRemaining->Wrap( -1 );
- m_staticTextFilesRemaining->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
-
- bSizer154->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticText117 = new wxStaticText( this, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText117->Wrap( -1 );
- m_staticText117->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) );
-
- bSizer154->Add( m_staticText117, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
-
- m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextDataRemaining->Wrap( -1 );
- m_staticTextDataRemaining->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) );
-
- bSizer154->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticText118 = new wxStaticText( this, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText118->Wrap( -1 );
- m_staticText118->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) );
-
- bSizer154->Add( m_staticText118, 0, wxALIGN_BOTTOM, 5 );
-
- bSizerFilesRemaining->Add( bSizer154, 0, wxALIGN_BOTTOM|wxLEFT, 5 );
-
- bSizer157->Add( bSizerFilesRemaining, 0, 0, 5 );
-
- bSizer42->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
-
- bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
-
- sSizerSpeed = new wxBoxSizer( wxHORIZONTAL );
-
- m_staticText104 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText104->Wrap( -1 );
- m_staticText104->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
-
- sSizerSpeed->Add( m_staticText104, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextSpeed->Wrap( -1 );
- m_staticTextSpeed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
-
- sSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
-
- bSizer42->Add( sSizerSpeed, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
-
- bSizer42->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- sSizerTimeRemaining = new wxBoxSizer( wxHORIZONTAL );
-
- m_staticTextTimeRemFixed = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextTimeRemFixed->Wrap( -1 );
- m_staticTextTimeRemFixed->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
-
- sSizerTimeRemaining->Add( m_staticTextTimeRemFixed, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticTextRemTime = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextRemTime->Wrap( -1 );
- m_staticTextRemTime->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
-
- sSizerTimeRemaining->Add( m_staticTextRemTime, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
-
- bSizer42->Add( sSizerTimeRemaining, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
-
- bSizer42->Add( 0, 0, 1, wxEXPAND, 5 );
-
- sSizerTimeElapsed = new wxBoxSizer( wxHORIZONTAL );
-
- wxStaticText* m_staticText37;
- m_staticText37 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText37->Wrap( -1 );
- m_staticText37->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) );
-
- sSizerTimeElapsed->Add( m_staticText37, 0, wxALIGN_BOTTOM, 5 );
-
- m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextTimeElapsed->Wrap( -1 );
- m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) );
-
- sSizerTimeElapsed->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
-
- bSizer42->Add( sSizerTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
-
-
- bSizer40->Add( 0, 0, 1, wxEXPAND, 5 );
-
- this->SetSizer( bSizer40 );
- this->Layout();
- bSizer40->Fit( this );
-}
-
-CompareStatusGenerated::~CompareStatusGenerated()
-{
-}
-
SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
@@ -1663,7 +1663,7 @@ SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const
fgSizer1->Add( m_buttonAutomatic, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
- m_staticText81 = new wxStaticText( this, wxID_ANY, _("Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically."), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText81 = new wxStaticText( this, wxID_ANY, _("Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText81->Wrap( 400 );
fgSizer1->Add( m_staticText81, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
@@ -2282,12 +2282,12 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id,
bSizerFinalStat = new wxBoxSizer( wxVERTICAL );
m_listbookResult = new wxListbook( m_panelBackground, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLB_TOP );
-#ifndef __WXGTK__ // Small icon style not supported in GTK
- wxListView* m_listbookResultListView = m_listbookResult->GetListView();
- long m_listbookResultFlags = m_listbookResultListView->GetWindowStyleFlag();
- m_listbookResultFlags = ( m_listbookResultFlags & ~wxLC_ICON ) | wxLC_SMALL_ICON;
- m_listbookResultListView->SetWindowStyleFlag( m_listbookResultFlags );
-#endif
+ wxSize m_listbookResultImageSize = wxSize( 180,1 );
+ int m_listbookResultIndex = 0;
+ wxImageList* m_listbookResultImages = new wxImageList( m_listbookResultImageSize.GetWidth(), m_listbookResultImageSize.GetHeight() );
+ m_listbookResult->AssignImageList( m_listbookResultImages );
+ wxBitmap m_listbookResultBitmap;
+ wxImage m_listbookResultImage;
bSizerFinalStat->Add( m_listbookResult, 1, wxEXPAND, 5 );
@@ -2351,14 +2351,6 @@ SyncStatusDlgGenerated::~SyncStatusDlgGenerated()
}
-MyPanel5::MyPanel5( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
-{
-}
-
-MyPanel5::~MyPanel5()
-{
-}
-
LogControlGenerated::LogControlGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
wxBoxSizer* bSizer153;
@@ -3420,30 +3412,29 @@ GlobalSettingsDlgGenerated::GlobalSettingsDlgGenerated( wxWindow* parent, wxWind
m_checkBoxTransCopy = new wxCheckBox( this, wxID_ANY, _("Transactional file copy"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer23->Add( m_checkBoxTransCopy, 0, wxEXPAND|wxALL, 5 );
- m_textCtrl22 = new wxTextCtrl( this, wxID_ANY, _("Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_NO_VSCROLL|wxTE_READONLY|wxNO_BORDER );
- m_textCtrl22->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- m_textCtrl22->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
- m_textCtrl22->SetMinSize( wxSize( 400,-1 ) );
+ m_staticText82 = new wxStaticText( this, wxID_ANY, _("Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error."), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText82->Wrap( 400 );
+ m_staticText82->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- sbSizer23->Add( m_textCtrl22, 0, wxLEFT|wxEXPAND, 20 );
+ sbSizer23->Add( m_staticText82, 0, wxLEFT, 20 );
m_checkBoxCopyLocked = new wxCheckBox( this, wxID_ANY, _("Copy locked files"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer23->Add( m_checkBoxCopyLocked, 0, wxALL|wxEXPAND, 5 );
- m_textCtrlCopyLocked = new wxTextCtrl( this, wxID_ANY, _("Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_NO_VSCROLL|wxTE_READONLY|wxNO_BORDER );
- m_textCtrlCopyLocked->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- m_textCtrlCopyLocked->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+ m_staticTextCopyLocked = new wxStaticText( this, wxID_ANY, _("Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextCopyLocked->Wrap( 400 );
+ m_staticTextCopyLocked->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- sbSizer23->Add( m_textCtrlCopyLocked, 0, wxLEFT|wxEXPAND, 20 );
+ sbSizer23->Add( m_staticTextCopyLocked, 0, wxLEFT|wxEXPAND, 20 );
m_checkBoxCopyPermissions = new wxCheckBox( this, wxID_ANY, _("Copy file access permissions"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer23->Add( m_checkBoxCopyPermissions, 0, wxALL|wxEXPAND, 5 );
- m_textCtrl2211 = new wxTextCtrl( this, wxID_ANY, _("Transfer file and directory permissions (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_NO_VSCROLL|wxTE_READONLY|wxNO_BORDER );
- m_textCtrl2211->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- m_textCtrl2211->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+ m_staticText8211 = new wxStaticText( this, wxID_ANY, _("Transfer file and directory permissions (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText8211->Wrap( 400 );
+ m_staticText8211->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- sbSizer23->Add( m_textCtrl2211, 0, wxLEFT|wxEXPAND, 20 );
+ sbSizer23->Add( m_staticText8211, 0, wxLEFT|wxEXPAND, 20 );
bSizer95->Add( sbSizer23, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 );
diff --git a/ui/gui_generated.h b/ui/gui_generated.h
index de1dc89b..8fc345a2 100644
--- a/ui/gui_generated.h
+++ b/ui/gui_generated.h
@@ -46,14 +46,15 @@ namespace zen { class Graph2D; }
#include <wx/textctrl.h>
#include <wx/statline.h>
#include <wx/frame.h>
+#include <wx/gauge.h>
#include <wx/choice.h>
#include <wx/spinctrl.h>
#include <wx/listbook.h>
#include <wx/listctrl.h>
#include <wx/dialog.h>
-#include <wx/gauge.h>
#include <wx/radiobut.h>
#include <wx/animate.h>
+#include <wx/imaglist.h>
#include <wx/hyperlink.h>
#include <wx/checklst.h>
#include <wx/calctrl.h>
@@ -263,6 +264,43 @@ public:
};
///////////////////////////////////////////////////////////////////////////////
+/// Class CompareStatusGenerated
+///////////////////////////////////////////////////////////////////////////////
+class CompareStatusGenerated : public wxPanel
+{
+private:
+
+protected:
+ wxStaticText* m_staticText30;
+ wxTextCtrl* m_textCtrlStatus;
+ wxGauge* m_gauge2;
+ wxBoxSizer* bSizer42;
+ wxBoxSizer* bSizerFilesFound;
+ wxStaticText* m_staticText321;
+ wxStaticText* m_staticTextScanned;
+ wxBoxSizer* bSizerFilesRemaining;
+ wxStaticText* m_staticText46;
+ wxStaticText* m_staticTextFilesRemaining;
+ wxStaticText* m_staticText117;
+ wxStaticText* m_staticTextDataRemaining;
+ wxStaticText* m_staticText118;
+ wxBoxSizer* sSizerSpeed;
+ wxStaticText* m_staticText104;
+ wxStaticText* m_staticTextSpeed;
+ wxBoxSizer* sSizerTimeRemaining;
+ wxStaticText* m_staticTextTimeRemFixed;
+ wxStaticText* m_staticTextRemTime;
+ wxBoxSizer* sSizerTimeElapsed;
+ wxStaticText* m_staticTextTimeElapsed;
+
+public:
+
+ CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxRAISED_BORDER|wxTAB_TRAVERSAL );
+ ~CompareStatusGenerated();
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
/// Class BatchDlgGenerated
///////////////////////////////////////////////////////////////////////////////
class BatchDlgGenerated : public wxDialog
@@ -365,43 +403,6 @@ public:
};
///////////////////////////////////////////////////////////////////////////////
-/// Class CompareStatusGenerated
-///////////////////////////////////////////////////////////////////////////////
-class CompareStatusGenerated : public wxPanel
-{
-private:
-
-protected:
- wxStaticText* m_staticText30;
- wxTextCtrl* m_textCtrlStatus;
- wxGauge* m_gauge2;
- wxBoxSizer* bSizer42;
- wxBoxSizer* bSizerFilesFound;
- wxStaticText* m_staticText321;
- wxStaticText* m_staticTextScanned;
- wxBoxSizer* bSizerFilesRemaining;
- wxStaticText* m_staticText46;
- wxStaticText* m_staticTextFilesRemaining;
- wxStaticText* m_staticText117;
- wxStaticText* m_staticTextDataRemaining;
- wxStaticText* m_staticText118;
- wxBoxSizer* sSizerSpeed;
- wxStaticText* m_staticText104;
- wxStaticText* m_staticTextSpeed;
- wxBoxSizer* sSizerTimeRemaining;
- wxStaticText* m_staticTextTimeRemFixed;
- wxStaticText* m_staticTextRemTime;
- wxBoxSizer* sSizerTimeElapsed;
- wxStaticText* m_staticTextTimeElapsed;
-
-public:
-
- CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxRAISED_BORDER|wxTAB_TRAVERSAL );
- ~CompareStatusGenerated();
-
-};
-
-///////////////////////////////////////////////////////////////////////////////
/// Class SyncCfgDlgGenerated
///////////////////////////////////////////////////////////////////////////////
class SyncCfgDlgGenerated : public wxDialog
@@ -586,22 +587,6 @@ public:
};
///////////////////////////////////////////////////////////////////////////////
-/// Class MyPanel5
-///////////////////////////////////////////////////////////////////////////////
-class MyPanel5 : public wxPanel
-{
-private:
-
-protected:
-
-public:
-
- MyPanel5( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxTAB_TRAVERSAL );
- ~MyPanel5();
-
-};
-
-///////////////////////////////////////////////////////////////////////////////
/// Class LogControlGenerated
///////////////////////////////////////////////////////////////////////////////
class LogControlGenerated : public wxPanel
@@ -904,11 +889,11 @@ protected:
wxPanel* m_panel8;
wxStaticText* m_staticText56;
wxCheckBox* m_checkBoxTransCopy;
- wxTextCtrl* m_textCtrl22;
+ wxStaticText* m_staticText82;
wxCheckBox* m_checkBoxCopyLocked;
- wxTextCtrl* m_textCtrlCopyLocked;
+ wxStaticText* m_staticTextCopyLocked;
wxCheckBox* m_checkBoxCopyPermissions;
- wxTextCtrl* m_textCtrl2211;
+ wxStaticText* m_staticText8211;
wxStaticText* m_staticText100;
zen::BitmapButton* m_buttonResetDialogs;
wxGrid* m_gridCustomCommand;
diff --git a/ui/gui_status_handler.cpp b/ui/gui_status_handler.cpp
index b353e918..6809b362 100644
--- a/ui/gui_status_handler.cpp
+++ b/ui/gui_status_handler.cpp
@@ -114,21 +114,21 @@ void CompareStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64
}
-void CompareStatusHandler::reportStatus(const wxString& text)
+void CompareStatusHandler::reportStatus(const std::wstring& text)
{
mainDlg.compareStatus->setStatusText_NoUpdate(text);
requestUiRefresh(); //throw AbortThisProcess
}
-void CompareStatusHandler::reportInfo(const wxString& text)
+void CompareStatusHandler::reportInfo(const std::wstring& text)
{
mainDlg.compareStatus->setStatusText_NoUpdate(text);
requestUiRefresh(); //throw AbortThisProcess
}
-ProcessCallback::Response CompareStatusHandler::reportError(const wxString& message)
+ProcessCallback::Response CompareStatusHandler::reportError(const std::wstring& message)
{
if (ignoreErrors)
return ProcessCallback::IGNORE_ERROR;
@@ -155,7 +155,7 @@ ProcessCallback::Response CompareStatusHandler::reportError(const wxString& mess
}
-void CompareStatusHandler::reportFatalError(const wxString& errorMessage)
+void CompareStatusHandler::reportFatalError(const std::wstring& errorMessage)
{
forceUiRefresh();
@@ -165,7 +165,7 @@ void CompareStatusHandler::reportFatalError(const wxString& errorMessage)
}
-void CompareStatusHandler::reportWarning(const wxString& warningMessage, bool& warningActive)
+void CompareStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive)
{
if (!warningActive || ignoreErrors) //if errors are ignored, then warnings should also
return;
@@ -266,14 +266,14 @@ void SyncStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dat
}
-void SyncStatusHandler::reportStatus(const wxString& text)
+void SyncStatusHandler::reportStatus(const std::wstring& text)
{
syncStatusFrame.setStatusText_NoUpdate(text); //throw ()
requestUiRefresh(); //throw AbortThisProccess
}
-void SyncStatusHandler::reportInfo(const wxString& text)
+void SyncStatusHandler::reportInfo(const std::wstring& text)
{
errorLog.logMsg(text, TYPE_INFO);
@@ -282,7 +282,7 @@ void SyncStatusHandler::reportInfo(const wxString& text)
}
-ProcessCallback::Response SyncStatusHandler::reportError(const wxString& errorMessage)
+ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& errorMessage)
{
switch (handleError_)
{
@@ -320,13 +320,13 @@ ProcessCallback::Response SyncStatusHandler::reportError(const wxString& errorMe
}
-void SyncStatusHandler::reportFatalError(const wxString& errorMessage)
+void SyncStatusHandler::reportFatalError(const std::wstring& errorMessage)
{
errorLog.logMsg(errorMessage, TYPE_FATAL_ERROR);
}
-void SyncStatusHandler::reportWarning(const wxString& warningMessage, bool& warningActive)
+void SyncStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive)
{
errorLog.logMsg(warningMessage, TYPE_WARNING);
diff --git a/ui/gui_status_handler.h b/ui/gui_status_handler.h
index 28429d68..997e511f 100644
--- a/ui/gui_status_handler.h
+++ b/ui/gui_status_handler.h
@@ -29,13 +29,13 @@ public:
virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID);
virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed);
- virtual void reportStatus(const wxString& text);
- virtual void reportInfo(const wxString& text);
+ virtual void reportStatus(const std::wstring& text);
+ virtual void reportInfo(const std::wstring& text);
virtual void forceUiRefresh();
- virtual Response reportError(const wxString& text);
- virtual void reportFatalError(const wxString& errorMessage);
- virtual void reportWarning(const wxString& warningMessage, bool& warningActive);
+ virtual Response reportError(const std::wstring& text);
+ virtual void reportFatalError(const std::wstring& errorMessage);
+ virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive);
private:
void OnKeyPressed(wxKeyEvent& event);
@@ -56,13 +56,13 @@ public:
virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID);
virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed);
- virtual void reportStatus(const wxString& text);
- virtual void reportInfo(const wxString& text);
+ virtual void reportStatus(const std::wstring& text);
+ virtual void reportInfo(const std::wstring& text);
virtual void forceUiRefresh();
- virtual Response reportError(const wxString& text);
- virtual void reportFatalError(const wxString& errorMessage);
- virtual void reportWarning(const wxString& warningMessage, bool& warningActive);
+ virtual Response reportError(const std::wstring& text);
+ virtual void reportFatalError(const std::wstring& errorMessage);
+ virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive);
private:
virtual void abortThisProcess();
diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp
index e1227509..97c3625c 100644
--- a/ui/main_dlg.cpp
+++ b/ui/main_dlg.cpp
@@ -662,8 +662,8 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg,
if (dirFmtLeft.empty() && dirFmtRight.empty()) //only skip check if both sides are empty!
return;
- dirEx.push_back(zen::async2<bool>([=]() { return !dirFmtLeft .empty() && zen::dirExists(dirFmtLeft); }));
- dirEx.push_back(zen::async2<bool>([=]() { return !dirFmtRight.empty() && zen::dirExists(dirFmtRight); }));
+ dirEx.push_back(zen::async2<bool>([=] { return !dirFmtLeft .empty() && zen::dirExists(dirFmtLeft); }));
+ dirEx.push_back(zen::async2<bool>([=] { return !dirFmtRight.empty() && zen::dirExists(dirFmtRight); }));
};
addDirCheck(currMainCfg.firstPair);
std::for_each(currMainCfg.additionalPairs.begin(), currMainCfg.additionalPairs.end(), addDirCheck);
@@ -972,7 +972,7 @@ public:
mainDlg->enableAllElements();
}
- virtual Response reportError(const wxString& errorMessage)
+ virtual Response reportError(const std::wstring& errorMessage)
{
if (abortRequested)
throw AbortDeleteProcess();
@@ -1122,17 +1122,6 @@ wxString extractLastValidDir(const FileSystemObject& fsObj)
return toWx(fullname);
}
-bool tryReplace(const wxString& phrase, const wxString& replacement, wxString& command) //return false on error
-{
- if (command.find(phrase) != wxString::npos)
- {
- if (replacement.empty())
- return false;
- replace(command, phrase, replacement);
- }
- return true;
-}
-
void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const wxString& commandline)
{
@@ -1163,10 +1152,22 @@ void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const
}
wxString command = commandline;
- if (tryReplace(L"%nameCo", nameCo, command) && //attention: replace %nameCo, %dirCo BEFORE %name, %dir to handle dependency
- tryReplace(L"%dirCo", dirCo, command) &&
- tryReplace(L"%name", name, command) &&
- tryReplace(L"%dir", dir, command))
+
+ auto tryReplace = [&](const wxString& phrase, const wxString& replacement) -> bool
+ {
+ if (command.find(phrase) != wxString::npos)
+ {
+ if (replacement.empty())
+ return false;
+ replace(command, phrase, replacement);
+ }
+ return true;
+ };
+
+ if (tryReplace(L"%nameCo", nameCo) && //attention: replace %nameCo, %dirCo BEFORE %name, %dir to handle dependency
+ tryReplace(L"%dirCo", dirCo ) &&
+ tryReplace(L"%name", name ) &&
+ tryReplace(L"%dir", dir ))
zen::shellExecute(command);
else //fallback
{
@@ -1246,9 +1247,6 @@ void MainDialog::disableAllElements(bool enableAbort)
if (m_buttonAbort->IsShownOnScreen()) m_buttonAbort->SetFocus();
m_buttonCompare->Disable();
m_buttonCompare->Hide();
- m_bpButtonCmpConfig ->Disable();
- m_bpButtonSyncConfig->Disable();
- m_buttonStartSync ->Disable();
m_panelTopButtons->Layout();
}
else
@@ -1261,7 +1259,7 @@ void MainDialog::enableAllElements()
EnableCloseButton(true);
m_panelViewFilter ->Enable();
- m_bpButtonCmpConfig ->Enable();
+ m_bpButtonCmpConfig ->Enable(); //wxGTK bug: this line seems to move main dialog to top!!!!!!!
m_panelFilter ->Enable();
m_panelConfig ->Enable();
m_bpButtonSyncConfig ->Enable();
@@ -1277,9 +1275,6 @@ void MainDialog::enableAllElements()
m_buttonAbort->Hide();
m_buttonCompare->Enable();
m_buttonCompare->Show();
- m_bpButtonCmpConfig ->Enable();
- m_bpButtonSyncConfig->Enable();
- m_buttonStartSync ->Enable();
m_panelTopButtons->Layout();
m_panelTopButtons->Enable();
@@ -3428,7 +3423,7 @@ void MainDialog::updateStatistics()
//update preview of bytes to be transferred:
const SyncStatistics st(gridDataView->getDataTentative());
const wxString toCreate = zen::toStringSep(st.getCreate());
- const wxString toUpdate = zen::toStringSep(st.getOverwrite());
+ const wxString toUpdate = zen::toStringSep(st.getUpdate());
const wxString toDelete = zen::toStringSep(st.getDelete());
const wxString data = zen::filesizeToShortString(st.getDataToProcess());
@@ -3977,7 +3972,7 @@ void MainDialog::applySyncConfig()
warningSyncDatabase_(warningSyncDatabase),
parent_(parent) {}
- virtual void reportWarning(const wxString& text)
+ virtual void reportWarning(const std::wstring& text)
{
if (warningSyncDatabase_)
{
@@ -4268,25 +4263,25 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
exportString += copyStringTo<zxString>(_("Legend")) + wxT('\n');
if (syncPreview->previewIsEnabled())
{
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_CREATE_NEW_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_LEFT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_CREATE_NEW_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_RIGHT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_DELETE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_LEFT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_DELETE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_RIGHT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_OVERWRITE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_LEFT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_OVERWRITE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_RIGHT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_DO_NOTHING)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DO_NOTHING)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_EQUAL)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_UNRESOLVED_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_UNRESOLVED_CONFLICT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_EQUAL)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_CREATE_NEW_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_LEFT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_CREATE_NEW_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_RIGHT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_OVERWRITE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_LEFT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_OVERWRITE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_RIGHT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DELETE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_LEFT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DELETE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_RIGHT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DO_NOTHING)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DO_NOTHING)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_UNRESOLVED_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_UNRESOLVED_CONFLICT)) + wxT('\n');
}
else
{
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_LEFT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_SIDE_ONLY)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_RIGHT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_SIDE_ONLY)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_LEFT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_NEWER)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_RIGHT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_NEWER)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_DIFFERENT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_DIFFERENT)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_EQUAL)) + wxT('\n');
- exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_CONFLICT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_EQUAL)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_DIFFERENT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_DIFFERENT)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_LEFT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_SIDE_ONLY)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_RIGHT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_SIDE_ONLY)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_LEFT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_NEWER)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_RIGHT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_NEWER)) + wxT('\n');
+ exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_CONFLICT)) + wxT('\n');
}
exportString += wxT('\n');
diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp
index 25b9d6e8..092cb182 100644
--- a/ui/progress_indicator.cpp
+++ b/ui/progress_indicator.cpp
@@ -6,24 +6,23 @@
#include "progress_indicator.h"
#include <memory>
-#include "gui_generated.h"
+#include <zen/basic_math.h>
+#include <wx/imaglist.h>
#include <wx/stopwatch.h>
-#include "../lib/resources.h"
-#include <wx+/string_conv.h>
-#include <wx+/format_unit.h>
-#include "../lib/statistics.h"
#include <wx/wupdlock.h>
-#include <zen/basic_math.h>
-#include "tray_icon.h"
-#include <memory>
#include <wx+/mouse_move_dlg.h>
-#include "../lib/error_log.h"
#include <wx+/toggle_button.h>
-#include "taskbar.h"
+#include <wx+/string_conv.h>
+#include <wx+/format_unit.h>
#include <wx+/image_tools.h>
#include <wx+/graph.h>
#include <wx+/no_flicker.h>
-#include <zen/basic_math.h>
+#include "gui_generated.h"
+#include "../lib/resources.h"
+#include "../lib/error_log.h"
+#include "../lib/statistics.h"
+#include "tray_icon.h"
+#include "taskbar.h"
using namespace zen;
@@ -289,7 +288,7 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow()
showProgressExternally(toStringSep(scannedObjects) + wxT(" - ") + _("Scanning..."));
break;
case COMPARING_CONTENT:
- showProgressExternally(percentageToShortString(fraction) + wxT(" - ") + _("Comparing content..."), fraction);
+ showProgressExternally(fractionToShortString(fraction) + wxT(" - ") + _("Comparing content..."), fraction);
break;
}
@@ -393,13 +392,15 @@ public:
m_bpButtonErrors ->setActive(true);
m_bpButtonWarnings->setActive(true);
- m_bpButtonInfo ->setActive(false);
+ m_bpButtonInfo ->setActive(errorCount + warningCount == 0);
m_bpButtonErrors ->Show(errorCount != 0);
m_bpButtonWarnings->Show(warningCount != 0);
m_bpButtonInfo ->Show(infoCount != 0);
updateLogText();
+
+ m_textCtrlInfo->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(LogControl::onKeyEvent), NULL, this);
}
virtual void OnErrors(wxCommandEvent& event)
@@ -421,6 +422,20 @@ public:
}
private:
+ void onKeyEvent(wxKeyEvent& event)
+ {
+ const int keyCode = event.GetKeyCode();
+
+ if (event.ControlDown())
+ switch (keyCode)
+ {
+ case 'A': //CTRL + A
+ m_textCtrlInfo->SetSelection(-1, -1); //select all
+ return;
+ }
+ event.Skip();
+ }
+
void updateLogText()
{
int includedTypes = 0;
@@ -509,9 +524,12 @@ struct LabelFormatterBytes : public LabelFormatter
{
virtual double getOptimalBlockSize(double bytesProposed) const
{
+ bytesProposed *= 2; //make blocks twice the default size
+
+ if (bytesProposed <= 1024 * 1024) //set 1 MB min size: reduce initial rapid changes in y-label
+ return 1024 * 1024;
+
//round to next number which is a convenient to read block size
- if (bytesProposed <= 0)
- return 0;
const double k = std::floor(std::log(bytesProposed) / std::log(2.0));
const double e = std::pow(2.0, k);
@@ -530,8 +548,11 @@ struct LabelFormatterTimeElapsed : public LabelFormatter
{
virtual double getOptimalBlockSize(double secProposed) const
{
- if (secProposed <= 5)
- return 5; //minimum block size
+ if (secProposed <= 10)
+ return 10; //minimum block size
+
+ if (secProposed <= 20) //avoid flicker between 10<->15<->20 sec blocks
+ return bestFit(secProposed, 10, 20);
//for seconds and minutes: nice numbers are 1, 5, 10, 15, 20, 30
auto calcBlock = [](double val) -> double
@@ -803,10 +824,7 @@ SyncStatus::SyncStatusImpl::~SyncStatusImpl()
if (mainDialog)
{
mainDialog->enableAllElements();
-
- //restore title text
- mainDialog->SetTitle(titelTextBackup);
-
+ mainDialog->SetTitle(titelTextBackup); //restore title text
mainDialog->Raise();
mainDialog->SetFocus();
}
@@ -977,13 +995,13 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield)
showProgressExternally(wxString() + toStringSep(scannedObjects) + wxT(" - ") + _("Scanning...") + postFix);
break;
case SyncStatus::COMPARING_CONTENT:
- showProgressExternally(wxString() + percentageToShortString(fraction) + wxT(" - ") + _("Comparing content...") + postFix, fraction);
+ showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Comparing content...") + postFix, fraction);
break;
case SyncStatus::SYNCHRONIZING:
- showProgressExternally(wxString() + percentageToShortString(fraction) + wxT(" - ") + _("Synchronizing...") + postFix, fraction);
+ showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Synchronizing...") + postFix, fraction);
break;
case SyncStatus::PAUSE:
- showProgressExternally(wxString() + percentageToShortString(fraction) + wxT(" - ") + _("Paused") + postFix, fraction);
+ showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Paused") + postFix, fraction);
break;
case SyncStatus::ABORTED:
showProgressExternally(_("Aborted") + postFix, fraction);
@@ -1219,10 +1237,17 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id,
m_staticTextSpeed->SetLabel(timeElapMs <= 0 ? L"-" : zen::filesizeToShortString(zen::to<UInt64>(currentData * 1000 / timeElapMs)) + _("/sec"));
//fill result listbox:
+
+ //workaround wxListBox bug on Windows XP: labels are drawn on top of each other
+ assert(m_listbookResult->GetImageList()); //make sure listbook keeps *any* image list
+ //due to some crazy reasons that aren't worth debugging, this needs to be done directly in wxFormBuilder,
+ //the following call is *not* sufficient: m_listbookResult->AssignImageList(new wxImageList(0, 0));
+ //note: alternative solutions involving wxLC_LIST, wxLC_REPORT and SetWindowStyleFlag() do not work portably! wxListBook using wxLC_ICON is obviously a class invariant!
+
//1. re-arrange graph into results listbook
bSizerTop->Detach(m_panelProgress);
m_panelProgress->Reparent(m_listbookResult);
- m_listbookResult->AddPage(m_panelProgress, _("Statistics"), true);
+ m_listbookResult->AddPage(m_panelProgress, _("Statistics"), true); //AddPage() takes ownership!
//2. log file
LogControl* logControl = new LogControl(m_listbookResult, log);
diff --git a/ui/small_dlgs.cpp b/ui/small_dlgs.cpp
index 779bc427..cf323279 100644
--- a/ui/small_dlgs.cpp
+++ b/ui/small_dlgs.cpp
@@ -607,13 +607,13 @@ SyncPreviewDlg::SyncPreviewDlg(wxWindow* parent,
m_staticTextVariant->SetLabel(variantName);
m_textCtrlData->SetValue(zen::filesizeToShortString(statistics.getDataToProcess()));
- m_textCtrlCreateL->SetValue(toStringSep(statistics.getCreate <LEFT_SIDE>()));
- m_textCtrlUpdateL->SetValue(toStringSep(statistics.getOverwrite<LEFT_SIDE>()));
- m_textCtrlDeleteL->SetValue(toStringSep(statistics.getDelete <LEFT_SIDE>()));
+ m_textCtrlCreateL->SetValue(toStringSep(statistics.getCreate<LEFT_SIDE>()));
+ m_textCtrlUpdateL->SetValue(toStringSep(statistics.getUpdate<LEFT_SIDE>()));
+ m_textCtrlDeleteL->SetValue(toStringSep(statistics.getDelete<LEFT_SIDE>()));
- m_textCtrlCreateR->SetValue(toStringSep(statistics.getCreate <RIGHT_SIDE>()));
- m_textCtrlUpdateR->SetValue(toStringSep(statistics.getOverwrite<RIGHT_SIDE>()));
- m_textCtrlDeleteR->SetValue(toStringSep(statistics.getDelete <RIGHT_SIDE>()));
+ m_textCtrlCreateR->SetValue(toStringSep(statistics.getCreate<RIGHT_SIDE>()));
+ m_textCtrlUpdateR->SetValue(toStringSep(statistics.getUpdate<RIGHT_SIDE>()));
+ m_textCtrlDeleteR->SetValue(toStringSep(statistics.getDelete<RIGHT_SIDE>()));
m_checkBoxDontShowAgain->SetValue(dontShowAgain);
@@ -694,7 +694,7 @@ CompareCfgDialog::CompareCfgDialog(wxWindow* parent,
#endif
enumDescrHandleSyml.
- add(SYMLINK_IGNORE, _("Ignore")).
+ add(SYMLINK_IGNORE, _("Exclude")).
add(SYMLINK_USE_DIRECTLY, _("Direct")).
add(SYMLINK_FOLLOW_LINK, _("Follow"));
@@ -818,7 +818,7 @@ GlobalSettingsDlg::GlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSetti
m_checkBoxCopyPermissions->SetLabel(_("Copy NTFS permissions"));
#else
m_checkBoxCopyLocked->Hide();
- m_textCtrlCopyLocked->Hide();
+ m_staticTextCopyLocked->Hide();
#endif
set(globalSettings.gui.externelApplications);
diff --git a/ui/sync_cfg.cpp b/ui/sync_cfg.cpp
index d19520be..26ea5b2e 100644
--- a/ui/sync_cfg.cpp
+++ b/ui/sync_cfg.cpp
@@ -5,6 +5,7 @@
// **************************************************************************
#include "sync_cfg.h"
+#include <memory>
#include "../lib/resources.h"
#include "../lib/dir_name.h"
#include <wx/wupdlock.h>
@@ -12,10 +13,10 @@
#include <wx+/string_conv.h>
#include <wx+/dir_picker.h>
#include "gui_generated.h"
-#include <memory>
#include <wx+/choice_enum.h>
#include "../lib/dir_name.h"
#include <wx+/image_tools.h>
+#include "../file_hierarchy.h"
using namespace zen;
using namespace xmlAccess;
@@ -97,15 +98,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
{
case SYNC_DIR_RIGHT:
buttonLeftOnly->SetBitmapLabel(GlobalResources::getImage(wxT("createRight")));
- buttonLeftOnly->SetToolTip(getDescription(SO_CREATE_NEW_RIGHT));
+ buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_RIGHT));
break;
case SYNC_DIR_LEFT:
buttonLeftOnly->SetBitmapLabel(GlobalResources::getImage(wxT("deleteLeft")));
- buttonLeftOnly->SetToolTip(getDescription(SO_DELETE_LEFT));
+ buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DELETE_LEFT));
break;
case SYNC_DIR_NONE:
buttonLeftOnly->SetBitmapLabel(GlobalResources::getImage(wxT("none")));
- buttonLeftOnly->SetToolTip(getDescription(SO_DO_NOTHING));
+ buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
}
@@ -113,15 +114,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
{
case SYNC_DIR_RIGHT:
buttonRightOnly->SetBitmapLabel(GlobalResources::getImage(wxT("deleteRight")));
- buttonRightOnly->SetToolTip(getDescription(SO_DELETE_RIGHT));
+ buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DELETE_RIGHT));
break;
case SYNC_DIR_LEFT:
buttonRightOnly->SetBitmapLabel(GlobalResources::getImage(wxT("createLeft")));
- buttonRightOnly->SetToolTip(getDescription(SO_CREATE_NEW_LEFT));
+ buttonRightOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_LEFT));
break;
case SYNC_DIR_NONE:
buttonRightOnly->SetBitmapLabel(GlobalResources::getImage(wxT("none")));
- buttonRightOnly->SetToolTip(getDescription(SO_DO_NOTHING));
+ buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
}
@@ -129,15 +130,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
{
case SYNC_DIR_RIGHT:
buttonLeftNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight")));
- buttonLeftNewer->SetToolTip(getDescription(SO_OVERWRITE_RIGHT));
+ buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
case SYNC_DIR_LEFT:
buttonLeftNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft")));
- buttonLeftNewer->SetToolTip(getDescription(SO_OVERWRITE_LEFT));
+ buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
case SYNC_DIR_NONE:
buttonLeftNewer->SetBitmapLabel(GlobalResources::getImage(wxT("none")));
- buttonLeftNewer->SetToolTip(getDescription(SO_DO_NOTHING));
+ buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
}
@@ -145,15 +146,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
{
case SYNC_DIR_RIGHT:
buttonRightNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight")));
- buttonRightNewer->SetToolTip(getDescription(SO_OVERWRITE_RIGHT));
+ buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
case SYNC_DIR_LEFT:
buttonRightNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft")));
- buttonRightNewer->SetToolTip(getDescription(SO_OVERWRITE_LEFT));
+ buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
case SYNC_DIR_NONE:
buttonRightNewer->SetBitmapLabel(GlobalResources::getImage(wxT("none")));
- buttonRightNewer->SetToolTip(getDescription(SO_DO_NOTHING));
+ buttonRightNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
}
@@ -161,15 +162,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
{
case SYNC_DIR_RIGHT:
buttonDifferent->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight")));
- buttonDifferent->SetToolTip(getDescription(SO_OVERWRITE_RIGHT));
+ buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
case SYNC_DIR_LEFT:
buttonDifferent->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft")));
- buttonDifferent->SetToolTip(getDescription(SO_OVERWRITE_LEFT));
+ buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
case SYNC_DIR_NONE:
buttonDifferent->SetBitmapLabel(GlobalResources::getImage(wxT("none")));
- buttonDifferent->SetToolTip(getDescription(SO_DO_NOTHING));
+ buttonDifferent->SetToolTip(getSyncOpDescription(SO_DO_NOTHING));
break;
}
@@ -177,11 +178,11 @@ void updateConfigIcons(const DirectionConfig& directionCfg,
{
case SYNC_DIR_RIGHT:
buttonConflict->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight")));
- buttonConflict->SetToolTip(getDescription(SO_OVERWRITE_RIGHT));
+ buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT));
break;
case SYNC_DIR_LEFT:
buttonConflict->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft")));
- buttonConflict->SetToolTip(getDescription(SO_OVERWRITE_LEFT));
+ buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT));
break;
case SYNC_DIR_NONE:
buttonConflict->SetBitmapLabel(GlobalResources::getImage(wxT("conflict")));
@@ -219,7 +220,7 @@ SyncCfgDialog::SyncCfgDialog(wxWindow* window,
//a proper set-method may be in order some time...
setEnumVal(enumDelhandDescr, *m_choiceHandleDeletion, syncCfg.handleDeletion);
- customDelFolder.setName(syncCfg.customDeletionDirectory);
+ customDelFolder.setName(toWx(syncCfg.customDeletionDirectory));
updateGui();
//error handling
@@ -330,7 +331,7 @@ void SyncCfgDialog::OnApply(wxCommandEvent& event)
//write configuration to main dialog
syncCfgOut.directionCfg = currentDirectionCfg;
syncCfgOut.handleDeletion = getEnumVal(enumDelhandDescr, *m_choiceHandleDeletion);
- syncCfgOut.customDeletionDirectory = customDelFolder.getName();
+ syncCfgOut.customDeletionDirectory = toZ(customDelFolder.getName());
if (refHandleError)
*refHandleError = getEnumVal(enumErrhandDescr, *m_choiceHandleError);
diff --git a/ui/wx_form_build_hide_warnings.h b/ui/wx_form_build_hide_warnings.h
index 277fa0e7..5988aa12 100644
--- a/ui/wx_form_build_hide_warnings.h
+++ b/ui/wx_form_build_hide_warnings.h
@@ -7,10 +7,14 @@
#ifndef WX_FORM_BUILD_230948324234234
#define WX_FORM_BUILD_230948324234234
-//hide compiler warnings in generated code
+//pamper over wxFormBuilder "sub-optimal" code
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+
+#elif defined _MSC_VER
+#pragma warning(disable: 4189)
#endif
#endif //WX_FORM_BUILD_230948324234234
diff --git a/version/version.h b/version/version.h
index e1117ea0..f029c89d 100644
--- a/version/version.h
+++ b/version/version.h
@@ -3,7 +3,7 @@
namespace zen
{
-const wchar_t currentVersion[] = L"4.2"; //internal linkage!
+const wchar_t currentVersion[] = L"4.3"; //internal linkage!
}
#endif
diff --git a/version/version.rc b/version/version.rc
index b902445b..60e22b93 100644
--- a/version/version.rc
+++ b/version/version.rc
@@ -1,2 +1,2 @@
-#define VER_FREEFILESYNC 4,2,0,0
-#define VER_FREEFILESYNC_STR "4.2\0"
+#define VER_FREEFILESYNC 4,3,0,0
+#define VER_FREEFILESYNC_STR "4.3\0"
diff --git a/wx+/format_unit.cpp b/wx+/format_unit.cpp
index 994a2b29..361dbc62 100644
--- a/wx+/format_unit.cpp
+++ b/wx+/format_unit.cpp
@@ -135,7 +135,7 @@ std::wstring zen::remainingTimeToShortString(double timeInSec)
}
-std::wstring zen::percentageToShortString(double fraction)
+std::wstring zen::fractionToShortString(double fraction)
{
return replaceCpy(_("%x%"), L"%x", printNumber<std::wstring>(L"%3.2f", fraction * 100.0), false);
}
diff --git a/wx+/format_unit.h b/wx+/format_unit.h
index 4adf74f8..953910b6 100644
--- a/wx+/format_unit.h
+++ b/wx+/format_unit.h
@@ -15,7 +15,7 @@ namespace zen
{
std::wstring filesizeToShortString(UInt64 filesize);
std::wstring remainingTimeToShortString(double timeInSec);
-std::wstring percentageToShortString(double fraction); //within [0, 1]
+std::wstring fractionToShortString(double fraction); //within [0, 1]
template <class NumberType>
std::wstring toStringSep(NumberType number); //convert number to std::wstring including thousands separator
diff --git a/wx+/serialize.h b/wx+/serialize.h
index cec70278..020b8709 100644
--- a/wx+/serialize.h
+++ b/wx+/serialize.h
@@ -7,11 +7,8 @@
#ifndef SERIALIZE_H_INCLUDED
#define SERIALIZE_H_INCLUDED
-#include <vector>
#include <cstdint>
-#include <memory>
#include <wx/stream.h>
-#include <zen/file_error.h>
#include <zen/file_io.h>
@@ -26,18 +23,13 @@ template <class S> void writeString(wxOutputStream& stream, const S& str);
//############# wxWidgets stream adapter #############
-// can be used as base classes (have virtual destructors)
class FileInputStream : public wxInputStream
{
public:
- FileInputStream(const Zstring& filename) : //throw FileError
- fileObj(filename) {}
+ FileInputStream(const Zstring& filename) : fileObj(filename) {} //throw FileError
private:
- virtual size_t OnSysRead(void* buffer, size_t bufsize)
- {
- return fileObj.read(buffer, bufsize); //throw FileError
- }
+ virtual size_t OnSysRead(void* buffer, size_t bufsize) { return fileObj.read(buffer, bufsize); } //throw FileError
zen::FileInput fileObj;
};
@@ -46,8 +38,7 @@ private:
class FileOutputStream : public wxOutputStream
{
public:
- FileOutputStream(const Zstring& filename) : //throw FileError
- fileObj(filename, zen::FileOutput::ACC_OVERWRITE) {}
+ FileOutputStream(const Zstring& filename) : fileObj(filename, zen::FileOutput::ACC_OVERWRITE) {} //throw FileError
private:
virtual size_t OnSysWrite(const void* buffer, size_t bufsize)
@@ -60,11 +51,11 @@ private:
};
-
-class ReadInputStream //throw FileError
+//wxInputStream proxy throwing FileError on error
+class CheckedReader
{
-protected:
- ReadInputStream(wxInputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {}
+public:
+ CheckedReader(wxInputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {}
template <class T>
T readNumberC() const; //throw FileError, checked read operation
@@ -72,23 +63,19 @@ protected:
template <class S>
S readStringC() const; //throw FileError, checked read operation
- typedef std::shared_ptr<std::vector<char> > CharArray; //there's no guarantee std::string has a ref-counted implementation... so use this "thing"
- CharArray readArrayC() const; //throw FileError
-
+private:
void check() const;
- wxInputStream& getStream() { return stream_; }
-
-private:
wxInputStream& stream_;
const Zstring& errorObjName_; //used for error text only
};
-class WriteOutputStream //throw FileError
+//wxOutputStream proxy throwing FileError on error
+class CheckedWriter
{
-protected:
- WriteOutputStream(const Zstring& errorObjName, wxOutputStream& stream) : stream_(stream), errorObjName_(errorObjName) {}
+public:
+ CheckedWriter(wxOutputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {}
template <class T>
void writeNumberC(T number) const; //throw FileError, checked write operation
@@ -96,13 +83,9 @@ protected:
template <class S>
void writeStringC(const S& str) const; //throw FileError, checked write operation
- void writeArrayC(const std::vector<char>& buffer) const; //throw FileError
-
+private:
void check() const;
- wxOutputStream& getStream() { return stream_; }
-
-private:
wxOutputStream& stream_;
const Zstring& errorObjName_; //used for error text only!
};
@@ -130,11 +113,6 @@ private:
-
-
-
-
-
//-----------------------implementation-------------------------------
template <class T> inline
T readPOD(wxInputStream& stream)
@@ -155,21 +133,15 @@ void writePOD(wxOutputStream& stream, const T& pod)
template <class S> inline
S readString(wxInputStream& stream)
{
+ //don't even consider UTF8 conversions here! "string" is expected to handle arbitrary binary data!
+
typedef typename S::value_type CharType;
const auto strLength = readPOD<std::uint32_t>(stream);
- if (strLength <= 1000)
- {
- CharType buffer[1000];
- stream.Read(buffer, sizeof(CharType) * strLength);
- return S(buffer, strLength);
- }
- else
- {
- std::vector<CharType> buffer(strLength); //throw std::bad_alloc
- stream.Read(&buffer[0], sizeof(CharType) * strLength);
- return S(&buffer[0], strLength);
- }
+ S output;
+ output.resize(strLength); //throw std::bad_alloc
+ stream.Read(&*output.begin(), sizeof(CharType) * strLength);
+ return output;
}
@@ -182,7 +154,7 @@ void writeString(wxOutputStream& stream, const S& str)
inline
-void ReadInputStream::check() const
+void CheckedReader::check() const
{
if (stream_.GetLastError() != wxSTREAM_NO_ERROR)
throw zen::FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\"");
@@ -191,7 +163,7 @@ void ReadInputStream::check() const
template <class T>
inline
-T ReadInputStream::readNumberC() const //checked read operation
+T CheckedReader::readNumberC() const //checked read operation
{
T output = readPOD<T>(stream_);
check();
@@ -200,13 +172,15 @@ T ReadInputStream::readNumberC() const //checked read operation
template <class S> inline
-S ReadInputStream::readStringC() const //checked read operation
+S CheckedReader::readStringC() const //checked read operation
{
S output;
try
{
- output = readString<S>(stream_); //throw (std::bad_alloc)
+ output = readString<S>(stream_); //throw std::bad_alloc
check();
+ if (stream_.LastRead() != output.length() * sizeof(typename S::value_type)) //some additional check
+ throw FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\"");
}
catch (std::exception&)
{
@@ -216,24 +190,8 @@ S ReadInputStream::readStringC() const //checked read operation
}
-inline
-ReadInputStream::CharArray ReadInputStream::readArrayC() const
-{
- const std::uint32_t byteCount = readNumberC<std::uint32_t>();
- CharArray buffer(new std::vector<char>(byteCount));
- if (byteCount > 0)
- {
- stream_.Read(&(*buffer)[0], byteCount);
- check();
- if (stream_.LastRead() != byteCount) //some additional check
- throw FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\"");
- }
- return buffer;
-}
-
-
template <class T> inline
-void WriteOutputStream::writeNumberC(T number) const //checked write operation
+void CheckedWriter::writeNumberC(T number) const //checked write operation
{
writePOD<T>(stream_, number);
check();
@@ -241,29 +199,17 @@ void WriteOutputStream::writeNumberC(T number) const //checked write operation
template <class S> inline
-void WriteOutputStream::writeStringC(const S& str) const //checked write operation
+void CheckedWriter::writeStringC(const S& str) const //checked write operation
{
writeString(stream_, str);
check();
+ if (stream_.LastWrite() != str.length() * sizeof(typename S::value_type)) //some additional check
+ throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\"");
}
inline
-void WriteOutputStream::writeArrayC(const std::vector<char>& buffer) const
-{
- writeNumberC<std::uint32_t>(static_cast<std::uint32_t>(buffer.size()));
- if (buffer.size() > 0)
- {
- stream_.Write(&buffer[0], buffer.size());
- check();
- if (stream_.LastWrite() != buffer.size()) //some additional check
- throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\"");
- }
-}
-
-
-inline
-void WriteOutputStream::check() const
+void CheckedWriter::check() const
{
if (stream_.GetLastError() != wxSTREAM_NO_ERROR)
throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\"");
diff --git a/lib/FindFilePlus/FindFilePlus.vcxproj b/zen/FindFilePlus/FindFilePlus.vcxproj
index 2c4256a6..2c4256a6 100644
--- a/lib/FindFilePlus/FindFilePlus.vcxproj
+++ b/zen/FindFilePlus/FindFilePlus.vcxproj
diff --git a/lib/FindFilePlus/dll_main.cpp b/zen/FindFilePlus/dll_main.cpp
index 5d64181b..5d64181b 100644
--- a/lib/FindFilePlus/dll_main.cpp
+++ b/zen/FindFilePlus/dll_main.cpp
diff --git a/lib/FindFilePlus/find_file_plus.cpp b/zen/FindFilePlus/find_file_plus.cpp
index becfe553..becfe553 100644
--- a/lib/FindFilePlus/find_file_plus.cpp
+++ b/zen/FindFilePlus/find_file_plus.cpp
diff --git a/lib/FindFilePlus/find_file_plus.h b/zen/FindFilePlus/find_file_plus.h
index aacdf0ea..72b76dbb 100644
--- a/lib/FindFilePlus/find_file_plus.h
+++ b/zen/FindFilePlus/find_file_plus.h
@@ -48,7 +48,7 @@ FindHandle openDir(const wchar_t* dirname); //returns NULL on error, call ::GetL
//note: do NOT place an asterisk at end, e.g. C:\SomeDir\*, as one would do for ::FindFirstFile()
DLL_FUNCTION_DECLARATION
-bool readDir(FindHandle hnd, FileInformation& output); //returns false on error or if there are no more files; ::GetLastError() returns ERROR_NO_MORE_FILES
+bool readDir(FindHandle hnd, FileInformation& output); //returns false on error or if there are no more files; ::GetLastError() returns ERROR_NO_MORE_FILES in this case
DLL_FUNCTION_DECLARATION
void closeDir(FindHandle hnd);
diff --git a/lib/FindFilePlus/init_dll_binding.h b/zen/FindFilePlus/init_dll_binding.h
index 51b32c99..51b32c99 100644
--- a/lib/FindFilePlus/init_dll_binding.h
+++ b/zen/FindFilePlus/init_dll_binding.h
diff --git a/lib/FindFilePlus/load_dll.cpp b/zen/FindFilePlus/load_dll.cpp
index 20d9a5fe..20d9a5fe 100644
--- a/lib/FindFilePlus/load_dll.cpp
+++ b/zen/FindFilePlus/load_dll.cpp
diff --git a/lib/FindFilePlus/load_dll.h b/zen/FindFilePlus/load_dll.h
index 350de9f8..350de9f8 100644
--- a/lib/FindFilePlus/load_dll.h
+++ b/zen/FindFilePlus/load_dll.h
diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp
index 81e49f89..c980c715 100644
--- a/zen/dir_watcher.cpp
+++ b/zen/dir_watcher.cpp
@@ -134,7 +134,8 @@ public:
ReadChangesAsync(const Zstring& directory, //make sure to not leak in thread-unsafe types!
const std::shared_ptr<SharedData>& shared) :
shared_(shared),
- dirname(directory)
+ dirname(directory),
+ hDir(INVALID_HANDLE_VALUE)
{
if (!endsWith(dirname, FILE_NAME_SEPARATOR))
dirname += FILE_NAME_SEPARATOR;
@@ -143,8 +144,8 @@ public:
//http://msdn.microsoft.com/en-us/library/aa363858(v=vs.85).aspx
try
{
- Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError
- Privileges::getInstance().ensureActive(SE_RESTORE_NAME); //
+ activatePrivilege(SE_BACKUP_NAME); //throw FileError
+ activatePrivilege(SE_RESTORE_NAME); //
}
catch (const FileError&) {}
@@ -155,7 +156,7 @@ public:
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
- if (hDir == INVALID_HANDLE_VALUE )
+ if (hDir == INVALID_HANDLE_VALUE)
{
const std::wstring errorMsg = _("Could not initialize directory monitoring:") + L"\n\"" + dirname + L"\"" + L"\n\n" + zen::getLastErrorFormatted();
if (errorCodeForNotExisting(::GetLastError()))
@@ -253,7 +254,7 @@ public:
std::swap(hDir, other.hDir);
}
- HANDLE getDirHandle() const { return hDir; } //for reading purposes only, don't abuse (e.g. close handle)!
+ HANDLE getDirHandle() const { return hDir; } //for reading/monitoring purposes only, don't abuse (e.g. close handle)!
private:
//shared between main and worker:
@@ -268,13 +269,9 @@ class HandleVolumeRemoval : public NotifyRequestDeviceRemoval
{
public:
HandleVolumeRemoval(HANDLE hDir,
- boost::thread& worker,
- const std::shared_ptr<SharedData>& shared,
- const Zstring& dirname) :
+ boost::thread& worker) :
NotifyRequestDeviceRemoval(hDir), //throw FileError
worker_(worker),
- shared_(shared),
- dirname_(dirname),
removalRequested(false),
operationComplete(false) {}
@@ -291,16 +288,12 @@ private:
worker_.join();
//now hDir should have been released
- //report removal as change to main directory
- shared_->addChange(dirname_);
-
removalRequested = true;
} //don't throw!
+
virtual void onRemovalFinished(HANDLE hnd, bool successful) { operationComplete = true; } //throw()!
boost::thread& worker_;
- std::shared_ptr<SharedData> shared_;
- Zstring dirname_;
bool removalRequested;
bool operationComplete;
};
@@ -312,6 +305,7 @@ struct DirWatcher::Pimpl
boost::thread worker;
std::shared_ptr<SharedData> shared;
+ Zstring dirname;
std::unique_ptr<HandleVolumeRemoval> volRemoval;
};
@@ -320,9 +314,10 @@ DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError
pimpl_(new Pimpl)
{
pimpl_->shared = std::make_shared<SharedData>();
+ pimpl_->dirname = directory;
ReadChangesAsync reader(directory, pimpl_->shared); //throw FileError
- pimpl_->volRemoval.reset(new HandleVolumeRemoval(reader.getDirHandle(), pimpl_->worker, pimpl_->shared, directory)); //throw FileError
+ pimpl_->volRemoval.reset(new HandleVolumeRemoval(reader.getDirHandle(), pimpl_->worker)); //throw FileError
pimpl_->worker = boost::thread(std::move(reader));
}
@@ -332,22 +327,29 @@ DirWatcher::~DirWatcher()
pimpl_->worker.interrupt();
//pimpl_->worker.join(); -> we don't have time to wait... will take ~50ms anyway
//caveat: exitting the app may simply kill this thread!
+}
+
+
+std::vector<Zstring> DirWatcher::getChanges(const std::function<void()>& processGuiMessages) //throw FileError
+{
+ std::vector<Zstring> output;
- //wait until device removal is confirmed, to (hopefully!) prevent locking hDir again by new watch!
+ //wait until device removal is confirmed, to prevent locking hDir again by some new watch!
if (pimpl_->volRemoval->requestReceived())
{
- const boost::system_time maxwait = boost::get_system_time() + boost::posix_time::seconds(3); //HandleVolumeRemoval::finished() not guaranteed!
+ const boost::system_time maxwait = boost::get_system_time() + boost::posix_time::seconds(15);
+ //HandleVolumeRemoval::finished() not guaranteed! note: Windows gives unresponsive applications ca. 10 seconds until unmounting the usb stick in worst case
while (!pimpl_->volRemoval->finished() && boost::get_system_time() < maxwait)
+ {
+ processGuiMessages(); //DBT_DEVICEREMOVECOMPLETE message is sent here!
boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(50));
- }
-}
-
+ }
-std::vector<Zstring> DirWatcher::getChanges() //throw FileError
-{
- std::vector<Zstring> output;
- pimpl_->shared->getChanges(output); //throw FileError
+ output.push_back(pimpl_->dirname); //report removal as change to main directory
+ }
+ else //the normal case...
+ pimpl_->shared->getChanges(output); //throw FileError
return output;
}
@@ -454,7 +456,7 @@ DirWatcher::~DirWatcher()
}
-std::vector<Zstring> DirWatcher::getChanges() //throw FileError
+std::vector<Zstring> DirWatcher::getChanges(const std::function<void()>&) //throw FileError
{
std::vector<char> buffer(1024 * (sizeof(struct inotify_event) + 16));
diff --git a/zen/dir_watcher.h b/zen/dir_watcher.h
index df3c444c..a9898abb 100644
--- a/zen/dir_watcher.h
+++ b/zen/dir_watcher.h
@@ -9,6 +9,7 @@
#include <vector>
#include <memory>
+#include <functional>
#include "file_error.h"
namespace zen
@@ -35,7 +36,7 @@ public:
~DirWatcher();
//extract accumulated changes since last call
- std::vector<Zstring> getChanges(); //throw FileError
+ std::vector<Zstring> getChanges(const std::function<void()>& processGuiMessages); //throw FileError
private:
DirWatcher(const DirWatcher&);
diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp
index 5d57938a..8523c633 100644
--- a/zen/file_handling.cpp
+++ b/zen/file_handling.cpp
@@ -15,7 +15,7 @@
#include "assert_static.h"
#include <boost/thread/tss.hpp>
#include <boost/thread/once.hpp>
-#include "file_id_internal.h"
+#include "file_id_def.h"
#ifdef FFS_WIN
#include "privilege.h"
@@ -194,12 +194,15 @@ namespace
#ifdef FFS_WIN
DWORD retrieveVolumeSerial(const Zstring& pathName) //return 0 on error!
{
- std::vector<wchar_t> buffer(10000);
+ //note: this even works for network shares: \\share\dirname
+
+ const DWORD BUFFER_SIZE = 10000;
+ std::vector<wchar_t> buffer(BUFFER_SIZE);
//full pathName need not yet exist!
if (!::GetVolumePathName(pathName.c_str(), //__in LPCTSTR lpszFileName,
&buffer[0], //__out LPTSTR lpszVolumePathName,
- static_cast<DWORD>(buffer.size()))) //__in DWORD cchBufferLength
+ BUFFER_SIZE)) //__in DWORD cchBufferLength
return 0;
Zstring volumePath = &buffer[0];
@@ -608,7 +611,7 @@ struct RemoveCallbackImpl : public CallbackRemoveDir
moveCallback_(moveCallback) {}
virtual void notifyFileDeletion(const Zstring& filename) { moveCallback_.requestUiRefresh(sourceDir_); }
- virtual void notifyDirDeletion(const Zstring& dirname) { moveCallback_.requestUiRefresh(sourceDir_); }
+ virtual void notifyDirDeletion (const Zstring& dirname ) { moveCallback_.requestUiRefresh(sourceDir_); }
private:
RemoveCallbackImpl(const RemoveCallbackImpl&);
@@ -620,7 +623,7 @@ private:
}
-void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError;
+void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError
{
//call back once per folder
if (callback)
@@ -683,7 +686,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool
}
-void zen::moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError;
+void zen::moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError
{
#ifdef FFS_WIN
const Zstring& sourceDirFormatted = sourceDir;
@@ -999,13 +1002,13 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, ProcSym
try
{
//enable privilege: required to read/write SACL information
- Privileges::getInstance().ensureActive(SE_SECURITY_NAME); //polling allowed...
+ activatePrivilege(SE_SECURITY_NAME); //polling allowed...
//enable privilege: required to copy owner information
- Privileges::getInstance().ensureActive(SE_RESTORE_NAME);
+ activatePrivilege(SE_RESTORE_NAME);
//the following privilege may be required according to http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx (although not needed nor active in my tests)
- Privileges::getInstance().ensureActive(SE_BACKUP_NAME);
+ activatePrivilege(SE_BACKUP_NAME);
}
catch (const FileError& e)
{
@@ -1416,14 +1419,19 @@ public:
throw FileError(errorMsg);
}
- void setSrcAttr(const FileAttrib& attr) { sourceAttr = attr; }
- FileAttrib getSrcAttr() const { assert(sourceAttr.modificationTime != 0); return sourceAttr; }
+ void setNewAttr(const FileAttrib& attr) { newAttrib = attr; }
+
+ FileAttrib getSrcAttr() const
+ {
+ assert(newAttrib.modificationTime != 0);
+ return newAttrib;
+ }
private:
CallbackData(const CallbackData&);
CallbackData& operator=(const CallbackData&);
- FileAttrib sourceAttr;
+ FileAttrib newAttrib;
std::wstring errorMsg; //
bool exceptionInUserCallback; //these two are exclusive!
UInt64 bytesTransferredOnException;
@@ -1456,19 +1464,27 @@ DWORD CALLBACK copyCallbackInternal(
//#################### return source file attributes ################################
if (dwCallbackReason == CALLBACK_STREAM_SWITCH) //called up front for every file (even if 0-sized)
{
- BY_HANDLE_FILE_INFORMATION fileInfo = {};
- if (!::GetFileInformationByHandle(hSourceFile, &fileInfo))
+ BY_HANDLE_FILE_INFORMATION fileInfoSrc = {};
+ if (!::GetFileInformationByHandle(hSourceFile, &fileInfoSrc))
{
cbd.reportError(_("Error reading file attributes:") + L"\n\"" + cbd.sourceFile_ + L"\"" + L"\n\n" + getLastErrorFormatted());
return PROGRESS_CANCEL;
}
- const FileAttrib attr = { UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh),
- toTimeT(fileInfo.ftLastWriteTime)
- };
- //extractFileID(fileInfo));
+ BY_HANDLE_FILE_INFORMATION fileInfoTrg = {};
+ if (!::GetFileInformationByHandle(hDestinationFile, &fileInfoTrg))
+ {
+ cbd.reportError(_("Error reading file attributes:") + L"\n\"" + cbd.targetFile_ + L"\"" + L"\n\n" + getLastErrorFormatted());
+ return PROGRESS_CANCEL;
+ }
+
+ FileAttrib attr;
+ attr.fileSize = UInt64(fileInfoSrc.nFileSizeLow, fileInfoSrc.nFileSizeHigh);
+ attr.modificationTime = toTimeT(fileInfoSrc.ftLastWriteTime);
+ attr.sourceFileId = extractFileID(fileInfoSrc);
+ attr.targetFileId = extractFileID(fileInfoTrg);
- cbd.setSrcAttr(attr);
+ cbd.setNewAttr(attr);
//#################### copy file creation time ################################
FILETIME creationTime = {};
@@ -1527,7 +1543,7 @@ DWORD CALLBACK copyCallbackInternal(
void rawCopyWinApi_sub(const Zstring& sourceFile,
const Zstring& targetFile,
CallbackCopyFile* callback,
- FileAttrib* sourceAttr) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
+ FileAttrib* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked
{
zen::ScopeGuard guardTarget = zen::makeGuard([&]() { removeFile(targetFile); }); //transactional behavior: guard just before starting copy, we don't trust ::CopyFileEx(), do we ;)
@@ -1601,8 +1617,8 @@ void rawCopyWinApi_sub(const Zstring& sourceFile,
throw FileError(errorMessage);
}
- if (sourceAttr)
- *sourceAttr = cbd.getSrcAttr();
+ if (newAttrib)
+ *newAttrib = cbd.getSrcAttr();
{
const Int64 modTime = getFileTime(sourceFile, SYMLINK_FOLLOW); //throw FileError
@@ -1972,7 +1988,7 @@ void rawCopyWinApi(const Zstring& sourceFile,
void rawCopyStream(const Zstring& sourceFile,
const Zstring& targetFile,
CallbackCopyFile* callback,
- FileAttrib* sourceAttr) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting
+ FileAttrib* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting
{
zen::ScopeGuard guardTarget = zen::makeGuard([&]() { removeFile(targetFile); }); //transactional behavior: place guard before lifetime of FileOutput
try
@@ -2012,23 +2028,29 @@ void rawCopyStream(const Zstring& sourceFile,
//adapt file modification time:
{
- struct stat srcInfo = {};
+ struct ::stat srcInfo = {};
if (::stat(sourceFile.c_str(), &srcInfo) != 0) //read file attributes from source directory
throw FileError(_("Error reading file attributes:") + L"\n\"" + sourceFile + L"\"" + L"\n\n" + getLastErrorFormatted());
- if (sourceAttr)
- {
- sourceAttr->fileSize = UInt64(srcInfo.st_size);
- sourceAttr->modificationTime = srcInfo.st_mtime;
- }
-
- struct utimbuf newTimes = {};
+ struct ::utimbuf newTimes = {};
newTimes.actime = srcInfo.st_atime;
newTimes.modtime = srcInfo.st_mtime;
//set new "last write time"
if (::utime(targetFile.c_str(), &newTimes) != 0)
throw FileError(_("Error changing modification time:") + L"\n\"" + targetFile + L"\"" + L"\n\n" + getLastErrorFormatted());
+
+ if (newAttrib)
+ {
+ struct ::stat trgInfo = {};
+ if (::stat(targetFile.c_str(), &trgInfo) != 0) //read file attributes from source directory
+ throw FileError(_("Error reading file attributes:") + L"\n\"" + targetFile + L"\"" + L"\n\n" + getLastErrorFormatted());
+
+ newAttrib->fileSize = UInt64(srcInfo.st_size);
+ newAttrib->modificationTime = srcInfo.st_mtime;
+ newAttrib->sourceFileId = extractFileID(srcInfo);
+ newAttrib->targetFileId = extractFileID(trgInfo);
+ }
}
guardTarget.dismiss(); //target has been created successfully!
diff --git a/zen/file_handling.h b/zen/file_handling.h
index 02f3e532..8ffe38d0 100644
--- a/zen/file_handling.h
+++ b/zen/file_handling.h
@@ -10,6 +10,7 @@
#include "zstring.h"
#include "file_error.h"
#include "int64.h"
+#include "file_id_def.h"
namespace zen
{
@@ -68,7 +69,9 @@ void createDirectory(const Zstring& directory); //throw FileError; -> function o
struct FileAttrib
{
UInt64 fileSize;
- Int64 modificationTime; //size_t UTC compatible
+ Int64 modificationTime; //time_t UTC compatible
+ FileId sourceFileId;
+ FileId targetFileId;
};
void copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPathMissing, ErrorFileLocked (Windows-only)
@@ -76,7 +79,7 @@ void copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPathMissi
bool copyFilePermissions,
bool transactionalCopy,
CallbackCopyFile* callback, //may be NULL
- FileAttrib* sourceAttr = NULL); //return current attributes at the time of copy
+ FileAttrib* newAttrib = NULL); //return current attributes at the time of copy
//Note: it MAY happen that copyFile() leaves temp files behind, e.g. temporary network drop.
// => clean them up at an appropriate time (automatically set sync directions to delete them). They have the following ending:
const Zstring TEMP_FILE_ENDING = Zstr(".ffs_tmp");
diff --git a/zen/file_id.cpp b/zen/file_id.cpp
index acbdcd7b..7527062b 100644
--- a/zen/file_id.cpp
+++ b/zen/file_id.cpp
@@ -5,7 +5,6 @@
// **************************************************************************
#include "file_id.h"
-#include "file_id_internal.h"
#ifdef FFS_WIN
#include "win.h" //includes "windows.h"
@@ -17,7 +16,7 @@
#endif
-std::string zen::getFileID(const Zstring& filename)
+zen::FileId zen::getFileID(const Zstring& filename)
{
#ifdef FFS_WIN
//WARNING: CreateFile() is SLOW, while GetFileInformationByHandle() is cheap!
@@ -43,11 +42,11 @@ std::string zen::getFileID(const Zstring& filename)
#elif defined FFS_LINUX
struct ::stat fileInfo = {};
- if (::lstat(filename.c_str(), &fileInfo) == 0) //lstat() does not follow symlinks
+ if (::stat(filename.c_str(), &fileInfo) == 0) //stat() follows symlinks
return extractFileID(fileInfo);
#endif
- return std::string();
+ return zen::FileId();
}
@@ -56,10 +55,10 @@ bool zen::samePhysicalFile(const Zstring& file1, const Zstring& file2)
if (EqualFilename()(file1, file2)) //quick check
return true;
- const std::string id1 = getFileID(file1);
- const std::string id2 = getFileID(file2);
+ const auto id1 = getFileID(file1);
+ const auto id2 = getFileID(file2);
- if (id1.empty() || id2.empty())
+ if (id1 == zen::FileId() || id2 == zen::FileId())
return false;
return id1 == id2;
diff --git a/zen/file_id.h b/zen/file_id.h
index f015569d..3fd4c6bb 100644
--- a/zen/file_id.h
+++ b/zen/file_id.h
@@ -7,6 +7,7 @@
#ifndef FILEID_H_INCLUDED
#define FILEID_H_INCLUDED
+#include "file_id_def.h"
#include "zstring.h"
#include <string>
@@ -15,8 +16,8 @@
namespace zen
{
//get unique file id (symbolic link handling: opens the link!!!)
-//returns empty string on error!
-std::string getFileID(const Zstring& filename);
+//returns initial FileId() on error!
+FileId getFileID(const Zstring& filename);
//test whether two distinct paths point to the same file or directory:
// true: paths point to same files/dirs
diff --git a/zen/file_id_def.h b/zen/file_id_def.h
new file mode 100644
index 00000000..b2029879
--- /dev/null
+++ b/zen/file_id_def.h
@@ -0,0 +1,65 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#ifndef FILE_ID_INTERNAL_HEADER_013287632486321493
+#define FILE_ID_INTERNAL_HEADER_013287632486321493
+
+#include <utility>
+#include "assert_static.h"
+
+#ifdef FFS_WIN
+#include "win.h" //includes "windows.h"
+
+#elif defined FFS_LINUX
+#include <sys/stat.h>
+#endif
+
+
+namespace zen
+{
+#ifdef FFS_WIN
+typedef std::pair<decltype(BY_HANDLE_FILE_INFORMATION().dwVolumeSerialNumber), decltype(ULARGE_INTEGER().QuadPart)> FileId; //(volume serial number, file ID)
+
+inline
+FileId extractFileID(const BY_HANDLE_FILE_INFORMATION& fileInfo)
+{
+ ULARGE_INTEGER uint = {};
+ uint.HighPart = fileInfo.nFileIndexHigh;
+ uint.LowPart = fileInfo.nFileIndexLow;
+ return std::make_pair(fileInfo.dwVolumeSerialNumber, uint.QuadPart);
+}
+
+inline
+FileId extractFileID(DWORD dwVolumeSerialNumber, ULARGE_INTEGER fileId)
+{
+ return std::make_pair(dwVolumeSerialNumber, fileId.QuadPart);
+}
+
+namespace impl
+{
+inline
+void validate(const FileId& id, const BY_HANDLE_FILE_INFORMATION& fileInfo)
+{
+ assert_static(sizeof(id.second) == sizeof(fileInfo.nFileIndexHigh) + sizeof(fileInfo.nFileIndexLow));
+ assert_static(sizeof(id.first ) == sizeof(DWORD));
+ assert_static(sizeof(id.second) == sizeof(ULARGE_INTEGER));
+}
+}
+
+#elif defined FFS_LINUX
+namespace impl { typedef struct ::stat StatDummy; } //sigh...
+
+typedef std::pair<decltype(impl::StatDummy::st_dev), decltype(impl::StatDummy::st_ino)> FileId; //(device id, inode)
+
+inline
+FileId extractFileID(const struct stat& fileInfo)
+{
+ return std::make_pair(fileInfo.st_dev, fileInfo.st_ino);
+}
+#endif
+}
+
+#endif //FILE_ID_INTERNAL_HEADER_013287632486321493
diff --git a/zen/file_id_internal.h b/zen/file_id_internal.h
deleted file mode 100644
index 492d8432..00000000
--- a/zen/file_id_internal.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
-// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef FILE_ID_INTERNAL_HEADER_013287632486321493
-#define FILE_ID_INTERNAL_HEADER_013287632486321493
-
-#include <string>
-
-#ifdef FFS_WIN
-#include "win.h" //includes "windows.h"
-
-#elif defined FFS_LINUX
-#include <sys/stat.h>
-#endif
-
-namespace
-{
-template <class T> inline
-std::string numberToBytes(T number)
-{
- const char* rawBegin = reinterpret_cast<const char*>(&number);
- return std::string(rawBegin, rawBegin + sizeof(number));
-}
-
-#ifdef FFS_WIN
-inline
-std::string extractFileID(const BY_HANDLE_FILE_INFORMATION& fileInfo)
-{
- return numberToBytes(fileInfo.dwVolumeSerialNumber) +
- numberToBytes(fileInfo.nFileIndexHigh) +
- numberToBytes(fileInfo.nFileIndexLow);
-}
-#elif defined FFS_LINUX
-inline
-std::string extractFileID(const struct stat& fileInfo)
-{
- return numberToBytes(fileInfo.st_dev) +
- numberToBytes(fileInfo.st_ino);
-}
-#endif
-
-}
-
-
-#endif //FILE_ID_INTERNAL_HEADER_013287632486321493
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp
index 7a2df695..81e70383 100644
--- a/zen/file_traverser.cpp
+++ b/zen/file_traverser.cpp
@@ -14,8 +14,8 @@
#include "long_path_prefix.h"
#include "dst_hack.h"
#include "file_update_handle.h"
-//#include "dll_loader.h"
-//#include "FindFilePlus/find_file_plus.h"
+#include "dll.h"
+#include "FindFilePlus/find_file_plus.h"
#elif defined FFS_LINUX
#include <sys/stat.h>
@@ -30,33 +30,34 @@ namespace
{
//implement "retry" in a generic way:
-//returns "true" if "cmd" was invoked successfully, "false" if error occured and was ignored
-template <class Command> inline //function object with bool operator()(std::wstring& errorMsg), returns "true" on success, "false" on error and writes "errorMsg" in this case
-bool tryReportingError(Command cmd, zen::TraverseCallback& callback)
+template <class Command> inline //function object expecting to throw FileError if operation fails
+void tryReportingError(Command cmd, zen::TraverseCallback& callback)
{
for (;;)
- {
- std::wstring errorMsg;
- if (cmd(errorMsg))
- return true;
-
- switch (callback.onError(errorMsg))
+ try
{
- case TraverseCallback::TRAV_ERROR_RETRY:
- break;
- case TraverseCallback::TRAV_ERROR_IGNORE:
- return false;
- default:
- assert(false);
- break;
+ cmd();
+ return;
+ }
+ catch (const FileError& e)
+ {
+ switch (callback.onError(e.toString()))
+ {
+ case TraverseCallback::TRAV_ERROR_RETRY:
+ break;
+ case TraverseCallback::TRAV_ERROR_IGNORE:
+ return;
+ default:
+ assert(false);
+ break;
+ }
}
- }
}
#ifdef FFS_WIN
inline
-bool setWin32FileInformationFromSymlink(const Zstring& linkName, zen::TraverseCallback::FileInfo& output)
+bool extractFileInfoFromSymlink(const Zstring& linkName, zen::TraverseCallback::FileInfo& output)
{
//open handle to target of symbolic link
HANDLE hFile = ::CreateFile(zen::applyLongPathPrefix(linkName).c_str(),
@@ -75,288 +76,308 @@ bool setWin32FileInformationFromSymlink(const Zstring& linkName, zen::TraverseCa
return false;
//write output
- output.lastWriteTimeRaw = toTimeT(fileInfoByHandle.ftLastWriteTime);
output.fileSize = zen::UInt64(fileInfoByHandle.nFileSizeLow, fileInfoByHandle.nFileSizeHigh);
+ output.lastWriteTimeRaw = toTimeT(fileInfoByHandle.ftLastWriteTime);
+ //output.id = extractFileID(fileInfoByHandle); -> id from dereferenced symlink is problematic, since renaming will consider the link, not the target!
return true;
}
+
+DWORD retrieveVolumeSerial(const Zstring& pathName) //return 0 on error!
+{
+ //note: this even works for network shares: \\share\dirname
+
+ const DWORD BUFFER_SIZE = 10000;
+ std::vector<wchar_t> buffer(BUFFER_SIZE);
+
+ //full pathName need not yet exist!
+ if (!::GetVolumePathName(pathName.c_str(), //__in LPCTSTR lpszFileName,
+ &buffer[0], //__out LPTSTR lpszVolumePathName,
+ BUFFER_SIZE)) //__in DWORD cchBufferLength
+ return 0;
+
+ Zstring volumePath = &buffer[0];
+ if (!endsWith(volumePath, FILE_NAME_SEPARATOR))
+ volumePath += FILE_NAME_SEPARATOR;
+
+ DWORD volumeSerial = 0;
+ if (!::GetVolumeInformation(volumePath.c_str(), //__in_opt LPCTSTR lpRootPathName,
+ NULL, //__out LPTSTR lpVolumeNameBuffer,
+ 0, //__in DWORD nVolumeNameSize,
+ &volumeSerial, //__out_opt LPDWORD lpVolumeSerialNumber,
+ NULL, //__out_opt LPDWORD lpMaximumComponentLength,
+ NULL, //__out_opt LPDWORD lpFileSystemFlags,
+ NULL, //__out LPTSTR lpFileSystemNameBuffer,
+ 0)) //__in DWORD nFileSystemNameSize
+ return 0;
+
+ return volumeSerial;
+}
+
+
+const DllFun<findplus::OpenDirFunc> openDir (findplus::getDllName(), findplus::openDirFuncName ); //
+const DllFun<findplus::ReadDirFunc> readDir (findplus::getDllName(), findplus::readDirFuncName ); //load at startup: avoid pre C++11 static initialization MT issues
+const DllFun<findplus::CloseDirFunc> closeDir(findplus::getDllName(), findplus::closeDirFuncName); //
+
+
/*
-warn_static("finish")
- DllFun<findplus::OpenDirFunc> openDir (findplus::getDllName(), findplus::openDirFuncName);
- DllFun<findplus::ReadDirFunc> readDir (findplus::getDllName(), findplus::readDirFuncName);
- DllFun<findplus::CloseDirFunc> closeDir(findplus::getDllName(), findplus::closeDirFuncName);
- -> thread safety!
-*/
-#endif
+Common C-style interface for Win32 FindFirstFile(), FindNextFile() and FileFilePlus openDir(), closeDir():
+struct X //see "policy based design"
+{
+typedef ... Handle;
+typedef ... FindData;
+static Handle create(const Zstring& directoryPf, FindData& fileInfo); //throw FileError
+static void destroy(Handle hnd); //throw()
+static bool next(Handle hnd, const Zstring& directory, WIN32_FIND_DATA& fileInfo) //throw FileError
+
+//helper routines
+static void extractFileInfo (const FindData& fileInfo, const DWORD* volumeSerial, TraverseCallback::FileInfo& output);
+static Int64 getModTime (const FindData& fileInfo);
+static const FILETIME& getModTimeRaw (const FindData& fileInfo); //yet another concession to DST hack
+static const FILETIME& getCreateTimeRaw(const FindData& fileInfo); //
+static const wchar_t* getShortName (const FindData& fileInfo);
+static bool isDirectory (const FindData& fileInfo);
+static bool isSymlink (const FindData& fileInfo);
}
+Note: Win32 FindFirstFile(), FindNextFile() is a weaker abstraction than FileFilePlus openDir(), readDir(), closeDir() and Unix opendir(), closedir(), stat(),
+ so unfortunately we have to use former as a greatest common divisor
+*/
-class DirTraverser
+
+struct Win32Traverser
{
-public:
- DirTraverser(const Zstring& baseDirectory, bool followSymlinks, zen::TraverseCallback& sink, zen::DstHackCallback* dstCallback) :
-#ifdef FFS_WIN
- isFatFileSystem(dst::isFatDrive(baseDirectory)),
-#endif
- followSymlinks_(followSymlinks)
+ typedef HANDLE Handle;
+ typedef WIN32_FIND_DATA FindData;
+
+ static Handle create(const Zstring& directory, FindData& fileInfo) //throw FileError
{
-#ifdef FFS_WIN
- //format base directory name
- const Zstring& directoryFormatted = baseDirectory;
+ const Zstring& directoryPf = endsWith(directory, FILE_NAME_SEPARATOR) ?
+ directory :
+ directory + FILE_NAME_SEPARATOR;
-#elif defined FFS_LINUX
- const Zstring directoryFormatted = //remove trailing slash
- baseDirectory.size() > 1 && endsWith(baseDirectory, FILE_NAME_SEPARATOR) ? //exception: allow '/'
- beforeLast(baseDirectory, FILE_NAME_SEPARATOR) :
- baseDirectory;
-#endif
+ HANDLE output = ::FindFirstFile(applyLongPathPrefix(directoryPf + L'*').c_str(), &fileInfo);
+ //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH
+ if (output == INVALID_HANDLE_VALUE)
+ throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted());
+ //::GetLastError() == ERROR_FILE_NOT_FOUND -> actually NOT okay, even for an empty directory this should not occur (., ..)
+ return output;
+ }
- //traverse directories
- traverse(directoryFormatted, sink, 0);
+ static void destroy(Handle hnd) { ::FindClose(hnd); } //throw()
- //apply daylight saving time hack AFTER file traversing, to give separate feedback to user
-#ifdef FFS_WIN
- if (isFatFileSystem && dstCallback)
- applyDstHack(*dstCallback);
-#endif
+ static bool next(Handle hnd, const Zstring& directory, FindData& fileInfo) //throw FileError
+ {
+ if (!::FindNextFile(hnd, &fileInfo))
+ {
+ if (::GetLastError() == ERROR_NO_MORE_FILES) //not an error situation
+ return false;
+ //else we have a problem... report it:
+ throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted());
+ }
+ return true;
}
-private:
- DirTraverser(const DirTraverser&);
- DirTraverser& operator=(const DirTraverser&);
+ //helper routines
+ template <class FindData>
+ static void extractFileInfo(const FindData& fileInfo, const DWORD* volumeSerial, TraverseCallback::FileInfo& output)
+ {
+ output.lastWriteTimeRaw = getModTime(fileInfo);
+ output.fileSize = UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
+ }
- void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level)
+ template <class FindData>
+ static Int64 getModTime(const FindData& fileInfo) { return toTimeT(fileInfo.ftLastWriteTime); }
+
+ template <class FindData>
+ static const FILETIME& getModTimeRaw(const FindData& fileInfo) { return fileInfo.ftLastWriteTime; }
+
+ template <class FindData>
+ static const FILETIME& getCreateTimeRaw(const FindData& fileInfo) { return fileInfo.ftCreationTime; }
+
+ template <class FindData>
+ static const wchar_t* getShortName(const FindData& fileInfo) { return fileInfo.cFileName; }
+
+ template <class FindData>
+ static bool isDirectory(const FindData& fileInfo) { return (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
+
+ template <class FindData>
+ static bool isSymlink(const FindData& fileInfo) { return (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }
+};
+
+
+struct FilePlusTraverser
+{
+ typedef findplus::FindHandle Handle;
+ typedef findplus::FileInformation FindData;
+
+ static Handle create(const Zstring& directory, FindData& fileInfo) //throw FileError
{
- tryReportingError([&](std::wstring& errorMsg) -> bool
+ Handle output = ::openDir(applyLongPathPrefix(directory).c_str());
+ if (output == NULL)
+ throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted());
+
+ bool rv = next(output, directory, fileInfo); //throw FileError
+ if (!rv) //we expect at least two successful reads, even for an empty directory: ., ..
+ throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted(ERROR_NO_MORE_FILES));
+
+ return output;
+ }
+
+ static void destroy(Handle hnd) { ::closeDir(hnd); } //throw()
+
+ static bool next(Handle hnd, const Zstring& directory, FindData& fileInfo) //throw FileError
+ {
+ if (!::readDir(hnd, fileInfo))
{
- if (level == 100) //notify endless recursion
- {
- errorMsg = _("Endless loop when traversing directory:") + L"\n\"" + directory + L"\"";
+ if (::GetLastError() == ERROR_NO_MORE_FILES) //not an error situation
return false;
- }
- return true;
- }, sink);
+ //else we have a problem... report it:
+ throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted());
+ }
+ return true;
+ }
-#ifdef FFS_WIN
- /*
- //ensure directoryPf ends with backslash
- const Zstring& directoryPf = directory.EndsWith(FILE_NAME_SEPARATOR) ?
- directory :
- directory + FILE_NAME_SEPARATOR;
-
- FindHandle searchHandle = NULL;
- tryReportingError([&](std::wstring& errorMsg) -> bool
- {
- searchHandle = this->openDir(applyLongPathPrefix(directoryPf).c_str());
- //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH
+ //helper routines
+ template <class FindData>
+ static void extractFileInfo(const FindData& fileInfo, const DWORD* volumeSerial, TraverseCallback::FileInfo& output)
+ {
+ output.fileSize = UInt64(fileInfo.fileSize.QuadPart);
+ output.lastWriteTimeRaw = getModTime(fileInfo);
+ if (volumeSerial)
+ output.id = extractFileID(*volumeSerial, fileInfo.fileId);
+ }
- if (searchHandle == NULL)
- {
- //const DWORD lastError = ::GetLastError();
- //if (lastError == ERROR_FILE_NOT_FOUND) -> actually NOT okay, even for an empty directory this should not occur (., ..)
- //return true; //fine: empty directory
+ template <class FindData>
+ static Int64 getModTime(const FindData& fileInfo) { return toTimeT(fileInfo.lastWriteTime); }
- //else: we have a problem... report it:
- errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted();
- return false;
- }
- return true;
- }, sink);
+ template <class FindData>
+ static const FILETIME& getModTimeRaw(const FindData& fileInfo) { return fileInfo.lastWriteTime; }
- if (searchHandle == NULL)
- return; //empty dir or ignore error
- ZEN_ON_BLOCK_EXIT(this->closeDir(searchHandle));
+ template <class FindData>
+ static const FILETIME& getCreateTimeRaw(const FindData& fileInfo) { return fileInfo.creationTime; }
- FileInformation fileInfo = {};
- for (;;)
- {
- bool moreData = false;
- tryReportingError([&](std::wstring& errorMsg) -> bool
- {
- if (!this->readDir(searchHandle, fileInfo))
- {
- if (::GetLastError() == ERROR_NO_MORE_FILES) //this is fine
- return true;
-
- //else we have a problem... report it:
- errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted();
- return false;
- }
-
- moreData = true;
- return true;
- }, sink);
- if (!moreData) //no more items or ignore error
- return;
-
-
- //don't return "." and ".."
- const Zchar* const shortName = fileInfo.shortName;
- if (shortName[0] == L'.' &&
- (shortName[1] == L'\0' || (shortName[1] == L'.' && shortName[2] == L'\0')))
- continue;
+ template <class FindData>
+ static const wchar_t* getShortName(const FindData& fileInfo) { return fileInfo.shortName; }
- const Zstring& fullName = directoryPf + shortName;
+ template <class FindData>
+ static bool isDirectory(const FindData& fileInfo) { return (fileInfo.fileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
- const bool isSymbolicLink = (fileInfo.fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+ template <class FindData>
+ static bool isSymlink(const FindData& fileInfo) { return (fileInfo.fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }
+};
- if (isSymbolicLink && !followSymlinks_) //evaluate symlink directly
- {
- TraverseCallback::SymlinkInfo details;
- try
- {
- details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError
- }
- catch (FileError& e)
- {
- (void)e;
- #ifndef NDEBUG //show broken symlink / access errors in debug build!
- sink.onError(e.msg());
- #endif
- }
-
- details.lastWriteTimeRaw = toTimeT(fileInfo.lastWriteTime);
- details.dirLink = (fileInfo.fileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; //directory symlinks have this flag on Windows
- sink.onSymlink(shortName, fullName, details);
- }
- else if (fileInfo.fileAttributes & FILE_ATTRIBUTE_DIRECTORY) //a directory... or symlink that needs to be followed (for directory symlinks this flag is set too!)
- {
- const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName);
- if (rv)
- traverse<followSymlinks_>(fullName, *rv, level + 1);
- }
- else //a file or symlink that is followed...
- {
- TraverseCallback::FileInfo details;
-
- if (isSymbolicLink) //dereference symlinks!
- {
- if (!setWin32FileInformationFromSymlink(fullName, details))
- {
- //broken symlink...
- details.lastWriteTimeRaw = 0; //we are not interested in the modification time of the link
- details.fileSize = 0U;
- }
- }
- else
- {
- //####################################### DST hack ###########################################
- if (isFatFileSystem)
- {
- const dst::RawTime rawTime(fileInfo.creationTime, fileInfo.lastWriteTime);
-
- if (dst::fatHasUtcEncoded(rawTime)) //throw (std::runtime_error)
- fileInfo.lastWriteTime = dst::fatDecodeUtcTime(rawTime); //return real UTC time; throw (std::runtime_error)
- else
- markForDstHack.push_back(std::make_pair(fullName, fileInfo.lastWriteTime));
- }
- //####################################### DST hack ###########################################
-
- details.lastWriteTimeRaw = toTimeT(fileInfo.lastWriteTime);
- details.fileSize = fileInfo.fileSize.QuadPart;
- }
-
- sink.onFile(shortName, fullName, details);
- }
- }
- */
+class DirTraverser
+{
+public:
+ DirTraverser(const Zstring& baseDirectory, bool followSymlinks, zen::TraverseCallback& sink, zen::DstHackCallback* dstCallback) :
+ isFatFileSystem(dst::isFatDrive(baseDirectory)),
+ followSymlinks_(followSymlinks),
+ volumeSerial(retrieveVolumeSerial(baseDirectory)) //return 0 on error
+ {
+ try //traversing certain folders with restricted permissions requires this privilege! (but copying these files may still fail)
+ {
+ activatePrivilege(SE_BACKUP_NAME); //throw FileError
+ }
+ catch (...) {} //don't cause issues in user mode
+ if (::openDir && ::readDir && ::closeDir)
+ traverse<FilePlusTraverser>(baseDirectory, sink, 0);
+ else //fallback
+ traverse<Win32Traverser>(baseDirectory, sink, 0);
- //ensure directoryPf ends with backslash
- const Zstring& directoryPf = endsWith(directory, FILE_NAME_SEPARATOR) ?
- directory :
- directory + FILE_NAME_SEPARATOR;
- WIN32_FIND_DATA fileInfo = {};
+ //apply daylight saving time hack AFTER file traversing, to give separate feedback to user
+ if (dstCallback && isFatFileSystem)
+ applyDstHack(*dstCallback);
+ }
- HANDLE searchHandle = INVALID_HANDLE_VALUE;
- tryReportingError([&](std::wstring& errorMsg) -> bool
+private:
+ DirTraverser(const DirTraverser&);
+ DirTraverser& operator=(const DirTraverser&);
+
+ template <class Trav>
+ void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level)
+ {
+ tryReportingError([&]
{
- searchHandle = ::FindFirstFile(applyLongPathPrefix(directoryPf + L'*').c_str(), &fileInfo);
- //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH
+ if (level == 100) //notify endless recursion
+ throw FileError(_("Endless loop when traversing directory:") + L"\n\"" + directory + L"\"");
+ }, sink);
- if (searchHandle == INVALID_HANDLE_VALUE)
- {
- //const DWORD lastError = ::GetLastError();
- //if (lastError == ERROR_FILE_NOT_FOUND) -> actually NOT okay, even for an empty directory this should not occur (., ..)
- //return true; //fine: empty directory
+ typename Trav::FindData fileInfo = {};
- //else: we have a problem... report it:
- errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted();
- return false;
- }
- return true;
+ typename Trav::Handle searchHandle = 0;
+
+ tryReportingError([&]
+ {
+ typedef Trav Trav; //f u VS!
+ searchHandle = Trav::create(directory, fileInfo); //throw FileError
}, sink);
- if (searchHandle == INVALID_HANDLE_VALUE)
- return; //empty dir or ignore error
- ZEN_ON_BLOCK_EXIT(::FindClose(searchHandle));
+ if (searchHandle == 0)
+ return; //ignored error
+ ZEN_ON_BLOCK_EXIT(typedef Trav Trav; Trav::destroy(searchHandle));
do
{
//don't return "." and ".."
- const Zchar* const shortName = fileInfo.cFileName;
+ const Zchar* const shortName = Trav::getShortName(fileInfo);
if (shortName[0] == L'.' &&
(shortName[1] == L'\0' || (shortName[1] == L'.' && shortName[2] == L'\0')))
continue;
- const Zstring& fullName = directoryPf + shortName;
-
- const bool isSymbolicLink = (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+ const Zstring& fullName = endsWith(directory, FILE_NAME_SEPARATOR) ?
+ directory + shortName :
+ directory + FILE_NAME_SEPARATOR + shortName;
- if (isSymbolicLink && !followSymlinks_) //evaluate symlink directly
+ if (Trav::isSymlink(fileInfo) && !followSymlinks_) //evaluate symlink directly
{
TraverseCallback::SymlinkInfo details;
try
{
details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError
}
- catch (FileError& e)
- {
- (void)e;
-#ifndef NDEBUG //show broken symlink / access errors in debug build!
- sink.onError(e.toString());
+#ifdef NDEBUG //Release
+ catch (FileError&) {}
+#else
+ catch (FileError& e) { sink.onError(e.toString()); } //show broken symlink / access errors in debug build!
#endif
- }
- details.lastWriteTimeRaw = toTimeT(fileInfo.ftLastWriteTime);
- details.dirLink = (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; //directory symlinks have this flag on Windows
+ details.lastWriteTimeRaw = Trav::getModTime (fileInfo);
+ details.dirLink = Trav::isDirectory(fileInfo); //directory symlinks have this flag on Windows
sink.onSymlink(shortName, fullName, details);
}
- else if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //a directory... or symlink that needs to be followed (for directory symlinks this flag is set too!)
+ else if (Trav::isDirectory(fileInfo)) //a directory... or symlink that needs to be followed (for directory symlinks this flag is set too!)
{
const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName);
if (rv)
- traverse(fullName, *rv, level + 1);
+ traverse<Trav>(fullName, *rv, level + 1);
}
else //a file or symlink that is followed...
{
TraverseCallback::FileInfo details;
- if (isSymbolicLink) //dereference symlinks!
+ if (Trav::isSymlink(fileInfo)) //dereference symlinks!
{
- if (!setWin32FileInformationFromSymlink(fullName, details))
- {
- //broken symlink...
- details.lastWriteTimeRaw = 0; //we are not interested in the modification time of the link
- details.fileSize = 0U;
- }
+ extractFileInfoFromSymlink(fullName, details); //try to...
+ //keep details initial if symlink is broken
}
else
{
+ Trav::extractFileInfo(fileInfo, volumeSerial != 0 ? &volumeSerial : nullptr, details); //make optional character of volumeSerial explicit in the interface
+
//####################################### DST hack ###########################################
if (isFatFileSystem)
{
- const dst::RawTime rawTime(fileInfo.ftCreationTime, fileInfo.ftLastWriteTime);
+ const dst::RawTime rawTime(Trav::getCreateTimeRaw(fileInfo), Trav::getModTimeRaw(fileInfo));
if (dst::fatHasUtcEncoded(rawTime)) //throw (std::runtime_error)
- fileInfo.ftLastWriteTime = dst::fatDecodeUtcTime(rawTime); //return real UTC time; throw (std::runtime_error)
+ details.lastWriteTimeRaw = toTimeT(dst::fatDecodeUtcTime(rawTime)); //return real UTC time; throw (std::runtime_error)
else
- markForDstHack.push_back(std::make_pair(fullName, fileInfo.ftLastWriteTime));
+ markForDstHack.push_back(std::make_pair(fullName, Trav::getModTimeRaw(fileInfo)));
}
//####################################### DST hack ###########################################
- details.lastWriteTimeRaw = toTimeT(fileInfo.ftLastWriteTime);
- details.fileSize = zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
}
sink.onFile(shortName, fullName, details);
@@ -366,141 +387,18 @@ private:
{
bool moreData = false;
- tryReportingError([&](std::wstring& errorMsg) -> bool
+ typedef Trav Trav1; //f u VS!
+ tryReportingError([&]
{
- if (!::FindNextFile(searchHandle, // handle to search
- &fileInfo)) // pointer to structure for data on found file
- {
- if (::GetLastError() == ERROR_NO_MORE_FILES) //this is fine
- return true;
-
- //else we have a problem... report it:
- errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted();
- return false;
- }
-
- moreData = true;
- return true;
+ typedef Trav1 Trav; //f u VS!
+ moreData = Trav::next(searchHandle, directory, fileInfo); //throw FileError
}, sink);
return moreData;
}());
-
-#elif defined FFS_LINUX
- DIR* dirObj = NULL;
- if (!tryReportingError([&](std::wstring& errorMsg) -> bool
- {
- dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/"
- if (dirObj == NULL)
- {
- errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted();
- return false;
- }
- return true;
- }, sink))
- return;
- ZEN_ON_BLOCK_EXIT(::closedir(dirObj)); //never close NULL handles! -> crash
-
- while (true)
- {
- struct dirent* dirEntry = NULL;
- tryReportingError([&](std::wstring& errorMsg) -> bool
- {
- errno = 0; //set errno to 0 as unfortunately this isn't done when readdir() returns NULL because it can't find any files
- dirEntry = ::readdir(dirObj);
- if (dirEntry == NULL)
- {
- if (errno == 0)
- return true; //everything okay, not more items
-
- //else: we have a problem... report it:
- errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted();
- return false;
- }
- return true;
- }, sink);
- if (dirEntry == NULL) //no more items or ignore error
- return;
-
-
- //don't return "." and ".."
- const char* const shortName = dirEntry->d_name;
- if (shortName[0] == '.' &&
- (shortName[1] == '\0' || (shortName[1] == '.' && shortName[2] == '\0')))
- continue;
-
- const Zstring& fullName = endsWith(directory, FILE_NAME_SEPARATOR) ? //e.g. "/"
- directory + shortName :
- directory + FILE_NAME_SEPARATOR + shortName;
-
- struct stat fileInfo = {};
-
- if (!tryReportingError([&](std::wstring& errorMsg) -> bool
- {
- if (::lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks
- {
- errorMsg = _("Error reading file attributes:") + L"\n\"" + fullName + L"\"" + L"\n\n" + zen::getLastErrorFormatted();
- return false;
- }
- return true;
- }, sink))
- continue; //ignore error: skip file
-
- const bool isSymbolicLink = S_ISLNK(fileInfo.st_mode);
-
- if (isSymbolicLink)
- {
- if (followSymlinks_) //on Linux Symlinks need to be followed to evaluate whether they point to a file or directory
- {
- if (::stat(fullName.c_str(), &fileInfo) != 0) //stat() resolves symlinks
- {
- sink.onFile(shortName, fullName, TraverseCallback::FileInfo()); //report broken symlink as file!
- continue;
- }
- }
- else //evaluate symlink directly
- {
- TraverseCallback::SymlinkInfo details;
- try
- {
- details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError
- }
- catch (FileError& e)
- {
-#ifndef NDEBUG //show broken symlink / access errors in debug build!
- sink.onError(e.toString());
-#endif
- }
-
- details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second
- details.dirLink = ::stat(fullName.c_str(), &fileInfo) == 0 && S_ISDIR(fileInfo.st_mode); //S_ISDIR and S_ISLNK are mutually exclusive on Linux => need to follow link
- sink.onSymlink(shortName, fullName, details);
- continue;
- }
- }
-
- //fileInfo contains dereferenced data in any case from here on
-
- if (S_ISDIR(fileInfo.st_mode)) //a directory... cannot be a symlink on Linux in this case
- {
- const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName);
- if (rv)
- traverse(fullName, *rv, level + 1);
- }
- else //a file... (or symlink; pathological!)
- {
- TraverseCallback::FileInfo details;
- details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second
- details.fileSize = zen::UInt64(fileInfo.st_size);
-
- sink.onFile(shortName, fullName, details);
- }
- }
-#endif
}
-#ifdef FFS_WIN
//####################################### DST hack ###########################################
void applyDstHack(zen::DstHackCallback& dstCallback)
{
@@ -517,7 +415,7 @@ private:
const dst::RawTime encodedTime = dst::fatEncodeUtcTime(i->second); //throw (std::runtime_error)
{
//may need to remove the readonly-attribute (e.g. FAT usb drives)
- FileUpdateHandle updateHandle(i->first, [ = ]()
+ FileUpdateHandle updateHandle(i->first, [=]()
{
return ::CreateFile(zen::applyLongPathPrefix(i->first).c_str(),
GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp
@@ -571,20 +469,167 @@ private:
typedef std::vector<std::pair<Zstring, FILETIME> > FilenameTimeList;
FilenameTimeList markForDstHack;
//####################################### DST hack ###########################################
-#endif
+
const bool followSymlinks_;
+ const DWORD volumeSerial; //may be 0!
};
-void zen::traverseFolder(const Zstring& directory, bool followSymlinks, TraverseCallback& sink, DstHackCallback* dstCallback)
+#elif defined FFS_LINUX
+class DirTraverser
{
-#ifdef FFS_WIN
- try //traversing certain folders with restricted permissions requires this privilege! (but copying these files may still fail)
+public:
+ DirTraverser(const Zstring& baseDirectory, bool followSymlinks, zen::TraverseCallback& sink, zen::DstHackCallback* dstCallback) :
+ followSymlinks_(followSymlinks)
{
- zen::Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError
+ const Zstring directoryFormatted = //remove trailing slash
+ baseDirectory.size() > 1 && endsWith(baseDirectory, FILE_NAME_SEPARATOR) ? //exception: allow '/'
+ beforeLast(baseDirectory, FILE_NAME_SEPARATOR) :
+ baseDirectory;
+
+ /* quote: "Since POSIX.1 does not specify the size of the d_name field, and other nonstandard fields may precede
+ that field within the dirent structure, portable applications that use readdir_r() should allocate
+ the buffer whose address is passed in entry as follows:
+ len = offsetof(struct dirent, d_name) + pathconf(dirpath, _PC_NAME_MAX) + 1
+ entryp = malloc(len); */
+ const long maxPath = std::max<long>(::pathconf(directoryFormatted.c_str(), _PC_NAME_MAX), 10000); //::pathconf may return -1
+ buffer.resize(offsetof(struct ::dirent, d_name) + maxPath + 1);
+
+ traverse(directoryFormatted, sink, 0);
}
- catch (...) {} //don't cause issues in user mode
+
+private:
+ DirTraverser(const DirTraverser&);
+ DirTraverser& operator=(const DirTraverser&);
+
+ void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level)
+ {
+ tryReportingError([&]
+ {
+ if (level == 100) //notify endless recursion
+ throw FileError(_("Endless loop when traversing directory:") + L"\n\"" + directory + L"\"");
+ }, sink);
+
+
+ DIR* dirObj = NULL;
+ tryReportingError([&]
+ {
+ dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/"
+ if (dirObj == NULL)
+ throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted());
+ }, sink);
+
+ if (dirObj == NULL)
+ return; //ignored error
+ ZEN_ON_BLOCK_EXIT(::closedir(dirObj)); //never close NULL handles! -> crash
+
+ while (true)
+ {
+ struct ::dirent* dirEntry = NULL;
+ tryReportingError([&]
+ {
+ if (::readdir_r(dirObj, reinterpret_cast< ::dirent*>(&buffer[0]), &dirEntry) != 0)
+ throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted());
+ }, sink);
+ if (dirEntry == NULL) //no more items or ignore error
+ return;
+
+
+ //don't return "." and ".."
+ const char* const shortName = dirEntry->d_name; //evaluate dirEntry *before* going into recursion => we use a single "buffer"!
+ if (shortName[0] == '.' &&
+ (shortName[1] == '\0' || (shortName[1] == '.' && shortName[2] == '\0')))
+ continue;
+
+ const Zstring& fullName = endsWith(directory, FILE_NAME_SEPARATOR) ? //e.g. "/"
+ directory + shortName :
+ directory + FILE_NAME_SEPARATOR + shortName;
+
+ struct ::stat fileInfo = {};
+ bool haveData = false;
+ tryReportingError([&]
+ {
+ if (::lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks
+ throw FileError(_("Error reading file attributes:") + L"\n\"" + fullName + L"\"" + L"\n\n" + zen::getLastErrorFormatted());
+ haveData = true;
+ }, sink);
+ if (!haveData)
+ continue; //ignore error: skip file
+
+ if (S_ISLNK(fileInfo.st_mode))
+ {
+ if (followSymlinks_) //on Linux Symlinks need to be followed to evaluate whether they point to a file or directory
+ {
+ if (::stat(fullName.c_str(), &fileInfo) != 0) //stat() resolves symlinks
+ {
+ sink.onFile(shortName, fullName, TraverseCallback::FileInfo()); //report broken symlink as file!
+ continue;
+ }
+
+ fileInfo.st_dev = 0; //id from dereferenced symlink is problematic, since renaming will consider the link, not the target!
+ fileInfo.st_ino = 0; //
+ }
+ else //evaluate symlink directly
+ {
+ TraverseCallback::SymlinkInfo details;
+ try
+ {
+ details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError
+ }
+ catch (FileError& e)
+ {
+#ifndef NDEBUG //show broken symlink / access errors in debug build!
+ sink.onError(e.toString());
#endif
+ }
+
+ details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second
+ details.dirLink = ::stat(fullName.c_str(), &fileInfo) == 0 && S_ISDIR(fileInfo.st_mode);
+ //S_ISDIR and S_ISLNK are mutually exclusive on Linux => explicitly need to follow link
+ sink.onSymlink(shortName, fullName, details);
+ continue;
+ }
+ }
+
+ //fileInfo contains dereferenced data in any case from here on
+
+ if (S_ISDIR(fileInfo.st_mode)) //a directory... cannot be a symlink on Linux in this case
+ {
+ const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName);
+ if (rv)
+ traverse(fullName, *rv, level + 1);
+ }
+ else //a file... (or symlink; pathological!)
+ {
+ TraverseCallback::FileInfo details;
+ details.fileSize = zen::UInt64(fileInfo.st_size);
+ details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time (time_t format); unit: 1 second
+ details.id = extractFileID(fileInfo);
+
+ sink.onFile(shortName, fullName, details);
+ }
+ }
+ }
+ std::vector<char> buffer;
+ const bool followSymlinks_;
+};
+#endif
+}
+
+
+void zen::traverseFolder(const Zstring& directory, bool followSymlinks, TraverseCallback& sink, DstHackCallback* dstCallback)
+{
DirTraverser(directory, followSymlinks, sink, dstCallback);
}
+
+
+bool zen::supportForFileId() //Linux: always; Windows: if FindFilePlus_Win32.dll was loaded correctly
+{
+#ifdef FFS_WIN
+ return ::openDir && ::readDir && ::closeDir;
+
+#elif defined FFS_LINUX
+ return true;
+#endif
+}
diff --git a/zen/file_traverser.h b/zen/file_traverser.h
index 3f4f47d5..075c32e5 100644
--- a/zen/file_traverser.h
+++ b/zen/file_traverser.h
@@ -10,6 +10,8 @@
#include <memory>
#include "zstring.h"
#include "int64.h"
+#include "file_id_def.h"
+
//advanced file traverser returning metadata and hierarchical information on files and directories
@@ -24,6 +26,7 @@ public:
{
UInt64 fileSize; //unit: bytes!
Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC
+ FileId id; //optional: may be initial!
};
struct SymlinkInfo
@@ -67,6 +70,10 @@ void traverseFolder(const Zstring& directory, //throw();
//followSymlinks:
//"true": Symlinks dereferenced and reported via onFile() and onDir() => onSymlink not used!
//"false": Symlinks directly reported via onSymlink(), directory symlinks are not followed
+
+
+//determine whether FileId can be expected to be retrieved
+bool supportForFileId(); //Linux: always; Windows: if FindFilePlus_Win32.dll was loaded correctly
}
#endif // FILETRAVERSER_H_INCLUDED
diff --git a/zen/guid.h b/zen/guid.h
index 218c80a5..f9f497b2 100644
--- a/zen/guid.h
+++ b/zen/guid.h
@@ -10,7 +10,7 @@
#include <string>
#include <boost/uuid/uuid.hpp>
-#ifdef __MINGW32__ //boost should start and clean up!
+#ifdef __MINGW32__ //boost should start cleaning this mess up
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wuninitialized"
diff --git a/zen/int64.h b/zen/int64.h
index e8a9cbe0..91e24437 100644
--- a/zen/int64.h
+++ b/zen/int64.h
@@ -56,7 +56,7 @@ public:
value(rhs) {} //-> std::int64_t equals long int on x64 Linux! Still we want implicit behavior for all other systems!
//unsafe explicit but checked conversion from arbitrary integer type
- template <class T> explicit Int64(T rhs) : value(rhs) { checkRange<std::int64_t>(rhs); }
+ template <class T> explicit Int64(T rhs) : value(static_cast<std::int64_t>(rhs)) { checkRange<std::int64_t>(rhs); }
Int64& operator=(const Int64& rhs) { value = rhs.value; return *this; }
@@ -135,7 +135,7 @@ public:
value(rhs) {} //-> std::uint64_t equals unsigned long int on x64 Linux! Still we want implicit behavior for all other systems!
//unsafe explicit but checked conversion from arbitrary integer type
- template <class T> explicit UInt64(T rhs) : value(rhs) { checkRange<std::uint64_t>(rhs); }
+ template <class T> explicit UInt64(T rhs) : value(static_cast<std::uint64_t>(rhs)) { checkRange<std::uint64_t>(rhs); }
UInt64& operator=(const UInt64& rhs) { value = rhs.value; return *this; }
diff --git a/zen/long_path_prefix.h b/zen/long_path_prefix.h
index 1d9213d1..d03409e1 100644
--- a/zen/long_path_prefix.h
+++ b/zen/long_path_prefix.h
@@ -7,6 +7,7 @@
#ifndef LONGPATHPREFIX_H_INCLUDED
#define LONGPATHPREFIX_H_INCLUDED
+#include "win.h"
#include "zstring.h"
namespace zen
diff --git a/zen/notify_removal.cpp b/zen/notify_removal.cpp
index 8d8eeb90..2b6b9003 100644
--- a/zen/notify_removal.cpp
+++ b/zen/notify_removal.cpp
@@ -74,11 +74,10 @@ private:
const wchar_t MessageProvider::WINDOW_NAME[] = L"E6AD5EB1-527B-4EEF-AC75-27883B233380"; //random name
-LRESULT CALLBACK topWndProc(
- HWND hwnd, //handle to window
- UINT uMsg, //message identifier
- WPARAM wParam, //first message parameter
- LPARAM lParam) //second message parameter
+LRESULT CALLBACK topWndProc(HWND hwnd, //handle to window
+ UINT uMsg, //message identifier
+ WPARAM wParam, //first message parameter
+ LPARAM lParam) //second message parameter
{
if (messageProviderConstructed) //attention: this callback is triggered in the middle of singleton construction! It is a bad idea to to call back at this time!
try
@@ -110,18 +109,17 @@ MessageProvider::MessageProvider() :
zen::ScopeGuard guardClass = zen::makeGuard([&]() { ::UnregisterClass(WINDOW_NAME, process); });
//create dummy-window
- windowHandle = ::CreateWindow(
- WINDOW_NAME, //LPCTSTR lpClassName OR ATOM in low-order word!
- NULL, //LPCTSTR lpWindowName,
- 0, //DWORD dwStyle,
- 0, //int x,
- 0, //int y,
- 0, //int nWidth,
- 0, //int nHeight,
- 0, //note: we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)!
- NULL, //HMENU hMenu,
- process, //HINSTANCE hInstance,
- NULL); //LPVOID lpParam
+ windowHandle = ::CreateWindow(WINDOW_NAME, //LPCTSTR lpClassName OR ATOM in low-order word!
+ NULL, //LPCTSTR lpWindowName,
+ 0, //DWORD dwStyle,
+ 0, //int x,
+ 0, //int y,
+ 0, //int nWidth,
+ 0, //int nHeight,
+ 0, //note: we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)!
+ NULL, //HMENU hMenu,
+ process, //HINSTANCE hInstance,
+ NULL); //LPVOID lpParam
if (windowHandle == NULL)
throw zen::FileError(std::wstring(L"Could not start monitoring window notifications:") + L"\n\n" + getLastErrorFormatted() + L" (CreateWindow)");
@@ -160,17 +158,16 @@ public:
filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
filter.dbch_handle = hDir;
- hNotification = ::RegisterDeviceNotification(
- MessageProvider::instance().getWnd(), //__in HANDLE hRecipient,
- &filter, //__in LPVOID NotificationFilter,
- DEVICE_NOTIFY_WINDOW_HANDLE); //__in DWORD Flags
+ hNotification = ::RegisterDeviceNotification(MessageProvider::instance().getWnd(), //__in HANDLE hRecipient,
+ &filter, //__in LPVOID NotificationFilter,
+ DEVICE_NOTIFY_WINDOW_HANDLE); //__in DWORD Flags
if (hNotification == NULL)
{
const DWORD lastError = ::GetLastError();
if (lastError != ERROR_CALL_NOT_IMPLEMENTED && //fail on SAMBA share: this shouldn't be a showstopper!
lastError != ERROR_SERVICE_SPECIFIC_ERROR && //neither should be fail for "Pogoplug" mapped network drives
lastError != ERROR_INVALID_DATA) //this seems to happen for a NetDrive-mapped FTP server
- throw zen::FileError(std::wstring(L"Could not register device removal notifications:") + L"\n\n" + getLastErrorFormatted(lastError));
+ throw zen::FileError(L"Could not register device removal notifications:" L"\n\n" + getLastErrorFormatted(lastError));
}
}
diff --git a/zen/privilege.cpp b/zen/privilege.cpp
index 809202b7..6dd0b2d7 100644
--- a/zen/privilege.cpp
+++ b/zen/privilege.cpp
@@ -1,17 +1,15 @@
#include "privilege.h"
+#include <map>
+#include "thread.h" //includes <boost/thread.hpp>
+#include "zstring.h"
#include "scope_guard.h"
using namespace zen;
-Privileges& Privileges::getInstance()
+namespace
{
- static Privileges instance;
- return instance;
-}
-
-
-bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw FileError
+bool privilegeIsActive(LPCTSTR privilege) //throw FileError
{
HANDLE hToken = NULL;
if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle,
@@ -42,7 +40,7 @@ bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw FileError
}
-void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw FileError
+void setPrivilege(LPCTSTR privilege, bool enable) //throw FileError
{
HANDLE hToken = NULL;
if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle,
@@ -62,15 +60,67 @@ void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw FileError
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
- if (!::AdjustTokenPrivileges(
- hToken, //__in HANDLE TokenHandle,
- false, //__in BOOL DisableAllPrivileges,
- &tp, //__in_opt PTOKEN_PRIVILEGES NewState,
- 0, //__in DWORD BufferLength,
- NULL, //__out_opt PTOKEN_PRIVILEGES PreviousState,
- NULL)) //__out_opt PDWORD ReturnLength
+ if (!::AdjustTokenPrivileges(hToken, //__in HANDLE TokenHandle,
+ false, //__in BOOL DisableAllPrivileges,
+ &tp, //__in_opt PTOKEN_PRIVILEGES NewState,
+ 0, //__in DWORD BufferLength,
+ NULL, //__out_opt PTOKEN_PRIVILEGES PreviousState,
+ NULL)) //__out_opt PDWORD ReturnLength
throw FileError(_("Error setting privilege:") + L" \"" + privilege + L"\"" + L"\n\n" + getLastErrorFormatted());
if (::GetLastError() == ERROR_NOT_ALL_ASSIGNED) //check although previous function returned with success!
throw FileError(_("Error setting privilege:") + L" \"" + privilege + L"\"" + L"\n\n" + getLastErrorFormatted());
}
+
+
+class Privileges
+{
+public:
+ static Privileges& getInstance()
+ {
+ static Privileges inst;
+ return inst;
+ }
+
+ void ensureActive(LPCTSTR privilege) //throw FileError
+ {
+ if (activePrivileges.find(privilege) != activePrivileges.end())
+ return; //privilege already active
+
+ if (privilegeIsActive(privilege)) //privilege was already active before starting this tool
+ activePrivileges.insert(std::make_pair(privilege, false));
+ else
+ {
+ setPrivilege(privilege, true);
+ activePrivileges.insert(std::make_pair(privilege, true));
+ }
+ }
+
+private:
+ Privileges() {}
+ Privileges(Privileges&);
+ void operator=(Privileges&);
+
+ ~Privileges() //clean up: deactivate all privileges that have been activated by this application
+ {
+ for (auto iter = activePrivileges.begin(); iter != activePrivileges.end(); ++iter)
+ if (iter->second)
+ try
+ {
+ setPrivilege(iter->first.c_str(), false);
+ }
+ catch (...) {}
+ }
+
+ std::map<Zstring, bool> activePrivileges; //bool: enabled by this application
+};
+
+boost::mutex lockPrivileges;
+}
+
+
+void zen::activatePrivilege(LPCTSTR privilege) //throw FileError
+{
+ boost::lock_guard<boost::mutex> dummy(lockPrivileges);
+ Privileges::getInstance().ensureActive(privilege);
+}
diff --git a/zen/privilege.h b/zen/privilege.h
index 4545aac7..88fc8992 100644
--- a/zen/privilege.h
+++ b/zen/privilege.h
@@ -7,57 +7,12 @@
#ifndef PRIVILEGE_H_INCLUDED
#define PRIVILEGE_H_INCLUDED
-#include <map>
-#include "zstring.h"
#include "file_error.h"
#include "win.h" //includes "windows.h"
namespace zen
{
-#ifdef FFS_WIN
-class Privileges
-{
-public:
- static Privileges& getInstance();
-
- void ensureActive(LPCTSTR privilege) //throw FileError
- {
- if (activePrivileges.find(privilege) != activePrivileges.end())
- return; //privilege already active
-
- if (privilegeIsActive(privilege)) //privilege was already active before starting this tool
- activePrivileges.insert(std::make_pair(privilege, false));
- else
- {
- setPrivilege(privilege, true);
- activePrivileges.insert(std::make_pair(privilege, true));
- }
- }
-
-private:
- Privileges() {}
- Privileges(Privileges&);
- void operator=(Privileges&);
-
- ~Privileges() //clean up: deactivate all privileges that have been activated by this application
- {
- for (PrivBuffType::const_iterator i = activePrivileges.begin(); i != activePrivileges.end(); ++i)
- try
- {
- if (i->second)
- Privileges::setPrivilege(i->first.c_str(), false);
- }
- catch (...) {}
- }
-
- static bool privilegeIsActive(LPCTSTR privilege); //throw FileError
- static void setPrivilege(LPCTSTR privilege, bool enable); //throw FileError
-
- typedef std::map<Zstring, bool> PrivBuffType; //bool: enabled by this application
-
- PrivBuffType activePrivileges;
-};
-#endif
+void activatePrivilege(LPCTSTR privilege); //throw FileError; thread-safe!!!
}
diff --git a/zen/process_status.h b/zen/process_status.h
index cc5825aa..15266b28 100644
--- a/zen/process_status.h
+++ b/zen/process_status.h
@@ -3,29 +3,55 @@
#ifdef FFS_WIN
#include "win.h" //includes "windows.h"
+
+#elif defined FFS_LINUX
#endif
namespace zen
{
-struct DisableStandby //signal a "busy" state to the operating system
+struct PreventStandby //signal a "busy" state to the operating system
{
#ifdef FFS_WIN
- DisableStandby() { ::SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED /* | ES_AWAYMODE_REQUIRED*/ ); }
- ~DisableStandby() { ::SetThreadExecutionState(ES_CONTINUOUS); }
+ PreventStandby() { ::SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED /* | ES_AWAYMODE_REQUIRED*/ ); }
+ ~PreventStandby() { ::SetThreadExecutionState(ES_CONTINUOUS); }
#endif
};
+struct ScheduleForBackgroundProcessing //lower CPU and file I/O priorities
+{
+#ifdef FFS_WIN
#ifndef PROCESS_MODE_BACKGROUND_BEGIN
#define PROCESS_MODE_BACKGROUND_BEGIN 0x00100000 // Windows Server 2003 and Windows XP/2000: This value is not supported!
#define PROCESS_MODE_BACKGROUND_END 0x00200000 //
#endif
-struct ScheduleForBackgroundProcessing //lower CPU and file I/O priorities
-{
-#ifdef FFS_WIN
- ScheduleForBackgroundProcessing() { ::SetPriorityClass(::GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN); }
+ ScheduleForBackgroundProcessing() { ::SetPriorityClass(::GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN); } //this call lowers CPU priority, too!!
~ScheduleForBackgroundProcessing() { ::SetPriorityClass(::GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END); }
+
+#elif defined FFS_LINUX
+ /*
+ CPU prio:
+ int getpriority(PRIO_PROCESS, 0); - errno caveat!
+ int ::setpriority(PRIO_PROCESS, 0, int prio); //a zero value for "who" denotes the calling process
+
+ priority can be decreased, but NOT increased :(
+
+ file I/O prio:
+ ScheduleForBackgroundProcessing() : oldIoPrio(::ioprio_get(IOPRIO_WHO_PROCESS, ::getpid()))
+ {
+ if (oldIoPrio != -1)
+ ::ioprio_set(IOPRIO_WHO_PROCESS, ::getpid(), IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
+ }
+ ~ScheduleForBackgroundProcessing()
+ {
+ if (oldIoPrio != -1)
+ ::ioprio_set(IOPRIO_WHO_PROCESS, ::getpid(), oldIoPrio);
+ }
+
+ private:
+ const int oldIoPrio;
+ */
#endif
};
}
diff --git a/zen/stl_tools.h b/zen/stl_tools.h
index 1707a1eb..96101821 100644
--- a/zen/stl_tools.h
+++ b/zen/stl_tools.h
@@ -28,11 +28,11 @@ void map_remove_if(M& map, Predicate p);
template <class ForwardIterator, class T, typename Compare>
ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp);
-template<class BidirectionalIterator, class T>
+template <class BidirectionalIterator, class T>
BidirectionalIterator find_last(BidirectionalIterator first, BidirectionalIterator last, const T& value);
//replacement for std::find_end taking advantage of bidirectional iterators (and giving the algorithm a reasonable name)
-template<class BidirectionalIterator1, class BidirectionalIterator2>
+template <class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator1 search_last(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
BidirectionalIterator2 first2, BidirectionalIterator2 last2);
@@ -96,45 +96,47 @@ ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const
}
-template<class BidirectionalIterator, class T> inline
+template <class BidirectionalIterator, class T> inline
BidirectionalIterator find_last(const BidirectionalIterator first, BidirectionalIterator last, const T& value)
{
+ //reverse iteration: 1. check 2. decrement 3. evaluate
const BidirectionalIterator iterNotFound = last;
- do
+ for (;;) //VS 2010 doesn't like "while (true)"
{
if (last == first)
return iterNotFound;
--last;
+
+ if (*last == value)
+ return last;
}
- while (!(*last == value)); //loop over "last": 1. check 2. decrement 3. evaluate
- return last;
}
-template<class BidirectionalIterator1, class BidirectionalIterator2> inline
+template <class BidirectionalIterator1, class BidirectionalIterator2> inline
BidirectionalIterator1 search_last(const BidirectionalIterator1 first1, BidirectionalIterator1 last1,
const BidirectionalIterator2 first2, BidirectionalIterator2 last2)
{
- if (first1 == last1 ||
- first2 == last2)
- return last1;
-
- int diff = static_cast<int>(std::distance(first1, last1)) -
- static_cast<int>(std::distance(first2, last2));
-
const BidirectionalIterator1 iterNotFound = last1;
- --last2;
- while (diff-- >= 0) //loop over "last1": 1. check 2. decrement 3. evaluate
+ //reverse iteration: 1. check 2. decrement 3. evaluate
+ for (;;)
{
- --last1;
+ BidirectionalIterator1 it1 = last1;
+ BidirectionalIterator2 it2 = last2;
- BidirectionalIterator1 iter1 = last1;
- for (BidirectionalIterator2 iter2 = last2; *iter1 == *iter2; --iter1, --iter2)
- if (iter2 == first2)
- return iter1;
+ for (;;)
+ {
+ if (it2 == first2) return it1;
+ if (it1 == first1) return iterNotFound;
+
+ --it1;
+ --it2;
+
+ if (*it1 != *it2) break;
+ }
+ --last1;
}
- return iterNotFound;
}
}
diff --git a/zen/symlink_target.h b/zen/symlink_target.h
index 370a0c56..dfbbba6d 100644
--- a/zen/symlink_target.h
+++ b/zen/symlink_target.h
@@ -66,7 +66,7 @@ Zstring getSymlinkRawTargetString(const Zstring& linkPath) //throw FileError
try //reading certain symlinks/junctions requires admin rights! This shall not cause an error in user mode!
{
- Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError
+ activatePrivilege(SE_BACKUP_NAME); //throw FileError
}
catch (...) {}
diff --git a/zen/time.h b/zen/time.h
index f08f6ef8..6124d4d1 100644
--- a/zen/time.h
+++ b/zen/time.h
@@ -175,7 +175,10 @@ String formatTime(const String2& format, const TimeComp& comp, UserDefinedFormat
{
typedef typename GetCharType<String>::Result CharType;
- const struct std::tm& ctc = toClibTimeComponents(comp);
+ struct std::tm ctc = toClibTimeComponents(comp);
+ std::mktime (&ctc); // unfortunately std::strftime() needs all elements of "struct tm" filled, e.g. tm_wday, tm_yday
+ //note: although std::mktime() explicitly expects "local time", calculating weekday and day of year *should* be time-zone and DST independent
+
CharType buffer[256];
const size_t charsWritten = strftimeWrap(buffer, 256, strBegin(format), &ctc);
return String(buffer, charsWritten);
bgstack15