summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FreeFileSync/Build/Changelog.txt24
-rw-r--r--FreeFileSync/Build/Help/html/FreeFileSync.html18
-rw-r--r--FreeFileSync/Build/Help/html/Macros.html4
-rw-r--r--FreeFileSync/Build/Help/html/base.css14
-rw-r--r--FreeFileSync/Build/Help/html/external-applications.html27
-rw-r--r--FreeFileSync/Build/Help/html/tips-and-tricks.html78
-rw-r--r--FreeFileSync/Build/Help/images/add-folder-pair.pngbin7258 -> 6922 bytes
-rw-r--r--FreeFileSync/Build/Help/images/basic-step-choose-folders.pngbin3165 -> 2972 bytes
-rw-r--r--FreeFileSync/Build/Help/images/basic-step-compare.pngbin2900 -> 2823 bytes
-rw-r--r--FreeFileSync/Build/Help/images/basic-step-start-sync.pngbin2853 -> 2678 bytes
-rw-r--r--FreeFileSync/Build/Help/images/basic-step-sync-config.pngbin1951 -> 1936 bytes
-rw-r--r--FreeFileSync/Build/Help/images/com-settings-context.pngbin6210 -> 5983 bytes
-rw-r--r--FreeFileSync/Build/Help/images/comparison-settings.pngbin19034 -> 17442 bytes
-rw-r--r--FreeFileSync/Build/Help/images/comparison-variant-double-click.pngbin10744 -> 10180 bytes
-rw-r--r--FreeFileSync/Build/Help/images/config-double-click.pngbin10081 -> 9812 bytes
-rw-r--r--FreeFileSync/Build/Help/images/config-multiple-selection.pngbin10158 -> 9804 bytes
-rw-r--r--FreeFileSync/Build/Help/images/dialog-drag-move.pngbin11063 -> 10324 bytes
-rw-r--r--FreeFileSync/Build/Help/images/direct-synchronize.pngbin4871 -> 4705 bytes
-rw-r--r--FreeFileSync/Build/Help/images/filter-context.pngbin2997 -> 2893 bytes
-rw-r--r--FreeFileSync/Build/Help/images/gnome-scheduler.pngbin47924 -> 46979 bytes
-rw-r--r--FreeFileSync/Build/Help/images/ignore-time-shift.pngbin16458 -> 15113 bytes
-rw-r--r--FreeFileSync/Build/Help/images/main-window.pngbin49108 -> 45613 bytes
-rw-r--r--FreeFileSync/Build/Help/images/path-by-volume-name.pngbin2875 -> 2768 bytes
-rw-r--r--FreeFileSync/Build/Help/images/realtimesync-create-shortcut.pngbin7797 -> 6353 bytes
-rw-r--r--FreeFileSync/Build/Help/images/realtimesync-logo.pngbin6775 -> 5396 bytes
-rw-r--r--FreeFileSync/Build/Help/images/realtimesync-main-window.pngbin13099 -> 12197 bytes
-rw-r--r--FreeFileSync/Build/Help/images/realtimesync-monitor-usb.pngbin13141 -> 12382 bytes
-rw-r--r--FreeFileSync/Build/Help/images/realtimesync-schedule.pngbin12941 -> 8708 bytes
-rw-r--r--FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.pngbin11453 -> 10587 bytes
-rw-r--r--FreeFileSync/Build/Help/images/remove-local-settings.pngbin7088 -> 6908 bytes
-rw-r--r--FreeFileSync/Build/Help/images/sync-settings-context.pngbin4180 -> 4037 bytes
-rw-r--r--FreeFileSync/Build/Help/images/synchronization-variant-double-click.pngbin4261 -> 4033 bytes
-rw-r--r--FreeFileSync/Build/Help/images/two-folder-drop.pngbin8992 -> 8299 bytes
-rw-r--r--FreeFileSync/Build/Help/images/windows-scheduler.pngbin13906 -> 9166 bytes
-rw-r--r--FreeFileSync/Build/Help/images/xp-scheduler.pngbin19070 -> 18530 bytes
-rw-r--r--FreeFileSync/Build/Languages/arabic.lng39
-rw-r--r--FreeFileSync/Build/Languages/bulgarian.lng39
-rw-r--r--FreeFileSync/Build/Languages/chinese_simple.lng39
-rw-r--r--FreeFileSync/Build/Languages/chinese_traditional.lng39
-rw-r--r--FreeFileSync/Build/Languages/croatian.lng39
-rw-r--r--FreeFileSync/Build/Languages/czech.lng39
-rw-r--r--FreeFileSync/Build/Languages/danish.lng39
-rw-r--r--FreeFileSync/Build/Languages/dutch.lng39
-rw-r--r--FreeFileSync/Build/Languages/english_uk.lng39
-rw-r--r--FreeFileSync/Build/Languages/finnish.lng39
-rw-r--r--FreeFileSync/Build/Languages/french.lng39
-rw-r--r--FreeFileSync/Build/Languages/german.lng49
-rw-r--r--FreeFileSync/Build/Languages/greek.lng39
-rw-r--r--FreeFileSync/Build/Languages/hebrew.lng39
-rw-r--r--FreeFileSync/Build/Languages/hindi.lng39
-rw-r--r--FreeFileSync/Build/Languages/hungarian.lng39
-rw-r--r--FreeFileSync/Build/Languages/italian.lng39
-rw-r--r--FreeFileSync/Build/Languages/japanese.lng39
-rw-r--r--FreeFileSync/Build/Languages/korean.lng39
-rw-r--r--FreeFileSync/Build/Languages/lithuanian.lng39
-rw-r--r--FreeFileSync/Build/Languages/outdated/norwegian.lng16
-rw-r--r--FreeFileSync/Build/Languages/polish.lng39
-rw-r--r--FreeFileSync/Build/Languages/portuguese.lng39
-rw-r--r--FreeFileSync/Build/Languages/portuguese_br.lng39
-rw-r--r--FreeFileSync/Build/Languages/romanian.lng39
-rw-r--r--FreeFileSync/Build/Languages/russian.lng59
-rw-r--r--FreeFileSync/Build/Languages/serbian.lng39
-rw-r--r--FreeFileSync/Build/Languages/slovak.lng1805
-rw-r--r--FreeFileSync/Build/Languages/slovenian.lng39
-rw-r--r--FreeFileSync/Build/Languages/spanish.lng39
-rw-r--r--FreeFileSync/Build/Languages/swedish.lng39
-rw-r--r--FreeFileSync/Build/Languages/turkish.lng39
-rw-r--r--FreeFileSync/Build/Languages/ukrainian.lng39
-rw-r--r--FreeFileSync/Build/Resources.zipbin291282 -> 291954 bytes
-rw-r--r--FreeFileSync/Build/styles.gtk_rc8
-rw-r--r--FreeFileSync/Source/RealtimeSync/main_dlg.cpp2
-rw-r--r--FreeFileSync/Source/algorithm.cpp14
-rw-r--r--FreeFileSync/Source/algorithm.h4
-rw-r--r--FreeFileSync/Source/application.cpp7
-rw-r--r--FreeFileSync/Source/comparison.cpp8
-rw-r--r--FreeFileSync/Source/file_hierarchy.h2
-rw-r--r--FreeFileSync/Source/fs/abstract.cpp48
-rw-r--r--FreeFileSync/Source/fs/abstract.h49
-rw-r--r--FreeFileSync/Source/fs/native.cpp13
-rw-r--r--FreeFileSync/Source/lib/binary.cpp163
-rw-r--r--FreeFileSync/Source/lib/binary.h4
-rw-r--r--FreeFileSync/Source/lib/db_file.cpp53
-rw-r--r--FreeFileSync/Source/lib/db_file.h4
-rw-r--r--FreeFileSync/Source/lib/dir_exist_async.h4
-rw-r--r--FreeFileSync/Source/lib/dir_lock.cpp264
-rw-r--r--FreeFileSync/Source/lib/error_log.h4
-rw-r--r--FreeFileSync/Source/lib/ffs_paths.cpp36
-rw-r--r--FreeFileSync/Source/lib/ffs_paths.h2
-rw-r--r--FreeFileSync/Source/lib/generate_logfile.h60
-rw-r--r--FreeFileSync/Source/lib/help_provider.h16
-rw-r--r--FreeFileSync/Source/lib/icon_buffer.cpp6
-rw-r--r--FreeFileSync/Source/lib/localization.cpp7
-rw-r--r--FreeFileSync/Source/lib/parallel_scan.cpp6
-rw-r--r--FreeFileSync/Source/lib/parse_lng.h14
-rw-r--r--FreeFileSync/Source/lib/parse_plural.h2
-rw-r--r--FreeFileSync/Source/lib/process_xml.h2
-rw-r--r--FreeFileSync/Source/lib/resolve_path.cpp44
-rw-r--r--FreeFileSync/Source/lib/versioning.h2
-rw-r--r--FreeFileSync/Source/synchronization.cpp8
-rw-r--r--FreeFileSync/Source/ui/batch_config.cpp2
-rw-r--r--FreeFileSync/Source/ui/batch_status_handler.cpp6
-rw-r--r--FreeFileSync/Source/ui/custom_grid.cpp5
-rw-r--r--FreeFileSync/Source/ui/gui_generated.cpp269
-rw-r--r--FreeFileSync/Source/ui/gui_generated.h1
-rw-r--r--FreeFileSync/Source/ui/main_dlg.cpp153
-rw-r--r--FreeFileSync/Source/ui/progress_indicator.cpp3
-rw-r--r--FreeFileSync/Source/ui/small_dlgs.cpp12
-rw-r--r--FreeFileSync/Source/ui/sync_cfg.cpp26
-rw-r--r--FreeFileSync/Source/ui/tree_view.cpp2
-rw-r--r--FreeFileSync/Source/ui/version_check.cpp12
-rw-r--r--FreeFileSync/Source/version/version.h4
-rw-r--r--wx+/dc.h30
-rw-r--r--wx+/font_size.h43
-rw-r--r--wx+/graph.cpp2
-rw-r--r--wx+/grid.cpp2
-rw-r--r--wx+/image_resources.cpp12
-rw-r--r--wx+/image_tools.h5
-rw-r--r--wx+/popup_dlg_generated.cpp8
-rw-r--r--wx+/popup_dlg_generated.h2
-rw-r--r--zen/dir_watcher.cpp4
-rw-r--r--zen/file_access.cpp641
-rw-r--r--zen/file_access.h2
-rw-r--r--zen/file_io.cpp93
-rw-r--r--zen/file_io.h40
-rw-r--r--zen/file_traverser.cpp32
-rw-r--r--zen/format_unit.cpp4
-rw-r--r--zen/guid.h5
-rw-r--r--zen/i18n.h4
-rw-r--r--zen/long_path_prefix.h134
-rw-r--r--zen/scope_guard.h6
-rw-r--r--zen/serialize.h223
-rw-r--r--zen/shell_execute.h12
-rw-r--r--zen/string_base.h11
-rw-r--r--zen/string_tools.h41
-rw-r--r--zen/thread.h4
-rw-r--r--zen/win.h33
-rw-r--r--zen/xml_io.cpp46
-rw-r--r--zen/zstring.cpp120
138 files changed, 3980 insertions, 2155 deletions
diff --git a/FreeFileSync/Build/Changelog.txt b/FreeFileSync/Build/Changelog.txt
index 1d444704..510a754e 100644
--- a/FreeFileSync/Build/Changelog.txt
+++ b/FreeFileSync/Build/Changelog.txt
@@ -1,5 +1,27 @@
-FreeFileSync 7.9
+FreeFileSync 8.0
----------------
+Fine-tuned buffer sizes for 70% improved SFTP stream I/O speed
+Support incomplete read/write operations while maximizing buffer saturation
+Automatically check consistency of FreeFileSync installation
+Fixed crash when using SFTP on CPUs without SSE2 support
+Improved GUI responsiveness during SFTP I/O
+Disabled automatic quote substitution for file filter (OS X)
+Work around invalid parameter error on FAT drives for broken create times
+Avoid filter mismatches by using precomposed UTF (OS X)
+Fixed main dialog close button not being disabled during sync (OS X)
+Don't create AppleDouble files if extended attributes are unsupported (OS X)
+Set content format metadata when copying to an MTP device
+Fixed F-keys not working in sync config dialog (Linux)
+Revert to default button margin values (Linux)
+Fixed crash when thumbnail loading fails on MTP device
+Fixed main grids not scrolling in parallel during mouse selection
+Revert to default scaling for non-dpi-aware apps
+Integrate FreeFileSync online manual
+Added Slovak translation
+
+
+FreeFileSync 7.9 [2016-02-13]
+-----------------------------
New comparison variant: compare by file size
Buffer SFTP read/write accesses for optimal packet sizes
Configure folder access time out via GlobalSettings.xml
diff --git a/FreeFileSync/Build/Help/html/FreeFileSync.html b/FreeFileSync/Build/Help/html/FreeFileSync.html
index ffbe372a..e823f033 100644
--- a/FreeFileSync/Build/Help/html/FreeFileSync.html
+++ b/FreeFileSync/Build/Help/html/FreeFileSync.html
@@ -50,23 +50,5 @@
</div>
<div style="clear:both"></div>
<br>
-
- <h2>FreeFileSync Links</h2>
-
- <div class="box-outer"><div class="bluebox"><div class="box-inner">
- <b>Homepage:</b><br>
- <a target="_blank" href="http://www.freefilesync.org">http://www.freefilesync.org</a> - feedback, suggestions, bug-reports, official download<br>
- <br>
-
- <b>Support the project:</b><br>
- If you like FreeFileSync...
- <a target="_blank" href="http://www.freefilesync.org/donate.php">Donate with PayPal</a>
-
- <!-- for some inconceivable reason following image is not shown in chm file when not preloaded!!! -->
- <img style="width:0px; height:0px; visibility:hidden;" alt="Donate via PayPal" src="../images/donate.png">
-
- <a style="width: 65px; height:51px;display:inline-block;vertical-align:middle;background: url(../images/donate.png) no-repeat;"
- title="Donate via PayPal" target="_blank" href="http://www.freefilesync.org/donate.php"></a>
- </div></div></div>
</body>
</html> \ No newline at end of file
diff --git a/FreeFileSync/Build/Help/html/Macros.html b/FreeFileSync/Build/Help/html/Macros.html
index ea325880..6c4a0c4d 100644
--- a/FreeFileSync/Build/Help/html/Macros.html
+++ b/FreeFileSync/Build/Help/html/Macros.html
@@ -11,8 +11,8 @@
<p>
All directory paths may contain macros that are expanded during
- synchronization. Begin and end of each macro is marked by a <b>%</b> character. Besides special macros
- handling time and date, the <b>operating system's environment variables</b> can also be used.
+ synchronization. Begin and end of each macro are marked by a <b>%</b> character. In addition to special macros
+ handling time and date, the <b>operating system's environment variables</b> may also be used.
</p>
<br>
diff --git a/FreeFileSync/Build/Help/html/base.css b/FreeFileSync/Build/Help/html/base.css
index 980840ea..4a49e88e 100644
--- a/FreeFileSync/Build/Help/html/base.css
+++ b/FreeFileSync/Build/Help/html/base.css
@@ -77,4 +77,16 @@ table th
{
font-family: Consolas, Courier New, Courier, monospace;
text-align: left;
-} \ No newline at end of file
+}
+
+.separation_line
+{
+ border-bottom: 1px solid #AAA;
+ margin: 10px 0 20px 0;
+}
+
+.tip
+{
+ font-weight: bold;
+ margin-bottom: 5px;
+}
diff --git a/FreeFileSync/Build/Help/html/external-applications.html b/FreeFileSync/Build/Help/html/external-applications.html
index a4c6daad..ea2ed918 100644
--- a/FreeFileSync/Build/Help/html/external-applications.html
+++ b/FreeFileSync/Build/Help/html/external-applications.html
@@ -13,13 +13,17 @@
When you double-click on one of the rows on the main dialog, FreeFileSync opens the operating system's file browser
by default. On Windows it calls <span class="command-line">explorer /select, &quot;%item_path%&quot;</span>, on
Linux <span class="command-line">xdg-open &quot;%item_folder%&quot;</span> and on OS X <span class="command-line">open -R &quot;%item_path%&quot;</span>.
+ To customize this behavior and integrate other external applications into FreeFileSync,
+ navigate to <b>Menu &rarr; Tools &rarr; Options: Customize context menu</b> and add or replace a command.
</p>
-
+
+ <p>
+ The first entry will be executed when double-clicking a row on main grid or when pressing ENTER. All other entries can be accessed
+ quickly via the associated numeric keys or via the context menu shown after a right mouse click.
+ </p>
+
<p>
- You can customize this behavior and integrate other external applications into FreeFileSync:
- Navigate to <b>Menu &rarr; Tools &rarr; Options: Customize context menu</b>
- and add or replace a command. The first entry is executed when double-clicking a row on main grid or pressing ENTER while all other entries can be accessed via the
- context menu shown after a right mouse click. In addition to regular <a href="macros.html">Macros</a>, the following specific macros are available:
+ In addition to regular <a href="macros.html">Macros</a>, the following specific macros are available:
</p>
<div class="box-outer"><div class="greybox"><div class="box-inner">
@@ -30,11 +34,11 @@
</tr>
<tr>
<td><div class="command-line">%item_path%</div></td>
- <td>Full file or folder name</td>
+ <td>Full file or folder path</td>
</tr>
<tr>
<td><div class="command-line">%item_folder%</div></td>
- <td>Folder part only</td>
+ <td>Folder path only</td>
</tr>
<tr>
<td><div class="command-line">%item2_path%</div></td>
@@ -52,7 +56,7 @@
<h2>Examples:</h2>
<ul>
- <li>Start visual content comparison tool:<br>
+ <li>Start file content comparison (Diff) tool:<br>
<div class="command-line">&quot;C:\Program Files (x86)\WinMerge\WinMergeU.exe&quot; &quot;%item_path%&quot; &quot;%item2_path%&quot;</div><br>
<li>Show file in Windows Explorer:<br>
@@ -61,8 +65,11 @@
<li>Open file with associated application:<br>
<div class="command-line">&quot;%item_path%&quot;</div><br>
- <li>Open console for directory:<br>
- <div class="command-line">cmd /k cd /D &quot;%item_folder%&quot;</div>
+ <li>Open Command Prompt for selected item:<br>
+ <div class="command-line">cmd /k cd /D &quot;%item_folder%&quot;</div><br>
+
+ <li>Write list of selected file paths to a text file:<br>
+ <div class="command-line">cmd /c echo %item_path% >> %csidl_Desktop%\file_list.txt</div>
</ul>
<div class="box-outer"><div class="bluebox"><div class="box-inner">
diff --git a/FreeFileSync/Build/Help/html/tips-and-tricks.html b/FreeFileSync/Build/Help/html/tips-and-tricks.html
index 9376b208..0a196ea9 100644
--- a/FreeFileSync/Build/Help/html/tips-and-tricks.html
+++ b/FreeFileSync/Build/Help/html/tips-and-tricks.html
@@ -4,90 +4,108 @@
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="base.css" >
<title>Tips and Tricks</title>
-
- <style>
- .separation_line
- {
- border-bottom: 1px solid #AAA;
- margin: 10px 0 20px 0;
- }
-
- .tip
- {
- font-weight: bold;
- margin-bottom: 5px;
- }
- </style>
</head>
<body>
<h1>Tips and Tricks</h1>
- <div class="tip">Change settings with a single mouse click: Press and hold the right mouse button until the context menu is shown then release over the selection.</div>
+ <div class="tip" id="single-click-settings-change">
+ Change settings with a single mouse click: Press and hold the right mouse button until the context menu is shown then release while over the selection:
+ </div>
<img style="vertical-align: top;" src="../images/com-settings-context.png" alt="Comparison settings context menu">
<img style="vertical-align: top;" src="../images/filter-context.png" alt="Filter context menu">
<img style="vertical-align: top;" src="../images/sync-settings-context.png" alt="Synchronization settings context menu"><br>
<div class="separation_line"></div>
- <div class="tip">You can select multiple configurations at a time.</div>
+ <div class="tip" id="select-multiple-configurations">
+ Select multiple configurations at a time:
+ </div>
<img style="float:left; margin-right:10px" src="../images/config-multiple-selection.png" alt="Select multiple configurations">
Select a few items via mouse and refine the selection by holding the Control key while clicking.<br>
<div style="clear:both"></div>
<div class="separation_line"></div>
- <div class="tip">You can synchronize multiple folder pairs at a time.</div>
+ <div class="tip" id="sync-multiple-folders">
+ Synchronize multiple folder pairs at a time:
+ </div>
<img src="../images/add-folder-pair.png" alt="Add folder pair">
<div class="separation_line"></div>
- <div class="tip">You can start comparison directly by double-clicking on a configuration.</div>
+ <div class="tip" id="start-comparison-directly">
+ Start comparison directly by double-clicking on a configuration:
+ </div>
<img src="../images/config-double-click.png" alt="Double-click on configuration">
<div class="separation_line"></div>
- <div class="tip">You can start synchronization directly without clicking on compare first.</div>
+ <div class="tip" id="start-sync-directly">
+ Start synchronization directly without clicking on compare first:
+ </div>
<img src="../images/direct-synchronize.png" alt="Start synchronization directly">
<div class="separation_line"></div>
- <div class="tip">You can move a window by clicking on a free area and holding the mouse button.</div>
+ <div class="tip" id="mouse-window-drag">
+ Move a window by clicking on a free area and holding the mouse button:
+ </div>
<img src="../images/dialog-drag-move.png" alt="Move dialog via mouse">
<div class="separation_line"></div>
- <div class="tip">You can open a batch configuration without running it via the Windows Explorer context menu.</div>
+ <div class="tip" id="open-config-from-explorer">
+ Open a batch configuration for edit via the Windows Explorer context menu:
+ </div>
<img src="../images/explorer-context.png" alt="Explorer context menu">
<div class="separation_line"></div>
- <div class="tip">You can drag and drop two folders at a time from Windows Explorer to fill a folder pair in one go.</div>
+ <div class="tip" id="two-folder-drop">
+ Drag and drop two folders at a time from Windows Explorer to fill a folder pair in one go:
+ </div>
<img src="../images/two-folder-drop.png" alt="Two-folder drop">
<div class="separation_line"></div>
- <div class="tip">You can copy files selected on the main dialog to an alternate folder and thereby save a "diff".</div>
+ <div class="tip" id="copy-to-alternate-folder">
+ Copy files selected on the main dialog to an alternate folder and thereby save a "diff":
+ </div>
<img src="../images/copy-alternative-path.png" alt="Copy to alternative path">
<div class="separation_line"></div>
- <div class="tip">You can use a volume name instead of a drive letter.</div>
+ <div class="tip" id="variable-drive-letter">
+ Use a volume name instead of a drive letter:
+ </div>
<img src="../images/path-by-volume-name.png" alt="Drive letter by volume name">
<div class="separation_line"></div>
- <div class="tip">You can show thumbnail icons via the column header context menu.</div>
+ <div class="tip" id="show-thumbnails">
+ Show thumbnail icons via the column header context menu:
+ </div>
<img src="../images/show-thumbnails.png" alt="Show thumbnail icons">
<div class="separation_line"></div>
- <div class="tip">You can save the current view filter selection as default.</div>
+ <div class="tip" id="save-view-filter">
+ Save the current view filter selection as default:
+ </div>
<img src="../images/view-filter-default.png" alt="Save view filter settings">
<div class="separation_line"></div>
- <div class="tip">You can remove local settings from individual folder pairs.</div>
+ <div class="tip" id="remove-local-settings">
+ Remove local settings from individual folder pairs:
+ </div>
<img src="../images/remove-local-settings.png" alt="Remove local settings">
<div class="separation_line"></div>
- <div class="tip">You can remove obsolete paths from the folder drop-down list by pressing the Delete key.</div>
+ <div class="tip" id="remove-obsolete-paths">
+ Remove obsolete paths from the folder drop-down list by pressing the Delete key:
+ </div>
<img src="../images/remove-drop-down-path.png" alt="Remove drop-down path">
<div class="separation_line"></div>
- <div class="tip">You can select a time span for files to include via the date column context menu.</div>
+ <div class="tip" id="select-time-span">
+ Select a time span for files to include via the date column context menu:
+ </div>
<img src="../images/select-time-span.png" alt="Select time span">
<div class="separation_line"></div>
- <div class="tip">You can double-click on comparison and synchronization variants to confirm the dialog.</div>
+ <div class="tip" id="double-click-dialog-confirm">
+ Double-click on comparison and synchronization variants to confirm the dialog:
+ </div>
<img src="../images/comparison-variant-double-click.png" alt="Double-click comparison variant">
<img src="../images/synchronization-variant-double-click.png" alt="Double-click synchronization variant">
<br>
diff --git a/FreeFileSync/Build/Help/images/add-folder-pair.png b/FreeFileSync/Build/Help/images/add-folder-pair.png
index 049fcf6b..916447e8 100644
--- a/FreeFileSync/Build/Help/images/add-folder-pair.png
+++ b/FreeFileSync/Build/Help/images/add-folder-pair.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/basic-step-choose-folders.png b/FreeFileSync/Build/Help/images/basic-step-choose-folders.png
index deeceeff..27c897b2 100644
--- a/FreeFileSync/Build/Help/images/basic-step-choose-folders.png
+++ b/FreeFileSync/Build/Help/images/basic-step-choose-folders.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/basic-step-compare.png b/FreeFileSync/Build/Help/images/basic-step-compare.png
index 01095864..704fd4fa 100644
--- a/FreeFileSync/Build/Help/images/basic-step-compare.png
+++ b/FreeFileSync/Build/Help/images/basic-step-compare.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/basic-step-start-sync.png b/FreeFileSync/Build/Help/images/basic-step-start-sync.png
index f7574691..f7309bfc 100644
--- a/FreeFileSync/Build/Help/images/basic-step-start-sync.png
+++ b/FreeFileSync/Build/Help/images/basic-step-start-sync.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/basic-step-sync-config.png b/FreeFileSync/Build/Help/images/basic-step-sync-config.png
index 5895099c..6656c437 100644
--- a/FreeFileSync/Build/Help/images/basic-step-sync-config.png
+++ b/FreeFileSync/Build/Help/images/basic-step-sync-config.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/com-settings-context.png b/FreeFileSync/Build/Help/images/com-settings-context.png
index 75068d22..8024d4bf 100644
--- a/FreeFileSync/Build/Help/images/com-settings-context.png
+++ b/FreeFileSync/Build/Help/images/com-settings-context.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/comparison-settings.png b/FreeFileSync/Build/Help/images/comparison-settings.png
index c224dae4..4ea72934 100644
--- a/FreeFileSync/Build/Help/images/comparison-settings.png
+++ b/FreeFileSync/Build/Help/images/comparison-settings.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/comparison-variant-double-click.png b/FreeFileSync/Build/Help/images/comparison-variant-double-click.png
index 8fde4654..8af50d42 100644
--- a/FreeFileSync/Build/Help/images/comparison-variant-double-click.png
+++ b/FreeFileSync/Build/Help/images/comparison-variant-double-click.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/config-double-click.png b/FreeFileSync/Build/Help/images/config-double-click.png
index 6019e1db..54ec22d3 100644
--- a/FreeFileSync/Build/Help/images/config-double-click.png
+++ b/FreeFileSync/Build/Help/images/config-double-click.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/config-multiple-selection.png b/FreeFileSync/Build/Help/images/config-multiple-selection.png
index ea6907d0..8e26b523 100644
--- a/FreeFileSync/Build/Help/images/config-multiple-selection.png
+++ b/FreeFileSync/Build/Help/images/config-multiple-selection.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/dialog-drag-move.png b/FreeFileSync/Build/Help/images/dialog-drag-move.png
index df38ef4a..b1f9cda3 100644
--- a/FreeFileSync/Build/Help/images/dialog-drag-move.png
+++ b/FreeFileSync/Build/Help/images/dialog-drag-move.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/direct-synchronize.png b/FreeFileSync/Build/Help/images/direct-synchronize.png
index bdaa0bf1..f3fdbe1f 100644
--- a/FreeFileSync/Build/Help/images/direct-synchronize.png
+++ b/FreeFileSync/Build/Help/images/direct-synchronize.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/filter-context.png b/FreeFileSync/Build/Help/images/filter-context.png
index 3e31f2c6..94ce3237 100644
--- a/FreeFileSync/Build/Help/images/filter-context.png
+++ b/FreeFileSync/Build/Help/images/filter-context.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/gnome-scheduler.png b/FreeFileSync/Build/Help/images/gnome-scheduler.png
index 99ac0abe..fee122bd 100644
--- a/FreeFileSync/Build/Help/images/gnome-scheduler.png
+++ b/FreeFileSync/Build/Help/images/gnome-scheduler.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/ignore-time-shift.png b/FreeFileSync/Build/Help/images/ignore-time-shift.png
index 5dbeb0ae..4c19e893 100644
--- a/FreeFileSync/Build/Help/images/ignore-time-shift.png
+++ b/FreeFileSync/Build/Help/images/ignore-time-shift.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/main-window.png b/FreeFileSync/Build/Help/images/main-window.png
index 5fbbca9f..b4e5b034 100644
--- a/FreeFileSync/Build/Help/images/main-window.png
+++ b/FreeFileSync/Build/Help/images/main-window.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/path-by-volume-name.png b/FreeFileSync/Build/Help/images/path-by-volume-name.png
index 2e606e25..7b0ab2e9 100644
--- a/FreeFileSync/Build/Help/images/path-by-volume-name.png
+++ b/FreeFileSync/Build/Help/images/path-by-volume-name.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png b/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png
index 4df9413b..c0910bf7 100644
--- a/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png
+++ b/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/realtimesync-logo.png b/FreeFileSync/Build/Help/images/realtimesync-logo.png
index b5aba408..40ad9645 100644
--- a/FreeFileSync/Build/Help/images/realtimesync-logo.png
+++ b/FreeFileSync/Build/Help/images/realtimesync-logo.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/realtimesync-main-window.png b/FreeFileSync/Build/Help/images/realtimesync-main-window.png
index ded56422..326cda46 100644
--- a/FreeFileSync/Build/Help/images/realtimesync-main-window.png
+++ b/FreeFileSync/Build/Help/images/realtimesync-main-window.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png b/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png
index 0aadf3b6..68413b6e 100644
--- a/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png
+++ b/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/realtimesync-schedule.png b/FreeFileSync/Build/Help/images/realtimesync-schedule.png
index a964590d..cd67e71d 100644
--- a/FreeFileSync/Build/Help/images/realtimesync-schedule.png
+++ b/FreeFileSync/Build/Help/images/realtimesync-schedule.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png b/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png
index bcfc1da8..e089672f 100644
--- a/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png
+++ b/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/remove-local-settings.png b/FreeFileSync/Build/Help/images/remove-local-settings.png
index 6dfb9075..cccdcd2b 100644
--- a/FreeFileSync/Build/Help/images/remove-local-settings.png
+++ b/FreeFileSync/Build/Help/images/remove-local-settings.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/sync-settings-context.png b/FreeFileSync/Build/Help/images/sync-settings-context.png
index cf92e087..e6b3d924 100644
--- a/FreeFileSync/Build/Help/images/sync-settings-context.png
+++ b/FreeFileSync/Build/Help/images/sync-settings-context.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png b/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png
index 709ad67d..9e2597c7 100644
--- a/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png
+++ b/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/two-folder-drop.png b/FreeFileSync/Build/Help/images/two-folder-drop.png
index 7b3794af..81e1f12e 100644
--- a/FreeFileSync/Build/Help/images/two-folder-drop.png
+++ b/FreeFileSync/Build/Help/images/two-folder-drop.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/windows-scheduler.png b/FreeFileSync/Build/Help/images/windows-scheduler.png
index 09a6af1d..ff52b34a 100644
--- a/FreeFileSync/Build/Help/images/windows-scheduler.png
+++ b/FreeFileSync/Build/Help/images/windows-scheduler.png
Binary files differ
diff --git a/FreeFileSync/Build/Help/images/xp-scheduler.png b/FreeFileSync/Build/Help/images/xp-scheduler.png
index 27346809..6a643d78 100644
--- a/FreeFileSync/Build/Help/images/xp-scheduler.png
+++ b/FreeFileSync/Build/Help/images/xp-scheduler.png
Binary files differ
diff --git a/FreeFileSync/Build/Languages/arabic.lng b/FreeFileSync/Build/Languages/arabic.lng
index ab6214f9..8f522c4c 100644
--- a/FreeFileSync/Build/Languages/arabic.lng
+++ b/FreeFileSync/Build/Languages/arabic.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>تحديث السمات على اليسار</target>
-<source>Cannot read file %x.</source>
-<target>لا يمكن قراءة المل٠%x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>لا يمكن كتابة أذونات %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>العملية غير مدعومة لأنواع المجلدات مختلÙØ© الأساس.</target>
+
+<source>Cannot write file %x.</source>
+<target>لا يمكن كتابة المل٠%x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
الÙعلي: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>لا يمكن كتابة أذونات %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>العملية غير مدعومة لأنواع المجلدات مختلÙØ© الأساس.</target>
-
-<source>Cannot write file %x.</source>
-<target>لا يمكن كتابة المل٠%x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>لا يمكن نسخ الرابط الرمزي من %x إلى %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>تعذر Ùتح المل٠%x.</target>
+<source>Cannot read file %x.</source>
+<target>لا يمكن قراءة المل٠%x.</target>
+
<source>Cannot find device %x.</source>
<target>لا يمكن العثور على الجهاز %x.</target>
@@ -1659,8 +1659,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>تعذر الاتصال بـ www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>لم نستطع العثور على على رقم إصدار FreeFileSync على الشبكة. هل تريد التحقق يدوياً؟</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&تحقق</target>
@@ -1698,12 +1698,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>لا يمكن العثور على وظيÙØ© نظام %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>لا يمكن نسخ السمات من %x إلى %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>لا يمكن نسخ المل٠%x إلى %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>لا يمكن نسخ السمات من %x إلى %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>نوع العنصر %x غير مدعوم:</target>
@@ -1842,6 +1842,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>شكرا على تبرعك ودعمك !</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>مثبت FreeFileSync للمنبرعين هذا وصل حدود التثبيت. هل تريد تحميل النسخة الاعتيادة من الصÙحة الرئيسية لـ FreeFileSync الآن ØŸ</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/bulgarian.lng b/FreeFileSync/Build/Languages/bulgarian.lng
index 67909db9..96716838 100644
--- a/FreeFileSync/Build/Languages/bulgarian.lng
+++ b/FreeFileSync/Build/Languages/bulgarian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Ðктуализирай атрибутите на деÑÐ½Ð¸Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ‚</target>
-<source>Cannot read file %x.</source>
-<target>Ðе може да Ñе прочете файл %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Ðе могат да Ñе запишат правата за доÑтъп на %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>ОперациÑта не Ñе поддържа за различни типове оÑновни папки.</target>
+
+<source>Cannot write file %x.</source>
+<target>Ðе може да Ñе запише файл %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
ДейÑтвителни: %y байта
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Ðе могат да Ñе запишат правата за доÑтъп на %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>ОперациÑта не Ñе поддържа за различни типове оÑновни папки.</target>
-
-<source>Cannot write file %x.</source>
-<target>Ðе може да Ñе запише файл %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Ðе може да Ñе копира Ñимволната връзка %x в %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>Ðе може да Ñе отвори файл %x.</target>
+<source>Cannot read file %x.</source>
+<target>Ðе може да Ñе прочете файл %x.</target>
+
<source>Cannot find device %x.</source>
<target>Ðе е намерено уÑтройÑтво %x.</target>
@@ -1615,8 +1615,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>ÐÑма връзка ÑÑŠÑ www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Ðомера на текущата верÑÐ¸Ñ Ð½Ð° FreeFileSync не е открит онлайн. Ще опитате ли ръчно?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>Оп&итай</target>
@@ -1654,12 +1654,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>Ðе е намерена ÑиÑтемната Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Ðе могат да Ñе копират атрибутите от %x в %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Ðе може да Ñе копира файл %x в %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Ðе могат да Ñе копират атрибутите от %x в %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Типа на елемент %x не Ñе поддържа:</target>
@@ -1786,6 +1786,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>БлагодарноÑти за Вашите Ð´Ð°Ñ€ÐµÐ½Ð¸Ñ Ð¸ подкрепа!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Този FreeFileSync-инÑталатор за дарители изчерпа инÑÑ‚Ð°Ð»Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñи лимит. Ще Ñвалите ли регулÑрната верÑÐ¸Ñ Ð¾Ñ‚ Ñтраницата на FreeFileSync Ñега?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/chinese_simple.lng b/FreeFileSync/Build/Languages/chinese_simple.lng
index 0ca7d726..21f03125 100644
--- a/FreeFileSync/Build/Languages/chinese_simple.lng
+++ b/FreeFileSync/Build/Languages/chinese_simple.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>æ›´æ–°å³ä¾§çš„文件属性</target>
-<source>Cannot read file %x.</source>
-<target>无法读å–文件 %x .</target>
+<source>Cannot write permissions of %x.</source>
+<target>无法写入 %x çš„æƒé™.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>对于ä¸åŒåŸºç¡€æ–‡ä»¶å¤¹æ–¹å¼æ­¤æ“作ä¸è¢«æ”¯æŒ.</target>
+
+<source>Cannot write file %x.</source>
+<target>无法写入文件 %x .</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
实际: %y 字节
</target>
-<source>Cannot write permissions of %x.</source>
-<target>无法写入 %x çš„æƒé™.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>对于ä¸åŒåŸºç¡€æ–‡ä»¶å¤¹æ–¹å¼æ­¤æ“作ä¸è¢«æ”¯æŒ.</target>
-
-<source>Cannot write file %x.</source>
-<target>无法写入文件 %x .</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>无法å¤åˆ¶ç¬¦å·è¿žæŽ¥ %x 到 %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>无法打开文件 %x.</target>
+<source>Cannot read file %x.</source>
+<target>无法读å–文件 %x .</target>
+
<source>Cannot find device %x.</source>
<target>无法找到设备 %x.</target>
@@ -1601,8 +1601,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>无法连接到www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>无法在线找到当å‰FreeFileSync版本å·. ä½ è¦æ‰‹åŠ¨æ£€æŸ¥å—?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>检查(&C)</target>
@@ -1640,12 +1640,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>无法找到系统功能 %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>无法从 %x å¤åˆ¶å±žæ€§åˆ° %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>无法å¤åˆ¶æ–‡ä»¶ %x 到 %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>无法从 %x å¤åˆ¶å±žæ€§åˆ° %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>%x 的类型ä¸è¢«æ”¯æŒ:</target>
@@ -1769,6 +1769,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>谢谢你的æ助和支æŒ!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>这个用于æ赠者的FreeFileSync安装程åºå·²ç»è¾¾åˆ°äº†å®‰è£…次数的é™åˆ¶. 是å¦ä»ŽFreeFileSync主页下载普通版本?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/chinese_traditional.lng b/FreeFileSync/Build/Languages/chinese_traditional.lng
index 411ef4dd..f383f381 100644
--- a/FreeFileSync/Build/Languages/chinese_traditional.lng
+++ b/FreeFileSync/Build/Languages/chinese_traditional.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>æ›´æ–°å³é‚Šçš„屬性</target>
-<source>Cannot read file %x.</source>
-<target>無法讀å–檔案 %x。</target>
+<source>Cannot write permissions of %x.</source>
+<target>無法寫入 %x 的權é™ã€‚</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>ä¸æ”¯æ´ä¸åŒåŸºæœ¬è³‡æ–™å¤¾é¡žåž‹çš„æ“作。</target>
+
+<source>Cannot write file %x.</source>
+<target>無法寫入檔案 %x。</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
實際:%y ä½å…ƒçµ„
</target>
-<source>Cannot write permissions of %x.</source>
-<target>無法寫入 %x 的權é™ã€‚</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>ä¸æ”¯æ´ä¸åŒåŸºæœ¬è³‡æ–™å¤¾é¡žåž‹çš„æ“作。</target>
-
-<source>Cannot write file %x.</source>
-<target>無法寫入檔案 %x。</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>ç„¡æ³•è¤‡è£½ç¬¦è™Ÿé€£çµ %x 到 %y。</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>無法開啟檔案 %x。</target>
+<source>Cannot read file %x.</source>
+<target>無法讀å–檔案 %x。</target>
+
<source>Cannot find device %x.</source>
<target>找ä¸åˆ°è£ç½® %x。</target>
@@ -1604,8 +1604,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>無法連接到www.freefilesync.org。</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>線上找ä¸åˆ°ç›®å‰FreeFileSync版號ï¼æ˜¯å¦è¦æ‰‹å‹•æª¢æŸ¥ï¼Ÿ</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>檢查(&C)</target>
@@ -1643,12 +1643,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>找ä¸åˆ°ç³»çµ±å‡½æ•¸ %x。</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>無法從 %x 複製屬性到 %y。</target>
-
<source>Cannot copy file %x to %y.</source>
<target>無法從 %x 複製檔案到 %y。</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>無法從 %x 複製屬性到 %y。</target>
+
<source>Type of item %x is not supported:</source>
<target>項目類型 %x ä¸è¢«æ”¯æ´ï¼š</target>
@@ -1772,6 +1772,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>æ„Ÿè¬æ‚¨çš„æ贈和支æ´ï¼</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>æ贈者為此FreeFileSync安è£ç¨‹å¼å·²é”到其安è£é™åˆ¶ã€‚ç¾åœ¨è¦å¾žFreeFileSync首é ä¸‹è¼‰æ™®é€šç‰ˆå—Žï¼Ÿ</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/croatian.lng b/FreeFileSync/Build/Languages/croatian.lng
index 73b0a527..92cb8282 100644
--- a/FreeFileSync/Build/Languages/croatian.lng
+++ b/FreeFileSync/Build/Languages/croatian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Osvježi atribute desno</target>
-<source>Cannot read file %x.</source>
-<target>Ne mogu Äitati datoteku %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Ne mogu zapisati dopuštenja za %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operacija nije podržana za razliÄite bazne mape.</target>
+
+<source>Cannot write file %x.</source>
+<target>Ne mogu zapisati datoteku %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ OÄekivano: %x bajta
Stvarno: %y bajta
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Ne mogu zapisati dopuštenja za %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operacija nije podržana za razliÄite bazne mape.</target>
-
-<source>Cannot write file %x.</source>
-<target>Ne mogu zapisati datoteku %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Ne može se kopirati simboliÄna poveznica %x prema %y.</target>
@@ -255,6 +252,9 @@ Stvarno: %y bajta
<source>Cannot open file %x.</source>
<target>Ne mogu otvoriti datoteku %x.</target>
+<source>Cannot read file %x.</source>
+<target>Ne mogu Äitati datoteku %x.</target>
+
<source>Cannot find device %x.</source>
<target>Nije moguće pronaći uređaj %x.</target>
@@ -1626,8 +1626,8 @@ Ovo garantira Ävrsto stanje Äak u sluÄaju ozbiljne greÅ¡ke.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Nije moguće povezivanje s www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Ne mogu pronaći trenutnu verziju FreeFileSync-a online. Da li želite ruÄno potražiti?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Provjeri</target>
@@ -1665,12 +1665,12 @@ Ovo garantira Ävrsto stanje Äak u sluÄaju ozbiljne greÅ¡ke.
<source>Cannot find system function %x.</source>
<target>Ne mogu pronaći sistemsku funkciju %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Nije moguće kopiranje atributa od %x prema %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Ne mogu kopirati datoteku %x na %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Nije moguće kopiranje atributa od %x prema %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Vrsta stavke %x koji nije podržan:</target>
@@ -1800,6 +1800,9 @@ Ovo garantira Ävrsto stanje Äak u sluÄaju ozbiljne greÅ¡ke.
<source>Thanks for your donation and support!</source>
<target>Hvala na donaciji i podršci!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Ovaj FreeFileSync instalacijski paket za donatore je prekoraÄio broj instalacija. Preuzeti normalnu verziju s FreeFileSync stranice sada?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/czech.lng b/FreeFileSync/Build/Languages/czech.lng
index 85cb2f62..ff525fef 100644
--- a/FreeFileSync/Build/Languages/czech.lng
+++ b/FreeFileSync/Build/Languages/czech.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Nastavit vlastnosti vpravo</target>
-<source>Cannot read file %x.</source>
-<target>Nelze Äíst soubor %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Nelze zapsat oprávnění pro %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operace není podporována pro různé typy základních adresářů.</target>
+
+<source>Cannot write file %x.</source>
+<target>Nelze zapsat soubor %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ OÄekáváno: %x b
Aktuálně: %y b
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Nelze zapsat oprávnění pro %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operace není podporována pro různé typy základních adresářů.</target>
-
-<source>Cannot write file %x.</source>
-<target>Nelze zapsat soubor %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Nelze kopírovat symbolický odkaz %x do %y.</target>
@@ -255,6 +252,9 @@ Aktuálně: %y b
<source>Cannot open file %x.</source>
<target>Nelze otevřít soubor %x.</target>
+<source>Cannot read file %x.</source>
+<target>Nelze Äíst soubor %x.</target>
+
<source>Cannot find device %x.</source>
<target>Nelze nalézt zařízení %x.</target>
@@ -1623,8 +1623,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Není možné se připojit k www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>SouÄasná verze FreeFileSync nebyla nalezena online! Chcete verzi zkontrolovat ruÄnÄ›?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Kontrola</target>
@@ -1662,12 +1662,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>Nelze najít systémovou funkci %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Nelze kopírovat atributy z %x do %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Nelze kopírovat soubor %x do %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Nelze kopírovat atributy z %x do %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Typ položky %x není podporován:</target>
@@ -1797,6 +1797,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>Děkuji za Vaše příspěvky a podporu!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Tento instalátor pro pÅ™ispÄ›vovatele FreeFileSync dosáhl maximální poÄet instalací. Stáhnout verzi FreeFiileSync z domovské stránky?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/danish.lng b/FreeFileSync/Build/Languages/danish.lng
index 4706b1ad..1808257c 100644
--- a/FreeFileSync/Build/Languages/danish.lng
+++ b/FreeFileSync/Build/Languages/danish.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Opdater attributter mod højre</target>
-<source>Cannot read file %x.</source>
-<target>Kan ikke læse filen %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Kan ikke skrive tilladelserne til %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Handlingen understøtter ikke forskellige typer hovedmapper.</target>
+
+<source>Cannot write file %x.</source>
+<target>Kan ikke oprette filen %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Forventet: %x byte
Aktuel: %y byte
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Kan ikke skrive tilladelserne til %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Handlingen understøtter ikke forskellige typer hovedmapper.</target>
-
-<source>Cannot write file %x.</source>
-<target>Kan ikke oprette filen %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Kan ikke kopiere symlink fra %x til %y.</target>
@@ -255,6 +252,9 @@ Aktuel: %y byte
<source>Cannot open file %x.</source>
<target>Filen %x kan ikke åbnes.</target>
+<source>Cannot read file %x.</source>
+<target>Kan ikke læse filen %x.</target>
+
<source>Cannot find device %x.</source>
<target>Kan ikke finde enheden %x.</target>
@@ -1615,8 +1615,8 @@ Sikrer processen ved alvorlige fejl.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Kan ikke kontakte www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Kunne ikke finde FreeFileSync's versionsnummer online. Vil du kontrollere manuelt?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Kontroller</target>
@@ -1654,12 +1654,12 @@ Sikrer processen ved alvorlige fejl.
<source>Cannot find system function %x.</source>
<target>Kan ikke finde systemfunktionen %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Kan ikke kopiere attributter fra %x til %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Kan ikke kopiere filen %x til %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Kan ikke kopiere attributter fra %x til %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Filtypen %x understøttes ikke:</target>
@@ -1786,6 +1786,9 @@ Sikrer processen ved alvorlige fejl.
<source>Thanks for your donation and support!</source>
<target>Tak for støtten!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Antal FreeFileSync for donorer er opbrugt. Vil du downloade den normale version nu?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/dutch.lng b/FreeFileSync/Build/Languages/dutch.lng
index 8ac84954..d4f4412c 100644
--- a/FreeFileSync/Build/Languages/dutch.lng
+++ b/FreeFileSync/Build/Languages/dutch.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Update kenmerken aan de rechterzijde</target>
-<source>Cannot read file %x.</source>
-<target>Kan het bestand %x niet lezen.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Kan de aangegeven machtigingen van %x niet schrijven.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Deze bewerking wordt niet ondersteund voor verschillende basis maptypen.</target>
+
+<source>Cannot write file %x.</source>
+<target>Kan bestand %x niet schrijven.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Verwacht: %x bytes
Werkelijk: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Kan de aangegeven machtigingen van %x niet schrijven.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Deze bewerking wordt niet ondersteund voor verschillende basis maptypen.</target>
-
-<source>Cannot write file %x.</source>
-<target>Kan bestand %x niet schrijven.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Kan de symbolische koppeling %x niet kopiëren naar %y.</target>
@@ -255,6 +252,9 @@ Werkelijk: %y bytes
<source>Cannot open file %x.</source>
<target>Het bestand %x kan niet geopend worden.</target>
+<source>Cannot read file %x.</source>
+<target>Kan het bestand %x niet lezen.</target>
+
<source>Cannot find device %x.</source>
<target>Kan apparaat %x niet vinden.</target>
@@ -1615,8 +1615,8 @@ Dit garandeert een consistente status zelfs in het geval van een ernstige fout.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Kan geen verbinding maken met www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Kan online niet het actuele FreeFileSync versienummer vinden. Wilt u handmatig controleren?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Controleren</target>
@@ -1654,12 +1654,12 @@ Dit garandeert een consistente status zelfs in het geval van een ernstige fout.
<source>Cannot find system function %x.</source>
<target>Kan de systeemfunctie %x niet vinden.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Kan de attributen van %x niet kopiëren naar %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Kan bestand %x niet kopiëren naar %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Kan de attributen van %x niet kopiëren naar %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Dit itemtype %x wordt niet ondersteund:</target>
@@ -1786,6 +1786,9 @@ Dit garandeert een consistente status zelfs in het geval van een ernstige fout.
<source>Thanks for your donation and support!</source>
<target>Bedankt voor uw donatie en ondersteuning!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Dit FreeFileSync installatieprogramma voor donateurs heeft zijn installatielimiet bereikt. Download de reguliere versie van de FreeFileSync startpagina nu?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/english_uk.lng b/FreeFileSync/Build/Languages/english_uk.lng
index a9156ef5..025252cd 100644
--- a/FreeFileSync/Build/Languages/english_uk.lng
+++ b/FreeFileSync/Build/Languages/english_uk.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Update attributes on right</target>
-<source>Cannot read file %x.</source>
-<target>Cannot read file %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Cannot write permissions of %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operation not supported for different base folder types.</target>
+
+<source>Cannot write file %x.</source>
+<target>Cannot write file %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Expected: %x bytes
Actual: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Cannot write permissions of %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operation not supported for different base folder types.</target>
-
-<source>Cannot write file %x.</source>
-<target>Cannot write file %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Cannot copy symbolic link %x to %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>Cannot open file %x.</target>
+<source>Cannot read file %x.</source>
+<target>Cannot read file %x.</target>
+
<source>Cannot find device %x.</source>
<target>Cannot find device %x.</target>
@@ -1615,8 +1615,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Unable to connect to www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Cannot find current FreeFileSync version number online. Do you want to check manually?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Check</target>
@@ -1654,12 +1654,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>Cannot find system function %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Cannot copy attributes from %x to %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Cannot copy file %x to %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Cannot copy attributes from %x to %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Type of item %x is not supported:</target>
@@ -1786,6 +1786,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>Thanks for your donation and support!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/finnish.lng b/FreeFileSync/Build/Languages/finnish.lng
index 808a6cc2..3dcd8cea 100644
--- a/FreeFileSync/Build/Languages/finnish.lng
+++ b/FreeFileSync/Build/Languages/finnish.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Päivitä oikeudet oikealla</target>
-<source>Cannot read file %x.</source>
-<target>Tiedoston %x lukeminen ei onnistu.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Ei voi tallentaa %x:n oikeuksia.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Toiminto ei tue eri lähde hakemistoja.</target>
+
+<source>Cannot write file %x.</source>
+<target>Tiedoston %x kirjoittaminen ei onnistu.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Oletettu: %x tavua
Todellinen: %y tavua
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Ei voi tallentaa %x:n oikeuksia.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Toiminto ei tue eri lähde hakemistoja.</target>
-
-<source>Cannot write file %x.</source>
-<target>Tiedoston %x kirjoittaminen ei onnistu.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Pikakuvike %x - %y kopiointi epäonnistui.</target>
@@ -255,6 +252,9 @@ Todellinen: %y tavua
<source>Cannot open file %x.</source>
<target>Tiedosto %x ei aukea.</target>
+<source>Cannot read file %x.</source>
+<target>Tiedoston %x lukeminen ei onnistu.</target>
+
<source>Cannot find device %x.</source>
<target>Laite %x ei löydy.</target>
@@ -1615,8 +1615,8 @@ Tällä varmistetaan eheys, vaikka vakava virhe tapahtuisi.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Ei yhteyttä www.freefilesync.org:iin.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Nykyistä FreeFileSyncin versiota ei löydy verkosta. Suoritetaanko manuaalinen haku?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Tarkista</target>
@@ -1654,12 +1654,12 @@ Tällä varmistetaan eheys, vaikka vakava virhe tapahtuisi.
<source>Cannot find system function %x.</source>
<target>Järjestelmäfunktiota %x ei löydy.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Ominaisuuksien monistus %x:ltä %y:lle ei onnistu.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Tiedostoa %x ei voida kopioida kohtaan %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Ominaisuuksien monistus %x:ltä %y:lle ei onnistu.</target>
+
<source>Type of item %x is not supported:</source>
<target>Kohteen %x tyyppiä ei tueta:</target>
@@ -1786,6 +1786,9 @@ Tällä varmistetaan eheys, vaikka vakava virhe tapahtuisi.
<source>Thanks for your donation and support!</source>
<target>Kiitän tuesta ja lahjoituksista!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Tämä lahjoittajien version FreeFileSync:n latauskerrat on käytetty. Ladataanko normi versio FreeFileSync kotisivulta?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/french.lng b/FreeFileSync/Build/Languages/french.lng
index 11bb0341..075b04f2 100644
--- a/FreeFileSync/Build/Languages/french.lng
+++ b/FreeFileSync/Build/Languages/french.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Mise à jour des attributs à droite</target>
-<source>Cannot read file %x.</source>
-<target>Impossible de lire le fichier %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Impossible d'écrire les permissions de %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Opération non prise en charge pour dee dossiers de base de types différents.</target>
+
+<source>Cannot write file %x.</source>
+<target>Impossible d'écrire le fichier %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Attendu : %x octets
Trouvé : %y octets
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Impossible d'écrire les permissions de %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Opération non prise en charge pour dee dossiers de base de types différents.</target>
-
-<source>Cannot write file %x.</source>
-<target>Impossible d'écrire le fichier %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Impossible de copier le lien symbolique %x vers %y.</target>
@@ -255,6 +252,9 @@ Trouvé : %y octets
<source>Cannot open file %x.</source>
<target>Impossible d'ouvrir le fichier %x.</target>
+<source>Cannot read file %x.</source>
+<target>Impossible de lire le fichier %x.</target>
+
<source>Cannot find device %x.</source>
<target>Impossible de trouver le périphérique %x.</target>
@@ -1615,8 +1615,8 @@ Cela garantit la cohérence du système de fichiers en cas d'erreur grave.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Impossible de se connecter à www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Impossible de trouver en ligne une nouvelle version de FreeFileSync.Voulez-vous le faire manuellement ?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Contrôle</target>
@@ -1654,12 +1654,12 @@ Cela garantit la cohérence du système de fichiers en cas d'erreur grave.
<source>Cannot find system function %x.</source>
<target>Impossible de trouver la fonction système %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Impossible de copier les attributs de %x à %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Impossible de copier le fichier %x vers %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Impossible de copier les attributs de %x à %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Le type de l'élément %x n'est pas accepté :</target>
@@ -1786,6 +1786,9 @@ Cela garantit la cohérence du système de fichiers en cas d'erreur grave.
<source>Thanks for your donation and support!</source>
<target>Merci pour votre don et votre aide !</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Le programme d'installation pour les donateurs a atteint sa limite d'installations. Voulez-vous télécharger la version valide à partir du site de FreeFileSync ?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/german.lng b/FreeFileSync/Build/Languages/german.lng
index 1adf8fbf..de0e6ca3 100644
--- a/FreeFileSync/Build/Languages/german.lng
+++ b/FreeFileSync/Build/Languages/german.lng
@@ -7,6 +7,12 @@
<plural_definition>n == 1 ? 0 : 1</plural_definition>
</header>
+<source>Installation files are corrupt. Please reinstall FreeFileSync.</source>
+<target>Die Installationsdateien sind beschädigt. Bitte installieren Sie FreeFileSync neu.</target>
+
+<source>Consistency check failed for %x.</source>
+<target>Die Konsistenzprüfung für %x ist fehlgeschlagen.</target>
+
<source>Both sides have changed since last synchronization.</source>
<target>Beide Seiten wurden seit der letzten Synchronisation verändert.</target>
@@ -214,8 +220,14 @@
<source>Update attributes on right</source>
<target>Aktualisiere Attribute des rechten Elements</target>
-<source>Cannot read file %x.</source>
-<target>Die Datei %x kann nicht gelesen werden.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Die Berechtigungen von %x können nicht geschrieben werden.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Der Vorgang wird für unterschiedliche Basisordner nicht unterstützt.</target>
+
+<source>Cannot write file %x.</source>
+<target>Die Datei %x kann nicht geschrieben werden.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +240,6 @@ Erwartet: %x bytes
Tatsächlich: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Die Berechtigungen von %x können nicht geschrieben werden.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Der Vorgang wird für unterschiedliche Basisordner nicht unterstützt.</target>
-
-<source>Cannot write file %x.</source>
-<target>Die Datei %x kann nicht geschrieben werden.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Die symbolische Verknüpfung %x kann nicht nach %y kopiert werden.</target>
@@ -255,6 +258,9 @@ Tatsächlich: %y bytes
<source>Cannot open file %x.</source>
<target>Die Datei %x kann nicht geöffnet werden.</target>
+<source>Cannot read file %x.</source>
+<target>Die Datei %x kann nicht gelesen werden.</target>
+
<source>Cannot find device %x.</source>
<target>Das Gerät %x wurde nicht gefunden.</target>
@@ -1615,12 +1621,15 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Es kann keine Verbindung zu www.freefilesync.org aufgebaut werden.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Die aktuelle FreeFileSync Versionsnummer wurde online nicht gefunden. Möchten Sie manuell prüfen?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target>Die aktuelle FreeFileSync Versionsnummer wurde online nicht gefunden. Wahrscheinlich ist eine neuere Version verfügbar. Jetzt manuell prüfen?</target>
<source>&Check</source>
<target>&Prüfen</target>
+<source>Cannot find system function %x.</source>
+<target>Die Systemfunktion %x wurde nicht gefunden.</target>
+
<source>Unable to register to receive system messages.</source>
<target>Die Registrierung zum Empfang von Systemmeldungen ist fehlgeschlagen.</target>
@@ -1651,15 +1660,12 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert.
<source>%x is not a regular directory name.</source>
<target>%x ist kein regulärer Verzeichnisname.</target>
-<source>Cannot find system function %x.</source>
-<target>Die Systemfunktion %x wurde nicht gefunden.</target>
+<source>Cannot copy file %x to %y.</source>
+<target>Die Datei %x kann nicht nach %y kopiert werden.</target>
<source>Cannot copy attributes from %x to %y.</source>
<target>Die Attribute können nicht von %x nach %y kopiert werden.</target>
-<source>Cannot copy file %x to %y.</source>
-<target>Die Datei %x kann nicht nach %y kopiert werden.</target>
-
<source>Type of item %x is not supported:</source>
<target>Der Typ des Elements %x wird nicht unterstützt:</target>
@@ -1786,6 +1792,9 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert.
<source>Thanks for your donation and support!</source>
<target>Danke für Ihre Spende und Unterstützung!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Das FreeFileSync Installationsprogramm für Spender hat sein Installationslimit erreicht. Jetzt die normale Version von der FreeFileSync Homepage herunterladen?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target>Das FreeFileSync Installationsprogramm für Spender hat sein tägliches Installationslimit erreicht.</target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target>Jetzt die normale Version von der FreeFileSync Homepage herunterladen?</target>
diff --git a/FreeFileSync/Build/Languages/greek.lng b/FreeFileSync/Build/Languages/greek.lng
index f5e9dd66..11dd984b 100644
--- a/FreeFileSync/Build/Languages/greek.lng
+++ b/FreeFileSync/Build/Languages/greek.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>ΕνημέÏωση των στοιχείων στα δεξιά</target>
-<source>Cannot read file %x.</source>
-<target>Δεν μποÏεί να γίνει ανάγνωση του αÏχείου %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Δεν μποÏεί να γίνει εγγÏαφή των αδειών Ï€Ïοσπέλασης του %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Η λειτουÏγία δεν υποστηÏίζεται για διαφοÏετικοÏÏ‚ Ï„Ïπους βασικών υποκαταλόγων.</target>
+
+<source>Cannot write file %x.</source>
+<target>Δεν μποÏεί να γίνει εγγÏαφή του αÏχείου %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
Î’Ïέθηκε: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Δεν μποÏεί να γίνει εγγÏαφή των αδειών Ï€Ïοσπέλασης του %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Η λειτουÏγία δεν υποστηÏίζεται για διαφοÏετικοÏÏ‚ Ï„Ïπους βασικών υποκαταλόγων.</target>
-
-<source>Cannot write file %x.</source>
-<target>Δεν μποÏεί να γίνει εγγÏαφή του αÏχείου %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Αδυναμία αντιγÏαφής του ÏƒÏ…Î¼Î²Î¿Î»Î¹ÎºÎ¿Ï Î´ÎµÏƒÎ¼Î¿Ï %x στο %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>Δεν είναι δυνατό το άνοιγμα του αÏχείου %x.</target>
+<source>Cannot read file %x.</source>
+<target>Δεν μποÏεί να γίνει ανάγνωση του αÏχείου %x.</target>
+
<source>Cannot find device %x.</source>
<target>Η συσχευή %x δεν μποÏεί να βÏεθεί.</target>
@@ -1615,8 +1615,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Αδυναμία επικοινωνίας με το www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Ο αÏιθμός της Ï„Ïέχουσας έκδοσης του FreeFileSync δεν βÏέθηκε στο δίκτυο. Θέλετε να το ελέγξετε εσείς;</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>Έλε&γχος</target>
@@ -1654,12 +1654,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>Δεν ανευÏίσκεται η λειτουÏγία συστήματος %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Δεν μποÏοÏν να αντιγÏαφοÏν τα χαÏακτηÏιστικά του %x στο %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Δεν μποÏεί να αντιγÏαφεί το αÏχείο %x στο %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Δεν μποÏοÏν να αντιγÏαφοÏν τα χαÏακτηÏιστικά του %x στο %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Ο Ï„Ïπος του στοιχείου %x δεν υποστηÏίζεται:</target>
@@ -1786,6 +1786,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>ΕυχαÏιστοÏμε για τη δωÏεά και την υποστήÏιξή σας!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Αυτό το Ï€ÏόγÏαμμα εγκατάστασης του FreeFileSync για υποστηÏικτές έχει λήξει. Θέλετε να κατεβάσετε την κανονική έκδοση από τη σελίδα του FreeFileSync;</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/hebrew.lng b/FreeFileSync/Build/Languages/hebrew.lng
index 021eb64e..945710d1 100644
--- a/FreeFileSync/Build/Languages/hebrew.lng
+++ b/FreeFileSync/Build/Languages/hebrew.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>עדכן תכונות בצד שמ×ל</target>
-<source>Cannot read file %x.</source>
-<target>×œ× ×™×›×•×œ ×œ×§×¨×•× ×§×•×‘×¥ %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>×œ× ×™×›×•×œ לכתוב הרש×ות של %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>פעולה ×œ× × ×ª×ž×›×ª עבור ×¡×•×’×™× ××—×¨×™× ×©×œ תיקית בסיס.</target>
+
+<source>Cannot write file %x.</source>
+<target>×œ× ×™×›×•×œ לכתוב קובץ %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
בפועל: %y בתי×
</target>
-<source>Cannot write permissions of %x.</source>
-<target>×œ× ×™×›×•×œ לכתוב הרש×ות של %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>פעולה ×œ× × ×ª×ž×›×ª עבור ×¡×•×’×™× ××—×¨×™× ×©×œ תיקית בסיס.</target>
-
-<source>Cannot write file %x.</source>
-<target>×œ× ×™×›×•×œ לכתוב קובץ %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>×œ× ×™×›×•×œ להעתיק קישור סימבולי %x ×ל %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>×œ× ×™×›×•×œ לפתוח קובץ %x.</target>
+<source>Cannot read file %x.</source>
+<target>×œ× ×™×›×•×œ ×œ×§×¨×•× ×§×•×‘×¥ %x.</target>
+
<source>Cannot find device %x.</source>
<target>×œ× ×ž×•×¦× ×”×ª×§×Ÿ %x.</target>
@@ -1615,8 +1615,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>×ין תקשורת ×ל www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>×œ× ×ž×•×¦× ×ž×¡×¤×¨ גירסה עדכנית של FreeFileSync ב×ופן מכוון. ×”×× ×תה רוצה לבדוק ב×ופן ידני?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&בדוק</target>
@@ -1654,12 +1654,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>×œ× ×™×›×•×œ ×œ×ž×¦×•× ×¤×•× ×§×¦×™×ª מערכת %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>×œ× ×™×›×•×œ להעתיק תכונות מ- %x ×ל %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>×œ× ×™×›×•×œ להעתיק קובץ %x ×ל %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>×œ× ×™×›×•×œ להעתיק תכונות מ- %x ×ל %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>סוג של פריט %x ×ינו נתמך:</target>
@@ -1786,6 +1786,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>תודה עבור תרומתך ותמיכתך!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>קובץ התקנת FreeFileSync ×œ×ª×•×¨×ž×™× ×”×’×™×¢ למגבלת ההתקנות. ×”×× ×œ×”×•×¨×™×“ ×ת הגירסה הרגילה של קובץ ההתקנה מ×תר הבית של FreeFileSync כעת?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/hindi.lng b/FreeFileSync/Build/Languages/hindi.lng
index b818e364..058b6b19 100644
--- a/FreeFileSync/Build/Languages/hindi.lng
+++ b/FreeFileSync/Build/Languages/hindi.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>दाईं तरफ के गà¥à¤£ अदà¥à¤¯à¤¤à¤¨ करें</target>
-<source>Cannot read file %x.</source>
-<target>फ़ाइल %x पढ़ने में असमरà¥à¤¥à¥¤</target>
+<source>Cannot write permissions of %x.</source>
+<target>%x की अनà¥à¤®à¤¤à¤¿à¤¯à¤¾à¤‚ लिख नहीं सकते।</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>भिनà¥à¤¨ मूल फ़ोलà¥à¤¡à¤° पà¥à¤°à¤•à¤¾à¤°à¥‹à¤‚ के लिठकारà¥à¤¯à¤µà¤¾à¤ˆ समरà¥à¤¥à¤¿à¤¤ नहीं।</target>
+
+<source>Cannot write file %x.</source>
+<target>फ़ाइल %x लिखने में असमरà¥à¤¥à¥¤</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
वासà¥à¤¤à¤µà¤¿à¤•: %y बाइटà¥à¤¸
</target>
-<source>Cannot write permissions of %x.</source>
-<target>%x की अनà¥à¤®à¤¤à¤¿à¤¯à¤¾à¤‚ लिख नहीं सकते।</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>भिनà¥à¤¨ मूल फ़ोलà¥à¤¡à¤° पà¥à¤°à¤•à¤¾à¤°à¥‹à¤‚ के लिठकारà¥à¤¯à¤µà¤¾à¤ˆ समरà¥à¤¥à¤¿à¤¤ नहीं।</target>
-
-<source>Cannot write file %x.</source>
-<target>फ़ाइल %x लिखने में असमरà¥à¤¥à¥¤</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>सिंबॉलिक लिंक %x से %y पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿à¤¤ नहीं कर सकते।</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>%x फ़ाइल को खोलने में असमरà¥à¤¥à¥¤</target>
+<source>Cannot read file %x.</source>
+<target>फ़ाइल %x पढ़ने में असमरà¥à¤¥à¥¤</target>
+
<source>Cannot find device %x.</source>
<target>डिवाइस %x नहीं मिला।</target>
@@ -1615,8 +1615,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>www.freefilesync.org से जà¥à¤¡à¤¼à¤¨à¥‡ में असमरà¥à¤¥à¥¤</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>वरà¥à¤¤à¤®à¤¾à¤¨ FreeFileSync संसà¥à¤•à¤°à¤£ संखà¥à¤¯à¤¾ ऑनलाइन नहीं मिल सकती. कà¥à¤¯à¤¾ आप मैनà¥à¤¯à¥à¤…ल रूप से जाà¤à¤š करना चाहते हैं?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>जाà¤à¤š करें (&C)</target>
@@ -1654,12 +1654,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>सिसà¥à¤Ÿà¤® फ़ंकशन %x ढूंढ नहीं सकते।</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>%x से %y गà¥à¤£ पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿à¤¤ नहीं कर सकते।</target>
-
<source>Cannot copy file %x to %y.</source>
<target>फ़ाइल %x से %y पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿à¤¤ नहीं कर सकते।</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>%x से %y गà¥à¤£ पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿à¤¤ नहीं कर सकते।</target>
+
<source>Type of item %x is not supported:</source>
<target>%x पà¥à¤°à¤•à¤¾à¤° का आइटम समरà¥à¤¥à¤¿à¤¤ नहीं है:</target>
@@ -1786,6 +1786,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>आपके दान और समरà¥à¤¥à¤¨ के लिठधनà¥à¤¯à¤µà¤¾à¤¦!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>यह दाताओं का FreeFileSync installer अपनी सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ सीमा तक पहूà¤à¤šà¤¾ है। नियमित संसà¥à¤•à¤°à¤£ FreeFileSync मà¥à¤– पà¥à¤°à¥à¤·à¥à¤  से डाउनलोड करें?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/hungarian.lng b/FreeFileSync/Build/Languages/hungarian.lng
index 82160fb3..e4e9794d 100644
--- a/FreeFileSync/Build/Languages/hungarian.lng
+++ b/FreeFileSync/Build/Languages/hungarian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Attribútumok frissítése a jobb oldalon</target>
-<source>Cannot read file %x.</source>
-<target>%x fájl olvasása nem sikerült.</target>
+<source>Cannot write permissions of %x.</source>
+<target>%x jogosultságait nem lehet felírni.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>A művelet nem támogatott különböző alapkönyvtártípusok esetén.</target>
+
+<source>Cannot write file %x.</source>
+<target>%x fájl írása nem sikerült.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Várt: %x bájt
Jelenlegi: %y bájt
</target>
-<source>Cannot write permissions of %x.</source>
-<target>%x jogosultságait nem lehet felírni.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>A művelet nem támogatott különböző alapkönyvtártípusok esetén.</target>
-
-<source>Cannot write file %x.</source>
-<target>%x fájl írása nem sikerült.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>%x szimbolikus linket nem tudja %y-ba másolni.</target>
@@ -255,6 +252,9 @@ Jelenlegi: %y bájt
<source>Cannot open file %x.</source>
<target>%x fájl nem nyitható.</target>
+<source>Cannot read file %x.</source>
+<target>%x fájl olvasása nem sikerült.</target>
+
<source>Cannot find device %x.</source>
<target>%x eszköz nem található.</target>
@@ -1615,8 +1615,8 @@ Ez garantálja a konzisztens állapotot egy komoly hiba esetén is.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Nem lehet csatlakozni a www.freefilesync.org-hoz.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Nem lehet online megtalálni a jelenlegi FreeFileSync verziószámot. Meg akarod keresni manuálisan?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Ellenőriz</target>
@@ -1654,12 +1654,12 @@ Ez garantálja a konzisztens állapotot egy komoly hiba esetén is.
<source>Cannot find system function %x.</source>
<target>%x rendszerfunkció nem elérhető.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Nem lehet az attribútumokat %x-ből %y-ba másolni.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>%x fájl másolása a(z) %y fájlba nem sikerült.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Nem lehet az attribútumokat %x-ből %y-ba másolni.</target>
+
<source>Type of item %x is not supported:</source>
<target>A(z) %x elem típusa nem támogatott:</target>
@@ -1786,6 +1786,9 @@ Ez garantálja a konzisztens állapotot egy komoly hiba esetén is.
<source>Thanks for your donation and support!</source>
<target>Köszönöm az adományt és támogatást!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Ez az adományozók számára biztosított FreeFileSync telepítőcsomag elérte a megengedett telepítési számot. Letöltse most a normál verziót a FreeFileSync honlapjáról?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/italian.lng b/FreeFileSync/Build/Languages/italian.lng
index 8c795b67..77638f94 100644
--- a/FreeFileSync/Build/Languages/italian.lng
+++ b/FreeFileSync/Build/Languages/italian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Aggiorna attributi a destra</target>
-<source>Cannot read file %x.</source>
-<target>Impossibile leggere il file %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Impossibile scrivere i permessi di %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operazione non supportata per i diversi tipi di cartelle di base.</target>
+
+<source>Cannot write file %x.</source>
+<target>Impossibile scrivere il file %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Previsto: %x byte
Attuale: %y byte
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Impossibile scrivere i permessi di %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operazione non supportata per i diversi tipi di cartelle di base.</target>
-
-<source>Cannot write file %x.</source>
-<target>Impossibile scrivere il file %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Impossibile copiare collegamento %x per %y.</target>
@@ -255,6 +252,9 @@ Attuale: %y byte
<source>Cannot open file %x.</source>
<target>Impossibile aprire il file %x.</target>
+<source>Cannot read file %x.</source>
+<target>Impossibile leggere il file %x.</target>
+
<source>Cannot find device %x.</source>
<target>Impossibile trovare dispositivo %x.</target>
@@ -1615,8 +1615,8 @@ Questo garantisce uno stato consistente anche in caso di errore grave.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Impossibile connettersi al www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Non riesci a trovare l'attuale numero di versione di FreeFileSync on-line. Vuoi controllare manualmente?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Controllare</target>
@@ -1654,12 +1654,12 @@ Questo garantisce uno stato consistente anche in caso di errore grave.
<source>Cannot find system function %x.</source>
<target>Impossibile trovare la funzione di sistema %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Non è possibile copiare gli attributi da %x per %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Impossibile copiare il file %x in %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Non è possibile copiare gli attributi da %x per %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Il tipo di oggetto %x non è supportato:</target>
@@ -1786,6 +1786,9 @@ Questo garantisce uno stato consistente anche in caso di errore grave.
<source>Thanks for your donation and support!</source>
<target>Grazie per la vostra donazione e il supporto!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Questo programma di installazione di FreeFileSync per i donatori ha raggiunto il suo limite di utilizzo. Scarica la versione normale dalla homepage FreeFileSync ora?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/japanese.lng b/FreeFileSync/Build/Languages/japanese.lng
index a6174dec..3c3f6842 100644
--- a/FreeFileSync/Build/Languages/japanese.lng
+++ b/FreeFileSync/Build/Languages/japanese.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>å³ã®å±žæ€§ã‚’æ›´æ–°</target>
-<source>Cannot read file %x.</source>
-<target>ファイル %x を読ã¿è¾¼ã‚ã¾ã›ã‚“.</target>
+<source>Cannot write permissions of %x.</source>
+<target>%x ã®ï¾Šï¾Ÿï½°ï¾ï½¯ï½¼ï½®ï¾ã‚’書ãè¾¼ã‚ã¾ã›ã‚“.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>別ã®åŸºæº–フォルダタイプã§ã¯å¯¾å¿œã—ã¦ã„ãªã„æ“作.</target>
+
+<source>Cannot write file %x.</source>
+<target>ファイル %x ã«æ›¸ãè¾¼ã‚ã¾ã›ã‚“.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
実際ã®å€¤: %y ãƒã‚¤ãƒˆ
</target>
-<source>Cannot write permissions of %x.</source>
-<target>%x ã®ï¾Šï¾Ÿï½°ï¾ï½¯ï½¼ï½®ï¾ã‚’書ãè¾¼ã‚ã¾ã›ã‚“.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>別ã®åŸºæº–フォルダタイプã§ã¯å¯¾å¿œã—ã¦ã„ãªã„æ“作.</target>
-
-<source>Cannot write file %x.</source>
-<target>ファイル %x ã«æ›¸ãè¾¼ã‚ã¾ã›ã‚“.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>シンボリックリンク %x ã‚’ %y ã«ã‚³ãƒ”ーã§ãã¾ã›ã‚“.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>ファイル %x ã‚’é–‹ã‘ã¾ã›ã‚“.</target>
+<source>Cannot read file %x.</source>
+<target>ファイル %x を読ã¿è¾¼ã‚ã¾ã›ã‚“.</target>
+
<source>Cannot find device %x.</source>
<target>デãƒã‚¤ã‚¹ %x ãŒã¿ã¤ã‹ã‚Šã¾ã›ã‚“.</target>
@@ -1604,8 +1604,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>www.freefilesync.org ã«æŽ¥ç¶šã§ãã¾ã›ã‚“.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>ç¾åœ¨ã® FreeFileSync ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸã€æ‰‹å‹•ã§ç¢ºèªã—ã¾ã™ã‹?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>ãƒã‚§ãƒƒã‚¯(&C)</target>
@@ -1643,12 +1643,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>システム関数 %x ãŒã¿ã¤ã‹ã‚Šã¾ã›ã‚“.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>属性 ã‚’ %x ã‹ã‚‰ %y ã«ã‚³ãƒ”ーã§ãã¾ã›ã‚“.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>%x ã‹ã‚‰ %y ã«ã‚³ãƒ”ーã§ãã¾ã›ã‚“.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>属性 ã‚’ %x ã‹ã‚‰ %y ã«ã‚³ãƒ”ーã§ãã¾ã›ã‚“.</target>
+
<source>Type of item %x is not supported:</source>
<target>é …ç›® %x ã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“:</target>
@@ -1772,6 +1772,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>ã‚ãªãŸã®å¯„付ã¨æ”¯æ´ã«æ„Ÿè¬ã—ã¾ã™!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>ã“ã®ãƒ‰ãƒŠãƒ¼ç”¨ FreeFileSync インストーラã¯ã€ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã®åˆ¶é™ã«é”ã—ã¾ã—ãŸã€‚ 今ã™ã FreeFileSync å…¬å¼ã‚µã‚¤ãƒˆã§æ­£è¦ç‰ˆã‚’ダウンロードã—ã¾ã™ã‹?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/korean.lng b/FreeFileSync/Build/Languages/korean.lng
index 0677d2a7..dc39bfdb 100644
--- a/FreeFileSync/Build/Languages/korean.lng
+++ b/FreeFileSync/Build/Languages/korean.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>우측 ì†ì„± ì—…ë°ì´íŠ¸</target>
-<source>Cannot read file %x.</source>
-<target>íŒŒì¼ %xì„(를) ì½ì„ 수 없습니다.</target>
+<source>Cannot write permissions of %x.</source>
+<target>%xì˜ ê¶Œí•œì„ ì“¸ 수 없습니다.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>다른 기본 í´ë” ìœ í˜•ì— ëŒ€í•´ 지ì›ë˜ì§€ 않는 ë™ìž‘.</target>
+
+<source>Cannot write file %x.</source>
+<target>íŒŒì¼ %xì„(를) 쓸 수 없습니다.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
실제 사ì´ì¦ˆ: %y ë°”ì´íŠ¸
</target>
-<source>Cannot write permissions of %x.</source>
-<target>%xì˜ ê¶Œí•œì„ ì“¸ 수 없습니다.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>다른 기본 í´ë” ìœ í˜•ì— ëŒ€í•´ 지ì›ë˜ì§€ 않는 ë™ìž‘.</target>
-
-<source>Cannot write file %x.</source>
-<target>íŒŒì¼ %xì„(를) 쓸 수 없습니다.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>심볼릭 ë§í¬ %xì„(를) %y(으)ë¡œ 복사할 수 없습니다.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>íŒŒì¼ %xì„(를) ì—´ 수 없습니다.</target>
+<source>Cannot read file %x.</source>
+<target>íŒŒì¼ %xì„(를) ì½ì„ 수 없습니다.</target>
+
<source>Cannot find device %x.</source>
<target>장치 %xì„(를) ì°¾ì„ ìˆ˜ 없습니다.</target>
@@ -1604,8 +1604,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>www.freefilesync.org.ì— ì ‘ì†í•  수 없습니다.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>현재 사용 ì¤‘ì¸ FreeFileSync 버전 번호를 온ë¼ì¸ì—ì„œ ì°¾ì„ ìˆ˜ 없습니다. 수ë™ìœ¼ë¡œ 확ì¸í•´ 보시겠습니까?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>ì²´í¬(&C)</target>
@@ -1643,12 +1643,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>시스템 함수 %xì„(를) ì°¾ì„ ìˆ˜ 없습니다.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>%xì—ì„œ %y(으)ë¡œì˜ ì†ì„±ì„ 복사할 수 없습니다.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>íŒŒì¼ %xì„(를) %y(으)ë¡œ 복사할 수 없습니다.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>%xì—ì„œ %y(으)ë¡œì˜ ì†ì„±ì„ 복사할 수 없습니다.</target>
+
<source>Type of item %x is not supported:</source>
<target>항목 %xì˜ í˜•ì‹ì€ 지ì›ë˜ì§€ 않습니다:</target>
@@ -1772,6 +1772,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>ê·€í•˜ì˜ ê¸°ë¶€ì™€ 지ì›ì— ê°ì‚¬ë“œë¦½ë‹ˆë‹¤!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>기부ìžìš© FreeFileSync ì¸ìŠ¤í†¨ëŸ¬ê°€ 설치 ì œí•œì— ë„달했습니다. FreeFileSync 홈페ì´ì§€ì—ì„œ ì¼ë°˜ ë²„ì „ì„ ë‹¤ìš´ë¡œë“œ 하시겠습니까?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/lithuanian.lng b/FreeFileSync/Build/Languages/lithuanian.lng
index 69f267e9..72eb4cd2 100644
--- a/FreeFileSync/Build/Languages/lithuanian.lng
+++ b/FreeFileSync/Build/Languages/lithuanian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Atnaujinti atributus dešinėje</target>
-<source>Cannot read file %x.</source>
-<target>Nepavyksta nuskaityti failo %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Nepavyksta įrašyti leidimų %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Veiksmas yra nesuderinamas dėl skirtingų aplankų savybių.</target>
+
+<source>Cannot write file %x.</source>
+<target>Nepavyksta įrašyti failo %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Numatytas: %x baitai
Esamas: %y baitai
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Nepavyksta įrašyti leidimų %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Veiksmas yra nesuderinamas dėl skirtingų aplankų savybių.</target>
-
-<source>Cannot write file %x.</source>
-<target>Nepavyksta įrašyti failo %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Nepavyko nukopijuoti simbolinės nuorodos %x į %y.</target>
@@ -255,6 +252,9 @@ Esamas: %y baitai
<source>Cannot open file %x.</source>
<target>%x failo nepavyko atidaryti.</target>
+<source>Cannot read file %x.</source>
+<target>Nepavyksta nuskaityti failo %x.</target>
+
<source>Cannot find device %x.</source>
<target>Negalima surasti įrenginio %x.</target>
@@ -1626,8 +1626,8 @@ Tai garantuos pastovią buseną, netgi įvykus rimtai klaidai.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Nepavyko prisijungti prie www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Dabartinės FreeFileSync versijos numeris internete nerastas. Ar norėtumėte patikrinti rankiniu būdu?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Tikrinti</target>
@@ -1665,12 +1665,12 @@ Tai garantuos pastovią buseną, netgi įvykus rimtai klaidai.
<source>Cannot find system function %x.</source>
<target>Nepavyksta rasti sisteminÄ—s funkcijos %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Nepavyko nukopijuoti atributų iš %x į %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Nepavyksta nukopijuoti failų %x į %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Nepavyko nukopijuoti atributų iš %x į %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Elemento tipas %x nepalaikomas:</target>
@@ -1800,6 +1800,9 @@ Tai garantuos pastovią buseną, netgi įvykus rimtai klaidai.
<source>Thanks for your donation and support!</source>
<target>AÄių už jÅ«sų aukas ir palaikymÄ…!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Šis FreeFileSync remėjų diegiamasis failas pasiekė savo ribą. Ar dabar parsisiųsti standartinę versiją iš FreeFileSync internetinio puslapio?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/outdated/norwegian.lng b/FreeFileSync/Build/Languages/outdated/norwegian.lng
index 02efdf9c..879580ba 100644
--- a/FreeFileSync/Build/Languages/outdated/norwegian.lng
+++ b/FreeFileSync/Build/Languages/outdated/norwegian.lng
@@ -92,7 +92,7 @@
<target>Vilkårlig antall FreeFileSync .ffs_gui og/eller .ffs_batch indstillingsfiler.</target>
<source>Any number of alternative directory pairs for at most one config file.</source>
-<target>Et ubegrenset antall alternative kataloger for maksimalt én konfigurasjonsfil</target>
+<target>Et ubegrenset antall alternative kataloger for maksimalt én konfigurasjonsfil.</target>
<source>Open configuration for editing without executing it.</source>
<target></target>
@@ -125,7 +125,7 @@
<target>Størrelse:</target>
<source>Content comparison was skipped for excluded files %x.</source>
-<target>Innholdsanalyse er utelatt for ekskluderte filer %x</target>
+<target>Innholdsanalyse er utelatt for ekskluderte filer %x.</target>
<source>Items differ in attributes only</source>
<target>Enhetene har kun forskjellige attributter</target>
@@ -222,7 +222,7 @@ Actual: %y bytes
<target>Kan ikke opprette filen %x.</target>
<source>Cannot copy symbolic link %x to %y.</source>
-<target>Kan ikke kopiere symolsk link %x til %y</target>
+<target>Kan ikke kopiere symolsk link %x til %y.</target>
<source>Cannot move file %x to %y.</source>
<target>Kan ikke flytte filen %x til %y.</target>
@@ -258,7 +258,7 @@ Actual: %y bytes
<target>Kan ikke oppdatere tidsendring på %x.</target>
<source>Cannot determine final path for %x.</source>
-<target>Kan ikke bestemme endelig sti for %x</target>
+<target>Kan ikke bestemme endelig sti for %x.</target>
<source>Cannot resolve symbolic link %x.</source>
<target>Kan ikke følge symlinken %x.</target>
@@ -327,7 +327,7 @@ Actual: %y bytes
<target>Venter mens mappe låses:</target>
<source>Lock owner:</source>
-<target>LÃ¥sens eier</target>
+<target>LÃ¥sens eier:</target>
<source>
<pluralform>1 sec</pluralform>
@@ -390,7 +390,7 @@ Actual: %y bytes
<target>Gjennomse mappe</target>
<source>Cannot access the Volume Shadow Copy Service.</source>
-<target>VSS tjenesten er ikke tilgjengelig</target>
+<target>VSS tjenesten er ikke tilgjengelig.</target>
<source>Please use FreeFileSync 64-bit version to create shadow copies on this system.</source>
<target>Bruk FreeFileSync 64-bit til å lage VSS kopier på dette system.</target>
@@ -465,7 +465,7 @@ Actual: %y bytes
<target><Søk</target>
<source>Idle time (in seconds):</source>
-<target>PC ikke brukt i (sek)</target>
+<target>PC ikke brukt i (sek):</target>
<source>Idle time between last detected change and execution of command</source>
<target>Tid mellom sist funnet endring og utførelse</target>
@@ -641,7 +641,7 @@ Kommandoen utføres hvis:
<target>Synkronisering gjennomført</target>
<source>Cleaning up old log files...</source>
-<target>Fjerner gamle loggfiler</target>
+<target>Fjerner gamle loggfiler...</target>
<source>You can switch to FreeFileSync's main window to resolve this issue.</source>
<target>Skift til FreeFileSyncs hovedvindu for at løse problemet.</target>
diff --git a/FreeFileSync/Build/Languages/polish.lng b/FreeFileSync/Build/Languages/polish.lng
index fc602fc4..8a808194 100644
--- a/FreeFileSync/Build/Languages/polish.lng
+++ b/FreeFileSync/Build/Languages/polish.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Aktualizuj atrybuty po prawej stronie</target>
-<source>Cannot read file %x.</source>
-<target>Nie można odczytać pliku %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Nie można zapisać uprawnień %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operacja nie jest wspierana dla różnych typów katalogów.</target>
+
+<source>Cannot write file %x.</source>
+<target>Nie można zapisać pliku %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Oczekiwany: %x bajtów
Przesłany: %y bajtów
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Nie można zapisać uprawnień %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operacja nie jest wspierana dla różnych typów katalogów.</target>
-
-<source>Cannot write file %x.</source>
-<target>Nie można zapisać pliku %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Nie można skopiować linku symbolicznego %x do %y.</target>
@@ -255,6 +252,9 @@ Przesłany: %y bajtów
<source>Cannot open file %x.</source>
<target>Nie można otworzyć pliku %x.</target>
+<source>Cannot read file %x.</source>
+<target>Nie można odczytać pliku %x.</target>
+
<source>Cannot find device %x.</source>
<target>Nie można odnaleźć urządzenia %x.</target>
@@ -1626,8 +1626,8 @@ program kopiuje zawartość do pliku tymczasowego (*.ffs_tmp), a następnie nadp
<source>Unable to connect to www.freefilesync.org.</source>
<target>Nie można połączyć się z www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Nie można znaleźć obecnej wersji FreeFileSync. Czy chcesz sprawdzić ręcznie?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>S&prawdź</target>
@@ -1665,12 +1665,12 @@ program kopiuje zawartość do pliku tymczasowego (*.ffs_tmp), a następnie nadp
<source>Cannot find system function %x.</source>
<target>Nie można odnaleźć funkcji systemowej %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Nie można skopiować atrybutów z %x do %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Nie można skopiować pliku %x do %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Nie można skopiować atrybutów z %x do %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Element typu %x nie jest wspierany:</target>
@@ -1800,6 +1800,9 @@ program kopiuje zawartość do pliku tymczasowego (*.ffs_tmp), a następnie nadp
<source>Thanks for your donation and support!</source>
<target>Dziękujemy za wsparcie i dotacje!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Ta wersja instalatora FreeFileSync osiągneła swój limit instalacji. Pobrać zwykłą wersję ze strony FreeFileSync?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/portuguese.lng b/FreeFileSync/Build/Languages/portuguese.lng
index 7e6ce0b6..73f7f010 100644
--- a/FreeFileSync/Build/Languages/portuguese.lng
+++ b/FreeFileSync/Build/Languages/portuguese.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Actualizar atributos à direita</target>
-<source>Cannot read file %x.</source>
-<target>Não é possível ler o ficheiro %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Não é possível escrever as permissões de %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operação sem suporte para tipos de pastas base distintas.</target>
+
+<source>Cannot write file %x.</source>
+<target>Não é possível escrever o ficheiro %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Esperado: %x bytes
Actual: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Não é possível escrever as permissões de %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operação sem suporte para tipos de pastas base distintas.</target>
-
-<source>Cannot write file %x.</source>
-<target>Não é possível escrever o ficheiro %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Não é possível criar o link simbólico de %x para %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>Não é possível abrir o ficheiro %x.</target>
+<source>Cannot read file %x.</source>
+<target>Não é possível ler o ficheiro %x.</target>
+
<source>Cannot find device %x.</source>
<target>Não é possível encontrar o dispositivo %x.</target>
@@ -1615,8 +1615,8 @@ Isto garante um estado consistente mesmo em caso de falha grave.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Não é possível ligar a www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Não é possível encontrar a última versão do FreeFileSync online. Deseja verificar manualmente?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Verificar</target>
@@ -1654,12 +1654,12 @@ Isto garante um estado consistente mesmo em caso de falha grave.
<source>Cannot find system function %x.</source>
<target>Não é possível encontrar a função do sistema %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Não é possível copiar os atributos de %x para %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Não é possível copiar o ficheiro %x para %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Não é possível copiar os atributos de %x para %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Tipo de item %x não é suportado:</target>
@@ -1786,6 +1786,9 @@ Isto garante um estado consistente mesmo em caso de falha grave.
<source>Thanks for your donation and support!</source>
<target>Obrigado pela sua doação e apoio!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Este instalador para doadores do FreeFileSync atingiu seu limite de instalação. Descarregar a versão normal na página do FreeFileSync agora?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/portuguese_br.lng b/FreeFileSync/Build/Languages/portuguese_br.lng
index 5207e0f1..82faeea6 100644
--- a/FreeFileSync/Build/Languages/portuguese_br.lng
+++ b/FreeFileSync/Build/Languages/portuguese_br.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Atualizar atributos à direita</target>
-<source>Cannot read file %x.</source>
-<target>Não foi possível ler o arquivo %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Não foi possível escrever as permissões de %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operação não suportada para tipos de pastas de base diferentes.</target>
+
+<source>Cannot write file %x.</source>
+<target>Não foi possível escrever o arquivo %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Esperado: %x bytes
Atual: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Não foi possível escrever as permissões de %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operação não suportada para tipos de pastas de base diferentes.</target>
-
-<source>Cannot write file %x.</source>
-<target>Não foi possível escrever o arquivo %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Não foi possível copiar o link simbólico %x para %y.</target>
@@ -255,6 +252,9 @@ Atual: %y bytes
<source>Cannot open file %x.</source>
<target>Não foi possível abrir o arquivo %x.</target>
+<source>Cannot read file %x.</source>
+<target>Não foi possível ler o arquivo %x.</target>
+
<source>Cannot find device %x.</source>
<target>Não foi possível encontrar o dispositivo %x.</target>
@@ -1615,8 +1615,8 @@ Isto garante um estado consistente mesmo em caso de erro grave.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Não foi possível conectar a www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Não foi possível encontrar a versão atual do FreeFileSync online. Deseja verificar manualmente?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Verificar</target>
@@ -1654,12 +1654,12 @@ Isto garante um estado consistente mesmo em caso de erro grave.
<source>Cannot find system function %x.</source>
<target>Não foi possível localizar a função de sistema %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Não foi possível copiar os atributos de %x para %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Não foi possível copiar o arquivo %x para %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Não foi possível copiar os atributos de %x para %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Tipo de item %x não é suportado:</target>
@@ -1786,6 +1786,9 @@ Isto garante um estado consistente mesmo em caso de erro grave.
<source>Thanks for your donation and support!</source>
<target>Obrigado pela sua doação e suporte!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Este instalador do FreeFileSync para doadores atingiu seu limite de instalação. Baixar a versão regular da página do FreeFileSync agora?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/romanian.lng b/FreeFileSync/Build/Languages/romanian.lng
index f38efc04..5dc84db8 100644
--- a/FreeFileSync/Build/Languages/romanian.lng
+++ b/FreeFileSync/Build/Languages/romanian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Actualizează atributele în partea dreaptă</target>
-<source>Cannot read file %x.</source>
-<target>Nu pot citi fila %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Nu pot scrie permisiunile lui %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operație nesuportată pentru tipuri diferite de dosare bază (rădăcină).</target>
+
+<source>Cannot write file %x.</source>
+<target>Nu pot scrie fila %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Așteptată: %x baiți
Actuală: %y baiți
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Nu pot scrie permisiunile lui %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operație nesuportată pentru tipuri diferite de dosare bază (rădăcină).</target>
-
-<source>Cannot write file %x.</source>
-<target>Nu pot scrie fila %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Nu pot copia legătura simbolică %x în %y.</target>
@@ -255,6 +252,9 @@ Actuală: %y baiți
<source>Cannot open file %x.</source>
<target>Nu pot deschide fila %x.</target>
+<source>Cannot read file %x.</source>
+<target>Nu pot citi fila %x.</target>
+
<source>Cannot find device %x.</source>
<target>Nu pot găsi dispozitivul %x.</target>
@@ -1626,8 +1626,8 @@ Aceasta garantează consecvența stării filelor chiar și în cazul apariției
<source>Unable to connect to www.freefilesync.org.</source>
<target>Nu pot face conectarea la www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Nu pot afla numărul versiunii FreeFileSync disponibile acum pe internet. Vrei să-l cauți manual?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Verifică</target>
@@ -1665,12 +1665,12 @@ Aceasta garantează consecvența stării filelor chiar și în cazul apariției
<source>Cannot find system function %x.</source>
<target>Nu pot găsi funcția de sistem %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Nu pot copia atributele de pe %x pe %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Nu pot copia fila %x în %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Nu pot copia atributele de pe %x pe %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Tipul de element %x nu e suportat:</target>
@@ -1800,6 +1800,9 @@ Aceasta garantează consecvența stării filelor chiar și în cazul apariției
<source>Thanks for your donation and support!</source>
<target>Mulțumiri pentru donația și sprijinul tău!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Acest instalator FreeFileSync pentru donatori și-a atins limita de instalări permise. Descarci acum versiunea obișnuită de pe situl FreeFileSync?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/russian.lng b/FreeFileSync/Build/Languages/russian.lng
index 92d47eee..74fd26f7 100644
--- a/FreeFileSync/Build/Languages/russian.lng
+++ b/FreeFileSync/Build/Languages/russian.lng
@@ -7,6 +7,15 @@
<plural_definition>n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<11 || n%100>14) ? 1 : 2</plural_definition>
</header>
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
+
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
+
<source>Both sides have changed since last synchronization.</source>
<target>Со времени поÑледней Ñинхронизации Ñ Ð¾Ð±ÐµÐ¸Ñ… Ñторон произошли изменениÑ.</target>
@@ -20,10 +29,7 @@
<target>ЗапиÑÑŒ в базе данных не находитÑÑ Ð² ÑоÑтоÑнии Ñинхронизации, ÑƒÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ðµ наÑтройки.</target>
<source>Setting default synchronization directions: Old files will be overwritten with newer files.</source>
-<target>
-ÐаÑтройка Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñинхронизации по умолчанию:
-Старые файлы будут перезапиÑаны более новыми файлами.
-</target>
+<target>ÐаÑтройка Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñинхронизации по умолчанию: Старые файлы будут перезапиÑаны более новыми файлами.</target>
<source>Creating folder %x</source>
<target>Создание папки %x</target>
@@ -217,8 +223,14 @@
<source>Update attributes on right</source>
<target>Обновление атрибутов Ñправа</target>
-<source>Cannot read file %x.</source>
-<target>Ðевозможно прочитать файл %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Ðевозможно запиÑать права доÑтупа %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ поддерживаетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð½Ñ‹Ñ… базовых типов папок.</target>
+
+<source>Cannot write file %x.</source>
+<target>Ðевозможно запиÑать файл %x.</target>
<source>
Unexpected size of data stream.
@@ -231,15 +243,6 @@ Actual: %y bytes
ФактичеÑкий: %y байт
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Ðевозможно запиÑать права доÑтупа %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ поддерживаетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð½Ñ‹Ñ… базовых типов папок.</target>
-
-<source>Cannot write file %x.</source>
-<target>Ðевозможно запиÑать файл %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Ðевозможно Ñкопировать Ñимвольную ÑÑылку %x в %y.</target>
@@ -258,6 +261,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>Ðевозможно открыть файл %x.</target>
+<source>Cannot read file %x.</source>
+<target>Ðевозможно прочитать файл %x.</target>
+
<source>Cannot find device %x.</source>
<target>Ðевозможно найти уÑтройÑтво %x.</target>
@@ -1071,11 +1077,7 @@ The command is triggered if:
<target>ОÑтановить</target>
<source>Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x</source>
-<target>
-Создать файл пакетного Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкой Ñинхронизации.
-Ð”Ð»Ñ Ð·Ð°Ð¿ÑƒÑка дважды кликните Ñтот файл или запланируйте
-в планировщике задач: %x
-</target>
+<target>Создать файл пакетного Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкой Ñинхронизации. Ð”Ð»Ñ Ð·Ð°Ð¿ÑƒÑка дважды кликните Ñтот файл или запланируйте в планировщике задач: %x</target>
<source>&Stop</source>
<target>&ОÑтановить</target>
@@ -1508,10 +1510,7 @@ This guarantees a consistent state even in case of a serious error.
<target>Копировать DACL, SACL, владелец, группа</target>
<source>Integrate external applications into context menu. The following macros are available:</source>
-<target>
-Интегрируйте внешние Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² контекÑтное меню.
-ДоÑтупны Ñледующие команды:
-</target>
+<target>Интегрируйте внешние Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² контекÑтное меню. ДоÑтупны Ñледующие команды:</target>
<source>- full file or folder name</source>
<target>- полный путь файла или папки</target>
@@ -1636,9 +1635,6 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Ðевозможно ÑоединитьÑÑ Ñ www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Ðевозможно найти номер текущей верÑии FreeFileSync онлайн! Ð’Ñ‹ хотите проверить вручную?</target>
-
<source>&Check</source>
<target>&Проверить</target>
@@ -1675,12 +1671,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>Ðевозможно найти ÑиÑтемную функцию %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Ðевозможно Ñкопировать атрибуты от %x к %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Ðевозможно Ñкопировать файл %x в %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Ðевозможно Ñкопировать атрибуты от %x к %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Тип Ñлемента %x не поддерживаетÑÑ:</target>
@@ -1810,6 +1806,3 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>СпаÑибо за Ваше пожертвование и поддержку!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Ð”Ð»Ñ Ñтого уÑтановщика FreeFileSync Ð´Ð»Ñ Ð´Ð¾Ð½Ð¾Ñ€Ð¾Ð² был превышен лимит уÑтановок. Скачать обычную верÑию Ñ Ð´Ð¾Ð¼Ð°ÑˆÐ½ÐµÐ¹ Ñтраницы FreeFileSync ÑейчаÑ?</target>
-
diff --git a/FreeFileSync/Build/Languages/serbian.lng b/FreeFileSync/Build/Languages/serbian.lng
index bb3975ed..55f61c4b 100644
--- a/FreeFileSync/Build/Languages/serbian.lng
+++ b/FreeFileSync/Build/Languages/serbian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>ОÑвежи атрибуте деÑно</target>
-<source>Cannot read file %x.</source>
-<target>Ðе могу читати датотеку %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Ðе могу упиÑати овлашћења за %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Операција није подржана за различите типове оÑновних фолдера.</target>
+
+<source>Cannot write file %x.</source>
+<target>Ðе могу упиÑати датотеку %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
Стварно: %y бајтова
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Ðе могу упиÑати овлашћења за %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Операција није подржана за различите типове оÑновних фолдера.</target>
-
-<source>Cannot write file %x.</source>
-<target>Ðе могу упиÑати датотеку %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Ðе могу копирати Ñимболичну везу %x у %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>Ðе могу отворити датотеку %x.</target>
+<source>Cannot read file %x.</source>
+<target>Ðе могу читати датотеку %x.</target>
+
<source>Cannot find device %x.</source>
<target>Ðе могу пронаћи уређај %x.</target>
@@ -1626,8 +1626,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Ðе може Ñе уÑпоÑтавити веза Ñа www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Ðе могу на мрежи пронаћи тренутни број верзије FreeFileSync-а. Да ли желите да проверите ручно?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Провера</target>
@@ -1665,12 +1665,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>Ðе могу пронаћи ÑиÑтемÑку функцију %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Ðе могу копирати атрибуте од %x у %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Ðе могу копирати датотеку %x на %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Ðе могу копирати атрибуте од %x у %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Тип Ñтавке %x није подржан:</target>
@@ -1800,6 +1800,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>Хвала за вашу донацију и подршку!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Ова FreeFileSync инÑталација за донаторе доÑтигла је Ñвоју границу инÑталиÑања. Преузети регуларну верзију Ñа веб Ñтранице FreeFileSync-а?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/slovak.lng b/FreeFileSync/Build/Languages/slovak.lng
new file mode 100644
index 00000000..c7d78a3e
--- /dev/null
+++ b/FreeFileSync/Build/Languages/slovak.lng
@@ -0,0 +1,1805 @@
+<header>
+ <language>SlovenÄina</language>
+ <translator>slavusec</translator>
+ <locale>sk_SK</locale>
+ <image>flag_slovakia.png</image>
+ <plural_count>3</plural_count>
+ <plural_definition>n==1 ? 0 : n>=2 && n<=4 ? 1 : 2</plural_definition>
+</header>
+
+<source>Both sides have changed since last synchronization.</source>
+<target>Od poslednej synchronizácie došlo ku zmene obidvoch strán.</target>
+
+<source>Cannot determine sync-direction:</source>
+<target>Nie je možné urÄit smer synchronizácie:</target>
+
+<source>No change since last synchronization.</source>
+<target>Žiadne zmeny od poslednej synchronizácie.</target>
+
+<source>The database entry is not in sync considering current settings.</source>
+<target>Databázové položky nie sú podľa aktuálnej konfigurácie synchronné.</target>
+
+<source>Setting default synchronization directions: Old files will be overwritten with newer files.</source>
+<target>Je nastavený predvolený spôsob synchronizácie: Staré súbory budú nahradené novými.</target>
+
+<source>Creating folder %x</source>
+<target>Vytváranie prieÄinka %x</target>
+
+<source>Creating file %x</source>
+<target>Vytváranie súboru %x</target>
+
+<source>Creating symbolic link %x</source>
+<target>Vytváranie symbolického odkazu %x</target>
+
+<source>Moving file %x to the recycle bin</source>
+<target>Presúvanie súboru %x do Koša</target>
+
+<source>Moving folder %x to the recycle bin</source>
+<target>Presúvanie prieÄinka %x do KoÅ¡a</target>
+
+<source>Moving symbolic link %x to the recycle bin</source>
+<target>Presúvanie symbolického odkazu %x do Koša</target>
+
+<source>Deleting file %x</source>
+<target>Zmazanie súboru %x</target>
+
+<source>Deleting folder %x</source>
+<target>Zmazanie prieÄinka %x</target>
+
+<source>Deleting symbolic link %x</source>
+<target>Zmazanie symbolického odkazu %x</target>
+
+<source>Checking recycle bin availability for folder %x...</source>
+<target>Kontrola KoÅ¡a pre prieÄinok %x ...</target>
+
+<source>The recycle bin is not available for the following folders. Files will be deleted permanently instead:</source>
+<target>Nie je možné použiÅ¥ KoÅ¡ pre následujúce prieÄinky. Súbory budú odstránené permanentne:</target>
+
+<source>An exception occurred</source>
+<target>Vyskytla sa chyba</target>
+
+<source>A directory path is expected after %x.</source>
+<target>OÄakávaná adresárová cesta po %x.</target>
+
+<source>Syntax error</source>
+<target>Chyba syntaxu</target>
+
+<source>Cannot find file %x.</source>
+<target>Nie je možné nájsť súbor %x.</target>
+
+<source>Error</source>
+<target>Chyba</target>
+
+<source>File %x does not contain a valid configuration.</source>
+<target>Súbor %x neobsahuje platnú konfiguráciu.</target>
+
+<source>Unequal number of left and right directories specified.</source>
+<target>Bol zistený nezhodný poÄet ľavých a pravých adresárov.</target>
+
+<source>The config file must not contain settings at directory pair level when directories are set via command line.</source>
+<target>KonfiguraÄný súbor nesmie obsahovaÅ¥ nastavenia na úrovni adresárových párov pokiaľ je zadány cez príkazový riadok.</target>
+
+<source>Directories cannot be set for more than one configuration file.</source>
+<target>Adresáre nemôžu obsahovaÅ¥ viac ako jeden konfiguraÄný súbor.</target>
+
+<source>Command line</source>
+<target>Príkazový riadok</target>
+
+<source>Syntax:</source>
+<target>Syntax:</target>
+
+<source>global config file:</source>
+<target>globálny konfiguraÄný súbor:</target>
+
+<source>config files:</source>
+<target>konfiguraÄné súbory:</target>
+
+<source>directory</source>
+<target>adresár</target>
+
+<source>Path to an alternate GlobalSettings.xml file.</source>
+<target>Cesta k alternatívnemu súboru GlobalSettings.xml.</target>
+
+<source>Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files.</source>
+<target>Ľubovolný poÄet konfiguraÄných súborov FreeFileSync typu .ffs_gui a/alebo .ffs_batch.</target>
+
+<source>Any number of alternative directory pairs for at most one config file.</source>
+<target>Ľubovolný poÄet alternatívnych dvojíc adresárov na aspoň jednu konfiguráciu.</target>
+
+<source>Open configuration for editing without executing it.</source>
+<target>Otvriť konfiguráciu pre editáciu bez jej spustenia.</target>
+
+<source>Cannot find the following folders:</source>
+<target>Nie je možné nájsÅ¥ následujúce prieÄinky:</target>
+
+<source>If you ignore this error the folders will be considered empty. Missing folders are created automatically when needed.</source>
+<target>Ak budete túto chybu ignorovaÅ¥, prieÄinok bude považovaný za prázdny. Chýbajuce prieÄinky budú podľa potreby automaticky vytvorené.</target>
+
+<source>A folder input field is empty.</source>
+<target>Nie je zadaná vstupný prieÄinok.</target>
+
+<source>The corresponding folder will be considered as empty.</source>
+<target>Odpovedajúci prieÄinok bude považovaný za prázdny.</target>
+
+<source>The following folder paths are dependent from each other:</source>
+<target>Následujúce prieÄinky majú navzájom závislé cesty:</target>
+
+<source>File %x has an invalid date.</source>
+<target>Súbor %x má chybný dátum.</target>
+
+<source>Date:</source>
+<target>Dátum:</target>
+
+<source>Files %x have the same date but a different size.</source>
+<target>Súbory %x majú rovnaký dátum a Äas ale rozdieľnu veľkosÅ¥.</target>
+
+<source>Size:</source>
+<target>Veľkosť:</target>
+
+<source>Content comparison was skipped for excluded files %x.</source>
+<target>Porovnanie obsahu bolo vynechané pre súbory %x.</target>
+
+<source>Items differ in attributes only</source>
+<target>Položky se lišia iba v atribútoch</target>
+
+<source>Resolving symbolic link %x</source>
+<target>Nasledovať odkaz symbolického zástupcu %x</target>
+
+<source>Comparing content of files %x</source>
+<target>Porovnávanie obsahu súborov %x</target>
+
+<source>Generating file list...</source>
+<target>Vytváranie zoznamu súborov...</target>
+
+<source>Starting comparison</source>
+<target>Spustiť porovnávania</target>
+
+<source>Calculating sync directions...</source>
+<target>Príprava adresárov synchronizácie...</target>
+
+<source>Out of memory.</source>
+<target>Nedostatok pracovnej pamäti.</target>
+
+<source>Item exists on left side only</source>
+<target>Položky existujúce iba vľavo</target>
+
+<source>Item exists on right side only</source>
+<target>Položky existujúce iba vpravo</target>
+
+<source>Left side is newer</source>
+<target>Ľavá strana je novšia</target>
+
+<source>Right side is newer</source>
+<target>Pravá strana je novšia</target>
+
+<source>Items have different content</source>
+<target>Obsah položiek je rozdielny</target>
+
+<source>Both sides are equal</source>
+<target>Obe strany sú zhodné</target>
+
+<source>Conflict/item cannot be categorized</source>
+<target>Konflikty/položky ktoré nemožno zaradiť</target>
+
+<source>Copy new item to left</source>
+<target>Kopírovať novú položku doľava</target>
+
+<source>Copy new item to right</source>
+<target>Kopírovať novou položku doprava</target>
+
+<source>Delete left item</source>
+<target>Zmazať položku naľavo</target>
+
+<source>Delete right item</source>
+<target>Zmazať položku napravo</target>
+
+<source>Move file on left</source>
+<target>Presunúť súbor naľavo</target>
+
+<source>Move file on right</source>
+<target>Presunúť súbor napravo</target>
+
+<source>Update left item</source>
+<target>Aktualizovať ľavú položku</target>
+
+<source>Update right item</source>
+<target>Aktualizovať pravú položku</target>
+
+<source>Do nothing</source>
+<target>NerobiÅ¥ niÄ</target>
+
+<source>Update attributes on left</source>
+<target>Aktualizovať atribúty naľavo</target>
+
+<source>Update attributes on right</source>
+<target>Aktualizovať atribúty napravo</target>
+
+<source>Cannot write permissions of %x.</source>
+<target>Nie je možné zapísať oprávnenie pre %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operácia nie je podporovaná pre rozdielne typy základných prieÄinkov.</target>
+
+<source>Cannot write file %x.</source>
+<target>Nie je možné zapísať súbor %x.</target>
+
+<source>
+Unexpected size of data stream.
+Expected: %x bytes
+Actual: %y bytes
+</source>
+<target>
++NeoÄakávana veľkosÅ¥ dat. streamu.
+OÄakávané: %x b
+Aktuálne: %y b
+</target>
+
+<source>Cannot copy symbolic link %x to %y.</source>
+<target>Nie je možné kopírovať symbolický odkaz %x do %y.</target>
+
+<source>Cannot move file %x to %y.</source>
+<target>Nie je možné presunúť súbor %x do %y.</target>
+
+<source>Cannot enumerate directory %x.</source>
+<target>Nie je možné prechádzať adresár %x.</target>
+
+<source>Cannot read file attributes of %x.</source>
+<target>Nie je možné naÄítaÅ¥ atribúty súboru %x.</target>
+
+<source>Cannot find %x.</source>
+<target>Nie je možné nájsť %x.</target>
+
+<source>Cannot open file %x.</source>
+<target>Nie je možné otvoriť súbor %x.</target>
+
+<source>Cannot read file %x.</source>
+<target>Nie je možné ÄítaÅ¥ súbor %x.</target>
+
+<source>Cannot find device %x.</source>
+<target>Nie je možné nájsť zariadenie %x.</target>
+
+<source>Cannot create directory %x.</source>
+<target>Nie je možné vytvoriť adresár %x.</target>
+
+<source>Cannot delete directory %x.</source>
+<target>Nie je možné zmazať adresár %x.</target>
+
+<source>Cannot delete file %x.</source>
+<target>Nie je možné zmazať súbor %x.</target>
+
+<source>Cannot write modification time of %x.</source>
+<target>Nie je možné zmeniÅ¥ atribút Äasu zmeny pre %x.</target>
+
+<source>Cannot determine final path for %x.</source>
+<target>Nie je možné urÄiÅ¥ koneÄnú cestu pre %x.</target>
+
+<source>Cannot resolve symbolic link %x.</source>
+<target>Nie je možné nájsť odkaz zástupcu %x.</target>
+
+<source>Cannot open directory %x.</source>
+<target>Nie je možné otvoriť adresár %x.</target>
+
+<source>Cannot determine free disk space for %x.</source>
+<target>Nie je možné zistiť voľné miesto na disku %x.</target>
+
+<source>Unable to move %x to the recycle bin.</source>
+<target>Nie je možné presunúť %x do Koša.</target>
+
+<source>Incorrect command line:</source>
+<target>Neplatný príkaz:</target>
+
+<source>Error Code %x:</source>
+<target>Chybový kód %x:</target>
+
+<source>Failed to connect to SFTP server %x.</source>
+<target>Nepodarilo sa pripojiť k SFTP servru %x.</target>
+
+<source>
+<pluralform>1 byte</pluralform>
+<pluralform>%x bytes</pluralform>
+</source>
+<target>
+<pluralform>%x B</pluralform>
+<pluralform>%x B</pluralform>
+<pluralform>%x B</pluralform>
+</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>Cannot load file %x.</source>
+<target>Nie je možné naÄítaÅ¥ súbor %x.</target>
+
+<source>Database file %x is incompatible.</source>
+<target>Databázy súbor %x je nekompatibilný.</target>
+
+<source>Initial synchronization:</source>
+<target>Prvá synchronizácia:</target>
+
+<source>Database file %x does not yet exist.</source>
+<target>Databázový súbor %x neexistuje.</target>
+
+<source>Database file is corrupt:</source>
+<target>Databázový súbor je poškodená:</target>
+
+<source>Database files do not share a common session.</source>
+<target>Databázové súbory nie sú navzájom komplementárne.</target>
+
+<source>Searching for folder %x...</source>
+<target>Vyhľadávanie prieÄinka %x...</target>
+
+<source>Time out while searching for folder %x.</source>
+<target>VyprÅ¡al Äasový limit pre nájdenie prieÄinka %x.</target>
+
+<source>Cannot get process information.</source>
+<target>Nie je možné získať informácie procesu.</target>
+
+<source>Waiting while directory is locked:</source>
+<target>Čakanie na uzamknutie adresára:</target>
+
+<source>Lock owner:</source>
+<target>Vlastník uzamknutia:</target>
+
+<source>
+<pluralform>1 sec</pluralform>
+<pluralform>%x sec</pluralform>
+</source>
+<target>
+<pluralform>1 sekunda</pluralform>
+<pluralform>%x sekundy</pluralform>
+<pluralform>%x sekúnd</pluralform>
+</target>
+
+<source>Detecting abandoned lock...</source>
+<target>Preverovanie uzamknutia...</target>
+
+<source>Saving file %x...</source>
+<target>Ukládanie súboru %x...</target>
+
+<source>Items processed:</source>
+<target>Spracovaných položiek:</target>
+
+<source>Items remaining:</source>
+<target>Ostáva položiek:</target>
+
+<source>Total time:</source>
+<target>Celkový Äas:</target>
+
+<source>Error parsing file %x, row %y, column %z.</source>
+<target>Chyba spracovania súboru %x: na riadku %y v stĺpci %z.</target>
+
+<source>Cannot set directory lock for %x.</source>
+<target>Nie je možné nastaviť zámok adresára %x.</target>
+
+<source>
+<pluralform>1 thread</pluralform>
+<pluralform>%x threads</pluralform>
+</source>
+<target>
+<pluralform>1 proces</pluralform>
+<pluralform>%x procesy</pluralform>
+<pluralform>%x procesov</pluralform>
+</target>
+
+<source>Scanning:</source>
+<target>Vyhľadávanie:</target>
+
+<source>/sec</source>
+<target>/s</target>
+
+<source>%x items/sec</source>
+<target>%x položiek/s</target>
+
+<source>Show in Explorer</source>
+<target>Zobraziť v Prieskumníkovi</target>
+
+<source>Open with default application</source>
+<target>Otvoriť predvolenou aplikáciou</target>
+
+<source>Browse directory</source>
+<target>Prechádzať adresár</target>
+
+<source>Cannot access the Volume Shadow Copy Service.</source>
+<target>Nie je prístup k službe Tieňové kópie.</target>
+
+<source>Please use FreeFileSync 64-bit version to create shadow copies on this system.</source>
+<target>Prosím použite FreeFileSync 64-bitovou verziu pre použitie služby Tieňové kópie.</target>
+
+<source>Cannot determine volume name for %x.</source>
+<target>>Nie je možné zistiť názov jednotky pre %x.</target>
+
+<source>Volume name %x is not part of file path %y.</source>
+<target>Názov disku %x nie je súÄásÅ¥ou cesty súboru %y.</target>
+
+<source>Stop requested: Waiting for current operation to finish...</source>
+<target>Zastavovanie: ÄŒakanie na dokonÄenie práve prebiehajúcej operácie...</target>
+
+<source>Unable to create time stamp for versioning:</source>
+<target>Nie je možné vytvoriÅ¥ Äasovú znaÄku verzovania:</target>
+
+<source>Drag && drop</source>
+<target>Pretiahni sem && pusť</target>
+
+<source>Cannot find folder %x.</source>
+<target>Nie je možné nájsÅ¥ prieÄinok %x.</target>
+
+<source>Select a folder</source>
+<target>Vyberte prieÄinok</target>
+
+<source>&Open...</source>
+<target>&Otvoriť...</target>
+
+<source>Save &as...</source>
+<target>Uložiť &ako...</target>
+
+<source>E&xit</source>
+<target>U&konÄiÅ¥</target>
+
+<source>&File</source>
+<target>&Súbor</target>
+
+<source>&View help</source>
+<target>&Nápoveda (iba anglicky)</target>
+
+<source>&About</source>
+<target>O &programe</target>
+
+<source>&Help</source>
+<target>&Pomoc</target>
+
+<source>Usage:</source>
+<target>Použitie:</target>
+
+<source>1. Select folders to watch.</source>
+<target>1. Vyberte prieÄinok k sledovaniu.</target>
+
+<source>2. Enter a command line.</source>
+<target>2. Zadajte príkazový riadok.</target>
+
+<source>3. Press 'Start'.</source>
+<target>3. StlaÄte 'Å tart'.</target>
+
+<source>To get started just import a .ffs_batch file.</source>
+<target>Môžete naÄítaÅ¥ tiež konfiguraÄný súbor .ffs_batch.</target>
+
+<source>Folders to watch:</source>
+<target>Sledované prieÄinka:</target>
+
+<source>Add folder</source>
+<target>PridaÅ¥ prieÄinok</target>
+
+<source>Remove folder</source>
+<target>OdstrániÅ¥ prieÄinok</target>
+
+<source>Browse</source>
+<target>Prechádzať</target>
+
+<source>Idle time (in seconds):</source>
+<target>Doba neÄinnosti (v sekundách):</target>
+
+<source>Idle time between last detected change and execution of command</source>
+<target>Doba neÄinnosti medzi zistením poslednej zmeny a spustením príkazu</target>
+
+<source>Command line:</source>
+<target>Príkazový riadok:</target>
+
+<source>
+The command is triggered if:
+- files or subfolders change
+- new folders arrive (e.g. USB stick insert)
+</source>
+<target>
+Príkaz bude spustení ak:
+- dôjde k zmene v súboru alebo v prieÄinku
+- je zistený nový prieÄinok (napr. vložením USB disku)
+</target>
+
+<source>Start</source>
+<target>Å tart</target>
+
+<source>About</source>
+<target>O programe</target>
+
+<source>Build: %x</source>
+<target>Verzia: %x</target>
+
+<source>All files</source>
+<target>Všetky súbory</target>
+
+<source>Automated Synchronization</source>
+<target>Automatická synchronizácia</target>
+
+<source>The following path does not support directory monitoring:</source>
+<target>Následujúca cesta nepodporuje sledovanie adresárov:</target>
+
+<source>Directory monitoring active</source>
+<target>Sledovanie adresárov je aktivne</target>
+
+<source>Waiting until all directories are available...</source>
+<target>Čakanie na nedostupné adresáre...</target>
+
+<source>&Restore</source>
+<target>&Obnoviť</target>
+
+<source>&Show error</source>
+<target>&Zobraziť chybu</target>
+
+<source>&Quit</source>
+<target>U&konÄiÅ¥</target>
+
+<source>&Retry</source>
+<target>&Opakovať</target>
+
+<source>File time and size</source>
+<target>Podľa Äasu a veľkosti súboru</target>
+
+<source>File content</source>
+<target>Podľa obsahu súboru</target>
+
+<source>File size</source>
+<target>Podľa veľkosti súboru</target>
+
+<source>Two way</source>
+<target>Dve cesty</target>
+
+<source>Mirror</source>
+<target>Zrkadlenie</target>
+
+<source>Update</source>
+<target>Aktualizácia</target>
+
+<source>Custom</source>
+<target>Vlastné</target>
+
+<source>Multiple...</source>
+<target>Rôzne...</target>
+
+<source>Moving file %x to %y</source>
+<target>Presúvanie súboru %x do %y</target>
+
+<source>Moving folder %x to %y</source>
+<target>Presúvanie prieÄinka %x do %y</target>
+
+<source>Moving symbolic link %x to %y</source>
+<target>Presúvanie symbolického odkazu %x do %y</target>
+
+<source>Removing old versions...</source>
+<target>Odstráňovanie starých verzií...</target>
+
+<source>Updating file %x</source>
+<target>Aktualizácia súboru %x</target>
+
+<source>Updating symbolic link %x</source>
+<target>Aktualizácia symbolického odkazu %x</target>
+
+<source>Verifying file %x</source>
+<target>Verifikácia súboru %x</target>
+
+<source>Updating attributes of %x</source>
+<target>Aktualizácia atribútov súboru %x</target>
+
+<source>%x and %y have different content.</source>
+<target>%x a %y majú odlišný obsah.</target>
+
+<source>Data verification error:</source>
+<target>Chyba verifikácie údajov:</target>
+
+<source>Creating a Volume Shadow Copy for %x...</source>
+<target>Vytváranie Tieňovej kópie zväzkov pre %x...</target>
+
+<source>Target folder %x already existing.</source>
+<target>Cieľový prieÄinok %x už existuje.</target>
+
+<source>Target folder input field must not be empty.</source>
+<target>Cieľový prieÄinok nesmie byÅ¥ prázdny.</target>
+
+<source>Source folder %x not found.</source>
+<target>Zdrojový prieÄinok %x nie je možné nájsÅ¥.</target>
+
+<source>Please enter a target folder for versioning.</source>
+<target>Prosím zadajte cieľový prieÄinok pre archívovanie.</target>
+
+<source>The following items have unresolved conflicts and will not be synchronized:</source>
+<target>Následujúce položky majú nevyriešené konflikty a nebudú synchronizované:</target>
+
+<source>The following folders are significantly different. Make sure you have selected the correct folders for synchronization.</source>
+<target>Následujúce prieÄinky sa významne liÅ¡ia. Skontrolujte Äi máte vybránu správnu dvojicu prieÄinkov pre synchronizáciu.</target>
+
+<source>Not enough free disk space available in:</source>
+<target>Nedostatok miesta na disku:</target>
+
+<source>Required:</source>
+<target>Požadované:</target>
+
+<source>Available:</source>
+<target>K dispozícií:</target>
+
+<source>Multiple folder pairs write to a common subfolder. Please review your configuration.</source>
+<target>Viac prieÄinkov obsahuje spoleÄný podprieÄinok. Prosím skontrolujte si nastavenia synchronizácie.</target>
+
+<source>Synchronizing folder pair:</source>
+<target>Synchronizácia dvojice prieÄinkov:</target>
+
+<source>Generating database...</source>
+<target>Vytváranie databázy...</target>
+
+<source>job name</source>
+<target>názov úlohy</target>
+
+<source>Synchronization stopped</source>
+<target>Synchronizácia je zastavená</target>
+
+<source>Stopped</source>
+<target>Zastavené</target>
+
+<source>Synchronization completed with errors</source>
+<target>Synchronizácia dokonÄena s chybami</target>
+
+<source>Synchronization completed with warnings</source>
+<target>Synchronizácia dokonÄena s varovaním</target>
+
+<source>Warning</source>
+<target>Varovanie</target>
+
+<source>Nothing to synchronize</source>
+<target>Nie je Äo synchronizovaÅ¥</target>
+
+<source>Synchronization completed successfully</source>
+<target>Synchronizácia je úspeÅ¡ne dokonÄená</target>
+
+<source>Cleaning up old log files...</source>
+<target>Odstráňovanie starých log súborov...</target>
+
+<source>You can switch to FreeFileSync's main window to resolve this issue.</source>
+<target>K odstráneniu tohoto problému sa môžete prepnúť do hlavného okna FreeFileSync.</target>
+
+<source>&Don't show this warning again</source>
+<target>&Nezobrazovať znova toto varovanie</target>
+
+<source>&Ignore</source>
+<target>&Ignorovať</target>
+
+<source>&Switch</source>
+<target>&Prepnúť</target>
+
+<source>Switching to FreeFileSync's main window</source>
+<target>Prepínanie do hlavného okna FreeFileSync</target>
+
+<source>
+<pluralform>Automatic retry in 1 second...</pluralform>
+<pluralform>Automatic retry in %x seconds...</pluralform>
+</source>
+<target>
+<pluralform>Automatické opakovanie za 1 sekundu...</pluralform>
+<pluralform>Automaticky opakovať za %x sekundy...</pluralform>
+<pluralform>Autoamticky opakovať za %x sekúnd...</pluralform>
+</target>
+
+<source>&Ignore subsequent errors</source>
+<target>Pre&skoÄiÅ¥ ÄalÅ¡ie chyby</target>
+
+<source>Retrying operation...</source>
+<target>Opakovanie operácie...</target>
+
+<source>Serious Error</source>
+<target>Závažná chyba</target>
+
+<source>Symlink</source>
+<target>Symlink</target>
+
+<source>Folder</source>
+<target>PrieÄinok</target>
+
+<source>Full path</source>
+<target>Plná cesta</target>
+
+<source>Name</source>
+<target>Názov</target>
+
+<source>Relative folder</source>
+<target>Relatívny prieÄinok</target>
+
+<source>Base folder</source>
+<target>Zlákladný prieÄinok</target>
+
+<source>Size</source>
+<target>Veľkosť</target>
+
+<source>Date</source>
+<target>Dátum</target>
+
+<source>Extension</source>
+<target>Prípona</target>
+
+<source>Category</source>
+<target>Kategórie</target>
+
+<source>Action</source>
+<target>Akcia</target>
+
+<source>Local comparison settings</source>
+<target>Lokálne nastavenie porovnánia</target>
+
+<source>Local synchronization settings</source>
+<target>Lokálne nastavenie synchronizácie</target>
+
+<source>Local filter</source>
+<target>Lokálny filter</target>
+
+<source>Active</source>
+<target>Zapnutý</target>
+
+<source>None</source>
+<target>Žiadna</target>
+
+<source>Remove local settings</source>
+<target>Zrušiť lokálne nastavenie</target>
+
+<source>Clear local filter</source>
+<target>Vymazať lokálne nastavenie filtra</target>
+
+<source>Copy</source>
+<target>Kopírovať</target>
+
+<source>Paste</source>
+<target>Vložiť</target>
+
+<source>The selected folder %x cannot be used with FreeFileSync.</source>
+<target>Vybraný prieÄinok %x nie je možné použíť s FreeFileSync.</target>
+
+<source>Please select a folder on a local file system, network or an MTP device.</source>
+<target>Prosím vyberte prieÄinok v lokálnom súborovom systéme, sieti alebo multimediálnom zariadení.</target>
+
+<source>SFTP folder</source>
+<target>SFTP prieÄinok</target>
+
+<source>Select SFTP folder</source>
+<target>Vyberte SFTP prieÄinok</target>
+
+<source>Select alternative folder type</source>
+<target>Vyberte alternatívny typ prieÄinka</target>
+
+<source>&New</source>
+<target>&Nový</target>
+
+<source>&Save</source>
+<target>&Uložiť</target>
+
+<source>Save as &batch job...</source>
+<target>Uložiť ako &dávku...</target>
+
+<source>Start &comparison</source>
+<target>Spustiť &porovnanie</target>
+
+<source>C&omparison settings</source>
+<target>Nastavenia p&orovnania</target>
+
+<source>&Filter settings</source>
+<target>Nastavenia &filtra</target>
+
+<source>S&ynchronization settings</source>
+<target>Nastavenia s&ynchronizácie</target>
+
+<source>Start &synchronization</source>
+<target>Spustiť &synchronizáciu</target>
+
+<source>&Actions</source>
+<target>&Akcie</target>
+
+<source>&Preferences</source>
+<target>&Predvoľby...</target>
+
+<source>&Language</source>
+<target>&Jazyk</target>
+
+<source>&Find...</source>
+<target>&Hľadať...</target>
+
+<source>&Reset layout</source>
+<target>&Obnoviť rozloženie</target>
+
+<source>&Export file list...</source>
+<target>&Exportovať zoznam súborov...</target>
+
+<source>&Tools</source>
+<target>&Nastavenie</target>
+
+<source>&Check for new version</source>
+<target>&Skontrolovať aktualizácie</target>
+
+<source>&Check now</source>
+<target>Skontrolovať &teraz</target>
+
+<source>Check &automatically once a week</source>
+<target>Kontrolovať &automaticky raz týždenne</target>
+
+<source>Cancel</source>
+<target>Zrušiť</target>
+
+<source>Compare</source>
+<target>Porovnanie</target>
+
+<source>Synchronize</source>
+<target>Synchronizácia</target>
+
+<source>Add folder pair</source>
+<target>PridaÅ¥ prieÄinok pre porovnanie</target>
+
+<source>Remove folder pair</source>
+<target>OdstrániÅ¥ dvojicu prieÄinkov</target>
+
+<source>Swap sides</source>
+<target>Zámena strán</target>
+
+<source>Close search bar</source>
+<target>Zavrieť hľadanie</target>
+
+<source>Find:</source>
+<target>Hľadať:</target>
+
+<source>Match case</source>
+<target>Rozlišovať malé a veľké písmená</target>
+
+<source>New</source>
+<target>Nový</target>
+
+<source>Open...</source>
+<target>Otvoriť...</target>
+
+<source>Save</source>
+<target>Uložiť</target>
+
+<source>Save as...</source>
+<target>Uložiť ako...</target>
+
+<source>View type:</source>
+<target>Typ zobrazenia:</target>
+
+<source>Select view:</source>
+<target>Výber zobrazenia:</target>
+
+<source>Statistics:</source>
+<target>Å tatistika:</target>
+
+<source>Number of files and folders that will be deleted</source>
+<target>PoÄet súborov a prieÄinkov k zmazaniu</target>
+
+<source>Number of files that will be updated</source>
+<target>PoÄet súborov k aktualizácií</target>
+
+<source>Number of files and folders that will be created</source>
+<target>PoÄet súborov a prieÄinkov k vytvoreniu</target>
+
+<source>Total bytes to copy</source>
+<target>Celkový objem kopírovaných údajov</target>
+
+<source>Folder pair:</source>
+<target>Dvojica prieÄinkov:</target>
+
+<source>Use local settings:</source>
+<target>Použiť lokálne nastavenie:</target>
+
+<source>Select a variant:</source>
+<target>Výber varianty:</target>
+
+<source>Include &symbolic links:</source>
+<target>Aj &symbolické odkazy:</target>
+
+<source>&Follow</source>
+<target>&Nasledovať</target>
+
+<source>&Direct</source>
+<target>&Direktne</target>
+
+<source>More information</source>
+<target>Viac informácií</target>
+
+<source>&Ignore time shift [hh:mm]</source>
+<target>&IgnorovaÅ¥ Äasový posun [hh:mm]</target>
+
+<source>List of file time offsets to ignore</source>
+<target>Zoznam ignorovaných Äasových posunov súborov</target>
+
+<source>Example:</source>
+<target>Príklad:</target>
+
+<source>Handle daylight saving time</source>
+<target>PoužívaÅ¥ letný Äas</target>
+
+<source>Local settings:</source>
+<target>lOKáLNE Nastavenia:</target>
+
+<source>Include:</source>
+<target>Zahrnúť:</target>
+
+<source>Exclude:</source>
+<target>Vynechať:</target>
+
+<source>Show examples</source>
+<target>Ukázať príklady</target>
+
+<source>Time span:</source>
+<target>Časová doba:</target>
+
+<source>File size:</source>
+<target>Veľkosť súboru:</target>
+
+<source>Minimum:</source>
+<target>Od:</target>
+
+<source>Maximum:</source>
+<target>Do:</target>
+
+<source>Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair.</source>
+<target>Nastavte pravidlá filtra pre vynechanie niekterých súborov zo synchronizácie. Zadávajte cesty súborov relativne k odpovedajúcej dvojici prieÄinkov.</target>
+
+<source>C&lear</source>
+<target>Vy&mazať</target>
+
+<source>Detect moved files</source>
+<target>Detekcia presunutých súborov</target>
+
+<source>
+- Not supported by all file systems
+- Requires and creates database files
+- Detection not available for first sync
+</source>
+<target>
+- Nie je podporované vštkými souborovými systémami
+- Vyžaduje vytvorenie databázového súboru
+- Detekcia rozdielov je dostupná až po prvej synchronizácií
+</target>
+
+<source>Detect synchronization directions with the help of database files</source>
+<target>UrÄiÅ¥ smer synchronizácie pomocou databázy</target>
+
+<source>Delete files:</source>
+<target>Zmazanie súborov:</target>
+
+<source>&Permanent</source>
+<target>&Trvale</target>
+
+<source>Delete or overwrite files permanently</source>
+<target>Zmazať alebo prepísať súbory natrvalo</target>
+
+<source>&Recycle bin</source>
+<target>&Kôš</target>
+
+<source>Back up deleted and overwritten files in the recycle bin</source>
+<target>Použiť Kôš pri zmazaní alebo prepisu súborov</target>
+
+<source>&Versioning</source>
+<target>&Archívovanie</target>
+
+<source>Move files to a user-defined folder</source>
+<target>Presunúť súbory do uživateľom zadaného prieÄinka</target>
+
+<source>Naming convention:</source>
+<target>Pomenovanie:</target>
+
+<source>Handle errors:</source>
+<target>Spracovanie chýb:</target>
+
+<source>Hide all error and warning messages</source>
+<target>Skryť všetky chyby a varovania</target>
+
+<source>&Pop-up</source>
+<target>&Hlásenie</target>
+
+<source>Show pop-up on errors or warnings</source>
+<target>Zobraziť hlásenie pri chybe alebo varovaní</target>
+
+<source>On completion:</source>
+<target>Po dokonÄení:</target>
+
+<source>OK</source>
+<target>OK</target>
+
+<source>Arrange folder pair</source>
+<target>UsporiadaÅ¥ dvojicu prieÄinkov</target>
+
+<source>Enter your SFTP login details:</source>
+<target>Zadajte prihlasovacie údaje k SFTP:</target>
+
+<source>Server name or IP address:</source>
+<target>Meno servera alebo jeho IP adresa:</target>
+
+<source>Port:</source>
+<target>Port:</target>
+
+<source>User name:</source>
+<target>Uživateľské meno:</target>
+
+<source>Password:</source>
+<target>Heslo:</target>
+
+<source>&Show password</source>
+<target>&Zobraziť heslo</target>
+
+<source>Directory on server:</source>
+<target>Adresár na servery:</target>
+
+<source>Select a directory on the server:</source>
+<target>Výber adresára na servery:</target>
+
+<source>Select Folder</source>
+<target>Výber prieÄinka</target>
+
+<source>Start synchronization now?</source>
+<target>Spustiť synchronizáciu teraz?</target>
+
+<source>Variant:</source>
+<target>Varianta:</target>
+
+<source>&Don't show this dialog again</source>
+<target>Tento dialog už &nezobrazovať</target>
+
+<source>Items found:</source>
+<target>Nájdených položiek:</target>
+
+<source>Time remaining:</source>
+<target>Ostávajúci Äas:</target>
+
+<source>Time elapsed:</source>
+<target>Uplynulý Äas:</target>
+
+<source>Synchronizing...</source>
+<target>Synchronizujem...</target>
+
+<source>Minimize to notification area</source>
+<target>Minimalizovať do oznamovacej oblasti</target>
+
+<source>Bytes copied:</source>
+<target>Skopírovaných údajov:</target>
+
+<source>Close</source>
+<target>Zavrieť</target>
+
+<source>&Pause</source>
+<target>&Pauza</target>
+
+<source>Stop</source>
+<target>Zastaviť</target>
+
+<source>Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x</source>
+<target>Vytvorí dávkový súbor pre automatickú synchronizáciu. Ku spusteniu dávky jednoducho pokliknite na vytvorený súbor alebo využite plánovaÄ Ãºloh vaÅ¡eho systému: %x</target>
+
+<source>&Stop</source>
+<target>&Zastaviť</target>
+
+<source>Stop synchronization at first error</source>
+<target>UkonÄiÅ¥ synchronizáciu pri prvej chybe</target>
+
+<source>Run minimized</source>
+<target>Spustiť minimalizované</target>
+
+<source>Save log:</source>
+<target>Uložiť log:</target>
+
+<source>Limit:</source>
+<target>Obmedzenie:</target>
+
+<source>Limit maximum number of log files</source>
+<target>Obmedzenie maximálneho poÄtu log súborov</target>
+
+<source>How can I schedule a batch job?</source>
+<target>Ako nastaviÅ¥ spustenie dávky v PlánovaÄi?</target>
+
+<source>&Keep relative paths</source>
+<target>&Zachovať relatívnu cesty</target>
+
+<source>&Overwrite existing files</source>
+<target>&Prepísať existujúce súbory</target>
+
+<source>The following settings are used for all synchronization jobs.</source>
+<target>Toto nastavenie je platné pre vÅ¡etky synchronizaÄné úlohy.</target>
+
+<source>Fail-safe file copy</source>
+<target>BezpeÄné kopírovanie súborov</target>
+
+<source>
+Copy to a temporary file (*.ffs_tmp) before overwriting target.
+This guarantees a consistent state even in case of a serious error.
+</source>
+<target>KopírovaÅ¥ najprv do doÄasného súboru (*.ffs_tmp), pred prepisom cieľa. Tento postup zaisÅ¥uje bezpeÄný chod aj v prípade závažnej chyby.</target>
+
+<source>(recommended)</source>
+<target>(doporuÄené)</target>
+
+<source>Copy locked files</source>
+<target>Kopírovať zamknuté súbory</target>
+
+<source>Copy shared or locked files using the Volume Shadow Copy Service.</source>
+<target>Kopírovať zdielané alebo zamknuté súbory pomocou služby Tieňové kópie zväzkov.</target>
+
+<source>(requires administrator rights)</source>
+<target>(vyžaduje práva správcu)</target>
+
+<source>Copy file access permissions</source>
+<target>Kopírovať prístupové oprávnenie súborov</target>
+
+<source>Transfer file and folder permissions.</source>
+<target>PreniesÅ¥ prístupové oprávnenie súborov a prieÄinkov.</target>
+
+<source>Automatic retry on error:</source>
+<target>Automaticky opakovať pri chybe:</target>
+
+<source>Retry count:</source>
+<target>PoÄet opakovaní:</target>
+
+<source>Delay (in seconds):</source>
+<target>Oneskorenie (v sekundách):</target>
+
+<source>Customize context menu:</source>
+<target>Prispôsobiť kontextovú ponuku:</target>
+
+<source>Description</source>
+<target>Popis</target>
+
+<source>Show hidden dialogs again</source>
+<target>Znovu zobraziť skryté dialógy</target>
+
+<source>Show all permanently hidden dialogs and warning messages again</source>
+<target>Zobraziť znovu všetky trvale skryté dialógy a varovné hlásenia</target>
+
+<source>&Default</source>
+<target>&Predvolené</target>
+
+<source>Source code written in C++ using:</source>
+<target>Zdrojový kód bol napísaný kompletne v C++ pomocou:</target>
+
+<source>If you like FreeFileSync:</source>
+<target>Pokiaľ sa Vám FreeFileSync páÄi:</target>
+
+<source>Donate with PayPal</source>
+<target>Prispieť pomocou PayPal</target>
+
+<source>Feedback and suggestions are welcome</source>
+<target>Komentáre a námety sú vždy vítané</target>
+
+<source>Homepage</source>
+<target>Domovská stránka</target>
+
+<source>Email</source>
+<target>Email</target>
+
+<source>Published under the GNU General Public License</source>
+<target>Vydané pod GNU General Public License (GPL)</target>
+
+<source>Many thanks for localization:</source>
+<target>PoÄakovanie za preklad FreeFileSync:</target>
+
+<source>SSH File Transfer Protocol</source>
+<target>SSH protokol</target>
+
+<source>Save as Batch Job</source>
+<target>Uložiť ako dávku</target>
+
+<source>Delete Items</source>
+<target>Zmazať položky</target>
+
+<source>Copy items</source>
+<target>Kopírovať položky</target>
+
+<source>Options</source>
+<target>Nastavenie programu</target>
+
+<source>Select Time Span</source>
+<target>ZadaÅ¥ Äasové rozmedzie</target>
+
+<source>&Options</source>
+<target>Nastavenie &programu</target>
+
+<source>Main Bar</source>
+<target>Hlavná lišta</target>
+
+<source>Folder Pairs</source>
+<target>PrieÄinkové dvojice</target>
+
+<source>Find</source>
+<target>Hľadať</target>
+
+<source>View Settings</source>
+<target>Nastavenie zobrazenia</target>
+
+<source>Configuration</source>
+<target>Konfigurácia</target>
+
+<source>Overview</source>
+<target>Prehľad</target>
+
+<source>&Download</source>
+<target>&SÅ¥ahovannie</target>
+
+<source>A new version of FreeFileSync is available:</source>
+<target>Je dostupná nová verzia FreeFileSync:</target>
+
+<source>Confirm</source>
+<target>Potvrdiť</target>
+
+<source>
+<pluralform>Do you really want to execute the command %y for one item?</pluralform>
+<pluralform>Do you really want to execute the command %y for %x items?</pluralform>
+</source>
+<target>
+<pluralform>Naozaj chcete vykonať príkaz %y pre 1 položku?</pluralform>
+<pluralform>Naozaj chcete vykonať príkaz %y pre %x položky?</pluralform>
+<pluralform>Naozaj chcete vykonať príkaz %y pro %x položiek?</pluralform>
+</target>
+
+<source>&Execute</source>
+<target>&Spustiť</target>
+
+<source>
+<pluralform>1 directory</pluralform>
+<pluralform>%x directories</pluralform>
+</source>
+<target>
+<pluralform>1 adresár</pluralform>
+<pluralform>%x adresáre</pluralform>
+<pluralform>%x adresárov</pluralform>
+</target>
+
+<source>
+<pluralform>1 file</pluralform>
+<pluralform>%x files</pluralform>
+</source>
+<target>
+<pluralform>1 súbor</pluralform>
+<pluralform>%x súbory</pluralform>
+<pluralform>%x súborov</pluralform>
+</target>
+
+<source>
+<pluralform>Showing %y of 1 row</pluralform>
+<pluralform>Showing %y of %x rows</pluralform>
+</source>
+<target>
+<pluralform>Zobrazenie %y z 1 riadku</pluralform>
+<pluralform>Zobrazenie %y z %x riadky</pluralform>
+<pluralform>Zobrazenie %y z %x riadkov</pluralform>
+</target>
+
+<source>Set direction:</source>
+<target>Zadať smer:</target>
+
+<source>multiple selection</source>
+<target>viacnásobný výber</target>
+
+<source>Include via filter:</source>
+<target>Zahrnúť pomocou filtra:</target>
+
+<source>Exclude via filter:</source>
+<target>Vynechať pomocou filtra:</target>
+
+<source>Include temporarily</source>
+<target>PridaÅ¥ doÄasne</target>
+
+<source>Exclude temporarily</source>
+<target>VynechaÅ¥ doÄasne</target>
+
+<source>&Copy to...</source>
+<target>&Kopírovať do...</target>
+
+<source>&Delete</source>
+<target>&Zmazať</target>
+
+<source>Include all</source>
+<target>Zahrnúť všetko</target>
+
+<source>Exclude all</source>
+<target>Vynechať všetko</target>
+
+<source>Show icons:</source>
+<target>Zobraziť ikony:</target>
+
+<source>Small</source>
+<target>Malé</target>
+
+<source>Medium</source>
+<target>Stredné</target>
+
+<source>Large</source>
+<target>Veľké</target>
+
+<source>Select time span...</source>
+<target>Zadajte Äasové rozmedzie...</target>
+
+<source>Show "%x"</source>
+<target>Zobraziť "%x"</target>
+
+<source>Last session</source>
+<target>Posledné sedenie</target>
+
+<source>Folder Comparison and Synchronization</source>
+<target>Porovnanie a synchronizácia prieÄinkov</target>
+
+<source>Configuration saved</source>
+<target>Konfigurácia uložená</target>
+
+<source>FreeFileSync batch</source>
+<target>FreeFileSync dávka</target>
+
+<source>Do you want to save changes to %x?</source>
+<target>Uložiť zmeny do %x?</target>
+
+<source>Never save &changes</source>
+<target>Nikdy &neukladať zmeny</target>
+
+<source>Do&n't save</source>
+<target>&Neukladať</target>
+
+<source>Remove entry from list</source>
+<target>Odstrániť položku zo zoznamu</target>
+
+<source>Clear filter</source>
+<target>Vymazať filter</target>
+
+<source>Show files that exist on left side only</source>
+<target>Zobraziť súbory existujúce iba vľavo</target>
+
+<source>Show files that exist on right side only</source>
+<target>Zobraziť súbory existujúce iba vpravo</target>
+
+<source>Show files that are newer on left</source>
+<target>Zobraziť novšie súbory vľavo</target>
+
+<source>Show files that are newer on right</source>
+<target>Zobraziť novšie súbory vpravo</target>
+
+<source>Show files that are equal</source>
+<target>Zobraziť rovnaké súbory</target>
+
+<source>Show files that are different</source>
+<target>Zobraziť rozdielne súbory</target>
+
+<source>Show conflicts</source>
+<target>Zobraziť konflikty</target>
+
+<source>Show files that will be created on the left side</source>
+<target>Zobraziť súbory, ktoré budú vľavo vytvorené</target>
+
+<source>Show files that will be created on the right side</source>
+<target>Zobraziť súbory, ktoré budú vpravo vytvorené</target>
+
+<source>Show files that will be deleted on the left side</source>
+<target>Zobraziť súbory, ktoré budú vľavo zmazané</target>
+
+<source>Show files that will be deleted on the right side</source>
+<target>Zobraziť súbory, ktoré budú vpravo zmazané</target>
+
+<source>Show files that will be updated on the left side</source>
+<target>Zobraziť súbory, ktoré budú vľavo aktualizované</target>
+
+<source>Show files that will be updated on the right side</source>
+<target>Zobraziť súbory, ktoré budú vpravo aktualizované</target>
+
+<source>Show files that won't be copied</source>
+<target>Zobraziť súbory, ktoré nebudú kopírované</target>
+
+<source>Show filtered or temporarily excluded files</source>
+<target>ZobraziÅ¥ filtrované alebo doÄasne vynechané súbory</target>
+
+<source>Save as default</source>
+<target>Uložiť ako predvolené</target>
+
+<source>Filter</source>
+<target>Filter</target>
+
+<source>All files are in sync</source>
+<target>Všetky súbory sú synchronizované</target>
+
+<source>Cannot find %x</source>
+<target>Nie je možné nájsť %x</target>
+
+<source>Move up</source>
+<target>Dohora</target>
+
+<source>Move down</source>
+<target>Dodola</target>
+
+<source>Comma-separated values</source>
+<target>Hodnoty oddelené Äiarkami</target>
+
+<source>File list exported</source>
+<target>Zoznam súborov bol exportovaný</target>
+
+<source>Searching for program updates...</source>
+<target>Hľadanie aktualizácií programu ...</target>
+
+<source>Close progress dialog</source>
+<target>Zavrieť dialóg priebehu</target>
+
+<source>Log off</source>
+<target>Odhlásiť uživateľa</target>
+
+<source>Standby</source>
+<target>Prepnúť do úsporného režímu</target>
+
+<source>Shut down</source>
+<target>Vypnúť poÄítaÄ</target>
+
+<source>Paused</source>
+<target>Pauza</target>
+
+<source>Initializing...</source>
+<target>Inicializácia...</target>
+
+<source>Scanning...</source>
+<target>Vyhľadávanie...</target>
+
+<source>Comparing content...</source>
+<target>Porovnávanie obsahu...</target>
+
+<source>Completed</source>
+<target>Hotovo</target>
+
+<source>Info</source>
+<target>Info</target>
+
+<source>Select all</source>
+<target>Vybrať všetko</target>
+
+<source>&Continue</source>
+<target>&PokraÄovaÅ¥</target>
+
+<source>Progress</source>
+<target>Priebeh</target>
+
+<source>Log</source>
+<target>Záznam spracovania</target>
+
+<source>Loading...</source>
+<target>NaÄítanie...</target>
+
+<source>
+<pluralform>Copy the following item to another folder?</pluralform>
+<pluralform>Copy the following %x items to another folder?</pluralform>
+</source>
+<target>
+<pluralform>KopírovaÅ¥ následujúcu položku do iného prieÄinka?</pluralform>
+<pluralform>KopírovaÅ¥ následujúce %x položky do iného prieÄinka?</pluralform>
+<pluralform>KopírovaÅ¥ následujúcich %x položiek do iného prieÄinka?</pluralform>
+</target>
+
+<source>Please enter a target folder.</source>
+<target>Prosím zadajte cieľový prieÄinok.</target>
+
+<source>
+<pluralform>Do you really want to move the following item to the recycle bin?</pluralform>
+<pluralform>Do you really want to move the following %x items to the recycle bin?</pluralform>
+</source>
+<target>
+<pluralform>Naozaj chcete presunúť následujúcu položku do Koša?</pluralform>
+<pluralform>Naozaj chcete presunúť následujúce %x položky do Koša?</pluralform>
+<pluralform>Naozaj chcete presunúť následujúcich %x položiek do Koša?</pluralform>
+</target>
+
+<source>Move</source>
+<target>Presunúť</target>
+
+<source>
+<pluralform>Do you really want to delete the following item?</pluralform>
+<pluralform>Do you really want to delete the following %x items?</pluralform>
+</source>
+<target>
+<pluralform>Naozaj chcete zmazať následujúcu položku?</pluralform>
+<pluralform>Naozaj chcete zmazať následujúce %x položky?</pluralform>
+<pluralform>Naozaj chcete zmazať následujúcich %x položiek?</pluralform>
+</target>
+
+<source>Copy DACL, SACL, Owner, Group</source>
+<target>Kopírovať DACL, SACL, Owner, Group</target>
+
+<source>Integrate external applications into context menu. The following macros are available:</source>
+<target>Integrácia externej aplikácie do kontextovéj ponuky. K dispozici jsou následující makrá:</target>
+
+<source>- full file or folder name</source>
+<target>- celá cesta alebo názov prieÄinka</target>
+
+<source>- folder part only</source>
+<target>- iba cesta prieÄinka</target>
+
+<source>- Other side's counterpart to %item_path%</source>
+<target>- celá cesta alebo názov z opaÄného panelu pre %item_path%</target>
+
+<source>- Other side's counterpart to %item_folder%</source>
+<target>- iba cesta z opaÄného panelu pre %item_folder%</target>
+
+<source>Show hidden dialogs and warning messages again?</source>
+<target>Zobraziť skryté dialógy a varovné hlásenia?</target>
+
+<source>&Show</source>
+<target>&Zobraziť</target>
+
+<source>Identify equal files by comparing modification time and size.</source>
+<target>RozpoznaÅ¥ rovnaké súbory porovnaním ich Äasu úpravy a veľkosti.</target>
+
+<source>Identify equal files by comparing the file content.</source>
+<target>Rozpoznať rovnaké súbory porovnaním ich obsahu.</target>
+
+<source>Identify equal files by comparing their file size.</source>
+<target>Rozpoznať rovnaké súbory porovnaním ich veľkosti.</target>
+
+<source>Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database.</source>
+<target>Rozpoznať a vykonať zmeny na oboch stranách. Odstránené, presunuté alebo premenované súbory a konflikty budú detekované automaticky pomocou databázy.</target>
+
+<source>Create a mirror backup of the left folder by adapting the right folder to match.</source>
+<target>VytvoriÅ¥ zrkadlovú kópiu ľavého prieÄinka tak, aby po synchronizácií pravého prieÄinka presne odpovedal ľavému.</target>
+
+<source>Copy new and updated files to the right folder.</source>
+<target>KopírovaÅ¥ nové a aktualizované súbory do pravého prieÄinka.</target>
+
+<source>Configure your own synchronization rules.</source>
+<target>Nastavenie vlastných pravidiel synchronizácie.</target>
+
+<source>Synchronization Settings</source>
+<target>Nastavenia synchronizácie</target>
+
+<source>Comparison</source>
+<target>Porovnanie</target>
+
+<source>Synchronization</source>
+<target>Synchronizácia</target>
+
+<source>Today</source>
+<target>Dnes</target>
+
+<source>This week</source>
+<target>Tento týždeň</target>
+
+<source>This month</source>
+<target>Tento mesiac</target>
+
+<source>This year</source>
+<target>Tento rok</target>
+
+<source>Last x days</source>
+<target>Posledných x dní</target>
+
+<source>Byte</source>
+<target>Byte</target>
+
+<source>KB</source>
+<target>KB</target>
+
+<source>MB</source>
+<target>MB</target>
+
+<source>Replace</source>
+<target>Nahradiť</target>
+
+<source>Move files and replace if existing</source>
+<target>Presunúť a nahradiť súbory pokiaľ už existujú</target>
+
+<source>Time stamp</source>
+<target>ÄŒasová znaÄka</target>
+
+<source>Append a time stamp to each file name</source>
+<target>PridaÅ¥ Äasovú znaÄku ku každému názvu súboru</target>
+
+<source>Main config</source>
+<target>Hlavná konfigurácia</target>
+
+<source>empty</source>
+<target>prázdne</target>
+
+<source>Leave as unresolved conflict</source>
+<target>Ponechať ako nevyriešený konflikt</target>
+
+<source>File</source>
+<target>Súbor</target>
+
+<source>YYYY-MM-DD hhmmss</source>
+<target>RRRR-MM-DD hhmmss</target>
+
+<source>Files</source>
+<target>Súbory</target>
+
+<source>Items</source>
+<target>Položky</target>
+
+<source>Percentage</source>
+<target>Percentný podiel</target>
+
+<source>Internet access failed.</source>
+<target>Nie je prístup k internetu.</target>
+
+<source>Check for Program Updates</source>
+<target>Hľadanie aktualizácií programu</target>
+
+<source>Download now?</source>
+<target>Stiahúť teraz?</target>
+
+<source>FreeFileSync is up to date.</source>
+<target>FreeFileSync je aktuálny.</target>
+
+<source>Unable to connect to www.freefilesync.org.</source>
+<target>Nie je možné sa pripojiť k www.freefilesync.org.</target>
+
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
+
+<source>&Check</source>
+<target>&Kontrola</target>
+
+<source>Unable to register to receive system messages.</source>
+<target>Nepodarilo sa registrovať k odberu systémových správ.</target>
+
+<source>Unable to register device notifications for %x.</source>
+<target>Nepodarilo sa registrovať správy zaiadenia %x.</target>
+
+<source>Cannot monitor directory %x.</source>
+<target>Nie je možné nastaviť monitorovanie adresára %x.</target>
+
+<source>The file is locked by another process:</source>
+<target>Súbor je uzamknutý iným procesom:</target>
+
+<source>Cannot write file attributes of %x.</source>
+<target>Nie je možné zapísať atribúty súboru %x.</target>
+
+<source>Cannot read security context of %x.</source>
+<target>Nie je možné naÄítaÅ¥ prístupové práva pre %x.</target>
+
+<source>Cannot write security context of %x.</source>
+<target>Nie je možné zapísať prístupové práva pre %x.</target>
+
+<source>Cannot read permissions of %x.</source>
+<target>Nie je možné naÄítaÅ¥ oprávnenie pre %x.</target>
+
+<source>Cannot copy permissions from %x to %y.</source>
+<target>Nie je možné kopírovať oprávnenie z %x do %y.</target>
+
+<source>%x is not a regular directory name.</source>
+<target>%x nie je platným názvom adresára.</target>
+
+<source>Cannot find system function %x.</source>
+<target>Nie je možné nájsť systémovú funkciu %x.</target>
+
+<source>Cannot copy file %x to %y.</source>
+<target>Nie je možné kopírovať súbor %x do %y.</target>
+
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Nie je možné kopírovať atribúty z %x do %y.</target>
+
+<source>Type of item %x is not supported:</source>
+<target>Typ položky %x nie je podporovaný:</target>
+
+<source>%x TB</source>
+<target>%x TB</target>
+
+<source>%x PB</source>
+<target>%x PB</target>
+
+<source>
+<pluralform>1 min</pluralform>
+<pluralform>%x min</pluralform>
+</source>
+<target>
+<pluralform>1 minúta</pluralform>
+<pluralform>%x minúty</pluralform>
+<pluralform>%x minút</pluralform>
+</target>
+
+<source>
+<pluralform>1 hour</pluralform>
+<pluralform>%x hours</pluralform>
+</source>
+<target>
+<pluralform>1 hodina</pluralform>
+<pluralform>%x hodiny</pluralform>
+<pluralform>%x hodín</pluralform>
+</target>
+
+<source>
+<pluralform>1 day</pluralform>
+<pluralform>%x days</pluralform>
+</source>
+<target>
+<pluralform>1 deň</pluralform>
+<pluralform>%x dni</pluralform>
+<pluralform>%x dní</pluralform>
+</target>
+
+<source>Cannot set privilege %x.</source>
+<target>Nie je možné nastaviť práva pre %x.</target>
+
+<source>Unable to suspend system sleep mode.</source>
+<target>Nie je možné pozastaviť Režím spánku.</target>
+
+<source>Cannot change process I/O priorities.</source>
+<target>Nie je možné nastaviť I/O priority procesu.</target>
+
+<source>Checking recycle bin failed for folder %x.</source>
+<target>Zlyhala kontrola KoÅ¡a pre prieÄinok %x.</target>
+
+<source>The following XML elements could not be read:</source>
+<target>Nie je možné naÄítaÅ¥ následujúce XML elementy:</target>
+
+<source>Configuration file %x is incomplete. The missing elements will be set to their default values.</source>
+<target>KonfiguraÄný súbor %x je nekompletný. Chybajúce položky budú nahradené predvolenými hodnotami.</target>
+
+<source>Prepare installation</source>
+<target>Príprava inštalácie</target>
+
+<source>Choose which components you want to install.</source>
+<target>Vyberte komponenty k inštalácií.</target>
+
+<source>Select installation type:</source>
+<target>Vyberte typ inštalácie:</target>
+
+<source>Local</source>
+<target>Lokálne</target>
+
+<source>Portable</source>
+<target>Prenosná</target>
+
+<source>recommended</source>
+<target>doporuÄené</target>
+
+<source>Save settings to "%APPDATA%\FreeFileSync"</source>
+<target>Uložiť nastavenia do zložky "%APPDATA%\FreeFileSync"</target>
+
+<source>Register FreeFileSync file extensions</source>
+<target>Zaregistruje prípony súborov FreeFileSync</target>
+
+<source>Create Explorer context menu entries</source>
+<target>Vytvoriť položky v kontextovej pnuke Prieskumníka</target>
+
+<source>Save settings in installation directory</source>
+<target>Uložiť nastavenia do zložky inštalácie</target>
+
+<source>Do not write to Registry</source>
+<target>Nezapisovať do Registrov</target>
+
+<source>Just copy the files</source>
+<target>Skopíruje iba súbory</target>
+
+<source>Choose a directory for installation:</source>
+<target>Vyberte zložku pre inštaláciu:</target>
+
+<source>Create shortcuts:</source>
+<target>Vytvoriť zástupcu:</target>
+
+<source>Desktop</source>
+<target>Plocha</target>
+
+<source>Start menu</source>
+<target>Ponuka Å tart</target>
+
+<source>Registering FreeFileSync file extensions</source>
+<target>Zaregistrovať príponu súborov FreeFileSync</target>
+
+<source>Unregistering FreeFileSync file extensions</source>
+<target>Odregistrovať príponu súborov FreeFileSync</target>
+
+<source>FreeFileSync Configuration</source>
+<target>FreeFileSync konfigurácia</target>
+
+<source>FreeFileSync Batch File</source>
+<target>Dávk. súbor FreeFileSync</target>
+
+<source>FreeFileSync Synchronization Database</source>
+<target>SynchronizaÄná databáza FreeFileSync</target>
+
+<source>RealTimeSync Configuration</source>
+<target>konfigurácia RealTimeSync</target>
+
+<source>Edit with FreeFileSync</source>
+<target>Upraviť vo FreeFileSync</target>
+
+<source>Thanks for your donation and support!</source>
+<target>Ďakujem za Vaše príspevky a podporu!</target>
+
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
+
diff --git a/FreeFileSync/Build/Languages/slovenian.lng b/FreeFileSync/Build/Languages/slovenian.lng
index 7fcc09e3..9fda61ff 100644
--- a/FreeFileSync/Build/Languages/slovenian.lng
+++ b/FreeFileSync/Build/Languages/slovenian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Posodobi atribute na desni strani</target>
-<source>Cannot read file %x.</source>
-<target>Ne morem prebrati datoteke %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Ne morem zapisati dovoljenj od %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Operacija ni podprta za razliÄne osnovne tipe map.</target>
+
+<source>Cannot write file %x.</source>
+<target>Ne morem zapisati datoteke %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ PriÄakovano: %x bajtov
Dejansko: %y bajtov
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Ne morem zapisati dovoljenj od %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Operacija ni podprta za razliÄne osnovne tipe map.</target>
-
-<source>Cannot write file %x.</source>
-<target>Ne morem zapisati datoteke %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Ne morem kopirati simboliÄne povezave %x v %y.</target>
@@ -255,6 +252,9 @@ Dejansko: %y bajtov
<source>Cannot open file %x.</source>
<target>Ne morem odpreti datoteke %x.</target>
+<source>Cannot read file %x.</source>
+<target>Ne morem prebrati datoteke %x.</target>
+
<source>Cannot find device %x.</source>
<target>Ne najdem naprave %x.</target>
@@ -1637,8 +1637,8 @@ To zagotavlja konsistenÄnost podatkov v primeru napake.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Povezava na www.freefilesync.org ni mogoÄa.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Na omrežju ne najdem obstojeÄe verzije FreeFileSync-a. Ali želite preveriti lastnoroÄno?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Preveri</target>
@@ -1676,12 +1676,12 @@ To zagotavlja konsistenÄnost podatkov v primeru napake.
<source>Cannot find system function %x.</source>
<target>Ne morem najti sistemske funkcije %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Ne morem kopirati atributov iz %x v %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Ne morem kopirati datoteke %x v %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Ne morem kopirati atributov iz %x v %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Element tipa %x ni podprt:</target>
@@ -1814,6 +1814,9 @@ To zagotavlja konsistenÄnost podatkov v primeru napake.
<source>Thanks for your donation and support!</source>
<target>Hvala za vašo donacijo in podporo!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>FreeFileSync namestitev za donatorje je dosegla zgornjo mejo instalacij. Naj priÄnem prenos redne verzije z domaÄe strani FreeFileSync sedaj?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/spanish.lng b/FreeFileSync/Build/Languages/spanish.lng
index 9a2df76e..fccdf5ad 100644
--- a/FreeFileSync/Build/Languages/spanish.lng
+++ b/FreeFileSync/Build/Languages/spanish.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Actualizar atributos en la derecha</target>
-<source>Cannot read file %x.</source>
-<target>No se puede leer el archivo %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>No se pueden escribir los permisos de %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>No se admite esta operación para tipos de carpetas base diferentes.</target>
+
+<source>Cannot write file %x.</source>
+<target>No se puede escribir el archivo %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Esperados: %x bytes
Reales: %y bytes
</target>
-<source>Cannot write permissions of %x.</source>
-<target>No se pueden escribir los permisos de %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>No se admite esta operación para tipos de carpetas base diferentes.</target>
-
-<source>Cannot write file %x.</source>
-<target>No se puede escribir el archivo %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>No se puede copiar el vínculo simbólico %x a %y.</target>
@@ -255,6 +252,9 @@ Reales: %y bytes
<source>Cannot open file %x.</source>
<target>No se puede abrir el archivo %x.</target>
+<source>Cannot read file %x.</source>
+<target>No se puede leer el archivo %x.</target>
+
<source>Cannot find device %x.</source>
<target>No se encuentra el dispositivo %x.</target>
@@ -1615,8 +1615,8 @@ Se garantiza un estado coherente incluso en caso de error grave.
<source>Unable to connect to www.freefilesync.org.</source>
<target>No se puede conectar al sitio www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>No se encuentra el número de versión actual de FreeFileSync en línea. ¿Desea comprobarla manualmente?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Comprobar</target>
@@ -1654,12 +1654,12 @@ Se garantiza un estado coherente incluso en caso de error grave.
<source>Cannot find system function %x.</source>
<target>No se puede encontrar la función del sistema %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>No se puedem copiar los atributos desde %x hacia %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>No se puede copiar el archivo %x a %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>No se puedem copiar los atributos desde %x hacia %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>El tipo de objeto %x no esta soportado:</target>
@@ -1786,6 +1786,9 @@ Se garantiza un estado coherente incluso en caso de error grave.
<source>Thanks for your donation and support!</source>
<target>¡Muchas gracias por su contribución y ayuda!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Este instalador de FreeFileSync para contribuidores alcanzó su límite de instalaciones. ¿Desea descargar la versión normal desde la página de FreeFileSync ahora?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/swedish.lng b/FreeFileSync/Build/Languages/swedish.lng
index e36b3748..3a8e4f91 100644
--- a/FreeFileSync/Build/Languages/swedish.lng
+++ b/FreeFileSync/Build/Languages/swedish.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Uppdatera attribut på höger sida</target>
-<source>Cannot read file %x.</source>
-<target>Filen %x kan inte läsas in.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Kan inte skriva behörigheter för %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Åtgärden stöder inte olika basmapptyper.</target>
+
+<source>Cannot write file %x.</source>
+<target>Filen %x kan inte skrivas.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Förväntad: %x byte
Aktuell: %y byte
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Kan inte skriva behörigheter för %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Åtgärden stöder inte olika basmapptyper.</target>
-
-<source>Cannot write file %x.</source>
-<target>Filen %x kan inte skrivas.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Kan inte kopiera den symboliska länken %x till %y.</target>
@@ -255,6 +252,9 @@ Aktuell: %y byte
<source>Cannot open file %x.</source>
<target>Kan inte öppna %x.</target>
+<source>Cannot read file %x.</source>
+<target>Filen %x kan inte läsas in.</target>
+
<source>Cannot find device %x.</source>
<target>Kan inte hitta enheten %x.</target>
@@ -1615,8 +1615,8 @@ Detta garanterar ett konsekvent tillstånd även vid allvarliga fel.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Kan inte ansluta till www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Kan inte hitta aktuellt versionsnummer online. Vill du kontrollera manuellt?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Kontrollera</target>
@@ -1654,12 +1654,12 @@ Detta garanterar ett konsekvent tillstånd även vid allvarliga fel.
<source>Cannot find system function %x.</source>
<target>Kan inte hitta systemfunktion %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Kan inte kopiera attribut från %x till %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Kan inte kopiera %x till %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Kan inte kopiera attribut från %x till %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Objekttyp %x stöds ej:</target>
@@ -1786,6 +1786,9 @@ Detta garanterar ett konsekvent tillstånd även vid allvarliga fel.
<source>Thanks for your donation and support!</source>
<target>Tack för donationen och ditt stöd!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Denna FreeFileSync-installerare för donatorer, har nått sin installationsgräns. Vill du ladda ner den vanliga versionen från FreeFileSyncs hemsida nu?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/turkish.lng b/FreeFileSync/Build/Languages/turkish.lng
index 6a043751..0419a7f7 100644
--- a/FreeFileSync/Build/Languages/turkish.lng
+++ b/FreeFileSync/Build/Languages/turkish.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Sağdaki öznitelikler güncellensin</target>
-<source>Cannot read file %x.</source>
-<target>%x dosyası okunamadı.</target>
+<source>Cannot write permissions of %x.</source>
+<target>%x izinleri yazılamadı.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>Farklı temel klasör tipleri üzerindeki işlemler desteklenmiyor.</target>
+
+<source>Cannot write file %x.</source>
+<target>%x dosyası yazılamadı.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Beklenen: %x bayt
Gerçekleşen: %y bayt
</target>
-<source>Cannot write permissions of %x.</source>
-<target>%x izinleri yazılamadı.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>Farklı temel klasör tipleri üzerindeki işlemler desteklenmiyor.</target>
-
-<source>Cannot write file %x.</source>
-<target>%x dosyası yazılamadı.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>%x sembolik bağlantısı %y hedefine kopyalanamadı.</target>
@@ -255,6 +252,9 @@ Gerçekleşen: %y bayt
<source>Cannot open file %x.</source>
<target>%x dosyası açılamadı.</target>
+<source>Cannot read file %x.</source>
+<target>%x dosyası okunamadı.</target>
+
<source>Cannot find device %x.</source>
<target>%x aygıtı bulunamadı.</target>
@@ -1615,8 +1615,8 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya
<source>Unable to connect to www.freefilesync.org.</source>
<target>www.freefilesync.org sitesine bağlanılamadı.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Geçerli FreeFileSync sürüm numarası çevrimiçi olarak bulunamadı. El ile denetlemek ister misiniz?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Denetle</target>
@@ -1654,12 +1654,12 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya
<source>Cannot find system function %x.</source>
<target>%x sistem işlevi bulunamadı.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Öznitelikler %x üzerinden %y üzerine kopyalanamadı.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>%x dosyası %y olarak kopyalanamadı.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Öznitelikler %x üzerinden %y üzerine kopyalanamadı.</target>
+
<source>Type of item %x is not supported:</source>
<target>%x ögesi tipi desteklenmiyor:</target>
@@ -1786,6 +1786,9 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya
<source>Thanks for your donation and support!</source>
<target>Bağış ve destekleriniz için teşekkürler!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Bağışçılara özel bu FreeFileSync kopyası için yükleme sınırına ulaşıldı. FreeFileSync sayfasından normal sürümü indirmek ister misiniz?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Languages/ukrainian.lng b/FreeFileSync/Build/Languages/ukrainian.lng
index 286e3f7c..f821aa56 100644
--- a/FreeFileSync/Build/Languages/ukrainian.lng
+++ b/FreeFileSync/Build/Languages/ukrainian.lng
@@ -214,8 +214,14 @@
<source>Update attributes on right</source>
<target>Оновити атрибути праворуч</target>
-<source>Cannot read file %x.</source>
-<target>Ðе вдаєтьÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл %x.</target>
+<source>Cannot write permissions of %x.</source>
+<target>Ðе вдаєтьÑÑ Ð·Ð°Ð¿Ð¸Ñати права доÑтупу до %x.</target>
+
+<source>Operation not supported for different base folder types.</source>
+<target>ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ підтримуєтьÑÑ Ð´Ð»Ñ Ñ€Ñ–Ð·Ð½Ð¸Ñ… типів базових папок.</target>
+
+<source>Cannot write file %x.</source>
+<target>Ðе вдаєтьÑÑ Ð·Ð°Ð¿Ð¸Ñати файл %x.</target>
<source>
Unexpected size of data stream.
@@ -228,15 +234,6 @@ Actual: %y bytes
ДійÑний: %y байт
</target>
-<source>Cannot write permissions of %x.</source>
-<target>Ðе вдаєтьÑÑ Ð·Ð°Ð¿Ð¸Ñати права доÑтупу до %x.</target>
-
-<source>Operation not supported for different base folder types.</source>
-<target>ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ підтримуєтьÑÑ Ð´Ð»Ñ Ñ€Ñ–Ð·Ð½Ð¸Ñ… типів базових папок.</target>
-
-<source>Cannot write file %x.</source>
-<target>Ðе вдаєтьÑÑ Ð·Ð°Ð¿Ð¸Ñати файл %x.</target>
-
<source>Cannot copy symbolic link %x to %y.</source>
<target>Ðе вдаєтьÑÑ Ñкопіювати Ñимвольне поÑÐ¸Ð»Ð°Ð½Ð½Ñ %x до %y.</target>
@@ -255,6 +252,9 @@ Actual: %y bytes
<source>Cannot open file %x.</source>
<target>Ðе вдаєтьÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ файл %x.</target>
+<source>Cannot read file %x.</source>
+<target>Ðе вдаєтьÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл %x.</target>
+
<source>Cannot find device %x.</source>
<target>Ðе вдаєтьÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ приÑтрій %x.</target>
@@ -1626,8 +1626,8 @@ This guarantees a consistent state even in case of a serious error.
<source>Unable to connect to www.freefilesync.org.</source>
<target>Ðе вдалоÑÑŒ підключитиÑÑŒ до www.freefilesync.org.</target>
-<source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source>
-<target>Ðе вдаєтьÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ номер поточної верÑÑ–Ñ— FreeFileSync он-лайн. Бажаєте перевірити вручну?</target>
+<source>Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?</source>
+<target></target>
<source>&Check</source>
<target>&Перевірити</target>
@@ -1665,12 +1665,12 @@ This guarantees a consistent state even in case of a serious error.
<source>Cannot find system function %x.</source>
<target>Ðе вдаєтьÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ ÑиÑтемну функцію %x.</target>
-<source>Cannot copy attributes from %x to %y.</source>
-<target>Ðе вдаєтьÑÑ Ñкопіювати атрибути з %x до %y.</target>
-
<source>Cannot copy file %x to %y.</source>
<target>Ðе вдаєтьÑÑ Ñкопіювати файл %x до %y.</target>
+<source>Cannot copy attributes from %x to %y.</source>
+<target>Ðе вдаєтьÑÑ Ñкопіювати атрибути з %x до %y.</target>
+
<source>Type of item %x is not supported:</source>
<target>Тип елемента %x не підтримуєтьÑÑ:</target>
@@ -1800,6 +1800,9 @@ This guarantees a consistent state even in case of a serious error.
<source>Thanks for your donation and support!</source>
<target>СпаÑибі за Ð¿Ð¾Ð¶ÐµÑ€Ñ‚Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° підтримку!</target>
-<source>This FreeFileSync installer for donors has reached its installation limit. Download the regular version from the FreeFileSync homepage now?</source>
-<target>Цей FreeFileSync інÑталÑтор Ð´Ð»Ñ Ð´Ð¾Ð½Ð¾Ñ€Ñ–Ð² доÑÑг Ñвого ліміту вÑтановлень. Завантажити звичайну верÑÑ–ÑŽ з домашньої Ñторінки FreeFileSync зараз?</target>
+<source>This FreeFileSync installer for donors has reached its daily installation limit.</source>
+<target></target>
+
+<source>Download the regular version from the FreeFileSync homepage now?</source>
+<target></target>
diff --git a/FreeFileSync/Build/Resources.zip b/FreeFileSync/Build/Resources.zip
index c1f815e4..e45debd5 100644
--- a/FreeFileSync/Build/Resources.zip
+++ b/FreeFileSync/Build/Resources.zip
Binary files differ
diff --git a/FreeFileSync/Build/styles.gtk_rc b/FreeFileSync/Build/styles.gtk_rc
deleted file mode 100644
index c6b1b5ab..00000000
--- a/FreeFileSync/Build/styles.gtk_rc
+++ /dev/null
@@ -1,8 +0,0 @@
-style "no-inner-border"
-{
- GtkButton::focus-padding = 0
- GtkButton::focus-line-width = 0
- GtkButton::inner-border = {0, 0, 0, 0}
-}
-
-class "GtkButton" style "no-inner-border"
diff --git a/FreeFileSync/Source/RealtimeSync/main_dlg.cpp b/FreeFileSync/Source/RealtimeSync/main_dlg.cpp
index c49db1cf..0d9f7610 100644
--- a/FreeFileSync/Source/RealtimeSync/main_dlg.cpp
+++ b/FreeFileSync/Source/RealtimeSync/main_dlg.cpp
@@ -182,7 +182,7 @@ const Zstring& MainDialog::lastConfigFileName()
void MainDialog::OnShowHelp(wxCommandEvent& event)
{
- zen::displayHelpEntry(L"html/realtimesync.html", this);
+ zen::displayHelpEntry(L"realtimesync", this);
}
diff --git a/FreeFileSync/Source/algorithm.cpp b/FreeFileSync/Source/algorithm.cpp
index 79689ceb..4663165c 100644
--- a/FreeFileSync/Source/algorithm.cpp
+++ b/FreeFileSync/Source/algorithm.cpp
@@ -673,7 +673,7 @@ std::vector<DirectionConfig> zen::extractDirectionCfg(const MainConfiguration& m
void zen::redetermineSyncDirection(const DirectionConfig& dirCfg,
BaseFolderPair& baseFolder,
const std::function<void(const std::wstring& msg)>& reportWarning,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
//try to load sync-database files
std::shared_ptr<InSyncFolder> lastSyncState;
@@ -683,7 +683,7 @@ void zen::redetermineSyncDirection(const DirectionConfig& dirCfg,
if (allItemsCategoryEqual(baseFolder))
return; //nothing to do: abort and don't even try to open db files
- lastSyncState = loadLastSynchronousState(baseFolder, onUpdateStatus); //throw FileError, FileErrorDatabaseNotExisting
+ lastSyncState = loadLastSynchronousState(baseFolder, notifyProgress); //throw FileError, FileErrorDatabaseNotExisting
}
catch (FileErrorDatabaseNotExisting&) {} //let's ignore this error, there's no value in reporting it other than confuse users
catch (const FileError& e) //e.g. incompatible database version
@@ -714,7 +714,7 @@ void zen::redetermineSyncDirection(const DirectionConfig& dirCfg,
void zen::redetermineSyncDirection(const MainConfiguration& mainCfg,
FolderComparison& folderCmp,
const std::function<void(const std::wstring& msg)>& reportWarning,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
if (folderCmp.empty())
return;
@@ -722,12 +722,12 @@ void zen::redetermineSyncDirection(const MainConfiguration& mainCfg,
std::vector<DirectionConfig> directCfgs = extractDirectionCfg(mainCfg);
if (folderCmp.size() != directCfgs.size())
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
for (auto it = folderCmp.begin(); it != folderCmp.end(); ++it)
{
const DirectionConfig& cfg = directCfgs[it - folderCmp.begin()];
- redetermineSyncDirection(cfg, **it, reportWarning, onUpdateStatus);
+ redetermineSyncDirection(cfg, **it, reportWarning, notifyProgress);
}
}
@@ -1028,7 +1028,7 @@ void zen::applyFiltering(FolderComparison& folderCmp, const MainConfiguration& m
if (folderCmp.empty())
return;
else if (folderCmp.size() != mainCfg.additionalPairs.size() + 1)
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
//merge first and additional pairs
std::vector<FolderPairEnh> allPairs;
@@ -1460,7 +1460,7 @@ void zen::deleteFromGridAndHD(const std::vector<FileSystemObject*>& rowsToDelete
if (folderCmp.empty())
return;
else if (folderCmp.size() != directCfgs.size())
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
//build up mapping from base directory to corresponding direction config
std::unordered_map<const BaseFolderPair*, DirectionConfig> baseFolderCfgs;
diff --git a/FreeFileSync/Source/algorithm.h b/FreeFileSync/Source/algorithm.h
index f93811a5..cd8d8a7c 100644
--- a/FreeFileSync/Source/algorithm.h
+++ b/FreeFileSync/Source/algorithm.h
@@ -22,12 +22,12 @@ std::vector<DirectionConfig> extractDirectionCfg(const MainConfiguration& mainCf
void redetermineSyncDirection(const DirectionConfig& directConfig,
BaseFolderPair& baseFolder,
const std::function<void(const std::wstring& msg)>& reportWarning,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus);
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress);
void redetermineSyncDirection(const MainConfiguration& mainCfg,
FolderComparison& folderCmp,
const std::function<void(const std::wstring& msg)>& reportWarning,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus);
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress);
void setSyncDirectionRec(SyncDirection newDirection, FileSystemObject& fsObj); //set new direction (recursively)
diff --git a/FreeFileSync/Source/application.cpp b/FreeFileSync/Source/application.cpp
index fb0c0a12..71a59bfb 100644
--- a/FreeFileSync/Source/application.cpp
+++ b/FreeFileSync/Source/application.cpp
@@ -80,11 +80,12 @@ std::vector<Zstring> getCommandlineArgs(const wxApp& app)
{
std::vector<Zstring> args;
#ifdef ZEN_WIN
+ //"Parsing C++ Command-Line Arguments": https://msdn.microsoft.com/en-us/library/17w5ykft
//we do the job ourselves! both wxWidgets and ::CommandLineToArgvW() parse "C:\" "D:\" as single line C:\" D:\"
//-> "solution": we just don't support protected quotation mark!
Zstring cmdLine = ::GetCommandLine(); //only way to get a unicode commandline
while (endsWith(cmdLine, L' ')) //may end with space
- cmdLine.resize(cmdLine.size() - 1);
+ cmdLine.pop_back();
auto iterStart = cmdLine.end(); //end() means: no token
for (auto it = cmdLine.begin(); it != cmdLine.end(); ++it)
@@ -149,7 +150,7 @@ bool Application::OnInit()
#elif defined ZEN_LINUX
::gtk_init(nullptr, nullptr);
- ::gtk_rc_parse((getResourceDir() + "styles.gtk_rc").c_str()); //remove inner border from bitmap buttons
+ //::gtk_rc_parse((getResourceDir() + "styles.gtk_rc").c_str()); //remove inner border from bitmap buttons
#endif
//Windows User Experience Interaction Guidelines: tool tips should have 5s timeout, info tips no timeout => compromise:
@@ -656,7 +657,7 @@ void runBatchMode(const Zstring& globalConfigFile, const XmlBatchConfig& batchCf
//START SYNCHRONIZATION
const std::vector<FolderPairSyncCfg> syncProcessCfg = extractSyncCfg(batchCfg.mainCfg);
if (syncProcessCfg.size() != cmpResult.size())
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
synchronize(timeStamp,
globalCfg.optDialogs,
diff --git a/FreeFileSync/Source/comparison.cpp b/FreeFileSync/Source/comparison.cpp
index f699c5cb..99e9b8d6 100644
--- a/FreeFileSync/Source/comparison.cpp
+++ b/FreeFileSync/Source/comparison.cpp
@@ -626,7 +626,9 @@ void MergeSides::fillOneSide(const FolderContainer& folderCont, const std::wstri
}
-//improve merge-perf by over 70% + more natural default sequence
+//perf: 70% faster than traversing over left and right containers + more natural default sequence
+//- 2 x lessKey vs 1 x cmpFilePath() => no significant difference
+//- simplify loop by placing the eob check at the beginning => slightly slower
template <class MapType, class ProcessLeftOnly, class ProcessRightOnly, class ProcessBoth> inline
void linearMerge(const MapType& mapLeft, const MapType& mapRight, ProcessLeftOnly lo, ProcessRightOnly ro, ProcessBoth bo)
{
@@ -874,7 +876,7 @@ FolderComparison zen::compare(xmlAccess::OptionalDialogs& warnings,
//directory existence only checked *once* to avoid race conditions!
if (resInfo.resolvedPairs.size() != cfgList.size())
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
checkForIncompleteInput(resInfo.resolvedPairs, warnings.warningInputFieldEmpty, callback);
checkFolderDependency (resInfo.resolvedPairs, warnings.warningDependentFolders, callback);
@@ -979,6 +981,6 @@ FolderComparison zen::compare(xmlAccess::OptionalDialogs& warnings,
callback.reportFatalError(_("Out of memory.") + L" " + utfCvrtTo<std::wstring>(e.what()));
//we need to maintain the "output.size() == cfgList.size()" contract in ALL cases! => abort
callback.abortProcessNow(); //throw X
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
}
}
diff --git a/FreeFileSync/Source/file_hierarchy.h b/FreeFileSync/Source/file_hierarchy.h
index 1e7741ad..f83eb720 100644
--- a/FreeFileSync/Source/file_hierarchy.h
+++ b/FreeFileSync/Source/file_hierarchy.h
@@ -116,7 +116,7 @@ struct FolderContainer
void addSubFile(const Zstring& itemName, const FileDescriptor& fileData)
{
auto rv = files.emplace(itemName, fileData);
- if (!rv.second) //update entry if already existing (e.g. during folder traverser "retry")
+ if (!rv.second) //update entry if already existing (e.g. during folder traverser "retry") => does not handle different item name case (irrelvant!..)
rv.first->second = fileData;
}
diff --git a/FreeFileSync/Source/fs/abstract.cpp b/FreeFileSync/Source/fs/abstract.cpp
index 20e86923..b8c5bec3 100644
--- a/FreeFileSync/Source/fs/abstract.cpp
+++ b/FreeFileSync/Source/fs/abstract.cpp
@@ -5,6 +5,7 @@
// **************************************************************************
#include "abstract.h"
+#include <zen/serialize.h>
using namespace zen;
using AFS = AbstractFileSystem;
@@ -13,49 +14,26 @@ const Zchar* AFS::TEMP_FILE_ENDING = Zstr(".ffs_tmp");
AFS::FileAttribAfterCopy AFS::copyFileAsStream(const Zstring& itemPathImplSource, const AbstractPath& apTarget, //throw FileError, ErrorTargetExisting, ErrorFileLocked
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) const
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) const
{
auto streamIn = getInputStream(itemPathImplSource); //throw FileError, ErrorFileLocked
- if (onNotifyCopyStatus) onNotifyCopyStatus(0); //throw X!
+ if (notifyProgress) notifyProgress(0); //throw X!
- std::uint64_t bytesWritten = 0;
std::uint64_t fileSizeExpected = streamIn->getFileSize (); //throw FileError
const std::int64_t modificationTime = streamIn->getModificationTime(); //throw FileError
const FileId sourceFileId = streamIn->getFileId (); //throw FileError
- FileId targetFileId;
auto streamOut = getOutputStream(apTarget, &fileSizeExpected, &modificationTime); //throw FileError, ErrorTargetExisting
- if (onNotifyCopyStatus) onNotifyCopyStatus(0); //throw X!
+ if (notifyProgress) notifyProgress(0); //throw X!
- std::vector<char> buffer(std::min(streamIn ->optimalBlockSize(),
- streamOut->optimalBlockSize()));
- for (;;)
- {
- const size_t bytesRead = streamIn->read(&buffer[0], buffer.size()); //throw FileError
- assert(bytesRead <= buffer.size());
-
- streamOut->write(&buffer[0], bytesRead); //throw FileError
- bytesWritten += bytesRead;
-
- if (onNotifyCopyStatus)
- onNotifyCopyStatus(bytesRead); //throw X!
-
- if (bytesRead != buffer.size()) //end of file
- break;
- }
-
- //important check: catches corrupt sftp download with libssh2!
- if (bytesWritten != fileSizeExpected)
- throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getDisplayPath(itemPathImplSource))),
- replaceCpy(replaceCpy(_("Unexpected size of data stream.\nExpected: %x bytes\nActual: %y bytes"),
- L"%x", numberTo<std::wstring>(fileSizeExpected)),
- L"%y", numberTo<std::wstring>(bytesWritten)));
+ unbufferedStreamCopy(*streamIn, *streamOut, notifyProgress); //throw FileError
- //modification time should be set here!
- targetFileId = streamOut->finalize([&] { if (onNotifyCopyStatus) onNotifyCopyStatus(0); /*throw X*/ }); //throw FileError
+ const FileId targetFileId = streamOut->finalize([&] { if (notifyProgress) notifyProgress(0); /*throw X*/ }); //throw FileError
+ //- modification time should be set here!
+ //- checks if "expected == actual number of bytes written"
AFS::FileAttribAfterCopy attr;
- attr.fileSize = bytesWritten;
+ attr.fileSize = fileSizeExpected;
attr.modificationTime = modificationTime;
attr.sourceFileId = sourceFileId;
attr.targetFileId = targetFileId;
@@ -67,20 +45,20 @@ AFS::FileAttribAfterCopy AFS::copyFileTransactional(const AbstractPath& apSource
bool copyFilePermissions,
bool transactionalCopy,
const std::function<void()>& onDeleteTargetFile,
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
auto copyFileBestEffort = [&](const AbstractPath& apTargetTmp)
{
//caveat: typeid returns static type for pointers, dynamic type for references!!!
if (typeid(*apSource.afs) == typeid(*apTarget.afs))
- return apSource.afs->copyFileForSameAfsType(apSource.itemPathImpl, apTargetTmp, copyFilePermissions, onNotifyCopyStatus); //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ return apSource.afs->copyFileForSameAfsType(apSource.itemPathImpl, apTargetTmp, copyFilePermissions, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
//fall back to stream-based file copy:
if (copyFilePermissions)
throw FileError(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(AFS::getDisplayPath(apTargetTmp))),
_("Operation not supported for different base folder types."));
- return AFS::copyFileAsStream(apSource, apTargetTmp, onNotifyCopyStatus); //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ return AFS::copyFileAsStream(apSource, apTargetTmp, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
};
if (transactionalCopy)
@@ -96,7 +74,7 @@ AFS::FileAttribAfterCopy AFS::copyFileTransactional(const AbstractPath& apSource
}
catch (const ErrorTargetExisting&) //optimistic strategy: assume everything goes well, but recover on error -> minimize file accesses
{
- if (i == 10) throw; //avoid endless recursion in pathological cases, e.g. https://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/36adac33
+ if (i == 10) throw; //avoid endless recursion in pathological cases, e.g. http://www.freefilesync.org/forum/viewtopic.php?t=1592
apTargetTmp.itemPathImpl = apTarget.itemPathImpl + Zchar('_') + numberTo<Zstring>(i) + TEMP_FILE_ENDING;
}
diff --git a/FreeFileSync/Source/fs/abstract.h b/FreeFileSync/Source/fs/abstract.h
index 1b21757c..e424506c 100644
--- a/FreeFileSync/Source/fs/abstract.h
+++ b/FreeFileSync/Source/fs/abstract.h
@@ -113,18 +113,18 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
struct InputStream
{
virtual ~InputStream() {}
- virtual size_t read(void* buffer, size_t bytesToRead) = 0; //throw FileError; returns "bytesToRead", unless end of file!
+ virtual size_t getBlockSize() const = 0; //non-zero block size is AFS contract! it's implementers job to always give a reasonable buffer size!
+ virtual size_t tryRead(void* buffer, size_t bytesToRead) = 0; //throw FileError; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
virtual FileId getFileId () = 0; //throw FileError
virtual std::int64_t getModificationTime() = 0; //throw FileError
virtual std::uint64_t getFileSize () = 0; //throw FileError
- virtual size_t optimalBlockSize() const = 0; //non-zero block size is AFS contract! it's implementers job to always give a reasonable buffer size!
};
struct OutputStreamImpl
{
virtual ~OutputStreamImpl() {}
- virtual size_t optimalBlockSize() const = 0; //non-zero block size is AFS contract!
- virtual void write (const void* buffer, size_t bytesToWrite ) = 0; //throw FileError
+ virtual size_t getBlockSize() const = 0; //non-zero block size is AFS contract!
+ virtual size_t tryWrite(const void* data, size_t len) = 0; //throw FileError; may return short! CONTRACT: bytesToWrite > 0
virtual FileId finalize(const std::function<void()>& onUpdateStatus) = 0; //throw FileError
};
@@ -133,16 +133,16 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
{
OutputStream(std::unique_ptr<OutputStreamImpl>&& outStream, const AbstractPath& filePath, const std::uint64_t* streamSize);
~OutputStream();
- size_t optimalBlockSize() const { return outStream_->optimalBlockSize(); } //non-zero block size is AFS contract!
- void write(const void* buffer, size_t bytesToWrite); //throw FileError
- FileId finalize(const std::function<void()>& onUpdateStatus); //throw FileError
+ size_t getBlockSize() const { return outStream_->getBlockSize(); } //non-zero block size is AFS contract!
+ size_t tryWrite(const void* data, size_t len); //throw FileError; may return short! CONTRACT: bytesToWrite > 0
+ FileId finalize (const std::function<void()>& onUpdateStatus); //throw FileError
private:
std::unique_ptr<OutputStreamImpl> outStream_; //bound!
const AbstractPath filePath_;
bool finalizeSucceeded = false;
Opt<std::uint64_t> bytesExpected;
- std::uint64_t bytesWritten = 0;
+ std::uint64_t bytesWrittenTotal = 0;
};
//return value always bound:
@@ -215,8 +215,8 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
//symlink handling: dereference source
static FileAttribAfterCopy copyFileAsStream(const AbstractPath& apSource, const AbstractPath& apTarget, //throw FileError, ErrorTargetExisting, ErrorFileLocked
//accummulated delta != file size! consider ADS, sparse, compressed files
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) //may be nullptr; throw X!
- { return apSource.afs->copyFileAsStream(apSource.itemPathImpl, apTarget, onNotifyCopyStatus); }
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //may be nullptr; throw X!
+ { return apSource.afs->copyFileAsStream(apSource.itemPathImpl, apTarget, notifyProgress); }
//Note: it MAY happen that copyFileTransactional() leaves temp files behind, e.g. temporary network drop.
@@ -229,7 +229,7 @@ struct AbstractFileSystem //THREAD-SAFETY: "const" member functions must model t
//if target is existing user needs to implement deletion: copyFile() NEVER overwrites target if already existing!
//if transactionalCopy == true, full read access on source had been proven at this point, so it's safe to delete it.
const std::function<void()>& onDeleteTargetFile,
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus);
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress);
static void copyNewFolder(const AbstractPath& apSource, const AbstractPath& apTarget, bool copyFilePermissions); //throw FileError
static void copySymlink (const AbstractPath& apSource, const AbstractPath& apTarget, bool copyFilePermissions); //throw FileError
@@ -265,7 +265,7 @@ protected: //grant derived classes access to AbstractPath:
static Zstring getItemPathImpl(const AbstractPath& ap) { return ap.itemPathImpl; }
FileAttribAfterCopy copyFileAsStream(const Zstring& itemPathImplSource, const AbstractPath& apTarget, //throw FileError, ErrorTargetExisting, ErrorFileLocked
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) const; //may be nullptr; throw X!
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) const; //may be nullptr; throw X!
private:
virtual bool isNativeFileSystem() const { return false; }
@@ -322,7 +322,7 @@ private:
//symlink handling: follow link!
virtual FileAttribAfterCopy copyFileForSameAfsType(const Zstring& itemPathImplSource, const AbstractPath& apTarget, bool copyFilePermissions, //throw FileError, ErrorTargetExisting, ErrorFileLocked
//accummulated delta != file size! consider ADS, sparse, compressed files
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) const = 0; //may be nullptr; throw X!
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) const = 0; //may be nullptr; throw X!
//symlink handling: follow link!
virtual void copyNewFolderForSameAfsType(const Zstring& itemPathImplSource, const AbstractPath& apTarget, bool copyFilePermissions) const = 0; //throw FileError
@@ -459,7 +459,7 @@ AbstractFileSystem::OutputStream::OutputStream(std::unique_ptr<OutputStreamImpl>
inline
AbstractFileSystem::OutputStream::~OutputStream()
{
- //delete file on errors: => fail if already existing BEFORE creating OutputStream instance!!
+ //we delete the file on errors: => fail if already existing BEFORE creating OutputStream instance!!
outStream_.reset(); //close file handle *before* remove!
@@ -470,24 +470,31 @@ AbstractFileSystem::OutputStream::~OutputStream()
inline
-void AbstractFileSystem::OutputStream::write(const void* buffer, size_t bytesToWrite)
+size_t AbstractFileSystem::OutputStream::tryWrite(const void* data, size_t len) //throw FileError, CONTRACT: bytesToWrite > 0
{
- bytesWritten += bytesToWrite;
- outStream_->write(buffer, bytesToWrite); //throw FileError
+ if (len == 0)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
+ const size_t bytesWritten = outStream_->tryWrite(data, len); //throw FileError; CONTRACT: bytesToWrite > 0
+ if (bytesWritten > len)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
+ bytesWrittenTotal += bytesWritten;
+ return bytesWritten;
}
inline
AbstractFileSystem::FileId AbstractFileSystem::OutputStream::finalize(const std::function<void()>& onUpdateStatus) //throw FileError
{
- if (bytesExpected && bytesWritten != *bytesExpected)
+ //important check: catches corrupt sftp download with libssh2!
+ if (bytesExpected && *bytesExpected != bytesWrittenTotal)
throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getDisplayPath(filePath_))),
replaceCpy(replaceCpy(_("Unexpected size of data stream.\nExpected: %x bytes\nActual: %y bytes"),
L"%x", numberTo<std::wstring>(*bytesExpected)),
- L"%y", numberTo<std::wstring>(bytesWritten)));
-
- const FileId fileId = outStream_->finalize(onUpdateStatus); //throw FileError
+ L"%y", numberTo<std::wstring>(bytesWrittenTotal)));
+ FileId fileId = outStream_->finalize(onUpdateStatus); //throw FileError
finalizeSucceeded = true;
return fileId;
}
diff --git a/FreeFileSync/Source/fs/native.cpp b/FreeFileSync/Source/fs/native.cpp
index a592f069..de0b3d27 100644
--- a/FreeFileSync/Source/fs/native.cpp
+++ b/FreeFileSync/Source/fs/native.cpp
@@ -143,11 +143,11 @@ struct InputStreamNative : public AbstractFileSystem::InputStream
{
InputStreamNative(const Zstring& filePath) : fi(filePath) {} //throw FileError, ErrorFileLocked
- size_t read(void* buffer, size_t bytesToRead) override { return fi.read(buffer, bytesToRead); } //throw FileError; returns "bytesToRead", unless end of file!
+ size_t getBlockSize() const override { return fi.getBlockSize(); } //non-zero block size is AFS contract!
+ size_t tryRead(void* buffer, size_t bytesToRead) override { return fi.tryRead(buffer, bytesToRead); } //throw FileError; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
AFS::FileId getFileId () override; //throw FileError
std::int64_t getModificationTime() override; //throw FileError
std::uint64_t getFileSize () override; //throw FileError
- size_t optimalBlockSize() const override { return fi.optimalBlockSize(); } //non-zero block size is AFS contract!
private:
const FileAttribs& getBufferedAttributes() //throw FileError
@@ -205,10 +205,9 @@ struct OutputStreamNative : public AbstractFileSystem::OutputStreamImpl
preAllocateSpaceBestEffort(fo.getHandle(), *streamSize, fo.getFilePath()); //throw FileError
}
- size_t optimalBlockSize() const override { return fo.optimalBlockSize(); } //non-zero block size is AFS contract!
+ size_t getBlockSize() const override { return fo.getBlockSize(); } //non-zero block size is AFS contract!
-private:
- void write(const void* buffer, size_t bytesToWrite) override { fo.write(buffer, bytesToWrite); } //throw FileError
+ size_t tryWrite(const void* buffer, size_t bytesToWrite) override { return fo.tryWrite(buffer, bytesToWrite); } //throw FileError; may return short! CONTRACT: bytesToWrite > 0
AFS::FileId finalize(const std::function<void()>& onUpdateStatus) override //throw FileError
{
@@ -230,10 +229,10 @@ private:
//perspective (treated like external update), except for the inconvenience.
//Support additional scenarios like writing to FTP on Linux? Keep strict handling for now.
}
-
return fileId;
}
+private:
FileOutput fo;
Opt<std::int64_t> modTime_;
};
@@ -248,7 +247,7 @@ public:
static Zstring getItemPathImplForRecycler(const AbstractPath& ap)
{
if (typeid(getAfs(ap)) != typeid(NativeFileSystem))
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
return getItemPathImpl(ap);
}
diff --git a/FreeFileSync/Source/lib/binary.cpp b/FreeFileSync/Source/lib/binary.cpp
index 8ec4a184..67630d78 100644
--- a/FreeFileSync/Source/lib/binary.cpp
+++ b/FreeFileSync/Source/lib/binary.cpp
@@ -5,9 +5,8 @@
// **************************************************************************
#include "binary.h"
-#include <zen/tick_count.h>
#include <vector>
-#include <zen/file_io.h>
+#include <zen/tick_count.h>
using namespace zen;
using AFS = AbstractFileSystem;
@@ -33,97 +32,127 @@ buffer MB/s
8192 56
*/
-class BufferSize
-{
-public:
- BufferSize(size_t initialSize) : bufSize(initialSize) {}
+const size_t BLOCK_SIZE_MAX = 16 * 1024 * 1024;
+const std::int64_t TICKS_PER_SEC = ticksPerSec();
- void inc()
- {
- if (bufSize < BUFFER_SIZE_MAX)
- bufSize *= 2;
- }
- void dec()
+struct StreamReader
+{
+ StreamReader(const AbstractPath& filePath, const std::function<void(std::int64_t bytesDelta)>& notifyProgress, size_t& unevenBytes) :
+ stream(AFS::getInputStream(filePath)), //throw FileError, (ErrorFileLocked)
+ defaultBlockSize(stream->getBlockSize()),
+ dynamicBlockSize(defaultBlockSize),
+ notifyProgress_(notifyProgress),
+ unevenBytes_(unevenBytes) {}
+
+ void appendChunk(std::vector<char>& buffer) //throw FileError
{
- if (bufSize > BUFFER_SIZE_MIN)
- bufSize /= 2;
- }
+ assert(!eof);
+ if (eof) return;
- size_t get() const { return bufSize; }
+ const TickVal startTime = getTicks();
-private:
- static const size_t BUFFER_SIZE_MIN = 8 * 1024; //slow FTP transfer!
- static const size_t BUFFER_SIZE_MAX = 1024 * 1024 * 1024;
+ buffer.resize(buffer.size() + dynamicBlockSize);
+ const size_t bytesRead = stream->tryRead(&*(buffer.end() - dynamicBlockSize), dynamicBlockSize); //throw FileError; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
+ buffer.resize(buffer.size() - dynamicBlockSize + bytesRead); //caveat: unsigned arithmetics
- size_t bufSize;
-};
+ const TickVal stopTime = getTicks();
+ //report bytes processed
+ if (notifyProgress_)
+ {
+ const size_t bytesToReport = (unevenBytes_ + bytesRead) / 2;
+ notifyProgress_(bytesToReport); //throw X!
+ unevenBytes_ = (unevenBytes_ + bytesRead) - bytesToReport * 2; //unsigned arithmetics!
+ }
-inline
-void setMinSize(std::vector<char>& buffer, size_t minSize)
-{
- if (buffer.size() < minSize) //this is similar to reserve(), but we need a "properly initialized" array here
- buffer.resize(minSize);
-}
+ if (bytesRead == 0)
+ {
+ eof = true;
+ return;
+ }
+ if (TICKS_PER_SEC > 0)
+ {
+ size_t proposedBlockSize = 0;
+ const std::int64_t loopTimeMs = dist(startTime, stopTime) * 1000 / TICKS_PER_SEC; //unit: [ms]
-const std::int64_t TICKS_PER_SEC = ticksPerSec();
+ if (loopTimeMs >= 100)
+ lastDelayViolation = stopTime;
+
+ //avoid "flipping back": e.g. DVD-ROMs read 32MB at once, so first read may be > 500 ms, but second one will be 0ms!
+ if (dist(lastDelayViolation, stopTime) / TICKS_PER_SEC >= 2)
+ {
+ lastDelayViolation = stopTime;
+ proposedBlockSize = dynamicBlockSize * 2;
+ }
+ if (loopTimeMs > 500)
+ proposedBlockSize = dynamicBlockSize / 2;
+
+ if (defaultBlockSize <= proposedBlockSize && proposedBlockSize <= BLOCK_SIZE_MAX)
+ dynamicBlockSize = proposedBlockSize;
+ }
+ }
+
+ bool isEof() const { return eof; }
+
+private:
+ const std::unique_ptr<AFS::InputStream> stream;
+ const size_t defaultBlockSize;
+ size_t dynamicBlockSize;
+ const std::function<void(std::int64_t bytesDelta)> notifyProgress_;
+ size_t& unevenBytes_;
+ TickVal lastDelayViolation = getTicks();
+ bool eof = false;
+};
}
-bool zen::filesHaveSameContent(const AbstractPath& filePath1, const AbstractPath& filePath2, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //throw FileError
+bool zen::filesHaveSameContent(const AbstractPath& filePath1, const AbstractPath& filePath2, const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //throw FileError
{
- const std::unique_ptr<AFS::InputStream> inStream1 = AFS::getInputStream(filePath1); //throw FileError, (ErrorFileLocked)
- const std::unique_ptr<AFS::InputStream> inStream2 = AFS::getInputStream(filePath2); //
+ size_t unevenBytes = 0;
+ StreamReader reader1(filePath1, notifyProgress, unevenBytes); //throw FileError, (ErrorFileLocked)
+ StreamReader reader2(filePath2, notifyProgress, unevenBytes); //
- BufferSize dynamicBufSize(std::min(inStream1->optimalBlockSize(),
- inStream2->optimalBlockSize()));
+ StreamReader* readerLow = &reader1;
+ StreamReader* readerHigh = &reader2;
- TickVal lastDelayViolation = getTicks();
- std::vector<char> buf; //make this thread-local? => on noticeable perf advantage!
+ std::vector<char> bufferLow;
+ std::vector<char> bufferHigh;
for (;;)
{
- const size_t bufSize = dynamicBufSize.get(); //save for reliable eof check below!!!
- setMinSize(buf, 2 * bufSize);
- char* buf1 = &buf[0];
- char* buf2 = &buf[bufSize];
+ const size_t bytesChecked = bufferLow.size();
- const TickVal startTime = getTicks();
+ readerLow->appendChunk(bufferLow); //throw FileError
- const size_t length1 = inStream1->read(buf1, bufSize); //throw FileError
- const size_t length2 = inStream2->read(buf2, bufSize); //returns actual number of bytes read
- //send progress updates immediately after reading to reliably allow speed calculations for our clients!
- if (onUpdateStatus)
- onUpdateStatus(std::max(length1, length2));
+ if (bufferLow.size() > bufferHigh.size())
+ {
+ bufferLow.swap(bufferHigh);
+ std::swap(readerLow, readerHigh);
+ }
- if (length1 != length2 || ::memcmp(buf1, buf2, length1) != 0)
+ if (!std::equal(bufferLow. begin() + bytesChecked, bufferLow.end(),
+ bufferHigh.begin() + bytesChecked))
return false;
- //-------- dynamically set buffer size to keep callback interval between 100 - 500ms ---------------------
- if (TICKS_PER_SEC > 0)
+ if (readerLow->isEof())
{
- const TickVal now = getTicks();
-
- const std::int64_t loopTime = dist(startTime, now) * 1000 / TICKS_PER_SEC; //unit: [ms]
- if (loopTime < 100)
- {
- if (dist(lastDelayViolation, now) / TICKS_PER_SEC > 2) //avoid "flipping back": e.g. DVD-Roms read 32MB at once, so first read may be > 500 ms, but second one will be 0ms!
- {
- lastDelayViolation = now;
- dynamicBufSize.inc();
- }
- }
- else if (loopTime > 500)
- {
- lastDelayViolation = now;
- dynamicBufSize.dec();
- }
+ if (bufferLow.size() < bufferHigh.size())
+ return false;
+ if (readerHigh->isEof())
+ break;
+ //bufferLow.swap(bufferHigh); not needed
+ std::swap(readerLow, readerHigh);
}
- //------------------------------------------------------------------------------------------------
- if (length1 != bufSize) //end of file
- return true;
+ //don't let sliding buffer grow too large
+ bufferHigh.erase(bufferHigh.begin(), bufferHigh.begin() + bufferLow.size());
+ bufferLow.clear();
}
+
+ if (unevenBytes != 0)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
+ return true;
}
diff --git a/FreeFileSync/Source/lib/binary.h b/FreeFileSync/Source/lib/binary.h
index 41e4f3df..e23aa36b 100644
--- a/FreeFileSync/Source/lib/binary.h
+++ b/FreeFileSync/Source/lib/binary.h
@@ -7,8 +7,6 @@
#ifndef BINARY_H_3941281398513241134
#define BINARY_H_3941281398513241134
-#include <functional>
-#include <zen/file_error.h>
#include "../fs/abstract.h"
@@ -16,7 +14,7 @@ namespace zen
{
bool filesHaveSameContent(const AbstractPath& filePath1, //throw FileError
const AbstractPath& filePath2,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus); //may be nullptr
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress); //may be nullptr
}
#endif //BINARY_H_3941281398513241134
diff --git a/FreeFileSync/Source/lib/db_file.cpp b/FreeFileSync/Source/lib/db_file.cpp
index ea3d5efd..0bcc3e40 100644
--- a/FreeFileSync/Source/lib/db_file.cpp
+++ b/FreeFileSync/Source/lib/db_file.cpp
@@ -37,8 +37,8 @@ using MemStreamIn = MemoryStreamIn <ByteArray>;
template <SelectedSide side> inline
AbstractPath getDatabaseFilePath(const BaseFolderPair& baseFolder, bool tempfile = false)
{
- //Linux and Windows builds are binary incompatible: different file id?, problem with case sensitivity? are UTC file times really compatible?
- //what about endianess!?
+ //Linux and Windows builds are binary incompatible: different file id?, problem with case sensitivity?
+ //precomposed/decomposed UTF? are UTC file times really compatible? what about endianess!?
//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 be excluded from comparison
@@ -54,7 +54,7 @@ AbstractPath getDatabaseFilePath(const BaseFolderPair& baseFolder, bool tempfile
//#######################################################################################################################################
-void saveStreams(const DbStreams& streamList, const AbstractPath& dbPath, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //throw FileError
+void saveStreams(const DbStreams& streamList, const AbstractPath& dbPath, const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //throw FileError
{
//perf? instead of writing to a file stream directly, collect data into memory first, then write to file block-wise
MemStreamOut memStreamOut;
@@ -78,12 +78,11 @@ void saveStreams(const DbStreams& streamList, const AbstractPath& dbPath, const
//save memory stream to file (as a transaction!)
{
- MemoryStreamIn<ByteArray> memStreamIn(memStreamOut.ref());
- const std::uint64_t streamSize = memStreamOut.ref().size();
- const std::unique_ptr<AFS::OutputStream> fileStreamOut = AFS::getOutputStream(dbPath, &streamSize, nullptr /*modificationTime*/); //throw FileError, ErrorTargetExisting
- if (onUpdateStatus) onUpdateStatus(0);
- copyStream(memStreamIn, *fileStreamOut, fileStreamOut->optimalBlockSize(), onUpdateStatus); //throw FileError
- fileStreamOut->finalize([&] { if (onUpdateStatus) onUpdateStatus(0); }); //throw FileError
+ const std::uint64_t bufferSize = memStreamOut.ref().size();
+ const std::unique_ptr<AFS::OutputStream> fileStreamOut = AFS::getOutputStream(dbPath, &bufferSize, nullptr /*modificationTime*/); //throw FileError, ErrorTargetExisting
+ if (notifyProgress) notifyProgress(0);
+ unbufferedSave(memStreamOut.ref(), *fileStreamOut, notifyProgress); //throw FileError
+ fileStreamOut->finalize([&] { if (notifyProgress) notifyProgress(0); }); //throw FileError
//commit and close stream
}
@@ -94,19 +93,19 @@ void saveStreams(const DbStreams& streamList, const AbstractPath& dbPath, const
}
-DbStreams loadStreams(const AbstractPath& dbPath, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //throw FileError, FileErrorDatabaseNotExisting
+DbStreams loadStreams(const AbstractPath& dbPath, const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //throw FileError, FileErrorDatabaseNotExisting
{
try
{
//load memory stream from file
- MemoryStreamOut<ByteArray> memStreamOut;
+ ByteArray buffer;
{
const std::unique_ptr<AFS::InputStream> fileStreamIn = AFS::getInputStream(dbPath); //throw FileError, ErrorFileLocked
- if (onUpdateStatus) onUpdateStatus(0);
- copyStream(*fileStreamIn, memStreamOut, fileStreamIn->optimalBlockSize(), onUpdateStatus); //throw FileError
+ if (notifyProgress) notifyProgress(0);
+ buffer = unbufferedLoad<ByteArray>(*fileStreamIn, notifyProgress); //throw FileError
} //close file handle
- MemStreamIn streamIn(memStreamOut.ref());
+ MemStreamIn streamIn(buffer);
//read FreeFileSync file identifier
char formatDescr[sizeof(FILE_FORMAT_DESCR)] = {};
@@ -142,7 +141,7 @@ DbStreams loadStreams(const AbstractPath& dbPath, const std::function<void(std::
}
catch (UnexpectedEndOfStreamError&)
{
- throw FileError(_("Database file is corrupt:") + L"\n" + fmtPath(AFS::getDisplayPath(dbPath)));
+ throw FileError(_("Database file is corrupt:") + L"\n" + fmtPath(AFS::getDisplayPath(dbPath)), L"Unexpected end of stream.");
}
catch (const std::bad_alloc& e) //still required?
{
@@ -343,7 +342,7 @@ public:
}
catch (const UnexpectedEndOfStreamError&)
{
- throw FileError(_("Database file is corrupt:") + L"\n" + fmtPath(displayFilePathL) + L"\n" + fmtPath(displayFilePathR));
+ throw FileError(_("Database file is corrupt:") + L"\n" + fmtPath(displayFilePathL) + L"\n" + fmtPath(displayFilePathR), L"Unexpected end of stream.");
}
catch (const std::bad_alloc& e)
{
@@ -690,7 +689,7 @@ private:
//#######################################################################################################################################
std::shared_ptr<InSyncFolder> zen::loadLastSynchronousState(const BaseFolderPair& baseFolder, //throw FileError, FileErrorDatabaseNotExisting -> return value always bound!
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
const AbstractPath dbPathLeft = getDatabaseFilePath<LEFT_SIDE >(baseFolder);
const AbstractPath dbPathRight = getDatabaseFilePath<RIGHT_SIDE>(baseFolder);
@@ -706,8 +705,8 @@ std::shared_ptr<InSyncFolder> zen::loadLastSynchronousState(const BaseFolderPair
}
//read file data: list of session ID + DirInfo-stream
- const DbStreams streamsLeft = ::loadStreams(dbPathLeft, onUpdateStatus); //throw FileError, FileErrorDatabaseNotExisting
- const DbStreams streamsRight = ::loadStreams(dbPathRight, onUpdateStatus); //
+ const DbStreams streamsLeft = ::loadStreams(dbPathLeft, notifyProgress); //throw FileError, FileErrorDatabaseNotExisting
+ const DbStreams streamsRight = ::loadStreams(dbPathRight, notifyProgress); //
//find associated session: there can be at most one session within intersection of left and right ids
for (const auto& streamLeft : streamsLeft)
@@ -726,7 +725,7 @@ std::shared_ptr<InSyncFolder> zen::loadLastSynchronousState(const BaseFolderPair
}
-void zen::saveLastSynchronousState(const BaseFolderPair& baseFolder, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //throw FileError
+void zen::saveLastSynchronousState(const BaseFolderPair& baseFolder, const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //throw FileError
{
//transactional behaviour! write to tmp files first
const AbstractPath dbPathLeft = getDatabaseFilePath<LEFT_SIDE >(baseFolder);
@@ -744,12 +743,12 @@ void zen::saveLastSynchronousState(const BaseFolderPair& baseFolder, const std::
DbStreams streamsRight;
//std::function<void(std::int64_t bytesDelta)> onUpdateLoadStatus;
- //if (onUpdateStatus)
- // onUpdateLoadStatus = [&](std::int64_t bytesDelta) { onUpdateStatus(0); };
+ //if (notifyProgress)
+ // onUpdateLoadStatus = [&](std::int64_t bytesDelta) { notifyProgress(0); };
- try { streamsLeft = ::loadStreams(dbPathLeft, onUpdateStatus); }
+ try { streamsLeft = ::loadStreams(dbPathLeft, notifyProgress); }
catch (FileError&) {}
- try { streamsRight = ::loadStreams(dbPathRight, onUpdateStatus); }
+ try { streamsRight = ::loadStreams(dbPathRight, notifyProgress); }
catch (FileError&) {}
//if error occurs: just overwrite old file! User is already informed about issues right after comparing!
@@ -810,10 +809,10 @@ void zen::saveLastSynchronousState(const BaseFolderPair& baseFolder, const std::
streamsRight[sessionID] = std::move(updatedStreamRight);
//write (temp-) files as a transaction
- saveStreams(streamsLeft, dbPathLeftTmp, onUpdateStatus); //throw FileError
- saveStreams(streamsRight, dbPathRightTmp, onUpdateStatus); //
+ saveStreams(streamsLeft, dbPathLeftTmp, notifyProgress); //throw FileError
+ saveStreams(streamsRight, dbPathRightTmp, notifyProgress); //
- //operation finished: rename temp files -> this should work transactionally:
+ //operation finished: rename temp files -> this should work (almost) transactionally:
//if there were no write access, creation of temp files would have failed
AFS::removeFile(dbPathLeft); //throw FileError
AFS::renameItem(dbPathLeftTmp, dbPathLeft); //throw FileError, (ErrorTargetExisting, ErrorDifferentVolume)
diff --git a/FreeFileSync/Source/lib/db_file.h b/FreeFileSync/Source/lib/db_file.h
index 0876f7c2..69eb3aa0 100644
--- a/FreeFileSync/Source/lib/db_file.h
+++ b/FreeFileSync/Source/lib/db_file.h
@@ -95,10 +95,10 @@ struct InSyncFolder
DEFINE_NEW_FILE_ERROR(FileErrorDatabaseNotExisting);
std::shared_ptr<InSyncFolder> loadLastSynchronousState(const BaseFolderPair& baseDirObj, //throw FileError, FileErrorDatabaseNotExisting -> return value always bound!
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus);
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress);
void saveLastSynchronousState(const BaseFolderPair& baseDirObj, //throw FileError
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus);
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress);
}
#endif //DB_FILE_H_834275398588021574
diff --git a/FreeFileSync/Source/lib/dir_exist_async.h b/FreeFileSync/Source/lib/dir_exist_async.h
index 33b31afc..56a14cdc 100644
--- a/FreeFileSync/Source/lib/dir_exist_async.h
+++ b/FreeFileSync/Source/lib/dir_exist_async.h
@@ -49,7 +49,7 @@ FolderStatus getFolderStatusNonBlocking(const std::set<AbstractPath, AFS::LessAb
}));
//don't wait (almost) endlessly like Win32 would on non-existing network shares:
- std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now() + std::chrono::seconds(folderAccessTimeout);
+ std::chrono::steady_clock::time_point stopTime = std::chrono::steady_clock::now() + std::chrono::seconds(folderAccessTimeout);
for (auto& fi : futureInfo)
{
@@ -57,7 +57,7 @@ FolderStatus getFolderStatusNonBlocking(const std::set<AbstractPath, AFS::LessAb
procCallback.reportStatus(replaceCpy(_("Searching for folder %x..."), L"%x", displayPathFmt)); //may throw!
- while (std::chrono::steady_clock::now() < endTime &&
+ while (std::chrono::steady_clock::now() < stopTime &&
fi.second.wait_for(std::chrono::milliseconds(UI_UPDATE_INTERVAL / 2)) != std::future_status::ready)
procCallback.requestUiRefresh(); //may throw!
diff --git a/FreeFileSync/Source/lib/dir_lock.cpp b/FreeFileSync/Source/lib/dir_lock.cpp
index abd8d633..fc98f308 100644
--- a/FreeFileSync/Source/lib/dir_lock.cpp
+++ b/FreeFileSync/Source/lib/dir_lock.cpp
@@ -13,15 +13,15 @@
#include <zen/guid.h>
#include <zen/tick_count.h>
#include <zen/file_access.h>
-#include <zen/serialize.h>
+#include <zen/file_io.h>
#include <zen/optional.h>
#ifdef ZEN_WIN
+ #include <zen/win_process.h>
#include <zen/int64.h>
#include <zen/win.h> //includes "windows.h"
#include <zen/long_path_prefix.h>
#include <zen/privilege.h>
- #include <tlhelp32.h>
#include <Sddl.h> //login sid
#include <Lmcons.h> //UNLEN
@@ -136,27 +136,6 @@ private:
};
-std::uint64_t getLockFileSize(const Zstring& filepath) //throw FileError
-{
-#ifdef ZEN_WIN
- WIN32_FIND_DATA fileInfo = {};
- const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(filepath).c_str(), &fileInfo);
- if (searchHandle == INVALID_HANDLE_VALUE)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(filepath)), L"FindFirstFile");
- ::FindClose(searchHandle);
-
- return get64BitUInt(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh);
-
-#elif defined ZEN_LINUX || defined ZEN_MAC
- struct ::stat fileInfo = {};
- if (::stat(filepath.c_str(), &fileInfo) != 0) //follow symbolic links
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(filepath)), L"stat");
-
- return fileInfo.st_size;
-#endif
-}
-
-
Zstring abandonedLockDeletionName(const Zstring& lockFilePath) //make sure to NOT change file ending!
{
const size_t pos = lockFilePath.rfind(FILE_NAME_SEPARATOR); //search from end
@@ -230,28 +209,9 @@ Opt<SessionId> getSessionId(ProcessId processId) //throw FileError
{
#ifdef ZEN_WIN
//note: ::OpenProcess() is no alternative as it may successfully return for crashed processes! -> remark: "WaitForSingleObject" may identify this case!
- HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, //__in DWORD dwFlags,
- 0); //__in DWORD th32ProcessID
- if (snapshot == INVALID_HANDLE_VALUE)
- THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"CreateToolhelp32Snapshot");
- ZEN_ON_SCOPE_EXIT(::CloseHandle(snapshot));
-
- PROCESSENTRY32 processEntry = {};
- processEntry.dwSize = sizeof(processEntry);
-
- if (!::Process32First(snapshot, //__in HANDLE hSnapshot,
- &processEntry)) //__inout LPPROCESSENTRY32 lppe
- THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"Process32First"); //ERROR_NO_MORE_FILES not possible
- do
- {
- if (processEntry.th32ProcessID == processId) //yes, MSDN says this is the way: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684868(v=vs.85).aspx
- return processEntry.th32ParentProcessID; //parent id is stable, even if parent process has already terminated!
- }
- while (::Process32Next(snapshot, &processEntry));
-
- const DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls!
- if (ec != ERROR_NO_MORE_FILES) //yes, they call it "files"
- throw FileError(_("Cannot get process information."), formatSystemError(L"Process32Next", ec));
+ for (const ProcessInfo& procInfo : getRunningProcesses()) //throw FileError
+ if (procInfo.processId == processId) //yes, MSDN says this is the way: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684868
+ return procInfo.parentProcessId; //parent id is stable, even if parent process has already terminated!
return NoValue();
@@ -268,126 +228,131 @@ Opt<SessionId> getSessionId(ProcessId processId) //throw FileError
}
-class FromCurrentProcess {}; //tag
-
struct LockInformation //throw FileError
{
- explicit LockInformation(FromCurrentProcess) :
- lockId(zen::generateGUID()),
- sessionId(), //dummy value
+ std::string lockId; //16 byte GUID - a universal identifier for this lock (no matter what the path is, considering symlinks, distributed network, etc.)
+
+ //identify local computer
+ std::string computerName; //format: HostName.DomainName
+ std::string userId;
+
+ //identify running process
+ SessionId sessionId = 0; //Windows: parent process id; Linux/OS X: session of the process, NOT the user
+ ProcessId processId = 0;
+};
+
+
+LockInformation getLockInfoFromCurrentProcess() //throw FileError
+{
+ LockInformation lockInfo = {};
+ lockInfo.lockId = zen::generateGUID();
+
+ //wxGetFullHostName() is a performance killer and can hang for some users, so don't touch!
+
#ifdef ZEN_WIN
- processId(::GetCurrentProcessId()) //never fails
- {
- DWORD bufferSize = 0;
- ::GetComputerNameEx(ComputerNameDnsFullyQualified, nullptr, &bufferSize); //get required buffer size
+ lockInfo.processId = ::GetCurrentProcessId(); //never fails
- std::vector<wchar_t> buffer(bufferSize);
- if (!::GetComputerNameEx(ComputerNameDnsFullyQualified, //__in COMPUTER_NAME_FORMAT NameType,
- bufferSize > 0 ? &buffer[0] : nullptr, //__out LPTSTR lpBuffer,
- &bufferSize)) //__inout LPDWORD lpnSize
- THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"GetComputerNameEx");
+ DWORD bufferSize = 0;
+ ::GetComputerNameEx(ComputerNameDnsFullyQualified, nullptr, &bufferSize); //get required buffer size
- computerName = "Windows." + utfCvrtTo<std::string>(&buffer[0]);
+ std::vector<wchar_t> buffer(bufferSize);
+ if (!::GetComputerNameEx(ComputerNameDnsFullyQualified, //__in COMPUTER_NAME_FORMAT NameType,
+ bufferSize > 0 ? &buffer[0] : nullptr, //__out LPTSTR lpBuffer,
+ &bufferSize)) //__inout LPDWORD lpnSize
+ THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"GetComputerNameEx");
- bufferSize = UNLEN + 1;
- buffer.resize(bufferSize);
- if (!::GetUserName(&buffer[0], //__out LPTSTR lpBuffer,
- &bufferSize)) //__inout LPDWORD lpnSize
- THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"GetUserName");
- userId = utfCvrtTo<std::string>(&buffer[0]);
+ lockInfo.computerName = "Windows." + utfCvrtTo<std::string>(&buffer[0]);
+
+ bufferSize = UNLEN + 1;
+ buffer.resize(bufferSize);
+ if (!::GetUserName(&buffer[0], //__out LPTSTR lpBuffer,
+ &bufferSize)) //__inout LPDWORD lpnSize
+ THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"GetUserName");
+ lockInfo.userId = utfCvrtTo<std::string>(&buffer[0]);
#elif defined ZEN_LINUX || defined ZEN_MAC
- processId(::getpid()) //never fails
- {
- std::vector<char> buffer(10000);
-
- if (::gethostname(&buffer[0], buffer.size()) != 0)
- THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"gethostname");
- computerName += "Linux."; //distinguish linux/windows lock files
- computerName += &buffer[0];
-
- if (::getdomainname(&buffer[0], buffer.size()) != 0)
- THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"getdomainname");
- computerName += ".";
- computerName += &buffer[0];
-
- const uid_t userIdNo = ::getuid(); //never fails
- userId = numberTo<std::string>(userIdNo);
-
- //the id alone is not very distinctive, e.g. often 1000 on Ubuntu => add name
- buffer.resize(std::max<long>(buffer.size(), ::sysconf(_SC_GETPW_R_SIZE_MAX))); //::sysconf may return long(-1)
- struct passwd buffer2 = {};
- struct passwd* pwsEntry = nullptr;
- if (::getpwuid_r(userIdNo, &buffer2, &buffer[0], buffer.size(), &pwsEntry) != 0) //getlogin() is deprecated and not working on Ubuntu at all!!!
- THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"getpwuid_r");
- if (!pwsEntry)
- throw FileError(_("Cannot get process information."), L"no login found"); //should not happen?
- userId += '(' + std::string(pwsEntry->pw_name) + ')'; //follow Linux naming convention "1000(zenju)"
+ lockInfo.processId = ::getpid(); //never fails
+
+ std::vector<char> buffer(10000);
+ if (::gethostname(&buffer[0], buffer.size()) != 0)
+ THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"gethostname");
+ lockInfo.computerName = "Linux."; //distinguish linux/windows lock files
+ lockInfo.computerName += &buffer[0];
+
+ if (::getdomainname(&buffer[0], buffer.size()) != 0)
+ THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"getdomainname");
+ lockInfo.computerName += ".";
+ lockInfo.computerName += &buffer[0];
+
+ const uid_t userIdNo = ::getuid(); //never fails
+
+ //the id alone is not very distinctive, e.g. often 1000 on Ubuntu => add name
+ buffer.resize(std::max<long>(buffer.size(), ::sysconf(_SC_GETPW_R_SIZE_MAX))); //::sysconf may return long(-1)
+ struct passwd buffer2 = {};
+ struct passwd* pwsEntry = nullptr;
+ if (::getpwuid_r(userIdNo, &buffer2, &buffer[0], buffer.size(), &pwsEntry) != 0) //getlogin() is deprecated and not working on Ubuntu at all!!!
+ THROW_LAST_FILE_ERROR(_("Cannot get process information."), L"getpwuid_r");
+ if (!pwsEntry)
+ throw FileError(_("Cannot get process information."), L"no login found"); //should not happen?
+
+ lockInfo.userId = numberTo<std::string>(userIdNo) + "(" + pwsEntry->pw_name + ")"; //follow Linux naming convention "1000(zenju)"
#endif
- Opt<SessionId> sessionIdTmp = getSessionId(processId); //throw FileError
- if (!sessionIdTmp)
- throw FileError(_("Cannot get process information."), L"no session id found"); //should not happen?
- sessionId = *sessionIdTmp;
- }
+ Opt<SessionId> sessionIdTmp = getSessionId(lockInfo.processId); //throw FileError
+ if (!sessionIdTmp)
+ throw FileError(_("Cannot get process information."), L"no session id found"); //should not happen?
+ lockInfo.sessionId = *sessionIdTmp;
- explicit LockInformation(MemStreamIn& stream) //throw UnexpectedEndOfStreamError
- {
- char tmp[sizeof(LOCK_FORMAT_DESCR)] = {};
- readArray(stream, &tmp, sizeof(tmp)); //file format header
- const int lockFileVersion = readNumber<std::int32_t>(stream); //
-
- if (!std::equal(std::begin(tmp), std::end(tmp), std::begin(LOCK_FORMAT_DESCR)) ||
- lockFileVersion != LOCK_FORMAT_VER)
- throw UnexpectedEndOfStreamError(); //well, not really...!?
-
- lockId = readContainer<std::string>(stream); //
- computerName = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
- userId = readContainer<std::string>(stream); //
- sessionId = static_cast<SessionId>(readNumber<std::uint64_t>(stream)); //[!] conversion
- processId = static_cast<ProcessId>(readNumber<std::uint64_t>(stream)); //[!] conversion
- }
-
- void toStream(MemStreamOut& stream) const //throw ()
- {
- writeArray(stream, LOCK_FORMAT_DESCR, sizeof(LOCK_FORMAT_DESCR));
- writeNumber<std::int32_t>(stream, LOCK_FORMAT_VER);
-
- static_assert(sizeof(processId) <= sizeof(std::uint64_t), ""); //ensure cross-platform compatibility!
- static_assert(sizeof(sessionId) <= sizeof(std::uint64_t), ""); //
+ return lockInfo;
+}
- writeContainer(stream, lockId);
- writeContainer(stream, computerName);
- writeContainer(stream, userId);
- writeNumber<std::uint64_t>(stream, sessionId);
- writeNumber<std::uint64_t>(stream, processId);
- }
- std::string lockId; //16 byte GUID - a universal identifier for this lock (no matter what the path is, considering symlinks, distributed network, etc.)
+LockInformation unserialize(MemStreamIn& stream) //throw UnexpectedEndOfStreamError
+{
+ char tmp[sizeof(LOCK_FORMAT_DESCR)] = {};
+ readArray(stream, &tmp, sizeof(tmp)); //file format header
+ const int lockFileVersion = readNumber<std::int32_t>(stream); //
+
+ if (!std::equal(std::begin(tmp), std::end(tmp), std::begin(LOCK_FORMAT_DESCR)) ||
+ lockFileVersion != LOCK_FORMAT_VER)
+ throw UnexpectedEndOfStreamError(); //well, not really...!?
+
+ LockInformation lockInfo = {};
+ lockInfo.lockId = readContainer<std::string>(stream); //
+ lockInfo.computerName = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
+ lockInfo.userId = readContainer<std::string>(stream); //
+ lockInfo.sessionId = static_cast<SessionId>(readNumber<std::uint64_t>(stream)); //[!] conversion
+ lockInfo.processId = static_cast<ProcessId>(readNumber<std::uint64_t>(stream)); //[!] conversion
+ return lockInfo;
+}
- //identify local computer
- std::string computerName; //format: HostName.DomainName
- std::string userId;
- //identify running process
- SessionId sessionId; //Windows: parent process id; Linux/OS X: session of the process, NOT the user
- ProcessId processId;
-};
+void serialize(const LockInformation& lockInfo, MemStreamOut& stream)
+{
+ writeArray(stream, LOCK_FORMAT_DESCR, sizeof(LOCK_FORMAT_DESCR));
+ writeNumber<std::int32_t>(stream, LOCK_FORMAT_VER);
+ static_assert(sizeof(lockInfo.processId) <= sizeof(std::uint64_t), ""); //ensure cross-platform compatibility!
+ static_assert(sizeof(lockInfo.sessionId) <= sizeof(std::uint64_t), ""); //
-//wxGetFullHostName() is a performance killer and can hang for some users, so don't touch!
+ writeContainer(stream, lockInfo.lockId);
+ writeContainer(stream, lockInfo.computerName);
+ writeContainer(stream, lockInfo.userId);
+ writeNumber<std::uint64_t>(stream, lockInfo.sessionId);
+ writeNumber<std::uint64_t>(stream, lockInfo.processId);
+}
LockInformation retrieveLockInfo(const Zstring& lockFilePath) //throw FileError
{
- MemStreamIn streamIn = loadBinStream<ByteArray>(lockFilePath, nullptr); //throw FileError
+ MemStreamIn memStreamIn = loadBinContainer<ByteArray>(lockFilePath, nullptr); //throw FileError
try
{
- return LockInformation(streamIn); //throw UnexpectedEndOfStreamError
+ return unserialize(memStreamIn); //throw UnexpectedEndOfStreamError
}
catch (UnexpectedEndOfStreamError&)
{
- throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(lockFilePath)), L"unexpected end of stream");
+ throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(lockFilePath)), L"Unexpected end of stream.");
}
}
@@ -409,7 +374,7 @@ enum ProcessStatus
ProcessStatus getProcessStatus(const LockInformation& lockInfo) //throw FileError
{
- const LockInformation localInfo((FromCurrentProcess())); //throw FileError
+ const LockInformation localInfo = getLockInfoFromCurrentProcess(); //throw FileError
if (lockInfo.computerName != localInfo.computerName ||
lockInfo.userId != localInfo.userId) //another user may run a session right now!
@@ -466,7 +431,7 @@ void waitOnDirLock(const Zstring& lockFilePath, DirLockCallback* callback) //thr
for (;;)
{
const TickVal now = getTicks();
- const std::uint64_t fileSizeNew = getLockFileSize(lockFilePath); //throw FileError
+ const std::uint64_t fileSizeNew = getFilesize(lockFilePath); //throw FileError
if (TICKS_PER_SEC <= 0 || !lastLifeSign.isValid() || !now.isValid())
throw FileError(L"System timer failed."); //no i18n: "should" never throw ;)
@@ -478,7 +443,7 @@ void waitOnDirLock(const Zstring& lockFilePath, DirLockCallback* callback) //thr
}
if (lockOwnderDead || //no need to wait any longer...
- dist(lastLifeSign, now) / TICKS_PER_SEC > DETECT_ABANDONED_INTERVAL)
+ dist(lastLifeSign, now) / TICKS_PER_SEC >= DETECT_ABANDONED_INTERVAL)
{
DirLock dummy(abandonedLockDeletionName(lockFilePath), callback); //throw FileError
@@ -488,7 +453,7 @@ void waitOnDirLock(const Zstring& lockFilePath, DirLockCallback* callback) //thr
if (retrieveLockId(lockFilePath) != originalLockId) //throw FileError -> since originalLockId is filled, we are not expecting errors!
return; //another process has placed a new lock, leave scope: the wait for the old lock is technically over...
- if (getLockFileSize(lockFilePath) != fileSizeOld) //throw FileError
+ if (getFilesize(lockFilePath) != fileSizeOld) //throw FileError
continue; //late life sign
removeFile(lockFilePath); //throw FileError
@@ -585,16 +550,11 @@ bool tryLock(const Zstring& lockFilePath) //throw FileError
FileOutput fileOut(fileHandle, lockFilePath); //pass handle ownership
//write housekeeping info: user, process info, lock GUID
- ByteArray binStream = [&]
- {
- MemStreamOut streamOut;
- LockInformation(FromCurrentProcess()).toStream(streamOut);
- return streamOut.ref();
- }();
-
- if (!binStream.empty())
- fileOut.write(&*binStream.begin(), binStream.size()); //throw FileError
+ MemStreamOut streamOut;
+ serialize(getLockInfoFromCurrentProcess(), streamOut);
+ unbufferedSave(streamOut.ref(), fileOut, nullptr); //throw FileError
+ fileOut.close(); //
return true;
}
}
diff --git a/FreeFileSync/Source/lib/error_log.h b/FreeFileSync/Source/lib/error_log.h
index 0102bebd..9d51ab0d 100644
--- a/FreeFileSync/Source/lib/error_log.h
+++ b/FreeFileSync/Source/lib/error_log.h
@@ -8,7 +8,7 @@
#define ERROR_LOG_H_89734181783491324134
#include <cassert>
-#include <zen/serialize.h>
+#include <zen/file_io.h>
#include <zen/time.h>
#include "ffs_paths.h"
@@ -34,7 +34,7 @@ void logFatalError(const std::string& msg) //throw()
const std::string logEntry = "[" + formatTime<std::string>(FORMAT_DATE) + " "+ formatTime<std::string>(FORMAT_TIME) + "] " + msg;
try
{
- saveBinStream(getConfigDir() + Zstr("LastError.log"), logEntry, nullptr); //throw FileError
+ saveBinContainer(getConfigDir() + Zstr("LastError.log"), logEntry, nullptr); //throw FileError
}
catch (const FileError&) {}
}
diff --git a/FreeFileSync/Source/lib/ffs_paths.cpp b/FreeFileSync/Source/lib/ffs_paths.cpp
index a8b27d4b..31694214 100644
--- a/FreeFileSync/Source/lib/ffs_paths.cpp
+++ b/FreeFileSync/Source/lib/ffs_paths.cpp
@@ -25,7 +25,7 @@ namespace
{
#if defined ZEN_WIN || defined ZEN_LINUX
inline
-Zstring getExecutableDir() //directory containing executable WITH path separator at end
+Zstring getExecutablePathPf() //directory containing executable WITH path separator at end
{
return appendSeparator(beforeLast(utfCvrtTo<Zstring>(wxStandardPaths::Get().GetExecutablePath()), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE));
}
@@ -33,23 +33,25 @@ Zstring getExecutableDir() //directory containing executable WITH path separator
#ifdef ZEN_WIN
inline
-Zstring getInstallDir() //root install directory WITH path separator at end
+Zstring getInstallFolderPathPf() //root install directory WITH path separator at end
{
- return appendSeparator(beforeLast(beforeLast(getExecutableDir(), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE));
+ return appendSeparator(beforeLast(beforeLast(getExecutablePathPf(), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE), FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE));
}
#endif
+}
-#ifdef ZEN_WIN
-inline
-bool isPortableVersion()
+bool zen::isPortableVersion()
{
- return !(fileExists(getInstallDir() + L"uninstall.exe") || //created by NSIS
- dirExists (getInstallDir() + L"Uninstall")); //created by Inno Setup
-}
+#ifdef ZEN_WIN
+ return !fileExists(getInstallFolderPathPf() + L"uninstall.exe") && //created by NSIS
+ !dirExists (getInstallFolderPathPf() + L"Uninstall"); //created by Inno Setup
+
#elif defined ZEN_LINUX
-inline
-bool isPortableVersion() { return !endsWith(getExecutableDir(), "/bin/"); } //this check is a bit lame...
+ return !endsWith(getExecutablePathPf(), "/bin/"); //this check is a bit lame...
+
+#elif defined ZEN_MAC
+ return false;
#endif
}
@@ -73,10 +75,10 @@ Zstring zen::getResourceDir()
ZEN_ON_SCOPE_EXIT(wxTheApp->SetAppName(appName));
#ifdef ZEN_WIN
- return getInstallDir();
+ return getInstallFolderPathPf();
#elif defined ZEN_LINUX
if (isPortableVersion())
- return getExecutableDir();
+ return getExecutablePathPf();
else //use OS' standard paths
return appendSeparator(toZ(wxStandardPathsBase::Get().GetResourcesDir()));
#elif defined ZEN_MAC
@@ -94,10 +96,10 @@ Zstring zen::getConfigDir()
#ifdef ZEN_WIN
if (isPortableVersion())
- return getInstallDir();
+ return getInstallFolderPathPf();
#elif defined ZEN_LINUX
if (isPortableVersion())
- return getExecutableDir();
+ return getExecutablePathPf();
#elif defined ZEN_MAC
//portable apps do not seem common on OS - fine with me: http://theocacao.com/document.page/319
#endif
@@ -117,10 +119,10 @@ Zstring zen::getConfigDir()
Zstring zen::getFreeFileSyncLauncherPath()
{
#ifdef ZEN_WIN
- return getInstallDir() + Zstr("FreeFileSync.exe");
+ return getInstallFolderPathPf() + Zstr("FreeFileSync.exe");
#elif defined ZEN_LINUX
- return getExecutableDir() + Zstr("FreeFileSync");
+ return getExecutablePathPf() + Zstr("FreeFileSync");
#elif defined ZEN_MAC
CFURLRef appURL = nullptr;
diff --git a/FreeFileSync/Source/lib/ffs_paths.h b/FreeFileSync/Source/lib/ffs_paths.h
index 65b26f4f..dd0821ac 100644
--- a/FreeFileSync/Source/lib/ffs_paths.h
+++ b/FreeFileSync/Source/lib/ffs_paths.h
@@ -18,6 +18,8 @@ Zstring getResourceDir(); //resource directory WITH path separator at end
Zstring getConfigDir (); //config directory WITH path separator at end
//------------------------------------------------------------------------------
+bool isPortableVersion();
+
Zstring getFreeFileSyncLauncherPath(); //full path to application launcher C:\...\FreeFileSync.exe
bool manualProgramUpdateRequired();
}
diff --git a/FreeFileSync/Source/lib/generate_logfile.h b/FreeFileSync/Source/lib/generate_logfile.h
index a27daf6a..5a8f2df6 100644
--- a/FreeFileSync/Source/lib/generate_logfile.h
+++ b/FreeFileSync/Source/lib/generate_logfile.h
@@ -8,7 +8,7 @@
#define GENERATE_LOGFILE_H_931726432167489732164
#include <zen/error_log.h>
-#include <zen/serialize.h>
+#include <zen/file_io.h>
#include <zen/format_unit.h>
#include "ffs_paths.h"
#include "../fs/abstract.h"
@@ -27,10 +27,10 @@ struct SummaryInfo
int64_t totalTime; //unit: [sec]
};
-void saveLogToFile(const SummaryInfo& summary, //throw FileError
- const ErrorLog& log,
- FileOutput& fileOut,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus);
+void streamToLogFile(const SummaryInfo& summary, //throw FileError
+ const ErrorLog& log,
+ FileOutput& fileOut,
+ const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus);
void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError
const ErrorLog& log,
@@ -117,36 +117,37 @@ std::wstring generateLogHeader(const SummaryInfo& s)
inline
-void saveLogToFile(const SummaryInfo& summary, //throw FileError
- const ErrorLog& log,
- AFS::OutputStream& streamOut,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus)
+void streamToLogFile(const SummaryInfo& summary, //throw FileError
+ const ErrorLog& log,
+ AFS::OutputStream& streamOut,
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
//write log items in blocks instead of creating one big string: memory allocation might fail; think 1 million entries!
- const size_t blockSize = streamOut.optimalBlockSize();
- Utf8String msgBuffer;
+ const size_t blockSize = streamOut.getBlockSize();
+ std::string buffer;
- auto flushToFile = [&]
+ auto flushBlock = [&]
{
- streamOut.write(&*msgBuffer.begin(), msgBuffer.size()); //throw FileError
- if (onUpdateSaveStatus)
- onUpdateSaveStatus(msgBuffer.size());
- msgBuffer.clear();
+ size_t bytesRemaining = buffer.size();
+ while (bytesRemaining >= blockSize)
+ {
+ const size_t bytesWritten = streamOut.tryWrite(&*(buffer.end() - bytesRemaining), blockSize); //throw FileError; may return short! CONTRACT: bytesToWrite > 0
+ bytesRemaining -= bytesWritten;
+ if (notifyProgress) notifyProgress(bytesWritten); //throw X!
+ }
+ buffer.erase(buffer.begin(), buffer.end() - bytesRemaining);
};
- msgBuffer += replaceCpy(utfCvrtTo<Utf8String>(generateLogHeader(summary)), '\n', LINE_BREAK); //don't replace line break any earlier
- msgBuffer += LINE_BREAK;
+ buffer += replaceCpy(utfCvrtTo<std::string>(generateLogHeader(summary)), '\n', LINE_BREAK); //don't replace line break any earlier
+ buffer += LINE_BREAK;
for (const LogEntry& entry : log)
{
- msgBuffer += replaceCpy(utfCvrtTo<Utf8String>(formatMessage<std::wstring>(entry)), '\n', LINE_BREAK);
- msgBuffer += LINE_BREAK; //=> string is not empty!
-
- if (msgBuffer.size() > blockSize)
- flushToFile();
+ buffer += replaceCpy(utfCvrtTo<std::string>(formatMessage<std::wstring>(entry)), '\n', LINE_BREAK);
+ buffer += LINE_BREAK;
+ flushBlock(); //throw FileError
}
- if (!msgBuffer.empty())
- flushToFile();
+ unbufferedSave(buffer, streamOut, notifyProgress); //throw FileError
}
@@ -183,14 +184,11 @@ void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError
//fill up the rest of permitted space by appending old log
if (newStream.size() < maxBytesToWrite)
{
- //std::function<void(std::int64_t bytesDelta)> onUpdateLoadStatus;
- //if (onUpdateSaveStatus)
- // onUpdateLoadStatus = [&](std::int64_t bytesDelta) { onUpdateSaveStatus(0); };
-
Utf8String oldStream;
try
{
- oldStream = loadBinStream<Utf8String>(filepath, onUpdateSaveStatus); //throw FileError
+ oldStream = loadBinContainer<Utf8String>(filepath, onUpdateSaveStatus); //throw FileError
+ //Note: we also report the loaded bytes via onUpdateSaveStatus()!
}
catch (FileError&) {}
@@ -217,7 +215,7 @@ void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError
}
}
- saveBinStream(filepath, newStream, onUpdateSaveStatus); //throw FileError
+ saveBinContainer(filepath, newStream, onUpdateSaveStatus); //throw FileError
}
}
diff --git a/FreeFileSync/Source/lib/help_provider.h b/FreeFileSync/Source/lib/help_provider.h
index 629501ce..adc736c3 100644
--- a/FreeFileSync/Source/lib/help_provider.h
+++ b/FreeFileSync/Source/lib/help_provider.h
@@ -7,6 +7,14 @@
#ifndef HELP_PROVIDER_H_85930427583421563126
#define HELP_PROVIDER_H_85930427583421563126
+#if 1
+namespace zen
+{
+inline void displayHelpEntry(const wxString& topic, wxWindow* parent) { wxLaunchDefaultBrowser(L"http://www.freefilesync.org/manual.php?topic=" + topic); }
+inline void uninitializeHelp() {}
+}
+
+#else
#ifdef ZEN_WIN
#include <zen/zstring.h>
#include <wx/msw/helpchm.h>
@@ -20,9 +28,8 @@
namespace zen
{
-//use '/' as path separator!
void displayHelpEntry(wxWindow* parent);
-void displayHelpEntry(const wxString& section, wxWindow* parent);
+void displayHelpEntry(const wxString& topic, wxWindow* parent);
void uninitializeHelp(); //clean up gracefully during app shutdown: leaving this up to static destruction crashes on Win 8.1!
@@ -106,9 +113,9 @@ public:
inline
-void displayHelpEntry(const wxString& section, wxWindow* parent)
+void displayHelpEntry(const wxString& topic, wxWindow* parent)
{
- impl::FfsHelpController::getInstance().openSection(section, parent);
+ impl::FfsHelpController::getInstance().openSection(L"html/" + topic + L".html", parent);
}
@@ -125,5 +132,6 @@ void uninitializeHelp()
}
}
+#endif
#endif //HELP_PROVIDER_H_85930427583421563126
diff --git a/FreeFileSync/Source/lib/icon_buffer.cpp b/FreeFileSync/Source/lib/icon_buffer.cpp
index 25bc158e..3d3683b8 100644
--- a/FreeFileSync/Source/lib/icon_buffer.cpp
+++ b/FreeFileSync/Source/lib/icon_buffer.cpp
@@ -336,12 +336,12 @@ private:
};
+#ifdef ZEN_WIN
class InitFileIconCacheOnStartup
{
public:
InitFileIconCacheOnStartup()
{
-#ifdef ZEN_WIN
//icon_loader.h/file_icon_win.h prerequisites: 1. initialize COM, 2. initialize system image list
typedef BOOL (WINAPI* FileIconInitFun)(BOOL fRestoreCache);
const SysDllFun<FileIconInitFun> fileIconInit(L"Shell32.dll", reinterpret_cast<LPCSTR>(660)); //MS requires and documents this magic number
@@ -354,9 +354,9 @@ public:
your copy of the system image list to contain the standard icons, you should call FileIconInit(TRUE) at startup."
- Jim Barry, MVP (Windows SDK)
*/
-#endif
}
-} dummy;
+} startupInitIconCache;
+#endif
void WorkerThread::operator()() const //thread entry
diff --git a/FreeFileSync/Source/lib/localization.cpp b/FreeFileSync/Source/lib/localization.cpp
index fa8035da..2f93c7ae 100644
--- a/FreeFileSync/Source/lib/localization.cpp
+++ b/FreeFileSync/Source/lib/localization.cpp
@@ -11,7 +11,7 @@
#include <iterator>
#include <zen/string_tools.h>
#include <zen/file_traverser.h>
-#include <zen/serialize.h>
+#include <zen/file_io.h>
#include <zen/i18n.h>
#include <zen/format_unit.h>
#include <wx/intl.h>
@@ -77,7 +77,7 @@ FFSTranslation::FFSTranslation(const Zstring& lngFilePath, wxLanguage langId) :
std::string inputStream;
try
{
- inputStream = loadBinStream<std::string>(lngFilePath, nullptr); //throw FileError
+ inputStream = loadBinContainer<std::string>(lngFilePath, nullptr); //throw FileError
}
catch (const FileError& e)
{
@@ -174,7 +174,7 @@ std::vector<TranslationInfo> loadTranslations()
{
try
{
- const std::string stream = loadBinStream<std::string>(filepath, nullptr); //throw FileError
+ const std::string stream = loadBinContainer<std::string>(filepath, nullptr); //throw FileError
lngfile::TransHeader lngHeader;
lngfile::parseHeader(stream, lngHeader); //throw ParsingError
@@ -353,6 +353,7 @@ wxLanguage mapLanguageDialect(wxLanguage language)
//case wxLANGUAGE_PORTUGUESE:
//case wxLANGUAGE_PORTUGUESE_BRAZILIAN:
//case wxLANGUAGE_SCOTS_GAELIC:
+ //case wxLANGUAGE_SLOVAK:
//case wxLANGUAGE_SLOVENIAN:
//case wxLANGUAGE_TURKISH:
//case wxLANGUAGE_UKRAINIAN:
diff --git a/FreeFileSync/Source/lib/parallel_scan.cpp b/FreeFileSync/Source/lib/parallel_scan.cpp
index 05ba6671..4cc12619 100644
--- a/FreeFileSync/Source/lib/parallel_scan.cpp
+++ b/FreeFileSync/Source/lib/parallel_scan.cpp
@@ -46,14 +46,14 @@ bool operator<(const DiskInfo& lhs, const DiskInfo& rhs)
}
-DiskInfo retrieveDiskInfo(const Zstring& pathName)
+DiskInfo retrieveDiskInfo(const Zstring& itemPath)
{
std::vector<wchar_t> volName(std::max(pathName.size(), static_cast<size_t>(10000)));
DiskInfo output;
//full pathName need not yet exist!
- if (!::GetVolumePathName(pathName.c_str(), //__in LPCTSTR lpszFileName,
+ if (!::GetVolumePathName(itemPath.c_str(), //__in LPCTSTR lpszFileName,
&volName[0], //__out LPTSTR lpszVolumePathName,
static_cast<DWORD>(volName.size()))) //__in DWORD cchBufferLength
return output;
@@ -73,7 +73,7 @@ DiskInfo retrieveDiskInfo(const Zstring& pathName)
//format into form: "\\.\C:"
Zstring volnameFmt = rootPathName;
if (endsWith(volnameFmt, FILE_NAME_SEPARATOR))
- volnameFmt.resize(volnameFmt.size() - 1);
+ volnameFmt.pop_back();
volnameFmt = L"\\\\.\\" + volnameFmt;
HANDLE hVolume = ::CreateFile(volnameFmt.c_str(),
diff --git a/FreeFileSync/Source/lib/parse_lng.h b/FreeFileSync/Source/lib/parse_lng.h
index 05a769b5..d1c345d5 100644
--- a/FreeFileSync/Source/lib/parse_lng.h
+++ b/FreeFileSync/Source/lib/parse_lng.h
@@ -510,6 +510,10 @@ private:
!endsWith(translation, "...") &&
!endsWith(translation, "\xe2\x80\xa6")) //narrow ellipsis (spanish?)
throw ParsingError(L"Source text ends with an ellipsis \"...\", but translation does not", scn.posRow(), scn.posCol());
+
+ //if source is a one-liner, so should be the translation
+ if (!contains(original, '\n') && contains(translation, '\n'))
+ throw ParsingError(L"Source text is a one-liner, but translation consists of multiple lines", scn.posRow(), scn.posCol());
}
}
@@ -567,13 +571,17 @@ private:
throw ParsingError(zen::replaceCpy<std::wstring>(L"Placeholder %x missing in plural form source", L"%x", zen::utfCvrtTo<std::wstring>(placeholder)), scn.posRow(), scn.posCol());
//secondary placeholder is required for all plural forms
- if (!std::all_of(translation.begin(), translation.end(), [&](const std::string& pform) { return zen::contains(pform, placeholder); }))
+ if (std::any_of(translation.begin(), translation.end(), [&](const std::string& pform) { return !zen::contains(pform, placeholder); }))
throw ParsingError(zen::replaceCpy<std::wstring>(L"Placeholder %x missing in plural form translation", L"%x", zen::utfCvrtTo<std::wstring>(placeholder)), scn.posRow(), scn.posCol());
}
};
-
checkSecondaryPlaceholder("%y");
checkSecondaryPlaceholder("%z");
+
+ //if source is a one-liner, so should be the translation
+ if (!contains(original.first, '\n') && !contains(original.second, '\n') &&
+ std::any_of(translation.begin(), translation.end(), [&](const std::string& pform) { return contains(pform, '\n'); }))
+ throw ParsingError(L"Source text is a one-liner, but at least one plural form translation consists of multiple lines", scn.posRow(), scn.posCol());
}
}
@@ -619,7 +627,7 @@ void formatMultiLineText(std::string& text)
{
assert(!zen::contains(text, "\r\n"));
- if (text.find('\n') != std::string::npos) //multiple lines
+ if (zen::contains(text, '\n')) //multiple lines
{
if (*text.begin() != '\n')
text = '\n' + text;
diff --git a/FreeFileSync/Source/lib/parse_plural.h b/FreeFileSync/Source/lib/parse_plural.h
index e7e1e066..54206cef 100644
--- a/FreeFileSync/Source/lib/parse_plural.h
+++ b/FreeFileSync/Source/lib/parse_plural.h
@@ -48,7 +48,7 @@ public:
int getCount() const { return static_cast<int>(forms.size()); }
bool isSingleNumberForm(int index) const { return 0 <= index && index < static_cast<int>(forms.size()) ? forms[index].count == 1 : false; }
- int getFirstNumber (int index) const { return 0 <= index && index < static_cast<int>(forms.size()) ? forms[index].firstNumber : -1; }
+ int getFirstNumber (int index) const { return 0 <= index && index < static_cast<int>(forms.size()) ? forms[index].firstNumber : -1; }
private:
struct FormInfo
diff --git a/FreeFileSync/Source/lib/process_xml.h b/FreeFileSync/Source/lib/process_xml.h
index aa7146aa..8e72f71c 100644
--- a/FreeFileSync/Source/lib/process_xml.h
+++ b/FreeFileSync/Source/lib/process_xml.h
@@ -235,7 +235,7 @@ struct XmlGlobalSettings
std::vector<ConfigFileItem> lastUsedConfigFiles;
std::vector<ConfigFileItem> cfgFileHistory;
- size_t cfgFileHistMax = 30;
+ size_t cfgFileHistMax = 50;
std::vector<Zstring> folderHistoryLeft;
std::vector<Zstring> folderHistoryRight;
diff --git a/FreeFileSync/Source/lib/resolve_path.cpp b/FreeFileSync/Source/lib/resolve_path.cpp
index 671edf55..371d3ee3 100644
--- a/FreeFileSync/Source/lib/resolve_path.cpp
+++ b/FreeFileSync/Source/lib/resolve_path.cpp
@@ -172,29 +172,24 @@ private:
}
};
- //================================================================================================
- //SHGetKnownFolderPath: API available only with Windows Vista and later:
- typedef HRESULT (STDAPICALLTYPE* SHGetKnownFolderPathFunc)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR* ppszPath);
- const SysDllFun<SHGetKnownFolderPathFunc> shGetKnownFolderPath(L"Shell32.dll", "SHGetKnownFolderPath");
-
+#ifdef ZEN_WIN_VISTA_AND_LATER
auto addFolderId = [&](REFKNOWNFOLDERID rfid, const Zstring& paramName)
{
- if (shGetKnownFolderPath != nullptr) //[!] avoid bogus MSVC "performance warning"
+ PWSTR path = nullptr;
+ if (SUCCEEDED(::SHGetKnownFolderPath(rfid, //_In_ REFKNOWNFOLDERID rfid,
+ KF_FLAG_DONT_VERIFY, //_In_ DWORD dwFlags,
+ nullptr, //_In_opt_ HANDLE hToken,
+ &path))) //_Out_ PWSTR *ppszPath
{
- PWSTR path = nullptr;
- if (SUCCEEDED(shGetKnownFolderPath(rfid, //_In_ REFKNOWNFOLDERID rfid,
- KF_FLAG_DONT_VERIFY, //_In_ DWORD dwFlags,
- nullptr, //_In_opt_ HANDLE hToken,
- &path))) //_Out_ PWSTR *ppszPath
- {
- ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(path));
+ ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(path));
- Zstring dirpath = path;
- if (!dirpath.empty())
- output.emplace(paramName, dirpath);
- }
+ Zstring dirpath = path;
+ if (!dirpath.empty())
+ output.emplace(paramName, dirpath);
}
};
+#endif
+ //================================================================================================
addCsidl(CSIDL_DESKTOPDIRECTORY, L"csidl_Desktop"); // C:\Users\<user>\Desktop
addCsidl(CSIDL_COMMON_DESKTOPDIRECTORY, L"csidl_PublicDesktop"); // C:\Users\All Users\Desktop
@@ -230,11 +225,12 @@ private:
addCsidl(CSIDL_TEMPLATES, L"csidl_Templates"); // C:\Users\<user>\AppData\Roaming\Microsoft\Windows\Templates
addCsidl(CSIDL_COMMON_TEMPLATES, L"csidl_PublicTemplates"); // C:\ProgramData\Microsoft\Windows\Templates
- //Vista and later:
+#ifdef ZEN_WIN_VISTA_AND_LATER
addFolderId(FOLDERID_Downloads, L"csidl_Downloads"); // C:\Users\<user>\Downloads
addFolderId(FOLDERID_PublicDownloads, L"csidl_PublicDownloads"); // C:\Users\Public\Downloads
addFolderId(FOLDERID_QuickLaunch, L"csidl_QuickLaunch"); // C:\Users\<user>\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch
+#endif
/*
CSIDL_APPDATA covered by %AppData%
@@ -364,18 +360,18 @@ Opt<Zstring> getPathByVolumenName(const Zstring& volumeName) //return no value o
for (const wchar_t* it = &buffer[0]; *it != 0; it += strLength(it) + 1) //list terminated by empty c-string
{
- const Zstring path = it;
+ const Zstring pathPf = appendSeparator(it);
- firstMatch.addJob([path, volumeName]() -> Opt<Zstring>
+ firstMatch.addJob([pathPf, volumeName]() -> Opt<Zstring>
{
- UINT type = ::GetDriveType(appendSeparator(path).c_str()); //non-blocking call!
+ UINT type = ::GetDriveType(pathPf.c_str()); //non-blocking call!
if (type == DRIVE_REMOTE || type == DRIVE_CDROM)
return NoValue();
//next call seriously blocks for non-existing network drives!
std::vector<wchar_t> volName(MAX_PATH + 1); //docu says so
- if (::GetVolumeInformation(appendSeparator(path).c_str(), //__in_opt LPCTSTR lpRootPathName,
+ if (::GetVolumeInformation(pathPf.c_str(), //__in_opt LPCTSTR lpRootPathName,
&volName[0], //__out LPTSTR lpVolumeNameBuffer,
static_cast<DWORD>(volName.size()), //__in DWORD nVolumeNameSize,
nullptr, //__out_opt LPDWORD lpVolumeSerialNumber,
@@ -384,7 +380,7 @@ Opt<Zstring> getPathByVolumenName(const Zstring& volumeName) //return no value o
nullptr, //__out LPTSTR lpFileSystemNameBuffer,
0)) //__in DWORD nFileSystemNameSize
if (equalFilePath(volumeName, &volName[0]))
- return path;
+ return pathPf;
return NoValue();
});
}
@@ -564,7 +560,7 @@ Zstring zen::getResolvedFilePath(const Zstring& pathPhrase) //noexcept
//remove leading/trailing whitespace before allowing misinterpretation in applyLongPathPrefix()
trim(path, true, false);
while (endsWith(path, Zstr(' '))) //don't remove any whitespace from right, e.g. 0xa0 may be used as part of folder name
- path.resize(path.size() - 1);
+ path.pop_back();
#ifdef ZEN_WIN
path = removeLongPathPrefix(path);
diff --git a/FreeFileSync/Source/lib/versioning.h b/FreeFileSync/Source/lib/versioning.h
index 08426dba..9227c608 100644
--- a/FreeFileSync/Source/lib/versioning.h
+++ b/FreeFileSync/Source/lib/versioning.h
@@ -39,7 +39,7 @@ public:
timeStamp_(formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"), timeStamp)) //e.g. "2012-05-15 131513"
{
if (AbstractFileSystem::isNullPath(versioningFolderPath_))
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
if (timeStamp_.size() != 17) //formatTime() returns empty string on error; unexpected length: e.g. problem in year 10,000!
throw FileError(_("Unable to create time stamp for versioning:") + L" \"" + utfCvrtTo<std::wstring>(timeStamp_) + L"\"");
diff --git a/FreeFileSync/Source/synchronization.cpp b/FreeFileSync/Source/synchronization.cpp
index b5ad2e90..1d1eb1d1 100644
--- a/FreeFileSync/Source/synchronization.cpp
+++ b/FreeFileSync/Source/synchronization.cpp
@@ -1605,7 +1605,7 @@ void SynchronizeFolderPair::synchronizeFolderInt(FolderPair& folder, SyncOperati
//###########################################################################################
//--------------------- data verification -------------------------
-void verifyFiles(const AbstractPath& sourcePath, const AbstractPath& targetPath, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //throw FileError
+void verifyFiles(const AbstractPath& sourcePath, const AbstractPath& targetPath, const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //throw FileError
{
try
{
@@ -1640,9 +1640,9 @@ void verifyFiles(const AbstractPath& sourcePath, const AbstractPath& targetPath,
#endif
} //close file handles!
- if (onUpdateStatus) onUpdateStatus(0);
+ if (notifyProgress) notifyProgress(0);
- if (!filesHaveSameContent(sourcePath, targetPath, onUpdateStatus)) //throw FileError
+ if (!filesHaveSameContent(sourcePath, targetPath, notifyProgress)) //throw FileError
throw FileError(replaceCpy(replaceCpy(_("%x and %y have different content."),
L"%x", L"\n" + fmtPath(AFS::getDisplayPath(sourcePath))),
L"%y", L"\n" + fmtPath(AFS::getDisplayPath(targetPath))));
@@ -1839,7 +1839,7 @@ void zen::synchronize(const TimeComp& timeStamp,
//PERF_START;
if (syncConfig.size() != folderCmp.size())
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
//aggregate basic information
std::vector<SyncStatistics> folderPairStats;
diff --git a/FreeFileSync/Source/ui/batch_config.cpp b/FreeFileSync/Source/ui/batch_config.cpp
index 85d4d7c1..f43c9c06 100644
--- a/FreeFileSync/Source/ui/batch_config.cpp
+++ b/FreeFileSync/Source/ui/batch_config.cpp
@@ -39,7 +39,7 @@ private:
void OnErrorPopup (wxCommandEvent& event) override { localBatchCfg.handleError = ON_ERROR_POPUP; updateGui(); }
void OnErrorIgnore (wxCommandEvent& event) override { localBatchCfg.handleError = ON_ERROR_IGNORE; updateGui(); }
void OnErrorStop (wxCommandEvent& event) override { localBatchCfg.handleError = ON_ERROR_STOP; updateGui(); }
- void OnHelpScheduleBatch(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/schedule-a-batch-job.html", this); }
+ void OnHelpScheduleBatch(wxHyperlinkEvent& event) override { displayHelpEntry(L"schedule-a-batch-job", this); }
void OnToggleGenerateLogfile(wxCommandEvent& event) override { updateGui(); }
void OnToggleLogfilesLimit (wxCommandEvent& event) override { updateGui(); }
diff --git a/FreeFileSync/Source/ui/batch_status_handler.cpp b/FreeFileSync/Source/ui/batch_status_handler.cpp
index 7288256c..435b41a8 100644
--- a/FreeFileSync/Source/ui/batch_status_handler.cpp
+++ b/FreeFileSync/Source/ui/batch_status_handler.cpp
@@ -35,7 +35,7 @@ std::pair<std::unique_ptr<AFS::OutputStream>, AbstractPath> prepareNewLogfile(co
AFS::createFolderRecursively(logFolderPath); //throw FileError
//const std::string colon = "\xcb\xb8"; //="modifier letter raised colon" => regular colon is forbidden in file names on Windows and OS X
- //=> too many issues, most notably cmd.exe is not Unicode-awere: http://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/c559a5fb/
+ //=> too many issues, most notably cmd.exe is not Unicode-awere: http://www.freefilesync.org/forum/viewtopic.php?t=1679
//assemble logfile name
Zstring body = utfCvrtTo<Zstring>(jobName) + Zstr(" ") + formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"), timeStamp);
@@ -188,7 +188,7 @@ BatchStatusHandler::~BatchStatusHandler()
else
try
{
- //use EXEC_TYPE_ASYNC until there is reason not to: https://sourceforge.net/p/freefilesync/discussion/help/thread/828dca52
+ //use EXEC_TYPE_ASYNC until there is reason not to: http://www.freefilesync.org/forum/viewtopic.php?t=31
tryReportingError([&] { shellExecute(expandMacros(finalCommand), EXEC_TYPE_ASYNC); }, //throw FileError
*this); //throw X?
}
@@ -257,7 +257,7 @@ BatchStatusHandler::~BatchStatusHandler()
AFS::OutputStream& logFileStream = *rv.first;
const AbstractPath logFilePath = rv.second;
- saveLogToFile(summary, errorLog, logFileStream, OnUpdateLogfileStatusNoThrow(*this, AFS::getDisplayPath(logFilePath))); //throw FileError
+ streamToLogFile(summary, errorLog, logFileStream, OnUpdateLogfileStatusNoThrow(*this, AFS::getDisplayPath(logFilePath))); //throw FileError
logFileStream.finalize([&] { try { requestUiRefresh(); } catch (...) {} }); //throw FileError
}, *this); //throw X?
}
diff --git a/FreeFileSync/Source/ui/custom_grid.cpp b/FreeFileSync/Source/ui/custom_grid.cpp
index dbc948e5..9e352d58 100644
--- a/FreeFileSync/Source/ui/custom_grid.cpp
+++ b/FreeFileSync/Source/ui/custom_grid.cpp
@@ -1292,6 +1292,11 @@ public:
grid.getMainWin().Connect(wxEVT_CHAR, func, nullptr, this);
grid.getMainWin().Connect(wxEVT_KEY_UP, func, nullptr, this);
grid.getMainWin().Connect(wxEVT_KEY_DOWN, func, nullptr, this);
+
+ grid.getMainWin().Connect(wxEVT_LEFT_DOWN, func, nullptr, this);
+ grid.getMainWin().Connect(wxEVT_LEFT_DCLICK, func, nullptr, this);
+ grid.getMainWin().Connect(wxEVT_RIGHT_DOWN, func, nullptr, this);
+ //grid.getMainWin().Connect(wxEVT_MOUSEWHEEL, func, nullptr, this); -> should be covered by wxEVT_SCROLLWIN_*
};
connectGridAccess(gridL_, wxEventHandler(GridEventManager::onGridAccessL)); //
connectGridAccess(gridC_, wxEventHandler(GridEventManager::onGridAccessC)); //connect *after* onKeyDown() in order to receive callback *before*!!!
diff --git a/FreeFileSync/Source/ui/gui_generated.cpp b/FreeFileSync/Source/ui/gui_generated.cpp
index a220a6d6..ebd9d706 100644
--- a/FreeFileSync/Source/ui/gui_generated.cpp
+++ b/FreeFileSync/Source/ui/gui_generated.cpp
@@ -42,7 +42,6 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_menuFile->AppendSeparator();
- wxMenuItem* m_menuItem4;
m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ) , wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItem4 );
@@ -134,14 +133,14 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_buttonCancel->Enable( false );
m_buttonCancel->Hide();
- bSizerTopButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerTopButtons->Add( m_buttonCancel, 0, wxEXPAND, 5 );
m_buttonCompare = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Compare"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
m_buttonCompare->SetDefault();
m_buttonCompare->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
m_buttonCompare->SetToolTip( _("dummy") );
- bSizerTopButtons->Add( m_buttonCompare, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerTopButtons->Add( m_buttonCompare, 0, wxEXPAND, 5 );
bSizerTopButtons->Add( 4, 0, 0, 0, 5 );
@@ -152,15 +151,15 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW );
m_bpButtonCmpConfig->SetToolTip( _("dummy") );
- bSizer198->Add( m_bpButtonCmpConfig, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer198->Add( m_bpButtonCmpConfig, 1, wxEXPAND, 5 );
m_bpButtonCmpContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 18,-1 ), wxBU_AUTODRAW );
m_bpButtonCmpContext->SetToolTip( _("dummy") );
- bSizer198->Add( m_bpButtonCmpContext, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer198->Add( m_bpButtonCmpContext, 0, wxEXPAND, 5 );
- bSizerTopButtons->Add( bSizer198, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerTopButtons->Add( bSizer198, 0, wxEXPAND, 5 );
bSizerTopButtons->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 );
@@ -172,15 +171,15 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer199 = new wxBoxSizer( wxHORIZONTAL );
m_bpButtonFilter = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 60,-1 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE );
- bSizer199->Add( m_bpButtonFilter, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer199->Add( m_bpButtonFilter, 1, wxEXPAND, 5 );
m_bpButtonFilterContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 18,-1 ), wxBU_AUTODRAW );
m_bpButtonFilterContext->SetToolTip( _("dummy") );
- bSizer199->Add( m_bpButtonFilterContext, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer199->Add( m_bpButtonFilterContext, 0, wxEXPAND, 5 );
- bSizerTopButtons->Add( bSizer199, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerTopButtons->Add( bSizer199, 0, wxEXPAND, 5 );
bSizerTopButtons->Add( 5, 5, 0, 0, 5 );
@@ -194,15 +193,15 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW );
m_bpButtonSyncConfig->SetToolTip( _("dummy") );
- bSizer200->Add( m_bpButtonSyncConfig, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer200->Add( m_bpButtonSyncConfig, 1, wxEXPAND, 5 );
m_bpButtonSyncContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 18,-1 ), wxBU_AUTODRAW );
m_bpButtonSyncContext->SetToolTip( _("dummy") );
- bSizer200->Add( m_bpButtonSyncContext, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer200->Add( m_bpButtonSyncContext, 0, wxEXPAND, 5 );
- bSizerTopButtons->Add( bSizer200, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerTopButtons->Add( bSizer200, 0, wxEXPAND, 5 );
bSizerTopButtons->Add( 4, 0, 0, 0, 5 );
@@ -211,19 +210,19 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_buttonSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
m_buttonSync->SetToolTip( _("dummy") );
- bSizerTopButtons->Add( m_buttonSync, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerTopButtons->Add( m_buttonSync, 0, wxEXPAND, 5 );
bSizerTopButtons->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 );
- bSizer1791->Add( bSizerTopButtons, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizer1791->Add( bSizerTopButtons, 1, wxEXPAND, 5 );
m_panelTopButtons->SetSizer( bSizer1791 );
m_panelTopButtons->Layout();
bSizer1791->Fit( m_panelTopButtons );
- bSizerPanelHolder->Add( m_panelTopButtons, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizerPanelHolder->Add( m_panelTopButtons, 0, wxEXPAND, 5 );
m_panelDirectoryPairs = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL );
wxBoxSizer* bSizer1601;
@@ -278,10 +277,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderLeft->SetToolTip( _("Select SFTP folder") );
- bSizer182->Add( m_bpButtonSelectAltFolderLeft, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer182->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 );
- fgSizer8->Add( bSizer182, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ fgSizer8->Add( bSizer182, 0, wxEXPAND, 5 );
m_panelTopLeft->SetSizer( fgSizer8 );
@@ -299,7 +298,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonSwapSides = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW );
m_bpButtonSwapSides->SetToolTip( _("Swap sides") );
- bSizer1771->Add( m_bpButtonSwapSides, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer1771->Add( m_bpButtonSwapSides, 0, wxEXPAND, 5 );
wxBoxSizer* bSizer160;
bSizer160 = new wxBoxSizer( wxHORIZONTAL );
@@ -323,7 +322,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_panelTopCenter->SetSizer( bSizer1771 );
m_panelTopCenter->Layout();
bSizer1771->Fit( m_panelTopCenter );
- bSizer91->Add( m_panelTopCenter, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer91->Add( m_panelTopCenter, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 );
m_panelTopRight = new wxPanel( m_panelDirectoryPairs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_panelTopRight->SetMinSize( wxSize( 1,-1 ) );
@@ -333,7 +332,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_staticTextResolvedPathR = new wxStaticText( m_panelTopRight, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextResolvedPathR->Wrap( -1 );
- bSizer183->Add( m_staticTextResolvedPathR, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2 );
+ bSizer183->Add( m_staticTextResolvedPathR, 0, wxALL, 2 );
wxBoxSizer* bSizer179;
bSizer179 = new wxBoxSizer( wxHORIZONTAL );
@@ -349,10 +348,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderRight->SetToolTip( _("Select SFTP folder") );
- bSizer179->Add( m_bpButtonSelectAltFolderRight, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer179->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 );
- bSizer183->Add( bSizer179, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer183->Add( bSizer179, 0, wxEXPAND, 5 );
m_panelTopRight->SetSizer( bSizer183 );
@@ -373,13 +372,13 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_scrolledWindowFolderPairs->SetSizer( bSizerAddFolderPairs );
m_scrolledWindowFolderPairs->Layout();
bSizerAddFolderPairs->Fit( m_scrolledWindowFolderPairs );
- bSizer1601->Add( m_scrolledWindowFolderPairs, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer1601->Add( m_scrolledWindowFolderPairs, 1, wxEXPAND, 5 );
m_panelDirectoryPairs->SetSizer( bSizer1601 );
m_panelDirectoryPairs->Layout();
bSizer1601->Fit( m_panelDirectoryPairs );
- bSizerPanelHolder->Add( m_panelDirectoryPairs, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizerPanelHolder->Add( m_panelDirectoryPairs, 0, wxEXPAND, 5 );
m_gridNavi = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
m_gridNavi->SetScrollRate( 5, 5 );
@@ -470,13 +469,13 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 );
- bSizerStatusLeft->Add( bSizer53, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerStatusLeft->Add( bSizer53, 1, wxEXPAND, 5 );
m_staticline9 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
- bSizerStatusLeft->Add( m_staticline9, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP, 2 );
+ bSizerStatusLeft->Add( m_staticline9, 0, wxEXPAND|wxTOP, 2 );
- bSizerFileStatus->Add( bSizerStatusLeft, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerFileStatus->Add( bSizerStatusLeft, 1, wxEXPAND, 5 );
bSizerFileStatus->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -491,7 +490,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizerStatusRight = new wxBoxSizer( wxHORIZONTAL );
m_staticline10 = new wxStaticLine( m_panelStatusBar, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
- bSizerStatusRight->Add( m_staticline10, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP, 2 );
+ bSizerStatusRight->Add( m_staticline10, 0, wxEXPAND|wxTOP, 2 );
wxBoxSizer* bSizer52;
bSizer52 = new wxBoxSizer( wxHORIZONTAL );
@@ -543,13 +542,13 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 );
- bSizerStatusRight->Add( bSizer52, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerStatusRight->Add( bSizer52, 1, wxEXPAND, 5 );
- bSizerFileStatus->Add( bSizerStatusRight, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerFileStatus->Add( bSizerStatusRight, 1, wxEXPAND, 5 );
- bSizer451->Add( bSizerFileStatus, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer451->Add( bSizerFileStatus, 1, wxEXPAND, 5 );
m_staticTextFullStatus = new wxStaticText( m_panelStatusBar, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextFullStatus->Wrap( -1 );
@@ -561,7 +560,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_panelStatusBar->SetSizer( bSizer451 );
m_panelStatusBar->Layout();
bSizer451->Fit( m_panelStatusBar );
- bSizer1711->Add( m_panelStatusBar, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer1711->Add( m_panelStatusBar, 0, wxEXPAND, 5 );
m_panelCenter->SetSizer( bSizer1711 );
@@ -582,7 +581,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_staticText101->Wrap( -1 );
bSizer1713->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_textCtrlSearchTxt = new wxTextCtrl( m_panelSearch, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220,-1 ), 0|wxWANTS_CHARS );
+ m_textCtrlSearchTxt = new wxTextCtrl( m_panelSearch, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 220,-1 ), wxTE_PROCESS_ENTER|wxWANTS_CHARS );
m_textCtrlSearchTxt->SetMaxLength( 0 );
bSizer1713->Add( m_textCtrlSearchTxt, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
@@ -607,7 +606,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonNew = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
m_bpButtonNew->SetToolTip( _("dummy") );
- bSizer17611->Add( m_bpButtonNew, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer17611->Add( m_bpButtonNew, 0, wxEXPAND, 5 );
m_staticText951 = new wxStaticText( m_panelConfig, wxID_ANY, _("New"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText951->Wrap( -1 );
@@ -622,7 +621,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
m_bpButtonOpen->SetToolTip( _("dummy") );
- bSizer1761->Add( m_bpButtonOpen, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer1761->Add( m_bpButtonOpen, 0, wxEXPAND, 5 );
m_staticText95 = new wxStaticText( m_panelConfig, wxID_ANY, _("Open..."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText95->Wrap( -1 );
@@ -637,7 +636,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
m_bpButtonSave->SetToolTip( _("dummy") );
- bSizer175->Add( m_bpButtonSave, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer175->Add( m_bpButtonSave, 0, wxEXPAND, 5 );
m_staticText961 = new wxStaticText( m_panelConfig, wxID_ANY, _("Save"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText961->Wrap( -1 );
@@ -660,10 +659,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_bpButtonSaveAsBatch = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
m_bpButtonSaveAsBatch->SetToolTip( _("dummy") );
- bSizer1772->Add( m_bpButtonSaveAsBatch, 1, wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizer1772->Add( m_bpButtonSaveAsBatch, 1, 0, 5 );
- bSizer174->Add( bSizer1772, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer174->Add( bSizer1772, 0, wxEXPAND, 5 );
m_staticText97 = new wxStaticText( m_panelConfig, wxID_ANY, _("Save as..."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText97->Wrap( -1 );
@@ -678,7 +677,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_listBoxHistory = new wxListBox( m_panelConfig, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_EXTENDED|wxLB_NEEDED_SB );
m_listBoxHistory->SetMinSize( wxSize( -1,40 ) );
- bSizerConfig->Add( m_listBoxHistory, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerConfig->Add( m_listBoxHistory, 1, wxEXPAND, 5 );
m_panelConfig->SetSizer( bSizerConfig );
@@ -783,7 +782,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer173->Add( m_staticTextDeleteLeft, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizerStatistics->Add( bSizer173, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerStatistics->Add( bSizer173, 0, wxEXPAND, 5 );
bSizerStatistics->Add( 5, 5, 0, 0, 5 );
@@ -809,7 +808,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer172->Add( m_staticTextUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- bSizerStatistics->Add( bSizer172, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerStatistics->Add( bSizer172, 0, wxEXPAND, 5 );
bSizerStatistics->Add( 5, 5, 0, 0, 5 );
@@ -835,7 +834,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer1712->Add( m_staticTextCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- bSizerStatistics->Add( bSizer1712, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerStatistics->Add( bSizer1712, 0, wxEXPAND, 5 );
bSizerStatistics->Add( 5, 5, 0, 0, 5 );
@@ -860,7 +859,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizerData->Add( m_staticTextData, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizerStatistics->Add( bSizerData, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerStatistics->Add( bSizerData, 0, wxEXPAND, 5 );
bSizerStatistics->Add( 5, 5, 0, 0, 5 );
@@ -886,7 +885,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer178->Add( m_staticTextCreateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizerStatistics->Add( bSizer178, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerStatistics->Add( bSizer178, 0, wxEXPAND, 5 );
bSizerStatistics->Add( 5, 5, 0, 0, 5 );
@@ -912,7 +911,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer177->Add( m_staticTextUpdateRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizerStatistics->Add( bSizer177, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerStatistics->Add( bSizer177, 0, wxEXPAND, 5 );
bSizerStatistics->Add( 5, 5, 0, 0, 5 );
@@ -938,10 +937,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer176->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizerStatistics->Add( bSizer176, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerStatistics->Add( bSizer176, 0, wxEXPAND, 5 );
- bSizer1801->Add( bSizerStatistics, 0, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
+ bSizer1801->Add( bSizerStatistics, 0, wxALL, 4 );
m_panelStatistics->SetSizer( bSizer1801 );
@@ -953,7 +952,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_panelViewFilter->SetSizer( bSizerViewFilter );
m_panelViewFilter->Layout();
bSizerViewFilter->Fit( m_panelViewFilter );
- bSizerPanelHolder->Add( m_panelViewFilter, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerPanelHolder->Add( m_panelViewFilter, 0, 0, 5 );
this->SetSizer( bSizerPanelHolder );
@@ -1119,7 +1118,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_toggleBtnByTimeSize = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File time and size"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
m_toggleBtnByTimeSize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- fgSizer16->Add( m_toggleBtnByTimeSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ fgSizer16->Add( m_toggleBtnByTimeSize, 0, wxEXPAND, 5 );
m_bitmapByContent = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer16->Add( m_bitmapByContent, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -1127,7 +1126,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_toggleBtnByContent = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
m_toggleBtnByContent->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- fgSizer16->Add( m_toggleBtnByContent, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ fgSizer16->Add( m_toggleBtnByContent, 0, wxEXPAND, 5 );
m_bitmapBySize = new wxStaticBitmap( m_panelComparisonSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer16->Add( m_bitmapBySize, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -1136,7 +1135,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_toggleBtnBySize->SetValue( true );
m_toggleBtnBySize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- fgSizer16->Add( m_toggleBtnBySize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ fgSizer16->Add( m_toggleBtnBySize, 0, wxEXPAND, 5 );
bSizer182->Add( fgSizer16, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -1242,7 +1241,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_panelCompSettingsHolder->SetSizer( bSizer275 );
m_panelCompSettingsHolder->Layout();
bSizer275->Fit( m_panelCompSettingsHolder );
- m_notebook->AddPage( m_panelCompSettingsHolder, _("dummy"), true );
+ m_notebook->AddPage( m_panelCompSettingsHolder, _("dummy"), false );
m_panelFilterSettingsHolder = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_panelFilterSettingsHolder->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
@@ -1289,13 +1288,13 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_textCtrlInclude = new wxTextCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE );
m_textCtrlInclude->SetMinSize( wxSize( 280,-1 ) );
- bSizer1731->Add( m_textCtrlInclude, 1, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP, 5 );
+ bSizer1731->Add( m_textCtrlInclude, 1, wxEXPAND|wxTOP, 5 );
- bSizer1661->Add( bSizer1731, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer1661->Add( bSizer1731, 1, wxEXPAND, 5 );
- bSizer166->Add( bSizer1661, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxLEFT, 5 );
+ bSizer166->Add( bSizer1661, 1, wxEXPAND|wxLEFT, 5 );
m_staticline22 = new wxStaticLine( m_panelFilterSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer166->Add( m_staticline22, 0, wxEXPAND, 5 );
@@ -1329,19 +1328,19 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer1742->Add( bSizer189, 0, wxEXPAND, 5 );
m_textCtrlExclude = new wxTextCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE );
- bSizer1742->Add( m_textCtrlExclude, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxTOP, 5 );
+ bSizer1742->Add( m_textCtrlExclude, 1, wxEXPAND|wxTOP, 5 );
- bSizer1651->Add( bSizer1742, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer1651->Add( bSizer1742, 1, wxEXPAND, 5 );
- bSizer166->Add( bSizer1651, 2, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxLEFT, 5 );
+ bSizer166->Add( bSizer1651, 2, wxEXPAND|wxLEFT, 5 );
- bSizer1591->Add( bSizer166, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer1591->Add( bSizer166, 1, wxEXPAND, 5 );
m_staticline24 = new wxStaticLine( m_panelFilterSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
- bSizer1591->Add( m_staticline24, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer1591->Add( m_staticline24, 0, wxEXPAND, 5 );
wxBoxSizer* bSizer160;
bSizer160 = new wxBoxSizer( wxVERTICAL );
@@ -1360,18 +1359,18 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer165->Add( m_staticText79, 0, wxBOTTOM, 5 );
m_spinCtrlTimespan = new wxSpinCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 );
- bSizer165->Add( m_spinCtrlTimespan, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer165->Add( m_spinCtrlTimespan, 0, wxEXPAND, 5 );
wxArrayString m_choiceUnitTimespanChoices;
m_choiceUnitTimespan = new wxChoice( m_panelFilterSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitTimespanChoices, 0 );
m_choiceUnitTimespan->SetSelection( 0 );
- bSizer165->Add( m_choiceUnitTimespan, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer165->Add( m_choiceUnitTimespan, 0, wxEXPAND, 5 );
bSizer167->Add( bSizer165, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
- bSizer160->Add( bSizer167, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 );
+ bSizer160->Add( bSizer167, 0, wxEXPAND|wxALL, 5 );
m_staticline23 = new wxStaticLine( m_panelFilterSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer160->Add( m_staticline23, 0, wxEXPAND, 5 );
@@ -1397,12 +1396,12 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer162->Add( m_staticText101, 0, wxBOTTOM, 2 );
m_spinCtrlMinSize = new wxSpinCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 );
- bSizer162->Add( m_spinCtrlMinSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer162->Add( m_spinCtrlMinSize, 0, wxEXPAND, 5 );
wxArrayString m_choiceUnitMinSizeChoices;
m_choiceUnitMinSize = new wxChoice( m_panelFilterSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMinSizeChoices, 0 );
m_choiceUnitMinSize->SetSelection( 0 );
- bSizer162->Add( m_choiceUnitMinSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer162->Add( m_choiceUnitMinSize, 0, wxEXPAND, 5 );
bSizer158->Add( bSizer162, 0, wxBOTTOM|wxEXPAND, 5 );
@@ -1415,12 +1414,12 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer163->Add( m_staticText102, 0, wxBOTTOM, 2 );
m_spinCtrlMaxSize = new wxSpinCtrl( m_panelFilterSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 );
- bSizer163->Add( m_spinCtrlMaxSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer163->Add( m_spinCtrlMaxSize, 0, wxEXPAND, 5 );
wxArrayString m_choiceUnitMaxSizeChoices;
m_choiceUnitMaxSize = new wxChoice( m_panelFilterSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitMaxSizeChoices, 0 );
m_choiceUnitMaxSize->SetSelection( 0 );
- bSizer163->Add( m_choiceUnitMaxSize, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer163->Add( m_choiceUnitMaxSize, 0, wxEXPAND, 5 );
bSizer158->Add( bSizer163, 0, wxEXPAND, 5 );
@@ -1429,7 +1428,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer168->Add( bSizer158, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
- bSizer160->Add( bSizer168, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 );
+ bSizer160->Add( bSizer168, 1, wxEXPAND|wxALL, 5 );
bSizer1591->Add( bSizer160, 0, wxEXPAND, 5 );
@@ -1506,22 +1505,22 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_toggleBtnTwoWay = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_toggleBtnTwoWay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnTwoWay, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM, 5 );
+ bSizer236->Add( m_toggleBtnTwoWay, 0, wxEXPAND|wxBOTTOM, 5 );
m_toggleBtnMirror = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_toggleBtnMirror->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnMirror, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM, 5 );
+ bSizer236->Add( m_toggleBtnMirror, 0, wxEXPAND|wxBOTTOM, 5 );
m_toggleBtnUpdate = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_toggleBtnUpdate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnUpdate, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM, 5 );
+ bSizer236->Add( m_toggleBtnUpdate, 0, wxEXPAND|wxBOTTOM, 5 );
m_toggleBtnCustom = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_toggleBtnCustom->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnCustom, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer236->Add( m_toggleBtnCustom, 0, wxEXPAND, 5 );
bSizer235->Add( bSizer236, 0, wxRIGHT|wxLEFT, 5 );
@@ -1530,7 +1529,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_checkBoxDetectMove->SetValue(true);
m_checkBoxDetectMove->SetToolTip( _("- Not supported by all file systems\n- Requires and creates database files\n- Detection not available for first sync") );
- bSizer235->Add( m_checkBoxDetectMove, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 );
+ bSizer235->Add( m_checkBoxDetectMove, 0, wxEXPAND|wxALL, 5 );
bSizer237->Add( bSizer235, 0, wxALL, 5 );
@@ -1557,7 +1556,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticText119 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Category"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText119->Wrap( -1 );
- bSizer173->Add( m_staticText119, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer173->Add( m_staticText119, 0, 0, 5 );
bSizer173->Add( 0, 0, 1, wxEXPAND, 5 );
@@ -1567,7 +1566,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticText120 = new wxStaticText( m_panelSyncSettings, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText120->Wrap( -1 );
- bSizer173->Add( m_staticText120, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer173->Add( m_staticText120, 0, 0, 5 );
bSizer173->Add( 0, 0, 1, wxEXPAND, 5 );
@@ -1715,7 +1714,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_bpButtonSelectAltFolder = new wxBitmapButton( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolder->SetToolTip( _("Select SFTP folder") );
- bSizer156->Add( m_bpButtonSelectAltFolder, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer156->Add( m_bpButtonSelectAltFolder, 0, wxEXPAND, 5 );
bSizer191->Add( bSizer156, 0, wxEXPAND|wxBOTTOM, 5 );
@@ -1757,7 +1756,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer192->Add( m_hyperlink17, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
- bSizer191->Add( bSizer192, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer191->Add( bSizer192, 0, wxEXPAND, 5 );
m_panelVersioning->SetSizer( bSizer191 );
@@ -1815,7 +1814,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizerOnCompletion->Add( m_staticText89, 0, wxBOTTOM, 5 );
m_comboBoxOnCompletion = new OnCompletionBox( m_panelSyncSettings, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
- bSizerOnCompletion->Add( m_comboBoxOnCompletion, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizerOnCompletion->Add( m_comboBoxOnCompletion, 0, wxEXPAND, 5 );
bSizer1732->Add( bSizerOnCompletion, 1, wxALL, 10 );
@@ -1836,7 +1835,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_panelSyncSettingsHolder->SetSizer( bSizer276 );
m_panelSyncSettingsHolder->Layout();
bSizer276->Fit( m_panelSyncSettingsHolder );
- m_notebook->AddPage( m_panelSyncSettingsHolder, _("dummy"), false );
+ m_notebook->AddPage( m_panelSyncSettingsHolder, _("dummy"), true );
bSizer190->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
@@ -1950,13 +1949,13 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderLeft->SetToolTip( _("Select SFTP folder") );
- bSizer134->Add( m_bpButtonSelectAltFolderLeft, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer134->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 );
m_panelLeft->SetSizer( bSizer134 );
m_panelLeft->Layout();
bSizer134->Fit( m_panelLeft );
- bSizer74->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxEXPAND, 5 );
+ bSizer74->Add( m_panelLeft, 0, wxLEFT|wxEXPAND, 5 );
m_panel20 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer95;
@@ -1981,7 +1980,7 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
m_panel20->SetSizer( bSizer95 );
m_panel20->Layout();
bSizer95->Fit( m_panel20 );
- bSizer74->Add( m_panel20, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 );
+ bSizer74->Add( m_panel20, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 );
m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_panelRight->SetMinSize( wxSize( 1,-1 ) );
@@ -2000,13 +1999,13 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltFolderRight->SetToolTip( _("Select SFTP folder") );
- bSizer135->Add( m_bpButtonSelectAltFolderRight, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer135->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 );
m_panelRight->SetSizer( bSizer135 );
m_panelRight->Layout();
bSizer135->Fit( m_panelRight );
- bSizer74->Add( m_panelRight, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, 5 );
+ bSizer74->Add( m_panelRight, 1, wxRIGHT|wxEXPAND, 5 );
this->SetSizer( bSizer74 );
@@ -2062,17 +2061,17 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
bSizer183 = new wxBoxSizer( wxHORIZONTAL );
m_textCtrlServer = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 260,-1 ), 0 );
- bSizer183->Add( m_textCtrlServer, 1, wxALIGN_CENTER_HORIZONTAL|wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer183->Add( m_textCtrlServer, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
m_staticText1233 = new wxStaticText( m_panel41, wxID_ANY, _("Port:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1233->Wrap( -1 );
- bSizer183->Add( m_staticText1233, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 );
+ bSizer183->Add( m_staticText1233, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
m_textCtrlPort = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), 0 );
- bSizer183->Add( m_textCtrlPort, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer183->Add( m_textCtrlPort, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
- fgSizer16->Add( bSizer183, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ fgSizer16->Add( bSizer183, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
fgSizer16->Add( 0, 0, 0, 0, 5 );
@@ -2084,13 +2083,13 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
m_staticText1381->Wrap( -1 );
m_staticText1381->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- bSizer181->Add( m_staticText1381, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxBOTTOM|wxRIGHT, 5 );
+ bSizer181->Add( m_staticText1381, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
m_staticText1382 = new wxStaticText( m_panel41, wxID_ANY, _("www.website.com"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1382->Wrap( -1 );
m_staticText1382->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- bSizer181->Add( m_staticText1382, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer181->Add( m_staticText1382, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_staticText138 = new wxStaticText( m_panel41, wxID_ANY, _("123.123.123"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText138->Wrap( -1 );
@@ -2103,10 +2102,10 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
m_staticText123 = new wxStaticText( m_panel41, wxID_ANY, _("User name:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText123->Wrap( -1 );
- fgSizer16->Add( m_staticText123, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
+ fgSizer16->Add( m_staticText123, 0, wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 );
m_textCtrlUserName = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
- fgSizer16->Add( m_textCtrlUserName, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+ fgSizer16->Add( m_textCtrlUserName, 0, wxALL|wxEXPAND, 5 );
m_staticText1231 = new wxStaticText( m_panel41, wxID_ANY, _("Password:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1231->Wrap( -1 );
@@ -2116,13 +2115,13 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
bSizer182 = new wxBoxSizer( wxVERTICAL );
m_textCtrlPasswordVisible = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
- bSizer182->Add( m_textCtrlPasswordVisible, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer182->Add( m_textCtrlPasswordVisible, 0, wxEXPAND, 5 );
m_textCtrlPasswordHidden = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PASSWORD );
- bSizer182->Add( m_textCtrlPasswordHidden, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer182->Add( m_textCtrlPasswordHidden, 0, wxEXPAND, 5 );
- fgSizer16->Add( bSizer182, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT|wxEXPAND, 5 );
+ fgSizer16->Add( bSizer182, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT|wxLEFT|wxEXPAND, 5 );
fgSizer16->Add( 0, 0, 0, 0, 5 );
@@ -2146,7 +2145,7 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c
bSizer206->Add( m_buttonSelectFolder, 0, wxALIGN_CENTER_VERTICAL, 5 );
- fgSizer16->Add( bSizer206, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 );
+ fgSizer16->Add( bSizer206, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
bSizer185->Add( fgSizer16, 1, wxALL, 5 );
@@ -2329,7 +2328,7 @@ SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wx
bSizer182->Add( 0, 0, 1, wxEXPAND, 5 );
- bSizer162->Add( bSizer182, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 );
+ bSizer162->Add( bSizer182, 0, wxALL|wxEXPAND, 5 );
m_staticline14 = new wxStaticLine( m_panelStatistics, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer162->Add( m_staticline14, 0, wxEXPAND, 5 );
@@ -2424,7 +2423,7 @@ SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wx
fgSizer11->Add( m_staticTextDeleteRight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizer181->Add( fgSizer11, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer181->Add( fgSizer11, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
bSizer162->Add( bSizer181, 0, wxEXPAND|wxALL, 5 );
@@ -2587,7 +2586,7 @@ CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWi
m_staticTextSpeed->Wrap( -1 );
m_staticTextSpeed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizer181->Add( m_staticTextSpeed, 0, wxALIGN_BOTTOM|wxTOP, 5 );
+ bSizer181->Add( m_staticTextSpeed, 0, wxTOP, 5 );
bSizer40->Add( bSizer181, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
@@ -2635,7 +2634,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer42->Add( m_bpButtonMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL, 5 );
- bSizerRoot->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 );
+ bSizerRoot->Add( bSizer42, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 );
bSizerStatusText = new wxBoxSizer( wxVERTICAL );
@@ -2679,7 +2678,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
wxStaticText* m_staticText96;
m_staticText96 = new wxStaticText( m_panelItemsProcessed, wxID_ANY, _("Items processed:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText96->Wrap( -1 );
- bSizer165->Add( m_staticText96, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer165->Add( m_staticText96, 0, wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizer169;
bSizer169 = new wxBoxSizer( wxHORIZONTAL );
@@ -2695,7 +2694,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer169->Add( m_staticTextDataProcessed, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
- bSizer165->Add( bSizer169, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer165->Add( bSizer169, 0, wxRIGHT|wxLEFT, 5 );
bSizer165->Add( 0, 5, 0, 0, 5 );
@@ -2718,7 +2717,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
wxStaticText* m_staticText97;
m_staticText97 = new wxStaticText( m_panelItemsRemaining, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText97->Wrap( -1 );
- bSizer166->Add( m_staticText97, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer166->Add( m_staticText97, 0, wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizer170;
bSizer170 = new wxBoxSizer( wxHORIZONTAL );
@@ -2734,7 +2733,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer170->Add( m_staticTextDataRemaining, 0, wxLEFT|wxALIGN_BOTTOM, 5 );
- bSizer166->Add( bSizer170, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer166->Add( bSizer170, 0, wxRIGHT|wxLEFT, 5 );
bSizer166->Add( 0, 5, 0, 0, 5 );
@@ -2757,13 +2756,13 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
wxStaticText* m_staticText98;
m_staticText98 = new wxStaticText( m_panelTimeRemaining, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText98->Wrap( -1 );
- bSizer167->Add( m_staticText98, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer167->Add( m_staticText98, 0, wxRIGHT|wxLEFT, 5 );
m_staticTextRemTime = new wxStaticText( m_panelTimeRemaining, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextRemTime->Wrap( -1 );
m_staticTextRemTime->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizer167->Add( m_staticTextRemTime, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer167->Add( m_staticTextRemTime, 0, wxRIGHT|wxLEFT, 5 );
bSizer167->Add( 0, 5, 0, 0, 5 );
@@ -2787,13 +2786,13 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
wxStaticText* m_staticText961;
m_staticText961 = new wxStaticText( m_panelTimeElapsed, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText961->Wrap( -1 );
- bSizer168->Add( m_staticText961, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer168->Add( m_staticText961, 0, wxRIGHT|wxLEFT, 5 );
m_staticTextTimeElapsed = new wxStaticText( m_panelTimeElapsed, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextTimeElapsed->Wrap( -1 );
m_staticTextTimeElapsed->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) );
- bSizer168->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer168->Add( m_staticTextTimeElapsed, 0, wxRIGHT|wxLEFT, 5 );
bSizer168->Add( 0, 5, 0, 0, 5 );
@@ -2830,7 +2829,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
m_panelGraphBytes = new zen::Graph2D( m_panelProgress, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), 0 );
m_panelGraphBytes->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- bSizer161->Add( m_panelGraphBytes, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 15 );
+ bSizer161->Add( m_panelGraphBytes, 1, wxEXPAND, 15 );
wxBoxSizer* bSizer174;
bSizer174 = new wxBoxSizer( wxHORIZONTAL );
@@ -2912,7 +2911,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizerStdButtons->Add( m_buttonStop, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
- bSizerRoot->Add( bSizerStdButtons, 0, wxALIGN_RIGHT|wxEXPAND, 5 );
+ bSizerRoot->Add( bSizerStdButtons, 0, wxEXPAND, 5 );
this->SetSizer( bSizerRoot );
@@ -2954,7 +2953,7 @@ LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxP
m_gridMessages = new zen::Grid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
m_gridMessages->SetScrollRate( 5, 5 );
- bSizer153->Add( m_gridMessages, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer153->Add( m_gridMessages, 1, wxEXPAND, 5 );
bSizer179->Add( bSizer153, 1, wxEXPAND, 5 );
@@ -3033,7 +3032,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer169->Add( m_radioBtnStopOnError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizer171->Add( bSizer169, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer171->Add( bSizer169, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizer180->Add( bSizer171, 0, wxALL, 5 );
@@ -3045,7 +3044,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer170 = new wxBoxSizer( wxVERTICAL );
m_checkBoxRunMinimized = new wxCheckBox( m_panel35, wxID_ANY, _("Run minimized"), wxDefaultPosition, wxDefaultSize, 0 );
- bSizer170->Add( m_checkBoxRunMinimized, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 );
+ bSizer170->Add( m_checkBoxRunMinimized, 0, wxEXPAND|wxALL, 5 );
wxBoxSizer* bSizer179;
bSizer179 = new wxBoxSizer( wxHORIZONTAL );
@@ -3092,12 +3091,12 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltLogFolder->SetToolTip( _("Select SFTP folder") );
- bSizer1721->Add( m_bpButtonSelectAltLogFolder, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer1721->Add( m_bpButtonSelectAltLogFolder, 0, wxEXPAND, 5 );
m_checkBoxLogfilesLimit = new wxCheckBox( m_panelLogfile, wxID_ANY, _("Limit:"), wxDefaultPosition, wxDefaultSize, 0 );
m_checkBoxLogfilesLimit->SetToolTip( _("Limit maximum number of log files") );
- bSizer1721->Add( m_checkBoxLogfilesLimit, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+ bSizer1721->Add( m_checkBoxLogfilesLimit, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
m_spinCtrlLogfileLimit = new wxSpinCtrl( m_panelLogfile, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 70,-1 ), wxSP_ARROW_KEYS, 1, 2000000000, 1 );
m_spinCtrlLogfileLimit->SetToolTip( _("Limit maximum number of log files") );
@@ -3108,19 +3107,19 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_panelLogfile->SetSizer( bSizer1721 );
m_panelLogfile->Layout();
bSizer1721->Fit( m_panelLogfile );
- bSizer191->Add( m_panelLogfile, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer191->Add( m_panelLogfile, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
bSizer172->Add( bSizer191, 0, wxEXPAND|wxALL, 5 );
m_hyperlink17 = new wxHyperlinkCtrl( m_panel35, wxID_ANY, _("How can I schedule a batch job?"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- bSizer172->Add( m_hyperlink17, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 );
+ bSizer172->Add( m_hyperlink17, 0, wxALL, 10 );
m_panel35->SetSizer( bSizer172 );
m_panel35->Layout();
bSizer172->Fit( m_panel35 );
- bSizer54->Add( m_panel35, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer54->Add( m_panel35, 1, wxEXPAND, 5 );
m_staticline13 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer54->Add( m_staticline13, 0, wxEXPAND, 5 );
@@ -3199,13 +3198,13 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 );
m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 500,200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
- bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 );
m_panel31->SetSizer( bSizer185 );
m_panel31->Layout();
bSizer185->Fit( m_panel31 );
- bSizer24->Add( m_panel31, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizer24->Add( m_panel31, 1, wxEXPAND, 5 );
m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 );
@@ -3282,13 +3281,13 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 );
m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 500,200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
- bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 );
m_panel31->SetSizer( bSizer185 );
m_panel31->Layout();
bSizer185->Fit( m_panel31 );
- bSizer24->Add( m_panel31, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizer24->Add( m_panel31, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer182;
bSizer182 = new wxBoxSizer( wxHORIZONTAL );
@@ -3304,7 +3303,7 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_bpButtonSelectAltTargetFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW );
m_bpButtonSelectAltTargetFolder->SetToolTip( _("Select SFTP folder") );
- bSizer182->Add( m_bpButtonSelectAltTargetFolder, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
+ bSizer182->Add( m_bpButtonSelectAltTargetFolder, 0, wxEXPAND, 5 );
bSizer24->Add( bSizer182, 0, wxEXPAND|wxALL, 5 );
@@ -3319,7 +3318,7 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_checkBoxKeepRelPath = new wxCheckBox( this, wxID_ANY, _("&Keep relative paths"), wxDefaultPosition, wxDefaultSize, 0 );
m_checkBoxKeepRelPath->SetValue(true);
- bSizer189->Add( m_checkBoxKeepRelPath, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
+ bSizer189->Add( m_checkBoxKeepRelPath, 0, wxALL|wxEXPAND, 5 );
m_checkBoxOverwriteIfExists = new wxCheckBox( this, wxID_ANY, _("&Overwrite existing files"), wxDefaultPosition, wxDefaultSize, 0 );
m_checkBoxOverwriteIfExists->SetValue(true);
@@ -3459,7 +3458,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
m_staticText95 = new wxStaticText( m_panel39, wxID_ANY, _("Automatic retry on error:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText95->Wrap( -1 );
- bSizer188->Add( m_staticText95, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
+ bSizer188->Add( m_staticText95, 0, wxBOTTOM, 5 );
wxFlexGridSizer* fgSizer6;
fgSizer6 = new wxFlexGridSizer( 0, 2, 5, 5 );
@@ -3497,7 +3496,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
m_staticText85 = new wxStaticText( m_panel39, wxID_ANY, _("Customize context menu:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText85->Wrap( -1 );
- bSizer181->Add( m_staticText85, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
+ bSizer181->Add( m_staticText85, 0, wxBOTTOM, 5 );
m_gridCustomCommand = new wxGrid( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
@@ -3527,7 +3526,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
// Cell Defaults
m_gridCustomCommand->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
- bSizer181->Add( m_gridCustomCommand, 1, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer181->Add( m_gridCustomCommand, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer193;
bSizer193 = new wxBoxSizer( wxHORIZONTAL );
@@ -3571,7 +3570,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
m_panel39->SetSizer( bSizer166 );
m_panel39->Layout();
bSizer166->Fit( m_panel39 );
- bSizer95->Add( m_panel39, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer95->Add( m_panel39, 1, wxEXPAND, 5 );
m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer95->Add( m_staticline36, 0, wxEXPAND, 5 );
@@ -3667,7 +3666,7 @@ SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWind
m_panel35->SetSizer( bSizer98 );
m_panel35->Layout();
bSizer98->Fit( m_panel35 );
- bSizer96->Add( m_panel35, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizer96->Add( m_panel35, 0, wxEXPAND, 5 );
m_staticline21 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer96->Add( m_staticline21, 0, wxEXPAND, 5 );
@@ -3720,7 +3719,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer162 = new wxBoxSizer( wxVERTICAL );
m_bitmapLogo = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
- bSizer162->Add( m_bitmapLogo, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer162->Add( m_bitmapLogo, 0, 0, 5 );
m_staticline341 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer162->Add( m_staticline341, 0, wxEXPAND, 5 );
@@ -3863,7 +3862,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_panelDonate->SetSizer( bSizer183 );
m_panelDonate->Layout();
bSizer183->Fit( m_panelDonate );
- bSizer181->Add( m_panelDonate, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 );
+ bSizer181->Add( m_panelDonate, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizer186;
bSizer186 = new wxBoxSizer( wxVERTICAL );
@@ -3909,7 +3908,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer166->Add( 0, 0, 1, wxEXPAND, 5 );
- bSizer186->Add( bSizer166, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer186->Add( bSizer166, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizer181->Add( bSizer186, 0, wxALL|wxEXPAND, 5 );
@@ -3972,7 +3971,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_scrolledWindowTranslators->SetSizer( fgSizerTranslators );
m_scrolledWindowTranslators->Layout();
fgSizerTranslators->Fit( m_scrolledWindowTranslators );
- bSizer177->Add( m_scrolledWindowTranslators, 1, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxEXPAND, 5 );
+ bSizer177->Add( m_scrolledWindowTranslators, 1, wxLEFT|wxEXPAND, 5 );
bSizer174->Add( bSizer177, 0, wxEXPAND|wxTOP|wxLEFT, 5 );
@@ -3984,7 +3983,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_panel41->SetSizer( bSizer162 );
m_panel41->Layout();
bSizer162->Fit( m_panel41 );
- bSizer31->Add( m_panel41, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer31->Add( m_panel41, 0, wxEXPAND, 5 );
m_staticline36 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizer31->Add( m_staticline36, 0, wxEXPAND, 5 );
@@ -3993,7 +3992,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
m_buttonClose->SetDefault();
- bSizerStdButtons->Add( m_buttonClose, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerStdButtons->Add( m_buttonClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bSizer31->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
diff --git a/FreeFileSync/Source/ui/gui_generated.h b/FreeFileSync/Source/ui/gui_generated.h
index bb479d22..105a989f 100644
--- a/FreeFileSync/Source/ui/gui_generated.h
+++ b/FreeFileSync/Source/ui/gui_generated.h
@@ -74,6 +74,7 @@ protected:
wxMenuItem* m_menuItemSave;
wxMenuItem* m_menuItemSaveAs;
wxMenuItem* m_menuItemSaveAsBatch;
+ wxMenuItem* m_menuItem4;
wxMenu* m_menu4;
wxMenuItem* m_menuItemCompare;
wxMenuItem* m_menuItemCompSettings;
diff --git a/FreeFileSync/Source/ui/main_dlg.cpp b/FreeFileSync/Source/ui/main_dlg.cpp
index 3a8ed8ad..8e1713e2 100644
--- a/FreeFileSync/Source/ui/main_dlg.cpp
+++ b/FreeFileSync/Source/ui/main_dlg.cpp
@@ -7,7 +7,7 @@
#include "main_dlg.h"
#include <zen/format_unit.h>
#include <zen/file_access.h>
-#include <zen/serialize.h>
+#include <zen/file_io.h>
#include <zen/thread.h>
#include <zen/shell_execute.h>
#include <wx/clipbrd.h>
@@ -291,45 +291,6 @@ private:
namespace
{
-//workaround for wxWidgets bug failing to update menu item bitmaps (affects Windows- and Linux-build)
-void setMenuItemImage(wxMenuItem*& menuItem, const wxBitmap& bmp)
-{
- assert(menuItem->GetKind() == wxITEM_NORMAL);
-
- //support polling
- if (isEqual(bmp, menuItem->GetBitmap()))
- return;
-
- if (wxMenu* menu = menuItem->GetMenu())
- {
- int pos = menu->GetMenuItems().IndexOf(menuItem);
- if (pos != wxNOT_FOUND)
- {
- /*
- menu->Remove(menuItem); ->this simple sequence crashes on Kubuntu x64, wxWidgets 2.9.2
- menu->Insert(pos, menuItem);
- */
- const bool enabled = menuItem->IsEnabled();
- wxMenuItem* newItem = new wxMenuItem(menu, menuItem->GetId(), menuItem->GetItemLabel());
-
- newItem->SetBitmap(bmp);
-#ifdef __WXMSW__ //not availabe on wxGTK or wxOSX
- //for some inconceivable reason wxWidgets is not consistent with itself and renders disabled icons
- //just greyscale instead of brightened like bitmap buttons; much better:
- newItem->SetDisabledBitmap(bmp.ConvertToDisabled());
-#endif
- bool isDestroyed = menu->Destroy(menuItem); //actual workaround
- assert(isDestroyed);
- (void)isDestroyed;
- menuItem = menu->Insert(pos, newItem); //don't forget to update input item pointer!
-
- if (!enabled)
- menuItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason
- }
- }
-}
-
-
const int TOP_BUTTON_OPTIMAL_WIDTH = 180;
@@ -512,9 +473,9 @@ MainDialog::MainDialog(const Zstring& globalConfigFile,
m_bpButtonCmpConfig ->SetBitmapLabel(getResourceImage(L"cfg_compare"));
m_bpButtonSyncConfig->SetBitmapLabel(getResourceImage(L"cfg_sync"));
- m_bpButtonCmpContext ->SetBitmapLabel(getResourceImage(L"button_arrow_right"));
- m_bpButtonFilterContext->SetBitmapLabel(getResourceImage(L"button_arrow_right"));
- m_bpButtonSyncContext ->SetBitmapLabel(getResourceImage(L"button_arrow_right"));
+ m_bpButtonCmpContext ->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"button_arrow_right")));
+ m_bpButtonFilterContext->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"button_arrow_right")));
+ m_bpButtonSyncContext ->SetBitmapLabel(mirrorIfRtl(getResourceImage(L"button_arrow_right")));
m_bpButtonNew ->SetBitmapLabel(getResourceImage(L"new"));
m_bpButtonOpen ->SetBitmapLabel(getResourceImage(L"load"));
@@ -581,16 +542,19 @@ MainDialog::MainDialog(const Zstring& globalConfigFile,
auiMgr.Update();
- //give panel captions bold typeface
if (wxAuiDockArt* artProvider = auiMgr.GetArtProvider())
{
wxFont font = artProvider->GetFont(wxAUI_DOCKART_CAPTION_FONT);
font.SetWeight(wxFONTWEIGHT_BOLD);
font.SetPointSize(wxNORMAL_FONT->GetPointSize()); //= larger than the wxAuiDockArt default; looks better on OS X
artProvider->SetFont(wxAUI_DOCKART_CAPTION_FONT, font);
+ artProvider->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, font.GetPixelSize().GetHeight() + 2 + 2);
- //accessibility: fix wxAUI drawing black text on black background on high-contrast color schemes:
- artProvider->SetColor(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
+ //- fix wxWidgets 3.1.0 insane color scheme
+ artProvider->SetColor(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, wxColor(220, 220, 220)); //light grey
+ artProvider->SetColor(wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR, wxColor(220, 220, 220)); //
+ artProvider->SetColor(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR, *wxBLACK); //accessibility: always set both foreground AND background colors!
+ //wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) -> better than wxBLACK, but which background to use?
}
auiMgr.GetPane(m_gridNavi).MinSize(-1, -1); //we successfully tricked wxAuiManager into setting an initial Window size :> incomplete API anyone??
@@ -662,23 +626,21 @@ MainDialog::MainDialog(const Zstring& globalConfigFile,
m_bitmapSmallFileRight ->SetBitmap(bmpFile);
}
- //menu icons: workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build)
- setMenuItemImage(m_menuItemNew, getResourceImage(L"new_small"));
-
- setMenuItemImage(m_menuItemLoad, getResourceImage(L"load_small"));
- setMenuItemImage(m_menuItemSave, getResourceImage(L"save_small"));
+ m_menuItemNew ->SetBitmap(getResourceImage(L"new_small"));
+ m_menuItemLoad ->SetBitmap(getResourceImage(L"load_small"));
+ m_menuItemSave ->SetBitmap(getResourceImage(L"save_small"));
+ m_menuItemSaveAsBatch->SetBitmap(getResourceImage(L"batch_small"));
- setMenuItemImage(m_menuItemCompare, getResourceImage(L"compare_small"));
- setMenuItemImage(m_menuItemCompSettings, getResourceImage(L"cfg_compare_small"));
- setMenuItemImage(m_menuItemFilter, getResourceImage(L"filter_small"));
- setMenuItemImage(m_menuItemSyncSettings, getResourceImage(L"cfg_sync_small"));
- setMenuItemImage(m_menuItemSynchronize, getResourceImage(L"sync_small"));
+ m_menuItemCompare ->SetBitmap(getResourceImage(L"compare_small"));
+ m_menuItemCompSettings->SetBitmap(getResourceImage(L"cfg_compare_small"));
+ m_menuItemFilter ->SetBitmap(getResourceImage(L"filter_small"));
+ m_menuItemSyncSettings->SetBitmap(getResourceImage(L"cfg_sync_small"));
+ m_menuItemSynchronize ->SetBitmap(getResourceImage(L"sync_small"));
- setMenuItemImage(m_menuItemOptions, getResourceImage(L"settings_small"));
- setMenuItemImage(m_menuItemSaveAsBatch, getResourceImage(L"batch_small"));
+ m_menuItemOptions ->SetBitmap(getResourceImage(L"settings_small"));
- setMenuItemImage(m_menuItemHelp, getResourceImage(L"help_small"));
- setMenuItemImage(m_menuItemAbout, getResourceImage(L"about_small"));
+ m_menuItemHelp ->SetBitmap(getResourceImage(L"help_small"));
+ m_menuItemAbout->SetBitmap(getResourceImage(L"about_small"));
if (!manualProgramUpdateRequired())
{
@@ -1586,15 +1548,14 @@ void MainDialog::disableAllElements(bool enableAbort)
//disables all elements (except abort button) that might receive user input during long-running processes:
//when changing consider: comparison, synchronization, manual deletion
- EnableCloseButton(false); //not allowed for synchronization! progress indicator is top window! -> not honored on OS X!
+ EnableCloseButton(false); //not allowed for synchronization! progress indicator is top window!
//OS X: wxWidgets portability promise is again a mess: http://wxwidgets.10942.n7.nabble.com/Disable-panel-and-appropriate-children-windows-linux-macos-td35357.html
localKeyEventsEnabled = false;
- m_menubar1->EnableTop(0, false);
- m_menubar1->EnableTop(1, false);
- m_menubar1->EnableTop(2, false);
+ for (size_t pos = 0; pos < m_menubar1->GetMenuCount(); ++pos)
+ m_menubar1->EnableTop(pos, false);
m_bpButtonCmpConfig ->Disable();
m_bpButtonFilter ->Disable();
m_bpButtonSyncConfig ->Disable();
@@ -1636,9 +1597,8 @@ void MainDialog::enableAllElements()
localKeyEventsEnabled = true;
- m_menubar1->EnableTop(0, true);
- m_menubar1->EnableTop(1, true);
- m_menubar1->EnableTop(2, true);
+ for (size_t pos = 0; pos < m_menubar1->GetMenuCount(); ++pos)
+ m_menubar1->EnableTop(pos, true);
m_bpButtonCmpConfig ->Enable();
m_bpButtonFilter ->Enable();
m_bpButtonSyncConfig ->Enable();
@@ -3893,7 +3853,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
//START SYNCHRONIZATION
const std::vector<zen::FolderPairSyncCfg> syncProcessCfg = zen::extractSyncCfg(guiCfg.mainCfg);
if (syncProcessCfg.size() != folderCmp.size())
- throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
//should never happen: sync button is deactivated if they are not in sync
synchronize(localTime(),
@@ -4674,9 +4634,9 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
const char CSV_SEP = haveCommaAsDecimalSep ? ';' : ',';
- auto fmtValue = [&](const wxString& val) -> Utf8String
+ auto fmtValue = [&](const wxString& val) -> std::string
{
- Utf8String&& tmp = utfCvrtTo<Utf8String>(val);
+ std::string&& tmp = utfCvrtTo<std::string>(val);
if (contains(tmp, CSV_SEP))
return '\"' + tmp + '\"';
@@ -4684,18 +4644,18 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
return tmp;
};
- Utf8String header; //perf: wxString doesn't model exponential growth and so is out, std::string doesn't give performance guarantee!
+ std::string header; //perf: wxString doesn't model exponential growth and so is out, std::string doesn't give performance guarantee!
header += BYTE_ORDER_MARK_UTF8;
//base folders
- header += fmtValue(_("Folder Pairs")) + '\n' ;
+ header += fmtValue(_("Folder Pairs")) + LINE_BREAK;
std::for_each(begin(folderCmp), end(folderCmp),
[&](BaseFolderPair& baseFolder)
{
- header += utfCvrtTo<Utf8String>(AFS::getDisplayPath(baseFolder.getAbstractPath<LEFT_SIDE >())) + CSV_SEP;
- header += utfCvrtTo<Utf8String>(AFS::getDisplayPath(baseFolder.getAbstractPath<RIGHT_SIDE>())) + '\n';
+ header += utfCvrtTo<std::string>(AFS::getDisplayPath(baseFolder.getAbstractPath<LEFT_SIDE >())) + CSV_SEP;
+ header += utfCvrtTo<std::string>(AFS::getDisplayPath(baseFolder.getAbstractPath<RIGHT_SIDE>())) + LINE_BREAK;
});
- header += '\n';
+ header += LINE_BREAK;
//write header
auto provLeft = m_gridMainL->getDataProvider();
@@ -4732,16 +4692,27 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
});
header += fmtValue(provRight->getColumnLabel(colAttrRight.back().type_));
}
- header += '\n';
+ header += LINE_BREAK;
try
{
//write file
- FileOutput fileOut(filepath, zen::FileOutput::ACC_OVERWRITE); //throw FileError
+ FileOutput fileOut(filepath, FileOutput::ACC_OVERWRITE); //throw FileError
+ const size_t blockSize = fileOut.getBlockSize();
+ std::string buffer;
- replace(header, '\n', LINE_BREAK);
- fileOut.write(&*header.begin(), header.size()); //throw FileError
+ auto flushBlock = [&]
+ {
+ size_t bytesRemaining = buffer.size();
+ while (bytesRemaining >= blockSize)
+ {
+ const size_t bytesWritten = fileOut.tryWrite(&*(buffer.end() - bytesRemaining), blockSize); //throw FileError; may return short! CONTRACT: bytesToWrite > 0
+ bytesRemaining -= bytesWritten;
+ }
+ buffer.erase(buffer.begin(), buffer.end() - bytesRemaining);
+ };
+ buffer += header;
//main grid: write rows one after the other instead of creating one big string: memory allocation might fail; think 1 million rows!
/*
performance test case "export 600.000 rows" to CSV:
@@ -4751,30 +4722,28 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event)
const size_t rowCount = m_gridMainL->getRowCount();
for (size_t row = 0; row < rowCount; ++row)
{
- Utf8String tmp;
-
for (const Grid::ColumnAttribute& ca : colAttrLeft)
{
- tmp += fmtValue(provLeft->getValue(row, ca.type_));
- tmp += CSV_SEP;
+ buffer += fmtValue(provLeft->getValue(row, ca.type_));
+ buffer += CSV_SEP;
}
for (const Grid::ColumnAttribute& ca : colAttrCenter)
{
- tmp += fmtValue(provCenter->getValue(row, ca.type_));
- tmp += CSV_SEP;
+ buffer += fmtValue(provCenter->getValue(row, ca.type_));
+ buffer += CSV_SEP;
}
for (const Grid::ColumnAttribute& ca : colAttrRight)
{
- tmp += fmtValue(provRight->getValue(row, ca.type_));
- tmp += CSV_SEP;
+ buffer += fmtValue(provRight->getValue(row, ca.type_));
+ buffer += CSV_SEP;
}
- tmp += '\n';
-
- replace(tmp, '\n', LINE_BREAK);
- fileOut.write(&*tmp.begin(), tmp.size()); //throw FileError
+ buffer += LINE_BREAK;
+ flushBlock(); //throw FileError
}
+ unbufferedSave(buffer, fileOut, nullptr); //throw FileError
+ fileOut.close(); //throw FileError
flashStatusInformation(_("File list exported"));
}
@@ -4862,7 +4831,7 @@ void MainDialog::OnMenuAbout(wxCommandEvent& event)
void MainDialog::OnShowHelp(wxCommandEvent& event)
{
- zen::displayHelpEntry(this);
+ zen::displayHelpEntry(L"freefilesync", this);
}
//#########################################################################################################
diff --git a/FreeFileSync/Source/ui/progress_indicator.cpp b/FreeFileSync/Source/ui/progress_indicator.cpp
index 8961c0a4..bfa7b506 100644
--- a/FreeFileSync/Source/ui/progress_indicator.cpp
+++ b/FreeFileSync/Source/ui/progress_indicator.cpp
@@ -57,7 +57,7 @@ inline wxColor getColorGridLine() { return { 192, 192, 192 }; } //light grey
//don't use wxStopWatch for long-running measurements: internally it uses ::QueryPerformanceCounter() which can overflow after only a few days:
-//https://sourceforge.net/p/freefilesync/discussion/help/thread/5d62339e
+//http://www.freefilesync.org/forum/viewtopic.php?t=1426
class StopWatch
{
@@ -2086,7 +2086,6 @@ void SyncProgressDialogImpl<TopLevelDialog>::minimizeToTray()
ProcessSerialNumber psn = { 0, kCurrentProcess };
::TransformProcessType(&psn, kProcessTransformToUIElementApplication);
wxTheApp->Yield(true /*onlyIfNeeded -> avoid recursive yield*/); //required to complete TransformProcessType: else a subsequent modal dialog will be erroneously hidden!
- //-> Yield not needed here since we continue the event loop afterwards!
#endif
}
}
diff --git a/FreeFileSync/Source/ui/small_dlgs.cpp b/FreeFileSync/Source/ui/small_dlgs.cpp
index b7c572cd..d7b4cd37 100644
--- a/FreeFileSync/Source/ui/small_dlgs.cpp
+++ b/FreeFileSync/Source/ui/small_dlgs.cpp
@@ -636,7 +636,7 @@ private:
void OnClose (wxCloseEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
void OnAddRow (wxCommandEvent& event) override;
void OnRemoveRow (wxCommandEvent& event) override;
- void OnHelpShowExamples(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/external-applications.html", this); }
+ void OnHelpShowExamples(wxHyperlinkEvent& event) override { displayHelpEntry(L"external-applications", this); }
void onResize(wxSizeEvent& event);
void updateGui();
@@ -942,16 +942,6 @@ SelectTimespanDlg::SelectTimespanDlg(wxWindow* parent, std::int64_t& timeFrom, s
m_calendarFrom->SetDate(static_cast<time_t>(timeFromTmp));
m_calendarTo ->SetDate(static_cast<time_t>(timeToTmp ));
-#if wxCHECK_VERSION(2, 9, 5)
- //doesn't seem to be a problem here:
-#else
- //wxDatePickerCtrl::BestSize() does not respect year field and trims it, both wxMSW/wxGTK - why isn't there anybody testing this wxWidgets stuff???
- wxSize minSz = m_calendarFrom->GetBestSize();
- minSz.x += 30;
- m_calendarFrom->SetMinSize(minSz);
- m_calendarTo ->SetMinSize(minSz);
-#endif
-
GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize()
//=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!!
diff --git a/FreeFileSync/Source/ui/sync_cfg.cpp b/FreeFileSync/Source/ui/sync_cfg.cpp
index ae55cea7..74789c83 100644
--- a/FreeFileSync/Source/ui/sync_cfg.cpp
+++ b/FreeFileSync/Source/ui/sync_cfg.cpp
@@ -65,8 +65,8 @@ private:
};
//------------- comparison panel ----------------------
- void OnHelpComparisonSettings(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/comparison-settings.html" , this); }
- void OnHelpTimeShift (wxHyperlinkEvent& event) override { displayHelpEntry(L"html/daylight-saving-time.html", this); }
+ void OnHelpComparisonSettings(wxHyperlinkEvent& event) override { displayHelpEntry(L"comparison-settings" , this); }
+ void OnHelpTimeShift (wxHyperlinkEvent& event) override { displayHelpEntry(L"daylight-saving-time", this); }
void OnToggleLocalCompSettings(wxCommandEvent& event) override { updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ }
void OnCompByTimeSize (wxCommandEvent& event) override { localCmpVar = CMP_BY_TIME_SIZE; updateCompGui(); updateSyncGui(); } //
@@ -86,7 +86,7 @@ private:
CompareVariant localCmpVar = CMP_BY_TIME_SIZE;
//------------- filter panel --------------------------
- void OnHelpShowExamples(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/exclude-items.html", this); }
+ void OnHelpShowExamples(wxHyperlinkEvent& event) override { displayHelpEntry(L"exclude-items", this); }
void OnChangeFilterOption(wxCommandEvent& event) override { updateFilterGui(); }
void OnFilterReset (wxCommandEvent& event) override { setFilterConfig(FilterConfig()); }
@@ -128,7 +128,7 @@ private:
void OnToggleDeletionType(wxCommandEvent& event) override { toggleDeletionPolicy(handleDeletion); updateSyncGui(); }
- void OnHelpVersioning(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/versioning.html", this); }
+ void OnHelpVersioning(wxHyperlinkEvent& event) override { displayHelpEntry(L"versioning", this); }
std::shared_ptr<const SyncConfig> getSyncConfig() const;
void setSyncConfig(std::shared_ptr<const SyncConfig> syncCfg);
@@ -267,8 +267,8 @@ ConfigDialog::ConfigDialog(wxWindow* parent,
m_bitmapByTimeSize->SetToolTip(getCompVariantDescription(CMP_BY_TIME_SIZE));
m_bitmapByContent ->SetToolTip(getCompVariantDescription(CMP_BY_CONTENT));
m_bitmapBySize ->SetToolTip(getCompVariantDescription(CMP_BY_SIZE));
- //------------- filter panel --------------------------
+ //------------- filter panel --------------------------
#ifndef __WXGTK__ //wxWidgets breaks portability promise once again
m_textCtrlInclude->SetMaxLength(0); //allow large filter entries!
m_textCtrlExclude->SetMaxLength(0); //
@@ -350,7 +350,8 @@ ConfigDialog::ConfigDialog(wxWindow* parent,
unselectFolderPairConfig();
selectFolderPairConfig(localPairIndexToShow);
- m_listBoxFolderPair->SetFocus(); //more useful and Enter is redirected to m_buttonOkay anyway!
+ //more useful and Enter is redirected to m_buttonOkay anyway:
+ (m_listBoxFolderPair->IsShown() ? static_cast<wxWindow*>(m_listBoxFolderPair) : m_notebook)->SetFocus();
}
@@ -362,19 +363,18 @@ void ConfigDialog::onLocalKeyEvent(wxKeyEvent& event) //process key events witho
{
case WXK_F6:
m_notebook->ChangeSelection(static_cast<size_t>(SyncConfigPanel::COMPARISON));
- m_listBoxFolderPair->SetFocus();
- return; //handled!
+ break; //handled!
case WXK_F7:
m_notebook->ChangeSelection(static_cast<size_t>(SyncConfigPanel::FILTER));
- m_listBoxFolderPair->SetFocus();
- return;
+ break;
case WXK_F8:
m_notebook->ChangeSelection(static_cast<size_t>(SyncConfigPanel::SYNC));
- m_listBoxFolderPair->SetFocus();
+ break;
+ default:
+ event.Skip();
return;
}
-
- event.Skip();
+ (m_listBoxFolderPair->IsShown() ? static_cast<wxWindow*>(m_listBoxFolderPair) : m_notebook)->SetFocus(); //GTK ignores F-keys if focus is on hidden item!
}
diff --git a/FreeFileSync/Source/ui/tree_view.cpp b/FreeFileSync/Source/ui/tree_view.cpp
index 1fbd859d..590a00c9 100644
--- a/FreeFileSync/Source/ui/tree_view.cpp
+++ b/FreeFileSync/Source/ui/tree_view.cpp
@@ -60,7 +60,7 @@ void TreeView::extractVisibleSubtree(HierarchyObject& hierObj, //in
// }
//prefer file-browser semantics over sync preview (=> always show useful numbers, even for SyncDirection::NONE)
- //discussion: https://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/ba6b6a33
+ //discussion: http://www.freefilesync.org/forum/viewtopic.php?t=1595
return std::max(file.getFileSize<LEFT_SIDE>(), file.getFileSize<RIGHT_SIDE>());
};
diff --git a/FreeFileSync/Source/ui/version_check.cpp b/FreeFileSync/Source/ui/version_check.cpp
index b98c68ed..de76a998 100644
--- a/FreeFileSync/Source/ui/version_check.cpp
+++ b/FreeFileSync/Source/ui/version_check.cpp
@@ -14,6 +14,7 @@
#include <zen/file_error.h>
#include <wx+/popup_dlg.h>
#include "version_id.h"
+#include "../lib/ffs_paths.h"
#ifdef ZEN_WIN
#include <zen/win.h> //tame wininet.h include
@@ -106,6 +107,9 @@ std::string geHttpPostParameters() //must be in application/x-www-form-urlencode
std::string params = "ffs_version=" + utfCvrtTo<std::string>(zen::ffsVersion);
+ params += "&ffs_type=";
+ params += isPortableVersion() ? "Portable" : "Local";
+
#ifdef ZEN_WIN
params += "&os_name=Windows";
const auto osvMajor = getOsVersion().major;
@@ -376,7 +380,8 @@ bool internetIsAlive() //noexcept
sc / 100 == 3; //e.g. 301, 302, 303, 307... when in doubt, consider internet alive!
}
-#if 0 //not needed yet: -Wunused-function on OS X
+
+#if 0 //not needed yet: -Wunused-function on clang
inline
std::string sendHttpGet(const std::wstring& url) //throw FileError
{
@@ -384,6 +389,7 @@ std::string sendHttpGet(const std::wstring& url) //throw FileError
}
#endif
+
inline
std::string sendHttpPost(const std::wstring& url, const std::string& postParams) //throw FileError
{
@@ -489,7 +495,7 @@ void zen::checkForUpdateNow(wxWindow* parent, std::wstring& lastOnlineVersion)
lastOnlineVersion = L"Unknown";
switch (showConfirmationDialog(parent, DialogInfoType::ERROR2, PopupDialogCfg().
setTitle(_("Check for Program Updates")).
- setMainInstructions(_("Cannot find current FreeFileSync version number online. Do you want to check manually?")),
+ setMainInstructions(_("Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?")),
_("&Check")))
{
case ConfirmationButton::DO_IT:
@@ -580,7 +586,7 @@ void zen::evalPeriodicUpdateCheck(wxWindow* parent, time_t& lastUpdateCheck, std
lastOnlineVersion = L"Unknown";
switch (showConfirmationDialog(parent, DialogInfoType::ERROR2, PopupDialogCfg().
setTitle(_("Check for Program Updates")).
- setMainInstructions(_("Cannot find current FreeFileSync version number online. Do you want to check manually?")),
+ setMainInstructions(_("Cannot find current FreeFileSync version number online. A newer version is likely available. Check manually now?")),
_("&Check")))
{
case ConfirmationButton::DO_IT:
diff --git a/FreeFileSync/Source/version/version.h b/FreeFileSync/Source/version/version.h
index e3e7c41d..59a94db2 100644
--- a/FreeFileSync/Source/version/version.h
+++ b/FreeFileSync/Source/version/version.h
@@ -3,8 +3,8 @@
namespace zen
{
-const wchar_t ffsVersion[] = L"7.9"; //internal linkage!
-const wchar_t FFS_VERSION_SEPARATOR = L'.';
+ const wchar_t ffsVersion[] = L"8.0"; //internal linkage!
+ const wchar_t FFS_VERSION_SEPARATOR = L'.';
}
#endif
diff --git a/wx+/dc.h b/wx+/dc.h
index 568da47b..278d3458 100644
--- a/wx+/dc.h
+++ b/wx+/dc.h
@@ -98,25 +98,33 @@ public:
BufferedPaintDC(wxWindow& wnd, Opt<wxBitmap>& buffer) : buffer_(buffer), paintDc(&wnd)
{
const wxSize clientSize = wnd.GetClientSize();
- if (!buffer_ || clientSize != wxSize(buffer->GetWidth(), buffer->GetHeight()))
- buffer = wxBitmap(clientSize.GetWidth(), clientSize.GetHeight());
+ if (clientSize.GetWidth() > 0 && clientSize.GetHeight() > 0) //wxBitmap asserts this!! width may be 0; test case "Grid::CornerWin": compare both sides, then change config
+ {
+ if (!buffer_ || clientSize != wxSize(buffer->GetWidth(), buffer->GetHeight()))
+ buffer = wxBitmap(clientSize.GetWidth(), clientSize.GetHeight());
- SelectObject(*buffer);
+ SelectObject(*buffer);
- if (paintDc.IsOk() && paintDc.GetLayoutDirection() == wxLayout_RightToLeft)
- SetLayoutDirection(wxLayout_RightToLeft);
+ if (paintDc.IsOk() && paintDc.GetLayoutDirection() == wxLayout_RightToLeft)
+ SetLayoutDirection(wxLayout_RightToLeft);
+ }
+ else
+ buffer = NoValue();
}
~BufferedPaintDC()
{
- if (GetLayoutDirection() == wxLayout_RightToLeft)
+ if (buffer_)
{
- paintDc.SetLayoutDirection(wxLayout_LeftToRight); //workaround bug in wxDC::Blit()
- SetLayoutDirection(wxLayout_LeftToRight); //
+ if (GetLayoutDirection() == wxLayout_RightToLeft)
+ {
+ paintDc.SetLayoutDirection(wxLayout_LeftToRight); //workaround bug in wxDC::Blit()
+ SetLayoutDirection(wxLayout_LeftToRight); //
+ }
+
+ const wxPoint origin = GetDeviceOrigin();
+ paintDc.Blit(0, 0, buffer_->GetWidth(), buffer_->GetHeight(), this, -origin.x, -origin.y);
}
-
- const wxPoint origin = GetDeviceOrigin();
- paintDc.Blit(0, 0, buffer_->GetWidth(), buffer_->GetHeight(), this, -origin.x, -origin.y);
}
private:
diff --git a/wx+/font_size.h b/wx+/font_size.h
index 2858afb6..03f3c62b 100644
--- a/wx+/font_size.h
+++ b/wx+/font_size.h
@@ -9,11 +9,12 @@
#include <zen/basic_math.h>
#include <wx/window.h>
-#ifdef ZEN_WIN
- #include <zen/dll.h>
+#include <zen/scope_guard.h>
+#ifdef ZEN_WIN_VISTA_AND_LATER
+ #include <zen/win.h>
#include <Uxtheme.h>
#include <vsstyle.h> //TEXT_MAININSTRUCTION
- #include <vssym32.h> //TMT_COLOR
+ #include <vssym32.h> //TMT_TEXTCOLOR
#endif
@@ -49,28 +50,22 @@ void setMainInstructionFont(wxWindow& control)
#ifdef ZEN_WIN //http://msdn.microsoft.com/de-DE/library/windows/desktop/aa974176#fonts
font.SetPointSize(wxNORMAL_FONT->GetPointSize() * 4 / 3); //integer round down
+#ifdef ZEN_WIN_VISTA_AND_LATER
//get main instruction color: don't hard-code, respect accessibility!
- typedef HTHEME (WINAPI* OpenThemeDataFun )(HWND hwnd, LPCWSTR pszClassList);
- typedef HRESULT (WINAPI* CloseThemeDataFun)(HTHEME hTheme);
- typedef HRESULT (WINAPI* GetThemeColorFun )(HTHEME hTheme, int iPartId, int iStateId, int iPropId, COLORREF *pColor);
-
- const SysDllFun<OpenThemeDataFun> openThemeData (L"UxTheme.dll", "OpenThemeData"); //available with Windows XP and later
- const SysDllFun<CloseThemeDataFun> closeThemeData(L"UxTheme.dll", "CloseThemeData");
- const SysDllFun<GetThemeColorFun> getThemeColor (L"UxTheme.dll", "GetThemeColor");
- if (openThemeData && closeThemeData && getThemeColor)
- if (HTHEME hTheme = openThemeData(NULL, //__in HWND hwnd,
- L"TEXTSTYLE")) //__in LPCWSTR pszClassList
- {
- ZEN_ON_SCOPE_EXIT(closeThemeData(hTheme));
-
- COLORREF cr = {};
- if (getThemeColor(hTheme, //_In_ HTHEME hTheme,
- TEXT_MAININSTRUCTION, // _In_ int iPartId,
- 0, // _In_ int iStateId,
- TMT_TEXTCOLOR, // _In_ int iPropId,
- &cr) == S_OK) // _Out_ COLORREF *pColor
- control.SetForegroundColour(wxColor(cr));
- }
+ if (HTHEME hTheme = ::OpenThemeData(NULL, //__in HWND hwnd,
+ L"TEXTSTYLE")) //__in LPCWSTR pszClassList
+ {
+ ZEN_ON_SCOPE_EXIT(::CloseThemeData(hTheme));
+
+ COLORREF cr = {};
+ if (::GetThemeColor(hTheme, //_In_ HTHEME hTheme,
+ TEXT_MAININSTRUCTION, // _In_ int iPartId,
+ 0, // _In_ int iStateId,
+ TMT_TEXTCOLOR, // _In_ int iPropId,
+ &cr) == S_OK) // _Out_ COLORREF *pColor
+ control.SetForegroundColour(wxColor(cr));
+ }
+#endif
#elif defined ZEN_LINUX //https://developer.gnome.org/hig-book/3.2/hig-book.html#alert-text
font.SetPointSize(numeric::round(wxNORMAL_FONT->GetPointSize() * 12.0 / 11));
diff --git a/wx+/graph.cpp b/wx+/graph.cpp
index f39d29f5..95a6955b 100644
--- a/wx+/graph.cpp
+++ b/wx+/graph.cpp
@@ -45,7 +45,7 @@ wxColor getDefaultColor(size_t pos)
switch (pos % 10)
{
case 0:
- return { 0, 69, 134 }; //blue
+ return { 0, 69, 134 }; //blue
case 1:
return { 255, 66, 14 }; //red
case 2:
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index a6c71600..f80c9c73 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -235,7 +235,7 @@ void GridData::drawColumnLabelText(wxDC& dc, const wxRect& rect, const std::wstr
/|\
|
-----------------------------------
- | | | |
+ | | | |
CornerWin RowLabelWin ColLabelWin MainWin
*/
diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp
index 4ba62bb9..7c6de43f 100644
--- a/wx+/image_resources.cpp
+++ b/wx+/image_resources.cpp
@@ -50,18 +50,18 @@ public:
}
void init(const Zstring& filepath);
- void cleanup()
- {
- bitmaps.clear();
- anims.clear();
- }
+ void cleanup()
+ {
+ bitmaps.clear();
+ anims.clear();
+ }
const wxBitmap& getImage (const wxString& name) const;
const wxAnimation& getAnimation(const wxString& name) const;
private:
GlobalResources() {}
- ~GlobalResources() { assert(bitmaps.empty() && anims.empty()); } //don't leave wxWidgets objects for static destruction!
+ ~GlobalResources() { assert(bitmaps.empty() && anims.empty()); } //don't leave wxWidgets objects for static destruction!
GlobalResources (const GlobalResources&) = delete;
GlobalResources& operator=(const GlobalResources&) = delete;
diff --git a/wx+/image_tools.h b/wx+/image_tools.h
index 554e7b49..c8077aa4 100644
--- a/wx+/image_tools.h
+++ b/wx+/image_tools.h
@@ -127,10 +127,9 @@ double getAvgBrightness(const wxImage& img)
inline
void brighten(wxImage& img, int level)
{
- const int pixelCount = img.GetWidth() * img.GetHeight();
- auto pixBegin = img.GetData();
- if (pixBegin)
+ if (auto pixBegin = img.GetData())
{
+ const int pixelCount = img.GetWidth() * img.GetHeight();
auto pixEnd = pixBegin + 3 * pixelCount; //RGB
if (level > 0)
std::for_each(pixBegin, pixEnd, [&](unsigned char& c) { c = static_cast<unsigned char>(std::min(255, c + level)); });
diff --git a/wx+/popup_dlg_generated.cpp b/wx+/popup_dlg_generated.cpp
index c3d50a70..dfddbc8e 100644
--- a/wx+/popup_dlg_generated.cpp
+++ b/wx+/popup_dlg_generated.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun 5 2014)
+// C++ code generated with wxFormBuilder (version Jun 17 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@@ -43,10 +43,10 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, con
m_panel33->SetSizer( bSizer165 );
m_panel33->Layout();
bSizer165->Fit( m_panel33 );
- bSizer24->Add( m_panel33, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer24->Add( m_panel33, 1, wxEXPAND, 5 );
m_staticline6 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
- bSizer24->Add( m_staticline6, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizer24->Add( m_staticline6, 0, wxEXPAND, 5 );
wxBoxSizer* bSizer25;
bSizer25 = new wxBoxSizer( wxVERTICAL );
@@ -69,7 +69,7 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, con
bSizer25->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
- bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ bSizer24->Add( bSizer25, 0, wxEXPAND, 5 );
this->SetSizer( bSizer24 );
diff --git a/wx+/popup_dlg_generated.h b/wx+/popup_dlg_generated.h
index b0397f1e..bef871c7 100644
--- a/wx+/popup_dlg_generated.h
+++ b/wx+/popup_dlg_generated.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun 5 2014)
+// C++ code generated with wxFormBuilder (version Jun 17 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp
index e7748519..702a8e32 100644
--- a/zen/dir_watcher.cpp
+++ b/zen/dir_watcher.cpp
@@ -358,10 +358,10 @@ std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void()
//wait until device removal is confirmed, to prevent locking hDir again by some new watch!
if (pimpl_->volRemoval->requestReceived())
{
- const std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now() + std::chrono::seconds(15);
+ const std::chrono::steady_clock::time_point stopTime = std::chrono::steady_clock::now() + std::chrono::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() && std::chrono::steady_clock::now() < endTime)
+ while (!pimpl_->volRemoval->finished() && std::chrono::steady_clock::now() < stopTime)
{
processGuiMessages(); //DBT_DEVICEREMOVECOMPLETE message is sent here!
std::this_thread::sleep_for(std::chrono::milliseconds(50));
diff --git a/zen/file_access.cpp b/zen/file_access.cpp
index 009d60b2..ea13d381 100644
--- a/zen/file_access.cpp
+++ b/zen/file_access.cpp
@@ -12,7 +12,7 @@
#include "scope_guard.h"
#include "symlink_target.h"
#include "file_id_def.h"
-#include "serialize.h"
+#include "file_io.h"
#ifdef ZEN_WIN
#include <Aclapi.h>
@@ -232,7 +232,7 @@ std::uint64_t zen::getFreeDiskSpace(const Zstring& path) //throw FileError, retu
nullptr, //__out_opt PULARGE_INTEGER lpTotalNumberOfBytes,
nullptr)) //__out_opt PULARGE_INTEGER lpTotalNumberOfFreeBytes
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot determine free disk space for %x."), L"%x", fmtPath(path)), L"GetDiskFreeSpaceEx");
- //succeeds even if path is not yet existing!
+ //succeeds even if path is not yet existing!
//return 0 if info is not available: "The GetDiskFreeSpaceEx function returns zero for lpFreeBytesAvailable for all CD requests"
return get64BitUInt(bytesFree.LowPart, bytesFree.HighPart);
@@ -613,80 +613,191 @@ namespace
{
#ifdef ZEN_WIN
-void setFileTimeRaw(const Zstring& filePath,
- const FILETIME* creationTime, //optional
- const FILETIME& lastWriteTime,
- ProcSymlink procSl) //throw FileError
+void setFileTimeByHandle(HANDLE hFile, //throw FileError
+ const FILETIME* creationTime, //optional
+ const FILETIME& lastWriteTime,
+ const Zstring& filePath) //for error message only
{
+ if (!::SetFileTime(hFile, //__in HANDLE hFile,
+ creationTime, //__in_opt const FILETIME *lpCreationTime,
+ nullptr, //__in_opt const FILETIME *lpLastAccessTime,
+ &lastWriteTime)) //__in_opt const FILETIME *lpLastWriteTime
{
- //extra scope for debug check below
-
- //privilege SE_BACKUP_NAME doesn't seem to be required here for symbolic links
- //note: setting privileges requires admin rights!
+ DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls!
- //opening newly created target file may fail due to some AV-software scanning it: no error, we will wait!
- //http://support.microsoft.com/?scid=kb%3Ben-us%3B316609&x=17&y=20
- //-> enable as soon it turns out it is required!
+ auto toLargeInteger = [](const FILETIME& ft) -> LARGE_INTEGER
+ {
+ LARGE_INTEGER tmp = {};
+ tmp.LowPart = ft.dwLowDateTime;
+ tmp.HighPart = ft.dwHighDateTime;
+ return tmp;
+ };
- /*const int retryInterval = 50;
- const int maxRetries = 2000 / retryInterval;
- for (int i = 0; i < maxRetries; ++i)
+#ifdef ZEN_WIN_VISTA_AND_LATER
+ //function may fail if file is read-only: https://sourceforge.net/tracker/?func=detail&atid=1093080&aid=3514569&group_id=234430
+ if (ec == ERROR_ACCESS_DENIED)
{
- */
+ auto setFileInfo = [&](FILE_BASIC_INFO basicInfo) //throw FileError; no const& since SetFileInformationByHandle() requires non-const parameter!
+ {
+ if (!::SetFileInformationByHandle(hFile, //__in HANDLE hFile,
+ FileBasicInfo, //__in FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
+ &basicInfo, //__in LPVOID lpFileInformation,
+ sizeof(basicInfo))) //__in DWORD dwBufferSize
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file attributes of %x."), L"%x", fmtPath(filePath)), L"SetFileInformationByHandle");
+ };
+ //---------------------------------------------------------------------------
+
+ BY_HANDLE_FILE_INFORMATION fileInfo = {};
+ if (::GetFileInformationByHandle(hFile, &fileInfo))
+ if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ {
+ FILE_BASIC_INFO basicInfo = {}; //undocumented: file times of "0" stand for "don't change"
+ basicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; //[!] the bug in the ticket above requires we set this together with file times!!!
+ basicInfo.LastWriteTime = toLargeInteger(lastWriteTime); //
+ if (creationTime)
+ basicInfo.CreationTime = toLargeInteger(*creationTime);
- /*
- if (hTarget == INVALID_HANDLE_VALUE && ::GetLastError() == ERROR_SHARING_VIOLATION)
- ::Sleep(retryInterval); //wait then retry
- else //success or unknown failure
- break;
+ //set file time + attributes
+ setFileInfo(basicInfo); //throw FileError
+
+ try //... to restore original file attributes
+ {
+ FILE_BASIC_INFO basicInfo2 = {};
+ basicInfo2.FileAttributes = fileInfo.dwFileAttributes;
+ setFileInfo(basicInfo2); //throw FileError
+ }
+ catch (FileError&) {}
+
+ ec = ERROR_SUCCESS;
+ }
}
- */
- //temporarily reset read-only flag if required
- DWORD attribs = INVALID_FILE_ATTRIBUTES;
- ZEN_ON_SCOPE_EXIT(
- if (attribs != INVALID_FILE_ATTRIBUTES)
- ::SetFileAttributes(applyLongPathPrefix(filePath).c_str(), attribs);
- );
-
- auto removeReadonly = [&]() -> bool //throw FileError; may need to remove the readonly-attribute (e.g. on FAT usb drives)
+#endif
+
+ std::wstring errorMsg = replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath));
+
+ //add more meaningful message: FAT accepts only a subset of the NTFS date range
+ if (ec == ERROR_INVALID_PARAMETER && isFatDrive(filePath))
{
- if (attribs == INVALID_FILE_ATTRIBUTES)
+ //let's not fail due to an invalid creation time on FAT: http://www.freefilesync.org/forum/viewtopic.php?t=2278
+ if (creationTime) //retry (single-level recursion at most!)
+ return setFileTimeByHandle(hFile, nullptr, lastWriteTime, filePath); //throw FileError
+
+ //if the ERROR_INVALID_PARAMETER is due to an invalid date, enhance message:
+ const LARGE_INTEGER writeTimeInt = toLargeInteger(lastWriteTime);
+ if (writeTimeInt.QuadPart < 0x01a8e79fe1d58000 || //1980-01-01 https://en.wikipedia.org/wiki/Time_formatting_and_storage_bugs#Year_2100
+ writeTimeInt.QuadPart >= 0x022f716377640000) //2100-01-01
{
- const DWORD tmpAttr = ::GetFileAttributes(applyLongPathPrefix(filePath).c_str());
- if (tmpAttr == INVALID_FILE_ATTRIBUTES)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(filePath)), L"GetFileAttributes");
-
- if (tmpAttr & FILE_ATTRIBUTE_READONLY)
+ errorMsg += L"\nA FAT volume can only store dates from 1980 to 2099:\n" "\twrite time (UTC):";
+ SYSTEMTIME st = {};
+ if (::FileTimeToSystemTime(&lastWriteTime, //__in const FILETIME *lpFileTime,
+ &st)) //__out LPSYSTEMTIME lpSystemTime
{
- if (!::SetFileAttributes(applyLongPathPrefix(filePath).c_str(), FILE_ATTRIBUTE_NORMAL))
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file attributes of %x."), L"%x", fmtPath(filePath)), L"SetFileAttributes");
+ //we need a low-level reliable routine to format a potentially invalid date => don't use strftime!!!
+ int bufferSize = ::GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
+ if (bufferSize > 0)
+ {
+ std::vector<wchar_t> buffer(bufferSize);
+ if (::GetDateFormat(LOCALE_USER_DEFAULT, //_In_ LCID Locale,
+ 0, //_In_ DWORD dwFlags,
+ &st, //_In_opt_ const SYSTEMTIME *lpDate,
+ nullptr, //_In_opt_ LPCTSTR lpFormat,
+ &buffer[0], //_Out_opt_ LPTSTR lpDateStr,
+ bufferSize) > 0) //_In_ int cchDate
+ errorMsg += std::wstring(L" ") + &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
+ }
- attribs = tmpAttr; //reapplied on scope exit
- return true;
+ bufferSize = ::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
+ if (bufferSize > 0)
+ {
+ std::vector<wchar_t> buffer(bufferSize);
+ if (::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, &buffer[0], bufferSize) > 0)
+ errorMsg += std::wstring(L" ") + &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
+ }
}
+ errorMsg += L" (" + numberTo<std::wstring>(writeTimeInt.QuadPart) + L")"; //just in case the above date formatting fails
}
- return false;
- };
+ }
+
+ if (ec != ERROR_SUCCESS)
+ throw FileError(errorMsg, formatSystemError(L"SetFileTime", ec));
+ }
+}
+
+
+void setWriteTimeNative(const Zstring& filePath,
+ const FILETIME& lastWriteTime,
+ const FILETIME* creationTime, //optional
+ ProcSymlink procSl) //throw FileError
+{
+ //privilege SE_BACKUP_NAME doesn't seem to be required here for symbolic links
+ //note: setting privileges requires admin rights!
+
+ //opening newly created target file may fail due to some AV-software scanning it: no error, we will wait!
+ //http://support.microsoft.com/?scid=kb%3Ben-us%3B316609&x=17&y=20
+ //-> enable as soon it turns out it is required!
+
+ /*const int retryInterval = 50;
+ const int maxRetries = 2000 / retryInterval;
+ for (int i = 0; i < maxRetries; ++i)
+ {
+ */
- auto openFile = [&](bool conservativeApproach)
+ /*
+ if (hTarget == INVALID_HANDLE_VALUE && ::GetLastError() == ERROR_SHARING_VIOLATION)
+ ::Sleep(retryInterval); //wait then retry
+ else //success or unknown failure
+ break;
+ }
+ */
+ //temporarily reset read-only flag if required
+ DWORD attribs = INVALID_FILE_ATTRIBUTES;
+ ZEN_ON_SCOPE_EXIT(
+ if (attribs != INVALID_FILE_ATTRIBUTES)
+ ::SetFileAttributes(applyLongPathPrefix(filePath).c_str(), attribs);
+ );
+
+ auto removeReadonly = [&]() -> bool //throw FileError; may need to remove the readonly-attribute (e.g. on FAT usb drives)
+ {
+ if (attribs == INVALID_FILE_ATTRIBUTES)
{
- return ::CreateFile(applyLongPathPrefix(filePath).c_str(), //_In_ LPCTSTR lpFileName,
- (conservativeApproach ?
- //some NAS seem to have issues with FILE_WRITE_ATTRIBUTES, even worse, they may fail silently!
- //http://sourceforge.net/tracker/?func=detail&atid=1093081&aid=3536680&group_id=234430
- //Citrix shares seem to have this issue, too, but at least fail with "access denied" => try generic access first:
- GENERIC_READ | GENERIC_WRITE :
- //avoids mysterious "access denied" when using "GENERIC_READ | GENERIC_WRITE" on a read-only file, even *after* read-only was removed directly before the call!
- //http://sourceforge.net/tracker/?func=detail&atid=1093080&aid=3514569&group_id=234430
- //since former gives an error notification we may very well try FILE_WRITE_ATTRIBUTES second.
- FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES), //_In_ DWORD dwDesiredAccess,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //_In_ DWORD dwShareMode,
- nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- OPEN_EXISTING, //_In_ DWORD dwCreationDisposition,
- (procSl == ProcSymlink::DIRECT ? FILE_FLAG_OPEN_REPARSE_POINT : 0) |
- FILE_FLAG_BACKUP_SEMANTICS, /*needed to open a directory*/ //_In_ DWORD dwFlagsAndAttributes,
- nullptr); //_In_opt_ HANDLE hTemplateFile
- };
+ const DWORD tmpAttr = ::GetFileAttributes(applyLongPathPrefix(filePath).c_str());
+ if (tmpAttr == INVALID_FILE_ATTRIBUTES)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(filePath)), L"GetFileAttributes");
+
+ if (tmpAttr & FILE_ATTRIBUTE_READONLY)
+ {
+ if (!::SetFileAttributes(applyLongPathPrefix(filePath).c_str(), FILE_ATTRIBUTE_NORMAL))
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file attributes of %x."), L"%x", fmtPath(filePath)), L"SetFileAttributes");
+
+ attribs = tmpAttr; //reapplied on scope exit
+ return true;
+ }
+ }
+ return false;
+ };
+
+ auto openFile = [&](bool conservativeApproach)
+ {
+ return ::CreateFile(applyLongPathPrefix(filePath).c_str(), //_In_ LPCTSTR lpFileName,
+ (conservativeApproach ?
+ //some NAS seem to have issues with FILE_WRITE_ATTRIBUTES, even worse, they may fail silently!
+ //http://sourceforge.net/tracker/?func=detail&atid=1093081&aid=3536680&group_id=234430
+ //Citrix shares seem to have this issue, too, but at least fail with "access denied" => try generic access first:
+ GENERIC_READ | GENERIC_WRITE :
+ //avoids mysterious "access denied" when using "GENERIC_READ | GENERIC_WRITE" on a read-only file, even *after* read-only was removed directly before the call!
+ //http://sourceforge.net/tracker/?func=detail&atid=1093080&aid=3514569&group_id=234430
+ //since former gives an error notification we may very well try FILE_WRITE_ATTRIBUTES second.
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES), //_In_ DWORD dwDesiredAccess,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //_In_ DWORD dwShareMode,
+ nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ OPEN_EXISTING, //_In_ DWORD dwCreationDisposition,
+ (procSl == ProcSymlink::DIRECT ? FILE_FLAG_OPEN_REPARSE_POINT : 0) |
+ FILE_FLAG_BACKUP_SEMANTICS, /*needed to open a directory*/ //_In_ DWORD dwFlagsAndAttributes,
+ nullptr); //_In_opt_ HANDLE hTemplateFile
+ };
+
+ {
+ //extra scope for debug check below
HANDLE hFile = INVALID_HANDLE_VALUE;
for (int i = 0; i < 2; ++i) //we will get this handle, no matter what! :)
@@ -716,118 +827,7 @@ void setFileTimeRaw(const Zstring& filePath,
}
ZEN_ON_SCOPE_EXIT(::CloseHandle(hFile));
-
- if (!::SetFileTime(hFile, //__in HANDLE hFile,
- creationTime, //__in_opt const FILETIME *lpCreationTime,
- nullptr, //__in_opt const FILETIME *lpLastAccessTime,
- &lastWriteTime)) //__in_opt const FILETIME *lpLastWriteTime
- {
- DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls!
-
- //function may fail if file is read-only: https://sourceforge.net/tracker/?func=detail&atid=1093080&aid=3514569&group_id=234430
- if (ec == ERROR_ACCESS_DENIED)
- {
- //dynamically load windows API function: available with Windows Vista and later
- typedef BOOL (WINAPI* SetFileInformationByHandleFunc)(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
- const SysDllFun<SetFileInformationByHandleFunc> setFileInformationByHandle(L"kernel32.dll", "SetFileInformationByHandle");
-
- if (setFileInformationByHandle) //if not: let the original error propagate!
- {
- auto setFileInfo = [&](FILE_BASIC_INFO basicInfo) //throw FileError; no const& since SetFileInformationByHandle() requires non-const parameter!
- {
- if (!setFileInformationByHandle(hFile, //__in HANDLE hFile,
- FileBasicInfo, //__in FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
- &basicInfo, //__in LPVOID lpFileInformation,
- sizeof(basicInfo))) //__in DWORD dwBufferSize
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file attributes of %x."), L"%x", fmtPath(filePath)), L"SetFileInformationByHandle");
- };
-
- auto toLargeInteger = [](const FILETIME& ft) -> LARGE_INTEGER
- {
- LARGE_INTEGER tmp = {};
- tmp.LowPart = ft.dwLowDateTime;
- tmp.HighPart = ft.dwHighDateTime;
- return tmp;
- };
- //---------------------------------------------------------------------------
-
- BY_HANDLE_FILE_INFORMATION fileInfo = {};
- if (::GetFileInformationByHandle(hFile, &fileInfo))
- if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- {
- FILE_BASIC_INFO basicInfo = {}; //undocumented: file times of "0" stand for "don't change"
- basicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; //[!] the bug in the ticket above requires we set this together with file times!!!
- basicInfo.LastWriteTime = toLargeInteger(lastWriteTime); //
- if (creationTime)
- basicInfo.CreationTime = toLargeInteger(*creationTime);
-
- //set file time + attributes
- setFileInfo(basicInfo); //throw FileError
-
- try //... to restore original file attributes
- {
- FILE_BASIC_INFO basicInfo2 = {};
- basicInfo2.FileAttributes = fileInfo.dwFileAttributes;
- setFileInfo(basicInfo2); //throw FileError
- }
- catch (FileError&) {}
-
- ec = ERROR_SUCCESS;
- }
- }
- }
-
- std::wstring errorMsg = replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath));
-
- //add more meaningful message: FAT accepts only a subset of the NTFS date range
- if (ec == ERROR_INVALID_PARAMETER &&
- isFatDrive(filePath))
- {
- //we need a low-level reliable routine to format a potentially invalid date => don't use strftime!!!
- auto fmtDate = [](const FILETIME& ft)
- {
- SYSTEMTIME st = {};
- if (!::FileTimeToSystemTime(&ft, //__in const FILETIME *lpFileTime,
- &st)) //__out LPSYSTEMTIME lpSystemTime
- return std::wstring();
-
- std::wstring dateTime;
- {
- const int bufferSize = ::GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
- if (bufferSize > 0)
- {
- std::vector<wchar_t> buffer(bufferSize);
- if (::GetDateFormat(LOCALE_USER_DEFAULT, //_In_ LCID Locale,
- 0, //_In_ DWORD dwFlags,
- &st, //_In_opt_ const SYSTEMTIME *lpDate,
- nullptr, //_In_opt_ LPCTSTR lpFormat,
- &buffer[0], //_Out_opt_ LPTSTR lpDateStr,
- bufferSize) > 0) //_In_ int cchDate
- dateTime = &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
- }
- }
-
- const int bufferSize = ::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, nullptr, 0);
- if (bufferSize > 0)
- {
- std::vector<wchar_t> buffer(bufferSize);
- if (::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, nullptr, &buffer[0], bufferSize) > 0)
- {
- dateTime += L" ";
- dateTime += &buffer[0]; //GetDateFormat() returns char count *including* 0-termination!
- }
- }
- return dateTime;
- };
-
- errorMsg += std::wstring(L"\nA FAT volume can only store dates between 1980 and 2107:\n") +
- L"\twrite (UTC): \t" + fmtDate(lastWriteTime) +
- (creationTime ? L"\n\tcreate (UTC): \t" + fmtDate(*creationTime) : L"");
- }
-
- if (ec != ERROR_SUCCESS)
- throw FileError(errorMsg, formatSystemError(L"SetFileTime", ec));
- }
+ setFileTimeByHandle(hFile, creationTime, lastWriteTime, filePath); //throw FileError
}
#ifndef NDEBUG //verify written data
FILETIME creationTimeDbg = {};
@@ -856,9 +856,26 @@ void setFileTimeRaw(const Zstring& filePath,
#elif defined ZEN_LINUX
-DEFINE_NEW_FILE_ERROR(ErrorLinuxFallbackToUtimes);
+void setWriteTimeFallback(const Zstring& filePath, std::int64_t modTime, ProcSymlink procSl) //throw FileError
+{
+ struct ::timeval writeTime[2] = {};
+ writeTime[0].tv_sec = ::time(nullptr); //access time (seconds)
+ writeTime[1].tv_sec = modTime; //modification time (seconds)
+
+ if (procSl == ProcSymlink::FOLLOW)
+ {
+ if (::utimes(filePath.c_str(), writeTime) != 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath)), L"utimes");
+ }
+ else
+ {
+ if (::lutimes(filePath.c_str(), writeTime) != 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath)), L"lutimes");
+ }
+}
-void setFileTimeRaw(const Zstring& filePath, const struct ::timespec& modTime, ProcSymlink procSl) //throw FileError, ErrorLinuxFallbackToUtimes
+
+void setWriteTimeNative(const Zstring& filePath, std::int64_t modTime, ProcSymlink procSl) //throw FileError
{
/*
[2013-05-01] sigh, we can't use utimensat() on NTFS volumes on Ubuntu: silent failure!!! what morons are programming this shit???
@@ -867,15 +884,15 @@ void setFileTimeRaw(const Zstring& filePath, const struct ::timespec& modTime, P
[2015-03-09]
- cannot reproduce issues with NTFS and utimensat() on Ubuntu
- utimensat() is supposed to obsolete utime/utimes and is also used by "cp" and "touch"
- - solves utimes() EINVAL bug for certain CIFS/NTFS drives: https://sourceforge.net/p/freefilesync/discussion/help/thread/1ace042d/
+ - solves utimes() EINVAL bug for certain CIFS/NTFS drives: http://www.freefilesync.org/forum/viewtopic.php?t=387
=> don't use utimensat() directly, but open file descriptor manually, else EINVAL, again!
=> let's give utimensat another chance:
*/
struct ::timespec newTimes[2] = {};
newTimes[0].tv_sec = ::time(nullptr); //access time; using UTIME_OMIT for tv_nsec would trigger even more bugs!!
- //https://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/218564cf/
- newTimes[1] = modTime; //modification time
+ //http://www.freefilesync.org/forum/viewtopic.php?t=1701
+ newTimes[1].tv_sec = modTime; //modification time
//=> using open()/futimens() for regular files and utimensat(AT_SYMLINK_NOFOLLOW) for symlinks is consistent with "cp" and "touch"!
if (procSl == ProcSymlink::FOLLOW)
@@ -884,7 +901,7 @@ void setFileTimeRaw(const Zstring& filePath, const struct ::timespec& modTime, P
if (fdFile == -1)
{
if (errno == EACCES) //bullshit, access denied even with 0777 permissions! => utimes should work!
- throw ErrorLinuxFallbackToUtimes(L"");
+ return setWriteTimeFallback(filePath, modTime, procSl); //throw FileError
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath)), L"open");
}
@@ -910,10 +927,10 @@ struct AttrBufFileTimes
} __attribute__((aligned(4), packed));
-void setFileTimeRaw(const Zstring& filePath,
- const struct ::timespec* createTime, //optional
- const struct ::timespec& writeTime,
- ProcSymlink procSl) //throw FileError
+void setWriteTimeNative(const Zstring& filePath,
+ const struct ::timespec& writeTime,
+ const struct ::timespec* createTime, //optional
+ ProcSymlink procSl) //throw FileError
{
//OS X: utime() is obsoleted by utimes()! utimensat() not yet implemented
//use ::setattrlist() instead of ::utimes() => 1. set file creation times 2. nanosecond precision
@@ -923,19 +940,19 @@ void setFileTimeRaw(const Zstring& filePath,
attribs.bitmapcount = ATTR_BIT_MAP_COUNT;
attribs.commonattr = (createTime ? ATTR_CMN_CRTIME : 0) | ATTR_CMN_MODTIME;
- AttrBufFileTimes newTimes;
+ AttrBufFileTimes attrBuf;
if (createTime)
{
- newTimes.createTime.tv_sec = createTime->tv_sec;
- newTimes.createTime.tv_nsec = createTime->tv_nsec;
+ attrBuf.createTime.tv_sec = createTime->tv_sec;
+ attrBuf.createTime.tv_nsec = createTime->tv_nsec;
}
- newTimes.writeTime.tv_sec = writeTime.tv_sec;
- newTimes.writeTime.tv_nsec = writeTime.tv_nsec;
+ attrBuf.writeTime.tv_sec = writeTime.tv_sec;
+ attrBuf.writeTime.tv_nsec = writeTime.tv_nsec;
const int rv = ::setattrlist(filePath.c_str(), //const char* path,
&attribs, //struct ::attrlist* attrList,
- createTime ? &newTimes.createTime : &newTimes.writeTime, //void* attrBuf,
- (createTime ? sizeof(newTimes.createTime) : 0) + sizeof(newTimes.writeTime), //size_t attrBufSize,
+ createTime ? &attrBuf.createTime : &attrBuf.writeTime, //void* attrBuf,
+ (createTime ? sizeof(attrBuf.createTime) : 0) + sizeof(attrBuf.writeTime), //size_t attrBufSize,
procSl == ProcSymlink::DIRECT ? FSOPT_NOFOLLOW : 0); //unsigned long options
if (rv != 0)
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath)), L"setattrlist");
@@ -952,22 +969,52 @@ void getFileTimeRaw(int fd, //throw FileError
attribs.bitmapcount = ATTR_BIT_MAP_COUNT;
attribs.commonattr = ATTR_CMN_CRTIME | ATTR_CMN_MODTIME;
- AttrBufFileTimes fileTimes;
+ AttrBufFileTimes attrBuf;
- const int rv = ::fgetattrlist(fd, //int fd,
- &attribs, //struct ::attrlist* attrList,
- &fileTimes, //void* attrBuf,
- sizeof(fileTimes), //size_t attrBufSize,
- 0); //unsigned long options
+ const int rv = ::fgetattrlist(fd, //int fd,
+ &attribs, //struct ::attrlist* attrList,
+ &attrBuf, //void* attrBuf,
+ sizeof(attrBuf), //size_t attrBufSize,
+ 0); //unsigned long options
if (rv != 0)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(filePath)), L"getattrlist");
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(filePath)), L"fgetattrlist");
- createTime.tv_sec = fileTimes.createTime.tv_sec;
- createTime.tv_nsec = fileTimes.createTime.tv_nsec;
- writeTime.tv_sec = fileTimes.writeTime.tv_sec;
- writeTime.tv_nsec = fileTimes.writeTime.tv_nsec;
+ createTime.tv_sec = attrBuf.createTime.tv_sec;
+ createTime.tv_nsec = attrBuf.createTime.tv_nsec;
+ writeTime.tv_sec = attrBuf.writeTime.tv_sec;
+ writeTime.tv_nsec = attrBuf.writeTime.tv_nsec;
}
*/
+
+//PERF: ~10µs per call for "int fd" variant (irrespective if file is local or on mounted USB; test case: 3000 files)
+bool hasNativeSupportForExtendedAtrributes(const Zstring& filePath, //throw FileError
+ int fd = -1) //speed up!?
+{
+ struct ::statfs volInfo = {};
+ if ((fd != -1 ? ::fstatfs(fd, &volInfo) : ::statfs(filePath.c_str(), &volInfo)) != 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(filePath)), fd != -1 ? L"fstatfs" : L"statfs");
+
+ struct ::attrlist attribs = {};
+ attribs.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attribs.volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES;
+
+ struct
+ {
+ std::uint32_t length = 0;
+ vol_capabilities_attr_t volCaps{};
+ } __attribute__((aligned(4), packed)) attrBuf;
+
+ const int rv = ::getattrlist(volInfo.f_mntonname, //const char* path,
+ &attribs, //struct ::attrlist* attrList,
+ &attrBuf, //void* attrBuf,
+ sizeof(attrBuf), //size_t attrBufSize,
+ 0); //unsigned long options
+ if (rv != 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(volInfo.f_mntonname)), L"getattrlist");
+
+ return (attrBuf.volCaps.valid [VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_EXTENDED_ATTR) != 0 &&
+ (attrBuf.volCaps.capabilities[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_EXTENDED_ATTR) != 0;
+}
#endif
}
@@ -975,37 +1022,15 @@ void getFileTimeRaw(int fd, //throw FileError
void zen::setFileTime(const Zstring& filePath, std::int64_t modTime, ProcSymlink procSl) //throw FileError
{
#ifdef ZEN_WIN
- setFileTimeRaw(filePath, nullptr, timetToFileTime(modTime), procSl); //throw FileError
+ setWriteTimeNative(filePath, timetToFileTime(modTime), nullptr, procSl); //throw FileError
#elif defined ZEN_LINUX
- try
- {
- struct ::timespec writeTime = {};
- writeTime.tv_sec = modTime;
- setFileTimeRaw(filePath, writeTime, procSl); //throw FileError, ErrorLinuxFallbackToUtimes
- }
- catch (ErrorLinuxFallbackToUtimes&)
- {
- struct ::timeval writeTime[2] = {};
- writeTime[0].tv_sec = ::time(nullptr); //access time (seconds)
- writeTime[1].tv_sec = modTime; //modification time (seconds)
-
- if (procSl == ProcSymlink::FOLLOW)
- {
- if (::utimes(filePath.c_str(), writeTime) != 0)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath)), L"utimes");
- }
- else
- {
- if (::lutimes(filePath.c_str(), writeTime) != 0)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(filePath)), L"lutimes");
- }
- }
+ setWriteTimeNative(filePath, modTime, procSl); //throw FileError
#elif defined ZEN_MAC
struct ::timespec writeTime = {};
writeTime.tv_sec = modTime;
- setFileTimeRaw(filePath, nullptr, writeTime, procSl); //throw FileError
+ setWriteTimeNative(filePath, writeTime, nullptr, procSl); //throw FileError
#endif
}
@@ -1351,20 +1376,16 @@ void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath,
auto getErrorMsg = [](const Zstring& path) { return replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(path)); };
//special handling for volume root: trying to create existing root directory results in ERROR_ACCESS_DENIED rather than ERROR_ALREADY_EXISTS!
- Zstring dirTmp = removeLongPathPrefix(endsWith(targetPath, FILE_NAME_SEPARATOR) ?
- beforeLast(targetPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE) :
- targetPath);
- if (dirTmp.size() == 2 &&
- isAlpha(dirTmp[0]) && dirTmp[1] == L':')
+ const Zstring pathPf = appendSeparator(targetPath); //we do not support "C:" to represent a relative path!
+ if (pathPf.size() == 3 &&
+ isAlpha(pathPf[0]) && pathPf[1] == L':')
{
- dirTmp += FILE_NAME_SEPARATOR; //we do not support "C:" to represent a relative path!
-
- const DWORD ec = somethingExists(dirTmp) ? ERROR_ALREADY_EXISTS : ERROR_PATH_NOT_FOUND; //don't use dirExists() => harmonize with ErrorTargetExisting!
+ const DWORD ec = somethingExists(pathPf) ? ERROR_ALREADY_EXISTS : ERROR_PATH_NOT_FOUND; //don't use dirExists() => harmonize with ErrorTargetExisting!
const std::wstring errorDescr = formatSystemError(L"CreateDirectory", ec);
if (ec == ERROR_ALREADY_EXISTS)
- throw ErrorTargetExisting(getErrorMsg(dirTmp), errorDescr);
- throw FileError(getErrorMsg(dirTmp), errorDescr); //[!] this is NOT a ErrorTargetPathMissing case!
+ throw ErrorTargetExisting(getErrorMsg(pathPf), errorDescr);
+ throw FileError(getErrorMsg(pathPf), errorDescr); //[!] this is NOT a ErrorTargetPathMissing case!
}
//deliberately don't support creating irregular folders like "...." https://social.technet.microsoft.com/Forums/windows/en-US/ffee2322-bb6b-4fdf-86f9-8f93cf1fa6cb/
@@ -1498,7 +1519,8 @@ void zen::copyNewDirectory(const Zstring& sourcePath, const Zstring& targetPath,
}
#elif defined ZEN_MAC
- /*int rv =*/ ::copyfile(sourcePath.c_str(), targetPath.c_str(), nullptr, COPYFILE_XATTR);
+ if (hasNativeSupportForExtendedAtrributes(targetPath)) //throw FileError
+ ::copyfile(sourcePath.c_str(), targetPath.c_str(), nullptr, COPYFILE_XATTR); //ignore errors, see related comments in copyFileOsSpecific()
#endif
ZEN_ON_SCOPE_FAIL(try { removeDirectorySimple(targetPath); }
@@ -1564,24 +1586,24 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool
&sourceAttr)) //__out LPVOID lpFileInformation
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(sourceLink)), L"GetFileAttributesEx");
- setFileTimeRaw(targetLink, &sourceAttr.ftCreationTime, sourceAttr.ftLastWriteTime, ProcSymlink::DIRECT); //throw FileError
+ setWriteTimeNative(targetLink, sourceAttr.ftLastWriteTime, &sourceAttr.ftCreationTime, ProcSymlink::DIRECT); //throw FileError
#elif defined ZEN_LINUX
struct ::stat sourceInfo = {};
if (::lstat(sourceLink.c_str(), &sourceInfo) != 0)
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(sourceLink)), L"lstat");
- setFileTime(targetLink, sourceInfo.st_mtime, ProcSymlink::DIRECT); //throw FileError
+ setWriteTimeNative(targetLink, sourceInfo.st_mtime, ProcSymlink::DIRECT); //throw FileError
#elif defined ZEN_MAC
struct ::stat sourceInfo = {};
if (::lstat(sourceLink.c_str(), &sourceInfo) != 0)
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(sourceLink)), L"lstat");
- if (::copyfile(sourceLink.c_str(), targetLink.c_str(), nullptr, COPYFILE_XATTR | COPYFILE_NOFOLLOW) != 0)
- THROW_LAST_FILE_ERROR(replaceCpy(replaceCpy(_("Cannot copy attributes from %x to %y."), L"%x", L"\n" + fmtPath(sourceLink)), L"%y", L"\n" + fmtPath(targetLink)), L"copyfile");
+ if (hasNativeSupportForExtendedAtrributes(targetLink)) //throw FileError
+ ::copyfile(sourceLink.c_str(), targetLink.c_str(), nullptr, COPYFILE_XATTR | COPYFILE_NOFOLLOW); //ignore errors, see related comments in copyFileOsSpecific()
- setFileTimeRaw(targetLink, &sourceInfo.st_birthtimespec, sourceInfo.st_mtimespec, ProcSymlink::DIRECT); //throw FileError
+ setWriteTimeNative(targetLink, sourceInfo.st_mtimespec, &sourceInfo.st_birthtimespec, ProcSymlink::DIRECT); //throw FileError
#endif
if (copyFilePermissions)
@@ -1720,10 +1742,10 @@ bool canCopyAsSparse(const Zstring& sourceFile, const Zstring& targetFile) //thr
InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw FileError, ErrorTargetExisting, ErrorFileLocked
const Zstring& targetFile,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
//try to get backup read and write privileges: help solve most "access denied" errors with FILE_FLAG_BACKUP_SEMANTICS:
- //https://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/1998ebf2/
+ //http://www.freefilesync.org/forum/viewtopic.php?t=1714
try { activatePrivilege(SE_BACKUP_NAME); }
catch (const FileError&) {}
try { activatePrivilege(SE_RESTORE_NAME); }
@@ -1933,7 +1955,7 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw
throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(targetFile)), L"BackupWrite: incomplete write."); //user should never see this
//total bytes transferred may be larger than file size! context information + ADS or smaller (sparse, compressed)!
- if (onUpdateCopyStatus) onUpdateCopyStatus(bytesRead); //throw X!
+ if (notifyProgress) notifyProgress(bytesRead); //throw X!
if (bytesRead > 0)
someBytesRead = true;
@@ -1946,11 +1968,7 @@ InSyncAttributes copyFileWindowsBackupStream(const Zstring& sourceFile, //throw
throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(sourceFile)), L"BackupRead: unknown error"); //user should never see this -> this method is called only if "canCopyAsSparse()"
//time needs to be set at the end: BackupWrite() changes modification time
- if (!::SetFileTime(hFileTarget,
- &fileInfoSource.ftCreationTime,
- nullptr,
- &fileInfoSource.ftLastWriteTime))
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write modification time of %x."), L"%x", fmtPath(targetFile)), L"SetFileTime");
+ setFileTimeByHandle(hFileTarget, &fileInfoSource.ftCreationTime,fileInfoSource.ftLastWriteTime, targetFile); //throw FileError
return newAttrib;
}
@@ -1961,16 +1979,16 @@ DEFINE_NEW_FILE_ERROR(ErrorFallbackToCopyAsBackupStream);
struct CallbackData
{
- CallbackData(const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus,
+ CallbackData(const std::function<void(std::int64_t bytesDelta)>& notifyProgress,
const Zstring& sourceFile,
const Zstring& targetFile) :
sourceFile_(sourceFile),
targetFile_(targetFile),
- onUpdateCopyStatus_(onUpdateCopyStatus) {}
+ notifyProgress_(notifyProgress) {}
const Zstring& sourceFile_;
const Zstring& targetFile_;
- const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus_; //optional
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress_; //optional
std::exception_ptr exception; //out
BY_HANDLE_FILE_INFORMATION fileInfoSrc{}; //out: modified by CopyFileEx() at beginning
@@ -2059,9 +2077,9 @@ DWORD CALLBACK copyCallbackInternal(LARGE_INTEGER totalFileSize,
}
}
- if (cbd.onUpdateCopyStatus_ && totalBytesTransferred.QuadPart >= 0) //should always be true, but let's still check
+ if (cbd.notifyProgress_ && totalBytesTransferred.QuadPart >= 0) //should always be true, but let's still check
{
- cbd.onUpdateCopyStatus_(totalBytesTransferred.QuadPart - cbd.bytesReported); //throw X!
+ cbd.notifyProgress_(totalBytesTransferred.QuadPart - cbd.bytesReported); //throw X!
cbd.bytesReported = totalBytesTransferred.QuadPart;
}
}
@@ -2076,7 +2094,7 @@ DWORD CALLBACK copyCallbackInternal(LARGE_INTEGER totalFileSize,
InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileError, ErrorTargetExisting, ErrorFileLocked, ErrorFallbackToCopyAsBackupStream
const Zstring& targetFile,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
//try to get backup read and write privileges: may help solve some "access denied" errors
bool backupPrivilegesActive = true;
@@ -2095,12 +2113,12 @@ InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileE
//if (vistaOrLater()) //see http://blogs.technet.com/b/askperf/archive/2007/05/08/slow-large-file-copy-issues.aspx
// copyFlags |= COPY_FILE_NO_BUFFERING; //no perf difference at worst, improvement for large files (20% in test NTFS -> NTFS)
- // - this flag may cause file corruption! https://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/65f48357/
+ // - this flag may cause file corruption! http://www.freefilesync.org/forum/viewtopic.php?t=1857
// - documentation on CopyFile2() even states: "It is not recommended to pause copies that are using this flag."
//=> it's not worth it! instead of skipping buffering at kernel-level (=> also NO prefetching!!!), skip it at user-level: memory mapped files!
// however, perf-measurements for memory mapped files show: it's also not worth it!
- CallbackData cbd(onUpdateCopyStatus, sourceFile, targetFile);
+ CallbackData cbd(notifyProgress, sourceFile, targetFile);
const bool success = ::CopyFileEx(applyLongPathPrefix(sourceFile).c_str(), //__in LPCTSTR lpExistingFileName,
applyLongPathPrefix(targetFile).c_str(), //__in LPCTSTR lpNewFileName,
@@ -2122,10 +2140,10 @@ InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileE
throw ErrorFallbackToCopyAsBackupStream(L"sparse, copy failure");
if (ec == ERROR_ACCESS_DENIED && backupPrivilegesActive)
- //chances are good this will work with copyFileWindowsBackupStream: https://sourceforge.net/p/freefilesync/discussion/open-discussion/thread/1998ebf2/
+ //chances are good this will work with copyFileWindowsBackupStream: http://www.freefilesync.org/forum/viewtopic.php?t=1714
throw ErrorFallbackToCopyAsBackupStream(L"access denied");
- //copying ADS may incorrectly fail with ERROR_FILE_NOT_FOUND: https://sourceforge.net/p/freefilesync/discussion/help/thread/a18a2c02/
+ //copying ADS may incorrectly fail with ERROR_FILE_NOT_FOUND: http://www.freefilesync.org/forum/viewtopic.php?t=446
if (ec == ERROR_FILE_NOT_FOUND &&
cbd.fileInfoSrc.nNumberOfLinks > 0 &&
cbd.fileInfoTrg.nNumberOfLinks > 0)
@@ -2175,7 +2193,7 @@ InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileE
//caveat: - ::CopyFileEx() silently *ignores* failure to set modification time!!! => we always need to set it again but with proper error checking!
// - perf: recent measurements show no slow down at all for buffered USB sticks!
- setFileTimeRaw(targetFile, &cbd.fileInfoSrc.ftCreationTime, cbd.fileInfoSrc.ftLastWriteTime, ProcSymlink::FOLLOW); //throw FileError
+ setWriteTimeNative(targetFile, cbd.fileInfoSrc.ftLastWriteTime, &cbd.fileInfoSrc.ftCreationTime, ProcSymlink::FOLLOW); //throw FileError
InSyncAttributes newAttrib;
newAttrib.fileSize = get64BitUInt(cbd.fileInfoSrc.nFileSizeLow, cbd.fileInfoSrc.nFileSizeHigh);
@@ -2188,15 +2206,15 @@ InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileE
//another layer to support copying sparse files and handle some access denied errors
inline
-InSyncAttributes copyFileWindowsSelectRoutine(const Zstring& sourceFile, const Zstring& targetFile, const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus)
+InSyncAttributes copyFileWindowsSelectRoutine(const Zstring& sourceFile, const Zstring& targetFile, const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
try
{
- return copyFileWindowsDefault(sourceFile, targetFile, onUpdateCopyStatus); //throw FileError, ErrorTargetExisting, ErrorFileLocked, ErrorFallbackToCopyAsBackupStream
+ return copyFileWindowsDefault(sourceFile, targetFile, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked, ErrorFallbackToCopyAsBackupStream
}
catch (ErrorFallbackToCopyAsBackupStream&)
{
- return copyFileWindowsBackupStream(sourceFile, targetFile, onUpdateCopyStatus); //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ return copyFileWindowsBackupStream(sourceFile, targetFile, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
}
}
@@ -2205,11 +2223,11 @@ InSyncAttributes copyFileWindowsSelectRoutine(const Zstring& sourceFile, const Z
inline
InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile,
const Zstring& targetFile,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
try
{
- return copyFileWindowsSelectRoutine(sourceFile, targetFile, onUpdateCopyStatus); //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ return copyFileWindowsSelectRoutine(sourceFile, targetFile, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
}
catch (const ErrorTargetExisting&)
{
@@ -2217,7 +2235,7 @@ InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile,
if (have8dot3NameClash(targetFile))
{
Fix8Dot3NameClash dummy(targetFile); //throw FileError; move clashing file path to the side
- return copyFileWindowsSelectRoutine(sourceFile, targetFile, onUpdateCopyStatus); //throw FileError; the short file path name clash is solved, this should work now
+ return copyFileWindowsSelectRoutine(sourceFile, targetFile, notifyProgress); //throw FileError; the short file path name clash is solved, this should work now
}
throw;
}
@@ -2227,19 +2245,20 @@ InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile,
#elif defined ZEN_LINUX || defined ZEN_MAC
InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile, //throw FileError, ErrorTargetExisting
const Zstring& targetFile,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
FileInput fileIn(sourceFile); //throw FileError
+ if (notifyProgress) notifyProgress(0); //throw X!
struct ::stat sourceInfo = {};
if (::fstat(fileIn.getHandle(), &sourceInfo) != 0)
THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(sourceFile)), L"fstat");
-
+
const mode_t mode = sourceInfo.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); //analog to "cp" which copies "mode" (considering umask) by default
- //it seems we don't need S_IWUSR, not even for the setFileTime() below! (tested with source file having different user/group!)
-
- const int fdTarget = ::open(targetFile.c_str(), O_WRONLY | O_CREAT | O_EXCL, mode);
+ //it seems we don't need S_IWUSR, not even for the setFileTime() below! (tested with source file having different user/group!)
+
//=> need copyItemPermissions() only for "chown" and umask-agnostic permissions
+ const int fdTarget = ::open(targetFile.c_str(), O_WRONLY | O_CREAT | O_EXCL, mode);
if (fdTarget == -1)
{
const int ec = errno; //copy before making other system calls!
@@ -2251,66 +2270,62 @@ InSyncAttributes copyFileOsSpecific(const Zstring& sourceFile, //throw FileError
throw FileError(errorMsg, errorDescr);
}
- if (onUpdateCopyStatus) onUpdateCopyStatus(0); //throw X!
-
- InSyncAttributes newAttrib;
ZEN_ON_SCOPE_FAIL( try { removeFile(targetFile); }
catch (FileError&) {} );
//transactional behavior: place guard after ::open() and before lifetime of FileOutput:
//=> don't delete file that existed previously!!!
- {
- FileOutput fileOut(fdTarget, targetFile); //pass ownership
- if (onUpdateCopyStatus) onUpdateCopyStatus(0); //throw X!
-
- copyStream(fileIn, fileOut, std::min(fileIn .optimalBlockSize(),
- fileOut.optimalBlockSize()), onUpdateCopyStatus); //throw FileError, X
-
- struct ::stat targetInfo = {};
- if (::fstat(fileOut.getHandle(), &targetInfo) != 0)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(targetFile)), L"fstat");
+ FileOutput fileOut(fdTarget, targetFile); //pass ownership
+ if (notifyProgress) notifyProgress(0); //throw X!
- newAttrib.fileSize = sourceInfo.st_size;
-#ifdef ZEN_MAC
- newAttrib.modificationTime = sourceInfo.st_mtimespec.tv_sec; //use same time variable like setFileTimeRaw() for consistency
-#else
- newAttrib.modificationTime = sourceInfo.st_mtime;
-#endif
- newAttrib.sourceFileId = extractFileId(sourceInfo);
- newAttrib.targetFileId = extractFileId(targetInfo);
+ unbufferedStreamCopy(fileIn, fileOut, notifyProgress); //throw FileError, X
#ifdef ZEN_MAC
- //using ::copyfile with COPYFILE_DATA seems to trigger bugs unlike our stream-based copying!
- //=> use ::copyfile for extended attributes only: https://sourceforge.net/p/freefilesync/discussion/help/thread/91384c8a/
- //http://blog.plasticsfuture.org/2006/03/05/the-state-of-backup-and-cloning-tools-under-mac-os-x/
- //docs: http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/copyfile.3.html
- //source: http://www.opensource.apple.com/source/copyfile/copyfile-103.92.1/copyfile.c
+ //using ::copyfile with COPYFILE_DATA seems to trigger bugs unlike our stream-based copying!
+ //=> use ::copyfile for extended attributes only: http://www.freefilesync.org/forum/viewtopic.php?t=401
+ //http://blog.plasticsfuture.org/2006/03/05/the-state-of-backup-and-cloning-tools-under-mac-os-x/
+ //docs: http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/copyfile.3.html
+ //source: http://www.opensource.apple.com/source/copyfile/copyfile-103.92.1/copyfile.c
+
+ //avoid creation of ._ files if target doesn't support extended attributes: http://www.freefilesync.org/forum/viewtopic.php?t=2226
+ if (hasNativeSupportForExtendedAtrributes(targetFile, fileOut.getHandle())) //throw FileError
if (::fcopyfile(fileIn.getHandle(), fileOut.getHandle(), nullptr, COPYFILE_XATTR) != 0)
- {
- /*
- extended attributes are only optional here => ignore error
- E2BIG - reference email: "FFS V7.8 on Mac with 10.11.2 ElCapitan"
- EINVAL - reference email: "Error Code 22: Invalid argument (copyfile)"
- */
- //THROW_LAST_FILE_ERROR(replaceCpy(replaceCpy(_("Cannot copy attributes from %x to %y."), L"%x", L"\n" + fmtPath(sourceFile)), L"%y", L"\n" + fmtPath(targetFile)), L"fcopyfile");
- }
+ ; //THROW_LAST_FILE_ERROR(replaceCpy(replaceCpy(_("Cannot copy attributes from %x to %y."), L"%x", L"\n" + fmtPath(sourceFile)), L"%y", L"\n" + fmtPath(targetFile)), L"fcopyfile");
+ /*
+ both problems still occur even with the "hasNativeSupportForExtendedAtrributes" check above:
+ E2BIG - reference email: "Re: FFS V7.8 on Mac with 10.11.2 ElCapitan"
+ EINVAL - reference email: "Error Code 22: Invalid argument (copyfile)"
+ */
#endif
+ struct ::stat targetInfo = {};
+ if (::fstat(fileOut.getHandle(), &targetInfo) != 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(targetFile)), L"fstat");
- fileOut.close(); //throw FileError -> optional, but good place to catch errors when closing stream!
- } //close output file handle before setting file time
+ //close output file handle before setting file time; also good place to catch errors when closing stream!
+ fileOut.close(); //throw FileError
+ if (notifyProgress) notifyProgress(0); //throw X!
//we cannot set the target file times (::futimes) while the file descriptor is still open after a write operation:
//this triggers bugs on samba shares where the modification time is set to current time instead.
//Linux: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=340236
// http://comments.gmane.org/gmane.linux.file-systems.cifs/2854
- //OS X: https://sourceforge.net/p/freefilesync/discussion/help/thread/881357c0/
+ //OS X: http://www.freefilesync.org/forum/viewtopic.php?t=356
#ifdef ZEN_MAC
- setFileTimeRaw(targetFile, &sourceInfo.st_birthtimespec, sourceInfo.st_mtimespec, ProcSymlink::FOLLOW); //throw FileError
+ setWriteTimeNative(targetFile, sourceInfo.st_mtimespec, &sourceInfo.st_birthtimespec, ProcSymlink::FOLLOW); //throw FileError
//sourceInfo.st_birthtime; -> only seconds-precision
//sourceInfo.st_mtime; ->
#else
- setFileTime(targetFile, sourceInfo.st_mtime, ProcSymlink::FOLLOW); //throw FileError
+ setWriteTimeNative(targetFile, sourceInfo.st_mtime, ProcSymlink::FOLLOW); //throw FileError
#endif
+ InSyncAttributes newAttrib;
+ newAttrib.fileSize = sourceInfo.st_size;
+#ifdef ZEN_MAC
+ newAttrib.modificationTime = sourceInfo.st_mtimespec.tv_sec; //use same time variable like setWriteTimeNative() for consistency
+#else
+ newAttrib.modificationTime = sourceInfo.st_mtime;
+#endif
+ newAttrib.sourceFileId = extractFileId(sourceInfo);
+ newAttrib.targetFileId = extractFileId(targetInfo);
return newAttrib;
}
#endif
@@ -2331,9 +2346,9 @@ copyFileWindowsDefault(::CopyFileEx) copyFileWindowsBackupStream(::BackupRead/:
InSyncAttributes zen::copyNewFile(const Zstring& sourceFile, const Zstring& targetFile, bool copyFilePermissions, //throw FileError, ErrorTargetExisting, ErrorFileLocked
- const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus)
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress)
{
- const InSyncAttributes attr = copyFileOsSpecific(sourceFile, targetFile, onUpdateCopyStatus); //throw FileError, ErrorTargetExisting, ErrorFileLocked
+ const InSyncAttributes attr = copyFileOsSpecific(sourceFile, targetFile, notifyProgress); //throw FileError, ErrorTargetExisting, ErrorFileLocked
//at this point we know we created a new file, so it's fine to delete it for cleanup!
ZEN_ON_SCOPE_FAIL(try { removeFile(targetFile); }
diff --git a/zen/file_access.h b/zen/file_access.h
index ec5bda66..026027e7 100644
--- a/zen/file_access.h
+++ b/zen/file_access.h
@@ -63,7 +63,7 @@ struct InSyncAttributes
InSyncAttributes copyNewFile(const Zstring& sourceFile, const Zstring& targetFile, bool copyFilePermissions, //throw FileError, ErrorTargetExisting, ErrorFileLocked
//accummulated delta != file size! consider ADS, sparse, compressed files
- const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus); //may be nullptr; throw X!
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress); //may be nullptr; throw X!
}
#endif //FILE_ACCESS_H_8017341345614857
diff --git a/zen/file_io.cpp b/zen/file_io.cpp
index b385ce33..b4351ee8 100644
--- a/zen/file_io.cpp
+++ b/zen/file_io.cpp
@@ -152,6 +152,7 @@ FileInput::FileInput(const Zstring& filepath) : //throw FileError, ErrorFileLock
#ifdef ZEN_WIN //destructor call would lead to member double clean-up!!!
ZEN_ON_SCOPE_FAIL(::CloseHandle(fileHandle));
+
#elif defined ZEN_LINUX || defined ZEN_MAC
ZEN_ON_SCOPE_FAIL(::close(fileHandle));
#endif
@@ -178,45 +179,38 @@ FileInput::~FileInput()
}
-size_t FileInput::read(void* buffer, size_t bytesToRead) //throw FileError; returns actual number of bytes read
+size_t FileInput::tryRead(void* buffer, size_t bytesToRead) //throw FileError; may return short, only 0 means EOF!
{
- size_t bytesReadTotal = 0;
+ if (bytesToRead == 0) //"read() with a count of 0 returns zero" => indistinguishable from end of file! => check!
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
- while (bytesToRead > 0) //"read() with a count of 0 returns zero" => indistinguishable from end of file! => check!
- {
#ifdef ZEN_WIN
- //test for end of file: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365690%28v=vs.85%29.aspx
- DWORD bytesRead = 0;
- if (!::ReadFile(fileHandle, //__in HANDLE hFile,
- buffer, //__out LPVOID lpBuffer,
- static_cast<DWORD>(bytesToRead), //__in DWORD nNumberOfBytesToRead,
- &bytesRead, //__out_opt LPDWORD lpNumberOfBytesRead,
- nullptr)) //__inout_opt LPOVERLAPPED lpOverlapped
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getFilePath())), L"ReadFile");
+ //posix ::read() semantics: test for end of file: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365690%28v=vs.85%29.aspx
+ DWORD bytesRead = 0;
+ if (!::ReadFile(fileHandle, //__in HANDLE hFile,
+ buffer, //__out LPVOID lpBuffer,
+ static_cast<DWORD>(bytesToRead), //__in DWORD nNumberOfBytesToRead,
+ &bytesRead, //__out_opt LPDWORD lpNumberOfBytesRead,
+ nullptr)) //__inout_opt LPOVERLAPPED lpOverlapped
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getFilePath())), L"ReadFile");
#elif defined ZEN_LINUX || defined ZEN_MAC
- ssize_t bytesRead = 0;
- do
- {
- bytesRead = ::read(fileHandle, buffer, bytesToRead);
- }
- while (bytesRead < 0 && errno == EINTR); //Compare copy_reg() in copy.c: ftp://ftp.gnu.org/gnu/coreutils/coreutils-8.23.tar.xz
+ ssize_t bytesRead = 0;
+ do
+ {
+ bytesRead = ::read(fileHandle, buffer, bytesToRead);
+ }
+ while (bytesRead < 0 && errno == EINTR); //Compare copy_reg() in copy.c: ftp://ftp.gnu.org/gnu/coreutils/coreutils-8.23.tar.xz
- if (bytesRead < 0)
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getFilePath())), L"read");
+ if (bytesRead < 0)
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getFilePath())), L"read");
#endif
- if (bytesRead == 0) //"zero indicates end of file"
- return bytesReadTotal;
+ if (static_cast<size_t>(bytesRead) > bytesToRead) //better safe than sorry
+ throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getFilePath())), L"ReadFile: buffer overflow."); //user should never see this
- if (static_cast<size_t>(bytesRead) > bytesToRead) //better safe than sorry
- throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(getFilePath())), L"ReadFile: buffer overflow."); //user should never see this
+ //if ::read is interrupted (EINTR) right in the middle, it will return successfully with "bytesRead < bytesToRead" => loop!
- //if ::read is interrupted (EINTR) right in the middle, it will return successfully with "bytesRead < bytesToRead" => loop!
- buffer = static_cast<char*>(buffer) + bytesRead; //suppress warning about pointer arithmetics on void*
- bytesToRead -= bytesRead;
- bytesReadTotal += bytesRead;
- }
- return bytesReadTotal;
+ return bytesRead; //"zero indicates end of file"
}
//----------------------------------------------------------------------------------------------------
@@ -355,8 +349,11 @@ void FileOutput::close() //throw FileError
}
-void FileOutput::write(const void* buffer, size_t bytesToWrite) //throw FileError
+size_t FileOutput::tryWrite(const void* buffer, size_t bytesToWrite) //throw FileError; may return short! CONTRACT: bytesToWrite > 0
{
+ if (bytesToWrite == 0)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
#ifdef ZEN_WIN
DWORD bytesWritten = 0; //this parameter is NOT optional: http://blogs.msdn.com/b/oldnewthing/archive/2013/04/04/10407417.aspx
if (!::WriteFile(fileHandle, //__in HANDLE hFile,
@@ -370,28 +367,24 @@ void FileOutput::write(const void* buffer, size_t bytesToWrite) //throw FileErro
throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getFilePath())), L"WriteFile: incomplete write."); //user should never see this
#elif defined ZEN_LINUX || defined ZEN_MAC
- while (bytesToWrite > 0)
+ ssize_t bytesWritten = 0;
+ do
{
- ssize_t bytesWritten = 0;
- do
- {
- bytesWritten = ::write(fileHandle, buffer, bytesToWrite);
- }
- while (bytesWritten < 0 && errno == EINTR);
-
- if (bytesWritten <= 0)
- {
- if (bytesWritten == 0) //comment in safe-read.c suggests to treat this as an error due to buggy drivers
- errno = ENOSPC;
+ bytesWritten = ::write(fileHandle, buffer, bytesToWrite);
+ }
+ while (bytesWritten < 0 && errno == EINTR);
- THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getFilePath())), L"write");
- }
- if (bytesWritten > static_cast<ssize_t>(bytesToWrite)) //better safe than sorry
- throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getFilePath())), L"write: buffer overflow."); //user should never see this
+ if (bytesWritten <= 0)
+ {
+ if (bytesWritten == 0) //comment in safe-read.c suggests to treat this as an error due to buggy drivers
+ errno = ENOSPC;
- //if ::write() is interrupted (EINTR) right in the middle, it will return successfully with "bytesWritten < bytesToWrite"!
- buffer = static_cast<const char*>(buffer) + bytesWritten; //suppress warning about pointer arithmetics on void*
- bytesToWrite -= bytesWritten;
+ THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getFilePath())), L"write");
}
+ if (bytesWritten > static_cast<ssize_t>(bytesToWrite)) //better safe than sorry
+ throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(getFilePath())), L"write: buffer overflow."); //user should never see this
+
+ //if ::write() is interrupted (EINTR) right in the middle, it will return successfully with "bytesWritten < bytesToWrite"!
#endif
+ return bytesWritten;
}
diff --git a/zen/file_io.h b/zen/file_io.h
index 5bcf4189..261829cd 100644
--- a/zen/file_io.h
+++ b/zen/file_io.h
@@ -8,6 +8,7 @@
#define FILE_IO_H_89578342758342572345
#include "file_error.h"
+#include "serialize.h"
#ifdef ZEN_WIN
#include "win.h" //includes "windows.h"
@@ -54,9 +55,12 @@ public:
FileInput(FileHandle handle, const Zstring& filepath); //takes ownership!
~FileInput();
- size_t read(void* buffer, size_t bytesToRead); //throw FileError; returns "bytesToRead", unless end of file!
+ //Windows: better use 64kB ?? https://technet.microsoft.com/en-us/library/cc938632.aspx
+ //Linux: use st_blksize?
+ size_t getBlockSize() const { return 128 * 1024; }
+ size_t tryRead(void* buffer, size_t bytesToRead); //throw FileError; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0!
+
FileHandle getHandle() { return fileHandle; }
- size_t optimalBlockSize() const { return 128 * 1024; }
private:
FileHandle fileHandle;
@@ -75,17 +79,39 @@ public:
FileOutput(const Zstring& filepath, AccessFlag access); //throw FileError, ErrorTargetExisting
FileOutput(FileHandle handle, const Zstring& filepath); //takes ownership!
~FileOutput();
- void close(); //throw FileError -> optional, but good place to catch errors when closing stream!
-
- void write(const void* buffer, size_t bytesToWrite); //throw FileError
- FileHandle getHandle() { return fileHandle; }
- size_t optimalBlockSize() const { return 128 * 1024; }
FileOutput(FileOutput&& tmp);
+ size_t getBlockSize() const { return 128 * 1024; }
+ size_t tryWrite(const void* buffer, size_t bytesToWrite); //throw FileError; may return short! CONTRACT: bytesToWrite > 0
+
+ void close(); //throw FileError -> optional, but good place to catch errors when closing stream!
+ FileHandle getHandle() { return fileHandle; }
+
private:
FileHandle fileHandle;
};
+
+
+//native stream I/O convenience functions:
+
+template <class BinContainer> inline
+BinContainer loadBinContainer(const Zstring& filePath, //throw FileError
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //optional
+{
+ FileInput streamIn(filePath); //throw FileError, ErrorFileLocked
+ return unbufferedLoad<BinContainer>(streamIn, notifyProgress); //throw FileError
+}
+
+
+template <class BinContainer> inline
+void saveBinContainer(const Zstring& filePath, const BinContainer& buffer, //throw FileError
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //optional
+{
+ FileOutput fileOut(filePath, FileOutput::ACC_OVERWRITE); //
+ unbufferedSave(buffer, fileOut, notifyProgress); //throw FileError
+ fileOut.close(); //
+}
}
#endif //FILE_IO_H_89578342758342572345
diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp
index 7fd6c596..aa39e508 100644
--- a/zen/file_traverser.cpp
+++ b/zen/file_traverser.cpp
@@ -102,9 +102,6 @@ void zen::traverseFolder(const Zstring& dirPath,
entryp = malloc(len); */
const size_t nameMax = std::max<long>(::pathconf(dirPath.c_str(), _PC_NAME_MAX), 10000); //::pathconf may return long(-1)
std::vector<char> buffer(offsetof(struct ::dirent, d_name) + nameMax + 1);
-#ifdef ZEN_MAC
- std::vector<char> bufferUtfDecomposed;
-#endif
DIR* folder = ::opendir(dirPath.c_str()); //directory must NOT end with path separator, except "/"
if (!folder)
@@ -131,26 +128,21 @@ void zen::traverseFolder(const Zstring& dirPath,
(itemNameRaw[1] == 0 || (itemNameRaw[1] == '.' && itemNameRaw[2] == 0)))
continue;
#ifdef ZEN_MAC
- //some file system abstraction layers fail to properly return decomposed UTF8: http://developer.apple.com/library/mac/#qa/qa1173/_index.html
- //so we need to do it ourselves; perf: ~600 ns per conversion
- //note: it's not sufficient to apply this in z_impl::compareFilenamesNoCase: if UTF8 forms differ, FFS assumes a rename in case sensitivity and
- // will try to propagate the rename => this won't work if target drive reports a particular UTF8 form only!
- if (CFStringRef cfStr = osx::createCFString(itemNameRaw))
+ //see native_traverser_impl.h:
+ Zstring itemName;
+ try
{
- ZEN_ON_SCOPE_EXIT(::CFRelease(cfStr));
-
- CFIndex lenMax = ::CFStringGetMaximumSizeOfFileSystemRepresentation(cfStr); //"could be much larger than the actual space required" => don't store in Zstring
- if (lenMax > 0)
- {
- bufferUtfDecomposed.resize(lenMax);
- if (::CFStringGetFileSystemRepresentation(cfStr, &bufferUtfDecomposed[0], lenMax)) //get decomposed UTF form (verified!) despite ambiguous documentation
- itemNameRaw = &bufferUtfDecomposed[0];
- }
+ itemName = osx::convertToPrecomposedUtf(itemNameRaw); //throw SysError
}
- //const char* sampleDecomposed = "\x6f\xcc\x81.txt";
- //const char* samplePrecomposed = "\xc3\xb3.txt";
-#endif
+ catch (const SysError& e) //failure is not an item-level error since wo don't have the proper decomposed name!!!
+ {
+ throw FileError(replaceCpy(_("Cannot enumerate directory %x."), L"%x", fmtPath(dirPath)),
+ L"Failed to generate precomposed file name: " + fmtPath(itemNameRaw) + L"\n" + e.toString()); //too obscure to warrant translation
+ }
+ const Zstring& itemPath = appendSeparator(dirPath) + itemName;
+#else
const Zstring& itemPath = appendSeparator(dirPath) + itemNameRaw;
+#endif
struct ::stat statData = {};
try
diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp
index cb92f1e4..3dfe805b 100644
--- a/zen/format_unit.cpp
+++ b/zen/format_unit.cpp
@@ -403,8 +403,8 @@ Opt<double> zen::utcToMtpVariantTime(std::int64_t utcTime) //returns empty on er
return NoValue();
double localVarTime = 0;
- if (!SystemTimeToVariantTime(&systemTimeLocal, //_In_ LPSYSTEMTIME lpSystemTime,
- &localVarTime)) //_Out_ DOUBLE *pvtime
+ if (!::SystemTimeToVariantTime(&systemTimeLocal, //_In_ LPSYSTEMTIME lpSystemTime,
+ &localVarTime)) //_Out_ DOUBLE *pvtime
return NoValue();
return localVarTime;
diff --git a/zen/guid.h b/zen/guid.h
index 7f247508..e8326ce6 100644
--- a/zen/guid.h
+++ b/zen/guid.h
@@ -8,15 +8,12 @@
#define GUID_H_80425780237502345
#include <string>
-#include <boost/uuid/uuid.hpp>
#ifdef __GNUC__ //boost should clean this mess up
#pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
-
#include <boost/uuid/uuid_generators.hpp>
-
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
diff --git a/zen/i18n.h b/zen/i18n.h
index 3f10ec81..340473f9 100644
--- a/zen/i18n.h
+++ b/zen/i18n.h
@@ -102,7 +102,7 @@ inline
const TranslationHandler*& getTranslationInstance()
{
//avoid static destruction order fiasco: there may be accesses to "getTranslator()" during process shutdown e.g. show message in debug_minidump.cpp!
- //=> use POD instead of a std::unique_ptr<>!!!
+ //=> use POD instead of a std::unique_ptr<>!!!
static const TranslationHandler* inst = nullptr; //external linkage even in header!
return inst;
}
@@ -113,7 +113,7 @@ struct CleanUpTranslationHandler
~CleanUpTranslationHandler()
{
const TranslationHandler*& handler = getTranslationInstance();
- assert(!handler); //clean up at a better time rather than during static destruction! potential MT issues!?
+ assert(!handler); //clean up at a better time rather than during static destruction! potential MT issues!?
delete handler;
handler = nullptr; //getTranslator() may be called even after static objects of this translation unit are destroyed!
}
diff --git a/zen/long_path_prefix.h b/zen/long_path_prefix.h
deleted file mode 100644
index ef8e5dc8..00000000
--- a/zen/long_path_prefix.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
-// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef LONG_PATH_PREFIX_H_3984678473567247567
-#define LONG_PATH_PREFIX_H_3984678473567247567
-
-#include "win.h"
-#include "zstring.h"
-
-
-namespace zen
-{
-//handle filepaths longer-equal 260 (== MAX_PATH) characters by applying \\?\-prefix; see: http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
-/*
-1. path must be absolute
-2. if path is smaller than MAX_PATH nothing is changed! caveat: FindFirstFile() "Prepending the string "\\?\" does not allow access to the root directory."
-3. path may already contain \\?\-prefix
-*/
-Zstring applyLongPathPrefix(const Zstring& path); //noexcept
-Zstring applyLongPathPrefixCreateDir(const Zstring& path); //noexcept -> special rule for ::CreateDirectory()/::CreateDirectoryEx(): MAX_PATH - 12(=^ 8.3 filepath) is threshold
-
-Zstring removeLongPathPrefix(const Zstring& path); //noexcept
-
-
-Zstring ntPathToWin32Path(const Zstring& path); //noexcept
-/*
-http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#NT_Namespaces
-
-As used by GetModuleFileNameEx() and symlinks (FSCTL_GET_REPARSE_POINT):
- E.g.:
- \??\C:\folder -> C:\folder
- \SystemRoot -> C:\Windows
-*/
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-//################## implementation ##################
-
-//there are two flavors of long path prefix: one for UNC paths, one for regular paths
-const wchar_t LONG_PATH_PREFIX [] = L"\\\\?\\"; //don't use Zstring as global constant: avoid static initialization order problem in global namespace!
-const wchar_t LONG_PATH_PREFIX_UNC[] = L"\\\\?\\UNC"; //
-
-template <size_t maxPath> inline
-Zstring applyLongPathPrefixImpl(const Zstring& path)
-{
- assert(!path.empty()); //nicely check almost all WinAPI accesses!
- assert(!zen::isWhiteSpace(path[0]));
-
- //http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#naming_conventions
- /*
- - special names like ".NUL" create all kinds of trouble (e.g. CreateDirectory() reports success, but does nothing)
- unless prefix is supplied => accept as limitation
- */
- if (path.length() >= maxPath || //maximum allowed path length without prefix is (MAX_PATH - 1)
- endsWith(path, L' ') || //by default all Win32 APIs trim trailing spaces and period, unless long path prefix is supplied!
- endsWith(path, L'.')) //note: adding long path prefix might screw up relative paths "." and ".."!
- if (!startsWith(path, LONG_PATH_PREFIX))
- {
- if (startsWith(path, L"\\\\")) //UNC-name, e.g. \\zenju-pc\Users
- return LONG_PATH_PREFIX_UNC + afterFirst(path, L'\\', zen::IF_MISSING_RETURN_NONE); //convert to \\?\UNC\zenju-pc\Users
- else
- return LONG_PATH_PREFIX + path; //prepend \\?\ prefix
- }
- return path; //fallback
-}
-
-
-inline
-Zstring zen::applyLongPathPrefix(const Zstring& path)
-{
- return applyLongPathPrefixImpl<MAX_PATH>(path);
-}
-
-
-inline
-Zstring zen::applyLongPathPrefixCreateDir(const Zstring& path) //noexcept
-{
- //special rule for ::CreateDirectoryEx(): MAX_PATH - 12(=^ 8.3 filepath) is threshold
- return applyLongPathPrefixImpl<MAX_PATH - 12> (path);
-}
-
-
-inline
-Zstring zen::removeLongPathPrefix(const Zstring& path) //noexcept
-{
- if (zen::startsWith(path, LONG_PATH_PREFIX))
- {
- if (zen::startsWith(path, LONG_PATH_PREFIX_UNC)) //UNC-name
- return replaceCpy(path, LONG_PATH_PREFIX_UNC, Zstr("\\"), false);
- else
- return replaceCpy(path, LONG_PATH_PREFIX, Zstr(""), false);
- }
- return path; //fallback
-}
-
-
-inline
-Zstring zen::ntPathToWin32Path(const Zstring& path) //noexcept
-{
- if (startsWith(path, L"\\??\\"))
- return Zstring(path.c_str() + 4, path.length() - 4);
-
- if (startsWith(path, L"\\SystemRoot\\"))
- {
- DWORD bufSize = ::GetEnvironmentVariable(L"SystemRoot", nullptr, 0);
- if (bufSize > 0)
- {
- std::vector<wchar_t> buf(bufSize);
- const DWORD charsWritten = ::GetEnvironmentVariable(L"SystemRoot", //_In_opt_ LPCTSTR lpName,
- &buf[0], //_Out_opt_ LPTSTR lpBuffer,
- bufSize); //_In_ DWORD nSize
- if (0 < charsWritten && charsWritten < bufSize)
- return replaceCpy(path, L"\\SystemRoot\\", appendSeparator(Zstring(&buf[0], charsWritten)), false);
- }
- }
-
- return path;
-}
-
-#endif //LONG_PATH_PREFIX_H_3984678473567247567
diff --git a/zen/scope_guard.h b/zen/scope_guard.h
index 1345447e..67eb3053 100644
--- a/zen/scope_guard.h
+++ b/zen/scope_guard.h
@@ -20,7 +20,7 @@ inline int getUncaughtExceptionCount() { return std::uncaught_exceptions(); }
#elif defined ZEN_LINUX || defined ZEN_MAC
//std::uncaught_exceptions() currently unsupported on GCC and Clang => clean up ASAP
#ifdef ZEN_LINUX
- static_assert(__GNUC__ < 5 || (__GNUC__ == 5 && (__GNUC_MINOR__ < 2 || (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ <= 1))), "check std::uncaught_exceptions support");
+ static_assert(__GNUC__ < 5 || (__GNUC__ == 5 && (__GNUC_MINOR__ < 3 || (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ <= 1))), "check std::uncaught_exceptions support");
#else
static_assert(__clang_major__ < 7 || (__clang_major__ == 7 && __clang_minor__ <= 0), "check std::uncaught_exceptions support");
#endif
@@ -76,7 +76,7 @@ public:
if (!dismissed)
{
#ifdef _MSC_VER
- #pragma warning(suppress: 4127) //"conditional expression is constant"
+#pragma warning(suppress: 4127) //"conditional expression is constant"
#endif
if (runMode != ScopeGuardRunMode::ON_EXIT)
{
@@ -86,7 +86,7 @@ public:
}
#ifdef _MSC_VER
- #pragma warning(suppress: 4127) //"conditional expression is constant"
+#pragma warning(suppress: 4127) //"conditional expression is constant"
#endif
if (runMode == ScopeGuardRunMode::ON_SUCCESS)
fun_(); //throw X
diff --git a/zen/serialize.h b/zen/serialize.h
index 77cf657e..d7b4cd22 100644
--- a/zen/serialize.h
+++ b/zen/serialize.h
@@ -10,7 +10,7 @@
#include <functional>
#include <cstdint>
#include "string_base.h"
-#include "file_io.h"
+//keep header clean from specific stream implementations! (e.g.file_io.h)! used by abstract.h!
namespace zen
@@ -32,8 +32,6 @@ class ByteArray; //ref-counted byte stream + guaranteed per
class ByteArray //essentially a std::vector<char> with ref-counted semantics, but no COW! => *almost* value type semantics, but not quite
{
public:
- ByteArray() : buffer(std::make_shared<std::vector<char>>()) {}
-
typedef std::vector<char>::value_type value_type;
typedef std::vector<char>::iterator iterator;
typedef std::vector<char>::const_iterator const_iterator;
@@ -46,45 +44,78 @@ public:
void resize(size_t len) { buffer->resize(len); }
size_t size() const { return buffer->size(); }
- bool empty() const { return buffer->empty(); }
+ bool empty() const { return buffer->empty(); }
inline friend bool operator==(const ByteArray& lhs, const ByteArray& rhs) { return *lhs.buffer == *rhs.buffer; }
private:
- std::shared_ptr<std::vector<char>> buffer; //always bound!
+ std::shared_ptr<std::vector<char>> buffer { std::make_shared<std::vector<char>>() }; //always bound!
//perf: shared_ptr indirection irrelevant: less than 1% slower!
};
-//----------------------------------------------------------------------
-//functions based on binary container abstraction
-template <class BinContainer> void saveBinStream(const Zstring& filepath, const BinContainer& cont, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus); //throw FileError
-template <class BinContainer> BinContainer loadBinStream(const Zstring& filepath, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus); //throw FileError
+/*
+---------------------------------
+|Unbuffered Input Stream Concept|
+---------------------------------
+struct UnbufferedInputStream
+{
+ size_t getBlockSize();
+ size_t tryRead(void* buffer, size_t bytesToRead); //may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
+};
+
+----------------------------------
+|Unbuffered Output Stream Concept|
+----------------------------------
+struct UnbufferedOutputStream
+{
+ size_t getBlockSize();
+ size_t tryWrite(const void* buffer, size_t bytesToWrite); //may return short! CONTRACT: bytesToWrite > 0
+};
+*/
+//functions based on unbuffered stream abstraction
+
+template <class UnbufferedInputStream, class UnbufferedOutputStream>
+void unbufferedStreamCopy(UnbufferedInputStream& streamIn, UnbufferedOutputStream& streamOut, const std::function<void(std::int64_t bytesDelta)>& notifyProgress); //throw X
+
+template <class BinContainer, class UnbufferedOutputStream>
+void unbufferedSave(const BinContainer& buffer, UnbufferedOutputStream& streamOut, const std::function<void(std::int64_t bytesDelta)>& notifyProgress); //throw X
+template <class BinContainer, class UnbufferedInputStream>
+BinContainer unbufferedLoad(UnbufferedInputStream& streamIn, const std::function<void(std::int64_t bytesDelta)>& notifyProgress); //throw X
/*
------------------------------
-|Binary Input Stream Concept|
------------------------------
-struct BinInputStream
+-------------------------------
+|Buffered Input Stream Concept|
+-------------------------------
+struct BufferedInputStream
{
- size_t read(void* data, size_t len); //return "len" bytes unless end of stream!
+ size_t read(void* buffer, size_t bytesToRead); //return "len" bytes unless end of stream! throw ?
};
-------------------------------
-|Binary Output Stream Concept|
-------------------------------
-struct BinOutputStream
+--------------------------------
+|Buffered Output Stream Concept|
+--------------------------------
+struct BufferedOutputStream
{
- void write(const void* data, size_t len);
+ void write(const void* buffer, size_t bytesToWrite); //throw ?
};
*/
+//functions based on buffered stream abstraction
+template <class N, class BufferedOutputStream> void writeNumber (BufferedOutputStream& stream, const N& num); //
+template <class C, class BufferedOutputStream> void writeContainer(BufferedOutputStream& stream, const C& str); //throw ()
+template < class BufferedOutputStream> void writeArray (BufferedOutputStream& stream, const void* data, size_t len); //
-//binary input/output stream reference implementations:
+//----------------------------------------------------------------------
+class UnexpectedEndOfStreamError {};
+template <class N, class BufferedInputStream> N readNumber (BufferedInputStream& stream); //throw UnexpectedEndOfStreamError (corrupted data)
+template <class C, class BufferedInputStream> C readContainer(BufferedInputStream& stream); //
+template < class BufferedInputStream> void readArray (BufferedInputStream& stream, void* data, size_t len); //
+//buffered input/output stream reference implementations:
template <class BinContainer>
struct MemoryStreamIn
{
- MemoryStreamIn(const BinContainer& cont) : buffer(cont), pos(0) {} //this better be cheap!
+ MemoryStreamIn(const BinContainer& cont) : buffer(cont) {} //this better be cheap!
size_t read(void* data, size_t len) //return "len" bytes unless end of stream!
{
@@ -98,7 +129,7 @@ struct MemoryStreamIn
private:
const BinContainer buffer;
- size_t pos;
+ size_t pos = 0;
};
template <class BinContainer>
@@ -118,21 +149,6 @@ private:
BinContainer buffer;
};
-//----------------------------------------------------------------------
-//functions based on binary stream abstraction
-template <class BinInputStream, class BinOutputStream>
-void copyStream(BinInputStream& streamIn, BinOutputStream& streamOut, const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus); //optional
-
-template <class N, class BinOutputStream> void writeNumber (BinOutputStream& stream, const N& num); //
-template <class C, class BinOutputStream> void writeContainer(BinOutputStream& stream, const C& str); //throw ()
-template < class BinOutputStream> void writeArray (BinOutputStream& stream, const void* data, size_t len); //
-
-//----------------------------------------------------------------------
-class UnexpectedEndOfStreamError {};
-template <class N, class BinInputStream> N readNumber (BinInputStream& stream); //throw UnexpectedEndOfStreamError (corrupted data)
-template <class C, class BinInputStream> C readContainer(BinInputStream& stream); //
-template < class BinInputStream> void readArray (BinInputStream& stream, void* data, size_t len); //
-
@@ -141,67 +157,124 @@ template < class BinInputStream> void readArray (BinInputStream& stre
//-----------------------implementation-------------------------------
-template <class BinInputStream, class BinOutputStream> inline
-void copyStream(BinInputStream& streamIn, BinOutputStream& streamOut, size_t blockSize,
- const std::function<void(std::int64_t bytesDelta)>& onNotifyCopyStatus) //optional
+template <class UnbufferedInputStream, class UnbufferedOutputStream> inline
+void unbufferedStreamCopy(UnbufferedInputStream& streamIn, //throw X
+ UnbufferedOutputStream& streamOut, //
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //optional
{
- assert(blockSize > 0);
- std::vector<char> buffer(blockSize);
+ size_t unevenBytes = 0;
+ auto reportBytesProcessed = [&](size_t bytesReadOrWritten)
+ {
+ if (notifyProgress)
+ {
+ const size_t bytesToReport = (unevenBytes + bytesReadOrWritten) / 2;
+ notifyProgress(bytesToReport); //throw X!
+ unevenBytes = (unevenBytes + bytesReadOrWritten) - bytesToReport * 2; //unsigned arithmetics!
+ }
+ };
+
+ const size_t blockSizeIn = streamIn .getBlockSize();
+ const size_t blockSizeOut = streamOut.getBlockSize();
+ if (blockSizeIn == 0 || blockSizeOut == 0)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
+ std::vector<char> buffer;
for (;;)
{
- const size_t bytesRead = streamIn.read(&buffer[0], buffer.size());
- streamOut.write(&buffer[0], bytesRead);
+ buffer.resize(buffer.size() + blockSizeIn);
+ const size_t bytesRead = streamIn.tryRead(&*(buffer.end() - blockSizeIn), blockSizeIn); //throw X; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
+ buffer.resize(buffer.size() - blockSizeIn + bytesRead); //caveat: unsigned arithmetics
+
+ reportBytesProcessed(bytesRead); //throw X!
- if (onNotifyCopyStatus)
- onNotifyCopyStatus(bytesRead); //throw X!
+ size_t bytesRemaining = buffer.size();
+ while (bytesRemaining >= blockSizeOut)
+ {
+ const size_t bytesWritten = streamOut.tryWrite(&*(buffer.end() - bytesRemaining), blockSizeOut); //throw X; may return short! CONTRACT: bytesToWrite > 0
+ bytesRemaining -= bytesWritten;
+ reportBytesProcessed(bytesWritten); //throw X!
+ }
+ buffer.erase(buffer.begin(), buffer.end() - bytesRemaining);
- if (bytesRead != buffer.size()) //end of file
+ if (bytesRead == 0) //end of file
break;
}
+
+ for (size_t bytesRemaining = buffer.size(); bytesRemaining > 0;)
+ {
+ const size_t bytesWritten = streamOut.tryWrite(&*(buffer.end() - bytesRemaining), bytesRemaining); //throw X; may return short! CONTRACT: bytesToWrite > 0
+ bytesRemaining -= bytesWritten;
+ reportBytesProcessed(bytesWritten); //throw X!
+ }
+
+ if (unevenBytes != 0)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
}
-template <class BinContainer> inline
-void saveBinStream(const Zstring& filepath, //throw FileError
- const BinContainer& cont,
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //optional
+template <class BinContainer, class UnbufferedOutputStream> inline
+void unbufferedSave(const BinContainer& buffer,
+ UnbufferedOutputStream& streamOut, //throw X
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //optional
{
- MemoryStreamIn<BinContainer> streamIn(cont);
- FileOutput streamOut(filepath, zen::FileOutput::ACC_OVERWRITE); //throw FileError, (ErrorTargetExisting)
- if (onUpdateStatus) onUpdateStatus(0); //throw X!
- copyStream(streamIn, streamOut, streamOut.optimalBlockSize(), onUpdateStatus); //throw FileError
+ const size_t blockSize = streamOut.getBlockSize();
+ if (blockSize == 0)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
+ static_assert(sizeof(typename BinContainer::value_type) == 1, ""); //expect: bytes
+
+ for (size_t bytesRemaining = buffer.size(); bytesRemaining > 0;)
+ {
+ const size_t bytesToWrite = std::min(bytesRemaining, blockSize);
+ const size_t bytesWritten = streamOut.tryWrite(&*(buffer.end() - bytesRemaining), bytesToWrite); //throw X; may return short! CONTRACT: bytesToWrite > 0
+ bytesRemaining -= bytesWritten;
+ if (notifyProgress) notifyProgress(bytesWritten); //throw X!
+ }
}
-template <class BinContainer> inline
-BinContainer loadBinStream(const Zstring& filepath, //throw FileError
- const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //optional
+template <class BinContainer, class UnbufferedInputStream> inline
+BinContainer unbufferedLoad(UnbufferedInputStream& streamIn, //throw X
+ const std::function<void(std::int64_t bytesDelta)>& notifyProgress) //optional
{
- FileInput streamIn(filepath); //throw FileError, ErrorFileLocked
- if (onUpdateStatus) onUpdateStatus(0); //throw X!
- MemoryStreamOut<BinContainer> streamOut;
- copyStream(streamIn, streamOut, streamIn.optimalBlockSize(), onUpdateStatus); //throw FileError
- return streamOut.ref();
+ const size_t blockSize = streamIn.getBlockSize();
+ if (blockSize == 0)
+ throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+
+ static_assert(sizeof(typename BinContainer::value_type) == 1, ""); //expect: bytes
+
+ BinContainer buffer;
+ for (;;)
+ {
+ buffer.resize(buffer.size() + blockSize);
+ const size_t bytesRead = streamIn.tryRead(&*(buffer.end() - blockSize), blockSize); //throw X; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
+ buffer.resize(buffer.size() - blockSize + bytesRead); //caveat: unsigned arithmetics
+
+ if (notifyProgress) notifyProgress(bytesRead); //throw X!
+
+ if (bytesRead == 0) //end of file
+ return buffer;
+ }
}
-template <class BinOutputStream> inline
-void writeArray(BinOutputStream& stream, const void* data, size_t len)
+template <class BufferedOutputStream> inline
+void writeArray(BufferedOutputStream& stream, const void* data, size_t len)
{
stream.write(data, len);
}
-template <class N, class BinOutputStream> inline
-void writeNumber(BinOutputStream& stream, const N& num)
+template <class N, class BufferedOutputStream> inline
+void writeNumber(BufferedOutputStream& stream, const N& num)
{
static_assert(IsArithmetic<N>::value || IsSameType<N, bool>::value, "");
writeArray(stream, &num, sizeof(N));
}
-template <class C, class BinOutputStream> inline
-void writeContainer(BinOutputStream& stream, const C& cont) //don't even consider UTF8 conversions here, we're handling arbitrary binary data!
+template <class C, class BufferedOutputStream> inline
+void writeContainer(BufferedOutputStream& stream, const C& cont) //don't even consider UTF8 conversions here, we're handling arbitrary binary data!
{
const auto len = cont.size();
writeNumber(stream, static_cast<std::uint32_t>(len));
@@ -210,8 +283,8 @@ void writeContainer(BinOutputStream& stream, const C& cont) //don't even conside
}
-template <class BinInputStream> inline
-void readArray(BinInputStream& stream, void* data, size_t len) //throw UnexpectedEndOfStreamError
+template <class BufferedInputStream> inline
+void readArray(BufferedInputStream& stream, void* data, size_t len) //throw UnexpectedEndOfStreamError
{
const size_t bytesRead = stream.read(data, len);
if (bytesRead < len)
@@ -219,8 +292,8 @@ void readArray(BinInputStream& stream, void* data, size_t len) //throw Unexpecte
}
-template <class N, class BinInputStream> inline
-N readNumber(BinInputStream& stream) //throw UnexpectedEndOfStreamError
+template <class N, class BufferedInputStream> inline
+N readNumber(BufferedInputStream& stream) //throw UnexpectedEndOfStreamError
{
static_assert(IsArithmetic<N>::value || IsSameType<N, bool>::value, "");
N num = 0;
@@ -229,8 +302,8 @@ N readNumber(BinInputStream& stream) //throw UnexpectedEndOfStreamError
}
-template <class C, class BinInputStream> inline
-C readContainer(BinInputStream& stream) //throw UnexpectedEndOfStreamError
+template <class C, class BufferedInputStream> inline
+C readContainer(BufferedInputStream& stream) //throw UnexpectedEndOfStreamError
{
C cont;
auto strLength = readNumber<std::uint32_t>(stream);
diff --git a/zen/shell_execute.h b/zen/shell_execute.h
index 9b8e00f9..e6dcf7f5 100644
--- a/zen/shell_execute.h
+++ b/zen/shell_execute.h
@@ -82,12 +82,14 @@ void shellExecute(const Zstring& command, ExecutionType type) //throw FileError
trim(commandTmp, true, false); //CommandLineToArgvW() does not like leading spaces
std::vector<Zstring> argv;
- int argc = 0;
- if (LPWSTR* tmp = ::CommandLineToArgvW(commandTmp.c_str(), &argc))
- {
+ {
+ int argc = 0;
+ LPWSTR* tmp = ::CommandLineToArgvW(commandTmp.c_str(), &argc);
+ if (!tmp)
+ THROW_LAST_FILE_ERROR(_("Incorrect command line:") + L"\n" + commandTmp.c_str(), L"CommandLineToArgvW");
ZEN_ON_SCOPE_EXIT(::LocalFree(tmp));
std::copy(tmp, tmp + argc, std::back_inserter(argv));
- }
+ }
Zstring filepath;
Zstring arguments;
@@ -106,7 +108,7 @@ void shellExecute(const Zstring& command, ExecutionType type) //throw FileError
};
if (!shellExecuteImpl(fillExecInfo, type))
- THROW_LAST_FILE_ERROR(_("Incorrect command line:") + L"\nFile: " + fmtPath(filepath) + L"\nArg: " + copyStringTo<std::wstring>(arguments), L"ShellExecuteEx");
+ THROW_LAST_FILE_ERROR(_("Incorrect command line:") + L"\nFile: " + fmtPath(filepath) + L"\nArg: " + arguments.c_str(), L"ShellExecuteEx");
#elif defined ZEN_LINUX || defined ZEN_MAC
/*
diff --git a/zen/string_base.h b/zen/string_base.h
index 96d46fc4..365e359e 100644
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -266,6 +266,7 @@ public:
void resize(size_t newSize, Char fillChar = 0);
void swap(Zbase& other);
void push_back(Char val) { operator+=(val); } //STL access
+ void pop_back();
Zbase& operator=(const Zbase& source);
Zbase& operator=(Zbase&& tmp) noexcept;
@@ -684,6 +685,16 @@ Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator+=(Char ch)
{
return append(&ch, 1);
}
+
+
+template <class Char, template <class, class> class SP, class AP> inline
+void Zbase<Char, SP, AP>::pop_back()
+{
+ const size_t len = length();
+ assert(len > 0);
+ if (len > 0)
+ resize(len - 1);
+}
}
#endif //STRING_BASE_H_083217454562342526
diff --git a/zen/string_tools.h b/zen/string_tools.h
index fc9fe806..92ca1654 100644
--- a/zen/string_tools.h
+++ b/zen/string_tools.h
@@ -77,6 +77,7 @@ template <class T, class S> T copyStringTo(S&& str);
template <> inline
bool isWhiteSpace(char ch)
{
+ assert(ch != 0); //std C++ does not consider 0 as white space
//caveat 1: std::isspace() takes an int, but expects an unsigned char
//caveat 2: some parts of UTF-8 chars are erroneously seen as whitespace, e.g. the a0 from "\xec\x8b\xa0" (MSVC)
return static_cast<unsigned char>(ch) < 128 &&
@@ -84,7 +85,11 @@ bool isWhiteSpace(char ch)
}
template <> inline
-bool isWhiteSpace(wchar_t ch) { return std::iswspace(ch) != 0; }
+bool isWhiteSpace(wchar_t ch)
+{
+ assert(ch != 0); //std C++ does not consider 0 as white space
+ return std::iswspace(ch) != 0;
+}
template <class Char> inline
@@ -402,7 +407,7 @@ template <class S, class T, class Num> inline
S printNumber(const T& format, const Num& number) //format a single number using ::sprintf
{
static_assert(IsSameType<typename GetCharType<S>::Type, typename GetCharType<T>::Type>::value, "");
- using CharType = typename GetCharType<S>::Type;
+ using CharType = typename GetCharType<S>::Type;
const int BUFFER_SIZE = 128;
CharType buffer[BUFFER_SIZE]; //zero-initialize?
@@ -426,7 +431,7 @@ enum NumberType
template <class S, class Num> inline
S numberTo(const Num& number, Int2Type<NUM_TYPE_OTHER>) //default number to string conversion using streams: convenient, but SLOW, SLOW, SLOW!!!! (~ factor of 20)
{
- using CharType = typename GetCharType<S>::Type;
+ using CharType = typename GetCharType<S>::Type;
std::basic_ostringstream<CharType> ss;
ss << number;
@@ -455,7 +460,7 @@ template <class OutputIterator, class Num> inline
void formatNegativeInteger(Num n, OutputIterator& it)
{
assert(n < 0);
- using CharType = typename std::iterator_traits<OutputIterator>::value_type;
+ using CharType = typename std::iterator_traits<OutputIterator>::value_type;
do
{
const Num tmp = n / 10;
@@ -471,7 +476,7 @@ template <class OutputIterator, class Num> inline
void formatPositiveInteger(Num n, OutputIterator& it)
{
assert(n >= 0);
- using CharType = typename std::iterator_traits<OutputIterator>::value_type;
+ using CharType = typename std::iterator_traits<OutputIterator>::value_type;
do
{
const Num tmp = n / 10;
@@ -487,7 +492,7 @@ S numberTo(const Num& number, Int2Type<NUM_TYPE_SIGNED_INT>)
{
using CharType = typename GetCharType<S>::Type;
CharType buffer[2 + sizeof(Num) * 241 / 100]; //zero-initialize?
- //it's generally faster to use a buffer than to rely on String::operator+=() (in)efficiency
+ //it's generally faster to use a buffer than to rely on String::operator+=() (in)efficiency
//required chars (+ sign char): 1 + ceil(ln_10(256^sizeof(n) / 2 + 1)) -> divide by 2 for signed half-range; second +1 since one half starts with 1!
// <= 1 + ceil(ln_10(256^sizeof(n))) =~ 1 + ceil(sizeof(n) * 2.4082) <= 2 + floor(sizeof(n) * 2.41)
@@ -506,7 +511,7 @@ S numberTo(const Num& number, Int2Type<NUM_TYPE_SIGNED_INT>)
template <class S, class Num> inline
S numberTo(const Num& number, Int2Type<NUM_TYPE_UNSIGNED_INT>)
{
- using CharType = typename GetCharType<S>::Type;
+ using CharType = typename GetCharType<S>::Type;
CharType buffer[1 + sizeof(Num) * 241 / 100]; //zero-initialize?
//required chars: ceil(ln_10(256^sizeof(n))) =~ ceil(sizeof(n) * 2.4082) <= 1 + floor(sizeof(n) * 2.41)
@@ -522,7 +527,7 @@ S numberTo(const Num& number, Int2Type<NUM_TYPE_UNSIGNED_INT>)
template <class Num, class S> inline
Num stringTo(const S& str, Int2Type<NUM_TYPE_OTHER>) //default string to number conversion using streams: convenient, but SLOW
{
- using CharType = typename GetCharType<S>::Type;
+ using CharType = typename GetCharType<S>::Type;
Num number = 0;
std::basic_istringstream<CharType>(copyStringTo<std::basic_string<CharType>>(str)) >> number;
return number;
@@ -541,8 +546,8 @@ Num stringTo(const S& str, Int2Type<NUM_TYPE_FLOATING_POINT>)
template <class Num, class S>
Num extractInteger(const S& str, bool& hasMinusSign) //very fast conversion to integers: slightly faster than std::atoi, but more importantly: generic
{
- using CharType = typename GetCharType<S>::Type;
-
+ using CharType = typename GetCharType<S>::Type;
+
const CharType* first = strBegin(str);
const CharType* last = first + strLength(str);
@@ -610,10 +615,10 @@ template <class S, class Num> inline
S numberTo(const Num& number)
{
using TypeTag = Int2Type<
- IsSignedInt <Num>::value ? impl::NUM_TYPE_SIGNED_INT :
- IsUnsignedInt<Num>::value ? impl::NUM_TYPE_UNSIGNED_INT :
- IsFloat <Num>::value ? impl::NUM_TYPE_FLOATING_POINT :
- impl::NUM_TYPE_OTHER>;
+ IsSignedInt <Num>::value ? impl::NUM_TYPE_SIGNED_INT :
+ IsUnsignedInt<Num>::value ? impl::NUM_TYPE_UNSIGNED_INT :
+ IsFloat <Num>::value ? impl::NUM_TYPE_FLOATING_POINT :
+ impl::NUM_TYPE_OTHER>;
return impl::numberTo<S>(number, TypeTag());
}
@@ -623,10 +628,10 @@ template <class Num, class S> inline
Num stringTo(const S& str)
{
using TypeTag = Int2Type<
- IsSignedInt <Num>::value ? impl::NUM_TYPE_SIGNED_INT :
- IsUnsignedInt<Num>::value ? impl::NUM_TYPE_UNSIGNED_INT :
- IsFloat <Num>::value ? impl::NUM_TYPE_FLOATING_POINT :
- impl::NUM_TYPE_OTHER>;
+ IsSignedInt <Num>::value ? impl::NUM_TYPE_SIGNED_INT :
+ IsUnsignedInt<Num>::value ? impl::NUM_TYPE_UNSIGNED_INT :
+ IsFloat <Num>::value ? impl::NUM_TYPE_FLOATING_POINT :
+ impl::NUM_TYPE_OTHER>;
return impl::stringTo<Num>(str, TypeTag());
}
diff --git a/zen/thread.h b/zen/thread.h
index 700d42dc..f747f965 100644
--- a/zen/thread.h
+++ b/zen/thread.h
@@ -181,9 +181,9 @@ auto runAsync(Function&& fun)
template<class InputIterator, class Duration> inline
bool wait_for_all_timed(InputIterator first, InputIterator last, const Duration& duration)
{
- const std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now() + duration;
+ const std::chrono::steady_clock::time_point stopTime = std::chrono::steady_clock::now() + duration;
for (; first != last; ++first)
- if (first->wait_until(endTime) != std::future_status::ready)
+ if (first->wait_until(stopTime) != std::future_status::ready)
return false; //time elapsed
return true;
}
diff --git a/zen/win.h b/zen/win.h
deleted file mode 100644
index 8c1a1c7b..00000000
--- a/zen/win.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// **************************************************************************
-// * This file is part of the FreeFileSync project. It is distributed under *
-// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
-// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
-// **************************************************************************
-
-#ifndef WIN_H_8701570183560183247891346363457
-#define WIN_H_8701570183560183247891346363457
-
-#ifndef _WINSOCKAPI_ //prevent inclusion of winsock.h in windows.h: obsoleted by and conflicting with winsock2.h
- #define _WINSOCKAPI_
-#endif
-
-//------------------------------------------------------
-#ifdef __WXMSW__ //we have wxWidgets
- #include <wx/msw/wrapwin.h> //includes "windows.h"
- //------------------------------------------------------
-#else
- //#define WIN32_LEAN_AND_MEAN
-
- #ifndef NOMINMAX
- #define NOMINMAX
- #endif
-
- #ifndef STRICT
- #define STRICT //improve type checking
- #endif
-
- #include <windows.h>
-#endif
-//------------------------------------------------------
-
-#endif //WIN_H_8701570183560183247891346363457
diff --git a/zen/xml_io.cpp b/zen/xml_io.cpp
index 5b2cfdca..ae69ade4 100644
--- a/zen/xml_io.cpp
+++ b/zen/xml_io.cpp
@@ -7,35 +7,42 @@
#include "xml_io.h"
#include "file_access.h"
#include "file_io.h"
-#include "serialize.h"
using namespace zen;
XmlDoc zen::loadXmlDocument(const Zstring& filepath) //throw FileError
{
- //can't simply use zen::loadBinStream() due to the short-circuit xml-validation below!
+ //can't simply use zen::unbufferedLoad) due to the short-circuit xml-validation below!
- FileInput fileStreamIn(filepath); //throw FileError
- MemoryStreamOut<std::string> memStreamOut;
- {
- //quick test whether input is an XML: avoid loading large binary files up front!
- const std::string xmlBegin = "<?xml version=";
- std::vector<char> buf(xmlBegin.size() + strLength(BYTE_ORDER_MARK_UTF8));
+ FileInput fileIn(filepath); //throw FileError, ErrorFileLocked
+ const size_t blockSize = fileIn.getBlockSize();
+ const std::string xmlPrefix = "<?xml version=";
+ bool xmlPrefixChecked = false;
- const size_t bytesRead = fileStreamIn.read(&buf[0], buf.size());
- memStreamOut.write(&buf[0], bytesRead);
+ std::string buffer;
+ for (;;)
+ {
+ buffer.resize(buffer.size() + blockSize);
+ const size_t bytesRead = fileIn.tryRead(&*(buffer.end() - blockSize), blockSize); //throw X; may return short, only 0 means EOF! => CONTRACT: bytesToRead > 0
+ buffer.resize(buffer.size() - blockSize + bytesRead); //caveat: unsigned arithmetics
- if (!startsWith(memStreamOut.ref(), xmlBegin) &&
- !startsWith(memStreamOut.ref(), BYTE_ORDER_MARK_UTF8 + xmlBegin)) //allow BOM!
- throw FileError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtPath(filepath)));
+ //quick test whether input is an XML: avoid loading large binary files up front!
+ if (!xmlPrefixChecked && buffer.size() >= xmlPrefix.size() + strLength(BYTE_ORDER_MARK_UTF8))
+ {
+ xmlPrefixChecked = true;
+ if (!startsWith(buffer, xmlPrefix) &&
+ !startsWith(buffer, BYTE_ORDER_MARK_UTF8 + xmlPrefix)) //allow BOM!
+ throw FileError(replaceCpy(_("File %x does not contain a valid configuration."), L"%x", fmtPath(filepath)));
+ }
+
+ if (bytesRead == 0) //end of file
+ break;
}
- copyStream(fileStreamIn, memStreamOut, fileStreamIn.optimalBlockSize(), nullptr); //throw FileError
-
try
{
- return parse(memStreamOut.ref()); //throw XmlParsingError
+ return parse(buffer); //throw XmlParsingError
}
catch (const XmlParsingError& e)
{
@@ -50,19 +57,18 @@ XmlDoc zen::loadXmlDocument(const Zstring& filepath) //throw FileError
void zen::saveXmlDocument(const XmlDoc& doc, const Zstring& filepath) //throw FileError
{
- std::string stream = serialize(doc); //noexcept
+ const std::string stream = serialize(doc); //noexcept
//only update xml file if there are real changes
try
{
if (getFilesize(filepath) == stream.size()) //throw FileError
- if (loadBinStream<std::string>(filepath, nullptr) == stream) //throw FileError
+ if (loadBinContainer<std::string>(filepath, nullptr) == stream) //throw FileError
return;
}
catch (FileError&) {}
- FileOutput outputFile(filepath, FileOutput::ACC_OVERWRITE); //throw FileError
- outputFile.write(stream.c_str(), stream.length()); //
+ saveBinContainer(filepath, stream, nullptr); //throw FileError
}
diff --git a/zen/zstring.cpp b/zen/zstring.cpp
index 59f15f19..6d249e70 100644
--- a/zen/zstring.cpp
+++ b/zen/zstring.cpp
@@ -8,8 +8,7 @@
#include <stdexcept>
#ifdef ZEN_WIN
- #include "dll.h"
- //#include "win_ver.h"
+ #include "win.h"
#endif
using namespace zen;
@@ -37,80 +36,67 @@ time per call | function
#ifdef ZEN_WIN
-namespace
-{
-//try to call "CompareStringOrdinal" for low-level string comparison: unfortunately available not before Windows Vista!
-//by a factor ~3 faster than old string comparison using "LCMapString"
-typedef int (WINAPI* CompareStringOrdinalFunc)(LPCWSTR lpString1, int cchCount1,
- LPCWSTR lpString2, int cchCount2, BOOL bIgnoreCase);
-const SysDllFun<CompareStringOrdinalFunc> compareStringOrdinal = SysDllFun<CompareStringOrdinalFunc>(L"kernel32.dll", "CompareStringOrdinal");
-//watch for dependencies in global namespace!!!
-}
-
-
int cmpStringNoCase(const wchar_t* lhs, size_t lhsLen, const wchar_t* rhs, size_t rhsLen)
{
assert(std::find(lhs, lhs + lhsLen, 0) == lhs + lhsLen); //don't expect embedded nulls!
assert(std::find(rhs, rhs + rhsLen, 0) == rhs + rhsLen); //
- if (compareStringOrdinal) //this additional test has no noticeable performance impact
+#ifdef ZEN_WIN_VISTA_AND_LATER
+ //"CompareStringOrdinal" (available since Windows Vista) is by a factor ~3 faster than old string comparison using "LCMapString"
+ const int rv = ::CompareStringOrdinal(lhs, //__in LPCWSTR lpString1,
+ static_cast<int>(lhsLen), //__in int cchCount1,
+ rhs, //__in LPCWSTR lpString2,
+ static_cast<int>(rhsLen), //__in int cchCount2,
+ true); //__in BOOL bIgnoreCase
+ if (rv <= 0)
+ throw std::runtime_error("Error comparing strings (CompareStringOrdinal). " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ else
+ return rv - 2; //convert to C-style string compare result
+#else
+ //do NOT use "CompareString"; this function is NOT meant for file name comparisons (even with LOCALE_INVARIANT and SORT_STRINGSORT): for example "weiß" == "weiss"!!!
+ //the only reliable way to compare filepaths (with XP) is to call "CharUpper" or "LCMapString":
+
+ const auto minSize = std::min(lhsLen, rhsLen);
+
+ if (minSize == 0) //LCMapString does not allow input sizes of 0!
+ return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
+
+ auto copyToUpperCase = [minSize](const wchar_t* strIn, wchar_t* strOut)
+ {
+ //faster than CharUpperBuff + wmemcpy or CharUpper + wmemcpy and same speed like ::CompareString()
+ if (::LCMapString(LOCALE_INVARIANT, //__in LCID Locale,
+ LCMAP_UPPERCASE, //__in DWORD dwMapFlags,
+ strIn, //__in LPCTSTR lpSrcStr,
+ static_cast<int>(minSize), //__in int cchSrc,
+ strOut, //__out LPTSTR lpDestStr,
+ static_cast<int>(minSize)) == 0) //__in int cchDest
+ throw std::runtime_error("Error comparing strings (LCMapString). " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
+ };
+
+ auto eval = [&](wchar_t* bufL, wchar_t* bufR)
+ {
+ copyToUpperCase(lhs, bufL);
+ copyToUpperCase(rhs, bufR);
+
+ const int rv = ::wcsncmp(bufL, bufR, minSize);
+ if (rv != 0)
+ return rv;
+
+ return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
+ };
+
+ if (minSize <= MAX_PATH) //performance optimization: stack
{
- const int rv = compareStringOrdinal(lhs, //__in LPCWSTR lpString1,
- static_cast<int>(lhsLen), //__in int cchCount1,
- rhs, //__in LPCWSTR lpString2,
- static_cast<int>(rhsLen), //__in int cchCount2,
- true); //__in BOOL bIgnoreCase
- if (rv <= 0)
- throw std::runtime_error("Error comparing strings (CompareStringOrdinal). " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
- else
- return rv - 2; //convert to C-style string compare result
+ wchar_t bufferL[MAX_PATH] = {};
+ wchar_t bufferR[MAX_PATH] = {};
+ return eval(bufferL, bufferR);
}
- else //fallback
+ else //use freestore
{
- //do NOT use "CompareString"; this function is NOT accurate (even with LOCALE_INVARIANT and SORT_STRINGSORT): for example "weiß" == "weiss"!!!
- //the only reliable way to compare filepaths (with XP) is to call "CharUpper" or "LCMapString":
-
- const auto minSize = std::min(lhsLen, rhsLen);
-
- if (minSize == 0) //LCMapString does not allow input sizes of 0!
- return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
-
- auto copyToUpperCase = [minSize](const wchar_t* strIn, wchar_t* strOut)
- {
- //faster than CharUpperBuff + wmemcpy or CharUpper + wmemcpy and same speed like ::CompareString()
- if (::LCMapString(LOCALE_INVARIANT, //__in LCID Locale,
- LCMAP_UPPERCASE, //__in DWORD dwMapFlags,
- strIn, //__in LPCTSTR lpSrcStr,
- static_cast<int>(minSize), //__in int cchSrc,
- strOut, //__out LPTSTR lpDestStr,
- static_cast<int>(minSize)) == 0) //__in int cchDest
- throw std::runtime_error("Error comparing strings (LCMapString). " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
- };
-
- auto eval = [&](wchar_t* bufL, wchar_t* bufR)
- {
- copyToUpperCase(lhs, bufL);
- copyToUpperCase(rhs, bufR);
-
- const int rv = ::wcsncmp(bufL, bufR, minSize);
- if (rv != 0)
- return rv;
-
- return static_cast<int>(lhsLen) - static_cast<int>(rhsLen);
- };
-
- if (minSize <= MAX_PATH) //performance optimization: stack
- {
- wchar_t bufferL[MAX_PATH] = {};
- wchar_t bufferR[MAX_PATH] = {};
- return eval(bufferL, bufferR);
- }
- else //use freestore
- {
- std::vector<wchar_t> buffer(2 * minSize);
- return eval(&buffer[0], &buffer[minSize]);
- }
+ std::vector<wchar_t> buffer(2 * minSize);
+ return eval(&buffer[0], &buffer[minSize]);
}
+#endif
}
bgstack15