diff options
author | Daniel Wilhelm <daniel@wili.li> | 2016-03-16 21:34:59 +0100 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2016-03-16 21:34:59 +0100 |
commit | 339ed7f63798fb5ccab05fa7fb9d0d95743c9c89 (patch) | |
tree | 214819f601b69bfd32507ca59047dd4d68ed5632 | |
parent | 7.9 (diff) | |
download | FreeFileSync-339ed7f63798fb5ccab05fa7fb9d0d95743c9c89.tar.gz FreeFileSync-339ed7f63798fb5ccab05fa7fb9d0d95743c9c89.tar.bz2 FreeFileSync-339ed7f63798fb5ccab05fa7fb9d0d95743c9c89.zip |
8.0
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, "%item_path%"</span>, on Linux <span class="command-line">xdg-open "%item_folder%"</span> and on OS X <span class="command-line">open -R "%item_path%"</span>. + To customize this behavior and integrate other external applications into FreeFileSync, + navigate to <b>Menu → Tools → 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 → Tools → 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">"C:\Program Files (x86)\WinMerge\WinMergeU.exe" "%item_path%" "%item2_path%"</div><br> <li>Show file in Windows Explorer:<br> @@ -61,8 +65,11 @@ <li>Open file with associated application:<br> <div class="command-line">"%item_path%"</div><br> - <li>Open console for directory:<br> - <div class="command-line">cmd /k cd /D "%item_folder%"</div> + <li>Open Command Prompt for selected item:<br> + <div class="command-line">cmd /k cd /D "%item_folder%"</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 Binary files differindex 049fcf6b..916447e8 100644 --- a/FreeFileSync/Build/Help/images/add-folder-pair.png +++ b/FreeFileSync/Build/Help/images/add-folder-pair.png diff --git a/FreeFileSync/Build/Help/images/basic-step-choose-folders.png b/FreeFileSync/Build/Help/images/basic-step-choose-folders.png Binary files differindex deeceeff..27c897b2 100644 --- a/FreeFileSync/Build/Help/images/basic-step-choose-folders.png +++ b/FreeFileSync/Build/Help/images/basic-step-choose-folders.png diff --git a/FreeFileSync/Build/Help/images/basic-step-compare.png b/FreeFileSync/Build/Help/images/basic-step-compare.png Binary files differindex 01095864..704fd4fa 100644 --- a/FreeFileSync/Build/Help/images/basic-step-compare.png +++ b/FreeFileSync/Build/Help/images/basic-step-compare.png diff --git a/FreeFileSync/Build/Help/images/basic-step-start-sync.png b/FreeFileSync/Build/Help/images/basic-step-start-sync.png Binary files differindex f7574691..f7309bfc 100644 --- a/FreeFileSync/Build/Help/images/basic-step-start-sync.png +++ b/FreeFileSync/Build/Help/images/basic-step-start-sync.png diff --git a/FreeFileSync/Build/Help/images/basic-step-sync-config.png b/FreeFileSync/Build/Help/images/basic-step-sync-config.png Binary files differindex 5895099c..6656c437 100644 --- a/FreeFileSync/Build/Help/images/basic-step-sync-config.png +++ b/FreeFileSync/Build/Help/images/basic-step-sync-config.png diff --git a/FreeFileSync/Build/Help/images/com-settings-context.png b/FreeFileSync/Build/Help/images/com-settings-context.png Binary files differindex 75068d22..8024d4bf 100644 --- a/FreeFileSync/Build/Help/images/com-settings-context.png +++ b/FreeFileSync/Build/Help/images/com-settings-context.png diff --git a/FreeFileSync/Build/Help/images/comparison-settings.png b/FreeFileSync/Build/Help/images/comparison-settings.png Binary files differindex c224dae4..4ea72934 100644 --- a/FreeFileSync/Build/Help/images/comparison-settings.png +++ b/FreeFileSync/Build/Help/images/comparison-settings.png diff --git a/FreeFileSync/Build/Help/images/comparison-variant-double-click.png b/FreeFileSync/Build/Help/images/comparison-variant-double-click.png Binary files differindex 8fde4654..8af50d42 100644 --- a/FreeFileSync/Build/Help/images/comparison-variant-double-click.png +++ b/FreeFileSync/Build/Help/images/comparison-variant-double-click.png diff --git a/FreeFileSync/Build/Help/images/config-double-click.png b/FreeFileSync/Build/Help/images/config-double-click.png Binary files differindex 6019e1db..54ec22d3 100644 --- a/FreeFileSync/Build/Help/images/config-double-click.png +++ b/FreeFileSync/Build/Help/images/config-double-click.png diff --git a/FreeFileSync/Build/Help/images/config-multiple-selection.png b/FreeFileSync/Build/Help/images/config-multiple-selection.png Binary files differindex ea6907d0..8e26b523 100644 --- a/FreeFileSync/Build/Help/images/config-multiple-selection.png +++ b/FreeFileSync/Build/Help/images/config-multiple-selection.png diff --git a/FreeFileSync/Build/Help/images/dialog-drag-move.png b/FreeFileSync/Build/Help/images/dialog-drag-move.png Binary files differindex df38ef4a..b1f9cda3 100644 --- a/FreeFileSync/Build/Help/images/dialog-drag-move.png +++ b/FreeFileSync/Build/Help/images/dialog-drag-move.png diff --git a/FreeFileSync/Build/Help/images/direct-synchronize.png b/FreeFileSync/Build/Help/images/direct-synchronize.png Binary files differindex bdaa0bf1..f3fdbe1f 100644 --- a/FreeFileSync/Build/Help/images/direct-synchronize.png +++ b/FreeFileSync/Build/Help/images/direct-synchronize.png diff --git a/FreeFileSync/Build/Help/images/filter-context.png b/FreeFileSync/Build/Help/images/filter-context.png Binary files differindex 3e31f2c6..94ce3237 100644 --- a/FreeFileSync/Build/Help/images/filter-context.png +++ b/FreeFileSync/Build/Help/images/filter-context.png diff --git a/FreeFileSync/Build/Help/images/gnome-scheduler.png b/FreeFileSync/Build/Help/images/gnome-scheduler.png Binary files differindex 99ac0abe..fee122bd 100644 --- a/FreeFileSync/Build/Help/images/gnome-scheduler.png +++ b/FreeFileSync/Build/Help/images/gnome-scheduler.png diff --git a/FreeFileSync/Build/Help/images/ignore-time-shift.png b/FreeFileSync/Build/Help/images/ignore-time-shift.png Binary files differindex 5dbeb0ae..4c19e893 100644 --- a/FreeFileSync/Build/Help/images/ignore-time-shift.png +++ b/FreeFileSync/Build/Help/images/ignore-time-shift.png diff --git a/FreeFileSync/Build/Help/images/main-window.png b/FreeFileSync/Build/Help/images/main-window.png Binary files differindex 5fbbca9f..b4e5b034 100644 --- a/FreeFileSync/Build/Help/images/main-window.png +++ b/FreeFileSync/Build/Help/images/main-window.png diff --git a/FreeFileSync/Build/Help/images/path-by-volume-name.png b/FreeFileSync/Build/Help/images/path-by-volume-name.png Binary files differindex 2e606e25..7b0ab2e9 100644 --- a/FreeFileSync/Build/Help/images/path-by-volume-name.png +++ b/FreeFileSync/Build/Help/images/path-by-volume-name.png diff --git a/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png b/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png Binary files differindex 4df9413b..c0910bf7 100644 --- a/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png +++ b/FreeFileSync/Build/Help/images/realtimesync-create-shortcut.png diff --git a/FreeFileSync/Build/Help/images/realtimesync-logo.png b/FreeFileSync/Build/Help/images/realtimesync-logo.png Binary files differindex b5aba408..40ad9645 100644 --- a/FreeFileSync/Build/Help/images/realtimesync-logo.png +++ b/FreeFileSync/Build/Help/images/realtimesync-logo.png diff --git a/FreeFileSync/Build/Help/images/realtimesync-main-window.png b/FreeFileSync/Build/Help/images/realtimesync-main-window.png Binary files differindex ded56422..326cda46 100644 --- a/FreeFileSync/Build/Help/images/realtimesync-main-window.png +++ b/FreeFileSync/Build/Help/images/realtimesync-main-window.png diff --git a/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png b/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png Binary files differindex 0aadf3b6..68413b6e 100644 --- a/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png +++ b/FreeFileSync/Build/Help/images/realtimesync-monitor-usb.png diff --git a/FreeFileSync/Build/Help/images/realtimesync-schedule.png b/FreeFileSync/Build/Help/images/realtimesync-schedule.png Binary files differindex a964590d..cd67e71d 100644 --- a/FreeFileSync/Build/Help/images/realtimesync-schedule.png +++ b/FreeFileSync/Build/Help/images/realtimesync-schedule.png diff --git a/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png b/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png Binary files differindex bcfc1da8..e089672f 100644 --- a/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png +++ b/FreeFileSync/Build/Help/images/realtimesync-shortcut-properties.png diff --git a/FreeFileSync/Build/Help/images/remove-local-settings.png b/FreeFileSync/Build/Help/images/remove-local-settings.png Binary files differindex 6dfb9075..cccdcd2b 100644 --- a/FreeFileSync/Build/Help/images/remove-local-settings.png +++ b/FreeFileSync/Build/Help/images/remove-local-settings.png diff --git a/FreeFileSync/Build/Help/images/sync-settings-context.png b/FreeFileSync/Build/Help/images/sync-settings-context.png Binary files differindex cf92e087..e6b3d924 100644 --- a/FreeFileSync/Build/Help/images/sync-settings-context.png +++ b/FreeFileSync/Build/Help/images/sync-settings-context.png diff --git a/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png b/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png Binary files differindex 709ad67d..9e2597c7 100644 --- a/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png +++ b/FreeFileSync/Build/Help/images/synchronization-variant-double-click.png diff --git a/FreeFileSync/Build/Help/images/two-folder-drop.png b/FreeFileSync/Build/Help/images/two-folder-drop.png Binary files differindex 7b3794af..81e1f12e 100644 --- a/FreeFileSync/Build/Help/images/two-folder-drop.png +++ b/FreeFileSync/Build/Help/images/two-folder-drop.png diff --git a/FreeFileSync/Build/Help/images/windows-scheduler.png b/FreeFileSync/Build/Help/images/windows-scheduler.png Binary files differindex 09a6af1d..ff52b34a 100644 --- a/FreeFileSync/Build/Help/images/windows-scheduler.png +++ b/FreeFileSync/Build/Help/images/windows-scheduler.png diff --git a/FreeFileSync/Build/Help/images/xp-scheduler.png b/FreeFileSync/Build/Help/images/xp-scheduler.png Binary files differindex 27346809..6a643d78 100644 --- a/FreeFileSync/Build/Help/images/xp-scheduler.png +++ b/FreeFileSync/Build/Help/images/xp-scheduler.png 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 Binary files differindex c1f815e4..e45debd5 100644 --- a/FreeFileSync/Build/Resources.zip +++ b/FreeFileSync/Build/Resources.zip 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 @@ -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; @@ -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 @@ -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 } |